Просмотр исходного кода

feat(condense): improve condensation with environment details, accurate token counts, and lazy evaluation (#10920)

Hannes Rudolph 3 недель назад
Родитель
Сommit
0ff826d21d

+ 7 - 7
src/core/condense/__tests__/condense.spec.ts

@@ -136,7 +136,7 @@ Line 2
 				{ role: "user", content: "Ninth message" },
 			]
 
-			const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, 5000, false)
+			const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, false)
 
 			// Verify we have a summary message with role "user" (fresh start model)
 			const summaryMessage = result.messages.find((msg) => msg.isSummary)
@@ -164,7 +164,7 @@ Line 2
 				{ role: "user", content: "Fifth message" },
 			]
 
-			const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, 5000, false)
+			const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, false)
 
 			// All original messages should be tagged with condenseParent
 			const taggedMessages = result.messages.filter((msg) => !msg.isSummary)
@@ -193,7 +193,7 @@ Line 2
 				{ role: "user", content: "Ninth message" },
 			]
 
-			const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, 5000, false)
+			const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, false)
 
 			const summaryMessage = result.messages.find((msg) => msg.isSummary)
 			expect(summaryMessage).toBeTruthy()
@@ -227,7 +227,7 @@ Line 2
 				{ role: "user", content: "Perfect!" },
 			]
 
-			const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, 5000, false)
+			const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, false)
 
 			// Effective history should contain only the summary (fresh start)
 			const effectiveHistory = getEffectiveApiHistory(result.messages)
@@ -239,7 +239,7 @@ Line 2
 		it("should return error when not enough messages to summarize", async () => {
 			const messages: ApiMessage[] = [{ role: "user", content: "Only one message" }]
 
-			const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, 5000, false)
+			const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, false)
 
 			// Should return an error since we have only 1 message
 			expect(result.error).toBeDefined()
@@ -253,7 +253,7 @@ Line 2
 				{ role: "assistant", content: "Previous summary", isSummary: true },
 			]
 
-			const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, 5000, false)
+			const result = await summarizeConversation(messages, mockApiHandler, "System prompt", taskId, false)
 
 			// Should return an error due to recent summary with no substantial messages after
 			expect(result.error).toBeDefined()
@@ -286,7 +286,7 @@ Line 2
 				{ role: "user", content: "Seventh" },
 			]
 
-			const result = await summarizeConversation(messages, emptyHandler, "System prompt", taskId, 5000, false)
+			const result = await summarizeConversation(messages, emptyHandler, "System prompt", taskId, false)
 
 			expect(result.error).toBeDefined()
 			expect(result.messages).toEqual(messages)

+ 23 - 136
src/core/condense/__tests__/index.spec.ts

@@ -30,7 +30,6 @@ vi.mock("@roo-code/telemetry", () => ({
 }))
 
 const taskId = "test-task-id"
