memorix 1.8.3 → 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 (74) hide show
  1. package/CHANGELOG.md +53 -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 +1544 -635
  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 +214 -73
  11. package/dist/memcode/index.js +28035 -169
  12. package/dist/memcode-runtime/CHANGELOG.md +53 -0
  13. package/dist/sdk.js +30 -14
  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 +74 -86
  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/mcp-discovery.ts +0 -1
  69. package/src/server/modern-mcp-bridge.ts +108 -0
  70. package/src/server/stdio-startup-gate.ts +41 -2
  71. package/src/server/tool-profile.ts +7 -6
  72. package/src/server.ts +1 -1
  73. package/src/store/orama-store.ts +2 -2
  74. 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,14 +158129,13 @@ var init_request_context = __esm({
158121
158129
  function getMcpServerInfo() {
158122
158130
  return {
158123
158131
  name: "memorix",
158124
- version: true ? "1.8.3" : "1.0.1"
158132
+ version: true ? "1.8.5" : "1.0.1"
158125
158133
  };
158126
158134
  }
158127
158135
  function createMcpDiscoverResult(capabilities, serverInfo) {
158128
158136
  return {
158129
158137
  resultType: "complete",
158130
158138
  supportedVersions: [
158131
- MCP_MODERN_PROTOCOL_VERSION,
158132
158139
  MCP_LEGACY_PROTOCOL_VERSION,
158133
158140
  MCP_OLDEST_LEGACY_PROTOCOL_VERSION
158134
158141
  ],
@@ -158145,12 +158152,11 @@ function createMcpDiscoverResult(capabilities, serverInfo) {
158145
158152
  function createMcpStartupDiscoverResult(serverInfo) {
158146
158153
  return createMcpDiscoverResult({ tools: { listChanged: true } }, serverInfo);
158147
158154
  }
158148
- var MCP_MODERN_PROTOCOL_VERSION, MCP_LEGACY_PROTOCOL_VERSION, MCP_OLDEST_LEGACY_PROTOCOL_VERSION, MCP_SERVER_DISCOVER_METHOD, MCP_SERVER_INFO_META_KEY;
158155
+ var MCP_LEGACY_PROTOCOL_VERSION, MCP_OLDEST_LEGACY_PROTOCOL_VERSION, MCP_SERVER_DISCOVER_METHOD, MCP_SERVER_INFO_META_KEY;
158149
158156
  var init_mcp_discovery = __esm({
158150
158157
  "src/server/mcp-discovery.ts"() {
158151
158158
  "use strict";
158152
158159
  init_esm_shims();
158153
- MCP_MODERN_PROTOCOL_VERSION = "2026-07-28";
158154
158160
  MCP_LEGACY_PROTOCOL_VERSION = "2025-11-25";
158155
158161
  MCP_OLDEST_LEGACY_PROTOCOL_VERSION = "2024-11-05";
158156
158162
  MCP_SERVER_DISCOVER_METHOD = "server/discover";
@@ -166532,6 +166538,9 @@ var init_official_skills = __esm({
166532
166538
  '| Specific past decision, bug, file, or change | `memorix_search` | `memorix memory search --query "<topic>"` |',
166533
166539
  "| Need the full source for a search hit | `memorix_detail` | `memorix memory detail --id <id>` |",
166534
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` |",
166535
166544
  '| Learned reusable project knowledge | `memorix_store` | `memorix memory store --type <type> --entity <name> --title "<title>" "<text>"` |',
166536
166545
  "| Task or bug is complete/outdated | `memorix_resolve` | `memorix memory resolve --ids <ids>` |",
166537
166546
  "",
@@ -166662,6 +166671,8 @@ var init_official_skills = __esm({
166662
166671
  "",
166663
166672
  "Promote memories into mini-skills only when they are reusable instructions, not just historical notes.",
166664
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
+ "",
166665
166676
  "## Tool Router",
166666
166677
  "",
166667
166678
  "| Situation | Prefer | CLI fallback |",
@@ -166697,15 +166708,17 @@ var init_official_skills = __esm({
166697
166708
  "| Situation | Prefer | CLI fallback |",
166698
166709
  "|---|---|---|",
166699
166710
  '| Run managed subagent execution | CLI | `memorix orchestrate --goal "<goal>" --agents claude:1,codex:1` |',
166700
- "| Register coordination identity | `team_manage` action `join` | `memorix team join --agentType <agent>` |",
166701
- "| Create or inspect tasks | `team_task` | `memorix task create|list|claim|complete` |",
166702
- "| Send or read coordination messages | `team_message` | `memorix message send|broadcast|inbox` |",
166703
- "| Share structured handoff | `memorix_handoff` | `memorix handoff send` |",
166704
- "| Avoid file conflicts | `team_file_lock` | `memorix lock lock|unlock|status` |",
166705
- "| 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` |",
166706
166717
  "",
166707
166718
  "## Boundaries",
166708
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
+ "",
166709
166722
  "- For ordinary memory, do not join coordination state.",
166710
166723
  "- For production multi-agent execution, prefer `memorix orchestrate` so the main process owns planning, dispatch, retries, and verification gates.",
166711
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.",
@@ -167869,7 +167882,10 @@ alwaysApply: true
167869
167882
  "| `memorix_store` | Save something worth persisting |",
167870
167883
  '| `memorix_store_reasoning` | Save the "why" behind a decision |',
167871
167884
  "| `memorix_resolve` | Mark completed/outdated memories |",
167872
- "| `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 |"
167873
167889
  ].join("\n");
167874
167890
  }
167875
167891
  async function uninstallHooks(agent, projectRoot, global2 = false) {
@@ -172909,7 +172925,17 @@ var init_stdio_startup_gate = __esm({
172909
172925
  this.fail(new Error(`stdio input chunk exceeded ${this.maxBufferSize} bytes`));
172910
172926
  return;
172911
172927
  }
172912
- 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
+ }
172913
172939
  return;
172914
172940
  }
172915
172941
  const text2 = typeof chunk === "string" ? chunk : chunk.toString("utf8");
@@ -173008,6 +173034,24 @@ var init_stdio_startup_gate = __esm({
173008
173034
  this.queuedMessages.push(line);
173009
173035
  this.queuedBytes += bytes;
173010
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
+ }
173011
173055
  parseLine(line) {
173012
173056
  const trimmed = line.endsWith("\n") ? line.slice(0, -1).replace(/\r$/, "") : line;
173013
173057
  if (!trimmed.trim()) return null;
@@ -173046,7 +173090,8 @@ var init_stdio_startup_gate = __esm({
173046
173090
  if (message.method !== MCP_SERVER_DISCOVER_METHOD) return false;
173047
173091
  if (!Object.prototype.hasOwnProperty.call(message, "id")) return false;
173048
173092
  const params = message.params;
173049
- 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");
173050
173095
  }
173051
173096
  isValidRequestId(id) {
173052
173097
  return id === null || typeof id === "string" || typeof id === "number" && Number.isFinite(id);
@@ -173125,6 +173170,81 @@ var init_mcp_root_path = __esm({
173125
173170
  }
173126
173171
  });
173127
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
+
173128
173248
  // src/cli/commands/serve-shared.ts
173129
173249
  var serve_shared_exports = {};
173130
173250
  __export(serve_shared_exports, {
@@ -173233,7 +173353,7 @@ var init_serve_shared = __esm({
173233
173353
 
173234
173354
  // src/cli/version.ts
173235
173355
  function getCliVersion() {
173236
- return true ? "1.8.3" : pkg.version;
173356
+ return true ? "1.8.5" : pkg.version;
173237
173357
  }
173238
173358
  var init_version3 = __esm({
173239
173359
  "src/cli/version.ts"() {
@@ -173489,6 +173609,14 @@ var init_serve = __esm({
173489
173609
  }
173490
173610
  },
173491
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;
173492
173620
  const startupGate = new StdioStartupGate({
173493
173621
  stdin: process.stdin,
173494
173622
  stdout: process.stdout,
@@ -173498,16 +173626,17 @@ var init_serve = __esm({
173498
173626
  process.exit(1);
173499
173627
  },
173500
173628
  onEnd: () => {
173501
- console.error("[memorix] stdin closed \u2014 exiting");
173502
- 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
+ }
173503
173637
  }
173504
173638
  });
173505
173639
  startupGate.start();
173506
- const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
173507
- const { createMemorixServer: createMemorixServer2 } = await Promise.resolve().then(() => (init_server2(), server_exports2));
173508
- const { detectProject: detectProject2, findGitInSubdirs: findGitInSubdirs2, isSystemDirectory: isSystemDirectory2 } = await Promise.resolve().then(() => (init_detector(), detector_exports));
173509
- const { homedir: homedir27 } = await import("os");
173510
- const { resolveServeProject: resolveServeProject2 } = await Promise.resolve().then(() => (init_serve_shared(), serve_shared_exports));
173511
173640
  let safeCwd;
173512
173641
  try {
173513
173642
  safeCwd = process.cwd();
@@ -173524,70 +173653,82 @@ var init_serve = __esm({
173524
173653
  },
173525
173654
  { detectProject: detectProject2, findGitInSubdirs: findGitInSubdirs2, isSystemDirectory: isSystemDirectory2 }
173526
173655
  );
173527
- for (const message of resolution.messages) {
173528
- console.error(message);
173529
- }
173656
+ for (const message of resolution.messages) console.error(message);
173530
173657
  if (!resolution.detectedProject) {
173531
173658
  console.error(`[memorix] [WARN] ${resolution.error}`);
173532
- console.error(`[memorix] Starting in deferred-binding mode \u2014 project will bind via MCP roots or memorix_session_start.`);
173533
- 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.");
173534
173661
  }
173535
173662
  const detected = resolution.detectedProject;
173536
173663
  const projectRoot = resolution.projectRoot;
173537
- if (detected) {
173538
- const { writeLastProjectRoot: writeLastProjectRoot2 } = await Promise.resolve().then(() => (init_launch_root(), launch_root_exports));
173539
- writeLastProjectRoot2(detected.rootPath);
173540
- }
173664
+ if (detected) writeLastProjectRoot2(detected.rootPath);
173541
173665
  const allowUntracked = args["allow-untracked"] ?? false;
173542
- const toolProfile = resolveToolProfile({ explicit: args.mode, envValue: process.env.MEMORIX_MODE, fallback: "micro" });
173543
- const serverOptions = detected ? { toolProfile, deferProjectRuntimeInit: true } : { allowUntrackedFallback: allowUntracked, deferProjectInitUntilBound: !allowUntracked, deferProjectRuntimeInit: true, toolProfile };
173544
- 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
+ });
173545
173671
  const transport = new StdioServerTransport(startupGate.input, process.stdout);
173546
- await server.connect(transport);
173547
- startupGate.markReady();
173548
- console.error(`[memorix] MCP Server running on stdio (project: ${projectId})`);
173549
- console.error(`[memorix] Project root: ${detected?.rootPath ?? projectRoot}`);
173550
- const tryRootsSwitch = async () => {
173551
- try {
173552
- const { roots } = await server.server.listRoots();
173553
- if (!roots || roots.length === 0) return;
173554
- for (const root of roots) {
173555
- if (!root.uri.startsWith("file://")) continue;
173556
- const rootPath = mcpFileUriToPath(root.uri);
173557
- if (!rootPath) continue;
173558
- const rootDetected = detectProject2(rootPath);
173559
- if (rootDetected) {
173560
- 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");
173561
173689
  if (switched) {
173562
- console.error(`[memorix] [UPDATED] Project updated via MCP roots: ${rootDetected.id}`);
173690
+ console.error(`[memorix] [UPDATED] Project updated via MCP roots: ${rootPath}`);
173691
+ return;
173563
173692
  }
173564
- return;
173565
- }
173566
- const subGit = findGitInSubdirs2(rootPath);
173567
- if (subGit) {
173568
- const switched = await switchProject(subGit);
173569
- if (switched) {
173693
+ const subGit = findGitInSubdirs2(rootPath);
173694
+ if (subGit && await bridge.memorix.switchProject(subGit, "mcp-roots")) {
173570
173695
  console.error(`[memorix] [UPDATED] Project updated via MCP roots (subdir): ${subGit}`);
173696
+ return;
173571
173697
  }
173572
- return;
173573
173698
  }
173699
+ } catch (error) {
173700
+ console.error(`[memorix] MCP roots not available (${error instanceof Error ? error.message : "unsupported"})`);
173574
173701
  }
173575
- } catch (err) {
173576
- console.error(`[memorix] MCP roots not available (${err.message ?? "unsupported"})`);
173577
- }
173578
- };
173579
- try {
173580
- const { RootsListChangedNotificationSchema } = await import("@modelcontextprotocol/sdk/types.js");
173581
- server.server.setNotificationHandler(RootsListChangedNotificationSchema, async () => {
173582
- console.error(`[memorix] Roots changed \u2014 re-detecting project...`);
173702
+ };
173703
+ bridge.server.setNotificationHandler("notifications/roots/list_changed", async () => {
173583
173704
  await tryRootsSwitch();
173584
173705
  });
173585
- } 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
+ });
173586
173729
  }
173587
- const deferredInitTimer = setTimeout(() => {
173588
- deferredInit().catch((e2) => console.error(`[memorix] Deferred init error:`, e2));
173589
- }, 5e3);
173590
- 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}`);
173591
173732
  Promise.resolve().then(() => (init_update_checker(), update_checker_exports)).then((m2) => m2.checkForUpdates()).catch(() => {
173592
173733
  });
173593
173734
  }