memorix 0.9.33 → 0.9.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +529 -297
- package/dist/cli/index.js.map +1 -1
- package/dist/dashboard/static/app.js +455 -201
- package/dist/dashboard/static/index.html +73 -44
- package/dist/dashboard/static/style.css +260 -87
- package/dist/index.js +444 -203
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -2615,10 +2615,10 @@ function assignProp(target, prop, value) {
|
|
|
2615
2615
|
configurable: true
|
|
2616
2616
|
});
|
|
2617
2617
|
}
|
|
2618
|
-
function getElementAtPath(obj,
|
|
2619
|
-
if (!
|
|
2618
|
+
function getElementAtPath(obj, path10) {
|
|
2619
|
+
if (!path10)
|
|
2620
2620
|
return obj;
|
|
2621
|
-
return
|
|
2621
|
+
return path10.reduce((acc, key) => acc?.[key], obj);
|
|
2622
2622
|
}
|
|
2623
2623
|
function promiseAllObject(promisesObj) {
|
|
2624
2624
|
const keys = Object.keys(promisesObj);
|
|
@@ -2867,11 +2867,11 @@ function aborted(x3, startIndex = 0) {
|
|
|
2867
2867
|
}
|
|
2868
2868
|
return false;
|
|
2869
2869
|
}
|
|
2870
|
-
function prefixIssues(
|
|
2870
|
+
function prefixIssues(path10, issues) {
|
|
2871
2871
|
return issues.map((iss) => {
|
|
2872
2872
|
var _a;
|
|
2873
2873
|
(_a = iss).path ?? (_a.path = []);
|
|
2874
|
-
iss.path.unshift(
|
|
2874
|
+
iss.path.unshift(path10);
|
|
2875
2875
|
return iss;
|
|
2876
2876
|
});
|
|
2877
2877
|
}
|
|
@@ -9225,8 +9225,8 @@ var init_parseUtil = __esm({
|
|
|
9225
9225
|
init_errors3();
|
|
9226
9226
|
init_en2();
|
|
9227
9227
|
makeIssue = (params) => {
|
|
9228
|
-
const { data, path:
|
|
9229
|
-
const fullPath = [...
|
|
9228
|
+
const { data, path: path10, errorMaps, issueData } = params;
|
|
9229
|
+
const fullPath = [...path10, ...issueData.path || []];
|
|
9230
9230
|
const fullIssue = {
|
|
9231
9231
|
...issueData,
|
|
9232
9232
|
path: fullPath
|
|
@@ -9540,11 +9540,11 @@ var init_types2 = __esm({
|
|
|
9540
9540
|
init_parseUtil();
|
|
9541
9541
|
init_util2();
|
|
9542
9542
|
ParseInputLazyPath = class {
|
|
9543
|
-
constructor(parent, value,
|
|
9543
|
+
constructor(parent, value, path10, key) {
|
|
9544
9544
|
this._cachedPath = [];
|
|
9545
9545
|
this.parent = parent;
|
|
9546
9546
|
this.data = value;
|
|
9547
|
-
this._path =
|
|
9547
|
+
this._path = path10;
|
|
9548
9548
|
this._key = key;
|
|
9549
9549
|
}
|
|
9550
9550
|
get path() {
|
|
@@ -19090,8 +19090,8 @@ var require_utils = __commonJS({
|
|
|
19090
19090
|
}
|
|
19091
19091
|
return ind;
|
|
19092
19092
|
}
|
|
19093
|
-
function removeDotSegments(
|
|
19094
|
-
let input =
|
|
19093
|
+
function removeDotSegments(path10) {
|
|
19094
|
+
let input = path10;
|
|
19095
19095
|
const output = [];
|
|
19096
19096
|
let nextSlash = -1;
|
|
19097
19097
|
let len = 0;
|
|
@@ -19291,8 +19291,8 @@ var require_schemes = __commonJS({
|
|
|
19291
19291
|
wsComponent.secure = void 0;
|
|
19292
19292
|
}
|
|
19293
19293
|
if (wsComponent.resourceName) {
|
|
19294
|
-
const [
|
|
19295
|
-
wsComponent.path =
|
|
19294
|
+
const [path10, query] = wsComponent.resourceName.split("?");
|
|
19295
|
+
wsComponent.path = path10 && path10 !== "/" ? path10 : void 0;
|
|
19296
19296
|
wsComponent.query = query;
|
|
19297
19297
|
wsComponent.resourceName = void 0;
|
|
19298
19298
|
}
|
|
@@ -22691,12 +22691,12 @@ var require_dist = __commonJS({
|
|
|
22691
22691
|
throw new Error(`Unknown format "${name}"`);
|
|
22692
22692
|
return f4;
|
|
22693
22693
|
};
|
|
22694
|
-
function addFormats(ajv, list,
|
|
22694
|
+
function addFormats(ajv, list, fs7, exportName) {
|
|
22695
22695
|
var _a;
|
|
22696
22696
|
var _b;
|
|
22697
22697
|
(_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
22698
22698
|
for (const f4 of list)
|
|
22699
|
-
ajv.addFormat(f4,
|
|
22699
|
+
ajv.addFormat(f4, fs7[f4]);
|
|
22700
22700
|
}
|
|
22701
22701
|
module2.exports = exports2 = formatsPlugin;
|
|
22702
22702
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -24563,9 +24563,6 @@ import { promises as fs2 } from "fs";
|
|
|
24563
24563
|
import path3 from "path";
|
|
24564
24564
|
import os from "os";
|
|
24565
24565
|
async function getProjectDataDir(_projectId, baseDir) {
|
|
24566
|
-
if (_projectId === "__invalid__") {
|
|
24567
|
-
throw new Error("Cannot create data directory for invalid project");
|
|
24568
|
-
}
|
|
24569
24566
|
const base = baseDir ?? DEFAULT_DATA_DIR;
|
|
24570
24567
|
await fs2.mkdir(base, { recursive: true });
|
|
24571
24568
|
return base;
|
|
@@ -25252,15 +25249,15 @@ function getDocumentProperties(doc, paths) {
|
|
|
25252
25249
|
const properties = {};
|
|
25253
25250
|
const pathsLength = paths.length;
|
|
25254
25251
|
for (let i2 = 0; i2 < pathsLength; i2++) {
|
|
25255
|
-
const
|
|
25256
|
-
const pathTokens =
|
|
25252
|
+
const path10 = paths[i2];
|
|
25253
|
+
const pathTokens = path10.split(".");
|
|
25257
25254
|
let current = doc;
|
|
25258
25255
|
const pathTokensLength = pathTokens.length;
|
|
25259
25256
|
for (let j3 = 0; j3 < pathTokensLength; j3++) {
|
|
25260
25257
|
current = current[pathTokens[j3]];
|
|
25261
25258
|
if (typeof current === "object") {
|
|
25262
25259
|
if (current !== null && "lat" in current && "lon" in current && typeof current.lat === "number" && typeof current.lon === "number") {
|
|
25263
|
-
current = properties[
|
|
25260
|
+
current = properties[path10] = current;
|
|
25264
25261
|
break;
|
|
25265
25262
|
} else if (!Array.isArray(current) && current !== null && j3 === pathTokensLength - 1) {
|
|
25266
25263
|
current = void 0;
|
|
@@ -25272,14 +25269,14 @@ function getDocumentProperties(doc, paths) {
|
|
|
25272
25269
|
}
|
|
25273
25270
|
}
|
|
25274
25271
|
if (typeof current !== "undefined") {
|
|
25275
|
-
properties[
|
|
25272
|
+
properties[path10] = current;
|
|
25276
25273
|
}
|
|
25277
25274
|
}
|
|
25278
25275
|
return properties;
|
|
25279
25276
|
}
|
|
25280
|
-
function getNested(obj,
|
|
25281
|
-
const props = getDocumentProperties(obj, [
|
|
25282
|
-
return props[
|
|
25277
|
+
function getNested(obj, path10) {
|
|
25278
|
+
const props = getDocumentProperties(obj, [path10]);
|
|
25279
|
+
return props[path10];
|
|
25283
25280
|
}
|
|
25284
25281
|
function convertDistanceToMeters(distance, unit) {
|
|
25285
25282
|
const ratio = mapDistanceToMeters[unit];
|
|
@@ -25295,10 +25292,10 @@ function removeVectorsFromHits(searchResult, vectorProperties) {
|
|
|
25295
25292
|
...result.document,
|
|
25296
25293
|
// Remove embeddings from the result
|
|
25297
25294
|
...vectorProperties.reduce((acc, prop) => {
|
|
25298
|
-
const
|
|
25299
|
-
const lastKey =
|
|
25295
|
+
const path10 = prop.split(".");
|
|
25296
|
+
const lastKey = path10.pop();
|
|
25300
25297
|
let obj = acc;
|
|
25301
|
-
for (const key of
|
|
25298
|
+
for (const key of path10) {
|
|
25302
25299
|
obj[key] = obj[key] ?? {};
|
|
25303
25300
|
obj = obj[key];
|
|
25304
25301
|
}
|
|
@@ -26030,15 +26027,15 @@ var init_avl = __esm({
|
|
|
26030
26027
|
if (node === null) {
|
|
26031
26028
|
return new AVLNode(key, [value]);
|
|
26032
26029
|
}
|
|
26033
|
-
const
|
|
26030
|
+
const path10 = [];
|
|
26034
26031
|
let current = node;
|
|
26035
26032
|
let parent = null;
|
|
26036
26033
|
while (current !== null) {
|
|
26037
|
-
|
|
26034
|
+
path10.push({ parent, node: current });
|
|
26038
26035
|
if (key < current.k) {
|
|
26039
26036
|
if (current.l === null) {
|
|
26040
26037
|
current.l = new AVLNode(key, [value]);
|
|
26041
|
-
|
|
26038
|
+
path10.push({ parent: current, node: current.l });
|
|
26042
26039
|
break;
|
|
26043
26040
|
} else {
|
|
26044
26041
|
parent = current;
|
|
@@ -26047,7 +26044,7 @@ var init_avl = __esm({
|
|
|
26047
26044
|
} else if (key > current.k) {
|
|
26048
26045
|
if (current.r === null) {
|
|
26049
26046
|
current.r = new AVLNode(key, [value]);
|
|
26050
|
-
|
|
26047
|
+
path10.push({ parent: current, node: current.r });
|
|
26051
26048
|
break;
|
|
26052
26049
|
} else {
|
|
26053
26050
|
parent = current;
|
|
@@ -26062,8 +26059,8 @@ var init_avl = __esm({
|
|
|
26062
26059
|
if (this.insertCount++ % rebalanceThreshold === 0) {
|
|
26063
26060
|
needRebalance = true;
|
|
26064
26061
|
}
|
|
26065
|
-
for (let i2 =
|
|
26066
|
-
const { parent: parent2, node: currentNode } =
|
|
26062
|
+
for (let i2 = path10.length - 1; i2 >= 0; i2--) {
|
|
26063
|
+
const { parent: parent2, node: currentNode } = path10[i2];
|
|
26067
26064
|
currentNode.updateHeight();
|
|
26068
26065
|
if (needRebalance) {
|
|
26069
26066
|
const rebalancedNode = this.rebalanceNode(currentNode);
|
|
@@ -26169,10 +26166,10 @@ var init_avl = __esm({
|
|
|
26169
26166
|
removeNode(node, key) {
|
|
26170
26167
|
if (node === null)
|
|
26171
26168
|
return null;
|
|
26172
|
-
const
|
|
26169
|
+
const path10 = [];
|
|
26173
26170
|
let current = node;
|
|
26174
26171
|
while (current !== null && current.k !== key) {
|
|
26175
|
-
|
|
26172
|
+
path10.push(current);
|
|
26176
26173
|
if (key < current.k) {
|
|
26177
26174
|
current = current.l;
|
|
26178
26175
|
} else {
|
|
@@ -26184,10 +26181,10 @@ var init_avl = __esm({
|
|
|
26184
26181
|
}
|
|
26185
26182
|
if (current.l === null || current.r === null) {
|
|
26186
26183
|
const child = current.l ? current.l : current.r;
|
|
26187
|
-
if (
|
|
26184
|
+
if (path10.length === 0) {
|
|
26188
26185
|
node = child;
|
|
26189
26186
|
} else {
|
|
26190
|
-
const parent =
|
|
26187
|
+
const parent = path10[path10.length - 1];
|
|
26191
26188
|
if (parent.l === current) {
|
|
26192
26189
|
parent.l = child;
|
|
26193
26190
|
} else {
|
|
@@ -26210,13 +26207,13 @@ var init_avl = __esm({
|
|
|
26210
26207
|
}
|
|
26211
26208
|
current = successorParent;
|
|
26212
26209
|
}
|
|
26213
|
-
|
|
26214
|
-
for (let i2 =
|
|
26215
|
-
const currentNode =
|
|
26210
|
+
path10.push(current);
|
|
26211
|
+
for (let i2 = path10.length - 1; i2 >= 0; i2--) {
|
|
26212
|
+
const currentNode = path10[i2];
|
|
26216
26213
|
currentNode.updateHeight();
|
|
26217
26214
|
const rebalancedNode = this.rebalanceNode(currentNode);
|
|
26218
26215
|
if (i2 > 0) {
|
|
26219
|
-
const parent =
|
|
26216
|
+
const parent = path10[i2 - 1];
|
|
26220
26217
|
if (parent.l === currentNode) {
|
|
26221
26218
|
parent.l = rebalancedNode;
|
|
26222
26219
|
} else if (parent.r === currentNode) {
|
|
@@ -27383,15 +27380,15 @@ function create2(orama, sharedInternalDocumentStore, schema, index, prefix = "")
|
|
|
27383
27380
|
};
|
|
27384
27381
|
}
|
|
27385
27382
|
for (const [prop, type] of Object.entries(schema)) {
|
|
27386
|
-
const
|
|
27383
|
+
const path10 = `${prefix}${prefix ? "." : ""}${prop}`;
|
|
27387
27384
|
if (typeof type === "object" && !Array.isArray(type)) {
|
|
27388
|
-
create2(orama, sharedInternalDocumentStore, type, index,
|
|
27385
|
+
create2(orama, sharedInternalDocumentStore, type, index, path10);
|
|
27389
27386
|
continue;
|
|
27390
27387
|
}
|
|
27391
27388
|
if (isVectorType(type)) {
|
|
27392
|
-
index.searchableProperties.push(
|
|
27393
|
-
index.searchablePropertiesWithTypes[
|
|
27394
|
-
index.vectorIndexes[
|
|
27389
|
+
index.searchableProperties.push(path10);
|
|
27390
|
+
index.searchablePropertiesWithTypes[path10] = type;
|
|
27391
|
+
index.vectorIndexes[path10] = {
|
|
27395
27392
|
type: "Vector",
|
|
27396
27393
|
node: new VectorIndex(getVectorSize(type)),
|
|
27397
27394
|
isArray: false
|
|
@@ -27401,32 +27398,32 @@ function create2(orama, sharedInternalDocumentStore, schema, index, prefix = "")
|
|
|
27401
27398
|
switch (type) {
|
|
27402
27399
|
case "boolean":
|
|
27403
27400
|
case "boolean[]":
|
|
27404
|
-
index.indexes[
|
|
27401
|
+
index.indexes[path10] = { type: "Bool", node: new BoolNode(), isArray };
|
|
27405
27402
|
break;
|
|
27406
27403
|
case "number":
|
|
27407
27404
|
case "number[]":
|
|
27408
|
-
index.indexes[
|
|
27405
|
+
index.indexes[path10] = { type: "AVL", node: new AVLTree(0, []), isArray };
|
|
27409
27406
|
break;
|
|
27410
27407
|
case "string":
|
|
27411
27408
|
case "string[]":
|
|
27412
|
-
index.indexes[
|
|
27413
|
-
index.avgFieldLength[
|
|
27414
|
-
index.frequencies[
|
|
27415
|
-
index.tokenOccurrences[
|
|
27416
|
-
index.fieldLengths[
|
|
27409
|
+
index.indexes[path10] = { type: "Radix", node: new RadixTree(), isArray };
|
|
27410
|
+
index.avgFieldLength[path10] = 0;
|
|
27411
|
+
index.frequencies[path10] = {};
|
|
27412
|
+
index.tokenOccurrences[path10] = {};
|
|
27413
|
+
index.fieldLengths[path10] = {};
|
|
27417
27414
|
break;
|
|
27418
27415
|
case "enum":
|
|
27419
27416
|
case "enum[]":
|
|
27420
|
-
index.indexes[
|
|
27417
|
+
index.indexes[path10] = { type: "Flat", node: new FlatTree(), isArray };
|
|
27421
27418
|
break;
|
|
27422
27419
|
case "geopoint":
|
|
27423
|
-
index.indexes[
|
|
27420
|
+
index.indexes[path10] = { type: "BKD", node: new BKDTree(), isArray };
|
|
27424
27421
|
break;
|
|
27425
27422
|
default:
|
|
27426
|
-
throw createError("INVALID_SCHEMA_TYPE", Array.isArray(type) ? "array" : type,
|
|
27423
|
+
throw createError("INVALID_SCHEMA_TYPE", Array.isArray(type) ? "array" : type, path10);
|
|
27427
27424
|
}
|
|
27428
|
-
index.searchableProperties.push(
|
|
27429
|
-
index.searchablePropertiesWithTypes[
|
|
27425
|
+
index.searchableProperties.push(path10);
|
|
27426
|
+
index.searchablePropertiesWithTypes[path10] = type;
|
|
27430
27427
|
}
|
|
27431
27428
|
}
|
|
27432
27429
|
return index;
|
|
@@ -27997,12 +27994,12 @@ function innerCreate(orama, sharedInternalDocumentStore, schema, sortableDeniedP
|
|
|
27997
27994
|
sorts: {}
|
|
27998
27995
|
};
|
|
27999
27996
|
for (const [prop, type] of Object.entries(schema)) {
|
|
28000
|
-
const
|
|
28001
|
-
if (sortableDeniedProperties.includes(
|
|
27997
|
+
const path10 = `${prefix}${prefix ? "." : ""}${prop}`;
|
|
27998
|
+
if (sortableDeniedProperties.includes(path10)) {
|
|
28002
27999
|
continue;
|
|
28003
28000
|
}
|
|
28004
28001
|
if (typeof type === "object" && !Array.isArray(type)) {
|
|
28005
|
-
const ret = innerCreate(orama, sharedInternalDocumentStore, type, sortableDeniedProperties,
|
|
28002
|
+
const ret = innerCreate(orama, sharedInternalDocumentStore, type, sortableDeniedProperties, path10);
|
|
28006
28003
|
safeArrayPush(sorter.sortableProperties, ret.sortableProperties);
|
|
28007
28004
|
sorter.sorts = {
|
|
28008
28005
|
...sorter.sorts,
|
|
@@ -28019,9 +28016,9 @@ function innerCreate(orama, sharedInternalDocumentStore, schema, sortableDeniedP
|
|
|
28019
28016
|
case "boolean":
|
|
28020
28017
|
case "number":
|
|
28021
28018
|
case "string":
|
|
28022
|
-
sorter.sortableProperties.push(
|
|
28023
|
-
sorter.sortablePropertiesWithTypes[
|
|
28024
|
-
sorter.sorts[
|
|
28019
|
+
sorter.sortableProperties.push(path10);
|
|
28020
|
+
sorter.sortablePropertiesWithTypes[path10] = type;
|
|
28021
|
+
sorter.sorts[path10] = {
|
|
28025
28022
|
docs: /* @__PURE__ */ new Map(),
|
|
28026
28023
|
orderedDocsToRemove: /* @__PURE__ */ new Map(),
|
|
28027
28024
|
orderedDocs: [],
|
|
@@ -28037,7 +28034,7 @@ function innerCreate(orama, sharedInternalDocumentStore, schema, sortableDeniedP
|
|
|
28037
28034
|
case "string[]":
|
|
28038
28035
|
continue;
|
|
28039
28036
|
default:
|
|
28040
|
-
throw createError("INVALID_SORT_SCHEMA_TYPE", Array.isArray(type) ? "array" : type,
|
|
28037
|
+
throw createError("INVALID_SORT_SCHEMA_TYPE", Array.isArray(type) ? "array" : type, path10);
|
|
28041
28038
|
}
|
|
28042
28039
|
}
|
|
28043
28040
|
}
|
|
@@ -29882,8 +29879,8 @@ function innerFullTextSearch(orama, params, language) {
|
|
|
29882
29879
|
function escapeRegex2(str2) {
|
|
29883
29880
|
return str2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
29884
29881
|
}
|
|
29885
|
-
function getPropValue(obj,
|
|
29886
|
-
const keys =
|
|
29882
|
+
function getPropValue(obj, path10) {
|
|
29883
|
+
const keys = path10.split(".");
|
|
29887
29884
|
let value = obj;
|
|
29888
29885
|
for (const key of keys) {
|
|
29889
29886
|
if (value && typeof value === "object" && key in value) {
|
|
@@ -31045,6 +31042,217 @@ var init_provider = __esm({
|
|
|
31045
31042
|
}
|
|
31046
31043
|
});
|
|
31047
31044
|
|
|
31045
|
+
// src/project/aliases.ts
|
|
31046
|
+
var aliases_exports = {};
|
|
31047
|
+
__export(aliases_exports, {
|
|
31048
|
+
autoMergeByBaseName: () => autoMergeByBaseName,
|
|
31049
|
+
getAllAliasGroups: () => getAllAliasGroups,
|
|
31050
|
+
getCanonicalId: () => getCanonicalId,
|
|
31051
|
+
initAliasRegistry: () => initAliasRegistry,
|
|
31052
|
+
registerAlias: () => registerAlias,
|
|
31053
|
+
resetAliasCache: () => resetAliasCache,
|
|
31054
|
+
resolveAliases: () => resolveAliases
|
|
31055
|
+
});
|
|
31056
|
+
import { promises as fs3 } from "fs";
|
|
31057
|
+
import path4 from "path";
|
|
31058
|
+
import os2 from "os";
|
|
31059
|
+
function normalizePath(p2) {
|
|
31060
|
+
let normalized = p2.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
31061
|
+
if (process.platform === "win32") {
|
|
31062
|
+
normalized = normalized.toLowerCase();
|
|
31063
|
+
}
|
|
31064
|
+
return normalized;
|
|
31065
|
+
}
|
|
31066
|
+
function idPriority(id) {
|
|
31067
|
+
if (id.startsWith("placeholder/")) return 0;
|
|
31068
|
+
if (id.startsWith("local/")) return 1;
|
|
31069
|
+
return 2;
|
|
31070
|
+
}
|
|
31071
|
+
function getRegistryPath(baseDir) {
|
|
31072
|
+
return path4.join(baseDir ?? registryDir ?? DEFAULT_DATA_DIR2, ALIAS_FILE);
|
|
31073
|
+
}
|
|
31074
|
+
async function loadRegistry(baseDir) {
|
|
31075
|
+
if (registryCache) return registryCache;
|
|
31076
|
+
try {
|
|
31077
|
+
const data = await fs3.readFile(getRegistryPath(baseDir), "utf-8");
|
|
31078
|
+
const parsed = JSON.parse(data);
|
|
31079
|
+
if (parsed.version === 1 && Array.isArray(parsed.groups)) {
|
|
31080
|
+
registryCache = parsed;
|
|
31081
|
+
return registryCache;
|
|
31082
|
+
}
|
|
31083
|
+
} catch {
|
|
31084
|
+
}
|
|
31085
|
+
registryCache = { version: 1, groups: [] };
|
|
31086
|
+
return registryCache;
|
|
31087
|
+
}
|
|
31088
|
+
async function saveRegistry(baseDir) {
|
|
31089
|
+
if (!registryCache) return;
|
|
31090
|
+
const filePath = getRegistryPath(baseDir);
|
|
31091
|
+
await fs3.mkdir(path4.dirname(filePath), { recursive: true });
|
|
31092
|
+
await fs3.writeFile(filePath, JSON.stringify(registryCache, null, 2), "utf-8");
|
|
31093
|
+
}
|
|
31094
|
+
function findMatchingGroup(registry2, projectInfo) {
|
|
31095
|
+
const normalizedRoot = normalizePath(projectInfo.rootPath);
|
|
31096
|
+
for (const group of registry2.groups) {
|
|
31097
|
+
if (group.aliases.includes(projectInfo.id)) return group;
|
|
31098
|
+
if (group.rootPaths.some((rp) => rp === normalizedRoot)) return group;
|
|
31099
|
+
if (projectInfo.gitRemote && group.gitRemote && group.gitRemote === projectInfo.gitRemote) {
|
|
31100
|
+
return group;
|
|
31101
|
+
}
|
|
31102
|
+
}
|
|
31103
|
+
return null;
|
|
31104
|
+
}
|
|
31105
|
+
function selectCanonical(aliases) {
|
|
31106
|
+
return [...aliases].sort((a3, b3) => idPriority(b3) - idPriority(a3))[0];
|
|
31107
|
+
}
|
|
31108
|
+
async function registerAlias(projectInfo, baseDir) {
|
|
31109
|
+
const registry2 = await loadRegistry(baseDir);
|
|
31110
|
+
const normalizedRoot = normalizePath(projectInfo.rootPath);
|
|
31111
|
+
const existingGroup = findMatchingGroup(registry2, projectInfo);
|
|
31112
|
+
if (existingGroup) {
|
|
31113
|
+
let changed = false;
|
|
31114
|
+
if (!existingGroup.aliases.includes(projectInfo.id)) {
|
|
31115
|
+
existingGroup.aliases.push(projectInfo.id);
|
|
31116
|
+
changed = true;
|
|
31117
|
+
}
|
|
31118
|
+
if (!existingGroup.rootPaths.includes(normalizedRoot)) {
|
|
31119
|
+
existingGroup.rootPaths.push(normalizedRoot);
|
|
31120
|
+
changed = true;
|
|
31121
|
+
}
|
|
31122
|
+
if (projectInfo.gitRemote && !existingGroup.gitRemote) {
|
|
31123
|
+
existingGroup.gitRemote = projectInfo.gitRemote;
|
|
31124
|
+
changed = true;
|
|
31125
|
+
}
|
|
31126
|
+
const newCanonical = selectCanonical(existingGroup.aliases);
|
|
31127
|
+
if (newCanonical !== existingGroup.canonical) {
|
|
31128
|
+
existingGroup.canonical = newCanonical;
|
|
31129
|
+
changed = true;
|
|
31130
|
+
}
|
|
31131
|
+
if (changed) {
|
|
31132
|
+
await saveRegistry(baseDir);
|
|
31133
|
+
}
|
|
31134
|
+
return existingGroup.canonical;
|
|
31135
|
+
}
|
|
31136
|
+
const newGroup = {
|
|
31137
|
+
canonical: projectInfo.id,
|
|
31138
|
+
aliases: [projectInfo.id],
|
|
31139
|
+
rootPaths: [normalizedRoot],
|
|
31140
|
+
...projectInfo.gitRemote ? { gitRemote: projectInfo.gitRemote } : {}
|
|
31141
|
+
};
|
|
31142
|
+
registry2.groups.push(newGroup);
|
|
31143
|
+
await saveRegistry(baseDir);
|
|
31144
|
+
return newGroup.canonical;
|
|
31145
|
+
}
|
|
31146
|
+
async function resolveAliases(projectId, baseDir) {
|
|
31147
|
+
const registry2 = await loadRegistry(baseDir);
|
|
31148
|
+
for (const group of registry2.groups) {
|
|
31149
|
+
if (group.aliases.includes(projectId) || group.canonical === projectId) {
|
|
31150
|
+
return [...group.aliases];
|
|
31151
|
+
}
|
|
31152
|
+
}
|
|
31153
|
+
return [projectId];
|
|
31154
|
+
}
|
|
31155
|
+
async function getCanonicalId(projectId, baseDir) {
|
|
31156
|
+
const registry2 = await loadRegistry(baseDir);
|
|
31157
|
+
for (const group of registry2.groups) {
|
|
31158
|
+
if (group.aliases.includes(projectId) || group.canonical === projectId) {
|
|
31159
|
+
return group.canonical;
|
|
31160
|
+
}
|
|
31161
|
+
}
|
|
31162
|
+
return projectId;
|
|
31163
|
+
}
|
|
31164
|
+
async function getAllAliasGroups(baseDir) {
|
|
31165
|
+
const registry2 = await loadRegistry(baseDir);
|
|
31166
|
+
return registry2.groups;
|
|
31167
|
+
}
|
|
31168
|
+
async function autoMergeByBaseName(observedIds, baseDir) {
|
|
31169
|
+
if (observedIds.length <= 1) return 0;
|
|
31170
|
+
const registry2 = await loadRegistry(baseDir);
|
|
31171
|
+
const byBaseName = /* @__PURE__ */ new Map();
|
|
31172
|
+
for (const id of observedIds) {
|
|
31173
|
+
const baseName = id.split("/").pop() ?? id;
|
|
31174
|
+
if (!byBaseName.has(baseName)) byBaseName.set(baseName, []);
|
|
31175
|
+
byBaseName.get(baseName).push(id);
|
|
31176
|
+
}
|
|
31177
|
+
let mergeCount = 0;
|
|
31178
|
+
for (const [_baseName, ids] of byBaseName) {
|
|
31179
|
+
if (ids.length <= 1) continue;
|
|
31180
|
+
const existingGroups = /* @__PURE__ */ new Set();
|
|
31181
|
+
const ungroupedIds = [];
|
|
31182
|
+
for (const id of ids) {
|
|
31183
|
+
const groupIdx = registry2.groups.findIndex(
|
|
31184
|
+
(g3) => g3.aliases.includes(id) || g3.canonical === id
|
|
31185
|
+
);
|
|
31186
|
+
if (groupIdx >= 0) {
|
|
31187
|
+
existingGroups.add(groupIdx);
|
|
31188
|
+
} else {
|
|
31189
|
+
ungroupedIds.push(id);
|
|
31190
|
+
}
|
|
31191
|
+
}
|
|
31192
|
+
if (existingGroups.size <= 1 && ungroupedIds.length === 0) continue;
|
|
31193
|
+
const allIdsInGroup = [...ids];
|
|
31194
|
+
const canonical = selectCanonical(allIdsInGroup);
|
|
31195
|
+
if (existingGroups.size > 0) {
|
|
31196
|
+
const primaryIdx = [...existingGroups][0];
|
|
31197
|
+
const primaryGroup = registry2.groups[primaryIdx];
|
|
31198
|
+
for (const id of allIdsInGroup) {
|
|
31199
|
+
if (!primaryGroup.aliases.includes(id)) {
|
|
31200
|
+
primaryGroup.aliases.push(id);
|
|
31201
|
+
}
|
|
31202
|
+
}
|
|
31203
|
+
const otherIdxs = [...existingGroups].slice(1).sort((a3, b3) => b3 - a3);
|
|
31204
|
+
for (const idx of otherIdxs) {
|
|
31205
|
+
const other = registry2.groups[idx];
|
|
31206
|
+
for (const alias of other.aliases) {
|
|
31207
|
+
if (!primaryGroup.aliases.includes(alias)) {
|
|
31208
|
+
primaryGroup.aliases.push(alias);
|
|
31209
|
+
}
|
|
31210
|
+
}
|
|
31211
|
+
for (const rp of other.rootPaths) {
|
|
31212
|
+
if (!primaryGroup.rootPaths.includes(rp)) {
|
|
31213
|
+
primaryGroup.rootPaths.push(rp);
|
|
31214
|
+
}
|
|
31215
|
+
}
|
|
31216
|
+
if (other.gitRemote && !primaryGroup.gitRemote) {
|
|
31217
|
+
primaryGroup.gitRemote = other.gitRemote;
|
|
31218
|
+
}
|
|
31219
|
+
registry2.groups.splice(idx, 1);
|
|
31220
|
+
}
|
|
31221
|
+
primaryGroup.canonical = selectCanonical(primaryGroup.aliases);
|
|
31222
|
+
mergeCount++;
|
|
31223
|
+
} else {
|
|
31224
|
+
registry2.groups.push({
|
|
31225
|
+
canonical,
|
|
31226
|
+
aliases: allIdsInGroup,
|
|
31227
|
+
rootPaths: []
|
|
31228
|
+
});
|
|
31229
|
+
mergeCount++;
|
|
31230
|
+
}
|
|
31231
|
+
}
|
|
31232
|
+
if (mergeCount > 0) {
|
|
31233
|
+
await saveRegistry(baseDir);
|
|
31234
|
+
}
|
|
31235
|
+
return mergeCount;
|
|
31236
|
+
}
|
|
31237
|
+
function initAliasRegistry(dataDir) {
|
|
31238
|
+
registryDir = dataDir;
|
|
31239
|
+
registryCache = null;
|
|
31240
|
+
}
|
|
31241
|
+
function resetAliasCache() {
|
|
31242
|
+
registryCache = null;
|
|
31243
|
+
}
|
|
31244
|
+
var DEFAULT_DATA_DIR2, ALIAS_FILE, registryCache, registryDir;
|
|
31245
|
+
var init_aliases = __esm({
|
|
31246
|
+
"src/project/aliases.ts"() {
|
|
31247
|
+
"use strict";
|
|
31248
|
+
init_esm_shims();
|
|
31249
|
+
DEFAULT_DATA_DIR2 = path4.join(os2.homedir(), ".memorix", "data");
|
|
31250
|
+
ALIAS_FILE = ".project-aliases.json";
|
|
31251
|
+
registryCache = null;
|
|
31252
|
+
registryDir = null;
|
|
31253
|
+
}
|
|
31254
|
+
});
|
|
31255
|
+
|
|
31048
31256
|
// src/store/orama-store.ts
|
|
31049
31257
|
var orama_store_exports = {};
|
|
31050
31258
|
__export(orama_store_exports, {
|
|
@@ -31116,17 +31324,27 @@ async function removeObservation(oramaId) {
|
|
|
31116
31324
|
}
|
|
31117
31325
|
async function searchObservations(options2) {
|
|
31118
31326
|
const database = await getDb();
|
|
31119
|
-
|
|
31327
|
+
let projectIds = null;
|
|
31120
31328
|
if (options2.projectId) {
|
|
31121
|
-
|
|
31329
|
+
try {
|
|
31330
|
+
const { resolveAliases: resolveAliases3 } = await Promise.resolve().then(() => (init_aliases(), aliases_exports));
|
|
31331
|
+
projectIds = await resolveAliases3(options2.projectId);
|
|
31332
|
+
} catch {
|
|
31333
|
+
projectIds = [options2.projectId];
|
|
31334
|
+
}
|
|
31335
|
+
}
|
|
31336
|
+
const filters = {};
|
|
31337
|
+
if (projectIds && projectIds.length === 1) {
|
|
31338
|
+
filters["projectId"] = projectIds[0];
|
|
31122
31339
|
}
|
|
31123
31340
|
if (options2.type) {
|
|
31124
31341
|
filters["type"] = options2.type;
|
|
31125
31342
|
}
|
|
31126
31343
|
const hasQuery = options2.query && options2.query.trim().length > 0;
|
|
31344
|
+
const requestLimit = projectIds && projectIds.length > 1 ? (options2.limit ?? 20) * 3 : options2.limit ?? 20;
|
|
31127
31345
|
let searchParams = {
|
|
31128
31346
|
term: options2.query,
|
|
31129
|
-
limit:
|
|
31347
|
+
limit: requestLimit,
|
|
31130
31348
|
...Object.keys(filters).length > 0 ? { where: filters } : {},
|
|
31131
31349
|
// Search specific fields (not tokens, accessCount, etc.)
|
|
31132
31350
|
properties: ["title", "entityName", "narrative", "facts", "concepts", "filesModified"],
|
|
@@ -31165,7 +31383,11 @@ async function searchObservations(options2) {
|
|
|
31165
31383
|
}
|
|
31166
31384
|
}
|
|
31167
31385
|
const results = await search2(database, searchParams);
|
|
31168
|
-
let intermediate = results.hits.
|
|
31386
|
+
let intermediate = results.hits.filter((hit) => {
|
|
31387
|
+
if (!projectIds || projectIds.length <= 1) return true;
|
|
31388
|
+
const doc = hit.document;
|
|
31389
|
+
return projectIds.includes(doc.projectId);
|
|
31390
|
+
}).map((hit) => {
|
|
31169
31391
|
const doc = hit.document;
|
|
31170
31392
|
const obsType = doc.type;
|
|
31171
31393
|
return {
|
|
@@ -31186,50 +31408,30 @@ async function searchObservations(options2) {
|
|
|
31186
31408
|
const untilDate = new Date(options2.until).getTime();
|
|
31187
31409
|
intermediate = intermediate.filter((e3) => new Date(e3.rawTime).getTime() <= untilDate);
|
|
31188
31410
|
}
|
|
31411
|
+
if (projectIds && projectIds.length > 1) {
|
|
31412
|
+
intermediate = intermediate.slice(0, options2.limit ?? 20);
|
|
31413
|
+
}
|
|
31189
31414
|
let entries = intermediate.map(({ rawTime: _4, ...rest }) => rest);
|
|
31190
31415
|
if (hasQuery && options2.query) {
|
|
31191
31416
|
const queryLower = options2.query.toLowerCase();
|
|
31192
31417
|
const queryTokens = queryLower.split(/\s+/).filter((t2) => t2.length > 1);
|
|
31418
|
+
const entryMap = new Map(entries.map((e3) => [e3.id, e3]));
|
|
31193
31419
|
for (const hit of results.hits) {
|
|
31194
31420
|
const doc = hit.document;
|
|
31195
|
-
const entry =
|
|
31421
|
+
const entry = entryMap.get(doc.observationId);
|
|
31196
31422
|
if (!entry) continue;
|
|
31197
31423
|
const reasons = [];
|
|
31198
|
-
|
|
31199
|
-
|
|
31200
|
-
|
|
31201
|
-
|
|
31202
|
-
|
|
31203
|
-
|
|
31204
|
-
|
|
31205
|
-
|
|
31206
|
-
|
|
31207
|
-
|
|
31208
|
-
|
|
31209
|
-
}
|
|
31210
|
-
for (const token of queryTokens) {
|
|
31211
|
-
if (doc.concepts.toLowerCase().includes(token)) {
|
|
31212
|
-
reasons.push("concept");
|
|
31213
|
-
break;
|
|
31214
|
-
}
|
|
31215
|
-
}
|
|
31216
|
-
for (const token of queryTokens) {
|
|
31217
|
-
if (doc.narrative.toLowerCase().includes(token)) {
|
|
31218
|
-
reasons.push("narrative");
|
|
31219
|
-
break;
|
|
31220
|
-
}
|
|
31221
|
-
}
|
|
31222
|
-
for (const token of queryTokens) {
|
|
31223
|
-
if (doc.facts.toLowerCase().includes(token)) {
|
|
31224
|
-
reasons.push("fact");
|
|
31225
|
-
break;
|
|
31226
|
-
}
|
|
31227
|
-
}
|
|
31228
|
-
for (const token of queryTokens) {
|
|
31229
|
-
if (doc.filesModified.toLowerCase().includes(token)) {
|
|
31230
|
-
reasons.push("file");
|
|
31231
|
-
break;
|
|
31232
|
-
}
|
|
31424
|
+
const fields = [
|
|
31425
|
+
["title", doc.title],
|
|
31426
|
+
["entity", doc.entityName],
|
|
31427
|
+
["concept", doc.concepts],
|
|
31428
|
+
["narrative", doc.narrative],
|
|
31429
|
+
["fact", doc.facts],
|
|
31430
|
+
["file", doc.filesModified]
|
|
31431
|
+
];
|
|
31432
|
+
for (const [name, value] of fields) {
|
|
31433
|
+
const valueLower = value.toLowerCase();
|
|
31434
|
+
if (queryTokens.some((t2) => valueLower.includes(t2))) reasons.push(name);
|
|
31233
31435
|
}
|
|
31234
31436
|
if (reasons.length === 0) reasons.push("fuzzy");
|
|
31235
31437
|
entry["matchedFields"] = reasons;
|
|
@@ -31238,8 +31440,8 @@ async function searchObservations(options2) {
|
|
|
31238
31440
|
if (options2.maxTokens && options2.maxTokens > 0) {
|
|
31239
31441
|
entries = applyTokenBudget(entries, options2.maxTokens);
|
|
31240
31442
|
}
|
|
31241
|
-
const
|
|
31242
|
-
recordAccessBatch(
|
|
31443
|
+
const hitDocs = results.hits.map((h3) => ({ id: h3.id, doc: h3.document }));
|
|
31444
|
+
recordAccessBatch(hitDocs).catch(() => {
|
|
31243
31445
|
});
|
|
31244
31446
|
return entries;
|
|
31245
31447
|
}
|
|
@@ -31288,20 +31490,12 @@ async function getTimeline(anchorId, _projectId, depthBefore = 3, depthAfter = 3
|
|
|
31288
31490
|
after
|
|
31289
31491
|
};
|
|
31290
31492
|
}
|
|
31291
|
-
async function recordAccessBatch(
|
|
31493
|
+
async function recordAccessBatch(hitDocs) {
|
|
31292
31494
|
const database = await getDb();
|
|
31293
31495
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
31294
|
-
for (const id of
|
|
31496
|
+
for (const { id, doc } of hitDocs) {
|
|
31295
31497
|
try {
|
|
31296
|
-
|
|
31297
|
-
term: "",
|
|
31298
|
-
where: { id },
|
|
31299
|
-
limit: 1
|
|
31300
|
-
});
|
|
31301
|
-
if (result.hits.length === 0) continue;
|
|
31302
|
-
const doc = result.hits[0].document;
|
|
31303
|
-
await remove4(database, id);
|
|
31304
|
-
await insert3(database, {
|
|
31498
|
+
await update(database, id, {
|
|
31305
31499
|
...doc,
|
|
31306
31500
|
accessCount: (doc.accessCount ?? 0) + 1,
|
|
31307
31501
|
lastAccessedAt: now
|
|
@@ -33355,6 +33549,7 @@ __export(observations_exports, {
|
|
|
33355
33549
|
getObservationCount: () => getObservationCount2,
|
|
33356
33550
|
getProjectObservations: () => getProjectObservations,
|
|
33357
33551
|
initObservations: () => initObservations,
|
|
33552
|
+
migrateProjectIds: () => migrateProjectIds,
|
|
33358
33553
|
reindexObservations: () => reindexObservations,
|
|
33359
33554
|
storeObservation: () => storeObservation,
|
|
33360
33555
|
suggestTopicKey: () => suggestTopicKey
|
|
@@ -33516,8 +33711,29 @@ function getObservation(id) {
|
|
|
33516
33711
|
return observations.find((o3) => o3.id === id);
|
|
33517
33712
|
}
|
|
33518
33713
|
function getProjectObservations(projectId) {
|
|
33714
|
+
if (Array.isArray(projectId)) {
|
|
33715
|
+
const idSet = new Set(projectId);
|
|
33716
|
+
return observations.filter((o3) => idSet.has(o3.projectId));
|
|
33717
|
+
}
|
|
33519
33718
|
return observations.filter((o3) => o3.projectId === projectId);
|
|
33520
33719
|
}
|
|
33720
|
+
async function migrateProjectIds(aliasIds, canonicalId) {
|
|
33721
|
+
const nonCanonical = new Set(aliasIds.filter((id) => id !== canonicalId));
|
|
33722
|
+
if (nonCanonical.size === 0) return 0;
|
|
33723
|
+
let migrated = 0;
|
|
33724
|
+
for (const obs of observations) {
|
|
33725
|
+
if (nonCanonical.has(obs.projectId)) {
|
|
33726
|
+
obs.projectId = canonicalId;
|
|
33727
|
+
migrated++;
|
|
33728
|
+
}
|
|
33729
|
+
}
|
|
33730
|
+
if (migrated > 0 && projectDir) {
|
|
33731
|
+
await withFileLock(projectDir, async () => {
|
|
33732
|
+
await saveObservationsJson(projectDir, observations);
|
|
33733
|
+
});
|
|
33734
|
+
}
|
|
33735
|
+
return migrated;
|
|
33736
|
+
}
|
|
33521
33737
|
function getAllObservations() {
|
|
33522
33738
|
return [...observations];
|
|
33523
33739
|
}
|
|
@@ -33857,31 +34073,34 @@ __export(detector_exports, {
|
|
|
33857
34073
|
});
|
|
33858
34074
|
import { execSync } from "child_process";
|
|
33859
34075
|
import { existsSync, readFileSync } from "fs";
|
|
33860
|
-
import
|
|
33861
|
-
import
|
|
34076
|
+
import os3 from "os";
|
|
34077
|
+
import path5 from "path";
|
|
33862
34078
|
function detectProject(cwd) {
|
|
33863
34079
|
const basePath = cwd ?? process.cwd();
|
|
33864
34080
|
const rootPath = getGitRoot(basePath) ?? findPackageRoot(basePath) ?? basePath;
|
|
33865
34081
|
const gitRemote = getGitRemote(rootPath);
|
|
33866
34082
|
if (gitRemote) {
|
|
33867
34083
|
const id2 = normalizeGitRemote(gitRemote);
|
|
33868
|
-
const name2 = id2.split("/").pop() ??
|
|
34084
|
+
const name2 = id2.split("/").pop() ?? path5.basename(rootPath);
|
|
33869
34085
|
return { id: id2, name: name2, gitRemote, rootPath };
|
|
33870
34086
|
}
|
|
33871
34087
|
if (isDangerousRoot(rootPath)) {
|
|
33872
|
-
|
|
33873
|
-
|
|
34088
|
+
const name2 = path5.basename(rootPath) || "unknown";
|
|
34089
|
+
const id2 = `placeholder/${name2}`;
|
|
34090
|
+
console.error(`[memorix] WARNING: cwd "${rootPath}" is not a project directory \u2014 using degraded mode (${id2})`);
|
|
34091
|
+
console.error(`[memorix] For best results, set MEMORIX_PROJECT_ROOT or --cwd to your project path.`);
|
|
34092
|
+
return { id: id2, name: name2, rootPath };
|
|
33874
34093
|
}
|
|
33875
|
-
const name =
|
|
34094
|
+
const name = path5.basename(rootPath);
|
|
33876
34095
|
const id = `local/${name}`;
|
|
33877
34096
|
return { id, name, rootPath };
|
|
33878
34097
|
}
|
|
33879
34098
|
function isDangerousRoot(dirPath) {
|
|
33880
|
-
const resolved =
|
|
33881
|
-
const home =
|
|
34099
|
+
const resolved = path5.resolve(dirPath);
|
|
34100
|
+
const home = path5.resolve(os3.homedir());
|
|
33882
34101
|
if (resolved === home) return true;
|
|
33883
|
-
if (resolved ===
|
|
33884
|
-
const basename2 =
|
|
34102
|
+
if (resolved === path5.parse(resolved).root) return true;
|
|
34103
|
+
const basename2 = path5.basename(resolved).toLowerCase();
|
|
33885
34104
|
const knownNonProjectDirs = /* @__PURE__ */ new Set([
|
|
33886
34105
|
// IDE / editor config dirs
|
|
33887
34106
|
".vscode",
|
|
@@ -33915,31 +34134,31 @@ function isDangerousRoot(dirPath) {
|
|
|
33915
34134
|
".memorix"
|
|
33916
34135
|
]);
|
|
33917
34136
|
if (knownNonProjectDirs.has(basename2)) {
|
|
33918
|
-
const parent =
|
|
33919
|
-
if (parent === home || parent ===
|
|
34137
|
+
const parent = path5.resolve(path5.dirname(resolved));
|
|
34138
|
+
if (parent === home || parent === path5.parse(parent).root) {
|
|
33920
34139
|
return true;
|
|
33921
34140
|
}
|
|
33922
34141
|
}
|
|
33923
34142
|
return false;
|
|
33924
34143
|
}
|
|
33925
34144
|
function findPackageRoot(cwd) {
|
|
33926
|
-
let dir =
|
|
33927
|
-
const root =
|
|
34145
|
+
let dir = path5.resolve(cwd);
|
|
34146
|
+
const root = path5.parse(dir).root;
|
|
33928
34147
|
while (dir !== root) {
|
|
33929
34148
|
if (isDangerousRoot(dir)) return null;
|
|
33930
|
-
if (existsSync(
|
|
34149
|
+
if (existsSync(path5.join(dir, "package.json"))) {
|
|
33931
34150
|
return dir;
|
|
33932
34151
|
}
|
|
33933
|
-
dir =
|
|
34152
|
+
dir = path5.dirname(dir);
|
|
33934
34153
|
}
|
|
33935
34154
|
return null;
|
|
33936
34155
|
}
|
|
33937
34156
|
function getGitRoot(cwd) {
|
|
33938
|
-
let dir =
|
|
33939
|
-
const fsRoot =
|
|
34157
|
+
let dir = path5.resolve(cwd);
|
|
34158
|
+
const fsRoot = path5.parse(dir).root;
|
|
33940
34159
|
while (dir !== fsRoot) {
|
|
33941
|
-
if (existsSync(
|
|
33942
|
-
dir =
|
|
34160
|
+
if (existsSync(path5.join(dir, ".git"))) return dir;
|
|
34161
|
+
dir = path5.dirname(dir);
|
|
33943
34162
|
}
|
|
33944
34163
|
try {
|
|
33945
34164
|
const root = execSync("git -c safe.directory=* rev-parse --show-toplevel", {
|
|
@@ -33970,7 +34189,7 @@ function getGitRemote(cwd) {
|
|
|
33970
34189
|
}
|
|
33971
34190
|
function readGitConfigRemote(cwd) {
|
|
33972
34191
|
try {
|
|
33973
|
-
const configPath =
|
|
34192
|
+
const configPath = path5.join(cwd, ".git", "config");
|
|
33974
34193
|
if (!existsSync(configPath)) return null;
|
|
33975
34194
|
const content = readFileSync(configPath, "utf-8");
|
|
33976
34195
|
const remoteMatch = content.match(/\[remote\s+"origin"\]([\s\S]*?)(?=\n\[|$)/);
|
|
@@ -37419,7 +37638,7 @@ var require_gray_matter = __commonJS({
|
|
|
37419
37638
|
"node_modules/gray-matter/index.js"(exports2, module2) {
|
|
37420
37639
|
"use strict";
|
|
37421
37640
|
init_esm_shims();
|
|
37422
|
-
var
|
|
37641
|
+
var fs7 = __require("fs");
|
|
37423
37642
|
var sections = require_section_matter();
|
|
37424
37643
|
var defaults = require_defaults2();
|
|
37425
37644
|
var stringify = require_stringify();
|
|
@@ -37503,7 +37722,7 @@ var require_gray_matter = __commonJS({
|
|
|
37503
37722
|
return stringify(file, data, options2);
|
|
37504
37723
|
};
|
|
37505
37724
|
matter9.read = function(filepath, options2) {
|
|
37506
|
-
const str2 =
|
|
37725
|
+
const str2 = fs7.readFileSync(filepath, "utf8");
|
|
37507
37726
|
const file = matter9(str2, options2);
|
|
37508
37727
|
file.path = filepath;
|
|
37509
37728
|
return file;
|
|
@@ -38123,8 +38342,8 @@ var syncer_exports = {};
|
|
|
38123
38342
|
__export(syncer_exports, {
|
|
38124
38343
|
RulesSyncer: () => RulesSyncer
|
|
38125
38344
|
});
|
|
38126
|
-
import { promises as
|
|
38127
|
-
import
|
|
38345
|
+
import { promises as fs4 } from "fs";
|
|
38346
|
+
import path6 from "path";
|
|
38128
38347
|
var RulesSyncer;
|
|
38129
38348
|
var init_syncer = __esm({
|
|
38130
38349
|
"src/rules/syncer.ts"() {
|
|
@@ -38165,8 +38384,8 @@ var init_syncer = __esm({
|
|
|
38165
38384
|
const found = await this.findFiles(scanPath);
|
|
38166
38385
|
for (const filePath of found) {
|
|
38167
38386
|
try {
|
|
38168
|
-
const content = await
|
|
38169
|
-
const relativePath =
|
|
38387
|
+
const content = await fs4.readFile(filePath, "utf-8");
|
|
38388
|
+
const relativePath = path6.relative(this.projectRoot, filePath).replace(/\\/g, "/");
|
|
38170
38389
|
const parsed = entry.adapter.parse(relativePath, content);
|
|
38171
38390
|
rules.push(...parsed);
|
|
38172
38391
|
} catch {
|
|
@@ -38234,7 +38453,7 @@ var init_syncer = __esm({
|
|
|
38234
38453
|
const entries = [];
|
|
38235
38454
|
for (const adapter of this.adapters.values()) {
|
|
38236
38455
|
const absolutePaths = adapter.filePatterns.map(
|
|
38237
|
-
(p2) =>
|
|
38456
|
+
(p2) => path6.join(this.projectRoot, p2)
|
|
38238
38457
|
);
|
|
38239
38458
|
entries.push({ adapter, paths: absolutePaths });
|
|
38240
38459
|
}
|
|
@@ -38242,13 +38461,13 @@ var init_syncer = __esm({
|
|
|
38242
38461
|
}
|
|
38243
38462
|
/** Find files matching a glob-like path (simple implementation) */
|
|
38244
38463
|
async findFiles(pattern) {
|
|
38245
|
-
const dir =
|
|
38246
|
-
const fileGlob =
|
|
38464
|
+
const dir = path6.dirname(pattern);
|
|
38465
|
+
const fileGlob = path6.basename(pattern);
|
|
38247
38466
|
try {
|
|
38248
|
-
const stat = await
|
|
38467
|
+
const stat = await fs4.stat(dir);
|
|
38249
38468
|
if (!stat.isDirectory()) {
|
|
38250
38469
|
try {
|
|
38251
|
-
await
|
|
38470
|
+
await fs4.access(pattern);
|
|
38252
38471
|
return [pattern];
|
|
38253
38472
|
} catch {
|
|
38254
38473
|
return [];
|
|
@@ -38256,7 +38475,7 @@ var init_syncer = __esm({
|
|
|
38256
38475
|
}
|
|
38257
38476
|
} catch {
|
|
38258
38477
|
try {
|
|
38259
|
-
await
|
|
38478
|
+
await fs4.access(pattern);
|
|
38260
38479
|
return [pattern];
|
|
38261
38480
|
} catch {
|
|
38262
38481
|
return [];
|
|
@@ -38264,16 +38483,16 @@ var init_syncer = __esm({
|
|
|
38264
38483
|
}
|
|
38265
38484
|
if (fileGlob.includes("*")) {
|
|
38266
38485
|
try {
|
|
38267
|
-
const files = await
|
|
38486
|
+
const files = await fs4.readdir(dir);
|
|
38268
38487
|
const ext = fileGlob.replace("*", "");
|
|
38269
|
-
return files.filter((f4) => ext ? f4.endsWith(ext) : true).map((f4) =>
|
|
38488
|
+
return files.filter((f4) => ext ? f4.endsWith(ext) : true).map((f4) => path6.join(dir, f4));
|
|
38270
38489
|
} catch {
|
|
38271
38490
|
return [];
|
|
38272
38491
|
}
|
|
38273
38492
|
}
|
|
38274
38493
|
try {
|
|
38275
|
-
await
|
|
38276
|
-
return [
|
|
38494
|
+
await fs4.access(path6.join(dir, fileGlob));
|
|
38495
|
+
return [path6.join(dir, fileGlob)];
|
|
38277
38496
|
} catch {
|
|
38278
38497
|
return [];
|
|
38279
38498
|
}
|
|
@@ -39108,10 +39327,10 @@ var init_engine2 = __esm({
|
|
|
39108
39327
|
for (const [target, adapter] of this.adapters) {
|
|
39109
39328
|
const configPath = adapter.getConfigPath(this.projectRoot);
|
|
39110
39329
|
const globalPath = adapter.getConfigPath();
|
|
39111
|
-
for (const
|
|
39112
|
-
if (existsSync3(
|
|
39330
|
+
for (const path10 of [configPath, globalPath]) {
|
|
39331
|
+
if (existsSync3(path10)) {
|
|
39113
39332
|
try {
|
|
39114
|
-
const content = readFileSync2(
|
|
39333
|
+
const content = readFileSync2(path10, "utf-8");
|
|
39115
39334
|
const servers = adapter.parse(content);
|
|
39116
39335
|
if (servers.length > 0) {
|
|
39117
39336
|
mcpConfigs[target] = servers;
|
|
@@ -40314,8 +40533,8 @@ __export(server_exports, {
|
|
|
40314
40533
|
startDashboard: () => startDashboard
|
|
40315
40534
|
});
|
|
40316
40535
|
import { createServer } from "http";
|
|
40317
|
-
import { promises as
|
|
40318
|
-
import
|
|
40536
|
+
import { promises as fs5 } from "fs";
|
|
40537
|
+
import path7 from "path";
|
|
40319
40538
|
import { exec } from "child_process";
|
|
40320
40539
|
function sendJson(res, data, status = 200) {
|
|
40321
40540
|
res.writeHead(status, {
|
|
@@ -40338,31 +40557,37 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir) {
|
|
|
40338
40557
|
let effectiveProjectId = projectId;
|
|
40339
40558
|
let effectiveProjectName = projectName;
|
|
40340
40559
|
if (requestedProject && requestedProject !== projectId) {
|
|
40341
|
-
|
|
40342
|
-
|
|
40343
|
-
|
|
40344
|
-
await fs4.access(candidateDir);
|
|
40345
|
-
effectiveDataDir = candidateDir;
|
|
40346
|
-
effectiveProjectId = requestedProject;
|
|
40347
|
-
effectiveProjectName = requestedProject.split("/").pop() || requestedProject;
|
|
40348
|
-
} catch {
|
|
40349
|
-
}
|
|
40560
|
+
effectiveDataDir = baseDir;
|
|
40561
|
+
effectiveProjectId = requestedProject;
|
|
40562
|
+
effectiveProjectName = requestedProject.split("/").pop() || requestedProject;
|
|
40350
40563
|
}
|
|
40351
40564
|
try {
|
|
40352
40565
|
switch (apiPath) {
|
|
40353
40566
|
case "/projects": {
|
|
40354
40567
|
try {
|
|
40355
|
-
const
|
|
40356
|
-
const
|
|
40357
|
-
|
|
40358
|
-
|
|
40359
|
-
|
|
40360
|
-
|
|
40361
|
-
|
|
40362
|
-
|
|
40363
|
-
|
|
40364
|
-
};
|
|
40365
|
-
|
|
40568
|
+
const allObs = await loadObservationsJson(baseDir);
|
|
40569
|
+
const projectSet = /* @__PURE__ */ new Map();
|
|
40570
|
+
for (const obs of allObs) {
|
|
40571
|
+
if (obs.projectId) {
|
|
40572
|
+
projectSet.set(obs.projectId, (projectSet.get(obs.projectId) || 0) + 1);
|
|
40573
|
+
}
|
|
40574
|
+
}
|
|
40575
|
+
let mergedSet = projectSet;
|
|
40576
|
+
try {
|
|
40577
|
+
const { getCanonicalId: getCanonicalId2 } = await Promise.resolve().then(() => (init_aliases(), aliases_exports));
|
|
40578
|
+
mergedSet = /* @__PURE__ */ new Map();
|
|
40579
|
+
for (const [id, count3] of projectSet) {
|
|
40580
|
+
const canonical = await getCanonicalId2(id);
|
|
40581
|
+
mergedSet.set(canonical, (mergedSet.get(canonical) || 0) + count3);
|
|
40582
|
+
}
|
|
40583
|
+
} catch {
|
|
40584
|
+
}
|
|
40585
|
+
const projects = Array.from(mergedSet.entries()).sort((a3, b3) => b3[1] - a3[1]).map(([id, count3]) => ({
|
|
40586
|
+
id,
|
|
40587
|
+
name: id.split("/").pop() || id,
|
|
40588
|
+
count: count3,
|
|
40589
|
+
isCurrent: id === projectId
|
|
40590
|
+
}));
|
|
40366
40591
|
sendJson(res, projects);
|
|
40367
40592
|
} catch {
|
|
40368
40593
|
sendJson(res, []);
|
|
@@ -40522,14 +40747,14 @@ async function serveStatic(req, res, staticDir) {
|
|
|
40522
40747
|
if (urlPath === "/" || !urlPath.includes(".")) {
|
|
40523
40748
|
urlPath = "/index.html";
|
|
40524
40749
|
}
|
|
40525
|
-
const filePath =
|
|
40750
|
+
const filePath = path7.join(staticDir, urlPath);
|
|
40526
40751
|
if (!filePath.startsWith(staticDir)) {
|
|
40527
40752
|
sendError(res, "Forbidden", 403);
|
|
40528
40753
|
return;
|
|
40529
40754
|
}
|
|
40530
40755
|
try {
|
|
40531
|
-
const data = await
|
|
40532
|
-
const ext =
|
|
40756
|
+
const data = await fs5.readFile(filePath);
|
|
40757
|
+
const ext = path7.extname(filePath);
|
|
40533
40758
|
res.writeHead(200, {
|
|
40534
40759
|
"Content-Type": MIME_TYPES[ext] || "application/octet-stream",
|
|
40535
40760
|
"Cache-Control": "no-cache"
|
|
@@ -40537,7 +40762,7 @@ async function serveStatic(req, res, staticDir) {
|
|
|
40537
40762
|
res.end(data);
|
|
40538
40763
|
} catch {
|
|
40539
40764
|
try {
|
|
40540
|
-
const indexData = await
|
|
40765
|
+
const indexData = await fs5.readFile(path7.join(staticDir, "index.html"));
|
|
40541
40766
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
40542
40767
|
res.end(indexData);
|
|
40543
40768
|
} catch {
|
|
@@ -40568,17 +40793,9 @@ async function startDashboard(dataDir, port, staticDir, projectId, projectName,
|
|
|
40568
40793
|
try {
|
|
40569
40794
|
const body = JSON.parse(await readBody(req));
|
|
40570
40795
|
if (body.projectId) {
|
|
40571
|
-
const sanitized = body.projectId.replace(/\//g, "--").replace(/[<>:"|?*\\]/g, "_");
|
|
40572
|
-
const candidateDir = path6.join(baseDir, sanitized);
|
|
40573
|
-
try {
|
|
40574
|
-
await fs4.access(candidateDir);
|
|
40575
|
-
} catch {
|
|
40576
|
-
sendError(res, `Project data directory not found: ${candidateDir}`, 404);
|
|
40577
|
-
return;
|
|
40578
|
-
}
|
|
40579
40796
|
state.projectId = body.projectId;
|
|
40580
40797
|
state.projectName = body.projectName || body.projectId.split("/").pop() || body.projectId;
|
|
40581
|
-
state.dataDir =
|
|
40798
|
+
state.dataDir = baseDir;
|
|
40582
40799
|
console.error(`[dashboard] Switched current project to: ${state.projectId}`);
|
|
40583
40800
|
sendJson(res, { ok: true, projectId: state.projectId, projectName: state.projectName });
|
|
40584
40801
|
} else {
|
|
@@ -40647,9 +40864,9 @@ __export(installers_exports, {
|
|
|
40647
40864
|
installHooks: () => installHooks,
|
|
40648
40865
|
uninstallHooks: () => uninstallHooks
|
|
40649
40866
|
});
|
|
40650
|
-
import * as
|
|
40651
|
-
import * as
|
|
40652
|
-
import * as
|
|
40867
|
+
import * as fs6 from "fs/promises";
|
|
40868
|
+
import * as path8 from "path";
|
|
40869
|
+
import * as os4 from "os";
|
|
40653
40870
|
function resolveHookCommand() {
|
|
40654
40871
|
if (process.platform === "win32") {
|
|
40655
40872
|
return "cmd /c memorix";
|
|
@@ -40797,81 +41014,81 @@ function generateKiroHookFiles() {
|
|
|
40797
41014
|
function getProjectConfigPath(agent, projectRoot) {
|
|
40798
41015
|
switch (agent) {
|
|
40799
41016
|
case "claude":
|
|
40800
|
-
return
|
|
41017
|
+
return path8.join(projectRoot, ".claude", "settings.local.json");
|
|
40801
41018
|
case "copilot":
|
|
40802
|
-
return
|
|
41019
|
+
return path8.join(projectRoot, ".github", "hooks", "memorix.json");
|
|
40803
41020
|
case "windsurf":
|
|
40804
|
-
return
|
|
41021
|
+
return path8.join(projectRoot, ".windsurf", "hooks.json");
|
|
40805
41022
|
case "cursor":
|
|
40806
|
-
return
|
|
41023
|
+
return path8.join(projectRoot, ".cursor", "hooks.json");
|
|
40807
41024
|
case "kiro":
|
|
40808
|
-
return
|
|
41025
|
+
return path8.join(projectRoot, ".kiro", "hooks", "memorix-agent-stop.kiro.hook");
|
|
40809
41026
|
case "codex":
|
|
40810
|
-
return
|
|
41027
|
+
return path8.join(projectRoot, "AGENTS.md");
|
|
40811
41028
|
case "antigravity":
|
|
40812
|
-
return
|
|
41029
|
+
return path8.join(projectRoot, ".gemini", "settings.json");
|
|
40813
41030
|
default:
|
|
40814
|
-
return
|
|
41031
|
+
return path8.join(projectRoot, ".memorix", "hooks.json");
|
|
40815
41032
|
}
|
|
40816
41033
|
}
|
|
40817
41034
|
function getGlobalConfigPath(agent) {
|
|
40818
|
-
const home =
|
|
41035
|
+
const home = os4.homedir();
|
|
40819
41036
|
switch (agent) {
|
|
40820
41037
|
case "claude":
|
|
40821
41038
|
case "copilot":
|
|
40822
|
-
return
|
|
41039
|
+
return path8.join(home, ".claude", "settings.json");
|
|
40823
41040
|
case "windsurf":
|
|
40824
|
-
return
|
|
41041
|
+
return path8.join(home, ".codeium", "windsurf", "hooks.json");
|
|
40825
41042
|
case "cursor":
|
|
40826
|
-
return
|
|
41043
|
+
return path8.join(home, ".cursor", "hooks.json");
|
|
40827
41044
|
case "antigravity":
|
|
40828
|
-
return
|
|
41045
|
+
return path8.join(home, ".gemini", "settings.json");
|
|
40829
41046
|
default:
|
|
40830
|
-
return
|
|
41047
|
+
return path8.join(home, ".memorix", "hooks.json");
|
|
40831
41048
|
}
|
|
40832
41049
|
}
|
|
40833
41050
|
async function detectInstalledAgents() {
|
|
40834
41051
|
const agents = [];
|
|
40835
|
-
const home =
|
|
40836
|
-
const claudeDir =
|
|
41052
|
+
const home = os4.homedir();
|
|
41053
|
+
const claudeDir = path8.join(home, ".claude");
|
|
40837
41054
|
try {
|
|
40838
|
-
await
|
|
41055
|
+
await fs6.access(claudeDir);
|
|
40839
41056
|
agents.push("claude");
|
|
40840
41057
|
} catch {
|
|
40841
41058
|
}
|
|
40842
|
-
const windsurfDir =
|
|
41059
|
+
const windsurfDir = path8.join(home, ".codeium", "windsurf");
|
|
40843
41060
|
try {
|
|
40844
|
-
await
|
|
41061
|
+
await fs6.access(windsurfDir);
|
|
40845
41062
|
agents.push("windsurf");
|
|
40846
41063
|
} catch {
|
|
40847
41064
|
}
|
|
40848
|
-
const cursorDir =
|
|
41065
|
+
const cursorDir = path8.join(home, ".cursor");
|
|
40849
41066
|
try {
|
|
40850
|
-
await
|
|
41067
|
+
await fs6.access(cursorDir);
|
|
40851
41068
|
agents.push("cursor");
|
|
40852
41069
|
} catch {
|
|
40853
41070
|
}
|
|
40854
|
-
const vscodeDir =
|
|
41071
|
+
const vscodeDir = path8.join(home, ".vscode");
|
|
40855
41072
|
try {
|
|
40856
|
-
await
|
|
41073
|
+
await fs6.access(vscodeDir);
|
|
40857
41074
|
agents.push("copilot");
|
|
40858
41075
|
} catch {
|
|
40859
41076
|
}
|
|
40860
|
-
const kiroConfig =
|
|
41077
|
+
const kiroConfig = path8.join(home, ".kiro");
|
|
40861
41078
|
try {
|
|
40862
|
-
await
|
|
41079
|
+
await fs6.access(kiroConfig);
|
|
40863
41080
|
agents.push("kiro");
|
|
40864
41081
|
} catch {
|
|
40865
41082
|
}
|
|
40866
|
-
const codexDir =
|
|
41083
|
+
const codexDir = path8.join(home, ".codex");
|
|
40867
41084
|
try {
|
|
40868
|
-
await
|
|
41085
|
+
await fs6.access(codexDir);
|
|
40869
41086
|
agents.push("codex");
|
|
40870
41087
|
} catch {
|
|
40871
41088
|
}
|
|
40872
|
-
const geminiDir =
|
|
41089
|
+
const geminiDir = path8.join(home, ".gemini");
|
|
40873
41090
|
try {
|
|
40874
|
-
await
|
|
41091
|
+
await fs6.access(geminiDir);
|
|
40875
41092
|
agents.push("antigravity");
|
|
40876
41093
|
} catch {
|
|
40877
41094
|
}
|
|
@@ -40910,18 +41127,18 @@ async function installHooks(agent, projectRoot, global = false) {
|
|
|
40910
41127
|
default:
|
|
40911
41128
|
generated = generateClaudeConfig();
|
|
40912
41129
|
}
|
|
40913
|
-
await
|
|
41130
|
+
await fs6.mkdir(path8.dirname(configPath), { recursive: true });
|
|
40914
41131
|
if (agent === "kiro") {
|
|
40915
41132
|
const hookFiles = generateKiroHookFiles();
|
|
40916
|
-
const hooksDir =
|
|
40917
|
-
await
|
|
41133
|
+
const hooksDir = path8.join(path8.dirname(configPath));
|
|
41134
|
+
await fs6.mkdir(hooksDir, { recursive: true });
|
|
40918
41135
|
for (const hf of hookFiles) {
|
|
40919
|
-
await
|
|
41136
|
+
await fs6.writeFile(path8.join(hooksDir, hf.filename), hf.content, "utf-8");
|
|
40920
41137
|
}
|
|
40921
41138
|
} else {
|
|
40922
41139
|
let existing = {};
|
|
40923
41140
|
try {
|
|
40924
|
-
const content = await
|
|
41141
|
+
const content = await fs6.readFile(configPath, "utf-8");
|
|
40925
41142
|
existing = JSON.parse(content);
|
|
40926
41143
|
} catch {
|
|
40927
41144
|
}
|
|
@@ -40948,7 +41165,7 @@ async function installHooks(agent, projectRoot, global = false) {
|
|
|
40948
41165
|
const h3 = merged.hooks;
|
|
40949
41166
|
if (h3) delete h3.preToolUse;
|
|
40950
41167
|
}
|
|
40951
|
-
await
|
|
41168
|
+
await fs6.writeFile(configPath, JSON.stringify(merged, null, 2), "utf-8");
|
|
40952
41169
|
}
|
|
40953
41170
|
const events = [];
|
|
40954
41171
|
switch (agent) {
|
|
@@ -40984,45 +41201,45 @@ async function installAgentRules(agent, projectRoot) {
|
|
|
40984
41201
|
let rulesPath;
|
|
40985
41202
|
switch (agent) {
|
|
40986
41203
|
case "windsurf":
|
|
40987
|
-
rulesPath =
|
|
41204
|
+
rulesPath = path8.join(projectRoot, ".windsurf", "rules", "memorix.md");
|
|
40988
41205
|
break;
|
|
40989
41206
|
case "cursor":
|
|
40990
|
-
rulesPath =
|
|
41207
|
+
rulesPath = path8.join(projectRoot, ".cursor", "rules", "memorix.mdc");
|
|
40991
41208
|
break;
|
|
40992
41209
|
case "claude":
|
|
40993
41210
|
case "copilot":
|
|
40994
|
-
rulesPath =
|
|
41211
|
+
rulesPath = path8.join(projectRoot, ".github", "copilot-instructions.md");
|
|
40995
41212
|
break;
|
|
40996
41213
|
case "codex":
|
|
40997
|
-
rulesPath =
|
|
41214
|
+
rulesPath = path8.join(projectRoot, "AGENTS.md");
|
|
40998
41215
|
break;
|
|
40999
41216
|
case "kiro":
|
|
41000
|
-
rulesPath =
|
|
41217
|
+
rulesPath = path8.join(projectRoot, ".kiro", "steering", "memorix.md");
|
|
41001
41218
|
break;
|
|
41002
41219
|
case "antigravity":
|
|
41003
|
-
rulesPath =
|
|
41220
|
+
rulesPath = path8.join(projectRoot, "GEMINI.md");
|
|
41004
41221
|
break;
|
|
41005
41222
|
default:
|
|
41006
|
-
rulesPath =
|
|
41223
|
+
rulesPath = path8.join(projectRoot, ".agent", "rules", "memorix.md");
|
|
41007
41224
|
break;
|
|
41008
41225
|
}
|
|
41009
41226
|
try {
|
|
41010
|
-
await
|
|
41227
|
+
await fs6.mkdir(path8.dirname(rulesPath), { recursive: true });
|
|
41011
41228
|
if (agent === "codex" || agent === "antigravity") {
|
|
41012
41229
|
try {
|
|
41013
|
-
const existing = await
|
|
41230
|
+
const existing = await fs6.readFile(rulesPath, "utf-8");
|
|
41014
41231
|
if (existing.includes("Memorix")) {
|
|
41015
41232
|
return;
|
|
41016
41233
|
}
|
|
41017
|
-
await
|
|
41234
|
+
await fs6.writeFile(rulesPath, existing + "\n\n" + rulesContent, "utf-8");
|
|
41018
41235
|
} catch {
|
|
41019
|
-
await
|
|
41236
|
+
await fs6.writeFile(rulesPath, rulesContent, "utf-8");
|
|
41020
41237
|
}
|
|
41021
41238
|
} else {
|
|
41022
41239
|
try {
|
|
41023
|
-
await
|
|
41240
|
+
await fs6.access(rulesPath);
|
|
41024
41241
|
} catch {
|
|
41025
|
-
await
|
|
41242
|
+
await fs6.writeFile(rulesPath, rulesContent, "utf-8");
|
|
41026
41243
|
}
|
|
41027
41244
|
}
|
|
41028
41245
|
} catch {
|
|
@@ -41107,15 +41324,15 @@ async function uninstallHooks(agent, projectRoot, global = false) {
|
|
|
41107
41324
|
const configPath = global ? getGlobalConfigPath(agent) : getProjectConfigPath(agent, projectRoot);
|
|
41108
41325
|
try {
|
|
41109
41326
|
if (agent === "kiro") {
|
|
41110
|
-
await
|
|
41327
|
+
await fs6.unlink(configPath);
|
|
41111
41328
|
} else {
|
|
41112
|
-
const content = await
|
|
41329
|
+
const content = await fs6.readFile(configPath, "utf-8");
|
|
41113
41330
|
const config2 = JSON.parse(content);
|
|
41114
41331
|
delete config2.hooks;
|
|
41115
41332
|
if (Object.keys(config2).length === 0) {
|
|
41116
|
-
await
|
|
41333
|
+
await fs6.unlink(configPath);
|
|
41117
41334
|
} else {
|
|
41118
|
-
await
|
|
41335
|
+
await fs6.writeFile(configPath, JSON.stringify(config2, null, 2), "utf-8");
|
|
41119
41336
|
}
|
|
41120
41337
|
}
|
|
41121
41338
|
return true;
|
|
@@ -41132,11 +41349,11 @@ async function getHookStatus(projectRoot) {
|
|
|
41132
41349
|
let installed = false;
|
|
41133
41350
|
let usedPath = projectPath;
|
|
41134
41351
|
try {
|
|
41135
|
-
await
|
|
41352
|
+
await fs6.access(projectPath);
|
|
41136
41353
|
installed = true;
|
|
41137
41354
|
} catch {
|
|
41138
41355
|
try {
|
|
41139
|
-
await
|
|
41356
|
+
await fs6.access(globalPath);
|
|
41140
41357
|
installed = true;
|
|
41141
41358
|
usedPath = globalPath;
|
|
41142
41359
|
} catch {
|
|
@@ -41212,18 +41429,7 @@ function coerceObjectArray(val) {
|
|
|
41212
41429
|
return [];
|
|
41213
41430
|
}
|
|
41214
41431
|
async function createMemorixServer(cwd, existingServer) {
|
|
41215
|
-
const
|
|
41216
|
-
if (project.id === "__invalid__") {
|
|
41217
|
-
const resolvedCwd = cwd ?? process.cwd();
|
|
41218
|
-
console.error(`[memorix] ERROR: Could not detect a valid project at: ${resolvedCwd}`);
|
|
41219
|
-
console.error(`[memorix] The directory is not a git repository and has no project indicator files.`);
|
|
41220
|
-
console.error(`[memorix] Fix: set --cwd to your project directory, or set MEMORIX_PROJECT_ROOT env var.`);
|
|
41221
|
-
console.error(`[memorix] Example: memorix serve --cwd /path/to/your/project`);
|
|
41222
|
-
console.error(`[memorix] Example: "env": { "MEMORIX_PROJECT_ROOT": "/path/to/your/project" }`);
|
|
41223
|
-
throw new Error(
|
|
41224
|
-
`Cannot start Memorix: no valid project detected at "${resolvedCwd}". Set --cwd or MEMORIX_PROJECT_ROOT to your project directory.`
|
|
41225
|
-
);
|
|
41226
|
-
}
|
|
41432
|
+
const rawProject = detectProject(cwd);
|
|
41227
41433
|
try {
|
|
41228
41434
|
const { migrateSubdirsToFlat: migrateSubdirsToFlat2 } = await Promise.resolve().then(() => (init_persistence(), persistence_exports));
|
|
41229
41435
|
const migrated = await migrateSubdirsToFlat2();
|
|
@@ -41232,10 +41438,44 @@ async function createMemorixServer(cwd, existingServer) {
|
|
|
41232
41438
|
}
|
|
41233
41439
|
} catch {
|
|
41234
41440
|
}
|
|
41235
|
-
const projectDir2 = await getProjectDataDir(
|
|
41441
|
+
const projectDir2 = await getProjectDataDir(rawProject.id);
|
|
41442
|
+
initAliasRegistry(projectDir2);
|
|
41443
|
+
const canonicalId = await registerAlias(rawProject);
|
|
41444
|
+
const project = { ...rawProject, id: canonicalId };
|
|
41445
|
+
if (canonicalId !== rawProject.id) {
|
|
41446
|
+
console.error(`[memorix] Alias resolved: ${rawProject.id} \u2192 ${canonicalId}`);
|
|
41447
|
+
}
|
|
41236
41448
|
const graphManager = new KnowledgeGraphManager(projectDir2);
|
|
41237
41449
|
await graphManager.init();
|
|
41238
41450
|
await initObservations(projectDir2);
|
|
41451
|
+
try {
|
|
41452
|
+
const { getAllObservations: getAllObservations2 } = await Promise.resolve().then(() => (init_observations(), observations_exports));
|
|
41453
|
+
const allObs = getAllObservations2();
|
|
41454
|
+
const observedIds = [...new Set(allObs.map((o3) => o3.projectId))];
|
|
41455
|
+
const merged = await autoMergeByBaseName(observedIds);
|
|
41456
|
+
if (merged > 0) {
|
|
41457
|
+
console.error(`[memorix] Auto-merged ${merged} alias group(s) by base name`);
|
|
41458
|
+
}
|
|
41459
|
+
} catch {
|
|
41460
|
+
}
|
|
41461
|
+
try {
|
|
41462
|
+
const { getAllAliasGroups: getAllAliasGroups2 } = await Promise.resolve().then(() => (init_aliases(), aliases_exports));
|
|
41463
|
+
const groups = await getAllAliasGroups2();
|
|
41464
|
+
let totalMigrated = 0;
|
|
41465
|
+
for (const group of groups) {
|
|
41466
|
+
if (group.aliases.length > 1) {
|
|
41467
|
+
const migrated = await migrateProjectIds(group.aliases, group.canonical);
|
|
41468
|
+
if (migrated > 0) {
|
|
41469
|
+
console.error(`[memorix] Migrated ${migrated} observations \u2192 ${group.canonical}`);
|
|
41470
|
+
totalMigrated += migrated;
|
|
41471
|
+
}
|
|
41472
|
+
}
|
|
41473
|
+
}
|
|
41474
|
+
if (totalMigrated > 0) {
|
|
41475
|
+
console.error(`[memorix] Total migrated: ${totalMigrated} observations across ${groups.filter((g3) => g3.aliases.length > 1).length} project(s)`);
|
|
41476
|
+
}
|
|
41477
|
+
} catch {
|
|
41478
|
+
}
|
|
41239
41479
|
const reindexed = await reindexObservations();
|
|
41240
41480
|
if (reindexed > 0) {
|
|
41241
41481
|
console.error(`[memorix] Reindexed ${reindexed} observations for project: ${project.id}`);
|
|
@@ -41947,9 +42187,9 @@ ${skill.content}` }]
|
|
|
41947
42187
|
lines.push(`- **Description**: ${sk.description}`);
|
|
41948
42188
|
lines.push(`- **Observations**: ${sk.content.split("\n").length} lines of knowledge`);
|
|
41949
42189
|
if (write && target) {
|
|
41950
|
-
const
|
|
41951
|
-
if (
|
|
41952
|
-
lines.push(`- \u2705 **Written**: \`${
|
|
42190
|
+
const path10 = engine.writeSkill(sk, target);
|
|
42191
|
+
if (path10) {
|
|
42192
|
+
lines.push(`- \u2705 **Written**: \`${path10}\``);
|
|
41953
42193
|
} else {
|
|
41954
42194
|
lines.push(`- \u274C Failed to write`);
|
|
41955
42195
|
}
|
|
@@ -42398,6 +42638,7 @@ var init_server4 = __esm({
|
|
|
42398
42638
|
init_entity_extractor();
|
|
42399
42639
|
init_engine();
|
|
42400
42640
|
init_detector();
|
|
42641
|
+
init_aliases();
|
|
42401
42642
|
init_persistence();
|
|
42402
42643
|
init_syncer();
|
|
42403
42644
|
init_engine2();
|
|
@@ -42456,7 +42697,8 @@ var init_serve = __esm({
|
|
|
42456
42697
|
const looksValid = existsSync5(join13(projectRoot, ".git")) || existsSync5(join13(projectRoot, "package.json")) || existsSync5(join13(projectRoot, "Cargo.toml")) || existsSync5(join13(projectRoot, "go.mod")) || existsSync5(join13(projectRoot, "pyproject.toml"));
|
|
42457
42698
|
if (!looksValid) {
|
|
42458
42699
|
const earlyDetect = detectProject2(projectRoot);
|
|
42459
|
-
|
|
42700
|
+
const isDegraded = earlyDetect.id.startsWith("placeholder/");
|
|
42701
|
+
if (!isDegraded) {
|
|
42460
42702
|
console.error(`[memorix] detectProject succeeded without standard indicators`);
|
|
42461
42703
|
const { server, projectId, deferredInit } = await createMemorixServer2(projectRoot);
|
|
42462
42704
|
const transport = new StdioServerTransport2();
|
|
@@ -42475,7 +42717,6 @@ var init_serve = __esm({
|
|
|
42475
42717
|
}));
|
|
42476
42718
|
const transport = new StdioServerTransport2();
|
|
42477
42719
|
await mcpServer.connect(transport);
|
|
42478
|
-
let rootResolved = false;
|
|
42479
42720
|
try {
|
|
42480
42721
|
const rootsResult = await Promise.race([
|
|
42481
42722
|
mcpServer.server.listRoots(),
|
|
@@ -42488,20 +42729,11 @@ var init_serve = __esm({
|
|
|
42488
42729
|
const normalizedPath = process.platform === "win32" && urlPath.match(/^\/[A-Za-z]:/) ? urlPath.slice(1) : urlPath;
|
|
42489
42730
|
console.error(`[memorix] MCP client root: ${normalizedPath}`);
|
|
42490
42731
|
projectRoot = normalizedPath;
|
|
42491
|
-
rootResolved = true;
|
|
42492
42732
|
}
|
|
42493
42733
|
}
|
|
42494
42734
|
} catch {
|
|
42495
42735
|
console.error(`[memorix] MCP roots not available (client may not support it)`);
|
|
42496
42736
|
}
|
|
42497
|
-
if (!rootResolved) {
|
|
42498
|
-
const retryDetect = detectProject2(projectRoot);
|
|
42499
|
-
if (retryDetect.id === "__invalid__") {
|
|
42500
|
-
console.error(`[memorix] ERROR: Could not detect a valid project.`);
|
|
42501
|
-
console.error(`[memorix] Fix: set --cwd or MEMORIX_PROJECT_ROOT, or use an IDE that supports MCP roots.`);
|
|
42502
|
-
process.exit(1);
|
|
42503
|
-
}
|
|
42504
|
-
}
|
|
42505
42737
|
const { projectId, deferredInit } = await createMemorixServer2(projectRoot, mcpServer);
|
|
42506
42738
|
console.error(`[memorix] MCP Server running on stdio (project: ${projectId})`);
|
|
42507
42739
|
console.error(`[memorix] Project root: ${projectRoot}`);
|
|
@@ -43367,8 +43599,8 @@ var init_sync = __esm({
|
|
|
43367
43599
|
run: async ({ args }) => {
|
|
43368
43600
|
const { detectProject: detectProject2 } = await Promise.resolve().then(() => (init_detector(), detector_exports));
|
|
43369
43601
|
const { RulesSyncer: RulesSyncer2 } = await Promise.resolve().then(() => (init_syncer(), syncer_exports));
|
|
43370
|
-
const { promises:
|
|
43371
|
-
const
|
|
43602
|
+
const { promises: fs7 } = await import("fs");
|
|
43603
|
+
const path10 = await import("path");
|
|
43372
43604
|
we("memorix sync");
|
|
43373
43605
|
const project = detectProject2();
|
|
43374
43606
|
v4.info(`Project: ${project.name} (${project.id})`);
|
|
@@ -43436,9 +43668,9 @@ var init_sync = __esm({
|
|
|
43436
43668
|
process.exit(0);
|
|
43437
43669
|
}
|
|
43438
43670
|
for (const file of files) {
|
|
43439
|
-
const fullPath =
|
|
43440
|
-
await
|
|
43441
|
-
await
|
|
43671
|
+
const fullPath = path10.join(project.rootPath, file.filePath);
|
|
43672
|
+
await fs7.mkdir(path10.dirname(fullPath), { recursive: true });
|
|
43673
|
+
await fs7.writeFile(fullPath, file.content, "utf-8");
|
|
43442
43674
|
v4.success(`Written: ${file.filePath}`);
|
|
43443
43675
|
}
|
|
43444
43676
|
fe2(`Synced ${files.length} rule(s) to ${target} format`);
|
|
@@ -44259,12 +44491,12 @@ var init_hooks_install = __esm({
|
|
|
44259
44491
|
},
|
|
44260
44492
|
run: async ({ args }) => {
|
|
44261
44493
|
const { detectInstalledAgents: detectInstalledAgents2, installHooks: installHooks2 } = await Promise.resolve().then(() => (init_installers(), installers_exports));
|
|
44262
|
-
const
|
|
44494
|
+
const os5 = await import("os");
|
|
44263
44495
|
let cwd;
|
|
44264
44496
|
try {
|
|
44265
44497
|
cwd = process.cwd();
|
|
44266
44498
|
} catch {
|
|
44267
|
-
cwd =
|
|
44499
|
+
cwd = os5.homedir();
|
|
44268
44500
|
console.log(`\u26A0\uFE0F Could not access current directory, using home: ${cwd}`);
|
|
44269
44501
|
}
|
|
44270
44502
|
let agents;
|
|
@@ -44327,12 +44559,12 @@ var init_hooks_uninstall = __esm({
|
|
|
44327
44559
|
},
|
|
44328
44560
|
run: async ({ args }) => {
|
|
44329
44561
|
const { detectInstalledAgents: detectInstalledAgents2, uninstallHooks: uninstallHooks2 } = await Promise.resolve().then(() => (init_installers(), installers_exports));
|
|
44330
|
-
const
|
|
44562
|
+
const os5 = await import("os");
|
|
44331
44563
|
let cwd;
|
|
44332
44564
|
try {
|
|
44333
44565
|
cwd = process.cwd();
|
|
44334
44566
|
} catch {
|
|
44335
|
-
cwd =
|
|
44567
|
+
cwd = os5.homedir();
|
|
44336
44568
|
}
|
|
44337
44569
|
let agents;
|
|
44338
44570
|
if (args.agent) {
|
|
@@ -44375,12 +44607,12 @@ var init_hooks_status = __esm({
|
|
|
44375
44607
|
},
|
|
44376
44608
|
run: async () => {
|
|
44377
44609
|
const { getHookStatus: getHookStatus2 } = await Promise.resolve().then(() => (init_installers(), installers_exports));
|
|
44378
|
-
const
|
|
44610
|
+
const os5 = await import("os");
|
|
44379
44611
|
let cwd;
|
|
44380
44612
|
try {
|
|
44381
44613
|
cwd = process.cwd();
|
|
44382
44614
|
} catch {
|
|
44383
|
-
cwd =
|
|
44615
|
+
cwd = os5.homedir();
|
|
44384
44616
|
}
|
|
44385
44617
|
const statuses = await getHookStatus2(cwd);
|
|
44386
44618
|
console.log("\nMemorix Hooks Status");
|
|
@@ -44429,7 +44661,7 @@ __export(dashboard_exports, {
|
|
|
44429
44661
|
default: () => dashboard_default
|
|
44430
44662
|
});
|
|
44431
44663
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
44432
|
-
import
|
|
44664
|
+
import path9 from "path";
|
|
44433
44665
|
var dashboard_default;
|
|
44434
44666
|
var init_dashboard = __esm({
|
|
44435
44667
|
"src/cli/commands/dashboard.ts"() {
|
|
@@ -44455,8 +44687,8 @@ var init_dashboard = __esm({
|
|
|
44455
44687
|
const project = detectProject2();
|
|
44456
44688
|
const dataDir = await getProjectDataDir2(project.id);
|
|
44457
44689
|
const port = parseInt(args.port, 10) || 3210;
|
|
44458
|
-
const cliDir =
|
|
44459
|
-
const staticDir =
|
|
44690
|
+
const cliDir = path9.dirname(fileURLToPath2(import.meta.url));
|
|
44691
|
+
const staticDir = path9.join(cliDir, "..", "dashboard", "static");
|
|
44460
44692
|
await startDashboard2(dataDir, port, staticDir, project.id, project.name);
|
|
44461
44693
|
await new Promise(() => {
|
|
44462
44694
|
});
|
|
@@ -44509,9 +44741,9 @@ var init_cleanup = __esm({
|
|
|
44509
44741
|
},
|
|
44510
44742
|
async run({ args }) {
|
|
44511
44743
|
const project = detectProject();
|
|
44512
|
-
if (project.id
|
|
44513
|
-
console.error("\
|
|
44514
|
-
|
|
44744
|
+
if (project.id.startsWith("placeholder/")) {
|
|
44745
|
+
console.error("\u26A0\uFE0F Not in a valid project directory \u2014 using degraded mode.");
|
|
44746
|
+
console.error("Set MEMORIX_PROJECT_ROOT or --cwd for best results.");
|
|
44515
44747
|
}
|
|
44516
44748
|
console.log(`
|
|
44517
44749
|
\u{1F4E6} Project: ${project.name} (${project.id})
|