agents

package
v0.36.2 Latest Latest
Warning

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

Go to latest
Published: Aug 4, 2026 License: MIT Imports: 92 Imported by: 0

Documentation

Overview

Package agents backs /tools/agents — the Agents UI Manager. It lets users manage AI agent sessions, workspaces, and presets from the browser and streams real-time agent output via Server-Sent Events.

Index

Constants

This section is empty.

Variables

View Source
var SPAFS fs.FS = func() fs.FS { return spaLoader.FS() }()

SPAFS is kept for backward compatibility with spa_handler.go (reads the FS directly to serve assets + the shell). Points at the same FS as spaLoader.

Functions

func AirouterAutostart added in v0.31.0

func AirouterAutostart(logf func(string))

AirouterAutostart starts every auto-start-enabled router at boot. Called from server.go after the tool router mounts (so the config store is wired).

func AirouterEnabled added in v0.31.0

func AirouterEnabled() bool

AirouterEnabled reports the master switch. Absent row = ON (default true, matching DefaultGeneralConfig) so an existing setup keeps working until an admin disables it. Falls back to the legacy router9enabled key.

func AirouterExternalAllowed added in v0.31.0

func AirouterExternalAllowed(id string) bool

AirouterExternalAllowed reports whether router id's /v1 API may be reached off-machine — the host-allowlist exemption in server.go consults this for a non-loopback caller on the /airouter/<id>/v1 subtree.

func AirouterVisible added in v0.31.0

func AirouterVisible(ctx context.Context) bool

AirouterVisible reports whether the AI Router nav entry should show: master on AND the caller has access.

func AnyAirouterAutostart added in v0.31.0

func AnyAirouterAutostart() bool

AnyAirouterAutostart reports whether at least one router has auto-start on.

func AutoInstallMCP added in v0.13.4

func AutoInstallMCP()

AutoInstallMCP installs wick into every detected MCP client that doesn't have it yet, skipping blocklisted (manually-uninstalled) clients. Called once at server startup; the mcp_auto_installed flag prevents re-runs so page renders never trigger spurious re-installs.

func Register

func Register(r tool.Router)

Register mounts all Agents routes under /tools/agents.

func RegisterAirouter added in v0.31.0

func RegisterAirouter(r tool.Router)

RegisterAirouter wires the AI Router control endpoints + SPA page onto the agents tool router. Called from handler.go's Register.

func SetApprovals

func SetApprovals(m *gate.ApprovalManager)

SetApprovals wires in the gate ApprovalManager. nil = gate disabled (handler endpoints fall back to 503).

func SetAskUsers

func SetAskUsers(m *askuser.Manager)

SetAskUsers wires in the ask_user Manager. nil = ask_user MCP tool returns errors and the answer endpoint 503s.

func SetAuth added in v0.14.21

func SetAuth(a *login.Service)

SetAuth wires the login service so per-user preferences (pinned project) can be read/written from the agents tool.

func SetBroadcaster

func SetBroadcaster(b *Broadcaster)

SetBroadcaster wires in the SSE event broadcaster.

func SetChannelRegistry added in v0.10.0

func SetChannelRegistry(r *agentchannels.Registry)

SetChannelRegistry wires the live channel registry so picker fields can issue lookup queries against each channel's upstream (Slack API, etc.). Without this, /channels/{slug}/lookup returns 503.

func SetConfigs

func SetConfigs(c *configs.Service)

SetConfigs wires the shared configs service so the Providers page can toggle agents.gate_enabled inline. Without this, the toggle endpoint 503s.

It also hands the wick provider a secret decryptor so its in-process engine can decrypt per-model API keys (wick_cenc_ tokens) at spawn time without the wick package importing configs (avoids a cycle).

func SetConnectors added in v0.17.0

func SetConnectors(c *connectors.Service)

SetConnectors wires the connectors service so the session Config tab can read a connector's field schema (to render the form) and resolve which connectors opted into per-session overrides.

func SetDB

func SetDB(db *gorm.DB)

SetDB wires the shared GORM DB so channel handlers can read/write agent_channels rows. Without this, channel config endpoints 503.

Workflow data is DB-primary. Folders left on disk from before the DB migration are not imported automatically — use the SPA or MCP to recreate them, then remove the old folders.

func SetDataTables added in v0.13.1

func SetDataTables(s datatable.Service)

SetDataTables registers the shared data-table service. nil is allowed during early boot; handlers fall back to 503.

func SetDelegation added in v0.36.0

func SetDelegation(s *delegation.Service)

SetDelegation wires the delegation service for the HTTP layer.

func SetGateStatus

func SetGateStatus(s GateStatus)

SetGateStatus records the boot-time gate-resolution result. Read by the Providers page. Call exactly once during server boot.

func SetLayout

func SetLayout(l agentconfig.Layout)

SetLayout wires in the on-disk layout used for direct file reads.

