fix(session): validate surface replacement endpoints

This commit is contained in:
Tianyi Cui
2026-09-03 15:26:35 +08:00
parent 618a7a46e8
commit b5f1539733
3 changed files with 20 additions and 2 deletions
@@ -191,7 +191,7 @@ function assertSurfaceMetadata(record: Record<string, SessionFormatJsonValue>, s
if (replacement['op'] !== 'replace') throw new SessionFormatError(`${type} ${seq} surfaceOp must replace`)
const start = sessionFormatCount(replacement['start'], `${type} ${seq} surface start`)
const end = sessionFormatCount(replacement['end'], `${type} ${seq} surface end`)
if (start > end || end >= seq) throw new SessionFormatError(`${type} ${seq} has an invalid surface replacement`)
if (start >= seq || end >= seq) throw new SessionFormatError(`${type} ${seq} has an invalid surface replacement`)
}
/**
@@ -112,6 +112,24 @@ describe('released v1 whole-artifact relationships', () => {
expect(decode(rows).events).toEqual(rows)
})
it('accepts a surface-position range whose sequence values descend', () => {
const rows = [
{ type: 'user/message', seq: 0, time: 1, data: user('zero'), surfaceOp: 'append' },
{ type: 'user/message', seq: 1, time: 2, data: user('one'), surfaceOp: 'append' },
{ type: 'user/message', seq: 2, time: 3, data: user('two'), surfaceOp: 'append' },
{
type: 'user/message', seq: 3, time: 4, data: user('first replacement'),
sourceEventSeqs: [0, 1], surfaceOp: { op: 'replace', start: 0, end: 1 },
},
{
type: 'user/message', seq: 4, time: 5, data: user('second replacement'),
sourceEventSeqs: [3, 2], surfaceOp: { op: 'replace', start: 3, end: 2 },
},
]
expect(decode(rows).events).toEqual(rows)
})
it('keeps the latest request provider across later steps and turns', () => {
const rows = [
{ type: 'turn/start', seq: 0, time: 1, data: { turn: 1 } },
@@ -524,7 +524,7 @@ describe('released event and payload inventory', () => {
{ sourceEventSeqs: [], surfaceOp: 'append' },
{ surfaceOp: null },
{ surfaceOp: { op: 'append', start: 0, end: 1 } },
{ surfaceOp: { op: 'replace', start: 2, end: 1 } },
{ surfaceOp: { op: 'replace', start: 3, end: 1 } },
{ surfaceOp: { op: 'replace', start: 1, end: 3 } },
]
for (const metadata of surfaceVariants) {