Merge remote-tracking branch 'origin/master' into codex/enforce-tool-cancellation

# Conflicts:
#	docs/event-producer-consumer.md
#	examples/acp-agent/tests/snapshots/bash-spill/session.jsonl
#	examples/acp-agent/tests/snapshots/escalation-approved/session.jsonl
#	examples/acp-agent/tests/snapshots/escalation-rejected/session.jsonl
#	examples/acp-agent/tests/snapshots/fs-escalation-approved/session.jsonl
#	examples/acp-agent/tests/snapshots/hook-cc-pretool-ask/session.jsonl
#	packages/context/workspace-context/tests/workspace-context.spec.ts
#	packages/core/agent/src/index.ts
#	packages/support/invariants/tests/invariants.spec.ts
#	packages/ui/acp/src/index.ts
#	packages/ui/tui/tests/harness.ts
#	packages/ui/tui/tests/tui.spec.ts
This commit is contained in:
Tianyi Cui
2026-07-21 20:03:00 +08:00
623 changed files with 21217 additions and 3024 deletions

View File

@@ -743,10 +743,11 @@ describe('SessionStore', () => {
// may create an unrelated property with the old implementation's name,
// but cannot suppress the durable event feed.
expect(Reflect.set(session, 'onAppend', undefined)).toBe(true)
session.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('user/message', { content: [{ type: 'text', text: 'x' }], source: { kind: 'user' } }, { surfaceOp: 'append' })
expect(events).toHaveLength(1)
expect(events[0]![0]).toBe(session)
expect(events[0]![1].type).toBe('user/message')
expect(events).toHaveLength(2)
expect(events[1]![0]).toBe(session)
expect(events[1]![1].type).toBe('user/message')
expect(ctx.sessions.get(session.id)).toBe(session)
expect(ctx.sessions.list()).toEqual([session])
@@ -758,6 +759,7 @@ describe('SessionStore', () => {
const a = ctx.sessions.create(SessionId('fixed'))
expect(() => ctx.sessions.create(SessionId('fixed'))).toThrow('already exists')
a.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
a.append('user/message', { content: [{ type: 'text', text: 'q' }], source: { kind: 'user' } }, { surfaceOp: 'append' })
const forked = ctx.sessions.create(SessionId('fork'), { seed: [...a.events] })
expect(forked.deriveMessages()).toEqual(a.deriveMessages())
@@ -999,8 +1001,9 @@ describe('SessionStore', () => {
ctx.on('session/event', (_session, event) => void events.push(event))
const session = ctx.sessions.create(SessionId('fixed'))
expect(ctx.sessions.get(SessionId('fixed'))).toBe(session)
session.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('user/message', { content: [{ type: 'text', text: 'hi' }], source: { kind: 'user' } }, { surfaceOp: 'append' })
expect(events).toHaveLength(1)
expect(events.at(-1)?.type).toBe('user/message')
})
it('contains session/event observer failures after the append commit point', async () => {
@@ -1084,6 +1087,8 @@ describe('SessionStore', () => {
const ctx = new Context()
await ctx.plugin(SessionStore)
const session = ctx.sessions.create(SessionId('surface-dispatch-veto'))
session.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('step/start', { turn: 1, step: 1 })
session.append('user/message', {
content: [{ type: 'text', text: 'source' }],
source: { kind: 'user' },
@@ -1103,19 +1108,19 @@ describe('SessionStore', () => {
step: 1,
content: [{ type: 'text', text: 'replacement' }],
}, {
surfaceOp: { op: 'replace', start: 0, end: 0 },
sourceEventSeqs: [0],
surfaceOp: { op: 'replace', start: 2, end: 2 },
sourceEventSeqs: [2],
})).toThrow('reject surface candidate')
expect(session.events).toHaveLength(1)
expect(surface.nodes).toEqual([0])
expect(session.events).toHaveLength(3)
expect(surface.nodes).toEqual([2])
expect(surface.replaceGeneration).toBe(0)
session.append('user/message', {
content: [{ type: 'text', text: 'next' }],
source: { kind: 'user' },
}, { surfaceOp: 'append' })
expect(surface.nodes).toEqual([0, 1])
expect(surface.nodes).toEqual([2, 3])
expect(surface.replaceGeneration).toBe(0)
})