diff --git a/.github/assets/children-tab/populated.png b/.github/assets/children-tab/populated.png new file mode 100644 index 000000000..dd04d4fd0 Binary files /dev/null and b/.github/assets/children-tab/populated.png differ diff --git a/.github/assets/children-tab/zero-state.png b/.github/assets/children-tab/zero-state.png new file mode 100644 index 000000000..a475b7acd Binary files /dev/null and b/.github/assets/children-tab/zero-state.png differ diff --git a/apps/fabro-web/app/data/runs.ts b/apps/fabro-web/app/data/runs.ts index 9ff09e868..28a0160a8 100644 --- a/apps/fabro-web/app/data/runs.ts +++ b/apps/fabro-web/app/data/runs.ts @@ -136,6 +136,16 @@ export function columnForRun(run: Run): BoardColumn | null { return columnForStatus(run.lifecycle.status); } +export function toRunWithStatus(run: Run): RunWithStatus { + const item = mapRunListItem(run); + const column = columnForRun(run) ?? "queued"; + return { + ...item, + status: column, + statusLabel: columnStatusDisplay[column].label, + }; +} + export function deriveCiStatus(checks: CheckRun[]): CiStatus { if (checks.some((c) => c.status === "failure")) return "failing"; if (checks.some((c) => c.status === "pending" || c.status === "queued")) return "pending"; diff --git a/apps/fabro-web/app/lib/queries.ts b/apps/fabro-web/app/lib/queries.ts index 90f8307bc..8f7bce147 100644 --- a/apps/fabro-web/app/lib/queries.ts +++ b/apps/fabro-web/app/lib/queries.ts @@ -143,6 +143,16 @@ export function useRunFiles( ); } +export function useChildRuns(parentId: string | undefined) { + return useSWR( + parentId ? queryKeys.runs.children(parentId) : null, + () => + apiNullableData(() => + runsApi.listRuns(undefined, undefined, false, parentId!), + ), + ); +} + export function useRunCommits(id: string | undefined) { return useSWR( id ? queryKeys.runs.commits(id) : null, diff --git a/apps/fabro-web/app/lib/query-keys.ts b/apps/fabro-web/app/lib/query-keys.ts index ac86a9101..eaf2b952c 100644 --- a/apps/fabro-web/app/lib/query-keys.ts +++ b/apps/fabro-web/app/lib/query-keys.ts @@ -50,6 +50,7 @@ export const queryKeys = { queryKeys.runs.files(id, runFileScopeSelection(scope)), ), commits: (id: string) => ["runs", "commits", id] as const, + children: (parentId: string) => ["runs", "children", parentId] as const, stages: (id: string) => ["runs", "stages", id] as const, graph: (id: string, direction?: RunGraphDirection) => ["runs", "graph", id, direction ?? null] as const, diff --git a/apps/fabro-web/app/router.tsx b/apps/fabro-web/app/router.tsx index 6e1d085bc..602e3b234 100644 --- a/apps/fabro-web/app/router.tsx +++ b/apps/fabro-web/app/router.tsx @@ -23,6 +23,7 @@ import * as RunSource from "./routes/run-source"; import * as RunLogs from "./routes/run-logs"; import * as RunEvents from "./routes/run-events"; import * as RunArtifacts from "./routes/run-artifacts"; +import * as RunChildren from "./routes/run-children"; import * as RunFiles from "./routes/run-files"; import * as RunSandbox from "./routes/run-sandbox"; import * as RunTerminal from "./routes/run-terminal"; @@ -116,6 +117,7 @@ export const routes: RouteObject[] = [ route("events", RunEvents), route("artifacts", RunArtifacts), route("files", RunFiles), + route("children", RunChildren), route("sandbox", RunSandbox), route("billing", RunBilling), ], diff --git a/apps/fabro-web/app/routes/run-children.tsx b/apps/fabro-web/app/routes/run-children.tsx new file mode 100644 index 000000000..ca0181764 --- /dev/null +++ b/apps/fabro-web/app/routes/run-children.tsx @@ -0,0 +1,124 @@ +import { useCallback, useEffect, useRef, useState } from "react"; +import { useParams } from "react-router"; +import { ArrowPathIcon } from "@heroicons/react/20/solid"; + +import { EmptyState, ErrorState, LoadingState } from "../components/state"; +import { SECONDARY_BUTTON_CLASS } from "../components/ui"; +import { toRunWithStatus } from "../data/runs"; +import { ApiError } from "../lib/api-client"; +import { formatRelativeTime } from "../lib/format"; +import { useChildRuns, useRun } from "../lib/queries"; +import { RUNS_LIST_GRID_TEMPLATE, RunRow } from "./runs"; + +export default function RunChildren() { + const { id } = useParams(); + const runQuery = useRun(id); + const childRunsQuery = useChildRuns(id); + + const lastFetchedAtRef = useRef(null); + const [now, setNow] = useState(() => Date.now()); + + useEffect(() => { + if (childRunsQuery.data) { + lastFetchedAtRef.current = Date.now(); + setNow(Date.now()); + } + }, [childRunsQuery.data]); + + useEffect(() => { + const interval = window.setInterval(() => setNow(Date.now()), 15_000); + return () => window.clearInterval(interval); + }, []); + + const handleRefresh = useCallback(() => { + void childRunsQuery.mutate(); + void runQuery.mutate(); + }, [childRunsQuery, runQuery]); + + if (childRunsQuery.isLoading && !childRunsQuery.data) { + return ; + } + + const apiError = + childRunsQuery.error instanceof ApiError ? childRunsQuery.error : null; + if (apiError && !childRunsQuery.data) { + return ( + + ); + } + + const data = childRunsQuery.data; + const children = data?.data ?? []; + const hasMore = data?.meta.has_more ?? false; + const updatedAt = lastFetchedAtRef.current; + + return ( +
+
+

Runs spawned from this run.

+
+ {updatedAt != null ? ( + + Updated{" "} + {formatRelativeTime(new Date(updatedAt).toISOString(), now)} + + ) : null} + +
+
+ + {children.length === 0 ? ( + + Learn about parent links + + } + /> + ) : ( + <> +
+ {children.map((child) => ( + + ))} +
+ {hasMore ? ( +

+ Showing the first {children.length} child runs — more exist. +

+ ) : null} + + )} +
+ ); +} diff --git a/apps/fabro-web/app/routes/run-detail.tsx b/apps/fabro-web/app/routes/run-detail.tsx index c12c46b28..1820c7b93 100644 --- a/apps/fabro-web/app/routes/run-detail.tsx +++ b/apps/fabro-web/app/routes/run-detail.tsx @@ -62,6 +62,7 @@ const allTabs = [ { name: "Overview", path: "", count: null, demoOnly: false }, { name: "Stages", path: "/stages", count: null, demoOnly: false }, { name: "Files Changed", path: "/files", count: null, demoOnly: false }, + { name: "Children", path: "/children", count: null, demoOnly: false }, { name: "Sandbox", path: "/sandbox", count: null, demoOnly: false, requiresSandbox: true }, { name: "Billing", path: "/billing", count: null, demoOnly: false }, ]; @@ -189,11 +190,14 @@ export default function RunDetail({ params }: { params: { id: string } }) { const [deletePending, setDeletePending] = useState(false); const { push, dismiss } = useToast(); const filesCount = runQuery.data?.diff?.files_changed ?? null; + const childrenCount = runQuery.data?.children_count ?? null; const hasSandbox = runHasSandbox(runStateQuery.data); const tabs = allTabs - .map((tab) => - tab.name === "Files Changed" ? { ...tab, count: filesCount } : tab, - ) + .map((tab) => { + if (tab.name === "Files Changed") return { ...tab, count: filesCount }; + if (tab.name === "Children") return { ...tab, count: childrenCount }; + return tab; + }) .filter((t) => (!t.demoOnly || demoMode) && (!t.requiresSandbox || hasSandbox)); const lifecycleToastStateRef = useRef(INITIAL_LIFECYCLE_TOAST_STATE); const steerBarRef = useRef(null); diff --git a/apps/fabro-web/app/routes/runs.tsx b/apps/fabro-web/app/routes/runs.tsx index b01d3af24..6eb1652cd 100644 --- a/apps/fabro-web/app/routes/runs.tsx +++ b/apps/fabro-web/app/routes/runs.tsx @@ -581,7 +581,9 @@ function createdCutoffMsFor(filter: CreatedFilter): number | null { } } -function RunRow({ run }: { run: RunWithStatus }) { +export const RUNS_LIST_GRID_TEMPLATE = "auto 5rem auto 1fr auto auto 8rem auto"; + +export function RunRow({ run }: { run: RunWithStatus }) { const lifecycleLabel = listLifecycleStatusLabel(run); const statusDisplay = columnStatusDisplay[run.status]; @@ -995,7 +997,7 @@ export default function Runs() { ) : ( <> {filteredRuns > 0 && ( -
+
{visibleColumns.flatMap((col) => col.items.map((item) => ( diff --git a/docs/public/api-reference/fabro-api.yaml b/docs/public/api-reference/fabro-api.yaml index fff684c23..c45f52933 100644 --- a/docs/public/api-reference/fabro-api.yaml +++ b/docs/public/api-reference/fabro-api.yaml @@ -7302,12 +7302,18 @@ components: - current_question - superseded_by - links + - children_count properties: id: type: string parent_id: type: ["string", "null"] description: Current orchestration parent run ID, if linked. + children_count: + type: integer + format: uint64 + minimum: 0 + description: Number of runs currently linked to this run as their orchestration parent. title: type: string goal: diff --git a/lib/crates/fabro-api/tests/run_summary_round_trip.rs b/lib/crates/fabro-api/tests/run_summary_round_trip.rs index 2a9099dc8..33f7cb908 100644 --- a/lib/crates/fabro-api/tests/run_summary_round_trip.rs +++ b/lib/crates/fabro-api/tests/run_summary_round_trip.rs @@ -25,6 +25,7 @@ fn run_summary_json_matches_openapi_shape() { let summary = Run { id: run_id, parent_id: None, + children_count: 2, title: "API title".to_string(), goal: String::new(), workflow: WorkflowRef { @@ -83,6 +84,7 @@ fn run_summary_json_matches_openapi_shape() { serde_json::to_value(&summary).unwrap(), json!({ "id": run_id.to_string(), + "children_count": 2, "title": "API title", "goal": "", "workflow": { @@ -188,6 +190,7 @@ fn run_summary_deserializes_when_optional_fields_are_absent() { .unwrap(); assert_eq!(summary.id, run_id); + assert_eq!(summary.children_count, 0); assert_eq!(summary.workflow.name, "unnamed"); assert_eq!(summary.workflow.slug, None); assert_eq!(summary.goal, "ship it"); diff --git a/lib/crates/fabro-mcp-server/src/run_tools/search.rs b/lib/crates/fabro-mcp-server/src/run_tools/search.rs index bc6ce7d37..7b9ef9407 100644 --- a/lib/crates/fabro-mcp-server/src/run_tools/search.rs +++ b/lib/crates/fabro-mcp-server/src/run_tools/search.rs @@ -338,6 +338,7 @@ mod tests { Run { id: id.parse().expect("test run id should parse"), parent_id: None, + children_count: 0, title: "test".to_string(), goal: "test".to_string(), workflow: WorkflowRef { diff --git a/lib/crates/fabro-server/src/demo/mod.rs b/lib/crates/fabro-server/src/demo/mod.rs index c0f4f5515..7c781cf7f 100644 --- a/lib/crates/fabro-server/src/demo/mod.rs +++ b/lib/crates/fabro-server/src/demo/mod.rs @@ -1057,6 +1057,7 @@ mod runs { Run { id: run_id, parent_id: None, + children_count: 0, title: fabro_types::infer_run_title(goal), goal: goal.into(), workflow: WorkflowRef { diff --git a/lib/crates/fabro-store/src/run_state.rs b/lib/crates/fabro-store/src/run_state.rs index 67dd98001..6b4fd2d22 100644 --- a/lib/crates/fabro-store/src/run_state.rs +++ b/lib/crates/fabro-store/src/run_state.rs @@ -679,6 +679,7 @@ pub(crate) fn build_summary(state: &RunProjection, run_id: &RunId) -> Run { Run { id: *run_id, parent_id: state.parent_id, + children_count: 0, title: state.title().into_owned(), goal, workflow: WorkflowRef { diff --git a/lib/crates/fabro-store/src/slate/mod.rs b/lib/crates/fabro-store/src/slate/mod.rs index 969bd9b43..ae793ee1d 100644 --- a/lib/crates/fabro-store/src/slate/mod.rs +++ b/lib/crates/fabro-store/src/slate/mod.rs @@ -438,6 +438,12 @@ mod tests { .cast_unsigned(), 3, ), + "run-4" => ( + dt("2026-03-27T12:00:30Z") + .timestamp_millis() + .cast_unsigned(), + 4, + ), _ => panic!("unknown test run id: {label}"), }; RunId::from(ulid::Ulid::from_parts(timestamp_ms, random)) @@ -836,6 +842,51 @@ mod tests { assert_eq!(summaries[0].parent_id, Some(test_run_id("run-1"))); } + #[tokio::test] + async fn run_summary_includes_children_count() { + let (_object_store, store) = make_store(); + let parent = store.create_run(&test_run_id("run-1")).await.unwrap(); + let child_a = store.create_run(&test_run_id("run-2")).await.unwrap(); + let child_b = store.create_run(&test_run_id("run-3")).await.unwrap(); + let unrelated = store.create_run(&test_run_id("run-4")).await.unwrap(); + append_created(&parent, "run-1", dt("2026-03-27T12:00:00Z")).await; + append_created_with_parent( + &child_a, + "run-2", + dt("2026-03-27T12:00:10Z"), + test_run_id("run-1"), + ) + .await; + append_created_with_parent( + &child_b, + "run-3", + dt("2026-03-27T12:00:20Z"), + test_run_id("run-1"), + ) + .await; + append_created(&unrelated, "run-4", dt("2026-03-27T12:00:30Z")).await; + + let summaries = store.list_runs(&ListRunsQuery::default()).await.unwrap(); + + let parent_summary = summaries + .iter() + .find(|r| r.id == test_run_id("run-1")) + .expect("parent summary should be present"); + assert_eq!(parent_summary.children_count, 2); + + let child_summary = summaries + .iter() + .find(|r| r.id == test_run_id("run-2")) + .expect("child summary should be present"); + assert_eq!(child_summary.children_count, 0); + + let unrelated_summary = summaries + .iter() + .find(|r| r.id == test_run_id("run-4")) + .expect("unrelated summary should be present"); + assert_eq!(unrelated_summary.children_count, 0); + } + #[tokio::test] async fn control_effect_events_clear_pending_control_and_update_status() { let (_object_store, store) = make_store(); diff --git a/lib/crates/fabro-store/src/slate/projection_cache.rs b/lib/crates/fabro-store/src/slate/projection_cache.rs index 0b821aec6..32127fcea 100644 --- a/lib/crates/fabro-store/src/slate/projection_cache.rs +++ b/lib/crates/fabro-store/src/slate/projection_cache.rs @@ -79,6 +79,17 @@ impl RunProjectionCacheState { self.children_by_parent.remove(&parent_id); } } + + fn count_children(&self, run_id: &RunId) -> u64 { + self.children_by_parent + .get(run_id) + .map_or(0, |children| children.len() as u64) + } + + fn with_children_count(&self, mut entry: CachedRunProjection) -> CachedRunProjection { + entry.summary.children_count = self.count_children(&entry.run_id); + entry + } } impl RunProjectionCache { @@ -93,7 +104,7 @@ impl RunProjectionCache { pub(crate) async fn list(&self, query: &ListRunsQuery) -> Vec { let entries = { let state = self.state.lock().await; - match query.parent_id { + let raw = match query.parent_id { Some(parent_id) => state .children_by_parent .get(&parent_id) @@ -102,7 +113,10 @@ impl RunProjectionCache { .filter_map(|run_id| state.entries.get(run_id).cloned()) .collect::>(), None => state.entries.values().cloned().collect::>(), - } + }; + raw.into_iter() + .map(|entry| state.with_children_count(entry)) + .collect::>() }; let mut entries = entries .into_iter() @@ -128,16 +142,21 @@ impl RunProjectionCache { } pub(crate) async fn get(&self, run_id: &RunId) -> Option { - self.state.lock().await.entries.get(run_id).cloned() + let state = self.state.lock().await; + state + .entries + .get(run_id) + .cloned() + .map(|entry| state.with_children_count(entry)) } pub(crate) async fn get_summary(&self, run_id: &RunId) -> Option { - self.state - .lock() - .await - .entries - .get(run_id) - .map(|entry| entry.summary.clone()) + let state = self.state.lock().await; + state.entries.get(run_id).map(|entry| { + let mut summary = entry.summary.clone(); + summary.children_count = state.count_children(run_id); + summary + }) } pub(crate) async fn apply_event(&self, run_id: &RunId, event: &EventEnvelope) -> Result<()> { diff --git a/lib/crates/fabro-types/src/run_summary.rs b/lib/crates/fabro-types/src/run_summary.rs index 68c7ccb23..3a8a4c0ba 100644 --- a/lib/crates/fabro-types/src/run_summary.rs +++ b/lib/crates/fabro-types/src/run_summary.rs @@ -13,6 +13,8 @@ pub struct Run { pub id: RunId, #[serde(default, skip_serializing_if = "Option::is_none")] pub parent_id: Option, + #[serde(default)] + pub children_count: u64, pub title: String, pub goal: String, pub workflow: WorkflowRef, diff --git a/lib/packages/fabro-api-client/src/.openapi-generator/FILES b/lib/packages/fabro-api-client/src/.openapi-generator/FILES index 053768992..f33120152 100644 --- a/lib/packages/fabro-api-client/src/.openapi-generator/FILES +++ b/lib/packages/fabro-api-client/src/.openapi-generator/FILES @@ -235,6 +235,7 @@ models/pull-request-user.ts models/pull-request.ts models/question-type.ts models/reasoning-effort-feature.ts +models/related-workflow-diagnostic.ts models/render-workflow-graph-direction.ts models/render-workflow-graph-format.ts models/render-workflow-graph-request.ts diff --git a/lib/packages/fabro-api-client/src/api.ts b/lib/packages/fabro-api-client/src/api.ts index bda32eb1e..8f689f8f7 100644 --- a/lib/packages/fabro-api-client/src/api.ts +++ b/lib/packages/fabro-api-client/src/api.ts @@ -5,7 +5,7 @@ * HTTP API for managing Fabro workflow run executions. * * The version of the OpenAPI document: 0.1.0 - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech @@ -32,3 +32,4 @@ export * from './api/sessions-api'; export * from './api/settings-api'; export * from './api/system-api'; export * from './api/workflows-api'; + diff --git a/lib/packages/fabro-api-client/src/api/sessions-api.ts b/lib/packages/fabro-api-client/src/api/sessions-api.ts index f7e163321..7dfebba34 100644 --- a/lib/packages/fabro-api-client/src/api/sessions-api.ts +++ b/lib/packages/fabro-api-client/src/api/sessions-api.ts @@ -5,7 +5,7 @@ * HTTP API for managing Fabro workflow run executions. * * The version of the OpenAPI document: 0.1.0 - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech @@ -47,9 +47,9 @@ import type { UpdateSessionRequest } from '../models'; export const SessionsApiAxiosParamCreator = function (configuration?: Configuration) { return { /** - * + * * @summary Create session - * @param {CreateSessionRequest} createSessionRequest + * @param {CreateSessionRequest} createSessionRequest * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -88,9 +88,9 @@ export const SessionsApiAxiosParamCreator = function (configuration?: Configurat }; }, /** - * + * * @summary Delete session - * @param {string} id + * @param {string} id * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -127,9 +127,9 @@ export const SessionsApiAxiosParamCreator = function (configuration?: Configurat }; }, /** - * + * * @summary Get session - * @param {string} id + * @param {string} id * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -167,10 +167,10 @@ export const SessionsApiAxiosParamCreator = function (configuration?: Configurat }; }, /** - * + * * @summary Get session turn - * @param {string} id - * @param {string} turnId + * @param {string} id + * @param {string} turnId * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -211,10 +211,10 @@ export const SessionsApiAxiosParamCreator = function (configuration?: Configurat }; }, /** - * + * * @summary Interrupt a session turn - * @param {string} id - * @param {string} turnId + * @param {string} id + * @param {string} turnId * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -257,8 +257,8 @@ export const SessionsApiAxiosParamCreator = function (configuration?: Configurat /** * Returns JSON replay by default. When the `Accept` header includes `text/event-stream`, replays durable events from `since_seq` or `Last-Event-ID`, then stays attached for live events. * @summary List or stream session events - * @param {string} id - * @param {number} [sinceSeq] + * @param {string} id + * @param {number} [sinceSeq] * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -300,9 +300,9 @@ export const SessionsApiAxiosParamCreator = function (configuration?: Configurat }; }, /** - * + * * @summary List session turns - * @param {string} id + * @param {string} id * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -340,7 +340,7 @@ export const SessionsApiAxiosParamCreator = function (configuration?: Configurat }; }, /** - * + * * @summary List sessions * @param {*} [options] Override http request option. * @throws {RequiredError} @@ -378,8 +378,8 @@ export const SessionsApiAxiosParamCreator = function (configuration?: Configurat /** * Starts a streamed turn immediately. Background turns are not supported in this API version. * @summary Submit a session turn - * @param {string} id - * @param {SubmitTurnRequest} submitTurnRequest + * @param {string} id + * @param {SubmitTurnRequest} submitTurnRequest * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -421,10 +421,10 @@ export const SessionsApiAxiosParamCreator = function (configuration?: Configurat }; }, /** - * + * * @summary Update session - * @param {string} id - * @param {UpdateSessionRequest} updateSessionRequest + * @param {string} id + * @param {UpdateSessionRequest} updateSessionRequest * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -475,9 +475,9 @@ export const SessionsApiFp = function(configuration?: Configuration) { const localVarAxiosParamCreator = SessionsApiAxiosParamCreator(configuration) return { /** - * + * * @summary Create session - * @param {CreateSessionRequest} createSessionRequest + * @param {CreateSessionRequest} createSessionRequest * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -488,9 +488,9 @@ export const SessionsApiFp = function(configuration?: Configuration) { return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * + * * @summary Delete session - * @param {string} id + * @param {string} id * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -501,9 +501,9 @@ export const SessionsApiFp = function(configuration?: Configuration) { return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * + * * @summary Get session - * @param {string} id + * @param {string} id * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -514,10 +514,10 @@ export const SessionsApiFp = function(configuration?: Configuration) { return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * + * * @summary Get session turn - * @param {string} id - * @param {string} turnId + * @param {string} id + * @param {string} turnId * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -528,10 +528,10 @@ export const SessionsApiFp = function(configuration?: Configuration) { return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * + * * @summary Interrupt a session turn - * @param {string} id - * @param {string} turnId + * @param {string} id + * @param {string} turnId * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -544,8 +544,8 @@ export const SessionsApiFp = function(configuration?: Configuration) { /** * Returns JSON replay by default. When the `Accept` header includes `text/event-stream`, replays durable events from `since_seq` or `Last-Event-ID`, then stays attached for live events. * @summary List or stream session events - * @param {string} id - * @param {number} [sinceSeq] + * @param {string} id + * @param {number} [sinceSeq] * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -556,9 +556,9 @@ export const SessionsApiFp = function(configuration?: Configuration) { return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * + * * @summary List session turns - * @param {string} id + * @param {string} id * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -569,7 +569,7 @@ export const SessionsApiFp = function(configuration?: Configuration) { return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * + * * @summary List sessions * @param {*} [options] Override http request option. * @throws {RequiredError} @@ -583,8 +583,8 @@ export const SessionsApiFp = function(configuration?: Configuration) { /** * Starts a streamed turn immediately. Background turns are not supported in this API version. * @summary Submit a session turn - * @param {string} id - * @param {SubmitTurnRequest} submitTurnRequest + * @param {string} id + * @param {SubmitTurnRequest} submitTurnRequest * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -595,10 +595,10 @@ export const SessionsApiFp = function(configuration?: Configuration) { return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * + * * @summary Update session - * @param {string} id - * @param {UpdateSessionRequest} updateSessionRequest + * @param {string} id + * @param {UpdateSessionRequest} updateSessionRequest * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -618,9 +618,9 @@ export const SessionsApiFactory = function (configuration?: Configuration, baseP const localVarFp = SessionsApiFp(configuration) return { /** - * + * * @summary Create session - * @param {CreateSessionRequest} createSessionRequest + * @param {CreateSessionRequest} createSessionRequest * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -628,9 +628,9 @@ export const SessionsApiFactory = function (configuration?: Configuration, baseP return localVarFp.createSession(createSessionRequest, options).then((request) => request(axios, basePath)); }, /** - * + * * @summary Delete session - * @param {string} id + * @param {string} id * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -638,9 +638,9 @@ export const SessionsApiFactory = function (configuration?: Configuration, baseP return localVarFp.deleteSession(id, options).then((request) => request(axios, basePath)); }, /** - * + * * @summary Get session - * @param {string} id + * @param {string} id * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -648,10 +648,10 @@ export const SessionsApiFactory = function (configuration?: Configuration, baseP return localVarFp.getSession(id, options).then((request) => request(axios, basePath)); }, /** - * + * * @summary Get session turn - * @param {string} id - * @param {string} turnId + * @param {string} id + * @param {string} turnId * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -659,10 +659,10 @@ export const SessionsApiFactory = function (configuration?: Configuration, baseP return localVarFp.getSessionTurn(id, turnId, options).then((request) => request(axios, basePath)); }, /** - * + * * @summary Interrupt a session turn - * @param {string} id - * @param {string} turnId + * @param {string} id + * @param {string} turnId * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -672,8 +672,8 @@ export const SessionsApiFactory = function (configuration?: Configuration, baseP /** * Returns JSON replay by default. When the `Accept` header includes `text/event-stream`, replays durable events from `since_seq` or `Last-Event-ID`, then stays attached for live events. * @summary List or stream session events - * @param {string} id - * @param {number} [sinceSeq] + * @param {string} id + * @param {number} [sinceSeq] * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -681,9 +681,9 @@ export const SessionsApiFactory = function (configuration?: Configuration, baseP return localVarFp.listSessionEvents(id, sinceSeq, options).then((request) => request(axios, basePath)); }, /** - * + * * @summary List session turns - * @param {string} id + * @param {string} id * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -691,7 +691,7 @@ export const SessionsApiFactory = function (configuration?: Configuration, baseP return localVarFp.listSessionTurns(id, options).then((request) => request(axios, basePath)); }, /** - * + * * @summary List sessions * @param {*} [options] Override http request option. * @throws {RequiredError} @@ -702,8 +702,8 @@ export const SessionsApiFactory = function (configuration?: Configuration, baseP /** * Starts a streamed turn immediately. Background turns are not supported in this API version. * @summary Submit a session turn - * @param {string} id - * @param {SubmitTurnRequest} submitTurnRequest + * @param {string} id + * @param {SubmitTurnRequest} submitTurnRequest * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -711,10 +711,10 @@ export const SessionsApiFactory = function (configuration?: Configuration, baseP return localVarFp.submitSessionTurn(id, submitTurnRequest, options).then((request) => request(axios, basePath)); }, /** - * + * * @summary Update session - * @param {string} id - * @param {UpdateSessionRequest} updateSessionRequest + * @param {string} id + * @param {UpdateSessionRequest} updateSessionRequest * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -729,9 +729,9 @@ export const SessionsApiFactory = function (configuration?: Configuration, baseP */ export class SessionsApi extends BaseAPI { /** - * + * * @summary Create session - * @param {CreateSessionRequest} createSessionRequest + * @param {CreateSessionRequest} createSessionRequest * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -740,9 +740,9 @@ export class SessionsApi extends BaseAPI { } /** - * + * * @summary Delete session - * @param {string} id + * @param {string} id * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -751,9 +751,9 @@ export class SessionsApi extends BaseAPI { } /** - * + * * @summary Get session - * @param {string} id + * @param {string} id * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -762,10 +762,10 @@ export class SessionsApi extends BaseAPI { } /** - * + * * @summary Get session turn - * @param {string} id - * @param {string} turnId + * @param {string} id + * @param {string} turnId * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -774,10 +774,10 @@ export class SessionsApi extends BaseAPI { } /** - * + * * @summary Interrupt a session turn - * @param {string} id - * @param {string} turnId + * @param {string} id + * @param {string} turnId * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -788,8 +788,8 @@ export class SessionsApi extends BaseAPI { /** * Returns JSON replay by default. When the `Accept` header includes `text/event-stream`, replays durable events from `since_seq` or `Last-Event-ID`, then stays attached for live events. * @summary List or stream session events - * @param {string} id - * @param {number} [sinceSeq] + * @param {string} id + * @param {number} [sinceSeq] * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -798,9 +798,9 @@ export class SessionsApi extends BaseAPI { } /** - * + * * @summary List session turns - * @param {string} id + * @param {string} id * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -809,7 +809,7 @@ export class SessionsApi extends BaseAPI { } /** - * + * * @summary List sessions * @param {*} [options] Override http request option. * @throws {RequiredError} @@ -821,8 +821,8 @@ export class SessionsApi extends BaseAPI { /** * Starts a streamed turn immediately. Background turns are not supported in this API version. * @summary Submit a session turn - * @param {string} id - * @param {SubmitTurnRequest} submitTurnRequest + * @param {string} id + * @param {SubmitTurnRequest} submitTurnRequest * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -831,10 +831,10 @@ export class SessionsApi extends BaseAPI { } /** - * + * * @summary Update session - * @param {string} id - * @param {UpdateSessionRequest} updateSessionRequest + * @param {string} id + * @param {UpdateSessionRequest} updateSessionRequest * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -842,3 +842,4 @@ export class SessionsApi extends BaseAPI { return SessionsApiFp(this.configuration).updateSession(id, updateSessionRequest, options).then((request) => request(this.axios, this.basePath)); } } + diff --git a/lib/packages/fabro-api-client/src/models/create-session-request.ts b/lib/packages/fabro-api-client/src/models/create-session-request.ts index 3d948d6d8..1fb3d2350 100644 --- a/lib/packages/fabro-api-client/src/models/create-session-request.ts +++ b/lib/packages/fabro-api-client/src/models/create-session-request.ts @@ -5,7 +5,7 @@ * HTTP API for managing Fabro workflow run executions. * * The version of the OpenAPI document: 0.1.0 - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech @@ -21,3 +21,4 @@ export interface CreateSessionRequest { 'model'?: string; 'permissions'?: string; } + diff --git a/lib/packages/fabro-api-client/src/models/index.ts b/lib/packages/fabro-api-client/src/models/index.ts index dda5fec58..376bfa06b 100644 --- a/lib/packages/fabro-api-client/src/models/index.ts +++ b/lib/packages/fabro-api-client/src/models/index.ts @@ -211,6 +211,7 @@ export * from './pull-request-settings'; export * from './pull-request-user'; export * from './question-type'; export * from './reasoning-effort-feature'; +export * from './related-workflow-diagnostic'; export * from './render-workflow-graph-direction'; export * from './render-workflow-graph-format'; export * from './render-workflow-graph-request'; diff --git a/lib/packages/fabro-api-client/src/models/paginated-session-event-list.ts b/lib/packages/fabro-api-client/src/models/paginated-session-event-list.ts index bba6d9b76..96a2f06ba 100644 --- a/lib/packages/fabro-api-client/src/models/paginated-session-event-list.ts +++ b/lib/packages/fabro-api-client/src/models/paginated-session-event-list.ts @@ -5,7 +5,7 @@ * HTTP API for managing Fabro workflow run executions. * * The version of the OpenAPI document: 0.1.0 - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech @@ -27,3 +27,4 @@ export interface PaginatedSessionEventList { 'data': Array; 'meta': PaginationMeta; } + diff --git a/lib/packages/fabro-api-client/src/models/paginated-session-list.ts b/lib/packages/fabro-api-client/src/models/paginated-session-list.ts index 25dc0cf9a..5ea6f39d4 100644 --- a/lib/packages/fabro-api-client/src/models/paginated-session-list.ts +++ b/lib/packages/fabro-api-client/src/models/paginated-session-list.ts @@ -5,7 +5,7 @@ * HTTP API for managing Fabro workflow run executions. * * The version of the OpenAPI document: 0.1.0 - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech @@ -27,3 +27,4 @@ export interface PaginatedSessionList { 'data': Array; 'meta': PaginationMeta; } + diff --git a/lib/packages/fabro-api-client/src/models/paginated-turn-list.ts b/lib/packages/fabro-api-client/src/models/paginated-turn-list.ts index d7b9c8c2c..05b1c8630 100644 --- a/lib/packages/fabro-api-client/src/models/paginated-turn-list.ts +++ b/lib/packages/fabro-api-client/src/models/paginated-turn-list.ts @@ -5,7 +5,7 @@ * HTTP API for managing Fabro workflow run executions. * * The version of the OpenAPI document: 0.1.0 - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech @@ -27,3 +27,4 @@ export interface PaginatedTurnList { 'data': Array; 'meta': PaginationMeta; } + diff --git a/lib/packages/fabro-api-client/src/models/related-workflow-diagnostic.ts b/lib/packages/fabro-api-client/src/models/related-workflow-diagnostic.ts new file mode 100644 index 000000000..65e3c6649 --- /dev/null +++ b/lib/packages/fabro-api-client/src/models/related-workflow-diagnostic.ts @@ -0,0 +1,23 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Fabro Run API + * HTTP API for managing Fabro workflow run executions. + * + * The version of the OpenAPI document: 0.1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +export interface RelatedWorkflowDiagnostic { + 'message': string; + 'source_path'?: string | null; + 'line'?: number | null; + 'column'?: number | null; +} + diff --git a/lib/packages/fabro-api-client/src/models/run.ts b/lib/packages/fabro-api-client/src/models/run.ts index 67d4aa233..c8d4cfb3c 100644 --- a/lib/packages/fabro-api-client/src/models/run.ts +++ b/lib/packages/fabro-api-client/src/models/run.ts @@ -65,6 +65,10 @@ export interface Run { * Current orchestration parent run ID, if linked. */ 'parent_id'?: string | null; + /** + * Number of runs currently linked to this run as their orchestration parent. + */ + 'children_count': number; 'title': string; 'goal': string; 'workflow': WorkflowRef; diff --git a/lib/packages/fabro-api-client/src/models/session-event-envelope.ts b/lib/packages/fabro-api-client/src/models/session-event-envelope.ts index 826d0e993..a4c0f9243 100644 --- a/lib/packages/fabro-api-client/src/models/session-event-envelope.ts +++ b/lib/packages/fabro-api-client/src/models/session-event-envelope.ts @@ -5,7 +5,7 @@ * HTTP API for managing Fabro workflow run executions. * * The version of the OpenAPI document: 0.1.0 - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech @@ -31,3 +31,4 @@ export interface SessionEventEnvelope { 'properties': any; 'ts': string; } + diff --git a/lib/packages/fabro-api-client/src/models/session-message.ts b/lib/packages/fabro-api-client/src/models/session-message.ts index 6ac25cf10..7544e6ca2 100644 --- a/lib/packages/fabro-api-client/src/models/session-message.ts +++ b/lib/packages/fabro-api-client/src/models/session-message.ts @@ -5,7 +5,7 @@ * HTTP API for managing Fabro workflow run executions. * * The version of the OpenAPI document: 0.1.0 - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech @@ -37,3 +37,5 @@ export const SessionMessageKindEnum = { } as const; export type SessionMessageKindEnum = typeof SessionMessageKindEnum[keyof typeof SessionMessageKindEnum]; + + diff --git a/lib/packages/fabro-api-client/src/models/session-record.ts b/lib/packages/fabro-api-client/src/models/session-record.ts index 88047587c..b5cda39a9 100644 --- a/lib/packages/fabro-api-client/src/models/session-record.ts +++ b/lib/packages/fabro-api-client/src/models/session-record.ts @@ -5,7 +5,7 @@ * HTTP API for managing Fabro workflow run executions. * * The version of the OpenAPI document: 0.1.0 - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech @@ -39,3 +39,6 @@ export interface SessionRecord { 'deleted_at'?: string | null; 'runtime_context': Array; } + + + diff --git a/lib/packages/fabro-api-client/src/models/session-status.ts b/lib/packages/fabro-api-client/src/models/session-status.ts index 0ba65e789..b2fcce960 100644 --- a/lib/packages/fabro-api-client/src/models/session-status.ts +++ b/lib/packages/fabro-api-client/src/models/session-status.ts @@ -5,7 +5,7 @@ * HTTP API for managing Fabro workflow run executions. * * The version of the OpenAPI document: 0.1.0 - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech @@ -24,3 +24,6 @@ export const SessionStatus = { } as const; export type SessionStatus = typeof SessionStatus[keyof typeof SessionStatus]; + + + diff --git a/lib/packages/fabro-api-client/src/models/session-summary.ts b/lib/packages/fabro-api-client/src/models/session-summary.ts index 1c244f817..92c0f1d15 100644 --- a/lib/packages/fabro-api-client/src/models/session-summary.ts +++ b/lib/packages/fabro-api-client/src/models/session-summary.ts @@ -5,7 +5,7 @@ * HTTP API for managing Fabro workflow run executions. * * The version of the OpenAPI document: 0.1.0 - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech @@ -33,3 +33,6 @@ export interface SessionSummary { 'created_at': string; 'updated_at': string; } + + + diff --git a/lib/packages/fabro-api-client/src/models/submit-turn-request.ts b/lib/packages/fabro-api-client/src/models/submit-turn-request.ts index ff6e824b0..ab67f7391 100644 --- a/lib/packages/fabro-api-client/src/models/submit-turn-request.ts +++ b/lib/packages/fabro-api-client/src/models/submit-turn-request.ts @@ -5,7 +5,7 @@ * HTTP API for managing Fabro workflow run executions. * * The version of the OpenAPI document: 0.1.0 - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech @@ -17,3 +17,4 @@ export interface SubmitTurnRequest { 'input': string; } + diff --git a/lib/packages/fabro-api-client/src/models/turn-record.ts b/lib/packages/fabro-api-client/src/models/turn-record.ts index 5f372c976..cf989b465 100644 --- a/lib/packages/fabro-api-client/src/models/turn-record.ts +++ b/lib/packages/fabro-api-client/src/models/turn-record.ts @@ -5,7 +5,7 @@ * HTTP API for managing Fabro workflow run executions. * * The version of the OpenAPI document: 0.1.0 - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech @@ -37,3 +37,6 @@ export interface TurnRecord { 'updated_at': string; 'completed_at'?: string | null; } + + + diff --git a/lib/packages/fabro-api-client/src/models/turn-status.ts b/lib/packages/fabro-api-client/src/models/turn-status.ts index d87205d45..b2e2cc894 100644 --- a/lib/packages/fabro-api-client/src/models/turn-status.ts +++ b/lib/packages/fabro-api-client/src/models/turn-status.ts @@ -5,7 +5,7 @@ * HTTP API for managing Fabro workflow run executions. * * The version of the OpenAPI document: 0.1.0 - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech @@ -23,3 +23,6 @@ export const TurnStatus = { } as const; export type TurnStatus = typeof TurnStatus[keyof typeof TurnStatus]; + + + diff --git a/lib/packages/fabro-api-client/src/models/update-session-request.ts b/lib/packages/fabro-api-client/src/models/update-session-request.ts index bab220b1a..d1b0bd395 100644 --- a/lib/packages/fabro-api-client/src/models/update-session-request.ts +++ b/lib/packages/fabro-api-client/src/models/update-session-request.ts @@ -5,7 +5,7 @@ * HTTP API for managing Fabro workflow run executions. * * The version of the OpenAPI document: 0.1.0 - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech @@ -17,3 +17,4 @@ export interface UpdateSessionRequest { 'title'?: string; } + diff --git a/lib/packages/fabro-api-client/src/models/workflow-diagnostic.ts b/lib/packages/fabro-api-client/src/models/workflow-diagnostic.ts index e38743e24..19ad20750 100644 --- a/lib/packages/fabro-api-client/src/models/workflow-diagnostic.ts +++ b/lib/packages/fabro-api-client/src/models/workflow-diagnostic.ts @@ -13,6 +13,9 @@ */ +// May contain unused imports in some cases +// @ts-ignore +import type { RelatedWorkflowDiagnostic } from './related-workflow-diagnostic'; export interface WorkflowDiagnostic { 'rule': string; @@ -21,6 +24,12 @@ export interface WorkflowDiagnostic { 'node_id'?: string | null; 'edge'?: Array | null; 'fix'?: string | null; + 'source_path'?: string | null; + 'line'?: number | null; + 'column'?: number | null; + 'span_start'?: number | null; + 'span_len'?: number | null; + 'related'?: Array; } export const WorkflowDiagnosticSeverityEnum = {