memorix 1.4.6 → 1.5.0

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
@@ -2,6 +2,30 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [1.5.0] - 2026-08-14
6
+
7
+ ### Added
8
+ - **Stability stress suite** -- Five deterministic, offline stress exams now
9
+ run in the normal test suite: a 2,000-observation corpus (planted needles,
10
+ ranked determinism, project isolation), 60-way parallel writes plus
11
+ 20-way same-topic upserts, session churn across projects with parallel
12
+ starts, 300-record long-term maintenance exactness, and repeated CLI
13
+ invocations. Live embedding stress exams are env-gated
14
+ (`MEMORIX_RUN_LIVE_EMBEDDING_TESTS=1`) and never run in CI.
15
+ - **Provider-aware embedding default** -- When the embedding base URL
16
+ points at OpenRouter and no model is configured, the default is now
17
+ `qwen/qwen3-embedding-8b` (4096 dimensions) instead of the OpenAI-only
18
+ default. An explicitly configured model always wins.
19
+
20
+ ### Changed
21
+ - **Verified OpenRouter embedding lane** -- The `api` embedding provider
22
+ was exercised live against `qwen/qwen3-embedding-8b` on OpenRouter:
23
+ a 100-text batch, cache round-trip, and provider-singleton stability all
24
+ pass. Docs cover the env-var form and borrowing `OPENROUTER_API_KEY`.
25
+ - **Multimodal vision option documented** -- Image analysis can run on the
26
+ LLM lane through an OpenAI-compatible vision endpoint, including
27
+ OpenRouter models such as `qwen/qwen3-vl-8b-instruct`.
28
+
5
29
  ## [1.4.6] - 2026-08-14
6
30
 
7
31
  ### Added
package/dist/cli/index.js CHANGED
@@ -3221,7 +3221,7 @@ ${import_picocolors.default.gray(m3)} ${s4}
3221
3221
 
3222
3222
  // src/cli/version.ts
3223
3223
  function getCliVersion() {
3224
- return true ? "1.4.6" : pkg.version;
3224
+ return true ? "1.5.0" : pkg.version;
3225
3225
  }
