feat(web): add a Pi-native thinking-level selector to the composer - #531
Conversation
109e352 to
23b6b73
Compare
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.
8106646 to
923c723
Compare
tt-a1i
left a comment
There was a problem hiding this comment.
Reviewed 351769c after current-main integration. Standards: no remaining actionable blocker identified. Spec: Pi owns supported thinking levels and serialized Session-bound mutation; the composer projects the resulting canonical state. No P0/P1 found. This supersedes findings against older implementations where stated; merge remains conditional on current required CI and branch protection.
# Conflicts: # tests/web/openpi-web.e2e.ts # web/dist/app.js # web/dist/styles.css
tt-a1i
left a comment
There was a problem hiding this comment.
已解决最新 main 集成冲突并重新生成 Web 产物。双线复审确认保留移动侧栏焦点行为和本 PR 功能;check通过,完整测试及Web E2E继续执行。未发现P0/P1。此账户推送了集成修复,仍需另一维护者满足最后推送后的独立批准。
tt-a1i
left a comment
There was a problem hiding this comment.
追加跨环境测试修复:基础页面不再假定真实 runtime 一定不支持思考;将禁用状态及标签断言移至明确 supported:false 的夹具。原行为覆盖保留,bun run check 与27项浏览器E2E通过。最新完整CI正在验证。此账户推送了修复,仍需独立批准。
# Conflicts: # tests/web/web-store.spec.ts # web/dist/app.js # web/dist/styles.css # web/ui/src/protocol/client.ts # web/ui/src/store/web-store.ts
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.