adapter

package
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Apr 28, 2026 License: MIT Imports: 30 Imported by: 0

Documentation

Index

Constants

View Source
const (
	FrameworkZeroClaw = "zeroclaw"
	FrameworkOpenClaw = "openclaw"
	FrameworkHermes   = "hermes"
	FrameworkPicoClaw = "picoclaw"
	FrameworkEmbedded = "embedded"
)

Framework name constants. Use these instead of string literals to avoid typos and enable grep-ability. Files in the embedded package that cannot import adapter keep using the string literal "embedded" to avoid cycles.

Variables

View Source
var (
	ErrUnauthorized     = errors.New("authentication expired or invalid")
	ErrForbidden        = errors.New("access denied")
	ErrAgentUnreachable = errors.New("agent is not reachable")
	ErrAgentTimeout     = errors.New("agent did not respond in time")
)

Sentinel errors for adapter-to-gateway communication failures. Server handlers use these to return appropriate HTTP status codes instead of collapsing all failures into 500 Internal Server Error.

Functions

func ProbeProvider

func ProbeProvider(ctx context.Context, provider string) string

ProbeProvider checks whether the LLM provider is reachable by hitting its /v1/models endpoint. It understands "custom:<url>" format and well-known provider names. Returns "ok", "error", or "" if the URL can't be determined.

func ProviderBaseURL

func ProviderBaseURL(provider string) string

ProviderBaseURL extracts an OpenAI-compatible base URL from a provider string. Handles "custom:http://host:port/v1" and well-known providers.

Types

type ActivityEvent

type ActivityEvent struct {
	Timestamp   time.Time      `json:"timestamp"`
	Type        string         `json:"type"` // "agent_start", "agent_end", "tool_call", "tool_call_start", "llm_request", "error", "chat", "separator"
	Summary     string         `json:"summary"`
	FullContent string         `json:"full_content,omitempty"`
	Fields      map[string]any `json:"fields,omitempty"`
}

type Agent

type Agent interface {
	// Identity
	ID() string
	Name() string
	Framework() string // "zeroclaw", "openclaw", "picoclaw", "hermes", "embedded"

	// Gateway connection info
	BaseURL() string

	// Probing
	Health(ctx context.Context) (*HealthStatus, error)
	Status(ctx context.Context) (*AgentStatus, error)
	Config(ctx context.Context) (*AgentConfig, error)

	// Lifecycle (delegated to framework CLI)
	Start(ctx context.Context) error
	Stop(ctx context.Context) error
	Restart(ctx context.Context) error

	// Streaming
	TailLogs(ctx context.Context) (<-chan LogEntry, error)
	TailActivity(ctx context.Context) (<-chan ActivityEvent, error)

	// Conversation history (framework-dependent; may return nil, nil if unsupported)
	Sessions(ctx context.Context) ([]Session, error)
	ChatHistory(ctx context.Context, sessionKey string, limit int) ([]ChatMessage, error)

	// Chat: send a message and get the assistant's reply.
	// sessionKey identifies the conversation (e.g. "agent:main:main"); empty means default.
	SendMessage(ctx context.Context, message, sessionKey string) (*ChatMessage, error)

	// StreamMessage sends a message and streams the response as ChatEvent values.
	// The channel is closed when the response is complete (after a "done" or "error" event).
	StreamMessage(ctx context.Context, message, sessionKey string) (<-chan ChatEvent, error)

	// Interrupt asks the framework to cancel an in-flight response for the
	// given session. Best-effort — returns nil if the framework doesn't
	// support interruption or no response is active. The partial response
	// should NOT be stored as if it completed.
	Interrupt(ctx context.Context, sessionKey string) error

	// CreateSession creates a new conversation session with the given name. Returns the new session.
	CreateSession(ctx context.Context, name string) (*Session, error)

	// ResetSession archives the current transcript and starts a fresh session.
	ResetSession(ctx context.Context, sessionKey string) error

	// DeleteSession permanently removes a session from disk.
	DeleteSession(ctx context.Context, sessionKey string) error

	// Personality
	Personality(ctx context.Context) (*Personality, error)

	// Capabilities reports what roles this agent can fill in the hierarchy.
	Capabilities() AgentCapabilities
}

