client

package
v0.1.12 Latest Latest
Warning

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

Go to latest
Published: May 28, 2025 License: MIT Imports: 14 Imported by: 0

README

Agent Master Daemon gRPC Client

A Go client library for interacting with the Agent Master daemon via gRPC.

Features

  • Connection Management: Support for both TCP and Unix socket connections
  • Automatic Retries: Built-in retry logic with exponential backoff
  • Connection Keepalive: Automatic connection health monitoring
  • Simplified API: Wraps complex gRPC calls in simple Go methods
  • Event Streaming: Subscribe to real-time daemon events
  • Thread-Safe: Safe for concurrent use

Installation

go get github.com/b-open-io/agent-master-engine/daemon/client

Quick Start

package main

import (
    "context"
    "log"
    
    "github.com/b-open-io/agent-master-engine/daemon/client"
    pb "github.com/b-open-io/agent-master-engine/daemon/proto"
)

func main() {
    // Create client with default options (TCP on localhost:50051)
    c := client.NewClient(client.DefaultOptions())
    
    // Connect to daemon
    ctx := context.Background()
    if err := c.Connect(ctx); err != nil {
        log.Fatal(err)
    }
    defer c.Close()
    
    // Add a server
    serverInfo, err := c.AddServer(ctx, "my-server", &pb.ServerConfig{
        Transport: "stdio",
        Command:   "node",
        Args:      []string{"server.js"},
        Enabled:   true,
    })
    if err != nil {
        log.Fatal(err)
    }
    
    log.Printf("Added server: %s", serverInfo.Name)
}

Connection Options

TCP Connection (Default)
c := client.NewClient(&client.ClientOptions{
    Type:    client.ConnectionTCP,
    Address: "localhost:50051",
})
Unix Socket Connection
c := client.NewClient(&client.ClientOptions{
    Type:    client.ConnectionUnix,
    Address: "/tmp/agent-master.sock",
})
Advanced Options
c := client.NewClient(&client.ClientOptions{
    Type:                   client.ConnectionTCP,
    Address:                "localhost:50051",
    MaxRetries:             5,
    RetryDelay:             2 * time.Second,
    RetryBackoffMultiplier: 1.5,
    KeepaliveTime:          30 * time.Second,
    KeepaliveTimeout:       10 * time.Second,
    RequestTimeout:         30 * time.Second,
})

API Methods

Server Management
  • AddServer(ctx, name, config) - Add a new server
  • UpdateServer(ctx, name, config) - Update existing server
  • RemoveServer(ctx, name) - Remove a server
  • GetServer(ctx, name) - Get server details
  • ListServers(ctx, filter) - List servers with optional filter
  • EnableServer(ctx, name) - Enable a server
  • DisableServer(ctx, name) - Disable a server
Destination Management
  • RegisterDestination(ctx, name, type, path, options) - Register a destination
  • RemoveDestination(ctx, name) - Remove a destination
  • ListDestinations(ctx) - List all destinations
Sync Operations
  • SyncTo(ctx, destination, options) - Sync to a single destination
  • SyncToMultiple(ctx, destinations, options) - Sync to multiple destinations
  • PreviewSync(ctx, destination) - Preview sync changes
Auto-sync
  • StartAutoSync(ctx, config) - Start auto-sync with configuration
  • StopAutoSync(ctx) - Stop auto-sync
  • GetAutoSyncStatus(ctx) - Get auto-sync status
Configuration
  • GetConfig(ctx) - Get current configuration
  • SetConfig(ctx, config) - Update configuration
  • LoadConfig(ctx, path) - Load configuration from file
  • SaveConfig(ctx) - Save current configuration
Daemon Control
  • GetStatus(ctx) - Get daemon status
  • Shutdown(ctx) - Shutdown the daemon
Events
  • Subscribe(ctx, eventTypes, handler) - Subscribe to daemon events

Event Handling

Subscribe to real-time events from the daemon:

err := c.Subscribe(ctx, []pb.EventType{
    pb.EventType_CONFIG_CHANGE,
    pb.EventType_SYNC_COMPLETE,
    pb.EventType_ERROR,
}, func(event *pb.Event) error {
    switch event.Type {
    case pb.EventType_CONFIG_CHANGE:
        log.Printf("Config changed: %v", event.GetConfigChange())
    case pb.EventType_SYNC_COMPLETE:
        sync := event.GetSyncComplete()
        log.Printf("Sync to %s: %v", sync.Destination, sync.Success)
    case pb.EventType_ERROR:
        err := event.GetError()
        log.Printf("Error: %s", err.Message)
    }
    return nil
})

Error Handling

The client includes automatic retry logic for transient errors:

  • Unavailable - Service temporarily unavailable
  • DeadlineExceeded - Request timeout
  • ResourceExhausted - Rate limiting

Non-retryable errors are returned immediately.

Thread Safety

