ソースを参照

Fix global settings export (#3890)

Chris Estreich 7 ヶ月 前
コミット
6931cc9262

+ 5 - 0
.changeset/young-buckets-fold.md

@@ -0,0 +1,5 @@
+---
+"roo-cline": patch
+---
+
+Fix global settings export

+ 59 - 26
src/core/config/__tests__/importExport.test.ts

@@ -282,41 +282,41 @@ describe("importExport", () => {
 			expect(result.providerProfiles?.apiConfigs["default"]).toBeDefined()
 			expect(result.providerProfiles?.apiConfigs["default"].apiProvider).toBe("anthropic")
 		})
-	})
 
-	it("should call updateCustomMode for each custom mode in config", async () => {
-		;(vscode.window.showOpenDialog as jest.Mock).mockResolvedValue([{ fsPath: "/mock/path/settings.json" }])
+		it("should call updateCustomMode for each custom mode in config", async () => {
+			;(vscode.window.showOpenDialog as jest.Mock).mockResolvedValue([{ fsPath: "/mock/path/settings.json" }])
 
-		const customModes = [
-			{ slug: "mode1", name: "Mode One", roleDefinition: "Custom role one", groups: [] },
-			{ slug: "mode2", name: "Mode Two", roleDefinition: "Custom role two", groups: [] },
-		]
+			const customModes = [
+				{ slug: "mode1", name: "Mode One", roleDefinition: "Custom role one", groups: [] },
+				{ slug: "mode2", name: "Mode Two", roleDefinition: "Custom role two", groups: [] },
+			]
 
-		const mockFileContent = JSON.stringify({
-			providerProfiles: { currentApiConfigName: "test", apiConfigs: {} },
-			globalSettings: { mode: "code", customModes },
-		})
+			const mockFileContent = JSON.stringify({
+				providerProfiles: { currentApiConfigName: "test", apiConfigs: {} },
+				globalSettings: { mode: "code", customModes },
+			})
 
-		;(fs.readFile as jest.Mock).mockResolvedValue(mockFileContent)
+			;(fs.readFile as jest.Mock).mockResolvedValue(mockFileContent)
 
-		mockProviderSettingsManager.export.mockResolvedValue({
-			currentApiConfigName: "test",
-			apiConfigs: {},
-		})
+			mockProviderSettingsManager.export.mockResolvedValue({
+				currentApiConfigName: "test",
+				apiConfigs: {},
+			})
 
-		mockProviderSettingsManager.listConfig.mockResolvedValue([])
+			mockProviderSettingsManager.listConfig.mockResolvedValue([])
 
-		const result = await importSettings({
-			providerSettingsManager: mockProviderSettingsManager,
-			contextProxy: mockContextProxy,
-			customModesManager: mockCustomModesManager,
-		})
+			const result = await importSettings({
+				providerSettingsManager: mockProviderSettingsManager,
+				contextProxy: mockContextProxy,
+				customModesManager: mockCustomModesManager,
+			})
 
-		expect(result.success).toBe(true)
-		expect(mockCustomModesManager.updateCustomMode).toHaveBeenCalledTimes(customModes.length)
+			expect(result.success).toBe(true)
+			expect(mockCustomModesManager.updateCustomMode).toHaveBeenCalledTimes(customModes.length)
 
-		customModes.forEach((mode) => {
-			expect(mockCustomModesManager.updateCustomMode).toHaveBeenCalledWith(mode.slug, mode)
+			customModes.forEach((mode) => {
+				expect(mockCustomModesManager.updateCustomMode).toHaveBeenCalledWith(mode.slug, mode)
+			})
 		})
 	})
 
@@ -375,6 +375,39 @@ describe("importExport", () => {
 			)
 		})
 
+		it("should include globalSettings when allowedMaxRequests is null", async () => {
+			;(vscode.window.showSaveDialog as jest.Mock).mockResolvedValue({
+				fsPath: "/mock/path/roo-code-settings.json",
+			})
+
+			const mockProviderProfiles = {
+				currentApiConfigName: "test",
+				apiConfigs: { test: { apiProvider: "openai" as ProviderName, id: "test-id" } },
+				migrations: { rateLimitSecondsMigrated: false },
+			}
+
+			mockProviderSettingsManager.export.mockResolvedValue(mockProviderProfiles)
+
+			const mockGlobalSettings = {
+				mode: "code",
+				autoApprovalEnabled: true,
+				allowedMaxRequests: null,
+			}
+
+			mockContextProxy.export.mockResolvedValue(mockGlobalSettings)
+
+			await exportSettings({
+				providerSettingsManager: mockProviderSettingsManager,
+				contextProxy: mockContextProxy,
+			})
+
+			expect(fs.writeFile).toHaveBeenCalledWith(
+				"/mock/path/roo-code-settings.json",
+				JSON.stringify({ providerProfiles: mockProviderProfiles, globalSettings: mockGlobalSettings }, null, 2),
+				"utf-8",
+			)
+		})
+
 		it("should handle errors during the export process", async () => {
 			;(vscode.window.showSaveDialog as jest.Mock).mockResolvedValue({
 				fsPath: "/mock/path/roo-code-settings.json",

+ 2 - 2
src/core/webview/ClineProvider.ts

@@ -1263,7 +1263,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 			alwaysAllowMcp: alwaysAllowMcp ?? false,
 			alwaysAllowModeSwitch: alwaysAllowModeSwitch ?? false,
 			alwaysAllowSubtasks: alwaysAllowSubtasks ?? false,
-			allowedMaxRequests: allowedMaxRequests ?? Infinity,
+			allowedMaxRequests,
 			autoCondenseContextPercent: autoCondenseContextPercent ?? 100,
 			uriScheme: vscode.env.uriScheme,
 			currentTaskItem: this.getCurrentCline()?.taskId
@@ -1369,7 +1369,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 			alwaysAllowMcp: stateValues.alwaysAllowMcp ?? false,
 			alwaysAllowModeSwitch: stateValues.alwaysAllowModeSwitch ?? false,
 			alwaysAllowSubtasks: stateValues.alwaysAllowSubtasks ?? false,
-			allowedMaxRequests: stateValues.allowedMaxRequests ?? Infinity,
+			allowedMaxRequests: stateValues.allowedMaxRequests,
 			autoCondenseContextPercent: stateValues.autoCondenseContextPercent ?? 100,
 			taskHistory: stateValues.taskHistory,
 			allowedCommands: stateValues.allowedCommands,

+ 3 - 3
src/exports/roo-code.d.ts

@@ -72,7 +72,7 @@ type GlobalSettings = {
 	alwaysAllowSubtasks?: boolean | undefined
 	alwaysAllowExecute?: boolean | undefined
 	allowedCommands?: string[] | undefined
-	allowedMaxRequests?: number | undefined
+	allowedMaxRequests?: (number | null) | undefined
 	autoCondenseContextPercent?: number | undefined
 	browserToolEnabled?: boolean | undefined
 	browserViewportSize?: string | undefined
@@ -809,7 +809,7 @@ type IpcMessage =
 								alwaysAllowSubtasks?: boolean | undefined
 								alwaysAllowExecute?: boolean | undefined
 								allowedCommands?: string[] | undefined
-								allowedMaxRequests?: number | undefined
+								allowedMaxRequests?: (number | null) | undefined
 								autoCondenseContextPercent?: number | undefined
 								browserToolEnabled?: boolean | undefined
 								browserViewportSize?: string | undefined
@@ -1286,7 +1286,7 @@ type TaskCommand =
 					alwaysAllowSubtasks?: boolean | undefined
 					alwaysAllowExecute?: boolean | undefined
 					allowedCommands?: string[] | undefined
-					allowedMaxRequests?: number | undefined
+					allowedMaxRequests?: (number | null) | undefined
 					autoCondenseContextPercent?: number | undefined
 					browserToolEnabled?: boolean | undefined
 					browserViewportSize?: string | undefined

+ 3 - 3
src/exports/types.ts

@@ -72,7 +72,7 @@ type GlobalSettings = {
 	alwaysAllowSubtasks?: boolean | undefined
 	alwaysAllowExecute?: boolean | undefined
 	allowedCommands?: string[] | undefined
-	allowedMaxRequests?: number | undefined
+	allowedMaxRequests?: (number | null) | undefined
 	autoCondenseContextPercent?: number | undefined
 	browserToolEnabled?: boolean | undefined
 	browserViewportSize?: string | undefined
@@ -823,7 +823,7 @@ type IpcMessage =
 								alwaysAllowSubtasks?: boolean | undefined
 								alwaysAllowExecute?: boolean | undefined
 								allowedCommands?: string[] | undefined
-								allowedMaxRequests?: number | undefined
+								allowedMaxRequests?: (number | null) | undefined
 								autoCondenseContextPercent?: number | undefined
 								browserToolEnabled?: boolean | undefined
 								browserViewportSize?: string | undefined
@@ -1302,7 +1302,7 @@ type TaskCommand =
 					alwaysAllowSubtasks?: boolean | undefined
 					alwaysAllowExecute?: boolean | undefined
 					allowedCommands?: string[] | undefined
-					allowedMaxRequests?: number | undefined
+					allowedMaxRequests?: (number | null) | undefined
 					autoCondenseContextPercent?: number | undefined
 					browserToolEnabled?: boolean | undefined
 					browserViewportSize?: string | undefined

+ 1 - 1
src/schemas/index.ts

@@ -752,7 +752,7 @@ export const globalSettingsSchema = z.object({
 	alwaysAllowSubtasks: z.boolean().optional(),
 	alwaysAllowExecute: z.boolean().optional(),
 	allowedCommands: z.array(z.string()).optional(),
-	allowedMaxRequests: z.number().optional(),
+	allowedMaxRequests: z.number().nullish(),
 	autoCondenseContextPercent: z.number().optional(),
 
 	browserToolEnabled: z.boolean().optional(),

+ 1 - 1
webview-ui/src/components/settings/SettingsView.tsx

@@ -250,7 +250,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
 			vscode.postMessage({ type: "alwaysAllowBrowser", bool: alwaysAllowBrowser })
 			vscode.postMessage({ type: "alwaysAllowMcp", bool: alwaysAllowMcp })
 			vscode.postMessage({ type: "allowedCommands", commands: allowedCommands ?? [] })
-			vscode.postMessage({ type: "allowedMaxRequests", value: allowedMaxRequests })
+			vscode.postMessage({ type: "allowedMaxRequests", value: allowedMaxRequests ?? undefined })
 			vscode.postMessage({ type: "autoCondenseContextPercent", value: autoCondenseContextPercent })
 			vscode.postMessage({ type: "browserToolEnabled", bool: browserToolEnabled })
 			vscode.postMessage({ type: "soundEnabled", bool: soundEnabled })

+ 0 - 1
webview-ui/src/context/ExtensionStateContext.tsx

@@ -140,7 +140,6 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
 		taskHistory: [],
 		shouldShowAnnouncement: false,
 		allowedCommands: [],
-		allowedMaxRequests: Infinity,
 		soundEnabled: false,
 		soundVolume: 0.5,
 		ttsEnabled: false,