(
retryAttempt: number = 0,
options: { skipProviderRateLimit?: boolean } = {},
)
| 3970 | } |
| 3971 | |
| 3972 | public async *attemptApiRequest( |
| 3973 | retryAttempt: number = 0, |
| 3974 | options: { skipProviderRateLimit?: boolean } = {}, |
| 3975 | ): ApiStream { |
| 3976 | const state = await this.providerRef.deref()?.getState() |
| 3977 | |
| 3978 | const { |
| 3979 | apiConfiguration, |
| 3980 | autoApprovalEnabled, |
| 3981 | requestDelaySeconds, |
| 3982 | mode, |
| 3983 | autoCondenseContext = true, |
| 3984 | autoCondenseContextPercent = 100, |
| 3985 | profileThresholds = {}, |
| 3986 | } = state ?? {} |
| 3987 | |
| 3988 | // Get condensing configuration for automatic triggers. |
| 3989 | const customCondensingPrompt = state?.customSupportPrompts?.CONDENSE |
| 3990 | |
| 3991 | if (!options.skipProviderRateLimit) { |
| 3992 | await this.maybeWaitForProviderRateLimit(retryAttempt) |
| 3993 | } |
| 3994 | |
| 3995 | // Update last request time right before making the request so that subsequent |
| 3996 | // requests — even from new subtasks — will honour the provider's rate-limit. |
| 3997 | // |
| 3998 | // NOTE: When recursivelyMakeClineRequests handles rate limiting, it sets the |
| 3999 | // timestamp earlier to include the environment details build. We still set it |
| 4000 | // here for direct callers (tests) and for the case where we didn't rate-limit |
| 4001 | // in the caller. |
| 4002 | this.rateLimitClock.recordRequest() |
| 4003 | |
| 4004 | const systemPrompt = await this.getSystemPrompt() |
| 4005 | const { contextTokens } = this.getTokenUsage() |
| 4006 | |
| 4007 | if (contextTokens) { |
| 4008 | const modelInfo = this.api.getModel().info |
| 4009 | |
| 4010 | const maxTokens = getModelMaxOutputTokens({ |
| 4011 | modelId: this.api.getModel().id, |
| 4012 | model: modelInfo, |
| 4013 | settings: this.apiConfiguration, |
| 4014 | }) |
| 4015 | |
| 4016 | // vscode-lm condenses against its static-table maxInputTokens (not the inflated live window); |
| 4017 | // only it implements getCondenseContextWindow, so others fall back to the full contextWindow. |
| 4018 | const contextWindow = this.api.getCondenseContextWindow?.() ?? modelInfo.contextWindow |
| 4019 | const useAvailableInputForContextPercent = typeof this.api.getCondenseContextWindow === "function" |
| 4020 | |
| 4021 | // Get the current profile ID using the helper method |
| 4022 | const currentProfileId = this.getCurrentProfileId(state) |
| 4023 | // Check if context management will likely run (threshold check) |
| 4024 | // This allows us to show an in-progress indicator to the user |
| 4025 | // We use the centralized willManageContext helper to avoid duplicating threshold logic |
| 4026 | const lastMessage = this.apiConversationHistory[this.apiConversationHistory.length - 1] |
| 4027 | const lastMessageContent = lastMessage?.content |
| 4028 | let lastMessageTokens = 0 |
| 4029 | if (lastMessageContent) { |
no test coverage detected