fix: prevent parent task from hanging when subtask delegation returns after per-mode API profile switch#466
Conversation
* test(list-files,search-files): unskip read-only e2e tools * chore: tighten list_files replay predicates * test(e2e): replace opaque smoke codes with explicit instructions * test(e2e): log say messages when running against real endpoints * test(e2e): restore replay result validation * test(e2e): address review feedback on readonly tool fixtures * fix(e2e): address readonly tool review feedback * test(e2e): address search-files review feedback * test: fix Windows list-files cwd assertions * test: fix Windows list-files expected file path --------- Co-authored-by: Roomote <roomote@roocode.com> Co-authored-by: Elliott de Launay <edelauna@gmail.com>
* test(read-file): unskipping read-file tests * test(list-files,search-files): unskip read-only e2e tools * test: unskip mutating vscode e2e tool suites * test(e2e): replace opaque smoke codes with explicit instructions * test(e2e): address review feedback on readonly tool fixtures * test(list-files,search-files): unskip read-only e2e tools * test(e2e): replace opaque smoke codes with explicit instructions * test(e2e): address review feedback on readonly tool fixtures * test(e2e): address search-files review feedback * test(e2e): address mutating tool review feedback * test: validate mutating replay payload fixtures * test: drop read-file fixture whitespace churn --------- Co-authored-by: Elliott de Launay <edelauna@gmail.com> Co-authored-by: Roomote <roomote@roocode.com>
…-Org#160) * fix: cap default glm output reservation * test: align zai e2e max_tokens expectations --------- Co-authored-by: Roomote <roomote@roocode.com>
* update default zai model to glm-5.1 * change default model to glm-4.7 per coding plan recs
Co-authored-by: Roomote <roomote@roocode.com>
* test: add xai provider e2e coverage * test(xai): updates from local testing * fix(api): dedupe Responses API streamed tool calls * Fix Z.ai e2e state reset and Responses API tool fallback * Fix xAI e2e probe isolation --------- Co-authored-by: Roomote <roomote@roocode.com> Co-authored-by: Elliott de Launay <edelauna@gmail.com>
Co-authored-by: Roomote <roomote@roocode.com> Co-authored-by: Naved Merchant <naved.merchant@gmail.com>
* test(e2e): unskip use_mcp_tool replay coverage * test(e2e): relax mcp completion wording checks * test(e2e): use real MCP prompts in use_mcp_tool suite * test(e2e): unskip use_mcp_tool replay coverage with local MCP server --------- Co-authored-by: Roomote <roomote@roocode.com> Co-authored-by: Elliott de Launay <edelauna@gmail.com>
* refactor(core): extract monolith helpers Refs Zoo-Code-Org#8 * fix: address PR 27 review feedback * fix: defensively copy pending edit images * fix: preserve reasoning summary field * test: cover api conversation edge cases * docs: clarify reasoning summary fallback
* FEATURE: Add Xiaomi MiMo as a first-class API provider - New MimoHandler with reasoning_content passthrough for multi-turn tool calling - Custom message conversion preserving MiMo's interleaved thinking chain - Strip OpenAI-specific extensions (strict, additionalProperties) from tool schemas - Models: mimo-v2.5-pro, mimo-v2.5, mimo-v2-flash with official pricing - UI settings with 4 base URL options (3 Token Plan regions + Pay-as-you-go) - Full wiring: types, schema, model picker, i18n, provider config * Update openrouter.ts * Preserve Mimo reasoning fields & switch AMS endpoint Update Mimo provider config and UI to use the token-plan-ams endpoint instead of the old FRA host. Allow Mimo assistant messages with string content to include and preserve a reasoning_content field when present. Also avoid attaching mapped reasoning_details when converting messages for Mimo models (skip mapping if modelId matches /mimo/i) to preserve the provider's original shape. Types, API handler, transform logic, and the settings UI were updated to keep Mimo-specific reasoning data intact and align the endpoint selection. * Add MiMo i18n translations to all 17 locales and unit tests Also hide the "not sure which model" hint for the MiMo provider since it's a static model list, not fetched dynamically. * Address CodeRabbit review feedback Fix Japanese translation consistency, strengthen base URL tests to verify actual values, and add ModelPicker test for MiMo hint hiding. * Expand MiMo test coverage and remove dev/null files from PR Added tests for tool_call_partial streaming, cache token usage, API error handling, message conversion pipeline, empty delta chunks, and tools parameter presence/absence. Removed dev/null/ hook files that were accidentally included in the branch. * Use data-testid for automaticFetch hint instead of i18n key matching * Remove mimo-v2-flash model that no longer supports thinking mode * Replace mimo-v2-flash with mimo-v2-pro model * Drop mimo-v2-flash since it doesn't support thinking mode * Address maintainer feedback: revert unrelated changes, add i18n, fix stream_options * Update doc links to use puter developer URLs * Fix i18n: JP spacing, FR translations, add multimodal support to message conversion * Add docstrings and document mimo-v2-flash exclusion rationale * Address edelauna review: sanitize tool IDs, use handleProviderError, fix prompt cache, clean up comments * Fold text into last tool message to preserve reasoning continuity * Refactor: use shared convertToR1Format, processToolCalls, cleanup unused imports/props * Remove dead temperature param, add 2-tier pricing, clarify strict stripping * Remove strict/additionalProperties stripping — proxy no longer rejects it * Use longContextPricing instead of tiers for cost calculation * Remove stale convertToolsForOpenAI tests (stripping removed)
…#199) Co-authored-by: Roomote <roomote@roocode.com> Co-authored-by: Naved Merchant <naved.merchant@gmail.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Roomote <roomote@roocode.com>
…Org#207) * chore: split packages/core integration coverage lane * [Chore] Fix core integration lane follow-up issues * [Chore] Relax Windows worktree integration matching * [Chore] Align worktree delete integration assertion with service contract * chore: Move core dual-lane test:coverage inside the package * chore: Flag core unit/integration Codecov uploads separately * chore: tighten core coverage lane wiring * Optimize CI cache and coverage uploads * chore: add merge queue triggers for required CI --------- Co-authored-by: Roomote <roomote@roocode.com> Co-authored-by: Elliott de Launay <edelauna@gmail.com>
…-Org#210) * test: add comprehensive unit tests for MimoHandler provider Add 45 unit tests covering the MimoHandler provider: - Constructor: model selection, default model fallback, base URL config - getModel(): model info for v2.5-pro, v2.5, unknown models - completePrompt(): happy path, multi-turn, JSON mode, model override - createMessage() with Anthropic format and custom baseUrl - Edge cases: empty choices, null content, network/rate limit errors - Streaming: multi-tool calls, parallel tools, tool call IDs, interruption - Sanitization: model ID, tool call IDs, prompt caching - convertToR1Format: empty arrays, thinking blocks, nested structures All 45 tests passing. * fix: sanitize mimo streaming tool call ids --------- Co-authored-by: Roomote <roomote@roocode.com>
* test(tools): add unit tests for SwitchModeTool - Add comprehensive test suite for SwitchModeTool (18 tests) - Cover mode slug validation (valid/invalid/missing) - Test error propagation from mode loading - Validate approval flow with correct params - Test mode switching delegation to Controller - Verify resolve() returns correct messages for both paths - Follow existing test patterns from ask.spec.ts * test: tighten switch mode review feedback cases --------- Co-authored-by: Roomote <roomote@roocode.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…Org#226) Closes Zoo-Code-Org#193 The temporary diagnostics file generated via the 'Report Issue' feature retained the legacy 'roo-diagnostics-' prefix from the Roo Code fork. This commit replaces it with 'zoo-diagnostics-' to match Zoo Code branding. Changes: - diagnosticsHandler.ts: rename temp file template from roo-diagnostics- to zoo-diagnostics- - diagnosticsHandler.spec.ts: update two assertions that matched the old prefix
* Merge upstream/main (Roo Code sunset) into Zoo Code * test: updating e2e collision and optimization 4.7 tests * chore: remove web-roo-code website and evals packages * fix: deepseek e2e fixture matching and mock model list fallback * refactor: make reasoningEffort optional in GetModelReasoningOptions * test(deepseek): updating fixture format * test: adding back coverage for telemetry and marketplace * fix(Announcement): reverting finalRelease message key * fix(ModeSelector): adding back telemetry * fix(DismissibleUpsell): adding back telemetry * fix(Announcement): adding back className * fix(McpView): keeping marketplace view * fix: adding back marketplace buttons * fix: adding back telemetry * fix: merge history * test: bumping coverage * merge: feedback
…oo-Code-Org#148) * test: add Gemini provider e2e coverage * fix(gemini): INVALID_ARGUMENT when loaded too many MCPs * fix(gemini): resolve $ref, deep-merge allOf, align e2e fixtures * refactor: dropping extra command * fix: preserve top-level Gemini schema fields with allOf * fix: guard recursive Gemini schema refs * fix(gemini): preserve keyword-named tool parameters during schema sanitization * test(gemini-e2e): wire aimock recording and use real model id --------- Co-authored-by: Roomote <roomote@roocode.com> Co-authored-by: Elliott de Launay <edelauna@gmail.com>
…o-Code-Org#154) (Zoo-Code-Org#240) remark-gfm treats a single ~ around text (e.g. "~10", "1~3") as strikethrough, unlike VS Code's markdown. Pass { singleTilde: false } so only "~~text~~" renders as strikethrough. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…ode-Org#215) (Zoo-Code-Org#233) * fix(openai): omit temperature for models that don't support it (Zoo-Code-Org#215) claude-opus-4-7 (and similar) reject requests through the OpenAI-Compatible provider with a 400 error because 'temperature' is deprecated/unsupported. Honor the model's existing supportsTemperature flag (already respected by openai-native, gemini, lite-llm and vercel-ai-gateway) and omit temperature from the streaming request when it is explicitly set to false. undefined keeps sending temperature, preserving current behavior for all other models. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * test(openai): cover both temperature branches behind supportsTemperature gate (Zoo-Code-Org#215) Add two tests so the temperature expression's branches are fully exercised: - explicit modelTemperature (left side of the `??`) - deepseek-reasoner default of DEEP_SEEK_DEFAULT_TEMPERATURE (truthy ternary) Closes the partial-branch gap codecov/patch flagged on line 162. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
* chore: prepare v3.55.0 release * chore: genericize release announcement highlight keys * chore: remove v3.55.0 release artwork --------- Co-authored-by: Roomote <roomote@roocode.com>
…e-Org#260) * docs: clarify stable release version lane * docs: use generic release version placeholders --------- Co-authored-by: Roomote <roomote@roocode.com>
…Code-Org#245) (Zoo-Code-Org#261) releaseTerminalsForTask only disassociated the terminal (taskId = undefined) without aborting a still-running command, so cancel (✕) left the process orphaned and the terminal stuck "busy" until a manual kill. Now abort the running process for busy terminals on release. Adds TerminalRegistry tests. Co-authored-by: Armando Vaquera <263793884+proyectoauraorg@users.noreply.github.com>
…-Org#186) (Zoo-Code-Org#230) * fix(diff): repair truncated Grok diffs by reinserting missing markers (Zoo-Code-Org#186) Grok frequently truncates streamed diffs, leaving SEARCH blocks without the ======= separator and/or the >>>>>>> REPLACE closer, which makes applyDiff fail with 'Expected ======= was not found'. repairTruncatedDiff() detects incomplete blocks and reinserts the missing markers while preserving valid blocks and escaped markers. * test(diff): add fixture-based regression tests for truncated Grok diffs (Zoo-Code-Org#186) Per review feedback: end-to-end applyDiff() regression guards using realistic truncated-Grok fixtures (missing >>>>>>> REPLACE, missing ======= separator), plus a well-formed multi-block diff that must pass through unchanged. * refactor(diff): address CodeRabbit review on truncated-diff repair (Zoo-Code-Org#186) - Use a local repairedDiff in applyDiff instead of reassigning the diffContent parameter, keeping the original input observable. - When a block has a closer but no ======= separator, splice the separator in before the existing >>>>>>> REPLACE rather than synthesizing a second closer. - Strip leading Grok header directives (:start_line:, :end_line:, -------) before the first-line-is-SEARCH heuristic so metadata isn't treated as content; the directives are preserved on the SEARCH section. * fix: remove unused needsRepair variable in repairTruncatedDiff Address review feedback from @edelauna (code review #3284681514): needsRepair was assigned but never read, making it a dead store. The variable served no functional purpose in the repair loop, so it has been removed. --------- Co-authored-by: Armando Vaquera <263793884+proyectoauraorg@users.noreply.github.com>
* chore(webview): migrate build to Vite 8 * update lockfile * remove minify on nightly mode
…g#383) * chore: prepare v3.55.1 release * chore: drop release image references * fix: localize v3.55.1 marketplace notes --------- Co-authored-by: Roomote <roomote@roocode.com>
…g#385) Drops the no-op webview handler and the unused message types. No callers remain in the extension. Co-authored-by: James Mtendamema <jmtendamema@geologicai.com> Co-authored-by: Cursor <cursoragent@cursor.com>
…Org#400) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…de-Org#235) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…rg#258) (Zoo-Code-Org#275) * feat(markdown): render GitHub-style alerts in the webview (Zoo-Code-Org#258) GitHub-style alerts ([!NOTE], [!TIP], [!IMPORTANT], [!WARNING], [!CAUTION]) were rendered as plain blockquotes, losing their semantic meaning and visual priority. Adds a focused remark transform (no new dependency) that detects a leading alert marker in a blockquote and tags it, plus a blockquote component that renders a codicon + label header and per-type accent styling using VS Code theme variables. Normal blockquotes (and unsupported markers) render unchanged. Closes Zoo-Code-Org#258 * fix(markdown): address PR Zoo-Code-Org#275 review feedback --------- Co-authored-by: Armando Vaquera <263793884+proyectoauraorg@users.noreply.github.com> Co-authored-by: Elliott de Launay <edelauna@gmail.com>
…oo-Code-Org#341) * dep(tmp): removing unused dependancy * chore(deps): remove unused dependencies from src * test: remove stale default-shell mocks --------- Co-authored-by: Elliott de Launay <edelauna@gmail.com>
Co-authored-by: Elliott de Launay <edelauna@gmail.com>
…oo-Code-Org#276) * feat(settings): add configurable chat font size (Zoo-Code-Org#157) The Zoo Code chat font could not be sized independently of VS Code's UI zoom. Adds an optional chatFontSize setting (px, 8-32) surfaced as a slider with a 'Use VS Code default' reset in the UI settings section. When unset the appearance is unchanged: the --zoo-chat-font-size CSS var defaults to --vscode-font-size, and the webview text scale derives from it. When set, the value is applied to the document root and persisted via the generic updateSettings path (nullish + null-on-reset, matching allowedMaxRequests). Includes init-vs-user-edit webview tests and full i18n for all 18 locales. Closes Zoo-Code-Org#157 * fix(webview): normalize nullish chatFontSize in context value (Zoo-Code-Org#157) * fix(settings): scope chat font size to the chat markdown surface (Zoo-Code-Org#157) * feat(settings): emit telemetry for chat font size changes (Zoo-Code-Org#157) The chat font size change/reset handlers now emit telemetry like the other UI settings handlers in this file (ui_settings_chat_font_size_changed with the value, and ui_settings_chat_font_size_reset). Covered by UISettings spec. --------- Co-authored-by: Armando Vaquera <263793884+proyectoauraorg@users.noreply.github.com>
* test: unskip subtasks e2e suite * test: tighten subtasks cancellation replay * test(e2e): validation and bumping codecov * fix: prevent child delegation start after parent metadata failure * chore: address delegation review cleanup * fix: delegated subtask lifecycle races * fix: harden delegated subtask cancellation * test(e2e): simplyfying e2e tests --------- Co-authored-by: Roomote <roomote@roocode.com> Co-authored-by: Elliott de Launay <edelauna@gmail.com>
… with native path (Zoo-Code-Org#222) Add unit coverage for ReadFileTool: input validation, rooignore blocking, directory/binary/image handling, image memory limits, approval flow, slice and indentation modes, output structure, and the legacy multi-file format. Source changes: - Drop the temporary "[read_file] Legacy format detected" debug console.warn. - Mirror the native path in the legacy read path: set didToolFailInCurrentTurn on rooignore blocks, directory reads, and read errors so a failed legacy read fails the tool turn consistently. - Recognize re-hydrated bare-`files` calls in isLegacyReadFileParams (history persisted before the _legacyFormat flag existed). Co-authored-by: Armando Vaquera <263793884+proyectoauraorg@users.noreply.github.com>
…de-Org#344) * feat(zoo-gateway): add provider types, handler, and model fetcher Co-authored-by: Cursor <cursoragent@cursor.com> * fix(zoo-gateway): respect readonly client, real version header, safer fetch - Stop reassigning RouterProvider.client; thread Zoo enrichment headers through openAiHeaders so a single OpenAI client is used. - Replace npm_package_version (never populated at extension runtime) with Package.version from the shared package shim. - Default the model list to [] on a structurally broken response so we log and recover instead of crashing on response.data.data being undefined. - Bypass inFlightRefresh de-duplication for zoo-gateway: a refresh triggered after sign-out/sign-in must not return the previous user's in-flight response. - Add fetcher unit tests covering auth header, timeout, error redaction, and bad-response handling. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(types): include zoo-gateway key in requestRouterModels record so RouterName stays exhaustive Co-authored-by: Cursor <cursoragent@cursor.com> * test(router-models): expect zoo-gateway in requestRouterModels responses Co-authored-by: Cursor <cursoragent@cursor.com> * test(zoo-gateway): add ZooGatewayHandler unit tests for codecov patch Cover constructor auth guard, base URL resolution, streaming, task/mode headers, temperature, cache breakpoints, tool calls, and completePrompt. Co-authored-by: Cursor <cursoragent@cursor.com> * test(zoo-gateway): mock cached-token + clear-token auth helpers The downstream stack (settings-ui) calls getCachedZooCodeToken and clearZooCodeToken from the auth handler. CI on stacked PRs merges base into head so this spec runs against the cached-token-aware handler; expand the auth module mock so the auth guard test exercises the real throw path instead of vitest's missing-mock-export error. Co-authored-by: Cursor <cursoragent@cursor.com> * test(zoo-gateway): align expected OpenAI headers with Zoo Code branding Co-authored-by: Cursor <cursoragent@cursor.com> * fix(zoo-gateway): defer auth check, fail-closed models, reuse Vercel schemas Co-authored-by: Cursor <cursoragent@cursor.com> * fix(zoo-gateway): accept models list without created/description fields Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(zoo-gateway): centralize auth-scoped cache-skip via AUTH_SCOPED_PROVIDERS Co-authored-by: Cursor <cursoragent@cursor.com> * chore(types): drop retired 'roo' provider from getApiProtocol allowlist Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: James Mtendamema <jmtendamema@geologicai.com> Co-authored-by: Cursor <cursoragent@cursor.com>
…rg#242) (Zoo-Code-Org#247) When "use custom temperature" is off, the OpenAI-Compatible provider still sent temperature: 0 (the fallback), so the model's server-side default never applied. Per the discussion on Zoo-Code-Org#242 (option A), omit the temperature field in that case. Preserves the supportsTemperature gate (Zoo-Code-Org#233), model-required defaults (deepseek-reasoner), and a deliberately-set 0. Co-authored-by: Armando Vaquera <263793884+proyectoauraorg@users.noreply.github.com>
…Code-Org#161) (Zoo-Code-Org#274) * feat(zai): expose configurable max output tokens for GLM models (Zoo-Code-Org#161) Add a standalone "max output tokens" slider for models that advertise `supportsMaxTokens` (e.g. Z.ai GLM) but do not surface a reasoning budget, and send the chosen value to the provider as `max_tokens`. - ThinkingBudget: extract the max-tokens slider into a small render helper shared by the standalone control and the reasoning-budget branch, and surface it for binary-reasoning models that also support a configurable max. - getModelMaxOutputTokens: honor the user's `modelMaxTokens` override for `supportsMaxTokens` models (capped at the model ceiling) instead of the 20% context-window clamp, so the runtime budget matches what is sent to the provider. - ProviderSettingsManager.export(): preserve `modelMaxTokens` for configurable-max models while dropping it for models that support neither reasoning budgets nor a configurable max. * Update src/shared/api.ts * Update webview-ui/src/components/settings/ThinkingBudget.tsx --------- Co-authored-by: Armando Vaquera <263793884+proyectoauraorg@users.noreply.github.com> Co-authored-by: edelauna <54631123+edelauna@users.noreply.github.com>
* feat(zoo-gateway): add provider types, handler, and model fetcher Co-authored-by: Cursor <cursoragent@cursor.com> * fix(zoo-gateway): respect readonly client, real version header, safer fetch - Stop reassigning RouterProvider.client; thread Zoo enrichment headers through openAiHeaders so a single OpenAI client is used. - Replace npm_package_version (never populated at extension runtime) with Package.version from the shared package shim. - Default the model list to [] on a structurally broken response so we log and recover instead of crashing on response.data.data being undefined. - Bypass inFlightRefresh de-duplication for zoo-gateway: a refresh triggered after sign-out/sign-in must not return the previous user's in-flight response. - Add fetcher unit tests covering auth header, timeout, error redaction, and bad-response handling. Co-authored-by: Cursor <cursoragent@cursor.com> * test(zoo-gateway): mock cached-token + clear-token auth helpers The downstream stack (settings-ui) calls getCachedZooCodeToken and clearZooCodeToken from the auth handler. CI on stacked PRs merges base into head so this spec runs against the cached-token-aware handler; expand the auth module mock so the auth guard test exercises the real throw path instead of vitest's missing-mock-export error. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(zoo-gateway): add settings UI, validation, and i18n Co-authored-by: Cursor <cursoragent@cursor.com> * fix(zoo-gateway): dynamic dashboard URL and cached-token fallback - Resolve ModelPicker serviceUrl from zooCodeBaseUrl so staging/dev environments link to the matching dashboard. - Fall back to getCachedZooCodeToken() in the handler and model fetcher when the profile has not been seeded yet (auth before webview open). Co-authored-by: Cursor <cursoragent@cursor.com> * fix(deps): drop stale webview-ui package.json drift that broke frozen-lockfile installs Co-authored-by: Cursor <cursoragent@cursor.com> * fix(i18n): restore googleCloudCredentialsPathWarning and automaticFetch 'free' search hint dropped on rebase Co-authored-by: Cursor <cursoragent@cursor.com> * fix(zoo-gateway): pick default model from fetched list, prefer Sonnet 4.5 Resolves Sonnet 4.5 from the gateway model catalog instead of a static Vercel slug so test (Bedrock) and live accounts both get a valid default. Reassigns stale profile model IDs when they are not in the catalog. Co-authored-by: Cursor <cursoragent@cursor.com> * test(zoo-gateway): cover dynamic default model picker for codecov patch Exports pickZooGatewayDefaultModelId so the helper is unit-testable and adds component tests for the auto-default useEffect (no-op while catalog loads, auto-pick on empty profile, repair stale id, no-op when valid). Co-authored-by: Cursor <cursoragent@cursor.com> * fix(i18n): restore UTF-8 for Google Cloud warning and model picker strings Co-authored-by: Cursor <cursoragent@cursor.com> * fix(zoo-gateway): settings UI sign-in button, validation tests, defer auth Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(zoo-gateway): localize auth-state UX to provider component Move the zoo-gateway sign-in error out of the shared form-validation effect in ApiOptions and into ZooGateway.tsx, where it renders inline via ApiErrorMessage. ApiOptions can then drop zooCodeIsAuthenticated from its useEffect dependency list, and validateApiConfigurationExcludingModelErrors short-circuits zoo-gateway entirely. Also rename the inline isSonnet45ModelId helper to isClaudeSonnetModelId and let pickZooGatewayDefaultModelId express the version-priority order directly, so the helper has no version baked into its name. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(zoo-gateway): enforce org provider check, simplify sign-in copy The settings-form short-circuit for zoo-gateway also bypassed the organization PROVIDER_NOT_ALLOWED check, so a workspace that disallows zoo-gateway could not surface that error. Scope the short-circuit to the keys/sign-in check only and let the org allowlist check run for every provider. Drop the quoted CTA from zooGatewaySignIn in all 18 locales: the sign-in button is rendered immediately below the inline error, so a duplicate label was just a drift hazard. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(webview): move provider model config + docs slugs out of ApiOptions Lift the inline PROVIDER_MODEL_CONFIG map and the docs-slug lookup out of ApiOptions.tsx into webview-ui/src/components/settings/utils/providerModelConfig.ts behind getProviderModelConfig and getProviderDocsSlug helpers. ApiOptions now reads provider-specific model fields, defaults, and docs slugs through those helpers, leaving the component focused on rendering. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(i18n): align French zooGatewaySignIn to formal vous register validation.zooGatewaySignIn used "Connecte-toi" while providers.zooGateway.signInDescription uses "Connectez-vous". Use vous consistently across both strings. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: James Mtendamema <jmtendamema@geologicai.com> Co-authored-by: Cursor <cursoragent@cursor.com>
…ode-Org#277) * feat(terminal): add inline terminal profile selection (Zoo-Code-Org#119) Add a 'terminalProfile' setting that lets users choose which VS Code terminal profile the inline terminal uses. On Windows the default cmd/PowerShell shell may use a non-UTF-8 code page (e.g. GBK) and garble output; selecting a UTF-8 profile such as Git Bash resolves this. The setting reuses VS Code's terminal profile concept: when set, the profile name is resolved against terminal.integrated.profiles.<platform> to derive shellPath/shellArgs for createTerminal. When empty/unset the default terminal behavior is preserved unchanged. Adds backend unit tests for profile resolution and a webview test for the settings dropdown wiring. * fix(test): relax spy types for overloaded VS Code APIs (Zoo-Code-Org#119) * fix(test): use ES import instead of require() in terminal profile spec (Zoo-Code-Org#119) * refactor(terminal): address review feedback on inline terminal profile (Zoo-Code-Org#119) - Route profile names through a dedicated allowlisted `requestTerminalProfiles` message instead of the generic `getVSCodeSetting` (which reads any key the webview supplies); the extension reads the profiles and returns only names. - Preserve the profile's `env` (sanitized to string/null; null unsets a var), merged onto the base env in createTerminal. - Clarify the setting copy (en + es) vs the 'Use Inline Terminal' description. - Add tests: updateSettings->setTerminalProfile bridge, resolveWebviewView startup hydration, and profile env preservation/sanitization. * fix(terminal): resolve profile path[] to first existing candidate (Zoo-Code-Org#119) VS Code selects the first terminal-profile path candidate that exists on disk; mirror that instead of always taking index 0, falling back to the first non-empty candidate when none exist. Addresses CodeRabbit review on Zoo-Code-Org#277. * fix(terminal): hide inline profile picker when inline execution is off The terminal-profile dropdown only affects inline execution, which is active when shell integration is disabled. It previously stayed visible and editable even when inline mode was off, where it has no effect. Guard it with terminalShellIntegrationDisabled (defaulting to shown, matching the checkbox), mirroring the inline-only settings below. Addresses PR Zoo-Code-Org#277 review (edelauna). * fix(terminal): address review feedback * refactor(terminal): scope profile picker to VS Code integrated terminal, filter source-only profiles * fix(terminal): scope profile config to user settings, filter shellArgs, fix PATH join * refactor(terminal): address review feedback on profile picker * refactor(terminal): address review feedback on profile picker * refactor(terminal): promote no_shell_integration payload to typed object * feat(terminal): replace pWaitFor with event-based shell integration wait; add cmd.exe fast-path * fix(terminal): retry via execa silently when shell integration fails before submission * fix(terminal): close idle terminals when profile changes * fix(terminal): skip ZDOTDIR injection with profile override; clear cached profile on picker open * test(e2e): smoke-test VS Code terminal profile override lifecycle * fix(terminal): avoid replaying commands after shell integration failure * fix(terminal): harden profile settings and cleanup * Revert "feat(terminal): replace pWaitFor with event-based shell integration wait; add cmd.exe fast-path" This reverts commit 40e17b1. * fix(TerminalProcess): warning even when shell opens --------- Co-authored-by: Armando Vaquera <263793884+proyectoauraorg@users.noreply.github.com> Co-authored-by: Elliott de Launay <edelauna@gmail.com>
…de-Org#347) * feat(zoo-gateway): auth callback, profile token sync, and sign-out Co-authored-by: Cursor <cursoragent@cursor.com> * test(zoo-gateway): cover auth callback profile sync and sign-out Add ClineProvider tests for handleZooCodeCallback, ensureZooGatewayProfileSeeded, and webviewMessageHandler zooCodeSignOut to satisfy codecov patch on PR Zoo-Code-Org#347. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(zoo-gateway): surface 401/402/403 errors with actionable toasts Clear the cached token on 401 and offer sign-in. On insufficient credits or budget limits, open the credits page. On account frozen/banned, open support. Errors still propagate to the task layer after the toast. Co-authored-by: Cursor <cursoragent@cursor.com> * i18n(zoo-gateway): backfill zooAuth translations for 17 non-English locales Adds session_expired, out_of_credits, account_unavailable, budget_exceeded under zooAuth.errors and a new zooAuth.buttons block (sign_in, add_credits, contact_support) introduced by the gateway 401/402/403 UX so check-translations passes. Co-authored-by: Cursor <cursoragent@cursor.com> * test(zoo-gateway): cover surfaceGatewayApiError UX branches for codecov patch Adds vscode + i18n mocks and asserts the 401/402/403/429 paths in surfaceGatewayApiError: token clear + sign-in URL on 401, add-credits URL on 402 and budget-coded 429, support URL on 403, no-op on 429 without a budget code or on errors without a status. Also verifies the helper still runs before completePrompt rewraps the upstream error. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(zoo-gateway): address PR review feedback on auth, seeding, and errors Co-authored-by: Cursor <cursoragent@cursor.com> * test(zoo-gateway): cover stale baseUrl seeding path Co-authored-by: Cursor <cursoragent@cursor.com> * fix(zoo-gateway): sign-out clears stale profile tokens, simplify model fetch Co-authored-by: Cursor <cursoragent@cursor.com> * test(zoo-gateway): drop stale profile-scan test for requestRouterModels Co-authored-by: Cursor <cursoragent@cursor.com> * fix(zoo-gateway): treat verify 5xx as transient, do not clear token The website's /api/extension/auth/verify route now returns 503 when the backend can't reach the database, instead of crashing. The extension previously treated any non-OK response from this endpoint as a definitively invalid token, which meant a transient backend hiccup would silently clear the user's session and force a fresh sign-in. verifyZooCodeToken now returns "unreachable" for 5xx responses (same classification as a network error), so initZooCodeAuth keeps the cached token in place and reports subscription status as "unknown" until the backend recovers. handleAuthCallback shows the could-not-verify message on 5xx so users see this is a temporary issue rather than a bad token. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(zoo-gateway): split error classification from UX, extract callback fan-out Address review feedback on PR Zoo-Code-Org#347: - zoo-gateway.ts: split surfaceGatewayApiError into a pure classifyGatewayApiError (error -> action) plus a thin UX layer that switches on the action. The classifier is exported and covered by focused unit tests, so the status/code -> action mapping no longer needs the VS Code notification mocks to verify. - handleUri.ts: extract the per-instance token propagation loop into a propagateZooGatewayCallback helper, keeping the /auth-callback case focused on routing. Behaviour (sequential read-modify-write, per instance error isolation) is unchanged. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: isolate per-profile token cleanup on sign-out and assert state refresh Wrap per-profile work in the zoo-gateway sign-out cleanup loop in its own try/catch so one corrupted profile or failed write no longer aborts cleanup of the remaining profiles. Also assert postStateToWebview runs on the handleZooCodeCallback persistence-failure path. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: James Mtendamema <jmtendamema@geologicai.com> Co-authored-by: Cursor <cursoragent@cursor.com>
…gs (Zoo-Code-Org#346) * feat(privacy): remove extension LLM telemetry and observability section Delete the extension-side LLM telemetry path (zoo-telemetry.ts and its Task.ts hook) so BYOK requests no longer send usage metadata to zoocode.dev. Drop the "Zoo Code Observability" section from PRIVACY.md entirely: server-side gateway request logging is not extension behavior and is documented at zoocode.dev like any other provider's, so the extension privacy policy should not single it out. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(zoo-code-auth): drop subscription-status helpers with telemetry The checkSubscriptionStatus / getCachedSubscriptionStatus helpers existed only to gate the now-removed LLM telemetry path. Remove them and their tests. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
… after per-mode API profile switch **Problem:** When an orchestrator/parent task delegates to a subtask whose mode is bound to a different API-configuration profile (modeApiConfigs) than the parent, the subtask completes and calls attempt_completion, but control never returns to the parent. The run silently waits for manual click instead of auto-resuming. **Root cause:** handleModeSwitch → activateProviderProfile leaves the parent task record as status="active" while awaitingChildId still points at the child. Two guards then reject because they require parent status to be exactly "delegated": 1. reopenParentFromDelegation() had an overly strict guard checking cancelledDelegationChildIds.has(childTaskId). When cancelTask() fails to detach the parent due to a runDelegationTransition race, the child is added to the blacklist. On the second attempt_completion call, the guard blocks reopen permanently. 2. Guard in attempt_completion delegation pre-check only accepts status === "delegated". **Fix:** - Remove cancelledDelegationChildIds from reopenParentFromDelegation guard. The cancelledDelegationChildIds blacklist is redundant — cancelTask() already sets parent status to "active" before adding to blacklist. If parent is still "delegated" and awaiting this child, it is safe to reopen. - Add parentHistory verification before delegation: check parentHistory.status === "delegated" && parentHistory.awaitingChildId === task.taskId before calling delegateToParent. - Exempt subtask delegation from didToolFailInCurrentTurn guard (&& !task.parentTaskId) — the subtask is legitimately finishing assigned work. Fixes Zoo-Code-Org#457
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThe PR refines subtask completion and return-to-parent flow by exempting delegated subtasks from tool-failure guards, re-validating that the parent is still actively awaiting the child before delegation, and simplifying the parent reopening precondition by removing a now-obsolete blacklist check. Changes span both the tool execution layer and the webview provider state management. ChangesSubtask delegation return flow robustness
Sequence Diagram(s)sequenceDiagram
participant AttemptCompletion as AttemptCompletionTool
participant ParentState as Parent Task State
participant ClineProvider as ClineProvider.reopenParent
participant User as User (fallback)
AttemptCompletion->>AttemptCompletion: Check: tool failed but parentTaskId exists?
Note over AttemptCompletion: Exempted for delegated subtasks
AttemptCompletion->>ParentState: Re-fetch parent history
ParentState-->>AttemptCompletion: parentHistory
AttemptCompletion->>AttemptCompletion: Verify parent.status=delegated && awaitingChildId=childId?
alt Parent still awaiting child
AttemptCompletion->>ClineProvider: reopenParentFromDelegation
Note over ClineProvider: Check parent status & awaitingChildId (no blacklist)
ClineProvider-->>AttemptCompletion: success/failure
alt Reopen succeeded
ClineProvider-->>ParentState: resume parent
else Reopen failed
ClineProvider->>User: log warning, user must resume manually
end
else Parent no longer awaiting
AttemptCompletion->>User: log warning, fall back to user confirmation
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
d4995a0 to
2433c85
Compare
Description
Fixes #457 — a critical bug where subtask delegation never returns to the parent when two modes use different API configuration profiles (per-mode
modeApiConfigs).Problem
When an orchestrator/parent task delegates to a subtask whose mode uses a different
modeApiConfigsprofile than the parent, the flow silently stalls after the subtask completes. The parent is never resumed, requiring manual intervention.Root Cause
The per-mode profile switch runs
handleModeSwitch→activateProviderProfile, which leaves the parent task record asstatus: "active"whileawaitingChildIdstill points at the child. Two guards then reject because they requirestatus === "delegated":reopenParentFromDelegation()— an overly strictcancelledDelegationChildIds.has(childTaskId)guard blocks reopen permanently whencancelTask()fails to detach the parent (race condition inrunDelegationTransition). The child is added to the blacklist, and the secondattempt_completioncall can never recover.AttemptCompletionTooldelegation pre-check — only acceptsstatus === "delegated"for the parent, missing the"active"state that occurs after a per-mode profile switch.Changes
src/core/webview/ClineProvider.tscancelledDelegationChildIdscheck fromreopenParentFromDelegation()guard. The blacklist is redundant:cancelTask()sets parent status to"active"before adding to the blacklist. If the parent is still"delegated"and awaiting this child, it is safe to reopen. Thestatus + awaitingChildIdcheck already handles orphaned children.src/core/tools/AttemptCompletionTool.tsparentHistory.status === "delegated"andparentHistory.awaitingChildId === task.taskIdbefore callingdelegateToParent(). If parent detached (cancelled/resumed), skip delegation gracefully.didToolFailInCurrentTurnguard (&& !task.parentTaskId). Subtasks finishing their assigned work should not be blocked by a parent's error flag.historyLookupTaskIdvariable that could point at the wrong task.Testing
Summary by CodeRabbit