Add scheduled tasks with a Project tab section and lead tools

This commit is contained in:
Ian Gulliver
2026-10-21 15:15:20 -07:00
parent 4b4763779d
commit f445e1cac3
21 changed files with 1689 additions and 347 deletions
+28
View File
@@ -58,6 +58,7 @@ final class Store {
var me: User?
var projects: [Project] = []
var tasks: [String: [ByreTask]] = [:]
var schedules: [String: [Schedule]] = [:]
var sessions: [String: [AgentSession]] = [:]
var inbox: [InboxItem] = []
private(set) var terminals: [String: [TaskTerminal]] = [:]
@@ -313,9 +314,34 @@ final class Store {
projects = try await api.client.listProjects().ok.body.json
try await each(projects.map(\.id)) { id in
try await self.loadTasks(id)
try await self.loadSchedules(id)
}
}
func loadSchedules(_ projectId: String) async throws {
let latest = claimRequest("schedules:\(projectId)")
let list = try await api.client.listSchedules(path: .init(projectId: projectId)).ok.body.json
if !latest() {
return
}
schedules[projectId] = list
}
private func applySchedule(_ ev: ByreEvent) {
guard let projectId = ev.projectId else {
return
}
var list = schedules[projectId] ?? []
if ev.kind == "schedule.saved" {
let sc = try! decodePayload(ev.payload, as: Schedule.self)
list.removeAll { $0.id == sc.id }
list.append(sc)
} else if let id = str(ev.payload.value, "id") {
list.removeAll { $0.id == id }
}
schedules[projectId] = list.sorted { ($0.nextRun, $0.id) < ($1.nextRun, $1.id) }
}
private func claimRequest(_ key: String) -> () -> Bool {
let seq = (requestSeqs[key] ?? 0) + 1
requestSeqs[key] = seq
@@ -671,6 +697,8 @@ final class Store {
spawn("load projects") {
try await self.loadProjects()
}
case "schedule.saved", "schedule.deleted":
applySchedule(ev)
case "task.created", "task.title", "task.merge_title", "task.merge_queued", "task.merge_unqueued", "task.merge_after_review", "task.merge_after_review_ended", "task.merge_after_review_cancelled", "task.parent_merge_started", "task.parent_merge_stopped", "task.merge_started", "task.merge_ended", "task.discard_started", "task.merged", "task.discarded", "task.state", "task.ready", "task.discard_suggested", "task.ready_cleared", "snapshot.created":
if let taskId = ev.taskId, ["task.merged", "task.discarded"].contains(ev.kind) || (ev.kind == "snapshot.created" && !["answer", "fork", "ask_human"].contains(str(ev.payload.value, "trigger"))) {
clearTask(self, taskId)