diff --git a/template/agent/src/__init__.py b/template/agent/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/template/agent/src/core/__init__.py b/template/agent/src/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/template/agent/src/core/config.py.jinja b/template/agent/src/core/config.py.jinja new file mode 100644 index 0000000..e6abd16 --- /dev/null +++ b/template/agent/src/core/config.py.jinja @@ -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() diff --git a/template/agent/src/core/logging.py.jinja b/template/agent/src/core/logging.py.jinja new file mode 100644 index 0000000..d8f2d66 --- /dev/null +++ b/template/agent/src/core/logging.py.jinja @@ -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) diff --git a/template/backend/src/__init__.py b/template/backend/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/template/backend/src/core/__init__.py b/template/backend/src/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/template/backend/src/core/config.py.jinja b/template/backend/src/core/config.py.jinja new file mode 100644 index 0000000..57fee66 --- /dev/null +++ b/template/backend/src/core/config.py.jinja @@ -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() diff --git a/template/backend/src/core/logging.py.jinja b/template/backend/src/core/logging.py.jinja new file mode 100644 index 0000000..d8f2d66 --- /dev/null +++ b/template/backend/src/core/logging.py.jinja @@ -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)