@2en/clawly-plugins 1.15.0 → 1.16.0

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 (3) hide show
  1. package/auto-pair.ts +72 -0
  2. package/index.ts +3 -0
  3. package/package.json +2 -1
package/auto-pair.ts ADDED
@@ -0,0 +1,72 @@
1
+ import type {PluginApi} from './index'
2
+
3
+ const AUTO_APPROVE_CLIENT_IDS = new Set(['openclaw-ios'])
4
+ const POLL_INTERVAL_MS = 3_000
5
+
6
+ type PendingRequest = {
7
+ requestId: string
8
+ deviceId: string
9
+ clientId?: string
10
+ displayName?: string
11
+ platform?: string
12
+ }
13
+
14
+ type PairedDevice = {
15
+ deviceId: string
16
+ displayName?: string
17
+ platform?: string
18
+ }
19
+
20
+ type DevicePairingList = {
21
+ pending: PendingRequest[]
22
+ paired: PairedDevice[]
23
+ }
24
+
25
+ export function registerAutoPair(api: PluginApi) {
26
+ let timer: ReturnType<typeof setInterval> | null = null
27
+ let sdk: {
28
+ listDevicePairing: () => Promise<DevicePairingList>
29
+ approveDevicePairing: (
30
+ requestId: string,
31
+ ) => Promise<{requestId: string; device: PairedDevice} | null>
32
+ } | null = null
33
+
34
+ api.on('gateway_start', async () => {
35
+ try {
36
+ sdk = await import('openclaw/plugin-sdk')
37
+ } catch {
38
+ api.logger.warn('auto-pair: openclaw/plugin-sdk not available, skipping')
39
+ return
40
+ }
41
+
42
+ api.logger.info('auto-pair: started polling for pending pairing requests')
43
+
44
+ timer = setInterval(async () => {
45
+ if (!sdk) return
46
+ try {
47
+ const {pending} = await sdk.listDevicePairing()
48
+ for (const req of pending) {
49
+ if (req.clientId && AUTO_APPROVE_CLIENT_IDS.has(req.clientId)) {
50
+ const result = await sdk.approveDevicePairing(req.requestId)
51
+ if (result) {
52
+ api.logger.info(
53
+ `auto-pair: approved device=${result.device.deviceId} ` +
54
+ `name=${result.device.displayName ?? 'unknown'} ` +
55
+ `platform=${result.device.platform ?? 'unknown'}`,
56
+ )
57
+ }
58
+ }
59
+ }
60
+ } catch (err) {
61
+ api.logger.warn(`auto-pair: poll error: ${String(err)}`)
62
+ }
63
+ }, POLL_INTERVAL_MS)
64
+ })
65
+
66
+ api.on('gateway_stop', () => {
67
+ if (timer) {
68
+ clearInterval(timer)
69
+ timer = null
70
+ }
71
+ })
72
+ }
package/index.ts CHANGED
@@ -24,8 +24,10 @@
24
24
  * Hooks:
25
25
  * - tool_result_persist — copies TTS audio to persistent outbound directory
26
26
  * - before_tool_call — enforces delivery fields on cron.create
27
+ * - gateway_start — auto-approves device pairing for Clawly mobile clients (clientId: openclaw-ios)
27
28
  */
28
29
 
30
+ import {registerAutoPair} from './auto-pair'
29
31
  import {registerCalendar} from './calendar'
30
32
  import {registerClawlyCronChannel} from './channel'
31
33
  import {registerCommands} from './command'
@@ -114,6 +116,7 @@ export default {
114
116
  registerClawlyCronChannel(api)
115
117
  registerCronHook(api)
116
118
  registerGateway(api)
119
+ registerAutoPair(api)
117
120
 
118
121
  // Email & calendar (optional — requires skillGatewayBaseUrl + skillGatewayToken in config)
119
122
  const gw = getGatewayConfig(api)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@2en/clawly-plugins",
3
- "version": "1.15.0",
3
+ "version": "1.16.0",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "repository": {
@@ -17,6 +17,7 @@
17
17
  "lib",
18
18
  "tools",
19
19
  "index.ts",
20
+ "auto-pair.ts",
20
21
  "calendar.ts",
21
22
  "channel.ts",
22
23
  "cron-hook.ts",