Skip to content

feat(dte): dynamic thinking effort (series PRs 1-5 + e2e addenda + F7) - #1379

Closed
easonLiangWorldedtech wants to merge 124 commits into
Zoo-Code-Org:mainfrom
easonLiangWorldedtech:feat/dte-trial-all
Closed

feat(dte): dynamic thinking effort (series PRs 1-5 + e2e addenda + F7)#1379
easonLiangWorldedtech wants to merge 124 commits into
Zoo-Code-Org:mainfrom
easonLiangWorldedtech:feat/dte-trial-all

Conversation

@easonLiangWorldedtech

@easonLiangWorldedtech easonLiangWorldedtech commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Dynamic Thinking Effort — reviewer guide (trial VSIX included)

What this is: one installable VS Code build that composes the entire DTE (Dynamic Thinking Effort) series — the 5 feature PRs, both e2e addenda, and F7 (OpenAI-compatible effort declaration) — so it can be tried end-to-end as a single extension.

This PR composes the entire series into one installable build so the combined behavior can be reviewed and tried end-to-end. The 8 component PRs (listed below) remain open and can be merged independently — this PR is a review convenience vehicle for the trial build, not a replacement for them.


1. What's in the build

# PR (upstream) Role Status
1/5 #1336 feat/dte-1-experiment dynamicThinkingEffort experimental setting ✅ CI green
2/5 #1338 feat/dte-2-task-state task-local effort state, per-request override, adaptive envelope ✅ CI green
3/5 #1354 feat/dte-3-native-tool set_thinking_effort native tool (model-driven, no approval) ✅ CI green
4/5 #1359 feat/dte-4-webview-ui webview surfaces: header chip, composer toggle, in-chat display ✅ CI green
5/5 #1355 feat/dte-5-orchestrator orchestrator new_task thinking_effort (subtask start effort) ✅ CI green
addendum #1361 feat/dte-3-e2e e2e: set_thinking_effort mid-task workflow ✅ CI green
addendum #1356 feat/dte-5-e2e e2e: orchestrator new_task thinking_effort ✅ CI green
F7 #1366 feat/dte-7-f7-openai-compat OpenAI-compatible profiles declare supported effort levels ✅ CI green

Patch coverage (combined trial tree, Codecov on 27a2e97df): 97.31% (check codecov/patchSuccessful, target 80% — pass) · webview patch 97.67% (check codecov/patch/webview-patch, target 70% — pass). The DTE diff has no fully-missing lines — Codecov's 5 missing lines sit on files outside this PR's diff (stale-base artifact) and the DTE files carry 5 partial branches only; line-level detail in §7.

Trial branch: feat/dte-trial-all @ 27a2e97df (all 8 heads merged, additive; includes the CodeRabbit review fixes, §7). The installable VSIX is the CI-built zoo-code-vsix-pr-1379 artifact from this PR's Code QA run on the current head — it already includes the review fixes (§2).


2. Install (5 minutes)

  1. Download the CI build from the PR's Code QA run (built on head 27a2e97df; the zip contains zoo-code-3.80.0.vsix): zoo-code-vsix-pr-1379 artifact (zip: 33,684,498 bytes · zip SHA256 307100E9C745EEE1BC2A7040A7EC0F6185A5006A5AE70A2B276014927346926D). CI artifacts are retained for 7 days — if the link has expired, re-run the Code QA Roo Code workflow on this PR to get a fresh build at the same head.

  2. Install it:

    code --install-extension zoo-code-3.80.0.vsix

    …or in VS Code: Extensions view → menu → Install from VSIX… → pick the file.

  3. Reload the window (Command Palette → Developer: Reload Window).

  4. Open the Zoo Code panel — you're ready.


3. How to use DTE

A. Managed providers (Anthropic / OpenAI / DeepSeek / …)

  1. Pick a capable model. The composer thinking-effort toggle renders for models that advertise a reasoning-effort capability (e.g. Anthropic adaptive-thinking models, OpenAI o-series, DeepSeek, Gemini effort models).
  2. Set the effort for the next request using the composer toggle (bottom bar of the chat). The chip shows the current value; open it to see the selectable levels.
  3. Watch the applied effort in the header chip and the in-chat display for each turn.
  4. Switch mid-task. The model can call set_thinking_effort to change the effort itself (you can also change it at any time with the composer toggle). The change is task-local — it applies from the next request only and is never written to settings; it is stored with the task (like the task mode) and restored when the task is reopened from history.\n\n > Note: the model can only call the tool when the Dynamic Thinking Effort experimental setting is enabled (see 4.5) — the composer toggle, header chip and in-chat display do not require it.
  5. Subtasks. new_task can be given a starting effort; if you leave it unset it inherits the parent's effective effort.

