@openclaw/zalo 2026.3.13 → 2026.5.1-beta.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.
Files changed (67) hide show
  1. package/README.md +1 -1
  2. package/api.ts +9 -0
  3. package/channel-plugin-api.ts +1 -0
  4. package/contract-api.ts +5 -0
  5. package/index.test.ts +15 -0
  6. package/index.ts +16 -13
  7. package/openclaw.plugin.json +514 -1
  8. package/package.json +31 -5
  9. package/runtime-api.test.ts +17 -0
  10. package/runtime-api.ts +75 -0
  11. package/secret-contract-api.ts +5 -0
  12. package/setup-api.ts +34 -0
  13. package/setup-entry.ts +13 -0
  14. package/src/accounts.test.ts +70 -0
  15. package/src/accounts.ts +19 -19
  16. package/src/actions.runtime.ts +5 -0
  17. package/src/actions.test.ts +32 -0
  18. package/src/actions.ts +20 -14
  19. package/src/api.test.ts +93 -2
  20. package/src/api.ts +29 -2
  21. package/src/approval-auth.test.ts +17 -0
  22. package/src/approval-auth.ts +25 -0
  23. package/src/channel.directory.test.ts +19 -6
  24. package/src/channel.runtime.ts +93 -0
  25. package/src/channel.startup.test.ts +26 -19
  26. package/src/channel.ts +228 -336
  27. package/src/config-schema.ts +3 -3
  28. package/src/group-access.ts +4 -3
  29. package/src/monitor.group-policy.test.ts +0 -12
  30. package/src/monitor.image.polling.test.ts +110 -0
  31. package/src/monitor.lifecycle.test.ts +41 -22
  32. package/src/monitor.pairing.lifecycle.test.ts +141 -0
  33. package/src/monitor.polling.media-reply.test.ts +425 -0
  34. package/src/monitor.reply-once.lifecycle.test.ts +171 -0
  35. package/src/monitor.ts +460 -206
  36. package/src/monitor.types.ts +4 -0
  37. package/src/monitor.webhook.test.ts +392 -62
  38. package/src/monitor.webhook.ts +73 -36
  39. package/src/outbound-media.test.ts +182 -0
  40. package/src/outbound-media.ts +241 -0
  41. package/src/outbound-payload.contract.test.ts +45 -0
  42. package/src/probe.ts +1 -1
  43. package/src/proxy.ts +1 -1
  44. package/src/runtime-api.ts +75 -0
  45. package/src/runtime-support.ts +91 -0
  46. package/src/runtime.ts +6 -3
  47. package/src/secret-contract.ts +109 -0
  48. package/src/secret-input.ts +1 -9
  49. package/src/send.test.ts +120 -0
  50. package/src/send.ts +15 -13
  51. package/src/session-route.ts +32 -0
  52. package/src/setup-allow-from.ts +94 -0
  53. package/src/setup-core.ts +149 -0
  54. package/src/{onboarding.status.test.ts → setup-status.test.ts} +13 -4
  55. package/src/setup-surface.test.ts +175 -0
  56. package/src/{onboarding.ts → setup-surface.ts} +59 -177
  57. package/src/status-issues.test.ts +2 -14
  58. package/src/status-issues.ts +8 -2
  59. package/src/test-support/lifecycle-test-support.ts +413 -0
  60. package/src/test-support/monitor-mocks-test-support.ts +209 -0
  61. package/src/token.test.ts +15 -0
  62. package/src/token.ts +8 -17
  63. package/src/types.ts +2 -2
  64. package/test-api.ts +1 -0
  65. package/tsconfig.json +16 -0
  66. package/CHANGELOG.md +0 -101
  67. package/src/channel.sendpayload.test.ts +0 -44
package/README.md CHANGED
@@ -5,7 +5,7 @@ Zalo channel plugin for OpenClaw (Bot API).
5
5
  ## Install (local checkout)
6
6
 
7
7
  ```bash
8
- openclaw plugins install ./extensions/zalo
8
+ openclaw plugins install ./path/to/local/zalo-plugin
9
9
  ```
10
10
 
11
11
  ## Install (npm)
