This commit is contained in:
Generated
+9
@@ -947,6 +947,7 @@ dependencies = [
|
||||
"maestro-cli",
|
||||
"maestro-daemon",
|
||||
"maestro-registry",
|
||||
"maestro-tui",
|
||||
"tokio",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
@@ -1080,6 +1081,14 @@ dependencies = [
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maestro-tui"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maestro-web"
|
||||
version = "0.1.0"
|
||||
|
||||
@@ -19,6 +19,7 @@ jsonwebtoken = { version = "9", default-features = false }
|
||||
libc = "0.2"
|
||||
maestro-config = { path = "crates/maestro-config" }
|
||||
maestro-protocol = { path = "crates/maestro-protocol" }
|
||||
maestro-tui = { path = "crates/maestro-tui" }
|
||||
nix = { version = "0.29", default-features = false, features = ["term", "signal"] }
|
||||
rand = "0.8"
|
||||
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls", "cookies", "stream"] }
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "maestro-tui"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
publish.workspace = true
|
||||
description = "Terminal UI client over the local maestro daemon's `/api/*` surface."
|
||||
|
||||
[dependencies]
|
||||
clap.workspace = true
|
||||
thiserror.workspace = true
|
||||
@@ -0,0 +1,40 @@
|
||||
//! Clap-derive subcommand definition for `maestro tui`.
|
||||
|
||||
#[derive(Debug, clap::Args)]
|
||||
pub struct TuiArgs {
|
||||
/// Override the local daemon's HTTP base URL (default `http://127.0.0.1:7070`).
|
||||
#[arg(long, env = "MAESTRO_DAEMON_URL")]
|
||||
pub daemon_url: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use clap::Parser;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
struct Harness {
|
||||
#[command(subcommand)]
|
||||
cmd: Cmd,
|
||||
}
|
||||
|
||||
#[derive(Debug, clap::Subcommand)]
|
||||
enum Cmd {
|
||||
Tui(TuiArgs),
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_with_daemon_url() {
|
||||
let h = Harness::try_parse_from(["maestro", "tui", "--daemon-url", "http://10.0.0.1:7070"])
|
||||
.unwrap();
|
||||
let Cmd::Tui(args) = h.cmd;
|
||||
assert_eq!(args.daemon_url.as_deref(), Some("http://10.0.0.1:7070"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_without_daemon_url() {
|
||||
let h = Harness::try_parse_from(["maestro", "tui"]).unwrap();
|
||||
let Cmd::Tui(args) = h.cmd;
|
||||
assert!(args.daemon_url.is_none());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
//! `maestro tui` — terminal UI client over the local daemon's `/api/*` surface.
|
||||
//!
|
||||
//! Design: `docs/superpowers/specs/2026-05-28-maestro-tui-design.md`
|
||||
//! Implementation: `docs/superpowers/plans/2026-05-28-maestro-tui.md`
|
||||
//!
|
||||
//! Phase 1 (NAP-276) scaffolds the crate and a `Tui` subcommand stub. The real
|
||||
//! event loop, rendering, and `/api/*` plumbing land in NAP-277 onward.
|
||||
|
||||
#![deny(missing_debug_implementations)]
|
||||
|
||||
pub mod cli;
|
||||
|
||||
/// Inputs for [`run`]. Built by the umbrella binary from the parsed
|
||||
/// `TuiArgs` plus any global flags.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RunConfig {
|
||||
/// HTTP base URL of the local daemon, e.g. `http://127.0.0.1:7070`.
|
||||
/// No trailing slash.
|
||||
pub daemon_url: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum TuiError {
|
||||
#[error("not implemented")]
|
||||
NotImplemented,
|
||||
}
|
||||
|
||||
/// Entry point. Phase-1 stub — returns `NotImplemented` so the subcommand
|
||||
/// dispatch path is exercisable end-to-end before the renderer lands.
|
||||
pub async fn run(_cfg: RunConfig) -> Result<(), TuiError> {
|
||||
Err(TuiError::NotImplemented)
|
||||
}
|
||||
@@ -12,10 +12,11 @@ name = "maestro"
|
||||
path = "src/main.rs"
|
||||
|
||||
[features]
|
||||
default = ["cli", "daemon", "registry"]
|
||||
default = ["cli", "daemon", "registry", "tui"]
|
||||
cli = ["dep:maestro-cli"]
|
||||
daemon = ["dep:maestro-daemon"]
|
||||
registry = ["dep:maestro-registry"]
|
||||
tui = ["dep:maestro-tui"]
|
||||
|
||||
[dependencies]
|
||||
clap.workspace = true
|
||||
@@ -24,3 +25,4 @@ tracing-subscriber.workspace = true
|
||||
maestro-cli = { path = "../maestro-cli", optional = true }
|
||||
maestro-daemon = { path = "../maestro-daemon", optional = true }
|
||||
maestro-registry = { path = "../maestro-registry", optional = true }
|
||||
maestro-tui = { path = "../maestro-tui", optional = true }
|
||||
|
||||
@@ -7,8 +7,13 @@
|
||||
//! cargo install maestro # default: cli + daemon + registry
|
||||
//! ```
|
||||
|
||||
#[cfg(not(any(feature = "cli", feature = "daemon", feature = "registry")))]
|
||||
compile_error!("at least one of the `cli`, `daemon`, `registry` features must be enabled");
|
||||
#[cfg(not(any(
|
||||
feature = "cli",
|
||||
feature = "daemon",
|
||||
feature = "registry",
|
||||
feature = "tui"
|
||||
)))]
|
||||
compile_error!("at least one of the `cli`, `daemon`, `registry`, `tui` features must be enabled");
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::process::ExitCode;
|
||||
@@ -73,6 +78,10 @@ enum Command {
|
||||
/// Always-on registry: presence index + session catalog.
|
||||
#[cfg(feature = "registry")]
|
||||
Registry,
|
||||
|
||||
/// Open the terminal UI.
|
||||
#[cfg(feature = "tui")]
|
||||
Tui(maestro_tui::cli::TuiArgs),
|
||||
}
|
||||
|
||||
fn main() -> ExitCode {
|
||||
@@ -153,6 +162,13 @@ async fn dispatch(cli: Cli) -> Result<(), Box<dyn std::error::Error>> {
|
||||
Command::Daemon { cmd } => maestro_daemon::cli::dispatch(cli.config, cmd).await?,
|
||||
#[cfg(feature = "registry")]
|
||||
Command::Registry => maestro_registry::run(cli.config).await?,
|
||||
#[cfg(feature = "tui")]
|
||||
Command::Tui(args) => {
|
||||
let daemon_url = args
|
||||
.daemon_url
|
||||
.unwrap_or_else(|| "http://127.0.0.1:7070".to_string());
|
||||
maestro_tui::run(maestro_tui::RunConfig { daemon_url }).await?
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user