Initial commit: VoIdeaAI - voice-first AI idea assistant

This commit is contained in:
2026-05-13 12:51:42 +03:00
commit 688d043dad
421 changed files with 47915 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
# schemas Module - VoIdea
## Overview
[Auto-generated documentation]
## Files
| File | Purpose |
|------|---------|
| `admin.py` | Module file |
| `agent.py` | Module file |
| `auth.py` | Module file |
| `idea.py` | Module file |
| `sync.py` | Module file |
| `user.py` | Module file |
+113
View File
@@ -0,0 +1,113 @@
"""VoIdea - Pydantic schemas for API."""
from app.schemas.auth import (
ForgotPasswordRequest,
LoginRequest,
OAuthCallbackRequest,
OAuthUrlResponse,
RefreshRequest,
RegisterRequest,
ResetPasswordRequest,
TokenResponse,
)
from app.schemas.user import (
ChangePasswordRequest,
UserCreate,
UserResponse,
UserUpdate,
VoiceSettingsResponse,
VoiceSettingsUpdate,
)
from app.schemas.idea import (
AnalysisResultResponse,
IdeaAnalyzeResponse,
IdeaCreate,
IdeaResponse,
IdeaUpdate,
)
from app.schemas.agent import AgentReportResponse, AgentRunRequest, AgentStatusResponse
from app.schemas.sync import SyncPullRequest, SyncPushRequest, SyncResponse
from app.schemas.admin import (
AgentInfoResponse,
AgentUpdateRequest,
FeatureCreate,
FeatureResponse,
FeatureUpdate,
LogEntryResponse,
ServiceActionRequest,
ServiceActionResult,
ServiceStatusResponse,
SystemHealth,
SystemInfoResponse,
UserAdminUpdate,
UserRoleUpdate,
)
from app.schemas.feedback import FeedbackCreate, FeedbackResponse, FeedbackUpdate
from app.schemas.tariff import (
TariffPlanCreate,
TariffPlanResponse,
TariffPlanUpdate,
UserSubscriptionResponse,
)
from app.schemas.pipeline import (
PipelineConfigResponse,
PipelineConfigUpdate,
PipelineStageConfig,
PipelineStatsEntry,
PipelineStatsSummary,
)
from app.schemas.config import PublicConfigResponse
__all__ = [
"RegisterRequest",
"LoginRequest",
"RefreshRequest",
"TokenResponse",
"ForgotPasswordRequest",
"ResetPasswordRequest",
"OAuthUrlResponse",
"OAuthCallbackRequest",
"UserCreate",
"UserUpdate",
"UserResponse",
"ChangePasswordRequest",
"IdeaCreate",
"IdeaUpdate",
"IdeaResponse",
"IdeaAnalyzeResponse",
"AnalysisResultResponse",
"AgentRunRequest",
"AgentStatusResponse",
"AgentReportResponse",
"SyncPullRequest",
"SyncPushRequest",
"SyncResponse",
"SystemHealth",
"LogEntryResponse",
"UserRoleUpdate",
"UserAdminUpdate",
"AgentInfoResponse",
"AgentUpdateRequest",
"ServiceActionRequest",
"ServiceActionResult",
"ServiceStatusResponse",
"FeatureCreate",
"FeatureUpdate",
"FeatureResponse",
"SystemInfoResponse",
"FeedbackCreate",
"FeedbackResponse",
"FeedbackUpdate",
"TariffPlanCreate",
"TariffPlanUpdate",
"TariffPlanResponse",
"UserSubscriptionResponse",
"PublicConfigResponse",
"VoiceSettingsResponse",
"VoiceSettingsUpdate",
"PipelineConfigResponse",
"PipelineConfigUpdate",
"PipelineStageConfig",
"PipelineStatsEntry",
"PipelineStatsSummary",
]
+104
View File
@@ -0,0 +1,104 @@
"""Admin schemas for VoIdea API."""
from datetime import datetime
from typing import Any, Optional
from pydantic import BaseModel, EmailStr, Field
class UserRoleUpdate(BaseModel):
is_superuser: bool
class UserAdminUpdate(BaseModel):
display_name: Optional[str] = None
email: Optional[EmailStr] = None
role: Optional[str] = Field(None, description="user | moderator | admin")
is_active: Optional[bool] = None
permissions: Optional[dict[str, bool]] = None
class SystemHealth(BaseModel):
status: str
database: str
redis: str
uptime: Optional[float] = None
version: str
class LogEntryResponse(BaseModel):
id: str
level: str
source: str
message: str
details: Optional[dict[str, Any]] = None
user_id: Optional[str] = None
created_at: datetime
class AgentInfoResponse(BaseModel):
agent_name: str
description: str = ""
is_enabled: bool = True
version: str = "1.0.0"
last_run_at: Optional[datetime] = None
class AgentUpdateRequest(BaseModel):
description: Optional[str] = None
is_enabled: Optional[bool] = None
class ServiceActionRequest(BaseModel):
service: str = Field(description="api | worker | beat | all")
action: str = Field(default="restart", description="restart | start | stop | status")
class ServiceActionResult(BaseModel):
service: str
action: str
success: bool
message: str
class ServiceStatusResponse(BaseModel):
service: str
description: str
status: str
is_running: bool
class FeatureCreate(BaseModel):
title: str = Field(min_length=1, max_length=255)
description: Optional[str] = None
priority: str = "medium"
category: str = "feature"
class FeatureUpdate(BaseModel):
title: Optional[str] = None
description: Optional[str] = None
priority: Optional[str] = None
status: Optional[str] = None
category: Optional[str] = None
class FeatureResponse(BaseModel):
id: str
title: str
description: Optional[str] = None
priority: str
status: str
category: str
source_agent: Optional[str] = None
created_at: datetime
updated_at: datetime
class SystemInfoResponse(BaseModel):
version: str
environment: str
database_status: str
redis_status: str
python_version: str
uptime_seconds: Optional[float] = None
+28
View File
@@ -0,0 +1,28 @@
"""Agent schemas for VoIdea API."""
from datetime import datetime
from typing import Any, Optional
from pydantic import BaseModel
class AgentRunRequest(BaseModel):
context: Optional[dict[str, Any]] = None
class AgentStatusResponse(BaseModel):
name: str
version: str
description: str
status: str
last_run: Optional[datetime] = None
class AgentReportResponse(BaseModel):
id: str
agent_id: str
status: str
message: Optional[str] = None
success: bool
duration_ms: int
created_at: datetime
+68
View File
@@ -0,0 +1,68 @@
"""Auth schemas for VoIdea API."""
from datetime import datetime
from pydantic import BaseModel, EmailStr, Field
class RegisterRequest(BaseModel):
email: EmailStr
password: str = Field(min_length=8, max_length=128)
display_name: str = Field(min_length=1, max_length=255)
accepted_terms: bool = Field(default=True, description="Must accept Terms & Privacy Policy")
class LoginRequest(BaseModel):
email: EmailStr
password: str
class RefreshRequest(BaseModel):
refresh_token: str
class TokenResponse(BaseModel):
access_token: str
refresh_token: str
token_type: str = "bearer"
expires_at: datetime
class OAuthUrlResponse(BaseModel):
url: str
provider: str
class OAuthCallbackRequest(BaseModel):
code: str
class ForgotPasswordRequest(BaseModel):
email: EmailStr
class ResetPasswordRequest(BaseModel):
token: str
new_password: str = Field(min_length=8, max_length=128)
class TwoFactorSetupResponse(BaseModel):
secret: str
uri: str
qr_base64: str
class TwoFactorVerifyRequest(BaseModel):
token: str = Field(min_length=6, max_length=6)
class TwoFactorLoginRequest(BaseModel):
temp_token: str
totp_code: str = Field(min_length=6, max_length=6)
class TwoFactorLoginResponse(BaseModel):
access_token: str
refresh_token: str
token_type: str = "bearer"
expires_at: datetime
+19
View File
@@ -0,0 +1,19 @@
"""Bot command schemas."""
from datetime import datetime
from pydantic import BaseModel
class BotCommandResponse(BaseModel):
id: str
name: str
description: str
enabled: bool
requires_auth: bool
created_at: datetime
updated_at: datetime
class BotCommandUpdate(BaseModel):
name: str
enabled: bool
+19
View File
@@ -0,0 +1,19 @@
"""Public config schema for VoIdea API."""
from pydantic import BaseModel
class PublicConfigResponse(BaseModel):
project_name: str
project_version: str
project_env: str
project_slogan: str
social_telegram: str
social_vk: str
social_youtube: str
social_tiktok: str
yandex_metrika_id: str
google_analytics_id: str
tariffs_enabled: bool
tariffs_free_code: str
accepted_terms_version: str
+25
View File
@@ -0,0 +1,25 @@
"""Feedback schemas for VoIdea API."""
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, Field
class FeedbackCreate(BaseModel):
text: str = Field(min_length=1, max_length=5000)
page_url: Optional[str] = Field(None, max_length=512)
class FeedbackResponse(BaseModel):
id: str
user_id: Optional[str] = None
text: str
page_url: Optional[str] = None
status: str = "new"
created_at: datetime
updated_at: datetime
class FeedbackUpdate(BaseModel):
status: str = Field(default="read", description="new | read | replied | done")
+66
View File
@@ -0,0 +1,66 @@
"""Idea schemas for VoIdea API."""
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, Field
class IdeaCreate(BaseModel):
title: str = Field(min_length=1, max_length=255)
content: str = Field(min_length=1)
tags: Optional[list[str]] = None
is_public: bool = False
class IdeaUpdate(BaseModel):
title: Optional[str] = Field(None, min_length=1, max_length=255)
content: Optional[str] = Field(None, min_length=1)
status: Optional[str] = None
tags: Optional[list[str]] = None
is_public: Optional[bool] = None
class IdeaResponse(BaseModel):
id: str
user_id: str
title: str
content: str
status: str
tags: Optional[list[str]] = None
is_public: bool
public_slug: Optional[str] = None
created_at: datetime
updated_at: datetime
AI_AGENT_ROLES = [
"coordinator",
"task_organizer",
"business_analyst",
"legal_expert",
"financial_consultant",
"solution_architect",
"tester",
"ui_designer",
"smm_specialist",
"life_coach",
"accessibility_expert",
]
class IdeaAnalyzeResponse(BaseModel):
status: str = "started"
idea_id: str
task_count: int = 0
tasks: list[dict] = []
class AnalysisResultResponse(BaseModel):
id: str
role: str
status: str
message: str | None = None
success: bool
duration_ms: int
created_at: str | None = None
+63
View File
@@ -0,0 +1,63 @@
"""Pipeline config and stats schemas for VoIdea."""
from datetime import datetime
from typing import Any, Optional
from pydantic import BaseModel, Field
class PipelineStageConfig(BaseModel):
enabled: bool = True
noise_threshold: float | None = None
silence_timeout_ms: int | None = None
min_audio_duration_ms: int | None = None
word: str | None = None
timeout_minutes: int | None = None
sensitivity: float | None = None
mode: str | None = None
timeout_ms: int | None = None
verified_threshold: int | None = None
warning_threshold: int | None = None
max_agents_per_dialog: int | None = None
min_samples: int | None = None
learning_rate: float | None = None
class PipelineConfigResponse(BaseModel):
vad: PipelineStageConfig = Field(default_factory=PipelineStageConfig)
wake_word: PipelineStageConfig = Field(default_factory=PipelineStageConfig)
semantic_validation: PipelineStageConfig = Field(default_factory=PipelineStageConfig)
confidence: PipelineStageConfig = Field(default_factory=PipelineStageConfig)
agent_chaining: PipelineStageConfig = Field(default_factory=PipelineStageConfig)
auto_tuning: PipelineStageConfig = Field(default_factory=PipelineStageConfig)
stages_order: list[str] = [
"vad", "wake_word", "semantic_validation", "routing", "verification"
]
class PipelineConfigUpdate(BaseModel):
vad: Optional[dict[str, Any]] = None
wake_word: Optional[dict[str, Any]] = None
semantic_validation: Optional[dict[str, Any]] = None
confidence: Optional[dict[str, Any]] = None
agent_chaining: Optional[dict[str, Any]] = None
auto_tuning: Optional[dict[str, Any]] = None
stages_order: Optional[list[str]] = None
class PipelineStatsEntry(BaseModel):
id: str
user_id: str | None
stage: str
passed: bool
reason: str | None
duration_ms: int | None
created_at: datetime
class PipelineStatsSummary(BaseModel):
total_entries: int
stages: dict[str, int]
passed_ratio: float
avg_duration_ms: float | None
fail_reasons: list[tuple[str, int]]
+22
View File
@@ -0,0 +1,22 @@
"""Sync schemas for VoIdea API."""
from datetime import datetime
from typing import Any, Optional
from pydantic import BaseModel
class SyncPullRequest(BaseModel):
last_sync: Optional[datetime] = None
device_id: str
class SyncPushRequest(BaseModel):
device_id: str
changes: list[dict[str, Any]]
class SyncResponse(BaseModel):
status: str
changes: list[dict[str, Any]] = []
sync_token: Optional[str] = None
+55
View File
@@ -0,0 +1,55 @@
"""Tariff schemas for VoIdea API."""
from datetime import datetime
from decimal import Decimal
from typing import Any, Optional
from pydantic import BaseModel, Field
class TariffPlanCreate(BaseModel):
name: str = Field(min_length=1, max_length=100)
code: str = Field(min_length=1, max_length=50)
description: Optional[str] = None
price_monthly: Decimal = Decimal("0")
price_yearly: Optional[Decimal] = None
features: Optional[dict[str, Any]] = None
is_active: bool = True
sort_order: int = 0
class TariffPlanUpdate(BaseModel):
name: Optional[str] = Field(None, min_length=1, max_length=100)
description: Optional[str] = None
price_monthly: Optional[Decimal] = None
price_yearly: Optional[Decimal] = None
features: Optional[dict[str, Any]] = None
is_active: Optional[bool] = None
sort_order: Optional[int] = None
class TariffPlanResponse(BaseModel):
id: str
name: str
code: str
description: Optional[str] = None
price_monthly: Decimal
price_yearly: Optional[Decimal] = None
features: Optional[dict[str, Any]] = None
is_active: bool
sort_order: int
created_at: datetime
updated_at: datetime
class UserSubscriptionResponse(BaseModel):
id: str
user_id: str
plan_id: str
plan_name: str = ""
plan_code: str = ""
status: str
current_period_start: Optional[datetime] = None
current_period_end: Optional[datetime] = None
canceled_at: Optional[datetime] = None
created_at: datetime
+61
View File
@@ -0,0 +1,61 @@
"""User schemas for VoIdea API."""
from datetime import datetime
from typing import Any, Optional
from pydantic import BaseModel, EmailStr, Field
class UserCreate(BaseModel):
email: EmailStr
password: str = Field(min_length=8, max_length=128)
display_name: str = Field(min_length=1, max_length=255)
accepted_terms: bool = Field(default=True, description="Must accept Terms & Privacy")
class UserUpdate(BaseModel):
display_name: Optional[str] = Field(None, min_length=1, max_length=255)
avatar_url: Optional[str] = None
class UserResponse(BaseModel):
id: str
email: str
display_name: str
avatar_url: Optional[str] = None
is_active: bool
is_superuser: bool
role: str = "user"
is_owner: bool = False
permissions: Optional[dict[str, Any]] = None
accepted_terms_at: Optional[datetime] = None
accepted_terms_version: Optional[str] = None
oauth_provider: Optional[str] = None
created_at: datetime
updated_at: datetime
class ChangePasswordRequest(BaseModel):
current_password: str
new_password: str = Field(min_length=8, max_length=128)
class SubscriptionInfo(BaseModel):
plan_name: str
plan_code: str
status: str
expires_at: Optional[datetime] = None
features: Optional[dict[str, Any]] = None
class VoiceSettingsResponse(BaseModel):
preset: str
overrides: dict[str, Any]
available_presets: list[str]
preset_values: dict[str, Any]
class VoiceSettingsUpdate(BaseModel):
preset: Optional[str] = None
overrides: Optional[dict[str, Any]] = None
reset: Optional[bool] = None
+70
View File
@@ -0,0 +1,70 @@
"""Voice schemas for VoIdeaAI."""
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, Field
class ChatRequest(BaseModel):
text: str
session_id: str | None = None
vad_enabled: bool | None = None
wake_word_detected: bool | None = None
audio_duration_ms: int | None = None
pipeline_mode: str | None = None # "fast" | "full" | "off"
class ChatResponse(BaseModel):
response: str
agent_name: str
agent_description: str
confidence: int
verification_status: str
processing_time_ms: float
interaction_id: str
session_id: str
suggested_command: str | None = None
class CommandCreate(BaseModel):
phrase: str = Field(min_length=1, max_length=255)
action: str = Field(min_length=1, max_length=50)
agent_name: str | None = None
class CommandResponse(BaseModel):
id: str
phrase: str
action: str
agent_name: str | None
count: int
is_active: bool
class RateRequest(BaseModel):
interaction_id: str
rating: int = Field(ge=1, le=5)
class SessionResponse(BaseModel):
id: str
title: str
status: str
idea_id: Optional[str] = None
created_at: datetime
updated_at: datetime
class CreateSessionRequest(BaseModel):
title: str = "Новое обсуждение"
class SaveIdeaRequest(BaseModel):
session_id: str
class SaveIdeaResponse(BaseModel):
idea_id: str
title: str
exported: bool = False