diff --git a/src/api/providers/__tests__/virtual-quota-fallback-provider.spec.ts b/src/api/providers/__tests__/virtual-quota-fallback-provider.spec.ts index 0a8d52988f9..8b95c16f166 100644 --- a/src/api/providers/__tests__/virtual-quota-fallback-provider.spec.ts +++ b/src/api/providers/__tests__/virtual-quota-fallback-provider.spec.ts @@ -552,7 +552,7 @@ describe("VirtualQuotaFallbackProvider", () => { id: "", info: { maxTokens: 1, - contextWindow: 1, + contextWindow: 1000000, supportsPromptCache: false, }, }) diff --git a/src/api/providers/virtual-quota-fallback.ts b/src/api/providers/virtual-quota-fallback.ts index f36d8c835f0..d0ee9ccdaa0 100644 --- a/src/api/providers/virtual-quota-fallback.ts +++ b/src/api/providers/virtual-quota-fallback.ts @@ -99,12 +99,12 @@ export class VirtualQuotaFallbackHandler extends EventEmitter implements ApiHand yield chunk } } catch (error) { - // Check if this is a retryable + // Check if this is a retryable error (rate limit or overload) if (this.isRateLimitError(error) || this.isOverloadError(error)) { - // Set cooldown for the current provider - await this.usage.setCooldown(this.activeProfileId, 10 * 60 * 1000) + // Set a short cooldown (10 seconds) to prevent rapid cycling + await this.usage.setCooldown(this.activeProfileId, 10 * 1000) - // Switch to a different provider + // Switch to a different provider and retry await this.adjustActiveHandler("Retryable Error") // Retry the request with the new provider @@ -112,8 +112,8 @@ export class VirtualQuotaFallbackHandler extends EventEmitter implements ApiHand return } - // For non-rate limit errors, set cooldown and rethrow - await this.usage.setCooldown(this.activeProfileId, 10 * 60 * 1000) + // For non-retryable errors, set cooldown and rethrow + await this.usage.setCooldown(this.activeProfileId, 10 * 1000) throw error } } catch (error) { @@ -130,7 +130,7 @@ export class VirtualQuotaFallbackHandler extends EventEmitter implements ApiHand id: "", info: { maxTokens: 1, - contextWindow: 1, + contextWindow: 1000000, supportsPromptCache: false, }, } @@ -138,9 +138,17 @@ export class VirtualQuotaFallbackHandler extends EventEmitter implements ApiHand return this.activeHandler.getModel() } + getActiveProfileNumber(): number | undefined { + if (!this.activeProfileId) { + return undefined + } + const index = this.handlerConfigs.findIndex((c) => c.profileId === this.activeProfileId) + return index >= 0 ? index + 1 : undefined + } + get contextWindow(): number { if (!this.activeHandler) { - return 1 // Default fallback + return 1000000 // Default fallback } const model = this.activeHandler.getModel() return model.info.contextWindow diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 296d3eb3021..7ae77a2e490 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -88,6 +88,7 @@ import { t } from "../../i18n" import { buildApiHandler } from "../../api" import { forceFullModelDetailsLoad, hasLoadedFullDetails } from "../../api/providers/fetchers/lmstudio" +import { VirtualQuotaFallbackHandler } from "../../api/providers/virtual-quota-fallback" import { ContextProxy } from "../config/ContextProxy" import { getEnabledRules } from "./kilorules" @@ -2190,7 +2191,13 @@ export class ClineProvider // kilocode_change start: Get active model for virtual quota fallback UI display const virtualQuotaActiveModel = apiConfiguration?.apiProvider === "virtual-quota-fallback" && this.getCurrentTask() - ? this.getCurrentTask()!.api.getModel() + ? { + ...this.getCurrentTask()!.api.getModel(), + activeProfileNumber: + this.getCurrentTask()!.api instanceof VirtualQuotaFallbackHandler + ? (this.getCurrentTask()!.api as VirtualQuotaFallbackHandler).getActiveProfileNumber() + : undefined, + } : undefined // kilocode_change end diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index ab41fa022ca..ef634af39fe 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -549,7 +549,7 @@ export type ExtensionState = Pick< remoteControlEnabled: boolean taskSyncEnabled: boolean featureRoomoteControlEnabled: boolean - virtualQuotaActiveModel?: { id: string; info: ModelInfo } // kilocode_change: Add virtual quota active model for UI display + virtualQuotaActiveModel?: { id: string; info: ModelInfo; activeProfileNumber?: number } // kilocode_change: Add virtual quota active model for UI display with profile number showTimestamps?: boolean // kilocode_change: Show timestamps in chat messages claudeCodeIsAuthenticated?: boolean debug?: boolean diff --git a/webview-ui/src/components/kilocode/BottomApiConfig.tsx b/webview-ui/src/components/kilocode/BottomApiConfig.tsx index dd177255c5f..26748e31624 100644 --- a/webview-ui/src/components/kilocode/BottomApiConfig.tsx +++ b/webview-ui/src/components/kilocode/BottomApiConfig.tsx @@ -21,7 +21,11 @@ export const BottomApiConfig = () => { //kilocode_change: Pass virtual quota active model to ModelSelector virtualQuotaActiveModel={ virtualQuotaActiveModel - ? { id: virtualQuotaActiveModel.id, name: virtualQuotaActiveModel.id } + ? { + id: virtualQuotaActiveModel.id, + name: virtualQuotaActiveModel.id, + activeProfileNumber: virtualQuotaActiveModel.activeProfileNumber, + } : undefined } /> diff --git a/webview-ui/src/components/kilocode/chat/ModelSelector.tsx b/webview-ui/src/components/kilocode/chat/ModelSelector.tsx index a22fb30538b..dfdd2f32ef4 100644 --- a/webview-ui/src/components/kilocode/chat/ModelSelector.tsx +++ b/webview-ui/src/components/kilocode/chat/ModelSelector.tsx @@ -13,7 +13,7 @@ interface ModelSelectorProps { currentApiConfigName?: string apiConfiguration: ProviderSettings fallbackText: string - virtualQuotaActiveModel?: { id: string; name: string } // kilocode_change: Add virtual quota active model for UI display + virtualQuotaActiveModel?: { id: string; name: string; activeProfileNumber?: number } // kilocode_change: Add virtual quota active model for UI display } export const ModelSelector = ({ @@ -123,6 +123,9 @@ export const ModelSelector = ({ return ( {prettyModelName(virtualQuotaActiveModel.id)} + {virtualQuotaActiveModel.activeProfileNumber !== undefined && ( + <> ({virtualQuotaActiveModel.activeProfileNumber}) + )} ) }