refactor(agent-loop): simplify message machine

This commit is contained in:
_Kerman
2026-07-30 13:49:57 +08:00
parent d554ae3019
commit f2e20c1ef0
212 changed files with 1326 additions and 2382 deletions

View File

@@ -46,10 +46,10 @@ function reading(
function preparing(turn: number, step: number): Session {
const session = new Session(SessionId(`time-invariant-${turn}-${step}`))
for (let priorTurn = 1; priorTurn < turn; priorTurn += 1) {
session.append('turn/start', { turn: priorTurn, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('turn/start', { turn: priorTurn })
session.append('turn/end', { turn: priorTurn, reason: { kind: 'completed' } })
}
session.append('turn/start', { turn, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('turn/start', { turn })
session.append('user/message', createUserMessage({
content: [{ type: 'text', text: `turn ${turn}` }],
source: { kind: 'user' },
@@ -87,7 +87,7 @@ describe('time-context invariants', () => {
const ctx = new Context()
await ctx.plugin(SessionStore)
const session = ctx.sessions.create(SessionId('time-invariant-late-valid'))
session.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('turn/start', { turn: 1 })
session.append('user/message', createUserMessage({
content: [{ type: 'text', text: 'prepare' }],
source: { kind: 'user' },
@@ -103,7 +103,7 @@ describe('time-context invariants', () => {
const ctx = new Context()
await ctx.plugin(SessionStore)
const session = ctx.sessions.create(SessionId('time-invariant-late-invalid'))
session.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('turn/start', { turn: 1 })
session.append('user/message', createUserMessage({
content: [{ type: 'text', text: 'prepare' }],
source: { kind: 'user' },
@@ -125,7 +125,7 @@ describe('time-context invariants', () => {
it('rejects a reading after cancellation closes the turn', async () => {
const ctx = await setup()
const session = preparing(1, 2)
session.append('turn/end', { turn: 1, reason: { kind: 'aborted' } })
session.append('turn/end', { turn: 1, reason: { kind: 'aborted', reason: { kind: 'user' } } })
expect(() => { ctx.emit('session/event', session, event(reading('1', '2', 'step context'))) })
.toThrow(/inside an open turn/)
})
@@ -180,7 +180,7 @@ describe('time-context invariants', () => {
expect(() => { ctx.emit('session/event', preparing(1, 1), user) }).not.toThrow()
expect(() => {
ctx.emit('session/event', preparing(1, 1), {
type: 'turn/start', seq: 0, time: 0, data: { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } },
type: 'turn/start', seq: 0, time: 0, data: { turn: 1 },
})
ctx.emit('tools/change')
}).not.toThrow()

View File

@@ -48,14 +48,13 @@ function sessionAgent(session: Session, id = 'agent'): Agent {
inject(input) {
session.append('user/message', input, { surfaceOp: 'append' })
},
send: () => {},
cancel() {},
whenIdle: () => Promise.resolve(),
}
}
function openMessageTurn(session: Session, turn: number): void {
session.append('turn/start', { turn, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('turn/start', { turn })
session.append('user/message', createUserMessage({
content: [{ type: 'text', text: `turn ${turn}` }],
source: { kind: 'user' },
@@ -159,7 +158,7 @@ describe('durable step context', () => {
it('reports an unavailable first-step baseline when no model-visible message precedes it', async () => {
const { ctx } = await mount()
const session = new Session(SessionId('unavailable'))
session.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('turn/start', { turn: 1 })
await fire(ctx, sessionAgent(session), 1, 1)

View File

@@ -183,7 +183,6 @@ function stubAgent(cwd?: string, seed: SessionEvent[] = []): Agent {
inject(input) {
session.append('user/message', input, { surfaceOp: 'append' })
},
send: () => {},
cancel() {},
whenIdle: () => Promise.resolve(),
}