Commit graph

780 commits

Author SHA1 Message Date
Bryan Helmkamp
7d7931e56a
feat(web): show GitHub App install return state on /setup
When GitHub redirects back to /setup after installing the app, render a
distinct view that confirms the install and points users to retry the
run, instead of the first-time terminal setup instructions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 10:41:28 -04:00
Bryan Helmkamp
beff3985f0
ui(web): add Settings/JSON view toggle on settings page
Place a Settings | JSON toggle on the right of the description row. The
JSON view renders the full server settings object as syntax-highlighted
server-settings.json via the existing CollapsibleFile component.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 09:12:40 -04:00
Bryan Helmkamp
81f73e8246
ui(web): syntax-highlight DOT source on run graph page
Reuse the existing @pierre/diffs Shiki highlighter and registered DOT
grammar (already used on the workflow definition page) so the Source
view renders workflow.fabro with proper highlighting instead of plain
monospace text.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 09:09:45 -04:00
Bryan Helmkamp
b36be97675
fix(web): keep graph mounted when toggling to source view
Toggling to Source unmounted the graph container, so switching back
mounted a fresh inner div without re-running the render effect — leaving
"Loading diagram..." stuck. Hide the graph via the hidden attribute
instead so the cached SVG and pan/zoom state survive view switches.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 09:01:38 -04:00
Bryan Helmkamp
066cd9fa15
ui(web): right-align Graph/Source toggle on run graph page
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 09:00:42 -04:00
Bryan Helmkamp
9ad47990f4
fix(web): include server URL in auth quick start
Expose the configured server.web.url in system info so the empty runs quick start can show a runnable fabro auth login command instead of a placeholder.
2026-04-29 07:45:17 -04:00
Bryan Helmkamp
ab9b28875b
fix: close sandbox-native metadata gaps
Ensure local runs use the worktree checkpoint path by default, expose source and sandbox paths in API/web surfaces, and remove dead fork/rewind push controls. Update docs for clone-based sandboxes and durable checkpoint timelines.
2026-04-28 08:05:18 -07:00
Bryan Helmkamp
0543c5c8fe
chore: simplify sandbox-native git metadata code
- Reuse fabro_sandbox::shell_quote in sandbox_metadata.rs and sandbox_git.rs
  (CLAUDE.md mandates the shared helper, not local reimplementations).
- Skip git_diff call on first checkpoint when prev SHA equals new SHA;
  previously diffed a SHA against itself, costing one sandbox round-trip.
- Drop tuple-match theatre in write_snapshot cleanup.
- Type LEVEL_COLOR as Record<LogLevel, string> so the lookup is exhaustive.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 06:39:01 -07:00
Bryan Helmkamp
cdd46b4fa8
Make git metadata sandbox-native 2026-04-27 21:43:15 -07:00
Bryan Helmkamp
fd1087fe2d
feat(api): expose workflow graph source as raw DOT
Add GET /api/v1/runs/{id}/graph/source returning text/vnd.graphviz so
the run graph can be inspected as the original Graphviz DOT in addition
to the rendered SVG. Refactor get_graph to share DOT loading with the
new handler. The web run-graph view gains a Graph | Source toggle that
lazy-loads and displays the DOT with a copy button.
2026-04-27 16:24:17 -07:00
Bryan Helmkamp
cdc43e05fc
feat(web): drop Unarchive action from archive toast
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 16:10:16 -07:00
Bryan Helmkamp
4beee7358b
feat(web): colorize run logs by level and target
Parse each tracing line in the run logs panel and tint the timestamp,
level, target, and message separately. Errors and warnings now stand
out at a glance (coral/amber) while debug/trace and the surrounding
chrome recede. Original whitespace is preserved so the formatter's
column alignment is intact.
2026-04-27 16:06:02 -07:00
Bryan Helmkamp
90b6db1e52
feat(web): polish runs board and install nav
Hide the Steer action on board cards outside demo mode so the action
list reflects what the operator can actually do. Hide the lifecycle
status pill on cards in the Initializing column since the column header
already conveys the state. Shorten the install wizard top nav label
"Object store" to "Storage".
2026-04-27 16:02:54 -07:00
Bryan Helmkamp
2460ffc37a
feat(install): add sandbox provider step to web install wizard
Operators choose Docker (default, zero-config) or Daytona (validated
via Daytona SDK) during browser install. Selection is captured in
settings.toml under [run.sandbox] -- explicitly even for Docker, so the
choice is locked in. Daytona keys land in the vault as DAYTONA_API_KEY
(Environment secret). Step always runs after object_store and before
the LLM step.

