2026-02-11 15:23:26 +00:00
|
|
|
//! Line-oriented diagnostic protocol for LLM-driven runtime investigation.
|
|
|
|
|
//!
|
feat: command interface — frontend-agnostic dispatch crate
Add swactor-command crate that decouples command dispatch from the
dashboard, enabling the same commands from REPL, REST, TUI, or any
future frontend.
- CommandRouter with dispatch(), CommandHandler trait, CommandMeta
- CommandRequest/CommandResponse (serde-serializable JSON protocol)
- CommandContext with Arc<Runtime> + optional StatsEnricher trait
- 9 built-in commands extracted from investigate.rs:
help, overview, workers, worker, actors, actor, hot, phases, diff,
shutdown
- REPL line parser (parse_line) with positional arg mapping
- REST adapter (from_query_params) for HTTP query parameters
- Dashboard integration: StatsEnricher impl for StatsCollector,
investigate.rs refactored to thin CommandRouter wrapper,
server.rs updated to share CommandRouter across handler threads
- 18 behavioral tests in crates/command/tests/command_api.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 18:03:30 +00:00
|
|
|
//! Delegates all command logic to the `swactor-command` crate.
|
|
|
|
|
//!
|
2026-02-11 15:23:26 +00:00
|
|
|
//! Send text commands on stdin, receive JSON responses on stdout (one per line).
|
|
|
|
|
//! All human-readable diagnostics go to stderr.
|
|
|
|
|
//!
|
|
|
|
|
//! # Protocol
|
|
|
|
|
//!
|
|
|
|
|
//! ```text
|
|
|
|
|
//! → overview
|
|
|
|
|
//! ← {"ok":true,"command":"overview","data":{"workers":4,"actors":120,...}}
|
|
|
|
|
//!
|
|
|
|
|
//! → hot 5
|
|
|
|
|
//! ← {"ok":true,"command":"hot","data":[{"address":"a1b2...","worker_id":2,"mailbox_depth":47},..]}
|
|
|
|
|
//!
|
|
|
|
|
//! → diff 2
|
|
|
|
|
//! ← {"ok":true,"command":"diff","data":{"elapsed_s":2.0,"delta_messages":8432,"msg_per_sec":4216.0,...}}
|
|
|
|
|
//! ```
|
|
|
|
|
|
2026-02-12 09:13:50 +00:00
|
|
|
use std::collections::HashMap;
|
2026-02-11 15:23:26 +00:00
|
|
|
use std::io::{self, BufRead, Write};
|
|
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
|
|
use swactor::runtime::Runtime;
|
feat: command interface — frontend-agnostic dispatch crate
Add swactor-command crate that decouples command dispatch from the
dashboard, enabling the same commands from REPL, REST, TUI, or any
future frontend.
- CommandRouter with dispatch(), CommandHandler trait, CommandMeta
- CommandRequest/CommandResponse (serde-serializable JSON protocol)
- CommandContext with Arc<Runtime> + optional StatsEnricher trait
- 9 built-in commands extracted from investigate.rs:
help, overview, workers, worker, actors, actor, hot, phases, diff,
shutdown
- REPL line parser (parse_line) with positional arg mapping
- REST adapter (from_query_params) for HTTP query parameters
- Dashboard integration: StatsEnricher impl for StatsCollector,
investigate.rs refactored to thin CommandRouter wrapper,
server.rs updated to share CommandRouter across handler threads
- 18 behavioral tests in crates/command/tests/command_api.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 18:03:30 +00:00
|
|
|
use swactor_command::{CommandContext, CommandRouter};
|
2026-02-11 15:23:26 +00:00
|
|
|
|
|
|
|
|
use crate::collector::StatsCollector;
|
|
|
|
|
|
|
|
|
|
/// Run the investigate REPL. Blocks until stdin is closed or `quit` is received.
|
|
|
|
|
pub fn run_investigate(runtime: Arc<Runtime>, collector: Arc<StatsCollector>) -> io::Result<()> {
|
feat: command interface — frontend-agnostic dispatch crate
Add swactor-command crate that decouples command dispatch from the
dashboard, enabling the same commands from REPL, REST, TUI, or any
future frontend.
- CommandRouter with dispatch(), CommandHandler trait, CommandMeta
- CommandRequest/CommandResponse (serde-serializable JSON protocol)
- CommandContext with Arc<Runtime> + optional StatsEnricher trait
- 9 built-in commands extracted from investigate.rs:
help, overview, workers, worker, actors, actor, hot, phases, diff,
shutdown
- REPL line parser (parse_line) with positional arg mapping
- REST adapter (from_query_params) for HTTP query parameters
- Dashboard integration: StatsEnricher impl for StatsCollector,
investigate.rs refactored to thin CommandRouter wrapper,
server.rs updated to share CommandRouter across handler threads
- 18 behavioral tests in crates/command/tests/command_api.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 18:03:30 +00:00
|
|
|
let router = CommandRouter::with_builtins();
|
|
|
|
|
let ctx = CommandContext::with_enricher(runtime, collector);
|
|
|
|
|
|
2026-02-11 15:23:26 +00:00
|
|
|
let stdin = io::stdin();
|
|
|
|
|
let mut stdout = io::stdout();
|
|
|
|
|
|
|
|
|
|
eprintln!("swactor investigate protocol ready — send `help` for commands");
|
|
|
|
|
|
|
|
|
|
for line in stdin.lock().lines() {
|
|
|
|
|
let line = line?;
|
|
|
|
|
let line = line.trim();
|
|
|
|
|
if line.is_empty() {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
feat: command interface — frontend-agnostic dispatch crate
Add swactor-command crate that decouples command dispatch from the
dashboard, enabling the same commands from REPL, REST, TUI, or any
future frontend.
- CommandRouter with dispatch(), CommandHandler trait, CommandMeta
- CommandRequest/CommandResponse (serde-serializable JSON protocol)
- CommandContext with Arc<Runtime> + optional StatsEnricher trait
- 9 built-in commands extracted from investigate.rs:
help, overview, workers, worker, actors, actor, hot, phases, diff,
shutdown
- REPL line parser (parse_line) with positional arg mapping
- REST adapter (from_query_params) for HTTP query parameters
- Dashboard integration: StatsEnricher impl for StatsCollector,
investigate.rs refactored to thin CommandRouter wrapper,
server.rs updated to share CommandRouter across handler threads
- 18 behavioral tests in crates/command/tests/command_api.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 18:03:30 +00:00
|
|
|
if line == "quit" || line == "exit" {
|
2026-02-12 09:13:50 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
feat: command interface — frontend-agnostic dispatch crate
Add swactor-command crate that decouples command dispatch from the
dashboard, enabling the same commands from REPL, REST, TUI, or any
future frontend.
- CommandRouter with dispatch(), CommandHandler trait, CommandMeta
- CommandRequest/CommandResponse (serde-serializable JSON protocol)
- CommandContext with Arc<Runtime> + optional StatsEnricher trait
- 9 built-in commands extracted from investigate.rs:
help, overview, workers, worker, actors, actor, hot, phases, diff,
shutdown
- REPL line parser (parse_line) with positional arg mapping
- REST adapter (from_query_params) for HTTP query parameters
- Dashboard integration: StatsEnricher impl for StatsCollector,
investigate.rs refactored to thin CommandRouter wrapper,
server.rs updated to share CommandRouter across handler threads
- 18 behavioral tests in crates/command/tests/command_api.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 18:03:30 +00:00
|
|
|
let req = swactor_command::parse_line(line);
|
|
|
|
|
let resp = router.dispatch(&req, &ctx);
|
2026-02-11 15:23:26 +00:00
|
|
|
|
feat: command interface — frontend-agnostic dispatch crate
Add swactor-command crate that decouples command dispatch from the
dashboard, enabling the same commands from REPL, REST, TUI, or any
future frontend.
- CommandRouter with dispatch(), CommandHandler trait, CommandMeta
- CommandRequest/CommandResponse (serde-serializable JSON protocol)
- CommandContext with Arc<Runtime> + optional StatsEnricher trait
- 9 built-in commands extracted from investigate.rs:
help, overview, workers, worker, actors, actor, hot, phases, diff,
shutdown
- REPL line parser (parse_line) with positional arg mapping
- REST adapter (from_query_params) for HTTP query parameters
- Dashboard integration: StatsEnricher impl for StatsCollector,
investigate.rs refactored to thin CommandRouter wrapper,
server.rs updated to share CommandRouter across handler threads
- 18 behavioral tests in crates/command/tests/command_api.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 18:03:30 +00:00
|
|
|
stdout.write_all(resp.to_json_line().as_bytes())?;
|
2026-02-11 15:23:26 +00:00
|
|
|
stdout.write_all(b"\n")?;
|
|
|
|
|
stdout.flush()?;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-12 09:13:50 +00:00
|
|
|
/// Dispatch an investigate command from HTTP query parameters.
|
|
|
|
|
///
|
feat: command interface — frontend-agnostic dispatch crate
Add swactor-command crate that decouples command dispatch from the
dashboard, enabling the same commands from REPL, REST, TUI, or any
future frontend.
- CommandRouter with dispatch(), CommandHandler trait, CommandMeta
- CommandRequest/CommandResponse (serde-serializable JSON protocol)
- CommandContext with Arc<Runtime> + optional StatsEnricher trait
- 9 built-in commands extracted from investigate.rs:
help, overview, workers, worker, actors, actor, hot, phases, diff,
shutdown
- REPL line parser (parse_line) with positional arg mapping
- REST adapter (from_query_params) for HTTP query parameters
- Dashboard integration: StatsEnricher impl for StatsCollector,
investigate.rs refactored to thin CommandRouter wrapper,
server.rs updated to share CommandRouter across handler threads
- 18 behavioral tests in crates/command/tests/command_api.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 18:03:30 +00:00
|
|
|
/// Maps `?cmd=overview`, `?cmd=hot&n=10`, etc. to the appropriate command.
|
2026-02-12 09:13:50 +00:00
|
|
|
pub fn dispatch_command(
|
|
|
|
|
params: &HashMap<String, String>,
|
feat: command interface — frontend-agnostic dispatch crate
Add swactor-command crate that decouples command dispatch from the
dashboard, enabling the same commands from REPL, REST, TUI, or any
future frontend.
- CommandRouter with dispatch(), CommandHandler trait, CommandMeta
- CommandRequest/CommandResponse (serde-serializable JSON protocol)
- CommandContext with Arc<Runtime> + optional StatsEnricher trait
- 9 built-in commands extracted from investigate.rs:
help, overview, workers, worker, actors, actor, hot, phases, diff,
shutdown
- REPL line parser (parse_line) with positional arg mapping
- REST adapter (from_query_params) for HTTP query parameters
- Dashboard integration: StatsEnricher impl for StatsCollector,
investigate.rs refactored to thin CommandRouter wrapper,
server.rs updated to share CommandRouter across handler threads
- 18 behavioral tests in crates/command/tests/command_api.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 18:03:30 +00:00
|
|
|
router: &CommandRouter,
|
|
|
|
|
ctx: &CommandContext,
|
2026-02-12 09:13:50 +00:00
|
|
|
) -> String {
|
feat: command interface — frontend-agnostic dispatch crate
Add swactor-command crate that decouples command dispatch from the
dashboard, enabling the same commands from REPL, REST, TUI, or any
future frontend.
- CommandRouter with dispatch(), CommandHandler trait, CommandMeta
- CommandRequest/CommandResponse (serde-serializable JSON protocol)
- CommandContext with Arc<Runtime> + optional StatsEnricher trait
- 9 built-in commands extracted from investigate.rs:
help, overview, workers, worker, actors, actor, hot, phases, diff,
shutdown
- REPL line parser (parse_line) with positional arg mapping
- REST adapter (from_query_params) for HTTP query parameters
- Dashboard integration: StatsEnricher impl for StatsCollector,
investigate.rs refactored to thin CommandRouter wrapper,
server.rs updated to share CommandRouter across handler threads
- 18 behavioral tests in crates/command/tests/command_api.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 18:03:30 +00:00
|
|
|
let req = swactor_command::from_query_params(params);
|
|
|
|
|
router.dispatch(&req, ctx).to_json_line()
|
2026-02-11 15:23:26 +00:00
|
|
|
}
|