mirror of
https://github.com/outbackdingo/optimclaw.git
synced 2026-08-27 08:00:17 +00:00
feat(gemini_oauth): full Cloud Code API integration with project discovery
- Register gemini_oauth as a dedicated backend in config/llm.rs (skip registry fallback, preserve backend name, suppress unknown-backend warning) - Fix app.rs credential guard to exclude backends with dedicated configs (gemini_oauth, bedrock) from the provider.is_none() check - Auto-discover Cloud Code project_id via loadCodeAssist when credentials lack it (e.g. created by the original Gemini CLI) - Persist discovered project_id to credentials file for subsequent runs - Add safety settings (BLOCK_NONE), gated behind GEMINI_SAFETY_BLOCK_NONE env - Add thinkingConfig: budget-based for Gemini 2.5, level-based for Gemini 3.x (without includeThoughts to avoid empty responses from reasoning.rs stripping) - Add thought signature injection for Gemini 3.x preview APIs - Add history curation to filter invalid model outputs before re-sending - Add extended generationConfig env vars (topP, topK, seed, penalties, responseMimeType, responseJsonSchema, cachedContent) - Add custom headers support via GEMINI_CLI_CUSTOM_HEADERS - Add API key auth mode (GEMINI_API_KEY + GEMINI_API_KEY_AUTH_MECHANISM) - Add SSE metadata extraction (modelVersion, credits, promptFeedback, groundingMetadata, citationMetadata, cachedContentTokenCount) - Add countTokens API support - Add new models to wizard (gemini-3.1-pro-preview-customtools, gemini-3-pro-preview, gemini-3.1-flash-lite-preview) - Update docs/LLM_PROVIDERS.md with new models and routing rules - Rewrite regression tests with comprehensive coverage (23 unit tests pass)
This commit is contained in:
@@ -1,28 +1,96 @@
|
||||
use ironclaw::llm::ChatMessage;
|
||||
use ironclaw::llm::gemini_oauth::GeminiOauthProvider;
|
||||
|
||||
/// Regression: Cloud Code API routing for Gemini 2.0+ models.
|
||||
/// Gemini 1.x → legacy generativelanguage.googleapis.com
|
||||
/// Gemini 2.0+ → Cloud Code API (cloudcode-pa.googleapis.com)
|
||||
#[test]
|
||||
fn test_regression_gemini_oauth_fields() {
|
||||
// This test ensures that the CompletionResponse and ToolCompletionResponse
|
||||
// include the newly added caching fields, which was a critical compilation fix.
|
||||
// Since we are using the public API, if it compiles and runs, the fields are present.
|
||||
fn test_regression_cloud_code_api_routing() {
|
||||
// Legacy models (1.x) → false
|
||||
assert!(!GeminiOauthProvider::model_uses_cloud_code_api(
|
||||
"gemini-1.5-pro"
|
||||
));
|
||||
assert!(!GeminiOauthProvider::model_uses_cloud_code_api(
|
||||
"gemini-1.5-flash"
|
||||
));
|
||||
|
||||
// Test model metadata logic (which we updated)
|
||||
assert!(
|
||||
!ironclaw::llm::gemini_oauth::GeminiOauthProvider::model_uses_cloud_code_api(
|
||||
"gemini-1.5-pro"
|
||||
)
|
||||
);
|
||||
assert!(
|
||||
ironclaw::llm::gemini_oauth::GeminiOauthProvider::model_uses_cloud_code_api(
|
||||
"gemini-2.0-flash"
|
||||
)
|
||||
);
|
||||
// 2.0+ models → true
|
||||
assert!(GeminiOauthProvider::model_uses_cloud_code_api(
|
||||
"gemini-2.0-flash"
|
||||
));
|
||||
assert!(GeminiOauthProvider::model_uses_cloud_code_api(
|
||||
"gemini-2.5-pro"
|
||||
));
|
||||
assert!(GeminiOauthProvider::model_uses_cloud_code_api(
|
||||
"gemini-2.5-flash"
|
||||
));
|
||||
|
||||
// Preview models with hyphen → true
|
||||
assert!(GeminiOauthProvider::model_uses_cloud_code_api(
|
||||
"gemini-3.1-pro-preview"
|
||||
));
|
||||
assert!(GeminiOauthProvider::model_uses_cloud_code_api(
|
||||
"gemini-3-flash-preview"
|
||||
));
|
||||
|
||||
// Gemini 3 family → true
|
||||
assert!(GeminiOauthProvider::model_uses_cloud_code_api(
|
||||
"gemini-3-pro"
|
||||
));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_regression_chat_message_helpers() {
|
||||
// Verify ChatMessage helper methods which were used to fix tests
|
||||
let msg = ChatMessage::user("test");
|
||||
assert_eq!(msg.role, ironclaw::llm::Role::User);
|
||||
assert_eq!(msg.content, "test");
|
||||
/// Regression: "preview" false-positive fix.
|
||||
/// `model.contains("-preview")` (with hyphen) prevents models whose name
|
||||
/// happens to include "preview" without a hyphen prefix from being
|
||||
/// mis-routed to Cloud Code API.
|
||||
#[test]
|
||||
fn test_regression_preview_false_positive_fix() {
|
||||
// "my-preview-custom" still matches (contains "-preview")
|
||||
assert!(GeminiOauthProvider::model_uses_cloud_code_api(
|
||||
"my-preview-custom"
|
||||
));
|
||||
|
||||
// "mypreviewcustom" does NOT match (no hyphen before "preview")
|
||||
assert!(!GeminiOauthProvider::model_uses_cloud_code_api(
|
||||
"mypreviewcustom"
|
||||
));
|
||||
|
||||
// Non-Gemini models without "-preview" → false
|
||||
assert!(!GeminiOauthProvider::model_uses_cloud_code_api(
|
||||
"not-a-gemini-model"
|
||||
));
|
||||
}
|
||||
|
||||
/// Regression: model list consistency.
|
||||
/// Wizard, list_models(), and LLM_PROVIDERS.md all return the same 5 models.
|
||||
#[test]
|
||||
fn test_regression_standardized_model_list() {
|
||||
let expected_models = [
|
||||
"gemini-3.1-pro-preview",
|
||||
"gemini-3-flash-preview",
|
||||
"gemini-2.5-pro",
|
||||
"gemini-2.5-flash",
|
||||
"gemini-2.5-flash-lite",
|
||||
];
|
||||
|
||||
// All standardized models must route to Cloud Code API (all are >= 2.0)
|
||||
for model in &expected_models {
|
||||
assert!(
|
||||
GeminiOauthProvider::model_uses_cloud_code_api(model),
|
||||
"Standardized model '{}' should route to Cloud Code API",
|
||||
model
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Regression: ChatMessage helper constructors.
|
||||
#[test]
|
||||
fn test_regression_chat_message_helpers() {
|
||||
let user_msg = ChatMessage::user("hello");
|
||||
assert_eq!(user_msg.role, ironclaw::llm::Role::User);
|
||||
assert_eq!(user_msg.content, "hello");
|
||||
|
||||
let system_msg = ChatMessage::system("you are helpful");
|
||||
assert_eq!(system_msg.role, ironclaw::llm::Role::System);
|
||||
assert_eq!(system_msg.content, "you are helpful");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user