fix: void the cost of rows whose usage is unavailable

失败尝试与终态失败行的 usage_source 由 estimated 改 unavailable(用量确实
不可得),并在 TelemetryEmitter 的成本换算里为 unavailable 短路记 NULL。
短路刻意插在 cache_hit 分支之后: 缓存命中未产生新调用,0.0 是事实而非未知。
附 OCR 成功行的防回归钉(仍为 measured、settle 恒 0,设计 §3.3 剔出决定)。
This commit is contained in:
2026-07-30 10:37:48 -04:00
parent 76e7d9594c
commit 42e429eb58
3 changed files with 79 additions and 4 deletions
+15
View File
@@ -394,6 +394,21 @@ class TestTelemetry:
assert recorder.rows[1]["error"] is None
assert recorder.rows[1]["prompt_tokens"] == 0
async def test_success_row_stays_measured_and_settles_zero(self):
"""OCR 的 0 token 是**事实**而非未知(est_tokens 解耦设计 §3.3 剔出决定)。
三态化不得把 OCR 成功行改成 `unavailable`——那会灌水缺口度量
`COUNT(*) WHERE usage_source='unavailable'`;settle 恒 0 的差异①同样不动。
"""
recorder = _MemoryRecorder()
client, limiter, _ = _client([_src(tpm=1000, est_tokens=400)], ["text"], telemetry=recorder)
await client.recognize_text(b"jpg")
row = recorder.rows[0]
assert row["usage_source"] == "measured"
assert row["prompt_tokens"] == 0 and row["completion_tokens"] == 0
assert row["error"] is None
assert (await limiter.source_stats("m1")).tpm_used == 0 # settle(0) 全额退回预扣
class TestAssembly:
_ENV = {