memorix 1.9.1 → 1.9.2
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 +11 -0
- package/README.md +17 -4
- package/README.zh-CN.md +8 -4
- package/dist/cli/index.js +132 -104
- package/dist/index.js +61 -47
- package/dist/maintenance-runner.js +10 -5
- package/dist/media-audio-runner.js +12 -7
- package/dist/media-video-runner.js +10 -5
- package/dist/memcode-runtime/CHANGELOG.md +11 -0
- package/dist/sdk.js +60 -46
- package/dist/vector-backfill-runner.js +10 -5
- package/docs/INTEGRATIONS.md +4 -0
- package/docs/SETUP.md +5 -0
- package/package.json +1 -2
- 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/commands/memory.ts +2 -1
- package/src/cli/default-mode.ts +15 -0
- package/src/cli/index.ts +10 -1
- package/src/codegraph/lite-provider.ts +10 -1
- package/src/dashboard/maintenance.ts +11 -2
- package/src/memory/consolidation.ts +15 -6
- package/assets/star-history-dark.svg +0 -30
- package/assets/star-history-light.svg +0 -30
- package/assets/star-history.json +0 -712
package/dist/sdk.js
CHANGED
|
@@ -10928,7 +10928,8 @@ function clampCursor(afterId) {
|
|
|
10928
10928
|
}
|
|
10929
10929
|
async function loadConsolidationPage(projectId, options) {
|
|
10930
10930
|
const limit2 = clampBatchSize(options.limit);
|
|
10931
|
-
const
|
|
10931
|
+
const store = options.store ?? getObservationStore();
|
|
10932
|
+
const page = await store.loadByProject(projectId, {
|
|
10932
10933
|
status: "active",
|
|
10933
10934
|
afterId: clampCursor(options.afterId),
|
|
10934
10935
|
limit: limit2 + 1
|
|
@@ -10988,7 +10989,7 @@ async function findConsolidationCandidates(_projectDir, projectId, opts) {
|
|
|
10988
10989
|
return findClusters(page.observations, threshold);
|
|
10989
10990
|
}
|
|
10990
10991
|
async function executeConsolidation(_projectDir, projectId, opts) {
|
|
10991
|
-
const store = getObservationStore();
|
|
10992
|
+
const store = opts?.store ?? getObservationStore();
|
|
10992
10993
|
const page = await loadConsolidationPage(projectId, opts ?? {});
|
|
10993
10994
|
const clusters = findClusters(page.observations, opts?.threshold ?? DEFAULT_SIMILARITY_THRESHOLD);
|
|
10994
10995
|
if (clusters.length === 0) {
|
|
@@ -148928,7 +148929,7 @@ __export(lite_provider_exports, {
|
|
|
148928
148929
|
refreshProjectLite: () => refreshProjectLite
|
|
148929
148930
|
});
|
|
148930
148931
|
import { createHash as createHash10 } from "crypto";
|
|
148931
|
-
import { readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
|
|
148932
|
+
import { existsSync as existsSync12, readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
|
|
148932
148933
|
import { join as join4, relative as relative2 } from "path";
|
|
148933
148934
|
function hashText2(text3) {
|
|
148934
148935
|
return createHash10("sha256").update(text3).digest("hex");
|
|
@@ -148945,6 +148946,9 @@ function resolveMaxFileBytes(value) {
|
|
|
148945
148946
|
if (!Number.isFinite(value)) return DEFAULT_CODEGRAPH_MAX_FILE_BYTES;
|
|
148946
148947
|
return Math.max(1, Math.floor(value));
|
|
148947
148948
|
}
|
|
148949
|
+
function isPythonVirtualenvDir(dir) {
|
|
148950
|
+
return existsSync12(join4(dir, "pyvenv.cfg"));
|
|
148951
|
+
}
|
|
148948
148952
|
function walk(root, exclude, maxFiles) {
|
|
148949
148953
|
const out = [];
|
|
148950
148954
|
const visit = (dir) => {
|
|
@@ -148962,6 +148966,7 @@ function walk(root, exclude, maxFiles) {
|
|
|
148962
148966
|
if (entry.isDirectory()) {
|
|
148963
148967
|
if (entry.name === ".git" || entry.name === ".worktrees" || entry.name === ".tmp" || entry.name === "node_modules") continue;
|
|
148964
148968
|
if (rel === ".claude/worktrees" || rel.startsWith(".claude/worktrees/")) continue;
|
|
148969
|
+
if (isPythonVirtualenvDir(abs)) continue;
|
|
148965
148970
|
visit(abs);
|
|
148966
148971
|
if (out.length >= maxFiles) return;
|
|
148967
148972
|
continue;
|
|
@@ -152858,7 +152863,7 @@ __export(vector_backfill_runner_exports, {
|
|
|
152858
152863
|
import { spawn as spawn4 } from "child_process";
|
|
152859
152864
|
import {
|
|
152860
152865
|
closeSync,
|
|
152861
|
-
existsSync as
|
|
152866
|
+
existsSync as existsSync13,
|
|
152862
152867
|
mkdirSync as mkdirSync2,
|
|
152863
152868
|
openSync,
|
|
152864
152869
|
readFileSync as readFileSync9,
|
|
@@ -152986,7 +152991,7 @@ function releaseVectorBackfillLock(lockPath = process.env.MEMORIX_VECTOR_BACKFIL
|
|
|
152986
152991
|
}
|
|
152987
152992
|
function launchDetachedVectorBackfill(request, options = {}) {
|
|
152988
152993
|
const runnerPath = options.runnerPath ?? resolveVectorBackfillRunnerPath();
|
|
152989
|
-
const exists = options.exists ??
|
|
152994
|
+
const exists = options.exists ?? existsSync13;
|
|
152990
152995
|
if (!exists(runnerPath)) return false;
|
|
152991
152996
|
const lock = acquireVectorBackfillLock(request.dataDir, request.projectId, options.lockPath);
|
|
152992
152997
|
if (!lock) return false;
|
|
@@ -155664,7 +155669,7 @@ __export(behavior_exports, {
|
|
|
155664
155669
|
getBehaviorConfig: () => getBehaviorConfig,
|
|
155665
155670
|
resetBehaviorConfigCache: () => resetBehaviorConfigCache
|
|
155666
155671
|
});
|
|
155667
|
-
import { existsSync as
|
|
155672
|
+
import { existsSync as existsSync16, readFileSync as readFileSync11 } from "fs";
|
|
155668
155673
|
import { homedir as homedir22 } from "os";
|
|
155669
155674
|
function isSessionInject(value) {
|
|
155670
155675
|
return value === "full" || value === "minimal" || value === "silent";
|
|
@@ -155675,7 +155680,7 @@ function isFormationMode(value) {
|
|
|
155675
155680
|
function legacyBehavior(homeDir) {
|
|
155676
155681
|
const configPath = getLegacyConfigJsonPath(homeDir);
|
|
155677
155682
|
try {
|
|
155678
|
-
if (!
|
|
155683
|
+
if (!existsSync16(configPath)) return {};
|
|
155679
155684
|
const parsed = JSON.parse(readFileSync11(configPath, "utf-8"));
|
|
155680
155685
|
return parsed.behavior && typeof parsed.behavior === "object" && !Array.isArray(parsed.behavior) ? parsed.behavior : {};
|
|
155681
155686
|
} catch {
|
|
@@ -157029,11 +157034,11 @@ __export(current_facts_exports, {
|
|
|
157029
157034
|
formatGitFact: () => formatGitFact
|
|
157030
157035
|
});
|
|
157031
157036
|
import { execFileSync } from "child_process";
|
|
157032
|
-
import { existsSync as
|
|
157037
|
+
import { existsSync as existsSync17, readFileSync as readFileSync12 } from "fs";
|
|
157033
157038
|
import path29 from "path";
|
|
157034
157039
|
function readTextIfExists(filePath) {
|
|
157035
157040
|
try {
|
|
157036
|
-
if (!
|
|
157041
|
+
if (!existsSync17(filePath)) return null;
|
|
157037
157042
|
return readFileSync12(filePath, "utf8");
|
|
157038
157043
|
} catch {
|
|
157039
157044
|
return null;
|
|
@@ -157324,7 +157329,7 @@ __export(external_provider_exports, {
|
|
|
157324
157329
|
runExternalCodeGraphLifecycle: () => runExternalCodeGraphLifecycle
|
|
157325
157330
|
});
|
|
157326
157331
|
import { spawn as spawn5 } from "child_process";
|
|
157327
|
-
import { existsSync as
|
|
157332
|
+
import { existsSync as existsSync18, readFileSync as readFileSync13 } from "fs";
|
|
157328
157333
|
import { delimiter, dirname as dirname2, extname, isAbsolute as isAbsolute3, join as join20, relative as relative4, resolve as resolve3, sep } from "path";
|
|
157329
157334
|
function boundedTimeout(value) {
|
|
157330
157335
|
if (!Number.isFinite(value)) return DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS;
|
|
@@ -157361,13 +157366,13 @@ function resolveCommandCandidates(command) {
|
|
|
157361
157366
|
}
|
|
157362
157367
|
function resolveLaunch(command) {
|
|
157363
157368
|
for (const candidate of resolveCommandCandidates(command)) {
|
|
157364
|
-
if (!
|
|
157369
|
+
if (!existsSync18(candidate)) continue;
|
|
157365
157370
|
const extension3 = extname(candidate).toLowerCase();
|
|
157366
157371
|
if (extension3 === ".cmd") {
|
|
157367
157372
|
const bundleRoot = resolve3(dirname2(candidate), "..");
|
|
157368
157373
|
const node = join20(bundleRoot, "node.exe");
|
|
157369
157374
|
const entry = join20(bundleRoot, "lib", "dist", "bin", "codegraph.js");
|
|
157370
|
-
if (
|
|
157375
|
+
if (existsSync18(node) && existsSync18(entry)) {
|
|
157371
157376
|
return { executable: node, prefixArgs: ["--liftoff-only", entry] };
|
|
157372
157377
|
}
|
|
157373
157378
|
try {
|
|
@@ -157376,7 +157381,7 @@ function resolveLaunch(command) {
|
|
|
157376
157381
|
if (match2?.[1]) {
|
|
157377
157382
|
const base = dirname2(candidate).endsWith(sep) ? dirname2(candidate) : dirname2(candidate) + sep;
|
|
157378
157383
|
const entry2 = resolve3(match2[1].replace(/%(?:~)?dp0%?/gi, base));
|
|
157379
|
-
if (
|
|
157384
|
+
if (existsSync18(entry2)) return { executable: process.execPath, prefixArgs: [entry2] };
|
|
157380
157385
|
}
|
|
157381
157386
|
} catch {
|
|
157382
157387
|
}
|
|
@@ -157524,7 +157529,7 @@ async function inspectExternalCodeGraph(input) {
|
|
|
157524
157529
|
const health2 = { state: "disabled", reason: "External CodeGraph is disabled by configuration." };
|
|
157525
157530
|
return { health: health2, quality: providerQuality({ mode, health: health2 }) };
|
|
157526
157531
|
}
|
|
157527
|
-
if (!
|
|
157532
|
+
if (!existsSync18(join20(input.projectRoot, ".codegraph"))) {
|
|
157528
157533
|
const health2 = { state: "not-detected", reason: "No local .codegraph index is present for this project." };
|
|
157529
157534
|
return { health: health2, quality: providerQuality({ mode, health: health2 }) };
|
|
157530
157535
|
}
|
|
@@ -157560,7 +157565,7 @@ async function runExternalCodeGraphLifecycle(input) {
|
|
|
157560
157565
|
};
|
|
157561
157566
|
}
|
|
157562
157567
|
const indexPath = join20(input.projectRoot, ".codegraph");
|
|
157563
|
-
if (input.action === "sync" && !
|
|
157568
|
+
if (input.action === "sync" && !existsSync18(indexPath)) {
|
|
157564
157569
|
const health = { state: "not-detected", reason: "No local .codegraph index is present for this project." };
|
|
157565
157570
|
return {
|
|
157566
157571
|
action: input.action,
|
|
@@ -157570,7 +157575,7 @@ async function runExternalCodeGraphLifecycle(input) {
|
|
|
157570
157575
|
quality: providerQuality({ mode, health })
|
|
157571
157576
|
};
|
|
157572
157577
|
}
|
|
157573
|
-
if (input.action === "init" &&
|
|
157578
|
+
if (input.action === "init" && existsSync18(indexPath)) {
|
|
157574
157579
|
const inspected2 = await inspectExternalCodeGraph(input);
|
|
157575
157580
|
return {
|
|
157576
157581
|
action: input.action,
|
|
@@ -158631,7 +158636,7 @@ __export(auto_context_exports, {
|
|
|
158631
158636
|
formatAutoProjectContextSummary: () => formatAutoProjectContextSummary,
|
|
158632
158637
|
formatLegacyAutoProjectContextPrompt: () => formatLegacyAutoProjectContextPrompt
|
|
158633
158638
|
});
|
|
158634
|
-
import { existsSync as
|
|
158639
|
+
import { existsSync as existsSync19, statSync as statSync5 } from "fs";
|
|
158635
158640
|
import path30 from "path";
|
|
158636
158641
|
function activeProjectObservations(observations2, projectId) {
|
|
158637
158642
|
return observations2.filter((obs) => obs.projectId === projectId && (obs.status ?? "active") === "active");
|
|
@@ -158977,7 +158982,7 @@ function existingLensCandidates(rootPath, lens) {
|
|
|
158977
158982
|
for (const candidate of lensPathCandidates(lens)) {
|
|
158978
158983
|
const absolute = path30.join(rootPath, candidate);
|
|
158979
158984
|
try {
|
|
158980
|
-
if (!
|
|
158985
|
+
if (!existsSync19(absolute)) continue;
|
|
158981
158986
|
const stat5 = statSync5(absolute);
|
|
158982
158987
|
if (stat5.isFile()) out.push(candidate);
|
|
158983
158988
|
if (stat5.isDirectory()) out.push(candidate.replace(/\\/g, "/"));
|
|
@@ -159511,7 +159516,7 @@ var engine_exports2 = {};
|
|
|
159511
159516
|
__export(engine_exports2, {
|
|
159512
159517
|
SkillsEngine: () => SkillsEngine
|
|
159513
159518
|
});
|
|
159514
|
-
import { existsSync as
|
|
159519
|
+
import { existsSync as existsSync20, readFileSync as readFileSync14, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, readdirSync as readdirSync4 } from "fs";
|
|
159515
159520
|
import { join as join21 } from "path";
|
|
159516
159521
|
import { homedir as homedir23 } from "os";
|
|
159517
159522
|
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;
|
|
@@ -159592,7 +159597,7 @@ var init_engine3 = __esm({
|
|
|
159592
159597
|
paths.push(join21(home, dir));
|
|
159593
159598
|
}
|
|
159594
159599
|
for (const skillsRoot of paths) {
|
|
159595
|
-
if (!
|
|
159600
|
+
if (!existsSync20(skillsRoot)) continue;
|
|
159596
159601
|
try {
|
|
159597
159602
|
const entries = readdirSync4(skillsRoot, { withFileTypes: true });
|
|
159598
159603
|
for (const entry of entries) {
|
|
@@ -159600,7 +159605,7 @@ var init_engine3 = __esm({
|
|
|
159600
159605
|
const name = entry.name;
|
|
159601
159606
|
if (seen.has(name)) continue;
|
|
159602
159607
|
const skillMd = join21(skillsRoot, name, "SKILL.md");
|
|
159603
|
-
if (!
|
|
159608
|
+
if (!existsSync20(skillMd)) continue;
|
|
159604
159609
|
try {
|
|
159605
159610
|
const content = readFileSync14(skillMd, "utf-8");
|
|
159606
159611
|
const description = this.parseDescription(content);
|
|
@@ -161401,7 +161406,8 @@ async function executeDeduplicate(context, payload, token) {
|
|
|
161401
161406
|
async function previewConsolidate(context) {
|
|
161402
161407
|
const clusters = await findConsolidationCandidates(
|
|
161403
161408
|
context.projectRoot ?? context.dataDir,
|
|
161404
|
-
context.projectId
|
|
161409
|
+
context.projectId,
|
|
161410
|
+
{ store: context.store }
|
|
161405
161411
|
);
|
|
161406
161412
|
const payload = { clusterIds: normalizeClusters(clusters.map((cluster) => cluster.ids)) };
|
|
161407
161413
|
return {
|
|
@@ -161424,11 +161430,19 @@ async function executeConsolidate(context, payload, token) {
|
|
|
161424
161430
|
const clusterIds = record80.clusterIds.map((ids, index) => payloadIds(ids, `clusterIds[${index}]`));
|
|
161425
161431
|
const normalized = { clusterIds: normalizeClusters(clusterIds) };
|
|
161426
161432
|
verify("consolidate", context.projectId, normalized, token);
|
|
161427
|
-
const current = await findConsolidationCandidates(
|
|
161433
|
+
const current = await findConsolidationCandidates(
|
|
161434
|
+
context.projectRoot ?? context.dataDir,
|
|
161435
|
+
context.projectId,
|
|
161436
|
+
{ store: context.store }
|
|
161437
|
+
);
|
|
161428
161438
|
if (JSON.stringify(normalized.clusterIds) !== JSON.stringify(normalizeClusters(current.map((cluster) => cluster.ids)))) {
|
|
161429
161439
|
throw new DashboardMaintenanceError("Memory changed after the preview. Refresh before consolidating.", 409);
|
|
161430
161440
|
}
|
|
161431
|
-
const result = await executeConsolidation(
|
|
161441
|
+
const result = await executeConsolidation(
|
|
161442
|
+
context.projectRoot ?? context.dataDir,
|
|
161443
|
+
context.projectId,
|
|
161444
|
+
{ store: context.store }
|
|
161445
|
+
);
|
|
161432
161446
|
return { action: "consolidate", projectId: context.projectId, ...result };
|
|
161433
161447
|
}
|
|
161434
161448
|
async function retentionCandidates(context) {
|
|
@@ -162585,7 +162599,7 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
162585
162599
|
}
|
|
162586
162600
|
case "/config": {
|
|
162587
162601
|
const os6 = await import("os");
|
|
162588
|
-
const { existsSync:
|
|
162602
|
+
const { existsSync: existsSync23 } = await import("fs");
|
|
162589
162603
|
const { join: join25 } = await import("path");
|
|
162590
162604
|
const configProjectRoot = effectiveProjectRoot;
|
|
162591
162605
|
const resolved = getResolvedConfig({ projectRoot: configProjectRoot });
|
|
@@ -162613,7 +162627,7 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
162613
162627
|
if (fpath === null) {
|
|
162614
162628
|
files[key] = { exists: false, path: "unavailable", unavailable: true };
|
|
162615
162629
|
} else {
|
|
162616
|
-
files[key] = { exists:
|
|
162630
|
+
files[key] = { exists: existsSync23(fpath), path: fpath };
|
|
162617
162631
|
}
|
|
162618
162632
|
}
|
|
162619
162633
|
} catch {
|
|
@@ -163423,7 +163437,7 @@ var init_task_graph = __esm({
|
|
|
163423
163437
|
|
|
163424
163438
|
// src/orchestrate/context-collector.ts
|
|
163425
163439
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
163426
|
-
import { readFileSync as readFileSync15, existsSync as
|
|
163440
|
+
import { readFileSync as readFileSync15, existsSync as existsSync21 } from "fs";
|
|
163427
163441
|
import { join as join22 } from "path";
|
|
163428
163442
|
function normalizeEntryLimit(value, fallback) {
|
|
163429
163443
|
if (!Number.isSafeInteger(value) || value < 1) return fallback;
|
|
@@ -163500,7 +163514,7 @@ function collectFileTree(projectDir2, maxEntries) {
|
|
|
163500
163514
|
function collectDependencies(projectDir2) {
|
|
163501
163515
|
try {
|
|
163502
163516
|
const pkgPath = join22(projectDir2, "package.json");
|
|
163503
|
-
if (!
|
|
163517
|
+
if (!existsSync21(pkgPath)) return "";
|
|
163504
163518
|
const pkg = JSON.parse(readFileSync15(pkgPath, "utf-8"));
|
|
163505
163519
|
const parts = [];
|
|
163506
163520
|
if (pkg.dependencies && Object.keys(pkg.dependencies).length > 0) {
|
|
@@ -166001,11 +166015,11 @@ __export(hooks_path_exports, {
|
|
|
166001
166015
|
resolveGitDir: () => resolveGitDir,
|
|
166002
166016
|
resolveHooksDir: () => resolveHooksDir
|
|
166003
166017
|
});
|
|
166004
|
-
import { existsSync as
|
|
166018
|
+
import { existsSync as existsSync22, readFileSync as readFileSync16, statSync as statSync6, mkdirSync as mkdirSync6 } from "fs";
|
|
166005
166019
|
import path35 from "path";
|
|
166006
166020
|
function resolveGitDir(projectRoot) {
|
|
166007
166021
|
const dotGit = path35.join(projectRoot, ".git");
|
|
166008
|
-
if (!
|
|
166022
|
+
if (!existsSync22(dotGit)) return null;
|
|
166009
166023
|
const stat5 = statSync6(dotGit);
|
|
166010
166024
|
if (stat5.isDirectory()) {
|
|
166011
166025
|
return dotGit;
|
|
@@ -166017,7 +166031,7 @@ function resolveGitDir(projectRoot) {
|
|
|
166017
166031
|
if (match2) {
|
|
166018
166032
|
const gitdir = match2[1].trim();
|
|
166019
166033
|
const resolved = path35.isAbsolute(gitdir) ? gitdir : path35.resolve(projectRoot, gitdir);
|
|
166020
|
-
if (
|
|
166034
|
+
if (existsSync22(resolved)) {
|
|
166021
166035
|
return resolved;
|
|
166022
166036
|
}
|
|
166023
166037
|
}
|
|
@@ -168233,7 +168247,7 @@ var RulesSyncer = class {
|
|
|
168233
168247
|
|
|
168234
168248
|
// src/workspace/engine.ts
|
|
168235
168249
|
init_esm_shims();
|
|
168236
|
-
import { readFileSync as readFileSync10, readdirSync as readdirSync3, existsSync as
|
|
168250
|
+
import { readFileSync as readFileSync10, readdirSync as readdirSync3, existsSync as existsSync15, cpSync, mkdirSync as mkdirSync4 } from "fs";
|
|
168237
168251
|
import { join as join19 } from "path";
|
|
168238
168252
|
import { homedir as homedir21 } from "os";
|
|
168239
168253
|
|
|
@@ -169185,7 +169199,7 @@ function sanitize(input) {
|
|
|
169185
169199
|
|
|
169186
169200
|
// src/workspace/applier.ts
|
|
169187
169201
|
init_esm_shims();
|
|
169188
|
-
import { existsSync as
|
|
169202
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync3, copyFileSync, writeFileSync as writeFileSync3, unlinkSync as unlinkSync2, renameSync } from "fs";
|
|
169189
169203
|
import { dirname } from "path";
|
|
169190
169204
|
var WorkspaceSyncApplier = class {
|
|
169191
169205
|
/**
|
|
@@ -169211,7 +169225,7 @@ var WorkspaceSyncApplier = class {
|
|
|
169211
169225
|
for (const file of files) {
|
|
169212
169226
|
try {
|
|
169213
169227
|
const dir = dirname(file.filePath);
|
|
169214
|
-
if (!
|
|
169228
|
+
if (!existsSync14(dir)) {
|
|
169215
169229
|
mkdirSync3(dir, { recursive: true });
|
|
169216
169230
|
}
|
|
169217
169231
|
} catch (err) {
|
|
@@ -169220,7 +169234,7 @@ var WorkspaceSyncApplier = class {
|
|
|
169220
169234
|
}
|
|
169221
169235
|
}
|
|
169222
169236
|
for (const file of files) {
|
|
169223
|
-
if (
|
|
169237
|
+
if (existsSync14(file.filePath)) {
|
|
169224
169238
|
try {
|
|
169225
169239
|
const backupPath = file.filePath + `.backup-${Date.now()}`;
|
|
169226
169240
|
copyFileSync(file.filePath, backupPath);
|
|
@@ -169271,7 +169285,7 @@ var WorkspaceSyncApplier = class {
|
|
|
169271
169285
|
cleanBackups(backups) {
|
|
169272
169286
|
for (const backup of backups) {
|
|
169273
169287
|
try {
|
|
169274
|
-
if (
|
|
169288
|
+
if (existsSync14(backup.backupPath)) {
|
|
169275
169289
|
unlinkSync2(backup.backupPath);
|
|
169276
169290
|
}
|
|
169277
169291
|
} catch {
|
|
@@ -169336,7 +169350,7 @@ var WorkspaceSyncEngine = class _WorkspaceSyncEngine {
|
|
|
169336
169350
|
}
|
|
169337
169351
|
const merged = /* @__PURE__ */ new Map();
|
|
169338
169352
|
for (const path36 of pathsToCheck) {
|
|
169339
|
-
if (
|
|
169353
|
+
if (existsSync15(path36)) {
|
|
169340
169354
|
try {
|
|
169341
169355
|
const content = readFileSync10(path36, "utf-8");
|
|
169342
169356
|
const servers = adapter.parse(content);
|
|
@@ -169390,7 +169404,7 @@ var WorkspaceSyncEngine = class _WorkspaceSyncEngine {
|
|
|
169390
169404
|
const adapter = this.adapters.get(target);
|
|
169391
169405
|
const configPath = adapter.getConfigPath(this.projectRoot);
|
|
169392
169406
|
let configContent;
|
|
169393
|
-
if (target === "antigravity" &&
|
|
169407
|
+
if (target === "antigravity" && existsSync15(configPath)) {
|
|
169394
169408
|
try {
|
|
169395
169409
|
const existing = JSON.parse(readFileSync10(configPath, "utf-8"));
|
|
169396
169410
|
const generated = JSON.parse(adapter.generate(result.mcpServers.scanned));
|
|
@@ -169466,13 +169480,13 @@ var WorkspaceSyncEngine = class _WorkspaceSyncEngine {
|
|
|
169466
169480
|
join19(home, dir)
|
|
169467
169481
|
];
|
|
169468
169482
|
for (const skillsRoot of paths) {
|
|
169469
|
-
if (!
|
|
169483
|
+
if (!existsSync15(skillsRoot)) continue;
|
|
169470
169484
|
try {
|
|
169471
169485
|
const entries = readdirSync3(skillsRoot, { withFileTypes: true });
|
|
169472
169486
|
for (const entry of entries) {
|
|
169473
169487
|
if (!entry.isDirectory()) continue;
|
|
169474
169488
|
const skillMd = join19(skillsRoot, entry.name, "SKILL.md");
|
|
169475
|
-
if (!
|
|
169489
|
+
if (!existsSync15(skillMd)) continue;
|
|
169476
169490
|
let description = "";
|
|
169477
169491
|
try {
|
|
169478
169492
|
const content = readFileSync10(skillMd, "utf-8");
|
|
@@ -169521,7 +169535,7 @@ var WorkspaceSyncEngine = class _WorkspaceSyncEngine {
|
|
|
169521
169535
|
for (const skill2 of skills) {
|
|
169522
169536
|
if (skill2.sourceAgent === target) continue;
|
|
169523
169537
|
const dest = join19(targetDir, skill2.name);
|
|
169524
|
-
if (
|
|
169538
|
+
if (existsSync15(dest)) {
|
|
169525
169539
|
skipped.push(`${skill2.name} (already exists in ${target})`);
|
|
169526
169540
|
continue;
|
|
169527
169541
|
}
|
|
@@ -169537,7 +169551,7 @@ var WorkspaceSyncEngine = class _WorkspaceSyncEngine {
|
|
|
169537
169551
|
scanWorkflows() {
|
|
169538
169552
|
const workflows = [];
|
|
169539
169553
|
const wfDir = join19(this.projectRoot, ".windsurf", "workflows");
|
|
169540
|
-
if (!
|
|
169554
|
+
if (!existsSync15(wfDir)) return workflows;
|
|
169541
169555
|
try {
|
|
169542
169556
|
const files = readdirSync3(wfDir).filter((f3) => f3.endsWith(".md"));
|
|
169543
169557
|
for (const file of files) {
|
|
@@ -169882,7 +169896,7 @@ var MCP_SERVER_INFO_META_KEY = "io.modelcontextprotocol/serverInfo";
|
|
|
169882
169896
|
function getMcpServerInfo() {
|
|
169883
169897
|
return {
|
|
169884
169898
|
name: "memorix",
|
|
169885
|
-
version: true ? "1.9.
|
|
169899
|
+
version: true ? "1.9.2" : "1.0.1"
|
|
169886
169900
|
};
|
|
169887
169901
|
}
|
|
169888
169902
|
function createMcpDiscoverResult(capabilities, serverInfo) {
|
|
@@ -174499,10 +174513,10 @@ Preview: ${analysis.description.slice(0, 300)}${analysis.description.length > 30
|
|
|
174499
174513
|
const { ensureHooksDir: ensureHooksDir2 } = await Promise.resolve().then(() => (init_hooks_path(), hooks_path_exports));
|
|
174500
174514
|
const resolved = ensureHooksDir2(project.rootPath);
|
|
174501
174515
|
if (resolved) {
|
|
174502
|
-
const { existsSync:
|
|
174516
|
+
const { existsSync: existsSync23, readFileSync: readFileSync17, writeFileSync: writeFileSync5, chmodSync } = await import("fs");
|
|
174503
174517
|
const { hookPath } = resolved;
|
|
174504
174518
|
const HOOK_MARKER = "# [memorix-git-hook]";
|
|
174505
|
-
const needsInstall = !
|
|
174519
|
+
const needsInstall = !existsSync23(hookPath) || !readFileSync17(hookPath, "utf-8").includes(HOOK_MARKER);
|
|
174506
174520
|
if (needsInstall) {
|
|
174507
174521
|
const hookScript = `#!/bin/sh
|
|
174508
174522
|
${HOOK_MARKER}
|
|
@@ -174511,7 +174525,7 @@ if command -v memorix >/dev/null 2>&1; then
|
|
|
174511
174525
|
memorix ingest commit --auto >/dev/null 2>&1 &
|
|
174512
174526
|
fi
|
|
174513
174527
|
`;
|
|
174514
|
-
if (
|
|
174528
|
+
if (existsSync23(hookPath)) {
|
|
174515
174529
|
const existing = readFileSync17(hookPath, "utf-8");
|
|
174516
174530
|
writeFileSync5(hookPath, existing.trimEnd() + `
|
|
174517
174531
|
|
|
@@ -11716,7 +11716,8 @@ function clampCursor(afterId) {
|
|
|
11716
11716
|
}
|
|
11717
11717
|
async function loadConsolidationPage(projectId, options) {
|
|
11718
11718
|
const limit2 = clampBatchSize(options.limit);
|
|
11719
|
-
const
|
|
11719
|
+
const store = options.store ?? getObservationStore();
|
|
11720
|
+
const page = await store.loadByProject(projectId, {
|
|
11720
11721
|
status: "active",
|
|
11721
11722
|
afterId: clampCursor(options.afterId),
|
|
11722
11723
|
limit: limit2 + 1
|
|
@@ -11776,7 +11777,7 @@ async function findConsolidationCandidates(_projectDir, projectId, opts) {
|
|
|
11776
11777
|
return findClusters(page.observations, threshold);
|
|
11777
11778
|
}
|
|
11778
11779
|
async function executeConsolidation(_projectDir, projectId, opts) {
|
|
11779
|
-
const store = getObservationStore();
|
|
11780
|
+
const store = opts?.store ?? getObservationStore();
|
|
11780
11781
|
const page = await loadConsolidationPage(projectId, opts ?? {});
|
|
11781
11782
|
const clusters = findClusters(page.observations, opts?.threshold ?? DEFAULT_SIMILARITY_THRESHOLD);
|
|
11782
11783
|
if (clusters.length === 0) {
|
|
@@ -148353,7 +148354,7 @@ __export(lite_provider_exports, {
|
|
|
148353
148354
|
refreshProjectLite: () => refreshProjectLite
|
|
148354
148355
|
});
|
|
148355
148356
|
import { createHash as createHash10 } from "crypto";
|
|
148356
|
-
import { readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
|
|
148357
|
+
import { existsSync as existsSync11, readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
|
|
148357
148358
|
import { join as join4, relative as relative2 } from "path";
|
|
148358
148359
|
function hashText2(text2) {
|
|
148359
148360
|
return createHash10("sha256").update(text2).digest("hex");
|
|
@@ -148370,6 +148371,9 @@ function resolveMaxFileBytes(value) {
|
|
|
148370
148371
|
if (!Number.isFinite(value)) return DEFAULT_CODEGRAPH_MAX_FILE_BYTES;
|
|
148371
148372
|
return Math.max(1, Math.floor(value));
|
|
148372
148373
|
}
|
|
148374
|
+
function isPythonVirtualenvDir(dir) {
|
|
148375
|
+
return existsSync11(join4(dir, "pyvenv.cfg"));
|
|
148376
|
+
}
|
|
148373
148377
|
function walk(root, exclude, maxFiles) {
|
|
148374
148378
|
const out = [];
|
|
148375
148379
|
const visit = (dir) => {
|
|
@@ -148387,6 +148391,7 @@ function walk(root, exclude, maxFiles) {
|
|
|
148387
148391
|
if (entry.isDirectory()) {
|
|
148388
148392
|
if (entry.name === ".git" || entry.name === ".worktrees" || entry.name === ".tmp" || entry.name === "node_modules") continue;
|
|
148389
148393
|
if (rel === ".claude/worktrees" || rel.startsWith(".claude/worktrees/")) continue;
|
|
148394
|
+
if (isPythonVirtualenvDir(abs)) continue;
|
|
148390
148395
|
visit(abs);
|
|
148391
148396
|
if (out.length >= maxFiles) return;
|
|
148392
148397
|
continue;
|
|
@@ -151749,7 +151754,7 @@ __export(vector_backfill_runner_exports, {
|
|
|
151749
151754
|
import { spawn as spawn3 } from "child_process";
|
|
151750
151755
|
import {
|
|
151751
151756
|
closeSync,
|
|
151752
|
-
existsSync as
|
|
151757
|
+
existsSync as existsSync12,
|
|
151753
151758
|
mkdirSync as mkdirSync2,
|
|
151754
151759
|
openSync,
|
|
151755
151760
|
readFileSync as readFileSync9,
|
|
@@ -151877,7 +151882,7 @@ function releaseVectorBackfillLock(lockPath = process.env.MEMORIX_VECTOR_BACKFIL
|
|
|
151877
151882
|
}
|
|
151878
151883
|
function launchDetachedVectorBackfill(request, options = {}) {
|
|
151879
151884
|
const runnerPath = options.runnerPath ?? resolveVectorBackfillRunnerPath();
|
|
151880
|
-
const exists = options.exists ??
|
|
151885
|
+
const exists = options.exists ?? existsSync12;
|
|
151881
151886
|
if (!exists(runnerPath)) return false;
|
|
151882
151887
|
const lock = acquireVectorBackfillLock(request.dataDir, request.projectId, options.lockPath);
|
|
151883
151888
|
if (!lock) return false;
|
package/docs/INTEGRATIONS.md
CHANGED
|
@@ -122,6 +122,10 @@ If an agent only needs a raw stdio MCP entry:
|
|
|
122
122
|
|
|
123
123
|
Avoid `npx` in persistent MCP configs. Use the globally installed `memorix` binary so startup is predictable.
|
|
124
124
|
|
|
125
|
+
For npm-based MCP clients or registry testers, the complete package command is
|
|
126
|
+
`npx -y memorix serve`. Do not omit `serve`: bare `memorix` is the interactive
|
|
127
|
+
memcode entry in a human terminal.
|
|
128
|
+
|
|
125
129
|
For HTTP mode:
|
|
126
130
|
|
|
127
131
|
```bash
|
package/docs/SETUP.md
CHANGED
|
@@ -170,6 +170,11 @@ Generic stdio MCP config:
|
|
|
170
170
|
|
|
171
171
|
Avoid `npx` in persistent MCP configs. Use the globally installed `memorix` binary so startup is predictable.
|
|
172
172
|
|
|
173
|
+
When an npm-based MCP client or registry tester must launch the package
|
|
174
|
+
directly, use `npx -y memorix serve`. The explicit `serve` argument selects
|
|
175
|
+
the stdio MCP server; a human running bare `memorix` in a terminal gets the
|
|
176
|
+
bundled memcode agent instead.
|
|
177
|
+
|
|
173
178
|
### Option C: memcode terminal agent
|
|
174
179
|
|
|
175
180
|
```bash
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "memorix",
|
|
3
3
|
"mcpName": "io.github.AVIDS2/memorix",
|
|
4
|
-
"version": "1.9.
|
|
4
|
+
"version": "1.9.2",
|
|
5
5
|
"description": "Local-first shared memory layer for AI coding agents across MCP clients, Git history, reasoning context, and project sessions.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"sideEffects": false,
|
|
@@ -77,7 +77,6 @@
|
|
|
77
77
|
"benchmark:codegraph:scale": "node scripts/benchmark-codegraph-scale.mjs",
|
|
78
78
|
"benchmark:retrieval": "npm run build && node scripts/benchmark-retrieval.mjs",
|
|
79
79
|
"gate:large-store": "npm run build && node scripts/large-store-gate.mjs",
|
|
80
|
-
"generate:star-history": "node scripts/generate-star-history.mjs",
|
|
81
80
|
"sync:mcp-registry": "node scripts/sync-mcp-registry-manifest.mjs",
|
|
82
81
|
"check:mcp-registry": "node scripts/check-mcp-registry-manifest.mjs",
|
|
83
82
|
"sync:plugin-release": "node scripts/sync-plugin-release-manifests.mjs",
|
package/server.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"url": "https://github.com/AVIDS2/memorix",
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
|
-
"version": "1.9.
|
|
10
|
+
"version": "1.9.2",
|
|
11
11
|
"websiteUrl": "https://mem.rglens.com",
|
|
12
12
|
"icons": [
|
|
13
13
|
{
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
{
|
|
23
23
|
"registryType": "npm",
|
|
24
24
|
"identifier": "memorix",
|
|
25
|
-
"version": "1.9.
|
|
25
|
+
"version": "1.9.2",
|
|
26
26
|
"runtimeHint": "npx",
|
|
27
27
|
"packageArguments": [
|
|
28
28
|
{
|
|
@@ -280,7 +280,8 @@ export default defineCommand({
|
|
|
280
280
|
case 'deduplicate': {
|
|
281
281
|
const query = asStringArg(args.query);
|
|
282
282
|
const dryRun = !!args.dryRun || !!args['dry-run'];
|
|
283
|
-
const { isLLMEnabled } = await import('../../llm/provider.js');
|
|
283
|
+
const { initLLM, isLLMEnabled } = await import('../../llm/provider.js');
|
|
284
|
+
initLLM({ scope: 'memory', projectRoot: project.rootPath });
|
|
284
285
|
if (!isLLMEnabled()) {
|
|
285
286
|
emitResult(
|
|
286
287
|
{ project, available: false, usedLLM: false },
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface CliInteractivity {
|
|
2
|
+
stdinIsTTY?: boolean;
|
|
3
|
+
stdoutIsTTY?: boolean;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* MCP hosts start package commands with piped stdio, while a human terminal
|
|
8
|
+
* has TTYs on both streams. Keep the friendly memcode default for humans and
|
|
9
|
+
* make the package safe for registry probes and generic MCP launchers.
|
|
10
|
+
*/
|
|
11
|
+
export function shouldDefaultToMcp(options: CliInteractivity = {}): boolean {
|
|
12
|
+
const stdinIsTTY = options.stdinIsTTY ?? process.stdin.isTTY;
|
|
13
|
+
const stdoutIsTTY = options.stdoutIsTTY ?? process.stdout.isTTY;
|
|
14
|
+
return stdinIsTTY !== true || stdoutIsTTY !== true;
|
|
15
|
+
}
|