@lingyao037/openclaw-lingyao-cli 0.4.0 → 0.4.1

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.
@@ -299,6 +299,12 @@ declare class AccountManager {
299
299
  * Revoke an account
300
300
  */
301
301
  revokeAccount(deviceId: string): Promise<boolean>;
302
+ /**
303
+ * Manually add a device by deviceId (user-initiated pairing).
304
+ * No pairing code or deviceToken required — the user explicitly
305
+ * trusts this device from the OpenClaw CLI.
306
+ */
307
+ addDevice(deviceId: string, deviceInfo: DeviceInfo): Promise<LingyaoAccount>;
302
308
  /**
303
309
  * Refresh device token
304
310
  */
package/dist/cli.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { L as LingyaoRuntime, H as HealthStatus, A as AccountManager } from './accounts-AwHXj7VB.js';
1
+ import { L as LingyaoRuntime, H as HealthStatus, A as AccountManager } from './accounts-DeDlxyS9.js';
2
2
 
3
3
  /**
4
4
  * Probe status levels
@@ -131,6 +131,10 @@ declare class LingyaoCLI {
131
131
  private accountManager;
132
132
  private probe;
133
133
  constructor(runtime: LingyaoRuntime, accountManager: AccountManager, probe: Probe);
134
+ /**
135
+ * Handle pair command - Add a device by deviceId
136
+ */
137
+ handlePair(args: PairArgs): Promise<CLIResult>;
134
138
  /**
135
139
  * Handle logout command - Revoke a device
136
140
  */
@@ -144,6 +148,16 @@ declare class LingyaoCLI {
144
148
  */
145
149
  listDevices(): Promise<CLIResult>;
146
150
  }
151
+ /**
152
+ * Pair command arguments
153
+ */
154
+ interface PairArgs {
155
+ channel?: string;
156
+ deviceId?: string;
157
+ device?: string;
158
+ name?: string;
159
+ platform?: string;
160
+ }
147
161
  /**
148
162
  * Logout command arguments
149
163
  */
@@ -172,4 +186,4 @@ interface CLIResult {
172
186
  */
173
187
  declare function executeCLICommand(command: string, args: Record<string, unknown>, runtime: LingyaoRuntime, accountManager: AccountManager, probe: Probe): Promise<CLIResult>;
174
188
 
175
- export { type CLIResult, LingyaoCLI, type LogoutArgs, type StatusArgs, executeCLICommand };
189
+ export { type CLIResult, LingyaoCLI, type LogoutArgs, type PairArgs, type StatusArgs, executeCLICommand };
package/dist/cli.js CHANGED
@@ -8,6 +8,45 @@ var LingyaoCLI = class {
8
8
  this.accountManager = accountManager;
9
9
  this.probe = probe;
10
10
  }
11
+ /**
12
+ * Handle pair command - Add a device by deviceId
13
+ */
14
+ async handlePair(args) {
15
+ try {
16
+ const { deviceId, device, name, platform } = args;
17
+ const targetId = deviceId ?? device;
18
+ if (!targetId) {
19
+ return {
20
+ success: false,
21
+ error: "Usage: openclaw channels pair --channel lingyao --device <deviceId> [--name <name>] [--platform <platform>]"
22
+ };
23
+ }
24
+ const deviceInfo = {
25
+ name: name ?? targetId,
26
+ platform: platform ?? "harmonyos",
27
+ version: ""
28
+ };
29
+ const account = await this.accountManager.addDevice(targetId, deviceInfo);
30
+ return {
31
+ success: true,
32
+ output: [
33
+ `Device paired successfully.`,
34
+ "",
35
+ ` Device ID: ${account.deviceId}`,
36
+ ` Name: ${account.deviceInfo.name}`,
37
+ ` Platform: ${account.deviceInfo.platform}`,
38
+ "",
39
+ "OpenClaw can now send notifications to this device via lingyao.live relay."
40
+ ].join("\n")
41
+ };
42
+ } catch (error) {
43
+ this.runtime.logger.error("Pair command failed", error);
44
+ return {
45
+ success: false,
46
+ error: `Pair command failed: ${error}`
47
+ };
48
+ }
49
+ }
11
50
  /**
12
51
  * Handle logout command - Revoke a device
13
52
  */
@@ -108,6 +147,7 @@ Usage: openclaw channels logout --channel lingyao --device <deviceId>`
108
147
  }
109
148
  }
110
149
  lines.push("Commands:");
150
+ lines.push(" openclaw channels pair --channel lingyao --device <deviceId>");
111
151
  lines.push(" openclaw channels logout --channel lingyao --device <deviceId>");
112
152
  lines.push(" openclaw channels status --channel lingyao");
113
153
  lines.push("");
@@ -161,6 +201,8 @@ Usage: openclaw channels logout --channel lingyao --device <deviceId>`
161
201
  async function executeCLICommand(command, args, runtime, accountManager, probe) {
162
202
  const cli = new LingyaoCLI(runtime, accountManager, probe);
163
203
  switch (command) {
204
+ case "pair":
205
+ return await cli.handlePair(args);
164
206
  case "logout":
165
207
  return await cli.handleLogout(args);
166
208
  case "status":
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import type { LingyaoRuntime } from \"./types.js\";\nimport { AccountManager } from \"./accounts.js\";\nimport { Probe } from \"./probe.js\";\n\n/**\n * CLI command handler for Lingyao plugin\n */\nexport class LingyaoCLI {\n private runtime: LingyaoRuntime;\n private accountManager: AccountManager;\n private probe: Probe;\n\n constructor(\n runtime: LingyaoRuntime,\n accountManager: AccountManager,\n probe: Probe\n ) {\n this.runtime = runtime;\n this.accountManager = accountManager;\n this.probe = probe;\n }\n\n /**\n * Handle logout command - Revoke a device\n */\n async handleLogout(args: LogoutArgs): Promise<CLIResult> {\n try {\n const { deviceId } = args;\n\n if (!deviceId) {\n // List devices and ask to specify\n const accounts = this.accountManager.getActiveAccounts();\n if (accounts.length === 0) {\n return {\n success: false,\n error: \"No paired devices found\",\n };\n }\n\n const list = accounts\n .map(\n (acc, i) =>\n `${i + 1}. ${acc.deviceId} (${acc.deviceInfo.name}) - Last seen: ${new Date(acc.lastSeenAt).toLocaleString()}`\n )\n .join(\"\\n\");\n\n return {\n success: false,\n error: `Please specify a device ID to revoke.\\n\\nPaired devices:\\n${list}\\n\\nUsage: openclaw channels logout --channel lingyao --device <deviceId>`,\n };\n }\n\n const account = this.accountManager.getAccount(deviceId);\n if (!account) {\n return {\n success: false,\n error: `Device not found: ${deviceId}`,\n };\n }\n\n const revoked = await this.accountManager.revokeAccount(deviceId);\n if (!revoked) {\n return {\n success: false,\n error: `Failed to revoke device: ${deviceId}`,\n };\n }\n\n return {\n success: true,\n output: `Device revoked: ${deviceId} (${account.deviceInfo.name})`,\n };\n } catch (error) {\n this.runtime.logger.error(\"Logout failed\", error);\n return {\n success: false,\n error: `Logout failed: ${error}`,\n };\n }\n }\n\n /**\n * Handle status command - Show channel status\n */\n async handleStatus(_args: StatusArgs): Promise<CLIResult> {\n try {\n const accounts = this.accountManager.getActiveAccounts();\n const healthStatus = await this.probe.getHealthStatus(\n 0, // activeConnections - would come from WebSocket manager\n 0 // queuedMessages - would come from outbound adapter\n );\n\n const statusColor = healthStatus.status === \"healthy\" ? \"✓\" : \"⚠\";\n\n const lines = [\n \"\",\n \"╔═══════════════════════════════════════════════════════════╗\",\n \"║ 灵爻 (Lingyao) Channel Status ║\",\n \"╚═══════════════════════════════════════════════════════════╝\",\n \"\",\n `Status: ${statusColor} ${healthStatus.status.toUpperCase()}`,\n `Uptime: ${this.probe.getUptimeString()}`,\n \"\",\n ];\n\n if (healthStatus.lastError) {\n lines.push(`Last Error: ${healthStatus.lastError}`);\n lines.push(\"\");\n }\n\n if (accounts.length === 0) {\n lines.push(\"No paired devices.\");\n lines.push(\"\");\n lines.push(\"Pairing is managed by the lingyao.live relay and Lingyao App.\");\n } else {\n lines.push(`Paired Devices (${accounts.length}):`);\n lines.push(\"\");\n\n for (const account of accounts) {\n const lastSeen = new Date(account.lastSeenAt).toLocaleString();\n const pairedAt = new Date(account.pairedAt).toLocaleString();\n\n lines.push(` Device: ${account.deviceId}`);\n lines.push(` Name: ${account.deviceInfo.name}`);\n lines.push(` Platform: ${account.deviceInfo.platform} ${account.deviceInfo.version}`);\n lines.push(` Status: ${account.status}`);\n lines.push(` Paired: ${pairedAt}`);\n lines.push(` Last Seen: ${lastSeen}`);\n lines.push(\"\");\n }\n }\n\n lines.push(\"Commands:\");\n lines.push(\" openclaw channels logout --channel lingyao --device <deviceId>\");\n lines.push(\" openclaw channels status --channel lingyao\");\n lines.push(\"\");\n\n return {\n success: true,\n output: lines.join(\"\\n\"),\n };\n } catch (error) {\n this.runtime.logger.error(\"Status command failed\", error);\n return {\n success: false,\n error: `Status command failed: ${error}`,\n };\n }\n }\n\n /**\n * List all paired devices\n */\n async listDevices(): Promise<CLIResult> {\n try {\n const accounts = this.accountManager.getActiveAccounts();\n\n if (accounts.length === 0) {\n return {\n success: true,\n output: \"No paired devices found.\",\n };\n }\n\n const lines = [\n `Paired Devices (${accounts.length}):`,\n \"\",\n ];\n\n for (const account of accounts) {\n lines.push(` ${account.deviceId}`);\n lines.push(` Name: ${account.deviceInfo.name}`);\n lines.push(` Platform: ${account.deviceInfo.platform}`);\n lines.push(` Status: ${account.status}`);\n lines.push(\"\");\n }\n\n return {\n success: true,\n output: lines.join(\"\\n\"),\n };\n } catch (error) {\n return {\n success: false,\n error: `Failed to list devices: ${error}`,\n };\n }\n }\n}\n\n/**\n * Logout command arguments\n */\nexport interface LogoutArgs {\n channel?: string;\n deviceId?: string;\n device?: string;\n}\n\n/**\n * Status command arguments\n */\nexport interface StatusArgs {\n channel?: string;\n verbose?: boolean;\n}\n\n/**\n * CLI command result\n */\nexport interface CLIResult {\n success: boolean;\n output?: string;\n error?: string;\n}\n\n/**\n * Execute CLI command\n */\nexport async function executeCLICommand(\n command: string,\n args: Record<string, unknown>,\n runtime: LingyaoRuntime,\n accountManager: AccountManager,\n probe: Probe\n): Promise<CLIResult> {\n const cli = new LingyaoCLI(runtime, accountManager, probe);\n\n switch (command) {\n case \"logout\":\n return await cli.handleLogout(args as LogoutArgs);\n\n case \"status\":\n return await cli.handleStatus(args as StatusArgs);\n\n case \"list\":\n return await cli.listDevices();\n\n default:\n return {\n success: false,\n error: `Unknown command: ${command}`,\n };\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import type { LingyaoRuntime } from \"./types.js\";\nimport { AccountManager } from \"./accounts.js\";\nimport { Probe } from \"./probe.js\";\n\n/**\n * CLI command handler for Lingyao plugin\n */\nexport class LingyaoCLI {\n private runtime: LingyaoRuntime;\n private accountManager: AccountManager;\n private probe: Probe;\n\n constructor(\n runtime: LingyaoRuntime,\n accountManager: AccountManager,\n probe: Probe\n ) {\n this.runtime = runtime;\n this.accountManager = accountManager;\n this.probe = probe;\n }\n\n /**\n * Handle pair command - Add a device by deviceId\n */\n async handlePair(args: PairArgs): Promise<CLIResult> {\n try {\n const { deviceId, device, name, platform } = args;\n const targetId = deviceId ?? device;\n\n if (!targetId) {\n return {\n success: false,\n error: \"Usage: openclaw channels pair --channel lingyao --device <deviceId> [--name <name>] [--platform <platform>]\",\n };\n }\n\n const deviceInfo: { name: string; platform: string; version: string } = {\n name: name ?? targetId,\n platform: platform ?? 'harmonyos',\n version: '',\n };\n\n const account = await this.accountManager.addDevice(targetId, deviceInfo);\n\n return {\n success: true,\n output: [\n `Device paired successfully.`,\n \"\",\n ` Device ID: ${account.deviceId}`,\n ` Name: ${account.deviceInfo.name}`,\n ` Platform: ${account.deviceInfo.platform}`,\n \"\",\n \"OpenClaw can now send notifications to this device via lingyao.live relay.\",\n ].join(\"\\n\"),\n };\n } catch (error) {\n this.runtime.logger.error(\"Pair command failed\", error);\n return {\n success: false,\n error: `Pair command failed: ${error}`,\n };\n }\n }\n\n /**\n * Handle logout command - Revoke a device\n */\n async handleLogout(args: LogoutArgs): Promise<CLIResult> {\n try {\n const { deviceId } = args;\n\n if (!deviceId) {\n // List devices and ask to specify\n const accounts = this.accountManager.getActiveAccounts();\n if (accounts.length === 0) {\n return {\n success: false,\n error: \"No paired devices found\",\n };\n }\n\n const list = accounts\n .map(\n (acc, i) =>\n `${i + 1}. ${acc.deviceId} (${acc.deviceInfo.name}) - Last seen: ${new Date(acc.lastSeenAt).toLocaleString()}`\n )\n .join(\"\\n\");\n\n return {\n success: false,\n error: `Please specify a device ID to revoke.\\n\\nPaired devices:\\n${list}\\n\\nUsage: openclaw channels logout --channel lingyao --device <deviceId>`,\n };\n }\n\n const account = this.accountManager.getAccount(deviceId);\n if (!account) {\n return {\n success: false,\n error: `Device not found: ${deviceId}`,\n };\n }\n\n const revoked = await this.accountManager.revokeAccount(deviceId);\n if (!revoked) {\n return {\n success: false,\n error: `Failed to revoke device: ${deviceId}`,\n };\n }\n\n return {\n success: true,\n output: `Device revoked: ${deviceId} (${account.deviceInfo.name})`,\n };\n } catch (error) {\n this.runtime.logger.error(\"Logout failed\", error);\n return {\n success: false,\n error: `Logout failed: ${error}`,\n };\n }\n }\n\n /**\n * Handle status command - Show channel status\n */\n async handleStatus(_args: StatusArgs): Promise<CLIResult> {\n try {\n const accounts = this.accountManager.getActiveAccounts();\n const healthStatus = await this.probe.getHealthStatus(\n 0, // activeConnections - would come from WebSocket manager\n 0 // queuedMessages - would come from outbound adapter\n );\n\n const statusColor = healthStatus.status === \"healthy\" ? \"✓\" : \"⚠\";\n\n const lines = [\n \"\",\n \"╔═══════════════════════════════════════════════════════════╗\",\n \"║ 灵爻 (Lingyao) Channel Status ║\",\n \"╚═══════════════════════════════════════════════════════════╝\",\n \"\",\n `Status: ${statusColor} ${healthStatus.status.toUpperCase()}`,\n `Uptime: ${this.probe.getUptimeString()}`,\n \"\",\n ];\n\n if (healthStatus.lastError) {\n lines.push(`Last Error: ${healthStatus.lastError}`);\n lines.push(\"\");\n }\n\n if (accounts.length === 0) {\n lines.push(\"No paired devices.\");\n lines.push(\"\");\n lines.push(\"Pairing is managed by the lingyao.live relay and Lingyao App.\");\n } else {\n lines.push(`Paired Devices (${accounts.length}):`);\n lines.push(\"\");\n\n for (const account of accounts) {\n const lastSeen = new Date(account.lastSeenAt).toLocaleString();\n const pairedAt = new Date(account.pairedAt).toLocaleString();\n\n lines.push(` Device: ${account.deviceId}`);\n lines.push(` Name: ${account.deviceInfo.name}`);\n lines.push(` Platform: ${account.deviceInfo.platform} ${account.deviceInfo.version}`);\n lines.push(` Status: ${account.status}`);\n lines.push(` Paired: ${pairedAt}`);\n lines.push(` Last Seen: ${lastSeen}`);\n lines.push(\"\");\n }\n }\n\n lines.push(\"Commands:\");\n lines.push(\" openclaw channels pair --channel lingyao --device <deviceId>\");\n lines.push(\" openclaw channels logout --channel lingyao --device <deviceId>\");\n lines.push(\" openclaw channels status --channel lingyao\");\n lines.push(\"\");\n\n return {\n success: true,\n output: lines.join(\"\\n\"),\n };\n } catch (error) {\n this.runtime.logger.error(\"Status command failed\", error);\n return {\n success: false,\n error: `Status command failed: ${error}`,\n };\n }\n }\n\n /**\n * List all paired devices\n */\n async listDevices(): Promise<CLIResult> {\n try {\n const accounts = this.accountManager.getActiveAccounts();\n\n if (accounts.length === 0) {\n return {\n success: true,\n output: \"No paired devices found.\",\n };\n }\n\n const lines = [\n `Paired Devices (${accounts.length}):`,\n \"\",\n ];\n\n for (const account of accounts) {\n lines.push(` ${account.deviceId}`);\n lines.push(` Name: ${account.deviceInfo.name}`);\n lines.push(` Platform: ${account.deviceInfo.platform}`);\n lines.push(` Status: ${account.status}`);\n lines.push(\"\");\n }\n\n return {\n success: true,\n output: lines.join(\"\\n\"),\n };\n } catch (error) {\n return {\n success: false,\n error: `Failed to list devices: ${error}`,\n };\n }\n }\n}\n\n/**\n * Pair command arguments\n */\nexport interface PairArgs {\n channel?: string;\n deviceId?: string;\n device?: string;\n name?: string;\n platform?: string;\n}\n\n/**\n * Logout command arguments\n */\nexport interface LogoutArgs {\n channel?: string;\n deviceId?: string;\n device?: string;\n}\n\n/**\n * Status command arguments\n */\nexport interface StatusArgs {\n channel?: string;\n verbose?: boolean;\n}\n\n/**\n * CLI command result\n */\nexport interface CLIResult {\n success: boolean;\n output?: string;\n error?: string;\n}\n\n/**\n * Execute CLI command\n */\nexport async function executeCLICommand(\n command: string,\n args: Record<string, unknown>,\n runtime: LingyaoRuntime,\n accountManager: AccountManager,\n probe: Probe\n): Promise<CLIResult> {\n const cli = new LingyaoCLI(runtime, accountManager, probe);\n\n switch (command) {\n case \"pair\":\n return await cli.handlePair(args as PairArgs);\n\n case \"logout\":\n return await cli.handleLogout(args as LogoutArgs);\n\n case \"status\":\n return await cli.handleStatus(args as StatusArgs);\n\n case \"list\":\n return await cli.listDevices();\n\n default:\n return {\n success: false,\n error: `Unknown command: ${command}`,\n };\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as openclaw_plugin_sdk_core from 'openclaw/plugin-sdk/core';
2
2
  import * as openclaw_plugin_sdk from 'openclaw/plugin-sdk';
3
- import { L as LingyaoRuntime, D as DeviceInfo, a as DeviceToken, A as AccountManager, S as SyncRequest, b as SyncResponse, c as LingyaoMessage, d as LingyaoConfig, N as NotifyPayload, H as HealthStatus } from './accounts-AwHXj7VB.js';
4
- export { e as AckRequest, f as DiarySyncPayload, F as FailedEntry, g as LINGYAO_SERVER_URL, h as LingyaoAccount, i as LingyaoAccountConfig, M as MemorySyncPayload, j as MessageType, k as NotifyAction, l as NotifyRequest, P as PairingCode, m as PairingConfirmRequest, n as PairingConfirmResponse, o as PollRequest, p as PollResponse, Q as QueuedMessage, T as TokenRefreshRequest, q as TokenRefreshResponse, W as WebSocketConnection } from './accounts-AwHXj7VB.js';
3
+ import { L as LingyaoRuntime, D as DeviceInfo, a as DeviceToken, A as AccountManager, S as SyncRequest, b as SyncResponse, c as LingyaoMessage, d as LingyaoConfig, N as NotifyPayload, H as HealthStatus } from './accounts-DeDlxyS9.js';
4
+ export { e as AckRequest, f as DiarySyncPayload, F as FailedEntry, g as LINGYAO_SERVER_URL, h as LingyaoAccount, i as LingyaoAccountConfig, M as MemorySyncPayload, j as MessageType, k as NotifyAction, l as NotifyRequest, P as PairingCode, m as PairingConfirmRequest, n as PairingConfirmResponse, o as PollRequest, p as PollResponse, Q as QueuedMessage, T as TokenRefreshRequest, q as TokenRefreshResponse, W as WebSocketConnection } from './accounts-DeDlxyS9.js';
5
5
 
6
6
  /**
7
7
  * 错误处理模块
package/dist/index.js CHANGED
@@ -14,11 +14,16 @@ function setRuntime(runtime) {
14
14
  function adaptPluginRuntime(pr) {
15
15
  const noop = (..._args) => {
16
16
  };
17
- const childLogger = pr.logging?.getChildLogger?.() ?? {
17
+ const rawLogger = pr.logging?.getChildLogger?.() ?? {
18
18
  info: console.info.bind(console),
19
19
  warn: console.warn.bind(console),
20
- error: console.error.bind(console),
21
- debug: noop
20
+ error: console.error.bind(console)
21
+ };
22
+ const childLogger = {
23
+ info: rawLogger.info,
24
+ warn: rawLogger.warn,
25
+ error: rawLogger.error,
26
+ debug: rawLogger.debug ?? noop
22
27
  };
23
28
  const stateDir = pr.state?.resolveStateDir?.() ?? join(process.cwd(), ".lingyao-data");
24
29
  const storeDir = join(stateDir, "lingyao");
@@ -1125,6 +1130,42 @@ var AccountManager = class {
1125
1130
  this.runtime.logger.info(`Account revoked: ${deviceId}`);
1126
1131
  return true;
1127
1132
  }
1133
+ /**
1134
+ * Manually add a device by deviceId (user-initiated pairing).
1135
+ * No pairing code or deviceToken required — the user explicitly
1136
+ * trusts this device from the OpenClaw CLI.
1137
+ */
1138
+ async addDevice(deviceId, deviceInfo) {
1139
+ const existing = this.accounts.get(deviceId);
1140
+ if (existing) {
1141
+ existing.status = "active";
1142
+ existing.deviceInfo = deviceInfo;
1143
+ existing.lastSeenAt = Date.now();
1144
+ await this.saveAccounts();
1145
+ this.runtime.logger.info(`Device re-activated: ${deviceId} (${deviceInfo.name})`);
1146
+ return existing;
1147
+ }
1148
+ const now = Date.now();
1149
+ const account = {
1150
+ deviceId,
1151
+ deviceInfo,
1152
+ deviceToken: {
1153
+ deviceId,
1154
+ pairingId: `manual_${now}`,
1155
+ token: "",
1156
+ secret: "",
1157
+ expiresAt: 0,
1158
+ deviceInfo
1159
+ },
1160
+ pairedAt: now,
1161
+ lastSeenAt: now,
1162
+ status: "active"
1163
+ };
1164
+ this.accounts.set(deviceId, account);
1165
+ await this.saveAccounts();
1166
+ this.runtime.logger.info(`Device added: ${deviceId} (${deviceInfo.name})`);
1167
+ return account;
1168
+ }
1128
1169
  /**
1129
1170
  * Refresh device token
1130
1171
  */