package/api.ts ADDED
@@ -0,0 +1,9 @@
1
+ export { zaloPlugin } from "./src/channel.js";
2
+ export {
3
+ createZaloSetupWizardProxy,
4
+ evaluateZaloGroupAccess,
5
+ resolveZaloRuntimeGroupPolicy,
6
+ zaloDmPolicy,
7
+ zaloSetupAdapter,
8
+ zaloSetupWizard,
9
+ } from "./setup-api.js";
@@ -0,0 +1 @@
1
+ export { zaloPlugin } from "./src/channel.js";
@@ -0,0 +1,5 @@
1
+ export { evaluateZaloGroupAccess, resolveZaloRuntimeGroupPolicy } from "./src/group-access.js";
2
+ export {
3
+ collectRuntimeConfigAssignments,
4
+ secretTargetRegistryEntries,
5
+ } from "./src/secret-contract.js";
package/index.test.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { assertBundledChannelEntries } from "openclaw/plugin-sdk/channel-test-helpers";
2
+ import { describe } from "vitest";
3
+ import entry from "./index.js";
4
+ import setupEntry from "./setup-entry.js";
5
+
6
+ describe("zalo bundled entries", () => {
7
+ assertBundledChannelEntries({
8
+ entry,
9
+ expectedId: "zalo",
10
+ expectedName: "Zalo",
11
+ setupEntry,
12
+ channelMessage: "declares the channel plugin without a runtime-barrel cycle",
13
+ setupMessage: "declares the setup plugin without a runtime-barrel cycle",
14
+ });
15
+ });
package/index.ts CHANGED
@@ -1,17 +1,20 @@
1
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk/zalo";
2
- import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/zalo";
3
- import { zaloDock, zaloPlugin } from "./src/channel.js";
4
- import { setZaloRuntime } from "./src/runtime.js";
1
+ import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
5
2
 
