Skip to content

Commit 79010dc

Browse files
authored
Merge branch 'main' into feat/jump-to-file-in-regular-chat-diff
2 parents d3fde81 + dcaa3cb commit 79010dc

266 files changed

Lines changed: 13121 additions & 1523 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.changeset/itchy-moles-thank.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"zoo-code": patch
3+
---
4+
5+
Fix bedrock DNS resolution when behind corporate proxy

.github/actions/setup-node-pnpm/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ inputs:
66
node-version:
77
description: "Node.js version to use"
88
required: false
9-
default: "20.20.2"
9+
default: "22.23.1"
1010
pnpm-version:
1111
description: "pnpm version to use"
1212
required: false

.github/pull_request_template.md

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,35 @@ Detail the steps to test your changes. This helps reviewers verify your work.
3838
- [ ] **Scope**: My changes are focused on the linked issue (one major feature/fix per PR).
3939
- [ ] **Self-Review**: I have performed a thorough self-review of my code.
4040
- [ ] **Testing**: New and/or updated tests have been added to cover my changes (if applicable).
41+
- [ ] **Visual Snapshot** (UI changes only): If a user would notice this change at a glance (layout, theme tokens, brand elements, empty/error states), I've added or updated a `*.visual.tsx` snapshot in `webview-ui/`. See `webview-ui/AGENTS.md` → "When a UI change needs a snapshot".
4142
- [ ] **Documentation Impact**: I have considered if my changes require documentation updates (see "Documentation Updates" section below).
4243
- [ ] **Contribution Guidelines**: I have read and agree to the [Contributor Guidelines](/CONTRIBUTING.md).
4344

44-
### Screenshots / Videos
45+
### Visual Snapshots
4546

4647
<!--
47-
For UI changes, please provide before-and-after screenshots or a short video of the *actual results*.
48-
This greatly helps in understanding the visual impact of your changes.
48+
For UI changes to static rendered state, the primary artifact is a committed
49+
Playwright CT snapshot (`*.visual.tsx` in `webview-ui/`) — that baseline
50+
becomes durable regression coverage for the surface. See
51+
`webview-ui/AGENTS.md` for what deserves a snapshot.
52+
53+
Before/after screenshots pasted here are welcome as a review aid but are not a
54+
substitute for the committed baseline. If a snapshot is possible, prefer the
55+
snapshot.
56+
-->
57+
58+
### Videos (interaction / animation only)
59+
60+
<!--
61+
Snapshots cannot capture motion or multi-step flows. Attach a short screen
62+
recording here when reviewers need to see:
63+
- A new interactive flow (dropdown, form, dialog progression)
64+
- Animation, transition, or timing behavior
65+
- A regression that only manifests during interaction
66+
67+
Videos are a review aid, not regression coverage. If the *result* of the
68+
interaction has a distinct rendered state worth protecting, still commit a
69+
`*.visual.tsx` snapshot of that end-state alongside the video.
4970
-->
5071

5172
### Documentation Updates

.github/workflows/code-qa.yml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,25 +135,32 @@ jobs:
135135
# lanes for behavioral confidence, but duplicating coverage uploads
136136
# there mostly adds Codecov overhead without changing pass/fail
137137
# behavior.
138-
# Coverage is uploaded in three separate steps so each LCOV gets the
138+
# Coverage is uploaded in separate steps so each LCOV gets the
139139
# correct flag set. Codecov double-counts overlapping lines when a
140140
# single upload carries multiple flags whose paths overlap, so the
141-
# two core lanes (which both cover packages/core/src/**) must be
142-
# uploaded individually with their own lane flag.
141+
# core lanes and webview lane must be uploaded individually with
142+
# their own flag.
143143
# See https://docs.codecov.com/docs/flags
144144
- name: Upload non-core coverage to Codecov
145145
if: matrix.upload-coverage
146146
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4
147147
with:
148148
files: >-
149149
src/coverage/lcov.info,
150-
webview-ui/coverage/lcov.info,
151150
packages/cloud/coverage/lcov.info,
152151
packages/telemetry/coverage/lcov.info,
153152
apps/cli/coverage/lcov.info
154153
disable_search: true
155154
flags: ${{ matrix.codecov-flag }}
156155
token: ${{ secrets.CODECOV_TOKEN }}
156+
- name: Upload webview JSDOM coverage to Codecov
157+
if: matrix.upload-coverage
158+
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4
159+
with:
160+
files: webview-ui/coverage/lcov.info
161+
disable_search: true
162+
flags: webview-ui
163+
token: ${{ secrets.CODECOV_TOKEN }}
157164
- name: Upload core unit coverage to Codecov
158165
if: matrix.upload-coverage
159166
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4

