mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Extract update_plan tool spec into codex-tools (#16481)
## Why `codex-rs/core/src/tools/handlers/plan.rs` still owned both the `update_plan` runtime handler and the static tool definition. The tool definition is pure metadata, so keeping it in `codex-core` works against the ongoing effort to move tool-spec code into `codex-tools` and keep `codex-core` focused on orchestration and execution paths. This continues the extraction work from #16379, #16471, and #16477. ## What Changed - added `codex-rs/tools/src/plan_tool.rs` with `create_update_plan_tool()` - re-exported that constructor from `codex-rs/tools/src/lib.rs` - updated `codex-rs/core/src/tools/spec.rs` and `codex-rs/core/src/tools/spec_tests.rs` to use the `codex-tools` export instead of a core-local static - removed the old `PLAN_TOOL` definition from `codex-rs/core/src/tools/handlers/plan.rs`; the `PlanHandler` runtime logic still stays in `codex-core` - tightened two `codex-core` aliases to `#[cfg(test)]` now that production code no longer needs them ## Testing - `cargo test -p codex-tools` - `cargo test -p codex-core tools::spec::tests` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/16481). * #16482 * __->__ #16481
This commit is contained in:
committed by
GitHub
Unverified
parent
30f6786d62
commit
6cf832fc63
@@ -157,6 +157,7 @@ fn strip_total_output_header(output: &str) -> Option<(&str, u32)> {
|
||||
}
|
||||
|
||||
pub(crate) mod tools {
|
||||
#[cfg(test)]
|
||||
pub(crate) use codex_tools::ResponsesApiTool;
|
||||
pub(crate) use codex_tools::ToolSearchOutputTool;
|
||||
pub(crate) use codex_tools::ToolSpec;
|
||||
|
||||
@@ -147,7 +147,7 @@ fn tool_search_payloads_roundtrip_as_tool_search_outputs() {
|
||||
description: String::new(),
|
||||
strict: false,
|
||||
defer_loading: Some(true),
|
||||
parameters: crate::tools::spec::JsonSchema::Object {
|
||||
parameters: codex_tools::JsonSchema::Object {
|
||||
properties: Default::default(),
|
||||
required: None,
|
||||
additional_properties: None,
|
||||
|
||||
@@ -22,7 +22,6 @@ use codex_sandboxing::policy_transforms::intersect_permission_profiles;
|
||||
use codex_sandboxing::policy_transforms::merge_permission_profiles;
|
||||
use codex_sandboxing::policy_transforms::normalize_additional_permissions;
|
||||
use codex_utils_absolute_path::AbsolutePathBufGuard;
|
||||
pub use plan::PLAN_TOOL;
|
||||
use serde::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::path::Path;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use crate::client_common::tools::ResponsesApiTool;
|
||||
use crate::client_common::tools::ToolSpec;
|
||||
use crate::codex::Session;
|
||||
use crate::codex::TurnContext;
|
||||
use crate::function_tool::FunctionCallError;
|
||||
@@ -8,7 +6,6 @@ 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;
|
||||
@@ -16,8 +13,6 @@ 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;
|
||||
|
||||
@@ -49,50 +44,6 @@ impl ToolOutput for PlanToolOutput {
|
||||
}
|
||||
}
|
||||
|
||||
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 });
|
||||
plan_item_props.insert(
|
||||
"status".to_string(),
|
||||
JsonSchema::String {
|
||||
description: Some("One of: pending, in_progress, completed".to_string()),
|
||||
},
|
||||
);
|
||||
|
||||
let plan_items_schema = JsonSchema::Array {
|
||||
description: Some("The list of steps".to_string()),
|
||||
items: Box::new(JsonSchema::Object {
|
||||
properties: plan_item_props,
|
||||
required: Some(vec!["step".to_string(), "status".to_string()]),
|
||||
additional_properties: Some(false.into()),
|
||||
}),
|
||||
};
|
||||
|
||||
let mut properties = BTreeMap::new();
|
||||
properties.insert(
|
||||
"explanation".to_string(),
|
||||
JsonSchema::String { description: None },
|
||||
);
|
||||
properties.insert("plan".to_string(), plan_items_schema);
|
||||
|
||||
ToolSpec::Function(ResponsesApiTool {
|
||||
name: "update_plan".to_string(),
|
||||
description: r#"Updates the task plan.
|
||||
Provide an optional explanation and a list of plan items, each with a step and status.
|
||||
At most one step can be in_progress at a time.
|
||||
"#
|
||||
.to_string(),
|
||||
strict: false,
|
||||
defer_loading: None,
|
||||
parameters: JsonSchema::Object {
|
||||
properties,
|
||||
required: Some(vec!["plan".to_string()]),
|
||||
additional_properties: Some(false.into()),
|
||||
},
|
||||
output_schema: None,
|
||||
})
|
||||
});
|
||||
|
||||
#[async_trait]
|
||||
impl ToolHandler for PlanHandler {
|
||||
type Output = PlanToolOutput;
|
||||
|
||||
@@ -105,7 +105,7 @@ fn serialize_tool_search_output_tools_groups_results_by_namespace() {
|
||||
description: "Create a calendar event.".to_string(),
|
||||
strict: false,
|
||||
defer_loading: Some(true),
|
||||
parameters: crate::tools::spec::JsonSchema::Object {
|
||||
parameters: codex_tools::JsonSchema::Object {
|
||||
properties: Default::default(),
|
||||
required: None,
|
||||
additional_properties: None,
|
||||
@@ -117,7 +117,7 @@ fn serialize_tool_search_output_tools_groups_results_by_namespace() {
|
||||
description: "List calendar events.".to_string(),
|
||||
strict: false,
|
||||
defer_loading: Some(true),
|
||||
parameters: crate::tools::spec::JsonSchema::Object {
|
||||
parameters: codex_tools::JsonSchema::Object {
|
||||
properties: Default::default(),
|
||||
required: None,
|
||||
additional_properties: None,
|
||||
@@ -134,7 +134,7 @@ fn serialize_tool_search_output_tools_groups_results_by_namespace() {
|
||||
description: "Read an email.".to_string(),
|
||||
strict: false,
|
||||
defer_loading: Some(true),
|
||||
parameters: crate::tools::spec::JsonSchema::Object {
|
||||
parameters: codex_tools::JsonSchema::Object {
|
||||
properties: Default::default(),
|
||||
required: None,
|
||||
additional_properties: None,
|
||||
@@ -187,7 +187,7 @@ fn serialize_tool_search_output_tools_falls_back_to_connector_name_description()
|
||||
description: "Read multiple emails.".to_string(),
|
||||
strict: false,
|
||||
defer_loading: Some(true),
|
||||
parameters: crate::tools::spec::JsonSchema::Object {
|
||||
parameters: codex_tools::JsonSchema::Object {
|
||||
properties: Default::default(),
|
||||
required: None,
|
||||
additional_properties: None,
|
||||
|
||||
@@ -5,7 +5,6 @@ use crate::shell::Shell;
|
||||
use crate::shell::ShellType;
|
||||
use crate::tools::code_mode::PUBLIC_TOOL_NAME;
|
||||
use crate::tools::code_mode::WAIT_TOOL_NAME;
|
||||
use crate::tools::handlers::PLAN_TOOL;
|
||||
use crate::tools::handlers::TOOL_SEARCH_DEFAULT_LIMIT;
|
||||
use crate::tools::handlers::TOOL_SEARCH_TOOL_NAME;
|
||||
use crate::tools::handlers::TOOL_SUGGEST_TOOL_NAME;
|
||||
@@ -59,6 +58,7 @@ use codex_tools::create_spawn_agents_on_csv_tool;
|
||||
use codex_tools::create_test_sync_tool;
|
||||
use codex_tools::create_tool_search_tool;
|
||||
use codex_tools::create_tool_suggest_tool;
|
||||
use codex_tools::create_update_plan_tool;
|
||||
use codex_tools::create_view_image_tool;
|
||||
use codex_tools::create_wait_agent_tool_v1;
|
||||
use codex_tools::create_wait_agent_tool_v2;
|
||||
@@ -71,7 +71,6 @@ use codex_tools::request_user_input_tool_description;
|
||||
use codex_tools::tool_spec_to_code_mode_tool_definition;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub type JsonSchema = codex_tools::JsonSchema;
|
||||
pub use codex_tools::ShellCommandBackendConfig;
|
||||
pub use codex_tools::ToolsConfig;
|
||||
pub use codex_tools::ToolsConfigParams;
|
||||
@@ -318,7 +317,7 @@ pub(crate) fn build_specs_with_discoverable_tools(
|
||||
|
||||
push_tool_spec(
|
||||
&mut builder,
|
||||
PLAN_TOOL.clone(),
|
||||
create_update_plan_tool(),
|
||||
/*supports_parallel_tool_calls*/ false,
|
||||
config.code_mode_enabled,
|
||||
);
|
||||
|
||||
@@ -24,6 +24,7 @@ use codex_tools::ConfiguredToolSpec;
|
||||
use codex_tools::DiscoverablePluginInfo;
|
||||
use codex_tools::DiscoverableTool;
|
||||
use codex_tools::FreeformTool;
|
||||
use codex_tools::JsonSchema;
|
||||
use codex_tools::ResponsesApiTool;
|
||||
use codex_tools::ResponsesApiWebSearchFilters;
|
||||
use codex_tools::ResponsesApiWebSearchUserLocation;
|
||||
@@ -41,6 +42,7 @@ use codex_tools::create_send_input_tool_v1;
|
||||
use codex_tools::create_send_message_tool;
|
||||
use codex_tools::create_spawn_agent_tool_v1;
|
||||
use codex_tools::create_spawn_agent_tool_v2;
|
||||
use codex_tools::create_update_plan_tool;
|
||||
use codex_tools::create_view_image_tool;
|
||||
use codex_tools::create_wait_agent_tool_v1;
|
||||
use codex_tools::create_wait_agent_tool_v2;
|
||||
@@ -331,7 +333,7 @@ fn test_full_toolset_specs_for_gpt5_codex_unified_exec_web_search() {
|
||||
exec_permission_approvals_enabled: false,
|
||||
}),
|
||||
create_write_stdin_tool(),
|
||||
PLAN_TOOL.clone(),
|
||||
create_update_plan_tool(),
|
||||
request_user_input_tool_spec(/*default_mode_request_user_input*/ false),
|
||||
create_apply_patch_freeform_tool(),
|
||||
ToolSpec::WebSearch {
|
||||
|
||||
@@ -12,6 +12,7 @@ mod json_schema;
|
||||
mod local_tool;
|
||||
mod mcp_resource_tool;
|
||||
mod mcp_tool;
|
||||
mod plan_tool;
|
||||
mod request_user_input_tool;
|
||||
mod responses_api;
|
||||
mod tool_config;
|
||||
@@ -64,6 +65,7 @@ pub use mcp_resource_tool::create_list_mcp_resources_tool;
|
||||
pub use mcp_resource_tool::create_read_mcp_resource_tool;
|
||||
pub use mcp_tool::mcp_call_tool_result_output_schema;
|
||||
pub use mcp_tool::parse_mcp_tool;
|
||||
pub use plan_tool::create_update_plan_tool;
|
||||
pub use request_user_input_tool::create_request_user_input_tool;
|
||||
pub use request_user_input_tool::request_user_input_tool_description;
|
||||
pub use request_user_input_tool::request_user_input_unavailable_message;
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
use crate::JsonSchema;
|
||||
use crate::ResponsesApiTool;
|
||||
use crate::ToolSpec;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
pub fn create_update_plan_tool() -> ToolSpec {
|
||||
let plan_item_properties = BTreeMap::from([
|
||||
("step".to_string(), JsonSchema::String { description: None }),
|
||||
(
|
||||
"status".to_string(),
|
||||
JsonSchema::String {
|
||||
description: Some("One of: pending, in_progress, completed".to_string()),
|
||||
},
|
||||
),
|
||||
]);
|
||||
|
||||
let properties = BTreeMap::from([
|
||||
(
|
||||
"explanation".to_string(),
|
||||
JsonSchema::String { description: None },
|
||||
),
|
||||
(
|
||||
"plan".to_string(),
|
||||
JsonSchema::Array {
|
||||
description: Some("The list of steps".to_string()),
|
||||
items: Box::new(JsonSchema::Object {
|
||||
properties: plan_item_properties,
|
||||
required: Some(vec!["step".to_string(), "status".to_string()]),
|
||||
additional_properties: Some(false.into()),
|
||||
}),
|
||||
},
|
||||
),
|
||||
]);
|
||||
|
||||
ToolSpec::Function(ResponsesApiTool {
|
||||
name: "update_plan".to_string(),
|
||||
description: r#"Updates the task plan.
|
||||
Provide an optional explanation and a list of plan items, each with a step and status.
|
||||
At most one step can be in_progress at a time.
|
||||
"#
|
||||
.to_string(),
|
||||
strict: false,
|
||||
defer_loading: None,
|
||||
parameters: JsonSchema::Object {
|
||||
properties,
|
||||
required: Some(vec!["plan".to_string()]),
|
||||
additional_properties: Some(false.into()),
|
||||
},
|
||||
output_schema: None,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user