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

@@ -45,12 +45,9 @@ export function extractSessionEventText(event: SessionEvent): string {
function turnEndText(reason: SessionEvent<'turn/end'>['data']['reason']): string {
switch (reason.kind) {
case 'error':
return 'failure' in reason
? joinText(['error', reason.failure.message, reason.failure.code])
: joinText(['error', reason.message, reason.code ?? ''])
return joinText(['error', reason.error instanceof Error ? reason.error.message : String(reason.error)])
case 'aborted':
return 'aborted'
case 'disposed':
case 'max-tokens':
case 'interrupted':
return reason.kind

View File

@@ -125,7 +125,7 @@ describe('session-query semantic extraction', () => {
expect(extractSessionEventText({ type: 'turn/end', seq: 0, time: 1, data: { turn: 1, reason } })).toBe(text)
}
const structural: SessionEvent[] = [
{ type: 'turn/start', seq: 0, time: 1, data: { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } } },
{ type: 'turn/start', seq: 0, time: 1, data: { turn: 1 } },
{ type: 'step/start', seq: 1, time: 1, data: { turn: 1, step: 1 } },
{ type: 'step/end', seq: 2, time: 1, data: { turn: 1, step: 1 } },
{ type: 'assistant/chunk', seq: 3, time: 1, data: { turn: 1, step: 1, chunk: { type: 'text-delta', index: 0, text: 'raw' } } },

View File

@@ -893,7 +893,7 @@ describe('session-query exact reads', () => {
it('classifies current, shadowed, and raw-log-only events through foldSurface', async () => {
const ctx = await liveContext()
const session = ctx.sessions.create(SessionId('surface'))
session.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('turn/start', { turn: 1 })
session.append('step/start', { turn: 1, step: 1 })
const first = session.append(
'user/message',
@@ -1008,7 +1008,7 @@ describe('session-query exact reads', () => {
it('returns a bounded detached raw-event window and validates the request', async () => {
const ctx = await liveContext({ readWindowMax: 1 })
const session = ctx.sessions.create(SessionId('window'), { meta: { cwd: '/work' } })
session.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('turn/start', { turn: 1 })
for (const text of ['one', 'two', 'three']) {
session.append(
'user/message',
@@ -1050,7 +1050,7 @@ describe('session-query exact reads', () => {
])
const ctx = await liveContext()
const live = ctx.sessions.create(shared.id, { meta: { createdAt: 3, cwd: '/same' } })
live.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
live.append('turn/start', { turn: 1 })
live.append(
'user/message',
createUserMessage({
@@ -1090,7 +1090,7 @@ describe('session-query exact reads', () => {
TestPersistence.reset()
const ctx = await liveContext()
const live = ctx.sessions.create(SessionId('live'))
live.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
live.append('turn/start', { turn: 1 })
live.append(
'user/message',
createUserMessage({

View File

@@ -106,7 +106,7 @@ function expectCode(code: SessionQueryErrorCode): Error {
}
function appendTraceEvents(session: Session): void {
session.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('turn/start', { turn: 1 })
session.append('step/start', { turn: 1, step: 1 })
session.append('assistant/chunk', {
turn: 1,
@@ -348,7 +348,7 @@ describe('session event tracing', () => {
expect([TracePersistence.listCalls, TracePersistence.inspectCalls]).toEqual([1, 1])
const live = ctx.sessions.create(durable.id, { meta: { createdAt: 1, cwd: '/same' } })
live.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
live.append('turn/start', { turn: 1 })
live.append(
'user/message',
createUserMessage({
@@ -412,7 +412,7 @@ describe('session event tracing', () => {
it.each([
['non-surface sources', [
{ type: 'turn/start', seq: 0, time: 1, data: { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } }, sourceEventSeqs: [0] },
{ type: 'turn/start', seq: 0, time: 1, data: { turn: 1 }, sourceEventSeqs: [0] },
]],
['invalid source array', [
{ ...appendEvent(0), sourceEventSeqs: 'invalid' },
@@ -461,7 +461,7 @@ describe('session event tracing', () => {
type: 'turn/start',
seq: 0,
time: 1,
data: { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } },
data: { turn: 1 },
surfaceOp: 'append',
}] as unknown as SessionEvent[]
TracePersistence.reset([{ meta: durable, events }])

View File

@@ -64,7 +64,7 @@ describe('tool-session-query with the real SQLite provider', () => {
const caller = ctx.sessions.create(SessionId('caller'), {
meta: { createdAt: 10, cwd: '/work' },
})
caller.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
caller.append('turn/start', { turn: 1 })
caller.append(
'user/message',
createUserMessage({

View File

@@ -64,7 +64,7 @@ function createSession(
}
function openStep(session: Session, text = 'prior needle'): void {
session.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('turn/start', { turn: 1 })
session.append(
'user/message',
createUserMessage({