docs(changelog): refresh recent product changes

This commit is contained in:
Bryan Helmkamp 2026-07-24 10:47:14 -04:00
parent 678e75e2f3
commit 39664cd966
No known key found for this signature in database
25 changed files with 486 additions and 3 deletions

View file

@ -1 +1 @@
074f90c3915b477486210e429cfc4581815e034b
678e75e2f35ae90e70c4b369f74ec202b168982d

View file

@ -0,0 +1,10 @@
---
title: "Completion cost estimates"
date: "2026-06-11"
---
## More
<Accordion title="API">
- Completion responses now include catalog-estimated `cost_usd` and `cost_source` fields, including when a model alias is used
</Accordion>

View file

@ -0,0 +1,13 @@
---
title: "OpenRouter support"
date: "2026-06-12"
---
## OpenRouter support
Using OpenRouter previously required custom provider configuration, and aggregator-specific cache and cost details were lost. OpenRouter is now an opt-in built-in provider with a curated model catalog, cached and reasoning token accounting, and authoritative provider-reported costs for blocking and streaming responses.
```toml title="settings.toml"
[llm.providers.openrouter]
enabled = true
```

View file

@ -0,0 +1,12 @@
---
title: "Environment management in Settings"
date: "2026-06-13"
---
<Warning>
**Environment `volumes` settings were removed.** Remove `volumes` from managed environment definitions; the field is no longer accepted or applied.
</Warning>
## Environment management in Settings
Server-managed environments previously required API or file-level administration. The new **Settings → Environments** pages let you create, edit, and delete environments while configuring images, resources, environment variables, networking, and lifecycle behavior. Built-in environments are seeded during installation instead of every server start, and `default` is now an ordinary environment that you can delete.

View file

@ -0,0 +1,14 @@
---
title: "Local environment working directories"
date: "2026-06-14"
---
## More
<Accordion title="Workflows">
- Added `cwd` to server-managed local environments so remote servers can choose an absolute host working directory; Docker and Daytona ignore this setting
</Accordion>
<Accordion title="Fixes">
- Local runs now keep a submitted source directory only when it exists on the server and otherwise report how to configure environment `cwd` instead of trying to recreate a client-only path
</Accordion>

View file

@ -0,0 +1,10 @@
---
title: "Graph rendering for templated comments"
date: "2026-06-15"
---
## More
<Accordion title="Fixes">
- Fixed workflow graph rendering when a leading DOT comment contains template braces such as `{{ goal }}`
</Accordion>

View file

@ -0,0 +1,18 @@
---
title: "Amazon Bedrock support"
date: "2026-06-16"
---
<Warning>
**Identifier and path settings no longer interpolate template tokens.** Model/provider selectors, Git author fields, SCM owner/repository fields, CLI target addresses, and `run.working_dir` are now literal strings. Replace any `{{ vars.* }}` or `{{ env.* }}` tokens in those fields with explicit values.
</Warning>
## Amazon Bedrock support
Running AWS-hosted models previously required a custom gateway. Fabro now includes an opt-in Amazon Bedrock provider for the Converse API, with streaming, tools, prompt caching, reasoning, and models from Anthropic, Amazon, Meta, Mistral, DeepSeek, and other Bedrock families. Authentication supports the AWS default credential chain with per-request SigV4 refresh or a Bedrock API key.
```toml title="settings.toml"
[llm.providers.bedrock]
enabled = true
base_url = "https://bedrock-runtime.us-east-1.amazonaws.com"
```

View file

