From 46bbac92eb69c6f437ae35152130e7502815adb9 Mon Sep 17 00:00:00 2001 From: "fabro-releases[bot]" Date: Wed, 29 Apr 2026 09:55:40 +0000 Subject: [PATCH 1/5] Bump version to 0.218.0-nightly.0 --- Cargo.lock | 84 +++++++++++++++++++++++++++--------------------------- Cargo.toml | 2 +- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f88c821aa..660096da4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1535,7 +1535,7 @@ dependencies = [ [[package]] name = "fabro-agent" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "anyhow", "async-trait", @@ -1574,7 +1574,7 @@ dependencies = [ [[package]] name = "fabro-api" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "chrono", "fabro-config", @@ -1594,7 +1594,7 @@ dependencies = [ [[package]] name = "fabro-auth" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "anyhow", "async-trait", @@ -1617,7 +1617,7 @@ dependencies = [ [[package]] name = "fabro-checkpoint" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "chrono", "fabro-config", @@ -1633,7 +1633,7 @@ dependencies = [ [[package]] name = "fabro-cli" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "anyhow", "assert_cmd", @@ -1727,7 +1727,7 @@ dependencies = [ [[package]] name = "fabro-client" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "anyhow", "bytes", @@ -1756,7 +1756,7 @@ dependencies = [ [[package]] name = "fabro-config" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "anyhow", "chrono", @@ -1783,7 +1783,7 @@ dependencies = [ [[package]] name = "fabro-core" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "async-trait", "fabro-types", @@ -1798,7 +1798,7 @@ dependencies = [ [[package]] name = "fabro-dev" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "anyhow", "assert_cmd", @@ -1818,7 +1818,7 @@ dependencies = [ [[package]] name = "fabro-devcontainer" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "fabro-http", "fabro-static", @@ -1835,7 +1835,7 @@ dependencies = [ [[package]] name = "fabro-github" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "base64", "chrono", @@ -1856,7 +1856,7 @@ dependencies = [ [[package]] name = "fabro-graphviz" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "anyhow", "fabro-types", @@ -1870,7 +1870,7 @@ dependencies = [ [[package]] name = "fabro-hooks" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "async-trait", "fabro-agent", @@ -1894,7 +1894,7 @@ dependencies = [ [[package]] name = "fabro-http" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "fabro-static", "http", @@ -1904,7 +1904,7 @@ dependencies = [ [[package]] name = "fabro-install" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "anyhow", "base64", @@ -1919,7 +1919,7 @@ dependencies = [ [[package]] name = "fabro-interview" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "async-trait", "dialoguer", @@ -1933,7 +1933,7 @@ dependencies = [ [[package]] name = "fabro-llm" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "anyhow", "async-trait", @@ -1965,7 +1965,7 @@ dependencies = [ [[package]] name = "fabro-macros" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "clap", "fabro-options-metadata", @@ -1976,7 +1976,7 @@ dependencies = [ [[package]] name = "fabro-mcp" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "anyhow", "fabro-config", @@ -1992,7 +1992,7 @@ dependencies = [ [[package]] name = "fabro-model" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "fabro-static", "insta", @@ -2003,7 +2003,7 @@ dependencies = [ [[package]] name = "fabro-oauth" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "axum", "base64", @@ -2024,7 +2024,7 @@ dependencies = [ [[package]] name = "fabro-options-metadata" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "serde", "serde_json", @@ -2032,7 +2032,7 @@ dependencies = [ [[package]] name = "fabro-proc" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "cc", "libc", @@ -2041,7 +2041,7 @@ dependencies = [ [[package]] name = "fabro-redact" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "aho-corasick", "ref-cast", @@ -2057,7 +2057,7 @@ dependencies = [ [[package]] name = "fabro-retro" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "anyhow", "chrono", @@ -2075,7 +2075,7 @@ dependencies = [ [[package]] name = "fabro-sandbox" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "anyhow", "async-trait", @@ -2111,7 +2111,7 @@ dependencies = [ [[package]] name = "fabro-server" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "anyhow", "async-trait", @@ -2192,7 +2192,7 @@ dependencies = [ [[package]] name = "fabro-slack" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "fabro-http", "fabro-interview", @@ -2212,18 +2212,18 @@ dependencies = [ [[package]] name = "fabro-spa" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "rust-embed", ] [[package]] name = "fabro-static" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" [[package]] name = "fabro-store" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "async-trait", "bytes", @@ -2250,7 +2250,7 @@ dependencies = [ [[package]] name = "fabro-telemetry" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "anyhow", "base64", @@ -2276,7 +2276,7 @@ dependencies = [ [[package]] name = "fabro-template" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "anyhow", "fabro-util", @@ -2288,7 +2288,7 @@ dependencies = [ [[package]] name = "fabro-test" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "assert_cmd", "axum", @@ -2311,7 +2311,7 @@ dependencies = [ [[package]] name = "fabro-tracker" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "async-trait", "fabro-github", @@ -2324,7 +2324,7 @@ dependencies = [ [[package]] name = "fabro-types" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "chrono", "clap", @@ -2345,7 +2345,7 @@ dependencies = [ [[package]] name = "fabro-util" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "anyhow", "console 0.15.11", @@ -2365,7 +2365,7 @@ dependencies = [ [[package]] name = "fabro-validate" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "fabro-graphviz", "fabro-model", @@ -2375,7 +2375,7 @@ dependencies = [ [[package]] name = "fabro-vault" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "chrono", "fabro-types", @@ -2387,7 +2387,7 @@ dependencies = [ [[package]] name = "fabro-workflow" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "anyhow", "assert_cmd", @@ -7127,7 +7127,7 @@ dependencies = [ [[package]] name = "twin-github" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "axum", "base64", @@ -7146,7 +7146,7 @@ dependencies = [ [[package]] name = "twin-openai" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" dependencies = [ "anyhow", "async-stream", diff --git a/Cargo.toml b/Cargo.toml index a6b84dbd5..973b8ef74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ resolver = "2" [workspace.package] edition = "2021" -version = "0.217.0-nightly.0" +version = "0.218.0-nightly.0" license = "MIT" [workspace.dependencies] From 066cd9fa158e882770f2229e34d0aeab1554526d Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Wed, 29 Apr 2026 09:00:42 -0400 Subject: [PATCH 2/5] ui(web): right-align Graph/Source toggle on run graph page Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/fabro-web/app/routes/run-graph.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/fabro-web/app/routes/run-graph.tsx b/apps/fabro-web/app/routes/run-graph.tsx index 1590a2ac9..c018279c4 100644 --- a/apps/fabro-web/app/routes/run-graph.tsx +++ b/apps/fabro-web/app/routes/run-graph.tsx @@ -191,7 +191,9 @@ export default function RunGraph() {
- +
+ +
{view === "graph" ? (
From b36be97675dc984b33dab1ad3801b584d9ea4b11 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Wed, 29 Apr 2026 09:01:38 -0400 Subject: [PATCH 3/5] fix(web): keep graph mounted when toggling to source view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- apps/fabro-web/app/routes/run-graph.tsx | 51 +++++++++++++------------ 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/apps/fabro-web/app/routes/run-graph.tsx b/apps/fabro-web/app/routes/run-graph.tsx index c018279c4..13f4b3cc5 100644 --- a/apps/fabro-web/app/routes/run-graph.tsx +++ b/apps/fabro-web/app/routes/run-graph.tsx @@ -195,35 +195,38 @@ export default function RunGraph() {
- {view === "graph" ? ( -
- + + + {view === "source" && ( )}
From 81f73e8246c06ec41c1fe385279476cb53371eec Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Wed, 29 Apr 2026 09:09:45 -0400 Subject: [PATCH 4/5] 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) --- apps/fabro-web/app/routes/run-graph.tsx | 45 ++++++++++++++++++------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/apps/fabro-web/app/routes/run-graph.tsx b/apps/fabro-web/app/routes/run-graph.tsx index 13f4b3cc5..c42f5113f 100644 --- a/apps/fabro-web/app/routes/run-graph.tsx +++ b/apps/fabro-web/app/routes/run-graph.tsx @@ -1,8 +1,8 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useParams } from "react-router"; +import type { BundledLanguage } from "@pierre/diffs"; import { graphTheme } from "../lib/graph-theme"; import { useRunGraph, useRunGraphSource, useRunStages } from "../lib/queries"; -import { CopyButton } from "../components/ui"; import { LoadingState } from "../components/state"; import { StageSidebar } from "../components/stage-sidebar"; import { @@ -10,6 +10,8 @@ import { GRAPH_ZOOM_STEPS, GraphToolbar, } from "../components/graph-toolbar"; +import { CollapsibleFile } from "../components/collapsible-file"; +import { registerDotLanguage } from "../data/register-dot-language"; import { mapRunStagesToSidebarStages } from "../lib/stage-sidebar"; export const handle = { wide: true }; @@ -91,6 +93,17 @@ export default function RunGraph() { const [error, setError] = useState(null); const [zoomIndex, setZoomIndex] = useState(GRAPH_DEFAULT_ZOOM_INDEX); const [pan, setPan] = useState({ x: 0, y: 0 }); + const [dotReady, setDotReady] = useState(false); + + useEffect(() => { + let cancelled = false; + registerDotLanguage().then(() => { + if (!cancelled) setDotReady(true); + }); + return () => { + cancelled = true; + }; + }, []); const dragState = useRef<{ startX: number; startY: number; startPanX: number; startPanY: number } | null>(null); const zoom = GRAPH_ZOOM_STEPS[zoomIndex]; @@ -227,7 +240,11 @@ export default function RunGraph() {
{view === "source" && ( - + )} @@ -259,8 +276,16 @@ function ViewToggle({ view, setView }: { view: View; setView: (v: View) => void ); } -function SourcePanel({ source, loading }: { source: string | null | undefined; loading: boolean }) { - if (loading) { +function SourcePanel({ + source, + loading, + dotReady, +}: { + source: string | null | undefined; + loading: boolean; + dotReady: boolean; +}) { + if (loading || !dotReady) { return (
@@ -275,14 +300,8 @@ function SourcePanel({ source, loading }: { source: string | null | undefined; l ); } return ( -
-
- workflow.fabro - -
-
-        {source}
-      
-
+ ); } From beff3985f02990d705345c4f52c0b0fd0758809c Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Wed, 29 Apr 2026 09:12:40 -0400 Subject: [PATCH 5/5] 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) --- apps/fabro-web/app/routes/settings.tsx | 71 +++++++++++++++++++++----- 1 file changed, 59 insertions(+), 12 deletions(-) diff --git a/apps/fabro-web/app/routes/settings.tsx b/apps/fabro-web/app/routes/settings.tsx index cf4b1f1fb..e789be717 100644 --- a/apps/fabro-web/app/routes/settings.tsx +++ b/apps/fabro-web/app/routes/settings.tsx @@ -1,23 +1,27 @@ -import type { ReactNode } from "react"; +import { useState, type ReactNode } from "react"; import type { ObjectStoreSettings, ServerListenSettings, ServerSettings, } from "@qltysh/fabro-api-client"; import { useServerSettings } from "../lib/queries"; +import { CollapsibleFile } from "../components/collapsible-file"; export function meta({}: any) { return [{ title: "Settings — Fabro" }]; } +type View = "settings" | "json"; + export default function Settings() { const settingsQuery = useServerSettings(); const settings = settingsQuery.data; + const [view, setView] = useState("settings"); if (!settings) { return (
- + @@ -27,21 +31,64 @@ export default function Settings() { return (
- - - - + + {view === "settings" ? ( + <> + + + + + ) : ( + + )}
); } -function PageIntro() { +function PageIntro({ view, setView }: { view: View; setView: (v: View) => void }) { return ( -

- Snapshot of the server configuration. Edit via{" "} - settings.toml; changes take - effect on the next server restart. -

+
+

+ Snapshot of the server configuration. Edit via{" "} + settings.toml; changes take + effect on the next server restart. +

+ +
+ ); +} + +function ViewToggle({ view, setView }: { view: View; setView: (v: View) => void }) { + const btn = "rounded px-3 py-1.5 text-xs font-medium transition-colors"; + return ( +
+ + +
); }