Documentation
¶
Overview ¶
Package control is part of the GoFastr harness.
See docs/harness-architecture.md for the architecture this package implements.
Package control hosts the engine-as-a-service control plane.
This file defines the transport-agnostic wire protocol: the canonical event envelope, the Command and Event sealed unions, the handshake, and the JSON codec. Every transport carries the same canonical event JSON verbatim; envelopes are framing only.
See docs/harness-architecture.md § Control plane + § Protocol versioning & evolution.
Index ¶
- Constants
- Variables
- func AllCommandKinds() []string
- func AllEventKinds() []string
- func MarshalCommand(c Command) ([]byte, error)
- type AnswerPermission
- type AttachSession
- type CancelTurn
- type Cancelled
- type Client
- type Command
- type CompactionTriggered
- type ContentBlock
- type CostIncremented
- type CreateSession
- type CustomCommand
- type CustomEvent
- type Decision
- type DetachSession
- type EnterPlanMode
- type Error
- type Event
- type EventEnvelope
- type ExitPlanMode
- type Handshake
- type HookError
- type HookTimeout
- type IdentityClass
- type ImageBlock
- type MCPServerDown
- type PermissionRequested
- type PermitScope
- type SendInput
- type SessionEnded
- type SetModel
- type StreamGap
- type TextDelta
- type ThinkingDelta
- type TokenExpiring
- type ToolCallProgress
- type ToolCallStarted
- type ToolResult
- type ToolResultBlk
- type ToolTimingEntry
- type ToolUse
- type TurnEnded
- type TurnStarted
- type TurnTiming
- type YieldBlock
Constants ¶
const ( SchemaVersionTokenClaim = 1 SchemaVersionProfile = 1 SchemaVersionSessionLog = 1 )
Schema versions of independently-evolving sub-schemas, surfaced in the handshake response.
const ( ReasonHandshakeRequired = "HandshakeRequired" ReasonHandshakeVersionMismatch = "HandshakeVersionMismatch" ReasonTurnInProgress = "TurnInProgress" ReasonPermissionDenied = "PermissionDenied" ReasonPermissionTimeout = "PermissionTimeout" ReasonTokenExpired = "TokenExpired" ReasonTokenRevoked = "TokenRevoked" ReasonMCPServerSHA256Mismatch = "MCPServerSHA256Mismatch" ReasonHookHashChanged = "HookHashChanged" ReasonHookTimeout = "HookTimeout" ReasonRateLimited = "RateLimited" ReasonBashCancelledMidCommand = "BashCancelledMidCommand" ReasonNonInteractiveAckRefused = "NonInteractiveAckRefused" ReasonCredentialHelperFailed = "CredentialHelperFailed" ReasonInvalidCommand = "InvalidCommand" )
Stable Reason codes used in Error events. Strings are documented in docs/harness-architecture.md § User-facing errors.
const CanonicalFormVersion = 1
CanonicalFormVersion is the version of the internal Anthropic-shape canonical message form. Provider adapters target an explicit version; the engine asserts they match.
const ProtocolVersion = "0.1.0"
ProtocolVersion is the SemVer string identifying the wire protocol. Minor bumps are additive-only; major bumps require client re-implementation. See docs § Protocol versioning → Handshake.
const ResourceURIScheme = "harness/v1"
ResourceURIScheme is the URI scheme for MCP-server-exposed resources. Pinned to v1 so a v2 scheme can coexist later.
Variables ¶
var ErrClientClosed = errors.New("control: client closed")
ErrClientClosed is returned when a client method is called after Close.
var FeaturesV01 = []string{
"rest",
"branching",
"auto_approve",
"plan_mode",
}
FeaturesV01 is the feature flag set advertised by v0.1 builds.
Per the build-order section of the architecture doc:
- inproc + rest transports are first-class in v0.1
- ws + mcpserver_stdio land in v0.2
- mcpserver_http lands in v0.3
- delegate ships with v0.3
Functions ¶
func AllCommandKinds ¶
func AllCommandKinds() []string
AllCommandKinds returns the closed set of built-in command kinds, in the order they appear in the handshake response.
func AllEventKinds ¶
func AllEventKinds() []string
AllEventKinds returns the closed set of built-in event kinds.
func MarshalCommand ¶
MarshalCommand encodes a Command to JSON with a "kind" discriminator.
Types ¶
type AnswerPermission ¶
type AnswerPermission struct {
SessionID ids.SessionID `json:"sessionId"`
CallID ids.CallID `json:"callId"`
Decision Decision `json:"decision"`
Scope PermitScope `json:"scope,omitempty"` // for argv-glob/tool/session allow buttons
}
func (AnswerPermission) CommandKind ¶
func (AnswerPermission) CommandKind() string
type AttachSession ¶
func (AttachSession) CommandKind ¶
func (AttachSession) CommandKind() string
type CancelTurn ¶
func (CancelTurn) CommandKind ¶
func (CancelTurn) CommandKind() string
type Cancelled ¶
type Client ¶
type Client interface {
// ID returns the client's stable identifier for the lifetime of
// the attach. Cross-references the OriginatorID embedded in
// event envelopes the engine emits for turns this client started.
ID() ids.ClientID
// IdentityClass distinguishes human-driven clients from
// agent-driven ones. Permission middleware honors this.
IdentityClass() IdentityClass
// Subscribe returns a receive-only channel of events broadcast
// to this client. The channel is closed when the client is
// detached or the context is done.
Subscribe(ctx context.Context) <-chan EventEnvelope
// Send delivers a command from the client to the multiplexer.
// Returns an error if the transport is closed or the command
// fails wire-format validation.
Send(ctx context.Context, cmd Command) error
// Close detaches the client. Detach is non-destructive at the
// engine level — see § Multi-client semantics.
Close() error
}
Client is the transport-agnostic abstraction the multiplexer uses to route commands and events. Every transport (inproc, rest, ws, mcpserver) provides a Client implementation.
Per hard rule 7, the engine sees only this interface — it never inspects how a client is wired.
type Command ¶
type Command interface {
// CommandKind returns the kind discriminator used on the wire
// (matches handshake.command_kinds entries).
CommandKind() string
// contains filtered or unexported methods
}
Command is a sealed union of wire-level verbs sent from clients to the engine. Per hard rule 14, this set is closed in `control/`; plugins extend via CustomCommand.
func UnmarshalCommand ¶
UnmarshalCommand decodes a wire JSON envelope back into a typed Command. Unknown command kinds return an error (closed-union enforcement).
type CompactionTriggered ¶
type CompactionTriggered struct {
BeforeTokens int `json:"beforeTokens"`
AfterTokens int `json:"afterTokens"`
}
func (CompactionTriggered) EventKind ¶
func (CompactionTriggered) EventKind() string
type ContentBlock ¶
type ContentBlock struct {
Type string `json:"type"`
// Type-specific fields. Only the field matching Type is meaningful.
Text string `json:"text,omitempty"`
ToolUse *ToolUse `json:"tool_use,omitempty"`
ToolResult *ToolResultBlk `json:"tool_result,omitempty"`
Thinking json.RawMessage `json:"thinking,omitempty"` // opaque, provider-stamped
Image *ImageBlock `json:"image,omitempty"`
Yield *YieldBlock `json:"yield,omitempty"` // explicit end-turn signal
}
ContentBlock is a typed content item in a message. Blocks have a "type" discriminator on the wire.
type CostIncremented ¶
type CostIncremented struct {
Provider string `json:"provider"`
Model string `json:"model"`
InputTokens int `json:"inputTokens"`
OutputTokens int `json:"outputTokens"`
CacheTokens int `json:"cacheTokens,omitempty"`
USD float64 `json:"usd"`
}
func (CostIncremented) EventKind ¶
func (CostIncremented) EventKind() string
type CreateSession ¶
type CreateSession struct {
Profile string `json:"profile"`
// Resume, when non-nil, attaches the new EngineRun to an existing LogID.
Resume *ids.LogID `json:"resume,omitempty"`
}
func (CreateSession) CommandKind ¶
func (CreateSession) CommandKind() string
type CustomCommand ¶
type CustomCommand struct {
SessionID ids.SessionID `json:"sessionId"`
Namespace string `json:"namespace"` // matches a claimed slash-command namespace
Verb string `json:"verb"`
Payload json.RawMessage `json:"payload"`
}
CustomCommand is the open extension verb for plugin-defined wire commands. The engine routes by Namespace to the registered plugin handler.
func (CustomCommand) CommandKind ¶
func (CustomCommand) CommandKind() string
type CustomEvent ¶
type CustomEvent struct {
Namespace string `json:"namespace"`
Kind string `json:"kind"`
Payload json.RawMessage `json:"payload"`
}
CustomEvent is the open extension event for plugin-defined wire events.
func (CustomEvent) EventKind ¶
func (CustomEvent) EventKind() string
type DetachSession ¶
func (DetachSession) CommandKind ¶
func (DetachSession) CommandKind() string
type EnterPlanMode ¶
func (EnterPlanMode) CommandKind ¶
func (EnterPlanMode) CommandKind() string
type Error ¶
type Error struct {
Reason string `json:"reason"` // stable error code
Message string `json:"message"` // human-friendly text
Details json.RawMessage `json:"details,omitempty"`
}
type Event ¶
type Event interface {
EventKind() string
// contains filtered or unexported methods
}
Event is a sealed union of engine-emitted events. Per hard rule 14, this set is closed in `control/`; plugins extend via CustomEvent.
func DecodeEvent ¶
func DecodeEvent(env EventEnvelope) (Event, error)
DecodeEvent extracts the typed event payload from a canonical envelope. Unknown event kinds return an error.
type EventEnvelope ¶
type EventEnvelope struct {
ID uint64 `json:"id"` // monotonic per SessionID
Kind string `json:"kind"` // matches handshake.event_kinds
Session ids.SessionID `json:"session"`
Originator ids.ClientID `json:"originator,omitempty"`
TS time.Time `json:"ts"`
Payload json.RawMessage `json:"payload"`
}
EventEnvelope is the canonical JSON wrapper used by every transport. Transports may add their own framing on top (SSE `id:`/`event:`/`data:`, WS `{"frame":"event","body":...}`, MCP `notifications/resources/updated`), but the body is always this envelope.
type ExitPlanMode ¶
type ExitPlanMode struct {
SessionID ids.SessionID `json:"sessionId"`
Approve bool `json:"approve"`
}
func (ExitPlanMode) CommandKind ¶
func (ExitPlanMode) CommandKind() string
type Handshake ¶
type Handshake struct {
ProtocolVersion string `json:"protocol_version"`
CanonicalFormVersion int `json:"canonical_form_version"`
SchemaVersionTokenClaim int `json:"schema_version_token_claim"`
SchemaVersionProfile int `json:"schema_version_profile"`
SchemaVersionSessionLog int `json:"schema_version_session_log"`
CommandKinds []string `json:"command_kinds"`
EventKinds []string `json:"event_kinds"`
Features []string `json:"features"`
ResourceURIScheme string `json:"resource_uri_scheme"`
}
Handshake is the response to GET /v1/handshake (or the first frame on a WS/MCP session). Required before any other command.
func CurrentHandshake ¶
CurrentHandshake returns the handshake advertised by this binary. The Features list is provided by the caller so different builds (e.g. v0.1 vs v0.2) can advertise different optional capabilities.
type HookError ¶
type HookTimeout ¶
type HookTimeout struct {
Event string `json:"event"`
Command string `json:"command"`
After time.Duration `json:"after"`
}
func (HookTimeout) EventKind ¶
func (HookTimeout) EventKind() string
type IdentityClass ¶
type IdentityClass uint8
IdentityClass distinguishes human-driven clients from agent-driven ones. See hard rule 11 in the architecture doc.
const ( IdentityHuman IdentityClass = iota IdentityAgent )
func (IdentityClass) MarshalJSON ¶
func (c IdentityClass) MarshalJSON() ([]byte, error)
MarshalJSON encodes the IdentityClass as its lowercase wire string.
func (IdentityClass) String ¶
func (c IdentityClass) String() string
String returns the wire-format string for the identity class.
func (*IdentityClass) UnmarshalJSON ¶
func (c *IdentityClass) UnmarshalJSON(data []byte) error
UnmarshalJSON decodes the IdentityClass from its lowercase wire string.
type ImageBlock ¶
ImageBlock is a base64-encoded image content block.
type MCPServerDown ¶
type MCPServerDown struct {
Name string `json:"name"`
Reason string `json:"reason"`
Attempts int `json:"attempts"`
}
func (MCPServerDown) EventKind ¶
func (MCPServerDown) EventKind() string
type PermissionRequested ¶
type PermissionRequested struct {
CallID ids.CallID `json:"callId"`
Tool string `json:"tool"`
Args json.RawMessage `json:"args"`
Originator ids.ClientID `json:"originator"`
Reason string `json:"reason,omitempty"` // e.g. why this is being asked
}
func (PermissionRequested) EventKind ¶
func (PermissionRequested) EventKind() string
type PermitScope ¶
type PermitScope string
PermitScope describes how broadly an "allow" decision applies.
const ( ScopeOnce PermitScope = "once" ScopeArgvGlob PermitScope = "argv_glob" ScopeTool PermitScope = "tool" ScopeSessionWide PermitScope = "session" // ScopeAlways persists the rule to disk so subsequent harness // runs honor it without re-prompting. The persistence layer // (XDG_CONFIG_HOME/gofastr/harness/permissions.json) is loaded // on Engine boot. ScopeAlways PermitScope = "always" )
type SendInput ¶
type SendInput struct {
SessionID ids.SessionID `json:"sessionId"`
Content []ContentBlock `json:"content"`
// Wait controls REST/MCP synchronous vs streaming behavior.
// "" / "none" → returns immediately; "turn" → blocks until TurnEnded.
Wait string `json:"wait,omitempty"`
}
func (SendInput) CommandKind ¶
type SessionEnded ¶
type SessionEnded struct {
Reason string `json:"reason"` // "idle" | "user" | "error" | "binary-shutdown"
}
func (SessionEnded) EventKind ¶
func (SessionEnded) EventKind() string
type SetModel ¶
func (SetModel) CommandKind ¶
type StreamGap ¶
type ThinkingDelta ¶
type ThinkingDelta struct {
Block json.RawMessage `json:"block"` // opaque, provider-stamped
}
func (ThinkingDelta) EventKind ¶
func (ThinkingDelta) EventKind() string
type TokenExpiring ¶
func (TokenExpiring) EventKind ¶
func (TokenExpiring) EventKind() string
type ToolCallProgress ¶
func (ToolCallProgress) EventKind ¶
func (ToolCallProgress) EventKind() string
type ToolCallStarted ¶
type ToolCallStarted struct {
CallID ids.CallID `json:"callId"`
Tool string `json:"tool"`
Args json.RawMessage `json:"args"`
Mutating bool `json:"mutating"`
}
func (ToolCallStarted) EventKind ¶
func (ToolCallStarted) EventKind() string
type ToolResult ¶
type ToolResult struct {
CallID ids.CallID `json:"callId"`
Content []ContentBlock `json:"content"`
IsError bool `json:"isError,omitempty"`
}
func (ToolResult) EventKind ¶
func (ToolResult) EventKind() string
type ToolResultBlk ¶
type ToolResultBlk struct {
ToolUseID string `json:"tool_use_id"`
Content []ContentBlock `json:"content"`
IsError bool `json:"is_error,omitempty"`
}
ToolResultBlk is the result of a tool invocation, fed back to the model on the next turn.
type ToolTimingEntry ¶
type ToolUse ¶
type ToolUse struct {
ID string `json:"id"` // matches a tool_use id later in ToolResultBlk
Name string `json:"name"` // tool name
Input json.RawMessage `json:"input"` // tool-call arguments
}
ToolUse is a model-emitted tool invocation.
type TurnEnded ¶
type TurnStarted ¶
type TurnStarted struct {
Turn int `json:"turn"`
Originator ids.ClientID `json:"originator"`
// Content is the input that started this turn. Lets non-originator
// clients (browser sidecar attached to the same session as the TUI,
// or vice-versa) render the user message without round-tripping
// through a separate "echo" event. Optional for backwards
// compatibility — older publishers may omit it.
Content []ContentBlock `json:"content,omitempty"`
}
func (TurnStarted) EventKind ¶
func (TurnStarted) EventKind() string
type TurnTiming ¶
type TurnTiming struct {
Turn int `json:"turn"`
Components map[string]time.Duration `json:"components"`
ToolCalls []ToolTimingEntry `json:"toolCalls,omitempty"`
}
TurnTiming is emitted at TurnEnded with per-component duration data. Operators answer "where was the time?" from a single event.
func (TurnTiming) EventKind ¶
func (TurnTiming) EventKind() string
type YieldBlock ¶
type YieldBlock struct {
Reason string `json:"reason,omitempty"`
}
YieldBlock signals an explicit end-of-turn from the provider.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package auth implements the capability-token model: claim set, internal JWT-like encoding (no third-party dep), revocation list, and the issuance flow with TTY/notification confirmation.
|
Package auth implements the capability-token model: claim set, internal JWT-like encoding (no third-party dep), revocation list, and the issuance flow with TTY/notification confirmation. |
|
Package conformance is the cross-transport parity test framework.
|
Package conformance is the cross-transport parity test framework. |
|
Package inproc is part of the GoFastr harness.
|
Package inproc is part of the GoFastr harness. |
|
Package mcpserver will expose the harness engine as an MCP server.
|
Package mcpserver will expose the harness engine as an MCP server. |
|
Package multiplex is part of the GoFastr harness.
|
Package multiplex is part of the GoFastr harness. |
|
Package resources is part of the GoFastr harness.
|
Package resources is part of the GoFastr harness. |
|
Package rest is part of the GoFastr harness.
|
Package rest is part of the GoFastr harness. |
|
Package ws will implement the WebSocket transport for the control plane.
|
Package ws will implement the WebSocket transport for the control plane. |