Commit graph

508 commits

Author SHA1 Message Date
Bryan Helmkamp
2d36ef63cc
ci(web): isolate Bun test files
Some checks failed
Rust / Format (push) Waiting to run
Rust / Clippy (push) Waiting to run
Rust / Generated Docs (push) Waiting to run
Rust / Test (Linux) (push) Waiting to run
Rust / Test (macOS) (push) Waiting to run
TypeScript / Typecheck (push) Has been cancelled
TypeScript / Test (push) Has been cancelled
TypeScript / Build (push) Has been cancelled
2026-05-11 00:20:42 -04:00
Bryan Helmkamp
4fa4716015
refactor(core): simplify reviewed run cleanup
Reuse shared frontend formatting and SSE dedupe helpers, tighten typed sandbox handling, remove obsolete run DTOs, and collapse auth-session revoke into a single store operation.
2026-05-10 22:53:20 -04:00
Bryan Helmkamp
cccb557281
feat(api): unify public run shape
Return canonical Run payloads across run list, board, create, and lifecycle endpoints. Move archive state out of RunStatus and into lifecycle metadata, split sandbox runtime from planned sandbox data, and separate static pull request records from live pull request details.

Regenerate the TypeScript API client and migrate web, CLI, server, store, workflow, and API tests to the new contract.
2026-05-10 20:48:55 -04:00
Bryan Helmkamp
92ce72da6e
refactor(web): simplify profile sessions layout
Split the unified list into separate Browser and CLI panels and drop
provider, login, kind/current badges, and user agent. Each panel shows
just the timestamps that matter, with revoke gated to CLI sessions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 14:32:19 -04:00
Bryan Helmkamp
d2623662e0
feat(web): build unified auth sessions page
Render /profile/sessions from the new GET /api/v1/auth/sessions API.
The page shows the current browser session and active CLI sessions in one
list, with revoke buttons gated by the backend-supplied revocable field.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 14:30:00 -04:00
Bryan Helmkamp
acec32cea9
feat(web): build live events page in settings
Replaces the /settings/live-events placeholder with a working page that
streams server-wide events from /api/v1/attach. Shares the leader-owned
cross-tab EventSource so additional tabs subscribe without opening
parallel connections.

The page keeps an in-memory ring buffer (newest first, max 1,000) with
id or run_id:seq dedupe and resets on remount; live-only by design,
nothing is replayed on connect or persisted in the browser. Reuses the
existing event-debug filters, search, and details panel, and links each
row's run_id to /runs/:id. The category filter is the static set of
DebugCategory values so "All types" always matches.

