fastapi_output/lib.rs
1//! Agent-aware rich console output for fastapi_rust.
2//!
3//! This crate provides beautiful terminal output that automatically
4//! detects whether it's running in an AI agent environment and switches
5//! to plain text mode accordingly.
6//!
7//! # Role In The System
8//!
9//! `fastapi-output` is an optional, presentation-only layer. It formats
10//! diagnostics, route tables, middleware stacks, and test reports in a way
11//! that's readable for humans and stable for automated agents. The main
12//! framework can run without it; the `fastapi` crate enables it by default
13//! behind a feature flag so production users can opt out.
14//!
15//! # Features
16//!
17//! - Automatic agent detection (Claude Code, Codex, Cursor, etc.)
18//! - Dual-mode output (Rich for humans, Plain for agents)
19//! - FastAPI-themed color palette
20//! - Tables, panels, progress bars, and more
21//!
22//! # Quick Start
23//!
24//! ```rust,ignore
25//! use fastapi_output::prelude::*;
26//!
27//! // Auto-detects mode based on environment
28//! let output = RichOutput::auto();
29//!
30//! // Print styled text (rendered appropriately for mode)
31//! output.success("Server started successfully");
32//! output.error("Failed to bind to port 8000");
33//!
34//! // Check if running in agent-friendly mode
35//! if output.is_agent_mode() {
36//! // Output is plain text, safe for agent parsing
37//! }
38//! ```
39//!
40//! # Output Modes
41//!
42//! The library supports three output modes:
43//!
44//! | Mode | Description | Use Case |
45//! |------|-------------|----------|
46//! | `Rich` | Full ANSI styling with Unicode symbols | Human terminals |
47//! | `Plain` | Zero ANSI codes, ASCII only | AI agents, CI, logs |
48//! | `Minimal` | Colors only, no box characters | Simple terminals |
49//!
50//! # Agent Detection
51//!
52//! The library automatically detects agent environments by checking for
53//! known environment variables set by AI coding assistants:
54//!
55//! | Variable | Agent |
56//! |----------|-------|
57//! | `CLAUDE_CODE` | Claude Code CLI |
58//! | `CODEX_CLI` | OpenAI Codex CLI |
59//! | `CURSOR_SESSION` | Cursor IDE |
60//! | `AIDER_SESSION` | Aider |
61//! | `AGENT_MODE` | Generic agent flag |
62//! | `WINDSURF_SESSION` | Windsurf |
63//! | `CLINE_SESSION` | Cline |
64//! | `COPILOT_AGENT` | GitHub Copilot agent mode |
65//!
66//! # CI Detection
67//!
68//! CI environments are also detected and default to plain mode:
69//!
70//! | Variable | CI System |
71//! |----------|-----------|
72//! | `CI` | Generic CI flag |
73//! | `GITHUB_ACTIONS` | GitHub Actions |
74//! | `GITLAB_CI` | GitLab CI |
75//! | `JENKINS_URL` | Jenkins |
76//! | `CIRCLECI` | CircleCI |
77//! | `TRAVIS` | Travis CI |
78//! | `BUILDKITE` | Buildkite |
79//!
80//! # Environment Variable Precedence
81//!
82//! Environment variables are checked in the following order (highest to lowest priority):
83//!
84//! 1. **`FASTAPI_OUTPUT_MODE`** (highest) - Explicit mode selection
85//! - Values: `rich`, `plain`, `minimal`
86//! - Example: `FASTAPI_OUTPUT_MODE=plain cargo run`
87//!
88//! 2. **`FASTAPI_AGENT_MODE=1`** - Force agent detection (plain mode)
89//! - Useful for testing agent behavior in a human terminal
90//!
91//! 3. **`FASTAPI_HUMAN_MODE=1`** - Force human detection (rich mode)
92//! - Overrides agent detection when you want rich output
93//!
94//! 4. **`FORCE_COLOR`** - Standard force-color flag
95//! - Non-zero value forces rich output even in CI
96//!
97//! 5. **`NO_COLOR`** - Standard no-color flag
98//! - When set (any value), forces plain output
99//!
100//! 6. **Auto-detection** (lowest) - TTY check + agent/CI env vars
101//!
102//! ## Precedence Examples
103//!
104//! ```bash
105//! # Explicit mode always wins
106//! FASTAPI_OUTPUT_MODE=rich CLAUDE_CODE=1 cargo run # → Rich mode
107//!
108//! # Agent override beats CI detection
109//! FASTAPI_HUMAN_MODE=1 CI=true cargo run # → Rich mode
110//!
111//! # FORCE_COLOR beats NO_COLOR and CI
112//! FORCE_COLOR=1 CI=true NO_COLOR=1 cargo run # → Rich mode
113//!
114//! # NO_COLOR beats auto-detection
115//! NO_COLOR=1 cargo run # → Plain mode (even in TTY)
116//! ```
117//!
118//! # For Agent Authors
119//!
120//! If you're building an AI coding agent that invokes fastapi_rust applications:
121//!
122//! 1. **Set your agent's env var** (e.g., `CLAUDE_CODE=1`) for auto-detection
123//! 2. **Or set `FASTAPI_OUTPUT_MODE=plain`** for explicit plain mode
124//! 3. **Parse plain output** which uses consistent prefixes:
125//! - `[OK]` for success
126//! - `[ERROR]` for errors
127//! - `[WARN]` for warnings
128//! - `[INFO]` for info
129//! - `[DEBUG]` for debug
130//!
131//! # Components
132//!
133//! The library provides several output components:
134//!
135//! - [`Banner`] - Server startup banner with ASCII art
136//! - [`RouteDisplay`] - Route table display
137//! - [`ErrorFormatter`] - Validation and HTTP error formatting
138//! - [`RequestLogger`] - HTTP request/response logging
139//! - [`MiddlewareStackDisplay`] - Middleware stack visualization
140//! - [`DependencyTreeDisplay`] - Dependency injection tree
141//! - [`ShutdownProgressDisplay`] - Graceful shutdown progress
142//! - [`TestReportDisplay`] - Test results formatting
143//! - [`OpenApiDisplay`] - OpenAPI endpoint table and schema visualization (Phase 5)
144//! - [`HelpDisplay`] - Help and usage display (Phase 5)
145
146// SAFETY: We use deny instead of forbid to allow unsafe in test modules.
147// The only unsafe code is for env::set_var/remove_var in tests, which
148// became unsafe in Rust 2024 edition due to thread-safety concerns.
149// Our tests use serial_test to ensure sequential execution.
150#![deny(unsafe_code)]
151#![warn(missing_docs)]
152
153pub mod components;
154pub mod detection;
155pub mod facade;
156pub mod mode;
157pub mod testing;
158pub mod themes;
159
160// Re-exports for convenience
161pub use detection::{
162 DetectionResult, OutputPreference, OverrideMode, detect_environment, detected_preference,
163 detection_diagnostics, is_agent_environment,
164};
165pub use facade::{RichOutput, RichOutputBuilder, StatusKind, get_global, set_global};
166pub use mode::{OutputMode, feature_info, has_rich_support};
167pub use testing::{
168 OutputEntry, OutputLevel, TestOutput, assert_contains, assert_contains_in_order,
169 assert_has_ansi, assert_max_width, assert_no_ansi, assert_not_contains, capture, capture_both,
170 capture_with_width, debug_output, is_verbose, strip_ansi_codes,
171};
172pub use themes::{FastApiTheme, ThemePreset};
173
174// Re-export component types
175pub use components::banner::{Banner, BannerConfig, ServerInfo};
176pub use components::dependency_tree::{DependencyNode, DependencyTreeDisplay};
177pub use components::errors::{
178 ErrorFormatter, FormattedError, HttpErrorInfo, LocItem, ValidationContext,
179 ValidationErrorDetail,
180};
181pub use components::help_display::{ArgGroup, ArgInfo, CommandInfo, HelpDisplay, HelpInfo};
182pub use components::http_inspector::{
183 RequestInfo, RequestInspector, ResponseInfo, ResponseInspector,
184};
185pub use components::logging::{HttpMethod, LogEntry, RequestLogger, ResponseTiming};
186pub use components::middleware_stack::{MiddlewareInfo, MiddlewareStackDisplay};
187pub use components::openapi_display::{
188 EndpointInfo, OpenApiDisplay, OpenApiDisplayConfig, OpenApiSummary, PropertyInfo, SchemaType,
189};
190pub use components::routes::{RouteDisplay, RouteEntry, RouteTableConfig};
191pub use components::routing_debug::{
192 CandidateRoute, ExtractedParams, MatchResult, RoutingDebug, RoutingDebugInfo,
193};
194pub use components::shutdown_progress::{ShutdownPhase, ShutdownProgress, ShutdownProgressDisplay};
195pub use components::test_results::{
196 TestCaseResult, TestModuleResult, TestReport, TestReportDisplay, TestStatus,
197};
198
199/// Prelude module for convenient imports.
200pub mod prelude {
201 // Components
202 pub use crate::components::banner::{Banner, BannerConfig, ServerInfo};
203 pub use crate::components::dependency_tree::{DependencyNode, DependencyTreeDisplay};
204 pub use crate::components::errors::{
205 ErrorFormatter, FormattedError, HttpErrorInfo, LocItem, ValidationContext,
206 ValidationErrorDetail,
207 };
208 pub use crate::components::help_display::{
209 ArgGroup, ArgInfo, CommandInfo, HelpDisplay, HelpInfo,
210 };
211 pub use crate::components::http_inspector::{
212 RequestInfo, RequestInspector, ResponseInfo, ResponseInspector,
213 };
214 pub use crate::components::logging::{HttpMethod, LogEntry, RequestLogger, ResponseTiming};
215 pub use crate::components::middleware_stack::{MiddlewareInfo, MiddlewareStackDisplay};
216 pub use crate::components::openapi_display::{
217 EndpointInfo, OpenApiDisplay, OpenApiDisplayConfig, OpenApiSummary, PropertyInfo,
218 SchemaType,
219 };
220 pub use crate::components::routes::{RouteDisplay, RouteEntry, RouteTableConfig};
221 pub use crate::components::routing_debug::{
222 CandidateRoute, ExtractedParams, MatchResult, RoutingDebug, RoutingDebugInfo,
223 };
224 pub use crate::components::shutdown_progress::{
225 ShutdownPhase, ShutdownProgress, ShutdownProgressDisplay,
226 };
227 pub use crate::components::test_results::{
228 TestCaseResult, TestModuleResult, TestReport, TestReportDisplay, TestStatus,
229 };
230
231 // Core types
232 pub use crate::detection::{
233 DetectionResult, OutputPreference, OverrideMode, detect_environment, detected_preference,
234 is_agent_environment,
235 };
236 pub use crate::facade::{RichOutput, RichOutputBuilder, StatusKind, get_global, set_global};
237 pub use crate::mode::{OutputMode, feature_info, has_rich_support};
238 pub use crate::testing::{
239 OutputEntry, OutputLevel, TestOutput, assert_contains, assert_contains_in_order,
240 assert_has_ansi, assert_max_width, assert_no_ansi, assert_not_contains, capture,
241 capture_both, capture_with_width, debug_output, is_verbose, strip_ansi_codes,
242 };
243 pub use crate::themes::{FastApiTheme, ThemePreset};
244}