3226
3226
  var init_version = __esm({
3227
3227
  "src/cli/version.ts"() {
@@ -21713,6 +21713,7 @@ var init_resolved_config = __esm({
21713
21713
  // src/config.ts
21714
21714
  var config_exports = {};
21715
21715
  __export(config_exports, {
21716
+ defaultEmbeddingModelFor: () => defaultEmbeddingModelFor,
21716
21717
  getAgentLLMApiKey: () => getAgentLLMApiKey,
21717
21718
  getAgentLLMBaseUrl: () => getAgentLLMBaseUrl,
21718
21719
  getAgentLLMModel: () => getAgentLLMModel,
@@ -21775,7 +21776,19 @@ function getEmbeddingBaseUrl() {
21775
21776
  return getResolvedEmbeddingLane().baseUrl || "https://api.openai.com/v1";
21776
21777
  }
21777
21778
  function getEmbeddingModel() {
21778
- return getResolvedEmbeddingLane().model || "text-embedding-3-small";
21779
+ const lane = getResolvedEmbeddingLane();
21780
+ return defaultEmbeddingModelFor(lane.baseUrl, lane.model);
21781
+ }
21782
+ function defaultEmbeddingModelFor(baseUrl, explicitModel) {
21783
+ if (explicitModel) return explicitModel;
21784
+ try {
21785
+ const url2 = baseUrl ? new URL(baseUrl) : null;
21786
+ if (url2 && (url2.hostname === "openrouter.ai" || url2.hostname.endsWith(".openrouter.ai"))) {
21787
+ return "qwen/qwen3-embedding-8b";
21788
+ }
21789
+ } catch {
21790
+ }
21791
+ return "text-embedding-3-small";
21779
21792
  }
21780
21793
  function getEmbeddingDimensions() {
21781
21794
  return getResolvedEmbeddingLane().dimensions ?? null;
@@ -258695,7 +258708,7 @@ The path should point to a directory containing a .git folder.`
258695
258708
  };
258696
258709
  const server = existingServer ?? new McpServer({
258697
258710
  name: "memorix",
258698
- version: true ? "1.4.6" : "1.0.1"
258711
+ version: true ? "1.5.0" : "1.0.1"
258699
258712
  });
258700
258713
  const originalRegisterTool = server.registerTool.bind(server);
258701
258714
  server.registerTool = ((name, ...args) => {
package/dist/index.js CHANGED
@@ -3373,6 +3373,7 @@ var init_resolved_config = __esm({
3373
3373
  // src/config.ts
3374
3374
  var config_exports = {};
3375
3375
  __export(config_exports, {
3376
+ defaultEmbeddingModelFor: () => defaultEmbeddingModelFor,
3376
3377
  getAgentLLMApiKey: () => getAgentLLMApiKey,
3377
3378
  getAgentLLMBaseUrl: () => getAgentLLMBaseUrl,
3378
3379
  getAgentLLMModel: () => getAgentLLMModel,
@@ -3435,7 +3436,19 @@ function getEmbeddingBaseUrl() {
3435
3436
  return getResolvedEmbeddingLane().baseUrl || "https://api.openai.com/v1";
3436
3437
  }
3437
3438
  function getEmbeddingModel() {
3438
- return getResolvedEmbeddingLane().model || "text-embedding-3-small";
3439
+ const lane = getResolvedEmbeddingLane();
3440
+ return defaultEmbeddingModelFor(lane.baseUrl, lane.model);
3441
+ }
3442
+ function defaultEmbeddingModelFor(baseUrl, explicitModel) {
3443
+ if (explicitModel) return explicitModel;
3444
+ try {
3445
+ const url = baseUrl ? new URL(baseUrl) : null;
3446
+ if (url && (url.hostname === "openrouter.ai" || url.hostname.endsWith(".openrouter.ai"))) {
3447
+ return "qwen/qwen3-embedding-8b";
3448
+ }
3449
+ } catch {
3450
+ }
3451
+ return "text-embedding-3-small";
3439
3452
  }
3440
3453
  function getEmbeddingDimensions() {
3441
3454
  return getResolvedEmbeddingLane().dimensions ?? null;
@@ -165821,7 +165834,7 @@ The path should point to a directory containing a .git folder.`
165821
165834
  };
165822
165835
  const server = existingServer ?? new McpServer({
165823
165836
  name: "memorix",
165824
- version: true ? "1.4.6" : "1.0.1"
165837
+ version: true ? "1.5.0" : "1.0.1"
165825
165838
  });
165826
165839
  const originalRegisterTool = server.registerTool.bind(server);
165827
165840
  server.registerTool = ((name, ...args) => {
@@ -170200,7 +170213,7 @@ var init_serve_shared = __esm({
170200
170213
 
170201
170214
  // src/cli/version.ts
170202
170215
  function getCliVersion() {
170203
- return true ? "1.4.6" : pkg.version;
170216
+ return true ? "1.5.0" : pkg.version;
170204
170217
  }
170205
170218
  var init_version3 = __esm({
170206
170219
  "src/cli/version.ts"() {
@@ -1868,6 +1868,7 @@ var init_resolved_config = __esm({
1868
1868
  // src/config.ts
1869
1869
  var config_exports = {};
1870
1870
  __export(config_exports, {
1871
+ defaultEmbeddingModelFor: () => defaultEmbeddingModelFor,
1871
1872
  getAgentLLMApiKey: () => getAgentLLMApiKey,
1872
1873
  getAgentLLMBaseUrl: () => getAgentLLMBaseUrl,
1873
1874
  getAgentLLMModel: () => getAgentLLMModel,
@@ -1930,7 +1931,19 @@ function getEmbeddingBaseUrl() {
1930
1931
  return getResolvedEmbeddingLane().baseUrl || "https://api.openai.com/v1";
1931
1932
  }
1932
1933
  function getEmbeddingModel() {
1933
- return getResolvedEmbeddingLane().model || "text-embedding-3-small";
1934
+ const lane = getResolvedEmbeddingLane();
1935
+ return defaultEmbeddingModelFor(lane.baseUrl, lane.model);
1936
+ }
1937
+ function defaultEmbeddingModelFor(baseUrl, explicitModel) {
1938
+ if (explicitModel) return explicitModel;
1939
+ try {
1940
+ const url = baseUrl ? new URL(baseUrl) : null;
1941
+ if (url && (url.hostname === "openrouter.ai" || url.hostname.endsWith(".openrouter.ai"))) {
1942
+ return "qwen/qwen3-embedding-8b";
1943
+ }
1944
+ } catch {
1945
+ }
1946
+ return "text-embedding-3-small";
1934
1947
  }
1935
1948
  function getEmbeddingDimensions() {
1936
1949
  return getResolvedEmbeddingLane().dimensions ?? null;
@@ -3124,6 +3124,7 @@ var init_resolved_config = __esm({
3124
3124
  // src/config.ts
3125
3125
  var config_exports = {};
3126
3126
  __export(config_exports, {
3127
+ defaultEmbeddingModelFor: () => defaultEmbeddingModelFor,
3127
3128
  getAgentLLMApiKey: () => getAgentLLMApiKey,
3128
3129
  getAgentLLMBaseUrl: () => getAgentLLMBaseUrl,
3129
3130
  getAgentLLMModel: () => getAgentLLMModel,
@@ -3186,7 +3187,19 @@ function getEmbeddingBaseUrl() {
3186
3187
  return getResolvedEmbeddingLane().baseUrl || "https://api.openai.com/v1";
3187
3188
  }
3188
3189
  function getEmbeddingModel() {
3189
- return getResolvedEmbeddingLane().model || "text-embedding-3-small";
3190
+ const lane = getResolvedEmbeddingLane();
3191
+ return defaultEmbeddingModelFor(lane.baseUrl, lane.model);
3192
+ }
3193
+ function defaultEmbeddingModelFor(baseUrl, explicitModel) {
3194
+ if (explicitModel) return explicitModel;
3195
+ try {
3196
+ const url = baseUrl ? new URL(baseUrl) : null;
3197
+ if (url && (url.hostname === "openrouter.ai" || url.hostname.endsWith(".openrouter.ai"))) {
3198
+ return "qwen/qwen3-embedding-8b";
3199
+ }
3200
+ } catch {
3201
+ }
3202
+ return "text-embedding-3-small";
3190
3203
  }
3191
3204
  function getEmbeddingDimensions() {
3192
3205
  return getResolvedEmbeddingLane().dimensions ?? null;
@@ -2141,6 +2141,7 @@ var init_resolved_config = __esm({
2141
2141
  // src/config.ts
2142
2142
  var config_exports = {};
2143
2143
  __export(config_exports, {
2144
+ defaultEmbeddingModelFor: () => defaultEmbeddingModelFor,
2144
2145
  getAgentLLMApiKey: () => getAgentLLMApiKey,
2145
2146
  getAgentLLMBaseUrl: () => getAgentLLMBaseUrl,
2146
2147
  getAgentLLMModel: () => getAgentLLMModel,
@@ -2203,7 +2204,19 @@ function getEmbeddingBaseUrl() {
2203
2204
  return getResolvedEmbeddingLane().baseUrl || "https://api.openai.com/v1";
2204
2205
  }
2205
2206
  function getEmbeddingModel() {
2206
- return getResolvedEmbeddingLane().model || "text-embedding-3-small";
2207
+ const lane = getResolvedEmbeddingLane();
2208
+ return defaultEmbeddingModelFor(lane.baseUrl, lane.model);
2209
+ }
2210
+ function defaultEmbeddingModelFor(baseUrl, explicitModel) {
2211
+ if (explicitModel) return explicitModel;
2212
+ try {
2213
+ const url = baseUrl ? new URL(baseUrl) : null;
2214
+ if (url && (url.hostname === "openrouter.ai" || url.hostname.endsWith(".openrouter.ai"))) {
2215
+ return "qwen/qwen3-embedding-8b";
2216
+ }
2217
+ } catch {
2218
+ }
2219
+ return "text-embedding-3-small";
2207
2220
  }
2208
2221
  function getEmbeddingDimensions() {
2209
2222
  return getResolvedEmbeddingLane().dimensions ?? null;
@@ -2,6 +2,30 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [1.5.0] - 2026-08-14
6
+
7
+ ### Added
8
+ - **Stability stress suite** -- Five deterministic, offline stress exams now
9
+ run in the normal test suite: a 2,000-observation corpus (planted needles,
10
+ ranked determinism, project isolation), 60-way parallel writes plus
11
+ 20-way same-topic upserts, session churn across projects with parallel
12
+ starts, 300-record long-term maintenance exactness, and repeated CLI
13
+ invocations. Live embedding stress exams are env-gated
14
+ (`MEMORIX_RUN_LIVE_EMBEDDING_TESTS=1`) and never run in CI.
15
+ - **Provider-aware embedding default** -- When the embedding base URL
16
+ points at OpenRouter and no model is configured, the default is now
17
+ `qwen/qwen3-embedding-8b` (4096 dimensions) instead of the OpenAI-only
18
+ default. An explicitly configured model always wins.
19
+
20
+ ### Changed
21
+ - **Verified OpenRouter embedding lane** -- The `api` embedding provider
22
+ was exercised live against `qwen/qwen3-embedding-8b` on OpenRouter:
23
+ a 100-text batch, cache round-trip, and provider-singleton stability all
24
+ pass. Docs cover the env-var form and borrowing `OPENROUTER_API_KEY`.
25
+ - **Multimodal vision option documented** -- Image analysis can run on the
26
+ LLM lane through an OpenAI-compatible vision endpoint, including
27
+ OpenRouter models such as `qwen/qwen3-vl-8b-instruct`.
28
+
5
29
  ## [1.4.6] - 2026-08-14
6
30
 
7
31
  ### Added
package/dist/sdk.js CHANGED
@@ -3377,6 +3377,7 @@ var init_resolved_config = __esm({
3377
3377
  // src/config.ts
3378
3378
  var config_exports = {};
3379
3379
  __export(config_exports, {
3380
+ defaultEmbeddingModelFor: () => defaultEmbeddingModelFor,
3380
3381
  getAgentLLMApiKey: () => getAgentLLMApiKey,
3381
3382
  getAgentLLMBaseUrl: () => getAgentLLMBaseUrl,
3382
3383
  getAgentLLMModel: () => getAgentLLMModel,
@@ -3439,7 +3440,19 @@ function getEmbeddingBaseUrl() {
3439
3440
  return getResolvedEmbeddingLane().baseUrl || "https://api.openai.com/v1";
3440
3441
  }
3441
3442
  function getEmbeddingModel() {
3442
- return getResolvedEmbeddingLane().model || "text-embedding-3-small";
3443
+ const lane = getResolvedEmbeddingLane();
3444
+ return defaultEmbeddingModelFor(lane.baseUrl, lane.model);
3445
+ }
3446
+ function defaultEmbeddingModelFor(baseUrl, explicitModel) {
3447
+ if (explicitModel) return explicitModel;
3448
+ try {
3449
+ const url = baseUrl ? new URL(baseUrl) : null;
3450
+ if (url && (url.hostname === "openrouter.ai" || url.hostname.endsWith(".openrouter.ai"))) {
3451
+ return "qwen/qwen3-embedding-8b";
3452
+ }
3453
+ } catch {
3454
+ }
3455
+ return "text-embedding-3-small";
3443
3456
  }
3444
3457
  function getEmbeddingDimensions() {
3445
3458
  return getResolvedEmbeddingLane().dimensions ?? null;
@@ -165629,7 +165642,7 @@ The path should point to a directory containing a .git folder.`
165629
165642
  };
165630
165643
  const server = existingServer ?? new McpServer({
165631
165644
  name: "memorix",
165632
- version: true ? "1.4.6" : "1.0.1"
165645
+ version: true ? "1.5.0" : "1.0.1"
165633
165646
  });
165634
165647
  const originalRegisterTool = server.registerTool.bind(server);
165635
165648
  server.registerTool = ((name, ...args) => {
@@ -2141,6 +2141,7 @@ var init_resolved_config = __esm({
2141
2141
  // src/config.ts
2142
2142
  var config_exports = {};
2143
2143
  __export(config_exports, {
2144
+ defaultEmbeddingModelFor: () => defaultEmbeddingModelFor,
2144
2145
  getAgentLLMApiKey: () => getAgentLLMApiKey,
2145
2146
  getAgentLLMBaseUrl: () => getAgentLLMBaseUrl,
2146
2147
  getAgentLLMModel: () => getAgentLLMModel,
@@ -2203,7 +2204,19 @@ function getEmbeddingBaseUrl() {
2203
2204
  return getResolvedEmbeddingLane().baseUrl || "https://api.openai.com/v1";
2204
2205
  }
2205
2206
  function getEmbeddingModel() {
2206
- return getResolvedEmbeddingLane().model || "text-embedding-3-small";
2207
+ const lane = getResolvedEmbeddingLane();
2208
+ return defaultEmbeddingModelFor(lane.baseUrl, lane.model);
2209
+ }
2210
+ function defaultEmbeddingModelFor(baseUrl, explicitModel) {
2211
+ if (explicitModel) return explicitModel;
2212
+ try {
2213
+ const url = baseUrl ? new URL(baseUrl) : null;
2214
+ if (url && (url.hostname === "openrouter.ai" || url.hostname.endsWith(".openrouter.ai"))) {
2215
+ return "qwen/qwen3-embedding-8b";
2216
+ }
2217
+ } catch {
2218
+ }
2219
+ return "text-embedding-3-small";
2207
2220
  }
2208
2221
  function getEmbeddingDimensions() {
2209
2222
  return getResolvedEmbeddingLane().dimensions ?? null;
@@ -180,6 +180,18 @@ Then set `OPENROUTER_API_KEY` in your shell, user environment, or `.env`. You
180
180
  can still set `MEMORIX_EMBEDDING_API_KEY` when you want an explicit embedding
181
181
  key override; it takes priority over `OPENROUTER_API_KEY`.
182
182
 
183
+ When `base_url` points at OpenRouter and no `model` is configured, Memorix
184
+ defaults to `qwen/qwen3-embedding-8b` (4096 dimensions) instead of the
185
+ OpenAI-only default. The equivalent env-var form is
186
+ `MEMORIX_EMBEDDING=api`, `MEMORIX_EMBEDDING_BASE_URL=https://openrouter.ai/api/v1`,
187
+ `MEMORIX_EMBEDDING_MODEL=qwen/qwen3-embedding-8b`.
188
+
189
+ Image analysis (visual description for ingested images) runs on the LLM lane
190
+ through an OpenAI-compatible vision endpoint, so it can also use OpenRouter
191
+ with a multimodal model — for example `qwen/qwen3-vl-8b-instruct` via
192
+ `MEMORIX_LLM_BASE_URL=https://openrouter.ai/api/v1` and
193
+ `MEMORIX_LLM_MODEL=qwen/qwen3-vl-8b-instruct`.
194
+
183
195
  ### Controlled MiniMax media
184
196
 
185
197
  MiniMax generation is separate from the text embedding lane. Set one of these
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "memorix",
3
3
  "mcpName": "io.github.AVIDS2/memorix",
4
- "version": "1.4.6",
4
+ "version": "1.5.0",
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,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://anthropic.com/claude-code/plugin.schema.json",
3
3
  "name": "memorix",
4
- "version": "1.4.6",
4
+ "version": "1.5.0",
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.4.6",
3
+ "version": "1.5.0",
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.4.6",
3
+ "version": "1.5.0",
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.4.6",
3
+ "version": "1.5.0",
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.4.6",
3
+ "version": "1.5.0",
4
4
  "mcpServers": {
5
5
  "memorix": {
6
6
  "command": "memorix",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix-omp-package",
3
- "version": "1.4.6",
3
+ "version": "1.5.0",
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.4.6",
3
+ "version": "1.5.0",
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.4.6",
3
+ "version": "1.5.0",
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.4.6",
10
+ "version": "1.5.0",
11
11
  "websiteUrl": "https://github.com/AVIDS2/memorix#readme",
12
12
  "icons": [
13
13
  {
@@ -22,7 +22,7 @@
22
22
  {
23
23
  "registryType": "npm",
24
24
  "identifier": "memorix",
25
- "version": "1.4.6",
25
+ "version": "1.5.0",
26
26
  "runtimeHint": "npx",
27
27
  "packageArguments": [
28
28
  {
package/src/config.ts CHANGED
@@ -84,9 +84,30 @@ export function getEmbeddingBaseUrl(): string {
84
84
  return getResolvedEmbeddingLane().baseUrl || 'https://api.openai.com/v1';
85
85
  }
86
86
 
87
- /** Embedding model: env > memorix.yml > config.json > default */
87
+ /** Embedding model: env > memorix.yml > config.json > provider-aware default */
88
88
  export function getEmbeddingModel(): string {
89
- return getResolvedEmbeddingLane().model || 'text-embedding-3-small';
89
+ const lane = getResolvedEmbeddingLane();
90
+ return defaultEmbeddingModelFor(lane.baseUrl, lane.model);
91
+ }
92
+
93
+ /**
94
+ * Provider-aware embedding model default: OpenRouter serves many providers,
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.
97
+ * An explicitly configured model always wins.
98
+ */
99
+ export function defaultEmbeddingModelFor(
100
+ baseUrl: string | undefined,
101
+ explicitModel: string | undefined,
102
+ ): string {
103
+ if (explicitModel) return explicitModel;
104
+ try {
105
+ const url = baseUrl ? new URL(baseUrl) : null;
106
+ if (url && (url.hostname === 'openrouter.ai' || url.hostname.endsWith('.openrouter.ai'))) {
107
+ return 'qwen/qwen3-embedding-8b';
108
+ }
109
+ } catch { /* treat unparsable base URLs as non-OpenRouter */ }
110
+ return 'text-embedding-3-small';
90
111
  }
91
112
 
92
113
  /** Embedding dimensions override: env > memorix.yml > config.json > null (auto-detect) */