Agent is the common interface that every Claw framework adapter implements. Eyrie's CLI, web server, and discovery system all work through this interface.

type AgentCapabilities

type AgentCapabilities struct {
	CommanderCapable bool `json:"commander_capable"` // Can serve as Commander (requires tool execution, session context, API access)
}

type AgentConfig

type AgentConfig struct {
	Raw    string `json:"raw"`
	Format string `json:"format"` // "toml" or "json"
}

type AgentStatus

type AgentStatus struct {
	Provider       string     `json:"provider"`
	Model          string     `json:"model"`
	Channels       []string   `json:"channels"`
	Skills         int        `json:"skills"`
	LastTask       *time.Time `json:"last_task,omitempty"`
	Errors24h      int        `json:"errors_24h"`
	GatewayPort    int        `json:"gateway_port"`
	ProviderStatus string     `json:"provider_status,omitempty"` // "ok", "error", or "" (unknown/not checked)
	BusyState      string     `json:"busy_state,omitempty"`      // "idle", "busy", "error"
	CurrentTask    string     `json:"current_task,omitempty"`    // description of current activity
}

func (*AgentStatus) InferBusyState

func (s *AgentStatus) InferBusyState()

InferBusyState populates BusyState based on LastTask timestamp. Call after Status() to enrich the response.

type ChatEvent

type ChatEvent struct {
	Type    string         `json:"type"` // "delta", "tool_start", "tool_result", "done", "error"
	Content string         `json:"content,omitempty"`
	Tool    string         `json:"tool,omitempty"`
	ToolID  string         `json:"tool_id,omitempty"`
	Args    map[string]any `json:"args,omitempty"`
	Output  string         `json:"output,omitempty"`
	Success *bool          `json:"success,omitempty"`
	Error   string         `json:"error,omitempty"`
	// Usage stats (populated on "done" events when available)
	InputTokens  int     `json:"input_tokens,omitempty"`
	OutputTokens int     `json:"output_tokens,omitempty"`
	CostUSD      float64 `json:"cost_usd,omitempty"`
}

type ChatMessage

type ChatMessage struct {
	ID        string     `json:"id,omitempty"`
	Sender    string     `json:"sender,omitempty"` // agent name or "user" (project chat)
	Role      string     `json:"role"`             // "user", "assistant", "commander", "captain", "talon", "system"
	Content   string     `json:"content"`
	Timestamp time.Time  `json:"timestamp"`
	Channel   string     `json:"channel,omitempty"`
	Mention   string     `json:"mention,omitempty"` // "@captain", "@commander", etc. (project chat)
	Parts     []ChatPart `json:"parts,omitempty"`
	Detail    string     `json:"detail,omitempty"` // expandable content (e.g., full briefing text)
}

ChatMessage is the unified message type used across both 1:1 agent chats and multi-agent project conversations. Fields like ID, Sender, and Mention are only populated in project chat contexts; 1:1 chat leaves them empty.

type ChatPart

type ChatPart struct {
	Type   string         `json:"type"`
	Text   string         `json:"text,omitempty"`
	ID     string         `json:"id,omitempty"`
	Name   string         `json:"name,omitempty"`
	Args   map[string]any `json:"args,omitempty"`
	Output string         `json:"output,omitempty"`
	Error  bool           `json:"error,omitempty"`
}

ChatPart is an ordered content element within a message. Type is "text" or "tool_call".

type ComponentHealth

type ComponentHealth struct {
	Status       string     `json:"status"`
	LastOK       *time.Time `json:"last_ok,omitempty"`
	LastError    string     `json:"last_error,omitempty"`
	RestartCount int        `json:"restart_count"`
}

type DiscoveredAgent

type DiscoveredAgent struct {
	Name        string `json:"name"`
	DisplayName string `json:"display_name,omitempty"`
	Framework   string `json:"framework"`
	Host        string `json:"host"`
	Port        int    `json:"port"`
	ConfigPath  string `json:"config_path"`
	Token       string `json:"-"`
	InstanceID  string `json:"instance_id,omitempty"`
}

DiscoveredAgent holds the result of auto-discovery before a full adapter is created.