.github/workflows/e2e.yml

Lines changed: 101 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,100 @@ jobs:
4545
VERSION=$(node -p 'require("./apps/vscode-e2e/package.json").devDependencies["@types/vscode"]')
4646
echo "version=$VERSION" >> $GITHUB_OUTPUT
4747
48-
- name: Cache VS Code test binary
48+
- name: Restore VS Code test binary cache
4949
if: github.event_name != 'pull_request' || steps.e2e-marker.outputs.cache-hit != 'true'
50-
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
50+
id: vscode-cache
51+
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
52+
with:
53+
path: |
54+
apps/vscode-e2e/.vscode-test/
55+
key: vscode-test-${{ runner.os }}-${{ steps.vscode-ver.outputs.version }}-v1
56+
# Fall back to the most recent stale binary so a version bump or cache
57+
# eviction doesn't force a download when the VS Code CDN is unreachable.
58+
restore-keys: |
59+
vscode-test-${{ runner.os }}-
60+
61+
- name: Probe VS Code download endpoints
62+
if: (github.event_name != 'pull_request' || steps.e2e-marker.outputs.cache-hit != 'true') && steps.vscode-cache.outputs.cache-hit != 'true'
63+
id: vscode-probe
64+
# The version-resolution API and the archive CDN are different hosts. The
65+
# archive URL 302-redirects to the CDN, so a HEAD probe that follows the
66+
# redirect covers both. The fallback engages when either is unreachable.
67+
run: |
68+
API_OK=false
69+
CDN_OK=false
70+
if curl -sf --max-time 10 https://update.code.visualstudio.com/api/releases/stable > /dev/null; then
71+
API_OK=true
72+
fi
73+
if curl -sfIL --max-time 20 -o /dev/null "https://update.code.visualstudio.com/${{ steps.vscode-ver.outputs.version }}/linux-x64/stable"; then
74+
CDN_OK=true
75+
fi
76+
if [ "$API_OK" = "true" ] && [ "$CDN_OK" = "true" ]; then
77+
echo "reachable=true" >> "$GITHUB_OUTPUT"
78+
else
79+
echo "reachable=false" >> "$GITHUB_OUTPUT"
80+
echo "::warning::VS Code download endpoints unreachable (api=$API_OK, cdn=$CDN_OK); will try the stale cached binary"
81+
fi
82+
83+
# @vscode/test-electron only skips its live version-resolution request when the
84+
# requested version already exists in .vscode-test/. On an exact-key miss it calls
85+
# the update API before its download retry loop, so an unreachable CDN fails the
86+
# job before any test runs. When the endpoints are down, point the runner at the
87+
# stale binary restored above (runTest.ts honors VSCODE_VERSION) so the suite
88+
# still runs.
89+
- name: Fall back to stale VS Code binary when CDN is unreachable
90+
if: (github.event_name != 'pull_request' || steps.e2e-marker.outputs.cache-hit != 'true') && steps.vscode-cache.outputs.cache-hit != 'true' && steps.vscode-probe.outputs.reachable == 'false'
91+
id: vscode-fallback
92+
run: |
93+
STALE=$(ls -d apps/vscode-e2e/.vscode-test/vscode-linux-x64-* 2>/dev/null | sort -V | tail -n 1 || true)
94+
if [ -n "$STALE" ]; then
95+
echo "VSCODE_VERSION=${STALE##*-}" >> "$GITHUB_ENV"
96+
echo "used=true" >> "$GITHUB_OUTPUT"
97+
echo "VS Code download endpoints are unreachable; falling back to cached VS Code ${STALE##*-}"
98+
else
99+
echo "::warning::VS Code download endpoints are unreachable and no cached binary is available; the download step will retry but may fail"
100+
fi
101+
102+
# Retry only the binary download: version resolution and the archive fetch are
103+
# the network-fragile parts. Genuine test failures should fail fast, so the
104+
# test step itself is deliberately not retried.
105+
- name: Download VS Code test binary
106+
if: github.event_name != 'pull_request' || steps.e2e-marker.outputs.cache-hit != 'true'
107+
id: vscode-download
108+
run: |
109+
cd apps/vscode-e2e
110+
for attempt in 1 2 3; do
111+
if node -e "const { downloadAndUnzipVSCode } = require('@vscode/test-electron'); const version = process.env.VSCODE_VERSION || require('./package.json').devDependencies['@types/vscode']; downloadAndUnzipVSCode(version).catch((err) => { console.error(err); process.exit(1); });"; then
112+
exit 0
113+
fi
114+
echo "VS Code download attempt ${attempt} failed"
115+
if [ "$attempt" -lt 3 ]; then
116+
sleep 15
117+
fi
118+
done
119+
exit 1
120+
121+
# restore-keys can bring back older binaries alongside the one just
122+
# downloaded; keep only the effective version so each saved cache entry
123+
# stays at one binary instead of growing with every version bump.
124+
- name: Prune stale VS Code binaries
125+
if: github.event_name != 'pull_request' || steps.e2e-marker.outputs.cache-hit != 'true'
126+
run: |
127+
EFFECTIVE="${VSCODE_VERSION:-${{ steps.vscode-ver.outputs.version }}}"
128+
for dir in apps/vscode-e2e/.vscode-test/vscode-linux-x64-*; do
129+
[ -e "$dir" ] || continue
130+
if [ "$(basename "$dir")" != "vscode-linux-x64-$EFFECTIVE" ]; then
131+
echo "Pruning stale VS Code binary $(basename "$dir")"
132+
rm -rf "$dir"
133+
fi
134+
done
135+
136+
# Skip the save when the stale-binary fallback ran: the pinned-version key
137+
# must not be populated with an older binary.
138+
- name: Save VS Code test binary cache
139+
if: (github.event_name != 'pull_request' || steps.e2e-marker.outputs.cache-hit != 'true') && steps.vscode-cache.outputs.cache-hit != 'true' && steps.vscode-fallback.outputs.used != 'true'
140+
continue-on-error: true
141+
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
51142
with:
52143
path: |
53144
apps/vscode-e2e/.vscode-test/
@@ -59,12 +150,18 @@ jobs:
59150
if: github.event_name != 'pull_request' || steps.e2e-marker.outputs.cache-hit != 'true'
60151
run: xvfb-run -a pnpm --filter @roo-code/vscode-e2e test:ci:mock
61152