@ -0,0 +1,22 @@
---
title: "MCP transport interpolation"
date: "2026-06-18"
---
<Warning>
**Control-plane settings no longer interpolate template tokens.** Server listen, API/web URL, storage, object-store, and GitHub App identity fields are now literal strings. Use native overrides such as `FABRO_WEB_URL` and `FABRO_STORAGE_DIR` where deployment-time values are required.
</Warning>
<Warning>
**A workflow goal can no longer reference itself.** A `{{ goal }}` token inside the graph goal now fails validation instead of passing through as literal text. Prompts may continue to reference the rendered goal.
</Warning>
## MCP transport interpolation
Environment-dependent MCP commands, URLs, headers, and environment values previously carried unresolved tokens into the launched server. `fabro run` and `fabro exec` now resolve `{{ env.NAME }}` at the boundary where the MCP server starts, and a missing variable fails clearly instead of leaking the token as text.
```toml
[run.agent.mcps.search]
type = "http"
url = "{{ env.SEARCH_MCP_URL }}"
```

View file

@ -0,0 +1,25 @@
---
title: "Variables in workflow prompts and goals"
date: "2026-06-24"
---
## Variables in workflow prompts and goals
Stored run variables previously worked in settings but were unavailable inside DOT prompts and goals. Node prompts, graph goals, imported subgraphs, and `@file` prompt/goal contents can now reference `{{ vars.NAME }}`; Fabro snapshots the server variable store when the run is created.
```dot
digraph Deploy {
graph [goal="Deploy {{ vars.SERVICE }}"]
work [prompt="Deploy to {{ vars.REGION }}"]
}
```
## More
<Accordion title="Workflows">
- `{{ inputs.* }}` outside prompts and goals now reports a specific error explaining that inputs are template-only
</Accordion>
<Accordion title="Fixes">
- Inline MCP entries now honor `enabled = false`, an explicitly empty `cli.exec.agent.mcps` set no longer falls back to run MCPs, and per-server `tool_timeout` values now apply
</Accordion>

View file

@ -0,0 +1,10 @@
---
title: "OpenRouter branding in model settings"
date: "2026-06-25"
---
## More
<Accordion title="Improvements">
- OpenRouter now displays its provider logo in **Settings → Models** instead of a letter fallback
</Accordion>

View file

@ -0,0 +1,11 @@
---
title: "Docker diagnostics and remote provider login"
date: "2026-06-26"
---
## More
<Accordion title="CLI">
- `fabro doctor` now pings the Docker daemon when the Docker sandbox provider is enabled and reports actionable failure or timeout details
- `fabro provider login --server ...` now reads the target server's catalog and tests credentials there, so you can log into providers that the local CLI does not know
</Accordion>

View file

@ -0,0 +1,10 @@
---
title: "Runtime security updates"
date: "2026-06-27"
---
## More
<Accordion title="Fixes">
- Updated the Rust `tar` runtime and React Router to patched releases that resolve disclosed security vulnerabilities
</Accordion>

View file

@ -0,0 +1,23 @@
---
title: "Safer hooks and managed MCP servers"
date: "2026-06-30"
---
<Warning>
**Hook interpolation now fails closed.** A missing or unavailable `{{ env.* }}` or `{{ secrets.* }}` token in a command, URL, header, prompt, or model blocks the hook instead of firing it with an empty or partially resolved value. Ensure every referenced value is available where the hook runs.
</Warning>
## Safer hook interpolation
Hook commands, URLs, headers, prompts, and models now carry typed interpolation through to execution instead of being flattened and reparsed. HTTP headers use the same narrow token syntax as other hook fields, and resolution failures consistently block command, HTTP, prompt, and agent hooks before they can act on incomplete data.
## More
<Accordion title="API">
- New `GET`, `POST`, `PUT`, and `DELETE /api/v1/mcp-servers` endpoints manage a shared MCP catalog with ETag concurrency; read responses expose configured key names without returning stored values
- Run configurations can reference a server-managed MCP definition with `id = "..."` instead of repeating its transport settings
</Accordion>
<Accordion title="Improvements">
- Workflow variables now live in SQLite; existing `variables.json` data is imported transactionally and renamed to a timestamped backup
</Accordion>

View file

