@2en/clawly-plugins 1.20.1 → 1.21.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.
package/gateway/index.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import type {PluginApi} from '../index'
2
2
  import {registerAgentSend} from './agent'
3
- import {registerChannelsConfigure} from './channels-configure'
4
3
  import {registerClawhub2gateway} from './clawhub2gateway'
5
4
  import {registerConfigRepair} from './config-repair'
6
5
  import {registerPairing} from './pairing'
@@ -17,7 +16,6 @@ export function registerGateway(api: PluginApi) {
17
16
  registerMemoryBrowser(api)
18
17
  registerClawhub2gateway(api)
19
18
  registerPlugins(api)
20
- registerChannelsConfigure(api)
21
19
  registerOfflinePush(api)
22
20
  registerConfigRepair(api)
23
21
  registerPairing(api)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@2en/clawly-plugins",
3
- "version": "1.20.1",
3
+ "version": "1.21.0",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "repository": {
@@ -1,151 +0,0 @@
1
- /**
2
- * Channel configuration management via openclaw.json.
3
- *
4
- * Methods:
5
- * - clawly.channels.configure — add/update a channel account config
6
- * - clawly.channels.disconnect — remove a channel account config
7
- */
8
-
9
- import fs from 'node:fs'
10
- import path from 'node:path'
11
-
12
- import type {PluginApi} from '../index'
13
-
14
- const TOKEN_CHANNELS = new Set(['telegram', 'discord', 'slack', 'irc', 'googlechat'])
15
-
16
- function resolveStateDir(api: PluginApi): string {
17
- return api.runtime.state?.resolveStateDir?.(process.env) ?? process.env.OPENCLAW_STATE_DIR ?? ''
18
- }
19
-
20
- function readOpenclawConfig(configPath: string): Record<string, unknown> {
21
- try {
22
- return JSON.parse(fs.readFileSync(configPath, 'utf-8'))
23
- } catch {
24
- return {}
25
- }
26
- }
27
-
28
- function writeOpenclawConfig(configPath: string, config: Record<string, unknown>) {
29
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n')
30
- }
31
-
32
- export function registerChannelsConfigure(api: PluginApi) {
33
- // ── clawly.channels.configure ──────────────────────────────────
34
-
35
- api.registerGatewayMethod('clawly.channels.configure', async ({params, respond}) => {
36
- const channel = typeof params.channel === 'string' ? params.channel.trim() : ''
37
- const accountId = typeof params.accountId === 'string' ? params.accountId.trim() : 'default'
38
- const config =
39
- params.config && typeof params.config === 'object' && !Array.isArray(params.config)
40
- ? (params.config as Record<string, unknown>)
41
- : null
42
-
43
- if (!channel) {
44
- respond(false, undefined, {code: 'invalid_params', message: 'channel is required'})
45
- return
46
- }
47
-
48
- if (!TOKEN_CHANNELS.has(channel)) {
49
- respond(false, undefined, {
50
- code: 'invalid_params',
51
- message: `unsupported channel: ${channel}. Supported: ${[...TOKEN_CHANNELS].join(', ')}`,
52
- })
53
- return
54
- }
55
-
56
- if (!config) {
57
- respond(false, undefined, {code: 'invalid_params', message: 'config object is required'})
58
- return
59
- }
60
-
61
- const stateDir = resolveStateDir(api)
62
- if (!stateDir) {
63
- respond(false, undefined, {code: 'internal', message: 'cannot resolve openclaw state dir'})
64
- return
65
- }
66
-
67
- const configPath = path.join(stateDir, 'openclaw.json')
68
-
69
- try {
70
- const ocConfig = readOpenclawConfig(configPath)
71
-
72
- // Ensure channels.<channel>.accounts.<accountId> path exists
73
- if (!ocConfig.channels || typeof ocConfig.channels !== 'object') {
74
- ocConfig.channels = {}
75
- }
76
- const channels = ocConfig.channels as Record<string, unknown>
77
-
78
- if (!channels[channel] || typeof channels[channel] !== 'object') {
79
- channels[channel] = {}
80
- }
81
- const channelConfig = channels[channel] as Record<string, unknown>
82
-
83
- if (!channelConfig.accounts || typeof channelConfig.accounts !== 'object') {
84
- channelConfig.accounts = {}
85
- }
86
- const accounts = channelConfig.accounts as Record<string, unknown>
87
-
88
- // Merge config with enabled: true
89
- accounts[accountId] = {
90
- ...((accounts[accountId] as Record<string, unknown>) ?? {}),
91
- ...config,
92
- enabled: true,
93
- }
94
-
95
- writeOpenclawConfig(configPath, ocConfig)
96
- api.logger.info(`channels.configure: wrote ${channel}/${accountId} to openclaw.json`)
97
-
98
- respond(true, {ok: true, channel, accountId})
99
- } catch (err) {
100
- const msg = err instanceof Error ? err.message : String(err)
101
- api.logger.error(`channels.configure: failed — ${msg}`)
102
- respond(false, undefined, {code: 'internal', message: msg})
103
- }
104
- })
105
-
106
- // ── clawly.channels.disconnect ─────────────────────────────────
107
-
108
- api.registerGatewayMethod('clawly.channels.disconnect', async ({params, respond}) => {
109
- const channel = typeof params.channel === 'string' ? params.channel.trim() : ''
110
- const accountId = typeof params.accountId === 'string' ? params.accountId.trim() : 'default'
111
-
112
- if (!channel) {
113
- respond(false, undefined, {code: 'invalid_params', message: 'channel is required'})
114
- return
115
- }
116
-
117
- const stateDir = resolveStateDir(api)
118
- if (!stateDir) {
119
- respond(false, undefined, {code: 'internal', message: 'cannot resolve openclaw state dir'})
120
- return
121
- }
122
-
123
- const configPath = path.join(stateDir, 'openclaw.json')
124
-
125
- try {
126
- const ocConfig = readOpenclawConfig(configPath)
127
- const channels = ocConfig.channels as Record<string, unknown> | undefined
128
-
129
- if (channels && typeof channels === 'object') {
130
- const channelConfig = channels[channel] as Record<string, unknown> | undefined
131
- if (channelConfig && typeof channelConfig === 'object') {
132
- const accounts = channelConfig.accounts as Record<string, unknown> | undefined
133
- if (accounts && typeof accounts === 'object' && accountId in accounts) {
134
- delete accounts[accountId]
135
- }
136
- }
137
- }
138
-
139
- writeOpenclawConfig(configPath, ocConfig)
140
- api.logger.info(`channels.disconnect: removed ${channel}/${accountId} from openclaw.json`)
141
-
142
- respond(true, {ok: true, channel, accountId})
143
- } catch (err) {
144
- const msg = err instanceof Error ? err.message : String(err)
145
- api.logger.error(`channels.disconnect: failed — ${msg}`)
146
- respond(false, undefined, {code: 'internal', message: msg})
147
- }
148
- })
149
-
150
- api.logger.info('channels: registered clawly.channels.configure + clawly.channels.disconnect')
151
- }