153+
- name: Explain skipped mocked E2E pass marker
154+
if: steps.e2e-marker.outputs.cache-hit != 'true' && steps.run-e2e.outcome == 'success' && steps.vscode-fallback.outputs.used == 'true'
155+
run: echo "Skipping mocked E2E pass marker because tests ran against a stale cached VS Code binary (VS Code download endpoints unreachable)."
156+
62157
- name: Write mocked E2E pass marker
63-
if: steps.e2e-marker.outputs.cache-hit != 'true' && steps.run-e2e.outcome == 'success'
158+
# Skip when the stale-binary fallback ran: a pass against an older VS Code
159+
# must not mint a marker for the intended-version source hash.
160+
if: steps.e2e-marker.outputs.cache-hit != 'true' && steps.run-e2e.outcome == 'success' && steps.vscode-fallback.outputs.used != 'true'
64161
run: mkdir -p .cache/e2e-pass && date -u > .cache/e2e-pass/passed
65162

66163
- name: Save mocked E2E pass marker
67-
if: steps.e2e-marker.outputs.cache-hit != 'true' && steps.run-e2e.outcome == 'success'
164+
if: steps.e2e-marker.outputs.cache-hit != 'true' && steps.run-e2e.outcome == 'success' && steps.vscode-fallback.outputs.used != 'true'
68165
continue-on-error: true
69166
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
70167
with:
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: Webview Visual Regression
2+
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
types: [opened, reopened, ready_for_review, synchronize]
7+
paths:
8+
- "webview-ui/**"
9+
- "src/shared/**"
10+
- "package.json"
11+
- "pnpm-lock.yaml"
12+
- ".github/workflows/visual-regression.yml"
13+
merge_group:
14+
types: [checks_requested]
15+
16+
concurrency:
17+
group: ${{ github.workflow }}-${{ github.ref }}
18+
cancel-in-progress: true
19+
20+
permissions:
21+
contents: read
22+
23+
jobs:
24+
webview-visual:
25+
runs-on: ubuntu-latest
26+
timeout-minutes: 10
27+
container:
28+
image: mcr.microsoft.com/playwright:v1.60.0-noble@sha256:9bd26ad900bb5e0f4dee75839e957a89ae89c2b7ab1e76050e559790e946b948
29+
options: --ipc=host
30+
steps:
31+
- name: Checkout code
32+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
33+
with:
34+
persist-credentials: false
35+
- name: Setup Node.js and pnpm
36+
uses: ./.github/actions/setup-node-pnpm
37+
with:
38+
install-args: "--frozen-lockfile"
39+
- name: Run webview visual tests
40+
run: pnpm --filter @roo-code/vscode-webview test:visual
41+
- name: Upload visual test coverage to Codecov
42+
if: always()
43+
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4
44+
with:
45+
files: webview-ui/coverage-ct/lcov.info
46+
disable_search: true
47+
flags: webview-ui-ct
48+
token: ${{ secrets.CODECOV_TOKEN }}
49+
- name: Upload visual test artifacts
50+
if: failure()
51+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
52+
with:
53+
name: webview-visual-regression
54+
path: |
55+
webview-ui/playwright-report
56+
webview-ui/test-results
57+
if-no-files-found: ignore

.nvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
20.20.2
1+
22.23.1

.tool-versions

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
pnpm 10.8.1
2-
nodejs 20.20.2
2+
nodejs 22.23.1

AGENTS.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ This file provides guidance to agents when working with code in this repository.
55
- Settings View Pattern: When working on `SettingsView`, inputs must bind to the local `cachedState`, NOT the live `useExtensionState()`. The `cachedState` acts as a buffer for user edits, isolating them from the `ContextProxy` source-of-truth until the user explicitly clicks "Save". Wiring inputs directly to the live state causes race conditions.
66
- Changesets: Do NOT create `.changeset` files for each commit or code change. Changesets are managed separately by maintainers and should not be generated by agents during normal development.
77

8+
## ESLint Suppressions
9+
10+
`src/eslint-suppressions.json` tracks per-file counts of suppressed lint rules. Suppression counts must never increase. When touching a file, prefer reducing its count when the fix is local and low-risk; avoid broad unrelated cleanup.
11+
12+
When writing new code:
13+
14+
- Fix lint violations in the new code rather than suppressing them.
15+
- Avoid `as any`; use typed APIs directly (e.g. `RooCodeEventName.X` constants with typed `on()`/`listenerCount()`), or bracket notation (`obj["privateField"]`) to access private members. Prefer precise test doubles or `unknown` with a type guard over double assertions (`as unknown as T`); use double assertions only as a last resort, with a comment explaining why.
16+
- Avoid floating promises; add `void`, `await`, or `.catch()` as appropriate.
17+
- After editing a file, run `pnpm --dir src exec eslint --prune-suppressions --max-warnings=0 <relative-file>` and confirm the count for that file did not increase.
18+
- If a suppression is truly unavoidable (e.g. `vi.spyOn(Cls.prototype as any, "privateMethod")` where no typed alternative exists), document why in a comment next to the cast.
19+
820
## Test Placement Guidance
921

