diff --git a/packages/types/src/global-settings.ts b/packages/types/src/global-settings.ts index dc5a9e6744..00a052c673 100644 --- a/packages/types/src/global-settings.ts +++ b/packages/types/src/global-settings.ts @@ -139,6 +139,7 @@ export const globalSettingsSchema = z.object({ customModePrompts: customModePromptsSchema.optional(), customSupportPrompts: customSupportPromptsSchema.optional(), enhancementApiConfigId: z.string().optional(), + includeTaskHistoryInEnhance: z.boolean().optional(), historyPreviewCollapsed: z.boolean().optional(), profileThresholds: z.record(z.string(), z.number()).optional(), hasOpenedModeSelector: z.boolean().optional(), diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 1218999a9a..d23e5a0823 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -1511,6 +1511,7 @@ export class ClineProvider followupAutoApproveTimeoutMs, includeDiagnosticMessages, maxDiagnosticMessages, + includeTaskHistoryInEnhance, } = await this.getState() const telemetryKey = process.env.POSTHOG_API_KEY @@ -1635,6 +1636,7 @@ export class ClineProvider followupAutoApproveTimeoutMs: followupAutoApproveTimeoutMs ?? 60000, includeDiagnosticMessages: includeDiagnosticMessages ?? true, maxDiagnosticMessages: maxDiagnosticMessages ?? 50, + includeTaskHistoryInEnhance: includeTaskHistoryInEnhance ?? false, } } @@ -1805,6 +1807,8 @@ export class ClineProvider // Add diagnostic message settings includeDiagnosticMessages: stateValues.includeDiagnosticMessages ?? true, maxDiagnosticMessages: stateValues.maxDiagnosticMessages ?? 50, + // Add includeTaskHistoryInEnhance setting + includeTaskHistoryInEnhance: stateValues.includeTaskHistoryInEnhance ?? false, } } diff --git a/src/core/webview/__tests__/messageEnhancer.test.ts b/src/core/webview/__tests__/messageEnhancer.test.ts new file mode 100644 index 0000000000..f6f6b44e1d --- /dev/null +++ b/src/core/webview/__tests__/messageEnhancer.test.ts @@ -0,0 +1,365 @@ +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest" +import { MessageEnhancer } from "../messageEnhancer" +import { ProviderSettings, ClineMessage } from "@roo-code/types" +import { TelemetryService } from "@roo-code/telemetry" +import * as singleCompletionHandlerModule from "../../../utils/single-completion-handler" +import { ProviderSettingsManager } from "../../config/ProviderSettingsManager" + +// Mock dependencies +vi.mock("../../../utils/single-completion-handler") +vi.mock("@roo-code/telemetry") + +describe("MessageEnhancer", () => { + let mockProviderSettingsManager: ProviderSettingsManager + let mockSingleCompletionHandler: ReturnType + + const mockApiConfiguration: ProviderSettings = { + apiProvider: "openai", + apiKey: "test-key", + apiModelId: "gpt-4", + } + + const mockListApiConfigMeta = [ + { id: "config1", name: "Config 1" }, + { id: "config2", name: "Config 2" }, + ] + + beforeEach(() => { + // Reset all mocks + vi.clearAllMocks() + + // Mock provider settings manager + mockProviderSettingsManager = { + getProfile: vi.fn().mockResolvedValue({ + name: "Enhancement Config", + apiProvider: "anthropic", + apiKey: "enhancement-key", + apiModelId: "claude-3", + }), + } as any + + // Mock single completion handler + mockSingleCompletionHandler = vi.fn().mockResolvedValue("Enhanced prompt text") + vi.mocked(singleCompletionHandlerModule).singleCompletionHandler = mockSingleCompletionHandler + + // Mock TelemetryService + vi.mocked(TelemetryService).hasInstance = vi.fn().mockReturnValue(true) + // Mock the instance getter + Object.defineProperty(TelemetryService, "instance", { + get: vi.fn().mockReturnValue({ + capturePromptEnhanced: vi.fn(), + }), + configurable: true, + }) + }) + + afterEach(() => { + vi.restoreAllMocks() + }) + + describe("enhanceMessage", () => { + it("should enhance a simple message successfully", async () => { + const result = await MessageEnhancer.enhanceMessage({ + text: "Write a function to calculate fibonacci", + apiConfiguration: mockApiConfiguration, + listApiConfigMeta: mockListApiConfigMeta, + providerSettingsManager: mockProviderSettingsManager, + }) + + expect(result.success).toBe(true) + expect(result.enhancedText).toBe("Enhanced prompt text") + expect(result.error).toBeUndefined() + + // Verify single completion handler was called with correct prompt + expect(mockSingleCompletionHandler).toHaveBeenCalledWith( + mockApiConfiguration, + expect.stringContaining("Write a function to calculate fibonacci"), + ) + }) + + it("should use enhancement API config when provided", async () => { + const result = await MessageEnhancer.enhanceMessage({ + text: "Test prompt", + apiConfiguration: mockApiConfiguration, + customSupportPrompts: {}, + listApiConfigMeta: mockListApiConfigMeta, + enhancementApiConfigId: "config2", + providerSettingsManager: mockProviderSettingsManager, + }) + + expect(result.success).toBe(true) + expect(mockProviderSettingsManager.getProfile).toHaveBeenCalledWith({ id: "config2" }) + + // Verify the enhancement config was used instead of default + const expectedConfig = { + apiProvider: "anthropic", + apiKey: "enhancement-key", + apiModelId: "claude-3", + } + expect(mockSingleCompletionHandler).toHaveBeenCalledWith(expectedConfig, expect.any(String)) + }) + + it("should include task history when enabled", async () => { + const mockClineMessages: ClineMessage[] = [ + { type: "ask", text: "Create a React component", ts: 1000 }, + { type: "say", say: "text", text: "I'll create a React component for you", ts: 2000 }, + { type: "ask", text: "Add props to the component", ts: 3000 }, + { type: "say", say: "reasoning", text: "Using tool", ts: 4000 }, // Should be filtered out + ] + + const result = await MessageEnhancer.enhanceMessage({ + text: "Improve the component", + apiConfiguration: mockApiConfiguration, + listApiConfigMeta: mockListApiConfigMeta, + includeTaskHistoryInEnhance: true, + currentClineMessages: mockClineMessages, + providerSettingsManager: mockProviderSettingsManager, + }) + + expect(result.success).toBe(true) + + // Verify the prompt includes task history + const calledPrompt = mockSingleCompletionHandler.mock.calls[0][1] + expect(calledPrompt).toContain("Improve the component") + expect(calledPrompt).toContain("previous conversation context") + expect(calledPrompt).toContain("User: Create a React component") + expect(calledPrompt).toContain("Assistant: I'll create a React component for you") + expect(calledPrompt).toContain("User: Add props to the component") + expect(calledPrompt).not.toContain("Using tool") // reasoning messages should be filtered + }) + + it("should limit task history to last 10 messages", async () => { + // Create 15 messages + const mockClineMessages: ClineMessage[] = Array.from({ length: 15 }, (_, i) => ({ + type: i % 2 === 0 ? "ask" : "say", + say: i % 2 === 1 ? "text" : undefined, + text: `Message ${i + 1}`, + ts: i * 1000, + })) as ClineMessage[] + + await MessageEnhancer.enhanceMessage({ + text: "Test", + apiConfiguration: mockApiConfiguration, + listApiConfigMeta: mockListApiConfigMeta, + includeTaskHistoryInEnhance: true, + currentClineMessages: mockClineMessages, + providerSettingsManager: mockProviderSettingsManager, + }) + + const calledPrompt = mockSingleCompletionHandler.mock.calls[0][1] + + // Should include messages 6-15 (last 10) + expect(calledPrompt).toContain("Message 6") + expect(calledPrompt).toContain("Message 15") + expect(calledPrompt).not.toContain("Message 5") + }) + + it("should truncate long messages in task history", async () => { + const longText = "A".repeat(600) // 600 characters + const mockClineMessages: ClineMessage[] = [{ type: "ask", text: longText, ts: 1000 }] + + await MessageEnhancer.enhanceMessage({ + text: "Test", + apiConfiguration: mockApiConfiguration, + listApiConfigMeta: mockListApiConfigMeta, + includeTaskHistoryInEnhance: true, + currentClineMessages: mockClineMessages, + providerSettingsManager: mockProviderSettingsManager, + }) + + const calledPrompt = mockSingleCompletionHandler.mock.calls[0][1] + + // Should truncate to 500 chars + "..." + expect(calledPrompt).toContain("A".repeat(500) + "...") + expect(calledPrompt).not.toContain("A".repeat(501)) + }) + + it("should use custom support prompts when provided", async () => { + const customSupportPrompts = { + ENHANCE: "Custom enhancement template: ${userInput}", + } + + await MessageEnhancer.enhanceMessage({ + text: "Test prompt", + apiConfiguration: mockApiConfiguration, + customSupportPrompts, + listApiConfigMeta: mockListApiConfigMeta, + providerSettingsManager: mockProviderSettingsManager, + }) + + const calledPrompt = mockSingleCompletionHandler.mock.calls[0][1] + expect(calledPrompt).toBe("Custom enhancement template: Test prompt") + }) + + it("should handle errors gracefully", async () => { + mockSingleCompletionHandler.mockRejectedValue(new Error("API error")) + + const result = await MessageEnhancer.enhanceMessage({ + text: "Test", + apiConfiguration: mockApiConfiguration, + listApiConfigMeta: mockListApiConfigMeta, + providerSettingsManager: mockProviderSettingsManager, + }) + + expect(result.success).toBe(false) + expect(result.error).toBe("API error") + expect(result.enhancedText).toBeUndefined() + }) + + it("should handle non-Error exceptions", async () => { + mockSingleCompletionHandler.mockRejectedValue("String error") + + const result = await MessageEnhancer.enhanceMessage({ + text: "Test", + apiConfiguration: mockApiConfiguration, + listApiConfigMeta: mockListApiConfigMeta, + providerSettingsManager: mockProviderSettingsManager, + }) + + expect(result.success).toBe(false) + expect(result.error).toBe("String error") + }) + + it("should fall back to default config if enhancement config is invalid", async () => { + mockProviderSettingsManager.getProfile = vi.fn().mockResolvedValue({ + name: "Invalid Config", + // Missing apiProvider + }) + + await MessageEnhancer.enhanceMessage({ + text: "Test", + apiConfiguration: mockApiConfiguration, + listApiConfigMeta: mockListApiConfigMeta, + enhancementApiConfigId: "config2", + providerSettingsManager: mockProviderSettingsManager, + }) + + // Should use the default config + expect(mockSingleCompletionHandler).toHaveBeenCalledWith(mockApiConfiguration, expect.any(String)) + }) + + it("should handle empty task history gracefully", async () => { + const result = await MessageEnhancer.enhanceMessage({ + text: "Test", + apiConfiguration: mockApiConfiguration, + listApiConfigMeta: mockListApiConfigMeta, + includeTaskHistoryInEnhance: true, + currentClineMessages: [], + providerSettingsManager: mockProviderSettingsManager, + }) + + expect(result.success).toBe(true) + + const calledPrompt = mockSingleCompletionHandler.mock.calls[0][1] + // Should not include task history section + expect(calledPrompt).not.toContain("previous conversation context") + }) + }) + + describe("captureTelemetry", () => { + it("should capture telemetry when TelemetryService is available", () => { + const mockTaskId = "task-123" + const mockCaptureEvent = vi.fn() + vi.mocked(TelemetryService.instance).captureEvent = mockCaptureEvent + + MessageEnhancer.captureTelemetry(mockTaskId, true) + + expect(TelemetryService.hasInstance).toHaveBeenCalled() + expect(mockCaptureEvent).toHaveBeenCalledWith(expect.any(String), { + taskId: mockTaskId, + includeTaskHistory: true, + }) + }) + + it("should handle missing TelemetryService gracefully", () => { + vi.mocked(TelemetryService).hasInstance = vi.fn().mockReturnValue(false) + + // Should not throw + expect(() => MessageEnhancer.captureTelemetry("task-123", true)).not.toThrow() + }) + + it("should work without task ID", () => { + const mockCaptureEvent = vi.fn() + vi.mocked(TelemetryService.instance).captureEvent = mockCaptureEvent + + MessageEnhancer.captureTelemetry(undefined, false) + + expect(mockCaptureEvent).toHaveBeenCalledWith(expect.any(String), { + includeTaskHistory: false, + }) + }) + + it("should default includeTaskHistory to false when not provided", () => { + const mockCaptureEvent = vi.fn() + vi.mocked(TelemetryService.instance).captureEvent = mockCaptureEvent + + MessageEnhancer.captureTelemetry("task-123") + + expect(mockCaptureEvent).toHaveBeenCalledWith(expect.any(String), { + taskId: "task-123", + includeTaskHistory: false, + }) + }) + }) + + describe("extractTaskHistory", () => { + it("should filter and format messages correctly", () => { + const messages: ClineMessage[] = [ + { type: "ask", text: "User message 1", ts: 1000 }, + { type: "say", say: "text", text: "Assistant message 1", ts: 2000 }, + { type: "say", say: "reasoning", text: "Tool use", ts: 3000 }, + { type: "ask", text: "", ts: 4000 }, // Empty text + { type: "say", say: "text", text: undefined, ts: 5000 }, // No text + { type: "ask", text: "User message 2", ts: 6000 }, + ] + + // Access private method through any type assertion for testing + const history = (MessageEnhancer as any).extractTaskHistory(messages) + + expect(history).toContain("User: User message 1") + expect(history).toContain("Assistant: Assistant message 1") + expect(history).toContain("User: User message 2") + expect(history).not.toContain("Tool use") + expect(history.split("\n").length).toBe(3) // Only 3 valid messages + }) + + it("should handle malformed messages gracefully", () => { + const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {}) + + // Create messages that will cause errors when accessed + const malformedMessages = [ + null, + undefined, + { type: "ask" }, // Missing required properties + "not an object", + ] as any + + // Access private method through any type assertion for testing + const history = (MessageEnhancer as any).extractTaskHistory(malformedMessages) + + // Should return empty string and log error + expect(history).toBe("") + expect(consoleSpy).toHaveBeenCalledWith("Failed to extract task history:", expect.any(Error)) + + consoleSpy.mockRestore() + }) + + it("should handle messages with circular references", () => { + const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {}) + + // Create a message with circular reference + const circularMessage: any = { type: "ask", text: "Test" } + circularMessage.self = circularMessage + + const messages = [circularMessage] as ClineMessage[] + + // Access private method through any type assertion for testing + const history = (MessageEnhancer as any).extractTaskHistory(messages) + + // Should handle gracefully + expect(history).toBe("User: Test") + + consoleSpy.mockRestore() + }) + }) +}) diff --git a/src/core/webview/messageEnhancer.ts b/src/core/webview/messageEnhancer.ts new file mode 100644 index 0000000000..89df7b5b59 --- /dev/null +++ b/src/core/webview/messageEnhancer.ts @@ -0,0 +1,143 @@ +import { ProviderSettings, ClineMessage, GlobalState, TelemetryEventName } from "@roo-code/types" +import { TelemetryService } from "@roo-code/telemetry" +import { supportPrompt } from "../../shared/support-prompt" +import { singleCompletionHandler } from "../../utils/single-completion-handler" +import { ProviderSettingsManager } from "../config/ProviderSettingsManager" +import { ClineProvider } from "./ClineProvider" + +export interface MessageEnhancerOptions { + text: string + apiConfiguration: ProviderSettings + customSupportPrompts?: Record + listApiConfigMeta: Array<{ id: string; name?: string }> + enhancementApiConfigId?: string + includeTaskHistoryInEnhance?: boolean + currentClineMessages?: ClineMessage[] + providerSettingsManager: ProviderSettingsManager +} + +export interface MessageEnhancerResult { + success: boolean + enhancedText?: string + error?: string +} + +/** + * Enhances a message prompt using AI, optionally including task history for context + */ +export class MessageEnhancer { + /** + * Enhances a message prompt using the configured AI provider + * @param options Configuration options for message enhancement + * @returns Enhanced message result with success status + */ + static async enhanceMessage(options: MessageEnhancerOptions): Promise { + try { + const { + text, + apiConfiguration, + customSupportPrompts, + listApiConfigMeta, + enhancementApiConfigId, + includeTaskHistoryInEnhance, + currentClineMessages, + providerSettingsManager, + } = options + + // Determine which API configuration to use + let configToUse: ProviderSettings = apiConfiguration + + // Try to get enhancement config first, fall back to current config + if (enhancementApiConfigId && listApiConfigMeta.find(({ id }) => id === enhancementApiConfigId)) { + const { name: _, ...providerSettings } = await providerSettingsManager.getProfile({ + id: enhancementApiConfigId, + }) + + if (providerSettings.apiProvider) { + configToUse = providerSettings + } + } + + // Prepare the prompt to enhance + let promptToEnhance = text + + // Include task history if enabled and available + if (includeTaskHistoryInEnhance && currentClineMessages && currentClineMessages.length > 0) { + const taskHistory = this.extractTaskHistory(currentClineMessages) + if (taskHistory) { + promptToEnhance = `${text}\n\nUse the following previous conversation context as needed:\n${taskHistory}` + } + } + + // Create the enhancement prompt using the support prompt system + const enhancementPrompt = supportPrompt.create( + "ENHANCE", + { userInput: promptToEnhance }, + customSupportPrompts, + ) + + // Call the single completion handler to get the enhanced prompt + const enhancedText = await singleCompletionHandler(configToUse, enhancementPrompt) + + return { + success: true, + enhancedText, + } + } catch (error) { + return { + success: false, + error: error instanceof Error ? error.message : String(error), + } + } + } + + /** + * Extracts relevant task history from Cline messages for context + * @param messages Array of Cline messages + * @returns Formatted task history string + */ + private static extractTaskHistory(messages: ClineMessage[]): string { + try { + const relevantMessages = messages + .filter((msg) => { + // Include user messages (type: "ask" with text) and assistant messages (type: "say" with say: "text") + if (msg.type === "ask" && msg.text) { + return true + } + if (msg.type === "say" && msg.say === "text" && msg.text) { + return true + } + return false + }) + .slice(-10) // Limit to last 10 messages to avoid context explosion + + return relevantMessages + .map((msg) => { + const role = msg.type === "ask" ? "User" : "Assistant" + const content = msg.text || "" + // Truncate long messages + return `${role}: ${content.slice(0, 500)}${content.length > 500 ? "..." : ""}` + }) + .join("\n") + } catch (error) { + // Log error but don't fail the enhancement + console.error("Failed to extract task history:", error) + return "" + } + } + + /** + * Captures telemetry for prompt enhancement + * @param taskId Optional task ID for telemetry tracking + * @param includeTaskHistory Whether task history was included in the enhancement + */ + static captureTelemetry(taskId?: string, includeTaskHistory?: boolean): void { + if (TelemetryService.hasInstance()) { + // Use captureEvent directly to include the includeTaskHistory property + TelemetryService.instance.captureEvent(TelemetryEventName.PROMPT_ENHANCED, { + ...(taskId && { taskId }), + includeTaskHistory: includeTaskHistory ?? false, + }) + } + } +} diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index 763e118125..b1b62229c9 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -22,6 +22,7 @@ import { changeLanguage, t } from "../../i18n" import { Package } from "../../shared/package" import { RouterName, toRouterName, ModelRecord } from "../../shared/api" import { supportPrompt } from "../../shared/support-prompt" +import { MessageEnhancer } from "./messageEnhancer" import { checkoutDiffPayloadSchema, checkoutRestorePayloadSchema, WebviewMessage } from "../../shared/WebviewMessage" import { checkExistKey } from "../../shared/checkExistApiConfig" @@ -35,7 +36,6 @@ import { discoverChromeHostUrl, tryChromeHostUrl } from "../../services/browser/ import { searchWorkspaceFiles } from "../../services/search/file-search" import { fileExistsAtPath } from "../../utils/fs" import { playTts, setTtsEnabled, setTtsSpeed, stopTts } from "../../utils/tts" -import { singleCompletionHandler } from "../../utils/single-completion-handler" import { searchCommits } from "../../utils/git" import { exportSettings, importSettingsWithFeedback } from "../config/importExport" import { getOpenAiModels } from "../../api/providers/openai" @@ -1311,6 +1311,10 @@ export const webviewMessageHandler = async ( await updateGlobalState("enhancementApiConfigId", message.text) await provider.postStateToWebview() break + case "includeTaskHistoryInEnhance": + await updateGlobalState("includeTaskHistoryInEnhance", message.bool ?? false) + await provider.postStateToWebview() + break case "condensingApiConfigId": await updateGlobalState("condensingApiConfigId", message.text) await provider.postStateToWebview() @@ -1335,32 +1339,34 @@ export const webviewMessageHandler = async ( case "enhancePrompt": if (message.text) { try { - const { apiConfiguration, customSupportPrompts, listApiConfigMeta, enhancementApiConfigId } = - await provider.getState() + const state = await provider.getState() + const { + apiConfiguration, + customSupportPrompts, + listApiConfigMeta, + enhancementApiConfigId, + includeTaskHistoryInEnhance, + } = state - // Try to get enhancement config first, fall back to current config. - let configToUse: ProviderSettings = apiConfiguration - - if (enhancementApiConfigId && !!listApiConfigMeta.find(({ id }) => id === enhancementApiConfigId)) { - const { name: _, ...providerSettings } = await provider.providerSettingsManager.getProfile({ - id: enhancementApiConfigId, - }) - - if (providerSettings.apiProvider) { - configToUse = providerSettings - } - } - - const enhancedPrompt = await singleCompletionHandler( - configToUse, - supportPrompt.create("ENHANCE", { userInput: message.text }, customSupportPrompts), - ) - - // Capture telemetry for prompt enhancement. const currentCline = provider.getCurrentCline() - TelemetryService.instance.capturePromptEnhanced(currentCline?.taskId) + const result = await MessageEnhancer.enhanceMessage({ + text: message.text, + apiConfiguration, + customSupportPrompts, + listApiConfigMeta, + enhancementApiConfigId, + includeTaskHistoryInEnhance, + currentClineMessages: currentCline?.clineMessages, + providerSettingsManager: provider.providerSettingsManager, + }) - await provider.postMessageToWebview({ type: "enhancedPrompt", text: enhancedPrompt }) + if (result.success && result.enhancedText) { + // Capture telemetry for prompt enhancement + MessageEnhancer.captureTelemetry(currentCline?.taskId, includeTaskHistoryInEnhance) + await provider.postMessageToWebview({ type: "enhancedPrompt", text: result.enhancedText }) + } else { + throw new Error(result.error || "Unknown error") + } } catch (error) { provider.log( `Error enhancing prompt: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`, diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index a91d1af7ba..0b0cc06880 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -140,6 +140,7 @@ export interface WebviewMessage { | "copySystemPrompt" | "systemPrompt" | "enhancementApiConfigId" + | "includeTaskHistoryInEnhance" | "updateExperimental" | "autoApprovalEnabled" | "updateCustomMode" diff --git a/webview-ui/src/components/settings/PromptsSettings.tsx b/webview-ui/src/components/settings/PromptsSettings.tsx index a71132d62b..ee112b54dd 100644 --- a/webview-ui/src/components/settings/PromptsSettings.tsx +++ b/webview-ui/src/components/settings/PromptsSettings.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from "react" -import { VSCodeTextArea } from "@vscode/webview-ui-toolkit/react" +import { VSCodeTextArea, VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react" import { supportPrompt, SupportPromptType } from "@roo/support-prompt" @@ -22,9 +22,16 @@ import { MessageSquare } from "lucide-react" interface PromptsSettingsProps { customSupportPrompts: Record setCustomSupportPrompts: (prompts: Record) => void + includeTaskHistoryInEnhance?: boolean + setIncludeTaskHistoryInEnhance?: (value: boolean) => void } -const PromptsSettings = ({ customSupportPrompts, setCustomSupportPrompts }: PromptsSettingsProps) => { +const PromptsSettings = ({ + customSupportPrompts, + setCustomSupportPrompts, + includeTaskHistoryInEnhance: propsIncludeTaskHistoryInEnhance, + setIncludeTaskHistoryInEnhance: propsSetIncludeTaskHistoryInEnhance, +}: PromptsSettingsProps) => { const { t } = useAppTranslation() const { listApiConfigMeta, @@ -34,8 +41,14 @@ const PromptsSettings = ({ customSupportPrompts, setCustomSupportPrompts }: Prom setCondensingApiConfigId, customCondensingPrompt, setCustomCondensingPrompt, + includeTaskHistoryInEnhance: contextIncludeTaskHistoryInEnhance, + setIncludeTaskHistoryInEnhance: contextSetIncludeTaskHistoryInEnhance, } = useExtensionState() + // Use props if provided, otherwise fall back to context + const includeTaskHistoryInEnhance = propsIncludeTaskHistoryInEnhance ?? contextIncludeTaskHistoryInEnhance + const setIncludeTaskHistoryInEnhance = propsSetIncludeTaskHistoryInEnhance ?? contextSetIncludeTaskHistoryInEnhance + const [testPrompt, setTestPrompt] = useState("") const [isEnhancing, setIsEnhancing] = useState(false) const [activeSupportOption, setActiveSupportOption] = useState("ENHANCE") @@ -219,28 +232,50 @@ const PromptsSettings = ({ customSupportPrompts, setCustomSupportPrompts }: Prom {activeSupportOption === "ENHANCE" && ( -
- - setTestPrompt((e.target as HTMLTextAreaElement).value)} - placeholder={t("prompts:supportPrompts.enhance.testPromptPlaceholder")} - rows={3} - className="w-full" - data-testid="test-prompt-textarea" - /> -
- + <> +
+ { + const value = e.target.checked + setIncludeTaskHistoryInEnhance(value) + vscode.postMessage({ + type: "includeTaskHistoryInEnhance", + bool: value, + }) + }}> + + {t("prompts:supportPrompts.enhance.includeTaskHistory")} + + +
+ {t("prompts:supportPrompts.enhance.includeTaskHistoryDescription")} +
-
+ +
+ + setTestPrompt((e.target as HTMLTextAreaElement).value)} + placeholder={t("prompts:supportPrompts.enhance.testPromptPlaceholder")} + rows={3} + className="w-full" + data-testid="test-prompt-textarea" + /> +
+ +
+
+ )}
)} diff --git a/webview-ui/src/components/settings/SettingsView.tsx b/webview-ui/src/components/settings/SettingsView.tsx index 1854585377..9cfd9b64e5 100644 --- a/webview-ui/src/components/settings/SettingsView.tsx +++ b/webview-ui/src/components/settings/SettingsView.tsx @@ -181,6 +181,7 @@ const SettingsView = forwardRef(({ onDone, t followupAutoApproveTimeoutMs, includeDiagnosticMessages, maxDiagnosticMessages, + includeTaskHistoryInEnhance, } = cachedState const apiConfiguration = useMemo(() => cachedState.apiConfiguration ?? {}, [cachedState.apiConfiguration]) @@ -338,6 +339,7 @@ const SettingsView = forwardRef(({ onDone, t vscode.postMessage({ type: "condensingApiConfigId", text: condensingApiConfigId || "" }) vscode.postMessage({ type: "updateCondensingPrompt", text: customCondensingPrompt || "" }) vscode.postMessage({ type: "updateSupportPrompt", values: customSupportPrompts || {} }) + vscode.postMessage({ type: "includeTaskHistoryInEnhance", bool: includeTaskHistoryInEnhance ?? false }) vscode.postMessage({ type: "upsertApiConfiguration", text: currentApiConfigName, apiConfiguration }) vscode.postMessage({ type: "telemetrySetting", text: telemetrySetting }) vscode.postMessage({ type: "profileThresholds", values: profileThresholds }) @@ -705,6 +707,10 @@ const SettingsView = forwardRef(({ onDone, t + setCachedStateField("includeTaskHistoryInEnhance", value) + } /> )} diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index b156d0193b..d9752bbfb1 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -143,6 +143,8 @@ export interface ExtensionStateContextType extends ExtensionState { setIncludeDiagnosticMessages: (value: boolean) => void maxDiagnosticMessages?: number setMaxDiagnosticMessages: (value: number) => void + includeTaskHistoryInEnhance?: boolean + setIncludeTaskHistoryInEnhance: (value: boolean) => void } export const ExtensionStateContext = createContext(undefined) @@ -260,6 +262,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode project: {}, global: {}, }) + const [includeTaskHistoryInEnhance, setIncludeTaskHistoryInEnhance] = useState(false) const setListApiConfigMeta = useCallback( (value: ProviderSettingsEntry[]) => setState((prevState) => ({ ...prevState, listApiConfigMeta: value })), @@ -293,6 +296,10 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode if ((newState as any).followupAutoApproveTimeoutMs !== undefined) { setFollowupAutoApproveTimeoutMs((newState as any).followupAutoApproveTimeoutMs) } + // Update includeTaskHistoryInEnhance if present in state message + if ((newState as any).includeTaskHistoryInEnhance !== undefined) { + setIncludeTaskHistoryInEnhance((newState as any).includeTaskHistoryInEnhance) + } // Handle marketplace data if present in state message if (newState.marketplaceItems !== undefined) { setMarketplaceItems(newState.marketplaceItems) @@ -503,6 +510,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode setMaxDiagnosticMessages: (value) => { setState((prevState) => ({ ...prevState, maxDiagnosticMessages: value })) }, + includeTaskHistoryInEnhance, + setIncludeTaskHistoryInEnhance, } return {children} diff --git a/webview-ui/src/i18n/locales/ca/prompts.json b/webview-ui/src/i18n/locales/ca/prompts.json index 1f67068df0..5730211daa 100644 --- a/webview-ui/src/i18n/locales/ca/prompts.json +++ b/webview-ui/src/i18n/locales/ca/prompts.json @@ -94,7 +94,9 @@ "useCurrentConfig": "Utilitzar la configuració d'API seleccionada actualment", "testPromptPlaceholder": "Introduïu un prompt per provar la millora", "previewButton": "Previsualització de la millora del prompt", - "testEnhancement": "Prova la millora" + "testEnhancement": "Prova la millora", + "includeTaskHistory": "Inclou l'historial de tasques com a context", + "includeTaskHistoryDescription": "Quan està activat, els últims 10 missatges de la conversa actual s'inclouran com a context en millorar els prompts, ajudant a generar suggeriments més rellevants i conscients del context." }, "condense": { "apiConfiguration": "Configuració de l'API per a la condensació de context", diff --git a/webview-ui/src/i18n/locales/de/prompts.json b/webview-ui/src/i18n/locales/de/prompts.json index 229178abb3..ce5fe66110 100644 --- a/webview-ui/src/i18n/locales/de/prompts.json +++ b/webview-ui/src/i18n/locales/de/prompts.json @@ -94,7 +94,9 @@ "useCurrentConfig": "Aktuell ausgewählte API-Konfiguration verwenden", "testPromptPlaceholder": "Gib einen Prompt ein, um die Verbesserung zu testen", "previewButton": "Vorschau der Prompt-Verbesserung", - "testEnhancement": "Verbesserung testen" + "testEnhancement": "Verbesserung testen", + "includeTaskHistory": "Aufgabenverlauf als Kontext einbeziehen", + "includeTaskHistoryDescription": "Wenn aktiviert, werden die letzten 10 Nachrichten aus der aktuellen Unterhaltung als Kontext beim Verbessern von Prompts einbezogen, um relevantere und kontextbewusste Vorschläge zu generieren." }, "condense": { "apiConfiguration": "API-Konfiguration für die Kontextverdichtung", diff --git a/webview-ui/src/i18n/locales/en/prompts.json b/webview-ui/src/i18n/locales/en/prompts.json index 5d0e6ff8db..0ea5e133b8 100644 --- a/webview-ui/src/i18n/locales/en/prompts.json +++ b/webview-ui/src/i18n/locales/en/prompts.json @@ -93,7 +93,9 @@ "useCurrentConfig": "Use currently selected API configuration", "testPromptPlaceholder": "Enter a prompt to test the enhancement", "previewButton": "Preview Prompt Enhancement", - "testEnhancement": "Test Enhancement" + "testEnhancement": "Test Enhancement", + "includeTaskHistory": "Include task history as context", + "includeTaskHistoryDescription": "When enabled, the last 10 messages from the current conversation will be included as context when enhancing prompts, helping to generate more relevant and context-aware suggestions." }, "condense": { "apiConfiguration": "API Configuration for Context Condensing", diff --git a/webview-ui/src/i18n/locales/es/prompts.json b/webview-ui/src/i18n/locales/es/prompts.json index 50ab1cdb76..26ee72b4b5 100644 --- a/webview-ui/src/i18n/locales/es/prompts.json +++ b/webview-ui/src/i18n/locales/es/prompts.json @@ -94,7 +94,9 @@ "useCurrentConfig": "Usar la configuración de API actualmente seleccionada", "testPromptPlaceholder": "Ingresa una solicitud para probar la mejora", "previewButton": "Vista previa de la mejora de solicitud", - "testEnhancement": "Probar mejora" + "testEnhancement": "Probar mejora", + "includeTaskHistory": "Incluir historial de tareas como contexto", + "includeTaskHistoryDescription": "Cuando está habilitado, los últimos 10 mensajes de la conversación actual se incluirán como contexto al mejorar solicitudes, ayudando a generar sugerencias más relevantes y conscientes del contexto." }, "condense": { "apiConfiguration": "Configuración de API para la condensación de contexto", diff --git a/webview-ui/src/i18n/locales/fr/prompts.json b/webview-ui/src/i18n/locales/fr/prompts.json index d48ef28fa4..3b43280c00 100644 --- a/webview-ui/src/i18n/locales/fr/prompts.json +++ b/webview-ui/src/i18n/locales/fr/prompts.json @@ -94,7 +94,9 @@ "useCurrentConfig": "Utiliser la configuration API actuellement sélectionnée", "testPromptPlaceholder": "Entrez un prompt pour tester l'amélioration", "previewButton": "Aperçu de l'amélioration du prompt", - "testEnhancement": "Tester l'amélioration" + "testEnhancement": "Tester l'amélioration", + "includeTaskHistory": "Inclure l'historique des tâches comme contexte", + "includeTaskHistoryDescription": "Lorsque activé, les 10 derniers messages de la conversation actuelle seront inclus comme contexte lors de l'amélioration des prompts, aidant à générer des suggestions plus pertinentes et conscientes du contexte." }, "condense": { "apiConfiguration": "Configuration de l'API pour la condensation du contexte", diff --git a/webview-ui/src/i18n/locales/hi/prompts.json b/webview-ui/src/i18n/locales/hi/prompts.json index ff409f41f5..bd403adde9 100644 --- a/webview-ui/src/i18n/locales/hi/prompts.json +++ b/webview-ui/src/i18n/locales/hi/prompts.json @@ -94,7 +94,9 @@ "useCurrentConfig": "वर्तमान में चयनित API कॉन्फ़िगरेशन का उपयोग करें", "testPromptPlaceholder": "वृद्धि का परीक्षण करने के लिए एक प्रॉम्प्ट दर्ज करें", "previewButton": "प्रॉम्प्ट वृद्धि का पूर्वावलोकन", - "testEnhancement": "वृद्धि का परीक्षण करें" + "testEnhancement": "वृद्धि का परीक्षण करें", + "includeTaskHistory": "कार्य इतिहास को संदर्भ के रूप में शामिल करें", + "includeTaskHistoryDescription": "जब सक्षम किया जाता है, तो वर्तमान बातचीत के अंतिम 10 संदेश प्रॉम्प्ट को बेहतर बनाते समय संदर्भ के रूप में शामिल किए जाएंगे, जो अधिक प्रासंगिक और संदर्भ-जागरूक सुझाव उत्पन्न करने में मदद करेगा।" }, "condense": { "apiConfiguration": "संदर्भ संघनन के लिए API कॉन्फ़िगरेशन", diff --git a/webview-ui/src/i18n/locales/id/prompts.json b/webview-ui/src/i18n/locales/id/prompts.json index 52736ad69b..b4d45459f0 100644 --- a/webview-ui/src/i18n/locales/id/prompts.json +++ b/webview-ui/src/i18n/locales/id/prompts.json @@ -94,7 +94,9 @@ "useCurrentConfig": "Gunakan konfigurasi API yang sedang dipilih", "testPromptPlaceholder": "Masukkan prompt untuk menguji peningkatan", "previewButton": "Pratinjau Peningkatan Prompt", - "testEnhancement": "Uji Peningkatan" + "testEnhancement": "Uji Peningkatan", + "includeTaskHistory": "Sertakan riwayat tugas sebagai konteks", + "includeTaskHistoryDescription": "Ketika diaktifkan, 10 pesan terakhir dari percakapan saat ini akan disertakan sebagai konteks saat meningkatkan prompt, membantu menghasilkan saran yang lebih relevan dan sadar konteks." }, "condense": { "apiConfiguration": "Konfigurasi API untuk Peringkasan Konteks", diff --git a/webview-ui/src/i18n/locales/it/prompts.json b/webview-ui/src/i18n/locales/it/prompts.json index e6356f828b..57c144a650 100644 --- a/webview-ui/src/i18n/locales/it/prompts.json +++ b/webview-ui/src/i18n/locales/it/prompts.json @@ -94,7 +94,9 @@ "useCurrentConfig": "Usa la configurazione API attualmente selezionata", "testPromptPlaceholder": "Inserisci un prompt per testare il miglioramento", "previewButton": "Anteprima miglioramento prompt", - "testEnhancement": "Testa miglioramento" + "testEnhancement": "Testa miglioramento", + "includeTaskHistory": "Includi cronologia attività come contesto", + "includeTaskHistoryDescription": "Quando abilitato, gli ultimi 10 messaggi della conversazione corrente verranno inclusi come contesto durante il miglioramento dei prompt, aiutando a generare suggerimenti più rilevanti e consapevoli del contesto." }, "condense": { "apiConfiguration": "Configurazione API per la condensazione del contesto", diff --git a/webview-ui/src/i18n/locales/ja/prompts.json b/webview-ui/src/i18n/locales/ja/prompts.json index e9f108f615..15cb64dcf2 100644 --- a/webview-ui/src/i18n/locales/ja/prompts.json +++ b/webview-ui/src/i18n/locales/ja/prompts.json @@ -94,7 +94,9 @@ "useCurrentConfig": "現在選択されているAPI設定を使用", "testPromptPlaceholder": "強化をテストするプロンプトを入力してください", "previewButton": "プロンプト強化のプレビュー", - "testEnhancement": "強化をテスト" + "testEnhancement": "強化をテスト", + "includeTaskHistory": "タスク履歴をコンテキストとして含める", + "includeTaskHistoryDescription": "有効にすると、現在の会話の最後の10メッセージがプロンプト強化時にコンテキストとして含まれ、より関連性が高くコンテキストを意識した提案の生成に役立ちます。" }, "condense": { "apiConfiguration": "コンテキスト圧縮のためのAPI構成", diff --git a/webview-ui/src/i18n/locales/ko/prompts.json b/webview-ui/src/i18n/locales/ko/prompts.json index 688ddd18a9..d21107be43 100644 --- a/webview-ui/src/i18n/locales/ko/prompts.json +++ b/webview-ui/src/i18n/locales/ko/prompts.json @@ -94,7 +94,9 @@ "useCurrentConfig": "현재 선택된 API 구성 사용", "testPromptPlaceholder": "향상을 테스트할 프롬프트 입력", "previewButton": "프롬프트 향상 미리보기", - "testEnhancement": "향상 테스트" + "testEnhancement": "향상 테스트", + "includeTaskHistory": "작업 기록을 컨텍스트로 포함", + "includeTaskHistoryDescription": "활성화하면 현재 대화의 마지막 10개 메시지가 프롬프트 향상 시 컨텍스트로 포함되어 더 관련성 높고 컨텍스트를 인식하는 제안을 생성하는 데 도움이 됩니다." }, "condense": { "apiConfiguration": "컨텍스트 압축을 위한 API 구성", diff --git a/webview-ui/src/i18n/locales/nl/prompts.json b/webview-ui/src/i18n/locales/nl/prompts.json index 7c8ba28605..43af1ada59 100644 --- a/webview-ui/src/i18n/locales/nl/prompts.json +++ b/webview-ui/src/i18n/locales/nl/prompts.json @@ -94,7 +94,9 @@ "useCurrentConfig": "Huidige API-configuratie gebruiken", "testPromptPlaceholder": "Voer een prompt in om de verbetering te testen", "previewButton": "Voorbeeld promptverbetering", - "testEnhancement": "Test verbetering" + "testEnhancement": "Test verbetering", + "includeTaskHistory": "Taakgeschiedenis als context opnemen", + "includeTaskHistoryDescription": "Wanneer ingeschakeld, worden de laatste 10 berichten van het huidige gesprek opgenomen als context bij het verbeteren van prompts, wat helpt bij het genereren van meer relevante en contextbewuste suggesties." }, "condense": { "apiConfiguration": "API-configuratie voor contextcondensatie", diff --git a/webview-ui/src/i18n/locales/pl/prompts.json b/webview-ui/src/i18n/locales/pl/prompts.json index c627f3a84d..7bd71f49b0 100644 --- a/webview-ui/src/i18n/locales/pl/prompts.json +++ b/webview-ui/src/i18n/locales/pl/prompts.json @@ -94,7 +94,9 @@ "useCurrentConfig": "Użyj aktualnie wybranej konfiguracji API", "testPromptPlaceholder": "Wprowadź podpowiedź, aby przetestować ulepszenie", "previewButton": "Podgląd ulepszenia podpowiedzi", - "testEnhancement": "Testuj ulepszenie" + "testEnhancement": "Testuj ulepszenie", + "includeTaskHistory": "Uwzględnij historię zadań jako kontekst", + "includeTaskHistoryDescription": "Gdy włączone, ostatnie 10 wiadomości z bieżącej rozmowy zostanie uwzględnione jako kontekst podczas ulepszania podpowiedzi, pomagając generować bardziej trafne i świadome kontekstu sugestie." }, "condense": { "apiConfiguration": "Konfiguracja API do kondensacji kontekstu", diff --git a/webview-ui/src/i18n/locales/pt-BR/prompts.json b/webview-ui/src/i18n/locales/pt-BR/prompts.json index e5989d2894..5bc3234c4d 100644 --- a/webview-ui/src/i18n/locales/pt-BR/prompts.json +++ b/webview-ui/src/i18n/locales/pt-BR/prompts.json @@ -94,7 +94,9 @@ "useCurrentConfig": "Usar configuração de API atualmente selecionada", "testPromptPlaceholder": "Digite um prompt para testar o aprimoramento", "previewButton": "Visualizar aprimoramento do prompt", - "testEnhancement": "Testar aprimoramento" + "testEnhancement": "Testar aprimoramento", + "includeTaskHistory": "Incluir histórico de tarefas como contexto", + "includeTaskHistoryDescription": "Quando habilitado, as últimas 10 mensagens da conversa atual serão incluídas como contexto ao aprimorar prompts, ajudando a gerar sugestões mais relevantes e conscientes do contexto." }, "condense": { "apiConfiguration": "Configuração da API para condensação de contexto", diff --git a/webview-ui/src/i18n/locales/ru/prompts.json b/webview-ui/src/i18n/locales/ru/prompts.json index c96d4b54a1..cc9210c678 100644 --- a/webview-ui/src/i18n/locales/ru/prompts.json +++ b/webview-ui/src/i18n/locales/ru/prompts.json @@ -91,7 +91,9 @@ "useCurrentConfig": "Использовать текущую конфигурацию API", "testPromptPlaceholder": "Введите промпт для тестирования улучшения", "previewButton": "Просмотреть улучшенный промпт", - "testEnhancement": "Тестировать улучшение" + "testEnhancement": "Тестировать улучшение", + "includeTaskHistory": "Включить историю задач как контекст", + "includeTaskHistoryDescription": "При включении последние 10 сообщений из текущего разговора будут включены как контекст при улучшении промптов, помогая генерировать более релевантные и контекстно-осведомленные предложения." }, "condense": { "apiConfiguration": "Конфигурация API для сжатия контекста", diff --git a/webview-ui/src/i18n/locales/tr/prompts.json b/webview-ui/src/i18n/locales/tr/prompts.json index 9b7e2c569f..eec283977c 100644 --- a/webview-ui/src/i18n/locales/tr/prompts.json +++ b/webview-ui/src/i18n/locales/tr/prompts.json @@ -91,7 +91,9 @@ "useCurrentConfig": "Şu anda seçili API yapılandırmasını kullan", "testPromptPlaceholder": "Geliştirmeyi test etmek için bir prompt girin", "previewButton": "Prompt geliştirmesini önizle", - "testEnhancement": "Geliştirmeyi test et" + "testEnhancement": "Geliştirmeyi test et", + "includeTaskHistory": "Görev geçmişini bağlam olarak dahil et", + "includeTaskHistoryDescription": "Etkinleştirildiğinde, mevcut konuşmanın son 10 mesajı promptları geliştirirken bağlam olarak dahil edilecek ve daha alakalı ve bağlam farkında öneriler üretmeye yardımcı olacaktır." }, "condense": { "apiConfiguration": "Bağlam Yoğunlaştırma için API Yapılandırması", diff --git a/webview-ui/src/i18n/locales/vi/prompts.json b/webview-ui/src/i18n/locales/vi/prompts.json index d3b7e75f3c..d7a38cda6f 100644 --- a/webview-ui/src/i18n/locales/vi/prompts.json +++ b/webview-ui/src/i18n/locales/vi/prompts.json @@ -91,7 +91,9 @@ "useCurrentConfig": "Sử dụng cấu hình API hiện tại đã chọn", "testPromptPlaceholder": "Nhập lời nhắc để kiểm tra việc nâng cao", "previewButton": "Xem trước nâng cao lời nhắc", - "testEnhancement": "Kiểm tra cải tiến" + "testEnhancement": "Kiểm tra cải tiến", + "includeTaskHistory": "Bao gồm lịch sử tác vụ làm ngữ cảnh", + "includeTaskHistoryDescription": "Khi được bật, 10 tin nhắn cuối cùng từ cuộc trò chuyện hiện tại sẽ được bao gồm làm ngữ cảnh khi nâng cao lời nhắc, giúp tạo ra các gợi ý phù hợp và nhận thức ngữ cảnh hơn." }, "condense": { "apiConfiguration": "Cấu hình API để cô đọng ngữ cảnh", diff --git a/webview-ui/src/i18n/locales/zh-CN/prompts.json b/webview-ui/src/i18n/locales/zh-CN/prompts.json index 157ba5d7ea..c21c22b7bd 100644 --- a/webview-ui/src/i18n/locales/zh-CN/prompts.json +++ b/webview-ui/src/i18n/locales/zh-CN/prompts.json @@ -91,7 +91,9 @@ "useCurrentConfig": "使用当前选择的API配置", "testPromptPlaceholder": "输入提示词以测试增强效果", "previewButton": "测试提示词增强", - "testEnhancement": "测试增强" + "testEnhancement": "测试增强", + "includeTaskHistory": "包含任务历史作为上下文", + "includeTaskHistoryDescription": "启用后,当前对话的最后 10 条消息将作为上下文包含在增强提示词时,有助于生成更相关和上下文感知的建议。" }, "condense": { "apiConfiguration": "用于上下文压缩的 API 配置", diff --git a/webview-ui/src/i18n/locales/zh-TW/prompts.json b/webview-ui/src/i18n/locales/zh-TW/prompts.json index 3a2bae4af5..47a32d7d83 100644 --- a/webview-ui/src/i18n/locales/zh-TW/prompts.json +++ b/webview-ui/src/i18n/locales/zh-TW/prompts.json @@ -91,7 +91,9 @@ "useCurrentConfig": "使用目前選擇的 API 設定", "testPromptPlaceholder": "輸入提示詞以測試增強效果", "previewButton": "預覽提示詞增強", - "testEnhancement": "測試增強" + "testEnhancement": "測試增強", + "includeTaskHistory": "包含工作歷史作為內容", + "includeTaskHistoryDescription": "啟用後,目前對話的最後 10 則訊息將作為內容包含在增強提示詞時,有助於產生更相關和內容感知的建議。" }, "condense": { "apiConfiguration": "用於上下文壓縮的 API 設定",