It also enables persistence for per-session provider overrides (the composer's /thinking popover): the store needs a session-ID → dir resolver to find its overrides.json sidecar, and this is the one place the layout is known. Without it the store stays memory-only and a toggle dies with the engine goroutine.

func SetManager

func SetManager(m *registry.Manager)

SetManager wires in the agents registry manager.

func SetPool

func SetPool(p *pool.Pool)

SetPool wires in the agent subprocess pool.

func SetSkillStore added in v0.17.0

func SetSkillStore(s *skills.Store)

SetSkillStore wires the skills ownership store so delete/upload/sync handlers can enforce owner-or-admin access control.

func SetSpawnLogger

func SetSpawnLogger(s *provider.SpawnLogger)

SetSpawnLogger wires in the per-spawn jsonl writer/reader. The Providers page reads from it via List + Read; the pool factory already writes through it.

func SetSyncManager added in v0.11.0

func SetSyncManager(m *providersync.Manager)

SetSyncManager wires the provider storage sync manager.

func SetTagsService added in v0.17.0

func SetTagsService(svc *tags.Service)

SetTagsService wires the tags service for skill ownership checks.

func SetWorkflowEncService added in v0.16.0

func SetWorkflowEncService(s *enc.Service)

SetWorkflowEncService wires the cipher used by the env save handler.

func SetWorkflowManager added in v0.13.0

func SetWorkflowManager(m *setup.Manager)

SetWorkflowManager wires in the workflow Manager constructed by server.go. After the JSON migration, workflow body is DB-primary — no file→DB importer runs here.

func WorkflowEventHook added in v0.13.0

func WorkflowEventHook(b *Broadcaster) func(id, runID string, ev wf.RunEvent)

WorkflowEventHook builds an engine.OnEvent callback that fans workflow run events out to the SSE broadcaster.

func WorkflowSSESession added in v0.13.0

func WorkflowSSESession(id string) string

WorkflowSSESession returns the broadcaster session key used for workflow run events.

Types

type AIRouterChoiceDTO added in v0.31.0

type AIRouterChoiceDTO struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

AIRouterChoiceDTO is one selectable router backend.

type AIRouterDetailDTO added in v0.31.0

type AIRouterDetailDTO struct {
	Supported bool                `json:"supported"`
	Enabled   bool                `json:"enabled"`
	Provider  string              `json:"provider"`
	Routers   []AIRouterChoiceDTO `json:"routers"`
	Models    map[string]string   `json:"models"`
	KeySet    bool                `json:"key_set"`
	RawConfig string              `json:"raw_config"`
	// Preview is the effective config wick injects at spawn for the current
	// saved settings — env vars (claude) or -c overrides (codex), one per line,
	// secret values masked. Shown read-only in the Advanced section so the user
	// can see exactly what gets set (and which keys to override via RawConfig).
	Preview string `json:"preview"`
}

AIRouterDetailDTO carries the instance's current AI-router settings so the detail page can seed its widget. The API key is never returned — only a flag indicating one is stored. Routers lists the available backends to pick from.

type AgentProfileItem added in v0.36.0

type AgentProfileItem struct {
	ID string `json:"id"`
	// ProjectID is the scope. Empty = global; non-empty = owned by that
	// project and invisible elsewhere.
	ProjectID          string   `json:"project_id"`
	Key                string   `json:"key"`
	Name               string   `json:"name"`
	Description        string   `json:"description"`
	Icon               string   `json:"icon"`
	Provider           string   `json:"provider"`
	Model              string   `json:"model"`
	SystemPrompt       string   `json:"system_prompt"`
	AllowedTagIDs      []string `json:"allowed_tag_ids"`
	AllowedNativeTools []string `json:"allowed_native_tools"`
	StrictMCP          bool     `json:"strict_mcp"`
	DefaultMaxTurns    int      `json:"default_max_turns"`
	CanDelegate        bool     `json:"can_delegate"`
	AllowTakeOver      bool     `json:"allow_take_over"`
	Disabled           bool     `json:"disabled"`
	// Locked freezes the role: no edit, no delete, from any surface. Only
	// this UI can clear it — MCP may set it, never unset it.
	Locked bool `json:"locked"`
}

AgentProfileItem is one sub-agent role as the admin UI sees it.

type BoardItem added in v0.36.0

type BoardItem struct {
	ID           string                   `json:"id"`
	Key          string                   `json:"key"`
	Name         string                   `json:"name"`
	Description  string                   `json:"description"`
	Columns      []delegation.BoardColumn `json:"columns"`
	SquadKey     string                   `json:"squad_key,omitempty"`
	GateMode     string                   `json:"gate_mode"`
	AutoDelegate bool                     `json:"auto_delegate"`
	Disabled     bool                     `json:"disabled"`
}

BoardItem is one board as the UI sees it.

type Broadcaster

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

Broadcaster fans out agent events to all subscribed SSE connections. Subscribe returns a receive channel and an unsub func. Publish is called from ClaudeFactory.OnEvent on every AgentEvent.

subs is keyed by sessionID ("" = global subscribers that receive all events). Channels are buffered at 64 so a slow client never stalls the agent reader goroutine.

func NewBroadcaster

func NewBroadcaster() *Broadcaster

NewBroadcaster returns a ready Broadcaster.

func (*Broadcaster) Publish

func (b *Broadcaster) Publish(sessionID, agentName string, ev event.AgentEvent)

Publish fires ev to all subscribers of sessionID and all global ("") subscribers. Non-blocking: a full channel's event is dropped rather than blocking.

func (*Broadcaster) PublishApprovalRequest

func (b *Broadcaster) PublishApprovalRequest(sessionID string, req gate.ApprovalRequest)

PublishApprovalRequest fires when the gate binary dials the daemon socket with an unrecognised command. Browsers render this as a modal with 4 decision buttons (approve_once / approve_session / approve_always / block); the user's pick rides back through POST /approve.

Data is the JSON-encoded ApprovalRequest so the front-end can decode it once and use every field (cmd, work_dir, match_key, ...).

func (*Broadcaster) PublishApprovalResolved

func (b *Broadcaster) PublishApprovalResolved(sessionID, requestID, decision string)

PublishApprovalResolved fires once a decision is delivered (UI click, timeout, or listener close). Browsers use this to dismiss any open modal across all tabs subscribed to the session.

func (*Broadcaster) PublishAskUser

func (b *Broadcaster) PublishAskUser(sessionID, agentName string, payload []byte)

PublishAskUser fires when the ask_user MCP tool is invoked by an agent. Front-end renders an inline card with options + freeform input; user's pick rides back through POST /answer. Data is the JSON-encoded request body so every field (question, options, allow_freeform, ...) round-trips exactly once.

func (*Broadcaster) PublishAskUserResolved

func (b *Broadcaster) PublishAskUserResolved(sessionID, requestID string)

PublishAskUserResolved fires once an ask_user request resolves (UI answer or timeout). Used by the UI to dismiss the inline card across all tabs subscribed to the session.

func (*Broadcaster) PublishConnectorRun added in v0.35.0

func (b *Broadcaster) PublishConnectorRun(sessionID, runID, connectorID, opKey, status string, running bool)

PublishConnectorRun broadcasts the start/finish of a connector run to a session's subscribers so the conversation UI can show a per-run Cancel button on an in-flight tool call. running=true is the start (status "running"), carrying the run_id + connector_id the FE needs to hit the cancel route; running=false is the terminal update carrying the final status so the FE drops the button. Wired from connectors.Service via SetRunObserver.

func (*Broadcaster) PublishGitStatusJSON added in v0.15.5

func (b *Broadcaster) PublishGitStatusJSON(sessionID, jsonPayload string)

PublishGitStatusJSON broadcasts a pre-marshalled git_status payload to a session's subscribers. The payload is the full repo+status snapshot (built by the fs watcher) so the FE updates entirely from the event — no follow-up fetch, hence no polling. The marshalling lives in the caller (scm_watch.go) to avoid an import cycle on the scm types.

func (*Broadcaster) PublishLifecycle

func (b *Broadcaster) PublishLifecycle(ctx context.Context, sessionID, agentName, lifecycle, provider string, pid int)

PublishLifecycle pushes a lifecycle transition (Spawning, Killed) to subscribers. Idle/Working transitions are inferred from AgentEvent flow on the client side; only the bookend transitions — which never carry an AgentEvent — go through this channel. PublishLifecycle takes the spawn-time ctx so the broadcast log line carries the originating request_id (set by the HTTP middleware) when the spawn came from an HTTP path. Pass context.Background() when no spawn ctx is in scope.

func (*Broadcaster) PublishPoolStats added in v0.15.2

func (b *Broadcaster) PublishPoolStats(active, max, queueLen int, procs []LiveProcessEntry)

PublishPoolStats broadcasts a pool_stats event to all global SSE subscribers (sessionID == ""). Called after every lifecycle transition so the Providers page stays live.

func (*Broadcaster) PublishRaw added in v0.13.4

func (b *Broadcaster) PublishRaw(sessionID, agentName, evType, data string)

func (*Broadcaster) PublishSessionMeta added in v0.17.0

func (b *Broadcaster) PublishSessionMeta(sessionID, title string, titleCustom bool, status string)

PublishSessionMeta broadcasts a session's current title + status so open tabs update the header/sidebar live — no page reload. Fired after session meta changes (wick_set_title, status transitions), including changes that originated in a sibling stdio process and were relayed in via the agentctl refresh_session op.

func (*Broadcaster) PublishSystemTurn added in v0.13.4

func (b *Broadcaster) PublishSystemTurn(sessionID, agentName, text string, steps []string)

PublishSystemTurn fires a system_turn event so the UI can append it to the conversation without a page reload. Data is JSON with text + steps so the front-end can render the pill + checklist inline.

func (*Broadcaster) PublishUserMessage added in v0.29.0

func (b *Broadcaster) PublishUserMessage(sessionID, agentName, source, text string)

PublishUserMessage fires a user_message event so connected web viewers render a user turn injected from a NON-web source (a channel or the schedule runner) live, instead of only after a manual refresh. Without this the SSE stream carries only the assistant reply, so the incoming user turn silently goes missing until a refetch. Data is JSON with the text + source so the UI can badge where the message came from.

func (*Broadcaster) Subscribe

func (b *Broadcaster) Subscribe(sessionID string) (<-chan Event, func())

Subscribe registers a listener for a specific session (or "" for all). The caller must call the returned unsub func when the SSE connection closes.

type ComposerCommand added in v0.30.0

type ComposerCommand struct {
	ID       string `json:"id"`
	Label    string `json:"label"`
	Hint     string `json:"hint,omitempty"`
	Category string `json:"category,omitempty"`
	// Action is an id the FE resolves to a handler (e.g. "switch:provider",
	// "panel:process", "view:commands"). Empty for insert-type entries.
	Action string `json:"action,omitempty"`
	// Insert is the text placed after `/` for insert-type entries (skills).
	Insert string `json:"insert,omitempty"`
}

ComposerCommand is one entry in the composer's `/` menu. It is intentionally data-only: the FE maps Action ids to local handlers (opening a panel, switching provider, changing the view) — those live in the FE because they are UI actions. Skills carry no Action; the FE inserts `/`+Insert instead.

To add a new `/` command that reuses an existing FE action, add an entry here with a known Action id — no FE change needed. A genuinely new behaviour needs one new handler in the FE action map.

type ComposerCommandsResponse added in v0.30.0

type ComposerCommandsResponse struct {
	Commands []ComposerCommand `json:"commands"`
}

ComposerCommandsResponse is the envelope for GET /api/composer/commands.

type ConfigFieldDTO added in v0.19.0

type ConfigFieldDTO struct {
	Key         string `json:"key"`
	Value       string `json:"value"`
	Type        string `json:"type"`
	Options     string `json:"options,omitempty"`
	IsSecret    bool   `json:"is_secret"`
	Description string `json:"description,omitempty"`
	Required    bool   `json:"required"`
}

ConfigFieldDTO is one config row for the detail page (secret values masked).

type DefaultModelDTO added in v0.35.0

type DefaultModelDTO struct {
	ID   string `json:"id"`
	Desc string `json:"desc,omitempty"`
}

DefaultModelDTO is one catalog seed model surfaced to the detail page's "Load defaults" button — id plus its description.

type DelegationStream added in v0.36.0

type DelegationStream struct {
	Bcast *Broadcaster
}

DelegationStream adapts the SSE Broadcaster to the delegation package's EventStream interface, so a waiting delegation.Run observes exactly the same normalized event flow the UI does — one source of truth for "what did this agent do", rather than a second tap into the provider stream that could drift from it.

func NewDelegationStream added in v0.36.0

func NewDelegationStream(b *Broadcaster) *DelegationStream

NewDelegationStream wraps a live broadcaster.

func (*DelegationStream) SubscribeSession added in v0.36.0

func (d *DelegationStream) SubscribeSession(sessionID string) (<-chan delegation.StreamEvent, func())

SubscribeSession bridges one session's event channel, translating the SSE wire shape back into the typed events the turn counter reads.

type Event

type Event struct {
	SessionID string `json:"session_id"`
	AgentName string `json:"agent_name"`
	Type      string `json:"type"`
	Data      string `json:"data"`
	// ToolName, ToolInput, ToolUseID are populated for tool_use events;
	// ToolUseID and IsError are also set for tool_result events.
	ToolName  string `json:"tool_name,omitempty"`
	ToolInput string `json:"tool_input,omitempty"`
	ToolUseID string `json:"tool_use_id,omitempty"`
	IsError   bool   `json:"is_error,omitempty"`
	PID       int    `json:"pid,omitempty"`
	Lifecycle string `json:"lifecycle,omitempty"`
	// SubAgent carries a DELEGATED lifecycle attributed to the session in
	// SessionID — set when a sub-agent of that conversation transitioned,
	// not the conversation's own process. Kept separate from Lifecycle so
	// a child's work can never be mistaken for the leader's, and so a
	// subscriber can render both at once. Sidebar-stream only.
	SubAgent string `json:"sub_agent,omitempty"`
	// At / EndAt carry Unix ms timestamps for tool_use/tool_result events
	// so the UI can show "started HH:MM:SS, took Ns".
	At    int64 `json:"at,omitempty"`
	EndAt int64 `json:"end_at,omitempty"`
}

Event is one SSE payload pushed to browser subscribers. Type distinguishes agent stream events ("text_delta", "tool_use", ...) from lifecycle events ("lifecycle"); the latter carry PID + lifecycle label in Data so the UI can update the status badge without re-fetching the page.

func (Event) JSON

func (e Event) JSON() string

type GateStatus

type GateStatus struct {
	Enabled bool
	Binary  string // absolute path
	Source  string // gate.Source* constant
	Reason  string // populated when Enabled=false
}

GateStatus is the boot-time snapshot of the command gate. Populated once during server.go startup and read by the Providers page so operators can tell at a glance whether the gate sidecar is wired up.

Enabled=false means ResolveGateBinary returned an error — every command will hit fail-safe block at the matcher / no-socket path, except whitelist matches. Reason carries the error message so the UI can show actionable guidance (run `wick build`).

func GetGateStatus

func GetGateStatus() GateStatus

GetGateStatus is the read side. Returns a zero value when boot hasn't reached SetGateStatus yet.

type GateStatusDTO added in v0.19.0

type GateStatusDTO struct {
	Enabled        bool   `json:"enabled"`
	Binary         string `json:"binary"`
	Source         string `json:"source"`
	Reason         string `json:"reason,omitempty"`
	Note           string `json:"note"`
	PermissionMode string `json:"permission_mode"`
	BypassLocked   bool   `json:"bypass_locked"`
}

GateStatusDTO is the gate policy state.

type GitStatusSnapshot added in v0.15.5

type GitStatusSnapshot struct {
	Repos        []RepoSummary               `json:"repos"`
	Statuses     map[string]scm.StatusResult `json:"statuses"`
	TotalChanged int                         `json:"total_changed"`
}

GitStatusSnapshot is the full session-wide git state pushed over SSE (git_status event) AND returned by GET /git/repos. The FE renders entirely from this — repos for the switcher, statuses[rel] for the changes list of each repo — so a change event needs no follow-up fetch (zero polling).

type HookCapabilityDTO added in v0.19.0

type HookCapabilityDTO struct {
	Supported bool   `json:"supported"`
	Verified  bool   `json:"verified"`
	ProbedAt  string `json:"probed_at,omitempty"`
	Error     string `json:"error,omitempty"`
	Scope     string `json:"scope,omitempty"`
}

HookCapabilityDTO is the per-event hook capability state for one provider.

type IncidentSummary added in v0.36.1

type IncidentSummary struct {
	Status        string `json:"status"`
	Iteration     int    `json:"iteration"`
	Summary       string `json:"summary"`
	StopReason    string `json:"stop_reason,omitempty"`
	EvidenceCount int    `json:"evidence_count"`
}

IncidentSummary is the compact incident header the rail shows above the agent list. Deliberately not the whole record: the panel answers "is this an investigation, and how is it going", and the full state belongs to whoever opens it.

type LiveProcessDTO added in v0.19.0

type LiveProcessDTO struct {
	SessionID string `json:"session_id"`
	AgentName string `json:"agent_name"`
	PID       int    `json:"pid"`
	Lifecycle string `json:"lifecycle"`
	Substate  string `json:"substate"`
}

LiveProcessDTO is one active spawn entry.

type LiveProcessEntry added in v0.15.2

type LiveProcessEntry struct {
	SessionID string `json:"session_id"`
	AgentName string `json:"agent_name"`
	Provider  string `json:"provider,omitempty"` // "type/name"
	PID       int    `json:"pid,omitempty"`
	Queued    int    `json:"queued,omitempty"` // messages waiting after current turn
	Alive     bool   `json:"alive"`            // false only for a genuinely dead process (zombie). Respawn-mode idle-between-turns is alive.
	Lifecycle string `json:"lifecycle"`
	Substate  string `json:"substate,omitempty"`
}

LiveProcessEntry is one row in PoolStatsPayload.

type LogRefDTO added in v0.32.0

type LogRefDTO struct {
	Prefix string `json:"prefix"`
	Path   string `json:"path"`
}

LogRefDTO is one process log file relevant to a spawn: its component name (server/daemon/…) and absolute path.

type LogTailResponse added in v0.32.0

type LogTailResponse struct {
	Name      string `json:"name"`
	Path      string `json:"path"`
	Size      int64  `json:"size"`
	Content   string `json:"content"`
	Truncated bool   `json:"truncated"` // older bytes dropped to fit the byte cap
	Modified  string `json:"modified"`
}

LogTailResponse is the JSON envelope for GET /api/providers/logs/{file}.

type MCPClientDTO added in v0.19.0

type MCPClientDTO struct {
	ID          string `json:"id"`
	Label       string `json:"label"`
	Detected    bool   `json:"detected"`
	Installed   bool   `json:"installed"`
	Blocklisted bool   `json:"blocklisted"`
	ConfigPath  string `json:"config_path"`
}

MCPClientDTO is one MCP client install state.

type MCPStatusDTO added in v0.19.0

type MCPStatusDTO struct {
	AppName string         `json:"app_name"`
	Clients []MCPClientDTO `json:"clients"`
}

MCPStatusDTO is the aggregate MCP Wick card state.

type MonitorAgent added in v0.36.0

type MonitorAgent struct {
	SessionID    string `json:"session_id"`
	AgentName    string `json:"agent_name"`
	ProviderType string `json:"provider_type"`
	ProviderName string `json:"provider_name"`
	PID          int    `json:"pid"`
	Lifecycle    string `json:"lifecycle"`
	Substate     string `json:"substate"`
	Queued       int    `json:"queued"`
	LastActive   string `json:"last_active,omitempty"`
	// Status is the UI badge: running | idle | spawning | dead.
	Status string `json:"status"`
	// IsSubAgent marks a process that belongs to a delegation rather than
	// a human-facing conversation.
	IsSubAgent bool   `json:"is_sub_agent"`
	ProfileKey string `json:"profile_key,omitempty"`
	// DelegationID lets the UI offer Stop for a sub-agent row.
	DelegationID string `json:"delegation_id,omitempty"`
	RootID       string `json:"root_id,omitempty"`
}

MonitorAgent is one live agent process in the fleet view.

type MonitorTree added in v0.36.0

type MonitorTree struct {
	RootID     string `json:"root_id"`
	RootTask   string `json:"root_task"`
	SubAgents  int    `json:"sub_agents"`
	TurnsUsed  int    `json:"turns_used"`
	TokensUsed int    `json:"tokens_used,omitempty"`
	CostUSD    string `json:"cost_usd,omitempty"`
	Active     int    `json:"active"`
	StartedAt  string `json:"started_at,omitempty"`
	ElapsedSec int    `json:"elapsed_sec"`
	Status     string `json:"status"`
}

MonitorTree summarises one delegation tree. Cheap cost signals — total turns, wall-clock, how many sub-agents — so a tree that is running away is obvious at a glance even before token accounting exists.

type OverviewActiveDTO added in v0.19.0

type OverviewActiveDTO struct {
	SessionID string `json:"session_id"`
	Label     string `json:"label"`
	Lifecycle string `json:"lifecycle"`
	PID       int    `json:"pid,omitempty"`
	ProjectID string `json:"project_id"`
}

OverviewActiveDTO is one row in the active sessions panel returned by /api/overview.

type OverviewDTO added in v0.19.0

type OverviewDTO struct {
	Queued []OverviewQueuedDTO `json:"queued"`
	Active []OverviewActiveDTO `json:"active"`
	Stats  OverviewStatsDTO    `json:"stats"`
}

OverviewDTO is the JSON body returned by GET /api/overview.

type OverviewQueuedDTO added in v0.19.0

type OverviewQueuedDTO struct {
	SessionID string `json:"session_id"`
	AgentName string `json:"agent_name"`
	WaitingMs int64  `json:"waiting_ms"`
	Label     string `json:"label"`
	Project   string `json:"project"`
}

OverviewQueuedDTO is one row in the queue panel returned by /api/overview.

type OverviewStatsDTO added in v0.19.0

type OverviewStatsDTO struct {
	Active   int `json:"active"`
	PoolMax  int `json:"pool_max"`
	QueueLen int `json:"queue_len"`
}

OverviewStatsDTO carries the pool counters for the stats row.

type PoolStatsPayload added in v0.15.2

type PoolStatsPayload struct {
	Active        int                `json:"active"`
	Max           int                `json:"max"`
	QueueLen      int                `json:"queue_len"`
	LiveProcesses []LiveProcessEntry `json:"live_processes"`
}

PublishRaw fires an arbitrary typed SSE event. Used to inject synthetic agent events (e.g. text_delta + done for a switch confirmation reply). PoolStatsPayload is the JSON shape of a pool_stats SSE event. Sent to global ("") subscribers on every lifecycle transition so the Providers page can update the Active Processes panel without reload.

type PresetDetailResponse added in v0.19.0

type PresetDetailResponse struct {
	Name string `json:"name"`
	Body string `json:"body"`
}

PresetDetailResponse is the envelope for GET /api/presets/{name}.

type PresetListItem added in v0.19.0

type PresetListItem struct {
	Name      string `json:"name"`
	IsDefault bool   `json:"is_default,omitempty"`
}

PresetListItem is one row in GET /api/presets.

type PresetListResponse added in v0.19.0

type PresetListResponse struct {
	Presets []PresetListItem `json:"presets"`
}

PresetListResponse is the envelope for GET /api/presets.

type ProjectPinnedSession added in v0.19.0

type ProjectPinnedSession struct {
	ID    string `json:"id"`
	Label string `json:"label"`
}

ProjectPinnedSession is one pinned session row in the API response.

type ProjectSettingsResponse added in v0.19.0

type ProjectSettingsResponse struct {
	ID          string `json:"id"`
	Name        string `json:"name"`
	Icon        string `json:"icon"`
	Description string `json:"description"`
	CustomPath  string `json:"custom_path"`
	Managed     bool   `json:"managed"`
	// IsProtected reports whether the project cannot be deleted — the
	// built-in "default" project or an auto-created personal project.
	// The SPA hides the delete control when true.
	IsProtected     bool   `json:"is_protected"`
	IsNew           bool   `json:"is_new"`
	DefaultPreset   string `json:"default_preset"`
	DefaultProvider string `json:"default_provider"`
	// DefaultModel pins which model on DefaultProvider this project runs,
	// in that instance's own id space (for wick, down to a live-set leaf).
	// Only meaningful alongside DefaultProvider.
	DefaultModel string                 `json:"default_model"`
	SystemAddon  string                 `json:"system_addon"`
	ChatCount    int                    `json:"chat_count"`
	CreatedAt    string                 `json:"created_at"`
	PresetList   []string               `json:"preset_list"`
	ProviderList []ProviderListItem     `json:"provider_list"`
	Pinned       []ProjectPinnedSession `json:"pinned"`
	MetaJSON     string                 `json:"meta_json"`
	Action       string                 `json:"action"`
}

ProjectSettingsResponse is the envelope for GET /api/projects/{id}.

type ProviderCapDTO added in v0.19.0

type ProviderCapDTO struct {
	Used      int  `json:"used"`
	Max       int  `json:"max"`
	Unlimited bool `json:"unlimited"`
}

ProviderCapDTO is the used / effective-max slot count for one provider.

type ProviderDetailResponse added in v0.19.0

type ProviderDetailResponse struct {
	Instance     ProviderInstanceDTO          `json:"instance"`
	Path         string                       `json:"path"`
	PathFound    bool                         `json:"path_found"`
	Version      string                       `json:"version"`
	VersionErr   string                       `json:"version_err,omitempty"`
	Probing      bool                         `json:"probing"`
	Hooks        map[string]HookCapabilityDTO `json:"hooks"`
	HookEnabled  map[string]bool              `json:"hook_enabled"`
	Gate         GateStatusDTO                `json:"gate"`
	GlobalMax    int                          `json:"global_max"`
	ActiveCount  int                          `json:"active_count"`
	ActivePIDs   []LiveProcessDTO             `json:"active_pids"`
	ConfigFields []ConfigFieldDTO             `json:"config_fields"`
	AIRouter     AIRouterDetailDTO            `json:"airouter"`
	// DefaultModels are the per-type catalog seed models (id + description),
	// shown in the model-selection card so the operator sees what's used when
	// the curated list is empty, and can Load them as an editable starting
	// point (id + desc columns). Sourced from the merged catalog
	// (embedded + GitHub + disk cache). Empty for wick (uses WickModels).
	DefaultModels []DefaultModelDTO `json:"default_models,omitempty"`
}

ProviderDetailResponse is the JSON envelope for GET /api/providers/{type}/{name}.

type ProviderInstanceDTO added in v0.19.0

type ProviderInstanceDTO struct {
	Type          string `json:"type"`
	Name          string `json:"name"`
	Binary        string `json:"binary"`
	Disabled      bool   `json:"disabled"`
	MaxConcurrent int    `json:"max_concurrent"`
	SendMode      string `json:"send_mode"`
}

ProviderInstanceDTO is the static config of one instance.

type ProviderListItem added in v0.28.1

type ProviderListItem struct {
	Type string `json:"type"`
	Name string `json:"name"`
	// Models are this instance's selectable models (id+label), so the
	// project default picker can descend to a model level — same data the
	// composer's provider picker uses. Empty for single-model instances.
	Models []ProviderModelItem `json:"models,omitempty"`
}

ProviderListItem is one selectable provider instance for the project defaults dropdown. The "type/name" pair is what Defaults.Provider stores; the SPA renders the value as "type/name" so a custom instance (e.g. claude/abc) is selectable, not just the base type.

type ProviderModelItem added in v0.35.0

type ProviderModelItem struct {
	ID      string `json:"id"`
	Label   string `json:"label"`
	Default bool   `json:"default"`
	Desc    string `json:"desc,omitempty"`
	// Live marks a live model SET, not a single model: the picker expands it
	// one level further (lazily, via the models endpoint with ?entry=) and
	// pins a chosen leaf as "<id>@<vendorModelID>". Without this flag the set
	// looked like an ordinary model whose id resolves to nothing runnable.
	Live bool `json:"live,omitempty"`
}

ProviderModelItem is one model choice under a provider instance.

type ProviderStatusDTO added in v0.19.0

type ProviderStatusDTO struct {
	Instance    ProviderInstanceDTO          `json:"instance"`
	Path        string                       `json:"path"`
	PathFound   bool                         `json:"path_found"`
	Version     string                       `json:"version"`
	VersionErr  string                       `json:"version_err,omitempty"`
	Probing     bool                         `json:"probing"`
	Hooks       map[string]HookCapabilityDTO `json:"hooks"`
	Cap         ProviderCapDTO               `json:"cap"`
	HookEnabled map[string]bool              `json:"hook_enabled"`
}

ProviderStatusDTO is one provider card's data: instance config + live status.

type ProvidersListResponse added in v0.19.0

type ProvidersListResponse struct {
	Providers     []ProviderStatusDTO `json:"providers"`
	Gate          GateStatusDTO       `json:"gate"`
	MCPClients    MCPStatusDTO        `json:"mcp"`
	AutoRescan    bool                `json:"auto_rescan"`
	PoolActive    int                 `json:"pool_active"`
	PoolQueueLen  int                 `json:"pool_queue_len"`
	PoolMax       int                 `json:"pool_max"`
	LiveProcesses []LiveProcessDTO    `json:"live_processes"`
	SupportedKeys []string            `json:"supported_keys"`
}

ProvidersListResponse is the JSON envelope for GET /api/providers.

type RepoSummary added in v0.15.5

type RepoSummary struct {
	Rel     string `json:"rel"`
	Name    string `json:"name"`
	Branch  string `json:"branch"`
	Changed int    `json:"changed"`
	Ahead   int    `json:"ahead"`
	Behind  int    `json:"behind"`
}

RepoSummary is one repo in the /git/repos listing.

type SessionListItem added in v0.19.0

type SessionListItem struct {
	ID          string `json:"id"`
	Label       string `json:"label"`
	Status      string `json:"status"`
	ProjectID   string `json:"project_id"`
	ActiveAgent string `json:"active_agent"`
	CreatedAt   string `json:"created_at"`
	LastActive  string `json:"last_active"`
	Lifecycle   string `json:"lifecycle"`
	PID         int    `json:"pid,omitempty"`
}

SessionListItem is the JSON shape for one session in the /api/sessions list.

type SessionMetaDTO added in v0.19.0

type SessionMetaDTO struct {
	ID          string `json:"id"`
	Label       string `json:"label"`
	Status      string `json:"status"`
	ProjectID   string `json:"project_id"`
	ActiveAgent string `json:"active_agent"`
	TitleCustom bool   `json:"title_custom"`
	CreatedAt   string `json:"created_at"`
	LastActive  string `json:"last_active"`
	// Provider is the active agent's "type/name" provider key — distinct
	// from ActiveAgent (the agent's own name, e.g. "main"). Empty if no
	// agent entry exists yet.
	Provider string `json:"provider,omitempty"`
	// ModelID is the active agent's pinned model id (currently meaningful
	// for wick only). Empty = that provider's own default model.
	ModelID string `json:"model_id,omitempty"`
}

SessionMetaDTO is the JSON shape returned by /api/sessions/{id}/meta.

type SessionSpawnsResponse added in v0.32.0

type SessionSpawnsResponse struct {
	SessionID    string            `json:"session_id"`
	ProviderType string            `json:"provider_type"`
	ProviderName string            `json:"provider_name"`
	Spawns       []SpawnLogFileDTO `json:"spawns"`
}

SessionSpawnsResponse is the JSON envelope for GET /api/providers/sessions/{id} — every spawn of one session, newest first.

type SessionSummaryDTO added in v0.32.0

type SessionSummaryDTO struct {
	SessionID    string `json:"session_id"`
	ProviderType string `json:"provider_type"`
	ProviderName string `json:"provider_name"`
	SpawnCount   int    `json:"spawn_count"`
	LastStatus   string `json:"last_status"`   // exit reason of the newest spawn ("" → running)
	LastStarted  string `json:"last_started"`  // RFC3339 of the newest spawn
	FirstMessage string `json:"first_message"` // newest spawn's first user message
	Origin       string `json:"origin,omitempty"`
}

SessionSummaryDTO is one row in the per-session Recent Spawns list: a session that spawned one or more processes, collapsed to its latest state. Clicking it opens the session detail (all its spawns).

type SessionsListResponse added in v0.32.0

type SessionsListResponse struct {
	Sessions []SessionSummaryDTO `json:"sessions"`
	Page     int                 `json:"page"`
	HasNext  bool                `json:"has_next"`
	Total    int                 `json:"total"`
}

SessionsListResponse is the JSON envelope for GET /api/providers/sessions.

type SkillDetailResponse added in v0.19.0

type SkillDetailResponse struct {
	Name        string          `json:"name"`
	IsDir       bool            `json:"is_dir"`
	Content     string          `json:"content,omitempty"`
	SourcePath  string          `json:"source_path,omitempty"`
	InDirs      []string        `json:"in_dirs"`
	Entries     []SkillListItem `json:"entries,omitempty"`
	MissingDirs []string        `json:"missing_dirs,omitempty"`
}

SkillDetailResponse is the envelope for GET /api/skills/{name}.

type SkillFileDetailResponse added in v0.19.0

type SkillFileDetailResponse struct {
	Name       string          `json:"name"`
	IsDir      bool            `json:"is_dir"`
	Content    string          `json:"content,omitempty"`
	SourcePath string          `json:"source_path,omitempty"`
	InDirs     []string        `json:"in_dirs"`
	Entries    []SkillListItem `json:"entries,omitempty"`
}

SkillFileDetailResponse is the envelope for GET /api/skills/{folder}/files/{file...}.

type SkillListItem added in v0.19.0

type SkillListItem struct {
	Name        string   `json:"name"`
	IsDir       bool     `json:"is_dir"`
	InDirs      []string `json:"in_dirs"`
	MissingDirs []string `json:"missing_dirs"`
}

SkillListItem is one row in GET /api/skills.

type SkillListResponse added in v0.19.0

type SkillListResponse struct {
	Dirs   []string        `json:"dirs"`
	Skills []SkillListItem `json:"skills"`
}

SkillListResponse is the envelope for GET /api/skills.

type SkillProviderEntryResponse added in v0.19.0

type SkillProviderEntryResponse struct {
	Provider     string          `json:"provider"`
	Path         string          `json:"path"`
	IsDir        bool            `json:"is_dir"`
	Content      string          `json:"content,omitempty"`
	SourcePath   string          `json:"source_path,omitempty"`
	Entries      []SkillListItem `json:"entries,omitempty"`
	AllProviders []string        `json:"all_providers"`
	HasFile      map[string]bool `json:"has_file,omitempty"`
}

SkillProviderEntryResponse is the envelope for GET /api/skills/{provider}/{path...}.

type SpawnDetailResponse added in v0.28.1

type SpawnDetailResponse struct {
	File           SpawnLogFileDTO   `json:"file"`
	Events         []SpawnEventDTO   `json:"events"`
	SessionDeleted bool              `json:"session_deleted"`
	Repro          map[string]string `json:"repro"`
	// HasResume is true when the spawn carried a --resume/resume id, so the
	// Keep/Fresh toggle is meaningful. False on a session's first spawn.
	HasResume bool `json:"has_resume"`
	// Logs points the operator at the on-disk log files relevant to this
	// spawn so a crash can be copied out for analysis without shelling in.
	Logs SpawnLogsDTO `json:"logs"`
}

SpawnDetailResponse is the full spawn-log detail: metadata, the event timeline, whether the session was since deleted, and the MASKED reproduce commands keyed by view.ReproKey (shell-mode-path). Unmasked variants come from the separate reveal endpoint.

type SpawnEventDTO added in v0.28.1

type SpawnEventDTO struct {
	Type             string   `json:"type"`
	At               string   `json:"at"`
	ProviderType     string   `json:"provider_type,omitempty"`
	ProviderName     string   `json:"provider_name,omitempty"`
	AgentName        string   `json:"agent_name,omitempty"`
	Workspace        string   `json:"workspace,omitempty"`
	ResumeID         string   `json:"resume_id,omitempty"`
	Binary           string   `json:"binary,omitempty"`
	Args             []string `json:"args,omitempty"`
	Env              []string `json:"env,omitempty"`
	PID              int      `json:"pid,omitempty"`
	Origin           string   `json:"origin,omitempty"`
	FirstUserMessage string   `json:"first_user_message,omitempty"`
	ExitReason       string   `json:"exit_reason,omitempty"`
	ReasonDetail     string   `json:"reason_detail,omitempty"`
	ExitCode         int      `json:"exit_code,omitempty"`
	StderrTail       string   `json:"stderr_tail,omitempty"`
	DurationMs       int64    `json:"duration_ms,omitempty"`
	Error            string   `json:"error,omitempty"`
	Message          string   `json:"message,omitempty"`
}

SpawnEventDTO is one event line from a spawn log's timeline.

type SpawnLogFileDTO added in v0.19.0

type SpawnLogFileDTO struct {
	Path             string `json:"path"`
	ProviderType     string `json:"provider_type"`
	ProviderName     string `json:"provider_name"`
	SessionID        string `json:"session_id"`
	StartedAt        string `json:"started_at"`
	PID              int    `json:"pid,omitempty"`
	Origin           string `json:"origin,omitempty"`
	FirstUserMessage string `json:"first_user_message,omitempty"`
	Binary           string `json:"binary,omitempty"`
	ExitReason       string `json:"exit_reason,omitempty"`
	// ReasonDetail is the "why it ended" sentence; ExitCode + StderrTail
	// carry the crash detail. All empty/0 while the spawn is still alive.
	ReasonDetail string `json:"reason_detail,omitempty"`
	ExitCode     int    `json:"exit_code,omitempty"`
	StderrTail   string `json:"stderr_tail,omitempty"`
}

SpawnLogFileDTO is a parsed spawn log file entry.

type SpawnLogsDTO added in v0.32.0

type SpawnLogsDTO struct {
	SpawnPath  string      `json:"spawn_path"`           // full path to the spawn jsonl
	LogsDir    string      `json:"logs_dir,omitempty"`   // absolute logs dir for display
	Components []LogRefDTO `json:"components,omitempty"` // process logs from the spawn day(s)
	Window     SpawnWindow `json:"window"`               // start→end time range to scan
	// LogsPresent is the total number of .log files in the logs dir (any
	// date). 0 = no process logs are being written at all (e.g. dev/console
	// mode) — lets the UI explain an empty Components list.
	LogsPresent int `json:"logs_present"`
}

SpawnLogsDTO carries the on-disk log paths + the spawn's time window for one spawn's detail page. SpawnPath is the spawn's own jsonl (full event timeline incl. crash stderr). Components lists the process logs (app/server/worker/mcp/gate/daemon) written on the spawn's day(s), so the operator can open the right file and scan the Window range.

type SpawnWindow added in v0.32.0

type SpawnWindow struct {
	Start      string `json:"start"`         // RFC3339
	End        string `json:"end,omitempty"` // RFC3339; "" only while genuinely running
	DurationMs int64  `json:"duration_ms,omitempty"`
	Running    bool   `json:"running"`
	Unclean    bool   `json:"unclean"` // died without an exit event; End is approximate
}

SpawnWindow is the spawn's lifetime — start (spawn) → end. End comes from the exit event when the process shut down cleanly. Running=true only when the process is genuinely still alive. Unclean=true means the process died WITHOUT recording an exit (crash / OS-kill): End is then a best-effort "last sign of life" (the last event's timestamp), not a real exit time.

