kairo-code 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- image-service/main.py +178 -0
- infra/chat/app/main.py +84 -0
- kairo/backend/__init__.py +0 -0
- kairo/backend/api/__init__.py +0 -0
- kairo/backend/api/admin/__init__.py +23 -0
- kairo/backend/api/admin/audit.py +54 -0
- kairo/backend/api/admin/content.py +142 -0
- kairo/backend/api/admin/incidents.py +148 -0
- kairo/backend/api/admin/stats.py +125 -0
- kairo/backend/api/admin/system.py +87 -0
- kairo/backend/api/admin/users.py +279 -0
- kairo/backend/api/agents.py +94 -0
- kairo/backend/api/api_keys.py +85 -0
- kairo/backend/api/auth.py +116 -0
- kairo/backend/api/billing.py +41 -0
- kairo/backend/api/chat.py +72 -0
- kairo/backend/api/conversations.py +125 -0
- kairo/backend/api/device_auth.py +100 -0
- kairo/backend/api/files.py +83 -0
- kairo/backend/api/health.py +36 -0
- kairo/backend/api/images.py +80 -0
- kairo/backend/api/openai_compat.py +225 -0
- kairo/backend/api/projects.py +102 -0
- kairo/backend/api/usage.py +32 -0
- kairo/backend/api/webhooks.py +79 -0
- kairo/backend/app.py +297 -0
- kairo/backend/config.py +179 -0
- kairo/backend/core/__init__.py +0 -0
- kairo/backend/core/admin_auth.py +24 -0
- kairo/backend/core/api_key_auth.py +55 -0
- kairo/backend/core/database.py +28 -0
- kairo/backend/core/dependencies.py +70 -0
- kairo/backend/core/logging.py +23 -0
- kairo/backend/core/rate_limit.py +73 -0
- kairo/backend/core/security.py +29 -0
- kairo/backend/models/__init__.py +19 -0
- kairo/backend/models/agent.py +30 -0
- kairo/backend/models/api_key.py +25 -0
- kairo/backend/models/api_usage.py +29 -0
- kairo/backend/models/audit_log.py +26 -0
- kairo/backend/models/conversation.py +48 -0
- kairo/backend/models/device_code.py +30 -0
- kairo/backend/models/feature_flag.py +21 -0
- kairo/backend/models/image_generation.py +24 -0
- kairo/backend/models/incident.py +28 -0
- kairo/backend/models/project.py +28 -0
- kairo/backend/models/uptime_record.py +24 -0
- kairo/backend/models/usage.py +24 -0
- kairo/backend/models/user.py +49 -0
- kairo/backend/schemas/__init__.py +0 -0
- kairo/backend/schemas/admin/__init__.py +0 -0
- kairo/backend/schemas/admin/audit.py +28 -0
- kairo/backend/schemas/admin/content.py +53 -0
- kairo/backend/schemas/admin/stats.py +77 -0
- kairo/backend/schemas/admin/system.py +44 -0
- kairo/backend/schemas/admin/users.py +48 -0
- kairo/backend/schemas/agent.py +42 -0
- kairo/backend/schemas/api_key.py +30 -0
- kairo/backend/schemas/auth.py +57 -0
- kairo/backend/schemas/chat.py +26 -0
- kairo/backend/schemas/conversation.py +39 -0
- kairo/backend/schemas/device_auth.py +40 -0
- kairo/backend/schemas/image.py +15 -0
- kairo/backend/schemas/openai_compat.py +76 -0
- kairo/backend/schemas/project.py +21 -0
- kairo/backend/schemas/status.py +81 -0
- kairo/backend/schemas/usage.py +15 -0
- kairo/backend/services/__init__.py +0 -0
- kairo/backend/services/admin/__init__.py +0 -0
- kairo/backend/services/admin/audit_service.py +78 -0
- kairo/backend/services/admin/content_service.py +119 -0
- kairo/backend/services/admin/incident_service.py +94 -0
- kairo/backend/services/admin/stats_service.py +281 -0
- kairo/backend/services/admin/system_service.py +126 -0
- kairo/backend/services/admin/user_service.py +157 -0
- kairo/backend/services/agent_service.py +107 -0
- kairo/backend/services/api_key_service.py +66 -0
- kairo/backend/services/api_usage_service.py +126 -0
- kairo/backend/services/auth_service.py +101 -0
- kairo/backend/services/chat_service.py +501 -0
- kairo/backend/services/conversation_service.py +264 -0
- kairo/backend/services/device_auth_service.py +193 -0
- kairo/backend/services/email_service.py +55 -0
- kairo/backend/services/image_service.py +181 -0
- kairo/backend/services/llm_service.py +186 -0
- kairo/backend/services/project_service.py +109 -0
- kairo/backend/services/status_service.py +167 -0
- kairo/backend/services/stripe_service.py +78 -0
- kairo/backend/services/usage_service.py +150 -0
- kairo/backend/services/web_search_service.py +96 -0
- kairo/migrations/env.py +60 -0
- kairo/migrations/versions/001_initial.py +55 -0
- kairo/migrations/versions/002_usage_tracking_and_indexes.py +66 -0
- kairo/migrations/versions/003_username_to_email.py +21 -0
- kairo/migrations/versions/004_add_plans_and_verification.py +67 -0
- kairo/migrations/versions/005_add_projects.py +52 -0
- kairo/migrations/versions/006_add_image_generation.py +63 -0
- kairo/migrations/versions/007_add_admin_portal.py +107 -0
- kairo/migrations/versions/008_add_device_code_auth.py +76 -0
- kairo/migrations/versions/009_add_status_page.py +65 -0
- kairo/tools/extract_claude_data.py +465 -0
- kairo/tools/filter_claude_data.py +303 -0
- kairo/tools/generate_curated_data.py +157 -0
- kairo/tools/mix_training_data.py +295 -0
- kairo_code/__init__.py +3 -0
- kairo_code/agents/__init__.py +25 -0
- kairo_code/agents/architect.py +98 -0
- kairo_code/agents/audit.py +100 -0
- kairo_code/agents/base.py +463 -0
- kairo_code/agents/coder.py +155 -0
- kairo_code/agents/database.py +77 -0
- kairo_code/agents/docs.py +88 -0
- kairo_code/agents/explorer.py +62 -0
- kairo_code/agents/guardian.py +80 -0
- kairo_code/agents/planner.py +66 -0
- kairo_code/agents/reviewer.py +91 -0
- kairo_code/agents/security.py +94 -0
- kairo_code/agents/terraform.py +88 -0
- kairo_code/agents/testing.py +97 -0
- kairo_code/agents/uiux.py +88 -0
- kairo_code/auth.py +232 -0
- kairo_code/config.py +172 -0
- kairo_code/conversation.py +173 -0
- kairo_code/heartbeat.py +63 -0
- kairo_code/llm.py +291 -0
- kairo_code/logging_config.py +156 -0
- kairo_code/main.py +818 -0
- kairo_code/router.py +217 -0
- kairo_code/sandbox.py +248 -0
- kairo_code/settings.py +183 -0
- kairo_code/tools/__init__.py +51 -0
- kairo_code/tools/analysis.py +509 -0
- kairo_code/tools/base.py +417 -0
- kairo_code/tools/code.py +58 -0
- kairo_code/tools/definitions.py +617 -0
- kairo_code/tools/files.py +315 -0
- kairo_code/tools/review.py +390 -0
- kairo_code/tools/search.py +185 -0
- kairo_code/ui.py +418 -0
- kairo_code-0.1.0.dist-info/METADATA +13 -0
- kairo_code-0.1.0.dist-info/RECORD +144 -0
- kairo_code-0.1.0.dist-info/WHEEL +5 -0
- kairo_code-0.1.0.dist-info/entry_points.txt +2 -0
- kairo_code-0.1.0.dist-info/top_level.txt +4 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from pydantic import BaseModel
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class OverviewStats(BaseModel):
|
|
5
|
+
total_users: int
|
|
6
|
+
active_today: int
|
|
7
|
+
active_7d: int
|
|
8
|
+
active_30d: int
|
|
9
|
+
pro_subscribers: int
|
|
10
|
+
max_subscribers: int
|
|
11
|
+
mrr: int
|
|
12
|
+
conversations_today: int
|
|
13
|
+
images_today: int
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class UserGrowthEntry(BaseModel):
|
|
17
|
+
date: str
|
|
18
|
+
signups: int
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class UsageStatsEntry(BaseModel):
|
|
22
|
+
date: str
|
|
23
|
+
total_tokens: int
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class RevenueStats(BaseModel):
|
|
27
|
+
free_count: int
|
|
28
|
+
pro_count: int
|
|
29
|
+
max_count: int
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class TopUserEntry(BaseModel):
|
|
33
|
+
user_id: str
|
|
34
|
+
email: str
|
|
35
|
+
total_tokens: int
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# --- Analytics endpoint schemas ---
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class DailyCountEntry(BaseModel):
|
|
42
|
+
date: str
|
|
43
|
+
count: int
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class DailyCountResponse(BaseModel):
|
|
47
|
+
data: list[DailyCountEntry]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class DailyTokensEntry(BaseModel):
|
|
51
|
+
date: str
|
|
52
|
+
tokens: int
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class DailyTokensResponse(BaseModel):
|
|
56
|
+
data: list[DailyTokensEntry]
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class PlanDistributionEntry(BaseModel):
|
|
60
|
+
plan: str
|
|
61
|
+
count: int
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class PlanDistributionResponse(BaseModel):
|
|
65
|
+
data: list[PlanDistributionEntry]
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class TopUserAnalyticsEntry(BaseModel):
|
|
69
|
+
email: str
|
|
70
|
+
plan: str
|
|
71
|
+
total_tokens: int
|
|
72
|
+
conversations: int
|
|
73
|
+
images: int
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class TopUserAnalyticsResponse(BaseModel):
|
|
77
|
+
data: list[TopUserAnalyticsEntry]
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ServiceHealth(BaseModel):
|
|
7
|
+
name: str
|
|
8
|
+
status: str # "healthy" | "degraded" | "down"
|
|
9
|
+
latency_ms: int | None = None
|
|
10
|
+
message: str | None = None
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class HealthStatus(BaseModel):
|
|
14
|
+
overall: str # "healthy" | "degraded" | "down"
|
|
15
|
+
services: list[ServiceHealth]
|
|
16
|
+
checked_at: str
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class FeatureFlagItem(BaseModel):
|
|
20
|
+
key: str
|
|
21
|
+
enabled: bool
|
|
22
|
+
updated_by: str | None = None
|
|
23
|
+
updated_at: str | None = None
|
|
24
|
+
|
|
25
|
+
model_config = {"from_attributes": True}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class FeatureFlagResponse(BaseModel):
|
|
29
|
+
flags: list[FeatureFlagItem]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class FeatureFlagUpdate(BaseModel):
|
|
33
|
+
key: str
|
|
34
|
+
enabled: bool
|
|
35
|
+
reason: str = ""
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ConfigEntry(BaseModel):
|
|
39
|
+
key: str
|
|
40
|
+
value: str
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class ConfigResponse(BaseModel):
|
|
44
|
+
config: list[ConfigEntry]
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AdminUserListItem(BaseModel):
|
|
7
|
+
id: str
|
|
8
|
+
email: str
|
|
9
|
+
role: str
|
|
10
|
+
status: str
|
|
11
|
+
plan: str
|
|
12
|
+
email_verified: bool
|
|
13
|
+
created_at: datetime
|
|
14
|
+
|
|
15
|
+
model_config = {"from_attributes": True}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AdminUserDetailResponse(BaseModel):
|
|
19
|
+
"""Allowlisted fields only — never expose hashed_password, tokens, etc."""
|
|
20
|
+
|
|
21
|
+
id: str
|
|
22
|
+
email: str
|
|
23
|
+
role: str
|
|
24
|
+
status: str
|
|
25
|
+
plan: str
|
|
26
|
+
created_at: datetime
|
|
27
|
+
email_verified: bool
|
|
28
|
+
stripe_customer_id: str | None = None
|
|
29
|
+
stripe_subscription_id: str | None = None
|
|
30
|
+
daily_token_limit: int
|
|
31
|
+
monthly_token_limit: int
|
|
32
|
+
|
|
33
|
+
model_config = {"from_attributes": True}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class PlanChangeRequest(BaseModel):
|
|
37
|
+
plan: str = Field(..., description="New plan: free, pro, or max")
|
|
38
|
+
reason: str = Field(..., min_length=1, max_length=1000)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class StatusChangeRequest(BaseModel):
|
|
42
|
+
status: str = Field(..., description="New status: active, suspended, or banned")
|
|
43
|
+
reason: str = Field(..., min_length=1, max_length=1000)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class RoleChangeRequest(BaseModel):
|
|
47
|
+
role: str = Field(..., description="New role: user, moderator, admin, or superadmin")
|
|
48
|
+
reason: str = Field(..., min_length=1, max_length=1000)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class RegisterAgentRequest(BaseModel):
|
|
7
|
+
name: str = Field(..., min_length=1, max_length=100)
|
|
8
|
+
description: str | None = Field(None, max_length=500)
|
|
9
|
+
system_prompt: str | None = Field(None, max_length=10000)
|
|
10
|
+
model_preference: str = "nyx"
|
|
11
|
+
tools: list[str] | None = None
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class UpdateAgentRequest(BaseModel):
|
|
15
|
+
name: str | None = Field(None, min_length=1, max_length=100)
|
|
16
|
+
description: str | None = None
|
|
17
|
+
system_prompt: str | None = Field(None, max_length=10000)
|
|
18
|
+
model_preference: str | None = None
|
|
19
|
+
tools: list[str] | None = None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class AgentResponse(BaseModel):
|
|
23
|
+
id: str
|
|
24
|
+
name: str
|
|
25
|
+
description: str | None = None
|
|
26
|
+
model_preference: str
|
|
27
|
+
status: str
|
|
28
|
+
last_heartbeat_at: datetime | None = None
|
|
29
|
+
created_at: datetime
|
|
30
|
+
updated_at: datetime
|
|
31
|
+
|
|
32
|
+
model_config = {"from_attributes": True}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class AgentHeartbeatRequest(BaseModel):
|
|
36
|
+
agent_id: str
|
|
37
|
+
status: str = Field("online", pattern="^(online|busy|idle)$")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class AgentHeartbeatResponse(BaseModel):
|
|
41
|
+
acknowledged: bool
|
|
42
|
+
server_time: datetime
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class CreateApiKeyRequest(BaseModel):
|
|
7
|
+
name: str = Field(..., min_length=1, max_length=100)
|
|
8
|
+
expires_in_days: int | None = Field(None, ge=1, le=365)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ApiKeyResponse(BaseModel):
|
|
12
|
+
id: str
|
|
13
|
+
name: str
|
|
14
|
+
key_prefix: str
|
|
15
|
+
is_active: bool
|
|
16
|
+
last_used_at: datetime | None = None
|
|
17
|
+
created_at: datetime
|
|
18
|
+
expires_at: datetime | None = None
|
|
19
|
+
|
|
20
|
+
model_config = {"from_attributes": True}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ApiKeyCreatedResponse(ApiKeyResponse):
|
|
24
|
+
"""Returned only once on creation — includes the full key."""
|
|
25
|
+
full_key: str
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class RevokeApiKeyResponse(BaseModel):
|
|
29
|
+
id: str
|
|
30
|
+
revoked: bool
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, EmailStr, Field
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class RegisterRequest(BaseModel):
|
|
7
|
+
email: EmailStr = Field(..., max_length=254)
|
|
8
|
+
password: str = Field(..., min_length=8, max_length=128)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class LoginRequest(BaseModel):
|
|
12
|
+
email: EmailStr = Field(..., max_length=254)
|
|
13
|
+
password: str = Field(..., max_length=128)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class VerifyEmailRequest(BaseModel):
|
|
17
|
+
token: str = Field(..., max_length=128)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ForgotPasswordRequest(BaseModel):
|
|
21
|
+
email: EmailStr = Field(..., max_length=254)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ResetPasswordRequest(BaseModel):
|
|
25
|
+
token: str = Field(..., max_length=128)
|
|
26
|
+
password: str = Field(..., min_length=8, max_length=128)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class UserResponse(BaseModel):
|
|
30
|
+
id: str
|
|
31
|
+
email: str
|
|
32
|
+
created_at: datetime
|
|
33
|
+
plan: str = "free"
|
|
34
|
+
email_verified: bool = False
|
|
35
|
+
role: str = "user"
|
|
36
|
+
|
|
37
|
+
model_config = {"from_attributes": True}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class TokenResponse(BaseModel):
|
|
41
|
+
access_token: str
|
|
42
|
+
token_type: str = "bearer"
|
|
43
|
+
user: UserResponse
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class CheckoutResponse(BaseModel):
|
|
47
|
+
checkout_url: str
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class BillingPortalResponse(BaseModel):
|
|
51
|
+
portal_url: str
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class BillingStatusResponse(BaseModel):
|
|
55
|
+
plan: str
|
|
56
|
+
stripe_customer_id: str | None = None
|
|
57
|
+
stripe_subscription_id: str | None = None
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field, field_validator
|
|
2
|
+
|
|
3
|
+
from backend.config import settings
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ChatRequest(BaseModel):
|
|
7
|
+
conversation_id: str | None = None
|
|
8
|
+
message: str = Field(..., min_length=1, max_length=32000)
|
|
9
|
+
model: str = "nyx"
|
|
10
|
+
temperature: float = Field(default=0.7, ge=0.0, le=2.0)
|
|
11
|
+
max_tokens: int = Field(default=2048, ge=1, le=16384)
|
|
12
|
+
project_id: str | None = None
|
|
13
|
+
|
|
14
|
+
@field_validator("model")
|
|
15
|
+
@classmethod
|
|
16
|
+
def model_must_be_allowed(cls, v: str) -> str:
|
|
17
|
+
allowed = set(settings.MODEL_MAP.keys())
|
|
18
|
+
if v not in allowed:
|
|
19
|
+
raise ValueError(f"model must be one of: {', '.join(sorted(allowed))}")
|
|
20
|
+
return v
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class StreamChunk(BaseModel):
|
|
24
|
+
type: str # "meta", "content", "error"
|
|
25
|
+
conversation_id: str | None = None
|
|
26
|
+
content: str | None = None
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from pydantic import BaseModel, Field
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class MessageSchema(BaseModel):
|
|
6
|
+
id: str
|
|
7
|
+
role: str
|
|
8
|
+
content: str
|
|
9
|
+
created_at: datetime
|
|
10
|
+
image_url: str | None = None
|
|
11
|
+
|
|
12
|
+
model_config = {"from_attributes": True}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ConversationSummary(BaseModel):
|
|
16
|
+
id: str
|
|
17
|
+
title: str
|
|
18
|
+
model: str
|
|
19
|
+
updated_at: datetime
|
|
20
|
+
message_count: int
|
|
21
|
+
project_id: str | None = None
|
|
22
|
+
|
|
23
|
+
model_config = {"from_attributes": True}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ConversationDetail(BaseModel):
|
|
27
|
+
id: str
|
|
28
|
+
title: str
|
|
29
|
+
model: str
|
|
30
|
+
created_at: datetime
|
|
31
|
+
updated_at: datetime
|
|
32
|
+
project_id: str | None = None
|
|
33
|
+
messages: list[MessageSchema]
|
|
34
|
+
|
|
35
|
+
model_config = {"from_attributes": True}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ConversationRename(BaseModel):
|
|
39
|
+
title: str = Field(..., min_length=1, max_length=200)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class DeviceCodeRequest(BaseModel):
|
|
5
|
+
client_name: str = Field("kairo-code", max_length=100)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class DeviceCodeResponse(BaseModel):
|
|
9
|
+
device_code: str
|
|
10
|
+
user_code: str
|
|
11
|
+
verification_uri: str
|
|
12
|
+
verification_uri_complete: str
|
|
13
|
+
expires_in: int
|
|
14
|
+
interval: int
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class DeviceTokenRequest(BaseModel):
|
|
18
|
+
device_code: str
|
|
19
|
+
grant_type: str = "urn:ietf:params:oauth:grant-type:device_code"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class DeviceTokenResponse(BaseModel):
|
|
23
|
+
access_token: str
|
|
24
|
+
token_type: str = "bearer"
|
|
25
|
+
plan: str
|
|
26
|
+
email: str
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class DeviceTokenErrorResponse(BaseModel):
|
|
30
|
+
error: str # authorization_pending, slow_down, expired_token, access_denied
|
|
31
|
+
error_description: str
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class DeviceApproveRequest(BaseModel):
|
|
35
|
+
user_code: str
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class DeviceApproveResponse(BaseModel):
|
|
39
|
+
approved: bool
|
|
40
|
+
message: str
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class ImageGenerateRequest(BaseModel):
|
|
5
|
+
prompt: str = Field(..., min_length=1, max_length=2000)
|
|
6
|
+
conversation_id: str | None = None
|
|
7
|
+
width: int = Field(default=1024, ge=256, le=2048)
|
|
8
|
+
height: int = Field(default=1024, ge=256, le=2048)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ImageGenerateResponse(BaseModel):
|
|
12
|
+
image_url: str
|
|
13
|
+
message_id: str
|
|
14
|
+
conversation_id: str
|
|
15
|
+
prompt: str
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ChatMessage(BaseModel):
|
|
7
|
+
role: str
|
|
8
|
+
content: str | None = None
|
|
9
|
+
name: str | None = None
|
|
10
|
+
tool_calls: list[dict[str, Any]] | None = None
|
|
11
|
+
tool_call_id: str | None = None
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ChatCompletionRequest(BaseModel):
|
|
15
|
+
model: str
|
|
16
|
+
messages: list[ChatMessage]
|
|
17
|
+
temperature: float = Field(0.7, ge=0.0, le=2.0)
|
|
18
|
+
max_tokens: int | None = Field(None, ge=1)
|
|
19
|
+
stream: bool = False
|
|
20
|
+
top_p: float | None = Field(None, ge=0.0, le=1.0)
|
|
21
|
+
stop: str | list[str] | None = None
|
|
22
|
+
# Tool calling
|
|
23
|
+
tools: list[dict[str, Any]] | None = None
|
|
24
|
+
tool_choice: str | dict[str, Any] | None = None
|
|
25
|
+
parallel_tool_calls: bool | None = None
|
|
26
|
+
# Additional OpenAI-compatible fields
|
|
27
|
+
response_format: dict[str, Any] | None = None
|
|
28
|
+
frequency_penalty: float | None = Field(None, ge=-2.0, le=2.0)
|
|
29
|
+
presence_penalty: float | None = Field(None, ge=-2.0, le=2.0)
|
|
30
|
+
seed: int | None = None
|
|
31
|
+
n: int | None = Field(None, ge=1, le=8)
|
|
32
|
+
logprobs: bool | None = None
|
|
33
|
+
top_logprobs: int | None = Field(None, ge=0, le=20)
|
|
34
|
+
user: str | None = None
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class ChoiceDelta(BaseModel):
|
|
38
|
+
role: str | None = None
|
|
39
|
+
content: str | None = None
|
|
40
|
+
tool_calls: list[dict[str, Any]] | None = None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class ChatCompletionChoice(BaseModel):
|
|
44
|
+
index: int
|
|
45
|
+
message: ChatMessage
|
|
46
|
+
finish_reason: str | None = None
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class StreamChoice(BaseModel):
|
|
50
|
+
index: int
|
|
51
|
+
delta: ChoiceDelta
|
|
52
|
+
finish_reason: str | None = None
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class UsageInfo(BaseModel):
|
|
56
|
+
prompt_tokens: int
|
|
57
|
+
completion_tokens: int
|
|
58
|
+
total_tokens: int
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class ChatCompletionResponse(BaseModel):
|
|
62
|
+
id: str
|
|
63
|
+
object: str = "chat.completion"
|
|
64
|
+
created: int
|
|
65
|
+
model: str
|
|
66
|
+
choices: list[ChatCompletionChoice]
|
|
67
|
+
usage: UsageInfo | None = None
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class ChatCompletionChunk(BaseModel):
|
|
71
|
+
id: str
|
|
72
|
+
object: str = "chat.completion.chunk"
|
|
73
|
+
created: int
|
|
74
|
+
model: str
|
|
75
|
+
choices: list[StreamChoice]
|
|
76
|
+
usage: UsageInfo | None = None
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ProjectCreate(BaseModel):
|
|
7
|
+
name: str = Field(..., min_length=1, max_length=200)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ProjectUpdate(BaseModel):
|
|
11
|
+
name: str | None = Field(default=None, min_length=1, max_length=200)
|
|
12
|
+
instructions: str | None = None
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ProjectResponse(BaseModel):
|
|
16
|
+
id: str
|
|
17
|
+
name: str
|
|
18
|
+
instructions: str | None
|
|
19
|
+
conversation_count: int
|
|
20
|
+
created_at: datetime
|
|
21
|
+
updated_at: datetime
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from pydantic import BaseModel, field_validator
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class ComponentStatus(BaseModel):
|
|
5
|
+
name: str
|
|
6
|
+
status: str # operational, degraded, down
|
|
7
|
+
latency_ms: int | None = None
|
|
8
|
+
uptime_24h: float | None = None
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class IncidentSummary(BaseModel):
|
|
12
|
+
id: str
|
|
13
|
+
title: str
|
|
14
|
+
description: str | None = None
|
|
15
|
+
severity: str
|
|
16
|
+
component: str
|
|
17
|
+
status: str
|
|
18
|
+
started_at: str
|
|
19
|
+
resolved_at: str | None = None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class UptimeEntry(BaseModel):
|
|
23
|
+
date: str
|
|
24
|
+
uptime_percent: float
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class StatusPageResponse(BaseModel):
|
|
28
|
+
status: str # operational, degraded, outage
|
|
29
|
+
overall_uptime: float
|
|
30
|
+
checked_at: str
|
|
31
|
+
components: list[ComponentStatus]
|
|
32
|
+
recent_incidents: list[IncidentSummary]
|
|
33
|
+
uptime_history: list[UptimeEntry]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
VALID_SEVERITIES = {"info", "warning", "critical"}
|
|
37
|
+
VALID_COMPONENTS = {"api", "chat", "models", "images", "database"}
|
|
38
|
+
VALID_STATUSES = {"investigating", "identified", "monitoring", "resolved"}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class CreateIncidentRequest(BaseModel):
|
|
42
|
+
title: str
|
|
43
|
+
description: str | None = None
|
|
44
|
+
severity: str = "warning"
|
|
45
|
+
component: str
|
|
46
|
+
|
|
47
|
+
@field_validator("severity")
|
|
48
|
+
@classmethod
|
|
49
|
+
def validate_severity(cls, v: str) -> str:
|
|
50
|
+
if v not in VALID_SEVERITIES:
|
|
51
|
+
raise ValueError(f"severity must be one of {VALID_SEVERITIES}")
|
|
52
|
+
return v
|
|
53
|
+
|
|
54
|
+
@field_validator("component")
|
|
55
|
+
@classmethod
|
|
56
|
+
def validate_component(cls, v: str) -> str:
|
|
57
|
+
if v not in VALID_COMPONENTS:
|
|
58
|
+
raise ValueError(f"component must be one of {VALID_COMPONENTS}")
|
|
59
|
+
return v
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class UpdateIncidentRequest(BaseModel):
|
|
63
|
+
title: str | None = None
|
|
64
|
+
description: str | None = None
|
|
65
|
+
severity: str | None = None
|
|
66
|
+
status: str | None = None
|
|
67
|
+
resolved_at: str | None = None
|
|
68
|
+
|
|
69
|
+
@field_validator("severity")
|
|
70
|
+
@classmethod
|
|
71
|
+
def validate_severity(cls, v: str | None) -> str | None:
|
|
72
|
+
if v is not None and v not in VALID_SEVERITIES:
|
|
73
|
+
raise ValueError(f"severity must be one of {VALID_SEVERITIES}")
|
|
74
|
+
return v
|
|
75
|
+
|
|
76
|
+
@field_validator("status")
|
|
77
|
+
@classmethod
|
|
78
|
+
def validate_status(cls, v: str | None) -> str | None:
|
|
79
|
+
if v is not None and v not in VALID_STATUSES:
|
|
80
|
+
raise ValueError(f"status must be one of {VALID_STATUSES}")
|
|
81
|
+
return v
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from pydantic import BaseModel
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class UsageSummaryResponse(BaseModel):
|
|
5
|
+
daily_percent: float
|
|
6
|
+
monthly_percent: float
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class UsageHistoryEntry(BaseModel):
|
|
10
|
+
date: str
|
|
11
|
+
usage_percent: float
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class UsageHistoryResponse(BaseModel):
|
|
15
|
+
entries: list[UsageHistoryEntry]
|
|
File without changes
|
|
File without changes
|