Skip to content

Commit 8d86d53

Browse files
committed
Merge remote-tracking branch 'origin/main' into feat/kimi-k3-support
2 parents 51d9eb7 + 7af1a8a commit 8d86d53

181 files changed

Lines changed: 5847 additions & 1312 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.

.github/workflows/code-qa.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,17 @@ jobs:
170170
disable_search: true
171171
flags: ${{ matrix.codecov-flag }},core-integration
172172
token: ${{ secrets.CODECOV_TOKEN }}
173+
- name: Upload coverage reports to GitHub
174+
if: matrix.upload-coverage
175+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
176+
with:
177+
name: coverage-reports-${{ matrix.name }}
178+
path: |
179+
src/coverage/lcov.info
180+
webview-ui/coverage/lcov.info
181+
packages/cloud/coverage/lcov.info
182+
packages/telemetry/coverage/lcov.info
183+
apps/cli/coverage/lcov.info
184+
packages/core/coverage/unit/lcov.info
185+
packages/core/coverage/integration/lcov.info
186+
retention-days: 7

CHANGELOG.md

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

3+
## [3.70.0]
4+
5+
### Minor Changes
6+
7+
- Add Kenari as a first-class provider, an Indonesian OpenAI-compatible AI gateway billed in Rupiah covering Claude, GPT, DeepSeek, GLM, Kimi and more (#792 by @doedja, PR #793 by @doedja)
8+
- Add OpenAI GPT-5.6 family support (sol, terra, luna) across both OpenAI Codex and OpenAI Native provider paths (#871 by @xRaTcHeT302, PR #876 by @navedmerchant)
9+
- Add Grok 4.5 support and fix a latent xAI reasoning-effort format bug affecting Grok 4 Mini (#866 by @navedmerchant, PR #867 by @navedmerchant)
10+
- Surface the context-compaction button and context window progress bar in the collapsed task header so context pressure can be monitored and acted on without expanding it (#606 by @awschmeder, PR #680 by @awschmeder)
11+
- Fix(terminal): fix output loss and premature task completion on cold terminals by reading command output only after shell execution actually starts (#800 by @juneleung, PR #834 by @edelauna)
12+
- Fix(zoo-gateway): enable image attach for Zoo Gateway and Vercel AI Gateway models based on live vision-capability tags instead of a static allowlist (PR #897 by @JamesRobert20)
13+
- Chore(deps): routine dependency updates (PRs #807-#828 by @app/renovate)
14+
315
## [3.68.0]
416

517
### Minor Changes

README.md

Lines changed: 18 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,35 +16,17 @@
1616
1717
## We are Zoo Code
1818

19-
> You may have seen the
20-
> [recent announcement](https://x.com/mattrubens/status/2046636598859559114)
21-
> from the Roo team 🦘🦘🦘. The TLDR is the team is winding down active Roo
22-
> Code development as they focus on [Roomote](https://roomote.dev/). That news
23-
> was difficult for many Roo users, this plugin means a lot to this community.
19+
> Zoo Code continues development of this project after the Roo team wound down
20+
> active Roo Code work to focus on [Roomote](https://roomote.dev/). Thank you
21+
> to the Roo team for everything they built.
2422
>
25-
> We want to thank the entire Roo team for the work they put into this plugin.
26-
> We won't call out each person by name here, but we can all agree they are
27-
> exceptional developers and, just as importantly, incredible people. Thank you
28-
> to the Roo team.
29-
>
30-
> As Roo coders, we come in all kinds of shapes and sizes. Some of us are using
31-
> it professionally in our day-to-day work, some are using it to tinker and
32-
> scheme unimaginably complicated workflows. Some are using it to improve Roo
33-
> itself while others are using it to improve the very models that Roo is using
34-
> (super meta). The point we are making is that the community is
35-
> diverse, and although a kangaroo 🦘🦘🦘 is a distinguished and noble animal,
36-
> we felt a "Zoo" 🐘🦡🦒🦓🦛🦧🦭🦦 of different species better reflected this
37-
> diversity of the plugin's users.
38-
>
39-
> So we would like to announce that **Zoo Code** will continue development on
40-
> this important project. The core team is a group of developers who contributed
41-
> to Roo previously and care deeply about this plugin. We will continue to make
42-
> model updates, fix bugs, and release features. But more than anything, we plan
43-
> to listen to the community that made this plugin so special. Feel free to join
44-
> us on [Discord](https://discord.gg/VxfP4Vx3gX),
23+
> The core team is a group of developers who contributed to Roo previously and
24+
> care deeply about this plugin. We will continue to make model updates, fix
25+
> bugs, and release features, and we plan to listen closely to the community
26+
> that made this plugin so special. Join us on
27+
> [Discord](https://discord.gg/VxfP4Vx3gX),
4528
> [Reddit](https://www.reddit.com/r/ZooCode), or
46-
> [open a PR or issue](https://github.com/Zoo-Code-Org/Zoo-Code), and above all,
47-
> please stay involved, connected, and active as a community.
29+
> [open a PR or issue](https://github.com/Zoo-Code-Org/Zoo-Code).
4830
>
4931
> _-Zoo Code Team_
5032
@@ -53,15 +35,15 @@
5335
You can find a quick guide for migrating from Roo Code to Zoo Code in the [Roo→Zoo migration guide](https://docs.zoocode.dev/roo-to-zoo-migration). We plan to try and help users as they transition over, we have our [Reddit](https://www.reddit.com/r/ZooCode) and [Discord](https://discord.gg/VxfP4Vx3gX)
5436
for this exact support, so if you are having problems or if you have question, jump on and ask.
5537

56-
## What's New in v3.68.0
38+
## What's New in v3.70.0
5739

58-
- **Friendli provider with GLM-5.2 support**use the latest GLM model through Friendli.
59-
- **Native Ollama thinking/reasoning support**preserve reasoning output end-to-end when you use Ollama models.
60-
- **Anthropic custom `apiModelId` fix**custom Anthropic model IDs now stay selected instead of silently falling back to `claude-sonnet-4-5`.
61-
- Fix: Ollama provider tool result handling and premature context condensing.
62-
- Fix: preserve the parent-child task link when a delegated subtask is interrupted.
63-
- Improve Anthropic Vertex Claude content block handling for more reliable responses.
64-
- CI, nightly publishing, and dependency/tooling updates.
40+
- **OpenAI GPT-5.6 family**`Sol`, `Terra`, and `Luna` are now available across both the OpenAI Codex and OpenAI Native provider paths.
41+
- **Grok 4.5 support**xAI's new flagship model, plus a reasoning-effort format fix that also benefits Grok 4 Mini.
42+
- **Kenari provider support**a first-class, OpenAI-compatible AI gateway billed in Rupiah covering Claude, GPT, DeepSeek, GLM, Kimi and more.
43+
- Surface the context-compaction button and context window progress bar in the collapsed task header.
44+
- Fix: terminal output loss and premature task completion on cold terminals.
45+
- Fix: image attach for Zoo Gateway and Vercel AI Gateway models now follows live vision-capability tags instead of a static allowlist.
46+
- Dependency and tooling updates.
6547

6648
<details>
6749
<summary>🌐 Available languages</summary>
@@ -85,7 +67,7 @@ for this exact support, so if you are having problems or if you have question, j
8567
- [简体中文](locales/zh-CN/README.md)
8668
- [繁體中文](locales/zh-TW/README.md)
8769
- ...
88-
</details>
70+
</details>
8971

9072
---
9173

apps/vscode-e2e/src/fixtures/subtasks.ts

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ const SUBTASK_PARENT_MARKER = "SUBTASK_PARENT_CANCELLATION_SMOKE"
77
const SUBTASK_CHILD_MARKER = "SUBTASK_CHILD_CALCULATOR_SMOKE"
88
const SUBTASK_INTERRUPT_PARENT_MARKER = "SUBTASK_PARENT_INTERRUPT_RESUME"
99
const SUBTASK_INTERRUPT_CHILD_MARKER = "SUBTASK_CHILD_INTERRUPT_RESUME"
10+
export const SUBTASK_API_HANG_PARENT_MARKER = "SUBTASK_PARENT_API_HANG_INTERRUPT_RESUME"
11+
export const SUBTASK_API_HANG_CHILD_MARKER = "SUBTASK_CHILD_API_HANG_INTERRUPT_RESUME"
1012
const SUBTASK_FAST_PARENT_MARKER = "SUBTASK_PARENT_IMMEDIATE_COMPLETION"
1113
const SUBTASK_FAST_CHILD_MARKER = "SUBTASK_CHILD_IMMEDIATE_COMPLETION"
1214
const SUBTASK_XPROFILE_PARENT_MARKER = "SUBTASK_PARENT_CROSS_PROFILE"
@@ -24,13 +26,29 @@ export const SUBTASK_INTERRUPT_PARENT_PROMPT = `${SUBTASK_INTERRUPT_PARENT_MARKE
2426
export const SUBTASK_INTERRUPT_CHILD_FOLLOWUP_ANSWER = "9"
2527
export const SUBTASK_INTERRUPT_PARENT_RESULT = "Interrupted parent resumed"
2628

29+
const SUBTASK_API_HANG_CHILD_PROMPT = `${SUBTASK_API_HANG_CHILD_MARKER}: Complete with the exact result "Hung child completed".`
30+
export const SUBTASK_API_HANG_PARENT_PROMPT = `${SUBTASK_API_HANG_PARENT_MARKER}: Use the new_task tool exactly once. Create an ask-mode subtask with this exact message: "${SUBTASK_API_HANG_CHILD_PROMPT}" Do not answer directly. When the subtask returns, complete with the exact result "API hang parent resumed".`
31+
export const SUBTASK_API_HANG_RESUME_MESSAGE = "Continue after provider hang."
32+
export const SUBTASK_API_HANG_CHILD_RESULT = "Hung child completed"
33+
export const SUBTASK_API_HANG_PARENT_RESULT = "API hang parent resumed"
34+
35+
// Abandon-subtask scenario (#559) — separate markers to avoid sequenceIndex collisions with the
36+
// interrupted-child-resumes tests above, which exhaust the sequence count for INTERRUPT markers.
37+
const SUBTASK_ABANDON_PARENT_MARKER = "SUBTASK_PARENT_ABANDON_SEVER"
38+
const SUBTASK_ABANDON_CHILD_MARKER = "SUBTASK_CHILD_ABANDON_SEVER"
39+
const SUBTASK_ABANDON_CHILD_PROMPT = `${SUBTASK_ABANDON_CHILD_MARKER}: Ask the user exactly this follow-up question: What is the square root of 81? After the user answers, complete with only the answer.`
40+
export const SUBTASK_ABANDON_PARENT_PROMPT = `${SUBTASK_ABANDON_PARENT_MARKER}: Use the new_task tool exactly once. Create an ask-mode subtask with this exact message: "${SUBTASK_ABANDON_CHILD_PROMPT}" Do not answer directly.`
41+
export const SUBTASK_ABANDON_CHILD_FOLLOWUP_ANSWER = "9"
42+
2743
const SUBTASK_XPROFILE_SAME_CHILD_PROMPT = `${SUBTASK_XPROFILE_SAME_CHILD_MARKER}: Complete immediately with the exact result "Same-profile child completed".`
2844
const SUBTASK_XPROFILE_DIFFERENT_CHILD_PROMPT = `${SUBTASK_XPROFILE_DIFFERENT_CHILD_MARKER}: Complete immediately with the exact result "Different-profile child completed".`
2945
export const SUBTASK_XPROFILE_PARENT_PROMPT = `${SUBTASK_XPROFILE_PARENT_MARKER}: First use new_task to create a code-mode subtask with this exact message: "${SUBTASK_XPROFILE_SAME_CHILD_PROMPT}" After it returns, create an ask-mode subtask with the next instructions you receive.`
3046
export const SUBTASK_XPROFILE_SAME_CHILD_RESULT = "Same-profile child completed"
3147
export const SUBTASK_XPROFILE_DIFFERENT_CHILD_RESULT = "Different-profile child completed"
3248
export const SUBTASK_XPROFILE_PARENT_RESULT = "Sequential cross-profile parent resumed"
3349

50+
const apiHangChildMatch = new RegExp(SUBTASK_API_HANG_CHILD_MARKER)
51+
3452
const requestContains = (req: ChatCompletionRequest, expected: string[]) => {
3553
const rawRequest = JSON.stringify(req)
3654
return expected.every((text) => rawRequest.includes(text))
@@ -167,6 +185,79 @@ export function addSubtaskFixtures(mock: InstanceType<typeof LLMock>) {
167185
},
168186
})
169187

188+
mock.addFixture({
189+
match: {
190+
userMessage: new RegExp(SUBTASK_API_HANG_PARENT_MARKER),
191+
sequenceIndex: 0,
192+
},
193+
response: {
194+
toolCalls: [
195+
{
196+
name: "new_task",
197+
arguments: JSON.stringify({
198+
mode: "ask",
199+
message: SUBTASK_API_HANG_CHILD_PROMPT,
200+
}),
201+
id: "call_api_hang_parent_new_task_001",
202+
},
203+
],
204+
},
205+
})
206+
207+
mock.addFixture({
208+
match: {
209+
userMessage: apiHangChildMatch,
210+
sequenceIndex: 0,
211+
},
212+
// Keep the first child response pending long enough for the e2e test to cancel an in-flight API request.
213+
latency: 15_000,
214+
response: {
215+
toolCalls: [
216+
{
217+
name: "attempt_completion",
218+
arguments: JSON.stringify({ result: SUBTASK_API_HANG_CHILD_RESULT }),
219+
id: "call_api_hang_child_completion_002",
220+
},
221+
],
222+
},
223+
})
224+
225+
mock.addFixture({
226+
match: {
227+
userMessage: apiHangChildMatch,
228+
sequenceIndex: 1,
229+
},
230+
response: {
231+
toolCalls: [
232+
{
233+
name: "attempt_completion",
234+
arguments: JSON.stringify({ result: SUBTASK_API_HANG_CHILD_RESULT }),
235+
id: "call_api_hang_child_completion_003",
236+
},
237+
],
238+
},
239+
})
240+
241+
mock.addFixture({
242+
match: {
243+
predicate: (req: ChatCompletionRequest) =>
244+
requestContains(req, [
245+
SUBTASK_API_HANG_PARENT_MARKER,
246+
"call_api_hang_parent_new_task_001",
247+
SUBTASK_API_HANG_CHILD_RESULT,
248+
]),
249+
},
250+
response: {
251+
toolCalls: [
252+
{
253+
name: "attempt_completion",
254+
arguments: JSON.stringify({ result: SUBTASK_API_HANG_PARENT_RESULT }),
255+
id: "call_api_hang_parent_completion_004",
256+
},
257+
],
258+
},
259+
})
260+
170261
// Issue #457 sequence: a same-profile child returns first, then the resumed
171262
// parent delegates to a child whose mode uses a different API profile.
172263
mock.addFixture({
@@ -354,4 +445,67 @@ export function addSubtaskFixtures(mock: InstanceType<typeof LLMock>) {
354445
],
355446
},
356447
})
448+
449+
// Abandon-subtask scenario (#559)
450+
mock.addFixture({
451+
match: {
452+
userMessage: new RegExp(SUBTASK_ABANDON_PARENT_MARKER),
453+
sequenceIndex: 0,
454+
},
455+
response: {
456+
toolCalls: [
457+
{
458+
name: "new_task",
459+
arguments: JSON.stringify({
460+
mode: "ask",
461+
message: SUBTASK_ABANDON_CHILD_PROMPT,
462+
}),
463+
id: "call_abandon_parent_new_task_001",
464+
},
465+
],
466+
},
467+
})
468+
469+
mock.addFixture({
470+
match: {
471+
predicate: (req: ChatCompletionRequest) =>
472+
requestContains(req, [SUBTASK_ABANDON_CHILD_MARKER]) &&
473+
!requestContains(req, [SUBTASK_ABANDON_PARENT_MARKER]) &&
474+
!requestContains(req, ["call_abandon_child_followup_001"]) &&
475+
!requestContains(req, [`<user_message>\\n${SUBTASK_ABANDON_CHILD_FOLLOWUP_ANSWER}\\n</user_message>`]),
476+
},
477+
response: {
478+
toolCalls: [
479+
{
480+
name: "ask_followup_question",
481+
arguments: JSON.stringify({
482+
question: "What is the square root of 81?",
483+
follow_up: [{ text: SUBTASK_ABANDON_CHILD_FOLLOWUP_ANSWER }],
484+
}),
485+
id: "call_abandon_child_followup_001",
486+
},
487+
],
488+
},
489+
})
490+
491+
mock.addFixture({
492+
match: {
493+
predicate: (req: ChatCompletionRequest) =>
494+
toolResultContains(req, "call_abandon_child_followup_001", [SUBTASK_ABANDON_CHILD_FOLLOWUP_ANSWER]) ||
495+
requestContains(req, ["call_abandon_child_followup_001", SUBTASK_ABANDON_CHILD_FOLLOWUP_ANSWER]) ||
496+
requestContains(req, [
497+
SUBTASK_ABANDON_CHILD_MARKER,
498+
`<user_message>\\n${SUBTASK_ABANDON_CHILD_FOLLOWUP_ANSWER}\\n</user_message>`,
499+
]),
500+
},
501+
response: {
502+
toolCalls: [
503+
{
504+
name: "attempt_completion",
505+
arguments: JSON.stringify({ result: SUBTASK_ABANDON_CHILD_FOLLOWUP_ANSWER }),
506+
id: "call_abandon_child_completion_002",
507+
},
508+
],
509+
},
510+
})
357511
}

0 commit comments

Comments
 (0)