Commit graph

3454 commits

Author SHA1 Message Date
Actual Operator
67b2f3d037 Sync context files with ADRs
- Update CLAUDE.md (claude)
- Update .claude/rules/fcd6a21d-756b-4d3f-98d7-f42d21122afd.md (claude)
- Update .claude/rules/da815559-806f-4816-ac62-f2bcba187047.md (claude)
- Update .claude/rules/860946d2-f81f-45ed-b3f2-25c8d5f4956f.md (claude)
- Update .claude/rules/8743e5ed-c257-4d49-8295-a4481f8523b5.md (claude)
- Update .claude/rules/67d628ca-c9de-4922-93cb-1fd54450f492.md (claude)
- Update .claude/rules/a4786ef4-01e0-4b65-9c9f-0c3175726c86.md (claude)
- Update .claude/rules/b1a53926-9804-45b7-9543-634d35c15734.md (claude)
- Update .claude/rules/4dbd1df3-2cdc-4996-a874-d94ee89c9983.md (claude)
- Update .claude/rules/c81e5425-fcc1-4177-9246-bd167e4322af.md (claude)
- Update .claude/rules/9607dcb3-91d3-44b9-85f9-ccb1fa25bd76.md (claude)
- Update .claude/rules/f39ea92e-c1c0-46b6-b4ff-9c07cc3b42b7.md (claude)
- Update .claude/rules/372c20f8-a9ae-4489-b3a3-4825d3343af4.md (claude)
- Update .claude/rules/19fbda95-be0a-43ce-88bd-b2cbb1c4075a.md (claude)
- Update .claude/rules/36c17245-9a45-4855-affd-3e23712797d8.md (claude)
- Update .claude/rules/1267d2fe-4cfa-4c45-9004-ada782af479d.md (claude)
- Update .claude/rules/57fb44e9-c959-408b-9e6a-87b058b1ecc7.md (claude)
- Update .claude/rules/0ba59d63-b106-4111-a75e-cb18a23f7c56.md (claude)
- Update .claude/rules/0c99d9c0-10fb-40b3-bc7d-6f69d4cd5498.md (claude)
- Update .claude/rules/f5680bc5-1992-44e9-92a3-65214350b7a7.md (claude)
- Update .claude/rules/e5731ea0-1ffc-4e87-b5f7-07551952f609.md (claude)
- Update .claude/rules/5b2054c7-ba4e-44f2-b4ee-faacb67305d6.md (claude)
- Update .claude/rules/f1ba5186-840f-4423-9876-d7cb8ec75614.md (claude)
- Update AGENTS.md (agents)
- Update docs/adr/fcd6a21d-756b-4d3f-98d7-f42d21122afd-standardize-service-boundary-logging-for-observability-service-implementations-include.md (docs)
- Update docs/adr/da815559-806f-4816-ac62-f2bcba187047-standardize-service-boundary-logging-for-observability-service-boundary-logs.md (docs)
- Update docs/adr/860946d2-f81f-45ed-b3f2-25c8d5f4956f-standardize-service-boundary-logging-for-observability-log-levels-service.md (docs)
- Update docs/adr/8743e5ed-c257-4d49-8295-a4481f8523b5-standardize-service-boundary-logging-for-observability-service-boundary-logging.md (docs)
- Update docs/adr/67d628ca-c9de-4922-93cb-1fd54450f492-standardize-service-boundary-logging-for-observability-service-boundary-logs.md (docs)
- Update docs/adr/a4786ef4-01e0-4b65-9c9f-0c3175726c86-standardize-service-boundary-logging-for-observability-service-boundary-exit.md (docs)
- Update docs/adr/b1a53926-9804-45b7-9543-634d35c15734-standardize-service-boundary-logging-for-observability-service-boundary-entry.md (docs)
- Update docs/adr/4dbd1df3-2cdc-4996-a874-d94ee89c9983-adopt-distributed-tracing-for-public-api-observability-internal-private-use.md (docs)
- Update docs/adr/c81e5425-fcc1-4177-9246-bd167e4322af-adopt-distributed-tracing-for-public-api-observability-implement-sampling-strategies.md (docs)
- Update docs/adr/9607dcb3-91d3-44b9-85f9-ccb1fa25bd76-adopt-distributed-tracing-for-public-api-observability-tracing-instrumentation-not.md (docs)
- Update docs/adr/f39ea92e-c1c0-46b6-b4ff-9c07cc3b42b7-adopt-distributed-tracing-for-public-api-observability-trace-spans-include.md (docs)
- Update docs/adr/372c20f8-a9ae-4489-b3a3-4825d3343af4-adopt-distributed-tracing-for-public-api-observability-implementations-create-child.md (docs)
- Update docs/adr/19fbda95-be0a-43ce-88bd-b2cbb1c4075a-adopt-distributed-tracing-for-public-api-observability-each-trace-span.md (docs)
- Update docs/adr/36c17245-9a45-4855-affd-3e23712797d8-adopt-distributed-tracing-for-public-api-observability-tracing-implementations-propagate.md (docs)
- Update docs/adr/1267d2fe-4cfa-4c45-9004-ada782af479d-adopt-distributed-tracing-for-public-api-observability-public-external-endpoints.md (docs)
- Update docs/adr/57fb44e9-c959-408b-9e6a-87b058b1ecc7-standardize-server-sent-events-sse-for-real-time-configuration-and-runtime-state-updates-sse-implementations-support.md (docs)
- Update docs/adr/0ba59d63-b106-4111-a75e-cb18a23f7c56-standardize-server-sent-events-sse-for-real-time-configuration-and-runtime-state-updates-route-handlers-properly.md (docs)
- Update docs/adr/0c99d9c0-10fb-40b3-bc7d-6f69d4cd5498-standardize-server-sent-events-sse-for-real-time-configuration-and-runtime-state-updates-sse-connections-implement.md (docs)
- Update docs/adr/f5680bc5-1992-44e9-92a3-65214350b7a7-standardize-server-sent-events-sse-for-real-time-configuration-and-runtime-state-updates-sse-event-streams.md (docs)
- Update docs/adr/e5731ea0-1ffc-4e87-b5f7-07551952f609-standardize-server-sent-events-sse-for-real-time-configuration-and-runtime-state-updates-route-handlers-that.md (docs)
- Update docs/adr/5b2054c7-ba4e-44f2-b4ee-faacb67305d6-standardize-server-sent-events-sse-for-real-time-configuration-and-runtime-state-updates-sse-implementations-utilize.md (docs)
- Update docs/adr/f1ba5186-840f-4423-9876-d7cb8ec75614-standardize-server-sent-events-sse-for-real-time-configuration-and-runtime-state-updates-runtime-state-updates.md (docs)
2026-05-12 21:56:09 +00:00
Bryan Helmkamp
264cac3c64
feat(server): inject settings-backed model catalog (#247)
Some checks are pending
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) Waiting to run
TypeScript / Test (push) Waiting to run
TypeScript / Build (push) Waiting to run
## Summary