Settings layout is now fullHeight-aware so the events page can fill the
viewport alongside the sub-nav. DebugEventDetailsPanel's event prop is
broadened to a shared EventDisplayPayload shape so it accepts both
EventEnvelope and the live payload.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 14:05:10 -04:00
Bryan Helmkamp
5209d05623
refactor(sandbox): unify run sandbox identity
Replace the separate sandbox record shape with a typed RunSandbox model shared by projections, API responses, and generated clients. The public contract now uses SandboxProvider plus a non-null id and working_directory, and removes sandbox identifier/name leakage.
2026-05-10 13:16:57 -04:00
Bryan Helmkamp
3acfa9eb93
feat(web): add profile sub-navigation with Sessions
Wraps /profile in a left-sidebar layout. Existing profile page becomes
the index; adds a placeholder /profile/sessions. Renames the identity
rows from "IdP issuer"/"IdP subject" to "Issuer"/"Subject".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 12:40:50 -04:00
Bryan Helmkamp
47f581cc1d
fix(server): improve sandbox service discovery
Fall back to procfs when ss is unavailable, report the discovery source in API metadata, and surface the sandbox install tip in the services UI. Previewable services are ordered first for clearer service selection.
2026-05-10 12:40:38 -04:00
Bryan Helmkamp
a74ae2e7f8
feat(web): add settings sub-navigation with Live Events
Wraps /settings in a left-sidebar layout. Existing settings page becomes
the index; adds a placeholder /settings/live-events. The layout owns the
section h1 and hides the app-shell header.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 12:20:42 -04:00
Bryan Helmkamp
7b832c74a8
feat(web): add Services tab to sandbox page
Lists backend-discovered TCP services for a run's sandbox between the
Terminal and Filesystem tabs. Previewable ports open a signed Daytona
URL in a new browser tab; the rest render as Unavailable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 11:56:05 -04:00
Bryan Helmkamp
1f6965386c
refactor(web): rename Workflows tab to Automations
Repurpose the /workflows tab to manage Automations (e.g., scheduled
workflows). The underlying Workflow domain entity, API types, and
"workflow runs" are unchanged — this is a web-surface rename only:
URLs (/workflows -> /automations), route file names, default-export
component names, page titles, breadcrumbs, and the visible UI labels
on these pages (Create Automation, Search automations..., Run automation).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 10:47:46 -04:00
Bryan Helmkamp
d0f3676d88
fix(web): hide filesystem directory sentinels 2026-05-10 10:41:02 -04:00
Bryan Helmkamp
f607068a99
fix(web): wrap full-screen terminal route in ToastProvider
TerminalView calls useToast() unconditionally, so the chromeless route
crashed with "useToast must be used within a ToastProvider" because the
route lives outside the AppShell that normally provides it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 10:32:11 -04:00
Bryan Helmkamp
e4093a2e61
feat(web): virtualize sandbox file preview and handle empty files
Wraps the Pierre File renderer in WorkerPoolContextProvider + Virtualizer
so long file previews scroll efficiently and reuse the shared highlighter
worker pool. Adds a content-aware sandbox cacheKey so previews don't
re-highlight unchanged content. Empty files now render an "Empty file"
state instead of mounting an empty File component.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 10:25:08 -04:00
Bryan Helmkamp
ee3ef3a3b2
feat(web): add "Open in new tab" button to embedded terminal toolbar
Mirrors the affordance on the VNC panel. The button links to
/runs/:id/terminal, which renders the chromeless full-screen TerminalView
in a new browser tab.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 10:23:42 -04:00
Bryan Helmkamp
cb316936e3
feat(web): add chromeless TerminalView and full-screen terminal route
New `/runs/:id/terminal` route renders a bare TerminalView at viewport
size, opened outside the AppShell so there is no nav, sidebar, or run
detail tabs around it. TerminalView gains a `chromeless` prop that hides
the toolbar and decorative wrapper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 10:23:11 -04:00
Bryan Helmkamp
5ac9a188c6
refactor(web): drop Start nav tab and reuse sparkles for Workflows
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 10:22:18 -04:00
Bryan Helmkamp
04b37ed1d3
refactor(web): collapse sandbox mode toggle into panel header rows
Previously the right column rendered the mode toggle on its own line
above each panel's status/action row, leaving an awkward double-row
header. Now each panel accepts a `leading` slot and hosts the toggle
inline with its existing status pill / breadcrumbs and action buttons,
so Terminal/Filesystem/VNC each occupy a single tight header row.

Also lands a quiet DEFAULT_DIR change in the filesystem panel from
/workspace to /, matching how non-clone sandboxes (and Daytona's image
layout) actually expose the working tree, plus matching test updates.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 10:01:19 -04:00
Bryan Helmkamp
8bde7d77f5
feat(web): add Daytona VNC mode to Sandbox tab
Adds a third right-column mode (Terminal | Filesystem | VNC) gated to
Daytona sandboxes. The panel POSTs /api/v1/runs/:id/sandbox/vnc, embeds
the signed noVNC preview URL in an iframe with clipboard + fullscreen
allowed, and renders distinct states for unsupported provider (Docker
hides the tab entirely), 409 startup failure (recoverable, "Try again"),
and 404/501 (non-recoverable). A reconnect button refetches the signed
URL when it expires.

