memorix 1.8.4 → 1.8.5

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.
Files changed (73) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/CLAUDE.md +3 -0
  3. package/README.md +4 -4
  4. package/README.zh-CN.md +5 -3
  5. package/dist/cli/index.js +1542 -626
  6. package/dist/dashboard/static/app.js +29 -885
  7. package/dist/dashboard/static/index.html +1 -5
  8. package/dist/dashboard/static/style.css +36 -503
  9. package/dist/index.d.ts +4 -4
  10. package/dist/index.js +213 -70
  11. package/dist/memcode/index.js +28035 -169
  12. package/dist/memcode-runtime/CHANGELOG.md +34 -0
  13. package/dist/sdk.js +30 -12
  14. package/docs/1.8.0-RELEASE-CANDIDATE-SPEC.md +22 -16
  15. package/docs/AGENT_OPERATOR_PLAYBOOK.md +2 -2
  16. package/docs/API_REFERENCE.md +10 -8
  17. package/docs/DASHBOARD.md +23 -0
  18. package/docs/DEVELOPMENT.md +2 -2
  19. package/docs/DOCKER.md +6 -3
  20. package/docs/INTEGRATIONS.md +1 -1
  21. package/docs/MODULES.md +46 -20
  22. package/docs/PERFORMANCE.md +1 -1
  23. package/docs/README.md +8 -7
  24. package/docs/SETUP.md +3 -3
  25. package/package.json +11 -11
  26. package/plugins/antigravity/memorix/plugin.json +1 -1
  27. package/plugins/antigravity/memorix/rules/memorix.md +5 -0
  28. package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
  29. package/plugins/claude/memorix/skills/memorix-memory/SKILL.md +3 -0
  30. package/plugins/claude/memorix/skills/memorix-mini-skills/SKILL.md +2 -0
  31. package/plugins/claude/memorix/skills/memorix-orchestrate/SKILL.md +2 -0
  32. package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
  33. package/plugins/codebuddy/memorix/skills/memorix-memory/SKILL.md +3 -0
  34. package/plugins/codebuddy/memorix/skills/memorix-mini-skills/SKILL.md +2 -0
  35. package/plugins/codebuddy/memorix/skills/memorix-orchestrate/SKILL.md +2 -0
  36. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  37. package/plugins/codex/memorix/skills/memorix-memory/SKILL.md +3 -0
  38. package/plugins/codex/memorix/skills/memorix-mini-skills/SKILL.md +2 -0
  39. package/plugins/codex/memorix/skills/memorix-orchestrate/SKILL.md +2 -0
  40. package/plugins/copilot/memorix/plugin.json +1 -1
  41. package/plugins/copilot/memorix/skills/memorix-memory/SKILL.md +3 -0
  42. package/plugins/copilot/memorix/skills/memorix-mini-skills/SKILL.md +2 -0
  43. package/plugins/copilot/memorix/skills/memorix-orchestrate/SKILL.md +2 -0
  44. package/plugins/cursor/memorix/skills/memorix-memory/SKILL.md +3 -0
  45. package/plugins/cursor/memorix/skills/memorix-mini-skills/SKILL.md +2 -0
  46. package/plugins/cursor/memorix/skills/memorix-orchestrate/SKILL.md +2 -0
  47. package/plugins/gemini/memorix/GEMINI.md +5 -0
  48. package/plugins/gemini/memorix/gemini-extension.json +1 -1
  49. package/plugins/hermes/memorix/plugin.yaml +7 -1
  50. package/plugins/omp/memorix/package.json +1 -1
  51. package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
  52. package/plugins/pi/memorix/package.json +1 -1
  53. package/plugins/pi/memorix/skills/memorix-memory/SKILL.md +3 -0
  54. package/plugins/pi/memorix/skills/memorix-mini-skills/SKILL.md +2 -0
  55. package/plugins/pi/memorix/skills/memorix-orchestrate/SKILL.md +2 -0
  56. package/server.json +2 -2
  57. package/src/cli/command-guide.ts +52 -1
  58. package/src/cli/commands/background.ts +166 -6
  59. package/src/cli/commands/serve-http.ts +73 -80
  60. package/src/cli/commands/serve.ts +95 -93
  61. package/src/cli/index.ts +1 -1
  62. package/src/dashboard/static/index.html +1 -5
  63. package/src/dashboard/static/style.css +36 -503
  64. package/src/hooks/installers/index.ts +3 -0
  65. package/src/hooks/official-skills.ts +13 -6
  66. package/src/memory/graph.ts +2 -2
  67. package/src/server/mcp-diagnostics.ts +9 -7
  68. package/src/server/modern-mcp-bridge.ts +108 -0
  69. package/src/server/stdio-startup-gate.ts +41 -2
  70. package/src/server/tool-profile.ts +7 -6
  71. package/src/server.ts +1 -1
  72. package/src/store/orama-store.ts +2 -2
  73. package/src/wiki/types.ts +2 -2
