This commit is contained in:
Roy Han
2026-03-23 10:56:47 -07:00
parent 82a9f1fbf0
commit 2a612613f2
12 changed files with 221 additions and 2 deletions
@@ -1996,6 +1996,16 @@
"description": "Client-visible metadata ID generated by Codex for this item.",
"type": "string"
},
"sandbox_policy": {
"anyOf": [
{
"$ref": "#/definitions/SandboxPolicyMetadata"
},
{
"type": "null"
}
]
},
"user_message_type": {
"anyOf": [
{
@@ -2030,6 +2040,16 @@
}
]
},
"sandbox_policy": {
"anyOf": [
{
"$ref": "#/definitions/SandboxPolicyMetadata"
},
{
"type": "null"
}
]
},
"user_message_type": {
"anyOf": [
{
@@ -2408,6 +2428,14 @@
}
]
},
"SandboxPolicyMetadata": {
"enum": [
"read_only",
"sandbox",
"full_access"
],
"type": "string"
},
"ServiceTier": {
"enum": [
"fast",
@@ -10719,6 +10719,16 @@
"description": "Client-visible metadata ID generated by Codex for this item.",
"type": "string"
},
"sandbox_policy": {
"anyOf": [
{
"$ref": "#/definitions/v2/SandboxPolicyMetadata"
},
{
"type": "null"
}
]
},
"user_message_type": {
"anyOf": [
{
@@ -10753,6 +10763,16 @@
}
]
},
"sandbox_policy": {
"anyOf": [
{
"$ref": "#/definitions/v2/SandboxPolicyMetadata"
},
{
"type": "null"
}
]
},
"user_message_type": {
"anyOf": [
{
@@ -11151,6 +11171,14 @@
}
]
},
"SandboxPolicyMetadata": {
"enum": [
"read_only",
"sandbox",
"full_access"
],
"type": "string"
},
"SandboxWorkspaceWrite": {
"properties": {
"exclude_slash_tmp": {
@@ -7487,6 +7487,16 @@
"description": "Client-visible metadata ID generated by Codex for this item.",
"type": "string"
},
"sandbox_policy": {
"anyOf": [
{
"$ref": "#/definitions/SandboxPolicyMetadata"
},
{
"type": "null"
}
]
},
"user_message_type": {
"anyOf": [
{
@@ -7521,6 +7531,16 @@
}
]
},
"sandbox_policy": {
"anyOf": [
{
"$ref": "#/definitions/SandboxPolicyMetadata"
},
{
"type": "null"
}
]
},
"user_message_type": {
"anyOf": [
{
@@ -7919,6 +7939,14 @@
}
]
},
"SandboxPolicyMetadata": {
"enum": [
"read_only",
"sandbox",
"full_access"
],
"type": "string"
},
"SandboxWorkspaceWrite": {
"properties": {
"exclude_slash_tmp": {
@@ -844,6 +844,16 @@
"description": "Client-visible metadata ID generated by Codex for this item.",
"type": "string"
},
"sandbox_policy": {
"anyOf": [
{
"$ref": "#/definitions/SandboxPolicyMetadata"
},
{
"type": "null"
}
]
},
"user_message_type": {
"anyOf": [
{
@@ -878,6 +888,16 @@
}
]
},
"sandbox_policy": {
"anyOf": [
{
"$ref": "#/definitions/SandboxPolicyMetadata"
},
{
"type": "null"
}
]
},
"user_message_type": {
"anyOf": [
{
@@ -1004,6 +1024,14 @@
],
"type": "string"
},
"SandboxPolicyMetadata": {
"enum": [
"read_only",
"sandbox",
"full_access"
],
"type": "string"
},
"UserMessageType": {
"enum": [
"prompt",
@@ -910,6 +910,16 @@
"description": "Client-visible metadata ID generated by Codex for this item.",
"type": "string"
},
"sandbox_policy": {
"anyOf": [
{
"$ref": "#/definitions/SandboxPolicyMetadata"
},
{
"type": "null"
}
]
},
"user_message_type": {
"anyOf": [
{
@@ -944,6 +954,16 @@
}
]
},
"sandbox_policy": {
"anyOf": [
{
"$ref": "#/definitions/SandboxPolicyMetadata"
},
{
"type": "null"
}
]
},
"user_message_type": {
"anyOf": [
{
@@ -1078,6 +1098,14 @@
],
"type": "string"
},
"SandboxPolicyMetadata": {
"enum": [
"read_only",
"sandbox",
"full_access"
],
"type": "string"
},
"ServiceTier": {
"enum": [
"fast",
@@ -1,9 +1,10 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { SandboxPolicyMetadata } from "./SandboxPolicyMetadata";
import type { UserMessageType } from "./UserMessageType";
export type ResponseItemMessageMetadata = { user_message_type?: UserMessageType,
export type ResponseItemMessageMetadata = { user_message_type?: UserMessageType, sandbox_policy?: SandboxPolicyMetadata,
/**
* Client-visible metadata ID generated by Codex for this item.
*/
@@ -0,0 +1,8 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ReviewDecisionMetadata } from "./ReviewDecisionMetadata";
import type { SandboxPolicyMetadata } from "./SandboxPolicyMetadata";
import type { UserMessageType } from "./UserMessageType";
export type ResponseItemMetadata = { user_message_type?: UserMessageType, sandbox_policy?: SandboxPolicyMetadata, is_tool_call_escalated?: boolean, review_decision?: ReviewDecisionMetadata, };
@@ -0,0 +1,5 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type SandboxPolicyMetadata = "read_only" | "sandbox" | "full_access";
@@ -63,6 +63,7 @@ export type { ResponseItemMessageMetadata } from "./ResponseItemMessageMetadata"
export type { ResponseItemMetadata } from "./ResponseItemMetadata";
export type { ReviewDecision } from "./ReviewDecision";
export type { ReviewDecisionMetadata } from "./ReviewDecisionMetadata";
export type { SandboxPolicyMetadata } from "./SandboxPolicyMetadata";
export type { ServerNotification } from "./ServerNotification";
export type { ServerRequest } from "./ServerRequest";
export type { ServiceTier } from "./ServiceTier";
+31 -1
View File
@@ -83,6 +83,7 @@ use codex_protocol::config_types::Settings;
use codex_protocol::config_types::WebSearchMode;
use codex_protocol::dynamic_tools::DynamicToolResponse;
use codex_protocol::dynamic_tools::DynamicToolSpec;
use codex_protocol::item_metadata::stamp_sandbox_policy_on_input_item;
use codex_protocol::item_metadata::stamp_user_message_type_on_input_item;
use codex_protocol::items::PlanItem;
use codex_protocol::items::TurnItem;
@@ -335,6 +336,7 @@ use codex_protocol::models::ResponseInputItem;
use codex_protocol::models::ResponseItem;
use codex_protocol::models::ResponseItemMetadata;
use codex_protocol::models::ReviewDecisionMetadata;
use codex_protocol::models::SandboxPolicyMetadata;
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
use codex_protocol::protocol::CodexErrorInfo;
use codex_protocol::protocol::InitialHistory;
@@ -1027,6 +1029,16 @@ fn review_decision_to_metadata(decision: &ReviewDecision) -> ReviewDecisionMetad
}
}
fn sandbox_policy_to_metadata(policy: &SandboxPolicy) -> SandboxPolicyMetadata {
match policy {
SandboxPolicy::ReadOnly { .. } => SandboxPolicyMetadata::ReadOnly,
SandboxPolicy::WorkspaceWrite { .. } | SandboxPolicy::ExternalSandbox { .. } => {
SandboxPolicyMetadata::Sandbox
}
SandboxPolicy::DangerFullAccess => SandboxPolicyMetadata::FullAccess,
}
}
fn response_item_tool_call_id(item: &ResponseItem) -> Option<&str> {
match item {
ResponseItem::LocalShellCall {
@@ -3374,6 +3386,9 @@ impl Session {
| ResponseItem::CustomToolCall { metadata, .. } => metadata.clone().unwrap_or_default(),
_ => return response_item,
};
metadata.sandbox_policy = Some(sandbox_policy_to_metadata(
turn_context.sandbox_policy.get(),
));
match outcome {
Some(review_decision) => {
@@ -4050,7 +4065,7 @@ impl Session {
return Err(SteerInputError::NoActiveTurn(input));
};
let Some((active_turn_id, _)) = active_turn.tasks.first() else {
let Some((active_turn_id, active_turn_context)) = active_turn.tasks.first() else {
return Err(SteerInputError::NoActiveTurn(input));
};
@@ -4066,6 +4081,10 @@ impl Session {
let mut input_item: ResponseInputItem = input.into();
if self.enabled(Feature::ItemMetadata) {
stamp_user_message_type_on_input_item(&mut input_item, UserMessageType::PromptSteering);
stamp_sandbox_policy_on_input_item(
&mut input_item,
sandbox_policy_to_metadata(active_turn_context.sandbox_policy.get()),
);
}
let mut turn_state = active_turn.turn_state.lock().await;
@@ -4081,6 +4100,10 @@ impl Session {
let mut active = self.active_turn.lock().await;
match active.as_mut() {
Some(at) => {
let sandbox_policy = at
.tasks
.first()
.map(|(_, task)| sandbox_policy_to_metadata(task.sandbox_policy.get()));
let mut ts = at.turn_state.lock().await;
for mut item in input {
if self.enabled(Feature::ItemMetadata)
@@ -4090,6 +4113,9 @@ impl Session {
&mut item,
UserMessageType::PromptQueued,
);
if let Some(sandbox_policy) = sandbox_policy.clone() {
stamp_sandbox_policy_on_input_item(&mut item, sandbox_policy);
}
}
ts.push_pending_input(item);
}
@@ -5790,6 +5816,10 @@ pub(crate) async fn run_turn(
let mut initial_input_for_turn: ResponseInputItem = ResponseInputItem::from(input.clone());
if sess.enabled(Feature::ItemMetadata) {
stamp_user_message_type_on_input_item(&mut initial_input_for_turn, UserMessageType::Prompt);
stamp_sandbox_policy_on_input_item(
&mut initial_input_for_turn,
sandbox_policy_to_metadata(turn_context.sandbox_policy.get()),
);
}
let response_item: ResponseItem = initial_input_for_turn.clone().into();
sess.record_user_prompt_and_emit_turn_item(turn_context.as_ref(), &input, response_item)
+18
View File
@@ -1,5 +1,6 @@
use crate::models::ResponseInputItem;
use crate::models::ResponseItemMessageMetadata;
use crate::models::SandboxPolicyMetadata;
use crate::models::UserMessageType;
pub fn stamp_user_message_type_on_input_item(item: &mut ResponseInputItem, kind: UserMessageType) {
@@ -15,3 +16,20 @@ pub fn stamp_user_message_type_on_input_item(item: &mut ResponseInputItem, kind:
metadata_value.user_message_type = Some(kind);
*metadata = Some(metadata_value);
}
pub fn stamp_sandbox_policy_on_input_item(
item: &mut ResponseInputItem,
sandbox_policy: SandboxPolicyMetadata,
) {
let ResponseInputItem::Message { role, metadata, .. } = item else {
return;
};
if role != "user" {
return;
}
let mut metadata_value = metadata
.take()
.unwrap_or_else(|| ResponseItemMessageMetadata::new(/*user_message_type*/ None));
metadata_value.sandbox_policy = Some(sandbox_policy);
*metadata = Some(metadata_value);
}
+16
View File
@@ -274,6 +274,9 @@ pub struct ResponseItemMessageMetadata {
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional)]
pub user_message_type: Option<UserMessageType>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional)]
pub sandbox_policy: Option<SandboxPolicyMetadata>,
/// Client-visible metadata ID generated by Codex for this item.
pub metadata_id: String,
}
@@ -282,6 +285,7 @@ impl ResponseItemMessageMetadata {
pub fn new(user_message_type: Option<UserMessageType>) -> Self {
Self {
user_message_type,
sandbox_policy: None,
metadata_id: uuid::Uuid::new_v4().to_string(),
}
}
@@ -300,6 +304,15 @@ pub enum ReviewDecisionMetadata {
DeniedWithNetworkPolicyDeny,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "snake_case")]
#[ts(rename_all = "snake_case")]
pub enum SandboxPolicyMetadata {
ReadOnly,
Sandbox,
FullAccess,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, TS)]
pub struct ResponseItemMetadata {
#[serde(default, skip_serializing_if = "Option::is_none")]
@@ -307,6 +320,9 @@ pub struct ResponseItemMetadata {
pub user_message_type: Option<UserMessageType>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional)]
pub sandbox_policy: Option<SandboxPolicyMetadata>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional)]
pub is_tool_call_escalated: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional)]