fix: read a tier the way every config path actually spells it
Both public assembly paths took the tier on trust: a bare "none" from JSON or a hand-built SourceConfig stayed a str, and `is Effort.NONE` then read it as a contradiction and crashed on `.value` while wording the error -- the caller got an AttributeError where a ValueError was promised, and on the request side that unclassified exception walked straight through the transport's ThinkingUnsupportedError catch and the retry classifier. Normalize at the two entrances instead, matching what the .env path has always done, and let EFFORT_FALLBACK be spelled with the same freedom as its neighbour.
This commit is contained in:
@@ -22,10 +22,10 @@ from loguru import logger
|
||||
from polygateway.types import (
|
||||
BackpressurePolicy,
|
||||
BreakerConfig,
|
||||
Effort,
|
||||
GlobalLimits,
|
||||
RetryPolicy,
|
||||
SourceConfig,
|
||||
coerce_effort,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -47,6 +47,7 @@ _SOURCE_FIELDS: dict[str, tuple[str, str]] = {
|
||||
# 档位两键(issue #20);值域校验分工: 档位在此(解析即校验,报错点得出 env 键名),
|
||||
# fallback 交给 SourceConfig 构造期(那道同时覆盖构造函数注入与 dataclasses.replace)
|
||||
"REASONING_EFFORT": ("reasoning_effort", "effort"),
|
||||
# 归一化(strip+lower)在 SourceConfig 构造期,与值域校验同处一点,故这里是裸 "str"
|
||||
"EFFORT_FALLBACK": ("effort_fallback", "str"),
|
||||
"MISSING_DONE": ("missing_done", "str"),
|
||||
"TRUST_ENV": ("trust_env", "bool"),
|
||||
@@ -99,7 +100,9 @@ def _cast(raw: str, kind: str, key: str) -> object:
|
||||
return False
|
||||
raise ValueError(f"非法布尔值: {raw!r}")
|
||||
if kind == "effort":
|
||||
return _to_effort(raw)
|
||||
# 归一化只有一份实现(`types.coerce_effort`),env 路与两条装配路同口径;
|
||||
# origin 传空串是因为 env 键名由下面统一的"配置 X 解析失败"补上
|
||||
return coerce_effort(raw, origin="")
|
||||
if kind == "json":
|
||||
# JSONDecodeError 是 ValueError 子类,复用下方的统一包装
|
||||
parsed = json.loads(raw)
|
||||
@@ -111,25 +114,6 @@ def _cast(raw: str, kind: str, key: str) -> object:
|
||||
raise ValueError(f"配置 {key} 解析失败: {exc}") from exc
|
||||
|
||||
|
||||
def _to_effort(raw: str) -> Effort:
|
||||
"""把 env 字符串解成 `Effort`;越界时报错并**列出全部八档**。
|
||||
|
||||
列全八档不是啰嗦: 档位词汇是封闭的,而下游会照着别处的习惯写
|
||||
(`lowest`/`off`/`disabled` 都出现过),只说"非法值"等于让人去翻源码。
|
||||
|
||||
`strip().lower()` 与 `bool` 分支同一先例: `.env` 里的行尾空格与大写写法
|
||||
是常态,而档位取值本身没有大小写语义(`Effort` 的值全小写)。
|
||||
"""
|
||||
try:
|
||||
return Effort(raw.strip().lower())
|
||||
except ValueError:
|
||||
# 不 `from exc`: 枚举原生的 "'lowest' is not a valid Effort" 只是同一
|
||||
# 件事的英文复述,链上去反而把可操作的那句挤到后面
|
||||
raise ValueError(
|
||||
f"非法推理档位 {raw!r};允许: {', '.join(e.value for e in Effort)}"
|
||||
) from None
|
||||
|
||||
|
||||
def _first(env: Mapping[str, str], *keys: str) -> tuple[str, str] | None:
|
||||
for key in keys:
|
||||
raw = env.get(key)
|
||||
|
||||
Reference in New Issue
Block a user