package/dist/index.js CHANGED
@@ -156854,17 +156854,25 @@ function resolveToolProfile(opts) {
156854
156854
  return normalize(opts.explicit) ?? normalize(opts.envValue) ?? opts.fallback;
156855
156855
  }
156856
156856
  function describeProfile(profile) {
156857
+ const count2 = countToolsInProfile(profile);
156857
156858
  switch (profile) {
156858
156859
  case "micro":
156859
- return "micro (agent-ready context + bounded recovery/media, ~9 tools)";
156860
+ return `micro (agent-ready context + bounded recovery/media, ${count2} tools)`;
156860
156861
  case "lite":
156861
- return "lite (core memory + sessions, ~18 tools)";
156862
+ return `lite (core memory + sessions, ${count2} tools)`;
156862
156863
  case "team":
156863
- return "team (lite + coordination tools + dashboard + knowledge workspace, ~26 tools)";
156864
+ return `team (lite + coordination tools + dashboard + knowledge workspace, ${count2} tools)`;
156864
156865
  case "full":
156865
- return "full (all tools including advanced / KG-compat)";
156866
+ return `full (all tools including advanced / KG-compat, ${count2} tools)`;
156866
156867
  }
156867
156868
  }
156869
+ function countToolsInProfile(profile) {
156870
+ let n = 0;
156871
+ for (const name of Object.keys(TOOL_PROFILES)) {
156872
+ if (isToolInProfile(name, profile)) n++;
156873
+ }
156874
+ return n;
156875
+ }
156868
156876
  var TOOL_PROFILES;
