Questions tab, question bubbles, answer snapshots; errors to transcript
This commit is contained in:
@@ -2,7 +2,7 @@ import Foundation
|
||||
import Observation
|
||||
import SwiftData
|
||||
|
||||
let taskTabs: [TaskTab] = [.transcript, .board, .changes, .files, .terminal, .inbox, .reviews, .workflow, .project]
|
||||
let taskTabs: [TaskTab] = [.transcript, .board, .changes, .files, .terminal, .questions, .reviews, .workflow, .project]
|
||||
|
||||
private let historyPage = 1000
|
||||
private let leadPage = 50
|
||||
@@ -10,7 +10,7 @@ private let routeHash = Re(#"^#/(task|project)/(\w+)(?:/(\w+))?$"#)
|
||||
|
||||
struct TaskState {
|
||||
enum Kind {
|
||||
case answer, merging, held, error, working, idle
|
||||
case answer, merging, held, working, idle
|
||||
}
|
||||
|
||||
let kind: Kind
|
||||
@@ -37,6 +37,7 @@ final class Store {
|
||||
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(tabs: [.transcript], tab: .transcript)
|
||||
var leadSessions: [AgentSession] = []
|
||||
@@ -188,9 +189,8 @@ final class Store {
|
||||
}
|
||||
|
||||
func taskState(_ task: ByreTask) -> TaskState {
|
||||
let open = inbox.filter { $0.taskId == task.id }
|
||||
if open.contains(where: { $0.kind == .question }) {
|
||||
return TaskState(kind: .answer, label: "Needs your answer", title: "The agent asked a question in the inbox")
|
||||
if inbox.contains(where: { $0.taskId == task.id }) {
|
||||
return TaskState(kind: .answer, label: "Needs your answer", title: "The agent asked a question")
|
||||
}
|
||||
if task.merging {
|
||||
return TaskState(kind: .merging, label: "Merging", title: "The merge turn is running")
|
||||
@@ -204,9 +204,6 @@ final class Store {
|
||||
if task.mergeAfterReview {
|
||||
return TaskState(kind: .held, label: "Merge after review", title: "Merges when the running review finishes with no findings")
|
||||
}
|
||||
if !open.isEmpty {
|
||||
return TaskState(kind: .error, label: "Error", title: "The agent's session failed or hit a rate limit; see the inbox")
|
||||
}
|
||||
if let working = workingTitles[task.state] {
|
||||
return TaskState(kind: .working, label: "Working", title: working)
|
||||
}
|
||||
@@ -234,6 +231,21 @@ final class Store {
|
||||
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
|
||||
}
|
||||
guard let ev = transcript.last(where: { ($0.kind == "inbox.created" || $0.kind == "inbox.updated") && str($0.payload.value, "id") == itemId }) else {
|
||||
return nil
|
||||
}
|
||||
return try! decodePayload(ev.payload, as: InboxItem.self)
|
||||
}
|
||||
|
||||
var defaultModel: String {
|
||||
me!.defaultModel
|
||||
}
|
||||
@@ -346,6 +358,7 @@ final class Store {
|
||||
}
|
||||
|
||||
func focusTask(_ taskId: String, _ tab: TaskTab = .transcript) {
|
||||
question = nil
|
||||
spawn("set focus") {
|
||||
try await self.setFocus(taskId: taskId, tab: tab)
|
||||
}
|
||||
@@ -358,6 +371,7 @@ final class Store {
|
||||
}
|
||||
|
||||
func focusTab(_ tab: TaskTab) {
|
||||
question = nil
|
||||
spawn("set focus") {
|
||||
try await self.setFocus(tab: tab)
|
||||
}
|
||||
@@ -370,6 +384,7 @@ 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)
|
||||
@@ -617,6 +632,8 @@ final class Store {
|
||||
spawn("load inbox") {
|
||||
try await self.loadInbox()
|
||||
}
|
||||
case "session.error", "session.rate_limited":
|
||||
notifyError(self, ev)
|
||||
case "turn.ended":
|
||||
notifyTurn(self, ev)
|
||||
if ev.payload.value["summary"] as? Bool == true, let taskId = ev.taskId {
|
||||
|
||||
Reference in New Issue
Block a user