func (*DiscoveredAgent) URL

func (d *DiscoveredAgent) URL() string

type EmbeddedAdapter

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

EmbeddedAdapter implements the Agent interface for EyrieClaw — an agent that runs inside the Eyrie process as a goroutine. No separate binary, no gateway, no HTTP roundtrip. It calls LLM APIs directly and streams responses through the existing ChatEvent model.

func NewEmbeddedAdapter

func NewEmbeddedAdapter(id, name, configPath, workspacePath string) *EmbeddedAdapter

NewEmbeddedAdapter creates an adapter from the instance metadata.

func (*EmbeddedAdapter) BaseURL

func (a *EmbeddedAdapter) BaseURL() string

func (*EmbeddedAdapter) Capabilities

func (a *EmbeddedAdapter) Capabilities() AgentCapabilities

func (*EmbeddedAdapter) ChatHistory

func (a *EmbeddedAdapter) ChatHistory(_ context.Context, sessionKey string, limit int) ([]ChatMessage, error)

func (*EmbeddedAdapter) Config

func (a *EmbeddedAdapter) Config(_ context.Context) (*AgentConfig, error)

func (*EmbeddedAdapter) CreateSession

func (a *EmbeddedAdapter) CreateSession(_ context.Context, name string) (*Session, error)

func (*EmbeddedAdapter) DeleteSession

func (a *EmbeddedAdapter) DeleteSession(_ context.Context, sessionKey string) error

func (*EmbeddedAdapter) Framework

func (a *EmbeddedAdapter) Framework() string

func (*EmbeddedAdapter) Health

func (*EmbeddedAdapter) ID

func (a *EmbeddedAdapter) ID() string

func (*EmbeddedAdapter) Interrupt

func (a *EmbeddedAdapter) Interrupt(_ context.Context, _ string) error

func (*EmbeddedAdapter) IsRunning

func (a *EmbeddedAdapter) IsRunning() bool

IsRunning returns whether the embedded agent is currently active. Used by discovery/probe to check health without HTTP.

func (*EmbeddedAdapter) Name

func (a *EmbeddedAdapter) Name() string

func (*EmbeddedAdapter) Personality

func (a *EmbeddedAdapter) Personality(_ context.Context) (*Personality, error)

func (*EmbeddedAdapter) ResetSession

func (a *EmbeddedAdapter) ResetSession(_ context.Context, sessionKey string) error

func (*EmbeddedAdapter) Restart

func (a *EmbeddedAdapter) Restart(ctx context.Context) error

func (*EmbeddedAdapter) SendMessage

func (a *EmbeddedAdapter) SendMessage(ctx context.Context, message, sessionKey string) (*ChatMessage, error)

func (*EmbeddedAdapter) Sessions

func (a *EmbeddedAdapter) Sessions(_ context.Context) ([]Session, error)

func (*EmbeddedAdapter) SetVault

func (a *EmbeddedAdapter) SetVault(v *config.KeyVault)

SetVault injects the centralized key vault after construction. Called by discovery after creating the adapter singleton, avoiding import cycles between adapter and config packages at construction time.

func (*EmbeddedAdapter) Start

func (a *EmbeddedAdapter) Start(_ context.Context) error

func (*EmbeddedAdapter) Status

func (a *EmbeddedAdapter) Status(ctx context.Context) (*AgentStatus, error)

func (*EmbeddedAdapter) Stop

func (a *EmbeddedAdapter) Stop(_ context.Context) error

func (*EmbeddedAdapter) StreamMessage

func (a *EmbeddedAdapter) StreamMessage(ctx context.Context, message, sessionKey string) (<-chan ChatEvent, error)

StreamMessage constructs the system prompt from workspace identity files, appends the user message to the session, and delegates to the agent loop.

func (*EmbeddedAdapter) TailActivity

func (a *EmbeddedAdapter) TailActivity(_ context.Context) (<-chan ActivityEvent, error)

func (*EmbeddedAdapter) TailLogs

func (a *EmbeddedAdapter) TailLogs(_ context.Context) (<-chan LogEntry, error)

type EmbeddedConfig

type EmbeddedConfig struct {
	Provider         string   `json:"provider"`
	Model            string   `json:"model"`
	Tools            []string `json:"tools"`
	Workspace        string   `json:"workspace"`
	CommanderCapable bool     `json:"commander_capable"`
}

EmbeddedConfig holds the JSON config format for embedded agents.

type HealthStatus

type HealthStatus struct {
	Alive      bool                       `json:"alive"`
	Uptime     time.Duration              `json:"uptime"`
	RAM        uint64                     `json:"ram_bytes"`
	CPU        float64                    `json:"cpu_percent"`
	PID        int                        `json:"pid,omitempty"`
	Components map[string]ComponentHealth `json:"components,omitempty"`
}

type HermesAdapter

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

HermesAdapter implements the Agent interface for Hermes (Python-based agent) using CLI invocation and file-based status checks.

func NewHermesAdapter

func NewHermesAdapter(id, name, configPath, binaryPath string) *HermesAdapter

NewHermesAdapter creates a new Hermes adapter

func (*HermesAdapter) BaseURL

func (h *HermesAdapter) BaseURL() string

BaseURL returns empty string (no HTTP API)

func (*HermesAdapter) Capabilities

func (h *HermesAdapter) Capabilities() AgentCapabilities

func (*HermesAdapter) ChatHistory

func (h *HermesAdapter) ChatHistory(ctx context.Context, sessionKey string, limit int) ([]ChatMessage, error)

ChatHistory returns chat messages for a session

func (*HermesAdapter) Config

func (h *HermesAdapter) Config(ctx context.Context) (*AgentConfig, error)

Config returns the agent configuration

func (*HermesAdapter) CreateSession

func (h *HermesAdapter) CreateSession(ctx context.Context, name string) (*Session, error)

CreateSession creates a new conversation session

func (*HermesAdapter) DeleteSession

func (h *HermesAdapter) DeleteSession(ctx context.Context, sessionKey string) error

DeleteSession permanently removes a session

func (*HermesAdapter) Framework

func (h *HermesAdapter) Framework() string

Framework returns "hermes"

func (*HermesAdapter) Health

func (h *HermesAdapter) Health(ctx context.Context) (*HealthStatus, error)

Health checks if the Hermes gateway is running by reading PID file and state file

func (*HermesAdapter) ID

func (h *HermesAdapter) ID() string

ID returns the unique identifier

func (*HermesAdapter) Interrupt

func (h *HermesAdapter) Interrupt(_ context.Context, _ string) error

Interrupt is a no-op for Hermes — cancellation already works via exec.CommandContext, which kills the subprocess when ctx is cancelled.

func (*HermesAdapter) Name

func (h *HermesAdapter) Name() string

Name returns the agent name

func (*HermesAdapter) Personality

func (h *HermesAdapter) Personality(ctx context.Context) (*Personality, error)

Personality returns the agent's personality

func (*HermesAdapter) ResetSession

func (h *HermesAdapter) ResetSession(ctx context.Context, sessionKey string) error

ResetSession deletes a conversation session

func (*HermesAdapter) Restart

func (h *HermesAdapter) Restart(ctx context.Context) error

Restart restarts the Hermes gateway

func (*HermesAdapter) SendMessage

func (h *HermesAdapter) SendMessage(ctx context.Context, message, sessionKey string) (*ChatMessage, error)

SendMessage sends a message and waits for the response

func (*HermesAdapter) Sessions

func (h *HermesAdapter) Sessions(ctx context.Context) ([]Session, error)

Sessions returns conversation sessions

func (*HermesAdapter) Start

func (h *HermesAdapter) Start(ctx context.Context) error

Start starts the Hermes gateway

func (*HermesAdapter) Status

func (h *HermesAdapter) Status(ctx context.Context) (*AgentStatus, error)

Status returns agent status by parsing config file

func (*HermesAdapter) Stop

func (h *HermesAdapter) Stop(ctx context.Context) error

Stop stops the Hermes gateway by killing the process

func (*HermesAdapter) StreamMessage

func (h *HermesAdapter) StreamMessage(ctx context.Context, message, sessionKey string) (<-chan ChatEvent, error)

StreamMessage sends a message and streams the response