B. Self-hosted / OpenAI-compatible (F7)

  1. Go to Settings → your OpenAI-compatible profile (custom OpenAI endpoint, LM Studio, Ollama, vLLM, SGLang, …).
  2. Use the new supportedEffortLevels multi-select to declare which effort levels your model supports.
  3. This unlocks the DTE capability + UI surfaces for that profile.

    ⚠️ Honest scope note: F7 lands the declaration half (capability + settings + UI). For most OpenAI-compatible families the wire half — sending the selected effort level to the server — is a follow-up PR, because each server family needs a different wire shape (LM Studio reasoning:{effort}, vLLM/SGLang flat reasoning_effort). Exception — Ollama: its effort wire is already live today via the pre-existing think request parameter (requires the “Model Reasoning Effort” toggle; low/medium/high map 1:1 and xhigh/max clamp to high), so declaring levels on an Ollama profile also unlocks a working effort wire. Undeclared profiles keep today's behavior exactly.

C. Effort resolution (precedence, strongest first)

task-local override (composer selection, set_thinking_effort, subtask start effort from new_task — all stored with the task and restored when it reopens; none is ever written to settings) → settings.reasoningEffortmodel default.
disable is a UI off-switch (not a level, not sent). adaptive is Anthropic's model-decides soft signal.


4. New UI surfaces — screenshots & guide

Every new DTE surface, what it is, where it appears, and how to use it. (Captured from the real webview components; light + dark themes.)

4.1 Composer thinking-effort toggle (PR 4/5)

