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

@@ -93,7 +93,7 @@ describe('TelemetryOtel wire', () => {
const { url, captures } = await mockCollector()
const { ctx, fiber } = await boot(url)
const session = ctx.sessions.create(SessionId('wire'), { meta: { cwd: '/tmp/w' } })
session.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('turn/start', { turn: 1 })
session.append('turn/end', { turn: 1, reason: { kind: 'error', step: 1, message: 'boom' } })
await fiber.dispose()
@@ -146,7 +146,7 @@ describe('TelemetryOtel wire', () => {
processor: { scheduledDelayMillis: 10 },
})
const session = ctx.sessions.create(SessionId('drain'), { meta: {} })
session.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('turn/start', { turn: 1 })
await arrived.promise
const disposal = fiber.dispose()
@@ -171,7 +171,7 @@ describe('TelemetryOtel wire', () => {
exporter: { url, compression: 'gzip' },
} as Config)
const session = ctx.sessions.create(SessionId('gzip'), { meta: {} })
session.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('turn/start', { turn: 1 })
await fiber.dispose()
expect(captures.length).toBeGreaterThan(0)
@@ -186,7 +186,7 @@ describe('TelemetryOtel wire', () => {
const { ctx, fiber } = await boot(url)
ctx.on('telemetry/record', (_record, next) => ({ ...next(), severity: 'warn' }))
const session = ctx.sessions.create(SessionId('warn'), { meta: {} })
session.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('turn/start', { turn: 1 })
// No flush(): the coordinator's optional-call forwarding no-ops, and the
// batch processor owns export cadence end to end (see the backend note).
expect('flush' in ctx.telemetry && ctx.telemetry.flush !== undefined).toBe(false)

View File

@@ -70,7 +70,7 @@ function liveSession(ctx: Context, id = `s-${Math.random().toString(36).slice(2)
}
function appendTurn(session: Session): void {
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: 'hello' }], source: { kind: 'user' },
}), { surfaceOp: 'append' })
@@ -108,7 +108,7 @@ describe('TelemetryCoordinator capture', () => {
it('maps outcome flags to severity, unknown types falling through as info', async () => {
const { ctx, backend } = await setup()
const session = liveSession(ctx)
session.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('turn/start', { turn: 1 })
session.append('tool/result', {
turn: 1, step: 1,
message: createToolResultMessage({
@@ -194,7 +194,7 @@ describe('TelemetryCoordinator adoption', () => {
const ctx = new Context()
await ctx.plugin(SessionStore)
const donor = ctx.sessions.create(SessionId('donor'), { meta: {} })
donor.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
donor.append('turn/start', { turn: 1 })
donor.append('assistant/chunk', { turn: 1, step: 1, chunk: { type: 'text-delta', index: 0, text: 'first' } })
const resumed = ctx.sessions.create(SessionId('resumed'), { seed: [...donor.events], meta: {} })
await ctx.plugin({
@@ -261,7 +261,7 @@ describe('TelemetryCoordinator adoption', () => {
const backend = new FakeBackend()
const { ctx, fiber } = await setup(backend)
const session = liveSession(ctx, 'hmr')
session.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
session.append('turn/start', { turn: 1 })
session.append('assistant/chunk', { turn: 1, step: 1, chunk: { type: 'text-delta', index: 0, text: 'first' } })
expect(backend.ledger()).toHaveLength(2)
@@ -408,7 +408,7 @@ describe('TelemetryCoordinator lifecycle and containment', () => {
const warn = vi.spyOn(ctx.logger, 'warn').mockImplementation(() => {})
const session = liveSession(ctx)
backend.emitError = new Error('backend broke')
expect(() => session.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })).not.toThrow()
expect(() => session.append('turn/start', { turn: 1 })).not.toThrow()
expect(warn).toHaveBeenCalled()
backend.emitError = undefined
session.append('turn/end', { turn: 1, reason: { kind: 'completed' } })