mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Remove js_repl feature (#19410)
This commit is contained in:
@@ -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;
|
||||
@@ -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,
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user