Upgrade Gemini and ACP (#1431)
* Upgrade Gemini and ACP Upgrade ACP SDK version to the latest. Upgrade Gemini-CLI to the latest working version. * fmt
This commit is contained in:
@@ -39,7 +39,7 @@ convert_case = "0.6"
|
||||
sqlx = "0.8.6"
|
||||
axum = { workspace = true }
|
||||
shlex = "1.3.0"
|
||||
agent-client-protocol = "0.4"
|
||||
agent-client-protocol = "0.8"
|
||||
codex-protocol = { git = "https://github.com/openai/codex.git", package = "codex-protocol", rev = "80d6a3868ef1414e0fb1c2e28a369f2ef4fa4dcc" }
|
||||
codex-app-server-protocol = { git = "https://github.com/openai/codex.git", package = "codex-app-server-protocol", rev = "80d6a3868ef1414e0fb1c2e28a369f2ef4fa4dcc" }
|
||||
codex-mcp-types = { git = "https://github.com/openai/codex.git", package = "mcp-types", rev = "80d6a3868ef1414e0fb1c2e28a369f2ef4fa4dcc" }
|
||||
|
||||
@@ -50,26 +50,23 @@ impl acp::Client for AcpClient {
|
||||
.or_else(|| args.options.first());
|
||||
|
||||
let outcome = if let Some(opt) = chosen_option {
|
||||
debug!("Auto-approving permission with option: {}", opt.id);
|
||||
acp::RequestPermissionOutcome::Selected {
|
||||
option_id: opt.id.clone(),
|
||||
}
|
||||
debug!("Auto-approving permission with option: {}", opt.option_id);
|
||||
acp::RequestPermissionOutcome::Selected(acp::SelectedPermissionOutcome::new(
|
||||
opt.option_id.clone(),
|
||||
))
|
||||
} else {
|
||||
warn!("No permission options available, cancelling");
|
||||
acp::RequestPermissionOutcome::Cancelled
|
||||
};
|
||||
|
||||
Ok(acp::RequestPermissionResponse {
|
||||
outcome,
|
||||
meta: None,
|
||||
})
|
||||
Ok(acp::RequestPermissionResponse::new(outcome))
|
||||
}
|
||||
|
||||
async fn session_notification(&self, args: acp::SessionNotification) -> Result<(), acp::Error> {
|
||||
// Convert to typed events
|
||||
let event = match args.update {
|
||||
acp::SessionUpdate::AgentMessageChunk { content } => Some(AcpEvent::Message(content)),
|
||||
acp::SessionUpdate::AgentThoughtChunk { content } => Some(AcpEvent::Thought(content)),
|
||||
acp::SessionUpdate::AgentMessageChunk(chunk) => Some(AcpEvent::Message(chunk.content)),
|
||||
acp::SessionUpdate::AgentThoughtChunk(chunk) => Some(AcpEvent::Thought(chunk.content)),
|
||||
acp::SessionUpdate::ToolCall(tc) => Some(AcpEvent::ToolCall(tc)),
|
||||
acp::SessionUpdate::ToolCallUpdate(update) => Some(AcpEvent::ToolUpdate(update)),
|
||||
acp::SessionUpdate::Plan(plan) => Some(AcpEvent::Plan(plan)),
|
||||
|
||||
@@ -272,19 +272,7 @@ impl AcpAgentHarness {
|
||||
|
||||
// Initialize
|
||||
let _ = conn
|
||||
.initialize(proto::InitializeRequest {
|
||||
protocol_version: proto::V1,
|
||||
client_capabilities: proto::ClientCapabilities {
|
||||
fs: proto::FileSystemCapability {
|
||||
read_text_file: false,
|
||||
write_text_file: false,
|
||||
meta: None,
|
||||
},
|
||||
terminal: false,
|
||||
meta: None,
|
||||
},
|
||||
meta: None,
|
||||
})
|
||||
.initialize(proto::InitializeRequest::new(proto::ProtocolVersion::V1))
|
||||
.await;
|
||||
|
||||
// Handle session creation/forking
|
||||
@@ -298,14 +286,13 @@ impl AcpAgentHarness {
|
||||
let meta =
|
||||
history.map(|h| serde_json::json!({ "history_jsonl": h }));
|
||||
|
||||
match conn
|
||||
.new_session(proto::NewSessionRequest {
|
||||
mcp_servers: vec![],
|
||||
cwd: cwd.clone(),
|
||||
meta,
|
||||
})
|
||||
.await
|
||||
let mut req = proto::NewSessionRequest::new(cwd.clone());
|
||||
if let Some(m) = meta
|
||||
&& let Some(obj) = m.as_object()
|
||||
{
|
||||
req = req.meta(obj.clone());
|
||||
}
|
||||
match conn.new_session(req).await {
|
||||
Ok(resp) => {
|
||||
let resume_prompt = session_manager
|
||||
.generate_resume_prompt(&new_ui_id, &prompt)
|
||||
@@ -320,11 +307,7 @@ impl AcpAgentHarness {
|
||||
} else {
|
||||
// New session
|
||||
match conn
|
||||
.new_session(proto::NewSessionRequest {
|
||||
mcp_servers: vec![],
|
||||
cwd: cwd.clone(),
|
||||
meta: None,
|
||||
})
|
||||
.new_session(proto::NewSessionRequest::new(cwd.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(resp) => {
|
||||
@@ -364,15 +347,12 @@ impl AcpAgentHarness {
|
||||
);
|
||||
|
||||
// Build prompt request
|
||||
let req = proto::PromptRequest {
|
||||
session_id: proto::SessionId(acp_session_id.clone().into()),
|
||||
prompt: vec![proto::ContentBlock::Text(proto::TextContent {
|
||||
annotations: None,
|
||||
text: prompt_to_send,
|
||||
meta: None,
|
||||
})],
|
||||
meta: None,
|
||||
};
|
||||
let req = proto::PromptRequest::new(
|
||||
proto::SessionId::new(acp_session_id.clone()),
|
||||
vec![proto::ContentBlock::Text(proto::TextContent::new(
|
||||
prompt_to_send,
|
||||
))],
|
||||
);
|
||||
|
||||
// Send the prompt and await completion to obtain stop_reason
|
||||
match conn.prompt(req).await {
|
||||
@@ -403,10 +383,9 @@ impl AcpAgentHarness {
|
||||
|
||||
// Cancel session work
|
||||
let _ = conn
|
||||
.cancel(proto::CancelNotification {
|
||||
session_id: proto::SessionId(acp_session_id.into()),
|
||||
meta: None,
|
||||
})
|
||||
.cancel(proto::CancelNotification::new(proto::SessionId::new(
|
||||
acp_session_id,
|
||||
)))
|
||||
.await;
|
||||
|
||||
// Cleanup
|
||||
|
||||
@@ -183,7 +183,7 @@ pub fn normalize_logs(msg_store: Arc<MsgStore>, worktree_path: &Path) {
|
||||
let mut update = update;
|
||||
if update.fields.title.is_none() {
|
||||
update.fields.title = tool_states
|
||||
.get(&update.id.0.to_string())
|
||||
.get(&update.tool_call_id.0.to_string())
|
||||
.map(|s| s.title.clone())
|
||||
.or_else(|| Some("".to_string()));
|
||||
}
|
||||
@@ -216,7 +216,7 @@ pub fn normalize_logs(msg_store: Arc<MsgStore>, worktree_path: &Path) {
|
||||
) {
|
||||
streaming.assistant_text = None;
|
||||
streaming.thinking_text = None;
|
||||
let id = tc.id.0.to_string();
|
||||
let id = tc.tool_call_id.0.to_string();
|
||||
let is_new = !tool_states.contains_key(&id);
|
||||
let tool_data = tool_states.entry(id).or_default();
|
||||
tool_data.extend(tc, worktree_path);
|
||||
@@ -373,7 +373,9 @@ pub fn normalize_logs(msg_store: Arc<MsgStore>, worktree_path: &Path) {
|
||||
agent_client_protocol::ToolKind::SwitchMode => ActionType::Other {
|
||||
description: "switch_mode".to_string(),
|
||||
},
|
||||
agent_client_protocol::ToolKind::Other | agent_client_protocol::ToolKind::Move => {
|
||||
agent_client_protocol::ToolKind::Other
|
||||
| agent_client_protocol::ToolKind::Move
|
||||
| _ => {
|
||||
// Derive a friendlier tool name from the id if it looks like name-<digits>
|
||||
let tool_name = extract_tool_name_from_id(tc.id.0.as_ref())
|
||||
.unwrap_or_else(|| tc.title.clone());
|
||||
@@ -411,7 +413,7 @@ pub fn normalize_logs(msg_store: Arc<MsgStore>, worktree_path: &Path) {
|
||||
fn extract_file_changes(tc: &PartialToolCallData) -> Vec<FileChange> {
|
||||
let mut changes = Vec::new();
|
||||
for c in &tc.content {
|
||||
if let agent_client_protocol::ToolCallContent::Diff { diff } = c {
|
||||
if let agent_client_protocol::ToolCallContent::Diff(diff) = c {
|
||||
let path = diff.path.to_string_lossy().to_string();
|
||||
let rel = if !path.is_empty() {
|
||||
path
|
||||
@@ -497,8 +499,8 @@ pub fn normalize_logs(msg_store: Arc<MsgStore>, worktree_path: &Path) {
|
||||
) -> Option<String> {
|
||||
let mut out = String::new();
|
||||
for c in content {
|
||||
if let agent_client_protocol::ToolCallContent::Content { content } = c
|
||||
&& let agent_client_protocol::ContentBlock::Text(t) = content
|
||||
if let agent_client_protocol::ToolCallContent::Content(inner) = c
|
||||
&& let agent_client_protocol::ContentBlock::Text(t) = &inner.content
|
||||
{
|
||||
out.push_str(&t.text);
|
||||
if !out.ends_with('\n') {
|
||||
@@ -515,6 +517,10 @@ pub fn normalize_logs(msg_store: Arc<MsgStore>, worktree_path: &Path) {
|
||||
| agent_client_protocol::ToolCallStatus::InProgress => LogToolStatus::Created,
|
||||
agent_client_protocol::ToolCallStatus::Completed => LogToolStatus::Success,
|
||||
agent_client_protocol::ToolCallStatus::Failed => LogToolStatus::Failed,
|
||||
_ => {
|
||||
tracing::debug!("Unknown tool call status: {:?}", status);
|
||||
LogToolStatus::Created
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -534,7 +540,7 @@ struct PartialToolCallData {
|
||||
|
||||
impl PartialToolCallData {
|
||||
fn extend(&mut self, tc: &agent_client_protocol::ToolCall, worktree_path: &Path) {
|
||||
self.id = tc.id.clone();
|
||||
self.id = tc.tool_call_id.clone();
|
||||
if tc.kind != Default::default() {
|
||||
self.kind = tc.kind;
|
||||
}
|
||||
@@ -567,7 +573,7 @@ impl PartialToolCallData {
|
||||
impl Default for PartialToolCallData {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
id: agent_client_protocol::ToolCallId(Default::default()),
|
||||
id: agent_client_protocol::ToolCallId::new(""),
|
||||
index: 0,
|
||||
kind: agent_client_protocol::ToolKind::default(),
|
||||
title: String::new(),
|
||||
@@ -623,16 +629,16 @@ impl TryFrom<SessionNotification> for AcpEvent {
|
||||
|
||||
fn try_from(notification: SessionNotification) -> Result<Self, ()> {
|
||||
let event = match notification.update {
|
||||
acp::SessionUpdate::AgentMessageChunk { content } => AcpEvent::Message(content),
|
||||
acp::SessionUpdate::AgentThoughtChunk { content } => AcpEvent::Thought(content),
|
||||
acp::SessionUpdate::AgentMessageChunk(chunk) => AcpEvent::Message(chunk.content),
|
||||
acp::SessionUpdate::AgentThoughtChunk(chunk) => AcpEvent::Thought(chunk.content),
|
||||
acp::SessionUpdate::ToolCall(tc) => AcpEvent::ToolCall(tc),
|
||||
acp::SessionUpdate::ToolCallUpdate(update) => AcpEvent::ToolUpdate(update),
|
||||
acp::SessionUpdate::Plan(plan) => AcpEvent::Plan(plan),
|
||||
acp::SessionUpdate::AvailableCommandsUpdate { available_commands } => {
|
||||
AcpEvent::AvailableCommands(available_commands)
|
||||
acp::SessionUpdate::AvailableCommandsUpdate(update) => {
|
||||
AcpEvent::AvailableCommands(update.available_commands)
|
||||
}
|
||||
acp::SessionUpdate::CurrentModeUpdate { current_mode_id } => {
|
||||
AcpEvent::CurrentMode(current_mode_id)
|
||||
acp::SessionUpdate::CurrentModeUpdate(update) => {
|
||||
AcpEvent::CurrentMode(update.current_mode_id)
|
||||
}
|
||||
_ => return Err(()),
|
||||
};
|
||||
|
||||
@@ -29,7 +29,8 @@ pub struct Gemini {
|
||||
|
||||
impl Gemini {
|
||||
fn build_command_builder(&self) -> CommandBuilder {
|
||||
let mut builder = CommandBuilder::new("npx -y @google/gemini-cli@0.16.0");
|
||||
let mut builder =
|
||||
CommandBuilder::new("npx -y @google/gemini-cli@0.21.0-nightly.20251204.3da4fd5f7");
|
||||
|
||||
if let Some(model) = &self.model {
|
||||
builder = builder.extend_params(["--model", model.as_str()]);
|
||||
|
||||
Reference in New Issue
Block a user