mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
dynamic tool calls: add param exposeToContext to optionally hide tool (#14501)
This extends dynamic_tool_calls to allow us to hide a tool from the model context but still use it as part of the general tool calling runtime (for ex from js_repl/code_mode)
This commit is contained in:
committed by
GitHub
Unverified
parent
e389091042
commit
70eddad6b0
@@ -6219,9 +6219,25 @@ fn build_prompt(
|
||||
turn_context: &TurnContext,
|
||||
base_instructions: BaseInstructions,
|
||||
) -> Prompt {
|
||||
let deferred_dynamic_tools = turn_context
|
||||
.dynamic_tools
|
||||
.iter()
|
||||
.filter(|tool| tool.defer_loading)
|
||||
.map(|tool| tool.name.as_str())
|
||||
.collect::<HashSet<_>>();
|
||||
let tools = if deferred_dynamic_tools.is_empty() {
|
||||
router.model_visible_specs()
|
||||
} else {
|
||||
router
|
||||
.model_visible_specs()
|
||||
.into_iter()
|
||||
.filter(|spec| !deferred_dynamic_tools.contains(spec.name()))
|
||||
.collect()
|
||||
};
|
||||
|
||||
Prompt {
|
||||
input,
|
||||
tools: router.model_visible_specs(),
|
||||
tools,
|
||||
parallel_tool_calls: turn_context.model_info.supports_parallel_tool_calls,
|
||||
base_instructions,
|
||||
personality: turn_context.personality,
|
||||
|
||||
@@ -1851,6 +1851,7 @@ async fn js_repl_emit_image_rejects_mixed_content() -> anyhow::Result<()> {
|
||||
"properties": {},
|
||||
"additionalProperties": false
|
||||
}),
|
||||
defer_loading: false,
|
||||
}])
|
||||
.await;
|
||||
if !turn
|
||||
@@ -1949,6 +1950,7 @@ async fn js_repl_dynamic_tool_response_preserves_js_line_separator_text() -> any
|
||||
"properties": {},
|
||||
"additionalProperties": false
|
||||
}),
|
||||
defer_loading: false,
|
||||
}])
|
||||
.await;
|
||||
|
||||
@@ -2008,6 +2010,79 @@ console.log(text);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn js_repl_can_call_hidden_dynamic_tools() -> anyhow::Result<()> {
|
||||
if !can_run_js_repl_runtime_tests().await {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let (session, turn, rx_event) =
|
||||
make_session_and_context_with_dynamic_tools_and_rx(vec![DynamicToolSpec {
|
||||
name: "hidden_dynamic_tool".to_string(),
|
||||
description: "A hidden dynamic tool.".to_string(),
|
||||
input_schema: serde_json::json!({
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"city": { "type": "string" }
|
||||
},
|
||||
"required": ["city"],
|
||||
"additionalProperties": false
|
||||
}),
|
||||
defer_loading: true,
|
||||
}])
|
||||
.await;
|
||||
|
||||
*session.active_turn.lock().await = Some(crate::state::ActiveTurn::default());
|
||||
|
||||
let tracker = Arc::new(tokio::sync::Mutex::new(TurnDiffTracker::default()));
|
||||
let manager = turn.js_repl.manager().await?;
|
||||
let code = r#"
|
||||
const out = await codex.tool("hidden_dynamic_tool", { city: "Paris" });
|
||||
console.log(JSON.stringify(out));
|
||||
"#;
|
||||
|
||||
let session_for_response = Arc::clone(&session);
|
||||
let response_watcher = async move {
|
||||
loop {
|
||||
let event = tokio::time::timeout(Duration::from_secs(2), rx_event.recv()).await??;
|
||||
if let EventMsg::DynamicToolCallRequest(request) = event.msg {
|
||||
session_for_response
|
||||
.notify_dynamic_tool_response(
|
||||
&request.call_id,
|
||||
DynamicToolResponse {
|
||||
content_items: vec![DynamicToolCallOutputContentItem::InputText {
|
||||
text: "hidden-ok".to_string(),
|
||||
}],
|
||||
success: true,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
return Ok::<(), anyhow::Error>(());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let (result, response_watcher_result) = tokio::join!(
|
||||
manager.execute(
|
||||
Arc::clone(&session),
|
||||
Arc::clone(&turn),
|
||||
tracker,
|
||||
JsReplArgs {
|
||||
code: code.to_string(),
|
||||
timeout_ms: Some(15_000),
|
||||
},
|
||||
),
|
||||
response_watcher,
|
||||
);
|
||||
|
||||
let result = result?;
|
||||
response_watcher_result?;
|
||||
assert!(result.output.contains("hidden-ok"));
|
||||
assert!(session.get_pending_input().await.is_empty());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn js_repl_prefers_env_node_module_dirs_over_config() -> anyhow::Result<()> {
|
||||
if !can_run_js_repl_runtime_tests().await {
|
||||
|
||||
Reference in New Issue
Block a user