Remove js_repl feature (#19410)

This commit is contained in:
Curtis 'Fjord' Hawthorne
2026-04-24 17:49:29 -07:00
committed by GitHub
parent cf02e9c052
commit 8a559e7938
63 changed files with 77 additions and 9261 deletions
-55
View File
@@ -1,55 +0,0 @@
use crate::FreeformTool;
use crate::FreeformToolFormat;
use crate::JsonSchema;
use crate::ResponsesApiTool;
use crate::ToolSpec;
use std::collections::BTreeMap;
pub fn create_js_repl_tool() -> ToolSpec {
// Keep JS input freeform, but block the most common malformed payload shapes
// (JSON wrappers, quoted strings, and markdown fences) before they reach the
// runtime `reject_json_or_quoted_source` validation. The API's regex engine
// does not support look-around, so this uses a "first significant token"
// pattern rather than negative lookaheads.
const JS_REPL_FREEFORM_GRAMMAR: &str = r#"
start: pragma_source | plain_source
pragma_source: PRAGMA_LINE NEWLINE js_source
plain_source: PLAIN_JS_SOURCE
js_source: JS_SOURCE
PRAGMA_LINE: /[ \t]*\/\/ codex-js-repl:[^\r\n]*/
NEWLINE: /\r?\n/
PLAIN_JS_SOURCE: /(?:\s*)(?:[^\s{\"`]|`[^`]|``[^`])[\s\S]*/
JS_SOURCE: /(?:\s*)(?:[^\s{\"`]|`[^`]|``[^`])[\s\S]*/
"#;
ToolSpec::Freeform(FreeformTool {
name: "js_repl".to_string(),
description: "Runs JavaScript in a persistent Node kernel with top-level await. This is a freeform tool: send raw JavaScript source text, optionally with a first-line pragma like `// codex-js-repl: timeout_ms=15000`; do not send JSON/quotes/markdown fences."
.to_string(),
format: FreeformToolFormat {
r#type: "grammar".to_string(),
syntax: "lark".to_string(),
definition: JS_REPL_FREEFORM_GRAMMAR.to_string(),
},
})
}
pub fn create_js_repl_reset_tool() -> ToolSpec {
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(BTreeMap::new(), /*required*/ None, Some(false.into())),
output_schema: None,
})
}
#[cfg(test)]
#[path = "js_repl_tool_tests.rs"]
mod tests;
-41
View File
@@ -1,41 +0,0 @@
use super::*;
use crate::JsonSchema;
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(
BTreeMap::new(),
/*required*/ None,
Some(false.into())
),
output_schema: None,
})
);
}
-3
View File
@@ -7,7 +7,6 @@ mod apply_patch_tool;
mod code_mode;
mod dynamic_tool;
mod image_detail;
mod js_repl_tool;
mod json_schema;
mod local_tool;
mod mcp_resource_tool;
@@ -55,8 +54,6 @@ pub use dynamic_tool::parse_dynamic_tool;
pub use image_detail::can_request_original_image_detail;
pub use image_detail::normalize_output_image_detail;
pub use image_detail::sanitize_original_image_detail;
pub use js_repl_tool::create_js_repl_reset_tool;
pub use js_repl_tool::create_js_repl_tool;
pub use json_schema::AdditionalProperties;
pub use json_schema::JsonSchema;
pub use json_schema::JsonSchemaPrimitiveType;
-7
View File
@@ -99,8 +99,6 @@ pub struct ToolsConfig {
pub request_permissions_tool_enabled: bool,
pub code_mode_enabled: bool,
pub code_mode_only_enabled: bool,
pub js_repl_enabled: bool,
pub js_repl_tools_only: bool,
pub can_request_original_image_detail: bool,
pub collab_tools: bool,
pub multi_agent_v2: bool,
@@ -141,9 +139,6 @@ impl ToolsConfig {
let include_apply_patch_tool = features.enabled(Feature::ApplyPatchFreeform);
let include_code_mode = features.enabled(Feature::CodeMode);
let include_code_mode_only = include_code_mode && features.enabled(Feature::CodeModeOnly);
let include_js_repl = features.enabled(Feature::JsRepl);
let include_js_repl_tools_only =
include_js_repl && features.enabled(Feature::JsReplToolsOnly);
let include_collab_tools = features.enabled(Feature::Collab);
let include_multi_agent_v2 = features.enabled(Feature::MultiAgentV2);
let include_agent_jobs = features.enabled(Feature::SpawnCsv);
@@ -221,8 +216,6 @@ impl ToolsConfig {
request_permissions_tool_enabled,
code_mode_enabled: include_code_mode,
code_mode_only_enabled: include_code_mode_only,
js_repl_enabled: include_js_repl,
js_repl_tools_only: include_js_repl_tools_only,
can_request_original_image_detail: include_original_image_detail,
collab_tools: include_collab_tools,
multi_agent_v2: include_multi_agent_v2,
-17
View File
@@ -29,8 +29,6 @@ use crate::create_code_mode_tool;
use crate::create_exec_command_tool;
use crate::create_followup_task_tool;
use crate::create_image_generation_tool;
use crate::create_js_repl_reset_tool;
use crate::create_js_repl_tool;
use crate::create_list_agents_tool;
use crate::create_list_dir_tool;
use crate::create_list_mcp_resource_templates_tool;
@@ -218,21 +216,6 @@ pub fn build_tool_registry_plan(
);
plan.register_handler("update_plan", ToolHandlerKind::Plan);
if config.has_environment && config.js_repl_enabled {
plan.push_spec(
create_js_repl_tool(),
/*supports_parallel_tool_calls*/ false,
config.code_mode_enabled,
);
plan.push_spec(
create_js_repl_reset_tool(),
/*supports_parallel_tool_calls*/ false,
config.code_mode_enabled,
);
plan.register_handler("js_repl", ToolHandlerKind::JsRepl);
plan.register_handler("js_repl_reset", ToolHandlerKind::JsReplReset);
}
plan.push_spec(
create_request_user_input_tool(request_user_input_tool_description(
config.default_mode_request_user_input,
@@ -437,7 +437,6 @@ fn disabled_environment_omits_environment_backed_tools() {
let model_info = model_info();
let mut features = Features::with_defaults();
features.enable(Feature::UnifiedExec);
features.enable(Feature::JsRepl);
let available_models = Vec::new();
let mut tools_config = ToolsConfig::new(&ToolsConfigParams {
model_info: &model_info,
@@ -462,8 +461,6 @@ fn disabled_environment_omits_environment_backed_tools() {
assert_lacks_tool_name(&tools, "exec_command");
assert_lacks_tool_name(&tools, "write_stdin");
assert_lacks_tool_name(&tools, "js_repl");
assert_lacks_tool_name(&tools, "js_repl_reset");
assert_lacks_tool_name(&tools, "apply_patch");
assert_lacks_tool_name(&tools, "list_dir");
assert_lacks_tool_name(&tools, VIEW_IMAGE_TOOL_NAME);
@@ -636,66 +633,6 @@ fn request_permissions_tool_is_independent_from_additional_permissions() {
assert_lacks_tool_name(&tools, "request_permissions");
}
#[test]
fn js_repl_requires_feature_flag() {
let model_info = model_info();
let features = Features::with_defaults();
let available_models = Vec::new();
let tools_config = ToolsConfig::new(&ToolsConfigParams {
model_info: &model_info,
available_models: &available_models,
features: &features,
image_generation_tool_auth_allowed: true,
web_search_mode: Some(WebSearchMode::Cached),
session_source: SessionSource::Cli,
sandbox_policy: &SandboxPolicy::DangerFullAccess,
windows_sandbox_level: WindowsSandboxLevel::Disabled,
});
let (tools, _) = build_specs(
&tools_config,
/*mcp_tools*/ None,
/*deferred_mcp_tools*/ None,
&[],
);
assert!(
!tools.iter().any(|tool| tool.spec.name() == "js_repl"),
"js_repl should be disabled when the feature is off"
);
assert!(
!tools.iter().any(|tool| tool.spec.name() == "js_repl_reset"),
"js_repl_reset should be disabled when the feature is off"
);
}
#[test]
fn js_repl_enabled_adds_tools() {
let model_info = model_info();
let mut features = Features::with_defaults();
features.enable(Feature::JsRepl);
let available_models = Vec::new();
let tools_config = ToolsConfig::new(&ToolsConfigParams {
model_info: &model_info,
available_models: &available_models,
features: &features,
image_generation_tool_auth_allowed: true,
web_search_mode: Some(WebSearchMode::Cached),
session_source: SessionSource::Cli,
sandbox_policy: &SandboxPolicy::DangerFullAccess,
windows_sandbox_level: WindowsSandboxLevel::Disabled,
});
let (tools, _) = build_specs(
&tools_config,
/*mcp_tools*/ None,
/*deferred_mcp_tools*/ None,
&[],
);
assert_contains_tool_names(&tools, &["js_repl", "js_repl_reset"]);
}
#[test]
fn image_generation_tools_require_feature_and_supported_model() {
let supported_model_info = model_info();
@@ -18,8 +18,6 @@ pub enum ToolHandlerKind {
CodeModeWait,
DynamicTool,
FollowupTaskV2,
JsRepl,
JsReplReset,
ListAgentsV2,
ListDir,
Mcp,