func (*HermesAdapter) TailActivity

func (h *HermesAdapter) TailActivity(ctx context.Context) (<-chan ActivityEvent, error)

TailActivity tails the Hermes log file and extracts activity events

func (*HermesAdapter) TailLogs

func (h *HermesAdapter) TailLogs(ctx context.Context) (<-chan LogEntry, error)

TailLogs tails the Hermes log file

type LogEntry

type LogEntry struct {
	Timestamp time.Time      `json:"timestamp"`
	Level     string         `json:"level"`
	Message   string         `json:"message"`
	Fields    map[string]any `json:"fields,omitempty"`
}

type OpenClawAdapter

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

OpenClawAdapter communicates with an OpenClaw instance via its WebSocket RPC gateway. OpenClaw exposes a single WebSocket endpoint at ws://host:port with RPC methods.

func NewOpenClawAdapter

func NewOpenClawAdapter(id, name, host string, port int, token, configPath string) *OpenClawAdapter

func (*OpenClawAdapter) BaseURL

func (o *OpenClawAdapter) BaseURL() string

func (*OpenClawAdapter) Capabilities

func (o *OpenClawAdapter) Capabilities() AgentCapabilities

func (*OpenClawAdapter) ChatHistory

func (o *OpenClawAdapter) ChatHistory(_ context.Context, sessionKey string, limit int) ([]ChatMessage, error)

ChatHistory reads the JSONL transcript file for a given session key directly from disk. It extracts user and assistant messages, handling OpenClaw's content format (array of {type, text} objects).

func (*OpenClawAdapter) Config

func (o *OpenClawAdapter) Config(ctx context.Context) (*AgentConfig, error)

func (*OpenClawAdapter) CreateSession

func (o *OpenClawAdapter) CreateSession(_ context.Context, name string) (*Session, error)

func (*OpenClawAdapter) DeleteSession

func (o *OpenClawAdapter) DeleteSession(_ context.Context, sessionKey string) error

func (*OpenClawAdapter) DestroySession

func (o *OpenClawAdapter) DestroySession(ctx context.Context, sessionKey string) error

DestroySession completely removes a session — deletes the JSONL transcript and removes the entry from sessions.json. Works for both active and archived sessions.

For active sessions this delegates to OpenClaw's sessions.delete RPC, which handles its own locking and transcript cleanup. Previous versions did file surgery on sessions.json from Eyrie, which was racy (TOCTOU) when OpenClaw wrote to the same file concurrently.

func (*OpenClawAdapter) Framework

func (o *OpenClawAdapter) Framework() string

func (*OpenClawAdapter) Health

func (o *OpenClawAdapter) Health(ctx context.Context) (*HealthStatus, error)

func (*OpenClawAdapter) ID

func (o *OpenClawAdapter) ID() string

func (*OpenClawAdapter) Interrupt

func (o *OpenClawAdapter) Interrupt(_ context.Context, _ string) error

Interrupt asks OpenClaw to cancel an in-flight response. OpenClaw emits "aborted" events internally, but no public RPC method is exposed yet. No-op until we identify the right RPC call.

func (*OpenClawAdapter) Name

func (o *OpenClawAdapter) Name() string

func (*OpenClawAdapter) Personality

func (o *OpenClawAdapter) Personality(ctx context.Context) (*Personality, error)

func (*OpenClawAdapter) QuickHealthCheck

func (o *OpenClawAdapter) QuickHealthCheck(ctx context.Context) bool

QuickHealthCheck does a fast WebSocket connect + handshake probe.

func (*OpenClawAdapter) ResetSession

func (o *OpenClawAdapter) ResetSession(ctx context.Context, sessionKey string) error

func (*OpenClawAdapter) Restart

func (o *OpenClawAdapter) Restart(ctx context.Context) error

func (*OpenClawAdapter) SendMessage

func (o *OpenClawAdapter) SendMessage(ctx context.Context, message, sessionKey string) (*ChatMessage, error)

func (*OpenClawAdapter) Sessions

func (o *OpenClawAdapter) Sessions(_ context.Context) ([]Session, error)

