feat(web): add a Pi-native thinking-level selector to the composer - #531
Open
Matt-qwq wants to merge 1 commit into
Open
feat(web): add a Pi-native thinking-level selector to the composer#531Matt-qwq wants to merge 1 commit into
Matt-qwq wants to merge 1 commit into
Conversation
Matt-qwq
force-pushed
the
feat/web-thinking-selector
branch
from
September 10, 2026 20:11
109e352 to
23b6b73
Compare
11 tasks
Matt-qwq
force-pushed
the
feat/web-thinking-selector
branch
3 times, most recently
from
September 11, 2026 00:20
2f9351e to
8106646
Compare
Expose Pi's native thinking/reasoning level in the Web workbench: a runtime setter with a bounded merge-to-latest, a lease-sensitive POST /api/thinking, a bounded optional thinking projection with a monotonic revision on the snapshot, a last-intent-wins client store with a revision gate, and an icon-only composer picker with a disabled placeholder for unsupported models. Levels come from Pi's getAvailableThinkingLevels()/supportsThinking(); OpenPI adds no second reasoning store and no persisted configuration (session-only). Advances the change-thinking-level criterion of openpi-dev#348 and continues the read-only GET /api/thinking inspection from openpi-dev#375/openpi-dev#444, preserving its unknown fallback. Adds browser coverage (22 e2e incl. an axe pass) and a hermetic provider e2e that proves the selected level reaches the next provider request as reasoning_effort.
Matt-qwq
force-pushed
the
feat/web-thinking-selector
branch
from
September 11, 2026 00:30
8106646 to
923c723
Compare
This was referenced Sep 11, 2026
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.
Problem
The Web workbench can inspect the reasoning/thinking state but cannot change it.
InspectionPanelrenders the current level and the available set read-only, and the composer's model picker only changes the model. There is no way to raise or lower reasoning effort for the active Session without leaving the workbench. This is the unmetchange thinking/reasoning levelhalf of #348: #375/#444 already landed read-onlyGET /api/thinkinginspection with an explicitunknownfallback; the setter and the UI control are still missing.Related to #348 (advances the thinking/reasoning criterion; does not close it), #76 (Web workbench roadmap), #455 (Web UI/UX task), and #195 (Pi owns reasoning state). Continues #375 / #444 and credits
seekskyworldfor the read-only inspection slice.Value
session.getAvailableThinkingLevels()andsession.supportsThinking(); OpenPI adds no second reasoning store, no browser-side parser, and no new persisted configuration. This matches docs(routing): define provider/model selection, fallback, reasoning state, and invocation evidence #195 (reasoning state is Pi-owned; reasoning UI is presentation only) and [Roadmap] OpenPI Web:像 Codex / Kimi Code 一样的本地浏览器 Agent 工作台 #76 (configuration writes stay on the controlled Pi/OpenPI path).extensions/setup/,setup-config.ts,SETUP.md, or README default changes are required, and no second config source is introduced (cf. the feat(web): restore polished workbench UI and conversation rendering #352 precedent).Approach
web/protocol/types.ts): newWebThinkingState { level, available, supported, revision }; optionalthinkingonWebSnapshot. Protocol version unchanged (optional field).web/runtime/pi-runtime.ts):getThinkingState()gainssupported; newsetThinkingLevel(level, { expectedSessionId })runs throughserializeControllerMutation(synchronous Pi setter, no retained runtime reference) and enforces a non-configurable merge-to-latest bound (≤1 in flight + 1 pending; every waiter resolves to the final authoritative projection or its own 409SESSION_CONFLICT).web/adapter/pi-adapter.ts): fail-opensafeThinking()— a throwing getter omitsthinkingand never breaks/api/snapshot; the projection is bounded (≤16 levels, each ≤500 chars).web/host/web-host.ts):POST /api/thinkingplaced before the non-GET fallback and made lease-sensitive (400 invalid body, 409WORKSPACE_REQUIRED/SESSION_CONFLICT, 501 unavailable,THINKING_LEVEL_NOT_AVAILABLEfor unsupported models).GET /api/thinkingkeeps feat(web): integrate terminal details, thinking state and unarchive #444's shape and never-500unknownfallback; both responses now share the host-bound projection helper and carry the monotonic hostrevision.web/ui/src/store/web-store.ts): last-intent-wins single-flight flush; a monotonicrevisiongate (scoped to the Session epoch, reset on cursor reset) so a stale snapshot or reordered response can never regress the level;thinking_level_changedis applied as a local revision-gated patch rather than forcing a full snapshot refresh.Composer.tsx,Transcript.tsx,InspectionPanel.tsx,i18n.ts,styles.css): icon-only picker beside the model picker with a section title, current-level check, disabled-reason tooltip, pending visual, and a mismatch warning. The level is always present in the accessible name, and the check/data-levelare redundant signals (WCAG 1.4.1)./openpi-setupconfiguration contract.Validation
web/distwas rebuilt from source andbun run checkleaves it clean (CI's stale-build guard).models.json) and asserts the real backend request body carriesreasoning_effort: "high"after selectinghighin the browser, and omits the field foroff; it also asserts the picker is disabled while a turn runs and the read path still reportshighafter reload.GET /api/thinkingreconcile, 501 → notice, out-of-set mismatch warning, running lock, narrow-viewport overflow, and axe.off/low/medium/high/max), and the opened menus for both models (GLM exposesmedium, DeepSeek exposesoff).npm pack) acceptance and the native TUI. No merge-tree check against a newermainwas needed because the branch is based onmain@5bf2fe2; it will be rebased ifmainmoves.Real-browser evidence (live workbench, real models)
Captured from a running workbench with real models; each dropdown was captured after its animation settled. The picker's Brain icon is tinted by the active level.
mediumis offered only by GLM 5.3 Flash andoffonly by DeepSeek V4.1 Flash — each model exposes exactly the levels itsthinkingLevelMapallows, so the two menus differ by design.Placement — right of the model picker, left of send:
Icon color by level (
offfrom DeepSeek;low/medium/high/maxfrom GLM):Opened menus:
Impact
revision; there is intentionally no server-side rate limit (client is single-flight), documented as a known gap.