compute

package
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: MIT Imports: 39 Imported by: 0

Documentation

Overview

Package compute is the control-plane state for Compitas: the computes a Compa can run agents on, and the Compitas placed on them.

A Compute is a place (this computer, or another machine that enrolled). A Compita is an agent bound to exactly one Compute at a chosen isolation level. The state lives in compute.json in the Compa home, beside pairing.json, so it adds no keys to config.json and the kernel does not depend on it.

Index

Constants

View Source
const (
	InfoPath = "/info"
	RunPath  = "/run"
)

Paths a dial-in compute serves. Compa calls them with the dial secret.

View Source
const (
	// LiveTunnelPath is where a dial-in compute offers the tunnel.
	LiveTunnelPath = "/live/tunnel"
	// LiveConnectPath is where a dial-out compute connects back; the tunnel's
	// session follows.
	LiveConnectPath = "/api/compute/live/"
	// DefaultLiveAddr is where the browser image serves the live view when the
	// compute itself runs inside that image.
	DefaultLiveAddr = "127.0.0.1:6080"
)

Where a Compita's browser can be watched. The live view is the RFB stream of the browser's virtual display; Compa's own noVNC client shows it, so a machine never serves a page to the dashboard. The machine only carries bytes to the display's WebSocket endpoint (websockify), through a tunnel:

  • the local computer is reached directly;
  • a dial-in compute offers LiveTunnelPath, which Compa dials;
  • a dial-out compute connects back to LiveConnectPath when Compa asks (a control job), as it cannot take connections.
View Source
const (
	DefaultMaxTurns   = 50
	DefaultMaxMinutes = 120
)

Defaults for a new objective.

View Source
const (
	// ApprovalsCareful asks the owner before a tool that writes outside, is
	// destructive or may cost money runs, and before commands run directly on
	// a machine rather than in a container. Everything else follows the
	// machine's own policy.
	ApprovalsCareful = "careful"
	// ApprovalsOpen leaves the machine's own policy as it is.
	ApprovalsOpen = "open"
)

Approval presets a Compita can run with.

View Source
const (
	// FileName is the store's file in the Compa home.
	FileName = "compute.json"
	// TokenTTL is how long an enrollment token can be redeemed.
	TokenTTL = 15 * time.Minute

	// LocalID is the id of the compute that is this computer.
	LocalID = "this-computer"
)
View Source
const (
	MaxPendingEvents = 20
	MaxEventBytes    = 64 << 10
	MinScheduleEvery = 1
)

Limits that keep one source from flooding a Compita.

View Source
const (
	PollPath   = "/api/compute/poll"
	ResultPath = "/api/compute/result"
	EventsPath = "/api/compute/events"
)

Paths a dial-out compute calls on Compa. All authenticate with the credential issued at enrollment.

View Source
const ApproverHookName = "compita-approver"

ApproverHookName is the process hook that routes a Compita's approvals to the owner through the Compa host.

View Source
const BrowserServerName = "browser"

BrowserServerName names the MCP server that drives the browser; the agent sees its tools as mcp_browser_<tool>.

View Source
const DefaultBrowserImage = "compa-compita-browser:local"

DefaultBrowserImage is the image for Compitas with a browser. Build it with docker/Dockerfile.compita-browser, after the default image.

View Source
const DefaultImage = "compa-compita:local"

DefaultImage is the container image used for container isolation. Build it with docker/Dockerfile.compita.

View Source
const EnrollPath = "/api/compute/enroll"

EnrollPath is the Compa endpoint a compute redeems its token at.

View Source
const IdentityFileName = "compute-identity.json"

IdentityFileName is where an enrolled compute keeps who it belongs to.

View Source
const MaxPendingPerCompita = 10

MaxPendingPerCompita keeps a runaway Compita from burying the owner.

View Source
const NoVNCPort = "6080"

