Files
zeekayandGitHub 5b5cf9e9db feat: merge AgentField control plane + SDKs as Hanzo Agents (#1)
Transforms hanzoai/agents from a marketplace config repo into a full
agent orchestration platform by merging the AgentField infrastructure:

- Go control plane (K8s-like agent orchestration, service mesh, DAG workflows)
- Python SDK (FastAPI-based agent framework, LiteLLM, memory, DID/VC)
- TypeScript SDK (@hanzo/agents - Vercel AI SDK, MCP, workflows)
- Go SDK (idiomatic agent builder + client)
- React 19 embedded dashboard (XyFlow DAGs, Recharts, Radix UI)
- Docker/K8s/Helm deployment configs
- Examples: hello world, deep research, RAG, simulation, benchmarks
- Functional test suite across Python/Go/TypeScript

All references rebranded: AgentField → Hanzo Agents
- Module: github.com/hanzoai/agents/control-plane
- Python: hanzo_agents
- TypeScript: @hanzo/agents
- Go: github.com/hanzoai/agents/sdk/go
- Env vars: HANZO_AGENTS_*
- Config: hanzo-agents.yaml

Previous marketplace configs moved to config/ directory.
2026-02-09 18:53:09 -08:00

120 lines
3.1 KiB
Go

package cli
import (
"errors"
"fmt"
"os"
"os/exec" // Added missing import
"path/filepath"
"github.com/hanzoai/agents/control-plane/internal/logger"
"github.com/hanzoai/agents/control-plane/internal/packages"
"github.com/spf13/cobra"
"gopkg.in/yaml.v3"
)
var (
logsFollow bool
logsTail int
)
// NewLogsCommand creates the logs command
func NewLogsCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "logs <agent-node-name>",
Short: "View logs for a HanzoAgents agent node",
Long: `Display logs for an installed HanzoAgents agent node package.
Shows the most recent log entries from the agent node's log file.
Examples:
af logs email-helper
af logs data-analyzer --follow`,
Args: cobra.ExactArgs(1),
RunE: runLogsCommand,
}
cmd.Flags().BoolVarP(&logsFollow, "follow", "f", false, "Follow log output")
cmd.Flags().IntVarP(&logsTail, "tail", "n", 50, "Number of lines to show from the end")
return cmd
}
func runLogsCommand(cmd *cobra.Command, args []string) error {
agentNodeName := args[0]
logViewer := &LogViewer{
HanzoAgentsHome: getHanzoAgentsHomeDir(),
Follow: logsFollow,
Tail: logsTail,
}
if err := logViewer.ViewLogs(agentNodeName); err != nil {
logger.Logger.Error().Err(err).Msg("Failed to view logs")
return fmt.Errorf("failed to view logs: %w", err)
}
return nil
}
// LogViewer handles viewing agent node logs
type LogViewer struct {
HanzoAgentsHome string
Follow bool
Tail int
}
// ViewLogs displays logs for an agent node
func (lv *LogViewer) ViewLogs(agentNodeName string) error {
// Load registry to get log file path
registryPath := filepath.Join(lv.HanzoAgentsHome, "installed.yaml")
registry := &packages.InstallationRegistry{
Installed: make(map[string]packages.InstalledPackage),
}
if data, err := os.ReadFile(registryPath); err == nil {
if err := yaml.Unmarshal(data, registry); err != nil {
return fmt.Errorf("failed to parse registry: %w", err)
}
} else if !errors.Is(err, os.ErrNotExist) {
return fmt.Errorf("failed to read registry: %w", err)
}
agentNode, exists := registry.Installed[agentNodeName]
if !exists {
return fmt.Errorf("agent node %s not installed", agentNodeName)
}
logFile := agentNode.Runtime.LogFile
if _, err := os.Stat(logFile); os.IsNotExist(err) {
logger.Logger.Info().Msgf("📝 No logs found for %s", agentNodeName)
logger.Logger.Info().Msg("💡 Logs will appear here when the agent node is running")
return nil
}
logger.Logger.Info().Msgf("📝 Logs for %s:", agentNodeName)
logger.Logger.Info().Msgf("📁 %s\n", logFile)
if lv.Follow {
return lv.followLogs(logFile)
} else {
return lv.tailLogs(logFile, lv.Tail)
}
}
// tailLogs shows the last N lines of the log file
func (lv *LogViewer) tailLogs(logFile string, lines int) error {
cmd := exec.Command("tail", "-n", fmt.Sprintf("%d", lines), logFile)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}
// followLogs follows the log file in real-time
func (lv *LogViewer) followLogs(logFile string) error {
cmd := exec.Command("tail", "-f", logFile)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}