Server adds POST /install/sandbox/test (validates Daytona key via
client.list) and PUT /install/sandbox; both reuse the install-token
auth and InstallSecret redaction patterns established by object-store.
A resolve_install_sandbox_state helper preserves a saved Daytona key
when the operator revisits the step without re-entering it. The
in-memory api_key is dropped from PendingInstall after finish, matching
the manual_credentials cleanup for S3 access keys.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 14:59:17 -07:00
Bryan Helmkamp
44d1d7f5e2
refactor(api): reuse run summary domain type 2026-04-26 23:28:04 -04:00
Bryan Helmkamp
7ecd8df32e
refactor(web): simplify run logs view
Drop unjustified useMemo around byteCount, add void to mutate(), let
errorMessage return undefined for non-Error values so the description
doesn't duplicate the retry button label, and reuse formatBytes (hoisted
to lib/format.ts from insights-editor) so log size renders as "1.23 MB"
instead of "1,234,567 bytes".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 17:47:10 -04:00
Bryan Helmkamp
4e9d3774ef
feat(web): add run logs view
Add a "Run Logs" entry to the run detail sidebar that fetches the
worker tracing log via GET /api/v1/runs/{id}/logs and renders it with
auto-refresh while the run is live. Refreshes the embedded SPA bundle.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 17:38:22 -04:00
Bryan Helmkamp
c28b040c6f
fix(install): reject wildcard public URLs
Normalize bind-address wildcards before presenting install URLs, reject wildcard public origins at CLI and server install boundaries, and surface recovery guidance in the installer and doctor output.
2026-04-25 18:58:00 -04:00
Bryan Helmkamp
d1b0548197
fix(web): unbox file tree sidebar
Drop the border, rounding, and background from the FileTree wrapper
(and its empty state) so the tree sits directly on the sidebar
container.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 09:43:12 -04:00
Bryan Helmkamp
40fa088410
refactor(web): redesign settings page as titled panels
Replace the raw JSON dump with three panels (Server, Access & Capacity,
Integrations & Artifacts), each rendering a small set of curated rows.
Each row uses an aligned two-column layout — title and help on the
left, a typed value renderer on the right (toggle dot, mono path,
URL link, badge, tabular-nums count, listen/object-store summaries).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 09:37:55 -04:00
Bryan Helmkamp
be63bda5c8
fix(web): stabilize run files sidebar interactions
Reserve the desktop file-tree column while files and the lazy sidebar load, and make the custom changed-files filter drive the rendered tree directly.
2026-04-25 09:34:40 -04:00
Bryan Helmkamp
0f5280d857
fix(web): tighten run files tree navigation
Keep the changed-files tree selection aligned to valid file paths, avoid mobile and initial-reset overhead, and lazy-load the tree bundle. Refresh the embedded SPA assets to match.
2026-04-25 09:07:12 -04:00
Bryan Helmkamp
9b81aba086
feat(web): add Trees-based file tree sidebar to Files Changed tab
Adds a GitHub-style left sidebar to /runs/:id/files using @pierre/trees.
Lists only the modified files, shows git status per row, and wires
selection into the existing #file=<path> deep-link flow so clicking a
row scrolls and focuses the matching diff. Uses the @pierre/theme
pierre-dark Shiki theme for visual parity with @pierre/diffs.

Configured read-only (no drag-and-drop, no rename), flattens empty
directory chains, defaults to standard icons and default density, and
filters via hide-non-matches search. Hidden below the md breakpoint to
match where the diff style is forced to unified.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 08:32:11 -04:00
Bryan Helmkamp
e9388f02c0
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	apps/fabro-web/app/routes/run-files.test.ts
#	apps/fabro-web/app/routes/run-files.tsx
#	lib/crates/fabro-spa/assets/assets/entry-5nzjj9ar.js
#	lib/crates/fabro-spa/assets/index.html
2026-04-25 07:51:59 -04:00
Bryan Helmkamp
ac1e218162
feat(web): append short SHA to run files freshness label
`useFreshness` now appends the GitHub-style 7-char prefix of `meta.to_sha`
to the captured/fetched timestamp, e.g. `Captured 2m ago · a1b2c3d`.
The OpenAPI pattern guarantees at least 7 hex chars when present;
degraded responses with no captured commit gracefully omit the SHA.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 07:46:40 -04:00
Bryan Helmkamp
d4104be841
refactor(web): simplify SWR event plumbing
Share SSE subscription management, reuse query key builders, and remove duplicate route mapping/error helpers from the SWR refactor.
2026-04-25 07:37:17 -04:00
Bryan Helmkamp
ffbffa96aa
fix(run-files): align diff stats with visible files
Track numstat by path so sensitive, binary, symlink, and submodule entries do not inflate aggregate line counts, and clean generated client whitespace churn from the API update.
2026-04-25 07:36:33 -04:00
Bryan Helmkamp
a1f032e166
refactor(web): move server state to SWR
Replace React Router loader/action state paths with SWR query and mutation hooks.

