@clinebot/core 0.0.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 (200) hide show
  1. package/README.md +88 -0
  2. package/dist/account/cline-account-service.d.ts +34 -0
  3. package/dist/account/index.d.ts +3 -0
  4. package/dist/account/rpc.d.ts +38 -0
  5. package/dist/account/types.d.ts +74 -0
  6. package/dist/agents/agent-config-loader.d.ts +18 -0
  7. package/dist/agents/agent-config-parser.d.ts +25 -0
  8. package/dist/agents/hooks-config-loader.d.ts +23 -0
  9. package/dist/agents/index.d.ts +11 -0
  10. package/dist/agents/plugin-config-loader.d.ts +22 -0
  11. package/dist/agents/plugin-loader.d.ts +9 -0
  12. package/dist/agents/plugin-sandbox.d.ts +12 -0
  13. package/dist/agents/unified-config-file-watcher.d.ts +77 -0
  14. package/dist/agents/user-instruction-config-loader.d.ts +63 -0
  15. package/dist/auth/client.d.ts +11 -0
  16. package/dist/auth/cline.d.ts +41 -0
  17. package/dist/auth/codex.d.ts +39 -0
  18. package/dist/auth/oca.d.ts +22 -0
  19. package/dist/auth/server.d.ts +22 -0
  20. package/dist/auth/types.d.ts +72 -0
  21. package/dist/auth/utils.d.ts +32 -0
  22. package/dist/chat/chat-schema.d.ts +145 -0
  23. package/dist/default-tools/constants.d.ts +23 -0
  24. package/dist/default-tools/definitions.d.ts +96 -0
  25. package/dist/default-tools/executors/apply-patch-parser.d.ts +68 -0
  26. package/dist/default-tools/executors/apply-patch.d.ts +26 -0
  27. package/dist/default-tools/executors/bash.d.ts +49 -0
  28. package/dist/default-tools/executors/editor.d.ts +31 -0
  29. package/dist/default-tools/executors/file-read.d.ts +40 -0
  30. package/dist/default-tools/executors/index.d.ts +44 -0
  31. package/dist/default-tools/executors/search.d.ts +50 -0
  32. package/dist/default-tools/executors/web-fetch.d.ts +58 -0
  33. package/dist/default-tools/index.d.ts +57 -0
  34. package/dist/default-tools/presets.d.ts +124 -0
  35. package/dist/default-tools/schemas.d.ts +121 -0
  36. package/dist/default-tools/types.d.ts +237 -0
  37. package/dist/index.d.ts +23 -0
  38. package/dist/index.js +220 -0
  39. package/dist/input/file-indexer.d.ts +5 -0
  40. package/dist/input/index.d.ts +4 -0
  41. package/dist/input/mention-enricher.d.ts +12 -0
  42. package/dist/mcp/config-loader.d.ts +15 -0
  43. package/dist/mcp/index.d.ts +4 -0
  44. package/dist/mcp/manager.d.ts +24 -0
  45. package/dist/mcp/types.d.ts +66 -0
  46. package/dist/runtime/hook-file-hooks.d.ts +18 -0
  47. package/dist/runtime/rules.d.ts +5 -0
  48. package/dist/runtime/runtime-builder.d.ts +5 -0
  49. package/dist/runtime/sandbox/subprocess-sandbox.d.ts +19 -0
  50. package/dist/runtime/session-runtime.d.ts +36 -0
  51. package/dist/runtime/tool-approval.d.ts +9 -0
  52. package/dist/runtime/workflows.d.ts +13 -0
  53. package/dist/server/index.d.ts +47 -0
  54. package/dist/server/index.js +641 -0
  55. package/dist/session/default-session-manager.d.ts +77 -0
  56. package/dist/session/rpc-session-service.d.ts +12 -0
  57. package/dist/session/runtime-oauth-token-manager.d.ts +28 -0
  58. package/dist/session/session-artifacts.d.ts +19 -0
  59. package/dist/session/session-graph.d.ts +15 -0
  60. package/dist/session/session-host.d.ts +21 -0
  61. package/dist/session/session-manager.d.ts +50 -0
  62. package/dist/session/session-manifest.d.ts +30 -0
  63. package/dist/session/session-service.d.ts +113 -0
  64. package/dist/session/sqlite-rpc-session-backend.d.ts +30 -0
  65. package/dist/session/unified-session-persistence-service.d.ts +93 -0
  66. package/dist/session/workspace-manager.d.ts +28 -0
  67. package/dist/session/workspace-manifest.d.ts +25 -0
  68. package/dist/storage/provider-settings-legacy-migration.d.ts +13 -0
  69. package/dist/storage/provider-settings-manager.d.ts +20 -0
  70. package/dist/storage/sqlite-session-store.d.ts +29 -0
  71. package/dist/storage/sqlite-team-store.d.ts +31 -0
  72. package/dist/storage/team-store.d.ts +2 -0
  73. package/dist/team/index.d.ts +1 -0
  74. package/dist/team/projections.d.ts +8 -0
  75. package/dist/types/common.d.ts +10 -0
  76. package/dist/types/config.d.ts +37 -0
  77. package/dist/types/events.d.ts +54 -0
  78. package/dist/types/provider-settings.d.ts +20 -0
  79. package/dist/types/sessions.d.ts +9 -0
  80. package/dist/types/storage.d.ts +37 -0
  81. package/dist/types/workspace.d.ts +7 -0
  82. package/dist/types.d.ts +26 -0
  83. package/package.json +63 -0
  84. package/src/account/cline-account-service.test.ts +101 -0
  85. package/src/account/cline-account-service.ts +267 -0
  86. package/src/account/index.ts +20 -0
  87. package/src/account/rpc.test.ts +62 -0
  88. package/src/account/rpc.ts +172 -0
  89. package/src/account/types.ts +80 -0
  90. package/src/agents/agent-config-loader.test.ts +234 -0
  91. package/src/agents/agent-config-loader.ts +107 -0
  92. package/src/agents/agent-config-parser.ts +191 -0
  93. package/src/agents/hooks-config-loader.ts +97 -0
  94. package/src/agents/index.ts +84 -0
  95. package/src/agents/plugin-config-loader.test.ts +91 -0
  96. package/src/agents/plugin-config-loader.ts +160 -0
  97. package/src/agents/plugin-loader.test.ts +102 -0
  98. package/src/agents/plugin-loader.ts +105 -0
  99. package/src/agents/plugin-sandbox.test.ts +120 -0
  100. package/src/agents/plugin-sandbox.ts +471 -0
  101. package/src/agents/unified-config-file-watcher.test.ts +196 -0
  102. package/src/agents/unified-config-file-watcher.ts +483 -0
  103. package/src/agents/user-instruction-config-loader.test.ts +158 -0
  104. package/src/agents/user-instruction-config-loader.ts +438 -0
  105. package/src/auth/client.test.ts +40 -0
  106. package/src/auth/client.ts +25 -0
  107. package/src/auth/cline.test.ts +130 -0
  108. package/src/auth/cline.ts +414 -0
  109. package/src/auth/codex.test.ts +170 -0
  110. package/src/auth/codex.ts +466 -0
  111. package/src/auth/oca.test.ts +215 -0
  112. package/src/auth/oca.ts +546 -0
  113. package/src/auth/server.ts +216 -0
  114. package/src/auth/types.ts +78 -0
  115. package/src/auth/utils.test.ts +128 -0
  116. package/src/auth/utils.ts +247 -0
  117. package/src/chat/chat-schema.ts +82 -0
  118. package/src/default-tools/constants.ts +35 -0
  119. package/src/default-tools/definitions.test.ts +233 -0
  120. package/src/default-tools/definitions.ts +632 -0
  121. package/src/default-tools/executors/apply-patch-parser.ts +520 -0
  122. package/src/default-tools/executors/apply-patch.ts +359 -0
  123. package/src/default-tools/executors/bash.ts +205 -0
  124. package/src/default-tools/executors/editor.ts +231 -0
  125. package/src/default-tools/executors/file-read.test.ts +25 -0
  126. package/src/default-tools/executors/file-read.ts +94 -0
  127. package/src/default-tools/executors/index.ts +75 -0
  128. package/src/default-tools/executors/search.ts +278 -0
  129. package/src/default-tools/executors/web-fetch.ts +259 -0
  130. package/src/default-tools/index.ts +161 -0
  131. package/src/default-tools/presets.test.ts +63 -0
  132. package/src/default-tools/presets.ts +168 -0
  133. package/src/default-tools/schemas.ts +228 -0
  134. package/src/default-tools/types.ts +324 -0
  135. package/src/index.ts +119 -0
  136. package/src/input/file-indexer.d.ts +11 -0
  137. package/src/input/file-indexer.test.ts +87 -0
  138. package/src/input/file-indexer.ts +280 -0
  139. package/src/input/index.ts +7 -0
  140. package/src/input/mention-enricher.test.ts +82 -0
  141. package/src/input/mention-enricher.ts +119 -0
  142. package/src/mcp/config-loader.test.ts +238 -0
  143. package/src/mcp/config-loader.ts +219 -0
  144. package/src/mcp/index.ts +26 -0
  145. package/src/mcp/manager.test.ts +106 -0
  146. package/src/mcp/manager.ts +262 -0
  147. package/src/mcp/types.ts +88 -0
  148. package/src/runtime/hook-file-hooks.test.ts +106 -0
  149. package/src/runtime/hook-file-hooks.ts +736 -0
  150. package/src/runtime/index.ts +27 -0
  151. package/src/runtime/rules.ts +34 -0
  152. package/src/runtime/runtime-builder.team-persistence.test.ts +203 -0
  153. package/src/runtime/runtime-builder.test.ts +215 -0
  154. package/src/runtime/runtime-builder.ts +515 -0
  155. package/src/runtime/runtime-parity.test.ts +132 -0
  156. package/src/runtime/sandbox/subprocess-sandbox.ts +207 -0
  157. package/src/runtime/session-runtime.ts +44 -0
  158. package/src/runtime/tool-approval.ts +104 -0
  159. package/src/runtime/workflows.test.ts +119 -0
  160. package/src/runtime/workflows.ts +54 -0
  161. package/src/server/index.ts +282 -0
  162. package/src/session/default-session-manager.e2e.test.ts +354 -0
  163. package/src/session/default-session-manager.test.ts +816 -0
  164. package/src/session/default-session-manager.ts +1286 -0
  165. package/src/session/index.ts +37 -0
  166. package/src/session/rpc-session-service.ts +189 -0
  167. package/src/session/runtime-oauth-token-manager.test.ts +137 -0
  168. package/src/session/runtime-oauth-token-manager.ts +265 -0
  169. package/src/session/session-artifacts.ts +106 -0
  170. package/src/session/session-graph.ts +90 -0
  171. package/src/session/session-host.ts +190 -0
  172. package/src/session/session-manager.ts +56 -0
  173. package/src/session/session-manifest.ts +29 -0
  174. package/src/session/session-service.team-persistence.test.ts +48 -0
  175. package/src/session/session-service.ts +610 -0
  176. package/src/session/sqlite-rpc-session-backend.ts +303 -0
  177. package/src/session/unified-session-persistence-service.ts +781 -0
  178. package/src/session/workspace-manager.ts +98 -0
  179. package/src/session/workspace-manifest.ts +100 -0
  180. package/src/storage/artifact-store.ts +1 -0
  181. package/src/storage/index.ts +11 -0
  182. package/src/storage/provider-settings-legacy-migration.test.ts +175 -0
  183. package/src/storage/provider-settings-legacy-migration.ts +637 -0
  184. package/src/storage/provider-settings-manager.test.ts +111 -0
  185. package/src/storage/provider-settings-manager.ts +129 -0
  186. package/src/storage/session-store.ts +1 -0
  187. package/src/storage/sqlite-session-store.ts +270 -0
  188. package/src/storage/sqlite-team-store.ts +443 -0
  189. package/src/storage/team-store.ts +5 -0
  190. package/src/team/index.ts +4 -0
  191. package/src/team/projections.ts +285 -0
  192. package/src/types/common.ts +14 -0
  193. package/src/types/config.ts +64 -0
  194. package/src/types/events.ts +46 -0
  195. package/src/types/index.ts +24 -0
  196. package/src/types/provider-settings.ts +43 -0
  197. package/src/types/sessions.ts +16 -0
  198. package/src/types/storage.ts +64 -0
  199. package/src/types/workspace.ts +7 -0
  200. package/src/types.ts +127 -0
