Cut transcript noise: fold grey boxes, drop duplicate review rows
This commit is contained in:
@@ -146,7 +146,7 @@ final class ChatModel {
|
||||
}
|
||||
|
||||
func working(_ row: Row) -> Bool {
|
||||
row.pending && (running || subagents && row.inActive) || row.active && (running || subagents)
|
||||
row.pending && (running || subagents && row.inActive) || row.holdsActive && (running || subagents)
|
||||
}
|
||||
|
||||
var hasOlder: Bool {
|
||||
|
||||
@@ -300,19 +300,27 @@ private struct CardBody: View {
|
||||
var body: some View {
|
||||
let p = model.payload
|
||||
let item = model.item
|
||||
let split = model.context.firstIndex(where: choiceList) ?? model.context.count
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
MarkdownView(blocks: model.context, ctx: contextCtx)
|
||||
.onGeometryChange(for: Bool.self) { $0.size.width > 480 } action: { wide = $0 }
|
||||
.padding(.vertical, 10)
|
||||
MarkdownView(blocks: Array(model.context[..<split]), ctx: contextCtx)
|
||||
.padding(.top, 10)
|
||||
if question {
|
||||
MarkdownView(blocks: parseMarkdown(jsString(p["question"] ?? "")), ctx: MDContext(taskId: item.taskId))
|
||||
.padding(.top, 10)
|
||||
.padding(.bottom, 4)
|
||||
}
|
||||
WhyLine(text: jsString(p["why_blocked"] ?? ""), taskId: item.taskId)
|
||||
MarkdownView(blocks: Array(model.context[split...]), ctx: contextCtx)
|
||||
.padding(.top, 10)
|
||||
.padding(.bottom, 8)
|
||||
Attachments(list: attachments(p["attachments"] ?? nil), taskId: item.taskId)
|
||||
}
|
||||
.onGeometryChange(for: Bool.self) { $0.size.width > 480 } action: { wide = $0 }
|
||||
}
|
||||
|
||||
private func choiceList(_ block: MDBlock) -> Bool {
|
||||
if case .list(_, _, let items, _) = block {
|
||||
return items.contains { $0.choice != nil }
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private func attachments(_ v: (any Sendable)?) -> [Attachment] {
|
||||
@@ -328,23 +336,6 @@ private struct CardBody: View {
|
||||
}
|
||||
}
|
||||
|
||||
private struct WhyLine: View {
|
||||
let text: String
|
||||
let taskId: String
|
||||
@Environment(Store.self) private var store
|
||||
|
||||
var body: some View {
|
||||
var out = AttributedString("Blocked on: ")
|
||||
out.foregroundColor = Palette.text
|
||||
var rest = InlineRenderer(store: store, size: 13, taskId: taskId).text(parseInline(text))
|
||||
rest.foregroundColor = rest.foregroundColor ?? Palette.muted
|
||||
return Text(out + rest)
|
||||
.foregroundStyle(Palette.muted)
|
||||
.textSelection(.enabled)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
}
|
||||
|
||||
private struct ChoiceBox: View {
|
||||
let model: CardModel
|
||||
let item: MDItem
|
||||
|
||||
@@ -105,6 +105,13 @@ final class Row: Identifiable {
|
||||
}
|
||||
}
|
||||
|
||||
var holdsActive: Bool {
|
||||
if case .group = kind {
|
||||
return body!.rows.contains { $0.active }
|
||||
}
|
||||
return active
|
||||
}
|
||||
|
||||
var inActive: Bool {
|
||||
var o = owner
|
||||
while let r = o {
|
||||
@@ -300,7 +307,7 @@ final class TranscriptBuilder {
|
||||
!parent.isEmpty && ctx.subagents[parent] == nil
|
||||
}
|
||||
|
||||
private func addToRun(_ row: Row, _ call: Call, _ parent: String) {
|
||||
private func addToRun(_ row: Row, _ call: Call?, _ parent: String) {
|
||||
if let sub = ctx.subagents[parent] {
|
||||
sub.run = extendRun(sub.run, row, call, parent) { r in
|
||||
sub.row.body!.rows.append(r)
|
||||
@@ -313,12 +320,14 @@ final class TranscriptBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
private func extendRun(_ run: Run?, _ row: Row, _ call: Call, _ parent: String, _ place: (Row) -> RowList) -> Run {
|
||||
private func extendRun(_ run: Run?, _ row: Row, _ call: Call?, _ parent: String, _ place: (Row) -> RowList) -> Run {
|
||||
guard let run, run.parent == parent else {
|
||||
let list = place(row)
|
||||
return Run(first: row, container: list, calls: [call], parent: parent)
|
||||
return Run(first: row, container: list, calls: call.map { [$0] } ?? [], parent: parent)
|
||||
}
|
||||
if let call {
|
||||
run.calls.append(call)
|
||||
}
|
||||
run.calls.append(call)
|
||||
if run.group == nil {
|
||||
let group = Row(.group, taskId: rowTask, body: true)
|
||||
group.owner = ctx.subagents[parent]?.row
|
||||
@@ -383,6 +392,7 @@ final class TranscriptBuilder {
|
||||
private func openHandoff() {
|
||||
let row = Row(.handoff, taskId: rowTask, body: true)
|
||||
row.summary = Note(parts: [.text("writing a handoff…")])
|
||||
ctx.run = nil
|
||||
put(row)
|
||||
ctx.handoff = row
|
||||
}
|
||||
@@ -497,8 +507,11 @@ final class TranscriptBuilder {
|
||||
row.review = r
|
||||
}
|
||||
if ev.kind == "review.finished" {
|
||||
ctx.run = nil
|
||||
for row in renderReview(r, ev.createdAt) {
|
||||
let rows = renderReview(r, ev.createdAt)
|
||||
if !rows.isEmpty {
|
||||
ctx.run = nil
|
||||
}
|
||||
for row in rows {
|
||||
put(row)
|
||||
}
|
||||
continue
|
||||
@@ -518,8 +531,7 @@ final class TranscriptBuilder {
|
||||
sub.row.body!.rows.append(row)
|
||||
continue
|
||||
}
|
||||
ctx.run = nil
|
||||
put(row, keepHeld: true)
|
||||
addToRun(row, Call(name: jsString(p["name"]), target: ""), parent)
|
||||
continue
|
||||
}
|
||||
if ev.kind == "agent.tool_call" && sub == nil && str(p, "name") == "mcp__byre__respond_to_finding" {
|
||||
@@ -540,6 +552,9 @@ final class TranscriptBuilder {
|
||||
let name = toolLabel(jsString(p["name"]))
|
||||
let row = renderToolCall(p)
|
||||
row.started = ev.createdAt
|
||||
if name == "ToolSearch" {
|
||||
continue
|
||||
}
|
||||
addToRun(row, Call(name: name, target: toolTarget(p["input"] ?? nil, worktree())), parent)
|
||||
continue
|
||||
}
|
||||
@@ -551,7 +566,11 @@ final class TranscriptBuilder {
|
||||
sub.row.body!.rows.append(row)
|
||||
continue
|
||||
}
|
||||
ctx.run = nil
|
||||
let prompt = if case .byrePrompt = row.kind { true } else { false }
|
||||
let agentNote = if case .note = row.kind, ev.actor == "agent" { true } else { false }
|
||||
if !prompt && !agentNote {
|
||||
ctx.run = nil
|
||||
}
|
||||
if ev.kind == "agent.message" && parent.isEmpty {
|
||||
ctx.drawn = nil
|
||||
ctx.reply = row
|
||||
@@ -577,6 +596,7 @@ final class TranscriptBuilder {
|
||||
ctx.drawn = nil
|
||||
}
|
||||
if ev.kind == "user.message" && ev.actor == "byre" && !(ev.owner ?? "").isEmpty && !bool(p, "mid_turn") && !bool(p, "handoff") {
|
||||
ctx.run = nil
|
||||
ctx.held = RowList()
|
||||
ctx.open = false
|
||||
ctx.drawn = []
|
||||
@@ -597,6 +617,11 @@ final class TranscriptBuilder {
|
||||
if (ev.kind == "inbox.created" || ev.kind == "task.ready_cleared") && sink == nil && own {
|
||||
lastReady = nil
|
||||
}
|
||||
if prompt && !row.hidden || agentNote {
|
||||
release()
|
||||
addToRun(row, agentNote ? nil : Call(name: "byre", target: ""), parent)
|
||||
continue
|
||||
}
|
||||
put(row, keepHeld: ev.kind == "agent.thinking")
|
||||
}
|
||||
return contextChanged
|
||||
@@ -659,9 +684,12 @@ final class TranscriptBuilder {
|
||||
}
|
||||
|
||||
private func renderReview(_ r: Review, _ when: Date) -> [Row] {
|
||||
let outcome = r.state == .failed ? "failed: \(r.error)" : r.state == .skipped ? "skipped: no changes" : reviewCounts(r)
|
||||
let parts: [NotePart] = [.text("review of snapshot #\(r.snapshotN): \(outcome)")]
|
||||
let fs = findings(r)
|
||||
if fs.isEmpty && r.state != .failed {
|
||||
return []
|
||||
}
|
||||
let outcome = r.state == .failed ? "failed: \(r.error)" : reviewCounts(r)
|
||||
let parts: [NotePart] = [.text("review of snapshot #\(r.snapshotN): \(outcome)")]
|
||||
let head = fs.isEmpty
|
||||
? Row(.note(Note(parts: parts, when: when, style: r.state == .failed ? .error : .plain)), taskId: rowTask)
|
||||
: Row(.review(note: Note(parts: parts, when: when), md: parseMarkdown(str(r.result?.value ?? [:], "summary") ?? "")), taskId: rowTask)
|
||||
@@ -692,7 +720,7 @@ final class TranscriptBuilder {
|
||||
let first = text.components(separatedBy: "\n").first ?? ""
|
||||
let brief = first.count > 120 ? "\(first.prefix(120))…" : first
|
||||
let row = Row(.byrePrompt(brief: brief, when: when, md: parseMarkdown(text)), taskId: rowTask)
|
||||
row.hidden = bool(p, "continuation")
|
||||
row.hidden = bool(p, "continuation") || bool(p, "findings")
|
||||
return row
|
||||
}
|
||||
let images = (p["images"] as? [(any Sendable)?] ?? []).map { jsString($0) }
|
||||
@@ -886,11 +914,10 @@ private func isSubagentCall(_ p: JSONDict) -> Bool {
|
||||
}
|
||||
|
||||
func toolLabel(_ name: String) -> String {
|
||||
let prefix = "mcp__byre__"
|
||||
if !name.hasPrefix(prefix) {
|
||||
guard name.hasPrefix("mcp__"), let sep = name.dropFirst(5).range(of: "__") else {
|
||||
return name
|
||||
}
|
||||
return name.dropFirst(prefix.count).split(separator: "_", omittingEmptySubsequences: false).map { $0.prefix(1).uppercased() + $0.dropFirst() }.joined(separator: " ")
|
||||
return name[sep.upperBound...].split(separator: "_", omittingEmptySubsequences: false).map { $0.prefix(1).uppercased() + $0.dropFirst() }.joined(separator: " ")
|
||||
}
|
||||
|
||||
private func toolBrief(_ input: (any Sendable)?, _ root: String) -> String {
|
||||
|
||||
Reference in New Issue
Block a user