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..b1a85075464 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: { + rateLimitSecondsMigrated: 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..715450014db 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" + }, + "rateLimitSeconds": { + "label": "Límit de freqüència", + "description": "Temps mínim entre sol·licituds d'API." } }, "browser": { @@ -298,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 cc64250fe88..c5f7eb083b4 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" + }, + "rateLimitSeconds": { + "label": "Ratenbegrenzung", + "description": "Minimale Zeit zwischen API-Anfragen." } }, "browser": { @@ -298,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/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..700ce2f82e6 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" + }, + "rateLimitSeconds": { + "label": "Límite de tasa", + "description": "Tiempo mínimo entre solicitudes de API." } }, "browser": { @@ -298,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 9ba21b985a0..039a0168f91 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" + }, + "rateLimitSeconds": { + "label": "Limite de débit", + "description": "Temps minimum entre les requêtes API." } }, "browser": { @@ -298,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 8ab10bb23ea..0bbc862a6b9 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -218,6 +218,10 @@ } }, "resetDefaults": "डिफ़ॉल्ट पर रीसेट करें" + }, + "rateLimitSeconds": { + "label": "दर सीमा", + "description": "API अनुरोधों के बीच न्यूनतम समय।" } }, "browser": { @@ -298,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 f210cd76e9f..d8ce9e4d88f 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" + }, + "rateLimitSeconds": { + "label": "Limite di frequenza", + "description": "Tempo minimo tra le richieste API." } }, "browser": { @@ -298,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 8697141a49b..bbe187bae2b 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -218,6 +218,10 @@ } }, "resetDefaults": "デフォルトにリセット" + }, + "rateLimitSeconds": { + "label": "レート制限", + "description": "APIリクエスト間の最小時間。" } }, "browser": { @@ -298,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 1b28c60368c..3b1fc76e134 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -218,6 +218,10 @@ } }, "resetDefaults": "기본값으로 재설정" + }, + "rateLimitSeconds": { + "label": "속도 제한", + "description": "API 요청 간 최소 시간." } }, "browser": { @@ -298,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 0dda4dfae6a..d456ea42526 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" + }, + "rateLimitSeconds": { + "label": "Limit szybkości", + "description": "Minimalny czas między żądaniami API." } }, "browser": { @@ -298,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 e13f9cb3020..dfd072b5285 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" + }, + "rateLimitSeconds": { + "label": "Limite de taxa", + "description": "Tempo mínimo entre requisições de API." } }, "browser": { @@ -298,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 6766a91cf1f..38cf4192c30 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" + }, + "rateLimitSeconds": { + "label": "Hız sınırı", + "description": "API istekleri arasındaki minimum süre." } }, "browser": { @@ -298,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 04f36f5c852..d30d897af02 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" + }, + "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." } }, "browser": { @@ -298,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 1836faebfc8..0c03dd8fdb5 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": "重置为默认值" + }, + "rateLimitSeconds": { + "label": "请求频率限制", + "description": "设置API请求的最小间隔时间" } }, "browser": { @@ -298,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 18e86e6b3f2..67182010301 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": "重設為預設值" + }, + "rateLimitSeconds": { + "label": "速率限制", + "description": "API 請求間的最短時間" } }, "browser": { @@ -298,10 +302,6 @@ } }, "advanced": { - "rateLimit": { - "label": "速率限制", - "description": "API 請求間的最短時間" - }, "diff": { "label": "透過差異比對編輯", "description": "啟用後,Roo 可更快速地編輯檔案,並自動拒絕不完整的整檔覆寫。搭配最新的 Claude 3.7 Sonnet 模型效果最佳。",