memorix 1.9.8 → 1.9.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,14 @@ All notable changes to this project will be documented in this file.
6
6
 
7
7
  No unreleased changes.
8
8
 
9
+ ## [1.9.9] - 2026-10-02
10
+
11
+ ### Added
12
+ - **Requesty memory preset** -- `memorix init` and the configuration TUI can
13
+ select Requesty for optional background memory LLM work through its
14
+ OpenAI-compatible endpoint, with provider-specific key isolation.
15
+ `REQUESTY_API_KEY` is also accepted for Requesty embedding endpoints.
16
+
9
17
  ## [1.9.8] - 2026-10-02
10
18
 
11
19
  ### Fixed
package/README.md CHANGED
@@ -533,6 +533,8 @@ OpenAI-compatible `https://api.atlascloud.ai/v1` endpoint and reads
533
533
 
534
534
  For OpenRouter embeddings, use `provider = "api"`, `base_url = "https://openrouter.ai/api/v1"`, and `model = "qwen/qwen3-embedding-8b"`. Memorix accepts `OPENROUTER_API_KEY` for that embedding endpoint; `MEMORIX_EMBEDDING_API_KEY` remains the explicit override.
535
535
 
536
+ For Requesty, choose Requesty in `memorix init` or set `provider = "requesty"` in `[memory.llm]` (endpoint `https://router.requesty.ai/v1`, key from `REQUESTY_API_KEY` or `MEMORIX_LLM_API_KEY`). Requesty embeddings use `provider = "api"`, `base_url = "https://router.requesty.ai/v1"`, and `model = "openai/text-embedding-3-small"` with `REQUESTY_API_KEY`.
537
+
536
538
  For controlled MiniMax media generation, set `MINIMAX_API_KEY` (global) or
537
539
  `MINIMAX_CN_API_KEY` (China region) in your environment or `.env`. The media
538
540
  library never stores that key, a signed output URL, or base64 payloads. CLI
package/README.zh-CN.md CHANGED
@@ -506,6 +506,8 @@ OpenAI-compatible 的 `https://api.atlascloud.ai/v1` endpoint,并读取
506
506
 
507
507
  如果使用 OpenRouter embedding,可以设置 `provider = "api"`、`base_url = "https://openrouter.ai/api/v1"`、`model = "qwen/qwen3-embedding-8b"`。这个 endpoint 下 Memorix 会读取官方 `OPENROUTER_API_KEY`;需要单独覆盖 embedding key 时仍可用 `MEMORIX_EMBEDDING_API_KEY`。
508
508
 
509
+ 使用 Requesty 时,可在 `memorix init` 中选择 Requesty,或在 `[memory.llm]` 中设置 `provider = "requesty"`(endpoint 为 `https://router.requesty.ai/v1`,key 读取 `REQUESTY_API_KEY` 或 `MEMORIX_LLM_API_KEY`)。Requesty embedding 使用 `provider = "api"`、`base_url = "https://router.requesty.ai/v1"`、`model = "openai/text-embedding-3-small"`,并读取 `REQUESTY_API_KEY`。
510
+
509
511
  受控 MiniMax 媒体生成可在环境变量或 `.env` 中设置全局 `MINIMAX_API_KEY`,或中国区 `MINIMAX_CN_API_KEY`。媒体库不会保存该 key、临时签名 URL 或 base64 负载。CLI 生成本身就是显式操作;若要让 MCP 中的 Agent 发起生成,还必须明确设置 `MEMORIX_MCP_MEDIA_GENERATION=1`。
510
512
 
511
513
  <h2 id="docker"><picture><source media="(prefers-color-scheme: dark)" srcset="assets/tags/light/section-docker.svg"><img src="assets/tags/section-docker.svg" alt="Docker" height="32" /></picture></h2>
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.8" : pkg.version;
3235
+ return true ? "1.9.9" : pkg.version;
3236
3236
  }
