返回 DeepSeek-Reasonix
sink.go
根目录 / internal / notify / sink.go
1 package notify
2
3 import (
4 "reasonix/internal/config"
5 "reasonix/internal/event"
6 )
7
8 // Message is the user-visible payload sent to the platform notifier.
9 type Message struct {
10 Title string
11 Body string
12 }
13
14 // Sender delivers a notification without taking ownership of event routing.
15 type Sender interface {
16 Send(Message) error
17 }
18
19 // Sink forwards every event to inner and mirrors configured attention events to sender.
20 type Sink struct {
21 event.AuditForwarder
22 inner event.Sink
23 sender Sender
24 cfg config.NotificationsConfig
25 }
26
27 // NewSink wraps an existing event sink with best-effort notification delivery.
28 func NewSink(inner event.Sink, sender Sender, cfg config.NotificationsConfig) *Sink {
29 return &Sink{AuditForwarder: event.AuditForwarder{Inner: inner}, inner: inner, sender: sender, cfg: cfg}
30 }
31
32 // Emit preserves the underlying event stream before attempting notification side effects.
33 func (s *Sink) Emit(e event.Event) {
34 if s.inner != nil {
35 s.inner.Emit(e)
36 }
37 SendEvent(s.sender, s.cfg, e)
38 }
39
40 // SendEvent applies the same notification rules for paths that do not emit through Sink.
41 func SendEvent(sender Sender, cfg config.NotificationsConfig, e event.Event) {
42 if !cfg.Enabled || sender == nil {
43 return
44 }
45 if msg, ok := message(cfg, e); ok {
46 _ = sender.Send(msg)
47 }
48 }
49
50 func message(cfg config.NotificationsConfig, e event.Event) (Message, bool) {
51 if e.Replayed {
52 return Message{}, false
53 }
54 switch e.Kind {
55 case event.TurnDone:
56 if cfg.TurnDone {
57 if e.Err != nil {
58 return Message{Title: "Reasonix", Body: "Turn failed"}, true
59 }
60 return Message{Title: "Reasonix", Body: "Turn finished"}, true
61 }
62 case event.ApprovalRequest:
63 if cfg.ApprovalRequest {
64 return Message{Title: "Reasonix", Body: "Approval needed"}, true
65 }
66 case event.AskRequest:
67 if cfg.AskRequest {
68 return Message{Title: "Reasonix", Body: "Question needs your answer"}, true
69 }
70 }
71 return Message{}, false
72 }
73
73 lines GO