fix(tui): route prompts by next-step capability

This commit is contained in:
_Kerman
2026-07-27 18:05:43 +08:00
parent a59ce0367c
commit f63d937496
21 changed files with 87 additions and 22 deletions

View File

@@ -53,7 +53,7 @@ export class ReactLoopAgent implements Agent {
/** Whether observers see a running interval; consecutive turns share it. */
private busy = false
/** Whether next-step input belongs to the current admission or open turn. */
private acceptingNextStep = false
acceptsNextStep = false
/** Abort owner for the current admission or turn. */
private abort: AbortController | undefined
/** Coalesced retry capability scoped to the active request-error waterfall. */
@@ -99,7 +99,7 @@ export class ReactLoopAgent implements Agent {
const { target, wakeup } = options
const id = AgentMessageId(randomUUID())
if (target === 'next-step' && !wakeup) {
if (this.acceptingNextStep) {
if (this.acceptsNextStep) {
this.outbox.push({ content, source })
return id
}
@@ -107,7 +107,7 @@ export class ReactLoopAgent implements Agent {
return id
}
const placement: InboxPlacement = target === 'next-step' && this.acceptingNextStep ? 'steering' : 'queued'
const placement: InboxPlacement = target === 'next-step' && this.acceptsNextStep ? 'steering' : 'queued'
const message: AgentMessage = {
id,
content,
@@ -215,7 +215,7 @@ export class ReactLoopAgent implements Agent {
const admission = new AbortController()
this.abort = admission
this.acceptingNextStep = true
this.acceptsNextStep = true
// Claimed admission is part of the running interval: it is cancellable
// activity, so observers (and their cancel routing) must see it.
if (!this.busy) {
@@ -257,7 +257,7 @@ export class ReactLoopAgent implements Agent {
// still owns the slot here and releasing it unconditionally is exact.
this.abort = undefined
if (admitted === undefined) {
this.acceptingNextStep = false
this.acceptsNextStep = false
// A synchronously aborted admission would otherwise publish idle
// inside send()'s own synchronous extent, before any post-send
// subscriber could observe the transition.
@@ -284,7 +284,7 @@ export class ReactLoopAgent implements Agent {
if (this.abort !== undefined) throw new Error(`agent "${this.id}" is already running`)
const controller = new AbortController()
this.abort = controller
this.acceptingNextStep = true
this.acceptsNextStep = true
if (!this.busy) {
this.busy = true
emitAgentEvent(this.loopCtx, this, 'agent/status', 'running')
@@ -390,7 +390,7 @@ export class ReactLoopAgent implements Agent {
// Every step-close happens before this point on both success and
// failure paths (step(), the request-failed branch, the catch), so the
// finally owes only the turn boundary.
this.acceptingNextStep = false
this.acceptsNextStep = false
try {
if (this.turnOpen) {
// Re-entrant turn/end listeners must route new input to a later turn.