-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathnotify.go
More file actions
98 lines (89 loc) · 2.91 KB
/
Copy pathnotify.go
File metadata and controls
98 lines (89 loc) · 2.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package main
import (
"fmt"
"math/rand"
"os"
"os/exec"
"runtime"
)
// sound is one chime across both platforms: a canberra event id (+dB volume)
// and .oga fallback for Linux, and a system sound name for macOS.
type sound struct {
linuxID string
linuxFile string
linuxDB string
macName string
}
var (
soundDone = sound{"complete", "complete.oga", "-6", "Glass"}
soundAlert = sound{"dialog-warning", "dialog-warning.oga", "-3", "Funk"}
)
var cuteDoneMessages = []string{
"%s finished, come see what it did! 🎉",
"All done! %s is waiting for you ✨",
"%s wrapped up. Your turn! 🌸",
"Ding! %s just finished cooking 🍳",
"Task complete, %s says hi 👋",
"%s is done and looking rather pleased with itself 😌",
}
func (s *Session) agentName() string {
name := s.agent
if name != "" {
name = string(name[0]-'a'+'A') + name[1:]
}
return name
}
// notifyDone announces the agent finished its turn. Native desktop notifications
// fire only when local notifications are enabled; web push is always attempted
// (it no-ops without subscribers) and is controlled per-browser instead.
func (s *Session) notifyDone() {
body := fmt.Sprintf(cuteDoneMessages[rand.Intn(len(cuteDoneMessages))], s.agentName())
if s.d.localNotify {
go notify("✨ pulse", body, soundDone)
}
go s.d.pushAll("✨ pulse", body, "/s/"+s.id)
}
// notifyPermission announces the agent is waiting for tool approval.
func (s *Session) notifyPermission(tool string) {
body := fmt.Sprintf("%s wants to run %s. approve? 🔐", s.agentName(), tool)
if tool == "" {
body = fmt.Sprintf("%s needs your permission 🔐", s.agentName())
}
if s.d.localNotify {
go notify("🔐 pulse: needs you", body, soundAlert)
}
go s.d.pushAll("🔐 pulse: needs you", body, "/s/"+s.id)
}
// notify pops a native OS notification on Linux and macOS. Best-effort: any
// failure is ignored so it never disrupts the session.
func notify(title, body string, snd sound) {
switch runtime.GOOS {
case "darwin":
script := fmt.Sprintf("display notification %q with title %q sound name %q", body, title, snd.macName)
_ = exec.Command("osascript", "-e", script).Start()
case "linux":
_ = exec.Command("notify-send", "-a", "pulse", "-u", "normal", title, body).Start()
playSound(snd) // notify-send is silent on its own
}
}
// playSound plays snd's chime on Linux, trying each available player in turn.
func playSound(snd sound) {
if p, err := exec.LookPath("canberra-gtk-play"); err == nil {
_ = exec.Command(p, "-i", snd.linuxID, "-V", snd.linuxDB).Start()
return
}
file := "/usr/share/sounds/freedesktop/stereo/" + snd.linuxFile
if _, err := os.Stat(file); err != nil {
return
}
for _, player := range []string{"paplay", "pw-play", "ogg123"} {
if p, err := exec.LookPath(player); err == nil {
args := []string{file}
if player == "paplay" {
args = []string{"--volume=33000", file} // ~-6dB
}
_ = exec.Command(p, args...).Start()
return
}
}
}