@@ -25,6 +25,7 @@ from polygateway.types import (
BackpressurePolicy ,
BreakerConfig ,
ChatRequest ,
Effort ,
EmbeddingTransportResult ,
GlobalLimits ,
LLMResponse ,
@@ -63,6 +64,7 @@ _EXPECTED_COLUMNS = [
" tenant_id " ,
" meta " ,
" thinking_observation " ,
" reasoning_effort " ,
]
@@ -132,6 +134,8 @@ async def _record_minimal(recorder, call_id="c1", **overrides):
" meta " : " {} " ,
# 同样已由 emitter 归一化: 枚举取 .value 后才下沉,recorder 只见裸 str
" thinking_observation " : " unknown " ,
# 同理: `Effort` 归一成裸 str,不表态则是 None(与 'low' 必须分得开)
" reasoning_effort " : None ,
}
fields . update ( overrides )
await recorder . record_llm_call ( * * fields )
@@ -177,16 +181,17 @@ _FROZEN_SQLITE_INSERT = (
" INSERT OR IGNORE INTO llm_calls (call_id, parent_call_id, session_id, model, provider, "
" source_name, messages, response, thinking, prompt_tokens, completion_tokens, usage_source, "
" latency_ms, ttft_ms, max_inter_token_ms, cache_hit, error, cost, cached_prompt_tokens, "
" model_reported, sampling, reasoning_tokens, tenant_id, meta, thinking_observation) "
" VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "
" model_reported, sampling, reasoning_tokens, tenant_id, meta, thinking_observation, "
" reasoning_effort) "
" VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "
)
_FROZEN_PG_INSERT = (
" INSERT INTO llm_calls (call_id, parent_call_id, session_id, model, provider, source_name, "
" messages, response, thinking, prompt_tokens, completion_tokens, usage_source, latency_ms, "
" ttft_ms, max_inter_token_ms, cache_hit, error, cost, cached_prompt_tokens, model_reported, "
" sampling, reasoning_tokens, tenant_id, meta, thinking_observation) "
" sampling, reasoning_tokens, tenant_id, meta, thinking_observation, reasoning_effort ) "
" VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, "
" $19, $20, $21, $22, $23, $24, $25) "
" $19, $20, $21, $22, $23, $24, $25, $26 ) "
# 无冲突目标(issue #13 Task 2): 带 `(call_id)` 的版本在按 created_at 分区、
# 主键为 (call_id, created_at) 的表上匹配不到约束,PG 直接拒收整条写入
" ON CONFLICT DO NOTHING "
@@ -212,7 +217,7 @@ class TestSchemaModule:
# COLUMNS 是 INSERT 字段序,不含数据库自填的 created_at
assert list ( COLUMNS ) == [ c for c in _EXPECTED_COLUMNS if c != " created_at " ]
assert len ( COLUMNS ) == 25
assert len ( COLUMNS ) == 26
# 两端 DDL 的列出现顺序 == 物理列序(created_at 在第 19 位)
for ddl in ( SQLITE_DDL , PG_DDL ) :
assert _first_occurrence_order ( ddl , _EXPECTED_COLUMNS ) == _EXPECTED_COLUMNS
@@ -226,8 +231,8 @@ class TestSchemaModule:
" ALTER TABLE llm_calls ADD COLUMN cached_prompt_tokens INTEGER " ,
)
assert PG_BACKFILL [ - 1 ] == (
" thinking_observation " ,
" ALTER TABLE llm_calls ADD COLUMN thinking_observation TEXT " ,
" reasoning_effort " ,
" ALTER TABLE llm_calls ADD COLUMN reasoning_effort TEXT " ,
)
assert all ( " IF NOT EXISTS " not in stmt for _ , stmt in PG_BACKFILL )
@@ -275,7 +280,7 @@ class TestSchemaModule:
pg = telemetry_schema_sql ( " postgres " )
lite = telemetry_schema_sql ( " sqlite " )
for script in ( pg , lite ) :
# 25 个 INSERT 字段 + created_at 全在,且首次出现顺序与建表 DDL 一致
# 26 个 INSERT 字段 + created_at 全在,且首次出现顺序与建表 DDL 一致
assert _first_occurrence_order ( script , _EXPECTED_COLUMNS ) == _EXPECTED_COLUMNS
assert " CREATE TABLE IF NOT EXISTS llm_calls " in script
# 人执行的那份必须幂等: PG 用 ADD COLUMN IF NOT EXISTS(与库内那份有意不同)
@@ -313,7 +318,7 @@ class TestBackendColumnParity:
""" 新列只能追加在末尾: 旧表经 ALTER 补列必落末尾,插在中间会让两条路径分叉。 """
from polygateway . telemetry . schema import COLUMNS
assert COLUMNS [ - 3 : ] == ( " tenant_id " , " meta " , " thinking_observation " )
assert COLUMNS [ - 4 : ] == ( " tenant_id " , " meta " , " thinking_observation " , " reasoning_effort " )
class TestSQLiteRecorder :
@@ -405,6 +410,27 @@ class TestSQLiteRecorder:
assert rows [ " t-absent " ] == " absent " # 观测到"确实没推理",与"看不出来"不是一回事
assert rows [ " t-unknown " ] == " unknown "
async def test_reasoning_effort_column_round_trips ( self , tmp_path ) :
""" issue #20: 实际档位落库,事后才分得清 " 这一行跑在哪档 " 。
断言裸串而非枚举,理由与 `thinking_observation` 逐字相同: `StrEnum` 是
`str` 子类,而 asyncpg 对子类编码不保证接受,遥测写失败只降级一条 warning
——PG 那一路会静默少一列,SQLite 本地全绿也发现不了。
"""
recorder = SQLiteRecorder ( tmp_path / " t.db " , auto_migrate = True )
await _record_minimal ( recorder , call_id = " e-low " , reasoning_effort = " low " )
await _record_minimal ( recorder , call_id = " e-max " , reasoning_effort = " max " )
await _record_minimal ( recorder , call_id = " e-silent " )
recorder . close ( )
rows = dict (
sqlite3 . connect ( tmp_path / " t.db " )
. execute ( " SELECT call_id, reasoning_effort FROM llm_calls " )
. fetchall ( )
)
assert rows [ " e-low " ] == " low "
assert rows [ " e-max " ] == " max "
assert rows [ " e-silent " ] is None # 不表态是 NULL,与任何一档都分得开
async def test_sampling_column_round_trips ( self , tmp_path ) :
""" issue #4: 采样参数落库,否则事后无法证明某批数据跑在什么温度下。 """
recorder = SQLiteRecorder ( tmp_path / " t.db " , auto_migrate = True )
@@ -568,7 +594,7 @@ class TestSQLiteCallerDimensionsAcceptance:
conn = sqlite3 . connect ( db )
cols = [ r [ 1 ] for r in conn . execute ( " PRAGMA table_info(llm_calls) " ) ]
assert cols == _EXPECTED_COLUMNS # 22 → 25 个 recorder 字段(+ created_at 共 26 物理列)
assert cols == _EXPECTED_COLUMNS # 22 → 26 个 recorder 字段(+ created_at 共 27 物理列)
rows = dict ( conn . execute ( " SELECT call_id, tenant_id FROM llm_calls " ) . fetchall ( ) )
assert rows [ " new-row " ] == " tenant-a "
assert rows [ " old-row " ] == " " # 不是 None: NULL 会被 RLS 静默吞掉
@@ -610,7 +636,7 @@ class TestSQLiteCallerDimensionsAcceptance:
stale = sqlite3 . connect ( db )
assert [ r [ 1 ] for r in stale . execute ( " PRAGMA table_info(llm_calls) " ) ] == (
_EXPECTED_COLUMNS [ : - 3 ]
_EXPECTED_COLUMNS [ : - 4 ]
) # 补列确实没成功,用例不是在只读库上空转
@@ -618,7 +644,7 @@ class TestSQLiteSchemaMode:
""" issue #13: `auto_migrate` 两档——auto 保持自动补列,manual 只裁剪写入不发 DDL。
列数断言一律按**物理列数**写: 旧表 22 个 INSERT 字段 + `created_at` = 23,
补齐后 25 + `created_at` = 26 。混用 INSERT 字段数与物理列数是本处最易错的地方。
补齐后 26 + `created_at` = 27 。混用 INSERT 字段数与物理列数是本处最易错的地方。
"""
def _physical_columns ( self , db : Path ) - > list [ str ] :
@@ -657,7 +683,7 @@ class TestSQLiteSchemaMode:
assert " ALTER TABLE " in message # 给出可直接执行的补列 SQL
async def test_auto_mode_still_upgrades_the_legacy_table ( self , tmp_path ) :
""" auto + 同款旧表: 现状回归,补列后物理列数 23 → 26 。 """
""" auto + 同款旧表: 现状回归,补列后物理列数 23 → 27 。 """
db = tmp_path / " auto_legacy.db "
_make_pre_tenant_db ( db )
@@ -666,10 +692,10 @@ class TestSQLiteSchemaMode:
recorder . close ( )
assert self . _physical_columns ( db ) == _EXPECTED_COLUMNS
assert len ( self . _physical_columns ( db ) ) == 26
assert len ( self . _physical_columns ( db ) ) == 27
async def test_manual_mode_still_creates_a_fresh_table ( self , tmp_path ) :
""" manual 只管 ALTER,不管 CREATE: 全新库照建,26 个物理列齐全(设计 §4.2)。 """
""" manual 只管 ALTER,不管 CREATE: 全新库照建,27 个物理列齐全(设计 §4.2)。 """
db = tmp_path / " manual_fresh.db "
recorder = SQLiteRecorder ( db , auto_migrate = False )
await _record_minimal ( recorder , call_id = " c-fresh " , tenant_id = " tenant-a " )
@@ -894,6 +920,7 @@ class TestPostgresBackfillDiscipline:
" tenant_id " ,
" meta " ,
" thinking_observation " ,
" reasoning_effort " ,
]
def _recorder ( self , conn ) :
@@ -1120,6 +1147,7 @@ class TestEmitterRecorderContract:
latency_ms = 42 ,
response = _resp ( ) ,
error = None ,
reasoning_applies = True ,
)
assert set ( rec . rows [ 0 ] ) == set ( COLUMNS )
@@ -1137,6 +1165,7 @@ class TestEmitterRecorderContract:
latency_ms = 1 ,
response = None ,
error = " boom " ,
reasoning_applies = True ,
)
elif emit == " cache_hit " :
await emitter . emit_cache_hit ( request = _REQ , response = _resp ( ) )
@@ -1165,6 +1194,7 @@ class TestEmitterThinkingObservation:
latency_ms = 1 ,
response = _resp ( thinking_observation = ThinkingObservation . OBSERVED ) ,
error = None ,
reasoning_applies = True ,
)
value = rec . rows [ 0 ] [ " thinking_observation " ]
assert value == " observed "
@@ -1187,6 +1217,7 @@ class TestEmitterThinkingObservation:
latency_ms = 1 ,
response = _resp ( thinking_observation = " observed " ) ,
error = None ,
reasoning_applies = True ,
)
assert len ( rec . rows ) == 1 , " 整行被吞了 "
value = rec . rows [ 0 ] [ " thinking_observation " ]
@@ -1212,6 +1243,7 @@ class TestEmitterThinkingObservation:
latency_ms = 1 ,
response = _resp ( thinking_observation = " OBSERVED " ) , # 大小写不符即域外
error = None ,
reasoning_applies = True ,
)
finally :
logger . remove ( sink_id )
@@ -1250,10 +1282,190 @@ class TestEmitterThinkingObservation:
latency_ms = 1 ,
response = None ,
error = " boom " ,
reasoning_applies = True ,
)
assert rec . rows [ 0 ] [ " thinking_observation " ] == " unknown "
class TestEmitterReasoningEffort :
""" issue #20: 每行记下这次调用**实际跑在哪档**,否则压测无从分组。
三个入口的取值口径**有意不同**,故逐个钉死: 只有 `emit_attempt` 手上有生效源,
它才谈得上 " 实际档 " ;另两个入口没有选中源,源级档位无从谈起,只能记请求档。
与 `sampling` 列的现有做法同构。
"""
async def test_attempt_records_the_tier_the_transport_applied ( self ) :
""" `nearest` 映射后成功行记的是**映射后**的档,不是请求档。
请求 `medium`、模型只有 low/high/max 时二者分叉(实发 `low`)。emitter 若
" 顺手 " 重算 `effective_effort`,记的就是一个从未发出过的档,而两个值在没开
映射的源上恒等——本地跑不开映射的源永远看不出这个错。
"""
rec = _MemoryRecorder ( )
await TelemetryEmitter ( rec , text_cap = None ) . emit_attempt (
request = ChatRequest (
messages = [ { " role " : " user " , " content " : " hi " } ] , reasoning_effort = Effort . MEDIUM
) ,
source = _source ( effort_fallback = " nearest " ) ,
call_id = " c " ,
latency_ms = 1 ,
response = _resp ( applied_effort = Effort . LOW ) ,
error = None ,
reasoning_applies = True ,
)
value = rec . rows [ 0 ] [ " reasoning_effort " ]
assert value == " low " # 不是 medium: 那一档从未发出去过
assert type ( value ) is str # 不是 Effort: 子类实例不得下沉到 recorder
async def test_failed_attempt_falls_back_to_the_requested_tier ( self ) :
""" 失败尝试没有响应,实际档不可知,记请求档并接受这层含义差别。
档位错误(resolve 的 Phase 2/4/5)根本没发 HTTP,却照样经
`RequestRejectedError` 走到这里——记的正是**被拒绝的那一档**,这对
" 哪一档配错了 " 是有用信号,不该被过滤掉。
"""
rec = _MemoryRecorder ( )
await TelemetryEmitter ( rec , text_cap = None ) . emit_attempt (
request = _REQ ,
source = _source ( reasoning_effort = Effort . HIGH ) ,
call_id = " c " ,
latency_ms = 1 ,
response = None ,
error = " boom " ,
reasoning_applies = True ,
)
assert rec . rows [ 0 ] [ " reasoning_effort " ] == " high "
async def test_failed_attempt_resolves_the_syntactic_sugar_too ( self ) :
""" 回落走 `effective_effort` 而非裸读字段: `enable_thinking` 也是表态。 """
rec = _MemoryRecorder ( )
await TelemetryEmitter ( rec , text_cap = None ) . emit_attempt (
request = _REQ ,
source = _source ( enable_thinking = True ) ,
call_id = " c " ,
latency_ms = 1 ,
response = None ,
error = " boom " ,
reasoning_applies = True ,
)
assert rec . rows [ 0 ] [ " reasoning_effort " ] == " auto "
async def test_cache_hit_records_the_request_tier_not_the_replayed_one ( self ) :
""" 命中行没有选中源,故记请求档;与 model/prompt_tokens 的回放口径相反。 """
rec = _MemoryRecorder ( )
await TelemetryEmitter ( rec , text_cap = None ) . emit_cache_hit (
request = ChatRequest (
messages = [ { " role " : " user " , " content " : " hi " } ] , reasoning_effort = Effort . MEDIUM
) ,
response = _resp ( cache_hit = True , applied_effort = Effort . LOW ) ,
)
assert rec . rows [ 0 ] [ " reasoning_effort " ] == " medium "
async def test_terminal_failure_records_the_request_tier ( self ) :
""" 终态失败可能根本没选出源,源级档位无从谈起。 """
rec = _MemoryRecorder ( )
await TelemetryEmitter ( rec , text_cap = None ) . emit_terminal_failure (
request = ChatRequest (
messages = [ { " role " : " user " , " content " : " hi " } ] , reasoning_effort = Effort . XHIGH
) ,
call_id = " c " ,
latency_ms = 1 ,
error = " dead " ,
)
value = rec . rows [ 0 ] [ " reasoning_effort " ]
assert value == " xhigh "
assert type ( value ) is str
@pytest.mark.parametrize ( " emit " , [ " attempt " , " cache_hit " , " terminal_failure " ] )
async def test_silence_lands_as_null ( self , emit ) :
""" 谁都没表态时落 `NULL`: `None` 与 ` ' low ' ` 必须分得开(设计 §6)。
库并不观测模型内部的默认档,记一个推定值等于把 " 没看见 " 说成 " 发生了 " 。
"""
rec = _MemoryRecorder ( )
emitter = TelemetryEmitter ( rec , text_cap = None )
if emit == " attempt " :
await emitter . emit_attempt (
request = _REQ ,
source = _source ( ) ,
call_id = " c " ,
latency_ms = 1 ,
response = _resp ( ) ,
error = None ,
reasoning_applies = True ,
)
elif emit == " cache_hit " :
await emitter . emit_cache_hit ( request = _REQ , response = _resp ( cache_hit = True ) )
else :
await emitter . emit_terminal_failure (
request = _REQ , call_id = " c " , latency_ms = 1 , error = " dead "
)
assert rec . rows [ 0 ] [ " reasoning_effort " ] is None
async def test_a_reasonless_path_never_records_a_tier ( self ) :
""" embedding/OCR 走同一个 emitter,但它们的 payload 里没有推理参数。
源上误配了 `ENABLE_THINKING` 时,回落若照算就会给一次 embedding 失败
挂上 `auto` ——那一档从来没有、也不可能被发出去。
"""
rec = _MemoryRecorder ( )
await TelemetryEmitter ( rec , text_cap = None ) . emit_attempt (
request = _REQ ,
source = _source ( enable_thinking = True ) ,
call_id = " c " ,
latency_ms = 1 ,
response = None ,
error = " boom " ,
reasoning_applies = False ,
)
assert rec . rows [ 0 ] [ " reasoning_effort " ] is None
async def test_an_out_of_domain_tier_degrades_but_keeps_the_row ( self ) :
""" 域外取值降级为 `NULL` 且**不丢整行**(遥测必录);与缓存回放同一方向。
`LLMResponse` 无运行时校验,测试替身写裸串完全自然;直接 `Effort(raw)` 会
抛 `ValueError`,被 `_record` 的 `except Exception` 吞成丢整行。
"""
rec = _MemoryRecorder ( )
messages : list [ str ] = [ ]
sink_id = logger . add ( messages . append , level = " WARNING " )
try :
await TelemetryEmitter ( rec , text_cap = None ) . emit_attempt (
request = _REQ ,
source = _source ( ) ,
call_id = " c " ,
latency_ms = 1 ,
response = _resp ( applied_effort = " lowest " ) ,
error = None ,
reasoning_applies = True ,
)
finally :
logger . remove ( sink_id )
assert len ( rec . rows ) == 1 , " 整行被吞了 "
assert rec . rows [ 0 ] [ " reasoning_effort " ] is None
hits = [ m for m in messages if " lowest " in m ]
assert len ( hits ) == 1 , f " 域外取值必须单独告警: { messages } "
assert [ m for m in messages if " 遥测记录失败 " in m ] == [ ]
async def test_a_bare_string_tier_still_lands ( self ) :
""" 裸串在域内时照常归一并落库,整行不得丢失。 """
rec = _MemoryRecorder ( )
await TelemetryEmitter ( rec , text_cap = None ) . emit_attempt (
request = _REQ ,
source = _source ( ) ,
call_id = " c " ,
latency_ms = 1 ,
response = _resp ( applied_effort = " max " ) ,
error = None ,
reasoning_applies = True ,
)
assert len ( rec . rows ) == 1 , " 整行被吞了 "
value = rec . rows [ 0 ] [ " reasoning_effort " ]
assert value == " max "
assert type ( value ) is str
class TestEmitterObservabilityFields :
""" issue #3: 三个入口各自的取值口径(设计 §5 表)。 """
@@ -1266,6 +1478,7 @@ class TestEmitterObservabilityFields:
latency_ms = 42 ,
response = _resp ( cached_prompt_tokens = 64 , model_reported = " m-real " , reasoning_tokens = 7 ) ,
error = None ,
reasoning_applies = True ,
)
assert rec . rows [ 0 ] [ " cached_prompt_tokens " ] == 64
assert rec . rows [ 0 ] [ " model_reported " ] == " m-real "
@@ -1280,6 +1493,7 @@ class TestEmitterObservabilityFields:
latency_ms = 7 ,
response = None ,
error = " boom " ,
reasoning_applies = True ,
)
assert rec . rows [ 0 ] [ " cached_prompt_tokens " ] is None
assert rec . rows [ 0 ] [ " model_reported " ] is None
@@ -1330,6 +1544,7 @@ class TestEmitterSamplingColumn:
latency_ms = 1 ,
response = _resp ( ) ,
error = None ,
reasoning_applies = True ,
)
assert json . loads ( rec . rows [ 0 ] [ " sampling " ] ) == { " seed " : 42 , " temperature " : 0 }
@@ -1344,6 +1559,7 @@ class TestEmitterSamplingColumn:
latency_ms = 1 ,
response = _resp ( ) ,
error = None ,
reasoning_applies = True ,
)
await emitter . emit_cache_hit ( request = self . _SAMPLED , response = _resp ( ) )
await emitter . emit_terminal_failure (
@@ -1376,6 +1592,7 @@ class TestEmitterSamplingColumn:
latency_ms = 1 ,
response = _resp ( ) ,
error = None ,
reasoning_applies = True ,
)
assert rec . rows [ 0 ] [ " sampling " ] is None
@@ -1408,6 +1625,7 @@ class TestEmitterCallerDimensions:
latency_ms = 1 ,
response = _resp ( ) ,
error = None ,
reasoning_applies = True ,
)
elif emit == " cache_hit " :
await emitter . emit_cache_hit ( request = self . _REQ_A , response = _resp ( cache_hit = True ) )
@@ -1461,6 +1679,7 @@ class TestEmitterCallerDimensions:
latency_ms = 1 ,
response = _resp ( ) ,
error = None ,
reasoning_applies = True ,
)
row = rec . rows [ 0 ]
assert row [ " tenant_id " ] == " "
@@ -1521,6 +1740,7 @@ class TestCostWithCachedTier:
latency_ms = 1 ,
response = full ,
error = None ,
reasoning_applies = True ,
)
await emitter . emit_attempt (
request = _REQ ,
@@ -1531,6 +1751,7 @@ class TestCostWithCachedTier:
prompt_tokens = 1_000_000 , completion_tokens = 0 , cached_prompt_tokens = 600_000
) ,
error = None ,
reasoning_applies = True ,
)
assert rec . rows [ 0 ] [ " cost " ] == pytest . approx ( 10.0 )
assert rec . rows [ 1 ] [ " cost " ] == pytest . approx ( 5.2 ) # 400k× 10 + 600k× 2
@@ -1553,6 +1774,7 @@ class TestCostWithCachedTier:
latency_ms = 1 ,
response = _resp ( usage_source = " unavailable " , cached_prompt_tokens = 5 ) ,
error = None ,
reasoning_applies = True ,
)
assert rec . rows [ 0 ] [ " cost " ] is None
@@ -1568,6 +1790,7 @@ class TestEmitter:
latency_ms = 42 ,
response = _resp ( ) ,
error = None ,
reasoning_applies = True ,
)
row = rec . rows [ 0 ]
assert row [ " call_id " ] == " cid-1 " and row [ " error " ] is None
@@ -1584,6 +1807,7 @@ class TestEmitter:
latency_ms = 7 ,
response = None ,
error = " TransientError: boom " ,
reasoning_applies = True ,
)
row = rec . rows [ 0 ]
assert row [ " error " ] . startswith ( " TransientError " )
@@ -1615,6 +1839,7 @@ class TestEmitter:
usage_source = " unavailable " , prompt_tokens = prompt , completion_tokens = completion
) ,
error = None ,
reasoning_applies = True ,
)
assert rec . rows [ 0 ] [ " cost " ] is None
@@ -1628,6 +1853,7 @@ class TestEmitter:
latency_ms = 42 ,
response = _resp ( prompt_tokens = 0 , completion_tokens = 4000 ) ,
error = None ,
reasoning_applies = True ,
)
assert rec . rows [ 0 ] [ " cost " ] == pytest . approx ( 0.032 )
@@ -1661,6 +1887,7 @@ class TestEmitter:
latency_ms = 1 ,
response = None ,
error = " x " ,
reasoning_applies = True ,
)
assert len ( rec . rows [ 0 ] [ " messages " ] ) < 500 # base64 不整段进库(VT R12)
@@ -1677,6 +1904,7 @@ class TestEmitter:
latency_ms = 1 ,
response = _resp ( ) ,
error = None ,
reasoning_applies = True ,
) # 不抛(降级不冒泡)
@@ -1773,6 +2001,7 @@ async def _emit_with_cap(messages, *, cap, response=_LONG, thinking=_LONG):
latency_ms = 1 ,
response = _resp ( content = response , thinking = thinking ) ,
error = None ,
reasoning_applies = True ,
)
return rec . rows [ 0 ]