From 7f920ca63af5329c19a0e5a879c649c594beea35 Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Mon, 16 Mar 2026 20:43:28 +0000 Subject: feat: add web push notifications and file drop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Web Push: - WebPushNotifier with VAPID auth; urgency mapped to event type (BLOCKED=urgent, FAILED=high, COMPLETED=low) - Auto-generates VAPID keys on first serve, persists to config file - push_subscriptions table in SQLite (upsert by endpoint) - GET /api/push/vapid-key, POST/DELETE /api/push/subscribe endpoints - Service worker (sw.js) handles push events and notification clicks - Notification bell button in web UI; subscribes on click File Drop: - GET /api/drops, GET /api/drops/{filename}, POST /api/drops - Persistent ~/.claudomator/drops/ directory - CLAUDOMATOR_DROP_DIR env var passed to agent subprocesses - Drops tab (📁) in web UI with file listing and download links Co-Authored-By: Claude Sonnet 4.6 --- internal/config/config.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'internal/config') diff --git a/internal/config/config.go b/internal/config/config.go index ce3b53f..a3c37fb 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -19,6 +19,7 @@ type Config struct { DataDir string `toml:"data_dir"` DBPath string `toml:"-"` LogDir string `toml:"-"` + DropsDir string `toml:"-"` ClaudeBinaryPath string `toml:"claude_binary_path"` GeminiBinaryPath string `toml:"gemini_binary_path"` MaxConcurrent int `toml:"max_concurrent"` @@ -28,6 +29,9 @@ type Config struct { WorkspaceRoot string `toml:"workspace_root"` WebhookSecret string `toml:"webhook_secret"` Projects []Project `toml:"projects"` + VAPIDPublicKey string `toml:"vapid_public_key"` + VAPIDPrivateKey string `toml:"vapid_private_key"` + VAPIDEmail string `toml:"vapid_email"` } func Default() (*Config, error) { @@ -43,6 +47,7 @@ func Default() (*Config, error) { DataDir: dataDir, DBPath: filepath.Join(dataDir, "claudomator.db"), LogDir: filepath.Join(dataDir, "executions"), + DropsDir: filepath.Join(dataDir, "drops"), ClaudeBinaryPath: "claude", GeminiBinaryPath: "gemini", MaxConcurrent: 3, @@ -67,7 +72,7 @@ func LoadFile(path string) (*Config, error) { // EnsureDirs creates the data directory structure. func (c *Config) EnsureDirs() error { - for _, dir := range []string{c.DataDir, c.LogDir} { + for _, dir := range []string{c.DataDir, c.LogDir, c.DropsDir} { if err := os.MkdirAll(dir, 0700); err != nil { return err } -- cgit v1.2.3