Merge master into codex/session-title

This commit is contained in:
Tianyi Cui
2026-07-21 22:59:41 +08:00
197 changed files with 3343 additions and 1227 deletions

View File

@@ -102,7 +102,7 @@ describe('SessionStore.fork', () => {
const { ctx, sessions } = await setup()
const reasons: TurnEndReason[] = [
{ kind: 'completed' },
{ kind: 'aborted', reason: 'cancelled by user' },
{ kind: 'aborted' },
{ kind: 'error', step: 1, message: 'model failed', code: 'MODEL' },
{ kind: 'disposed' },
{ kind: 'max-tokens' },

View File

@@ -90,6 +90,32 @@ describe('Session', () => {
expect(findLastMessageTurnEnd(session.events)).toBe(messageEnd)
})
it('round-trips the coarse aborted turn outcome', () => {
const session = new Session(SessionId('aborted'))
session.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('turn/end', { turn: 1, reason: { kind: 'aborted' } })
const replayed = new Session(SessionId('aborted-replay'), structuredClone(session.events))
expect(replayed.events).toEqual(session.events)
const turnEnd = replayed.events.findLast(event => event.type === 'turn/end')
expect(turnEnd?.type === 'turn/end' && turnEnd.data.reason).toEqual({ kind: 'aborted' })
})
it('rejects legacy reason-bearing aborted outcomes at the seed/load boundary', () => {
const legacy = [
{
type: 'turn/start', seq: 0, time: 1,
data: { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } },
},
{
type: 'turn/end', seq: 1, time: 2,
data: { turn: 1, reason: { kind: 'aborted', reason: 'legacy cancellation detail' } },
},
] as unknown as SessionEvent[]
expect(() => new Session(SessionId('legacy-aborted'), legacy))
.toThrow('seed turn/end at index 1 uses unsupported reason-bearing aborted format')
})
it('renders context and steering messages as plain user content', () => {
const session = new Session(SessionId('s2'))
session.append('context/message', {