mirror of
https://github.com/openai/codex.git
synced 2026-10-23 18:08:45 +00:00
Approve the first Node REPL execution without a Guardian wait (#41666)
## Why The first REPL execution should proceed while its initial asynchronous Guardian classification is still pending. ## What changed - Fast-approve the first `js` execution from a Node REPL-backed server while continuing its asynchronous classification. - Track `js` executions separately so setup and reset tools do not consume the first-execution allowance. - Apply the normal Guardian review policy to subsequent executions. ## Testing Add coverage for browser and computer-use startup, reset, and module-directory setup sequences, verifying that only the first `js` execution skips the wait. GitOrigin-RevId: 7297b35411a6317bcf9e7058c08c6db3e3310ac8
This commit is contained in:
@@ -113,6 +113,8 @@ enum ClassificationOutcome {
|
||||
#[derive(Default)]
|
||||
struct GuardianV2ScoreProgress {
|
||||
latest_tool_call: AtomicUsize,
|
||||
// Setup and reset calls must not consume the first JS execution allowance.
|
||||
js_executions: AtomicUsize,
|
||||
latest_scored_tool_call: AtomicUsize,
|
||||
latest_failed_tool_call: AtomicUsize,
|
||||
// Serialize successful score publication with its authorization metadata.
|
||||
@@ -261,6 +263,26 @@ impl ApprovalReviewContributor for GuardianV2Extension {
|
||||
record_fast_decision(extension_metrics.as_deref(), "deferred", "out_of_scope");
|
||||
return None;
|
||||
}
|
||||
// The first REPL execution never waits for synchronous Guardian review.
|
||||
// The async classifier still runs, and later calls use the normal policy.
|
||||
if action.get("tool_name").and_then(serde_json::Value::as_str) == Some("js")
|
||||
&& action
|
||||
.get("connector_id")
|
||||
.and_then(serde_json::Value::as_str)
|
||||
== Some("node_repl")
|
||||
&& thread_store
|
||||
.get::<GuardianV2ScoreProgress>()?
|
||||
.js_executions
|
||||
.load(Ordering::Acquire)
|
||||
== 1
|
||||
{
|
||||
record_fast_decision(
|
||||
extension_metrics.as_deref(),
|
||||
"approved",
|
||||
"initial_cua_call",
|
||||
);
|
||||
return Some(ReviewDecision::Approved);
|
||||
}
|
||||
} else if thread_store.get::<ModelInfo>().is_some() {
|
||||
let manager = self.thread_manager.upgrade()?;
|
||||
let thread_id = ThreadId::from_string(thread_store.level_id()).ok()?;
|
||||
@@ -400,6 +422,14 @@ impl GuardianV2Extension {
|
||||
}
|
||||
return;
|
||||
}
|
||||
if input.mcp_tool.is_some_and(|tool| {
|
||||
let info = tool.tool_info();
|
||||
is_node_repl_backed_server(&info.server_name) && info.tool.name == "js"
|
||||
}) {
|
||||
score_progress
|
||||
.js_executions
|
||||
.fetch_add(/*val*/ 1, Ordering::Relaxed);
|
||||
}
|
||||
let metrics = score_progress.metrics.clone();
|
||||
let sampled_at = SystemTime::now();
|
||||
let tool_call_index = score_progress
|
||||
|
||||
Reference in New Issue
Block a user