ui

package
v0.11.0 Latest Latest
Warning

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

Go to latest
Published: Jul 19, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package ui is Fort's interface module (backlog Phase 3): the event/command contract (AO-031), the live board (AO-032), the SSE live-feed transport (AO-033), the chat surface (AO-034), the gate inbox (AO-035), and the OpenClaw inbound channel (AO-036). It imports core; core never imports ui.

Contract summary (published for clients, incl. the iOS shell, AO-037):

GET  /api/board                 -> Board (runs + waiting gates + checkpoints)
GET  /api/summary               -> Summary (counts + pending gates)
GET  /api/runs/{id}             -> RunDetail (run + nodes + events; replayable)
GET  /api/gates                 -> []GateItem
POST /api/gate                  <- GateDecision  -> ActionResult (reject may carry a note)
POST /api/chat                  <- ChatRequest   -> ChatResult
GET  /api/backlog               -> []BacklogItem
POST /api/backlog               <- BacklogRequest -> BacklogItem
PATCH /api/backlog/{id}         <- BacklogPatch  -> BacklogItem (reassign, spec 033)
POST /api/backlog/{id}/dispatch -> ChatResult
DELETE /api/backlog/{id}
POST /api/breakdown             <- BreakdownRequest -> BreakdownResult
GET  /api/metrics[?days=N&lane=L] -> MetricsResponse (spec 033)
POST /api/openclaw              <- OpenClawMessage-> ChatResult
GET  /api/events[?since=N]      -> text/event-stream of Event frames

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ActionResult

type ActionResult struct {
	State      string `json:"state"`
	PausedNode string `json:"paused_node,omitempty"`
}

ActionResult is a generic command result (gate decisions).

type AgentMetrics added in v0.11.0

type AgentMetrics struct {
	Agent         string    `json:"agent"`
	Assignments   int       `json:"assignments"`              // routed runs + flow task-node executions
	Decided       int       `json:"decided"`                  // sign-offs that reached a decision
	FirstPass     int       `json:"first_pass"`               // approved first try, no note
	FirstPassPct  float64   `json:"first_pass_pct"`           // 0 when Decided==0
	Accepted      int       `json:"accepted"`                 // finally-approved sign-offs
	Redirects     int       `json:"redirects"`                // rejects + approves-with-edits
	RedirectsPer  float64   `json:"redirects_per_assignment"` // 0 when Assignments==0
	CostUSD       float64   `json:"cost_usd"`                 // parsed engine cost; 0 = unknown
	CostPerAccept float64   `json:"cost_per_accepted"`        // 0 = unknown
	CostKnown     bool      `json:"cost_known"`
	Trend         string    `json:"trend"`       // improving | steady | slipping
	TrendDelta    float64   `json:"trend_delta"` // pct-point change between window halves
	Spark         []float64 `json:"spark"`       // 7 first-pass-% buckets, carried forward
	Best          []string  `json:"best"`        // strongest routing lanes (≥3 terminal runs)
	Weak          []string  `json:"weak"`
}

AgentMetrics is one agent's scorecard over the metrics window (spec 033). Everything is derived from the append-only event log + run rows — sign-off counts are human decisions, never agent estimates. Sample sizes (Assignments, Decided) ship alongside every ratio because 30-day windows are small.

type BacklogItem added in v0.7.0

type BacklogItem struct {
	ID      string   `json:"id"`
	Title   string   `json:"title"`
	Body    string   `json:"body,omitempty"`
	Agent   string   `json:"agent,omitempty"`
	Machine string   `json:"machine,omitempty"`
	Labels  []string `json:"labels,omitempty"`
	Source  string   `json:"source"` // "user" | "agent"
}

BacklogItem is a pending task queued on the board (spec 025).

type BacklogPatch added in v0.11.0

type BacklogPatch struct {
	Agent string `json:"agent"`
}

BacklogPatch is the command body for PATCH /api/backlog/{id} (spec 033): reassign an Up-next item to another agent ("" clears the pin).

type BacklogRequest added in v0.7.0

type BacklogRequest struct {
	Title   string   `json:"title"`
	Body    string   `json:"body,omitempty"`
	Agent   string   `json:"agent,omitempty"`
	Machine string   `json:"machine,omitempty"`
	Labels  []string `json:"labels,omitempty"`
	Source  string   `json:"source,omitempty"` // defaults to "user"
}

BacklogRequest is the command body for POST /api/backlog.

type Board

type Board struct {
	Runs  []RunSummary `json:"runs"`
	Gates []GateItem   `json:"gates"`
}

Board is the live board payload.

