fix(langfuse): read standard chat fields only for dict usage in responses logging

test_log_langfuse_v2_malformed_responses_api_usage_still_logs expects a
usage dict whose token counts fail validation to log as zero usage. The new
`_usage_token_value` helper's dict branch fell back to decisions-style names
(`input_tokens`/`output_tokens`), resurrecting `input_tokens: 16` from the
raw dict `_chat_usage` passes through when transform raises ValueError.

Keep the decisions fallback on the non-dict branch only (Pydantic decisions
usage models), and read the standard chat field for dicts — matching the
original `getattr(..., None) or 0` semantics. Also place `# cast-ok:` on the
cast call's first line so the type-discipline gate counts it as used
(previously folded onto the continuation line, tripping LIT006 + LIT013).

Verified with scripts/check_type_discipline.py: no LIT006/LIT013 on the
touched lines; remaining violations are main's pre-existing budgeted counts.

Signed-off-by: apex-mochen <2756823972@qq.com>
This commit is contained in:
apex-mochen 2026-10-11 10:24:10 +08:00
parent 30e8703990
commit 7c7c589ade

View file

@ -153,9 +153,13 @@ def _usage_token_value(usage_obj: object, standard_name: str, decision_name: str
"_UsageObject", usage_obj
)
)
if (dict_value := usage_proto.get(standard_name)) is None and decision_name is not None:
decision_dict_value: Final = usage_proto.get(decision_name)
return decision_dict_value if isinstance(decision_dict_value, int) else 0
# A raw dict here means _chat_usage could not validate it as a chat or
# responses usage (e.g. a malformed /v1/responses payload whose token
# counts fail validation) and passed it through unchanged. Read only the
# standard chat field so a failed validation logs as zero, matching
# getattr(..., None) or 0; do not fall back to decisions-style names,
# which would resurrect a value from a payload that failed validation.
dict_value: Final = usage_proto.get(standard_name)
return dict_value if isinstance(dict_value, int) else 0
if (attr_value := getattr(usage_obj, standard_name, None)) is None and decision_name is not None:
decision_attr_value: Final = getattr(usage_obj, decision_name, None)