Skip to main content

sokuto_server/
openapi.rs

1//! # OpenAPI 3.1 仕様統合モジュール
2//!
3//! `utoipa` によるコンパイル時スキーマ自動導出、Swagger UI マウント、
4//! および CLI/CI 用の静的スキーマエクスポート機能を提供する。
5
6use axum::Router;
7use axum::response::IntoResponse;
8use sokuto_core::gating::{
9    CandidateProbability, DecisionRoute, EscalationContext, GatingConfig, GatingMetadata,
10    SystemRoutingSummary,
11};
12use sokuto_core::schema::{
13    Answer, Criteria, Question, QuestionType, StateBatchRequest, StateBatchResponse,
14    SystemOneRequest, SystemOneResponse, Usage,
15};
16use utoipa::OpenApi;
17
18use crate::error::{ErrorDetail, ErrorResponse};
19use crate::handlers::ops::HealthStatusResponse;
20use crate::schema::dag::{
21    DagDefinitionDto, DagEscalationDetailDto, DagNodeDto, DagNodeTypeDto, DagRequest, DagResponse,
22    DagStepResultDto, DagUsageDto, NodeConditionDto, NodeConditionOpDto,
23};
24
25/// Jev 互換 HTTP API サーバーの OpenAPI 仕様定義。
26#[derive(OpenApi)]
27#[openapi(
28    paths(
29        crate::handlers::systemone::system_one_handler,
30        crate::handlers::state_batch::state_batch_handler,
31        crate::handlers::dag::dag_handler,
32        crate::handlers::ops::health_handler,
33        crate::handlers::ops::ready_handler,
34        crate::handlers::ops::metrics_handler,
35    ),
36    components(
37        schemas(
38            SystemOneRequest,
39            SystemOneResponse,
40            StateBatchRequest,
41            StateBatchResponse,
42            Question,
43            QuestionType,
44            Criteria,
45            Answer,
46            Usage,
47            DecisionRoute,
48            GatingConfig,
49            GatingMetadata,
50            CandidateProbability,
51            EscalationContext,
52            SystemRoutingSummary,
53            ErrorResponse,
54            ErrorDetail,
55            HealthStatusResponse,
56            DagRequest,
57            DagResponse,
58            DagDefinitionDto,
59            DagNodeDto,
60            DagNodeTypeDto,
61            NodeConditionDto,
62            NodeConditionOpDto,
63            DagStepResultDto,
64            DagEscalationDetailDto,
65            DagUsageDto,
66        )
67    ),
68    tags(
69        (name = "Inference", description = "TypeSafe AI Jev 互換の非自己回帰型判断推論 API"),
70        (name = "Operations", description = "ヘルスチェックおよび Prometheus 監視運用 API")
71    ),
72    info(
73        title = "Sokuto HTTP API",
74        version = "0.0.0",
75        description = "TypeSafe AI Jev 互換の非自己回帰型判断特化モデル向け超低遅延 REST API 仕様書。"
76    )
77)]
78pub struct ApiDoc;
79
80/// OpenAPI 3.1 仕様ドキュメント構造体を生成する。
81pub fn generate_openapi_spec() -> utoipa::openapi::OpenApi {
82    let mut spec = ApiDoc::openapi();
83    spec.info.version = env!("CARGO_PKG_VERSION").to_string();
84    spec
85}
86
87/// 整形済み OpenAPI 3.1 JSON 文字列をエクスポートする。
88pub fn export_openapi_json() -> String {
89    generate_openapi_spec()
90        .to_pretty_json()
91        .expect("OpenAPI 仕様の JSON シリアライズに失敗しました。")
92}
93
94/// OpenAPI JSON 仕様エンドポイントのハンドラ。
95pub async fn openapi_json_handler() -> impl IntoResponse {
96    (
97        [("content-type", "application/json; charset=utf-8")],
98        export_openapi_json(),
99    )
100}
101
102/// Swagger UI をルーターにマウントする。
103///
104/// `swagger` フィーチャーが無効化されている場合は何も追加せずルーターをそのまま返却する。
105pub fn mount_swagger_ui<S>(router: Router<S>) -> Router<S>
106where
107    S: Clone + Send + Sync + 'static,
108{
109    #[cfg(feature = "swagger")]
110    {
111        use utoipa_swagger_ui::SwaggerUi;
112        router.merge(
113            SwaggerUi::new("/swagger-ui").url("/api-docs/openapi.json", generate_openapi_spec()),
114        )
115    }
116
117    #[cfg(not(feature = "swagger"))]
118    {
119        router.route(
120            "/api-docs/openapi.json",
121            axum::routing::get(openapi_json_handler),
122        )
123    }
124}