@honor-claw/yoyo 1.1.2 → 1.1.4-beta.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.
Files changed (66) hide show
  1. package/index.ts +25 -25
  2. package/package.json +5 -5
  3. package/src/apis/claw-cloud.ts +124 -124
  4. package/src/apis/helpers.ts +10 -10
  5. package/src/apis/honor-auth.ts +158 -158
  6. package/src/apis/http-client.ts +239 -239
  7. package/src/apis/index.ts +8 -8
  8. package/src/apis/types.ts +77 -73
  9. package/src/cloud-channel/channel.ts +117 -117
  10. package/src/cloud-channel/client.ts +3 -3
  11. package/src/cloud-channel/index.ts +4 -4
  12. package/src/cloud-channel/message-handler.ts +50 -42
  13. package/src/cloud-channel/session-manager.ts +14 -9
  14. package/src/cloud-channel/types.ts +115 -115
  15. package/src/commands/env/impl.ts +58 -58
  16. package/src/commands/env/index.ts +1 -1
  17. package/src/commands/index.ts +30 -30
  18. package/src/commands/login/impl.ts +30 -30
  19. package/src/commands/login/index.ts +1 -1
  20. package/src/commands/logout/index.ts +1 -1
  21. package/src/commands/status/index.ts +194 -194
  22. package/src/gateway-client/client.ts +90 -90
  23. package/src/gateway-client/device/auth.ts +57 -57
  24. package/src/gateway-client/device/builder.ts +105 -105
  25. package/src/gateway-client/device/helpers.ts +40 -40
  26. package/src/gateway-client/device/identity.ts +251 -251
  27. package/src/gateway-client/device/index.ts +40 -40
  28. package/src/gateway-client/device/types.ts +57 -57
  29. package/src/gateway-client/index.ts +5 -5
  30. package/src/gateway-client/protocol-client.ts +49 -34
  31. package/src/honor-auth/browser.ts +2 -2
  32. package/src/honor-auth/callback-server.ts +109 -109
  33. package/src/honor-auth/cloud.ts +57 -57
  34. package/src/honor-auth/config.ts +43 -43
  35. package/src/honor-auth/index.ts +3 -3
  36. package/src/honor-auth/token-manager.ts +90 -90
  37. package/src/honor-auth/types.ts +50 -50
  38. package/src/index.ts +10 -10
  39. package/src/modules/claw-configs/config-manager.ts +409 -409
  40. package/src/modules/claw-configs/hosts.ts +48 -48
  41. package/src/modules/claw-configs/index.ts +8 -8
  42. package/src/modules/claw-configs/provider.ts +394 -394
  43. package/src/modules/claw-configs/types.ts +34 -34
  44. package/src/modules/device/device-info.ts +1 -1
  45. package/src/modules/device/index.ts +3 -3
  46. package/src/modules/device/providers/base.ts +32 -32
  47. package/src/modules/device/providers/pad.ts +107 -107
  48. package/src/modules/device/providers/windows.ts +130 -130
  49. package/src/modules/device/registry.ts +48 -43
  50. package/src/modules/login/impl.ts +31 -26
  51. package/src/modules/login/index.ts +6 -6
  52. package/src/schemas.ts +23 -23
  53. package/src/services/connection/impl.ts +339 -339
  54. package/src/services/connection/status-tracker/events.ts +127 -127
  55. package/src/services/connection/status-tracker/index.ts +31 -31
  56. package/src/services/connection/status-tracker/storage.ts +133 -133
  57. package/src/services/connection/status-tracker/tracker.ts +370 -370
  58. package/src/services/connection/status-tracker/types.ts +131 -131
  59. package/src/services/connection/types.ts +20 -20
  60. package/src/types.ts +64 -64
  61. package/src/utils/id.ts +8 -8
  62. package/src/utils/jwt.ts +37 -37
  63. package/src/utils/logger.ts +20 -20
  64. package/src/utils/proxy.ts +58 -58
  65. package/src/utils/version.ts +29 -29
  66. package/src/utils/ws.ts +21 -21
