docs(changelog): refresh recent product changes

Add dated changelog entries for the recent user-facing changes and advance the changelog watermark.
This commit is contained in:
Bryan Helmkamp 2026-05-18 14:13:11 -04:00
parent a9ef40d9e4
commit 7f81beb63c
No known key found for this signature in database
9 changed files with 326 additions and 27 deletions

View file

@ -1 +1 @@
a19f6dd03a2ed2b690161476b562462590d78790
29b7cc0de0b9661cd01a6aaa37752652882e76be

View file

@ -1,8 +1,14 @@
---
title: "Fabro MCP server"
title: "ACP backend and Fabro MCP server"
date: "2026-05-11"
---
## ACP agent backend
Fabro introduced Agent Client Protocol as a first-class backend for agent execution. Instead of routing every agent through Fabro-owned provider adapters, workflows can hand a stage to a stdio ACP process and keep that process responsible for its own tools, context, and model auth.
ACP runs also emit dedicated workflow events and projections, so run detail, logs, and stored events can distinguish protocol activity from API-backed model calls. This gives teams a clearer integration path for custom agent runtimes while keeping normal Fabro run lifecycle, checkpoint, and validation behavior.
## Fabro MCP server
Fabro now ships a stdio-based Model Context Protocol server, so MCP clients can manage workflow runs through the authenticated `fabro` CLI. It reuses normal CLI server targeting, OAuth refresh, dev-token and local-server handling, proxy behavior, and storage configuration instead of requiring a separate MCP authentication flow.
@ -33,7 +39,9 @@ This lets agent tools orchestrate Fabro runs without scraping CLI output or hand
</Accordion>
<Accordion title="Workflows">
- Added a bundled `daytona-medium` workflow for verifying the Daytona Medium sandbox starts with standard tooling
- Added ACP execution events and stored projections for protocol sessions
- Added validation for ACP backend configuration on workflow nodes
- Added sandbox stdio support for local, Docker, and test-support providers
</Accordion>
<Accordion title="Improvements">

View file

@ -0,0 +1,39 @@
---
title: "Managed run branches and validation fixes"
date: "2026-05-12"
---
## Managed run branch controls
Fabro-managed Git behavior can now be controlled at the run level instead of through provider-specific sandbox switches. Workflows can opt out of automatic cloning, run branch setup, branch pushes, metadata branch writes, and metadata pushes while keeping the default behavior unchanged for existing runs.
```toml
[run.clone]
enabled = false
[run.run_branch]
enabled = false
[run.meta_branch]
enabled = false
```
This is useful for workflows that prepare their own workspace, run against already-mounted files, or should avoid pushing Fabro-managed branches back to GitHub. Pull request creation still validates that a pushed run branch is enabled before it proceeds.
## More
<Accordion title="Workflows">
- Added `[run.clone]`, `[run.run_branch]`, and `[run.meta_branch]` settings for clone, branch, and metadata branch behavior
- Added `[llm.providers]` and `[llm.models]` settings foundations for configurable provider and model catalog data
- Added typed provider `extra_headers` settings for gateway-backed LLM providers
</Accordion>
<Accordion title="CLI">
- `fabro validate path/to/workflow.fabro` now discovers a sibling `workflow.toml` when it points back to the same graph and supplies `[run.inputs]`
</Accordion>
<Accordion title="Fixes">
- Fixed local sandbox startup on NixOS by resolving `bash` through `PATH` instead of requiring `/bin/bash`
- Fixed ACP stdio handling so a clean process exit after the final response is tolerated
- Fixed templated `.fabro` validation by ignoring unrelated sibling `workflow.toml` files in the same directory
</Accordion>

View file

