@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.
- package/docs/configuration.md +5 -2
- package/docs/troubleshooting.md +5 -2
- package/lib/memorax-code-backend/package.json +1 -1
- package/lib/memorax-code-claude-adapter/.claude-plugin/plugin.json +1 -1
- package/lib/memorax-code-claude-adapter/hooks/runtime-shell.json +1 -1
- package/lib/memorax-code-claude-adapter/package.json +1 -1
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/.claude-plugin/plugin.json +1 -1
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/hooks/runtime-shell.json +1 -1
- package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/package.json +1 -1
- package/lib/memorax-code-codebuddy-adapter/.codebuddy-plugin/plugin.json +1 -1
- package/lib/memorax-code-codebuddy-adapter/hooks/runtime-hook.mjs +11 -1
- package/lib/memorax-code-codebuddy-adapter/package.json +1 -1
- package/lib/memorax-code-codebuddy-adapter/src/config.mjs +86 -23
- package/lib/memorax-code-codex-adapter/.codex-plugin/plugin.json +1 -1
- package/lib/memorax-code-codex-adapter/hooks/runtime-shell.json +1 -1
- package/lib/memorax-code-codex-adapter/package.json +1 -1
- package/lib/memorax-code-dsh-adapter/package.json +1 -1
- package/lib/memorax-code-opencode-adapter/package.json +1 -1
- package/lib/resolve-codebuddy-command.mjs +15 -4
- package/package.json +1 -1
package/docs/configuration.md
CHANGED
|
@@ -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
|
|
213
|
-
`%USERPROFILE%\.
|
|
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
|
|
package/docs/troubleshooting.md
CHANGED
|
@@ -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
|
|
272
|
-
|
|
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,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
|
-
??
|
|
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,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(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
|
71
|
-
|
|
72
|
-
await
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
|
107
|
-
|
|
108
|
-
const
|
|
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
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
await
|
|
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
|
|
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,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(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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