Also fixes a Filesystem regression: the previous "skip first effect"
ref guard meant @pierre/trees never received its first resetPaths call
when the listing transitioned from empty to populated, leaving the tree
stuck on the initial empty model. Now the model is always synced via
resetPaths whenever the listing changes; verified live against a
Daytona /workspace + / listing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 04:21:35 -04:00
Bryan Helmkamp
cc5c505487
feat(web): add read-only Filesystem mode to Sandbox tab
Adds a Filesystem right-column mode alongside Terminal in /runs/:id/sandbox,
selectable via ?mode=filesystem. The persistent SandboxDetails left column
stays visible in both modes. Browses the run sandbox via the existing
list/get file endpoints, previews text files with @pierre/diffs, and falls
back to download-only for binary, oversized, and unreadable files.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 03:48:56 -04:00
Bryan Helmkamp
91a3f552e4
fix(web): widen gap between sandbox state label and native state
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 22:11:58 -04:00
Bryan Helmkamp
45c7f2d59f
fix(web): inline sandbox native state next to status label
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 22:11:28 -04:00
Bryan Helmkamp
2600eb905d
feat(web): merge Terminal into Sandbox tab as side-by-side panes
Combines the run detail Sandbox and Terminal tabs into one. Sandbox
details sit in a narrow left column and the terminal fills the wider
right column, separated by a vertical divider that runs from the tab
nav down to the steer bar.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 22:10:51 -04:00
Bryan Helmkamp
3b2c1fa3c4
fix(web): align command empty-state padding with populated layout
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 22:10:19 -04:00
Bryan Helmkamp
f73a1bb8f7
feat(web): add Sandbox tab and route to run detail
Adds /runs/:id/sandbox between Files Changed and Terminal, gated by
the same sandbox-presence check as Terminal. The route fetches
SandboxDetails through a new useRunSandboxDetails SWR hook and renders
provider-neutral panels for Overview, Resources, Labels, and
Timestamps. Null fields render as muted em dashes.
2026-05-09 21:48:31 -04:00
Bryan Helmkamp
02d494c268
feat(sandbox,server,web): add sandbox_details inspection and unify SandboxResources
Adds fabro_sandbox::sandbox_details, a control-plane inspection function
that maps Local, Docker, and Daytona providers into a shared
SandboxDetails record (state, image, resources, labels, timestamps).

To avoid type sprawl, the demo board's SandboxResources is unified with
the new control-plane shape (cpu_cores: f64, memory_bytes: u64,
disk_bytes: u64). The runs board chip in apps/fabro-web converts
memory_bytes back to GB for display.
2026-05-09 21:40:19 -04:00
Bryan Helmkamp
74862bdbaf
feat(web): add Thread DNA strip to agent stage tabs
Renders a Gantt-style strip below the Thread toolbar on agent and prompt
stages only. Bar position encodes start time and width encodes duration,
so empty stretches in the strip are real dead time (idle waits, sandbox
spin-up, time waiting on a human steer). Categories collapse to five
colors: system/agent/tool/user/interrupt. Tool/command bars use their
explicit durationMs; tool groups span first child's start to last
child's end so dead time between grouped tools is honored; assistant
bars span the gap from the previous activity's end to the message ts as
an approximation of "thinking" time; system/steer/interrupt are 4 px
instant markers. Hover shows kind/label/elapsed/duration in a portaled
popover; click selects the matching turn or tool group and shares state
with the existing event list and side panel.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 21:10:53 -04:00
Bryan Helmkamp
4f202303bc
fix(web): hide retry on non-recoverable terminal errors
Server-typed errors like "Local sandboxes do not support embedded
terminals" won't change on retry, so the ErrorState now omits the
"Try again" button for them. WebSocket connection failures stay
recoverable and keep the retry affordance.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 20:21:58 -04:00
Bryan Helmkamp
85a2cdda64
fix(web): show terminal errors as a centered ErrorState panel
Replaces the stray red caption + empty terminal frame with the shared
ErrorState card so errors like "Local sandboxes do not support embedded
terminals" land in a clear, retry-able panel instead of floating above a
misleading blank terminal.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 20:21:09 -04:00
Bryan Helmkamp
06277c79f5
fix(web): balance top and bottom padding in stage renderer area
The outer scroll container had pt-2 with pb-[calc(1.5rem+dock)], so
content sat ~8px below the tab toolbar but ~24px above the dock —
visibly off. Each new renderer also re-applied its own pt-2, doubling
the top spacing. Bump the outer pt to pt-6 so it matches the 24px
baseline bottom, and drop the duplicated pt-2 from every renderer
wrapper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 19:33:13 -04:00
Bryan Helmkamp
8b4442096d
refactor(web): polish stage renderer designs after visual review
Tighten the meta bar (drop redundant labels, fold timestamp into the
duration tooltip), elevate the wait card to a centered hero clock,
strengthen the conditional view with the actual chosen edge and
condition expression sourced from run-level edge.selected events,
upgrade the fan-in selected card with a trophy badge and gradient, and
redesign the parallel stat strip with toned numbers and a duration
column.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 19:16:27 -04:00
Bryan Helmkamp
80d3965670
feat(web): add DNA strip timeline to debug events view
Renders a full-width strip below the Debug toolbar with one bar per
event placed by elapsed time. Hover shows category/name/elapsed;
click opens the event in the side panel. Collapses event categories
to five colors (agent/command/lifecycle/human/system) and shows the
event count persistently on Debug so the strip's density has a number
next to it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 18:51:35 -04:00
Bryan Helmkamp
b6ebe9ca50
feat(web): add specialized stage renderers for non-agent handlers
Replace the raw Debug fallback for human, conditional, parallel,
parallel.fan_in, stack.manager_loop, and wait stages with purpose-built
views — Q&A transcript, decision card, children grid, fan-in results
with reducer transcript, cycle summary, and live waiter clock. Add a
generic Summary card as the new default for any unknown handler so
future StageHandler additions get a usable view for free. Debug tab
remains as the escape hatch on every handler.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 18:35:19 -04:00
Bryan Helmkamp
7e9edcf229
fix(web): show sandbox id in terminal status 2026-05-09 17:21:33 -04:00
Bryan Helmkamp
fb577b1fcb
fix(web): add bottom padding inside terminal frame
Give the terminal wrapper pb-3 so the active console no longer hugs
the bottom edge of the bordered frame.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 17:12:47 -04:00
Bryan Helmkamp
61ab94195e
feat(sandbox): copy Docker exec access command 2026-05-09 17:05:46 -04:00
Bryan Helmkamp
160c21c8b1
fix(web): rename run "Diff" tab back to "Files Changed"
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 16:53:47 -04:00
Bryan Helmkamp
872c81bdc7
fix(web): stop terminal bottom row from being clipped
The xterm.js renderer cell height is fontSize (13) × lineHeight (1.45)
= 18.85px — non-integer. FitAddon proposes N rows where
N × cellHeight <= available height, but sub-pixel rounding in the
renderer (and font-load timing on first paint) lets the Nth row
extend past the wrapper's content edge, so the last visible line
gets half-clipped.

