rol-websocket-channel 1.6.3 → 1.6.4

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/dist/index.js CHANGED
@@ -530,6 +530,12 @@ export async function handleCustomMessageType(msgType, innerData, traceId, accou
530
530
  response.data = methodResult.result;
531
531
  if (!methodResult.ok) {
532
532
  response.error = methodResult.error?.message || "Unknown error";
533
+ if (methodResult.error?.code !== undefined) {
534
+ response.error_code = methodResult.error.code;
535
+ }
536
+ if (methodResult.error?.data !== undefined) {
537
+ response.error_data = methodResult.error.data;
538
+ }
533
539
  if (isSkillInstallFlow) {
534
540
  console.error(`[rol-websocket-channel] custom message failed: type=${msgType}, traceId=${traceId}, slug=${innerData?.slug ?? ""}, error=${response.error}, detail=${JSON.stringify(methodResult.error?.data ?? {})}`);
535
541
  }
@@ -34,7 +34,7 @@ function resolveOpenClawBin() {
34
34
  export async function installMem9(context) {
35
35
  const config = await ensureOpenClawConfigExists(context.openclawRoot);
36
36
  const currentState = readMem9State(config);
37
- const currentEntrypoint = await findMem9RuntimeEntrypoint(context.openclawRoot);
37
+ const currentEntrypoint = await findMem9RuntimeEntrypoint(context.openclawRoot, config);
38
38
  // Phase A: Plugin not installed → install only, then restart
39
39
  if (!currentState.installed && !currentEntrypoint) {
40
40
  await ensureOpenClawCli();
@@ -52,7 +52,7 @@ export async function installMem9(context) {
52
52
  }
53
53
  // Phase B: Installed but no key → create key, write config, restart
54
54
  if (!currentState.configured || !currentState.apiKey) {
55
- const runtimeEntrypoint = await ensureMem9RuntimeEntrypoint(context.openclawRoot);
55
+ const runtimeEntrypoint = await ensureMem9RuntimeEntrypoint(context.openclawRoot, config);
56
56
  const apiKey = await createMem9Key();
57
57
  const updated = await writeMem9Config(context.openclawRoot, apiKey);
58
58
  const restart = await restartGateway(context.projectRoot);
@@ -73,7 +73,7 @@ export async function installMem9(context) {
73
73
  };
74
74
  }
75
75
  // Phase C: Already configured → ensure slot/hooks/allow are correct
76
- const runtimeEntrypoint = await ensureMem9RuntimeEntrypoint(context.openclawRoot);
76
+ const runtimeEntrypoint = await ensureMem9RuntimeEntrypoint(context.openclawRoot, config);
77
77
  const updated = await ensureMem9SlotConfig(context.openclawRoot, currentState.apiKey);
78
78
  const restart = await restartGateway(context.projectRoot);
79
79
  return {
@@ -102,7 +102,7 @@ export async function reconnectMem9(key, context) {
102
102
  }
103
103
  const config = await ensureOpenClawConfigExists(context.openclawRoot);
104
104
  const previousState = readMem9State(config);
105
- const runtimeEntrypoint = await ensureMem9RuntimeEntrypoint(context.openclawRoot);
105
+ const runtimeEntrypoint = await ensureMem9RuntimeEntrypoint(context.openclawRoot, config);
106
106
  const updated = await writeMem9Config(context.openclawRoot, apiKey);
107
107
  const restart = await restartGateway(context.projectRoot);
108
108
  return {
@@ -178,8 +178,8 @@ async function installMem9Plugin(cwd) {
178
178
  });
179
179
  }
180
180
  }
181
- export async function findMem9RuntimeEntrypoint(openclawRoot) {
182
- for (const packageRoot of MEM9_PACKAGE_ROOTS.map((item) => path.join(openclawRoot, item))) {
181
+ export async function findMem9RuntimeEntrypoint(openclawRoot, config) {
182
+ for (const packageRoot of resolveMem9RuntimePackageRoots(openclawRoot, config)) {
183
183
  for (const entrypoint of RUNTIME_ENTRYPOINTS.map((item) => path.join(packageRoot, item))) {
184
184
  if (await pathExists(entrypoint)) {
185
185
  return entrypoint;
@@ -188,17 +188,34 @@ export async function findMem9RuntimeEntrypoint(openclawRoot) {
188
188
  }
189
189
  return null;
190
190
  }
191
- async function ensureMem9RuntimeEntrypoint(openclawRoot) {
192
- const entrypoint = await findMem9RuntimeEntrypoint(openclawRoot);
191
+ async function ensureMem9RuntimeEntrypoint(openclawRoot, config) {
192
+ const entrypoint = await findMem9RuntimeEntrypoint(openclawRoot, config);
193
193
  if (entrypoint) {
194
194
  return entrypoint;
195
195
  }
196
+ const installRecord = readMem9InstallRecord(config);
197
+ const checkedPackageRoots = resolveMem9RuntimePackageRoots(openclawRoot, config);
196
198
  throw new JsonRpcException(JSON_RPC_ERRORS.internalError, 'mem9 plugin is installed but missing compiled runtime output', {
197
199
  code: 'MEM9_RUNTIME_OUTPUT_MISSING',
198
200
  expected: RUNTIME_ENTRYPOINTS.map((item) => `./${item.replace(/\\/g, '/')}`),
199
- packageRoots: MEM9_PACKAGE_ROOTS.map((item) => path.join(openclawRoot, item))
201
+ checkedPackageRoots,
202
+ checkedEntrypoints: checkedPackageRoots.flatMap((packageRoot) => RUNTIME_ENTRYPOINTS.map((item) => path.join(packageRoot, item))),
203
+ installRecord
200
204
  });
201
205
  }
206
+ function resolveMem9RuntimePackageRoots(openclawRoot, config) {
207
+ const roots = [];
208
+ const installPath = pickString(readMem9InstallRecord(config)?.installPath);
209
+ if (installPath) {
210
+ roots.push(path.isAbsolute(installPath) ? installPath : path.resolve(openclawRoot, installPath));
211
+ }
212
+ for (const fallbackRoot of MEM9_PACKAGE_ROOTS.map((item) => path.join(openclawRoot, item))) {
213
+ if (!roots.includes(fallbackRoot)) {
214
+ roots.push(fallbackRoot);
215
+ }
216
+ }
217
+ return roots;
218
+ }
202
219
  async function createMem9Key() {
203
220
  let response;
204
221
  try {
@@ -368,6 +385,10 @@ function pickString(value) {
368
385
  function isRecord(value) {
369
386
  return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
370
387
  }
388
+ function readMem9InstallRecord(config) {
389
+ const record = config?.plugins?.installs?.[MEM9_PLUGIN_ID];
390
+ return isRecord(record) ? record : null;
391
+ }
371
392
  function readMem9State(config) {
372
393
  const installed = Boolean((config.plugins?.installs && typeof config.plugins.installs === 'object' && MEM9_PLUGIN_ID in config.plugins.installs)
373
394
  || (config.plugins?.entries && typeof config.plugins.entries === 'object' && MEM9_PLUGIN_ID in config.plugins.entries));
package/index.ts CHANGED
@@ -681,6 +681,12 @@ export async function handleCustomMessageType(
681
681
  response.data = methodResult.result;
682
682
  if (!methodResult.ok) {
683
683
  response.error = methodResult.error?.message || "Unknown error";
684
+ if (methodResult.error?.code !== undefined) {
685
+ response.error_code = methodResult.error.code;
686
+ }
687
+ if (methodResult.error?.data !== undefined) {
688
+ response.error_data = methodResult.error.data;
689
+ }
684
690
  if (isSkillInstallFlow) {
685
691
  console.error(
686
692
  `[rol-websocket-channel] custom message failed: type=${msgType}, traceId=${traceId}, slug=${innerData?.slug ?? ""}, error=${response.error}, detail=${JSON.stringify(methodResult.error?.data ?? {})}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rol-websocket-channel",
3
- "version": "1.6.3",
3
+ "version": "1.6.4",
4
4
  "description": "Unified OpenClaw plugin: MQTT Channel + Admin Bridge for remote management",
5
5
  "license": "MIT",
6
6
  "author": "nixgnehc",
@@ -53,7 +53,7 @@ function resolveOpenClawBin(): string {
53
53
  export async function installMem9(context: MethodContext): Promise<JsonValue> {
54
54
  const config = await ensureOpenClawConfigExists(context.openclawRoot);
55
55
  const currentState = readMem9State(config);
56
- const currentEntrypoint = await findMem9RuntimeEntrypoint(context.openclawRoot);
56
+ const currentEntrypoint = await findMem9RuntimeEntrypoint(context.openclawRoot, config);
57
57
 
58
58
  // Phase A: Plugin not installed → install only, then restart
59
59
  if (!currentState.installed && !currentEntrypoint) {
@@ -74,7 +74,7 @@ export async function installMem9(context: MethodContext): Promise<JsonValue> {
74
74
 
75
75
  // Phase B: Installed but no key → create key, write config, restart
76
76
  if (!currentState.configured || !currentState.apiKey) {
77
- const runtimeEntrypoint = await ensureMem9RuntimeEntrypoint(context.openclawRoot);
77
+ const runtimeEntrypoint = await ensureMem9RuntimeEntrypoint(context.openclawRoot, config);
78
78
  const apiKey = await createMem9Key();
79
79
  const updated = await writeMem9Config(context.openclawRoot, apiKey);
80
80
  const restart = await restartGateway(context.projectRoot);
@@ -97,7 +97,7 @@ export async function installMem9(context: MethodContext): Promise<JsonValue> {
97
97
  }
98
98
 
99
99
  // Phase C: Already configured → ensure slot/hooks/allow are correct
100
- const runtimeEntrypoint = await ensureMem9RuntimeEntrypoint(context.openclawRoot);
100
+ const runtimeEntrypoint = await ensureMem9RuntimeEntrypoint(context.openclawRoot, config);
101
101
  const updated = await ensureMem9SlotConfig(context.openclawRoot, currentState.apiKey!);
102
102
  const restart = await restartGateway(context.projectRoot);
103
103
 
@@ -130,7 +130,7 @@ export async function reconnectMem9(key: string, context: MethodContext): Promis
130
130
 
131
131
  const config = await ensureOpenClawConfigExists(context.openclawRoot);
132
132
  const previousState = readMem9State(config);
133
- const runtimeEntrypoint = await ensureMem9RuntimeEntrypoint(context.openclawRoot);
133
+ const runtimeEntrypoint = await ensureMem9RuntimeEntrypoint(context.openclawRoot, config);
134
134
  const updated = await writeMem9Config(context.openclawRoot, apiKey);
135
135
  const restart = await restartGateway(context.projectRoot);
136
136
 
@@ -225,8 +225,8 @@ async function installMem9Plugin(cwd: string): Promise<void> {
225
225
  }
226
226
  }
227
227
 
228
- export async function findMem9RuntimeEntrypoint(openclawRoot: string): Promise<string | null> {
229
- for (const packageRoot of MEM9_PACKAGE_ROOTS.map((item) => path.join(openclawRoot, item))) {
228
+ export async function findMem9RuntimeEntrypoint(openclawRoot: string, config?: OpenClawConfig): Promise<string | null> {
229
+ for (const packageRoot of resolveMem9RuntimePackageRoots(openclawRoot, config)) {
230
230
  for (const entrypoint of RUNTIME_ENTRYPOINTS.map((item) => path.join(packageRoot, item))) {
231
231
  if (await pathExists(entrypoint)) {
232
232
  return entrypoint;
@@ -236,22 +236,40 @@ export async function findMem9RuntimeEntrypoint(openclawRoot: string): Promise<s
236
236
  return null;
237
237
  }
238
238
 
239
- async function ensureMem9RuntimeEntrypoint(openclawRoot: string): Promise<string> {
240
- const entrypoint = await findMem9RuntimeEntrypoint(openclawRoot);
239
+ async function ensureMem9RuntimeEntrypoint(openclawRoot: string, config?: OpenClawConfig): Promise<string> {
240
+ const entrypoint = await findMem9RuntimeEntrypoint(openclawRoot, config);
241
241
  if (entrypoint) {
242
242
  return entrypoint;
243
243
  }
244
+ const installRecord = readMem9InstallRecord(config);
245
+ const checkedPackageRoots = resolveMem9RuntimePackageRoots(openclawRoot, config);
244
246
  throw new JsonRpcException(
245
247
  JSON_RPC_ERRORS.internalError,
246
248
  'mem9 plugin is installed but missing compiled runtime output',
247
249
  {
248
250
  code: 'MEM9_RUNTIME_OUTPUT_MISSING',
249
251
  expected: RUNTIME_ENTRYPOINTS.map((item) => `./${item.replace(/\\/g, '/')}`),
250
- packageRoots: MEM9_PACKAGE_ROOTS.map((item) => path.join(openclawRoot, item))
252
+ checkedPackageRoots,
253
+ checkedEntrypoints: checkedPackageRoots.flatMap((packageRoot) => RUNTIME_ENTRYPOINTS.map((item) => path.join(packageRoot, item))),
254
+ installRecord
251
255
  }
252
256
  );
253
257
  }
254
258
 
259
+ function resolveMem9RuntimePackageRoots(openclawRoot: string, config?: OpenClawConfig): string[] {
260
+ const roots: string[] = [];
261
+ const installPath = pickString(readMem9InstallRecord(config)?.installPath);
262
+ if (installPath) {
263
+ roots.push(path.isAbsolute(installPath) ? installPath : path.resolve(openclawRoot, installPath));
264
+ }
265
+ for (const fallbackRoot of MEM9_PACKAGE_ROOTS.map((item) => path.join(openclawRoot, item))) {
266
+ if (!roots.includes(fallbackRoot)) {
267
+ roots.push(fallbackRoot);
268
+ }
269
+ }
270
+ return roots;
271
+ }
272
+
255
273
  async function createMem9Key(): Promise<string> {
256
274
  let response: Response;
257
275
  try {
@@ -447,6 +465,11 @@ function isRecord(value: unknown): value is Record<string, any> {
447
465
  return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
448
466
  }
449
467
 
468
+ function readMem9InstallRecord(config?: OpenClawConfig): Record<string, any> | null {
469
+ const record = config?.plugins?.installs?.[MEM9_PLUGIN_ID];
470
+ return isRecord(record) ? record : null;
471
+ }
472
+
450
473
  function readMem9State(config: OpenClawConfig): {
451
474
  installed: boolean;
452
475
  configured: boolean;