Sessions reads session metadata directly from OpenClaw's on-disk session store rather than using the WebSocket RPC (which requires a full device-auth handshake that Eyrie does not implement).

func (*OpenClawAdapter) Start

func (o *OpenClawAdapter) Start(ctx context.Context) error

func (*OpenClawAdapter) Status

func (o *OpenClawAdapter) Status(ctx context.Context) (*AgentStatus, error)

func (*OpenClawAdapter) Stop

func (o *OpenClawAdapter) Stop(ctx context.Context) error

func (*OpenClawAdapter) StreamMessage

func (o *OpenClawAdapter) StreamMessage(ctx context.Context, message, sessionKey string) (<-chan ChatEvent, error)

func (*OpenClawAdapter) TailActivity

func (o *OpenClawAdapter) TailActivity(ctx context.Context) (<-chan ActivityEvent, error)

TailActivity emits recent conversation history as activity events, then subscribes to the OpenClaw WebSocket event stream for live events.

func (*OpenClawAdapter) TailLogs

func (o *OpenClawAdapter) TailLogs(ctx context.Context) (<-chan LogEntry, error)

TailLogs subscribes to the OpenClaw logs.tail RPC stream. If the agent is not running, historical logs are still returned before closing.

type Personality

type Personality struct {
	Name         string            `json:"name"`
	SystemPrompt string            `json:"system_prompt,omitempty"`
	Traits       map[string]string `json:"traits,omitempty"`
	// Raw workspace identity files (IDENTITY.md, SOUL.md, etc.)
	IdentityFiles map[string]string `json:"identity_files,omitempty"`
}

type PicoClawAdapter

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

PicoClawAdapter communicates with a PicoClaw instance via the web backend's REST API (sessions, config, lifecycle) and the gateway's health endpoint. Chat streaming uses the Pico Protocol WebSocket with delta diffing.

Architecture: PicoClaw has a two-tier design — a gateway (agent runtime, default port 18790) and a web backend (launcher + API proxy, default port 18800 = gatewayPort + 10). Eyrie stores the gateway port in DiscoveredAgent for health probing (consistent with all adapters) and derives the web port.

func NewPicoClawAdapter

func NewPicoClawAdapter(id, name, host string, gatewayPort int, token, configPath string) *PicoClawAdapter

func (*PicoClawAdapter) BaseURL

func (p *PicoClawAdapter) BaseURL() string

func (*PicoClawAdapter) Capabilities

func (p *PicoClawAdapter) Capabilities() AgentCapabilities

Capabilities reports that PicoClaw is commander-capable.

func (*PicoClawAdapter) ChatHistory

func (p *PicoClawAdapter) ChatHistory(ctx context.Context, sessionKey string, limit int) ([]ChatMessage, error)

ChatHistory reads message history for a session from the web backend. Falls back to reading JSONL from disk if the API is unavailable.

func (*PicoClawAdapter) Config

func (p *PicoClawAdapter) Config(ctx context.Context) (*AgentConfig, error)

Config reads the config.json from disk. Returns the raw JSON content.

func (*PicoClawAdapter) CreateSession

func (p *PicoClawAdapter) CreateSession(_ context.Context, name string) (*Session, error)

CreateSession generates a new session UUID. PicoClaw creates sessions implicitly when a message is sent with a new session_id.

func (*PicoClawAdapter) DeleteSession

func (p *PicoClawAdapter) DeleteSession(ctx context.Context, sessionKey string) error

DeleteSession permanently removes a session via the web backend API.

func (*PicoClawAdapter) Framework

func (p *PicoClawAdapter) Framework() string

func (*PicoClawAdapter) Health

func (p *PicoClawAdapter) Health(ctx context.Context) (*HealthStatus, error)

Health probes the gateway's /health endpoint for status, uptime, and PID, then enriches with process-level stats from ps.

func (*PicoClawAdapter) ID

func (p *PicoClawAdapter) ID() string

func (*PicoClawAdapter) Interrupt

func (p *PicoClawAdapter) Interrupt(_ context.Context, _ string) error

func (*PicoClawAdapter) Name

func (p *PicoClawAdapter) Name() string

func (*PicoClawAdapter) Personality

func (p *PicoClawAdapter) Personality(ctx context.Context) (*Personality, error)

