smith

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Mar 9, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package smith manages Claude Code CLI process spawning for Smith workers.

Each Smith is a Claude Code process running in a worktree directory, executing autonomously against a bead's description/prompt.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Process

type Process struct {
	// Cmd is the underlying exec.Cmd (nil after completion).
	Cmd *exec.Cmd
	// LogPath is the path to the session log file.
	LogPath string
	// PID is the process ID once started.
	PID int
	// contains filtered or unexported fields
}

Process represents a running or completed Smith (Claude Code) process.

func NewProcessForTest

func NewProcessForTest(result *Result) *Process

NewProcessForTest creates a Process that has already completed and whose Wait() immediately returns the provided result. Intended for use in tests of packages that depend on smith without needing to spawn a real process.

func Spawn

func Spawn(ctx context.Context, worktreePath, promptText, logDir string, extraFlags []string) (*Process, error)

Spawn starts a Claude Code process in the given worktree directory. This is a convenience wrapper around SpawnWithProvider using provider.Claude.

logDir is where the session log file is written.

func SpawnWithProvider

func SpawnWithProvider(ctx context.Context, worktreePath, promptText, logDir string, pv provider.Provider, extraFlags []string) (*Process, error)

SpawnWithProvider starts an AI coding agent process for the given provider. The provider determines which binary is executed and how arguments are built.

logDir is where the session log file is written.

func (*Process) Done

func (p *Process) Done() <-chan struct{}

Done returns a channel that is closed when the process completes.

func (*Process) IsRunning

func (p *Process) IsRunning() bool

IsRunning returns true if the process is still running.

func (*Process) Kill

func (p *Process) Kill() error

Kill forcefully terminates the process.

func (*Process) Wait

func (p *Process) Wait() *Result

Wait blocks until the process completes and returns the result.

type RateLimitInfo

type RateLimitInfo struct {
	Status            string `json:"status"`
	ResetAt           string `json:"reset_at,omitempty"` // RFC3339 timestamp from Claude
	ResetsAt          int64  `json:"resetsAt,omitempty"` // Unix epoch seconds (observed in real rate_limit_event payloads)
	RequestsRemaining int    `json:"requests_remaining,omitempty"`
	RequestsLimit     int    `json:"requests_limit,omitempty"`
	RequestsReset     string `json:"requests_reset,omitempty"` // RFC3339 or similar
	TokensRemaining   int    `json:"tokens_remaining,omitempty"`
	TokensLimit       int    `json:"tokens_limit,omitempty"`
	TokensReset       string `json:"tokens_reset,omitempty"`
}

RateLimitInfo is the payload of a Claude rate_limit_event.

type Result

type Result struct {
	// ExitCode is the process exit code.
	ExitCode int
	// Duration is how long the process ran.
	Duration time.Duration
	// Output is the raw stdout collected.
	Output string
	// ErrorOutput is the raw stderr collected.
	ErrorOutput string
	// Summary is extracted from the stream-json output (last assistant message).
	Summary string
	// FullOutput is the complete text response from the AI (from the result event).
	FullOutput string
	// CostUSD is the total cost if extractable from output.
	CostUSD float64
	// TokensIn is the total input tokens if extractable.
	TokensIn int
	// TokensOut is the total output tokens if extractable.
	TokensOut int
	// RateLimited is true when the provider refused the request due to quota.
	RateLimited bool
	// IsError is true when the result event had is_error:true (session aborted,
	// e.g. hard rate-limit rejection). A success subtype with is_error:true
	// means Claude returned the rate-limit message as the "result" text, and we
	// must NOT treat this as a successful session.
	IsError bool
	// ResultSubtype is the stream-json result event subtype (e.g. "success",
	// "error_max_turns", "error_rate_limit_exceeded").
	ResultSubtype string
	// ProviderUsed records which provider produced this result.
	ProviderUsed provider.Kind
	// Quota contains the latest known quota information from the provider.
	Quota *provider.Quota
	// GeminiStats holds the raw stats block from a Gemini result event.
	// Nil for non-Gemini providers or when no stats were emitted.
	GeminiStats *StreamStats
}

Result captures the outcome of a Smith session.

type StreamEvent

type StreamEvent struct {
	Type    string          `json:"type"`
	Subtype string          `json:"subtype,omitempty"`
	Message json.RawMessage `json:"message,omitempty"`
	Content string          `json:"content,omitempty"`
	// Role is present on Gemini delta message events (role: "assistant" or "user").
	Role string `json:"role,omitempty"`
	// Fields present when type == "result":
	Result       string       `json:"result,omitempty"`
	IsError      bool         `json:"is_error,omitempty"`
	TotalCostUSD float64      `json:"total_cost_usd,omitempty"`
	Usage        *StreamUsage `json:"usage,omitempty"`
	// Stats from Gemini result event
	Stats *StreamStats `json:"stats,omitempty"`
	// rate_limit_event fields
	RateLimitInfo *RateLimitInfo `json:"rate_limit_info,omitempty"`
}

StreamEvent represents a single event from a provider's stream-json output.

type StreamStats

type StreamStats struct {
	TotalTokens     int `json:"total_tokens,omitempty"`
	InputTokens     int `json:"input_tokens,omitempty"`
	OutputTokens    int `json:"output_tokens,omitempty"`
	Cached          int `json:"cached,omitempty"`
	Input           int `json:"input,omitempty"`
	DurationMs      int `json:"duration_ms,omitempty"`
	ToolCalls       int `json:"tool_calls,omitempty"`
	RequestsLimit   int `json:"requests_limit,omitempty"`
	RequestsUsed    int `json:"requests_used,omitempty"`
	RequestsResetMs int `json:"requests_reset_ms,omitempty"`
	TokensLimit     int `json:"tokens_limit,omitempty"`
	TokensUsed      int `json:"tokens_used,omitempty"`
	TokensResetMs   int `json:"tokens_reset_ms,omitempty"`
}

StreamStats from Gemini result event.

type StreamUsage

type StreamUsage struct {
	InputTokens  int `json:"input_tokens"`
	OutputTokens int `json:"output_tokens"`
}

StreamUsage holds token counts from the result event.

Jump to

Keyboard shortcuts

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