@ -0,0 +1,30 @@
---
title: "MCP server settings and prepare-step environments"
date: "2026-07-01"
---
## Manage MCP servers in Settings
Server-managed MCP definitions previously required direct API calls. The new **Settings → MCP Servers** pages provide list, create, edit, and delete flows for stdio, HTTP, and sandbox transports. Credential-like values get a nudge toward `{{ secrets.NAME }}` references, while stored header and environment values remain write-only in the UI.
## Prepare-step environments
Per-step environment values in `run.prepare.steps` were parsed but dropped before execution. Prepare commands and their environment values now reach the sandbox, resolve `{{ env.* }}` at the run boundary, and fail clearly when a required value is missing; argv-style commands are also shell-quoted correctly.
```toml
[[run.prepare.steps]]
command = ["npm", "install"]
env = { NPM_TOKEN = "{{ env.NPM_TOKEN }}" }
```
## More
<Accordion title="Fixes">
- `Sandbox::glob` now applies consistent `*`, `**`, and path-segment matching across local, Docker, and Daytona environments, restoring remote skill discovery and common agent glob searches
- Newly created GitHub Apps now include the organization Projects V2 permission required by project-tracker workflows
</Accordion>
<Accordion title="Improvements">
- Newly created GitHub Apps now request Dependabot alert read/write permission; existing apps require a manual permission update and installation approval
- Server-managed environments now live in SQLite, with legacy TOML definitions imported and renamed to a timestamped backup
</Accordion>

View file

@ -0,0 +1,23 @@
---
title: "Faster web loading and run-time secret interpolation"
date: "2026-07-02"
---
## Faster web loading
Remote web sessions previously downloaded about 13.5 MB of uncompressed JavaScript on every refresh, delaying first render by roughly 1114 seconds on a 1 MB/s connection. Hashed assets now cache correctly, responses use Brotli or gzip compression, and dynamic chunks load only when needed, reducing the measured initial transfer to about 0.8 MB and making refreshes effectively instant.
## Run-time secret interpolation
Workflow configuration can now reference vault tokens with `{{ secrets.NAME }}` in MCP transports, prepare steps, and run environment values. Secrets resolve only in the worker at run start, are never persisted in expanded form, and a missing or non-token secret aborts startup instead of passing through literally.
```toml
[run.environment.env]
DEPLOY_TOKEN = "{{ secrets.DEPLOY_TOKEN }}"
```
## More
<Accordion title="Fixes">
- The stages sidebar now scrolls independently on run overview and stages pages, so long runs no longer push the graph off screen
</Accordion>

View file

@ -0,0 +1,10 @@
---
title: "Workflow graph direction in run views"
date: "2026-07-03"
---
## More
<Accordion title="Fixes">
- Run overview graphs now honor the workflow's `rankdir` instead of always rendering with the default direction
</Accordion>

View file

@ -0,0 +1,19 @@
---
title: "Private deployments with Tailscale Services"
date: "2026-07-07"
---
## Private deployments with Tailscale Services
Self-hosted Fabro can now stay private to a tailnet using the new loopback-only `docker-compose.tailscale.yaml` deployment. Set `FABRO_WEB_URL` to the Tailscale Service HTTPS origin, start the compose stack, and publish it with `tailscale serve`; Tailscale handles TLS without Caddy, public DNS, or a public Fabro port. Because a Tailscale Service is private, GitHub.com cannot deliver webhooks to it—use a public webhook relay, `server_url`, or Tailscale Funnel when webhooks are required.
```bash
docker compose -f docker-compose.tailscale.yaml up -d
tailscale serve --service=svc:fabro --https=443 http://127.0.0.1:32276
```
## More
<Accordion title="Fixes">
- Automation workflow slugs now preserve kebab-case, preventing names such as `patch-cves` from being saved as the non-existent `patch_cves`; previously saved snake-case selectors require manual correction
</Accordion>

View file

