package herdr import ( "context" "time" ) // Backend is the machine-local terminal/process seam used by a federation // worker. Herdr remains the default implementation; tmux is a deliberately // smaller alternative for Claude Code hosts that do not run herdr. // // The interface deals only in local session operations. Git checkout and // lease ownership stay with orchestra-worker regardless of the backend. type Backend interface { Kind() string Check(context.Context) error Worktree(context.Context, string, string, string) (string, error) StartAgent(context.Context, string, string, string, string, string) (Session, error) Prompt(context.Context, string, string, time.Duration) error Kill(context.Context, Session) error AgentStatus(context.Context, Session) (string, error) PaneCapture(context.Context, Session, string) (string, error) SendText(context.Context, Session, string) error SendKeys(context.Context, Session, []string) error ReleaseAgent(context.Context, Session, string) error } // Kind identifies the existing JSON-RPC backend. func (c *Client) Kind() string { return "herdr" } // Check verifies the live protocol rather than treating an open socket as a // healthy execution backend. func (c *Client) Check(ctx context.Context) error { return c.CheckProtocol(ctx, "17") } func (c *Client) Kill(ctx context.Context, s Session) error { return c.Call(ctx, "pane.close", map[string]any{"pane_id": s.PaneID}, nil) } func (c *Client) AgentStatus(ctx context.Context, s Session) (string, error) { var result map[string]any if err := c.Call(ctx, "agent.get", map[string]any{"target": s.PaneID}, &result); err != nil { return "", err } return statusFromAgentResult(result), nil } func (c *Client) PaneCapture(ctx context.Context, s Session, source string) (string, error) { if source == "" { source = "recent" } var result struct { Read struct { Text string `json:"text"` } `json:"read"` } if err := c.Call(ctx, "pane.read", map[string]any{"pane_id": s.PaneID, "source": source}, &result); err != nil { return "", err } return result.Read.Text, nil } func (c *Client) SendText(ctx context.Context, s Session, text string) error { return c.Call(ctx, "pane.send_text", map[string]any{"pane_id": s.PaneID, "text": text}, nil) } func (c *Client) SendKeys(ctx context.Context, s Session, keys []string) error { return c.Call(ctx, "pane.send_keys", map[string]any{"pane_id": s.PaneID, "keys": keys}, nil) } func (c *Client) ReleaseAgent(ctx context.Context, s Session, harness string) error { return c.Call(ctx, "pane.release_agent", map[string]any{ "pane_id": s.PaneID, "source": "herdr:" + harness, "agent": agentForSession(s, harness), }, nil) } var _ Backend = (*Client)(nil)