Team events: a change inside the pace window is said at its end, so the last state always goes out; the main agent waiting for a slot is the waiting_for_model phase
ci / check (push) Waiting to run
ci / check (push) Waiting to run
Found by the full suite: the link's tree could miss a subagent's last change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2 files changed
+15
-3
No files matched your search
+5
-1
@@ -752,7 +752,11 @@ export function createApp(o: AppOptions): App {
|
|||||||
teamRt.memberDone(member.name, "", `error — ${(e as Error).message}`, [])
|
teamRt.memberDone(member.name, "", `error — ${(e as Error).message}`, [])
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
lead: { note: (text) => engine.note(text), wake: (text) => wake(text, shownLine(text)) },
|
lead: {
|
||||||
|
note: (text) => engine.note(text),
|
||||||
|
wake: (text) => wake(text, shownLine(text)),
|
||||||
|
waiting: (model) => engine.progress.set({ phase: "waiting_for_model", model: engine.model.spec.name ?? model, reason: "slots" }),
|
||||||
|
},
|
||||||
tools: () => tools,
|
tools: () => tools,
|
||||||
resolve: (agent, model) => {
|
resolve: (agent, model) => {
|
||||||
if (!agentList.some((a) => a.name === agent)) return { error: `There is no agent "${agent}". The agents are: ${agentList.map((a) => a.name).join(", ")}.` }
|
if (!agentList.some((a) => a.name === agent)) return { error: `There is no agent "${agent}". The agents are: ${agentList.map((a) => a.name).join(", ")}.` }
|
||||||
|
|||||||
+10
-2
@@ -29,7 +29,7 @@ export interface RuntimeOptions {
|
|||||||
/** Make a member's engine (attached here with `attach`) and start its first turn with `text`. */
|
/** Make a member's engine (attached here with `attach`) and start its first turn with `text`. */
|
||||||
spawnMember(member: TeamAgent, text: string): void
|
spawnMember(member: TeamAgent, text: string): void
|
||||||
/** The lead: a message at its next step (`note`), or — idle — a turn of its own (`wake`). */
|
/** The lead: a message at its next step (`note`), or — idle — a turn of its own (`wake`). */
|
||||||
lead: { note(text: string): void; wake(text: string): void }
|
lead: { note(text: string): void; wake(text: string): void; /** Spec 3.4.0: its progress while it waits for a slot. */ waiting?(model: string): void }
|
||||||
/** An unknown agent or model, answered as task answers it; undefined when both are known. The
|
/** An unknown agent or model, answered as task answers it; undefined when both are known. The
|
||||||
* model's ref as the session knows it. */
|
* model's ref as the session knows it. */
|
||||||
resolve?(agent: string, model: string | undefined): { error: string } | { model: string }
|
resolve?(agent: string, model: string | undefined): { error: string } | { model: string }
|
||||||
@@ -74,17 +74,24 @@ export class TeamRuntime {
|
|||||||
|
|
||||||
/** Said on the lead's bus as `team`, at most four times a second (acp.md `team` event). */
|
/** Said on the lead's bus as `team`, at most four times a second (acp.md `team` event). */
|
||||||
private changed() {
|
private changed() {
|
||||||
if (this.pace) return
|
// A change inside the pace window is said once at its end, so the last state always goes out.
|
||||||
|
if (this.pace) return void (this.trailing = true)
|
||||||
this.o.bus.emit({ type: "team" })
|
this.o.bus.emit({ type: "team" })
|
||||||
this.pace = setTimeout(() => {
|
this.pace = setTimeout(() => {
|
||||||
this.pace = undefined
|
this.pace = undefined
|
||||||
|
if (this.trailing) {
|
||||||
|
this.trailing = false
|
||||||
|
this.changed()
|
||||||
|
}
|
||||||
}, 1000 / 4)
|
}, 1000 / 4)
|
||||||
}
|
}
|
||||||
|
private trailing = false
|
||||||
|
|
||||||
/** Something changed that a reader must see now (the tools' answers, tests): said at once. */
|
/** Something changed that a reader must see now (the tools' answers, tests): said at once. */
|
||||||
private changedNow() {
|
private changedNow() {
|
||||||
if (this.pace) clearTimeout(this.pace)
|
if (this.pace) clearTimeout(this.pace)
|
||||||
this.pace = undefined
|
this.pace = undefined
|
||||||
|
this.trailing = false
|
||||||
this.o.bus.emit({ type: "team" })
|
this.o.bus.emit({ type: "team" })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,6 +213,7 @@ export class TeamRuntime {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
this.o.bus.emit({ type: "notice", message: `waiting for a free slot: the model serves ${parallelFrom(this.team.capacityOf(this.team.model))} requests at once and the team's members hold them` })
|
this.o.bus.emit({ type: "notice", message: `waiting for a free slot: the model serves ${parallelFrom(this.team.capacityOf(this.team.model))} requests at once and the team's members hold them` })
|
||||||
|
this.o.lead.waiting?.(this.team.model)
|
||||||
this.changed()
|
this.changed()
|
||||||
return await new Promise<boolean>((resolve) => {
|
return await new Promise<boolean>((resolve) => {
|
||||||
const onAbort = () => {
|
const onAbort = () => {
|
||||||
|
|||||||
Reference in new issue
Block a user