From 425e5dfc0ead29a3b7a3fe15d9ad78feb1035b1a Mon Sep 17 00:00:00 2001 From: Ross McFarland Date: Sun, 6 Apr 2025 09:16:25 -0700 Subject: [PATCH 1/4] Rate-limit setting updated to be per-profile --- .changeset/curvy-masks-scream.md | 5 ++ src/core/config/ProviderSettingsManager.ts | 59 +++++++++++++++- .../__tests__/ProviderSettingsManager.test.ts | 70 ++++++++++++++++++- .../config/__tests__/importExport.test.ts | 10 +++ src/exports/roo-code.d.ts | 1 + src/exports/types.ts | 1 + src/schemas/index.ts | 2 + .../components/settings/AdvancedSettings.tsx | 23 +----- .../src/components/settings/ApiOptions.tsx | 17 +++-- .../settings/RateLimitSecondsControl.tsx | 38 ++++++++++ .../src/components/settings/SettingsView.tsx | 3 - .../settings/__tests__/ApiOptions.test.tsx | 21 +++++- webview-ui/src/i18n/locales/ca/settings.json | 4 ++ webview-ui/src/i18n/locales/de/settings.json | 4 ++ webview-ui/src/i18n/locales/en/settings.json | 8 +-- webview-ui/src/i18n/locales/es/settings.json | 4 ++ webview-ui/src/i18n/locales/fr/settings.json | 4 ++ webview-ui/src/i18n/locales/hi/settings.json | 4 ++ webview-ui/src/i18n/locales/it/settings.json | 4 ++ webview-ui/src/i18n/locales/ja/settings.json | 4 ++ webview-ui/src/i18n/locales/ko/settings.json | 4 ++ webview-ui/src/i18n/locales/pl/settings.json | 4 ++ .../src/i18n/locales/pt-BR/settings.json | 4 ++ webview-ui/src/i18n/locales/tr/settings.json | 4 ++ webview-ui/src/i18n/locales/vi/settings.json | 4 ++ .../src/i18n/locales/zh-CN/settings.json | 4 ++ .../src/i18n/locales/zh-TW/settings.json | 4 ++ 27 files changed, 275 insertions(+), 39 deletions(-) create mode 100644 .changeset/curvy-masks-scream.md create mode 100644 webview-ui/src/components/settings/RateLimitSecondsControl.tsx diff --git a/.changeset/curvy-masks-scream.md b/.changeset/curvy-masks-scream.md new file mode 100644 index 00000000000..5923d7d8eb7 --- /dev/null +++ b/.changeset/curvy-masks-scream.md @@ -0,0 +1,5 @@ +--- +"roo-cline": minor +--- + +Rate-limit setting updated to be per-profile diff --git a/src/core/config/ProviderSettingsManager.ts b/src/core/config/ProviderSettingsManager.ts index a6153e636c0..8b9c5e23508 100644 --- a/src/core/config/ProviderSettingsManager.ts +++ b/src/core/config/ProviderSettingsManager.ts @@ -13,6 +13,11 @@ export const providerProfilesSchema = z.object({ currentApiConfigName: z.string(), apiConfigs: z.record(z.string(), providerSettingsWithIdSchema), modeApiConfigs: z.record(z.string(), z.string()).optional(), + migrations: z + .object({ + rateLimitSecondsMigrated: z.boolean().optional(), + }) + .optional(), }) export type ProviderProfiles = z.infer @@ -27,8 +32,16 @@ export class ProviderSettingsManager { private readonly defaultProviderProfiles: ProviderProfiles = { currentApiConfigName: "default", - apiConfigs: { default: { id: this.defaultConfigId } }, + apiConfigs: { + default: { + id: this.defaultConfigId, + rateLimitSeconds: 0, + }, + }, modeApiConfigs: this.defaultModeApiConfigs, + migrations: { + rateLimitSecondsMigrated: true, // Mark as migrated on fresh installs + }, } private readonly context: ExtensionContext @@ -53,7 +66,7 @@ export class ProviderSettingsManager { } /** - * Initialize config if it doesn't exist. + * Initialize config if it doesn't exist and run migrations. */ public async initialize() { try { @@ -75,6 +88,18 @@ export class ProviderSettingsManager { } } + // Ensure migrations field exists + if (!providerProfiles.migrations) { + providerProfiles.migrations = { rateLimitSecondsMigrated: false } // Initialize with default values + isDirty = true + } + + if (!providerProfiles.migrations.rateLimitSecondsMigrated) { + await this.migrateRateLimitSeconds(providerProfiles) + providerProfiles.migrations.rateLimitSecondsMigrated = true + isDirty = true + } + if (isDirty) { await this.store(providerProfiles) } @@ -84,6 +109,36 @@ export class ProviderSettingsManager { } } + private async migrateRateLimitSeconds(providerProfiles: ProviderProfiles) { + try { + let rateLimitSeconds: number | undefined + + try { + rateLimitSeconds = await this.context.globalState.get("rateLimitSeconds") + } catch (error) { + console.error("[MigrateRateLimitSeconds] Error getting global rate limit:", error) + } + + if (rateLimitSeconds === undefined) { + // Failed to get the existing value, use the default + rateLimitSeconds = 0 + } + + for (const [name, apiConfig] of Object.entries(providerProfiles.apiConfigs)) { + if (apiConfig.rateLimitSeconds === undefined) { + console.log( + `[MigrateRateLimitSeconds] Applying rate limit ${rateLimitSeconds}s to profile: ${name}`, + ) + apiConfig.rateLimitSeconds = rateLimitSeconds + } + } + + console.log(`[MigrateRateLimitSeconds] migration complete`) + } catch (error) { + console.error(`[MigrateRateLimitSeconds] Failed to migrate rate limit settings:`, error) + } + } + /** * List all available configs with metadata. */ diff --git a/src/core/config/__tests__/ProviderSettingsManager.test.ts b/src/core/config/__tests__/ProviderSettingsManager.test.ts index c72abdab654..1ce370bf039 100644 --- a/src/core/config/__tests__/ProviderSettingsManager.test.ts +++ b/src/core/config/__tests__/ProviderSettingsManager.test.ts @@ -12,8 +12,14 @@ const mockSecrets = { delete: jest.fn(), } +const mockGlobalState = { + get: jest.fn(), + update: jest.fn(), +} + const mockContext = { secrets: mockSecrets, + globalState: mockGlobalState, } as unknown as ExtensionContext describe("ProviderSettingsManager", () => { @@ -45,6 +51,9 @@ describe("ProviderSettingsManager", () => { id: "default", }, }, + migrations: { + rateLimitSecondsMigrated: true, + }, }), ) @@ -78,6 +87,43 @@ describe("ProviderSettingsManager", () => { expect(storedConfig.apiConfigs.test.id).toBeTruthy() }) + it("should call migrateRateLimitSeconds if it has not done so already", async () => { + mockGlobalState.get.mockResolvedValue(42) + + mockSecrets.get.mockResolvedValue( + JSON.stringify({ + currentApiConfigName: "default", + apiConfigs: { + default: { + config: {}, + id: "default", + rateLimitSeconds: undefined, + }, + test: { + apiProvider: "anthropic", + rateLimitSeconds: undefined, + }, + existing: { + apiProvider: "anthropic", + // this should not really be possible, unless someone has loaded a hand edited config, + // but we don't overwrite so we'll check that + rateLimitSeconds: 43, + }, + }, + migrations: { + rateLimitSecondsMigrate: false, + }, + }), + ) + + await providerSettingsManager.initialize() + + const storedConfig = JSON.parse(mockSecrets.store.mock.calls[1][1]) + expect(storedConfig.apiConfigs.default.rateLimitSeconds).toEqual(42) + expect(storedConfig.apiConfigs.test.rateLimitSeconds).toEqual(42) + expect(storedConfig.apiConfigs.existing.rateLimitSeconds).toEqual(43) + }) + it("should throw error if secrets storage fails", async () => { mockSecrets.get.mockRejectedValue(new Error("Storage failed")) @@ -105,6 +151,9 @@ describe("ProviderSettingsManager", () => { architect: "default", ask: "default", }, + migrations: { + rateLimitSecondsMigrated: false, + }, } mockSecrets.get.mockResolvedValue(JSON.stringify(existingConfig)) @@ -125,6 +174,9 @@ describe("ProviderSettingsManager", () => { architect: "default", ask: "default", }, + migrations: { + rateLimitSecondsMigrated: false, + }, } mockSecrets.get.mockResolvedValue(JSON.stringify(emptyConfig)) @@ -201,6 +253,9 @@ describe("ProviderSettingsManager", () => { id: "test-id", }, }, + migrations: { + rateLimitSecondsMigrated: false, + }, } mockSecrets.get.mockResolvedValue(JSON.stringify(existingConfig)) @@ -221,6 +276,9 @@ describe("ProviderSettingsManager", () => { id: "test-id", }, }, + migrations: { + rateLimitSecondsMigrated: false, + }, } expect(mockSecrets.store).toHaveBeenCalledWith( @@ -257,6 +315,9 @@ describe("ProviderSettingsManager", () => { id: "test-id", }, }, + migrations: { + rateLimitSecondsMigrated: false, + }, } mockSecrets.get.mockResolvedValue(JSON.stringify(existingConfig)) @@ -312,8 +373,12 @@ describe("ProviderSettingsManager", () => { id: "test-id", }, }, + migrations: { + rateLimitSecondsMigrated: false, + }, } + mockGlobalState.get.mockResolvedValue(42) mockSecrets.get.mockResolvedValue(JSON.stringify(existingConfig)) const config = await providerSettingsManager.loadConfig("test") @@ -325,7 +390,7 @@ describe("ProviderSettingsManager", () => { }) // Get the stored config to check the structure - const storedConfig = JSON.parse(mockSecrets.store.mock.calls[0][1]) + const storedConfig = JSON.parse(mockSecrets.store.mock.calls[1][1]) expect(storedConfig.currentApiConfigName).toBe("test") expect(storedConfig.apiConfigs.test).toEqual({ apiProvider: "anthropic", @@ -409,6 +474,9 @@ describe("ProviderSettingsManager", () => { id: "test-id", }, }, + migrations: { + rateLimitSecondsMigrated: false, + }, } mockSecrets.get.mockResolvedValue(JSON.stringify(existingConfig)) diff --git a/src/core/config/__tests__/importExport.test.ts b/src/core/config/__tests__/importExport.test.ts index d472856975a..038bf2ad80a 100644 --- a/src/core/config/__tests__/importExport.test.ts +++ b/src/core/config/__tests__/importExport.test.ts @@ -121,6 +121,7 @@ describe("importExport", () => { }, }, } + mockProviderSettingsManager.export.mockResolvedValue(previousProviderProfiles) // Mock listConfig @@ -294,6 +295,9 @@ describe("importExport", () => { id: "test-id", }, }, + migrations: { + rateLimitSecondsMigrated: false, + }, } mockProviderSettingsManager.export.mockResolvedValue(mockProviderProfiles) @@ -345,6 +349,9 @@ describe("importExport", () => { id: "test-id", }, }, + migrations: { + rateLimitSecondsMigrated: false, + }, }) // Mock global settings @@ -384,6 +391,9 @@ describe("importExport", () => { id: "test-id", }, }, + migrations: { + rateLimitSecondsMigrated: false, + }, }) // Mock global settings diff --git a/src/exports/roo-code.d.ts b/src/exports/roo-code.d.ts index 7b6f19a31d0..3586464ef1c 100644 --- a/src/exports/roo-code.d.ts +++ b/src/exports/roo-code.d.ts @@ -177,6 +177,7 @@ type ProviderSettings = { modelMaxTokens?: number | undefined modelMaxThinkingTokens?: number | undefined includeMaxTokens?: boolean | undefined + rateLimitSeconds?: number | undefined fakeAi?: unknown | undefined } diff --git a/src/exports/types.ts b/src/exports/types.ts index 1cd4df7e57d..d9824ef1dbc 100644 --- a/src/exports/types.ts +++ b/src/exports/types.ts @@ -178,6 +178,7 @@ type ProviderSettings = { modelMaxTokens?: number | undefined modelMaxThinkingTokens?: number | undefined includeMaxTokens?: boolean | undefined + rateLimitSeconds?: number | undefined fakeAi?: unknown | undefined } diff --git a/src/schemas/index.ts b/src/schemas/index.ts index bd45b99667e..f5cd620e2aa 100644 --- a/src/schemas/index.ts +++ b/src/schemas/index.ts @@ -386,6 +386,7 @@ export const providerSettingsSchema = z.object({ modelMaxThinkingTokens: z.number().optional(), // Generic includeMaxTokens: z.boolean().optional(), + rateLimitSeconds: z.number().optional(), // Fake AI fakeAi: z.unknown().optional(), }) @@ -470,6 +471,7 @@ const providerSettingsRecord: ProviderSettingsRecord = { modelMaxThinkingTokens: undefined, // Generic includeMaxTokens: undefined, + rateLimitSeconds: undefined, // Fake AI fakeAi: undefined, } diff --git a/webview-ui/src/components/settings/AdvancedSettings.tsx b/webview-ui/src/components/settings/AdvancedSettings.tsx index 7942ca0f564..b6e34354183 100644 --- a/webview-ui/src/components/settings/AdvancedSettings.tsx +++ b/webview-ui/src/components/settings/AdvancedSettings.tsx @@ -11,13 +11,11 @@ import { SectionHeader } from "./SectionHeader" import { Section } from "./Section" type AdvancedSettingsProps = HTMLAttributes & { - rateLimitSeconds: number diffEnabled?: boolean fuzzyMatchThreshold?: number - setCachedStateField: SetCachedStateField<"rateLimitSeconds" | "diffEnabled" | "fuzzyMatchThreshold"> + setCachedStateField: SetCachedStateField<"diffEnabled" | "fuzzyMatchThreshold"> } export const AdvancedSettings = ({ - rateLimitSeconds, diffEnabled, fuzzyMatchThreshold, setCachedStateField, @@ -36,25 +34,6 @@ export const AdvancedSettings = ({
-
-
- {t("settings:advanced.rateLimit.label")} -
- setCachedStateField("rateLimitSeconds", value)} - /> - {rateLimitSeconds}s -
-
-
- {t("settings:advanced.rateLimit.description")} -
-
-
+ <> + + setApiConfigurationField("rateLimitSeconds", value)} + /> + )}
) diff --git a/webview-ui/src/components/settings/RateLimitSecondsControl.tsx b/webview-ui/src/components/settings/RateLimitSecondsControl.tsx new file mode 100644 index 00000000000..b01afd0ace5 --- /dev/null +++ b/webview-ui/src/components/settings/RateLimitSecondsControl.tsx @@ -0,0 +1,38 @@ +import React, { useCallback } from "react" +import { Slider } from "@/components/ui" +import { useAppTranslation } from "@/i18n/TranslationContext" + +interface RateLimitSecondsControlProps { + value: number + onChange: (value: number) => void +} + +export const RateLimitSecondsControl: React.FC = ({ value, onChange }) => { + const { t } = useAppTranslation() + + const handleValueChange = useCallback( + (newValue: number) => { + onChange(newValue) + }, + [onChange], + ) + + return ( +
+ +
+ handleValueChange(newValue[0])} + /> + {value}s +
+
+ {t("settings:providers.rateLimitSeconds.description", { value })} +
+
+ ) +} diff --git a/webview-ui/src/components/settings/SettingsView.tsx b/webview-ui/src/components/settings/SettingsView.tsx index 0171537b9e0..f3da7c363c2 100644 --- a/webview-ui/src/components/settings/SettingsView.tsx +++ b/webview-ui/src/components/settings/SettingsView.tsx @@ -118,7 +118,6 @@ const SettingsView = forwardRef(({ onDone }, maxOpenTabsContext, maxWorkspaceFiles, mcpEnabled, - rateLimitSeconds, requestDelaySeconds, remoteBrowserHost, screenshotQuality, @@ -240,7 +239,6 @@ const SettingsView = forwardRef(({ onDone }, vscode.postMessage({ type: "mcpEnabled", bool: mcpEnabled }) vscode.postMessage({ type: "alwaysApproveResubmit", bool: alwaysApproveResubmit }) vscode.postMessage({ type: "requestDelaySeconds", value: requestDelaySeconds }) - vscode.postMessage({ type: "rateLimitSeconds", value: rateLimitSeconds }) vscode.postMessage({ type: "maxOpenTabsContext", value: maxOpenTabsContext }) vscode.postMessage({ type: "maxWorkspaceFiles", value: maxWorkspaceFiles ?? 200 }) vscode.postMessage({ type: "showRooIgnoredFiles", bool: showRooIgnoredFiles }) @@ -477,7 +475,6 @@ const SettingsView = forwardRef(({ onDone },
({ ), })) +jest.mock("../RateLimitSecondsControl", () => ({ + RateLimitSecondsControl: ({ value, onChange }: any) => ( +
+ onChange(parseFloat(e.target.value))} + min={0} + max={60} + step={1} + /> +
+ ), +})) + // Mock ThinkingBudget component jest.mock("../ThinkingBudget", () => ({ ThinkingBudget: ({ apiConfiguration, setApiConfigurationField, modelInfo, provider }: any) => @@ -101,14 +116,16 @@ const renderApiOptions = (props = {}) => { } describe("ApiOptions", () => { - it("shows temperature control by default", () => { + it("shows temperature and rate limit controls by default", () => { renderApiOptions() expect(screen.getByTestId("temperature-control")).toBeInTheDocument() + expect(screen.getByTestId("rate-limit-seconds-control")).toBeInTheDocument() }) - it("hides temperature control when fromWelcomeView is true", () => { + it("hides temperature and rate limit controls when fromWelcomeView is true", () => { renderApiOptions({ fromWelcomeView: true }) expect(screen.queryByTestId("temperature-control")).not.toBeInTheDocument() + expect(screen.queryByTestId("rate-limit-seconds-control")).not.toBeInTheDocument() }) describe("thinking functionality", () => { diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index 60c944a3af9..a84b51c92bc 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -218,6 +218,10 @@ } }, "resetDefaults": "Restablir als valors per defecte" + }, + "rateLimit": { + "label": "Limit de velocitat", + "description": "Temps mínim entre sol·licituds d'API." } }, "browser": { diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index cc64250fe88..13104487192 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -218,6 +218,10 @@ } }, "resetDefaults": "Auf Standardwerte zurücksetzen" + }, + "rateLimit": { + "label": "Ratenbegrenzung", + "description": "Minimale Zeit zwischen API-Anfragen." } }, "browser": { diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index cd0dbde2049..757fc299281 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -218,6 +218,10 @@ } }, "resetDefaults": "Reset to Defaults" + }, + "rateLimitSeconds": { + "label": "Rate limit", + "description": "Minimum time between API requests." } }, "browser": { @@ -298,10 +302,6 @@ } }, "advanced": { - "rateLimit": { - "label": "Rate limit", - "description": "Minimum time between API requests." - }, "diff": { "label": "Enable editing through diffs", "description": "When enabled, Roo will be able to edit files more quickly and will automatically reject truncated full-file writes. Works best with the latest Claude 3.7 Sonnet model.", diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index a884db41421..368c1edad8c 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -218,6 +218,10 @@ } }, "resetDefaults": "Restablecer valores predeterminados" + }, + "rateLimit": { + "label": "Límite de tasa", + "description": "Tiempo mínimo entre solicitudes de API." } }, "browser": { diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 9ba21b985a0..84fc07810f0 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -218,6 +218,10 @@ } }, "resetDefaults": "Réinitialiser les valeurs par défaut" + }, + "rateLimit": { + "label": "Limite de débit", + "description": "Temps minimum entre les requêtes API." } }, "browser": { diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index 8ab10bb23ea..f6e87a9a32e 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -218,6 +218,10 @@ } }, "resetDefaults": "डिफ़ॉल्ट पर रीसेट करें" + }, + "rateLimit": { + "label": "दर सीमा", + "description": "API अनुरोधों के बीच न्यूनतम समय।" } }, "browser": { diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index f210cd76e9f..3053e210fae 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -218,6 +218,10 @@ } }, "resetDefaults": "Ripristina valori predefiniti" + }, + "rateLimit": { + "label": "Limite di frequenza", + "description": "Tempo minimo tra le richieste API." } }, "browser": { diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index 8697141a49b..b524af352bd 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -218,6 +218,10 @@ } }, "resetDefaults": "デフォルトにリセット" + }, + "rateLimit": { + "label": "レート制限", + "description": "APIリクエスト間の最小時間。" } }, "browser": { diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index 1b28c60368c..cbec654db72 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -218,6 +218,10 @@ } }, "resetDefaults": "기본값으로 재설정" + }, + "rateLimit": { + "label": "속도 제한", + "description": "API 요청 간 최소 시간입니다." } }, "browser": { diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index 0dda4dfae6a..c844bc663e8 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -218,6 +218,10 @@ } }, "resetDefaults": "Przywróć domyślne" + }, + "rateLimit": { + "label": "Limit szybkości", + "description": "Minimalny czas między żądaniami API." } }, "browser": { diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index e13f9cb3020..708dd0a0a50 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -218,6 +218,10 @@ } }, "resetDefaults": "Restaurar Padrões" + }, + "rateLimit": { + "label": "Limite de taxa", + "description": "Tempo mínimo entre requisições de API." } }, "browser": { diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index 6766a91cf1f..444f117c57a 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -218,6 +218,10 @@ } }, "resetDefaults": "Varsayılanlara Sıfırla" + }, + "rateLimit": { + "label": "Hız sınırı", + "description": "API istekleri arasındaki minimum süre." } }, "browser": { diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index 04f36f5c852..104abbc84b7 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -218,6 +218,10 @@ } }, "resetDefaults": "Đặt lại về mặc định" + }, + "rateLimit": { + "label": "Giới hạn tốc độ", + "description": "Thời gian tối thiểu giữa các yêu cầu API." } }, "browser": { diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index 1836faebfc8..7592db292d4 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -218,6 +218,10 @@ } }, "resetDefaults": "重置为默认值" + }, + "rateLimit": { + "label": "请求频率限制", + "description": "设置API请求的最小间隔时间" } }, "browser": { diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index 18e86e6b3f2..d264ad78b29 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -218,6 +218,10 @@ } }, "resetDefaults": "重設為預設值" + }, + "rateLimit": { + "label": "速率限制", + "description": "設定 API 請求間的最短時間" } }, "browser": { From 91176d1a06550ba2edfc621a6fe6fb8fefa018df Mon Sep 17 00:00:00 2001 From: Ross McFarland Date: Mon, 7 Apr 2025 07:42:30 -0700 Subject: [PATCH 2/4] Correct rateLimitSeconds translations --- webview-ui/src/i18n/locales/ca/settings.json | 8 ++------ webview-ui/src/i18n/locales/de/settings.json | 6 +----- webview-ui/src/i18n/locales/es/settings.json | 6 +----- webview-ui/src/i18n/locales/fr/settings.json | 6 +----- webview-ui/src/i18n/locales/hi/settings.json | 6 +----- webview-ui/src/i18n/locales/it/settings.json | 6 +----- webview-ui/src/i18n/locales/ja/settings.json | 6 +----- webview-ui/src/i18n/locales/ko/settings.json | 8 ++------ webview-ui/src/i18n/locales/pl/settings.json | 6 +----- webview-ui/src/i18n/locales/pt-BR/settings.json | 6 +----- webview-ui/src/i18n/locales/tr/settings.json | 6 +----- webview-ui/src/i18n/locales/vi/settings.json | 6 +----- webview-ui/src/i18n/locales/zh-CN/settings.json | 6 +----- webview-ui/src/i18n/locales/zh-TW/settings.json | 8 ++------ 14 files changed, 17 insertions(+), 73 deletions(-) diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index a84b51c92bc..715450014db 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -219,8 +219,8 @@ }, "resetDefaults": "Restablir als valors per defecte" }, - "rateLimit": { - "label": "Limit de velocitat", + "rateLimitSeconds": { + "label": "Límit de freqüència", "description": "Temps mínim entre sol·licituds d'API." } }, @@ -302,10 +302,6 @@ } }, "advanced": { - "rateLimit": { - "label": "Límit de freqüència", - "description": "Temps mínim entre sol·licituds d'API." - }, "diff": { "label": "Habilitar edició mitjançant diffs", "description": "Quan està habilitat, Roo podrà editar fitxers més ràpidament i rebutjarà automàticament escriptures completes de fitxers truncats. Funciona millor amb l'últim model Claude 3.7 Sonnet.", diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index 13104487192..c5f7eb083b4 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -219,7 +219,7 @@ }, "resetDefaults": "Auf Standardwerte zurücksetzen" }, - "rateLimit": { + "rateLimitSeconds": { "label": "Ratenbegrenzung", "description": "Minimale Zeit zwischen API-Anfragen." } @@ -302,10 +302,6 @@ } }, "advanced": { - "rateLimit": { - "label": "Ratenbegrenzung", - "description": "Minimale Zeit zwischen API-Anfragen." - }, "diff": { "label": "Bearbeitung durch Diffs aktivieren", "description": "Wenn aktiviert, kann Roo Dateien schneller bearbeiten und lehnt automatisch gekürzte vollständige Dateischreibvorgänge ab. Funktioniert am besten mit dem neuesten Claude 3.7 Sonnet-Modell.", diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index 368c1edad8c..700ce2f82e6 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -219,7 +219,7 @@ }, "resetDefaults": "Restablecer valores predeterminados" }, - "rateLimit": { + "rateLimitSeconds": { "label": "Límite de tasa", "description": "Tiempo mínimo entre solicitudes de API." } @@ -302,10 +302,6 @@ } }, "advanced": { - "rateLimit": { - "label": "Límite de tasa", - "description": "Tiempo mínimo entre solicitudes de API." - }, "diff": { "label": "Habilitar edición a través de diffs", "description": "Cuando está habilitado, Roo podrá editar archivos más rápidamente y rechazará automáticamente escrituras completas de archivos truncados. Funciona mejor con el último modelo Claude 3.7 Sonnet.", diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 84fc07810f0..54b51b77e69 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -219,7 +219,7 @@ }, "resetDefaults": "Réinitialiser les valeurs par défaut" }, - "rateLimit": { + "rateLimitSecons": { "label": "Limite de débit", "description": "Temps minimum entre les requêtes API." } @@ -302,10 +302,6 @@ } }, "advanced": { - "rateLimit": { - "label": "Limite de débit", - "description": "Temps minimum entre les requêtes API." - }, "diff": { "label": "Activer l'édition via des diffs", "description": "Lorsque cette option est activée, Roo pourra éditer des fichiers plus rapidement et rejettera automatiquement les écritures de fichiers complets tronqués. Fonctionne mieux avec le dernier modèle Claude 3.7 Sonnet.", diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index f6e87a9a32e..0bbc862a6b9 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -219,7 +219,7 @@ }, "resetDefaults": "डिफ़ॉल्ट पर रीसेट करें" }, - "rateLimit": { + "rateLimitSeconds": { "label": "दर सीमा", "description": "API अनुरोधों के बीच न्यूनतम समय।" } @@ -302,10 +302,6 @@ } }, "advanced": { - "rateLimit": { - "label": "दर सीमा", - "description": "API अनुरोधों के बीच न्यूनतम समय।" - }, "diff": { "label": "diffs के माध्यम से संपादन सक्षम करें", "description": "जब सक्षम होता है, Roo फाइलों को तेजी से संपादित कर सकेगा और स्वचालित रूप से काटे गए पूर्ण-फाइल लेखन को अस्वीकार करेगा। नवीनतम Claude 3.7 Sonnet मॉडल के साथ सबसे अच्छा काम करता है।", diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index 3053e210fae..d8ce9e4d88f 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -219,7 +219,7 @@ }, "resetDefaults": "Ripristina valori predefiniti" }, - "rateLimit": { + "rateLimitSeconds": { "label": "Limite di frequenza", "description": "Tempo minimo tra le richieste API." } @@ -302,10 +302,6 @@ } }, "advanced": { - "rateLimit": { - "label": "Limite di frequenza", - "description": "Tempo minimo tra le richieste API." - }, "diff": { "label": "Abilita modifica tramite diff", "description": "Quando abilitato, Roo sarà in grado di modificare i file più velocemente e rifiuterà automaticamente scritture di file completi troncati. Funziona meglio con l'ultimo modello Claude 3.7 Sonnet.", diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index b524af352bd..bbe187bae2b 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -219,7 +219,7 @@ }, "resetDefaults": "デフォルトにリセット" }, - "rateLimit": { + "rateLimitSeconds": { "label": "レート制限", "description": "APIリクエスト間の最小時間。" } @@ -302,10 +302,6 @@ } }, "advanced": { - "rateLimit": { - "label": "レート制限", - "description": "APIリクエスト間の最小時間。" - }, "diff": { "label": "diff経由の編集を有効化", "description": "有効にすると、Rooはファイルをより迅速に編集でき、切り詰められた全ファイル書き込みを自動的に拒否します。最新のClaude 3.7 Sonnetモデルで最良に機能します。", diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index cbec654db72..3b1fc76e134 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -219,9 +219,9 @@ }, "resetDefaults": "기본값으로 재설정" }, - "rateLimit": { + "rateLimitSeconds": { "label": "속도 제한", - "description": "API 요청 간 최소 시간입니다." + "description": "API 요청 간 최소 시간." } }, "browser": { @@ -302,10 +302,6 @@ } }, "advanced": { - "rateLimit": { - "label": "속도 제한", - "description": "API 요청 간 최소 시간." - }, "diff": { "label": "diff를 통한 편집 활성화", "description": "활성화되면 Roo는 파일을 더 빠르게 편집할 수 있으며 잘린 전체 파일 쓰기를 자동으로 거부합니다. 최신 Claude 3.7 Sonnet 모델에서 가장 잘 작동합니다.", diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index c844bc663e8..d456ea42526 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -219,7 +219,7 @@ }, "resetDefaults": "Przywróć domyślne" }, - "rateLimit": { + "rateLimitSeconds": { "label": "Limit szybkości", "description": "Minimalny czas między żądaniami API." } @@ -302,10 +302,6 @@ } }, "advanced": { - "rateLimit": { - "label": "Limit szybkości", - "description": "Minimalny czas między żądaniami API." - }, "diff": { "label": "Włącz edycję przez różnice", "description": "Gdy włączone, Roo będzie w stanie edytować pliki szybciej i automatycznie odrzuci obcięte pełne zapisy plików. Działa najlepiej z najnowszym modelem Claude 3.7 Sonnet.", diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index 708dd0a0a50..dfd072b5285 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -219,7 +219,7 @@ }, "resetDefaults": "Restaurar Padrões" }, - "rateLimit": { + "rateLimitSeconds": { "label": "Limite de taxa", "description": "Tempo mínimo entre requisições de API." } @@ -302,10 +302,6 @@ } }, "advanced": { - "rateLimit": { - "label": "Limite de taxa", - "description": "Tempo mínimo entre requisições de API." - }, "diff": { "label": "Ativar edição através de diffs", "description": "Quando ativado, o Roo poderá editar arquivos mais rapidamente e rejeitará automaticamente escritas completas de arquivos truncados. Funciona melhor com o modelo mais recente Claude 3.7 Sonnet.", diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index 444f117c57a..38cf4192c30 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -219,7 +219,7 @@ }, "resetDefaults": "Varsayılanlara Sıfırla" }, - "rateLimit": { + "rateLimitSeconds": { "label": "Hız sınırı", "description": "API istekleri arasındaki minimum süre." } @@ -302,10 +302,6 @@ } }, "advanced": { - "rateLimit": { - "label": "Hız sınırı", - "description": "API istekleri arasındaki minimum süre." - }, "diff": { "label": "Diff'ler aracılığıyla düzenlemeyi etkinleştir", "description": "Etkinleştirildiğinde, Roo dosyaları daha hızlı düzenleyebilecek ve kesik tam dosya yazımlarını otomatik olarak reddedecektir. En son Claude 3.7 Sonnet modeliyle en iyi şekilde çalışır.", diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index 104abbc84b7..d30d897af02 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -219,7 +219,7 @@ }, "resetDefaults": "Đặt lại về mặc định" }, - "rateLimit": { + "rateLimitSeconds": { "label": "Giới hạn tốc độ", "description": "Thời gian tối thiểu giữa các yêu cầu API." } @@ -302,10 +302,6 @@ } }, "advanced": { - "rateLimit": { - "label": "Giới hạn tốc độ", - "description": "Thời gian tối thiểu giữa các yêu cầu API." - }, "diff": { "label": "Bật chỉnh sửa qua diff", "description": "Khi được bật, Roo sẽ có thể chỉnh sửa tệp nhanh hơn và sẽ tự động từ chối ghi toàn bộ tệp bị cắt ngắn. Hoạt động tốt nhất với mô hình Claude 3.7 Sonnet mới nhất.", diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index 7592db292d4..0c03dd8fdb5 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -219,7 +219,7 @@ }, "resetDefaults": "重置为默认值" }, - "rateLimit": { + "rateLimitSeconds": { "label": "请求频率限制", "description": "设置API请求的最小间隔时间" } @@ -302,10 +302,6 @@ } }, "advanced": { - "rateLimit": { - "label": "请求频率限制", - "description": "设置API请求的最小间隔时间" - }, "diff": { "label": "启用diff更新", "description": "启用后,Roo 将能够通过差异算法写入,避免模型输出完整文件,以降低Token消耗。与最新的 Claude 3.7 Sonnet 模型配合最佳。", diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index d264ad78b29..67182010301 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -219,9 +219,9 @@ }, "resetDefaults": "重設為預設值" }, - "rateLimit": { + "rateLimitSeconds": { "label": "速率限制", - "description": "設定 API 請求間的最短時間" + "description": "API 請求間的最短時間" } }, "browser": { @@ -302,10 +302,6 @@ } }, "advanced": { - "rateLimit": { - "label": "速率限制", - "description": "API 請求間的最短時間" - }, "diff": { "label": "透過差異比對編輯", "description": "啟用後,Roo 可更快速地編輯檔案,並自動拒絕不完整的整檔覆寫。搭配最新的 Claude 3.7 Sonnet 模型效果最佳。", From 0f8b5f111b108ab4f09867fff0db4a06cd0bc256 Mon Sep 17 00:00:00 2001 From: Ross McFarland Date: Mon, 7 Apr 2025 07:47:31 -0700 Subject: [PATCH 3/4] Add missing d to rateLimitSecondsMigrate --- src/core/config/__tests__/ProviderSettingsManager.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/config/__tests__/ProviderSettingsManager.test.ts b/src/core/config/__tests__/ProviderSettingsManager.test.ts index 1ce370bf039..b1a85075464 100644 --- a/src/core/config/__tests__/ProviderSettingsManager.test.ts +++ b/src/core/config/__tests__/ProviderSettingsManager.test.ts @@ -111,7 +111,7 @@ describe("ProviderSettingsManager", () => { }, }, migrations: { - rateLimitSecondsMigrate: false, + rateLimitSecondsMigrated: false, }, }), ) From 1e9fa727a58738b5520ba5a5d098beaeacfd9b58 Mon Sep 17 00:00:00 2001 From: Ross McFarland Date: Mon, 7 Apr 2025 07:56:06 -0700 Subject: [PATCH 4/4] Fix fr rate-limit translation --- webview-ui/src/i18n/locales/fr/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 54b51b77e69..039a0168f91 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -219,7 +219,7 @@ }, "resetDefaults": "Réinitialiser les valeurs par défaut" }, - "rateLimitSecons": { + "rateLimitSeconds": { "label": "Limite de débit", "description": "Temps minimum entre les requêtes API." }