Files
agent-dashboard/internal/config/config.go
T
2026-06-02 14:37:40 +08:00

153 lines
3.3 KiB
Go

package config
import (
"os"
"path/filepath"
"strings"
"github.com/BurntSushi/toml"
)
type Config struct {
Events Events `toml:"events"`
Notify Notify `toml:"notify"`
Inbox Inbox `toml:"inbox"`
Remote Remote `toml:"remote"`
}
type Events struct {
Stop bool `toml:"stop"`
Response bool `toml:"response"`
Idle bool `toml:"idle"`
Tool bool `toml:"tool"`
}
type Notify struct {
Protocol string `toml:"protocol"`
TitleTemplate string `toml:"title_template"`
BodyStop string `toml:"body_stop"`
BodyIdle string `toml:"body_idle"`
BodyTool string `toml:"body_tool"`
}
type Inbox struct {
Enabled bool `toml:"enabled"`
Socket string `toml:"socket"`
RemoteSocket string `toml:"remote_socket"`
Addr string `toml:"addr"`
FallbackLocal bool `toml:"fallback_local"`
TimeoutMS int `toml:"timeout_ms"`
}
type Remote struct {
Enabled bool `toml:"enabled"`
URL string `toml:"url"`
Token string `toml:"token"`
TimeoutMS int `toml:"timeout_ms"`
}
func Default() Config {
return Config{
Events: Events{Stop: true, Response: true, Idle: false, Tool: false},
Notify: Notify{
Protocol: "osc777",
TitleTemplate: "{agent} — {context}",
BodyStop: "等待输入",
BodyIdle: "空闲 60s+,等待输入",
BodyTool: "工具执行完成",
},
Inbox: Inbox{
Enabled: false,
Socket: DefaultInboxSocket(),
RemoteSocket: DefaultInboxRemoteSocket(),
Addr: "127.0.0.1:17777",
FallbackLocal: true,
TimeoutMS: 500,
},
Remote: Remote{
Enabled: false,
URL: "",
Token: "",
TimeoutMS: 2000,
},
}
}
func DefaultInboxRemoteSocket() string {
user := os.Getenv("USER")
if user == "" {
user = "user"
}
return filepath.Join("/tmp", "agent-notify-"+user+".sock")
}
func DefaultInboxSocket() string {
if runtimeDir := os.Getenv("XDG_RUNTIME_DIR"); runtimeDir != "" {
return filepath.Join(runtimeDir, "agent-notify.sock")
}
return filepath.Join(os.Getenv("HOME"), ".local", "state", "agent-notify", "agent-notify.sock")
}
func DefaultPath() string {
return filepath.Join(os.Getenv("HOME"), ".config", "agent-notify", "config.toml")
}
func Load(path string) (Config, error) {
cfg := Default()
if path == "" {
return cfg, nil
}
if _, err := os.Stat(path); os.IsNotExist(err) {
return cfg, nil
}
if _, err := toml.DecodeFile(path, &cfg); err != nil {
return Config{}, err
}
return cfg, nil
}
func LoadDefault() (Config, error) {
return Load(DefaultPath())
}
func (c Config) EventEnabled(event string) bool {
switch strings.ToLower(event) {
case "stop":
return c.Events.Stop
case "response":
return c.Events.Response
case "idle":
return c.Events.Idle
case "tool":
return c.Events.Tool
default:
return false
}
}
func (c Config) BodyForEvent(event string) string {
switch strings.ToLower(event) {
case "idle":
return c.Notify.BodyIdle
case "tool":
return c.Notify.BodyTool
default:
return c.Notify.BodyStop
}
}
func (c Config) WriteDefault(path string) error {
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
return err
}
f, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0644)
if err != nil {
if os.IsExist(err) {
return nil
}
return err
}
defer f.Close()
return toml.NewEncoder(f).Encode(Default())
}