Skip to content

feat(webui): add tabbed pane workbench - #5322

Merged
chengyongru merged 8 commits into
mainfrom
codex/webui-pane-workbench
Aug 12, 2026
Merged

feat(webui): add tabbed pane workbench#5322
chengyongru merged 8 commits into
mainfrom
codex/webui-pane-workbench

Conversation

@chengyongru

@chengyongru chengyongru commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • model the sidebar as an explicit Tab → Pane[] hierarchy: Panes are peers and each Tab contains one to four sessions
  • render columns, rows, grid, main-stack, and monocle layouts with one shared header/composer owned by the focused Pane
  • replace the moving selection pill and insertion line with row-owned selection plus Chrome-style same-Tab repulsion and snapping
  • keep dragged Panes fully opaque, shadowless, and the same color as selection while sibling transforms preserve total list height
  • make cross-Tab membership an explicit Move to tab action; dragging a Pane never attaches it to another Tab
  • retain collapsible groups, explicit Tab/Panes hierarchy, localized copy, and multi-select deletion

Design boundaries

  • this PR is UI-only; it does not introduce the proposed session is agent or multi-agent protocol
  • a one-Pane Tab remains the default and temporary chats retain the existing single-thread path
  • workbench membership, focus, and layout remain versioned local UI state; gateway/session schemas are unchanged
  • each Tab is capped at four Panes so every visible Pane remains useful

Verification

  • bun run test — 56 files, 1009 tests passed
  • bun run lint — passed with zero warnings
  • bun run build — TypeScript and production Vite build passed (2846 modules)
  • production-browser verification confirmed fixed 68 px list height before/during/after drag, absolute snap slot, one displaced sibling, opacity 1, no shadow, and byte-stable membership across cross-Tab drops
  • selected and dragged surfaces matched exactly: rgb(228, 228, 228) in light mode and rgb(76, 76, 76) in dark mode
  • live http://127.0.0.1:5173/ verification after restarting Vite confirmed persistent click selection after pointer exit/two animation frames and matching opaque drag state

Notes

  • newly created empty sessions still produce the existing history-endpoint 404 until a first thread entry exists; no JavaScript exception or changed-flow failure was observed

@chengyongru
chengyongru force-pushed the codex/webui-pane-workbench branch from 7ddd051 to 32c5a10 Compare August 11, 2026 04:08
@chengyongru
chengyongru marked this pull request as ready for review August 12, 2026 02:47
@chengyongru
chengyongru merged commit 4b5319b into main Aug 12, 2026
6 checks passed
@chengyongru
chengyongru deleted the codex/webui-pane-workbench branch August 12, 2026 06:45
fuutott added a commit to fuutott/nanobot that referenced this pull request Aug 14, 2026
…actor, exec/security hardening

Absorbed from HKUDS/nanobot (b3b0517..221e8a4):
- feat(mcp) HKUDS#5316: native browser OAuth for remote MCP servers (mcp_oauth.py +
  webui/mcp_oauth_api.py; auth: "oauth" marker; MCP SDK OAuthClientProvider).
- refactor HKUDS#5343: move MCP lifecycle out of AgentLoop into an MCPProvider;
  from_config now takes a caller-owned tool_registry; close_mcp -> aclose.
- Security: exec.allowPatterns shell-chain bypass fix, exec path-guard hardening
  (double-slash / redirection / named-user home), Docker privilege-drop
  hardening, stop leaking API keys into subprocess env, web credential-URL
  redaction (keep creds out of logs / Jina reader / SW caches).
- WebUI: tabbed pane workbench (HKUDS#5322), MCP management dialog, PWA support,
  native folder picker, settings split by domain (HKUDS#5323), session drag polish.
- Providers: DeepSeek V4 Pro Responses; gemini tool-history across model switch.
- Session: history stored outside workspace, symlink-migration rejection,
  storage relocation.

Local customisations — MCP OAuth now COEXISTS with upstream's native flow
(upstream is browser-only; our fork keeps the headless path for containers):
- schema.py: unified auth field to `OAuthConfig | Literal["oauth"] | None`
  ("oauth" -> upstream browser flow; OAuthConfig object -> our headless
  device_code/client_credentials).
- mcp.py: re-applied _resolve_oauth_token bearer injection inside upstream's new
  open_single_server, selected by auth-type; upstream's oauth_auth httpx.Auth
  handles the "oauth" marker. request_headers now also feeds streamableHttp.
- loop.py: _oauth_refresh_loop reads self.tools_config.mcp_servers (post-HKUDS#5343
  self._mcp_servers is gone), gated to isinstance(cfg.auth, OAuthConfig); kept
  our from_config subagent factory + tool_registry param together.
- Dropped orphaned fork reload_single_server (its module-level deps were removed
  by HKUDS#5343); the refresh loop now refreshes tokens on disk and the live session
  picks them up on next reconnect (reactive, matching upstream). Removed its
  two fork tests; fixed test_oauth_refresh_task to use tools_config.
- docker-compose.yml: kept SYS_ADMIN + unconfined apparmor/seccomp for the
  bubblewrap sandbox (upstream's no-new-privileges model breaks bwrap; we run
  as nanobottie via direct USER, not upstream's entrypoint drop).
- conftest.py: kept fork plugin-path setup alongside upstream's session
  isolation fixture. strip_history / web exclusive-timeout / utf-8-sig / mcp_auth
  CLI / plugin channels all preserved.

Verified: ruff clean; host sweep ~4270 passed. One expected Windows-only
failure (test_equivalent_workspace_paths_share_one_store: WinError 1314 on an
unguarded symlink() in a new upstream test — passes on Linux).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant