fix: 配置接线审查修复(push数值哨兵化/恒真测试修正/哨兵防漂移/种子映射消双路径)
Important-1: push 数值字段(timeout/max_attempts/retry_backoff_base) 出厂默认改 None 哨兵(与 ai.model 同款),resolve_push_settings 对 None 回退 env——根治 truthy 出厂默认永久遮住 env 覆盖;恒真测试修正(env 数值 patch 成 7.5/5/2.0 与出厂区分)+租户显式数值优先断言;ai.provider 遮 env 的边界记入 docstring。Minor-2: 出厂 model 哨兵与 DEFAULT_CONFIG 一致性测试 + defaults.py 双源注释(model/rate_limit_per_hour)。 Minor-4: allowed_seed_keys → context_seed_map(返回映射,单一取值路径)。 Minor-6/7/3/8: WS 配置冻结时机注释/name_to_region 查表序注释改准确/ chat_rest limit 0 语义注释/resolver None 路径仅供测试注释。404 全绿。 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -114,6 +114,9 @@ def resolve_ai_settings(config_data: dict | None) -> dict:
|
||||
api_key/base_url 空槽(None/空串)→ env 智谱凭据(平台默认集团 key,
|
||||
spec §5.5 "用平台默认"状态下租户侧不存密钥);model 空或等于出厂默认
|
||||
→ env AI_MODEL。
|
||||
已知边界: provider 出厂 "glm" 同样遮 env AI_PROVIDER——当前单 provider
|
||||
无实害,多 provider 接入时再改哨兵结构(与 push 数值同款纪律)。
|
||||
config_data=None 路径仅供测试直调,生产调用一律传 runtime.config.data。
|
||||
"""
|
||||
ai = ((config_data or {}).get("ai")) or {}
|
||||
model = ai.get("model")
|
||||
|
||||
@@ -298,7 +298,9 @@ def name_to_region(name: str | None,
|
||||
|
||||
容错:去首尾空白、大小写不敏感、弯撇号(U+2019)归一为 ASCII。
|
||||
Task 9: extras = misc.name_to_region_extras(租户扩表),可加键也可
|
||||
覆盖基础表同名键(租户纠偏)——查表序 extras 优先。
|
||||
覆盖基础表同名键(租户纠偏)。查表分两轮:先精确匹配(extras→基础
|
||||
表)、后 casefold 折叠(extras→基础表)——基础表的精确命中优先于
|
||||
extras 的大小写折叠命中(精确 > 折叠,非"extras 整体优先")。
|
||||
"""
|
||||
if not name:
|
||||
return None
|
||||
|
||||
@@ -50,14 +50,16 @@ def resolve_contact_flags(config_data: dict | None) -> dict:
|
||||
}
|
||||
|
||||
|
||||
def allowed_seed_keys(config_data: dict | None) -> set[str]:
|
||||
"""context 种子白名单 = config.engine.context_seed_keys 的键集合。
|
||||
def context_seed_map(config_data: dict | None) -> dict:
|
||||
"""context 种子映射 = config.engine.context_seed_keys(ctx_key → raw_key)。
|
||||
|
||||
Task 9 前白名单(product_name/product_id)硬编码在本模块——两租户差异
|
||||
(auto 是 vehicle_*)由此配置化;create_conversation 按映射值写 raw_info。
|
||||
(auto 是 vehicle_*)由此配置化;create_conversation 是唯一消费口(按
|
||||
映射值写 raw_info,白名单 = 本映射的键集合——审查 Minor-4: 单一取值
|
||||
路径,不留第二条内联读法)。
|
||||
"""
|
||||
engine = ((config_data or {}).get("engine")) or {}
|
||||
return {str(k) for k in (engine.get("context_seed_keys") or {})}
|
||||
return dict(engine.get("context_seed_keys") or {})
|
||||
|
||||
# 职能边界触发词(Task 13.2, 评审#1/#4 修订): 命中即注入红线提醒。精修说明:
|
||||
# - 裸 "how long"/"多久" 不收(规格参数类问题常用),英文要求 take/arrive/deliver/ship 邻接,
|
||||
@@ -372,7 +374,9 @@ class ConversationManager:
|
||||
wall=runtime.compiled_wall,
|
||||
config_data=runtime.config.data)
|
||||
# Task 9: contact 行为开关(cc 补全/邮箱轻补)与国名映射扩表——
|
||||
# manager 生命周期内配置不变(reload 换 runtime 即换 manager 装配线)
|
||||
# manager 生命周期内配置不变(reload 换 runtime 即换 manager 装配线;
|
||||
# 生效时机: WS 长连接内冻结至断连,REST 路径下一请求生效——Phase 2
|
||||
# 联调改配置后按此预期,勿误判"没生效")
|
||||
self._contact_flags = resolve_contact_flags(runtime.config.data)
|
||||
self._region_extras = (((runtime.config.data.get("misc")) or {})
|
||||
.get("name_to_region_extras") or None)
|
||||
@@ -408,9 +412,8 @@ class ConversationManager:
|
||||
# WS path passes no context -> raw_info stays {}.
|
||||
raw_info: dict = {}
|
||||
if context:
|
||||
engine_cfg = self.runtime.config.data.get("engine") or {}
|
||||
seed_map = engine_cfg.get("context_seed_keys") or {}
|
||||
for ctx_key, raw_key in seed_map.items():
|
||||
for ctx_key, raw_key in context_seed_map(
|
||||
self.runtime.config.data).items():
|
||||
if context.get(ctx_key):
|
||||
raw_info[raw_key] = context[ctx_key]
|
||||
profile = CustomerProfile(conversation_id=conv.id, raw_info=raw_info)
|
||||
|
||||
@@ -37,8 +37,14 @@ logger = logging.getLogger(__name__)
|
||||
def resolve_push_settings(config_data: dict | None) -> dict:
|
||||
"""租户 config.push → 推送参数(Task 9 接线; env settings 回退)。
|
||||
|
||||
出厂默认的空槽(False/空串)视同"未设置"→ 回退 env PUSH_*——部署级
|
||||
.env 开关是平台默认集的一部分,租户未配置时继承,不静默关停。
|
||||
空槽回退哨兵(审查 Important-1, 与 ai.model 同款纪律):
|
||||
- 布尔/字符串: falsy 出厂默认(False/空串)视同"未设置"→ 回退 env
|
||||
PUSH_*——部署级 .env 开关是平台默认集的一部分,租户未配置时继承,
|
||||
不静默关停;
|
||||
- 数值字段(timeout/max_attempts/retry_backoff_base): 出厂 None =
|
||||
"未设置"→ 回退 env(settings 自带默认 10.0/3/1.0,最终行为与出厂
|
||||
truthy 默认时一致),租户显式数值(含显式 0)优先于 env。
|
||||
config_data=None 路径仅供测试直调,生产调用一律传 runtime.config.data。
|
||||
已知边界: env 开 + 租户显式 false 无法区分于未配置(布尔空槽只有
|
||||
False),Phase 2 admin 落地时以"平台清 env、配置显式写 false"解决。
|
||||
"""
|
||||
@@ -48,10 +54,15 @@ def resolve_push_settings(config_data: dict | None) -> dict:
|
||||
"url": p.get("url") or settings.PUSH_API_URL,
|
||||
"api_key": p.get("api_key") or settings.PUSH_API_KEY,
|
||||
"prefix": p.get("prefix") or settings.PUSH_EXTERNAL_KEY_PREFIX,
|
||||
"timeout": p.get("timeout") or settings.PUSH_TIMEOUT_SECONDS,
|
||||
"max_attempts": p.get("max_attempts") or settings.PUSH_MAX_ATTEMPTS,
|
||||
# 数值哨兵: None(出厂/显式清空)→ env;显式数值优先
|
||||
"timeout": (p.get("timeout") if p.get("timeout") is not None
|
||||
else settings.PUSH_TIMEOUT_SECONDS),
|
||||
"max_attempts": (p.get("max_attempts")
|
||||
if p.get("max_attempts") is not None
|
||||
else settings.PUSH_MAX_ATTEMPTS),
|
||||
"retry_backoff_base": (p.get("retry_backoff_base")
|
||||
or settings.PUSH_RETRY_BACKOFF_BASE),
|
||||
if p.get("retry_backoff_base") is not None
|
||||
else settings.PUSH_RETRY_BACKOFF_BASE),
|
||||
}
|
||||
|
||||
# 对方契约(docs/AI_INQUIRY_PUSH_API.md): phone/whatsapp/email 至少一个有效
|
||||
|
||||
Reference in New Issue
Block a user