NoVNCPort is where the browser image serves its live view (websockify, the WebSocket side of the display's VNC server), inside the container. The machine publishes it on a free loopback port; see LiveAddr.

Variables

View Source
var (
	// ErrDisabled is returned when Compitas support is off.
	ErrDisabled = errors.New("compute: Compitas support is not enabled")
	// ErrNotFound is returned for an unknown compute or Compita.
	ErrNotFound = errors.New("compute: not found")
	// ErrInvalidToken covers an unknown, used or expired enrollment token.
	ErrInvalidToken = errors.New("compute: enrollment token is invalid or expired")
	// ErrInUse is returned when removing a compute that still has Compitas.
	ErrInUse = errors.New("compute: still has Compitas")
)
View Source
var ApprovalWait = 10 * time.Minute

ApprovalWait is how long the host holds a request for the owner.

View Source
var ErrEventsFull = errors.New("compute: too many events are waiting for this Compita")

ErrEventsFull means too many events are waiting.

View Source
var ErrNoLiveView = errors.New("compute: the Compita's browser is not running on this machine right now")

ErrNoLiveView means no browser display of the Compita is up on this machine.

View Source
var ErrNoSuchApproval = errors.New("compute: that approval is no longer waiting")

ErrNoSuchApproval means the request was already answered or has gone.

View Source
var ErrOffline = errors.New("compute: the compute is offline or busy")

ErrOffline means no compute picked the job up in time.

Isolations lists every level, strongest first.

Functions

func AppendChat

func AppendChat(home, compitaID string, m ChatMessage) error

AppendChat adds a message to the Compita's chat log on the Compa host.

func DialInHandler

func DialInHandler(secret string, runner Runner) http.Handler

DialInHandler is what `compute serve --listen` exposes: Compa connects to it, so the machine needs a reachable address but never reaches out.

func DialTunnel

func DialTunnel(ctx context.Context, c Compute, compitaID string, iso Isolation) (net.Conn, error)

DialTunnel opens a tunnel to the live view of a Compita's browser on a dial-in compute. The Compita's isolation tells the machine where to look.

func Drive

func Drive(ctx context.Context, home, id string, opt DriveOptions)

Drive works on the Compita's objective until it ends, or ctx is cancelled. Cancelling leaves an active objective active, so the next start resumes it. Pausing or stopping are done by changing the status; Drive notices after the turn in flight.

The brakes: a turn and a time budget, a cap on failing turns in a row, a cap on identical replies in a row, and a check turn before "done" is accepted.

func EventGoal

func EventGoal(instruction, source, body string) string

EventGoal turns an event into the goal the Compita works on. The event is data from outside, so the prompt says not to take orders from it.

func Fingerprint

func Fingerprint(der []byte) string

Fingerprint is the SHA-256 of a certificate, as lowercase hex.

func FirstPrompt

func FirstPrompt(goal, progress string, colleagues []string) string

FirstPrompt starts work on an objective.

func Free

func Free(o *Objective) bool

Free reports whether a Compita can take new work: it has no objective, or its last one ended. One that is blocked or paused waits for the owner, so scheduled and incoming work waits too.

func InstallCommand

func InstallCommand(baseURL, token string) string

InstallCommand is the one line that runs InstallScript from the host.

func InstallScript

func InstallScript(baseURL, token, kernelSHA256 string) string

InstallScript is the shell script a new machine runs to become a compute: it fetches the kernel from the Compa host that issued the token (checked against sha256), enrolls with the one-time token, connects the free model providers if the machine has no model setup, and keeps `compute serve` running under systemd when it can. Everything it needs comes from the host, so there is nothing to download from anywhere else.

func LiveAddr

func LiveAddr(id string, iso Isolation) (string, bool)

LiveAddr says where the live view of the Compita's browser listens on this machine, if it is up. A browser in a container is published on a free loopback port while its turn runs. Otherwise the browser is the machine's own, and a compute that runs inside the browser image has the live view at COMPA_LIVE_ADDR, by default DefaultLiveAddr. The two never mix: a Compita in a container must not be shown whatever else listens on the default address.

func LoadOrCreateCert

func LoadOrCreateCert(home string) (tls.Certificate, string, error)

LoadOrCreateCert returns a self-signed certificate kept in home, creating it on first use, and its fingerprint.

func NewTriggerToken

func NewTriggerToken(home, id, instruction, baseURL string) (string, error)

NewTriggerToken creates (or replaces) the token events must carry and says what to do with them. The old token stops working.

func NextPrompt

func NextPrompt(goal, note, progress string, colleagues []string) string

NextPrompt asks for the next step after a turn that did not finish.

func NextWork

func NextWork(home, id string, now time.Time) (goal, kind string, err error)

NextWork hands out the next thing to start, if any: the oldest waiting event, else a schedule that is due (whose clock then moves on). The Compita must be free to take it.

func QueueEvent

func QueueEvent(home, id, goal string) error

QueueEvent keeps an event for when the Compita is free.

func RemoveSchedule

func RemoveSchedule(home, id, sid string) error

RemoveSchedule deletes a schedule.

func RevokeTrigger

func RevokeTrigger(home, id string) error

RevokeTrigger stops events from being accepted and drops the queued ones.

func SaveIdentity

func SaveIdentity(home string, id Identity) error

SaveIdentity writes the identity to home, readable by its owner only.

func Serve

func Serve(ctx context.Context, id Identity, runner Runner, logf func(string, ...any))

Serve is the loop an enrolled compute runs: poll Compa for jobs, run them, post the results. Jobs run alongside each other and polling goes on while they do, so the compute stays reachable and several Compitas can work at once. It returns only when ctx ends.

func ServeApprover

func ServeApprover(ctx context.Context, in io.Reader, out io.Writer, ask func(ctx context.Context, tool string, args map[string]any) (bool, string)) error

ServeApprover speaks the kernel's process-hook protocol (JSON-RPC 2.0, one message per line) as an approve_tool hook: every call it is asked about goes to ask, and its answer goes back to the kernel.

func SetScheduleEnabled

func SetScheduleEnabled(home, id, sid string, enabled bool, now time.Time) error

SetScheduleEnabled turns a schedule on or off. Turning it on starts its clock afresh.

func Summarize

func Summarize(tool string, args map[string]any) string

Summarize says what a call does in words the owner can judge. The whole command or arguments are shown, up to a generous cap.

func UpdateTriggers

func UpdateTriggers(home, id string, fn func(*Triggers) error) error

UpdateTriggers applies fn to the Compita's triggers under a lock.

func ValidApprovals

func ValidApprovals(p string) bool

ValidApprovals reports whether p is a known preset; empty means careful.

func ValidIsolation

func ValidIsolation(i Isolation) bool

ValidIsolation reports whether i is a known level.

func ValidateConnection

func ValidateConnection(name string, c Connection) error

ValidateConnection checks a connection before it is stored.

func VerifyPrompt

func VerifyPrompt(goal, claimed, progress string) string

VerifyPrompt asks the Compita to prove a claimed result before it counts.

func VerifyTrigger

func VerifyTrigger(t Triggers, bearer, signature string, body []byte) bool

VerifyTrigger reports whether an event request is authentic: the bearer token, or a GitHub-style "sha256=<hmac of body>" signature made with it.

Types

type Approval

type Approval struct {
	ID        string    `json:"id"`
	CompitaID string    `json:"compita_id"`
	Tool      string    `json:"tool"`
	Summary   string    `json:"summary"`
	At        time.Time `json:"at"`
}

Approval is a request waiting for the owner.

type ApprovalAsk

type ApprovalAsk struct {
	From      string         `json:"from"`
	Tool      string         `json:"tool"`
	Arguments map[string]any `json:"arguments,omitempty"`
}

ApprovalAsk is what a Compita's approver hook sends the Compa host when a tool call needs the owner's say-so.

type Broker

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

Broker hands jobs to dial-out computes. They poll for work, so the compute never needs an open port.

func NewBroker

func NewBroker() *Broker

func (*Broker) Complete

func (b *Broker) Complete(computeID string, r Result) bool

Complete delivers what computeID reports for one of its jobs to whoever waits for it. A result for a job that compute does not run is dropped, so no compute can answer for another. It reports whether it was delivered.

func (*Broker) Enqueue

func (b *Broker) Enqueue(computeID string, job Job) error

Enqueue hands a control job to the compute without waiting for an answer.

func (*Broker) Events

func (b *Broker) Events(computeID, jobID string, evs []StreamEvent) bool

Events delivers events a compute reports for one of its running jobs. It reports whether the job is one that compute runs and streams.

func (*Broker) HandleTunnel

func (b *Broker) HandleTunnel(w http.ResponseWriter, r *http.Request, computeID, session string)

HandleTunnel serves the request a compute makes to connect back for a tunnel it was asked for: it upgrades the request to a WebSocket and hands that to whoever waits for session. The caller has authenticated computeID.

func (*Broker) Next

func (b *Broker) Next(ctx context.Context, computeID string, wait time.Duration) (Job, bool)

Next blocks until the compute has a job, wait elapses, or ctx ends.

func (*Broker) Online

func (b *Broker) Online(computeID string) bool

Online reports whether the compute polled recently.

func (*Broker) OpenTunnel

func (b *Broker) OpenTunnel(ctx context.Context, computeID, compitaID string, iso Isolation) (net.Conn, error)

OpenTunnel asks a dial-out compute to connect back with a tunnel to the live view of the Compita's browser, and waits for it.

func (*Broker) Submit

func (b *Broker) Submit(ctx context.Context, computeID string, job Job) (Result, error)

Submit queues job for the compute and waits for its result.

func (*Broker) SubmitStream

func (b *Broker) SubmitStream(ctx context.Context, computeID string, job Job, onEvent func(StreamEvent)) (Result, error)

SubmitStream is Submit that also hands onEvent what the turn does as the compute reports it.

type Capabilities

type Capabilities struct {
	// Docker is true when a container runtime was found.
	Docker bool `json:"docker"`
	// DockerVersion is the runtime's version when Docker is true.
	DockerVersion string `json:"docker_version,omitempty"`
	// Browser is true when the machine has a browser its Compitas can drive
	// without a container of their own (playwright-mcp), as the browser image
	// does. A Compita in a container brings its own.
	Browser bool `json:"browser,omitempty"`
}

Capabilities are what a compute can offer.

func Detect

func Detect() Capabilities

Detect reports what this computer offers Compitas: a container runtime and a browser a Compita outside a container can drive. The browser image has one; so does any machine with playwright-mcp installed.

func DetectDocker

func DetectDocker() Capabilities

DetectDocker asks the local docker CLI for its server version. A missing binary, a stopped daemon and a permission error all mean "no Docker": a Compita cannot use a container runtime it cannot talk to.

func DialInfo

func DialInfo(ctx context.Context, c Compute) (Capabilities, error)

DialInfo asks a dial-in compute what it can do.

type ChatMessage

type ChatMessage struct {
	Role  string    `json:"role"` // "user" or "compita"
	Text  string    `json:"text"`
	Error bool      `json:"error,omitempty"`
	At    time.Time `json:"at"`
}

ChatMessage is one line of a Compita's direct chat with the user.

func LoadChat

func LoadChat(home, compitaID string, limit int) ([]ChatMessage, error)

LoadChat returns up to the last limit messages.

type Compita

type Compita struct {
	ID          string    `json:"id"`
	Name        string    `json:"name"`
	Description string    `json:"description,omitempty"`
	ComputeID   string    `json:"compute_id"`
	Isolation   Isolation `json:"isolation"`
	// Approvals is the approval preset; empty means careful.
	Approvals string `json:"approvals,omitempty"`
	// Browser gives the Compita a web browser it can drive and a human can
	// watch. In a container it brings its own; on the machine itself the
	// compute must have one (see Capabilities).
	Browser bool `json:"browser,omitempty"`
	// Connections are the tools and integrations made for this Compita, as MCP
	// servers it may use (a GitHub server with its token, say). Their
	// environment holds secrets, so the dashboard never gets it back.
	Connections map[string]Connection `json:"connections,omitempty"`
	CreatedAt   time.Time             `json:"created_at"`
}

Compita is an agent placed on one compute.

func (Compita) Redacted

func (p Compita) Redacted() Compita

Redacted returns the Compita as the dashboard may see it: connections keep their command and the names of their variables, never the values.

type Compute

type Compute struct {
	ID           string       `json:"id"`
	Name         string       `json:"name"`
	Kind         Kind         `json:"kind"`
	Mode         Mode         `json:"mode,omitempty"`
	URL          string       `json:"url,omitempty"`
	Status       Status       `json:"status"`
	Capabilities Capabilities `json:"capabilities"`
	CreatedAt    time.Time    `json:"created_at"`
	EnrolledAt   *time.Time   `json:"enrolled_at,omitempty"`
	// CredentialHash is the SHA-256 of the secret the compute presents after
	// enrolling. The secret itself is never stored.
	CredentialHash string `json:"credential_hash,omitempty"`
	// DialSecret is what Compa presents to a dial-in compute. Compa is the
	// client there, so it has to keep the secret; compute.json is mode 0600.
	DialSecret string `json:"dial_secret,omitempty"`
	// PinSHA256 pins the certificate of a dial-in compute that serves its own
	// self-signed certificate (`compute serve --tls`).
	PinSHA256 string `json:"pin_sha256,omitempty"`
}

Compute is a place Compitas can run.

func (Compute) Allows

func (c Compute) Allows(i Isolation) error

Allows reports whether a compute with these capabilities can host a Compita at the given isolation level.

func (Compute) AllowsBrowser

func (c Compute) AllowsBrowser(i Isolation) error

AllowsBrowser reports whether a Compita at isolation level i can have a browser on this compute. Allows has already vouched for Docker when i is a container, whose image has the browser; at the other levels the browser runs on the compute itself, which must have one.

type Connection

type Connection struct {
	Command string            `json:"command"`
	Args    []string          `json:"args,omitempty"`
	Env     map[string]string `json:"env,omitempty"`
}

Connection is an MCP server a Compita can use.

type DriveOptions

type DriveOptions struct {
	// Turn runs one turn of the Compita and returns its reply.
	Turn func(ctx context.Context, prompt string) (string, error)
	// Say records a Compita line in its chat; Log is optional.
	Say func(text string, isError bool)
	// Pause is the gap between turns; Backoff computes retry waits.
	Pause   time.Duration
	Backoff func(failures int) time.Duration
	// MaxFailures is how many turns in a row may fail before the objective
	// is marked blocked. Waiting for an offline compute does not count.
	MaxFailures int
	// MaxStalls is how many identical replies in a row mean no progress.
	MaxStalls int
	// Colleagues names the other Compitas, listed in each prompt. Optional.
	Colleagues func() []string
}

DriveOptions tune Drive; zero values give production behavior.

type EnrollRequest

type EnrollRequest struct {
	Token        string       `json:"token"`
	Capabilities Capabilities `json:"capabilities"`
}

EnrollRequest is what a compute sends to redeem its token.

type EnrollResponse

type EnrollResponse struct {
	ComputeID  string `json:"compute_id"`
	Credential string `json:"credential"`
}

EnrollResponse is what Compa answers with. Credential is shown once.

type Enrollment

type Enrollment struct {
	ComputeID string    `json:"compute_id"`
	TokenHash string    `json:"token_hash"`
	ExpiresAt time.Time `json:"expires_at"`
}

Enrollment is a pending one-time token for a remote compute.

type EventsReport

type EventsReport struct {
	JobID  string        `json:"job_id"`
	Events []StreamEvent `json:"events"`
}

EventsReport is what a compute posts to EventsPath: events of a running job.

type HostAsker

type HostAsker struct {
	URL, ComputeID, Token, Self string
	Client                      *http.Client
}

HostAsker asks the Compa host for the owner's approval. It is built from the same environment as the message_peer tool.

func HostAskerFromEnv

func HostAskerFromEnv() *HostAsker

HostAskerFromEnv returns nil when the Compita has no way to reach its host.

func (*HostAsker) Ask

func (h *HostAsker) Ask(ctx context.Context, tool string, args map[string]any) (bool, string)

Ask posts the request and blocks until the owner answers.

type Identity

type Identity struct {
	CompaURL   string `json:"compa_url"`
	ComputeID  string `json:"compute_id"`
	Credential string `json:"credential"`
}

Identity is the compute's own record of the Compa it enrolled with.

func Enroll

func Enroll(ctx context.Context, client *http.Client, baseURL, token string, caps Capabilities) (Identity, error)

Enroll redeems token at the Compa at baseURL, probing local capabilities first, and returns the identity to keep. It does not store it: see SaveIdentity.

func LoadIdentity

func LoadIdentity(home string) (Identity, error)

LoadIdentity reads the identity saved by SaveIdentity. A compute that has not enrolled returns os.ErrNotExist.

type Inbox

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

Inbox holds the approvals owed to the owner. The turn that asked stays parked inside its tool call until the owner answers, so an answer resumes the very same work.

func NewInbox

func NewInbox() *Inbox

NewInbox returns an empty inbox.

func (*Inbox) Ask

func (in *Inbox) Ask(ctx context.Context, a ApprovalAsk, wait time.Duration) (approved bool, reason string)

Ask files the request and waits for the owner's answer. No answer within wait, or the caller going away, denies it.

func (*Inbox) Decide

func (in *Inbox) Decide(id string, approved bool) (Approval, error)

Decide gives the owner's answer to a waiting request.

func (*Inbox) Pending

func (in *Inbox) Pending(compitaID string) []Approval

Pending lists what waits for the owner, oldest first; compitaID narrows it.

type Isolation

type Isolation string

Isolation is how a Compita is separated from the others on its compute, strongest first.

const (
	// IsolationMachine: the Compita has the whole compute to itself.
	IsolationMachine Isolation = "machine"
	// IsolationContainer: its own container, volume and browser.
	IsolationContainer Isolation = "container"
	// IsolationProfile: a shared container, a separate browser profile.
	// Cookies and files are separate by convention only.
	IsolationProfile Isolation = "profile"
	// IsolationShared: everything is shared with the other Compitas.
	IsolationShared Isolation = "shared"
)

type Job

type Job struct {
	ID        string    `json:"id"`
	CompitaID string    `json:"compita_id"`
	Isolation Isolation `json:"isolation"`
	Session   string    `json:"session"`
	Message   string    `json:"message"`
	Depth     int       `json:"depth,omitempty"`
	Approvals string    `json:"approvals,omitempty"`
	Browser   bool      `json:"browser,omitempty"`
	// Connections are the Compita's own MCP servers.
	Connections map[string]Connection `json:"connections,omitempty"`
	// Events asks the compute to report the turn as it runs.
	Events bool `json:"events,omitempty"`
	// Tunnel, when set, makes this a control job rather than a turn: open a
	// tunnel to the host for this session (see Tunnel in tunnel.go).
	Tunnel string `json:"tunnel,omitempty"`
}

Job is one message for a Compita, handed to the compute that hosts it.

type Kind

type Kind string

Kind says where a compute is.

const (
	// KindLocal is the machine Compa itself runs on.
	KindLocal Kind = "local"
	// KindRemote is another machine that enrolls with a one-time token.
	KindRemote Kind = "remote"
)

type Mode

type Mode string

Mode says who opens the connection between Compa and a remote compute.

const (
	// ModeDialOut: the compute connects out to Compa. It needs no open port.
	ModeDialOut Mode = "dial_out"
	// ModeDialIn: Compa connects to the compute's URL.
	ModeDialIn Mode = "dial_in"
)

type Objective

type Objective struct {
	Goal       string          `json:"goal"`
	Status     ObjectiveStatus `json:"status"`
	Turns      int             `json:"turns"`
	MaxTurns   int             `json:"max_turns"`
	MaxMinutes int             `json:"max_minutes"`
	StartedAt  time.Time       `json:"started_at"`
	UpdatedAt  time.Time       `json:"updated_at"`
	// Spent is the active working time so far, so a budget survives restarts.
	SpentSeconds int `json:"spent_seconds"`
	// Note is the Compita's latest progress note; Summary or Reason end it.
	Note    string `json:"note,omitempty"`
	Summary string `json:"summary,omitempty"`
	Reason  string `json:"reason,omitempty"`
	// Claimed is the Compita's own report that it is done, kept while a check
	// turn confirms it. A Compita that says "done" is not trusted until then.
	Claimed string `json:"claimed,omitempty"`
	// Sig and Stalls spot a Compita that keeps repeating itself.
	Sig    string `json:"sig,omitempty"`
	Stalls int    `json:"stalls,omitempty"`
	// BaseURL is how the Compita reaches Compa to message its peers.
	BaseURL string `json:"base_url,omitempty"`
}

Objective is a goal a Compita keeps working on, turn after turn, until it is done, blocked, out of budget or stopped.

func LoadObjective

func LoadObjective(home, id string) (*Objective, error)

LoadObjective returns the Compita's objective, or nil when it has none.

func StartObjective

func StartObjective(home, id, goal, baseURL string, maxTurns, maxMinutes int) (*Objective, error)

StartObjective sets a new objective and makes it active. A Compita works on one objective at a time; an active one must be stopped first.

func UpdateObjective

func UpdateObjective(home, id string, fn func(*Objective) error) (*Objective, error)

UpdateObjective applies fn to the stored objective under a lock.

func (*Objective) ProgressFile

func (o *Objective) ProgressFile() string

ProgressFile is where the Compita keeps this objective's acceptance criteria and progress. It is named for the objective, so a file left by an earlier one is never mistaken for this one's.

type ObjectiveStatus

type ObjectiveStatus string

ObjectiveStatus is where a Compita stands on its objective.

const (
	ObjActive    ObjectiveStatus = "active"
	ObjDone      ObjectiveStatus = "done"
	ObjBlocked   ObjectiveStatus = "blocked"
	ObjPaused    ObjectiveStatus = "paused"
	ObjStopped   ObjectiveStatus = "stopped"
	ObjExhausted ObjectiveStatus = "exhausted" // a budget ran out
)

func Outcome

func Outcome(reply string) (status ObjectiveStatus, text string)

Outcome reads the marker a reply ends with. With no marker the objective simply goes on: a reply never ends the work by itself.

type Peer

type Peer struct {
	URL        string
	ComputeID  string
	Credential string
}

Peer tells a Compita turn how to reach the Compa host and its other Compitas.

type Result

type Result struct {
	JobID string `json:"job_id"`
	Reply string `json:"reply"`
	Error string `json:"error,omitempty"`
}

Result is a compute's answer to a Job.

func DialRun

func DialRun(ctx context.Context, c Compute, t Turn, onEvent func(StreamEvent)) (Result, error)

DialRun asks a dial-in compute to run a turn. With onEvent it also hears what the turn does as it happens.

type Runner

type Runner struct {
	// Home is this machine's Compa home; its config.json seeds each Compita.
	Home string
	// Kernel is the compa-kernel binary used outside containers.
	Kernel string
	// Image is the container image for container isolation.
	Image string
	// BrowserImage is the image for Compitas with a browser.
	BrowserImage string
	// Peer lets the Compita message its peers. Optional.
	Peer *Peer
}

Runner runs one Compita turn on this machine. Every Compita has its own COMPA_HOME (config, sessions, workspace) under Home/compitas/<id>.

func (Runner) CompitaHome

func (r Runner) CompitaHome(id string) string

CompitaHome is the directory a Compita owns on this machine.

func (Runner) Run

func (r Runner) Run(ctx context.Context, t Turn) (string, error)

Run sends one message to the Compita and returns its reply.

func (Runner) RunStream

func (r Runner) RunStream(ctx context.Context, t Turn, onEvent func(StreamEvent)) (string, error)

RunStream is Run that also reports what the turn does as it happens. A kernel that cannot stream still answers: the turn runs whole.

type Schedule

type Schedule struct {
	ID           string    `json:"id"`
	Goal         string    `json:"goal"`
	EveryMinutes int       `json:"every_minutes"`
	Enabled      bool      `json:"enabled"`
	LastRun      time.Time `json:"last_run,omitempty"`
	NextRun      time.Time `json:"next_run"`
}

Schedule starts the Compita on a goal every so often, with nobody chatting.

func AddSchedule

func AddSchedule(home, id, goal string, everyMinutes int, baseURL string, now time.Time) (Schedule, error)

AddSchedule makes the Compita pursue goal every everyMinutes minutes.

type State

type State struct {
	Enabled     bool         `json:"enabled"`
	Computes    []Compute    `json:"computes"`
	Compitas    []Compita    `json:"compitas"`
	Enrollments []Enrollment `json:"enrollments,omitempty"`
}

State is everything compute.json holds.

type Status

type Status string

Status is the enrollment state of a compute.

const (
	StatusPending  Status = "pending"
	StatusEnrolled Status = "enrolled"
)

type Store

type Store struct {
	Home string
	// Detect reports what this computer offers Compitas: a container runtime
	// and a browser. Tests replace it.
	Detect func() Capabilities
	// contains filtered or unexported fields
}

Store reads and writes compute.json under one Compa home. Every change runs under the file's lock, so the dashboard and a compute enrolling cannot lose each other's writes.

func NewStore

func NewStore(home string) *Store

NewStore returns a store for home that detects this computer's capabilities with Detect.

func (*Store) AddCompita

func (s *Store) AddCompita(name, description, computeID string, iso Isolation) (Compita, error)

AddCompita places a new Compita on a compute at an isolation level the compute can give.

func (*Store) AddRemote

func (s *Store) AddRemote(name string, mode Mode, rawURL string) (Compute, string, error)

AddRemote adds a remote compute in the pending state and returns its one-time enrollment token. The token is shown once; only its hash is kept. A dial-in compute needs the URL Compa will connect to.

func (*Store) Authenticate

func (s *Store) Authenticate(computeID, credential string) bool

Authenticate reports whether credential belongs to the enrolled compute.

func (*Store) AuthenticateDial

func (s *Store) AuthenticateDial(computeID, secret string) bool

AuthenticateDial reports whether secret is the dial secret of an enrolled dial-in compute.

func (*Store) CheckBrowser

func (s *Store) CheckBrowser(computeID string, i Isolation) error

CheckBrowser reports whether a Compita with isolation level i on the compute can have a browser, so a request that cannot be met is refused before anything is created.

func (*Store) Load

func (s *Store) Load() (State, error)

Load returns the current state; a missing file is an empty, disabled state.

func (*Store) Redeem

func (s *Store) Redeem(token string, caps Capabilities) (computeID, credential string, err error)

Redeem exchanges a valid enrollment token for the compute's credential. The token works once: it is gone when Redeem returns. The credential is returned in the clear exactly once; the store keeps its hash.

func (*Store) RefreshLocal

func (s *Store) RefreshLocal() error

RefreshLocal detects what this computer offers again and updates its compute.

func (*Store) ReissueToken

func (s *Store) ReissueToken(computeID string) (string, error)

ReissueToken replaces the enrollment token of a pending compute.

func (*Store) RemoveCompita

func (s *Store) RemoveCompita(id string) error

RemoveCompita deletes a Compita.

func (*Store) RemoveCompute

func (s *Store) RemoveCompute(id string) error

RemoveCompute deletes a compute that no Compita uses. This computer cannot be removed; turn Compitas support off instead.

func (*Store) RemoveConnection

func (s *Store) RemoveConnection(compitaID, name string) error

RemoveConnection deletes a connection of a Compita.

func (*Store) SetCapabilities

func (s *Store) SetCapabilities(computeID string, caps Capabilities) error

func (*Store) SetCompitaApprovals

func (s *Store) SetCompitaApprovals(id, preset string) error

SetCompitaApprovals sets how much a Compita asks the owner before acting.

func (*Store) SetCompitaBrowser

func (s *Store) SetCompitaBrowser(id string, on bool) error

SetCompitaBrowser gives a Compita a browser, or takes it away, if its compute can provide one (see Compute.AllowsBrowser).

func (*Store) SetConnection

func (s *Store) SetConnection(compitaID, name string, c Connection) error

SetConnection adds or replaces a connection of a Compita. A new one with the name of an existing connection keeps the secrets it does not restate: a variable left empty keeps its stored value, so the dashboard can edit a connection without ever being told its secrets.

func (*Store) SetEnabled

func (s *Store) SetEnabled(enabled bool) error

SetEnabled turns Compitas support on or off. Turning it on adds this computer as a compute, with the capabilities it has now.

func (*Store) SetPin

func (s *Store) SetPin(computeID, pin string) error

SetCapabilities records what a compute reported about itself. SetPin pins the certificate a dial-in compute must present.

func (*Store) ValidEnrollment

func (s *Store) ValidEnrollment(token string) bool

ValidEnrollment reports whether token is an enrollment token that has not been used or expired. It does not use the token up.

type StreamEvent

type StreamEvent struct {
	Type   string `json:"type"`
	Text   string `json:"text,omitempty"`
	Tool   string `json:"tool,omitempty"`
	State  string `json:"state,omitempty"`
	Detail string `json:"detail,omitempty"`
}

StreamEvent is something a Compita's turn does while it runs, as the kernel reports it with `agent --events`: the answer being written ("segment", "reset", "delta") or a tool being used ("tool").

type Triggers

type Triggers struct {
	Schedules []Schedule `json:"schedules"`
	// Token authenticates events (as a bearer token, or as the secret of a
	// GitHub-style HMAC signature). It is kept in the clear, like a webhook
	// secret has to be, in a file only the owner reads.
	Token string `json:"token,omitempty"`
	// Instruction says what to do with each event.
	Instruction string `json:"instruction,omitempty"`
	// Pending holds events that arrived while the Compita was busy.
	Pending []string `json:"pending,omitempty"`
	// BaseURL is how the Compita reaches Compa for objectives these start.
	BaseURL string `json:"base_url,omitempty"`
}

Triggers is how work reaches a Compita besides the user chatting with it: schedules, and events posted to its trigger endpoint.

func LoadTriggers

func LoadTriggers(home, id string) (Triggers, error)

LoadTriggers returns the Compita's triggers; empty when it has none.

type Turn

type Turn struct {
	CompitaID string
	Isolation Isolation
	Session   string
	Message   string
	// Depth counts hops of Compita-to-Compita messages, to stop loops.
	Depth int
	// Peer* let a dial-in compute's Compitas reach back to the Compa host.
	PeerURL, PeerCompute, PeerToken string
	// Approvals is the Compita's approval preset (see ApprovalsCareful).
	Approvals string
	// Browser runs the turn in the browser image, with a browser to drive.
	Browser bool
	// Connections are the Compita's own MCP servers.
	Connections map[string]Connection
	// Events asks the kernel to report the turn as it runs (`agent --events`).
	// RunStream sets it; callers of Run leave it off.
	Events bool
}

Turn is one message to a Compita.

Jump to

Keyboard shortcuts

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