1 line
5.7 KiB
JSON
1 line
5.7 KiB
JSON
{"repo": "bcefghj/xiaonian", "files": {".env.example": {"a57dfbac7e0b119cfefac3970afb04be25df7b8a": {"t": 1785604107.7277687, "n": 991, "h": "ce89d7115ff04fcc", "c": "# 小念 XiaoNian — 环境配置示例\n# 复制为 .env 后填入你的密钥。所有数据与密钥仅保存在本机。\n\n# ===== 默认使用的模型 provider:minimax | deepseek | mimo | mock =====\nXIAONIAN_PROVIDER=minimax\n\n# ===== MiniMax(主力)=====\n# coding 套餐 key(sk-cp-...)走 Anthropic 兼容端点(与 OpenAI 文本接口是不同额度池)\nMINIMAX_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx\nMINIMAX_BASE_URL=https://api.minimaxi.com/anthropic\nMINIMAX_PROTOCOL=anthropic\nMINIMAX_MODEL=MiniMax-M2\n\n# ===== DeepSeek(高性价比备选)=====\nDEEPSEEK_API_KEY=\nDEEPSEEK_BASE_URL=https://api.deepseek.com/v1\nDEEPSEEK_MODEL=deepseek-chat\n\n# ===== 小米 MiMo(生态加分,OpenAI 兼容)=====\nMIMO_API_KEY=\nMIMO_BASE_URL=https://api.example-mimo.xiaomi.com/v1\nMIMO_MODEL=mimo\n\n# ===== 服务 =====\nXIAONIAN_HOST=127.0.0.1\nXIAONIAN_PORT=8765\n\n# ===== 安全/隐私 =====\n# 写操作(删除/移动/执行命令/下单)是否需要两步确认\nXIAONIAN_REQUIRE_CONFIRM=true\n# 上云前 PII 脱敏\nXIAONIAN_REDACT_PII=true\n\n# ===== 主动关心引擎 =====\nXIAONIAN_PROACTIVE_ENABLED=true\n# 静默时段(不主动打扰),24h\nXIAONIAN_QUIET_START=23\nXIAONIAN_QUIET_END=8\n\n# ===== 用户 =====\nXIAONIAN_USER_ID=master\nXIAONIAN_USER_NAME=主人\n"}}, "config.py": {"9813677eed179f6341028448837ecb297a2f5ab7": {"t": 1785604109.1580005, "n": 3027, "h": "b4cebea76b223276", "c": "\"\"\"小念 XiaoNian — 全局配置。\n\n集中读取环境变量(.env),供各层使用。所有路径默认指向本机 data/ 目录,\n体现\"数据全本地\"的隐私原则。\n\"\"\"\nfrom __future__ import annotations\n\nimport os\nfrom dataclasses import dataclass, field\nfrom pathlib import Path\nfrom typing import Dict\n\ntry:\n from dotenv import load_dotenv\n\n load_dotenv()\nexcept Exception: # pragma: no cover - dotenv 可选\n pass\n\n\nROOT = Path(__file__).resolve().parent\nDATA_DIR = ROOT / \"data\"\nDATA_DIR.mkdir(exist_ok=True)\n\n\ndef _b(key: str, default: bool) -> bool:\n v = os.getenv(key)\n if v is None:\n return default\n return v.strip().lower() in {\"1\", \"true\", \"yes\", \"on\"}\n\n\n@dataclass\nclass ProviderConfig:\n \"\"\"单个模型 provider 的连接配置。\n\n protocol:openai(OpenAI 兼容 /chat/completions)或 anthropic(Anthropic 兼容\n /v1/messages)。MiniMax 的 coding 套餐 key 走 anthropic 协议(与 OpenAI 文本\n 接口是不同的额度池)。\n \"\"\"\n\n name: str\n api_key: str\n base_url: str\n model: str\n protocol: str = \"openai\"\n\n @property\n def available(self) -> bool:\n return bool(self.api_key) and not self.api_key.startswith(\"sk-xxxx\")\n\n\n@dataclass\nclass Settings:\n user_id: str = os.getenv(\"XIAONIAN_USER_ID\", \"master\")\n user_name: str = os.getenv(\"XIAONIAN_USER_NAME\", \"主人\")\n host: str = os.getenv(\"XIAONIAN_HOST\", \"127.0.0.1\")\n port: int = int(os.getenv(\"XIAONIAN_PORT\", \"8765\"))\n\n default_provider: str = os.getenv(\"XIAONIAN_PROVIDER\", \"minimax\")\n\n require_confirm: bool = _b(\"XIAONIAN_REQUIRE_CONFIRM\", True)\n redact_pii: bool = _b(\"XIAONIAN_REDACT_PII\", True)\n\n proactive_enabled: bool = _b(\"XIAONIAN_PROACTIVE_ENABLED\", True)\n quiet_start: int = int(os.getenv(\"XIAONIAN_QUIET_START\", \"23\"))\n quiet_end: int = int(os.getenv(\"XIAONIAN_QUIET_END\", \"8\"))\n\n providers: Dict[str, ProviderConfig] = field(default_factory=dict)\n\n def __post_init__(self) -> None:\n self.providers = {\n \"minimax\": ProviderConfig(\n name=\"minimax\",\n api_key=os.getenv(\"MINIMAX_API_KEY\", \"\"),\n base_url=os.getenv(\"MINIMAX_BASE_URL\", \"https://api.minimaxi.com/anthropic\"),\n model=os.getenv(\"MINIMAX_MODEL\", \"MiniMax-M2\"),\n protocol=os.getenv(\"MINIMAX_PROTOCOL\", \"anthropic\"),\n ),\n \"deepseek\": ProviderConfig(\n name=\"deepseek\",\n api_key=os.getenv(\"DEEPSEEK_API_KEY\", \"\"),\n base_url=os.getenv(\"DEEPSEEK_BASE_URL\", \"https://api.deepseek.com/v1\"),\n model=os.getenv(\"DEEPSEEK_MODEL\", \"deepseek-chat\"),\n ),\n \"mimo\": ProviderConfig(\n name=\"mimo\",\n api_key=os.getenv(\"MIMO_API_KEY\", \"\"),\n base_url=os.getenv(\"MIMO_BASE_URL\", \"\"),\n model=os.getenv(\"MIMO_MODEL\", \"mimo\"),\n ),\n }\n\n def provider(self, name: str | None = None) -> ProviderConfig:\n return self.providers.get(name or self.default_provider, self.providers[\"minimax\"])\n\n @property\n def data_dir(self) -> Path:\n return DATA_DIR\n\n\nsettings = Settings()\n"}}, "run.py": {"dd652ac22163bac6e81b92bcaf2519b970aee9cd": {"t": 1785604110.3626041, "n": 518, "h": "9f1902d43cec6842", "c": "\"\"\"小念 XiaoNian 启动入口。\n\n用法:\n python run.py\n然后浏览器打开 http://127.0.0.1:8765\n\"\"\"\nfrom __future__ import annotations\n\nimport uvicorn\n\nfrom config import settings\n\nif __name__ == \"__main__\":\n print(\"=\" * 56)\n print(\" 小念 XiaoNian — 你电脑里会成长的生活助理\")\n print(f\" 本地服务: http://{settings.host}:{settings.port}\")\n print(f\" 默认模型: {settings.default_provider}\")\n print(f\" 数据目录: {settings.data_dir}(全部留在本机)\")\n print(\"=\" * 56)\n uvicorn.run(\"daemon.main:app\", host=settings.host, port=settings.port, reload=False)\n"}}}} |