memorix 1.8.9 → 1.9.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 +18 -0
- package/README.md +7 -0
- package/README.zh-CN.md +6 -0
- package/dist/cli/index.js +3261 -1348
- package/dist/index.js +324 -187
- package/dist/maintenance-runner.js +285 -103
- package/dist/media-audio-runner.js +285 -103
- package/dist/media-video-runner.js +285 -103
- package/dist/memcode-runtime/CHANGELOG.md +18 -0
- package/dist/sdk.js +323 -186
- package/dist/vector-backfill-runner.d.ts +4 -1
- package/dist/vector-backfill-runner.js +288 -104
- package/docs/API_REFERENCE.md +14 -0
- package/docs/CONFIGURATION.md +46 -0
- package/docs/DEVELOPMENT.md +2 -2
- package/docs/MULTI-DEVICE-SYNC-RESEARCH.md +344 -0
- package/docs/PERFORMANCE.md +32 -0
- package/docs/README.md +4 -2
- package/llms-full.txt +1 -0
- package/llms.txt +1 -0
- package/package.json +1 -1
- package/plugins/antigravity/memorix/plugin.json +1 -1
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +1 -1
- package/plugins/hermes/memorix/plugin.yaml +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/server.json +2 -2
- package/src/cli/command-guide.ts +9 -1
- package/src/cli/commands/serve-http.ts +11 -0
- package/src/cli/commands/sync-store.ts +191 -0
- package/src/cli/commands/sync.ts +8 -0
- package/src/memory/observations.ts +15 -2
- package/src/runtime/maintenance-targets.ts +6 -0
- package/src/runtime/vector-backfill-runner.ts +185 -7
- package/src/store/orama-store.ts +85 -102
- package/src/sync/adapters/fs.ts +179 -0
- package/src/sync/adapters/github.ts +258 -0
- package/src/sync/adapters/object-store.ts +267 -0
- package/src/sync/adapters/postgres.ts +269 -0
- package/src/sync/engine.ts +353 -0
- package/src/sync/journal.ts +162 -0
- package/src/sync/merge.ts +116 -0
- package/src/sync/namespace.ts +15 -0
- package/src/sync/paging.ts +45 -0
- package/src/sync/policy.ts +37 -0
- package/src/sync/remote-factory.ts +49 -0
- package/src/sync/store-port.ts +288 -0
- package/src/sync/types.ts +183 -0
package/dist/sdk.js
CHANGED
|
@@ -7280,6 +7280,14 @@ __export(orama_store_exports, {
|
|
|
7280
7280
|
updateObservationMetadata: () => updateObservationMetadata
|
|
7281
7281
|
});
|
|
7282
7282
|
import { create, insert as insert2, insertMultiple, search, remove as remove2, update, count, getByID } from "@orama/orama";
|
|
7283
|
+
function rememberSearchMode(key, value) {
|
|
7284
|
+
if (!lastSearchModeByProject.has(key) && lastSearchModeByProject.size >= MAX_SEARCH_MODE_KEYS) {
|
|
7285
|
+
const oldest = lastSearchModeByProject.keys().next().value;
|
|
7286
|
+
if (oldest !== void 0) lastSearchModeByProject.delete(oldest);
|
|
7287
|
+
}
|
|
7288
|
+
lastSearchModeByProject.delete(key);
|
|
7289
|
+
lastSearchModeByProject.set(key, value);
|
|
7290
|
+
}
|
|
7283
7291
|
function getLastSearchMode(projectId) {
|
|
7284
7292
|
return lastSearchModeByProject.get(projectId ?? SEARCH_MODE_DEFAULT_KEY) ?? "fulltext";
|
|
7285
7293
|
}
|
|
@@ -7292,9 +7300,6 @@ function makeEntryKey(projectId, observationId2) {
|
|
|
7292
7300
|
function rememberObservationDoc(doc) {
|
|
7293
7301
|
const publicDoc = { ...doc };
|
|
7294
7302
|
delete publicDoc.embedding;
|
|
7295
|
-
if (doc.projectId && typeof doc.observationId === "number") {
|
|
7296
|
-
docByObservationKey.set(makeEntryKey(doc.projectId, doc.observationId), publicDoc);
|
|
7297
|
-
}
|
|
7298
7303
|
return publicDoc;
|
|
7299
7304
|
}
|
|
7300
7305
|
function isCommandLikeQuery(query) {
|
|
@@ -7398,7 +7403,6 @@ async function resetDb() {
|
|
|
7398
7403
|
indexEmbeddingProvider = null;
|
|
7399
7404
|
deferredCachedVectorHydration = null;
|
|
7400
7405
|
lastSearchModeByProject.clear();
|
|
7401
|
-
docByObservationKey.clear();
|
|
7402
7406
|
}
|
|
7403
7407
|
function isEmbeddingEnabled() {
|
|
7404
7408
|
return embeddingEnabled;
|
|
@@ -7461,78 +7465,72 @@ function isCompatibleCachedVector(vector) {
|
|
|
7461
7465
|
vector && embeddingDimensions !== null && vector.length === embeddingDimensions && vector.every(Number.isFinite)
|
|
7462
7466
|
);
|
|
7463
7467
|
}
|
|
7464
|
-
async function attachCachedVectors(database,
|
|
7465
|
-
const
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7476
|
-
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
|
|
7468
|
+
async function attachCachedVectors(database, observations2) {
|
|
7469
|
+
const batchSize = 200;
|
|
7470
|
+
for (let start = 0; start < observations2.length; start += batchSize) {
|
|
7471
|
+
const batch = observations2.slice(start, start + batchSize);
|
|
7472
|
+
const cachedVectors = await getCachedEmbeddings(batch.map(observationEmbeddingText));
|
|
7473
|
+
if (db !== database) return;
|
|
7474
|
+
for (let index = 0; index < batch.length; index++) {
|
|
7475
|
+
const vector = cachedVectors[index];
|
|
7476
|
+
if (!isCompatibleCachedVector(vector)) continue;
|
|
7477
|
+
const id = makeOramaObservationId(batch[index].projectId, batch[index].id);
|
|
7478
|
+
const existing = getByID(database, id);
|
|
7479
|
+
if (!existing || documentEmbeddingText(existing) !== observationEmbeddingText(batch[index])) continue;
|
|
7480
|
+
try {
|
|
7481
|
+
await update(database, id, { ...existing, embedding: vector });
|
|
7482
|
+
} catch {
|
|
7483
|
+
}
|
|
7480
7484
|
}
|
|
7485
|
+
await new Promise((resolve5) => setImmediate(resolve5));
|
|
7481
7486
|
}
|
|
7482
7487
|
}
|
|
7483
7488
|
async function hydrateIndex(observations2, options = {}) {
|
|
7484
7489
|
const database = await getDb({ allowNetworkProbe: options.allowNetworkProbe });
|
|
7485
|
-
const candidates = [];
|
|
7486
|
-
for (const observation of observations2) {
|
|
7487
|
-
if (!observation || !observation.id || !observation.projectId) continue;
|
|
7488
|
-
const id = makeOramaObservationId(observation.projectId, observation.id);
|
|
7489
|
-
if (getByID(database, id)) continue;
|
|
7490
|
-
candidates.push({ observation, id });
|
|
7491
|
-
}
|
|
7492
7490
|
const deferCachedVectors = options.deferCachedVectors === true && Boolean(indexEmbeddingProvider?.getCachedEmbeddings);
|
|
7493
|
-
const cachedVectors = deferCachedVectors ? candidates.map(() => null) : await getCachedEmbeddings(candidates.map(({ observation }) => observationEmbeddingText(observation)));
|
|
7494
|
-
const documents = [];
|
|
7495
|
-
for (let index = 0; index < candidates.length; index++) {
|
|
7496
|
-
const { observation: obs, id } = candidates[index];
|
|
7497
|
-
try {
|
|
7498
|
-
const vector = cachedVectors[index];
|
|
7499
|
-
const compatibleVector = isCompatibleCachedVector(vector) ? vector : null;
|
|
7500
|
-
const doc = {
|
|
7501
|
-
id,
|
|
7502
|
-
observationId: obs.id,
|
|
7503
|
-
entityName: obs.entityName || "",
|
|
7504
|
-
type: obs.type || "discovery",
|
|
7505
|
-
title: obs.title || "",
|
|
7506
|
-
narrative: obs.narrative || "",
|
|
7507
|
-
facts: Array.isArray(obs.facts) ? obs.facts.join(" ") : "",
|
|
7508
|
-
filesModified: Array.isArray(obs.filesModified) ? obs.filesModified.join(" ") : "",
|
|
7509
|
-
concepts: Array.isArray(obs.concepts) ? obs.concepts.join(" ") : "",
|
|
7510
|
-
tokens: obs.tokens ?? 0,
|
|
7511
|
-
createdAt: obs.createdAt || "",
|
|
7512
|
-
projectId: obs.projectId,
|
|
7513
|
-
accessCount: obs.accessCount ?? 0,
|
|
7514
|
-
lastAccessedAt: obs.lastAccessedAt || "",
|
|
7515
|
-
status: obs.status ?? "active",
|
|
7516
|
-
source: obs.source || "agent",
|
|
7517
|
-
sourceDetail: obs.sourceDetail ?? "",
|
|
7518
|
-
valueCategory: obs.valueCategory ?? "",
|
|
7519
|
-
admissionState: obs.admissionState ?? "",
|
|
7520
|
-
admissionReason: obs.admissionReason ?? "",
|
|
7521
|
-
visibility: obs.visibility ?? "project",
|
|
7522
|
-
createdByAgentId: obs.createdByAgentId ?? "",
|
|
7523
|
-
sharedWithAgentIds: JSON.stringify(obs.sharedWithAgentIds ?? []),
|
|
7524
|
-
documentType: "observation",
|
|
7525
|
-
knowledgeLayer: resolveKnowledgeLayer("observation", obs.sourceDetail, obs.source),
|
|
7526
|
-
...compatibleVector ? { embedding: compatibleVector } : {}
|
|
7527
|
-
};
|
|
7528
|
-
documents.push(doc);
|
|
7529
|
-
} catch {
|
|
7530
|
-
}
|
|
7531
|
-
}
|
|
7532
7491
|
let inserted = 0;
|
|
7533
7492
|
const hydrationBatchSize = 200;
|
|
7534
|
-
for (let start = 0; start <
|
|
7535
|
-
const
|
|
7493
|
+
for (let start = 0; start < observations2.length; start += hydrationBatchSize) {
|
|
7494
|
+
const batchObservations = observations2.slice(start, start + hydrationBatchSize).filter((observation) => observation && observation.id && observation.projectId).filter((observation) => !getByID(database, makeOramaObservationId(observation.projectId, observation.id)));
|
|
7495
|
+
if (batchObservations.length === 0) continue;
|
|
7496
|
+
const cachedVectors = deferCachedVectors || options.skipCachedVectors ? batchObservations.map(() => null) : await getCachedEmbeddings(batchObservations.map(observationEmbeddingText));
|
|
7497
|
+
const batch = [];
|
|
7498
|
+
for (let index = 0; index < batchObservations.length; index++) {
|
|
7499
|
+
const obs = batchObservations[index];
|
|
7500
|
+
try {
|
|
7501
|
+
const compatibleVector = isCompatibleCachedVector(cachedVectors[index]) ? cachedVectors[index] : null;
|
|
7502
|
+
batch.push({
|
|
7503
|
+
id: makeOramaObservationId(obs.projectId, obs.id),
|
|
7504
|
+
observationId: obs.id,
|
|
7505
|
+
entityName: obs.entityName || "",
|
|
7506
|
+
type: obs.type || "discovery",
|
|
7507
|
+
title: obs.title || "",
|
|
7508
|
+
narrative: obs.narrative || "",
|
|
7509
|
+
facts: Array.isArray(obs.facts) ? obs.facts.join(" ") : "",
|
|
7510
|
+
filesModified: Array.isArray(obs.filesModified) ? obs.filesModified.join(" ") : "",
|
|
7511
|
+
concepts: Array.isArray(obs.concepts) ? obs.concepts.join(" ") : "",
|
|
7512
|
+
tokens: obs.tokens ?? 0,
|
|
7513
|
+
createdAt: obs.createdAt || "",
|
|
7514
|
+
projectId: obs.projectId,
|
|
7515
|
+
accessCount: obs.accessCount ?? 0,
|
|
7516
|
+
lastAccessedAt: obs.lastAccessedAt || "",
|
|
7517
|
+
status: obs.status ?? "active",
|
|
7518
|
+
source: obs.source || "agent",
|
|
7519
|
+
sourceDetail: obs.sourceDetail ?? "",
|
|
7520
|
+
valueCategory: obs.valueCategory ?? "",
|
|
7521
|
+
admissionState: obs.admissionState ?? "",
|
|
7522
|
+
admissionReason: obs.admissionReason ?? "",
|
|
7523
|
+
visibility: obs.visibility ?? "project",
|
|
7524
|
+
createdByAgentId: obs.createdByAgentId ?? "",
|
|
7525
|
+
sharedWithAgentIds: JSON.stringify(obs.sharedWithAgentIds ?? []),
|
|
7526
|
+
documentType: "observation",
|
|
7527
|
+
knowledgeLayer: resolveKnowledgeLayer("observation", obs.sourceDetail, obs.source),
|
|
7528
|
+
...compatibleVector ? { embedding: compatibleVector } : {}
|
|
7529
|
+
});
|
|
7530
|
+
} catch {
|
|
7531
|
+
}
|
|
7532
|
+
}
|
|
7533
|
+
if (batch.length === 0) continue;
|
|
7536
7534
|
try {
|
|
7537
7535
|
await insertMultiple(database, batch, batch.length);
|
|
7538
7536
|
for (const doc of batch) rememberObservationDoc(doc);
|
|
@@ -7554,7 +7552,7 @@ async function hydrateIndex(observations2, options = {}) {
|
|
|
7554
7552
|
}
|
|
7555
7553
|
await new Promise((resolve5) => setImmediate(resolve5));
|
|
7556
7554
|
}
|
|
7557
|
-
deferredCachedVectorHydration = options.skipCachedVectors ? null : deferCachedVectors ? attachCachedVectors(database,
|
|
7555
|
+
deferredCachedVectorHydration = options.skipCachedVectors ? null : deferCachedVectors ? attachCachedVectors(database, observations2).catch(() => {
|
|
7558
7556
|
}) : null;
|
|
7559
7557
|
return inserted;
|
|
7560
7558
|
}
|
|
@@ -7591,12 +7589,6 @@ async function updateObservationMetadata(projectId, observationId2, patch) {
|
|
|
7591
7589
|
async function removeObservation(oramaId) {
|
|
7592
7590
|
const database = await getDb();
|
|
7593
7591
|
await remove2(database, oramaId);
|
|
7594
|
-
for (const [key, doc] of docByObservationKey.entries()) {
|
|
7595
|
-
if (doc.id === oramaId) {
|
|
7596
|
-
docByObservationKey.delete(key);
|
|
7597
|
-
break;
|
|
7598
|
-
}
|
|
7599
|
-
}
|
|
7600
7592
|
}
|
|
7601
7593
|
async function searchObservations(options) {
|
|
7602
7594
|
const perf = !!process.env.MEMORIX_PERF;
|
|
@@ -7611,7 +7603,7 @@ async function searchObservations(options) {
|
|
|
7611
7603
|
const modeKey = options.projectId ?? SEARCH_MODE_DEFAULT_KEY;
|
|
7612
7604
|
const quality = options.quality ?? "balanced";
|
|
7613
7605
|
const database = await getDb();
|
|
7614
|
-
|
|
7606
|
+
rememberSearchMode(
|
|
7615
7607
|
modeKey,
|
|
7616
7608
|
quality === "fast" ? "fulltext (fast profile)" : embeddingEnabled ? "hybrid" : "fulltext"
|
|
7617
7609
|
);
|
|
@@ -7678,7 +7670,7 @@ async function searchObservations(options) {
|
|
|
7678
7670
|
if (provider2) {
|
|
7679
7671
|
const activeVectorDimensions = getVectorDimensions();
|
|
7680
7672
|
if (activeVectorDimensions !== null && provider2.dimensions !== activeVectorDimensions) {
|
|
7681
|
-
|
|
7673
|
+
rememberSearchMode(
|
|
7682
7674
|
modeKey,
|
|
7683
7675
|
`fulltext (embedding dimension mismatch: provider ${provider2.dimensions}d vs index ${activeVectorDimensions}d)`
|
|
7684
7676
|
);
|
|
@@ -7703,7 +7695,7 @@ async function searchObservations(options) {
|
|
|
7703
7695
|
mark("embedding");
|
|
7704
7696
|
const cjkRatio = (originalQuery.match(/[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]/g) || []).length / originalQuery.length;
|
|
7705
7697
|
const isCJKHeavy = cjkRatio > 0.3;
|
|
7706
|
-
|
|
7698
|
+
rememberSearchMode(modeKey, "hybrid");
|
|
7707
7699
|
searchParams = {
|
|
7708
7700
|
...searchParams,
|
|
7709
7701
|
mode: "hybrid",
|
|
@@ -7719,7 +7711,7 @@ async function searchObservations(options) {
|
|
|
7719
7711
|
}
|
|
7720
7712
|
}
|
|
7721
7713
|
} catch (error) {
|
|
7722
|
-
|
|
7714
|
+
rememberSearchMode(modeKey, "fulltext (embedding unavailable)");
|
|
7723
7715
|
console.error("[memorix] Embedding failed or timed out, falling back to fulltext search");
|
|
7724
7716
|
}
|
|
7725
7717
|
}
|
|
@@ -7729,7 +7721,7 @@ async function searchObservations(options) {
|
|
|
7729
7721
|
results = await search(database, searchParams);
|
|
7730
7722
|
} catch (error) {
|
|
7731
7723
|
if (queryVector && isVectorDimensionMismatchError(error)) {
|
|
7732
|
-
|
|
7724
|
+
rememberSearchMode(modeKey, "fulltext (embedding dimension mismatch)");
|
|
7733
7725
|
console.error("[memorix] Vector search dimension mismatch detected, retrying without embeddings");
|
|
7734
7726
|
results = await search(database, stripVectorSearchParams(searchParams));
|
|
7735
7727
|
} else {
|
|
@@ -7751,7 +7743,7 @@ async function searchObservations(options) {
|
|
|
7751
7743
|
},
|
|
7752
7744
|
similarity: 0.25
|
|
7753
7745
|
};
|
|
7754
|
-
|
|
7746
|
+
rememberSearchMode(modeKey, "vector-only (hybrid empty fallback)");
|
|
7755
7747
|
results = await search(database, vectorOnlyParams);
|
|
7756
7748
|
} catch {
|
|
7757
7749
|
}
|
|
@@ -7992,7 +7984,7 @@ async function searchObservations(options) {
|
|
|
7992
7984
|
const rerankedTop = neural.map((row) => candidateMap.get(row.id)).filter((entry) => entry != null);
|
|
7993
7985
|
if (rerankedTop.length > 0) {
|
|
7994
7986
|
intermediate = [...rerankedTop, ...intermediate.slice(RERANK_TOP_K)];
|
|
7995
|
-
|
|
7987
|
+
rememberSearchMode(modeKey, (lastSearchModeByProject.get(modeKey) ?? "fulltext") + " + neural rerank");
|
|
7996
7988
|
mark("rerank(usedNeural=true)");
|
|
7997
7989
|
}
|
|
7998
7990
|
}
|
|
@@ -8009,7 +8001,7 @@ async function searchObservations(options) {
|
|
|
8009
8001
|
);
|
|
8010
8002
|
mark(`rerank(usedLLM=${usedLLM})`);
|
|
8011
8003
|
if (usedLLM) {
|
|
8012
|
-
|
|
8004
|
+
rememberSearchMode(modeKey, (lastSearchModeByProject.get(modeKey) ?? "fulltext") + " + LLM rerank");
|
|
8013
8005
|
const rerankedTop = reranked.map((row) => candidateMap.get(row.id)).filter((entry) => entry != null);
|
|
8014
8006
|
if (rerankedTop.length > 0) {
|
|
8015
8007
|
intermediate = [...rerankedTop, ...intermediate.slice(RERANK_TOP_K)];
|
|
@@ -8082,13 +8074,6 @@ async function getObservationsByIds(ids, projectId) {
|
|
|
8082
8074
|
const database = await getDb();
|
|
8083
8075
|
const results = [];
|
|
8084
8076
|
for (const id of ids) {
|
|
8085
|
-
if (projectId) {
|
|
8086
|
-
const cached = docByObservationKey.get(makeEntryKey(projectId, id));
|
|
8087
|
-
if (cached) {
|
|
8088
|
-
results.push(cached);
|
|
8089
|
-
continue;
|
|
8090
|
-
}
|
|
8091
|
-
}
|
|
8092
8077
|
const searchResult = await search(database, {
|
|
8093
8078
|
term: "",
|
|
8094
8079
|
includeVectors: true,
|
|
@@ -8188,7 +8173,7 @@ function formatTime(isoDate) {
|
|
|
8188
8173
|
return isoDate;
|
|
8189
8174
|
}
|
|
8190
8175
|
}
|
|
8191
|
-
var db, dbInitPromise, dbGeneration, embeddingEnabled, embeddingDimensions, indexEmbeddingProvider, deferredCachedVectorHydration,
|
|
8176
|
+
var db, dbInitPromise, dbGeneration, embeddingEnabled, embeddingDimensions, indexEmbeddingProvider, deferredCachedVectorHydration, NON_CJK_HYBRID_SIMILARITY, lastSearchModeByProject, SEARCH_MODE_DEFAULT_KEY, MAX_SEARCH_MODE_KEYS, COMMAND_LOG_TITLE2, COMMAND_STYLE_TITLE, COMMAND_LIKE_QUERY2, COMMAND_INTENT_QUERY, NATURAL_LANGUAGE_MARKERS;
|
|
8192
8177
|
var init_orama_store = __esm({
|
|
8193
8178
|
"src/store/orama-store.ts"() {
|
|
8194
8179
|
"use strict";
|
|
@@ -8209,10 +8194,10 @@ var init_orama_store = __esm({
|
|
|
8209
8194
|
embeddingDimensions = null;
|
|
8210
8195
|
indexEmbeddingProvider = null;
|
|
8211
8196
|
deferredCachedVectorHydration = null;
|
|
8212
|
-
docByObservationKey = /* @__PURE__ */ new Map();
|
|
8213
8197
|
NON_CJK_HYBRID_SIMILARITY = 0.45;
|
|
8214
8198
|
lastSearchModeByProject = /* @__PURE__ */ new Map();
|
|
8215
8199
|
SEARCH_MODE_DEFAULT_KEY = "__global__";
|
|
8200
|
+
MAX_SEARCH_MODE_KEYS = 4096;
|
|
8216
8201
|
COMMAND_LOG_TITLE2 = /^(Ran:|Command:|Executed:)\s/i;
|
|
8217
8202
|
COMMAND_STYLE_TITLE = /(\bfindstr\b|\bSelect-String\b|\bGet-Content\b|\bnpx\s+vitest\b|\bnpx\s+tsc\b|\b2>&1\b)/i;
|
|
8218
8203
|
COMMAND_LIKE_QUERY2 = /\b(git|npm|npx|pnpm|yarn|node|bash|powershell|curl|memorix)\b/i;
|
|
@@ -9640,6 +9625,60 @@ var init_evidence_store = __esm({
|
|
|
9640
9625
|
}
|
|
9641
9626
|
});
|
|
9642
9627
|
|
|
9628
|
+
// src/runtime/maintenance-targets.ts
|
|
9629
|
+
var maintenance_targets_exports = {};
|
|
9630
|
+
__export(maintenance_targets_exports, {
|
|
9631
|
+
MaintenanceTargetStore: () => MaintenanceTargetStore
|
|
9632
|
+
});
|
|
9633
|
+
function rowToTarget(row) {
|
|
9634
|
+
return {
|
|
9635
|
+
projectId: row.project_id,
|
|
9636
|
+
projectRoot: row.project_root,
|
|
9637
|
+
dataDir: row.data_dir,
|
|
9638
|
+
updatedAt: Number(row.updated_at)
|
|
9639
|
+
};
|
|
9640
|
+
}
|
|
9641
|
+
var MaintenanceTargetStore;
|
|
9642
|
+
var init_maintenance_targets = __esm({
|
|
9643
|
+
"src/runtime/maintenance-targets.ts"() {
|
|
9644
|
+
"use strict";
|
|
9645
|
+
init_esm_shims();
|
|
9646
|
+
init_sqlite_db();
|
|
9647
|
+
MaintenanceTargetStore = class {
|
|
9648
|
+
db;
|
|
9649
|
+
constructor(dataDir) {
|
|
9650
|
+
this.db = getDatabase(dataDir);
|
|
9651
|
+
}
|
|
9652
|
+
register(input) {
|
|
9653
|
+
if (!input.projectId.trim()) throw new Error("Maintenance target requires a project ID");
|
|
9654
|
+
if (!input.projectRoot.trim()) throw new Error("Maintenance target requires a project root");
|
|
9655
|
+
if (!input.dataDir.trim()) throw new Error("Maintenance target requires a data directory");
|
|
9656
|
+
const now3 = input.now ?? Date.now();
|
|
9657
|
+
this.db.prepare(`
|
|
9658
|
+
INSERT INTO maintenance_targets (project_id, project_root, data_dir, updated_at)
|
|
9659
|
+
VALUES (?, ?, ?, ?)
|
|
9660
|
+
ON CONFLICT(project_id) DO UPDATE SET
|
|
9661
|
+
project_root = excluded.project_root,
|
|
9662
|
+
data_dir = excluded.data_dir,
|
|
9663
|
+
updated_at = excluded.updated_at
|
|
9664
|
+
`).run(input.projectId, input.projectRoot, input.dataDir, now3);
|
|
9665
|
+
return this.get(input.projectId);
|
|
9666
|
+
}
|
|
9667
|
+
get(projectId) {
|
|
9668
|
+
const row = this.db.prepare(`
|
|
9669
|
+
SELECT * FROM maintenance_targets WHERE project_id = ?
|
|
9670
|
+
`).get(projectId);
|
|
9671
|
+
return row ? rowToTarget(row) : void 0;
|
|
9672
|
+
}
|
|
9673
|
+
list() {
|
|
9674
|
+
return this.db.prepare(`
|
|
9675
|
+
SELECT * FROM maintenance_targets ORDER BY updated_at DESC
|
|
9676
|
+
`).all().map(rowToTarget);
|
|
9677
|
+
}
|
|
9678
|
+
};
|
|
9679
|
+
}
|
|
9680
|
+
});
|
|
9681
|
+
|
|
9643
9682
|
// src/runtime/isolated-maintenance.ts
|
|
9644
9683
|
import { spawn } from "child_process";
|
|
9645
9684
|
import { existsSync as existsSync8 } from "fs";
|
|
@@ -152176,10 +152215,21 @@ __export(vector_backfill_runner_exports, {
|
|
|
152176
152215
|
launchDetachedVectorBackfill: () => launchDetachedVectorBackfill,
|
|
152177
152216
|
main: () => main,
|
|
152178
152217
|
parseVectorBackfillRequest: () => parseVectorBackfillRequest,
|
|
152179
|
-
|
|
152218
|
+
releaseVectorBackfillLock: () => releaseVectorBackfillLock,
|
|
152219
|
+
resolveVectorBackfillRunnerPath: () => resolveVectorBackfillRunnerPath,
|
|
152220
|
+
vectorBackfillLockPath: () => vectorBackfillLockPath
|
|
152180
152221
|
});
|
|
152181
152222
|
import { spawn as spawn4 } from "child_process";
|
|
152182
|
-
import {
|
|
152223
|
+
import {
|
|
152224
|
+
closeSync,
|
|
152225
|
+
existsSync as existsSync12,
|
|
152226
|
+
mkdirSync as mkdirSync2,
|
|
152227
|
+
openSync,
|
|
152228
|
+
readFileSync as readFileSync9,
|
|
152229
|
+
statSync as statSync4,
|
|
152230
|
+
unlinkSync,
|
|
152231
|
+
writeFileSync as writeFileSync2
|
|
152232
|
+
} from "fs";
|
|
152183
152233
|
import path24 from "path";
|
|
152184
152234
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
152185
152235
|
function isNonEmptyString(value) {
|
|
@@ -152206,10 +152256,104 @@ function parseVectorBackfillRequest(raw) {
|
|
|
152206
152256
|
dataDir: value.dataDir
|
|
152207
152257
|
};
|
|
152208
152258
|
}
|
|
152259
|
+
function vectorBackfillLockPath(dataDir) {
|
|
152260
|
+
return path24.join(dataDir, VECTOR_BACKFILL_LOCK_FILE);
|
|
152261
|
+
}
|
|
152262
|
+
function processIsAlive(pid) {
|
|
152263
|
+
if (!Number.isSafeInteger(pid) || pid == null || pid <= 0) return false;
|
|
152264
|
+
try {
|
|
152265
|
+
process.kill(pid, 0);
|
|
152266
|
+
return true;
|
|
152267
|
+
} catch (error) {
|
|
152268
|
+
return error.code === "EPERM";
|
|
152269
|
+
}
|
|
152270
|
+
}
|
|
152271
|
+
function readVectorBackfillLock(lockPath) {
|
|
152272
|
+
try {
|
|
152273
|
+
const value = JSON.parse(readFileSync9(lockPath, "utf8"));
|
|
152274
|
+
if (typeof value.parentPid !== "number" || !Number.isSafeInteger(value.parentPid) || typeof value.startedAt !== "number" || !Number.isFinite(value.startedAt) || typeof value.projectId !== "string") return void 0;
|
|
152275
|
+
return {
|
|
152276
|
+
parentPid: value.parentPid,
|
|
152277
|
+
...typeof value.childPid === "number" ? { childPid: value.childPid } : {},
|
|
152278
|
+
startedAt: value.startedAt,
|
|
152279
|
+
projectId: value.projectId
|
|
152280
|
+
};
|
|
152281
|
+
} catch {
|
|
152282
|
+
return void 0;
|
|
152283
|
+
}
|
|
152284
|
+
}
|
|
152285
|
+
function writeVectorBackfillLock(lockPath, value) {
|
|
152286
|
+
writeFileSync2(lockPath, `${JSON.stringify(value)}
|
|
152287
|
+
`, "utf8");
|
|
152288
|
+
}
|
|
152289
|
+
function acquireVectorBackfillLock(dataDir, projectId, preferredPath) {
|
|
152290
|
+
const lockPath = preferredPath ?? vectorBackfillLockPath(dataDir);
|
|
152291
|
+
mkdirSync2(path24.dirname(lockPath), { recursive: true });
|
|
152292
|
+
const initial = {
|
|
152293
|
+
parentPid: process.pid,
|
|
152294
|
+
startedAt: Date.now(),
|
|
152295
|
+
projectId
|
|
152296
|
+
};
|
|
152297
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
152298
|
+
try {
|
|
152299
|
+
const fd = openSync(lockPath, "wx");
|
|
152300
|
+
try {
|
|
152301
|
+
writeFileSync2(fd, `${JSON.stringify(initial)}
|
|
152302
|
+
`, "utf8");
|
|
152303
|
+
} finally {
|
|
152304
|
+
closeSync(fd);
|
|
152305
|
+
}
|
|
152306
|
+
return {
|
|
152307
|
+
path: lockPath,
|
|
152308
|
+
setChildPid(pid) {
|
|
152309
|
+
try {
|
|
152310
|
+
writeVectorBackfillLock(lockPath, { ...initial, childPid: pid });
|
|
152311
|
+
} catch {
|
|
152312
|
+
}
|
|
152313
|
+
},
|
|
152314
|
+
release() {
|
|
152315
|
+
try {
|
|
152316
|
+
unlinkSync(lockPath);
|
|
152317
|
+
} catch {
|
|
152318
|
+
}
|
|
152319
|
+
}
|
|
152320
|
+
};
|
|
152321
|
+
} catch (error) {
|
|
152322
|
+
if (error.code !== "EEXIST") return void 0;
|
|
152323
|
+
const existing = readVectorBackfillLock(lockPath);
|
|
152324
|
+
const ownerAlive = existing && (processIsAlive(existing.childPid) || processIsAlive(existing.parentPid));
|
|
152325
|
+
if (ownerAlive) return void 0;
|
|
152326
|
+
let stale = false;
|
|
152327
|
+
try {
|
|
152328
|
+
stale = Date.now() - statSync4(lockPath).mtimeMs >= STALE_LOCK_RECOVERY_MS;
|
|
152329
|
+
} catch {
|
|
152330
|
+
stale = false;
|
|
152331
|
+
}
|
|
152332
|
+
if (!existing && !stale) return void 0;
|
|
152333
|
+
try {
|
|
152334
|
+
unlinkSync(lockPath);
|
|
152335
|
+
} catch {
|
|
152336
|
+
return void 0;
|
|
152337
|
+
}
|
|
152338
|
+
}
|
|
152339
|
+
}
|
|
152340
|
+
return void 0;
|
|
152341
|
+
}
|
|
152342
|
+
function releaseVectorBackfillLock(lockPath = process.env.MEMORIX_VECTOR_BACKFILL_LOCK) {
|
|
152343
|
+
if (!lockPath) return;
|
|
152344
|
+
const lock = readVectorBackfillLock(lockPath);
|
|
152345
|
+
if (lock && lock.childPid !== process.pid) return;
|
|
152346
|
+
try {
|
|
152347
|
+
unlinkSync(lockPath);
|
|
152348
|
+
} catch {
|
|
152349
|
+
}
|
|
152350
|
+
}
|
|
152209
152351
|
function launchDetachedVectorBackfill(request, options = {}) {
|
|
152210
152352
|
const runnerPath = options.runnerPath ?? resolveVectorBackfillRunnerPath();
|
|
152211
152353
|
const exists = options.exists ?? existsSync12;
|
|
152212
152354
|
if (!exists(runnerPath)) return false;
|
|
152355
|
+
const lock = acquireVectorBackfillLock(request.dataDir, request.projectId, options.lockPath);
|
|
152356
|
+
if (!lock) return false;
|
|
152213
152357
|
try {
|
|
152214
152358
|
const child = (options.spawn ?? spawn4)(process.execPath, [runnerPath], {
|
|
152215
152359
|
cwd: request.projectRoot,
|
|
@@ -152219,14 +152363,23 @@ function launchDetachedVectorBackfill(request, options = {}) {
|
|
|
152219
152363
|
stdio: "ignore",
|
|
152220
152364
|
// The request contains only local project metadata, never credentials.
|
|
152221
152365
|
// Environment transport avoids a live stdin pipe keeping the CLI alive.
|
|
152222
|
-
env: {
|
|
152366
|
+
env: {
|
|
152367
|
+
...process.env,
|
|
152368
|
+
MEMORIX_VECTOR_BACKFILL_REQUEST: JSON.stringify(request),
|
|
152369
|
+
MEMORIX_VECTOR_BACKFILL_LOCK: lock.path
|
|
152370
|
+
},
|
|
152223
152371
|
windowsHide: true
|
|
152224
152372
|
});
|
|
152373
|
+
if (child.pid) lock.setChildPid(child.pid);
|
|
152374
|
+
else lock.release();
|
|
152225
152375
|
child.once?.("error", () => {
|
|
152226
152376
|
});
|
|
152377
|
+
child.once?.("close", () => lock.release());
|
|
152378
|
+
if (typeof child.once !== "function") lock.release();
|
|
152227
152379
|
child.unref();
|
|
152228
|
-
return
|
|
152380
|
+
return Boolean(child.pid);
|
|
152229
152381
|
} catch {
|
|
152382
|
+
lock.release();
|
|
152230
152383
|
return false;
|
|
152231
152384
|
}
|
|
152232
152385
|
}
|
|
@@ -152238,12 +152391,32 @@ async function executeVectorBackfill(request) {
|
|
|
152238
152391
|
await prepareSearchIndex();
|
|
152239
152392
|
await getDeferredCachedVectorHydration()?.catch(() => {
|
|
152240
152393
|
});
|
|
152394
|
+
const queue = new MaintenanceJobStore(request.dataDir);
|
|
152395
|
+
const targets = new MaintenanceTargetStore(request.dataDir);
|
|
152396
|
+
let preparedRoot = request.projectRoot;
|
|
152397
|
+
const prepareTarget = async (target) => {
|
|
152398
|
+
if (target.projectRoot === preparedRoot) return;
|
|
152399
|
+
initProjectRoot(target.projectRoot);
|
|
152400
|
+
loadDotenv(target.projectRoot);
|
|
152401
|
+
preparedRoot = target.projectRoot;
|
|
152402
|
+
};
|
|
152403
|
+
const handler = async (job) => {
|
|
152404
|
+
const target = targets.get(job.projectId) ?? (job.projectId === request.projectId ? { projectId: request.projectId, projectRoot: request.projectRoot, dataDir: request.dataDir, updatedAt: Date.now() } : void 0);
|
|
152405
|
+
if (!target) return { action: "reschedule", delayMs: 3e4 };
|
|
152406
|
+
await prepareTarget(target);
|
|
152407
|
+
return createProjectMaintenanceHandler(job.projectId, target.dataDir, target.projectRoot)(job);
|
|
152408
|
+
};
|
|
152241
152409
|
const worker = new MaintenanceJobWorker(
|
|
152242
|
-
|
|
152243
|
-
|
|
152244
|
-
{
|
|
152410
|
+
queue,
|
|
152411
|
+
handler,
|
|
152412
|
+
{ kinds: ["vector-backfill"] }
|
|
152245
152413
|
);
|
|
152246
|
-
|
|
152414
|
+
let result = { state: "idle" };
|
|
152415
|
+
while (true) {
|
|
152416
|
+
result = await worker.runOnce();
|
|
152417
|
+
if (result.state === "idle") break;
|
|
152418
|
+
}
|
|
152419
|
+
return result;
|
|
152247
152420
|
}
|
|
152248
152421
|
async function readStdin() {
|
|
152249
152422
|
return new Promise((resolve5, reject) => {
|
|
@@ -152266,9 +152439,11 @@ async function main() {
|
|
|
152266
152439
|
`);
|
|
152267
152440
|
process.exitCode = 1;
|
|
152268
152441
|
} finally {
|
|
152442
|
+
releaseVectorBackfillLock();
|
|
152269
152443
|
closeAllDatabases();
|
|
152270
152444
|
}
|
|
152271
152445
|
}
|
|
152446
|
+
var VECTOR_BACKFILL_LOCK_FILE, STALE_LOCK_RECOVERY_MS;
|
|
152272
152447
|
var init_vector_backfill_runner = __esm({
|
|
152273
152448
|
"src/runtime/vector-backfill-runner.ts"() {
|
|
152274
152449
|
"use strict";
|
|
@@ -152281,7 +152456,10 @@ var init_vector_backfill_runner = __esm({
|
|
|
152281
152456
|
init_orama_store();
|
|
152282
152457
|
init_sqlite_db();
|
|
152283
152458
|
init_maintenance_jobs();
|
|
152459
|
+
init_maintenance_targets();
|
|
152284
152460
|
init_project_maintenance();
|
|
152461
|
+
VECTOR_BACKFILL_LOCK_FILE = ".memorix-vector-backfill.lock";
|
|
152462
|
+
STALE_LOCK_RECOVERY_MS = 24 * 60 * 60 * 1e3;
|
|
152285
152463
|
if (process.argv[1] && process.argv[1].endsWith("vector-backfill-runner.js")) {
|
|
152286
152464
|
void main();
|
|
152287
152465
|
}
|
|
@@ -152323,11 +152501,17 @@ function resetObservationRuntime() {
|
|
|
152323
152501
|
embeddingWorkerProjectRoot = void 0;
|
|
152324
152502
|
vectorMissingIds.clear();
|
|
152325
152503
|
vectorSchemaUpgradePromise = null;
|
|
152504
|
+
embeddingFailureLogTimestamps.clear();
|
|
152326
152505
|
}
|
|
152327
152506
|
function logEmbeddingFailureOnce(key, message) {
|
|
152328
152507
|
const now3 = Date.now();
|
|
152329
152508
|
const last = embeddingFailureLogTimestamps.get(key) ?? 0;
|
|
152330
152509
|
if (now3 - last < EMBEDDING_FAILURE_LOG_COOLDOWN_MS) return;
|
|
152510
|
+
if (!embeddingFailureLogTimestamps.has(key) && embeddingFailureLogTimestamps.size >= MAX_EMBEDDING_FAILURE_KEYS) {
|
|
152511
|
+
const oldest = embeddingFailureLogTimestamps.keys().next().value;
|
|
152512
|
+
if (oldest !== void 0) embeddingFailureLogTimestamps.delete(oldest);
|
|
152513
|
+
}
|
|
152514
|
+
embeddingFailureLogTimestamps.delete(key);
|
|
152331
152515
|
embeddingFailureLogTimestamps.set(key, now3);
|
|
152332
152516
|
console.error(message);
|
|
152333
152517
|
}
|
|
@@ -152357,13 +152541,14 @@ function queueVectorBackfill(projectId, options = {}) {
|
|
|
152357
152541
|
const dataDir = projectDir;
|
|
152358
152542
|
if (!dataDir) return;
|
|
152359
152543
|
void Promise.resolve().then(() => (init_maintenance_jobs(), maintenance_jobs_exports)).then(({ MaintenanceJobStore: MaintenanceJobStore2 }) => {
|
|
152360
|
-
new MaintenanceJobStore2(dataDir).enqueue({
|
|
152544
|
+
const job = new MaintenanceJobStore2(dataDir).enqueue({
|
|
152361
152545
|
projectId,
|
|
152362
152546
|
kind: "vector-backfill",
|
|
152363
152547
|
dedupeKey: "vector-backfill",
|
|
152364
152548
|
payload: { limit: 12 }
|
|
152365
152549
|
});
|
|
152366
|
-
|
|
152550
|
+
const due = !job || job.status === "pending" && job.runAfter <= Date.now();
|
|
152551
|
+
if (due && options.detachedWorker && options.projectRoot) {
|
|
152367
152552
|
void Promise.resolve().then(() => (init_vector_backfill_runner(), vector_backfill_runner_exports)).then(({ launchDetachedVectorBackfill: launchDetachedVectorBackfill2 }) => {
|
|
152368
152553
|
launchDetachedVectorBackfill2({
|
|
152369
152554
|
projectId,
|
|
@@ -153294,7 +153479,7 @@ async function backfillVectorEmbeddings(options = {}) {
|
|
|
153294
153479
|
...lastFailure ? { lastError: lastFailure } : {}
|
|
153295
153480
|
};
|
|
153296
153481
|
}
|
|
153297
|
-
var observations, nextId, projectDir, searchIndexPrepared, embeddingWriteMode, embeddingWorkerProjectRoot, corpusLoaded, loadedObservationStore, vectorMissingIds, vectorBackfillRunning, vectorSchemaUpgradePromise, lastVectorBackfill, embeddingFailureLogTimestamps, EMBEDDING_FAILURE_LOG_COOLDOWN_MS;
|
|
153482
|
+
var observations, nextId, projectDir, searchIndexPrepared, embeddingWriteMode, embeddingWorkerProjectRoot, corpusLoaded, loadedObservationStore, vectorMissingIds, vectorBackfillRunning, vectorSchemaUpgradePromise, lastVectorBackfill, embeddingFailureLogTimestamps, EMBEDDING_FAILURE_LOG_COOLDOWN_MS, MAX_EMBEDDING_FAILURE_KEYS;
|
|
153298
153483
|
var init_observations = __esm({
|
|
153299
153484
|
"src/memory/observations.ts"() {
|
|
153300
153485
|
"use strict";
|
|
@@ -153322,6 +153507,7 @@ var init_observations = __esm({
|
|
|
153322
153507
|
lastVectorBackfill = null;
|
|
153323
153508
|
embeddingFailureLogTimestamps = /* @__PURE__ */ new Map();
|
|
153324
153509
|
EMBEDDING_FAILURE_LOG_COOLDOWN_MS = 3e4;
|
|
153510
|
+
MAX_EMBEDDING_FAILURE_KEYS = 1024;
|
|
153325
153511
|
}
|
|
153326
153512
|
});
|
|
153327
153513
|
|
|
@@ -154759,62 +154945,13 @@ var init_formation = __esm({
|
|
|
154759
154945
|
}
|
|
154760
154946
|
});
|
|
154761
154947
|
|
|
154762
|
-
// src/runtime/maintenance-targets.ts
|
|
154763
|
-
var maintenance_targets_exports = {};
|
|
154764
|
-
__export(maintenance_targets_exports, {
|
|
154765
|
-
MaintenanceTargetStore: () => MaintenanceTargetStore
|
|
154766
|
-
});
|
|
154767
|
-
function rowToTarget(row) {
|
|
154768
|
-
return {
|
|
154769
|
-
projectId: row.project_id,
|
|
154770
|
-
projectRoot: row.project_root,
|
|
154771
|
-
dataDir: row.data_dir,
|
|
154772
|
-
updatedAt: Number(row.updated_at)
|
|
154773
|
-
};
|
|
154774
|
-
}
|
|
154775
|
-
var MaintenanceTargetStore;
|
|
154776
|
-
var init_maintenance_targets = __esm({
|
|
154777
|
-
"src/runtime/maintenance-targets.ts"() {
|
|
154778
|
-
"use strict";
|
|
154779
|
-
init_esm_shims();
|
|
154780
|
-
init_sqlite_db();
|
|
154781
|
-
MaintenanceTargetStore = class {
|
|
154782
|
-
db;
|
|
154783
|
-
constructor(dataDir) {
|
|
154784
|
-
this.db = getDatabase(dataDir);
|
|
154785
|
-
}
|
|
154786
|
-
register(input) {
|
|
154787
|
-
if (!input.projectId.trim()) throw new Error("Maintenance target requires a project ID");
|
|
154788
|
-
if (!input.projectRoot.trim()) throw new Error("Maintenance target requires a project root");
|
|
154789
|
-
if (!input.dataDir.trim()) throw new Error("Maintenance target requires a data directory");
|
|
154790
|
-
const now3 = input.now ?? Date.now();
|
|
154791
|
-
this.db.prepare(`
|
|
154792
|
-
INSERT INTO maintenance_targets (project_id, project_root, data_dir, updated_at)
|
|
154793
|
-
VALUES (?, ?, ?, ?)
|
|
154794
|
-
ON CONFLICT(project_id) DO UPDATE SET
|
|
154795
|
-
project_root = excluded.project_root,
|
|
154796
|
-
data_dir = excluded.data_dir,
|
|
154797
|
-
updated_at = excluded.updated_at
|
|
154798
|
-
`).run(input.projectId, input.projectRoot, input.dataDir, now3);
|
|
154799
|
-
return this.get(input.projectId);
|
|
154800
|
-
}
|
|
154801
|
-
get(projectId) {
|
|
154802
|
-
const row = this.db.prepare(`
|
|
154803
|
-
SELECT * FROM maintenance_targets WHERE project_id = ?
|
|
154804
|
-
`).get(projectId);
|
|
154805
|
-
return row ? rowToTarget(row) : void 0;
|
|
154806
|
-
}
|
|
154807
|
-
};
|
|
154808
|
-
}
|
|
154809
|
-
});
|
|
154810
|
-
|
|
154811
154948
|
// src/config/behavior.ts
|
|
154812
154949
|
var behavior_exports = {};
|
|
154813
154950
|
__export(behavior_exports, {
|
|
154814
154951
|
getBehaviorConfig: () => getBehaviorConfig,
|
|
154815
154952
|
resetBehaviorConfigCache: () => resetBehaviorConfigCache
|
|
154816
154953
|
});
|
|
154817
|
-
import { existsSync as existsSync15, readFileSync as
|
|
154954
|
+
import { existsSync as existsSync15, readFileSync as readFileSync11 } from "fs";
|
|
154818
154955
|
import { homedir as homedir22 } from "os";
|
|
154819
154956
|
function isSessionInject(value) {
|
|
154820
154957
|
return value === "full" || value === "minimal" || value === "silent";
|
|
@@ -154826,7 +154963,7 @@ function legacyBehavior(homeDir) {
|
|
|
154826
154963
|
const configPath = getLegacyConfigJsonPath(homeDir);
|
|
154827
154964
|
try {
|
|
154828
154965
|
if (!existsSync15(configPath)) return {};
|
|
154829
|
-
const parsed = JSON.parse(
|
|
154966
|
+
const parsed = JSON.parse(readFileSync11(configPath, "utf-8"));
|
|
154830
154967
|
return parsed.behavior && typeof parsed.behavior === "object" && !Array.isArray(parsed.behavior) ? parsed.behavior : {};
|
|
154831
154968
|
} catch {
|
|
154832
154969
|
return {};
|
|
@@ -156179,12 +156316,12 @@ __export(current_facts_exports, {
|
|
|
156179
156316
|
formatGitFact: () => formatGitFact
|
|
156180
156317
|
});
|
|
156181
156318
|
import { execFileSync } from "child_process";
|
|
156182
|
-
import { existsSync as existsSync16, readFileSync as
|
|
156319
|
+
import { existsSync as existsSync16, readFileSync as readFileSync12 } from "fs";
|
|
156183
156320
|
import path28 from "path";
|
|
156184
156321
|
function readTextIfExists(filePath) {
|
|
156185
156322
|
try {
|
|
156186
156323
|
if (!existsSync16(filePath)) return null;
|
|
156187
|
-
return
|
|
156324
|
+
return readFileSync12(filePath, "utf8");
|
|
156188
156325
|
} catch {
|
|
156189
156326
|
return null;
|
|
156190
156327
|
}
|
|
@@ -156474,7 +156611,7 @@ __export(external_provider_exports, {
|
|
|
156474
156611
|
runExternalCodeGraphLifecycle: () => runExternalCodeGraphLifecycle
|
|
156475
156612
|
});
|
|
156476
156613
|
import { spawn as spawn5 } from "child_process";
|
|
156477
|
-
import { existsSync as existsSync17, readFileSync as
|
|
156614
|
+
import { existsSync as existsSync17, readFileSync as readFileSync13 } from "fs";
|
|
156478
156615
|
import { delimiter, dirname as dirname2, extname, isAbsolute as isAbsolute3, join as join20, relative as relative4, resolve as resolve3, sep } from "path";
|
|
156479
156616
|
function boundedTimeout(value) {
|
|
156480
156617
|
if (!Number.isFinite(value)) return DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS;
|
|
@@ -156521,7 +156658,7 @@ function resolveLaunch(command) {
|
|
|
156521
156658
|
return { executable: node, prefixArgs: ["--liftoff-only", entry] };
|
|
156522
156659
|
}
|
|
156523
156660
|
try {
|
|
156524
|
-
const shim =
|
|
156661
|
+
const shim = readFileSync13(candidate, "utf8");
|
|
156525
156662
|
const match2 = shim.match(/["']([^"']*%(?:~)?dp0%?[^"']*\.m?js)["']/i);
|
|
156526
156663
|
if (match2?.[1]) {
|
|
156527
156664
|
const base = dirname2(candidate).endsWith(sep) ? dirname2(candidate) : dirname2(candidate) + sep;
|
|
@@ -157781,7 +157918,7 @@ __export(auto_context_exports, {
|
|
|
157781
157918
|
formatAutoProjectContextSummary: () => formatAutoProjectContextSummary,
|
|
157782
157919
|
formatLegacyAutoProjectContextPrompt: () => formatLegacyAutoProjectContextPrompt
|
|
157783
157920
|
});
|
|
157784
|
-
import { existsSync as existsSync18, statSync as
|
|
157921
|
+
import { existsSync as existsSync18, statSync as statSync5 } from "fs";
|
|
157785
157922
|
import path29 from "path";
|
|
157786
157923
|
function activeProjectObservations(observations2, projectId) {
|
|
157787
157924
|
return observations2.filter((obs) => obs.projectId === projectId && (obs.status ?? "active") === "active");
|
|
@@ -158128,7 +158265,7 @@ function existingLensCandidates(rootPath, lens) {
|
|
|
158128
158265
|
const absolute = path29.join(rootPath, candidate);
|
|
158129
158266
|
try {
|
|
158130
158267
|
if (!existsSync18(absolute)) continue;
|
|
158131
|
-
const stat5 =
|
|
158268
|
+
const stat5 = statSync5(absolute);
|
|
158132
158269
|
if (stat5.isFile()) out.push(candidate);
|
|
158133
158270
|
if (stat5.isDirectory()) out.push(candidate.replace(/\\/g, "/"));
|
|
158134
158271
|
} catch {
|
|
@@ -158661,7 +158798,7 @@ var engine_exports2 = {};
|
|
|
158661
158798
|
__export(engine_exports2, {
|
|
158662
158799
|
SkillsEngine: () => SkillsEngine
|
|
158663
158800
|
});
|
|
158664
|
-
import { existsSync as existsSync19, readFileSync as
|
|
158801
|
+
import { existsSync as existsSync19, readFileSync as readFileSync14, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, readdirSync as readdirSync4 } from "fs";
|
|
158665
158802
|
import { join as join21 } from "path";
|
|
158666
158803
|
import { homedir as homedir23 } from "os";
|
|
158667
158804
|
var SKILLS_DIRS, SKILL_WORTHY_TYPES, MIN_OBS_FOR_SKILL, MIN_SCORE_FOR_SKILL, LOW_SIGNAL_TITLE_PATTERNS, LOW_SIGNAL_ENTITY_PATTERNS, COMMAND_TRACE_PATTERNS2, SkillsEngine;
|
|
@@ -158752,7 +158889,7 @@ var init_engine3 = __esm({
|
|
|
158752
158889
|
const skillMd = join21(skillsRoot, name, "SKILL.md");
|
|
158753
158890
|
if (!existsSync19(skillMd)) continue;
|
|
158754
158891
|
try {
|
|
158755
|
-
const content =
|
|
158892
|
+
const content = readFileSync14(skillMd, "utf-8");
|
|
158756
158893
|
const description = this.parseDescription(content);
|
|
158757
158894
|
skills.push({
|
|
158758
158895
|
name,
|
|
@@ -158802,8 +158939,8 @@ var init_engine3 = __esm({
|
|
|
158802
158939
|
if (!dirs || dirs.length === 0) return null;
|
|
158803
158940
|
const targetDir = join21(this.projectRoot, dirs[0], skill2.name);
|
|
158804
158941
|
try {
|
|
158805
|
-
|
|
158806
|
-
|
|
158942
|
+
mkdirSync5(targetDir, { recursive: true });
|
|
158943
|
+
writeFileSync4(join21(targetDir, "SKILL.md"), skill2.content, "utf-8");
|
|
158807
158944
|
return join21(dirs[0], skill2.name, "SKILL.md");
|
|
158808
158945
|
} catch {
|
|
158809
158946
|
return null;
|
|
@@ -162573,7 +162710,7 @@ var init_task_graph = __esm({
|
|
|
162573
162710
|
|
|
162574
162711
|
// src/orchestrate/context-collector.ts
|
|
162575
162712
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
162576
|
-
import { readFileSync as
|
|
162713
|
+
import { readFileSync as readFileSync15, existsSync as existsSync20 } from "fs";
|
|
162577
162714
|
import { join as join22 } from "path";
|
|
162578
162715
|
function normalizeEntryLimit(value, fallback) {
|
|
162579
162716
|
if (!Number.isSafeInteger(value) || value < 1) return fallback;
|
|
@@ -162651,7 +162788,7 @@ function collectDependencies(projectDir2) {
|
|
|
162651
162788
|
try {
|
|
162652
162789
|
const pkgPath = join22(projectDir2, "package.json");
|
|
162653
162790
|
if (!existsSync20(pkgPath)) return "";
|
|
162654
|
-
const pkg = JSON.parse(
|
|
162791
|
+
const pkg = JSON.parse(readFileSync15(pkgPath, "utf-8"));
|
|
162655
162792
|
const parts = [];
|
|
162656
162793
|
if (pkg.dependencies && Object.keys(pkg.dependencies).length > 0) {
|
|
162657
162794
|
parts.push(`dependencies: ${Object.keys(pkg.dependencies).join(", ")}`);
|
|
@@ -165151,18 +165288,18 @@ __export(hooks_path_exports, {
|
|
|
165151
165288
|
resolveGitDir: () => resolveGitDir,
|
|
165152
165289
|
resolveHooksDir: () => resolveHooksDir
|
|
165153
165290
|
});
|
|
165154
|
-
import { existsSync as existsSync21, readFileSync as
|
|
165291
|
+
import { existsSync as existsSync21, readFileSync as readFileSync16, statSync as statSync6, mkdirSync as mkdirSync6 } from "fs";
|
|
165155
165292
|
import path34 from "path";
|
|
165156
165293
|
function resolveGitDir(projectRoot) {
|
|
165157
165294
|
const dotGit = path34.join(projectRoot, ".git");
|
|
165158
165295
|
if (!existsSync21(dotGit)) return null;
|
|
165159
|
-
const stat5 =
|
|
165296
|
+
const stat5 = statSync6(dotGit);
|
|
165160
165297
|
if (stat5.isDirectory()) {
|
|
165161
165298
|
return dotGit;
|
|
165162
165299
|
}
|
|
165163
165300
|
if (stat5.isFile()) {
|
|
165164
165301
|
try {
|
|
165165
|
-
const content =
|
|
165302
|
+
const content = readFileSync16(dotGit, "utf-8").trim();
|
|
165166
165303
|
const match2 = content.match(/^gitdir:\s*(.+)$/);
|
|
165167
165304
|
if (match2) {
|
|
165168
165305
|
const gitdir = match2[1].trim();
|
|
@@ -165188,7 +165325,7 @@ function resolveHooksDir(projectRoot) {
|
|
|
165188
165325
|
function ensureHooksDir(projectRoot) {
|
|
165189
165326
|
const resolved = resolveHooksDir(projectRoot);
|
|
165190
165327
|
if (!resolved) return null;
|
|
165191
|
-
|
|
165328
|
+
mkdirSync6(resolved.hooksDir, { recursive: true });
|
|
165192
165329
|
return resolved;
|
|
165193
165330
|
}
|
|
165194
165331
|
var init_hooks_path = __esm({
|
|
@@ -167373,7 +167510,7 @@ var RulesSyncer = class {
|
|
|
167373
167510
|
|
|
167374
167511
|
// src/workspace/engine.ts
|
|
167375
167512
|
init_esm_shims();
|
|
167376
|
-
import { readFileSync as
|
|
167513
|
+
import { readFileSync as readFileSync10, readdirSync as readdirSync3, existsSync as existsSync14, cpSync, mkdirSync as mkdirSync4 } from "fs";
|
|
167377
167514
|
import { join as join19 } from "path";
|
|
167378
167515
|
import { homedir as homedir21 } from "os";
|
|
167379
167516
|
|
|
@@ -168325,7 +168462,7 @@ function sanitize(input) {
|
|
|
168325
168462
|
|
|
168326
168463
|
// src/workspace/applier.ts
|
|
168327
168464
|
init_esm_shims();
|
|
168328
|
-
import { existsSync as existsSync13, mkdirSync as
|
|
168465
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync3, copyFileSync, writeFileSync as writeFileSync3, unlinkSync as unlinkSync2, renameSync } from "fs";
|
|
168329
168466
|
import { dirname } from "path";
|
|
168330
168467
|
var WorkspaceSyncApplier = class {
|
|
168331
168468
|
/**
|
|
@@ -168352,7 +168489,7 @@ var WorkspaceSyncApplier = class {
|
|
|
168352
168489
|
try {
|
|
168353
168490
|
const dir = dirname(file.filePath);
|
|
168354
168491
|
if (!existsSync13(dir)) {
|
|
168355
|
-
|
|
168492
|
+
mkdirSync3(dir, { recursive: true });
|
|
168356
168493
|
}
|
|
168357
168494
|
} catch (err) {
|
|
168358
168495
|
result.errors.push(`Cannot create directory for ${file.filePath}: ${err}`);
|
|
@@ -168377,7 +168514,7 @@ var WorkspaceSyncApplier = class {
|
|
|
168377
168514
|
for (const file of files) {
|
|
168378
168515
|
try {
|
|
168379
168516
|
const tempPath = file.filePath + `.tmp-${Date.now()}`;
|
|
168380
|
-
|
|
168517
|
+
writeFileSync3(tempPath, file.content, "utf-8");
|
|
168381
168518
|
renameSync(tempPath, file.filePath);
|
|
168382
168519
|
result.filesWritten.push(file.filePath);
|
|
168383
168520
|
} catch (err) {
|
|
@@ -168412,7 +168549,7 @@ var WorkspaceSyncApplier = class {
|
|
|
168412
168549
|
for (const backup of backups) {
|
|
168413
168550
|
try {
|
|
168414
168551
|
if (existsSync13(backup.backupPath)) {
|
|
168415
|
-
|
|
168552
|
+
unlinkSync2(backup.backupPath);
|
|
168416
168553
|
}
|
|
168417
168554
|
} catch {
|
|
168418
168555
|
}
|
|
@@ -168478,7 +168615,7 @@ var WorkspaceSyncEngine = class _WorkspaceSyncEngine {
|
|
|
168478
168615
|
for (const path35 of pathsToCheck) {
|
|
168479
168616
|
if (existsSync14(path35)) {
|
|
168480
168617
|
try {
|
|
168481
|
-
const content =
|
|
168618
|
+
const content = readFileSync10(path35, "utf-8");
|
|
168482
168619
|
const servers = adapter.parse(content);
|
|
168483
168620
|
for (const s2 of servers) {
|
|
168484
168621
|
if (!merged.has(s2.name)) merged.set(s2.name, s2);
|
|
@@ -168532,7 +168669,7 @@ var WorkspaceSyncEngine = class _WorkspaceSyncEngine {
|
|
|
168532
168669
|
let configContent;
|
|
168533
168670
|
if (target === "antigravity" && existsSync14(configPath)) {
|
|
168534
168671
|
try {
|
|
168535
|
-
const existing = JSON.parse(
|
|
168672
|
+
const existing = JSON.parse(readFileSync10(configPath, "utf-8"));
|
|
168536
168673
|
const generated = JSON.parse(adapter.generate(result.mcpServers.scanned));
|
|
168537
168674
|
existing.mcpServers = { ...existing.mcpServers ?? {}, ...generated.mcpServers };
|
|
168538
168675
|
configContent = JSON.stringify(existing, null, 2);
|
|
@@ -168615,7 +168752,7 @@ var WorkspaceSyncEngine = class _WorkspaceSyncEngine {
|
|
|
168615
168752
|
if (!existsSync14(skillMd)) continue;
|
|
168616
168753
|
let description = "";
|
|
168617
168754
|
try {
|
|
168618
|
-
const content =
|
|
168755
|
+
const content = readFileSync10(skillMd, "utf-8");
|
|
168619
168756
|
const match2 = content.match(/^---[\s\S]*?description:\s*["']?(.+?)["']?\s*$/m);
|
|
168620
168757
|
if (match2) description = match2[1];
|
|
168621
168758
|
} catch {
|
|
@@ -168666,7 +168803,7 @@ var WorkspaceSyncEngine = class _WorkspaceSyncEngine {
|
|
|
168666
168803
|
continue;
|
|
168667
168804
|
}
|
|
168668
168805
|
try {
|
|
168669
|
-
|
|
168806
|
+
mkdirSync4(targetDir, { recursive: true });
|
|
168670
168807
|
cpSync(skill2.sourcePath, dest, { recursive: true });
|
|
168671
168808
|
copied.push(skill2.name);
|
|
168672
168809
|
} catch {
|
|
@@ -168682,7 +168819,7 @@ var WorkspaceSyncEngine = class _WorkspaceSyncEngine {
|
|
|
168682
168819
|
const files = readdirSync3(wfDir).filter((f3) => f3.endsWith(".md"));
|
|
168683
168820
|
for (const file of files) {
|
|
168684
168821
|
try {
|
|
168685
|
-
const content =
|
|
168822
|
+
const content = readFileSync10(join19(wfDir, file), "utf-8");
|
|
168686
168823
|
workflows.push(this.workflowSyncer.parseWindsurfWorkflow(file, content));
|
|
168687
168824
|
} catch {
|
|
168688
168825
|
}
|
|
@@ -169022,7 +169159,7 @@ var MCP_SERVER_INFO_META_KEY = "io.modelcontextprotocol/serverInfo";
|
|
|
169022
169159
|
function getMcpServerInfo() {
|
|
169023
169160
|
return {
|
|
169024
169161
|
name: "memorix",
|
|
169025
|
-
version: true ? "1.
|
|
169162
|
+
version: true ? "1.9.0" : "1.0.1"
|
|
169026
169163
|
};
|
|
169027
169164
|
}
|
|
169028
169165
|
function createMcpDiscoverResult(capabilities, serverInfo) {
|
|
@@ -173639,10 +173776,10 @@ Preview: ${analysis.description.slice(0, 300)}${analysis.description.length > 30
|
|
|
173639
173776
|
const { ensureHooksDir: ensureHooksDir2 } = await Promise.resolve().then(() => (init_hooks_path(), hooks_path_exports));
|
|
173640
173777
|
const resolved = ensureHooksDir2(project.rootPath);
|
|
173641
173778
|
if (resolved) {
|
|
173642
|
-
const { existsSync: existsSync22, readFileSync:
|
|
173779
|
+
const { existsSync: existsSync22, readFileSync: readFileSync17, writeFileSync: writeFileSync5, chmodSync } = await import("fs");
|
|
173643
173780
|
const { hookPath } = resolved;
|
|
173644
173781
|
const HOOK_MARKER = "# [memorix-git-hook]";
|
|
173645
|
-
const needsInstall = !existsSync22(hookPath) || !
|
|
173782
|
+
const needsInstall = !existsSync22(hookPath) || !readFileSync17(hookPath, "utf-8").includes(HOOK_MARKER);
|
|
173646
173783
|
if (needsInstall) {
|
|
173647
173784
|
const hookScript = `#!/bin/sh
|
|
173648
173785
|
${HOOK_MARKER}
|
|
@@ -173652,8 +173789,8 @@ if command -v memorix >/dev/null 2>&1; then
|
|
|
173652
173789
|
fi
|
|
173653
173790
|
`;
|
|
173654
173791
|
if (existsSync22(hookPath)) {
|
|
173655
|
-
const existing =
|
|
173656
|
-
|
|
173792
|
+
const existing = readFileSync17(hookPath, "utf-8");
|
|
173793
|
+
writeFileSync5(hookPath, existing.trimEnd() + `
|
|
173657
173794
|
|
|
173658
173795
|
${HOOK_MARKER}
|
|
173659
173796
|
if command -v memorix >/dev/null 2>&1; then
|
|
@@ -173661,7 +173798,7 @@ if command -v memorix >/dev/null 2>&1; then
|
|
|
173661
173798
|
fi
|
|
173662
173799
|
`, "utf-8");
|
|
173663
173800
|
} else {
|
|
173664
|
-
|
|
173801
|
+
writeFileSync5(hookPath, hookScript, "utf-8");
|
|
173665
173802
|
}
|
|
173666
173803
|
try {
|
|
173667
173804
|
chmodSync(hookPath, 493);
|