| """ |
| Configuration constants for the Geminicli2api proxy server. |
| Centralizes all configuration to avoid duplication across modules. |
| """ |
| import os |
|
|
| |
| CODE_ASSIST_ENDPOINT = "https://cloudcode-pa.googleapis.com" |
|
|
| |
| CLI_VERSION = "0.1.5" |
|
|
| |
| CLIENT_ID = "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com" |
| CLIENT_SECRET = "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" |
| SCOPES = [ |
| "https://www.googleapis.com/auth/cloud-platform", |
| "https://www.googleapis.com/auth/userinfo.email", |
| "https://www.googleapis.com/auth/userinfo.profile", |
| ] |
|
|
| |
| SCRIPT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
| CREDENTIAL_FILE = os.path.join(SCRIPT_DIR, os.getenv("GOOGLE_APPLICATION_CREDENTIALS", "oauth_creds.json")) |
|
|
| |
| GEMINI_AUTH_PASSWORD = os.getenv("GEMINI_AUTH_PASSWORD", "123456") |
|
|
| |
| DEFAULT_SAFETY_SETTINGS = [ |
| {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"}, |
| {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"}, |
| {"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_NONE"}, |
| {"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE"}, |
| {"category": "HARM_CATEGORY_CIVIC_INTEGRITY", "threshold": "BLOCK_NONE"}, |
| {"category": "HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE"}, |
| {"category": "HARM_CATEGORY_IMAGE_HARASSMENT", "threshold": "BLOCK_NONE"}, |
| {"category": "HARM_CATEGORY_IMAGE_HATE", "threshold": "BLOCK_NONE"}, |
| {"category": "HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT", "threshold": "BLOCK_NONE"}, |
| {"category": "HARM_CATEGORY_UNSPECIFIED", "threshold": "BLOCK_NONE"} |
| ] |
|
|
| |
| BASE_MODELS = [ |
| { |
| "name": "models/gemini-2.5-pro-preview-05-06", |
| "version": "001", |
| "displayName": "Gemini 2.5 Pro Preview 05-06", |
| "description": "Preview version of Gemini 2.5 Pro from May 6th", |
| "inputTokenLimit": 1048576, |
| "outputTokenLimit": 65535, |
| "supportedGenerationMethods": ["generateContent", "streamGenerateContent"], |
| "temperature": 1.0, |
| "maxTemperature": 2.0, |
| "topP": 0.95, |
| "topK": 64 |
| }, |
| { |
| "name": "models/gemini-2.5-pro-preview-06-05", |
| "version": "001", |
| "displayName": "Gemini 2.5 Pro Preview 06-05", |
| "description": "Preview version of Gemini 2.5 Pro from June 5th", |
| "inputTokenLimit": 1048576, |
| "outputTokenLimit": 65535, |
| "supportedGenerationMethods": ["generateContent", "streamGenerateContent"], |
| "temperature": 1.0, |
| "maxTemperature": 2.0, |
| "topP": 0.95, |
| "topK": 64 |
| }, |
| { |
| "name": "models/gemini-2.5-pro", |
| "version": "001", |
| "displayName": "Gemini 2.5 Pro", |
| "description": "Advanced multimodal model with enhanced capabilities", |
| "inputTokenLimit": 1048576, |
| "outputTokenLimit": 65535, |
| "supportedGenerationMethods": ["generateContent", "streamGenerateContent"], |
| "temperature": 1.0, |
| "maxTemperature": 2.0, |
| "topP": 0.95, |
| "topK": 64 |
| }, |
| { |
| "name": "models/gemini-2.5-flash-preview-05-20", |
| "version": "001", |
| "displayName": "Gemini 2.5 Flash Preview 05-20", |
| "description": "Preview version of Gemini 2.5 Flash from May 20th", |
| "inputTokenLimit": 1048576, |
| "outputTokenLimit": 65535, |
| "supportedGenerationMethods": ["generateContent", "streamGenerateContent"], |
| "temperature": 1.0, |
| "maxTemperature": 2.0, |
| "topP": 0.95, |
| "topK": 64 |
| }, |
| { |
| "name": "models/gemini-2.5-flash-preview-04-17", |
| "version": "001", |
| "displayName": "Gemini 2.5 Flash Preview 04-17", |
| "description": "Preview version of Gemini 2.5 Flash from April 17th", |
| "inputTokenLimit": 1048576, |
| "outputTokenLimit": 65535, |
| "supportedGenerationMethods": ["generateContent", "streamGenerateContent"], |
| "temperature": 1.0, |
| "maxTemperature": 2.0, |
| "topP": 0.95, |
| "topK": 64 |
| }, |
| { |
| "name": "models/gemini-2.5-flash", |
| "version": "001", |
| "displayName": "Gemini 2.5 Flash", |
| "description": "Fast and efficient multimodal model with latest improvements", |
| "inputTokenLimit": 1048576, |
| "outputTokenLimit": 65535, |
| "supportedGenerationMethods": ["generateContent", "streamGenerateContent"], |
| "temperature": 1.0, |
| "maxTemperature": 2.0, |
| "topP": 0.95, |
| "topK": 64 |
| } |
| ] |
|
|
| |
| def _generate_search_variants(): |
| """Generate search variants for models that support content generation.""" |
| search_models = [] |
| for model in BASE_MODELS: |
| |
| if "generateContent" in model["supportedGenerationMethods"]: |
| search_variant = model.copy() |
| search_variant["name"] = model["name"] + "-search" |
| search_variant["displayName"] = model["displayName"] + " with Google Search" |
| search_variant["description"] = model["description"] + " (includes Google Search grounding)" |
| search_models.append(search_variant) |
| return search_models |
|
|
| |
| def _generate_thinking_variants(): |
| """Generate nothinking and maxthinking variants for models that support thinking.""" |
| thinking_models = [] |
| for model in BASE_MODELS: |
| |
| |
| if ("generateContent" in model["supportedGenerationMethods"] and |
| ("gemini-2.5-flash" in model["name"] or "gemini-2.5-pro" in model["name"])): |
| |
| |
| nothinking_variant = model.copy() |
| nothinking_variant["name"] = model["name"] + "-nothinking" |
| nothinking_variant["displayName"] = model["displayName"] + " (No Thinking)" |
| nothinking_variant["description"] = model["description"] + " (thinking disabled)" |
| thinking_models.append(nothinking_variant) |
| |
| |
| maxthinking_variant = model.copy() |
| maxthinking_variant["name"] = model["name"] + "-maxthinking" |
| maxthinking_variant["displayName"] = model["displayName"] + " (Max Thinking)" |
| maxthinking_variant["description"] = model["description"] + " (maximum thinking budget)" |
| thinking_models.append(maxthinking_variant) |
| return thinking_models |
|
|
| |
| def _generate_combined_variants(): |
| """Generate combined search and thinking variants.""" |
| combined_models = [] |
| for model in BASE_MODELS: |
| |
| |
| if ("generateContent" in model["supportedGenerationMethods"] and |
| ("gemini-2.5-flash" in model["name"] or "gemini-2.5-pro" in model["name"])): |
| |
| |
| search_nothinking = model.copy() |
| search_nothinking["name"] = model["name"] + "-search-nothinking" |
| search_nothinking["displayName"] = model["displayName"] + " with Google Search (No Thinking)" |
| search_nothinking["description"] = model["description"] + " (includes Google Search grounding, thinking disabled)" |
| combined_models.append(search_nothinking) |
| |
| |
| search_maxthinking = model.copy() |
| search_maxthinking["name"] = model["name"] + "-search-maxthinking" |
| search_maxthinking["displayName"] = model["displayName"] + " with Google Search (Max Thinking)" |
| search_maxthinking["description"] = model["description"] + " (includes Google Search grounding, maximum thinking budget)" |
| combined_models.append(search_maxthinking) |
| return combined_models |
|
|
| |
| |
| all_models = BASE_MODELS + _generate_search_variants() + _generate_thinking_variants() |
| SUPPORTED_MODELS = sorted(all_models, key=lambda x: x['name']) |
|
|
| |
| def get_base_model_name(model_name): |
| """Convert variant model name to base model name.""" |
| |
| suffixes = ["-maxthinking", "-nothinking", "-search"] |
| for suffix in suffixes: |
| if model_name.endswith(suffix): |
| return model_name[:-len(suffix)] |
| return model_name |
|
|
| |
| def is_search_model(model_name): |
| """Check if model name indicates search grounding should be enabled.""" |
| return "-search" in model_name |
|
|
| |
| def is_nothinking_model(model_name): |
| """Check if model name indicates thinking should be disabled.""" |
| return "-nothinking" in model_name |
|
|
| |
| def is_maxthinking_model(model_name): |
| """Check if model name indicates maximum thinking budget should be used.""" |
| return "-maxthinking" in model_name |
|
|
| |
| def get_thinking_budget(model_name): |
| """Get the appropriate thinking budget for a model based on its name and variant.""" |
| base_model = get_base_model_name(model_name) |
| |
| if is_nothinking_model(model_name): |
| if "gemini-2.5-flash" in base_model: |
| return 0 |
| elif "gemini-2.5-pro" in base_model: |
| return 128 |
| elif is_maxthinking_model(model_name): |
| if "gemini-2.5-flash" in base_model: |
| return 24576 |
| elif "gemini-2.5-pro" in base_model: |
| return 32768 |
| else: |
| |
| return -1 |
|
|
| |
| def should_include_thoughts(model_name): |
| """Check if thoughts should be included in the response.""" |
| if is_nothinking_model(model_name): |
| |
| base_model = get_base_model_name(model_name) |
| return "gemini-2.5-pro" in base_model |
| else: |
| |
| return True |