@@ -1,409 +1,409 @@
1
- /**
2
- * 配置管理器 - 统一管理 openclaw 配置文件的读写
3
- */
4
-
5
- import type { OpenClawConfig } from "openclaw/plugin-sdk";
6
- import { getYoyoRuntime } from "../../runtime.js";
7
- import { isBetaVersion } from "../../utils/version.js";
8
- import type { GatewayAuthConfig, UserConfig } from "./types.js";
9
- import { detectProvidersToRename, updateProviderReferences } from "./provider.js";
10
-
11
- const PLUGIN_YOYO_ID = "yoyo";
12
- const YOYO_ALLOW_COMMANDS = [
13
- "alarm.create",
14
- "alarm.delete",
15
- "alarm.disable",
16
- "alarm.enable",
17
- "alarm.query",
18
- "alarm.update",
19
- "app.close",
20
- "app.open",
21
- "call.phone",
22
- "call.search",
23
- "capture-screenshot",
24
- "contact.search",
25
- "file-upload",
26
- "hotspot",
27
- "local-search",
28
- "message.search",
29
- "message.send",
30
- "mobile-data",
31
- "no-disturb",
32
- "quiet-mode",
33
- "ringing-mode",
34
- "schedule.create",
35
- "schedule.delete",
36
- "schedule.search",
37
- "schedule.update",
38
- "screen-record",
39
- "vibration-mode",
40
- "volume.operate",
41
- "wlan",
42
- "bluetooth"
43
- ]
44
-
45
- /**
46
- * 配置管理器类
47
- */
48
- export class ConfigManager {
49
- /**
50
- * 加载完整配置
51
- */
52
- loadConfig(): OpenClawConfig {
53
- try {
54
- const runtime = getYoyoRuntime();
55
- return runtime.config.loadConfig();
56
- } catch (error) {
57
- throw new Error(
58
- `Failed to load config: ${error instanceof Error ? error.message : String(error)
59
- }`
60
- );
61
- }
62
- }
63
-
64
- /**
65
- * 保存完整配置
66
- */
67
- async saveConfig(config: OpenClawConfig): Promise<void> {
68
- try {
69
- const runtime = getYoyoRuntime();
70
- await runtime.config.writeConfigFile(config);
71
- } catch (error) {
72
- throw new Error(
73
- `Failed to save config: ${error instanceof Error ? error.message : String(error)
74
- }`
75
- );
76
- }
77
- }
78
-
79
- /**
80
- * 获取 Gateway 认证配置
81
- */
82
- getGatewayAuthConfig(): GatewayAuthConfig | undefined {
83
- try {
84
- const config = this.loadConfig();
85
- const authConfig = config.gateway?.auth;
86
-
87
- if (!authConfig) {
88
- return undefined;
89
- }
90
-
91
- const result: GatewayAuthConfig = {};
92
-
93
- if (authConfig.token) {
94
- result.token = authConfig.token;
95
- }
96
-
97
- if (authConfig.password) {
98
- result.password = authConfig.password;
99
- }
100
-
101
- // 如果没有任何认证信息,返回 undefined
102
- if (Object.keys(result).length === 0) {
103
- return undefined;
104
- }
105
-
106
- return result;
107
- } catch (error) {
108
- console.error(
109
- `[claw-configs] Failed to read gateway auth config: ${error}`
110
- );
111
- return undefined;
112
- }
113
- }
114
-
115
- /**
116
- * 获取 Gateway 端口配置
117
- */
118
- getGatewayPort(): number {
119
- try {
120
- const config = this.loadConfig();
121
- const port = config.gateway?.port;
122
- return port ?? 18789;
123
- } catch (error) {
124
- console.error(
125
- `[claw-configs] Failed to read gateway port config: ${error}`
126
- );
127
- return 18789;
128
- }
129
- }
130
-
131
- /**
132
- * 获取用户配置
133
- */
134
- getUserConfig(): UserConfig | undefined {
135
- try {
136
- const config = this.loadConfig();
137
- const userConfig = config.plugins?.entries?.[PLUGIN_YOYO_ID]?.config
138
- ?.user as UserConfig | undefined;
139
- return userConfig;
140
- } catch (error) {
141
- console.error(`[claw-configs] Failed to read user config: ${error}`);
142
- return undefined;
143
- }
144
- }
145
-
146
- /**
147
- * 获取运行环境配置
148
- */
149
- getEnv(): "test" | "production" {
150
- try {
151
- const config = this.loadConfig();
152
- const env = config.plugins?.entries?.[PLUGIN_YOYO_ID]?.config?.env as
153
- | "test"
154
- | "production"
155
- | undefined;
156
- return env || "production";
157
- } catch (error) {
158
- console.error(`[claw-configs] Failed to read env config: ${error}`);
159
- return "production";
160
- }
161
- }
162
-
163
- /**
164
- * 获取灰度标签配置
165
- */
166
- getGrayTag(): string | undefined {
167
- try {
168
- const config = this.loadConfig();
169
- const grayTag = config.plugins?.entries?.[PLUGIN_YOYO_ID]?.config?.gray as
170
- | string
171
- | undefined;
172
- return grayTag;
173
- } catch (error) {
174
- console.error(`[claw-configs] Failed to read gray tag config: ${error}`);
175
- return undefined;
176
- }
177
- }
178
-
179
- /**
180
- * 更新运行环境配置
181
- */
182
- async updateEnv(env: "test" | "production"): Promise<void> {
183
- try {
184
- const currentConfig = this.loadConfig();
185
-
186
- const updatedConfig: OpenClawConfig = {
187
- ...currentConfig,
188
- plugins: {
189
- ...currentConfig.plugins,
190
- entries: {
191
- ...currentConfig.plugins?.entries,
192
- [PLUGIN_YOYO_ID]: {
193
- ...currentConfig.plugins?.entries?.[PLUGIN_YOYO_ID],
194
- enabled: true,
195
- config: {
196
- ...currentConfig.plugins?.entries?.[PLUGIN_YOYO_ID]?.config,
197
- env,
198
- },
199
- },
200
- },
201
- },
202
- };
203
-
204
- await this.saveConfig(updatedConfig);
205
- } catch (error) {
206
- throw new Error(
207
- `Failed to update env config: ${error instanceof Error ? error.message : String(error)
208
- }`
209
- );
210
- }
211
- }
212
-
213
- /**
214
- * 更新灰度标签配置
215
- */
216
- async updateGrayTag(grayTag: string | undefined): Promise<void> {
217
- try {
218
- const currentConfig = this.loadConfig();
219
-
220
- const updatedConfig: OpenClawConfig = {
221
- ...currentConfig,
222
- plugins: {
223
- ...currentConfig.plugins,
224
- entries: {
225
- ...currentConfig.plugins?.entries,
226
- [PLUGIN_YOYO_ID]: {
227
- ...currentConfig.plugins?.entries?.[PLUGIN_YOYO_ID],
228
- enabled: true,
229
- config: {
230
- ...currentConfig.plugins?.entries?.[PLUGIN_YOYO_ID]?.config,
231
- ...(grayTag && { gray: grayTag }),
232
- },
233
- },
234
- },
235
- },
236
- };
237
-
238
- await this.saveConfig(updatedConfig);
239
- } catch (error) {
240
- throw new Error(
241
- `Failed to update gray tag config: ${error instanceof Error ? error.message : String(error)
242
- }`
243
- );
244
- }
245
- }
246
-
247
- /**
248
- * 更新用户配置
249
- */
250
- async updateUserConfig(userConfig: UserConfig): Promise<void> {
251
- try {
252
- const currentConfig = this.loadConfig();
253
-
254
- const updatedConfig: OpenClawConfig = {
255
- ...currentConfig,
256
- plugins: {
257
- ...currentConfig.plugins,
258
- entries: {
259
- ...currentConfig.plugins?.entries,
260
- [PLUGIN_YOYO_ID]: {
261
- ...currentConfig.plugins?.entries?.[PLUGIN_YOYO_ID],
262
- enabled: true,
263
- config: {
264
- ...currentConfig.plugins?.entries?.[PLUGIN_YOYO_ID]?.config,
265
- user: userConfig,
266
- },
267
- },
268
- },
269
- },
270
- };
271
-
272
- await this.saveConfig(updatedConfig);
273
- } catch (error) {
274
- throw new Error(
275
- `Failed to update user config: ${error instanceof Error ? error.message : String(error)
276
- }`
277
- );
278
- }
279
- }
280
-
281
- /**
282
- * 清除用户配置
283
- */
284
- async clearUserConfig(): Promise<void> {
285
- try {
286
- const currentConfig = this.loadConfig();
287
-
288
- const updatedConfig: OpenClawConfig = {
289
- ...currentConfig,
290
- plugins: {
291
- ...currentConfig.plugins,
292
- entries: {
293
- ...currentConfig.plugins?.entries,
294
- [PLUGIN_YOYO_ID]: {
295
- ...currentConfig.plugins?.entries?.[PLUGIN_YOYO_ID],
296
- config: {
297
- ...currentConfig.plugins?.entries?.[PLUGIN_YOYO_ID]?.config,
298
- user: undefined,
299
- },
300
- },
301
- },
302
- },
303
- };
304
-
305
- await this.saveConfig(updatedConfig);
306
- } catch (error) {
307
- throw new Error(
308
- `Failed to clear user config: ${error instanceof Error ? error.message : String(error)
309
- }`
310
- );
311
- }
312
- }
313
-
314
- /**
315
- * 初始化插件配置 - 统一处理插件和命令配置
316
- */
317
- async initializePluginConfig(pluginId: string): Promise<void> {
318
- try {
319
- const currentConfig = this.loadConfig();
320
-
321
- // 处理 plugins.allow
322
- const currentAllow = currentConfig.plugins?.allow || [];
323
- const updatedAllow = currentAllow.includes(pluginId)
324
- ? currentAllow
325
- : [...currentAllow, pluginId];
326
-
327
- // 处理 gateway.nodes.allowCommands
328
- const currentAllowCommands =
329
- currentConfig.gateway?.nodes?.allowCommands || [];
330
- const mergedCommands = Array.from(
331
- new Set([...currentAllowCommands, ...YOYO_ALLOW_COMMANDS])
332
- );
333
-
334
- // 处理 env 默认值(仅在未设置时设置)
335
- const currentEnv =
336
- currentConfig.plugins?.entries?.[pluginId]?.config?.env;
337
- const shouldSetEnv = !isBetaVersion() || !currentEnv;
338
- const defaultEnv = isBetaVersion() ? "test" : "production";
339
-
340
- // 构建插件配置
341
- const pluginConfig =
342
- currentConfig.plugins?.entries?.[pluginId]?.config || {};
343
- const updatedPluginConfig = shouldSetEnv
344
- ? { ...pluginConfig, env: defaultEnv }
345
- : pluginConfig;
346
-
347
- // 检测并重命名包含"minimax"的provider
348
- const renameMap = detectProvidersToRename(currentConfig);
349
- if (Object.keys(renameMap).length > 0) {
350
- console.log(
351
- `[claw-configs] Found ${Object.keys(renameMap).length} providers to rename:`,
352
- Object.entries(renameMap).map(([old, newName]) => `${old} -> ${newName}`).join(", ")
353
- );
354
- }
355
-
356
- // 一次性更新所有配置(包括provider重命名)
357
- let updatedConfig: OpenClawConfig = {
358
- ...currentConfig,
359
- plugins: {
360
- ...currentConfig.plugins,
361
- allow: updatedAllow,
362
- entries: {
363
- ...currentConfig.plugins?.entries,
364
- [pluginId]: {
365
- ...currentConfig.plugins?.entries?.[pluginId],
366
- enabled: true,
367
- config: updatedPluginConfig,
368
- },
369
- },
370
- },
371
- gateway: {
372
- ...currentConfig.gateway,
373
- nodes: {
374
- ...currentConfig.gateway?.nodes,
375
- allowCommands: mergedCommands,
376
- },
377
- },
378
- };
379
-
380
- // 如果需要重命名provider,更新所有引用
381
- if (Object.keys(renameMap).length > 0) {
382
- updatedConfig = updateProviderReferences(updatedConfig, renameMap);
383
- console.log("[claw-configs] Provider renaming completed");
384
- }
385
-
386
- await this.saveConfig(updatedConfig);
387
- } catch (error) {
388
- throw new Error(
389
- `failed to initialize plugin config: ${error instanceof Error ? error.message : String(error)
390
- }`
391
- );
392
- }
393
- }
394
- }
395
-
396
- /**
397
- * 配置管理器单例
398
- */
399
- let configManagerInstance: ConfigManager | null = null;
400
-
401
- /**
402
- * 获取配置管理器实例
403
- */
404
- export function getConfigManager(): ConfigManager {
405
- if (!configManagerInstance) {
406
- configManagerInstance = new ConfigManager();
407
- }
408
- return configManagerInstance;
409
- }
1
+ /**
2
+ * 配置管理器 - 统一管理 openclaw 配置文件的读写
3
+ */
4
+
5
+ import type { OpenClawConfig } from "openclaw/plugin-sdk";
6
+ import { getYoyoRuntime } from "../../runtime.js";
7
+ import { isBetaVersion } from "../../utils/version.js";
8
+ import type { GatewayAuthConfig, UserConfig } from "./types.js";
9
+ import { detectProvidersToRename, updateProviderReferences } from "./provider.js";
10
+
11
+ const PLUGIN_YOYO_ID = "yoyo";
12
+ const YOYO_ALLOW_COMMANDS = [
13
+ "alarm.create",
14
+ "alarm.delete",
15
+ "alarm.disable",
16
+ "alarm.enable",
17
+ "alarm.query",
18
+ "alarm.update",
19
+ "app.close",
20
+ "app.open",
21
+ "call.phone",
22
+ "call.search",
23
+ "capture-screenshot",
24
+ "contact.search",
25
+ "file-upload",
26
+ "hotspot",
27
+ "local-search",
28
+ "message.search",
29
+ "message.send",
30
+ "mobile-data",
31
+ "no-disturb",
32
+ "quiet-mode",
33
+ "ringing-mode",
34
+ "schedule.create",
35
+ "schedule.delete",
36
+ "schedule.search",
37
+ "schedule.update",
38
+ "screen-record",
39
+ "vibration-mode",
40
+ "volume.operate",
41
+ "wlan",
42
+ "bluetooth"
43
+ ]
44
+
45
+ /**
46
+ * 配置管理器类
47
+ */
48
+ export class ConfigManager {
49
+ /**
50
+ * 加载完整配置
51
+ */
52
+ loadConfig(): OpenClawConfig {
53
+ try {
54
+ const runtime = getYoyoRuntime();
55
+ return runtime.config.loadConfig();
56
+ } catch (error) {
57
+ throw new Error(
58
+ `Failed to load config: ${error instanceof Error ? error.message : String(error)
59
+ }`
60
+ );
61
+ }
62
+ }
63
+
64
+ /**
65
+ * 保存完整配置
66
+ */
67
+ async saveConfig(config: OpenClawConfig): Promise<void> {
68
+ try {
69
+ const runtime = getYoyoRuntime();
70
+ await runtime.config.writeConfigFile(config);
71
+ } catch (error) {
72
+ throw new Error(
73
+ `Failed to save config: ${error instanceof Error ? error.message : String(error)
74
+ }`
75
+ );
76
+ }
77
+ }
78
+
79
+ /**
80
+ * 获取 Gateway 认证配置
81
+ */
82
+ getGatewayAuthConfig(): GatewayAuthConfig | undefined {
83
+ try {
84
+ const config = this.loadConfig();
85
+ const authConfig = config.gateway?.auth;
86
+
87
+ if (!authConfig) {
88
+ return undefined;
89
+ }
90
+
91
+ const result: GatewayAuthConfig = {};
92
+
93
+ if (authConfig.token) {
94
+ result.token = authConfig.token;
95
+ }
96
+
97
+ if (authConfig.password) {
98
+ result.password = authConfig.password;
99
+ }
100
+
101
+ // 如果没有任何认证信息,返回 undefined
102
+ if (Object.keys(result).length === 0) {
103
+ return undefined;
104
+ }
105
+
106
+ return result;
107
+ } catch (error) {
108
+ console.error(
109
+ `[claw-configs] Failed to read gateway auth config: ${error}`
110
+ );
111
+ return undefined;
112
+ }
113
+ }
114
+
115
+ /**
116
+ * 获取 Gateway 端口配置
117
+ */
118
+ getGatewayPort(): number {
119
+ try {
120
+ const config = this.loadConfig();
121
+ const port = config.gateway?.port;
122
+ return port ?? 18789;
123
+ } catch (error) {
124
+ console.error(
125
+ `[claw-configs] Failed to read gateway port config: ${error}`
126
+ );
127
+ return 18789;
128
+ }
129
+ }
130
+
131
+ /**
132
+ * 获取用户配置
133
+ */
134
+ getUserConfig(): UserConfig | undefined {
135
+ try {
136
+ const config = this.loadConfig();
137
+ const userConfig = config.plugins?.entries?.[PLUGIN_YOYO_ID]?.config
138
+ ?.user as UserConfig | undefined;
139
+ return userConfig;
140
+ } catch (error) {
141
+ console.error(`[claw-configs] Failed to read user config: ${error}`);
142
+ return undefined;
143
+ }
144
+ }
145
+
146
+ /**
147
+ * 获取运行环境配置
148
+ */
149
+ getEnv(): "test" | "production" {
150
+ try {
151
+ const config = this.loadConfig();
152
+ const env = config.plugins?.entries?.[PLUGIN_YOYO_ID]?.config?.env as
153
+ | "test"
154
+ | "production"
155
+ | undefined;
156
+ return env || "production";
157
+ } catch (error) {
158
+ console.error(`[claw-configs] Failed to read env config: ${error}`);
159
+ return "production";
160
+ }
161
+ }
162
+
163
+ /**
164
+ * 获取灰度标签配置
165
+ */
166
+ getGrayTag(): string | undefined {
167
+ try {
168
+ const config = this.loadConfig();
169
+ const grayTag = config.plugins?.entries?.[PLUGIN_YOYO_ID]?.config?.gray as
170
+ | string
171
+ | undefined;
172
+ return grayTag;
173
+ } catch (error) {
174
+ console.error(`[claw-configs] Failed to read gray tag config: ${error}`);
175
+ return undefined;
176
+ }
177
+ }
178
+
179
+ /**
180
+ * 更新运行环境配置
181
+ */
182
+ async updateEnv(env: "test" | "production"): Promise<void> {
183
+ try {
184
+ const currentConfig = this.loadConfig();
185
+
186
+ const updatedConfig: OpenClawConfig = {
187
+ ...currentConfig,
188
+ plugins: {
189
+ ...currentConfig.plugins,
190
+ entries: {
191
+ ...currentConfig.plugins?.entries,
192
+ [PLUGIN_YOYO_ID]: {
193
+ ...currentConfig.plugins?.entries?.[PLUGIN_YOYO_ID],
194
+ enabled: true,
195
+ config: {
196
+ ...currentConfig.plugins?.entries?.[PLUGIN_YOYO_ID]?.config,
197
+ env,
198
+ },
199
+ },
200
+ },
201
+ },
202
+ };
203
+
204
+ await this.saveConfig(updatedConfig);
205
+ } catch (error) {
206
+ throw new Error(
207
+ `Failed to update env config: ${error instanceof Error ? error.message : String(error)
208
+ }`
209
+ );
210
+ }
211
+ }
212
+
213
+ /**
214
+ * 更新灰度标签配置
215
+ */
216
+ async updateGrayTag(grayTag: string | undefined): Promise<void> {
217
+ try {
218
+ const currentConfig = this.loadConfig();
219
+
220
+ const updatedConfig: OpenClawConfig = {
221
+ ...currentConfig,
222
+ plugins: {
223
+ ...currentConfig.plugins,
224
+ entries: {
225
+ ...currentConfig.plugins?.entries,
226
+ [PLUGIN_YOYO_ID]: {
227
+ ...currentConfig.plugins?.entries?.[PLUGIN_YOYO_ID],
228
+ enabled: true,
229
+ config: {
230
+ ...currentConfig.plugins?.entries?.[PLUGIN_YOYO_ID]?.config,
231
+ ...(grayTag && { gray: grayTag }),
232
+ },
233
+ },
234
+ },
235
+ },
236
+ };
237
+
238
+ await this.saveConfig(updatedConfig);
239
+ } catch (error) {
240
+ throw new Error(
241
+ `Failed to update gray tag config: ${error instanceof Error ? error.message : String(error)
242
+ }`
243
+ );
244
+ }
245
+ }
246
+
247
+ /**
248
+ * 更新用户配置
249
+ */
250
+ async updateUserConfig(userConfig: UserConfig): Promise<void> {
251
+ try {
252
+ const currentConfig = this.loadConfig();
253
+
254
+ const updatedConfig: OpenClawConfig = {
255
+ ...currentConfig,
256
+ plugins: {
257
+ ...currentConfig.plugins,
258
+ entries: {
259
+ ...currentConfig.plugins?.entries,
260
+ [PLUGIN_YOYO_ID]: {
261
+ ...currentConfig.plugins?.entries?.[PLUGIN_YOYO_ID],
262
+ enabled: true,
263
+ config: {
264
+ ...currentConfig.plugins?.entries?.[PLUGIN_YOYO_ID]?.config,
265
+ user: userConfig,
266
+ },
267
+ },
268
+ },
269
+ },
270
+ };
271
+
272
+ await this.saveConfig(updatedConfig);
273
+ } catch (error) {
274
+ throw new Error(
275
+ `Failed to update user config: ${error instanceof Error ? error.message : String(error)
276
+ }`
277
+ );
278
+ }
279
+ }
280
+
281
+ /**
282
+ * 清除用户配置
283
+ */
284
+ async clearUserConfig(): Promise<void> {
285
+ try {
286
+ const currentConfig = this.loadConfig();
287
+
288
+ const updatedConfig: OpenClawConfig = {
289
+ ...currentConfig,
290
+ plugins: {
291
+ ...currentConfig.plugins,
292
+ entries: {
293
+ ...currentConfig.plugins?.entries,
294
+ [PLUGIN_YOYO_ID]: {
295
+ ...currentConfig.plugins?.entries?.[PLUGIN_YOYO_ID],
296
+ config: {
297
+ ...currentConfig.plugins?.entries?.[PLUGIN_YOYO_ID]?.config,
298
+ user: undefined,
299
+ },
300
+ },
301
+ },
302
+ },
303
+ };
304
+
305
+ await this.saveConfig(updatedConfig);
306
+ } catch (error) {
307
+ throw new Error(
308
+ `Failed to clear user config: ${error instanceof Error ? error.message : String(error)
309
+ }`
310
+ );
311
+ }
312
+ }
313
+
314
+ /**
315
+ * 初始化插件配置 - 统一处理插件和命令配置
316
+ */
317
+ async initializePluginConfig(pluginId: string): Promise<void> {
318
+ try {
319
+ const currentConfig = this.loadConfig();
320
+
321
+ // 处理 plugins.allow
322
+ const currentAllow = currentConfig.plugins?.allow || [];
323
+ const updatedAllow = currentAllow.includes(pluginId)
324
+ ? currentAllow
325
+ : [...currentAllow, pluginId];
326
+
327
+ // 处理 gateway.nodes.allowCommands
328
+ const currentAllowCommands =
329
+ currentConfig.gateway?.nodes?.allowCommands || [];
330
+ const mergedCommands = Array.from(
331
+ new Set([...currentAllowCommands, ...YOYO_ALLOW_COMMANDS])
332
+ );
333
+
334
+ // 处理 env 默认值(仅在未设置时设置)
335
+ const currentEnv =
336
+ currentConfig.plugins?.entries?.[pluginId]?.config?.env;
337
+ const shouldSetEnv = !isBetaVersion() || !currentEnv;
338
+ const defaultEnv = isBetaVersion() ? "test" : "production";
339
+
340
+ // 构建插件配置
341
+ const pluginConfig =
342
+ currentConfig.plugins?.entries?.[pluginId]?.config || {};
343
+ const updatedPluginConfig = shouldSetEnv
344
+ ? { ...pluginConfig, env: defaultEnv }
345
+ : pluginConfig;
346
+
347
+ // 检测并重命名包含"minimax"的provider
348
+ const renameMap = detectProvidersToRename(currentConfig);
349
+ if (Object.keys(renameMap).length > 0) {
350
+ console.log(
351
+ `[claw-configs] Found ${Object.keys(renameMap).length} providers to rename:`,
352
+ Object.entries(renameMap).map(([old, newName]) => `${old} -> ${newName}`).join(", ")
353
+ );
354
+ }
355
+
356
+ // 一次性更新所有配置(包括provider重命名)
357
+ let updatedConfig: OpenClawConfig = {
358
+ ...currentConfig,
359
+ plugins: {
360
+ ...currentConfig.plugins,
361
+ allow: updatedAllow,
362
+ entries: {
363
+ ...currentConfig.plugins?.entries,
364
+ [pluginId]: {
365
+ ...currentConfig.plugins?.entries?.[pluginId],
366
+ enabled: true,
367
+ config: updatedPluginConfig,
368
+ },
369
+ },
370
+ },
371
+ gateway: {
372
+ ...currentConfig.gateway,
373
+ nodes: {
374
+ ...currentConfig.gateway?.nodes,
375
+ allowCommands: mergedCommands,
376
+ },
377
+ },
378
+ };
379
+
380
+ // 如果需要重命名provider,更新所有引用
381
+ if (Object.keys(renameMap).length > 0) {
382
+ updatedConfig = updateProviderReferences(updatedConfig, renameMap);
383
+ console.log("[claw-configs] Provider renaming completed");
384
+ }
385
+
386
+ await this.saveConfig(updatedConfig);
387
+ } catch (error) {
388
+ throw new Error(
389
+ `failed to initialize plugin config: ${error instanceof Error ? error.message : String(error)
390
+ }`
391
+ );
392
+ }
393
+ }
394
+ }
395
+
396
+ /**
397
+ * 配置管理器单例
398
+ */
399
+ let configManagerInstance: ConfigManager | null = null;
400
+
401
+ /**
402
+ * 获取配置管理器实例
403
+ */
404
+ export function getConfigManager(): ConfigManager {
405
+ if (!configManagerInstance) {
406
+ configManagerInstance = new ConfigManager();
407
+ }
408
+ return configManagerInstance;
409
+ }