Files
agent-mgr/internal/events/valkey.go
Steven Hooker e5b07cc1d8 initial agent-mgr: app builder platform MVP
Go API server + Preact UI + Claude Code adapter.
- App-centric model (ideas, not repos)
- AgentProvider interface for multi-agent support
- K8s pod lifecycle for sandboxed agent sessions
- Gitea integration (create repos, push branches)
- WebSocket streaming for live session output
- Woodpecker CI/CD pipelines (kaniko build + kubectl deploy)
2026-02-18 15:56:32 +01:00

72 lines
1.4 KiB
Go

package events
import (
"context"
"encoding/json"
"fmt"
"github.com/redis/go-redis/v9"
)
const channel = "agent-mgr:events"
type Bus struct {
rdb *redis.Client
}
type Event struct {
Type string `json:"type"` // "session.started", "session.completed", "session.failed", "session.stopped", "app.status"
SessionID string `json:"session_id,omitempty"`
AppID string `json:"app_id,omitempty"`
Status string `json:"status,omitempty"`
Message string `json:"message,omitempty"`
}
func NewBus(addr, password string) *Bus {
return &Bus{
rdb: redis.NewClient(&redis.Options{
Addr: addr,
Password: password,
}),
}
}
func (b *Bus) Publish(ctx context.Context, evt Event) error {
data, err := json.Marshal(evt)
if err != nil {
return fmt.Errorf("marshal event: %w", err)
}
return b.rdb.Publish(ctx, channel, data).Err()
}
func (b *Bus) Subscribe(ctx context.Context) (<-chan Event, error) {
sub := b.rdb.Subscribe(ctx, channel)
ch := make(chan Event, 64)
go func() {
defer close(ch)
defer sub.Close()
for {
msg, err := sub.ReceiveMessage(ctx)
if err != nil {
return
}
var evt Event
if err := json.Unmarshal([]byte(msg.Payload), &evt); err != nil {
continue
}
select {
case ch <- evt:
case <-ctx.Done():
return
}
}
}()
return ch, nil
}
func (b *Bus) Close() error {
return b.rdb.Close()
}