1022
Prefer the narrowest test layer that proves the behavior. This follows standard test-pyramid guidance: keep most coverage in fast, focused tests; add integration tests for cross-module contracts; reserve end-to-end tests for full workflow confidence.

CHANGELOG.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,32 @@
11
# Zoo Code Changelog
22

3+
## [3.72.0]
4+
5+
### Minor Changes
6+
7+
- Add the Moonshot provider with live model discovery, streaming, model metadata, and a model picker (PR #857 by @grizmin)
8+
- Add the Kimi Code provider with OAuth device-flow authentication (PR #945 by @taltas)
9+
- Add Claude Opus 5 support across all providers (PR #1010 by @app/zoomote)
10+
- Add Kimi K3 to the Moonshot and OpenCode Go providers (#932 by @navedmerchant, PR #996 by @app/zoomote)
11+
- Add Gemini 3.6 Flash model support (PR #975 by @app/zoomote)
12+
- Add MiniMax-M3 model support (#888 by @RayWinter0816, PR #946 by @app/zoomote)
13+
- Add a safe way to abandon interrupted subtasks by severing stale parent-child links and surfacing delegation status (#559 by @edelauna, PR #935 by @edelauna)
14+
- Add Dart support to codebase indexing (#940 by @WebMad, PR #941 by @WebMad)
15+
- Fix codebase indexing for plain-text files (#931 by @tool-buddy, PR #938 by @WebMad)
16+
- Enable image input for DeepSeek V4 models (#964 by @grizmin, PR #963 by @grizmin)
17+
- Fix ChatGPT OAuth requests for GPT-5.6 Luna being rejected by the Codex backend (PR #889 by @taltas)
18+
- Preserve `reasoning_content` for known reasoning model families when using LiteLLM (#891 by @daewoongoh, PR #899 by @daewoongoh)
19+
- Fix task-history cache invalidation races by routing `invalidate()` and `invalidateAll()` through the task-history lock (#698 by @edelauna, PR #912 by @morgan-coded)
20+
- Fix Settings mode changes by synchronizing the local `cachedState` editing buffer (#914 by @easonLiangWorldedtech, PR #925 by @easonLiangWorldedtech)
21+
- Dismiss the welcome screen after successful Zoo Gateway sign-in (#961 by @JohnCanty, PR #962 by @JamesRobert20)
22+
- Add `CompletePromptOptions` to the `completePrompt` API so callers can configure prompt completion (#615 by @edelauna, PR #901 by @easonLiangWorldedtech)
23+
- Centralize provider identifiers into canonical shared types (#951 by @WebMad, PR #952 by @WebMad)
24+
- Refactor provider categories to use canonical provider identifiers (PR #989 by @WebMad)
25+
- Remove obsolete MCP server-creation translations (#895 by @edelauna, PR #943 by @WebMad)
26+
- Add regression coverage for resuming interrupted subtasks (#566 by @myk1yt, PR #911 by @edelauna)
27+
- Upload coverage reports as GitHub Actions artifacts to simplify CI debugging (PR #939 by @app/zoomote)
28+
- Update `esbuild-wasm` to v0.28.1 (PR #829 by @app/renovate)
29+
330
## [3.70.0]
431

532
### Minor Changes

0 commit comments

Comments
 (0)