use crate::custom_plugin_host::{unix_timestamp, CustomPluginHost};
use std::sync::Arc;
use thenodes::plugin_host::PluginContext;
/// Application-specific command handler for the prompt interface
pub struct AppCommands {
host: Arc<CustomPluginHost>,
context: PluginContext,
}
impl AppCommands {
pub fn new(host: Arc<CustomPluginHost>, context: PluginContext) -> Self {
Self { host, context }
}
/// Handle application commands
pub async fn handle_command(
&self,
input: &str,
) -> Result<Option<String>, Box<dyn std::error::Error>> {
let parts: Vec<&str> = input.split_whitespace().collect();
if parts.is_empty() {
return Ok(None);
}
let command = parts[0];
let args = if parts.len() > 1 {
parts[1..].to_vec()
} else {
vec![]
};
match command {
// Application-specific commands
"help" | "?" => Ok(Some(self.show_help())),
"status" | "info" => {
let result = self.host.handle_custom_command("status", args).await?;
Ok(Some(result))
}
"sessions" => {
let result = self.host.handle_custom_command("sessions", args).await?;
Ok(Some(result))
}
"plugins" => {
let result = self.host.handle_custom_command("plugins", args).await?;
Ok(Some(result))
}
"data" => {
let result = self.host.handle_custom_command("data", args).await?;
Ok(Some(result))
}
"send" => self.handle_send_command(args).await,
"session" => self.handle_session_command(args).await,
// Let custom plugins handle unknown commands
_ => match self.host.handle_custom_command(command, args).await {
Ok(result) => Ok(Some(result)),
Err(_) => Ok(Some(format!(
"❓ Unknown command: '{}'. Type 'help' for available commands.",
command
))),
},
}
}
fn show_help(&self) -> String {
r#"
🎮 {{APP_NAME}} Commands:
📊 Information:
help, ? - Show this help message
status, info - Show host status
sessions - List active sessions
plugins - List loaded custom plugins
📂 Data Management:
data set <key> <value> - Store custom data
data get <key> - Retrieve custom data
data list - List all custom data
📤 Messaging:
send <type> <target> <payload> - Send custom message
🎯 Session Management:
session create <id> - Create new session
session destroy <id> - Destroy session
session list - List sessions (same as 'sessions')
🔌 Plugin Commands:
(Custom plugin commands will appear here when plugins are loaded)
💡 Tips:
- Commands are case-sensitive
- Use Ctrl+C to exit
"#
.trim()
.to_string()
}
async fn handle_send_command(
&self,
args: Vec<&str>,
) -> Result<Option<String>, Box<dyn std::error::Error>> {
if args.len() < 3 {
return Ok(Some(
"Usage: send <message_type> <target> <payload_json>".to_string(),
));
}
let msg_type = args[0];
let target = args[1];
let payload_str = args[2..].join(" ");
// Try to parse payload as JSON
let payload: serde_json::Value = match serde_json::from_str(&payload_str) {
Ok(json) => json,
Err(_) => {
// If not valid JSON, treat as simple string
serde_json::Value::String(payload_str)
}
};
self.host
.send_custom_message(msg_type, payload, target, &self.context)
.await?;
Ok(Some(format!("📤 Sent {} message to {}", msg_type, target)))
}
async fn handle_session_command(
&self,
args: Vec<&str>,
) -> Result<Option<String>, Box<dyn std::error::Error>> {
if args.is_empty() {
return Ok(Some(
"Usage: session [create <id> | destroy <id> | list]".to_string(),
));
}
match args[0] {
"create" if args.len() >= 2 => {
let session_id = args[1];
let payload = serde_json::json!({
"session_id": session_id,
"timestamp": unix_timestamp()
});
self.host
.send_custom_message("session_create", payload, "*", &self.context)
.await?;
Ok(Some(format!("🎯 Creating session: {}", session_id)))
}
"destroy" if args.len() >= 2 => {
let session_id = args[1];
let payload = serde_json::json!({
"session_id": session_id,
"timestamp": unix_timestamp()
});
self.host
.send_custom_message("session_destroy", payload, "*", &self.context)
.await?;
Ok(Some(format!("🗑️ Destroying session: {}", session_id)))
}
"list" => {
let result = self.host.handle_custom_command("sessions", vec![]).await?;
Ok(Some(result))
}
_ => Ok(Some(
"Usage: session [create <id> | destroy <id> | list]".to_string(),
)),
}
}
}
// Integration with TheNodes prompt system
impl AppCommands {
/// Handle prompt input - this integrates with TheNodes' prompt system
pub async fn handle_prompt_input(
&self,
input: &str,
) -> Result<String, Box<dyn std::error::Error>> {
match self.handle_command(input).await? {
Some(response) => Ok(response),
None => Ok("".to_string()),
}
}
}