3237
3237
  var init_version = __esm({
3238
3238
  "src/cli/version.ts"() {
@@ -22122,6 +22122,7 @@ function getResolvedConfig(options = {}) {
22122
22122
  const legacy = loadFileConfig(homeDir);
22123
22123
  const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
22124
22124
  const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
22125
+ const requestyEmbeddingApiKey = isRequestyUrl(embeddingBaseUrl) ? process.env.REQUESTY_API_KEY : void 0;
22125
22126
  const memoryLlmProvider = first(
22126
22127
  process.env.MEMORIX_LLM_PROVIDER,
22127
22128
  toml.memory?.llm?.provider,
@@ -22142,16 +22143,18 @@ function getResolvedConfig(options = {}) {
22142
22143
  );
22143
22144
  const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
22144
22145
  const isAtlasCloud = memoryLlmProvider === "atlascloud";
22146
+ const isRequesty = memoryLlmProvider === "requesty";
22147
+ const usesPresetKeyOnly = isAtlasCloud || isRequesty;
22145
22148
  const memoryLlmApiKey = first(
22146
22149
  process.env.MEMORIX_LLM_API_KEY,
22147
22150
  process.env.MEMORIX_API_KEY,
22148
22151
  toml.memory?.llm?.api_key,
22149
22152
  yaml.llm?.apiKey,
22150
22153
  legacy.llm?.apiKey,
22151
- // Never borrow another provider's credentials for the Atlas Cloud preset.
22152
- isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
22153
- isAtlasCloud ? void 0 : process.env.ANTHROPIC_API_KEY,
22154
- isAtlasCloud ? void 0 : openRouterMemoryLlmApiKey
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,
22156
+ usesPresetKeyOnly ? void 0 : process.env.ANTHROPIC_API_KEY,
22157
+ usesPresetKeyOnly ? void 0 : openRouterMemoryLlmApiKey
22155
22158
  );
22156
22159
  const resolved = {
22157
22160
  agent: {
@@ -22200,7 +22203,7 @@ function getResolvedConfig(options = {}) {
22200
22203
  provider: first(process.env.MEMORIX_EMBEDDING, toml.embedding?.provider, yaml.embedding?.provider, legacy.embedding, "off"),
22201
22204
  model: first(process.env.MEMORIX_EMBEDDING_MODEL, toml.embedding?.model, yaml.embedding?.model, legacy.embeddingApi?.model),
22202
22205
  baseUrl: embeddingBaseUrl,
22203
- apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey),
22206
+ apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey, requestyEmbeddingApiKey),
22204
22207
  dimensions: firstNumber(parseNumber(process.env.MEMORIX_EMBEDDING_DIMENSIONS), toml.embedding?.dimensions, yaml.embedding?.dimensions, legacy.embeddingApi?.dimensions)
22205
22208
  },
22206
22209
  rerank: resolveRerankLane({
@@ -22331,6 +22334,7 @@ function getEnvSourceNames() {
22331
22334
  "MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
22332
22335
  "MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
22333
22336
  "OPENROUTER_API_KEY",
22337
+ "REQUESTY_API_KEY",
22334
22338
  "ATLASCLOUD_API_KEY"
22335
22339
  ].filter((name) => process.env[name]);
22336
22340
  }
@@ -22343,6 +22347,15 @@ function isOpenRouterUrl(value) {
22343
22347
  return /(^|\.)openrouter\.ai(?::|\/|$)/i.test(value);
22344
22348
  }
22345
22349
  }
22350
+ function isRequestyUrl(value) {
22351
+ if (!value) return false;
22352
+ try {
22353
+ const url2 = new URL(value);
22354
+ return url2.hostname.toLowerCase() === "requesty.ai" || url2.hostname.toLowerCase().endsWith(".requesty.ai");
22355
+ } catch {
22356
+ return /(^|\.)requesty\.ai(?::|\/|$)/i.test(value);
22357
+ }
22358
+ }
22346
22359
  function isOpenRouterMemoryLane(provider2, baseUrl) {
22347
22360
  return provider2?.trim().toLowerCase() === "openrouter" || isOpenRouterUrl(baseUrl);
22348
22361
  }
@@ -22497,6 +22510,9 @@ function defaultEmbeddingModelFor(baseUrl, explicitModel) {
22497
22510
  if (url2 && (url2.hostname === "openrouter.ai" || url2.hostname.endsWith(".openrouter.ai"))) {
22498
22511
  return "qwen/qwen3-embedding-8b";
22499
22512
  }
22513
+ if (url2 && (url2.hostname === "requesty.ai" || url2.hostname.endsWith(".requesty.ai"))) {
22514
+ return "openai/text-embedding-3-small";
22515
+ }
22500
22516
  } catch {
22501
22517
  }
22502
22518
  return "text-embedding-3-small";
@@ -25311,6 +25327,7 @@ var init_provider2 = __esm({
25311
25327
  openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
25312
25328
  anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
25313
25329
  openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
25330
+ requesty: { baseUrl: "https://router.requesty.ai/v1", model: "openai/gpt-4.1-nano" },
25314
25331
  atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
25315
25332
  custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
25316
25333
  };
@@ -193093,6 +193110,8 @@ function buildInitTomlConfig(options) {
193093
193110
  lines.push('model = "claude-3-haiku-20240307"');
193094
193111
  } else if (options.llmProvider === "openrouter") {
193095
193112
  lines.push('# model = "openai/gpt-4o-mini"');
193113
+ } else if (options.llmProvider === "requesty") {
193114
+ lines.push('# model = "openai/gpt-4o-mini"');
193096
193115
  } else if (options.llmProvider === "atlascloud") {
193097
193116
  lines.push('model = "deepseek-ai/deepseek-v3.2"');
193098
193117
  }
@@ -193227,6 +193246,7 @@ var init_init = __esm({
193227
193246
  { value: "openai", label: "OpenAI", hint: "gpt-4o-mini" },
193228
193247
  { value: "anthropic", label: "Anthropic", hint: "claude-3-haiku" },
193229
193248
  { value: "openrouter", label: "OpenRouter", hint: "multi-provider" },
193249
+ { value: "requesty", label: "Requesty", hint: "multi-provider" },
193230
193250
  { value: "atlascloud", label: "Atlas Cloud", hint: "DeepSeek V3.2" },
193231
193251
  { value: "custom", label: "Custom", hint: "OpenAI-compatible endpoint" }
193232
193252
  ]
@@ -193287,6 +193307,8 @@ var init_init = __esm({
193287
193307
  envLines.push("MEMORIX_LLM_API_KEY=sk-ant-your-key-here");
193288
193308
  } else if (llmProvider === "openrouter") {
193289
193309
  envLines.push("MEMORIX_LLM_API_KEY=sk-or-your-key-here");
193310
+ } else if (llmProvider === "requesty") {
193311
+ envLines.push("MEMORIX_LLM_API_KEY=rqsty-your-key-here");
193290
193312
  }
193291
193313
  if (llmProvider === "custom") {
193292
193314
  envLines.push("# MEMORIX_LLM_BASE_URL=http://localhost:11434/v1");
@@ -193313,6 +193335,7 @@ var init_init = __esm({
193313
193335
  envLines.push("# OPENAI_API_KEY=sk-...");
193314
193336
  envLines.push("# ANTHROPIC_API_KEY=sk-ant-...");
193315
193337
  envLines.push("# OPENROUTER_API_KEY=sk-or-...");
193338
+ envLines.push("# REQUESTY_API_KEY=rqsty-...");
193316
193339
  envLines.push("");
193317
193340
  mkdirSync3(targetDir, { recursive: true });
193318
193341
  writeFileSync3(targetPath, tomlContent, "utf-8");
@@ -209174,7 +209197,7 @@ var init_tool_profile = __esm({
209174
209197
  function getMcpServerInfo() {
209175
209198
  return {
209176
209199
  name: "memorix",
209177
- version: true ? "1.9.8" : "1.0.1"
209200
+ version: true ? "1.9.9" : "1.0.1"
209178
209201
  };
209179
209202
  }
209180
209203
  function createMcpDiscoverResult(capabilities, serverInfo) {
@@ -225106,7 +225129,8 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
225106
225129
  "MEMORIX_API_KEY",
225107
225130
  "OPENAI_API_KEY",
225108
225131
  "ANTHROPIC_API_KEY",
225109
- ...resolved.memory.llm.provider === "openrouter" || resolved.memory.llm.baseUrl?.includes("openrouter.ai") ? ["OPENROUTER_API_KEY"] : []
225132
+ ...resolved.memory.llm.provider === "openrouter" || resolved.memory.llm.baseUrl?.includes("openrouter.ai") ? ["OPENROUTER_API_KEY"] : [],
225133
+ ...resolved.memory.llm.provider === "requesty" ? ["REQUESTY_API_KEY"] : []
225110
225134
  ];
225111
225135
  if (llmKey) {
225112
225136
  const src2 = resolveDashboardKeySource({ value: llmKey, envKeys: memoryKeyEnv, configSource });
@@ -265497,7 +265521,7 @@ async function analyzeImage(input) {
265497
265521
  const config2 = getLLMConfig();
265498
265522
  if (!OPENAI_COMPATIBLE_PROVIDERS.has(config2.provider)) {
265499
265523
  throw new Error(
265500
- `Image analysis requires an OpenAI-compatible provider (openai, openrouter, or custom). Current provider "${config2.provider}" uses a different API shape. Set MEMORIX_LLM_PROVIDER=openai or configure an OpenAI-compatible base URL.`
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.`
265501
265525
  );
265502
265526
  }
265503
265527
  const bytes = decodeBase64ImagePayload(input.base64, MAX_VISION_IMAGE_BYTES);
@@ -265536,7 +265560,7 @@ var init_image_loader = __esm({
265536
265560
  init_provider2();
265537
265561
  init_secret_filter();
265538
265562
  init_image_payload();
265539
- OPENAI_COMPATIBLE_PROVIDERS = /* @__PURE__ */ new Set(["openai", "openrouter", "custom"]);
265563
+ OPENAI_COMPATIBLE_PROVIDERS = /* @__PURE__ */ new Set(["openai", "openrouter", "requesty", "custom"]);
265540
265564
  MAX_VISION_PROMPT_CHARS = 12e3;
265541
265565
  MAX_VISION_DESCRIPTION_CHARS = 12e3;
265542
265566
  MAX_VISION_LABELS = 50;
@@ -289682,6 +289706,7 @@ function ConfigureView({ onBack }) {
289682
289706
  { key: "openai", label: "OpenAI", hint: "gpt-4o-mini" },
289683
289707
  { key: "anthropic", label: "Anthropic", hint: "claude-3-haiku" },
289684
289708
  { key: "openrouter", label: "OpenRouter", hint: "multi-provider" },
289709
+ { key: "requesty", label: "Requesty", hint: "multi-provider" },
289685
289710
  { key: "atlascloud", label: "Atlas Cloud", hint: "DeepSeek V3.2" },
289686
289711
  { key: "custom", label: "Custom endpoint", hint: "OpenAI-compatible" },
289687
289712
  { key: "disable", label: "Disable LLM", hint: "free heuristic mode", color: COLORS.warning },
@@ -289975,6 +290000,7 @@ function ConfigureView({ onBack }) {
289975
290000
  function getDefaultModel(provider2) {
289976
290001
  if (provider2 === "anthropic") return "claude-3-haiku-20240307";
289977
290002
  if (provider2 === "openrouter") return "openai/gpt-4o-mini";
290003
+ if (provider2 === "requesty") return "openai/gpt-4o-mini";
289978
290004
  if (provider2 === "atlascloud") return "deepseek-ai/deepseek-v3.2";
289979
290005
  return "gpt-4o-mini";
289980
290006
  }
package/dist/index.js CHANGED
@@ -3818,6 +3818,7 @@ function getResolvedConfig(options = {}) {
3818
3818
  const legacy = loadFileConfig(homeDir);
3819
3819
  const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
3820
3820
  const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
3821
+ const requestyEmbeddingApiKey = isRequestyUrl(embeddingBaseUrl) ? process.env.REQUESTY_API_KEY : void 0;
3821
3822
  const memoryLlmProvider = first(
3822
3823
  process.env.MEMORIX_LLM_PROVIDER,
3823
3824
  toml.memory?.llm?.provider,
@@ -3838,16 +3839,18 @@ function getResolvedConfig(options = {}) {
3838
3839
  );
3839
3840
  const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
3840
3841
  const isAtlasCloud = memoryLlmProvider === "atlascloud";
3842
+ const isRequesty = memoryLlmProvider === "requesty";
3843
+ const usesPresetKeyOnly = isAtlasCloud || isRequesty;
3841
3844
  const memoryLlmApiKey = first(
3842
3845
  process.env.MEMORIX_LLM_API_KEY,
3843
3846
  process.env.MEMORIX_API_KEY,
3844
3847
  toml.memory?.llm?.api_key,
3845
3848
  yaml.llm?.apiKey,
3846
3849
  legacy.llm?.apiKey,
3847
- // Never borrow another provider's credentials for the Atlas Cloud preset.
3848
- isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
3849
- isAtlasCloud ? void 0 : process.env.ANTHROPIC_API_KEY,
3850
- isAtlasCloud ? void 0 : openRouterMemoryLlmApiKey
3850
+ // Never borrow another provider's credentials for the Atlas Cloud or Requesty presets.
3851
+ isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : isRequesty ? process.env.REQUESTY_API_KEY : process.env.OPENAI_API_KEY,
3852
+ usesPresetKeyOnly ? void 0 : process.env.ANTHROPIC_API_KEY,
3853
+ usesPresetKeyOnly ? void 0 : openRouterMemoryLlmApiKey
3851
3854
  );
3852
3855
  const resolved = {
3853
3856
  agent: {
@@ -3896,7 +3899,7 @@ function getResolvedConfig(options = {}) {
3896
3899
  provider: first(process.env.MEMORIX_EMBEDDING, toml.embedding?.provider, yaml.embedding?.provider, legacy.embedding, "off"),
3897
3900
  model: first(process.env.MEMORIX_EMBEDDING_MODEL, toml.embedding?.model, yaml.embedding?.model, legacy.embeddingApi?.model),
3898
3901
  baseUrl: embeddingBaseUrl,
3899
- apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey),
3902
+ apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey, requestyEmbeddingApiKey),
3900
3903
  dimensions: firstNumber(parseNumber(process.env.MEMORIX_EMBEDDING_DIMENSIONS), toml.embedding?.dimensions, yaml.embedding?.dimensions, legacy.embeddingApi?.dimensions)
3901
3904
  },
3902
3905
  rerank: resolveRerankLane({
@@ -4027,6 +4030,7 @@ function getEnvSourceNames() {
4027
4030
  "MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
4028
4031
  "MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
4029
4032
  "OPENROUTER_API_KEY",
4033
+ "REQUESTY_API_KEY",
4030
4034
  "ATLASCLOUD_API_KEY"
4031
4035
  ].filter((name) => process.env[name]);
4032
4036
  }
@@ -4039,6 +4043,15 @@ function isOpenRouterUrl(value) {
4039
4043
  return /(^|\.)openrouter\.ai(?::|\/|$)/i.test(value);
4040
4044
  }
4041
4045
  }
4046
+ function isRequestyUrl(value) {
4047
+ if (!value) return false;
4048
+ try {
4049
+ const url = new URL(value);
4050
+ return url.hostname.toLowerCase() === "requesty.ai" || url.hostname.toLowerCase().endsWith(".requesty.ai");
4051
+ } catch {
4052
+ return /(^|\.)requesty\.ai(?::|\/|$)/i.test(value);
4053
+ }
4054
+ }
4042
4055
  function isOpenRouterMemoryLane(provider2, baseUrl) {
4043
4056
  return provider2?.trim().toLowerCase() === "openrouter" || isOpenRouterUrl(baseUrl);
4044
4057
  }
@@ -4193,6 +4206,9 @@ function defaultEmbeddingModelFor(baseUrl, explicitModel) {
4193
4206
  if (url && (url.hostname === "openrouter.ai" || url.hostname.endsWith(".openrouter.ai"))) {
4194
4207
  return "qwen/qwen3-embedding-8b";
4195
4208
  }
4209
+ if (url && (url.hostname === "requesty.ai" || url.hostname.endsWith(".requesty.ai"))) {
4210
+ return "openai/text-embedding-3-small";
4211
+ }
4196
4212
  } catch {
4197
4213
  }
4198
4214
  return "text-embedding-3-small";
@@ -7007,6 +7023,7 @@ var init_provider2 = __esm({
7007
7023
  openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
7008
7024
  anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
7009
7025
  openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
7026
+ requesty: { baseUrl: "https://router.requesty.ai/v1", model: "openai/gpt-4.1-nano" },
7010
7027
  atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
7011
7028
  custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
7012
7029
  };
@@ -160104,7 +160121,7 @@ var init_request_context = __esm({
160104
160121
  function getMcpServerInfo() {
160105
160122
  return {
160106
160123
  name: "memorix",
160107
- version: true ? "1.9.8" : "1.0.1"
160124
+ version: true ? "1.9.9" : "1.0.1"
160108
160125
  };
160109
160126
  }
160110
160127
  function createMcpDiscoverResult(capabilities, serverInfo) {
@@ -167573,7 +167590,8 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
167573
167590
  "MEMORIX_API_KEY",
167574
167591
  "OPENAI_API_KEY",
167575
167592
  "ANTHROPIC_API_KEY",
167576
- ...resolved.memory.llm.provider === "openrouter" || resolved.memory.llm.baseUrl?.includes("openrouter.ai") ? ["OPENROUTER_API_KEY"] : []
167593
+ ...resolved.memory.llm.provider === "openrouter" || resolved.memory.llm.baseUrl?.includes("openrouter.ai") ? ["OPENROUTER_API_KEY"] : [],
167594
+ ...resolved.memory.llm.provider === "requesty" ? ["REQUESTY_API_KEY"] : []
167577
167595
  ];
167578
167596
  if (llmKey) {
167579
167597
  const src = resolveDashboardKeySource({ value: llmKey, envKeys: memoryKeyEnv, configSource });
@@ -169158,7 +169176,7 @@ async function analyzeImage(input) {
169158
169176
  const config = getLLMConfig();
169159
169177
  if (!OPENAI_COMPATIBLE_PROVIDERS.has(config.provider)) {
169160
169178
  throw new Error(
169161
- `Image analysis requires an OpenAI-compatible provider (openai, openrouter, or custom). Current provider "${config.provider}" uses a different API shape. Set MEMORIX_LLM_PROVIDER=openai or configure an OpenAI-compatible base URL.`
169179
+ `Image analysis requires an OpenAI-compatible provider (openai, openrouter, requesty, or custom). Current provider "${config.provider}" uses a different API shape. Set MEMORIX_LLM_PROVIDER=openai or configure an OpenAI-compatible base URL.`
169162
169180
  );
169163
169181
  }
169164
169182
  const bytes = decodeBase64ImagePayload(input.base64, MAX_VISION_IMAGE_BYTES);
@@ -169197,7 +169215,7 @@ var init_image_loader = __esm({
169197
169215
  init_provider2();
169198
169216
  init_secret_filter();
169199
169217
  init_image_payload();
169200
- OPENAI_COMPATIBLE_PROVIDERS = /* @__PURE__ */ new Set(["openai", "openrouter", "custom"]);
169218
+ OPENAI_COMPATIBLE_PROVIDERS = /* @__PURE__ */ new Set(["openai", "openrouter", "requesty", "custom"]);
169201
169219
  MAX_VISION_PROMPT_CHARS = 12e3;
169202
169220
  MAX_VISION_DESCRIPTION_CHARS = 12e3;
169203
169221
  MAX_VISION_LABELS = 50;
@@ -176597,7 +176615,7 @@ var init_serve_shared = __esm({
176597
176615
 
176598
176616
  // src/cli/version.ts
176599
176617
  function getCliVersion() {
176600
- return true ? "1.9.8" : pkg.version;
176618
+ return true ? "1.9.9" : pkg.version;
176601
176619
  }
176602
176620
  var init_version3 = __esm({
176603
176621
  "src/cli/version.ts"() {
@@ -2089,6 +2089,7 @@ function getResolvedConfig(options = {}) {
2089
2089
  const legacy = loadFileConfig(homeDir);
2090
2090
  const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
2091
2091
  const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
2092
+ const requestyEmbeddingApiKey = isRequestyUrl(embeddingBaseUrl) ? process.env.REQUESTY_API_KEY : void 0;
2092
2093
  const memoryLlmProvider = first(
2093
2094
  process.env.MEMORIX_LLM_PROVIDER,
2094
2095
  toml.memory?.llm?.provider,
@@ -2109,16 +2110,18 @@ function getResolvedConfig(options = {}) {
2109
2110
  );
2110
2111
  const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
2111
2112
  const isAtlasCloud = memoryLlmProvider === "atlascloud";
2113
+ const isRequesty = memoryLlmProvider === "requesty";
2114
+ const usesPresetKeyOnly = isAtlasCloud || isRequesty;
2112
2115
  const memoryLlmApiKey = first(
2113
2116
  process.env.MEMORIX_LLM_API_KEY,
2114
2117
  process.env.MEMORIX_API_KEY,
2115
2118
  toml.memory?.llm?.api_key,
2116
2119
  yaml.llm?.apiKey,
2117
2120
  legacy.llm?.apiKey,
2118
- // Never borrow another provider's credentials for the Atlas Cloud preset.
2119
- isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
2120
- isAtlasCloud ? void 0 : process.env.ANTHROPIC_API_KEY,
2121
- isAtlasCloud ? void 0 : openRouterMemoryLlmApiKey
2121
+ // Never borrow another provider's credentials for the Atlas Cloud or Requesty presets.
2122
+ isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : isRequesty ? process.env.REQUESTY_API_KEY : process.env.OPENAI_API_KEY,
2123
+ usesPresetKeyOnly ? void 0 : process.env.ANTHROPIC_API_KEY,
2124
+ usesPresetKeyOnly ? void 0 : openRouterMemoryLlmApiKey
2122
2125
  );
2123
2126
  const resolved = {
2124
2127
  agent: {
@@ -2167,7 +2170,7 @@ function getResolvedConfig(options = {}) {
2167
2170
  provider: first(process.env.MEMORIX_EMBEDDING, toml.embedding?.provider, yaml.embedding?.provider, legacy.embedding, "off"),
2168
2171
  model: first(process.env.MEMORIX_EMBEDDING_MODEL, toml.embedding?.model, yaml.embedding?.model, legacy.embeddingApi?.model),
2169
2172
  baseUrl: embeddingBaseUrl,
2170
- apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey),
2173
+ apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey, requestyEmbeddingApiKey),
2171
2174
  dimensions: firstNumber(parseNumber(process.env.MEMORIX_EMBEDDING_DIMENSIONS), toml.embedding?.dimensions, yaml.embedding?.dimensions, legacy.embeddingApi?.dimensions)
2172
2175
  },
2173
2176
  rerank: resolveRerankLane({
@@ -2298,6 +2301,7 @@ function getEnvSourceNames() {
2298
2301
  "MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
2299
2302
  "MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
2300
2303
  "OPENROUTER_API_KEY",
2304
+ "REQUESTY_API_KEY",
2301
2305
  "ATLASCLOUD_API_KEY"
2302
2306
  ].filter((name) => process.env[name]);
2303
2307
  }
@@ -2310,6 +2314,15 @@ function isOpenRouterUrl(value) {
2310
2314
  return /(^|\.)openrouter\.ai(?::|\/|$)/i.test(value);
2311
2315
  }
2312
2316
  }
2317
+ function isRequestyUrl(value) {
2318
+ if (!value) return false;
2319
+ try {
2320
+ const url = new URL(value);
2321
+ return url.hostname.toLowerCase() === "requesty.ai" || url.hostname.toLowerCase().endsWith(".requesty.ai");
2322
+ } catch {
2323
+ return /(^|\.)requesty\.ai(?::|\/|$)/i.test(value);
2324
+ }
2325
+ }
2313
2326
  function isOpenRouterMemoryLane(provider2, baseUrl) {
2314
2327
  return provider2?.trim().toLowerCase() === "openrouter" || isOpenRouterUrl(baseUrl);
2315
2328
  }
@@ -2464,6 +2477,9 @@ function defaultEmbeddingModelFor(baseUrl, explicitModel) {
2464
2477
  if (url && (url.hostname === "openrouter.ai" || url.hostname.endsWith(".openrouter.ai"))) {
2465
2478
  return "qwen/qwen3-embedding-8b";
2466
2479
  }
2480
+ if (url && (url.hostname === "requesty.ai" || url.hostname.endsWith(".requesty.ai"))) {
2481
+ return "openai/text-embedding-3-small";
2482
+ }
2467
2483
  } catch {
2468
2484
  }
2469
2485
  return "text-embedding-3-small";
@@ -3129,6 +3145,7 @@ var init_provider = __esm({
3129
3145
  openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
3130
3146
  anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
3131
3147
  openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
3148
+ requesty: { baseUrl: "https://router.requesty.ai/v1", model: "openai/gpt-4.1-nano" },
3132
3149
  atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
3133
3150
  custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
3134
3151
  };
@@ -3372,6 +3372,7 @@ function getResolvedConfig(options = {}) {
3372
3372
  const legacy = loadFileConfig(homeDir);
3373
3373
  const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
3374
3374
  const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
3375
+ const requestyEmbeddingApiKey = isRequestyUrl(embeddingBaseUrl) ? process.env.REQUESTY_API_KEY : void 0;
3375
3376
  const memoryLlmProvider = first(
3376
3377
  process.env.MEMORIX_LLM_PROVIDER,
3377
3378
  toml.memory?.llm?.provider,
@@ -3392,16 +3393,18 @@ function getResolvedConfig(options = {}) {
3392
3393
  );
3393
3394
  const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
3394
3395
  const isAtlasCloud = memoryLlmProvider === "atlascloud";
3396
+ const isRequesty = memoryLlmProvider === "requesty";
3397
+ const usesPresetKeyOnly = isAtlasCloud || isRequesty;
3395
3398
  const memoryLlmApiKey = first(
3396
3399
  process.env.MEMORIX_LLM_API_KEY,
3397
3400
  process.env.MEMORIX_API_KEY,
3398
3401
  toml.memory?.llm?.api_key,
3399
3402
  yaml.llm?.apiKey,
3400
3403
  legacy.llm?.apiKey,
3401
- // Never borrow another provider's credentials for the Atlas Cloud preset.
3402
- isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
3403
- isAtlasCloud ? void 0 : process.env.ANTHROPIC_API_KEY,
3404
- isAtlasCloud ? void 0 : openRouterMemoryLlmApiKey
3404
+ // Never borrow another provider's credentials for the Atlas Cloud or Requesty presets.
3405
+ isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : isRequesty ? process.env.REQUESTY_API_KEY : process.env.OPENAI_API_KEY,
3406
+ usesPresetKeyOnly ? void 0 : process.env.ANTHROPIC_API_KEY,
3407
+ usesPresetKeyOnly ? void 0 : openRouterMemoryLlmApiKey
3405
3408
  );
3406
3409
  const resolved = {
3407
3410
  agent: {
@@ -3450,7 +3453,7 @@ function getResolvedConfig(options = {}) {
3450
3453
  provider: first(process.env.MEMORIX_EMBEDDING, toml.embedding?.provider, yaml.embedding?.provider, legacy.embedding, "off"),
3451
3454
  model: first(process.env.MEMORIX_EMBEDDING_MODEL, toml.embedding?.model, yaml.embedding?.model, legacy.embeddingApi?.model),
3452
3455
  baseUrl: embeddingBaseUrl,
3453
- apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey),
3456
+ apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey, requestyEmbeddingApiKey),
3454
3457
  dimensions: firstNumber(parseNumber(process.env.MEMORIX_EMBEDDING_DIMENSIONS), toml.embedding?.dimensions, yaml.embedding?.dimensions, legacy.embeddingApi?.dimensions)
3455
3458
  },
3456
3459
  rerank: resolveRerankLane({
@@ -3581,6 +3584,7 @@ function getEnvSourceNames() {
3581
3584
  "MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
3582
3585
  "MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
3583
3586
  "OPENROUTER_API_KEY",
3587
+ "REQUESTY_API_KEY",
3584
3588
  "ATLASCLOUD_API_KEY"
3585
3589
  ].filter((name) => process.env[name]);
3586
3590
  }
@@ -3593,6 +3597,15 @@ function isOpenRouterUrl(value) {
3593
3597
  return /(^|\.)openrouter\.ai(?::|\/|$)/i.test(value);
3594
3598
  }
3595
3599
  }
3600
+ function isRequestyUrl(value) {
3601
+ if (!value) return false;
3602
+ try {
3603
+ const url = new URL(value);
3604
+ return url.hostname.toLowerCase() === "requesty.ai" || url.hostname.toLowerCase().endsWith(".requesty.ai");
3605
+ } catch {
3606
+ return /(^|\.)requesty\.ai(?::|\/|$)/i.test(value);
3607
+ }
3608
+ }
3596
3609
  function isOpenRouterMemoryLane(provider2, baseUrl) {
3597
3610
  return provider2?.trim().toLowerCase() === "openrouter" || isOpenRouterUrl(baseUrl);
3598
3611
  }
@@ -3747,6 +3760,9 @@ function defaultEmbeddingModelFor(baseUrl, explicitModel) {
3747
3760
  if (url && (url.hostname === "openrouter.ai" || url.hostname.endsWith(".openrouter.ai"))) {
3748
3761
  return "qwen/qwen3-embedding-8b";
3749
3762
  }
3763
+ if (url && (url.hostname === "requesty.ai" || url.hostname.endsWith(".requesty.ai"))) {
3764
+ return "openai/text-embedding-3-small";
3765
+ }
3750
3766
  } catch {
3751
3767
  }
3752
3768
  return "text-embedding-3-small";
@@ -6561,6 +6577,7 @@ var init_provider2 = __esm({
6561
6577
  openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
6562
6578
  anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
6563
6579
  openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
6580
+ requesty: { baseUrl: "https://router.requesty.ai/v1", model: "openai/gpt-4.1-nano" },
6564
6581
  atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
6565
6582
  custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
6566
6583
  };
@@ -2384,6 +2384,7 @@ function getResolvedConfig(options = {}) {
2384
2384
  const legacy = loadFileConfig(homeDir);
2385
2385
  const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
2386
2386
  const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
2387
+ const requestyEmbeddingApiKey = isRequestyUrl(embeddingBaseUrl) ? process.env.REQUESTY_API_KEY : void 0;
2387
2388
  const memoryLlmProvider = first(
2388
2389
  process.env.MEMORIX_LLM_PROVIDER,
2389
2390
  toml.memory?.llm?.provider,
@@ -2404,16 +2405,18 @@ function getResolvedConfig(options = {}) {
2404
2405
  );
2405
2406
  const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
2406
2407
  const isAtlasCloud = memoryLlmProvider === "atlascloud";
2408
+ const isRequesty = memoryLlmProvider === "requesty";
2409
+ const usesPresetKeyOnly = isAtlasCloud || isRequesty;
2407
2410
  const memoryLlmApiKey = first(
2408
2411
  process.env.MEMORIX_LLM_API_KEY,
2409
2412
  process.env.MEMORIX_API_KEY,
2410
2413
  toml.memory?.llm?.api_key,
2411
2414
  yaml.llm?.apiKey,
2412
2415
  legacy.llm?.apiKey,
2413
- // Never borrow another provider's credentials for the Atlas Cloud preset.
2414
- isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
2415
- isAtlasCloud ? void 0 : process.env.ANTHROPIC_API_KEY,
2416
- isAtlasCloud ? void 0 : openRouterMemoryLlmApiKey
2416
+ // Never borrow another provider's credentials for the Atlas Cloud or Requesty presets.
2417
+ isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : isRequesty ? process.env.REQUESTY_API_KEY : process.env.OPENAI_API_KEY,
2418
+ usesPresetKeyOnly ? void 0 : process.env.ANTHROPIC_API_KEY,
2419
+ usesPresetKeyOnly ? void 0 : openRouterMemoryLlmApiKey
2417
2420
  );
2418
2421
  const resolved = {
2419
2422
  agent: {
@@ -2462,7 +2465,7 @@ function getResolvedConfig(options = {}) {
2462
2465
  provider: first(process.env.MEMORIX_EMBEDDING, toml.embedding?.provider, yaml.embedding?.provider, legacy.embedding, "off"),
2463
2466
  model: first(process.env.MEMORIX_EMBEDDING_MODEL, toml.embedding?.model, yaml.embedding?.model, legacy.embeddingApi?.model),
2464
2467
  baseUrl: embeddingBaseUrl,
2465
- apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey),
2468
+ apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey, requestyEmbeddingApiKey),
2466
2469
  dimensions: firstNumber(parseNumber(process.env.MEMORIX_EMBEDDING_DIMENSIONS), toml.embedding?.dimensions, yaml.embedding?.dimensions, legacy.embeddingApi?.dimensions)
2467
2470
  },
2468
2471
  rerank: resolveRerankLane({
@@ -2593,6 +2596,7 @@ function getEnvSourceNames() {
2593
2596
  "MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
2594
2597
  "MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
2595
2598
  "OPENROUTER_API_KEY",
2599
+ "REQUESTY_API_KEY",
2596
2600
  "ATLASCLOUD_API_KEY"
2597
2601
  ].filter((name) => process.env[name]);
2598
2602
  }
@@ -2605,6 +2609,15 @@ function isOpenRouterUrl(value) {
2605
2609
  return /(^|\.)openrouter\.ai(?::|\/|$)/i.test(value);
2606
2610
  }
2607
2611
  }
2612
+ function isRequestyUrl(value) {
2613
+ if (!value) return false;
2614
+ try {
2615
+ const url = new URL(value);
2616
+ return url.hostname.toLowerCase() === "requesty.ai" || url.hostname.toLowerCase().endsWith(".requesty.ai");
2617
+ } catch {
2618
+ return /(^|\.)requesty\.ai(?::|\/|$)/i.test(value);
2619
+ }
2620
+ }
2608
2621
  function isOpenRouterMemoryLane(provider2, baseUrl) {
2609
2622
  return provider2?.trim().toLowerCase() === "openrouter" || isOpenRouterUrl(baseUrl);
2610
2623
  }
@@ -2759,6 +2772,9 @@ function defaultEmbeddingModelFor(baseUrl, explicitModel) {
2759
2772
  if (url && (url.hostname === "openrouter.ai" || url.hostname.endsWith(".openrouter.ai"))) {
2760
2773
  return "qwen/qwen3-embedding-8b";
2761
2774
  }
2775
+ if (url && (url.hostname === "requesty.ai" || url.hostname.endsWith(".requesty.ai"))) {
2776
+ return "openai/text-embedding-3-small";
2777
+ }
2762
2778
  } catch {
2763
2779
  }
2764
2780
  return "text-embedding-3-small";
@@ -5573,6 +5589,7 @@ var init_provider2 = __esm({
5573
5589
  openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
5574
5590
  anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
5575
5591
  openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
5592
+ requesty: { baseUrl: "https://router.requesty.ai/v1", model: "openai/gpt-4.1-nano" },
5576
5593
  atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
5577
5594
  custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
5578
5595
  };
@@ -6,6 +6,14 @@ All notable changes to this project will be documented in this file.
6
6
 
7
7
  No unreleased changes.
8
8
 
9
+ ## [1.9.9] - 2026-10-02
10
+
11
+ ### Added
12
+ - **Requesty memory preset** -- `memorix init` and the configuration TUI can
13
+ select Requesty for optional background memory LLM work through its
14
+ OpenAI-compatible endpoint, with provider-specific key isolation.
15
+ `REQUESTY_API_KEY` is also accepted for Requesty embedding endpoints.
16
+
9
17
  ## [1.9.8] - 2026-10-02
10
18
 
11
19
  ### Fixed
package/dist/sdk.js CHANGED
@@ -3847,6 +3847,7 @@ function getResolvedConfig(options = {}) {
3847
3847
  const legacy = loadFileConfig(homeDir);
3848
3848
  const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
3849
3849
  const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
3850
+ const requestyEmbeddingApiKey = isRequestyUrl(embeddingBaseUrl) ? process.env.REQUESTY_API_KEY : void 0;
3850
3851
  const memoryLlmProvider = first(
3851
3852
  process.env.MEMORIX_LLM_PROVIDER,
3852
3853
  toml.memory?.llm?.provider,
@@ -3867,16 +3868,18 @@ function getResolvedConfig(options = {}) {
3867
3868
  );
3868
3869
  const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
3869
3870
  const isAtlasCloud = memoryLlmProvider === "atlascloud";
3871
+ const isRequesty = memoryLlmProvider === "requesty";
3872
+ const usesPresetKeyOnly = isAtlasCloud || isRequesty;
3870
3873
  const memoryLlmApiKey = first(
3871
3874
  process.env.MEMORIX_LLM_API_KEY,
3872
3875
  process.env.MEMORIX_API_KEY,
3873
3876
  toml.memory?.llm?.api_key,
3874
3877
  yaml.llm?.apiKey,
3875
3878
  legacy.llm?.apiKey,
3876
- // Never borrow another provider's credentials for the Atlas Cloud preset.
3877
- isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
3878
- isAtlasCloud ? void 0 : process.env.ANTHROPIC_API_KEY,
3879
- isAtlasCloud ? void 0 : openRouterMemoryLlmApiKey
3879
+ // Never borrow another provider's credentials for the Atlas Cloud or Requesty presets.
3880
+ isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : isRequesty ? process.env.REQUESTY_API_KEY : process.env.OPENAI_API_KEY,
3881
+ usesPresetKeyOnly ? void 0 : process.env.ANTHROPIC_API_KEY,
3882
+ usesPresetKeyOnly ? void 0 : openRouterMemoryLlmApiKey
3880
3883
  );
3881
3884
  const resolved = {
3882
3885
  agent: {
@@ -3925,7 +3928,7 @@ function getResolvedConfig(options = {}) {
3925
3928
  provider: first(process.env.MEMORIX_EMBEDDING, toml.embedding?.provider, yaml.embedding?.provider, legacy.embedding, "off"),
3926
3929
  model: first(process.env.MEMORIX_EMBEDDING_MODEL, toml.embedding?.model, yaml.embedding?.model, legacy.embeddingApi?.model),
3927
3930
  baseUrl: embeddingBaseUrl,
3928
- apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey),
3931
+ apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey, requestyEmbeddingApiKey),
3929
3932
  dimensions: firstNumber(parseNumber(process.env.MEMORIX_EMBEDDING_DIMENSIONS), toml.embedding?.dimensions, yaml.embedding?.dimensions, legacy.embeddingApi?.dimensions)
3930
3933
  },
3931
3934
  rerank: resolveRerankLane({
@@ -4056,6 +4059,7 @@ function getEnvSourceNames() {
4056
4059
  "MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
4057
4060
  "MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
4058
4061
  "OPENROUTER_API_KEY",
4062
+ "REQUESTY_API_KEY",
4059
4063
  "ATLASCLOUD_API_KEY"
4060
4064
  ].filter((name) => process.env[name]);
4061
4065
  }
@@ -4068,6 +4072,15 @@ function isOpenRouterUrl(value) {
4068
4072
  return /(^|\.)openrouter\.ai(?::|\/|$)/i.test(value);
4069
4073
  }
4070
4074
  }
4075
+ function isRequestyUrl(value) {
4076
+ if (!value) return false;
4077
+ try {
4078
+ const url = new URL(value);
4079
+ return url.hostname.toLowerCase() === "requesty.ai" || url.hostname.toLowerCase().endsWith(".requesty.ai");
4080
+ } catch {
4081
+ return /(^|\.)requesty\.ai(?::|\/|$)/i.test(value);
4082
+ }
4083
+ }
4071
4084
  function isOpenRouterMemoryLane(provider2, baseUrl) {
4072
4085
  return provider2?.trim().toLowerCase() === "openrouter" || isOpenRouterUrl(baseUrl);
4073
4086
  }
@@ -4222,6 +4235,9 @@ function defaultEmbeddingModelFor(baseUrl, explicitModel) {
4222
4235
  if (url && (url.hostname === "openrouter.ai" || url.hostname.endsWith(".openrouter.ai"))) {
4223
4236
  return "qwen/qwen3-embedding-8b";
4224
4237
  }
4238
+ if (url && (url.hostname === "requesty.ai" || url.hostname.endsWith(".requesty.ai"))) {
4239
+ return "openai/text-embedding-3-small";
4240
+ }
4225
4241
  } catch {
4226
4242
  }
4227
4243
  return "text-embedding-3-small";
@@ -7036,6 +7052,7 @@ var init_provider2 = __esm({
7036
7052
  openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
7037
7053
  anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
7038
7054
  openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
7055
+ requesty: { baseUrl: "https://router.requesty.ai/v1", model: "openai/gpt-4.1-nano" },
7039
7056
  atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
7040
7057
  custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
7041
7058
  };
@@ -163566,7 +163583,8 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
163566
163583
  "MEMORIX_API_KEY",
163567
163584
  "OPENAI_API_KEY",
163568
163585
  "ANTHROPIC_API_KEY",
163569
- ...resolved.memory.llm.provider === "openrouter" || resolved.memory.llm.baseUrl?.includes("openrouter.ai") ? ["OPENROUTER_API_KEY"] : []
163586
+ ...resolved.memory.llm.provider === "openrouter" || resolved.memory.llm.baseUrl?.includes("openrouter.ai") ? ["OPENROUTER_API_KEY"] : [],
163587
+ ...resolved.memory.llm.provider === "requesty" ? ["REQUESTY_API_KEY"] : []
163570
163588
  ];
163571
163589
  if (llmKey) {
163572
163590
  const src = resolveDashboardKeySource({ value: llmKey, envKeys: memoryKeyEnv, configSource });
@@ -165151,7 +165169,7 @@ async function analyzeImage(input) {
165151
165169
  const config = getLLMConfig();
165152
165170
  if (!OPENAI_COMPATIBLE_PROVIDERS.has(config.provider)) {
165153
165171
  throw new Error(
165154
- `Image analysis requires an OpenAI-compatible provider (openai, openrouter, or custom). Current provider "${config.provider}" uses a different API shape. Set MEMORIX_LLM_PROVIDER=openai or configure an OpenAI-compatible base URL.`
165172
+ `Image analysis requires an OpenAI-compatible provider (openai, openrouter, requesty, or custom). Current provider "${config.provider}" uses a different API shape. Set MEMORIX_LLM_PROVIDER=openai or configure an OpenAI-compatible base URL.`
165155
165173
  );
165156
165174
  }
165157
165175
  const bytes = decodeBase64ImagePayload(input.base64, MAX_VISION_IMAGE_BYTES);
@@ -165190,7 +165208,7 @@ var init_image_loader = __esm({
165190
165208
  init_provider2();
165191
165209
  init_secret_filter();
165192
165210
  init_image_payload();
165193
- OPENAI_COMPATIBLE_PROVIDERS = /* @__PURE__ */ new Set(["openai", "openrouter", "custom"]);
165211
+ OPENAI_COMPATIBLE_PROVIDERS = /* @__PURE__ */ new Set(["openai", "openrouter", "requesty", "custom"]);
165194
165212
  MAX_VISION_PROMPT_CHARS = 12e3;
165195
165213
  MAX_VISION_DESCRIPTION_CHARS = 12e3;
165196
165214
  MAX_VISION_LABELS = 50;
@@ -170971,7 +170989,7 @@ var MCP_SERVER_INFO_META_KEY = "io.modelcontextprotocol/serverInfo";
170971
170989
  function getMcpServerInfo() {
170972
170990
  return {
170973
170991
  name: "memorix",
170974
- version: true ? "1.9.8" : "1.0.1"
170992
+ version: true ? "1.9.9" : "1.0.1"
170975
170993
  };
170976
170994
  }
170977
170995
  function createMcpDiscoverResult(capabilities, serverInfo) {
@@ -2384,6 +2384,7 @@ function getResolvedConfig(options = {}) {
2384
2384
  const legacy = loadFileConfig(homeDir);
2385
2385
  const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
2386
2386
  const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
2387
+ const requestyEmbeddingApiKey = isRequestyUrl(embeddingBaseUrl) ? process.env.REQUESTY_API_KEY : void 0;
2387
2388
  const memoryLlmProvider = first(
2388
2389
  process.env.MEMORIX_LLM_PROVIDER,
2389
2390
  toml.memory?.llm?.provider,
@@ -2404,16 +2405,18 @@ function getResolvedConfig(options = {}) {
2404
2405
  );
2405
2406
  const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
2406
2407
  const isAtlasCloud = memoryLlmProvider === "atlascloud";
2408
+ const isRequesty = memoryLlmProvider === "requesty";
2409
+ const usesPresetKeyOnly = isAtlasCloud || isRequesty;
2407
2410
  const memoryLlmApiKey = first(
2408
2411
  process.env.MEMORIX_LLM_API_KEY,
2409
2412
  process.env.MEMORIX_API_KEY,
2410
2413
  toml.memory?.llm?.api_key,
2411
2414
  yaml.llm?.apiKey,
2412
2415
  legacy.llm?.apiKey,
2413
- // Never borrow another provider's credentials for the Atlas Cloud preset.
2414
- isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
2415
- isAtlasCloud ? void 0 : process.env.ANTHROPIC_API_KEY,
2416
- isAtlasCloud ? void 0 : openRouterMemoryLlmApiKey
2416
+ // Never borrow another provider's credentials for the Atlas Cloud or Requesty presets.
2417
+ isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : isRequesty ? process.env.REQUESTY_API_KEY : process.env.OPENAI_API_KEY,
2418
+ usesPresetKeyOnly ? void 0 : process.env.ANTHROPIC_API_KEY,
2419
+ usesPresetKeyOnly ? void 0 : openRouterMemoryLlmApiKey
2417
2420
  );
2418
2421
  const resolved = {
2419
2422
  agent: {
@@ -2462,7 +2465,7 @@ function getResolvedConfig(options = {}) {
2462
2465
  provider: first(process.env.MEMORIX_EMBEDDING, toml.embedding?.provider, yaml.embedding?.provider, legacy.embedding, "off"),
2463
2466
  model: first(process.env.MEMORIX_EMBEDDING_MODEL, toml.embedding?.model, yaml.embedding?.model, legacy.embeddingApi?.model),
2464
2467
  baseUrl: embeddingBaseUrl,
2465
- apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey),
2468
+ apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey, requestyEmbeddingApiKey),
2466
2469
  dimensions: firstNumber(parseNumber(process.env.MEMORIX_EMBEDDING_DIMENSIONS), toml.embedding?.dimensions, yaml.embedding?.dimensions, legacy.embeddingApi?.dimensions)
2467
2470
  },
2468
2471
  rerank: resolveRerankLane({
@@ -2593,6 +2596,7 @@ function getEnvSourceNames() {
2593
2596
  "MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
2594
2597
  "MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
2595
2598
  "OPENROUTER_API_KEY",
2599
+ "REQUESTY_API_KEY",
2596
2600
  "ATLASCLOUD_API_KEY"
2597
2601
  ].filter((name) => process.env[name]);
2598
2602
  }
@@ -2605,6 +2609,15 @@ function isOpenRouterUrl(value) {
2605
2609
  return /(^|\.)openrouter\.ai(?::|\/|$)/i.test(value);
2606
2610
  }
2607
2611
  }
2612
+ function isRequestyUrl(value) {
2613
+ if (!value) return false;
2614
+ try {
2615
+ const url = new URL(value);
2616
+ return url.hostname.toLowerCase() === "requesty.ai" || url.hostname.toLowerCase().endsWith(".requesty.ai");
2617
+ } catch {
2618
+ return /(^|\.)requesty\.ai(?::|\/|$)/i.test(value);
2619
+ }
2620
+ }
2608
2621
  function isOpenRouterMemoryLane(provider2, baseUrl) {
2609
2622
  return provider2?.trim().toLowerCase() === "openrouter" || isOpenRouterUrl(baseUrl);
2610
2623
  }
@@ -2759,6 +2772,9 @@ function defaultEmbeddingModelFor(baseUrl, explicitModel) {
2759
2772
  if (url && (url.hostname === "openrouter.ai" || url.hostname.endsWith(".openrouter.ai"))) {
2760
2773
  return "qwen/qwen3-embedding-8b";
2761
2774
  }
2775
+ if (url && (url.hostname === "requesty.ai" || url.hostname.endsWith(".requesty.ai"))) {
2776
+ return "openai/text-embedding-3-small";
2777
+ }
2762
2778
  } catch {
2763
2779
  }
2764
2780
  return "text-embedding-3-small";
@@ -5573,6 +5589,7 @@ var init_provider2 = __esm({
5573
5589
  openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
5574
5590
  anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
5575
5591
  openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
5592
+ requesty: { baseUrl: "https://router.requesty.ai/v1", model: "openai/gpt-4.1-nano" },
5576
5593
  atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
5577
5594
  custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
5578
5595
  };
@@ -178,6 +178,23 @@ This is opt-in background memory processing and may incur API charges. Setting
178
178
  `ATLASCLOUD_API_KEY` alone does not enable it. Embeddings and memcode's model
179
179
  registry are unchanged.
180
180
 
181
+ Requesty is available as a memory LLM preset in `memorix init` and the
182
+ configuration TUI:
183
+
184
+ ```toml
185
+ [memory.llm]
186
+ provider = "requesty"
187
+ model = "openai/gpt-4o-mini"
188
+ ```
189
+
190
+ The preset uses `https://router.requesty.ai/v1` and the existing
191
+ OpenAI-compatible chat completion transport. Set `REQUESTY_API_KEY` or
192
+ `MEMORIX_LLM_API_KEY`; the preset does not fall back to OpenAI, Anthropic, or
193
+ OpenRouter environment keys. Model IDs use the `vendor/model` form, for example
194
+ `anthropic/claude-sonnet-4-5`. To keep traffic in the EU, set
195
+ `base_url = "https://router.eu.requesty.ai/v1"`. Get a key at
196
+ https://app.requesty.ai/api-keys.
197
+
181
198
  OrcaRouter works through the generic OpenAI-compatible gateway path. Keep the
182
199
  provider label as `openai`, set its base URL, and use an explicit model ID:
183
200
 
@@ -247,6 +264,11 @@ OpenAI-only default. The equivalent env-var form is
247
264
  `MEMORIX_EMBEDDING=api`, `MEMORIX_EMBEDDING_BASE_URL=https://openrouter.ai/api/v1`,
248
265
  `MEMORIX_EMBEDDING_MODEL=qwen/qwen3-embedding-8b`.
249
266
 
267
+ Requesty embeddings work the same way with
268
+ `base_url = "https://router.requesty.ai/v1"`. Memorix then accepts
269
+ `REQUESTY_API_KEY` for the embedding endpoint and, when no `model` is
270
+ configured, defaults to `openai/text-embedding-3-small`.
271
+
250
272
  ### Large-store retrieval
251
273
 
252
274
  Memorix does not cap the number of durable observations to make search fast.
@@ -13,7 +13,7 @@ Memorix is a TypeScript project built around:
13
13
 
14
14
  ## Current Development Baseline
15
15
 
16
- The current release line is **1.9.8** and package metadata is kept synchronized
16
+ The current release line is **1.9.9** and package metadata is kept synchronized
17
17
  with the root package and MCP Registry manifest.
18
18
 
19
19
  Contributors should assume the following areas are part of the current release line:
package/docs/README.md CHANGED
@@ -126,7 +126,7 @@ Historical/deep-reference documents may describe older designs. If they conflict
126
126
 
127
127
  ## Current Product Line
128
128
 
129
- The current product line is **1.9.8**. Multi-device store sync is opt-in and
129
+ The current product line is **1.9.9**. Multi-device store sync is opt-in and
130
130
  keeps local SQLite canonical; existing users do not upload anything until they
131
131
  configure a relay provider explicitly.
132
132
  The authoritative acceptance contract for the current implementation is
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "memorix",
3
3
  "mcpName": "io.github.AVIDS2/memorix",
4
- "version": "1.9.8",
4
+ "version": "1.9.9",
5
5
  "description": "Local-first shared memory layer for AI coding agents across MCP clients, Git history, reasoning context, and project sessions.",
6
6
  "type": "module",
7
7
  "sideEffects": false,
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.9.8"
3
+ "version": "1.9.9"
4
4
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://anthropic.com/claude-code/plugin.schema.json",
3
3
  "name": "memorix",
4
- "version": "1.9.8",
4
+ "version": "1.9.9",
5
5
  "description": "Shared workspace memory for Claude Code and other AI coding agents.",
6
6
  "author": {
7
7
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.9.8",
3
+ "version": "1.9.9",
4
4
  "description": "Local-first project memory for CodeBuddy Code and other coding agents.",
5
5
  "author": {
6
6
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.9.8",
3
+ "version": "1.9.9",
4
4
  "description": "Shared workspace memory for Codex and other AI coding agents.",
5
5
  "author": {
6
6
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.9.8",
3
+ "version": "1.9.9",
4
4
  "description": "Shared local workspace memory for GitHub Copilot CLI and other AI coding agents.",
5
5
  "author": {
6
6
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.9.8",
3
+ "version": "1.9.9",
4
4
  "mcpServers": {
5
5
  "memorix": {
6
6
  "command": "memorix",
@@ -1,5 +1,5 @@
1
1
  name: memorix
2
- version: "1.9.8"
2
+ version: "1.9.9"
3
3
  description: Shared workspace memory bridge for Hermes Agent.
4
4
  author: AVIDS2
5
5
  license: Apache-2.0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix-omp-package",
3
- "version": "1.9.8",
3
+ "version": "1.9.9",
4
4
  "description": "Memorix shared workspace memory package for Oh-my-Pi.",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.9.8",
3
+ "version": "1.9.9",
4
4
  "description": "Shared workspace memory for OpenClaw and other AI coding agents.",
5
5
  "author": {
6
6
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix-pi-package",
3
- "version": "1.9.8",
3
+ "version": "1.9.9",
4
4
  "description": "Memorix shared workspace memory package for Pi coding agent.",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
package/server.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "url": "https://github.com/AVIDS2/memorix",
8
8
  "source": "github"
9
9
  },
10
- "version": "1.9.8",
10
+ "version": "1.9.9",
11
11
  "websiteUrl": "https://mem.rglens.com",
12
12
  "icons": [
13
13
  {
@@ -22,7 +22,7 @@
22
22
  {
23
23
  "registryType": "npm",
24
24
  "identifier": "memorix",
25
- "version": "1.9.8",
25
+ "version": "1.9.9",
26
26
  "runtimeHint": "npx",
27
27
  "packageArguments": [
28
28
  {
@@ -21,7 +21,7 @@ import {
21
21
  type InitScope,
22
22
  } from './init-shared.js';
23
23
 
24
- type InitLlmProvider = 'none' | 'openai' | 'anthropic' | 'openrouter' | 'atlascloud' | 'custom';
24
+ type InitLlmProvider = 'none' | 'openai' | 'anthropic' | 'openrouter' | 'requesty' | 'atlascloud' | 'custom';
25
25
  type InitEmbeddingProvider = 'off' | 'api' | 'fastembed';
26
26
  type InitInjectMode = 'minimal' | 'full' | 'silent';
27
27
 
@@ -103,6 +103,7 @@ export default defineCommand({
103
103
  { value: 'openai', label: 'OpenAI', hint: 'gpt-4o-mini' },
104
104
  { value: 'anthropic', label: 'Anthropic', hint: 'claude-3-haiku' },
105
105
  { value: 'openrouter', label: 'OpenRouter', hint: 'multi-provider' },
106
+ { value: 'requesty', label: 'Requesty', hint: 'multi-provider' },
106
107
  { value: 'atlascloud', label: 'Atlas Cloud', hint: 'DeepSeek V3.2' },
107
108
  { value: 'custom', label: 'Custom', hint: 'OpenAI-compatible endpoint' },
108
109
  ],
@@ -169,6 +170,8 @@ export default defineCommand({
169
170
  envLines.push('MEMORIX_LLM_API_KEY=sk-ant-your-key-here');
170
171
  } else if (llmProvider === 'openrouter') {
171
172
  envLines.push('MEMORIX_LLM_API_KEY=sk-or-your-key-here');
173
+ } else if (llmProvider === 'requesty') {
174
+ envLines.push('MEMORIX_LLM_API_KEY=rqsty-your-key-here');
172
175
  }
173
176
  if (llmProvider === 'custom') {
174
177
  envLines.push('# MEMORIX_LLM_BASE_URL=http://localhost:11434/v1');
@@ -197,6 +200,7 @@ export default defineCommand({
197
200
  envLines.push('# OPENAI_API_KEY=sk-...');
198
201
  envLines.push('# ANTHROPIC_API_KEY=sk-ant-...');
199
202
  envLines.push('# OPENROUTER_API_KEY=sk-or-...');
203
+ envLines.push('# REQUESTY_API_KEY=rqsty-...');
200
204
  envLines.push('');
201
205
 
202
206
  mkdirSync(targetDir, { recursive: true });
@@ -293,6 +297,8 @@ export function buildInitTomlConfig(options: {
293
297
  lines.push('model = "claude-3-haiku-20240307"');
294
298
  } else if (options.llmProvider === 'openrouter') {
295
299
  lines.push('# model = "openai/gpt-4o-mini"');
300
+ } else if (options.llmProvider === 'requesty') {
301
+ lines.push('# model = "openai/gpt-4o-mini"');
296
302
  } else if (options.llmProvider === 'atlascloud') {
297
303
  lines.push('model = "deepseek-ai/deepseek-v3.2"');
298
304
  }
@@ -166,6 +166,7 @@ export function ConfigureView({ onBack }: ConfigureViewProps): React.ReactElemen
166
166
  { key: 'openai', label: 'OpenAI', hint: 'gpt-4o-mini' },
167
167
  { key: 'anthropic', label: 'Anthropic', hint: 'claude-3-haiku' },
168
168
  { key: 'openrouter', label: 'OpenRouter', hint: 'multi-provider' },
169
+ { key: 'requesty', label: 'Requesty', hint: 'multi-provider' },
169
170
  { key: 'atlascloud', label: 'Atlas Cloud', hint: 'DeepSeek V3.2' },
170
171
  { key: 'custom', label: 'Custom endpoint', hint: 'OpenAI-compatible' },
171
172
  { key: 'disable', label: 'Disable LLM', hint: 'free heuristic mode', color: COLORS.warning },
@@ -447,6 +448,7 @@ export function ConfigureView({ onBack }: ConfigureViewProps): React.ReactElemen
447
448
  function getDefaultModel(provider: string): string {
448
449
  if (provider === 'anthropic') return 'claude-3-haiku-20240307';
449
450
  if (provider === 'openrouter') return 'openai/gpt-4o-mini';
451
+ if (provider === 'requesty') return 'openai/gpt-4o-mini';
450
452
  if (provider === 'atlascloud') return 'deepseek-ai/deepseek-v3.2';
451
453
  return 'gpt-4o-mini';
452
454
  }
@@ -143,6 +143,7 @@ export function getLoadedEnvValue(key: string): string | undefined {
143
143
  // OPENAI_API_KEY — OpenAI compatibility fallback
144
144
  // ANTHROPIC_API_KEY — Anthropic compatibility fallback
145
145
  // OPENROUTER_API_KEY — OpenRouter compatibility fallback
146
+ // REQUESTY_API_KEY - Requesty memory preset and embedding endpoint key
146
147
  // MINIMAX_API_KEY — MiniMax global image/video generation key
147
148
  // MINIMAX_CN_API_KEY — MiniMax China-region image/video generation key
148
149
  // MINIMAX_REGION — MiniMax region: global or cn
@@ -96,6 +96,7 @@ export function getResolvedConfig(options: ResolvedLaneOptions = {}): ResolvedMe
96
96
  const legacy = loadFileConfig(homeDir);
97
97
  const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
98
98
  const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : undefined;
99
+ const requestyEmbeddingApiKey = isRequestyUrl(embeddingBaseUrl) ? process.env.REQUESTY_API_KEY : undefined;
99
100
  const memoryLlmProvider = first(
100
101
  process.env.MEMORIX_LLM_PROVIDER,
101
102
  toml.memory?.llm?.provider,
@@ -118,16 +119,18 @@ export function getResolvedConfig(options: ResolvedLaneOptions = {}): ResolvedMe
118
119
  ? process.env.OPENROUTER_API_KEY
119
120
  : undefined;
120
121
  const isAtlasCloud = memoryLlmProvider === 'atlascloud';
122
+ const isRequesty = memoryLlmProvider === 'requesty';
123
+ const usesPresetKeyOnly = isAtlasCloud || isRequesty;
121
124
  const memoryLlmApiKey = first(
122
125
  process.env.MEMORIX_LLM_API_KEY,
123
126
  process.env.MEMORIX_API_KEY,
124
127
  toml.memory?.llm?.api_key,
125
128
  yaml.llm?.apiKey,
126
129
  legacy.llm?.apiKey,
127
- // Never borrow another provider's credentials for the Atlas Cloud preset.
128
- isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
129
- isAtlasCloud ? undefined : process.env.ANTHROPIC_API_KEY,
130
- isAtlasCloud ? undefined : openRouterMemoryLlmApiKey,
130
+ // Never borrow another provider's credentials for the Atlas Cloud or Requesty presets.
131
+ isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : isRequesty ? process.env.REQUESTY_API_KEY : process.env.OPENAI_API_KEY,
132
+ usesPresetKeyOnly ? undefined : process.env.ANTHROPIC_API_KEY,
133
+ usesPresetKeyOnly ? undefined : openRouterMemoryLlmApiKey,
131
134
  );
132
135
 
133
136
  const resolved: ResolvedMemorixConfig = {
@@ -177,7 +180,7 @@ export function getResolvedConfig(options: ResolvedLaneOptions = {}): ResolvedMe
177
180
  provider: first(process.env.MEMORIX_EMBEDDING, toml.embedding?.provider, yaml.embedding?.provider, legacy.embedding, 'off'),
178
181
  model: first(process.env.MEMORIX_EMBEDDING_MODEL, toml.embedding?.model, yaml.embedding?.model, legacy.embeddingApi?.model),
179
182
  baseUrl: embeddingBaseUrl,
180
- apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey),
183
+ apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey, requestyEmbeddingApiKey),
181
184
  dimensions: firstNumber(parseNumber(process.env.MEMORIX_EMBEDDING_DIMENSIONS), toml.embedding?.dimensions, yaml.embedding?.dimensions, legacy.embeddingApi?.dimensions),
182
185
  },
183
186
  rerank: resolveRerankLane({
@@ -323,6 +326,7 @@ function getEnvSourceNames(): string[] {
323
326
  'MEMORIX_CODEGRAPH_EXTERNAL_COMMAND',
324
327
  'MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS',
325
328
  'OPENROUTER_API_KEY',
329
+ 'REQUESTY_API_KEY',
326
330
  'ATLASCLOUD_API_KEY',
327
331
  ].filter((name) => process.env[name]);
328
332
  }
@@ -337,6 +341,16 @@ function isOpenRouterUrl(value: string | undefined): boolean {
337
341
  }
338
342
  }
339
343
 
344
+ function isRequestyUrl(value: string | undefined): boolean {
345
+ if (!value) return false;
346
+ try {
347
+ const url = new URL(value);
348
+ return url.hostname.toLowerCase() === 'requesty.ai' || url.hostname.toLowerCase().endsWith('.requesty.ai');
349
+ } catch {
350
+ return /(^|\.)requesty\.ai(?::|\/|$)/i.test(value);
351
+ }
352
+ }
353
+
340
354
  function isOpenRouterMemoryLane(provider: string | undefined, baseUrl: string | undefined): boolean {
341
355
  return provider?.trim().toLowerCase() === 'openrouter' || isOpenRouterUrl(baseUrl);
342
356
  }
@@ -25,7 +25,7 @@ import { getGlobalYamlPath, getProjectYamlPath } from './config-paths.js';
25
25
  export interface MemorixYamlConfig {
26
26
  /** LLM provider configuration */
27
27
  llm?: {
28
- provider?: 'openai' | 'anthropic' | 'openrouter' | string;
28
+ provider?: 'openai' | 'anthropic' | 'openrouter' | 'requesty' | string;
29
29
  model?: string;
30
30
  apiKey?: string;
31
31
  baseUrl?: string;
@@ -33,7 +33,7 @@ export interface MemorixYamlConfig {
33
33
 
34
34
  /** TUI / chat agent LLM provider configuration */
35
35
  agent?: {
36
- provider?: 'openai' | 'anthropic' | 'openrouter' | string;
36
+ provider?: 'openai' | 'anthropic' | 'openrouter' | 'requesty' | string;
37
37
  model?: string;
38
38
  apiKey?: string;
39
39
  baseUrl?: string;
package/src/config.ts CHANGED
@@ -93,7 +93,8 @@ export function getEmbeddingModel(): string {
93
93
  /**
94
94
  * Provider-aware embedding model default: OpenRouter serves many providers,
95
95
  * and the OpenAI-only default does not fit it. Qwen3-Embedding-8B is a
96
- * strong multilingual default there; everywhere else keep the OpenAI model.
96
+ * strong multilingual default there. Requesty expects vendor-prefixed ids,
97
+ * so it gets the prefixed OpenAI model. Everywhere else keep the OpenAI model.
97
98
  * An explicitly configured model always wins.
98
99
  */
99
100
  export function defaultEmbeddingModelFor(
@@ -106,6 +107,9 @@ export function defaultEmbeddingModelFor(
106
107
  if (url && (url.hostname === 'openrouter.ai' || url.hostname.endsWith('.openrouter.ai'))) {
107
108
  return 'qwen/qwen3-embedding-8b';
108
109
  }
110
+ if (url && (url.hostname === 'requesty.ai' || url.hostname.endsWith('.requesty.ai'))) {
111
+ return 'openai/text-embedding-3-small';
112
+ }
109
113
  } catch { /* treat unparsable base URLs as non-OpenRouter */ }
110
114
  return 'text-embedding-3-small';
111
115
  }
@@ -682,6 +682,9 @@ async function handleApi(
682
682
  ...(resolved.memory.llm.provider === 'openrouter' || resolved.memory.llm.baseUrl?.includes('openrouter.ai')
683
683
  ? ['OPENROUTER_API_KEY']
684
684
  : []),
685
+ ...(resolved.memory.llm.provider === 'requesty'
686
+ ? ['REQUESTY_API_KEY']
687
+ : []),
685
688
  ];
686
689
  if (llmKey) {
687
690
  const src = resolveDashboardKeySource({ value: llmKey, envKeys: memoryKeyEnv, configSource });
@@ -20,7 +20,7 @@ import {
20
20
  } from '../config.js';
21
21
 
22
22
  export interface LLMConfig {
23
- provider: 'openai' | 'anthropic' | 'openrouter' | 'atlascloud' | 'custom';
23
+ provider: 'openai' | 'anthropic' | 'openrouter' | 'requesty' | 'atlascloud' | 'custom';
24
24
  apiKey: string;
25
25
  model?: string;
26
26
  baseUrl?: string;
@@ -201,6 +201,7 @@ const PROVIDER_DEFAULTS: Record<string, { baseUrl: string; model: string }> = {
201
201
  openai: { baseUrl: 'https://api.openai.com/v1', model: 'gpt-4.1-nano' },
202
202
  anthropic: { baseUrl: 'https://api.anthropic.com/v1', model: 'claude-3-5-haiku-latest' },
203
203
  openrouter: { baseUrl: 'https://openrouter.ai/api/v1', model: 'openai/gpt-4.1-nano' },
204
+ requesty: { baseUrl: 'https://router.requesty.ai/v1', model: 'openai/gpt-4.1-nano' },
204
205
  atlascloud: { baseUrl: 'https://api.atlascloud.ai/v1', model: 'deepseek-ai/deepseek-v3.2' },
205
206
  custom: { baseUrl: 'http://localhost:11434/v1', model: 'llama3' },
206
207
  };
@@ -19,7 +19,7 @@ import {
19
19
  } from './image-payload.js';
20
20
 
21
21
  // Providers that use the OpenAI-compatible /chat/completions Vision endpoint
22
- const OPENAI_COMPATIBLE_PROVIDERS = new Set(['openai', 'openrouter', 'custom']);
22
+ const OPENAI_COMPATIBLE_PROVIDERS = new Set(['openai', 'openrouter', 'requesty', 'custom']);
23
23
  const MAX_VISION_PROMPT_CHARS = 12_000;
24
24
  const MAX_VISION_DESCRIPTION_CHARS = 12_000;
25
25
  const MAX_VISION_LABELS = 50;
@@ -137,7 +137,7 @@ export async function analyzeImage(input: ImageInput): Promise<ImageAnalysisResu
137
137
  const config = getLLMConfig()!;
138
138
  if (!OPENAI_COMPATIBLE_PROVIDERS.has(config.provider)) {
139
139
  throw new Error(
140
- `Image analysis requires an OpenAI-compatible provider (openai, openrouter, or custom). ` +
140
+ `Image analysis requires an OpenAI-compatible provider (openai, openrouter, requesty, or custom). ` +
141
141
  `Current provider "${config.provider}" uses a different API shape. ` +
142
142
  `Set MEMORIX_LLM_PROVIDER=openai or configure an OpenAI-compatible base URL.`,
143
143
  );