@ -1,11 +1,20 @@
---
title: "Configurable LLM providers"
title: "Configurable LLM providers, Slack reviews, and Daytona Dockerfiles"
date: "2026-05-13"
---
<Warning>
**Run failure payloads now use structured failure objects.** Terminal run failures emit a nested `failure` value instead of relying on flat error, cause, or reason fields.
To migrate:
1. Regenerate API clients from the current OpenAPI schema.
2. Read terminal diagnostics from `failure.reason`, `failure.causes`, `failure.category`, and related structured fields.
3. Treat stage-level failure strings and terminal run failures as separate API surfaces.
</Warning>
## Configurable LLM providers and models
Fabro can now merge LLM provider and model catalog entries from settings. Teams can add OpenAI-compatible gateways, route through provider proxies, attach typed extra headers, map a Fabro model ID to a provider-specific `api_id`, and declare model controls and per-speed pricing without waiting for a new built-in catalog entry.
Fabro can now merge LLM provider and model catalog entries from settings. Teams can add OpenAI-compatible gateways, route through provider proxies, attach typed extra headers, map a Fabro model ID to a provider-specific `api_id`, declare model controls, and set per-speed pricing without waiting for a new built-in catalog entry.
```toml
[llm.providers.proxy]
@ -25,22 +34,44 @@ api_id = "provider-wire-model-name"
default = true
```
## Migration note
Provider values exposed by configuration, model routing, and the API are provider ID strings. Built-in names like `anthropic`, `openai`, and `gemini` still work, and custom IDs such as `proxy` now work wherever the selected catalog defines them.
Clients that generated closed provider enums from older API specs should regenerate against the current OpenAPI schema and treat model `provider` fields as strings.
## Slack review messages with context
Slack interview prompts now include the upstream stage response and an "Open in Fabro" link when the server has a web URL. Reviewers can see the plan summary or other context directly in Slack before choosing an answer.
Multi-button Slack gates also use unique button action IDs, fixing the `invalid_blocks` rejection that could prevent approval messages from appearing at all. Existing in-flight buttons remain compatible while new messages use the safer suffixed action IDs.
## Path-based Daytona Dockerfiles
Daytona snapshot configuration can now reference Dockerfiles by path from project or workflow TOML. Fabro resolves the path relative to the declaring TOML file, bundles the Dockerfile into run manifests, and rewrites it to inline content before sandbox creation.
```toml
[run.sandbox.daytona.snapshot]
dockerfile = { path = "./Dockerfile" }
```
## More
<Accordion title="LLM catalog">
- Added settings-reference coverage for `[llm.providers.<id>]`, provider `extra_headers`, `[llm.models.<id>]`, model limits, features, controls, base costs, and per-speed cost overrides
- Documented OpenAI-compatible provider configuration and gateway header examples
- Documented `api_id` for provider wire-model names
- Documented run-level model controls for reasoning effort and speed
<Accordion title="API">
- Run failures now preserve public messages, source-chain causes, classifications, actor/signature metadata, and redacted exec output tails in one structured contract
- Billing APIs now expose provider, model, and speed identity so standard and fast usage can be priced separately
- Model catalog responses now use open-ended provider IDs instead of a closed provider enum
</Accordion>
<Accordion title="Guardrails">
- Added a workspace policy test preventing direct production `Catalog::builtin()` usage outside the catalog owner and tests
- Clarified that `fabro_model::Provider` is a built-in compatibility enum, while open-ended provider identity is string-backed `ProviderId`
<Accordion title="Workflows">
- Added catalog-aware LLM request control validation and per-speed billing lookup
- Added support for `dockerfile = { path = "..." }` in Daytona snapshot settings
- Added structured diagnostics for terminal run failures and failed-run commit state
</Accordion>
<Accordion title="Fixes">
- Fixed Graphviz parsing so multi-line DOT attribute blocks no longer require commas between every attribute
- Fixed multi-button Slack interview messages being rejected by Slack because every button shared the same `action_id`
</Accordion>
<Accordion title="Improvements">
- Built-in provider and model metadata now comes from settings-shaped catalog TOML files
- OpenAI-compatible provider aliases can use canonical catalog model IDs for billing while preserving provider-specific `api_id` values on the wire
- Public contribution docs now allow small outside pull requests as well as issue-first contribution paths
</Accordion>

View file