Add targeted run and board EventSource managers that invalidate SWR keys, and refresh embedded SPA assets.
2026-04-25 07:16:41 -04:00
Bryan Helmkamp
a4e63ec897
feat(api): expose aggregate +/- diff stats on run files response
Adds `meta.stats: DiffStats` (required) to `PaginatedRunFileList` so the
Files Changed toolbar can render `+387 −104` next to the file count.

Server: refactors `list_binary_paths` into `list_diff_numstat`, which
returns the binary-path set plus aggregate `+/-` totals from a single
`git diff --numstat` invocation. The degraded patch-only response
populates the same field by counting `+`/`-` line prefixes in the
filtered patch (excluding `+++`/`---` file headers).

UI: `Toolbar` accepts `additions` / `deletions` and renders them as
mono-tabular `+387 −104` to the right of the file count. The block is
elided when the diff has 0 changes (e.g. binary-only or empty runs) so
the empty case stays clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 23:38:02 -04:00
Bryan Helmkamp
664b15ae86
feat(web): redesign run files toolbar as PR-style header
Replaces the panel-style toolbar with a single-row header showing
"<N> files changed" on the left and Captured-time + Split/Stacked
toggle + icon Refresh on the right. Heights of left and right groups
match. The Unified label is renamed to Stacked to match diffs.com
terminology; the underlying DiffStyle value is unchanged so the
@pierre/diffs option and the localStorage key continue to roundtrip.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 21:08:40 -04:00
Bryan Helmkamp
f537222372
feat(auth): store dev tokens in auth store
Persist dev-token credentials in auth.json alongside OAuth entries so CLI targets resolve credentials consistently across TCP and Unix socket flows.

Move install-time token minting to runtime storage, add auth login --dev-token, and refresh the embedded SPA after updating the stale dev-token hint.
2026-04-24 16:02:36 -04:00
Bryan Helmkamp
8aeaef5f33 fix(install): mount wizard at root route 2026-04-24 12:59:16 -04:00
Bryan Helmkamp
533785cd4c fix(install): expose local object store root 2026-04-24 12:38:04 -04:00
Bryan Helmkamp
b975a802dc fix(install): show AWS access key ID as plain input
The AWS access key ID is not a secret — swap its PasswordInput for a
regular text input so operators can read and edit it directly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 12:29:27 -04:00
Bryan Helmkamp
7d791c531b fix(install): use single-line install token input
Refresh the embedded SPA assets so the Rust bundle serves the updated install screen.
2026-04-24 12:20:17 -04:00
Bryan Helmkamp
099dd881a8
merge origin/main into local main
Integrates origin's worker-JWT-auth work (commits 8a6f83bb0..c847a828d)
with the config-boundary refactor that landed locally. Conflicts
resolved:

- commands/dump.rs: take origin's removal of the 500-line in-process
  test block (replaced by real-server integration coverage).
- commands/run/runner.rs: keep local's dense WorkflowSettings import,
  drop dead SettingsLayer import, pull in origin's ActorRef.