The client is thread-safe and can be used concurrently from multiple goroutines. A single client instance can be shared across your application.

Examples

See example_test.go for comprehensive examples including:

  • Basic server management
  • Batch operations
  • Auto-sync configuration
  • Event subscription
  • Multi-destination sync

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

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

Client wraps the gRPC connection and provides simplified methods

Example (Tcp)
package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/b-open-io/agent-master-engine/daemon/client"
	pb "github.com/b-open-io/agent-master-engine/daemon/proto"
)

func main() {
	// Create a client with default TCP options
	c := client.NewClient(&client.ClientOptions{
		Type:           client.ConnectionTCP,
		Address:        "localhost:50051",
		RequestTimeout: 10 * time.Second,
	})

	// Connect to the daemon
	ctx := context.Background()
	if err := c.Connect(ctx); err != nil {
		log.Fatalf("Failed to connect: %v", err)
	}
	defer c.Close()

	// Add a new server
	serverConfig := &pb.ServerConfig{
		Transport: "stdio",
		Command:   "node",
		Args:      []string{"/path/to/server.js"},
		Enabled:   true,
		Metadata: map[string]string{
			"version": "1.0.0",
		},
	}

	serverInfo, err := c.AddServer(ctx, "my-mcp-server", serverConfig)
	if err != nil {
		log.Fatalf("Failed to add server: %v", err)
	}
	fmt.Printf("Added server: %s\n", serverInfo.Name)

	// List all servers
	servers, err := c.ListServers(ctx, nil)
	if err != nil {
		log.Fatalf("Failed to list servers: %v", err)
	}
	fmt.Printf("Found %d servers\n", len(servers))

	// Sync to Claude
	syncResult, err := c.SyncTo(ctx, "claude", &pb.SyncOptions{
		Force:  false,
		Backup: true,
	})
	if err != nil {
		log.Fatalf("Failed to sync: %v", err)
	}
	fmt.Printf("Synced %d servers successfully\n", syncResult.ServersSynced)
}
Example (UnixSocket)
package main

import (
	"context"
	"fmt"
	"log"

	"github.com/b-open-io/agent-master-engine/daemon/client"
)

func main() {
	// Create a client for Unix socket connection
	c := client.NewClient(&client.ClientOptions{
		Type:    client.ConnectionUnix,
		Address: "/tmp/agent-master.sock",
	})

	ctx := context.Background()
	if err := c.Connect(ctx); err != nil {
		log.Fatalf("Failed to connect: %v", err)
	}
	defer c.Close()

	// Get daemon status
	status, err := c.GetStatus(ctx)
	if err != nil {
		log.Fatalf("Failed to get status: %v", err)
	}

	fmt.Printf("Daemon version: %s\n", status.Version)
	fmt.Printf("Uptime: %d seconds\n", status.UptimeSeconds)
	fmt.Printf("Auto-sync running: %v\n", status.AutoSyncRunning)
}

func NewClient

func NewClient(opts *ClientOptions) *Client

NewClient creates a new client with the given options

func (*Client) AddServer

func (c *Client) AddServer(ctx context.Context, name string, config *pb.ServerConfig) (*pb.ServerInfo, error)

AddServer adds a new server configuration

func (*Client) Close

func (c *Client) Close() error

Close closes the connection

func (*Client) Connect

func (c *Client) Connect(ctx context.Context) error

Connect establishes a connection to the daemon

func (*Client) DisableServer

func (c *Client) DisableServer(ctx context.Context, name string) (*pb.ServerInfo, error)

DisableServer disables a server

func (*Client) EnableServer

func (c *Client) EnableServer(ctx context.Context, name string) (*pb.ServerInfo, error)

EnableServer enables a server

func (*Client) GetAutoSyncStatus

func (c *Client) GetAutoSyncStatus(ctx context.Context) (*pb.AutoSyncStatus, error)

GetAutoSyncStatus gets the current auto-sync status

func (*Client) GetConfig

func (c *Client) GetConfig(ctx context.Context) (*pb.Config, error)

GetConfig retrieves the current configuration

func (*Client) GetServer

func (c *Client) GetServer(ctx context.Context, name string) (*pb.ServerInfo, error)

GetServer retrieves a server configuration

func (*Client) GetStatus

func (c *Client) GetStatus(ctx context.Context) (*pb.DaemonStatus, error)

GetStatus retrieves the daemon status

func (*Client) IsConnected

func (c *Client) IsConnected() bool

IsConnected returns true if the client is connected

func (*Client) ListDestinations

func (c *Client) ListDestinations(ctx context.Context) (map[string]*pb.DestinationInfo, error)

ListDestinations lists all available destinations

func (*Client) ListServers

func (c *Client) ListServers(ctx context.Context, filter *pb.ServerFilter) ([]*pb.ServerInfo, error)

ListServers lists all server configurations

func (*Client) LoadConfig

