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:
Michael Neale
2026-03-19 13:20:45 +11:00
committed by GitHub
parent 4e7a572497
commit 5be96c1ab2
12 changed files with 269 additions and 18 deletions
+16 -2
View File
@@ -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
+1 -1
View File
@@ -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![],
+1 -1
View File
@@ -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,
+81
View File
@@ -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(),
}
}
+1 -1
View File
@@ -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,
+2
View File
@@ -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);
+1
View File
@@ -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;
+9
View File
@@ -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();