refactor(agent): trim obsolete loop surfaces

This commit is contained in:
_Kerman
2026-07-24 21:58:07 +08:00
parent 194b18a32f
commit 009d113e0e
40 changed files with 252 additions and 288 deletions

View File

@@ -23,6 +23,7 @@ interface FakeAgent extends Agent {
sent: ContentBlock[][]
sentOptions: (SendOptions | AliasSendOptions | undefined)[]
steered: ContentBlock[][]
steeredIds: AgentMessageId[]
steeredOptions: (AliasSendOptions | undefined)[]
injected: ContentBlock[][]
injectedOptions: (AliasSendOptions | undefined)[]
@@ -161,6 +162,7 @@ export async function createTuiTestHarness<TerminalType extends Terminal, Exit e
options.beforeMount?.(session)
const sent: ContentBlock[][] = []
const steered: ContentBlock[][] = []
const steeredIds: AgentMessageId[] = []
const sentOptions: (SendOptions | AliasSendOptions | undefined)[] = []
const steeredOptions: (AliasSendOptions | undefined)[] = []
const injected: ContentBlock[][] = []
@@ -175,6 +177,7 @@ export async function createTuiTestHarness<TerminalType extends Terminal, Exit e
sent,
sentOptions,
steered,
steeredIds,
steeredOptions,
injected,
injectedOptions,
@@ -192,7 +195,9 @@ export async function createTuiTestHarness<TerminalType extends Terminal, Exit e
steer(content, options) {
steered.push(content)
steeredOptions.push(options)
return AgentMessageId('stub')
const id = AgentMessageId(`steering-${steeredIds.length + 1}`)
steeredIds.push(id)
return id
},
inject(content, options) {
injected.push(content)

View File

@@ -1363,6 +1363,14 @@ describe('pi-tui chat lifecycle and transcript', () => {
result.terminal.send('\r')
}
const drainSteering = (text: string): void => {
const id = result.agent.steeredIds.shift()
if (id !== undefined) {
result.ctx.emit('agent/inbox/dequeue', result.agent, {
id,
content: [{ type: 'text', text }],
source: { kind: 'user' },
})
}
result.session.append('steering/message', { turn: 1, content: [{ type: 'text', text }], source: { kind: 'user' } }, { surfaceOp: 'append' })
}
@@ -1401,9 +1409,8 @@ describe('pi-tui chat lifecycle and transcript', () => {
await tick()
expect(result.terminal.output).toContain('1 queued')
// A steering/message whose source matches no pending badge entry (here a
// plugin source with no tracked enqueue) pops nothing, so it cannot consume
// a pending user slot even when it drains first.
// A steering/message has no inbox identity and therefore cannot consume a
// pending slot by itself.
result.terminal.output = ''
result.session.append('steering/message', {
turn: 1,