memorix 0.7.0 → 0.7.2

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,21 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.7.2] — 2026-02-22
6
+
7
+ ### Fixed
8
+ - **`memorix_workspace_sync` rejects `kiro` as target** — Added `kiro` to `AGENT_TARGETS` enum (adapter was already implemented but missing from the tool's input schema)
9
+ - **`memorix_rules_sync` missing `kiro` target** — Added `kiro` to `RULE_SOURCES` enum so Kiro steering rules can be generated as a sync target
10
+ - **VS Code Copilot README config** — Separated `.vscode/mcp.json` (workspace) and `settings.json` (global) formats which have different JSON structures
11
+
12
+ ## [0.7.1] — 2026-02-22
13
+
14
+ ### Fixed
15
+ - **Dashboard checkbox checkmark not visible** — Added `position: relative/absolute` to `.obs-checkbox::after` so the ✓ renders correctly in batch select mode
16
+ - **Embedding provider status flickers to "fulltext only"** — Replaced `initialized` boolean flag with a shared Promise lock; concurrent callers now wait for the same initialization instead of seeing `provider = null` mid-load
17
+ - **`memorix_dashboard` MCP tool reliability** — Replaced fixed 800ms wait with TCP port polling (up to 5s) so the tool only returns after the HTTP server is actually listening
18
+ - **Dashboard embedding status always shows "fulltext only"** — Fixed root cause: dashboard is an independent process, `isEmbeddingEnabled()` from orama-store always returns false there; now uses `provider !== null` directly
19
+
5
20
  ## [0.7.0] — 2026-02-21
6
21
 
7
22
  ### Added
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  <a href="https://www.npmjs.com/package/memorix"><img src="https://img.shields.io/npm/dm/memorix.svg?style=flat-square&color=blue" alt="npm downloads"></a>
8
8
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-green.svg?style=flat-square" alt="License"></a>
9
9
  <a href="https://github.com/AVIDS2/memorix"><img src="https://img.shields.io/github/stars/AVIDS2/memorix?style=flat-square&color=yellow" alt="GitHub stars"></a>
10
- <img src="https://img.shields.io/badge/tests-405%20passed-brightgreen?style=flat-square" alt="Tests">
10
+ <img src="https://img.shields.io/badge/tests-422%20passed-brightgreen?style=flat-square" alt="Tests">
11
11
  </p>
12
12
  <p align="center">
13
13
  <a href="#-quick-start">Quick Start</a> •
@@ -28,11 +28,8 @@
28
28
 
29
29
  ## ⚡ Quick Start
30
30
 
31
- ### 30-Second Setup (Zero Install)
31
+ One config line. Seven agents. Zero context loss.
32
32
 
33
- Add Memorix to your agent's MCP config — **that's it**. No global install needed.
34
-
35
- **Windsurf** → `~/.codeium/windsurf/mcp_config.json`
36
33
  ```json
37
34
  {
38
35
  "mcpServers": {
@@ -44,17 +41,9 @@ Add Memorix to your agent's MCP config — **that's it**. No global install need
44
41
  }
45
42
  ```
46
43
 
47
- Restart your agent and Memorix is running! 🎉
48
-
49
- > 💡 More agent configs: [Cursor](#cursor) • [Claude Code](#claude-code) • [Codex](#codex) • [VS Code Copilot](#vs-code-copilot) • [Antigravity](#antigravity) • [Kiro](#kiro)
50
-
51
- ### Or Install Globally
52
-
53
- ```bash
54
- npm install -g memorix
55
- ```
44
+ Add this to your agent's MCP config, restart done. 🎉
56
45
 
57
- Then use `"command": "memorix"` instead of `"command": "npx"` in your config.
46
+ > 💡 Agent-specific config paths: [Windsurf](#windsurf) [Cursor](#cursor) [Claude Code](#claude-code) [Codex](#codex) • [VS Code Copilot](#vs-code-copilot) • [Antigravity](#antigravity) • [Kiro](#kiro)
58
47
 
59
48
  ---
60
49
 
@@ -143,6 +132,32 @@ Session 2: New chat, same project
143
132
 
144
133
  ## 🔧 Agent Configuration
145
134
 
135
+ ### Windsurf
136
+
137
+ `~/.codeium/windsurf/mcp_config.json`:
138
+ ```json
139
+ {
140
+ "mcpServers": {
141
+ "memorix": {
142
+ "command": "npx",
143
+ "args": ["-y", "memorix@latest", "serve"]
144
+ }
145
+ }
146
+ }
147
+ ```
148
+
149
+ > **Timeout troubleshooting** — If you see `MCP server initialization timed out after 60 seconds`, add `--cwd` to force the project root:
150
+ > ```json
151
+ > {
152
+ > "mcpServers": {
153
+ > "memorix": {
154
+ > "command": "npx",
155
+ > "args": ["-y", "memorix@latest", "serve", "--cwd", "<your-project-path>"]
156
+ > }
157
+ > }
158
+ > }
159
+ > ```
160
+
146
161
  ### Cursor
147
162
 
148
163
  `.cursor/mcp.json`:
@@ -182,7 +197,19 @@ args = ["-y", "memorix@latest", "serve"]
182
197
 
183
198
  ### VS Code Copilot
184
199
 
185
- `.vscode/mcp.json` or VS Code `settings.json`:
200
+ **Option A** — `.vscode/mcp.json` (workspace-scoped):
201
+ ```json
202
+ {
203
+ "servers": {
204
+ "memorix": {
205
+ "command": "npx",
206
+ "args": ["-y", "memorix@latest", "serve"]
207
+ }
208
+ }
209
+ }
210
+ ```
211
+
212
+ **Option B** — VS Code `settings.json` (global):
186
213
  ```json
187
214
  {
188
215
  "mcp": {
package/dist/cli/index.js CHANGED
@@ -571,24 +571,26 @@ __export(provider_exports, {
571
571
  resetProvider: () => resetProvider
572
572
  });
573
573
  async function getEmbeddingProvider() {
574
- if (initialized) return provider;
575
- initialized = true;
576
- try {
577
- const { FastEmbedProvider: FastEmbedProvider2 } = await Promise.resolve().then(() => (init_fastembed_provider(), fastembed_provider_exports));
578
- provider = await FastEmbedProvider2.create();
579
- console.error(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
580
- return provider;
581
- } catch {
582
- }
583
- try {
584
- const { TransformersProvider: TransformersProvider2 } = await Promise.resolve().then(() => (init_transformers_provider(), transformers_provider_exports));
585
- provider = await TransformersProvider2.create();
586
- console.error(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
587
- return provider;
588
- } catch {
589
- }
590
- console.error("[memorix] No embedding provider available \u2014 using fulltext search only");
591
- return null;
574
+ if (initPromise) return initPromise;
575
+ initPromise = (async () => {
576
+ try {
577
+ const { FastEmbedProvider: FastEmbedProvider2 } = await Promise.resolve().then(() => (init_fastembed_provider(), fastembed_provider_exports));
578
+ provider = await FastEmbedProvider2.create();
579
+ console.error(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
580
+ return provider;
581
+ } catch {
582
+ }
583
+ try {
584
+ const { TransformersProvider: TransformersProvider2 } = await Promise.resolve().then(() => (init_transformers_provider(), transformers_provider_exports));
585
+ provider = await TransformersProvider2.create();
586
+ console.error(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
587
+ return provider;
588
+ } catch {
589
+ }
590
+ console.error("[memorix] No embedding provider available \u2014 using fulltext search only");
591
+ return null;
592
+ })();
593
+ return initPromise;
592
594
  }
593
595
  async function isVectorSearchAvailable() {
594
596
  const p3 = await getEmbeddingProvider();
@@ -596,15 +598,15 @@ async function isVectorSearchAvailable() {
596
598
  }
597
599
  function resetProvider() {
598
600
  provider = null;
599
- initialized = false;
601
+ initPromise = null;
600
602
  }
601
- var provider, initialized;
603
+ var provider, initPromise;
602
604
  var init_provider = __esm({
603
605
  "src/embedding/provider.ts"() {
604
606
  "use strict";
605
607
  init_esm_shims();
606
608
  provider = null;
607
- initialized = false;
609
+ initPromise = null;
608
610
  }
609
611
  });
610
612
 
@@ -4216,7 +4218,7 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir) {
4216
4218
  case "/projects": {
4217
4219
  try {
4218
4220
  const entries = await fs4.readdir(baseDir, { withFileTypes: true });
4219
- const projects = entries.filter((e) => e.isDirectory() && e.name.includes("--")).map((e) => {
4221
+ const projects = entries.filter((e) => e.isDirectory() && e.name.includes("--") && !e.name.startsWith("local--")).map((e) => {
4220
4222
  const dirName = e.name;
4221
4223
  const id = dirName.replace(/--/g, "/");
4222
4224
  return {
@@ -4260,13 +4262,12 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir) {
4260
4262
  const sorted = [...observations2].sort((a, b) => (b.id || 0) - (a.id || 0)).slice(0, 10);
4261
4263
  let embeddingStatus = { enabled: false, provider: "", dimensions: 0 };
4262
4264
  try {
4263
- const { isEmbeddingEnabled: isEmbeddingEnabled2 } = await Promise.resolve().then(() => (init_orama_store(), orama_store_exports));
4264
4265
  const { getEmbeddingProvider: getEmbeddingProvider2 } = await Promise.resolve().then(() => (init_provider(), provider_exports));
4265
- const provider2 = await getEmbeddingProvider2();
4266
+ const embProvider = await getEmbeddingProvider2();
4266
4267
  embeddingStatus = {
4267
- enabled: isEmbeddingEnabled2(),
4268
- provider: provider2?.name || "",
4269
- dimensions: provider2?.dimensions || 0
4268
+ enabled: embProvider !== null,
4269
+ provider: embProvider?.name || "",
4270
+ dimensions: embProvider?.dimensions || 0
4270
4271
  };
4271
4272
  } catch {
4272
4273
  }
@@ -4924,12 +4925,12 @@ Entity: ${entityName} | Type: ${type} | Project: ${project.id}${enrichment}`
4924
4925
  };
4925
4926
  }
4926
4927
  );
