Skip to content

Token Optimization — Context Reduction and LLM-Assisted Compression#14

Closed
JamesRobert20 wants to merge 3 commits into
mainfrom
feat/token-optimization
Closed

Token Optimization — Context Reduction and LLM-Assisted Compression#14
JamesRobert20 wants to merge 3 commits into
mainfrom
feat/token-optimization

Conversation

@JamesRobert20

@JamesRobert20 JamesRobert20 commented May 3, 2026

Copy link
Copy Markdown
Contributor

What it does

Every time a tool like read_file or search_files runs, its full output goes into conversation history and gets re-sent to the primary model on every subsequent API call. A single read_file on 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.tsshouldCompress() + compress() with configurable per-tool thresholds
  • src/core/tools/compressAndPush.ts — wrapper that replaces direct pushToolResult calls in tool handlers
  • src/core/tools/resolveCompressionHandler.ts — async subscription check via Zoo Code API (1hr cache per key), returns ZooGatewayApiHandler for subscribers or null for free users
  • src/core/tools/ToolResultProcessorConfig.ts — config interface + defaults
  • src/core/tools/CompletionPostProcessor.ts — optional reformatting of attempt_completion result text
  • src/api/providers/zoo-gateway.ts — routes compression calls to /api/proxy/internal/compress using the user's Zoo Code API key
  • src/core/context-management/compressToolResults.ts — truncates old tool results in long conversations
  • src/core/environment/environmentDiff.ts — only sends changed env detail sections on turns 2+

Modified files:

  • src/core/tools/{ReadFileTool,SearchFilesTool,ListFilesTool,CodebaseSearchTool,ExecuteCommandTool}.ts — use compressAndPushToolResult instead of raw pushToolResult
  • src/core/task/Task.ts — async handler init on construction, isSubscriber flag, toolResultProcessorSettings from global state, compressOldToolResults in main loop, env diff tracking
  • src/core/webview/webviewMessageHandler.ts — clears subscription cache when zooCodeApiKey changes
  • webview-ui/src/components/settings/SettingsView.tsxzooCodeApiKey input field
  • packages/types/src/global-settings.tszooCodeApiKey + zooCodeBaseUrl in schema, toolResultProcessorSettings
  • src/api/index.tstaskId optional, toolName added to ApiHandlerCreateMessageMetadata
  • src/package.jsonzooCodeApiKey/zooCodeBaseUrl VS Code settings contributions

Test coverage:

  • resolveCompressionHandler.spec.ts — 11 tests
  • ToolResultProcessor.spec.ts — 27 tests
  • compressAndPush.spec.ts — 6 tests
  • CompletionPostProcessor.spec.ts — 7 tests
  • compressToolResults.spec.ts — context compression tests
  • environmentDiff.spec.ts — env diff tests

How it works

User generates a Zoo Code API key at zoocode.dev/dashboard/api-tokens
  → pastes it in Settings → Zoo Code API Key
  → stored in VS Code SecretStorage

Task starts →
  resolveCompressionHandler(apiKey) called async
    → GET zoocode.dev/api/subscription/status (Bearer: apiKey)
    → returns { isSubscriber: true } for paid plans, false for free
  → ZooGatewayApiHandler instantiated for subscribers
  → ToolResultProcessor(handler) + isSubscriber: true set on config

Tool executes (e.g. read_file returns 10,000 chars) →
  compressAndPushToolResult("read_file", rawResult, context, task, pushToolResult)
    → shouldCompress() checks: enabled + isSubscriber + threshold exceeded
    → compress() calls ZooGatewayApiHandler.createMessage(systemPrompt, [rawResult], { toolName })
    → POST zoocode.dev/api/proxy/internal/compress (Bearer: apiKey)
      → returns { compressed: "focused 200-token summary" }
    → compressed result pushed to conversation history

Primary model receives focused summary instead of full 10,000-char blob

Compression triggers by tool

Tool Compresses when
read_file result > 1,500 chars
search_files / codebase_search > 20 non-empty lines
list_files > 100 paths
execute_command result > 1,500 chars

All thresholds are user-configurable via toolResultProcessorSettings in extension settings.

Optimizations that apply to everyone

  • Env details diffing — only changed sections sent on turns 2+, saves 150–600 tokens/turn
  • Old tool result truncationread_file/list_files results older than N turns replaced with [content omitted]
  • Parallel tool calls — already enabled via parallelToolCalls: true in metadata

Testing this manually

  1. Subscribe to Zoo Code Pro at zoocode.dev
  2. Go to Dashboard → API Tokens → generate a key (zoo_sk_...)
  3. Open VS Code → open the Zoo Code sidebar → click the settings icon → go to the About tab
  4. Under Zoo Code Subscription, paste the key into the API Key field
  5. Start a task, run read_file on a large file (> 1,500 chars)
  6. Verify the compressed summary — not the full raw output — appears in conversation history