@ -0,0 +1,50 @@
---
title: "Optional LLM setup and Daytona volumes"
date: "2026-05-14"
---
## Skip LLM setup during install
Fabro installs no longer require LLM credentials up front. The web installer has an explicit "Skip LLM setup" action, and the CLI supports the same flow for non-interactive installs.
```bash
fabro install --non-interactive --skip-llm --github-strategy token --github-username acme-dev
```
Skipping marks the LLM step complete without writing provider secrets. Later LLM-dependent workflows still fail with the normal provider-not-configured behavior until credentials are added.
## Daytona volume mounts
Fabro-managed Daytona sandboxes can now attach existing Daytona volumes from run configuration. This gives workflows a provider-owned place for persistent state such as credentials, caches, datasets, or other files that should survive ephemeral sandbox lifecycles.
```toml
[[run.sandbox.daytona.volumes]]
volume_id = "vol_123"
mount_path = "/home/daytona/.cache"
```
Fabro does not create or manage the volume lifecycle. Create the volume in Daytona first, then reference its `volume_id` from workflow, project, or user run settings.
## More
<Accordion title="API">
- `PUT /install/llm` now accepts an empty provider list to record an intentionally skipped LLM step
- `/install/finish` now accepts completed installs with no LLM vault credentials
- Sandbox runtime layout metadata now records provider workspace, repository root, primary repository path, and workspace symlink information
</Accordion>
<Accordion title="CLI">
- Added non-interactive `fabro install --skip-llm`
- Interactive `fabro install` now asks whether to configure LLM providers before provider selection
</Accordion>
<Accordion title="Workflows">
- Docker and Daytona clone primary GitHub repositories into provider-owned repository roots and keep execution under the workspace symlink
- Added `[[run.sandbox.daytona.volumes]]` passthrough for attaching pre-created Daytona volumes
</Accordion>
<Accordion title="Improvements">
- Added Venice as a built-in catalog provider with OpenAI-compatible routing
- Preflight now skips LLM client initialization for workflows with no LLM nodes
- `/models` listing now paginates before cloning returned model rows
</Accordion>

View file

@ -0,0 +1,76 @@
---
title: "Agent sessions, run relationships, and sandbox visibility"
date: "2026-05-16"
---
<Warning>
**Failure diagnostics now use the richer `{ reason, detail }` shape.** API clients reading terminal run failures should regenerate and read structured fields instead of parsing display strings.
To migrate:
1. Regenerate clients from the current OpenAPI schema.
2. Read public summaries from `failure.reason`.
3. Read source chains, categories, signatures, and redacted command output from `failure.detail`.
</Warning>
## Server-backed agent sessions
Fabro now has durable server-backed agent sessions with persistent session records, turns, transcripts, event replay, and SSE turn streaming. The first slice is local to the same-machine server target, but it gives API clients and the CLI a durable session surface instead of treating every agent interaction as a one-off process.
```bash
fabro session -p "Inspect this checkout and summarize the failing tests"
```
Sessions store messages and turn events under Fabro storage, reject conflicting active turns, validate local working directories, and support interrupt requests through the server.
## Run relationships and pull request links
Runs can now be connected with orchestration-only parent links without merging them into fork or rewind lineage. You can create child runs, filter by parent, link or unlink parent runs, and keep historical parent references even if a parent run is deleted.
```bash
fabro run hello --parent 01KRTKP5DJJ4EV6T7QSB081Z1N
fabro parent link child-run parent-run
fabro pr link run-id https://github.com/fabro-sh/fabro/pull/123
```
Pull request associations are event-sourced too. Existing runs can link, replace, view, and unlink GitHub PR URLs while Fabro-created PR flows continue to work as before.
## Chats in the web app
The web app now includes `/chats/new` and `/chats/:id` routes for the emerging agent chat surface. The implementation ports the validated prototype into the real app shell, using assistant-ui rendering, scripted streaming replies, markdown, tool-call rendering, and a StrictMode-safe first-message handoff.
This is the first web-facing layer over the new session primitives. It keeps the existing `/start` entry point for now while giving the product a dedicated conversation surface.
## More
<Accordion title="API">
- Added session create/list/read/update/delete, turn submission, event replay, interrupt, and session-scoped tool endpoints
- Added parent run fields and `PUT`/`DELETE /api/v1/runs/{id}/parent`
- Added pull request link and unlink endpoints for existing runs
- Added `GET /api/v1/health` alongside the root `/health` probe
- Sandbox details now expose provider dashboard links and network egress/ingress policy
</Accordion>
<Accordion title="CLI">
- Added `fabro session -p <prompt>` for server-backed local agent sessions
- Added `fabro parent link` and `fabro parent unlink`
- Added `--parent` to `fabro run`, `fabro create`, and `fabro ps`
- Added `fabro pr link`, `fabro pr unlink`, and updated `fabro pr view` for stored PR associations
</Accordion>
<Accordion title="Workflows">
- Template diagnostics now preserve source files, line/column spans, node IDs, and attribute context through CLI and server validation
- `fabro validate` now treats undefined variables inside `@file` prompts as warnings in structural mode, matching inline prompt behavior
- Custom provider and model `agent_profile` overrides now control profile-specific behavior for project memory, sessions, and runtime agent routing
</Accordion>
<Accordion title="Improvements">
- Added opt-in Ollama and LiteLLM catalog providers
- Sandbox tabs now show provider links and network policy where Fabro can assert them
- Generated API client output is marked as generated for GitHub language and code-quality tooling
</Accordion>
<Accordion title="Fixes">
- Fixed custom provider IDs in `fabro exec` and provider-filtered model listing
- Fixed Daytona clone setup by moving Daytona repository roots under `/home/daytona/repos`
- Fixed template validation so imported prompt files with undefined inputs produce warnings instead of hard errors
</Accordion>

View file

@ -0,0 +1,50 @@
---
title: "Run detail summaries and MCP parent tools"
date: "2026-05-17"
---
<Warning>
**Session creation now requires typed permissions.** `POST /api/v1/sessions` requires `permissions` to be one of `read-only`, `read-write`, or `full`, and session records always return a non-null permissions value.
To migrate:
1. Send an explicit `permissions` value in every `CreateSessionRequest`.
2. Regenerate clients so the generated type uses the `PermissionLevel` enum or union.
3. Clear old local dev session records with `"permissions": null` if they fail to deserialize.
</Warning>
## Run detail overview and children
Run detail now surfaces more run state without forcing you to tab-hop. The Overview tab includes a summary panel for created-by, changes, sandbox, cost, and artifacts, while pull request links are promoted into a header pill that stays visible across tabs.
Parent and child relationships also have a dedicated Children tab. It reuses the run list row layout, shows a zero state when no child runs exist, and includes a refresh action that updates both the child list and the parent count badge.
## MCP run orchestration parity
Fabro MCP tools now understand parent and child run relationships. MCP clients can create child runs, search direct children, link or unlink an existing run's parent, and receive `parent_id` plus `children_count` in run summaries.
MCP clients can also send a bare `interrupt` action through `fabro_run_interact`. This pauses an active API-mode agent round without requiring follow-up steering text in the same tool call.
## More
<Accordion title="API">
- `POST /api/v1/sessions` now rejects missing or invalid `permissions` with `422 Unprocessable Entity`
- Run summaries now include `children_count` for parent-aware UI and MCP tools
- Generated TypeScript clients now expose typed `PermissionLevel`
</Accordion>
<Accordion title="Workflows">
- ACP and workflow template rendering now resolve static MiniJinja `{% include %}` partials relative to the file being rendered
- Manifest validation now bundles static prompt and goal include dependencies so `fabro validate` can resolve them
</Accordion>
<Accordion title="Improvements">
- Provider auth mode, primary auth header policy, billing policy, agent profile, base URLs, and probe markers now live in provider catalog data
- LLM readiness checks now report adapter construction failures without making catalog parsing adapter-specific
- The Children tab uses the wider run detail layout and hides the count badge when the value is zero
</Accordion>
<Accordion title="Fixes">
- Fixed MiniJinja include partials failing with `template not found` when the partial lived next to the rendered prompt or goal file
- Fixed Children tab layout narrowing compared with the rest of run detail
- Fixed zero-count Children tab badges adding visual noise
</Accordion>

View file

