@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,394 +1,394 @@
1
- import type { OpenClawConfig } from "openclaw/plugin-sdk";
2
- import fs from "node:fs";
3
- import path from "node:path";
4
-
5
- /**
6
- * 检测需要改名的provider
7
- */
8
- export function detectProvidersToRename(config: OpenClawConfig): Record<string, string> {
9
- const renameMap: Record<string, string> = {};
10
-
11
- if (!config.models?.providers) {
12
- return renameMap;
13
- }
14
-
15
- const providers = Object.keys(config.models.providers);
16
-
17
- for (const provider of providers) {
18
- const lowerProvider = provider.trim().toLowerCase();
19
- if (lowerProvider.includes("minimax")) {
20
- // 使用下划线分隔:minimax -> mini_max, minimax-pro -> mini_max-pro
21
- const newName = lowerProvider.replace("minimax", "mini_max");
22
- renameMap[provider] = newName;
23
- }
24
- }
25
-
26
- return renameMap;
27
- }
28
-
29
- /**
30
- * 更新所有provider引用
31
- */
32
- export function updateProviderReferences(
33
- config: OpenClawConfig,
34
- renameMap: Record<string, string>
35
- ): OpenClawConfig {
36
- const updatedConfig = { ...config };
37
-
38
- // 1. 更新 models.providers 本身
39
- if (updatedConfig.models?.providers) {
40
- const newProviders: Record<string, any> = {};
41
- for (const [provider, providerConfig] of Object.entries(updatedConfig.models.providers)) {
42
- const newName = renameMap[provider];
43
- if (newName) {
44
- newProviders[newName] = providerConfig;
45
- } else {
46
- newProviders[provider] = providerConfig;
47
- }
48
- }
49
- updatedConfig.models = {
50
- ...updatedConfig.models,
51
- providers: newProviders,
52
- };
53
- }
54
-
55
- // 2. 更新 agents 配置
56
- if (updatedConfig.agents) {
57
- updatedConfig.agents = updateAgentsProviderReferences(
58
- updatedConfig.agents,
59
- renameMap
60
- );
61
- }
62
-
63
- // 3. 更新 auth.profiles 配置
64
- if (updatedConfig.auth?.profiles) {
65
- updatedConfig.auth = {
66
- ...updatedConfig.auth,
67
- profiles: updateAuthProfilesProviderReferences(
68
- updatedConfig.auth.profiles,
69
- renameMap
70
- ),
71
- };
72
-
73
- // 更新 auth.profiles 文件
74
- updateAuthProfilesFiles(renameMap);
75
- }
76
-
77
- return updatedConfig;
78
- }
79
-
80
- /**
81
- * 更新 agents 配置中的 provider 引用
82
- */
83
- function updateAgentsProviderReferences(
84
- agents: any,
85
- renameMap: Record<string, string>
86
- ): any {
87
- const updatedAgents = { ...agents };
88
-
89
- // 更新 defaults 配置
90
- if (updatedAgents.defaults) {
91
- updatedAgents.defaults = updateAgentDefaultsProviderReferences(
92
- updatedAgents.defaults,
93
- renameMap
94
- );
95
- }
96
-
97
- // 更新 list 配置
98
- if (updatedAgents.list) {
99
- updatedAgents.list = updatedAgents.list.map((agent: any) =>
100
- updateAgentConfigProviderReferences(agent, renameMap)
101
- );
102
- }
103
-
104
- return updatedAgents;
105
- }
106
-
107
- /**
108
- * 更新 agent defaults 配置中的 provider 引用
109
- */
110
- function updateAgentDefaultsProviderReferences(
111
- defaults: any,
112
- renameMap: Record<string, string>
113
- ): any {
114
- const updatedDefaults = { ...defaults };
115
-
116
- // 更新 model 配置
117
- if (updatedDefaults.model) {
118
- updatedDefaults.model = updateAgentModelConfig(
119
- updatedDefaults.model,
120
- renameMap
121
- );
122
- }
123
-
124
- // 更新 imageModel 配置
125
- if (updatedDefaults.imageModel) {
126
- updatedDefaults.imageModel = updateAgentModelConfig(
127
- updatedDefaults.imageModel,
128
- renameMap
129
- );
130
- }
131
-
132
- // 更新 pdfModel 配置
133
- if (updatedDefaults.pdfModel) {
134
- updatedDefaults.pdfModel = updateAgentModelConfig(
135
- updatedDefaults.pdfModel,
136
- renameMap
137
- );
138
- }
139
-
140
- // 更新 models 目录(key可能是"provider/model"格式)
141
- if (updatedDefaults.models) {
142
- const newModels: Record<string, any> = {};
143
- for (const [key, value] of Object.entries(updatedDefaults.models)) {
144
- const newKey = updateStringModelReference(key, renameMap);
145
- newModels[newKey] = value;
146
- }
147
- updatedDefaults.models = newModels;
148
- }
149
-
150
- // 更新 subagents.model 配置
151
- if (updatedDefaults.subagents?.model) {
152
- updatedDefaults.subagents = {
153
- ...updatedDefaults.subagents,
154
- model: updateAgentModelConfig(
155
- updatedDefaults.subagents.model,
156
- renameMap
157
- ),
158
- };
159
- }
160
-
161
- return updatedDefaults;
162
- }
163
-
164
- /**
165
- * 更新单个 agent 配置中的 provider 引用
166
- */
167
- function updateAgentConfigProviderReferences(
168
- agent: any,
169
- renameMap: Record<string, string>
170
- ): any {
171
- const updatedAgent = { ...agent };
172
-
173
- // 更新 model 配置
174
- if (updatedAgent.model) {
175
- updatedAgent.model = updateAgentModelConfig(
176
- updatedAgent.model,
177
- renameMap
178
- );
179
- }
180
-
181
- // 更新 subagents.model 配置
182
- if (updatedAgent.subagents?.model) {
183
- updatedAgent.subagents = {
184
- ...updatedAgent.subagents,
185
- model: updateAgentModelConfig(
186
- updatedAgent.subagents.model,
187
- renameMap
188
- ),
189
- };
190
- }
191
-
192
- return updatedAgent;
193
- }
194
-
195
- /**
196
- * 更新 AgentModelConfig 类型(可能是 string 或 {primary, fallbacks})
197
- */
198
- function updateAgentModelConfig(
199
- modelConfig: any,
200
- renameMap: Record<string, string>
201
- ): any {
202
- if (typeof modelConfig === "string") {
203
- return updateStringModelReference(modelConfig, renameMap);
204
- }
205
-
206
- if (typeof modelConfig === "object" && modelConfig !== null) {
207
- const updatedModelConfig = { ...modelConfig };
208
-
209
- if (updatedModelConfig.primary) {
210
- updatedModelConfig.primary = updateStringModelReference(
211
- updatedModelConfig.primary,
212
- renameMap
213
- );
214
- }
215
-
216
- if (updatedModelConfig.fallbacks && Array.isArray(updatedModelConfig.fallbacks)) {
217
- updatedModelConfig.fallbacks = updatedModelConfig.fallbacks.map((fallback: string) =>
218
- updateStringModelReference(fallback, renameMap)
219
- );
220
- }
221
-
222
- return updatedModelConfig;
223
- }
224
-
225
- return modelConfig;
226
- }
227
-
228
- /**
229
- * 更新 "provider/model" 格式的字符串
230
- */
231
- function updateStringModelReference(
232
- modelString: string,
233
- renameMap: Record<string, string>
234
- ): string {
235
- const parts = modelString.split("/");
236
- if (parts.length > 0) {
237
- const provider = parts[0];
238
- const newProvider = renameMap[provider];
239
- if (newProvider) {
240
- parts[0] = newProvider;
241
- return parts.join("/");
242
- }
243
- }
244
- return modelString;
245
- }
246
-
247
- /**
248
- * 更新 auth.profiles 配置中的 provider 引用
249
- */
250
- function updateAuthProfilesProviderReferences(
251
- profiles: Record<string, any>,
252
- renameMap: Record<string, string>
253
- ): Record<string, any> {
254
- const updatedProfiles: Record<string, any> = {};
255
-
256
- for (const [profileId, profileConfig] of Object.entries(profiles)) {
257
- const updatedProfile = { ...profileConfig };
258
- const provider = updatedProfile.provider;
259
- const newProvider = renameMap[provider];
260
- if (newProvider) {
261
- updatedProfile.provider = newProvider;
262
- }
263
- updatedProfiles[profileId] = updatedProfile;
264
- }
265
-
266
- return updatedProfiles;
267
- }
268
-
269
- /**
270
- * 解析用户主目录路径
271
- */
272
- function resolveHomePath(): string {
273
- if (process.platform === "win32") {
274
- return process.env.USERPROFILE || "";
275
- }
276
- return process.env.HOME || "";
277
- }
278
-
279
- /**
280
- * 获取所有 auth-profiles.json 文件路径
281
- */
282
- function getAuthProfilesFilePaths(stateDir?: string): string[] {
283
- const paths: string[] = [];
284
- const homePath = resolveHomePath();
285
- const baseDir = stateDir || path.join(homePath, ".openclaw");
286
-
287
- // 默认路径: ~/.openclaw/agents/main/agent/auth-profiles.json
288
- const defaultPath = path.join(baseDir, "agents", "main", "agent", "auth-profiles.json");
289
- if (fs.existsSync(defaultPath)) {
290
- paths.push(defaultPath);
291
- }
292
-
293
- // 扫描所有 agent 目录
294
- const agentsDir = path.join(baseDir, "agents");
295
- if (fs.existsSync(agentsDir)) {
296
- const agentDirs = fs.readdirSync(agentsDir, { withFileTypes: true });
297
- for (const agentDir of agentDirs) {
298
- if (agentDir.isDirectory()) {
299
- const agentAuthPath = path.join(agentsDir, agentDir.name, "agent", "auth-profiles.json");
300
- if (fs.existsSync(agentAuthPath) && !paths.includes(agentAuthPath)) {
301
- paths.push(agentAuthPath);
302
- }
303
- }
304
- }
305
- }
306
-
307
- return paths;
308
- }
309
-
310
- /**
311
- * 更新 auth-profiles.json 文件中的 provider 引用
312
- */
313
- export function updateAuthProfilesFiles(
314
- renameMap: Record<string, string>,
315
- stateDir?: string
316
- ): { updated: boolean; files: string[]; errors: string[] } {
317
- const filePaths = getAuthProfilesFilePaths(stateDir);
318
- const updatedFiles: string[] = [];
319
- const errors: string[] = [];
320
- let hasUpdates = false;
321
-
322
- for (const filePath of filePaths) {
323
- try {
324
- // 读取文件
325
- const content = fs.readFileSync(filePath, "utf-8");
326
- const store = JSON.parse(content);
327
-
328
- if (!store.profiles || typeof store.profiles !== "object") {
329
- continue;
330
- }
331
-
332
- let fileHasUpdates = false;
333
-
334
- // 更新 profiles 中的 provider
335
- for (const [profileId, credential] of Object.entries(store.profiles)) {
336
- const cred = credential as any;
337
- const provider = cred.provider;
338
- const newProvider = renameMap[provider];
339
- if (newProvider && provider !== newProvider) {
340
- cred.provider = newProvider;
341
- fileHasUpdates = true;
342
- }
343
- }
344
-
345
- // 更新 order 中的 provider key
346
- if (store.order && typeof store.order === "object") {
347
- const newOrder: Record<string, string[]> = {};
348
- for (const [provider, profileList] of Object.entries<string[]>(store.order)) {
349
- const newProvider = renameMap[provider];
350
- const targetProvider = newProvider || provider;
351
- newOrder[targetProvider] = profileList;
352
- if (newProvider && provider !== newProvider) {
353
- fileHasUpdates = true;
354
- }
355
- }
356
- if (fileHasUpdates) {
357
- store.order = newOrder;
358
- }
359
- }
360
-
361
- // 更新 lastGood 中的 provider key
362
- if (store.lastGood && typeof store.lastGood === "object") {
363
- const newLastGood: Record<string, string> = {};
364
- for (const [provider, profileId] of Object.entries<string>(store.lastGood)) {
365
- const newProvider = renameMap[provider];
366
- const targetProvider = newProvider || provider;
367
- newLastGood[targetProvider] = profileId;
368
- if (newProvider && provider !== newProvider) {
369
- fileHasUpdates = true;
370
- }
371
- }
372
- if (fileHasUpdates) {
373
- store.lastGood = newLastGood;
374
- }
375
- }
376
-
377
- // 如果有更新,保存文件
378
- if (fileHasUpdates) {
379
- fs.writeFileSync(filePath, JSON.stringify(store, null, 2) + "\n", "utf-8");
380
- updatedFiles.push(filePath);
381
- hasUpdates = true;
382
- }
383
- } catch (error) {
384
- const errorMsg = error instanceof Error ? error.message : String(error);
385
- errors.push(`${filePath}: ${errorMsg}`);
386
- }
387
- }
388
-
389
- return {
390
- updated: hasUpdates,
391
- files: updatedFiles,
392
- errors,
393
- };
394
- }
1
+ import type { OpenClawConfig } from "openclaw/plugin-sdk";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+
5
+ /**
6
+ * 检测需要改名的provider
7
+ */
8
+ export function detectProvidersToRename(config: OpenClawConfig): Record<string, string> {
9
+ const renameMap: Record<string, string> = {};
10
+
11
+ if (!config.models?.providers) {
12
+ return renameMap;
13
+ }
14
+
15
+ const providers = Object.keys(config.models.providers);
16
+
17
+ for (const provider of providers) {
18
+ const lowerProvider = provider.trim().toLowerCase();
19
+ if (lowerProvider.includes("minimax")) {
20
+ // 使用下划线分隔:minimax -> mini_max, minimax-pro -> mini_max-pro
21
+ const newName = lowerProvider.replace("minimax", "mini_max");
22
+ renameMap[provider] = newName;
23
+ }
24
+ }
25
+
26
+ return renameMap;
27
+ }
28
+
29
+ /**
30
+ * 更新所有provider引用
31
+ */
32
+ export function updateProviderReferences(
33
+ config: OpenClawConfig,
34
+ renameMap: Record<string, string>
35
+ ): OpenClawConfig {
36
+ const updatedConfig = { ...config };
37
+
38
+ // 1. 更新 models.providers 本身
39
+ if (updatedConfig.models?.providers) {
40
+ const newProviders: Record<string, any> = {};
41
+ for (const [provider, providerConfig] of Object.entries(updatedConfig.models.providers)) {
42
+ const newName = renameMap[provider];
43
+ if (newName) {
44
+ newProviders[newName] = providerConfig;
45
+ } else {
46
+ newProviders[provider] = providerConfig;
47
+ }
48
+ }
49
+ updatedConfig.models = {
50
+ ...updatedConfig.models,
51
+ providers: newProviders,
52
+ };
53
+ }
54
+
55
+ // 2. 更新 agents 配置
56
+ if (updatedConfig.agents) {
57
+ updatedConfig.agents = updateAgentsProviderReferences(
58
+ updatedConfig.agents,
59
+ renameMap
60
+ );
61
+ }
62
+
63
+ // 3. 更新 auth.profiles 配置
64
+ if (updatedConfig.auth?.profiles) {
65
+ updatedConfig.auth = {
66
+ ...updatedConfig.auth,
67
+ profiles: updateAuthProfilesProviderReferences(
68
+ updatedConfig.auth.profiles,
69
+ renameMap
70
+ ),
71
+ };
72
+
73
+ // 更新 auth.profiles 文件
74
+ updateAuthProfilesFiles(renameMap);
75
+ }
76
+
77
+ return updatedConfig;
78
+ }
79
+
80
+ /**
81
+ * 更新 agents 配置中的 provider 引用
82
+ */
83
+ function updateAgentsProviderReferences(
84
+ agents: any,
85
+ renameMap: Record<string, string>
86
+ ): any {
87
+ const updatedAgents = { ...agents };
88
+
89
+ // 更新 defaults 配置
90
+ if (updatedAgents.defaults) {
91
+ updatedAgents.defaults = updateAgentDefaultsProviderReferences(
92
+ updatedAgents.defaults,
93
+ renameMap
94
+ );
95
+ }
96
+
97
+ // 更新 list 配置
98
+ if (updatedAgents.list) {
99
+ updatedAgents.list = updatedAgents.list.map((agent: any) =>
100
+ updateAgentConfigProviderReferences(agent, renameMap)
101
+ );
102
+ }
103
+
104
+ return updatedAgents;
105
+ }
106
+
107
+ /**
108
+ * 更新 agent defaults 配置中的 provider 引用
109
+ */
110
+ function updateAgentDefaultsProviderReferences(
111
+ defaults: any,
112
+ renameMap: Record<string, string>
113
+ ): any {
114
+ const updatedDefaults = { ...defaults };
115
+
116
+ // 更新 model 配置
117
+ if (updatedDefaults.model) {
118
+ updatedDefaults.model = updateAgentModelConfig(
119
+ updatedDefaults.model,
120
+ renameMap
121
+ );
122
+ }
123
+
124
+ // 更新 imageModel 配置
125
+ if (updatedDefaults.imageModel) {
126
+ updatedDefaults.imageModel = updateAgentModelConfig(
127
+ updatedDefaults.imageModel,
128
+ renameMap
129
+ );
130
+ }
131
+
132
+ // 更新 pdfModel 配置
133
+ if (updatedDefaults.pdfModel) {
134
+ updatedDefaults.pdfModel = updateAgentModelConfig(
135
+ updatedDefaults.pdfModel,
136
+ renameMap
137
+ );
138
+ }
139
+
140
+ // 更新 models 目录(key可能是"provider/model"格式)
141
+ if (updatedDefaults.models) {
142
+ const newModels: Record<string, any> = {};
143
+ for (const [key, value] of Object.entries(updatedDefaults.models)) {
144
+ const newKey = updateStringModelReference(key, renameMap);
145
+ newModels[newKey] = value;
146
+ }
147
+ updatedDefaults.models = newModels;
148
+ }
149
+
150
+ // 更新 subagents.model 配置
151
+ if (updatedDefaults.subagents?.model) {
152
+ updatedDefaults.subagents = {
153
+ ...updatedDefaults.subagents,
154
+ model: updateAgentModelConfig(
155
+ updatedDefaults.subagents.model,
156
+ renameMap
157
+ ),
158
+ };
159
+ }
160
+
161
+ return updatedDefaults;
162
+ }
163
+
164
+ /**
165
+ * 更新单个 agent 配置中的 provider 引用
166
+ */
167
+ function updateAgentConfigProviderReferences(
168
+ agent: any,
169
+ renameMap: Record<string, string>
170
+ ): any {
171
+ const updatedAgent = { ...agent };
172
+
173
+ // 更新 model 配置
174
+ if (updatedAgent.model) {
175
+ updatedAgent.model = updateAgentModelConfig(
176
+ updatedAgent.model,
177
+ renameMap
178
+ );
179
+ }
180
+
181
+ // 更新 subagents.model 配置
182
+ if (updatedAgent.subagents?.model) {
183
+ updatedAgent.subagents = {
184
+ ...updatedAgent.subagents,
185
+ model: updateAgentModelConfig(
186
+ updatedAgent.subagents.model,
187
+ renameMap
188
+ ),
189
+ };
190
+ }
191
+
192
+ return updatedAgent;
193
+ }
194
+
195
+ /**
196
+ * 更新 AgentModelConfig 类型(可能是 string 或 {primary, fallbacks})
197
+ */
198
+ function updateAgentModelConfig(
199
+ modelConfig: any,
200
+ renameMap: Record<string, string>
201
+ ): any {
202
+ if (typeof modelConfig === "string") {
203
+ return updateStringModelReference(modelConfig, renameMap);
204
+ }
205
+
206
+ if (typeof modelConfig === "object" && modelConfig !== null) {
207
+ const updatedModelConfig = { ...modelConfig };
208
+
209
+ if (updatedModelConfig.primary) {
210
+ updatedModelConfig.primary = updateStringModelReference(
211
+ updatedModelConfig.primary,
212
+ renameMap
213
+ );
214
+ }
215
+
216
+ if (updatedModelConfig.fallbacks && Array.isArray(updatedModelConfig.fallbacks)) {
217
+ updatedModelConfig.fallbacks = updatedModelConfig.fallbacks.map((fallback: string) =>
218
+ updateStringModelReference(fallback, renameMap)
219
+ );
220
+ }
221
+
222
+ return updatedModelConfig;
223
+ }
224
+
225
+ return modelConfig;
226
+ }
227
+
228
+ /**
229
+ * 更新 "provider/model" 格式的字符串
230
+ */
231
+ function updateStringModelReference(
232
+ modelString: string,
233
+ renameMap: Record<string, string>
234
+ ): string {
235
+ const parts = modelString.split("/");
236
+ if (parts.length > 0) {
237
+ const provider = parts[0];
238
+ const newProvider = renameMap[provider];
239
+ if (newProvider) {
240
+ parts[0] = newProvider;
241
+ return parts.join("/");
242
+ }
243
+ }
244
+ return modelString;
245
+ }
246
+
247
+ /**
248
+ * 更新 auth.profiles 配置中的 provider 引用
249
+ */
250
+ function updateAuthProfilesProviderReferences(
251
+ profiles: Record<string, any>,
252
+ renameMap: Record<string, string>
253
+ ): Record<string, any> {
254
+ const updatedProfiles: Record<string, any> = {};
255
+
256
+ for (const [profileId, profileConfig] of Object.entries(profiles)) {
257
+ const updatedProfile = { ...profileConfig };
258
+ const provider = updatedProfile.provider;
259
+ const newProvider = renameMap[provider];
260
+ if (newProvider) {
261
+ updatedProfile.provider = newProvider;
262
+ }
263
+ updatedProfiles[profileId] = updatedProfile;
264
+ }
265
+
266
+ return updatedProfiles;
267
+ }
268
+
269
+ /**
270
+ * 解析用户主目录路径
271
+ */
272
+ function resolveHomePath(): string {
273
+ if (process.platform === "win32") {
274
+ return process.env.USERPROFILE || "";
275
+ }
276
+ return process.env.HOME || "";
277
+ }
278
+
279
+ /**
280
+ * 获取所有 auth-profiles.json 文件路径
281
+ */
282
+ function getAuthProfilesFilePaths(stateDir?: string): string[] {
283
+ const paths: string[] = [];
284
+ const homePath = resolveHomePath();
285
+ const baseDir = stateDir || path.join(homePath, ".openclaw");
286
+
287
+ // 默认路径: ~/.openclaw/agents/main/agent/auth-profiles.json
288
+ const defaultPath = path.join(baseDir, "agents", "main", "agent", "auth-profiles.json");
289
+ if (fs.existsSync(defaultPath)) {
290
+ paths.push(defaultPath);
291
+ }
292
+
293
+ // 扫描所有 agent 目录
294
+ const agentsDir = path.join(baseDir, "agents");
295
+ if (fs.existsSync(agentsDir)) {
296
+ const agentDirs = fs.readdirSync(agentsDir, { withFileTypes: true });
297
+ for (const agentDir of agentDirs) {
298
+ if (agentDir.isDirectory()) {
299
+ const agentAuthPath = path.join(agentsDir, agentDir.name, "agent", "auth-profiles.json");
300
+ if (fs.existsSync(agentAuthPath) && !paths.includes(agentAuthPath)) {
301
+ paths.push(agentAuthPath);
302
+ }
303
+ }
304
+ }
305
+ }
306
+
307
+ return paths;
308
+ }
309
+
310
+ /**
311
+ * 更新 auth-profiles.json 文件中的 provider 引用
312
+ */
313
+ export function updateAuthProfilesFiles(
314
+ renameMap: Record<string, string>,
315
+ stateDir?: string
316
+ ): { updated: boolean; files: string[]; errors: string[] } {
317
+ const filePaths = getAuthProfilesFilePaths(stateDir);
318
+ const updatedFiles: string[] = [];
319
+ const errors: string[] = [];
320
+ let hasUpdates = false;
321
+
322
+ for (const filePath of filePaths) {
323
+ try {
324
+ // 读取文件
325
+ const content = fs.readFileSync(filePath, "utf-8");
326
+ const store = JSON.parse(content);
327
+
328
+ if (!store.profiles || typeof store.profiles !== "object") {
329
+ continue;
330
+ }
331
+
332
+ let fileHasUpdates = false;
333
+
334
+ // 更新 profiles 中的 provider
335
+ for (const [profileId, credential] of Object.entries(store.profiles)) {
336
+ const cred = credential as any;
337
+ const provider = cred.provider;
338
+ const newProvider = renameMap[provider];
339
+ if (newProvider && provider !== newProvider) {
340
+ cred.provider = newProvider;
341
+ fileHasUpdates = true;
342
+ }
343
+ }
344
+
345
+ // 更新 order 中的 provider key
346
+ if (store.order && typeof store.order === "object") {
347
+ const newOrder: Record<string, string[]> = {};
348
+ for (const [provider, profileList] of Object.entries<string[]>(store.order)) {
349
+ const newProvider = renameMap[provider];
350
+ const targetProvider = newProvider || provider;
351
+ newOrder[targetProvider] = profileList;
352
+ if (newProvider && provider !== newProvider) {
353
+ fileHasUpdates = true;
354
+ }
355
+ }
356
+ if (fileHasUpdates) {
357
+ store.order = newOrder;
358
+ }
359
+ }
360
+
361
+ // 更新 lastGood 中的 provider key
362
+ if (store.lastGood && typeof store.lastGood === "object") {
363
+ const newLastGood: Record<string, string> = {};
364
+ for (const [provider, profileId] of Object.entries<string>(store.lastGood)) {
365
+ const newProvider = renameMap[provider];
366
+ const targetProvider = newProvider || provider;
367
+ newLastGood[targetProvider] = profileId;
368
+ if (newProvider && provider !== newProvider) {
369
+ fileHasUpdates = true;
370
+ }
371
+ }
372
+ if (fileHasUpdates) {
373
+ store.lastGood = newLastGood;
374
+ }
375
+ }
376
+
377
+ // 如果有更新,保存文件
378
+ if (fileHasUpdates) {
379
+ fs.writeFileSync(filePath, JSON.stringify(store, null, 2) + "\n", "utf-8");
380
+ updatedFiles.push(filePath);
381
+ hasUpdates = true;
382
+ }
383
+ } catch (error) {
384
+ const errorMsg = error instanceof Error ? error.message : String(error);
385
+ errors.push(`${filePath}: ${errorMsg}`);
386
+ }
387
+ }
388
+
389
+ return {
390
+ updated: hasUpdates,
391
+ files: updatedFiles,
392
+ errors,
393
+ };
394
+ }