Notes

  • zoo-gateway.ts has no unit test yet — toolName wiring via metadata is the one gap in test coverage
  • Evals A/B comparison (token cost with/without compression) is the next validation step before production rollout

Summary by CodeRabbit

  • New Features

    • On-device compression of large tool outputs using an optional Zoo Code subscription.
    • Concurrent execution of multiple read-only tools for faster responses.
    • Automatic pruning/diffing of environment details to avoid resending unchanged info.
    • Optional post-processing of completion results into concise, scannable summaries.
  • Configuration

    • New Zoo Code Subscription settings (API key and base URL) exposed in the Settings UI.
  • Tests

    • Added comprehensive tests covering compression, post-processing, environment diffing, and tool batching.

@coderabbitai

coderabbitai Bot commented May 3, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds 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.

Changes

Tool Result Compression System

Layer / File(s) Summary
Types & Configuration
packages/types/src/global-settings.ts, src/core/tools/ToolResultProcessorConfig.ts
Adds toolResultProcessorSettings, zooCodeApiKey, zooCodeBaseUrl; exports ToolResultProcessorSettings; adds GLOBAL_SECRET_KEYS entry. Defines ToolResultProcessorConfig and DEFAULT_PROCESSOR_CONFIG.
API Metadata
src/api/index.ts
ApiHandlerCreateMessageMetadata makes taskId optional and adds optional toolName.
Compression Handler Resolution
src/core/tools/resolveCompressionHandler.ts
Implements cached subscription check, returns ZooGatewayApiHandler for subscribers or null; adds clearSubscriptionCache.
Zoo Code Provider
src/api/providers/zoo-gateway.ts
New ZooGatewayApiHandler that POSTs { systemPrompt, rawResult, toolName } to Zoo Code compress endpoint and yields text + usage events.
Core Processor
src/core/tools/ToolResultProcessor.ts, src/core/tools/compressAndPush.ts
New ToolResultProcessor with shouldCompress/compress/prompts/threshold logic; compressAndPushToolResult wrapper to conditionally compress before push.
History Compression / Placeholders
src/core/context-management/compressToolResults.ts
Adds TOOL_RESULT_* thresholds, COMPRESSIBLE_TOOLS, generatePlaceholder, extractToolNameFromHistory, and compressOldToolResults to replace stale large tool_result blocks with placeholders.
Tool Integrations
src/core/tools/*.ts (ReadFileTool, SearchFilesTool, ListFilesTool, ExecuteCommandTool, CodebaseSearchTool, AttemptCompletionTool)
Tools route outputs through compressAndPushToolResult; AttemptCompletionTool now uses CompletionPostProcessor for display-only post-processing. ReadFileTool refactored to await async push with per-file context.
Task Wiring
src/core/task/Task.ts
Task exposes toolResultProcessor and completionPostProcessor, merges persisted settings with defaults, asynchronously resolves Zoo handler (sets isSubscriber on success), applies compressOldToolResults to outbound history, and tracks lastEnvironmentSections.
Tests
src/core/tools/__tests__/*, src/core/context-management/__tests__/*
Unit and integration tests for ToolResultProcessor, compressAndPushToolResult, resolver caching, compressOldToolResults, and related utilities.

Environment Details Optimization

Layer / File(s) Summary
Parsing & Diffing
src/core/environment/environmentDiff.ts
Adds parseEnvironmentSections, diffEnvironmentDetails, assembleEnvironmentDetails, and ALWAYS_INCLUDE_SECTIONS to split, diff, and reassemble <environment_details> sections.
Task Integration
src/core/task/Task.ts
Task parses current environment sections, diffs against lastEnvironmentSections, injects only filtered/changed sections into outgoing user content, and resets cache when history is overwritten.
Tests
src/core/environment/__tests__/environmentDiff.spec.ts
Tests for parsing, diffing, assembly, always-include behavior, and round-trip correctness.

Parallel Read-Only Tool Execution

Layer / File(s) Summary
Tool Classification
src/core/tools/toolCategories.ts
Adds READ_ONLY_TOOLS, isReadOnlyTool(), and partitionToolsForExecution() to identify and group read-only tools for parallel execution.
Assistant Execution
src/core/assistant-message/presentAssistantMessage.ts
Detects 2+ consecutive complete read-only tool_use blocks, executes them concurrently with isolated per-tool callbacks, advances indexes, and records usage/telemetry.
Tests
src/core/tools/__tests__/toolCategories.spec.ts
Covers classification, partitioning, and batching behaviors.

Completion Post-Processing

Layer / File(s) Summary
Processor Class
src/core/tools/CompletionPostProcessor.ts
New CompletionPostProcessor that optionally reformats long attempt_completion output via an ApiHandler streaming call using a fixed prompt; gated by availability and input length; falls back on error.
Integration
src/core/tools/AttemptCompletionTool.ts, src/core/task/Task.ts
AttemptCompletionTool uses completionPostProcessor for display; Task instantiates the processor.
Tests
src/core/tools/__tests__/CompletionPostProcessor.spec.ts
Tests availability, length gating, streaming concatenation, and error fallback.

Zoo Code Settings & UI

Layer / File(s) Summary
Extension Settings
src/package.json
Adds roo-cline.zooCodeApiKey and roo-cline.zooCodeBaseUrl configuration properties.
Global Types
packages/types/src/global-settings.ts
Schema additions for toolResultProcessorSettings, zooCodeApiKey, and zooCodeBaseUrl; exports ToolResultProcessorSettings.
Webview UI
webview-ui/src/components/settings/SettingsView.tsx
Adds "Zoo Code Subscription" section with password field, state handling, and includes zooCodeApiKey in settings update payload.
i18n
webview-ui/src/i18n/locales/*/settings.json
Adds zooCodeSubscription translation block across locales.
Cache Invalidation
src/core/webview/webviewMessageHandler.ts
Calls clearSubscriptionCache() when zooCodeApiKey setting is updated.

