refactor(agent): unify sourced message delivery

This commit is contained in:
_Kerman
2026-07-24 22:38:50 +08:00
parent 009d113e0e
commit 992cf894af
197 changed files with 1890 additions and 2132 deletions

View File

@@ -447,8 +447,8 @@ export function createApiProxy(ctx: Context, defaults: ApiProxyDefaults): ApiPro
// The rpcId rides MessageSource into user/message (merge declaration in api/sessions.ts; provisional correlation).
const source: MessageSource = { kind: 'user', rpcId: request.rpcId }
try {
if (mode === 'steer') agent.steer(content, { source })
else agent.followup(content, { source })
if (mode === 'steer') agent.steer({ content, source })
else agent.followup({ content, source })
} catch (error: unknown) {
// A synchronous throw from send/steer means disposed or invalid input; surface as agent-busy with the reason attached.
return err(request, { code: 'agent-busy', message: 'prompt rejected', details: { reason: String(error) } })

View File

@@ -386,7 +386,7 @@ describe('sessions.prompt / cancel', () => {
const { api, ctx } = running
const { sessionId } = expectOk(await api.sessions.create(request({})))
const agent = ctx.agents.get(sessionId) as Agent
agent.followup([{ type: 'text', text: 'run forever' }])
agent.followup({ content: [{ type: 'text', text: 'run forever' }], source: { kind: 'user' } })
expectOk(await api.sessions.cancel(request({ sessionId })))
const missing = await api.sessions.cancel(request({ sessionId: 'session-none' as SessionId }))
@@ -405,7 +405,7 @@ describe('sessions.history', () => {
const { sessionId } = expectOk(await first.api.sessions.create(request({})))
const agent = first.ctx.agents.get(sessionId) as Agent
const idle = waitForIdle(first.ctx, agent)
agent.followup([{ type: 'text', text: 'save me' }])
agent.followup({ content: [{ type: 'text', text: 'save me' }], source: { kind: 'user' } })
await idle
const titleEvent = await appendTitle(first.ctx, agent, 'Persisted title')
await first.dispose()
@@ -454,7 +454,7 @@ describe('sessions.history', () => {
const agent = ctx.agents.get(sessionId) as Agent
for (const text of ['q1', 'q2', 'q3']) {
const idle = waitForIdle(ctx, agent)
agent.followup([{ type: 'text', text }])
agent.followup({ content: [{ type: 'text', text }], source: { kind: 'user' } })
await idle
}
@@ -528,7 +528,7 @@ describe('events streams', () => {
const agent = ctx.agents.get(sessionId) as Agent
const idle = waitForIdle(ctx, agent)
agent.followup([{ type: 'text', text: 'go' }])
agent.followup({ content: [{ type: 'text', text: 'go' }], source: { kind: 'user' } })
await idle
const live = await stream.next()
expect((live.value as RpcRequest<MuxFrame>).payload.type).toBe('session/event')
@@ -591,7 +591,7 @@ describe('events streams', () => {
const agent = ctx.agents.get(sessionId) as Agent
const idle = waitForIdle(ctx, agent)
agent.followup([{ type: 'text', text: 'run' }])
agent.followup({ content: [{ type: 'text', text: 'run' }], source: { kind: 'user' } })
await idle
const runningFrame = await stream.next()
expect((runningFrame.value as RpcRequest<HostFrame>).payload).toMatchObject({ type: 'host/session-status', running: true })