Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions crates/lingua/src/providers/google/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -969,6 +969,21 @@ impl TryFromLLM<Vec<GoogleTool>> for Vec<UniversalTool> {
Some(Value::Object(url_context.clone())),
));
}

if let Some(computer_use) = &tool.computer_use {
let config = serde_json::to_value(computer_use).map_err(|e| {
ConvertError::JsonSerializationFailed {
field: "computer_use".to_string(),
error: e.to_string(),
}
})?;
result.push(UniversalTool::builtin(
"computer_use",
BuiltinToolProvider::Google,
"computer_use",
Some(config),
));
}
}

Ok(result)
Expand Down Expand Up @@ -1022,6 +1037,11 @@ impl TryFromLLM<Vec<UniversalTool>> for Vec<GoogleTool> {
_ => None,
});
}
"computer_use" => {
google_tool.computer_use = config
.as_ref()
.and_then(|v| serde_json::from_value(v.clone()).ok());
Comment on lines +1040 to +1043

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Return errors for invalid computer_use configs

When a universal Google builtin computer_use tool has malformed or missing config, this branch turns the deserialization failure into None; the code then still pushes the default GoogleTool after the match, so the generated Google request contains an empty {} tool instead of surfacing the bad config. That hides the conversion error and can produce an invalid provider request for user-supplied universal tools.

Useful? React with 👍 / 👎.

}
_ => {
continue;
}
Expand Down Expand Up @@ -1746,6 +1766,69 @@ mod tests {
assert_eq!(back[0].url_context, Some(Map::new()));
}

#[test]
fn test_computer_use_builtin_roundtrip() {
use crate::providers::google::generated::{ComputerUse, DisabledSafetyPolicy, Environment};

let computer_use = ComputerUse {
environment: Some(Environment::EnvironmentBrowser),
disabled_safety_policies: Some(vec![
DisabledSafetyPolicy::FinancialTransactions,
DisabledSafetyPolicy::AccountCreation,
]),
enable_prompt_injection_detection: Some(true),
excluded_predefined_functions: None,
};

let google_tools = vec![GoogleTool {
computer_use: Some(computer_use.clone()),
..Default::default()
}];

let universal =
<Vec<UniversalTool> as TryFromLLM<Vec<GoogleTool>>>::try_from(google_tools).unwrap();
assert_eq!(universal.len(), 1);
assert_eq!(universal[0].name, "computer_use");
assert!(!universal[0].is_function());

let back =
<Vec<GoogleTool> as TryFromLLM<Vec<UniversalTool>>>::try_from(universal).unwrap();
assert_eq!(back.len(), 1);
assert_eq!(back[0].computer_use, Some(computer_use));
}

#[test]
fn test_computer_use_new_environments_roundtrip() {
use crate::providers::google::generated::{ComputerUse, Environment};

for env in [
Environment::EnvironmentDesktop,
Environment::EnvironmentMobile,
] {
let computer_use = ComputerUse {
environment: Some(env.clone()),
disabled_safety_policies: None,
enable_prompt_injection_detection: None,
excluded_predefined_functions: None,
};

let google_tools = vec![GoogleTool {
computer_use: Some(computer_use.clone()),
..Default::default()
}];

let universal =
<Vec<UniversalTool> as TryFromLLM<Vec<GoogleTool>>>::try_from(google_tools)
.unwrap();
let back =
<Vec<GoogleTool> as TryFromLLM<Vec<UniversalTool>>>::try_from(universal).unwrap();
assert_eq!(
back[0].computer_use.as_ref().unwrap().environment,
Some(env)
);
}
}

#[test]
fn test_executable_code_parts_roundtrip() {
let google_content = vec![GoogleContent {
Expand Down
32 changes: 32 additions & 0 deletions crates/lingua/src/providers/google/generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1390,6 +1390,12 @@ pub struct Tool {
#[serde(rename_all = "camelCase")]
#[ts(export_to = "google/")]
pub struct ComputerUse {
/// Optional. Disabled safety policies for computer use.
#[serde(skip_serializing_if = "Option::is_none")]
pub disabled_safety_policies: Option<Vec<DisabledSafetyPolicy>>,
/// Optional. Whether enable the prompt injection detection check on computer-use request.
#[serde(skip_serializing_if = "Option::is_none")]
pub enable_prompt_injection_detection: Option<bool>,
/// Required. The environment being operated.
#[serde(skip_serializing_if = "Option::is_none")]
pub environment: Option<Environment>,
Expand All @@ -1401,13 +1407,39 @@ pub struct ComputerUse {
pub excluded_predefined_functions: Option<Vec<String>>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
#[ts(export_to = "google/")]
pub enum DisabledSafetyPolicy {
#[serde(rename = "ACCOUNT_CREATION")]
AccountCreation,
#[serde(rename = "COMMUNICATION_TOOL")]
CommunicationTool,
#[serde(rename = "DATA_MODIFICATION")]
DataModification,
#[serde(rename = "FINANCIAL_TRANSACTIONS")]
FinancialTransactions,
#[serde(rename = "LEGAL_TERMS_AND_AGREEMENTS")]
LegalTermsAndAgreements,
#[serde(rename = "SAFETY_POLICY_UNSPECIFIED")]
SafetyPolicyUnspecified,
#[serde(rename = "SENSITIVE_DATA_MODIFICATION")]
SensitiveDataModification,
#[serde(rename = "USER_CONSENT_MANAGEMENT")]
UserConsentManagement,
}

/// Required. The environment being operated.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
#[ts(export_to = "google/")]
pub enum Environment {
#[serde(rename = "ENVIRONMENT_BROWSER")]
EnvironmentBrowser,
#[serde(rename = "ENVIRONMENT_DESKTOP")]
EnvironmentDesktop,
#[serde(rename = "ENVIRONMENT_MOBILE")]
EnvironmentMobile,
#[serde(rename = "ENVIRONMENT_UNSPECIFIED")]
EnvironmentUnspecified,
}
Expand Down
31 changes: 31 additions & 0 deletions provider-type-update-notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Google provider type update notes

## Changes in this update

### `ComputerUse` struct: two new optional fields

- `disabled_safety_policies: Option<Vec<DisabledSafetyPolicy>>` — allows disabling specific safety policies for computer use sessions.
- `enable_prompt_injection_detection: Option<bool>` — enables prompt injection detection on computer-use requests.

### New `DisabledSafetyPolicy` enum

Eight variants: `AccountCreation`, `CommunicationTool`, `DataModification`, `FinancialTransactions`, `LegalTermsAndAgreements`, `SafetyPolicyUnspecified`, `SensitiveDataModification`, `UserConsentManagement`.

### `Environment` enum: two new variants

- `EnvironmentDesktop` — desktop environment for computer use.
- `EnvironmentMobile` — mobile environment for computer use.

## Adapter changes made

Added `computer_use` as a builtin tool type in the `GoogleTool` <-> `UniversalTool` conversion (`convert.rs`). Previously, `computer_use` was silently dropped during tool conversion. It now roundtrips through `UniversalTool::builtin` with its full typed config (including the new fields), matching the existing pattern for `google_search`, `code_execution`, `google_search_retrieval`, and `url_context`.

## No changes needed

- No new `FinishReason` variants were added, so no finish-reason mapping updates are required.
- No new roles or content part types were added.
- All new fields are optional and serialize/deserialize correctly via serde without adapter changes.

## Pre-existing gaps not addressed

- `file_search` and `google_maps` tool types on the `GoogleTool` struct are not yet handled in the builtin tool conversion (same as before this update — they were not modified in this diff).
Loading
Loading