fix: persist explicit usage models on replay

This commit is contained in:
2026-08-04 16:17:10 +08:00
parent f7020f8fcc
commit a58b6769f1
2 changed files with 47 additions and 0 deletions
+10
View File
@@ -128,6 +128,13 @@ export function recordUsageScan(
last_cache_creation_tokens = excluded.last_cache_creation_tokens
WHERE usage_events.kind = 'delta'
`)
const updateCumulativeModel = db.prepare(`
UPDATE usage_events
SET model = ?
WHERE session_id = ?
AND source_key = ?
AND kind = 'cumulative'
`)
for (const event of events) {
statement.run({
@@ -147,6 +154,9 @@ export function recordUsageScan(
last_cache_read_tokens: event.lastCacheReadTokens,
last_cache_creation_tokens: event.lastCacheCreationTokens
})
if (event.kind === 'cumulative' && event.model !== null) {
updateCumulativeModel.run(event.model, event.sessionId, event.sourceKey)
}
}
}
+37
View File
@@ -256,6 +256,43 @@ describe('usage service', () => {
store.close()
})
it('replaces a cumulative fallback model when a replay adds an explicit model', () => {
const store = new Store(':memory:')
const session = store.sessions.getOrCreateSession(
'codex-explicit-model-replay-test',
{ path: '/tmp', host: 'test', flavor: 'codex' },
null,
'default',
'deepseek-v4-flash'
)
const tokenCount = (model?: string) => ({
type: 'codex',
data: {
type: 'token_count',
model,
thread_id: 'thread-1',
turn_id: 'turn-1',
info: {
total_token_usage: { input_tokens: 100, output_tokens: 10 },
last_token_usage: { input_tokens: 100, output_tokens: 10 }
}
}
})
addAgentMessage(store, session.id, tokenCount())
expect(getUsageSummary(store, 'default', 'all').byModel).toEqual([
expect.objectContaining({ key: 'deepseek-v4-flash', totalTokens: 110, requests: 1 })
])
addAgentMessage(store, session.id, tokenCount('gpt-5.6-sol'))
const result = getUsageSummary(store, 'default', 'all')
expect(result.totals).toEqual(expect.objectContaining({ totalTokens: 110, requests: 1 }))
expect(result.byModel).toEqual([
expect.objectContaining({ key: 'gpt-5.6-sol', totalTokens: 110, requests: 1 })
])
store.close()
})
it('preserves event-level models across model switches and epoch rebuilds', () => {
const store = new Store(':memory:')
const session = store.sessions.getOrCreateSession(