Skip to content

CL-6469: agents list to spec - #195

Merged
TheGreatAxios merged 7 commits into
mainfrom
cl-6469-agents-list
Aug 21, 2026
Merged

TheGreatAxios merged 7 commits into
mainfrom
cl-6469-agents-list

Conversation

@TheGreatAxios

@TheGreatAxios TheGreatAxios commented Aug 21, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Brings apps/web/src/pages/agents-page.tsx (Agents list only) up to the mock spec's §5.1:

  • Table columns: checkbox · Agent (name/slug two-line cell) · Description (.opt → hidden lg:table-cell) · Status · Model (.opt) · Runs · 7d (.opt, numeric)
  • Bulk row selection via @corbits/react-ui's useListSelection/SelectionCheckbox/BulkActionBar (PR CL-5849: Return 409 not 500 when an agent can't resolve an inference source #33) — shift/cmd range select, header select-all/indeterminate, floating bulk bar with Archive only
  • Top-bar page action renamed to primary "New agent" (#Plus), per §2.3's page-action inventory (was "Create")

Update after 2nd peer review (both blocking items fixed)

  1. Partial-failure bug in bulk archive fixed. onArchiveSelected used Promise.all, which rejects on the first failure even though the other archive calls already succeeded server-side — a mid-batch failure left the roster showing stale state and the toast implied nothing happened. Replaced with archiveDefinitions (Promise.allSettled) + archiveResultToast, both exported and unit-tested: the definitions/runs queries are now invalidated regardless of outcome, and the toast reports an honest count ("Archived 4 of 5 — the rest failed" / all-succeeded / all-failed).
  2. prettier --check now passes on the touched files (bunx prettier --write run on agents-page.tsx and agents-page.test.tsx).
  3. Dropped the now-unused Trash export from packages/icons (was left over from before Delete was removed from the bulk bar).

Update after 1st peer review

  • Bulk Archive now really works. onArchiveSelected calls the real setAgentDefinitionStatus(tenantId, id, "stopped") — the same PUT route the single-agent Archive button on agent-detail-page.tsx already uses. Duplicate/Move/Delete are dropped from the bulk bar entirely: batch duplication would need slug-collision handling the detail page's single-agent duplicate never had to solve, and Move/Delete have no backend primitive at all.
  • Status tones fixed. Adopted @corbits/react-ui's own RUN_STATUS_TONE convention: Running → info (blue) with a pulsing StatusDot (live prop), Idle → success (green). Blocked (danger)/Archived (neutral) were already correct.

Real-data notes

  • Status is derived from real fields: a stopped definition always reads Archived; a deployed one reads Running if any of its top-level runs (listTopLevelRuns) is running, Blocked if any is error, else Idle — grounded in WorkflowDefinitionResponse.status + WorkflowRunResponse.status, not invented states.
  • Model is fetched lazily per row via getAgentCapabilities, the same plain fetch-effect pattern (not react-query) the existing detail rail already uses — a load/fetch failure degrades that row's cell to — instead of blocking the table.
  • Runs · 7d counts a definition's top-level runs with createdAt inside the trailing 7 days.
  • Kept the existing "Workbenches" side-panel summary (on row selection) untouched — not one of the spec's table columns, but real, tested functionality this task wasn't asked to remove.

Known follow-up (not blocking, flagged for a ticket)

AgentModelCell fires one uncached getAgentCapabilities fetch per row on mount via a plain useEffect — on a real-size roster every render refires every row's request (no batching, no cache). Needs either a batch capabilities endpoint or a react-query cache keyed by (tenantId, definitionId) before this scales past a handful of agents.

Test plan

  • bunx prettier --check on touched files — clean
  • bunx eslint on touched files — clean
  • bun run typecheck (apps/web) — clean
  • bun run build (apps/web) — clean
  • bun test ./src ./test (apps/web) — 786 pass, 0 fail (full existing suite, no regressions)
  • bun test (packages/icons) — 3 pass, 0 fail
  • New tests: archiveDefinitions/archiveResultToast unit tests covering partial/full success/failure, plus the earlier agentRosterStatus/runsInLast7Days unit tests, populated/empty render, Running's live-dot rendering, selection checkboxes + header select-all, no bulk-bar leakage at zero selection, "New agent" top-bar action, workbench-link side panel still works
  • NOT verified: no live-stack/browser check was done (per instructions — owner is testing live on :3000). Bulk-bar Archive's real network round-trip (including an actual partial-failure scenario against the live hub), the Model column's real network latency/skeleton timing, and Status against real multi-instance data are unverified beyond render/unit-test level.
  • NOT verified: agent detail page (agent-detail-page.tsx) — out of scope, untouched, owned by another unit.

Do not merge — flagging for peer review per task instructions.

Covers the new agentRosterStatus/runsInLast7Days helpers and the
per-row checkbox + header select-all rendering the roster table gains.
…, New agent action

Roster table gains Status (folded from a definition's deployed/stopped
state and its live instances), Model (lazy per-row fetch), and Runs·7d
(counted from top-level runs created in the trailing week) alongside
bulk row selection (useListSelection/SelectionCheckbox) and a floating
BulkActionBar (Duplicate/Archive/Move/Delete). The top-bar action is
now "New agent" per the page-action contract. Duplicate/Archive/Move/
Delete surface as an honest not-yet-wired toast — the hub exposes no
bulk mutation endpoint for any of them yet.

Adds Archive/Trash to the shared icon re-export surface.
Bulk bar now wires Archive to the real setAgentDefinitionStatus PUT
(same route the single-agent Archive button already uses), and drops
Duplicate/Move/Delete — none of the three has a real bulk primitive,
and a button that can't do what it says is worse than no button.

Status tones now adopt react-ui's own run-status convention instead of
an invented mapping: Running is the blue "live" tone with a pulsing
StatusDot, Idle is the green "healthy" tone — Blocked/Archived were
already right.
Covers archiveDefinitions/archiveResultToast: one id failing must not
hide or roll back the ids that already succeeded server-side, and the
toast copy must report an honest count for partial/full success/failure.
onArchiveSelected used Promise.all, which rejects on the first
rejection even though the other archive calls already succeeded
server-side — the roster kept showing stale state and the toast
implied nothing happened. Switch to Promise.allSettled
(archiveDefinitions), always invalidate the definitions/runs queries
regardless of outcome, and toast a real count via archiveResultToast.

Also runs prettier on the touched files and drops packages/icons'
Trash export, unused since Delete was removed from the bulk bar.
@TheGreatAxios
TheGreatAxios merged commit c879408 into main Aug 21, 2026
2 checks passed
@TheGreatAxios
TheGreatAxios deleted the cl-6469-agents-list branch August 25, 2026 15:29
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