Testing & Prompt-Caching

Layer / File(s) Summary
Prompt Caching Tests
src/api/providers/__tests__/prompt-caching.spec.ts
Vitest regression tests for Anthropic provider prompt-caching behavior, headers, system/user cache_control markers, and stream-derived cacheWriteTokens/cacheReadTokens.
General Tests
multiple src/core/tools/__tests__/*, src/core/context-management/__tests__/*
Comprehensive unit and integration coverage for new features and edge cases.

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
Loading
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
Loading
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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

"I'm a rabbit in the code-lined glen,
compressing outputs again and again,
old results rest while new ones fly,
Zoo Code hums beneath the sky—
parallel hops and tidy trails, hooray!" 🐇✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures the main change: token optimization through context reduction and LLM-assisted compression, which aligns with the core focus of all file changes.
Description check ✅ Passed The PR description provides comprehensive coverage: clear 'What it does' section, detailed file changes, implementation flow, compression triggers table, testing instructions, and explicit notes on coverage gaps—exceeding template requirements.
Docstring Coverage ✅ Passed Docstring coverage is 96.15% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/token-optimization

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.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

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 help to get the list of available commands and usage tips.

@JamesRobert20

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 3, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🧹 Nitpick comments (4)
src/core/assistant-message/presentAssistantMessage.ts (1)

856-856: 💤 Low value

Consider Promise.allSettled for more resilient batch execution.

If one tool throws an unexpected exception (not caught by handleError), Promise.all rejects immediately and remaining tools may not push their results. Using Promise.allSettled would 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 value

Note: execute_command reuses readFileCharsAbove threshold.

The execute_command tool uses the same threshold as read_file (thresholds.readFileCharsAbove). This is functional but may be unclear to users configuring thresholds. Consider documenting this behavior or adding an explicit executeCommandCharsAbove threshold 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 value

Consider 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 value

Minor: Cache hit creates new handler instance each time.

On cache hit, a new ZooGatewayApiHandler is 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

📥 Commits

Reviewing files that changed from the base of the PR and between 2e3ec13 and 2644752.

📒 Files selected for processing (30)
  • packages/types/src/global-settings.ts
  • src/api/index.ts
  • src/api/providers/__tests__/prompt-caching.spec.ts
  • src/api/providers/zoo-gateway.ts
  • src/core/assistant-message/presentAssistantMessage.ts
  • src/core/context-management/__tests__/compressToolResults.spec.ts
  • src/core/context-management/compressToolResults.ts
  • src/core/environment/__tests__/environmentDiff.spec.ts
  • src/core/environment/environmentDiff.ts
  • src/core/task/Task.ts
  • src/core/tools/AttemptCompletionTool.ts
  • src/core/tools/CodebaseSearchTool.ts
  • src/core/tools/CompletionPostProcessor.ts
  • src/core/tools/ExecuteCommandTool.ts
  • src/core/tools/ListFilesTool.ts
  • src/core/tools/ReadFileTool.ts
  • src/core/tools/SearchFilesTool.ts
  • src/core/tools/ToolResultProcessor.ts
  • src/core/tools/ToolResultProcessorConfig.ts
  • src/core/tools/__tests__/CompletionPostProcessor.spec.ts
  • src/core/tools/__tests__/ToolResultProcessor.spec.ts
  • src/core/tools/__tests__/compressAndPush.spec.ts
  • src/core/tools/__tests__/resolveCompressionHandler.spec.ts
  • src/core/tools/__tests__/toolCategories.spec.ts
  • src/core/tools/compressAndPush.ts
  • src/core/tools/resolveCompressionHandler.ts
  • src/core/tools/toolCategories.ts
  • src/core/webview/webviewMessageHandler.ts
  • src/package.json
  • webview-ui/src/components/settings/SettingsView.tsx

Comment thread packages/types/src/global-settings.ts
Comment thread src/api/providers/zoo-gateway.ts Outdated
Comment on lines +692 to +707
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
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

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.

Comment on lines +24 to +40
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)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

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.

Suggested change
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.

Comment thread src/core/task/Task.ts
Comment on lines +583 to +597
// 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
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

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.

Comment on lines +83 to +85
const displayResult = task.completionPostProcessor?.isAvailable
? await task.completionPostProcessor.postProcess(result)
: result

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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.

Comment thread src/core/tools/CompletionPostProcessor.ts
Comment thread src/core/tools/ToolResultProcessorConfig.ts
Comment thread webview-ui/src/components/settings/SettingsView.tsx Outdated
@JamesRobert20

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 3, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 2644752 and d8e60af.

📒 Files selected for processing (26)
  • packages/types/src/global-settings.ts
  • src/api/providers/zoo-gateway.ts
  • src/core/task/Task.ts
  • src/core/tools/CompletionPostProcessor.ts
  • src/core/tools/ToolResultProcessor.ts
  • src/core/tools/ToolResultProcessorConfig.ts
  • src/core/tools/__tests__/ToolResultProcessor.spec.ts
  • webview-ui/src/components/settings/SettingsView.tsx
  • webview-ui/src/i18n/locales/ca/settings.json
  • webview-ui/src/i18n/locales/de/settings.json
  • webview-ui/src/i18n/locales/en/settings.json
  • webview-ui/src/i18n/locales/es/settings.json
  • webview-ui/src/i18n/locales/fr/settings.json
  • webview-ui/src/i18n/locales/hi/settings.json
  • webview-ui/src/i18n/locales/id/settings.json
  • webview-ui/src/i18n/locales/it/settings.json
  • webview-ui/src/i18n/locales/ja/settings.json
  • webview-ui/src/i18n/locales/ko/settings.json
  • webview-ui/src/i18n/locales/nl/settings.json
  • webview-ui/src/i18n/locales/pl/settings.json
  • webview-ui/src/i18n/locales/pt-BR/settings.json
  • webview-ui/src/i18n/locales/ru/settings.json
  • webview-ui/src/i18n/locales/tr/settings.json
  • webview-ui/src/i18n/locales/vi/settings.json
  • webview-ui/src/i18n/locales/zh-CN/settings.json
  • webview-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

Comment on lines +1011 to +1014
"zooCodeSubscription": {
"sectionTitle": "Zoo Code Subscription",
"apiKeyLabel": "API Key",
"apiKeyDescription": "Obtén tu API Key en"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

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.

Suggested change
"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.

Comment on lines +1011 to +1014
"zooCodeSubscription": {
"sectionTitle": "Zoo Code Subscription",
"apiKeyLabel": "API Key",
"apiKeyDescription": "Obtenez votre API Key sur"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

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.

Comment on lines +1011 to +1014
"zooCodeSubscription": {
"sectionTitle": "Zoo Code Subscription",
"apiKeyLabel": "API Key",
"apiKeyDescription": "अपनी API Key यहाँ प्राप्त करें"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

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.

Suggested change
"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.

Comment on lines +1011 to +1014
"zooCodeSubscription": {
"sectionTitle": "Zoo Code Subscription",
"apiKeyLabel": "API Key",
"apiKeyDescription": "Ottieni la tua API Key su"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

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.

Comment on lines +1011 to +1014
"zooCodeSubscription": {
"sectionTitle": "Zoo Code Subscription",
"apiKeyLabel": "API Key",
"apiKeyDescription": "API Keyはこちらで取得できます"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

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).

Comment on lines +1011 to +1014
"zooCodeSubscription": {
"sectionTitle": "Zoo Code Subscription",
"apiKeyLabel": "API Key",
"apiKeyDescription": "Haal uw API Key op bij"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

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.

Suggested change
"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.

Comment on lines +1011 to +1014
"zooCodeSubscription": {
"sectionTitle": "Zoo Code Subscription",
"apiKeyLabel": "API Key",
"apiKeyDescription": "Uzyskaj swój API Key na"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

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.

Suggested change
"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).

Comment on lines +1011 to +1014
"zooCodeSubscription": {
"sectionTitle": "Zoo Code Subscription",
"apiKeyLabel": "API Key",
"apiKeyDescription": "Obtenha sua API Key em"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

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.

Comment on lines +1011 to +1014
"zooCodeSubscription": {
"sectionTitle": "Zoo Code Subscription",
"apiKeyLabel": "API Key",
"apiKeyDescription": "Получите свой API Key на"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant