memorix 1.9.9 → 1.9.11

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 (54) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +2 -0
  3. package/README.zh-CN.md +2 -0
  4. package/dist/cli/index.js +855 -231
  5. package/dist/index.js +284 -77
  6. package/dist/maintenance-runner.js +74 -20
  7. package/dist/media-audio-runner.js +74 -20
  8. package/dist/media-video-runner.js +74 -20
  9. package/dist/memcode/index.js +1532 -1002
  10. package/dist/memcode-runtime/CHANGELOG.md +42 -0
  11. package/dist/memcode-runtime/package.json +4 -4
  12. package/dist/sdk.js +283 -76
  13. package/dist/vector-backfill-runner.js +74 -20
  14. package/docs/CONFIGURATION.md +26 -0
  15. package/docs/DEVELOPMENT.md +3 -2
  16. package/docs/INTEGRATIONS.md +3 -1
  17. package/docs/README.md +2 -1
  18. package/docs/SETUP.md +1 -1
  19. package/docs/hooks-architecture.md +5 -0
  20. package/package.json +18 -11
  21. package/plugins/antigravity/memorix/plugin.json +1 -1
  22. package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
  23. package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
  24. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  25. package/plugins/copilot/memorix/plugin.json +1 -1
  26. package/plugins/gemini/memorix/gemini-extension.json +1 -1
  27. package/plugins/hermes/memorix/plugin.yaml +1 -1
  28. package/plugins/omp/memorix/package.json +1 -1
  29. package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
  30. package/plugins/pi/memorix/package.json +1 -1
  31. package/server.json +2 -2
  32. package/src/cli/commands/hooks-install.ts +2 -0
  33. package/src/cli/commands/init.ts +6 -2
  34. package/src/cli/commands/integrate.ts +2 -0
  35. package/src/cli/commands/setup.ts +1 -1
  36. package/src/cli/index.ts +2 -2
  37. package/src/cli/tui/ConfigureView.tsx +2 -0
  38. package/src/config/dotenv-loader.ts +1 -0
  39. package/src/config/resolved-config.ts +7 -3
  40. package/src/config/yaml-loader.ts +2 -2
  41. package/src/dashboard/server.ts +3 -0
  42. package/src/hooks/installers/index.ts +219 -31
  43. package/src/hooks/lifecycle.ts +4 -9
  44. package/src/hooks/normalizer.ts +6 -1
  45. package/src/hooks/types.ts +3 -1
  46. package/src/llm/provider.ts +2 -1
  47. package/src/memory/observations.ts +11 -0
  48. package/src/memory/session.ts +4 -13
  49. package/src/memory/visibility.ts +8 -2
  50. package/src/multimodal/image-loader.ts +6 -5
  51. package/src/server.ts +8 -4
  52. package/src/store/obs-store.ts +3 -0
  53. package/src/store/orama-store.ts +43 -6
  54. package/src/store/sqlite-store.ts +15 -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.9.9" : pkg.version;
3235
+ return true ? "1.9.11" : pkg.version;
3236
3236
  }
3237
3237
  var init_version = __esm({
3238
3238
  "src/cli/version.ts"() {
@@ -13748,9 +13748,9 @@ function sharedAgentIds(record2) {
13748
13748
  return [];
13749
13749
  }
13750
13750
  }
13751
- function canReadObservation(record2, reader2) {
13751
+ function canReadObservation(record2, reader2, allowedProjectIds) {
13752
13752
  if (!reader2) return true;
13753
- const sameProject = reader2.projectId === record2.projectId;
13753
+ const sameProject = allowedProjectIds ? allowedProjectIds.includes(record2.projectId) : reader2.projectId === record2.projectId;
13754
13754
  const visibility = resolveObservationVisibility(record2);
13755
13755
  if (visibility === "project") return !reader2.projectId || sameProject;
13756
13756
  if (!sameProject || !reader2.agentId) return false;
@@ -22144,15 +22144,16 @@ function getResolvedConfig(options = {}) {
22144
22144
  const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
22145
22145
  const isAtlasCloud = memoryLlmProvider === "atlascloud";
22146
22146
  const isRequesty = memoryLlmProvider === "requesty";
22147
- const usesPresetKeyOnly = isAtlasCloud || isRequesty;
22147
+ const isApiRoute = memoryLlmProvider === "apiroute";
22148
+ const usesPresetKeyOnly = isAtlasCloud || isRequesty || isApiRoute;
22148
22149
  const memoryLlmApiKey = first(
22149
22150
  process.env.MEMORIX_LLM_API_KEY,
22150
22151
  process.env.MEMORIX_API_KEY,
22151
22152
  toml.memory?.llm?.api_key,
22152
22153
  yaml.llm?.apiKey,
22153
22154
  legacy.llm?.apiKey,
22154
- // Never borrow another provider's credentials for the Atlas Cloud or Requesty presets.
22155
- isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : isRequesty ? process.env.REQUESTY_API_KEY : process.env.OPENAI_API_KEY,
22155
+ // Never borrow another provider's credentials for these gateway presets.
22156
+ isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : isRequesty ? process.env.REQUESTY_API_KEY : isApiRoute ? process.env.API_ROUTE_API_KEY : process.env.OPENAI_API_KEY,
22156
22157
  usesPresetKeyOnly ? void 0 : process.env.ANTHROPIC_API_KEY,
22157
22158
  usesPresetKeyOnly ? void 0 : openRouterMemoryLlmApiKey
22158
22159
  );
@@ -22335,6 +22336,7 @@ function getEnvSourceNames() {
22335
22336
  "MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
22336
22337
  "OPENROUTER_API_KEY",
22337
22338
  "REQUESTY_API_KEY",
22339
+ "API_ROUTE_API_KEY",
22338
22340
  "ATLASCLOUD_API_KEY"
22339
22341
  ].filter((name) => process.env[name]);
22340
22342
  }
@@ -25328,6 +25330,7 @@ var init_provider2 = __esm({
25328
25330
  anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
25329
25331
  openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
25330
25332
  requesty: { baseUrl: "https://router.requesty.ai/v1", model: "openai/gpt-4.1-nano" },
25333
+ apiroute: { baseUrl: "https://global.api-route.com/v1", model: "deepseek-v4.1-flash" },
25331
25334
  atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
25332
25335
  custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
25333
25336
  };
@@ -25822,6 +25825,19 @@ var init_sqlite_store = __esm({
25822
25825
  async listProjectIds() {
25823
25826
  return this.db.prepare("SELECT DISTINCT projectId FROM observations ORDER BY projectId").all().map((row) => row.projectId).filter((projectId) => Boolean(projectId));
25824
25827
  }
25828
+ async migrateProjectIds(aliasIds, canonicalId) {
25829
+ const sourceIds = [...new Set(aliasIds.filter((projectId) => projectId && projectId !== canonicalId))];
25830
+ if (sourceIds.length === 0) return 0;
25831
+ return retrySqliteBusy(async () => {
25832
+ const placeholders = sourceIds.map(() => "?").join(", ");
25833
+ const result = this.db.prepare(
25834
+ `UPDATE observations SET projectId = ? WHERE projectId IN (${placeholders})`
25835
+ ).run(canonicalId, ...sourceIds);
25836
+ const migrated = Number(result.changes ?? 0);
25837
+ if (migrated > 0) this.bumpGeneration();
25838
+ return migrated;
25839
+ }, "Migrate observation project IDs");
25840
+ }
25825
25841
  async searchLexical(options) {
25826
25842
  return searchObservationLexically(this.db, options).map((hit) => ({
25827
25843
  observation: rowToObs(hit.row),
@@ -186704,6 +186720,16 @@ function getProjectObservations(projectId) {
186704
186720
  async function migrateProjectIds(aliasIds, canonicalId) {
186705
186721
  const nonCanonical = new Set(aliasIds.filter((id) => id !== canonicalId));
186706
186722
  if (nonCanonical.size === 0) return 0;
186723
+ const store2 = projectDir ? getObservationStore() : null;
186724
+ if (store2?.migrateProjectIds) {
186725
+ const migrated2 = await store2.migrateProjectIds(aliasIds, canonicalId);
186726
+ if (migrated2 > 0 && corpusLoaded) {
186727
+ for (const observation of observations) {
186728
+ if (nonCanonical.has(observation.projectId)) observation.projectId = canonicalId;
186729
+ }
186730
+ }
186731
+ return migrated2;
186732
+ }
186707
186733
  let migrated = 0;
186708
186734
  const changed = [];
186709
186735
  for (const obs of observations) {
@@ -186714,8 +186740,8 @@ async function migrateProjectIds(aliasIds, canonicalId) {
186714
186740
  }
186715
186741
  }
186716
186742
  if (migrated > 0 && projectDir) {
186717
- const store2 = getObservationStore();
186718
- await store2.atomic(async (tx) => {
186743
+ const store3 = getObservationStore();
186744
+ await store3.atomic(async (tx) => {
186719
186745
  await Promise.all(changed.map((observation) => tx.update(observation)));
186720
186746
  });
186721
186747
  }
@@ -187668,6 +187694,7 @@ var orama_store_exports = {};
187668
187694
  __export(orama_store_exports, {
187669
187695
  _classifyQueryTier: () => classifyQueryTier,
187670
187696
  batchGenerateEmbeddings: () => batchGenerateEmbeddings,
187697
+ createSearchTokenizer: () => createSearchTokenizer,
187671
187698
  generateEmbedding: () => generateEmbedding,
187672
187699
  generateEmbeddingInput: () => generateEmbeddingInput,
187673
187700
  getActiveSemanticIndexProfile: () => getActiveSemanticIndexProfile,
@@ -187708,6 +187735,26 @@ function getOptionalObservationStore() {
187708
187735
  return null;
187709
187736
  }
187710
187737
  }
187738
+ function createSearchTokenizer() {
187739
+ const defaultTokenizer = components_exports2.tokenizer.createTokenizer({ language: "english" });
187740
+ return {
187741
+ language: defaultTokenizer.language,
187742
+ normalizationCache: defaultTokenizer.normalizationCache,
187743
+ tokenize(raw, language, prop, withCache = true) {
187744
+ const defaultTokens = defaultTokenizer.tokenize(raw, language, prop, withCache);
187745
+ const cjkTokens = [];
187746
+ const normalized = raw.normalize("NFKC").toLowerCase();
187747
+ for (const match2 of normalized.matchAll(CJK_RUN)) {
187748
+ const characters = Array.from(match2[0]);
187749
+ cjkTokens.push(...characters);
187750
+ for (let index = 0; index + 1 < characters.length; index++) {
187751
+ cjkTokens.push(`${characters[index]}${characters[index + 1]}`);
187752
+ }
187753
+ }
187754
+ return [.../* @__PURE__ */ new Set([...defaultTokens, ...cjkTokens])];
187755
+ }
187756
+ };
187757
+ }
187711
187758
  async function shouldUsePersistentSearch(projectIds, projectId) {
187712
187759
  const store2 = getOptionalObservationStore();
187713
187760
  if (!store2?.hasLexicalIndex?.()) return false;
@@ -187808,6 +187855,7 @@ async function searchPersistentSemantically(options, projectIds, limit2, queryVe
187808
187855
  const lexical = await searchPersistentLexically(options, projectIds, limit2);
187809
187856
  const store2 = getObservationStore();
187810
187857
  const documents = /* @__PURE__ */ new Map();
187858
+ const vectorDocumentKeys = /* @__PURE__ */ new Map();
187811
187859
  const addObservation = (observation) => {
187812
187860
  const document2 = observationToSearchDocument(observation);
187813
187861
  documents.set(makeEntryKey(document2.projectId, document2.observationId), document2);
@@ -187823,6 +187871,7 @@ async function searchPersistentSemantically(options, projectIds, limit2, queryVe
187823
187871
  if (options.type && observation.type !== options.type) return null;
187824
187872
  if (options.source && observation.source !== options.source) return null;
187825
187873
  addObservation(observation);
187874
+ vectorDocumentKeys.set(hit.observationId, makeEntryKey(observation.projectId, observation.id));
187826
187875
  return observation;
187827
187876
  }));
187828
187877
  const RRF_K = 60;
@@ -187832,7 +187881,7 @@ async function searchPersistentSemantically(options, projectIds, limit2, queryVe
187832
187881
  scores.set(key, (scores.get(key) ?? 0) + 0.6 / (RRF_K + index + 1));
187833
187882
  }
187834
187883
  for (const [index, hit] of vectorHits.entries()) {
187835
- const key = makeEntryKey(hit.projectId, hit.observationId);
187884
+ const key = vectorDocumentKeys.get(hit.observationId) ?? makeEntryKey(hit.projectId, hit.observationId);
187836
187885
  if (!documents.has(key)) continue;
187837
187886
  scores.set(key, (scores.get(key) ?? 0) + 0.4 / (RRF_K + index + 1));
187838
187887
  }
@@ -187845,12 +187894,13 @@ async function searchPersistentSemantically(options, projectIds, limit2, queryVe
187845
187894
  return {
187846
187895
  count: vectorHits.length,
187847
187896
  hits: vectorHits.map((hit, index) => {
187848
- const key = makeEntryKey(hit.projectId, hit.observationId);
187897
+ const key = vectorDocumentKeys.get(hit.observationId) ?? makeEntryKey(hit.projectId, hit.observationId);
187849
187898
  const document2 = documents.get(key);
187850
187899
  return document2 ? { id: document2.id, score: 0.4 / (RRF_K + index + 1), document: document2 } : null;
187851
187900
  }).filter((hit) => hit !== null).slice(0, limit2)
187852
187901
  };
187853
187902
  }
187903
+ if (hits.length === 0) return null;
187854
187904
  return { count: hits.length, hits };
187855
187905
  } catch {
187856
187906
  return null;
@@ -187925,7 +187975,10 @@ async function initializeDb(options, generation) {
187925
187975
  };
187926
187976
  const dims = nextEmbeddingDimensions ?? 384;
187927
187977
  const schema = nextEmbeddingEnabled ? { ...baseSchema, embedding: `vector[${dims}]` } : baseSchema;
187928
- const nextDb = await create5({ schema });
187978
+ const nextDb = await create5({
187979
+ schema,
187980
+ components: { tokenizer: createSearchTokenizer() }
187981
+ });
187929
187982
  if (generation !== dbGeneration) {
187930
187983
  return getDb(options);
187931
187984
  }
@@ -188359,7 +188412,7 @@ async function searchObservations(options) {
188359
188412
  if (!projectIds) return true;
188360
188413
  const doc = hit.document;
188361
188414
  return projectIds.includes(doc.projectId);
188362
- }).filter((hit) => canReadObservation(hit.document, options.reader)).filter((hit) => {
188415
+ }).filter((hit) => canReadObservation(hit.document, options.reader, projectIds ?? void 0)).filter((hit) => {
188363
188416
  if (statusFilter === "all") return true;
188364
188417
  const doc = hit.document;
188365
188418
  return (doc.status || "active") === statusFilter;
@@ -188625,7 +188678,7 @@ async function searchObservations(options) {
188625
188678
  let entries = intermediate.map(({ rawTime: _5, _isCommandLog: _c, ...rest }) => rest);
188626
188679
  for (const hit of results.hits) {
188627
188680
  const doc = hit.document;
188628
- if (canReadObservation(doc, options.reader)) rememberObservationDoc(doc);
188681
+ if (canReadObservation(doc, options.reader, projectIds ?? void 0)) rememberObservationDoc(doc);
188629
188682
  }
188630
188683
  if (hasQuery && originalQuery) {
188631
188684
  const queryLower = originalQuery.toLowerCase();
@@ -188783,7 +188836,7 @@ function formatTime(isoDate) {
188783
188836
  return isoDate;
188784
188837
  }
188785
188838
  }
188786
- var db, dbInitPromise, dbGeneration, embeddingEnabled, embeddingDimensions, indexEmbeddingProvider, deferredCachedVectorHydration, NON_CJK_HYBRID_SIMILARITY, lastSearchModeByProject, SEARCH_MODE_DEFAULT_KEY, MAX_SEARCH_MODE_KEYS, COMMAND_LOG_TITLE2, COMMAND_STYLE_TITLE, COMMAND_LIKE_QUERY2, COMMAND_INTENT_QUERY, NATURAL_LANGUAGE_MARKERS;
188839
+ var db, dbInitPromise, dbGeneration, embeddingEnabled, embeddingDimensions, indexEmbeddingProvider, deferredCachedVectorHydration, NON_CJK_HYBRID_SIMILARITY, CJK_RUN, lastSearchModeByProject, SEARCH_MODE_DEFAULT_KEY, MAX_SEARCH_MODE_KEYS, COMMAND_LOG_TITLE2, COMMAND_STYLE_TITLE, COMMAND_LIKE_QUERY2, COMMAND_INTENT_QUERY, NATURAL_LANGUAGE_MARKERS;
188787
188840
  var init_orama_store = __esm({
188788
188841
  "src/store/orama-store.ts"() {
188789
188842
  "use strict";
@@ -188808,6 +188861,7 @@ var init_orama_store = __esm({
188808
188861
  indexEmbeddingProvider = null;
188809
188862
  deferredCachedVectorHydration = null;
188810
188863
  NON_CJK_HYBRID_SIMILARITY = 0.45;
188864
+ CJK_RUN = /[\u3400-\u4dbf\u4e00-\u9fff\u3040-\u30ff\uac00-\ud7af]+/gu;
188811
188865
  lastSearchModeByProject = /* @__PURE__ */ new Map();
188812
188866
  SEARCH_MODE_DEFAULT_KEY = "__global__";
188813
188867
  MAX_SEARCH_MODE_KEYS = 4096;
@@ -193112,6 +193166,8 @@ function buildInitTomlConfig(options) {
193112
193166
  lines.push('# model = "openai/gpt-4o-mini"');
193113
193167
  } else if (options.llmProvider === "requesty") {
193114
193168
  lines.push('# model = "openai/gpt-4o-mini"');
193169
+ } else if (options.llmProvider === "apiroute") {
193170
+ lines.push('model = "deepseek-v4.1-flash"');
193115
193171
  } else if (options.llmProvider === "atlascloud") {
193116
193172
  lines.push('model = "deepseek-ai/deepseek-v3.2"');
193117
193173
  }
@@ -193247,6 +193303,7 @@ var init_init = __esm({
193247
193303
  { value: "anthropic", label: "Anthropic", hint: "claude-3-haiku" },
193248
193304
  { value: "openrouter", label: "OpenRouter", hint: "multi-provider" },
193249
193305
  { value: "requesty", label: "Requesty", hint: "multi-provider" },
193306
+ { value: "apiroute", label: "API Route", hint: "multi-provider" },
193250
193307
  { value: "atlascloud", label: "Atlas Cloud", hint: "DeepSeek V3.2" },
193251
193308
  { value: "custom", label: "Custom", hint: "OpenAI-compatible endpoint" }
193252
193309
  ]
@@ -193301,7 +193358,7 @@ var init_init = __esm({
193301
193358
  ];
193302
193359
  if (llmProvider !== "none") {
193303
193360
  envLines.push("# LLM API key");
193304
- if (llmProvider === "openai" || llmProvider === "custom" || llmProvider === "atlascloud") {
193361
+ if (llmProvider === "openai" || llmProvider === "custom" || llmProvider === "atlascloud" || llmProvider === "apiroute") {
193305
193362
  envLines.push("MEMORIX_LLM_API_KEY=sk-your-key-here");
193306
193363
  } else if (llmProvider === "anthropic") {
193307
193364
  envLines.push("MEMORIX_LLM_API_KEY=sk-ant-your-key-here");
@@ -193336,6 +193393,7 @@ var init_init = __esm({
193336
193393
  envLines.push("# ANTHROPIC_API_KEY=sk-ant-...");
193337
193394
  envLines.push("# OPENROUTER_API_KEY=sk-or-...");
193338
193395
  envLines.push("# REQUESTY_API_KEY=rqsty-...");
193396
+ envLines.push("# API_ROUTE_API_KEY=sk-...");
193339
193397
  envLines.push("");
193340
193398
  mkdirSync3(targetDir, { recursive: true });
193341
193399
  writeFileSync3(targetPath, tomlContent, "utf-8");
@@ -195224,6 +195282,26 @@ function generateClaudeConfig() {
195224
195282
  }
195225
195283
  };
195226
195284
  }
195285
+ function generateQwenConfig() {
195286
+ const cmd = `${resolveHookCommand()} hook --agent qwen`;
195287
+ const hookEntry = {
195288
+ type: "command",
195289
+ command: cmd,
195290
+ timeout: 10
195291
+ };
195292
+ return {
195293
+ hooks: {
195294
+ SessionStart: [{ hooks: [hookEntry] }],
195295
+ SessionEnd: [{ hooks: [hookEntry] }],
195296
+ PostToolUse: [{ hooks: [hookEntry] }],
195297
+ PostToolUseFailure: [{ hooks: [hookEntry] }],
195298
+ UserPromptSubmit: [{ hooks: [hookEntry] }],
195299
+ PreCompact: [{ hooks: [hookEntry] }],
195300
+ PostCompact: [{ hooks: [hookEntry] }],
195301
+ Stop: [{ hooks: [hookEntry] }]
195302
+ }
195303
+ };
195304
+ }
195227
195305
  function generateGrokConfig() {
195228
195306
  const cmd = `${resolveHookCommand()} hook --agent grok`;
195229
195307
  const hookEntry = {
@@ -195254,7 +195332,13 @@ function isMemorixGrokCommand(value) {
195254
195332
  function isMemorixGrokHook(value) {
195255
195333
  return isJsonRecord(value) && value.type === "command" && isMemorixGrokCommand(value.command);
195256
195334
  }
195257
- function mergeGrokHookConfig(existing, generated) {
195335
+ function isMemorixQwenCommand(value) {
195336
+ return value === "memorix hook --agent qwen" || value === "memorix.cmd hook --agent qwen";
195337
+ }
195338
+ function isMemorixQwenHook(value) {
195339
+ return isJsonRecord(value) && value.type === "command" && isMemorixQwenCommand(value.command);
195340
+ }
195341
+ function mergeCommandHookConfig(existing, generated, isOwnedHook) {
195258
195342
  const merged = { ...existing };
195259
195343
  const existingHooks = isJsonRecord(existing.hooks) ? { ...existing.hooks } : {};
195260
195344
  const generatedHooks = isJsonRecord(generated.hooks) ? generated.hooks : {};
@@ -195262,7 +195346,7 @@ function mergeGrokHookConfig(existing, generated) {
195262
195346
  const currentGroups = Array.isArray(existingHooks[event]) ? existingHooks[event] : [];
195263
195347
  const preservedGroups = currentGroups.flatMap((group) => {
195264
195348
  if (!isJsonRecord(group) || !Array.isArray(group.hooks)) return [group];
195265
- const preservedHooks = group.hooks.filter((hook) => !isMemorixGrokHook(hook));
195349
+ const preservedHooks = group.hooks.filter((hook) => !isOwnedHook(hook));
195266
195350
  if (preservedHooks.length === 0) return [];
195267
195351
  return [{ ...group, hooks: preservedHooks }];
195268
195352
  });
@@ -195271,7 +195355,13 @@ function mergeGrokHookConfig(existing, generated) {
195271
195355
  merged.hooks = existingHooks;
195272
195356
  return merged;
195273
195357
  }
195274
- function removeMemorixGrokHooks(config2) {
195358
+ function mergeGrokHookConfig(existing, generated) {
195359
+ return mergeCommandHookConfig(existing, generated, isMemorixGrokHook);
195360
+ }
195361
+ function mergeQwenHookConfig(existing, generated) {
195362
+ return mergeCommandHookConfig(existing, generated, isMemorixQwenHook);
195363
+ }
195364
+ function removeCommandHooks(config2, isOwnedHook) {
195275
195365
  const cleaned = { ...config2 };
195276
195366
  const hooks = isJsonRecord(config2.hooks) ? { ...config2.hooks } : null;
195277
195367
  if (!hooks) return cleaned;
@@ -195279,7 +195369,7 @@ function removeMemorixGrokHooks(config2) {
195279
195369
  if (!Array.isArray(groups)) continue;
195280
195370
  const preservedGroups = groups.flatMap((group) => {
195281
195371
  if (!isJsonRecord(group) || !Array.isArray(group.hooks)) return [group];
195282
- const preservedHooks = group.hooks.filter((hook) => !isMemorixGrokHook(hook));
195372
+ const preservedHooks = group.hooks.filter((hook) => !isOwnedHook(hook));
195283
195373
  if (preservedHooks.length === 0) return [];
195284
195374
  return [{ ...group, hooks: preservedHooks }];
195285
195375
  });
@@ -195290,6 +195380,12 @@ function removeMemorixGrokHooks(config2) {
195290
195380
  else delete cleaned.hooks;
195291
195381
  return cleaned;
195292
195382
  }
195383
+ function removeMemorixGrokHooks(config2) {
195384
+ return removeCommandHooks(config2, isMemorixGrokHook);
195385
+ }
195386
+ function removeMemorixQwenHooks(config2) {
195387
+ return removeCommandHooks(config2, isMemorixQwenHook);
195388
+ }
195293
195389
  async function readGrokHookConfig(configPath) {
195294
195390
  let content;
195295
195391
  try {
@@ -195308,6 +195404,24 @@ async function readGrokHookConfig(configPath) {
195308
195404
  throw new Error(`Cannot safely update Grok hook config ${configPath}: ${reason}`);
195309
195405
  }
195310
195406
  }
195407
+ async function readQwenHookConfig(configPath) {
195408
+ let content;
195409
+ try {
195410
+ content = await fs19.readFile(configPath, "utf-8");
195411
+ } catch (error40) {
195412
+ if (error40.code === "ENOENT") return {};
195413
+ throw error40;
195414
+ }
195415
+ if (!content.trim()) return {};
195416
+ try {
195417
+ const parsed = JSON.parse(content);
195418
+ if (!isJsonRecord(parsed)) throw new Error("top-level value must be an object");
195419
+ return parsed;
195420
+ } catch (error40) {
195421
+ const reason = error40 instanceof Error ? error40.message : String(error40);
195422
+ throw new Error(`Cannot safely update Qwen hook config ${configPath}: ${reason}`);
195423
+ }
195424
+ }
195311
195425
  function generateCopilotConfig() {
195312
195426
  const cmd = `${resolveHookCommand()} hook`;
195313
195427
  const hasPwsh = detectPwsh();
@@ -195509,6 +195623,8 @@ function generateOpenCodePlugin() {
195509
195623
  */
195510
195624
  import { spawnSync } from 'node:child_process';
195511
195625
 
195626
+ const HOOK_TIMEOUT_MS = 30_000;
195627
+
195512
195628
  export const MemorixPlugin = async ({ project, client, $, directory, worktree }) => {
195513
195629
  // Generate a stable session ID for this plugin lifetime
195514
195630
  const sessionId = \`opencode-\${Date.now().toString(36)}-\${Math.random().toString(36).slice(2, 8)}\`;
@@ -195534,14 +195650,14 @@ export const MemorixPlugin = async ({ project, client, $, directory, worktree })
195534
195650
  * - spawnSync is simpler: no stream lifecycle, no writer.close() bugs
195535
195651
  * - stdin pipe via input option is reliable cross-platform
195536
195652
  */
195537
- function runHook(payload) {
195538
- payload.session_id = sessionId;
195653
+ function runHook(payload, activeSessionId = sessionId) {
195654
+ payload.session_id = activeSessionId;
195539
195655
  const data = JSON.stringify(payload);
195540
195656
  const eventName = payload.hook_event_name || 'unknown';
195541
195657
  try {
195542
195658
  const result = spawnSync(hookCommand, ['hook'], {
195543
195659
  input: data,
195544
- timeout: 10_000,
195660
+ timeout: HOOK_TIMEOUT_MS,
195545
195661
  encoding: 'utf-8',
195546
195662
  stdio: ['pipe', 'pipe', 'pipe'],
195547
195663
  shell: process.platform === 'win32',
@@ -195586,7 +195702,87 @@ export const MemorixPlugin = async ({ project, client, $, directory, worktree })
195586
195702
  .trim();
195587
195703
  }
195588
195704
 
195705
+ function flushAssistantResponse(activeSessionId = sessionId) {
195706
+ if (!pendingAssistantResponse?.text) return;
195707
+ const deliveryKey = pendingAssistantResponse.id
195708
+ ? \`\${pendingAssistantResponse.id}:\${pendingAssistantResponse.text}\`
195709
+ : pendingAssistantResponse.text;
195710
+ if (deliveryKey === lastDeliveredAssistantKey) return;
195711
+ runHook({
195712
+ agent: 'opencode',
195713
+ hook_event_name: 'message.updated',
195714
+ ai_response: pendingAssistantResponse.text,
195715
+ message_id: pendingAssistantResponse.id,
195716
+ cwd: directory,
195717
+ }, activeSessionId);
195718
+ lastDeliveredAssistantKey = deliveryKey;
195719
+ }
195720
+
195721
+ function eventSessionId(event) {
195722
+ const properties = event?.properties ?? {};
195723
+ const value = properties.sessionID ?? properties.sessionId ?? properties.info?.id;
195724
+ return typeof value === 'string' && value ? value : sessionId;
195725
+ }
195726
+
195727
+ async function handleEvent({ event }) {
195728
+ const properties = event?.properties ?? {};
195729
+ const activeSessionId = eventSessionId(event);
195730
+ switch (event?.type) {
195731
+ case 'session.created':
195732
+ runHook({
195733
+ agent: 'opencode',
195734
+ hook_event_name: 'session.created',
195735
+ cwd: directory,
195736
+ }, activeSessionId);
195737
+ break;
195738
+ case 'session.idle':
195739
+ flushAssistantResponse(activeSessionId);
195740
+ runHook({
195741
+ agent: 'opencode',
195742
+ hook_event_name: 'session.idle',
195743
+ cwd: directory,
195744
+ }, activeSessionId);
195745
+ break;
195746
+ case 'file.edited':
195747
+ runHook({
195748
+ agent: 'opencode',
195749
+ hook_event_name: 'file.edited',
195750
+ file_path: properties.file ?? properties.path ?? '',
195751
+ cwd: directory,
195752
+ }, activeSessionId);
195753
+ break;
195754
+ case 'command.executed':
195755
+ runHook({
195756
+ agent: 'opencode',
195757
+ hook_event_name: 'command.executed',
195758
+ command: properties.name ?? properties.command ?? '',
195759
+ cwd: directory,
195760
+ }, activeSessionId);
195761
+ break;
195762
+ case 'message.updated': {
195763
+ const message = properties.info ?? properties.message ?? properties;
195764
+ if (message?.role !== 'assistant') break;
195765
+ const text = extractMessageText(message);
195766
+ if (!text) break;
195767
+ pendingAssistantResponse = { id: message.id, text };
195768
+ break;
195769
+ }
195770
+ case 'session.compacted':
195771
+ runHook({
195772
+ agent: 'opencode',
195773
+ hook_event_name: 'session.compacted',
195774
+ cwd: directory,
195775
+ }, activeSessionId);
195776
+ break;
195777
+ default:
195778
+ break;
195779
+ }
195780
+ }
195781
+
195589
195782
  return {
195783
+ // OpenCode 1.x delivers lifecycle/file/command/message events through this
195784
+ // generic hook. The named keys below remain for older compatible hosts.
195785
+ event: handleEvent,
195590
195786
  /** Session created \u2014 record session start */
195591
195787
  'session.created': async ({ session }) => {
195592
195788
  runHook({
@@ -195598,21 +195794,7 @@ export const MemorixPlugin = async ({ project, client, $, directory, worktree })
195598
195794
 
195599
195795
  /** Session idle \u2014 record session end */
195600
195796
  'session.idle': async ({ session }) => {
195601
- if (pendingAssistantResponse?.text) {
195602
- const deliveryKey = pendingAssistantResponse.id
195603
- ? \`\${pendingAssistantResponse.id}:\${pendingAssistantResponse.text}\`
195604
- : pendingAssistantResponse.text;
195605
- if (deliveryKey !== lastDeliveredAssistantKey) {
195606
- runHook({
195607
- agent: 'opencode',
195608
- hook_event_name: 'message.updated',
195609
- ai_response: pendingAssistantResponse.text,
195610
- message_id: pendingAssistantResponse.id,
195611
- cwd: directory,
195612
- });
195613
- lastDeliveredAssistantKey = deliveryKey;
195614
- }
195615
- }
195797
+ flushAssistantResponse();
195616
195798
  runHook({
195617
195799
  agent: 'opencode',
195618
195800
  hook_event_name: 'session.idle',
@@ -195720,7 +195902,7 @@ function v2RunHook(payload, directory, sessionId) {
195720
195902
  try {
195721
195903
  const result = spawnSync(v2HookCommand, ['hook'], {
195722
195904
  input: JSON.stringify(nextPayload),
195723
- timeout: 10_000,
195905
+ timeout: HOOK_TIMEOUT_MS,
195724
195906
  encoding: 'utf-8',
195725
195907
  stdio: ['pipe', 'pipe', 'pipe'],
195726
195908
  shell: process.platform === 'win32',
@@ -195844,7 +196026,7 @@ function setup(ctx) {
195844
196026
  return () => controller.abort();
195845
196027
  }
195846
196028
 
195847
- export default { id: 'memorix', setup };
196029
+ export default { id: 'memorix', server: MemorixPlugin, setup };
195848
196030
  `;
195849
196031
  }
195850
196032
  async function installOpenCodeSkills(projectRoot, global2 = false) {
@@ -195854,6 +196036,8 @@ function getProjectConfigPath(agent, projectRoot) {
195854
196036
  switch (agent) {
195855
196037
  case "claude":
195856
196038
  return path31.join(projectRoot, ".claude", "settings.local.json");
196039
+ case "qwen":
196040
+ return path31.join(projectRoot, ".qwen", "settings.json");
195857
196041
  case "copilot":
195858
196042
  return path31.join(projectRoot, ".github", "hooks", "memorix.json");
195859
196043
  case "windsurf":
@@ -195895,6 +196079,8 @@ function getGlobalConfigPath(agent) {
195895
196079
  switch (agent) {
195896
196080
  case "claude":
195897
196081
  return path31.join(home, ".claude", "settings.json");
196082
+ case "qwen":
196083
+ return path31.join(home, ".qwen", "settings.json");
195898
196084
  case "copilot":
195899
196085
  return "";
195900
196086
  case "windsurf":
@@ -195936,6 +196122,8 @@ function getAgentRulesPath(agent, root, global2 = false) {
195936
196122
  return path31.join(root, ".cursor", "rules", "memorix.mdc");
195937
196123
  case "claude":
195938
196124
  return path31.join(root, ".claude", "CLAUDE.md");
196125
+ case "qwen":
196126
+ return path31.join(root, ".qwen", "QWEN.md");
195939
196127
  case "codex":
195940
196128
  return path31.join(root, ".codex", "AGENTS.md");
195941
196129
  case "kiro":
@@ -195964,6 +196152,8 @@ function getAgentRulesPath(agent, root, global2 = false) {
195964
196152
  return path31.join(root, ".cursor", "rules", "memorix.mdc");
195965
196153
  case "claude":
195966
196154
  return path31.join(root, "CLAUDE.md");
196155
+ case "qwen":
196156
+ return path31.join(root, "QWEN.md");
195967
196157
  case "copilot":
195968
196158
  return path31.join(root, ".github", "copilot-instructions.md");
195969
196159
  case "codex":
@@ -196040,6 +196230,12 @@ async function detectInstalledAgents() {
196040
196230
  agents.push("grok");
196041
196231
  } catch {
196042
196232
  }
196233
+ const qwenDir = path31.join(home, ".qwen");
196234
+ try {
196235
+ await fs19.access(qwenDir);
196236
+ agents.push("qwen");
196237
+ } catch {
196238
+ }
196043
196239
  const codexDir = path31.join(home, ".codex");
196044
196240
  try {
196045
196241
  await fs19.access(codexDir);
@@ -196123,10 +196319,10 @@ async function installHooks(agent, projectRoot, global2 = false) {
196123
196319
  const { access: access5, unlink: unlink3 } = await import("fs/promises");
196124
196320
  await access5(entry.path);
196125
196321
  const basename7 = path31.basename(entry.path);
196126
- if (basename7 === "AGENTS.md" || basename7 === "GEMINI.md" || basename7 === "CONTEXT.md") {
196322
+ if (basename7 === "AGENTS.md" || basename7 === "GEMINI.md" || basename7 === "QWEN.md" || basename7 === "CONTEXT.md") {
196127
196323
  continue;
196128
196324
  }
196129
- if (agent === "grok" && path31.resolve(entry.path) === path31.resolve(configPath)) {
196325
+ if ((agent === "grok" || agent === "qwen") && path31.resolve(entry.path) === path31.resolve(configPath)) {
196130
196326
  continue;
196131
196327
  }
196132
196328
  await unlink3(entry.path);
@@ -196141,6 +196337,9 @@ async function installHooks(agent, projectRoot, global2 = false) {
196141
196337
  case "claude":
196142
196338
  generated = generateClaudeConfig();
196143
196339
  break;
196340
+ case "qwen":
196341
+ generated = generateQwenConfig();
196342
+ break;
196144
196343
  case "grok":
196145
196344
  generated = generateGrokConfig();
196146
196345
  break;
@@ -196247,6 +196446,15 @@ async function installHooks(agent, projectRoot, global2 = false) {
196247
196446
  await recordFile2(projectRoot, "hook", configPath, agent);
196248
196447
  } catch {
196249
196448
  }
196449
+ } else if (agent === "qwen") {
196450
+ const existing = await readQwenHookConfig(configPath);
196451
+ const merged = mergeQwenHookConfig(existing, generated);
196452
+ await fs19.writeFile(configPath, JSON.stringify(merged, null, 2), "utf-8");
196453
+ try {
196454
+ const { recordFile: recordFile2 } = await Promise.resolve().then(() => (init_audit(), audit_exports));
196455
+ await recordFile2(projectRoot, "hook", configPath, agent);
196456
+ } catch {
196457
+ }
196250
196458
  } else if (agent === "kiro") {
196251
196459
  const hookFiles = generateKiroHookFiles();
196252
196460
  const hooksDir = path31.join(path31.dirname(configPath));
@@ -196310,6 +196518,9 @@ async function installHooks(agent, projectRoot, global2 = false) {
196310
196518
  case "claude":
196311
196519
  events.push("session_start", "post_tool", "user_prompt", "pre_compact", "session_end");
196312
196520
  break;
196521
+ case "qwen":
196522
+ events.push("session_start", "session_end", "user_prompt", "post_tool", "pre_compact", "post_compact");
196523
+ break;
196313
196524
  case "copilot":
196314
196525
  events.push("session_start", "session_end", "user_prompt", "post_tool");
196315
196526
  break;
@@ -196351,7 +196562,7 @@ async function installAgentRules(agent, projectRoot, global2 = false) {
196351
196562
  const rulesPath = getAgentRulesPath(agent, rulesRoot, global2);
196352
196563
  try {
196353
196564
  await fs19.mkdir(path31.dirname(rulesPath), { recursive: true });
196354
- if (agent === "claude" || agent === "codex" || agent === "opencode" || agent === "antigravity" || agent === "gemini-cli" || agent === "dsh" || agent === "grok") {
196565
+ if (agent === "claude" || agent === "qwen" || agent === "codex" || agent === "opencode" || agent === "antigravity" || agent === "gemini-cli" || agent === "dsh" || agent === "grok") {
196355
196566
  try {
196356
196567
  const existing = await fs19.readFile(rulesPath, "utf-8");
196357
196568
  await fs19.writeFile(rulesPath, mergeMemorixRulesContent(existing, rulesContent), "utf-8");
@@ -196529,6 +196740,15 @@ async function uninstallHooks(agent, projectRoot, global2 = false) {
196529
196740
  await fs19.writeFile(configPath, JSON.stringify(cleaned, null, 2), "utf-8");
196530
196741
  }
196531
196742
  success2 = true;
196743
+ } else if (agent === "qwen") {
196744
+ const config2 = await readQwenHookConfig(configPath);
196745
+ const cleaned = removeMemorixQwenHooks(config2);
196746
+ if (Object.keys(cleaned).length === 0) {
196747
+ await fs19.unlink(configPath);
196748
+ } else {
196749
+ await fs19.writeFile(configPath, JSON.stringify(cleaned, null, 2), "utf-8");
196750
+ }
196751
+ success2 = true;
196532
196752
  } else if (agent === "kiro" || agent === "opencode") {
196533
196753
  await fs19.unlink(configPath);
196534
196754
  success2 = true;
@@ -196552,13 +196772,13 @@ async function uninstallHooks(agent, projectRoot, global2 = false) {
196552
196772
  const agentFiles = prevFiles.filter((e5) => e5.agent === agent);
196553
196773
  for (const entry of agentFiles) {
196554
196774
  try {
196555
- if (agent === "grok" && path31.resolve(entry.path) === path31.resolve(configPath)) {
196775
+ if ((agent === "grok" || agent === "qwen") && path31.resolve(entry.path) === path31.resolve(configPath)) {
196556
196776
  await removeFile2(projectRoot, entry.path);
196557
196777
  auditCleaned = true;
196558
196778
  continue;
196559
196779
  }
196560
196780
  const basename7 = path31.basename(entry.path);
196561
- if (basename7 === "AGENTS.md" || basename7 === "GEMINI.md" || basename7 === "CONTEXT.md") {
196781
+ if (basename7 === "AGENTS.md" || basename7 === "GEMINI.md" || basename7 === "QWEN.md" || basename7 === "CONTEXT.md") {
196562
196782
  try {
196563
196783
  const content = await fs19.readFile(entry.path, "utf-8");
196564
196784
  const memorixStart = content.indexOf("# Memorix");
@@ -196617,7 +196837,7 @@ async function uninstallHooks(agent, projectRoot, global2 = false) {
196617
196837
  }
196618
196838
  async function getHookStatus(projectRoot) {
196619
196839
  const results = [];
196620
- const agents = ["claude", "copilot", "windsurf", "cursor", "kiro", "codex", "antigravity", "gemini-cli", "opencode", "pi", "trae", "grok"];
196840
+ const agents = ["claude", "qwen", "copilot", "windsurf", "cursor", "kiro", "codex", "antigravity", "gemini-cli", "opencode", "pi", "trae", "grok"];
196621
196841
  for (const agent of agents) {
196622
196842
  const projectPath = getProjectConfigPath(agent, projectRoot);
196623
196843
  const globalPath = getGlobalConfigPath(agent);
@@ -196670,7 +196890,7 @@ var init_installers = __esm({
196670
196890
  "use strict";
196671
196891
  init_esm_shims();
196672
196892
  init_official_skills();
196673
- OPENCODE_PLUGIN_VERSION = 8;
196893
+ OPENCODE_PLUGIN_VERSION = 9;
196674
196894
  AGENT_SKILL_DIRS = {
196675
196895
  cursor: { project: path31.join(".cursor", "skills"), global: path31.join(".cursor", "skills") },
196676
196896
  windsurf: { project: path31.join(".windsurf", "skills"), global: path31.join(".windsurf", "skills") },
@@ -198379,6 +198599,7 @@ async function installSingleAgent(installHooks2, agent, targetRoot, global2) {
198379
198599
  function getAgentLabel(agent) {
198380
198600
  const labels = {
198381
198601
  claude: "Claude Code",
198602
+ qwen: "Qwen Code",
198382
198603
  windsurf: "Windsurf",
198383
198604
  cursor: "Cursor",
198384
198605
  copilot: "GitHub Copilot",
@@ -198397,6 +198618,7 @@ function getAgentLabel(agent) {
198397
198618
  function getAgentHint(agent) {
198398
198619
  const hints = {
198399
198620
  claude: "settings + instructions",
198621
+ qwen: "settings.json hooks + QWEN.md guidance",
198400
198622
  windsurf: "hooks + rules",
198401
198623
  cursor: "hooks + rules",
198402
198624
  copilot: "hooks + instructions",
@@ -201557,7 +201779,7 @@ async function getSessionContext(projectDir2, projectId, limit2 = 3, reader2) {
201557
201779
  lines.push("## Key Project Memories");
201558
201780
  lines.push("*Durable working context \u2014 explicit decisions, gotchas, and discoveries.*");
201559
201781
  for (const obs of l2Obs) {
201560
- const emoji3 = TYPE_EMOJI[obs.type] ?? "[PIN]";
201782
+ const emoji3 = OBSERVATION_ICONS[obs.type] ?? "[PIN]";
201561
201783
  const fact = obs.facts?.[0] ? ` \u2014 ${redactCredentials(obs.facts[0])}` : "";
201562
201784
  lines.push(`${emoji3} ${redactCredentials(obs.title)}${fact}`);
201563
201785
  }
@@ -201605,11 +201827,12 @@ async function getActiveSession(projectDir2, projectId) {
201605
201827
  const sessions = await loadAliasActiveSessions(aliasSet);
201606
201828
  return sessions.sort((a4, b4) => new Date(b4.startedAt).getTime() - new Date(a4.startedAt).getTime())[0] ?? null;
201607
201829
  }
201608
- var PRIORITY_TYPES, RESUME_TYPES, TYPE_EMOJI, TYPE_WEIGHTS, NOISE_PATTERNS, COMMAND_TRACE_PATTERNS, SYSTEM_SELF_PATTERNS, SESSION_RESUME_OBSERVATION_LIMIT, SESSION_CONTEXT_OBSERVATION_LIMIT, AUTO_RESUME_SUMMARY_LIMIT, AUTO_RESUME_TITLE_LIMIT;
201830
+ var PRIORITY_TYPES, RESUME_TYPES, TYPE_WEIGHTS, NOISE_PATTERNS, COMMAND_TRACE_PATTERNS, SYSTEM_SELF_PATTERNS, SESSION_RESUME_OBSERVATION_LIMIT, SESSION_CONTEXT_OBSERVATION_LIMIT, AUTO_RESUME_SUMMARY_LIMIT, AUTO_RESUME_TITLE_LIMIT;
201609
201831
  var init_session = __esm({
201610
201832
  "src/memory/session.ts"() {
201611
201833
  "use strict";
201612
201834
  init_esm_shims();
201835
+ init_types2();
201613
201836
  init_admission();
201614
201837
  init_disclosure_policy();
201615
201838
  init_aliases();
@@ -201637,18 +201860,6 @@ var init_session = __esm({
201637
201860
  "what-changed",
201638
201861
  "reasoning"
201639
201862
  ]);
201640
- TYPE_EMOJI = {
201641
- "gotcha": "[DISCOVERY]",
201642
- "decision": "[WHY]",
201643
- "problem-solution": "[FIX]",
201644
- "trade-off": "[TRADEOFF]",
201645
- "discovery": "[DISCOVERY]",
201646
- "how-it-works": "[INFO]",
201647
- "what-changed": "[CHANGE]",
201648
- "why-it-exists": "[DECISION]",
201649
- "session-request": "[SESSION]",
201650
- "probe": "[PROBE]"
201651
- };
201652
201863
  TYPE_WEIGHTS = {
201653
201864
  "gotcha": 6,
201654
201865
  "decision": 5.5,
@@ -209197,7 +209408,7 @@ var init_tool_profile = __esm({
209197
209408
  function getMcpServerInfo() {
209198
209409
  return {
209199
209410
  name: "memorix",
209200
- version: true ? "1.9.9" : "1.0.1"
209411
+ version: true ? "1.9.11" : "1.0.1"
209201
209412
  };
209202
209413
  }
209203
209414
  function createMcpDiscoverResult(capabilities, serverInfo) {
@@ -211650,6 +211861,9 @@ var init_protocol = __esm({
211650
211861
  this.setRequestHandler(GetTaskPayloadRequestSchema, async (request, extra) => {
211651
211862
  const handleTaskResult = async () => {
211652
211863
  const taskId = request.params.taskId;
211864
+ if (!await this._taskStore.getTask(taskId, extra.sessionId)) {
211865
+ throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
211866
+ }
211653
211867
  if (this._taskMessageQueue) {
211654
211868
  let queuedMessage;
211655
211869
  while (queuedMessage = await this._taskMessageQueue.dequeue(taskId, extra.sessionId)) {
@@ -211680,12 +211894,12 @@ var init_protocol = __esm({
211680
211894
  throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
211681
211895
  }
211682
211896
  if (!isTerminal(task.status)) {
211683
- await this._waitForTaskUpdate(taskId, extra.signal);
211897
+ await this._waitForTaskUpdate(taskId, extra.signal, extra.sessionId);
211684
211898
  return await handleTaskResult();
211685
211899
  }
211686
211900
  if (isTerminal(task.status)) {
211687
211901
  const result = await this._taskStore.getTaskResult(taskId, extra.sessionId);
211688
- this._clearTaskQueue(taskId);
211902
+ this._clearTaskQueue(taskId, extra.sessionId);
211689
211903
  return {
211690
211904
  ...result,
211691
211905
  _meta: {
@@ -211722,7 +211936,7 @@ var init_protocol = __esm({
211722
211936
  throw new McpError(ErrorCode.InvalidParams, `Cannot cancel task in terminal status: ${task.status}`);
211723
211937
  }
211724
211938
  await this._taskStore.updateTaskStatus(request.params.taskId, "cancelled", "Client cancelled task execution.", extra.sessionId);
211725
- this._clearTaskQueue(request.params.taskId);
211939
+ this._clearTaskQueue(request.params.taskId, extra.sessionId);
211726
211940
  const cancelledTask = await this._taskStore.getTask(request.params.taskId, extra.sessionId);
211727
211941
  if (!cancelledTask) {
211728
211942
  throw new McpError(ErrorCode.InvalidParams, `Task not found after cancellation: ${request.params.taskId}`);
@@ -211850,6 +212064,19 @@ var init_protocol = __esm({
211850
212064
  const handler = this._requestHandlers.get(request.method) ?? this.fallbackRequestHandler;
211851
212065
  const capturedTransport = this._transport;
211852
212066
  const relatedTaskId = request.params?._meta?.[RELATED_TASK_META_KEY]?.taskId;
212067
+ const sessionId = capturedTransport?.sessionId;
212068
+ const store2 = this._taskStore;
212069
+ let relatedTaskFound = true;
212070
+ let relatedTaskLookup;
212071
+ if (relatedTaskId && store2 && this._taskMessageQueue && sessionId !== void 0) {
212072
+ relatedTaskFound = false;
212073
+ relatedTaskLookup = (async () => {
212074
+ if (!await store2.getTask(relatedTaskId, sessionId)) {
212075
+ throw new McpError(ErrorCode.InvalidParams, `Task not found: ${relatedTaskId}`);
212076
+ }
212077
+ relatedTaskFound = true;
212078
+ })();
212079
+ }
211853
212080
  if (handler === void 0) {
211854
212081
  const errorResponse = {
211855
212082
  jsonrpc: "2.0",
@@ -211859,7 +212086,10 @@ var init_protocol = __esm({
211859
212086
  message: "Method not found"
211860
212087
  }
211861
212088
  };
211862
- if (relatedTaskId && this._taskMessageQueue) {
212089
+ if (relatedTaskId && relatedTaskLookup) {
212090
+ const queuedError = { type: "error", message: errorResponse, timestamp: Date.now() };
212091
+ relatedTaskLookup.then(() => this._enqueueTaskMessage(relatedTaskId, queuedError, sessionId), () => capturedTransport?.send(errorResponse)).catch((error40) => this._onerror(new Error(`Failed to send an error response: ${error40}`)));
212092
+ } else if (relatedTaskId && this._taskMessageQueue) {
211863
212093
  this._enqueueTaskMessage(relatedTaskId, {
211864
212094
  type: "error",
211865
212095
  message: errorResponse,
@@ -211910,7 +212140,10 @@ var init_protocol = __esm({
211910
212140
  closeSSEStream: extra?.closeSSEStream,
211911
212141
  closeStandaloneSSEStream: extra?.closeStandaloneSSEStream
211912
212142
  };
211913
- Promise.resolve().then(() => {
212143
+ (relatedTaskLookup ?? Promise.resolve()).then(() => {
212144
+ if (relatedTaskLookup && abortController.signal.aborted) {
212145
+ throw new McpError(ErrorCode.ConnectionClosed, "Request was cancelled");
212146
+ }
211914
212147
  if (taskCreationParams) {
211915
212148
  this.assertTaskHandlerCapability(request.method);
211916
212149
  }
@@ -211945,7 +212178,7 @@ var init_protocol = __esm({
211945
212178
  ...error40["data"] !== void 0 && { data: error40["data"] }
211946
212179
  }
211947
212180
  };
211948
- if (relatedTaskId && this._taskMessageQueue) {
212181
+ if (relatedTaskId && this._taskMessageQueue && relatedTaskFound) {
211949
212182
  await this._enqueueTaskMessage(relatedTaskId, {
211950
212183
  type: "error",
211951
212184
  message: errorResponse,
@@ -212425,7 +212658,7 @@ var init_protocol = __esm({
212425
212658
  throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");
212426
212659
  }
212427
212660
  const maxQueueSize = this._options?.maxTaskQueueSize;
212428
- await this._taskMessageQueue.enqueue(taskId, message, sessionId, maxQueueSize);
212661
+ await this._taskMessageQueue.enqueue(taskId, message, sessionId ?? this._transport?.sessionId, maxQueueSize);
212429
212662
  }
212430
212663
  /**
212431
212664
  * Clears the message queue for a task and rejects any pending request resolvers.
@@ -212454,12 +212687,13 @@ var init_protocol = __esm({
212454
212687
  * Uses polling to check for updates at the task's configured poll interval.
212455
212688
  * @param taskId The task ID to wait for
212456
212689
  * @param signal Abort signal to cancel the wait
212690
+ * @param sessionId Session of the request that waits, passed to the task store
212457
212691
  * @returns Promise that resolves when an update occurs or rejects if aborted
212458
212692
  */
212459
- async _waitForTaskUpdate(taskId, signal) {
212693
+ async _waitForTaskUpdate(taskId, signal, sessionId) {
212460
212694
  let interval = this._options?.defaultTaskPollInterval ?? 1e3;
212461
212695
  try {
212462
- const task = await this._taskStore?.getTask(taskId);
212696
+ const task = await this._taskStore?.getTask(taskId, sessionId);
212463
212697
  if (task?.pollInterval) {
212464
212698
  interval = task.pollInterval;
212465
212699
  }
@@ -215644,9 +215878,28 @@ var require_utils = __commonJS({
215644
215878
  init_esm_shims();
215645
215879
  var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
215646
215880
  var isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
215881
+ var isPort = RegExp.prototype.test.bind(/^\d*$/u);
215647
215882
  var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
215648
215883
  var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
215649
- var isPathCharacter = RegExp.prototype.test.bind(/^[\da-z\-._~!$&'()*+,;=:@/]$/iu);
215884
+ var isPathCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/]$/u);
215885
+ var isQueryFragmentCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/?]$/u);
215886
+ var isUserinfoCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:]$/u);
215887
+ var BYTE_HEX = new Array(256);
215888
+ {
215889
+ const HEX_DIGITS = "0123456789ABCDEF";
215890
+ for (let i4 = 0; i4 < 256; i4++) {
215891
+ BYTE_HEX[i4] = "%" + HEX_DIGITS[i4 >> 4] + HEX_DIGITS[i4 & 15];
215892
+ }
215893
+ }
215894
+ function percentEncodeNonAscii(cp) {
215895
+ if (cp < 2048) {
215896
+ return BYTE_HEX[192 | cp >> 6] + BYTE_HEX[128 | cp & 63];
215897
+ }
215898
+ if (cp < 65536) {
215899
+ return BYTE_HEX[224 | cp >> 12] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
215900
+ }
215901
+ return BYTE_HEX[240 | cp >> 18] + BYTE_HEX[128 | cp >> 12 & 63] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
215902
+ }
215650
215903
  function stringArrayToHexStripped(input) {
215651
215904
  let acc = "";
215652
215905
  let code = 0;
@@ -215671,91 +215924,105 @@ var require_utils = __commonJS({
215671
215924
  }
215672
215925
  return acc;
215673
215926
  }
215927
+ var isHextet = RegExp.prototype.test.bind(/^[\dA-Fa-f]{1,4}$/);
215928
+ var isIPvFuture = RegExp.prototype.test.bind(/^[vV][\dA-Fa-f]+\.[A-Za-z\d\-._~!$&'()*+,;=:]+$/);
215929
+ var isZoneCharacter = RegExp.prototype.test.bind(/^[A-Za-z\d\-._~]$/);
215674
215930
  var nonSimpleDomain = RegExp.prototype.test.bind(/[^!"$&'()*+,\-.;=_`a-z{}~]/u);
215675
- function consumeIsZone(buffer) {
215676
- buffer.length = 0;
215677
- return true;
215678
- }
215679
- function consumeHextets(buffer, address, output) {
215680
- if (buffer.length) {
215681
- const hex = stringArrayToHexStripped(buffer);
215682
- if (hex !== "") {
215683
- address.push(hex);
215684
- } else {
215685
- output.error = true;
215686
- return false;
215931
+ function isZoneIdentifier(zone) {
215932
+ if (zone.length === 0) return false;
215933
+ for (let i4 = 0; i4 < zone.length; i4++) {
215934
+ if (isZoneCharacter(zone[i4])) continue;
215935
+ if (zone[i4] === "%" && i4 + 2 < zone.length && isHexPair(zone.slice(i4 + 1, i4 + 3))) {
215936
+ i4 += 2;
215937
+ continue;
215687
215938
  }
215688
- buffer.length = 0;
215939
+ return false;
215689
215940
  }
215690
215941
  return true;
215691
215942
  }
215692
- function getIPV6(input) {
215693
- let tokenCount = 0;
215694
- const output = { error: false, address: "", zone: "" };
215695
- const address = [];
215696
- const buffer = [];
215697
- let endipv6Encountered = false;
215698
- let endIpv6 = false;
215699
- let consume = consumeHextets;
215700
- for (let i4 = 0; i4 < input.length; i4++) {
215701
- const cursor = input[i4];
215702
- if (cursor === "[" || cursor === "]") {
215703
- continue;
215704
- }
215705
- if (cursor === ":") {
215706
- if (endipv6Encountered === true) {
215707
- endIpv6 = true;
215943
+ function compressIPv6ZeroRun(hextets) {
215944
+ let bestStart = -1;
215945
+ let bestLength = 0;
215946
+ let runStart = -1;
215947
+ let runLength = 0;
215948
+ for (let i4 = 0; i4 < hextets.length; i4++) {
215949
+ if (hextets[i4] === "0") {
215950
+ if (runStart === -1) runStart = i4;
215951
+ runLength++;
215952
+ if (runLength > bestLength) {
215953
+ bestLength = runLength;
215954
+ bestStart = runStart;
215708
215955
  }
215709
- if (!consume(buffer, address, output)) {
215710
- break;
215711
- }
215712
- if (++tokenCount > 7) {
215713
- output.error = true;
215714
- break;
215715
- }
215716
- if (i4 > 0 && input[i4 - 1] === ":") {
215717
- endipv6Encountered = true;
215718
- }
215719
- address.push(":");
215720
- continue;
215721
- } else if (cursor === "%") {
215722
- if (!consume(buffer, address, output)) {
215723
- break;
215724
- }
215725
- consume = consumeIsZone;
215726
215956
  } else {
215727
- buffer.push(cursor);
215957
+ runStart = -1;
215958
+ runLength = 0;
215959
+ }
215960
+ }
215961
+ if (bestLength < 2) return hextets.join(":");
215962
+ const head = hextets.slice(0, bestStart).join(":");
215963
+ const tail = hextets.slice(bestStart + bestLength).join(":");
215964
+ return head + "::" + tail;
215965
+ }
215966
+ function normalizeIPv6Address(input) {
215967
+ const compression = input.indexOf("::");
215968
+ if (compression !== -1 && input.indexOf("::", compression + 1) !== -1) return void 0;
215969
+ const left = compression === -1 ? input.split(":") : input.slice(0, compression).split(":");
215970
+ const right = compression === -1 ? [] : input.slice(compression + 2).split(":");
215971
+ if (compression !== -1) {
215972
+ if (left.length === 1 && left[0] === "") left.length = 0;
215973
+ if (right.length === 1 && right[0] === "") right.length = 0;
215974
+ }
215975
+ const parts = left.concat(right);
215976
+ let hextetCount = 0;
215977
+ for (let i4 = 0; i4 < parts.length; i4++) {
215978
+ const part = parts[i4];
215979
+ if (part === "") return void 0;
215980
+ if (part.indexOf(".") !== -1) {
215981
+ if (i4 !== parts.length - 1 || compression !== -1 && right.length === 0 || !isIPv4(part)) return void 0;
215982
+ hextetCount += 2;
215728
215983
  continue;
215729
215984
  }
215985
+ if (!isHextet(part)) return void 0;
215986
+ parts[i4] = parseInt(part, 16).toString(16);
215987
+ hextetCount++;
215730
215988
  }
215731
- if (buffer.length) {
215732
- if (consume === consumeIsZone) {
215733
- output.zone = buffer.join("");
215734
- } else if (endIpv6) {
215735
- address.push(buffer.join(""));
215736
- } else {
215737
- address.push(stringArrayToHexStripped(buffer));
215738
- }
215989
+ if (compression === -1) {
215990
+ if (hextetCount !== 8) return void 0;
215991
+ return compressIPv6ZeroRun(parts);
215739
215992
  }
215740
- output.address = address.join("");
215741
- return output;
215993
+ if (hextetCount >= 8) return void 0;
215994
+ const expanded = parts.slice(0, left.length);
215995
+ for (let i4 = hextetCount; i4 < 8; i4++) expanded.push("0");
215996
+ for (let i4 = left.length; i4 < parts.length; i4++) expanded.push(parts[i4]);
215997
+ return compressIPv6ZeroRun(expanded);
215742
215998
  }
215743
215999
  function normalizeIPv6(host) {
215744
- if (findToken(host, ":") < 2) {
215745
- return { host, isIPV6: false };
215746
- }
215747
- const ipv63 = getIPV6(host);
215748
- if (!ipv63.error) {
215749
- let newHost = ipv63.address;
215750
- let escapedHost = ipv63.address;
215751
- if (ipv63.zone) {
215752
- newHost += "%" + ipv63.zone;
215753
- escapedHost += "%25" + ipv63.zone;
215754
- }
215755
- return { host: newHost, isIPV6: true, escapedHost };
215756
- } else {
215757
- return { host, isIPV6: false };
215758
- }
216000
+ const bracketed = host[0] === "[" && host[host.length - 1] === "]";
216001
+ const hasBracket = host[0] === "[" || host[host.length - 1] === "]";
216002
+ if (hasBracket && !bracketed) return { host, isIPV6: false, error: true };
216003
+ let input = bracketed ? host.slice(1, -1) : host;
216004
+ if (bracketed && isIPvFuture(input)) {
216005
+ input = input.toLowerCase();
216006
+ return { host: `[${input}]`, escapedHost: input, isIPV6: false, isIPVFuture: true };
216007
+ }
216008
+ if (findToken(input, ":") < 2) {
216009
+ return { host, isIPV6: false, error: bracketed };
216010
+ }
216011
+ let zoneIdentifier = "";
216012
+ const zoneSeparator = input.indexOf("%");
216013
+ if (zoneSeparator !== -1) {
216014
+ const separatorLength = input.slice(zoneSeparator, zoneSeparator + 3).toLowerCase() === "%25" ? 3 : 1;
216015
+ zoneIdentifier = input.slice(zoneSeparator + separatorLength);
216016
+ if (!isZoneIdentifier(zoneIdentifier)) return { host, isIPV6: false, error: true };
216017
+ input = input.slice(0, zoneSeparator);
216018
+ }
216019
+ const address = normalizeIPv6Address(input);
216020
+ if (address === void 0) return { host, isIPV6: false, error: true };
216021
+ return {
216022
+ host: address + (zoneIdentifier ? "%" + zoneIdentifier : ""),
216023
+ escapedHost: address + (zoneIdentifier ? "%25" + zoneIdentifier : ""),
216024
+ isIPV6: true
216025
+ };
215759
216026
  }
215760
216027
  function findToken(str2, token) {
215761
216028
  let ind = 0;
@@ -215874,7 +216141,8 @@ var require_utils = __commonJS({
215874
216141
  function normalizePathEncoding(input) {
215875
216142
  let output = "";
215876
216143
  for (let i4 = 0; i4 < input.length; i4++) {
215877
- if (input[i4] === "%" && i4 + 2 < input.length) {
216144
+ const ch2 = input[i4];
216145
+ if (ch2 === "%" && i4 + 2 < input.length) {
215878
216146
  const hex = input.slice(i4 + 1, i4 + 3);
215879
216147
  if (isHexPair(hex)) {
215880
216148
  const normalizedHex = hex.toUpperCase();
@@ -215888,10 +216156,152 @@ var require_utils = __commonJS({
215888
216156
  continue;
215889
216157
  }
215890
216158
  }
215891
- if (isPathCharacter(input[i4])) {
215892
- output += input[i4];
216159
+ if (isPathCharacter(ch2)) {
216160
+ output += ch2;
216161
+ } else {
216162
+ const code = input.charCodeAt(i4);
216163
+ if (code < 128) {
216164
+ output += isEscapeSafe(code) ? ch2 : BYTE_HEX[code];
216165
+ } else if (code < 55296 || code > 57343) {
216166
+ output += percentEncodeNonAscii(code);
216167
+ } else if (code <= 56319 && i4 + 1 < input.length) {
216168
+ const low = input.charCodeAt(i4 + 1);
216169
+ if (low >= 56320 && low <= 57343) {
216170
+ output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
216171
+ i4++;
216172
+ } else {
216173
+ output += percentEncodeNonAscii(65533);
216174
+ }
216175
+ } else {
216176
+ output += percentEncodeNonAscii(65533);
216177
+ }
216178
+ }
216179
+ }
216180
+ return output;
216181
+ }
216182
+ function serializePathEncoding(input, pathNoScheme = false) {
216183
+ let output = "";
216184
+ let firstSegment = pathNoScheme && input[0] !== "/";
216185
+ for (let i4 = 0; i4 < input.length; i4++) {
216186
+ const ch2 = input[i4];
216187
+ if (ch2 === "%" && i4 + 2 < input.length) {
216188
+ const hex = input.slice(i4 + 1, i4 + 3);
216189
+ if (isHexPair(hex)) {
216190
+ output += "%" + hex.toUpperCase();
216191
+ i4 += 2;
216192
+ continue;
216193
+ }
216194
+ }
216195
+ if (ch2 === "/") {
216196
+ firstSegment = false;
216197
+ }
216198
+ if (isPathCharacter(ch2) && (ch2 !== ":" || !firstSegment)) {
216199
+ output += ch2;
216200
+ } else {
216201
+ const code = input.charCodeAt(i4);
216202
+ if (code < 128) {
216203
+ output += BYTE_HEX[code];
216204
+ } else if (code < 55296 || code > 57343) {
216205
+ output += percentEncodeNonAscii(code);
216206
+ } else if (code <= 56319 && i4 + 1 < input.length) {
216207
+ const low = input.charCodeAt(i4 + 1);
216208
+ if (low >= 56320 && low <= 57343) {
216209
+ output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
216210
+ i4++;
216211
+ } else {
216212
+ output += percentEncodeNonAscii(65533);
216213
+ }
216214
+ } else {
216215
+ output += percentEncodeNonAscii(65533);
216216
+ }
216217
+ }
216218
+ }
216219
+ return output;
216220
+ }
216221
+ function encodeComponent(input, isAllowed) {
216222
+ let output = "";
216223
+ for (let i4 = 0; i4 < input.length; i4++) {
216224
+ const ch2 = input[i4];
216225
+ if (ch2 === "%" && i4 + 2 < input.length) {
216226
+ const hex = input.slice(i4 + 1, i4 + 3);
216227
+ if (isHexPair(hex)) {
216228
+ output += "%" + hex.toUpperCase();
216229
+ i4 += 2;
216230
+ continue;
216231
+ }
216232
+ }
216233
+ if (isAllowed(ch2)) {
216234
+ output += ch2;
216235
+ } else {
216236
+ const code = input.charCodeAt(i4);
216237
+ if (code < 128) {
216238
+ output += BYTE_HEX[code];
216239
+ } else if (code < 55296 || code > 57343) {
216240
+ output += percentEncodeNonAscii(code);
216241
+ } else if (code <= 56319 && i4 + 1 < input.length) {
216242
+ const low = input.charCodeAt(i4 + 1);
216243
+ if (low >= 56320 && low <= 57343) {
216244
+ output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
216245
+ i4++;
216246
+ } else {
216247
+ output += percentEncodeNonAscii(65533);
216248
+ }
216249
+ } else {
216250
+ output += percentEncodeNonAscii(65533);
216251
+ }
216252
+ }
216253
+ }
216254
+ return output;
216255
+ }
216256
+ function encodeUserinfo(input) {
216257
+ return encodeComponent(input, isUserinfoCharacter);
216258
+ }
216259
+ function encodeQuery(input) {
216260
+ return encodeComponent(input, isQueryFragmentCharacter);
216261
+ }
216262
+ function encodeFragment(input) {
216263
+ return encodeComponent(input, isQueryFragmentCharacter);
216264
+ }
216265
+ function isEscapeSafe(cp) {
216266
+ return cp >= 48 && cp <= 57 || cp >= 65 && cp <= 90 || cp >= 97 && cp <= 122 || cp === 42 || cp === 43 || cp === 45 || cp === 46 || cp === 47 || cp === 64 || cp === 95;
216267
+ }
216268
+ function normalizeQueryFragmentEncoding(input) {
216269
+ let output = "";
216270
+ for (let i4 = 0; i4 < input.length; i4++) {
216271
+ const ch2 = input[i4];
216272
+ if (ch2 === "%" && i4 + 2 < input.length) {
216273
+ const hex = input.slice(i4 + 1, i4 + 3);
216274
+ if (isHexPair(hex)) {
216275
+ const normalizedHex = hex.toUpperCase();
216276
+ const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
216277
+ if (isUnreserved(decoded)) {
216278
+ output += decoded;
216279
+ } else {
216280
+ output += "%" + normalizedHex;
216281
+ }
216282
+ i4 += 2;
216283
+ continue;
216284
+ }
216285
+ }
216286
+ if (isQueryFragmentCharacter(ch2)) {
216287
+ output += ch2;
215893
216288
  } else {
215894
- output += escape(input[i4]);
216289
+ const code = input.charCodeAt(i4);
216290
+ if (code < 128) {
216291
+ output += isEscapeSafe(code) ? ch2 : BYTE_HEX[code];
216292
+ } else if (code < 55296 || code > 57343) {
216293
+ output += percentEncodeNonAscii(code);
216294
+ } else if (code <= 56319 && i4 + 1 < input.length) {
216295
+ const low = input.charCodeAt(i4 + 1);
216296
+ if (low >= 56320 && low <= 57343) {
216297
+ output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
216298
+ i4++;
216299
+ } else {
216300
+ output += percentEncodeNonAscii(65533);
216301
+ }
216302
+ } else {
216303
+ output += percentEncodeNonAscii(65533);
216304
+ }
215895
216305
  }
215896
216306
  }
215897
216307
  return output;
@@ -215914,14 +216324,18 @@ var require_utils = __commonJS({
215914
216324
  function recomposeAuthority(component) {
215915
216325
  const uriTokens = [];
215916
216326
  if (component.userinfo !== void 0) {
215917
- uriTokens.push(component.userinfo);
216327
+ uriTokens.push(encodeUserinfo(component.userinfo));
215918
216328
  uriTokens.push("@");
215919
216329
  }
215920
216330
  if (component.host !== void 0) {
215921
- let host = unescape(component.host);
216331
+ let host = component.host;
215922
216332
  if (!isIPv4(host)) {
215923
- const ipV6res = normalizeIPv6(host);
215924
- if (ipV6res.isIPV6 === true) {
216333
+ let ipV6res = normalizeIPv6(host);
216334
+ if (ipV6res.isIPV6 !== true && ipV6res.isIPVFuture !== true) {
216335
+ host = normalizePercentEncoding(host, true);
216336
+ ipV6res = normalizeIPv6(host);
216337
+ }
216338
+ if (ipV6res.isIPV6 === true || ipV6res.isIPVFuture === true) {
215925
216339
  host = `[${ipV6res.escapedHost}]`;
215926
216340
  } else {
215927
216341
  host = reescapeHostDelimiters(host, false);
@@ -215930,8 +216344,12 @@ var require_utils = __commonJS({
215930
216344
  uriTokens.push(host);
215931
216345
  }
215932
216346
  if (typeof component.port === "number" || typeof component.port === "string") {
216347
+ const port = String(component.port);
216348
+ if (!isPort(port)) {
216349
+ throw new TypeError("URI port is malformed.");
216350
+ }
215933
216351
  uriTokens.push(":");
215934
- uriTokens.push(String(component.port));
216352
+ uriTokens.push(port);
215935
216353
  }
215936
216354
  return uriTokens.length ? uriTokens.join("") : void 0;
215937
216355
  }
@@ -215941,6 +216359,11 @@ var require_utils = __commonJS({
215941
216359
  reescapeHostDelimiters,
215942
216360
  normalizePercentEncoding,
215943
216361
  normalizePathEncoding,
216362
+ serializePathEncoding,
216363
+ normalizeQueryFragmentEncoding,
216364
+ encodeUserinfo,
216365
+ encodeQuery,
216366
+ encodeFragment,
215944
216367
  escapePreservingEscapes,
215945
216368
  removeDotSegments,
215946
216369
  isIPv4,
@@ -215957,7 +216380,7 @@ var require_schemes = __commonJS({
215957
216380
  "use strict";
215958
216381
  init_esm_shims();
215959
216382
  var { isUUID } = require_utils();
215960
- var URN_REG = /([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-.:;=@]|%[\da-f]{2})+)/iu;
216383
+ var URN_REG = /^([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-./:;=@]|%[\da-f]{2})+)$/iu;
215961
216384
  var supportedSchemeNames = (
215962
216385
  /** @type {const} */
215963
216386
  [
@@ -216018,9 +216441,10 @@ var require_schemes = __commonJS({
216018
216441
  wsComponent.secure = void 0;
216019
216442
  }
216020
216443
  if (wsComponent.resourceName) {
216021
- const [path50, query] = wsComponent.resourceName.split("?");
216444
+ const queryIndex = wsComponent.resourceName.indexOf("?");
216445
+ const path50 = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
216022
216446
  wsComponent.path = path50 && path50 !== "/" ? path50 : void 0;
216023
- wsComponent.query = query;
216447
+ wsComponent.query = queryIndex === -1 ? void 0 : wsComponent.resourceName.slice(queryIndex + 1);
216024
216448
  wsComponent.resourceName = void 0;
216025
216449
  }
216026
216450
  wsComponent.fragment = void 0;
@@ -216032,7 +216456,7 @@ var require_schemes = __commonJS({
216032
216456
  return urnComponent;
216033
216457
  }
216034
216458
  const matches = urnComponent.path.match(URN_REG);
216035
- if (matches) {
216459
+ if (matches && matches[0] === urnComponent.path) {
216036
216460
  const scheme = options.scheme || urnComponent.scheme || "urn";
216037
216461
  urnComponent.nid = matches[1].toLowerCase();
216038
216462
  urnComponent.nss = matches[2];
@@ -216167,8 +216591,17 @@ var require_fast_uri = __commonJS({
216167
216591
  "node_modules/fast-uri/index.js"(exports, module) {
216168
216592
  "use strict";
216169
216593
  init_esm_shims();
216170
- var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, escapePreservingEscapes, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
216594
+ var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
216171
216595
  var { SCHEMES, getSchemeHandler } = require_schemes();
216596
+ var VALID_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*$/u;
216597
+ var MALFORMED_SCHEME_ERROR = "URI scheme is malformed.";
216598
+ function decodeValidScheme(scheme) {
216599
+ const decodedScheme = unescape(String(scheme));
216600
+ if (!VALID_SCHEME.test(decodedScheme)) {
216601
+ throw new TypeError(MALFORMED_SCHEME_ERROR);
216602
+ }
216603
+ return decodedScheme;
216604
+ }
216172
216605
  function normalize(uri, options) {
216173
216606
  if (typeof uri === "string") {
216174
216607
  uri = /** @type {T} */
@@ -216181,12 +216614,34 @@ var require_fast_uri = __commonJS({
216181
216614
  }
216182
216615
  function resolve9(baseURI, relativeURI, options) {
216183
216616
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
216184
- const { parsed: baseParsed, malformedAuthorityOrPort: baseMalformed } = parseWithStatus(baseURI, schemelessOptions);
216185
- const { parsed: relativeParsed, malformedAuthorityOrPort: relativeMalformed } = parseWithStatus(relativeURI, schemelessOptions);
216186
- if (baseMalformed || relativeMalformed) {
216617
+ const {
216618
+ parsed: baseParsed,
216619
+ malformedAuthorityOrPort: baseMalformed,
216620
+ malformedPercentEncoding: baseMalformedPercentEncoding,
216621
+ malformedSchemeSpecific: baseMalformedSchemeSpecific,
216622
+ malformedHost: baseMalformedHost,
216623
+ malformedScheme: baseMalformedScheme
216624
+ } = parseWithStatus(baseURI, schemelessOptions);
216625
+ const {
216626
+ parsed: relativeParsed,
216627
+ malformedAuthorityOrPort: relativeMalformed,
216628
+ malformedPercentEncoding: relativeMalformedPercentEncoding,
216629
+ malformedSchemeSpecific: relativeMalformedSchemeSpecific,
216630
+ malformedHost: relativeMalformedHost,
216631
+ malformedScheme: relativeMalformedScheme
216632
+ } = parseWithStatus(relativeURI, schemelessOptions);
216633
+ if (baseMalformed || relativeMalformed || baseMalformedPercentEncoding || relativeMalformedPercentEncoding || baseMalformedSchemeSpecific || relativeMalformedSchemeSpecific || baseMalformedHost || relativeMalformedHost || baseMalformedScheme || relativeMalformedScheme) {
216187
216634
  throw new Error(baseParsed.error || relativeParsed.error || "URI is malformed.");
216188
216635
  }
216189
216636
  const resolved = resolveComponent(baseParsed, relativeParsed, schemelessOptions, true);
216637
+ const resolvedSchemeHandler = getSchemeHandler(options && options.scheme || resolved.scheme);
216638
+ const resolvedHost = resolved.host;
216639
+ const resolvedHostIsIP = resolvedHost !== void 0 && resolvedHost !== "" && (isIPv4(resolvedHost) || normalizeIPv6(resolvedHost).isIPV6);
216640
+ canonicalizeHost(resolved, options || {}, resolvedSchemeHandler, resolvedHostIsIP);
216641
+ const encodedASCIIHost = resolvedHost && resolvedHost.indexOf("%") !== -1 && !new RegExp("\\P{ASCII}", "u").test(resolvedHost);
216642
+ if (resolved.error && !encodedASCIIHost) {
216643
+ throw new Error(resolved.error);
216644
+ }
216190
216645
  schemelessOptions.skipEscape = true;
216191
216646
  return serialize(resolved, schemelessOptions);
216192
216647
  }
@@ -216246,7 +216701,7 @@ var require_fast_uri = __commonJS({
216246
216701
  function equal(uriA, uriB, options) {
216247
216702
  const normalizedA = normalizeComparableURI(uriA, options);
216248
216703
  const normalizedB = normalizeComparableURI(uriB, options);
216249
- return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA.toLowerCase() === normalizedB.toLowerCase();
216704
+ return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA === normalizedB;
216250
216705
  }
216251
216706
  function serialize(cmpts, opts) {
216252
216707
  const component = {
@@ -216267,19 +216722,22 @@ var require_fast_uri = __commonJS({
216267
216722
  };
216268
216723
  const options = Object.assign({}, opts);
216269
216724
  const uriTokens = [];
216725
+ if (component.scheme) {
216726
+ component.scheme = decodeValidScheme(component.scheme);
216727
+ }
216270
216728
  const schemeHandler = getSchemeHandler(options.scheme || component.scheme);
216271
216729
  if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options);
216730
+ const hasAuthority = component.userinfo !== void 0 || component.host !== void 0 || component.port !== void 0;
216731
+ const pathNoScheme = !options.skipEscape && component.scheme === void 0 && !hasAuthority;
216272
216732
  if (component.path !== void 0) {
216273
216733
  if (!options.skipEscape) {
216274
- component.path = escapePreservingEscapes(component.path);
216275
- if (component.scheme !== void 0) {
216276
- component.path = component.path.split("%3A").join(":");
216277
- }
216734
+ component.path = serializePathEncoding(component.path, pathNoScheme);
216278
216735
  } else {
216279
216736
  component.path = normalizePercentEncoding(component.path);
216280
216737
  }
216281
216738
  }
216282
216739
  if (options.reference !== "suffix" && component.scheme) {
216740
+ component.scheme = decodeValidScheme(component.scheme);
216283
216741
  uriTokens.push(component.scheme, ":");
216284
216742
  }
216285
216743
  const authority = recomposeAuthority(component);
@@ -216297,16 +216755,19 @@ var require_fast_uri = __commonJS({
216297
216755
  if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
216298
216756
  s4 = removeDotSegments(s4);
216299
216757
  }
216758
+ if (pathNoScheme) {
216759
+ s4 = serializePathEncoding(s4, true);
216760
+ }
216300
216761
  if (authority === void 0 && s4[0] === "/" && s4[1] === "/") {
216301
216762
  s4 = "/%2F" + s4.slice(2);
216302
216763
  }
216303
216764
  uriTokens.push(s4);
216304
216765
  }
216305
216766
  if (component.query !== void 0) {
216306
- uriTokens.push("?", component.query);
216767
+ uriTokens.push("?", encodeQuery(component.query));
216307
216768
  }
216308
216769
  if (component.fragment !== void 0) {
216309
- uriTokens.push("#", component.fragment);
216770
+ uriTokens.push("#", encodeFragment(component.fragment));
216310
216771
  }
216311
216772
  return uriTokens.join("");
216312
216773
  }
@@ -216322,6 +216783,35 @@ var require_fast_uri = __commonJS({
216322
216783
  }
216323
216784
  return void 0;
216324
216785
  }
216786
+ function hasMalformedPercentEncoding(component) {
216787
+ if (component === void 0) return false;
216788
+ let percent = component.indexOf("%");
216789
+ while (percent !== -1) {
216790
+ if (percent + 2 >= component.length || !/^[\da-f]{2}$/iu.test(component.slice(percent + 1, percent + 3))) {
216791
+ return true;
216792
+ }
216793
+ percent = component.indexOf("%", percent + 3);
216794
+ }
216795
+ return false;
216796
+ }
216797
+ function isIPLiteral(host) {
216798
+ return host[0] === "[" && host[host.length - 1] === "]";
216799
+ }
216800
+ function hasMalformedComponentPercentEncoding(matches) {
216801
+ const host = matches[4];
216802
+ return hasMalformedPercentEncoding(matches[3]) || host !== void 0 && !isIPLiteral(host) && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches[6]) || hasMalformedPercentEncoding(matches[7]) || hasMalformedPercentEncoding(matches[8]);
216803
+ }
216804
+ function canonicalizeHost(parsed, options, schemeHandler, isIP5) {
216805
+ if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP5 === false && nonSimpleDomain(parsed.host)) {
216806
+ try {
216807
+ parsed.host = new URL("http://" + parsed.host).hostname;
216808
+ } catch (e5) {
216809
+ parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e5;
216810
+ return true;
216811
+ }
216812
+ }
216813
+ return false;
216814
+ }
216325
216815
  function parseWithStatus(uri, opts) {
216326
216816
  const options = Object.assign({}, opts);
216327
216817
  const parsed = {
@@ -216334,6 +216824,11 @@ var require_fast_uri = __commonJS({
216334
216824
  fragment: void 0
216335
216825
  };
216336
216826
  let malformedAuthorityOrPort = false;
216827
+ let malformedPercentEncoding = false;
216828
+ let malformedSchemeSpecific = false;
216829
+ let malformedHost = false;
216830
+ let malformedIPLiteral = false;
216831
+ let malformedScheme = false;
216337
216832
  let isIP5 = false;
216338
216833
  if (options.reference === "suffix") {
216339
216834
  if (options.scheme) {
@@ -216370,6 +216865,19 @@ var require_fast_uri = __commonJS({
216370
216865
  parsed.path = matches[6] || "";
216371
216866
  parsed.query = matches[7];
216372
216867
  parsed.fragment = matches[8];
216868
+ if (parsed.scheme !== void 0) {
216869
+ const decodedScheme = unescape(parsed.scheme);
216870
+ if (VALID_SCHEME.test(decodedScheme)) {
216871
+ parsed.scheme = decodedScheme.toLowerCase();
216872
+ } else {
216873
+ parsed.error = parsed.error || MALFORMED_SCHEME_ERROR;
216874
+ malformedScheme = true;
216875
+ }
216876
+ }
216877
+ malformedPercentEncoding = hasMalformedComponentPercentEncoding(matches);
216878
+ if (malformedPercentEncoding) {
216879
+ parsed.error = parsed.error || "URI contains malformed percent-encoding.";
216880
+ }
216373
216881
  if (isNaN(parsed.port)) {
216374
216882
  parsed.port = matches[5];
216375
216883
  }
@@ -216381,9 +216889,16 @@ var require_fast_uri = __commonJS({
216381
216889
  if (parsed.host) {
216382
216890
  const ipv4result = isIPv4(parsed.host);
216383
216891
  if (ipv4result === false) {
216892
+ const bracketedIPLiteral = isIPLiteral(parsed.host);
216893
+ const hasIPLiteralBracket = parsed.host.indexOf("[") !== -1 || parsed.host.indexOf("]") !== -1;
216384
216894
  const ipv6result = normalizeIPv6(parsed.host);
216385
- parsed.host = ipv6result.host.toLowerCase();
216386
- isIP5 = ipv6result.isIPV6;
216895
+ isIP5 = ipv6result.isIPV6 || ipv6result.isIPVFuture === true;
216896
+ malformedIPLiteral = hasIPLiteralBracket && (!bracketedIPLiteral || ipv6result.error === true);
216897
+ parsed.host = isIP5 ? ipv6result.host : ipv6result.host.toLowerCase();
216898
+ if (malformedIPLiteral) {
216899
+ parsed.error = parsed.error || "URI host is malformed.";
216900
+ malformedAuthorityOrPort = true;
216901
+ }
216387
216902
  } else {
216388
216903
  isIP5 = true;
216389
216904
  }
@@ -216401,42 +216916,37 @@ var require_fast_uri = __commonJS({
216401
216916
  parsed.error = parsed.error || "URI is not a " + options.reference + " reference.";
216402
216917
  }
216403
216918
  const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
216404
- if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport)) {
216405
- if (parsed.host && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP5 === false && nonSimpleDomain(parsed.host)) {
216406
- try {
216407
- parsed.host = new URL("http://" + parsed.host).hostname;
216408
- } catch (e5) {
216409
- parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e5;
216410
- }
216919
+ if (!malformedIPLiteral) {
216920
+ malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP5);
216921
+ }
216922
+ if (uri.indexOf("%") !== -1 && parsed.host !== void 0 && !malformedIPLiteral) {
216923
+ let host = isIP5 ? parsed.host : normalizePercentEncoding(parsed.host, true);
216924
+ if (!isIP5) {
216925
+ host = normalizePercentEncoding(host.toLowerCase());
216411
216926
  }
216927
+ parsed.host = reescapeHostDelimiters(host, isIP5);
216412
216928
  }
216413
216929
  if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
216414
- if (uri.indexOf("%") !== -1) {
216415
- if (parsed.scheme !== void 0) {
216416
- parsed.scheme = unescape(parsed.scheme);
216417
- }
216418
- if (parsed.host !== void 0) {
216419
- parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP5);
216420
- }
216421
- }
216422
216930
  if (parsed.path) {
216423
216931
  parsed.path = normalizePathEncoding(parsed.path);
216424
216932
  }
216933
+ if (parsed.query) {
216934
+ parsed.query = normalizeQueryFragmentEncoding(parsed.query);
216935
+ }
216425
216936
  if (parsed.fragment) {
216426
- try {
216427
- parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
216428
- } catch {
216429
- parsed.error = parsed.error || "URI malformed";
216430
- }
216937
+ parsed.fragment = normalizeQueryFragmentEncoding(parsed.fragment);
216431
216938
  }
216432
216939
  }
216433
216940
  if (schemeHandler && schemeHandler.parse) {
216434
216941
  schemeHandler.parse(parsed, options);
216942
+ if (schemeHandler === SCHEMES.urn && parsed.nid === void 0) {
216943
+ malformedSchemeSpecific = true;
216944
+ }
216435
216945
  }
216436
216946
  } else {
216437
216947
  parsed.error = parsed.error || "URI can not be parsed.";
216438
216948
  }
216439
- return { parsed, malformedAuthorityOrPort };
216949
+ return { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
216440
216950
  }
216441
216951
  function parse5(uri, opts) {
216442
216952
  return parseWithStatus(uri, opts).parsed;
@@ -216445,20 +216955,28 @@ var require_fast_uri = __commonJS({
216445
216955
  return normalizeStringWithStatus(uri, opts).normalized;
216446
216956
  }
216447
216957
  function normalizeStringWithStatus(uri, opts) {
216448
- const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts);
216958
+ const { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = parseWithStatus(uri, opts);
216449
216959
  return {
216450
- normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
216451
- malformedAuthorityOrPort
216960
+ normalized: malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? uri : serialize(parsed, opts),
216961
+ malformedAuthorityOrPort,
216962
+ malformedPercentEncoding,
216963
+ malformedSchemeSpecific,
216964
+ malformedHost,
216965
+ malformedScheme
216452
216966
  };
216453
216967
  }
216454
216968
  function normalizeComparableURI(uri, opts) {
216455
- if (typeof uri === "string") {
216456
- const { normalized, malformedAuthorityOrPort } = normalizeStringWithStatus(uri, opts);
216457
- return malformedAuthorityOrPort ? void 0 : normalized;
216969
+ if (typeof uri !== "string" && typeof uri !== "object") {
216970
+ return void 0;
216458
216971
  }
216459
- if (typeof uri === "object") {
216460
- return serialize(uri, opts);
216972
+ let value;
216973
+ try {
216974
+ value = typeof uri === "string" ? uri : serialize(uri, opts);
216975
+ } catch {
216976
+ return void 0;
216461
216977
  }
216978
+ const { normalized, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = normalizeStringWithStatus(value, opts);
216979
+ return malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? void 0 : normalized;
216462
216980
  }
216463
216981
  var fastUri = {
216464
216982
  SCHEMES,
@@ -221070,6 +221588,42 @@ var init_mcp_server = __esm({
221070
221588
  });
221071
221589
 
221072
221590
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
221591
+ function toolInputElementCount(value, max) {
221592
+ let count3 = 0;
221593
+ const stack = [value];
221594
+ while (stack.length > 0) {
221595
+ const node = stack.pop();
221596
+ if (node === null || typeof node !== "object")
221597
+ continue;
221598
+ if (Array.isArray(node)) {
221599
+ for (const child of node) {
221600
+ if (++count3 > max)
221601
+ return count3;
221602
+ if (child !== null && typeof child === "object")
221603
+ stack.push(child);
221604
+ }
221605
+ } else {
221606
+ for (const key in node) {
221607
+ if (!Object.prototype.hasOwnProperty.call(node, key))
221608
+ continue;
221609
+ if (++count3 > max)
221610
+ return count3;
221611
+ const child = node[key];
221612
+ if (child !== null && typeof child === "object")
221613
+ stack.push(child);
221614
+ }
221615
+ }
221616
+ }
221617
+ return count3;
221618
+ }
221619
+ function resolveMaxToolInputElements(value) {
221620
+ if (value === void 0 || value === Infinity)
221621
+ return void 0;
221622
+ if (typeof value !== "number" || Number.isNaN(value) || value < 1) {
221623
+ throw new RangeError(`maxToolInputElements must be a number of at least 1, or Infinity, got ${String(value)}`);
221624
+ }
221625
+ return value;
221626
+ }
221073
221627
  function isZodTypeLike(value) {
221074
221628
  return value !== null && typeof value === "object" && "parse" in value && typeof value.parse === "function" && "safeParse" in value && typeof value.safeParse === "function";
221075
221629
  }
@@ -221160,6 +221714,7 @@ var init_mcp = __esm({
221160
221714
  this._resourceHandlersInitialized = false;
221161
221715
  this._promptHandlersInitialized = false;
221162
221716
  this.server = new Server(serverInfo, options);
221717
+ this._maxToolInputElements = resolveMaxToolInputElements(options?.maxToolInputElements);
221163
221718
  }
221164
221719
  /**
221165
221720
  * Access experimental features.
@@ -221290,12 +221845,15 @@ var init_mcp = __esm({
221290
221845
  * Validates tool input arguments against the tool's input schema.
221291
221846
  */
221292
221847
  async validateToolInput(tool, args, toolName) {
221848
+ if (this._maxToolInputElements !== void 0 && toolInputElementCount(args, this._maxToolInputElements) > this._maxToolInputElements) {
221849
+ throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for tool ${toolName}: arguments contain more than the maximum of ${this._maxToolInputElements} elements`);
221850
+ }
221293
221851
  if (!tool.inputSchema) {
221294
221852
  return void 0;
221295
221853
  }
221296
221854
  const inputObj = normalizeObjectSchema(tool.inputSchema);
221297
221855
  const schemaToParse = inputObj ?? tool.inputSchema;
221298
- const parseResult = await safeParseAsync3(schemaToParse, args);
221856
+ const parseResult = await safeParseAsync3(schemaToParse, args ?? {});
221299
221857
  if (!parseResult.success) {
221300
221858
  const error40 = "error" in parseResult ? parseResult.error : "Unknown error";
221301
221859
  const errorMessage = getParseErrorMessage(error40);
@@ -221533,7 +222091,7 @@ var init_mcp = __esm({
221533
222091
  }
221534
222092
  if (prompt2.argsSchema) {
221535
222093
  const argsObj = normalizeObjectSchema(prompt2.argsSchema);
221536
- const parseResult = await safeParseAsync3(argsObj, request.params.arguments);
222094
+ const parseResult = await safeParseAsync3(argsObj, request.params.arguments ?? {});
221537
222095
  if (!parseResult.success) {
221538
222096
  const error40 = "error" in parseResult ? parseResult.error : "Unknown error";
221539
222097
  const errorMessage = getParseErrorMessage(error40);
@@ -225130,7 +225688,8 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
225130
225688
  "OPENAI_API_KEY",
225131
225689
  "ANTHROPIC_API_KEY",
225132
225690
  ...resolved.memory.llm.provider === "openrouter" || resolved.memory.llm.baseUrl?.includes("openrouter.ai") ? ["OPENROUTER_API_KEY"] : [],
225133
- ...resolved.memory.llm.provider === "requesty" ? ["REQUESTY_API_KEY"] : []
225691
+ ...resolved.memory.llm.provider === "requesty" ? ["REQUESTY_API_KEY"] : [],
225692
+ ...resolved.memory.llm.provider === "apiroute" ? ["API_ROUTE_API_KEY"] : []
225134
225693
  ];
225135
225694
  if (llmKey) {
225136
225695
  const src2 = resolveDashboardKeySource({ value: llmKey, envKeys: memoryKeyEnv, configSource });
@@ -265461,12 +266020,13 @@ __export(image_loader_exports, {
265461
266020
  analyzeImage: () => analyzeImage
265462
266021
  });
265463
266022
  async function callVisionLLM(systemPrompt, imageBase64, mimeType) {
265464
- const apiKey = getLLMApiKey();
266023
+ const config2 = getLLMConfig();
266024
+ const apiKey = config2?.apiKey ?? getLLMApiKey();
265465
266025
  if (!apiKey) {
265466
266026
  throw new Error("No LLM API key configured for image analysis.");
265467
266027
  }
265468
- const baseUrl = normalizeOpenAICompatibleBaseUrl(getLLMBaseUrl("https://api.openai.com/v1"));
265469
- const model = getLLMModel("gpt-4o");
266028
+ const baseUrl = normalizeOpenAICompatibleBaseUrl(config2?.baseUrl ?? getLLMBaseUrl("https://api.openai.com/v1"));
266029
+ const model = config2?.model ?? getLLMModel("gpt-4o");
265470
266030
  const response = await fetch(`${baseUrl}/chat/completions`, {
265471
266031
  method: "POST",
265472
266032
  headers: {
@@ -265521,7 +266081,7 @@ async function analyzeImage(input) {
265521
266081
  const config2 = getLLMConfig();
265522
266082
  if (!OPENAI_COMPATIBLE_PROVIDERS.has(config2.provider)) {
265523
266083
  throw new Error(
265524
- `Image analysis requires an OpenAI-compatible provider (openai, openrouter, requesty, or custom). Current provider "${config2.provider}" uses a different API shape. Set MEMORIX_LLM_PROVIDER=openai or configure an OpenAI-compatible base URL.`
266084
+ `Image analysis requires an OpenAI-compatible provider (openai, openrouter, requesty, apiroute, or custom). Current provider "${config2.provider}" uses a different API shape. Set MEMORIX_LLM_PROVIDER=openai or configure an OpenAI-compatible base URL.`
265525
266085
  );
265526
266086
  }
265527
266087
  const bytes = decodeBase64ImagePayload(input.base64, MAX_VISION_IMAGE_BYTES);
@@ -265560,7 +266120,7 @@ var init_image_loader = __esm({
265560
266120
  init_provider2();
265561
266121
  init_secret_filter();
265562
266122
  init_image_payload();
265563
- OPENAI_COMPATIBLE_PROVIDERS = /* @__PURE__ */ new Set(["openai", "openrouter", "requesty", "custom"]);
266123
+ OPENAI_COMPATIBLE_PROVIDERS = /* @__PURE__ */ new Set(["openai", "openrouter", "requesty", "apiroute", "custom"]);
265564
266124
  MAX_VISION_PROMPT_CHARS = 12e3;
265565
266125
  MAX_VISION_DESCRIPTION_CHARS = 12e3;
265566
266126
  MAX_VISION_LABELS = 50;
@@ -265842,8 +266402,8 @@ async function createMemorixServer(cwd, existingServer, sharedTeam, options = {}
265842
266402
  if (!lightweightUnresolvedSession && !deferProjectRuntimeInit) {
265843
266403
  try {
265844
266404
  const { getAllObservations: getAllObservations2 } = await Promise.resolve().then(() => (init_observations(), observations_exports));
265845
- const allObs = getAllObservations2();
265846
- const observedIds = [...new Set(allObs.map((o4) => o4.projectId))];
266405
+ const store2 = getObservationStore();
266406
+ const observedIds = store2.listProjectIds ? await store2.listProjectIds() : [...new Set(getAllObservations2().map((o4) => o4.projectId))];
265847
266407
  const merged = await autoMergeByBaseName(observedIds);
265848
266408
  if (merged > 0) {
265849
266409
  console.error(`[memorix] Auto-merged ${merged} alias group(s) by base name`);
@@ -265884,8 +266444,8 @@ async function createMemorixServer(cwd, existingServer, sharedTeam, options = {}
265884
266444
  try {
265885
266445
  const { getAllObservations: getAllObservations2 } = await Promise.resolve().then(() => (init_observations(), observations_exports));
265886
266446
  await initObservations(projectDir2);
265887
- const allObs = getAllObservations2();
265888
- const observedIds = [...new Set(allObs.map((o4) => o4.projectId))];
266447
+ const store2 = getObservationStore();
266448
+ const observedIds = store2.listProjectIds ? await store2.listProjectIds() : [...new Set(getAllObservations2().map((o4) => o4.projectId))];
265889
266449
  const merged = await autoMergeByBaseName(observedIds);
265890
266450
  if (merged > 0) {
265891
266451
  console.error(`[memorix] Auto-merged ${merged} alias group(s) by base name`);
@@ -271256,20 +271816,15 @@ var init_websocket = __esm({
271256
271816
  if (typeof args[0] === "function") {
271257
271817
  const [createEvents, options] = args;
271258
271818
  return async function upgradeWebSocket2(c6, next) {
271259
- const events = await createEvents(c6);
271260
- const result = await handler(c6, events, options);
271261
- if (result) {
271262
- return result;
271263
- }
271819
+ const result = await handler(c6, await createEvents(c6), options);
271820
+ if (result) return result;
271264
271821
  await next();
271265
271822
  };
271266
271823
  } else {
271267
271824
  const [c6, events, options] = args;
271268
271825
  return (async () => {
271269
271826
  const upgraded = await handler(c6, events, options);
271270
- if (!upgraded) {
271271
- throw new Error("Failed to upgrade WebSocket");
271272
- }
271827
+ if (!upgraded) throw new Error("Failed to upgrade WebSocket");
271273
271828
  return upgraded;
271274
271829
  })();
271275
271830
  }
@@ -272428,6 +272983,57 @@ var init_mediaType = __esm({
272428
272983
  }
272429
272984
  });
272430
272985
 
272986
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/server/requestBody.js
272987
+ function requestBodyTooLargeMessage(maxBytes) {
272988
+ return `Payload Too Large: Request body must not exceed ${maxBytes} bytes`;
272989
+ }
272990
+ function resolveMaxRequestBodySize(value) {
272991
+ if (value === void 0) {
272992
+ return DEFAULT_MAX_REQUEST_BODY_SIZE;
272993
+ }
272994
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
272995
+ throw new RangeError(`maxRequestBodySize must be a positive number of bytes, got ${String(value)}`);
272996
+ }
272997
+ return value;
272998
+ }
272999
+ async function readRequestBody(request, maxBytes = DEFAULT_MAX_REQUEST_BODY_SIZE) {
273000
+ if (Number(request.headers.get("content-length")) > maxBytes) {
273001
+ return { tooLarge: true };
273002
+ }
273003
+ if (request.body === null) {
273004
+ return { tooLarge: false, text: "" };
273005
+ }
273006
+ const reader2 = request.body.getReader();
273007
+ const decoder2 = new TextDecoder();
273008
+ let received = 0;
273009
+ let text3 = "";
273010
+ try {
273011
+ for (; ; ) {
273012
+ const { done, value } = await reader2.read();
273013
+ if (done) {
273014
+ break;
273015
+ }
273016
+ received += value.byteLength;
273017
+ if (received > maxBytes) {
273018
+ return { tooLarge: true };
273019
+ }
273020
+ text3 += decoder2.decode(value, { stream: true });
273021
+ }
273022
+ } finally {
273023
+ reader2.releaseLock();
273024
+ }
273025
+ return { tooLarge: false, text: text3 + decoder2.decode() };
273026
+ }
273027
+ var DEFAULT_MAX_REQUEST_BODY_SIZE, MAX_BATCH_SIZE2;
273028
+ var init_requestBody = __esm({
273029
+ "node_modules/@modelcontextprotocol/sdk/dist/esm/server/requestBody.js"() {
273030
+ "use strict";
273031
+ init_esm_shims();
273032
+ DEFAULT_MAX_REQUEST_BODY_SIZE = 4 * 1024 * 1024;
273033
+ MAX_BATCH_SIZE2 = 100;
273034
+ }
273035
+ });
273036
+
272431
273037
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/sseKeepAlive.js
272432
273038
  function armSseKeepAlive(intervalMs, onTick) {
272433
273039
  if (!Number.isFinite(intervalMs) || intervalMs < 1) {
@@ -272454,6 +273060,7 @@ var init_webStandardStreamableHttp = __esm({
272454
273060
  "use strict";
272455
273061
  init_esm_shims();
272456
273062
  init_mediaType();
273063
+ init_requestBody();
272457
273064
  init_sseKeepAlive();
272458
273065
  init_types8();
272459
273066
  WebStandardStreamableHTTPServerTransport = class {
@@ -272478,6 +273085,7 @@ var init_webStandardStreamableHttp = __esm({
272478
273085
  this._enableDnsRebindingProtection = options.enableDnsRebindingProtection ?? false;
272479
273086
  this._retryInterval = options.retryInterval;
272480
273087
  this._keepAliveMs = options.keepAliveMs ?? DEFAULT_SSE_KEEP_ALIVE_MS;
273088
+ this._maxRequestBodySize = resolveMaxRequestBodySize(options.maxRequestBodySize);
272481
273089
  }
272482
273090
  /**
272483
273091
  * Arms a keep-alive interval for an SSE stream that periodically writes an SSE
@@ -272839,12 +273447,22 @@ data:
272839
273447
  rawMessage = options.parsedBody;
272840
273448
  } else {
272841
273449
  try {
272842
- rawMessage = await req.json();
273450
+ const body = await readRequestBody(req, this._maxRequestBodySize);
273451
+ if (body.tooLarge) {
273452
+ const message = requestBodyTooLargeMessage(this._maxRequestBodySize);
273453
+ this.onerror?.(new Error(message));
273454
+ return this.createJsonErrorResponse(413, -32e3, message);
273455
+ }
273456
+ rawMessage = JSON.parse(body.text);
272843
273457
  } catch {
272844
273458
  this.onerror?.(new Error("Parse error: Invalid JSON"));
272845
273459
  return this.createJsonErrorResponse(400, -32700, "Parse error: Invalid JSON");
272846
273460
  }
272847
273461
  }
273462
+ if (Array.isArray(rawMessage) && rawMessage.length > MAX_BATCH_SIZE2) {
273463
+ this.onerror?.(new Error(`Invalid Request: Batch must not exceed ${MAX_BATCH_SIZE2} messages`));
273464
+ return this.createJsonErrorResponse(400, -32600, `Invalid Request: Batch must not exceed ${MAX_BATCH_SIZE2} messages`);
273465
+ }
272848
273466
  let messages;
272849
273467
  try {
272850
273468
  if (Array.isArray(rawMessage)) {
@@ -278143,6 +278761,7 @@ function extractEventName(payload, agent) {
278143
278761
  case "cursor":
278144
278762
  return payload.hook_event_name ?? inferCursorEvent(payload);
278145
278763
  case "claude":
278764
+ case "qwen":
278146
278765
  return payload.hook_event_name ?? "";
278147
278766
  case "codex":
278148
278767
  return payload.hook_event_name ?? "";
@@ -278191,7 +278810,7 @@ function normalizeClaude(payload, event) {
278191
278810
  if (/^bash$/i.test(toolName) && toolInput?.command) {
278192
278811
  result.command = toolInput.command;
278193
278812
  }
278194
- if (/^(write|edit|multi_edit|multiedittool)$/i.test(toolName)) {
278813
+ if (/^(write|write_file|edit|edit_file|multi_edit|multiedittool)$/i.test(toolName)) {
278195
278814
  result.filePath = toolInput?.file_path ?? toolInput?.filePath;
278196
278815
  }
278197
278816
  }
@@ -278481,6 +279100,7 @@ function normalizeHookInput(payload) {
278481
279100
  let agentSpecific = {};
278482
279101
  switch (agent) {
278483
279102
  case "claude":
279103
+ case "qwen":
278484
279104
  agentSpecific = normalizeClaude(payload, event);
278485
279105
  break;
278486
279106
  case "copilot":
@@ -278564,9 +279184,12 @@ var init_normalizer = __esm({
278564
279184
  PreToolUse: "post_tool",
278565
279185
  // we handle pre as post for memory purposes
278566
279186
  PostToolUse: "post_tool",
279187
+ PostToolUseFailure: "post_tool",
278567
279188
  PreCompact: "pre_compact",
279189
+ PostCompact: "post_compact",
278568
279190
  Stop: "session_end",
278569
279191
  SessionEnd: "session_end",
279192
+ SessionDelete: "session_end",
278570
279193
  // Grok Build (Claude-compatible PascalCase plus snake_case hookEventName)
278571
279194
  user_prompt_submit: "user_prompt",
278572
279195
  pre_tool_use: "post_tool",
@@ -278847,11 +279470,7 @@ async function readHookStdin(stdin2, timeoutMs) {
278847
279470
  stdin2.removeListener("end", finish);
278848
279471
  stdin2.removeListener("error", finish);
278849
279472
  stdin2.pause?.();
278850
- if (!stdin2.isTTY) {
278851
- stdin2.destroy?.();
278852
- } else {
278853
- stdin2.unref?.();
278854
- }
279473
+ stdin2.unref?.();
278855
279474
  resolve9(Buffer.concat(chunks).toString("utf-8").trim());
278856
279475
  };
278857
279476
  const onData = (chunk) => {
@@ -278932,7 +279551,7 @@ var init_lifecycle2 = __esm({
278932
279551
  // src/hooks/handler.ts
278933
279552
  var handler_exports = {};
278934
279553
  __export(handler_exports, {
278935
- TYPE_EMOJI: () => TYPE_EMOJI2,
279554
+ TYPE_EMOJI: () => TYPE_EMOJI,
278936
279555
  formatHookOutput: () => formatHookOutput,
278937
279556
  handleHookEvent: () => handleHookEvent,
278938
279557
  resetCooldowns: () => resetCooldowns,
@@ -279496,7 +280115,7 @@ function toAntigravityHookOutput(rawEventName, output) {
279496
280115
  return {};
279497
280116
  }
279498
280117
  }
279499
- var TYPE_EMOJI2, cooldowns, COOLDOWN_MS, MIN_PROMPT_LENGTH, MAX_CONTENT_LENGTH, STORAGE_POLICY;
280118
+ var TYPE_EMOJI, cooldowns, COOLDOWN_MS, MIN_PROMPT_LENGTH, MAX_CONTENT_LENGTH, STORAGE_POLICY;
279500
280119
  var init_handler = __esm({
279501
280120
  "src/hooks/handler.ts"() {
279502
280121
  "use strict";
@@ -279506,7 +280125,7 @@ var init_handler = __esm({
279506
280125
  init_pattern_detector();
279507
280126
  init_significance_filter();
279508
280127
  init_lifecycle2();
279509
- TYPE_EMOJI2 = {
280128
+ TYPE_EMOJI = {
279510
280129
  "gotcha": "[GOTCHA]",
279511
280130
  "decision": "[DECISION]",
279512
280131
  "problem-solution": "[FIX]",
@@ -279600,7 +280219,8 @@ var init_types9 = __esm({
279600
280219
  pi: "community",
279601
280220
  omp: "community",
279602
280221
  antigravity: "community",
279603
- grok: "community"
280222
+ grok: "community",
280223
+ qwen: "extended"
279604
280224
  };
279605
280225
  }
279606
280226
  });
@@ -279650,6 +280270,7 @@ async function installSingleAgent2(agent, cwd, global2) {
279650
280270
  function getAgentLabel2(agent) {
279651
280271
  const labels = {
279652
280272
  claude: "Claude Code",
280273
+ qwen: "Qwen Code",
279653
280274
  codex: "Codex",
279654
280275
  windsurf: "Windsurf",
279655
280276
  cursor: "Cursor",
@@ -279671,6 +280292,7 @@ function getAgentLabel2(agent) {
279671
280292
  function getAgentHint2(agent) {
279672
280293
  const hints = {
279673
280294
  claude: ".claude/settings.json",
280295
+ qwen: ".qwen/settings.json",
279674
280296
  windsurf: ".windsurf/hooks.json",
279675
280297
  cursor: ".cursor/hooks.json",
279676
280298
  copilot: ".github/hooks/memorix.json (project-only, no global)",
@@ -289707,6 +290329,7 @@ function ConfigureView({ onBack }) {
289707
290329
  { key: "anthropic", label: "Anthropic", hint: "claude-3-haiku" },
289708
290330
  { key: "openrouter", label: "OpenRouter", hint: "multi-provider" },
289709
290331
  { key: "requesty", label: "Requesty", hint: "multi-provider" },
290332
+ { key: "apiroute", label: "API Route", hint: "multi-provider" },
289710
290333
  { key: "atlascloud", label: "Atlas Cloud", hint: "DeepSeek V3.2" },
289711
290334
  { key: "custom", label: "Custom endpoint", hint: "OpenAI-compatible" },
289712
290335
  { key: "disable", label: "Disable LLM", hint: "free heuristic mode", color: COLORS.warning },
@@ -290001,6 +290624,7 @@ function getDefaultModel(provider2) {
290001
290624
  if (provider2 === "anthropic") return "claude-3-haiku-20240307";
290002
290625
  if (provider2 === "openrouter") return "openai/gpt-4o-mini";
290003
290626
  if (provider2 === "requesty") return "openai/gpt-4o-mini";
290627
+ if (provider2 === "apiroute") return "deepseek-v4.1-flash";
290004
290628
  if (provider2 === "atlascloud") return "deepseek-ai/deepseek-v3.2";
290005
290629
  return "gpt-4o-mini";
290006
290630
  }
@@ -293558,14 +294182,14 @@ var main2 = defineCommand({
293558
294182
  search: () => Promise.resolve(defineCommand({
293559
294183
  meta: { name: "search", description: "Shortcut for `memorix memory search`" },
293560
294184
  args: {
293561
- query: { type: "positional", description: "Search query", required: true },
294185
+ query: { type: "string", description: "Search query (also accepts the first positional argument)", required: false },
293562
294186
  limit: { type: "string", description: "Maximum results" },
293563
294187
  quality: { type: "string", description: "Retrieval profile: fast, balanced (default), or thorough" },
293564
294188
  json: { type: "boolean", description: "Emit machine-readable JSON output" }
293565
294189
  },
293566
294190
  async run({ args }) {
293567
294191
  await runMemoryShortcut("search", {
293568
- query: args.query,
294192
+ query: args.query ?? args._?.[0],
293569
294193
  limit: args.limit,
293570
294194
  quality: args.quality,
293571
294195
  json: args.json