@memorax/memorax-code 0.1.10 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -209,8 +209,11 @@ native plugin layout:
209
209
  └── skills/memorax-code/
210
210
  ```
211
211
 
212
- `CODEBUDDY_HOME` or `WORKBUDDY_HOME` overrides the default root. Windows uses
213
- `%USERPROFILE%\.codebuddy`; other platforms use `~/.workbuddy`. The Skill is
212
+ `CODEBUDDY_HOME` or `WORKBUDDY_HOME` overrides the default root. Windows prefers
213
+ `%USERPROFILE%\.workbuddy` and falls back to an existing `%USERPROFILE%\.codebuddy`
214
+ for legacy CodeBuddy installations. When both homes exist, setup removes only the
215
+ legacy MemoraX-managed plugin state from `.codebuddy`; other platforms use
216
+ `~/.workbuddy`. The Skill is
214
217
  materialized from the canonical MemoraX Code Skill and is owned by the managed
215
218
  marketplace plugin; user files outside that plugin are not modified.
216
219
 
@@ -268,8 +268,11 @@ memorax-code start --clients codebuddy
268
268
  memorax-code-codebuddy status --json
269
269
  ```
270
270
 
271
- On Windows, the managed plugin defaults to `%USERPROFILE%\.codebuddy`, while
272
- `CODEBUDDY_HOME` or `WORKBUDDY_HOME` remains an explicit override. A
271
+ On Windows, the managed plugin prefers `%USERPROFILE%\.workbuddy` and falls back
272
+ to an existing `%USERPROFILE%\.codebuddy` for legacy CodeBuddy installations,
273
+ while `CODEBUDDY_HOME` or `WORKBUDDY_HOME` remains an explicit override. If both
274
+ homes exist, setup removes only the MemoraX-managed plugin registration,
275
+ marketplace, and cache from `.codebuddy`; unrelated data remains untouched. A
273
276
  `codebuddyHooks.status` value of `unverified` means the files are configured but
274
277
  the current plugin version has not yet produced a real Hook event. Restart or
