返回 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 inner event.Sink
22 sender Sender
23 cfg config.NotificationsConfig
24 }
25
26 // NewSink wraps an existing event sink with best-effort notification delivery.
27 func NewSink(inner event.Sink, sender Sender, cfg config.NotificationsConfig) *Sink {
28 return &Sink{inner: inner, sender: sender, cfg: cfg}
29 }
30
31 // Emit preserves the underlying event stream before attempting notification side effects.
32 func (s *Sink) Emit(e event.Event) {
33 if s.inner != nil {
34 s.inner.Emit(e)
35 }
36 SendEvent(s.sender, s.cfg, e)
37 }
38
39 func (s *Sink) RecordProtocolRecovery(a event.ProtocolRecoveryAudit) {
40 event.RecordProtocolRecovery(s.inner, a)
41 }
42
43 // SendEvent applies the same notification rules for paths that do not emit through Sink.
44 func SendEvent(sender Sender, cfg config.NotificationsConfig, e event.Event) {
45 if !cfg.Enabled || sender == nil {
46 return
47 }
48 if msg, ok := message(cfg, e); ok {
49 _ = sender.Send(msg)
50 }
51 }
52
53 func message(cfg config.NotificationsConfig, e event.Event) (Message, bool) {
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