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/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 page = await getObservationStore().loadByProject(projectId, {
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 existsSync12,
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 ?? existsSync12;
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 existsSync15, readFileSync as readFileSync11 } from "fs";
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 (!existsSync15(configPath)) return {};
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 existsSync16, readFileSync as readFileSync12 } from "fs";
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 (!existsSync16(filePath)) return null;
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 existsSync17, readFileSync as readFileSync13 } from "fs";
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 (!existsSync17(candidate)) continue;
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 (existsSync17(node) && existsSync17(entry)) {
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 (existsSync17(entry2)) return { executable: process.execPath, prefixArgs: [entry2] };
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 (!existsSync17(join20(input.projectRoot, ".codegraph"))) {
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" && !existsSync17(indexPath)) {
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" && existsSync17(indexPath)) {
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 existsSync18, statSync as statSync5 } from "fs";
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 (!existsSync18(absolute)) continue;
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 existsSync19, readFileSync as readFileSync14, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, readdirSync as readdirSync4 } from "fs";
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 (!existsSync19(skillsRoot)) continue;
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 (!existsSync19(skillMd)) continue;
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(context.projectRoot ?? context.dataDir, context.projectId);
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(context.projectRoot ?? context.dataDir, context.projectId);
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: existsSync22 } = await import("fs");
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: existsSync22(fpath), path: fpath };
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 existsSync20 } from "fs";
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 (!existsSync20(pkgPath)) return "";
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 existsSync21, readFileSync as readFileSync16, statSync as statSync6, mkdirSync as mkdirSync6 } from "fs";
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 (!existsSync21(dotGit)) return null;
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 (existsSync21(resolved)) {
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 existsSync14, cpSync, mkdirSync as mkdirSync4 } from "fs";
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 existsSync13, mkdirSync as mkdirSync3, copyFileSync, writeFileSync as writeFileSync3, unlinkSync as unlinkSync2, renameSync } from "fs";
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 (!existsSync13(dir)) {
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 (existsSync13(file.filePath)) {
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 (existsSync13(backup.backupPath)) {
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 (existsSync14(path36)) {
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" && existsSync14(configPath)) {
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 (!existsSync14(skillsRoot)) continue;
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 (!existsSync14(skillMd)) continue;
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 (existsSync14(dest)) {
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 (!existsSync14(wfDir)) return workflows;
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.1" : "1.0.1"
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: existsSync22, readFileSync: readFileSync17, writeFileSync: writeFileSync5, chmodSync } = await import("fs");
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 = !existsSync22(hookPath) || !readFileSync17(hookPath, "utf-8").includes(HOOK_MARKER);
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 (existsSync22(hookPath)) {
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 page = await getObservationStore().loadByProject(projectId, {
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 existsSync11,
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 ?? existsSync11;
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;
@@ -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.1",
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",
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.9.1"
3
+ "version": "1.9.2"
4
4
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://anthropic.com/claude-code/plugin.schema.json",
3
3
  "name": "memorix",
4
- "version": "1.9.1",
4
+ "version": "1.9.2",
5
5
  "description": "Shared workspace memory for Claude Code and other AI coding agents.",
6
6
  "author": {
7
7
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.9.1",
3
+ "version": "1.9.2",
4
4
  "description": "Local-first project memory for CodeBuddy Code and other coding agents.",
5
5
  "author": {
6
6
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.9.1",
3
+ "version": "1.9.2",
4
4
  "description": "Shared workspace memory for Codex and other AI coding agents.",
5
5
  "author": {
6
6
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.9.1",
3
+ "version": "1.9.2",
4
4
  "description": "Shared local workspace memory for GitHub Copilot CLI and other AI coding agents.",
5
5
  "author": {
6
6
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.9.1",
3
+ "version": "1.9.2",
4
4
  "mcpServers": {
5
5
  "memorix": {
6
6
  "command": "memorix",
@@ -1,5 +1,5 @@
1
1
  name: memorix
2
- version: "1.9.1"
2
+ version: "1.9.2"
3
3
  description: Shared workspace memory bridge for Hermes Agent.
4
4
  author: AVIDS2
5
5
  license: Apache-2.0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix-omp-package",
3
- "version": "1.9.1",
3
+ "version": "1.9.2",
4
4
  "description": "Memorix shared workspace memory package for Oh-my-Pi.",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.9.1",
3
+ "version": "1.9.2",
4
4
  "description": "Shared workspace memory for OpenClaw and other AI coding agents.",
5
5
  "author": {
6
6
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix-pi-package",
3
- "version": "1.9.1",
3
+ "version": "1.9.2",
4
4
  "description": "Memorix shared workspace memory package for Pi coding agent.",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
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.1",
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.1",
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
+ }