275
278
  refresh WorkBuddy, submit one prompt, and check status again. `observed` means
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memorax-code/backend",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "Local memory integration, lifecycle, trace, and diagnostics for MemoraX Code.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorax-code-claude-adapter",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "Memory skill and local hooks for MemoraX Code in Claude Code.",
5
5
  "author": {
6
6
  "name": "MemoraX Code Maintainers"
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "version": 1,
3
- "shellVersion": "0.1.10",
3
+ "shellVersion": "0.1.11",
4
4
  "runtimeAbi": 1
5
5
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memorax-code/claude-adapter",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "Claude Code Hook adapter for MemoraX Code memory services.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorax-code-claude-adapter",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "Memory skill and local hooks for MemoraX Code in Claude Code.",
5
5
  "author": {
6
6
  "name": "MemoraX Code Maintainers"
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "version": 1,
3
- "shellVersion": "0.1.10",
3
+ "shellVersion": "0.1.11",
4
4
  "runtimeAbi": 1
5
5
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memorax-code/claude-adapter",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "Claude Code Hook adapter for MemoraX Code memory services.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorax-code-codebuddy-adapter",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "MemoraX Code memory integration for CodeBuddy and WorkBuddy.",
5
5
  "hooks": "./hooks/hooks.json",
6
6
  "skills": ["./skills/memorax-code"]
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createHash } from "node:crypto";
3
+ import { existsSync } from "node:fs";
3
4
  import { appendFile, mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
4
5
  import { homedir } from "node:os";
5
6
  import { join } from "node:path";
@@ -40,7 +41,7 @@ const codeBuddyHome = commonStringValue(process.env.CODEBUDDY_HOME)
40
41
  ?? commonStringValue(packageMetadata.codeBuddyHome)
41
42
  ?? commonStringValue(input?.codebuddy_home)
42
43
  ?? commonStringValue(input?.codeBuddyHome)
43
- ?? join(homedir(), process.platform === "win32" ? ".codebuddy" : ".workbuddy");
44
+ ?? defaultCodeBuddyHome();
44
45
  try {
45
46
  await writeCodeBuddyRuntimeObservation({ memoraxCodeHome: home, codeBuddyHome, pluginRoot });
46
47
  } catch (error) {
@@ -239,6 +240,15 @@ async function bindMemoryCliTraceSession(sessionId) {
239
240
  function shellSingleQuote(value) { return `'${value.replaceAll("'", "'\"'\"'")}'`; }
240
241
  function stringValue(value) { return typeof value === "string" && value.trim() ? value.trim() : undefined; }
241
242
 
243
+ function defaultCodeBuddyHome() {
244
+ const workBuddyHome = join(homedir(), ".workbuddy");
245
+ if (process.platform !== "win32") return workBuddyHome;
246
+ const legacyCodeBuddyHome = join(homedir(), ".codebuddy");
247
+ return existsSync(workBuddyHome) || !existsSync(legacyCodeBuddyHome)
248
+ ? workBuddyHome
249
+ : legacyCodeBuddyHome;
250
+ }
251
+
242
252
  function provisionalTurnId(sessionId, boundary, prompt) {
243
253
  return `${sessionId}:${boundary}:${createHash("sha256").update(prompt.trim()).digest("hex")}`;
244
254
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memorax-code/codebuddy-adapter",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "CodeBuddy and WorkBuddy Hook adapter for MemoraX Code memory services.",
@@ -1,7 +1,7 @@
1
- import { readFileSync } from "node:fs";
1
+ import { existsSync, readFileSync } from "node:fs";
2
2
  import { chmod, cp, mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
3
3
  import { homedir } from "node:os";
4
- import { dirname, join, relative, sep, win32 } from "node:path";
4
+ import { basename, dirname, join, relative, sep, win32 } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { resolveHookCodeBuddyCommand } from "../../memorax-code-adapter-common/src/clients/codebuddy-command.mjs";
7
7
  import {
@@ -19,10 +19,20 @@ const PLUGIN_NAME = "memorax-code-codebuddy-adapter";
19
19
  const MARKETPLACE_NAME = "memorax-code-local";
20
20
  const PLUGIN_ID = `${PLUGIN_NAME}@${MARKETPLACE_NAME}`;
21
21
 
22
- export function defaultCodeBuddyHome(env = process.env, homeDir = homedir(), platform = process.platform) {
23
- return env.CODEBUDDY_HOME?.trim()
24
- || env.WORKBUDDY_HOME?.trim()
25
- || (platform === "win32" ? win32.join(homeDir, ".codebuddy") : join(homeDir, ".workbuddy"));
22
+ export function defaultCodeBuddyHome(
23
+ env = process.env,
24
+ homeDir = homedir(),
25
+ platform = process.platform,
26
+ pathExists = existsSync,
27
+ ) {
28
+ const configured = env.CODEBUDDY_HOME?.trim() || env.WORKBUDDY_HOME?.trim();
29
+ if (configured) return configured;
30
+ if (platform !== "win32") return join(homeDir, ".workbuddy");
31
+ const workBuddyHome = win32.join(homeDir, ".workbuddy");
32
+ const legacyCodeBuddyHome = win32.join(homeDir, ".codebuddy");
33
+ return pathExists(workBuddyHome) || !pathExists(legacyCodeBuddyHome)
34
+ ? workBuddyHome
35
+ : legacyCodeBuddyHome;
26
36
  }
27
37
  // CodeBuddy stores installed plugin caches under the marketplace namespace.
28
38
  export function codeBuddyInstallPath(home = defaultCodeBuddyHome()) { return join(home, "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME, VERSION); }
@@ -61,20 +71,21 @@ export async function enableCodeBuddyAdapter(options = {}) {
61
71
  settings.enabledPlugins[PLUGIN_ID] = true;
62
72
  });
63
73
  await updateLegacyRegistry(home, { installPath, enabled: true });
74
+ await removeLegacyManagedInstallation(home, platform);
64
75
  return { ok: true, action: "enable", runtime: "codebuddy", integration: "hooks", installed: true, enabled: true, codeBuddyHome: home, installPath, marketplace: MARKETPLACE_NAME, pluginId: PLUGIN_ID, marketplacePath: localPluginPath, codebuddyHooks: { ok: true, configured: true, runtimeObserved: false, status: "unverified" }, codebuddySkills: { ok: true, status: "installed", managed: true, memoraxCode: true, path: join(localPluginPath, "skills", "memorax-code", "SKILL.md") } };
65
76
  }
66
77
 
67
78
  export async function disableCodeBuddyAdapter(options = {}) {
68
79
  const home = options.codeBuddyHome ?? defaultCodeBuddyHome();
80
+ const platform = options.platform ?? process.platform;
69
81
  const registryPath = installedRegistryPath(home);
70
- const installed = await pathExists(marketplacePluginPath(home)) || await pathExists(codeBuddyInstallPath(home));
71
- if (!installed) return { ok: true, action: "disable", runtime: "codebuddy", installed: false, enabled: false, codeBuddyHome: home, statePath: registryPath, marketplace: MARKETPLACE_NAME, pluginId: PLUGIN_ID };
72
- await updateSettings(home, (settings) => {
73
- settings.enabledPlugins = recordValue(settings.enabledPlugins);
74
- settings.enabledPlugins[PLUGIN_ID] = false;
75
- });
76
- await updateLegacyRegistry(home, { installPath: codeBuddyInstallPath(home), enabled: false });
77
- return { ok: true, action: "disable", runtime: "codebuddy", installed: true, enabled: false, codeBuddyHome: home, statePath: registryPath, marketplace: MARKETPLACE_NAME, pluginId: PLUGIN_ID };
82
+ const legacyHome = legacyCodeBuddyHome(home, platform);
83
+ const installed = await managedCodeBuddyInstallationExists(home);
84
+ const legacyInstalled = legacyHome ? await managedCodeBuddyInstallationExists(legacyHome) : false;
85
+ if (!installed && !legacyInstalled) return { ok: true, action: "disable", runtime: "codebuddy", installed: false, enabled: false, codeBuddyHome: home, statePath: registryPath, marketplace: MARKETPLACE_NAME, pluginId: PLUGIN_ID };
86
+ if (installed) await disableManagedCodeBuddyInstallation(home);
87
+ if (legacyInstalled) await disableManagedCodeBuddyInstallation(legacyHome);
88
+ return { ok: true, action: "disable", runtime: "codebuddy", installed: true, enabled: false, codeBuddyHome: home, statePath: registryPath, marketplace: MARKETPLACE_NAME, pluginId: PLUGIN_ID, legacyCodeBuddyHome: legacyInstalled ? legacyHome : undefined, legacyManaged: legacyInstalled };
78
89
  }
79
90
 
80
91
  export async function readCodeBuddyAdapterStatus(options = {}) {
@@ -94,28 +105,73 @@ export async function readCodeBuddyAdapterStatus(options = {}) {
94
105
  const skillInstalled = await pathExists(skillPath);
95
106
  const enabled = settings.enabledPlugins?.[PLUGIN_ID] === true;
96
107
  const marketplaceReady = Boolean(known[MARKETPLACE_NAME]);
108
+ const legacyHome = legacyCodeBuddyHome(home, platform);
109
+ const legacyManaged = legacyHome ? await managedCodeBuddyInstallationExists(legacyHome) : false;
97
110
  const hookConfigured = installedRoots.length > 0
98
111
  && (await Promise.all(installedRoots.map((root) => codeBuddyHookManifestConfigured(root, platform)))).every(Boolean);
99
112
  const observation = await readCodeBuddyRuntimeObservation(memoraxCodeHome);
100
113
  const runtimeObserved = hookConfigured && observationMatches(observation, home, platform);
101
- return { ok: true, action: "status", runtime: "codebuddy", integration: "hooks", installed, enabled, managed: installed && marketplaceReady, codeBuddyHome: home, installPath, marketplace: MARKETPLACE_NAME, pluginId: PLUGIN_ID, marketplaceReady, codebuddyHooks: { ok: hookConfigured, configured: hookConfigured, runtimeObserved, status: hookConfigured ? (runtimeObserved ? "observed" : "unverified") : "invalid", observationPath: codeBuddyRuntimeObservationPath(memoraxCodeHome) }, codebuddySkills: { ok: skillInstalled, status: skillInstalled ? "installed" : "missing", managed: skillInstalled, memoraxCode: skillInstalled, path: skillPath } };
114
+ return { ok: true, action: "status", runtime: "codebuddy", integration: "hooks", installed, enabled, managed: installed && marketplaceReady, codeBuddyHome: home, installPath, marketplace: MARKETPLACE_NAME, pluginId: PLUGIN_ID, marketplaceReady, legacyCodeBuddyHome: legacyManaged ? legacyHome : undefined, legacyManaged, codebuddyHooks: { ok: hookConfigured, configured: hookConfigured, runtimeObserved, status: hookConfigured ? (runtimeObserved ? "observed" : "unverified") : "invalid", observationPath: codeBuddyRuntimeObservationPath(memoraxCodeHome) }, codebuddySkills: { ok: skillInstalled, status: skillInstalled ? "installed" : "missing", managed: skillInstalled, memoraxCode: skillInstalled, path: skillPath } };
102
115
  }
103
116
 
104
117
  export async function removeCodeBuddyPluginInstallation(options = {}) {
105
118
  const home = options.codeBuddyHome ?? defaultCodeBuddyHome();
106
- const installed = await pathExists(marketplacePluginPath(home)) || await pathExists(codeBuddyInstallPath(home));
107
- if (!installed) return { ok: true, action: "codebuddy-plugin-remove", runtime: "codebuddy", installed: false, enabled: false, removed: false, codeBuddyHome: home, marketplace: MARKETPLACE_NAME, pluginId: PLUGIN_ID };
108
- const status = await disableCodeBuddyAdapter({ codeBuddyHome: home });
119
+ const platform = options.platform ?? process.platform;
120
+ const legacyHome = legacyCodeBuddyHome(home, platform);
121
+ const removed = await removeManagedCodeBuddyInstallation(home);
122
+ const legacyRemoved = legacyHome ? await removeManagedCodeBuddyInstallation(legacyHome) : false;
123
+ return { ok: true, action: "codebuddy-plugin-remove", runtime: "codebuddy", installed: false, enabled: false, removed: removed || legacyRemoved, codeBuddyHome: home, statePath: installedRegistryPath(home), marketplace: MARKETPLACE_NAME, pluginId: PLUGIN_ID };
124
+ }
125
+
126
+ async function disableManagedCodeBuddyInstallation(home) {
109
127
  await updateSettings(home, (settings) => {
128
+ settings.enabledPlugins = recordValue(settings.enabledPlugins);
129
+ settings.enabledPlugins[PLUGIN_ID] = false;
130
+ });
131
+ await updateLegacyRegistry(home, { installPath: codeBuddyInstallPath(home), enabled: false });
132
+ }
133
+
134
+ async function removeLegacyManagedInstallation(home, platform) {
135
+ const legacyHome = legacyCodeBuddyHome(home, platform);
136
+ return legacyHome ? await removeManagedCodeBuddyInstallation(legacyHome) : false;
137
+ }
138
+
139
+ async function removeManagedCodeBuddyInstallation(home) {
140
+ if (!await managedCodeBuddyInstallationExists(home)) return false;
141
+ await updateJsonRecordIfPresent(codeBuddySettingsPath(home), (settings) => {
110
142
  settings.enabledPlugins = recordValue(settings.enabledPlugins);
111
143
  delete settings.enabledPlugins[PLUGIN_ID];
112
144
  });
113
- await updateKnownMarketplace(home, false);
114
- await updateRegistry(home, (registry) => { delete registry[PLUGIN_ID]; });
115
- await rm(codeBuddyInstallPath(home), { recursive: true, force: true });
116
- await rm(legacyCodeBuddyInstallPath(home), { recursive: true, force: true });
145
+ await updateJsonRecordIfPresent(knownMarketplacesPath(home), (known) => {
146
+ delete known[MARKETPLACE_NAME];
147
+ });
148
+ await updateJsonRecordIfPresent(installedRegistryPath(home), (value) => {
149
+ value.version = 2;
150
+ value.plugins = recordValue(value.plugins);
151
+ delete value.plugins[PLUGIN_ID];
152
+ });
153
+ await rm(codeBuddyPluginCacheRoot(home), { recursive: true, force: true });
154
+ await rm(legacyCodeBuddyPluginCacheRoot(home), { recursive: true, force: true });
117
155
  await rm(marketplaceRoot(home), { recursive: true, force: true });
118
- return { ...status, action: "codebuddy-plugin-remove", installed: false, enabled: false, removed: true };
156
+ return true;
157
+ }
158
+
159
+ async function managedCodeBuddyInstallationExists(home) {
160
+ if (await pathExists(marketplaceRoot(home))
161
+ || await pathExists(codeBuddyPluginCacheRoot(home))
162
+ || await pathExists(legacyCodeBuddyPluginCacheRoot(home))) return true;
163
+ const settings = await readJsonRecord(codeBuddySettingsPath(home));
164
+ const known = await readJsonRecord(knownMarketplacesPath(home));
165
+ const registry = await readJsonRecord(installedRegistryPath(home));
166
+ return Object.hasOwn(recordValue(settings.enabledPlugins), PLUGIN_ID)
167
+ || Object.hasOwn(known, MARKETPLACE_NAME)
168
+ || Object.hasOwn(recordValue(registry.plugins), PLUGIN_ID);
169
+ }
170
+
171
+ function legacyCodeBuddyHome(home, platform) {
172
+ return platform === "win32" && basename(home).toLowerCase() === ".workbuddy"
173
+ ? join(dirname(home), ".codebuddy")
174
+ : undefined;
119
175
  }
120
176
 
121
177
  async function readRegistry(home) {
@@ -196,6 +252,11 @@ async function updateJsonRecord(path, mutate) {
196
252
  await rm(lockPath, { force: true });
197
253
  }
198
254
  }
255
+
256
+ async function updateJsonRecordIfPresent(path, mutate) {
257
+ if (await pathExists(path)) await updateJsonRecord(path, mutate);
258
+ }
259
+
199
260
  async function readJsonRecord(path) {
200
261
  try {
201
262
  const value = JSON.parse(await readFile(path, "utf8"));
@@ -225,6 +286,8 @@ function readPluginVersion() {
225
286
  return manifest.version.trim();
226
287
  }
227
288
  function legacyCodeBuddyInstallPath(home) { return join(home, "plugins", "cache", PLUGIN_NAME, VERSION); }
289
+ function codeBuddyPluginCacheRoot(home) { return dirname(codeBuddyInstallPath(home)); }
290
+ function legacyCodeBuddyPluginCacheRoot(home) { return dirname(legacyCodeBuddyInstallPath(home)); }
228
291
 
229
292
  async function materializeCanonicalSkill(destination) {
230
293
  const packagedSkill = join(ROOT, "skills", "memorax-code");
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorax-code-codex-adapter",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "Codex adapter, memory skill, and local hooks for MemoraX Code.",
5
5
  "author": {
6
6
  "name": "MemoraX AI"
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "version": 1,
3
- "shellVersion": "0.1.10",
3
+ "shellVersion": "0.1.11",
4
4
  "runtimeAbi": 1
5
5
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memorax-code/codex-adapter",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "Codex Hook and memory integration for MemoraX Code.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memorax-code/dsh-memorax-code",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "DeepSeek Harness native memory adapter for MemoraX Code.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memorax-code/opencode-adapter",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "OpenCode plugin adapter for MemoraX Code memory services.",
@@ -1,3 +1,4 @@
1
+ import { existsSync } from "node:fs";
1
2
  import { homedir } from "node:os";
2
3
  import { delimiter, join, win32 } from "node:path";
3
4
  import {
@@ -80,10 +81,20 @@ export function ensureCodeBuddyCommandEnv(options = {}) {
80
81
  return resolved;
81
82
  }
82
83
 
83
- export function defaultCodeBuddyHome(env = process.env, homeDir = homedir(), platform = process.platform) {
84
- return nonEmpty(env.CODEBUDDY_HOME)
85
- ?? nonEmpty(env.WORKBUDDY_HOME)
86
- ?? (platform === "win32" ? win32.join(homeDir, ".codebuddy") : join(homeDir, ".workbuddy"));
84
+ export function defaultCodeBuddyHome(
85
+ env = process.env,
86
+ homeDir = homedir(),
87
+ platform = process.platform,
88
+ pathExists = existsSync,
89
+ ) {
90
+ const configured = nonEmpty(env.CODEBUDDY_HOME) ?? nonEmpty(env.WORKBUDDY_HOME);
91
+ if (configured) return configured;
92
+ if (platform !== "win32") return join(homeDir, ".workbuddy");
93
+ const workBuddyHome = win32.join(homeDir, ".workbuddy");
94
+ const legacyCodeBuddyHome = win32.join(homeDir, ".codebuddy");
95
+ return pathExists(workBuddyHome) || !pathExists(legacyCodeBuddyHome)
96
+ ? workBuddyHome
97
+ : legacyCodeBuddyHome;
87
98
  }
88
99
 
89
100
  function defaultWindowsRoots(env, homeDir) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memorax/memorax-code",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "Persistent coding memory for Codex, Claude Code, CodeBuddy/WorkBuddy, DeepSeek Harness, and OpenCode.",
5
5
  "license": "MIT",
6
6
  "type": "module",