WIP: Save agent roles integration work before CHORUS rebrand
- Agent roles and coordination features - Chat API integration testing - New configuration and workspace management 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
231
pubsub/pubsub.go
231
pubsub/pubsub.go
@@ -23,10 +23,12 @@ type PubSub struct {
|
||||
// Topic subscriptions
|
||||
bzzzTopic *pubsub.Topic
|
||||
antennaeTopic *pubsub.Topic
|
||||
contextTopic *pubsub.Topic
|
||||
|
||||
// Message subscriptions
|
||||
bzzzSub *pubsub.Subscription
|
||||
antennaeSub *pubsub.Subscription
|
||||
contextSub *pubsub.Subscription
|
||||
|
||||
// Dynamic topic management
|
||||
dynamicTopics map[string]*pubsub.Topic
|
||||
@@ -37,9 +39,22 @@ type PubSub struct {
|
||||
// Configuration
|
||||
bzzzTopicName string
|
||||
antennaeTopicName string
|
||||
contextTopicName string
|
||||
|
||||
// External message handler for Antennae messages
|
||||
AntennaeMessageHandler func(msg Message, from peer.ID)
|
||||
|
||||
// External message handler for Context Feedback messages
|
||||
ContextFeedbackHandler func(msg Message, from peer.ID)
|
||||
|
||||
// Hypercore-style logging
|
||||
hypercoreLog HypercoreLogger
|
||||
}
|
||||
|
||||
// HypercoreLogger interface for dependency injection
|
||||
type HypercoreLogger interface {
|
||||
AppendString(logType string, data map[string]interface{}) error
|
||||
GetStats() map[string]interface{}
|
||||
}
|
||||
|
||||
// MessageType represents different types of messages
|
||||
@@ -74,6 +89,13 @@ const (
|
||||
MentorshipResponse MessageType = "mentorship_response" // Senior role providing mentorship
|
||||
ProjectUpdate MessageType = "project_update" // Project-level status updates
|
||||
DeliverableReady MessageType = "deliverable_ready" // Notification that deliverable is complete
|
||||
|
||||
// RL Context Curator feedback messages
|
||||
FeedbackEvent MessageType = "feedback_event" // Context feedback for RL learning
|
||||
ContextRequest MessageType = "context_request" // Request context from HCFS
|
||||
ContextResponse MessageType = "context_response" // Response with context data
|
||||
ContextUsage MessageType = "context_usage" // Report context usage patterns
|
||||
ContextRelevance MessageType = "context_relevance" // Report context relevance scoring
|
||||
)
|
||||
|
||||
// Message represents a Bzzz/Antennae message
|
||||
@@ -95,12 +117,18 @@ type Message struct {
|
||||
|
||||
// NewPubSub creates a new PubSub instance for Bzzz coordination and Antennae meta-discussion
|
||||
func NewPubSub(ctx context.Context, h host.Host, bzzzTopic, antennaeTopic string) (*PubSub, error) {
|
||||
return NewPubSubWithLogger(ctx, h, bzzzTopic, antennaeTopic, nil)
|
||||
}
|
||||
|
||||
// NewPubSubWithLogger creates a new PubSub instance with hypercore logging
|
||||
func NewPubSubWithLogger(ctx context.Context, h host.Host, bzzzTopic, antennaeTopic string, logger HypercoreLogger) (*PubSub, error) {
|
||||
if bzzzTopic == "" {
|
||||
bzzzTopic = "bzzz/coordination/v1"
|
||||
}
|
||||
if antennaeTopic == "" {
|
||||
antennaeTopic = "antennae/meta-discussion/v1"
|
||||
}
|
||||
contextTopic := "bzzz/context-feedback/v1"
|
||||
|
||||
pubsubCtx, cancel := context.WithCancel(ctx)
|
||||
|
||||
@@ -123,8 +151,10 @@ func NewPubSub(ctx context.Context, h host.Host, bzzzTopic, antennaeTopic string
|
||||
cancel: cancel,
|
||||
bzzzTopicName: bzzzTopic,
|
||||
antennaeTopicName: antennaeTopic,
|
||||
contextTopicName: contextTopic,
|
||||
dynamicTopics: make(map[string]*pubsub.Topic),
|
||||
dynamicSubs: make(map[string]*pubsub.Subscription),
|
||||
hypercoreLog: logger,
|
||||
}
|
||||
|
||||
// Join static topics
|
||||
@@ -136,8 +166,9 @@ func NewPubSub(ctx context.Context, h host.Host, bzzzTopic, antennaeTopic string
|
||||
// Start message handlers
|
||||
go p.handleBzzzMessages()
|
||||
go p.handleAntennaeMessages()
|
||||
go p.handleContextFeedbackMessages()
|
||||
|
||||
fmt.Printf("📡 PubSub initialized - Bzzz: %s, Antennae: %s\n", bzzzTopic, antennaeTopic)
|
||||
fmt.Printf("📡 PubSub initialized - Bzzz: %s, Antennae: %s, Context: %s\n", bzzzTopic, antennaeTopic, contextTopic)
|
||||
return p, nil
|
||||
}
|
||||
|
||||
@@ -146,7 +177,12 @@ func (p *PubSub) SetAntennaeMessageHandler(handler func(msg Message, from peer.I
|
||||
p.AntennaeMessageHandler = handler
|
||||
}
|
||||
|
||||
// joinStaticTopics joins the main Bzzz and Antennae topics
|
||||
// SetContextFeedbackHandler sets the handler for incoming context feedback messages.
|
||||
func (p *PubSub) SetContextFeedbackHandler(handler func(msg Message, from peer.ID)) {
|
||||
p.ContextFeedbackHandler = handler
|
||||
}
|
||||
|
||||
// joinStaticTopics joins the main Bzzz, Antennae, and Context Feedback topics
|
||||
func (p *PubSub) joinStaticTopics() error {
|
||||
// Join Bzzz coordination topic
|
||||
bzzzTopic, err := p.ps.Join(p.bzzzTopicName)
|
||||
@@ -174,6 +210,19 @@ func (p *PubSub) joinStaticTopics() error {
|
||||
}
|
||||
p.antennaeSub = antennaeSub
|
||||
|
||||
// Join Context Feedback topic
|
||||
contextTopic, err := p.ps.Join(p.contextTopicName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to join Context Feedback topic: %w", err)
|
||||
}
|
||||
p.contextTopic = contextTopic
|
||||
|
||||
contextSub, err := contextTopic.Subscribe()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to subscribe to Context Feedback topic: %w", err)
|
||||
}
|
||||
p.contextSub = contextSub
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -332,6 +381,23 @@ func (p *PubSub) PublishAntennaeMessage(msgType MessageType, data map[string]int
|
||||
return p.antennaeTopic.Publish(p.ctx, msgBytes)
|
||||
}
|
||||
|
||||
// PublishContextFeedbackMessage publishes a message to the Context Feedback topic
|
||||
func (p *PubSub) PublishContextFeedbackMessage(msgType MessageType, data map[string]interface{}) error {
|
||||
msg := Message{
|
||||
Type: msgType,
|
||||
From: p.host.ID().String(),
|
||||
Timestamp: time.Now(),
|
||||
Data: data,
|
||||
}
|
||||
|
||||
msgBytes, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal context feedback message: %w", err)
|
||||
}
|
||||
|
||||
return p.contextTopic.Publish(p.ctx, msgBytes)
|
||||
}
|
||||
|
||||
// PublishRoleBasedMessage publishes a role-based collaboration message
|
||||
func (p *PubSub) PublishRoleBasedMessage(msgType MessageType, data map[string]interface{}, opts MessageOptions) error {
|
||||
msg := Message{
|
||||
@@ -366,6 +432,11 @@ func (p *PubSub) PublishRoleBasedMessage(msgType MessageType, data map[string]in
|
||||
return topic.Publish(p.ctx, msgBytes)
|
||||
}
|
||||
|
||||
// GetHypercoreLog returns the hypercore logger for external access
|
||||
func (p *PubSub) GetHypercoreLog() HypercoreLogger {
|
||||
return p.hypercoreLog
|
||||
}
|
||||
|
||||
// MessageOptions holds options for role-based messages
|
||||
type MessageOptions struct {
|
||||
FromRole string
|
||||
@@ -432,6 +503,36 @@ func (p *PubSub) handleAntennaeMessages() {
|
||||
}
|
||||
}
|
||||
|
||||
// handleContextFeedbackMessages processes incoming context feedback messages
|
||||
func (p *PubSub) handleContextFeedbackMessages() {
|
||||
for {
|
||||
msg, err := p.contextSub.Next(p.ctx)
|
||||
if err != nil {
|
||||
if p.ctx.Err() != nil {
|
||||
return // Context cancelled
|
||||
}
|
||||
fmt.Printf("❌ Error receiving Context Feedback message: %v\n", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if msg.ReceivedFrom == p.host.ID() {
|
||||
continue
|
||||
}
|
||||
|
||||
var contextMsg Message
|
||||
if err := json.Unmarshal(msg.Data, &contextMsg); err != nil {
|
||||
fmt.Printf("❌ Failed to unmarshal Context Feedback message: %v\n", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if p.ContextFeedbackHandler != nil {
|
||||
p.ContextFeedbackHandler(contextMsg, msg.ReceivedFrom)
|
||||
} else {
|
||||
p.processContextFeedbackMessage(contextMsg, msg.ReceivedFrom)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handleDynamicMessages processes messages from a dynamic topic subscription
|
||||
func (p *PubSub) handleDynamicMessages(sub *pubsub.Subscription) {
|
||||
for {
|
||||
@@ -464,12 +565,132 @@ func (p *PubSub) handleDynamicMessages(sub *pubsub.Subscription) {
|
||||
// processBzzzMessage handles different types of Bzzz coordination messages
|
||||
func (p *PubSub) processBzzzMessage(msg Message, from peer.ID) {
|
||||
fmt.Printf("🐝 Bzzz [%s] from %s: %v\n", msg.Type, from.ShortString(), msg.Data)
|
||||
|
||||
// Log to hypercore if logger is available
|
||||
if p.hypercoreLog != nil {
|
||||
logData := map[string]interface{}{
|
||||
"message_type": string(msg.Type),
|
||||
"from_peer": from.String(),
|
||||
"from_short": from.ShortString(),
|
||||
"timestamp": msg.Timestamp,
|
||||
"data": msg.Data,
|
||||
"topic": "bzzz",
|
||||
}
|
||||
|
||||
// Map pubsub message types to hypercore log types
|
||||
var logType string
|
||||
switch msg.Type {
|
||||
case TaskAnnouncement:
|
||||
logType = "task_announced"
|
||||
case TaskClaim:
|
||||
logType = "task_claimed"
|
||||
case TaskProgress:
|
||||
logType = "task_progress"
|
||||
case TaskComplete:
|
||||
logType = "task_completed"
|
||||
case CapabilityBcast:
|
||||
logType = "capability_broadcast"
|
||||
case AvailabilityBcast:
|
||||
logType = "network_event"
|
||||
default:
|
||||
logType = "network_event"
|
||||
}
|
||||
|
||||
if err := p.hypercoreLog.AppendString(logType, logData); err != nil {
|
||||
fmt.Printf("❌ Failed to log Bzzz message to hypercore: %v\n", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// processAntennaeMessage provides default handling for Antennae messages if no external handler is set
|
||||
func (p *PubSub) processAntennaeMessage(msg Message, from peer.ID) {
|
||||
fmt.Printf("🎯 Default Antennae Handler [%s] from %s: %v\n",
|
||||
msg.Type, from.ShortString(), msg.Data)
|
||||
|
||||
// Log to hypercore if logger is available
|
||||
if p.hypercoreLog != nil {
|
||||
logData := map[string]interface{}{
|
||||
"message_type": string(msg.Type),
|
||||
"from_peer": from.String(),
|
||||
"from_short": from.ShortString(),
|
||||
"timestamp": msg.Timestamp,
|
||||
"data": msg.Data,
|
||||
"topic": "antennae",
|
||||
"from_role": msg.FromRole,
|
||||
"to_roles": msg.ToRoles,
|
||||
"required_expertise": msg.RequiredExpertise,
|
||||
"project_id": msg.ProjectID,
|
||||
"priority": msg.Priority,
|
||||
"thread_id": msg.ThreadID,
|
||||
}
|
||||
|
||||
// Map pubsub message types to hypercore log types
|
||||
var logType string
|
||||
switch msg.Type {
|
||||
case MetaDiscussion, TaskHelpRequest, TaskHelpResponse:
|
||||
logType = "collaboration"
|
||||
case CoordinationRequest, CoordinationComplete:
|
||||
logType = "collaboration"
|
||||
case DependencyAlert:
|
||||
logType = "collaboration"
|
||||
case EscalationTrigger:
|
||||
logType = "escalation"
|
||||
case RoleAnnouncement, ExpertiseRequest, ExpertiseResponse:
|
||||
logType = "collaboration"
|
||||
case StatusUpdate, WorkAllocation, RoleCollaboration:
|
||||
logType = "collaboration"
|
||||
case MentorshipRequest, MentorshipResponse:
|
||||
logType = "collaboration"
|
||||
case ProjectUpdate, DeliverableReady:
|
||||
logType = "collaboration"
|
||||
default:
|
||||
logType = "collaboration"
|
||||
}
|
||||
|
||||
if err := p.hypercoreLog.AppendString(logType, logData); err != nil {
|
||||
fmt.Printf("❌ Failed to log Antennae message to hypercore: %v\n", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// processContextFeedbackMessage provides default handling for context feedback messages if no external handler is set
|
||||
func (p *PubSub) processContextFeedbackMessage(msg Message, from peer.ID) {
|
||||
fmt.Printf("🧠 Context Feedback [%s] from %s: %v\n",
|
||||
msg.Type, from.ShortString(), msg.Data)
|
||||
|
||||
// Log to hypercore if logger is available
|
||||
if p.hypercoreLog != nil {
|
||||
logData := map[string]interface{}{
|
||||
"message_type": string(msg.Type),
|
||||
"from_peer": from.String(),
|
||||
"from_short": from.ShortString(),
|
||||
"timestamp": msg.Timestamp,
|
||||
"data": msg.Data,
|
||||
"topic": "context_feedback",
|
||||
"from_role": msg.FromRole,
|
||||
"to_roles": msg.ToRoles,
|
||||
"project_id": msg.ProjectID,
|
||||
"priority": msg.Priority,
|
||||
"thread_id": msg.ThreadID,
|
||||
}
|
||||
|
||||
// Map context feedback message types to hypercore log types
|
||||
var logType string
|
||||
switch msg.Type {
|
||||
case FeedbackEvent:
|
||||
logType = "context_feedback"
|
||||
case ContextRequest, ContextResponse:
|
||||
logType = "context_request"
|
||||
case ContextUsage, ContextRelevance:
|
||||
logType = "context_usage"
|
||||
default:
|
||||
logType = "context_feedback"
|
||||
}
|
||||
|
||||
if err := p.hypercoreLog.AppendString(logType, logData); err != nil {
|
||||
fmt.Printf("❌ Failed to log Context Feedback message to hypercore: %v\n", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close shuts down the PubSub instance
|
||||
@@ -482,6 +703,9 @@ func (p *PubSub) Close() error {
|
||||
if p.antennaeSub != nil {
|
||||
p.antennaeSub.Cancel()
|
||||
}
|
||||
if p.contextSub != nil {
|
||||
p.contextSub.Cancel()
|
||||
}
|
||||
|
||||
if p.bzzzTopic != nil {
|
||||
p.bzzzTopic.Close()
|
||||
@@ -489,6 +713,9 @@ func (p *PubSub) Close() error {
|
||||
if p.antennaeTopic != nil {
|
||||
p.antennaeTopic.Close()
|
||||
}
|
||||
if p.contextTopic != nil {
|
||||
p.contextTopic.Close()
|
||||
}
|
||||
|
||||
p.dynamicTopicsMux.Lock()
|
||||
for _, topic := range p.dynamicTopics {
|
||||
|
||||
Reference in New Issue
Block a user