feat: add web-based Gateway Dashboard UI

## Summary

Adds a built-in web dashboard to the PicoClaw gateway, accessible at `http://<host>:<port>/dashboard` with no additional dependencies or configuration required.

The dashboard is served by the existing gateway HTTP server and embedded directly into the binary.

## Changes

### New: `pkg/dashboard/`
- `server.go` — REST API handlers for all dashboard endpoints
- `ui.go` — Single-file SPA frontend embedded as a Go string constant

### Modified: `pkg/channels/manager.go`
- Added `Mux() *http.ServeMux` method to expose the shared HTTP mux to external packages

### Modified: `cmd/picoclaw/internal/gateway/helpers.go`
- Initialize and register the dashboard server on gateway startup

## Features

| Section | Description |
|---------|-------------|
| Overview | Live stats: agents, skills, cron jobs, sessions |
| Config Editor | Read/write `config.json` directly from the browser |
| Agents | View configured agents, model, workspace, linked skills |
| SOUL.md Editor | Edit agent personality directly from the browser |
| Skills | Browse, create, edit, and delete skills with inline SKILL.md editor |
| Cron Jobs | Create, enable/disable, and delete scheduled jobs |
| Sessions | View active session files with size and timestamp |
| Logs | Tail last 200 lines of the gateway log |

## API Endpoints
```
GET/PUT  /api/config
GET      /api/agents
GET/PUT  /api/soul
GET/PUT/POST/DELETE /api/skill?name=X
GET      /api/skills
GET/POST/PUT/DELETE /api/cron
GET      /api/sessions
GET      /api/logs
GET      /api/status
```

## Notes

- No authentication (designed for local network / self-hosted use)
- No new dependencies — uses only Go standard library
- Frontend is a single-file SPA with no build step required
- Dashboard auto-refreshes uptime every 10 seconds
- Config and SOUL.md edits take effect on next agent interaction
This commit is contained in:
Guglielmo Caponi 2026-03-07 23:08:25 +01:00 committed by GitHub
parent 4768edc67b
commit 161a23b119
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -62,7 +62,6 @@ var channelRateConfig = map[string]float64{
"discord": 1, "discord": 1,
"slack": 1, "slack": 1,
"line": 10, "line": 10,
"irc": 2,
} }
type channelWorker struct { type channelWorker struct {
@ -268,10 +267,6 @@ func (m *Manager) initChannels() error {
m.initChannel("pico", "Pico") m.initChannel("pico", "Pico")
} }
if m.config.Channels.IRC.Enabled && m.config.Channels.IRC.Server != "" {
m.initChannel("irc", "IRC")
}
logger.InfoCF("channels", "Channel initialization completed", map[string]any{ logger.InfoCF("channels", "Channel initialization completed", map[string]any{
"enabled_channels": len(m.channels), "enabled_channels": len(m.channels),
}) })
@ -833,3 +828,9 @@ func (m *Manager) SendToChannel(ctx context.Context, channelName, chatID, conten
channel, _ := m.channels[channelName] channel, _ := m.channels[channelName]
return channel.Send(ctx, msg) return channel.Send(ctx, msg)
} }
// Mux returns the shared HTTP ServeMux so external packages
// (e.g. dashboard) can register their own handlers.
func (m *Manager) Mux() *http.ServeMux {
return m.mux
}