4927
- const RULE_SOURCES = ["cursor", "claude-code", "codex", "windsurf", "antigravity", "copilot"];
4928
+ const RULE_SOURCES = ["cursor", "claude-code", "codex", "windsurf", "antigravity", "copilot", "kiro"];
4928
4929
  server.registerTool(
4929
4930
  "memorix_rules_sync",
4930
4931
  {
4931
4932
  title: "Rules Sync",
4932
- description: "Scan project for agent rule files (Cursor, Claude Code, Codex, Windsurf, Antigravity, Copilot), deduplicate, detect conflicts, and optionally generate rules for a target agent format. Without target: returns sync status report. With target: generates converted rule files.",
4933
+ description: "Scan project for agent rule files (Cursor, Claude Code, Codex, Windsurf, Antigravity, Copilot, Kiro), deduplicate, detect conflicts, and optionally generate rules for a target agent format. Without target: returns sync status report. With target: generates converted rule files.",
4933
4934
  inputSchema: {
4934
4935
  action: z.enum(["status", "generate"]).describe('Action: "status" for report, "generate" to produce target files'),
4935
4936
  target: z.enum(RULE_SOURCES).optional().describe("Target agent format for generation (required when action=generate)")
@@ -4979,7 +4980,7 @@ Entity: ${entityName} | Type: ${type} | Project: ${project.id}${enrichment}`
4979
4980
  };
4980
4981
  }
4981
4982
  );
4982
- const AGENT_TARGETS = ["windsurf", "cursor", "claude-code", "codex", "copilot", "antigravity"];
4983
+ const AGENT_TARGETS = ["windsurf", "cursor", "claude-code", "codex", "copilot", "antigravity", "kiro"];
4983
4984
  server.registerTool(
4984
4985
  "memorix_workspace_sync",
4985
4986
  {
@@ -5237,7 +5238,23 @@ ${skill.content}` }]
5237
5238
  console.error("[memorix] Dashboard error:", err);
5238
5239
  dashboardRunning = false;
5239
5240
  });
5240
- await new Promise((resolve2) => setTimeout(resolve2, 800));
5241
+ const { createConnection } = await import("net");
5242
+ await new Promise((resolve2) => {
5243
+ const deadline = Date.now() + 5e3;
5244
+ const tryConnect = () => {
5245
+ const sock = createConnection(portNum, "127.0.0.1");
5246
+ sock.once("connect", () => {
5247
+ sock.destroy();
5248
+ resolve2();
5249
+ });
5250
+ sock.once("error", () => {
5251
+ sock.destroy();
5252
+ if (Date.now() < deadline) setTimeout(tryConnect, 100);
5253
+ else resolve2();
5254
+ });
5255
+ };
5256
+ tryConnect();
5257
+ });
5241
5258
  dashboardRunning = true;
5242
5259
  const { exec: execCmd } = await import("child_process");
5243
5260
  const openCmd = process.platform === "win32" ? `start "" "${url}"` : process.platform === "darwin" ? `open "${url}"` : `xdg-open "${url}"`;