Add audio variants to user input protocols (#33923)

## What changed

- Add remote and local audio variants to core and app-server user inputs, including generated JSON and TypeScript schemas.
- Preserve audio fields when converting app-server inputs and response content into thread items.
- Keep unsupported audio out of model requests, TUI rendering, text extraction, and truncated tool output, using explicit text placeholders where audio is submitted as a model input.

## Testing

- Cover app-server media conversion, unsupported-input placeholders, TUI omission, and tool-output truncation.

GitOrigin-RevId: 16152bf3af674575ce569764a8b472e032e7569d
This commit is contained in:
nhamidi-oai authored and copyberry committed 2026-07-17 23:14:37 +00:00
1 parent e98765c212
commit 97dbd01a3d
49 files changed
+1330 -33

No files matched your search

+12 -2
View File
@@ -38,12 +38,20 @@ pub fn formatted_truncate_text_content_items_with_policy(
.filter_map(|item| match item {
FunctionCallOutputContentItem::InputText { text } => Some(text.as_str()),
FunctionCallOutputContentItem::InputImage { .. }
| FunctionCallOutputContentItem::InputAudio { .. }
| FunctionCallOutputContentItem::EncryptedContent { .. } => None,
})
.collect::<Vec<_>>();
let without_audio = || {
items
.iter()
.filter(|item| !matches!(item, FunctionCallOutputContentItem::InputAudio { .. }))
.cloned()
.collect()
};
if text_segments.is_empty() {
return (items.to_vec(), None);
return (without_audio(), None);
}
let mut combined = String::new();
@@ -55,7 +63,7 @@ pub fn formatted_truncate_text_content_items_with_policy(
}
if combined.len() <= policy.byte_budget() {
return (items.to_vec(), None);
return (without_audio(), None);
}
let original_token_count = approx_token_count(&combined);
@@ -69,6 +77,7 @@ pub fn formatted_truncate_text_content_items_with_policy(
detail: *detail,
})
}
FunctionCallOutputContentItem::InputAudio { .. } => None,
FunctionCallOutputContentItem::EncryptedContent { encrypted_content } => {
Some(FunctionCallOutputContentItem::EncryptedContent {
encrypted_content: encrypted_content.clone(),
@@ -127,6 +136,7 @@ pub fn truncate_function_output_items_with_policy(
detail: *detail,
});
}
FunctionCallOutputContentItem::InputAudio { .. } => {}
FunctionCallOutputContentItem::EncryptedContent { encrypted_content } => {
out.push(FunctionCallOutputContentItem::EncryptedContent {
encrypted_content: encrypted_content.clone(),
@@ -208,7 +208,7 @@ fn formatted_truncate_text_content_items_with_policy_preserves_empty_leading_tex
}
#[test]
fn formatted_truncate_text_content_items_with_policy_merges_text_and_appends_images() {
fn formatted_truncate_text_content_items_with_policy_merges_text_and_drops_audio() {
let items = vec![
FunctionCallOutputContentItem::InputText {
text: "abcd".to_string(),
@@ -220,6 +220,9 @@ fn formatted_truncate_text_content_items_with_policy_merges_text_and_appends_ima
FunctionCallOutputContentItem::InputText {
text: "efgh".to_string(),
},
FunctionCallOutputContentItem::InputAudio {
audio_url: "audio:one".to_string(),
},
FunctionCallOutputContentItem::InputText {
text: "ijkl".to_string(),
},
@@ -280,7 +283,7 @@ fn formatted_truncate_text_content_items_with_policy_preserves_encrypted_content
}
#[test]
fn truncate_function_output_items_with_policy_preserves_encrypted_content() {
fn truncate_function_output_items_with_policy_preserves_encrypted_content_and_drops_audio() {
let items = vec![
FunctionCallOutputContentItem::InputText {
text: "abcdefgh".to_string(),
@@ -288,6 +291,9 @@ fn truncate_function_output_items_with_policy_preserves_encrypted_content() {
FunctionCallOutputContentItem::EncryptedContent {
encrypted_content: "enc_opaque".to_string(),
},
FunctionCallOutputContentItem::InputAudio {
audio_url: "audio:one".to_string(),
},
];
let output = truncate_function_output_items_with_policy(&items, TruncationPolicy::Bytes(2));