156869
156877
  var init_tool_profile = __esm({
156870
156878
  "src/server/tool-profile.ts"() {
@@ -158121,7 +158129,7 @@ var init_request_context = __esm({
158121
158129
  function getMcpServerInfo() {
158122
158130
  return {
158123
158131
  name: "memorix",
158124
- version: true ? "1.8.4" : "1.0.1"
158132
+ version: true ? "1.8.5" : "1.0.1"
158125
158133
  };
158126
158134
  }
158127
158135
  function createMcpDiscoverResult(capabilities, serverInfo) {
@@ -166530,6 +166538,9 @@ var init_official_skills = __esm({
166530
166538
  '| Specific past decision, bug, file, or change | `memorix_search` | `memorix memory search --query "<topic>"` |',
166531
166539
  "| Need the full source for a search hit | `memorix_detail` | `memorix memory detail --id <id>` |",
166532
166540
  "| Need the sequence around one memory | `memorix_timeline` | `memorix memory timeline --id <id>` |",
166541
+ "| Check source and freshness for a memory | `memorix_evidence` | `memorix evidence list|get|events` |",
166542
+ "| Record whether a memory helped, conflicted, or was corrected | `memorix_feedback` | `memorix feedback record|show|audit` |",
166543
+ "| Inspect or import controlled media | `memorix_media` | `memorix media import|attach|list|show|status` |",
166533
166544
  '| Learned reusable project knowledge | `memorix_store` | `memorix memory store --type <type> --entity <name> --title "<title>" "<text>"` |',
166534
166545
  "| Task or bug is complete/outdated | `memorix_resolve` | `memorix memory resolve --ids <ids>` |",
166535
166546
  "",
@@ -166660,6 +166671,8 @@ var init_official_skills = __esm({
166660
166671
  "",
166661
166672
  "Promote memories into mini-skills only when they are reusable instructions, not just historical notes.",
166662
166673
  "",
166674
+ "The standard setup uses the `lite` MCP profile. `memorix_skills` and `memorix_promote` are full-profile tools, so use the CLI fallback unless the current server was explicitly started with `MEMORIX_MODE=full` or `--mode full`. Do not probe hidden MCP tools repeatedly.",
166675
+ "",
166663
166676
  "## Tool Router",
166664
166677
  "",
166665
166678
  "| Situation | Prefer | CLI fallback |",
@@ -166695,15 +166708,17 @@ var init_official_skills = __esm({
166695
166708
  "| Situation | Prefer | CLI fallback |",
166696
166709
  "|---|---|---|",
166697
166710
  '| Run managed subagent execution | CLI | `memorix orchestrate --goal "<goal>" --agents claude:1,codex:1` |',
166698
- "| Register coordination identity | `team_manage` action `join` | `memorix team join --agentType <agent>` |",
166699
- "| Create or inspect tasks | `team_task` | `memorix task create|list|claim|complete` |",
166700
- "| Send or read coordination messages | `team_message` | `memorix message send|broadcast|inbox` |",
166701
- "| Share structured handoff | `memorix_handoff` | `memorix handoff send` |",
166702
- "| Avoid file conflicts | `team_file_lock` | `memorix lock lock|unlock|status` |",
166703
- "| Poll joined coordination state | `memorix_poll` | `memorix poll` |",
166711
+ "| Register coordination identity when team MCP tools are available | `team_manage` action `join` | `memorix team join --agentType <agent>` |",
166712
+ "| Create or inspect tasks when team MCP tools are available | `team_task` | `memorix task create|list|claim|complete` |",
166713
+ "| Send or read coordination messages when team MCP tools are available | `team_message` | `memorix message send|broadcast|inbox` |",
166714
+ "| Share structured handoff when team MCP tools are available | `memorix_handoff` | `memorix handoff send` |",
166715
+ "| Avoid file conflicts when team MCP tools are available | `team_file_lock` | `memorix lock lock|unlock|status` |",
166716
+ "| Poll joined coordination state when team MCP tools are available | `memorix_poll` | `memorix poll` |",
166704
166717
  "",
166705
166718
  "## Boundaries",
166706
166719
  "",
166720
+ "The standard setup uses the `lite` MCP profile. Coordination MCP tools are exposed only by `team` or `full`; use the CLI fallback for ordinary installations, or explicitly start the server with `--mode team`. Do not probe unavailable team tools in a loop.",
166721
+ "",
166707
166722
  "- For ordinary memory, do not join coordination state.",
166708
166723
  "- For production multi-agent execution, prefer `memorix orchestrate` so the main process owns planning, dispatch, retries, and verification gates.",
166709
166724
  "- `memorix orchestrate` uses the current checkout for single-worker runs and task worktrees for parallel runs. Use `--isolated` to force worktree isolation, `--no-worktree` to disable it, `--allow-dirty` to run with uncommitted changes, and `--no-auto-merge` to preserve task worktrees for manual review.",
@@ -167867,7 +167882,10 @@ alwaysApply: true
167867
167882
  "| `memorix_store` | Save something worth persisting |",
167868
167883
  '| `memorix_store_reasoning` | Save the "why" behind a decision |',
167869
167884
  "| `memorix_resolve` | Mark completed/outdated memories |",
167870
- "| `memorix_session_start` | Load session context (handoff, orchestration coordination) |"
167885
+ "| `memorix_session_start` | Load session context (handoff, orchestration coordination) |",
167886
+ "| `memorix_evidence` | Check a memory source, freshness, and verification state |",
167887
+ "| `memorix_feedback` | Record whether a memory helped, conflicted, or was corrected |",
167888
+ "| `memorix_media` | Inspect or import controlled local media |"
167871
167889
  ].join("\n");
167872
167890
  }
167873
167891
  async function uninstallHooks(agent, projectRoot, global2 = false) {
@@ -172907,7 +172925,17 @@ var init_stdio_startup_gate = __esm({
172907
172925
  this.fail(new Error(`stdio input chunk exceeded ${this.maxBufferSize} bytes`));
172908
172926
  return;
172909
172927
  }
172910
- this.input.write(chunk);
172928
+ this.pendingInput += typeof chunk === "string" ? chunk : chunk.toString("utf8");
172929
+ let newline2 = this.pendingInput.indexOf("\n");
172930
+ while (newline2 >= 0 && !this.stopped) {
172931
+ const line = this.pendingInput.slice(0, newline2 + 1);
172932
+ this.pendingInput = this.pendingInput.slice(newline2 + 1);
172933
+ this.handleReadyLine(line);
172934
+ newline2 = this.pendingInput.indexOf("\n");
172935
+ }
172936
+ if (!this.stopped && Buffer.byteLength(this.pendingInput, "utf8") > this.maxBufferSize) {
172937
+ this.fail(new Error(`stdio input exceeded ${this.maxBufferSize} bytes`));
172938
+ }
172911
172939
  return;
172912
172940
  }
172913
172941
  const text2 = typeof chunk === "string" ? chunk : chunk.toString("utf8");
@@ -173006,6 +173034,24 @@ var init_stdio_startup_gate = __esm({
173006
173034
  this.queuedMessages.push(line);
173007
173035
  this.queuedBytes += bytes;
173008
173036
  }
173037
+ handleReadyLine(line) {
173038
+ const parsed = this.parseLine(line);
173039
+ if (parsed && !("error" in parsed) && this.isDiscoveryRequest(parsed.message)) {
173040
+ const response = {
173041
+ jsonrpc: "2.0",
173042
+ id: parsed.message.id,
173043
+ result: createMcpStartupDiscoverResult(this.serverInfo)
173044
+ };
173045
+ try {
173046
+ this.stdout.write(`${JSON.stringify(response)}
173047
+ `);
173048
+ } catch (error) {
173049
+ this.fail(error instanceof Error ? error : new Error(String(error)));
173050
+ }
173051
+ return;
173052
+ }
173053
+ this.input.write(line);
173054
+ }
173009
173055
  parseLine(line) {
173010
173056
  const trimmed = line.endsWith("\n") ? line.slice(0, -1).replace(/\r$/, "") : line;
173011
173057
  if (!trimmed.trim()) return null;
@@ -173044,7 +173090,8 @@ var init_stdio_startup_gate = __esm({
173044
173090
  if (message.method !== MCP_SERVER_DISCOVER_METHOD) return false;
173045
173091
  if (!Object.prototype.hasOwnProperty.call(message, "id")) return false;
173046
173092
  const params = message.params;
173047
- return params === void 0 || typeof params === "object" && params !== null && !Array.isArray(params);
173093
+ if (params === void 0) return true;
173094
+ return typeof params === "object" && params !== null && !Array.isArray(params) && !Object.prototype.hasOwnProperty.call(params, "_meta");
173048
173095
  }
173049
173096
  isValidRequestId(id) {
173050
173097
  return id === null || typeof id === "string" || typeof id === "number" && Number.isFinite(id);
@@ -173123,6 +173170,81 @@ var init_mcp_root_path = __esm({
173123
173170
  }
173124
173171
  });
173125
173172
 
173173
+ // src/server/modern-mcp-bridge.ts
173174
+ var modern_mcp_bridge_exports = {};
173175
+ __export(modern_mcp_bridge_exports, {
173176
+ createModernMcpBridge: () => createModernMcpBridge
173177
+ });
173178
+ import {
173179
+ fromJsonSchema,
173180
+ McpServer as ModernMcpServer
173181
+ } from "@modelcontextprotocol/server";
173182
+ import { Client as LegacyClient } from "@modelcontextprotocol/sdk/client/index.js";
173183
+ import { InMemoryTransport as LegacyInMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
173184
+ async function createModernMcpBridge(options) {
173185
+ const { createMemorixServer: createMemorixServer2 } = await Promise.resolve().then(() => (init_server2(), server_exports2));
173186
+ const legacy = await createMemorixServer2(
173187
+ options.projectRoot,
173188
+ void 0,
173189
+ void 0,
173190
+ {
173191
+ ...options,
173192
+ allowUntrackedFallback: options.allowUntrackedFallback ?? false,
173193
+ deferProjectInitUntilBound: options.deferProjectInitUntilBound ?? true,
173194
+ deferProjectRuntimeInit: options.deferProjectRuntimeInit ?? true
173195
+ }
173196
+ );
173197
+ const [clientTransport, serverTransport] = LegacyInMemoryTransport.createLinkedPair();
173198
+ const legacyClient = new LegacyClient({
173199
+ name: "memorix-modern-bridge",
173200
+ version: getMcpServerInfo().version
173201
+ });
173202
+ await legacy.server.connect(serverTransport);
173203
+ await legacyClient.connect(clientTransport);
173204
+ const listed = await legacyClient.listTools();
173205
+ const modern = new ModernMcpServer(getMcpServerInfo());
173206
+ for (const tool of listed.tools) {
173207
+ modern.registerTool(
173208
+ tool.name,
173209
+ {
173210
+ ...tool.title ? { title: tool.title } : {},
173211
+ ...tool.description ? { description: tool.description } : {},
173212
+ inputSchema: fromJsonSchema(tool.inputSchema)
173213
+ },
173214
+ async (args) => await legacyClient.callTool({
173215
+ name: tool.name,
173216
+ arguments: args
173217
+ })
173218
+ );
173219
+ }
173220
+ const bridge = modern;
173221
+ bridge.memorix = {
173222
+ projectId: legacy.projectId,
173223
+ deferredInit: legacy.deferredInit,
173224
+ switchProject: legacy.switchProject,
173225
+ isExplicitlyBound: legacy.isExplicitlyBound,
173226
+ handleTransportClose: legacy.handleTransportClose
173227
+ };
173228
+ let closed = false;
173229
+ const modernClose = modern.close.bind(modern);
173230
+ modern.close = async () => {
173231
+ if (closed) return;
173232
+ closed = true;
173233
+ await modernClose();
173234
+ await legacyClient.close().catch(() => void 0);
173235
+ await legacy.server.close().catch(() => void 0);
173236
+ legacy.handleTransportClose();
173237
+ };
173238
+ return bridge;
173239
+ }
173240
+ var init_modern_mcp_bridge = __esm({
173241
+ "src/server/modern-mcp-bridge.ts"() {
173242
+ "use strict";
173243
+ init_esm_shims();
173244
+ init_mcp_discovery();
173245
+ }
173246
+ });
173247
+
173126
173248
  // src/cli/commands/serve-shared.ts
173127
173249
  var serve_shared_exports = {};
173128
173250
  __export(serve_shared_exports, {
@@ -173231,7 +173353,7 @@ var init_serve_shared = __esm({
173231
173353
 
173232
173354
  // src/cli/version.ts
173233
173355
  function getCliVersion() {
173234
- return true ? "1.8.4" : pkg.version;
173356
+ return true ? "1.8.5" : pkg.version;
173235
173357
  }
173236
173358
  var init_version3 = __esm({
173237
173359
  "src/cli/version.ts"() {
@@ -173487,6 +173609,14 @@ var init_serve = __esm({
173487
173609
  }
173488
173610
  },
173489
173611
  run: async ({ args }) => {
173612
+ const { serveStdio, StdioServerTransport } = await import("@modelcontextprotocol/server/stdio");
173613
+ const { createModernMcpBridge: createModernMcpBridge2 } = await Promise.resolve().then(() => (init_modern_mcp_bridge(), modern_mcp_bridge_exports));
173614
+ const { detectProject: detectProject2, findGitInSubdirs: findGitInSubdirs2, isSystemDirectory: isSystemDirectory2 } = await Promise.resolve().then(() => (init_detector(), detector_exports));
173615
+ const { homedir: homedir27 } = await import("os");
173616
+ const { writeLastProjectRoot: writeLastProjectRoot2 } = await Promise.resolve().then(() => (init_launch_root(), launch_root_exports));
173617
+ const { resolveServeProject: resolveServeProject2 } = await Promise.resolve().then(() => (init_serve_shared(), serve_shared_exports));
173618
+ let stdioHandle;
173619
+ let stdinEndedBeforeHandle = false;
173490
173620
  const startupGate = new StdioStartupGate({
173491
173621
  stdin: process.stdin,
173492
173622
  stdout: process.stdout,
@@ -173496,16 +173626,17 @@ var init_serve = __esm({
173496
173626
  process.exit(1);
173497
173627
  },
173498
173628
  onEnd: () => {
173499
- console.error("[memorix] stdin closed \u2014 exiting");
173500
- process.exitCode = 0;
173629
+ console.error("[memorix] stdin closed - exiting");
173630
+ if (stdioHandle) {
173631
+ void stdioHandle.close().catch((error) => {
173632
+ console.error(`[memorix] stdio close error: ${error instanceof Error ? error.message : String(error)}`);
173633
+ });
173634
+ } else {
173635
+ stdinEndedBeforeHandle = true;
173636
+ }
173501
173637
  }
173502
173638
  });
173503
173639
  startupGate.start();
173504
- const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
173505
- const { createMemorixServer: createMemorixServer2 } = await Promise.resolve().then(() => (init_server2(), server_exports2));
173506
- const { detectProject: detectProject2, findGitInSubdirs: findGitInSubdirs2, isSystemDirectory: isSystemDirectory2 } = await Promise.resolve().then(() => (init_detector(), detector_exports));
173507
- const { homedir: homedir27 } = await import("os");
173508
- const { resolveServeProject: resolveServeProject2 } = await Promise.resolve().then(() => (init_serve_shared(), serve_shared_exports));
173509
173640
  let safeCwd;
173510
173641
  try {
173511
173642
  safeCwd = process.cwd();
@@ -173522,70 +173653,82 @@ var init_serve = __esm({
173522
173653
  },
173523
173654
  { detectProject: detectProject2, findGitInSubdirs: findGitInSubdirs2, isSystemDirectory: isSystemDirectory2 }
173524
173655
  );
173525
- for (const message of resolution.messages) {
173526
- console.error(message);
173527
- }
173656
+ for (const message of resolution.messages) console.error(message);
173528
173657
  if (!resolution.detectedProject) {
173529
173658
  console.error(`[memorix] [WARN] ${resolution.error}`);
173530
- console.error(`[memorix] Starting in deferred-binding mode \u2014 project will bind via MCP roots or memorix_session_start.`);
173531
- console.error(`[memorix] For non-git directories, use --allow-untracked to enable untracked/ fallback.`);
173659
+ console.error("[memorix] Starting in deferred-binding mode - bind with memorix_session_start(projectRoot=...) when needed.");
173660
+ console.error("[memorix] For non-git directories, use --allow-untracked to enable untracked/ fallback.");
173532
173661
  }
173533
173662
  const detected = resolution.detectedProject;
173534
173663
  const projectRoot = resolution.projectRoot;
173535
- if (detected) {
173536
- const { writeLastProjectRoot: writeLastProjectRoot2 } = await Promise.resolve().then(() => (init_launch_root(), launch_root_exports));
173537
- writeLastProjectRoot2(detected.rootPath);
173538
- }
173664
+ if (detected) writeLastProjectRoot2(detected.rootPath);
173539
173665
  const allowUntracked = args["allow-untracked"] ?? false;
173540
- const toolProfile = resolveToolProfile({ explicit: args.mode, envValue: process.env.MEMORIX_MODE, fallback: "micro" });
173541
- const serverOptions = detected ? { toolProfile, deferProjectRuntimeInit: true } : { allowUntrackedFallback: allowUntracked, deferProjectInitUntilBound: !allowUntracked, deferProjectRuntimeInit: true, toolProfile };
173542
- const { server, projectId, deferredInit, switchProject } = await createMemorixServer2(projectRoot, void 0, void 0, serverOptions);
173666
+ const toolProfile = resolveToolProfile({
173667
+ explicit: args.mode,
173668
+ envValue: process.env.MEMORIX_MODE,
173669
+ fallback: "micro"
173670
+ });
173543
173671
  const transport = new StdioServerTransport(startupGate.input, process.stdout);
173544
- await server.connect(transport);
173545
- startupGate.markReady();
173546
- console.error(`[memorix] MCP Server running on stdio (project: ${projectId})`);
173547
- console.error(`[memorix] Project root: ${detected?.rootPath ?? projectRoot}`);
173548
- const tryRootsSwitch = async () => {
173549
- try {
173550
- const { roots } = await server.server.listRoots();
173551
- if (!roots || roots.length === 0) return;
173552
- for (const root of roots) {
173553
- if (!root.uri.startsWith("file://")) continue;
173554
- const rootPath = mcpFileUriToPath(root.uri);
173555
- if (!rootPath) continue;
173556
- const rootDetected = detectProject2(rootPath);
173557
- if (rootDetected) {
173558
- const switched = await switchProject(rootPath);
173672
+ const createBridge = async () => {
173673
+ const bridge = await createModernMcpBridge2({
173674
+ projectRoot,
173675
+ allowUntrackedFallback: allowUntracked,
173676
+ deferProjectInitUntilBound: !allowUntracked,
173677
+ deferProjectRuntimeInit: true,
173678
+ toolProfile
173679
+ });
173680
+ const tryRootsSwitch = async () => {
173681
+ try {
173682
+ if (bridge.memorix.isExplicitlyBound()) return;
173683
+ const { roots } = await bridge.server.listRoots();
173684
+ for (const root of roots ?? []) {
173685
+ if (!root.uri.startsWith("file://")) continue;
173686
+ const rootPath = mcpFileUriToPath(root.uri);
173687
+ if (!rootPath) continue;
173688
+ const switched = await bridge.memorix.switchProject(rootPath, "mcp-roots");
173559
173689
  if (switched) {
173560
- console.error(`[memorix] [UPDATED] Project updated via MCP roots: ${rootDetected.id}`);
173690
+ console.error(`[memorix] [UPDATED] Project updated via MCP roots: ${rootPath}`);
173691
+ return;
173561
173692
  }
173562
- return;
173563
- }
173564
- const subGit = findGitInSubdirs2(rootPath);
173565
- if (subGit) {
173566
- const switched = await switchProject(subGit);
173567
- if (switched) {
173693
+ const subGit = findGitInSubdirs2(rootPath);
173694
+ if (subGit && await bridge.memorix.switchProject(subGit, "mcp-roots")) {
173568
173695
  console.error(`[memorix] [UPDATED] Project updated via MCP roots (subdir): ${subGit}`);
173696
+ return;
173569
173697
  }
173570
- return;
173571
173698
  }
173699
+ } catch (error) {
173700
+ console.error(`[memorix] MCP roots not available (${error instanceof Error ? error.message : "unsupported"})`);
173572
173701
  }
173573
- } catch (err) {
173574
- console.error(`[memorix] MCP roots not available (${err.message ?? "unsupported"})`);
173575
- }
173576
- };
173577
- try {
173578
- const { RootsListChangedNotificationSchema } = await import("@modelcontextprotocol/sdk/types.js");
173579
- server.server.setNotificationHandler(RootsListChangedNotificationSchema, async () => {
173580
- console.error(`[memorix] Roots changed \u2014 re-detecting project...`);
173702
+ };
173703
+ bridge.server.setNotificationHandler("notifications/roots/list_changed", async () => {
173581
173704
  await tryRootsSwitch();
173582
173705
  });
173583
- } catch {
173706
+ const deferredInitTimer = setTimeout(() => {
173707
+ bridge.memorix.deferredInit().catch((error) => {
173708
+ console.error(`[memorix] Deferred init error: ${error instanceof Error ? error.message : String(error)}`);
173709
+ });
173710
+ }, 5e3);
173711
+ deferredInitTimer.unref?.();
173712
+ const originalClose = bridge.close.bind(bridge);
173713
+ bridge.close = async () => {
173714
+ clearTimeout(deferredInitTimer);
173715
+ await originalClose();
173716
+ };
173717
+ return bridge;
173718
+ };
173719
+ stdioHandle = serveStdio(createBridge, {
173720
+ transport,
173721
+ legacy: "serve",
173722
+ onerror: (error) => console.error(`[memorix] stdio MCP error: ${error.message}`)
173723
+ });
173724
+ startupGate.markReady();
173725
+ if (stdinEndedBeforeHandle) {
173726
+ void stdioHandle.close().catch((error) => {
173727
+ console.error(`[memorix] stdio close error: ${error instanceof Error ? error.message : String(error)}`);
173728
+ });
173584
173729
  }
173585
- const deferredInitTimer = setTimeout(() => {
173586
- deferredInit().catch((e2) => console.error(`[memorix] Deferred init error:`, e2));
173587
- }, 5e3);
173588
- deferredInitTimer.unref?.();
173730
+ console.error(`[memorix] MCP Server running on stdio (profile: ${toolProfile}, project: ${detected?.id ?? "deferred"})`);
173731
+ console.error(`[memorix] Project root: ${detected?.rootPath ?? projectRoot}`);
173589
173732
  Promise.resolve().then(() => (init_update_checker(), update_checker_exports)).then((m2) => m2.checkForUpdates()).catch(() => {
173590
173733
  });
173591
173734
  }