type SpawnsListResponse added in v0.32.0

type SpawnsListResponse struct {
	Spawns  []SpawnLogFileDTO `json:"spawns"`
	Page    int               `json:"page"`
	HasNext bool              `json:"has_next"`
	Total   int               `json:"total"` // matches after filter, before paging
}

SpawnsListResponse is the JSON envelope for GET /api/providers/spawns — the single source for the Recent Spawns table on both the providers list page (type/name empty = all) and a provider detail page (scoped). Search (q) + pagination happen server-side so one contract serves both.

type SquadItem added in v0.36.0

type SquadItem struct {
	ID               string   `json:"id"`
	Key              string   `json:"key"`
	Name             string   `json:"name"`
	Description      string   `json:"description"`
	LeaderProfileKey string   `json:"leader_profile_key"`
	MemberKeys       []string `json:"member_profile_keys"`
	Disabled         bool     `json:"disabled"`
}

SquadItem is one squad as the UI sees it.

type StorageFileDTO added in v0.19.0

type StorageFileDTO struct {
	ID            uint   `json:"id"`
	ProviderType  string `json:"provider_type"`
	InstanceName  string `json:"instance_name"`
	RelPath       string `json:"rel_path"`
	Name          string `json:"name"`
	IsDir         bool   `json:"is_dir"`
	Size          int    `json:"size"`
	SyncedAt      string `json:"synced_at"`
	RetentionDays int    `json:"retention_days"`
}

