rol-websocket-channel 1.5.1 → 1.5.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/dist/index.js CHANGED
@@ -12,6 +12,21 @@ let pluginRuntime = null;
12
12
  export function getPluginRuntime() {
13
13
  return pluginRuntime;
14
14
  }
15
+ export function formatCliErrorPayload(error) {
16
+ const data = error?.data;
17
+ const dataObject = data && typeof data === "object" && !Array.isArray(data)
18
+ ? data
19
+ : {};
20
+ const code = dataObject.code ?? error?.code;
21
+ return {
22
+ ok: false,
23
+ error: {
24
+ message: error instanceof Error ? error.message : String(error),
25
+ ...dataObject,
26
+ ...(code === undefined ? {} : { code }),
27
+ },
28
+ };
29
+ }
15
30
  // ============================================
16
31
  // 4. 插件主体定义
17
32
  // ============================================
@@ -554,13 +569,7 @@ function registerAdminBridgeCli(api) {
554
569
  }
555
570
  catch (error) {
556
571
  process.exitCode = 1;
557
- process.stderr.write(JSON.stringify({
558
- ok: false,
559
- error: {
560
- message: error instanceof Error ? error.message : String(error),
561
- code: error?.data?.code,
562
- },
563
- }, null, 2) + "\n");
572
+ process.stderr.write(JSON.stringify(formatCliErrorPayload(error), null, 2) + "\n");
564
573
  }
565
574
  });
566
575
  const mem9 = root
@@ -1,7 +1,7 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { readFileSync } from 'node:fs';
3
3
  import test from 'node:test';
4
- import register from '../../index.js';
4
+ import register, { formatCliErrorPayload } from '../../index.js';
5
5
  const manifest = JSON.parse(readFileSync(new URL('../../openclaw.plugin.json', import.meta.url), 'utf8'));
6
6
  test('manifest declares OpenClaw 2026 command ownership for admin bridge CLI', () => {
7
7
  assert.deepEqual(manifest.activation?.onCommands, ['admin-bridge', 'rol-websocket-channel']);
@@ -60,3 +60,26 @@ test('runtime CLI registrar exposes admin-bridge and rol-websocket-channel comma
60
60
  assert.equal(commands[0], 'admin-bridge');
61
61
  assert.equal(aliases[0], 'rol-websocket-channel');
62
62
  });
63
+ test('CLI error formatter preserves diagnostic data for pairing failures', () => {
64
+ const error = new Error('mqttUrl is missing from pairing payload');
65
+ error.data = {
66
+ code: 'PAIR_CHANNEL_CONFIG_INVALID',
67
+ debug: {
68
+ rootKeys: ['channel'],
69
+ channelConfigKeys: ['mqtt_topic'],
70
+ hasExistingMqttUrl: false
71
+ }
72
+ };
73
+ assert.deepEqual(formatCliErrorPayload(error), {
74
+ ok: false,
75
+ error: {
76
+ message: 'mqttUrl is missing from pairing payload',
77
+ code: 'PAIR_CHANNEL_CONFIG_INVALID',
78
+ debug: {
79
+ rootKeys: ['channel'],
80
+ channelConfigKeys: ['mqtt_topic'],
81
+ hasExistingMqttUrl: false
82
+ }
83
+ }
84
+ });
85
+ });
package/index.ts CHANGED
@@ -38,6 +38,28 @@ export function getPluginRuntime(): any {
38
38
  return pluginRuntime;
39
39
  }
40
40
 
41
+ export function formatCliErrorPayload(error: unknown): {
42
+ ok: false;
43
+ error: Record<string, unknown>;
44
+ } {
45
+ const data = (error as { data?: unknown } | null | undefined)?.data;
46
+ const dataObject =
47
+ data && typeof data === "object" && !Array.isArray(data)
48
+ ? (data as Record<string, unknown>)
49
+ : {};
50
+ const code =
51
+ dataObject.code ?? (error as { code?: unknown } | null | undefined)?.code;
52
+
53
+ return {
54
+ ok: false,
55
+ error: {
56
+ message: error instanceof Error ? error.message : String(error),
57
+ ...dataObject,
58
+ ...(code === undefined ? {} : { code }),
59
+ },
60
+ };
61
+ }
62
+
41
63
  // ============================================
42
64
  // 4. 插件主体定义
43
65
  // ============================================
@@ -725,18 +747,7 @@ function registerAdminBridgeCli(api: any) {
725
747
  } catch (error) {
726
748
  process.exitCode = 1;
727
749
  process.stderr.write(
728
- JSON.stringify(
729
- {
730
- ok: false,
731
- error: {
732
- message:
733
- error instanceof Error ? error.message : String(error),
734
- code: (error as any)?.data?.code,
735
- },
736
- },
737
- null,
738
- 2,
739
- ) + "\n",
750
+ JSON.stringify(formatCliErrorPayload(error), null, 2) + "\n",
740
751
  );
741
752
  }
742
753
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rol-websocket-channel",
3
- "version": "1.5.1",
3
+ "version": "1.5.2",
4
4
  "description": "Unified OpenClaw plugin: MQTT Channel + Admin Bridge for remote management",
5
5
  "license": "MIT",
6
6
  "author": "nixgnehc",
@@ -1,7 +1,7 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { readFileSync } from 'node:fs';
3
3
  import test from 'node:test';
4
- import register from '../../index.js';
4
+ import register, { formatCliErrorPayload } from '../../index.js';
5
5
 
6
6
  const manifest = JSON.parse(readFileSync(new URL('../../openclaw.plugin.json', import.meta.url), 'utf8'));
7
7
 
@@ -65,3 +65,30 @@ test('runtime CLI registrar exposes admin-bridge and rol-websocket-channel comma
65
65
  assert.equal(commands[0], 'admin-bridge');
66
66
  assert.equal(aliases[0], 'rol-websocket-channel');
67
67
  });
68
+
69
+ test('CLI error formatter preserves diagnostic data for pairing failures', () => {
70
+ const error = new Error('mqttUrl is missing from pairing payload') as Error & {
71
+ data: Record<string, unknown>;
72
+ };
73
+ error.data = {
74
+ code: 'PAIR_CHANNEL_CONFIG_INVALID',
75
+ debug: {
76
+ rootKeys: ['channel'],
77
+ channelConfigKeys: ['mqtt_topic'],
78
+ hasExistingMqttUrl: false
79
+ }
80
+ };
81
+
82
+ assert.deepEqual(formatCliErrorPayload(error), {
83
+ ok: false,
84
+ error: {
85
+ message: 'mqttUrl is missing from pairing payload',
86
+ code: 'PAIR_CHANNEL_CONFIG_INVALID',
87
+ debug: {
88
+ rootKeys: ['channel'],
89
+ channelConfigKeys: ['mqtt_topic'],
90
+ hasExistingMqttUrl: false
91
+ }
92
+ }
93
+ });
94
+ });