feat(frontend): rebuild Electron desktop UI as a React + Vite renderer#1
feat(frontend): rebuild Electron desktop UI as a React + Vite renderer#1yyovil wants to merge 9 commits into
Conversation
Full renderer rewrite by @ashish921998 in aoagents#156, extracted without the Prettier mass-reformat and husky/lint-staged tooling (those land separately in the chore/prettier-ci PR). Stack: - Shell: Electron + child_process daemon supervision with stale-handle guard - UI: React 19 + TypeScript renderer (Vite, contextBridge preload) - Data: TanStack Query + EventTransport (CDC SSE on /api/v1/events) - API types: openapi-typescript + openapi-fetch off openapi.yaml - Styling: Tailwind + shadcn/ui (Badge, Tabs, Button, Input, Tooltip) - Layout: react-resizable-panels, sizes persisted to Zustand - Terminal: @xterm/xterm per-session PTY over /mux WebSocket + WebGL addon - UI state: Zustand (selection, active pane, theme, layout sizes) - Testing: Vitest + RTL + Playwright Backend additions: - CORS middleware (cors.go) — allowlist-only, never * or null, handles Private Network Access preflight for file:// → loopback requests - session.TerminalHandleID field exposed in domain + OpenAPI spec - project.Path field added to OpenAPI spec + service/store/tests - CORS origin config wired through config.go Design: DESIGN.md added as source of truth for the emdash-matched dark UI. Co-Authored-By: Ashish Huddar <ashish921998@users.noreply.github.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Entire-Checkpoint: 9fd9e7f48ec8
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Entire-Checkpoint: a14c9f9aec7b
Replace vite-plugin-electron + electron-builder with electron-forge's blessed Vite template. Split vite.config.ts into three configs (main/preload/renderer), add forge.config.ts with 4 makers and publisher-github, update main.ts to use forge-injected globals and update-electron-app, and update the release workflow to use `electron-forge publish`. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace code-based route tree with file-system routing via @tanstack/router-plugin - createAppRouter() factory injects QueryClient into router context for loaders - createHashHistory() preserved for Electron file:// renderer origin - Routes: __root.tsx, index.tsx, workspaces.$workspaceId.tsx, workspaces.$workspaceId_.sessions.$sessionId.tsx - TanStackRouterVite plugin wired into vite.renderer.config.ts (before react plugin) - defaultPreload: 'intent', defaultPreloadStaleTime: 0, scrollRestoration: true - declare module Register moved to main.tsx alongside router instantiation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Entire-Checkpoint: 64aa08569fed
__root.tsx already wraps every route in TooltipProvider. All routes render <App>, so every render was double-nesting the provider. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Entire-Checkpoint: f466c24a4356
The migration to electron-forge made the release doc stale: - electron-builder → electron-forge (npm run publish) - electron-updater → update-electron-app (reads Releases API, no latest-mac.yml feed files) - package.json build.publish → forge.config.ts publishers - "identity": null removal → osxSign/osxNotarize already gated on CSC_LINK/APPLE_ID env vars Also fix the now-stale initAutoUpdates() comment in main.ts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Entire-Checkpoint: a93e60c1314e
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6061f76932
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| /api/v1/projects/{id}/config: | ||
| put: | ||
| operationId: setProjectConfig |
There was a problem hiding this comment.
Register the advertised project config route
This OpenAPI path is now advertised, and the service has SetConfig, but ProjectsController.Register still only mounts list/add/get/delete for /projects, so PUT /api/v1/projects/{id}/config always falls through to the JSON 404 instead of updating config or returning the documented validation errors. This breaks generated clients and the new config endpoint tests for any caller trying to set per-project config.
Useful? React with 👍 / 👎.
| /api/v1/sessions/{sessionId}/pr: | ||
| get: | ||
| operationId: listSessionPRs |
There was a problem hiding this comment.
Register the advertised session PR routes
The PR endpoints are added to the API spec and the session service/test fakes now expose ListPRs/ClaimPR, but SessionsController.Register does not mount /sessions/{sessionId}/pr or /sessions/{sessionId}/pr/claim, so both documented routes return 404 for all sessions. Clients generated from this spec will call endpoints the daemon never serves, including the new tests that expect these routes to work.
Useful? React with 👍 / 👎.
…ck-query/router Branch was cut before portless/stack landed on main, so its skills-lock.json would have dropped them on merge. Union all four so nothing is lost. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Entire-Checkpoint: db30ea05f345
…r-clean # Conflicts: # skills-lock.json
Match the std skills layout (as in yyork): commit canonical skill content under .agents/skills/ and gitignore the per-agent dirs (.claude/.codex/etc), which only hold symlinks regenerated locally by `skills experimental_install`. - Vendor portless, stack, tanstack-query, tanstack-router under .agents/skills/ - Move portless out of the stray .claude/skills/portless/ into .agents/ - skills-lock.json: portless hash refreshed to match vendored content Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 2216545f536d
|
Renderer now goes upstream via aoagents#168 (clean branch off upstream/main, fork-infra stripped). Closing this fork-internal copy. The skills-vendoring work lives on the feat/electron-renderer-clean branch if needed later. |
What
Clean extraction of @ashish921998's renderer work from the upstream aoagents#156, without the Prettier mass-reformat and husky/lint-staged tooling that made that PR hard to review.
Stack
file://)/api/v1/eventsopenapi.yaml/muxWebSocket + WebGL addonBackend additions
cors.go— allowlist-only CORS middleware, never*ornull, handles Private Network Access preflight forfile://→ loopbacksession.TerminalHandleIDexposed in domain + OpenAPI specproject.Pathadded to OpenAPI spec, service, store, and testsconfig.goDesign
DESIGN.mdis the source of truth for the emdash-matched dark UI (emdash tokens, blue accent, status glyph spec, orchestrator-led layout).Credit
All renderer implementation by @ashish921998 — this PR is a clean split of his work, retargeted to the fork.
🤖 Generated with Claude Code