- manifest_builder.rs: adopt origin's lifted working_directory
  resolution (fixes #159 - manifest git detection in nested repos),
  but via local's resolve_working_directory_from_run API that takes
  the dense RunNamespace. Update the regression test's
  ManifestBuildInput literal to local's run_overrides/cli_overrides
  field shape.
- server.rs: keep origin's jwt_auth_mode/jwt_auth_state/
  test_user_subject/issue_test_user_jwt/issue_test_worker_token/
  create_run_with_bearer/bearer_request test helpers, adapt
  jwt_auth_state to local's create_test_app_state_with_session_key
  signature (ServerSettings + RunLayer), keep local's dense
  canonical_origin_settings that returns ServerSettings via
  server_settings_from_toml. Rewrite
  build_app_state_requires_session_secret_for_worker_tokens against
  the dense AppStateConfig (resolved_settings +
  resolved_runtime_settings_for_tests).

Post-merge verification: workspace builds clean, cargo +nightly
fmt --check all clean, cargo +nightly clippy --workspace
--all-targets -- -D warnings clean, cargo nextest run --workspace
4560 tests passed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 21:13:28 -04:00
Bryan Helmkamp
6fc7251471
close config boundary audit and settings snapshot naming 2026-04-23 19:30:30 -04:00
Bryan Helmkamp
7456cb3252
fix(deps): bump astro from 5.9.3 to 6.1.6
Patches GHSA-j687-52p2-xcff (CVE-2026-41067): XSS in define:vars via
incomplete </script> tag sanitization. Requires Astro >= 6.1.6.

Also bumps @astrojs/react to ^5.0.4 for Astro 6 compatibility.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 15:08:28 -04:00
Bryan Helmkamp
b2bcf0d5a8
refactor settings builders and dense run snapshots 2026-04-23 11:35:21 -04:00
Bryan Helmkamp
fa62da5d9d
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	lib/crates/fabro-api/build.rs
#	lib/crates/fabro-server/src/install.rs
#	lib/crates/fabro-server/src/serve.rs
#	lib/packages/fabro-api-client/src/.openapi-generator/FILES
#	lib/packages/fabro-api-client/src/models/index.ts
2026-04-22 21:18:50 -04:00
Bryan Helmkamp
a5228e7a04
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	lib/crates/fabro-spa/assets/assets/entry-8ah4aryw.js
#	lib/crates/fabro-spa/assets/index.html
2026-04-22 20:24:50 -04:00
Bryan Helmkamp
ef78228c06
refactor(install): flatten resolver, dedupe fetch wrappers, share step-submit helper
- Derive strum::IntoStaticStr on InstallObjectStoreProvider/CredentialMode and use it in as_session_value instead of a hand-written match.
- Split resolve_install_object_store_state: extract resolve_s3_manual_credentials and fold the redundant outer "missing credentials" guard into its (None, None) arm.
- Replace the per-endpoint installFetch boilerplate with installRequest / installJsonRequest<T> so each install-api wrapper is a single call.
- Extract runStepSubmit inside InstallApp; the LLM, server, object-store, and GitHub step handlers now share the setSubmitting / try / refresh-session / navigate / finally scaffolding.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 20:21:13 -04:00
Bryan Helmkamp
e184213330
refactor(install): collapse install UI pickers and dedupe server strings
- Derive install stepper's current step from INSTALL_STEPS instead of a hand-maintained pathname if-chain.
- Replace four near-identical picker components with one generic CardPicker plus per-flow option arrays.
- Extract repeated object-store validation error strings into constants and a small helper.
- Run the S3 artifacts/ and slatedb/ prefix probes concurrently via tokio::try_join!.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 19:43:49 -04:00
Bryan Helmkamp
4bf0c40319
feat(install): add object-store step to web install 2026-04-22 19:31:09 -04:00
Bryan Helmkamp
ebb8bf7add
refactor settings API entrypoints 2026-04-22 18:58:47 -04:00
Bryan Helmkamp
6c3211e3ce
refactor(run-status): unify tagged lifecycle states 2026-04-22 17:15:13 -04:00
Bryan Helmkamp
a8599a924f
feat(install): pivot happy path to fabro server start web wizard
The primary install flow is now to start the server, complete setup in a
browser-based wizard, and restart. fabro install is retained as the
headless CLI-only alternative.

- Auto-open the install URL in the user's browser when fabro server start
  enters install mode; print a manual-open fallback when open::that fails
- Rewrite install.md so agents drive the full start → wait → restart loop
- Retarget install.sh Y/n prompt from fabro install to fabro server start
- Update README, quick-start, deploy-server, cli reference, and marketing
  captions to point at fabro server start as the next step after download
- Add troubleshooting entries for "wizard didn't open" and "server exited
  after wizard"

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 16:02:49 -04:00
Bryan Helmkamp
710f9869f0
fix(auth): stop demo mode from overriding authentication
The demo router hardcoded AuthMode::Disabled, which caused /auth/config
and /auth/me to lie and let demo endpoints be reached without a session
whenever the fabro-demo=1 cookie was set. With the cookie set on a
GitHub-configured server, /login rendered "Paste your dev token" with
no input and no GitHub button because /auth/config returned empty
methods.

Have the demo router inherit the real AuthMode so demo mode is purely a
data-source toggle: authentication is identical regardless of the
cookie. Update the translate test that locked in the old bypass, add a
companion test for the authed happy path, and add a regression test
that /auth/config returns real methods under the demo cookie.

As defense in depth, the login page now renders an explicit "no
authentication method is configured" state when methods is empty
instead of the misleading dev-token prompt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 16:02:49 -04:00
Bryan Helmkamp
3f6cc1f1ba
Merge remote-tracking branch 'origin/main' 2026-04-21 14:47:23 -04:00
Bryan Helmkamp
11ec4a2208
feat(runs): prepend fabro auth login to blank-slate quick-start on github-auth servers
On a GitHub-auth-only server, `fabro repo init` fails for a fresh CLI
because no credential is present yet, so the onboarding hint was wrong
for those installs. Fetch /auth/config alongside the board query and,
when `methods` contains "github", prefix the quick-start with
`fabro auth login`. The copy-to-clipboard target is derived from the
same list so it stays in sync. Falls open to the prior two-line hint if
the config call fails — the blank slate must not gate on that request.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 14:44:14 -04:00