collab

package
v0.4.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 16, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Index

Constants

View Source
const (
	RelationReportsTo = "reports_to"
	RelationReviews   = "reviews"
	RelationHandoff   = "handoff"
	RelationPeer      = "peer"
)

Graph edge relation kinds for swarm topology.

View Source
const (
	AgentStatusActive       = "active"
	AgentStatusIdle         = "idle"
	AgentStatusDisconnected = "disconnected"
)

AgentStatus constants

View Source
const (
	MessageTypeDirect    = "direct"
	MessageTypeBroadcast = "broadcast"
	MessageTypeSystem    = "system"
)

MessageType constants

View Source
const (
	ChangeTypeCreated  = "created"
	ChangeTypeModified = "modified"
	ChangeTypeDeleted  = "deleted"
)

ChangeType constants

View Source
const (
	WSMessageTypeAgentJoined    = "agent_joined"
	WSMessageTypeAgentLeft      = "agent_left"
	WSMessageTypeMessage        = "message"
	WSMessageTypeFileChanged    = "file_changed"
	WSMessageTypePresenceUpdate = "presence_update"
	WSMessageTypePing           = "ping"
	WSMessageTypePong           = "pong"
)

WSMessageType constants

View Source
const (
	MaxAgentIDLength    = 64
	MaxAgentNameLength  = 200
	MaxMessageBytes     = 64 * 1024 // 64 KB
	MaxFilePathLength   = 4096
	MaxAgentsPerSession = 32
)

Limits on agent-supplied values. Agent IDs become part of Redis key names and a Postgres unique key, so they are the most tightly constrained.

Variables

View Source
var (
	ErrAgentNotFound    = errors.New("agent not found")
	ErrSessionNotFound  = errors.New("session not found")
	ErrSessionNotCollab = errors.New("session does not allow collaboration")
	ErrMaxAgentsReached = errors.New("maximum agents reached for session")
)
View Source
var ErrGraphEdgeLimit = errors.New("graph edge limit reached")

ErrGraphEdgeLimit is returned when a session has too many edges.

View Source
var ErrGraphEdgeNotFound = errors.New("graph edge not found")

ErrGraphEdgeNotFound is returned when an edge cannot be deleted.

View Source
var ErrInvalidInput = errors.New("invalid input")

ErrInvalidInput wraps every validation failure in this package so that HTTP handlers can answer 400 instead of turning a caller's mistake into a 500.

Functions

func ValidateAgentID added in v0.3.1

func ValidateAgentID(agentID string) error

ValidateAgentID checks an agent identifier before it is used in a Redis key or stored as part of the (session_id, agent_id) unique constraint.

func ValidateAgentName added in v0.3.1

func ValidateAgentName(name string) error

ValidateAgentName checks the human-readable agent name. Names are only ever displayed, so the constraint is length and valid UTF-8 rather than charset.

func ValidateAgentStatus added in v0.3.1

func ValidateAgentStatus(status string) error

ValidateAgentStatus rejects unknown presence states.

func ValidateFilePath added in v0.3.1

func ValidateFilePath(path string) error

ValidateFilePath bounds the presence "current file" field. The value is informational — it is never opened — so only length and encoding matter.

func ValidateGraphRelation added in v0.3.2

func ValidateGraphRelation(relation string) error

ValidateGraphRelation restricts swarm edge kinds.

func ValidateMaxAgents added in v0.3.1

func ValidateMaxAgents(maxAgents int) error

ValidateMaxAgents bounds the per-session agent cap. Each agent holds a WebSocket connection and two goroutines, so an unbounded value is a resource-exhaustion vector.

func ValidateMessageBody added in v0.3.1

func ValidateMessageBody(body string) error

ValidateMessageBody bounds a message before it is written to Postgres and broadcast to every connected agent. Without a bound, one agent can exhaust the message table and saturate every peer's send buffer.

func ValidateMessageType added in v0.3.1

func ValidateMessageType(msgType string) error

ValidateMessageType rejects unknown types so that a client cannot invent a type that downstream consumers mishandle.

Types

type Agent

