Skip to content
Open
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
75 changes: 72 additions & 3 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ uuid = { version = "1.22.0", features = [
whoami = "2.1.0"
fnv_rs = "0.4.3"
merge = { version = "0.2", features = ["derive"] }
rusqlite = { version = "0.38", features = ["bundled"] }
rmcp = { version = "0.10.0", features = [
"client",
"transport-sse-client-reqwest",
Expand Down
2 changes: 2 additions & 0 deletions crates/forge_main/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ open.workspace = true
humantime.workspace = true
num-format.workspace = true
atty = "0.2"
dirs = "6.0.0"
rusqlite.workspace = true
url.workspace = true
forge_embed.workspace = true
include_dir.workspace = true
Expand Down
3 changes: 2 additions & 1 deletion crates/forge_main/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod input;
mod model;
mod porcelain;
mod prompt;
pub mod rprompt_fast;
mod sandbox;
mod state;
mod stream_renderer;
Expand All @@ -17,7 +18,7 @@ mod title_display;
mod tools_display;
pub mod tracker;
mod ui;
mod utils;
pub mod utils;
mod vscode;
mod zsh;

Expand Down
72 changes: 71 additions & 1 deletion crates/forge_main/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use anyhow::Result;
use clap::Parser;
use forge_api::ForgeAPI;
use forge_domain::TitleFormat;
use forge_main::{Cli, Sandbox, TitleDisplayExt, UI, tracker};
use forge_main::{Cli, Sandbox, TitleDisplayExt, UI, rprompt_fast, tracker, utils};

#[tokio::main]
async fn main() -> Result<()> {
Expand Down Expand Up @@ -35,6 +35,76 @@ async fn main() -> Result<()> {
}));

// Initialize and run the UI

// Fast path: zsh rprompt without conversation ID - check BEFORE Cli::parse()
let args: Vec<String> = std::env::args().collect();
let has_conv = std::env::var("_FORGE_CONVERSATION_ID")
.ok()
.filter(|s| !s.trim().is_empty())
.is_some();
if args.len() >= 3 && args[1] == "zsh" && args[2] == "rprompt" && !has_conv {
println!(" %B%F{{240}}󱙺 FORGE%f%b");
return Ok(());
}

// Fast path: zsh rprompt WITH conversation ID - direct SQLite query
if args.len() >= 3
&& args[1] == "zsh"
&& args[2] == "rprompt"
&& has_conv
&& let Ok(conv_id) = std::env::var("_FORGE_CONVERSATION_ID")
{
let conv_id = conv_id.trim();
if !conv_id.is_empty() {
// Try fast path - if it fails, fall through to normal path
if let Some(data) = rprompt_fast::fetch_rprompt_data(conv_id) {
let use_nerd_font = std::env::var("NERD_FONT")
.or_else(|_| std::env::var("USE_NERD_FONT"))
.map(|v| v == "1")
.unwrap_or(true);

// Check if we have token count (active state) or just show inactive
if let Some(token_count) = data.token_count {
let icon = if use_nerd_font { "󱙺" } else { "" };
let count_str = utils::humanize_number(token_count);

// Active state: bright colors
print!(" %B%F{{15}}{} FORGE%f%b %B%F{{15}}{}%f%b", icon, count_str);

if let Some(cost) = data.cost {
let currency = std::env::var("FORGE_CURRENCY_SYMBOL")
.unwrap_or_else(|_| "$".to_string());
let ratio: f64 = std::env::var("FORGE_CURRENCY_CONVERSION_RATE")
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(1.0);
print!(" %B%F{{2}}{}{:.2}%f%b", currency, cost * ratio);
}

if let Some(ref model) = data.model {
let model_icon = if use_nerd_font { "󰑙" } else { "" };
print!(" %F{{134}}{}{}", model_icon, model);
}

println!();
return Ok(());
} else {
// No token count - show inactive/dimmed state
let icon = if use_nerd_font { "󱙺" } else { "" };
let model_str = data.model.as_deref().unwrap_or("forge");
let model_icon = if use_nerd_font { "󰑙" } else { "" };

print!(
" %B%F{{240}}{} FORGE%f%b %F{{240}}{}{}%f",
icon, model_icon, model_str
);
println!();
return Ok(());
}
}
}
}

let mut cli = Cli::parse();

// Check if there's piped input
Expand Down
Loading
Loading