func (c *Client) LoadConfig(ctx context.Context, path string) error

LoadConfig loads configuration from a file

func (*Client) PreviewSync

func (c *Client) PreviewSync(ctx context.Context, destination string) (*pb.SyncPreview, error)

PreviewSync previews what would be synced to a destination

func (*Client) RegisterDestination

func (c *Client) RegisterDestination(ctx context.Context, name string, destType pb.DestinationType, path string, options map[string]string) error

RegisterDestination registers a new destination

func (*Client) RemoveDestination

func (c *Client) RemoveDestination(ctx context.Context, name string) error

RemoveDestination removes a destination

func (*Client) RemoveServer

func (c *Client) RemoveServer(ctx context.Context, name string) error

RemoveServer removes a server configuration

func (*Client) SaveConfig

func (c *Client) SaveConfig(ctx context.Context) error

SaveConfig saves the current configuration

func (*Client) SetConfig

func (c *Client) SetConfig(ctx context.Context, config *pb.Config) error

SetConfig updates the configuration

func (*Client) Shutdown

func (c *Client) Shutdown(ctx context.Context) error

Shutdown requests the daemon to shut down

func (*Client) StartAutoSync

func (c *Client) StartAutoSync(ctx context.Context, config *pb.AutoSyncConfig) error

StartAutoSync starts the auto-sync feature

func (*Client) StopAutoSync

func (c *Client) StopAutoSync(ctx context.Context) error

StopAutoSync stops the auto-sync feature

func (*Client) Subscribe

func (c *Client) Subscribe(ctx context.Context, eventTypes []pb.EventType, handler EventHandler) error

Subscribe subscribes to events from the daemon

Example
package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/b-open-io/agent-master-engine/daemon/client"
	pb "github.com/b-open-io/agent-master-engine/daemon/proto"
)

func main() {
	c := client.NewClient(client.DefaultOptions())

	ctx := context.Background()
	if err := c.Connect(ctx); err != nil {
		log.Fatalf("Failed to connect: %v", err)
	}
	defer c.Close()

	// Subscribe to all event types
	eventTypes := []pb.EventType{
		pb.EventType_CONFIG_CHANGE,
		pb.EventType_SYNC_COMPLETE,
		pb.EventType_ERROR,
		pb.EventType_AUTO_SYNC_STATUS,
	}

	err := c.Subscribe(ctx, eventTypes, func(event *pb.Event) error {
		fmt.Printf("Received event: %s at %s\n",
			event.Type.String(),
			event.Timestamp.AsTime().Format(time.RFC3339))

		// Handle specific event types
		switch event.Type {
		case pb.EventType_CONFIG_CHANGE:
			if cfg := event.GetConfigChange(); cfg != nil {
				fmt.Printf("Config changed: %s\n", cfg.ChangeType)
			}
		case pb.EventType_SYNC_COMPLETE:
			if sync := event.GetSyncComplete(); sync != nil {
				fmt.Printf("Sync completed to %s: success=%v\n",
					sync.Destination, sync.Success)
			}
		case pb.EventType_ERROR:
			if err := event.GetError(); err != nil {
				fmt.Printf("Error in %s: %s\n", err.Component, err.Message)
			}
		}
		return nil
	})

	if err != nil {
		log.Fatalf("Failed to subscribe: %v", err)
	}

	// Keep listening for events
	select {}
}

func (*Client) SyncTo

func (c *Client) SyncTo(ctx context.Context, destination string, options *pb.SyncOptions) (*pb.SyncResult, error)

SyncTo syncs configuration to a specific destination

func (*Client) SyncToMultiple

func (c *Client) SyncToMultiple(ctx context.Context, destinations []string, options *pb.SyncOptions) (*pb.MultiSyncResult, error)

SyncToMultiple syncs configuration to multiple destinations

func (*Client) UpdateServer

func (c *Client) UpdateServer(ctx context.Context, name string, config *pb.ServerConfig) (*pb.ServerInfo, error)

UpdateServer updates an existing server configuration

type ClientOptions

type ClientOptions struct {
	// Connection settings
	Type    ConnectionType
	Address string

	// Retry settings
	MaxRetries             int
	RetryDelay             time.Duration
	RetryBackoffMultiplier float64

	// Keepalive settings
	KeepaliveTime    time.Duration
	KeepaliveTimeout time.Duration

	// Request timeout
	RequestTimeout time.Duration
}

ClientOptions contains configuration options for the client

func DefaultOptions

func DefaultOptions() *ClientOptions

DefaultOptions returns sensible default options

type ConnectionType

type ConnectionType int

ConnectionType represents the type of connection (TCP or Unix socket)

const (
	ConnectionTCP ConnectionType = iota
	ConnectionUnix
)

type EventHandler

type EventHandler func(*pb.Event) error

EventHandler is a function that handles events

Jump to

Keyboard shortcuts

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