Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .beads/issues.jsonl
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{"id":"terraphim-ai-2sz","title":"Add embedded device settings fallback to terraphim-cli","description":"Evaluate and implement an embedded DeviceSettings fallback (similar to terraphim-agent) so terraphim-cli doesn't fail on missing settings.","status":"open","priority":2,"issue_type":"task","owner":"alex@metacortex.engineer","created_at":"2026-02-10T08:23:48.689656434Z","created_by":"AlexMikhalev","updated_at":"2026-02-10T08:23:48.689656434Z"}
{"id":"terraphim-ai-cbm","title":"Clarify terraphim-agent TUI offline/server requirement","description":"Determine whether terraphim-agent TUI is expected to work fully offline or requires a running server; document requirement and adjust behavior if needed.","status":"open","priority":2,"issue_type":"task","owner":"alex@metacortex.engineer","created_at":"2026-02-10T08:23:40.310825316Z","created_by":"AlexMikhalev","updated_at":"2026-02-10T08:23:45.675303405Z"}
{"id":"terraphim-ai-tcw","title":"Define required feature parity between terraphim-agent and terraphim-cli","description":"Decide which commands/features must exist in both CLIs and document any intentional gaps for automation vs interactive use.","status":"open","priority":3,"issue_type":"task","owner":"alex@metacortex.engineer","created_at":"2026-02-10T08:23:51.548645229Z","created_by":"AlexMikhalev","updated_at":"2026-02-10T08:23:51.548645229Z"}
{"id":"terraphim-ai-2sz","title":"Add embedded device settings fallback to terraphim-cli","description":"Evaluate and implement an embedded DeviceSettings fallback (similar to terraphim-agent) so terraphim-cli doesn't fail on missing settings.","status":"open","priority":2,"issue_type":"task","owner":"alex@metacortex.engineer","created_at":"2026-02-10T08:23:48.689656434Z","created_by":"AlexMikhalev","updated_at":"2026-02-10T08:23:48.689656434Z","source_repo":".","compaction_level":0,"original_size":0}
{"id":"terraphim-ai-cbm","title":"Clarify terraphim-agent TUI offline/server requirement","description":"Determine whether terraphim-agent TUI is expected to work fully offline or requires a running server; document requirement and adjust behavior if needed.","design":"Phase 1/2 docs: docs/plans/terraphim-agent-tui-offline-server-research-2026-02-13.md and docs/plans/terraphim-agent-tui-offline-server-design-2026-02-13.md","acceptance_criteria":"Contract for fullscreen TUI vs REPL/offline is explicit in help/docs; actionable messaging when fullscreen TUI server is unreachable; tests cover mode behavior to prevent regressions.","notes":"Implemented on 2026-02-13: mode-contract wording in CLI/docs, fullscreen TUI server preflight with actionable repl fallback, and regression tests for help/non-TTY/server-failure paths. Validation: cargo fmt --package terraphim_agent; cargo clippy -p terraphim_agent --all-targets -- -D warnings; cargo test -p terraphim_agent --test offline_mode_tests; cargo test -p terraphim_agent --test server_mode_tests test_server_mode_config_show; targeted unit tests in main.rs for URL resolution and error messaging.","status":"closed","priority":2,"issue_type":"task","owner":"alex@metacortex.engineer","created_at":"2026-02-10T08:23:40.310825316Z","created_by":"AlexMikhalev","updated_at":"2026-02-13T14:41:42.093162011Z","closed_at":"2026-02-13T14:41:42.093136090Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0}
{"id":"terraphim-ai-tcw","title":"Define required feature parity between terraphim-agent and terraphim-cli","description":"Decide which commands/features must exist in both CLIs and document any intentional gaps for automation vs interactive use.","status":"open","priority":3,"issue_type":"task","owner":"alex@metacortex.engineer","created_at":"2026-02-10T08:23:51.548645229Z","created_by":"AlexMikhalev","updated_at":"2026-02-10T08:23:51.548645229Z","source_repo":".","compaction_level":0,"original_size":0}
3 changes: 0 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,12 @@ pip install terraphim-automata

### 🦀 Rust CLI/TUI
```bash
# Interactive mode with full features
# Fullscreen TUI (requires a running server at TERRAPHIM_SERVER or localhost:8000)
terraphim-agent

# Offline-capable REPL
terraphim-agent repl

# Search commands
terraphim-agent search "Rust async programming"
terraphim-agent search --role engineer "microservices"
Expand Down Expand Up @@ -382,9 +385,12 @@ $ terraphim-agent update
# Build with all features
cargo build -p terraphim_agent --features repl-full --release

# Launch interactive REPL
# Launch fullscreen TUI (server-backed)
./target/release/terraphim-agent

# Launch REPL (offline-capable by default)
./target/release/terraphim-agent repl

# Available REPL commands:
/help # Show all commands
/search "query" # Semantic search
Expand Down Expand Up @@ -418,8 +424,8 @@ Search across AI coding assistant history from Claude Code, Cursor, and Aider se
# Install with session search support
cargo install terraphim_agent --features repl-full

# Launch REPL
terraphim-agent
# Launch REPL (offline-capable)
terraphim-agent repl

# In REPL:
/sessions sources # Detect available session sources (e.g., 419 Claude Code sessions)
Expand Down
13 changes: 0 additions & 13 deletions crates/terraphim_agent/docs/src/kg/test_ranking_kg.md

This file was deleted.

82 changes: 69 additions & 13 deletions crates/terraphim_agent/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,13 @@ enum LogicalOperatorCli {
fn show_usage_info() {
println!("Terraphim AI Agent v{}", env!("CARGO_PKG_VERSION"));
println!();
println!("Interactive Mode (requires TTY):");
println!(" terraphim-agent # Start REPL or TUI");
println!(" terraphim-agent repl # Explicit REPL mode");
println!("Interactive Modes (requires TTY):");
println!(" terraphim-agent # Start fullscreen TUI (requires running server)");
println!(" terraphim-agent repl # Start REPL (offline-capable by default)");
println!(" terraphim-agent repl --server # Start REPL in server mode");
println!();
println!("Common Commands:");
println!(" search <query> # Search documents");
println!(" search <query> # Search documents (offline-capable by default)");
println!(" roles list # List available roles");
println!(" config show # Show configuration");
println!(" replace <text> # Replace terms using thesaurus");
Expand All @@ -62,6 +63,38 @@ fn show_usage_info() {
println!(" terraphim-agent help # Show command-specific help");
}

fn resolve_tui_server_url(explicit: Option<&str>) -> String {
let env_server = std::env::var("TERRAPHIM_SERVER").ok();
resolve_tui_server_url_with_env(explicit, env_server.as_deref())
}

fn resolve_tui_server_url_with_env(explicit: Option<&str>, env_server: Option<&str>) -> String {
explicit
.map(ToOwned::to_owned)
.or_else(|| env_server.map(ToOwned::to_owned))
.unwrap_or_else(|| "http://localhost:8000".to_string())
}

fn tui_server_requirement_error(url: &str, cause: &anyhow::Error) -> anyhow::Error {
anyhow::anyhow!(
"Fullscreen TUI requires a running Terraphim server at {}. \
Start terraphim_server or use offline mode with `terraphim-agent repl`. \
Connection error: {}",
url,
cause
)
}

fn ensure_tui_server_reachable(
runtime: &tokio::runtime::Runtime,
api: &ApiClient,
url: &str,
) -> Result<()> {
runtime
.block_on(api.health())
.map_err(|err| tui_server_requirement_error(url, &err))
}

impl From<LogicalOperatorCli> for LogicalOperator {
fn from(op: LogicalOperatorCli) -> Self {
match op {
Expand Down Expand Up @@ -362,6 +395,28 @@ mod tests {
let text2 = "use npm, please";
assert!(is_at_word_boundary(text2, 4, 7)); // "npm" followed by comma
}

#[test]
fn resolve_tui_server_url_uses_explicit_then_env_then_default() {
let explicit = resolve_tui_server_url_with_env(Some("http://explicit:9000"), None);
assert_eq!(explicit, "http://explicit:9000");

let from_env = resolve_tui_server_url_with_env(None, Some("http://env:7000"));
assert_eq!(from_env, "http://env:7000");

let defaulted = resolve_tui_server_url_with_env(None, None);
assert_eq!(defaulted, "http://localhost:8000");
}

#[test]
fn tui_server_requirement_error_mentions_repl_fallback() {
let cause = anyhow::anyhow!("connect error");
let err = tui_server_requirement_error("http://localhost:8000", &cause);
let msg = err.to_string();
assert!(msg.contains("Fullscreen TUI requires a running Terraphim server"));
assert!(msg.contains("terraphim-agent repl"));
assert!(msg.contains("http://localhost:8000"));
}
}

#[derive(clap::ValueEnum, Debug, Clone, Default)]
Expand All @@ -376,7 +431,11 @@ pub enum OutputFormat {
}

#[derive(Parser, Debug)]
#[command(name = "terraphim-agent", version, about = "Terraphim TUI interface")]
#[command(
name = "terraphim-agent",
version,
about = "Terraphim Agent: server-backed fullscreen TUI with offline-capable REPL and CLI commands"
)]
struct Cli {
/// Use server API mode instead of self-contained offline mode
#[arg(long, default_value_t = false)]
Expand Down Expand Up @@ -627,9 +686,8 @@ fn main() -> Result<()> {
}
}
fn run_tui_offline_mode(transparent: bool) -> Result<()> {
// Note: TUI mode currently requires a running server to connect to.
// It will try TERRAPHIM_SERVER env var, or default to http://localhost:8000.
// For fully offline operation, use 'terraphim-agent repl' instead.
// Fullscreen TUI mode requires a running server.
// For offline operation, use `terraphim-agent repl`.
run_tui(None, transparent)
}

Expand Down Expand Up @@ -1895,15 +1953,13 @@ fn ui_loop(
let mut current_role = String::from("Terraphim Engineer"); // Default to Terraphim Engineer
let mut selected_result_index = 0;
let mut view_mode = ViewMode::Search;
// Use provided server_url, then TERRAPHIM_SERVER env var, then default to localhost
let effective_url = server_url.unwrap_or_else(|| {
std::env::var("TERRAPHIM_SERVER").unwrap_or_else(|_| "http://localhost:8000".to_string())
});
let api = ApiClient::new(effective_url);
let effective_url = resolve_tui_server_url(server_url.as_deref());
let api = ApiClient::new(effective_url.clone());

// Create a tokio runtime for this TUI session
// We need a local runtime because we're in a synchronous function (terminal event loop)
let rt = tokio::runtime::Runtime::new()?;
ensure_tui_server_reachable(&rt, &api, &effective_url)?;

// Initialize terms from rolegraph (selected role)
if let Ok(cfg) = rt.block_on(async { api.get_config().await }) {
Expand Down
16 changes: 15 additions & 1 deletion crates/terraphim_agent/tests/offline_mode_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ async fn test_offline_help_command() -> Result<()> {

assert_eq!(code, 0, "Help command should succeed");
assert!(
stdout.contains("Terraphim TUI interface"),
stdout.contains("server-backed fullscreen TUI"),
"Should show main help"
);
assert!(stdout.contains("--server"), "Should show server flag");
Expand All @@ -65,6 +65,20 @@ async fn test_offline_help_command() -> Result<()> {
Ok(())
}

#[tokio::test]
#[serial]
async fn test_non_tty_usage_clarifies_mode_contract() -> Result<()> {
let (stdout, _stderr, code) = run_offline_command(&[])?;

assert_eq!(code, 0, "Non-TTY usage should exit cleanly");
assert!(stdout.contains("Interactive Modes (requires TTY)"));
assert!(stdout.contains("fullscreen TUI (requires running server)"));
assert!(stdout.contains("repl"));
assert!(stdout.contains("offline-capable by default"));

Ok(())
}

#[tokio::test]
#[serial]
async fn test_offline_config_show() -> Result<()> {
Expand Down
5 changes: 0 additions & 5 deletions crates/terraphim_tinyclaw/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@ name = "terraphim-tinyclaw"
path = "src/main.rs"

[dependencies]
# Terraphim crates
terraphim_multi_agent = { path = "../terraphim_multi_agent" }
terraphim_config = { path = "../terraphim_config" }
terraphim_automata = { path = "../terraphim_automata" }

# Async runtime
tokio = { workspace = true }
tokio-util = { version = "0.7", features = ["rt"] }
Expand Down
Loading
Loading