mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-08-28 05:27:41 +00:00
762 lines
28 KiB
Rust
762 lines
28 KiB
Rust
#![expect(
|
|
clippy::disallowed_methods,
|
|
reason = "build script: runs at compile time outside any runtime"
|
|
)]
|
|
|
|
use std::path::{Path, PathBuf};
|
|
use std::{env, fs};
|
|
|
|
use progenitor::{GenerationSettings, Generator, InterfaceStyle, TypeImpl};
|
|
|
|
/// Recursively convert OpenAPI 3.1 `type: "null"` patterns to 3.0 `nullable:
|
|
/// true`.
|
|
///
|
|
/// Handles two patterns:
|
|
/// - `oneOf: [{...}, {type: "null"}]` → the non-null schema with `nullable:
|
|
/// true`
|
|
/// - `type: [T1, ..., "null"]` → the remaining types with `nullable: true`
|
|
fn patch_nullable(value: &mut serde_json::Value) {
|
|
match value {
|
|
serde_json::Value::Object(map) => {
|
|
// Pattern: oneOf with a {type: "null"} variant
|
|
if let Some(one_of) = map.get_mut("oneOf") {
|
|
if let Some(variants) = one_of.as_array_mut() {
|
|
let null_idx = variants.iter().position(|v| {
|
|
v.get("type").and_then(serde_json::Value::as_str) == Some("null")
|
|
});
|
|
if let Some(idx) = null_idx {
|
|
variants.remove(idx);
|
|
if variants.len() == 1 {
|
|
// Collapse single-variant oneOf into the schema itself
|
|
let mut inner = variants.remove(0);
|
|
if inner.get("$ref").is_some() {
|
|
inner = serde_json::json!({
|
|
"allOf": [inner],
|
|
"nullable": true,
|
|
});
|
|
} else {
|
|
inner
|
|
.as_object_mut()
|
|
.expect("oneOf collapse should leave an object schema")
|
|
.insert("nullable".to_string(), serde_json::Value::Bool(true));
|
|
}
|
|
patch_nullable(&mut inner);
|
|
*value = inner;
|
|
return;
|
|
}
|
|
map.insert("nullable".to_string(), serde_json::Value::Bool(true));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Pattern: type array containing "null"
|
|
let needs_nullable_from_type = map
|
|
.get("type")
|
|
.and_then(|v| v.as_array())
|
|
.is_some_and(|arr| arr.iter().any(|v| v.as_str() == Some("null")));
|
|
if needs_nullable_from_type {
|
|
if let Some(type_val) = map.get_mut("type") {
|
|
if let Some(arr) = type_val.as_array_mut() {
|
|
arr.retain(|v| v.as_str() != Some("null"));
|
|
if arr.len() == 1 {
|
|
*type_val = arr.remove(0);
|
|
}
|
|
}
|
|
}
|
|
map.insert("nullable".to_string(), serde_json::Value::Bool(true));
|
|
}
|
|
|
|
for v in map.values_mut() {
|
|
patch_nullable(v);
|
|
}
|
|
}
|
|
serde_json::Value::Array(arr) => {
|
|
for v in arr {
|
|
patch_nullable(v);
|
|
}
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
|
|
/// Progenitor currently panics when an operation advertises more than one
|
|
/// request-body media type.
|
|
///
|
|
/// Keep the source OpenAPI spec accurate for docs, but collapse the
|
|
/// generated-client view down to a single preferred media type so code
|
|
/// generation can proceed.
|
|
fn patch_codegen_request_body_media_types(value: &mut serde_json::Value) {
|
|
let Some(paths) = value
|
|
.get_mut("paths")
|
|
.and_then(serde_json::Value::as_object_mut)
|
|
else {
|
|
return;
|
|
};
|
|
|
|
for path_item in paths.values_mut() {
|
|
let Some(item) = path_item.as_object_mut() else {
|
|
continue;
|
|
};
|
|
|
|
for method in ["get", "put", "post", "delete", "patch"] {
|
|
let Some(operation) = item
|
|
.get_mut(method)
|
|
.and_then(serde_json::Value::as_object_mut)
|
|
else {
|
|
continue;
|
|
};
|
|
let Some(content) = operation
|
|
.get_mut("requestBody")
|
|
.and_then(|request_body| request_body.get_mut("content"))
|
|
.and_then(serde_json::Value::as_object_mut)
|
|
else {
|
|
continue;
|
|
};
|
|
if content.len() <= 1 {
|
|
continue;
|
|
}
|
|
|
|
let preferred = content
|
|
.get("application/octet-stream")
|
|
.cloned()
|
|
.map(|value| ("application/octet-stream".to_string(), value))
|
|
.or_else(|| {
|
|
content
|
|
.iter()
|
|
.next()
|
|
.map(|(key, value)| (key.clone(), value.clone()))
|
|
});
|
|
if let Some((key, value)) = preferred {
|
|
content.clear();
|
|
content.insert(key, value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Progenitor currently panics when an operation advertises a typed success
|
|
/// response alongside a no-content success response. Keep the source spec
|
|
/// accurate for docs and other generators, but preserve the existing Rust
|
|
/// client shape for `DELETE /runs/{id}`: success with no body.
|
|
fn patch_codegen_delete_run_responses(value: &mut serde_json::Value) {
|
|
let Some(responses) = value
|
|
.get_mut("paths")
|
|
.and_then(|paths| paths.get_mut("/api/v1/runs/{id}"))
|
|
.and_then(|path| path.get_mut("delete"))
|
|
.and_then(|operation| operation.get_mut("responses"))
|
|
.and_then(serde_json::Value::as_object_mut)
|
|
else {
|
|
return;
|
|
};
|
|
responses.remove("200");
|
|
}
|
|
|
|
fn spec_path_from_manifest_dir(manifest_dir: &Path) -> PathBuf {
|
|
manifest_dir
|
|
.ancestors()
|
|
.nth(3)
|
|
.expect("fabro-api manifest dir should be nested under <repo>/lib/foundation/fabro-api")
|
|
.join("docs/public/api-reference/fabro-api.yaml")
|
|
}
|
|
|
|
fn main() {
|
|
let manifest_dir = env::var_os("CARGO_MANIFEST_DIR")
|
|
.map(PathBuf::from)
|
|
.expect("CARGO_MANIFEST_DIR should be set for build scripts");
|
|
let spec_path = spec_path_from_manifest_dir(&manifest_dir);
|
|
|
|
println!("cargo::rerun-if-changed={}", spec_path.display());
|
|
|
|
let spec_text = fs::read_to_string(&spec_path)
|
|
.unwrap_or_else(|e| panic!("failed to read {}: {e}", spec_path.display()));
|
|
let mut spec_value: serde_json::Value =
|
|
serde_yaml::from_str(&spec_text).unwrap_or_else(|e| panic!("failed to parse YAML: {e}"));
|
|
|
|
// TODO: Remove 3.1→3.0 patch when progenitor supports OpenAPI 3.1.
|
|
// Progenitor only supports OpenAPI 3.0.x; our spec uses 3.1.0 but doesn't
|
|
// rely on any 3.1-only features that affect codegen.
|
|
spec_value["openapi"] = serde_json::Value::String("3.0.3".to_string());
|
|
patch_nullable(&mut spec_value);
|
|
patch_codegen_request_body_media_types(&mut spec_value);
|
|
patch_codegen_delete_run_responses(&mut spec_value);
|
|
|
|
let spec: openapiv3::OpenAPI =
|
|
serde_json::from_value(spec_value).expect("failed to deserialize OpenAPI spec");
|
|
|
|
let mut settings = GenerationSettings::default();
|
|
settings.with_interface(InterfaceStyle::Builder);
|
|
let replacements: &[(&str, &str, &[TypeImpl])] = &[
|
|
("RunStatus", "fabro_types::status::RunStatus", &[]),
|
|
("PendingReason", "fabro_types::status::PendingReason", &[]),
|
|
("SuccessReason", "fabro_types::status::SuccessReason", &[]),
|
|
("FailureReason", "fabro_types::status::FailureReason", &[]),
|
|
("FailureCategory", "fabro_types::FailureCategory", &[]),
|
|
("FailureSignature", "fabro_types::FailureSignature", &[]),
|
|
("FailureDetail", "fabro_types::FailureDetail", &[]),
|
|
("RunFailure", "fabro_types::RunFailure", &[]),
|
|
("BlockedReason", "fabro_types::status::BlockedReason", &[]),
|
|
(
|
|
"RunControlAction",
|
|
"fabro_types::status::RunControlAction",
|
|
&[],
|
|
),
|
|
("Run", "fabro_types::Run", &[]),
|
|
("RunApproval", "fabro_types::RunApproval", &[]),
|
|
("RunApprovalState", "fabro_types::RunApprovalState", &[]),
|
|
("RunRunnableSource", "fabro_types::RunRunnableSource", &[]),
|
|
("RunSize", "fabro_types::RunSize", &[]),
|
|
("DiffSummary", "fabro_types::DiffSummary", &[]),
|
|
("RepositoryRef", "fabro_types::RepositoryRef", &[]),
|
|
("WorkflowSettings", "fabro_types::WorkflowSettings", &[]),
|
|
// Run-level GitHub integration settings reuse the canonical resolved
|
|
// types instead of generating parallel API DTOs; the wire shape is
|
|
// identical (InterpString serializes as its source string).
|
|
(
|
|
"RunIntegrationsSettings",
|
|
"fabro_types::settings::run::RunIntegrationsSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"RunIntegrationsGithubSettings",
|
|
"fabro_types::settings::run::RunIntegrationsGithubSettings",
|
|
&[],
|
|
),
|
|
("ServerSettings", "fabro_types::ServerSettings", &[]),
|
|
(
|
|
"ServerNamespace",
|
|
"fabro_types::settings::ServerNamespace",
|
|
&[],
|
|
),
|
|
(
|
|
"ServerListenSettings",
|
|
"fabro_types::settings::server::ServerListenSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"ServerApiSettings",
|
|
"fabro_types::settings::server::ServerApiSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"ServerWebSettings",
|
|
"fabro_types::settings::server::ServerWebSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"ServerAuthSettings",
|
|
"fabro_types::settings::server::ServerAuthSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"ServerAuthMethod",
|
|
"fabro_types::settings::server::ServerAuthMethod",
|
|
&[],
|
|
),
|
|
(
|
|
"ServerAuthGithubSettings",
|
|
"fabro_types::settings::server::ServerAuthGithubSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"RunModelSettings",
|
|
"fabro_types::settings::run::RunModelSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"RunModelControls",
|
|
"fabro_types::settings::run::RunModelControls",
|
|
&[],
|
|
),
|
|
(
|
|
"ServerSandboxSettings",
|
|
"fabro_types::settings::server::ServerSandboxSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"ServerSandboxProvidersSettings",
|
|
"fabro_types::settings::server::ServerSandboxProvidersSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"ServerSandboxProviderSettings",
|
|
"fabro_types::settings::server::ServerSandboxProviderSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"ServerStorageSettings",
|
|
"fabro_types::settings::server::ServerStorageSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"ServerArtifactsSettings",
|
|
"fabro_types::settings::server::ServerArtifactsSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"ServerSlateDbSettings",
|
|
"fabro_types::settings::server::ServerSlateDbSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"ObjectStoreSettings",
|
|
"fabro_types::settings::server::ObjectStoreSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"ServerSchedulerSettings",
|
|
"fabro_types::settings::server::ServerSchedulerSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"ServerLoggingSettings",
|
|
"fabro_types::settings::server::ServerLoggingSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"LogDestination",
|
|
"fabro_types::settings::server::LogDestination",
|
|
&[],
|
|
),
|
|
(
|
|
"ServerIntegrationsSettings",
|
|
"fabro_types::settings::server::ServerIntegrationsSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"GithubIntegrationSettings",
|
|
"fabro_types::settings::server::GithubIntegrationSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"GithubIntegrationStrategy",
|
|
"fabro_types::settings::server::GithubIntegrationStrategy",
|
|
&[],
|
|
),
|
|
(
|
|
"SlackIntegrationSettings",
|
|
"fabro_types::settings::server::SlackIntegrationSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"IntegrationWebhooksSettings",
|
|
"fabro_types::settings::server::IntegrationWebhooksSettings",
|
|
&[],
|
|
),
|
|
(
|
|
"WebhookStrategy",
|
|
"fabro_types::settings::server::WebhookStrategy",
|
|
&[],
|
|
),
|
|
("AuthMethod", "fabro_types::AuthMethod", &[]),
|
|
("IdpIdentity", "fabro_types::IdpIdentity", &[]),
|
|
(
|
|
"RunClientProvenance",
|
|
"fabro_types::RunClientProvenance",
|
|
&[],
|
|
),
|
|
("RunProvenance", "fabro_types::RunProvenance", &[]),
|
|
(
|
|
"RunServerProvenance",
|
|
"fabro_types::RunServerProvenance",
|
|
&[],
|
|
),
|
|
("Principal", "fabro_types::Principal", &[]),
|
|
("PrincipalUser", "fabro_types::UserPrincipal", &[]),
|
|
("SystemActorKind", "fabro_types::SystemActorKind", &[]),
|
|
("QuestionType", "fabro_types::QuestionType", &[]),
|
|
("StageCompletion", "fabro_types::StageCompletion", &[]),
|
|
("Conclusion", "fabro_types::Conclusion", &[]),
|
|
("StageOutcome", "fabro_types::StageOutcome", &[]),
|
|
("StageId", "fabro_types::StageId", &[]),
|
|
("ParallelBranchId", "fabro_types::ParallelBranchId", &[]),
|
|
("StageHandler", "fabro_types::StageHandler", &[]),
|
|
("StageState", "fabro_types::StageState", &[]),
|
|
("AgentControlState", "fabro_types::AgentControlState", &[]),
|
|
("CommandTermination", "fabro_types::CommandTermination", &[]),
|
|
("StageModelUsage", "fabro_types::StageModelUsage", &[]),
|
|
(
|
|
"ParallelBranchResult",
|
|
"fabro_types::ParallelBranchResult",
|
|
&[],
|
|
),
|
|
("StageProjection", "fabro_types::StageProjection", &[]),
|
|
(
|
|
"StageInferenceProjection",
|
|
"fabro_types::StageInferenceProjection",
|
|
&[],
|
|
),
|
|
(
|
|
"StageToolBatchProjection",
|
|
"fabro_types::StageToolBatchProjection",
|
|
&[],
|
|
),
|
|
("LlmOutputKind", "fabro_types::LlmOutputKind", &[]),
|
|
("PermissionLevel", "fabro_types::PermissionLevel", &[]),
|
|
(
|
|
"AgentSessionActivatedProps",
|
|
"fabro_types::run_event::AgentSessionActivatedProps",
|
|
&[],
|
|
),
|
|
("TodoListProjection", "fabro_types::TodoListProjection", &[]),
|
|
("SubAgentProjection", "fabro_types::SubAgentProjection", &[]),
|
|
("SubAgentStatus", "fabro_types::SubAgentStatus", &[]),
|
|
("SkillsProjection", "fabro_types::SkillsProjection", &[]),
|
|
("ActivatedSkill", "fabro_types::ActivatedSkill", &[]),
|
|
("AgentSkillSummary", "fabro_types::AgentSkillSummary", &[]),
|
|
(
|
|
"AgentSkillActivationSource",
|
|
"fabro_types::AgentSkillActivationSource",
|
|
&[],
|
|
),
|
|
("AgentToolSummary", "fabro_types::AgentToolSummary", &[]),
|
|
("AgentToolSource", "fabro_types::AgentToolSource", &[]),
|
|
("AgentToolCategory", "fabro_types::AgentToolCategory", &[]),
|
|
(
|
|
"AgentToolsAvailableProps",
|
|
"fabro_types::AgentToolsAvailableProps",
|
|
&[],
|
|
),
|
|
(
|
|
"McpServerProjection",
|
|
"fabro_types::McpServerProjection",
|
|
&[],
|
|
),
|
|
("McpServerStatus", "fabro_types::McpServerStatus", &[]),
|
|
(
|
|
"AgentMcpToolSummary",
|
|
"fabro_types::AgentMcpToolSummary",
|
|
&[],
|
|
),
|
|
(
|
|
"McpHttpProtocol",
|
|
"fabro_types::settings::run::McpHttpProtocol",
|
|
&[],
|
|
),
|
|
(
|
|
"McpTransport",
|
|
"fabro_types::settings::run::McpTransport",
|
|
&[],
|
|
),
|
|
("McpTransportView", "fabro_types::McpTransportView", &[]),
|
|
("StageContextWindow", "fabro_types::StageContextWindow", &[]),
|
|
(
|
|
"StageContextWindowProjection",
|
|
"fabro_types::StageContextWindowProjection",
|
|
&[],
|
|
),
|
|
(
|
|
"StageContextWindowBreakdownItem",
|
|
"fabro_types::StageContextWindowBreakdownItem",
|
|
&[],
|
|
),
|
|
(
|
|
"StageContextWindowCategory",
|
|
"fabro_types::StageContextWindowCategory",
|
|
&[],
|
|
),
|
|
(
|
|
"StageContextWindowCountMethod",
|
|
"fabro_types::StageContextWindowCountMethod",
|
|
&[],
|
|
),
|
|
(
|
|
"StageContextWindowStaleness",
|
|
"fabro_types::StageContextWindowStaleness",
|
|
&[],
|
|
),
|
|
(
|
|
"StageContextWindowUnavailableReason",
|
|
"fabro_types::StageContextWindowUnavailableReason",
|
|
&[],
|
|
),
|
|
(
|
|
"StageContextWindowWarning",
|
|
"fabro_types::StageContextWindowWarning",
|
|
&[],
|
|
),
|
|
("SecretMetadata", "fabro_types::SecretMetadata", &[]),
|
|
("Variable", "fabro_types::Variable", &[]),
|
|
(
|
|
"VariableListResponse",
|
|
"fabro_types::VariableListResponse",
|
|
&[],
|
|
),
|
|
(
|
|
"CreateVariableRequest",
|
|
"fabro_types::CreateVariableRequest",
|
|
&[],
|
|
),
|
|
(
|
|
"UpdateVariableRequest",
|
|
"fabro_types::UpdateVariableRequest",
|
|
&[],
|
|
),
|
|
("InterviewOption", "fabro_types::InterviewOption", &[]),
|
|
("ReviewTarget", "fabro_types::ReviewTarget", &[]),
|
|
("ReviewTargetKind", "fabro_types::ReviewTargetKind", &[]),
|
|
(
|
|
"InterviewQuestionRecord",
|
|
"fabro_types::InterviewQuestionRecord",
|
|
&[],
|
|
),
|
|
(
|
|
"PendingInterviewRecord",
|
|
"fabro_types::PendingInterviewRecord",
|
|
&[],
|
|
),
|
|
("CompletionUsage", "fabro_model::TokenCounts", &[]),
|
|
("BilledTokenCounts", "fabro_types::BilledTokenCounts", &[]),
|
|
("BillingModelRef", "fabro_model::ModelRef", &[]),
|
|
("BillingSpeed", "fabro_model::Speed", &[]),
|
|
("ExecOutputTail", "fabro_types::ExecOutputTail", &[]),
|
|
("StageTiming", "fabro_types::StageTiming", &[]),
|
|
("RunTiming", "fabro_types::RunTiming", &[]),
|
|
("ProviderId", "fabro_model::ProviderId", &[]),
|
|
("Model", "fabro_model::Model", &[]),
|
|
("Provider", "fabro_model::Provider", &[]),
|
|
("ModelLimits", "fabro_model::ModelLimits", &[]),
|
|
(
|
|
"ReasoningEffortFeature",
|
|
"fabro_model::ReasoningEffortFeature",
|
|
&[],
|
|
),
|
|
("ReasoningEffort", "fabro_model::ReasoningEffort", &[]),
|
|
("ModelFeatures", "fabro_model::ModelFeatures", &[]),
|
|
("ModelControls", "fabro_model::ModelControls", &[]),
|
|
("ModelCosts", "fabro_model::ModelCosts", &[]),
|
|
("ModelTestMode", "fabro_model::ModelTestMode", &[]),
|
|
("RunProjection", "fabro_types::RunProjection", &[]),
|
|
("RunEvent", "fabro_types::RunEvent", &[]),
|
|
("PairId", "fabro_types::PairId", &[]),
|
|
("PairMessageId", "fabro_types::PairMessageId", &[]),
|
|
("PairStatus", "fabro_types::PairStatus", &[]),
|
|
("PairTarget", "fabro_types::PairTarget", &[]),
|
|
("PairRecord", "fabro_types::PairRecord", &[]),
|
|
(
|
|
"RunPairStatusResponse",
|
|
"fabro_types::RunPairStatusResponse",
|
|
&[],
|
|
),
|
|
("PairStartRequest", "fabro_types::PairStartRequest", &[]),
|
|
("PairMessageRequest", "fabro_types::PairMessageRequest", &[]),
|
|
("PairMessageRecord", "fabro_types::PairMessageRecord", &[]),
|
|
(
|
|
"PairTranscriptResponse",
|
|
"fabro_types::PairTranscriptResponse",
|
|
&[],
|
|
),
|
|
(
|
|
"PairTranscriptEntry",
|
|
"fabro_types::PairTranscriptEntry",
|
|
&[],
|
|
),
|
|
(
|
|
"RunEventDetailResponse",
|
|
"fabro_types::RunEventDetailResponse",
|
|
&[],
|
|
),
|
|
("EventEnvelope", "fabro_types::EventEnvelope", &[]),
|
|
("PullRequest", "fabro_types::PullRequest", &[]),
|
|
("PullRequestLink", "fabro_types::PullRequestLink", &[]),
|
|
(
|
|
"PullRequestCreationId",
|
|
"fabro_types::PullRequestCreationId",
|
|
&[],
|
|
),
|
|
(
|
|
"PullRequestCreationStatus",
|
|
"fabro_types::PullRequestCreationStatus",
|
|
&[],
|
|
),
|
|
(
|
|
"PullRequestCreation",
|
|
"fabro_types::PullRequestCreation",
|
|
&[],
|
|
),
|
|
("PullRequestDetails", "fabro_types::PullRequestDetails", &[]),
|
|
("PullRequestMeta", "fabro_types::PullRequestMeta", &[]),
|
|
(
|
|
"PullRequestResponse",
|
|
"fabro_types::PullRequestResponse",
|
|
&[],
|
|
),
|
|
(
|
|
"PullRequestDetailsStatus",
|
|
"fabro_types::PullRequestDetailsStatus",
|
|
&[],
|
|
),
|
|
(
|
|
"PullRequestDetailsUnavailableReason",
|
|
"fabro_types::PullRequestDetailsUnavailableReason",
|
|
&[],
|
|
),
|
|
("RunSandboxRuntime", "fabro_types::RunSandboxRuntime", &[]),
|
|
("RunSandboxKind", "fabro_types::RunSandboxKind", &[]),
|
|
("RunSandboxPlan", "fabro_types::RunSandboxPlan", &[]),
|
|
("RunSandboxInstance", "fabro_types::RunSandboxInstance", &[]),
|
|
("RunSandboxFailure", "fabro_types::RunSandboxFailure", &[]),
|
|
("PullRequestUser", "fabro_types::PullRequestUser", &[]),
|
|
("PullRequestRef", "fabro_types::PullRequestRef", &[]),
|
|
(
|
|
"MergeMethod",
|
|
"fabro_types::settings::run::MergeStrategy",
|
|
&[],
|
|
),
|
|
("SecretType", "fabro_types::SecretType", &[]),
|
|
("DiffStats", "fabro_types::DiffStats", &[]),
|
|
("DirtyStatus", "fabro_types::DirtyStatus", &[]),
|
|
("GitContext", "fabro_types::GitContext", &[]),
|
|
(
|
|
"SandboxProviderKind",
|
|
"fabro_types::SandboxProviderKind",
|
|
&[],
|
|
),
|
|
(
|
|
"SystemIntegrationsResponse",
|
|
"fabro_types::SystemIntegrationsResponse",
|
|
&[],
|
|
),
|
|
(
|
|
"SystemIntegrationStatus",
|
|
"fabro_types::SystemIntegrationStatus",
|
|
&[],
|
|
),
|
|
(
|
|
"IntegrationProvider",
|
|
"fabro_types::IntegrationProvider",
|
|
&[],
|
|
),
|
|
("IntegrationStatus", "fabro_types::IntegrationStatus", &[]),
|
|
(
|
|
"IntegrationConnectionStatus",
|
|
"fabro_types::IntegrationConnectionStatus",
|
|
&[],
|
|
),
|
|
(
|
|
"IntegrationConnectionKind",
|
|
"fabro_types::IntegrationConnectionKind",
|
|
&[],
|
|
),
|
|
(
|
|
"IntegrationConnectionState",
|
|
"fabro_types::IntegrationConnectionState",
|
|
&[],
|
|
),
|
|
("RunSandbox", "fabro_types::RunSandbox", &[]),
|
|
("SandboxDetails", "fabro_types::SandboxDetails", &[]),
|
|
("SandboxInfo", "fabro_types::SandboxInfo", &[]),
|
|
(
|
|
"SandboxProviderLookupError",
|
|
"fabro_types::SandboxProviderLookupError",
|
|
&[],
|
|
),
|
|
("SandboxListMeta", "fabro_types::SandboxListMeta", &[]),
|
|
(
|
|
"SandboxListResponse",
|
|
"fabro_types::SandboxListResponse",
|
|
&[],
|
|
),
|
|
("SandboxNetwork", "fabro_types::SandboxNetwork", &[]),
|
|
(
|
|
"SandboxNetworkPolicy",
|
|
"fabro_types::SandboxNetworkPolicy",
|
|
&[],
|
|
),
|
|
(
|
|
"SandboxNetworkPolicyMode",
|
|
"fabro_types::SandboxNetworkPolicyMode",
|
|
&[],
|
|
),
|
|
("SandboxService", "fabro_types::SandboxService", &[]),
|
|
(
|
|
"SandboxServiceDiscoverySource",
|
|
"fabro_types::SandboxServiceDiscoverySource",
|
|
&[],
|
|
),
|
|
(
|
|
"SandboxServiceListMeta",
|
|
"fabro_types::SandboxServiceListMeta",
|
|
&[],
|
|
),
|
|
(
|
|
"SandboxServiceListResponse",
|
|
"fabro_types::SandboxServiceListResponse",
|
|
&[],
|
|
),
|
|
("SandboxState", "fabro_types::SandboxState", &[]),
|
|
("SandboxResources", "fabro_types::SandboxResources", &[]),
|
|
("SandboxTimestamps", "fabro_types::SandboxTimestamps", &[]),
|
|
("AskFabro", "fabro_types::AskFabro", &[]),
|
|
("Automation", "fabro_automation::Automation", &[]),
|
|
("AutomationRef", "fabro_types::AutomationRef", &[]),
|
|
("AutomationTarget", "fabro_automation::AutomationTarget", &[
|
|
]),
|
|
(
|
|
"AutomationTrigger",
|
|
"fabro_automation::AutomationTrigger",
|
|
&[],
|
|
),
|
|
(
|
|
"CreateAutomationRequest",
|
|
"fabro_automation::AutomationDraft",
|
|
&[],
|
|
),
|
|
(
|
|
"ReplaceAutomationRequest",
|
|
"fabro_automation::AutomationReplace",
|
|
&[],
|
|
),
|
|
// MCP server catalog wire types reuse the domain model rather than
|
|
// generating parallel DTOs. The integer formats in the spec generate as
|
|
// `i64`/`i32`, but the domain types use `u64`/`u16`; the replacements
|
|
// ensure the signed widths never leak into the public client.
|
|
// (`McpTransport`/`McpTransportView`/`McpHttpProtocol` are mapped above.)
|
|
//
|
|
// Read responses use the value-omitting `McpServerView`/`McpTransportView`
|
|
// projection (env/header values are never returned); write requests carry
|
|
// the full transport, so they reuse the draft/replace domain types.
|
|
("McpServer", "fabro_types::McpServerView", &[]),
|
|
("CreateMcpServerRequest", "fabro_types::McpServerDraft", &[]),
|
|
(
|
|
"ReplaceMcpServerRequest",
|
|
"fabro_types::McpServerReplace",
|
|
&[],
|
|
),
|
|
("Environment", "fabro_environment::Environment", &[]),
|
|
("SessionId", "fabro_types::SessionId", &[]),
|
|
("TurnId", "fabro_types::TurnId", &[]),
|
|
("SessionStatus", "fabro_types::SessionStatus", &[]),
|
|
("SessionTurn", "fabro_types::SessionTurn", &[]),
|
|
("SessionMessage", "fabro_types::SessionMessage", &[]),
|
|
("SessionRecord", "fabro_types::SessionRecord", &[]),
|
|
("SessionSummary", "fabro_types::SessionSummary", &[]),
|
|
("SessionDetail", "fabro_types::SessionDetail", &[]),
|
|
("ReasoningOutput", "fabro_types::ReasoningOutput", &[]),
|
|
("CompletionMessage", "fabro_types::Message", &[]),
|
|
("CompletionMessageRole", "fabro_types::Role", &[]),
|
|
("CompletionContentPart", "fabro_types::ContentPart", &[]),
|
|
("WorkflowVersion", "fabro_types::WorkflowVersion", &[]),
|
|
("RunIntent", "fabro_types::RunIntent", &[]),
|
|
("RunIntentArgs", "fabro_types::RunIntentArgs", &[]),
|
|
("RunTarget", "fabro_types::RunTarget", &[]),
|
|
("GitRunTarget", "fabro_types::GitRunTarget", &[]),
|
|
("WorkflowPath", "fabro_types::WorkflowPath", &[]),
|
|
("WorkflowVersionId", "fabro_types::WorkflowVersionId", &[]),
|
|
("BlobHash", "fabro_types::BlobHash", &[]),
|
|
("CostSource", "fabro_model::CostSource", &[]),
|
|
];
|
|
for (name, path, impls) in replacements {
|
|
settings.with_replacement(*name, *path, impls.iter().copied());
|
|
}
|
|
|
|
let mut generator = Generator::new(&settings);
|
|
let tokens = generator
|
|
.generate_tokens(&spec)
|
|
.expect("failed to generate tokens from OpenAPI spec");
|
|
let syntax_tree = syn::parse2::<syn::File>(tokens).expect("failed to parse generated tokens");
|
|
let formatted = prettyplease::unparse(&syntax_tree);
|
|
|
|
let out_dir = env::var("OUT_DIR").expect("OUT_DIR should be set for build scripts");
|
|
let out_path = Path::new(&out_dir).join("codegen.rs");
|
|
fs::write(&out_path, formatted).expect("failed to write generated code");
|
|
}
|