Extract tool spec helpers into codex-tools (#16471)

## Why

Follow-up to #16379.

`codex-rs/core/src/tools/spec.rs` and the corresponding handlers still
owned several pure tool-definition helpers even though they do not need
`codex-core` runtime state. Keeping that spec-only logic in `codex-core`
keeps the crate boundary blurry and works against the guidance in
`AGENTS.md` to keep shared tooling out of `codex-core` when possible.

This change takes another step toward a dedicated `codex-tools` crate by
moving more metadata and schema-building code behind the `codex-tools`
API while leaving the actual tool execution paths in `codex-core`.

## What Changed

- Added `codex-rs/tools/src/apply_patch_tool.rs` to own
`ApplyPatchToolArgs`, the freeform/json `apply_patch` tool specs, and
the moved `tool_apply_patch.lark` grammar.
- Updated `codex-rs/tools/BUILD.bazel` so Bazel exposes the moved
grammar file to `codex-tools`.
- Moved the `request_user_input` availability and description helpers
into `codex-rs/tools/src/request_user_input_tool.rs`, with the related
unit tests moved alongside that business logic.
- Moved `request_permissions_tool_description()` into
`codex-rs/tools/src/local_tool.rs`.
- Rewired `codex-rs/core/src/tools/spec.rs`,
`codex-rs/core/src/tools/handlers/apply_patch.rs`, and
`codex-rs/core/src/tools/handlers/request_user_input.rs` to consume the
new `codex-tools` exports instead of local helper code.
- Removed the now-redundant helper implementations and tests from
`codex-core`, plus a couple of stale `client_common` re-exports that
became unused after the move.

## Testing

- `cargo test -p codex-tools`
- `cargo test -p codex-core tools::spec::tests`
- `cargo test -p codex-core tools::handlers::apply_patch::tests`
This commit is contained in:
Michael Bolin
2026-04-01 14:06:04 -07:00
committed by GitHub
parent 323aa968c3
commit e6f5451a2c
16 changed files with 292 additions and 244 deletions

View File

@@ -1,4 +1,5 @@
use super::*;
use codex_protocol::config_types::ModeKind;
use pretty_assertions::assert_eq;
use std::collections::BTreeMap;
@@ -100,3 +101,54 @@ fn request_user_input_tool_includes_questions_schema() {
})
);
}
#[test]
fn request_user_input_unavailable_messages_respect_default_mode_feature_flag() {
assert_eq!(
request_user_input_unavailable_message(
ModeKind::Plan,
/*default_mode_request_user_input*/ false
),
None
);
assert_eq!(
request_user_input_unavailable_message(
ModeKind::Default,
/*default_mode_request_user_input*/ false
),
Some("request_user_input is unavailable in Default mode".to_string())
);
assert_eq!(
request_user_input_unavailable_message(
ModeKind::Default,
/*default_mode_request_user_input*/ true
),
None
);
assert_eq!(
request_user_input_unavailable_message(
ModeKind::Execute,
/*default_mode_request_user_input*/ false
),
Some("request_user_input is unavailable in Execute mode".to_string())
);
assert_eq!(
request_user_input_unavailable_message(
ModeKind::PairProgramming,
/*default_mode_request_user_input*/ false
),
Some("request_user_input is unavailable in Pair Programming mode".to_string())
);
}
#[test]
fn request_user_input_tool_description_mentions_available_modes() {
assert_eq!(
request_user_input_tool_description(/*default_mode_request_user_input*/ false),
"Request user input for one to three short questions and wait for the response. This tool is only available in Plan mode.".to_string()
);
assert_eq!(
request_user_input_tool_description(/*default_mode_request_user_input*/ true),
"Request user input for one to three short questions and wait for the response. This tool is only available in Default or Plan mode.".to_string()
);
}