Personality reads SOUL.md and IDENTITY.md from the workspace directory, and returns config.json as an identity file.

func (*PicoClawAdapter) ResetSession

func (p *PicoClawAdapter) ResetSession(ctx context.Context, sessionKey string) error

ResetSession archives/deletes a session via the web backend API.

func (*PicoClawAdapter) Restart

func (p *PicoClawAdapter) Restart(ctx context.Context) error

Restart sends a POST to the web backend to restart the gateway.

func (*PicoClawAdapter) SendMessage

func (p *PicoClawAdapter) SendMessage(ctx context.Context, message, sessionKey string) (*ChatMessage, error)

SendMessage sends a message and collects the full response. Delegates to StreamMessage and reads until done, following the ZeroClaw pattern.

func (*PicoClawAdapter) Sessions

func (p *PicoClawAdapter) Sessions(ctx context.Context) ([]Session, error)

Sessions lists active sessions from the web backend.

func (*PicoClawAdapter) Start

func (p *PicoClawAdapter) Start(ctx context.Context) error

Start sends a POST to the web backend to start the gateway.

func (*PicoClawAdapter) Status

func (p *PicoClawAdapter) Status(ctx context.Context) (*AgentStatus, error)

Status queries the web backend for gateway status when online, falling back to parsing the config file for model/provider/channels when offline.

func (*PicoClawAdapter) Stop

func (p *PicoClawAdapter) Stop(ctx context.Context) error

Stop sends a POST to the web backend to stop the gateway.

func (*PicoClawAdapter) StreamMessage

func (p *PicoClawAdapter) StreamMessage(ctx context.Context, message, sessionKey string) (<-chan ChatEvent, error)

StreamMessage connects to the Pico Protocol WebSocket and streams the response.

Protocol:

  • Send: {type: "message.send", session_id, timestamp, payload: {content}}
  • Receive: message.update (streaming delta via full-content diffing) message.create (final complete response) error (error event)
  • Ignored: typing.start, typing.stop, pong

message.update delivers full-content replacements. The adapter diffs successive updates to emit append-only deltas for Eyrie's ChatEvent model.

func (*PicoClawAdapter) TailActivity

func (p *PicoClawAdapter) TailActivity(ctx context.Context) (<-chan ActivityEvent, error)

TailActivity reads historical log entries and classifies them as activity events, then polls for live updates.

func (*PicoClawAdapter) TailLogs

func (p *PicoClawAdapter) TailLogs(ctx context.Context) (<-chan LogEntry, error)

TailLogs reads historical log entries from the gateway log file (zerolog JSON), then polls the web backend's /api/gateway/logs endpoint every 2 seconds for live updates.

type Session

type Session struct {
	Key      string     `json:"key"`
	Title    string     `json:"title"`
	LastMsg  *time.Time `json:"last_message,omitempty"`
	Channel  string     `json:"channel,omitempty"`
	ReadOnly bool       `json:"readonly,omitempty"`
}

type ZeroClawAdapter

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

ZeroClawAdapter communicates with a ZeroClaw instance via its HTTP REST gateway and WebSocket chat endpoint. ZeroClaw exposes: GET /health, GET /api/status, GET /api/config, GET /api/events (SSE).

func NewZeroClawAdapter

func NewZeroClawAdapter(id, name, baseURL, token, configPath string) *ZeroClawAdapter

func (*ZeroClawAdapter) ActivateSession

func (z *ZeroClawAdapter) ActivateSession(_ context.Context, _ string) error

ActivateSession is a no-op for upstream ZeroClaw (0.5.7+) since sessions are selected per-connection via the ?session_id query param on the WS endpoint. Kept for interface compatibility with the hierarchy briefing handler.

func (*ZeroClawAdapter) BaseURL

func (z *ZeroClawAdapter) BaseURL() string

func (*ZeroClawAdapter) Capabilities

func (z *ZeroClawAdapter) Capabilities() AgentCapabilities

func (*ZeroClawAdapter) ChatHistory

func (z *ZeroClawAdapter) ChatHistory(ctx context.Context, sessionKey string, limit int) ([]ChatMessage, error)

