feat: wire the telemetry text cap through settings

`PGW_TELEMETRY_TEXT_CAP` now reaches the emitter on every assembly path.
Unset means no truncation, which stays the default: a truncated row is
no longer audit evidence and cannot be replayed, and downstreams rely on
that today. The flip side — contracts and bids sitting in `llm_calls`
indefinitely, multi-tenant — is spelled out in `.env.example` so readers
can weigh both.

All three `from_settings` paths are wired (chat, embedding, OCR): they
write the same table, so capping only chat would leave half of it
uncontrolled. `TelemetryEmitter.__init__` now rejects `text_cap <= 0`;
it is the single point where the three clients converge, so the direct
construction path — a public assembly route the settings guard never
sees — is covered too. `0` would otherwise reduce every body to a bare
elision marker.
This commit is contained in:
2026-08-19 13:57:15 -04:00
parent 33ed7ecdfc
commit c26b34e854
9 changed files with 192 additions and 0 deletions
+5
View File
@@ -144,7 +144,12 @@ class TelemetryEmitter:
"""`text_cap` 无默认值是有意的: 它是关键行为参数,漏传即静默改变落库正文。
本类是库内部类,唯一构造者是三个公共 Client,必填能保证没有一处漏传。
同理,值域校验也放在这一处: 三个 Client 的 `text_cap` 全部汇流到这里,
`GatewaySettings` 那道只管 env 一条路,而直接构造 Client 是库承诺的另一
条公共装配路——`text_cap=0` 会让每条正文只剩一个省略标记(P5 不得静默)。
"""
if text_cap is not None and text_cap <= 0:
raise ValueError(f"text_cap 必须 > 0(不截断请传 None): {text_cap}")
self._recorder = recorder
self._pricing = pricing
self._text_cap = text_cap