memorix 1.8.4 → 1.8.6

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 (88) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/CLAUDE.md +3 -0
  3. package/README.md +8 -6
  4. package/README.zh-CN.md +5 -3
  5. package/assets/star-history-dark.svg +5 -5
  6. package/assets/star-history-light.svg +5 -5
  7. package/assets/star-history.json +35 -5
  8. package/dist/cli/index.js +1848 -754
  9. package/dist/dashboard/static/app.js +29 -885
  10. package/dist/dashboard/static/index.html +1 -5
  11. package/dist/dashboard/static/style.css +36 -503
  12. package/dist/index.d.ts +4 -4
  13. package/dist/index.js +286 -79
  14. package/dist/memcode/index.js +28035 -169
  15. package/dist/memcode-runtime/CHANGELOG.md +52 -0
  16. package/dist/sdk.js +103 -21
  17. package/dist/types.d.ts +1 -1
  18. package/docs/1.8.0-RELEASE-CANDIDATE-SPEC.md +22 -16
  19. package/docs/AGENT_OPERATOR_PLAYBOOK.md +2 -2
  20. package/docs/API_REFERENCE.md +10 -8
  21. package/docs/DASHBOARD.md +23 -0
  22. package/docs/DEVELOPMENT.md +2 -2
  23. package/docs/DOCKER.md +6 -3
  24. package/docs/INTEGRATIONS.md +2 -1
  25. package/docs/MODULES.md +46 -20
  26. package/docs/PERFORMANCE.md +1 -1
  27. package/docs/README.md +8 -7
  28. package/docs/SETUP.md +4 -3
  29. package/package.json +11 -11
  30. package/plugins/antigravity/memorix/plugin.json +1 -1
  31. package/plugins/antigravity/memorix/rules/memorix.md +5 -0
  32. package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
  33. package/plugins/claude/memorix/skills/memorix-memory/SKILL.md +3 -0
  34. package/plugins/claude/memorix/skills/memorix-mini-skills/SKILL.md +2 -0
  35. package/plugins/claude/memorix/skills/memorix-orchestrate/SKILL.md +2 -0
  36. package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
  37. package/plugins/codebuddy/memorix/skills/memorix-memory/SKILL.md +3 -0
  38. package/plugins/codebuddy/memorix/skills/memorix-mini-skills/SKILL.md +2 -0
  39. package/plugins/codebuddy/memorix/skills/memorix-orchestrate/SKILL.md +2 -0
  40. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  41. package/plugins/codex/memorix/skills/memorix-memory/SKILL.md +3 -0
  42. package/plugins/codex/memorix/skills/memorix-mini-skills/SKILL.md +2 -0
  43. package/plugins/codex/memorix/skills/memorix-orchestrate/SKILL.md +2 -0
  44. package/plugins/copilot/memorix/plugin.json +1 -1
  45. package/plugins/copilot/memorix/skills/memorix-memory/SKILL.md +3 -0
  46. package/plugins/copilot/memorix/skills/memorix-mini-skills/SKILL.md +2 -0
  47. package/plugins/copilot/memorix/skills/memorix-orchestrate/SKILL.md +2 -0
  48. package/plugins/cursor/memorix/skills/memorix-memory/SKILL.md +3 -0
  49. package/plugins/cursor/memorix/skills/memorix-mini-skills/SKILL.md +2 -0
  50. package/plugins/cursor/memorix/skills/memorix-orchestrate/SKILL.md +2 -0
  51. package/plugins/gemini/memorix/GEMINI.md +5 -0
  52. package/plugins/gemini/memorix/gemini-extension.json +1 -1
  53. package/plugins/hermes/memorix/plugin.yaml +7 -1
  54. package/plugins/omp/memorix/package.json +1 -1
  55. package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
  56. package/plugins/pi/memorix/package.json +1 -1
  57. package/plugins/pi/memorix/skills/memorix-memory/SKILL.md +3 -0
  58. package/plugins/pi/memorix/skills/memorix-mini-skills/SKILL.md +2 -0
  59. package/plugins/pi/memorix/skills/memorix-orchestrate/SKILL.md +2 -0
  60. package/server.json +2 -2
  61. package/src/cli/command-guide.ts +52 -1
  62. package/src/cli/commands/agent-integrations.ts +1 -0
  63. package/src/cli/commands/background.ts +166 -6
  64. package/src/cli/commands/hooks-install.ts +9 -2
  65. package/src/cli/commands/hooks-preview.ts +5 -0
  66. package/src/cli/commands/integrate.ts +2 -0
  67. package/src/cli/commands/serve-http.ts +73 -80
  68. package/src/cli/commands/serve.ts +95 -93
  69. package/src/cli/commands/setup.ts +11 -1
  70. package/src/cli/commands/uninstall.ts +24 -2
  71. package/src/cli/index.ts +1 -1
  72. package/src/codegraph/task-lens.ts +72 -7
  73. package/src/dashboard/static/index.html +1 -5
  74. package/src/dashboard/static/style.css +36 -503
  75. package/src/hooks/installers/index.ts +58 -0
  76. package/src/hooks/official-skills.ts +13 -6
  77. package/src/hooks/types.ts +2 -0
  78. package/src/integrations/registry.ts +9 -0
  79. package/src/memory/graph.ts +2 -2
  80. package/src/server/mcp-diagnostics.ts +9 -7
  81. package/src/server/modern-mcp-bridge.ts +108 -0
  82. package/src/server/stdio-startup-gate.ts +41 -2
  83. package/src/server/tool-profile.ts +7 -6
  84. package/src/server.ts +1 -1
  85. package/src/store/orama-store.ts +2 -2
  86. package/src/types.ts +1 -1
  87. package/src/wiki/types.ts +2 -2
  88. package/src/workspace/mcp-adapters/workbuddy.ts +71 -0
package/dist/cli/index.js CHANGED
@@ -3232,7 +3232,7 @@ ${import_picocolors.default.gray(m3)} ${s4}
3232
3232
 
3233
3233
  // src/cli/version.ts
3234
3234
  function getCliVersion() {
3235
- return true ? "1.8.4" : pkg.version;
3235
+ return true ? "1.8.6" : pkg.version;
3236
3236
  }
