on main help sign in
chore(server): report background prompt failures via events
0a97743Christian Rocha
internal/agent/notify/notify.go+6
@@ -12,6 +12,9 @@ const (
12 // TypeReAuthenticate indicates the agent encountered an
12 // TypeReAuthenticate indicates the agent encountered an
13 // authentication error and the user needs to re-authenticate.
13 // authentication error and the user needs to re-authenticate.
14 TypeReAuthenticate Type = "re_authenticate"
14 TypeReAuthenticate Type = "re_authenticate"
15+ // TypeAgentError indicates the agent's turn terminated with an
16+ // error. The error text is carried in Notification.Message.
17+ TypeAgentError Type = "error"
15)
18)
16
19
17// Notification represents a domain event published by the agent.
20// Notification represents a domain event published by the agent.
@@ -20,6 +23,9 @@ type Notification struct {
20 SessionTitle string
23 SessionTitle string
21 Type Type
24 Type Type
22 ProviderID string
25 ProviderID string
26+ // Message carries the error text for TypeAgentError. Other
27+ // notification types ignore it.
28+ Message string
23}
29}
24
30
25// RunComplete is the authoritative end-of-run signal for a session.
31// RunComplete is the authoritative end-of-run signal for a session.
internal/server/events.go+12−6
@@ -2,6 +2,7 @@ package server
2
2
3import (
3import (
4 "encoding/json"
4 "encoding/json"
5+ "errors"
5 "fmt"
6 "fmt"
6 "log/slog"
7 "log/slog"
7
8
@@ -85,13 +86,18 @@ func wrapEvent(ev any) *pubsub.Payload {
85 Payload: fileToProto(e.Payload),
86 Payload: fileToProto(e.Payload),
86 })
87 })
87 case pubsub.Event[notify.Notification]:
88 case pubsub.Event[notify.Notification]:
89+ payload := proto.AgentEvent{
90+ SessionID: e.Payload.SessionID,
91+ SessionTitle: e.Payload.SessionTitle,
92+ Type: proto.AgentEventType(e.Payload.Type),
93+ }
94+ if e.Payload.Type == notify.TypeAgentError {
95+ payload.Type = proto.AgentEventTypeError
96+ payload.Error = errors.New(e.Payload.Message)
97+ }
88 return envelope(pubsub.PayloadTypeAgentEvent, pubsub.Event[proto.AgentEvent]{
98 return envelope(pubsub.PayloadTypeAgentEvent, pubsub.Event[proto.AgentEvent]{
89− Type: e.Type,
99+ Type: e.Type,
90− Payload: proto.AgentEvent{
100+ Payload: payload,
91− SessionID: e.Payload.SessionID,
92− SessionTitle: e.Payload.SessionTitle,
93− Type: proto.AgentEventType(e.Payload.Type),
94− },
95 })
101 })
96 case pubsub.Event[notify.RunComplete]:
102 case pubsub.Event[notify.RunComplete]:
97 return envelope(pubsub.PayloadTypeRunComplete, pubsub.Event[proto.RunComplete]{
103 return envelope(pubsub.PayloadTypeRunComplete, pubsub.Event[proto.RunComplete]{
internal/workspace/client_workspace.go+10−6
@@ -703,13 +703,17 @@ func (w *ClientWorkspace) translateEvent(ev any) tea.Msg {
703 Payload: protoToFile(e.Payload),
703 Payload: protoToFile(e.Payload),
704 }
704 }
705 case pubsub.Event[proto.AgentEvent]:
705 case pubsub.Event[proto.AgentEvent]:
706+ n := notify.Notification{
707+ SessionID: e.Payload.SessionID,
708+ SessionTitle: e.Payload.SessionTitle,
709+ Type: notify.Type(e.Payload.Type),
710+ }
711+ if e.Payload.Error != nil {
712+ n.Message = e.Payload.Error.Error()
713+ }
706 return pubsub.Event[notify.Notification]{
714 return pubsub.Event[notify.Notification]{
707− Type: e.Type,
715+ Type: e.Type,
708− Payload: notify.Notification{
716+ Payload: n,
709− SessionID: e.Payload.SessionID,
710− SessionTitle: e.Payload.SessionTitle,
711− Type: notify.Type(e.Payload.Type),
712− },
713 }
717 }
714 case pubsub.Event[proto.RunComplete]:
718 case pubsub.Event[proto.RunComplete]:
715 // Translate the wire-level proto.RunComplete back into the
719 // Translate the wire-level proto.RunComplete back into the