@ -1,27 +1,67 @@
---
title: "Explicit vault-backed provider credentials"
title: "Strict agent backends and explicit credentials"
date: "2026-05-18"
---
<Warning>
**Agent backends are now strictly `api` or `acp`.** The legacy `cli` backend and `acp_command` attribute are rejected, and ACP nodes can no longer use API-only model/provider controls.
To migrate:
1. Replace `backend="cli"` with API-backed execution or an explicit ACP process.
2. Replace `acp_command="..."` with `acp.command="..."` for shell command strings.
3. Use `acp.config="..."` for JSON stdio ACP configs.
4. Move `model`, `provider`, `reasoning_effort`, `max_tokens`, and `speed` onto API-backed nodes only.
</Warning>
<Warning>
**Vault credential refs and secret schemas are explicit.** Provider auth refs now use `env:<NAME>` for process environment lookup and `vault:<NAME>` for server-owned vault lookup. API-key secrets are stored as `token`, OAuth records as `oauth`, and file material as `file`.
To migrate:
1. Replace `credential:<NAME>` refs with `vault:<NAME>`.
2. Re-create old `environment` or `credential` secrets with `token`, `oauth`, or `file` schemas.
3. Use `fabro secret set NAME value` for API keys and PAT-style secrets.
</Warning>
## Strict API and ACP backends
Agent execution now has a clear two-backend contract. API-backed stages use Fabro-owned model/provider auth and request controls, while ACP-backed stages launch a user-supplied stdio process that owns its own auth, tools, and protocol behavior.
```dot
implement [label="Implement", backend="acp", acp.command="python3 tools/fake_acp_agent.py"]
```
This removes the old CLI runtime path and prevents ACP execution from accidentally resolving or forwarding provider credentials. ACP events and projections now report process identity such as `command` and optional `config_name` rather than provider/model metadata.
## Explicit vault-backed provider credentials
Fabro now separates process environment credentials from server-owned vault credentials. Provider auth refs use `env:<NAME>` for process environment lookup and `vault:<NAME>` for explicit vault lookup. API-key secrets are stored as raw `token` values, OAuth records are stored as typed `oauth` JSON, and file material remains `file`.
Fabro now separates process environment credentials from server-owned vault credentials. Provider auth configuration can try process env first, vault entries second, or any explicit order you choose.
```toml
[llm.providers.proxy.auth]
credentials = ["env:ACME_GATEWAY_API_KEY", "vault:ACME_GATEWAY_API_KEY"]
```
## Migration note
Use `fabro secret set NAME value` for API keys and PAT-style secrets. The default secret type is now `token`; `environment` and `credential` secret schemas are no longer part of the API.
Existing server-owned secrets using the removed `environment` or `credential` schemas must be re-created with the new `token`, `oauth`, or `file` schema.
OpenAI Codex OAuth credentials now live under `vault:OPENAI_CODEX`, and provider catalogs use the same explicit credential-source vocabulary as custom provider settings.
## More
<Accordion title="Auth model">
- Removed the old `credential:` provider ref prefix in favor of explicit `vault:`
- OpenAI Codex OAuth credentials now live under `vault:OPENAI_CODEX`
- Provider catalogs now check process env first, then same-name vault entries
<Accordion title="API">
- Removed old `environment` and `credential` secret schemas in favor of `token`, `oauth`, and `file`
- Session, run, and provider auth paths now consume typed credential sources and typed vault entries
</Accordion>
<Accordion title="Workflows">
- ACP configuration is now split into `acp.command` and `acp.config`
- ACP is restricted to `agent` nodes and rejects API-only model/provider attributes
- Import and stylesheet propagation now preserve the strict backend contract
</Accordion>
<Accordion title="Fixes">
- Server-created detached runs now persist inferred project and workflow names in run metadata
- Manifest preparation now prefers explicit `[workflow].name`, then graph name, then workflow slug when backfilling names
</Accordion>
<Accordion title="Improvements">
- Provider catalogs now check process environment credentials first, then same-name vault entries where configured
- Web stage model extraction now follows the new API/ACP event contract
</Accordion>

View file

@ -252,7 +252,12 @@
"group": "May 2026",
"icon": "clock-rotate-left",
"pages": [
"changelog/2026-05-18",
"changelog/2026-05-17",
"changelog/2026-05-16",
"changelog/2026-05-14",
"changelog/2026-05-13",
"changelog/2026-05-12",
"changelog/2026-05-11",
"changelog/2026-05-10",
"changelog/2026-05-09",