first pass of merging in warp (doesn't build)
This commit is contained in:
@@ -5,7 +5,6 @@
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
|
||||
use ai::skills::SkillProvider;
|
||||
use enum_iterator::Sequence;
|
||||
@@ -14,7 +13,11 @@ use markdown_parser::parse_markdown;
|
||||
use pathfinder_color::ColorU;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smol_str::SmolStr;
|
||||
|
||||
use galaxy_cli::agent::Harness;
|
||||
use galaxy_completer::parsers::simple::top_level_command;
|
||||
use galaxy_editor::content::buffer::Buffer;
|
||||
use galaxy_editor::content::markdown::MarkdownStyle;
|
||||
use galaxy_util::path::EscapeChar;
|
||||
use galaxyui::{AppContext, SingletonEntity};
|
||||
|
||||
use crate::ai::agent::{AgentReviewCommentBatch, DiffSetHunk};
|
||||
@@ -24,8 +27,6 @@ use crate::code_review::comments::AttachedReviewCommentTarget;
|
||||
use crate::server::telemetry::CLIAgentType;
|
||||
use crate::ui_components::icons::Icon;
|
||||
use crate::workspaces::user_workspaces::UserWorkspaces;
|
||||
use galaxy_completer::parsers::simple::top_level_command;
|
||||
use galaxy_util::path::EscapeChar;
|
||||
|
||||
/// UID for the Uber team.
|
||||
/// See https://warp.metabaseapp.com/dashboard/1454?team_id=46347
|
||||
@@ -40,7 +41,7 @@ pub(crate) const GEMINI_BLUE: ColorU = ColorU {
|
||||
};
|
||||
|
||||
/// OpenAI brand color (dark gray/black)
|
||||
const OPENAI_COLOR: ColorU = ColorU {
|
||||
pub(crate) const OPENAI_COLOR: ColorU = ColorU {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
@@ -64,7 +65,7 @@ const DROID_COLOR: ColorU = ColorU {
|
||||
};
|
||||
|
||||
/// OpenCode brand color (gray, used for contrast calculation only)
|
||||
const OPENCODE_COLOR: ColorU = ColorU {
|
||||
pub(crate) const OPENCODE_COLOR: ColorU = ColorU {
|
||||
r: 128,
|
||||
g: 128,
|
||||
b: 128,
|
||||
@@ -87,6 +88,14 @@ const PI_COLOR: ColorU = ColorU {
|
||||
a: 255,
|
||||
};
|
||||
|
||||
/// Antigravity brand color (white, monochrome logo)
|
||||
const ANTIGRAVITY_COLOR: ColorU = ColorU {
|
||||
r: 255,
|
||||
g: 255,
|
||||
b: 255,
|
||||
a: 255,
|
||||
};
|
||||
|
||||
/// Auggie brand color (white, monochrome logo)
|
||||
const AUGGIE_COLOR: ColorU = ColorU {
|
||||
r: 255,
|
||||
@@ -103,7 +112,31 @@ const CURSOR_COLOR: ColorU = ColorU {
|
||||
a: 255,
|
||||
};
|
||||
|
||||
/// Represents a CLI agent (e.g., Claude Code, Gemini CLI, Codex, Amp, Droid, OpenCode, Copilot, Pi, Auggie, Cursor)
|
||||
/// Goose brand color (#101010, from Block's official Goose logo)
|
||||
const GOOSE_COLOR: ColorU = ColorU {
|
||||
r: 16,
|
||||
g: 16,
|
||||
b: 16,
|
||||
a: 255,
|
||||
};
|
||||
|
||||
/// Hermes brand color (Nous Research purple #7C3AED)
|
||||
const HERMES_PURPLE: ColorU = ColorU {
|
||||
r: 124,
|
||||
g: 58,
|
||||
b: 237,
|
||||
a: 255,
|
||||
};
|
||||
|
||||
/// Mistral brand orange (#FA520F)
|
||||
const MISTRAL_ORANGE: ColorU = ColorU {
|
||||
r: 250,
|
||||
g: 82,
|
||||
b: 15,
|
||||
a: 255,
|
||||
};
|
||||
|
||||
/// Represents a CLI agent (e.g., Claude Code, Gemini CLI, Codex, Amp, Droid, OpenCode, Copilot, Pi, Auggie, Cursor, Goose, Hermes, Mistral Vibe)
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Sequence, Serialize, Deserialize)]
|
||||
pub enum CLIAgent {
|
||||
Claude,
|
||||
@@ -116,6 +149,10 @@ pub enum CLIAgent {
|
||||
Pi,
|
||||
Auggie,
|
||||
CursorCli,
|
||||
Goose,
|
||||
Hermes,
|
||||
Vibe,
|
||||
Antigravity,
|
||||
/// Represents an unknown/custom CLI agent matched by user-configured regex patterns.
|
||||
Unknown,
|
||||
}
|
||||
@@ -134,6 +171,10 @@ impl CLIAgent {
|
||||
CLIAgent::Pi => "pi",
|
||||
CLIAgent::Auggie => "auggie",
|
||||
CLIAgent::CursorCli => "agent",
|
||||
CLIAgent::Goose => "goose",
|
||||
CLIAgent::Hermes => "hermes",
|
||||
CLIAgent::Vibe => "vibe",
|
||||
CLIAgent::Antigravity => "agy",
|
||||
CLIAgent::Unknown => "",
|
||||
}
|
||||
}
|
||||
@@ -152,6 +193,20 @@ impl CLIAgent {
|
||||
serde_json::from_value(name.into()).unwrap_or(CLIAgent::Unknown)
|
||||
}
|
||||
|
||||
/// Returns the [`CLIAgent`] corresponding to a cloud-agent [`Harness`] when it represents a
|
||||
/// third-party agent. Returns `None` for [`Harness::Oz`] (Warp's built-in harness has no
|
||||
/// distinct CLI agent identity).
|
||||
pub fn from_harness(harness: Harness) -> Option<Self> {
|
||||
match harness {
|
||||
Harness::Oz => None,
|
||||
Harness::Claude => Some(CLIAgent::Claude),
|
||||
Harness::Gemini => Some(CLIAgent::Gemini),
|
||||
Harness::OpenCode => Some(CLIAgent::OpenCode),
|
||||
Harness::Codex => Some(CLIAgent::Codex),
|
||||
Harness::Unknown => Some(CLIAgent::Unknown),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display_name(&self) -> &'static str {
|
||||
match self {
|
||||
CLIAgent::Claude => "Claude Code",
|
||||
@@ -164,6 +219,10 @@ impl CLIAgent {
|
||||
CLIAgent::Pi => "Pi",
|
||||
CLIAgent::Auggie => "Auggie",
|
||||
CLIAgent::CursorCli => "Cursor",
|
||||
CLIAgent::Goose => "Goose",
|
||||
CLIAgent::Hermes => "Hermes",
|
||||
CLIAgent::Vibe => "Mistral Vibe",
|
||||
CLIAgent::Antigravity => "Antigravity",
|
||||
CLIAgent::Unknown => "CLI Agent",
|
||||
}
|
||||
}
|
||||
@@ -181,6 +240,13 @@ impl CLIAgent {
|
||||
CLIAgent::Pi => Some(Icon::PiLogo),
|
||||
CLIAgent::Auggie => Some(Icon::AuggieLogo),
|
||||
CLIAgent::CursorCli => Some(Icon::CursorLogo),
|
||||
CLIAgent::Goose => Some(Icon::GooseLogo),
|
||||
CLIAgent::Hermes => None,
|
||||
// Vibe is recognized but ships without a brand asset. The brand color
|
||||
// still drives the toolbar tile; an `Icon::MistralLogo` can be wired
|
||||
// up in a follow-up once an officially licensed SVG is available.
|
||||
CLIAgent::Vibe => None,
|
||||
CLIAgent::Antigravity => Some(Icon::AntigravityLogo),
|
||||
CLIAgent::Unknown => None,
|
||||
}
|
||||
}
|
||||
@@ -208,6 +274,10 @@ impl CLIAgent {
|
||||
CLIAgent::Pi => &[SkillProvider::Agents],
|
||||
CLIAgent::Auggie => &[SkillProvider::Agents],
|
||||
CLIAgent::CursorCli => &[SkillProvider::Agents],
|
||||
CLIAgent::Goose => &[SkillProvider::Agents],
|
||||
CLIAgent::Hermes => &[SkillProvider::Agents],
|
||||
CLIAgent::Vibe => &[SkillProvider::Agents],
|
||||
CLIAgent::Antigravity => &[],
|
||||
CLIAgent::Unknown => &[],
|
||||
}
|
||||
}
|
||||
@@ -247,6 +317,10 @@ impl CLIAgent {
|
||||
CLIAgent::Pi => Some(PI_COLOR),
|
||||
CLIAgent::Auggie => Some(AUGGIE_COLOR),
|
||||
CLIAgent::CursorCli => Some(CURSOR_COLOR),
|
||||
CLIAgent::Goose => Some(GOOSE_COLOR),
|
||||
CLIAgent::Hermes => Some(HERMES_PURPLE),
|
||||
CLIAgent::Vibe => Some(MISTRAL_ORANGE),
|
||||
CLIAgent::Antigravity => Some(ANTIGRAVITY_COLOR),
|
||||
CLIAgent::Unknown => None,
|
||||
}
|
||||
}
|
||||
@@ -255,7 +329,9 @@ impl CLIAgent {
|
||||
/// Agents with light brand colors use a dark icon for contrast.
|
||||
pub fn brand_icon_color(&self) -> ColorU {
|
||||
match self {
|
||||
CLIAgent::Pi | CLIAgent::Auggie | CLIAgent::Droid => ColorU::new(0, 0, 0, 255),
|
||||
CLIAgent::Pi | CLIAgent::Auggie | CLIAgent::Droid | CLIAgent::Antigravity => {
|
||||
ColorU::new(0, 0, 0, 255)
|
||||
}
|
||||
_ => ColorU::white(),
|
||||
}
|
||||
}
|
||||
@@ -308,13 +384,15 @@ impl CLIAgent {
|
||||
let resolved_first_word = Self::extract_first_command(&resolved_command, escape_char)?;
|
||||
|
||||
// Check if resolved command matches any known CLI agent.
|
||||
// Also matches `aifx agent run claude` as Claude for Uber employees.
|
||||
// Also matches `aifx agent run claude` as Claude for Uber employees,
|
||||
// and the `vibe-acp` ACP-mode binary as Mistral Vibe.
|
||||
enum_iterator::all::<CLIAgent>()
|
||||
.filter(|agent| !matches!(agent, CLIAgent::Unknown))
|
||||
.find(|agent| {
|
||||
resolved_first_word == agent.command_prefix()
|
||||
|| (matches!(agent, CLIAgent::Claude)
|
||||
&& Self::is_aifx_agent_run_claude(&resolved_command, ctx))
|
||||
|| (matches!(agent, CLIAgent::Vibe) && resolved_first_word == "vibe-acp")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -362,7 +440,7 @@ pub fn build_review_prompt(review: &AgentReviewCommentBatch) -> String {
|
||||
line,
|
||||
..
|
||||
} => {
|
||||
let path = absolute_file_path.display();
|
||||
let path = absolute_file_path.display_path();
|
||||
match line {
|
||||
EditorLineLocation::Current { line_number, .. } => {
|
||||
let n = line_number.as_usize() + 1;
|
||||
@@ -382,10 +460,9 @@ pub fn build_review_prompt(review: &AgentReviewCommentBatch) -> String {
|
||||
}
|
||||
}
|
||||
AttachedReviewCommentTarget::File { absolute_file_path } => {
|
||||
let path = absolute_file_path.display();
|
||||
let abs_str = absolute_file_path.to_string_lossy();
|
||||
let path = absolute_file_path.display_path();
|
||||
let is_deleted = review.diff_set.iter().any(|(file_key, hunks)| {
|
||||
abs_str.ends_with(file_key.as_str())
|
||||
path.ends_with(file_key.as_str())
|
||||
&& !hunks.is_empty()
|
||||
&& hunks
|
||||
.iter()
|
||||
@@ -394,7 +471,7 @@ pub fn build_review_prompt(review: &AgentReviewCommentBatch) -> String {
|
||||
if is_deleted {
|
||||
format!("{path} (deleted file — see `git diff`)")
|
||||
} else {
|
||||
format!("{path}")
|
||||
path
|
||||
}
|
||||
}
|
||||
AttachedReviewCommentTarget::General => "General".to_string(),
|
||||
@@ -430,15 +507,14 @@ fn export_review_comment_for_cli_prompt(comment: &str) -> String {
|
||||
/// `<path> L<start>-L<end>` where `start` and `end` are 1-indexed and both
|
||||
/// ends are **inclusive**.
|
||||
pub fn build_diff_hunk_prompt(
|
||||
file_path: &Path,
|
||||
file_path: &str,
|
||||
start_line: usize,
|
||||
end_line: usize,
|
||||
lines_added: u32,
|
||||
lines_removed: u32,
|
||||
) -> String {
|
||||
let path = file_path.display();
|
||||
format!(
|
||||
"{path} L{start_line}-L{end_line} (+{lines_added} -{lines_removed}) \
|
||||
"{file_path} L{start_line}-L{end_line} (+{lines_added} -{lines_removed}) \
|
||||
-- run `git diff` to see the full context."
|
||||
)
|
||||
}
|
||||
@@ -507,6 +583,10 @@ impl From<CLIAgent> for CLIAgentType {
|
||||
CLIAgent::Pi => CLIAgentType::Pi,
|
||||
CLIAgent::Auggie => CLIAgentType::Auggie,
|
||||
CLIAgent::CursorCli => CLIAgentType::Cursor,
|
||||
CLIAgent::Goose => CLIAgentType::Goose,
|
||||
CLIAgent::Hermes => CLIAgentType::Hermes,
|
||||
CLIAgent::Vibe => CLIAgentType::Vibe,
|
||||
CLIAgent::Antigravity => CLIAgentType::Antigravity,
|
||||
CLIAgent::Unknown => CLIAgentType::Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user