feat(acp): add session/set_config and stabilize list, delete and close (#7984)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
@@ -2,4 +2,6 @@ mod common;
|
||||
mod provider;
|
||||
|
||||
pub use common::{map_permission_response, PermissionDecision, PermissionMapping};
|
||||
pub use provider::{extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig};
|
||||
pub use provider::{
|
||||
extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig, ACP_CURRENT_MODEL,
|
||||
};
|
||||
|
||||
+869
-148
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,7 @@ use utoipa::ToSchema;
|
||||
Debug,
|
||||
Default,
|
||||
Eq,
|
||||
Hash,
|
||||
PartialEq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
use anyhow::Result;
|
||||
use futures::future::BoxFuture;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::acp::{
|
||||
extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig, PermissionMapping,
|
||||
ACP_CURRENT_MODEL,
|
||||
};
|
||||
use crate::config::search_path::SearchPaths;
|
||||
use crate::config::{Config, GooseMode};
|
||||
@@ -11,7 +13,6 @@ use crate::model::ModelConfig;
|
||||
use crate::providers::base::{ProviderDef, ProviderMetadata};
|
||||
|
||||
const CLAUDE_ACP_PROVIDER_NAME: &str = "claude-acp";
|
||||
pub const CLAUDE_ACP_DEFAULT_MODEL: &str = "default";
|
||||
const CLAUDE_ACP_DOC_URL: &str = "https://github.com/zed-industries/claude-agent-acp";
|
||||
const CLAUDE_ACP_BINARY: &str = "claude-agent-acp";
|
||||
|
||||
@@ -25,7 +26,7 @@ impl ProviderDef for ClaudeAcpProvider {
|
||||
CLAUDE_ACP_PROVIDER_NAME,
|
||||
"Claude Code",
|
||||
"ACP wrapper for Anthropic's Claude. Install: npm install -g @zed-industries/claude-agent-acp",
|
||||
CLAUDE_ACP_DEFAULT_MODEL,
|
||||
ACP_CURRENT_MODEL,
|
||||
vec![],
|
||||
CLAUDE_ACP_DOC_URL,
|
||||
vec![],
|
||||
@@ -51,6 +52,17 @@ impl ProviderDef for ClaudeAcpProvider {
|
||||
rejected_tool_status: sacp::schema::ToolCallStatus::Failed,
|
||||
};
|
||||
|
||||
let mode_mapping = HashMap::from([
|
||||
// Closest to "autonomous": bypassPermissions skips confirmations.
|
||||
(GooseMode::Auto, "bypassPermissions".to_string()),
|
||||
// Claude Code's default matches "ask before risky actions".
|
||||
(GooseMode::Approve, "default".to_string()),
|
||||
// acceptEdits auto-accepts file edits but still prompts for risky ops.
|
||||
(GooseMode::SmartApprove, "acceptEdits".to_string()),
|
||||
// Plan mode disables tool execution, aligning with chat-only intent.
|
||||
(GooseMode::Chat, "plan".to_string()),
|
||||
]);
|
||||
|
||||
let provider_config = AcpProviderConfig {
|
||||
command: resolved_command,
|
||||
args: vec![],
|
||||
@@ -59,7 +71,8 @@ impl ProviderDef for ClaudeAcpProvider {
|
||||
env_remove: vec!["CLAUDECODE".to_string()],
|
||||
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)),
|
||||
session_mode_id: Some(mode_mapping[&goose_mode].clone()),
|
||||
mode_mapping,
|
||||
permission_mapping,
|
||||
notification_callback: None,
|
||||
};
|
||||
@@ -69,24 +82,3 @@ impl ProviderDef for ClaudeAcpProvider {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn map_goose_mode(goose_mode: GooseMode) -> String {
|
||||
match goose_mode {
|
||||
GooseMode::Auto => {
|
||||
// Closest to "autonomous": Claude Code's bypassPermissions skips confirmations.
|
||||
"bypassPermissions".to_string()
|
||||
}
|
||||
GooseMode::Approve => {
|
||||
// Claude Code's default matches "ask before risky actions".
|
||||
"default".to_string()
|
||||
}
|
||||
GooseMode::SmartApprove => {
|
||||
// Best-effort: acceptEdits auto-accepts file edits but still prompts for risky ops.
|
||||
"acceptEdits".to_string()
|
||||
}
|
||||
GooseMode::Chat => {
|
||||
// Plan mode disables tool execution, aligning with chat-only intent.
|
||||
"plan".to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
use anyhow::Result;
|
||||
use futures::future::BoxFuture;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::acp::{
|
||||
extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig, PermissionMapping,
|
||||
ACP_CURRENT_MODEL,
|
||||
};
|
||||
use crate::config::search_path::SearchPaths;
|
||||
use crate::config::{Config, GooseMode};
|
||||
@@ -11,7 +13,6 @@ use crate::model::ModelConfig;
|
||||
use crate::providers::base::{ProviderDef, ProviderMetadata};
|
||||
|
||||
const CODEX_ACP_PROVIDER_NAME: &str = "codex-acp";
|
||||
pub const CODEX_ACP_DEFAULT_MODEL: &str = "gpt-5.2-codex";
|
||||
const CODEX_ACP_DOC_URL: &str = "https://github.com/zed-industries/codex-acp";
|
||||
|
||||
pub struct CodexAcpProvider;
|
||||
@@ -24,7 +25,7 @@ impl ProviderDef for CodexAcpProvider {
|
||||
CODEX_ACP_PROVIDER_NAME,
|
||||
"Codex CLI",
|
||||
"ACP adapter for OpenAI's coding assistant. Install: npm install -g @zed-industries/codex-acp",
|
||||
CODEX_ACP_DEFAULT_MODEL,
|
||||
ACP_CURRENT_MODEL,
|
||||
vec![],
|
||||
CODEX_ACP_DOC_URL,
|
||||
vec![],
|
||||
@@ -74,6 +75,14 @@ impl ProviderDef for CodexAcpProvider {
|
||||
rejected_tool_status: sacp::schema::ToolCallStatus::Failed,
|
||||
};
|
||||
|
||||
// Chat and Approve both map to "read-only".
|
||||
let mode_mapping = HashMap::from([
|
||||
(GooseMode::Auto, "full-access".to_string()),
|
||||
(GooseMode::Approve, "read-only".to_string()),
|
||||
(GooseMode::SmartApprove, "auto".to_string()),
|
||||
(GooseMode::Chat, "read-only".to_string()),
|
||||
]);
|
||||
|
||||
let provider_config = AcpProviderConfig {
|
||||
command: resolved_command,
|
||||
args,
|
||||
@@ -83,6 +92,7 @@ impl ProviderDef for CodexAcpProvider {
|
||||
mcp_servers,
|
||||
// Disabled until https://github.com/zed-industries/codex-acp/issues/179 is fixed.
|
||||
session_mode_id: None,
|
||||
mode_mapping,
|
||||
permission_mapping,
|
||||
notification_callback: None,
|
||||
};
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
use anyhow::Result;
|
||||
use futures::future::BoxFuture;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::acp::{
|
||||
extension_configs_to_mcp_servers, AcpProvider, AcpProviderConfig, PermissionMapping,
|
||||
ACP_CURRENT_MODEL,
|
||||
};
|
||||
use crate::config::search_path::SearchPaths;
|
||||
use crate::config::{Config, GooseMode};
|
||||
@@ -11,7 +13,6 @@ 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;
|
||||
@@ -24,7 +25,7 @@ impl ProviderDef for GeminiAcpProvider {
|
||||
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,
|
||||
ACP_CURRENT_MODEL,
|
||||
vec![],
|
||||
GEMINI_ACP_DOC_URL,
|
||||
vec![],
|
||||
@@ -48,11 +49,18 @@ impl ProviderDef for GeminiAcpProvider {
|
||||
};
|
||||
|
||||
let mut args = vec!["--acp".to_string()];
|
||||
if model.model_name != "default" {
|
||||
if model.model_name != ACP_CURRENT_MODEL {
|
||||
args.push("--model".to_string());
|
||||
args.push(model.model_name.clone());
|
||||
}
|
||||
|
||||
let mode_mapping = HashMap::from([
|
||||
(GooseMode::Auto, "yolo".to_string()),
|
||||
(GooseMode::Approve, "default".to_string()),
|
||||
(GooseMode::SmartApprove, "auto_edit".to_string()),
|
||||
(GooseMode::Chat, "plan".to_string()),
|
||||
]);
|
||||
|
||||
let provider_config = AcpProviderConfig {
|
||||
command: resolved_command,
|
||||
args,
|
||||
@@ -60,7 +68,8 @@ impl ProviderDef for GeminiAcpProvider {
|
||||
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)),
|
||||
session_mode_id: Some(mode_mapping[&goose_mode].clone()),
|
||||
mode_mapping,
|
||||
permission_mapping,
|
||||
notification_callback: None,
|
||||
};
|
||||
@@ -70,12 +79,3 @@ impl ProviderDef for GeminiAcpProvider {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,13 @@ use crate::model::ModelConfig;
|
||||
use crate::providers::errors::ProviderError;
|
||||
use anyhow::{anyhow, Result};
|
||||
use base64::Engine;
|
||||
use fs_err::File;
|
||||
use regex::Regex;
|
||||
use reqwest::{Response, StatusCode};
|
||||
use rmcp::model::{AnnotateAble, ImageContent, RawImageContent};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{json, Value};
|
||||
use std::fmt::Display;
|
||||
use std::fs::File;
|
||||
use std::io::{BufWriter, Read, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::OnceLock;
|
||||
@@ -436,10 +436,10 @@ impl RequestLog {
|
||||
let log_path = |i| logs_dir.join(format!("llm_request.{}.jsonl", i));
|
||||
|
||||
for i in (0..LOGS_TO_KEEP - 1).rev() {
|
||||
let _ = std::fs::rename(log_path(i), log_path(i + 1));
|
||||
let _ = fs_err::rename(log_path(i), log_path(i + 1));
|
||||
}
|
||||
|
||||
std::fs::rename(&self.temp_path, log_path(0))?;
|
||||
fs_err::rename(&self.temp_path, log_path(0))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user