type BreakdownRequest added in v0.8.0

type BreakdownRequest struct {
	Text    string `json:"text"`
	Agent   string `json:"agent,omitempty"`
	Machine string `json:"machine,omitempty"`
}

BreakdownRequest is the command body for POST /api/breakdown.

type BreakdownResult added in v0.8.0

type BreakdownResult struct {
	RunID string `json:"run_id"`
}

BreakdownResult is the response for POST /api/breakdown: the visible planner run's id. Sub-tasks appear in the backlog when that run completes.

type ChatRequest

type ChatRequest struct {
	Text    string `json:"text"`
	Agent   string `json:"agent,omitempty"`   // force a specific agent
	Machine string `json:"machine,omitempty"` // pin a target host (spec 022)
}

ChatRequest is the command body for POST /api/chat.

type ChatResult

type ChatResult struct {
	Kind    string `json:"kind"` // task | flow
	RunID   string `json:"run_id"`
	Route   string `json:"route,omitempty"`   // agent, for task kind (execution plane)
	Machine string `json:"machine,omitempty"` // resolved host (spec 022)
	Queued  bool   `json:"queued,omitempty"`  // true when only boarded (control-only)
	FlowID  string `json:"flow_id,omitempty"` // for flow kind
	Paused  string `json:"paused,omitempty"`  // gate id if the flow paused
}

ChatResult is the response for chat/openclaw.

type CheckpointSummary added in v0.11.0

type CheckpointSummary struct {
	Total    int `json:"total"`    // gate nodes in the plan (executed-only when no plan is known)
	Accepted int `json:"accepted"` // approved gates
	Waiting  int `json:"waiting"`  // gates awaiting sign-off
	Rejected int `json:"rejected"` // rejected gates
	Done     int `json:"done"`     // non-gate nodes finished (for in-progress inference)
}

CheckpointSummary is a run's human-checkpoint progress: checkpoints are the flow's gate nodes — progress is what the human accepted, never an agent estimate (spec 033).

type Deps

type Deps struct {
	Dispatcher Dispatcher    // required
	Runner     FlowRunner    // nil in control-only mode
	Store      *store.Store  // required
	FlowIDs    []string      // available flow ids (for chat templates); empty in control-only
	Machines   MachineLister // nil in single-machine mode (spec 022)
	Planner    Planner       // nil in control-only mode (spec 026)
}

Deps are the control-plane collaborators — ports only. With no Runner and a queue Dispatcher this serves a full control plane (board, chat, scheduler, gate inbox) that needs none of the deterministic execution components.

type Dispatcher

type Dispatcher interface {
	Submit(ctx context.Context, t task.Task) (RunRef, error)
}

Dispatcher accepts a task. With an execution plane it routes + dispatches; in control-only mode it simply boards the task (Queued=true).

type Event

type Event struct {
	ID     int64  `json:"id"`
	RunID  string `json:"run_id"`
	NodeID string `json:"node_id,omitempty"`
	Type   string `json:"type"`
	Data   string `json:"data,omitempty"`
	Code   int    `json:"code,omitempty"`
	Time   string `json:"time"`
}

Event is the wire form of one append-only event-log row (the live-feed unit).

type FlowNode added in v0.11.0

type FlowNode struct {
	ID   string `json:"id"`
	Type string `json:"type"` // task | gate | check | transform | fanout
}

FlowNode is one node of a flow plan as exposed to the control plane (spec 033): just enough to know a run's checkpoint total.

type FlowRunner

type FlowRunner interface {
	StartFlow(ctx context.Context, flowID, runID, payload string) (RunResult, error)
	Approve(runID, nodeID, edit string) error
	Reject(runID, nodeID, note string) error
	ResumeFlow(ctx context.Context, flowID, runID string) (RunResult, error)
	// Plan returns the flow's node list (nil for an unknown id).
	Plan(flowID string) []FlowNode
}

FlowRunner runs flows by id. It is nil in control-only mode (no DAG engine); chat "ship X" then degrades to a boarded task and gate actions return 409.

type GateDecision

type GateDecision struct {
	RunID    string `json:"run_id"`
	NodeID   string `json:"node_id"`
	Decision string `json:"decision"` // approve | reject
	Edit     string `json:"edit,omitempty"`
	Note     string `json:"note,omitempty"` // redirect note on reject (spec 033)
}

GateDecision is the command body for POST /api/gate.

type GateItem

type GateItem struct {
	RunID  string `json:"run_id"`
	NodeID string `json:"node_id"`
	Input  string `json:"input,omitempty"`
	Since  string `json:"since,omitempty"` // RFC3339 — when the gate began waiting (spec 033)
}