3237
3237
  var init_version = __esm({
3238
3238
  "src/cli/version.ts"() {
@@ -38645,8 +38645,8 @@ var init_uploads = __esm({
38645
38645
  init_shims();
38646
38646
  checkFileSupport = () => {
38647
38647
  if (typeof File === "undefined") {
38648
- const { process: process3 } = globalThis;
38649
- const isOldNode = typeof process3?.versions?.node === "string" && parseInt(process3.versions.node.split(".")) < 20;
38648
+ const { process: process2 } = globalThis;
38649
+ const isOldNode = typeof process2?.versions?.node === "string" && parseInt(process2.versions.node.split(".")) < 20;
38650
38650
  throw new Error("`File` is not defined as a global, which is required for file uploads." + (isOldNode ? " Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`." : ""));
38651
38651
  }
38652
38652
  };
@@ -65035,8 +65035,8 @@ var init_uploads4 = __esm({
65035
65035
  init_shims2();
65036
65036
  checkFileSupport2 = () => {
65037
65037
  if (typeof File === "undefined") {
65038
- const { process: process3 } = globalThis;
65039
- const isOldNode = typeof process3?.versions?.node === "string" && parseInt(process3.versions.node.split(".")) < 20;
65038
+ const { process: process2 } = globalThis;
65039
+ const isOldNode = typeof process2?.versions?.node === "string" && parseInt(process2.versions.node.split(".")) < 20;
65040
65040
  throw new Error("`File` is not defined as a global, which is required for file uploads." + (isOldNode ? " Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`." : ""));
65041
65041
  }
65042
65042
  };
@@ -79311,15 +79311,15 @@ var require_streams = __commonJS({
79311
79311
  var POOL_SIZE2 = 65536;
79312
79312
  if (!globalThis.ReadableStream) {
79313
79313
  try {
79314
- const process3 = __require("process");
79315
- const { emitWarning } = process3;
79314
+ const process2 = __require("process");
79315
+ const { emitWarning } = process2;
79316
79316
  try {
79317
- process3.emitWarning = () => {
79317
+ process2.emitWarning = () => {
79318
79318
  };
79319
79319
  Object.assign(globalThis, __require("stream/web"));
79320
- process3.emitWarning = emitWarning;
79320
+ process2.emitWarning = emitWarning;
79321
79321
  } catch (error40) {
79322
- process3.emitWarning = emitWarning;
79322
+ process2.emitWarning = emitWarning;
79323
79323
  throw error40;
79324
79324
  }
79325
79325
  } catch (error40) {
@@ -83960,7 +83960,7 @@ var require_logging_utils = __commonJS({
83960
83960
  exports.setBackend = setBackend;
83961
83961
  exports.log = log;
83962
83962
  var events_1 = __require("events");
83963
- var process3 = __importStar(__require("process"));
83963
+ var process2 = __importStar(__require("process"));
83964
83964
  var util2 = __importStar(__require("util"));
83965
83965
  var colours_1 = require_colours();
83966
83966
  var LogSeverity;
@@ -84017,7 +84017,7 @@ var require_logging_utils = __commonJS({
84017
84017
  this.cached = /* @__PURE__ */ new Map();
84018
84018
  this.filters = [];
84019
84019
  this.filtersSet = false;
84020
- let nodeFlag = (_a6 = process3.env[exports.env.nodeEnables]) !== null && _a6 !== void 0 ? _a6 : "*";
84020
+ let nodeFlag = (_a6 = process2.env[exports.env.nodeEnables]) !== null && _a6 !== void 0 ? _a6 : "*";
84021
84021
  if (nodeFlag === "all") {
84022
84022
  nodeFlag = "*";
84023
84023
  }
@@ -84057,7 +84057,7 @@ var require_logging_utils = __commonJS({
84057
84057
  return (fields, ...args) => {
84058
84058
  var _a6;
84059
84059
  const nscolour = `${colours_1.Colours.green}${namespace}${colours_1.Colours.reset}`;
84060
- const pid = `${colours_1.Colours.yellow}${process3.pid}${colours_1.Colours.reset}`;
84060
+ const pid = `${colours_1.Colours.yellow}${process2.pid}${colours_1.Colours.reset}`;
84061
84061
  let level;
84062
84062
  switch (fields.severity) {
84063
84063
  case LogSeverity.ERROR:
@@ -84105,8 +84105,8 @@ var require_logging_utils = __commonJS({
84105
84105
  }
84106
84106
  setFilters() {
84107
84107
  var _a6;
84108
- const existingFilters = (_a6 = process3.env["NODE_DEBUG"]) !== null && _a6 !== void 0 ? _a6 : "";
84109
- process3.env["NODE_DEBUG"] = `${existingFilters}${existingFilters ? "," : ""}${this.filters.join(",")}`;
84108
+ const existingFilters = (_a6 = process2.env["NODE_DEBUG"]) !== null && _a6 !== void 0 ? _a6 : "";
84109
+ process2.env["NODE_DEBUG"] = `${existingFilters}${existingFilters ? "," : ""}${this.filters.join(",")}`;
84110
84110
  }
84111
84111
  };
84112
84112
  function getDebugBackend(debugPkg) {
@@ -84159,7 +84159,7 @@ var require_logging_utils = __commonJS({
84159
84159
  }
84160
84160
  function log(namespace, parent) {
84161
84161
  if (!cachedBackend) {
84162
- const enablesFlag = process3.env[exports.env.nodeEnables];
84162
+ const enablesFlag = process2.env[exports.env.nodeEnables];
84163
84163
  if (!enablesFlag) {
84164
84164
  return exports.placeholder;
84165
84165
  }
@@ -111728,8 +111728,8 @@ var init_node = __esm({
111728
111728
  checkFileSupport3 = () => {
111729
111729
  var _a6;
111730
111730
  if (typeof File === "undefined") {
111731
- const { process: process3 } = globalThis;
111732
- const isOldNode = typeof ((_a6 = process3 === null || process3 === void 0 ? void 0 : process3.versions) === null || _a6 === void 0 ? void 0 : _a6.node) === "string" && parseInt(process3.versions.node.split(".")) < 20;
111731
+ const { process: process2 } = globalThis;
111732
+ const isOldNode = typeof ((_a6 = process2 === null || process2 === void 0 ? void 0 : process2.versions) === null || _a6 === void 0 ? void 0 : _a6.node) === "string" && parseInt(process2.versions.node.split(".")) < 20;
111733
111733
  throw new Error("`File` is not defined as a global, which is required for file uploads." + (isOldNode ? " Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`." : ""));
111734
111734
  }
111735
111735
  };
@@ -183148,6 +183148,15 @@ __export(task_lens_exports, {
183148
183148
  scoreLensSource: () => scoreLensSource,
183149
183149
  shouldShowLensSource: () => shouldShowLensSource
183150
183150
  });
183151
+ function hasSubstantiveTask(text2, keyword) {
183152
+ const withoutKeyword = text2.replace(
183153
+ new RegExp(keyword.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "gi"),
183154
+ " "
183155
+ );
183156
+ const residual = withoutKeyword.replace(TASK_FILLER_WORDS, " ").replace(TASK_FILLER_PHRASES, " ").replace(/[\s\p{P}]/gu, "");
183157
+ if (/^(?:任务|工作|一下|一起|接着)$/u.test(residual)) return false;
183158
+ return Array.from(residual).length >= MIN_TASK_SUBSTANCE;
183159
+ }
183151
183160
  function normalizePath2(path48) {
183152
183161
  return path48.replace(/\\/g, "/");
183153
183162
  }
@@ -183207,8 +183216,12 @@ function resolveTaskLens(task) {
183207
183216
  }
183208
183217
  function isContinuationTask(task) {
183209
183218
  const normalized = (task ?? "").trim().toLowerCase();
183210
- return normalized.length > 0 && CONTINUATION_KEYWORDS.some(
183211
- (keyword) => containsTaskKeyword(normalized, keyword)
183219
+ if (normalized.length === 0) return false;
183220
+ if (EXPLICIT_HANDOFF_KEYWORDS.some((keyword) => containsTaskKeyword(normalized, keyword))) {
183221
+ return true;
183222
+ }
183223
+ return AMBIGUOUS_CONTINUATION_KEYWORDS.some(
183224
+ (keyword) => containsTaskKeyword(normalized, keyword) && hasSubstantiveTask(normalized, keyword)
183212
183225
  );
183213
183226
  }
183214
183227
  function pathKindScore(path48, lens) {
@@ -183354,7 +183367,7 @@ function shouldShowLensSource(source, lens, task) {
183354
183367
  if (lens.id === "onboarding" || lens.id === "release" || lens.id === "docs") return score >= 40;
183355
183368
  return score > 0;
183356
183369
  }
183357
- var STOP_WORDS, LENSES, KEYWORDS, CONTINUATION_KEYWORDS, LENS_PRIORITY;
183370
+ var STOP_WORDS, LENSES, KEYWORDS, EXPLICIT_HANDOFF_KEYWORDS, AMBIGUOUS_CONTINUATION_KEYWORDS, TASK_FILLER_WORDS, TASK_FILLER_PHRASES, MIN_TASK_SUBSTANCE, LENS_PRIORITY;
183358
183371
  var init_task_lens = __esm({
183359
183372
  "src/codegraph/task-lens.ts"() {
183360
183373
  "use strict";
@@ -183475,18 +183488,31 @@ var init_task_lens = __esm({
183475
183488
  docs: ["doc", "docs", "readme", "\u6587\u6863", "\u8BF4\u660E"],
183476
183489
  test: ["coverage", "fixture", "smoke", "spec", "test", "tests", "testing", "vitest", "\u6D4B\u8BD5"]
183477
183490
  };
183478
- CONTINUATION_KEYWORDS = [
183491
+ EXPLICIT_HANDOFF_KEYWORDS = [
183492
+ "handoff",
183493
+ "hand off",
183494
+ "hand over",
183495
+ "previous session",
183496
+ "last session",
183497
+ "pick up where",
183498
+ "\u4EA4\u63A5",
183499
+ // 覆盖「任务交接」「工作交接」
183500
+ "\u63A5\u624B",
183501
+ "\u4E0A\u6B21\u4F1A\u8BDD",
183502
+ "\u4E0A\u6B21\u7684\u4F1A\u8BDD"
183503
+ ];
183504
+ AMBIGUOUS_CONTINUATION_KEYWORDS = [
183479
183505
  "continue",
183480
183506
  "resume",
183481
- "pick up",
183482
183507
  "carry on",
183483
- "previous session",
183508
+ "pick up",
183484
183509
  "\u7EE7\u7EED",
183485
- "\u63A5\u624B",
183486
183510
  "\u6062\u590D",
183487
- "\u5EF6\u7EED",
183488
- "\u4E0A\u6B21\u4F1A\u8BDD"
183511
+ "\u5EF6\u7EED"
183489
183512
  ];
183513
+ TASK_FILLER_WORDS = /\b(?:please|task|work|the|a|an)\b/giu;
183514
+ TASK_FILLER_PHRASES = /(?:吧|了|呢|啊|吗|嘛|呀|哦|噢|一下|一起|接着|请|帮我)/gu;
183515
+ MIN_TASK_SUBSTANCE = 2;
183490
183516
  LENS_PRIORITY = [
183491
183517
  "bugfix",
183492
183518
  "release",
@@ -192552,9 +192578,69 @@ var init_dsh = __esm({
192552
192578
  }
192553
192579
  });
192554
192580
 
192555
- // src/workspace/mcp-adapters/codebuddy.ts
192581
+ // src/workspace/mcp-adapters/workbuddy.ts
192556
192582
  import { homedir as homedir23 } from "os";
192557
192583
  import { join as join20 } from "path";
192584
+ var WorkbuddyMCPAdapter;
192585
+ var init_workbuddy = __esm({
192586
+ "src/workspace/mcp-adapters/workbuddy.ts"() {
192587
+ "use strict";
192588
+ init_esm_shims();
192589
+ WorkbuddyMCPAdapter = class {
192590
+ source = "workbuddy";
192591
+ parse(content) {
192592
+ try {
192593
+ const config2 = JSON.parse(content);
192594
+ const servers = config2.mcpServers ?? {};
192595
+ return Object.entries(servers).map(([name, entry]) => ({
192596
+ name,
192597
+ command: entry.command ?? "",
192598
+ args: entry.args ?? [],
192599
+ ...entry.env && Object.keys(entry.env).length > 0 ? { env: entry.env } : {},
192600
+ ...entry.url ? { url: entry.url } : {},
192601
+ ...entry.headers && Object.keys(entry.headers).length > 0 ? { headers: entry.headers } : {},
192602
+ ...entry.disabled === true ? { disabled: true } : {}
192603
+ }));
192604
+ } catch {
192605
+ return [];
192606
+ }
192607
+ }
192608
+ generate(servers) {
192609
+ const mcpServers = {};
192610
+ for (const s4 of servers) {
192611
+ const entry = {};
192612
+ if (s4.url) {
192613
+ entry.url = s4.url;
192614
+ if (s4.headers && Object.keys(s4.headers).length > 0) {
192615
+ entry.headers = s4.headers;
192616
+ }
192617
+ } else {
192618
+ entry.command = s4.command;
192619
+ entry.args = s4.args;
192620
+ }
192621
+ if (s4.env && Object.keys(s4.env).length > 0) {
192622
+ entry.env = s4.env;
192623
+ }
192624
+ if (s4.disabled === true) {
192625
+ entry.disabled = true;
192626
+ }
192627
+ mcpServers[s4.name] = entry;
192628
+ }
192629
+ return JSON.stringify({ mcpServers }, null, 2) + "\n";
192630
+ }
192631
+ getConfigPath(projectRoot) {
192632
+ if (projectRoot) {
192633
+ return join20(projectRoot, ".workbuddy", "mcp.json");
192634
+ }
192635
+ return join20(homedir23(), ".workbuddy", "mcp.json");
192636
+ }
192637
+ };
192638
+ }
192639
+ });
192640
+
192641
+ // src/workspace/mcp-adapters/codebuddy.ts
192642
+ import { homedir as homedir24 } from "os";
192643
+ import { join as join21 } from "path";
192558
192644
  var CodeBuddyMCPAdapter;
192559
192645
  var init_codebuddy = __esm({
192560
192646
  "src/workspace/mcp-adapters/codebuddy.ts"() {
@@ -192586,7 +192672,7 @@ var init_codebuddy = __esm({
192586
192672
  return JSON.stringify({ mcpServers }, null, 2);
192587
192673
  }
192588
192674
  getConfigPath(projectRoot) {
192589
- return projectRoot ? join20(projectRoot, ".mcp.json") : join20(homedir23(), ".codebuddy", ".mcp.json");
192675
+ return projectRoot ? join21(projectRoot, ".mcp.json") : join21(homedir24(), ".codebuddy", ".mcp.json");
192590
192676
  }
192591
192677
  };
192592
192678
  }
@@ -192736,6 +192822,15 @@ var init_registry2 = __esm({
192736
192822
  surfaces: ["MCP", "AGENTS.md", "skills"],
192737
192823
  note: "DeepSeek Harness support writes a @deepseek-ai/dsh-mcp-client row into $DSH_HOME/cordis.patch.yml (default ~/.dsh/cordis.patch.yml), guidance into the harness AGENTS.md, and skills under $DSH_HOME/skills."
192738
192824
  },
192825
+ {
192826
+ agent: "workbuddy",
192827
+ name: "WorkBuddy",
192828
+ entry: "official-config",
192829
+ status: "ready",
192830
+ install: "memorix setup --agent workbuddy",
192831
+ surfaces: ["MCP", "AGENTS.md"],
192832
+ note: "WorkBuddy support writes a memorix MCP server row into ~/.workbuddy/mcp.json (or <project>/.workbuddy/mcp.json for project installs) and guidance into AGENTS.md."
192833
+ },
192739
192834
  {
192740
192835
  agent: "memcode",
192741
192836
  name: "memcode",
@@ -192804,6 +192899,9 @@ var init_official_skills = __esm({
192804
192899
  '| Specific past decision, bug, file, or change | `memorix_search` | `memorix memory search --query "<topic>"` |',
192805
192900
  "| Need the full source for a search hit | `memorix_detail` | `memorix memory detail --id <id>` |",
192806
192901
  "| Need the sequence around one memory | `memorix_timeline` | `memorix memory timeline --id <id>` |",
192902
+ "| Check source and freshness for a memory | `memorix_evidence` | `memorix evidence list|get|events` |",
192903
+ "| Record whether a memory helped, conflicted, or was corrected | `memorix_feedback` | `memorix feedback record|show|audit` |",
192904
+ "| Inspect or import controlled media | `memorix_media` | `memorix media import|attach|list|show|status` |",
192807
192905
  '| Learned reusable project knowledge | `memorix_store` | `memorix memory store --type <type> --entity <name> --title "<title>" "<text>"` |',
192808
192906
  "| Task or bug is complete/outdated | `memorix_resolve` | `memorix memory resolve --ids <ids>` |",
192809
192907
  "",
@@ -192934,6 +193032,8 @@ var init_official_skills = __esm({
192934
193032
  "",
192935
193033
  "Promote memories into mini-skills only when they are reusable instructions, not just historical notes.",
192936
193034
  "",
193035
+ "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.",
193036
+ "",
192937
193037
  "## Tool Router",
192938
193038
  "",
192939
193039
  "| Situation | Prefer | CLI fallback |",
@@ -192969,15 +193069,17 @@ var init_official_skills = __esm({
192969
193069
  "| Situation | Prefer | CLI fallback |",
192970
193070
  "|---|---|---|",
192971
193071
  '| Run managed subagent execution | CLI | `memorix orchestrate --goal "<goal>" --agents claude:1,codex:1` |',
192972
- "| Register coordination identity | `team_manage` action `join` | `memorix team join --agentType <agent>` |",
192973
- "| Create or inspect tasks | `team_task` | `memorix task create|list|claim|complete` |",
192974
- "| Send or read coordination messages | `team_message` | `memorix message send|broadcast|inbox` |",
192975
- "| Share structured handoff | `memorix_handoff` | `memorix handoff send` |",
192976
- "| Avoid file conflicts | `team_file_lock` | `memorix lock lock|unlock|status` |",
192977
- "| Poll joined coordination state | `memorix_poll` | `memorix poll` |",
193072
+ "| Register coordination identity when team MCP tools are available | `team_manage` action `join` | `memorix team join --agentType <agent>` |",
193073
+ "| Create or inspect tasks when team MCP tools are available | `team_task` | `memorix task create|list|claim|complete` |",
193074
+ "| Send or read coordination messages when team MCP tools are available | `team_message` | `memorix message send|broadcast|inbox` |",
193075
+ "| Share structured handoff when team MCP tools are available | `memorix_handoff` | `memorix handoff send` |",
193076
+ "| Avoid file conflicts when team MCP tools are available | `team_file_lock` | `memorix lock lock|unlock|status` |",
193077
+ "| Poll joined coordination state when team MCP tools are available | `memorix_poll` | `memorix poll` |",
192978
193078
  "",
192979
193079
  "## Boundaries",
192980
193080
  "",
193081
+ "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.",
193082
+ "",
192981
193083
  "- For ordinary memory, do not join coordination state.",
192982
193084
  "- For production multi-agent execution, prefer `memorix orchestrate` so the main process owns planning, dispatch, retries, and verification gates.",
192983
193085
  "- `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.",
@@ -193029,9 +193131,9 @@ __export(audit_exports, {
193029
193131
  });
193030
193132
  import * as fs18 from "fs/promises";
193031
193133
  import * as path29 from "path";
193032
- import { homedir as homedir24 } from "os";
193134
+ import { homedir as homedir25 } from "os";
193033
193135
  function getAuditFilePath() {
193034
- return process.env.MEMORIX_AUDIT_FILE || path29.join(homedir24(), ".memorix", "audit.json");
193136
+ return process.env.MEMORIX_AUDIT_FILE || path29.join(homedir25(), ".memorix", "audit.json");
193035
193137
  }
193036
193138
  async function loadAudit() {
193037
193139
  try {
@@ -193592,6 +193694,8 @@ function getProjectConfigPath(agent, projectRoot) {
193592
193694
  return path30.join(projectRoot, ".agents", "hooks.json");
193593
193695
  case "gemini-cli":
193594
193696
  return path30.join(projectRoot, ".gemini", "settings.json");
193697
+ case "workbuddy":
193698
+ return "";
193595
193699
  default:
193596
193700
  return path30.join(projectRoot, ".memorix", "hooks.json");
193597
193701
  }
@@ -193625,6 +193729,8 @@ function getGlobalConfigPath(agent) {
193625
193729
  return path30.join(home, ".trae", "rules", "project_rules.md");
193626
193730
  case "dsh":
193627
193731
  return path30.join(process.env.DSH_HOME?.trim() || path30.join(home, ".dsh"), "AGENTS.md");
193732
+ case "workbuddy":
193733
+ return "";
193628
193734
  default:
193629
193735
  return path30.join(home, ".memorix", "hooks.json");
193630
193736
  }
@@ -193651,6 +193757,8 @@ function getAgentRulesPath(agent, root, global2 = false) {
193651
193757
  return path30.join(root, ".trae", "rules", "project_rules.md");
193652
193758
  case "dsh":
193653
193759
  return path30.join(process.env.DSH_HOME?.trim() || path30.join(root, ".dsh"), "AGENTS.md");
193760
+ case "workbuddy":
193761
+ return "";
193654
193762
  default:
193655
193763
  return path30.join(root, ".agent", "rules", "memorix.md");
193656
193764
  }
@@ -193677,6 +193785,8 @@ function getAgentRulesPath(agent, root, global2 = false) {
193677
193785
  return path30.join(root, ".trae", "rules", "project_rules.md");
193678
193786
  case "dsh":
193679
193787
  return path30.join(root, "AGENTS.md");
193788
+ case "workbuddy":
193789
+ return path30.join(root, "AGENTS.md");
193680
193790
  default:
193681
193791
  return path30.join(root, ".agent", "rules", "memorix.md");
193682
193792
  }
@@ -193765,6 +193875,11 @@ async function detectInstalledAgents() {
193765
193875
  agents.push("dsh");
193766
193876
  } catch {
193767
193877
  }
193878
+ try {
193879
+ await fs19.access(path30.join(home, ".workbuddy"));
193880
+ agents.push("workbuddy");
193881
+ } catch {
193882
+ }
193768
193883
  return agents;
193769
193884
  }
193770
193885
  async function installHooks(agent, projectRoot, global2 = false) {
@@ -193778,6 +193893,16 @@ async function installHooks(agent, projectRoot, global2 = false) {
193778
193893
  }
193779
193894
  };
193780
193895
  }
193896
+ if (agent === "workbuddy" && global2) {
193897
+ return {
193898
+ agent,
193899
+ configPath: "",
193900
+ events: [],
193901
+ generated: {
193902
+ note: "WorkBuddy has no hook system and no user-global guidance file \u2014 MCP only; no global guidance/hooks. Run `memorix setup --agent workbuddy` (without --global) to install project MCP config and AGENTS.md guidance."
193903
+ }
193904
+ };
193905
+ }
193781
193906
  if (global2 && getGlobalConfigPath(agent) === "") {
193782
193907
  return {
193783
193908
  agent,
@@ -193860,6 +193985,17 @@ async function installHooks(agent, projectRoot, global2 = false) {
193860
193985
  }
193861
193986
  };
193862
193987
  }
193988
+ case "workbuddy": {
193989
+ const rulesPath = await installAgentRules(agent, projectRoot, global2);
193990
+ return {
193991
+ agent,
193992
+ configPath: rulesPath,
193993
+ events: [],
193994
+ generated: {
193995
+ note: "WorkBuddy has no hook system \u2014 installed AGENTS.md guidance only; the MCP row is installed by `memorix setup --agent workbuddy`."
193996
+ }
193997
+ };
193998
+ }
193863
193999
  case "opencode": {
193864
194000
  const pluginContent = generateOpenCodePlugin();
193865
194001
  const pluginPath = global2 ? getGlobalConfigPath(agent) : getProjectConfigPath(agent, projectRoot);
@@ -193989,6 +194125,7 @@ async function installHooks(agent, projectRoot, global2 = false) {
193989
194125
  };
193990
194126
  }
193991
194127
  async function installAgentRules(agent, projectRoot, global2 = false) {
194128
+ if (agent === "workbuddy" && global2) return "";
193992
194129
  const rulesContent = getAgentRulesContent(agent, global2 ? "global" : "project");
193993
194130
  const rulesRoot = global2 ? os5.homedir() : projectRoot;
193994
194131
  const rulesPath = getAgentRulesPath(agent, rulesRoot, global2);
@@ -194141,7 +194278,10 @@ alwaysApply: true
194141
194278
  "| `memorix_store` | Save something worth persisting |",
194142
194279
  '| `memorix_store_reasoning` | Save the "why" behind a decision |',
194143
194280
  "| `memorix_resolve` | Mark completed/outdated memories |",
194144
- "| `memorix_session_start` | Load session context (handoff, orchestration coordination) |"
194281
+ "| `memorix_session_start` | Load session context (handoff, orchestration coordination) |",
194282
+ "| `memorix_evidence` | Check a memory source, freshness, and verification state |",
194283
+ "| `memorix_feedback` | Record whether a memory helped, conflicted, or was corrected |",
194284
+ "| `memorix_media` | Inspect or import controlled local media |"
194145
194285
  ].join("\n");
194146
194286
  }
194147
194287
  async function uninstallHooks(agent, projectRoot, global2 = false) {
@@ -194151,6 +194291,9 @@ async function uninstallHooks(agent, projectRoot, global2 = false) {
194151
194291
  if (agent === "pi") {
194152
194292
  return false;
194153
194293
  }
194294
+ if (agent === "workbuddy") {
194295
+ return false;
194296
+ }
194154
194297
  if (global2 && getGlobalConfigPath(agent) === "") {
194155
194298
  return false;
194156
194299
  }
@@ -194334,7 +194477,7 @@ __export(setup_exports, {
194334
194477
  import { spawnSync } from "child_process";
194335
194478
  import { existsSync as existsSync15 } from "fs";
194336
194479
  import { copyFile as copyFile2, mkdir as mkdir6, readFile as readFile6, readdir as readdir3, rm as rm2, writeFile as writeFile7 } from "fs/promises";
194337
- import { homedir as homedir26 } from "os";
194480
+ import { homedir as homedir27 } from "os";
194338
194481
  import path31 from "path";
194339
194482
  import { fileURLToPath as fileURLToPath7 } from "url";
194340
194483
  function getSetupAgentTargets() {
@@ -194496,7 +194639,8 @@ function getMcpAdapter(agent) {
194496
194639
  kiro: new KiroMCPAdapter(),
194497
194640
  opencode: new OpenCodeMCPAdapter(),
194498
194641
  trae: new TraeMCPAdapter(),
194499
- dsh: new DshMCPAdapter()
194642
+ dsh: new DshMCPAdapter(),
194643
+ workbuddy: new WorkbuddyMCPAdapter()
194500
194644
  };
194501
194645
  return adapters[agent];
194502
194646
  }
@@ -194618,7 +194762,7 @@ function isOwnedLegacyCodexMcp(content) {
194618
194762
  const server = new CodexMCPAdapter().parse(content).find((entry) => entry.name === "memorix");
194619
194763
  return Boolean(server && isLegacyCodexMemorixNodeServer(server));
194620
194764
  }
194621
- async function removeLegacyCodexMemorixMcpConfig(configPath = path31.join(homedir26(), ".codex", "config.toml")) {
194765
+ async function removeLegacyCodexMemorixMcpConfig(configPath = path31.join(homedir27(), ".codex", "config.toml")) {
194622
194766
  let existingContent;
194623
194767
  try {
194624
194768
  existingContent = await readFile6(configPath, "utf-8");
@@ -194675,7 +194819,7 @@ async function removeOwnedLegacyCodexPluginFolder(homeDir) {
194675
194819
  }
194676
194820
  }
194677
194821
  async function migrateLegacyCodexIntegration(options = {}) {
194678
- const homeDir = options.homeDir ?? homedir26();
194822
+ const homeDir = options.homeDir ?? homedir27();
194679
194823
  const projectRoot = options.projectRoot ?? process.cwd();
194680
194824
  const configPath = path31.join(homeDir, ".codex", "config.toml");
194681
194825
  let mcp = "missing";
@@ -194876,7 +195020,7 @@ async function stripCodeBuddyHookCapture(pluginPath) {
194876
195020
  await writeFile7(manifestPath, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
194877
195021
  }
194878
195022
  async function installCodeBuddyPluginPackage(options = {}) {
194879
- const home = options.homeDir ?? homedir26();
195023
+ const home = options.homeDir ?? homedir27();
194880
195024
  const packageRoot = findPackageRoot();
194881
195025
  const source = path31.join(packageRoot, "plugins", "codebuddy", "memorix");
194882
195026
  if (!existsSync15(source)) throw new Error(`CodeBuddy plugin template not found: ${source}`);
@@ -194896,7 +195040,7 @@ async function installCodeBuddyPluginPackage(options = {}) {
194896
195040
  };
194897
195041
  }
194898
195042
  async function installPluginPackage(options) {
194899
- const home = options.homeDir ?? homedir26();
195043
+ const home = options.homeDir ?? homedir27();
194900
195044
  const packageRoot = findPackageRoot();
194901
195045
  const source = path31.join(packageRoot, "plugins", options.agent, "memorix");
194902
195046
  const includeHooks = options.includeHooks ?? true;
@@ -194945,7 +195089,7 @@ async function installPluginPackage(options) {
194945
195089
  };
194946
195090
  }
194947
195091
  async function installGeminiExtensionPackage(options = {}) {
194948
- const home = options.homeDir ?? homedir26();
195092
+ const home = options.homeDir ?? homedir27();
194949
195093
  const packageRoot = findPackageRoot();
194950
195094
  const source = path31.join(packageRoot, "plugins", "gemini", "memorix");
194951
195095
  if (!existsSync15(source)) {
@@ -194965,7 +195109,7 @@ async function installAntigravityPluginPackage(options = {}) {
194965
195109
  if (!existsSync15(source)) {
194966
195110
  throw new Error(`Antigravity plugin template not found: ${source}`);
194967
195111
  }
194968
- const pluginPath = options.global === false ? path31.join(options.projectRoot ?? process.cwd(), ".agents", "plugins", "memorix") : path31.join(options.homeDir ?? homedir26(), ".gemini", "config", "plugins", "memorix");
195112
+ const pluginPath = options.global === false ? path31.join(options.projectRoot ?? process.cwd(), ".agents", "plugins", "memorix") : path31.join(options.homeDir ?? homedir27(), ".gemini", "config", "plugins", "memorix");
194969
195113
  await copyDir(source, pluginPath);
194970
195114
  if (options.includeHooks === false) {
194971
195115
  await rm2(path31.join(pluginPath, "hooks.json"), { force: true });
@@ -194983,7 +195127,7 @@ async function installPiPackage(options = {}) {
194983
195127
  if (!existsSync15(source)) {
194984
195128
  throw new Error(`Pi package template not found: ${source}`);
194985
195129
  }
194986
- const defaultRoot = options.global ? path31.join(options.homeDir ?? homedir26(), ".pi", "agent", "packages") : path31.join(process.cwd(), ".pi", "packages");
195130
+ const defaultRoot = options.global ? path31.join(options.homeDir ?? homedir27(), ".pi", "agent", "packages") : path31.join(process.cwd(), ".pi", "packages");
194987
195131
  const packagePath = options.packageDir ?? path31.join(defaultRoot, "memorix");
194988
195132
  await copyDir(source, packagePath);
194989
195133
  await writeOfficialSkills(path31.join(packagePath, "skills"));
@@ -194995,7 +195139,7 @@ async function installPiPackage(options = {}) {
194995
195139
  };
194996
195140
  }
194997
195141
  async function installOpenClawBundlePackage(options = {}) {
194998
- const home = options.homeDir ?? homedir26();
195142
+ const home = options.homeDir ?? homedir27();
194999
195143
  const packageRoot = findPackageRoot();
195000
195144
  const source = path31.join(packageRoot, "plugins", "openclaw", "memorix");
195001
195145
  if (!existsSync15(source)) {
@@ -195044,7 +195188,7 @@ async function installOmpPackage(options = {}) {
195044
195188
  if (!existsSync15(source)) {
195045
195189
  throw new Error(`Oh-my-Pi package template not found: ${source}`);
195046
195190
  }
195047
- const defaultRoot = options.global ? path31.join(options.homeDir ?? homedir26(), ".omp", "agent", "packages") : path31.join(process.cwd(), ".omp", "packages");
195191
+ const defaultRoot = options.global ? path31.join(options.homeDir ?? homedir27(), ".omp", "agent", "packages") : path31.join(process.cwd(), ".omp", "packages");
195048
195192
  const packagePath = options.packageDir ?? path31.join(defaultRoot, "memorix");
195049
195193
  await copyDir(source, packagePath);
195050
195194
  await writeOfficialSkills(path31.join(packagePath, "skills"));
@@ -195318,7 +195462,7 @@ ${result.stdout || ""}`.toLowerCase();
195318
195462
  }
195319
195463
  async function installAgentSetup(agent, plan, global2) {
195320
195464
  const { installAgentGuidance: installAgentGuidance2, installHooks: installHooks2 } = await Promise.resolve().then(() => (init_installers(), installers_exports));
195321
- const targetRoot = global2 ? homedir26() : process.cwd();
195465
+ const targetRoot = global2 ? homedir27() : process.cwd();
195322
195466
  const hasPluginPackage = plan.actions.includes("plugin-package") && PLUGIN_PACKAGE_AGENTS.has(agent);
195323
195467
  const hasExtensionPackage = plan.actions.includes("extension-package") && agent === "gemini-cli";
195324
195468
  const hasPiPackage = plan.actions.includes("pi-package") && agent === "pi";
@@ -195469,7 +195613,14 @@ async function installAgentSetup(agent, plan, global2) {
195469
195613
  }
195470
195614
  } else if (plan.actions.includes("hooks")) {
195471
195615
  const result = await installHooks2(agent, targetRoot, global2);
195472
- v3.success(`${agent}: integration files -> ${result.configPath}`);
195616
+ const note = result.generated?.note;
195617
+ if (result.configPath) {
195618
+ v3.success(`${agent}: integration files -> ${result.configPath}`);
195619
+ } else if (note) {
195620
+ v3.info(`${agent}: ${note}`);
195621
+ } else {
195622
+ v3.info(`${agent}: no hooks or guidance are available at this scope`);
195623
+ }
195473
195624
  } else if (plan.actions.includes("project-guidance")) {
195474
195625
  const rulesPath = await installAgentGuidance2(agent, targetRoot, global2);
195475
195626
  v3.success(`${agent}: guidance -> ${rulesPath}`);
@@ -195526,6 +195677,7 @@ var init_setup = __esm({
195526
195677
  init_opencode();
195527
195678
  init_trae();
195528
195679
  init_dsh();
195680
+ init_workbuddy();
195529
195681
  init_codebuddy();
195530
195682
  init_registry2();
195531
195683
  init_official_skills();
@@ -195555,6 +195707,7 @@ var init_setup = __esm({
195555
195707
  "kiro",
195556
195708
  "trae",
195557
195709
  "dsh",
195710
+ "workbuddy",
195558
195711
  "pi"
195559
195712
  ];
195560
195713
  getSetupIntegrationRows2 = getSetupIntegrationRows;
@@ -195698,7 +195851,7 @@ var config_path_exports = {};
195698
195851
  __export(config_path_exports, {
195699
195852
  default: () => config_path_default
195700
195853
  });
195701
- import { homedir as homedir27 } from "os";
195854
+ import { homedir as homedir28 } from "os";
195702
195855
  var config_path_default;
195703
195856
  var init_config_path = __esm({
195704
195857
  "src/cli/commands/config-path.ts"() {
@@ -195716,7 +195869,7 @@ var init_config_path = __esm({
195716
195869
  run: async () => {
195717
195870
  const project = detectProject(process.cwd());
195718
195871
  ye2([
195719
- `Global: ${getGlobalConfigTomlPath(homedir27())}`,
195872
+ `Global: ${getGlobalConfigTomlPath(homedir28())}`,
195720
195873
  `Project: ${project ? getProjectConfigTomlPath(project.rootPath) : "not inside a git project"}`
195721
195874
  ].join("\n"), "Memorix config");
195722
195875
  }
@@ -195792,7 +195945,7 @@ __export(config_migrate_exports, {
195792
195945
  serializeResolvedConfigToToml: () => serializeResolvedConfigToToml
195793
195946
  });
195794
195947
  import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
195795
- import { homedir as homedir28 } from "os";
195948
+ import { homedir as homedir29 } from "os";
195796
195949
  import { dirname as dirname4 } from "path";
195797
195950
  function serializeResolvedConfigToToml(config2, options = {}) {
195798
195951
  const includeSecrets = options.includeSecrets === true;
@@ -195891,7 +196044,7 @@ var init_config_migrate = __esm({
195891
196044
  v3.error("Not inside a git project. Use `memorix config migrate --global` for global config.");
195892
196045
  return;
195893
196046
  }
195894
- const target = isGlobal ? getGlobalConfigTomlPath(homedir28()) : getProjectConfigTomlPath(project.rootPath);
196047
+ const target = isGlobal ? getGlobalConfigTomlPath(homedir29()) : getProjectConfigTomlPath(project.rootPath);
195895
196048
  const resolved = getResolvedConfig({ projectRoot: project?.rootPath ?? null });
195896
196049
  const content = serializeResolvedConfigToToml(resolved, { includeSecrets: isGlobal });
195897
196050
  mkdirSync3(dirname4(target), { recursive: true });
@@ -195903,8 +196056,8 @@ var init_config_migrate = __esm({
195903
196056
  });
195904
196057
 
195905
196058
  // src/cli/commands/integrate-shared.ts
195906
- import { homedir as homedir29 } from "os";
195907
- function getIntegrationTargetRoot(useGlobalDefaults, cwd, homeDir = homedir29()) {
196059
+ import { homedir as homedir30 } from "os";
196060
+ function getIntegrationTargetRoot(useGlobalDefaults, cwd, homeDir = homedir30()) {
195908
196061
  return useGlobalDefaults ? homeDir : cwd;
195909
196062
  }
195910
196063
  function getIntegrationScopeLabel(useGlobalDefaults) {
@@ -195942,7 +196095,8 @@ function getAgentLabel(agent) {
195942
196095
  antigravity: "Antigravity",
195943
196096
  "gemini-cli": "Gemini CLI",
195944
196097
  trae: "Trae",
195945
- dsh: "DeepSeek Harness"
196098
+ dsh: "DeepSeek Harness",
196099
+ workbuddy: "WorkBuddy"
195946
196100
  };
195947
196101
  return labels[agent] || agent;
195948
196102
  }
@@ -195958,7 +196112,8 @@ function getAgentHint(agent) {
195958
196112
  antigravity: "plugin + MCP + hooks + skills",
195959
196113
  "gemini-cli": "settings + GEMINI.md",
195960
196114
  trae: "rules",
195961
- dsh: "MCP patch + AGENTS.md + skills"
196115
+ dsh: "MCP patch + AGENTS.md + skills",
196116
+ workbuddy: "MCP + AGENTS.md"
195962
196117
  };
195963
196118
  return hints[agent] || "integration files";
195964
196119
  }
@@ -197017,7 +197172,7 @@ __export(external_provider_exports, {
197017
197172
  });
197018
197173
  import { spawn as spawn5 } from "child_process";
197019
197174
  import { existsSync as existsSync17, readFileSync as readFileSync10 } from "fs";
197020
- import { delimiter, dirname as dirname5, extname, isAbsolute as isAbsolute2, join as join23, relative as relative2, resolve as resolve3, sep as sep2 } from "path";
197175
+ import { delimiter, dirname as dirname5, extname, isAbsolute as isAbsolute2, join as join24, relative as relative2, resolve as resolve3, sep as sep2 } from "path";
197021
197176
  function boundedTimeout(value) {
197022
197177
  if (!Number.isFinite(value)) return DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS;
197023
197178
  return Math.max(100, Math.min(Math.floor(value), MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS));
@@ -197046,10 +197201,10 @@ function resolveCommandCandidates(command) {
197046
197201
  }
197047
197202
  const names = extname(requested) ? [requested] : process.platform === "win32" ? [requested + ".exe", requested + ".cmd", requested + ".js", requested] : [requested];
197048
197203
  const directories = [
197049
- ...process.platform === "win32" && process.env.LOCALAPPDATA ? [join23(process.env.LOCALAPPDATA, "codegraph", "current", "bin")] : [],
197204
+ ...process.platform === "win32" && process.env.LOCALAPPDATA ? [join24(process.env.LOCALAPPDATA, "codegraph", "current", "bin")] : [],
197050
197205
  ...(process.env.PATH ?? "").split(delimiter).filter(Boolean)
197051
197206
  ];
197052
- return [...new Set(directories.flatMap((directory) => names.map((name) => join23(directory, name))))];
197207
+ return [...new Set(directories.flatMap((directory) => names.map((name) => join24(directory, name))))];
197053
197208
  }
197054
197209
  function resolveLaunch(command) {
197055
197210
  for (const candidate2 of resolveCommandCandidates(command)) {
@@ -197057,8 +197212,8 @@ function resolveLaunch(command) {
197057
197212
  const extension3 = extname(candidate2).toLowerCase();
197058
197213
  if (extension3 === ".cmd") {
197059
197214
  const bundleRoot = resolve3(dirname5(candidate2), "..");
197060
- const node = join23(bundleRoot, "node.exe");
197061
- const entry = join23(bundleRoot, "lib", "dist", "bin", "codegraph.js");
197215
+ const node = join24(bundleRoot, "node.exe");
197216
+ const entry = join24(bundleRoot, "lib", "dist", "bin", "codegraph.js");
197062
197217
  if (existsSync17(node) && existsSync17(entry)) {
197063
197218
  return { executable: node, prefixArgs: ["--liftoff-only", entry] };
197064
197219
  }
@@ -197210,7 +197365,7 @@ async function inspectExternalCodeGraph(input) {
197210
197365
  const health2 = { state: "disabled", reason: "External CodeGraph is disabled by configuration." };
197211
197366
  return { health: health2, quality: providerQuality({ mode, health: health2 }) };
197212
197367
  }
197213
- if (!existsSync17(join23(input.projectRoot, ".codegraph"))) {
197368
+ if (!existsSync17(join24(input.projectRoot, ".codegraph"))) {
197214
197369
  const health2 = { state: "not-detected", reason: "No local .codegraph index is present for this project." };
197215
197370
  return { health: health2, quality: providerQuality({ mode, health: health2 }) };
197216
197371
  }
@@ -197245,7 +197400,7 @@ async function runExternalCodeGraphLifecycle(input) {
197245
197400
  quality: providerQuality({ mode, health })
197246
197401
  };
197247
197402
  }
197248
- const indexPath = join23(input.projectRoot, ".codegraph");
197403
+ const indexPath = join24(input.projectRoot, ".codegraph");
197249
197404
  if (input.action === "sync" && !existsSync17(indexPath)) {
197250
197405
  const health = { state: "not-detected", reason: "No local .codegraph index is present for this project." };
197251
197406
  return {
@@ -203053,8 +203208,8 @@ __export(engine_exports2, {
203053
203208
  SkillsEngine: () => SkillsEngine
203054
203209
  });
203055
203210
  import { existsSync as existsSync19, readFileSync as readFileSync11, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, readdirSync as readdirSync3 } from "fs";
203056
- import { join as join24 } from "path";
203057
- import { homedir as homedir30 } from "os";
203211
+ import { join as join25 } from "path";
203212
+ import { homedir as homedir31 } from "os";
203058
203213
  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;
203059
203214
  var init_engine4 = __esm({
203060
203215
  "src/skills/engine.ts"() {
@@ -203125,12 +203280,12 @@ var init_engine4 = __esm({
203125
203280
  listSkills() {
203126
203281
  const skills = [];
203127
203282
  const seen = /* @__PURE__ */ new Set();
203128
- const home = homedir30();
203283
+ const home = homedir31();
203129
203284
  for (const [agent, dirs] of Object.entries(SKILLS_DIRS)) {
203130
203285
  for (const dir of dirs) {
203131
- const paths = [join24(this.projectRoot, dir)];
203286
+ const paths = [join25(this.projectRoot, dir)];
203132
203287
  if (!this.skipGlobal) {
203133
- paths.push(join24(home, dir));
203288
+ paths.push(join25(home, dir));
203134
203289
  }
203135
203290
  for (const skillsRoot of paths) {
203136
203291
  if (!existsSync19(skillsRoot)) continue;
@@ -203140,7 +203295,7 @@ var init_engine4 = __esm({
203140
203295
  if (!entry.isDirectory()) continue;
203141
203296
  const name = entry.name;
203142
203297
  if (seen.has(name)) continue;
203143
- const skillMd = join24(skillsRoot, name, "SKILL.md");
203298
+ const skillMd = join25(skillsRoot, name, "SKILL.md");
203144
203299
  if (!existsSync19(skillMd)) continue;
203145
203300
  try {
203146
203301
  const content = readFileSync11(skillMd, "utf-8");
@@ -203148,7 +203303,7 @@ var init_engine4 = __esm({
203148
203303
  skills.push({
203149
203304
  name,
203150
203305
  description,
203151
- sourcePath: join24(skillsRoot, name),
203306
+ sourcePath: join25(skillsRoot, name),
203152
203307
  sourceAgent: agent,
203153
203308
  content,
203154
203309
  generated: false
@@ -203191,11 +203346,11 @@ var init_engine4 = __esm({
203191
203346
  writeSkill(skill2, target) {
203192
203347
  const dirs = SKILLS_DIRS[target];
203193
203348
  if (!dirs || dirs.length === 0) return null;
203194
- const targetDir = join24(this.projectRoot, dirs[0], skill2.name);
203349
+ const targetDir = join25(this.projectRoot, dirs[0], skill2.name);
203195
203350
  try {
203196
203351
  mkdirSync4(targetDir, { recursive: true });
203197
- writeFileSync4(join24(targetDir, "SKILL.md"), skill2.content, "utf-8");
203198
- return join24(dirs[0], skill2.name, "SKILL.md");
203352
+ writeFileSync4(join25(targetDir, "SKILL.md"), skill2.content, "utf-8");
203353
+ return join25(dirs[0], skill2.name, "SKILL.md");
203199
203354
  } catch {
203200
203355
  return null;
203201
203356
  }
@@ -204364,7 +204519,7 @@ var init_task_graph = __esm({
204364
204519
  // src/orchestrate/context-collector.ts
204365
204520
  import { execFileSync as execFileSync2 } from "child_process";
204366
204521
  import { readFileSync as readFileSync12, existsSync as existsSync20 } from "fs";
204367
- import { join as join25 } from "path";
204522
+ import { join as join26 } from "path";
204368
204523
  function normalizeEntryLimit(value, fallback) {
204369
204524
  if (!Number.isSafeInteger(value) || value < 1) return fallback;
204370
204525
  return Math.min(value, 500);
@@ -204439,7 +204594,7 @@ function collectFileTree(projectDir2, maxEntries) {
204439
204594
  }
204440
204595
  function collectDependencies(projectDir2) {
204441
204596
  try {
204442
- const pkgPath = join25(projectDir2, "package.json");
204597
+ const pkgPath = join26(projectDir2, "package.json");
204443
204598
  if (!existsSync20(pkgPath)) return "";
204444
204599
  const pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
204445
204600
  const parts = [];
@@ -205684,16 +205839,24 @@ function resolveToolProfile(opts) {
205684
205839
  return normalize(opts.explicit) ?? normalize(opts.envValue) ?? opts.fallback;
205685
205840
  }
205686
205841
  function describeProfile(profile) {
205842
+ const count3 = countToolsInProfile(profile);
205687
205843
  switch (profile) {
205688
205844
  case "micro":
205689
- return "micro (agent-ready context + bounded recovery/media, ~9 tools)";
205845
+ return `micro (agent-ready context + bounded recovery/media, ${count3} tools)`;
205690
205846
  case "lite":
205691
- return "lite (core memory + sessions, ~18 tools)";
205847
+ return `lite (core memory + sessions, ${count3} tools)`;
205692
205848
  case "team":
205693
- return "team (lite + coordination tools + dashboard + knowledge workspace, ~26 tools)";
205849
+ return `team (lite + coordination tools + dashboard + knowledge workspace, ${count3} tools)`;
205694
205850
  case "full":
205695
- return "full (all tools including advanced / KG-compat)";
205851
+ return `full (all tools including advanced / KG-compat, ${count3} tools)`;
205852
+ }
205853
+ }
205854
+ function countToolsInProfile(profile) {
205855
+ let n3 = 0;
205856
+ for (const name of Object.keys(TOOL_PROFILES)) {
205857
+ if (isToolInProfile(name, profile)) n3++;
205696
205858
  }
205859
+ return n3;
205697
205860
  }
205698
205861
  var TOOL_PROFILES;
205699
205862
  var init_tool_profile = __esm({
@@ -205768,7 +205931,7 @@ var init_tool_profile = __esm({
205768
205931
  function getMcpServerInfo() {
205769
205932
  return {
205770
205933
  name: "memorix",
205771
- version: true ? "1.8.4" : "1.0.1"
205934
+ version: true ? "1.8.6" : "1.0.1"
205772
205935
  };
205773
205936
  }
205774
205937
  function createMcpDiscoverResult(capabilities, serverInfo) {
@@ -205835,7 +205998,17 @@ var init_stdio_startup_gate = __esm({
205835
205998
  this.fail(new Error(`stdio input chunk exceeded ${this.maxBufferSize} bytes`));
205836
205999
  return;
205837
206000
  }
205838
- this.input.write(chunk);
206001
+ this.pendingInput += typeof chunk === "string" ? chunk : chunk.toString("utf8");
206002
+ let newline2 = this.pendingInput.indexOf("\n");
206003
+ while (newline2 >= 0 && !this.stopped) {
206004
+ const line = this.pendingInput.slice(0, newline2 + 1);
206005
+ this.pendingInput = this.pendingInput.slice(newline2 + 1);
206006
+ this.handleReadyLine(line);
206007
+ newline2 = this.pendingInput.indexOf("\n");
206008
+ }
206009
+ if (!this.stopped && Buffer.byteLength(this.pendingInput, "utf8") > this.maxBufferSize) {
206010
+ this.fail(new Error(`stdio input exceeded ${this.maxBufferSize} bytes`));
206011
+ }
205839
206012
  return;
205840
206013
  }
205841
206014
  const text2 = typeof chunk === "string" ? chunk : chunk.toString("utf8");
@@ -205934,6 +206107,24 @@ var init_stdio_startup_gate = __esm({
205934
206107
  this.queuedMessages.push(line);
205935
206108
  this.queuedBytes += bytes;
205936
206109
  }
206110
+ handleReadyLine(line) {
206111
+ const parsed = this.parseLine(line);
206112
+ if (parsed && !("error" in parsed) && this.isDiscoveryRequest(parsed.message)) {
206113
+ const response = {
206114
+ jsonrpc: "2.0",
206115
+ id: parsed.message.id,
206116
+ result: createMcpStartupDiscoverResult(this.serverInfo)
206117
+ };
206118
+ try {
206119
+ this.stdout.write(`${JSON.stringify(response)}
206120
+ `);
206121
+ } catch (error40) {
206122
+ this.fail(error40 instanceof Error ? error40 : new Error(String(error40)));
206123
+ }
206124
+ return;
206125
+ }
206126
+ this.input.write(line);
206127
+ }
205937
206128
  parseLine(line) {
205938
206129
  const trimmed = line.endsWith("\n") ? line.slice(0, -1).replace(/\r$/, "") : line;
205939
206130
  if (!trimmed.trim()) return null;
@@ -205972,7 +206163,8 @@ var init_stdio_startup_gate = __esm({
205972
206163
  if (message.method !== MCP_SERVER_DISCOVER_METHOD) return false;
205973
206164
  if (!Object.prototype.hasOwnProperty.call(message, "id")) return false;
205974
206165
  const params = message.params;
205975
- return params === void 0 || typeof params === "object" && params !== null && !Array.isArray(params);
206166
+ if (params === void 0) return true;
206167
+ return typeof params === "object" && params !== null && !Array.isArray(params) && !Object.prototype.hasOwnProperty.call(params, "_meta");
205976
206168
  }
205977
206169
  isValidRequestId(id) {
205978
206170
  return id === null || typeof id === "string" || typeof id === "number" && Number.isFinite(id);
@@ -206051,6 +206243,297 @@ var init_mcp_root_path = __esm({
206051
206243
  }
206052
206244
  });
206053
206245
 
206246
+ // node_modules/zod/v4/mini/parse.js
206247
+ var init_parse8 = __esm({
206248
+ "node_modules/zod/v4/mini/parse.js"() {
206249
+ "use strict";
206250
+ init_esm_shims();
206251
+ init_core3();
206252
+ }
206253
+ });
206254
+
206255
+ // node_modules/zod/v4/mini/schemas.js
206256
+ function object2(shape, params) {
206257
+ const def = {
206258
+ type: "object",
206259
+ get shape() {
206260
+ util_exports.assignProp(this, "shape", { ...shape });
206261
+ return this.shape;
206262
+ },
206263
+ ...util_exports.normalizeParams(params)
206264
+ };
206265
+ return new ZodMiniObject(def);
206266
+ }
206267
+ var ZodMiniType, ZodMiniObject;
206268
+ var init_schemas4 = __esm({
206269
+ "node_modules/zod/v4/mini/schemas.js"() {
206270
+ "use strict";
206271
+ init_esm_shims();
206272
+ init_core3();
206273
+ init_core3();
206274
+ init_parse8();
206275
+ ZodMiniType = /* @__PURE__ */ $constructor("ZodMiniType", (inst, def) => {
206276
+ if (!inst._zod)
206277
+ throw new Error("Uninitialized schema in ZodMiniType.");
206278
+ $ZodType.init(inst, def);
206279
+ inst.def = def;
206280
+ inst.parse = (data, params) => parse2(inst, data, params, { callee: inst.parse });
206281
+ inst.safeParse = (data, params) => safeParse(inst, data, params);
206282
+ inst.parseAsync = async (data, params) => parseAsync(inst, data, params, { callee: inst.parseAsync });
206283
+ inst.safeParseAsync = async (data, params) => safeParseAsync(inst, data, params);
206284
+ inst.check = (...checks) => {
206285
+ return inst.clone(
206286
+ {
206287
+ ...def,
206288
+ checks: [
206289
+ ...def.checks ?? [],
206290
+ ...checks.map((ch2) => typeof ch2 === "function" ? { _zod: { check: ch2, def: { check: "custom" }, onattach: [] } } : ch2)
206291
+ ]
206292
+ }
206293
+ // { parent: true }
206294
+ );
206295
+ };
206296
+ inst.clone = (_def, params) => clone2(inst, _def, params);
206297
+ inst.brand = () => inst;
206298
+ inst.register = ((reg, meta) => {
206299
+ reg.add(inst, meta);
206300
+ return inst;
206301
+ });
206302
+ });
206303
+ ZodMiniObject = /* @__PURE__ */ $constructor("ZodMiniObject", (inst, def) => {
206304
+ $ZodObject.init(inst, def);
206305
+ ZodMiniType.init(inst, def);
206306
+ util_exports.defineLazy(inst, "shape", () => def.shape);
206307
+ });
206308
+ }
206309
+ });
206310
+
206311
+ // node_modules/zod/v4/mini/checks.js
206312
+ var init_checks3 = __esm({
206313
+ "node_modules/zod/v4/mini/checks.js"() {
206314
+ "use strict";
206315
+ init_esm_shims();
206316
+ }
206317
+ });
206318
+
206319
+ // node_modules/zod/v4/mini/iso.js
206320
+ var init_iso2 = __esm({
206321
+ "node_modules/zod/v4/mini/iso.js"() {
206322
+ "use strict";
206323
+ init_esm_shims();
206324
+ }
206325
+ });
206326
+
206327
+ // node_modules/zod/v4/mini/coerce.js
206328
+ var init_coerce2 = __esm({
206329
+ "node_modules/zod/v4/mini/coerce.js"() {
206330
+ "use strict";
206331
+ init_esm_shims();
206332
+ }
206333
+ });
206334
+
206335
+ // node_modules/zod/v4/mini/external.js
206336
+ var init_external3 = __esm({
206337
+ "node_modules/zod/v4/mini/external.js"() {
206338
+ "use strict";
206339
+ init_esm_shims();
206340
+ init_core3();
206341
+ init_parse8();
206342
+ init_schemas4();
206343
+ init_checks3();
206344
+ init_core3();
206345
+ init_locales();
206346
+ init_iso2();
206347
+ init_coerce2();
206348
+ }
206349
+ });
206350
+
206351
+ // node_modules/zod/v4/mini/index.js
206352
+ var init_mini = __esm({
206353
+ "node_modules/zod/v4/mini/index.js"() {
206354
+ "use strict";
206355
+ init_esm_shims();
206356
+ init_external3();
206357
+ }
206358
+ });
206359
+
206360
+ // node_modules/zod/v4-mini/index.js
206361
+ var init_v4_mini = __esm({
206362
+ "node_modules/zod/v4-mini/index.js"() {
206363
+ "use strict";
206364
+ init_esm_shims();
206365
+ init_mini();
206366
+ }
206367
+ });
206368
+
206369
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
206370
+ function isZ4Schema(s4) {
206371
+ const schema = s4;
206372
+ return !!schema._zod;
206373
+ }
206374
+ function objectFromShape(shape) {
206375
+ const values = Object.values(shape);
206376
+ if (values.length === 0)
206377
+ return object2({});
206378
+ const allV4 = values.every(isZ4Schema);
206379
+ const allV3 = values.every((s4) => !isZ4Schema(s4));
206380
+ if (allV4)
206381
+ return object2(shape);
206382
+ if (allV3)
206383
+ return objectType(shape);
206384
+ throw new Error("Mixed Zod versions detected in object shape.");
206385
+ }
206386
+ function safeParse4(schema, data) {
206387
+ if (isZ4Schema(schema)) {
206388
+ const result2 = safeParse(schema, data);
206389
+ return result2;
206390
+ }
206391
+ const v3Schema = schema;
206392
+ const result = v3Schema.safeParse(data);
206393
+ return result;
206394
+ }
206395
+ async function safeParseAsync3(schema, data) {
206396
+ if (isZ4Schema(schema)) {
206397
+ const result2 = await safeParseAsync(schema, data);
206398
+ return result2;
206399
+ }
206400
+ const v3Schema = schema;
206401
+ const result = await v3Schema.safeParseAsync(data);
206402
+ return result;
206403
+ }
206404
+ function getObjectShape(schema) {
206405
+ if (!schema)
206406
+ return void 0;
206407
+ let rawShape;
206408
+ if (isZ4Schema(schema)) {
206409
+ const v4Schema = schema;
206410
+ rawShape = v4Schema._zod?.def?.shape;
206411
+ } else {
206412
+ const v3Schema = schema;
206413
+ rawShape = v3Schema.shape;
206414
+ }
206415
+ if (!rawShape)
206416
+ return void 0;
206417
+ if (typeof rawShape === "function") {
206418
+ try {
206419
+ return rawShape();
206420
+ } catch {
206421
+ return void 0;
206422
+ }
206423
+ }
206424
+ return rawShape;
206425
+ }
206426
+ function normalizeObjectSchema(schema) {
206427
+ if (!schema)
206428
+ return void 0;
206429
+ if (typeof schema === "object") {
206430
+ const asV3 = schema;
206431
+ const asV4 = schema;
206432
+ if (!asV3._def && !asV4._zod) {
206433
+ const values = Object.values(schema);
206434
+ if (values.length > 0 && values.every((v6) => typeof v6 === "object" && v6 !== null && (v6._def !== void 0 || v6._zod !== void 0 || typeof v6.parse === "function"))) {
206435
+ return objectFromShape(schema);
206436
+ }
206437
+ }
206438
+ }
206439
+ if (isZ4Schema(schema)) {
206440
+ const v4Schema = schema;
206441
+ const def = v4Schema._zod?.def;
206442
+ if (def && (def.type === "object" || def.shape !== void 0)) {
206443
+ return schema;
206444
+ }
206445
+ } else {
206446
+ const v3Schema = schema;
206447
+ if (v3Schema.shape !== void 0) {
206448
+ return schema;
206449
+ }
206450
+ }
206451
+ return void 0;
206452
+ }
206453
+ function getDotPath(path48) {
206454
+ if (path48.length === 0) {
206455
+ return "object root";
206456
+ }
206457
+ return path48.reduce((acc, seg, index) => {
206458
+ if (index === 0) {
206459
+ return String(seg);
206460
+ }
206461
+ if (typeof seg === "number") {
206462
+ return `${acc}[${seg}]`;
206463
+ }
206464
+ return `${acc}.${seg}`;
206465
+ }, "");
206466
+ }
206467
+ function getParseErrorMessage(error40) {
206468
+ if (error40 && typeof error40 === "object") {
206469
+ if ("issues" in error40 && Array.isArray(error40.issues) && error40.issues.length > 0) {
206470
+ return error40.issues.map((i4) => {
206471
+ if (!i4.path?.length) {
206472
+ return i4.message;
206473
+ }
206474
+ return `${i4.message} at ${getDotPath(i4.path)}`;
206475
+ }).join("\n");
206476
+ }
206477
+ if ("message" in error40 && typeof error40.message === "string") {
206478
+ return error40.message;
206479
+ }
206480
+ try {
206481
+ return JSON.stringify(error40);
206482
+ } catch {
206483
+ return String(error40);
206484
+ }
206485
+ }
206486
+ return String(error40);
206487
+ }
206488
+ function getSchemaDescription(schema) {
206489
+ return schema.description;
206490
+ }
206491
+ function isSchemaOptional(schema) {
206492
+ if (isZ4Schema(schema)) {
206493
+ const v4Schema = schema;
206494
+ return v4Schema._zod?.def?.type === "optional";
206495
+ }
206496
+ const v3Schema = schema;
206497
+ if (typeof schema.isOptional === "function") {
206498
+ return schema.isOptional();
206499
+ }
206500
+ return v3Schema._def?.typeName === "ZodOptional";
206501
+ }
206502
+ function getLiteralValue(schema) {
206503
+ if (isZ4Schema(schema)) {
206504
+ const v4Schema = schema;
206505
+ const def2 = v4Schema._zod?.def;
206506
+ if (def2) {
206507
+ if (def2.value !== void 0)
206508
+ return def2.value;
206509
+ if (Array.isArray(def2.values) && def2.values.length > 0) {
206510
+ return def2.values[0];
206511
+ }
206512
+ }
206513
+ }
206514
+ const v3Schema = schema;
206515
+ const def = v3Schema._def;
206516
+ if (def) {
206517
+ if (def.value !== void 0)
206518
+ return def.value;
206519
+ if (Array.isArray(def.values) && def.values.length > 0) {
206520
+ return def.values[0];
206521
+ }
206522
+ }
206523
+ const directValue = schema.value;
206524
+ if (directValue !== void 0)
206525
+ return directValue;
206526
+ return void 0;
206527
+ }
206528
+ var init_zod_compat = __esm({
206529
+ "node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js"() {
206530
+ "use strict";
206531
+ init_esm_shims();
206532
+ init_v3();
206533
+ init_v4_mini();
206534
+ }
206535
+ });
206536
+
206054
206537
  // node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
206055
206538
  var types_exports3 = {};
206056
206539
  __export(types_exports3, {
@@ -207770,422 +208253,6 @@ var init_types8 = __esm({
207770
208253
  }
207771
208254
  });
207772
208255
 
207773
- // node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
207774
- function deserializeMessage(line) {
207775
- return JSONRPCMessageSchema.parse(JSON.parse(line));
207776
- }
207777
- function serializeMessage(message) {
207778
- return JSON.stringify(message) + "\n";
207779
- }
207780
- var STDIO_DEFAULT_MAX_BUFFER_SIZE, ReadBuffer;
207781
- var init_stdio = __esm({
207782
- "node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js"() {
207783
- "use strict";
207784
- init_esm_shims();
207785
- init_types8();
207786
- STDIO_DEFAULT_MAX_BUFFER_SIZE = 10 * 1024 * 1024;
207787
- ReadBuffer = class {
207788
- constructor(options) {
207789
- this._maxBufferSize = options?.maxBufferSize ?? STDIO_DEFAULT_MAX_BUFFER_SIZE;
207790
- }
207791
- append(chunk) {
207792
- const newSize = (this._buffer?.length ?? 0) + chunk.length;
207793
- if (newSize > this._maxBufferSize) {
207794
- this.clear();
207795
- throw new Error(`ReadBuffer exceeded maximum size of ${this._maxBufferSize} bytes`);
207796
- }
207797
- this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;
207798
- }
207799
- readMessage() {
207800
- if (!this._buffer) {
207801
- return null;
207802
- }
207803
- const index = this._buffer.indexOf("\n");
207804
- if (index === -1) {
207805
- return null;
207806
- }
207807
- const line = this._buffer.toString("utf8", 0, index).replace(/\r$/, "");
207808
- this._buffer = this._buffer.subarray(index + 1);
207809
- return deserializeMessage(line);
207810
- }
207811
- clear() {
207812
- this._buffer = void 0;
207813
- }
207814
- };
207815
- }
207816
- });
207817
-
207818
- // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
207819
- var stdio_exports = {};
207820
- __export(stdio_exports, {
207821
- StdioServerTransport: () => StdioServerTransport
207822
- });
207823
- import process2 from "process";
207824
- var StdioServerTransport;
207825
- var init_stdio2 = __esm({
207826
- "node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js"() {
207827
- "use strict";
207828
- init_esm_shims();
207829
- init_stdio();
207830
- StdioServerTransport = class {
207831
- constructor(_stdin = process2.stdin, _stdout = process2.stdout, options) {
207832
- this._stdin = _stdin;
207833
- this._stdout = _stdout;
207834
- this._started = false;
207835
- this._ondata = (chunk) => {
207836
- try {
207837
- this._readBuffer.append(chunk);
207838
- this.processReadBuffer();
207839
- } catch (error40) {
207840
- this.onerror?.(error40);
207841
- this.close().catch(() => {
207842
- });
207843
- }
207844
- };
207845
- this._onerror = (error40) => {
207846
- this.onerror?.(error40);
207847
- };
207848
- this._readBuffer = new ReadBuffer({ maxBufferSize: options?.maxBufferSize });
207849
- }
207850
- /**
207851
- * Starts listening for messages on stdin.
207852
- */
207853
- async start() {
207854
- if (this._started) {
207855
- throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");
207856
- }
207857
- this._started = true;
207858
- this._stdin.on("data", this._ondata);
207859
- this._stdin.on("error", this._onerror);
207860
- }
207861
- processReadBuffer() {
207862
- while (true) {
207863
- try {
207864
- const message = this._readBuffer.readMessage();
207865
- if (message === null) {
207866
- break;
207867
- }
207868
- this.onmessage?.(message);
207869
- } catch (error40) {
207870
- this.onerror?.(error40);
207871
- }
207872
- }
207873
- }
207874
- async close() {
207875
- this._stdin.off("data", this._ondata);
207876
- this._stdin.off("error", this._onerror);
207877
- const remainingDataListeners = this._stdin.listenerCount("data");
207878
- if (remainingDataListeners === 0) {
207879
- this._stdin.pause();
207880
- }
207881
- this._readBuffer.clear();
207882
- this.onclose?.();
207883
- }
207884
- send(message) {
207885
- return new Promise((resolve6) => {
207886
- const json4 = serializeMessage(message);
207887
- if (this._stdout.write(json4)) {
207888
- resolve6();
207889
- } else {
207890
- this._stdout.once("drain", resolve6);
207891
- }
207892
- });
207893
- }
207894
- };
207895
- }
207896
- });
207897
-
207898
- // node_modules/zod/v4/mini/parse.js
207899
- var init_parse8 = __esm({
207900
- "node_modules/zod/v4/mini/parse.js"() {
207901
- "use strict";
207902
- init_esm_shims();
207903
- init_core3();
207904
- }
207905
- });
207906
-
207907
- // node_modules/zod/v4/mini/schemas.js
207908
- function object2(shape, params) {
207909
- const def = {
207910
- type: "object",
207911
- get shape() {
207912
- util_exports.assignProp(this, "shape", { ...shape });
207913
- return this.shape;
207914
- },
207915
- ...util_exports.normalizeParams(params)
207916
- };
207917
- return new ZodMiniObject(def);
207918
- }
207919
- var ZodMiniType, ZodMiniObject;
207920
- var init_schemas4 = __esm({
207921
- "node_modules/zod/v4/mini/schemas.js"() {
207922
- "use strict";
207923
- init_esm_shims();
207924
- init_core3();
207925
- init_core3();
207926
- init_parse8();
207927
- ZodMiniType = /* @__PURE__ */ $constructor("ZodMiniType", (inst, def) => {
207928
- if (!inst._zod)
207929
- throw new Error("Uninitialized schema in ZodMiniType.");
207930
- $ZodType.init(inst, def);
207931
- inst.def = def;
207932
- inst.parse = (data, params) => parse2(inst, data, params, { callee: inst.parse });
207933
- inst.safeParse = (data, params) => safeParse(inst, data, params);
207934
- inst.parseAsync = async (data, params) => parseAsync(inst, data, params, { callee: inst.parseAsync });
207935
- inst.safeParseAsync = async (data, params) => safeParseAsync(inst, data, params);
207936
- inst.check = (...checks) => {
207937
- return inst.clone(
207938
- {
207939
- ...def,
207940
- checks: [
207941
- ...def.checks ?? [],
207942
- ...checks.map((ch2) => typeof ch2 === "function" ? { _zod: { check: ch2, def: { check: "custom" }, onattach: [] } } : ch2)
207943
- ]
207944
- }
207945
- // { parent: true }
207946
- );
207947
- };
207948
- inst.clone = (_def, params) => clone2(inst, _def, params);
207949
- inst.brand = () => inst;
207950
- inst.register = ((reg, meta) => {
207951
- reg.add(inst, meta);
207952
- return inst;
207953
- });
207954
- });
207955
- ZodMiniObject = /* @__PURE__ */ $constructor("ZodMiniObject", (inst, def) => {
207956
- $ZodObject.init(inst, def);
207957
- ZodMiniType.init(inst, def);
207958
- util_exports.defineLazy(inst, "shape", () => def.shape);
207959
- });
207960
- }
207961
- });
207962
-
207963
- // node_modules/zod/v4/mini/checks.js
207964
- var init_checks3 = __esm({
207965
- "node_modules/zod/v4/mini/checks.js"() {
207966
- "use strict";
207967
- init_esm_shims();
207968
- }
207969
- });
207970
-
207971
- // node_modules/zod/v4/mini/iso.js
207972
- var init_iso2 = __esm({
207973
- "node_modules/zod/v4/mini/iso.js"() {
207974
- "use strict";
207975
- init_esm_shims();
207976
- }
207977
- });
207978
-
207979
- // node_modules/zod/v4/mini/coerce.js
207980
- var init_coerce2 = __esm({
207981
- "node_modules/zod/v4/mini/coerce.js"() {
207982
- "use strict";
207983
- init_esm_shims();
207984
- }
207985
- });
207986
-
207987
- // node_modules/zod/v4/mini/external.js
207988
- var init_external3 = __esm({
207989
- "node_modules/zod/v4/mini/external.js"() {
207990
- "use strict";
207991
- init_esm_shims();
207992
- init_core3();
207993
- init_parse8();
207994
- init_schemas4();
207995
- init_checks3();
207996
- init_core3();
207997
- init_locales();
207998
- init_iso2();
207999
- init_coerce2();
208000
- }
208001
- });
208002
-
208003
- // node_modules/zod/v4/mini/index.js
208004
- var init_mini = __esm({
208005
- "node_modules/zod/v4/mini/index.js"() {
208006
- "use strict";
208007
- init_esm_shims();
208008
- init_external3();
208009
- }
208010
- });
208011
-
208012
- // node_modules/zod/v4-mini/index.js
208013
- var init_v4_mini = __esm({
208014
- "node_modules/zod/v4-mini/index.js"() {
208015
- "use strict";
208016
- init_esm_shims();
208017
- init_mini();
208018
- }
208019
- });
208020
-
208021
- // node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
208022
- function isZ4Schema(s4) {
208023
- const schema = s4;
208024
- return !!schema._zod;
208025
- }
208026
- function objectFromShape(shape) {
208027
- const values = Object.values(shape);
208028
- if (values.length === 0)
208029
- return object2({});
208030
- const allV4 = values.every(isZ4Schema);
208031
- const allV3 = values.every((s4) => !isZ4Schema(s4));
208032
- if (allV4)
208033
- return object2(shape);
208034
- if (allV3)
208035
- return objectType(shape);
208036
- throw new Error("Mixed Zod versions detected in object shape.");
208037
- }
208038
- function safeParse4(schema, data) {
208039
- if (isZ4Schema(schema)) {
208040
- const result2 = safeParse(schema, data);
208041
- return result2;
208042
- }
208043
- const v3Schema = schema;
208044
- const result = v3Schema.safeParse(data);
208045
- return result;
208046
- }
208047
- async function safeParseAsync3(schema, data) {
208048
- if (isZ4Schema(schema)) {
208049
- const result2 = await safeParseAsync(schema, data);
208050
- return result2;
208051
- }
208052
- const v3Schema = schema;
208053
- const result = await v3Schema.safeParseAsync(data);
208054
- return result;
208055
- }
208056
- function getObjectShape(schema) {
208057
- if (!schema)
208058
- return void 0;
208059
- let rawShape;
208060
- if (isZ4Schema(schema)) {
208061
- const v4Schema = schema;
208062
- rawShape = v4Schema._zod?.def?.shape;
208063
- } else {
208064
- const v3Schema = schema;
208065
- rawShape = v3Schema.shape;
208066
- }
208067
- if (!rawShape)
208068
- return void 0;
208069
- if (typeof rawShape === "function") {
208070
- try {
208071
- return rawShape();
208072
- } catch {
208073
- return void 0;
208074
- }
208075
- }
208076
- return rawShape;
208077
- }
208078
- function normalizeObjectSchema(schema) {
208079
- if (!schema)
208080
- return void 0;
208081
- if (typeof schema === "object") {
208082
- const asV3 = schema;
208083
- const asV4 = schema;
208084
- if (!asV3._def && !asV4._zod) {
208085
- const values = Object.values(schema);
208086
- if (values.length > 0 && values.every((v6) => typeof v6 === "object" && v6 !== null && (v6._def !== void 0 || v6._zod !== void 0 || typeof v6.parse === "function"))) {
208087
- return objectFromShape(schema);
208088
- }
208089
- }
208090
- }
208091
- if (isZ4Schema(schema)) {
208092
- const v4Schema = schema;
208093
- const def = v4Schema._zod?.def;
208094
- if (def && (def.type === "object" || def.shape !== void 0)) {
208095
- return schema;
208096
- }
208097
- } else {
208098
- const v3Schema = schema;
208099
- if (v3Schema.shape !== void 0) {
208100
- return schema;
208101
- }
208102
- }
208103
- return void 0;
208104
- }
208105
- function getDotPath(path48) {
208106
- if (path48.length === 0) {
208107
- return "object root";
208108
- }
208109
- return path48.reduce((acc, seg, index) => {
208110
- if (index === 0) {
208111
- return String(seg);
208112
- }
208113
- if (typeof seg === "number") {
208114
- return `${acc}[${seg}]`;
208115
- }
208116
- return `${acc}.${seg}`;
208117
- }, "");
208118
- }
208119
- function getParseErrorMessage(error40) {
208120
- if (error40 && typeof error40 === "object") {
208121
- if ("issues" in error40 && Array.isArray(error40.issues) && error40.issues.length > 0) {
208122
- return error40.issues.map((i4) => {
208123
- if (!i4.path?.length) {
208124
- return i4.message;
208125
- }
208126
- return `${i4.message} at ${getDotPath(i4.path)}`;
208127
- }).join("\n");
208128
- }
208129
- if ("message" in error40 && typeof error40.message === "string") {
208130
- return error40.message;
208131
- }
208132
- try {
208133
- return JSON.stringify(error40);
208134
- } catch {
208135
- return String(error40);
208136
- }
208137
- }
208138
- return String(error40);
208139
- }
208140
- function getSchemaDescription(schema) {
208141
- return schema.description;
208142
- }
208143
- function isSchemaOptional(schema) {
208144
- if (isZ4Schema(schema)) {
208145
- const v4Schema = schema;
208146
- return v4Schema._zod?.def?.type === "optional";
208147
- }
208148
- const v3Schema = schema;
208149
- if (typeof schema.isOptional === "function") {
208150
- return schema.isOptional();
208151
- }
208152
- return v3Schema._def?.typeName === "ZodOptional";
208153
- }
208154
- function getLiteralValue(schema) {
208155
- if (isZ4Schema(schema)) {
208156
- const v4Schema = schema;
208157
- const def2 = v4Schema._zod?.def;
208158
- if (def2) {
208159
- if (def2.value !== void 0)
208160
- return def2.value;
208161
- if (Array.isArray(def2.values) && def2.values.length > 0) {
208162
- return def2.values[0];
208163
- }
208164
- }
208165
- }
208166
- const v3Schema = schema;
208167
- const def = v3Schema._def;
208168
- if (def) {
208169
- if (def.value !== void 0)
208170
- return def.value;
208171
- if (Array.isArray(def.values) && def.values.length > 0) {
208172
- return def.values[0];
208173
- }
208174
- }
208175
- const directValue = schema.value;
208176
- if (directValue !== void 0)
208177
- return directValue;
208178
- return void 0;
208179
- }
208180
- var init_zod_compat = __esm({
208181
- "node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js"() {
208182
- "use strict";
208183
- init_esm_shims();
208184
- init_v3();
208185
- init_v4_mini();
208186
- }
208187
- });
208188
-
208189
208256
  // node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/interfaces.js
208190
208257
  function isTerminal(status) {
208191
208258
  return status === "completed" || status === "failed" || status === "cancelled";
@@ -216239,6 +216306,783 @@ var init_ajv_provider = __esm({
216239
216306
  }
216240
216307
  });
216241
216308
 
216309
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/client.js
216310
+ var ExperimentalClientTasks;
216311
+ var init_client3 = __esm({
216312
+ "node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/client.js"() {
216313
+ "use strict";
216314
+ init_esm_shims();
216315
+ init_types8();
216316
+ ExperimentalClientTasks = class {
216317
+ constructor(_client) {
216318
+ this._client = _client;
216319
+ }
216320
+ /**
216321
+ * Calls a tool and returns an AsyncGenerator that yields response messages.
216322
+ * The generator is guaranteed to end with either a 'result' or 'error' message.
216323
+ *
216324
+ * This method provides streaming access to tool execution, allowing you to
216325
+ * observe intermediate task status updates for long-running tool calls.
216326
+ * Automatically validates structured output if the tool has an outputSchema.
216327
+ *
216328
+ * @example
216329
+ * ```typescript
216330
+ * const stream = client.experimental.tasks.callToolStream({ name: 'myTool', arguments: {} });
216331
+ * for await (const message of stream) {
216332
+ * switch (message.type) {
216333
+ * case 'taskCreated':
216334
+ * console.log('Tool execution started:', message.task.taskId);
216335
+ * break;
216336
+ * case 'taskStatus':
216337
+ * console.log('Tool status:', message.task.status);
216338
+ * break;
216339
+ * case 'result':
216340
+ * console.log('Tool result:', message.result);
216341
+ * break;
216342
+ * case 'error':
216343
+ * console.error('Tool error:', message.error);
216344
+ * break;
216345
+ * }
216346
+ * }
216347
+ * ```
216348
+ *
216349
+ * @param params - Tool call parameters (name and arguments)
216350
+ * @param resultSchema - Zod schema for validating the result (defaults to CallToolResultSchema)
216351
+ * @param options - Optional request options (timeout, signal, task creation params, etc.)
216352
+ * @returns AsyncGenerator that yields ResponseMessage objects
216353
+ *
216354
+ * @experimental
216355
+ */
216356
+ async *callToolStream(params, resultSchema = CallToolResultSchema, options) {
216357
+ const clientInternal = this._client;
216358
+ const optionsWithTask = {
216359
+ ...options,
216360
+ // We check if the tool is known to be a task during auto-configuration, but assume
216361
+ // the caller knows what they're doing if they pass this explicitly
216362
+ task: options?.task ?? (clientInternal.isToolTask(params.name) ? {} : void 0)
216363
+ };
216364
+ const stream2 = clientInternal.requestStream({ method: "tools/call", params }, resultSchema, optionsWithTask);
216365
+ const validator = clientInternal.getToolOutputValidator(params.name);
216366
+ for await (const message of stream2) {
216367
+ if (message.type === "result" && validator) {
216368
+ const result = message.result;
216369
+ if (!result.structuredContent && !result.isError) {
216370
+ yield {
216371
+ type: "error",
216372
+ error: new McpError(ErrorCode.InvalidRequest, `Tool ${params.name} has an output schema but did not return structured content`)
216373
+ };
216374
+ return;
216375
+ }
216376
+ if (result.structuredContent) {
216377
+ try {
216378
+ const validationResult = validator(result.structuredContent);
216379
+ if (!validationResult.valid) {
216380
+ yield {
216381
+ type: "error",
216382
+ error: new McpError(ErrorCode.InvalidParams, `Structured content does not match the tool's output schema: ${validationResult.errorMessage}`)
216383
+ };
216384
+ return;
216385
+ }
216386
+ } catch (error40) {
216387
+ if (error40 instanceof McpError) {
216388
+ yield { type: "error", error: error40 };
216389
+ return;
216390
+ }
216391
+ yield {
216392
+ type: "error",
216393
+ error: new McpError(ErrorCode.InvalidParams, `Failed to validate structured content: ${error40 instanceof Error ? error40.message : String(error40)}`)
216394
+ };
216395
+ return;
216396
+ }
216397
+ }
216398
+ }
216399
+ yield message;
216400
+ }
216401
+ }
216402
+ /**
216403
+ * Gets the current status of a task.
216404
+ *
216405
+ * @param taskId - The task identifier
216406
+ * @param options - Optional request options
216407
+ * @returns The task status
216408
+ *
216409
+ * @experimental
216410
+ */
216411
+ async getTask(taskId, options) {
216412
+ return this._client.getTask({ taskId }, options);
216413
+ }
216414
+ /**
216415
+ * Retrieves the result of a completed task.
216416
+ *
216417
+ * @param taskId - The task identifier
216418
+ * @param resultSchema - Zod schema for validating the result
216419
+ * @param options - Optional request options
216420
+ * @returns The task result
216421
+ *
216422
+ * @experimental
216423
+ */
216424
+ async getTaskResult(taskId, resultSchema, options) {
216425
+ return this._client.getTaskResult({ taskId }, resultSchema, options);
216426
+ }
216427
+ /**
216428
+ * Lists tasks with optional pagination.
216429
+ *
216430
+ * @param cursor - Optional pagination cursor
216431
+ * @param options - Optional request options
216432
+ * @returns List of tasks with optional next cursor
216433
+ *
216434
+ * @experimental
216435
+ */
216436
+ async listTasks(cursor, options) {
216437
+ return this._client.listTasks(cursor ? { cursor } : void 0, options);
216438
+ }
216439
+ /**
216440
+ * Cancels a running task.
216441
+ *
216442
+ * @param taskId - The task identifier
216443
+ * @param options - Optional request options
216444
+ *
216445
+ * @experimental
216446
+ */
216447
+ async cancelTask(taskId, options) {
216448
+ return this._client.cancelTask({ taskId }, options);
216449
+ }
216450
+ /**
216451
+ * Sends a request and returns an AsyncGenerator that yields response messages.
216452
+ * The generator is guaranteed to end with either a 'result' or 'error' message.
216453
+ *
216454
+ * This method provides streaming access to request processing, allowing you to
216455
+ * observe intermediate task status updates for task-augmented requests.
216456
+ *
216457
+ * @param request - The request to send
216458
+ * @param resultSchema - Zod schema for validating the result
216459
+ * @param options - Optional request options (timeout, signal, task creation params, etc.)
216460
+ * @returns AsyncGenerator that yields ResponseMessage objects
216461
+ *
216462
+ * @experimental
216463
+ */
216464
+ requestStream(request, resultSchema, options) {
216465
+ return this._client.requestStream(request, resultSchema, options);
216466
+ }
216467
+ };
216468
+ }
216469
+ });
216470
+
216471
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js
216472
+ function assertToolsCallTaskCapability(requests, method, entityName) {
216473
+ if (!requests) {
216474
+ throw new Error(`${entityName} does not support task creation (required for ${method})`);
216475
+ }
216476
+ switch (method) {
216477
+ case "tools/call":
216478
+ if (!requests.tools?.call) {
216479
+ throw new Error(`${entityName} does not support task creation for tools/call (required for ${method})`);
216480
+ }
216481
+ break;
216482
+ default:
216483
+ break;
216484
+ }
216485
+ }
216486
+ function assertClientRequestTaskCapability(requests, method, entityName) {
216487
+ if (!requests) {
216488
+ throw new Error(`${entityName} does not support task creation (required for ${method})`);
216489
+ }
216490
+ switch (method) {
216491
+ case "sampling/createMessage":
216492
+ if (!requests.sampling?.createMessage) {
216493
+ throw new Error(`${entityName} does not support task creation for sampling/createMessage (required for ${method})`);
216494
+ }
216495
+ break;
216496
+ case "elicitation/create":
216497
+ if (!requests.elicitation?.create) {
216498
+ throw new Error(`${entityName} does not support task creation for elicitation/create (required for ${method})`);
216499
+ }
216500
+ break;
216501
+ default:
216502
+ break;
216503
+ }
216504
+ }
216505
+ var init_helpers2 = __esm({
216506
+ "node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js"() {
216507
+ "use strict";
216508
+ init_esm_shims();
216509
+ }
216510
+ });
216511
+
216512
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/client/index.js
216513
+ function applyElicitationDefaults(schema, data) {
216514
+ if (!schema || data === null || typeof data !== "object")
216515
+ return;
216516
+ if (schema.type === "object" && schema.properties && typeof schema.properties === "object") {
216517
+ const obj = data;
216518
+ const props = schema.properties;
216519
+ for (const key of Object.keys(props)) {
216520
+ const propSchema = props[key];
216521
+ if (obj[key] === void 0 && Object.prototype.hasOwnProperty.call(propSchema, "default")) {
216522
+ obj[key] = propSchema.default;
216523
+ }
216524
+ if (obj[key] !== void 0) {
216525
+ applyElicitationDefaults(propSchema, obj[key]);
216526
+ }
216527
+ }
216528
+ }
216529
+ if (Array.isArray(schema.anyOf)) {
216530
+ for (const sub of schema.anyOf) {
216531
+ if (typeof sub !== "boolean") {
216532
+ applyElicitationDefaults(sub, data);
216533
+ }
216534
+ }
216535
+ }
216536
+ if (Array.isArray(schema.oneOf)) {
216537
+ for (const sub of schema.oneOf) {
216538
+ if (typeof sub !== "boolean") {
216539
+ applyElicitationDefaults(sub, data);
216540
+ }
216541
+ }
216542
+ }
216543
+ }
216544
+ function getSupportedElicitationModes(capabilities) {
216545
+ if (!capabilities) {
216546
+ return { supportsFormMode: false, supportsUrlMode: false };
216547
+ }
216548
+ const hasFormCapability = capabilities.form !== void 0;
216549
+ const hasUrlCapability = capabilities.url !== void 0;
216550
+ const supportsFormMode = hasFormCapability || !hasFormCapability && !hasUrlCapability;
216551
+ const supportsUrlMode = hasUrlCapability;
216552
+ return { supportsFormMode, supportsUrlMode };
216553
+ }
216554
+ var Client;
216555
+ var init_client4 = __esm({
216556
+ "node_modules/@modelcontextprotocol/sdk/dist/esm/client/index.js"() {
216557
+ "use strict";
216558
+ init_esm_shims();
216559
+ init_protocol();
216560
+ init_types8();
216561
+ init_ajv_provider();
216562
+ init_zod_compat();
216563
+ init_client3();
216564
+ init_helpers2();
216565
+ Client = class extends Protocol {
216566
+ /**
216567
+ * Initializes this client with the given name and version information.
216568
+ */
216569
+ constructor(_clientInfo, options) {
216570
+ super(options);
216571
+ this._clientInfo = _clientInfo;
216572
+ this._cachedToolOutputValidators = /* @__PURE__ */ new Map();
216573
+ this._cachedKnownTaskTools = /* @__PURE__ */ new Set();
216574
+ this._cachedRequiredTaskTools = /* @__PURE__ */ new Set();
216575
+ this._listChangedDebounceTimers = /* @__PURE__ */ new Map();
216576
+ this._capabilities = options?.capabilities ?? {};
216577
+ this._jsonSchemaValidator = options?.jsonSchemaValidator ?? new AjvJsonSchemaValidator();
216578
+ if (options?.listChanged) {
216579
+ this._pendingListChangedConfig = options.listChanged;
216580
+ }
216581
+ }
216582
+ /**
216583
+ * Set up handlers for list changed notifications based on config and server capabilities.
216584
+ * This should only be called after initialization when server capabilities are known.
216585
+ * Handlers are silently skipped if the server doesn't advertise the corresponding listChanged capability.
216586
+ * @internal
216587
+ */
216588
+ _setupListChangedHandlers(config2) {
216589
+ if (config2.tools && this._serverCapabilities?.tools?.listChanged) {
216590
+ this._setupListChangedHandler("tools", ToolListChangedNotificationSchema, config2.tools, async () => {
216591
+ const result = await this.listTools();
216592
+ return result.tools;
216593
+ });
216594
+ }
216595
+ if (config2.prompts && this._serverCapabilities?.prompts?.listChanged) {
216596
+ this._setupListChangedHandler("prompts", PromptListChangedNotificationSchema, config2.prompts, async () => {
216597
+ const result = await this.listPrompts();
216598
+ return result.prompts;
216599
+ });
216600
+ }
216601
+ if (config2.resources && this._serverCapabilities?.resources?.listChanged) {
216602
+ this._setupListChangedHandler("resources", ResourceListChangedNotificationSchema, config2.resources, async () => {
216603
+ const result = await this.listResources();
216604
+ return result.resources;
216605
+ });
216606
+ }
216607
+ }
216608
+ /**
216609
+ * Access experimental features.
216610
+ *
216611
+ * WARNING: These APIs are experimental and may change without notice.
216612
+ *
216613
+ * @experimental
216614
+ */
216615
+ get experimental() {
216616
+ if (!this._experimental) {
216617
+ this._experimental = {
216618
+ tasks: new ExperimentalClientTasks(this)
216619
+ };
216620
+ }
216621
+ return this._experimental;
216622
+ }
216623
+ /**
216624
+ * Registers new capabilities. This can only be called before connecting to a transport.
216625
+ *
216626
+ * The new capabilities will be merged with any existing capabilities previously given (e.g., at initialization).
216627
+ */
216628
+ registerCapabilities(capabilities) {
216629
+ if (this.transport) {
216630
+ throw new Error("Cannot register capabilities after connecting to transport");
216631
+ }
216632
+ this._capabilities = mergeCapabilities(this._capabilities, capabilities);
216633
+ }
216634
+ /**
216635
+ * Override request handler registration to enforce client-side validation for elicitation.
216636
+ */
216637
+ setRequestHandler(requestSchema, handler) {
216638
+ const shape = getObjectShape(requestSchema);
216639
+ const methodSchema = shape?.method;
216640
+ if (!methodSchema) {
216641
+ throw new Error("Schema is missing a method literal");
216642
+ }
216643
+ const methodValue = getLiteralValue(methodSchema);
216644
+ if (typeof methodValue !== "string") {
216645
+ throw new Error("Schema method literal must be a string");
216646
+ }
216647
+ const method = methodValue;
216648
+ if (method === "elicitation/create") {
216649
+ const wrappedHandler = async (request, extra) => {
216650
+ const validatedRequest = safeParse4(ElicitRequestSchema, request);
216651
+ if (!validatedRequest.success) {
216652
+ const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
216653
+ throw new McpError(ErrorCode.InvalidParams, `Invalid elicitation request: ${errorMessage}`);
216654
+ }
216655
+ const { params } = validatedRequest.data;
216656
+ params.mode = params.mode ?? "form";
216657
+ const { supportsFormMode, supportsUrlMode } = getSupportedElicitationModes(this._capabilities.elicitation);
216658
+ if (params.mode === "form" && !supportsFormMode) {
216659
+ throw new McpError(ErrorCode.InvalidParams, "Client does not support form-mode elicitation requests");
216660
+ }
216661
+ if (params.mode === "url" && !supportsUrlMode) {
216662
+ throw new McpError(ErrorCode.InvalidParams, "Client does not support URL-mode elicitation requests");
216663
+ }
216664
+ const result = await Promise.resolve(handler(request, extra));
216665
+ if (params.task) {
216666
+ const taskValidationResult = safeParse4(CreateTaskResultSchema, result);
216667
+ if (!taskValidationResult.success) {
216668
+ const errorMessage = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
216669
+ throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage}`);
216670
+ }
216671
+ return taskValidationResult.data;
216672
+ }
216673
+ const validationResult = safeParse4(ElicitResultSchema, result);
216674
+ if (!validationResult.success) {
216675
+ const errorMessage = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
216676
+ throw new McpError(ErrorCode.InvalidParams, `Invalid elicitation result: ${errorMessage}`);
216677
+ }
216678
+ const validatedResult = validationResult.data;
216679
+ const requestedSchema = params.mode === "form" ? params.requestedSchema : void 0;
216680
+ if (params.mode === "form" && validatedResult.action === "accept" && validatedResult.content && requestedSchema) {
216681
+ if (this._capabilities.elicitation?.form?.applyDefaults) {
216682
+ try {
216683
+ applyElicitationDefaults(requestedSchema, validatedResult.content);
216684
+ } catch {
216685
+ }
216686
+ }
216687
+ }
216688
+ return validatedResult;
216689
+ };
216690
+ return super.setRequestHandler(requestSchema, wrappedHandler);
216691
+ }
216692
+ if (method === "sampling/createMessage") {
216693
+ const wrappedHandler = async (request, extra) => {
216694
+ const validatedRequest = safeParse4(CreateMessageRequestSchema, request);
216695
+ if (!validatedRequest.success) {
216696
+ const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
216697
+ throw new McpError(ErrorCode.InvalidParams, `Invalid sampling request: ${errorMessage}`);
216698
+ }
216699
+ const { params } = validatedRequest.data;
216700
+ const result = await Promise.resolve(handler(request, extra));
216701
+ if (params.task) {
216702
+ const taskValidationResult = safeParse4(CreateTaskResultSchema, result);
216703
+ if (!taskValidationResult.success) {
216704
+ const errorMessage = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
216705
+ throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage}`);
216706
+ }
216707
+ return taskValidationResult.data;
216708
+ }
216709
+ const hasTools = params.tools || params.toolChoice;
216710
+ const resultSchema = hasTools ? CreateMessageResultWithToolsSchema : CreateMessageResultSchema;
216711
+ const validationResult = safeParse4(resultSchema, result);
216712
+ if (!validationResult.success) {
216713
+ const errorMessage = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
216714
+ throw new McpError(ErrorCode.InvalidParams, `Invalid sampling result: ${errorMessage}`);
216715
+ }
216716
+ return validationResult.data;
216717
+ };
216718
+ return super.setRequestHandler(requestSchema, wrappedHandler);
216719
+ }
216720
+ return super.setRequestHandler(requestSchema, handler);
216721
+ }
216722
+ assertCapability(capability, method) {
216723
+ if (!this._serverCapabilities?.[capability]) {
216724
+ throw new Error(`Server does not support ${capability} (required for ${method})`);
216725
+ }
216726
+ }
216727
+ async connect(transport, options) {
216728
+ await super.connect(transport);
216729
+ if (transport.sessionId !== void 0) {
216730
+ return;
216731
+ }
216732
+ try {
216733
+ const result = await this.request({
216734
+ method: "initialize",
216735
+ params: {
216736
+ protocolVersion: LATEST_PROTOCOL_VERSION,
216737
+ capabilities: this._capabilities,
216738
+ clientInfo: this._clientInfo
216739
+ }
216740
+ }, InitializeResultSchema, options);
216741
+ if (result === void 0) {
216742
+ throw new Error(`Server sent invalid initialize result: ${result}`);
216743
+ }
216744
+ if (!SUPPORTED_PROTOCOL_VERSIONS.includes(result.protocolVersion)) {
216745
+ throw new Error(`Server's protocol version is not supported: ${result.protocolVersion}`);
216746
+ }
216747
+ this._serverCapabilities = result.capabilities;
216748
+ this._serverVersion = result.serverInfo;
216749
+ if (transport.setProtocolVersion) {
216750
+ transport.setProtocolVersion(result.protocolVersion);
216751
+ }
216752
+ this._instructions = result.instructions;
216753
+ await this.notification({
216754
+ method: "notifications/initialized"
216755
+ });
216756
+ if (this._pendingListChangedConfig) {
216757
+ this._setupListChangedHandlers(this._pendingListChangedConfig);
216758
+ this._pendingListChangedConfig = void 0;
216759
+ }
216760
+ } catch (error40) {
216761
+ void this.close();
216762
+ throw error40;
216763
+ }
216764
+ }
216765
+ /**
216766
+ * After initialization has completed, this will be populated with the server's reported capabilities.
216767
+ */
216768
+ getServerCapabilities() {
216769
+ return this._serverCapabilities;
216770
+ }
216771
+ /**
216772
+ * After initialization has completed, this will be populated with information about the server's name and version.
216773
+ */
216774
+ getServerVersion() {
216775
+ return this._serverVersion;
216776
+ }
216777
+ /**
216778
+ * After initialization has completed, this may be populated with information about the server's instructions.
216779
+ */
216780
+ getInstructions() {
216781
+ return this._instructions;
216782
+ }
216783
+ assertCapabilityForMethod(method) {
216784
+ switch (method) {
216785
+ case "logging/setLevel":
216786
+ if (!this._serverCapabilities?.logging) {
216787
+ throw new Error(`Server does not support logging (required for ${method})`);
216788
+ }
216789
+ break;
216790
+ case "prompts/get":
216791
+ case "prompts/list":
216792
+ if (!this._serverCapabilities?.prompts) {
216793
+ throw new Error(`Server does not support prompts (required for ${method})`);
216794
+ }
216795
+ break;
216796
+ case "resources/list":
216797
+ case "resources/templates/list":
216798
+ case "resources/read":
216799
+ case "resources/subscribe":
216800
+ case "resources/unsubscribe":
216801
+ if (!this._serverCapabilities?.resources) {
216802
+ throw new Error(`Server does not support resources (required for ${method})`);
216803
+ }
216804
+ if (method === "resources/subscribe" && !this._serverCapabilities.resources.subscribe) {
216805
+ throw new Error(`Server does not support resource subscriptions (required for ${method})`);
216806
+ }
216807
+ break;
216808
+ case "tools/call":
216809
+ case "tools/list":
216810
+ if (!this._serverCapabilities?.tools) {
216811
+ throw new Error(`Server does not support tools (required for ${method})`);
216812
+ }
216813
+ break;
216814
+ case "completion/complete":
216815
+ if (!this._serverCapabilities?.completions) {
216816
+ throw new Error(`Server does not support completions (required for ${method})`);
216817
+ }
216818
+ break;
216819
+ case "initialize":
216820
+ break;
216821
+ case "ping":
216822
+ break;
216823
+ }
216824
+ }
216825
+ assertNotificationCapability(method) {
216826
+ switch (method) {
216827
+ case "notifications/roots/list_changed":
216828
+ if (!this._capabilities.roots?.listChanged) {
216829
+ throw new Error(`Client does not support roots list changed notifications (required for ${method})`);
216830
+ }
216831
+ break;
216832
+ case "notifications/initialized":
216833
+ break;
216834
+ case "notifications/cancelled":
216835
+ break;
216836
+ case "notifications/progress":
216837
+ break;
216838
+ }
216839
+ }
216840
+ assertRequestHandlerCapability(method) {
216841
+ if (!this._capabilities) {
216842
+ return;
216843
+ }
216844
+ switch (method) {
216845
+ case "sampling/createMessage":
216846
+ if (!this._capabilities.sampling) {
216847
+ throw new Error(`Client does not support sampling capability (required for ${method})`);
216848
+ }
216849
+ break;
216850
+ case "elicitation/create":
216851
+ if (!this._capabilities.elicitation) {
216852
+ throw new Error(`Client does not support elicitation capability (required for ${method})`);
216853
+ }
216854
+ break;
216855
+ case "roots/list":
216856
+ if (!this._capabilities.roots) {
216857
+ throw new Error(`Client does not support roots capability (required for ${method})`);
216858
+ }
216859
+ break;
216860
+ case "tasks/get":
216861
+ case "tasks/list":
216862
+ case "tasks/result":
216863
+ case "tasks/cancel":
216864
+ if (!this._capabilities.tasks) {
216865
+ throw new Error(`Client does not support tasks capability (required for ${method})`);
216866
+ }
216867
+ break;
216868
+ case "ping":
216869
+ break;
216870
+ }
216871
+ }
216872
+ assertTaskCapability(method) {
216873
+ assertToolsCallTaskCapability(this._serverCapabilities?.tasks?.requests, method, "Server");
216874
+ }
216875
+ assertTaskHandlerCapability(method) {
216876
+ if (!this._capabilities) {
216877
+ return;
216878
+ }
216879
+ assertClientRequestTaskCapability(this._capabilities.tasks?.requests, method, "Client");
216880
+ }
216881
+ async ping(options) {
216882
+ return this.request({ method: "ping" }, EmptyResultSchema, options);
216883
+ }
216884
+ async complete(params, options) {
216885
+ return this.request({ method: "completion/complete", params }, CompleteResultSchema, options);
216886
+ }
216887
+ async setLoggingLevel(level, options) {
216888
+ return this.request({ method: "logging/setLevel", params: { level } }, EmptyResultSchema, options);
216889
+ }
216890
+ async getPrompt(params, options) {
216891
+ return this.request({ method: "prompts/get", params }, GetPromptResultSchema, options);
216892
+ }
216893
+ async listPrompts(params, options) {
216894
+ return this.request({ method: "prompts/list", params }, ListPromptsResultSchema, options);
216895
+ }
216896
+ async listResources(params, options) {
216897
+ return this.request({ method: "resources/list", params }, ListResourcesResultSchema, options);
216898
+ }
216899
+ async listResourceTemplates(params, options) {
216900
+ return this.request({ method: "resources/templates/list", params }, ListResourceTemplatesResultSchema, options);
216901
+ }
216902
+ async readResource(params, options) {
216903
+ return this.request({ method: "resources/read", params }, ReadResourceResultSchema, options);
216904
+ }
216905
+ async subscribeResource(params, options) {
216906
+ return this.request({ method: "resources/subscribe", params }, EmptyResultSchema, options);
216907
+ }
216908
+ async unsubscribeResource(params, options) {
216909
+ return this.request({ method: "resources/unsubscribe", params }, EmptyResultSchema, options);
216910
+ }
216911
+ /**
216912
+ * Calls a tool and waits for the result. Automatically validates structured output if the tool has an outputSchema.
216913
+ *
216914
+ * For task-based execution with streaming behavior, use client.experimental.tasks.callToolStream() instead.
216915
+ */
216916
+ async callTool(params, resultSchema = CallToolResultSchema, options) {
216917
+ if (this.isToolTaskRequired(params.name)) {
216918
+ throw new McpError(ErrorCode.InvalidRequest, `Tool "${params.name}" requires task-based execution. Use client.experimental.tasks.callToolStream() instead.`);
216919
+ }
216920
+ const result = await this.request({ method: "tools/call", params }, resultSchema, options);
216921
+ const validator = this.getToolOutputValidator(params.name);
216922
+ if (validator) {
216923
+ if (!result.structuredContent && !result.isError) {
216924
+ throw new McpError(ErrorCode.InvalidRequest, `Tool ${params.name} has an output schema but did not return structured content`);
216925
+ }
216926
+ if (result.structuredContent) {
216927
+ try {
216928
+ const validationResult = validator(result.structuredContent);
216929
+ if (!validationResult.valid) {
216930
+ throw new McpError(ErrorCode.InvalidParams, `Structured content does not match the tool's output schema: ${validationResult.errorMessage}`);
216931
+ }
216932
+ } catch (error40) {
216933
+ if (error40 instanceof McpError) {
216934
+ throw error40;
216935
+ }
216936
+ throw new McpError(ErrorCode.InvalidParams, `Failed to validate structured content: ${error40 instanceof Error ? error40.message : String(error40)}`);
216937
+ }
216938
+ }
216939
+ }
216940
+ return result;
216941
+ }
216942
+ isToolTask(toolName) {
216943
+ if (!this._serverCapabilities?.tasks?.requests?.tools?.call) {
216944
+ return false;
216945
+ }
216946
+ return this._cachedKnownTaskTools.has(toolName);
216947
+ }
216948
+ /**
216949
+ * Check if a tool requires task-based execution.
216950
+ * Unlike isToolTask which includes 'optional' tools, this only checks for 'required'.
216951
+ */
216952
+ isToolTaskRequired(toolName) {
216953
+ return this._cachedRequiredTaskTools.has(toolName);
216954
+ }
216955
+ /**
216956
+ * Cache validators for tool output schemas.
216957
+ * Called after listTools() to pre-compile validators for better performance.
216958
+ */
216959
+ cacheToolMetadata(tools) {
216960
+ this._cachedToolOutputValidators.clear();
216961
+ this._cachedKnownTaskTools.clear();
216962
+ this._cachedRequiredTaskTools.clear();
216963
+ for (const tool of tools) {
216964
+ if (tool.outputSchema) {
216965
+ const toolValidator = this._jsonSchemaValidator.getValidator(tool.outputSchema);
216966
+ this._cachedToolOutputValidators.set(tool.name, toolValidator);
216967
+ }
216968
+ const taskSupport = tool.execution?.taskSupport;
216969
+ if (taskSupport === "required" || taskSupport === "optional") {
216970
+ this._cachedKnownTaskTools.add(tool.name);
216971
+ }
216972
+ if (taskSupport === "required") {
216973
+ this._cachedRequiredTaskTools.add(tool.name);
216974
+ }
216975
+ }
216976
+ }
216977
+ /**
216978
+ * Get cached validator for a tool
216979
+ */
216980
+ getToolOutputValidator(toolName) {
216981
+ return this._cachedToolOutputValidators.get(toolName);
216982
+ }
216983
+ async listTools(params, options) {
216984
+ const result = await this.request({ method: "tools/list", params }, ListToolsResultSchema, options);
216985
+ this.cacheToolMetadata(result.tools);
216986
+ return result;
216987
+ }
216988
+ /**
216989
+ * Set up a single list changed handler.
216990
+ * @internal
216991
+ */
216992
+ _setupListChangedHandler(listType, notificationSchema, options, fetcher) {
216993
+ const parseResult = ListChangedOptionsBaseSchema.safeParse(options);
216994
+ if (!parseResult.success) {
216995
+ throw new Error(`Invalid ${listType} listChanged options: ${parseResult.error.message}`);
216996
+ }
216997
+ if (typeof options.onChanged !== "function") {
216998
+ throw new Error(`Invalid ${listType} listChanged options: onChanged must be a function`);
216999
+ }
217000
+ const { autoRefresh, debounceMs } = parseResult.data;
217001
+ const { onChanged } = options;
217002
+ const refresh = async () => {
217003
+ if (!autoRefresh) {
217004
+ onChanged(null, null);
217005
+ return;
217006
+ }
217007
+ try {
217008
+ const items = await fetcher();
217009
+ onChanged(null, items);
217010
+ } catch (e5) {
217011
+ const error40 = e5 instanceof Error ? e5 : new Error(String(e5));
217012
+ onChanged(error40, null);
217013
+ }
217014
+ };
217015
+ const handler = () => {
217016
+ if (debounceMs) {
217017
+ const existingTimer = this._listChangedDebounceTimers.get(listType);
217018
+ if (existingTimer) {
217019
+ clearTimeout(existingTimer);
217020
+ }
217021
+ const timer = setTimeout(refresh, debounceMs);
217022
+ this._listChangedDebounceTimers.set(listType, timer);
217023
+ } else {
217024
+ refresh();
217025
+ }
217026
+ };
217027
+ this.setNotificationHandler(notificationSchema, handler);
217028
+ }
217029
+ async sendRootsListChanged() {
217030
+ return this.notification({ method: "notifications/roots/list_changed" });
217031
+ }
217032
+ };
217033
+ }
217034
+ });
217035
+
217036
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/inMemory.js
217037
+ var InMemoryTransport;
217038
+ var init_inMemory = __esm({
217039
+ "node_modules/@modelcontextprotocol/sdk/dist/esm/inMemory.js"() {
217040
+ "use strict";
217041
+ init_esm_shims();
217042
+ InMemoryTransport = class _InMemoryTransport {
217043
+ constructor() {
217044
+ this._messageQueue = [];
217045
+ }
217046
+ /**
217047
+ * Creates a pair of linked in-memory transports that can communicate with each other. One should be passed to a Client and one to a Server.
217048
+ */
217049
+ static createLinkedPair() {
217050
+ const clientTransport = new _InMemoryTransport();
217051
+ const serverTransport = new _InMemoryTransport();
217052
+ clientTransport._otherTransport = serverTransport;
217053
+ serverTransport._otherTransport = clientTransport;
217054
+ return [clientTransport, serverTransport];
217055
+ }
217056
+ async start() {
217057
+ while (this._messageQueue.length > 0) {
217058
+ const queuedMessage = this._messageQueue.shift();
217059
+ this.onmessage?.(queuedMessage.message, queuedMessage.extra);
217060
+ }
217061
+ }
217062
+ async close() {
217063
+ const other = this._otherTransport;
217064
+ this._otherTransport = void 0;
217065
+ await other?.close();
217066
+ this.onclose?.();
217067
+ }
217068
+ /**
217069
+ * Sends a message with optional auth info.
217070
+ * This is useful for testing authentication scenarios.
217071
+ */
217072
+ async send(message, options) {
217073
+ if (!this._otherTransport) {
217074
+ throw new Error("Not connected");
217075
+ }
217076
+ if (this._otherTransport.onmessage) {
217077
+ this._otherTransport.onmessage(message, { authInfo: options?.authInfo });
217078
+ } else {
217079
+ this._otherTransport._messageQueue.push({ message, extra: { authInfo: options?.authInfo } });
217080
+ }
217081
+ }
217082
+ };
217083
+ }
217084
+ });
217085
+
216242
217086
  // node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/server.js
216243
217087
  var ExperimentalServerTasks;
216244
217088
  var init_server = __esm({
@@ -216460,47 +217304,6 @@ var init_server = __esm({
216460
217304
  }
216461
217305
  });
216462
217306
 
216463
- // node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js
216464
- function assertToolsCallTaskCapability(requests, method, entityName) {
216465
- if (!requests) {
216466
- throw new Error(`${entityName} does not support task creation (required for ${method})`);
216467
- }
216468
- switch (method) {
216469
- case "tools/call":
216470
- if (!requests.tools?.call) {
216471
- throw new Error(`${entityName} does not support task creation for tools/call (required for ${method})`);
216472
- }
216473
- break;
216474
- default:
216475
- break;
216476
- }
216477
- }
216478
- function assertClientRequestTaskCapability(requests, method, entityName) {
216479
- if (!requests) {
216480
- throw new Error(`${entityName} does not support task creation (required for ${method})`);
216481
- }
216482
- switch (method) {
216483
- case "sampling/createMessage":
216484
- if (!requests.sampling?.createMessage) {
216485
- throw new Error(`${entityName} does not support task creation for sampling/createMessage (required for ${method})`);
216486
- }
216487
- break;
216488
- case "elicitation/create":
216489
- if (!requests.elicitation?.create) {
216490
- throw new Error(`${entityName} does not support task creation for elicitation/create (required for ${method})`);
216491
- }
216492
- break;
216493
- default:
216494
- break;
216495
- }
216496
- }
216497
- var init_helpers2 = __esm({
216498
- "node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js"() {
216499
- "use strict";
216500
- init_esm_shims();
216501
- }
216502
- });
216503
-
216504
217307
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
216505
217308
  var Server;
216506
217309
  var init_server2 = __esm({
@@ -218934,8 +219737,8 @@ __export(engine_exports3, {
218934
219737
  WorkspaceSyncEngine: () => WorkspaceSyncEngine
218935
219738
  });
218936
219739
  import { readFileSync as readFileSync14, readdirSync as readdirSync4, existsSync as existsSync23, cpSync, mkdirSync as mkdirSync6 } from "fs";
218937
- import { join as join27 } from "path";
218938
- import { homedir as homedir31 } from "os";
219740
+ import { join as join28 } from "path";
219741
+ import { homedir as homedir32 } from "os";
218939
219742
  var WorkspaceSyncEngine;
218940
219743
  var init_engine5 = __esm({
218941
219744
  "src/workspace/engine.ts"() {
@@ -219007,9 +219810,9 @@ var init_engine5 = __esm({
219007
219810
  const globalPath = adapter.getConfigPath();
219008
219811
  const pathsToCheck = [configPath, globalPath];
219009
219812
  if (target === "antigravity") {
219010
- pathsToCheck.push(join27(this.projectRoot, ".gemini", "settings.json"));
219011
- pathsToCheck.push(join27(homedir31(), ".gemini", "settings.json"));
219012
- pathsToCheck.push(join27(homedir31(), ".gemini", "antigravity", "mcp_config.json"));
219813
+ pathsToCheck.push(join28(this.projectRoot, ".gemini", "settings.json"));
219814
+ pathsToCheck.push(join28(homedir32(), ".gemini", "settings.json"));
219815
+ pathsToCheck.push(join28(homedir32(), ".gemini", "antigravity", "mcp_config.json"));
219013
219816
  }
219014
219817
  const merged = /* @__PURE__ */ new Map();
219015
219818
  for (const path48 of pathsToCheck) {
@@ -219126,7 +219929,7 @@ var init_engine5 = __esm({
219126
219929
  getTargetSkillsDir(target) {
219127
219930
  const dirs = _WorkspaceSyncEngine.SKILLS_DIRS[target];
219128
219931
  if (!dirs || dirs.length === 0) return null;
219129
- return join27(this.projectRoot, dirs[0]);
219932
+ return join28(this.projectRoot, dirs[0]);
219130
219933
  }
219131
219934
  /**
219132
219935
  * Scan all agent skills directories and collect unique skills.
@@ -219135,12 +219938,12 @@ var init_engine5 = __esm({
219135
219938
  const skills = [];
219136
219939
  const conflicts = [];
219137
219940
  const seen = /* @__PURE__ */ new Map();
219138
- const home = homedir31();
219941
+ const home = homedir32();
219139
219942
  for (const [agent, dirs] of Object.entries(_WorkspaceSyncEngine.SKILLS_DIRS)) {
219140
219943
  for (const dir of dirs) {
219141
219944
  const paths = [
219142
- join27(this.projectRoot, dir),
219143
- join27(home, dir)
219945
+ join28(this.projectRoot, dir),
219946
+ join28(home, dir)
219144
219947
  ];
219145
219948
  for (const skillsRoot of paths) {
219146
219949
  if (!existsSync23(skillsRoot)) continue;
@@ -219148,7 +219951,7 @@ var init_engine5 = __esm({
219148
219951
  const entries = readdirSync4(skillsRoot, { withFileTypes: true });
219149
219952
  for (const entry of entries) {
219150
219953
  if (!entry.isDirectory()) continue;
219151
- const skillMd = join27(skillsRoot, entry.name, "SKILL.md");
219954
+ const skillMd = join28(skillsRoot, entry.name, "SKILL.md");
219152
219955
  if (!existsSync23(skillMd)) continue;
219153
219956
  let description = "";
219154
219957
  try {
@@ -219160,7 +219963,7 @@ var init_engine5 = __esm({
219160
219963
  const newEntry = {
219161
219964
  name: entry.name,
219162
219965
  description,
219163
- sourcePath: join27(skillsRoot, entry.name),
219966
+ sourcePath: join28(skillsRoot, entry.name),
219164
219967
  sourceAgent: agent
219165
219968
  };
219166
219969
  const existing = seen.get(entry.name);
@@ -219197,7 +220000,7 @@ var init_engine5 = __esm({
219197
220000
  }
219198
220001
  for (const skill2 of skills) {
219199
220002
  if (skill2.sourceAgent === target) continue;
219200
- const dest = join27(targetDir, skill2.name);
220003
+ const dest = join28(targetDir, skill2.name);
219201
220004
  if (existsSync23(dest)) {
219202
220005
  skipped.push(`${skill2.name} (already exists in ${target})`);
219203
220006
  continue;
@@ -219213,13 +220016,13 @@ var init_engine5 = __esm({
219213
220016
  }
219214
220017
  scanWorkflows() {
219215
220018
  const workflows = [];
219216
- const wfDir = join27(this.projectRoot, ".windsurf", "workflows");
220019
+ const wfDir = join28(this.projectRoot, ".windsurf", "workflows");
219217
220020
  if (!existsSync23(wfDir)) return workflows;
219218
220021
  try {
219219
220022
  const files = readdirSync4(wfDir).filter((f7) => f7.endsWith(".md"));
219220
220023
  for (const file2 of files) {
219221
220024
  try {
219222
- const content = readFileSync14(join27(wfDir, file2), "utf-8");
220025
+ const content = readFileSync14(join28(wfDir, file2), "utf-8");
219223
220026
  workflows.push(this.workflowSyncer.parseWindsurfWorkflow(file2, content));
219224
220027
  } catch {
219225
220028
  }
@@ -219494,7 +220297,7 @@ __export(behavior_exports, {
219494
220297
  resetBehaviorConfigCache: () => resetBehaviorConfigCache
219495
220298
  });
219496
220299
  import { existsSync as existsSync24, readFileSync as readFileSync15 } from "fs";
219497
- import { homedir as homedir32 } from "os";
220300
+ import { homedir as homedir33 } from "os";
219498
220301
  function isSessionInject(value) {
219499
220302
  return value === "full" || value === "minimal" || value === "silent";
219500
220303
  }
@@ -219512,7 +220315,7 @@ function legacyBehavior(homeDir) {
219512
220315
  }
219513
220316
  }
219514
220317
  function getBehaviorConfig(options = {}) {
219515
- const homeDir = options.homeDir ?? homedir32();
220318
+ const homeDir = options.homeDir ?? homedir33();
219516
220319
  const projectRoot = options.projectRoot === void 0 ? detectProject()?.rootPath ?? null : options.projectRoot;
219517
220320
  const cacheKey2 = `${homeDir}\0${projectRoot ?? ""}`;
219518
220321
  const cached2 = cache4.get(cacheKey2);
@@ -220944,7 +221747,7 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
220944
221747
  case "/config": {
220945
221748
  const os9 = await import("os");
220946
221749
  const { existsSync: existsSync34 } = await import("fs");
220947
- const { join: join34 } = await import("path");
221750
+ const { join: join35 } = await import("path");
220948
221751
  const configProjectRoot = effectiveProjectRoot;
220949
221752
  const resolved = getResolvedConfig({ projectRoot: configProjectRoot });
220950
221753
  const files = {
@@ -220959,13 +221762,13 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
220959
221762
  try {
220960
221763
  const home = os9.homedir();
220961
221764
  const paths = {
220962
- "project memorix.yml": configProjectRoot ? join34(configProjectRoot, "memorix.yml") : null,
220963
- "user memorix.yml": join34(home, ".memorix", "memorix.yml"),
220964
- "project memorix.toml": configProjectRoot ? join34(configProjectRoot, "memorix.toml") : null,
220965
- "user config.toml": join34(home, ".memorix", "config.toml"),
220966
- "project .env": configProjectRoot ? join34(configProjectRoot, ".env") : null,
220967
- "user .env": join34(home, ".memorix", ".env"),
220968
- "legacy config.json": join34(home, ".memorix", "config.json")
221765
+ "project memorix.yml": configProjectRoot ? join35(configProjectRoot, "memorix.yml") : null,
221766
+ "user memorix.yml": join35(home, ".memorix", "memorix.yml"),
221767
+ "project memorix.toml": configProjectRoot ? join35(configProjectRoot, "memorix.toml") : null,
221768
+ "user config.toml": join35(home, ".memorix", "config.toml"),
221769
+ "project .env": configProjectRoot ? join35(configProjectRoot, ".env") : null,
221770
+ "user .env": join35(home, ".memorix", ".env"),
221771
+ "legacy config.json": join35(home, ".memorix", "config.json")
220969
221772
  };
220970
221773
  for (const [key, fpath] of Object.entries(paths)) {
220971
221774
  if (fpath === null) {
@@ -263891,10 +264694,10 @@ ${Math.max(0, managedIds.size - result.resolved.length)} visible writable observ
263891
264694
  );
263892
264695
  let enableKG = isToolInProfile("create_entities", toolProfile);
263893
264696
  try {
263894
- const { homedir: homedir36 } = await import("os");
263895
- const { join: join34 } = await import("path");
264697
+ const { homedir: homedir37 } = await import("os");
264698
+ const { join: join35 } = await import("path");
263896
264699
  const { readFile: readFile10 } = await import("fs/promises");
263897
- const raw = await readFile10(join34(homedir36(), ".memorix", "settings.json"), "utf-8");
264700
+ const raw = await readFile10(join35(homedir37(), ".memorix", "settings.json"), "utf-8");
263898
264701
  const s4 = JSON.parse(raw);
263899
264702
  if (s4.knowledgeGraph === true) enableKG = true;
263900
264703
  } catch {
@@ -266275,6 +267078,81 @@ var init_server4 = __esm({
266275
267078
  }
266276
267079
  });
266277
267080
 
267081
+ // src/server/modern-mcp-bridge.ts
267082
+ var modern_mcp_bridge_exports = {};
267083
+ __export(modern_mcp_bridge_exports, {
267084
+ createModernMcpBridge: () => createModernMcpBridge
267085
+ });
267086
+ import {
267087
+ fromJsonSchema,
267088
+ McpServer as ModernMcpServer
267089
+ } from "@modelcontextprotocol/server";
267090
+ async function createModernMcpBridge(options) {
267091
+ const { createMemorixServer: createMemorixServer2 } = await Promise.resolve().then(() => (init_server4(), server_exports2));
267092
+ const legacy = await createMemorixServer2(
267093
+ options.projectRoot,
267094
+ void 0,
267095
+ void 0,
267096
+ {
267097
+ ...options,
267098
+ allowUntrackedFallback: options.allowUntrackedFallback ?? false,
267099
+ deferProjectInitUntilBound: options.deferProjectInitUntilBound ?? true,
267100
+ deferProjectRuntimeInit: options.deferProjectRuntimeInit ?? true
267101
+ }
267102
+ );
267103
+ const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
267104
+ const legacyClient = new Client({
267105
+ name: "memorix-modern-bridge",
267106
+ version: getMcpServerInfo().version
267107
+ });
267108
+ await legacy.server.connect(serverTransport);
267109
+ await legacyClient.connect(clientTransport);
267110
+ const listed = await legacyClient.listTools();
267111
+ const modern = new ModernMcpServer(getMcpServerInfo());
267112
+ for (const tool of listed.tools) {
267113
+ modern.registerTool(
267114
+ tool.name,
267115
+ {
267116
+ ...tool.title ? { title: tool.title } : {},
267117
+ ...tool.description ? { description: tool.description } : {},
267118
+ inputSchema: fromJsonSchema(tool.inputSchema)
267119
+ },
267120
+ async (args) => await legacyClient.callTool({
267121
+ name: tool.name,
267122
+ arguments: args
267123
+ })
267124
+ );
267125
+ }
267126
+ const bridge = modern;
267127
+ bridge.memorix = {
267128
+ projectId: legacy.projectId,
267129
+ deferredInit: legacy.deferredInit,
267130
+ switchProject: legacy.switchProject,
267131
+ isExplicitlyBound: legacy.isExplicitlyBound,
267132
+ handleTransportClose: legacy.handleTransportClose
267133
+ };
267134
+ let closed = false;
267135
+ const modernClose = modern.close.bind(modern);
267136
+ modern.close = async () => {
267137
+ if (closed) return;
267138
+ closed = true;
267139
+ await modernClose();
267140
+ await legacyClient.close().catch(() => void 0);
267141
+ await legacy.server.close().catch(() => void 0);
267142
+ legacy.handleTransportClose();
267143
+ };
267144
+ return bridge;
267145
+ }
267146
+ var init_modern_mcp_bridge = __esm({
267147
+ "src/server/modern-mcp-bridge.ts"() {
267148
+ "use strict";
267149
+ init_esm_shims();
267150
+ init_client4();
267151
+ init_inMemory();
267152
+ init_mcp_discovery();
267153
+ }
267154
+ });
267155
+
266278
267156
  // src/cli/commands/serve-shared.ts
266279
267157
  var serve_shared_exports = {};
266280
267158
  __export(serve_shared_exports, {
@@ -266392,8 +267270,8 @@ __export(update_checker_exports, {
266392
267270
  });
266393
267271
  import { execFile as execFile3 } from "child_process";
266394
267272
  import { readFile as readFile7, writeFile as writeFile8, mkdir as mkdir7 } from "fs/promises";
266395
- import { join as join28 } from "path";
266396
- import { homedir as homedir33 } from "os";
267273
+ import { join as join29 } from "path";
267274
+ import { homedir as homedir34 } from "os";
266397
267275
  function getCurrentVersion() {
266398
267276
  try {
266399
267277
  return getCliVersion();
@@ -266572,8 +267450,8 @@ var init_update_checker = __esm({
266572
267450
  MIN_AUTO_UPDATE_TIMEOUT_MS = 5e3;
266573
267451
  MAX_AUTO_UPDATE_TIMEOUT_MS = 30 * 60 * 1e3;
266574
267452
  REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
266575
- CACHE_DIR2 = join28(homedir33(), ".memorix");
266576
- CACHE_FILE2 = join28(CACHE_DIR2, "update-check.json");
267453
+ CACHE_DIR2 = join29(homedir34(), ".memorix");
267454
+ CACHE_FILE2 = join29(CACHE_DIR2, "update-check.json");
266577
267455
  _testing = {
266578
267456
  CACHE_FILE: CACHE_FILE2,
266579
267457
  CHECK_INTERVAL_MS,
@@ -266628,6 +267506,14 @@ var init_serve = __esm({
266628
267506
  }
266629
267507
  },
266630
267508
  run: async ({ args }) => {
267509
+ const { serveStdio, StdioServerTransport } = await import("@modelcontextprotocol/server/stdio");
267510
+ const { createModernMcpBridge: createModernMcpBridge2 } = await Promise.resolve().then(() => (init_modern_mcp_bridge(), modern_mcp_bridge_exports));
267511
+ const { detectProject: detectProject2, findGitInSubdirs: findGitInSubdirs2, isSystemDirectory: isSystemDirectory2 } = await Promise.resolve().then(() => (init_detector(), detector_exports));
267512
+ const { homedir: homedir37 } = await import("os");
267513
+ const { writeLastProjectRoot: writeLastProjectRoot2 } = await Promise.resolve().then(() => (init_launch_root(), launch_root_exports));
267514
+ const { resolveServeProject: resolveServeProject2 } = await Promise.resolve().then(() => (init_serve_shared(), serve_shared_exports));
267515
+ let stdioHandle;
267516
+ let stdinEndedBeforeHandle = false;
266631
267517
  const startupGate = new StdioStartupGate({
266632
267518
  stdin: process.stdin,
266633
267519
  stdout: process.stdout,
@@ -266637,21 +267523,22 @@ var init_serve = __esm({
266637
267523
  process.exit(1);
266638
267524
  },
266639
267525
  onEnd: () => {
266640
- console.error("[memorix] stdin closed \u2014 exiting");
266641
- process.exitCode = 0;
267526
+ console.error("[memorix] stdin closed - exiting");
267527
+ if (stdioHandle) {
267528
+ void stdioHandle.close().catch((error40) => {
267529
+ console.error(`[memorix] stdio close error: ${error40 instanceof Error ? error40.message : String(error40)}`);
267530
+ });
267531
+ } else {
267532
+ stdinEndedBeforeHandle = true;
267533
+ }
266642
267534
  }
266643
267535
  });
266644
267536
  startupGate.start();
266645
- const { StdioServerTransport: StdioServerTransport2 } = await Promise.resolve().then(() => (init_stdio2(), stdio_exports));
266646
- const { createMemorixServer: createMemorixServer2 } = await Promise.resolve().then(() => (init_server4(), server_exports2));
266647
- const { detectProject: detectProject2, findGitInSubdirs: findGitInSubdirs2, isSystemDirectory: isSystemDirectory2 } = await Promise.resolve().then(() => (init_detector(), detector_exports));
266648
- const { homedir: homedir36 } = await import("os");
266649
- const { resolveServeProject: resolveServeProject2 } = await Promise.resolve().then(() => (init_serve_shared(), serve_shared_exports));
266650
267537
  let safeCwd;
266651
267538
  try {
266652
267539
  safeCwd = process.cwd();
266653
267540
  } catch {
266654
- safeCwd = homedir36();
267541
+ safeCwd = homedir37();
266655
267542
  }
266656
267543
  const resolution = resolveServeProject2(
266657
267544
  {
@@ -266659,74 +267546,86 @@ var init_serve = __esm({
266659
267546
  envProjectRoot: process.env.MEMORIX_PROJECT_ROOT,
266660
267547
  initCwd: process.env.INIT_CWD,
266661
267548
  processCwd: safeCwd,
266662
- homeDir: homedir36()
267549
+ homeDir: homedir37()
266663
267550
  },
266664
267551
  { detectProject: detectProject2, findGitInSubdirs: findGitInSubdirs2, isSystemDirectory: isSystemDirectory2 }
266665
267552
  );
266666
- for (const message of resolution.messages) {
266667
- console.error(message);
266668
- }
267553
+ for (const message of resolution.messages) console.error(message);
266669
267554
  if (!resolution.detectedProject) {
266670
267555
  console.error(`[memorix] [WARN] ${resolution.error}`);
266671
- console.error(`[memorix] Starting in deferred-binding mode \u2014 project will bind via MCP roots or memorix_session_start.`);
266672
- console.error(`[memorix] For non-git directories, use --allow-untracked to enable untracked/ fallback.`);
267556
+ console.error("[memorix] Starting in deferred-binding mode - bind with memorix_session_start(projectRoot=...) when needed.");
267557
+ console.error("[memorix] For non-git directories, use --allow-untracked to enable untracked/ fallback.");
266673
267558
  }
266674
267559
  const detected = resolution.detectedProject;
266675
267560
  const projectRoot = resolution.projectRoot;
266676
- if (detected) {
266677
- const { writeLastProjectRoot: writeLastProjectRoot2 } = await Promise.resolve().then(() => (init_launch_root(), launch_root_exports));
266678
- writeLastProjectRoot2(detected.rootPath);
266679
- }
267561
+ if (detected) writeLastProjectRoot2(detected.rootPath);
266680
267562
  const allowUntracked = args["allow-untracked"] ?? false;
266681
- const toolProfile = resolveToolProfile({ explicit: args.mode, envValue: process.env.MEMORIX_MODE, fallback: "micro" });
266682
- const serverOptions = detected ? { toolProfile, deferProjectRuntimeInit: true } : { allowUntrackedFallback: allowUntracked, deferProjectInitUntilBound: !allowUntracked, deferProjectRuntimeInit: true, toolProfile };
266683
- const { server, projectId, deferredInit, switchProject } = await createMemorixServer2(projectRoot, void 0, void 0, serverOptions);
266684
- const transport = new StdioServerTransport2(startupGate.input, process.stdout);
266685
- await server.connect(transport);
266686
- startupGate.markReady();
266687
- console.error(`[memorix] MCP Server running on stdio (project: ${projectId})`);
266688
- console.error(`[memorix] Project root: ${detected?.rootPath ?? projectRoot}`);
266689
- const tryRootsSwitch = async () => {
266690
- try {
266691
- const { roots } = await server.server.listRoots();
266692
- if (!roots || roots.length === 0) return;
266693
- for (const root of roots) {
266694
- if (!root.uri.startsWith("file://")) continue;
266695
- const rootPath = mcpFileUriToPath(root.uri);
266696
- if (!rootPath) continue;
266697
- const rootDetected = detectProject2(rootPath);
266698
- if (rootDetected) {
266699
- const switched = await switchProject(rootPath);
267563
+ const toolProfile = resolveToolProfile({
267564
+ explicit: args.mode,
267565
+ envValue: process.env.MEMORIX_MODE,
267566
+ fallback: "micro"
267567
+ });
267568
+ const transport = new StdioServerTransport(startupGate.input, process.stdout);
267569
+ const createBridge = async () => {
267570
+ const bridge = await createModernMcpBridge2({
267571
+ projectRoot,
267572
+ allowUntrackedFallback: allowUntracked,
267573
+ deferProjectInitUntilBound: !allowUntracked,
267574
+ deferProjectRuntimeInit: true,
267575
+ toolProfile
267576
+ });
267577
+ const tryRootsSwitch = async () => {
267578
+ try {
267579
+ if (bridge.memorix.isExplicitlyBound()) return;
267580
+ const { roots } = await bridge.server.listRoots();
267581
+ for (const root of roots ?? []) {
267582
+ if (!root.uri.startsWith("file://")) continue;
267583
+ const rootPath = mcpFileUriToPath(root.uri);
267584
+ if (!rootPath) continue;
267585
+ const switched = await bridge.memorix.switchProject(rootPath, "mcp-roots");
266700
267586
  if (switched) {
266701
- console.error(`[memorix] [UPDATED] Project updated via MCP roots: ${rootDetected.id}`);
267587
+ console.error(`[memorix] [UPDATED] Project updated via MCP roots: ${rootPath}`);
267588
+ return;
266702
267589
  }
266703
- return;
266704
- }
266705
- const subGit = findGitInSubdirs2(rootPath);
266706
- if (subGit) {
266707
- const switched = await switchProject(subGit);
266708
- if (switched) {
267590
+ const subGit = findGitInSubdirs2(rootPath);
267591
+ if (subGit && await bridge.memorix.switchProject(subGit, "mcp-roots")) {
266709
267592
  console.error(`[memorix] [UPDATED] Project updated via MCP roots (subdir): ${subGit}`);
267593
+ return;
266710
267594
  }
266711
- return;
266712
267595
  }
267596
+ } catch (error40) {
267597
+ console.error(`[memorix] MCP roots not available (${error40 instanceof Error ? error40.message : "unsupported"})`);
266713
267598
  }
266714
- } catch (err) {
266715
- console.error(`[memorix] MCP roots not available (${err.message ?? "unsupported"})`);
266716
- }
266717
- };
266718
- try {
266719
- const { RootsListChangedNotificationSchema: RootsListChangedNotificationSchema2 } = await Promise.resolve().then(() => (init_types8(), types_exports3));
266720
- server.server.setNotificationHandler(RootsListChangedNotificationSchema2, async () => {
266721
- console.error(`[memorix] Roots changed \u2014 re-detecting project...`);
267599
+ };
267600
+ bridge.server.setNotificationHandler("notifications/roots/list_changed", async () => {
266722
267601
  await tryRootsSwitch();
266723
267602
  });
266724
- } catch {
267603
+ const deferredInitTimer = setTimeout(() => {
267604
+ bridge.memorix.deferredInit().catch((error40) => {
267605
+ console.error(`[memorix] Deferred init error: ${error40 instanceof Error ? error40.message : String(error40)}`);
267606
+ });
267607
+ }, 5e3);
267608
+ deferredInitTimer.unref?.();
267609
+ const originalClose = bridge.close.bind(bridge);
267610
+ bridge.close = async () => {
267611
+ clearTimeout(deferredInitTimer);
267612
+ await originalClose();
267613
+ };
267614
+ return bridge;
267615
+ };
267616
+ stdioHandle = serveStdio(createBridge, {
267617
+ transport,
267618
+ legacy: "serve",
267619
+ onerror: (error40) => console.error(`[memorix] stdio MCP error: ${error40.message}`)
267620
+ });
267621
+ startupGate.markReady();
267622
+ if (stdinEndedBeforeHandle) {
267623
+ void stdioHandle.close().catch((error40) => {
267624
+ console.error(`[memorix] stdio close error: ${error40 instanceof Error ? error40.message : String(error40)}`);
267625
+ });
266725
267626
  }
266726
- const deferredInitTimer = setTimeout(() => {
266727
- deferredInit().catch((e5) => console.error(`[memorix] Deferred init error:`, e5));
266728
- }, 5e3);
266729
- deferredInitTimer.unref?.();
267627
+ console.error(`[memorix] MCP Server running on stdio (profile: ${toolProfile}, project: ${detected?.id ?? "deferred"})`);
267628
+ console.error(`[memorix] Project root: ${detected?.rootPath ?? projectRoot}`);
266730
267629
  Promise.resolve().then(() => (init_update_checker(), update_checker_exports)).then((m6) => m6.checkForUpdates()).catch(() => {
266731
267630
  });
266732
267631
  }
@@ -266743,15 +267642,17 @@ function getMcpDiagnostics() {
266743
267642
  legacy: LEGACY_MCP_PROTOCOL_VERSION,
266744
267643
  discovery: "supported",
266745
267644
  versionlessRequests: "legacy-compatible",
266746
- modernResultMetadata: "discovery-only",
266747
- statelessRequests: "compatibility-only",
267645
+ modernResultMetadata: "supported",
267646
+ statelessRequests: "supported",
266748
267647
  statefulStreamableHttp: "supported"
266749
267648
  },
266750
267649
  capabilities: {
266751
267650
  tasks: "unsupported",
266752
267651
  polling: "unsupported",
266753
- subscriptions: "unsupported",
266754
- listCache: "unsupported",
267652
+ subscriptions: "supported",
267653
+ // The protocol envelope is emitted, but TTL is intentionally zero until
267654
+ // Memorix can invalidate a durable per-project list cache correctly.
267655
+ listCache: "protocol-hints-only",
266755
267656
  explicitProjectHandle: "supported"
266756
267657
  }
266757
267658
  };
@@ -269040,6 +269941,7 @@ var init_serve_http = __esm({
269040
269941
  init_retention();
269041
269942
  init_visibility();
269042
269943
  init_mcp_diagnostics();
269944
+ init_mcp_discovery();
269043
269945
  init_port();
269044
269946
  init_mcp_root_path();
269045
269947
  DEFAULT_SESSION_TIMEOUT_MS = 12 * 60 * 60 * 1e3;
@@ -269081,9 +269983,12 @@ var init_serve_http = __esm({
269081
269983
  const { createProjectBindingController: createProjectBindingController2 } = await Promise.resolve().then(() => (init_request_context(), request_context_exports));
269082
269984
  const { findGitInSubdirs: findGitInSubdirs2 } = await Promise.resolve().then(() => (init_detector(), detector_exports));
269083
269985
  const { writeFileSync: writeFileSync12, mkdirSync: mkdirSync12 } = await import("fs");
269084
- const { homedir: homedir36 } = await import("os");
269986
+ const { homedir: homedir37 } = await import("os");
269085
269987
  const { McpBindingStore: McpBindingStore2 } = await Promise.resolve().then(() => (init_mcp_binding_store(), mcp_binding_store_exports));
269086
269988
  const { MemoryFeedbackStore: MemoryFeedbackStore2 } = await Promise.resolve().then(() => (init_feedback(), feedback_exports));
269989
+ const { createModernMcpBridge: createModernMcpBridge2 } = await Promise.resolve().then(() => (init_modern_mcp_bridge(), modern_mcp_bridge_exports));
269990
+ const { createMcpHandler } = await import("@modelcontextprotocol/server");
269991
+ const { toNodeHandler } = await import("@modelcontextprotocol/node");
269087
269992
  let configuredDefaults = {};
269088
269993
  try {
269089
269994
  const { getServerConfig: getServerConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
@@ -269099,7 +270004,7 @@ var init_serve_http = __esm({
269099
270004
  try {
269100
270005
  safeCwd = process.cwd();
269101
270006
  } catch {
269102
- safeCwd = homedir36();
270007
+ safeCwd = homedir37();
269103
270008
  }
269104
270009
  const { resolveServeProject: resolveServeProject2 } = await Promise.resolve().then(() => (init_serve_shared(), serve_shared_exports));
269105
270010
  const { writeLastProjectRoot: writeLastProjectRoot2 } = await Promise.resolve().then(() => (init_launch_root(), launch_root_exports));
@@ -269110,7 +270015,7 @@ var init_serve_http = __esm({
269110
270015
  cwdArg: args.cwd,
269111
270016
  envProjectRoot: process.env.MEMORIX_PROJECT_ROOT,
269112
270017
  processCwd: safeCwd,
269113
- homeDir: homedir36()
270018
+ homeDir: homedir37()
269114
270019
  },
269115
270020
  { detectProject: detectorMod.detectProject, findGitInSubdirs: detectorMod.findGitInSubdirs, isSystemDirectory: detectorMod.isSystemDirectory }
269116
270021
  );
@@ -269138,6 +270043,27 @@ var init_serve_http = __esm({
269138
270043
  }
269139
270044
  const statelessBindingStore = new McpBindingStore2();
269140
270045
  await statelessBindingStore.init(persistMod.getBaseDataDir());
270046
+ const modernMcpHandler = createMcpHandler(async ({ requestInfo }) => {
270047
+ const handleId = requestInfo?.headers.get("mcp-project-handle") ?? void 0;
270048
+ const persisted = handleId ? statelessBindingStore.touch(handleId) : void 0;
270049
+ const requestedRoot = requestInfo?.headers.get("mcp-project-root") ?? void 0;
270050
+ const root = persisted?.projectRoot ?? requestedRoot ?? projectRoot;
270051
+ return createModernMcpBridge2({
270052
+ projectRoot: root,
270053
+ allowUntrackedFallback: false,
270054
+ deferProjectInitUntilBound: true,
270055
+ deferProjectRuntimeInit: true,
270056
+ dashboardMode: "control-plane",
270057
+ dashboardPort: port,
270058
+ toolProfile
270059
+ });
270060
+ }, {
270061
+ // Legacy requests are routed to the existing sessionful implementation
270062
+ // below; this handler is strict modern-only by construction.
270063
+ legacy: "reject",
270064
+ responseMode: "auto"
270065
+ });
270066
+ const modernNodeHandler = toNodeHandler(modernMcpHandler);
269141
270067
  const sessions = /* @__PURE__ */ new Map();
269142
270068
  const sessionLastActivity = /* @__PURE__ */ new Map();
269143
270069
  const expiredSessions = /* @__PURE__ */ new Map();
@@ -269283,78 +270209,34 @@ var init_serve_http = __esm({
269283
270209
  res.setHeader("Mcp-Method", req.method || "UNKNOWN");
269284
270210
  res.setHeader("Mcp-Name", MCP_SERVER_NAME);
269285
270211
  }
269286
- async function handleStatelessPost(req, res, body) {
269287
- const handleId = typeof req.headers["mcp-project-handle"] === "string" ? req.headers["mcp-project-handle"] : void 0;
269288
- const persisted = handleId ? statelessBindingStore.touch(handleId) : void 0;
269289
- if (handleId && !persisted) {
269290
- res.writeHead(404, { "Content-Type": "application/json" });
269291
- res.end(JSON.stringify({ jsonrpc: "2.0", error: { code: -32001, message: "MCP project handle not found or expired; initialize again." }, id: null }));
269292
- return;
269293
- }
269294
- const requestedRoot = typeof req.headers["mcp-project-root"] === "string" ? req.headers["mcp-project-root"] : void 0;
269295
- const root = persisted?.projectRoot ?? requestedRoot ?? projectRoot;
269296
- const { createMemorixServer: createMemorixServer3 } = await Promise.resolve().then(() => (init_server4(), server_exports2));
269297
- const { createProjectBindingController: createProjectBindingController3 } = await Promise.resolve().then(() => (init_request_context(), request_context_exports));
269298
- const binding = createProjectBindingController3(root);
269299
- const { server, projectId, handleTransportClose } = await createMemorixServer3(
269300
- root,
269301
- void 0,
269302
- void 0,
269303
- {
269304
- allowUntrackedFallback: false,
269305
- deferProjectInitUntilBound: true,
269306
- deferProjectRuntimeInit: true,
269307
- dashboardMode: "control-plane",
269308
- dashboardPort: port,
269309
- toolProfile,
269310
- projectBinding: binding
269311
- }
269312
- );
269313
- const transport = new StreamableHTTPServerTransport2({
269314
- // No Mcp-Session-Id: the protocol state is carried by our explicit
269315
- // durable project handle and reconstructed on every request.
269316
- sessionIdGenerator: void 0,
269317
- enableJsonResponse: true
269318
- });
269319
- try {
269320
- await server.connect(transport);
269321
- let effectiveHandle = persisted;
269322
- if (!effectiveHandle && projectId !== "__unresolved__" && isInitializeRequest2(body)) {
269323
- effectiveHandle = statelessBindingStore.create({
269324
- projectId,
269325
- projectRoot: root,
269326
- dataDir: await persistMod.getProjectDataDir(projectId)
269327
- });
269328
- }
269329
- if (effectiveHandle) res.setHeader("Mcp-Project-Handle", effectiveHandle.handleId);
269330
- const sdkBody = body && typeof body === "object" ? JSON.parse(JSON.stringify(body)) : body;
269331
- const sdkRequest = sdkBody;
269332
- if (sdkRequest && typeof sdkRequest === "object" && sdkRequest.method === "initialize" && sdkRequest.params) {
269333
- sdkRequest.params.protocolVersion = MCP_SDK_COMPAT_PROTOCOL_VERSION;
269334
- }
269335
- if (req.headers["mcp-protocol-version"]) {
269336
- req.headers["mcp-protocol-version"] = MCP_SDK_COMPAT_PROTOCOL_VERSION;
269337
- for (let i4 = 0; i4 < req.rawHeaders.length; i4 += 2) {
269338
- if (req.rawHeaders[i4].toLowerCase() === "mcp-protocol-version") {
269339
- req.rawHeaders[i4 + 1] = MCP_SDK_COMPAT_PROTOCOL_VERSION;
269340
- break;
269341
- }
269342
- }
269343
- }
269344
- patchMcpResponse(res);
269345
- await transport.handleRequest(req, res, sdkBody);
269346
- } finally {
269347
- handleTransportClose();
269348
- await transport.close().catch(() => void 0);
269349
- }
269350
- }
269351
270212
  async function handlePost(req, res) {
269352
270213
  const sessionId = req.headers["mcp-session-id"];
269353
270214
  const body = await parseBody(req);
270215
+ const params = body && typeof body === "object" && !Array.isArray(body) ? body.params : void 0;
270216
+ const claimlessDiscovery = !sessionId && isServerDiscoverRequest(body) && !req.headers["mcp-protocol-version"] && !req.headers["mcp-method"] && req.headers["mcp-stateless"] !== "true" && (params === void 0 || typeof params === "object" && params !== null && !Array.isArray(params) && !Object.prototype.hasOwnProperty.call(params, "_meta"));
270217
+ if (claimlessDiscovery) {
270218
+ res.writeHead(200, { "Content-Type": "application/json" });
270219
+ res.end(JSON.stringify({
270220
+ jsonrpc: "2.0",
270221
+ id: body.id ?? null,
270222
+ result: createMcpStartupDiscoverResult(getMcpServerInfo())
270223
+ }));
270224
+ return;
270225
+ }
269354
270226
  const requestedProtocol = req.headers["mcp-protocol-version"];
269355
270227
  const statelessRequested = req.headers["mcp-stateless"] === "true" || requestedProtocol === CURRENT_MCP_PROTOCOL_VERSION || typeof req.headers["mcp-project-handle"] === "string" || isServerDiscoverRequest(body);
269356
270228
  if (!sessionId && statelessRequested) {
269357
- await handleStatelessPost(req, res, body);
270229
+ const handleId = typeof req.headers["mcp-project-handle"] === "string" ? req.headers["mcp-project-handle"] : void 0;
270230
+ if (handleId && !statelessBindingStore.touch(handleId)) {
270231
+ res.writeHead(404, { "Content-Type": "application/json" });
270232
+ res.end(JSON.stringify({
270233
+ jsonrpc: "2.0",
270234
+ error: { code: -32001, message: "MCP project handle not found or expired; initialize again." },
270235
+ id: null
270236
+ }));
270237
+ return;
270238
+ }
270239
+ await modernNodeHandler(req, res, body);
269358
270240
  return;
269359
270241
  }
269360
270242
  if (sessionId && sessions.has(sessionId)) {
@@ -270010,7 +270892,7 @@ var init_serve_http = __esm({
270010
270892
  const { projectId: configProjectId } = await resolveRequestProject(url2);
270011
270893
  const os9 = await import("os");
270012
270894
  const { existsSync: existsSync34 } = await import("fs");
270013
- const { join: join34 } = await import("path");
270895
+ const { join: join35 } = await import("path");
270014
270896
  const { loadYamlConfig: loadYamlConfig2 } = await Promise.resolve().then(() => (init_yaml_loader(), yaml_loader_exports));
270015
270897
  const { loadFileConfig: loadFileConfig2, loadDotenv: loadDotenv2, getLoadedEnvFiles: getLoadedEnvFiles2 } = await Promise.resolve().then(() => (init_config(), config_exports));
270016
270898
  const isStartupProject = configProjectId === defaultProject.id;
@@ -270024,11 +270906,11 @@ var init_serve_http = __esm({
270024
270906
  const home = os9.homedir();
270025
270907
  if (effectiveRoot) {
270026
270908
  const paths = {
270027
- "project memorix.yml": join34(effectiveRoot, "memorix.yml"),
270028
- "user memorix.yml": join34(home, ".memorix", "memorix.yml"),
270029
- "project .env": join34(effectiveRoot, ".env"),
270030
- "user .env": join34(home, ".memorix", ".env"),
270031
- "legacy config.json": join34(home, ".memorix", "config.json")
270909
+ "project memorix.yml": join35(effectiveRoot, "memorix.yml"),
270910
+ "user memorix.yml": join35(home, ".memorix", "memorix.yml"),
270911
+ "project .env": join35(effectiveRoot, ".env"),
270912
+ "user .env": join35(home, ".memorix", ".env"),
270913
+ "legacy config.json": join35(home, ".memorix", "config.json")
270032
270914
  };
270033
270915
  for (const [key, fpath] of Object.entries(paths)) {
270034
270916
  files[key] = { exists: existsSync34(fpath), path: fpath };
@@ -270037,9 +270919,9 @@ var init_serve_http = __esm({
270037
270919
  files["project memorix.yml"] = { exists: false, path: "unavailable", unavailable: true };
270038
270920
  files["project .env"] = { exists: false, path: "unavailable", unavailable: true };
270039
270921
  const userPaths = {
270040
- "user memorix.yml": join34(home, ".memorix", "memorix.yml"),
270041
- "user .env": join34(home, ".memorix", ".env"),
270042
- "legacy config.json": join34(home, ".memorix", "config.json")
270922
+ "user memorix.yml": join35(home, ".memorix", "memorix.yml"),
270923
+ "user .env": join35(home, ".memorix", ".env"),
270924
+ "legacy config.json": join35(home, ".memorix", "config.json")
270043
270925
  };
270044
270926
  for (const [key, fpath] of Object.entries(userPaths)) {
270045
270927
  files[key] = { exists: existsSync34(fpath), path: fpath };
@@ -270316,6 +271198,7 @@ var init_serve_http = __esm({
270316
271198
  sendJson2({ error: err instanceof Error ? err.message : "Unknown error" }, 500);
270317
271199
  }
270318
271200
  }
271201
+ let httpReadyAt = null;
270319
271202
  const httpServer = createServer3(async (req, res) => {
270320
271203
  setCorsHeaders(req, res);
270321
271204
  if (req.method === "OPTIONS") {
@@ -270330,9 +271213,13 @@ var init_serve_http = __esm({
270330
271213
  res.end(JSON.stringify({
270331
271214
  status: "ok",
270332
271215
  mode: "control-plane",
271216
+ profile: toolProfile,
270333
271217
  port,
270334
271218
  uptime: Math.round(process.uptime()),
270335
271219
  pid: process.pid,
271220
+ projectId: defaultProject?.id ?? "__unresolved__",
271221
+ projectName: defaultProject?.name ?? null,
271222
+ readyAt: httpReadyAt,
270336
271223
  embedding: getEmbeddingRuntimeHealth2()
270337
271224
  }));
270338
271225
  return;
@@ -270399,6 +271286,7 @@ var init_serve_http = __esm({
270399
271286
  httpServer.keepAliveTimeout = 6e4;
270400
271287
  httpServer.headersTimeout = 65e3;
270401
271288
  httpServer.listen(port, host, () => {
271289
+ httpReadyAt = (/* @__PURE__ */ new Date()).toISOString();
270402
271290
  try {
270403
271291
  const memorixDir = (process.env.HOME || process.env.USERPROFILE || "").replace(/\\/g, "/") + "/.memorix";
270404
271292
  mkdirSync12(memorixDir, { recursive: true });
@@ -272873,6 +273761,7 @@ var init_types9 = __esm({
272873
273761
  opencode: "community",
272874
273762
  trae: "community",
272875
273763
  dsh: "community",
273764
+ workbuddy: "community",
272876
273765
  pi: "community",
272877
273766
  omp: "community",
272878
273767
  antigravity: "community"
@@ -272893,8 +273782,14 @@ async function installSingleAgent2(agent, cwd, global2) {
272893
273782
  cwd,
272894
273783
  global2
272895
273784
  );
272896
- console.log(`[OK] ${agent}: hooks installed -> ${config2.configPath}`);
273785
+ const note = config2.generated?.note;
273786
+ if (config2.configPath) {
273787
+ console.log(`[OK] ${agent}: hooks installed -> ${config2.configPath}`);
273788
+ } else {
273789
+ console.log(`[OK] ${agent}: no hooks installed at this scope (MCP-only integration)`);
273790
+ }
272897
273791
  console.log(` Events: ${config2.events.join(", ")}`);
273792
+ if (!config2.configPath && note) console.log(` Note: ${note}`);
272898
273793
  if (agent === "copilot" && process.platform === "win32") {
272899
273794
  try {
272900
273795
  const { execSync: execSync5 } = await import("child_process");
@@ -272910,7 +273805,6 @@ async function installSingleAgent2(agent, cwd, global2) {
272910
273805
  }
272911
273806
  }
272912
273807
  if (agent === "copilot" && global2) {
272913
- const note = config2.generated?.note;
272914
273808
  if (note) console.warn(`[WARN] ${note}`);
272915
273809
  }
272916
273810
  } catch (err) {
@@ -272932,7 +273826,8 @@ function getAgentLabel2(agent) {
272932
273826
  hermes: "Hermes Agent",
272933
273827
  omp: "Oh-my-Pi",
272934
273828
  trae: "Trae",
272935
- dsh: "DeepSeek Harness"
273829
+ dsh: "DeepSeek Harness",
273830
+ workbuddy: "WorkBuddy"
272936
273831
  };
272937
273832
  return labels[agent] || agent;
272938
273833
  }
@@ -272951,6 +273846,7 @@ function getAgentHint2(agent) {
272951
273846
  omp: "Oh-my-Pi package hooks; use `memorix setup --agent omp`",
272952
273847
  trae: ".trae/rules/project_rules.md (rules only, no hooks system)",
272953
273848
  dsh: "~/.dsh/cordis.patch.yml MCP row via `memorix setup --agent dsh` (no hooks system)",
273849
+ workbuddy: "~/.workbuddy/mcp.json MCP row via `memorix setup --agent workbuddy` (no hooks system)",
272954
273850
  codex: "Codex plugin hooks; use `memorix setup --agent codex`"
272955
273851
  };
272956
273852
  return hints[agent] || "";
@@ -273059,7 +273955,8 @@ function estimateFileSize(agent, configPath) {
273059
273955
  antigravity: "~2KB",
273060
273956
  opencode: "~3KB",
273061
273957
  trae: "~1KB",
273062
- dsh: "~1KB"
273958
+ dsh: "~1KB",
273959
+ workbuddy: "~1KB"
273063
273960
  };
273064
273961
  return sizes[agent] || "~2KB";
273065
273962
  }
@@ -273079,6 +273976,8 @@ function getRulesPath(agent, cwd, global2) {
273079
273976
  return path42.join(home, ".trae", "rules", "project_rules.md");
273080
273977
  case "dsh":
273081
273978
  return path42.join(process.env.DSH_HOME?.trim() || path42.join(home, ".dsh"), "AGENTS.md");
273979
+ case "workbuddy":
273980
+ return "";
273082
273981
  default:
273083
273982
  return "";
273084
273983
  }
@@ -273096,6 +273995,8 @@ function getRulesPath(agent, cwd, global2) {
273096
273995
  return path42.join(cwd, ".trae", "rules", "project_rules.md");
273097
273996
  case "dsh":
273098
273997
  return path42.join(cwd, "AGENTS.md");
273998
+ case "workbuddy":
273999
+ return path42.join(cwd, "AGENTS.md");
273099
274000
  default:
273100
274001
  return "";
273101
274002
  }
@@ -275000,6 +275901,9 @@ function getStateFilePath() {
275000
275901
  function getLogFilePath() {
275001
275902
  return getMemorixDir() + "/background.log";
275002
275903
  }
275904
+ function getBackgroundLockPath() {
275905
+ return getMemorixDir() + "/background.lock";
275906
+ }
275003
275907
  function parseBoundedPositiveInteger(value, fallback, label, maximum) {
275004
275908
  const raw = value ?? String(fallback);
275005
275909
  if (!/^[0-9]+$/u.test(raw)) {
@@ -275163,25 +276067,82 @@ async function startWindowsBackgroundService(options) {
275163
276067
  });
275164
276068
  }
275165
276069
  async function healthCheck(port, timeoutMs = 3e3) {
276070
+ const controller = new AbortController();
276071
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
275166
276072
  try {
275167
- const controller = new AbortController();
275168
- const timer = setTimeout(() => controller.abort(), timeoutMs);
275169
276073
  const res = await fetch(`http://127.0.0.1:${port}/health`, {
275170
276074
  signal: controller.signal
275171
276075
  });
275172
- clearTimeout(timer);
275173
276076
  if (!res.ok) return { ok: false, error: `HTTP ${res.status}` };
275174
276077
  const data = await res.json();
275175
276078
  return { ok: true, data };
275176
276079
  } catch (err) {
275177
276080
  return { ok: false, error: err instanceof Error ? err.message : "Unknown error" };
276081
+ } finally {
276082
+ clearTimeout(timer);
275178
276083
  }
275179
276084
  }
275180
276085
  async function isPortInUse(port) {
275181
276086
  const health = await healthCheck(port, 1500);
275182
276087
  return health.ok;
275183
276088
  }
275184
- async function doStart(port) {
276089
+ async function acquireBackgroundLock(lockPath, staleMs = BACKGROUND_LOCK_STALE_MS, timeoutMs = BACKGROUND_LOCK_ACQUIRE_TIMEOUT_MS) {
276090
+ const lockDir = path44.dirname(lockPath);
276091
+ if (!fs26.existsSync(lockDir)) fs26.mkdirSync(lockDir, { recursive: true });
276092
+ const deadline = Date.now() + timeoutMs;
276093
+ while (Date.now() < deadline) {
276094
+ try {
276095
+ const fd = fs26.openSync(lockPath, "wx");
276096
+ const token = `${process.pid}:${randomBytes2(12).toString("hex")}`;
276097
+ fs26.writeSync(fd, JSON.stringify({ pid: process.pid, acquiredAt: Date.now(), token }));
276098
+ const heartbeat = setInterval(() => {
276099
+ try {
276100
+ const now3 = /* @__PURE__ */ new Date();
276101
+ fs26.futimesSync(fd, now3, now3);
276102
+ } catch {
276103
+ }
276104
+ }, BACKGROUND_LOCK_HEARTBEAT_MS);
276105
+ heartbeat.unref();
276106
+ return { fd, acquired: true, path: lockPath, token, heartbeat };
276107
+ } catch (err) {
276108
+ if (!(err && err.code === "EEXIST")) throw err;
276109
+ try {
276110
+ if (Date.now() - fs26.statSync(lockPath).mtimeMs > staleMs) {
276111
+ let ownerAlive = false;
276112
+ try {
276113
+ const raw = fs26.readFileSync(lockPath, "utf8");
276114
+ const owner = JSON.parse(raw);
276115
+ ownerAlive = typeof owner.pid === "number" && owner.pid > 0 && isProcessRunning(owner.pid);
276116
+ } catch {
276117
+ }
276118
+ if (!ownerAlive) {
276119
+ fs26.unlinkSync(lockPath);
276120
+ continue;
276121
+ }
276122
+ }
276123
+ } catch {
276124
+ }
276125
+ await new Promise((resolve6) => setTimeout(resolve6, 200));
276126
+ }
276127
+ }
276128
+ throw new Error(
276129
+ `Another Memorix background start is still in progress (${lockPath}). Wait a few seconds and retry; no second control plane was started.`
276130
+ );
276131
+ }
276132
+ function releaseBackgroundLock(lock) {
276133
+ if (!lock.acquired) return;
276134
+ if (lock.heartbeat) clearInterval(lock.heartbeat);
276135
+ try {
276136
+ if (lock.fd !== null) fs26.closeSync(lock.fd);
276137
+ } catch {
276138
+ }
276139
+ try {
276140
+ const current = JSON.parse(fs26.readFileSync(lock.path, "utf8"));
276141
+ if (current.token === lock.token) fs26.unlinkSync(lock.path);
276142
+ } catch {
276143
+ }
276144
+ }
276145
+ async function doStartUnlocked(port) {
275185
276146
  const state = loadState();
275186
276147
  if (state) {
275187
276148
  if (isProcessRunning(state.pid)) {
@@ -275334,6 +276295,14 @@ async function doStart(port) {
275334
276295
  ].join("\n");
275335
276296
  process.stderr.write(footer + "\n");
275336
276297
  }
276298
+ async function doStart(port) {
276299
+ const lock = await acquireBackgroundLock(getBackgroundLockPath());
276300
+ try {
276301
+ await doStartUnlocked(port);
276302
+ } finally {
276303
+ releaseBackgroundLock(lock);
276304
+ }
276305
+ }
275337
276306
  async function doStop() {
275338
276307
  const state = loadState();
275339
276308
  if (!state) {
@@ -275393,11 +276362,22 @@ async function doStop() {
275393
276362
  }
275394
276363
  console.log("[OK] Control plane stopped.");
275395
276364
  }
275396
- async function doStatus() {
276365
+ async function doStatus(asJson = false) {
275397
276366
  const state = loadState();
275398
276367
  if (!state) {
275399
276368
  const portHealth = await healthCheck(3211, 2e3);
275400
276369
  if (portHealth.ok) {
276370
+ if (asJson) {
276371
+ console.log(JSON.stringify({
276372
+ status: "unmanaged",
276373
+ managed: false,
276374
+ port: 3211,
276375
+ dashboard: "http://127.0.0.1:3211/",
276376
+ mcp: "http://127.0.0.1:3211/mcp",
276377
+ health: portHealth.data ?? null
276378
+ }, null, 2));
276379
+ return;
276380
+ }
275401
276381
  console.log("");
275402
276382
  console.log("No background control plane is registered,");
275403
276383
  console.log('but a Memorix instance IS running on port 3211 (likely a foreground "memorix serve-http").');
@@ -275417,6 +276397,10 @@ async function doStatus() {
275417
276397
  console.log(' 2. Run "memorix background start"');
275418
276398
  console.log("");
275419
276399
  } else {
276400
+ if (asJson) {
276401
+ console.log(JSON.stringify({ status: "stopped", managed: false, port: 3211 }, null, 2));
276402
+ return;
276403
+ }
275420
276404
  console.log("No background control plane is registered.");
275421
276405
  console.log("");
275422
276406
  console.log("Start one with: memorix background start");
@@ -275427,6 +276411,30 @@ async function doStatus() {
275427
276411
  const health = running ? await healthCheck(state.port) : { ok: false, error: "Process not running" };
275428
276412
  const pidMismatch = health.ok && health.data?.pid && health.data.pid !== state.pid;
275429
276413
  const probablyReused = running && !health.ok;
276414
+ const status = health.ok && !pidMismatch ? "running" : pidMismatch ? "pid-mismatch" : probablyReused ? "pid-reused" : running ? "starting" : "stopped";
276415
+ if (asJson) {
276416
+ if (pidMismatch || probablyReused || !running) {
276417
+ clearState();
276418
+ try {
276419
+ fs26.unlinkSync(getMemorixDir() + "/background.ready");
276420
+ } catch {
276421
+ }
276422
+ }
276423
+ console.log(JSON.stringify({
276424
+ status,
276425
+ managed: true,
276426
+ pid: state.pid,
276427
+ port: state.port,
276428
+ startedAt: state.startedAt,
276429
+ instance: state.instanceToken ? `${state.instanceToken.slice(0, 8)}\u2026` : null,
276430
+ dashboard: `http://127.0.0.1:${state.port}/`,
276431
+ mcp: `http://127.0.0.1:${state.port}/mcp`,
276432
+ logFile: normalizePath3(state.logFile),
276433
+ health: health.ok ? health.data ?? null : null,
276434
+ error: health.ok ? null : health.error ?? (running ? "Health check failed" : "Process not running")
276435
+ }, null, 2));
276436
+ return;
276437
+ }
275430
276438
  console.log("");
275431
276439
  console.log("Memorix Background Control Plane");
275432
276440
  console.log("================================");
@@ -275446,6 +276454,9 @@ async function doStatus() {
275446
276454
  console.log(` PID: ${d4.pid ?? "unknown"}`);
275447
276455
  console.log(` Uptime: ${d4.uptime ?? 0}s`);
275448
276456
  console.log(` Mode: ${d4.mode ?? "unknown"}`);
276457
+ console.log(` Profile: ${d4.profile ?? "unknown"}`);
276458
+ console.log(` Project: ${d4.projectId ?? "unresolved"}${d4.projectName ? ` (${d4.projectName})` : ""}`);
276459
+ console.log(` Ready at: ${d4.readyAt ?? "unknown"}`);
275449
276460
  }
275450
276461
  if (pidMismatch) {
275451
276462
  console.log("");
@@ -275539,7 +276550,7 @@ function doLogs(follow, lines) {
275539
276550
  console.log(tail.join("\n"));
275540
276551
  }
275541
276552
  }
275542
- var background_default, _testing3;
276553
+ var BACKGROUND_LOCK_STALE_MS, BACKGROUND_LOCK_ACQUIRE_TIMEOUT_MS, BACKGROUND_LOCK_HEARTBEAT_MS, background_default, _testing3;
275543
276554
  var init_background = __esm({
275544
276555
  "src/cli/commands/background.ts"() {
275545
276556
  "use strict";
@@ -275547,6 +276558,9 @@ var init_background = __esm({
275547
276558
  init_dist2();
275548
276559
  init_port();
275549
276560
  init_launch_root();
276561
+ BACKGROUND_LOCK_STALE_MS = 15e3;
276562
+ BACKGROUND_LOCK_ACQUIRE_TIMEOUT_MS = 1e4;
276563
+ BACKGROUND_LOCK_HEARTBEAT_MS = 2e3;
275550
276564
  background_default = defineCommand({
275551
276565
  meta: {
275552
276566
  name: "background",
@@ -275569,6 +276583,11 @@ var init_background = __esm({
275569
276583
  alias: "n",
275570
276584
  description: "Number of log lines to show (default: 50)",
275571
276585
  required: false
276586
+ },
276587
+ json: {
276588
+ type: "boolean",
276589
+ description: "Emit a machine-readable status receipt",
276590
+ required: false
275572
276591
  }
275573
276592
  },
275574
276593
  run: async ({ args }) => {
@@ -275583,7 +276602,7 @@ var init_background = __esm({
275583
276602
  await doStop();
275584
276603
  break;
275585
276604
  case "status":
275586
- await doStatus();
276605
+ await doStatus(!!args.json);
275587
276606
  break;
275588
276607
  case "restart":
275589
276608
  await doRestart(port);
@@ -275609,6 +276628,7 @@ var init_background = __esm({
275609
276628
  console.log(" --port <port> HTTP port (default: 3211)");
275610
276629
  console.log(' --follow, -f Follow log output in real-time (for "logs")');
275611
276630
  console.log(" --lines, -n Number of log lines to show (default: 50)");
276631
+ console.log(' --json Emit a machine-readable status receipt (for "status")');
275612
276632
  console.log("");
275613
276633
  console.log("Mode distinction:");
275614
276634
  console.log(" Quick Mode = stdio / single project / zero friction");
@@ -275630,7 +276650,10 @@ var init_background = __esm({
275630
276650
  formatBackgroundCommandError,
275631
276651
  resolveBackgroundCliEntry,
275632
276652
  resolveBackgroundCliEntryFrom,
275633
- resolveBackgroundCwd
276653
+ resolveBackgroundCwd,
276654
+ acquireBackgroundLock,
276655
+ releaseBackgroundLock,
276656
+ getBackgroundLockPath
275634
276657
  };
275635
276658
  }
275636
276659
  });
@@ -275648,7 +276671,7 @@ import { spawnSync as spawnSync2 } from "child_process";
275648
276671
  import { existsSync as existsSync29, realpathSync as realpathSync2 } from "fs";
275649
276672
  import { mkdir as mkdir8, readFile as readFile9, writeFile as writeFile9 } from "fs/promises";
275650
276673
  import { basename as basename5, dirname as dirname8, resolve as resolve4 } from "path";
275651
- import { homedir as homedir34 } from "os";
276674
+ import { homedir as homedir35 } from "os";
275652
276675
  function requestedAgents(agent) {
275653
276676
  const all = getSetupAgentTargets();
275654
276677
  if (!agent || agent === "all") return all;
@@ -275726,16 +276749,16 @@ function asRecordArray(value) {
275726
276749
  return Array.isArray(value) ? value.map(asRecord3).filter((entry) => entry !== null) : [];
275727
276750
  }
275728
276751
  function codexPluginPath() {
275729
- return `${homedir34()}/plugins/${CODEX_PLUGIN_NAME}`;
276752
+ return `${homedir35()}/plugins/${CODEX_PLUGIN_NAME}`;
275730
276753
  }
275731
276754
  function codexPluginMcpPath() {
275732
276755
  return `${codexPluginPath()}/.mcp.json`;
275733
276756
  }
275734
276757
  function codexMarketplacePath() {
275735
- return `${homedir34()}/.agents/plugins/marketplace.json`;
276758
+ return `${homedir35()}/.agents/plugins/marketplace.json`;
275736
276759
  }
275737
276760
  function codexConfigPath() {
275738
- return `${homedir34()}/.codex/config.toml`;
276761
+ return `${homedir35()}/.codex/config.toml`;
275739
276762
  }
275740
276763
  function normalizeMarketplacePath(value) {
275741
276764
  return value.replace(/\\/g, "/").replace(/^\.\//, "");
@@ -276050,7 +277073,7 @@ function canonicalProjectPath(projectRoot) {
276050
277073
  return canonical.replace(/\\/g, "/");
276051
277074
  }
276052
277075
  function getClaudeLocalConfigPath() {
276053
- return `${homedir34()}/.claude.json`;
277076
+ return `${homedir35()}/.claude.json`;
276054
277077
  }
276055
277078
  function coerceMcpServer(name, value) {
276056
277079
  const entry = asRecord3(value);
@@ -276309,7 +277332,7 @@ async function inspectGuidance(agent, projectRoot, scope) {
276309
277332
  }
276310
277333
  const checks = [];
276311
277334
  for (const targetScope of requestedGuidanceScopes(scope)) {
276312
- const root = targetScope === "project" ? projectRoot : homedir34();
277335
+ const root = targetScope === "project" ? projectRoot : homedir35();
276313
277336
  const rulesPath = getAgentRulesPath(agent, root, targetScope === "global");
276314
277337
  if (!existsSync29(rulesPath)) {
276315
277338
  checks.push({
@@ -276526,7 +277549,8 @@ var init_agent_integrations = __esm({
276526
277549
  "kiro",
276527
277550
  "opencode",
276528
277551
  "trae",
276529
- "dsh"
277552
+ "dsh",
277553
+ "workbuddy"
276530
277554
  ]);
276531
277555
  CODEX_PLUGIN_NAME = "memorix";
276532
277556
  CODEX_PLUGIN_MARKETPLACE = "personal";
@@ -276588,8 +277612,8 @@ var init_doctor = __esm({
276588
277612
  return;
276589
277613
  }
276590
277614
  const { existsSync: existsSync34, readFileSync: readFileSync23 } = await import("fs");
276591
- const { join: join34, basename: basename7 } = await import("path");
276592
- const { homedir: homedir36 } = await import("os");
277615
+ const { join: join35, basename: basename7 } = await import("path");
277616
+ const { homedir: homedir37 } = await import("os");
276593
277617
  const { execSync: execSync5 } = await import("child_process");
276594
277618
  const report = {};
276595
277619
  const issues = [];
@@ -276651,8 +277675,8 @@ var init_doctor = __esm({
276651
277675
  }
276652
277676
  lines.push("");
276653
277677
  lines.push("\u250C\u2500 Runtime Mode \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
276654
- const memorixDir = join34(homedir36(), ".memorix");
276655
- const bgStatePath = join34(memorixDir, "background.json");
277678
+ const memorixDir = join35(homedir37(), ".memorix");
277679
+ const bgStatePath = join35(memorixDir, "background.json");
276656
277680
  let bgRunning = false;
276657
277681
  let bgPort = 0;
276658
277682
  let bgPid = 0;
@@ -276772,7 +277796,7 @@ var init_doctor = __esm({
276772
277796
  }
276773
277797
  }
276774
277798
  try {
276775
- const cachePath = join34(memorixDir, "embedding-cache.json");
277799
+ const cachePath = join35(memorixDir, "embedding-cache.json");
276776
277800
  if (existsSync34(cachePath)) {
276777
277801
  const cache5 = JSON.parse(readFileSync23(cachePath, "utf-8"));
276778
277802
  const cacheCount = Object.keys(cache5).length;
@@ -276966,7 +277990,7 @@ var init_doctor = __esm({
276966
277990
  lines.push("\u250C\u2500 Conflict Check \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
276967
277991
  let conflictsFound = false;
276968
277992
  if (dataDir) {
276969
- const lockFile = join34(dataDir, ".memorix.lock");
277993
+ const lockFile = join35(dataDir, ".memorix.lock");
276970
277994
  if (existsSync34(lockFile)) {
276971
277995
  try {
276972
277996
  const lockData = JSON.parse(readFileSync23(lockFile, "utf-8"));
@@ -277469,7 +278493,8 @@ var init_purge = __esm({
277469
278493
  // src/cli/commands/uninstall.ts
277470
278494
  var uninstall_exports = {};
277471
278495
  __export(uninstall_exports, {
277472
- default: () => uninstall_default
278496
+ default: () => uninstall_default,
278497
+ getMCPConfigEntries: () => getMCPConfigEntries
277473
278498
  });
277474
278499
  import * as fs27 from "fs";
277475
278500
  import * as path46 from "path";
@@ -277652,6 +278677,24 @@ function getMCPConfigEntries(home, cwd) {
277652
278677
  detected: checkDshPatch(dshPatchPath),
277653
278678
  note: "Remove the memory-memorix insert row from this patch file."
277654
278679
  });
278680
+ const workbuddyCfg = path46.join(home, ".workbuddy", "mcp.json");
278681
+ entries.push({
278682
+ agent: "WorkBuddy",
278683
+ path: workbuddyCfg,
278684
+ kind: "global",
278685
+ format: "json",
278686
+ detected: checkJSON(workbuddyCfg),
278687
+ note: 'Remove the "memorix" key from mcpServers in this file.'
278688
+ });
278689
+ const workbuddyProjectCfg = path46.join(cwd, ".workbuddy", "mcp.json");
278690
+ entries.push({
278691
+ agent: "WorkBuddy",
278692
+ path: workbuddyProjectCfg,
278693
+ kind: "project",
278694
+ format: "json",
278695
+ detected: checkJSON(workbuddyProjectCfg),
278696
+ note: 'Remove the "memorix" key from mcpServers in this file.'
278697
+ });
277655
278698
  return entries;
277656
278699
  }
277657
278700
  function checkBackground(home) {
@@ -279156,7 +280199,7 @@ var init_pipeline_trace = __esm({
279156
280199
  // src/orchestrate/worktree.ts
279157
280200
  import { execFileSync as execFileSync5 } from "child_process";
279158
280201
  import { existsSync as existsSync31, rmSync as rmSync2 } from "fs";
279159
- import { join as join32, basename as basename6 } from "path";
280202
+ import { join as join33, basename as basename6 } from "path";
279160
280203
  function runGit4(cwd, args, timeout = 5e3) {
279161
280204
  return String(execFileSync5("git", args, {
279162
280205
  cwd,
@@ -279195,7 +280238,7 @@ function isManagedWorktreePath(worktreePath, worktreeBase) {
279195
280238
  function createWorktree(projectDir2, taskId, pipelineId) {
279196
280239
  const shortId2 = taskId.slice(0, 8);
279197
280240
  const shortPipeline = pipelineId.slice(0, 8);
279198
- const worktreeBase = join32(projectDir2, WORKTREE_DIR, `task-${shortId2}`);
280241
+ const worktreeBase = join33(projectDir2, WORKTREE_DIR, `task-${shortId2}`);
279199
280242
  const branchBase = `pipeline/${shortPipeline}/task-${shortId2}`;
279200
280243
  for (let attempt = 1; attempt <= 100; attempt++) {
279201
280244
  const suffix = attempt === 1 ? "" : `-${attempt}`;
@@ -279285,7 +280328,7 @@ function listWorktrees(projectDir2) {
279285
280328
  }
279286
280329
  }
279287
280330
  if (current) worktrees.push(current);
279288
- const worktreeBase = join32(projectDir2, WORKTREE_DIR);
280331
+ const worktreeBase = join33(projectDir2, WORKTREE_DIR);
279289
280332
  return worktrees.filter((w4) => isManagedWorktreePath(w4.path, worktreeBase));
279290
280333
  } catch {
279291
280334
  return [];
@@ -279707,16 +280750,16 @@ var init_cost_tracker = __esm({
279707
280750
 
279708
280751
  // src/orchestrate/evidence.ts
279709
280752
  import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
279710
- import { join as join33 } from "path";
280753
+ import { join as join34 } from "path";
279711
280754
  function writeTaskEvidence(projectDir2, pipelineId, evidence) {
279712
280755
  try {
279713
- const dir = join33(projectDir2, ".pipeline", pipelineId, "evidence", evidence.taskId.slice(0, 12));
280756
+ const dir = join34(projectDir2, ".pipeline", pipelineId, "evidence", evidence.taskId.slice(0, 12));
279714
280757
  mkdirSync10(dir, { recursive: true });
279715
280758
  if (evidence.prompt) {
279716
- safeWrite(join33(dir, "prompt.md"), evidence.prompt);
280759
+ safeWrite(join34(dir, "prompt.md"), evidence.prompt);
279717
280760
  }
279718
280761
  if (evidence.tailOutput) {
279719
- safeWrite(join33(dir, "output.txt"), evidence.tailOutput);
280762
+ safeWrite(join34(dir, "output.txt"), evidence.tailOutput);
279720
280763
  }
279721
280764
  if (evidence.gateResults) {
279722
280765
  for (const g4 of evidence.gateResults) {
@@ -279725,7 +280768,7 @@ Status: ${g4.passed ? "PASS" : "FAIL"}
279725
280768
  Duration: ${(g4.durationMs / 1e3).toFixed(1)}s
279726
280769
 
279727
280770
  ${g4.output}`;
279728
- safeWrite(join33(dir, `${g4.gate}.txt`), content);
280771
+ safeWrite(join34(dir, `${g4.gate}.txt`), content);
279729
280772
  }
279730
280773
  }
279731
280774
  const resultJson = {
@@ -279739,7 +280782,7 @@ ${g4.output}`;
279739
280782
  tokenUsage: evidence.tokenUsage,
279740
280783
  costUSD: evidence.costUSD
279741
280784
  };
279742
- safeWrite(join33(dir, "result.json"), JSON.stringify(resultJson, null, 2));
280785
+ safeWrite(join34(dir, "result.json"), JSON.stringify(resultJson, null, 2));
279743
280786
  return dir;
279744
280787
  } catch {
279745
280788
  return null;
@@ -279747,7 +280790,7 @@ ${g4.output}`;
279747
280790
  }
279748
280791
  function writePipelineSummary(projectDir2, summary) {
279749
280792
  try {
279750
- const dir = join33(projectDir2, ".pipeline", summary.pipelineId);
280793
+ const dir = join34(projectDir2, ".pipeline", summary.pipelineId);
279751
280794
  mkdirSync10(dir, { recursive: true });
279752
280795
  const elapsed = (summary.elapsedMs / 1e3).toFixed(0);
279753
280796
  const lines = [
@@ -279768,8 +280811,8 @@ function writePipelineSummary(projectDir2, summary) {
279768
280811
  lines.push(`- [${status}] ${t4.taskDescription.slice(0, 80)} \u2014 ${t4.agentName}, ${dur}s${fixes}`);
279769
280812
  }
279770
280813
  const content = lines.join("\n") + "\n";
279771
- safeWrite(join33(dir, "summary.md"), content);
279772
- return join33(dir, "summary.md");
280814
+ safeWrite(join34(dir, "summary.md"), content);
280815
+ return join34(dir, "summary.md");
279773
280816
  } catch {
279774
280817
  return null;
279775
280818
  }
@@ -285996,6 +287039,10 @@ var GUIDES = {
285996
287039
  usage: [
285997
287040
  "memorix codegraph status",
285998
287041
  "memorix codegraph refresh",
287042
+ "memorix codegraph init",
287043
+ "memorix codegraph sync",
287044
+ "memorix codegraph diff [--from <snapshot>] [--to <snapshot>]",
287045
+ "memorix codegraph impact --path <relative-source-path>",
285999
287046
  'memorix codegraph context-pack --task "trace the auth flow" [--limit 20]'
286000
287047
  ]
286001
287048
  },
@@ -286014,10 +287061,57 @@ var GUIDES = {
286014
287061
  usage: [
286015
287062
  "memorix knowledge init [--mode local|versioned]",
286016
287063
  "memorix knowledge status",
287064
+ "memorix knowledge claims",
287065
+ 'memorix knowledge review --id <claim-id> --review approved|rejected --detail "..."',
286017
287066
  "memorix knowledge compile",
286018
287067
  "memorix knowledge lint",
286019
- "memorix knowledge workflow list"
286020
- ]
287068
+ "memorix knowledge apply --proposal <id> [--force]",
287069
+ "memorix knowledge workflow import|list",
287070
+ 'memorix knowledge workflow select --task "prepare a release"',
287071
+ "memorix knowledge workflow preview|apply --id <workflow-id> --agent codex",
287072
+ 'memorix knowledge workflow run --id <workflow-id> --task "..." --outcome passed'
287073
+ ],
287074
+ notes: ["Claims need source review before they can become maintained Knowledge Workspace pages."]
287075
+ },
287076
+ evidence: {
287077
+ summary: "Inspect the source, freshness, and verification state behind project memories.",
287078
+ usage: [
287079
+ 'memorix evidence list [--query "auth"] [--limit 20]',
287080
+ "memorix evidence get --id 42",
287081
+ "memorix evidence sync",
287082
+ 'memorix evidence stale --paths src/server.ts,tests/server.test.ts --reason "source changed"',
287083
+ "memorix evidence events --id 42"
287084
+ ],
287085
+ notes: ["Evidence cards point back to observations and source files; they are not a second memory store."]
287086
+ },
287087
+ feedback: {
287088
+ summary: "Record and inspect whether a memory helped, conflicted, or was corrected.",
287089
+ usage: [
287090
+ "memorix feedback record --id 42 --signal verification-success --source test:run-1",
287091
+ "memorix feedback show --id 42",
287092
+ "memorix feedback audit --id 42 [--limit 100]"
287093
+ ],
287094
+ notes: ["Feedback changes the candidate score through an auditable event; it does not rewrite the original memory."]
287095
+ },
287096
+ formation: {
287097
+ summary: "Inspect Memory Formation quality metrics collected by the runtime.",
287098
+ usage: ["memorix formation metrics"],
287099
+ notes: ["Metrics are empty until the formation pipeline has processed observations."]
287100
+ },
287101
+ media: {
287102
+ summary: "Import, inspect, derive, embed, and clean controlled local media assets.",
287103
+ usage: [
287104
+ "memorix media import --path ./diagram.png",
287105
+ 'memorix media attach --asset <asset-id> --title "Architecture diagram"',
287106
+ "memorix media list --kind image",
287107
+ "memorix media show --asset <asset-id>",
287108
+ "memorix media derive-pdf|derive-audio --asset <asset-id> [--attach]",
287109
+ "memorix media embed|similar --asset <asset-id>",
287110
+ 'memorix media generate image|video --prompt "..."',
287111
+ "memorix media status|cancel --job <media-job-id>",
287112
+ "memorix media cleanup [--max-bytes <limit>]"
287113
+ ],
287114
+ notes: ["Media generation is explicit and provider-gated; importing a file does not automatically send it to a model."]
286021
287115
  },
286022
287116
  reasoning: {
286023
287117
  summary: "Capture and retrieve engineering decision rationale.",
@@ -286510,7 +287604,7 @@ var main2 = defineCommand({
286510
287604
  console.error(" integrate Install one IDE integration into the current repo");
286511
287605
  console.error(" status Show project info + stats");
286512
287606
  console.error(" dashboard Open standalone dashboard (read-mostly)");
286513
- console.error(" hooks Open legacy hook installer menu");
287607
+ console.error(" hooks Install, inspect, or remove agent hooks");
286514
287608
  console.error(" cleanup Remove old memories");
286515
287609
  console.error(" purge Retire all memories (project by default, --all for everything)");
286516
287610
  console.error(" sync Rules/workspace sync plus interactive wizard");