Reserve one row of buffer in the fit calculation (proposed.rows - 1)
so xterm is never asked to render right up to the bottom edge. The
re-fit on document.fonts.ready stays in place; sendResize now reads
terminal.cols/rows directly so the server sees the same dimensions
xterm actually uses.

Trade-off: ~18px less visible terminal area. The alternative is
switching to an integer cell height (e.g. lineHeight 18/13), which
we can revisit if the lost row matters.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 16:53:33 -04:00
Bryan Helmkamp
01f33e6d50
refactor(web): polish terminal tab chrome and theme
- Replace heading + status badge with a single status pill that folds in the sandbox provider
- Make Reconnect an icon-only button with tooltip; keep SSH labeled
- Darken the terminal canvas and brighten the ANSI palette for higher contrast
- Trim the static gap above the steer-bar dock from 0.5rem to 0.25rem

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 16:41:49 -04:00
Bryan Helmkamp
0de07bbfec
refactor(web): rename Files Changed tab to Diff and reorder before Terminal
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 16:41:41 -04:00
Bryan Helmkamp
0f30150264
fix(web): show empty state on Billing tab when no models were used
Runs with only non-billable stages rendered as a header + empty body
+ all-dashes "Total" row, which looked broken. Show the existing
EmptyState panel ("No model usage") instead, keeping the original
"No stages yet" message for runs that haven't started executing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 16:41:28 -04:00
Bryan Helmkamp
39d8e65547
fix(web): tighten terminal dock spacing 2026-05-09 16:22:19 -04:00
Bryan Helmkamp
bf6bd670ce
fix(web): keep terminal clear of steer bar 2026-05-09 16:21:04 -04:00
Bryan Helmkamp
db3f348fab
feat(runs): add sandbox terminal
Expose a run-scoped websocket terminal for Docker and Daytona sandboxes, and add the web terminal route so sandbox-backed runs can be inspected interactively from the run detail page.
2026-05-09 16:06:04 -04:00
Bryan Helmkamp
237318f13f
Merge remote-tracking branch 'origin/main' 2026-05-09 15:40:18 -04:00
Bryan Helmkamp
65c8a12cce
Merge remote-tracking branch 'origin/main' 2026-05-09 15:39:44 -04:00
Bryan Helmkamp
6cfed82654
refactor(run-files): rename diff selection picker 2026-05-09 15:33:54 -04:00
Bryan Helmkamp
705ea0268a
refactor(run-files): extract commit picker options 2026-05-09 15:33:19 -04:00
Bryan Helmkamp
67decad7b5
feat(billing): project live stage token usage
Store live per-stage token counts on StageProjection, carry typed billing model identity through agent.message events, and derive billing rollups from the projection so in-flight stages can report usage before terminal events arrive.
2026-05-09 15:25:51 -04:00