refactor(agent-loop): drop the steering/message session event

Steer, inject, and followup now land as durable user/message events on the
session surface; the steering/message event type and its ConversationNode
kind are removed from the client projection. Update tests, docs, generated
catalogs, and agent notes to match, and align the steering e2e fixture and
prompt inventory assertions with the durable user/message landing.
This commit is contained in:
_Kerman
2026-08-03 16:04:26 +08:00
parent f4a2e0d10a
commit cb2f01f48c
86 files changed
+243 -458

No files matched your search

@@ -576,8 +576,8 @@ describe('Agent.cancel()', () => {
expect(turnStarts.length).toBe(1) // only the original (cancelled) turn
// The steering text was dropped — it never reached the log.
const flat = agent.session.events
.filter(e => e.type === 'steering/message')
.flatMap(e => e.type === 'steering/message' ? e.data.message.content : [])
.filter(e => e.type === 'user/message')
.flatMap(e => e.data.content)
.flatMap(b => b.type === 'text' ? [b.text] : [])
expect(flat).not.toContain('steer text')
})
@@ -448,7 +448,7 @@ describe('adapter registration, routing, and accepted-input ownership', () => {
expect(agent.session.deriveMessages().at(-1)?.content).toEqual([{ type: 'text', text: 'routed' }])
})
it('durable inbox splices carry exact messages and steering/message preserves its source', async () => {
it('durable inbox splices carry exact messages and the claimed steer preserves its source', async () => {
const adapter = new MockAdapter([toolCallResponse('c1', 'noop', {}), textResponse('done')])
const ctx = await harness(adapter)
const agent = ctx.agentLoop.create(SessionId('a1'), { provider: 'mock', model: 'mock' })
@@ -293,7 +293,7 @@ describe('agent/pre-step', () => {
expect(agent.inbox.hasPending).toBe(false)
const staged = events(agent).filter(event =>
event.type === 'turn/start' || event.type === 'user/message' || event.type === 'steering/message')
event.type === 'turn/start' || event.type === 'user/message')
expect(staged.map(event => event.type)).toEqual([
'turn/start',
'user/message',
@@ -350,7 +350,7 @@ describe('agent/pre-step', () => {
await waitForIdle(ctx, agent)
const staged = events(agent).filter(event =>
event.type === 'user/message' || event.type === 'steering/message')
event.type === 'user/message')
expect(staged.map(event => event.type)).toEqual([
'user/message',
'user/message',
@@ -544,7 +544,6 @@ describe('agent loop', () => {
[{ type: 'text', text: 'first idle steer' }],
[{ type: 'text', text: 'second idle steer' }],
])
expect(agent.session.events.filter(event => event.type === 'steering/message')).toEqual([])
expect(adapter.requests).toHaveLength(1)
expect(JSON.stringify(adapter.requests[0]?.messages)).toContain('first idle steer')
expect(JSON.stringify(adapter.requests[0]?.messages)).toContain('second idle steer')
@@ -574,7 +573,6 @@ describe('agent loop', () => {
expect(adapter.requests).toHaveLength(1)
expect(agent.session.events.filter(event => event.type === 'turn/start')).toHaveLength(1)
expect(agent.session.events.some(event => event.type === 'steering/message')).toBe(false)
expect(JSON.stringify(adapter.requests[0]?.messages)).toContain('pending steering')
})