@ -0,0 +1,18 @@
---
title: "Trackpad navigation for run graphs"
date: "2026-07-08"
---
## Trackpad navigation for run graphs
Run overview graphs now use familiar canvas controls: two-finger scrolling pans, while Command/Ctrl-scroll or trackpad pinch zooms smoothly around the cursor. Drag-to-pan, toolbar zoom, fit-to-window, node interaction, and browser back-navigation protection continue to work with the shared viewport state.
## More
<Accordion title="Workflows">
- Added `[run.checkpoint] commit_timeout_ms` so repositories with long-running commit hooks can raise the per-node checkpoint timeout above its 30-second default
</Accordion>
<Accordion title="Fixes">
- Runs created before the prepare-step schema change now load in the run list again instead of disappearing during projection rebuild
</Accordion>

View file

@ -3,8 +3,23 @@ title: "Provider header interpolation"
date: "2026-07-09"
---
<Warning>
**Provider `extra_headers` use a new value syntax.** Replace `{ literal = "value" }` with `"value"`, `{ env = "NAME" }` with `"{{ env.NAME }}"`, and `{ vault = "NAME" }` with `"{{ secrets.NAME }}"`.
</Warning>
## Provider header interpolation
Provider `extra_headers` now use interpolation strings instead of typed `{ literal = ... }`, `{ env = ... }`, and `{ vault = ... }` tables. Write literal header values as plain strings, replace `{ env = "X" }` with a `{{ env.X }}` token, and replace `{ vault = "X" }` with a `{{ secrets.X }}` token. Secret header tokens resolve only token-style vault entries, so file and OAuth vault entries fail closed.
Provider headers can now mix literal text with environment or secret values in one string, making bearer prefixes and gateway-specific formats straightforward. Secret tokens resolve only token-style vault entries, so missing, file, and OAuth secrets fail closed; put credentials in secrets rather than literal header values.
This also enables mixed literal and secret values such as `Authorization = "Bearer {{ secrets.GATEWAY_TOKEN }}"`. Bare string header values are now accepted; put credentials in secrets and reference them with `{{ secrets.NAME }}` instead of pasting a credential as a literal. Provider `base_url` remains a plain literal string for now and is not interpolated.
```toml
[llm.providers.gateway.extra_headers]
Authorization = "Bearer {{ secrets.GATEWAY_TOKEN }}"
```
Provider `base_url` remains a literal string and is not interpolated.
## More
<Accordion title="Improvements">
- Run graph zoom and pan now survive switching between the Overview and Stages tabs
</Accordion>

View file

@ -0,0 +1,18 @@
---
title: "GPT-5.6 models"
date: "2026-07-10"
---
<Warning>
**`server.integrations.slack.default_channel` is now literal text.** Replace any `{{ env.NAME }}` token with an explicit channel name. Per-run Slack notification and interview channels still support interpolation.
</Warning>
## GPT-5.6 models
Fabro now includes GPT-5.6 Sol, Terra, and Luna in the built-in OpenAI catalog, routed through the Responses API with a Codex-safe 272K context policy. GPT-5.6 Sol becomes the OpenAI default, while all three models expose their current capabilities, reasoning controls, limits, aliases, and pricing.
## More
<Accordion title="Fixes">
- Long ACP agent turns now refresh GitHub App push credentials at turn entry and every 45 minutes, preventing late `git push` operations from failing after installation tokens expire
</Accordion>

View file

@ -0,0 +1,15 @@
---
title: "Unified SQLite storage"
date: "2026-07-11"
---
## Unified SQLite storage
Server-managed secrets, MCP servers, automations, and run summaries now share Fabro's SQLite database instead of separate JSON or TOML stores. Existing data is imported during startup, with legacy sources renamed to timestamped backups after a successful transaction; the existing APIs and settings UI remain unchanged.
## More
<Accordion title="Fixes">
- Restored process-environment LLM credentials for standalone CLI and agent sessions after the secrets storage migration
- Fixed avatars and principal icons being squeezed into ovals in the runs list **By** column
</Accordion>

View file

