feat(agent): unify send(target × wakeup), coalesce context/message into user/message

Replace send/steer/inject with one Agent.send primitive over the
(target × wakeup) matrix; followup/steer/inject become fixed-preset
alias methods on the now-abstract Agent class. Coalesce context/message
into user/message (injected context is a non-user source). Replace
agent/queued with agent/inbox/enqueue/dequeue/discard, add cancel
keepInbox, and add a FIFO-conservation invariant.
This commit is contained in:
Turtle
2026-07-23 19:15:45 +08:00
parent 7c0c516f60
commit 44fd93fd06
117 changed files with 1249 additions and 728 deletions

View File

@@ -68,7 +68,7 @@ describe('startInProcessRun', () => {
turn,
trigger: { kind: 'injection', source: { kind: 'plugin', plugin: 'late-metadata' } },
})
session.append('context/message', {
session.append('user/message', {
content: [{ type: 'text', text: 'late metadata' }],
source: { kind: 'plugin', plugin: 'late-metadata' },
}, { surfaceOp: 'append' })

View File

@@ -187,10 +187,10 @@ describe('dsh-subagent-spawn', () => {
expect(published).toEqual([])
})
it('a cancel from agent/queued maps a no-turn child log to aborted', async () => {
it('a cancel from agent/inbox/enqueue maps a no-turn child log to aborted', async () => {
const { ctx, parent } = await setup([])
const controller = new AbortController()
ctx.on('agent/queued', () => { controller.abort('queued-window') })
ctx.on('agent/inbox/enqueue', () => { controller.abort('queued-window') })
const run = await start(ctx, 'spawn', { prompt: [{ type: 'text', text: 'p' }], parent, signal: controller.signal })
const result = await run.result
expect(result).toMatchObject({ stopReason: 'aborted', output: [] })