Add optional names to untrusted additional context (#57181)

## What changed

- Add an optional `name` to `AdditionalContextEntry` across the protocol, app-server schemas, and generated clients.
- Accept names matching `[a-z][a-z0-9_]{0,63}` only for `untrusted` context. Reject invalid names and names on `application` context before admitting turn input, returning invalid-request errors from `turn/start` and `turn/steer`.
- Preserve existing model-input rendering and deduplicate context when only its name changes.

## Testing

Add coverage for valid name boundaries, callers that omit `name`, invalid-name rejection without admitting input, and deduplication across name changes.

GitOrigin-RevId: 2caffa6fddd40ddb178733b335f520f317239edd
This commit is contained in:
Alex Kira
2026-10-26 18:23:07 +00:00
committed by copyberry
parent 457441bca9
commit 8ebd272491
21 changed files with 371 additions and 102 deletions
+39
View File
@@ -646,6 +646,45 @@ pub enum AdditionalContextKind {
pub struct AdditionalContextEntry {
pub value: String,
pub kind: AdditionalContextKind,
/// Optional name for untrusted context, used to label its tool output.
pub name: Option<String>,
}
impl AdditionalContextEntry {
/// Creates an unnamed context entry.
pub fn new(value: String, kind: AdditionalContextKind) -> Self {
Self {
value,
kind,
name: None,
}
}
/// Sets the name for untrusted context.
pub fn with_name(mut self, name: impl Into<String>) -> Self {
self.name = Some(name.into());
self
}
/// Validates the optional untrusted-context name before input admission.
pub fn validate(&self) -> Result<(), &'static str> {
let Some(name) = &self.name else {
return Ok(());
};
if self.kind == AdditionalContextKind::Application {
return Err("additional context name is only supported for untrusted context");
}
if name.is_empty()
|| name.len() > 64
|| !name.as_bytes()[0].is_ascii_lowercase()
|| !name
.bytes()
.all(|byte| byte.is_ascii_lowercase() || byte.is_ascii_digit() || byte == b'_')
{
return Err("additional context name must match [a-z][a-z0-9_]{0,63}");
}
Ok(())
}
}
/// Submission operation