This PR moves the server-facing model catalog paths onto a resolved
catalog stored in `AppState`, using configured `[llm]` provider/model
overrides layered on top of the built-in catalog.

The server now uses the injected catalog for:

- `/models` listing and model test lookup
- `/completions` default model and provider inference
- manifest preflight materialization and LLM model alias resolution
- diagnostics LLM probes
- pull request default model selection
- runtime settings refresh via `replace_settings`

It also adds catalog overlay helpers in `fabro-model` and converts
resolved server runtime `[llm]` settings into the catalog shape in
`fabro-config`.

This branch also includes the earlier `chore: update dockerfile` commit,
which updates the Daytona snapshot to `fabro-v10` and installs Chromium
through the xtradeb PPA with an XFCE/browser wrapper.

Related: #210

## Tests

- `cargo +nightly-2026-04-14 fmt --check --all`
- `cargo nextest run -p fabro-config -p fabro-model -p fabro-server`
(844 tests passed)
- `cargo +nightly-2026-04-14 clippy -p fabro-config -p fabro-model -p
fabro-server --all-targets -- -D warnings`
2026-05-12 17:55:28 -04:00
Bryan Helmkamp
34d83db801
feat(model): support open provider catalog data (#245)
## Summary

This PR moves Fabro’s provider/model catalog toward settings-driven
provider identity by replacing the closed provider schema at the
API/auth/model boundary with `ProviderId`, then loading built-in
provider and model metadata from embedded per-provider TOML files.

The immediate result is that built-ins now use the same settings-shaped
catalog data that custom providers will use later, while request-serving
paths still keep the existing bootstrap/default catalog behavior until
the resolved-catalog plumbing lands.

## Changes

- Replaces API-facing provider enum usage with string-backed
`ProviderId`, including OpenAPI/progenitor replacements and regenerated
TypeScript client models.
- Routes model, auth, billing, CLI, server, and workflow call sites
through provider IDs where they cross product identity boundaries.
- Builds `Catalog` from settings-shaped provider/model data with
validation for adapter keys, OpenAI-compatible `base_url`, duplicate
aliases, provider defaults, disabled entries, model controls, and
per-speed cost rows.
- Replaces `catalog.json` with embedded provider TOML files under
`lib/crates/fabro-model/src/catalog/providers/`.
- Adds an explicit `fabro_model::bootstrap_catalog` hatch for
setup/install paths and extends the dev policy test to keep bootstrap
access contained.
- Preserves public training and knowledge-cutoff labels in LLM model
settings while still accepting bare TOML dates.

## Verification

- `cargo nextest run -p fabro-model -p fabro-config -p fabro-api` — 416
passed
- `cargo nextest run -p fabro-dev --features dev
bootstrap_catalog_references_stay_in_allowlist` — 1 passed
- `cargo +nightly-2026-04-14 fmt --check --all`
- `cargo +nightly-2026-04-14 clippy --workspace --all-targets -- -D
warnings`
- `cargo build --workspace`
- `git diff --check`

---

[![Compound
Engineering](https://img.shields.io/badge/Compound_Engineering-6366f1)](https://github.com/EveryInc/compound-engineering-plugin)
🤖 Generated with GPT-5 via [Codex](https://openai.com/codex)
2026-05-12 15:42:49 -04:00
Bryan Helmkamp
d7cb27ff65
Add gateway extra_headers settings for LLM providers (#244)
## Summary

Adds the Phase 1 settings surface for gateway-backed LLM providers. This
was prompted by @haroldolivieri's Portkey/Bedrock field report on PR
#207, which showed that gateway auth and routing often live in custom
headers rather than the adapter's primary API-key header.

This PR is schema and seam work only. It does not make settings-defined
providers runnable yet; later phases still own ProviderId migration,
catalog construction, auth resolution, and production adapter
registration.

## Changes

- add typed `extra_headers` values to `[llm.providers.<id>]`
- support explicit `literal`, `env`, and `credential` header value forms
while rejecting bare strings, empty values, ambiguous tables, and
unknown keys
- cover whole-map header merge behavior and adapter header pass-through
tests
- update the settings-driven LLM plan with the Phase 1 gateway header
attribution and completion notes

## Non-goals

- does not make settings-defined providers runnable yet
- does not migrate ProviderId/OpenAPI/auth resolver/runtime catalog
plumbing
- does not route Codex OAuth through custom provider settings

## Tests

- `cargo nextest run -p fabro-config -p fabro-llm`
- `cargo +nightly-2026-04-14 fmt --check --all`
- `cargo +nightly-2026-04-14 clippy -p fabro-config -p fabro-llm
--all-targets -- -D warnings`
- `git diff --check origin/main...HEAD`

## Post-Deploy Monitoring & Validation

No additional operational monitoring required. This is schema and
adapter-seam coverage only; production provider registration and runtime
credential/header resolution remain deferred.

## Attribution

Motivated by @haroldolivieri's Portkey/Bedrock report on PR #207:
https://github.com/fabro-sh/fabro/pull/207#issuecomment-4377929769

Commits include `Co-authored-by: Haroldo Olivieri
<6575718+haroldolivieri@users.noreply.github.com>`.

---
Compound Engineered: Codex, `ce:work`.

---------

Co-authored-by: Haroldo Olivieri <6575718+haroldolivieri@users.noreply.github.com>
2026-05-12 12:09:08 -04:00
Bryan Helmkamp
087c9233f3
fix(validate): pick up sibling workflow.toml inputs for bare .fabro path (#242)
## Summary

- `fabro validate path/to/workflow.fabro` now auto-discovers a sibling
`workflow.toml` and loads its `[run.inputs]`, so templated graphs
validate the same way they do when invoked by name or by toml path.
- The discovery is opt-in to the user's specific graph: we only pick up
the sibling toml if its `[workflow].graph` resolves back to the `.fabro`
the user passed. Unrelated tomls in the same directory are ignored.

## Why

`fabro validate` is the natural fast-feedback tool for CI/pre-commit
hooks that iterate on changed `.fabro` files. Previously, a graph using
`{{ inputs.* }}` would fail with a generic MiniJinja "undefined value"
error when validated by path, even when a sibling `workflow.toml`
defined those inputs. The other two invocation forms (by name, by toml)
worked, which made the path form a usability cliff.

Fixes #195.

## Test plan

- [x] New integration test:
`bare_fabro_picks_up_sibling_workflow_toml_inputs` validates
`test/templated_inputs/workflow.fabro` (uses `{{ inputs.app_dir }}`) and
expects `Validation: OK`.
- [x] New unit tests in `fabro-config::project`:
  - `resolve_workflow_path_picks_up_sibling_workflow_toml` — happy path.
- `resolve_workflow_path_ignores_sibling_toml_pointing_elsewhere` —
guard: don't apply an unrelated sibling toml.
- [x] `cargo nextest run --workspace` — 5585 tests pass.
- [x] `cargo +nightly-2026-04-14 fmt --check --all`, `clippy --workspace
--all-targets -- -D warnings` clean.
- [x] Manual: `fabro validate /tmp/fabro-issue-195/workflow.fabro`
(templated graph + sibling toml with `[run.inputs]`) prints `Validation:
OK`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Nate Aune <118984+natea@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 12:05:21 -04:00
Bryan Helmkamp
a33d17c88d
feat(run): add managed branch controls (#243)
## Summary

Adds run-level controls for clone behavior, managed run branch
setup/pushes, and metadata branch writes/pushes so workflows can opt out
of Fabro-managed Git behavior without relying on provider-specific
`skip_clone` settings. This closes fabro-sh/fabro#240.

## What Changed

- Introduced `[run.clone]`, `[run.run_branch]`, and `[run.meta_branch]`
settings with defaults that preserve current behavior.
- Removed user-facing `skip_clone` from Docker/Daytona config while
mapping the new run-level clone setting into the internal sandbox
runtime options.
- Gated run branch setup/push, metadata branch writer creation/push, and
PR branch output on the new settings.
- Enforced invalid combinations: pull requests require an enabled pushed
run branch, and disabling the run branch also disables metadata branch
behavior.
- Updated OpenAPI, the generated TypeScript API client, frontend fixture
data, and docs for the new configuration shape.

## Testing

- `cargo nextest run -p fabro-config -p fabro-types -p fabro-workflow -p
fabro-server`
- `cargo build -p fabro-api`
- `cd lib/packages/fabro-api-client && bun run generate`
- `cd lib/packages/fabro-api-client && bun run typecheck`
- `cd apps/fabro-web && bun run typecheck`
- `cd apps/fabro-web && bun test`
- `cargo build --workspace`
- `cargo +nightly-2026-04-14 fmt --check --all`
- `cargo +nightly-2026-04-14 clippy --workspace --all-targets -- -D
warnings`
- `cargo insta pending-snapshots`
- `git diff --check`

## Post-Deploy Monitoring & Validation

- Validation window: first 24 hours after release; owner: release
owner/on-call engineer.
- Log queries/search terms: `run_branch`, `meta_branch`,
`clone.enabled`, `skip_clone`, `pull request requires an enabled pushed
run branch`, `metadata branch`.
- Healthy signals: runs without custom branch config continue creating
and pushing run/meta branches; runs with `[run.clone] enabled = false`
start provider sandboxes without cloning; runs with branch pushes
disabled complete without Git push errors.
- Failure signals: increased run startup failures for Docker/Daytona,
unexpected PR creation conflicts, missing metadata for default-config
runs, or validation errors for configurations that previously used
default settings.
- Mitigation trigger: if default-config runs stop producing expected
branch/metadata artifacts or sandbox startup failures increase, roll
back the release or temporarily restore previous defaults while
investigating the run-level setting resolution path.

---

[![Compound
Engineering](https://img.shields.io/badge/Compound_Engineering-6366f1)](https://github.com/EveryInc/compound-engineering-plugin)
🤖 Generated with GPT-5 via [Codex](https://openai.com/codex)

Co-authored-by: Haroldo Olivieri <6575718+haroldolivieri@users.noreply.github.com>
2026-05-12 12:00:30 -04:00
Bryan Helmkamp
762ac19649
fix(sandbox): resolve bash via PATH instead of /bin/bash (#241)
## Summary

The local sandbox provider hard-codes `/bin/bash` at three call sites in
`fabro-sandbox/src/local.rs` (`exec_command`, `exec_command_streaming`,
`spawn_stdio_process`). NixOS doesn't ship `/bin/bash` — only `/bin/sh`
and `/usr/bin/env` are managed under `/`, with bash living on `PATH` at
`/run/current-system/sw/bin/bash`. The result: a first run on NixOS dies
on the very first sandbox call (the git probe) with `No such file or
directory (os error 2)`, surfaced as `sandbox git unavailable`.

## Fix

Switch all three sites from `Command::new("/bin/bash")` to
`Command::new("bash")`. `PATH` is already preserved by
`filtered_env_vars` (and explicitly tested at `local.rs:1164`), so
libc's `execvp` lookup resolves bash on every distribution that has it
installed, including NixOS, without forcing users to symlink
`/bin/bash`.

The `/bin/bash` references in `docker.rs` are unaffected — those execute
inside containers where the path always exists.

## Credit

Diagnosis and proposed fix by @allouis in #232 — they ran the
PATH-lookup variant locally on NixOS 26.05 and confirmed workflows ran
cleanly without the symlink workaround.

Closes #232

---

[![Compound Engineering
v2.60.0](https://img.shields.io/badge/Compound_Engineering-v2.60.0-6366f1)](https://github.com/EveryInc/compound-engineering-plugin)
🤖 Generated with Claude Opus 4.7 (1M context, extended thinking) via
[Claude Code](https://claude.com/claude-code)

Co-authored-by: Fabien O'Carroll <3218915+allouis@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 10:31:12 -04:00
fabro-releases[bot]
8f120fbf5a Bump version to 0.231.0-nightly.3 2026-05-12 14:13:31 +00:00
fabro-sh-0530[bot]
10de9fd16c
Add foundation for settings-driven LLM catalog (#207)
## Summary

This lays the groundwork for settings-driven LLM providers and models
without switching production routing yet. The new schemas and shared
vocabulary let later catalog construction treat provider/model identity
as data while keeping adapter behavior and control values Rust-owned.

## What changed

- Added `[llm.providers]` and `[llm.models]` settings layers with sparse
per-entry merging, whole-array replacement for credential/alias/control
lists, TOML date support for `knowledge_cutoff`, and typed `credential:`
/ `env:` references that reject literal secrets.
- Added `ProviderId`, `ModelId`, and a shared `ReasoningEffort` enum in
`fabro-model`, plus adapter metadata for `anthropic`, `openai`,
`gemini`, and `openai_compatible`.
- Added a matching `fabro-llm` adapter factory registry with parity
tests to keep metadata keys and factory keys in sync.
- Added `[run.model.controls]` defaults through config resolution and
runtime settings types.
- Added a workspace policy test to prevent future `bootstrap_catalog`
use outside install/test-support paths.

### Plan Summary

- This is the foundation slice of the settings-driven catalog plan.
- Production still uses the existing `Provider` enum and
`Catalog::builtin()` call paths.
- ProviderId routing, OpenAPI regeneration, auth resolver changes,
resolved `Arc<Catalog>` injection, typed request speed, and per-speed
billing are deferred follow-ups.

⚒️ Generated with [Fabro](https://fabro.sh)

---------

Co-authored-by: Fabro <noreply@fabro.sh>
Co-authored-by: fabro-bot <fabro-bot@fabro.sh>
Co-authored-by: Bryan Helmkamp <bryan@brynary.com>
2026-05-12 10:01:57 -04:00
fabro-releases[bot]
00e5226521 Bump version to 0.231.0-nightly.2 2026-05-12 13:26:27 +00:00
Bryan Helmkamp
d6d7f18c23
fix(acp): tolerate clean stdio exit after final response 2026-05-12 09:03:53 -04:00
fabro-releases[bot]
cbf81d79fb Bump version to 0.231.0-nightly.1 2026-05-12 12:40:48 +00:00
Bryan Helmkamp
a15a7c757c
fix(acp): stabilize cancellation test readiness
Wait for protocol activity from the fake ACP agent before cancelling instead of polling a temp file. This keeps the test synchronized with session/prompt handling under CI load.
2026-05-12 08:29:02 -04:00
Bryan Helmkamp
5e839ef4ea
docs(mcp): document Fabro MCP server 2026-05-12 08:29:02 -04:00
Bryan Helmkamp
5d227dadc2
docs(changelog): refresh recent product changes 2026-05-12 08:29:02 -04:00
fabro-releases[bot]
ed602a1ad3 Bump version to 0.231.0-nightly.0
Some checks are pending
Rust / Test (macOS) (push) Waiting to run
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
2026-05-12 03:52:25 +00:00
Bryan Helmkamp
234bd5663e
Add ACP backend support (#237)
## Summary
Implemented ACP support as a first-class Fabro backend alongside `api`
and `cli`. This adds a new `fabro-acp` crate using the official ACP Rust
crates, routes `backend=\"acp\"` for agent and prompt nodes, adds
sandbox stdio support for local/Docker/test-support paths, emits ACP
workflow events/projections, updates server steerability handling,
validation, documentation, and black-box CLI coverage.

## Test Plan
Passed strict non-live verification:
- `ulimit -n 4096 && cargo nextest run -p fabro-workflow --run-ignored
all --no-fail-fast` — 1162 passed, 0 skipped.
- `ulimit -n 4096 && cargo nextest run -p fabro-acp -p fabro-sandbox -p
fabro-workflow -p fabro-validate -p fabro-store -p fabro-server -p
fabro-cli --run-ignored all --no-fail-fast -E 'not
test(daytona_streaming_live_smoke)'` — 3125 passed.
- `cargo build --workspace` — passed.
- `ulimit -n 4096 && cargo nextest run --workspace --run-ignored all
--no-fail-fast -E 'not test(daytona_streaming_live_smoke)'` — 5666
passed.
- `cargo +nightly-2026-04-14 fmt --check --all` — passed.
- `cargo +nightly-2026-04-14 clippy --workspace --all-targets -- -D
warnings` — passed.

Live-environment tests skipped/excluded under explicit user override:
- `daytona_streaming_live_smoke` was excluded from final nextest runs
because it requires live Daytona infrastructure and `DAYTONA_API_KEY`.
- Confirmed with `env -u DAYTONA_API_KEY cargo test -p fabro-sandbox
--features daytona --test daytona_streaming_live
daytona_streaming_live::daytona_streaming_live_smoke -- --ignored
--exact --nocapture`: failed fast with `DAYTONA_API_KEY must be set to
run this live smoke test`.
2026-05-11 23:39:43 -04:00
Bryan Helmkamp
a19f6dd03a
feat(cli): add Fabro MCP server (#236)
## Summary

Adds a stdio-based Fabro MCP server so MCP clients can manage Fabro
workflow runs through the authenticated `fabro` CLI, without a separate
MCP auth flow.

## What Changed

- Adds `fabro mcp start`, `fabro mcp config`, and `fabro mcp init
<agent>` for launching and configuring the MCP server.
- Introduces a new `fabro-mcp-server` crate with run-management tools:
  - `fabro_run_create`
  - `fabro_run_search`
  - `fabro_run_interact`
  - `fabro_run_gather`
  - `fabro_run_events`
- Reuses the CLI's authenticated server connection behavior, including
OAuth refresh, dev-token/local-server handling, explicit server targets,
proxy behavior, and stdio env/cwd isolation.
- Moves shared run-manifest construction into `fabro-manifest` so CLI
runs and MCP-created runs use the same override semantics.
- Extends MCP client stdio support with configured cwd and exact
environment handling for reliable spawned-server tests.

---------

Co-authored-by: fabro-sh-0530[bot] <281434857+fabro-sh-0530[bot]@users.noreply.github.com>
Co-authored-by: Fabro <noreply@fabro.sh>
2026-05-11 18:20:50 -04:00
Bryan Helmkamp
b4c7ab5800
feat(workflows): add daytona-medium sandbox check 2026-05-11 13:28:10 -04:00
Bryan Helmkamp
9ea00185dc
fix(server): avoid cancelling terminal runs during delete
Skip cancellation signaling when the durable run projection is already terminal so deletion cannot append cancelled failure events after a successful run.
2026-05-11 08:34:27 -04:00
fabro-releases[bot]
32c974d8f3 Bump version to 0.230.0-nightly.0 2026-05-11 10:28:17 +00:00
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
f15ff91307
chore: plans 2026-05-10 23:40:02 -04:00
Bryan Helmkamp
8b522a057e
Merge remote-tracking branch 'origin/main' 2026-05-10 23:39:34 -04:00
Bryan Helmkamp
00205a53d9
test(cli): align run summary fixtures
Use the canonical run summary test helper for remote run mocks so CLI integration fixtures match the shared Run wire shape.
2026-05-10 23:38:55 -04:00
Bryan Helmkamp
b5101bbde3
refactor(types): remove legacy run summary shape
Use the canonical nested Run DTO directly and reject the old flat run summary JSON shape. Update store, server, CLI, and fixtures to read and produce canonical fields.
2026-05-10 23:29:41 -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
5da2f3d455
test(cli): align sandbox event fixtures
Update seeded sandbox.initialized events to use the canonical sandbox id field expected by run event validation.
2026-05-10 14:23:44 -04:00
Bryan Helmkamp
b6d4d240ae
feat(auth): add unified session API
Expose browser and CLI auth sessions through a normalized API, and allow revoking active CLI refresh-token chains while keeping browser sessions non-revocable for v1.
2026-05-10 14:16:23 -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
da368366f0
fix(store): hydrate projection cache before appending later events 2026-05-10 13:38:06 -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
9c08653228
feat(server): list sandbox services 2026-05-10 11:24:39 -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
6c049dcf88
chore: dump daytona sdk 2026-05-10 10:43:59 -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
e9461c0ce1
chore: plans 2026-05-10 10:24:07 -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
e86b11f395
fix(server): point sandbox VNC preview at noVNC viewer page
Daytona's signed preview URL targets the noVNC service root, which
serves a directory listing of the noVNC distribution rather than the
actual viewer. The result was that selecting VNC mode in the run
sandbox tab loaded an iframe of `vnc.html`, `vnc_auto.html`, … as
links instead of the desktop.

Fix it server-side by parsing the signed URL, replacing the path with
`/vnc.html`, and appending `autoconnect=true&resize=scale` so the
iframe immediately connects and scales to fit. Existing query params
on the signed URL (e.g. proxy tokens) are preserved. The intentional
url::Url use is wrapped with #[expect(disallowed_types)] since this is
internal URL manipulation, not a logging/error boundary; the
parse-failure error message omits the URL to avoid leaking creds in
client-facing API responses.

Verified live against a Daytona run on the daytona-medium snapshot:
the response now ends with /vnc.html?autoconnect=true&resize=scale
and the iframe loads the actual noVNC viewer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 10:13:26 -04:00