GateItem is a gate awaiting a human decision (the gate inbox).

type MachineLister

type MachineLister interface {
	Machines() []MachineStatus
}

MachineLister reports the machine roster + reachability for the control plane (GET /api/machines, spec 022). It is nil in single-machine mode, in which case the endpoint returns an empty roster. Implemented by package control.

type MachineStatus

type MachineStatus struct {
	Name      string   `json:"name"`
	URL       string   `json:"url,omitempty"`
	Agents    []string `json:"agents"`
	Local     bool     `json:"local"`
	Reachable bool     `json:"reachable"`
}

MachineStatus is one host in the roster (GET /api/machines, spec 022).

type MetricsResponse added in v0.11.0

type MetricsResponse struct {
	WindowDays  int            `json:"window_days"`
	Assignments int            `json:"assignments"`
	Agents      []AgentMetrics `json:"agents"`
	Lanes       []string       `json:"lanes"` // distinct matched_rule values seen in the window
}

MetricsResponse is the payload of GET /api/metrics (spec 033).

type NodeSummary

type NodeSummary struct {
	NodeID   string `json:"node_id"`
	Type     string `json:"type"`
	Status   string `json:"status"`
	Attempts int    `json:"attempts,omitempty"`
}

NodeSummary is a node's state within a run.

type OpenClawMessage

type OpenClawMessage struct {
	From string `json:"from"`
	Text string `json:"text"`
}

OpenClawMessage is an inbound OpenClaw message (AO-036).

type Planner added in v0.8.0

type Planner interface {
	Breakdown(ctx context.Context, goal, agent, machine string) (runID string, err error)
}

Planner decomposes a goal into backlog sub-tasks by running a planner agent (spec 026). It is nil in control-only mode (planning needs an execution plane); the /api/breakdown endpoint 409s when it is nil. Breakdown returns the planner run's id immediately; the sub-tasks land in the backlog asynchronously when that run completes.

type RunDetail

type RunDetail struct {
	Run    RunSummary    `json:"run"`
	Nodes  []NodeSummary `json:"nodes"`
	Events []Event       `json:"events"`
}

RunDetail makes a run replayable from the event log.

type RunRef

type RunRef struct {
	RunID   string `json:"run_id"`
	Route   string `json:"route,omitempty"`   // agent, when an execution plane routed it
	Machine string `json:"machine,omitempty"` // host it was placed on (spec 022)
	Queued  bool   `json:"queued,omitempty"`  // true when only boarded (no execution plane)
}

RunRef identifies the run a submitted task produced.

type RunResult

type RunResult struct {
	State      string `json:"state"`
	PausedNode string `json:"paused_node,omitempty"`
}

RunResult is a flow run's state after a Start/Resume.

type RunSummary

type RunSummary struct {
	ID          string             `json:"id"`
	Title       string             `json:"title"`
	Body        string             `json:"body,omitempty"`
	Agent       string             `json:"agent"`
	Status      string             `json:"status"`
	Machine     string             `json:"machine,omitempty"` // host the run is placed on (spec 022)
	FlowID      string             `json:"flow_id,omitempty"`
	CreatedAt   string             `json:"created_at,omitempty"` // RFC3339 (spec 033)
	UpdatedAt   string             `json:"updated_at,omitempty"` // RFC3339 (spec 033)
	Checkpoints *CheckpointSummary `json:"checkpoints,omitempty"`
}

RunSummary is a board card.

type Server

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

Server holds the ui handlers.

func New

func New(d Deps) *Server

New builds a ui server.

func (*Server) HasExecution

func (s *Server) HasExecution() bool

HasExecution reports whether an execution plane is wired (for diagnostics).

func (*Server) Register

func (s *Server) Register(mux *http.ServeMux)

Register mounts the ui routes onto mux.

func (*Server) Run

func (s *Server) Run(ctx context.Context, addr string) error

Run is a convenience for standalone serving (used in tests / embedding).

type Summary

type Summary struct {
	Total     int        `json:"total"`
	Running   int        `json:"running"`
	Queued    int        `json:"queued"`
	Blocked   int        `json:"blocked"` // paused at a gate
	Succeeded int        `json:"succeeded"`
	Failed    int        `json:"failed"`
	Execution bool       `json:"execution"` // whether an execution plane is attached
	Gates     []GateItem `json:"gates"`
}

Summary is the glanceable control-plane snapshot for constrained surfaces (watch complication, CarPlay). Served at GET /api/summary.

Jump to

Keyboard shortcuts

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