fix: 补全最小可运行骨架(core/config + core/logging)
- main.py 此前 import 不存在的 .core.config/.core.logging,生成项目一 import 即崩 - 补 backend/agent 的 core/config.py(pydantic-settings)+ core/logging.py(loguru) + 各级 __init__.py,按服务/数据库/LLM 选型渲染配置字段 - 路线 A:仅补可运行的 plumbing,业务分层仍由 Claude 按规则现写 - 验证:生成 backend 后 uv sync + import app 成功,/health 路由就位
This commit is contained in:
@@ -0,0 +1,39 @@
|
|||||||
|
from functools import lru_cache
|
||||||
|
|
||||||
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||||
|
|
||||||
|
|
||||||
|
class Settings(BaseSettings):
|
||||||
|
"""Agent 配置。
|
||||||
|
|
||||||
|
字段 snake_case 自动映射 .env 的 SCREAMING_SNAKE,无需 alias_generator
|
||||||
|
(见 .claude/rules/config.md)。
|
||||||
|
"""
|
||||||
|
|
||||||
|
env: str = "dev"
|
||||||
|
port: int = {{ agent_port }}
|
||||||
|
log_level: str = "INFO"
|
||||||
|
enable_api_docs: bool = True
|
||||||
|
work_dir: str = "~/{{ project_slug }}"
|
||||||
|
{%- if llm_provider == 'gemini-cli' %}
|
||||||
|
llm_cmd: str = "{{ llm_cmd }}"
|
||||||
|
max_concurrent_sessions: int = 4
|
||||||
|
{%- elif llm_provider == 'openai-api' %}
|
||||||
|
openai_api_key: str = ""
|
||||||
|
openai_model: str = "gpt-4o"
|
||||||
|
{%- elif llm_provider == 'anthropic-api' %}
|
||||||
|
anthropic_api_key: str = ""
|
||||||
|
anthropic_model: str = "claude-sonnet-4-6"
|
||||||
|
{%- else %}
|
||||||
|
llm_cmd: str = "{{ llm_cmd }}"
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
model_config = SettingsConfigDict(
|
||||||
|
env_file=".env", env_file_encoding="utf-8", extra="ignore"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache
|
||||||
|
def get_settings() -> Settings:
|
||||||
|
"""单例配置,启动即校验类型,fail-fast。"""
|
||||||
|
return Settings()
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
|
||||||
|
def configure_logging(level: str = "INFO") -> None:
|
||||||
|
"""配置 loguru:结构化日志、单一 stderr sink。
|
||||||
|
|
||||||
|
生产可改 serialize=True 输出 JSON、或加文件 sink(见 .claude/rules/observability.md)。
|
||||||
|
"""
|
||||||
|
logger.remove()
|
||||||
|
logger.add(sys.stderr, level=level.upper(), backtrace=False, diagnose=False)
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
from functools import lru_cache
|
||||||
|
|
||||||
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||||
|
|
||||||
|
|
||||||
|
class Settings(BaseSettings):
|
||||||
|
"""应用配置。
|
||||||
|
|
||||||
|
字段为 snake_case,自动映射 .env 的 SCREAMING_SNAKE(如 ``port`` ↔ ``PORT``),
|
||||||
|
无需自定义 alias_generator——详见 .claude/rules/config.md。
|
||||||
|
"""
|
||||||
|
|
||||||
|
env: str = "dev"
|
||||||
|
port: int = {{ backend_port }}
|
||||||
|
log_level: str = "INFO"
|
||||||
|
enable_api_docs: bool = True
|
||||||
|
work_dir: str = "~/{{ project_slug }}"
|
||||||
|
{%- if include_agent %}
|
||||||
|
agent_ws_url: str = "ws://localhost:{{ agent_port }}"
|
||||||
|
{%- endif %}
|
||||||
|
{%- if database == 'sqlite' %}
|
||||||
|
database_url: str = "sqlite+aiosqlite:///~/{{ project_slug }}/{{ project_slug }}.db"
|
||||||
|
{%- elif database == 'postgresql' %}
|
||||||
|
database_url: str = "postgresql+asyncpg://user:password@localhost:5432/{{ project_slug }}"
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
model_config = SettingsConfigDict(
|
||||||
|
env_file=".env", env_file_encoding="utf-8", extra="ignore"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache
|
||||||
|
def get_settings() -> Settings:
|
||||||
|
"""单例配置,启动即校验类型,fail-fast。"""
|
||||||
|
return Settings()
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
|
||||||
|
def configure_logging(level: str = "INFO") -> None:
|
||||||
|
"""配置 loguru:结构化日志、单一 stderr sink。
|
||||||
|
|
||||||
|
生产可改 serialize=True 输出 JSON、或加文件 sink(见 .claude/rules/observability.md)。
|
||||||
|
"""
|
||||||
|
logger.remove()
|
||||||
|
logger.add(sys.stderr, level=level.upper(), backtrace=False, diagnose=False)
|
||||||
Reference in New Issue
Block a user