Avoid cloning deferred TUI lifecycle payloads (#34347)

## What changed

- Move lifecycle and approval payloads into either the interrupt queue or the
  immediate handler instead of cloning them for both branches.
- Borrow MCP elicitation request metadata while constructing the corresponding
  form, and consume apply-patch changes after collecting notification paths.

## Testing

- Add a history replay test confirming deferred MCP start and completion events
  remain FIFO after streaming finishes.

GitOrigin-RevId: 84ed34f6ff173463a1da016dc140405392c0ba45
This commit is contained in:
Charlie Marsh authored and copyberry committed 2026-07-20 13:54:11 +00:00
1 parent 2244d11a1d
commit ada5a79ddf
7 files changed
+111 -52

No files matched your search

@@ -207,7 +207,7 @@ impl McpServerElicitationFormRequest {
pub(crate) fn from_app_server_request(
thread_id: ThreadId,
request_id: AppServerRequestId,
request: McpServerElicitationRequestParams,
request: &McpServerElicitationRequestParams,
) -> Option<Self> {
let McpServerElicitationRequestParams {
server_name,
@@ -226,10 +226,10 @@ impl McpServerElicitationFormRequest {
let requested_schema = serde_json::to_value(requested_schema).ok()?;
Self::from_parts(
thread_id,
server_name,
server_name.clone(),
request_id,
meta,
message,
meta.as_ref(),
message.clone(),
requested_schema,
)
}
@@ -238,13 +238,12 @@ impl McpServerElicitationFormRequest {
thread_id: ThreadId,
server_name: String,
request_id: AppServerRequestId,
meta: Option<Value>,
meta: Option<&Value>,
message: String,
requested_schema: Value,
) -> Option<Self> {
let tool_suggestion = parse_tool_suggestion_request(meta.as_ref());
let tool_suggestion = parse_tool_suggestion_request(meta);
let is_tool_approval = meta
.as_ref()
.and_then(Value::as_object)
.and_then(|meta| meta.get(APPROVAL_META_KIND_KEY))
.and_then(Value::as_str)
@@ -259,7 +258,7 @@ impl McpServerElicitationFormRequest {
let is_message_only_schema = requested_schema.is_null() || is_empty_object_schema;
let is_tool_approval_action = is_tool_approval && is_message_only_schema;
let approval_display_params = if is_tool_approval_action {
parse_tool_approval_display_params(meta.as_ref())
parse_tool_approval_display_params(meta)
} else {
Vec::new()
};
@@ -277,7 +276,7 @@ impl McpServerElicitationFormRequest {
description: Some(allow_description.to_string()),
value: Value::String(APPROVAL_ACCEPT_ONCE_VALUE.to_string()),
}];
if approval_supports_persist_mode(meta.as_ref(), APPROVAL_PERSIST_SESSION_VALUE) {
if approval_supports_persist_mode(meta, APPROVAL_PERSIST_SESSION_VALUE) {
let description = if is_tool_approval_action {
"Run the tool and remember this choice for this session."
} else {
@@ -289,7 +288,7 @@ impl McpServerElicitationFormRequest {
value: Value::String(APPROVAL_ACCEPT_SESSION_VALUE.to_string()),
});
}
if approval_supports_persist_mode(meta.as_ref(), APPROVAL_PERSIST_ALWAYS_VALUE) {
if approval_supports_persist_mode(meta, APPROVAL_PERSIST_ALWAYS_VALUE) {
let description = if is_tool_approval_action {
"Run the tool and remember this choice for future tool calls."
} else {
@@ -1777,7 +1776,7 @@ mod tests {
McpServerElicitationFormRequest::from_app_server_request(
thread_id,
request_id("request-1"),
request,
&request,
)
}
@@ -2496,7 +2495,7 @@ mod tests {
McpServerElicitationFormRequest::from_app_server_request(
thread_id,
request_id("request-2"),
McpServerElicitationRequestParams {
&McpServerElicitationRequestParams {
thread_id: "thread-1".to_string(),
turn_id: Some("turn-2".to_string()),
server_name: "server-1".to_string(),