Files
bowenliang123 229f7b15ac fix(cost): make DeepSeek peak pricing explicit and weekday-based
The tooltip and shared type still described the pre-#78 scheme (peak at
list price, off at half), while models.dev lists DeepSeek's off-peak
rates and the estimator doubles the peak bucket. Correct the wording in
both locales, the cost type, and the READMEs; only DeepSeek's peak
buckets double, every other provider prices at list.

Express the peak clock in Beijing Time directly (Monday-Friday
09:00-12:00 and 14:00-18:00, weekends off-peak) and rename isPeakUtc to
isBeijingPeak. The UTC-to-Beijing refactor is behavior-preserving, so no
stateVersion bump is needed. Statutory holidays are deliberately not
modeled; record that limitation in docs/compatibility.md.

Refs #178
2026-10-21 10:42:31 +08:00

665 lines
35 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import assert from 'node:assert/strict'
import { describe, test } from 'vitest'
import type { SessionEvent } from '@deepseek-ai/dsh-session'
import { applyActivity, contextActivitySchema, createContextActivityDefinition } from '../../src/host/activity'
import { isBeijingPeak } from '../../src/host/fold'
import { dayKeyOf } from '../../src/shared/days'
/** Local noon of a day offset from 2026-01-01 — deterministic in every timezone. */
function at(daysFromNewYear: number): number {
return new Date(2026, 0, 1 + daysFromNewYear, 12).getTime()
}
function assistantMessage(time: number, usage?: unknown): SessionEvent {
return {
type: 'assistant/message',
seq: 1,
time,
data: usage === undefined ? {} : { usage },
} as never
}
function turnMessage(time: number, turn: number, usage?: unknown): SessionEvent {
return {
type: 'assistant/message',
seq: 1,
time,
data: { turn, ...(usage === undefined ? {} : { usage }) },
} as never
}
describe('contextActivity unit: shape', () => {
test('the definition carries the contract fields', () => {
const def = createContextActivityDefinition()
assert.equal(def.key, 'contextActivity')
assert.equal(def.stateVersion, 5, 'the daily turns/tool/wall tallies are the fifth shape')
assert.deepEqual(def.init(), { days: {} })
})
test('the wire view passes its schema; the state schema round-trips a folded state', () => {
const def = createContextActivityDefinition()
const state = applyActivity(def.init(), assistantMessage(at(0), { inputTokens: 3, outputTokens: 2 }))
const view = def.wire.view(state)
assert.equal(def.wire.viewSchema.safeParse(view).success, true)
assert.equal(contextActivitySchema.safeParse(view).success, true)
assert.equal(def.stateSchema.safeParse(state).success, true)
assert.equal(def.stateSchema.safeParse({ days: { '2026-01-01': { tokens: -1 } } }).success, false)
assert.equal(def.stateSchema.safeParse({ days: { '2026-01-01': { tokens: 'x', requests: 1 } } }).success, false)
})
})
describe('applyActivity: event filtering', () => {
test('non-assistant events return the state unchanged (same reference)', () => {
const def = createContextActivityDefinition()
const state = def.init()
for (const type of ['user/message', 'request/header', 'turn/start', 'bogus/event']) {
assert.ok(applyActivity(state, { type, seq: 1, time: at(0), data: {} } as never) === state, type)
}
})
test('a settlement with an unreadable time is dropped whole', () => {
const def = createContextActivityDefinition()
const state = def.init()
assert.ok(applyActivity(state, assistantMessage(Number.NaN, { inputTokens: 1 })) === state, 'NaN time')
assert.ok(applyActivity(state, assistantMessage(1e30, { inputTokens: 1 })) === state, 'out-of-range time')
assert.ok(applyActivity(state, assistantMessage(-2 * 86_400_000, { inputTokens: 1 })) === state, 'pre-epoch time')
assert.deepEqual(state, { days: {} })
})
test('a tagged fork/seed marker resets the ledger; the untagged resume marker keeps it', () => {
// A seeded fork's inherited prefix: one settlement the parent session
// already booked, plus the step slot its open tail left armed (issue #94).
let state = applyActivity({ days: {} }, assistantMessage(at(0), { inputTokens: 10 }))
state = applyActivity(state, { type: 'step/start', seq: 2, time: at(0), data: {} } as never)
const seeded = state
assert.ok(seeded.stepStart !== undefined)
for (const data of [undefined, null, {}, { inherited: 'yes' }]) {
assert.ok(
applyActivity(seeded, { type: 'session/end-seed', seq: 3, time: at(0), data } as never) === seeded,
`data ${JSON.stringify(data)} must not reset`,
)
}
assert.deepEqual(seeded.days, { '2026-01-01': { tokens: 10, requests: 1 } })
const cut = applyActivity(seeded, { type: 'session/end-seed', seq: 3, time: at(0), data: { inherited: true } } as never)
assert.deepEqual(cut, { days: {} }, 'the inherited ledger and the armed step slot die at the cut')
const after = applyActivity(cut, assistantMessage(at(1), { inputTokens: 3 }))
assert.deepEqual(after.days, { '2026-01-02': { tokens: 3, requests: 1 } })
})
})
describe('applyActivity: the ledger', () => {
test('a metered settlement books the disjoint buckets summed into its day', () => {
const state = applyActivity({ days: {} }, assistantMessage(at(0), {
inputTokens: 10,
cacheReadTokens: 4,
cacheWriteTokens: 2,
outputTokens: 5,
}))
assert.deepEqual(state.days, { '2026-01-01': { tokens: 21, requests: 1 } })
})
test('same-day settlements accumulate; distinct days key apart', () => {
let state = applyActivity({ days: {} }, assistantMessage(at(0), { inputTokens: 10, outputTokens: 5 }))
state = applyActivity(state, assistantMessage(at(0), { outputTokens: 1 }))
state = applyActivity(state, assistantMessage(at(1), { inputTokens: 3 }))
assert.deepEqual(state.days, {
'2026-01-01': { tokens: 16, requests: 2 },
'2026-01-02': { tokens: 3, requests: 1 },
})
})
test('a settlement without usage counts its request without fabricating tokens', () => {
let state = applyActivity({ days: {} }, assistantMessage(at(0)))
state = applyActivity(state, assistantMessage(at(0), null))
state = applyActivity(state, assistantMessage(at(0), 'usage'))
assert.deepEqual(state.days, { '2026-01-01': { tokens: 0, requests: 3 } })
})
test('usage buckets are sanitized: fractions round, negatives clamp, garbage reads absent', () => {
const state = applyActivity({ days: {} }, assistantMessage(at(0), {
inputTokens: 10.4,
cacheReadTokens: -7,
cacheWriteTokens: '6',
outputTokens: Number.NaN,
}))
assert.deepEqual(state.days, { '2026-01-01': { tokens: 16, requests: 1 } })
})
test('a fully unreadable usage object books zero tokens but keeps the request', () => {
const state = applyActivity({ days: {} }, assistantMessage(at(0), { inputTokens: 'x', outputTokens: null }))
assert.deepEqual(state.days, { '2026-01-01': { tokens: 0, requests: 1 } })
})
test('the persisted previous state is never mutated (copy-on-write)', () => {
const before = applyActivity({ days: {} }, assistantMessage(at(0), { inputTokens: 1 }))
const after = applyActivity(before, assistantMessage(at(1), { inputTokens: 2 }))
assert.deepEqual(before.days, { '2026-01-01': { tokens: 1, requests: 1 } })
assert.ok(before !== after)
assert.ok(before.days !== after.days)
})
test('the retention cap evicts the oldest day keys (chronological = lexicographic)', () => {
let state: ReturnType<typeof applyActivity> = { days: {} }
for (let d = 0; d < 401; d++) {
state = applyActivity(state, assistantMessage(at(d), { inputTokens: 1 }))
}
const keys = Object.keys(state.days)
assert.equal(keys.length, 400)
assert.equal(keys.includes('2026-01-01'), false, 'the oldest day dropped')
assert.equal(keys.includes('2026-01-02'), true, 'the kept suffix starts the next day')
// Later folds within the cap keep every day.
state = applyActivity(state, assistantMessage(at(400), { inputTokens: 1 }))
assert.equal(Object.keys(state.days).length, 400)
assert.equal(state.days['2027-02-05'].requests, 2)
})
})
describe('contextActivity unit: the view', () => {
test('the view copies the ledger (the wire never shares the fold’s record)', () => {
const def = createContextActivityDefinition()
const state = applyActivity(def.init(), assistantMessage(at(0), { inputTokens: 1 }))
const view = def.wire.view(state)
assert.ok(view.days !== state.days)
view.days['2026-01-01'].tokens = 999
assert.equal(state.days['2026-01-01'].tokens, 1)
})
})
/** A `user/message` carrying (or faking) a `skill-invocation` source. */
function skillInvocation(time: number, source: unknown): SessionEvent {
return { type: 'user/message', seq: 1, time, data: { source } } as never
}
function toolCall(time: number, callId: unknown, name: unknown): SessionEvent {
return { type: 'tool/call', seq: 1, time, data: { callId, name } } as never
}
function skillResult(time: number, text: string, callId?: string): SessionEvent {
return {
type: 'tool/result',
seq: 1,
time,
data: { message: { toolCallId: callId, content: [{ type: 'text', text }] } },
} as never
}
const INVOCATION = { kind: 'skill-invocation', name: 'tdd', form: 'instructions' }
describe('applyActivity: skill loads', () => {
test('a `/name` invocation books its name on its day', () => {
const state = applyActivity({ days: {} }, skillInvocation(at(0), INVOCATION))
assert.deepEqual(state.days, {
'2026-01-01': { tokens: 0, requests: 0, skills: { tdd: { n: 1, last: at(0) } } },
})
})
test('a `skill`-tool result books the wrapper’s name only when paired to a `skill` call', () => {
let state = applyActivity({ days: {} }, toolCall(at(0), 'c1', 'skill'))
assert.deepEqual(state.skillCalls, ['c1'], 'the call arms the pairing claim')
state = applyActivity(state, skillResult(at(0), '<skill_content name="ponytail">…</skill_content>', 'c1'))
assert.deepEqual(state.days['2026-01-01'].skills, { ponytail: { n: 1, last: at(0) } })
assert.equal(state.skillCalls, undefined, 'the claim consumes once')
})
test('a wrapper in another tool’s result books no skill (a `read` quoting the wrapper is no load)', () => {
let state = applyActivity({ days: {} }, toolCall(at(0), 'c1', 'read'))
state = applyActivity(state, skillResult(at(0), 'source text quoting <skill_content name="…"> inline', 'c1'))
assert.equal(state.days['2026-01-01'].skills, undefined)
assert.equal(state.days['2026-01-01'].toolCalls, 1, 'the read still prices its tool run')
// Wholly unpaired results add no tool run (a trimmed/foreign call).
state = applyActivity(state, skillResult(at(0), '<skill_content name="ponytail">…</skill_content>', 'c9'))
assert.equal(state.days['2026-01-01'].skills, undefined)
assert.equal(state.days['2026-01-01'].toolCalls, 1)
})
test('the lifted toolCallId and the durable source callId both pair', () => {
let state = applyActivity({ days: {} }, toolCall(at(0), 'c1', 'skill'))
const viaSource = {
type: 'tool/result',
seq: 2,
time: at(0),
data: { message: { source: { callId: 'c1' }, content: [{ type: 'text', text: '<skill_content name="tdd">…</skill_content>' }] } },
} as never
state = applyActivity(state, viaSource)
assert.deepEqual(state.days['2026-01-01'].skills, { tdd: { n: 1, last: at(0) } })
})
test('a paired result without the wrapper consumes the claim but books no skill', () => {
let state = applyActivity({ days: {} }, toolCall(at(0), 'c1', 'skill'))
state = applyActivity(state, skillResult(at(0), 'skill load failed', 'c1'))
assert.equal(state.days['2026-01-01'].skills, undefined)
assert.equal(state.days['2026-01-01'].toolCalls, 1)
assert.equal(state.skillCalls, undefined)
})
test('consuming one claim keeps the others pending', () => {
let state = applyActivity({ days: {} }, toolCall(at(0), 'c1', 'skill'))
state = applyActivity(state, toolCall(at(0), 'c2', 'skill'))
state = applyActivity(state, skillResult(at(0), '<skill_content name="tdd">…</skill_content>', 'c1'))
assert.deepEqual(state.skillCalls, ['c2'], 'the drained claim leaves its sibling armed')
assert.deepEqual(state.days['2026-01-01'].skills, { tdd: { n: 1, last: at(0) } })
})
test('the pairing list is bounded and duplicate arms are inert', () => {
let state: ReturnType<typeof applyActivity> = { days: {} }
state = applyActivity(state, toolCall(at(0), 'c1', 'skill'))
assert.ok(applyActivity(state, toolCall(at(0), 'c1', 'skill')) === state, 're-arming the same id is a no-op')
for (let i = 0; i < 120; i++) {
state = applyActivity(state, toolCall(at(0), `x${i}`, 'skill'))
}
assert.equal(state.skillCalls?.length, 100, 'the oldest pending claims drop first')
assert.equal(state.skillCalls?.includes('c1'), false)
// Non-skill calls and unreadable ids never arm a skill claim (the bash run still times itself).
for (const ev of [
toolCall(at(0), 'c2', 'bash'),
toolCall(at(0), 7, 'skill'),
toolCall(at(0), '', 'skill'),
toolCall(at(0), undefined, 'skill'),
{ type: 'tool/call', seq: 1, time: at(0), data: null } as never,
]) {
assert.deepEqual(applyActivity(state, ev).skillCalls, state.skillCalls, JSON.stringify(ev.data))
}
})
test('loads tally per name; the last instant never walks back on a disordered replay', () => {
let state = applyActivity({ days: {} }, skillInvocation(at(0), INVOCATION))
state = applyActivity(state, toolCall(at(0) + 60_000, 'c1', 'skill'))
state = applyActivity(state, skillResult(at(0) + 60_000, '<skill_content name="tdd">…</skill_content>', 'c1'))
state = applyActivity(state, skillInvocation(at(0), { kind: 'skill-invocation', name: 'tdd' }))
assert.deepEqual(state.days['2026-01-01'].skills, { tdd: { n: 3, last: at(0) + 60_000 } })
state = applyActivity(state, skillInvocation(at(1), INVOCATION))
assert.deepEqual(state.days['2026-01-02'].skills, { tdd: { n: 1, last: at(1) } }, 'distinct days key apart')
})
test('a developer/message carrier books its source too', () => {
const event = {
type: 'developer/message',
seq: 1,
time: at(0),
data: { message: { source: INVOCATION } },
} as never
const state = applyActivity({ days: {} }, event)
assert.deepEqual(state.days['2026-01-01'].skills, { tdd: { n: 1, last: at(0) } })
})
test('non-load messages and hostile payloads return the state unchanged', () => {
const state = applyActivity({ days: {} }, assistantMessage(at(0), { inputTokens: 1 }))
const cases: SessionEvent[] = [
skillInvocation(at(0), undefined), // no source
skillInvocation(at(0), null),
skillInvocation(at(0), 'skill-invocation'), // non-object source
skillInvocation(at(0), { kind: 'plugin', name: 'tdd' }), // another kind
skillInvocation(at(0), { kind: 'skill-invocation' }), // name absent
skillInvocation(at(0), { kind: 'skill-invocation', name: 7 }), // non-string name
skillInvocation(at(0), { kind: 'skill-invocation', name: '' }), // empty name
{ type: 'user/message', seq: 1, time: at(0), data: null } as never, // no data
{ type: 'user/message', seq: 1, time: Number.NaN, data: { source: INVOCATION } } as never, // unreadable time
skillResult(at(0), '<skill_content name="tdd">…</skill_content>'), // no call id at all
{ type: 'tool/result', seq: 1, time: at(0), data: null } as never, // no data
{ type: 'tool/result', seq: 1, time: at(0), data: { message: null } } as never, // no message
{ type: 'tool/result', seq: 1, time: at(0), data: { message: { toolCallId: 7 } } } as never, // unreadable ids
{ type: 'tool/result', seq: 1, time: at(0), data: { message: { toolCallId: '' } } } as never,
{ type: 'tool/result', seq: 1, time: at(0), data: { message: { source: { callId: 9 } } } } as never,
{ type: 'tool/result', seq: 1, time: at(0), data: { message: { source: 'x' } } } as never,
]
for (const event of cases) {
assert.ok(applyActivity(state, event) === state, JSON.stringify(event.data))
}
})
test('a settlement keeps the day’s skill table; the seed reset clears it', () => {
let state = applyActivity({ days: {} }, skillInvocation(at(0), INVOCATION))
state = applyActivity(state, assistantMessage(at(0), { inputTokens: 4 }))
assert.deepEqual(state.days['2026-01-01'], {
tokens: 4,
requests: 1,
skills: { tdd: { n: 1, last: at(0) } },
})
const cut = applyActivity(state, { type: 'session/end-seed', seq: 2, time: at(0), data: { inherited: true } } as never)
assert.deepEqual(cut, { days: {} })
})
test('a skill load on a priced day keeps the day’s tokens and fee', () => {
let state = applyActivity({ days: {} }, requestHeader('deepseek-v4', 'deepseek-official'))
state = applyActivity(state, assistantMessage(at(0), { inputTokens: 10, outputTokens: 5 }))
state = applyActivity(state, skillInvocation(at(0), INVOCATION))
const day = state.days['2026-01-01']
assert.equal(day.tokens, 15)
assert.equal(day.requests, 1)
assert.ok(day.cost !== undefined, 'the pricing record rides on')
assert.deepEqual(day.skills, { tdd: { n: 1, last: at(0) } })
})
test('the persisted previous state is never mutated (skill path copy-on-write)', () => {
const before = applyActivity({ days: {} }, skillInvocation(at(0), INVOCATION))
const after = applyActivity(before, skillInvocation(at(0), INVOCATION))
assert.deepEqual(before.days['2026-01-01'].skills, { tdd: { n: 1, last: at(0) } })
assert.deepEqual(after.days['2026-01-01'].skills, { tdd: { n: 2, last: at(0) } })
})
test('a day’s name table is capped: new names drop, booked names keep tallying', () => {
let state: ReturnType<typeof applyActivity> = { days: {} }
for (let i = 0; i < 100; i++) {
state = applyActivity(state, skillInvocation(at(0), { kind: 'skill-invocation', name: `skill-${i}` }))
}
const capped = applyActivity(state, skillInvocation(at(0), { kind: 'skill-invocation', name: 'skill-100' }))
assert.ok(capped === state, 'the 101st distinct name books nothing')
const again = applyActivity(state, skillInvocation(at(0), { kind: 'skill-invocation', name: 'skill-0' }))
assert.equal(again.days['2026-01-01'].skills?.['skill-0'].n, 2, 'a booked name still grows')
})
test('the wire view passes its schema with a skill table; the state schema round-trips it', () => {
const def = createContextActivityDefinition()
const state = applyActivity(def.init(), skillInvocation(at(0), INVOCATION))
const view = def.wire.view(state)
assert.equal(def.wire.viewSchema.safeParse(view).success, true)
assert.equal(def.stateSchema.safeParse(state).success, true)
assert.equal(def.stateSchema.safeParse({ days: { '2026-01-01': { tokens: 0, requests: 0, skills: { tdd: { n: 1.5, last: 0 } } } } }).success, false, 'a fractional tally')
assert.equal(def.stateSchema.safeParse({ days: { '2026-01-01': { tokens: 0, requests: 0, skills: { tdd: { n: 1 } } } } }).success, false, 'a missing last')
assert.equal(def.stateSchema.safeParse({ days: { '2026-01-01': { tokens: 0, requests: 0, skills: { tdd: { n: 1, last: Number.NaN } } } } }).success, false, 'a non-finite last')
assert.equal(def.stateSchema.safeParse({ days: {}, skillCalls: ['c1'] }).success, true, 'pending skill-call claims round-trip')
assert.equal(def.stateSchema.safeParse({ days: {}, skillCalls: [7] }).success, false, 'claims are strings')
})
})
/** A `request/header` event carrying the route in force (the fold's only model/provider source). */
function requestHeader(model: unknown, provider: unknown): SessionEvent {
return {
type: 'request/header',
seq: 1,
time: at(0),
data: { header: { config: { model, provider } } },
} as never
}
function stepStart(time: number): SessionEvent {
return { type: 'step/start', seq: 1, time, data: {} } as never
}
function stepEnd(time: number): SessionEvent {
return { type: 'step/end', seq: 1, time, data: {} } as never
}
/** Deterministic UTC instants: Thursday 02:00 (a peak window) and Saturday 12:00 (off-peak). */
const PEAK_UTC = Date.UTC(2026, 0, 1, 2)
const OFF_UTC = Date.UTC(2026, 0, 3, 12)
describe('applyActivity: the route in force', () => {
test('a header books later settlements under its (provider, model); the last header wins', () => {
let state = applyActivity({ days: {} }, requestHeader('deepseek-v4', 'deepseek-official'))
state = applyActivity(state, assistantMessage(PEAK_UTC, { inputTokens: 10, outputTokens: 5 }))
state = applyActivity(state, requestHeader('glm-5', 'zai-coding-cn'))
state = applyActivity(state, assistantMessage(PEAK_UTC, { inputTokens: 3 }))
const day = state.days[dayKeyOf(PEAK_UTC) ?? '']
assert.deepEqual(day?.cost, {
'deepseek-official': { 'deepseek-v4': { peak: { uncached: 10, cacheRead: 0, cacheWrite: 0, output: 5 } } },
'zai-coding-cn': { 'glm-5': { peak: { uncached: 3, cacheRead: 0, cacheWrite: 0, output: 0 } } },
})
})
test('a header without readable route fields returns the state unchanged (same reference)', () => {
const state = applyActivity({ days: {} }, assistantMessage(at(0), { inputTokens: 1 }))
for (const ev of [
{ type: 'request/header', seq: 1, time: at(0), data: null },
{ type: 'request/header', seq: 1, time: at(0), data: {} },
{ type: 'request/header', seq: 1, time: at(0), data: { header: null } },
{ type: 'request/header', seq: 1, time: at(0), data: { header: { config: 'x' } } },
{ type: 'request/header', seq: 1, time: at(0), data: { header: { config: { model: 7, provider: true } } } },
] as never as SessionEvent[]) {
assert.ok(applyActivity(state, ev) === state)
}
})
test('an identical header returns the same reference', () => {
const state = applyActivity({ days: {} }, requestHeader('deepseek-v4', 'deepseek-official'))
assert.ok(applyActivity(state, requestHeader('deepseek-v4', 'deepseek-official')) === state, 'no change, no copy')
})
test('a provider-only header tracks the provider without materializing a model field', () => {
let state = applyActivity({ days: {} }, requestHeader(undefined, 'deepseek-official'))
assert.ok(!('model' in state), 'the absent model stays absent (plain-JSON precondition)')
assert.equal(state.provider, 'deepseek-official')
// No model in force: the settlement still books no fee.
state = applyActivity(state, assistantMessage(at(0), { inputTokens: 2 }))
assert.deepEqual(state.days, { '2026-01-01': { tokens: 2, requests: 1 } })
})
test('a settlement with no route in force books its tokens and request but no fee', () => {
const state = applyActivity({ days: {} }, assistantMessage(at(0), { inputTokens: 4 }))
assert.deepEqual(state.days, { '2026-01-01': { tokens: 4, requests: 1 } }, 'no model, no fabricated fee')
})
test('a model without a provider books under the empty provider, at list price', () => {
let state = applyActivity({ days: {} }, requestHeader('deepseek-v4', undefined))
state = applyActivity(state, assistantMessage(OFF_UTC, { inputTokens: 10 }))
const day = state.days[dayKeyOf(OFF_UTC) ?? '']
assert.deepEqual(day?.cost, { '': { 'deepseek-v4': { peak: { uncached: 10, cacheRead: 0, cacheWrite: 0, output: 0 } } } },
'an unattributed provider is not DeepSeek, so its usage books under peak and is never doubled')
})
})
describe('applyActivity: the initiation stamp', () => {
test('a settlement books the day its step STARTED, across local midnight', () => {
const late = new Date(2026, 0, 1, 23, 30).getTime()
const early = new Date(2026, 0, 2, 0, 30).getTime()
let state = applyActivity({ days: {} }, requestHeader('deepseek-v4', 'deepseek-official'))
state = applyActivity(state, stepStart(late))
state = applyActivity(state, assistantMessage(early, { inputTokens: 6 }))
assert.deepEqual(Object.keys(state.days), ['2026-01-01'], 'the initiation day, not the settlement day')
assert.equal(state.days['2026-01-01'].tokens, 6)
})
test('step/end clears the stamp; the next settlement books its own day', () => {
let state = applyActivity({ days: {} }, requestHeader('deepseek-v4', 'deepseek-official'))
state = applyActivity(state, stepStart(at(0)))
state = applyActivity(state, stepEnd(at(0)))
assert.ok(!('stepStart' in state), 'the field is deleted, never materialized as undefined')
state = applyActivity(state, assistantMessage(at(1), { inputTokens: 2 }))
assert.deepEqual(Object.keys(state.days), ['2026-01-02'])
})
test('an unreadable settlement time still books over a valid stamp', () => {
let state = applyActivity({ days: {} }, requestHeader('deepseek-v4', 'deepseek-official'))
state = applyActivity(state, stepStart(at(0)))
state = applyActivity(state, assistantMessage(Number.NaN, { inputTokens: 9 }))
assert.deepEqual(state.days, {
'2026-01-01': {
tokens: 9,
requests: 1,
cost: { 'deepseek-official': { 'deepseek-v4': { [isBeijingPeak(at(0)) ? 'peak' : 'off']: { uncached: 9, cacheRead: 0, cacheWrite: 0, output: 0 } } } },
},
})
})
test('a non-finite step/start never arms the slot; a stale stamp stays armed like the timeline fold', () => {
let state: ReturnType<typeof applyActivity> = { days: {} }
state = applyActivity(state, stepStart(Number.NaN))
assert.ok(applyActivity(state, stepStart(Number.NaN)) === state)
state = applyActivity(state, requestHeader('deepseek-v4', 'deepseek-official'))
state = applyActivity(state, stepStart(at(0)))
state = applyActivity(state, stepStart(at(0)))
state = applyActivity(state, stepEnd(at(1)))
assert.ok(!('stepStart' in state), 'step/end without an armed slot is a no-op')
})
test('a step/end over an unarmed slot returns the state unchanged (same reference)', () => {
const state = applyActivity({ days: {} }, assistantMessage(at(0)))
assert.ok(applyActivity(state, stepEnd(at(0))) === state)
})
})
describe('applyActivity: turn, tool-run, and step-time attribution', () => {
const late = new Date(2026, 0, 1, 23, 30).getTime()
const early = new Date(2026, 0, 2, 0, 30).getTime()
test('a turn books once, on the initiation day of its first settlement', () => {
let state = applyActivity({ days: {} }, requestHeader('deepseek-v4', 'deepseek-official'))
state = applyActivity(state, stepStart(at(0)))
state = applyActivity(state, turnMessage(at(0), 7, { inputTokens: 1 }))
state = applyActivity(state, stepEnd(at(0)))
state = applyActivity(state, stepStart(at(1)))
state = applyActivity(state, turnMessage(at(1), 7, { inputTokens: 1 }))
state = applyActivity(state, stepEnd(at(1)))
assert.equal(state.days['2026-01-01'].turns, 1)
assert.equal(state.days['2026-01-02'].turns, undefined, 'the same turn never re-books on a later day')
state = applyActivity(state, stepStart(at(1)))
state = applyActivity(state, turnMessage(at(1), 8, { inputTokens: 1 }))
assert.equal(state.days['2026-01-02'].turns, 1, 'the next turn books its own day')
})
test('a tool run books its duration on the step-start day, across midnight', () => {
let state = applyActivity({ days: {} }, requestHeader('deepseek-v4', 'deepseek-official'))
state = applyActivity(state, stepStart(late))
state = applyActivity(state, toolCall(late, 'c1', 'bash'))
state = applyActivity(state, skillResult(early, 'done', 'c1'))
assert.equal(state.days['2026-01-01'].toolCalls, 1)
assert.equal(state.days['2026-01-01'].toolsMs, early - late)
assert.equal(state.days['2026-01-02'], undefined)
})
test('a step wall time books on the step-start day, across midnight', () => {
let state = applyActivity({ days: {} }, stepStart(late))
state = applyActivity(state, stepEnd(early))
assert.equal(state.days['2026-01-01'].wallMs, early - late)
assert.equal(state.days['2026-01-02'], undefined)
})
test('an unreadable or undatable tool start never arms', () => {
const state = applyActivity({ days: {} }, requestHeader('deepseek-v4', 'deepseek-official'))
assert.ok(applyActivity(state, toolCall(Number.NaN, 'c1', 'bash')) === state, 'a non-finite start')
assert.ok(applyActivity(state, toolCall(1e30, 'c2', 'bash')) === state, 'a start outside the day-key range')
const negative = applyActivity(state, stepStart(-2 * 86_400_000))
assert.equal(applyActivity(negative, toolCall(at(0), 'c3', 'bash')).toolStarts, undefined, 'a step stamp with no local day')
})
test('a later settlement keeps the day’s tool and wall tallies', () => {
const start = at(0)
let state = applyActivity({ days: {} }, requestHeader('deepseek-v4', 'deepseek-official'))
state = applyActivity(state, stepStart(start))
state = applyActivity(state, turnMessage(start, 1, { inputTokens: 1 }))
state = applyActivity(state, stepEnd(start + 100))
state = applyActivity(state, stepStart(start + 200))
state = applyActivity(state, toolCall(start + 200, 'c1', 'bash'))
state = applyActivity(state, skillResult(start + 300, 'done', 'c1'))
state = applyActivity(state, stepStart(start + 400))
state = applyActivity(state, turnMessage(start + 400, 2, { inputTokens: 1 }))
state = applyActivity(state, stepEnd(start + 500))
const day = state.days['2026-01-01']
assert.equal(day.turns, 2)
assert.equal(day.toolCalls, 1)
assert.equal(day.toolsMs, 100)
assert.equal(day.wallMs, 200, 'the first and last completed steps')
})
test('a tagged seed cut clears the turn cursor and pending tool starts', () => {
let state = applyActivity({ days: {} }, requestHeader('deepseek-v4', 'deepseek-official'))
state = applyActivity(state, stepStart(at(0)))
state = applyActivity(state, turnMessage(at(0), 1, { inputTokens: 1 }))
state = applyActivity(state, toolCall(at(0), 'c1', 'bash'))
assert.ok(state.lastTurn !== undefined && state.toolStarts !== undefined)
state = applyActivity(state, { type: 'session/end-seed', seq: 1, time: at(0), data: { inherited: true } } as never)
assert.deepEqual(state, { days: {} })
})
})
describe('applyActivity: the per-day pricing record', () => {
test('DeepSeek peak windows book the doubled list price; off-peak books the plain one', () => {
let state = applyActivity({ days: {} }, requestHeader('deepseek-v4', 'deepseek-official'))
state = applyActivity(state, assistantMessage(PEAK_UTC, { inputTokens: 100, cacheReadTokens: 10 }))
state = applyActivity(state, assistantMessage(OFF_UTC, { inputTokens: 100, cacheReadTokens: 10 }))
assert.deepEqual(state.days[dayKeyOf(PEAK_UTC) ?? '']?.cost, {
'deepseek-official': { 'deepseek-v4': { peak: { uncached: 100, cacheRead: 10, cacheWrite: 0, output: 0 } } },
})
assert.deepEqual(state.days[dayKeyOf(OFF_UTC) ?? '']?.cost, {
'deepseek-official': { 'deepseek-v4': { off: { uncached: 100, cacheRead: 10, cacheWrite: 0, output: 0 } } },
})
})
test('same-day settlements accumulate into the day’s record', () => {
let state = applyActivity({ days: {} }, requestHeader('deepseek-v4', 'deepseek-official'))
state = applyActivity(state, assistantMessage(at(0), { inputTokens: 1, outputTokens: 2 }))
state = applyActivity(state, assistantMessage(at(0), { inputTokens: 3 }))
assert.deepEqual(state.days['2026-01-01'].cost, {
'deepseek-official': { 'deepseek-v4': { [isBeijingPeak(at(0)) ? 'peak' : 'off']: { uncached: 4, cacheRead: 0, cacheWrite: 0, output: 2 } } },
})
})
test('an unmetered settlement keeps the day’s existing record; the ledger never loses it', () => {
let state = applyActivity({ days: {} }, requestHeader('deepseek-v4', 'deepseek-official'))
state = applyActivity(state, assistantMessage(at(0), { inputTokens: 1 }))
state = applyActivity(state, assistantMessage(at(0)))
assert.deepEqual(state.days['2026-01-01'], {
tokens: 1,
requests: 2,
cost: { 'deepseek-official': { 'deepseek-v4': { [isBeijingPeak(at(0)) ? 'peak' : 'off']: { uncached: 1, cacheRead: 0, cacheWrite: 0, output: 0 } } } },
})
})
test('the retention cap evicts priced days with their day', () => {
let state: ReturnType<typeof applyActivity> = { days: {} }
state = applyActivity(state, requestHeader('deepseek-v4', 'deepseek-official'))
for (let d = 0; d < 401; d++) {
state = applyActivity(state, assistantMessage(at(d), { inputTokens: 1 }))
}
const keys = Object.keys(state.days)
assert.equal(keys.length, 400)
assert.equal(keys.includes('2026-01-01'), false)
assert.ok(state.days['2027-02-05'].cost !== undefined, 'the kept suffix keeps its fee')
})
})
describe('contextActivity unit: the schemas over the pricing record', () => {
test('the state schema accepts the route and stamp fields; the wire passes its schema', () => {
const def = createContextActivityDefinition()
let state = applyActivity(def.init(), requestHeader('deepseek-v4', 'deepseek-official'))
state = applyActivity(state, stepStart(at(0)))
state = applyActivity(state, assistantMessage(at(0), { inputTokens: 1, outputTokens: 2 }))
assert.equal(def.stateSchema.safeParse(state).success, true)
assert.equal(def.stateSchema.safeParse({ days: {}, model: 'm', provider: 'p', stepStart: 1 }).success, true)
assert.equal(def.stateSchema.safeParse({ days: {}, lastTurn: 3, toolStarts: { c1: { start: 1, day: '2026-01-01' } } }).success, true)
assert.equal(def.stateSchema.safeParse({ days: {}, toolStarts: { c1: { start: -1, day: '2026-01-01' } } }).success, false)
assert.equal(def.stateSchema.safeParse({ days: { '2026-01-01': { tokens: 0, requests: 0, turns: 1, toolCalls: 2, toolsMs: 1.5, wallMs: 2 } } }).success, true)
assert.equal(def.stateSchema.safeParse({ days: { '2026-01-01': { tokens: 0, requests: 0, turns: 1.5 } } }).success, false)
assert.equal(contextActivitySchema.safeParse({ days: { '2026-01-01': { tokens: 0, requests: 0, turns: 1, toolCalls: 2, toolsMs: 1.5, wallMs: 2 } } }).success, true)
const view = def.wire.view(state)
assert.equal(def.wire.viewSchema.safeParse(view).success, true)
assert.equal(contextActivitySchema.safeParse(view).success, true)
assert.deepEqual(view.days, state.days, 'the view copies the entries whole')
})
test('the served view never aliases a day\'s nested cost or skill records', () => {
const def = createContextActivityDefinition()
let state = applyActivity(def.init(), requestHeader('deepseek-v4', 'deepseek-official'))
state = applyActivity(state, stepStart(at(0)))
state = applyActivity(state, assistantMessage(at(0), { inputTokens: 1, outputTokens: 2 }))
state = applyActivity(state, skillInvocation(at(0), INVOCATION))
const view = def.wire.view(state)
const day = Object.keys(state.days)[0]
const served = view.days[day]
const persisted = state.days[day]
assert.ok(persisted.cost !== undefined && persisted.skills !== undefined, 'the fixture carries both records')
// `cost` is four levels deep and `skills` two; a shallow day copy would leave both pointing at persisted state,
// so a mutating registry, cache writer, or wire payload would write straight into the fold's own record.
assert.notEqual(served.cost, persisted.cost)
assert.notEqual(served.cost?.['deepseek-official'], persisted.cost?.['deepseek-official'])
assert.notEqual(served.cost?.['deepseek-official']?.['deepseek-v4'], persisted.cost?.['deepseek-official']?.['deepseek-v4'])
assert.notEqual(served.cost?.['deepseek-official']?.['deepseek-v4']?.off, persisted.cost?.['deepseek-official']?.['deepseek-v4']?.off)
assert.notEqual(served.skills, persisted.skills)
assert.notEqual(served.skills?.tdd, persisted.skills?.tdd)
assert.deepEqual(served, persisted)
})
test('a malformed pricing record fails both schemas (strict: no drift)', () => {
const def = createContextActivityDefinition()
const bad = {
days: { '2026-01-01': { tokens: 1, requests: 1, cost: { deepseek: { 'deepseek-v4': { peak: { uncached: 'x' } } } } } },
}
assert.equal(def.stateSchema.safeParse(bad).success, false)
assert.equal(def.wire.viewSchema.safeParse(bad).success, false)
assert.equal(contextActivitySchema.safeParse(bad).success, false)
})
})