-
Notifications
You must be signed in to change notification settings - Fork 53
feat(hrm): Add optional HRM AI agent management commands #693
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -41,6 +41,16 @@ wezterm-client.workspace = true | |
| wezterm-gui-subcommands.workspace = true | ||
| wezterm-term.workspace = true | ||
|
|
||
| # HRM AI - Optional premium agent management (enable with --features hrm) | ||
| hrm-ai = { git = "https://github.com/mikejmorgan-ai/hrm-ai-standalone.git", optional = true } | ||
| sqlx = { version = "0.7", features = ["runtime-tokio", "postgres"], optional = true } | ||
|
Comment on lines
+44
to
+46
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, let's examine the Cargo.toml file to see the current state
cat -n wezterm/Cargo.toml | head -60Repository: cxlinux-ai/cx-core Length of output: 2220 🏁 Script executed: # Also check if there are any branding violations in the file
rg -n "(cortex|cortexlinux)" wezterm/Cargo.tomlRepository: cxlinux-ai/cx-core Length of output: 44 🏁 Script executed: # Search for any related configuration or documentation mentioning hrm-ai
rg -n "hrm-ai|hrm_ai" wezterm/ --type toml --type yaml --type mdRepository: cxlinux-ai/cx-core Length of output: 257 Pin the 🔒 Suggested pinning-hrm-ai = { git = "https://github.com/mikejmorgan-ai/hrm-ai-standalone.git", optional = true }
+hrm-ai = { git = "https://github.com/mikejmorgan-ai/hrm-ai-standalone.git", rev = "<commit-sha>", optional = true }🤖 Prompt for AI Agents |
||
| tokio = { version = "1", features = ["full"], optional = true } | ||
| uuid = { version = "1.6", features = ["v4"], optional = true } | ||
|
|
||
| [features] | ||
| default = [] | ||
| hrm = ["dep:hrm-ai", "dep:sqlx", "dep:tokio", "dep:uuid"] | ||
|
|
||
| [target."cfg(unix)".dependencies] | ||
| termios.workspace = true | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,183 @@ | ||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||
| * Copyright (c) 2026 CX Linux | ||||||||||||||||||||||||||||||||||||||
| * Licensed under the Business Source License 1.1 | ||||||||||||||||||||||||||||||||||||||
| * You may not use this file except in compliance with the License. | ||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1
to
+5
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix the license header copyright holder. 📄 Suggested update- * Copyright (c) 2026 CX Linux
+ * Copyright (c) 2026 AI Venture Holdings LLCAs per coding guidelines, Include BSL 1.1 license header on all new files with copyright to AI Venture Holdings LLC. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| //! HRM AI Agent Termination Command | ||||||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||||||
| //! Safely terminates AI agents with confirmation and audit logging. | ||||||||||||||||||||||||||||||||||||||
| //! This module is only available when the `hrm` feature is enabled. | ||||||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||||||
| //! # Example | ||||||||||||||||||||||||||||||||||||||
| //! ```bash | ||||||||||||||||||||||||||||||||||||||
| //! # Terminate an agent by ID | ||||||||||||||||||||||||||||||||||||||
| //! cx fire abc123-def456 | ||||||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||||||
| //! # Force termination (skip confirmation) | ||||||||||||||||||||||||||||||||||||||
| //! cx fire abc123-def456 --force | ||||||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||||||
| //! # Terminate with reason | ||||||||||||||||||||||||||||||||||||||
| //! cx fire abc123-def456 --reason "Migrating to new server" | ||||||||||||||||||||||||||||||||||||||
| //! ``` | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+7
to
+22
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace inner doc comments to restore fmt/build and align comment policy. ✅ Suggested rewrite-//! HRM AI Agent Termination Command
-//!
-//! Safely terminates AI agents with confirmation and audit logging.
-//! This module is only available when the `hrm` feature is enabled.
-//!
-//! # Example
-//! ```bash
-//! # Terminate an agent by ID
-//! cx fire abc123-def456
-//!
-//! # Force termination (skip confirmation)
-//! cx fire abc123-def456 --force
-//!
-//! # Terminate with reason
-//! cx fire abc123-def456 --reason "Migrating to new server"
-//! ```
+// CX Terminal: WHY — provide a guarded termination flow with audit logging
+// when the premium HRM feature is enabled.As per coding guidelines, Code comments must explain WHY, never WHAT or HOW, and Rust: Mark CX additions with '// CX Terminal:' comment prefix. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| use anyhow::Result; | ||||||||||||||||||||||||||||||||||||||
| use clap::Parser; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| #[cfg(feature = "hrm")] | ||||||||||||||||||||||||||||||||||||||
| use hrm_ai::{ | ||||||||||||||||||||||||||||||||||||||
| fire::{AgentTerminationService, TerminationConfig}, | ||||||||||||||||||||||||||||||||||||||
| database::AgentRepository, | ||||||||||||||||||||||||||||||||||||||
| theme::SovereignTheme, | ||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| /// Terminate (fire) an AI agent | ||||||||||||||||||||||||||||||||||||||
| #[derive(Debug, Parser, Clone)] | ||||||||||||||||||||||||||||||||||||||
| pub struct FireCommand { | ||||||||||||||||||||||||||||||||||||||
| /// Agent ID to terminate | ||||||||||||||||||||||||||||||||||||||
| pub agent_id: String, | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| /// Skip confirmation prompt (dangerous) | ||||||||||||||||||||||||||||||||||||||
| #[arg(long, short = 'f')] | ||||||||||||||||||||||||||||||||||||||
| pub force: bool, | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| /// Reason for termination (for audit log) | ||||||||||||||||||||||||||||||||||||||
| #[arg(long, short = 'r')] | ||||||||||||||||||||||||||||||||||||||
| pub reason: Option<String>, | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| /// Graceful shutdown timeout in seconds | ||||||||||||||||||||||||||||||||||||||
| #[arg(long, default_value = "30")] | ||||||||||||||||||||||||||||||||||||||
| pub timeout: u64, | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| /// Output format: table, json | ||||||||||||||||||||||||||||||||||||||
| #[arg(long, default_value = "table")] | ||||||||||||||||||||||||||||||||||||||
| pub format: String, | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| impl FireCommand { | ||||||||||||||||||||||||||||||||||||||
| pub fn run(self) -> Result<()> { | ||||||||||||||||||||||||||||||||||||||
| #[cfg(feature = "hrm")] | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| run_fire_with_hrm(self) | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| #[cfg(not(feature = "hrm"))] | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); | ||||||||||||||||||||||||||||||||||||||
| println!(" 🔒 HRM AI Premium Feature"); | ||||||||||||||||||||||||||||||||||||||
| println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); | ||||||||||||||||||||||||||||||||||||||
| println!(); | ||||||||||||||||||||||||||||||||||||||
| println!(" The 'fire' command requires the HRM AI premium module."); | ||||||||||||||||||||||||||||||||||||||
| println!(); | ||||||||||||||||||||||||||||||||||||||
| println!(" To enable HRM AI capabilities, rebuild with:"); | ||||||||||||||||||||||||||||||||||||||
| println!(" cargo build --features hrm"); | ||||||||||||||||||||||||||||||||||||||
| println!(); | ||||||||||||||||||||||||||||||||||||||
| println!(" HRM AI Features:"); | ||||||||||||||||||||||||||||||||||||||
| println!(" • cx hire <agent-type> - Deploy AI agents"); | ||||||||||||||||||||||||||||||||||||||
| println!(" • cx fire <agent-id> - Terminate agents"); | ||||||||||||||||||||||||||||||||||||||
| println!(" • PostgreSQL integration for fleet management"); | ||||||||||||||||||||||||||||||||||||||
| println!(" • Enterprise compliance automation"); | ||||||||||||||||||||||||||||||||||||||
| println!(); | ||||||||||||||||||||||||||||||||||||||
| println!(" License: BSL 1.1 (Business Source License)"); | ||||||||||||||||||||||||||||||||||||||
| println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); | ||||||||||||||||||||||||||||||||||||||
| Ok(()) | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| #[cfg(feature = "hrm")] | ||||||||||||||||||||||||||||||||||||||
| fn run_fire_with_hrm(cmd: FireCommand) -> Result<()> { | ||||||||||||||||||||||||||||||||||||||
| use tokio::runtime::Runtime; | ||||||||||||||||||||||||||||||||||||||
| use std::time::Duration; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| let rt = Runtime::new()?; | ||||||||||||||||||||||||||||||||||||||
| rt.block_on(async { | ||||||||||||||||||||||||||||||||||||||
| let theme = SovereignTheme::new(); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Print header | ||||||||||||||||||||||||||||||||||||||
| theme.print_header("CX Linux Agent Termination"); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Get database URL from environment | ||||||||||||||||||||||||||||||||||||||
| let db_url = std::env::var("DATABASE_URL") | ||||||||||||||||||||||||||||||||||||||
| .unwrap_or_else(|_| "postgres://localhost/cx_agents".to_string()); | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+101
to
+102
|
||||||||||||||||||||||||||||||||||||||
| let db_url = std::env::var("DATABASE_URL") | |
| .unwrap_or_else(|_| "postgres://localhost/cx_agents".to_string()); | |
| let db_url = match std::env::var("DATABASE_URL") { | |
| Ok(url) => url, | |
| Err(_) => { | |
| eprintln!( | |
| "WARNING: DATABASE_URL is not set. Falling back to a local default \ | |
| postgres:// connection with sslmode=require.\n\ | |
| For production and enterprise deployments, explicitly configure a secure DATABASE_URL." | |
| ); | |
| "postgres://localhost/cx_agents?sslmode=require".to_string() | |
| } | |
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a hardcoded fallback for DATABASE_URL can lead to unexpected behavior. If the environment variable is not set, the command will silently try to connect to postgres://localhost/cx_agents, which might not exist or might be the wrong database. This could cause confusion or data corruption.
It's more robust to fail explicitly if DATABASE_URL is not set, forcing the user to configure the environment correctly. This can be achieved by using .context() from anyhow to provide a clear error message.
| let db_url = std::env::var("DATABASE_URL") | |
| .unwrap_or_else(|_| "postgres://localhost/cx_agents".to_string()); | |
| let db_url = std::env::var("DATABASE_URL") | |
| .context("DATABASE_URL environment variable must be set to connect to the agent database")?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inline comments should state intent (WHY) and use the CX prefix.
Comments like “Print header” and “Get database URL” are “what/how”; rephrase to intent or remove.
As per coding guidelines, Code comments must explain WHY, never WHAT or HOW, and Rust: Mark CX additions with '// CX Terminal:' comment prefix.
🤖 Prompt for AI Agents
In `@wezterm/src/cli/fire.rs` around lines 97 - 105, Replace the existing WHAT/HOW
comments above theme.print_header, the DATABASE_URL getenv, and
AgentRepository::new with CX-prefixed intent comments that explain WHY these
steps are necessary; specifically add comments like "// CX Terminal: explain why
we print the termination header (provide user context)" before
theme.print_header, "// CX Terminal: explain why we fall back to default
DATABASE_URL (ensure local dev connectivity)" near the db_url initialization,
and "// CX Terminal: explain why we construct AgentRepository (to fetch agent
termination metadata)" before AgentRepository::new to satisfy the guideline that
comments state intent and use the CX prefix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, let me check the file and the specific lines mentioned
cat -n wezterm/src/cli/fire.rs | head -150 | tail -50Repository: cxlinux-ai/cx-core
Length of output: 2259
🏁 Script executed:
# Get the context around lines 108-113
sed -n '90,130p' wezterm/src/cli/fire.rsRepository: cxlinux-ai/cx-core
Length of output: 1467
🏁 Script executed:
# Check the function signature and return type
sed -n '80,120p' wezterm/src/cli/fire.rsRepository: cxlinux-ai/cx-core
Length of output: 1416
🏁 Script executed:
# Check if anyhow is imported in this file
head -50 wezterm/src/cli/fire.rs | grep -E "^use|^extern"Repository: cxlinux-ai/cx-core
Length of output: 113
🏁 Script executed:
# Check how errors are handled elsewhere in the file
rg "Err\(|anyhow::" wezterm/src/cli/fire.rs -A 2Repository: cxlinux-ai/cx-core
Length of output: 100
Return a non-zero exit when the agent is missing.
Printing an error but returning Ok(()) makes automation treat failures as success. Use anyhow::anyhow!() to propagate the error instead, which is already imported in this file and aligns with the error handling pattern used elsewhere in the function.
🚫 Suggested error propagation
- None => {
- theme.print_error(&format!("Agent not found: {}", cmd.agent_id));
- return Ok(());
- }
+ None => {
+ theme.print_error(&format!("Agent not found: {}", cmd.agent_id));
+ return Err(anyhow::anyhow!("Agent not found: {}", cmd.agent_id));
+ }🤖 Prompt for AI Agents
In `@wezterm/src/cli/fire.rs` around lines 108 - 113, The code prints an error
when repo.get_agent(&cmd.agent_id).await? returns None but still returns Ok(());
change this to propagate a non-zero failure by returning
Err(anyhow::anyhow!(...)) instead of Ok(()). Replace the None branch that
currently calls theme.print_error(&format!("Agent not found: {}",
cmd.agent_id)); return Ok(()) with a call to theme.print_error(...) followed by
returning Err(anyhow::anyhow!("Agent not found: {}", cmd.agent_id)) so the
function exits with an error when the agent is missing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The git dependency lacks version pinning (no tag, branch, or rev). This can lead to non-reproducible builds and unexpected breaking changes. Consider pinning to a specific tag or commit hash, e.g.,
tag = \"v1.0.0\"orrev = \"abc123\".