Skip to content

Commit 3eecc9f

Browse files
committed
Merge branch 'main-0716' into main
Integrate the codex-acp elicitation bridge (Plan-mode request_user_input and generic MCP forms routed to the native ask and permission cards), the codex-acp 1.1.7 pin, standalone goal capsules, and grok exit-plan approval. Grok's exit_plan_mode and codex's elicitation/create requests register as side-by-side ACP handlers; the connection context exposes both answerPlanApproval and goalControl; the folded task-duration outcome renders as a body-less "Completed" chip.
2 parents 7bd87da + 78d859d commit 3eecc9f

53 files changed

Lines changed: 3014 additions & 148 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src-tauri/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ toml_edit = "0.19"
100100
serde_yaml = "0.9"
101101
notify = "6"
102102
base64 = "0.22"
103-
agent-client-protocol-schema = { version = "0.11", features = ["unstable_session_usage", "unstable_session_fork", "unstable_session_resume"] }
103+
agent-client-protocol-schema = { version = "0.11", features = ["unstable_session_usage", "unstable_session_fork", "unstable_session_resume", "unstable_elicitation"] }
104104
kill_tree = { version = "0.2", features = ["tokio"] }
105105
which = "7"
106106
keyring = { version = "3", features = ["apple-native", "windows-native", "sync-secret-service"], optional = true }

src-tauri/src/acp/codex_goal.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,36 @@ mod tests {
248248
assert_eq!(input["objective"], "Fix the login bug");
249249
}
250250

251+
#[test]
252+
fn preserves_v114_slimmed_snapshot_fields() {
253+
// codex-acp v1.1.4 (#293) slimmed the goal snapshot: it dropped
254+
// `tokensUsed` and added `createdAt` / `controlMethod` (alongside the
255+
// existing `tokenBudget` / `timeUsedSeconds`). `goal_marker` clones the
256+
// object through, so the new fields survive onto the card output and the
257+
// absent `tokensUsed` is simply not present — `GoalCard` reads it as null
258+
// and hides that stat, so no display breaks.
259+
let goal = json!({
260+
"objective": " Ship the release ",
261+
"status": "active",
262+
"tokenBudget": 200000,
263+
"timeUsedSeconds": 42,
264+
"createdAt": "2026-07-16T10:00:00Z",
265+
"controlMethod": "_codex/session/goal_control",
266+
});
267+
let m = goal_marker(&goal).expect("goal marker");
268+
assert_eq!(m.tool_name, "create_goal");
269+
let out: Value = serde_json::from_str(&m.output_json).unwrap();
270+
let g = &out["goal"];
271+
assert_eq!(g["objective"], "Ship the release"); // trimmed
272+
assert_eq!(g["status"], "active");
273+
assert_eq!(g["tokenBudget"], 200000);
274+
assert_eq!(g["timeUsedSeconds"], 42);
275+
assert_eq!(g["createdAt"], "2026-07-16T10:00:00Z");
276+
assert_eq!(g["controlMethod"], "_codex/session/goal_control");
277+
// Slimmed snapshot carries no tokensUsed → the card hides that stat.
278+
assert!(g.get("tokensUsed").is_none());
279+
}
280+
251281
#[test]
252282
fn goal_tool_call_id_is_occurrence_unique() {
253283
// Occurrence-addressed so two runs sharing an objective never collide.

src-tauri/src/acp/connection.rs

Lines changed: 786 additions & 45 deletions
Large diffs are not rendered by default.

src-tauri/src/acp/delegation/listener.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1859,6 +1859,7 @@ mod tests {
18591859
description: String::new(),
18601860
},
18611861
],
1862+
is_secret: false,
18621863
}],
18631864
})
18641865
}

src-tauri/src/acp/manager.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ use sea_orm::{
1010
TransactionTrait,
1111
};
1212

13-
use crate::acp::connection::{spawn_agent_connection, AgentConnection, ConnectionCommand};
13+
use crate::acp::connection::{
14+
spawn_agent_connection, AgentConnection, ConnectionCommand, GoalControlAction,
15+
};
1416
use crate::acp::error::AcpError;
1517
use crate::acp::feedback::{
1618
bounded_feedback_batch, FeedbackItem, FeedbackStatus, PendingFeedback,
@@ -1179,6 +1181,27 @@ impl ConnectionManager {
11791181
.map_err(|_| AcpError::ProcessExited)
11801182
}
11811183

1184+
/// Pause or clear the session's active Codex goal via the connection loop
1185+
/// (codex-acp #293). Looked up by connectionId; the loop sources the
1186+
/// sessionId from the live session, so callers only supply the action.
1187+
pub async fn goal_control(
1188+
&self,
1189+
conn_id: &str,
1190+
action: GoalControlAction,
1191+
) -> Result<(), AcpError> {
1192+
let cmd_tx = {
1193+
let connections = self.connections.lock().await;
1194+
let conn = connections
1195+
.get(conn_id)
1196+
.ok_or_else(|| AcpError::ConnectionNotFound(conn_id.into()))?;
1197+
conn.cmd_tx.clone()
1198+
};
1199+
cmd_tx
1200+
.send(ConnectionCommand::GoalControl { action })
1201+
.await
1202+
.map_err(|_| AcpError::ProcessExited)
1203+
}
1204+
11821205
pub async fn cancel(&self, db: &DatabaseConnection, conn_id: &str) -> Result<(), AcpError> {
11831206
let (cmd_tx, state_arc, emitter) = {
11841207
let connections = self.connections.lock().await;
@@ -5595,6 +5618,7 @@ mod tests {
55955618
description: String::new(),
55965619
},
55975620
],
5621+
is_secret: false,
55985622
}]
55995623
}
56005624

0 commit comments

Comments
 (0)