|
|
""" |
|
|
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 |