chore: 迁移到 social-app 架构,集成 Supabase 和 taskiq worker

This commit is contained in:
qzl
2026-04-02 16:36:35 +08:00
parent 695adb7d6f
commit 92cdfd9fca
132 changed files with 5802 additions and 759 deletions
-3
View File
@@ -1,3 +0,0 @@
from .settings import Settings, config
__all__ = ["Settings", "config"]
+70 -86
View File
@@ -8,6 +8,7 @@ from pydantic import (
AnyHttpUrl,
BaseModel,
Field,
SecretStr,
computed_field,
field_validator,
model_validator,
@@ -118,11 +119,54 @@ class RedisSettings(BaseModel):
return f"redis://{self.host}:{self.port}/{self.db}"
class SupabaseSettings(BaseModel):
public_url: AnyHttpUrl
anon_key: str = "CHANGE_ME"
service_role_key: str = "CHANGE_ME"
jwt_secret: SecretStr | None = Field(default=None, exclude=True)
jwt_algorithm: Literal["HS256"] = "HS256"
jwt_issuer: str | None = None
@model_validator(mode="after")
def compute_defaults(self) -> "SupabaseSettings":
base = str(self.public_url).rstrip("/")
if self.jwt_issuer is None:
self.jwt_issuer = f"{base}/auth/v1"
return self
@computed_field
@property
def url(self) -> str:
return str(self.public_url)
class StorageSettings(BaseModel):
provider: Literal["supabase"] = "supabase"
signed_url_ttl_seconds: int = Field(default=600, ge=60, le=3600)
retention_days: int = Field(default=30, ge=1, le=3650)
class AttachmentSettings(BaseModel):
bucket: str = Field(default="eryao-attachments", min_length=3, max_length=63)
max_size_mb: int = Field(default=20, ge=1, le=200)
class AvatarSettings(BaseModel):
bucket: str = Field(default="avatars", min_length=3, max_length=63)
max_size_mb: int = Field(default=2, ge=1, le=10)
attachment: AttachmentSettings = Field(default_factory=AttachmentSettings)
avatar: AvatarSettings = Field(default_factory=AvatarSettings)
class LlmSettings(BaseModel):
provider_keys: dict[str, str] = Field(default_factory=dict)
class DatabaseSettings(BaseModel):
host: str = "localhost"
port: int = 3306
name: str = "eryao"
user: str = "root"
port: int = 5432
name: str = "postgres"
user: str = "postgres"
password: str = "CHANGE_ME"
@computed_field
@@ -130,83 +174,11 @@ class DatabaseSettings(BaseModel):
def url(self) -> str:
password = quote(self.password, safe="")
return (
f"mysql+aiomysql://{self.user}:{password}"
f"postgresql+asyncpg://{self.user}:{password}"
f"@{self.host}:{self.port}/{self.name}"
)
class AppVersionSettings(BaseModel):
manifest_path: str = Field(
default="deploy/static/releases/manifest.json",
description="发布清单文件路径,相对于项目根目录",
)
release_path_prefix: str = Field(
default="releases",
description="下载 URL 中文件目录前缀",
)
download_base_url: AnyHttpUrl | None = Field(
default=None,
description="下载链接基础域名,如 https://your-domain.com",
)
@field_validator("download_base_url", mode="before")
@classmethod
def empty_download_base_url_to_none(cls, value: object) -> object:
if value == "":
return None
return value
@field_validator("manifest_path")
@classmethod
def validate_manifest_path(cls, value: str) -> str:
normalized = Path(value)
if normalized.is_absolute() or ".." in normalized.parts:
raise ValueError("manifest_path must be a safe relative path")
return value
class AliyunSmsSettings(BaseModel):
access_key_id: str = "CHANGE_ME"
access_key_secret: str = "CHANGE_ME"
sign_name: str = "CHANGE_ME"
template_code: str = "CHANGE_ME"
region_id: str = "cn-hangzhou"
endpoint: str = "dysmsapi.aliyuncs.com"
test_mode: bool = False
class AliyunContentSecuritySettings(BaseModel):
access_key_id: str = "CHANGE_ME"
access_key_secret: str = "CHANGE_ME"
endpoint: str = "green-cip.cn-shenzhen.aliyuncs.com"
class AlipaySettings(BaseModel):
app_id: str = "CHANGE_ME"
merchant_id: str = "CHANGE_ME"
public_key: str = "CHANGE_ME"
private_key: str = "CHANGE_ME"
sign_type: str = "RSA2"
notify_url: str = ""
timeout_express: str = "30m"
sandbox: bool = False
class DeepSeekSettings(BaseModel):
api_key: str = "CHANGE_ME"
class AuthSettings(BaseModel):
token_expiration_days: int = 7
token_refresh_threshold_hours: int = 2
class VerificationSettings(BaseModel):
code_length: int = 6
expiration_minutes: int = 5
test_mode: bool = False
class SensitiveWordSettings(BaseModel):
use_aliyun: bool = True
fallback_to_local: bool = True
@@ -217,6 +189,11 @@ class TestSettings(BaseModel):
password: str = ""
class TaskiqSettings(BaseModel):
broker_url: str | None = None
result_backend_url: str | None = None
def _resolve_env_file() -> str:
current = Path(__file__).resolve()
for parent in [current, *current.parents]:
@@ -233,24 +210,31 @@ class Settings(BaseSettings):
runtime: RuntimeSettings = RuntimeSettings()
cors: CorsSettings = CorsSettings()
redis: RedisSettings = RedisSettings()
database: DatabaseSettings = DatabaseSettings()
app_version: AppVersionSettings = AppVersionSettings()
aliyun_sms: AliyunSmsSettings = AliyunSmsSettings()
aliyun_content_security: AliyunContentSecuritySettings = (
AliyunContentSecuritySettings()
supabase: SupabaseSettings = Field(
default_factory=lambda: SupabaseSettings(public_url="http://localhost:8001")
)
alipay: AlipaySettings = AlipaySettings()
deepseek: DeepSeekSettings = DeepSeekSettings()
auth: AuthSettings = AuthSettings()
verification: VerificationSettings = VerificationSettings()
sensitive_word: SensitiveWordSettings = SensitiveWordSettings()
storage: StorageSettings = StorageSettings()
llm: LlmSettings = LlmSettings()
database: DatabaseSettings = DatabaseSettings()
sensitive_word: SensitiveWordSettings = Field(default_factory=SensitiveWordSettings)
test: TestSettings = Field(default_factory=TestSettings)
taskiq: TaskiqSettings = Field(default_factory=TaskiqSettings)
@computed_field
@property
def database_url(self) -> str:
return self.database.url
@computed_field
@property
def taskiq_broker_url(self) -> str:
return self.taskiq.broker_url or self.redis.url
@computed_field
@property
def taskiq_result_backend_url(self) -> str:
return self.taskiq.result_backend_url or self.redis.url
model_config: ClassVar[SettingsConfigDict] = SettingsConfigDict(
env_file=_resolve_env_file(),
env_prefix="ERYAO_",
@@ -1,34 +0,0 @@
input_template: |
你正在执行一次"自动化记忆回顾与整理"任务。
任务目标:
1) 回顾最近两天的聊天与上下文,识别用户长期偏好、习惯和关键事实的变化。
2) 对已经失效、被否定或明显过期的信息执行遗忘。
3) 对新增且有证据支持的信息执行写入。
4) 严禁编造;没有证据就不要写入。
5) 只更新最小必要字段,避免过度覆盖。
输出要求:
- 必须使用以下固定格式输出:
<----------【周期任务输出】---------->
【记忆回顾】<一句人性化总结,说明今天主要发生了什么>
【新增记忆】<按"X条:要点1;要点2"描述;没有则写"0条">
【遗忘记忆】<按"X条:要点1;要点2"描述;没有则写"0条">
【未来展望】<基于本次记忆变化,给出1-2条温和、可执行的后续建议;若暂无建议则说明"可继续观察">
表达风格:
- 语言自然、温和、可读,像助理在做每日回顾。
- 结论先行,避免空话,不要输出与任务无关的闲聊内容。
enabled_tools:
- memory.write
- memory.forget
context:
source: latest_chat
window_mode: day
window_count: 2
schedule:
type: daily
run_at:
hour: 8
minute: 0
weekdays: null
@@ -1,158 +0,0 @@
version: "1.0"
routes:
- route_id: auth.boot
path: /boot
description: Bootstraps auth session and redirects to login or home.
category: auth
auth_required: false
- route_id: auth.login
path: /login
description: Login entry for unauthenticated users.
category: auth
auth_required: false
- route_id: home.main
path: /
description: Main assistant home screen.
category: home
auth_required: true
- route_id: message.invite_list
path: /messages/invites
description: Lists message invitations.
category: messages
auth_required: true
- route_id: message.invite_detail
path: /messages/invites/{id}
description: Shows details for a single invitation.
category: messages
auth_required: true
path_params:
- id
- route_id: contacts.list
path: /contacts
description: Contact list and quick relationship actions.
category: contacts
auth_required: true
- route_id: contacts.add
path: /contacts/add
description: Create or edit a contact profile.
category: contacts
auth_required: true
- route_id: calendar.dayweek
path: /calendar/dayweek
description: Day and week calendar view.
category: calendar
auth_required: true
query_params:
- date
- from
- route_id: calendar.month
path: /calendar/month
description: Month calendar overview.
category: calendar
auth_required: true
query_params:
- from
- route_id: calendar.event_detail
path: /calendar/events/{id}
description: Detail page for one calendar event.
category: calendar
auth_required: true
path_params:
- id
- route_id: calendar.event_create
path: /calendar/events/new
description: Create page for one calendar event.
category: calendar
auth_required: true
query_params:
- date
- route_id: calendar.event_edit
path: /calendar/events/{id}/edit
description: Edit page for one calendar event.
category: calendar
auth_required: true
path_params:
- id
- route_id: calendar.event_share
path: /calendar/events/{id}/share
description: Share settings page for one calendar event.
category: calendar
auth_required: true
path_params:
- id
- route_id: todo.list
path: /todo
description: Todo quadrants and backlog overview.
category: todo
auth_required: true
- route_id: todo.create
path: /todo/new
description: Create page for one todo item.
category: todo
auth_required: true
- route_id: todo.detail
path: /todo/{id}
description: Detail page for one todo item.
category: todo
auth_required: true
path_params:
- id
- route_id: todo.edit
path: /todo/{id}/edit
description: Dedicated subpage for editing one todo item (not an in-page modal).
category: todo
auth_required: true
path_params:
- id
- route_id: settings.main
path: /settings
description: Settings hub page.
category: settings
auth_required: true
- route_id: settings.features
path: /settings/features
description: Automation job list page.
category: settings
auth_required: true
- route_id: settings.job_new
path: /settings/job/new
description: Create page for one automation job.
category: settings
auth_required: true
- route_id: settings.job_detail
path: /settings/job/{id}
description: Detail page for one automation job.
category: settings
auth_required: true
path_params:
- id
- route_id: settings.memory
path: /settings/memory
description: Memory preferences and controls.
category: settings
auth_required: true
- route_id: settings.memory_user
path: /settings/memory/user
description: User memory summary view.
category: settings
auth_required: true
- route_id: settings.memory_work
path: /settings/memory/work
description: Work memory summary view.
category: settings
auth_required: true
- route_id: settings.memory_user_edit
path: /settings/memory/user/edit
description: Edit user memory details.
category: settings
auth_required: true
- route_id: settings.memory_work_edit
path: /settings/memory/work/edit
description: Edit work memory details.
category: settings
auth_required: true
- route_id: settings.edit_profile
path: /edit-profile
description: Profile editing page.
category: settings
auth_required: true