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:06:50 +01:00 committed by GitHub
parent 4768edc67b
commit 3f44ee47b6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -16,7 +16,6 @@ import (
_ "github.com/sipeed/picoclaw/pkg/channels/dingtalk"
_ "github.com/sipeed/picoclaw/pkg/channels/discord"
_ "github.com/sipeed/picoclaw/pkg/channels/feishu"
_ "github.com/sipeed/picoclaw/pkg/channels/irc"
_ "github.com/sipeed/picoclaw/pkg/channels/line"
_ "github.com/sipeed/picoclaw/pkg/channels/maixcam"
_ "github.com/sipeed/picoclaw/pkg/channels/onebot"
@ -31,6 +30,7 @@ import (
"github.com/sipeed/picoclaw/pkg/cron"
"github.com/sipeed/picoclaw/pkg/devices"
"github.com/sipeed/picoclaw/pkg/health"
"github.com/sipeed/picoclaw/pkg/dashboard"
"github.com/sipeed/picoclaw/pkg/heartbeat"
"github.com/sipeed/picoclaw/pkg/logger"
"github.com/sipeed/picoclaw/pkg/media"
@ -182,6 +182,10 @@ func gatewayCmd(debug bool) error {
addr := fmt.Sprintf("%s:%d", cfg.Gateway.Host, cfg.Gateway.Port)
channelManager.SetupHTTPServer(addr, healthServer)
dashServer := dashboard.NewServer(cfg, cronService, internal.GetConfigPath())
dashServer.RegisterOnMux(channelManager.Mux())
fmt.Printf("✓ Dashboard available at http://%s:%d/dashboard\n", cfg.Gateway.Host, cfg.Gateway.Port)
if err := channelManager.StartAll(ctx); err != nil {
fmt.Printf("Error starting channels: %v\n", err)
return err