Add team tasks: several agents in one worktree sharing a board
This commit is contained in:
@@ -2,7 +2,7 @@ import Foundation
|
||||
import Observation
|
||||
import SwiftData
|
||||
|
||||
let taskTabs: [TaskTab] = [.transcript, .changes, .files, .terminal, .inbox, .reviews, .workflow, .project]
|
||||
let taskTabs: [TaskTab] = [.transcript, .board, .changes, .files, .terminal, .inbox, .reviews, .workflow, .project]
|
||||
|
||||
private let historyPage = 1000
|
||||
private let leadPage = 50
|
||||
@@ -46,6 +46,7 @@ final class Store {
|
||||
var summaryReads: [String: Int64] = [:]
|
||||
private(set) var leadMore = false
|
||||
var todoBusy: [String: String] = [:]
|
||||
var pickedMembers: [String: String] = [:]
|
||||
private(set) var drafts: Drafts?
|
||||
let images = ImageDrafts()
|
||||
let events = Listeners<ByreEvent>()
|
||||
@@ -158,7 +159,32 @@ final class Store {
|
||||
}
|
||||
|
||||
func currentSession(_ taskId: String) -> AgentSession? {
|
||||
sessions[taskId]?.last(where: { $0.state != .completed }) ?? sessions[taskId]?.last
|
||||
let list = (sessions[taskId] ?? []).filter { $0.member == (pickedMember(taskId) ?? "") }
|
||||
return list.last(where: { $0.state != .completed }) ?? list.last
|
||||
}
|
||||
|
||||
func team(_ taskId: String) -> [AgentSession] {
|
||||
let list = sessions[taskId] ?? []
|
||||
var names: [String] = []
|
||||
for s in list where !s.member.isEmpty && !names.contains(s.member) {
|
||||
names.append(s.member)
|
||||
}
|
||||
return names.compactMap { name in
|
||||
let mine = list.filter { $0.member == name }
|
||||
return mine.last(where: { $0.state != .completed }) ?? mine.last
|
||||
}
|
||||
}
|
||||
|
||||
func pickedMember(_ taskId: String) -> String? {
|
||||
let names = team(taskId).map(\.member)
|
||||
if let picked = pickedMembers[taskId], names.contains(picked) {
|
||||
return picked
|
||||
}
|
||||
return names.first
|
||||
}
|
||||
|
||||
func taskBusy(_ taskId: String) -> Bool {
|
||||
(sessions[taskId] ?? []).contains { $0.state == .running }
|
||||
}
|
||||
|
||||
func taskState(_ task: ByreTask) -> TaskState {
|
||||
@@ -457,8 +483,31 @@ final class Store {
|
||||
}
|
||||
|
||||
func openSummary(_ task: ByreTask) {
|
||||
jump = (task.id, task.summarySeq)
|
||||
focusTask(task.id, .transcript)
|
||||
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)
|
||||
return
|
||||
}
|
||||
Task {
|
||||
do {
|
||||
let evs = try await api.client.listTaskEvents(path: .init(taskId: task.id), query: .init(after: seq - 1, limit: 1)).ok.body.json
|
||||
if let ev = evs.first(where: { $0.seq == seq }) {
|
||||
pickMember(task.id, ev)
|
||||
}
|
||||
} catch {
|
||||
log.error("load summary event: \(errorText(error), privacy: .public)")
|
||||
}
|
||||
jump = (task.id, seq)
|
||||
focusTask(task.id, .transcript)
|
||||
}
|
||||
}
|
||||
|
||||
private func pickMember(_ taskId: String, _ ev: ByreEvent) {
|
||||
if let member = str(ev.payload.value, "member"), !member.isEmpty {
|
||||
pickedMembers[taskId] = member
|
||||
}
|
||||
}
|
||||
|
||||
func selectTask(_ taskId: String?) {
|
||||
|
||||
Reference in New Issue
Block a user