type Agent struct {
	ID           string    `json:"id"`           // Agent identifier (e.g., "agent_a")
	Name         string    `json:"name"`         // Human-readable name
	SessionID    uuid.UUID `json:"session_id"`   // Session this agent is connected to
	Status       string    `json:"status"`       // "active", "idle", "disconnected"
	CurrentFile  string    `json:"current_file"` // File currently being edited (nullable)
	LastActivity time.Time `json:"last_activity"`
	ConnectedAt  time.Time `json:"connected_at"`
}

Agent represents a connected agent in a collaborative session

type AgentGraph added in v0.3.2

type AgentGraph struct {
	SessionID uuid.UUID   `json:"session_id"`
	Agents    []Agent     `json:"agents"`
	Edges     []GraphEdge `json:"edges"`
}

AgentGraph is the swarm topology snapshot for a session.

type AgentJoinedPayload

type AgentJoinedPayload struct {
	Agent Agent `json:"agent"`
}

AgentJoinedPayload is sent when an agent joins

type AgentLeftPayload

type AgentLeftPayload struct {
	AgentID   string    `json:"agent_id"`
	Timestamp time.Time `json:"timestamp"`
}

AgentLeftPayload is sent when an agent disconnects

type Client

type Client struct {
	SessionID uuid.UUID
	AgentID   string
	AgentName string
	Conn      *websocket.Conn
	Manager   *Manager
	// contains filtered or unexported fields
}

Client represents a WebSocket client (agent connection)

func NewClient

func NewClient(sessionID uuid.UUID, agentID, agentName string, conn *websocket.Conn, manager *Manager) *Client

NewClient creates a new WebSocket client

func (*Client) ReadPump

func (c *Client) ReadPump(ctx context.Context)

ReadPump reads messages from the WebSocket connection

func (*Client) Send

func (c *Client) Send(message []byte)

Send queues a message to be sent to the client

func (*Client) WritePump

func (c *Client) WritePump(ctx context.Context)

WritePump sends messages to the WebSocket connection

type FileChange

type FileChange struct {
	SessionID  uuid.UUID `json:"session_id"`
	File       string    `json:"file"`
	ChangedBy  string    `json:"changed_by"`  // Agent ID
	ChangeType string    `json:"change_type"` // "created", "modified", "deleted"
	Version    int       `json:"version"`     // Incremental version number
	Timestamp  time.Time `json:"timestamp"`
}

FileChange represents a file modification event

type FileChangedPayload

type FileChangedPayload struct {
	Change FileChange `json:"change"`
}

FileChangedPayload is sent when a file is modified

type GraphEdge added in v0.3.2

type GraphEdge struct {
	ID        uuid.UUID              `db:"id" json:"id"`
	SessionID uuid.UUID              `db:"session_id" json:"session_id"`
	FromAgent string                 `db:"from_agent" json:"from_agent"`
	ToAgent   string                 `db:"to_agent" json:"to_agent"`
	Relation  string                 `db:"relation" json:"relation"`
	Label     string                 `db:"label" json:"label"`
	Metadata  map[string]interface{} `db:"-" json:"metadata,omitempty"`
	CreatedAt time.Time              `db:"created_at" json:"created_at"`
}

GraphEdge is a directed relation between two agents in a session.

type Hub

type Hub struct {
	Manager *Manager
	// contains filtered or unexported fields
}

Hub manages all active WebSocket connections

func NewHub

func NewHub(manager *Manager) *Hub

NewHub creates a new WebSocket hub

func (*Hub) BroadcastToSession

func (h *Hub) BroadcastToSession(sessionID uuid.UUID, message []byte)

BroadcastToSession sends a message to all clients in a session

func (*Hub) RegisterClient

func (h *Hub) RegisterClient(client *Client)

RegisterClient registers a new WebSocket client

func (*Hub) Run

func (h *Hub) Run(ctx context.Context)

Run starts the hub

func (*Hub) UnregisterClient

func (h *Hub) UnregisterClient(client *Client)

UnregisterClient unregisters a WebSocket client

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager handles multi-agent collaboration

func New

func New(db *sqlx.DB, redisClient *redis.Client) *Manager

New creates a new collaboration manager

func (*Manager) AddGraphEdge added in v0.3.2

func (m *Manager) AddGraphEdge(ctx context.Context, sessionID uuid.UUID, from, to, relation, label string, metadata map[string]interface{}) (*GraphEdge, error)

