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
2 changes: 1 addition & 1 deletion backend/app/core/cloud/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ def get_cloud_storage(session: Session, project_id: int) -> CloudStorage:
Method to create and configure a cloud storage instance.
"""
# Lazy import to avoid a top-level cycle: storage.py is imported from
# app.services.llm.providers.google_ai, which itself is wired into the
# app.services.llm.providers.google_gcp, which itself is wired into the
# provider registry that app.crud transitively pulls in.
from app.crud import get_project_by_id

Expand Down
11 changes: 11 additions & 0 deletions backend/app/core/providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class Provider(str, Enum):
OPENAI = "openai"
LANGFUSE = "langfuse"
GOOGLE_AISTUDIO = "google-aistudio"
GOOGLE_GCP = "google-gcp"
SARVAMAI = "sarvamai"
ELEVENLABS = "elevenlabs"
ANTHROPIC = "anthropic"
Expand Down Expand Up @@ -55,6 +56,16 @@ class ProviderConfig:
],
sensitive_fields=["api_key"],
),
Provider.GOOGLE_GCP: ProviderConfig(
required_fields=[
"api_key",
"project_id",
"location",
"sa_key",
"gcs_bucket",
],
sensitive_fields=["api_key", "sa_key"],
),
Provider.WEBHOOK_SECRET: ProviderConfig(
required_fields=["webhook_secret"], sensitive_fields=["webhook_secret"]
),
Expand Down
28 changes: 19 additions & 9 deletions backend/app/crud/credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,24 +199,34 @@ def update_creds_for_org(
):
credential_data = credential_data[creds_in.provider]

statement = select(Credential).where(
Credential.organization_id == org_id,
Credential.provider == creds_in.provider,
Credential.is_active.is_(True),
Credential.project_id == project_id,
)
creds = session.exec(statement).one_or_none()

# Merge onto the existing credentials so a partial payload (PATCH) only
# overwrites the fields it supplies instead of dropping the rest.
merged_credential_data = credential_data
if creds and creds.credential:
merged_credential_data = {
**decrypt_credentials(creds.credential),
**credential_data,
}

try:
validate_provider_credentials(creds_in.provider, credential_data)
validate_provider_credentials(creds_in.provider, merged_credential_data)
except ValueError as e:
logger.warning(
f"[update_creds_for_org] Validation error | organization_id: {org_id}, project_id: {project_id}, provider: {creds_in.provider}, error: {str(e)}"
)
raise HTTPException(status_code=400, detail=str(e))

# Encrypt the entire credentials object
encrypted_credentials = encrypt_credentials(credential_data)
encrypted_credentials = encrypt_credentials(merged_credential_data)

statement = select(Credential).where(
Credential.organization_id == org_id,
Credential.provider == creds_in.provider,
Credential.is_active.is_(True),
Credential.project_id == project_id,
)
creds = session.exec(statement).one_or_none()
if creds is None:
# Create new credential if it doesn't exist
creds = Credential(
Expand Down
5 changes: 5 additions & 0 deletions backend/app/models/llm/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class Provider(StrEnum):
ELEVENLABS = "elevenlabs"
ANTHROPIC = "anthropic"
GOOGLE_AISTUDIO = "google-aistudio"
GOOGLE_GCP = "google-gcp"
PROXY = "proxy"


Expand All @@ -17,12 +18,14 @@ class Provider(StrEnum):
# instead of leaving behind stale magic strings.
STTProvider = Literal[
Provider.GOOGLE,
Provider.GOOGLE_GCP,
Provider.SARVAMAI,
Provider.ELEVENLABS,
Provider.GOOGLE_AISTUDIO,
]
TTSProvider = Literal[
Provider.GOOGLE,
Provider.GOOGLE_GCP,
Provider.SARVAMAI,
Provider.ELEVENLABS,
Provider.GOOGLE_AISTUDIO,
Expand All @@ -32,6 +35,7 @@ class Provider(StrEnum):
KaapiProvider = Literal[
Provider.OPENAI,
Provider.GOOGLE,
Provider.GOOGLE_GCP,
Provider.SARVAMAI,
Provider.ELEVENLABS,
Provider.ANTHROPIC,
Expand All @@ -49,6 +53,7 @@ class Provider(StrEnum):
"elevenlabs-native",
"anthropic-native",
"google-aistudio-native",
"google-gcp-native",
]


Expand Down
4 changes: 2 additions & 2 deletions backend/app/models/llm/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,8 @@ class KaapiCompletionConfig(SQLModel):
None,
description=(
"LLM provider (openai, google, sarvamai, elevenlabs, anthropic, "
"google-aistudio). 'google' routes via Google Vertex AI; "
"'google-aistudio' uses Google AI Studio."
"google-aistudio, google-gcp). 'google-aistudio' uses Google AI "
"Studio; 'google-gcp' uses Google GCP directly for STT/TTS."
),
)

Expand Down
4 changes: 3 additions & 1 deletion backend/app/models/model_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class ModelConfigBase(SQLModel):
"anthropic",
"proxy",
"google-aistudio",
"google-gcp",
] = Field(
default="openai",
sa_column=sa.Column(
Expand All @@ -29,12 +30,13 @@ class ModelConfigBase(SQLModel):
"anthropic",
"proxy",
"google-aistudio",
"google-gcp",
name="provider_enum",
schema="global",
create_type=False,
),
nullable=False,
comment="provider name (e.g. openai, google, sarvamai, elevenlabs, anthropic, google-aistudio, proxy)",
comment="provider name (e.g. openai, google, sarvamai, elevenlabs, anthropic, google-aistudio, google-gcp, proxy)",
),
)

Expand Down
14 changes: 14 additions & 0 deletions backend/app/services/llm/mappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,20 @@ def transform_kaapi_config_to_native(
warnings,
)

if kaapi_config.provider == Provider.GOOGLE_GCP:
# Kaapi STT/TTS param shape is identical to Google's; reuse the Google mapper.
mapped_params, warnings = map_kaapi_to_google_params(
kaapi_config.params, kaapi_config.type
)
return (
NativeCompletionConfig(
provider="google-gcp-native",
params=mapped_params,
type=kaapi_config.type,
),
warnings,
)

if kaapi_config.provider == Provider.ANTHROPIC:
if kaapi_config.type != CompletionType.TEXT:
raise ValueError(
Expand Down
2 changes: 1 addition & 1 deletion backend/app/services/llm/providers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from app.services.llm.providers.eleven_ai import ElevenlabsAIProvider
from app.services.llm.providers.sarvam_ai import SarvamAIProvider
from app.services.llm.providers.claude import ClaudeProvider
from app.services.llm.providers.google_ai import GoogleVertexAIProvider
from app.services.llm.providers.google_gcp import GoogleGCPProvider
from app.services.llm.providers.registry import (
LLMProvider,
get_llm_provider,
Expand Down
Loading
Loading