Files
ai-kefu-admin/app/platform/defaults.py
T
浅念 71e11c317f refactor: config_views 单入口 + 0语义统一 + FakeAI 收敛(清理单#1#2#3)
- #3 六个消费视图 resolver 收拢 app/platform/config_views(单一定义点):
  resolve_email/push/ai_settings ← 各服务文件, resolve_contact_flags/
  context_seed_map ← conversation, name_to_region_extras ← manager
  __init__ 内联取值(or None 语义原样)——函数体逐字搬入,服务层 import 之,
  旧定义删;Phase 3 编辑器/试金石与该模块对接
- #2 限流 0 语义统一: conn_limiter.try_acquire 的 limit 与 chat_rest 的
  rate_limit_per_hour 取值同款——0 或负 = 回退出厂默认(与姊妹键一致),
  原 conn_limiter 0=全拒改为回退;chat_rest 取值抽 _resolve_rate_limit
  纯函数供锚定
- #1 FakeAI 收敛进 conftest(超集: extract/evaluate/eval_calls),四份拷贝
  删(test_lead_email_trigger/test_cc_integration/test_channel_hygiene/
  test_lead_push_wiring——计划记三份,grep 实有四份;push_wiring 经
  evaluate 参数注入原本地固定返回值,断言零改动)

全量 558 passed(554 + 新增 4: 单入口/内联等价/两处 0 语义)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-13 11:45:42 +08:00

44 lines
2.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""出厂默认配置。结构 = spec §5.1 的 9 个配置组。
brand 由租户 seed(seed_profiles/<slug>/)提供;wall 由租户 seed 的
wall.json 提供(app/engine/wall_schema.compile_wall 编译),出厂均留空。
只读约定:消费者不得修改本 dict,需要定制走 deep_merge 拷贝。"""
import copy
DEFAULT_CONFIG: dict = {
"brand": {
"title": "AI Support", "color": "#066fc0", "avatar": "/static/kefu-small.png",
"welcome": "", "topics": [], "placeholder": "",
"whatsapp": "", "email": "", "privacy_url": "",
},
"wall": {}, # wall 由租户 seed 的 wall.json 提供,出厂留空
"contact": {"cc_completion": True, "email_light_ask": True, "template_languages": ["en", "zh", "es"]},
"email": {"smtp": None, "sender_name": "", "notify_emails": []},
# 数值字段出厂哨兵 None = "未设置"(与 ai.model 同款纪律):
# resolve_push_settings 对 None 回退 env PUSH_*(settings 自带部署级默认,
# 最终行为不变)——truthy 出厂默认(10/3/1.0)会永久遮住 env 同名覆盖
"push": {"enabled": False, "url": "", "api_key": "", "prefix": "",
"timeout": None, "max_attempts": None, "retry_backoff_base": None},
"ai": {"provider": "glm", "api_key": None, "base_url": None,
# 双源防漂移: 出厂 model 须与 config_views._FACTORY_DEFAULT_MODEL 一致
# (resolve_ai_settings 的"未设置"哨兵;测试强制同步)
"model": "glm-4-flash"},
"engine": {"context_seed_keys": {},
# 双源防漂移: 默认值须与 rate_limit.DEFAULT_MAX 一致
# (chat_rest 空槽兜底读它)
"rate_limit_per_hour": 30,
# 双源防漂移: 默认值须与 conn_limiter.DEFAULT_WS_CONN_LIMIT 一致
"ws_conn_limit": 10},
"misc": {"name_to_region_extras": {}},
}
def deep_merge(base: dict, override: dict) -> dict:
"""override 逐层覆盖 base;dict 递归合并,其余类型整体替换。不修改入参。"""
out = copy.deepcopy(base)
for k, v in (override or {}).items():
if isinstance(v, dict) and isinstance(out.get(k), dict):
out[k] = deep_merge(out[k], v)
else:
out[k] = copy.deepcopy(v)
return out