diff --git a/cmd/antidriftd/main.go b/cmd/antidriftd/main.go index e567bbf..27e7d1c 100644 --- a/cmd/antidriftd/main.go +++ b/cmd/antidriftd/main.go @@ -1,7 +1,59 @@ +// Command antidriftd is the AntiDrift focus daemon: it serves a local web UI +// and owns the commitment state machine. package main -import "fmt" +import ( + "log" + "os/exec" + "runtime" + "time" + + "antidrift/internal/session" + "antidrift/internal/store" + "antidrift/internal/web" +) + +const addr = "localhost:7777" func main() { - fmt.Println("antidriftd") + path, err := store.DefaultPath() + if err != nil { + log.Fatalf("resolve snapshot path: %v", err) + } + ctrl, err := session.New(path) + if err != nil { + log.Fatalf("load session: %v", err) + } + + srv := web.NewServer(ctrl) + srv.Init() // re-arm or expire a restored Active session + + go openBrowser("http://" + addr) + + log.Printf("antidriftd listening on http://%s", addr) + if err := srv.Router().Run(addr); err != nil { + log.Fatalf("server: %v", err) + } +} + +// openBrowser best-effort launches the default browser after a short delay so +// the server is listening first. Failures are logged, not fatal. +func openBrowser(url string) { + time.Sleep(300 * time.Millisecond) + var cmd string + var args []string + switch runtime.GOOS { + case "linux": + cmd, args = "xdg-open", []string{url} + case "darwin": + cmd, args = "open", []string{url} + case "windows": + cmd, args = "rundll32", []string{"url.dll,FileProtocolHandler", url} + default: + log.Printf("open browser manually: %s", url) + return + } + if err := exec.Command(cmd, args...).Start(); err != nil { + log.Printf("could not open browser (%v); visit %s", err, url) + } }