diff --git a/.changeset/young-buckets-fold.md b/.changeset/young-buckets-fold.md new file mode 100644 index 0000000000..a796dedc79 --- /dev/null +++ b/.changeset/young-buckets-fold.md @@ -0,0 +1,5 @@ +--- +"roo-cline": patch +--- + +Fix global settings export diff --git a/src/core/config/__tests__/importExport.test.ts b/src/core/config/__tests__/importExport.test.ts index a5a8614273..3fe5e97595 100644 --- a/src/core/config/__tests__/importExport.test.ts +++ b/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", diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 1bd57e2b5b..b4beed223e 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -1263,7 +1263,7 @@ export class ClineProvider extends EventEmitter 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 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, diff --git a/src/exports/roo-code.d.ts b/src/exports/roo-code.d.ts index 8c5aa5e8b6..5c59075638 100644 --- a/src/exports/roo-code.d.ts +++ b/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 diff --git a/src/exports/types.ts b/src/exports/types.ts index 0c228a714c..9f45866d0d 100644 --- a/src/exports/types.ts +++ b/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 diff --git a/src/schemas/index.ts b/src/schemas/index.ts index 3538be7062..6b1f6f3d0f 100644 --- a/src/schemas/index.ts +++ b/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(), diff --git a/webview-ui/src/components/settings/SettingsView.tsx b/webview-ui/src/components/settings/SettingsView.tsx index 8f25289a56..90031c6924 100644 --- a/webview-ui/src/components/settings/SettingsView.tsx +++ b/webview-ui/src/components/settings/SettingsView.tsx @@ -250,7 +250,7 @@ const SettingsView = forwardRef(({ 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 }) diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index 082c80d24c..11c7c9c0d4 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/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,