ChatHistory returns conversation messages for a session. It reads from ZeroClaw's SQLite session database as the source of truth, then enriches messages with tool call parts from Eyrie's JSONL store where available. Falls back to the legacy memory API if neither is available.

func (*ZeroClawAdapter) Config

func (z *ZeroClawAdapter) Config(ctx context.Context) (*AgentConfig, error)

func (*ZeroClawAdapter) CreateSession

func (z *ZeroClawAdapter) CreateSession(_ context.Context, name string) (*Session, error)

CreateSession generates a new session ID for ZeroClaw. Upstream creates sessions implicitly on first WS message, so we just return the ID. The session will be created in the backend when StreamMessage connects.

func (*ZeroClawAdapter) DeleteSession

func (z *ZeroClawAdapter) DeleteSession(ctx context.Context, sessionKey string) error

func (*ZeroClawAdapter) DestroySession

func (z *ZeroClawAdapter) DestroySession(ctx context.Context, sessionKey string) error

func (*ZeroClawAdapter) Framework

func (z *ZeroClawAdapter) Framework() string

func (*ZeroClawAdapter) Health

func (z *ZeroClawAdapter) Health(ctx context.Context) (*HealthStatus, error)

func (*ZeroClawAdapter) ID

func (z *ZeroClawAdapter) ID() string

func (*ZeroClawAdapter) Interrupt

func (z *ZeroClawAdapter) Interrupt(_ context.Context, _ string) error

Interrupt asks ZeroClaw to cancel an in-flight response. TODO: Call POST /api/sessions/{id}/abort once upstream ships zeroclaw-labs/zeroclaw#XXXX. Until then, this is a no-op — context cancellation on the WS connection is the only way to stop receiving, but the agent continues processing.

func (*ZeroClawAdapter) Name

func (z *ZeroClawAdapter) Name() string

func (*ZeroClawAdapter) Personality

func (z *ZeroClawAdapter) Personality(ctx context.Context) (*Personality, error)

func (*ZeroClawAdapter) ResetSession

func (z *ZeroClawAdapter) ResetSession(ctx context.Context, sessionKey string) error

func (*ZeroClawAdapter) Restart

func (z *ZeroClawAdapter) Restart(ctx context.Context) error

func (*ZeroClawAdapter) SendMessage

func (z *ZeroClawAdapter) SendMessage(ctx context.Context, message, sessionKey string) (*ChatMessage, error)

func (*ZeroClawAdapter) Sessions

func (z *ZeroClawAdapter) Sessions(ctx context.Context) ([]Session, error)

Sessions returns sessions from ZeroClaw's session backend (0.5.7+). Upstream uses UUID-based session_ids with a gw_ prefix internally. Falls back to a synthetic "memory" session for older versions.

func (*ZeroClawAdapter) Start

func (z *ZeroClawAdapter) Start(ctx context.Context) error

func (*ZeroClawAdapter) Status

func (z *ZeroClawAdapter) Status(ctx context.Context) (*AgentStatus, error)

func (*ZeroClawAdapter) Stop

func (z *ZeroClawAdapter) Stop(ctx context.Context) error

func (*ZeroClawAdapter) StreamMessage

func (z *ZeroClawAdapter) StreamMessage(ctx context.Context, message, sessionKey string) (<-chan ChatEvent, error)

StreamMessage connects to ZeroClaw's WebSocket chat endpoint with session support. The upstream WS handler (0.5.7+) creates a persistent Agent per connection, hydrates it from the session backend, and runs multi-turn chat with full tool execution.

func (*ZeroClawAdapter) TailActivity

func (z *ZeroClawAdapter) TailActivity(ctx context.Context) (<-chan ActivityEvent, error)

TailActivity emits historical activity from the daemon log, then connects to the ZeroClaw SSE event stream for live events.

func (*ZeroClawAdapter) TailLogs

func (z *ZeroClawAdapter) TailLogs(ctx context.Context) (<-chan LogEntry, error)

TailLogs emits historical log entries from the daemon log file, then connects to the ZeroClaw SSE event stream for live entries. If the agent is not running, historical logs are still returned before closing.

Jump to

Keyboard shortcuts

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