Bottom bar of the chat composer, next to the API-config selector. Renders only for models that advertise per-request effort support (registry capability, or an F7 declaration — see 4.6). The chip shows the current effective effort; open it to switch the task-local effort — the change applies from the next request and is never persisted to settings. If no task is open yet, the selection is parked and applied to the next top-level task you start (when that task's model supports the level; a stale selection never leaks into a later task).

Menu (selectable levels) Resting (current effort)

Dark: menu · resting

4.2 Task header chip (PR 4/5)

Sits in the task header (top of the chat, next to the task title). Shows the current effective effort plus a source badge so you can tell where it came from:

  • you — you set it with the composer toggle (and it differs from the default)
  • Zoo (auto) — model-driven or inherited (e.g. a subtask inherits the parent's effort)
  • default — from the provider-profile setting or model default
Task-local override (source: you) Settings default (source: default)

Dark: you · default

4.3 In-chat effort display (PR 3/5 + 4/5)

One-line entries in the chat whenever the effort changes, so the switch is visible in the conversation:

  • model-driven: "Thinking effort: high (Zoo) — " (the model called set_thinking_effort with a reason)
  • user-driven: "Thinking effort set to: low" (you changed it via the composer)
  • refused: escalation cap (max 3 upward changes per task) or oscillation detection
Applied (model, with reason) · Applied (you) · Refused (oscillation)

Dark: in-chat lines

4.4 Settings — supported reasoning effort levels (F7, self-hosted)

New control in Settings → your OpenAI-compatible profile (custom OpenAI endpoint, LM Studio, Ollama, vLLM, SGLang). Self-hosted models don't advertise effort capability, so declare the levels your model accepts — this unlocks the whole DTE feature set for that profile. Values buffer in the settings form and persist on Save.

Declared (5 levels) Undeclared (nothing declared — DTE stays off)

Dark: declared · undeclared

4.5 Settings — experimental toggle (PR 1/5)

Settings → Experimental → Dynamic Thinking Effort. This toggle gates model-driven mid-task switching only — when it is on, capable models are given the set_thinking_effort tool so the model itself can change the effort during a task. The UI surfaces (composer toggle, header chip, in-chat display, new_task selector, F7 settings) are gated by model capability, not by this experiment — they render without it. Turn it on to try the model-driven flow (step 4 of §3).

Experimental section with DTE enabled

Dark: experimental

4.6 Composer toggle — self-hosted model with F7 declaration (F7 + 4/5)

The same composer toggle for a self-hosted OpenAI-compatible model (Qwen3.8:27B) whose effort levels were declared in 4.4 — the declared levels appear in the menu (webview capability fill-in).

Menu (declared levels) Resting (current effort)

Dark: menu · resting

4.7 new_task start-effort selector (PR 5/5)

When the orchestrator asks to start a subtask (new_task), the ask block shows a small Brain-icon effort selector next to the prompt (only when the target model supports effort). It is pre-filled with the parent task's effective effort and can be switched before entering the subtask; leave it as-is to inherit. (Rendered inline in the ask bar — see the e2e addendum #1356 for the wire-level proof.)


5. Provider support & thinking-effort options

Which providers wire thinking effort into the request, the levels they accept, and the wire shape:

Provider Effort on the wire Thinking-effort options (levels) Wire field / shape Notes
Anthropic / Anthropic Vertex (adaptive-thinking) low · medium · high · xhigh · max (out-of-range → omitted → API default) output_config.effort (adaptive envelope) First-class DTE — per-request override fully wired
OpenAI / OpenAI-native low · medium · high (model default + selected) reasoning_effort o-series
OpenRouter ✅ (per-model) effort levels (model metadata) { effort } capability from model supported_parameters
Google Gemini minimal · low · medium · high (effort) / thinkingBudget (2.5) thinkingConfig.thinkingLevel
DeepSeek low · high · max reasoning_effort
xAI low · medium · high reasoning: { effort } object shape
Z.ai (GLM) none · minimal · low · medium · high · xhigh · max reasoning_effort + thinking toggle
Roo Code (capability array) reasoning: { enabled, effort }
nanoGPT low · medium · high (or model-declared) reasoning_effort
opencode-go low · medium · high reasoning_effort
kimi-code (boolean / array)
Friendli (OpenAI-compatible) minimal · low · medium · high · xhigh · max reasoning_effort (extended enum)
Poe low · medium · high reasoning_effort
Requesty low · medium · high (allow-listed) reasoning_effort
Unbound low · medium · high (allow-listed) reasoning_effort
Ollama ✅ (pre-existing) low / medium / high (xhigh/maxhigh) think (bool or level) Pre-existing wire — requires the Model Reasoning Effort toggle; F7's level declaration unlocks the UI menu on top of it\n

6. What to verify during the trial

  • Composer toggle appears for a capable model; chip + menu render (see §4).
  • Selecting an effort changes the next request (not mid-stream); the value is never written to settings — it is stored with the task and restored when the task is reopened from history.
  • set_thinking_effort mid-task: applied / no-op / refused transitions behave correctly (escalation cap = max 3 upward changes per task + oscillation refusal). Requires the DTE experiment enabled (4.5).
  • new_task: explicit start effort honored; unset inherits the parent's effective effort.
  • Header chip + in-chat display track the applied effort.
  • F7: declaring supportedEffortLevels on a self-hosted profile unlocks the UI; undeclared profiles are unchanged.
  • Settings round-trip: declared levels survive a reload (storage → webview).

Known limitations (by design, for this trial):

  • Self-hosted OpenAI-compatible per-server wire pass-through is a follow-up for custom endpoints / LM Studio / vLLM / SGLang (Ollama already has a live think wire — see §5).
  • adaptive is a soft guidance signal, not a concrete level.
  • Effort overrides are never written to settings; they are stored with the task (task layer) and restored when the task is reopened from history.

7. Provenance

Summary by CodeRabbit

  • New Features
    • Added configurable thinking-effort controls for supported models.
    • Users can select effort levels in the chat composer and view the active level in task headers.
    • Added in-task effort changes with validation, fallback handling, refusal messages, and escalation safeguards.
    • Added effort selection and inheritance for delegated tasks.
    • Added provider settings and an experimental dynamic-effort option.
    • Effort selections persist with tasks and support adaptive models.
  • Localization
    • Added translated labels, guidance, and status messages.
  • Tests
    • Added comprehensive coverage across providers, delegation, persistence, and UI interactions.

…nd adaptive effort envelope

DTE series 2/5 (part of Zoo-Code-Org#1329).

- ApiHandlerCreateMessageMetadata.reasoningEffort: per-request override channel
- resolveEffectiveReasoningEffort: single shared resolution point (override > settings > model default)
- AnthropicHandler: adaptive output_config.effort envelope in both requestParams branches (in-range only)
- Task: setRuntimeThinkingEffort/getRuntimeThinkingEffort with in-memory apiConfiguration merge/restore, per-request metadata at all four createMessage sites, dispose() reset; never persisted
DTE series 2/5 — addresses the CodeRabbit review finding on Zoo-Code-Org#1338:
when a task-local thinking-effort override is active, updateApiConfiguration()
now re-captures the incoming profile's reasoningEffort as the restore value
and re-applies the override on top of the new in-memory copy, so clearing the
override restores the NEW profile value instead of the stale one. Additive:
activation and clearing semantics are otherwise unchanged.

Adds two regression tests (override active + profile switch restores new
value; inactive updateApiConfiguration unchanged behavior).
DTE series 2/5 — addresses the CodeRabbit docstring-coverage warning on Zoo-Code-Org#1338
(33.33% < 80% across the functions touched by the diff):
- AnthropicHandler.createMessage: documents the shared effective-effort
  resolution and the adaptive output_config.effort envelope (in-range only).
- Task.dispose: documents centralized teardown incl. the transient task-local
  override reset.
- Task.updateApiConfiguration: documents the override-preservation behavior
  (re-captured restore value + re-applied override on the new in-memory copy).

Comment-only change: 30/30 patch lines and 10/10 branches unchanged;
317/317 tests and tsc --noEmit re-verified green.
Add the set_thinking_effort native tool (DTE series 3/5): the model adjusts
its own per-turn thinking effort mid-task with no approval gate.

- Guardrails: one-line chat notification (success or refusal), escalation cap
  (max 3 upward changes per task), A->B->A oscillation refusal, hard clamp to
  the model capability array (ties toward the lower level).
- Gating: dynamicThinkingEffort experiment + model supportsReasoningEffort
  (non-empty array or true), evaluated at task start so the tool list stays
  stable within a task (prompt-cache safety).
- Display: webview ChatRow one-line row (applied / oscillation / escalation
  refusal), i18n keys in all 17 locales; partial streaming updates the same
  line.
- Tests: executor (clamp/cap/oscillation/no-op/no-approval/display), parser
  (partial + complete), dispatch, gating matrix, schema wiring, ChatRow
  display.

Stacked on DTE PR-1 (experiment flag) and PR-2 (task-local runtime effort
state). Closes Zoo-Code-Org#1330.
Address PR review feedback on set_thinking_effort (DTE series 3/5):

- Executor: seed the per-task guard history with the task's effective
  baseline so returning from a changed value to the original baseline is
  refused as oscillation (A -> B -> A); existing no-op behavior preserved.
- Parser: only build nativeArgs when effort AND reason are strings; a
  non-string payload now fails at parse time and cannot reach the executor.
- Gating: a supportsReasoningEffort array that only lists 'disable' no
  longer exposes the tool (it could apply no level).
- i18n: translate the new thinkingEffort chat strings into all 17
  non-English webview locales (placeholders preserved).
- Tests: regression tests for each change plus branch-coverage for the
  previously partial lines (non-string args, 'disable'-only capability,
  baseline oscillation, partial streaming without params, description
  fallback, capability robustness). All touched patch lines are now
  fully branch-covered (codecov patch partials resolved).

CodeRabbit: Zoo-Code-Org#1354
… post-mode-switch revalidation, ask prefill normalization)
@github-actions github-actions Bot added awaiting-coderabbit Waiting for CodeRabbit to approve the latest commit has-conflicts PR has merge conflicts with the base branch coderabbit-review-active Required CI passed; CodeRabbit review is active and removed has-conflicts PR has merge conflicts with the base branch coderabbit-review-active Required CI passed; CodeRabbit review is active awaiting-coderabbit Waiting for CodeRabbit to approve the latest commit labels Sep 1, 2026
@easonLiangWorldedtech

Copy link
Copy Markdown
Contributor Author

Superseded by the DTE-v2 400-line redo. Content re-lands from the verified union 27a2e97 (feat/dte-trial-all, branch retained) as units U1-U39. New tracking issue: easonLiangWorldedtech#35.

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

Labels

awaiting-coderabbit Waiting for CodeRabbit to approve the latest commit coderabbit-review-active Required CI passed; CodeRabbit review is active

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants