Compare commits
2 Commits
e94df4be6b
...
f2dd0e8d6d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f2dd0e8d6d | ||
|
|
81b473d48f |
@@ -1,4 +1,4 @@
|
|||||||
FROM golang:1.21-alpine AS builder
|
FROM golang:1.23-alpine AS builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY go.mod go.sum ./
|
COPY go.mod go.sum ./
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/anthonyrawlins/bzzz/logging"
|
"github.com/anthonyrawlins/bzzz/logging"
|
||||||
|
"github.com/anthonyrawlins/bzzz/pkg/config"
|
||||||
"github.com/anthonyrawlins/bzzz/pkg/types"
|
"github.com/anthonyrawlins/bzzz/pkg/types"
|
||||||
"github.com/anthonyrawlins/bzzz/reasoning"
|
"github.com/anthonyrawlins/bzzz/reasoning"
|
||||||
"github.com/anthonyrawlins/bzzz/sandbox"
|
"github.com/anthonyrawlins/bzzz/sandbox"
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/anthonyrawlins/bzzz/executor"
|
"github.com/anthonyrawlins/bzzz/executor"
|
||||||
"github.com/anthonyrawlins/bzzz/logging"
|
"github.com/anthonyrawlins/bzzz/logging"
|
||||||
|
"github.com/anthonyrawlins/bzzz/pkg/config"
|
||||||
"github.com/anthonyrawlins/bzzz/pkg/hive"
|
"github.com/anthonyrawlins/bzzz/pkg/hive"
|
||||||
"github.com/anthonyrawlins/bzzz/pkg/types"
|
"github.com/anthonyrawlins/bzzz/pkg/types"
|
||||||
"github.com/anthonyrawlins/bzzz/pubsub"
|
"github.com/anthonyrawlins/bzzz/pubsub"
|
||||||
|
|||||||
81
main.go
81
main.go
@@ -91,6 +91,20 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply role-based configuration if no role is set
|
||||||
|
if cfg.Agent.Role == "" {
|
||||||
|
// Determine default role based on specialization
|
||||||
|
defaultRole := getDefaultRoleForSpecialization(cfg.Agent.Specialization)
|
||||||
|
if defaultRole != "" {
|
||||||
|
fmt.Printf("🎭 Applying default role: %s\n", defaultRole)
|
||||||
|
if err := cfg.ApplyRoleDefinition(defaultRole); err != nil {
|
||||||
|
fmt.Printf("⚠️ Failed to apply role definition: %v\n", err)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("✅ Role applied: %s\n", cfg.Agent.Role)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Printf("🐝 Bzzz node started successfully\n")
|
fmt.Printf("🐝 Bzzz node started successfully\n")
|
||||||
fmt.Printf("📍 Node ID: %s\n", node.ID().ShortString())
|
fmt.Printf("📍 Node ID: %s\n", node.ID().ShortString())
|
||||||
fmt.Printf("🤖 Agent ID: %s\n", cfg.Agent.ID)
|
fmt.Printf("🤖 Agent ID: %s\n", cfg.Agent.ID)
|
||||||
@@ -120,6 +134,15 @@ func main() {
|
|||||||
}
|
}
|
||||||
defer ps.Close()
|
defer ps.Close()
|
||||||
|
|
||||||
|
// Join role-based topics if role is configured
|
||||||
|
if cfg.Agent.Role != "" {
|
||||||
|
if err := ps.JoinRoleBasedTopics(cfg.Agent.Role, cfg.Agent.Expertise, cfg.Agent.ReportsTo); err != nil {
|
||||||
|
fmt.Printf("⚠️ Failed to join role-based topics: %v\n", err)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("🎯 Joined role-based collaboration topics\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// === Hive & Dynamic Repository Integration ===
|
// === Hive & Dynamic Repository Integration ===
|
||||||
// Initialize Hive API client
|
// Initialize Hive API client
|
||||||
hiveClient := hive.NewHiveClient(cfg.HiveAPI.BaseURL, cfg.HiveAPI.APIKey)
|
hiveClient := hive.NewHiveClient(cfg.HiveAPI.BaseURL, cfg.HiveAPI.APIKey)
|
||||||
@@ -173,9 +196,10 @@ func main() {
|
|||||||
activeTasks: make(map[string]bool),
|
activeTasks: make(map[string]bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Announce capabilities
|
// Announce capabilities and role
|
||||||
go announceAvailability(ps, node.ID().ShortString(), taskTracker)
|
go announceAvailability(ps, node.ID().ShortString(), taskTracker)
|
||||||
go announceCapabilitiesOnChange(ps, node.ID().ShortString(), cfg)
|
go announceCapabilitiesOnChange(ps, node.ID().ShortString(), cfg)
|
||||||
|
go announceRoleOnStartup(ps, node.ID().ShortString(), cfg)
|
||||||
|
|
||||||
// Start status reporting
|
// Start status reporting
|
||||||
go statusReporter(node)
|
go statusReporter(node)
|
||||||
@@ -468,3 +492,58 @@ func getChangeReason(current, stored map[string]interface{}) string {
|
|||||||
|
|
||||||
return "unknown_change"
|
return "unknown_change"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getDefaultRoleForSpecialization maps specializations to default roles
|
||||||
|
func getDefaultRoleForSpecialization(specialization string) string {
|
||||||
|
roleMap := map[string]string{
|
||||||
|
"code_generation": "backend_developer",
|
||||||
|
"advanced_reasoning": "senior_software_architect",
|
||||||
|
"code_analysis": "security_expert",
|
||||||
|
"general_developer": "full_stack_engineer",
|
||||||
|
"debugging": "qa_engineer",
|
||||||
|
"frontend": "frontend_developer",
|
||||||
|
"backend": "backend_developer",
|
||||||
|
"devops": "devops_engineer",
|
||||||
|
"security": "security_expert",
|
||||||
|
"design": "ui_ux_designer",
|
||||||
|
"architecture": "senior_software_architect",
|
||||||
|
}
|
||||||
|
|
||||||
|
if role, exists := roleMap[specialization]; exists {
|
||||||
|
return role
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default fallback
|
||||||
|
return "full_stack_engineer"
|
||||||
|
}
|
||||||
|
|
||||||
|
// announceRoleOnStartup announces the agent's role when starting up
|
||||||
|
func announceRoleOnStartup(ps *pubsub.PubSub, nodeID string, cfg *config.Config) {
|
||||||
|
if cfg.Agent.Role == "" {
|
||||||
|
return // No role to announce
|
||||||
|
}
|
||||||
|
|
||||||
|
roleData := map[string]interface{}{
|
||||||
|
"node_id": nodeID,
|
||||||
|
"role": cfg.Agent.Role,
|
||||||
|
"expertise": cfg.Agent.Expertise,
|
||||||
|
"reports_to": cfg.Agent.ReportsTo,
|
||||||
|
"deliverables": cfg.Agent.Deliverables,
|
||||||
|
"capabilities": cfg.Agent.Capabilities,
|
||||||
|
"specialization": cfg.Agent.Specialization,
|
||||||
|
"timestamp": time.Now().Unix(),
|
||||||
|
"status": "online",
|
||||||
|
}
|
||||||
|
|
||||||
|
opts := pubsub.MessageOptions{
|
||||||
|
FromRole: cfg.Agent.Role,
|
||||||
|
RequiredExpertise: cfg.Agent.Expertise,
|
||||||
|
Priority: "medium",
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ps.PublishRoleBasedMessage(pubsub.RoleAnnouncement, roleData, opts); err != nil {
|
||||||
|
fmt.Printf("❌ Failed to announce role: %v\n", err)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("📢 Role announced: %s\n", cfg.Agent.Role)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,6 +27,17 @@ type HiveAPIConfig struct {
|
|||||||
RetryCount int `yaml:"retry_count"`
|
RetryCount int `yaml:"retry_count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CollaborationConfig holds role-based collaboration settings
|
||||||
|
type CollaborationConfig struct {
|
||||||
|
PreferredMessageTypes []string `yaml:"preferred_message_types"`
|
||||||
|
AutoSubscribeToRoles []string `yaml:"auto_subscribe_to_roles"`
|
||||||
|
AutoSubscribeToExpertise []string `yaml:"auto_subscribe_to_expertise"`
|
||||||
|
ResponseTimeoutSeconds int `yaml:"response_timeout_seconds"`
|
||||||
|
MaxCollaborationDepth int `yaml:"max_collaboration_depth"`
|
||||||
|
EscalationThreshold int `yaml:"escalation_threshold"`
|
||||||
|
CustomTopicSubscriptions []string `yaml:"custom_topic_subscriptions"`
|
||||||
|
}
|
||||||
|
|
||||||
// AgentConfig holds agent-specific configuration
|
// AgentConfig holds agent-specific configuration
|
||||||
type AgentConfig struct {
|
type AgentConfig struct {
|
||||||
ID string `yaml:"id"`
|
ID string `yaml:"id"`
|
||||||
@@ -38,6 +49,16 @@ type AgentConfig struct {
|
|||||||
ModelSelectionWebhook string `yaml:"model_selection_webhook"`
|
ModelSelectionWebhook string `yaml:"model_selection_webhook"`
|
||||||
DefaultReasoningModel string `yaml:"default_reasoning_model"`
|
DefaultReasoningModel string `yaml:"default_reasoning_model"`
|
||||||
SandboxImage string `yaml:"sandbox_image"`
|
SandboxImage string `yaml:"sandbox_image"`
|
||||||
|
|
||||||
|
// Role-based configuration from Bees-AgenticWorkers
|
||||||
|
Role string `yaml:"role"`
|
||||||
|
SystemPrompt string `yaml:"system_prompt"`
|
||||||
|
ReportsTo []string `yaml:"reports_to"`
|
||||||
|
Expertise []string `yaml:"expertise"`
|
||||||
|
Deliverables []string `yaml:"deliverables"`
|
||||||
|
|
||||||
|
// Role-based collaboration settings
|
||||||
|
CollaborationSettings CollaborationConfig `yaml:"collaboration"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GitHubConfig holds GitHub integration settings
|
// GitHubConfig holds GitHub integration settings
|
||||||
|
|||||||
332
pkg/config/roles.go
Normal file
332
pkg/config/roles.go
Normal file
@@ -0,0 +1,332 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RoleDefinition represents a complete role definition from Bees-AgenticWorkers
|
||||||
|
type RoleDefinition struct {
|
||||||
|
Name string `yaml:"name"`
|
||||||
|
SystemPrompt string `yaml:"system_prompt"`
|
||||||
|
ReportsTo []string `yaml:"reports_to"`
|
||||||
|
Expertise []string `yaml:"expertise"`
|
||||||
|
Deliverables []string `yaml:"deliverables"`
|
||||||
|
Capabilities []string `yaml:"capabilities"`
|
||||||
|
|
||||||
|
// Collaboration preferences
|
||||||
|
CollaborationDefaults CollaborationConfig `yaml:"collaboration_defaults"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPredefinedRoles returns all predefined roles from Bees-AgenticWorkers.md
|
||||||
|
func GetPredefinedRoles() map[string]RoleDefinition {
|
||||||
|
return map[string]RoleDefinition{
|
||||||
|
"senior_software_architect": {
|
||||||
|
Name: "Senior Software Architect",
|
||||||
|
SystemPrompt: "You are the **Senior Software Architect**. You define the system's overall structure, select tech stacks, and ensure long-term maintainability.\n\n* **Responsibilities:** Draft high-level architecture diagrams, define API contracts, set coding standards, mentor engineering leads.\n* **Expertise:** Deep experience in multiple programming paradigms, distributed systems, security models, and cloud architectures.\n* **Reports To:** Product Owner / Technical Director.\n* **Deliverables:** Architecture blueprints, tech stack decisions, integration strategies, and review sign-offs on major design changes.",
|
||||||
|
ReportsTo: []string{"product_owner", "technical_director"},
|
||||||
|
Expertise: []string{"architecture", "distributed_systems", "security", "cloud_architectures", "api_design"},
|
||||||
|
Deliverables: []string{"architecture_blueprints", "tech_stack_decisions", "integration_strategies", "design_reviews"},
|
||||||
|
Capabilities: []string{"task-coordination", "meta-discussion", "architecture", "code-review", "mentoring"},
|
||||||
|
CollaborationDefaults: CollaborationConfig{
|
||||||
|
PreferredMessageTypes: []string{"coordination_request", "meta_discussion", "escalation_trigger"},
|
||||||
|
AutoSubscribeToRoles: []string{"lead_designer", "security_expert", "systems_engineer"},
|
||||||
|
AutoSubscribeToExpertise: []string{"architecture", "security", "infrastructure"},
|
||||||
|
ResponseTimeoutSeconds: 300,
|
||||||
|
MaxCollaborationDepth: 5,
|
||||||
|
EscalationThreshold: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"lead_designer": {
|
||||||
|
Name: "Lead Designer",
|
||||||
|
SystemPrompt: "You are the **Lead Designer**. You guide the creative vision and maintain design cohesion across the product.\n\n* **Responsibilities:** Oversee UX flow, wireframes, and feature design; ensure consistency of theme and style; mediate between product vision and technical constraints.\n* **Expertise:** UI/UX principles, accessibility, information architecture, Figma/Sketch proficiency.\n* **Reports To:** Product Owner.\n* **Deliverables:** Style guides, wireframes, feature specs, and iterative design documentation.",
|
||||||
|
ReportsTo: []string{"product_owner"},
|
||||||
|
Expertise: []string{"ui_ux", "accessibility", "information_architecture", "design_systems", "user_research"},
|
||||||
|
Deliverables: []string{"style_guides", "wireframes", "feature_specs", "design_documentation"},
|
||||||
|
Capabilities: []string{"task-coordination", "meta-discussion", "design", "user_experience"},
|
||||||
|
CollaborationDefaults: CollaborationConfig{
|
||||||
|
PreferredMessageTypes: []string{"task_help_request", "coordination_request", "meta_discussion"},
|
||||||
|
AutoSubscribeToRoles: []string{"ui_ux_designer", "frontend_developer"},
|
||||||
|
AutoSubscribeToExpertise: []string{"design", "frontend", "user_experience"},
|
||||||
|
ResponseTimeoutSeconds: 180,
|
||||||
|
MaxCollaborationDepth: 3,
|
||||||
|
EscalationThreshold: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"security_expert": {
|
||||||
|
Name: "Security Expert",
|
||||||
|
SystemPrompt: "You are the **Security Expert**. You ensure the system is hardened against vulnerabilities.\n\n* **Responsibilities:** Conduct threat modeling, penetration tests, code reviews for security flaws, and define access control policies.\n* **Expertise:** Cybersecurity frameworks (OWASP, NIST), encryption, key management, zero-trust systems.\n* **Reports To:** Senior Software Architect.\n* **Deliverables:** Security audits, vulnerability reports, risk mitigation plans, compliance documentation.",
|
||||||
|
ReportsTo: []string{"senior_software_architect"},
|
||||||
|
Expertise: []string{"cybersecurity", "owasp", "nist", "encryption", "key_management", "zero_trust", "penetration_testing"},
|
||||||
|
Deliverables: []string{"security_audits", "vulnerability_reports", "risk_mitigation_plans", "compliance_documentation"},
|
||||||
|
Capabilities: []string{"task-coordination", "meta-discussion", "security-analysis", "code-review", "threat-modeling"},
|
||||||
|
CollaborationDefaults: CollaborationConfig{
|
||||||
|
PreferredMessageTypes: []string{"dependency_alert", "task_help_request", "escalation_trigger"},
|
||||||
|
AutoSubscribeToRoles: []string{"backend_developer", "devops_engineer", "senior_software_architect"},
|
||||||
|
AutoSubscribeToExpertise: []string{"security", "backend", "infrastructure"},
|
||||||
|
ResponseTimeoutSeconds: 120,
|
||||||
|
MaxCollaborationDepth: 4,
|
||||||
|
EscalationThreshold: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"systems_engineer": {
|
||||||
|
Name: "Systems Engineer",
|
||||||
|
SystemPrompt: "You are the **Systems Engineer**. You connect hardware, operating systems, and software infrastructure.\n\n* **Responsibilities:** Configure OS environments, network setups, and middleware; ensure system performance and uptime.\n* **Expertise:** Linux/Unix systems, networking, hardware integration, automation tools.\n* **Reports To:** Technical Lead.\n* **Deliverables:** Infrastructure configurations, system diagrams, performance benchmarks.",
|
||||||
|
ReportsTo: []string{"technical_lead"},
|
||||||
|
Expertise: []string{"linux", "unix", "networking", "hardware_integration", "automation", "system_administration"},
|
||||||
|
Deliverables: []string{"infrastructure_configurations", "system_diagrams", "performance_benchmarks"},
|
||||||
|
Capabilities: []string{"task-coordination", "meta-discussion", "infrastructure", "system_administration", "automation"},
|
||||||
|
CollaborationDefaults: CollaborationConfig{
|
||||||
|
PreferredMessageTypes: []string{"coordination_request", "dependency_alert", "task_help_request"},
|
||||||
|
AutoSubscribeToRoles: []string{"devops_engineer", "backend_developer"},
|
||||||
|
AutoSubscribeToExpertise: []string{"infrastructure", "deployment", "monitoring"},
|
||||||
|
ResponseTimeoutSeconds: 240,
|
||||||
|
MaxCollaborationDepth: 3,
|
||||||
|
EscalationThreshold: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"frontend_developer": {
|
||||||
|
Name: "Frontend Developer",
|
||||||
|
SystemPrompt: "You are the **Frontend Developer**. You turn designs into interactive interfaces.\n\n* **Responsibilities:** Build UI components, optimize performance, ensure cross-browser/device compatibility, and integrate frontend with backend APIs.\n* **Expertise:** HTML, CSS, JavaScript/TypeScript, React/Vue/Angular, accessibility standards.\n* **Reports To:** Frontend Lead or Senior Architect.\n* **Deliverables:** Functional UI screens, reusable components, and documented frontend code.",
|
||||||
|
ReportsTo: []string{"frontend_lead", "senior_software_architect"},
|
||||||
|
Expertise: []string{"html", "css", "javascript", "typescript", "react", "vue", "angular", "accessibility"},
|
||||||
|
Deliverables: []string{"ui_screens", "reusable_components", "frontend_code", "documentation"},
|
||||||
|
Capabilities: []string{"task-coordination", "meta-discussion", "frontend", "ui_development", "component_design"},
|
||||||
|
CollaborationDefaults: CollaborationConfig{
|
||||||
|
PreferredMessageTypes: []string{"task_help_request", "coordination_request", "task_help_response"},
|
||||||
|
AutoSubscribeToRoles: []string{"ui_ux_designer", "backend_developer", "lead_designer"},
|
||||||
|
AutoSubscribeToExpertise: []string{"design", "backend", "api_integration"},
|
||||||
|
ResponseTimeoutSeconds: 180,
|
||||||
|
MaxCollaborationDepth: 3,
|
||||||
|
EscalationThreshold: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"backend_developer": {
|
||||||
|
Name: "Backend Developer",
|
||||||
|
SystemPrompt: "You are the **Backend Developer**. You create APIs, logic, and server-side integrations.\n\n* **Responsibilities:** Implement core logic, manage data pipelines, enforce security, and support scaling strategies.\n* **Expertise:** Server frameworks, REST/GraphQL APIs, authentication, caching, microservices.\n* **Reports To:** Backend Lead or Senior Architect.\n* **Deliverables:** API endpoints, backend services, unit tests, and deployment-ready server code.",
|
||||||
|
ReportsTo: []string{"backend_lead", "senior_software_architect"},
|
||||||
|
Expertise: []string{"server_frameworks", "rest_api", "graphql", "authentication", "caching", "microservices", "databases"},
|
||||||
|
Deliverables: []string{"api_endpoints", "backend_services", "unit_tests", "server_code"},
|
||||||
|
Capabilities: []string{"task-coordination", "meta-discussion", "backend", "api_development", "database_design"},
|
||||||
|
CollaborationDefaults: CollaborationConfig{
|
||||||
|
PreferredMessageTypes: []string{"task_help_request", "coordination_request", "dependency_alert"},
|
||||||
|
AutoSubscribeToRoles: []string{"database_engineer", "frontend_developer", "security_expert"},
|
||||||
|
AutoSubscribeToExpertise: []string{"database", "frontend", "security"},
|
||||||
|
ResponseTimeoutSeconds: 200,
|
||||||
|
MaxCollaborationDepth: 4,
|
||||||
|
EscalationThreshold: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"qa_engineer": {
|
||||||
|
Name: "QA Engineer",
|
||||||
|
SystemPrompt: "You are the **QA Engineer**. You ensure the system is reliable and bug-free.\n\n* **Responsibilities:** Create test plans, execute manual and automated tests, document bugs, and verify fixes.\n* **Expertise:** QA methodologies, Selenium/Cypress, regression testing, performance testing.\n* **Reports To:** QA Lead.\n* **Deliverables:** Test scripts, bug reports, QA coverage metrics, and sign-off on release quality.",
|
||||||
|
ReportsTo: []string{"qa_lead"},
|
||||||
|
Expertise: []string{"qa_methodologies", "selenium", "cypress", "regression_testing", "performance_testing", "test_automation"},
|
||||||
|
Deliverables: []string{"test_scripts", "bug_reports", "qa_metrics", "release_signoff"},
|
||||||
|
Capabilities: []string{"task-coordination", "meta-discussion", "testing", "quality_assurance", "test_automation"},
|
||||||
|
CollaborationDefaults: CollaborationConfig{
|
||||||
|
PreferredMessageTypes: []string{"task_help_request", "dependency_alert", "coordination_complete"},
|
||||||
|
AutoSubscribeToRoles: []string{"frontend_developer", "backend_developer", "devops_engineer"},
|
||||||
|
AutoSubscribeToExpertise: []string{"testing", "deployment", "automation"},
|
||||||
|
ResponseTimeoutSeconds: 150,
|
||||||
|
MaxCollaborationDepth: 3,
|
||||||
|
EscalationThreshold: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"ui_ux_designer": {
|
||||||
|
Name: "UI/UX Designer",
|
||||||
|
SystemPrompt: "You are the **UI/UX Designer**. You shape how users interact with the product.\n\n* **Responsibilities:** Produce wireframes, prototypes, and design systems; ensure user flows are intuitive.\n* **Expertise:** Human-computer interaction, usability testing, Figma/Sketch, accessibility.\n* **Reports To:** Lead Designer.\n* **Deliverables:** Interactive prototypes, annotated mockups, and updated design documentation.",
|
||||||
|
ReportsTo: []string{"lead_designer"},
|
||||||
|
Expertise: []string{"human_computer_interaction", "usability_testing", "figma", "sketch", "accessibility", "user_flows"},
|
||||||
|
Deliverables: []string{"interactive_prototypes", "annotated_mockups", "design_documentation"},
|
||||||
|
Capabilities: []string{"task-coordination", "meta-discussion", "design", "prototyping", "user_research"},
|
||||||
|
CollaborationDefaults: CollaborationConfig{
|
||||||
|
PreferredMessageTypes: []string{"task_help_request", "coordination_request", "meta_discussion"},
|
||||||
|
AutoSubscribeToRoles: []string{"frontend_developer", "lead_designer"},
|
||||||
|
AutoSubscribeToExpertise: []string{"frontend", "design", "user_experience"},
|
||||||
|
ResponseTimeoutSeconds: 180,
|
||||||
|
MaxCollaborationDepth: 3,
|
||||||
|
EscalationThreshold: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"ml_engineer": {
|
||||||
|
Name: "ML Engineer",
|
||||||
|
SystemPrompt: "You are the **Machine Learning Engineer**. You design, train, and integrate AI models into the product.\n\n* **Responsibilities:** Build pipelines, preprocess data, evaluate models, and deploy ML solutions.\n* **Expertise:** Python, TensorFlow/PyTorch, data engineering, model optimization.\n* **Reports To:** Senior Software Architect or Product Owner (depending on AI strategy).\n* **Deliverables:** Trained models, inference APIs, documentation of datasets and performance metrics.",
|
||||||
|
ReportsTo: []string{"senior_software_architect", "product_owner"},
|
||||||
|
Expertise: []string{"python", "tensorflow", "pytorch", "data_engineering", "model_optimization", "machine_learning"},
|
||||||
|
Deliverables: []string{"trained_models", "inference_apis", "dataset_documentation", "performance_metrics"},
|
||||||
|
Capabilities: []string{"task-coordination", "meta-discussion", "machine_learning", "data_analysis", "model_deployment"},
|
||||||
|
CollaborationDefaults: CollaborationConfig{
|
||||||
|
PreferredMessageTypes: []string{"task_help_request", "coordination_request", "meta_discussion"},
|
||||||
|
AutoSubscribeToRoles: []string{"backend_developer", "database_engineer", "devops_engineer"},
|
||||||
|
AutoSubscribeToExpertise: []string{"backend", "database", "deployment"},
|
||||||
|
ResponseTimeoutSeconds: 300,
|
||||||
|
MaxCollaborationDepth: 4,
|
||||||
|
EscalationThreshold: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"devops_engineer": {
|
||||||
|
Name: "DevOps Engineer",
|
||||||
|
SystemPrompt: "You are the **DevOps Engineer**. You automate and maintain build, deployment, and monitoring systems.\n\n* **Responsibilities:** Manage CI/CD pipelines, infrastructure as code, observability, and rollback strategies.\n* **Expertise:** Docker, Kubernetes, Terraform, GitHub Actions/Jenkins, cloud providers.\n* **Reports To:** Systems Engineer or Senior Architect.\n* **Deliverables:** CI/CD configurations, monitoring dashboards, and operational runbooks.",
|
||||||
|
ReportsTo: []string{"systems_engineer", "senior_software_architect"},
|
||||||
|
Expertise: []string{"docker", "kubernetes", "terraform", "cicd", "github_actions", "jenkins", "cloud_providers", "monitoring"},
|
||||||
|
Deliverables: []string{"cicd_configurations", "monitoring_dashboards", "operational_runbooks"},
|
||||||
|
Capabilities: []string{"task-coordination", "meta-discussion", "deployment", "automation", "monitoring", "infrastructure"},
|
||||||
|
CollaborationDefaults: CollaborationConfig{
|
||||||
|
PreferredMessageTypes: []string{"coordination_request", "dependency_alert", "task_help_request"},
|
||||||
|
AutoSubscribeToRoles: []string{"backend_developer", "systems_engineer", "security_expert"},
|
||||||
|
AutoSubscribeToExpertise: []string{"backend", "infrastructure", "security"},
|
||||||
|
ResponseTimeoutSeconds: 240,
|
||||||
|
MaxCollaborationDepth: 4,
|
||||||
|
EscalationThreshold: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"specialist_3d": {
|
||||||
|
Name: "3D Specialist",
|
||||||
|
SystemPrompt: "You are the **3D Specialist**. You create and optimize 3D assets for the product.\n\n* **Responsibilities:** Model, texture, and rig characters, environments, and props; ensure performance-friendly assets.\n* **Expertise:** Blender, Maya, Substance Painter, Unity/Unreal pipelines, optimization techniques.\n* **Reports To:** Art Director or Lead Designer.\n* **Deliverables:** Game-ready 3D assets, texture packs, rigged models, and export guidelines.",
|
||||||
|
ReportsTo: []string{"art_director", "lead_designer"},
|
||||||
|
Expertise: []string{"blender", "maya", "substance_painter", "unity", "unreal", "3d_modeling", "texturing", "rigging"},
|
||||||
|
Deliverables: []string{"3d_assets", "texture_packs", "rigged_models", "export_guidelines"},
|
||||||
|
Capabilities: []string{"task-coordination", "meta-discussion", "3d_modeling", "asset_optimization"},
|
||||||
|
CollaborationDefaults: CollaborationConfig{
|
||||||
|
PreferredMessageTypes: []string{"task_help_request", "coordination_request", "meta_discussion"},
|
||||||
|
AutoSubscribeToRoles: []string{"lead_designer", "engine_programmer"},
|
||||||
|
AutoSubscribeToExpertise: []string{"design", "engine", "optimization"},
|
||||||
|
ResponseTimeoutSeconds: 300,
|
||||||
|
MaxCollaborationDepth: 3,
|
||||||
|
EscalationThreshold: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"technical_writer": {
|
||||||
|
Name: "Technical Writer",
|
||||||
|
SystemPrompt: "You are the **Technical Writer**. You make sure all documentation is accurate and user-friendly.\n\n* **Responsibilities:** Write developer docs, API references, user manuals, and release notes.\n* **Expertise:** Strong writing skills, Markdown, diagramming, understanding of tech stacks.\n* **Reports To:** Product Owner or Project Manager.\n* **Deliverables:** User guides, developer onboarding docs, and API documentation.",
|
||||||
|
ReportsTo: []string{"product_owner", "project_manager"},
|
||||||
|
Expertise: []string{"technical_writing", "markdown", "diagramming", "documentation", "user_guides"},
|
||||||
|
Deliverables: []string{"user_guides", "developer_docs", "api_documentation", "release_notes"},
|
||||||
|
Capabilities: []string{"task-coordination", "meta-discussion", "documentation", "technical_writing"},
|
||||||
|
CollaborationDefaults: CollaborationConfig{
|
||||||
|
PreferredMessageTypes: []string{"task_help_request", "coordination_complete", "meta_discussion"},
|
||||||
|
AutoSubscribeToRoles: []string{"backend_developer", "frontend_developer", "senior_software_architect"},
|
||||||
|
AutoSubscribeToExpertise: []string{"api_design", "documentation", "architecture"},
|
||||||
|
ResponseTimeoutSeconds: 200,
|
||||||
|
MaxCollaborationDepth: 3,
|
||||||
|
EscalationThreshold: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"full_stack_engineer": {
|
||||||
|
Name: "Full Stack Engineer",
|
||||||
|
SystemPrompt: "You are the **Full Stack Engineer**. You bridge frontend and backend to build complete features.\n\n* **Responsibilities:** Implement end-to-end features, debug across the stack, and assist in both client and server layers.\n* **Expertise:** Modern JS frameworks, backend APIs, databases, cloud deployment.\n* **Reports To:** Senior Architect or Tech Lead.\n* **Deliverables:** Full feature implementations, integration tests, and code linking UI to backend.",
|
||||||
|
ReportsTo: []string{"senior_software_architect", "tech_lead"},
|
||||||
|
Expertise: []string{"javascript", "frontend_frameworks", "backend_apis", "databases", "cloud_deployment", "full_stack"},
|
||||||
|
Deliverables: []string{"feature_implementations", "integration_tests", "end_to_end_code"},
|
||||||
|
Capabilities: []string{"task-coordination", "meta-discussion", "frontend", "backend", "full_stack_development"},
|
||||||
|
CollaborationDefaults: CollaborationConfig{
|
||||||
|
PreferredMessageTypes: []string{"task_help_request", "coordination_request", "task_help_response"},
|
||||||
|
AutoSubscribeToRoles: []string{"frontend_developer", "backend_developer", "database_engineer"},
|
||||||
|
AutoSubscribeToExpertise: []string{"frontend", "backend", "database"},
|
||||||
|
ResponseTimeoutSeconds: 200,
|
||||||
|
MaxCollaborationDepth: 4,
|
||||||
|
EscalationThreshold: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"database_engineer": {
|
||||||
|
Name: "Database Engineer",
|
||||||
|
SystemPrompt: "You are the **Database Engineer**. You design and maintain data structures for performance and reliability.\n\n* **Responsibilities:** Design schemas, optimize queries, manage migrations, and implement backup strategies.\n* **Expertise:** SQL/NoSQL databases, indexing, query tuning, replication/sharding.\n* **Reports To:** Backend Lead or Senior Architect.\n* **Deliverables:** Schema diagrams, migration scripts, tuning reports, and disaster recovery plans.",
|
||||||
|
ReportsTo: []string{"backend_lead", "senior_software_architect"},
|
||||||
|
Expertise: []string{"sql", "nosql", "indexing", "query_tuning", "replication", "sharding", "database_design"},
|
||||||
|
Deliverables: []string{"schema_diagrams", "migration_scripts", "tuning_reports", "disaster_recovery_plans"},
|
||||||
|
Capabilities: []string{"task-coordination", "meta-discussion", "database_design", "query_optimization", "data_modeling"},
|
||||||
|
CollaborationDefaults: CollaborationConfig{
|
||||||
|
PreferredMessageTypes: []string{"task_help_request", "dependency_alert", "coordination_request"},
|
||||||
|
AutoSubscribeToRoles: []string{"backend_developer", "ml_engineer", "devops_engineer"},
|
||||||
|
AutoSubscribeToExpertise: []string{"backend", "machine_learning", "deployment"},
|
||||||
|
ResponseTimeoutSeconds: 240,
|
||||||
|
MaxCollaborationDepth: 3,
|
||||||
|
EscalationThreshold: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"engine_programmer": {
|
||||||
|
Name: "Engine Programmer",
|
||||||
|
SystemPrompt: "You are the **Engine Programmer**. You work close to the metal to extend and optimize the engine.\n\n* **Responsibilities:** Develop low-level systems (rendering, physics, memory), maintain performance, and enable tools for designers/artists.\n* **Expertise:** C++/Rust, graphics APIs (Vulkan/DirectX/OpenGL), performance profiling, game/real-time engines.\n* **Reports To:** Senior Software Architect or Technical Director.\n* **Deliverables:** Engine modules, profiling reports, performance patches, and technical documentation.",
|
||||||
|
ReportsTo: []string{"senior_software_architect", "technical_director"},
|
||||||
|
Expertise: []string{"cpp", "rust", "vulkan", "directx", "opengl", "performance_profiling", "game_engines", "low_level_programming"},
|
||||||
|
Deliverables: []string{"engine_modules", "profiling_reports", "performance_patches", "technical_documentation"},
|
||||||
|
Capabilities: []string{"task-coordination", "meta-discussion", "engine_development", "performance_optimization", "low_level_programming"},
|
||||||
|
CollaborationDefaults: CollaborationConfig{
|
||||||
|
PreferredMessageTypes: []string{"task_help_request", "meta_discussion", "coordination_request"},
|
||||||
|
AutoSubscribeToRoles: []string{"specialist_3d", "senior_software_architect"},
|
||||||
|
AutoSubscribeToExpertise: []string{"3d_modeling", "architecture", "optimization"},
|
||||||
|
ResponseTimeoutSeconds: 300,
|
||||||
|
MaxCollaborationDepth: 4,
|
||||||
|
EscalationThreshold: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyRoleDefinition applies a predefined role to the agent config
|
||||||
|
func (c *Config) ApplyRoleDefinition(roleName string) error {
|
||||||
|
roles := GetPredefinedRoles()
|
||||||
|
|
||||||
|
role, exists := roles[roleName]
|
||||||
|
if !exists {
|
||||||
|
return fmt.Errorf("unknown role: %s", roleName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply role configuration
|
||||||
|
c.Agent.Role = role.Name
|
||||||
|
c.Agent.SystemPrompt = role.SystemPrompt
|
||||||
|
c.Agent.ReportsTo = role.ReportsTo
|
||||||
|
c.Agent.Expertise = role.Expertise
|
||||||
|
c.Agent.Deliverables = role.Deliverables
|
||||||
|
c.Agent.Capabilities = role.Capabilities
|
||||||
|
c.Agent.CollaborationSettings = role.CollaborationDefaults
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRoleByName returns a role definition by name (case-insensitive)
|
||||||
|
func GetRoleByName(roleName string) (*RoleDefinition, error) {
|
||||||
|
roles := GetPredefinedRoles()
|
||||||
|
|
||||||
|
// Try exact match first
|
||||||
|
if role, exists := roles[roleName]; exists {
|
||||||
|
return &role, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try case-insensitive match
|
||||||
|
lowerRoleName := strings.ToLower(roleName)
|
||||||
|
for key, role := range roles {
|
||||||
|
if strings.ToLower(key) == lowerRoleName {
|
||||||
|
return &role, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("role not found: %s", roleName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAvailableRoles returns a list of all available role names
|
||||||
|
func GetAvailableRoles() []string {
|
||||||
|
roles := GetPredefinedRoles()
|
||||||
|
names := make([]string, 0, len(roles))
|
||||||
|
|
||||||
|
for name := range roles {
|
||||||
|
names = append(names, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return names
|
||||||
|
}
|
||||||
109
pubsub/pubsub.go
109
pubsub/pubsub.go
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -61,6 +62,18 @@ const (
|
|||||||
CoordinationComplete MessageType = "coordination_complete" // Coordination session completed
|
CoordinationComplete MessageType = "coordination_complete" // Coordination session completed
|
||||||
DependencyAlert MessageType = "dependency_alert" // Dependency detected
|
DependencyAlert MessageType = "dependency_alert" // Dependency detected
|
||||||
EscalationTrigger MessageType = "escalation_trigger" // Human escalation needed
|
EscalationTrigger MessageType = "escalation_trigger" // Human escalation needed
|
||||||
|
|
||||||
|
// Role-based collaboration messages
|
||||||
|
RoleAnnouncement MessageType = "role_announcement" // Agent announces its role and capabilities
|
||||||
|
ExpertiseRequest MessageType = "expertise_request" // Request for specific expertise
|
||||||
|
ExpertiseResponse MessageType = "expertise_response" // Response offering expertise
|
||||||
|
StatusUpdate MessageType = "status_update" // Regular status updates from agents
|
||||||
|
WorkAllocation MessageType = "work_allocation" // Allocation of work to specific roles
|
||||||
|
RoleCollaboration MessageType = "role_collaboration" // Cross-role collaboration message
|
||||||
|
MentorshipRequest MessageType = "mentorship_request" // Junior role requesting mentorship
|
||||||
|
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
|
||||||
)
|
)
|
||||||
|
|
||||||
// Message represents a Bzzz/Antennae message
|
// Message represents a Bzzz/Antennae message
|
||||||
@@ -70,6 +83,14 @@ type Message struct {
|
|||||||
Timestamp time.Time `json:"timestamp"`
|
Timestamp time.Time `json:"timestamp"`
|
||||||
Data map[string]interface{} `json:"data"`
|
Data map[string]interface{} `json:"data"`
|
||||||
HopCount int `json:"hop_count,omitempty"` // For Antennae hop limiting
|
HopCount int `json:"hop_count,omitempty"` // For Antennae hop limiting
|
||||||
|
|
||||||
|
// Role-based collaboration fields
|
||||||
|
FromRole string `json:"from_role,omitempty"` // Role of sender
|
||||||
|
ToRoles []string `json:"to_roles,omitempty"` // Target roles
|
||||||
|
RequiredExpertise []string `json:"required_expertise,omitempty"` // Required expertise areas
|
||||||
|
ProjectID string `json:"project_id,omitempty"` // Associated project
|
||||||
|
Priority string `json:"priority,omitempty"` // Message priority (low, medium, high, urgent)
|
||||||
|
ThreadID string `json:"thread_id,omitempty"` // Conversation thread ID
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPubSub creates a new PubSub instance for Bzzz coordination and Antennae meta-discussion
|
// NewPubSub creates a new PubSub instance for Bzzz coordination and Antennae meta-discussion
|
||||||
@@ -188,6 +209,50 @@ func (p *PubSub) JoinDynamicTopic(topicName string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JoinRoleBasedTopics joins topics based on role and expertise
|
||||||
|
func (p *PubSub) JoinRoleBasedTopics(role string, expertise []string, reportsTo []string) error {
|
||||||
|
var topicsToJoin []string
|
||||||
|
|
||||||
|
// Join role-specific topic
|
||||||
|
if role != "" {
|
||||||
|
roleTopic := fmt.Sprintf("bzzz/roles/%s/v1", strings.ToLower(strings.ReplaceAll(role, " ", "_")))
|
||||||
|
topicsToJoin = append(topicsToJoin, roleTopic)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join expertise-specific topics
|
||||||
|
for _, exp := range expertise {
|
||||||
|
expertiseTopic := fmt.Sprintf("bzzz/expertise/%s/v1", strings.ToLower(strings.ReplaceAll(exp, " ", "_")))
|
||||||
|
topicsToJoin = append(topicsToJoin, expertiseTopic)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join reporting hierarchy topics
|
||||||
|
for _, supervisor := range reportsTo {
|
||||||
|
supervisorTopic := fmt.Sprintf("bzzz/hierarchy/%s/v1", strings.ToLower(strings.ReplaceAll(supervisor, " ", "_")))
|
||||||
|
topicsToJoin = append(topicsToJoin, supervisorTopic)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join all identified topics
|
||||||
|
for _, topicName := range topicsToJoin {
|
||||||
|
if err := p.JoinDynamicTopic(topicName); err != nil {
|
||||||
|
fmt.Printf("⚠️ Failed to join role-based topic %s: %v\n", topicName, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("🎯 Joined %d role-based topics for role: %s\n", len(topicsToJoin), role)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// JoinProjectTopic joins a project-specific topic
|
||||||
|
func (p *PubSub) JoinProjectTopic(projectID string) error {
|
||||||
|
if projectID == "" {
|
||||||
|
return fmt.Errorf("project ID cannot be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
topicName := fmt.Sprintf("bzzz/projects/%s/coordination/v1", projectID)
|
||||||
|
return p.JoinDynamicTopic(topicName)
|
||||||
|
}
|
||||||
|
|
||||||
// LeaveDynamicTopic leaves a specific task topic
|
// LeaveDynamicTopic leaves a specific task topic
|
||||||
func (p *PubSub) LeaveDynamicTopic(topicName string) {
|
func (p *PubSub) LeaveDynamicTopic(topicName string) {
|
||||||
p.dynamicTopicsMux.Lock()
|
p.dynamicTopicsMux.Lock()
|
||||||
@@ -267,6 +332,50 @@ func (p *PubSub) PublishAntennaeMessage(msgType MessageType, data map[string]int
|
|||||||
return p.antennaeTopic.Publish(p.ctx, msgBytes)
|
return p.antennaeTopic.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{
|
||||||
|
Type: msgType,
|
||||||
|
From: p.host.ID().String(),
|
||||||
|
Timestamp: time.Now(),
|
||||||
|
Data: data,
|
||||||
|
FromRole: opts.FromRole,
|
||||||
|
ToRoles: opts.ToRoles,
|
||||||
|
RequiredExpertise: opts.RequiredExpertise,
|
||||||
|
ProjectID: opts.ProjectID,
|
||||||
|
Priority: opts.Priority,
|
||||||
|
ThreadID: opts.ThreadID,
|
||||||
|
}
|
||||||
|
|
||||||
|
msgBytes, err := json.Marshal(msg)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to marshal role-based message: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine which topic to use based on message type
|
||||||
|
var topic *pubsub.Topic
|
||||||
|
switch msgType {
|
||||||
|
case RoleAnnouncement, ExpertiseRequest, ExpertiseResponse, StatusUpdate,
|
||||||
|
WorkAllocation, RoleCollaboration, MentorshipRequest, MentorshipResponse,
|
||||||
|
ProjectUpdate, DeliverableReady:
|
||||||
|
topic = p.antennaeTopic // Use Antennae topic for role-based messages
|
||||||
|
default:
|
||||||
|
topic = p.bzzzTopic // Default to Bzzz topic
|
||||||
|
}
|
||||||
|
|
||||||
|
return topic.Publish(p.ctx, msgBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageOptions holds options for role-based messages
|
||||||
|
type MessageOptions struct {
|
||||||
|
FromRole string
|
||||||
|
ToRoles []string
|
||||||
|
RequiredExpertise []string
|
||||||
|
ProjectID string
|
||||||
|
Priority string
|
||||||
|
ThreadID string
|
||||||
|
}
|
||||||
|
|
||||||
// handleBzzzMessages processes incoming Bzzz coordination messages
|
// handleBzzzMessages processes incoming Bzzz coordination messages
|
||||||
func (p *PubSub) handleBzzzMessages() {
|
func (p *PubSub) handleBzzzMessages() {
|
||||||
for {
|
for {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/anthonyrawlins/bzzz/pkg/config"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/docker/docker/pkg/stdcopy"
|
"github.com/docker/docker/pkg/stdcopy"
|
||||||
|
|||||||
Reference in New Issue
Block a user