@2en/clawly-plugins 1.23.1 → 1.24.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.
package/config-setup.ts CHANGED
@@ -32,7 +32,8 @@ export interface ConfigPluginConfig {
32
32
  sessionMainKey?: string
33
33
  elevenlabsApiKey?: string
34
34
  elevenlabsVoiceId?: string
35
- braveSearchApiKey?: string
35
+ modelGatewayBaseUrl?: string
36
+ modelGatewayToken?: string
36
37
  }
37
38
 
38
39
  function toPC(api: PluginApi): ConfigPluginConfig {
@@ -284,20 +285,33 @@ export function patchTts(config: Record<string, unknown>, pc: ConfigPluginConfig
284
285
  }
285
286
 
286
287
  export function patchWebSearch(config: Record<string, unknown>, pc: ConfigPluginConfig): boolean {
287
- if (!pc.braveSearchApiKey) return false
288
+ if (!pc.modelGatewayBaseUrl || !pc.modelGatewayToken) return false
288
289
 
289
290
  let dirty = false
290
291
  const tools = (config.tools ?? {}) as Record<string, unknown>
291
292
  const web = (tools.web ?? {}) as Record<string, unknown>
292
293
  const search = (web.search ?? {}) as Record<string, unknown>
294
+ const perplexity = (search.perplexity ?? {}) as Record<string, unknown>
293
295
 
294
- // Credentials: enforce
295
- if (search.provider !== 'brave') {
296
- search.provider = 'brave'
296
+ // Provider: enforce
297
+ if (search.provider !== 'perplexity') {
298
+ search.provider = 'perplexity'
299
+ dirty = true
300
+ }
301
+
302
+ // Perplexity credentials: enforce (nested under search.perplexity)
303
+ if (perplexity.apiKey !== pc.modelGatewayToken) {
304
+ perplexity.apiKey = pc.modelGatewayToken
297
305
  dirty = true
298
306
  }
299
- if (search.apiKey !== pc.braveSearchApiKey) {
300
- search.apiKey = pc.braveSearchApiKey
307
+ if (perplexity.baseUrl !== pc.modelGatewayBaseUrl) {
308
+ perplexity.baseUrl = pc.modelGatewayBaseUrl
309
+ dirty = true
310
+ }
311
+
312
+ // Perplexity model: set-if-missing
313
+ if (perplexity.model === undefined) {
314
+ perplexity.model = 'perplexity/sonar-pro'
301
315
  dirty = true
302
316
  }
303
317
 
@@ -312,6 +326,7 @@ export function patchWebSearch(config: Record<string, unknown>, pc: ConfigPlugin
312
326
  }
313
327
 
314
328
  if (dirty) {
329
+ search.perplexity = perplexity
315
330
  web.search = search
316
331
  tools.web = web
317
332
  config.tools = tools
package/index.ts CHANGED
@@ -27,9 +27,11 @@
27
27
  * - before_tool_call — enforces delivery fields on cron.create
28
28
  * - agent_end — sends push notification when client is offline
29
29
  * - gateway_start — auto-approves device pairing for Clawly mobile clients (clientId: openclaw-ios)
30
+ * - gateway_start — registers auto-update cron job (0 3 * * *) for clawly-plugins
30
31
  */
31
32
 
32
33
  import {registerAutoPair} from './auto-pair'
34
+ import {registerAutoUpdate} from './internal/hooks/auto-update'
33
35
  import {registerCalendar} from './calendar'
34
36
  import {registerCommands} from './command'
35
37
  import {setupConfig} from './config-setup'
@@ -186,6 +188,7 @@ export default {
186
188
  setupConfig(api)
187
189
  registerGateway(api)
188
190
  registerAutoPair(api)
191
+ registerAutoUpdate(api)
189
192
 
190
193
  // Email & calendar (optional — requires skillGatewayBaseUrl + skillGatewayToken in config)
191
194
  const gw = getGatewayConfig(api)
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Registers a cron job (0 3 * * *) on gateway_start that
3
+ * checks user presence and auto-updates clawly-plugins when offline.
4
+ */
5
+ import {$} from 'zx'
6
+
7
+ import type {PluginApi} from '../../index'
8
+
9
+ $.verbose = false
10
+
11
+ // ── Types ──────────────────────────────────────────────────────
12
+
13
+ interface CronJobEntry {
14
+ id: string
15
+ name: string
16
+ description: string
17
+ enabled: boolean
18
+ schedule: {kind: 'cron'; expr: string; tz?: string} | {kind: string}
19
+ sessionTarget: string
20
+ wakeMode: string
21
+ payload: {kind: string; message?: string}
22
+ delivery: {mode: string}
23
+ }
24
+
25
+ interface JobConfig {
26
+ description: string
27
+ cron: string
28
+ session: 'main' | 'isolated'
29
+ wake: 'now' | 'next-heartbeat'
30
+ deliver: boolean
31
+ message: string
32
+ }
33
+
34
+ // ── Config ─────────────────────────────────────────────────────
35
+
36
+ const JOB_NAME = 'Clawly Plugins Auto-Update'
37
+
38
+ const JOB_CONFIG: JobConfig = {
39
+ description: 'Auto-update clawly-plugins when user is offline',
40
+ cron: '0 3 * * *',
41
+ session: 'isolated',
42
+ wake: 'now',
43
+ deliver: false,
44
+ message: [
45
+ 'Auto-update check for clawly-plugins.',
46
+ '',
47
+ 'Steps:',
48
+ '1. Call the clawly_is_user_online tool to check if the user is online.',
49
+ '2. If the user IS online, stop — do nothing.',
50
+ '3. If the user is NOT online, run this exact command in terminal:',
51
+ ` openclaw gateway call clawly.plugins.update --json --params '${JSON.stringify({pluginId: 'clawly-plugins', npmPkgName: '@2en/clawly-plugins', strategy: 'force', restart: true})}'`,
52
+ '',
53
+ 'Do not send any messages to the user. Just execute the steps silently.',
54
+ ].join('\n'),
55
+ }
56
+
57
+ // ── Helpers ────────────────────────────────────────────────────
58
+
59
+ function configToArgs(config: JobConfig): string[] {
60
+ const args = [
61
+ '--description',
62
+ config.description,
63
+ '--cron',
64
+ config.cron,
65
+ '--session',
66
+ config.session,
67
+ '--wake',
68
+ config.wake,
69
+ '--message',
70
+ config.message,
71
+ ]
72
+ if (!config.deliver) args.push('--no-deliver')
73
+ return args
74
+ }
75
+
76
+ function needsUpdate(job: CronJobEntry, config: JobConfig): boolean {
77
+ if (job.description !== config.description) return true
78
+ if (job.schedule.kind !== 'cron' || (job.schedule as {expr: string}).expr !== config.cron)
79
+ return true
80
+ if (job.sessionTarget !== config.session) return true
81
+ if (job.wakeMode !== config.wake) return true
82
+ if (job.payload.message !== config.message) return true
83
+ const wantMode = config.deliver ? 'announce' : 'none'
84
+ if (job.delivery.mode !== wantMode) return true
85
+ return false
86
+ }
87
+
88
+ async function findJob(): Promise<CronJobEntry | null> {
89
+ try {
90
+ const {stdout} = await $`openclaw cron list --json`
91
+ const parsed = JSON.parse(stdout)
92
+ const jobs: unknown[] = parsed?.jobs ?? parsed ?? []
93
+ if (!Array.isArray(jobs)) return null
94
+ return (jobs.find((j: any) => j.name === JOB_NAME) as CronJobEntry) ?? null
95
+ } catch {
96
+ return null
97
+ }
98
+ }
99
+
100
+ // ── Registration ───────────────────────────────────────────────
101
+
102
+ export function registerAutoUpdate(api: PluginApi) {
103
+ api.on('gateway_start', async () => {
104
+ try {
105
+ const existing = await findJob()
106
+
107
+ if (existing) {
108
+ if (!needsUpdate(existing, JOB_CONFIG)) {
109
+ api.logger.info('auto-update: cron job up to date')
110
+ return
111
+ }
112
+ await $`openclaw cron edit ${[existing.id, ...configToArgs(JOB_CONFIG)]}`
113
+ api.logger.info('auto-update: updated cron job')
114
+ } else {
115
+ await $`openclaw cron add ${['--name', JOB_NAME, ...configToArgs(JOB_CONFIG)]}`
116
+ api.logger.info('auto-update: registered cron job')
117
+ }
118
+ } catch (err) {
119
+ api.logger.warn(`auto-update: failed to register cron job: ${String(err)}`)
120
+ }
121
+ })
122
+ }
@@ -57,8 +57,7 @@
57
57
  "defaultImageModel": { "type": "string" },
58
58
  "sessionMainKey": { "type": "string" },
59
59
  "elevenlabsApiKey": { "type": "string" },
60
- "elevenlabsVoiceId": { "type": "string" },
61
- "braveSearchApiKey": { "type": "string" }
60
+ "elevenlabsVoiceId": { "type": "string" }
62
61
  },
63
62
  "required": []
64
63
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@2en/clawly-plugins",
3
- "version": "1.23.1",
3
+ "version": "1.24.1",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "repository": {
@@ -26,7 +26,8 @@
26
26
  "outbound.ts",
27
27
  "model-gateway-setup.ts",
28
28
  "skill-command-restore.ts",
29
- "openclaw.plugin.json"
29
+ "openclaw.plugin.json",
30
+ "internal"
30
31
  ],
31
32
  "publishConfig": {
32
33
  "access": "public"