Compare commits

2 Commits
Author SHA1 Message Date
JMR-dev 728c79cb86 crate updates 2026-05-30 21:31:29 -05:00
JMR-dev 0e4c54958f removed Gemini CLI references - added AntiGravity CLI 2026-05-30 20:13:01 -05:00
9 changed files with 1027 additions and 307 deletions
Generated
+1001 -281
View File
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -2,20 +2,20 @@
name = "secret-agent" name = "secret-agent"
version = "0.1.0" version = "0.1.0"
edition = "2024" edition = "2024"
description = "Rust TUI/CLI wrapper for Claude, Gemini, Codex, and Copilot with SQLite history" description = "Rust TUI/CLI wrapper for Claude, Antigravity, Codex, and Copilot with SQLite history"
[dependencies] [dependencies]
anyhow = "1.0" anyhow = "1.0"
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "0.4", features = ["serde"] }
clap = { version = "4.5", features = ["derive"] } clap = { version = "4.5", features = ["derive"] }
crossterm = { version = "0.28", features = ["event-stream"] } crossterm = { version = "^0.29.0", features = ["event-stream"] }
futures = "0.3" futures = "0.3"
ratatui = "0.29" ratatui = "0.30"
rusqlite = { version = "0.32", features = ["bundled"] } rusqlite = { version = "^0.40.0", features = ["bundled"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
serde_yaml = "0.9" serde_yaml = "0.9"
shell-words = "1.1" shell-words = "1.1"
tokio = { version = "1.43", features = ["full"] } tokio = { version = "1.43", features = ["full"] }
uuid = { version = "1.11", features = ["serde", "v7"] } uuid = { version = "1.11", features = ["serde", "v7"] }
which = "7.0" which = "^8.0.2"
+1 -1
View File
@@ -19,7 +19,7 @@ except ModuleNotFoundError as exc: # pragma: no cover - hard failure on old Pyt
REPO_ROOT = Path(__file__).resolve().parents[1] REPO_ROOT = Path(__file__).resolve().parents[1]
DEFAULT_OUTPUT_DIR = REPO_ROOT / "target" / "debian" DEFAULT_OUTPUT_DIR = REPO_ROOT / "target" / "debian"
DEFAULT_DESCRIPTION = ( DEFAULT_DESCRIPTION = (
"Rust TUI/CLI wrapper for Claude, Gemini, Codex, and Copilot with SQLite history" "Rust TUI/CLI wrapper for Claude, Antigravity, Codex, and Copilot with SQLite history"
) )
DEFAULT_MAINTAINER = "Secret Agent Maintainers <noreply@example.com>" DEFAULT_MAINTAINER = "Secret Agent Maintainers <noreply@example.com>"
+4 -4
View File
@@ -20,7 +20,7 @@ pub struct CommandSpec {
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OutputMode { pub enum OutputMode {
PlainText, PlainText,
GeminiJson, AgyJson,
CodexJson, CodexJson,
} }
@@ -63,7 +63,7 @@ pub fn build_command(request: &AgentRequest) -> Result<CommandSpec> {
args.push(composed_prompt); args.push(composed_prompt);
tool_conversation_id_hint = Some(tool_conversation_id); tool_conversation_id_hint = Some(tool_conversation_id);
} }
ToolKind::Gemini => { ToolKind::Agy => {
args.push("-p".to_string()); args.push("-p".to_string());
args.push(composed_prompt); args.push(composed_prompt);
args.push("--output-format".to_string()); args.push("--output-format".to_string());
@@ -73,7 +73,7 @@ pub fn build_command(request: &AgentRequest) -> Result<CommandSpec> {
args.push(model.to_string()); args.push(model.to_string());
} }
args.extend(collect_extra_args(role, &request.extra_args)?); args.extend(collect_extra_args(role, &request.extra_args)?);
output_mode = OutputMode::GeminiJson; output_mode = OutputMode::AgyJson;
} }
ToolKind::Codex => { ToolKind::Codex => {
args.push("exec".to_string()); args.push("exec".to_string());
@@ -129,7 +129,7 @@ pub fn tool_notes(tool: ToolKind) -> &'static str {
ToolKind::Claude => { ToolKind::Claude => {
"supports model and effort directly; role markdown can be injected as a system prompt" "supports model and effort directly; role markdown can be injected as a system prompt"
} }
ToolKind::Gemini => { ToolKind::Agy => {
"supports model directly; role markdown is prepended to the task prompt" "supports model directly; role markdown is prepended to the task prompt"
} }
ToolKind::Codex => "supports model directly; role markdown is prepended to the task prompt", ToolKind::Codex => "supports model directly; role markdown is prepended to the task prompt",
+1 -1
View File
@@ -24,7 +24,7 @@ use uuid::Uuid;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[command(name = "secret-agent")] #[command(name = "secret-agent")]
#[command( #[command(
about = "Rust TUI/CLI wrapper for Claude, Gemini, Codex, and Copilot with SQLite history" about = "Rust TUI/CLI wrapper for Claude, Antigravity, Codex, and Copilot with SQLite history"
)] )]
struct Cli { struct Cli {
#[arg(long, global = true)] #[arg(long, global = true)]
+2 -2
View File
@@ -15,7 +15,7 @@ const CLAUDE_MODELS: &[&str] = &[
"claude-haiku-4-5", "claude-haiku-4-5",
]; ];
const GEMINI_MODELS: &[&str] = &[ const AGY_MODELS: &[&str] = &[
"auto", "auto",
"gemini-2.5-pro", "gemini-2.5-pro",
"gemini-2.5-flash", "gemini-2.5-flash",
@@ -90,7 +90,7 @@ fn is_model_available(tool: ToolKind, model: &str) -> bool {
ToolKind::Claude => { ToolKind::Claude => {
CLAUDE_MODELS.contains(&normalized.as_str()) || matches_claude_model_name(&normalized) CLAUDE_MODELS.contains(&normalized.as_str()) || matches_claude_model_name(&normalized)
} }
ToolKind::Gemini => GEMINI_MODELS.contains(&normalized.as_str()), ToolKind::Agy => AGY_MODELS.contains(&normalized.as_str()),
ToolKind::Codex => CODEX_MODELS.contains(&normalized.as_str()), ToolKind::Codex => CODEX_MODELS.contains(&normalized.as_str()),
ToolKind::Copilot => COPILOT_MODELS.contains(&normalized.as_str()), ToolKind::Copilot => COPILOT_MODELS.contains(&normalized.as_str()),
} }
+8 -8
View File
@@ -92,7 +92,7 @@ async fn run(
internal_tx.clone(), internal_tx.clone(),
)); ));
} }
OutputMode::GeminiJson | OutputMode::CodexJson => { OutputMode::AgyJson | OutputMode::CodexJson => {
tokio::spawn(read_structured_stream( tokio::spawn(read_structured_stream(
stdout, stdout,
command_spec.output_mode, command_spec.output_mode,
@@ -279,7 +279,7 @@ fn parse_structured_line(output_mode: OutputMode, line: &str) -> Result<ParsedSt
let value: Value = serde_json::from_str(line)?; let value: Value = serde_json::from_str(line)?;
let tool_conversation_id = find_tool_conversation_id(output_mode, &value); let tool_conversation_id = find_tool_conversation_id(output_mode, &value);
let display_text = match output_mode { let display_text = match output_mode {
OutputMode::GeminiJson => extract_gemini_display_text(&value), OutputMode::AgyJson => extract_agy_display_text(&value),
OutputMode::CodexJson => extract_codex_display_text(&value), OutputMode::CodexJson => extract_codex_display_text(&value),
OutputMode::PlainText => None, OutputMode::PlainText => None,
}; };
@@ -290,7 +290,7 @@ fn parse_structured_line(output_mode: OutputMode, line: &str) -> Result<ParsedSt
}) })
} }
fn extract_gemini_display_text(value: &Value) -> Option<String> { fn extract_agy_display_text(value: &Value) -> Option<String> {
let event_type = value let event_type = value
.get("type") .get("type")
.and_then(Value::as_str) .and_then(Value::as_str)
@@ -358,7 +358,7 @@ fn extract_codex_display_text(value: &Value) -> Option<String> {
fn find_tool_conversation_id(output_mode: OutputMode, value: &Value) -> Option<String> { fn find_tool_conversation_id(output_mode: OutputMode, value: &Value) -> Option<String> {
let keys = match output_mode { let keys = match output_mode {
OutputMode::GeminiJson => &["session_id", "sessionId"][..], OutputMode::AgyJson => &["session_id", "sessionId"][..],
OutputMode::CodexJson => &["thread_id", "threadId", "session_id", "sessionId"][..], OutputMode::CodexJson => &["thread_id", "threadId", "session_id", "sessionId"][..],
OutputMode::PlainText => return None, OutputMode::PlainText => return None,
}; };
@@ -469,15 +469,15 @@ mod tests {
} }
#[test] #[test]
fn parses_gemini_session_id() { fn parses_agy_session_id() {
let parsed = parse_structured_line( let parsed = parse_structured_line(
OutputMode::GeminiJson, OutputMode::AgyJson,
r#"{"type":"init","session_id":"gemini-session-1"}"#, r#"{"type":"init","session_id":"agy-session-1"}"#,
) )
.expect("structured line should parse"); .expect("structured line should parse");
assert_eq!( assert_eq!(
parsed.tool_conversation_id.as_deref(), parsed.tool_conversation_id.as_deref(),
Some("gemini-session-1") Some("agy-session-1")
); );
} }
+1 -1
View File
@@ -435,7 +435,7 @@ impl ConversationDraft {
fn parse_tool(tool: String) -> rusqlite::Result<ToolKind> { fn parse_tool(tool: String) -> rusqlite::Result<ToolKind> {
match tool.as_str() { match tool.as_str() {
"claude" => Ok(ToolKind::Claude), "claude" => Ok(ToolKind::Claude),
"gemini" => Ok(ToolKind::Gemini), "agy" => Ok(ToolKind::Agy),
"codex" => Ok(ToolKind::Codex), "codex" => Ok(ToolKind::Codex),
"copilot" => Ok(ToolKind::Copilot), "copilot" => Ok(ToolKind::Copilot),
_ => Err(rusqlite::Error::FromSqlConversionFailure( _ => Err(rusqlite::Error::FromSqlConversionFailure(
+4 -4
View File
@@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum ToolKind { pub enum ToolKind {
Claude, Claude,
Gemini, Agy,
Codex, Codex,
Copilot, Copilot,
} }
@@ -17,7 +17,7 @@ pub enum ToolKind {
impl ToolKind { impl ToolKind {
pub const ALL: [ToolKind; 4] = [ pub const ALL: [ToolKind; 4] = [
ToolKind::Claude, ToolKind::Claude,
ToolKind::Gemini, ToolKind::Agy,
ToolKind::Codex, ToolKind::Codex,
ToolKind::Copilot, ToolKind::Copilot,
]; ];
@@ -25,7 +25,7 @@ impl ToolKind {
pub fn command_name(self) -> &'static str { pub fn command_name(self) -> &'static str {
match self { match self {
ToolKind::Claude => "claude", ToolKind::Claude => "claude",
ToolKind::Gemini => "gemini", ToolKind::Agy => "agy",
ToolKind::Codex => "codex", ToolKind::Codex => "codex",
ToolKind::Copilot => "copilot", ToolKind::Copilot => "copilot",
} }
@@ -40,7 +40,7 @@ impl fmt::Display for ToolKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let label = match self { let label = match self {
ToolKind::Claude => "Claude", ToolKind::Claude => "Claude",
ToolKind::Gemini => "Gemini", ToolKind::Agy => "Antigravity",
ToolKind::Codex => "Codex", ToolKind::Codex => "Codex",
ToolKind::Copilot => "Copilot", ToolKind::Copilot => "Copilot",
}; };