@@ -0,0 +1,637 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { models, providers } from "@clinebot/llms";
4
+ import { resolveClineDataDir } from "@clinebot/shared/storage";
5
+ import type { ProviderSettings } from "../types/provider-settings";
6
+ import { emptyStoredProviderSettings } from "../types/provider-settings";
7
+ import type { ProviderSettingsManager } from "./provider-settings-manager";
8
+
9
+ type LegacyMode = "plan" | "act";
10
+
11
+ interface LegacyGlobalState {
12
+ mode?: LegacyMode;
13
+ planModeApiProvider?: string;
14
+ actModeApiProvider?: string;
15
+ planModeApiModelId?: string;
16
+ actModeApiModelId?: string;
17
+ planModeReasoningEffort?: string;
18
+ actModeReasoningEffort?: string;
19
+ planModeThinkingBudgetTokens?: number;
20
+ actModeThinkingBudgetTokens?: number;
21
+ geminiPlanModeThinkingLevel?: string;
22
+ geminiActModeThinkingLevel?: string;
23
+ anthropicBaseUrl?: string;
24
+ openAiBaseUrl?: string;
25
+ ollamaBaseUrl?: string;
26
+ lmStudioBaseUrl?: string;
27
+ liteLlmBaseUrl?: string;
28
+ geminiBaseUrl?: string;
29
+ requestyBaseUrl?: string;
30
+ asksageApiUrl?: string;
31
+ difyBaseUrl?: string;
32
+ ocaBaseUrl?: string;
33
+ aihubmixBaseUrl?: string;
34
+ openAiHeaders?: Record<string, string>;
35
+ requestTimeoutMs?: number;
36
+ awsRegion?: string;
37
+ awsAuthentication?: "iam" | "api-key" | "profile";
38
+ awsUseProfile?: boolean;
39
+ awsProfile?: string;
40
+ awsUseCrossRegionInference?: boolean;
41
+ awsUseGlobalInference?: boolean;
42
+ awsBedrockUsePromptCache?: boolean;
43
+ awsBedrockEndpoint?: string;
44
+ planModeAwsBedrockCustomModelBaseId?: string;
45
+ actModeAwsBedrockCustomModelBaseId?: string;
46
+ vertexProjectId?: string;
47
+ vertexRegion?: string;
48
+ azureApiVersion?: string;
49
+ azureIdentity?: boolean;
50
+ sapAiCoreTokenUrl?: string;
51
+ sapAiCoreBaseUrl?: string;
52
+ sapAiResourceGroup?: string;
53
+ sapAiCoreUseOrchestrationMode?: boolean;
54
+ ocaMode?: "internal" | "external";
55
+ qwenApiLine?: "china" | "international";
56
+ moonshotApiLine?: "china" | "international";
57
+ zaiApiLine?: "china" | "international";
58
+ minimaxApiLine?: "china" | "international";
59
+ planModeOpenRouterModelId?: string;
60
+ actModeOpenRouterModelId?: string;
61
+ planModeClineModelId?: string;
62
+ actModeClineModelId?: string;
63
+ planModeOpenAiModelId?: string;
64
+ actModeOpenAiModelId?: string;
65
+ planModeOllamaModelId?: string;
66
+ actModeOllamaModelId?: string;
67
+ planModeLmStudioModelId?: string;
68
+ actModeLmStudioModelId?: string;
69
+ planModeLiteLlmModelId?: string;
70
+ actModeLiteLlmModelId?: string;
71
+ planModeRequestyModelId?: string;
72
+ actModeRequestyModelId?: string;
73
+ planModeTogetherModelId?: string;
74
+ actModeTogetherModelId?: string;
75
+ planModeFireworksModelId?: string;
76
+ actModeFireworksModelId?: string;
77
+ planModeSapAiCoreModelId?: string;
78
+ actModeSapAiCoreModelId?: string;
79
+ planModeSapAiCoreDeploymentId?: string;
80
+ actModeSapAiCoreDeploymentId?: string;
81
+ planModeGroqModelId?: string;
82
+ actModeGroqModelId?: string;
83
+ planModeBasetenModelId?: string;
84
+ actModeBasetenModelId?: string;
85
+ planModeHuggingFaceModelId?: string;
86
+ actModeHuggingFaceModelId?: string;
87
+ planModeHuaweiCloudMaasModelId?: string;
88
+ actModeHuaweiCloudMaasModelId?: string;
89
+ planModeOcaModelId?: string;
90
+ actModeOcaModelId?: string;
91
+ planModeAihubmixModelId?: string;
92
+ actModeAihubmixModelId?: string;
93
+ planModeHicapModelId?: string;
94
+ actModeHicapModelId?: string;
95
+ planModeNousResearchModelId?: string;
96
+ actModeNousResearchModelId?: string;
97
+ planModeVercelAiGatewayModelId?: string;
98
+ actModeVercelAiGatewayModelId?: string;
99
+ }
100
+
101
+ interface LegacySecrets {
102
+ apiKey?: string;
103
+ clineApiKey?: string;
104
+ "cline:clineAccountId"?: string;
105
+ clineAccountId?: string;
106
+ openRouterApiKey?: string;
107
+ awsAccessKey?: string;
108
+ awsSecretKey?: string;
109
+ awsSessionToken?: string;
110
+ awsBedrockApiKey?: string;
111
+ openAiApiKey?: string;
112
+ geminiApiKey?: string;
113
+ openAiNativeApiKey?: string;
114
+ ollamaApiKey?: string;
115
+ deepSeekApiKey?: string;
116
+ requestyApiKey?: string;
117
+ togetherApiKey?: string;
118
+ fireworksApiKey?: string;
119
+ qwenApiKey?: string;
120
+ doubaoApiKey?: string;
121
+ mistralApiKey?: string;
122
+ liteLlmApiKey?: string;
123
+ asksageApiKey?: string;
124
+ xaiApiKey?: string;
125
+ moonshotApiKey?: string;
126
+ zaiApiKey?: string;
127
+ huggingFaceApiKey?: string;
128
+ nebiusApiKey?: string;
129
+ sambanovaApiKey?: string;
130
+ cerebrasApiKey?: string;
131
+ sapAiCoreClientId?: string;
132
+ sapAiCoreClientSecret?: string;
133
+ groqApiKey?: string;
134
+ huaweiCloudMaasApiKey?: string;
135
+ basetenApiKey?: string;
136
+ vercelAiGatewayApiKey?: string;
137
+ difyApiKey?: string;
138
+ minimaxApiKey?: string;
139
+ hicapApiKey?: string;
140
+ aihubmixApiKey?: string;
141
+ nousResearchApiKey?: string;
142
+ ocaApiKey?: string;
143
+ ocaRefreshToken?: string;
144
+ "openai-codex-oauth-credentials"?: string;
145
+ }
146
+
147
+ interface LegacyProviderStorage {
148
+ globalState: LegacyGlobalState;
149
+ secrets: LegacySecrets;
150
+ }
151
+
152
+ export interface MigrateLegacyProviderSettingsOptions {
153
+ providerSettingsManager: ProviderSettingsManager;
154
+ dataDir?: string;
155
+ globalStatePath?: string;
156
+ secretsPath?: string;
157
+ }
158
+
159
+ export interface MigrateLegacyProviderSettingsResult {
160
+ migrated: boolean;
161
+ providerCount: number;
162
+ lastUsedProvider?: string;
163
+ }
164
+
165
+ function trimNonEmpty(value: string | undefined): string | undefined {
166
+ const trimmed = value?.trim();
167
+ return trimmed ? trimmed : undefined;
168
+ }
169
+
170
+ function readJsonObject<T extends object>(filePath: string): T | undefined {
171
+ if (!existsSync(filePath)) {
172
+ return undefined;
173
+ }
174
+ try {
175
+ const raw = readFileSync(filePath, "utf8");
176
+ const parsed = JSON.parse(raw) as unknown;
177
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
178
+ return parsed as T;
179
+ }
180
+ } catch {
181
+ // Invalid legacy file should not block startup.
182
+ }
183
+ return undefined;
184
+ }
185
+
186
+ function resolveLegacyStorage(
187
+ options: MigrateLegacyProviderSettingsOptions,
188
+ ): LegacyProviderStorage | undefined {
189
+ const dataDir = options.dataDir ?? resolveClineDataDir();
190
+ const globalStatePath =
191
+ options.globalStatePath ?? join(dataDir, "globalState.json");
192
+ const secretsPath = options.secretsPath ?? join(dataDir, "secrets.json");
193
+ const globalState = readJsonObject<LegacyGlobalState>(globalStatePath);
194
+ const secrets = readJsonObject<LegacySecrets>(secretsPath);
195
+ if (!globalState && !secrets) {
196
+ return undefined;
197
+ }
198
+ return {
199
+ globalState: globalState ?? {},
200
+ secrets: secrets ?? {},
201
+ };
202
+ }
203
+
204
+ function resolveModelForProvider(
205
+ legacy: LegacyGlobalState,
206
+ providerId: string,
207
+ mode: LegacyMode,
208
+ activeProviderForMode: string | undefined,
209
+ ): string | undefined {
210
+ const modePrefix = mode === "plan" ? "planMode" : "actMode";
211
+ const fallbackModel =
212
+ providerId === activeProviderForMode
213
+ ? trimNonEmpty(
214
+ mode === "plan"
215
+ ? legacy.planModeApiModelId
216
+ : legacy.actModeApiModelId,
217
+ )
218
+ : undefined;
219
+ const providerModelKeyById: Record<string, keyof LegacyGlobalState> = {
220
+ openrouter: `${modePrefix}OpenRouterModelId` as keyof LegacyGlobalState,
221
+ cline: `${modePrefix}ClineModelId` as keyof LegacyGlobalState,
222
+ openai: `${modePrefix}OpenAiModelId` as keyof LegacyGlobalState,
223
+ ollama: `${modePrefix}OllamaModelId` as keyof LegacyGlobalState,
224
+ lmstudio: `${modePrefix}LmStudioModelId` as keyof LegacyGlobalState,
225
+ litellm: `${modePrefix}LiteLlmModelId` as keyof LegacyGlobalState,
226
+ requesty: `${modePrefix}RequestyModelId` as keyof LegacyGlobalState,
227
+ together: `${modePrefix}TogetherModelId` as keyof LegacyGlobalState,
228
+ fireworks: `${modePrefix}FireworksModelId` as keyof LegacyGlobalState,
229
+ sapaicore: `${modePrefix}SapAiCoreModelId` as keyof LegacyGlobalState,
230
+ groq: `${modePrefix}GroqModelId` as keyof LegacyGlobalState,
231
+ baseten: `${modePrefix}BasetenModelId` as keyof LegacyGlobalState,
232
+ huggingface: `${modePrefix}HuggingFaceModelId` as keyof LegacyGlobalState,
233
+ "huawei-cloud-maas":
234
+ `${modePrefix}HuaweiCloudMaasModelId` as keyof LegacyGlobalState,
235
+ oca: `${modePrefix}OcaModelId` as keyof LegacyGlobalState,
236
+ aihubmix: `${modePrefix}AihubmixModelId` as keyof LegacyGlobalState,
237
+ hicap: `${modePrefix}HicapModelId` as keyof LegacyGlobalState,
238
+ nousResearch: `${modePrefix}NousResearchModelId` as keyof LegacyGlobalState,
239
+ "vercel-ai-gateway":
240
+ `${modePrefix}VercelAiGatewayModelId` as keyof LegacyGlobalState,
241
+ };
242
+ const providerModelKey = providerModelKeyById[providerId];
243
+ const providerModel = providerModelKey
244
+ ? trimNonEmpty(
245
+ typeof legacy[providerModelKey] === "string"
246
+ ? (legacy[providerModelKey] as string)
247
+ : undefined,
248
+ )
249
+ : undefined;
250
+ return providerModel ?? fallbackModel;
251
+ }
252
+
253
+ function resolveReasoning(
254
+ legacy: LegacyGlobalState,
255
+ providerId: string,
256
+ mode: LegacyMode,
257
+ ): ProviderSettings["reasoning"] | undefined {
258
+ const effortCandidate =
259
+ mode === "plan"
260
+ ? legacy.planModeReasoningEffort
261
+ : legacy.actModeReasoningEffort;
262
+ const geminiLevel =
263
+ mode === "plan"
264
+ ? legacy.geminiPlanModeThinkingLevel
265
+ : legacy.geminiActModeThinkingLevel;
266
+ const budgetTokens =
267
+ mode === "plan"
268
+ ? legacy.planModeThinkingBudgetTokens
269
+ : legacy.actModeThinkingBudgetTokens;
270
+ const rawEffort =
271
+ (providerId === "gemini" ? geminiLevel : undefined) ?? effortCandidate;
272
+ const effort =
273
+ rawEffort === "none" ||
274
+ rawEffort === "low" ||
275
+ rawEffort === "medium" ||
276
+ rawEffort === "high"
277
+ ? rawEffort
278
+ : undefined;
279
+ const normalizedBudget =
280
+ typeof budgetTokens === "number" &&
281
+ Number.isInteger(budgetTokens) &&
282
+ budgetTokens > 0
283
+ ? budgetTokens
284
+ : undefined;
285
+ if (!effort && normalizedBudget === undefined) {
286
+ return undefined;
287
+ }
288
+ return {
289
+ ...(effort ? { effort } : {}),
290
+ ...(normalizedBudget !== undefined
291
+ ? { budgetTokens: normalizedBudget }
292
+ : {}),
293
+ };
294
+ }
295
+
296
+ function resolveLegacyCodexAuth(
297
+ legacySecrets: LegacySecrets,
298
+ ): Pick<ProviderSettings, "apiKey" | "auth"> | undefined {
299
+ const raw = legacySecrets["openai-codex-oauth-credentials"];
300
+ if (!raw) {
301
+ return undefined;
302
+ }
303
+ try {
304
+ const parsed = JSON.parse(raw) as {
305
+ access_token?: string;
306
+ refresh_token?: string;
307
+ accountId?: string;
308
+ };
309
+ const access = trimNonEmpty(parsed.access_token);
310
+ const refresh = trimNonEmpty(parsed.refresh_token);
311
+ const accountId = trimNonEmpty(parsed.accountId);
312
+ if (!access && !refresh && !accountId) {
313
+ return undefined;
314
+ }
315
+ return {
316
+ ...(access ? { apiKey: access } : {}),
317
+ auth: {
318
+ ...(access ? { accessToken: access } : {}),
319
+ ...(refresh ? { refreshToken: refresh } : {}),
320
+ ...(accountId ? { accountId } : {}),
321
+ },
322
+ };
323
+ } catch {
324
+ return undefined;
325
+ }
326
+ }
327
+
328
+ function getDefaultModelForProvider(providerId: string): string | undefined {
329
+ const builtInModels = models.getGeneratedModelsForProvider(providerId);
330
+ const firstModelId = Object.keys(builtInModels)[0];
331
+ return firstModelId ?? undefined;
332
+ }
333
+
334
+ function buildLegacyProviderSettings(
335
+ providerId: string,
336
+ legacyGlobalState: LegacyGlobalState,
337
+ legacySecrets: LegacySecrets,
338
+ mode: LegacyMode,
339
+ ): ProviderSettings | undefined {
340
+ const activeProviderForMode = trimNonEmpty(
341
+ mode === "plan"
342
+ ? legacyGlobalState.planModeApiProvider
343
+ : legacyGlobalState.actModeApiProvider,
344
+ );
345
+ const model =
346
+ resolveModelForProvider(
347
+ legacyGlobalState,
348
+ providerId,
349
+ mode,
350
+ activeProviderForMode,
351
+ ) ?? getDefaultModelForProvider(providerId);
352
+ const reasoning = resolveReasoning(legacyGlobalState, providerId, mode);
353
+ const timeout =
354
+ typeof legacyGlobalState.requestTimeoutMs === "number" &&
355
+ Number.isInteger(legacyGlobalState.requestTimeoutMs) &&
356
+ legacyGlobalState.requestTimeoutMs > 0
357
+ ? legacyGlobalState.requestTimeoutMs
358
+ : undefined;
359
+
360
+ const secretByProvider: Record<string, string | undefined> = {
361
+ anthropic: legacySecrets.apiKey,
362
+ cline: legacySecrets.clineApiKey,
363
+ openai: legacySecrets.openAiApiKey,
364
+ "openai-native": legacySecrets.openAiNativeApiKey,
365
+ openrouter: legacySecrets.openRouterApiKey,
366
+ bedrock: legacySecrets.awsBedrockApiKey,
367
+ gemini: legacySecrets.geminiApiKey,
368
+ ollama: legacySecrets.ollamaApiKey,
369
+ deepseek: legacySecrets.deepSeekApiKey,
370
+ requesty: legacySecrets.requestyApiKey,
371
+ together: legacySecrets.togetherApiKey,
372
+ fireworks: legacySecrets.fireworksApiKey,
373
+ qwen: legacySecrets.qwenApiKey,
374
+ doubao: legacySecrets.doubaoApiKey,
375
+ mistral: legacySecrets.mistralApiKey,
376
+ litellm: legacySecrets.liteLlmApiKey,
377
+ asksage: legacySecrets.asksageApiKey,
378
+ xai: legacySecrets.xaiApiKey,
379
+ moonshot: legacySecrets.moonshotApiKey,
380
+ zai: legacySecrets.zaiApiKey,
381
+ huggingface: legacySecrets.huggingFaceApiKey,
382
+ nebius: legacySecrets.nebiusApiKey,
383
+ sambanova: legacySecrets.sambanovaApiKey,
384
+ cerebras: legacySecrets.cerebrasApiKey,
385
+ groq: legacySecrets.groqApiKey,
386
+ "huawei-cloud-maas": legacySecrets.huaweiCloudMaasApiKey,
387
+ baseten: legacySecrets.basetenApiKey,
388
+ "vercel-ai-gateway": legacySecrets.vercelAiGatewayApiKey,
389
+ dify: legacySecrets.difyApiKey,
390
+ minimax: legacySecrets.minimaxApiKey,
391
+ hicap: legacySecrets.hicapApiKey,
392
+ aihubmix: legacySecrets.aihubmixApiKey,
393
+ nousResearch: legacySecrets.nousResearchApiKey,
394
+ oca: legacySecrets.ocaApiKey,
395
+ sapaicore: legacySecrets.sapAiCoreClientId,
396
+ };
397
+
398
+ const providerSpecific: Partial<ProviderSettings> = {};
399
+ if (providerId === "openai-codex") {
400
+ Object.assign(providerSpecific, resolveLegacyCodexAuth(legacySecrets));
401
+ }
402
+ if (providerId === "cline") {
403
+ const accountId = trimNonEmpty(
404
+ legacySecrets["cline:clineAccountId"] ?? legacySecrets.clineAccountId,
405
+ );
406
+ if (accountId) {
407
+ providerSpecific.auth = {
408
+ ...(providerSpecific.auth ?? {}),
409
+ accountId,
410
+ };
411
+ }
412
+ }
413
+ if (providerId === "openai" && legacyGlobalState.openAiHeaders) {
414
+ providerSpecific.headers = legacyGlobalState.openAiHeaders;
415
+ }
416
+ if (providerId === "bedrock") {
417
+ providerSpecific.aws = {
418
+ accessKey: trimNonEmpty(legacySecrets.awsAccessKey),
419
+ secretKey: trimNonEmpty(legacySecrets.awsSecretKey),
420
+ sessionToken: trimNonEmpty(legacySecrets.awsSessionToken),
421
+ region: trimNonEmpty(legacyGlobalState.awsRegion),
422
+ authentication: legacyGlobalState.awsAuthentication,
423
+ profile: legacyGlobalState.awsUseProfile
424
+ ? trimNonEmpty(legacyGlobalState.awsProfile)
425
+ : undefined,
426
+ usePromptCache: legacyGlobalState.awsBedrockUsePromptCache,
427
+ useCrossRegionInference: legacyGlobalState.awsUseCrossRegionInference,
428
+ useGlobalInference: legacyGlobalState.awsUseGlobalInference,
429
+ endpoint: trimNonEmpty(legacyGlobalState.awsBedrockEndpoint),
430
+ customModelBaseId: trimNonEmpty(
431
+ mode === "plan"
432
+ ? legacyGlobalState.planModeAwsBedrockCustomModelBaseId
433
+ : legacyGlobalState.actModeAwsBedrockCustomModelBaseId,
434
+ ),
435
+ };
436
+ }
437
+ if (providerId === "vertex") {
438
+ providerSpecific.gcp = {
439
+ projectId: trimNonEmpty(legacyGlobalState.vertexProjectId),
440
+ region: trimNonEmpty(legacyGlobalState.vertexRegion),
441
+ };
442
+ }
443
+ if (
444
+ providerId === "openai" &&
445
+ (legacyGlobalState.azureApiVersion ||
446
+ legacyGlobalState.azureIdentity !== undefined)
447
+ ) {
448
+ providerSpecific.azure = {
449
+ apiVersion: trimNonEmpty(legacyGlobalState.azureApiVersion),
450
+ useIdentity: legacyGlobalState.azureIdentity,
451
+ };
452
+ }
453
+ if (providerId === "sapaicore") {
454
+ providerSpecific.sap = {
455
+ clientId: trimNonEmpty(legacySecrets.sapAiCoreClientId),
456
+ clientSecret: trimNonEmpty(legacySecrets.sapAiCoreClientSecret),
457
+ tokenUrl: trimNonEmpty(legacyGlobalState.sapAiCoreTokenUrl),
458
+ resourceGroup: trimNonEmpty(legacyGlobalState.sapAiResourceGroup),
459
+ deploymentId: trimNonEmpty(
460
+ mode === "plan"
461
+ ? legacyGlobalState.planModeSapAiCoreDeploymentId
462
+ : legacyGlobalState.actModeSapAiCoreDeploymentId,
463
+ ),
464
+ useOrchestrationMode: legacyGlobalState.sapAiCoreUseOrchestrationMode,
465
+ };
466
+ }
467
+ if (providerId === "oca") {
468
+ providerSpecific.oca = {
469
+ mode: legacyGlobalState.ocaMode,
470
+ };
471
+ const refreshToken = trimNonEmpty(legacySecrets.ocaRefreshToken);
472
+ if (refreshToken) {
473
+ providerSpecific.auth = {
474
+ ...(providerSpecific.auth ?? {}),
475
+ refreshToken,
476
+ };
477
+ }
478
+ }
479
+ if (providerId === "qwen") {
480
+ providerSpecific.apiLine = legacyGlobalState.qwenApiLine;
481
+ }
482
+ if (providerId === "moonshot") {
483
+ providerSpecific.apiLine = legacyGlobalState.moonshotApiLine;
484
+ }
485
+ if (providerId === "zai") {
486
+ providerSpecific.apiLine = legacyGlobalState.zaiApiLine;
487
+ }
488
+ if (providerId === "minimax") {
489
+ providerSpecific.apiLine = legacyGlobalState.minimaxApiLine;
490
+ }
491
+
492
+ const baseUrlByProvider: Record<string, string | undefined> = {
493
+ anthropic: legacyGlobalState.anthropicBaseUrl,
494
+ openai: legacyGlobalState.openAiBaseUrl,
495
+ ollama: legacyGlobalState.ollamaBaseUrl,
496
+ lmstudio: legacyGlobalState.lmStudioBaseUrl,
497
+ litellm: legacyGlobalState.liteLlmBaseUrl,
498
+ gemini: legacyGlobalState.geminiBaseUrl,
499
+ requesty: legacyGlobalState.requestyBaseUrl,
500
+ asksage: legacyGlobalState.asksageApiUrl,
501
+ dify: legacyGlobalState.difyBaseUrl,
502
+ oca: legacyGlobalState.ocaBaseUrl,
503
+ aihubmix: legacyGlobalState.aihubmixBaseUrl,
504
+ sapaicore: legacyGlobalState.sapAiCoreBaseUrl,
505
+ };
506
+
507
+ const apiKey = trimNonEmpty(secretByProvider[providerId]);
508
+ const baseUrl = trimNonEmpty(baseUrlByProvider[providerId]);
509
+
510
+ const settings: ProviderSettings = {
511
+ provider: providerId as ProviderSettings["provider"],
512
+ ...(apiKey ? { apiKey } : {}),
513
+ ...(model ? { model } : {}),
514
+ ...(baseUrl ? { baseUrl } : {}),
515
+ ...(reasoning ? { reasoning } : {}),
516
+ ...(timeout ? { timeout } : {}),
517
+ ...providerSpecific,
518
+ };
519
+ const parsed = providers.ProviderSettingsSchema.safeParse(settings);
520
+ if (!parsed.success) {
521
+ return undefined;
522
+ }
523
+ const hasNonProviderFields =
524
+ Object.keys(settings).filter((key) => key !== "provider").length > 0;
525
+ return hasNonProviderFields ? parsed.data : undefined;
526
+ }
527
+
528
+ function collectCandidateProviderIds(
529
+ legacyGlobalState: LegacyGlobalState,
530
+ legacySecrets: LegacySecrets,
531
+ ): Set<string> {
532
+ const candidates = new Set<string>();
533
+ for (const maybeProvider of [
534
+ legacyGlobalState.actModeApiProvider,
535
+ legacyGlobalState.planModeApiProvider,
536
+ ]) {
537
+ const provider = trimNonEmpty(maybeProvider);
538
+ if (provider) {
539
+ candidates.add(provider);
540
+ }
541
+ }
542
+ if (trimNonEmpty(legacySecrets.apiKey)) candidates.add("anthropic");
543
+ if (trimNonEmpty(legacySecrets.openRouterApiKey))
544
+ candidates.add("openrouter");
545
+ if (trimNonEmpty(legacySecrets.openAiApiKey)) candidates.add("openai");
546
+ if (trimNonEmpty(legacySecrets.openAiNativeApiKey))
547
+ candidates.add("openai-native");
548
+ if (trimNonEmpty(legacySecrets["openai-codex-oauth-credentials"]))
549
+ candidates.add("openai-codex");
550
+ if (trimNonEmpty(legacySecrets.geminiApiKey)) candidates.add("gemini");
551
+ if (trimNonEmpty(legacySecrets.ollamaApiKey)) candidates.add("ollama");
552
+ if (
553
+ trimNonEmpty(legacySecrets.awsAccessKey) ||
554
+ trimNonEmpty(legacySecrets.awsBedrockApiKey)
555
+ )
556
+ candidates.add("bedrock");
557
+ if (
558
+ trimNonEmpty(legacyGlobalState.vertexProjectId) ||
559
+ trimNonEmpty(legacyGlobalState.vertexRegion)
560
+ ) {
561
+ candidates.add("vertex");
562
+ }
563
+ if (trimNonEmpty(legacySecrets.clineApiKey)) candidates.add("cline");
564
+ if (trimNonEmpty(legacySecrets.ocaApiKey)) candidates.add("oca");
565
+ return candidates;
566
+ }
567
+
568
+ export function migrateLegacyProviderSettings(
569
+ options: MigrateLegacyProviderSettingsOptions,
570
+ ): MigrateLegacyProviderSettingsResult {
571
+ const existing = options.providerSettingsManager.read();
572
+ const legacyStorage = resolveLegacyStorage(options);
573
+ if (!legacyStorage) {
574
+ return {
575
+ migrated: false,
576
+ providerCount: Object.keys(existing.providers).length,
577
+ lastUsedProvider: existing.lastUsedProvider,
578
+ };
579
+ }
580
+
581
+ const { globalState, secrets } = legacyStorage;
582
+ const mode: LegacyMode = globalState.mode === "plan" ? "plan" : "act";
583
+ const candidates = collectCandidateProviderIds(globalState, secrets);
584
+ const next = emptyStoredProviderSettings();
585
+ next.providers = { ...existing.providers };
586
+ next.lastUsedProvider = existing.lastUsedProvider;
587
+ const now = new Date().toISOString();
588
+ let addedProviderCount = 0;
589
+
590
+ for (const providerId of candidates) {
591
+ if (next.providers[providerId]) {
592
+ continue;
593
+ }
594
+ const settings = buildLegacyProviderSettings(
595
+ providerId,
596
+ globalState,
597
+ secrets,
598
+ mode,
599
+ );
600
+ if (!settings) {
601
+ continue;
602
+ }
603
+ next.providers[providerId] = {
604
+ settings,
605
+ updatedAt: now,
606
+ tokenSource: "migration",
607
+ };
608
+ addedProviderCount += 1;
609
+ }
610
+
611
+ if (addedProviderCount === 0) {
612
+ return {
613
+ migrated: false,
614
+ providerCount: Object.keys(existing.providers).length,
615
+ lastUsedProvider: existing.lastUsedProvider,
616
+ };
617
+ }
618
+
619
+ const preferredProvider = trimNonEmpty(
620
+ mode === "plan"
621
+ ? globalState.planModeApiProvider
622
+ : globalState.actModeApiProvider,
623
+ );
624
+ next.lastUsedProvider =
625
+ existing.lastUsedProvider ??
626
+ (preferredProvider && next.providers[preferredProvider]
627
+ ? preferredProvider
628
+ : Object.keys(next.providers)[0]);
629
+
630
+ options.providerSettingsManager.write(next);
631
+
632
+ return {
633
+ migrated: true,
634
+ providerCount: Object.keys(next.providers).length,
635
+ lastUsedProvider: next.lastUsedProvider,
636
+ };
637
+ }