mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-15 23:31:04 +00:00
Merge e509e15636 into c3cae397a1
This commit is contained in:
commit
db1ae3ce6a
8 changed files with 118 additions and 7 deletions
|
|
@ -198,6 +198,7 @@ export const globalSettingsSchema = z.object({
|
|||
customModePrompts: customModePromptsSchema.optional(),
|
||||
customSupportPrompts: customSupportPromptsSchema.optional(),
|
||||
enhancementApiConfigId: z.string().optional(),
|
||||
condensingApiConfigId: z.string().optional(),
|
||||
includeTaskHistoryInEnhance: z.boolean().optional(),
|
||||
historyPreviewCollapsed: z.boolean().optional(),
|
||||
reasoningBlockCollapsed: z.boolean().optional(),
|
||||
|
|
|
|||
|
|
@ -289,6 +289,7 @@ export type ExtensionState = Pick<
|
|||
| "customModePrompts"
|
||||
| "customSupportPrompts"
|
||||
| "enhancementApiConfigId"
|
||||
| "condensingApiConfigId"
|
||||
| "customCondensingPrompt"
|
||||
| "codebaseIndexConfig"
|
||||
| "codebaseIndexModels"
|
||||
|
|
@ -485,6 +486,7 @@ export interface WebviewMessage {
|
|||
| "copySystemPrompt"
|
||||
| "systemPrompt"
|
||||
| "enhancementApiConfigId"
|
||||
| "condensingApiConfigId"
|
||||
| "autoApprovalEnabled"
|
||||
| "updateCustomMode"
|
||||
| "deleteCustomMode"
|
||||
|
|
|
|||
|
|
@ -1645,6 +1645,42 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a dedicated API handler for context condensing if a condensing API config is set.
|
||||
* Falls back to the task's main API handler if no dedicated config is configured.
|
||||
*/
|
||||
private async buildCondensingApiHandler(): Promise<ApiHandler> {
|
||||
const provider = this.providerRef.deref()
|
||||
if (!provider) {
|
||||
return this.api
|
||||
}
|
||||
|
||||
const state = await provider.getState()
|
||||
const { condensingApiConfigId, listApiConfigMeta } = state ?? {}
|
||||
|
||||
if (
|
||||
condensingApiConfigId &&
|
||||
listApiConfigMeta?.find(({ id }: { id: string }) => id === condensingApiConfigId)
|
||||
) {
|
||||
try {
|
||||
const { name: _, ...providerSettings } = await provider.providerSettingsManager.getProfile({
|
||||
id: condensingApiConfigId,
|
||||
})
|
||||
|
||||
if (providerSettings.apiProvider) {
|
||||
return buildApiHandler(providerSettings)
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
`[Task#${this.taskId}] Failed to build condensing API handler, falling back to task handler:`,
|
||||
error,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return this.api
|
||||
}
|
||||
|
||||
public async condenseContext(): Promise<void> {
|
||||
// CRITICAL: Flush any pending tool results before condensing
|
||||
// to ensure tool_use/tool_result pairs are complete in history
|
||||
|
|
@ -1659,6 +1695,9 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
|
||||
const { contextTokens: prevContextTokens } = this.getTokenUsage()
|
||||
|
||||
// Build a dedicated API handler for condensing if configured
|
||||
const condensingApiHandler = await this.buildCondensingApiHandler()
|
||||
|
||||
// Build tools for condensing metadata (same tools used for normal API calls)
|
||||
const provider = this.providerRef.deref()
|
||||
let allTools: import("openai").default.Chat.ChatCompletionTool[] = []
|
||||
|
|
@ -1705,7 +1744,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
condenseId,
|
||||
} = await summarizeConversation({
|
||||
messages: this.apiConversationHistory,
|
||||
apiHandler: this.api,
|
||||
apiHandler: condensingApiHandler,
|
||||
systemPrompt,
|
||||
taskId: this.taskId,
|
||||
isAutomaticTrigger: false,
|
||||
|
|
@ -3887,13 +3926,16 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
// Generate environment details to include in the condensed summary
|
||||
const environmentDetails = await getEnvironmentDetails(this, true)
|
||||
|
||||
// Build a dedicated API handler for condensing if configured
|
||||
const condensingApiHandler = await this.buildCondensingApiHandler()
|
||||
|
||||
// Force aggressive truncation by keeping only 75% of the conversation history
|
||||
const truncateResult = await manageContext({
|
||||
messages: this.apiConversationHistory,
|
||||
totalTokens: contextTokens || 0,
|
||||
maxTokens,
|
||||
contextWindow,
|
||||
apiHandler: this.api,
|
||||
apiHandler: condensingApiHandler,
|
||||
autoCondenseContext: true,
|
||||
autoCondenseContextPercent: FORCED_CONTEXT_REDUCTION_PERCENT,
|
||||
systemPrompt: await this.getSystemPrompt(),
|
||||
|
|
@ -4112,12 +4154,15 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
: undefined
|
||||
|
||||
try {
|
||||
// Build a dedicated API handler for condensing if configured
|
||||
const condensingApiHandler = await this.buildCondensingApiHandler()
|
||||
|
||||
const truncateResult = await manageContext({
|
||||
messages: this.apiConversationHistory,
|
||||
totalTokens: contextTokens,
|
||||
maxTokens,
|
||||
contextWindow,
|
||||
apiHandler: this.api,
|
||||
apiHandler: condensingApiHandler,
|
||||
autoCondenseContext,
|
||||
autoCondenseContextPercent,
|
||||
systemPrompt,
|
||||
|
|
|
|||
|
|
@ -2170,6 +2170,7 @@ export class ClineProvider
|
|||
customModePrompts,
|
||||
customSupportPrompts,
|
||||
enhancementApiConfigId,
|
||||
condensingApiConfigId,
|
||||
autoApprovalEnabled,
|
||||
customModes,
|
||||
experiments,
|
||||
|
|
@ -2290,6 +2291,7 @@ export class ClineProvider
|
|||
customModePrompts: customModePrompts ?? {},
|
||||
customSupportPrompts: customSupportPrompts ?? {},
|
||||
enhancementApiConfigId,
|
||||
condensingApiConfigId,
|
||||
autoApprovalEnabled: autoApprovalEnabled ?? false,
|
||||
customModes,
|
||||
experiments: experiments ?? experimentDefault,
|
||||
|
|
@ -2520,6 +2522,7 @@ export class ClineProvider
|
|||
customModePrompts: stateValues.customModePrompts ?? {},
|
||||
customSupportPrompts: stateValues.customSupportPrompts ?? {},
|
||||
enhancementApiConfigId: stateValues.enhancementApiConfigId,
|
||||
condensingApiConfigId: stateValues.condensingApiConfigId,
|
||||
experiments: stateValues.experiments ?? experimentDefault,
|
||||
autoApprovalEnabled: stateValues.autoApprovalEnabled ?? false,
|
||||
customModes,
|
||||
|
|
|
|||
|
|
@ -1669,6 +1669,10 @@ export const webviewMessageHandler = async (
|
|||
await updateGlobalState("enhancementApiConfigId", message.text)
|
||||
await provider.postStateToWebview()
|
||||
break
|
||||
case "condensingApiConfigId":
|
||||
await updateGlobalState("condensingApiConfigId", message.text)
|
||||
await provider.postStateToWebview()
|
||||
break
|
||||
|
||||
case "autoApprovalEnabled":
|
||||
await updateGlobalState("autoApprovalEnabled", message.bool ?? false)
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ type ContextManagementSettingsProps = HTMLAttributes<HTMLDivElement> & {
|
|||
autoCondenseContext: boolean
|
||||
autoCondenseContextPercent: number
|
||||
listApiConfigMeta: any[]
|
||||
condensingApiConfigId?: string
|
||||
setCondensingApiConfigId: (value: string) => void
|
||||
maxOpenTabsContext: number
|
||||
maxWorkspaceFiles: number
|
||||
showRooIgnoredFiles?: boolean
|
||||
|
|
@ -67,6 +69,8 @@ export const ContextManagementSettings = ({
|
|||
autoCondenseContext,
|
||||
autoCondenseContextPercent,
|
||||
listApiConfigMeta,
|
||||
condensingApiConfigId,
|
||||
setCondensingApiConfigId,
|
||||
maxOpenTabsContext,
|
||||
maxWorkspaceFiles,
|
||||
showRooIgnoredFiles,
|
||||
|
|
@ -472,6 +476,52 @@ export const ContextManagementSettings = ({
|
|||
/>
|
||||
</SearchableSetting>
|
||||
|
||||
{/* Condensing API Configuration */}
|
||||
<SearchableSetting
|
||||
settingId="context-condensing-api-config"
|
||||
section="contextManagement"
|
||||
label={t("settings:contextManagement.condensingApiConfiguration.label")}>
|
||||
<div>
|
||||
<label className="block font-medium mb-1">
|
||||
{t("settings:contextManagement.condensingApiConfiguration.label")}
|
||||
</label>
|
||||
<div className="text-sm text-vscode-descriptionForeground mb-2">
|
||||
{t("settings:contextManagement.condensingApiConfiguration.description")}
|
||||
</div>
|
||||
<Select
|
||||
value={condensingApiConfigId || "-"}
|
||||
onValueChange={(value) => {
|
||||
const newConfigId = value === "-" ? "" : value
|
||||
setCondensingApiConfigId(newConfigId)
|
||||
vscode.postMessage({
|
||||
type: "condensingApiConfigId",
|
||||
text: value === "-" ? "" : value,
|
||||
})
|
||||
}}>
|
||||
<SelectTrigger data-testid="condensing-api-config-select" className="w-full">
|
||||
<SelectValue
|
||||
placeholder={t(
|
||||
"settings:contextManagement.condensingApiConfiguration.useCurrentConfig",
|
||||
)}
|
||||
/>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="-">
|
||||
{t("settings:contextManagement.condensingApiConfiguration.useCurrentConfig")}
|
||||
</SelectItem>
|
||||
{(listApiConfigMeta || []).map((config: any) => (
|
||||
<SelectItem
|
||||
key={config.id}
|
||||
value={config.id}
|
||||
data-testid={`condensing-${config.id}-option`}>
|
||||
{config.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</SearchableSetting>
|
||||
|
||||
{/* Auto Condense Context */}
|
||||
<SearchableSetting
|
||||
settingId="context-auto-condense"
|
||||
|
|
|
|||
|
|
@ -831,6 +831,10 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
|
|||
autoCondenseContext={autoCondenseContext}
|
||||
autoCondenseContextPercent={autoCondenseContextPercent}
|
||||
listApiConfigMeta={listApiConfigMeta ?? []}
|
||||
condensingApiConfigId={cachedState.condensingApiConfigId}
|
||||
setCondensingApiConfigId={(value) =>
|
||||
setCachedState((prev) => ({ ...prev, condensingApiConfigId: value }))
|
||||
}
|
||||
maxOpenTabsContext={maxOpenTabsContext}
|
||||
maxWorkspaceFiles={maxWorkspaceFiles ?? 200}
|
||||
showRooIgnoredFiles={showRooIgnoredFiles}
|
||||
|
|
|
|||
|
|
@ -89,6 +89,8 @@ describe("ContextManagementSettings", () => {
|
|||
autoCondenseContext: false,
|
||||
autoCondenseContextPercent: 80,
|
||||
listApiConfigMeta: [],
|
||||
condensingApiConfigId: undefined as string | undefined,
|
||||
setCondensingApiConfigId: vi.fn(),
|
||||
maxOpenTabsContext: 20,
|
||||
maxWorkspaceFiles: 200,
|
||||
showRooIgnoredFiles: false,
|
||||
|
|
@ -333,9 +335,9 @@ describe("ContextManagementSettings", () => {
|
|||
const slider = screen.getByTestId("condense-threshold-slider")
|
||||
expect(slider).toBeInTheDocument()
|
||||
|
||||
// Should render the profile select dropdown
|
||||
// Should render the profile select dropdown and condensing API config dropdown
|
||||
const selects = screen.getAllByRole("combobox")
|
||||
expect(selects).toHaveLength(1)
|
||||
expect(selects).toHaveLength(2)
|
||||
})
|
||||
|
||||
describe("Auto Condense Context functionality", () => {
|
||||
|
|
@ -368,8 +370,8 @@ describe("ContextManagementSettings", () => {
|
|||
|
||||
// Threshold settings should be visible
|
||||
expect(screen.getByTestId("condense-threshold-slider")).toBeInTheDocument()
|
||||
// One combobox for profile selection
|
||||
expect(screen.getAllByRole("combobox")).toHaveLength(1)
|
||||
// Two comboboxes: condensing API config + profile selection
|
||||
expect(screen.getAllByRole("combobox")).toHaveLength(2)
|
||||
})
|
||||
|
||||
it("updates auto condense context percent", () => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue