mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
fix(condense): remove custom condensing model option (#10901)
* fix(condense): remove custom condensing model option Remove the ability to specify a different model/API configuration for condensing conversations. Modern conversations include provider-specific data (tool calls, reasoning blocks, thought signatures) that only the originating model can properly understand and summarize. Changes: - Remove condensingApiHandler parameter from summarizeConversation() - Remove condensingApiConfigId from context management and Task - Remove API config dropdown for CONDENSE in settings UI - Update telemetry to remove usedCustomApiHandler parameter - Update related tests Users can still customize the CONDENSE prompt text; only model selection is removed. * fix: remove condensingApiConfigId from types and test fixtures --------- Co-authored-by: Roo Code <roomote@roocode.com>
This commit is contained in:
parent
f98dc1389e
commit
9d65772d24
15 changed files with 74 additions and 385 deletions
|
|
@ -127,17 +127,11 @@ export class TelemetryService {
|
|||
this.captureEvent(TelemetryEventName.CHECKPOINT_RESTORED, { taskId })
|
||||
}
|
||||
|
||||
public captureContextCondensed(
|
||||
taskId: string,
|
||||
isAutomaticTrigger: boolean,
|
||||
usedCustomPrompt?: boolean,
|
||||
usedCustomApiHandler?: boolean,
|
||||
): void {
|
||||
public captureContextCondensed(taskId: string, isAutomaticTrigger: boolean, usedCustomPrompt?: boolean): void {
|
||||
this.captureEvent(TelemetryEventName.CONTEXT_CONDENSED, {
|
||||
taskId,
|
||||
isAutomaticTrigger,
|
||||
...(usedCustomPrompt !== undefined && { usedCustomPrompt }),
|
||||
...(usedCustomApiHandler !== undefined && { usedCustomApiHandler }),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,6 @@ export const globalSettingsSchema = z.object({
|
|||
openRouterImageApiKey: z.string().optional(),
|
||||
openRouterImageGenerationSelectedModel: z.string().optional(),
|
||||
|
||||
condensingApiConfigId: z.string().optional(),
|
||||
customCondensingPrompt: z.string().optional(),
|
||||
|
||||
autoApprovalEnabled: z.boolean().optional(),
|
||||
|
|
|
|||
|
|
@ -324,7 +324,6 @@ export type ExtensionState = Pick<
|
|||
| "customModePrompts"
|
||||
| "customSupportPrompts"
|
||||
| "enhancementApiConfigId"
|
||||
| "condensingApiConfigId"
|
||||
| "customCondensingPrompt"
|
||||
| "codebaseIndexConfig"
|
||||
| "codebaseIndexModels"
|
||||
|
|
|
|||
|
|
@ -1055,7 +1055,7 @@ describe("summarizeConversation", () => {
|
|||
expect(mockApiHandler.createMessage).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("should return error when both condensing and main API handlers are invalid", async () => {
|
||||
it("should return error when API handler is invalid", async () => {
|
||||
const messages: ApiMessage[] = [
|
||||
{ role: "user", content: "Hello", ts: 1 },
|
||||
{ role: "assistant", content: "Hi there", ts: 2 },
|
||||
|
|
@ -1066,14 +1066,8 @@ describe("summarizeConversation", () => {
|
|||
{ role: "user", content: "Tell me more", ts: 7 },
|
||||
]
|
||||
|
||||
// Create invalid handlers (missing createMessage)
|
||||
const invalidMainHandler = {
|
||||
countTokens: vi.fn(),
|
||||
getModel: vi.fn(),
|
||||
// createMessage is missing
|
||||
} as unknown as ApiHandler
|
||||
|
||||
const invalidCondensingHandler = {
|
||||
// Create invalid handler (missing createMessage)
|
||||
const invalidHandler = {
|
||||
countTokens: vi.fn(),
|
||||
getModel: vi.fn(),
|
||||
// createMessage is missing
|
||||
|
|
@ -1086,16 +1080,13 @@ describe("summarizeConversation", () => {
|
|||
|
||||
const result = await summarizeConversation(
|
||||
messages,
|
||||
invalidMainHandler,
|
||||
invalidHandler,
|
||||
defaultSystemPrompt,
|
||||
taskId,
|
||||
DEFAULT_PREV_CONTEXT_TOKENS,
|
||||
false,
|
||||
undefined,
|
||||
invalidCondensingHandler,
|
||||
)
|
||||
|
||||
// Should return original messages when both handlers are invalid
|
||||
// Should return original messages when handler is invalid
|
||||
expect(result.messages).toEqual(messages)
|
||||
expect(result.cost).toBe(0)
|
||||
expect(result.summary).toBe("")
|
||||
|
|
@ -1103,9 +1094,7 @@ describe("summarizeConversation", () => {
|
|||
expect(result.newContextTokens).toBeUndefined()
|
||||
|
||||
// Verify error was logged
|
||||
expect(mockError).toHaveBeenCalledWith(
|
||||
expect.stringContaining("Main API handler is also invalid for condensing"),
|
||||
)
|
||||
expect(mockError).toHaveBeenCalledWith(expect.stringContaining("API handler is invalid for condensing"))
|
||||
|
||||
// Restore console.error
|
||||
console.error = originalError
|
||||
|
|
@ -1157,10 +1146,6 @@ describe("summarizeConversation", () => {
|
|||
defaultSystemPrompt,
|
||||
taskId,
|
||||
DEFAULT_PREV_CONTEXT_TOKENS,
|
||||
false, // isAutomaticTrigger
|
||||
undefined, // customCondensingPrompt
|
||||
undefined, // condensingApiHandler
|
||||
true, // useNativeTools - required for tool_use block preservation
|
||||
)
|
||||
|
||||
// Find the summary message
|
||||
|
|
@ -1236,10 +1221,6 @@ describe("summarizeConversation", () => {
|
|||
defaultSystemPrompt,
|
||||
taskId,
|
||||
DEFAULT_PREV_CONTEXT_TOKENS,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
true,
|
||||
)
|
||||
|
||||
expect(result.error).toBeUndefined()
|
||||
|
|
@ -1315,10 +1296,6 @@ describe("summarizeConversation", () => {
|
|||
defaultSystemPrompt,
|
||||
taskId,
|
||||
DEFAULT_PREV_CONTEXT_TOKENS,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
true,
|
||||
)
|
||||
|
||||
// Find the summary message (it has isSummary: true)
|
||||
|
|
@ -1389,10 +1366,6 @@ describe("summarizeConversation", () => {
|
|||
defaultSystemPrompt,
|
||||
taskId,
|
||||
DEFAULT_PREV_CONTEXT_TOKENS,
|
||||
false, // isAutomaticTrigger
|
||||
undefined, // customCondensingPrompt
|
||||
undefined, // condensingApiHandler
|
||||
true, // useNativeTools - required for tool_use block preservation
|
||||
)
|
||||
|
||||
// Find the summary message
|
||||
|
|
@ -1458,10 +1431,6 @@ describe("summarizeConversation", () => {
|
|||
defaultSystemPrompt,
|
||||
taskId,
|
||||
DEFAULT_PREV_CONTEXT_TOKENS,
|
||||
false, // isAutomaticTrigger
|
||||
undefined, // customCondensingPrompt
|
||||
undefined, // condensingApiHandler
|
||||
false, // useNativeTools - not using tools in this test
|
||||
)
|
||||
|
||||
// Find the summary message
|
||||
|
|
@ -1489,7 +1458,6 @@ describe("summarizeConversation", () => {
|
|||
describe("summarizeConversation with custom settings", () => {
|
||||
// Mock necessary dependencies
|
||||
let mockMainApiHandler: ApiHandler
|
||||
let mockCondensingApiHandler: ApiHandler
|
||||
const defaultSystemPrompt = "Default prompt"
|
||||
const taskId = "test-task"
|
||||
|
||||
|
|
@ -1511,7 +1479,7 @@ describe("summarizeConversation with custom settings", () => {
|
|||
// Reset telemetry mock
|
||||
;(TelemetryService.instance.captureContextCondensed as Mock).mockClear()
|
||||
|
||||
// Setup mock API handlers
|
||||
// Setup mock API handler
|
||||
mockMainApiHandler = {
|
||||
createMessage: vi.fn().mockImplementation(() => {
|
||||
return (async function* () {
|
||||
|
|
@ -1534,29 +1502,6 @@ describe("summarizeConversation with custom settings", () => {
|
|||
},
|
||||
}),
|
||||
} as unknown as ApiHandler
|
||||
|
||||
mockCondensingApiHandler = {
|
||||
createMessage: vi.fn().mockImplementation(() => {
|
||||
return (async function* () {
|
||||
yield { type: "text" as const, text: "Summary from condensing handler" }
|
||||
yield { type: "usage" as const, totalCost: 0.03, outputTokens: 80 }
|
||||
})()
|
||||
}),
|
||||
countTokens: vi.fn().mockImplementation(() => Promise.resolve(40)),
|
||||
getModel: vi.fn().mockReturnValue({
|
||||
id: "condensing-model",
|
||||
info: {
|
||||
contextWindow: 4000,
|
||||
supportsImages: true,
|
||||
supportsVision: false,
|
||||
maxTokens: 2000,
|
||||
supportsPromptCache: false,
|
||||
maxCachePoints: 0,
|
||||
minTokensPerCachePoint: 0,
|
||||
cachableFields: [],
|
||||
},
|
||||
}),
|
||||
} as unknown as ApiHandler
|
||||
})
|
||||
|
||||
/**
|
||||
|
|
@ -1619,84 +1564,6 @@ describe("summarizeConversation with custom settings", () => {
|
|||
expect(createMessageCalls[0][0]).toContain("Your task is to create a detailed summary")
|
||||
})
|
||||
|
||||
/**
|
||||
* Test that condensing API handler is used when provided and valid
|
||||
*/
|
||||
it("should use condensingApiHandler when provided and valid", async () => {
|
||||
await summarizeConversation(
|
||||
sampleMessages,
|
||||
mockMainApiHandler,
|
||||
defaultSystemPrompt,
|
||||
taskId,
|
||||
DEFAULT_PREV_CONTEXT_TOKENS,
|
||||
false,
|
||||
undefined,
|
||||
mockCondensingApiHandler,
|
||||
)
|
||||
|
||||
// Verify the condensing handler was used
|
||||
expect((mockCondensingApiHandler.createMessage as Mock).mock.calls.length).toBe(1)
|
||||
expect((mockMainApiHandler.createMessage as Mock).mock.calls.length).toBe(0)
|
||||
})
|
||||
|
||||
/**
|
||||
* Test fallback to main API handler when condensing handler is not provided
|
||||
*/
|
||||
it("should fall back to mainApiHandler if condensingApiHandler is not provided", async () => {
|
||||
await summarizeConversation(
|
||||
sampleMessages,
|
||||
mockMainApiHandler,
|
||||
defaultSystemPrompt,
|
||||
taskId,
|
||||
DEFAULT_PREV_CONTEXT_TOKENS,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
)
|
||||
|
||||
// Verify the main handler was used
|
||||
expect((mockMainApiHandler.createMessage as Mock).mock.calls.length).toBe(1)
|
||||
})
|
||||
|
||||
/**
|
||||
* Test fallback to main API handler when condensing handler is invalid
|
||||
*/
|
||||
it("should fall back to mainApiHandler if condensingApiHandler is invalid", async () => {
|
||||
// Create an invalid handler (missing createMessage)
|
||||
const invalidHandler = {
|
||||
countTokens: vi.fn(),
|
||||
getModel: vi.fn(),
|
||||
// createMessage is missing
|
||||
} as unknown as ApiHandler
|
||||
|
||||
// Mock console.warn to verify warning message
|
||||
const originalWarn = console.warn
|
||||
const mockWarn = vi.fn()
|
||||
console.warn = mockWarn
|
||||
|
||||
await summarizeConversation(
|
||||
sampleMessages,
|
||||
mockMainApiHandler,
|
||||
defaultSystemPrompt,
|
||||
taskId,
|
||||
DEFAULT_PREV_CONTEXT_TOKENS,
|
||||
false,
|
||||
undefined,
|
||||
invalidHandler,
|
||||
)
|
||||
|
||||
// Verify the main handler was used as fallback
|
||||
expect((mockMainApiHandler.createMessage as Mock).mock.calls.length).toBe(1)
|
||||
|
||||
// Verify warning was logged
|
||||
expect(mockWarn).toHaveBeenCalledWith(
|
||||
expect.stringContaining("Chosen API handler for condensing does not support message creation"),
|
||||
)
|
||||
|
||||
// Restore console.warn
|
||||
console.warn = originalWarn
|
||||
})
|
||||
|
||||
/**
|
||||
* Test that telemetry is called for custom prompt usage
|
||||
*/
|
||||
|
|
@ -1716,38 +1583,13 @@ describe("summarizeConversation with custom settings", () => {
|
|||
taskId,
|
||||
false,
|
||||
true, // usedCustomPrompt
|
||||
false, // usedCustomApiHandler
|
||||
)
|
||||
})
|
||||
|
||||
/**
|
||||
* Test that telemetry is called for custom API handler usage
|
||||
* Test that telemetry is called with isAutomaticTrigger flag
|
||||
*/
|
||||
it("should capture telemetry when using custom API handler", async () => {
|
||||
await summarizeConversation(
|
||||
sampleMessages,
|
||||
mockMainApiHandler,
|
||||
defaultSystemPrompt,
|
||||
taskId,
|
||||
DEFAULT_PREV_CONTEXT_TOKENS,
|
||||
false,
|
||||
undefined,
|
||||
mockCondensingApiHandler,
|
||||
)
|
||||
|
||||
// Verify telemetry was called with custom API handler flag
|
||||
expect(TelemetryService.instance.captureContextCondensed).toHaveBeenCalledWith(
|
||||
taskId,
|
||||
false,
|
||||
false, // usedCustomPrompt
|
||||
true, // usedCustomApiHandler
|
||||
)
|
||||
})
|
||||
|
||||
/**
|
||||
* Test that telemetry is called with both custom prompt and API handler
|
||||
*/
|
||||
it("should capture telemetry when using both custom prompt and API handler", async () => {
|
||||
it("should capture telemetry with isAutomaticTrigger flag", async () => {
|
||||
await summarizeConversation(
|
||||
sampleMessages,
|
||||
mockMainApiHandler,
|
||||
|
|
@ -1756,15 +1598,13 @@ describe("summarizeConversation with custom settings", () => {
|
|||
DEFAULT_PREV_CONTEXT_TOKENS,
|
||||
true, // isAutomaticTrigger
|
||||
"Custom prompt",
|
||||
mockCondensingApiHandler,
|
||||
)
|
||||
|
||||
// Verify telemetry was called with both flags
|
||||
// Verify telemetry was called with isAutomaticTrigger flag
|
||||
expect(TelemetryService.instance.captureContextCondensed).toHaveBeenCalledWith(
|
||||
taskId,
|
||||
true, // isAutomaticTrigger
|
||||
true, // usedCustomPrompt
|
||||
true, // usedCustomApiHandler
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -169,24 +169,12 @@ export type SummarizeResponse = {
|
|||
* Summarizes the conversation messages using an LLM call
|
||||
*
|
||||
* @param {ApiMessage[]} messages - The conversation messages
|
||||
* @param {ApiHandler} apiHandler - The API handler to use for token counting.
|
||||
* @param {string} systemPrompt - The system prompt for API requests, which should be considered in the context token count
|
||||
* @param {string} taskId - The task ID for the conversation, used for telemetry
|
||||
* @param {boolean} isAutomaticTrigger - Whether the summarization is triggered automatically
|
||||
* @returns {SummarizeResponse} - The result of the summarization operation (see above)
|
||||
*/
|
||||
/**
|
||||
* Summarizes the conversation messages using an LLM call
|
||||
*
|
||||
* @param {ApiMessage[]} messages - The conversation messages
|
||||
* @param {ApiHandler} apiHandler - The API handler to use for token counting (fallback if condensingApiHandler not provided)
|
||||
* @param {ApiHandler} apiHandler - The API handler to use for summarization and token counting
|
||||
* @param {string} systemPrompt - The system prompt for API requests (fallback if customCondensingPrompt not provided)
|
||||
* @param {string} taskId - The task ID for the conversation, used for telemetry
|
||||
* @param {number} prevContextTokens - The number of tokens currently in the context, used to ensure we don't grow the context
|
||||
* @param {boolean} isAutomaticTrigger - Whether the summarization is triggered automatically
|
||||
* @param {string} customCondensingPrompt - Optional custom prompt to use for condensing
|
||||
* @param {ApiHandler} condensingApiHandler - Optional specific API handler to use for condensing
|
||||
* @param {boolean} useNativeTools - Whether to preserve tool_use/tool_result pairing in summarization
|
||||
* @returns {SummarizeResponse} - The result of the summarization operation (see above)
|
||||
*/
|
||||
export async function summarizeConversation(
|
||||
|
|
@ -197,14 +185,11 @@ export async function summarizeConversation(
|
|||
prevContextTokens: number,
|
||||
isAutomaticTrigger?: boolean,
|
||||
customCondensingPrompt?: string,
|
||||
condensingApiHandler?: ApiHandler,
|
||||
useNativeTools?: boolean,
|
||||
): Promise<SummarizeResponse> {
|
||||
TelemetryService.instance.captureContextCondensed(
|
||||
taskId,
|
||||
isAutomaticTrigger ?? false,
|
||||
!!customCondensingPrompt?.trim(),
|
||||
!!condensingApiHandler,
|
||||
)
|
||||
|
||||
const response: SummarizeResponse = { messages, cost: 0, summary: "" }
|
||||
|
|
@ -213,13 +198,10 @@ export async function summarizeConversation(
|
|||
const firstMessage = messages[0]
|
||||
|
||||
// Get keepMessages and any tool_use/reasoning blocks that need to be preserved for tool_result pairing.
|
||||
const { keepMessages, toolUseBlocksToPreserve, reasoningBlocksToPreserve } = useNativeTools
|
||||
? getKeepMessagesWithToolBlocks(messages, N_MESSAGES_TO_KEEP)
|
||||
: {
|
||||
keepMessages: messages.slice(-N_MESSAGES_TO_KEEP),
|
||||
toolUseBlocksToPreserve: [],
|
||||
reasoningBlocksToPreserve: [],
|
||||
}
|
||||
const { keepMessages, toolUseBlocksToPreserve, reasoningBlocksToPreserve } = getKeepMessagesWithToolBlocks(
|
||||
messages,
|
||||
N_MESSAGES_TO_KEEP,
|
||||
)
|
||||
|
||||
const keepStartIndex = Math.max(messages.length - N_MESSAGES_TO_KEEP, 0)
|
||||
const includeFirstKeptMessageInSummary = toolUseBlocksToPreserve.length > 0
|
||||
|
|
@ -258,29 +240,14 @@ export async function summarizeConversation(
|
|||
// Use custom prompt if provided and non-empty, otherwise use the default SUMMARY_PROMPT
|
||||
const promptToUse = customCondensingPrompt?.trim() ? customCondensingPrompt.trim() : SUMMARY_PROMPT
|
||||
|
||||
// Use condensing API handler if provided, otherwise use main API handler
|
||||
let handlerToUse = condensingApiHandler || apiHandler
|
||||
|
||||
// Check if the chosen handler supports the required functionality
|
||||
if (!handlerToUse || typeof handlerToUse.createMessage !== "function") {
|
||||
console.warn(
|
||||
"Chosen API handler for condensing does not support message creation or is invalid, falling back to main apiHandler.",
|
||||
)
|
||||
|
||||
handlerToUse = apiHandler // Fallback to the main, presumably valid, apiHandler
|
||||
|
||||
// Ensure the main apiHandler itself is valid before this point or add another check.
|
||||
if (!handlerToUse || typeof handlerToUse.createMessage !== "function") {
|
||||
// This case should ideally not happen if main apiHandler is always valid.
|
||||
// Consider throwing an error or returning a specific error response.
|
||||
console.error("Main API handler is also invalid for condensing. Cannot proceed.")
|
||||
// Return an appropriate error structure for SummarizeResponse
|
||||
const error = t("common:errors.condense_handler_invalid")
|
||||
return { ...response, error }
|
||||
}
|
||||
// Validate that the API handler supports message creation
|
||||
if (!apiHandler || typeof apiHandler.createMessage !== "function") {
|
||||
console.error("API handler is invalid for condensing. Cannot proceed.")
|
||||
const error = t("common:errors.condense_handler_invalid")
|
||||
return { ...response, error }
|
||||
}
|
||||
|
||||
const stream = handlerToUse.createMessage(promptToUse, requestMessages)
|
||||
const stream = apiHandler.createMessage(promptToUse, requestMessages)
|
||||
|
||||
let summary = ""
|
||||
let cost = 0
|
||||
|
|
|
|||
|
|
@ -620,8 +620,6 @@ describe("Context Management", () => {
|
|||
70001,
|
||||
true,
|
||||
undefined, // customCondensingPrompt
|
||||
undefined, // condensingApiHandler
|
||||
undefined, // useNativeTools
|
||||
)
|
||||
|
||||
// Verify the result contains the summary information
|
||||
|
|
@ -796,8 +794,6 @@ describe("Context Management", () => {
|
|||
60000,
|
||||
true,
|
||||
undefined, // customCondensingPrompt
|
||||
undefined, // condensingApiHandler
|
||||
undefined, // useNativeTools
|
||||
)
|
||||
|
||||
// Verify the result contains the summary information
|
||||
|
|
|
|||
|
|
@ -216,10 +216,8 @@ export type ContextManagementOptions = {
|
|||
systemPrompt: string
|
||||
taskId: string
|
||||
customCondensingPrompt?: string
|
||||
condensingApiHandler?: ApiHandler
|
||||
profileThresholds: Record<string, number>
|
||||
currentProfileId: string
|
||||
useNativeTools?: boolean
|
||||
}
|
||||
|
||||
export type ContextManagementResult = SummarizeResponse & {
|
||||
|
|
@ -246,10 +244,8 @@ export async function manageContext({
|
|||
systemPrompt,
|
||||
taskId,
|
||||
customCondensingPrompt,
|
||||
condensingApiHandler,
|
||||
profileThresholds,
|
||||
currentProfileId,
|
||||
useNativeTools,
|
||||
}: ContextManagementOptions): Promise<ContextManagementResult> {
|
||||
let error: string | undefined
|
||||
let cost = 0
|
||||
|
|
@ -302,8 +298,6 @@ export async function manageContext({
|
|||
prevContextTokens,
|
||||
true, // automatic trigger
|
||||
customCondensingPrompt,
|
||||
condensingApiHandler,
|
||||
useNativeTools,
|
||||
)
|
||||
if (result.error) {
|
||||
error = result.error
|
||||
|
|
|
|||
|
|
@ -1572,32 +1572,9 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
|
||||
// Get condensing configuration
|
||||
const state = await this.providerRef.deref()?.getState()
|
||||
// These properties may not exist in the state type yet, but are used for condensing configuration
|
||||
const customCondensingPrompt = state?.customSupportPrompts?.CONDENSE
|
||||
const condensingApiConfigId = state?.condensingApiConfigId
|
||||
const listApiConfigMeta = state?.listApiConfigMeta
|
||||
|
||||
// Determine API handler to use
|
||||
let condensingApiHandler: ApiHandler | undefined
|
||||
if (condensingApiConfigId && listApiConfigMeta && Array.isArray(listApiConfigMeta)) {
|
||||
// Find matching config by ID
|
||||
const matchingConfig = listApiConfigMeta.find((config) => config.id === condensingApiConfigId)
|
||||
if (matchingConfig) {
|
||||
const profile = await this.providerRef.deref()?.providerSettingsManager.getProfile({
|
||||
id: condensingApiConfigId,
|
||||
})
|
||||
// Ensure profile and apiProvider exist before trying to build handler
|
||||
if (profile && profile.apiProvider) {
|
||||
condensingApiHandler = buildApiHandler(profile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const { contextTokens: prevContextTokens } = this.getTokenUsage()
|
||||
|
||||
// Pass through so summarization preserves tool_use/tool_result integrity.
|
||||
const useNativeTools = true
|
||||
|
||||
const {
|
||||
messages,
|
||||
summary,
|
||||
|
|
@ -1613,8 +1590,6 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
prevContextTokens,
|
||||
false, // manual trigger
|
||||
customCondensingPrompt, // User's custom prompt
|
||||
condensingApiHandler, // Specific handler for condensing
|
||||
useNativeTools,
|
||||
)
|
||||
if (error) {
|
||||
this.say(
|
||||
|
|
@ -3706,9 +3681,6 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
`Current tokens: ${contextTokens}, Context window: ${contextWindow}. ` +
|
||||
`Forcing truncation to ${FORCED_CONTEXT_REDUCTION_PERCENT}% of current context.`,
|
||||
)
|
||||
|
||||
const useNativeTools = true
|
||||
|
||||
// Send condenseTaskContextStarted to show in-progress indicator
|
||||
await this.providerRef.deref()?.postMessageToWebview({ type: "condenseTaskContextStarted", text: this.taskId })
|
||||
|
||||
|
|
@ -3725,7 +3697,6 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
taskId: this.taskId,
|
||||
profileThresholds,
|
||||
currentProfileId,
|
||||
useNativeTools,
|
||||
})
|
||||
|
||||
if (truncateResult.messages !== this.apiConversationHistory) {
|
||||
|
|
@ -3822,27 +3793,6 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
|
||||
// Get condensing configuration for automatic triggers.
|
||||
const customCondensingPrompt = state?.customSupportPrompts?.CONDENSE
|
||||
const condensingApiConfigId = state?.condensingApiConfigId
|
||||
const listApiConfigMeta = state?.listApiConfigMeta
|
||||
|
||||
// Determine API handler to use for condensing.
|
||||
let condensingApiHandler: ApiHandler | undefined
|
||||
|
||||
if (condensingApiConfigId && listApiConfigMeta && Array.isArray(listApiConfigMeta)) {
|
||||
// Find matching config by ID
|
||||
const matchingConfig = listApiConfigMeta.find((config) => config.id === condensingApiConfigId)
|
||||
|
||||
if (matchingConfig) {
|
||||
const profile = await this.providerRef.deref()?.providerSettingsManager.getProfile({
|
||||
id: condensingApiConfigId,
|
||||
})
|
||||
|
||||
// Ensure profile and apiProvider exist before trying to build handler.
|
||||
if (profile && profile.apiProvider) {
|
||||
condensingApiHandler = buildApiHandler(profile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!options.skipProviderRateLimit) {
|
||||
await this.maybeWaitForProviderRateLimit(retryAttempt)
|
||||
|
|
@ -3873,9 +3823,6 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
|
||||
// Get the current profile ID using the helper method
|
||||
const currentProfileId = this.getCurrentProfileId(state)
|
||||
|
||||
const useNativeTools = true
|
||||
|
||||
// Check if context management will likely run (threshold check)
|
||||
// This allows us to show an in-progress indicator to the user
|
||||
// We use the centralized willManageContext helper to avoid duplicating threshold logic
|
||||
|
|
@ -3919,10 +3866,8 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
systemPrompt,
|
||||
taskId: this.taskId,
|
||||
customCondensingPrompt,
|
||||
condensingApiHandler,
|
||||
profileThresholds,
|
||||
currentProfileId,
|
||||
useNativeTools,
|
||||
})
|
||||
if (truncateResult.messages !== this.apiConversationHistory) {
|
||||
await this.overwriteApiConversationHistory(truncateResult.messages)
|
||||
|
|
|
|||
|
|
@ -2035,7 +2035,6 @@ export class ClineProvider
|
|||
organizationAllowList,
|
||||
organizationSettingsVersion,
|
||||
maxConcurrentFileReads,
|
||||
condensingApiConfigId,
|
||||
customCondensingPrompt,
|
||||
codebaseIndexConfig,
|
||||
codebaseIndexModels,
|
||||
|
|
@ -2188,7 +2187,6 @@ export class ClineProvider
|
|||
publicSharingEnabled: publicSharingEnabled ?? false,
|
||||
organizationAllowList,
|
||||
organizationSettingsVersion,
|
||||
condensingApiConfigId,
|
||||
customCondensingPrompt,
|
||||
codebaseIndexModels: codebaseIndexModels ?? EMBEDDING_MODEL_PROFILES,
|
||||
codebaseIndexConfig: {
|
||||
|
|
@ -2432,7 +2430,6 @@ export class ClineProvider
|
|||
publicSharingEnabled,
|
||||
organizationAllowList,
|
||||
organizationSettingsVersion,
|
||||
condensingApiConfigId: stateValues.condensingApiConfigId,
|
||||
customCondensingPrompt: stateValues.customCondensingPrompt,
|
||||
codebaseIndexModels: stateValues.codebaseIndexModels ?? EMBEDDING_MODEL_PROFILES,
|
||||
codebaseIndexConfig: {
|
||||
|
|
|
|||
|
|
@ -38,8 +38,6 @@ const PromptsSettings = ({
|
|||
listApiConfigMeta,
|
||||
enhancementApiConfigId,
|
||||
setEnhancementApiConfigId,
|
||||
condensingApiConfigId,
|
||||
setCondensingApiConfigId,
|
||||
includeTaskHistoryInEnhance: contextIncludeTaskHistoryInEnhance,
|
||||
setIncludeTaskHistoryInEnhance: contextSetIncludeTaskHistoryInEnhance,
|
||||
} = useExtensionState()
|
||||
|
|
@ -157,50 +155,30 @@ const PromptsSettings = ({
|
|||
className="w-full"
|
||||
/>
|
||||
|
||||
{(activeSupportOption === "ENHANCE" || activeSupportOption === "CONDENSE") && (
|
||||
{activeSupportOption === "ENHANCE" && (
|
||||
<div className="mt-4 flex flex-col gap-3 pl-3 border-l-2 border-vscode-button-background">
|
||||
<div>
|
||||
<label className="block font-medium mb-1">
|
||||
{activeSupportOption === "ENHANCE"
|
||||
? t("prompts:supportPrompts.enhance.apiConfiguration")
|
||||
: t("prompts:supportPrompts.condense.apiConfiguration")}
|
||||
{t("prompts:supportPrompts.enhance.apiConfiguration")}
|
||||
</label>
|
||||
<Select
|
||||
value={
|
||||
activeSupportOption === "ENHANCE"
|
||||
? enhancementApiConfigId || "-"
|
||||
: condensingApiConfigId || "-"
|
||||
}
|
||||
value={enhancementApiConfigId || "-"}
|
||||
onValueChange={(value) => {
|
||||
const newConfigId = value === "-" ? "" : value
|
||||
if (activeSupportOption === "ENHANCE") {
|
||||
setEnhancementApiConfigId(newConfigId)
|
||||
vscode.postMessage({
|
||||
type: "enhancementApiConfigId",
|
||||
text: value,
|
||||
})
|
||||
} else {
|
||||
setCondensingApiConfigId(newConfigId)
|
||||
vscode.postMessage({
|
||||
type: "updateSettings",
|
||||
updatedSettings: { condensingApiConfigId: newConfigId },
|
||||
})
|
||||
}
|
||||
setEnhancementApiConfigId(newConfigId)
|
||||
vscode.postMessage({
|
||||
type: "enhancementApiConfigId",
|
||||
text: value,
|
||||
})
|
||||
}}>
|
||||
<SelectTrigger data-testid="api-config-select" className="w-full">
|
||||
<SelectValue
|
||||
placeholder={
|
||||
activeSupportOption === "ENHANCE"
|
||||
? t("prompts:supportPrompts.enhance.useCurrentConfig")
|
||||
: t("prompts:supportPrompts.condense.useCurrentConfig")
|
||||
}
|
||||
placeholder={t("prompts:supportPrompts.enhance.useCurrentConfig")}
|
||||
/>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="-">
|
||||
{activeSupportOption === "ENHANCE"
|
||||
? t("prompts:supportPrompts.enhance.useCurrentConfig")
|
||||
: t("prompts:supportPrompts.condense.useCurrentConfig")}
|
||||
{t("prompts:supportPrompts.enhance.useCurrentConfig")}
|
||||
</SelectItem>
|
||||
{(listApiConfigMeta || []).map((config) => (
|
||||
<SelectItem
|
||||
|
|
@ -213,66 +191,55 @@ const PromptsSettings = ({
|
|||
</SelectContent>
|
||||
</Select>
|
||||
<div className="text-sm text-vscode-descriptionForeground mt-1">
|
||||
{activeSupportOption === "ENHANCE"
|
||||
? t("prompts:supportPrompts.enhance.apiConfigDescription")
|
||||
: t("prompts:supportPrompts.condense.apiConfigDescription")}
|
||||
{t("prompts:supportPrompts.enhance.apiConfigDescription")}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{activeSupportOption === "ENHANCE" && (
|
||||
<>
|
||||
<div>
|
||||
<VSCodeCheckbox
|
||||
checked={includeTaskHistoryInEnhance}
|
||||
onChange={(e: Event | FormEvent<HTMLElement>) => {
|
||||
const target = (
|
||||
"target" in e ? e.target : null
|
||||
) as HTMLInputElement | null
|
||||
<div>
|
||||
<VSCodeCheckbox
|
||||
checked={includeTaskHistoryInEnhance}
|
||||
onChange={(e: Event | FormEvent<HTMLElement>) => {
|
||||
const target = ("target" in e ? e.target : null) as HTMLInputElement | null
|
||||
|
||||
if (!target) {
|
||||
return
|
||||
}
|
||||
if (!target) {
|
||||
return
|
||||
}
|
||||
|
||||
setIncludeTaskHistoryInEnhance(target.checked)
|
||||
setIncludeTaskHistoryInEnhance(target.checked)
|
||||
|
||||
vscode.postMessage({
|
||||
type: "updateSettings",
|
||||
updatedSettings: { includeTaskHistoryInEnhance: target.checked },
|
||||
})
|
||||
}}>
|
||||
<span className="font-medium">
|
||||
{t("prompts:supportPrompts.enhance.includeTaskHistory")}
|
||||
</span>
|
||||
</VSCodeCheckbox>
|
||||
<div className="text-vscode-descriptionForeground text-sm mt-1 mb-3">
|
||||
{t("prompts:supportPrompts.enhance.includeTaskHistoryDescription")}
|
||||
</div>
|
||||
</div>
|
||||
vscode.postMessage({
|
||||
type: "updateSettings",
|
||||
updatedSettings: { includeTaskHistoryInEnhance: target.checked },
|
||||
})
|
||||
}}>
|
||||
<span className="font-medium">
|
||||
{t("prompts:supportPrompts.enhance.includeTaskHistory")}
|
||||
</span>
|
||||
</VSCodeCheckbox>
|
||||
<div className="text-vscode-descriptionForeground text-sm mt-1 mb-3">
|
||||
{t("prompts:supportPrompts.enhance.includeTaskHistoryDescription")}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block font-medium mb-1">
|
||||
{t("prompts:supportPrompts.enhance.testEnhancement")}
|
||||
</label>
|
||||
<VSCodeTextArea
|
||||
resize="vertical"
|
||||
value={testPrompt}
|
||||
onChange={(e) => setTestPrompt((e.target as HTMLTextAreaElement).value)}
|
||||
placeholder={t("prompts:supportPrompts.enhance.testPromptPlaceholder")}
|
||||
rows={3}
|
||||
className="w-full"
|
||||
data-testid="test-prompt-textarea"
|
||||
/>
|
||||
<div className="mt-2 flex justify-start items-center gap-2">
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={handleTestEnhancement}
|
||||
disabled={isEnhancing}>
|
||||
{t("prompts:supportPrompts.enhance.previewButton")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div>
|
||||
<label className="block font-medium mb-1">
|
||||
{t("prompts:supportPrompts.enhance.testEnhancement")}
|
||||
</label>
|
||||
<VSCodeTextArea
|
||||
resize="vertical"
|
||||
value={testPrompt}
|
||||
onChange={(e) => setTestPrompt((e.target as HTMLTextAreaElement).value)}
|
||||
placeholder={t("prompts:supportPrompts.enhance.testPromptPlaceholder")}
|
||||
rows={3}
|
||||
className="w-full"
|
||||
data-testid="test-prompt-textarea"
|
||||
/>
|
||||
<div className="mt-2 flex justify-start items-center gap-2">
|
||||
<Button variant="primary" onClick={handleTestEnhancement} disabled={isEnhancing}>
|
||||
{t("prompts:supportPrompts.enhance.previewButton")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -197,7 +197,6 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
|
|||
maxTotalImageSize,
|
||||
terminalCompressProgressBar,
|
||||
maxConcurrentFileReads,
|
||||
condensingApiConfigId,
|
||||
customSupportPrompts,
|
||||
profileThresholds,
|
||||
alwaysAllowFollowupQuestions,
|
||||
|
|
@ -419,7 +418,6 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
|
|||
alwaysAllowSubtasks,
|
||||
alwaysAllowFollowupQuestions: alwaysAllowFollowupQuestions ?? false,
|
||||
followupAutoApproveTimeoutMs,
|
||||
condensingApiConfigId: condensingApiConfigId || "",
|
||||
includeTaskHistoryInEnhance: includeTaskHistoryInEnhance ?? true,
|
||||
reasoningBlockCollapsed: reasoningBlockCollapsed ?? true,
|
||||
enterBehavior: enterBehavior ?? "send",
|
||||
|
|
|
|||
|
|
@ -87,7 +87,6 @@ describe("ContextManagementSettings", () => {
|
|||
const defaultProps = {
|
||||
autoCondenseContext: false,
|
||||
autoCondenseContextPercent: 80,
|
||||
condensingApiConfigId: undefined,
|
||||
customCondensingPrompt: undefined,
|
||||
listApiConfigMeta: [],
|
||||
maxOpenTabsContext: 20,
|
||||
|
|
|
|||
|
|
@ -192,7 +192,6 @@ describe("SettingsView - Change Detection Fix", () => {
|
|||
maxTotalImageSize: 20,
|
||||
terminalCompressProgressBar: false,
|
||||
maxConcurrentFileReads: 5,
|
||||
condensingApiConfigId: "",
|
||||
customCondensingPrompt: "",
|
||||
customSupportPrompts: {},
|
||||
profileThresholds: {},
|
||||
|
|
|
|||
|
|
@ -197,7 +197,6 @@ describe("SettingsView - Unsaved Changes Detection", () => {
|
|||
maxTotalImageSize: 20,
|
||||
terminalCompressProgressBar: false,
|
||||
maxConcurrentFileReads: 5,
|
||||
condensingApiConfigId: "",
|
||||
customCondensingPrompt: "",
|
||||
customSupportPrompts: {},
|
||||
profileThresholds: {},
|
||||
|
|
|
|||
|
|
@ -56,8 +56,6 @@ export interface ExtensionStateContextType extends ExtensionState {
|
|||
setAlwaysAllowFollowupQuestions: (value: boolean) => void // Setter for the new property
|
||||
followupAutoApproveTimeoutMs: number | undefined // Timeout in ms for auto-approving follow-up questions
|
||||
setFollowupAutoApproveTimeoutMs: (value: number) => void // Setter for the timeout
|
||||
condensingApiConfigId?: string
|
||||
setCondensingApiConfigId: (value: string) => void
|
||||
marketplaceItems?: any[]
|
||||
marketplaceInstalledMetadata?: MarketplaceInstalledMetadata
|
||||
profileThresholds: Record<string, number>
|
||||
|
|
@ -232,7 +230,6 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
customSupportPrompts: {},
|
||||
experiments: experimentDefault,
|
||||
enhancementApiConfigId: "",
|
||||
condensingApiConfigId: "", // Default empty string for condensing API config ID
|
||||
hasOpenedModeSelector: false, // Default to false (not opened yet)
|
||||
autoApprovalEnabled: false,
|
||||
customModes: [],
|
||||
|
|
@ -616,7 +613,6 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
setAutoCondenseContext: (value) => setState((prevState) => ({ ...prevState, autoCondenseContext: value })),
|
||||
setAutoCondenseContextPercent: (value) =>
|
||||
setState((prevState) => ({ ...prevState, autoCondenseContextPercent: value })),
|
||||
setCondensingApiConfigId: (value) => setState((prevState) => ({ ...prevState, condensingApiConfigId: value })),
|
||||
setProfileThresholds: (value) => setState((prevState) => ({ ...prevState, profileThresholds: value })),
|
||||
includeDiagnosticMessages: state.includeDiagnosticMessages,
|
||||
setIncludeDiagnosticMessages: (value) => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue