Skip to content

Redesign Core Web as an operations console - #96

Merged
SaladDay merged 36 commits into
mainfrom
codex/admin-console-redesign
Sep 25, 2026
Merged

SaladDay merged 36 commits into
mainfrom
codex/admin-console-redesign

Conversation

@SaladDay

@SaladDay SaladDay commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Rebuilds Core Web (apps/web) as the administrator console for a Core deployment, on the management contract from #92 and the Core metrics from #97. The browser talks only to the console service (/console/**, /core/v1/admin/**, /core/v1/sandbox/**) and never to /v1.

  • Navigation: Monitor (Overview, Core metrics, Agent metrics, Sandbox metrics, Session log), Resources (Agents, Environment templates, Skills, Files, Vaults), Platform (Projects and keys, Nodes, System).
  • Monitor pages: one page structure and one chart component. Overview shows status tiles, 24-hour activity, Core and its nodes as a topology with a popover glance at each, Sessions needing attention and usage by Project. Core metrics reads GET /core/v1/admin/core-metrics. Missing values stay "—".
  • Resources: inspection, confirmed deletion (Core's refusal reason is kept) and copies to another Project; Session history shown as a read-only conversation.
  • Projects and keys: create, rename, archive; keys shown once at issue; revocation; uncertain writes are reported, never replayed.
  • Foundation: Tailwind v4 utilities scoped to registry components (Beautiful UI foundation tokens, coss ui select and popover) with Parsar indigo and Inter; TanStack Query caching with prefetch and skeletons only on first loads; Motion for the navigation chip and segmented thumbs, NumberFlow for live figures, chart draw-in; reduced motion respected.
  • Console service: forwards read-only GET /core/v1/admin/core-metrics.
  • Consistency: card and section header actions are outline buttons; the Session conversation spans its card.
  • Browser acceptance: apps/web/e2e rewritten as one test per acceptance behavior against fixture-console.mjs, a synthetic console service; every test asserts nothing was sent to /v1 and no Authorization header.
  • Onboarding: sign-in and first run share a dark stage (Magic UI grid, light rays, Core with orbits); first run is the administrator account, the first project and its key (shown once, the example request typed into a terminal) and a three-chapter tour with real console screenshots; View Transitions between steps and into the console; reduced motion respected.
  • Docs: apps/web/PRODUCT.md, apps/web/DESIGN.md, docs/web/* updated for the implemented console.

Validation

  • GitHub CI (check, sessions) passes; check runs the full make check, including the Playwright browser acceptance on Chrome.
  • On the development server, make check passes in server mode (typecheck, 592 client tests, 328 web tests, Go tests, web build); the browser cases are skipped there and run separately on headless Chromium (9 tests, including first run).
  • Independent blind review: no blockers. Its should-fix findings are addressed in bd4932d9 (uncertain deletions reported on detail pages, Core's 409 reason shown, first key kept on screen, no "nothing needs attention" or "no runs" claims after failed reads, unknown Core status never shown as running, failed console-config reads reported as failures, Session deletions evicted from the cache, and a browser check that a missing figure shows "—").

Follow-ups

  • Per-provider sandbox UI (E2B, Docker, microsandbox), as a separate PR.
  • Node onboarding with capacity confirmation (Feishu proposal), with the per-provider sandbox UI.
  • Remove the Vite development proxy's /v1 path together with scripts/core-doctor.mjs and .env.example tooling.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith with what you need. Autofix is disabled.

Turn the administrator console into a back office for a self-hosted
Agents API deployment, and add the Skills, Files, full template
configuration and per-Agent usage pages from the Web specs.

- Navigation: Monitor (Overview, Agent metrics, Sandbox metrics, Session
  log), Resources (Agents, Skills, Environment templates, Vaults, Files),
  Platform (Nodes, API keys), Playground (API workbench, getting started).
  The Session console is a secondary page of the Session log; the System
  page is removed.
- Shared page grammar in components/console-ui (page header, help tips,
  icon refresh, metrics, meters, status dots) and a canvas/card surface.
- Overview: health, Session, capacity and attention figures, 24-hour
  Session activity, fleet with node detail, Sessions needing attention.
- Agent and Sandbox metrics computed in the browser from existing reads,
  with honest coverage; missing values never render as zero. Backend
  requirements for aggregate endpoints are documented.
- API keys as a table with a create dialog; the one-time secret survives
  closing the dialog. API workbench builds fixed-format requests (curl and
  JSON) and can send them or look objects up by ID.
- First-run introduction follows one request path; the first request uses
  the builder's form and request preview layout.
- agents-client: Skills (11 operations), Files list, and full Environment
  template projection with per-template unrecognized configuration.
- Agents page: table with per-Agent usage (sessions, tokens, coverage);
  starter templates removed.
- Chinese UI keeps API terms in English (Agent, Session, Turn, Skill,
  Vault).

Work in progress: remaining design feedback (list toolbar unification,
API workbench fields, first-run visual direction) and the Playwright
specs are not updated or run yet. Web typecheck and 904 unit tests pass.
…WIP)

- One list grammar (search, filters, count; name with ID; row actions)
  across Agents, Skills, Templates, Files, Vaults and the Session log.
- Vaults become a table with a Credential detail page; explanations move
  from banners and field hints into help tips.
- API workbench redesigned with grouped fields and a request panel.
- Client: tolerant Session list for usage aggregation; advanced-template
  hosted Sessions count as managed.
- Preview and docs: Files list wording, Credential term in Chinese.
…edesign

# Conflicts:
#	apps/web/e2e/agents-lifecycle.spec.ts
#	apps/web/e2e/sandbox-manager.spec.ts
#	apps/web/src/features/sandbox/SandboxManagerView.css
#	apps/web/src/features/sandbox/SandboxManagerView.tsx
- AdminClient in agents-client: key spaces and keys, write operations,
  summary, copies, all-space runtime observations and startup
  configuration; per-space read/delete scopes reuse public projections.
- New ConsoleApp shell with Monitor, Resources and Platform groups, no
  Agents API playground, key-space context and route parameters.
- Pages are stubs until each moves to the Web API.
The console becomes a management tool: every read, delete and copy goes
through /core/v1/admin; nothing calls the Agents API from the browser.

- Projects own isolated assets shared by their named API keys. Resource
  and Session pages filter by project, show the creating key (#87) and
  offer delete and copy-to-project; editors, uploads, Credential writes,
  Session creation and the composer are removed.
- Platform: projects and keys (create, rename, archive, issue and revoke
  keys with a one-time plaintext), write history, System configuration;
  first run creates the first project and key.
- Monitor: overview per project with Core and hosts separated in the
  fleet card, Agent metrics by project and key, sandbox runtime across
  projects. The API workbench and the introduction are removed.
Delete modules, tests and i18n namespaces no page reaches after the
move to the Web API, trim connection helpers to the URL checks the
sandbox pages use, prune CSS rules whose classes no source uses, and
move the deployment provider notes behind help tips.
Copy AdminClient, its projection and types verbatim from PR #92 and add a
web view-model layer (lib/admin-view.ts) that converts RFC 3339 timestamps,
resolves creating keys by name, walks cursor pages and keeps unmeasured
usage as missing rather than zero. Resource pages read through a
project-scoped adapter over AdminClient. Projects no longer carry a
configuration source.
Overview draws Core with its sandbox nodes (solid lines online, dashed
offline; unhealthy nodes first when more than eight) in place of the fleet
table, and a node opens its detail on Nodes. Nodes lists every node in a
table with removal behind a confirmation, and #nodes?id= shows one node's
facts, capacity, host figures and allocations. Sandbox metrics drops the
summed free-memory figure: nodes report no totals and a sandbox runs on
one node. The Nodes page no longer checks a /v1 connection.
The conversation view groups Items by Turn in one frame: each Turn has a
header with status, duration, tokens and start time, speakers sit in a fixed
left column, tool steps collapse into one line and a failed Turn shows its
error. The copy dialog shows the copied item, then the source project, an
arrow and the target select; the button names the target, the row action
reads "Copy to project" and target Vaults are read across every page.
Cards use an 11% ink border with a two-layer shadow, and the Session
transcript, deployment panel and topology nodes share it. Topology nodes put
the name on its own line so longer names are not cut short.
Spare width spreads over the figure columns instead of opening a gap
between a project and its key count.
Every chart starts its y-axis labels at the card's content edge, under the
title and legend, and sizes the gutter to the widest label, in both the
column/line charts and the Runtime trend charts. Cards are flat with a 1px
edge, and the page header and Runtime tooltip are solid instead of blurred.
…M tables

Overview, monitor, detail, Session, project, key, write-history, System and
Nodes reads use TanStack Query with keys per input, keep previous data on
refresh, poll where they polled before, and invalidate exactly what a write
changes. Project filters use coss ui's Base UI select through ConsoleSelect.
Agent replies render GitHub tables.
The page opens with slots by node, hosted CPU and memory, and what needs
attention (offline or degraded nodes, pending cleanup, diagnosed
allocations, Runtimes that could not be sampled), each linking to its node.
Nodes keep the monitoring columns; the hosted Runtime section carries its
project filter and a totals line, lists Runtimes before their trends, and
the trend charts use the console's data palette.
Controls share an 8px radius (6px inside segments), cards 12px, the page panel
and dialogs 14px, and only status badges stay pills. Cards and tables start
their content 16px in. Sandbox metrics drops its summary band: the overall
picture lives on Overview, this page covers each node and hosted Runtime.
A Monitor page between Overview and Agent metrics shows Core's service line,
HTTP requests by route family with latency, the Turn scheduling queue,
dependencies (database, queue, storage, model providers, Runtime sampler)
and process resources. It reads GET /core/v1/admin/core-metrics through a new
typed client module; the contract is requested in
docs/web/core-metrics-requirements.md and the page says so until Core serves
it. Overview's Core node opens the page.
The conversation puts the user's message in a bubble on the right and the
Agent's work and reply on the left under its avatar (Beautiful UI's
Monogram), with tool steps as inline mono chips and a failed Turn's error in
the Agent's block. useProjectCollection now keeps its items array until the
cached data changes, which stops the Session log's effect from re-running on
every render.
Monitor pages share one layout: page controls (project filter where it
applies, range, refresh) in the header, headline figures only where they
exist nowhere else, then sections that go from trends to the breakdown
table. Sandbox metrics follows it: the range moves to the header, the
Runtime section shows a CPU and memory chart pair before its table, and the
half-page project filter is gone. Runtime trends on Sandbox metrics and the
Session page use the console's TimeSeriesChart through RuntimeCharts; the
uPlot panel, its styles and the uplot dependency are removed.
The Nodes list keeps identity and lifecycle (status, heartbeat, joined,
removal); slots, cleanup and host resources are read on Sandbox metrics. A
node's page keeps its allocations and the capacity figures Sandbox metrics
does not show (running, retained, snapshots, reserved).
Resource pages show what exists and monitor pages show how it runs: the
Agent list drops its Session, Token and coverage columns, which Agent
metrics already breaks down per Agent; last activity stays.
Core is one agents-api process with one execution owner, a Turn queue in
PostgreSQL polled into four execution slots, connected daemons and
periodic background jobs; it calls no model provider and has no message
queue or object store. The page now shows execution slots, queued Turns
(and those waiting for a daemon), connected daemons, database latency and
pool, background jobs and process memory, in the same header, headline
figures and chart-then-table sections as the other monitor pages. The
requested contract and where each figure comes from are rewritten in
docs/web/core-metrics-requirements.md.
Overview: selecting Core or a node in the fleet topology now opens an
anchored popover (coss ui's Base UI popover behind a thin ConsolePopover
wrapper) instead of leaving the page. A node shows its status, last
heartbeat, active sandboxes, CPU, available memory and disk, with links to
Sandbox metrics and the node's details; Core shows its status and, once
Core reports its own metrics, uptime, execution slots, queued Turns,
connected daemons and database latency, with a link to Core metrics. The
attention table now comes before usage by project, and the project table
keeps only usage columns (asset counts live on the project page).

Type scale: headline figures are 20px/500 with small units, page titles
17px, card titles 14px; Markdown headings drop to 16/15px, the first-run
title to 20px and the sign-in headline to at most 26px. No console surface
sets text above 20px.
Motion (motion.dev) carries the shared-layout moves: the active navigation
item is one chip that glides to the next page, and each segmented
control's thumb glides between options, with one 320 ms spring without
bounce. Its DOM features load in their own chunk after first paint, and
MotionConfig follows the reduced-motion preference.

Live figures on Overview, Agent metrics and Core metrics roll their digits
to a new value on refresh (NumberFlow) instead of swapping. Charts draw in
once per range: bars rise in a short left-to-right wave, lines trace from
their first point. A running Turn ends with the Agent's shimmering
"Working…"/"Queued…" line (Beautiful UI's shimmer), pending status dots
breathe, and new conversation messages settle into place.

First reads no longer print "Loading…": the remaining loading lines are
skeletons in the final layout — a headline strip with chart panels on the
monitor pages and a Session's Runtime charts, a facts card with a table on
detail pages, and table rows on Projects. The reduced-motion rule now also
drops animation delays so staggered elements appear at once.
Conflicts: the client package keeps the console's template projection
module and exports the administrator types explicitly (Skill and
SkillVersion come from ./types). The Web docs take main's rewritten
structure and now describe the React console as implemented; the page
map and a current overview screenshot replace the old product tour.
protocol-coverage keeps the console's route-by-route use and adds main's
evidence section.

Core metrics: #97 serves the contract this branch proposed, so its
requirements draft is removed in favour of
contracts/agents-api/core-metrics.md. The console server now forwards
GET /core/v1/admin/core-metrics; without it the Core metrics page and the
Core popover could not reach Core.
The Playwright suite still exercised the old execution console against a
fixture Core on /v1. It is replaced by one test per acceptance behavior
against fixture-console.mjs, a synthetic console service (sign-in,
/core/v1/admin, /core/v1/sandbox) with deterministic data, in-memory
writes and injectable failures: administrator setup and sign-in, Project
and key lifecycle with one-time key display, an unconfirmed key issue that
is never replayed, copy results, a refused deletion, the monitor pages, a
read-only Session conversation, and node enrollment and removal. Every
test asserts the browser sent nothing to /v1 and no Authorization header.
Vite now proxies /console like the production service.

Fixes found by the new tests:
- ConsoleSelect put its accessible name on Base UI's root, which renders
  no element, so every project and target picker was an unnamed combobox;
  the name is now on the trigger.
- Name fields in the project and key dialogs were labelled by their help
  tip's button; the label now names the input explicitly.
- A successful copy did not refresh the target project's cached lists, so
  the copy appeared only after a manual refresh.
- An uncertain deletion on a detail page no longer navigates back as if it
  had succeeded: the dialog stays with the uncertain message while the
  page is re-read.
- A 409 from Core (archived project, existing ID) shows Core's reason; Core
  has no name conflict, so the "already in use" message is gone.
- First-run setup stays on screen until it finishes, so a background
  re-read of the projects cannot take the only view of the first key away.
  An unconfirmed key issue there offers opening the console to check
  instead of issuing a second key unseen.
- Overview no longer says "Nothing needs attention" or draws a complete
  activity chart when Session lists failed to read or Core's summary counts
  Sessions that were not listed.
- Agent metrics reports a failed read instead of "no Turn was created"
  when a Session list failed.
- The Core metrics client maps an unrecognised service status to unknown,
  never running, and rejects a response without a resolution.
- A failed /console/config read is a failure with a retry, not "sandbox
  administration is not configured"; only a 404 means not configured.
- Deleting from the Session log also drops the Session from the cache.
- Sandbox slots count online nodes only, for both use and limit; the pool
  limit line is drawn only where Core observed the pool.
- Acceptance: a null Core figure must show as "—"; the key-discard check no
  longer depends on markup; the unused in-browser /v1 route installer is
  removed from the fixture data.
@SaladDay

Copy link
Copy Markdown
Collaborator Author

Integration review found two frontend error-state issues to fix before merging. Backend/deployment work continues separately; the owner confirmed these should stay with the frontend team.

  1. apps/web/src/lib/projects.tsx:47,186,210: when the initial /core/v1/admin/projects request fails, resource collections become ready with empty rows and no error. Resource refresh invalidates only collection queries, so it does not recover the project dependency after the upstream recovers. A failed project refresh with cached data is also reported as ready. Preserve the project read error/stale state and retry that dependency from resource refresh. Acceptance: first-load failure is not an empty catalog; refresh recovers after the API succeeds; cached rows remain visible with an explicit failed refresh.
  2. apps/web/src/features/metrics/AgentMetricsPage.tsx:207 and apps/web/src/features/overview/OverviewPage.tsx:101,400: when every selected Project's Session-list request fails, Agent metrics still says no Turn was created, and Overview draws zero activity and says nothing needs attention. Distinguish an actual empty result from partial and wholly unavailable reads. Acceptance: all-503 responses produce unavailable/error states, not definite zero/no activity; partial successes retain their explicit coverage; a successful empty response still uses the normal empty state.

Independent review baseline: main 7322982a8309a17eb1d7ca72e0501918ca18cacf; integrated candidate 712be3fad8b6b5bacf130601718ec4de16514889. No frontend production fixes were made by the backend task. Production-console browser tests and onboarding documentation are on codex/cluster-console; please keep the frontend changes on this PR and we will integrate them without overwriting either branch.

Deferred, nonblocking: generic resource collections reach a 10,000-row cap without preserving a truncation indicator.

@SaladDay

Copy link
Copy Markdown
Collaborator Author

Follow-up: bd4932d already addresses the Session-read monitoring issue described above; it has been integrated into the backend acceptance branch for verification. The remaining project-dependency failure/retry issue is in apps/web/src/lib/projects.tsx, which that commit does not change. Please focus the remaining fix there. We are retaining the new production-console tests and the frontend team's changes together.

Actions in card and section headers (Manage nodes, Session log, Projects
and keys on Overview; Manage nodes on Sandbox metrics) were borderless text
links while every other header action (Issue key, Copy to project, View
Sessions) is an outline button. They are now outline buttons; text actions
remain only for per-row table actions and popover links.

The Session conversation was a centred 860px column, leaving wide empty
bands on both sides of its card. It now spans the card: each Turn's meta
line runs edge to edge, the user's message sits at the right edge, and the
Agent's work and reply start at the left, with only the reply held to a
readable measure.
@SaladDay

Copy link
Copy Markdown
Collaborator Author

The user confirmed that frontend error-state repairs remain with the frontend owner. The open item is the Project-list dependency failure/retry behavior described above; no frontend production repair was made in the backend integration task.

Actual deployment acceptance is complete: one Core/Web/PostgreSQL deployment on mx2, Docker nodes on mx/mx1/mx2, real Kimi K3 execution with Codex/Claude/MiniMax, template File/Skill initialization, live Files.list and persisted report content, Project/admin isolation, and thirteen console pages. Web is frozen at integrated 35183f8 (including bd4932d); cosmetic 86829ca was not added during acceptance. Core/Runtime remain a7ebbe7. Web restart preserved all node IDs and existing Session/artifact data.

Integration PR #99 remains stacked on this PR. Latest make check-web passed with 12 real-console-server browser cases; those use a synthetic Core upstream, separately from the actual-cluster acceptance above. The full gate's execution-ownership test failure and bounded rerun are recorded on #99 and the task board. Please address the Project-list blocker before main merge.

The table toggle expanded the numbers inside the chart panel, stretching
the chart grid and pushing the neighbouring chart out of line. It now
opens a dialog titled with the chart, holding a scrolling table with a
pinned header; rows include seconds when buckets are shorter than a
minute, so 30-second buckets no longer repeat the same label.
Signing in and first-run setup now share one frame: a dark stage beside
the task panel. The stage uses Magic UI components (MIT), adapted to the
console's lazy Motion: a flickering indigo dot grid under slow light rays,
Core as the Parsar mark on a tile with a travelling border beam, and two
orbits of the things Core manages. The Parsar mark is itself nodes on a
ring.

First run is three steps with progress in the panel header: the
administrator account, the first project and its key (shown once; the
example request types itself into a terminal), and a new three-chapter
tour (Monitor, Resources, Platform) whose stage shows real dark
screenshots of those pages, in English or Chinese. It replaces the
introduction removed with the /v1 migration, and it makes no request of
its own.

Steps change inside a View Transition: the stage holds still while the
panel slides and blurs across. Opening the console dissolves the
onboarding and reveals the console in a circle from the pressed button.
Right after the account is created, the shell keeps the stage while the
projects load instead of flashing the console. With reduced motion the
orbits hold still, the grid is a still frame, the request is a plain block
and no transition runs.

Acceptance: a fresh-install test covers setup, the first project and its
key shown once, the tour and the console.
@SaladDay
SaladDay marked this pull request as ready for review September 25, 2026 07:29
@SaladDay
SaladDay merged commit f7fe8b5 into main Sep 25, 2026
3 checks passed
@SaladDay
SaladDay deleted the codex/admin-console-redesign branch October 7, 2026 06:37
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