@ -0,0 +1,35 @@
---
title: "Poolside Laguna and safer database migrations"
date: "2026-07-22"
---
## Poolside Laguna models
Fabro now includes Poolside as a built-in OpenAI-compatible provider for Laguna S 2.1 and Laguna XS 2.1, with native reasoning and tool use. Both models are available directly from Poolside and through the opt-in OpenRouter provider.
```bash
fabro provider login --provider poolside
fabro run workflow.fabro --model laguna-s-2.1
```
## Safer database migrations
Schema upgrades now create a consistent `fabro.sqlite3.pre-migration.bak` snapshot before applying a new migration. If you need to roll back to an older binary, you have a known-good database from immediately before the latest schema change instead of having to repair migration metadata by hand.
## More
<Accordion title="CLI">
- `fabro repo init` now leaves the sample workflow environment unset so the target server can supply its configured default
</Accordion>
<Accordion title="Fixes">
- Parallel branch stages now reach a terminal state with their own duration instead of remaining **Running** after the fan-in and run complete
- OpenAI-compatible agent providers now receive compatible object-schema tools and an `edit_file` tool instead of the OpenAI-only custom patch tool
- Fixed legacy provider token details producing negative billing buckets in run summaries
</Accordion>
<Accordion title="Improvements">
- Added Kimi K3 through the direct Kimi provider and OpenRouter
- Added GLM 5.2 through Z.AI and OpenRouter
- Left-to-right run graphs now zoom to 400% and preserve separate viewport positions for left-to-right and top-to-bottom layouts
</Accordion>

View file

@ -0,0 +1,48 @@
---
title: "Provider-aware models and reliable agent control"
date: "2026-07-23"
---
<Warning>
**Ineffective agent execution-limit SDK fields were removed.** `SessionOptions.max_turns`, `SessionOptions.max_tool_rounds_per_input`, and the `TurnLimitReached` event no longer exist. Use session wall-clock timeouts or interruption when you need an execution bound.
</Warning>
## Provider-aware model selection
Model aliases used to be globally unique, which made portable model names ambiguous across direct providers and aggregators. Providers can now expose the same canonical slug and aliases: Fabro selects the highest-priority ready offering for an unqualified name, treats an explicit provider as a pin, and persists the chosen offering when the run is created. Custom offerings now nest under their provider; legacy top-level `[llm.models]` rows and historical built-in selectors remain accepted for compatibility.
```toml title="settings.toml"
[llm.providers.proxy.models."team-code-large"]
api_id = "provider-wire-model-name"
aliases = ["team-code"]
```
## Reliable interrupts and cancellation
Interrupting an agent now settles active inference, tools, and subagent waits before the stage enters a durable **waiting for steering** state shown in the web UI. Steering resumes from that state without orphaning child agents, while live run cancellations are durably recorded and remain visibly **Cancelling…** until the run reaches its terminal cancelled state.
## More
<Accordion title="API">
- LLM requests made during a run now carry `x-session-id: <run-id>` so compatible gateways can group them into one trace session
</Accordion>
<Accordion title="Workflows">
- `fabro validate` now warns when handler-specific attributes are placed on node or parallel-branch types that never read them, including clearer diagnostics for multiple parallel parents, custom types, and inherited thread settings
- Run manifests now bundle `@file` references used by `output_schema`
</Accordion>
<Accordion title="Fixes">
- Provider-reported completion costs now survive agent and workflow event projection, and billing accumulation saturates safely
- Explicit provider pins are preserved through run materialization and request-time routing instead of being redirected to a higher-priority provider
- OpenRouter Claude requests now emit cache-control breakpoints, enabling the prompt-cache reads and writes advertised by those catalog entries
- Agent stage events are flushed before stage completion, preventing final tool and usage events from appearing after the stage is marked done
- Agent routing's last-file fallback now accepts only `.json` and `.md` files whose final standalone object contains routing fields
- Generated run titles update atomically and no longer overwrite a title changed while generation was in flight
- Child OpenAI plans no longer replace the root agent's TODO list in the stage sidebar
- Run deletion failures now show delete-specific error messages
</Accordion>
<Accordion title="Improvements">
- OpenRouter now includes Claude Fable 5, Claude Opus 4.8, and GPT-5.6 Sol, Terra, and Luna offerings
</Accordion>