6
- const plugin = {
3
+ export default defineBundledChannelEntry({
7
4
  id: "zalo",
8
5
  name: "Zalo",
9
- description: "Zalo channel plugin (Bot API)",
10
- configSchema: emptyPluginConfigSchema(),
11
- register(api: OpenClawPluginApi) {
12
- setZaloRuntime(api.runtime);
13
- api.registerChannel({ plugin: zaloPlugin, dock: zaloDock });
6
+ description: "Zalo channel plugin",
7
+ importMetaUrl: import.meta.url,
8
+ plugin: {
9
+ specifier: "./channel-plugin-api.js",
10
+ exportName: "zaloPlugin",
14
11
  },
15
- };
16
-
17
- export default plugin;
12
+ secrets: {
13
+ specifier: "./secret-contract-api.js",
14
+ exportName: "channelSecrets",
15
+ },
16
+ runtime: {
17
+ specifier: "./runtime-api.js",
18
+ exportName: "setZaloRuntime",
19
+ },
20
+ });
@@ -1,9 +1,522 @@
1
1
  {
2
2
  "id": "zalo",
3
- "channels": ["zalo"],
3
+ "activation": {
4
+ "onStartup": false
5
+ },
6
+ "channels": [
7
+ "zalo"
8
+ ],
9
+ "channelEnvVars": {
10
+ "zalo": [
11
+ "ZALO_BOT_TOKEN",
12
+ "ZALO_WEBHOOK_SECRET"
13
+ ]
14
+ },
4
15
  "configSchema": {
5
16
  "type": "object",
6
17
  "additionalProperties": false,
7
18
  "properties": {}
19
+ },
20
+ "channelConfigs": {
21
+ "zalo": {
22
+ "schema": {
23
+ "$schema": "http://json-schema.org/draft-07/schema#",
24
+ "type": "object",
25
+ "properties": {
26
+ "name": {
27
+ "type": "string"
28
+ },
29
+ "enabled": {
30
+ "type": "boolean"
31
+ },
32
+ "markdown": {
33
+ "type": "object",
34
+ "properties": {
35
+ "tables": {
36
+ "type": "string",
37
+ "enum": [
38
+ "off",
39
+ "bullets",
40
+ "code",
41
+ "block"
42
+ ]
43
+ }
44
+ },
45
+ "additionalProperties": false
46
+ },
47
+ "botToken": {
48
+ "anyOf": [
49
+ {
50
+ "type": "string"
51
+ },
52
+ {
53
+ "oneOf": [
54
+ {
55
+ "type": "object",
56
+ "properties": {
57
+ "source": {
58
+ "type": "string",
59
+ "const": "env"
60
+ },
61
+ "provider": {
62
+ "type": "string",
63
+ "pattern": "^[a-z][a-z0-9_-]{0,63}$"
64
+ },
65
+ "id": {
66
+ "type": "string",
67
+ "pattern": "^[A-Z][A-Z0-9_]{0,127}$"
68
+ }
69
+ },
70
+ "required": [
71
+ "source",
72
+ "provider",
73
+ "id"
74
+ ],
75
+ "additionalProperties": false
76
+ },
77
+ {
78
+ "type": "object",
79
+ "properties": {
80
+ "source": {
81
+ "type": "string",
82
+ "const": "file"
83
+ },
84
+ "provider": {
85
+ "type": "string",
86
+ "pattern": "^[a-z][a-z0-9_-]{0,63}$"
87
+ },
88
+ "id": {
89
+ "type": "string"
90
+ }
91
+ },
92
+ "required": [
93
+ "source",
94
+ "provider",
95
+ "id"
96
+ ],
97
+ "additionalProperties": false
98
+ },
99
+ {
100
+ "type": "object",
101
+ "properties": {
102
+ "source": {
103
+ "type": "string",
104
+ "const": "exec"
105
+ },
106
+ "provider": {
107
+ "type": "string",
108
+ "pattern": "^[a-z][a-z0-9_-]{0,63}$"
109
+ },
110
+ "id": {
111
+ "type": "string"
112
+ }
113
+ },
114
+ "required": [
115
+ "source",
116
+ "provider",
117
+ "id"
118
+ ],
119
+ "additionalProperties": false
120
+ }
121
+ ]
122
+ }
123
+ ]
124
+ },
125
+ "tokenFile": {
126
+ "type": "string"
127
+ },
128
+ "webhookUrl": {
129
+ "type": "string"
130
+ },
131
+ "webhookSecret": {
132
+ "anyOf": [
133
+ {
134
+ "type": "string"
135
+ },
136
+ {
137
+ "oneOf": [
138
+ {
139
+ "type": "object",
140
+ "properties": {
141
+ "source": {
142
+ "type": "string",
143
+ "const": "env"
144
+ },
145
+ "provider": {
146
+ "type": "string",
147
+ "pattern": "^[a-z][a-z0-9_-]{0,63}$"
148
+ },
149
+ "id": {
150
+ "type": "string",
151
+ "pattern": "^[A-Z][A-Z0-9_]{0,127}$"
152
+ }
153
+ },
154
+ "required": [
155
+ "source",
156
+ "provider",
157
+ "id"
158
+ ],
159
+ "additionalProperties": false
160
+ },
161
+ {
162
+ "type": "object",
163
+ "properties": {
164
+ "source": {
165
+ "type": "string",
166
+ "const": "file"
167
+ },
168
+ "provider": {
169
+ "type": "string",
170
+ "pattern": "^[a-z][a-z0-9_-]{0,63}$"
171
+ },
172
+ "id": {
173
+ "type": "string"
174
+ }
175
+ },
176
+ "required": [
177
+ "source",
178
+ "provider",
179
+ "id"
180
+ ],
181
+ "additionalProperties": false
182
+ },
183
+ {
184
+ "type": "object",
185
+ "properties": {
186
+ "source": {
187
+ "type": "string",
188
+ "const": "exec"
189
+ },
190
+ "provider": {
191
+ "type": "string",
192
+ "pattern": "^[a-z][a-z0-9_-]{0,63}$"
193
+ },
194
+ "id": {
195
+ "type": "string"
196
+ }
197
+ },
198
+ "required": [
199
+ "source",
200
+ "provider",
201
+ "id"
202
+ ],
203
+ "additionalProperties": false
204
+ }
205
+ ]
206
+ }
207
+ ]
208
+ },
209
+ "webhookPath": {
210
+ "type": "string"
211
+ },
212
+ "dmPolicy": {
213
+ "type": "string",
214
+ "enum": [
215
+ "pairing",
216
+ "allowlist",
217
+ "open",
218
+ "disabled"
219
+ ]
220
+ },
221
+ "allowFrom": {
222
+ "type": "array",
223
+ "items": {
224
+ "anyOf": [
225
+ {
226
+ "type": "string"
227
+ },
228
+ {
229
+ "type": "number"
230
+ }
231
+ ]
232
+ }
233
+ },
234
+ "groupPolicy": {
235
+ "type": "string",
236
+ "enum": [
237
+ "open",
238
+ "disabled",
239
+ "allowlist"
240
+ ]
241
+ },
242
+ "groupAllowFrom": {
243
+ "type": "array",
244
+ "items": {
245
+ "anyOf": [
246
+ {
247
+ "type": "string"
248
+ },
249
+ {
250
+ "type": "number"
251
+ }
252
+ ]
253
+ }
254
+ },
255
+ "mediaMaxMb": {
256
+ "type": "number"
257
+ },
258
+ "proxy": {
259
+ "type": "string"
260
+ },
261
+ "responsePrefix": {
262
+ "type": "string"
263
+ },
264
+ "accounts": {
265
+ "type": "object",
266
+ "properties": {},
267
+ "additionalProperties": {
268
+ "type": "object",
269
+ "properties": {
270
+ "name": {
271
+ "type": "string"
272
+ },
273
+ "enabled": {
274
+ "type": "boolean"
275
+ },
276
+ "markdown": {
277
+ "type": "object",
278
+ "properties": {
279
+ "tables": {
280
+ "type": "string",
281
+ "enum": [
282
+ "off",
283
+ "bullets",
284
+ "code",
285
+ "block"
286
+ ]
287
+ }
288
+ },
289
+ "additionalProperties": false
290
+ },
291
+ "botToken": {
292
+ "anyOf": [
293
+ {
294
+ "type": "string"
295
+ },
296
+ {
297
+ "oneOf": [
298
+ {
299
+ "type": "object",
300
+ "properties": {
301
+ "source": {
302
+ "type": "string",
303
+ "const": "env"
304
+ },
305
+ "provider": {
306
+ "type": "string",
307
+ "pattern": "^[a-z][a-z0-9_-]{0,63}$"
308
+ },
309
+ "id": {
310
+ "type": "string",
311
+ "pattern": "^[A-Z][A-Z0-9_]{0,127}$"
312
+ }
313
+ },
314
+ "required": [
315
+ "source",
316
+ "provider",
317
+ "id"
318
+ ],
319
+ "additionalProperties": false
320
+ },
321
+ {
322
+ "type": "object",
323
+ "properties": {
324
+ "source": {
325
+ "type": "string",
326
+ "const": "file"
327
+ },
328
+ "provider": {
329
+ "type": "string",
330
+ "pattern": "^[a-z][a-z0-9_-]{0,63}$"
331
+ },
332
+ "id": {
333
+ "type": "string"
334
+ }
335
+ },
336
+ "required": [
337
+ "source",
338
+ "provider",
339
+ "id"
340
+ ],
341
+ "additionalProperties": false
342
+ },
343
+ {
344
+ "type": "object",
345
+ "properties": {
346
+ "source": {
347
+ "type": "string",
348
+ "const": "exec"
349
+ },
350
+ "provider": {
351
+ "type": "string",
352
+ "pattern": "^[a-z][a-z0-9_-]{0,63}$"
353
+ },
354
+ "id": {
355
+ "type": "string"
356
+ }
357
+ },
358
+ "required": [
359
+ "source",
360
+ "provider",
361
+ "id"
362
+ ],
363
+ "additionalProperties": false
364
+ }
365
+ ]
366
+ }
367
+ ]
368
+ },
369
+ "tokenFile": {
370
+ "type": "string"
371
+ },
372
+ "webhookUrl": {
373
+ "type": "string"
374
+ },
375
+ "webhookSecret": {
376
+ "anyOf": [
377
+ {
378
+ "type": "string"
379
+ },
380
+ {
381
+ "oneOf": [
382
+ {
383
+ "type": "object",
384
+ "properties": {
385
+ "source": {
386
+ "type": "string",
387
+ "const": "env"
388
+ },
389
+ "provider": {
390
+ "type": "string",
391
+ "pattern": "^[a-z][a-z0-9_-]{0,63}$"
392
+ },
393
+ "id": {
394
+ "type": "string",
395
+ "pattern": "^[A-Z][A-Z0-9_]{0,127}$"
396
+ }
397
+ },
398
+ "required": [
399
+ "source",
400
+ "provider",
401
+ "id"
402
+ ],
403
+ "additionalProperties": false
404
+ },
405
+ {
406
+ "type": "object",
407
+ "properties": {
408
+ "source": {
409
+ "type": "string",
410
+ "const": "file"
411
+ },
412
+ "provider": {
413
+ "type": "string",
414
+ "pattern": "^[a-z][a-z0-9_-]{0,63}$"
415
+ },
416
+ "id": {
417
+ "type": "string"
418
+ }
419
+ },
420
+ "required": [
421
+ "source",
422
+ "provider",
423
+ "id"
424
+ ],
425
+ "additionalProperties": false
426
+ },
427
+ {
428
+ "type": "object",
429
+ "properties": {
430
+ "source": {
431
+ "type": "string",
432
+ "const": "exec"
433
+ },
434
+ "provider": {
435
+ "type": "string",
436
+ "pattern": "^[a-z][a-z0-9_-]{0,63}$"
437
+ },
438
+ "id": {
439
+ "type": "string"
440
+ }
441
+ },
442
+ "required": [
443
+ "source",
444
+ "provider",
445
+ "id"
446
+ ],
447
+ "additionalProperties": false
448
+ }
449
+ ]
450
+ }
451
+ ]
452
+ },
453
+ "webhookPath": {
454
+ "type": "string"
455
+ },
456
+ "dmPolicy": {
457
+ "type": "string",
458
+ "enum": [
459
+ "pairing",
460
+ "allowlist",
461
+ "open",
462
+ "disabled"
463
+ ]
464
+ },
465
+ "allowFrom": {
466
+ "type": "array",
467
+ "items": {
468
+ "anyOf": [
469
+ {
470
+ "type": "string"
471
+ },
472
+ {
473
+ "type": "number"
474
+ }
475
+ ]
476
+ }
477
+ },
478
+ "groupPolicy": {
479
+ "type": "string",
480
+ "enum": [
481
+ "open",
482
+ "disabled",
483
+ "allowlist"
484
+ ]
485
+ },
486
+ "groupAllowFrom": {
487
+ "type": "array",
488
+ "items": {
489
+ "anyOf": [
490
+ {
491
+ "type": "string"
492
+ },
493
+ {
494
+ "type": "number"
495
+ }
496
+ ]
497
+ }
498
+ },
499
+ "mediaMaxMb": {
500
+ "type": "number"
501
+ },
502
+ "proxy": {
503
+ "type": "string"
504
+ },
505
+ "responsePrefix": {
506
+ "type": "string"
507
+ }
508
+ },
509
+ "additionalProperties": false
510
+ }
511
+ },
512
+ "defaultAccount": {
513
+ "type": "string"
514
+ }
515
+ },
516
+ "additionalProperties": false
517
+ },
518
+ "label": "Zalo",
519
+ "description": "Vietnam-focused messaging platform with Bot API."
520
+ }
8
521
  }
9
522
  }
package/package.json CHANGED
@@ -1,16 +1,32 @@
1
1
  {
2
2
  "name": "@openclaw/zalo",
3
- "version": "2026.3.13",
3
+ "version": "2026.5.1-beta.2",
4
4
  "description": "OpenClaw Zalo channel plugin",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/openclaw/openclaw"
8
+ },
5
9
  "type": "module",
6
10
  "dependencies": {
7
- "undici": "7.24.1",
8
- "zod": "^4.3.6"
11
+ "undici": "8.1.0"
12
+ },
13
+ "devDependencies": {
14
+ "@openclaw/plugin-sdk": "workspace:*",
15
+ "openclaw": "workspace:*"
16
+ },
17
+ "peerDependencies": {
18
+ "openclaw": ">=2026.4.25"
19
+ },
20
+ "peerDependenciesMeta": {
21
+ "openclaw": {
22
+ "optional": true
23
+ }
9
24
  },
10
25
  "openclaw": {
11
26
  "extensions": [
12
27
  "./index.ts"
13
28
  ],
29
+ "setupEntry": "./setup-entry.ts",
14
30
  "channel": {
15
31
  "id": "zalo",
16
32
  "label": "Zalo",
@@ -26,8 +42,18 @@
26
42
  },
27
43
  "install": {
28
44
  "npmSpec": "@openclaw/zalo",
29
- "localPath": "extensions/zalo",
30
- "defaultChoice": "npm"
45
+ "defaultChoice": "npm",
46
+ "minHostVersion": ">=2026.4.10"
47
+ },
48
+ "compat": {
49
+ "pluginApi": ">=2026.4.25"
50
+ },
51
+ "build": {
52
+ "openclawVersion": "2026.5.1-beta.2"
53
+ },
54
+ "release": {
55
+ "publishToClawHub": true,
56
+ "publishToNpm": true
31
57
  }
32
58
  }
33
59
  }
@@ -0,0 +1,17 @@
1
+ import { runDirectImportSmoke } from "openclaw/plugin-sdk/plugin-test-contracts";
2
+ import { describe, expect, it } from "vitest";
3
+
4
+ describe("zalo runtime api", () => {
5
+ it("loads the narrow runtime api without reentering setup surfaces", async () => {
6
+ const stdout = await runDirectImportSmoke(
7
+ `const runtime = await import("./extensions/zalo/runtime-api.ts");
8
+ process.stdout.write(JSON.stringify({
9
+ hasZaloPlugin: Object.hasOwn(runtime, "zaloPlugin"),
10
+ hasZaloSetupWizard: Object.hasOwn(runtime, "zaloSetupWizard"),
11
+ type: typeof runtime.setZaloRuntime,
12
+ }));`,
13
+ );
14
+
15
+ expect(stdout).toBe('{"hasZaloPlugin":false,"hasZaloSetupWizard":false,"type":"function"}');
16
+ }, 45_000);
17
+ });