Watch: snooze finished threads, name the files a file approval would edit, Settle on finished notifications, an instant launch from the saved feed, plain Loading states, and no more cancelled errors
Gateway: an approval push for a file change says which files it would edit
This commit is contained in:
1 parent
4dc4e57dac
commit
edc4b88990
35 files changed
+1162
-144
No files matched your search
@@ -1,9 +1,10 @@
|
||||
// One thread: the agent's latest message large, older messages one scroll up with Load earlier above
|
||||
// them, the pending approval or question with its options, the thread's subagents under a header
|
||||
// that collapses them, the files its latest run changed with their line counts, Reply by
|
||||
// dictation or Scribble, Settle once it finished or failed, an Ask before acting switch, and Stop
|
||||
// while a run is active. A subagent's request shows first, labeled with the subagent. Message text
|
||||
// renders as markdown.
|
||||
// dictation or Scribble, Settle and Snooze once it finished or failed, an Ask before acting switch,
|
||||
// and Stop while a run is active. A subagent's request shows first, labeled with the subagent. A file
|
||||
// approval names the files and shows the first changed lines when the gateway has them. Message
|
||||
// text renders as markdown. The detail saved when the thread last loaded shows while it loads again.
|
||||
|
||||
import SwiftUI
|
||||
|
||||
@@ -63,16 +64,8 @@ struct ThreadView: View {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
if let detail {
|
||||
content(detail)
|
||||
} else if error == nil {
|
||||
Text("Loading")
|
||||
.font(.system(size: 15, weight: .semibold))
|
||||
.foregroundStyle(Theme.secondaryText)
|
||||
}
|
||||
if let error {
|
||||
Text(error)
|
||||
.font(.system(size: 12))
|
||||
.foregroundStyle(Theme.secondaryText)
|
||||
}
|
||||
LoadStatus(loaded: detail != nil, error: error)
|
||||
}
|
||||
.padding(.horizontal, 4)
|
||||
}
|
||||
@@ -95,7 +88,10 @@ struct ThreadView: View {
|
||||
}
|
||||
}
|
||||
.navigationTitle(detail?.item.title ?? "Thread")
|
||||
.onAppear { visible = true }
|
||||
.onAppear {
|
||||
if detail == nil { detail = model.cachedThread(hostId: hostId, threadId: threadId) }
|
||||
visible = true
|
||||
}
|
||||
.onDisappear { visible = false }
|
||||
.task(id: visible && scenePhase == .active) {
|
||||
guard visible && scenePhase == .active else { return }
|
||||
@@ -183,10 +179,12 @@ struct ThreadView: View {
|
||||
.disabled(sending)
|
||||
|
||||
if settleable {
|
||||
Button { settle() } label: {
|
||||
Label("Settle", systemImage: "checkmark")
|
||||
HStack(spacing: 6) {
|
||||
Button("Settle") { settle() }
|
||||
.buttonStyle(PillButtonStyle(fill: Theme.work))
|
||||
Button("Snooze") { model.snoozing = item }
|
||||
.buttonStyle(PillButtonStyle(fill: Theme.control, foreground: Theme.snooze))
|
||||
}
|
||||
.buttonStyle(PillButtonStyle(fill: Theme.work))
|
||||
.disabled(sending)
|
||||
}
|
||||
|
||||
@@ -272,7 +270,9 @@ struct ThreadView: View {
|
||||
private func approval(_ request: PendingRequest, from via: FeedItem.Via?) -> some View {
|
||||
Card(edge: Theme.you) {
|
||||
subagentLabel(via)
|
||||
if let prompt = request.prompt {
|
||||
if let edit = request.fileEdit {
|
||||
FileEditRows(edit: edit, inThread: true)
|
||||
} else if let prompt = request.prompt {
|
||||
Text(prompt)
|
||||
.font(.system(size: 13, design: .monospaced))
|
||||
.foregroundStyle(.white)
|
||||
@@ -393,8 +393,9 @@ struct ThreadView: View {
|
||||
if let detail { history.keep(detail.messages) }
|
||||
detail = fresh
|
||||
error = nil
|
||||
model.saveThread(fresh)
|
||||
} catch {
|
||||
self.error = model.message(for: error)
|
||||
if let message = model.message(for: error) { self.error = message }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user