mirror of
https://github.com/cline/cline.git
synced 2026-09-02 15:52:29 +08:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8040d2516d | |||
| 9a0f5a5251 | |||
| ca1e309478 | |||
| 69ae9ebeb4 | |||
| 6e649ea6db | |||
| 2365039cfb | |||
| b31d43a526 | |||
| 3933885d55 | |||
| 1f4818c7e9 |
@@ -124,6 +124,7 @@ message UpdateSettingsRequest {
|
||||
optional OpenaiReasoningEffort openai_reasoning_effort = 15;
|
||||
optional bool strict_plan_mode_enabled = 16;
|
||||
optional FocusChainSettings focus_chain_settings = 17;
|
||||
optional bool use_auto_condense = 18;
|
||||
}
|
||||
|
||||
// Complete API Configuration message
|
||||
|
||||
@@ -135,7 +135,7 @@ export class ContextManager {
|
||||
maxContextWindow: number
|
||||
} | null {
|
||||
// Use provided triggerIndex or fallback to automatic detection
|
||||
let targetIndex
|
||||
let targetIndex: number
|
||||
if (triggerIndex !== undefined) {
|
||||
targetIndex = triggerIndex
|
||||
} else {
|
||||
@@ -174,13 +174,73 @@ export class ContextManager {
|
||||
*/
|
||||
async getNewContextMessagesAndMetadata(
|
||||
apiConversationHistory: Anthropic.Messages.MessageParam[],
|
||||
_clineMessages: ClineMessage[],
|
||||
_api: ApiHandler,
|
||||
clineMessages: ClineMessage[],
|
||||
api: ApiHandler,
|
||||
conversationHistoryDeletedRange: [number, number] | undefined,
|
||||
_previousApiReqIndex: number,
|
||||
_taskDirectory: string,
|
||||
previousApiReqIndex: number,
|
||||
taskDirectory: string,
|
||||
useAutoCondense: boolean, // option to use new auto-condense or old programmatic context management
|
||||
) {
|
||||
const updatedConversationHistoryDeletedRange = false
|
||||
let updatedConversationHistoryDeletedRange = false
|
||||
|
||||
if (!useAutoCondense) {
|
||||
// If the previous API request's total token usage is close to the context window, truncate the conversation history to free up space for the new request
|
||||
if (previousApiReqIndex >= 0) {
|
||||
const previousRequest = clineMessages[previousApiReqIndex]
|
||||
if (previousRequest && previousRequest.text) {
|
||||
const timestamp = previousRequest.ts
|
||||
const { tokensIn, tokensOut, cacheWrites, cacheReads }: ClineApiReqInfo = JSON.parse(previousRequest.text)
|
||||
const totalTokens = (tokensIn || 0) + (tokensOut || 0) + (cacheWrites || 0) + (cacheReads || 0)
|
||||
const { maxAllowedSize } = getContextWindowInfo(api)
|
||||
|
||||
// This is the most reliable way to know when we're close to hitting the context window.
|
||||
if (totalTokens >= maxAllowedSize) {
|
||||
// Since the user may switch between models with different context windows, truncating half may not be enough (ie if switching from claude 200k to deepseek 64k, half truncation will only remove 100k tokens, but we need to remove much more)
|
||||
// So if totalTokens/2 is greater than maxAllowedSize, we truncate 3/4 instead of 1/2
|
||||
const keep = totalTokens / 2 > maxAllowedSize ? "quarter" : "half"
|
||||
|
||||
// we later check how many chars we trim to determine if we should still truncate history
|
||||
let [anyContextUpdates, uniqueFileReadIndices] = this.applyContextOptimizations(
|
||||
apiConversationHistory,
|
||||
conversationHistoryDeletedRange ? conversationHistoryDeletedRange[1] + 1 : 2,
|
||||
timestamp,
|
||||
)
|
||||
|
||||
let needToTruncate = true
|
||||
if (anyContextUpdates) {
|
||||
// determine whether we've saved enough chars to not truncate
|
||||
const charactersSavedPercentage = this.calculateContextOptimizationMetrics(
|
||||
apiConversationHistory,
|
||||
conversationHistoryDeletedRange,
|
||||
uniqueFileReadIndices,
|
||||
)
|
||||
if (charactersSavedPercentage >= 0.3) {
|
||||
needToTruncate = false
|
||||
}
|
||||
}
|
||||
|
||||
if (needToTruncate) {
|
||||
// go ahead with truncation
|
||||
anyContextUpdates = this.applyStandardContextTruncationNoticeChange(timestamp) || anyContextUpdates
|
||||
|
||||
// NOTE: it's okay that we overwriteConversationHistory in resume task since we're only ever removing the last user message and not anything in the middle which would affect this range
|
||||
conversationHistoryDeletedRange = this.getNextTruncationRange(
|
||||
apiConversationHistory,
|
||||
conversationHistoryDeletedRange,
|
||||
keep,
|
||||
)
|
||||
|
||||
updatedConversationHistoryDeletedRange = true
|
||||
}
|
||||
|
||||
// if we alter the context history, save the updated version to disk
|
||||
if (anyContextUpdates) {
|
||||
await this.saveContextHistory(taskDirectory)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const truncatedConversationHistory = this.getAndAlterTruncatedMessages(
|
||||
apiConversationHistory,
|
||||
@@ -593,8 +653,7 @@ export class ContextManager {
|
||||
let foundMatch = false
|
||||
const filePaths: string[] = []
|
||||
|
||||
let match
|
||||
while ((match = pattern.exec(secondBlockText)) !== null) {
|
||||
for (const match of secondBlockText.matchAll(pattern)) {
|
||||
foundMatch = true
|
||||
|
||||
const filePath = match[1]
|
||||
@@ -835,7 +894,7 @@ export class ContextManager {
|
||||
|
||||
// if block was just altered, then calculate savings
|
||||
if (hasNewAlterations) {
|
||||
let originalTextLength
|
||||
let originalTextLength: number
|
||||
if (updates.length > 1) {
|
||||
originalTextLength = updates[updates.length - 2][2][0].length // handles case if we have multiple updates for same text block
|
||||
} else {
|
||||
|
||||
@@ -174,6 +174,7 @@ export class Controller {
|
||||
const isNewUser = this.cacheService.getGlobalStateKey("isNewUser")
|
||||
const taskHistory = this.cacheService.getGlobalStateKey("taskHistory")
|
||||
const strictPlanModeEnabled = this.cacheService.getGlobalStateKey("strictPlanModeEnabled")
|
||||
const useAutoCondense = this.cacheService.getGlobalStateKey("useAutoCondense")
|
||||
|
||||
const NEW_USER_TASK_COUNT_THRESHOLD = 10
|
||||
|
||||
@@ -211,6 +212,7 @@ export class Controller {
|
||||
openaiReasoningEffort,
|
||||
mode,
|
||||
strictPlanModeEnabled ?? false,
|
||||
useAutoCondense ?? true,
|
||||
shellIntegrationTimeout,
|
||||
terminalReuseEnabled ?? true,
|
||||
terminalOutputLineLimit ?? 500,
|
||||
@@ -584,6 +586,7 @@ export class Controller {
|
||||
const openaiReasoningEffort = this.cacheService.getGlobalStateKey("openaiReasoningEffort")
|
||||
const mode = this.cacheService.getGlobalStateKey("mode")
|
||||
const strictPlanModeEnabled = this.cacheService.getGlobalStateKey("strictPlanModeEnabled")
|
||||
const useAutoCondense = this.cacheService.getGlobalStateKey("useAutoCondense")
|
||||
const userInfo = this.cacheService.getGlobalStateKey("userInfo")
|
||||
const mcpMarketplaceEnabled = this.cacheService.getGlobalStateKey("mcpMarketplaceEnabled")
|
||||
const mcpDisplayMode = this.cacheService.getGlobalStateKey("mcpDisplayMode")
|
||||
@@ -641,6 +644,7 @@ export class Controller {
|
||||
openaiReasoningEffort,
|
||||
mode,
|
||||
strictPlanModeEnabled,
|
||||
useAutoCondense,
|
||||
userInfo,
|
||||
mcpMarketplaceEnabled,
|
||||
mcpDisplayMode,
|
||||
|
||||
@@ -139,6 +139,14 @@ export async function updateSettings(controller: Controller, request: UpdateSett
|
||||
controller.cacheService.setGlobalState("strictPlanModeEnabled", request.strictPlanModeEnabled)
|
||||
}
|
||||
|
||||
// Update auto-condense setting
|
||||
if (request.useAutoCondense !== undefined) {
|
||||
if (controller.task) {
|
||||
controller.task.updateUseAutoCondense(request.useAutoCondense)
|
||||
}
|
||||
controller.cacheService.setGlobalState("useAutoCondense", request.useAutoCondense)
|
||||
}
|
||||
|
||||
// Update focus chain settings
|
||||
if (request.focusChainSettings !== undefined) {
|
||||
const remoteEnabled = controller.cacheService.getGlobalStateKey("focusChainFeatureFlagEnabled")
|
||||
|
||||
@@ -736,6 +736,7 @@ export class CacheService {
|
||||
const globalStateFields = {
|
||||
// Extension state fields
|
||||
strictPlanModeEnabled: state.strictPlanModeEnabled,
|
||||
useAutoCondense: state.useAutoCondense,
|
||||
isNewUser: state.isNewUser,
|
||||
welcomeViewCompleted: state.welcomeViewCompleted,
|
||||
autoApprovalSettings: state.autoApprovalSettings || DEFAULT_AUTO_APPROVAL_SETTINGS,
|
||||
|
||||
@@ -103,6 +103,7 @@ export type GlobalStateKey =
|
||||
| "sapAiResourceGroup"
|
||||
| "claudeCodePath"
|
||||
| "strictPlanModeEnabled"
|
||||
| "useAutoCondense"
|
||||
| "focusChainSettings"
|
||||
| "focusChainFeatureFlagEnabled"
|
||||
// Settings around plan/act and ephemeral model configuration
|
||||
@@ -227,6 +228,7 @@ export interface GlobalState {
|
||||
sapAiResourceGroup: string | undefined
|
||||
claudeCodePath: string | undefined
|
||||
strictPlanModeEnabled: boolean
|
||||
useAutoCondense: boolean
|
||||
preferredLanguage: string
|
||||
openaiReasoningEffort: OpenaiReasoningEffort
|
||||
mode: Mode
|
||||
|
||||
@@ -14,6 +14,7 @@ import { SecretKey } from "../state-keys"
|
||||
export async function readStateFromDisk(context: ExtensionContext) {
|
||||
// Get all global state values
|
||||
const strictPlanModeEnabled = context.globalState.get("strictPlanModeEnabled") as boolean | undefined
|
||||
const useAutoCondense = context.globalState.get("useAutoCondense") as boolean | undefined
|
||||
const isNewUser = context.globalState.get("isNewUser") as boolean | undefined
|
||||
const welcomeViewCompleted = context.globalState.get("welcomeViewCompleted") as boolean | undefined
|
||||
const awsRegion = context.globalState.get("awsRegion") as string | undefined
|
||||
@@ -373,6 +374,7 @@ export async function readStateFromDisk(context: ExtensionContext) {
|
||||
actModeBasetenModelInfo,
|
||||
},
|
||||
strictPlanModeEnabled: strictPlanModeEnabled ?? false,
|
||||
useAutoCondense: useAutoCondense ?? true,
|
||||
isNewUser: isNewUser ?? true,
|
||||
welcomeViewCompleted,
|
||||
lastShownAnnouncementId,
|
||||
|
||||
+95
-63
@@ -121,6 +121,9 @@ export class Task {
|
||||
// Focus Chain
|
||||
private FocusChainManager?: FocusChainManager
|
||||
|
||||
// Context Management
|
||||
private useAutoCondense: boolean
|
||||
|
||||
// Callbacks
|
||||
private updateTaskHistory: (historyItem: HistoryItem) => Promise<HistoryItem[]>
|
||||
private postStateToWebview: () => Promise<void>
|
||||
@@ -155,6 +158,7 @@ export class Task {
|
||||
openaiReasoningEffort: OpenaiReasoningEffort,
|
||||
mode: Mode,
|
||||
strictPlanModeEnabled: boolean,
|
||||
useAutoCondense: boolean,
|
||||
shellIntegrationTimeout: number,
|
||||
terminalReuseEnabled: boolean,
|
||||
terminalOutputLineLimit: number,
|
||||
@@ -206,6 +210,7 @@ export class Task {
|
||||
this.enableCheckpoints = enableCheckpointsSetting
|
||||
this.cwd = cwd
|
||||
this.cacheService = cacheService
|
||||
this.useAutoCondense = useAutoCondense
|
||||
|
||||
// Set up MCP notification callback for real-time notifications
|
||||
this.mcpHub.setNotificationCallback(async (serverName: string, _level: string, message: string) => {
|
||||
@@ -377,6 +382,10 @@ export class Task {
|
||||
this.toolExecutor.updateStrictPlanModeEnabled(strictPlanModeEnabled)
|
||||
}
|
||||
|
||||
public updateUseAutoCondense(useAutoCondense: boolean): void {
|
||||
this.useAutoCondense = useAutoCondense
|
||||
}
|
||||
|
||||
// While a task is ref'd by a controller, it will always have access to the extension context
|
||||
// This error is thrown if the controller derefs the task after e.g., aborting the task
|
||||
private getContext(): vscode.ExtensionContext {
|
||||
@@ -1717,6 +1726,7 @@ export class Task {
|
||||
this.taskState.conversationHistoryDeletedRange,
|
||||
previousApiReqIndex,
|
||||
await ensureTaskDirectoryExists(this.getContext(), this.taskId),
|
||||
this.useAutoCondense,
|
||||
)
|
||||
|
||||
if (contextManagementMetadata.updatedConversationHistoryDeletedRange) {
|
||||
@@ -2142,84 +2152,106 @@ export class Task {
|
||||
// No explicit UI message here, error message will be in ExtensionState.
|
||||
}
|
||||
|
||||
// when we initially trigger the context cleanup, we will be increasing the context window size, so we need some state `currentlySummarizing`
|
||||
// to store whether we have already started the context summarization flow, so we don't attempt to summarize again. additionally, immediately
|
||||
// post summarizing we need to increment the conversationHistoryDeletedRange to mask out the summarization-trigger user & assistant response messaages
|
||||
let shouldCompact = false
|
||||
if (this.taskState.currentlySummarizing) {
|
||||
this.taskState.currentlySummarizing = false
|
||||
// Separate logic when using the auto-condense context management vs the original context management methods
|
||||
if (this.useAutoCondense) {
|
||||
// when we initially trigger the context cleanup, we will be increasing the context window size, so we need some state `currentlySummarizing`
|
||||
// to store whether we have already started the context summarization flow, so we don't attempt to summarize again. additionally, immediately
|
||||
// post summarizing we need to increment the conversationHistoryDeletedRange to mask out the summarization-trigger user & assistant response messaages
|
||||
let shouldCompact = false
|
||||
if (this.taskState.currentlySummarizing) {
|
||||
this.taskState.currentlySummarizing = false
|
||||
|
||||
if (this.taskState.conversationHistoryDeletedRange) {
|
||||
const [start, end] = this.taskState.conversationHistoryDeletedRange
|
||||
const apiHistory = this.messageStateHandler.getApiConversationHistory()
|
||||
if (this.taskState.conversationHistoryDeletedRange) {
|
||||
const [start, end] = this.taskState.conversationHistoryDeletedRange
|
||||
const apiHistory = this.messageStateHandler.getApiConversationHistory()
|
||||
|
||||
// we want to increment the deleted range to remove the pre-summarization tool call output, with additional safety check
|
||||
const safeEnd = Math.min(end + 2, apiHistory.length - 1)
|
||||
if (end + 2 <= safeEnd) {
|
||||
this.taskState.conversationHistoryDeletedRange = [start, end + 2]
|
||||
await this.messageStateHandler.saveClineMessagesAndUpdateHistory()
|
||||
// we want to increment the deleted range to remove the pre-summarization tool call output, with additional safety check
|
||||
const safeEnd = Math.min(end + 2, apiHistory.length - 1)
|
||||
if (end + 2 <= safeEnd) {
|
||||
this.taskState.conversationHistoryDeletedRange = [start, end + 2]
|
||||
await this.messageStateHandler.saveClineMessagesAndUpdateHistory()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
shouldCompact = this.contextManager.shouldCompactContextWindow(
|
||||
this.messageStateHandler.getClineMessages(),
|
||||
this.api,
|
||||
previousApiReqIndex,
|
||||
)
|
||||
|
||||
// There is an edge case where the summarize_task tool call completes but the user cancels the next request before it finishes
|
||||
// this will result in this.taskState.currentlySummarizing being false, and we also failed to update the context window token
|
||||
// estimate, which require a full new message to be completed along with gathering the latest usage block. A proxy for whether
|
||||
// we just summarized would be to check the number of in-range messages, which itself has some extreme edge case (e.g. what if
|
||||
// first+second user messages take up entire context-window, but in this case there's already an issue). TODO: Examine other
|
||||
// approaches such as storing this.taskState.currentlySummarizing on disk in the clineMessages. This was intentionally not done
|
||||
// for now to prevent additional disk from needing to be used.
|
||||
// The worse case scenario is effectively cline summarizing a summary, which is bad UX, but doesn't break other logic.
|
||||
if (shouldCompact && this.taskState.conversationHistoryDeletedRange) {
|
||||
const apiHistory = this.messageStateHandler.getApiConversationHistory()
|
||||
const activeMessageCount = apiHistory.length - this.taskState.conversationHistoryDeletedRange[1] - 1
|
||||
|
||||
// IMPORTANT - we didn't append this next user message yet so the last message in this array is an assistant message
|
||||
// that's why we are comparing to an even number of messages (0, 2) rather than odd (1, 3)
|
||||
if (activeMessageCount <= 2) {
|
||||
shouldCompact = false
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
shouldCompact = this.contextManager.shouldCompactContextWindow(
|
||||
this.messageStateHandler.getClineMessages(),
|
||||
this.api,
|
||||
previousApiReqIndex,
|
||||
)
|
||||
|
||||
// There is an edge case where the summarize_task tool call completes but the user cancels the next request before it finishes
|
||||
// this will result in this.taskState.currentlySummarizing being false, and we also failed to update the context window token
|
||||
// estimate, which require a full new message to be completed along with gathering the latest usage block. A proxy for whether
|
||||
// we just summarized would be to check the number of in-range messages, which itself has some extreme edge case (e.g. what if
|
||||
// first+second user messages take up entire context-window, but in this case there's already an issue). TODO: Examine other
|
||||
// approaches such as storing this.taskState.currentlySummarizing on disk in the clineMessages. This was intentionally not done
|
||||
// for now to prevent additional disk from needing to be used.
|
||||
// The worse case scenario is effectively cline summarizing a summary, which is bad UX, but doesn't break other logic.
|
||||
if (shouldCompact && this.taskState.conversationHistoryDeletedRange) {
|
||||
const apiHistory = this.messageStateHandler.getApiConversationHistory()
|
||||
const activeMessageCount = apiHistory.length - this.taskState.conversationHistoryDeletedRange[1] - 1
|
||||
let parsedUserContent: UserContent
|
||||
let environmentDetails: string
|
||||
let clinerulesError: boolean
|
||||
|
||||
// IMPORTANT - we didn't append this next user message yet so the last message in this array is an assistant message
|
||||
// that's why we are comparing to an even number of messages (0, 2) rather than odd (1, 3)
|
||||
if (activeMessageCount <= 2) {
|
||||
shouldCompact = false
|
||||
}
|
||||
// when summarizing the context window, we do not want to inject updated to the context
|
||||
if (shouldCompact) {
|
||||
parsedUserContent = userContent
|
||||
environmentDetails = ""
|
||||
clinerulesError = false
|
||||
this.taskState.lastAutoCompactTriggerIndex = previousApiReqIndex
|
||||
} else {
|
||||
;[parsedUserContent, environmentDetails, clinerulesError] = await this.loadContext(
|
||||
userContent,
|
||||
includeFileDetails,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
let parsedUserContent: UserContent
|
||||
let environmentDetails: string
|
||||
let clinerulesError: boolean
|
||||
// error handling if the user uses the /newrule command & their .clinerules is a file, for file read operations didnt work properly
|
||||
if (clinerulesError === true) {
|
||||
await this.say(
|
||||
"error",
|
||||
"Issue with processing the /newrule command. Double check that, if '.clinerules' already exists, it's a directory and not a file. Otherwise there was an issue referencing this file/directory.",
|
||||
)
|
||||
}
|
||||
|
||||
// when summarizing the context window, we do not want to inject updated to the context
|
||||
if (shouldCompact) {
|
||||
parsedUserContent = userContent
|
||||
environmentDetails = ""
|
||||
clinerulesError = false
|
||||
this.taskState.lastAutoCompactTriggerIndex = previousApiReqIndex
|
||||
userContent = parsedUserContent
|
||||
// add environment details as its own text block, separate from tool results
|
||||
// do not add environment details to the message which we are compacting the context window
|
||||
if (!shouldCompact) {
|
||||
userContent.push({ type: "text", text: environmentDetails })
|
||||
}
|
||||
|
||||
if (shouldCompact) {
|
||||
userContent.push({ type: "text", text: summarizeTask(this.focusChainSettings.enabled) })
|
||||
}
|
||||
} else {
|
||||
;[parsedUserContent, environmentDetails, clinerulesError] = await this.loadContext(userContent, includeFileDetails)
|
||||
}
|
||||
|
||||
// error handling if the user uses the /newrule command & their .clinerules is a file, for file read operations didnt work properly
|
||||
if (clinerulesError === true) {
|
||||
await this.say(
|
||||
"error",
|
||||
"Issue with processing the /newrule command. Double check that, if '.clinerules' already exists, it's a directory and not a file. Otherwise there was an issue referencing this file/directory.",
|
||||
const [parsedUserContent, environmentDetails, clinerulesError] = await this.loadContext(
|
||||
userContent,
|
||||
includeFileDetails,
|
||||
)
|
||||
}
|
||||
|
||||
userContent = parsedUserContent
|
||||
// add environment details as its own text block, separate from tool results
|
||||
// do not add environment details to the message which we are compacting the context window
|
||||
if (!shouldCompact) {
|
||||
if (clinerulesError === true) {
|
||||
await this.say(
|
||||
"error",
|
||||
"Issue with processing the /newrule command. Double check that, if '.clinerules' already exists, it's a directory and not a file. Otherwise there was an issue referencing this file/directory.",
|
||||
)
|
||||
}
|
||||
|
||||
userContent = parsedUserContent
|
||||
|
||||
userContent.push({ type: "text", text: environmentDetails })
|
||||
}
|
||||
|
||||
if (shouldCompact) {
|
||||
userContent.push({ type: "text", text: summarizeTask(this.focusChainSettings.enabled) })
|
||||
}
|
||||
|
||||
await this.messageStateHandler.addToApiConversationHistory({
|
||||
role: "user",
|
||||
content: userContent,
|
||||
|
||||
@@ -67,6 +67,7 @@ export interface ExtensionState {
|
||||
localWindsurfRulesToggles: ClineRulesToggles
|
||||
mcpResponsesCollapsed?: boolean
|
||||
strictPlanModeEnabled?: boolean
|
||||
useAutoCondense?: boolean
|
||||
focusChainSettings: FocusChainSettings
|
||||
focusChainFeatureFlagEnabled?: boolean
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ const FeatureSettingsSection = ({ renderSectionHeader }: FeatureSettingsSectionP
|
||||
mcpResponsesCollapsed,
|
||||
openaiReasoningEffort,
|
||||
strictPlanModeEnabled,
|
||||
useAutoCondense,
|
||||
focusChainSettings,
|
||||
focusChainFeatureFlagEnabled,
|
||||
} = useExtensionState()
|
||||
@@ -167,6 +168,20 @@ const FeatureSettingsSection = ({ renderSectionHeader }: FeatureSettingsSectionP
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
<div style={{ marginTop: 10 }}>
|
||||
<VSCodeCheckbox
|
||||
checked={useAutoCondense}
|
||||
onChange={(e: any) => {
|
||||
const checked = e.target.checked === true
|
||||
updateSetting("useAutoCondense", checked)
|
||||
}}>
|
||||
Enable auto condense
|
||||
</VSCodeCheckbox>
|
||||
<p className="text-xs text-[var(--vscode-descriptionForeground)]">
|
||||
Enables advanced context management system which uses LLM based condensing, instead of rule-based
|
||||
truncation.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
</div>
|
||||
|
||||
@@ -197,6 +197,7 @@ export const ExtensionStateContextProvider: React.FC<{
|
||||
welcomeViewCompleted: false,
|
||||
mcpResponsesCollapsed: false, // Default value (expanded), will be overwritten by extension state
|
||||
strictPlanModeEnabled: false,
|
||||
useAutoCondense: true,
|
||||
})
|
||||
const [didHydrateState, setDidHydrateState] = useState(false)
|
||||
const [showWelcome, setShowWelcome] = useState(false)
|
||||
|
||||
Reference in New Issue
Block a user