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:
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest'
|
||||
import { Inbox } from '../src/inbox.ts'
|
||||
|
||||
function message(text: string) {
|
||||
return { content: [{ type: 'text' as const, text }], source: { kind: 'user' as const }, contexts: [] }
|
||||
return { content: [{ type: 'text' as const, text }], source: { kind: 'user' as const }, contexts: [], wakeup: true }
|
||||
}
|
||||
|
||||
function resolverPair() {
|
||||
@@ -25,6 +25,32 @@ describe('Inbox', () => {
|
||||
expect(inbox.dequeueQueued()).toBeUndefined()
|
||||
})
|
||||
|
||||
it('enqueue(msg, false) queues without waking a parked waiter', async () => {
|
||||
const inbox = new Inbox()
|
||||
let woke = false
|
||||
const waiter = inbox.waitForQueued(new Promise(() => {})).then(() => { woke = true })
|
||||
inbox.enqueue(message('quiet'), false)
|
||||
// The item is queued, but the parked waiter was not resolved by it.
|
||||
expect(inbox.hasQueued).toBe(true)
|
||||
await Promise.resolve()
|
||||
expect(woke).toBe(false)
|
||||
// A later waking enqueue resolves the same waiter.
|
||||
inbox.enqueue(message('loud'))
|
||||
await waiter
|
||||
expect(woke).toBe(true)
|
||||
})
|
||||
|
||||
it('pending() snapshots queued then steering without removing them', () => {
|
||||
const inbox = new Inbox()
|
||||
inbox.enqueue(message('q'))
|
||||
inbox.steer(message('s'))
|
||||
const pending = inbox.pending()
|
||||
expect(pending.map(p => p.steering)).toEqual([false, true])
|
||||
// Snapshot does not drain the FIFOs.
|
||||
expect(inbox.hasQueued).toBe(true)
|
||||
expect(inbox.hasSteering).toBe(true)
|
||||
})
|
||||
|
||||
it('pushes and drains steering messages separately from queued', () => {
|
||||
const inbox = new Inbox()
|
||||
inbox.steer(message('steer'))
|
||||
|
||||
Reference in New Issue
Block a user