Move questions and reviews into the transcript; agents answer findings

This commit is contained in:
Ian Gulliver
2026-10-19 09:14:21 -07:00
parent eb7e0a13c4
commit 27ff0f457b
21 changed files with 903 additions and 801 deletions
+28 -30
View File
@@ -2,7 +2,19 @@ import Foundation
import Observation
import SwiftData
let taskTabs: [TaskTab] = [.transcript, .board, .changes, .files, .terminal, .questions, .reviews, .workflow, .project]
let taskTabs: [TaskTab] = [.transcript, .board, .changes, .files, .terminal, .workflow, .project]
enum JumpTarget: Equatable {
case summary(Int64)
case question(String)
case review(Int)
}
struct Jump: Equatable {
let taskId: String
let target: JumpTarget
let n: Int
}
private let historyPage = 1000
private let leadPage = 50
@@ -36,13 +48,12 @@ final class Store {
var inbox: [InboxItem] = []
private(set) var selectedTaskId: String?
var pinned: Int?
var reviewed: Int?
var question: (taskId: String, itemId: String)?
var connected = false
private(set) var focus = Focus(tab: .transcript)
var leadSessions: [AgentSession] = []
let leadFeed: Feed
var jump: (taskId: String, seq: Int64)?
var jump: Jump?
@ObservationIgnored private var jumps = 0
var composerFocus: String?
var summaryReads: [String: Int64] = [:]
private(set) var leadMore = false
@@ -224,28 +235,21 @@ final class Store {
pinned = n
}
func pickReview(_ n: Int) {
reviewed = n
func jumpTo(_ taskId: String, _ target: JumpTarget) {
jumps += 1
jump = Jump(taskId: taskId, target: target, n: jumps)
focusTask(taskId, .transcript)
}
func showReview(_ n: Int) {
pickReview(n)
focusTab(.reviews)
}
func showQuestion(_ taskId: String, _ itemId: String) {
focusTask(taskId, .questions)
question = (taskId, itemId)
}
func questionItem(_ itemId: String) -> InboxItem? {
if let open = inbox.first(where: { $0.id == itemId }) {
return open
func showQuestion(_ taskId: String) {
guard let item = inbox.filter({ $0.taskId == taskId }).min(by: { $0.createdAt < $1.createdAt }) else {
focusTask(taskId, .transcript)
return
}
guard let ev = transcript.last(where: { ($0.kind == "inbox.created" || $0.kind == "inbox.updated") && str($0.payload.value, "id") == itemId }) else {
return nil
if let member = sessions[taskId]?.first(where: { $0.id == item.agentSessionId })?.member, !member.isEmpty {
pickedMembers[taskId] = member
}
return try! decodePayload(ev.payload, as: InboxItem.self)
jumpTo(taskId, .question(item.id))
}
var defaultModel: String {
@@ -360,7 +364,6 @@ final class Store {
}
func focusTask(_ taskId: String, _ tab: TaskTab = .transcript) {
question = nil
spawn("set focus") {
try await self.setFocus(taskId: taskId, tab: tab)
}
@@ -373,7 +376,6 @@ final class Store {
}
func focusTab(_ tab: TaskTab) {
question = nil
spawn("set focus") {
try await self.setFocus(tab: tab)
}
@@ -386,7 +388,6 @@ final class Store {
let name = m?[3] ?? nil
let tab = taskTabs.first { $0.rawValue == name }
if kind == "task", let id {
question = nil
if id != focus.taskId || (tab != nil && tab != focus.tab) {
spawn("set focus") {
try await self.setFocus(taskId: id, tab: tab)
@@ -507,8 +508,7 @@ final class Store {
let seq = task.summarySeq
if let ev = taskFeeds[task.id]?.events.first(where: { $0.seq == seq }) {
pickMember(task.id, ev)
jump = (task.id, seq)
focusTask(task.id, .transcript)
jumpTo(task.id, .summary(seq))
return
}
Task {
@@ -520,8 +520,7 @@ final class Store {
} catch {
log.error("load summary event: \(errorText(error), privacy: .public)")
}
jump = (task.id, seq)
focusTask(task.id, .transcript)
jumpTo(task.id, .summary(seq))
}
}
@@ -539,7 +538,6 @@ final class Store {
_ = taskFeed(taskId)
}
pinned = nil
reviewed = nil
dropClosedFeeds()
}