Record sandbox backends in command execution analytics (#47568)

## Why

Command execution analytics lack the observed sandbox backend. Older execution servers may omit this information, so an unknown backend must remain distinguishable from an explicitly unsandboxed process.

## What changed

- Carry optional `sandbox_type` metadata through command execution items and emit its metric tag as `sandbox_backend` in analytics.
- Propagate the observed backend through unified execution completion and failure events, including asynchronous exits.
- Preserve missing backend information as `None` and mark executed user shell commands as `Some(SandboxType::None)`.
- Exclude the metadata from serialized command items and generated schemas and TypeScript types.

## Testing

Extend tests for missing and explicit executor backends, backend propagation on failed execution, and analytics payloads, including platform-specific backend tags in app-server integration coverage.

GitOrigin-RevId: 178fe46824a6194910802ec02168ed40ee0b2019
This commit is contained in:
iceweasel-oai
2026-09-23 15:05:59 +00:00
committed by copyberry
parent d6c4c6aea4
commit 6f6af0fce4
29 changed files with 113 additions and 21 deletions
+5
View File
@@ -242,6 +242,11 @@ pub struct ModelInvocationContext {
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq)]
pub struct CommandExecutionItem {
/// Observed process backend for live analytics; None means unknown or not launched.
#[serde(skip)]
#[schemars(skip)]
#[ts(skip)]
pub sandbox_type: Option<crate::sandbox::SandboxType>,
#[serde(skip)]
#[schemars(skip)]
#[ts(skip)]
+2
View File
@@ -5581,6 +5581,7 @@ mod tests {
started_at_ms: 10,
item: TurnItem::CommandExecution(CommandExecutionItem {
model_context: None,
sandbox_type: None,
id: "exec-1".into(),
plugin_id: Some("sample@openai-curated".into()),
script_path: Some("scripts/run.py".into()),
@@ -5608,6 +5609,7 @@ mod tests {
completed_at_ms: 20,
item: TurnItem::CommandExecution(CommandExecutionItem {
model_context: None,
sandbox_type: None,
id: "exec-1".into(),
plugin_id: Some("sample@openai-curated".into()),
script_path: Some("scripts/run.py".into()),