Merge nucleic/upbeat-cedar-weasel-1orz into dev
This commit is contained in:
@@ -451,6 +451,12 @@ enum TranscriptProjection {
|
||||
/// aside and re-emitted right after the block, so the calls stay one contiguous block.
|
||||
/// Mirrors the desktop projection.
|
||||
///
|
||||
/// A subagent spawn (`Task`/`Agent`) only groups with *other* subagent spawns: a run of them
|
||||
/// is a multi-agent fan-out (the gold orchestration card), which the view gates on the block
|
||||
/// being all-orchestration. So a subagent-ness switch breaks the run — a wave of `Task`s
|
||||
/// followed by the agent's own `Bash` calls yields a fan-out card *and* a tool block, not one
|
||||
/// generic block titled by the first `Task` that would swallow the fan-out.
|
||||
///
|
||||
/// `flatItems` already drops the only kind the phone has (empty redacted thinking), so the
|
||||
/// hold path is a guard for a caller passing unfiltered items — not a live case.
|
||||
static func coalesceToolRuns(_ flat: [TranscriptItem]) -> [TranscriptItem] {
|
||||
@@ -474,7 +480,14 @@ enum TranscriptProjection {
|
||||
}
|
||||
|
||||
for item in flat {
|
||||
if case .tool = item.kind {
|
||||
if case .tool(let group) = item.kind {
|
||||
// A subagent spawn and an ordinary tool call never share a run (see above):
|
||||
// switching kind flushes the run in progress so each side forms its own card.
|
||||
// `isOrchestration` mirrors the view's fan-out gate (`groups.allSatisfy(\.isOrchestration)`)
|
||||
// exactly — worker spawns included — so no mixed block can ever reach it.
|
||||
if case .tool(let first)? = run.first?.kind, first.isOrchestration != group.isOrchestration {
|
||||
flush()
|
||||
}
|
||||
run.append(item)
|
||||
} else if item.rendersNothing, !run.isEmpty {
|
||||
held.append(item)
|
||||
|
||||
Reference in New Issue
Block a user