StorageFileDTO is one storage file row (without the binary content blob).

type StorageFileVM added in v0.11.0

type StorageFileVM struct {
	entity.ProviderStorage
	SyncedAtFmt string
}

StorageFileVM is the view model for one file row in the storage table.

type StoragePageVM added in v0.11.0

type StoragePageVM struct {
	Base           string
	Files          []StorageFileVM
	FilterProvider string
	FilterInstance string
	ProviderTypes  []string
}

StoragePageVM is the view model for the storage manager page.

type StorageResponse added in v0.19.0

type StorageResponse struct {
	Files          []StorageFileDTO `json:"files"`
	FilterProvider string           `json:"filter_provider,omitempty"`
	FilterInstance string           `json:"filter_instance,omitempty"`
	ProviderTypes  []string         `json:"provider_types"`
}

StorageResponse is the JSON envelope for GET /api/providers/storage.

type SubAgentItem added in v0.36.0

type SubAgentItem struct {
	DelegationID   string `json:"delegation_id"`
	ChildSessionID string `json:"child_session_id"`
	ProfileKey     string `json:"profile_key"`
	// Handle is this instance's address inside its tree — what an @mention
	// resolves to. Empty on rows written before handles existed.
	Handle string `json:"handle,omitempty"`
	// Label is the task, truncated for display.
	Label  string `json:"label"`
	Status string `json:"status"`
	// Lifecycle is merged in from the pool's live snapshot; "" when the
	// child has no active process. Same merge apiSessionList does, so
	// there is only ever one source of truth for liveness.
	Lifecycle string `json:"lifecycle"`
	Depth     int    `json:"depth"`
	TurnsUsed int    `json:"turns_used"`
	MaxTurns  int    `json:"max_turns"`
	Result    string `json:"result,omitempty"`
	StartedAt string `json:"started_at,omitempty"`
	// EndedAt is when the delegation reached a terminal status. Absent
	// while it is queued or running, which is exactly how the UI tells
	// "finished 5m ago" apart from "started 5m ago".
	EndedAt string `json:"ended_at,omitempty"`
	// QueuePosition is the 1-based place this delegation holds in its
	// tree's waiting line, 0 when it is not queued. Computed server-side
	// so the panel never has to infer ordering from timestamps it may
	// have received out of order.
	QueuePosition int `json:"queue_position,omitempty"`
	// Envelope is the sub-agent's structured answer, when it finished.
	// Absent while it is still working.
	Envelope *delegation.ResultEnvelope `json:"envelope,omitempty"`
}

SubAgentItem is one row in the Sub-agents rail panel. Flat and string-typed, matching SessionListItem, so the SPA needs no special decoding.

type TestCaseItem added in v0.14.20

type TestCaseItem struct {
	Name   string
	Case   wftest.Case
	Result *wftest.Result
}

TestCaseItem pairs an on-disk test case with its last-run result for the spa test panel handlers.

Directories

Path Synopsis
templ: version: v0.3.1020
templ: version: v0.3.1020
workflow
templ: version: v0.3.1020
templ: version: v0.3.1020

Jump to

Keyboard shortcuts

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