AddGraphEdge upserts a directed edge in the session swarm graph.

func (*Manager) GetActiveAgents

func (m *Manager) GetActiveAgents(ctx context.Context, sessionID uuid.UUID) ([]Agent, error)

GetActiveAgents returns all active agents for a session

func (*Manager) GetAgentGraph added in v0.3.2

func (m *Manager) GetAgentGraph(ctx context.Context, sessionID uuid.UUID) (*AgentGraph, error)

GetAgentGraph returns active agents plus topology edges.

func (*Manager) GetFileVersion

func (m *Manager) GetFileVersion(ctx context.Context, sessionID uuid.UUID, filePath string) (int, error)

GetFileVersion returns the current version of a file

func (*Manager) GetMessages

func (m *Manager) GetMessages(ctx context.Context, sessionID uuid.UUID, limit int) ([]Message, error)

GetMessages retrieves recent messages for a session

func (*Manager) IsAgentActive added in v0.3.2

func (m *Manager) IsAgentActive(ctx context.Context, sessionID uuid.UUID, agentID string) (bool, error)

IsAgentActive reports whether an agent currently holds a slot in a session.

Membership lives in Redis rather than session_agents because that table keeps disconnected agents for the audit trail; only the Redis set answers "who is connected right now".

func (*Manager) JoinSession

func (m *Manager) JoinSession(ctx context.Context, sessionID uuid.UUID, agentID, agentName string) (*Agent, error)

JoinSession registers an agent as active in a session

func (*Manager) LeaveSession

func (m *Manager) LeaveSession(ctx context.Context, sessionID uuid.UUID, agentID string) error

LeaveSession removes an agent from a session

func (*Manager) ListGraphEdges added in v0.3.2

func (m *Manager) ListGraphEdges(ctx context.Context, sessionID uuid.UUID) ([]GraphEdge, error)

ListGraphEdges returns all edges for a session.

func (*Manager) RecordFileChange

func (m *Manager) RecordFileChange(ctx context.Context, sessionID uuid.UUID, filePath, agentID, changeType, checksum string, sizeBytes int64) (*FileChange, error)

RecordFileChange records a file modification

func (*Manager) RemoveGraphEdge added in v0.3.2

func (m *Manager) RemoveGraphEdge(ctx context.Context, sessionID, edgeID uuid.UUID) error

RemoveGraphEdge deletes an edge by ID within a session.

func (*Manager) SendMessage

func (m *Manager) SendMessage(ctx context.Context, sessionID uuid.UUID, from, to, body string, msgType string) (*Message, error)

SendMessage sends a message from one agent to another (or broadcast)

func (*Manager) SubscribeToEvents

func (m *Manager) SubscribeToEvents(ctx context.Context, sessionID uuid.UUID) *redis.PubSub

SubscribeToEvents subscribes to session events

func (*Manager) UpdatePresence

func (m *Manager) UpdatePresence(ctx context.Context, sessionID uuid.UUID, agentID string, currentFile string, status string) error

UpdatePresence updates an agent's presence (current file, status)

type Message

type Message struct {
	ID        uuid.UUID              `json:"id"`
	SessionID uuid.UUID              `json:"session_id"`
	Type      string                 `json:"type"` // "direct", "broadcast", "system"
	From      string                 `json:"from"` // Agent ID
	To        string                 `json:"to"`   // Agent ID (empty for broadcast)
	Body      string                 `json:"body"`
	Metadata  map[string]interface{} `json:"metadata,omitempty"`
	Timestamp time.Time              `json:"timestamp"`
}

Message represents a message between agents

type MessagePayload

type MessagePayload struct {
	Message Message `json:"message"`
}

MessagePayload wraps a message

type PresenceUpdatePayload

type PresenceUpdatePayload struct {
	AgentID     string    `json:"agent_id"`
	Status      string    `json:"status"`
	CurrentFile string    `json:"current_file"`
	Timestamp   time.Time `json:"timestamp"`
}

PresenceUpdatePayload is sent when agent presence changes

type WSMessage

type WSMessage struct {
	Type    string      `json:"type"` // "agent_joined", "agent_left", "message", "file_changed", "presence_update"
	Payload interface{} `json:"payload"`
}

WSMessage is the wrapper for all WebSocket messages

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL