Add update_plan code mode result (#15103)

It's empty!
This commit is contained in:
pakrym-oai 2026-03-18 16:10:51 -07:00 committed by GitHub
parent b306885bd8
commit 3590e181fa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 67 additions and 5 deletions

View file

@ -3,21 +3,52 @@ use crate::client_common::tools::ToolSpec;
use crate::codex::Session;
use crate::codex::TurnContext;
use crate::function_tool::FunctionCallError;
use crate::tools::context::FunctionToolOutput;
use crate::tools::context::ToolInvocation;
use crate::tools::context::ToolOutput;
use crate::tools::context::ToolPayload;
use crate::tools::registry::ToolHandler;
use crate::tools::registry::ToolKind;
use crate::tools::spec::JsonSchema;
use async_trait::async_trait;
use codex_protocol::config_types::ModeKind;
use codex_protocol::models::FunctionCallOutputPayload;
use codex_protocol::models::ResponseInputItem;
use codex_protocol::plan_tool::UpdatePlanArgs;
use codex_protocol::protocol::EventMsg;
use serde_json::Value as JsonValue;
use std::collections::BTreeMap;
use std::sync::LazyLock;
pub struct PlanHandler;
pub struct PlanToolOutput;
const PLAN_UPDATED_MESSAGE: &str = "Plan updated";
impl ToolOutput for PlanToolOutput {
fn log_preview(&self) -> String {
PLAN_UPDATED_MESSAGE.to_string()
}
fn success_for_logging(&self) -> bool {
true
}
fn to_response_item(&self, call_id: &str, _payload: &ToolPayload) -> ResponseInputItem {
let mut output = FunctionCallOutputPayload::from_text(PLAN_UPDATED_MESSAGE.to_string());
output.success = Some(true);
ResponseInputItem::FunctionCallOutput {
call_id: call_id.to_string(),
output,
}
}
fn code_mode_result(&self, _payload: &ToolPayload) -> JsonValue {
JsonValue::Object(serde_json::Map::new())
}
}
pub static PLAN_TOOL: LazyLock<ToolSpec> = LazyLock::new(|| {
let mut plan_item_props = BTreeMap::new();
plan_item_props.insert("step".to_string(), JsonSchema::String { description: None });
@ -64,7 +95,7 @@ At most one step can be in_progress at a time.
#[async_trait]
impl ToolHandler for PlanHandler {
type Output = FunctionToolOutput;
type Output = PlanToolOutput;
fn kind(&self) -> ToolKind {
ToolKind::Function
@ -88,10 +119,9 @@ impl ToolHandler for PlanHandler {
}
};
let content =
handle_update_plan(session.as_ref(), turn.as_ref(), arguments, call_id).await?;
handle_update_plan(session.as_ref(), turn.as_ref(), arguments, call_id).await?;
Ok(FunctionToolOutput::from_text(content, Some(true)))
Ok(PlanToolOutput)
}
}

View file

@ -363,6 +363,38 @@ text(output.output);
Ok(())
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn code_mode_update_plan_nested_tool_result_is_empty_object() -> Result<()> {
skip_if_no_network!(Ok(()));
let server = responses::start_mock_server().await;
let (_test, second_mock) = run_code_mode_turn(
&server,
"use exec to run update_plan",
r#"
const result = await tools.update_plan({
plan: [{ step: "Run update_plan from code mode", status: "in_progress" }],
});
text(JSON.stringify(result));
"#,
false,
)
.await?;
let req = second_mock.single_request();
let (output, success) = custom_tool_output_body_and_success(&req, "call-1");
assert_ne!(
success,
Some(false),
"exec update_plan call failed unexpectedly: {output}"
);
let parsed: Value = serde_json::from_str(&output)?;
assert_eq!(parsed, serde_json::json!({}));
Ok(())
}
#[cfg_attr(windows, ignore = "flaky on windows")]
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn code_mode_nested_tool_calls_can_run_in_parallel() -> Result<()> {