Conversation
…own-sourced openFile requests (Zoo-Code-Org#1762) * fix(webview-message-handler): enforce workspace containment for markdown-sourced openFile requests * fix(webview-message-handler): harden markdown containment against encoded and symlinked paths Address the automated review findings on the split PR: percent-decode tagged openFile paths to a fixed point at the containment boundary (openFile decodes after the check, so %2e%2e traversal would escape only after that later decode), and re-check containment on the real filesystem path so a workspace-internal symlink cannot resolve outside the workspace (fail closed; unresolvable targets reject). Tests now exercise the production isPathOutsideWorkspace against a mutable mock workspace (multi-root, no-folders cases) and a deterministic realpath model: encoded and double-encoded traversal rejected, legitimately encoded filenames still open, symlink escape rejected, file creation under a new directory allowed. * test(extension): pin the new containment mutants and fail-closed branches Mutation preflight on e98713a found blocking survivors in the new code: - direct tests for decodeUntrustedPathToStable (stable/fixed-point/invalid% escape/bound) and isRealPathOutsideWorkspace (no-folders, in-workspace, creation ancestor, symlink escape, EACCES fail-closed, unrealizable folder) cover the previously NoCoverage fail-closed returns - untagged percent-encoded paths stay undecoded at the boundary (legacy openFile decode applies exactly once) - kills the fromMarkdown gate mutant - a lexically outside path whose symlinked ancestor resolves inside is still rejected by the lexical check - kills the defense-in-depth ordering mutant - Stryker directives for the equivalent/bound mutants with concrete reasons * test(extension): cover the hostile-bound reject branch and the root guard - handler: a tagged encoding that never stabilizes inside the fixed-point bound is rejected at the boundary (covers the defensive null branch) - helper: the ancestor walk reaches the root guard when nothing exists and containment fails closed - locale-bundles.spec.ts imports all 18 common bundles and pins the path_outside_workspace key in each (completeness + puts the bundles into the coverage report for changed-line coverage) * fix(extension): type the realpath spy parameter as PathLike @types/node declares promises.realpath(path: PathLike, ...); string | URL is not assignable (PathLike also admits Buffer) * test(extension): assert the exact rejection message for the hostile-bound case Assert cannotAccessPathError with the raw path instead of only that an error was shown (CodeRabbit re-review, assertion identity) * chore: re-trigger CodeRabbit review * fix(extension): fail closed on dangling symlinks in realpath containment A dangling symlink inside a workspace folder fails realpath with ENOENT without being a nonexistent path: the ancestor walk would treat it as missing and check the (in-workspace) ancestor instead, while a creation flow (mkdir -p) would follow the link and escape the workspace. ENOENT from realpath now lstat's the entry first: an existing symlink whose target cannot be resolved fails closed; a genuinely absent entry keeps walking to its deepest existing ancestor. Unexpected lstat errors also fail closed. Adds the regression tests: dangling symlink rejected (handler and helper), a symlinked workspace root realized to the real root, and the lstat EACCES fail-closed path * chore(extension): document the equivalent lstat-symlink mutant Stryker marks the ConditionalExpression true/false replacements on the dangling-symlink check unobservable: lstat succeeding after a realpath ENOENT can only be a dangling symlink, so the condition is always true at every reachable point. The false replacement is pinned by the dangling-symlink tests; the directive documents the equivalence. --------- Co-authored-by: Eason Liang <easonliang28@gmail.com>
Extract the chat input model picker (ChatModelSelector + useChatModelSelector) into its own PR so each PR stays under the mutation-diff changed-lines gate. Mounts between ApiConfigSelector and AutoApproveDropdown in the chat composer action bar. Includes the Tab-navigation visual test (loop widened to 50 stops for the extra button) and the composer snapshots rendered with the selector present.
…t-model-selector source
…ion (Zoo-Code-Org#1818) * refactor(code-index): separate service factories and embedder validation * fix(code-index): localize validation errors and identify missing settings
* fix(task): keep the first abort reason * fix(task): apply first-reason-wins to both abort paths in catch block
…#1801) (Zoo-Code-Org#1812) * fix: reset didFinishAbortingStream for each request * test: wait for cancelTask to enter its wait before asserting pending
…Code-Org#1766) * refactor(code-index): introduce workspace scope behind registry Refs Zoo-Code-Org#1594 * test(code-index): cover registry retry after construction failure
…very (Zoo-Code-Org#1768) Centralize indexing status subscriptions in the extension scope and keep state ownership in workspace scopes. Honor the configured workspace root resolution when selecting the status source, with regression coverage for both selection strategies.
… race) - Enforce the organization allow-list on both the webview and the extension host - Make the selector trigger keyboard accessible (div -> button) - Correct Z.AI China API line handling so the mainland model list loads - Guard the OpenAI model list request against identity races - Show the currently saved model in the trigger
- Cover allow-list gating, keyboard interaction, race handling and trigger display - Align assertions with the div -> button markup change
- Add the selectModel label to all supported chat locales
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository: seeones/Zoo-Code/.coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
…ests - Enforce the organization model allow-list solely in ClineProvider.upsertProviderProfile so webview writes and direct callers (OAuth callbacks, sign-out) share a single enforcement point and the same user notification, instead of duplicating the check in webviewMessageHandler. - Add an internal bypassAllowList option reserved for Zoo Gateway credential writes (token refresh / sign-out) that ProfileValidator cannot map to a model id; it is never set from a webview-originated path. - Echo the caller requestId on Ollama/LM Studio/VSCode LM model replies and gate adoption per channel so a stale response cannot overwrite the active model list. - Compact the model selector hook (Object.fromEntries, optional chaining, merged comments) to keep the mutation-diff gate within budget. - Prune the now-unused any suppressions for webviewMessageHandler.spec.ts (35 -> 29).
Compact ChatModelSelector so the webview package stays within the mutation-diff changed-executable-line budget: fold the custom-model allow check into a derived boolean, merge the filter/return in the model-id memo, collapse the onSelect guards into one early return and drop a redundant return. Behaviour, DOM structure and allow-list gating are unchanged.
- ClineProvider: assert the organization allow-list rejects a disallowed profile in upsertProviderProfile and that a bypassAllowList write (Zoo Gateway credential cleanup) still succeeds. - webviewMessageHandler: assert the Ollama/LM Studio/VSCode LM replies echo the caller requestId, that a failing Zoo Gateway sign-out cleanup surfaces an error instead of a false success, and that upsertApiConfiguration delegates validation to the provider. - useChatModelSelector: assert replies carrying a superseded request id are dropped and only the request most recently issued per channel is adopted. - ChatModelSelector: assert the custom-model row is gated by the organization allow-list.
…n-out error ProfileValidator.getModelIdFromProfile now returns zooGatewayModelId so a listed Zoo Gateway model passes the organization allow-list without the internal bypass. Sign-out no longer reports an allow-list violation when the cleaned profile fails to persist (the allow-list check is bypassed on that call). Adds focused ProfileValidator and upsertProviderProfile coverage.
) * refactor(code-index): extract single-file preparation * refactor(code-index): use constructor-injected file preparation class * refactor(code-index): separate file preparation dependencies * test(code-index): cover platform-specific file preparation paths * refactor(code-index): inject preparation service objects * refactor(code-index): simplify file preparation stages * fix(code-index): decode prepared file bytes as UTF-8 * test(code-index): assert preparation receiver identity
…atomic Security Boundaries: only fall back to allow-all when no cloud instance exists; if a cloud instance is present but its allow-list cannot be read, reject the write (fail-closed) and notify the user. Persistence Integrity: snapshot prior profile/active state and the mode mapping before the activation writes; on failure, restore the previous profile, mode mapping, currentApiConfigName, listApiConfigMeta and provider settings, then rethrow so callers see the error. Tests: cover rejection when the allow-list is unavailable, allow-all when no cloud instance exists, and rollback after a post-save activation failure; complete the @roo-code/cloud mocks in ClineProvider.spec.ts and ClineProvider.sticky-mode.spec.ts with an allow-all getAllowList to match the real contract.
…ode-Org#695) (Zoo-Code-Org#700) * fix: streaming tool-call argument loss in NativeToolCallParser (Zoo-Code-Org#695) * chore: remove agent-generated changeset file per policy * test: add direct coverage for finalizeRawChunks() in NativeToolCallParser * fix: address PR Zoo-Code-Org#700 review feedback for tool-call streaming reassembly - Guard finalize results with not.toBeNull() in parallel-index and single-chunk tests so a null result fails instead of passing silently - Add reverse-ordering test (name -> buffered args -> id) covering the start-gate id requirement - Use name !== undefined recording plus a nameSeen flag in the start-gate as a defensive guard against an empty tool name - Clear rawChunkTracker in processFinishReason so finalizeRawChunks is a safe no-op; add a regression test asserting no double tool_call_end - Remove unrelated ask_followup_question wording change from PR scope - Remove prs/fix-toolcall-dropped-leading-deltas.md from the diff * fix: handle provider-emitted tool_call_end chunks during streaming Task.ts had no stream-level case for tool_call_end, so end chunks emitted by providers on finish_reason: "tool_calls" were silently dropped; tool calls only finalized at stream end via finalizeRawChunks(). Add a tool_call_end case so tools finalize and present during streaming, and extract the triplicated finalize/present logic into a shared idempotent helper. Correct the NativeToolCallParser test drive helper to finalize via finalizeRawChunks() (matching production) instead of processFinishReason(). * test: cover Task.finalizeStreamingToolCallById streaming finalization Add a focused spec that invokes the real Task.prototype.finalizeStreamingToolCallById via .call() with mocked presentAssistantMessage and NativeToolCallParser, covering the success, null-finalize (malformed JSON), untracked-id no-op, and idempotent re-finalize paths. Closes the codecov/patch gap on the new helper. * test: adapt tool-call streaming coverage to scoped parser state * test: type finalizeStreamingToolCallById fixtures as FinalizeStub * fix(task): defer finalized tool execution until history persists * refactor(parser): cut PR Zoo-Code-Org#700 to parser-only streaming scope Restore Task.ts persistence coordination and stream-time tool_call_end finalization to main; retain only the Zoo-Code-Org#695 parser fixes with their focused tests. --------- Co-authored-by: Elliott de Launay <edelauna@gmail.com>
… failure
getProfile({ name }) wraps both not-found and transient read failures in the same error, so a swallowed failure could be mistaken for absence. After a later saveConfig succeeded, a failing rollback would then call deleteConfig(name) and remove an existing profile and its secrets.
Probe existence explicitly via hasConfig: only deleteConfig when absence is confirmed; when the profile is known to exist but cannot be read, propagate before saveConfig and abort the write. Update the apiHandlerRebuild mock with hasConfig and add a test covering the read-failure abort path.
…ent (Zoo-Code-Org#1606) * fix(vscode-lm): trim oversized tool_results to fit the model context window Copilot's backend trims an over-window request without preserving tool_use/tool_result pairing, orphaning a tool_result and triggering a 400. Shrink oversized tool_result payloads middle-out on our side, and refuse a request that still cannot fit rather than send one we know is over-window. * fix(vscode-lm): restore em-dashes mangled during extraction * fix(vscode-lm): keep middleOutTruncate within maxChars for small limits * fix(vscode-lm): mark the over-budget refusal as a context-window error * fix(vscode-lm): remove unreachable truncation guard and strengthen tests Delete the target >= text.length guard, which cannot be reached. Move the middleOutTruncate JSDoc onto the function it documents. Make the fits-budget test actually assert no trimming, and assert the refusal error's reported character count so it fails if trimming is skipped. * refactor(vscode-lm): cache tool_result text, return remaining chars, share 400 constant F6: derive each tool_result's text once into a Map before sorting, removing the repeated filter+map+join in the comparator and the truncation loop. F7: return the running total as remainingChars so createMessage reuses it instead of re-scanning via estimateMessagesChars; a new test asserts the returned total matches an independent re-scan across eight paths. F8: export CONTEXT_WINDOW_EXCEEDED_STATUS from context-error-handling and use it on both the detector and the local over-budget refusal. * test(vscode-lm): widen raw-budget refusal margin to 1999 chars --------- Co-authored-by: Bertan Ari <bertanari@microsoft.com> Co-authored-by: edelauna <54631123+edelauna@users.noreply.github.com>
…e-Org#1778) Extract workspace enablement coordination and status publication, expose full workspace scopes, and replace direct manager access in webview handlers. Add toggle guard and default coverage, sync upstream main, and align the CodeRabbit test with upstream chat access policy. Refs Zoo-Code-Org#1594
* feat(openai): support GPT-6.1 Sol in native and Codex providers * fix(openai): use supported 872K Codex context for GPT-6.1 Sol * fix(build): rebuild dependents when dependency packages change --------- Co-authored-by: Elliott de Launay <edelauna@gmail.com>
…-Code-Org#1873) * feat: add community-approved advisory label for community code approvals (Zoo-Code-Org#1872) * test(workflow): cover community-approved label removal paths --------- Co-authored-by: @taltas <6816042+taltas@users.noreply.github.com> Co-authored-by: Elliott de Launay <edelauna@gmail.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…olution) (Zoo-Code-Org#1589) * fix(dev): use 127.0.0.1 instead of localhost for dev server to avoid IPv6 resolution issues * test(webview): assert HMR html targets the 127.0.0.1 dev server * test(webview): assert the dev-server probe targets the 127.0.0.1 health-check URL * test(webview): isolate the dev-server probe test from a stray .vite-port file and restore env in finally --------- Co-authored-by: hnbdr <hnbdr@users.noreply.github.com>
* fix(webview): batch repeated tool preambles Amp-Thread-ID: https://ampcode.com/threads/T-01a0aa02-b6de-7763-97b8-1650ea4b46da * fix(webview): preserve batching boundaries --------- Co-authored-by: Amp <amp@ampcode.com>
…ol-policy layer (Zoo-Code-Org#1724) * fix(mcp): validate native mcp_tool_use dispatch through the shared tool-policy layer The native mcp_tool_use arm now consults the shared validateToolUse layer (under the canonical use_mcp_tool name) before dispatching to the handler. A disabledTools or excludedTools entry naming use_mcp_tool is rejected at dispatch with a structured is_error tool_result and the server method is never invoked; the enabled path is unchanged. Issue: Zoo-Code-Org#1646 * test(mcp): cover native mcp validation guard branches; drop redundant optional chains Three tests pin the guard's deref-undefined fallback, the includedTools alias-map resolution, and the id-omitted rejection branch, taking patch coverage of the changed window from 78.9% to 100% and clearing codecov/patch. The modelInfo and toolError simplifications are behavior-preserving per the typed contracts (non-nullable getModel() return; toolError returns string). Mutation-diff survivor forms are eliminated: all 15 mutants in the regression map are killed. Issue: Zoo-Code-Org#1646
…oo-Code-Org#1852) `addToClineMessages` called `flushPostStateToWebviewThrottled()` for every message with `partial === true`. With lodash debounce configured `{ leading: true, trailing: true }`, a flush issued right after a leading-edge invocation has no pending trailing invocation to run, so it only cancels the trailing timer. The next call then hits the leading edge again and posts immediately, so the debounce never coalesced anything on the streaming path. Measured against lodash.debounce 4.0.8 with the provider's own settings (500ms wait, 1000ms maxWait), 20 messages arriving 100ms apart produced: with the interleaved flush: 20 full-state posts without it: 3 full-state posts Because `requiresImmediateState` matched every partial first chunk, throttling was effectively inert for tool-heavy tasks and the gray-screen OOM that Zoo-Code-Org#1078 set out to fix remained reproducible at high message counts. Drop `partial` from the condition. Partial `say` messages are safe on the throttled path: the trailing/maxWait post carries the message's current text, so a `messageUpdated` dropped for a `ts` the webview does not know yet is superseded rather than lost. Partial asks are unaffected — `Task#ask` adds them without `isAnswered`, so they keep flushing through the ask clause and retain the ordering guarantee unanswered asks depend on. The existing suite could not catch this: every Task-level test mocks the provider, so it asserted that flush was *called* rather than that state posts were actually coalesced. Retarget the partial-message test at the new contract and add a characterization test in ClineProvider.spec.ts that pins the debounce semantics against the real timer.
* chore(deps): update dependency mocha to v11.8.0 * fix(deps): override mocha diff to 8.0.4 --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Elliott de Launay <edelauna@gmail.com>
* fix(opencode-go): add DeepSeek V4.1 Flash metadata Amp-Thread-ID: https://ampcode.com/threads/T-01a0aa02-b6de-7763-97b8-1650ea4b46da * fix(opencode-go): enable DeepSeek Flash vision * test(api): pin DeepSeek V4.1 metadata --------- Co-authored-by: Amp <amp@ampcode.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Internal pre-flight PR to run the full CI suite (code-qa, mutation-diff, visual-regression, e2e) on the fork before syncing to upstream PR Zoo-Code-Org#1822.