feat: add gemini-acp provider, update docs on subscription models + improvements to codex (#8000)
Signed-off-by: Michael Neale <michael.neale@gmail.com>
This commit is contained in:
@@ -45,8 +45,9 @@ const OAUTH_TIMEOUT_SECS: u64 = 300;
|
||||
const HTML_AUTO_CLOSE_TIMEOUT_MS: u64 = 2000;
|
||||
|
||||
const CHATGPT_CODEX_PROVIDER_NAME: &str = "chatgpt_codex";
|
||||
pub const CHATGPT_CODEX_DEFAULT_MODEL: &str = "gpt-5.1-codex";
|
||||
pub const CHATGPT_CODEX_DEFAULT_MODEL: &str = "gpt-5.3-codex";
|
||||
pub const CHATGPT_CODEX_KNOWN_MODELS: &[&str] = &[
|
||||
"gpt-5.4",
|
||||
"gpt-5.3-codex",
|
||||
"gpt-5.2-codex",
|
||||
"gpt-5.1-codex",
|
||||
@@ -56,6 +57,14 @@ pub const CHATGPT_CODEX_KNOWN_MODELS: &[&str] = &[
|
||||
|
||||
const CHATGPT_CODEX_DOC_URL: &str = "https://openai.com/chatgpt";
|
||||
|
||||
const GPT_53_CODEX_TOOL_PREAMBLE: &str = "\
|
||||
You are a coding agent. You have access to tools to accomplish tasks. \
|
||||
Always use your tools to fulfill requests - do not just describe what you would do. \
|
||||
Keep going until the query is completely resolved before yielding back to the user. \
|
||||
Autonomously resolve the query using the tools available to you. \
|
||||
Do NOT guess or make up an answer. \
|
||||
Before making tool calls, send a brief message explaining what you're about to do.";
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ChatGptCodexAuthState {
|
||||
oauth_mutex: TokioMutex<()>,
|
||||
@@ -181,11 +190,16 @@ fn create_codex_request(
|
||||
) -> Result<Value> {
|
||||
let input_items = build_input_items(messages)?;
|
||||
|
||||
let instructions = match model_config.model_name.as_str() {
|
||||
"gpt-5.3-codex" => format!("{GPT_53_CODEX_TOOL_PREAMBLE}\n\n{system}"),
|
||||
_ => system.to_string(),
|
||||
};
|
||||
|
||||
let mut payload = json!({
|
||||
"model": model_config.model_name,
|
||||
"input": input_items,
|
||||
"store": false,
|
||||
"instructions": system,
|
||||
"instructions": instructions,
|
||||
});
|
||||
|
||||
let payload_obj = payload
|
||||
|
||||
@@ -589,7 +589,7 @@ impl ProviderDef for ClaudeCodeProvider {
|
||||
ProviderMetadata::new(
|
||||
CLAUDE_CODE_PROVIDER_NAME,
|
||||
"Claude Code CLI",
|
||||
"Requires claude CLI installed, no MCPs. Use Anthropic provider for full features.",
|
||||
"[Deprecated: use claude-acp instead] Requires claude CLI installed, no MCPs. Use claude-acp for ACP support with extensions.",
|
||||
CLAUDE_CODE_DEFAULT_MODEL,
|
||||
// Only a few agentic choices; fetched dynamically via fetch_supported_models.
|
||||
vec![],
|
||||
|
||||
@@ -598,7 +598,7 @@ impl ProviderDef for CodexProvider {
|
||||
ProviderMetadata::new(
|
||||
CODEX_PROVIDER_NAME,
|
||||
"OpenAI Codex CLI",
|
||||
"Execute OpenAI models via Codex CLI tool. Requires codex CLI installed.",
|
||||
"[Deprecated: use chatgpt_codex or codex-acp instead] Execute OpenAI models via Codex CLI tool. Requires codex CLI installed.",
|
||||
CODEX_DEFAULT_MODEL,
|
||||
CODEX_KNOWN_MODELS.to_vec(),
|
||||
CODEX_DOC_URL,
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
use anyhow::Result;
|
||||
use futures::future::BoxFuture;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::acp::{
|
||||
extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig, PermissionMapping,
|
||||
};
|
||||
use crate::config::search_path::SearchPaths;
|
||||
use crate::config::{Config, GooseMode};
|
||||
use crate::model::ModelConfig;
|
||||
use crate::providers::base::{ProviderDef, ProviderMetadata};
|
||||
|
||||
const GEMINI_ACP_PROVIDER_NAME: &str = "gemini-acp";
|
||||
pub const GEMINI_ACP_DEFAULT_MODEL: &str = "default";
|
||||
const GEMINI_ACP_DOC_URL: &str = "https://github.com/google-gemini/gemini-cli";
|
||||
|
||||
pub struct GeminiAcpProvider;
|
||||
|
||||
impl ProviderDef for GeminiAcpProvider {
|
||||
type Provider = AcpProvider;
|
||||
|
||||
fn metadata() -> ProviderMetadata {
|
||||
ProviderMetadata::new(
|
||||
GEMINI_ACP_PROVIDER_NAME,
|
||||
"Gemini CLI (ACP)",
|
||||
"ACP provider for Google's Gemini CLI. Install: npm install -g @google/gemini-cli",
|
||||
GEMINI_ACP_DEFAULT_MODEL,
|
||||
vec![],
|
||||
GEMINI_ACP_DOC_URL,
|
||||
vec![],
|
||||
)
|
||||
}
|
||||
|
||||
fn from_env(
|
||||
model: ModelConfig,
|
||||
extensions: Vec<crate::config::ExtensionConfig>,
|
||||
) -> BoxFuture<'static, Result<AcpProvider>> {
|
||||
Box::pin(async move {
|
||||
let config = Config::global();
|
||||
let command_name: String = config.get_gemini_cli_command().unwrap_or_default().into();
|
||||
let resolved_command = SearchPaths::builder().with_npm().resolve(&command_name)?;
|
||||
let goose_mode = config.get_goose_mode().unwrap_or(GooseMode::Auto);
|
||||
|
||||
let permission_mapping = PermissionMapping {
|
||||
allow_option_id: Some("allow".to_string()),
|
||||
reject_option_id: Some("reject".to_string()),
|
||||
rejected_tool_status: sacp::schema::ToolCallStatus::Failed,
|
||||
};
|
||||
|
||||
let mut args = vec!["--acp".to_string()];
|
||||
if model.model_name != "default" {
|
||||
args.push("--model".to_string());
|
||||
args.push(model.model_name.clone());
|
||||
}
|
||||
|
||||
let provider_config = AcpProviderConfig {
|
||||
command: resolved_command,
|
||||
args,
|
||||
env: vec![],
|
||||
env_remove: vec![],
|
||||
work_dir: std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")),
|
||||
mcp_servers: extension_configs_to_mcp_servers(&extensions),
|
||||
session_mode_id: Some(map_goose_mode(goose_mode)),
|
||||
permission_mapping,
|
||||
notification_callback: None,
|
||||
};
|
||||
|
||||
let metadata = Self::metadata();
|
||||
AcpProvider::connect(metadata.name, model, goose_mode, provider_config).await
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn map_goose_mode(goose_mode: GooseMode) -> String {
|
||||
match goose_mode {
|
||||
GooseMode::Auto => "yolo".to_string(),
|
||||
GooseMode::Approve => "default".to_string(),
|
||||
GooseMode::SmartApprove => "auto_edit".to_string(),
|
||||
GooseMode::Chat => "plan".to_string(),
|
||||
}
|
||||
}
|
||||
@@ -161,7 +161,7 @@ impl ProviderDef for GeminiCliProvider {
|
||||
ProviderMetadata::new(
|
||||
GEMINI_CLI_PROVIDER_NAME,
|
||||
"Gemini CLI",
|
||||
"Execute Gemini models via gemini CLI tool",
|
||||
"[Deprecated: use gemini-acp instead] Execute Gemini models via gemini CLI tool. Requires gemini CLI installed.",
|
||||
GEMINI_CLI_DEFAULT_MODEL,
|
||||
GEMINI_CLI_KNOWN_MODELS.to_vec(),
|
||||
GEMINI_CLI_DOC_URL,
|
||||
|
||||
@@ -14,6 +14,7 @@ use super::{
|
||||
cursor_agent::CursorAgentProvider,
|
||||
databricks::DatabricksProvider,
|
||||
gcpvertexai::GcpVertexAIProvider,
|
||||
gemini_acp::GeminiAcpProvider,
|
||||
gemini_cli::GeminiCliProvider,
|
||||
githubcopilot::GithubCopilotProvider,
|
||||
google::GoogleProvider,
|
||||
@@ -51,6 +52,7 @@ async fn init_registry() -> RwLock<ProviderRegistry> {
|
||||
registry.register::<LocalInferenceProvider>(false);
|
||||
registry.register::<ChatGptCodexProvider>(true);
|
||||
registry.register::<ClaudeAcpProvider>(false);
|
||||
registry.register::<GeminiAcpProvider>(false);
|
||||
registry.register::<ClaudeCodeProvider>(true);
|
||||
registry.register::<CodexAcpProvider>(false);
|
||||
registry.register::<CodexProvider>(true);
|
||||
|
||||
@@ -21,6 +21,7 @@ pub mod errors;
|
||||
pub mod formats;
|
||||
mod gcpauth;
|
||||
pub mod gcpvertexai;
|
||||
pub mod gemini_acp;
|
||||
pub mod gemini_cli;
|
||||
pub mod githubcopilot;
|
||||
pub mod google;
|
||||
|
||||
@@ -17,6 +17,7 @@ use goose::providers::codex_acp::CODEX_ACP_DEFAULT_MODEL;
|
||||
use goose::providers::create_with_named_model;
|
||||
use goose::providers::databricks::DATABRICKS_DEFAULT_MODEL;
|
||||
use goose::providers::errors::ProviderError;
|
||||
use goose::providers::gemini_acp::GEMINI_ACP_DEFAULT_MODEL;
|
||||
use goose::providers::google::GOOGLE_DEFAULT_MODEL;
|
||||
use goose::providers::litellm::LITELLM_DEFAULT_MODEL;
|
||||
use goose::providers::openai::OPEN_AI_DEFAULT_MODEL;
|
||||
@@ -890,6 +891,14 @@ async fn test_codex_acp_provider() -> Result<()> {
|
||||
.await
|
||||
}
|
||||
|
||||
// Requires: npm install -g @google/gemini-cli
|
||||
#[tokio::test]
|
||||
async fn test_gemini_acp_provider() -> Result<()> {
|
||||
ProviderTestConfig::with_agentic_provider("gemini-acp", GEMINI_ACP_DEFAULT_MODEL, "gemini")
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
|
||||
#[ctor::dtor]
|
||||
fn print_test_report() {
|
||||
TEST_REPORT.print_summary();
|
||||
|
||||
Reference in New Issue
Block a user