From 1c0b92e67e99eca3df51ad3f3ca068f5f1f2068b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesu=CC=81s=20Pe=CC=81rez?= Date: Tue, 20 Jan 2026 21:06:47 +0000 Subject: [PATCH] feat: add unified dispatcher for all backends via typedialog command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Implement dispatcher allowing access to web, tui, ai, ag, prov-gen via single entry point - Add 5 new subcommands with 3-line help format (description + usage + options) - Update CLI help text with backend examples and quick start - Update README.md with unified command interface section - Maintain backward compatibility with direct binary invocation - All backends now accessible: typedialog web/tui/ai/ag/prov-gen ✓ Tests pass, no compiler warnings --- CHANGELOG.md | 21 +++++ README.md | 60 ++++++++++++- crates/typedialog-core/src/cli_common.rs | 85 ++++++++++++------ crates/typedialog/src/main.rs | 104 ++++++++++++++++++++++- 4 files changed, 243 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b032cb0..13d5414 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,27 @@ ## [Unreleased] +### Added - Unified Command Interface (Dispatcher) + +**Dispatcher for Backend Access** +- Added dispatcher to `typedialog` command allowing access to all backends via single entry point +- Users can now invoke: `typedialog web`, `typedialog tui`, `typedialog ai`, `typedialog ag`, `typedialog prov-gen` +- Each backend command dispatches to corresponding binary (`typedialog-web`, `typedialog-tui`, etc.) +- All arguments are passed through transparently to backend binaries +- Help available via: `typedialog web -h`, `typedialog tui -h`, etc. +- Maintains backward compatibility - specialized binaries still work directly + +**Updated Documentation** +- README.md: Added "Unified Command Interface" section with dispatcher examples +- Backend sections now show both dispatcher and direct binary usage +- Consistent command examples across all backend documentation + +**Benefits** +- Simplified UX - Single entry point instead of 6 separate binaries +- No need to know about internal binary separation +- Easier discoverability: `typedialog -h` shows all backends as subcommands +- Transparent argument passing maintains full feature access + ### Added - Professional Quality Improvements **Community Health Files** diff --git a/README.md b/README.md index 7fa2654..3bffb8c 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,35 @@ cargo run --example form typedialog form config.toml --defaults defaults.json ```text +## Unified Command Interface + +All backends are accessible through the **single `typedialog` command** with automatic dispatcher: + +```bash +# Each backend can be invoked directly via typedialog +typedialog web form config.toml --port 8080 # Web backend (browser forms) +typedialog tui config.toml # TUI backend (terminal UI) +typedialog ai serve --port 8765 # AI backend (RAG assistant) +typedialog ag run agent.mdx # Agent backend (LLM agents) +typedialog prov-gen generate --spec project.ncl # Provisioning generator + +# Or use specific binaries if you prefer +typedialog-web form config.toml --port 8080 +typedialog-tui config.toml +typedialog-ai serve --port 8765 +typedialog-ag run agent.mdx +typedialog-prov-gen generate --spec project.ncl + +# Show help for each backend +typedialog web -h +typedialog tui -h +typedialog ai -h +typedialog ag -h +typedialog prov-gen -h +```text + +All backends produce identical JSON output from the same TOML form definition, making it easy to switch between interfaces without changing your data. + ## Backends at a Glance ### CLI Backend (inquire) @@ -99,6 +128,11 @@ typedialog form schema.toml --defaults config.json --format json Full terminal UI with keyboard navigation and mouse support. ```bash +# Via dispatcher +typedialog tui config.toml + +# Or run directly +typedialog-tui config.toml cargo run -p typedialog-tui --example form_with_autocompletion ```text @@ -110,8 +144,13 @@ cargo run -p typedialog-tui --example form_with_autocompletion HTTP server with browser-based forms. ```bash +# Via dispatcher +typedialog web form config.toml --port 8080 + +# Or run directly +typedialog-web form config.toml --port 8080 cargo run -p typedialog-web -- --config config/web/dev.toml -# Open http://localhost:3000 +# Open http://localhost:8080 ```text **Use for:** SaaS platforms, public forms, mobile-friendly interfaces @@ -122,6 +161,12 @@ cargo run -p typedialog-web -- --config config/web/dev.toml Retrieval-Augmented Generation (RAG) system with semantic search and embeddings. ```bash +# Via dispatcher +typedialog ai serve --port 8765 + +# Or run directly +typedialog-ai serve --port 8765 + # Query knowledge base typedialog-ai --config config/ai/dev.toml --query "How do I configure encryption?" @@ -147,6 +192,19 @@ typedialog-ai --config config/ai/production.toml --build-graph ./docs Execute AI agents defined as `.agent.mdx` files with template variables, file imports, shell integration, and output validation. +### Quick Start + +```bash +# Via dispatcher +typedialog ag run agent.mdx + +# Or run directly +typedialog-ag run agent.mdx + +# For more options +typedialog ag -h +```text + ### Quick Example Create `hello.agent.mdx`: diff --git a/crates/typedialog-core/src/cli_common.rs b/crates/typedialog-core/src/cli_common.rs index 43deaa3..ec94be5 100644 --- a/crates/typedialog-core/src/cli_common.rs +++ b/crates/typedialog-core/src/cli_common.rs @@ -1,45 +1,82 @@ //! Common CLI patterns and help text for all typedialog binaries /// Long help for typedialog (CLI) main command -pub const CLI_MAIN_LONG_ABOUT: &str = r#"typedialog - Create interactive forms and prompts with multiple backends. +pub const CLI_MAIN_LONG_ABOUT: &str = r#"typedialog - Interactive forms and prompts with multiple backends. -By default uses CLI backend (step-by-step prompts). Switch backends using TYPEDIALOG_BACKEND -environment variable or use specialized binaries: - - typedialog: CLI backend (this tool) - - typedialog-tui: Terminal UI backend - - typedialog-web: Web server backend +Use typedialog with different backends for various use cases: -All backends produce identical JSON output from the same TOML form. +BACKENDS (run with -h for full options): + form CLI backend - Step-by-step interactive prompts (default, scriptable) + Run: typedialog form config.toml -h -BACKENDS: - CLI Step-by-step prompts (scriptable, default) - Run: typedialog form + web Web backend - Browser-based forms (best for teams) + Run: typedialog web form config.toml --port 8080 + For options: typedialog web -h - TUI 3-panel terminal UI (best for interactive use) - Run: typedialog-tui - Or: TYPEDIALOG_BACKEND=tui typedialog form + tui TUI backend - 3-panel terminal UI (best for interactive use) + Run: typedialog tui config.toml + For options: typedialog tui -h - Web Browser-based interface (best for teams) - Run: typedialog-web --port 8080 - Or: TYPEDIALOG_BACKEND=web typedialog form + ai AI backend - AI-powered configuration assistant + Run: typedialog ai serve + For options: typedialog ai -h + + ag Agent backend - Type-safe AI agents + Run: typedialog ag run agent.ncl + For options: typedialog ag -h + + prov-gen Provisioning generator - Generate provisioning structures + Run: typedialog prov-gen generate + For options: typedialog prov-gen -h + +All backends produce identical JSON output from the same TOML form definition. + +QUICK START: + # Interactive forms (CLI - default) + typedialog form config.toml + + # Run form in terminal UI + typedialog tui config.toml + + # Run form in web browser + typedialog web form config.toml --port 8080 ENVIRONMENT VARIABLES: - TYPEDIALOG_BACKEND Backend to use: 'cli', 'tui', or 'web' (default: 'cli') - TYPEDIALOG_PORT Port for web backend (default: 9000) TYPEDIALOG_LANG Locale for form localization (e.g., 'en-US', 'es-ES') Priority: CLI flag > form locale > TYPEDIALOG_LANG > LANG > LC_ALL > default + TYPEDIALOG_PORT Port for web backend (default: 9000) LANG System locale (fallback if TYPEDIALOG_LANG not set) LC_ALL Alternate locale setting (fallback to LANG) EXAMPLES: - # Use TUI backend instead of CLI - TYPEDIALOG_BACKEND=tui typedialog form config.toml + # Run form with CLI backend (default) + typedialog form config.toml - # Use Web backend on custom port - TYPEDIALOG_BACKEND=web TYPEDIALOG_PORT=8080 typedialog form config.toml + # Run form with TUI backend + typedialog tui config.toml - # Force Spanish locale - TYPEDIALOG_LANG=es-ES typedialog form config.toml"#; + # Run form with Web backend on port 8080 + typedialog web form config.toml --port 8080 + + # AI-powered assistant + typedialog ai serve + + # Run agent + typedialog ag run agent.ncl + + # Generate provisioning structure + typedialog prov-gen generate + + # Use Spanish locale + TYPEDIALOG_LANG=es-ES typedialog form config.toml + +HELP: + typedialog form -h Show CLI backend options + typedialog web -h Show Web backend options + typedialog tui -h Show TUI backend options + typedialog ai -h Show AI backend options + typedialog ag -h Show Agent backend options + typedialog prov-gen -h Show provisioning generator options"#; /// Long help for typedialog-tui pub const TUI_MAIN_LONG_ABOUT: &str = r#"typedialog-tui - Terminal UI tool for interactive forms. diff --git a/crates/typedialog/src/main.rs b/crates/typedialog/src/main.rs index a08421a..cfa7ed5 100644 --- a/crates/typedialog/src/main.rs +++ b/crates/typedialog/src/main.rs @@ -11,6 +11,7 @@ mod commands; use clap::{Parser, Subcommand}; use serde_json::json; use std::path::PathBuf; +use std::process::Command; use typedialog_core::cli_common; use typedialog_core::config::load_backend_config; use typedialog_core::prelude::*; @@ -297,10 +298,80 @@ enum Commands { #[arg(short, long)] verbose: bool, }, + + #[command( + name = "web", + about = "Web backend\t- Browser-based forms\n\t\tUse: typedialog web form config.toml --port 8080\n\t\tFor options: typedialog web -h" + )] + Web, + + #[command( + name = "tui", + about = "TUI backend\t- Terminal UI with 3-panel interface\n\t\tUse: typedialog tui config.toml\n\t\tFor options: typedialog tui -h" + )] + Tui, + + #[command( + name = "ai", + about = "AI backend\t- AI-powered configuration assistant\n\t\tUse: typedialog ai serve\n\t\tFor options: typedialog ai -h" + )] + Ai, + + #[command( + name = "ag", + about = "Agent backend - Type-safe AI agents\n\t\tUse: typedialog ag run agent.ncl\n\t\tFor options: typedialog ag -h" + )] + Ag, + + #[command( + name = "prov-gen", + about = "Provisioning generator - Generate provisioning structures\n\t\tUse: typedialog prov-gen generate\n\t\tFor options: typedialog prov-gen -h" + )] + ProvGen, } -#[tokio::main] -async fn main() -> Result<()> { +/// Dispatch to a specific backend binary +fn dispatch_backend(backend: &str) -> ! { + let binary_name = match backend { + "web" => "typedialog-web", + "tui" => "typedialog-tui", + "ai" => "typedialog-ai", + "ag" => "typedialog-ag", + "prov-gen" => "typedialog-prov-gen", + _ => { + eprintln!("Error: Unknown backend '{}'", backend); + std::process::exit(1); + } + }; + + // Collect all remaining arguments (skip program name and backend name) + let args: Vec = std::env::args().skip(2).collect(); + + // Execute backend binary with remaining arguments + match Command::new(binary_name).args(&args).status() { + Ok(status) => { + std::process::exit(status.code().unwrap_or(1)); + } + Err(e) => { + eprintln!("Error: Failed to execute {}: {}", binary_name, e); + std::process::exit(1); + } + } +} + +/// Try to dispatch to backend if first argument is a backend name +fn try_dispatch_to_backend() -> Option<()> { + let first_arg = std::env::args().nth(1)?; + + match first_arg.as_str() { + "web" | "tui" | "ai" | "ag" | "prov-gen" => { + dispatch_backend(&first_arg); + } + _ => None, + } +} + +async fn main_impl() -> Result<()> { // Initialize tracing subscriber with env filter (respects RUST_LOG) tracing_subscriber::fmt() .with_env_filter( @@ -480,7 +551,36 @@ async fn main() -> Result<()> { verbose, )?; } + + Commands::Web => { + dispatch_backend("web"); + } + + Commands::Tui => { + dispatch_backend("tui"); + } + + Commands::Ai => { + dispatch_backend("ai"); + } + + Commands::Ag => { + dispatch_backend("ag"); + } + + Commands::ProvGen => { + dispatch_backend("prov-gen"); + } } Ok(()) } + +fn main() -> Result<()> { + // Try to dispatch to backend binaries before starting async runtime + try_dispatch_to_backend(); + + // If no backend dispatcher matched, run CLI normally + let rt = tokio::runtime::Runtime::new()?; + rt.block_on(main_impl()) +}