adp-openclaw 0.0.4 → 0.0.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adp-openclaw",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "OpenClaw demo channel plugin (Go WebSocket backend)",
5
5
  "type": "module",
6
6
  "dependencies": {
package/server.tar ADDED
Binary file
package/src/channel.ts CHANGED
@@ -12,7 +12,6 @@ export type AdpOpenclawChannelConfig = {
12
12
  enabled?: boolean;
13
13
  serverUrl?: string;
14
14
  wsUrl?: string;
15
- apiToken?: string;
16
15
  clientToken?: string;
17
16
  pollIntervalMs?: number;
18
17
  };
@@ -23,13 +22,13 @@ export type ResolvedAdpOpenclawAccount = {
23
22
  enabled: boolean;
24
23
  configured: boolean;
25
24
  serverUrl: string;
26
- apiToken: string;
25
+ clientToken: string;
27
26
  pollIntervalMs: number;
28
27
  };
29
28
 
30
29
  function resolveAdpOpenclawCredentials(channelCfg?: AdpOpenclawChannelConfig): {
31
30
  serverUrl: string;
32
- apiToken: string;
31
+ clientToken: string;
33
32
  pollIntervalMs: number;
34
33
  } | null {
35
34
  // Get serverUrl: support both serverUrl and wsUrl
@@ -45,23 +44,20 @@ function resolveAdpOpenclawCredentials(channelCfg?: AdpOpenclawChannelConfig): {
45
44
  serverUrl = process.env.ADP_OPENCLAW_SERVER_URL || "";
46
45
  }
47
46
 
48
- // Get apiToken: support both apiToken and clientToken
49
- let apiToken = channelCfg?.apiToken?.trim();
50
- if (!apiToken && channelCfg?.clientToken) {
51
- apiToken = channelCfg.clientToken.trim();
52
- }
53
- if (!apiToken) {
54
- apiToken = process.env.ADP_OPENCLAW_API_TOKEN || "";
47
+ // Get clientToken from config or env
48
+ let clientToken = channelCfg?.clientToken?.trim();
49
+ if (!clientToken) {
50
+ clientToken = process.env.ADP_OPENCLAW_CLIENT_TOKEN || "";
55
51
  }
56
52
 
57
53
  // Both are required for configured status
58
- if (!serverUrl || !apiToken) {
54
+ if (!serverUrl || !clientToken) {
59
55
  return null;
60
56
  }
61
57
 
62
58
  const pollIntervalMs = channelCfg?.pollIntervalMs ?? 1000;
63
59
 
64
- return { serverUrl, apiToken, pollIntervalMs };
60
+ return { serverUrl, clientToken, pollIntervalMs };
65
61
  }
66
62
 
67
63
  function resolveAccount(cfg: ClawdbotConfig, accountId?: string): ResolvedAdpOpenclawAccount {
@@ -75,7 +71,7 @@ function resolveAccount(cfg: ClawdbotConfig, accountId?: string): ResolvedAdpOpe
75
71
  enabled,
76
72
  configured: Boolean(creds),
77
73
  serverUrl: creds?.serverUrl || "http://localhost:9876",
78
- apiToken: creds?.apiToken || "",
74
+ clientToken: creds?.clientToken || "",
79
75
  pollIntervalMs: creds?.pollIntervalMs || 1000,
80
76
  };
81
77
  }
@@ -106,7 +102,6 @@ export const adpOpenclawPlugin: ChannelPlugin<ResolvedAdpOpenclawAccount> = {
106
102
  enabled: { type: "boolean" },
107
103
  serverUrl: { type: "string" },
108
104
  wsUrl: { type: "string" },
109
- apiToken: { type: "string" },
110
105
  clientToken: { type: "string" },
111
106
  pollIntervalMs: { type: "integer", minimum: 100 },
112
107
  },
@@ -222,7 +217,7 @@ export const adpOpenclawPlugin: ChannelPlugin<ResolvedAdpOpenclawAccount> = {
222
217
  const { monitorAdpOpenclaw } = await import("./monitor.js");
223
218
  return monitorAdpOpenclaw({
224
219
  serverUrl: account.serverUrl,
225
- apiToken: account.apiToken,
220
+ clientToken: account.clientToken,
226
221
  pollIntervalMs: account.pollIntervalMs,
227
222
  abortSignal: ctx.abortSignal,
228
223
  log: ctx.log,
@@ -256,7 +251,7 @@ export const adpOpenclawPlugin: ChannelPlugin<ResolvedAdpOpenclawAccount> = {
256
251
  method: "POST",
257
252
  headers: {
258
253
  "Content-Type": "application/json",
259
- Authorization: `Bearer ${account.apiToken}`,
254
+ Authorization: `Bearer ${account.clientToken}`,
260
255
  },
261
256
  body: JSON.stringify({
262
257
  to: target,
@@ -3,6 +3,6 @@ import { z } from "zod";
3
3
  export const AdpOpenclawConfigSchema = z.object({
4
4
  enabled: z.boolean().optional(),
5
5
  serverUrl: z.string().optional(),
6
- apiToken: z.string().optional(),
6
+ clientToken: z.string().optional(),
7
7
  pollIntervalMs: z.number().optional(),
8
8
  });
package/src/monitor.ts CHANGED
@@ -7,7 +7,7 @@ import crypto from "crypto";
7
7
 
8
8
  export type MonitorParams = {
9
9
  serverUrl: string;
10
- apiToken: string;
10
+ clientToken: string;
11
11
  pollIntervalMs: number; // Used as reconnect delay
12
12
  abortSignal?: AbortSignal;
13
13
  log?: PluginLogger;
@@ -63,9 +63,10 @@ type AuthResultPayload = {
63
63
  message?: string;
64
64
  };
65
65
 
66
- // Generate HMAC-SHA256 signature for extra security
67
- function generateSignature(token: string, nonce: string): string {
68
- return crypto.createHash("sha256").update(`${token}:${nonce}`).digest("hex");
66
+ // Generate HMAC-SHA256 signature for authentication (includes timestamp for anti-replay)
67
+ function generateSignature(token: string, nonce: string, timestamp: number): string {
68
+ // Use HMAC-SHA256 with token as the key, and "nonce:timestamp" as the message
69
+ return crypto.createHmac("sha256", token).update(`${nonce}:${timestamp}`).digest("hex");
69
70
  }
70
71
 
71
72
  // Generate random nonce
@@ -79,7 +80,7 @@ function generateRequestId(): string {
79
80
  }
80
81
 
81
82
  export async function monitorAdpOpenclaw(params: MonitorParams): Promise<void> {
82
- const { serverUrl, apiToken, pollIntervalMs, abortSignal, log, cfg } = params;
83
+ const { serverUrl, clientToken, pollIntervalMs, abortSignal, log, cfg } = params;
83
84
  const runtime = getAdpOpenclawRuntime();
84
85
 
85
86
  // Convert HTTP URL to WebSocket URL
@@ -91,7 +92,7 @@ export async function monitorAdpOpenclaw(params: MonitorParams): Promise<void> {
91
92
  try {
92
93
  await connectAndHandle({
93
94
  wsUrl,
94
- apiToken,
95
+ clientToken,
95
96
  serverUrl,
96
97
  abortSignal,
97
98
  log,
@@ -115,7 +116,7 @@ export async function monitorAdpOpenclaw(params: MonitorParams): Promise<void> {
115
116
 
116
117
  type ConnectParams = {
117
118
  wsUrl: string;
118
- apiToken: string;
119
+ clientToken: string;
119
120
  serverUrl: string;
120
121
  abortSignal?: AbortSignal;
121
122
  log?: PluginLogger;
@@ -124,7 +125,7 @@ type ConnectParams = {
124
125
  };
125
126
 
126
127
  async function connectAndHandle(params: ConnectParams): Promise<void> {
127
- const { wsUrl, apiToken, serverUrl, abortSignal, log, runtime, cfg } = params;
128
+ const { wsUrl, clientToken, serverUrl, abortSignal, log, runtime, cfg } = params;
128
129
 
129
130
  // Dynamic import for WebSocket (works in both Node.js and browser)
130
131
  const WebSocket = (await import("ws")).default;
@@ -144,19 +145,21 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
144
145
  ws.on("open", () => {
145
146
  log?.info(`[adp-openclaw] WebSocket connected, authenticating...`);
146
147
 
147
- // Send authentication message with signature
148
+ // Send authentication message with signature (includes timestamp for anti-replay)
148
149
  const nonce = generateNonce();
149
- const signature = generateSignature(apiToken, nonce);
150
+ const timestamp = Date.now();
151
+ const signature = generateSignature(clientToken, nonce, timestamp);
150
152
 
151
153
  const authMsg: WSMessage = {
152
154
  type: MsgType.Auth,
153
155
  requestId: generateRequestId(),
154
156
  payload: {
155
- token: apiToken,
157
+ token: clientToken,
156
158
  nonce,
157
159
  signature,
160
+ timestamp, // Include timestamp in payload for server verification
158
161
  },
159
- timestamp: Date.now(),
162
+ timestamp,
160
163
  };
161
164
 
162
165
  ws.send(JSON.stringify(authMsg));
package/src/runtime.ts CHANGED
@@ -8,7 +8,6 @@ export type PluginConfig = {
8
8
  wsUrl?: string;
9
9
  clientToken?: string;
10
10
  serverUrl?: string;
11
- apiToken?: string;
12
11
  pollIntervalMs?: number;
13
12
  };
14
13