fix(api): convert OpenAPI spec to valid 3.1 syntax

The spec declared openapi 3.1.0 but used nullable: true (3.0 idiom)
in 78 places, which Mintlify's parser rejected, breaking doc deploys.

Convert to proper 3.1 patterns (type arrays and oneOf with type: null),
switch the server conformance test from openapiv3 (3.0-only) to a
YAML-level walk so it accepts 3.1 input, and regenerate the typescript
client — it now correctly emits `| null` on nullable fields.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-04-18 01:11:19 -04:00
parent 828d686a6f
commit 2f2f14562d
No known key found for this signature in database
32 changed files with 181 additions and 257 deletions

1
Cargo.lock generated
View file

@ -1955,7 +1955,6 @@ dependencies = [
"mime_guess",
"multer",
"object_store",
"openapiv3",
"rand 0.9.2",
"regex",
"rustls",

View file

@ -1735,9 +1735,8 @@ components:
description: Maximum context window size in tokens.
example: 1000000
max_output:
type: integer
type: ["integer", "null"]
format: int64
nullable: true
description: Maximum output tokens, if known.
example: 128000
@ -1764,21 +1763,18 @@ components:
type: object
properties:
input_cost_per_mtok:
type: number
type: ["number", "null"]
format: double
nullable: true
description: Cost per million input tokens in USD.
example: 15.0
output_cost_per_mtok:
type: number
type: ["number", "null"]
format: double
nullable: true
description: Cost per million output tokens in USD.
example: 75.0
cache_input_cost_per_mtok:
type: number
type: ["number", "null"]
format: double
nullable: true
description: Cost per million cached input tokens in USD.
example: 1.50
@ -1815,8 +1811,7 @@ components:
limits:
$ref: "#/components/schemas/ModelLimits"
training:
type: string
nullable: true
type: ["string", "null"]
description: Training data cutoff date (YYYY-MM-DD).
example: "2025-08-01"
features:
@ -1824,9 +1819,8 @@ components:
costs:
$ref: "#/components/schemas/ModelCosts"
estimated_output_tps:
type: number
type: ["number", "null"]
format: double
nullable: true
description: Estimated output tokens per second.
aliases:
type: array
@ -1857,8 +1851,7 @@ components:
- skip
description: Whether the model responded successfully, failed, or was skipped because its provider is not configured.
error_message:
type: string
nullable: true
type: ["string", "null"]
description: Error details when status is "error".
ModelTestMode:
@ -2108,8 +2101,7 @@ components:
description: Manifest schema version.
example: 1
run_id:
type: string
nullable: true
type: ["string", "null"]
description: Optional pre-generated run ID to use instead of allocating a new ULID.
example: "01HV6D7S5YF4Z4B2M7K4N0Q6T9"
cwd:
@ -2175,8 +2167,7 @@ components:
type: string
description: Resolved goal content.
path:
type: string
nullable: true
type: ["string", "null"]
description: Original goal file path when the goal came from a file.
ManifestArgs:
@ -2230,11 +2221,9 @@ components:
- project
- user
path:
type: string
nullable: true
type: ["string", "null"]
source:
type: string
nullable: true
type: ["string", "null"]
ManifestWorkflowConfig:
type: object
@ -2274,8 +2263,7 @@ components:
original:
type: string
from:
type: string
nullable: true
type: ["string", "null"]
ManifestWorkflow:
type: object
@ -2341,8 +2329,7 @@ components:
name:
type: string
graph_path:
type: string
nullable: true
type: ["string", "null"]
nodes:
type: integer
edges:
@ -2372,18 +2359,15 @@ components:
message:
type: string
node_id:
type: string
nullable: true
type: ["string", "null"]
edge:
type: array
nullable: true
type: ["array", "null"]
minItems: 2
maxItems: 2
items:
type: string
fix:
type: string
nullable: true
type: ["string", "null"]
PreflightCheckReport:
type: object
@ -2434,8 +2418,7 @@ components:
items:
$ref: "#/components/schemas/PreflightCheckDetail"
remediation:
type: string
nullable: true
type: ["string", "null"]
PreflightCheckDetail:
type: object
@ -2478,13 +2461,13 @@ components:
description: Position in the queue (1-based). Only present when status is `queued`.
example: 3
status_reason:
allOf:
oneOf:
- $ref: "#/components/schemas/StatusReason"
nullable: true
- type: "null"
pending_control:
allOf:
oneOf:
- $ref: "#/components/schemas/RunControlAction"
nullable: true
- type: "null"
created_at:
type: string
format: date-time
@ -2542,14 +2525,12 @@ components:
description: Whether the user may provide freeform text in addition to selecting options.
example: true
timeout_seconds:
type: number
type: ["number", "null"]
format: double
nullable: true
description: Timeout for the question when configured by the workflow.
example: 30
context_display:
type: string
nullable: true
type: ["string", "null"]
description: Optional contextual text shown alongside the question.
example: Latest draft
@ -2662,44 +2643,36 @@ components:
run_id:
type: string
node_id:
type: string
nullable: true
type: ["string", "null"]
node_label:
type: string
nullable: true
type: ["string", "null"]
stage_id:
type: string
nullable: true
type: ["string", "null"]
description: Stage execution identity, formatted as "{node_id}@{visit}".
parallel_group_id:
type: string
nullable: true
type: ["string", "null"]
description: >
Durable identity of one execution of a parallel node, formatted as
"{node_id}@{visit}".
parallel_branch_id:
type: string
nullable: true
type: ["string", "null"]
description: >
Durable identity of one branch within a parallel execution,
formatted as "{parallel_group_id}:{index}".
session_id:
type: string
nullable: true
type: ["string", "null"]
parent_session_id:
type: string
nullable: true
type: ["string", "null"]
tool_call_id:
type: string
nullable: true
type: ["string", "null"]
description: >
Stable identifier for a tool call, present on agent.tool.* events
and other durable events that directly describe the same tool
call.
actor:
allOf:
oneOf:
- $ref: "#/components/schemas/ActorRef"
nullable: true
- type: "null"
event:
type: string
description: Event type discriminator.
@ -2803,20 +2776,17 @@ components:
description: Relative artifact path to store.
example: src/lib.rs
sha256:
type: string
nullable: true
type: ["string", "null"]
description: Optional lowercase hex SHA-256 checksum for the file contents.
example: 3f785df4c5b7d3f1f4c1f0ecb0f55f1d9f6f6a3d9f0a8a98f7a74f29d1f81a2c
expected_bytes:
type: integer
type: ["integer", "null"]
format: int64
nullable: true
minimum: 0
description: Optional exact byte length expected for the file part.
example: 1234
content_type:
type: string
nullable: true
type: ["string", "null"]
description: Optional client-supplied content type for the file part.
example: text/plain
@ -2945,11 +2915,9 @@ components:
status:
$ref: "#/components/schemas/InternalStageStatus"
notes:
type: string
nullable: true
type: ["string", "null"]
failure_reason:
type: string
nullable: true
type: ["string", "null"]
timestamp:
type: string
format: date-time
@ -2959,32 +2927,23 @@ components:
type: object
properties:
prompt:
type: string
nullable: true
type: ["string", "null"]
response:
type: string
nullable: true
type: ["string", "null"]
status:
oneOf:
- $ref: "#/components/schemas/NodeStatusRecord"
- type: "null"
provider_used:
nullable: true
provider_used: {}
diff:
type: string
nullable: true
script_invocation:
nullable: true
script_timing:
nullable: true
parallel_results:
nullable: true
type: ["string", "null"]
script_invocation: {}
script_timing: {}
parallel_results: {}
stdout:
type: string
nullable: true
type: ["string", "null"]
stderr:
type: string
nullable: true
type: ["string", "null"]
RunProjection:
description: Raw internal run projection derived from the event log.
@ -2993,16 +2952,13 @@ components:
- nodes
properties:
run:
type: object
type: ["object", "null"]
additionalProperties: true
nullable: true
graph_source:
type: string
nullable: true
type: ["string", "null"]
start:
type: object
type: ["object", "null"]
additionalProperties: true
nullable: true
status:
oneOf:
- $ref: "#/components/schemas/RunStatusRecord"
@ -3023,30 +2979,23 @@ components:
- type: integer
- $ref: "#/components/schemas/RunCheckpoint"
conclusion:
type: object
type: ["object", "null"]
additionalProperties: true
nullable: true
retro:
type: object
type: ["object", "null"]
additionalProperties: true
nullable: true
retro_prompt:
type: string
nullable: true
type: ["string", "null"]
retro_response:
type: string
nullable: true
type: ["string", "null"]
sandbox:
type: object
type: ["object", "null"]
additionalProperties: true
nullable: true
final_patch:
type: string
nullable: true
type: ["string", "null"]
pull_request:
type: object
type: ["object", "null"]
additionalProperties: true
nullable: true
nodes:
type: object
description: Map from StageId (`node_id@visit`) to NodeState.
@ -3063,44 +3012,35 @@ components:
run_id:
type: string
workflow_name:
type: string
nullable: true
type: ["string", "null"]
workflow_slug:
type: string
nullable: true
type: ["string", "null"]
goal:
type: string
nullable: true
type: ["string", "null"]
labels:
type: object
additionalProperties:
type: string
host_repo_path:
type: string
nullable: true
type: ["string", "null"]
start_time:
type: string
type: ["string", "null"]
format: date-time
nullable: true
status:
type: string
nullable: true
type: ["string", "null"]
status_reason:
type: string
nullable: true
type: ["string", "null"]
pending_control:
allOf:
oneOf:
- $ref: "#/components/schemas/RunControlAction"
nullable: true
- type: "null"
duration_ms:
type: integer
type: ["integer", "null"]
format: int64
minimum: 0
nullable: true
total_usd_micros:
type: integer
type: ["integer", "null"]
format: int64
nullable: true
# ── Run Board Schemas ────────────────────────────────────────────────
@ -3225,9 +3165,8 @@ components:
description: Number of cache write tokens.
example: 1500
total_usd_micros:
type: integer
type: ["integer", "null"]
format: int64
nullable: true
description: Billed USD amount in micros.
example: 720000
@ -3379,9 +3318,8 @@ components:
description: Total cache write tokens.
example: 9200
total_usd_micros:
type: integer
type: ["integer", "null"]
format: int64
nullable: true
description: Total billed USD amount in micros.
example: 20340000
runtime_secs:
@ -3768,9 +3706,8 @@ components:
description: Total cache write tokens.
example: 4500
total_usd_micros:
type: integer
type: ["integer", "null"]
format: int64
nullable: true
description: Total billed USD amount in micros.
example: 2260000
@ -4086,12 +4023,10 @@ components:
type: string
description: Server version string.
git_sha:
type: string
nullable: true
type: ["string", "null"]
description: Build git SHA when available.
build_date:
type: string
nullable: true
type: ["string", "null"]
description: Build date when available.
os:
type: string
@ -4158,8 +4093,7 @@ components:
format: int64
description: Total bytes reclaimable by deleting inactive runs and logs.
runs:
type: array
nullable: true
type: ["array", "null"]
description: Per-run usage rows when verbose output is requested.
items:
$ref: "#/components/schemas/DiskUsageRunRow"
@ -4176,18 +4110,16 @@ components:
format: int64
description: Number of items in the category.
active:
type: integer
type: ["integer", "null"]
format: int64
nullable: true
description: Number of active items when applicable.
size_bytes:
type: integer
format: int64
description: Total bytes used by the category.
reclaimable_bytes:
type: integer
type: ["integer", "null"]
format: int64
nullable: true
description: Bytes reclaimable by pruning the category.
DiskUsageRunRow:
@ -4249,8 +4181,7 @@ components:
type: boolean
description: Whether this response is a dry-run preview.
runs:
type: array
nullable: true
type: ["array", "null"]
description: Matched runs when dry-run is enabled.
items:
$ref: "#/components/schemas/PruneRunEntry"
@ -4428,17 +4359,14 @@ components:
type: boolean
description: Whether the server has read-write access to this repository.
default_branch:
type: string
nullable: true
type: ["string", "null"]
description: Default branch name, if accessible.
example: main
private:
type: boolean
nullable: true
type: ["boolean", "null"]
description: Whether the repository is private, if accessible.
permissions:
type: object
nullable: true
type: ["object", "null"]
description: Detected permission levels.
properties:
pull:
@ -4448,8 +4376,7 @@ components:
admin:
type: boolean
install_url:
type: string
nullable: true
type: ["string", "null"]
description: GitHub App installation URL when the repo is not yet accessible.
DiagnosticsReport:
@ -4502,8 +4429,7 @@ components:
items:
$ref: "#/components/schemas/DiagnosticsDetail"
remediation:
type: string
nullable: true
type: ["string", "null"]
DiagnosticsDetail:
type: object

View file

@ -87,6 +87,5 @@ tokio = { workspace = true, features = ["test-util", "macros"] }
tower = "0.5"
http-body-util = "0.1"
httpmock = "0.8"
openapiv3 = "2"
serde_yaml = "0.9"
fabro-sandbox = { path = "../fabro-sandbox" }

View file

@ -11,11 +11,12 @@ use axum::body::Body;
use axum::http::{Method, Request, StatusCode};
use fabro_server::jwt_auth::AuthMode;
use fabro_server::server::build_router;
use serde_yaml::Value;
use tower::ServiceExt;
use super::helpers::test_app_state;
fn load_spec() -> openapiv3::OpenAPI {
fn load_spec() -> Value {
let spec_path = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.parent()
.unwrap()
@ -36,24 +37,22 @@ fn resolve_path(path: &str) -> String {
.replace("{slug}", "test-slug")
}
fn methods_for_path_item(item: &openapiv3::PathItem) -> Vec<Method> {
let mut methods = Vec::new();
if item.get.is_some() {
methods.push(Method::GET);
}
if item.post.is_some() {
methods.push(Method::POST);
}
if item.put.is_some() {
methods.push(Method::PUT);
}
if item.delete.is_some() {
methods.push(Method::DELETE);
}
if item.patch.is_some() {
methods.push(Method::PATCH);
}
methods
fn methods_for_path_item(item: &Value) -> Vec<Method> {
const HTTP_METHODS: &[(&str, Method)] = &[
("get", Method::GET),
("post", Method::POST),
("put", Method::PUT),
("delete", Method::DELETE),
("patch", Method::PATCH),
];
let Some(map) = item.as_mapping() else {
return Vec::new();
};
HTTP_METHODS
.iter()
.filter(|(key, _)| map.contains_key(Value::String((*key).to_string())))
.map(|(_, method)| method.clone())
.collect()
}
#[tokio::test]
@ -62,15 +61,16 @@ async fn all_spec_routes_are_routable() {
let state = test_app_state();
let app = build_router(state, AuthMode::Disabled);
let mut checked = 0;
for (path, item) in &spec.paths.paths {
let path_item = match item {
openapiv3::ReferenceOr::Item(item) => item,
openapiv3::ReferenceOr::Reference { .. } => continue,
};
let paths = spec
.get("paths")
.and_then(Value::as_mapping)
.expect("spec is missing `paths`");
let mut checked = 0;
for (path_key, item) in paths {
let path = path_key.as_str().expect("path key must be a string");
let uri = resolve_path(path);
for method in methods_for_path_item(path_item) {
for method in methods_for_path_item(item) {
let mut builder = Request::builder().method(&method).uri(&uri);
let body = if method == Method::POST {

View file

@ -49,7 +49,7 @@ export interface AggregateBillingTotals {
/**
* Total billed USD amount in micros.
*/
'total_usd_micros'?: number;
'total_usd_micros'?: number | null;
/**
* Total runtime in seconds.
*/

View file

@ -48,11 +48,11 @@ export interface ApiQuestion {
/**
* Timeout for the question when configured by the workflow.
*/
'timeout_seconds'?: number;
'timeout_seconds'?: number | null;
/**
* Optional contextual text shown alongside the question.
*/
'context_display'?: string;
'context_display'?: string | null;
}

View file

@ -29,14 +29,14 @@ export interface ArtifactBatchUploadEntry {
/**
* Optional lowercase hex SHA-256 checksum for the file contents.
*/
'sha256'?: string;
'sha256'?: string | null;
/**
* Optional exact byte length expected for the file part.
*/
'expected_bytes'?: number;
'expected_bytes'?: number | null;
/**
* Optional client-supplied content type for the file part.
*/
'content_type'?: string;
'content_type'?: string | null;
}

View file

@ -45,6 +45,6 @@ export interface BilledTokenCounts {
/**
* Billed USD amount in micros.
*/
'total_usd_micros'?: number;
'total_usd_micros'?: number | null;
}

View file

@ -22,7 +22,7 @@ export interface DiagnosticsCheck {
'status': DiagnosticsCheckStatusEnum;
'summary': string;
'details'?: Array<DiagnosticsDetail>;
'remediation'?: string;
'remediation'?: string | null;
}
export const DiagnosticsCheckStatusEnum = {

View file

@ -36,6 +36,6 @@ export interface DiskUsageResponse {
/**
* Per-run usage rows when verbose output is requested.
*/
'runs'?: Array<DiskUsageRunRow>;
'runs'?: Array<DiskUsageRunRow> | null;
}

View file

@ -29,7 +29,7 @@ export interface DiskUsageSummaryRow {
/**
* Number of active items when applicable.
*/
'active'?: number;
'active'?: number | null;
/**
* Total bytes used by the category.
*/
@ -37,6 +37,6 @@ export interface DiskUsageSummaryRow {
/**
* Bytes reclaimable by pruning the category.
*/
'reclaimable_bytes'?: number;
'reclaimable_bytes'?: number | null;
}

View file

@ -16,8 +16,8 @@
export interface ManifestConfig {
'type': ManifestConfigTypeEnum;
'path'?: string;
'source'?: string;
'path'?: string | null;
'source'?: string | null;
}
export const ManifestConfigTypeEnum = {

View file

@ -17,7 +17,7 @@
export interface ManifestFileRef {
'type': ManifestFileRefTypeEnum;
'original': string;
'from'?: string;
'from'?: string | null;
}
export const ManifestFileRefTypeEnum = {

View file

@ -26,7 +26,7 @@ export interface ManifestGoal {
/**
* Original goal file path when the goal came from a file.
*/
'path'?: string;
'path'?: string | null;
}
export const ManifestGoalTypeEnum = {

View file

@ -21,14 +21,14 @@ export interface ModelCosts {
/**
* Cost per million input tokens in USD.
*/
'input_cost_per_mtok'?: number;
'input_cost_per_mtok'?: number | null;
/**
* Cost per million output tokens in USD.
*/
'output_cost_per_mtok'?: number;
'output_cost_per_mtok'?: number | null;
/**
* Cost per million cached input tokens in USD.
*/
'cache_input_cost_per_mtok'?: number;
'cache_input_cost_per_mtok'?: number | null;
}

View file

@ -25,6 +25,6 @@ export interface ModelLimits {
/**
* Maximum output tokens, if known.
*/
'max_output'?: number;
'max_output'?: number | null;
}

View file

@ -29,7 +29,7 @@ export interface ModelTestResult {
/**
* Error details when status is \"error\".
*/
'error_message'?: string;
'error_message'?: string | null;
}
export const ModelTestResultStatusEnum = {

View file

@ -47,13 +47,13 @@ export interface Model {
/**
* Training data cutoff date (YYYY-MM-DD).
*/
'training'?: string;
'training'?: string | null;
'features': ModelFeatures;
'costs': ModelCosts;
/**
* Estimated output tokens per second.
*/
'estimated_output_tps'?: number;
'estimated_output_tps'?: number | null;
/**
* Alternative names that resolve to this model.
*/

View file

@ -21,15 +21,15 @@ import type { NodeStatusRecord } from './node-status-record';
* Internal node projection state.
*/
export interface NodeState {
'prompt'?: string;
'response'?: string;
'prompt'?: string | null;
'response'?: string | null;
'status'?: NodeStatusRecord | null;
'provider_used'?: any;
'diff'?: string;
'diff'?: string | null;
'script_invocation'?: any;
'script_timing'?: any;
'parallel_results'?: any;
'stdout'?: string;
'stderr'?: string;
'stdout'?: string | null;
'stderr'?: string | null;
}

View file

@ -22,8 +22,8 @@ import type { InternalStageStatus } from './internal-stage-status';
*/
export interface NodeStatusRecord {
'status': InternalStageStatus;
'notes'?: string;
'failure_reason'?: string;
'notes'?: string | null;
'failure_reason'?: string | null;
'timestamp': string;
}

View file

@ -22,7 +22,7 @@ export interface PreflightCheckResult {
'status': PreflightCheckResultStatusEnum;
'summary': string;
'details': Array<PreflightCheckDetail>;
'remediation'?: string;
'remediation'?: string | null;
}
export const PreflightCheckResultStatusEnum = {

View file

@ -19,7 +19,7 @@ import type { WorkflowDiagnostic } from './workflow-diagnostic';
export interface PreflightWorkflowSummary {
'name': string;
'graph_path'?: string;
'graph_path'?: string | null;
'nodes': number;
'edges': number;
'goal': string;

View file

@ -28,7 +28,7 @@ export interface PruneRunsResponse {
/**
* Matched runs when dry-run is enabled.
*/
'runs'?: Array<PruneRunEntry>;
'runs'?: Array<PruneRunEntry> | null;
/**
* Count of runs matching the prune filters.
*/

View file

@ -36,15 +36,15 @@ export interface RepoCheckResponse {
/**
* Default branch name, if accessible.
*/
'default_branch'?: string;
'default_branch'?: string | null;
/**
* Whether the repository is private, if accessible.
*/
'private'?: boolean;
'private'?: boolean | null;
'permissions'?: RepoCheckResponsePermissions;
/**
* GitHub App installation URL when the repo is not yet accessible.
*/
'install_url'?: string;
'install_url'?: string | null;
}

View file

@ -49,6 +49,6 @@ export interface RunBillingTotals {
/**
* Total billed USD amount in micros.
*/
'total_usd_micros'?: number;
'total_usd_micros'?: number | null;
}

View file

@ -26,27 +26,27 @@ export interface RunEvent {
'id': string;
'ts': string;
'run_id': string;
'node_id'?: string;
'node_label'?: string;
'node_id'?: string | null;
'node_label'?: string | null;
/**
* Stage execution identity, formatted as \"{node_id}@{visit}\".
*/
'stage_id'?: string;
'stage_id'?: string | null;
/**
* Durable identity of one execution of a parallel node, formatted as \"{node_id}@{visit}\".
*/
'parallel_group_id'?: string;
'parallel_group_id'?: string | null;
/**
* Durable identity of one branch within a parallel execution, formatted as \"{parallel_group_id}:{index}\".
*/
'parallel_branch_id'?: string;
'session_id'?: string;
'parent_session_id'?: string;
'parallel_branch_id'?: string | null;
'session_id'?: string | null;
'parent_session_id'?: string | null;
/**
* Stable identifier for a tool call, present on agent.tool.* events and other durable events that directly describe the same tool call.
*/
'tool_call_id'?: string;
'actor'?: ActorRef;
'tool_call_id'?: string | null;
'actor'?: ActorRef | null;
/**
* Event type discriminator.
*/

View file

@ -43,7 +43,7 @@ export interface RunManifest {
/**
* Optional pre-generated run ID to use instead of allocating a new ULID.
*/
'run_id'?: string;
'run_id'?: string | null;
/**
* CLI working directory at invocation time.
*/

View file

@ -30,22 +30,22 @@ import type { RunStatusRecord } from './run-status-record';
* Raw internal run projection derived from the event log.
*/
export interface RunProjection {
'run'?: { [key: string]: any; };
'graph_source'?: string;
'start'?: { [key: string]: any; };
'run'?: { [key: string]: any; } | null;
'graph_source'?: string | null;
'start'?: { [key: string]: any; } | null;
'status'?: RunStatusRecord | null;
'checkpoint'?: RunCheckpoint | null;
/**
* Sequence-tagged checkpoint history entries as `[seq, checkpoint]`.
*/
'checkpoints'?: Array<Array<RunProjectionCheckpointsInnerInner>>;
'conclusion'?: { [key: string]: any; };
'retro'?: { [key: string]: any; };
'retro_prompt'?: string;
'retro_response'?: string;
'sandbox'?: { [key: string]: any; };
'final_patch'?: string;
'pull_request'?: { [key: string]: any; };
'conclusion'?: { [key: string]: any; } | null;
'retro'?: { [key: string]: any; } | null;
'retro_prompt'?: string | null;
'retro_response'?: string | null;
'sandbox'?: { [key: string]: any; } | null;
'final_patch'?: string | null;
'pull_request'?: { [key: string]: any; } | null;
/**
* Map from StageId (`node_id@visit`) to NodeState.
*/

View file

@ -40,8 +40,8 @@ export interface RunStatusResponse {
* Position in the queue (1-based). Only present when status is `queued`.
*/
'queue_position'?: number;
'status_reason'?: StatusReason;
'pending_control'?: RunControlAction;
'status_reason'?: StatusReason | null;
'pending_control'?: RunControlAction | null;
/**
* Timestamp when the run was created.
*/

View file

@ -22,17 +22,17 @@ import type { RunControlAction } from './run-control-action';
*/
export interface StoreRunSummary {
'run_id': string;
'workflow_name'?: string;
'workflow_slug'?: string;
'goal'?: string;
'workflow_name'?: string | null;
'workflow_slug'?: string | null;
'goal'?: string | null;
'labels': { [key: string]: string; };
'host_repo_path'?: string;
'start_time'?: string;
'status'?: string;
'status_reason'?: string;
'pending_control'?: RunControlAction;
'duration_ms'?: number;
'total_usd_micros'?: number;
'host_repo_path'?: string | null;
'start_time'?: string | null;
'status'?: string | null;
'status_reason'?: string | null;
'pending_control'?: RunControlAction | null;
'duration_ms'?: number | null;
'total_usd_micros'?: number | null;
}

View file

@ -31,11 +31,11 @@ export interface SystemInfoResponse {
/**
* Build git SHA when available.
*/
'git_sha'?: string;
'git_sha'?: string | null;
/**
* Build date when available.
*/
'build_date'?: string;
'build_date'?: string | null;
/**
* Target operating system.
*/

View file

@ -18,9 +18,9 @@ export interface WorkflowDiagnostic {
'rule': string;
'severity': WorkflowDiagnosticSeverityEnum;
'message': string;
'node_id'?: string;
'edge'?: Array<string>;
'fix'?: string;
'node_id'?: string | null;
'edge'?: Array<string> | null;
'fix'?: string | null;
}
export const WorkflowDiagnosticSeverityEnum = {