mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-06-10 08:05:22 +02:00
chore: finish renaming UserConfiguration
This commit is contained in:
parent
cdbd06c8d9
commit
91ac460799
16 changed files with 62 additions and 62 deletions
|
|
@ -19,7 +19,7 @@ from api.db.models import (
|
|||
WorkflowRunModel,
|
||||
)
|
||||
from api.enums import OrganizationConfigurationKey
|
||||
from api.schemas.user_configuration import UserConfiguration
|
||||
from api.schemas.user_configuration import EffectiveAIModelConfiguration
|
||||
|
||||
|
||||
class OrganizationUsageClient(BaseDBClient):
|
||||
|
|
@ -473,7 +473,7 @@ class OrganizationUsageClient(BaseDBClient):
|
|||
)
|
||||
config_obj = config_result.scalar_one_or_none()
|
||||
if config_obj and config_obj.configuration:
|
||||
user_config = UserConfiguration.model_validate(
|
||||
user_config = EffectiveAIModelConfiguration.model_validate(
|
||||
config_obj.configuration
|
||||
)
|
||||
if user_config.timezone and user_timezone == "UTC":
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from sqlalchemy.future import select
|
|||
|
||||
from api.db.base_client import BaseDBClient
|
||||
from api.db.models import UserConfigurationModel, UserModel
|
||||
from api.schemas.user_configuration import UserConfiguration
|
||||
from api.schemas.user_configuration import EffectiveAIModelConfiguration
|
||||
|
||||
|
||||
class UserClient(BaseDBClient):
|
||||
|
|
@ -65,7 +65,9 @@ class UserClient(BaseDBClient):
|
|||
)
|
||||
return result.scalars().first()
|
||||
|
||||
async def get_user_configurations(self, user_id: int) -> UserConfiguration:
|
||||
async def get_user_configurations(
|
||||
self, user_id: int
|
||||
) -> EffectiveAIModelConfiguration:
|
||||
async with self.async_session() as session:
|
||||
result = await session.execute(
|
||||
select(UserConfigurationModel).where(
|
||||
|
|
@ -74,10 +76,10 @@ class UserClient(BaseDBClient):
|
|||
)
|
||||
configuration_obj = result.scalars().first()
|
||||
if not configuration_obj:
|
||||
return UserConfiguration()
|
||||
return EffectiveAIModelConfiguration()
|
||||
|
||||
try:
|
||||
return UserConfiguration.model_validate(
|
||||
return EffectiveAIModelConfiguration.model_validate(
|
||||
{
|
||||
**configuration_obj.configuration,
|
||||
"last_validated_at": configuration_obj.last_validated_at,
|
||||
|
|
@ -90,11 +92,11 @@ class UserClient(BaseDBClient):
|
|||
f"Failed to validate user configuration for user {user_id}: {e}. "
|
||||
"Returning default configuration."
|
||||
)
|
||||
return UserConfiguration()
|
||||
return EffectiveAIModelConfiguration()
|
||||
|
||||
async def update_user_configuration(
|
||||
self, user_id: int, configuration: UserConfiguration
|
||||
) -> UserConfiguration:
|
||||
self, user_id: int, configuration: EffectiveAIModelConfiguration
|
||||
) -> EffectiveAIModelConfiguration:
|
||||
async with self.async_session() as session:
|
||||
result = await session.execute(
|
||||
select(UserConfigurationModel).where(
|
||||
|
|
@ -115,7 +117,9 @@ class UserClient(BaseDBClient):
|
|||
await session.rollback()
|
||||
raise e
|
||||
await session.refresh(configuration_obj)
|
||||
return UserConfiguration.model_validate(configuration_obj.configuration)
|
||||
return EffectiveAIModelConfiguration.model_validate(
|
||||
configuration_obj.configuration
|
||||
)
|
||||
|
||||
async def update_user_configuration_last_validated_at(self, user_id: int) -> None:
|
||||
async with self.async_session() as session:
|
||||
|
|
|
|||
|
|
@ -31,7 +31,3 @@ class EffectiveAIModelConfiguration(BaseModel):
|
|||
if isinstance(realtime, dict) and not realtime.get("api_key"):
|
||||
data.pop("realtime", None)
|
||||
return data
|
||||
|
||||
|
||||
# Backward-compatible alias for legacy persistence and existing call sites.
|
||||
UserConfiguration = EffectiveAIModelConfiguration
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from api.constants import AUTH_PROVIDER, DOGRAH_MPS_SECRET_KEY, MPS_API_URL
|
|||
from api.db import db_client
|
||||
from api.db.models import UserModel
|
||||
from api.enums import PostHogEvent
|
||||
from api.schemas.user_configuration import UserConfiguration
|
||||
from api.schemas.user_configuration import EffectiveAIModelConfiguration
|
||||
from api.services.auth.stack_auth import stackauth
|
||||
from api.services.configuration.registry import ServiceProviders
|
||||
from api.services.posthog_client import capture_event
|
||||
|
|
@ -213,7 +213,7 @@ async def _handle_api_key_auth(api_key: str) -> UserModel:
|
|||
|
||||
async def create_user_configuration_with_mps_key(
|
||||
user_id: int, organization_id: int, user_provider_id: str
|
||||
) -> Optional[UserConfiguration]:
|
||||
) -> Optional[EffectiveAIModelConfiguration]:
|
||||
"""Create user configuration using MPS service key.
|
||||
|
||||
Args:
|
||||
|
|
@ -222,7 +222,7 @@ async def create_user_configuration_with_mps_key(
|
|||
user_provider_id: The user's provider ID (for created_by field)
|
||||
|
||||
Returns:
|
||||
UserConfiguration with MPS-provided API keys or None if failed
|
||||
EffectiveAIModelConfiguration with MPS-provided API keys or None if failed
|
||||
"""
|
||||
|
||||
async with httpx.AsyncClient() as client:
|
||||
|
|
@ -285,7 +285,7 @@ async def create_user_configuration_with_mps_key(
|
|||
"model": "default",
|
||||
},
|
||||
}
|
||||
user_config = UserConfiguration(**configuration)
|
||||
user_config = EffectiveAIModelConfiguration(**configuration)
|
||||
return user_config
|
||||
else:
|
||||
logger.warning(
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from groq import Groq
|
|||
# except ImportError:
|
||||
# Neuphonic = None
|
||||
from api.schemas.user_configuration import (
|
||||
UserConfiguration,
|
||||
EffectiveAIModelConfiguration,
|
||||
)
|
||||
from api.services.configuration.registry import ServiceConfig, ServiceProviders
|
||||
from api.services.mps_service_key_client import mps_service_key_client
|
||||
|
|
@ -64,7 +64,7 @@ class UserConfigurationValidator:
|
|||
|
||||
async def validate(
|
||||
self,
|
||||
configuration: UserConfiguration,
|
||||
configuration: EffectiveAIModelConfiguration,
|
||||
organization_id: Optional[int] = None,
|
||||
created_by: Optional[str] = None,
|
||||
) -> APIKeyStatusResponse:
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ The rules are simple:
|
|||
import copy
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from api.schemas.user_configuration import UserConfiguration
|
||||
from api.schemas.user_configuration import EffectiveAIModelConfiguration
|
||||
from api.services.configuration.registry import ServiceConfig
|
||||
from api.services.integrations import get_node_secret_fields
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ def contains_masked_key(value: str | list[str] | None) -> bool:
|
|||
return any(MASK_MARKER in k for k in keys)
|
||||
|
||||
|
||||
def check_for_masked_keys(config: "UserConfiguration") -> None:
|
||||
def check_for_masked_keys(config: "EffectiveAIModelConfiguration") -> None:
|
||||
"""Raise ValueError if any service in *config* still has a masked secret."""
|
||||
for field in ("llm", "tts", "stt", "embeddings", "realtime"):
|
||||
service = getattr(config, field, None)
|
||||
|
|
@ -111,7 +111,7 @@ def resolve_masked_api_keys(
|
|||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# High-level helpers for UserConfiguration objects
|
||||
# High-level helpers for EffectiveAIModelConfiguration objects
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
|
@ -129,7 +129,7 @@ def _mask_service(service_cfg: Optional[ServiceConfig]) -> Optional[Dict[str, An
|
|||
return data
|
||||
|
||||
|
||||
def mask_user_config(config: UserConfiguration) -> Dict[str, Any]:
|
||||
def mask_user_config(config: EffectiveAIModelConfiguration) -> Dict[str, Any]:
|
||||
"""Return a JSON-serialisable dict of *config* with every api_key masked."""
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ stored, while honouring masked API keys.
|
|||
import copy
|
||||
from typing import Dict
|
||||
|
||||
from api.schemas.user_configuration import UserConfiguration
|
||||
from api.schemas.user_configuration import EffectiveAIModelConfiguration
|
||||
from api.services.configuration.masking import (
|
||||
MODEL_OVERRIDE_FIELDS,
|
||||
SERVICE_SECRET_FIELDS,
|
||||
|
|
@ -66,9 +66,9 @@ def _merge_service_secret_fields(
|
|||
|
||||
|
||||
def merge_user_configurations(
|
||||
existing: UserConfiguration, incoming_partial: Dict[str, dict]
|
||||
) -> UserConfiguration:
|
||||
"""Merge *incoming_partial* onto *existing* and return a new UserConfiguration.
|
||||
existing: EffectiveAIModelConfiguration, incoming_partial: Dict[str, dict]
|
||||
) -> EffectiveAIModelConfiguration:
|
||||
"""Merge *incoming_partial* onto *existing* and return a new EffectiveAIModelConfiguration.
|
||||
|
||||
*incoming_partial* is the body of the PUT request (already `model_dump()`ed or
|
||||
extracted via Pydantic `model_dump`).
|
||||
|
|
@ -113,7 +113,7 @@ def merge_user_configurations(
|
|||
if "timezone" in incoming_partial:
|
||||
merged["timezone"] = incoming_partial["timezone"]
|
||||
|
||||
return UserConfiguration.model_validate(merged)
|
||||
return EffectiveAIModelConfiguration.model_validate(merged)
|
||||
|
||||
|
||||
def merge_workflow_configuration_secrets(
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ from __future__ import annotations
|
|||
|
||||
import copy
|
||||
|
||||
from api.schemas.user_configuration import UserConfiguration
|
||||
from api.schemas.user_configuration import EffectiveAIModelConfiguration
|
||||
from api.services.configuration.registry import (
|
||||
REGISTRY,
|
||||
ServiceType,
|
||||
)
|
||||
|
||||
# Maps override key → (UserConfiguration field, ServiceType for registry lookup)
|
||||
# Maps override key → (EffectiveAIModelConfiguration field, ServiceType for registry lookup)
|
||||
_SECTION_MAP: dict[str, ServiceType] = {
|
||||
"llm": ServiceType.LLM,
|
||||
"tts": ServiceType.TTS,
|
||||
|
|
@ -36,7 +36,7 @@ _SECRET_FIELDS = ("api_key", "credentials", "aws_access_key", "aws_secret_key")
|
|||
|
||||
def enrich_overrides_with_api_keys(
|
||||
model_overrides: dict,
|
||||
user_config: UserConfiguration,
|
||||
user_config: EffectiveAIModelConfiguration,
|
||||
) -> dict:
|
||||
"""Copy API keys from the global config into model_overrides where missing.
|
||||
|
||||
|
|
@ -74,9 +74,9 @@ def enrich_overrides_with_api_keys(
|
|||
|
||||
|
||||
def resolve_effective_config(
|
||||
user_config: UserConfiguration,
|
||||
user_config: EffectiveAIModelConfiguration,
|
||||
model_overrides: dict | None,
|
||||
) -> UserConfiguration:
|
||||
) -> EffectiveAIModelConfiguration:
|
||||
"""Deep-merge workflow model_overrides onto global user config.
|
||||
|
||||
- If model_overrides is None or empty, returns a copy of user_config unchanged.
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ async def resolve_llm_config(
|
|||
async def resolve_user_llm_config(
|
||||
workflow_run: WorkflowRunModel,
|
||||
) -> tuple[str, str, str, dict]:
|
||||
"""Resolve the user's configured LLM (from UserConfiguration).
|
||||
"""Resolve the user's configured LLM (from EffectiveAIModelConfiguration).
|
||||
|
||||
Returns:
|
||||
(provider, model, api_key, service_kwargs) tuple
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ async def create_workflow_run_rows(
|
|||
Returns:
|
||||
Tuple of (workflow_run, user, workflow).
|
||||
"""
|
||||
from api.schemas.user_configuration import UserConfiguration
|
||||
from api.schemas.user_configuration import EffectiveAIModelConfiguration
|
||||
|
||||
org = OrganizationModel(provider_id=f"test-org-{provider_id_suffix}")
|
||||
async_session.add(org)
|
||||
|
|
@ -218,7 +218,7 @@ async def create_workflow_run_rows(
|
|||
|
||||
await db_session.update_user_configuration(
|
||||
user_id=user.id,
|
||||
configuration=UserConfiguration.model_validate(USER_CONFIGURATION),
|
||||
configuration=EffectiveAIModelConfiguration.model_validate(USER_CONFIGURATION),
|
||||
)
|
||||
|
||||
workflow = await db_session.create_workflow(
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from api.schemas.ai_model_configuration import (
|
|||
OrganizationAIModelConfigurationV2,
|
||||
compile_ai_model_configuration_v2,
|
||||
)
|
||||
from api.schemas.user_configuration import UserConfiguration
|
||||
from api.schemas.user_configuration import EffectiveAIModelConfiguration
|
||||
from api.services.configuration.ai_model_configuration import (
|
||||
WORKFLOW_MODEL_CONFIGURATION_V2_OVERRIDE_KEY,
|
||||
check_for_masked_keys_in_ai_model_configuration_v2,
|
||||
|
|
@ -142,7 +142,7 @@ def test_masked_v2_configuration_masks_nested_service_keys():
|
|||
|
||||
|
||||
def test_legacy_all_dograh_pipeline_converts_to_dograh_v2():
|
||||
legacy = UserConfiguration(
|
||||
legacy = EffectiveAIModelConfiguration(
|
||||
llm=DograhLLMService(
|
||||
provider="dograh",
|
||||
api_key=["mps-secret"],
|
||||
|
|
@ -170,7 +170,7 @@ def test_legacy_all_dograh_pipeline_converts_to_dograh_v2():
|
|||
|
||||
|
||||
def test_legacy_mixed_dograh_pipeline_converts_to_dograh_v2():
|
||||
legacy = UserConfiguration(
|
||||
legacy = EffectiveAIModelConfiguration(
|
||||
llm=OpenAILLMService(
|
||||
provider="openai",
|
||||
api_key="sk-llm",
|
||||
|
|
@ -202,7 +202,7 @@ def test_legacy_mixed_dograh_pipeline_converts_to_dograh_v2():
|
|||
|
||||
|
||||
def test_legacy_byok_pipeline_converts_to_byok_v2():
|
||||
legacy = UserConfiguration(
|
||||
legacy = EffectiveAIModelConfiguration(
|
||||
llm=OpenAILLMService(
|
||||
provider="openai",
|
||||
api_key="sk-llm",
|
||||
|
|
@ -235,7 +235,7 @@ def test_legacy_byok_pipeline_converts_to_byok_v2():
|
|||
|
||||
|
||||
def test_workflow_model_override_migration_removes_v1_override_and_sets_v2():
|
||||
base = UserConfiguration(
|
||||
base = EffectiveAIModelConfiguration(
|
||||
llm=OpenAILLMService(
|
||||
provider="openai",
|
||||
api_key="sk-llm",
|
||||
|
|
@ -279,7 +279,7 @@ def test_workflow_model_override_migration_removes_v1_override_and_sets_v2():
|
|||
|
||||
|
||||
def test_workflow_model_override_migration_removes_invalid_v1_override_marker():
|
||||
base = UserConfiguration()
|
||||
base = EffectiveAIModelConfiguration()
|
||||
workflow_configurations = {
|
||||
"ambient_noise_configuration": {"enabled": False},
|
||||
"model_overrides": None,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from pipecat.processors.aggregators.llm_context import LLMContext
|
|||
from pipecat.processors.frame_processor import FrameDirection
|
||||
from pipecat.services.xai.realtime import events
|
||||
|
||||
from api.schemas.user_configuration import UserConfiguration
|
||||
from api.schemas.user_configuration import EffectiveAIModelConfiguration
|
||||
from api.services.configuration.registry import GrokRealtimeLLMConfiguration
|
||||
from api.services.pipecat.realtime.grok_realtime import (
|
||||
DograhGrokRealtimeLLMService,
|
||||
|
|
@ -120,7 +120,7 @@ async def test_completed_input_transcription_is_broadcast_as_finalized():
|
|||
|
||||
|
||||
def test_factory_creates_dograh_grok_realtime_service():
|
||||
user_config = UserConfiguration(
|
||||
user_config = EffectiveAIModelConfiguration(
|
||||
is_realtime=True,
|
||||
realtime=GrokRealtimeLLMConfiguration(
|
||||
provider="grok_realtime",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from fastapi import FastAPI
|
|||
from fastapi.testclient import TestClient
|
||||
|
||||
from api.routes.user import router
|
||||
from api.schemas.user_configuration import UserConfiguration
|
||||
from api.schemas.user_configuration import EffectiveAIModelConfiguration
|
||||
from api.services.auth.depends import get_user
|
||||
from api.services.configuration.masking import mask_key
|
||||
from api.services.configuration.registry import (
|
||||
|
|
@ -33,7 +33,7 @@ MASKED_KEY = mask_key(REAL_KEY) # "**************************cdef"
|
|||
|
||||
|
||||
def _existing_openai_config():
|
||||
return UserConfiguration(
|
||||
return EffectiveAIModelConfiguration(
|
||||
llm=OpenAILLMService(
|
||||
provider="openai",
|
||||
api_key=REAL_KEY,
|
||||
|
|
@ -111,7 +111,7 @@ class TestMaskedKeyRejection:
|
|||
client = TestClient(app)
|
||||
|
||||
new_key = "AIzaSyNewRealKey12345678"
|
||||
updated = UserConfiguration(
|
||||
updated = EffectiveAIModelConfiguration(
|
||||
llm=GoogleLLMService(
|
||||
provider="google",
|
||||
api_key=new_key,
|
||||
|
|
@ -178,7 +178,7 @@ class TestMaskedKeyRejection:
|
|||
|
||||
real_credentials = '{"type":"service_account","project_id":"demo-project"}'
|
||||
masked_credentials = mask_key(real_credentials)
|
||||
existing = UserConfiguration(
|
||||
existing = EffectiveAIModelConfiguration(
|
||||
llm=GoogleVertexLLMConfiguration(
|
||||
provider="google_vertex",
|
||||
api_key=None,
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@
|
|||
TDD tests for resolve_effective_config().
|
||||
|
||||
This function deep-merges workflow-level model_overrides onto the global
|
||||
UserConfiguration. Fields not overridden inherit from global.
|
||||
EffectiveAIModelConfiguration. Fields not overridden inherit from global.
|
||||
|
||||
Module under test: api.services.configuration.resolve
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from api.schemas.user_configuration import UserConfiguration
|
||||
from api.schemas.user_configuration import EffectiveAIModelConfiguration
|
||||
from api.services.configuration.masking import (
|
||||
contains_masked_key,
|
||||
mask_workflow_configurations,
|
||||
|
|
@ -35,9 +35,9 @@ from api.services.configuration.resolve import (
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def global_config() -> UserConfiguration:
|
||||
def global_config() -> EffectiveAIModelConfiguration:
|
||||
"""A realistic global user configuration."""
|
||||
return UserConfiguration(
|
||||
return EffectiveAIModelConfiguration(
|
||||
llm=OpenAILLMService(
|
||||
provider="openai", api_key="sk-global-llm", model="gpt-4.1"
|
||||
),
|
||||
|
|
@ -59,9 +59,9 @@ def global_config() -> UserConfiguration:
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def global_config_realtime() -> UserConfiguration:
|
||||
def global_config_realtime() -> EffectiveAIModelConfiguration:
|
||||
"""Global config with realtime enabled."""
|
||||
return UserConfiguration(
|
||||
return EffectiveAIModelConfiguration(
|
||||
llm=OpenAILLMService(
|
||||
provider="openai", api_key="sk-global-llm", model="gpt-4.1"
|
||||
),
|
||||
|
|
@ -302,7 +302,7 @@ class TestRealtimeOverride:
|
|||
class TestOverrideOnNullGlobal:
|
||||
def test_override_stt_when_global_is_none(self):
|
||||
"""When global has no STT config, override creates one from scratch."""
|
||||
config = UserConfiguration(
|
||||
config = EffectiveAIModelConfiguration(
|
||||
llm=OpenAILLMService(provider="openai", api_key="sk-key", model="gpt-4.1"),
|
||||
stt=None,
|
||||
tts=None,
|
||||
|
|
@ -325,7 +325,7 @@ class TestOverrideOnNullGlobal:
|
|||
|
||||
def test_override_realtime_when_global_is_none(self):
|
||||
"""Realtime section can be created from override even if global has none."""
|
||||
config = UserConfiguration(
|
||||
config = EffectiveAIModelConfiguration(
|
||||
llm=OpenAILLMService(provider="openai", api_key="sk-key", model="gpt-4.1"),
|
||||
is_realtime=False,
|
||||
realtime=None,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ from pipecat.processors.frame_processor import FrameDirection
|
|||
from websockets.exceptions import ConnectionClosedError
|
||||
from websockets.frames import Close
|
||||
|
||||
from api.schemas.user_configuration import UserConfiguration
|
||||
from api.schemas.user_configuration import EffectiveAIModelConfiguration
|
||||
from api.services.configuration.registry import UltravoxRealtimeLLMConfiguration
|
||||
from api.services.pipecat.realtime.ultravox_realtime import (
|
||||
_RESUMPTION_USER_MESSAGE,
|
||||
|
|
@ -430,7 +430,7 @@ async def test_receive_messages_reports_unexpected_websocket_close():
|
|||
|
||||
|
||||
def test_factory_creates_dograh_ultravox_realtime_service():
|
||||
user_config = UserConfiguration(
|
||||
user_config = EffectiveAIModelConfiguration(
|
||||
is_realtime=True,
|
||||
realtime=UltravoxRealtimeLLMConfiguration(
|
||||
provider="ultravox_realtime",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from unittest.mock import AsyncMock, patch
|
|||
import pytest
|
||||
|
||||
from api.db.models import OrganizationModel, UserModel
|
||||
from api.schemas.user_configuration import UserConfiguration
|
||||
from api.schemas.user_configuration import EffectiveAIModelConfiguration
|
||||
from api.tests.integrations._run_pipeline_helpers import USER_CONFIGURATION
|
||||
from pipecat.tests import MockLLMService
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ async def _create_user_and_workflow(
|
|||
|
||||
await db_session.update_user_configuration(
|
||||
user_id=user.id,
|
||||
configuration=UserConfiguration.model_validate(USER_CONFIGURATION),
|
||||
configuration=EffectiveAIModelConfiguration.model_validate(USER_CONFIGURATION),
|
||||
)
|
||||
|
||||
workflow = await db_session.create_workflow(
|
||||
|
|
@ -1041,7 +1041,7 @@ async def test_text_chat_session_creation_requires_selected_org_scope(
|
|||
|
||||
await db_session.update_user_configuration(
|
||||
user_id=user.id,
|
||||
configuration=UserConfiguration.model_validate(USER_CONFIGURATION),
|
||||
configuration=EffectiveAIModelConfiguration.model_validate(USER_CONFIGURATION),
|
||||
)
|
||||
|
||||
workflow = await db_session.create_workflow(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue