fix: projection error
This commit is contained in:
@@ -180,7 +180,7 @@ describe('contextBreakdown session projection', () => {
|
||||
expect(agree()).toBeLessThan(grown)
|
||||
})
|
||||
|
||||
it('fails loud on a replacement without an adjacent matching shadow price', () => {
|
||||
it('folds a replacement without a claim at zero and fails on a mismatched claim', () => {
|
||||
const definition = contextBreakdownProjectionDefinition
|
||||
const replace = (start: number, end: number): SessionEvent => ({
|
||||
type: 'user/message',
|
||||
@@ -206,15 +206,17 @@ describe('contextBreakdown session projection', () => {
|
||||
let state = definition.init()
|
||||
state = definition.apply(state, append(1))
|
||||
state = definition.apply(state, append(3))
|
||||
// No metering event at all.
|
||||
expect(() => definition.apply(state, replace(1, 3))).toThrow('no adjacent shadow price')
|
||||
// A claim for a different range does not price this replacement.
|
||||
// No metering event: the replacement contributes zero instead of throwing.
|
||||
expect(definition.view(definition.apply(state, replace(1, 3))).messageTokens)
|
||||
.toBe(definition.view(state).messageTokens)
|
||||
// An adjacent claim for another range contradicts the replacement.
|
||||
const mismatched = definition.apply(state, meter(1, 1, 8))
|
||||
expect(() => definition.apply(mismatched, replace(1, 3))).toThrow('no adjacent shadow price')
|
||||
// A claim expires after one intervening event instead of lingering.
|
||||
// A claim expires after one intervening event, so replacement delta is zero.
|
||||
let expired = definition.apply(state, meter(1, 3, 8))
|
||||
expired = definition.apply(expired, { type: 'todo/write', seq: 9, time: 0, data: { todos: [] } } as unknown as SessionEvent)
|
||||
expect(() => definition.apply(expired, replace(1, 3))).toThrow('no adjacent shadow price')
|
||||
expect(definition.view(definition.apply(expired, replace(1, 3))).messageTokens)
|
||||
.toBe(definition.view(state).messageTokens)
|
||||
// The armed claim prices exactly the next event's matching replacement.
|
||||
const armed = definition.apply(state, meter(1, 3, 8))
|
||||
expect(definition.view(definition.apply(armed, replace(1, 3))).messageTokens)
|
||||
|
||||
@@ -419,6 +419,25 @@ describe('contextPressure session projection', () => {
|
||||
expect(compacted.projectedTokens).toBeLessThan(beforeCompaction!)
|
||||
})
|
||||
|
||||
it('folds a replacement without a claim at zero', async () => {
|
||||
const { ctx, session } = await harness()
|
||||
const question = appendUser(session, 'a question from an unmetered log')
|
||||
startStep(session, 1, 1)
|
||||
usageChunk(session, { inputTokens: 100, outputTokens: 1 }, 1, 1)
|
||||
session.append('step/end', { turn: 1, step: 1 })
|
||||
const before = pressure(ctx, session)
|
||||
|
||||
session.append('user/message', createUserMessage({
|
||||
content: [{ type: 'text', text: 'summary without a preceding claim' }],
|
||||
source: { kind: 'plugin', plugin: 'test' },
|
||||
}), {
|
||||
surfaceOp: { op: 'replace', start: question, end: question },
|
||||
sourceEventSeqs: [question],
|
||||
})
|
||||
|
||||
expect(pressure(ctx, session)).toEqual(before)
|
||||
})
|
||||
|
||||
it('clamps a projection that heuristic error drove below zero', async () => {
|
||||
const { ctx, session } = await harness()
|
||||
recordContext(session, 'large', 128_000)
|
||||
|
||||
Reference in New Issue
Block a user