memorix 1.2.10 → 1.3.0
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/CHANGELOG.md +15 -0
- package/README.md +28 -2
- package/README.zh-CN.md +28 -2
- package/assets/star-history-dark.svg +30 -0
- package/assets/star-history-light.svg +30 -0
- package/assets/star-history.json +599 -0
- package/dist/cli/index.js +1783 -557
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +1292 -267
- package/dist/index.js.map +1 -1
- package/dist/maintenance-runner.js +97 -21
- package/dist/maintenance-runner.js.map +1 -1
- package/dist/memcode-runtime/CHANGELOG.md +15 -0
- package/dist/sdk.d.ts +1 -1
- package/dist/sdk.js +1294 -269
- package/dist/sdk.js.map +1 -1
- package/dist/types.d.ts +99 -1
- package/dist/types.js.map +1 -1
- package/dist/vector-backfill-runner.js +97 -21
- package/dist/vector-backfill-runner.js.map +1 -1
- package/docs/1.3-MEMORY-ARCHITECTURE.md +236 -0
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +3 -1
- package/docs/API_REFERENCE.md +20 -1
- package/docs/ARCHITECTURE.md +34 -1
- package/docs/DEVELOPMENT.md +3 -2
- package/docs/MODULES.md +27 -1
- package/docs/README.md +3 -3
- package/docs/dev-log/progress.txt +22 -0
- package/llms-full.txt +5 -1
- package/llms.txt +2 -0
- package/package.json +2 -1
- package/plugins/antigravity/memorix/rules/memorix.md +2 -0
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/memorix/skills/memorix-memory/SKILL.md +3 -0
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/skills/memorix-memory/SKILL.md +3 -0
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/copilot/memorix/skills/memorix-memory/SKILL.md +3 -0
- package/plugins/cursor/memorix/skills/memorix-memory/SKILL.md +3 -0
- package/plugins/gemini/memorix/GEMINI.md +2 -0
- package/plugins/gemini/memorix/gemini-extension.json +1 -1
- package/plugins/omp/memorix/package.json +1 -1
- package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/pi/memorix/package.json +1 -1
- package/plugins/pi/memorix/skills/memorix-memory/SKILL.md +3 -0
- package/server.json +2 -2
- package/src/cli/command-guide.ts +9 -1
- package/src/cli/commands/codegraph.ts +1 -0
- package/src/cli/commands/memory.ts +217 -1
- package/src/codegraph/auto-context.ts +11 -0
- package/src/codegraph/context-pack.ts +3 -0
- package/src/embedding/api-provider.ts +23 -9
- package/src/embedding/provider.ts +21 -10
- package/src/hooks/installers/index.ts +2 -0
- package/src/knowledge/context-assembly.ts +2 -1
- package/src/knowledge/workset.ts +77 -4
- package/src/memory/long-term-store.ts +242 -0
- package/src/memory/long-term-types.ts +136 -0
- package/src/memory/long-term.ts +626 -0
- package/src/memory/owner.ts +75 -0
- package/src/server.ts +112 -30
- package/src/store/sqlite-db.ts +74 -0
- package/src/types.ts +20 -0
package/dist/cli/index.js
CHANGED
|
@@ -3212,7 +3212,7 @@ ${import_picocolors.default.gray(m3)} ${s2}
|
|
|
3212
3212
|
|
|
3213
3213
|
// src/cli/version.ts
|
|
3214
3214
|
function getCliVersion() {
|
|
3215
|
-
return true ? "1.
|
|
3215
|
+
return true ? "1.3.0" : pkg.version;
|
|
3216
3216
|
}
|
|
3217
3217
|
var init_version = __esm({
|
|
3218
3218
|
"src/cli/version.ts"() {
|
|
@@ -3529,15 +3529,15 @@ function getDocumentProperties(doc, paths) {
|
|
|
3529
3529
|
const properties = {};
|
|
3530
3530
|
const pathsLength = paths.length;
|
|
3531
3531
|
for (let i2 = 0; i2 < pathsLength; i2++) {
|
|
3532
|
-
const
|
|
3533
|
-
const pathTokens =
|
|
3532
|
+
const path38 = paths[i2];
|
|
3533
|
+
const pathTokens = path38.split(".");
|
|
3534
3534
|
let current = doc;
|
|
3535
3535
|
const pathTokensLength = pathTokens.length;
|
|
3536
3536
|
for (let j3 = 0; j3 < pathTokensLength; j3++) {
|
|
3537
3537
|
current = current[pathTokens[j3]];
|
|
3538
3538
|
if (typeof current === "object") {
|
|
3539
3539
|
if (current !== null && "lat" in current && "lon" in current && typeof current.lat === "number" && typeof current.lon === "number") {
|
|
3540
|
-
current = properties[
|
|
3540
|
+
current = properties[path38] = current;
|
|
3541
3541
|
break;
|
|
3542
3542
|
} else if (!Array.isArray(current) && current !== null && j3 === pathTokensLength - 1) {
|
|
3543
3543
|
current = void 0;
|
|
@@ -3549,14 +3549,14 @@ function getDocumentProperties(doc, paths) {
|
|
|
3549
3549
|
}
|
|
3550
3550
|
}
|
|
3551
3551
|
if (typeof current !== "undefined") {
|
|
3552
|
-
properties[
|
|
3552
|
+
properties[path38] = current;
|
|
3553
3553
|
}
|
|
3554
3554
|
}
|
|
3555
3555
|
return properties;
|
|
3556
3556
|
}
|
|
3557
|
-
function getNested(obj,
|
|
3558
|
-
const props = getDocumentProperties(obj, [
|
|
3559
|
-
return props[
|
|
3557
|
+
function getNested(obj, path38) {
|
|
3558
|
+
const props = getDocumentProperties(obj, [path38]);
|
|
3559
|
+
return props[path38];
|
|
3560
3560
|
}
|
|
3561
3561
|
function convertDistanceToMeters(distance, unit) {
|
|
3562
3562
|
const ratio = mapDistanceToMeters[unit];
|
|
@@ -3572,10 +3572,10 @@ function removeVectorsFromHits(searchResult, vectorProperties) {
|
|
|
3572
3572
|
...result.document,
|
|
3573
3573
|
// Remove embeddings from the result
|
|
3574
3574
|
...vectorProperties.reduce((acc, prop) => {
|
|
3575
|
-
const
|
|
3576
|
-
const lastKey =
|
|
3575
|
+
const path38 = prop.split(".");
|
|
3576
|
+
const lastKey = path38.pop();
|
|
3577
3577
|
let obj = acc;
|
|
3578
|
-
for (const key of
|
|
3578
|
+
for (const key of path38) {
|
|
3579
3579
|
obj[key] = obj[key] ?? {};
|
|
3580
3580
|
obj = obj[key];
|
|
3581
3581
|
}
|
|
@@ -4307,15 +4307,15 @@ var init_avl = __esm({
|
|
|
4307
4307
|
if (node === null) {
|
|
4308
4308
|
return new AVLNode(key, [value]);
|
|
4309
4309
|
}
|
|
4310
|
-
const
|
|
4310
|
+
const path38 = [];
|
|
4311
4311
|
let current = node;
|
|
4312
4312
|
let parent = null;
|
|
4313
4313
|
while (current !== null) {
|
|
4314
|
-
|
|
4314
|
+
path38.push({ parent, node: current });
|
|
4315
4315
|
if (key < current.k) {
|
|
4316
4316
|
if (current.l === null) {
|
|
4317
4317
|
current.l = new AVLNode(key, [value]);
|
|
4318
|
-
|
|
4318
|
+
path38.push({ parent: current, node: current.l });
|
|
4319
4319
|
break;
|
|
4320
4320
|
} else {
|
|
4321
4321
|
parent = current;
|
|
@@ -4324,7 +4324,7 @@ var init_avl = __esm({
|
|
|
4324
4324
|
} else if (key > current.k) {
|
|
4325
4325
|
if (current.r === null) {
|
|
4326
4326
|
current.r = new AVLNode(key, [value]);
|
|
4327
|
-
|
|
4327
|
+
path38.push({ parent: current, node: current.r });
|
|
4328
4328
|
break;
|
|
4329
4329
|
} else {
|
|
4330
4330
|
parent = current;
|
|
@@ -4339,8 +4339,8 @@ var init_avl = __esm({
|
|
|
4339
4339
|
if (this.insertCount++ % rebalanceThreshold === 0) {
|
|
4340
4340
|
needRebalance = true;
|
|
4341
4341
|
}
|
|
4342
|
-
for (let i2 =
|
|
4343
|
-
const { parent: parent2, node: currentNode } =
|
|
4342
|
+
for (let i2 = path38.length - 1; i2 >= 0; i2--) {
|
|
4343
|
+
const { parent: parent2, node: currentNode } = path38[i2];
|
|
4344
4344
|
currentNode.updateHeight();
|
|
4345
4345
|
if (needRebalance) {
|
|
4346
4346
|
const rebalancedNode = this.rebalanceNode(currentNode);
|
|
@@ -4446,10 +4446,10 @@ var init_avl = __esm({
|
|
|
4446
4446
|
removeNode(node, key) {
|
|
4447
4447
|
if (node === null)
|
|
4448
4448
|
return null;
|
|
4449
|
-
const
|
|
4449
|
+
const path38 = [];
|
|
4450
4450
|
let current = node;
|
|
4451
4451
|
while (current !== null && current.k !== key) {
|
|
4452
|
-
|
|
4452
|
+
path38.push(current);
|
|
4453
4453
|
if (key < current.k) {
|
|
4454
4454
|
current = current.l;
|
|
4455
4455
|
} else {
|
|
@@ -4461,10 +4461,10 @@ var init_avl = __esm({
|
|
|
4461
4461
|
}
|
|
4462
4462
|
if (current.l === null || current.r === null) {
|
|
4463
4463
|
const child = current.l ? current.l : current.r;
|
|
4464
|
-
if (
|
|
4464
|
+
if (path38.length === 0) {
|
|
4465
4465
|
node = child;
|
|
4466
4466
|
} else {
|
|
4467
|
-
const parent =
|
|
4467
|
+
const parent = path38[path38.length - 1];
|
|
4468
4468
|
if (parent.l === current) {
|
|
4469
4469
|
parent.l = child;
|
|
4470
4470
|
} else {
|
|
@@ -4487,13 +4487,13 @@ var init_avl = __esm({
|
|
|
4487
4487
|
}
|
|
4488
4488
|
current = successorParent;
|
|
4489
4489
|
}
|
|
4490
|
-
|
|
4491
|
-
for (let i2 =
|
|
4492
|
-
const currentNode =
|
|
4490
|
+
path38.push(current);
|
|
4491
|
+
for (let i2 = path38.length - 1; i2 >= 0; i2--) {
|
|
4492
|
+
const currentNode = path38[i2];
|
|
4493
4493
|
currentNode.updateHeight();
|
|
4494
4494
|
const rebalancedNode = this.rebalanceNode(currentNode);
|
|
4495
4495
|
if (i2 > 0) {
|
|
4496
|
-
const parent =
|
|
4496
|
+
const parent = path38[i2 - 1];
|
|
4497
4497
|
if (parent.l === currentNode) {
|
|
4498
4498
|
parent.l = rebalancedNode;
|
|
4499
4499
|
} else if (parent.r === currentNode) {
|
|
@@ -5660,15 +5660,15 @@ function create2(orama, sharedInternalDocumentStore, schema, index, prefix = "")
|
|
|
5660
5660
|
};
|
|
5661
5661
|
}
|
|
5662
5662
|
for (const [prop, type] of Object.entries(schema)) {
|
|
5663
|
-
const
|
|
5663
|
+
const path38 = `${prefix}${prefix ? "." : ""}${prop}`;
|
|
5664
5664
|
if (typeof type === "object" && !Array.isArray(type)) {
|
|
5665
|
-
create2(orama, sharedInternalDocumentStore, type, index,
|
|
5665
|
+
create2(orama, sharedInternalDocumentStore, type, index, path38);
|
|
5666
5666
|
continue;
|
|
5667
5667
|
}
|
|
5668
5668
|
if (isVectorType(type)) {
|
|
5669
|
-
index.searchableProperties.push(
|
|
5670
|
-
index.searchablePropertiesWithTypes[
|
|
5671
|
-
index.vectorIndexes[
|
|
5669
|
+
index.searchableProperties.push(path38);
|
|
5670
|
+
index.searchablePropertiesWithTypes[path38] = type;
|
|
5671
|
+
index.vectorIndexes[path38] = {
|
|
5672
5672
|
type: "Vector",
|
|
5673
5673
|
node: new VectorIndex(getVectorSize(type)),
|
|
5674
5674
|
isArray: false
|
|
@@ -5678,32 +5678,32 @@ function create2(orama, sharedInternalDocumentStore, schema, index, prefix = "")
|
|
|
5678
5678
|
switch (type) {
|
|
5679
5679
|
case "boolean":
|
|
5680
5680
|
case "boolean[]":
|
|
5681
|
-
index.indexes[
|
|
5681
|
+
index.indexes[path38] = { type: "Bool", node: new BoolNode(), isArray };
|
|
5682
5682
|
break;
|
|
5683
5683
|
case "number":
|
|
5684
5684
|
case "number[]":
|
|
5685
|
-
index.indexes[
|
|
5685
|
+
index.indexes[path38] = { type: "AVL", node: new AVLTree(0, []), isArray };
|
|
5686
5686
|
break;
|
|
5687
5687
|
case "string":
|
|
5688
5688
|
case "string[]":
|
|
5689
|
-
index.indexes[
|
|
5690
|
-
index.avgFieldLength[
|
|
5691
|
-
index.frequencies[
|
|
5692
|
-
index.tokenOccurrences[
|
|
5693
|
-
index.fieldLengths[
|
|
5689
|
+
index.indexes[path38] = { type: "Radix", node: new RadixTree(), isArray };
|
|
5690
|
+
index.avgFieldLength[path38] = 0;
|
|
5691
|
+
index.frequencies[path38] = {};
|
|
5692
|
+
index.tokenOccurrences[path38] = {};
|
|
5693
|
+
index.fieldLengths[path38] = {};
|
|
5694
5694
|
break;
|
|
5695
5695
|
case "enum":
|
|
5696
5696
|
case "enum[]":
|
|
5697
|
-
index.indexes[
|
|
5697
|
+
index.indexes[path38] = { type: "Flat", node: new FlatTree(), isArray };
|
|
5698
5698
|
break;
|
|
5699
5699
|
case "geopoint":
|
|
5700
|
-
index.indexes[
|
|
5700
|
+
index.indexes[path38] = { type: "BKD", node: new BKDTree(), isArray };
|
|
5701
5701
|
break;
|
|
5702
5702
|
default:
|
|
5703
|
-
throw createError("INVALID_SCHEMA_TYPE", Array.isArray(type) ? "array" : type,
|
|
5703
|
+
throw createError("INVALID_SCHEMA_TYPE", Array.isArray(type) ? "array" : type, path38);
|
|
5704
5704
|
}
|
|
5705
|
-
index.searchableProperties.push(
|
|
5706
|
-
index.searchablePropertiesWithTypes[
|
|
5705
|
+
index.searchableProperties.push(path38);
|
|
5706
|
+
index.searchablePropertiesWithTypes[path38] = type;
|
|
5707
5707
|
}
|
|
5708
5708
|
}
|
|
5709
5709
|
return index;
|
|
@@ -6274,12 +6274,12 @@ function innerCreate(orama, sharedInternalDocumentStore, schema, sortableDeniedP
|
|
|
6274
6274
|
sorts: {}
|
|
6275
6275
|
};
|
|
6276
6276
|
for (const [prop, type] of Object.entries(schema)) {
|
|
6277
|
-
const
|
|
6278
|
-
if (sortableDeniedProperties.includes(
|
|
6277
|
+
const path38 = `${prefix}${prefix ? "." : ""}${prop}`;
|
|
6278
|
+
if (sortableDeniedProperties.includes(path38)) {
|
|
6279
6279
|
continue;
|
|
6280
6280
|
}
|
|
6281
6281
|
if (typeof type === "object" && !Array.isArray(type)) {
|
|
6282
|
-
const ret = innerCreate(orama, sharedInternalDocumentStore, type, sortableDeniedProperties,
|
|
6282
|
+
const ret = innerCreate(orama, sharedInternalDocumentStore, type, sortableDeniedProperties, path38);
|
|
6283
6283
|
safeArrayPush(sorter.sortableProperties, ret.sortableProperties);
|
|
6284
6284
|
sorter.sorts = {
|
|
6285
6285
|
...sorter.sorts,
|
|
@@ -6296,9 +6296,9 @@ function innerCreate(orama, sharedInternalDocumentStore, schema, sortableDeniedP
|
|
|
6296
6296
|
case "boolean":
|
|
6297
6297
|
case "number":
|
|
6298
6298
|
case "string":
|
|
6299
|
-
sorter.sortableProperties.push(
|
|
6300
|
-
sorter.sortablePropertiesWithTypes[
|
|
6301
|
-
sorter.sorts[
|
|
6299
|
+
sorter.sortableProperties.push(path38);
|
|
6300
|
+
sorter.sortablePropertiesWithTypes[path38] = type;
|
|
6301
|
+
sorter.sorts[path38] = {
|
|
6302
6302
|
docs: /* @__PURE__ */ new Map(),
|
|
6303
6303
|
orderedDocsToRemove: /* @__PURE__ */ new Map(),
|
|
6304
6304
|
orderedDocs: [],
|
|
@@ -6314,7 +6314,7 @@ function innerCreate(orama, sharedInternalDocumentStore, schema, sortableDeniedP
|
|
|
6314
6314
|
case "string[]":
|
|
6315
6315
|
continue;
|
|
6316
6316
|
default:
|
|
6317
|
-
throw createError("INVALID_SORT_SCHEMA_TYPE", Array.isArray(type) ? "array" : type,
|
|
6317
|
+
throw createError("INVALID_SORT_SCHEMA_TYPE", Array.isArray(type) ? "array" : type, path38);
|
|
6318
6318
|
}
|
|
6319
6319
|
}
|
|
6320
6320
|
}
|
|
@@ -8159,8 +8159,8 @@ function innerFullTextSearch(orama, params, language) {
|
|
|
8159
8159
|
function escapeRegex(str2) {
|
|
8160
8160
|
return str2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
8161
8161
|
}
|
|
8162
|
-
function getPropValue(obj,
|
|
8163
|
-
const keys =
|
|
8162
|
+
function getPropValue(obj, path38) {
|
|
8163
|
+
const keys = path38.split(".");
|
|
8164
8164
|
let value = obj;
|
|
8165
8165
|
for (const key of keys) {
|
|
8166
8166
|
if (value && typeof value === "object" && key in value) {
|
|
@@ -9219,15 +9219,15 @@ function loadSqlite() {
|
|
|
9219
9219
|
throw new Error("[memorix] SQLite is unavailable (better-sqlite3, node:sqlite, and bun:sqlite failed)");
|
|
9220
9220
|
}
|
|
9221
9221
|
}
|
|
9222
|
-
function createDatabase(
|
|
9222
|
+
function createDatabase(path38, options2) {
|
|
9223
9223
|
const Sqlite = loadSqlite();
|
|
9224
9224
|
try {
|
|
9225
|
-
return addCompatibility(instantiateDatabase(Sqlite,
|
|
9225
|
+
return addCompatibility(instantiateDatabase(Sqlite, path38, options2));
|
|
9226
9226
|
} catch (error2) {
|
|
9227
9227
|
if (driver !== "better-sqlite3" || !isNativeBindingFailure(error2)) throw error2;
|
|
9228
9228
|
Database = loadNodeSqlite();
|
|
9229
9229
|
driver = "node:sqlite";
|
|
9230
|
-
return addCompatibility(instantiateDatabase(Database,
|
|
9230
|
+
return addCompatibility(instantiateDatabase(Database, path38, options2));
|
|
9231
9231
|
}
|
|
9232
9232
|
}
|
|
9233
9233
|
var Database, driver, requireFromHere;
|
|
@@ -9354,7 +9354,7 @@ function closeAllDatabases() {
|
|
|
9354
9354
|
_dbCache.delete(key);
|
|
9355
9355
|
}
|
|
9356
9356
|
}
|
|
9357
|
-
var BetterSqlite3, CREATE_OBSERVATIONS_TABLE, CREATE_MINI_SKILLS_TABLE, CREATE_SESSIONS_TABLE, CREATE_META_TABLE, CREATE_TEAM_AGENTS_TABLE, CREATE_TEAM_MESSAGES_TABLE, CREATE_TEAM_TASKS_TABLE, CREATE_TEAM_TASK_DEPS_TABLE, CREATE_TEAM_LOCKS_TABLE, CREATE_TEAM_ROLES_TABLE, CREATE_CHAT_TRANSCRIPT_TABLE, CREATE_GRAPH_ENTITIES_TABLE, CREATE_GRAPH_RELATIONS_TABLE, CREATE_CODE_FILES_TABLE, CREATE_CODE_SYMBOLS_TABLE, CREATE_CODE_EDGES_TABLE, CREATE_OBSERVATION_CODE_REFS_TABLE, CREATE_SCHEMA_MIGRATIONS_TABLE, CREATE_CODE_STATE_SNAPSHOTS_TABLE, CREATE_KNOWLEDGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_CLAIM_EVIDENCE_TABLE, CREATE_KNOWLEDGE_CLAIM_EVENTS_TABLE, CREATE_KNOWLEDGE_WORKSPACES_TABLE, CREATE_KNOWLEDGE_PAGES_TABLE, CREATE_KNOWLEDGE_PAGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_PAGE_LINKS_TABLE, CREATE_KNOWLEDGE_PROPOSALS_TABLE, CREATE_KNOWLEDGE_WORKFLOWS_TABLE, CREATE_KNOWLEDGE_WORKFLOW_RUNS_TABLE, CREATE_MAINTENANCE_JOBS_TABLE, CREATE_MAINTENANCE_TARGETS_TABLE, CREATE_COMPACTION_CHECKPOINTS_TABLE, CREATE_INDEXES, SCHEMA_MIGRATIONS, _dbCache;
|
|
9357
|
+
var BetterSqlite3, CREATE_OBSERVATIONS_TABLE, CREATE_MINI_SKILLS_TABLE, CREATE_SESSIONS_TABLE, CREATE_META_TABLE, CREATE_TEAM_AGENTS_TABLE, CREATE_TEAM_MESSAGES_TABLE, CREATE_TEAM_TASKS_TABLE, CREATE_TEAM_TASK_DEPS_TABLE, CREATE_TEAM_LOCKS_TABLE, CREATE_TEAM_ROLES_TABLE, CREATE_CHAT_TRANSCRIPT_TABLE, CREATE_GRAPH_ENTITIES_TABLE, CREATE_GRAPH_RELATIONS_TABLE, CREATE_CODE_FILES_TABLE, CREATE_CODE_SYMBOLS_TABLE, CREATE_CODE_EDGES_TABLE, CREATE_OBSERVATION_CODE_REFS_TABLE, CREATE_SCHEMA_MIGRATIONS_TABLE, CREATE_CODE_STATE_SNAPSHOTS_TABLE, CREATE_KNOWLEDGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_CLAIM_EVIDENCE_TABLE, CREATE_KNOWLEDGE_CLAIM_EVENTS_TABLE, CREATE_KNOWLEDGE_WORKSPACES_TABLE, CREATE_KNOWLEDGE_PAGES_TABLE, CREATE_KNOWLEDGE_PAGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_PAGE_LINKS_TABLE, CREATE_KNOWLEDGE_PROPOSALS_TABLE, CREATE_KNOWLEDGE_WORKFLOWS_TABLE, CREATE_KNOWLEDGE_WORKFLOW_RUNS_TABLE, CREATE_LONG_TERM_MEMORIES_TABLE, CREATE_LONG_TERM_MEMORY_EVIDENCE_TABLE, CREATE_LONG_TERM_MEMORY_EVENTS_TABLE, CREATE_MAINTENANCE_JOBS_TABLE, CREATE_MAINTENANCE_TARGETS_TABLE, CREATE_COMPACTION_CHECKPOINTS_TABLE, CREATE_INDEXES, SCHEMA_MIGRATIONS, _dbCache;
|
|
9358
9358
|
var init_sqlite_db = __esm({
|
|
9359
9359
|
"src/store/sqlite-db.ts"() {
|
|
9360
9360
|
"use strict";
|
|
@@ -9780,6 +9780,57 @@ CREATE TABLE IF NOT EXISTS knowledge_claim_events (
|
|
|
9780
9780
|
" FOREIGN KEY (workflowId) REFERENCES knowledge_workflows(id) ON DELETE CASCADE",
|
|
9781
9781
|
");"
|
|
9782
9782
|
].join("\n");
|
|
9783
|
+
CREATE_LONG_TERM_MEMORIES_TABLE = `
|
|
9784
|
+
CREATE TABLE IF NOT EXISTS long_term_memories (
|
|
9785
|
+
id TEXT PRIMARY KEY,
|
|
9786
|
+
originProjectId TEXT NOT NULL,
|
|
9787
|
+
ownerId TEXT NOT NULL,
|
|
9788
|
+
scope TEXT NOT NULL,
|
|
9789
|
+
kind TEXT NOT NULL,
|
|
9790
|
+
state TEXT NOT NULL,
|
|
9791
|
+
portability TEXT NOT NULL DEFAULT 'project-bound',
|
|
9792
|
+
title TEXT NOT NULL,
|
|
9793
|
+
content TEXT NOT NULL,
|
|
9794
|
+
factsJson TEXT NOT NULL DEFAULT '[]',
|
|
9795
|
+
tagsJson TEXT NOT NULL DEFAULT '[]',
|
|
9796
|
+
applicability TEXT,
|
|
9797
|
+
origin TEXT NOT NULL,
|
|
9798
|
+
createdAt TEXT NOT NULL,
|
|
9799
|
+
updatedAt TEXT NOT NULL,
|
|
9800
|
+
qualifiedAt TEXT,
|
|
9801
|
+
approvedAt TEXT,
|
|
9802
|
+
archivedAt TEXT,
|
|
9803
|
+
supersededBy TEXT,
|
|
9804
|
+
lastValidatedAt TEXT,
|
|
9805
|
+
accessCount INTEGER NOT NULL DEFAULT 0,
|
|
9806
|
+
lastAccessedAt TEXT
|
|
9807
|
+
);
|
|
9808
|
+
`;
|
|
9809
|
+
CREATE_LONG_TERM_MEMORY_EVIDENCE_TABLE = `
|
|
9810
|
+
CREATE TABLE IF NOT EXISTS long_term_memory_evidence (
|
|
9811
|
+
id TEXT PRIMARY KEY,
|
|
9812
|
+
memoryId TEXT NOT NULL,
|
|
9813
|
+
kind TEXT NOT NULL,
|
|
9814
|
+
referenceId TEXT NOT NULL,
|
|
9815
|
+
relation TEXT NOT NULL,
|
|
9816
|
+
locator TEXT,
|
|
9817
|
+
capturedHash TEXT,
|
|
9818
|
+
createdAt TEXT NOT NULL,
|
|
9819
|
+
FOREIGN KEY (memoryId) REFERENCES long_term_memories(id) ON DELETE CASCADE
|
|
9820
|
+
);
|
|
9821
|
+
`;
|
|
9822
|
+
CREATE_LONG_TERM_MEMORY_EVENTS_TABLE = `
|
|
9823
|
+
CREATE TABLE IF NOT EXISTS long_term_memory_events (
|
|
9824
|
+
id TEXT PRIMARY KEY,
|
|
9825
|
+
memoryId TEXT NOT NULL,
|
|
9826
|
+
kind TEXT NOT NULL,
|
|
9827
|
+
fromState TEXT,
|
|
9828
|
+
toState TEXT,
|
|
9829
|
+
detail TEXT,
|
|
9830
|
+
createdAt TEXT NOT NULL,
|
|
9831
|
+
FOREIGN KEY (memoryId) REFERENCES long_term_memories(id) ON DELETE CASCADE
|
|
9832
|
+
);
|
|
9833
|
+
`;
|
|
9783
9834
|
CREATE_MAINTENANCE_JOBS_TABLE = `
|
|
9784
9835
|
CREATE TABLE IF NOT EXISTS maintenance_jobs (
|
|
9785
9836
|
id TEXT PRIMARY KEY,
|
|
@@ -9875,6 +9926,11 @@ CREATE INDEX IF NOT EXISTS idx_knowledge_page_claims_claim ON knowledge_page_cla
|
|
|
9875
9926
|
CREATE INDEX IF NOT EXISTS idx_knowledge_proposals_workspace_status ON knowledge_proposals(workspaceId, status, createdAt DESC);
|
|
9876
9927
|
CREATE INDEX IF NOT EXISTS idx_knowledge_workflows_workspace_status ON knowledge_workflows(workspaceId, status, updatedAt DESC);
|
|
9877
9928
|
CREATE INDEX IF NOT EXISTS idx_knowledge_workflow_runs_project_workflow ON knowledge_workflow_runs(projectId, workflowId, startedAt DESC);
|
|
9929
|
+
CREATE INDEX IF NOT EXISTS idx_long_term_memories_owner_state ON long_term_memories(ownerId, state, updatedAt DESC);
|
|
9930
|
+
CREATE INDEX IF NOT EXISTS idx_long_term_memories_project_state ON long_term_memories(originProjectId, state, updatedAt DESC);
|
|
9931
|
+
CREATE INDEX IF NOT EXISTS idx_long_term_memories_scope_portability ON long_term_memories(scope, portability, state, updatedAt DESC);
|
|
9932
|
+
CREATE INDEX IF NOT EXISTS idx_long_term_memory_evidence_memory ON long_term_memory_evidence(memoryId, createdAt);
|
|
9933
|
+
CREATE INDEX IF NOT EXISTS idx_long_term_memory_events_memory ON long_term_memory_events(memoryId, createdAt);
|
|
9878
9934
|
CREATE INDEX IF NOT EXISTS idx_maintenance_jobs_ready ON maintenance_jobs(status, run_after);
|
|
9879
9935
|
CREATE INDEX IF NOT EXISTS idx_maintenance_jobs_project ON maintenance_jobs(project_id, status, run_after);
|
|
9880
9936
|
CREATE INDEX IF NOT EXISTS idx_maintenance_targets_updated ON maintenance_targets(updated_at);
|
|
@@ -9963,6 +10019,19 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
|
9963
10019
|
db2.exec("CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_session_pending ON compaction_checkpoints(project_id, session_id, agent, phase, status, pre_captured_at DESC)");
|
|
9964
10020
|
db2.exec("CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_source ON compaction_checkpoints(project_id, source_key)");
|
|
9965
10021
|
}
|
|
10022
|
+
},
|
|
10023
|
+
{
|
|
10024
|
+
id: "1.3-long-term-memory",
|
|
10025
|
+
apply: (db2) => {
|
|
10026
|
+
db2.exec(CREATE_LONG_TERM_MEMORIES_TABLE);
|
|
10027
|
+
db2.exec(CREATE_LONG_TERM_MEMORY_EVIDENCE_TABLE);
|
|
10028
|
+
db2.exec(CREATE_LONG_TERM_MEMORY_EVENTS_TABLE);
|
|
10029
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_long_term_memories_owner_state ON long_term_memories(ownerId, state, updatedAt DESC)");
|
|
10030
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_long_term_memories_project_state ON long_term_memories(originProjectId, state, updatedAt DESC)");
|
|
10031
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_long_term_memories_scope_portability ON long_term_memories(scope, portability, state, updatedAt DESC)");
|
|
10032
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_long_term_memory_evidence_memory ON long_term_memory_evidence(memoryId, createdAt)");
|
|
10033
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_long_term_memory_events_memory ON long_term_memory_events(memoryId, createdAt)");
|
|
10034
|
+
}
|
|
9966
10035
|
}
|
|
9967
10036
|
];
|
|
9968
10037
|
_dbCache = /* @__PURE__ */ new Map();
|
|
@@ -13292,9 +13361,9 @@ function parseTomlConfig(content, filePath) {
|
|
|
13292
13361
|
}
|
|
13293
13362
|
return root;
|
|
13294
13363
|
}
|
|
13295
|
-
function ensureTable(root,
|
|
13364
|
+
function ensureTable(root, path38) {
|
|
13296
13365
|
let cursor = root;
|
|
13297
|
-
for (const part of
|
|
13366
|
+
for (const part of path38) {
|
|
13298
13367
|
const value = cursor[part];
|
|
13299
13368
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
13300
13369
|
cursor[part] = {};
|
|
@@ -13428,8 +13497,8 @@ var require_main = __commonJS({
|
|
|
13428
13497
|
"node_modules/dotenv/lib/main.js"(exports2, module2) {
|
|
13429
13498
|
"use strict";
|
|
13430
13499
|
init_esm_shims();
|
|
13431
|
-
var
|
|
13432
|
-
var
|
|
13500
|
+
var fs28 = __require("fs");
|
|
13501
|
+
var path38 = __require("path");
|
|
13433
13502
|
var os5 = __require("os");
|
|
13434
13503
|
var crypto3 = __require("crypto");
|
|
13435
13504
|
var packageJson = require_package();
|
|
@@ -13567,7 +13636,7 @@ var require_main = __commonJS({
|
|
|
13567
13636
|
if (options2 && options2.path && options2.path.length > 0) {
|
|
13568
13637
|
if (Array.isArray(options2.path)) {
|
|
13569
13638
|
for (const filepath of options2.path) {
|
|
13570
|
-
if (
|
|
13639
|
+
if (fs28.existsSync(filepath)) {
|
|
13571
13640
|
possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
|
|
13572
13641
|
}
|
|
13573
13642
|
}
|
|
@@ -13575,15 +13644,15 @@ var require_main = __commonJS({
|
|
|
13575
13644
|
possibleVaultPath = options2.path.endsWith(".vault") ? options2.path : `${options2.path}.vault`;
|
|
13576
13645
|
}
|
|
13577
13646
|
} else {
|
|
13578
|
-
possibleVaultPath =
|
|
13647
|
+
possibleVaultPath = path38.resolve(process.cwd(), ".env.vault");
|
|
13579
13648
|
}
|
|
13580
|
-
if (
|
|
13649
|
+
if (fs28.existsSync(possibleVaultPath)) {
|
|
13581
13650
|
return possibleVaultPath;
|
|
13582
13651
|
}
|
|
13583
13652
|
return null;
|
|
13584
13653
|
}
|
|
13585
13654
|
function _resolveHome(envPath) {
|
|
13586
|
-
return envPath[0] === "~" ?
|
|
13655
|
+
return envPath[0] === "~" ? path38.join(os5.homedir(), envPath.slice(1)) : envPath;
|
|
13587
13656
|
}
|
|
13588
13657
|
function _configVault(options2) {
|
|
13589
13658
|
const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options2 && options2.debug);
|
|
@@ -13600,7 +13669,7 @@ var require_main = __commonJS({
|
|
|
13600
13669
|
return { parsed };
|
|
13601
13670
|
}
|
|
13602
13671
|
function configDotenv(options2) {
|
|
13603
|
-
const dotenvPath =
|
|
13672
|
+
const dotenvPath = path38.resolve(process.cwd(), ".env");
|
|
13604
13673
|
let encoding = "utf8";
|
|
13605
13674
|
let processEnv = process.env;
|
|
13606
13675
|
if (options2 && options2.processEnv != null) {
|
|
@@ -13628,13 +13697,13 @@ var require_main = __commonJS({
|
|
|
13628
13697
|
}
|
|
13629
13698
|
let lastError;
|
|
13630
13699
|
const parsedAll = {};
|
|
13631
|
-
for (const
|
|
13700
|
+
for (const path39 of optionPaths) {
|
|
13632
13701
|
try {
|
|
13633
|
-
const parsed = DotenvModule.parse(
|
|
13702
|
+
const parsed = DotenvModule.parse(fs28.readFileSync(path39, { encoding }));
|
|
13634
13703
|
DotenvModule.populate(parsedAll, parsed, options2);
|
|
13635
13704
|
} catch (e3) {
|
|
13636
13705
|
if (debug) {
|
|
13637
|
-
_debug(`Failed to load ${
|
|
13706
|
+
_debug(`Failed to load ${path39} ${e3.message}`);
|
|
13638
13707
|
}
|
|
13639
13708
|
lastError = e3;
|
|
13640
13709
|
}
|
|
@@ -13647,7 +13716,7 @@ var require_main = __commonJS({
|
|
|
13647
13716
|
const shortPaths = [];
|
|
13648
13717
|
for (const filePath of optionPaths) {
|
|
13649
13718
|
try {
|
|
13650
|
-
const relative3 =
|
|
13719
|
+
const relative3 = path38.relative(process.cwd(), filePath);
|
|
13651
13720
|
shortPaths.push(relative3);
|
|
13652
13721
|
} catch (e3) {
|
|
13653
13722
|
if (debug) {
|
|
@@ -14566,9 +14635,10 @@ function parseBatchLimit(error2) {
|
|
|
14566
14635
|
}
|
|
14567
14636
|
return null;
|
|
14568
14637
|
}
|
|
14569
|
-
async function fetchWithRetry(url, apiKey, body, attempt = 0) {
|
|
14638
|
+
async function fetchWithRetry(url, apiKey, body, options2 = {}, attempt = 0) {
|
|
14570
14639
|
const controller = new AbortController();
|
|
14571
|
-
const
|
|
14640
|
+
const timeoutMs = typeof options2.timeoutMs === "number" && Number.isFinite(options2.timeoutMs) ? Math.max(100, Math.min(Math.floor(options2.timeoutMs), 6e4)) : 1e4;
|
|
14641
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
14572
14642
|
let response;
|
|
14573
14643
|
try {
|
|
14574
14644
|
response = await fetch(url, {
|
|
@@ -14583,7 +14653,7 @@ async function fetchWithRetry(url, apiKey, body, attempt = 0) {
|
|
|
14583
14653
|
} catch (err) {
|
|
14584
14654
|
clearTimeout(timeout);
|
|
14585
14655
|
if (err instanceof Error && err.name === "AbortError") {
|
|
14586
|
-
throw new Error(`Embedding API timeout after
|
|
14656
|
+
throw new Error(`Embedding API timeout after ${timeoutMs}ms: ${url}`);
|
|
14587
14657
|
}
|
|
14588
14658
|
throw err;
|
|
14589
14659
|
}
|
|
@@ -14591,13 +14661,13 @@ async function fetchWithRetry(url, apiKey, body, attempt = 0) {
|
|
|
14591
14661
|
if (response.ok) {
|
|
14592
14662
|
return response.json();
|
|
14593
14663
|
}
|
|
14594
|
-
if ((response.status === 429 || response.status >= 500) && attempt < MAX_RETRIES2) {
|
|
14664
|
+
if (options2.retry !== false && (response.status === 429 || response.status >= 500) && attempt < MAX_RETRIES2) {
|
|
14595
14665
|
const delay = BASE_DELAY_MS * Math.pow(2, attempt);
|
|
14596
14666
|
const retryAfter = response.headers.get("retry-after");
|
|
14597
14667
|
const waitMs = retryAfter ? parseInt(retryAfter, 10) * 1e3 : delay;
|
|
14598
14668
|
console.error(`[memorix] Embedding API ${response.status}, retry ${attempt + 1}/${MAX_RETRIES2} in ${waitMs}ms`);
|
|
14599
14669
|
await new Promise((resolve6) => setTimeout(resolve6, waitMs));
|
|
14600
|
-
return fetchWithRetry(url, apiKey, body, attempt + 1);
|
|
14670
|
+
return fetchWithRetry(url, apiKey, body, options2, attempt + 1);
|
|
14601
14671
|
}
|
|
14602
14672
|
const errorText2 = await response.text().catch(() => "unknown error");
|
|
14603
14673
|
throw new Error(`Embedding API error (${response.status}): ${errorText2}`);
|
|
@@ -14653,7 +14723,10 @@ var init_api_provider = __esm({
|
|
|
14653
14723
|
}
|
|
14654
14724
|
} else {
|
|
14655
14725
|
if (!allowNetworkProbe) return null;
|
|
14656
|
-
probeDimensions = await _APIEmbeddingProvider.probeAPI(config2
|
|
14726
|
+
probeDimensions = await _APIEmbeddingProvider.probeAPI(config2, {
|
|
14727
|
+
timeoutMs: options2.requestTimeoutMs,
|
|
14728
|
+
retry: options2.retry
|
|
14729
|
+
});
|
|
14657
14730
|
console.error(`[memorix] API embedding: ${config2.model} @ ${config2.baseUrl} (${probeDimensions}d)`);
|
|
14658
14731
|
saveCachedDims(config2, probeDimensions).catch(() => {
|
|
14659
14732
|
});
|
|
@@ -14695,7 +14768,7 @@ var init_api_provider = __esm({
|
|
|
14695
14768
|
baseUrl = baseUrl.replace(/\/+$/, "");
|
|
14696
14769
|
return { apiKey, baseUrl, model, requestedDimensions };
|
|
14697
14770
|
}
|
|
14698
|
-
static async probeAPI(config2) {
|
|
14771
|
+
static async probeAPI(config2, options2) {
|
|
14699
14772
|
const body = {
|
|
14700
14773
|
model: config2.model,
|
|
14701
14774
|
input: "dimension probe"
|
|
@@ -14706,14 +14779,15 @@ var init_api_provider = __esm({
|
|
|
14706
14779
|
const response = await fetchWithRetry(
|
|
14707
14780
|
`${config2.baseUrl}/embeddings`,
|
|
14708
14781
|
config2.apiKey,
|
|
14709
|
-
body
|
|
14782
|
+
body,
|
|
14783
|
+
options2
|
|
14710
14784
|
);
|
|
14711
14785
|
if (response.data.length === 0 || !response.data[0].embedding) {
|
|
14712
14786
|
throw new Error("API probe returned no embeddings; check model name and API key");
|
|
14713
14787
|
}
|
|
14714
14788
|
return response.data[0].embedding.length;
|
|
14715
14789
|
}
|
|
14716
|
-
async embed(text) {
|
|
14790
|
+
async embed(text, options2) {
|
|
14717
14791
|
const normalized = normalizeText(text);
|
|
14718
14792
|
const hash4 = textHash2(normalized, this.cacheKeyNamespace);
|
|
14719
14793
|
if (diskCacheLoaded) {
|
|
@@ -14731,7 +14805,8 @@ var init_api_provider = __esm({
|
|
|
14731
14805
|
const response = await fetchWithRetry(
|
|
14732
14806
|
`${this.config.baseUrl}/embeddings`,
|
|
14733
14807
|
this.config.apiKey,
|
|
14734
|
-
body
|
|
14808
|
+
body,
|
|
14809
|
+
options2
|
|
14735
14810
|
);
|
|
14736
14811
|
const embedding2 = response.data[0].embedding;
|
|
14737
14812
|
if (embedding2.length !== this.dimensions) {
|
|
@@ -14765,7 +14840,7 @@ var init_api_provider = __esm({
|
|
|
14765
14840
|
scheduleDiskSave();
|
|
14766
14841
|
return embedding;
|
|
14767
14842
|
}
|
|
14768
|
-
async embedBatch(texts) {
|
|
14843
|
+
async embedBatch(texts, options2) {
|
|
14769
14844
|
await ensureDiskCacheLoaded();
|
|
14770
14845
|
const normalizedTexts = texts.map(normalizeText);
|
|
14771
14846
|
const results = new Array(texts.length);
|
|
@@ -14799,7 +14874,8 @@ var init_api_provider = __esm({
|
|
|
14799
14874
|
const response = await fetchWithRetry(
|
|
14800
14875
|
`${this.config.baseUrl}/embeddings`,
|
|
14801
14876
|
this.config.apiKey,
|
|
14802
|
-
body
|
|
14877
|
+
body,
|
|
14878
|
+
options2
|
|
14803
14879
|
);
|
|
14804
14880
|
this.trackUsage(response);
|
|
14805
14881
|
for (const item of response.data) {
|
|
@@ -14976,9 +15052,9 @@ function wrapProvider(candidate2) {
|
|
|
14976
15052
|
return {
|
|
14977
15053
|
name: candidate2.name,
|
|
14978
15054
|
dimensions: candidate2.dimensions,
|
|
14979
|
-
async embed(text) {
|
|
15055
|
+
async embed(text, options2) {
|
|
14980
15056
|
try {
|
|
14981
|
-
return await candidate2.embed(text);
|
|
15057
|
+
return await candidate2.embed(text, options2);
|
|
14982
15058
|
} catch (error2) {
|
|
14983
15059
|
if (kind === "api" && getEmbeddingMode2() === "auto" && isTemporaryEmbeddingFailure(error2)) {
|
|
14984
15060
|
warnOnce("[memorix] API embedding temporarily unavailable \u2014 switching to local fallback provider");
|
|
@@ -14986,7 +15062,7 @@ function wrapProvider(candidate2) {
|
|
|
14986
15062
|
if (fallback) {
|
|
14987
15063
|
provider = wrapProvider(fallback);
|
|
14988
15064
|
warnOnce(`[memorix] Embedding fallback activated: ${provider.name} (${provider.dimensions}d)`);
|
|
14989
|
-
return provider.embed(text);
|
|
15065
|
+
return provider.embed(text, options2);
|
|
14990
15066
|
}
|
|
14991
15067
|
}
|
|
14992
15068
|
if (isTemporaryEmbeddingFailure(error2)) {
|
|
@@ -14995,9 +15071,9 @@ function wrapProvider(candidate2) {
|
|
|
14995
15071
|
throw error2;
|
|
14996
15072
|
}
|
|
14997
15073
|
},
|
|
14998
|
-
async embedBatch(texts) {
|
|
15074
|
+
async embedBatch(texts, options2) {
|
|
14999
15075
|
try {
|
|
15000
|
-
return await candidate2.embedBatch(texts);
|
|
15076
|
+
return await candidate2.embedBatch(texts, options2);
|
|
15001
15077
|
} catch (error2) {
|
|
15002
15078
|
if (kind === "api" && getEmbeddingMode2() === "auto" && isTemporaryEmbeddingFailure(error2)) {
|
|
15003
15079
|
warnOnce("[memorix] API embedding temporarily unavailable \u2014 switching to local fallback provider");
|
|
@@ -15005,7 +15081,7 @@ function wrapProvider(candidate2) {
|
|
|
15005
15081
|
if (fallback) {
|
|
15006
15082
|
provider = wrapProvider(fallback);
|
|
15007
15083
|
warnOnce(`[memorix] Embedding fallback activated: ${provider.name} (${provider.dimensions}d)`);
|
|
15008
|
-
return provider.embedBatch(texts);
|
|
15084
|
+
return provider.embedBatch(texts, options2);
|
|
15009
15085
|
}
|
|
15010
15086
|
}
|
|
15011
15087
|
if (isTemporaryEmbeddingFailure(error2)) {
|
|
@@ -15061,14 +15137,14 @@ async function getEmbeddingProvider(options2 = {}) {
|
|
|
15061
15137
|
return provider;
|
|
15062
15138
|
}
|
|
15063
15139
|
if (mode === "api") {
|
|
15064
|
-
const initialized = await createAPIProvider();
|
|
15140
|
+
const initialized = await createAPIProvider(options2);
|
|
15065
15141
|
if (!initialized) return null;
|
|
15066
15142
|
provider = wrapProvider(initialized);
|
|
15067
15143
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
15068
15144
|
return provider;
|
|
15069
15145
|
}
|
|
15070
15146
|
if (hasAPIEmbeddingConfig()) {
|
|
15071
|
-
const initialized = await createAPIProvider();
|
|
15147
|
+
const initialized = await createAPIProvider(options2);
|
|
15072
15148
|
if (initialized) {
|
|
15073
15149
|
provider = wrapProvider(initialized);
|
|
15074
15150
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
@@ -18967,12 +19043,12 @@ import { createHash as createHash4 } from "crypto";
|
|
|
18967
19043
|
function digest(input) {
|
|
18968
19044
|
return createHash4("sha256").update(input).digest("hex").slice(0, 16);
|
|
18969
19045
|
}
|
|
18970
|
-
function normalizeCodePath(
|
|
18971
|
-
return
|
|
19046
|
+
function normalizeCodePath(path38) {
|
|
19047
|
+
return path38.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/");
|
|
18972
19048
|
}
|
|
18973
|
-
function makeCodeFileId(projectId,
|
|
19049
|
+
function makeCodeFileId(projectId, path38) {
|
|
18974
19050
|
return `file:${digest(`${projectId}
|
|
18975
|
-
${normalizeCodePath(
|
|
19051
|
+
${normalizeCodePath(path38)}`)}`;
|
|
18976
19052
|
}
|
|
18977
19053
|
function makeCodeSymbolId(input) {
|
|
18978
19054
|
return `symbol:${digest([
|
|
@@ -19446,8 +19522,8 @@ var init_store = __esm({
|
|
|
19446
19522
|
});
|
|
19447
19523
|
tx();
|
|
19448
19524
|
}
|
|
19449
|
-
getFile(projectId,
|
|
19450
|
-
const row = this.db.prepare(`SELECT * FROM code_files WHERE projectId = ? AND path = ?`).get(projectId, normalizeCodePath(
|
|
19525
|
+
getFile(projectId, path38) {
|
|
19526
|
+
const row = this.db.prepare(`SELECT * FROM code_files WHERE projectId = ? AND path = ?`).get(projectId, normalizeCodePath(path38));
|
|
19451
19527
|
return row ? rowToFile(row) : null;
|
|
19452
19528
|
}
|
|
19453
19529
|
listFiles(projectId) {
|
|
@@ -19682,30 +19758,30 @@ function normalizeCodeGraphExcludePatterns(exclude) {
|
|
|
19682
19758
|
...(exclude ?? []).map((pattern) => pattern.trim()).filter(Boolean)
|
|
19683
19759
|
])];
|
|
19684
19760
|
}
|
|
19685
|
-
function isCodeGraphExcludedPath(
|
|
19686
|
-
const normalized = normalizeCodePath2(
|
|
19761
|
+
function isCodeGraphExcludedPath(path38, exclude) {
|
|
19762
|
+
const normalized = normalizeCodePath2(path38);
|
|
19687
19763
|
return normalizeCodeGraphExcludePatterns(exclude).some((pattern) => matchesPattern(normalized, normalizeCodePath2(pattern)));
|
|
19688
19764
|
}
|
|
19689
|
-
function normalizeCodePath2(
|
|
19690
|
-
return
|
|
19765
|
+
function normalizeCodePath2(path38) {
|
|
19766
|
+
return path38.replace(/\\/g, "/").replace(/^\.\/+/, "");
|
|
19691
19767
|
}
|
|
19692
|
-
function matchesPattern(
|
|
19768
|
+
function matchesPattern(path38, pattern) {
|
|
19693
19769
|
if (pattern.endsWith("/**")) {
|
|
19694
19770
|
const base = pattern.slice(0, -3);
|
|
19695
19771
|
if (base.startsWith("**/")) {
|
|
19696
19772
|
const suffix = base.slice(3);
|
|
19697
|
-
return
|
|
19773
|
+
return path38 === suffix || path38.endsWith(`/${suffix}`) || path38.includes(`/${suffix}/`);
|
|
19698
19774
|
}
|
|
19699
19775
|
if (!base.includes("/")) {
|
|
19700
|
-
return
|
|
19776
|
+
return path38 === base || path38.startsWith(`${base}/`) || path38.includes(`/${base}/`);
|
|
19701
19777
|
}
|
|
19702
|
-
return
|
|
19778
|
+
return path38 === base || path38.startsWith(`${base}/`);
|
|
19703
19779
|
}
|
|
19704
19780
|
if (pattern.startsWith("**/")) {
|
|
19705
19781
|
const suffix = pattern.slice(3);
|
|
19706
|
-
return
|
|
19782
|
+
return path38 === suffix || path38.endsWith(`/${suffix}`);
|
|
19707
19783
|
}
|
|
19708
|
-
return
|
|
19784
|
+
return path38 === pattern || path38.startsWith(`${pattern}/`);
|
|
19709
19785
|
}
|
|
19710
19786
|
var DEFAULT_CODEGRAPH_EXCLUDES;
|
|
19711
19787
|
var init_exclude = __esm({
|
|
@@ -19750,12 +19826,12 @@ import { join as join5, relative } from "path";
|
|
|
19750
19826
|
function hashText(text) {
|
|
19751
19827
|
return createHash6("sha256").update(text).digest("hex");
|
|
19752
19828
|
}
|
|
19753
|
-
function extension(
|
|
19754
|
-
const index =
|
|
19755
|
-
return index === -1 ? "" :
|
|
19829
|
+
function extension(path38) {
|
|
19830
|
+
const index = path38.lastIndexOf(".");
|
|
19831
|
+
return index === -1 ? "" : path38.slice(index);
|
|
19756
19832
|
}
|
|
19757
|
-
function languageForPath(
|
|
19758
|
-
const ext = extension(
|
|
19833
|
+
function languageForPath(path38) {
|
|
19834
|
+
const ext = extension(path38);
|
|
19759
19835
|
return LANGUAGE_BY_EXTENSION.get(ext) ?? "unknown";
|
|
19760
19836
|
}
|
|
19761
19837
|
function resolveMaxFileBytes(value) {
|
|
@@ -20236,7 +20312,7 @@ function resolveObservationCodeRefs(obs, lookup) {
|
|
|
20236
20312
|
}
|
|
20237
20313
|
function createStoreLookup(store2, projectId) {
|
|
20238
20314
|
return {
|
|
20239
|
-
findFile: (
|
|
20315
|
+
findFile: (path38) => store2.getFile(projectId, path38) ?? void 0,
|
|
20240
20316
|
findSymbols: (names, hintedFileIds) => store2.findSymbolsByNames(projectId, names, hintedFileIds)
|
|
20241
20317
|
};
|
|
20242
20318
|
}
|
|
@@ -20249,7 +20325,7 @@ function createSnapshotLookup(files, symbols) {
|
|
|
20249
20325
|
symbolsByName.set(symbol.name, group);
|
|
20250
20326
|
}
|
|
20251
20327
|
return {
|
|
20252
|
-
findFile: (
|
|
20328
|
+
findFile: (path38) => filesByPath.get(normalizeCodePath(path38)),
|
|
20253
20329
|
findSymbols: (names, hintedFileIds) => {
|
|
20254
20330
|
const hinted = new Set(hintedFileIds);
|
|
20255
20331
|
const found = [];
|
|
@@ -24448,7 +24524,7 @@ var require_gray_matter = __commonJS({
|
|
|
24448
24524
|
"node_modules/gray-matter/index.js"(exports2, module2) {
|
|
24449
24525
|
"use strict";
|
|
24450
24526
|
init_esm_shims();
|
|
24451
|
-
var
|
|
24527
|
+
var fs28 = __require("fs");
|
|
24452
24528
|
var sections = require_section_matter();
|
|
24453
24529
|
var defaults = require_defaults();
|
|
24454
24530
|
var stringify = require_stringify();
|
|
@@ -24532,7 +24608,7 @@ var require_gray_matter = __commonJS({
|
|
|
24532
24608
|
return stringify(file, data, options2);
|
|
24533
24609
|
};
|
|
24534
24610
|
matter12.read = function(filepath, options2) {
|
|
24535
|
-
const str2 =
|
|
24611
|
+
const str2 = fs28.readFileSync(filepath, "utf8");
|
|
24536
24612
|
const file = matter12(str2, options2);
|
|
24537
24613
|
file.path = filepath;
|
|
24538
24614
|
return file;
|
|
@@ -25399,8 +25475,8 @@ __export(task_lens_exports, {
|
|
|
25399
25475
|
scoreLensSource: () => scoreLensSource,
|
|
25400
25476
|
shouldShowLensSource: () => shouldShowLensSource
|
|
25401
25477
|
});
|
|
25402
|
-
function normalizePath2(
|
|
25403
|
-
return
|
|
25478
|
+
function normalizePath2(path38) {
|
|
25479
|
+
return path38.replace(/\\/g, "/");
|
|
25404
25480
|
}
|
|
25405
25481
|
function tokenize3(text) {
|
|
25406
25482
|
return (text.toLowerCase().match(/[a-z0-9_./-]+|[\u4e00-\u9fff]+/g) ?? []).map((token) => token.trim()).filter((token) => token.length > 1 && !STOP_WORDS.has(token));
|
|
@@ -25462,8 +25538,8 @@ function isContinuationTask(task) {
|
|
|
25462
25538
|
(keyword) => containsTaskKeyword(normalized, keyword)
|
|
25463
25539
|
);
|
|
25464
25540
|
}
|
|
25465
|
-
function pathKindScore(
|
|
25466
|
-
const normalized = normalizePath2(
|
|
25541
|
+
function pathKindScore(path38, lens) {
|
|
25542
|
+
const normalized = normalizePath2(path38).toLowerCase();
|
|
25467
25543
|
const name = normalized.split("/").pop() ?? normalized;
|
|
25468
25544
|
const inDocs = normalized.startsWith("docs/") || name === "readme.md" || name.includes("readme");
|
|
25469
25545
|
const isTest = /(^|\/)(tests?|__tests__|spec|fixtures?)\//.test(normalized) || /\.(test|spec)\.[cm]?[jt]sx?$/.test(normalized) || /\.(test|spec)\.py$/.test(normalized);
|
|
@@ -25511,8 +25587,8 @@ function sourceTaskMatchScore(source, task) {
|
|
|
25511
25587
|
if (matches === 1) return 24;
|
|
25512
25588
|
return 0;
|
|
25513
25589
|
}
|
|
25514
|
-
function fallbackPathRank(
|
|
25515
|
-
const normalized = normalizePath2(
|
|
25590
|
+
function fallbackPathRank(path38) {
|
|
25591
|
+
const normalized = normalizePath2(path38);
|
|
25516
25592
|
if (normalized.startsWith("src/")) return 0;
|
|
25517
25593
|
if (normalized.startsWith("tests/") || normalized.startsWith("test/")) return 1;
|
|
25518
25594
|
if (normalized.startsWith("packages/") && normalized.includes("/src/")) return 2;
|
|
@@ -25521,11 +25597,11 @@ function fallbackPathRank(path37) {
|
|
|
25521
25597
|
}
|
|
25522
25598
|
function rankLensPaths(paths, lens, task) {
|
|
25523
25599
|
const tokens = tokenize3(task ?? "");
|
|
25524
|
-
return [...new Set(paths.map(normalizePath2))].map((
|
|
25525
|
-
path:
|
|
25600
|
+
return [...new Set(paths.map(normalizePath2))].map((path38, index) => ({
|
|
25601
|
+
path: path38,
|
|
25526
25602
|
index,
|
|
25527
|
-
score: pathKindScore(
|
|
25528
|
-
fallback: fallbackPathRank(
|
|
25603
|
+
score: pathKindScore(path38, lens) + tokenScore(path38, tokens),
|
|
25604
|
+
fallback: fallbackPathRank(path38)
|
|
25529
25605
|
})).sort((a3, b3) => b3.score - a3.score || a3.fallback - b3.fallback || a3.index - b3.index || a3.path.localeCompare(b3.path)).map((item) => item.path);
|
|
25530
25606
|
}
|
|
25531
25607
|
function lensPathCandidates(lens) {
|
|
@@ -32139,6 +32215,827 @@ var init_operator_shared = __esm({
|
|
|
32139
32215
|
}
|
|
32140
32216
|
});
|
|
32141
32217
|
|
|
32218
|
+
// src/memory/owner.ts
|
|
32219
|
+
var owner_exports = {};
|
|
32220
|
+
__export(owner_exports, {
|
|
32221
|
+
resolveLocalMemoryOwner: () => resolveLocalMemoryOwner
|
|
32222
|
+
});
|
|
32223
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
32224
|
+
import { promises as fs15 } from "fs";
|
|
32225
|
+
import path19 from "path";
|
|
32226
|
+
function ownerPath(dataDir) {
|
|
32227
|
+
const resolved = path19.resolve(dataDir);
|
|
32228
|
+
const home = path19.basename(resolved).toLocaleLowerCase("en-US") === "data" ? path19.dirname(resolved) : resolved;
|
|
32229
|
+
return path19.join(home, "memorix-user.json");
|
|
32230
|
+
}
|
|
32231
|
+
function normalizedOwnerId(value) {
|
|
32232
|
+
const trimmed = value?.trim();
|
|
32233
|
+
return trimmed && ID_PATTERN.test(trimmed) ? trimmed : void 0;
|
|
32234
|
+
}
|
|
32235
|
+
async function readOwnerFile(filePath) {
|
|
32236
|
+
try {
|
|
32237
|
+
const value = JSON.parse(await fs15.readFile(filePath, "utf8"));
|
|
32238
|
+
const id = typeof value.id === "string" ? normalizedOwnerId(value.id) : void 0;
|
|
32239
|
+
return id ? { id, source: "local-file" } : void 0;
|
|
32240
|
+
} catch {
|
|
32241
|
+
return void 0;
|
|
32242
|
+
}
|
|
32243
|
+
}
|
|
32244
|
+
async function resolveLocalMemoryOwner(dataDir, options2 = {}) {
|
|
32245
|
+
const configured = normalizedOwnerId(process.env.MEMORIX_USER_ID);
|
|
32246
|
+
if (configured) return { id: configured, source: "environment" };
|
|
32247
|
+
const filePath = ownerPath(dataDir);
|
|
32248
|
+
const existing = await readOwnerFile(filePath);
|
|
32249
|
+
if (existing || !options2.create) return existing;
|
|
32250
|
+
await fs15.mkdir(path19.dirname(filePath), { recursive: true });
|
|
32251
|
+
const created = {
|
|
32252
|
+
version: 1,
|
|
32253
|
+
id: "local-" + randomUUID9(),
|
|
32254
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
32255
|
+
};
|
|
32256
|
+
try {
|
|
32257
|
+
await fs15.writeFile(filePath, JSON.stringify(created, null, 2) + "\n", { encoding: "utf8", flag: "wx" });
|
|
32258
|
+
return { id: created.id, source: "local-file" };
|
|
32259
|
+
} catch (error2) {
|
|
32260
|
+
if (error2?.code !== "EEXIST") throw error2;
|
|
32261
|
+
const concurrent = await readOwnerFile(filePath);
|
|
32262
|
+
if (concurrent) return concurrent;
|
|
32263
|
+
throw new Error("Memorix could not establish a valid local memory owner identity.");
|
|
32264
|
+
}
|
|
32265
|
+
}
|
|
32266
|
+
var ID_PATTERN;
|
|
32267
|
+
var init_owner = __esm({
|
|
32268
|
+
"src/memory/owner.ts"() {
|
|
32269
|
+
"use strict";
|
|
32270
|
+
init_esm_shims();
|
|
32271
|
+
ID_PATTERN = /^[A-Za-z0-9:_-]{3,160}$/;
|
|
32272
|
+
}
|
|
32273
|
+
});
|
|
32274
|
+
|
|
32275
|
+
// src/memory/long-term-store.ts
|
|
32276
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
32277
|
+
function optionalText5(value) {
|
|
32278
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
32279
|
+
}
|
|
32280
|
+
function arrayValue2(value) {
|
|
32281
|
+
if (typeof value !== "string" || !value) return [];
|
|
32282
|
+
try {
|
|
32283
|
+
const parsed = JSON.parse(value);
|
|
32284
|
+
return Array.isArray(parsed) ? parsed.filter((item) => typeof item === "string") : [];
|
|
32285
|
+
} catch {
|
|
32286
|
+
return [];
|
|
32287
|
+
}
|
|
32288
|
+
}
|
|
32289
|
+
function rowToMemory(row) {
|
|
32290
|
+
return {
|
|
32291
|
+
id: row.id,
|
|
32292
|
+
originProjectId: row.originProjectId,
|
|
32293
|
+
ownerId: row.ownerId,
|
|
32294
|
+
scope: row.scope,
|
|
32295
|
+
kind: row.kind,
|
|
32296
|
+
state: row.state,
|
|
32297
|
+
portability: row.portability,
|
|
32298
|
+
title: row.title,
|
|
32299
|
+
content: row.content,
|
|
32300
|
+
facts: arrayValue2(row.factsJson),
|
|
32301
|
+
tags: arrayValue2(row.tagsJson),
|
|
32302
|
+
...optionalText5(row.applicability) ? { applicability: row.applicability } : {},
|
|
32303
|
+
origin: row.origin,
|
|
32304
|
+
createdAt: row.createdAt,
|
|
32305
|
+
updatedAt: row.updatedAt,
|
|
32306
|
+
...optionalText5(row.qualifiedAt) ? { qualifiedAt: row.qualifiedAt } : {},
|
|
32307
|
+
...optionalText5(row.approvedAt) ? { approvedAt: row.approvedAt } : {},
|
|
32308
|
+
...optionalText5(row.archivedAt) ? { archivedAt: row.archivedAt } : {},
|
|
32309
|
+
...optionalText5(row.supersededBy) ? { supersededBy: row.supersededBy } : {},
|
|
32310
|
+
...optionalText5(row.lastValidatedAt) ? { lastValidatedAt: row.lastValidatedAt } : {},
|
|
32311
|
+
accessCount: Number(row.accessCount ?? 0),
|
|
32312
|
+
...optionalText5(row.lastAccessedAt) ? { lastAccessedAt: row.lastAccessedAt } : {}
|
|
32313
|
+
};
|
|
32314
|
+
}
|
|
32315
|
+
function rowToEvidence2(row) {
|
|
32316
|
+
return {
|
|
32317
|
+
id: row.id,
|
|
32318
|
+
memoryId: row.memoryId,
|
|
32319
|
+
kind: row.kind,
|
|
32320
|
+
referenceId: row.referenceId,
|
|
32321
|
+
relation: row.relation,
|
|
32322
|
+
...optionalText5(row.locator) ? { locator: row.locator } : {},
|
|
32323
|
+
...optionalText5(row.capturedHash) ? { capturedHash: row.capturedHash } : {},
|
|
32324
|
+
createdAt: row.createdAt
|
|
32325
|
+
};
|
|
32326
|
+
}
|
|
32327
|
+
function rowToEvent2(row) {
|
|
32328
|
+
return {
|
|
32329
|
+
id: row.id,
|
|
32330
|
+
memoryId: row.memoryId,
|
|
32331
|
+
kind: row.kind,
|
|
32332
|
+
...optionalText5(row.fromState) ? { fromState: row.fromState } : {},
|
|
32333
|
+
...optionalText5(row.toState) ? { toState: row.toState } : {},
|
|
32334
|
+
...optionalText5(row.detail) ? { detail: row.detail } : {},
|
|
32335
|
+
createdAt: row.createdAt
|
|
32336
|
+
};
|
|
32337
|
+
}
|
|
32338
|
+
var LongTermMemoryStore;
|
|
32339
|
+
var init_long_term_store = __esm({
|
|
32340
|
+
"src/memory/long-term-store.ts"() {
|
|
32341
|
+
"use strict";
|
|
32342
|
+
init_esm_shims();
|
|
32343
|
+
init_sqlite_db();
|
|
32344
|
+
LongTermMemoryStore = class {
|
|
32345
|
+
db = null;
|
|
32346
|
+
async init(dataDir) {
|
|
32347
|
+
this.db = getDatabase(dataDir);
|
|
32348
|
+
}
|
|
32349
|
+
transaction(fn) {
|
|
32350
|
+
return this.db.transaction(fn)();
|
|
32351
|
+
}
|
|
32352
|
+
get(id) {
|
|
32353
|
+
const row = this.db.prepare("SELECT * FROM long_term_memories WHERE id = ?").get(id);
|
|
32354
|
+
return row ? rowToMemory(row) : void 0;
|
|
32355
|
+
}
|
|
32356
|
+
list(options2 = {}) {
|
|
32357
|
+
const limit = Math.max(1, Math.min(1e3, Math.floor(options2.limit ?? 500)));
|
|
32358
|
+
const clauses = [];
|
|
32359
|
+
const params = [];
|
|
32360
|
+
if (options2.ownerId) {
|
|
32361
|
+
clauses.push("ownerId = ?");
|
|
32362
|
+
params.push(options2.ownerId);
|
|
32363
|
+
}
|
|
32364
|
+
if (options2.originProjectId) {
|
|
32365
|
+
clauses.push("originProjectId = ?");
|
|
32366
|
+
params.push(options2.originProjectId);
|
|
32367
|
+
}
|
|
32368
|
+
const where = clauses.length ? " WHERE " + clauses.join(" AND ") : "";
|
|
32369
|
+
const rows = this.db.prepare(
|
|
32370
|
+
"SELECT * FROM long_term_memories" + where + " ORDER BY updatedAt DESC, id LIMIT ?"
|
|
32371
|
+
).all(...params, limit);
|
|
32372
|
+
return rows.map(rowToMemory);
|
|
32373
|
+
}
|
|
32374
|
+
insert(memory) {
|
|
32375
|
+
this.db.prepare(`
|
|
32376
|
+
INSERT INTO long_term_memories (
|
|
32377
|
+
id, originProjectId, ownerId, scope, kind, state, portability,
|
|
32378
|
+
title, content, factsJson, tagsJson, applicability, origin,
|
|
32379
|
+
createdAt, updatedAt, qualifiedAt, approvedAt, archivedAt,
|
|
32380
|
+
supersededBy, lastValidatedAt, accessCount, lastAccessedAt
|
|
32381
|
+
) VALUES (
|
|
32382
|
+
@id, @originProjectId, @ownerId, @scope, @kind, @state, @portability,
|
|
32383
|
+
@title, @content, @factsJson, @tagsJson, @applicability, @origin,
|
|
32384
|
+
@createdAt, @updatedAt, @qualifiedAt, @approvedAt, @archivedAt,
|
|
32385
|
+
@supersededBy, @lastValidatedAt, @accessCount, @lastAccessedAt
|
|
32386
|
+
)
|
|
32387
|
+
`).run({
|
|
32388
|
+
...memory,
|
|
32389
|
+
factsJson: JSON.stringify(memory.facts),
|
|
32390
|
+
tagsJson: JSON.stringify(memory.tags),
|
|
32391
|
+
applicability: memory.applicability ?? null,
|
|
32392
|
+
qualifiedAt: memory.qualifiedAt ?? null,
|
|
32393
|
+
approvedAt: memory.approvedAt ?? null,
|
|
32394
|
+
archivedAt: memory.archivedAt ?? null,
|
|
32395
|
+
supersededBy: memory.supersededBy ?? null,
|
|
32396
|
+
lastValidatedAt: memory.lastValidatedAt ?? null,
|
|
32397
|
+
lastAccessedAt: memory.lastAccessedAt ?? null
|
|
32398
|
+
});
|
|
32399
|
+
}
|
|
32400
|
+
update(memory) {
|
|
32401
|
+
this.db.prepare(`
|
|
32402
|
+
UPDATE long_term_memories SET
|
|
32403
|
+
scope = @scope,
|
|
32404
|
+
kind = @kind,
|
|
32405
|
+
state = @state,
|
|
32406
|
+
portability = @portability,
|
|
32407
|
+
title = @title,
|
|
32408
|
+
content = @content,
|
|
32409
|
+
factsJson = @factsJson,
|
|
32410
|
+
tagsJson = @tagsJson,
|
|
32411
|
+
applicability = @applicability,
|
|
32412
|
+
updatedAt = @updatedAt,
|
|
32413
|
+
qualifiedAt = @qualifiedAt,
|
|
32414
|
+
approvedAt = @approvedAt,
|
|
32415
|
+
archivedAt = @archivedAt,
|
|
32416
|
+
supersededBy = @supersededBy,
|
|
32417
|
+
lastValidatedAt = @lastValidatedAt,
|
|
32418
|
+
accessCount = @accessCount,
|
|
32419
|
+
lastAccessedAt = @lastAccessedAt
|
|
32420
|
+
WHERE id = @id
|
|
32421
|
+
`).run({
|
|
32422
|
+
...memory,
|
|
32423
|
+
factsJson: JSON.stringify(memory.facts),
|
|
32424
|
+
tagsJson: JSON.stringify(memory.tags),
|
|
32425
|
+
applicability: memory.applicability ?? null,
|
|
32426
|
+
qualifiedAt: memory.qualifiedAt ?? null,
|
|
32427
|
+
approvedAt: memory.approvedAt ?? null,
|
|
32428
|
+
archivedAt: memory.archivedAt ?? null,
|
|
32429
|
+
supersededBy: memory.supersededBy ?? null,
|
|
32430
|
+
lastValidatedAt: memory.lastValidatedAt ?? null,
|
|
32431
|
+
lastAccessedAt: memory.lastAccessedAt ?? null
|
|
32432
|
+
});
|
|
32433
|
+
}
|
|
32434
|
+
insertEvidence(input) {
|
|
32435
|
+
const evidence = {
|
|
32436
|
+
id: randomUUID10(),
|
|
32437
|
+
...input,
|
|
32438
|
+
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
32439
|
+
};
|
|
32440
|
+
this.db.prepare(`
|
|
32441
|
+
INSERT INTO long_term_memory_evidence (
|
|
32442
|
+
id, memoryId, kind, referenceId, relation, locator, capturedHash, createdAt
|
|
32443
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
32444
|
+
`).run(
|
|
32445
|
+
evidence.id,
|
|
32446
|
+
evidence.memoryId,
|
|
32447
|
+
evidence.kind,
|
|
32448
|
+
evidence.referenceId,
|
|
32449
|
+
evidence.relation,
|
|
32450
|
+
evidence.locator ?? null,
|
|
32451
|
+
evidence.capturedHash ?? null,
|
|
32452
|
+
evidence.createdAt
|
|
32453
|
+
);
|
|
32454
|
+
return evidence;
|
|
32455
|
+
}
|
|
32456
|
+
listEvidence(memoryId) {
|
|
32457
|
+
return this.db.prepare(`
|
|
32458
|
+
SELECT * FROM long_term_memory_evidence WHERE memoryId = ? ORDER BY createdAt ASC, id
|
|
32459
|
+
`).all(memoryId).map(rowToEvidence2);
|
|
32460
|
+
}
|
|
32461
|
+
recordEvent(input) {
|
|
32462
|
+
const event = {
|
|
32463
|
+
id: randomUUID10(),
|
|
32464
|
+
...input,
|
|
32465
|
+
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
32466
|
+
};
|
|
32467
|
+
this.db.prepare(`
|
|
32468
|
+
INSERT INTO long_term_memory_events (id, memoryId, kind, fromState, toState, detail, createdAt)
|
|
32469
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
32470
|
+
`).run(
|
|
32471
|
+
event.id,
|
|
32472
|
+
event.memoryId,
|
|
32473
|
+
event.kind,
|
|
32474
|
+
event.fromState ?? null,
|
|
32475
|
+
event.toState ?? null,
|
|
32476
|
+
event.detail ?? null,
|
|
32477
|
+
event.createdAt
|
|
32478
|
+
);
|
|
32479
|
+
return event;
|
|
32480
|
+
}
|
|
32481
|
+
listEvents(memoryId) {
|
|
32482
|
+
return this.db.prepare(`
|
|
32483
|
+
SELECT * FROM long_term_memory_events WHERE memoryId = ? ORDER BY createdAt ASC, rowid ASC
|
|
32484
|
+
`).all(memoryId).map(rowToEvent2);
|
|
32485
|
+
}
|
|
32486
|
+
markAccess(ids, at = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
32487
|
+
const unique3 = [...new Set(ids.filter(Boolean))];
|
|
32488
|
+
if (unique3.length === 0) return;
|
|
32489
|
+
const statement = this.db.prepare(`
|
|
32490
|
+
UPDATE long_term_memories
|
|
32491
|
+
SET accessCount = accessCount + 1, lastAccessedAt = ?
|
|
32492
|
+
WHERE id = ?
|
|
32493
|
+
`);
|
|
32494
|
+
this.db.transaction(() => {
|
|
32495
|
+
for (const id of unique3) statement.run(at, id);
|
|
32496
|
+
})();
|
|
32497
|
+
}
|
|
32498
|
+
};
|
|
32499
|
+
}
|
|
32500
|
+
});
|
|
32501
|
+
|
|
32502
|
+
// src/memory/long-term-types.ts
|
|
32503
|
+
var LONG_TERM_MEMORY_KINDS, LONG_TERM_MEMORY_SCOPES, LONG_TERM_MEMORY_PORTABILITIES, LONG_TERM_MEMORY_EVIDENCE_KINDS, LONG_TERM_MEMORY_EVIDENCE_RELATIONS;
|
|
32504
|
+
var init_long_term_types = __esm({
|
|
32505
|
+
"src/memory/long-term-types.ts"() {
|
|
32506
|
+
"use strict";
|
|
32507
|
+
init_esm_shims();
|
|
32508
|
+
LONG_TERM_MEMORY_KINDS = ["episodic", "semantic", "procedural"];
|
|
32509
|
+
LONG_TERM_MEMORY_SCOPES = ["project", "user", "team"];
|
|
32510
|
+
LONG_TERM_MEMORY_PORTABILITIES = ["project-bound", "portable"];
|
|
32511
|
+
LONG_TERM_MEMORY_EVIDENCE_KINDS = [
|
|
32512
|
+
"observation",
|
|
32513
|
+
"claim",
|
|
32514
|
+
"workflow",
|
|
32515
|
+
"session",
|
|
32516
|
+
"checkpoint",
|
|
32517
|
+
"git",
|
|
32518
|
+
"code",
|
|
32519
|
+
"test",
|
|
32520
|
+
"run",
|
|
32521
|
+
"document",
|
|
32522
|
+
"manual",
|
|
32523
|
+
"user"
|
|
32524
|
+
];
|
|
32525
|
+
LONG_TERM_MEMORY_EVIDENCE_RELATIONS = [
|
|
32526
|
+
"supports",
|
|
32527
|
+
"verifies",
|
|
32528
|
+
"derives",
|
|
32529
|
+
"user-confirmed"
|
|
32530
|
+
];
|
|
32531
|
+
}
|
|
32532
|
+
});
|
|
32533
|
+
|
|
32534
|
+
// src/memory/long-term.ts
|
|
32535
|
+
var long_term_exports = {};
|
|
32536
|
+
__export(long_term_exports, {
|
|
32537
|
+
approveLongTermMemory: () => approveLongTermMemory,
|
|
32538
|
+
archiveLongTermMemory: () => archiveLongTermMemory,
|
|
32539
|
+
canReadLongTermMemory: () => canReadLongTermMemory,
|
|
32540
|
+
createLongTermMemoryCandidate: () => createLongTermMemoryCandidate,
|
|
32541
|
+
createManualLongTermMemory: () => createManualLongTermMemory,
|
|
32542
|
+
getLongTermMemoryDetail: () => getLongTermMemoryDetail,
|
|
32543
|
+
isEligibleLongTermMemory: () => isEligibleLongTermMemory,
|
|
32544
|
+
listLongTermMemories: () => listLongTermMemories,
|
|
32545
|
+
promoteObservationToLongTermMemory: () => promoteObservationToLongTermMemory,
|
|
32546
|
+
qualifyLongTermMemory: () => qualifyLongTermMemory,
|
|
32547
|
+
renderLongTermMemorySummary: () => renderLongTermMemorySummary,
|
|
32548
|
+
selectLongTermMemoriesForTask: () => selectLongTermMemoriesForTask,
|
|
32549
|
+
supersedeLongTermMemory: () => supersedeLongTermMemory
|
|
32550
|
+
});
|
|
32551
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
32552
|
+
function isOneOf(value, values) {
|
|
32553
|
+
return typeof value === "string" && values.includes(value);
|
|
32554
|
+
}
|
|
32555
|
+
function compactText2(value, field, max = MAX_TEXT_LENGTH) {
|
|
32556
|
+
if (typeof value !== "string") throw new Error("Long-term memory " + field + " must be text.");
|
|
32557
|
+
const safe = sanitizeCredentials(value).replace(/\s+/g, " ").trim();
|
|
32558
|
+
if (!safe) throw new Error("Long-term memory " + field + " is required.");
|
|
32559
|
+
if (safe.length > max) throw new Error("Long-term memory " + field + " is too long.");
|
|
32560
|
+
return safe;
|
|
32561
|
+
}
|
|
32562
|
+
function compactList(values, field) {
|
|
32563
|
+
if (!values) return [];
|
|
32564
|
+
if (!Array.isArray(values)) throw new Error("Long-term memory " + field + " must be an array.");
|
|
32565
|
+
return [...new Set(values.filter((value) => typeof value === "string").map((value) => compactText2(value, field, 500)))].slice(0, MAX_LIST_ITEMS);
|
|
32566
|
+
}
|
|
32567
|
+
function normalizeEvidence(input) {
|
|
32568
|
+
if (!Array.isArray(input) || input.length === 0) {
|
|
32569
|
+
throw new Error("A long-term memory requires at least one source evidence reference.");
|
|
32570
|
+
}
|
|
32571
|
+
return input.map((evidence) => {
|
|
32572
|
+
if (!evidence || !isOneOf(evidence.kind, LONG_TERM_MEMORY_EVIDENCE_KINDS)) {
|
|
32573
|
+
throw new Error("Long-term memory evidence kind is invalid.");
|
|
32574
|
+
}
|
|
32575
|
+
if (!isOneOf(evidence.relation, LONG_TERM_MEMORY_EVIDENCE_RELATIONS)) {
|
|
32576
|
+
throw new Error("Long-term memory evidence relation is invalid.");
|
|
32577
|
+
}
|
|
32578
|
+
return {
|
|
32579
|
+
kind: evidence.kind,
|
|
32580
|
+
referenceId: compactText2(evidence.referenceId, "evidence reference", 1e3),
|
|
32581
|
+
relation: evidence.relation,
|
|
32582
|
+
...evidence.locator ? { locator: compactText2(evidence.locator, "evidence locator", 1e3) } : {},
|
|
32583
|
+
...evidence.capturedHash ? { capturedHash: compactText2(evidence.capturedHash, "evidence hash", 1e3) } : {}
|
|
32584
|
+
};
|
|
32585
|
+
});
|
|
32586
|
+
}
|
|
32587
|
+
function assertScope(scope) {
|
|
32588
|
+
if (!isOneOf(scope, LONG_TERM_MEMORY_SCOPES)) throw new Error("Long-term memory scope is invalid.");
|
|
32589
|
+
}
|
|
32590
|
+
function assertKind(kind) {
|
|
32591
|
+
if (!isOneOf(kind, LONG_TERM_MEMORY_KINDS)) throw new Error("Long-term memory kind is invalid.");
|
|
32592
|
+
}
|
|
32593
|
+
function assertPortability(value) {
|
|
32594
|
+
if (!isOneOf(value, LONG_TERM_MEMORY_PORTABILITIES)) {
|
|
32595
|
+
throw new Error("Long-term memory portability is invalid.");
|
|
32596
|
+
}
|
|
32597
|
+
}
|
|
32598
|
+
function assertPortableEvidence(scope, portability, evidence) {
|
|
32599
|
+
if (portability !== "portable") return;
|
|
32600
|
+
if (scope !== "user") {
|
|
32601
|
+
throw new Error("Only user-scoped long-term memories may be portable across projects.");
|
|
32602
|
+
}
|
|
32603
|
+
if (evidence.some((item) => !PORTABLE_EVIDENCE_KINDS.has(item.kind))) {
|
|
32604
|
+
throw new Error("Portable user memory may only use manual or user-confirmed evidence; project code, Git, observation, test, session, claim, and workflow evidence must remain project-bound.");
|
|
32605
|
+
}
|
|
32606
|
+
}
|
|
32607
|
+
function requireTeamReader(scope, reader) {
|
|
32608
|
+
if (scope === "team" && reader?.isTeamMember !== true) {
|
|
32609
|
+
throw new Error("Team long-term memory requires an explicit active team identity for this project.");
|
|
32610
|
+
}
|
|
32611
|
+
}
|
|
32612
|
+
function matchesScope(memory, reader) {
|
|
32613
|
+
if (memory.scope === "project") return memory.originProjectId === reader.projectId;
|
|
32614
|
+
if (memory.scope === "team") {
|
|
32615
|
+
return memory.originProjectId === reader.projectId && reader.isTeamMember === true;
|
|
32616
|
+
}
|
|
32617
|
+
if (!reader.ownerId || memory.ownerId !== reader.ownerId) return false;
|
|
32618
|
+
return memory.portability === "portable" || memory.originProjectId === reader.projectId;
|
|
32619
|
+
}
|
|
32620
|
+
function canReadLongTermMemory(memory, reader) {
|
|
32621
|
+
return matchesScope(memory, reader);
|
|
32622
|
+
}
|
|
32623
|
+
function isEligibleLongTermMemory(memory) {
|
|
32624
|
+
return memory.state === "qualified" || memory.state === "approved";
|
|
32625
|
+
}
|
|
32626
|
+
function taskTerms(task) {
|
|
32627
|
+
const matches = task.toLocaleLowerCase("en-US").match(/[\p{L}\p{N}_./:-]+/gu) ?? [];
|
|
32628
|
+
return [...new Set(matches.filter((term) => term.length > 1 && !STOP_TERMS.has(term)))].slice(0, 16);
|
|
32629
|
+
}
|
|
32630
|
+
function kindFitScore(kind, task) {
|
|
32631
|
+
const normalized = task.toLocaleLowerCase("en-US");
|
|
32632
|
+
const hints = {
|
|
32633
|
+
episodic: ["resume", "continue", "handoff", "previous", "session", "\u63A5\u624B", "\u7EE7\u7EED", "\u4EA4\u63A5", "\u4E0A\u6B21", "\u4F1A\u8BDD"],
|
|
32634
|
+
semantic: ["why", "what", "architecture", "design", "decision", "reason", "\u4E3A\u4EC0\u4E48", "\u662F\u4EC0\u4E48", "\u67B6\u6784", "\u8BBE\u8BA1", "\u51B3\u7B56", "\u539F\u56E0"],
|
|
32635
|
+
procedural: ["how", "steps", "procedure", "run", "release", "publish", "verify", "implement", "\u6D41\u7A0B", "\u6B65\u9AA4", "\u53D1\u5E03", "\u9A8C\u8BC1", "\u4FEE\u590D", "\u5B9E\u73B0"]
|
|
32636
|
+
};
|
|
32637
|
+
return hints[kind].some((hint) => normalized.includes(hint)) ? 1 : 0;
|
|
32638
|
+
}
|
|
32639
|
+
function validationFreshnessScore(memory) {
|
|
32640
|
+
const validatedAt = memory.lastValidatedAt ?? memory.approvedAt ?? memory.qualifiedAt;
|
|
32641
|
+
if (!validatedAt) return 0;
|
|
32642
|
+
const time3 = Date.parse(validatedAt);
|
|
32643
|
+
if (!Number.isFinite(time3)) return 0;
|
|
32644
|
+
const ageDays = Math.max(0, Date.now() - time3) / (24 * 60 * 60 * 1e3);
|
|
32645
|
+
if (ageDays <= 30) return 0.35;
|
|
32646
|
+
if (ageDays <= 90) return 0.15;
|
|
32647
|
+
return 0;
|
|
32648
|
+
}
|
|
32649
|
+
function scoreForTask(memory, task) {
|
|
32650
|
+
const terms = taskTerms(task);
|
|
32651
|
+
if (terms.length === 0) return void 0;
|
|
32652
|
+
const title = memory.title.toLocaleLowerCase("en-US");
|
|
32653
|
+
const content = memory.content.toLocaleLowerCase("en-US");
|
|
32654
|
+
const facts = memory.facts.join(" ").toLocaleLowerCase("en-US");
|
|
32655
|
+
const tags = memory.tags.join(" ").toLocaleLowerCase("en-US");
|
|
32656
|
+
const applicability = (memory.applicability ?? "").toLocaleLowerCase("en-US");
|
|
32657
|
+
let score = memory.state === "approved" ? 0.5 : 0;
|
|
32658
|
+
const matched = [];
|
|
32659
|
+
for (const term of terms) {
|
|
32660
|
+
let termScore = 0;
|
|
32661
|
+
if (title.includes(term)) termScore += 5;
|
|
32662
|
+
if (tags.includes(term)) termScore += 4;
|
|
32663
|
+
if (applicability.includes(term)) termScore += 3;
|
|
32664
|
+
if (facts.includes(term)) termScore += 2;
|
|
32665
|
+
if (content.includes(term)) termScore += 1;
|
|
32666
|
+
if (termScore > 0) {
|
|
32667
|
+
score += termScore;
|
|
32668
|
+
matched.push(term);
|
|
32669
|
+
}
|
|
32670
|
+
}
|
|
32671
|
+
if (matched.length === 0) return void 0;
|
|
32672
|
+
score += kindFitScore(memory.kind, task);
|
|
32673
|
+
score += validationFreshnessScore(memory);
|
|
32674
|
+
const kindLabel = memory.kind === "procedural" ? "procedure" : memory.kind === "semantic" ? "fact" : "episode";
|
|
32675
|
+
const freshness = validationFreshnessScore(memory) > 0 ? "; recently validated" : "";
|
|
32676
|
+
return { score, reason: kindLabel + " matches " + matched.slice(0, 3).join(", ") + freshness };
|
|
32677
|
+
}
|
|
32678
|
+
function semanticText(memory) {
|
|
32679
|
+
return sanitizeCredentials([
|
|
32680
|
+
memory.title,
|
|
32681
|
+
memory.applicability,
|
|
32682
|
+
memory.tags.join(" "),
|
|
32683
|
+
memory.facts.join(" "),
|
|
32684
|
+
memory.content
|
|
32685
|
+
].filter((value) => Boolean(value)).join("\n")).replace(/\s+/g, " ").trim().slice(0, MAX_TEXT_LENGTH);
|
|
32686
|
+
}
|
|
32687
|
+
function cosineSimilarity(left, right) {
|
|
32688
|
+
if (left.length === 0 || left.length !== right.length) return 0;
|
|
32689
|
+
let dot = 0;
|
|
32690
|
+
let leftMagnitude = 0;
|
|
32691
|
+
let rightMagnitude = 0;
|
|
32692
|
+
for (let index = 0; index < left.length; index += 1) {
|
|
32693
|
+
const a3 = left[index];
|
|
32694
|
+
const b3 = right[index];
|
|
32695
|
+
if (!Number.isFinite(a3) || !Number.isFinite(b3)) return 0;
|
|
32696
|
+
dot += a3 * b3;
|
|
32697
|
+
leftMagnitude += a3 * a3;
|
|
32698
|
+
rightMagnitude += b3 * b3;
|
|
32699
|
+
}
|
|
32700
|
+
if (leftMagnitude === 0 || rightMagnitude === 0) return 0;
|
|
32701
|
+
return dot / Math.sqrt(leftMagnitude * rightMagnitude);
|
|
32702
|
+
}
|
|
32703
|
+
function semanticSelection(memory, similarity, task) {
|
|
32704
|
+
if (similarity < MIN_SEMANTIC_SIMILARITY) return void 0;
|
|
32705
|
+
const kindLabel = memory.kind === "procedural" ? "procedure" : memory.kind === "semantic" ? "fact" : "episode";
|
|
32706
|
+
const freshness = validationFreshnessScore(memory) > 0 ? "; recently validated" : "";
|
|
32707
|
+
return {
|
|
32708
|
+
score: similarity * 10 + (memory.state === "approved" ? 0.5 : 0) + kindFitScore(memory.kind, task) + validationFreshnessScore(memory),
|
|
32709
|
+
reason: kindLabel + " semantic match " + similarity.toFixed(2) + freshness
|
|
32710
|
+
};
|
|
32711
|
+
}
|
|
32712
|
+
async function resolveSemanticProvider(explicit) {
|
|
32713
|
+
if (explicit !== void 0) return explicit;
|
|
32714
|
+
try {
|
|
32715
|
+
const { getEmbeddingProvider: getEmbeddingProvider2 } = await Promise.resolve().then(() => (init_provider(), provider_exports));
|
|
32716
|
+
return await withTimeout(
|
|
32717
|
+
getEmbeddingProvider2({ requestTimeoutMs: SEMANTIC_RETRIEVAL_TIMEOUT_MS, retry: false }),
|
|
32718
|
+
SEMANTIC_RETRIEVAL_TIMEOUT_MS,
|
|
32719
|
+
"Long-term semantic provider initialization"
|
|
32720
|
+
);
|
|
32721
|
+
} catch {
|
|
32722
|
+
return null;
|
|
32723
|
+
}
|
|
32724
|
+
}
|
|
32725
|
+
function createStore(dataDir) {
|
|
32726
|
+
const store2 = new LongTermMemoryStore();
|
|
32727
|
+
return store2.init(dataDir).then(() => store2);
|
|
32728
|
+
}
|
|
32729
|
+
async function createManualLongTermMemory(input) {
|
|
32730
|
+
const owner = await resolveLocalMemoryOwner(input.dataDir, { create: true });
|
|
32731
|
+
if (!owner) throw new Error("Memorix could not resolve a local memory owner.");
|
|
32732
|
+
assertScope(input.scope);
|
|
32733
|
+
const evidence = input.scope === "user" ? [{ kind: "user", referenceId: owner.id, relation: "user-confirmed" }] : [{ kind: "manual", referenceId: "manual:" + randomUUID11(), relation: "supports" }];
|
|
32734
|
+
return createLongTermMemoryWithDataDir({
|
|
32735
|
+
dataDir: input.dataDir,
|
|
32736
|
+
originProjectId: input.projectId,
|
|
32737
|
+
ownerId: owner.id,
|
|
32738
|
+
scope: input.scope,
|
|
32739
|
+
kind: input.kind,
|
|
32740
|
+
portability: input.portability,
|
|
32741
|
+
title: input.title,
|
|
32742
|
+
content: input.content,
|
|
32743
|
+
facts: input.facts,
|
|
32744
|
+
tags: input.tags,
|
|
32745
|
+
applicability: input.applicability,
|
|
32746
|
+
origin: "manual",
|
|
32747
|
+
evidence,
|
|
32748
|
+
reader: input.reader
|
|
32749
|
+
});
|
|
32750
|
+
}
|
|
32751
|
+
async function promoteObservationToLongTermMemory(input) {
|
|
32752
|
+
const owner = await resolveLocalMemoryOwner(input.dataDir, { create: true });
|
|
32753
|
+
if (!owner) throw new Error("Memorix could not resolve a local memory owner.");
|
|
32754
|
+
return createLongTermMemoryWithDataDir({
|
|
32755
|
+
dataDir: input.dataDir,
|
|
32756
|
+
originProjectId: input.observation.projectId,
|
|
32757
|
+
ownerId: owner.id,
|
|
32758
|
+
scope: input.scope,
|
|
32759
|
+
kind: input.kind,
|
|
32760
|
+
portability: "project-bound",
|
|
32761
|
+
title: input.observation.title,
|
|
32762
|
+
content: input.observation.narrative,
|
|
32763
|
+
facts: input.observation.facts,
|
|
32764
|
+
tags: input.tags ?? input.observation.concepts,
|
|
32765
|
+
applicability: input.applicability,
|
|
32766
|
+
origin: input.observation.source === "git" ? "git" : "agent",
|
|
32767
|
+
evidence: [{
|
|
32768
|
+
kind: "observation",
|
|
32769
|
+
referenceId: "obs:" + input.observation.projectId + ":" + input.observation.id,
|
|
32770
|
+
relation: "derives"
|
|
32771
|
+
}],
|
|
32772
|
+
reader: input.reader
|
|
32773
|
+
});
|
|
32774
|
+
}
|
|
32775
|
+
async function createLongTermMemoryCandidate(input) {
|
|
32776
|
+
return createLongTermMemoryWithDataDir(input);
|
|
32777
|
+
}
|
|
32778
|
+
async function createLongTermMemoryWithDataDir(input) {
|
|
32779
|
+
assertScope(input.scope);
|
|
32780
|
+
assertKind(input.kind);
|
|
32781
|
+
const portability = input.portability ?? "project-bound";
|
|
32782
|
+
assertPortability(portability);
|
|
32783
|
+
requireTeamReader(input.scope, input.reader);
|
|
32784
|
+
const evidenceInputs = normalizeEvidence(input.evidence);
|
|
32785
|
+
assertPortableEvidence(input.scope, portability, evidenceInputs);
|
|
32786
|
+
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
32787
|
+
const memory = {
|
|
32788
|
+
id: randomUUID11(),
|
|
32789
|
+
originProjectId: compactText2(input.originProjectId, "origin project id", 1e3),
|
|
32790
|
+
ownerId: compactText2(input.ownerId, "owner id", 160),
|
|
32791
|
+
scope: input.scope,
|
|
32792
|
+
kind: input.kind,
|
|
32793
|
+
state: "candidate",
|
|
32794
|
+
portability,
|
|
32795
|
+
title: compactText2(input.title, "title", 500),
|
|
32796
|
+
content: compactText2(input.content, "content"),
|
|
32797
|
+
facts: compactList(input.facts, "facts"),
|
|
32798
|
+
tags: compactList(input.tags, "tags"),
|
|
32799
|
+
...input.applicability ? { applicability: compactText2(input.applicability, "applicability", 1e3) } : {},
|
|
32800
|
+
origin: input.origin ?? "manual",
|
|
32801
|
+
createdAt: now3,
|
|
32802
|
+
updatedAt: now3,
|
|
32803
|
+
accessCount: 0
|
|
32804
|
+
};
|
|
32805
|
+
const store2 = await createStore(input.dataDir);
|
|
32806
|
+
const evidence = store2.transaction(() => {
|
|
32807
|
+
store2.insert(memory);
|
|
32808
|
+
const written = evidenceInputs.map((item) => store2.insertEvidence({ memoryId: memory.id, ...item, createdAt: now3 }));
|
|
32809
|
+
store2.recordEvent({
|
|
32810
|
+
memoryId: memory.id,
|
|
32811
|
+
kind: "created",
|
|
32812
|
+
toState: "candidate",
|
|
32813
|
+
detail: "Created as a source-backed long-term memory candidate.",
|
|
32814
|
+
createdAt: now3
|
|
32815
|
+
});
|
|
32816
|
+
return written;
|
|
32817
|
+
});
|
|
32818
|
+
return { memory, evidence };
|
|
32819
|
+
}
|
|
32820
|
+
function transitionDetail(value) {
|
|
32821
|
+
return compactText2(value, "transition reason", 1e3);
|
|
32822
|
+
}
|
|
32823
|
+
async function transitionMemory(input) {
|
|
32824
|
+
const store2 = await createStore(input.dataDir);
|
|
32825
|
+
return store2.transaction(() => {
|
|
32826
|
+
const current = store2.get(input.id);
|
|
32827
|
+
if (!current) throw new Error("Long-term memory was not found.");
|
|
32828
|
+
if (current.state !== input.expected) {
|
|
32829
|
+
throw new Error("Long-term memory must be " + input.expected + " before it can be " + input.next + ".");
|
|
32830
|
+
}
|
|
32831
|
+
const evidence = store2.listEvidence(current.id);
|
|
32832
|
+
if (evidence.length === 0) throw new Error("Long-term memory cannot advance without source evidence.");
|
|
32833
|
+
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
32834
|
+
const next = {
|
|
32835
|
+
...current,
|
|
32836
|
+
state: input.next,
|
|
32837
|
+
updatedAt: now3,
|
|
32838
|
+
lastValidatedAt: now3,
|
|
32839
|
+
...input.next === "qualified" ? { qualifiedAt: now3 } : { approvedAt: now3 }
|
|
32840
|
+
};
|
|
32841
|
+
store2.update(next);
|
|
32842
|
+
store2.recordEvent({
|
|
32843
|
+
memoryId: next.id,
|
|
32844
|
+
kind: input.event,
|
|
32845
|
+
fromState: current.state,
|
|
32846
|
+
toState: next.state,
|
|
32847
|
+
detail: transitionDetail(input.reason),
|
|
32848
|
+
createdAt: now3
|
|
32849
|
+
});
|
|
32850
|
+
return next;
|
|
32851
|
+
});
|
|
32852
|
+
}
|
|
32853
|
+
async function qualifyLongTermMemory(input) {
|
|
32854
|
+
return transitionMemory({ ...input, expected: "candidate", next: "qualified", event: "qualified" });
|
|
32855
|
+
}
|
|
32856
|
+
async function approveLongTermMemory(input) {
|
|
32857
|
+
return transitionMemory({ ...input, expected: "qualified", next: "approved", event: "approved" });
|
|
32858
|
+
}
|
|
32859
|
+
async function archiveLongTermMemory(input) {
|
|
32860
|
+
const store2 = await createStore(input.dataDir);
|
|
32861
|
+
return store2.transaction(() => {
|
|
32862
|
+
const current = store2.get(input.id);
|
|
32863
|
+
if (!current) throw new Error("Long-term memory was not found.");
|
|
32864
|
+
if (current.state === "archived" || current.state === "superseded") {
|
|
32865
|
+
throw new Error("Long-term memory is already inactive.");
|
|
32866
|
+
}
|
|
32867
|
+
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
32868
|
+
const next = { ...current, state: "archived", archivedAt: now3, updatedAt: now3 };
|
|
32869
|
+
store2.update(next);
|
|
32870
|
+
store2.recordEvent({
|
|
32871
|
+
memoryId: next.id,
|
|
32872
|
+
kind: "archived",
|
|
32873
|
+
fromState: current.state,
|
|
32874
|
+
toState: "archived",
|
|
32875
|
+
detail: transitionDetail(input.reason),
|
|
32876
|
+
createdAt: now3
|
|
32877
|
+
});
|
|
32878
|
+
return next;
|
|
32879
|
+
});
|
|
32880
|
+
}
|
|
32881
|
+
async function supersedeLongTermMemory(input) {
|
|
32882
|
+
const store2 = await createStore(input.dataDir);
|
|
32883
|
+
return store2.transaction(() => {
|
|
32884
|
+
const current = store2.get(input.id);
|
|
32885
|
+
if (!current) throw new Error("Long-term memory was not found.");
|
|
32886
|
+
if (current.state === "archived" || current.state === "superseded") {
|
|
32887
|
+
throw new Error("Long-term memory is already inactive.");
|
|
32888
|
+
}
|
|
32889
|
+
if (current.id === input.supersededBy) {
|
|
32890
|
+
throw new Error("Long-term memory cannot supersede itself.");
|
|
32891
|
+
}
|
|
32892
|
+
const replacement = store2.get(input.supersededBy);
|
|
32893
|
+
if (!replacement || !isEligibleLongTermMemory(replacement)) {
|
|
32894
|
+
throw new Error("Replacement long-term memory must be qualified or approved.");
|
|
32895
|
+
}
|
|
32896
|
+
if (replacement.scope !== current.scope) {
|
|
32897
|
+
throw new Error("Replacement long-term memory must use the same scope.");
|
|
32898
|
+
}
|
|
32899
|
+
if (current.scope === "user" && replacement.ownerId !== current.ownerId) {
|
|
32900
|
+
throw new Error("User long-term memory may only be superseded by the same local owner.");
|
|
32901
|
+
}
|
|
32902
|
+
if (current.scope !== "user" && replacement.originProjectId !== current.originProjectId) {
|
|
32903
|
+
throw new Error("Project and team long-term memory may only be superseded within the same project.");
|
|
32904
|
+
}
|
|
32905
|
+
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
32906
|
+
const next = {
|
|
32907
|
+
...current,
|
|
32908
|
+
state: "superseded",
|
|
32909
|
+
supersededBy: replacement.id,
|
|
32910
|
+
updatedAt: now3
|
|
32911
|
+
};
|
|
32912
|
+
store2.update(next);
|
|
32913
|
+
store2.recordEvent({
|
|
32914
|
+
memoryId: next.id,
|
|
32915
|
+
kind: "superseded",
|
|
32916
|
+
fromState: current.state,
|
|
32917
|
+
toState: "superseded",
|
|
32918
|
+
detail: transitionDetail(input.reason),
|
|
32919
|
+
createdAt: now3
|
|
32920
|
+
});
|
|
32921
|
+
return next;
|
|
32922
|
+
});
|
|
32923
|
+
}
|
|
32924
|
+
async function listLongTermMemories(input) {
|
|
32925
|
+
const store2 = await createStore(input.dataDir);
|
|
32926
|
+
return store2.list({ limit: input.limit ?? 100 }).filter((memory) => canReadLongTermMemory(memory, input.reader)).filter((memory) => input.includeInactive || memory.state !== "archived" && memory.state !== "superseded").map((memory) => ({ memory, evidence: store2.listEvidence(memory.id) }));
|
|
32927
|
+
}
|
|
32928
|
+
async function getLongTermMemoryDetail(input) {
|
|
32929
|
+
const store2 = await createStore(input.dataDir);
|
|
32930
|
+
const memory = store2.get(input.id);
|
|
32931
|
+
if (!memory || !canReadLongTermMemory(memory, input.reader)) {
|
|
32932
|
+
throw new Error("Long-term memory was not found in the active scope.");
|
|
32933
|
+
}
|
|
32934
|
+
store2.markAccess([memory.id]);
|
|
32935
|
+
return { memory, evidence: store2.listEvidence(memory.id), events: store2.listEvents(memory.id) };
|
|
32936
|
+
}
|
|
32937
|
+
async function selectLongTermMemoriesForTask(input) {
|
|
32938
|
+
const task = input.task?.trim();
|
|
32939
|
+
if (!task) return [];
|
|
32940
|
+
const owner = await resolveLocalMemoryOwner(input.dataDir, { create: false });
|
|
32941
|
+
const reader = {
|
|
32942
|
+
projectId: input.projectId,
|
|
32943
|
+
...owner ? { ownerId: owner.id } : {},
|
|
32944
|
+
...input.agentId ? { agentId: input.agentId } : {},
|
|
32945
|
+
...input.isTeamMember ? { isTeamMember: true } : {}
|
|
32946
|
+
};
|
|
32947
|
+
const store2 = await createStore(input.dataDir);
|
|
32948
|
+
const eligible = store2.list({ limit: 1e3 }).filter((memory) => isEligibleLongTermMemory(memory) && canReadLongTermMemory(memory, reader));
|
|
32949
|
+
let selected = eligible.map((memory) => {
|
|
32950
|
+
const ranked = scoreForTask(memory, task);
|
|
32951
|
+
return ranked ? {
|
|
32952
|
+
memory,
|
|
32953
|
+
evidence: store2.listEvidence(memory.id),
|
|
32954
|
+
score: ranked.score,
|
|
32955
|
+
reason: ranked.reason
|
|
32956
|
+
} : void 0;
|
|
32957
|
+
}).filter((item) => Boolean(item)).sort((left, right) => right.score - left.score || right.memory.updatedAt.localeCompare(left.memory.updatedAt) || left.memory.id.localeCompare(right.memory.id));
|
|
32958
|
+
if (selected.length === 0 && eligible.length > 0) {
|
|
32959
|
+
const provider2 = await resolveSemanticProvider(input.embeddingProvider);
|
|
32960
|
+
const candidates = eligible.slice(0, MAX_SEMANTIC_CANDIDATES);
|
|
32961
|
+
if (provider2 && candidates.length > 0) {
|
|
32962
|
+
try {
|
|
32963
|
+
const vectors = await withTimeout(
|
|
32964
|
+
provider2.embedBatch([task, ...candidates.map(semanticText)], {
|
|
32965
|
+
timeoutMs: SEMANTIC_RETRIEVAL_TIMEOUT_MS,
|
|
32966
|
+
retry: false
|
|
32967
|
+
}),
|
|
32968
|
+
SEMANTIC_RETRIEVAL_TIMEOUT_MS,
|
|
32969
|
+
"Long-term semantic retrieval"
|
|
32970
|
+
);
|
|
32971
|
+
const query = vectors[0];
|
|
32972
|
+
if (Array.isArray(query)) {
|
|
32973
|
+
selected = candidates.map((memory, index) => {
|
|
32974
|
+
const vector = vectors[index + 1];
|
|
32975
|
+
const ranked = Array.isArray(vector) ? semanticSelection(memory, cosineSimilarity(query, vector), task) : void 0;
|
|
32976
|
+
return ranked ? {
|
|
32977
|
+
memory,
|
|
32978
|
+
evidence: store2.listEvidence(memory.id),
|
|
32979
|
+
score: ranked.score,
|
|
32980
|
+
reason: ranked.reason
|
|
32981
|
+
} : void 0;
|
|
32982
|
+
}).filter((item) => Boolean(item)).sort((left, right) => right.score - left.score || right.memory.updatedAt.localeCompare(left.memory.updatedAt) || left.memory.id.localeCompare(right.memory.id));
|
|
32983
|
+
}
|
|
32984
|
+
} catch {
|
|
32985
|
+
}
|
|
32986
|
+
}
|
|
32987
|
+
}
|
|
32988
|
+
selected = selected.slice(0, Math.max(1, Math.min(input.limit ?? 3, 5)));
|
|
32989
|
+
store2.markAccess(selected.map((item) => item.memory.id));
|
|
32990
|
+
return selected;
|
|
32991
|
+
}
|
|
32992
|
+
function renderLongTermMemorySummary(memory, maxTokens = 22) {
|
|
32993
|
+
const source = [memory.title, memory.applicability, memory.content].filter(Boolean).join(": ");
|
|
32994
|
+
const safe = sanitizeCredentials(source).replace(/\s+/g, " ").trim();
|
|
32995
|
+
return countTextTokens(safe) <= maxTokens ? safe : truncateToTokenBudget(safe, maxTokens);
|
|
32996
|
+
}
|
|
32997
|
+
var MAX_TEXT_LENGTH, MAX_LIST_ITEMS, MAX_SEMANTIC_CANDIDATES, SEMANTIC_RETRIEVAL_TIMEOUT_MS, MIN_SEMANTIC_SIMILARITY, PORTABLE_EVIDENCE_KINDS, STOP_TERMS;
|
|
32998
|
+
var init_long_term = __esm({
|
|
32999
|
+
"src/memory/long-term.ts"() {
|
|
33000
|
+
"use strict";
|
|
33001
|
+
init_esm_shims();
|
|
33002
|
+
init_token_budget();
|
|
33003
|
+
init_timeout();
|
|
33004
|
+
init_secret_filter();
|
|
33005
|
+
init_owner();
|
|
33006
|
+
init_long_term_store();
|
|
33007
|
+
init_long_term_types();
|
|
33008
|
+
MAX_TEXT_LENGTH = 12e3;
|
|
33009
|
+
MAX_LIST_ITEMS = 40;
|
|
33010
|
+
MAX_SEMANTIC_CANDIDATES = 48;
|
|
33011
|
+
SEMANTIC_RETRIEVAL_TIMEOUT_MS = 1800;
|
|
33012
|
+
MIN_SEMANTIC_SIMILARITY = 0.58;
|
|
33013
|
+
PORTABLE_EVIDENCE_KINDS = /* @__PURE__ */ new Set(["manual", "user"]);
|
|
33014
|
+
STOP_TERMS = /* @__PURE__ */ new Set([
|
|
33015
|
+
"the",
|
|
33016
|
+
"and",
|
|
33017
|
+
"for",
|
|
33018
|
+
"with",
|
|
33019
|
+
"from",
|
|
33020
|
+
"that",
|
|
33021
|
+
"this",
|
|
33022
|
+
"into",
|
|
33023
|
+
"when",
|
|
33024
|
+
"what",
|
|
33025
|
+
"\u5982\u4F55",
|
|
33026
|
+
"\u4EC0\u4E48",
|
|
33027
|
+
"\u8FD9\u4E2A",
|
|
33028
|
+
"\u90A3\u4E2A",
|
|
33029
|
+
"\u6211\u4EEC",
|
|
33030
|
+
"\u9879\u76EE",
|
|
33031
|
+
"\u8FDB\u884C",
|
|
33032
|
+
"\u9700\u8981",
|
|
33033
|
+
"\u7EE7\u7EED",
|
|
33034
|
+
"\u5904\u7406"
|
|
33035
|
+
]);
|
|
33036
|
+
}
|
|
33037
|
+
});
|
|
33038
|
+
|
|
32142
33039
|
// src/cli/commands/memory.ts
|
|
32143
33040
|
var memory_exports = {};
|
|
32144
33041
|
__export(memory_exports, {
|
|
@@ -32151,6 +33048,26 @@ function getStringArg(named, positional) {
|
|
|
32151
33048
|
function getIdArg(args, positional) {
|
|
32152
33049
|
return args.ids || args.id || positional.join(",");
|
|
32153
33050
|
}
|
|
33051
|
+
function longTermKind(value) {
|
|
33052
|
+
const normalized = (value ?? "semantic").trim().toLowerCase();
|
|
33053
|
+
if (normalized === "episodic" || normalized === "semantic" || normalized === "procedural") return normalized;
|
|
33054
|
+
throw new Error("long-term kind must be episodic, semantic, or procedural.");
|
|
33055
|
+
}
|
|
33056
|
+
function longTermScope(value) {
|
|
33057
|
+
const normalized = (value ?? "project").trim().toLowerCase();
|
|
33058
|
+
if (normalized === "project" || normalized === "user" || normalized === "team") return normalized;
|
|
33059
|
+
throw new Error("long-term scope must be project, user, or team.");
|
|
33060
|
+
}
|
|
33061
|
+
function longTermPortability(value) {
|
|
33062
|
+
const normalized = (value ?? "project-bound").trim().toLowerCase();
|
|
33063
|
+
if (normalized === "project-bound" || normalized === "portable") return normalized;
|
|
33064
|
+
throw new Error("long-term portability must be project-bound or portable.");
|
|
33065
|
+
}
|
|
33066
|
+
function requiredLongTermReason(value) {
|
|
33067
|
+
const reason = value?.trim();
|
|
33068
|
+
if (!reason) throw new Error("reason is required for this long-term memory transition.");
|
|
33069
|
+
return reason;
|
|
33070
|
+
}
|
|
32154
33071
|
var memory_default;
|
|
32155
33072
|
var init_memory = __esm({
|
|
32156
33073
|
"src/cli/commands/memory.ts"() {
|
|
@@ -32197,16 +33114,27 @@ var init_memory = __esm({
|
|
|
32197
33114
|
instruction: { type: "string", description: "Custom instruction for promoted mini-skills" },
|
|
32198
33115
|
tags: { type: "string", description: "Comma-separated extra tags for promoted mini-skills" },
|
|
32199
33116
|
skillId: { type: "string", description: "Mini-skill ID for list/delete actions" },
|
|
33117
|
+
kind: { type: "string", description: "Long-term memory kind: episodic, semantic, or procedural" },
|
|
33118
|
+
scope: { type: "string", description: "Long-term memory scope: project, user, or team" },
|
|
33119
|
+
portability: { type: "string", description: "Long-term memory portability: project-bound or portable" },
|
|
33120
|
+
applicability: { type: "string", description: "When a long-term memory applies" },
|
|
33121
|
+
fromObservation: { type: "string", description: "Observation ID to promote into long-term memory" },
|
|
33122
|
+
supersededBy: { type: "string", description: "Qualified or approved long-term memory that replaces the current record" },
|
|
33123
|
+
"superseded-by": { type: "string", description: "Kebab-case alias for --supersededBy" },
|
|
33124
|
+
reason: { type: "string", description: "Evidence review reason for qualify, approve, or archive" },
|
|
33125
|
+
all: { type: "boolean", description: "Include archived and superseded long-term memories in list output" },
|
|
32200
33126
|
json: { type: "boolean", description: "Emit machine-readable JSON output" }
|
|
32201
33127
|
},
|
|
32202
33128
|
run: async ({ args }) => {
|
|
32203
33129
|
const action = args._?.[0] || "";
|
|
32204
33130
|
const positional = (args._ ?? []).slice(1);
|
|
33131
|
+
const longTermAction = action === "long-term" ? (positional[0] || args.action || "list").trim().toLowerCase() : void 0;
|
|
32205
33132
|
const asJson = !!args.json;
|
|
32206
33133
|
try {
|
|
32207
33134
|
const readOnlyActions = /* @__PURE__ */ new Set(["", "search", "graph-context", "recent", "suggest-topic-key", "detail", "timeline"]);
|
|
32208
33135
|
const needsSearchIndex = action === "search" || action === "detail" || action === "timeline";
|
|
32209
|
-
const
|
|
33136
|
+
const longTermReadOnly = longTermAction === "list" || longTermAction === "show";
|
|
33137
|
+
const context = readOnlyActions.has(action) || longTermReadOnly ? await getCliReadContext({ searchIndex: needsSearchIndex }) : await getCliProjectContext({ searchIndex: true });
|
|
32210
33138
|
const { project, dataDir, reader, identity } = context;
|
|
32211
33139
|
switch (action) {
|
|
32212
33140
|
case "search": {
|
|
@@ -32518,6 +33446,160 @@ var init_memory = __esm({
|
|
|
32518
33446
|
);
|
|
32519
33447
|
return;
|
|
32520
33448
|
}
|
|
33449
|
+
case "long-term": {
|
|
33450
|
+
const resolvedLongTermAction = longTermAction ?? "list";
|
|
33451
|
+
const longTermPositional = positional.slice(1);
|
|
33452
|
+
const {
|
|
33453
|
+
archiveLongTermMemory: archiveLongTermMemory2,
|
|
33454
|
+
approveLongTermMemory: approveLongTermMemory2,
|
|
33455
|
+
createManualLongTermMemory: createManualLongTermMemory2,
|
|
33456
|
+
getLongTermMemoryDetail: getLongTermMemoryDetail2,
|
|
33457
|
+
listLongTermMemories: listLongTermMemories2,
|
|
33458
|
+
promoteObservationToLongTermMemory: promoteObservationToLongTermMemory2,
|
|
33459
|
+
qualifyLongTermMemory: qualifyLongTermMemory2,
|
|
33460
|
+
supersedeLongTermMemory: supersedeLongTermMemory2
|
|
33461
|
+
} = await Promise.resolve().then(() => (init_long_term(), long_term_exports));
|
|
33462
|
+
const { resolveLocalMemoryOwner: resolveLocalMemoryOwner2 } = await Promise.resolve().then(() => (init_owner(), owner_exports));
|
|
33463
|
+
const owner = await resolveLocalMemoryOwner2(dataDir, { create: false });
|
|
33464
|
+
const longTermReader = {
|
|
33465
|
+
projectId: project.id,
|
|
33466
|
+
...owner ? { ownerId: owner.id } : {},
|
|
33467
|
+
...reader.agentId ? { agentId: reader.agentId } : {},
|
|
33468
|
+
...reader.isTeamMember ? { isTeamMember: true } : {}
|
|
33469
|
+
};
|
|
33470
|
+
const memoryId = () => {
|
|
33471
|
+
const id = args.id?.trim() || args.fromObservation?.trim() || longTermPositional[0]?.trim();
|
|
33472
|
+
if (!id) throw new Error("long-term memory id is required.");
|
|
33473
|
+
return id;
|
|
33474
|
+
};
|
|
33475
|
+
const scope = () => longTermScope(args.scope);
|
|
33476
|
+
const kind = () => longTermKind(args.kind);
|
|
33477
|
+
const portability = () => longTermPortability(args.portability);
|
|
33478
|
+
const reason = () => requiredLongTermReason(args.reason);
|
|
33479
|
+
switch (resolvedLongTermAction) {
|
|
33480
|
+
case "list": {
|
|
33481
|
+
const memories = await listLongTermMemories2({
|
|
33482
|
+
dataDir,
|
|
33483
|
+
reader: longTermReader,
|
|
33484
|
+
includeInactive: !!args.all,
|
|
33485
|
+
limit: parsePositiveInt(args.limit, 50)
|
|
33486
|
+
});
|
|
33487
|
+
emitResult(
|
|
33488
|
+
{ project, memories },
|
|
33489
|
+
memories.length === 0 ? "No long-term memories are visible in the active scope." : memories.map((item) => `- ${item.memory.id} [${item.memory.state}/${item.memory.kind}/${item.memory.scope}] ${item.memory.title}`).join("\n"),
|
|
33490
|
+
asJson
|
|
33491
|
+
);
|
|
33492
|
+
return;
|
|
33493
|
+
}
|
|
33494
|
+
case "show": {
|
|
33495
|
+
const detail = await getLongTermMemoryDetail2({ dataDir, id: memoryId(), reader: longTermReader });
|
|
33496
|
+
emitResult(
|
|
33497
|
+
{ project, ...detail },
|
|
33498
|
+
[
|
|
33499
|
+
`${detail.memory.id} [${detail.memory.state}/${detail.memory.kind}/${detail.memory.scope}]`,
|
|
33500
|
+
detail.memory.title,
|
|
33501
|
+
detail.memory.content,
|
|
33502
|
+
`Evidence: ${detail.evidence.length}`,
|
|
33503
|
+
`Audit events: ${detail.events.length}`
|
|
33504
|
+
].join("\n"),
|
|
33505
|
+
asJson
|
|
33506
|
+
);
|
|
33507
|
+
return;
|
|
33508
|
+
}
|
|
33509
|
+
case "add": {
|
|
33510
|
+
const content = getStringArg(args.text, longTermPositional);
|
|
33511
|
+
if (!content) {
|
|
33512
|
+
emitError('text is required for "memorix memory long-term add"', asJson);
|
|
33513
|
+
return;
|
|
33514
|
+
}
|
|
33515
|
+
const result = await createManualLongTermMemory2({
|
|
33516
|
+
dataDir,
|
|
33517
|
+
projectId: project.id,
|
|
33518
|
+
scope: scope(),
|
|
33519
|
+
kind: kind(),
|
|
33520
|
+
title: args.title?.trim() || content.slice(0, 100),
|
|
33521
|
+
content,
|
|
33522
|
+
facts: parseCsvList(args.facts),
|
|
33523
|
+
tags: parseCsvList(args.tags),
|
|
33524
|
+
applicability: args.applicability?.trim(),
|
|
33525
|
+
portability: portability(),
|
|
33526
|
+
reader: longTermReader
|
|
33527
|
+
});
|
|
33528
|
+
emitResult(
|
|
33529
|
+
{ project, ...result },
|
|
33530
|
+
`Created long-term memory candidate ${result.memory.id}. Qualify it after checking its evidence.`,
|
|
33531
|
+
asJson
|
|
33532
|
+
);
|
|
33533
|
+
return;
|
|
33534
|
+
}
|
|
33535
|
+
case "promote": {
|
|
33536
|
+
const rawId = args.fromObservation?.trim() || args.id?.trim() || longTermPositional[0]?.trim();
|
|
33537
|
+
const observationId2 = Number.parseInt(rawId || "", 10);
|
|
33538
|
+
if (!Number.isFinite(observationId2)) {
|
|
33539
|
+
emitError('fromObservation or id must be an observation ID for "memorix memory long-term promote"', asJson);
|
|
33540
|
+
return;
|
|
33541
|
+
}
|
|
33542
|
+
const observation = getObservation(observationId2, project.id);
|
|
33543
|
+
if (!observation || !canManageObservation(observation, reader)) {
|
|
33544
|
+
emitError("Observation was not found or is outside the active write scope.", asJson);
|
|
33545
|
+
return;
|
|
33546
|
+
}
|
|
33547
|
+
const result = await promoteObservationToLongTermMemory2({
|
|
33548
|
+
dataDir,
|
|
33549
|
+
observation,
|
|
33550
|
+
scope: scope(),
|
|
33551
|
+
kind: kind(),
|
|
33552
|
+
tags: parseCsvList(args.tags),
|
|
33553
|
+
applicability: args.applicability?.trim(),
|
|
33554
|
+
reader: longTermReader
|
|
33555
|
+
});
|
|
33556
|
+
emitResult(
|
|
33557
|
+
{ project, sourceObservationId: observation.id, ...result },
|
|
33558
|
+
`Promoted observation #${observation.id} to long-term memory candidate ${result.memory.id}.`,
|
|
33559
|
+
asJson
|
|
33560
|
+
);
|
|
33561
|
+
return;
|
|
33562
|
+
}
|
|
33563
|
+
case "qualify": {
|
|
33564
|
+
await getLongTermMemoryDetail2({ dataDir, id: memoryId(), reader: longTermReader });
|
|
33565
|
+
const memory = await qualifyLongTermMemory2({ dataDir, id: memoryId(), reason: reason() });
|
|
33566
|
+
emitResult({ project, memory }, `Qualified long-term memory ${memory.id}.`, asJson);
|
|
33567
|
+
return;
|
|
33568
|
+
}
|
|
33569
|
+
case "approve": {
|
|
33570
|
+
await getLongTermMemoryDetail2({ dataDir, id: memoryId(), reader: longTermReader });
|
|
33571
|
+
const memory = await approveLongTermMemory2({ dataDir, id: memoryId(), reason: reason() });
|
|
33572
|
+
emitResult({ project, memory }, `Approved long-term memory ${memory.id}.`, asJson);
|
|
33573
|
+
return;
|
|
33574
|
+
}
|
|
33575
|
+
case "archive": {
|
|
33576
|
+
await getLongTermMemoryDetail2({ dataDir, id: memoryId(), reader: longTermReader });
|
|
33577
|
+
const memory = await archiveLongTermMemory2({ dataDir, id: memoryId(), reason: reason() });
|
|
33578
|
+
emitResult({ project, memory }, `Archived long-term memory ${memory.id}.`, asJson);
|
|
33579
|
+
return;
|
|
33580
|
+
}
|
|
33581
|
+
case "supersede": {
|
|
33582
|
+
const supersededBy = args.supersededBy?.trim() || args["superseded-by"]?.trim();
|
|
33583
|
+
if (!supersededBy) {
|
|
33584
|
+
emitError('supersededBy is required for "memorix memory long-term supersede"', asJson);
|
|
33585
|
+
return;
|
|
33586
|
+
}
|
|
33587
|
+
await getLongTermMemoryDetail2({ dataDir, id: memoryId(), reader: longTermReader });
|
|
33588
|
+
await getLongTermMemoryDetail2({ dataDir, id: supersededBy, reader: longTermReader });
|
|
33589
|
+
const memory = await supersedeLongTermMemory2({
|
|
33590
|
+
dataDir,
|
|
33591
|
+
id: memoryId(),
|
|
33592
|
+
supersededBy,
|
|
33593
|
+
reason: reason()
|
|
33594
|
+
});
|
|
33595
|
+
emitResult({ project, memory }, `Superseded long-term memory ${memory.id} with ${supersededBy}.`, asJson);
|
|
33596
|
+
return;
|
|
33597
|
+
}
|
|
33598
|
+
default:
|
|
33599
|
+
emitError("long-term action must be list, show, add, promote, qualify, approve, archive, or supersede.", asJson);
|
|
33600
|
+
}
|
|
33601
|
+
return;
|
|
33602
|
+
}
|
|
32521
33603
|
default:
|
|
32522
33604
|
console.log("Memorix Memory Commands");
|
|
32523
33605
|
console.log("");
|
|
@@ -32533,6 +33615,13 @@ var init_memory = __esm({
|
|
|
32533
33615
|
console.log(' memorix memory deduplicate [--query "..."] [--dryRun]');
|
|
32534
33616
|
console.log(" memorix memory consolidate [--action preview|execute] [--threshold 0.45]");
|
|
32535
33617
|
console.log(' memorix memory promote --ids 42,43 [--trigger "..."] [--instruction "..."]');
|
|
33618
|
+
console.log(" memorix memory long-term list [--all]");
|
|
33619
|
+
console.log(' memorix memory long-term add --kind semantic --scope user --portability portable --title "..." --text "..." [--tags "..."] [--applicability "..."]');
|
|
33620
|
+
console.log(" memorix memory long-term promote --fromObservation 42 --kind procedural --scope project");
|
|
33621
|
+
console.log(' memorix memory long-term qualify --id <id> --reason "verified against evidence"');
|
|
33622
|
+
console.log(' memorix memory long-term approve --id <id> --reason "reviewed by operator"');
|
|
33623
|
+
console.log(' memorix memory long-term archive --id <id> --reason "no longer current"');
|
|
33624
|
+
console.log(' memorix memory long-term supersede --id <old-id> --superseded-by <qualified-id> --reason "replaced"');
|
|
32536
33625
|
}
|
|
32537
33626
|
} catch (error2) {
|
|
32538
33627
|
emitError(error2 instanceof Error ? error2.message : String(error2), asJson);
|
|
@@ -32543,7 +33632,7 @@ var init_memory = __esm({
|
|
|
32543
33632
|
});
|
|
32544
33633
|
|
|
32545
33634
|
// src/cli/commands/init-shared.ts
|
|
32546
|
-
import
|
|
33635
|
+
import path20 from "path";
|
|
32547
33636
|
function resolveInitScope(args, selectedScope) {
|
|
32548
33637
|
if (args.global && args.project) {
|
|
32549
33638
|
throw new Error("Choose either --global or --project, not both.");
|
|
@@ -32557,7 +33646,7 @@ function resolveInitScope(args, selectedScope) {
|
|
|
32557
33646
|
return selectedScope ?? "global";
|
|
32558
33647
|
}
|
|
32559
33648
|
function getInitTargetDir(scope, cwd, homeDir) {
|
|
32560
|
-
return scope === "global" ?
|
|
33649
|
+
return scope === "global" ? path20.join(homeDir, ".memorix") : cwd;
|
|
32561
33650
|
}
|
|
32562
33651
|
function getInitScopeDescription(scope) {
|
|
32563
33652
|
return scope === "global" ? "Global defaults for all projects on this machine" : "Project-level overrides for the current repository";
|
|
@@ -32567,7 +33656,7 @@ function shouldOfferDotenv(scope) {
|
|
|
32567
33656
|
}
|
|
32568
33657
|
function getEnvTemplateTarget(targetDir, options2) {
|
|
32569
33658
|
const filename = options2.hasDotenvExample ? ".env.memorix-example" : ".env.example";
|
|
32570
|
-
return
|
|
33659
|
+
return path20.join(targetDir, filename);
|
|
32571
33660
|
}
|
|
32572
33661
|
function getInitConfigFilename() {
|
|
32573
33662
|
return "config.toml";
|
|
@@ -32590,7 +33679,7 @@ __export(init_exports, {
|
|
|
32590
33679
|
});
|
|
32591
33680
|
import { existsSync as existsSync11, mkdirSync, writeFileSync } from "fs";
|
|
32592
33681
|
import { homedir as homedir8 } from "os";
|
|
32593
|
-
import
|
|
33682
|
+
import path21 from "path";
|
|
32594
33683
|
function buildInitTomlConfig(options2) {
|
|
32595
33684
|
const isGlobal = options2.scope === "global";
|
|
32596
33685
|
const lines = [
|
|
@@ -32724,8 +33813,8 @@ var init_init = __esm({
|
|
|
32724
33813
|
}
|
|
32725
33814
|
const isGlobal = scope === "global";
|
|
32726
33815
|
const targetDir = getInitTargetDir(scope, process.cwd(), homedir8());
|
|
32727
|
-
const targetPath =
|
|
32728
|
-
const envPath =
|
|
33816
|
+
const targetPath = path21.join(targetDir, isGlobal ? getInitConfigFilename() : getInitProjectConfigFilename());
|
|
33817
|
+
const envPath = path21.join(targetDir, ".env");
|
|
32729
33818
|
v3.info(getInitScopeDescription(scope));
|
|
32730
33819
|
if (existsSync11(targetPath)) {
|
|
32731
33820
|
const overwrite = await me({
|
|
@@ -32829,7 +33918,7 @@ var init_init = __esm({
|
|
|
32829
33918
|
v3.success(`Created ${targetPath}`);
|
|
32830
33919
|
if (shouldOfferDotenv(scope)) {
|
|
32831
33920
|
const envExamplePath = getEnvTemplateTarget(targetDir, {
|
|
32832
|
-
hasDotenvExample: existsSync11(
|
|
33921
|
+
hasDotenvExample: existsSync11(path21.join(targetDir, ".env.example"))
|
|
32833
33922
|
});
|
|
32834
33923
|
const envContent = envLines.join("\n");
|
|
32835
33924
|
if (existsSync11(envExamplePath)) {
|
|
@@ -32845,7 +33934,7 @@ var init_init = __esm({
|
|
|
32845
33934
|
writeFileSync(envExamplePath, envContent, "utf-8");
|
|
32846
33935
|
v3.success(`Created ${envExamplePath}`);
|
|
32847
33936
|
const createEnv = !existsSync11(envPath) ? await me({
|
|
32848
|
-
message: `Create .env from ${
|
|
33937
|
+
message: `Create .env from ${path21.basename(envExamplePath)} now? (you can fill in keys later)`,
|
|
32849
33938
|
initialValue: true
|
|
32850
33939
|
}) : false;
|
|
32851
33940
|
if (!BD(createEnv) && createEnv) {
|
|
@@ -34286,15 +35375,15 @@ __export(audit_exports, {
|
|
|
34286
35375
|
removeFile: () => removeFile,
|
|
34287
35376
|
saveAudit: () => saveAudit
|
|
34288
35377
|
});
|
|
34289
|
-
import * as
|
|
34290
|
-
import * as
|
|
35378
|
+
import * as fs16 from "fs/promises";
|
|
35379
|
+
import * as path22 from "path";
|
|
34291
35380
|
import { homedir as homedir22 } from "os";
|
|
34292
35381
|
function getAuditFilePath() {
|
|
34293
|
-
return process.env.MEMORIX_AUDIT_FILE ||
|
|
35382
|
+
return process.env.MEMORIX_AUDIT_FILE || path22.join(homedir22(), ".memorix", "audit.json");
|
|
34294
35383
|
}
|
|
34295
35384
|
async function loadAudit() {
|
|
34296
35385
|
try {
|
|
34297
|
-
const content = await
|
|
35386
|
+
const content = await fs16.readFile(getAuditFilePath(), "utf-8");
|
|
34298
35387
|
return JSON.parse(content);
|
|
34299
35388
|
} catch {
|
|
34300
35389
|
return {
|
|
@@ -34305,9 +35394,9 @@ async function loadAudit() {
|
|
|
34305
35394
|
}
|
|
34306
35395
|
async function saveAudit(data) {
|
|
34307
35396
|
const auditFile = getAuditFilePath();
|
|
34308
|
-
const dir =
|
|
34309
|
-
await
|
|
34310
|
-
await
|
|
35397
|
+
const dir = path22.dirname(auditFile);
|
|
35398
|
+
await fs16.mkdir(dir, { recursive: true });
|
|
35399
|
+
await fs16.writeFile(auditFile, JSON.stringify(data, null, 2), "utf-8");
|
|
34311
35400
|
}
|
|
34312
35401
|
function getProjectId(projectRoot) {
|
|
34313
35402
|
try {
|
|
@@ -34389,8 +35478,8 @@ __export(installers_exports, {
|
|
|
34389
35478
|
resolveOpenCodeHookCommand: () => resolveOpenCodeHookCommand,
|
|
34390
35479
|
uninstallHooks: () => uninstallHooks
|
|
34391
35480
|
});
|
|
34392
|
-
import * as
|
|
34393
|
-
import * as
|
|
35481
|
+
import * as fs17 from "fs/promises";
|
|
35482
|
+
import * as path23 from "path";
|
|
34394
35483
|
import * as os3 from "os";
|
|
34395
35484
|
import { execSync as execSync2 } from "child_process";
|
|
34396
35485
|
function resolveHookCommand() {
|
|
@@ -34406,7 +35495,7 @@ function resolveWindowsMemorixShim() {
|
|
|
34406
35495
|
stdio: ["ignore", "pipe", "ignore"],
|
|
34407
35496
|
windowsHide: true
|
|
34408
35497
|
}));
|
|
34409
|
-
return output.split(/\r?\n/).map((candidate2) => candidate2.trim()).find((candidate2) =>
|
|
35498
|
+
return output.split(/\r?\n/).map((candidate2) => candidate2.trim()).find((candidate2) => path23.isAbsolute(candidate2)) ?? null;
|
|
34410
35499
|
} catch {
|
|
34411
35500
|
return null;
|
|
34412
35501
|
}
|
|
@@ -34601,9 +35690,9 @@ async function installOfficialSkillsForAgent(agent, projectRoot, global2 = false
|
|
|
34601
35690
|
const root = global2 ? os3.homedir() : projectRoot;
|
|
34602
35691
|
const skillPaths = [];
|
|
34603
35692
|
for (const skillEntry of OFFICIAL_MEMORIX_SKILLS) {
|
|
34604
|
-
const skillPath =
|
|
34605
|
-
await
|
|
34606
|
-
await
|
|
35693
|
+
const skillPath = path23.join(root, relativeDir, skillEntry.name, "SKILL.md");
|
|
35694
|
+
await fs17.mkdir(path23.dirname(skillPath), { recursive: true });
|
|
35695
|
+
await fs17.writeFile(skillPath, skillEntry.content, "utf-8");
|
|
34607
35696
|
skillPaths.push(skillPath);
|
|
34608
35697
|
try {
|
|
34609
35698
|
const { recordFile: recordFile2 } = await Promise.resolve().then(() => (init_audit(), audit_exports));
|
|
@@ -34816,124 +35905,124 @@ async function installOpenCodeSkills(projectRoot, global2 = false) {
|
|
|
34816
35905
|
function getProjectConfigPath(agent, projectRoot) {
|
|
34817
35906
|
switch (agent) {
|
|
34818
35907
|
case "claude":
|
|
34819
|
-
return
|
|
35908
|
+
return path23.join(projectRoot, ".claude", "settings.local.json");
|
|
34820
35909
|
case "copilot":
|
|
34821
|
-
return
|
|
35910
|
+
return path23.join(projectRoot, ".github", "hooks", "memorix.json");
|
|
34822
35911
|
case "windsurf":
|
|
34823
|
-
return
|
|
35912
|
+
return path23.join(projectRoot, ".windsurf", "hooks.json");
|
|
34824
35913
|
case "cursor":
|
|
34825
|
-
return
|
|
35914
|
+
return path23.join(projectRoot, ".cursor", "hooks.json");
|
|
34826
35915
|
case "kiro":
|
|
34827
|
-
return
|
|
35916
|
+
return path23.join(projectRoot, ".kiro", "hooks", "memorix-agent-stop.kiro.hook");
|
|
34828
35917
|
case "codex":
|
|
34829
|
-
return
|
|
35918
|
+
return path23.join(projectRoot, "AGENTS.md");
|
|
34830
35919
|
case "trae":
|
|
34831
|
-
return
|
|
35920
|
+
return path23.join(projectRoot, ".trae", "rules", "project_rules.md");
|
|
34832
35921
|
case "opencode":
|
|
34833
|
-
return
|
|
35922
|
+
return path23.join(projectRoot, ".opencode", "plugins", "memorix.js");
|
|
34834
35923
|
case "pi":
|
|
34835
|
-
return
|
|
35924
|
+
return path23.join(projectRoot, ".pi", "packages", "memorix", "extensions", "memorix.js");
|
|
34836
35925
|
case "openclaw":
|
|
34837
|
-
return
|
|
35926
|
+
return path23.join(os3.homedir(), ".openclaw", "extensions", "memorix", "hooks", "memorix", "HOOK.md");
|
|
34838
35927
|
case "hermes":
|
|
34839
|
-
return
|
|
35928
|
+
return path23.join(os3.homedir(), ".hermes", "plugins", "memorix", "plugin.yaml");
|
|
34840
35929
|
case "omp":
|
|
34841
|
-
return
|
|
35930
|
+
return path23.join(projectRoot, ".omp", "packages", "memorix", "extensions", "memorix.js");
|
|
34842
35931
|
case "antigravity":
|
|
34843
|
-
return
|
|
35932
|
+
return path23.join(projectRoot, ".agents", "hooks.json");
|
|
34844
35933
|
case "gemini-cli":
|
|
34845
|
-
return
|
|
35934
|
+
return path23.join(projectRoot, ".gemini", "settings.json");
|
|
34846
35935
|
default:
|
|
34847
|
-
return
|
|
35936
|
+
return path23.join(projectRoot, ".memorix", "hooks.json");
|
|
34848
35937
|
}
|
|
34849
35938
|
}
|
|
34850
35939
|
function getGlobalConfigPath(agent) {
|
|
34851
35940
|
const home = os3.homedir();
|
|
34852
35941
|
switch (agent) {
|
|
34853
35942
|
case "claude":
|
|
34854
|
-
return
|
|
35943
|
+
return path23.join(home, ".claude", "settings.json");
|
|
34855
35944
|
case "copilot":
|
|
34856
35945
|
return "";
|
|
34857
35946
|
case "windsurf":
|
|
34858
|
-
return
|
|
35947
|
+
return path23.join(home, ".codeium", "windsurf", "hooks.json");
|
|
34859
35948
|
case "cursor":
|
|
34860
|
-
return
|
|
35949
|
+
return path23.join(home, ".cursor", "hooks.json");
|
|
34861
35950
|
case "antigravity":
|
|
34862
|
-
return
|
|
35951
|
+
return path23.join(home, ".gemini", "config", "hooks.json");
|
|
34863
35952
|
case "gemini-cli":
|
|
34864
|
-
return
|
|
35953
|
+
return path23.join(home, ".gemini", "settings.json");
|
|
34865
35954
|
case "opencode":
|
|
34866
|
-
return
|
|
35955
|
+
return path23.join(home, ".config", "opencode", "plugins", "memorix.js");
|
|
34867
35956
|
case "pi":
|
|
34868
|
-
return
|
|
35957
|
+
return path23.join(home, ".pi", "agent", "packages", "memorix", "extensions", "memorix.js");
|
|
34869
35958
|
case "openclaw":
|
|
34870
|
-
return
|
|
35959
|
+
return path23.join(home, ".openclaw", "extensions", "memorix", "hooks", "memorix", "HOOK.md");
|
|
34871
35960
|
case "hermes":
|
|
34872
|
-
return
|
|
35961
|
+
return path23.join(home, ".hermes", "plugins", "memorix", "plugin.yaml");
|
|
34873
35962
|
case "omp":
|
|
34874
|
-
return
|
|
35963
|
+
return path23.join(home, ".omp", "agent", "packages", "memorix", "extensions", "memorix.js");
|
|
34875
35964
|
case "trae":
|
|
34876
|
-
return
|
|
35965
|
+
return path23.join(home, ".trae", "rules", "project_rules.md");
|
|
34877
35966
|
default:
|
|
34878
|
-
return
|
|
35967
|
+
return path23.join(home, ".memorix", "hooks.json");
|
|
34879
35968
|
}
|
|
34880
35969
|
}
|
|
34881
35970
|
function getAgentRulesPath(agent, root, global2 = false) {
|
|
34882
35971
|
if (global2) {
|
|
34883
35972
|
switch (agent) {
|
|
34884
35973
|
case "windsurf":
|
|
34885
|
-
return
|
|
35974
|
+
return path23.join(root, ".codeium", "windsurf", "rules", "memorix.md");
|
|
34886
35975
|
case "cursor":
|
|
34887
|
-
return
|
|
35976
|
+
return path23.join(root, ".cursor", "rules", "memorix.mdc");
|
|
34888
35977
|
case "claude":
|
|
34889
|
-
return
|
|
35978
|
+
return path23.join(root, ".claude", "CLAUDE.md");
|
|
34890
35979
|
case "codex":
|
|
34891
|
-
return
|
|
35980
|
+
return path23.join(root, ".codex", "AGENTS.md");
|
|
34892
35981
|
case "kiro":
|
|
34893
|
-
return
|
|
35982
|
+
return path23.join(root, ".kiro", "steering", "memorix.md");
|
|
34894
35983
|
case "opencode":
|
|
34895
|
-
return
|
|
35984
|
+
return path23.join(root, ".config", "opencode", "AGENTS.md");
|
|
34896
35985
|
case "antigravity":
|
|
34897
35986
|
case "gemini-cli":
|
|
34898
|
-
return
|
|
35987
|
+
return path23.join(root, ".gemini", "GEMINI.md");
|
|
34899
35988
|
case "trae":
|
|
34900
|
-
return
|
|
35989
|
+
return path23.join(root, ".trae", "rules", "project_rules.md");
|
|
34901
35990
|
default:
|
|
34902
|
-
return
|
|
35991
|
+
return path23.join(root, ".agent", "rules", "memorix.md");
|
|
34903
35992
|
}
|
|
34904
35993
|
}
|
|
34905
35994
|
switch (agent) {
|
|
34906
35995
|
case "windsurf":
|
|
34907
|
-
return
|
|
35996
|
+
return path23.join(root, ".windsurf", "rules", "memorix.md");
|
|
34908
35997
|
case "cursor":
|
|
34909
|
-
return
|
|
35998
|
+
return path23.join(root, ".cursor", "rules", "memorix.mdc");
|
|
34910
35999
|
case "claude":
|
|
34911
|
-
return
|
|
36000
|
+
return path23.join(root, "CLAUDE.md");
|
|
34912
36001
|
case "copilot":
|
|
34913
|
-
return
|
|
36002
|
+
return path23.join(root, ".github", "copilot-instructions.md");
|
|
34914
36003
|
case "codex":
|
|
34915
|
-
return
|
|
36004
|
+
return path23.join(root, "AGENTS.md");
|
|
34916
36005
|
case "kiro":
|
|
34917
|
-
return
|
|
36006
|
+
return path23.join(root, ".kiro", "steering", "memorix.md");
|
|
34918
36007
|
case "opencode":
|
|
34919
|
-
return
|
|
36008
|
+
return path23.join(root, "AGENTS.md");
|
|
34920
36009
|
case "antigravity":
|
|
34921
36010
|
case "gemini-cli":
|
|
34922
|
-
return
|
|
36011
|
+
return path23.join(root, "GEMINI.md");
|
|
34923
36012
|
case "trae":
|
|
34924
|
-
return
|
|
36013
|
+
return path23.join(root, ".trae", "rules", "project_rules.md");
|
|
34925
36014
|
default:
|
|
34926
|
-
return
|
|
36015
|
+
return path23.join(root, ".agent", "rules", "memorix.md");
|
|
34927
36016
|
}
|
|
34928
36017
|
}
|
|
34929
36018
|
async function detectCopilotExtension(home) {
|
|
34930
36019
|
const extDirs = [
|
|
34931
|
-
|
|
34932
|
-
|
|
36020
|
+
path23.join(home, ".vscode", "extensions"),
|
|
36021
|
+
path23.join(home, ".vscode-insiders", "extensions")
|
|
34933
36022
|
];
|
|
34934
36023
|
for (const extDir of extDirs) {
|
|
34935
36024
|
try {
|
|
34936
|
-
const entries = await
|
|
36025
|
+
const entries = await fs17.readdir(extDir);
|
|
34937
36026
|
if (entries.some((e3) => e3.startsWith("github.copilot-"))) {
|
|
34938
36027
|
return true;
|
|
34939
36028
|
}
|
|
@@ -34945,21 +36034,21 @@ async function detectCopilotExtension(home) {
|
|
|
34945
36034
|
async function detectInstalledAgents() {
|
|
34946
36035
|
const agents = [];
|
|
34947
36036
|
const home = os3.homedir();
|
|
34948
|
-
const claudeDir =
|
|
36037
|
+
const claudeDir = path23.join(home, ".claude");
|
|
34949
36038
|
try {
|
|
34950
|
-
await
|
|
36039
|
+
await fs17.access(claudeDir);
|
|
34951
36040
|
agents.push("claude");
|
|
34952
36041
|
} catch {
|
|
34953
36042
|
}
|
|
34954
|
-
const windsurfDir =
|
|
36043
|
+
const windsurfDir = path23.join(home, ".codeium", "windsurf");
|
|
34955
36044
|
try {
|
|
34956
|
-
await
|
|
36045
|
+
await fs17.access(windsurfDir);
|
|
34957
36046
|
agents.push("windsurf");
|
|
34958
36047
|
} catch {
|
|
34959
36048
|
}
|
|
34960
|
-
const cursorDir =
|
|
36049
|
+
const cursorDir = path23.join(home, ".cursor");
|
|
34961
36050
|
try {
|
|
34962
|
-
await
|
|
36051
|
+
await fs17.access(cursorDir);
|
|
34963
36052
|
agents.push("cursor");
|
|
34964
36053
|
} catch {
|
|
34965
36054
|
}
|
|
@@ -34967,21 +36056,21 @@ async function detectInstalledAgents() {
|
|
|
34967
36056
|
if (copilotDetected) {
|
|
34968
36057
|
agents.push("copilot");
|
|
34969
36058
|
}
|
|
34970
|
-
const kiroConfig =
|
|
36059
|
+
const kiroConfig = path23.join(home, ".kiro");
|
|
34971
36060
|
try {
|
|
34972
|
-
await
|
|
36061
|
+
await fs17.access(kiroConfig);
|
|
34973
36062
|
agents.push("kiro");
|
|
34974
36063
|
} catch {
|
|
34975
36064
|
}
|
|
34976
|
-
const codexDir =
|
|
36065
|
+
const codexDir = path23.join(home, ".codex");
|
|
34977
36066
|
try {
|
|
34978
|
-
await
|
|
36067
|
+
await fs17.access(codexDir);
|
|
34979
36068
|
agents.push("codex");
|
|
34980
36069
|
} catch {
|
|
34981
36070
|
}
|
|
34982
|
-
const antigravityDir =
|
|
36071
|
+
const antigravityDir = path23.join(home, ".gemini", "config");
|
|
34983
36072
|
try {
|
|
34984
|
-
await
|
|
36073
|
+
await fs17.access(antigravityDir);
|
|
34985
36074
|
agents.push("antigravity");
|
|
34986
36075
|
} catch {
|
|
34987
36076
|
}
|
|
@@ -34992,15 +36081,15 @@ async function detectInstalledAgents() {
|
|
|
34992
36081
|
agents.push("gemini-cli");
|
|
34993
36082
|
} catch {
|
|
34994
36083
|
}
|
|
34995
|
-
const opencodeDir =
|
|
36084
|
+
const opencodeDir = path23.join(home, ".config", "opencode");
|
|
34996
36085
|
try {
|
|
34997
|
-
await
|
|
36086
|
+
await fs17.access(opencodeDir);
|
|
34998
36087
|
agents.push("opencode");
|
|
34999
36088
|
} catch {
|
|
35000
36089
|
}
|
|
35001
|
-
const traeDir =
|
|
36090
|
+
const traeDir = path23.join(home, ".trae");
|
|
35002
36091
|
try {
|
|
35003
|
-
await
|
|
36092
|
+
await fs17.access(traeDir);
|
|
35004
36093
|
agents.push("trae");
|
|
35005
36094
|
} catch {
|
|
35006
36095
|
}
|
|
@@ -35034,7 +36123,7 @@ async function installHooks(agent, projectRoot, global2 = false) {
|
|
|
35034
36123
|
try {
|
|
35035
36124
|
const { access: access3, unlink: unlink2 } = await import("fs/promises");
|
|
35036
36125
|
await access3(entry.path);
|
|
35037
|
-
const basename5 =
|
|
36126
|
+
const basename5 = path23.basename(entry.path);
|
|
35038
36127
|
if (basename5 === "AGENTS.md" || basename5 === "GEMINI.md" || basename5 === "CONTEXT.md") {
|
|
35039
36128
|
continue;
|
|
35040
36129
|
}
|
|
@@ -35089,8 +36178,8 @@ async function installHooks(agent, projectRoot, global2 = false) {
|
|
|
35089
36178
|
case "opencode": {
|
|
35090
36179
|
const pluginContent = generateOpenCodePlugin();
|
|
35091
36180
|
const pluginPath = global2 ? getGlobalConfigPath(agent) : getProjectConfigPath(agent, projectRoot);
|
|
35092
|
-
await
|
|
35093
|
-
await
|
|
36181
|
+
await fs17.mkdir(path23.dirname(pluginPath), { recursive: true });
|
|
36182
|
+
await fs17.writeFile(pluginPath, pluginContent, "utf-8");
|
|
35094
36183
|
try {
|
|
35095
36184
|
const { recordFile: recordFile2 } = await Promise.resolve().then(() => (init_audit(), audit_exports));
|
|
35096
36185
|
await recordFile2(projectRoot, "hook", pluginPath, agent);
|
|
@@ -35119,14 +36208,14 @@ async function installHooks(agent, projectRoot, global2 = false) {
|
|
|
35119
36208
|
default:
|
|
35120
36209
|
generated = generateClaudeConfig();
|
|
35121
36210
|
}
|
|
35122
|
-
await
|
|
36211
|
+
await fs17.mkdir(path23.dirname(configPath), { recursive: true });
|
|
35123
36212
|
if (agent === "kiro") {
|
|
35124
36213
|
const hookFiles = generateKiroHookFiles();
|
|
35125
|
-
const hooksDir =
|
|
35126
|
-
await
|
|
36214
|
+
const hooksDir = path23.join(path23.dirname(configPath));
|
|
36215
|
+
await fs17.mkdir(hooksDir, { recursive: true });
|
|
35127
36216
|
for (const hf of hookFiles) {
|
|
35128
|
-
const hookPath =
|
|
35129
|
-
await
|
|
36217
|
+
const hookPath = path23.join(hooksDir, hf.filename);
|
|
36218
|
+
await fs17.writeFile(hookPath, hf.content, "utf-8");
|
|
35130
36219
|
try {
|
|
35131
36220
|
const { recordFile: recordFile2 } = await Promise.resolve().then(() => (init_audit(), audit_exports));
|
|
35132
36221
|
await recordFile2(projectRoot, "hook", hookPath, agent);
|
|
@@ -35136,7 +36225,7 @@ async function installHooks(agent, projectRoot, global2 = false) {
|
|
|
35136
36225
|
} else {
|
|
35137
36226
|
let existing = {};
|
|
35138
36227
|
try {
|
|
35139
|
-
const content = await
|
|
36228
|
+
const content = await fs17.readFile(configPath, "utf-8");
|
|
35140
36229
|
existing = JSON.parse(content);
|
|
35141
36230
|
} catch {
|
|
35142
36231
|
}
|
|
@@ -35171,7 +36260,7 @@ async function installHooks(agent, projectRoot, global2 = false) {
|
|
|
35171
36260
|
const h3 = merged.hooks;
|
|
35172
36261
|
if (h3) delete h3.preToolUse;
|
|
35173
36262
|
}
|
|
35174
|
-
await
|
|
36263
|
+
await fs17.writeFile(configPath, JSON.stringify(merged, null, 2), "utf-8");
|
|
35175
36264
|
try {
|
|
35176
36265
|
const { recordFile: recordFile2 } = await Promise.resolve().then(() => (init_audit(), audit_exports));
|
|
35177
36266
|
await recordFile2(projectRoot, "hook", configPath, agent);
|
|
@@ -35219,18 +36308,18 @@ async function installAgentRules(agent, projectRoot, global2 = false) {
|
|
|
35219
36308
|
const rulesRoot = global2 ? os3.homedir() : projectRoot;
|
|
35220
36309
|
const rulesPath = getAgentRulesPath(agent, rulesRoot, global2);
|
|
35221
36310
|
try {
|
|
35222
|
-
await
|
|
36311
|
+
await fs17.mkdir(path23.dirname(rulesPath), { recursive: true });
|
|
35223
36312
|
if (agent === "claude" || agent === "codex" || agent === "opencode" || agent === "antigravity" || agent === "gemini-cli") {
|
|
35224
36313
|
try {
|
|
35225
|
-
const existing = await
|
|
35226
|
-
await
|
|
36314
|
+
const existing = await fs17.readFile(rulesPath, "utf-8");
|
|
36315
|
+
await fs17.writeFile(rulesPath, mergeMemorixRulesContent(existing, rulesContent), "utf-8");
|
|
35227
36316
|
try {
|
|
35228
36317
|
const { recordFile: recordFile2 } = await Promise.resolve().then(() => (init_audit(), audit_exports));
|
|
35229
36318
|
await recordFile2(projectRoot, "rule", rulesPath, agent);
|
|
35230
36319
|
} catch {
|
|
35231
36320
|
}
|
|
35232
36321
|
} catch {
|
|
35233
|
-
await
|
|
36322
|
+
await fs17.writeFile(rulesPath, rulesContent, "utf-8");
|
|
35234
36323
|
try {
|
|
35235
36324
|
const { recordFile: recordFile2 } = await Promise.resolve().then(() => (init_audit(), audit_exports));
|
|
35236
36325
|
await recordFile2(projectRoot, "rule", rulesPath, agent);
|
|
@@ -35239,9 +36328,9 @@ async function installAgentRules(agent, projectRoot, global2 = false) {
|
|
|
35239
36328
|
}
|
|
35240
36329
|
} else {
|
|
35241
36330
|
try {
|
|
35242
|
-
await
|
|
36331
|
+
await fs17.access(rulesPath);
|
|
35243
36332
|
} catch {
|
|
35244
|
-
await
|
|
36333
|
+
await fs17.writeFile(rulesPath, rulesContent, "utf-8");
|
|
35245
36334
|
try {
|
|
35246
36335
|
const { recordFile: recordFile2 } = await Promise.resolve().then(() => (init_audit(), audit_exports));
|
|
35247
36336
|
await recordFile2(projectRoot, "rule", rulesPath, agent);
|
|
@@ -35331,6 +36420,8 @@ alwaysApply: true
|
|
|
35331
36420
|
"- Include `filesModified` when relevant",
|
|
35332
36421
|
"- Use `topicKey` for topics that evolve over time (prevents duplicates)",
|
|
35333
36422
|
'- For "why" decisions, use `memorix_store_reasoning`',
|
|
36423
|
+
'- For a stable fact, reusable procedure, or completed episode that merits deliberate long-term review, include `longTerm` in `memorix_store` with the appropriate kind and normally `scope: "project"`. It creates a candidate only: do not use it for routine updates, do not make project-derived evidence portable user memory, and do not assume it enters context until an operator qualifies and approves it through `memorix memory long-term`.',
|
|
36424
|
+
"- A `user` + `portable` durable memory delivered in a task brief is intentionally available across projects. When it matches the task, use it as reusable background even if its origin differs; do not treat it as a current-project fact. Expand it only when needed with `memorix_detail` using its `durable:<id>` reference and a specific purpose.",
|
|
35334
36425
|
"",
|
|
35335
36426
|
"**Don't store:** greetings, simple file reads, trivial commands (ls, pwd, git status).",
|
|
35336
36427
|
"",
|
|
@@ -35367,16 +36458,16 @@ async function uninstallHooks(agent, projectRoot, global2 = false) {
|
|
|
35367
36458
|
let success = false;
|
|
35368
36459
|
try {
|
|
35369
36460
|
if (agent === "kiro" || agent === "opencode") {
|
|
35370
|
-
await
|
|
36461
|
+
await fs17.unlink(configPath);
|
|
35371
36462
|
success = true;
|
|
35372
36463
|
} else {
|
|
35373
|
-
const content = await
|
|
36464
|
+
const content = await fs17.readFile(configPath, "utf-8");
|
|
35374
36465
|
const config2 = JSON.parse(content);
|
|
35375
36466
|
delete config2.hooks;
|
|
35376
36467
|
if (Object.keys(config2).length === 0) {
|
|
35377
|
-
await
|
|
36468
|
+
await fs17.unlink(configPath);
|
|
35378
36469
|
} else {
|
|
35379
|
-
await
|
|
36470
|
+
await fs17.writeFile(configPath, JSON.stringify(config2, null, 2), "utf-8");
|
|
35380
36471
|
}
|
|
35381
36472
|
success = true;
|
|
35382
36473
|
}
|
|
@@ -35389,10 +36480,10 @@ async function uninstallHooks(agent, projectRoot, global2 = false) {
|
|
|
35389
36480
|
const agentFiles = prevFiles.filter((e3) => e3.agent === agent);
|
|
35390
36481
|
for (const entry of agentFiles) {
|
|
35391
36482
|
try {
|
|
35392
|
-
const basename5 =
|
|
36483
|
+
const basename5 = path23.basename(entry.path);
|
|
35393
36484
|
if (basename5 === "AGENTS.md" || basename5 === "GEMINI.md" || basename5 === "CONTEXT.md") {
|
|
35394
36485
|
try {
|
|
35395
|
-
const content = await
|
|
36486
|
+
const content = await fs17.readFile(entry.path, "utf-8");
|
|
35396
36487
|
const memorixStart = content.indexOf("# Memorix");
|
|
35397
36488
|
if (memorixStart >= 0) {
|
|
35398
36489
|
const afterMemorix = content.substring(memorixStart);
|
|
@@ -35404,9 +36495,9 @@ async function uninstallHooks(agent, projectRoot, global2 = false) {
|
|
|
35404
36495
|
}
|
|
35405
36496
|
const cleaned = (before + "\n" + after).trim();
|
|
35406
36497
|
if (cleaned.length === 0) {
|
|
35407
|
-
await
|
|
36498
|
+
await fs17.unlink(entry.path);
|
|
35408
36499
|
} else {
|
|
35409
|
-
await
|
|
36500
|
+
await fs17.writeFile(entry.path, cleaned + "\n", "utf-8");
|
|
35410
36501
|
}
|
|
35411
36502
|
}
|
|
35412
36503
|
} catch {
|
|
@@ -35415,7 +36506,7 @@ async function uninstallHooks(agent, projectRoot, global2 = false) {
|
|
|
35415
36506
|
auditCleaned = true;
|
|
35416
36507
|
continue;
|
|
35417
36508
|
}
|
|
35418
|
-
await
|
|
36509
|
+
await fs17.unlink(entry.path);
|
|
35419
36510
|
await removeFile2(projectRoot, entry.path);
|
|
35420
36511
|
auditCleaned = true;
|
|
35421
36512
|
} catch {
|
|
@@ -35427,14 +36518,14 @@ async function uninstallHooks(agent, projectRoot, global2 = false) {
|
|
|
35427
36518
|
if (success) {
|
|
35428
36519
|
try {
|
|
35429
36520
|
const { rm: rm2 } = await import("fs/promises");
|
|
35430
|
-
const dir =
|
|
36521
|
+
const dir = path23.dirname(configPath);
|
|
35431
36522
|
let current = dir;
|
|
35432
36523
|
for (let i2 = 0; i2 < 3; i2++) {
|
|
35433
36524
|
try {
|
|
35434
|
-
const entries = await
|
|
36525
|
+
const entries = await fs17.readdir(current);
|
|
35435
36526
|
if (entries.length === 0) {
|
|
35436
36527
|
await rm2(current, { recursive: true });
|
|
35437
|
-
current =
|
|
36528
|
+
current = path23.dirname(current);
|
|
35438
36529
|
} else {
|
|
35439
36530
|
break;
|
|
35440
36531
|
}
|
|
@@ -35458,12 +36549,12 @@ async function getHookStatus(projectRoot) {
|
|
|
35458
36549
|
let usedPath = projectPath;
|
|
35459
36550
|
const verifiedByDefault = agent !== "opencode" && agent !== "pi";
|
|
35460
36551
|
try {
|
|
35461
|
-
await
|
|
36552
|
+
await fs17.access(projectPath);
|
|
35462
36553
|
installed = true;
|
|
35463
36554
|
} catch {
|
|
35464
36555
|
if (globalPath) {
|
|
35465
36556
|
try {
|
|
35466
|
-
await
|
|
36557
|
+
await fs17.access(globalPath);
|
|
35467
36558
|
installed = true;
|
|
35468
36559
|
usedPath = globalPath;
|
|
35469
36560
|
} catch {
|
|
@@ -35472,7 +36563,7 @@ async function getHookStatus(projectRoot) {
|
|
|
35472
36563
|
}
|
|
35473
36564
|
if (installed && agent === "opencode") {
|
|
35474
36565
|
try {
|
|
35475
|
-
const content = await
|
|
36566
|
+
const content = await fs17.readFile(usedPath, "utf-8");
|
|
35476
36567
|
const match = content.match(/@generated-version\s+(\d+)/);
|
|
35477
36568
|
const installedVersion = match ? parseInt(match[1], 10) : 0;
|
|
35478
36569
|
outdated = installedVersion < OPENCODE_PLUGIN_VERSION;
|
|
@@ -35503,11 +36594,11 @@ var init_installers = __esm({
|
|
|
35503
36594
|
init_official_skills();
|
|
35504
36595
|
OPENCODE_PLUGIN_VERSION = 7;
|
|
35505
36596
|
AGENT_SKILL_DIRS = {
|
|
35506
|
-
cursor: { project:
|
|
35507
|
-
windsurf: { project:
|
|
35508
|
-
kiro: { project:
|
|
35509
|
-
opencode: { project:
|
|
35510
|
-
trae: { project:
|
|
36597
|
+
cursor: { project: path23.join(".cursor", "skills"), global: path23.join(".cursor", "skills") },
|
|
36598
|
+
windsurf: { project: path23.join(".windsurf", "skills"), global: path23.join(".windsurf", "skills") },
|
|
36599
|
+
kiro: { project: path23.join(".kiro", "skills"), global: path23.join(".kiro", "skills") },
|
|
36600
|
+
opencode: { project: path23.join(".opencode", "skills"), global: path23.join(".config", "opencode", "skills") },
|
|
36601
|
+
trae: { project: path23.join(".trae", "skills"), global: path23.join(".trae", "skills") }
|
|
35511
36602
|
};
|
|
35512
36603
|
PACKAGE_OWNED_HOOK_AGENTS = /* @__PURE__ */ new Set(["openclaw", "hermes", "omp"]);
|
|
35513
36604
|
}
|
|
@@ -35541,7 +36632,7 @@ import { existsSync as existsSync12 } from "fs";
|
|
|
35541
36632
|
import { copyFile, mkdir as mkdir5, readFile as readFile5, readdir as readdir2, rm, writeFile as writeFile5 } from "fs/promises";
|
|
35542
36633
|
import { createRequire as createRequire5 } from "module";
|
|
35543
36634
|
import { homedir as homedir24 } from "os";
|
|
35544
|
-
import
|
|
36635
|
+
import path24 from "path";
|
|
35545
36636
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
35546
36637
|
function getSetupAgentTargets() {
|
|
35547
36638
|
return [...SUPPORTED_SETUP_AGENTS];
|
|
@@ -35578,13 +36669,13 @@ function buildSetupPlan(options2) {
|
|
|
35578
36669
|
if (!isPackageOwnedAgent && includeHooks) actions.push("hooks");
|
|
35579
36670
|
return { agent: options2.agent, mcp, actions, includeHooks, includeRules, includePlugin: wantsPlugin };
|
|
35580
36671
|
}
|
|
35581
|
-
function findPackageRoot(start =
|
|
36672
|
+
function findPackageRoot(start = path24.dirname(fileURLToPath5(import.meta.url))) {
|
|
35582
36673
|
let dir = start;
|
|
35583
36674
|
for (let i2 = 0; i2 < 8; i2++) {
|
|
35584
|
-
if (existsSync12(
|
|
36675
|
+
if (existsSync12(path24.join(dir, "package.json")) && existsSync12(path24.join(dir, "plugins"))) {
|
|
35585
36676
|
return dir;
|
|
35586
36677
|
}
|
|
35587
|
-
const parent =
|
|
36678
|
+
const parent = path24.dirname(dir);
|
|
35588
36679
|
if (parent === dir) break;
|
|
35589
36680
|
dir = parent;
|
|
35590
36681
|
}
|
|
@@ -35595,12 +36686,12 @@ async function copyDir(source, destination) {
|
|
|
35595
36686
|
await mkdir5(destination, { recursive: true });
|
|
35596
36687
|
const entries = await readdir2(source, { withFileTypes: true });
|
|
35597
36688
|
for (const entry of entries) {
|
|
35598
|
-
const src2 =
|
|
35599
|
-
const dest =
|
|
36689
|
+
const src2 = path24.join(source, entry.name);
|
|
36690
|
+
const dest = path24.join(destination, entry.name);
|
|
35600
36691
|
if (entry.isDirectory()) {
|
|
35601
36692
|
await copyDir(src2, dest);
|
|
35602
36693
|
} else {
|
|
35603
|
-
await mkdir5(
|
|
36694
|
+
await mkdir5(path24.dirname(dest), { recursive: true });
|
|
35604
36695
|
await copyFile(src2, dest);
|
|
35605
36696
|
}
|
|
35606
36697
|
}
|
|
@@ -35608,16 +36699,16 @@ async function copyDir(source, destination) {
|
|
|
35608
36699
|
async function writeOfficialSkills(skillsRoot) {
|
|
35609
36700
|
const written = [];
|
|
35610
36701
|
for (const skill2 of OFFICIAL_MEMORIX_SKILLS) {
|
|
35611
|
-
const skillPath =
|
|
35612
|
-
await mkdir5(
|
|
36702
|
+
const skillPath = path24.join(skillsRoot, skill2.name, "SKILL.md");
|
|
36703
|
+
await mkdir5(path24.dirname(skillPath), { recursive: true });
|
|
35613
36704
|
await writeFile5(skillPath, skill2.content, "utf-8");
|
|
35614
36705
|
written.push(skillPath);
|
|
35615
36706
|
}
|
|
35616
36707
|
return written;
|
|
35617
36708
|
}
|
|
35618
36709
|
async function stripHookCaptureFromPlugin(pluginPath, agent) {
|
|
35619
|
-
await rm(
|
|
35620
|
-
const manifestPath = agent === "claude" ?
|
|
36710
|
+
await rm(path24.join(pluginPath, "hooks"), { recursive: true, force: true });
|
|
36711
|
+
const manifestPath = agent === "claude" ? path24.join(pluginPath, ".claude-plugin", "plugin.json") : agent === "codex" ? path24.join(pluginPath, ".codex-plugin", "plugin.json") : path24.join(pluginPath, "plugin.json");
|
|
35621
36712
|
try {
|
|
35622
36713
|
const manifest = JSON.parse(await readFile5(manifestPath, "utf-8"));
|
|
35623
36714
|
delete manifest.hooks;
|
|
@@ -35633,7 +36724,7 @@ async function stripHookCaptureFromPlugin(pluginPath, agent) {
|
|
|
35633
36724
|
}
|
|
35634
36725
|
}
|
|
35635
36726
|
async function stampCodexPluginVersion(pluginPath) {
|
|
35636
|
-
const manifestPath =
|
|
36727
|
+
const manifestPath = path24.join(pluginPath, ".codex-plugin", "plugin.json");
|
|
35637
36728
|
const manifest = JSON.parse(await readFile5(manifestPath, "utf-8"));
|
|
35638
36729
|
if (manifest.name !== "memorix") {
|
|
35639
36730
|
throw new Error(`Unexpected Codex plugin manifest at ${manifestPath}`);
|
|
@@ -35643,8 +36734,8 @@ async function stampCodexPluginVersion(pluginPath) {
|
|
|
35643
36734
|
`, "utf-8");
|
|
35644
36735
|
}
|
|
35645
36736
|
async function stripHookCaptureFromOpenClawBundle(bundlePath) {
|
|
35646
|
-
await rm(
|
|
35647
|
-
const manifestPath =
|
|
36737
|
+
await rm(path24.join(bundlePath, "hooks"), { recursive: true, force: true });
|
|
36738
|
+
const manifestPath = path24.join(bundlePath, ".codex-plugin", "plugin.json");
|
|
35648
36739
|
try {
|
|
35649
36740
|
const manifest = JSON.parse(await readFile5(manifestPath, "utf-8"));
|
|
35650
36741
|
delete manifest.hooks;
|
|
@@ -35680,7 +36771,7 @@ function mergeHermesPluginEnabled(existingContent, pluginName) {
|
|
|
35680
36771
|
}, { lineWidth: -1 });
|
|
35681
36772
|
}
|
|
35682
36773
|
function relativePosix(from, to) {
|
|
35683
|
-
let rel =
|
|
36774
|
+
let rel = path24.relative(from, to).replace(/\\/g, "/");
|
|
35684
36775
|
if (!rel.startsWith("./") && !rel.startsWith("../")) rel = `./${rel}`;
|
|
35685
36776
|
return rel;
|
|
35686
36777
|
}
|
|
@@ -35818,7 +36909,7 @@ function isOwnedLegacyCodexMcp(content) {
|
|
|
35818
36909
|
const server = new CodexMCPAdapter().parse(content).find((entry) => entry.name === "memorix");
|
|
35819
36910
|
return Boolean(server && isLegacyCodexMemorixNodeServer(server));
|
|
35820
36911
|
}
|
|
35821
|
-
async function removeLegacyCodexMemorixMcpConfig(configPath =
|
|
36912
|
+
async function removeLegacyCodexMemorixMcpConfig(configPath = path24.join(homedir24(), ".codex", "config.toml")) {
|
|
35822
36913
|
let existingContent;
|
|
35823
36914
|
try {
|
|
35824
36915
|
existingContent = await readFile5(configPath, "utf-8");
|
|
@@ -35858,12 +36949,12 @@ function isOwnedLegacyCodexHooks(content) {
|
|
|
35858
36949
|
}
|
|
35859
36950
|
}
|
|
35860
36951
|
async function removeOwnedLegacyCodexPluginFolder(homeDir) {
|
|
35861
|
-
const canonicalPath =
|
|
35862
|
-
const legacyPath =
|
|
36952
|
+
const canonicalPath = path24.join(homeDir, "plugins", "memorix");
|
|
36953
|
+
const legacyPath = path24.join(homeDir, ".codex", "plugins", "memorix");
|
|
35863
36954
|
if (!existsSync12(legacyPath)) return "missing";
|
|
35864
36955
|
if (!existsSync12(canonicalPath)) return "preserved";
|
|
35865
36956
|
try {
|
|
35866
|
-
const manifest = JSON.parse(await readFile5(
|
|
36957
|
+
const manifest = JSON.parse(await readFile5(path24.join(legacyPath, ".codex-plugin", "plugin.json"), "utf-8"));
|
|
35867
36958
|
const repository = String(manifest.repository ?? "");
|
|
35868
36959
|
if (manifest.name !== "memorix" || !repository.includes("github.com/AVIDS2/memorix")) return "preserved";
|
|
35869
36960
|
await rm(legacyPath, { recursive: true, force: true });
|
|
@@ -35875,7 +36966,7 @@ async function removeOwnedLegacyCodexPluginFolder(homeDir) {
|
|
|
35875
36966
|
async function migrateLegacyCodexIntegration(options2 = {}) {
|
|
35876
36967
|
const homeDir = options2.homeDir ?? homedir24();
|
|
35877
36968
|
const projectRoot = options2.projectRoot ?? process.cwd();
|
|
35878
|
-
const configPath =
|
|
36969
|
+
const configPath = path24.join(homeDir, ".codex", "config.toml");
|
|
35879
36970
|
let mcp = "missing";
|
|
35880
36971
|
try {
|
|
35881
36972
|
const content = await readFile5(configPath, "utf-8");
|
|
@@ -35885,7 +36976,7 @@ async function migrateLegacyCodexIntegration(options2 = {}) {
|
|
|
35885
36976
|
} catch {
|
|
35886
36977
|
mcp = "missing";
|
|
35887
36978
|
}
|
|
35888
|
-
const hooksPath =
|
|
36979
|
+
const hooksPath = path24.join(projectRoot, ".codex", "hooks.json");
|
|
35889
36980
|
let projectHooks = "missing";
|
|
35890
36981
|
try {
|
|
35891
36982
|
const content = await readFile5(hooksPath, "utf-8");
|
|
@@ -35945,12 +37036,12 @@ async function installMcpConfig(options2) {
|
|
|
35945
37036
|
}
|
|
35946
37037
|
const generated = adapter.generate([server]);
|
|
35947
37038
|
const content = options2.agent === "codex" ? mergeTomlMcpConfig(existingContent, generated) : options2.agent === "hermes" ? mergeYamlMcpConfig(existingContent, generated) : mergeJsonMcpConfig(existingContent, generated);
|
|
35948
|
-
await mkdir5(
|
|
37039
|
+
await mkdir5(path24.dirname(configPath), { recursive: true });
|
|
35949
37040
|
await writeFile5(configPath, content, "utf-8");
|
|
35950
37041
|
return { agent: options2.agent, configPath, transport: options2.mcp };
|
|
35951
37042
|
}
|
|
35952
37043
|
async function upsertCodexMarketplace(marketplacePath, pluginPath) {
|
|
35953
|
-
await mkdir5(
|
|
37044
|
+
await mkdir5(path24.dirname(marketplacePath), { recursive: true });
|
|
35954
37045
|
let catalog;
|
|
35955
37046
|
try {
|
|
35956
37047
|
catalog = JSON.parse(await readFile5(marketplacePath, "utf-8"));
|
|
@@ -35963,9 +37054,9 @@ async function upsertCodexMarketplace(marketplacePath, pluginPath) {
|
|
|
35963
37054
|
plugins: []
|
|
35964
37055
|
};
|
|
35965
37056
|
}
|
|
35966
|
-
const marketplaceDir =
|
|
35967
|
-
const agentsDir =
|
|
35968
|
-
const marketplaceRoot =
|
|
37057
|
+
const marketplaceDir = path24.dirname(marketplacePath);
|
|
37058
|
+
const agentsDir = path24.dirname(marketplaceDir);
|
|
37059
|
+
const marketplaceRoot = path24.basename(agentsDir) === ".agents" ? path24.dirname(agentsDir) : marketplaceDir;
|
|
35969
37060
|
const sourcePath = relativePosix(marketplaceRoot, pluginPath);
|
|
35970
37061
|
const entry = {
|
|
35971
37062
|
name: "memorix",
|
|
@@ -35988,7 +37079,7 @@ async function upsertCodexMarketplace(marketplacePath, pluginPath) {
|
|
|
35988
37079
|
await writeFile5(marketplacePath, JSON.stringify(catalog, null, 2) + "\n", "utf-8");
|
|
35989
37080
|
}
|
|
35990
37081
|
async function writeClaudeMarketplace(marketplacePath) {
|
|
35991
|
-
await mkdir5(
|
|
37082
|
+
await mkdir5(path24.dirname(marketplacePath), { recursive: true });
|
|
35992
37083
|
const catalog = {
|
|
35993
37084
|
$schema: "https://anthropic.com/claude-code/marketplace.schema.json",
|
|
35994
37085
|
name: "memorix-local",
|
|
@@ -36017,18 +37108,18 @@ async function writeClaudeMarketplace(marketplacePath) {
|
|
|
36017
37108
|
async function installPluginPackage(options2) {
|
|
36018
37109
|
const home = options2.homeDir ?? homedir24();
|
|
36019
37110
|
const packageRoot = findPackageRoot();
|
|
36020
|
-
const source =
|
|
37111
|
+
const source = path24.join(packageRoot, "plugins", options2.agent, "memorix");
|
|
36021
37112
|
const includeHooks = options2.includeHooks ?? true;
|
|
36022
37113
|
if (!existsSync12(source)) {
|
|
36023
37114
|
throw new Error(`Plugin package template not found: ${source}`);
|
|
36024
37115
|
}
|
|
36025
37116
|
if (options2.agent === "codex") {
|
|
36026
|
-
const pluginPath2 =
|
|
36027
|
-
const marketplacePath2 =
|
|
37117
|
+
const pluginPath2 = path24.join(home, "plugins", "memorix");
|
|
37118
|
+
const marketplacePath2 = path24.join(home, ".agents", "plugins", "marketplace.json");
|
|
36028
37119
|
await copyDir(source, pluginPath2);
|
|
36029
37120
|
await stampCodexPluginVersion(pluginPath2);
|
|
36030
37121
|
if (!includeHooks) await stripHookCaptureFromPlugin(pluginPath2, "codex");
|
|
36031
|
-
await writeOfficialSkills(
|
|
37122
|
+
await writeOfficialSkills(path24.join(pluginPath2, "skills"));
|
|
36032
37123
|
await upsertCodexMarketplace(marketplacePath2, pluginPath2);
|
|
36033
37124
|
return {
|
|
36034
37125
|
agent: "codex",
|
|
@@ -36038,22 +37129,22 @@ async function installPluginPackage(options2) {
|
|
|
36038
37129
|
};
|
|
36039
37130
|
}
|
|
36040
37131
|
if (options2.agent === "copilot") {
|
|
36041
|
-
const pluginPath2 =
|
|
37132
|
+
const pluginPath2 = path24.join(home, ".copilot", "plugins", "local", "memorix");
|
|
36042
37133
|
await copyDir(source, pluginPath2);
|
|
36043
37134
|
if (!includeHooks) await stripHookCaptureFromPlugin(pluginPath2, "copilot");
|
|
36044
|
-
await writeOfficialSkills(
|
|
37135
|
+
await writeOfficialSkills(path24.join(pluginPath2, "skills"));
|
|
36045
37136
|
return {
|
|
36046
37137
|
agent: "copilot",
|
|
36047
37138
|
pluginPath: pluginPath2,
|
|
36048
37139
|
installHint: "Run `copilot plugin install <path>` if automatic install is unavailable, then restart Copilot CLI."
|
|
36049
37140
|
};
|
|
36050
37141
|
}
|
|
36051
|
-
const marketplaceRoot =
|
|
36052
|
-
const marketplacePath =
|
|
36053
|
-
const pluginPath =
|
|
37142
|
+
const marketplaceRoot = path24.join(home, ".claude", "plugins", "marketplaces", "memorix-local");
|
|
37143
|
+
const marketplacePath = path24.join(marketplaceRoot, ".claude-plugin", "marketplace.json");
|
|
37144
|
+
const pluginPath = path24.join(marketplaceRoot, "plugins", "memorix");
|
|
36054
37145
|
await copyDir(source, pluginPath);
|
|
36055
37146
|
if (!includeHooks) await stripHookCaptureFromPlugin(pluginPath, "claude");
|
|
36056
|
-
await writeOfficialSkills(
|
|
37147
|
+
await writeOfficialSkills(path24.join(pluginPath, "skills"));
|
|
36057
37148
|
await writeClaudeMarketplace(marketplacePath);
|
|
36058
37149
|
return {
|
|
36059
37150
|
agent: "claude",
|
|
@@ -36066,11 +37157,11 @@ async function installPluginPackage(options2) {
|
|
|
36066
37157
|
async function installGeminiExtensionPackage(options2 = {}) {
|
|
36067
37158
|
const home = options2.homeDir ?? homedir24();
|
|
36068
37159
|
const packageRoot = findPackageRoot();
|
|
36069
|
-
const source =
|
|
37160
|
+
const source = path24.join(packageRoot, "plugins", "gemini", "memorix");
|
|
36070
37161
|
if (!existsSync12(source)) {
|
|
36071
37162
|
throw new Error(`Gemini extension template not found: ${source}`);
|
|
36072
37163
|
}
|
|
36073
|
-
const extensionPath =
|
|
37164
|
+
const extensionPath = path24.join(home, ".gemini", "extensions", "memorix");
|
|
36074
37165
|
await copyDir(source, extensionPath);
|
|
36075
37166
|
return {
|
|
36076
37167
|
agent: "gemini-cli",
|
|
@@ -36080,16 +37171,16 @@ async function installGeminiExtensionPackage(options2 = {}) {
|
|
|
36080
37171
|
}
|
|
36081
37172
|
async function installAntigravityPluginPackage(options2 = {}) {
|
|
36082
37173
|
const packageRoot = findPackageRoot();
|
|
36083
|
-
const source =
|
|
37174
|
+
const source = path24.join(packageRoot, "plugins", "antigravity", "memorix");
|
|
36084
37175
|
if (!existsSync12(source)) {
|
|
36085
37176
|
throw new Error(`Antigravity plugin template not found: ${source}`);
|
|
36086
37177
|
}
|
|
36087
|
-
const pluginPath = options2.global === false ?
|
|
37178
|
+
const pluginPath = options2.global === false ? path24.join(options2.projectRoot ?? process.cwd(), ".agents", "plugins", "memorix") : path24.join(options2.homeDir ?? homedir24(), ".gemini", "config", "plugins", "memorix");
|
|
36088
37179
|
await copyDir(source, pluginPath);
|
|
36089
37180
|
if (options2.includeHooks === false) {
|
|
36090
|
-
await rm(
|
|
37181
|
+
await rm(path24.join(pluginPath, "hooks.json"), { force: true });
|
|
36091
37182
|
}
|
|
36092
|
-
await writeOfficialSkills(
|
|
37183
|
+
await writeOfficialSkills(path24.join(pluginPath, "skills"));
|
|
36093
37184
|
return {
|
|
36094
37185
|
agent: "antigravity",
|
|
36095
37186
|
pluginPath,
|
|
@@ -36098,14 +37189,14 @@ async function installAntigravityPluginPackage(options2 = {}) {
|
|
|
36098
37189
|
}
|
|
36099
37190
|
async function installPiPackage(options2 = {}) {
|
|
36100
37191
|
const packageRoot = findPackageRoot();
|
|
36101
|
-
const source =
|
|
37192
|
+
const source = path24.join(packageRoot, "plugins", "pi", "memorix");
|
|
36102
37193
|
if (!existsSync12(source)) {
|
|
36103
37194
|
throw new Error(`Pi package template not found: ${source}`);
|
|
36104
37195
|
}
|
|
36105
|
-
const defaultRoot = options2.global ?
|
|
36106
|
-
const packagePath = options2.packageDir ??
|
|
37196
|
+
const defaultRoot = options2.global ? path24.join(options2.homeDir ?? homedir24(), ".pi", "agent", "packages") : path24.join(process.cwd(), ".pi", "packages");
|
|
37197
|
+
const packagePath = options2.packageDir ?? path24.join(defaultRoot, "memorix");
|
|
36107
37198
|
await copyDir(source, packagePath);
|
|
36108
|
-
await writeOfficialSkills(
|
|
37199
|
+
await writeOfficialSkills(path24.join(packagePath, "skills"));
|
|
36109
37200
|
const installHint = options2.global ? `Setup runs \`pi install "${packagePath}" --approve\`. If Pi is unavailable, run that command after installing Pi.` : `Setup runs \`pi install "${packagePath}" -l --approve\`. If Pi is unavailable, run that command from the project root after installing Pi.`;
|
|
36110
37201
|
return {
|
|
36111
37202
|
agent: "pi",
|
|
@@ -36116,14 +37207,14 @@ async function installPiPackage(options2 = {}) {
|
|
|
36116
37207
|
async function installOpenClawBundlePackage(options2 = {}) {
|
|
36117
37208
|
const home = options2.homeDir ?? homedir24();
|
|
36118
37209
|
const packageRoot = findPackageRoot();
|
|
36119
|
-
const source =
|
|
37210
|
+
const source = path24.join(packageRoot, "plugins", "openclaw", "memorix");
|
|
36120
37211
|
if (!existsSync12(source)) {
|
|
36121
37212
|
throw new Error(`OpenClaw bundle template not found: ${source}`);
|
|
36122
37213
|
}
|
|
36123
|
-
const bundlePath =
|
|
37214
|
+
const bundlePath = path24.join(home, ".openclaw", "extensions", "memorix");
|
|
36124
37215
|
await copyDir(source, bundlePath);
|
|
36125
37216
|
if (options2.includeHooks === false) await stripHookCaptureFromOpenClawBundle(bundlePath);
|
|
36126
|
-
await writeOfficialSkills(
|
|
37217
|
+
await writeOfficialSkills(path24.join(bundlePath, "skills"));
|
|
36127
37218
|
return {
|
|
36128
37219
|
agent: "openclaw",
|
|
36129
37220
|
bundlePath,
|
|
@@ -36132,22 +37223,22 @@ async function installOpenClawBundlePackage(options2 = {}) {
|
|
|
36132
37223
|
}
|
|
36133
37224
|
async function installHermesPluginPackage(options2 = {}) {
|
|
36134
37225
|
const packageRoot = findPackageRoot();
|
|
36135
|
-
const source =
|
|
37226
|
+
const source = path24.join(packageRoot, "plugins", "hermes", "memorix");
|
|
36136
37227
|
if (!existsSync12(source)) {
|
|
36137
37228
|
throw new Error(`Hermes plugin template not found: ${source}`);
|
|
36138
37229
|
}
|
|
36139
37230
|
const hermesHome = resolveHermesHome(options2.homeDir);
|
|
36140
|
-
const pluginPath =
|
|
37231
|
+
const pluginPath = path24.join(hermesHome, "plugins", "memorix");
|
|
36141
37232
|
await copyDir(source, pluginPath);
|
|
36142
|
-
await writeOfficialSkills(
|
|
36143
|
-
const configPath =
|
|
37233
|
+
await writeOfficialSkills(path24.join(pluginPath, "skills"));
|
|
37234
|
+
const configPath = path24.join(hermesHome, "config.yaml");
|
|
36144
37235
|
let existingContent = null;
|
|
36145
37236
|
try {
|
|
36146
37237
|
existingContent = await readFile5(configPath, "utf-8");
|
|
36147
37238
|
} catch {
|
|
36148
37239
|
existingContent = null;
|
|
36149
37240
|
}
|
|
36150
|
-
await mkdir5(
|
|
37241
|
+
await mkdir5(path24.dirname(configPath), { recursive: true });
|
|
36151
37242
|
await writeFile5(configPath, mergeHermesPluginEnabled(existingContent, "memorix"), "utf-8");
|
|
36152
37243
|
return {
|
|
36153
37244
|
agent: "hermes",
|
|
@@ -36159,14 +37250,14 @@ async function installHermesPluginPackage(options2 = {}) {
|
|
|
36159
37250
|
}
|
|
36160
37251
|
async function installOmpPackage(options2 = {}) {
|
|
36161
37252
|
const packageRoot = findPackageRoot();
|
|
36162
|
-
const source =
|
|
37253
|
+
const source = path24.join(packageRoot, "plugins", "omp", "memorix");
|
|
36163
37254
|
if (!existsSync12(source)) {
|
|
36164
37255
|
throw new Error(`Oh-my-Pi package template not found: ${source}`);
|
|
36165
37256
|
}
|
|
36166
|
-
const defaultRoot = options2.global ?
|
|
36167
|
-
const packagePath = options2.packageDir ??
|
|
37257
|
+
const defaultRoot = options2.global ? path24.join(options2.homeDir ?? homedir24(), ".omp", "agent", "packages") : path24.join(process.cwd(), ".omp", "packages");
|
|
37258
|
+
const packagePath = options2.packageDir ?? path24.join(defaultRoot, "memorix");
|
|
36168
37259
|
await copyDir(source, packagePath);
|
|
36169
|
-
await writeOfficialSkills(
|
|
37260
|
+
await writeOfficialSkills(path24.join(packagePath, "skills"));
|
|
36170
37261
|
return {
|
|
36171
37262
|
agent: "omp",
|
|
36172
37263
|
packagePath,
|
|
@@ -36345,7 +37436,7 @@ ${hook.stdout || ""}`.toLowerCase();
|
|
|
36345
37436
|
}
|
|
36346
37437
|
function resolveHermesCommand(hermesHome) {
|
|
36347
37438
|
if (process.platform === "win32") {
|
|
36348
|
-
const localHermes =
|
|
37439
|
+
const localHermes = path24.join(hermesHome, "hermes-agent", "venv", "Scripts", "hermes.exe");
|
|
36349
37440
|
if (existsSync12(localHermes)) return localHermes;
|
|
36350
37441
|
}
|
|
36351
37442
|
return "hermes";
|
|
@@ -37157,6 +38248,7 @@ function receiptOmissionKind(raw) {
|
|
|
37157
38248
|
if (raw.includes("state")) return "code-state";
|
|
37158
38249
|
if (raw.includes("semantic")) return "semantic-code";
|
|
37159
38250
|
if (raw.includes("start")) return "start-here";
|
|
38251
|
+
if (raw.includes("durable-memory")) return "durable-memory";
|
|
37160
38252
|
if (raw.includes("memory")) return "memory";
|
|
37161
38253
|
if (raw.includes("claim")) return "claim";
|
|
37162
38254
|
if (raw.includes("knowledge-page")) return "knowledge-page";
|
|
@@ -37415,6 +38507,26 @@ function renderTaskWorksetPrompt(input) {
|
|
|
37415
38507
|
});
|
|
37416
38508
|
}
|
|
37417
38509
|
}
|
|
38510
|
+
if (input.durableMemory.length > 0) {
|
|
38511
|
+
appendLine(lines, "", maxTokens, omitted, "durable-memory-heading");
|
|
38512
|
+
appendLine(lines, "Durable memory", maxTokens, omitted, "durable-memory-heading");
|
|
38513
|
+
for (const memory of input.durableMemory.slice(0, 3)) {
|
|
38514
|
+
appendLine(
|
|
38515
|
+
lines,
|
|
38516
|
+
"- " + memory.kind + " (" + memory.scope + ", " + memory.state + "; ref durable:" + memory.id + "): " + memory.summary,
|
|
38517
|
+
maxTokens,
|
|
38518
|
+
omitted,
|
|
38519
|
+
"durable-memory",
|
|
38520
|
+
selected,
|
|
38521
|
+
{
|
|
38522
|
+
kind: "durable-memory",
|
|
38523
|
+
id: "durable:" + memory.id,
|
|
38524
|
+
reason: memory.reason,
|
|
38525
|
+
trust: "source-backed"
|
|
38526
|
+
}
|
|
38527
|
+
);
|
|
38528
|
+
}
|
|
38529
|
+
}
|
|
37418
38530
|
if (input.workflows.length > 0) {
|
|
37419
38531
|
appendLine(lines, "", maxTokens, omitted, "workflow-heading");
|
|
37420
38532
|
appendLine(lines, "Project workflow", maxTokens, omitted, "workflow-heading");
|
|
@@ -37484,6 +38596,32 @@ async function buildTaskWorkset(input) {
|
|
|
37484
38596
|
evidenceRefs: evidenceByClaim.get(claim.id).map((item) => item.id),
|
|
37485
38597
|
reason: selection.reasons[claim.id] ?? "source-qualified task match"
|
|
37486
38598
|
}));
|
|
38599
|
+
let durableMemory = [];
|
|
38600
|
+
let durableEvidence = [];
|
|
38601
|
+
if (task) {
|
|
38602
|
+
try {
|
|
38603
|
+
const selected = await selectLongTermMemoriesForTask({
|
|
38604
|
+
dataDir: input.dataDir,
|
|
38605
|
+
projectId: input.projectId,
|
|
38606
|
+
task,
|
|
38607
|
+
...input.reader?.agentId ? { agentId: input.reader.agentId } : {},
|
|
38608
|
+
...input.reader?.isTeamMember ? { isTeamMember: true } : {},
|
|
38609
|
+
limit: 3
|
|
38610
|
+
});
|
|
38611
|
+
durableMemory = selected.map((item) => ({
|
|
38612
|
+
id: item.memory.id,
|
|
38613
|
+
kind: item.memory.kind,
|
|
38614
|
+
scope: item.memory.scope,
|
|
38615
|
+
state: item.memory.state,
|
|
38616
|
+
title: item.memory.title,
|
|
38617
|
+
summary: renderLongTermMemorySummary(item.memory, 20),
|
|
38618
|
+
evidenceRefs: item.evidence.map((evidence) => evidence.id),
|
|
38619
|
+
reason: item.reason
|
|
38620
|
+
}));
|
|
38621
|
+
durableEvidence = selected.flatMap((item) => item.evidence);
|
|
38622
|
+
} catch {
|
|
38623
|
+
}
|
|
38624
|
+
}
|
|
37487
38625
|
let workspace;
|
|
37488
38626
|
let pages = [];
|
|
37489
38627
|
let workflows = [];
|
|
@@ -37523,7 +38661,10 @@ async function buildTaskWorkset(input) {
|
|
|
37523
38661
|
const evidenceIds = unique(selection.claims.flatMap((claim) => evidenceIdsForClaim(
|
|
37524
38662
|
claim,
|
|
37525
38663
|
evidenceByClaim.get(claim.id) ?? []
|
|
37526
|
-
))
|
|
38664
|
+
)).concat(
|
|
38665
|
+
durableMemory.map((memory) => "durable:" + memory.id),
|
|
38666
|
+
durableEvidence.map((evidence) => "durable-evidence:" + evidence.id)
|
|
38667
|
+
));
|
|
37527
38668
|
const verification = unique([
|
|
37528
38669
|
...workflows.flatMap((workflow) => workflow.verificationGates),
|
|
37529
38670
|
...input.verificationHints
|
|
@@ -37549,7 +38690,7 @@ async function buildTaskWorkset(input) {
|
|
|
37549
38690
|
} : {}
|
|
37550
38691
|
} : void 0;
|
|
37551
38692
|
const base = {
|
|
37552
|
-
version: "1.
|
|
38693
|
+
version: "1.3",
|
|
37553
38694
|
task,
|
|
37554
38695
|
lens: input.lens,
|
|
37555
38696
|
currentFacts: input.currentFacts?.map((fact) => fact.startsWith("Historical note:") ? short(fact, 48) : short(fact, 28)).slice(0, 4) ?? [],
|
|
@@ -37562,6 +38703,7 @@ async function buildTaskWorkset(input) {
|
|
|
37562
38703
|
hiddenCautionMemoryCount: input.hiddenCautionMemoryCount ?? 0,
|
|
37563
38704
|
claims,
|
|
37564
38705
|
pages,
|
|
38706
|
+
durableMemory,
|
|
37565
38707
|
workflows,
|
|
37566
38708
|
cautions: normalizedCautions,
|
|
37567
38709
|
verification,
|
|
@@ -37578,7 +38720,7 @@ async function buildTaskWorkset(input) {
|
|
|
37578
38720
|
budget: { maxTokens }
|
|
37579
38721
|
});
|
|
37580
38722
|
const receipt = {
|
|
37581
|
-
version: "1.
|
|
38723
|
+
version: "1.3",
|
|
37582
38724
|
target: input.deliveryTarget ?? "project-context",
|
|
37583
38725
|
elapsedMs: Math.max(0, Date.now() - startedAt),
|
|
37584
38726
|
budget: {
|
|
@@ -37613,6 +38755,7 @@ var init_workset = __esm({
|
|
|
37613
38755
|
init_workspace();
|
|
37614
38756
|
init_workflow_store();
|
|
37615
38757
|
init_workflows();
|
|
38758
|
+
init_long_term();
|
|
37616
38759
|
CONTINUATION_DETAIL_TOKEN_BUDGET = 20;
|
|
37617
38760
|
}
|
|
37618
38761
|
});
|
|
@@ -37625,7 +38768,7 @@ __export(current_facts_exports, {
|
|
|
37625
38768
|
});
|
|
37626
38769
|
import { execFileSync } from "child_process";
|
|
37627
38770
|
import { existsSync as existsSync13, readFileSync as readFileSync8 } from "fs";
|
|
37628
|
-
import
|
|
38771
|
+
import path25 from "path";
|
|
37629
38772
|
function readTextIfExists(filePath) {
|
|
37630
38773
|
try {
|
|
37631
38774
|
if (!existsSync13(filePath)) return null;
|
|
@@ -37635,7 +38778,7 @@ function readTextIfExists(filePath) {
|
|
|
37635
38778
|
}
|
|
37636
38779
|
}
|
|
37637
38780
|
function readPackageVersion(rootPath) {
|
|
37638
|
-
const text = readTextIfExists(
|
|
38781
|
+
const text = readTextIfExists(path25.join(rootPath, "package.json"));
|
|
37639
38782
|
if (!text) return void 0;
|
|
37640
38783
|
try {
|
|
37641
38784
|
const parsed = JSON.parse(text);
|
|
@@ -37645,7 +38788,7 @@ function readPackageVersion(rootPath) {
|
|
|
37645
38788
|
}
|
|
37646
38789
|
}
|
|
37647
38790
|
function readLatestChangelog(rootPath) {
|
|
37648
|
-
const text = readTextIfExists(
|
|
38791
|
+
const text = readTextIfExists(path25.join(rootPath, "CHANGELOG.md"));
|
|
37649
38792
|
if (!text) return void 0;
|
|
37650
38793
|
const match = text.match(/^##\s+\[?v?([^\]\s]+)\]?\s*(?:-\s*(\d{4}-\d{2}-\d{2}))?/m);
|
|
37651
38794
|
if (!match) return void 0;
|
|
@@ -37715,7 +38858,7 @@ function detectStaleProgressNotes(input) {
|
|
|
37715
38858
|
];
|
|
37716
38859
|
const notes = [];
|
|
37717
38860
|
for (const relPath of candidates) {
|
|
37718
|
-
const content = readTextIfExists(
|
|
38861
|
+
const content = readTextIfExists(path25.join(input.rootPath, relPath));
|
|
37719
38862
|
if (!content) continue;
|
|
37720
38863
|
const parsed = parseProgressNote(content);
|
|
37721
38864
|
const olderThanChangelog = compareDateStrings(parsed.lastUpdated, input.latestChangelog?.date);
|
|
@@ -37966,9 +39109,9 @@ async function inspectExternalCodeGraph(input) {
|
|
|
37966
39109
|
return { health, quality: providerQuality({ mode, health }) };
|
|
37967
39110
|
}
|
|
37968
39111
|
function safeRelativePath(projectRoot, value, exclude) {
|
|
37969
|
-
const
|
|
37970
|
-
if (!
|
|
37971
|
-
const absolute = resolve3(projectRoot,
|
|
39112
|
+
const path38 = safeText(value, 1024);
|
|
39113
|
+
if (!path38 || isAbsolute2(path38)) return void 0;
|
|
39114
|
+
const absolute = resolve3(projectRoot, path38);
|
|
37972
39115
|
const fromRoot = relative2(projectRoot, absolute);
|
|
37973
39116
|
if (!fromRoot || fromRoot === ".." || fromRoot.startsWith("..\\") || fromRoot.startsWith("../") || isAbsolute2(fromRoot)) return void 0;
|
|
37974
39117
|
const normalized = normalizeCodePath(fromRoot);
|
|
@@ -38250,15 +39393,15 @@ function countLanguages(files) {
|
|
|
38250
39393
|
}
|
|
38251
39394
|
return [...counts.entries()].map(([language, files2]) => ({ language, files: files2 })).sort((a3, b3) => a3.language.localeCompare(b3.language));
|
|
38252
39395
|
}
|
|
38253
|
-
function suggestedReadRank(
|
|
38254
|
-
const normalized =
|
|
39396
|
+
function suggestedReadRank(path38) {
|
|
39397
|
+
const normalized = path38.replace(/\\/g, "/");
|
|
38255
39398
|
if (normalized.startsWith("src/")) return 0;
|
|
38256
39399
|
if (normalized.startsWith("tests/") || normalized.startsWith("test/")) return 0;
|
|
38257
39400
|
if (normalized.startsWith("packages/") && normalized.includes("/src/")) return 2;
|
|
38258
39401
|
return 3;
|
|
38259
39402
|
}
|
|
38260
39403
|
function compactSuggestedReads(paths, limit = 8, exclude) {
|
|
38261
|
-
return uniq(paths).filter((
|
|
39404
|
+
return uniq(paths).filter((path38) => !isCodeGraphExcludedPath(path38, exclude)).sort((a3, b3) => suggestedReadRank(a3) - suggestedReadRank(b3)).slice(0, limit);
|
|
38262
39405
|
}
|
|
38263
39406
|
function collectGraph(store2, projectId, observations2, exclude) {
|
|
38264
39407
|
const files = store2.listFiles(projectId);
|
|
@@ -38298,14 +39441,14 @@ function collectGraph(store2, projectId, observations2, exclude) {
|
|
|
38298
39441
|
}
|
|
38299
39442
|
if (files.length === 0) {
|
|
38300
39443
|
for (const observation of observations2) {
|
|
38301
|
-
for (const
|
|
38302
|
-
if (!
|
|
38303
|
-
suggestedReads.push(
|
|
39444
|
+
for (const path38 of observation.filesModified ?? []) {
|
|
39445
|
+
if (!path38 || isCodeGraphExcludedPath(path38, exclude)) continue;
|
|
39446
|
+
suggestedReads.push(path38);
|
|
38304
39447
|
sources.push({
|
|
38305
39448
|
observationId: observation.id,
|
|
38306
39449
|
title: observation.title,
|
|
38307
39450
|
type: observation.type,
|
|
38308
|
-
path:
|
|
39451
|
+
path: path38,
|
|
38309
39452
|
status: "unbound",
|
|
38310
39453
|
reason: "Recorded file hint; Code Memory refresh is pending."
|
|
38311
39454
|
});
|
|
@@ -38389,7 +39532,7 @@ function formatProjectContextOverview(overview) {
|
|
|
38389
39532
|
if (overview.suggestedReads.length === 0) {
|
|
38390
39533
|
lines.push("- none yet");
|
|
38391
39534
|
} else {
|
|
38392
|
-
overview.suggestedReads.slice(0, 8).forEach((
|
|
39535
|
+
overview.suggestedReads.slice(0, 8).forEach((path38, index) => lines.push(`${index + 1}. ${path38}`));
|
|
38393
39536
|
}
|
|
38394
39537
|
return lines.join("\n");
|
|
38395
39538
|
}
|
|
@@ -38430,8 +39573,8 @@ __export(graph_store_exports, {
|
|
|
38430
39573
|
initGraphStore: () => initGraphStore,
|
|
38431
39574
|
resetGraphStore: () => resetGraphStore
|
|
38432
39575
|
});
|
|
38433
|
-
import
|
|
38434
|
-
import
|
|
39576
|
+
import path26 from "path";
|
|
39577
|
+
import fs18 from "fs";
|
|
38435
39578
|
function safeJsonParse3(val, fallback) {
|
|
38436
39579
|
if (val == null || val === "") return fallback;
|
|
38437
39580
|
try {
|
|
@@ -38521,8 +39664,8 @@ var init_graph_store = __esm({
|
|
|
38521
39664
|
async migrateFromJsonlIfNeeded() {
|
|
38522
39665
|
const count3 = this.db.prepare(`SELECT COUNT(*) AS cnt FROM graph_entities`).get();
|
|
38523
39666
|
if (count3.cnt > 0) return;
|
|
38524
|
-
const jsonlPath =
|
|
38525
|
-
if (!
|
|
39667
|
+
const jsonlPath = path26.join(this.dataDir, "graph.jsonl");
|
|
39668
|
+
if (!fs18.existsSync(jsonlPath)) return;
|
|
38526
39669
|
try {
|
|
38527
39670
|
const data = await loadGraphJsonl(this.dataDir);
|
|
38528
39671
|
if (data.entities.length === 0 && data.relations.length === 0) return;
|
|
@@ -39264,8 +40407,8 @@ var compaction_checkpoint_store_exports = {};
|
|
|
39264
40407
|
__export(compaction_checkpoint_store_exports, {
|
|
39265
40408
|
CompactionCheckpointStore: () => CompactionCheckpointStore
|
|
39266
40409
|
});
|
|
39267
|
-
import { createHash as createHash12, randomUUID as
|
|
39268
|
-
function
|
|
40410
|
+
import { createHash as createHash12, randomUUID as randomUUID12 } from "crypto";
|
|
40411
|
+
function optionalText6(value) {
|
|
39269
40412
|
return typeof value === "string" && value ? value : void 0;
|
|
39270
40413
|
}
|
|
39271
40414
|
function optionalNumber2(value) {
|
|
@@ -39319,15 +40462,15 @@ function rowToCheckpoint(row) {
|
|
|
39319
40462
|
reason: row.reason,
|
|
39320
40463
|
sourceEvent: row.source_event,
|
|
39321
40464
|
sourceKey: row.source_key,
|
|
39322
|
-
...
|
|
40465
|
+
...optionalText6(row.summary) ? { summary: row.summary } : {},
|
|
39323
40466
|
...optionalNumber2(row.tokens_before) !== void 0 ? { tokensBefore: Number(row.tokens_before) } : {},
|
|
39324
|
-
...
|
|
40467
|
+
...optionalText6(row.first_kept_entry_id) ? { firstKeptEntryId: row.first_kept_entry_id } : {},
|
|
39325
40468
|
...parseDetails(row.details_json) ? { details: parseDetails(row.details_json) } : {},
|
|
39326
40469
|
transcriptAvailable: Boolean(row.transcript_available),
|
|
39327
40470
|
status: row.status,
|
|
39328
40471
|
preCapturedAt: row.pre_captured_at,
|
|
39329
|
-
...
|
|
39330
|
-
...
|
|
40472
|
+
...optionalText6(row.completed_at) ? { completedAt: row.completed_at } : {},
|
|
40473
|
+
...optionalText6(row.delivered_at) ? { deliveredAt: row.delivered_at } : {},
|
|
39331
40474
|
deliveryCount: Number(row.delivery_count ?? 0),
|
|
39332
40475
|
createdAt: row.created_at,
|
|
39333
40476
|
updatedAt: row.updated_at
|
|
@@ -39365,7 +40508,7 @@ var init_compaction_checkpoint_store = __esm({
|
|
|
39365
40508
|
if (pending) return rowToCheckpoint(pending);
|
|
39366
40509
|
const now3 = input.capturedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
39367
40510
|
const checkpoint = {
|
|
39368
|
-
id:
|
|
40511
|
+
id: randomUUID12(),
|
|
39369
40512
|
projectId: input.projectId,
|
|
39370
40513
|
sessionId: input.sessionId,
|
|
39371
40514
|
agent: input.agent,
|
|
@@ -39373,7 +40516,7 @@ var init_compaction_checkpoint_store = __esm({
|
|
|
39373
40516
|
captureKind: "preflight",
|
|
39374
40517
|
reason: safeReason(input.reason),
|
|
39375
40518
|
sourceEvent: input.sourceEvent,
|
|
39376
|
-
sourceKey: `pre:${
|
|
40519
|
+
sourceKey: `pre:${randomUUID12()}`,
|
|
39377
40520
|
transcriptAvailable: Boolean(input.transcriptAvailable),
|
|
39378
40521
|
status: "active",
|
|
39379
40522
|
preCapturedAt: now3,
|
|
@@ -39439,7 +40582,7 @@ var init_compaction_checkpoint_store = __esm({
|
|
|
39439
40582
|
return this.get(checkpoint2.id);
|
|
39440
40583
|
}
|
|
39441
40584
|
const checkpoint = {
|
|
39442
|
-
id:
|
|
40585
|
+
id: randomUUID12(),
|
|
39443
40586
|
projectId: input.projectId,
|
|
39444
40587
|
sessionId: input.sessionId,
|
|
39445
40588
|
agent: input.agent,
|
|
@@ -39574,7 +40717,7 @@ __export(auto_context_exports, {
|
|
|
39574
40717
|
formatLegacyAutoProjectContextPrompt: () => formatLegacyAutoProjectContextPrompt
|
|
39575
40718
|
});
|
|
39576
40719
|
import { existsSync as existsSync15, statSync as statSync4 } from "fs";
|
|
39577
|
-
import
|
|
40720
|
+
import path27 from "path";
|
|
39578
40721
|
function activeProjectObservations(observations2, projectId) {
|
|
39579
40722
|
return observations2.filter((obs) => obs.projectId === projectId && (obs.status ?? "active") === "active");
|
|
39580
40723
|
}
|
|
@@ -39809,6 +40952,7 @@ async function buildAutoProjectContext(input) {
|
|
|
39809
40952
|
stale: overview.freshness.stale
|
|
39810
40953
|
},
|
|
39811
40954
|
runtimeCautions,
|
|
40955
|
+
...input.reader ? { reader: input.reader } : {},
|
|
39812
40956
|
...input.deliveryTarget ? { deliveryTarget: input.deliveryTarget } : {}
|
|
39813
40957
|
});
|
|
39814
40958
|
return {
|
|
@@ -39853,7 +40997,7 @@ function dedupeSourcesByObservation(sources) {
|
|
|
39853
40997
|
function existingLensCandidates(rootPath, lens) {
|
|
39854
40998
|
const out = [];
|
|
39855
40999
|
for (const candidate2 of lensPathCandidates(lens)) {
|
|
39856
|
-
const absolute =
|
|
41000
|
+
const absolute = path27.join(rootPath, candidate2);
|
|
39857
41001
|
try {
|
|
39858
41002
|
if (!existsSync15(absolute)) continue;
|
|
39859
41003
|
const stat = statSync4(absolute);
|
|
@@ -39963,7 +41107,7 @@ function formatAutoProjectContextSummary(context) {
|
|
|
39963
41107
|
"Start here"
|
|
39964
41108
|
].filter(Boolean);
|
|
39965
41109
|
if (startHere.length > 0) {
|
|
39966
|
-
startHere.forEach((
|
|
41110
|
+
startHere.forEach((path38, index) => lines.push(`${index + 1}. ${path38}`));
|
|
39967
41111
|
} else {
|
|
39968
41112
|
lines.push("- no code-bound reads yet; inspect the task-relevant files directly");
|
|
39969
41113
|
}
|
|
@@ -39972,6 +41116,14 @@ function formatAutoProjectContextSummary(context) {
|
|
|
39972
41116
|
"Reliable memory",
|
|
39973
41117
|
reliableSources.length > 0 ? `- ${reliableSources.length} current code-bound memory link(s)` : "- none yet"
|
|
39974
41118
|
);
|
|
41119
|
+
if (context.workset.durableMemory.length > 0) {
|
|
41120
|
+
lines.push("", "Durable memory");
|
|
41121
|
+
for (const memory of context.workset.durableMemory.slice(0, 3)) {
|
|
41122
|
+
lines.push(
|
|
41123
|
+
"- " + memory.kind + " (" + memory.scope + ", " + memory.state + "): " + compactContinuationText(memory.summary, 28)
|
|
41124
|
+
);
|
|
41125
|
+
}
|
|
41126
|
+
}
|
|
39975
41127
|
const continuation = context.workset.continuation;
|
|
39976
41128
|
if (continuation?.previousSession || continuation?.memories.length || continuation?.compactCheckpoint) {
|
|
39977
41129
|
lines.push("", "Resume from prior work");
|
|
@@ -40021,7 +41173,7 @@ function formatLegacyAutoProjectContextPrompt(context) {
|
|
|
40021
41173
|
if (startHere.length === 0) {
|
|
40022
41174
|
lines.push("- no code-bound reads yet; inspect the task-relevant code directly");
|
|
40023
41175
|
} else {
|
|
40024
|
-
startHere.forEach((
|
|
41176
|
+
startHere.forEach((path38, index) => lines.push(`${index + 1}. ${path38}`));
|
|
40025
41177
|
}
|
|
40026
41178
|
const { reliableSources, cautionSources, hiddenReliableCount, hiddenCautionCount } = lensSourceSets(context);
|
|
40027
41179
|
lines.push("", "Reliable memory");
|
|
@@ -40489,6 +41641,7 @@ async function attachTaskWorkset(input) {
|
|
|
40489
41641
|
stale: input.pack.warnings.filter((warning) => warning.status === "stale").length
|
|
40490
41642
|
},
|
|
40491
41643
|
runtimeCautions: input.runtimeCautions,
|
|
41644
|
+
...input.reader ? { reader: input.reader } : {},
|
|
40492
41645
|
deliveryTarget: "context-pack"
|
|
40493
41646
|
});
|
|
40494
41647
|
return { ...input.pack, workset };
|
|
@@ -40499,7 +41652,7 @@ function buildContextPackPrompt(pack) {
|
|
|
40499
41652
|
const unboundMemories = pack.memories.filter((memory) => memory.status === "unbound");
|
|
40500
41653
|
const lines = ["## Task", pack.task, "", "## Reliable Memories"];
|
|
40501
41654
|
const visibleCodeFacts = pack.codeFacts.filter((fact) => !isCodeGraphExcludedPath(fact.path)).slice(0, 5);
|
|
40502
|
-
const visibleSuggestedReads = pack.suggestedReads.filter((
|
|
41655
|
+
const visibleSuggestedReads = pack.suggestedReads.filter((path38) => !isCodeGraphExcludedPath(path38)).slice(0, 5);
|
|
40503
41656
|
if (reliableMemories.length === 0) lines.push("- none");
|
|
40504
41657
|
for (const memory of reliableMemories) {
|
|
40505
41658
|
lines.push(`- #${memory.id} ${memory.status}: [${memory.type}] ${memory.title} (${memory.reason})`);
|
|
@@ -40523,7 +41676,7 @@ function buildContextPackPrompt(pack) {
|
|
|
40523
41676
|
}
|
|
40524
41677
|
lines.push("", "## Suggested Next Reads");
|
|
40525
41678
|
if (visibleSuggestedReads.length === 0) lines.push("- none");
|
|
40526
|
-
visibleSuggestedReads.forEach((
|
|
41679
|
+
visibleSuggestedReads.forEach((path38, index) => lines.push(`${index + 1}. ${path38}`));
|
|
40527
41680
|
lines.push("", "## Suggested Verification");
|
|
40528
41681
|
if (pack.suggestedVerification.length === 0) lines.push("- none");
|
|
40529
41682
|
for (const command of pack.suggestedVerification) lines.push(`- ${command}`);
|
|
@@ -40736,7 +41889,8 @@ ${formatUsageHint()}`;
|
|
|
40736
41889
|
} : {},
|
|
40737
41890
|
...external.outline ? { semanticCode: external.outline } : {},
|
|
40738
41891
|
providerQuality: external.quality,
|
|
40739
|
-
...external.caution ? { runtimeCautions: [{ kind: "external-codegraph-fallback", message: external.caution }] } : {}
|
|
41892
|
+
...external.caution ? { runtimeCautions: [{ kind: "external-codegraph-fallback", message: external.caution }] } : {},
|
|
41893
|
+
reader
|
|
40740
41894
|
});
|
|
40741
41895
|
emitResult({ project, pack, providerQuality: external.quality }, buildContextPackPrompt(pack), asJson);
|
|
40742
41896
|
return;
|
|
@@ -42922,8 +44076,8 @@ var transfer_exports = {};
|
|
|
42922
44076
|
__export(transfer_exports, {
|
|
42923
44077
|
default: () => transfer_default
|
|
42924
44078
|
});
|
|
42925
|
-
import { promises as
|
|
42926
|
-
import
|
|
44079
|
+
import { promises as fs19 } from "fs";
|
|
44080
|
+
import path28 from "path";
|
|
42927
44081
|
async function readStandardInput() {
|
|
42928
44082
|
return new Promise((resolve6, reject) => {
|
|
42929
44083
|
let content = "";
|
|
@@ -42944,13 +44098,13 @@ async function readImportPayload(args, projectRoot) {
|
|
|
42944
44098
|
throw new Error("Choose exactly one import source: --data <json>, --file <path>, or --stdin.");
|
|
42945
44099
|
}
|
|
42946
44100
|
if (readFromStdin) return readStandardInput();
|
|
42947
|
-
if (file) return
|
|
44101
|
+
if (file) return fs19.readFile(path28.resolve(projectRoot, file), "utf8");
|
|
42948
44102
|
return data;
|
|
42949
44103
|
}
|
|
42950
44104
|
async function writeExportPayload(projectRoot, output, payload) {
|
|
42951
|
-
const outputPath =
|
|
42952
|
-
await
|
|
42953
|
-
await
|
|
44105
|
+
const outputPath = path28.resolve(projectRoot, output);
|
|
44106
|
+
await fs19.mkdir(path28.dirname(outputPath), { recursive: true });
|
|
44107
|
+
await fs19.writeFile(outputPath, payload, "utf8");
|
|
42954
44108
|
return outputPath;
|
|
42955
44109
|
}
|
|
42956
44110
|
var transfer_default;
|
|
@@ -44524,8 +45678,8 @@ var init_parseUtil = __esm({
|
|
|
44524
45678
|
init_errors2();
|
|
44525
45679
|
init_en();
|
|
44526
45680
|
makeIssue = (params) => {
|
|
44527
|
-
const { data, path:
|
|
44528
|
-
const fullPath = [...
|
|
45681
|
+
const { data, path: path38, errorMaps, issueData } = params;
|
|
45682
|
+
const fullPath = [...path38, ...issueData.path || []];
|
|
44529
45683
|
const fullIssue = {
|
|
44530
45684
|
...issueData,
|
|
44531
45685
|
path: fullPath
|
|
@@ -44562,15 +45716,15 @@ var init_parseUtil = __esm({
|
|
|
44562
45716
|
this.value = "aborted";
|
|
44563
45717
|
}
|
|
44564
45718
|
static mergeArray(status, results) {
|
|
44565
|
-
const
|
|
45719
|
+
const arrayValue3 = [];
|
|
44566
45720
|
for (const s2 of results) {
|
|
44567
45721
|
if (s2.status === "aborted")
|
|
44568
45722
|
return INVALID;
|
|
44569
45723
|
if (s2.status === "dirty")
|
|
44570
45724
|
status.dirty();
|
|
44571
|
-
|
|
45725
|
+
arrayValue3.push(s2.value);
|
|
44572
45726
|
}
|
|
44573
|
-
return { status: status.value, value:
|
|
45727
|
+
return { status: status.value, value: arrayValue3 };
|
|
44574
45728
|
}
|
|
44575
45729
|
static async mergeObjectAsync(status, pairs) {
|
|
44576
45730
|
const syncPairs = [];
|
|
@@ -44839,11 +45993,11 @@ var init_types3 = __esm({
|
|
|
44839
45993
|
init_parseUtil();
|
|
44840
45994
|
init_util2();
|
|
44841
45995
|
ParseInputLazyPath = class {
|
|
44842
|
-
constructor(parent, value,
|
|
45996
|
+
constructor(parent, value, path38, key) {
|
|
44843
45997
|
this._cachedPath = [];
|
|
44844
45998
|
this.parent = parent;
|
|
44845
45999
|
this.data = value;
|
|
44846
|
-
this._path =
|
|
46000
|
+
this._path = path38;
|
|
44847
46001
|
this._key = key;
|
|
44848
46002
|
}
|
|
44849
46003
|
get path() {
|
|
@@ -48596,7 +49750,7 @@ function collectCodeMemory(opts) {
|
|
|
48596
49750
|
if (status.indexedAt) lines.push(`Last scan: ${status.indexedAt}`);
|
|
48597
49751
|
if (suggestedReads.length > 0) {
|
|
48598
49752
|
lines.push("Suggested reads:");
|
|
48599
|
-
suggestedReads.forEach((
|
|
49753
|
+
suggestedReads.forEach((path38, index) => lines.push(`${index + 1}. ${path38}`));
|
|
48600
49754
|
}
|
|
48601
49755
|
return lines.join("\n");
|
|
48602
49756
|
} catch {
|
|
@@ -48621,7 +49775,7 @@ __export(planner_exports, {
|
|
|
48621
49775
|
materializeTaskGraph: () => materializeTaskGraph,
|
|
48622
49776
|
seedAutonomousPipeline: () => seedAutonomousPipeline
|
|
48623
49777
|
});
|
|
48624
|
-
import { randomUUID as
|
|
49778
|
+
import { randomUUID as randomUUID13 } from "crypto";
|
|
48625
49779
|
function isPlannerTask(metadata) {
|
|
48626
49780
|
if (!metadata) return null;
|
|
48627
49781
|
try {
|
|
@@ -48679,7 +49833,7 @@ function seedAutonomousPipeline(teamStore, projectId, config2, opts) {
|
|
|
48679
49833
|
const maxIterations = config2.maxIterations ?? 3;
|
|
48680
49834
|
const taskBudget = config2.taskBudget ?? 15;
|
|
48681
49835
|
const structuredPlan = opts?.structuredPlan ?? true;
|
|
48682
|
-
const pipelineId =
|
|
49836
|
+
const pipelineId = randomUUID13();
|
|
48683
49837
|
const meta = {
|
|
48684
49838
|
plannerType: "plan",
|
|
48685
49839
|
pipelineId,
|
|
@@ -49600,7 +50754,7 @@ __export(receipt_service_exports, {
|
|
|
49600
50754
|
});
|
|
49601
50755
|
import { createHash as createHash13 } from "crypto";
|
|
49602
50756
|
import { existsSync as existsSync18, readFileSync as readFileSync12 } from "fs";
|
|
49603
|
-
import
|
|
50757
|
+
import path29 from "path";
|
|
49604
50758
|
function sha256(value) {
|
|
49605
50759
|
return `sha256:${createHash13("sha256").update(value).digest("hex")}`;
|
|
49606
50760
|
}
|
|
@@ -49629,7 +50783,7 @@ function safeJsonArray(value) {
|
|
|
49629
50783
|
}
|
|
49630
50784
|
}
|
|
49631
50785
|
async function loadReceiptObservations(dataDir, projectId) {
|
|
49632
|
-
const dbPath =
|
|
50786
|
+
const dbPath = path29.join(dataDir, "memorix.db");
|
|
49633
50787
|
if (existsSync18(dbPath)) {
|
|
49634
50788
|
try {
|
|
49635
50789
|
const DB = loadBetterSqlite3();
|
|
@@ -49646,7 +50800,7 @@ async function loadReceiptObservations(dataDir, projectId) {
|
|
|
49646
50800
|
} catch {
|
|
49647
50801
|
}
|
|
49648
50802
|
}
|
|
49649
|
-
const jsonPath =
|
|
50803
|
+
const jsonPath = path29.join(dataDir, "observations.json");
|
|
49650
50804
|
if (!existsSync18(jsonPath)) return [];
|
|
49651
50805
|
try {
|
|
49652
50806
|
const parsed = JSON.parse(readFileSync12(jsonPath, "utf-8"));
|
|
@@ -50067,10 +51221,10 @@ function assignProp(target, prop, value) {
|
|
|
50067
51221
|
configurable: true
|
|
50068
51222
|
});
|
|
50069
51223
|
}
|
|
50070
|
-
function getElementAtPath(obj,
|
|
50071
|
-
if (!
|
|
51224
|
+
function getElementAtPath(obj, path38) {
|
|
51225
|
+
if (!path38)
|
|
50072
51226
|
return obj;
|
|
50073
|
-
return
|
|
51227
|
+
return path38.reduce((acc, key) => acc?.[key], obj);
|
|
50074
51228
|
}
|
|
50075
51229
|
function promiseAllObject(promisesObj) {
|
|
50076
51230
|
const keys = Object.keys(promisesObj);
|
|
@@ -50319,11 +51473,11 @@ function aborted(x3, startIndex = 0) {
|
|
|
50319
51473
|
}
|
|
50320
51474
|
return false;
|
|
50321
51475
|
}
|
|
50322
|
-
function prefixIssues(
|
|
51476
|
+
function prefixIssues(path38, issues) {
|
|
50323
51477
|
return issues.map((iss) => {
|
|
50324
51478
|
var _a;
|
|
50325
51479
|
(_a = iss).path ?? (_a.path = []);
|
|
50326
|
-
iss.path.unshift(
|
|
51480
|
+
iss.path.unshift(path38);
|
|
50327
51481
|
return iss;
|
|
50328
51482
|
});
|
|
50329
51483
|
}
|
|
@@ -62629,8 +63783,8 @@ var require_utils2 = __commonJS({
|
|
|
62629
63783
|
}
|
|
62630
63784
|
return ind;
|
|
62631
63785
|
}
|
|
62632
|
-
function removeDotSegments(
|
|
62633
|
-
let input =
|
|
63786
|
+
function removeDotSegments(path38) {
|
|
63787
|
+
let input = path38;
|
|
62634
63788
|
const output = [];
|
|
62635
63789
|
let nextSlash = -1;
|
|
62636
63790
|
let len = 0;
|
|
@@ -62883,8 +64037,8 @@ var require_schemes = __commonJS({
|
|
|
62883
64037
|
wsComponent.secure = void 0;
|
|
62884
64038
|
}
|
|
62885
64039
|
if (wsComponent.resourceName) {
|
|
62886
|
-
const [
|
|
62887
|
-
wsComponent.path =
|
|
64040
|
+
const [path38, query] = wsComponent.resourceName.split("?");
|
|
64041
|
+
wsComponent.path = path38 && path38 !== "/" ? path38 : void 0;
|
|
62888
64042
|
wsComponent.query = query;
|
|
62889
64043
|
wsComponent.resourceName = void 0;
|
|
62890
64044
|
}
|
|
@@ -66323,12 +67477,12 @@ var require_dist = __commonJS({
|
|
|
66323
67477
|
throw new Error(`Unknown format "${name}"`);
|
|
66324
67478
|
return f4;
|
|
66325
67479
|
};
|
|
66326
|
-
function addFormats(ajv, list,
|
|
67480
|
+
function addFormats(ajv, list, fs28, exportName) {
|
|
66327
67481
|
var _a;
|
|
66328
67482
|
var _b;
|
|
66329
67483
|
(_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
66330
67484
|
for (const f4 of list)
|
|
66331
|
-
ajv.addFormat(f4,
|
|
67485
|
+
ajv.addFormat(f4, fs28[f4]);
|
|
66332
67486
|
}
|
|
66333
67487
|
module2.exports = exports2 = formatsPlugin;
|
|
66334
67488
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -68804,8 +69958,8 @@ var syncer_exports = {};
|
|
|
68804
69958
|
__export(syncer_exports, {
|
|
68805
69959
|
RulesSyncer: () => RulesSyncer
|
|
68806
69960
|
});
|
|
68807
|
-
import { promises as
|
|
68808
|
-
import
|
|
69961
|
+
import { promises as fs20 } from "fs";
|
|
69962
|
+
import path30 from "path";
|
|
68809
69963
|
var RulesSyncer;
|
|
68810
69964
|
var init_syncer = __esm({
|
|
68811
69965
|
"src/rules/syncer.ts"() {
|
|
@@ -68850,8 +70004,8 @@ var init_syncer = __esm({
|
|
|
68850
70004
|
const found = await this.findFiles(scanPath);
|
|
68851
70005
|
for (const filePath of found) {
|
|
68852
70006
|
try {
|
|
68853
|
-
const content = await
|
|
68854
|
-
const relativePath =
|
|
70007
|
+
const content = await fs20.readFile(filePath, "utf-8");
|
|
70008
|
+
const relativePath = path30.relative(this.projectRoot, filePath).replace(/\\/g, "/");
|
|
68855
70009
|
const parsed = entry.adapter.parse(relativePath, content);
|
|
68856
70010
|
rules.push(...parsed);
|
|
68857
70011
|
} catch {
|
|
@@ -68919,7 +70073,7 @@ var init_syncer = __esm({
|
|
|
68919
70073
|
const entries = [];
|
|
68920
70074
|
for (const adapter of this.adapters.values()) {
|
|
68921
70075
|
const absolutePaths = adapter.filePatterns.map(
|
|
68922
|
-
(p2) =>
|
|
70076
|
+
(p2) => path30.join(this.projectRoot, p2)
|
|
68923
70077
|
);
|
|
68924
70078
|
entries.push({ adapter, paths: absolutePaths });
|
|
68925
70079
|
}
|
|
@@ -68927,13 +70081,13 @@ var init_syncer = __esm({
|
|
|
68927
70081
|
}
|
|
68928
70082
|
/** Find files matching a glob-like path (simple implementation) */
|
|
68929
70083
|
async findFiles(pattern) {
|
|
68930
|
-
const dir =
|
|
68931
|
-
const fileGlob =
|
|
70084
|
+
const dir = path30.dirname(pattern);
|
|
70085
|
+
const fileGlob = path30.basename(pattern);
|
|
68932
70086
|
try {
|
|
68933
|
-
const stat = await
|
|
70087
|
+
const stat = await fs20.stat(dir);
|
|
68934
70088
|
if (!stat.isDirectory()) {
|
|
68935
70089
|
try {
|
|
68936
|
-
await
|
|
70090
|
+
await fs20.access(pattern);
|
|
68937
70091
|
return [pattern];
|
|
68938
70092
|
} catch {
|
|
68939
70093
|
return [];
|
|
@@ -68941,7 +70095,7 @@ var init_syncer = __esm({
|
|
|
68941
70095
|
}
|
|
68942
70096
|
} catch {
|
|
68943
70097
|
try {
|
|
68944
|
-
await
|
|
70098
|
+
await fs20.access(pattern);
|
|
68945
70099
|
return [pattern];
|
|
68946
70100
|
} catch {
|
|
68947
70101
|
return [];
|
|
@@ -68949,16 +70103,16 @@ var init_syncer = __esm({
|
|
|
68949
70103
|
}
|
|
68950
70104
|
if (fileGlob.includes("*")) {
|
|
68951
70105
|
try {
|
|
68952
|
-
const files = await
|
|
70106
|
+
const files = await fs20.readdir(dir);
|
|
68953
70107
|
const ext = fileGlob.replace("*", "");
|
|
68954
|
-
return files.filter((f4) => ext ? f4.endsWith(ext) : true).map((f4) =>
|
|
70108
|
+
return files.filter((f4) => ext ? f4.endsWith(ext) : true).map((f4) => path30.join(dir, f4));
|
|
68955
70109
|
} catch {
|
|
68956
70110
|
return [];
|
|
68957
70111
|
}
|
|
68958
70112
|
}
|
|
68959
70113
|
try {
|
|
68960
|
-
await
|
|
68961
|
-
return [
|
|
70114
|
+
await fs20.access(path30.join(dir, fileGlob));
|
|
70115
|
+
return [path30.join(dir, fileGlob)];
|
|
68962
70116
|
} catch {
|
|
68963
70117
|
return [];
|
|
68964
70118
|
}
|
|
@@ -69193,10 +70347,10 @@ var init_engine3 = __esm({
|
|
|
69193
70347
|
pathsToCheck.push(join25(homedir29(), ".gemini", "antigravity", "mcp_config.json"));
|
|
69194
70348
|
}
|
|
69195
70349
|
const merged = /* @__PURE__ */ new Map();
|
|
69196
|
-
for (const
|
|
69197
|
-
if (existsSync20(
|
|
70350
|
+
for (const path38 of pathsToCheck) {
|
|
70351
|
+
if (existsSync20(path38)) {
|
|
69198
70352
|
try {
|
|
69199
|
-
const content = readFileSync13(
|
|
70353
|
+
const content = readFileSync13(path38, "utf-8");
|
|
69200
70354
|
const servers = adapter.parse(content);
|
|
69201
70355
|
for (const s2 of servers) {
|
|
69202
70356
|
if (!merged.has(s2.name)) merged.set(s2.name, s2);
|
|
@@ -70173,8 +71327,8 @@ __export(server_exports, {
|
|
|
70173
71327
|
startDashboard: () => startDashboard
|
|
70174
71328
|
});
|
|
70175
71329
|
import { createServer } from "http";
|
|
70176
|
-
import { promises as
|
|
70177
|
-
import
|
|
71330
|
+
import { promises as fs21 } from "fs";
|
|
71331
|
+
import path31 from "path";
|
|
70178
71332
|
import { exec } from "child_process";
|
|
70179
71333
|
function sendJson(res, data, status = 200) {
|
|
70180
71334
|
res.writeHead(status, {
|
|
@@ -70652,7 +71806,7 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
70652
71806
|
const aliasModule = await Promise.resolve().then(() => (init_aliases(), aliases_exports));
|
|
70653
71807
|
canonicalId = await aliasModule.getCanonicalId(effectiveProjectId);
|
|
70654
71808
|
const { promises: fsP } = await import("fs");
|
|
70655
|
-
const registryPath =
|
|
71809
|
+
const registryPath = path31.join(baseDir, ".project-aliases.json");
|
|
70656
71810
|
const raw = await fsP.readFile(registryPath, "utf-8");
|
|
70657
71811
|
const registry2 = JSON.parse(raw);
|
|
70658
71812
|
aliasGroups = registry2.groups || [];
|
|
@@ -70767,14 +71921,14 @@ async function serveStatic(req, res, staticDir) {
|
|
|
70767
71921
|
if (urlPath === "/" || !urlPath.includes(".")) {
|
|
70768
71922
|
urlPath = "/index.html";
|
|
70769
71923
|
}
|
|
70770
|
-
const filePath =
|
|
71924
|
+
const filePath = path31.join(staticDir, urlPath);
|
|
70771
71925
|
if (!filePath.startsWith(staticDir)) {
|
|
70772
71926
|
sendError(res, "Forbidden", 403);
|
|
70773
71927
|
return;
|
|
70774
71928
|
}
|
|
70775
71929
|
try {
|
|
70776
|
-
const data = await
|
|
70777
|
-
const ext =
|
|
71930
|
+
const data = await fs21.readFile(filePath);
|
|
71931
|
+
const ext = path31.extname(filePath);
|
|
70778
71932
|
res.writeHead(200, {
|
|
70779
71933
|
"Content-Type": MIME_TYPES[ext] || "application/octet-stream",
|
|
70780
71934
|
"Cache-Control": "no-store, no-cache, must-revalidate, max-age=0",
|
|
@@ -70784,7 +71938,7 @@ async function serveStatic(req, res, staticDir) {
|
|
|
70784
71938
|
res.end(data);
|
|
70785
71939
|
} catch {
|
|
70786
71940
|
try {
|
|
70787
|
-
const indexData = await
|
|
71941
|
+
const indexData = await fs21.readFile(path31.join(staticDir, "index.html"));
|
|
70788
71942
|
res.writeHead(200, {
|
|
70789
71943
|
"Content-Type": "text/html; charset=utf-8",
|
|
70790
71944
|
"Cache-Control": "no-store, no-cache, must-revalidate, max-age=0",
|
|
@@ -71225,9 +72379,9 @@ __export(hooks_path_exports, {
|
|
|
71225
72379
|
resolveHooksDir: () => resolveHooksDir
|
|
71226
72380
|
});
|
|
71227
72381
|
import { existsSync as existsSync22, readFileSync as readFileSync15, statSync as statSync5, mkdirSync as mkdirSync6 } from "fs";
|
|
71228
|
-
import
|
|
72382
|
+
import path32 from "path";
|
|
71229
72383
|
function resolveGitDir(projectRoot) {
|
|
71230
|
-
const dotGit =
|
|
72384
|
+
const dotGit = path32.join(projectRoot, ".git");
|
|
71231
72385
|
if (!existsSync22(dotGit)) return null;
|
|
71232
72386
|
const stat = statSync5(dotGit);
|
|
71233
72387
|
if (stat.isDirectory()) {
|
|
@@ -71239,7 +72393,7 @@ function resolveGitDir(projectRoot) {
|
|
|
71239
72393
|
const match = content.match(/^gitdir:\s*(.+)$/);
|
|
71240
72394
|
if (match) {
|
|
71241
72395
|
const gitdir = match[1].trim();
|
|
71242
|
-
const resolved =
|
|
72396
|
+
const resolved = path32.isAbsolute(gitdir) ? gitdir : path32.resolve(projectRoot, gitdir);
|
|
71243
72397
|
if (existsSync22(resolved)) {
|
|
71244
72398
|
return resolved;
|
|
71245
72399
|
}
|
|
@@ -71252,10 +72406,10 @@ function resolveGitDir(projectRoot) {
|
|
|
71252
72406
|
function resolveHooksDir(projectRoot) {
|
|
71253
72407
|
const gitDir = resolveGitDir(projectRoot);
|
|
71254
72408
|
if (!gitDir) return null;
|
|
71255
|
-
const hooksDir =
|
|
72409
|
+
const hooksDir = path32.join(gitDir, "hooks");
|
|
71256
72410
|
return {
|
|
71257
72411
|
hooksDir,
|
|
71258
|
-
hookPath:
|
|
72412
|
+
hookPath: path32.join(hooksDir, "post-commit")
|
|
71259
72413
|
};
|
|
71260
72414
|
}
|
|
71261
72415
|
function ensureHooksDir(projectRoot) {
|
|
@@ -71633,7 +72787,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
71633
72787
|
};
|
|
71634
72788
|
const server = existingServer ?? new McpServer({
|
|
71635
72789
|
name: "memorix",
|
|
71636
|
-
version: true ? "1.
|
|
72790
|
+
version: true ? "1.3.0" : "1.0.1"
|
|
71637
72791
|
});
|
|
71638
72792
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
71639
72793
|
server.registerTool = ((name, ...args) => {
|
|
@@ -71713,7 +72867,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
71713
72867
|
"memorix_store",
|
|
71714
72868
|
{
|
|
71715
72869
|
title: "Store Memory",
|
|
71716
|
-
description: "Store a new observation/memory. Automatically indexed for search. Use type to classify: gotcha ([GOTCHA] critical pitfall), decision ([DECISION] architecture choice), problem-solution ([FIX] bug fix), how-it-works ([INFO] explanation), what-changed ([CHANGE] change), discovery ([DISCOVERY] insight), why-it-exists ([WHY] rationale), trade-off ([TRADEOFF] compromise), session-request ([SESSION] original goal). Project visibility is the default. Personal or team visibility requires an explicitly joined coordination identity. For a read-only task, do not store unless the user explicitly asks to save a record.",
|
|
72870
|
+
description: "Store a new observation/memory. Automatically indexed for search. Use type to classify: gotcha ([GOTCHA] critical pitfall), decision ([DECISION] architecture choice), problem-solution ([FIX] bug fix), how-it-works ([INFO] explanation), what-changed ([CHANGE] change), discovery ([DISCOVERY] insight), why-it-exists ([WHY] rationale), trade-off ([TRADEOFF] compromise), session-request ([SESSION] original goal). Project visibility is the default. Personal or team visibility requires an explicitly joined coordination identity. Set longTerm only when the caller explicitly wants an additional source-backed long-term candidate; it is never injected until an operator records a review through the CLI. For a read-only task, do not store unless the user explicitly asks to save a record.",
|
|
71717
72871
|
inputSchema: {
|
|
71718
72872
|
entityName: external_exports.string().describe('The entity this observation belongs to (e.g., "auth-module", "port-config")'),
|
|
71719
72873
|
type: external_exports.enum(OBSERVATION_TYPES2).describe("Observation type for classification"),
|
|
@@ -71735,30 +72889,43 @@ The path should point to a directory containing a .git folder.`
|
|
|
71735
72889
|
visibility: external_exports.enum(["personal", "project", "team"]).optional().describe(
|
|
71736
72890
|
"Retrieval scope. Project is the normal shared default; personal/team require memorix_session_start with joinTeam=true."
|
|
71737
72891
|
),
|
|
72892
|
+
longTerm: external_exports.object({
|
|
72893
|
+
kind: external_exports.enum(["episodic", "semantic", "procedural"]).describe("Cognitive kind for an additional long-term candidate."),
|
|
72894
|
+
scope: external_exports.enum(["project", "user", "team"]).optional().default("project").describe("Long-term scope. User capture is private source evidence and needs a bound agent identity."),
|
|
72895
|
+
tags: external_exports.array(external_exports.string()).optional().describe("Small set of retrieval tags for the candidate."),
|
|
72896
|
+
applicability: external_exports.string().optional().describe("When this durable fact or procedure applies.")
|
|
72897
|
+
}).optional().describe("Optional explicit request to create a source-backed long-term candidate alongside this observation. Candidates are not automatically injected."),
|
|
71738
72898
|
overrideReadOnly: external_exports.boolean().optional().describe(
|
|
71739
72899
|
"Use only when the user explicitly asks to save memory during a read-only or no-modification task."
|
|
71740
72900
|
)
|
|
71741
72901
|
}
|
|
71742
72902
|
},
|
|
71743
|
-
async ({ entityName: rawEntityName, type: rawType, title: rawTitle, narrative, facts, filesModified, concepts, topicKey, progress, relatedCommits, relatedEntities, visibility, overrideReadOnly }) => {
|
|
72903
|
+
async ({ entityName: rawEntityName, type: rawType, title: rawTitle, narrative, facts, filesModified, concepts, topicKey, progress, relatedCommits, relatedEntities, visibility, longTerm, overrideReadOnly }) => {
|
|
71744
72904
|
const unresolved = requireResolvedProject("store memory in the current project");
|
|
71745
72905
|
if (unresolved) return unresolved;
|
|
71746
72906
|
const readOnlyBoundary = blockReadOnlyAutopilotWrite(overrideReadOnly);
|
|
71747
72907
|
if (readOnlyBoundary) return readOnlyBoundary;
|
|
71748
|
-
const requestedVisibility =
|
|
72908
|
+
const requestedVisibility = longTerm?.scope === "user" ? "personal" : longTerm?.scope === "team" ? "team" : visibility;
|
|
72909
|
+
const effectiveVisibility = requestedVisibility ?? "project";
|
|
71749
72910
|
const reader = getObservationReader();
|
|
71750
|
-
if (
|
|
72911
|
+
if (effectiveVisibility !== "project" && !currentAgentId) {
|
|
71751
72912
|
return {
|
|
71752
72913
|
content: [{ type: "text", text: "Personal or team memory requires memorix_session_start with joinTeam=true so Memorix can bind an owner." }],
|
|
71753
72914
|
isError: true
|
|
71754
72915
|
};
|
|
71755
72916
|
}
|
|
71756
|
-
if (
|
|
72917
|
+
if (effectiveVisibility === "team" && !reader.isTeamMember) {
|
|
71757
72918
|
return {
|
|
71758
72919
|
content: [{ type: "text", text: "Team memory requires an active coordination membership in the current project." }],
|
|
71759
72920
|
isError: true
|
|
71760
72921
|
};
|
|
71761
72922
|
}
|
|
72923
|
+
if (longTerm?.scope === "team" && !reader.isTeamMember) {
|
|
72924
|
+
return {
|
|
72925
|
+
content: [{ type: "text", text: "Team long-term memory requires an active coordination membership in the current project." }],
|
|
72926
|
+
isError: true
|
|
72927
|
+
};
|
|
72928
|
+
}
|
|
71762
72929
|
try {
|
|
71763
72930
|
return await withFreshIndex(async () => {
|
|
71764
72931
|
let entityName = rawEntityName;
|
|
@@ -71780,7 +72947,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
71780
72947
|
const useFormation = formationMode === "active";
|
|
71781
72948
|
let formationResult = null;
|
|
71782
72949
|
let formationNote = "";
|
|
71783
|
-
if (useFormation && !topicKey && !progress) {
|
|
72950
|
+
if (useFormation && !topicKey && !progress && !longTerm) {
|
|
71784
72951
|
let currentFormationStage = "setup";
|
|
71785
72952
|
const completedFormationStages = {};
|
|
71786
72953
|
const formationStartTime = Date.now();
|
|
@@ -71931,7 +73098,7 @@ ${modeIcon} Formation[active]: ${formationResult.evaluation.category} (${formati
|
|
|
71931
73098
|
}
|
|
71932
73099
|
let compactAction = "";
|
|
71933
73100
|
let compactMerged = false;
|
|
71934
|
-
if (!useFormation && !topicKey && !progress) {
|
|
73101
|
+
if (!useFormation && !topicKey && !progress && !longTerm) {
|
|
71935
73102
|
try {
|
|
71936
73103
|
const searchResult = await compactSearch({
|
|
71937
73104
|
query: `${title} ${narrative.substring(0, 200)}`,
|
|
@@ -72088,9 +73255,33 @@ Mode: ${decision.usedLLM ? "LLM" : "heuristic"}`
|
|
|
72088
73255
|
sourceDetail: "explicit",
|
|
72089
73256
|
valueCategory: formationResult?.evaluation.category,
|
|
72090
73257
|
createdByAgentId: currentAgentId,
|
|
72091
|
-
visibility,
|
|
73258
|
+
visibility: requestedVisibility,
|
|
72092
73259
|
visibilityReader: reader
|
|
72093
73260
|
});
|
|
73261
|
+
let longTermNote = "";
|
|
73262
|
+
if (longTerm) {
|
|
73263
|
+
try {
|
|
73264
|
+
const { promoteObservationToLongTermMemory: promoteObservationToLongTermMemory2 } = await Promise.resolve().then(() => (init_long_term(), long_term_exports));
|
|
73265
|
+
const promoted = await promoteObservationToLongTermMemory2({
|
|
73266
|
+
dataDir: projectDir2,
|
|
73267
|
+
observation: obs,
|
|
73268
|
+
scope: longTerm.scope,
|
|
73269
|
+
kind: longTerm.kind,
|
|
73270
|
+
tags: longTerm.tags,
|
|
73271
|
+
applicability: longTerm.applicability,
|
|
73272
|
+
reader: {
|
|
73273
|
+
projectId: project.id,
|
|
73274
|
+
...reader.agentId ? { agentId: reader.agentId } : {},
|
|
73275
|
+
...reader.isTeamMember ? { isTeamMember: true } : {}
|
|
73276
|
+
}
|
|
73277
|
+
});
|
|
73278
|
+
longTermNote = `
|
|
73279
|
+
Long-term candidate: ${promoted.memory.id} (${promoted.memory.kind}/${promoted.memory.scope}). Review it with the CLI before it is delivered automatically.`;
|
|
73280
|
+
} catch (longTermError) {
|
|
73281
|
+
longTermNote = `
|
|
73282
|
+
[WARN] Observation stored, but long-term candidate was not created: ${longTermError instanceof Error ? longTermError.message : "unknown error"}`;
|
|
73283
|
+
}
|
|
73284
|
+
}
|
|
72094
73285
|
await graphManager.addObservations([
|
|
72095
73286
|
{ entityName, contents: [`[#${obs.id}] ${title}`] }
|
|
72096
73287
|
]);
|
|
@@ -72107,7 +73298,7 @@ Mode: ${decision.usedLLM ? "LLM" : "heuristic"}`
|
|
|
72107
73298
|
const enrichment = enrichmentParts.length > 0 ? `
|
|
72108
73299
|
Auto-enriched: ${enrichmentParts.join(", ")}` : "";
|
|
72109
73300
|
const action = upserted ? "[UPDATED] Updated" : "[OK] Stored";
|
|
72110
|
-
if (!useFormation && !topicKey && !progress) {
|
|
73301
|
+
if (!useFormation && !topicKey && !progress && !longTerm) {
|
|
72111
73302
|
const shadowFormation = async () => {
|
|
72112
73303
|
let oldCompactDecision = null;
|
|
72113
73304
|
try {
|
|
@@ -72197,7 +73388,7 @@ Auto-enriched: ${enrichmentParts.join(", ")}` : "";
|
|
|
72197
73388
|
{
|
|
72198
73389
|
type: "text",
|
|
72199
73390
|
text: `${action} observation #${obs.id} "${title}" (~${obs.tokens} tokens)
|
|
72200
|
-
Entity: ${entityName} | Type: ${type} | Project: ${project.id}${obs.topicKey ? ` | Topic: ${obs.topicKey}` : ""}${compactAction}${compressionNote}${enrichment}${formationNote}${attributionWarning}`
|
|
73391
|
+
Entity: ${entityName} | Type: ${type} | Project: ${project.id}${obs.topicKey ? ` | Topic: ${obs.topicKey}` : ""}${compactAction}${compressionNote}${enrichment}${formationNote}${attributionWarning}${longTermNote}`
|
|
72201
73392
|
}
|
|
72202
73393
|
]
|
|
72203
73394
|
};
|
|
@@ -72570,7 +73761,8 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
72570
73761
|
} : {},
|
|
72571
73762
|
...external.outline ? { semanticCode: external.outline } : {},
|
|
72572
73763
|
providerQuality: external.quality,
|
|
72573
|
-
...external.caution ? { runtimeCautions: [{ kind: "external-codegraph-fallback", message: external.caution }] } : {}
|
|
73764
|
+
...external.caution ? { runtimeCautions: [{ kind: "external-codegraph-fallback", message: external.caution }] } : {},
|
|
73765
|
+
reader: getObservationReader()
|
|
72574
73766
|
});
|
|
72575
73767
|
const text = buildContextPackPrompt2(pack);
|
|
72576
73768
|
return {
|
|
@@ -73244,7 +74436,7 @@ ${actions.join("\n")}`
|
|
|
73244
74436
|
"memorix_detail",
|
|
73245
74437
|
{
|
|
73246
74438
|
title: "Memory Details",
|
|
73247
|
-
description: 'Fetch full observation
|
|
74439
|
+
description: 'Fetch full observation, mini-skill, or curated durable-memory details \u2014 includes source kind (explicit memory / hook trace / git evidence), value category, and cross-references (~500-1000 tokens each). Do not re-fetch content already covered by a complete memorix_project_context brief unless a specific fact is still missing or the user asks for deeper history; provide purpose when intentionally expanding. Always use memorix_search first to find relevant IDs, then fetch only what you need. Accepts typed refs from search results (e.g. "obs:42", "skill:3") and durable refs from a project brief (e.g. "durable:<uuid>") via the typedRefs field, or legacy numeric ids / object refs for backward compatibility.',
|
|
73248
74440
|
inputSchema: {
|
|
73249
74441
|
ids: external_exports.array(external_exports.number()).optional().describe("Observation IDs to fetch (legacy, from memorix_search results)"),
|
|
73250
74442
|
refs: external_exports.array(
|
|
@@ -73253,7 +74445,7 @@ ${actions.join("\n")}`
|
|
|
73253
74445
|
projectId: external_exports.string().optional().describe("Project ID for global-search disambiguation")
|
|
73254
74446
|
})
|
|
73255
74447
|
).optional().describe("Explicit observation refs. Prefer this for global search results."),
|
|
73256
|
-
typedRefs: external_exports.array(external_exports.string()).optional().describe('Typed memory refs from search results, e.g. "obs:42", "skill:3", "obs:42@org/proj"'),
|
|
74448
|
+
typedRefs: external_exports.array(external_exports.string()).optional().describe('Typed memory refs from search results or a project brief, e.g. "obs:42", "skill:3", "durable:<uuid>", "obs:42@org/proj"'),
|
|
73257
74449
|
purpose: external_exports.string().optional().describe(
|
|
73258
74450
|
"Why this must expand beyond the latest Autopilot brief. Name the missing fact or the user's explicit request."
|
|
73259
74451
|
),
|
|
@@ -73266,14 +74458,19 @@ ${actions.join("\n")}`
|
|
|
73266
74458
|
const safeIds = coerceNumberArray(ids);
|
|
73267
74459
|
const safeRefs = coerceObservationRefs(refs);
|
|
73268
74460
|
const safeTypedRefs = coerceStringArray(typedRefs);
|
|
73269
|
-
const
|
|
74461
|
+
const durableIds = safeTypedRefs.flatMap((ref) => {
|
|
74462
|
+
const match = /^durable:([0-9a-f-]{36})$/i.exec(ref.trim());
|
|
74463
|
+
return match ? [match[1]] : [];
|
|
74464
|
+
});
|
|
74465
|
+
const observationTypedRefs = safeTypedRefs.filter((ref) => !/^durable:/i.test(ref.trim()));
|
|
74466
|
+
const hasCrossProjectRef = safeRefs.some((ref) => ref.projectId && ref.projectId !== project.id) || observationTypedRefs.some((ref) => ref.includes("@") && !ref.endsWith(`@${project.id}`));
|
|
73270
74467
|
if (!hasCrossProjectRef) {
|
|
73271
74468
|
const boundary = requireExplicitAutopilotExpansion("memorix_detail", purpose);
|
|
73272
74469
|
if (boundary) return boundary;
|
|
73273
74470
|
const requestedObservationIds = [
|
|
73274
74471
|
...safeIds,
|
|
73275
74472
|
...safeRefs.map((ref) => ref.id),
|
|
73276
|
-
...
|
|
74473
|
+
...observationTypedRefs.flatMap((ref) => {
|
|
73277
74474
|
const match = /^obs:(\d+)(?:@.+)?$/i.exec(ref.trim());
|
|
73278
74475
|
return match ? [Number(match[1])] : [];
|
|
73279
74476
|
})
|
|
@@ -73281,15 +74478,36 @@ ${actions.join("\n")}`
|
|
|
73281
74478
|
const duplicate = blockCoveredAutopilotEvidence("memorix_detail", requestedObservationIds, force);
|
|
73282
74479
|
if (duplicate) return duplicate;
|
|
73283
74480
|
}
|
|
73284
|
-
|
|
74481
|
+
const formatted = [];
|
|
73285
74482
|
try {
|
|
73286
|
-
|
|
73287
|
-
|
|
73288
|
-
|
|
73289
|
-
|
|
73290
|
-
|
|
73291
|
-
|
|
73292
|
-
|
|
74483
|
+
if (durableIds.length > 0) {
|
|
74484
|
+
const [{ getLongTermMemoryDetail: getLongTermMemoryDetail2 }, { resolveLocalMemoryOwner: resolveLocalMemoryOwner2 }] = await Promise.all([
|
|
74485
|
+
Promise.resolve().then(() => (init_long_term(), long_term_exports)),
|
|
74486
|
+
Promise.resolve().then(() => (init_owner(), owner_exports))
|
|
74487
|
+
]);
|
|
74488
|
+
const owner = await resolveLocalMemoryOwner2(projectDir2, { create: false });
|
|
74489
|
+
const observationReader = getObservationReader();
|
|
74490
|
+
const durableReader = {
|
|
74491
|
+
projectId: project.id,
|
|
74492
|
+
...owner ? { ownerId: owner.id } : {},
|
|
74493
|
+
...observationReader.agentId ? { agentId: observationReader.agentId } : {},
|
|
74494
|
+
...observationReader.isTeamMember ? { isTeamMember: true } : {}
|
|
74495
|
+
};
|
|
74496
|
+
const details = await Promise.all(durableIds.slice(0, 5).map(async (id) => {
|
|
74497
|
+
try {
|
|
74498
|
+
return await getLongTermMemoryDetail2({ dataDir: projectDir2, id, reader: durableReader });
|
|
74499
|
+
} catch (error2) {
|
|
74500
|
+
return { error: error2 instanceof Error ? error2.message : String(error2), id };
|
|
74501
|
+
}
|
|
74502
|
+
}));
|
|
74503
|
+
formatted.push(JSON.stringify({ durableMemory: details }, null, 2));
|
|
74504
|
+
}
|
|
74505
|
+
if (observationTypedRefs.length > 0 || safeRefs.length > 0 || safeIds.length > 0) {
|
|
74506
|
+
const reader = getObservationReader(hasCrossProjectRef ? "global" : "project");
|
|
74507
|
+
const result = observationTypedRefs.length > 0 ? await compactDetail(observationTypedRefs, { reader }) : safeRefs.length > 0 ? await compactDetail(safeRefs, { reader }) : await compactDetail(safeIds.map((id) => ({ id, projectId: project.id })), { reader });
|
|
74508
|
+
formatted.push(
|
|
74509
|
+
result.documents.length > 0 ? result.formatted : observationTypedRefs.length > 0 ? `No memories found for refs: ${observationTypedRefs.join(", ")}` : safeRefs.length > 0 ? `No memories found for refs: ${safeRefs.map((ref) => `${ref.projectId ?? "current"}#${ref.id}`).join(", ")}` : `No memories found for IDs: ${safeIds.join(", ")}`
|
|
74510
|
+
);
|
|
73293
74511
|
}
|
|
73294
74512
|
} catch (err) {
|
|
73295
74513
|
return { content: [{ type: "text", text: err instanceof Error ? err.message : String(err) }], isError: true };
|
|
@@ -73298,7 +74516,7 @@ ${actions.join("\n")}`
|
|
|
73298
74516
|
content: [
|
|
73299
74517
|
{
|
|
73300
74518
|
type: "text",
|
|
73301
|
-
text:
|
|
74519
|
+
text: formatted.length > 0 ? formatted.join("\n\n") : safeTypedRefs.length > 0 ? `No memories found for refs: ${safeTypedRefs.join(", ")}` : safeRefs.length > 0 ? `No memories found for refs: ${safeRefs.map((ref) => `${ref.projectId ?? "current"}#${ref.id}`).join(", ")}` : `No memories found for IDs: ${safeIds.join(", ")}`
|
|
73302
74520
|
}
|
|
73303
74521
|
]
|
|
73304
74522
|
};
|
|
@@ -74018,9 +75236,9 @@ ${skill2.content}` }]
|
|
|
74018
75236
|
lines.push(`- **Description**: ${sk.description}`);
|
|
74019
75237
|
lines.push(`- **Observations**: ${sk.content.split("\n").length} lines of knowledge`);
|
|
74020
75238
|
if (write && target) {
|
|
74021
|
-
const
|
|
74022
|
-
if (
|
|
74023
|
-
lines.push(`- [OK] **Written**: \`${
|
|
75239
|
+
const path38 = engine.writeSkill(sk, target);
|
|
75240
|
+
if (path38) {
|
|
75241
|
+
lines.push(`- [OK] **Written**: \`${path38}\``);
|
|
74024
75242
|
} else {
|
|
74025
75243
|
lines.push(`- [ERROR] Failed to write`);
|
|
74026
75244
|
}
|
|
@@ -75852,8 +77070,8 @@ var init_serve = __esm({
|
|
|
75852
77070
|
safeCwd = homedir34();
|
|
75853
77071
|
}
|
|
75854
77072
|
const { existsSync: existsSync31, readFileSync: readFileSync23 } = await import("fs");
|
|
75855
|
-
const
|
|
75856
|
-
const lastRootFile =
|
|
77073
|
+
const path38 = await import("path");
|
|
77074
|
+
const lastRootFile = path38.join(homedir34(), ".memorix", "last-project-root");
|
|
75857
77075
|
let lastKnownProjectRoot;
|
|
75858
77076
|
if (existsSync31(lastRootFile)) {
|
|
75859
77077
|
try {
|
|
@@ -75888,9 +77106,9 @@ var init_serve = __esm({
|
|
|
75888
77106
|
if (detected) {
|
|
75889
77107
|
try {
|
|
75890
77108
|
const { writeFileSync: writeFileSync11, mkdirSync: mkdirSync11 } = await import("fs");
|
|
75891
|
-
const memorixDir =
|
|
77109
|
+
const memorixDir = path38.join(homedir34(), ".memorix");
|
|
75892
77110
|
mkdirSync11(memorixDir, { recursive: true });
|
|
75893
|
-
writeFileSync11(
|
|
77111
|
+
writeFileSync11(path38.join(memorixDir, "last-project-root"), detected.rootPath, "utf-8");
|
|
75894
77112
|
} catch {
|
|
75895
77113
|
}
|
|
75896
77114
|
}
|
|
@@ -77431,7 +78649,7 @@ var init_serve_http = __esm({
|
|
|
77431
78649
|
},
|
|
77432
78650
|
run: async ({ args }) => {
|
|
77433
78651
|
const { createServer: createServer2 } = await import("http");
|
|
77434
|
-
const { randomUUID:
|
|
78652
|
+
const { randomUUID: randomUUID14 } = await import("crypto");
|
|
77435
78653
|
const { StreamableHTTPServerTransport: StreamableHTTPServerTransport2 } = await Promise.resolve().then(() => (init_streamableHttp(), streamableHttp_exports));
|
|
77436
78654
|
const { isInitializeRequest: isInitializeRequest2 } = await Promise.resolve().then(() => (init_types4(), types_exports));
|
|
77437
78655
|
const { createMemorixServer: createMemorixServer2 } = await Promise.resolve().then(() => (init_server4(), server_exports2));
|
|
@@ -77615,7 +78833,7 @@ var init_serve_http = __esm({
|
|
|
77615
78833
|
if (!sessionId && isInitializeRequest2(body)) {
|
|
77616
78834
|
let createdState = null;
|
|
77617
78835
|
const transport = new StreamableHTTPServerTransport2({
|
|
77618
|
-
sessionIdGenerator: () =>
|
|
78836
|
+
sessionIdGenerator: () => randomUUID14(),
|
|
77619
78837
|
enableJsonResponse: true,
|
|
77620
78838
|
onsessioninitialized: (sid) => {
|
|
77621
78839
|
if (createdState) sessions.set(sid, createdState);
|
|
@@ -78982,8 +80200,8 @@ var init_sync = __esm({
|
|
|
78982
80200
|
}
|
|
78983
80201
|
const { detectProject: detectProject2 } = await Promise.resolve().then(() => (init_detector(), detector_exports));
|
|
78984
80202
|
const { RulesSyncer: RulesSyncer2 } = await Promise.resolve().then(() => (init_syncer(), syncer_exports));
|
|
78985
|
-
const { promises:
|
|
78986
|
-
const
|
|
80203
|
+
const { promises: fs28 } = await import("fs");
|
|
80204
|
+
const path38 = await import("path");
|
|
78987
80205
|
we("memorix sync");
|
|
78988
80206
|
const project = detectProject2();
|
|
78989
80207
|
if (!project) {
|
|
@@ -79055,9 +80273,9 @@ var init_sync = __esm({
|
|
|
79055
80273
|
process.exit(0);
|
|
79056
80274
|
}
|
|
79057
80275
|
for (const file of files) {
|
|
79058
|
-
const fullPath =
|
|
79059
|
-
await
|
|
79060
|
-
await
|
|
80276
|
+
const fullPath = path38.join(project.rootPath, file.filePath);
|
|
80277
|
+
await fs28.mkdir(path38.dirname(fullPath), { recursive: true });
|
|
80278
|
+
await fs28.writeFile(fullPath, file.content, "utf-8");
|
|
79061
80279
|
v3.success(`Written: ${file.filePath}`);
|
|
79062
80280
|
}
|
|
79063
80281
|
fe2(`Synced ${files.length} rule(s) to ${target} format`);
|
|
@@ -80944,8 +82162,8 @@ var hooks_preview_exports = {};
|
|
|
80944
82162
|
__export(hooks_preview_exports, {
|
|
80945
82163
|
default: () => hooks_preview_default
|
|
80946
82164
|
});
|
|
80947
|
-
import * as
|
|
80948
|
-
import * as
|
|
82165
|
+
import * as fs22 from "fs/promises";
|
|
82166
|
+
import * as path33 from "path";
|
|
80949
82167
|
function estimateFileSize(agent, configPath) {
|
|
80950
82168
|
const sizes = {
|
|
80951
82169
|
claude: "~2KB",
|
|
@@ -80965,30 +82183,30 @@ function getRulesPath(agent, cwd, global2) {
|
|
|
80965
82183
|
if (global2) {
|
|
80966
82184
|
switch (agent) {
|
|
80967
82185
|
case "cursor":
|
|
80968
|
-
return
|
|
82186
|
+
return path33.join(home, ".cursor", "rules", "memorix.mdc");
|
|
80969
82187
|
case "codex":
|
|
80970
|
-
return
|
|
82188
|
+
return path33.join(home, ".codex", "AGENTS.md");
|
|
80971
82189
|
case "opencode":
|
|
80972
|
-
return
|
|
82190
|
+
return path33.join(home, ".config", "opencode", "AGENTS.md");
|
|
80973
82191
|
case "antigravity":
|
|
80974
|
-
return
|
|
82192
|
+
return path33.join(home, ".gemini", "GEMINI.md");
|
|
80975
82193
|
case "trae":
|
|
80976
|
-
return
|
|
82194
|
+
return path33.join(home, ".trae", "rules", "project_rules.md");
|
|
80977
82195
|
default:
|
|
80978
82196
|
return "";
|
|
80979
82197
|
}
|
|
80980
82198
|
} else {
|
|
80981
82199
|
switch (agent) {
|
|
80982
82200
|
case "cursor":
|
|
80983
|
-
return
|
|
82201
|
+
return path33.join(cwd, ".cursor", "rules", "memorix.mdc");
|
|
80984
82202
|
case "codex":
|
|
80985
|
-
return
|
|
82203
|
+
return path33.join(cwd, "AGENTS.md");
|
|
80986
82204
|
case "opencode":
|
|
80987
|
-
return
|
|
82205
|
+
return path33.join(cwd, "AGENTS.md");
|
|
80988
82206
|
case "antigravity":
|
|
80989
|
-
return
|
|
82207
|
+
return path33.join(cwd, "GEMINI.md");
|
|
80990
82208
|
case "trae":
|
|
80991
|
-
return
|
|
82209
|
+
return path33.join(cwd, ".trae", "rules", "project_rules.md");
|
|
80992
82210
|
default:
|
|
80993
82211
|
return "";
|
|
80994
82212
|
}
|
|
@@ -81045,7 +82263,7 @@ var init_hooks_preview = __esm({
|
|
|
81045
82263
|
const configPath = global2 ? getGlobalConfigPath2(agent) : getProjectConfigPath2(agent, cwd);
|
|
81046
82264
|
let action;
|
|
81047
82265
|
try {
|
|
81048
|
-
await
|
|
82266
|
+
await fs22.access(configPath);
|
|
81049
82267
|
action = "modify";
|
|
81050
82268
|
} catch {
|
|
81051
82269
|
action = "create";
|
|
@@ -81060,7 +82278,7 @@ var init_hooks_preview = __esm({
|
|
|
81060
82278
|
if (["cursor", "codex", "opencode", "antigravity", "trae"].includes(agent)) {
|
|
81061
82279
|
const rulesPath = getRulesPath(agent, cwd, global2);
|
|
81062
82280
|
try {
|
|
81063
|
-
await
|
|
82281
|
+
await fs22.access(rulesPath);
|
|
81064
82282
|
previewItems.push({
|
|
81065
82283
|
agent,
|
|
81066
82284
|
path: rulesPath,
|
|
@@ -81077,10 +82295,10 @@ var init_hooks_preview = __esm({
|
|
|
81077
82295
|
}
|
|
81078
82296
|
}
|
|
81079
82297
|
if (agent === "kiro") {
|
|
81080
|
-
const hooksDir =
|
|
82298
|
+
const hooksDir = path33.dirname(configPath);
|
|
81081
82299
|
previewItems.push({
|
|
81082
82300
|
agent,
|
|
81083
|
-
path:
|
|
82301
|
+
path: path33.join(hooksDir, "*.kiro.hook"),
|
|
81084
82302
|
action: "create",
|
|
81085
82303
|
size: "~500B each"
|
|
81086
82304
|
});
|
|
@@ -81851,9 +83069,9 @@ __export(ingest_image_exports, {
|
|
|
81851
83069
|
default: () => ingest_image_default
|
|
81852
83070
|
});
|
|
81853
83071
|
import { readFileSync as readFileSync16 } from "fs";
|
|
81854
|
-
import
|
|
83072
|
+
import path34 from "path";
|
|
81855
83073
|
function inferMimeType(filePath) {
|
|
81856
|
-
const ext =
|
|
83074
|
+
const ext = path34.extname(filePath).toLowerCase();
|
|
81857
83075
|
switch (ext) {
|
|
81858
83076
|
case ".jpg":
|
|
81859
83077
|
case ".jpeg":
|
|
@@ -81896,9 +83114,9 @@ var init_ingest_image = __esm({
|
|
|
81896
83114
|
return;
|
|
81897
83115
|
}
|
|
81898
83116
|
const { project, reader, identity } = await getCliProjectContext();
|
|
81899
|
-
const resolvedPath =
|
|
83117
|
+
const resolvedPath = path34.resolve(project.rootPath, imagePath);
|
|
81900
83118
|
const base642 = readFileSync16(resolvedPath).toString("base64");
|
|
81901
|
-
const filename =
|
|
83119
|
+
const filename = path34.basename(resolvedPath);
|
|
81902
83120
|
const analysis = await analyzeImage({
|
|
81903
83121
|
base64: base642,
|
|
81904
83122
|
filename,
|
|
@@ -82162,7 +83380,7 @@ __export(background_exports, {
|
|
|
82162
83380
|
doStart: () => doStart,
|
|
82163
83381
|
doStop: () => doStop
|
|
82164
83382
|
});
|
|
82165
|
-
import * as
|
|
83383
|
+
import * as fs23 from "fs";
|
|
82166
83384
|
import { spawn as spawn4, execSync as execSync5 } from "child_process";
|
|
82167
83385
|
import { randomBytes } from "crypto";
|
|
82168
83386
|
function getMemorixDir() {
|
|
@@ -82180,7 +83398,7 @@ function getLogFilePath() {
|
|
|
82180
83398
|
}
|
|
82181
83399
|
function loadState() {
|
|
82182
83400
|
try {
|
|
82183
|
-
const data =
|
|
83401
|
+
const data = fs23.readFileSync(getStateFilePath(), "utf-8");
|
|
82184
83402
|
return JSON.parse(data);
|
|
82185
83403
|
} catch {
|
|
82186
83404
|
return null;
|
|
@@ -82188,12 +83406,12 @@ function loadState() {
|
|
|
82188
83406
|
}
|
|
82189
83407
|
function saveState(state) {
|
|
82190
83408
|
const dir = getMemorixDir();
|
|
82191
|
-
if (!
|
|
82192
|
-
|
|
83409
|
+
if (!fs23.existsSync(dir)) fs23.mkdirSync(dir, { recursive: true });
|
|
83410
|
+
fs23.writeFileSync(getStateFilePath(), JSON.stringify(state, null, 2));
|
|
82193
83411
|
}
|
|
82194
83412
|
function clearState() {
|
|
82195
83413
|
try {
|
|
82196
|
-
|
|
83414
|
+
fs23.unlinkSync(getStateFilePath());
|
|
82197
83415
|
} catch {
|
|
82198
83416
|
}
|
|
82199
83417
|
}
|
|
@@ -82260,7 +83478,7 @@ async function doStart(port) {
|
|
|
82260
83478
|
} else {
|
|
82261
83479
|
try {
|
|
82262
83480
|
const heartbeatPath = getMemorixDir() + "/background.heartbeat";
|
|
82263
|
-
const hbData =
|
|
83481
|
+
const hbData = fs23.readFileSync(heartbeatPath, "utf-8");
|
|
82264
83482
|
const hb = JSON.parse(hbData);
|
|
82265
83483
|
const age = Date.now() - hb.heartbeatAt;
|
|
82266
83484
|
if (age < 12e4) {
|
|
@@ -82268,7 +83486,7 @@ async function doStart(port) {
|
|
|
82268
83486
|
console.log(" The control plane likely crashed. Auto-restarting...");
|
|
82269
83487
|
}
|
|
82270
83488
|
try {
|
|
82271
|
-
|
|
83489
|
+
fs23.unlinkSync(heartbeatPath);
|
|
82272
83490
|
} catch {
|
|
82273
83491
|
}
|
|
82274
83492
|
} catch {
|
|
@@ -82289,19 +83507,19 @@ async function doStart(port) {
|
|
|
82289
83507
|
}
|
|
82290
83508
|
try {
|
|
82291
83509
|
const readyFile = getMemorixDir() + "/background.ready";
|
|
82292
|
-
if (
|
|
83510
|
+
if (fs23.existsSync(readyFile)) fs23.unlinkSync(readyFile);
|
|
82293
83511
|
} catch {
|
|
82294
83512
|
}
|
|
82295
83513
|
const logFile = getLogFilePath();
|
|
82296
83514
|
const dir = getMemorixDir();
|
|
82297
|
-
if (!
|
|
82298
|
-
if (
|
|
83515
|
+
if (!fs23.existsSync(dir)) fs23.mkdirSync(dir, { recursive: true });
|
|
83516
|
+
if (fs23.existsSync(logFile)) {
|
|
82299
83517
|
try {
|
|
82300
|
-
|
|
83518
|
+
fs23.renameSync(logFile, logFile + ".prev");
|
|
82301
83519
|
} catch {
|
|
82302
83520
|
}
|
|
82303
83521
|
}
|
|
82304
|
-
const logFd =
|
|
83522
|
+
const logFd = fs23.openSync(logFile, "a");
|
|
82305
83523
|
const cliEntry = process.argv[1];
|
|
82306
83524
|
const child = spawn4(process.execPath, [cliEntry, "serve-http", "--port", String(port)], {
|
|
82307
83525
|
detached: true,
|
|
@@ -82311,7 +83529,7 @@ async function doStart(port) {
|
|
|
82311
83529
|
windowsHide: true
|
|
82312
83530
|
});
|
|
82313
83531
|
child.unref();
|
|
82314
|
-
|
|
83532
|
+
fs23.closeSync(logFd);
|
|
82315
83533
|
const pid = child.pid;
|
|
82316
83534
|
if (!pid) {
|
|
82317
83535
|
console.error("[ERROR] Failed to spawn background process");
|
|
@@ -82381,7 +83599,7 @@ async function doStop() {
|
|
|
82381
83599
|
console.log(`Background process (PID ${state.pid}) is not running. Cleaning up state.`);
|
|
82382
83600
|
clearState();
|
|
82383
83601
|
try {
|
|
82384
|
-
|
|
83602
|
+
fs23.unlinkSync(getMemorixDir() + "/background.ready");
|
|
82385
83603
|
} catch {
|
|
82386
83604
|
}
|
|
82387
83605
|
return;
|
|
@@ -82400,7 +83618,7 @@ async function doStop() {
|
|
|
82400
83618
|
}
|
|
82401
83619
|
clearState();
|
|
82402
83620
|
try {
|
|
82403
|
-
|
|
83621
|
+
fs23.unlinkSync(getMemorixDir() + "/background.ready");
|
|
82404
83622
|
} catch {
|
|
82405
83623
|
}
|
|
82406
83624
|
return;
|
|
@@ -82437,7 +83655,7 @@ async function doStop() {
|
|
|
82437
83655
|
}
|
|
82438
83656
|
clearState();
|
|
82439
83657
|
try {
|
|
82440
|
-
|
|
83658
|
+
fs23.unlinkSync(getMemorixDir() + "/background.ready");
|
|
82441
83659
|
} catch {
|
|
82442
83660
|
}
|
|
82443
83661
|
console.log("[OK] Control plane stopped.");
|
|
@@ -82513,7 +83731,7 @@ async function doStatus() {
|
|
|
82513
83731
|
console.log(" Process has exited. Cleaning up stale state...");
|
|
82514
83732
|
try {
|
|
82515
83733
|
const heartbeatPath = getMemorixDir() + "/background.heartbeat";
|
|
82516
|
-
const hbData =
|
|
83734
|
+
const hbData = fs23.readFileSync(heartbeatPath, "utf-8");
|
|
82517
83735
|
const hb = JSON.parse(hbData);
|
|
82518
83736
|
const age = Date.now() - hb.heartbeatAt;
|
|
82519
83737
|
if (age < 3e5) {
|
|
@@ -82554,26 +83772,26 @@ async function doEnsure(port) {
|
|
|
82554
83772
|
}
|
|
82555
83773
|
function doLogs(follow, lines) {
|
|
82556
83774
|
const logFile = getLogFilePath();
|
|
82557
|
-
if (!
|
|
83775
|
+
if (!fs23.existsSync(logFile)) {
|
|
82558
83776
|
console.log("No log file found. Start the background service first:");
|
|
82559
83777
|
console.log(" memorix background start");
|
|
82560
83778
|
return;
|
|
82561
83779
|
}
|
|
82562
83780
|
if (follow) {
|
|
82563
|
-
const content =
|
|
83781
|
+
const content = fs23.readFileSync(logFile, "utf-8");
|
|
82564
83782
|
const existingLines = content.split("\n");
|
|
82565
83783
|
const tail = existingLines.slice(-lines);
|
|
82566
83784
|
console.log(tail.join("\n"));
|
|
82567
83785
|
console.log("--- Following log (Ctrl+C to stop) ---");
|
|
82568
|
-
let position =
|
|
82569
|
-
const watcher =
|
|
83786
|
+
let position = fs23.statSync(logFile).size;
|
|
83787
|
+
const watcher = fs23.watch(logFile, () => {
|
|
82570
83788
|
try {
|
|
82571
|
-
const stat =
|
|
83789
|
+
const stat = fs23.statSync(logFile);
|
|
82572
83790
|
if (stat.size > position) {
|
|
82573
|
-
const fd =
|
|
83791
|
+
const fd = fs23.openSync(logFile, "r");
|
|
82574
83792
|
const buf = Buffer.alloc(stat.size - position);
|
|
82575
|
-
|
|
82576
|
-
|
|
83793
|
+
fs23.readSync(fd, buf, 0, buf.length, position);
|
|
83794
|
+
fs23.closeSync(fd);
|
|
82577
83795
|
process.stdout.write(buf.toString("utf-8"));
|
|
82578
83796
|
position = stat.size;
|
|
82579
83797
|
}
|
|
@@ -82583,7 +83801,7 @@ function doLogs(follow, lines) {
|
|
|
82583
83801
|
setInterval(() => {
|
|
82584
83802
|
}, 6e4);
|
|
82585
83803
|
} else {
|
|
82586
|
-
const content =
|
|
83804
|
+
const content = fs23.readFileSync(logFile, "utf-8");
|
|
82587
83805
|
const allLines = content.split("\n");
|
|
82588
83806
|
const tail = allLines.slice(-lines);
|
|
82589
83807
|
console.log(tail.join("\n"));
|
|
@@ -84163,7 +85381,7 @@ __export(dashboard_exports, {
|
|
|
84163
85381
|
default: () => dashboard_default
|
|
84164
85382
|
});
|
|
84165
85383
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
84166
|
-
import
|
|
85384
|
+
import path35 from "path";
|
|
84167
85385
|
var dashboard_default;
|
|
84168
85386
|
var init_dashboard = __esm({
|
|
84169
85387
|
"src/cli/commands/dashboard.ts"() {
|
|
@@ -84193,8 +85411,8 @@ var init_dashboard = __esm({
|
|
|
84193
85411
|
}
|
|
84194
85412
|
const dataDir = await getProjectDataDir2(project.id);
|
|
84195
85413
|
const port = parseInt(args.port, 10) || 3210;
|
|
84196
|
-
const cliDir =
|
|
84197
|
-
const staticDir =
|
|
85414
|
+
const cliDir = path35.dirname(fileURLToPath6(import.meta.url));
|
|
85415
|
+
const staticDir = path35.join(cliDir, "..", "dashboard", "static");
|
|
84198
85416
|
await startDashboard2(dataDir, port, staticDir, project.id, project.name, true, void 0, project.rootPath, true);
|
|
84199
85417
|
await new Promise(() => {
|
|
84200
85418
|
});
|
|
@@ -84450,12 +85668,12 @@ var uninstall_exports = {};
|
|
|
84450
85668
|
__export(uninstall_exports, {
|
|
84451
85669
|
default: () => uninstall_default
|
|
84452
85670
|
});
|
|
84453
|
-
import * as
|
|
84454
|
-
import * as
|
|
85671
|
+
import * as fs24 from "fs";
|
|
85672
|
+
import * as path36 from "path";
|
|
84455
85673
|
import * as os4 from "os";
|
|
84456
85674
|
function exists(p2) {
|
|
84457
85675
|
try {
|
|
84458
|
-
|
|
85676
|
+
fs24.accessSync(p2);
|
|
84459
85677
|
return true;
|
|
84460
85678
|
} catch {
|
|
84461
85679
|
return false;
|
|
@@ -84464,7 +85682,7 @@ function exists(p2) {
|
|
|
84464
85682
|
function checkJSON(p2) {
|
|
84465
85683
|
if (!exists(p2)) return false;
|
|
84466
85684
|
try {
|
|
84467
|
-
const content =
|
|
85685
|
+
const content = fs24.readFileSync(p2, "utf-8");
|
|
84468
85686
|
const cfg = JSON.parse(content);
|
|
84469
85687
|
const servers = cfg.mcpServers ?? cfg.mcp_servers ?? cfg.servers ?? {};
|
|
84470
85688
|
return Object.keys(servers).some((k5) => k5.toLowerCase().includes("memorix"));
|
|
@@ -84475,7 +85693,7 @@ function checkJSON(p2) {
|
|
|
84475
85693
|
function checkTOML(p2) {
|
|
84476
85694
|
if (!exists(p2)) return false;
|
|
84477
85695
|
try {
|
|
84478
|
-
const content =
|
|
85696
|
+
const content = fs24.readFileSync(p2, "utf-8");
|
|
84479
85697
|
return /\[mcp_servers\.(?:memorix|Memorix)\]/.test(content);
|
|
84480
85698
|
} catch {
|
|
84481
85699
|
return false;
|
|
@@ -84485,124 +85703,124 @@ function getMCPConfigEntries(home, cwd) {
|
|
|
84485
85703
|
const entries = [];
|
|
84486
85704
|
entries.push({
|
|
84487
85705
|
agent: "Claude Code",
|
|
84488
|
-
path:
|
|
85706
|
+
path: path36.join(home, ".claude.json"),
|
|
84489
85707
|
kind: "global",
|
|
84490
85708
|
format: "json",
|
|
84491
|
-
detected: checkJSON(
|
|
85709
|
+
detected: checkJSON(path36.join(home, ".claude.json")),
|
|
84492
85710
|
note: 'Remove the "memorix" key from mcpServers in this file.'
|
|
84493
85711
|
});
|
|
84494
85712
|
entries.push({
|
|
84495
85713
|
agent: "Claude Code",
|
|
84496
|
-
path:
|
|
85714
|
+
path: path36.join(cwd, ".claude", "settings.json"),
|
|
84497
85715
|
kind: "project",
|
|
84498
85716
|
format: "json",
|
|
84499
|
-
detected: checkJSON(
|
|
85717
|
+
detected: checkJSON(path36.join(cwd, ".claude", "settings.json")),
|
|
84500
85718
|
note: 'Remove the "memorix" key from mcpServers in this file.'
|
|
84501
85719
|
});
|
|
84502
85720
|
entries.push({
|
|
84503
85721
|
agent: "Cursor",
|
|
84504
|
-
path:
|
|
85722
|
+
path: path36.join(home, ".cursor", "mcp.json"),
|
|
84505
85723
|
kind: "global",
|
|
84506
85724
|
format: "json",
|
|
84507
|
-
detected: checkJSON(
|
|
85725
|
+
detected: checkJSON(path36.join(home, ".cursor", "mcp.json")),
|
|
84508
85726
|
note: 'Remove the "memorix" key from mcpServers in this file.'
|
|
84509
85727
|
});
|
|
84510
85728
|
entries.push({
|
|
84511
85729
|
agent: "Cursor",
|
|
84512
|
-
path:
|
|
85730
|
+
path: path36.join(cwd, ".cursor", "mcp.json"),
|
|
84513
85731
|
kind: "project",
|
|
84514
85732
|
format: "json",
|
|
84515
|
-
detected: checkJSON(
|
|
85733
|
+
detected: checkJSON(path36.join(cwd, ".cursor", "mcp.json")),
|
|
84516
85734
|
note: 'Remove the "memorix" key from mcpServers in this file.'
|
|
84517
85735
|
});
|
|
84518
85736
|
entries.push({
|
|
84519
85737
|
agent: "Windsurf",
|
|
84520
|
-
path:
|
|
85738
|
+
path: path36.join(home, ".codeium", "windsurf", "mcp_config.json"),
|
|
84521
85739
|
kind: "global",
|
|
84522
85740
|
format: "json",
|
|
84523
|
-
detected: checkJSON(
|
|
85741
|
+
detected: checkJSON(path36.join(home, ".codeium", "windsurf", "mcp_config.json")),
|
|
84524
85742
|
note: 'Remove the "memorix" key from mcpServers in this file.'
|
|
84525
85743
|
});
|
|
84526
85744
|
entries.push({
|
|
84527
85745
|
agent: "Codex",
|
|
84528
|
-
path:
|
|
85746
|
+
path: path36.join(home, ".codex", "config.toml"),
|
|
84529
85747
|
kind: "global",
|
|
84530
85748
|
format: "toml",
|
|
84531
|
-
detected: checkTOML(
|
|
85749
|
+
detected: checkTOML(path36.join(home, ".codex", "config.toml")),
|
|
84532
85750
|
note: "Remove the [mcp_servers.memorix] section from this file."
|
|
84533
85751
|
});
|
|
84534
85752
|
entries.push({
|
|
84535
85753
|
agent: "VS Code / Copilot",
|
|
84536
|
-
path:
|
|
85754
|
+
path: path36.join(home, ".vscode", "mcp.json"),
|
|
84537
85755
|
kind: "global",
|
|
84538
85756
|
format: "json",
|
|
84539
|
-
detected: checkJSON(
|
|
85757
|
+
detected: checkJSON(path36.join(home, ".vscode", "mcp.json")),
|
|
84540
85758
|
note: 'Remove the "memorix" key from servers in this file.'
|
|
84541
85759
|
});
|
|
84542
85760
|
entries.push({
|
|
84543
85761
|
agent: "VS Code / Copilot",
|
|
84544
|
-
path:
|
|
85762
|
+
path: path36.join(cwd, ".vscode", "mcp.json"),
|
|
84545
85763
|
kind: "project",
|
|
84546
85764
|
format: "json",
|
|
84547
|
-
detected: checkJSON(
|
|
85765
|
+
detected: checkJSON(path36.join(cwd, ".vscode", "mcp.json")),
|
|
84548
85766
|
note: 'Remove the "memorix" key from servers in this file.'
|
|
84549
85767
|
});
|
|
84550
85768
|
entries.push({
|
|
84551
85769
|
agent: "Kiro",
|
|
84552
|
-
path:
|
|
85770
|
+
path: path36.join(home, ".kiro", "settings", "mcp.json"),
|
|
84553
85771
|
kind: "global",
|
|
84554
85772
|
format: "json",
|
|
84555
|
-
detected: checkJSON(
|
|
85773
|
+
detected: checkJSON(path36.join(home, ".kiro", "settings", "mcp.json")),
|
|
84556
85774
|
note: 'Remove the "memorix" key from mcpServers in this file.'
|
|
84557
85775
|
});
|
|
84558
85776
|
entries.push({
|
|
84559
85777
|
agent: "Kiro",
|
|
84560
|
-
path:
|
|
85778
|
+
path: path36.join(cwd, ".kiro", "settings", "mcp.json"),
|
|
84561
85779
|
kind: "project",
|
|
84562
85780
|
format: "json",
|
|
84563
|
-
detected: checkJSON(
|
|
85781
|
+
detected: checkJSON(path36.join(cwd, ".kiro", "settings", "mcp.json")),
|
|
84564
85782
|
note: 'Remove the "memorix" key from mcpServers in this file.'
|
|
84565
85783
|
});
|
|
84566
85784
|
entries.push({
|
|
84567
85785
|
agent: "Gemini CLI",
|
|
84568
|
-
path:
|
|
85786
|
+
path: path36.join(home, ".gemini", "settings.json"),
|
|
84569
85787
|
kind: "global",
|
|
84570
85788
|
format: "json",
|
|
84571
|
-
detected: checkJSON(
|
|
85789
|
+
detected: checkJSON(path36.join(home, ".gemini", "settings.json")),
|
|
84572
85790
|
note: 'Remove the "memorix" key from mcpServers in this file.'
|
|
84573
85791
|
});
|
|
84574
85792
|
entries.push({
|
|
84575
85793
|
agent: "Antigravity",
|
|
84576
|
-
path:
|
|
85794
|
+
path: path36.join(home, ".gemini", "config", "mcp_config.json"),
|
|
84577
85795
|
kind: "global",
|
|
84578
85796
|
format: "json",
|
|
84579
|
-
detected: checkJSON(
|
|
85797
|
+
detected: checkJSON(path36.join(home, ".gemini", "config", "mcp_config.json")),
|
|
84580
85798
|
note: 'Remove the "memorix" key from mcpServers in this file.'
|
|
84581
85799
|
});
|
|
84582
85800
|
entries.push({
|
|
84583
85801
|
agent: "Antigravity",
|
|
84584
|
-
path:
|
|
85802
|
+
path: path36.join(home, ".gemini", "config", "hooks.json"),
|
|
84585
85803
|
kind: "global",
|
|
84586
85804
|
format: "json",
|
|
84587
|
-
detected: exists(
|
|
85805
|
+
detected: exists(path36.join(home, ".gemini", "config", "hooks.json")),
|
|
84588
85806
|
note: 'Remove the "memorix" hook group from this file.'
|
|
84589
85807
|
});
|
|
84590
85808
|
entries.push({
|
|
84591
85809
|
agent: "Antigravity",
|
|
84592
|
-
path:
|
|
85810
|
+
path: path36.join(home, ".gemini", "config", "plugins", "memorix", "plugin.json"),
|
|
84593
85811
|
kind: "global",
|
|
84594
85812
|
format: "json",
|
|
84595
|
-
detected: exists(
|
|
85813
|
+
detected: exists(path36.join(home, ".gemini", "config", "plugins", "memorix", "plugin.json")),
|
|
84596
85814
|
note: "Delete the containing ~/.gemini/config/plugins/memorix plugin directory if you want to remove the Antigravity plugin package."
|
|
84597
85815
|
});
|
|
84598
85816
|
const traeCfg = (() => {
|
|
84599
85817
|
if (process.platform === "win32") {
|
|
84600
|
-
return
|
|
85818
|
+
return path36.join(process.env.APPDATA || path36.join(home, "AppData", "Roaming"), "Trae", "User", "mcp.json");
|
|
84601
85819
|
}
|
|
84602
85820
|
if (process.platform === "darwin") {
|
|
84603
|
-
return
|
|
85821
|
+
return path36.join(home, "Library", "Application Support", "Trae", "User", "mcp.json");
|
|
84604
85822
|
}
|
|
84605
|
-
return
|
|
85823
|
+
return path36.join(home, ".config", "Trae", "User", "mcp.json");
|
|
84606
85824
|
})();
|
|
84607
85825
|
entries.push({
|
|
84608
85826
|
agent: "Trae",
|
|
@@ -84615,9 +85833,9 @@ function getMCPConfigEntries(home, cwd) {
|
|
|
84615
85833
|
return entries;
|
|
84616
85834
|
}
|
|
84617
85835
|
function checkBackground(home) {
|
|
84618
|
-
const statePath =
|
|
85836
|
+
const statePath = path36.join(home, ".memorix", "background.json");
|
|
84619
85837
|
try {
|
|
84620
|
-
const data =
|
|
85838
|
+
const data = fs24.readFileSync(statePath, "utf-8");
|
|
84621
85839
|
const state = JSON.parse(data);
|
|
84622
85840
|
try {
|
|
84623
85841
|
process.kill(state.pid, 0);
|
|
@@ -84756,7 +85974,7 @@ var init_uninstall = __esm({
|
|
|
84756
85974
|
},
|
|
84757
85975
|
async run({ args }) {
|
|
84758
85976
|
const home = os4.homedir();
|
|
84759
|
-
const memorixDir =
|
|
85977
|
+
const memorixDir = path36.join(home, ".memorix");
|
|
84760
85978
|
const dryRun = args["dry-run"];
|
|
84761
85979
|
const yes = args.yes;
|
|
84762
85980
|
const doHooks = args.hooks;
|
|
@@ -84884,7 +86102,7 @@ var init_uninstall = __esm({
|
|
|
84884
86102
|
if (exists(memorixDir)) {
|
|
84885
86103
|
console.log(`[DELETE] Removing ${memorixDir}...`);
|
|
84886
86104
|
try {
|
|
84887
|
-
|
|
86105
|
+
fs24.rmSync(memorixDir, { recursive: true, force: true });
|
|
84888
86106
|
console.log("[OK] Data directory deleted.");
|
|
84889
86107
|
changes++;
|
|
84890
86108
|
} catch (err) {
|
|
@@ -85255,24 +86473,24 @@ var init_claude_stream = __esm({
|
|
|
85255
86473
|
});
|
|
85256
86474
|
|
|
85257
86475
|
// src/orchestrate/adapters/claude.ts
|
|
85258
|
-
import * as
|
|
85259
|
-
import * as
|
|
86476
|
+
import * as fs25 from "fs";
|
|
86477
|
+
import * as path37 from "path";
|
|
85260
86478
|
function resolveMcpConfigPath(projectDir2) {
|
|
85261
|
-
const localPath =
|
|
86479
|
+
const localPath = path37.join(projectDir2, ".claude", "settings.local.json");
|
|
85262
86480
|
try {
|
|
85263
|
-
if (
|
|
86481
|
+
if (fs25.existsSync(localPath)) return localPath;
|
|
85264
86482
|
} catch {
|
|
85265
86483
|
}
|
|
85266
|
-
const settingsPath =
|
|
86484
|
+
const settingsPath = path37.join(projectDir2, ".claude", "settings.json");
|
|
85267
86485
|
try {
|
|
85268
|
-
if (
|
|
86486
|
+
if (fs25.existsSync(settingsPath)) return settingsPath;
|
|
85269
86487
|
} catch {
|
|
85270
86488
|
}
|
|
85271
86489
|
const mcpConfig = {
|
|
85272
86490
|
mcpServers: {
|
|
85273
86491
|
memorix: {
|
|
85274
86492
|
command: process.execPath,
|
|
85275
|
-
args: [
|
|
86493
|
+
args: [path37.resolve(path37.dirname(process.execPath), "..", "lib", "node_modules", "memorix", "dist", "index.js"), "serve", "--transport", "stdio"]
|
|
85276
86494
|
}
|
|
85277
86495
|
}
|
|
85278
86496
|
};
|
|
@@ -85282,10 +86500,10 @@ function resolveMcpConfigPath(projectDir2) {
|
|
|
85282
86500
|
args: ["serve", "--transport", "stdio"]
|
|
85283
86501
|
};
|
|
85284
86502
|
try {
|
|
85285
|
-
const claudeDir =
|
|
85286
|
-
|
|
85287
|
-
const tempPath =
|
|
85288
|
-
|
|
86503
|
+
const claudeDir = path37.join(projectDir2, ".claude");
|
|
86504
|
+
fs25.mkdirSync(claudeDir, { recursive: true });
|
|
86505
|
+
const tempPath = path37.join(claudeDir, "settings.local.json");
|
|
86506
|
+
fs25.writeFileSync(tempPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
|
|
85289
86507
|
return tempPath;
|
|
85290
86508
|
} catch {
|
|
85291
86509
|
return null;
|
|
@@ -86701,9 +87919,9 @@ function writePipelineSummary(projectDir2, summary) {
|
|
|
86701
87919
|
return null;
|
|
86702
87920
|
}
|
|
86703
87921
|
}
|
|
86704
|
-
function safeWrite(
|
|
87922
|
+
function safeWrite(path38, content) {
|
|
86705
87923
|
try {
|
|
86706
|
-
writeFileSync9(
|
|
87924
|
+
writeFileSync9(path38, content, "utf-8");
|
|
86707
87925
|
} catch {
|
|
86708
87926
|
}
|
|
86709
87927
|
}
|
|
@@ -88174,8 +89392,8 @@ var init_orchestrate = __esm({
|
|
|
88174
89392
|
const { getProjectDataDir: getProjectDataDir2 } = await Promise.resolve().then(() => (init_persistence(), persistence_exports));
|
|
88175
89393
|
const { resolveAdapters: resolveAdapters2, parseAgentQuotas: parseAgentQuotas2, buildQuotaMap: buildQuotaMap2 } = await Promise.resolve().then(() => (init_adapters(), adapters_exports));
|
|
88176
89394
|
const { runCoordinationLoop: runCoordinationLoop2 } = await Promise.resolve().then(() => (init_coordinator(), coordinator_exports));
|
|
88177
|
-
const
|
|
88178
|
-
const projectDir2 = args.project ?
|
|
89395
|
+
const path38 = await import("path");
|
|
89396
|
+
const projectDir2 = args.project ? path38.resolve(args.project) : process.cwd();
|
|
88179
89397
|
const proj = detectProject2(projectDir2);
|
|
88180
89398
|
if (!proj) {
|
|
88181
89399
|
console.error("[ERROR] Not a git repository. Run `git init` first.");
|
|
@@ -89285,7 +90503,7 @@ var init_Panels = __esm({
|
|
|
89285
90503
|
// src/cli/tui/ConfigureView.tsx
|
|
89286
90504
|
import { useState as useState2, useEffect as useEffect2 } from "react";
|
|
89287
90505
|
import { Box as Box6, Text as Text6, useInput as useInput2 } from "ink";
|
|
89288
|
-
import * as
|
|
90506
|
+
import * as fs26 from "fs";
|
|
89289
90507
|
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
89290
90508
|
function getConfigPath() {
|
|
89291
90509
|
return `${process.env.HOME || process.env.USERPROFILE}/.memorix/config.json`;
|
|
@@ -89293,15 +90511,15 @@ function getConfigPath() {
|
|
|
89293
90511
|
function loadConfig() {
|
|
89294
90512
|
try {
|
|
89295
90513
|
const p2 = getConfigPath();
|
|
89296
|
-
if (
|
|
90514
|
+
if (fs26.existsSync(p2)) return JSON.parse(fs26.readFileSync(p2, "utf-8"));
|
|
89297
90515
|
} catch {
|
|
89298
90516
|
}
|
|
89299
90517
|
return {};
|
|
89300
90518
|
}
|
|
89301
90519
|
function saveConfig(config2) {
|
|
89302
90520
|
const dir = `${process.env.HOME || process.env.USERPROFILE}/.memorix`;
|
|
89303
|
-
if (!
|
|
89304
|
-
|
|
90521
|
+
if (!fs26.existsSync(dir)) fs26.mkdirSync(dir, { recursive: true });
|
|
90522
|
+
fs26.writeFileSync(getConfigPath(), JSON.stringify(config2, null, 2));
|
|
89305
90523
|
}
|
|
89306
90524
|
function separator2(w3 = 50) {
|
|
89307
90525
|
return SEP.thin.repeat(w3);
|
|
@@ -90014,7 +91232,7 @@ var init_session_service = __esm({
|
|
|
90014
91232
|
});
|
|
90015
91233
|
|
|
90016
91234
|
// src/cli/tui/data.ts
|
|
90017
|
-
import * as
|
|
91235
|
+
import * as fs27 from "fs";
|
|
90018
91236
|
function formatSearchModeLabel(mode) {
|
|
90019
91237
|
const normalized = (mode || "").toLowerCase();
|
|
90020
91238
|
if (!normalized) return "Unknown";
|
|
@@ -90221,7 +91439,7 @@ async function getBackgroundStatus() {
|
|
|
90221
91439
|
try {
|
|
90222
91440
|
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
90223
91441
|
const statePath = `${home.replace(/\\/g, "/")}/.memorix/background.json`;
|
|
90224
|
-
if (!
|
|
91442
|
+
if (!fs27.existsSync(statePath)) {
|
|
90225
91443
|
try {
|
|
90226
91444
|
const controller = new AbortController();
|
|
90227
91445
|
const timer = setTimeout(() => controller.abort(), 2e3);
|
|
@@ -90242,7 +91460,7 @@ async function getBackgroundStatus() {
|
|
|
90242
91460
|
}
|
|
90243
91461
|
return result;
|
|
90244
91462
|
}
|
|
90245
|
-
const state = JSON.parse(
|
|
91463
|
+
const state = JSON.parse(fs27.readFileSync(statePath, "utf-8"));
|
|
90246
91464
|
result.pid = state.pid;
|
|
90247
91465
|
result.port = state.port;
|
|
90248
91466
|
result.startedAt = state.startedAt;
|
|
@@ -90333,8 +91551,8 @@ function detectMode() {
|
|
|
90333
91551
|
try {
|
|
90334
91552
|
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
90335
91553
|
const statePath = `${home.replace(/\\/g, "/")}/.memorix/background.json`;
|
|
90336
|
-
if (
|
|
90337
|
-
const state = JSON.parse(
|
|
91554
|
+
if (fs27.existsSync(statePath)) {
|
|
91555
|
+
const state = JSON.parse(fs27.readFileSync(statePath, "utf-8"));
|
|
90338
91556
|
try {
|
|
90339
91557
|
process.kill(state.pid, 0);
|
|
90340
91558
|
return { mode: "Background", detail: `port ${state.port}` };
|
|
@@ -92875,9 +94093,17 @@ var GUIDES = {
|
|
|
92875
94093
|
"memorix memory recent [--limit 10]",
|
|
92876
94094
|
"memorix memory resolve --ids 42,43 [--status resolved|archived]",
|
|
92877
94095
|
"memorix memory consolidate --action preview|execute",
|
|
92878
|
-
'memorix memory promote --ids 42,43 [--trigger "..."] [--instruction "..."]'
|
|
94096
|
+
'memorix memory promote --ids 42,43 [--trigger "..."] [--instruction "..."]',
|
|
94097
|
+
"memorix memory long-term list [--all]",
|
|
94098
|
+
'memorix memory long-term add --kind semantic --scope user --portability portable --title "..." --text "..." [--tags "..."] [--applicability "..."]',
|
|
94099
|
+
"memorix memory long-term promote --from-observation 42 --kind procedural --scope project",
|
|
94100
|
+
'memorix memory long-term qualify|approve|archive --id <id> --reason "..."',
|
|
94101
|
+
'memorix memory long-term supersede --id <old-id> --superseded-by <qualified-id> --reason "..."'
|
|
92879
94102
|
],
|
|
92880
|
-
notes: [
|
|
94103
|
+
notes: [
|
|
94104
|
+
"Personal and team visibility require `memorix identity join` or `memorix identity use` first.",
|
|
94105
|
+
"Candidates never enter a task Workset. Only manual or user-confirmed `user + portable` memory may cross local projects."
|
|
94106
|
+
]
|
|
92881
94107
|
},
|
|
92882
94108
|
identity: {
|
|
92883
94109
|
summary: "Select the active local actor for private memory and coordination commands.",
|