codex-tools: extract utility tool specs (#16154)

## Why

The previous `codex-tools` migration steps moved the shared schema
models, local-host specs, collaboration specs, and related adapters out
of `codex-core`, but `core/src/tools/spec.rs` still contained a grab bag
of pure utility tool builders. Those specs do not need session state or
handler logic; they only describe wire shapes for tools that
`codex-core` already knows how to execute.

Moving that remaining low-coupling layer into `codex-tools` keeps the
migration moving in meaningful chunks and trims another large block of
passive tool-spec construction out of `codex-core` without touching the
runtime-coupled handlers.

## What changed

- extended `codex-tools` to own the pure spec builders for:
  - code-mode `exec` / `wait`
  - `js_repl` / `js_repl_reset`
- MCP resource tools `list_mcp_resources`,
`list_mcp_resource_templates`, and `read_mcp_resource`
  - utility tools `list_dir` and `test_sync_tool`
- split those builders across small module files with sibling
`*_tests.rs` coverage, keeping `src/lib.rs` exports-only
- rewired `core/src/tools/spec.rs` to call the extracted builders and
deleted the duplicated core-local implementations
- moved the direct JS REPL grammar seam test out of
`core/src/tools/spec_tests.rs` so it now lives with the extracted
implementation in `codex-tools`
- updated `codex-rs/tools/README.md` so the documented crate boundary
matches the new utility-spec surface

## Test plan

- `CARGO_TARGET_DIR=/tmp/codex-tools-utility-specs cargo test -p
codex-tools`
- `CARGO_TARGET_DIR=/tmp/codex-core-utility-specs cargo test -p
codex-core --lib tools::spec::`
- `just fix -p codex-tools -p codex-core`
- `just argument-comment-lint`

## References

- #15923
- #15928
- #15944
- #15953
- #16031
- #16047
- #16129
- #16132
- #16138
- #16141
This commit is contained in:
Michael Bolin
2026-03-29 14:34:36 -07:00
committed by GitHub
parent 38e648ca67
commit af568afdd5
12 changed files with 794 additions and 372 deletions

View File

@@ -0,0 +1,40 @@
use super::*;
use crate::ToolSpec;
use pretty_assertions::assert_eq;
use std::collections::BTreeMap;
#[test]
fn js_repl_tool_uses_expected_freeform_grammar() {
let ToolSpec::Freeform(FreeformTool { format, .. }) = create_js_repl_tool() else {
panic!("js_repl should use a freeform tool spec");
};
assert_eq!(format.syntax, "lark");
assert!(format.definition.contains("PRAGMA_LINE"));
assert!(format.definition.contains("`[^`]"));
assert!(format.definition.contains("``[^`]"));
assert!(format.definition.contains("PLAIN_JS_SOURCE"));
assert!(format.definition.contains("codex-js-repl:"));
assert!(!format.definition.contains("(?!"));
}
#[test]
fn js_repl_reset_tool_matches_expected_spec() {
assert_eq!(
create_js_repl_reset_tool(),
ToolSpec::Function(ResponsesApiTool {
name: "js_repl_reset".to_string(),
description:
"Restarts the js_repl kernel for this run and clears persisted top-level bindings."
.to_string(),
strict: false,
defer_loading: None,
parameters: JsonSchema::Object {
properties: BTreeMap::new(),
required: None,
additional_properties: Some(false.into()),
},
output_schema: None,
})
);
}