-const DEFAULT_PREV_CONTEXT_TOKENS = 1000
 
 describe("extractCommandBlocks", () => {
 	it("should extract command blocks from string content", () => {
@@ -713,13 +712,7 @@ describe("summarizeConversation", () => {
 	it("should not summarize when there are not enough messages", async () => {
 		const messages: ApiMessage[] = [{ role: "user", content: "Hello", ts: 1 }]
 
-		const result = await summarizeConversation(
-			messages,
-			mockApiHandler,
-			defaultSystemPrompt,
-			taskId,
-			DEFAULT_PREV_CONTEXT_TOKENS,
-		)
+		const result = await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)
 		expect(result.messages).toEqual(messages)
 		expect(result.cost).toBe(0)
 		expect(result.summary).toBe("")
@@ -739,13 +732,7 @@ describe("summarizeConversation", () => {
 			{ role: "user", content: "Tell me more", ts: 7 },
 		]
 
-		const result = await summarizeConversation(
-			messages,
-			mockApiHandler,
-			defaultSystemPrompt,
-			taskId,
-			DEFAULT_PREV_CONTEXT_TOKENS,
-		)
+		const result = await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)
 
 		// Check that the API was called correctly
 		expect(mockApiHandler.createMessage).toHaveBeenCalled()
@@ -781,7 +768,8 @@ describe("summarizeConversation", () => {
 		// Check the cost and token counts
 		expect(result.cost).toBe(0.05)
 		expect(result.summary).toBe("This is a summary")
-		expect(result.newContextTokens).toBe(250) // outputTokens(150) + countTokens(100)
+		// newContextTokens = countTokens(systemPrompt + summaryMessage) - counts actual content, not outputTokens
+		expect(result.newContextTokens).toBe(100) // countTokens mock returns 100
 		expect(result.error).toBeUndefined()
 	})
 
@@ -798,13 +786,7 @@ describe("summarizeConversation", () => {
 			{ role: "user", content: "What's new?", ts: 5 },
 		]
 
-		const result = await summarizeConversation(
-			messages,
-			mockApiHandler,
-			defaultSystemPrompt,
-			taskId,
-			DEFAULT_PREV_CONTEXT_TOKENS,
-		)
+		const result = await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)
 
 		const summaryMessage = result.messages.find((m) => m.isSummary)
 		expect(summaryMessage).toBeDefined()
@@ -827,13 +809,7 @@ describe("summarizeConversation", () => {
 			{ role: "user", content: "What's new?", ts: 5 },
 		]
 
-		const result = await summarizeConversation(
-			messages,
-			mockApiHandler,
-			defaultSystemPrompt,
-			taskId,
-			DEFAULT_PREV_CONTEXT_TOKENS,
-		)
+		const result = await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)
 
 		const summaryMessage = result.messages.find((m) => m.isSummary)
 		expect(summaryMessage).toBeDefined()
@@ -870,13 +846,7 @@ describe("summarizeConversation", () => {
 			return messages.map(({ role, content }: { role: string; content: any }) => ({ role, content }))
 		})
 
-		const result = await summarizeConversation(
-			messages,
-			mockApiHandler,
-			defaultSystemPrompt,
-			taskId,
-			DEFAULT_PREV_CONTEXT_TOKENS,
-		)
+		const result = await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)
 
 		// Should return original messages when summary is empty
 		expect(result.messages).toEqual(messages)
@@ -897,7 +867,7 @@ describe("summarizeConversation", () => {
 			{ role: "user", content: "Tell me more", ts: 7 },
 		]
 
-		await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId, DEFAULT_PREV_CONTEXT_TOKENS)
+		await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)
 
 		// Verify that createMessage was called with the SUMMARY_PROMPT (which contains CRITICAL instructions), messages array, and optional metadata
 		expect(mockApiHandler.createMessage).toHaveBeenCalledWith(
@@ -929,7 +899,7 @@ describe("summarizeConversation", () => {
 			{ role: "user", content: "Newest", ts: 7 },
 		]
 
-		await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId, DEFAULT_PREV_CONTEXT_TOKENS)
+		await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)
 
 		const mockCallArgs = (maybeRemoveImageBlocks as Mock).mock.calls[0][0] as any[]
 
@@ -967,65 +937,19 @@ describe("summarizeConversation", () => {
 		// Override the mock for this test
 		mockApiHandler.createMessage = vi.fn().mockReturnValue(streamWithUsage) as any
 
-		const result = await summarizeConversation(
-			messages,
-			mockApiHandler,
-			systemPrompt,
-			taskId,
-			DEFAULT_PREV_CONTEXT_TOKENS,
-		)
+		const result = await summarizeConversation(messages, mockApiHandler, systemPrompt, taskId)
 
-		// Verify that countTokens was called with system prompt
+		// Verify that countTokens was called with system prompt + summary message
 		expect(mockApiHandler.countTokens).toHaveBeenCalled()
 
-		// newContextTokens includes the summary output tokens plus countTokens(systemPrompt)
-		expect(result.newContextTokens).toBe(300) // outputTokens(200) + countTokens(100)
+		// newContextTokens = countTokens(systemPrompt + summaryMessage) - counts actual content
+		expect(result.newContextTokens).toBe(100) // countTokens mock returns 100
 		expect(result.cost).toBe(0.06)
 		expect(result.summary).toBe("This is a summary with system prompt")
 		expect(result.error).toBeUndefined()
 	})
 
-	it("should return error when new context tokens >= previous context tokens", async () => {
-		const messages: ApiMessage[] = [
-			{ role: "user", content: "Hello", ts: 1 },
-			{ role: "assistant", content: "Hi there", ts: 2 },
-			{ role: "user", content: "How are you?", ts: 3 },
-			{ role: "assistant", content: "I'm good", ts: 4 },
-			{ role: "user", content: "What's new?", ts: 5 },
-			{ role: "assistant", content: "Not much", ts: 6 },
-			{ role: "user", content: "Tell me more", ts: 7 },
-		]
-
-		// Create a stream that produces a summary
-		const streamWithLargeTokens = (async function* () {
-			yield { type: "text" as const, text: "This is a very long summary that uses many tokens" }
-			yield { type: "usage" as const, totalCost: 0.08, outputTokens: 500 }
-		})()
-
-		// Override the mock for this test
-		mockApiHandler.createMessage = vi.fn().mockReturnValue(streamWithLargeTokens) as any
-
-		// Mock countTokens to return a value >= prevContextTokens
-		mockApiHandler.countTokens = vi.fn().mockImplementation(() => Promise.resolve(600)) as any
-
-		const prevContextTokens = 600
-		const result = await summarizeConversation(
-			messages,
-			mockApiHandler,
-			defaultSystemPrompt,
-			taskId,
-			prevContextTokens,
-		)
-
-		// Should return original messages when context would not shrink
-		expect(result.messages).toEqual(messages)
-		expect(result.cost).toBe(0.08)
-		expect(result.summary).toBe("")
-		expect(result.error).toBeTruthy() // Error should be set
-		expect(result.newContextTokens).toBeUndefined()
-	})
-
-	it("should successfully summarize when new context tokens < previous context tokens", async () => {
+	it("should successfully summarize conversation", async () => {
 		const messages: ApiMessage[] = [
 			{ role: "user", content: "Hello", ts: 1 },
 			{ role: "assistant", content: "Hi there", ts: 2 },
@@ -1045,17 +969,10 @@ describe("summarizeConversation", () => {
 		// Override the mock for this test
 		mockApiHandler.createMessage = vi.fn().mockReturnValue(streamWithSmallTokens) as any
 
-		// Mock countTokens to return a small value so total is < prevContextTokens
+		// Mock countTokens to return a small value
 		mockApiHandler.countTokens = vi.fn().mockImplementation(() => Promise.resolve(30)) as any
 
-		const prevContextTokens = 200
-		const result = await summarizeConversation(
-			messages,
-			mockApiHandler,
-			defaultSystemPrompt,
-			taskId,
-			prevContextTokens,
-		)
+		const result = await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)
 
 		// Result contains all messages plus summary
 		expect(result.messages.length).toBe(messages.length + 1)
@@ -1068,8 +985,8 @@ describe("summarizeConversation", () => {
 		expect(result.cost).toBe(0.03)
 		expect(result.summary).toBe("Concise summary")
 		expect(result.error).toBeUndefined()
-		expect(result.newContextTokens).toBe(80) // outputTokens(50) + countTokens(30)
-		expect(result.newContextTokens).toBeLessThan(prevContextTokens)
+		// newContextTokens = countTokens(systemPrompt + summaryMessage) - counts actual content
+		expect(result.newContextTokens).toBe(30) // countTokens mock returns 30
 	})
 
 	it("should return error when API handler is invalid", async () => {
@@ -1095,13 +1012,7 @@ describe("summarizeConversation", () => {
 		const mockError = vi.fn()
 		console.error = mockError
 
-		const result = await summarizeConversation(
-			messages,
-			invalidHandler,
-			defaultSystemPrompt,
-			taskId,
-			DEFAULT_PREV_CONTEXT_TOKENS,
-		)
+		const result = await summarizeConversation(messages, invalidHandler, defaultSystemPrompt, taskId)
 
 		// Should return original messages when handler is invalid
 		expect(result.messages).toEqual(messages)
@@ -1126,13 +1037,7 @@ describe("summarizeConversation", () => {
 			{ role: "user", content: "Thanks", ts: 5 },
 		]
 
-		const result = await summarizeConversation(
-			messages,
-			mockApiHandler,
-			defaultSystemPrompt,
-			taskId,
-			DEFAULT_PREV_CONTEXT_TOKENS,
-		)
+		const result = await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)
 
 		const summaryMessage = result.messages.find((m) => m.isSummary)
 		expect(summaryMessage).toBeDefined()
@@ -1153,13 +1058,7 @@ describe("summarizeConversation", () => {
 			{ role: "user", content: "Thanks", ts: 5 },
 		]
 
-		const result = await summarizeConversation(
-			messages,
-			mockApiHandler,
-			defaultSystemPrompt,
-			taskId,
-			DEFAULT_PREV_CONTEXT_TOKENS,
-		)
+		const result = await summarizeConversation(messages, mockApiHandler, defaultSystemPrompt, taskId)
 
 		// Summary should be the last message
 		const lastMessage = result.messages[result.messages.length - 1]
@@ -1228,7 +1127,6 @@ describe("summarizeConversation with custom settings", () => {
 			mockMainApiHandler,
 			defaultSystemPrompt,
 			localTaskId,
-			DEFAULT_PREV_CONTEXT_TOKENS,
 			false,
 			customPrompt,
 		)
@@ -1248,15 +1146,7 @@ describe("summarizeConversation with custom settings", () => {
 	 */
 	it("should use default systemPrompt when custom prompt is empty or not provided", async () => {
 		// Test with empty string
-		await summarizeConversation(
-			sampleMessages,
-			mockMainApiHandler,
-			defaultSystemPrompt,
-			localTaskId,
-			DEFAULT_PREV_CONTEXT_TOKENS,
-			false,
-			"  ", // Empty custom prompt
-		)
+		await summarizeConversation(sampleMessages, mockMainApiHandler, defaultSystemPrompt, localTaskId, false, "  ")
 
 		// Verify the default SUMMARY_PROMPT was used (contains CRITICAL instructions)
 		let createMessageCalls = (mockMainApiHandler.createMessage as Mock).mock.calls
@@ -1273,9 +1163,8 @@ describe("summarizeConversation with custom settings", () => {
 			mockMainApiHandler,
 			defaultSystemPrompt,
 			localTaskId,
-			DEFAULT_PREV_CONTEXT_TOKENS,
 			false,
-			undefined, // No custom prompt
+			undefined,
 		)
 
 		// Verify the default SUMMARY_PROMPT was used again (contains CRITICAL instructions)
@@ -1296,7 +1185,6 @@ describe("summarizeConversation with custom settings", () => {
 			mockMainApiHandler,
 			defaultSystemPrompt,
 			localTaskId,
-			DEFAULT_PREV_CONTEXT_TOKENS,
 			false,
 			"Custom prompt",
 		)
@@ -1318,7 +1206,6 @@ describe("summarizeConversation with custom settings", () => {
 			mockMainApiHandler,
 			defaultSystemPrompt,
 			localTaskId,
-			DEFAULT_PREV_CONTEXT_TOKENS,
 			true, // isAutomaticTrigger
 			"Custom prompt",
 		)

+ 24 - 10
src/core/condense/index.ts

@@ -131,15 +131,16 @@ export type SummarizeResponse = {
  * - Post-condense, the model sees only the summary (true fresh start)
  * - All messages are still stored but tagged with condenseParent
  * - <command> blocks from the original task are preserved across condensings
+ * - <environment_details> is included to provide current workspace context
  *
  * @param {ApiMessage[]} messages - The conversation messages
  * @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 {ApiHandlerCreateMessageMetadata} metadata - Optional metadata to pass to createMessage (tools, taskId, etc.)
+ * @param {string} environmentDetails - Optional environment details string to include in the summary
  * @returns {SummarizeResponse} - The result of the summarization operation (see above)
  */
 export async function summarizeConversation(
@@ -147,10 +148,10 @@ export async function summarizeConversation(
 	apiHandler: ApiHandler,
 	systemPrompt: string,
 	taskId: string,
-	prevContextTokens: number,
 	isAutomaticTrigger?: boolean,
 	customCondensingPrompt?: string,
 	metadata?: ApiHandlerCreateMessageMetadata,
+	environmentDetails?: string,
 ): Promise<SummarizeResponse> {
 	TelemetryService.instance.captureContextCondensed(
 		taskId,
@@ -293,6 +294,14 @@ ${commandBlocks}
 		})
 	}
 
+	// Add environment details as a separate text block if provided
+	if (environmentDetails?.trim()) {
+		summaryContent.push({
+			type: "text",
+			text: environmentDetails,
+		})
+	}
+
 	// Generate a unique condenseId for this summary
 	const condenseId = crypto.randomUUID()
 
@@ -332,20 +341,25 @@ ${commandBlocks}
 	newMessages.push(summaryMessage)
 
 	// Count the tokens in the context for the next API request
-	// After condense, the context will only contain the system prompt and the summary
+	// After condense, the context will contain: system prompt + summary + tool definitions
 	const systemPromptMessage: ApiMessage = { role: "user", content: systemPrompt }
 
-	const contextMessages = outputTokens ? [systemPromptMessage] : [systemPromptMessage, summaryMessage]
-
-	const contextBlocks = contextMessages.flatMap((message) =>
+	// Count actual summaryMessage content directly instead of using outputTokens as a proxy
+	// This ensures we account for wrapper text (## Conversation Summary, <system-reminder>, <environment_details>)
+	const contextBlocks = [systemPromptMessage, summaryMessage].flatMap((message) =>
 		typeof message.content === "string" ? [{ text: message.content, type: "text" as const }] : message.content,
 	)
 
-	const newContextTokens = outputTokens + (await apiHandler.countTokens(contextBlocks))
-	if (newContextTokens >= prevContextTokens) {
-		const error = t("common:errors.condense_context_grew")
-		return { ...response, cost, error }
+	const messageTokens = await apiHandler.countTokens(contextBlocks)
+
+	// Count tool definition tokens if tools are provided
+	let toolTokens = 0
+	if (metadata?.tools && metadata.tools.length > 0) {
+		const toolsText = JSON.stringify(metadata.tools)
+		toolTokens = await apiHandler.countTokens([{ text: toolsText, type: "text" }])
 	}
+
+	const newContextTokens = messageTokens + toolTokens
 	return { messages: newMessages, summary, cost, newContextTokens, condenseId }
 }
 

+ 4 - 4
src/core/context-management/__tests__/context-management.spec.ts

@@ -617,10 +617,10 @@ describe("Context Management", () => {
 				mockApiHandler,
 				"System prompt",
 				taskId,
-				70001,
-				true,
+				true, // isAutomaticTrigger
 				undefined, // customCondensingPrompt
 				undefined, // metadata
+				undefined, // environmentDetails
 			)
 
 			// Verify the result contains the summary information
@@ -792,10 +792,10 @@ describe("Context Management", () => {
 				mockApiHandler,
 				"System prompt",
 				taskId,
-				60000,
-				true,
+				true, // isAutomaticTrigger
 				undefined, // customCondensingPrompt
 				undefined, // metadata
+				undefined, // environmentDetails
 			)
 
 			// Verify the result contains the summary information

+ 4 - 1
src/core/context-management/index.ts

@@ -220,6 +220,8 @@ export type ContextManagementOptions = {
 	currentProfileId: string
 	/** Optional metadata to pass through to the condensing API call (tools, taskId, etc.) */
 	metadata?: ApiHandlerCreateMessageMetadata
+	/** Optional environment details string to include in the condensed summary */
+	environmentDetails?: string
 }
 
 export type ContextManagementResult = SummarizeResponse & {
@@ -249,6 +251,7 @@ export async function manageContext({
 	profileThresholds,
 	currentProfileId,
 	metadata,
+	environmentDetails,
 }: ContextManagementOptions): Promise<ContextManagementResult> {
 	let error: string | undefined
 	let errorDetails: string | undefined
@@ -299,10 +302,10 @@ export async function manageContext({
 				apiHandler,
 				systemPrompt,
 				taskId,
-				prevContextTokens,
 				true, // automatic trigger
 				customCondensingPrompt,
 				metadata,
+				environmentDetails,
 			)
 			if (result.error) {
 				error = result.error

+ 16 - 1
src/core/task/Task.ts

@@ -1626,6 +1626,9 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
 					}
 				: {}),
 		}
+		// Generate environment details to include in the condensed summary
+		const environmentDetails = await getEnvironmentDetails(this, true)
+
 		const {
 			messages,
 			summary,
@@ -1639,10 +1642,10 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
 			this.api, // Main API handler (fallback)
 			systemPrompt, // Default summarization prompt (fallback)
 			this.taskId,
-			prevContextTokens,
 			false, // manual trigger
 			customCondensingPrompt, // User's custom prompt
 			metadata, // Pass metadata with tools
+			environmentDetails, // Include environment details in summary
 		)
 		if (error) {
 			await this.say(
@@ -3772,6 +3775,9 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
 		}
 
 		try {
+			// Generate environment details to include in the condensed summary
+			const environmentDetails = await getEnvironmentDetails(this, true)
+
 			// Force aggressive truncation by keeping only 75% of the conversation history
 			const truncateResult = await manageContext({
 				messages: this.apiConversationHistory,
@@ -3786,6 +3792,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
 				profileThresholds,
 				currentProfileId,
 				metadata,
+				environmentDetails,
 			})
 
 			if (truncateResult.messages !== this.apiConversationHistory) {
@@ -3985,6 +3992,13 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
 					: {}),
 			}
 
+			// Only generate environment details when context management will actually run.
+			// getEnvironmentDetails(this, true) triggers a recursive workspace listing which
+			// adds overhead - avoid this for the common case where context is below threshold.
+			const contextMgmtEnvironmentDetails = contextManagementWillRun
+				? await getEnvironmentDetails(this, true)
+				: undefined
+
 			try {
 				const truncateResult = await manageContext({
 					messages: this.apiConversationHistory,
@@ -4000,6 +4014,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
 					profileThresholds,
 					currentProfileId,
 					metadata: contextMgmtMetadata,
+					environmentDetails: contextMgmtEnvironmentDetails,
 				})
 				if (truncateResult.messages !== this.apiConversationHistory) {
 					await this.overwriteApiConversationHistory(truncateResult.messages)

+ 0 - 1
src/i18n/locales/ca/common.json

@@ -66,7 +66,6 @@
 		"condense_not_enough_messages": "No hi ha prou missatges per condensar el context",
 		"condensed_recently": "El context s'ha condensat recentment; s'omet aquest intent",
 		"condense_handler_invalid": "El gestor de l'API per condensar el context no és vàlid",
-		"condense_context_grew": "La mida del context ha augmentat durant la condensació; s'omet aquest intent",
 		"condense_api_failed": "La crida a l'API de condensació ha fallat: {{message}}",
 		"url_timeout": "El lloc web ha trigat massa a carregar (timeout). Això pot ser degut a una connexió lenta, un lloc web pesat o temporalment no disponible. Pots tornar-ho a provar més tard o comprovar si la URL és correcta.",
 		"url_not_found": "No s'ha pogut trobar l'adreça del lloc web. Comprova si la URL és correcta i torna-ho a provar.",

+ 0 - 1
src/i18n/locales/de/common.json

@@ -62,7 +62,6 @@
 		"condense_not_enough_messages": "Nicht genügend Nachrichten zum Verdichten des Kontexts",
 		"condensed_recently": "Kontext wurde kürzlich verdichtet; dieser Versuch wird übersprungen",
 		"condense_handler_invalid": "API-Handler zum Verdichten des Kontexts ist ungültig",
-		"condense_context_grew": "Kontextgröße ist während der Verdichtung gewachsen; dieser Versuch wird übersprungen",
 		"condense_api_failed": "Verdichtungs-API-Aufruf fehlgeschlagen: {{message}}",
 		"url_timeout": "Die Website hat zu lange zum Laden gebraucht (Timeout). Das könnte an einer langsamen Verbindung, einer schweren Website oder vorübergehender Nichtverfügbarkeit liegen. Du kannst es später nochmal versuchen oder prüfen, ob die URL korrekt ist.",
 		"url_not_found": "Die Website-Adresse konnte nicht gefunden werden. Bitte prüfe, ob die URL korrekt ist und versuche es erneut.",

+ 0 - 1
src/i18n/locales/en/common.json

@@ -62,7 +62,6 @@
 		"condense_not_enough_messages": "Not enough messages to condense context",
 		"condensed_recently": "Context was condensed recently; skipping this attempt",
 		"condense_handler_invalid": "API handler for condensing context is invalid",
-		"condense_context_grew": "Context size increased during condensing; skipping this attempt",
 		"condense_api_failed": "Condensing API call failed: {{message}}",
 		"url_timeout": "The website took too long to load (timeout). This could be due to a slow connection, heavy website, or the site being temporarily unavailable. You can try again later or check if the URL is correct.",
 		"url_not_found": "The website address could not be found. Please check if the URL is correct and try again.",

+ 0 - 1
src/i18n/locales/es/common.json

@@ -62,7 +62,6 @@
 		"condense_not_enough_messages": "No hay suficientes mensajes para condensar el contexto",
 		"condensed_recently": "El contexto se condensó recientemente; se omite este intento",
 		"condense_handler_invalid": "El manejador de API para condensar el contexto no es válido",
-		"condense_context_grew": "El tamaño del contexto aumentó durante la condensación; se omite este intento",
 		"condense_api_failed": "La llamada API de condensación falló: {{message}}",
 		"url_timeout": "El sitio web tardó demasiado en cargar (timeout). Esto podría deberse a una conexión lenta, un sitio web pesado o que esté temporalmente no disponible. Puedes intentarlo más tarde o verificar si la URL es correcta.",
 		"url_not_found": "No se pudo encontrar la dirección del sitio web. Por favor verifica si la URL es correcta e inténtalo de nuevo.",

+ 0 - 1
src/i18n/locales/fr/common.json

@@ -62,7 +62,6 @@
 		"condense_not_enough_messages": "Pas assez de messages pour condenser le contexte",
 		"condensed_recently": "Le contexte a été condensé récemment ; cette tentative est ignorée",
 		"condense_handler_invalid": "Le gestionnaire d'API pour condenser le contexte est invalide",
-		"condense_context_grew": "La taille du contexte a augmenté pendant la condensation ; cette tentative est ignorée",
 		"condense_api_failed": "L'appel API de condensation a échoué : {{message}}",
 		"url_timeout": "Le site web a pris trop de temps à charger (timeout). Cela pourrait être dû à une connexion lente, un site web lourd ou temporairement indisponible. Tu peux réessayer plus tard ou vérifier si l'URL est correcte.",
 		"url_not_found": "L'adresse du site web n'a pas pu être trouvée. Vérifie si l'URL est correcte et réessaie.",

+ 0 - 1
src/i18n/locales/hi/common.json

@@ -62,7 +62,6 @@
 		"condense_not_enough_messages": "संदर्भ को संक्षिप्त करने के लिए पर्याप्त संदेश नहीं हैं",
 		"condensed_recently": "संदर्भ हाल ही में संक्षिप्त किया गया था; इस प्रयास को छोड़ा जा रहा है",
 		"condense_handler_invalid": "संदर्भ को संक्षिप्त करने के लिए API हैंडलर अमान्य है",
-		"condense_context_grew": "संक्षिप्तीकरण के दौरान संदर्भ का आकार बढ़ गया; इस प्रयास को छोड़ा जा रहा है",
 		"condense_api_failed": "संक्षिप्तीकरण API कॉल विफल: {{message}}",
 		"url_timeout": "वेबसाइट लोड होने में बहुत समय लगा (टाइमआउट)। यह धीमे कनेक्शन, भारी वेबसाइट या अस्थायी रूप से अनुपलब्ध होने के कारण हो सकता है। आप बाद में फिर से कोशिश कर सकते हैं या जांच सकते हैं कि URL सही है या नहीं।",
 		"url_not_found": "वेबसाइट का पता नहीं मिल सका। कृपया जांचें कि URL सही है और फिर से कोशिश करें।",

+ 0 - 1
src/i18n/locales/id/common.json

@@ -62,7 +62,6 @@
 		"condense_not_enough_messages": "Tidak cukup pesan untuk mengompres konteks",
 		"condensed_recently": "Konteks baru saja dikompres; melewati percobaan ini",
 		"condense_handler_invalid": "Handler API untuk mengompres konteks tidak valid",
-		"condense_context_grew": "Ukuran konteks bertambah saat mengompres; melewati percobaan ini",
 		"condense_api_failed": "Panggilan API pengompresan gagal: {{message}}",
 		"url_timeout": "Situs web membutuhkan waktu terlalu lama untuk dimuat (timeout). Ini bisa disebabkan oleh koneksi lambat, situs web berat, atau sementara tidak tersedia. Kamu bisa mencoba lagi nanti atau memeriksa apakah URL sudah benar.",
 		"url_not_found": "Alamat situs web tidak dapat ditemukan. Silakan periksa apakah URL sudah benar dan coba lagi.",

+ 0 - 1
src/i18n/locales/it/common.json

@@ -62,7 +62,6 @@
 		"condense_not_enough_messages": "Non ci sono abbastanza messaggi per condensare il contesto",
 		"condensed_recently": "Il contesto è stato condensato di recente; questo tentativo viene saltato",
 		"condense_handler_invalid": "Il gestore API per condensare il contesto non è valido",
-		"condense_context_grew": "La dimensione del contesto è aumentata durante la condensazione; questo tentativo viene saltato",
 		"condense_api_failed": "Chiamata API di condensazione fallita: {{message}}",
 		"url_timeout": "Il sito web ha impiegato troppo tempo a caricarsi (timeout). Questo potrebbe essere dovuto a una connessione lenta, un sito web pesante o temporaneamente non disponibile. Puoi riprovare più tardi o verificare se l'URL è corretto.",
 		"url_not_found": "L'indirizzo del sito web non è stato trovato. Verifica se l'URL è corretto e riprova.",

+ 0 - 1
src/i18n/locales/ja/common.json

@@ -62,7 +62,6 @@
 		"condense_not_enough_messages": "コンテキストを圧縮するのに十分なメッセージがありません",
 		"condensed_recently": "コンテキストは最近圧縮されました;この試行をスキップします",
 		"condense_handler_invalid": "コンテキストを圧縮するためのAPIハンドラーが無効です",
-		"condense_context_grew": "圧縮中にコンテキストサイズが増加しました;この試行をスキップします",
 		"condense_api_failed": "圧縮API呼び出しが失敗しました:{{message}}",
 		"url_timeout": "ウェブサイトの読み込みがタイムアウトしました。接続が遅い、ウェブサイトが重い、または一時的に利用できない可能性があります。後でもう一度試すか、URLが正しいか確認してください。",
 		"url_not_found": "ウェブサイトのアドレスが見つかりませんでした。URLが正しいか確認してもう一度試してください。",

+ 0 - 1
src/i18n/locales/ko/common.json

@@ -62,7 +62,6 @@
 		"condense_not_enough_messages": "컨텍스트를 압축할 메시지가 충분하지 않습니다",
 		"condensed_recently": "컨텍스트가 최근 압축되었습니다; 이 시도를 건너뜁니다",
 		"condense_handler_invalid": "컨텍스트 압축을 위한 API 핸들러가 유효하지 않습니다",
-		"condense_context_grew": "압축 중 컨텍스트 크기가 증가했습니다; 이 시도를 건너뜁니다",
 		"condense_api_failed": "압축 API 호출 실패: {{message}}",
 		"url_timeout": "웹사이트 로딩이 너무 오래 걸렸습니다(타임아웃). 느린 연결, 무거운 웹사이트 또는 일시적으로 사용할 수 없는 상태일 수 있습니다. 나중에 다시 시도하거나 URL이 올바른지 확인해 주세요.",
 		"url_not_found": "웹사이트 주소를 찾을 수 없습니다. URL이 올바른지 확인하고 다시 시도해 주세요.",

+ 0 - 1
src/i18n/locales/nl/common.json

@@ -62,7 +62,6 @@
 		"condense_not_enough_messages": "Niet genoeg berichten om context te comprimeren",
 		"condensed_recently": "Context is recent gecomprimeerd; deze poging wordt overgeslagen",
 		"condense_handler_invalid": "API-handler voor het comprimeren van context is ongeldig",
-		"condense_context_grew": "Contextgrootte nam toe tijdens comprimeren; deze poging wordt overgeslagen",
 		"condense_api_failed": "Comprimeer API-oproep mislukt: {{message}}",
 		"url_timeout": "De website deed er te lang over om te laden (timeout). Dit kan komen door een trage verbinding, een zware website of tijdelijke onbeschikbaarheid. Je kunt het later opnieuw proberen of controleren of de URL correct is.",
 		"url_not_found": "Het websiteadres kon niet worden gevonden. Controleer of de URL correct is en probeer opnieuw.",

+ 0 - 1
src/i18n/locales/pl/common.json

@@ -62,7 +62,6 @@
 		"condense_not_enough_messages": "Za mało wiadomości do skondensowania kontekstu",
 		"condensed_recently": "Kontekst został niedawno skondensowany; pomijanie tej próby",
 		"condense_handler_invalid": "Nieprawidłowy handler API do kondensowania kontekstu",
-		"condense_context_grew": "Rozmiar kontekstu wzrósł podczas kondensacji; pomijanie tej próby",
 		"condense_api_failed": "Wywołanie API kondensacji nie powiodło się: {{message}}",
 		"url_timeout": "Strona internetowa ładowała się zbyt długo (timeout). Może to być spowodowane wolnym połączeniem, ciężką stroną lub tymczasową niedostępnością. Możesz spróbować ponownie później lub sprawdzić, czy URL jest poprawny.",
 		"url_not_found": "Nie można znaleźć adresu strony internetowej. Sprawdź, czy URL jest poprawny i spróbuj ponownie.",

+ 0 - 1
src/i18n/locales/pt-BR/common.json

@@ -66,7 +66,6 @@
 		"condense_not_enough_messages": "Não há mensagens suficientes para condensar o contexto",
 		"condensed_recently": "O contexto foi condensado recentemente; pulando esta tentativa",
 		"condense_handler_invalid": "O manipulador de API para condensar o contexto é inválido",
-		"condense_context_grew": "O tamanho do contexto aumentou durante a condensação; pulando esta tentativa",
 		"condense_api_failed": "Chamada de API de condensação falhou: {{message}}",
 		"url_timeout": "O site demorou muito para carregar (timeout). Isso pode ser devido a uma conexão lenta, site pesado ou temporariamente indisponível. Você pode tentar novamente mais tarde ou verificar se a URL está correta.",
 		"url_not_found": "O endereço do site não pôde ser encontrado. Verifique se a URL está correta e tente novamente.",

+ 0 - 1
src/i18n/locales/ru/common.json

@@ -62,7 +62,6 @@
 		"condense_not_enough_messages": "Недостаточно сообщений для сжатия контекста",
 		"condensed_recently": "Контекст был недавно сжат; пропускаем эту попытку",
 		"condense_handler_invalid": "Обработчик API для сжатия контекста недействителен",
-		"condense_context_grew": "Размер контекста увеличился во время сжатия; пропускаем эту попытку",
 		"condense_api_failed": "Ошибка вызова API сжатия: {{message}}",
 		"url_timeout": "Веб-сайт слишком долго загружался (таймаут). Это может быть из-за медленного соединения, тяжелого веб-сайта или временной недоступности. Ты можешь попробовать позже или проверить правильность URL.",
 		"url_not_found": "Адрес веб-сайта не найден. Проверь правильность URL и попробуй снова.",

+ 0 - 1
src/i18n/locales/tr/common.json

@@ -62,7 +62,6 @@
 		"condense_not_enough_messages": "Bağlamı sıkıştırmak için yeterli mesaj yok",
 		"condensed_recently": "Bağlam yakın zamanda sıkıştırıldı; bu deneme atlanıyor",
 		"condense_handler_invalid": "Bağlamı sıkıştırmak için API işleyicisi geçersiz",
-		"condense_context_grew": "Sıkıştırma sırasında bağlam boyutu arttı; bu deneme atlanıyor",
 		"condense_api_failed": "Sıkıştırma API çağrısı başarısız oldu: {{message}}",
 		"url_timeout": "Web sitesi yüklenmesi çok uzun sürdü (zaman aşımı). Bu yavaş bağlantı, ağır web sitesi veya geçici olarak kullanılamama nedeniyle olabilir. Daha sonra tekrar deneyebilir veya URL'nin doğru olup olmadığını kontrol edebilirsin.",
 		"url_not_found": "Web sitesi adresi bulunamadı. URL'nin doğru olup olmadığını kontrol et ve tekrar dene.",

+ 0 - 1
src/i18n/locales/vi/common.json

@@ -62,7 +62,6 @@
 		"condense_not_enough_messages": "Không đủ tin nhắn để nén ngữ cảnh",
 		"condensed_recently": "Ngữ cảnh đã được nén gần đây; bỏ qua lần thử này",
 		"condense_handler_invalid": "Trình xử lý API để nén ngữ cảnh không hợp lệ",
-		"condense_context_grew": "Kích thước ngữ cảnh tăng lên trong quá trình nén; bỏ qua lần thử này",
 		"condense_api_failed": "Cuộc gọi API nén thất bại: {{message}}",
 		"url_timeout": "Trang web mất quá nhiều thời gian để tải (timeout). Điều này có thể do kết nối chậm, trang web nặng hoặc tạm thời không khả dụng. Bạn có thể thử lại sau hoặc kiểm tra xem URL có đúng không.",
 		"url_not_found": "Không thể tìm thấy địa chỉ trang web. Vui lòng kiểm tra URL có đúng không và thử lại.",

+ 0 - 1
src/i18n/locales/zh-CN/common.json

@@ -67,7 +67,6 @@
 		"condense_not_enough_messages": "没有足够的对话来压缩上下文",
 		"condensed_recently": "上下文最近已压缩;跳过此次尝试",
 		"condense_handler_invalid": "压缩上下文的API处理程序无效",
-		"condense_context_grew": "压缩过程中上下文大小增加;跳过此次尝试",
 		"condense_api_failed": "压缩 API 调用失败:{{message}}",
 		"url_timeout": "网站加载超时。这可能是由于网络连接缓慢、网站负载过重或暂时不可用。你可以稍后重试或检查 URL 是否正确。",
 		"url_not_found": "找不到网站地址。请检查 URL 是否正确并重试。",

+ 0 - 1
src/i18n/locales/zh-TW/common.json

@@ -62,7 +62,6 @@
 		"condense_not_enough_messages": "沒有足夠的訊息來壓縮上下文",
 		"condensed_recently": "上下文最近已壓縮;跳過此次嘗試",
 		"condense_handler_invalid": "壓縮上下文的 API 處理程式無效",
-		"condense_context_grew": "壓縮過程中上下文大小增加;跳過此次嘗試",
 		"condense_api_failed": "壓縮 API 呼叫失敗:{{message}}",
 		"url_timeout": "網站載入超時。這可能是由於網路連線緩慢、網站負載過重或暫時無法使用。你可以稍後重試或檢查 URL 是否正確。",
 		"url_not_found": "找不到網站位址。請檢查 URL 是否正確並重試。",