Token Optimization — Context Reduction and LLM-Assisted Compression#14
Token Optimization — Context Reduction and LLM-Assisted Compression#14JamesRobert20 wants to merge 3 commits into
Conversation
📝 WalkthroughWalkthroughAdds LLM-assisted tool-result compression (optional, Zoo Code-backed), environment-section diffing to reduce tokens, parallel execution for read-only tools, a completion post-processor, related settings/UI/types, subscription caching, and tests covering compression, environment diffs, tool batching, and prompt-caching behavior. ChangesTool Result Compression System
Environment Details Optimization
Parallel Read-Only Tool Execution
Completion Post-Processing
Zoo Code Settings & UI
Testing & Prompt-Caching
Sequence Diagram(s)sequenceDiagram
participant Tool as Tool (e.g., read_file)
participant CompressAndPush as compressAndPushToolResult
participant Processor as ToolResultProcessor
participant ZooGateway as ZooGatewayApiHandler
participant Zoo as Zoo Code Backend
participant Task as Task (pushToolResult)
Tool->>CompressAndPush: compressAndPushToolResult(toolName, rawResult, context, task, callback)
CompressAndPush->>Processor: shouldCompress(toolName, rawResult, config)
alt Compression Enabled & Subscriber
Processor-->>CompressAndPush: true
CompressAndPush->>Processor: compress(toolName, rawResult, context, config)
Processor->>ZooGateway: createMessage(systemPrompt, [{content: rawResult}], {toolName})
ZooGateway->>Zoo: POST /api/proxy/internal/compress<br/>{systemPrompt, rawResult, toolName}
Zoo-->>ZooGateway: compressed text
ZooGateway-->>Processor: stream [text, usage] chunks
Processor-->>CompressAndPush: trimmed compressed result
CompressAndPush->>Task: pushToolResult(compressedResult)
else Compression Disabled or Non-Subscriber
Processor-->>CompressAndPush: false
CompressAndPush->>Task: pushToolResult(rawResult)
end
Task-->>Tool: result pushed to history
sequenceDiagram
participant Assistant as Assistant Handler
participant Classify as isReadOnlyTool()
participant Lookahead as Lookahead Check
participant Execute as Promise.all
participant Callback as Per-Tool Callbacks
participant Results as Push Results/Telemetry
Assistant->>Classify: Check current tool_use
alt Current is Read-Only & Complete
Assistant->>Lookahead: Scan next blocks for consecutive read-only
Lookahead-->>Assistant: Found 2+ consecutive complete read-only
Assistant->>Callback: Create isolated callbacks per tool
Assistant->>Execute: Promise.all([tool1(callbacks1), tool2(callbacks2), ...])
Execute-->>Results: All tools complete
Results->>Assistant: Advance indexes and record telemetry
else Sequential
Assistant->>Assistant: Execute tool sequentially
end
sequenceDiagram
participant Task as Task (buildRequest)
participant GetEnv as getEnvironmentDetails()
participant Parse as parseEnvironmentSections()
participant Diff as diffEnvironmentDetails()
participant Assemble as assembleEnvironmentDetails()
participant Cache as lastEnvironmentSections (Map)
participant UserMsg as User Message Content
Task->>GetEnv: Fetch current environment details
GetEnv-->>Task: rawEnvironmentDetails
Task->>Parse: parseEnvironmentSections(rawEnvironmentDetails)
Parse-->>Task: currentSections
Task->>Cache: Retrieve lastEnvironmentSections
Task->>Diff: diffEnvironmentDetails(previous, currentSections)
Diff-->>Task: {sections, wasFiltered}
Task->>Assemble: assembleEnvironmentDetails(sections, wasFiltered)
Assemble-->>Task: assembled environment string
Task->>UserMsg: Remove prior environment block and inject filtered details
Task->>Cache: Update lastEnvironmentSections = currentSections
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. 👉 Get your free trial and get 200 agent minutes per Slack user (a $50 value). Review rate limit: 9/10 reviews remaining, refill in 6 minutes. Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 11
🧹 Nitpick comments (4)
src/core/assistant-message/presentAssistantMessage.ts (1)
856-856: 💤 Low valueConsider
Promise.allSettledfor more resilient batch execution.If one tool throws an unexpected exception (not caught by
handleError),Promise.allrejects immediately and remaining tools may not push their results. UsingPromise.allSettledwould ensure all tools complete regardless of individual failures.Proposed change
-await Promise.all(executionPromises) +const results = await Promise.allSettled(executionPromises) +// Log any rejected promises for debugging (tools should handle their own errors) +results.forEach((result, idx) => { + if (result.status === "rejected") { + console.error(`[presentAssistantMessage] Parallel tool ${parallelBatch[idx]?.name} failed unexpectedly:`, result.reason) + } +})🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/core/assistant-message/presentAssistantMessage.ts` at line 856, The batch execution currently uses await Promise.all(executionPromises) which aborts all remaining promises if any throws; replace this with await Promise.allSettled(executionPromises) in presentAssistantMessage.ts, then iterate the settled results and for any result.status === "rejected" call the existing handleError(error, /* context */) or convert the rejection into the same error handling path used for resolved tool results so each tool's outcome is recorded; reference the executionPromises array and the handleError function when making the change and ensure successful results are processed exactly as before.src/core/tools/ToolResultProcessor.ts (1)
146-166: 💤 Low valueNote:
execute_commandreusesreadFileCharsAbovethreshold.The
execute_commandtool uses the same threshold asread_file(thresholds.readFileCharsAbove). This is functional but may be unclear to users configuring thresholds. Consider documenting this behavior or adding an explicitexecuteCommandCharsAbovethreshold if different tuning is desired.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/core/tools/ToolResultProcessor.ts` around lines 146 - 166, The _exceedsThreshold method currently reuses thresholds.readFileCharsAbove for "execute_command", which is confusing; change the logic in ToolResultProcessor._exceedsThreshold to use a dedicated thresholds.executeCommandCharsAbove value (falling back to thresholds.readFileCharsAbove if executeCommandCharsAbove is undefined) and update the ToolResultProcessorConfig interface to add the optional executeCommandCharsAbove property so callers can tune execute_command separately while preserving legacy behavior.src/core/tools/resolveCompressionHandler.ts (2)
38-42: 💤 Low valueConsider differentiating transient vs permanent HTTP errors.
The code caches all non-OK responses as non-subscriber for 1 hour, including transient server errors (500, 503). If the Zoo Code API has a brief outage, subscribers won't get compression for an hour after recovering.
Consider only caching client errors (4xx) and retrying on server errors (5xx):
♻️ Optional: Skip caching for server errors
if (!response.ok) { - // 401 = invalid key, 403 = free plan — cache as non-subscriber - subscriptionCache.set(key, { isSubscriber: false, expiresAt: Date.now() + CACHE_TTL_MS }) + // Only cache client errors (4xx) — server errors (5xx) may be transient + if (response.status >= 400 && response.status < 500) { + subscriptionCache.set(key, { isSubscriber: false, expiresAt: Date.now() + CACHE_TTL_MS }) + } return null }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/core/tools/resolveCompressionHandler.ts` around lines 38 - 42, The current logic treats any non-OK response as a permanent non-subscriber and caches it (subscriptionCache.set), which incorrectly penalizes transient server errors; update the error handling in resolveCompressionHandler (the block that checks response.ok, uses subscriptionCache.set(key, { isSubscriber: false, expiresAt: Date.now() + CACHE_TTL_MS })) so that only 4xx client errors are cached as non-subscriber, while 5xx server errors are treated as transient (do not cache; optionally implement a short retry or simply return null without setting the cache). Ensure you still handle 401/403 the same way but skip setting subscriptionCache for responses with status >=500 and <600.
26-29: 💤 Low valueMinor: Cache hit creates new handler instance each time.
On cache hit, a new
ZooGatewayApiHandleris instantiated. This is fine for correctness (the handler is stateless), but if this function is called frequently, you could cache the handler instance itself rather than just the subscription status.This is a low-priority optimization since Task initialization typically calls this once per task.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/core/tools/resolveCompressionHandler.ts` around lines 26 - 29, The cache currently stores only subscription status and instantiates a new ZooGatewayApiHandler on every cache hit; change the cache entry shape to store the handler instance itself (e.g., { handler?: ZooGatewayApiHandler | null, expiresAt }) so that resolveCompressionHandler reuses the same ZooGatewayApiHandler for a valid cached subscription. Specifically, update logic around subscriptionCache.get(key) and where you set the cache so that when a subscription is active you create a single new ZooGatewayApiHandler(key, baseUrl) once, store it on the cache entry, and return the cached.handler on subsequent hits; keep the expiresAt check and return null when the cached handler is absent or expired. Ensure you update any code that writes subscriptionCache to populate the handler field instead of only a boolean isSubscriber.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/types/src/global-settings.ts`:
- Around line 240-251: The schema for toolResultProcessorSettings currently
makes the nested fields required when the object exists, causing validation
failures for partial/older persisted settings; change the Zod definition for
toolResultProcessorSettings to allow partial objects (e.g., use
z.object({...}).partial().optional() or mark each nested property as
.optional()) so each nested field can be omitted and Task.ts's merge/fallback
logic can apply defaults correctly; update the symbol
toolResultProcessorSettings in packages/types/src/global-settings.ts accordingly
while leaving Task.ts merge logic untouched.
In `@src/api/providers/zoo-gateway.ts`:
- Around line 56-58: The code assigns response.json().compressed directly to
compressed, which can be non-string and then sent into the "text" chunk; update
the handling in the function that processes the gateway response (the block that
sets compressed and rawResult) to validate that data.compressed is actually a
string before replacing rawResult — e.g., after awaiting response.json() check
typeof data?.compressed === "string" (or Buffer/Uint8Array if binary is
expected) and only set compressed = data.compressed in that case, otherwise
leave compressed = rawResult; keep the existing fallback logic and ensure you
reference the same local variables compressed and rawResult used in the
surrounding function.
In `@src/core/assistant-message/presentAssistantMessage.ts`:
- Around line 692-707: The lookahead loop that pushes nextBlock into
parallelBatch bypasses validateToolUse() and the prior tool-repetition checks;
change the loop to run the same validation and repetition-detection logic used
earlier (call validateToolUse(nextBlock) and apply the same repetition matching
used around the tool repetition detection block) before pushing to
parallelBatch, and only push when both checks pass; use the same identifiers
(lookAheadIdx, cline.assistantMessageContent, isReadOnlyTool, validateToolUse,
and parallelBatch) so the lookahead path enforces the same validation and
repetition rules as the first tool.
In `@src/core/environment/environmentDiff.ts`:
- Around line 24-40: The parser loop in assembleEnvironmentDetails currently
treats any non-empty trimmed block as a section header; change the logic in the
loop that iterates "for (const part of parts)" to first check whether the
trimmed block actually starts with "# " and skip it if not (i.e., continue) so
preamble/notice lines aren't mis-parsed as headers; update both the
newlineIdx/header extraction branches (the branches that call
sections.set(header, ...)) to only run when trimmed.startsWith("# ") is true.
In `@src/core/task/Task.ts`:
- Around line 2689-2696: The cache lastEnvironmentSections can become stale
after wholesale replacement of apiConversationHistory, causing
diffEnvironmentDetails() to omit sections that no longer exist in model-visible
history; update overwriteApiConversationHistory (and any other methods that
replace apiConversationHistory such as condense/truncate flows) to reset
lastEnvironmentSections to null after assigning apiConversationHistory and
before saving (e.g., set this.lastEnvironmentSections = null in
overwriteApiConversationHistory and any similar replacer methods like those that
call saveApiConversationHistory) so diffs will be recalculated against a cleared
cache.
In `@src/core/tools/AttemptCompletionTool.ts`:
- Around line 83-85: The attempt_completion flow makes displayResult depend on
task.completionPostProcessor.postProcess and will throw if postProcess errors;
change AttemptCompletionTool so postProcess is best-effort: call
task.completionPostProcessor.postProcess(result) inside a try/catch (referencing
task.completionPostProcessor, postProcess, displayResult, and result), on
exception log or swallow the error and set displayResult = result to ensure the
tool falls back to the raw result instead of failing the entire attempt.
In `@src/core/tools/CompletionPostProcessor.ts`:
- Line 37: The secondary post-processing call uses
this.apiHandler.createMessage(systemPrompt, messages as any) and currently sends
default metadata that may be stored; update the call to include an
options/metadata object with store: false (e.g., createMessage(..., { store:
false })) so the provider is instructed not to persist this display-only
completion; modify the call site in CompletionPostProcessor (the const stream =
this.apiHandler.createMessage(...) line) to pass the store: false flag in the
appropriate options/metadata parameter.
- Around line 38-44: The loop over the streaming response in
CompletionPostProcessor.ts currently only accumulates "text" chunks and then
returns output.trim() || resultText, which can produce a truncated rewrite if an
"error" chunk is emitted; modify the for-await loop that iterates over stream
(variable names: stream, chunk, output, resultText) to treat any chunk with
chunk.type === "error" as a hard fallback by immediately returning resultText
(or otherwise short-circuiting to the fallback) instead of continuing to
accumulate partial text.
In `@src/core/tools/ToolResultProcessorConfig.ts`:
- Around line 13-20: The thresholds config is missing a setting for
execute_command; add a new numeric property (e.g.,
executeCommandOutputCharsAbove or executeCommandCharsAbove) to the thresholds
object alongside readFileCharsAbove, searchMatchesAbove, and listFilesCountAbove
so execute_command output can be tuned; update the same thresholds shape where
it’s declared/validated (the thresholds object and any related interfaces or
defaults referenced near the existing
readFileCharsAbove/searchMatchesAbove/listFilesCountAbove definitions) to
include this new key and ensure consumers that compress execute_command results
read the new setting.
In `@webview-ui/src/components/settings/SettingsView.tsx`:
- Around line 938-952: The new Zoo subscription UI contains hardcoded
strings—"Zoo Code Subscription", the label "API Key", and the copy "Get your API
key at"—inside the SettingsView JSX (look for SectionHeader, the label element
and the paragraph that wraps the anchor, and the VSCodeTextField using
(cachedState as any).zooCodeApiKey and setZooCodeApiKey). Replace these literals
with calls to your i18n/translation helper (e.g., t('...') or translate('...'))
and add corresponding translation keys for each string in the locale files so
the UI text is localized.
---
Nitpick comments:
In `@src/core/assistant-message/presentAssistantMessage.ts`:
- Line 856: The batch execution currently uses await
Promise.all(executionPromises) which aborts all remaining promises if any
throws; replace this with await Promise.allSettled(executionPromises) in
presentAssistantMessage.ts, then iterate the settled results and for any
result.status === "rejected" call the existing handleError(error, /* context */)
or convert the rejection into the same error handling path used for resolved
tool results so each tool's outcome is recorded; reference the executionPromises
array and the handleError function when making the change and ensure successful
results are processed exactly as before.
In `@src/core/tools/resolveCompressionHandler.ts`:
- Around line 38-42: The current logic treats any non-OK response as a permanent
non-subscriber and caches it (subscriptionCache.set), which incorrectly
penalizes transient server errors; update the error handling in
resolveCompressionHandler (the block that checks response.ok, uses
subscriptionCache.set(key, { isSubscriber: false, expiresAt: Date.now() +
CACHE_TTL_MS })) so that only 4xx client errors are cached as non-subscriber,
while 5xx server errors are treated as transient (do not cache; optionally
implement a short retry or simply return null without setting the cache). Ensure
you still handle 401/403 the same way but skip setting subscriptionCache for
responses with status >=500 and <600.
- Around line 26-29: The cache currently stores only subscription status and
instantiates a new ZooGatewayApiHandler on every cache hit; change the cache
entry shape to store the handler instance itself (e.g., { handler?:
ZooGatewayApiHandler | null, expiresAt }) so that resolveCompressionHandler
reuses the same ZooGatewayApiHandler for a valid cached subscription.
Specifically, update logic around subscriptionCache.get(key) and where you set
the cache so that when a subscription is active you create a single new
ZooGatewayApiHandler(key, baseUrl) once, store it on the cache entry, and return
the cached.handler on subsequent hits; keep the expiresAt check and return null
when the cached handler is absent or expired. Ensure you update any code that
writes subscriptionCache to populate the handler field instead of only a boolean
isSubscriber.
In `@src/core/tools/ToolResultProcessor.ts`:
- Around line 146-166: The _exceedsThreshold method currently reuses
thresholds.readFileCharsAbove for "execute_command", which is confusing; change
the logic in ToolResultProcessor._exceedsThreshold to use a dedicated
thresholds.executeCommandCharsAbove value (falling back to
thresholds.readFileCharsAbove if executeCommandCharsAbove is undefined) and
update the ToolResultProcessorConfig interface to add the optional
executeCommandCharsAbove property so callers can tune execute_command separately
while preserving legacy behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: ef42492b-cd3f-4df2-956a-ce78ca953071
📒 Files selected for processing (30)
packages/types/src/global-settings.tssrc/api/index.tssrc/api/providers/__tests__/prompt-caching.spec.tssrc/api/providers/zoo-gateway.tssrc/core/assistant-message/presentAssistantMessage.tssrc/core/context-management/__tests__/compressToolResults.spec.tssrc/core/context-management/compressToolResults.tssrc/core/environment/__tests__/environmentDiff.spec.tssrc/core/environment/environmentDiff.tssrc/core/task/Task.tssrc/core/tools/AttemptCompletionTool.tssrc/core/tools/CodebaseSearchTool.tssrc/core/tools/CompletionPostProcessor.tssrc/core/tools/ExecuteCommandTool.tssrc/core/tools/ListFilesTool.tssrc/core/tools/ReadFileTool.tssrc/core/tools/SearchFilesTool.tssrc/core/tools/ToolResultProcessor.tssrc/core/tools/ToolResultProcessorConfig.tssrc/core/tools/__tests__/CompletionPostProcessor.spec.tssrc/core/tools/__tests__/ToolResultProcessor.spec.tssrc/core/tools/__tests__/compressAndPush.spec.tssrc/core/tools/__tests__/resolveCompressionHandler.spec.tssrc/core/tools/__tests__/toolCategories.spec.tssrc/core/tools/compressAndPush.tssrc/core/tools/resolveCompressionHandler.tssrc/core/tools/toolCategories.tssrc/core/webview/webviewMessageHandler.tssrc/package.jsonwebview-ui/src/components/settings/SettingsView.tsx
| while (lookAheadIdx < cline.assistantMessageContent.length) { | ||
| const nextBlock = cline.assistantMessageContent[lookAheadIdx] | ||
| if ( | ||
| nextBlock && | ||
| nextBlock.type === "tool_use" && | ||
| !(nextBlock as any).partial && | ||
| isReadOnlyTool((nextBlock as any).name) && | ||
| (nextBlock as any).id && | ||
| (nextBlock as any).nativeArgs | ||
| ) { | ||
| parallelBatch.push({ ...(nextBlock as any) }) | ||
| lookAheadIdx++ | ||
| } else { | ||
| break | ||
| } | ||
| } |
There was a problem hiding this comment.
Lookahead tools bypass validation and repetition checks.
Tools collected via lookahead (lines 692-707) skip the validateToolUse() check (lines 578-625) and the tool repetition detection (lines 628-677) that the first tool undergoes. If a read-only tool is disabled for the current mode or matches a repetition pattern, it would still be executed in the batch.
Consider validating each lookahead tool before adding it to the batch:
Proposed validation in lookahead
while (lookAheadIdx < cline.assistantMessageContent.length) {
const nextBlock = cline.assistantMessageContent[lookAheadIdx]
if (
nextBlock &&
nextBlock.type === "tool_use" &&
!(nextBlock as any).partial &&
isReadOnlyTool((nextBlock as any).name) &&
(nextBlock as any).id &&
(nextBlock as any).nativeArgs
) {
+ // Check if tool is disabled for current mode
+ const nextToolName = (nextBlock as any).name
+ if (disabledTools?.includes(nextToolName)) {
+ break // Stop batching; let sequential path handle the disabled tool
+ }
parallelBatch.push({ ...(nextBlock as any) })
lookAheadIdx++
} else {
break
}
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/core/assistant-message/presentAssistantMessage.ts` around lines 692 -
707, The lookahead loop that pushes nextBlock into parallelBatch bypasses
validateToolUse() and the prior tool-repetition checks; change the loop to run
the same validation and repetition-detection logic used earlier (call
validateToolUse(nextBlock) and apply the same repetition matching used around
the tool repetition detection block) before pushing to parallelBatch, and only
push when both checks pass; use the same identifiers (lookAheadIdx,
cline.assistantMessageContent, isReadOnlyTool, validateToolUse, and
parallelBatch) so the lookahead path enforces the same validation and repetition
rules as the first tool.
| for (const part of parts) { | ||
| const trimmed = part.trim() | ||
| if (!trimmed) { | ||
| continue | ||
| } | ||
|
|
||
| // First line is the header, the rest is content. | ||
| const newlineIdx = trimmed.indexOf("\n") | ||
| if (newlineIdx === -1) { | ||
| // Header with no body. | ||
| const header = trimmed.replace(/^# /, "").trim() | ||
| sections.set(header, "") | ||
| } else { | ||
| const header = trimmed.slice(0, newlineIdx).replace(/^# /, "").trim() | ||
| const content = trimmed.slice(newlineIdx + 1) | ||
| sections.set(header, content) | ||
| } |
There was a problem hiding this comment.
Skip non-section preamble blocks during parsing.
assembleEnvironmentDetails may prepend a notice line when filtered; current parser can incorrectly treat that notice as a section header. Guard for # at block start before parsing.
🧩 Suggested patch
for (const part of parts) {
const trimmed = part.trim()
if (!trimmed) {
continue
}
+ if (!trimmed.startsWith("# ")) {
+ continue
+ }
// First line is the header, the rest is content.
const newlineIdx = trimmed.indexOf("\n")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| for (const part of parts) { | |
| const trimmed = part.trim() | |
| if (!trimmed) { | |
| continue | |
| } | |
| // First line is the header, the rest is content. | |
| const newlineIdx = trimmed.indexOf("\n") | |
| if (newlineIdx === -1) { | |
| // Header with no body. | |
| const header = trimmed.replace(/^# /, "").trim() | |
| sections.set(header, "") | |
| } else { | |
| const header = trimmed.slice(0, newlineIdx).replace(/^# /, "").trim() | |
| const content = trimmed.slice(newlineIdx + 1) | |
| sections.set(header, content) | |
| } | |
| for (const part of parts) { | |
| const trimmed = part.trim() | |
| if (!trimmed) { | |
| continue | |
| } | |
| if (!trimmed.startsWith("# ")) { | |
| continue | |
| } | |
| // First line is the header, the rest is content. | |
| const newlineIdx = trimmed.indexOf("\n") | |
| if (newlineIdx === -1) { | |
| // Header with no body. | |
| const header = trimmed.replace(/^# /, "").trim() | |
| sections.set(header, "") | |
| } else { | |
| const header = trimmed.slice(0, newlineIdx).replace(/^# /, "").trim() | |
| const content = trimmed.slice(newlineIdx + 1) | |
| sections.set(header, content) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/core/environment/environmentDiff.ts` around lines 24 - 40, The parser
loop in assembleEnvironmentDetails currently treats any non-empty trimmed block
as a section header; change the logic in the loop that iterates "for (const part
of parts)" to first check whether the trimmed block actually starts with "# "
and skip it if not (i.e., continue) so preamble/notice lines aren't mis-parsed
as headers; update both the newlineIdx/header extraction branches (the branches
that call sections.set(header, ...)) to only run when trimmed.startsWith("# ")
is true.
| // Resolve compression handler asynchronously (checks subscription via Zoo Code API) | ||
| const zooCodeApiKey = provider.contextProxy?.getSecret("zooCodeApiKey") as string | undefined | ||
| const zooCodeBaseUrl = (provider.getValue?.("zooCodeBaseUrl") as string | undefined) ?? "https://zoocode.dev" | ||
|
|
||
| resolveCompressionHandler(zooCodeApiKey, zooCodeBaseUrl) | ||
| .then((handler) => { | ||
| this.toolResultProcessor = new ToolResultProcessor(handler) | ||
| this.completionPostProcessor = new CompletionPostProcessor(handler) | ||
| if (handler) { | ||
| this.toolResultProcessorConfig = { ...this.toolResultProcessorConfig, isSubscriber: true } | ||
| } | ||
| }) | ||
| .catch(() => { | ||
| // Keep null processors on error — graceful degradation | ||
| }) |
There was a problem hiding this comment.
Refresh compression handlers when Zoo credentials change.
This is resolved once in the constructor, then both processors capture that handler permanently. If the user adds, rotates, or removes zooCodeApiKey while a task is active, the task keeps using the old handler or null until a new task is created, even though the subscription cache was cleared.
You likely want to re-resolve on relevant settings/secret changes, or make the processor fetch the current handler lazily instead of storing it once.
| const displayResult = task.completionPostProcessor?.isAvailable | ||
| ? await task.completionPostProcessor.postProcess(result) | ||
| : result |
There was a problem hiding this comment.
Fail open when completion display post-processing errors.
Line 83 currently makes attempt_completion depend on optional post-processing success. If postProcess() throws, the tool fails even though result is valid. Keep post-processing best-effort and fall back to raw result.
Suggested fix
- const displayResult = task.completionPostProcessor?.isAvailable
- ? await task.completionPostProcessor.postProcess(result)
- : result
+ let displayResult = result
+ if (task.completionPostProcessor?.isAvailable) {
+ try {
+ displayResult = await task.completionPostProcessor.postProcess(result)
+ } catch (error) {
+ console.warn("[AttemptCompletionTool] completion post-processing failed; using raw result", error)
+ }
+ }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/core/tools/AttemptCompletionTool.ts` around lines 83 - 85, The
attempt_completion flow makes displayResult depend on
task.completionPostProcessor.postProcess and will throw if postProcess errors;
change AttemptCompletionTool so postProcess is best-effort: call
task.completionPostProcessor.postProcess(result) inside a try/catch (referencing
task.completionPostProcessor, postProcess, displayResult, and result), on
exception log or swallow the error and set displayResult = result to ensure the
tool falls back to the raw result instead of failing the entire attempt.
| const messages = [{ role: "user" as const, content: [{ type: "text" as const, text: resultText }] }] | ||
|
|
||
| let output = "" | ||
| const stream = this.apiHandler.createMessage(systemPrompt, messages as any) |
There was a problem hiding this comment.
Disable provider-side response storage for display-only post-processing.
This secondary formatting call can include sensitive completion content and currently uses default metadata. Pass store: false to reduce retention/compliance risk.
🔒 Suggested patch
- const stream = this.apiHandler.createMessage(systemPrompt, messages as any)
+ const stream = this.apiHandler.createMessage(systemPrompt, messages as any, { store: false })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/core/tools/CompletionPostProcessor.ts` at line 37, The secondary
post-processing call uses this.apiHandler.createMessage(systemPrompt, messages
as any) and currently sends default metadata that may be stored; update the call
to include an options/metadata object with store: false (e.g.,
createMessage(..., { store: false })) so the provider is instructed not to
persist this display-only completion; modify the call site in
CompletionPostProcessor (the const stream = this.apiHandler.createMessage(...)
line) to pass the store: false flag in the appropriate options/metadata
parameter.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 9
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@webview-ui/src/i18n/locales/es/settings.json`:
- Around line 1011-1014: The Spanish locale has untranslated Zoo subscription
strings: update the "zooCodeSubscription" object values—replace "sectionTitle":
"Zoo Code Subscription", "apiKeyLabel": "API Key", and the "apiKeyDescription"
English fragment with proper Spanish translations (e.g., "Suscripción a Zoo
Code", "Clave API", and a full Spanish sentence for the description) so the UI
is fully localized; ensure you modify the keys inside the existing
zooCodeSubscription object in settings.json without changing the key names.
In `@webview-ui/src/i18n/locales/fr/settings.json`:
- Around line 1011-1014: The JSON block for the "zooCodeSubscription" locale
keys is still in English; update the values for the keys
"zooCodeSubscription.sectionTitle", "zooCodeSubscription.apiKeyLabel", and
"zooCodeSubscription.apiKeyDescription" with proper French translations (e.g.,
"Abonnement Zoo Code" for sectionTitle, "Clé API" for apiKeyLabel, and an
appropriate French phrase for apiKeyDescription such as "Obtenez votre clé API
sur") while keeping the JSON keys unchanged and preserving surrounding
punctuation/spacing.
In `@webview-ui/src/i18n/locales/hi/settings.json`:
- Around line 1011-1014: The keys inside the "zooCodeSubscription" object
("sectionTitle", "apiKeyLabel", "apiKeyDescription") are still in English;
replace them with Hindi equivalents to keep localization consistent—e.g., change
"Zoo Code Subscription" -> "ज़ू कोड सदस्यता" (sectionTitle), "API Key" -> "API
कुंजी" (apiKeyLabel), and "अपनी API Key यहाँ प्राप्त करें" should be fully Hindi
like "अपनी API कुंजी यहाँ प्राप्त करें" (apiKeyDescription); update the string
values for these three keys accordingly.
In `@webview-ui/src/i18n/locales/it/settings.json`:
- Around line 1011-1014: The Italian locale has English strings in the
"zooCodeSubscription" object—translate "sectionTitle", "apiKeyLabel" and
"apiKeyDescription" into Italian to keep the settings UI consistent; update the
values for the keys "zooCodeSubscription.sectionTitle",
"zooCodeSubscription.apiKeyLabel" and "zooCodeSubscription.apiKeyDescription"
with appropriate Italian text (e.g., localized equivalents for "Zoo Code
Subscription", "API Key", and "Get your API Key at") while preserving the JSON
structure and punctuation.
In `@webview-ui/src/i18n/locales/ja/settings.json`:
- Around line 1011-1014: Localize the zooCodeSubscription object by translating
the three keys: "sectionTitle", "apiKeyLabel", and "apiKeyDescription" into
Japanese; update the values under the zooCodeSubscription block so
"sectionTitle" becomes a Japanese title for the subscription section,
"apiKeyLabel" becomes the Japanese label for API Key, and "apiKeyDescription"
becomes a natural Japanese sentence indicating where to obtain the API key
(replacing the current English text).
In `@webview-ui/src/i18n/locales/nl/settings.json`:
- Around line 1011-1014: The Dutch locale uses English text for the subscription
settings; update the "zooCodeSubscription" object keys ("sectionTitle",
"apiKeyLabel", "apiKeyDescription") in
webview-ui/src/i18n/locales/nl/settings.json to Dutch translations so the
settings page is fully localized—replace "Zoo Code Subscription" with a Dutch
section title, "API Key" with the Dutch label, and complete the
"apiKeyDescription" sentence in Dutch (including any punctuation) to match the
rest of the nl locale.
In `@webview-ui/src/i18n/locales/pl/settings.json`:
- Around line 1011-1014: The Polish locale contains untranslated English strings
under the zooCodeSubscription object; replace the values for "sectionTitle",
"apiKeyLabel", and "apiKeyDescription" in the "zooCodeSubscription" entry with
proper Polish translations so the settings file is fully localized (update the
"zooCodeSubscription" -> "sectionTitle", "apiKeyLabel", and "apiKeyDescription"
values).
In `@webview-ui/src/i18n/locales/pt-BR/settings.json`:
- Around line 1011-1014: The three strings under the "zooCodeSubscription"
object are still in English; update the values for "sectionTitle",
"apiKeyLabel", and "apiKeyDescription" to Portuguese so the pt-BR locale is
consistent (e.g., "sectionTitle": "Assinatura do Zoo Code", "apiKeyLabel":
"Chave de API", and "apiKeyDescription": "Obtenha sua Chave de API em"). Ensure
you only change the values for the keys "zooCodeSubscription.sectionTitle",
"zooCodeSubscription.apiKeyLabel", and "zooCodeSubscription.apiKeyDescription"
and preserve the existing JSON structure and punctuation.
In `@webview-ui/src/i18n/locales/ru/settings.json`:
- Around line 1011-1014: The keys under "zooCodeSubscription" ("sectionTitle",
"apiKeyLabel", "apiKeyDescription") are still in English; replace their values
with Russian translations so the settings UI is fully localized — update
"sectionTitle" to a Russian equivalent for "Zoo Code Subscription",
"apiKeyLabel" to "API ключ" (or similar), and "apiKeyDescription" to a Russian
phrase that completes "Получите свой API Key на" (e.g., "Получите свой API‑ключ
на <site>"), preserving existing punctuation and context/placeholder structure.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 78d40aff-dee1-4d89-aa15-a32f62e9bdff
📒 Files selected for processing (26)
packages/types/src/global-settings.tssrc/api/providers/zoo-gateway.tssrc/core/task/Task.tssrc/core/tools/CompletionPostProcessor.tssrc/core/tools/ToolResultProcessor.tssrc/core/tools/ToolResultProcessorConfig.tssrc/core/tools/__tests__/ToolResultProcessor.spec.tswebview-ui/src/components/settings/SettingsView.tsxwebview-ui/src/i18n/locales/ca/settings.jsonwebview-ui/src/i18n/locales/de/settings.jsonwebview-ui/src/i18n/locales/en/settings.jsonwebview-ui/src/i18n/locales/es/settings.jsonwebview-ui/src/i18n/locales/fr/settings.jsonwebview-ui/src/i18n/locales/hi/settings.jsonwebview-ui/src/i18n/locales/id/settings.jsonwebview-ui/src/i18n/locales/it/settings.jsonwebview-ui/src/i18n/locales/ja/settings.jsonwebview-ui/src/i18n/locales/ko/settings.jsonwebview-ui/src/i18n/locales/nl/settings.jsonwebview-ui/src/i18n/locales/pl/settings.jsonwebview-ui/src/i18n/locales/pt-BR/settings.jsonwebview-ui/src/i18n/locales/ru/settings.jsonwebview-ui/src/i18n/locales/tr/settings.jsonwebview-ui/src/i18n/locales/vi/settings.jsonwebview-ui/src/i18n/locales/zh-CN/settings.jsonwebview-ui/src/i18n/locales/zh-TW/settings.json
✅ Files skipped from review due to trivial changes (11)
- webview-ui/src/i18n/locales/de/settings.json
- src/core/tools/tests/ToolResultProcessor.spec.ts
- src/core/tools/CompletionPostProcessor.ts
- webview-ui/src/i18n/locales/en/settings.json
- webview-ui/src/i18n/locales/zh-CN/settings.json
- webview-ui/src/i18n/locales/zh-TW/settings.json
- webview-ui/src/i18n/locales/vi/settings.json
- webview-ui/src/i18n/locales/tr/settings.json
- webview-ui/src/i18n/locales/ca/settings.json
- webview-ui/src/i18n/locales/ko/settings.json
- webview-ui/src/i18n/locales/id/settings.json
🚧 Files skipped from review as they are similar to previous changes (4)
- src/core/tools/ToolResultProcessorConfig.ts
- src/api/providers/zoo-gateway.ts
- src/core/tools/ToolResultProcessor.ts
- src/core/task/Task.ts
| "zooCodeSubscription": { | ||
| "sectionTitle": "Zoo Code Subscription", | ||
| "apiKeyLabel": "API Key", | ||
| "apiKeyDescription": "Obtén tu API Key en" |
There was a problem hiding this comment.
Localize new Zoo subscription labels in Spanish.
Line 1012 and Line 1013 are still English, which causes mixed-language UI in this locale.
💡 Suggested update
"zooCodeSubscription": {
- "sectionTitle": "Zoo Code Subscription",
- "apiKeyLabel": "API Key",
- "apiKeyDescription": "Obtén tu API Key en"
+ "sectionTitle": "Suscripción de Zoo Code",
+ "apiKeyLabel": "Clave API",
+ "apiKeyDescription": "Obtén tu clave API en"
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "zooCodeSubscription": { | |
| "sectionTitle": "Zoo Code Subscription", | |
| "apiKeyLabel": "API Key", | |
| "apiKeyDescription": "Obtén tu API Key en" | |
| "zooCodeSubscription": { | |
| "sectionTitle": "Suscripción de Zoo Code", | |
| "apiKeyLabel": "Clave API", | |
| "apiKeyDescription": "Obtén tu clave API en" | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@webview-ui/src/i18n/locales/es/settings.json` around lines 1011 - 1014, The
Spanish locale has untranslated Zoo subscription strings: update the
"zooCodeSubscription" object values—replace "sectionTitle": "Zoo Code
Subscription", "apiKeyLabel": "API Key", and the "apiKeyDescription" English
fragment with proper Spanish translations (e.g., "Suscripción a Zoo Code",
"Clave API", and a full Spanish sentence for the description) so the UI is fully
localized; ensure you modify the keys inside the existing zooCodeSubscription
object in settings.json without changing the key names.
| "zooCodeSubscription": { | ||
| "sectionTitle": "Zoo Code Subscription", | ||
| "apiKeyLabel": "API Key", | ||
| "apiKeyDescription": "Obtenez votre API Key sur" |
There was a problem hiding this comment.
Translate the new subscription copy.
sectionTitle, apiKeyLabel, and apiKeyDescription are still English here, so the French settings page will show mixed-language UI. Please localize this block.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@webview-ui/src/i18n/locales/fr/settings.json` around lines 1011 - 1014, The
JSON block for the "zooCodeSubscription" locale keys is still in English; update
the values for the keys "zooCodeSubscription.sectionTitle",
"zooCodeSubscription.apiKeyLabel", and "zooCodeSubscription.apiKeyDescription"
with proper French translations (e.g., "Abonnement Zoo Code" for sectionTitle,
"Clé API" for apiKeyLabel, and an appropriate French phrase for
apiKeyDescription such as "Obtenez votre clé API sur") while keeping the JSON
keys unchanged and preserving surrounding punctuation/spacing.
| "zooCodeSubscription": { | ||
| "sectionTitle": "Zoo Code Subscription", | ||
| "apiKeyLabel": "API Key", | ||
| "apiKeyDescription": "अपनी API Key यहाँ प्राप्त करें" |
There was a problem hiding this comment.
Use Hindi labels for the new subscription section.
Line 1012 and Line 1013 are English, which breaks localization consistency for Hindi users.
💡 Suggested update
"zooCodeSubscription": {
- "sectionTitle": "Zoo Code Subscription",
- "apiKeyLabel": "API Key",
- "apiKeyDescription": "अपनी API Key यहाँ प्राप्त करें"
+ "sectionTitle": "Zoo Code सदस्यता",
+ "apiKeyLabel": "API कुंजी",
+ "apiKeyDescription": "अपनी API कुंजी यहाँ प्राप्त करें"
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "zooCodeSubscription": { | |
| "sectionTitle": "Zoo Code Subscription", | |
| "apiKeyLabel": "API Key", | |
| "apiKeyDescription": "अपनी API Key यहाँ प्राप्त करें" | |
| "zooCodeSubscription": { | |
| "sectionTitle": "Zoo Code सदस्यता", | |
| "apiKeyLabel": "API कुंजी", | |
| "apiKeyDescription": "अपनी API कुंजी यहाँ प्राप्त करें" | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@webview-ui/src/i18n/locales/hi/settings.json` around lines 1011 - 1014, The
keys inside the "zooCodeSubscription" object ("sectionTitle", "apiKeyLabel",
"apiKeyDescription") are still in English; replace them with Hindi equivalents
to keep localization consistent—e.g., change "Zoo Code Subscription" -> "ज़ू कोड
सदस्यता" (sectionTitle), "API Key" -> "API कुंजी" (apiKeyLabel), and "अपनी API
Key यहाँ प्राप्त करें" should be fully Hindi like "अपनी API कुंजी यहाँ प्राप्त
करें" (apiKeyDescription); update the string values for these three keys
accordingly.
| "zooCodeSubscription": { | ||
| "sectionTitle": "Zoo Code Subscription", | ||
| "apiKeyLabel": "API Key", | ||
| "apiKeyDescription": "Ottieni la tua API Key su" |
There was a problem hiding this comment.
Translate subscription key labels for Italian locale.
Line 1012 and Line 1013 are currently English; this introduces inconsistent language in the settings UI.
💡 Suggested update
"zooCodeSubscription": {
- "sectionTitle": "Zoo Code Subscription",
- "apiKeyLabel": "API Key",
- "apiKeyDescription": "Ottieni la tua API Key su"
+ "sectionTitle": "Abbonamento Zoo Code",
+ "apiKeyLabel": "Chiave API",
+ "apiKeyDescription": "Ottieni la tua chiave API su"
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@webview-ui/src/i18n/locales/it/settings.json` around lines 1011 - 1014, The
Italian locale has English strings in the "zooCodeSubscription" object—translate
"sectionTitle", "apiKeyLabel" and "apiKeyDescription" into Italian to keep the
settings UI consistent; update the values for the keys
"zooCodeSubscription.sectionTitle", "zooCodeSubscription.apiKeyLabel" and
"zooCodeSubscription.apiKeyDescription" with appropriate Italian text (e.g.,
localized equivalents for "Zoo Code Subscription", "API Key", and "Get your API
Key at") while preserving the JSON structure and punctuation.
| "zooCodeSubscription": { | ||
| "sectionTitle": "Zoo Code Subscription", | ||
| "apiKeyLabel": "API Key", | ||
| "apiKeyDescription": "API Keyはこちらで取得できます" |
There was a problem hiding this comment.
Translate the new subscription copy.
sectionTitle, apiKeyLabel, and apiKeyDescription are still English here, so the Japanese settings page will show mixed-language UI. Please localize this block.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@webview-ui/src/i18n/locales/ja/settings.json` around lines 1011 - 1014,
Localize the zooCodeSubscription object by translating the three keys:
"sectionTitle", "apiKeyLabel", and "apiKeyDescription" into Japanese; update the
values under the zooCodeSubscription block so "sectionTitle" becomes a Japanese
title for the subscription section, "apiKeyLabel" becomes the Japanese label for
API Key, and "apiKeyDescription" becomes a natural Japanese sentence indicating
where to obtain the API key (replacing the current English text).
| "zooCodeSubscription": { | ||
| "sectionTitle": "Zoo Code Subscription", | ||
| "apiKeyLabel": "API Key", | ||
| "apiKeyDescription": "Haal uw API Key op bij" |
There was a problem hiding this comment.
Dutch locale contains English subscription labels.
Line 1012 and Line 1013 should be localized to keep the settings page language consistent.
💡 Suggested update
"zooCodeSubscription": {
- "sectionTitle": "Zoo Code Subscription",
- "apiKeyLabel": "API Key",
- "apiKeyDescription": "Haal uw API Key op bij"
+ "sectionTitle": "Zoo Code-abonnement",
+ "apiKeyLabel": "API-sleutel",
+ "apiKeyDescription": "Haal uw API-sleutel op bij"
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "zooCodeSubscription": { | |
| "sectionTitle": "Zoo Code Subscription", | |
| "apiKeyLabel": "API Key", | |
| "apiKeyDescription": "Haal uw API Key op bij" | |
| "zooCodeSubscription": { | |
| "sectionTitle": "Zoo Code-abonnement", | |
| "apiKeyLabel": "API-sleutel", | |
| "apiKeyDescription": "Haal uw API-sleutel op bij" | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@webview-ui/src/i18n/locales/nl/settings.json` around lines 1011 - 1014, The
Dutch locale uses English text for the subscription settings; update the
"zooCodeSubscription" object keys ("sectionTitle", "apiKeyLabel",
"apiKeyDescription") in webview-ui/src/i18n/locales/nl/settings.json to Dutch
translations so the settings page is fully localized—replace "Zoo Code
Subscription" with a Dutch section title, "API Key" with the Dutch label, and
complete the "apiKeyDescription" sentence in Dutch (including any punctuation)
to match the rest of the nl locale.
| "zooCodeSubscription": { | ||
| "sectionTitle": "Zoo Code Subscription", | ||
| "apiKeyLabel": "API Key", | ||
| "apiKeyDescription": "Uzyskaj swój API Key na" |
There was a problem hiding this comment.
Localize the new subscription strings in Polish.
Line 1012 and Line 1013 are English, which creates a mixed-language experience in the Polish settings file.
💡 Suggested update
"zooCodeSubscription": {
- "sectionTitle": "Zoo Code Subscription",
- "apiKeyLabel": "API Key",
- "apiKeyDescription": "Uzyskaj swój API Key na"
+ "sectionTitle": "Subskrypcja Zoo Code",
+ "apiKeyLabel": "Klucz API",
+ "apiKeyDescription": "Uzyskaj swój klucz API na"
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "zooCodeSubscription": { | |
| "sectionTitle": "Zoo Code Subscription", | |
| "apiKeyLabel": "API Key", | |
| "apiKeyDescription": "Uzyskaj swój API Key na" | |
| "zooCodeSubscription": { | |
| "sectionTitle": "Subskrypcja Zoo Code", | |
| "apiKeyLabel": "Klucz API", | |
| "apiKeyDescription": "Uzyskaj swój klucz API na" | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@webview-ui/src/i18n/locales/pl/settings.json` around lines 1011 - 1014, The
Polish locale contains untranslated English strings under the
zooCodeSubscription object; replace the values for "sectionTitle",
"apiKeyLabel", and "apiKeyDescription" in the "zooCodeSubscription" entry with
proper Polish translations so the settings file is fully localized (update the
"zooCodeSubscription" -> "sectionTitle", "apiKeyLabel", and "apiKeyDescription"
values).
| "zooCodeSubscription": { | ||
| "sectionTitle": "Zoo Code Subscription", | ||
| "apiKeyLabel": "API Key", | ||
| "apiKeyDescription": "Obtenha sua API Key em" |
There was a problem hiding this comment.
Translate the new subscription copy.
sectionTitle, apiKeyLabel, and apiKeyDescription are still English here, so the new section will show mixed-language UI in pt-BR. Please localize this block.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@webview-ui/src/i18n/locales/pt-BR/settings.json` around lines 1011 - 1014,
The three strings under the "zooCodeSubscription" object are still in English;
update the values for "sectionTitle", "apiKeyLabel", and "apiKeyDescription" to
Portuguese so the pt-BR locale is consistent (e.g., "sectionTitle": "Assinatura
do Zoo Code", "apiKeyLabel": "Chave de API", and "apiKeyDescription": "Obtenha
sua Chave de API em"). Ensure you only change the values for the keys
"zooCodeSubscription.sectionTitle", "zooCodeSubscription.apiKeyLabel", and
"zooCodeSubscription.apiKeyDescription" and preserve the existing JSON structure
and punctuation.
| "zooCodeSubscription": { | ||
| "sectionTitle": "Zoo Code Subscription", | ||
| "apiKeyLabel": "API Key", | ||
| "apiKeyDescription": "Получите свой API Key на" |
There was a problem hiding this comment.
Translate the new subscription copy.
sectionTitle, apiKeyLabel, and apiKeyDescription are still English here, so the Russian settings page will show mixed-language UI. Please localize this block.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@webview-ui/src/i18n/locales/ru/settings.json` around lines 1011 - 1014, The
keys under "zooCodeSubscription" ("sectionTitle", "apiKeyLabel",
"apiKeyDescription") are still in English; replace their values with Russian
translations so the settings UI is fully localized — update "sectionTitle" to a
Russian equivalent for "Zoo Code Subscription", "apiKeyLabel" to "API ключ" (or
similar), and "apiKeyDescription" to a Russian phrase that completes "Получите
свой API Key на" (e.g., "Получите свой API‑ключ на <site>"), preserving existing
punctuation and context/placeholder structure.
What it does
Every time a tool like
read_fileorsearch_filesruns, its full output goes into conversation history and gets re-sent to the primary model on every subsequent API call. A singleread_fileon a 1,000-line file can add 8,000–15,000 tokens that stay in context for the entire task.This PR adds an invisible compression layer between tool execution and conversation history. Before a large tool result is stored, a cheap secondary model compresses it into a focused summary. The primary model sees less noise, the task runs cheaper, and the user sees nothing different in the UI.
All users benefit from env details diffing, old tool result truncation, parallel tool calls. LLM-assisted compression is subscription-only.
What changed
New files:
src/core/tools/ToolResultProcessor.ts—shouldCompress()+compress()with configurable per-tool thresholdssrc/core/tools/compressAndPush.ts— wrapper that replaces directpushToolResultcalls in tool handlerssrc/core/tools/resolveCompressionHandler.ts— async subscription check via Zoo Code API (1hr cache per key), returnsZooGatewayApiHandlerfor subscribers ornullfor free userssrc/core/tools/ToolResultProcessorConfig.ts— config interface + defaultssrc/core/tools/CompletionPostProcessor.ts— optional reformatting ofattempt_completionresult textsrc/api/providers/zoo-gateway.ts— routes compression calls to/api/proxy/internal/compressusing the user's Zoo Code API keysrc/core/context-management/compressToolResults.ts— truncates old tool results in long conversationssrc/core/environment/environmentDiff.ts— only sends changed env detail sections on turns 2+Modified files:
src/core/tools/{ReadFileTool,SearchFilesTool,ListFilesTool,CodebaseSearchTool,ExecuteCommandTool}.ts— usecompressAndPushToolResultinstead of rawpushToolResultsrc/core/task/Task.ts— async handler init on construction,isSubscriberflag,toolResultProcessorSettingsfrom global state,compressOldToolResultsin main loop, env diff trackingsrc/core/webview/webviewMessageHandler.ts— clears subscription cache whenzooCodeApiKeychangeswebview-ui/src/components/settings/SettingsView.tsx—zooCodeApiKeyinput fieldpackages/types/src/global-settings.ts—zooCodeApiKey+zooCodeBaseUrlin schema,toolResultProcessorSettingssrc/api/index.ts—taskIdoptional,toolNameadded toApiHandlerCreateMessageMetadatasrc/package.json—zooCodeApiKey/zooCodeBaseUrlVS Code settings contributionsTest coverage:
resolveCompressionHandler.spec.ts— 11 testsToolResultProcessor.spec.ts— 27 testscompressAndPush.spec.ts— 6 testsCompletionPostProcessor.spec.ts— 7 testscompressToolResults.spec.ts— context compression testsenvironmentDiff.spec.ts— env diff testsHow it works
Compression triggers by tool
read_filesearch_files/codebase_searchlist_filesexecute_commandAll thresholds are user-configurable via
toolResultProcessorSettingsin extension settings.Optimizations that apply to everyone
read_file/list_filesresults older than N turns replaced with[content omitted]parallelToolCalls: truein metadataTesting this manually
zoo_sk_...)read_fileon a large file (> 1,500 chars)Notes
zoo-gateway.tshas no unit test yet — toolName wiring via metadata is the one gap in test coverageSummary by CodeRabbit
New Features
Configuration
Tests