View file

@ -0,0 +1,45 @@
---
title: "Shared-checkout parallelism, Fireworks, and resume history"
date: "2026-07-24"
---
<Warning>
**Parallel branches now share one checkout, and `join_policy` was removed.** Remove `join_policy` from parallel nodes; fan-out now waits for every branch. Keep file-writing branches read-only or assign disjoint paths, and update fan-in logic to consume `parallel.results` instead of a selected branch workspace or `parallel_results.json`.
</Warning>
## Shared-checkout parallel execution
Parallel branches now run concurrently in the run's existing sandbox and working directory instead of creating branch-specific Git worktrees. Each branch still receives isolated context updates, returned in outgoing-edge order under `parallel.results`, while a prompted fan-in can synthesize the complete typed result array. Promptless fan-in nodes act as barriers and never select, restore, or merge workspace state.
## Fireworks AI
Fireworks AI is now an opt-in built-in provider with a curated serverless catalog for Kimi, DeepSeek, GLM, MiniMax, Qwen, and GPT-OSS models. The integration uses the existing OpenAI-compatible path, supports cached-input accounting, and works with the normal provider login, secret storage, diagnostics, and model-testing flows.
```toml title="settings.toml"
[llm.providers.fireworks]
enabled = true
```
## Resumed stages keep their history
When a run resumes after a node was cancelled or lost mid-flight, the replay now starts a new stage execution such as `work@2` instead of clearing and reusing `work@1`. The earlier execution keeps its events, session, output, timing, billing, and terminal state, and the stage UI links the new execution back to the one it resumed from.
## More
<Accordion title="API">
- `GET /api/v1/runs/{id}/events` now supports descending cursor pagination with `order=desc` and `before_seq`; `fabro run events --tail` uses it to fetch only the newest events
- Completion usage now reports disjoint input, output, reasoning, cache-read, and cache-write token buckets
- Model responses now advertise exact `controls.reasoning_effort` values, and completion requests—including structured completions—validate and forward reasoning effort with a `400` response for unsupported values
</Accordion>
<Accordion title="Fixes">
- Event history scans now use seek-based pagination with bounded cursors, avoiding full-history work and incorrect results for oversized sequence values
- Preflight now prefers providers that are actually ready while preserving explicit provider pins and useful diagnostics for unavailable offerings
- OpenAI-compatible agent providers now receive compatible file-edit and tool schemas
- Large values inside parallel branch results now stay available to fan-in prompts through normal artifact storage
</Accordion>
<Accordion title="Improvements">
- Added `gpt-sol`, `gpt-terra`, and `gpt-luna` aliases for GPT-5.6 offerings
- Added portable `glm`, `glm52`, `glm5.2`, `deepseek`, and `deepseek-flash` aliases across direct and OpenRouter offerings
</Accordion>

View file

@ -291,10 +291,39 @@
"tab": "Changelog",
"icon": "clock-rotate-left",
"groups": [
{
"group": "July 2026",
"icon": "clock-rotate-left",
"pages": [
"changelog/2026-07-24",
"changelog/2026-07-23",
"changelog/2026-07-22",
"changelog/2026-07-11",
"changelog/2026-07-10",
"changelog/2026-07-09",
"changelog/2026-07-08",
"changelog/2026-07-07",
"changelog/2026-07-03",
"changelog/2026-07-02",
"changelog/2026-07-01"
]
},
{
"group": "June 2026",
"icon": "clock-rotate-left",
"pages": [
"changelog/2026-06-30",
"changelog/2026-06-27",
"changelog/2026-06-26",
"changelog/2026-06-25",
"changelog/2026-06-24",
"changelog/2026-06-18",
"changelog/2026-06-16",
"changelog/2026-06-15",
"changelog/2026-06-14",
"changelog/2026-06-13",
"changelog/2026-06-12",
"changelog/2026-06-11",
"changelog/2026-06-10",
"changelog/2026-06-09",
"changelog/2026-06-05",