Documentation
¶
Overview ¶
Package serve provides an HTTP/WebSocket server for managing multiple agent sessions through a web dashboard.
Index ¶
- Variables
- func NewServer(manager *Manager, opts ...ServerOption) http.Handler
- type AskData
- type Attachment
- type AttachmentDTO
- type BashCompleteData
- type BashJobEndData
- type BashJobInitData
- type BashJobOutputData
- type BashJobStartData
- type CommandData
- type CommandDequeuedData
- type CommandQueuedData
- type CommandResult
- type ConfigChangeData
- type ContextUpdateData
- type ConversationMessage
- type CreateOpts
- type DeltaData
- type Event
- type GoalChangeData
- type GoalEndData
- type GoalIterationData
- type InitData
- type MCPChangeData
- type MCPSummary
- type ManagedSession
- type Manager
- func (m *Manager) ArchiveSession(id string, archived bool) error
- func (m *Manager) Cancel(sessionID string) error
- func (m *Manager) CancelBashJob(sessionID, jobID string) error
- func (m *Manager) CancelSubagent(sessionID, jobID string) error
- func (m *Manager) CreateSession(opts CreateOpts) (*ManagedSession, error)
- func (m *Manager) Delete(id string) error
- func (m *Manager) ExecCommand(sessionID, rawCommand, id string) (*CommandResult, error)
- func (m *Manager) FileScanner() *files.Scanner
- func (m *Manager) Get(id string) (*ManagedSession, bool)
- func (m *Manager) GetSubagentTranscript(sessionID, jobID string) (*session.SubagentTranscript, error)
- func (m *Manager) InvalidateFileCache(cwd string)
- func (m *Manager) List() []SessionInfo
- func (m *Manager) ListSubagentTranscripts(sessionID string) ([]session.SubagentTranscript, error)
- func (m *Manager) PromoteSubagent(sessionID, jobID string) error
- func (m *Manager) ReconfigureSession(sessionID, modelSpec, thinking string) (map[string]string, error)
- func (m *Manager) ResumeSession(id string) (*ManagedSession, error)
- func (m *Manager) Send(sessionID, text string, atts []Attachment, steerID string) (action, id string, descriptors []attachment.Descriptor, err error)
- func (m *Manager) SetCompactAt(sessionID string, tokens int) (int, error)
- func (m *Manager) SetPermissionMode(sessionID, modeStr string) (string, error)
- func (m *Manager) SetTitle(sessionID, title string) (string, error)
- func (m *Manager) Shutdown()
- func (m *Manager) SteerSubagent(sessionID, jobID, text string) (bool, error)
- func (m *Manager) ToggleMCPServer(anchor *ManagedSession, params mcpDisableParams, server string) (mcpToggleResult, error)
- func (m *Manager) Version() release.Result
- type ManagerConfig
- type MessageEndData
- type PendingSteerData
- type PermissionData
- type PlanModeData
- type RateLimitData
- type RealtimeAPIKeyFunc
- type RunEndData
- type RunTokensData
- type ServerOption
- func WithAllowedHosts(hosts []string) ServerOption
- func WithAuthToken(token string, secureCookie bool) ServerOption
- func WithDeviceAuthentication() ServerOption
- func WithDeviceStorePath(path string) ServerOption
- func WithRealtimeClientSecretBroker(key RealtimeAPIKeyFunc, client *http.Client) ServerOption
- type SessionCostData
- type SessionInfo
- type SessionState
- type StateChangeData
- type SteerData
- type SubagentCompleteData
- type SubagentCountData
- type SubagentEndData
- type SubagentEventData
- type SubagentInitData
- type SubagentStartData
- type SubagentSummary
- type SubagentUsageData
- type TasksUpdateData
- type ToolCallDeltaData
- type ToolCallStreamingData
- type ToolEndData
- type ToolStartData
- type ToolUpdateData
Constants ¶
This section is empty.
Variables ¶
var ( // ErrScopeInvalid is returned for a scope that isn't session/project/global. ErrScopeInvalid = errors.New("invalid scope") // ErrProjectUntrusted is returned when a project-scope write is requested for // a session whose project config path isn't trusted (409). ErrProjectUntrusted = errors.New("project config is untrusted") )
Errors returned by the MCP toggle path, mapped to HTTP status by the handler.
var ( ErrNotFound = errors.New("session not found") ErrBusy = errors.New("session is busy") ErrInvalidCWD = errors.New("invalid working directory") ErrInvalidModel = errors.New("invalid model") ErrNoMCP = errors.New("session has no MCP servers") )
var ErrBadAttachment = errors.New("bad attachment")
ErrBadAttachment wraps any attachment validation failure; the wrapping error message names the offending attachment and is safe to surface as a 400.
Functions ¶
Types ¶
type AskData ¶
type AskData struct {
ID string `json:"id"`
Questions []bus.AskQuestion `json:"questions"`
}
AskData is a pending ask_user request.
type Attachment ¶
type Attachment struct {
Name string `json:"name"`
Mime string `json:"mime"`
Data string `json:"data"` // base64 standard encoding
}
Attachment is a file uploaded inline (base64) with a /send request.
type AttachmentDTO ¶
type AttachmentDTO struct {
ID string `json:"id"`
Name string `json:"name"`
Mime string `json:"mime"`
Size int64 `json:"size"`
Kind string `json:"kind"`
Width int `json:"width"`
Height int `json:"height"`
URL string `json:"url"`
}
AttachmentDTO is the public metadata returned for attachments created by a send. The URL is served by the attachment endpoint.
type BashCompleteData ¶
type BashCompleteData struct {
JobID string `json:"job_id"`
OwnerAgentID string `json:"owner_agent_id,omitempty"`
Command string `json:"command"`
Status string `json:"status"`
Text string `json:"text"`
}
BashCompleteData is sent when an async background bash job finishes and its formatted result is reinjected into the conversation.
type BashJobEndData ¶
type BashJobInitData ¶
type BashJobInitData struct {
JobID string `json:"job_id"`
OwnerAgentID string `json:"owner_agent_id,omitempty"`
Command string `json:"command"`
CWD string `json:"cwd"`
Status string `json:"status"`
Output string `json:"output"`
}
BashJobInitData restores a live/recent background command after reconnect.
type BashJobOutputData ¶
type BashJobStartData ¶
type CommandData ¶
type CommandData struct {
Command string `json:"command"`
Messages []core.AgentMessage `json:"messages,omitempty"` // compact sends updated messages
HistoryTruncated bool `json:"history_truncated,omitempty"`
}
CommandData is sent when a slash command is executed.
type CommandDequeuedData ¶
type CommandDequeuedData struct {
ID string `json:"id"`
Raw string `json:"raw"`
Executed bool `json:"executed"`
Err string `json:"err,omitempty"`
}
CommandDequeuedData is sent when a queued command barrier leaves the queue (after execution, cancellation, or a permanent failure). The client removes the matching chip by ID. Err is set when it left because execution failed.
type CommandQueuedData ¶
CommandQueuedData is sent when a slash command is enqueued as a barrier in the unified queue rail (issued while the session was busy). The client renders a queued command chip keyed by ID, distinct from a queued message chip.
type CommandResult ¶
type CommandResult struct {
OK bool `json:"ok"`
Message string `json:"message"`
NewSessionID string `json:"newSessionId,omitempty"`
// Queued is true when the command was not executed now but enqueued as a
// barrier in the unified queue rail (issued while the session was busy). ID
// is then the queued chip's authoritative ID, so the client reconciles its
// optimistic command chip by ID.
Queued bool `json:"queued,omitempty"`
ID string `json:"id,omitempty"`
}
CommandResult is the response from executing a slash command.
type ConfigChangeData ¶
type ConfigChangeData struct {
Model string `json:"model,omitempty"`
Provider string `json:"provider,omitempty"`
Thinking string `json:"thinking,omitempty"`
PermissionMode string `json:"permission_mode,omitempty"`
PathScope string `json:"path_scope,omitempty"`
// CompactAt carries a compaction-threshold change only. Pointer because 0
// ("compact at the model window") is a real setting, not "unchanged".
CompactAt *int `json:"compact_at,omitempty"`
// ContextWindow carries a model switch's new input window, the denominator
// for every context percentage the client shows.
ContextWindow int `json:"context_window,omitempty"`
}
ConfigChangeData is sent when model/thinking/permissions/path scope change.
type ContextUpdateData ¶
type ContextUpdateData struct {
ContextPercent int `json:"context_percent"`
}
ContextUpdateData carries the current context usage percentage.
type ConversationMessage ¶
type ConversationMessage struct {
ID string `json:"id"`
Role string `json:"role"`
Timestamp time.Time `json:"timestamp,omitempty"`
Text string `json:"text,omitempty"`
Truncated bool `json:"truncated,omitempty"`
Omitted bool `json:"omitted,omitempty"`
OmittedBlocks int `json:"omitted_blocks,omitempty"`
Tool string `json:"tool,omitempty"`
Action string `json:"action,omitempty"`
Target string `json:"target,omitempty"`
Status string `json:"status,omitempty"`
Attachments []AttachmentDTO `json:"attachments,omitempty"`
}
ConversationMessage is the owner-facing transcript DTO. Tool activity is projected into role=tool items; tool result output remains available only through the explicit detail query.
type CreateOpts ¶
type CreateOpts struct {
Model string `json:"model"`
Title string `json:"title"`
CWD string `json:"cwd"`
}
CreateOpts configures a new session.
type DeltaData ¶
type DeltaData struct {
Delta string `json:"delta"`
}
DeltaData carries a streaming text delta.
type Event ¶
type Event struct {
Type string `json:"type"`
Data any `json:"data,omitempty"`
Seq uint64 `json:"seq,omitempty"`
}
Event is a JSON-serializable event sent to WebSocket clients.
type GoalChangeData ¶
type GoalChangeData struct {
Active bool `json:"active"`
Objective string `json:"objective,omitempty"`
WorkDir string `json:"work_dir,omitempty"`
Iteration int `json:"iteration"`
Stalled int `json:"stalled"`
}
GoalChangeData is sent when goal mode activates or deactivates.
type GoalEndData ¶
type GoalEndData struct {
Reason string `json:"reason"`
}
GoalEndData is sent when a goal loop ends.
type GoalIterationData ¶
type GoalIterationData struct {
Iteration int `json:"iteration"`
Satisfied bool `json:"satisfied"`
Feedback string `json:"feedback,omitempty"`
}
GoalIterationData is sent after the verifier judges a goal iteration.
type InitData ¶
type InitData struct {
Messages []core.AgentMessage `json:"messages"`
State string `json:"state"`
ContextPercent int `json:"context_percent"`
ContextWindow int `json:"context_window,omitempty"`
CompactAt int `json:"compact_at,omitempty"`
CompactAtMin int `json:"compact_at_min,omitempty"`
PermissionMode string `json:"permission_mode"`
PathScope string `json:"path_scope,omitempty"`
PendingPermission *PermissionData `json:"pending_permission,omitempty"`
PendingAsk *AskData `json:"pending_ask,omitempty"`
Tasks any `json:"tasks,omitempty"`
PlanMode string `json:"plan_mode,omitempty"`
PlanFile string `json:"plan_file,omitempty"`
GoalActive bool `json:"goal_active,omitempty"`
GoalObjective string `json:"goal_objective,omitempty"`
GoalWorkDir string `json:"goal_work_dir,omitempty"`
GoalIteration int `json:"goal_iteration,omitempty"`
GoalStalled int `json:"goal_stalled,omitempty"`
GoalVerifying bool `json:"goal_verifying,omitempty"`
Compacting bool `json:"compacting,omitempty"`
StreamingText string `json:"streaming_text,omitempty"`
StreamingThinking string `json:"streaming_thinking,omitempty"`
RunTokensUp int `json:"run_tokens_up"`
RunTokensDown int `json:"run_tokens_down"`
RunStartedAtMs int64 `json:"run_started_at_ms,omitempty"`
PendingSteers []PendingSteerData `json:"pending_steers,omitempty"`
CostUSD float64 `json:"cost_usd,omitempty"`
Subagents []SubagentInitData `json:"subagents,omitempty"`
BashJobs []BashJobInitData `json:"bash_jobs,omitempty"`
LastSeq uint64 `json:"last_seq,omitempty"`
HistoryTruncated bool `json:"history_truncated,omitempty"`
}
InitData is sent on WebSocket connect with the full session state.
type MCPChangeData ¶
type MCPChangeData struct {
Total int `json:"total"`
Ready int `json:"ready"`
Disabled int `json:"disabled"`
Unhealthy int `json:"unhealthy"`
Pending int `json:"pending"`
}
MCPChangeData carries the rolled-up MCP summary counts for the status-line indicator, matching the MCPSummary fields. An open panel re-fetches full per-server detail from GET /api/sessions/{id}/mcp when this arrives.
type MCPSummary ¶
type MCPSummary struct {
Total int `json:"total"`
Ready int `json:"ready"`
Disabled int `json:"disabled"`
Unhealthy int `json:"unhealthy"`
Pending int `json:"pending"`
}
MCPSummary is the glanceable MCP health for the status line. Total counts all configured servers (including disabled ones); Disabled is the count in the intentionally-off state (neutral, not an alarm); Unhealthy counts only servers that are enabled yet failed/exited (the alert color); Pending counts servers mid-transition (desired differs from applied). The indicator shows whenever Total > 0 and turns to an alert color only when Unhealthy > 0.
type ManagedSession ¶
type ManagedSession struct {
// Immutable after construction.
ID string `json:"id"`
CWD string `json:"cwd"`
Created time.Time `json:"created"`
Title string
TitleSource string // "manual" | "auto" | "" (legacy=auto); see session.TitleSource
Archived bool // closed-but-kept (presentation-only); see session.Session.Archived
Updated time.Time
// contains filtered or unexported fields
}
ManagedSession wraps a bus.SessionRuntime with metadata for the web dashboard.
func (*ManagedSession) History ¶
func (s *ManagedSession) History() []core.AgentMessage
History returns a copy of the session's conversation messages.
func (*ManagedSession) MCPStatus ¶
func (s *ManagedSession) MCPStatus() []mcp.ControllerStatus
MCPStatus returns the policy-decorated health snapshot of this session's MCP servers (empty if none are configured). Each entry carries the applied enabled state, desired-enabled, the scopes that veto it, and any pending action.
func (*ManagedSession) RestartMCPServer ¶
func (s *ManagedSession) RestartMCPServer(name string) (mcp.ServerStatus, error)
RestartMCPServer restarts a single MCP server for this session and re-syncs the tool registry with its (possibly changed) tool set. Other servers are untouched. Returns ErrNoMCP if the session has no MCP manager, mcp.ErrUnknownServer for a name it doesn't manage, mcp.ErrServerDisabled for a disabled server (enable it first), or ErrBusy if the session is running or awaiting a permission decision.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager owns all active sessions.
func NewManager ¶
func NewManager(ctx context.Context, cfg ManagerConfig) *Manager
NewManager creates a Manager. The context controls the lifetime of all agent runs — cancelling it aborts every active session.
func (*Manager) ArchiveSession ¶
ArchiveSession sets or clears the archived flag on a session, whether it is currently active in memory or only saved on disk. Archiving is presentation-only: it never unloads an active session or touches Updated.
func (*Manager) CancelBashJob ¶
CancelBashJob cancels a session-scoped background bash job.
func (*Manager) CancelSubagent ¶
CancelSubagent requests cancellation of a single (async) subagent job belonging to a session, without aborting the parent run.
func (*Manager) CreateSession ¶
func (m *Manager) CreateSession(opts CreateOpts) (*ManagedSession, error)
CreateSession creates a new agent session.
func (*Manager) Delete ¶
Delete aborts any running agent, closes resources, and removes the session.
func (*Manager) ExecCommand ¶
func (m *Manager) ExecCommand(sessionID, rawCommand, id string) (*CommandResult, error)
ExecCommand executes a slash command in a session. id is the client-minted stable ID for the optimistic chip when the command is enqueued as a barrier (busy session, PolicyQueue); it is ignored when the command runs immediately.
func (*Manager) FileScanner ¶
FileScanner returns the shared file scanner instance.
func (*Manager) Get ¶
func (m *Manager) Get(id string) (*ManagedSession, bool)
Get returns a managed session by ID.
func (*Manager) GetSubagentTranscript ¶
func (m *Manager) GetSubagentTranscript(sessionID, jobID string) (*session.SubagentTranscript, error)
GetSubagentTranscript loads one persisted transcript by jobID.
func (*Manager) InvalidateFileCache ¶
InvalidateFileCache invalidates the file scanner cache for a given CWD. Called after successful file edits to keep file suggestions fresh.
func (*Manager) List ¶
func (m *Manager) List() []SessionInfo
List returns info for all sessions, sorted by updated time descending.
func (*Manager) ListSubagentTranscripts ¶
func (m *Manager) ListSubagentTranscripts(sessionID string) ([]session.SubagentTranscript, error)
ListSubagentTranscripts returns the persisted subagent transcripts for a session (newest-finished first). Returns ErrNotFound if the session isn't active or has no persistence.
func (*Manager) PromoteSubagent ¶
PromoteSubagent flips a running sync subagent job to async, unblocking its parent's blocking tool call while the child keeps running in the background. Returns ErrNotFound if the session/job doesn't exist, and propagates subagent.ErrNotSync / subagent.ErrNotRunning otherwise so callers can map them to specific responses.
func (*Manager) ReconfigureSession ¶
func (m *Manager) ReconfigureSession(sessionID, modelSpec, thinking string) (map[string]string, error)
ReconfigureSession changes the model and/or thinking level of a session. Only allowed when the session is idle (not running).
func (*Manager) ResumeSession ¶
func (m *Manager) ResumeSession(id string) (*ManagedSession, error)
ResumeSession loads a saved session from disk and creates a full runtime.
func (*Manager) Send ¶
func (m *Manager) Send(sessionID, text string, atts []Attachment, steerID string) (action, id string, descriptors []attachment.Descriptor, err error)
Send delivers a user message (with optional attachments) to a session. If idle: starts a new agent run via bus. If running/permission: steers the running agent (attachments not allowed there). steerID, when non-empty, is the client-minted stable ID for the queued message: the client shows its optimistic chip under that same ID, so there is no window where a chip lacks an authoritative identity (closes the double-send and cancel-vs-in-flight races). When empty (e.g. CLI), the handler mints one. Returns the action taken ("send" or "steer") and the ID the message was queued under so the caller can reconcile by ID.
func (*Manager) SetCompactAt ¶
SetCompactAt changes a session's soft compaction threshold (tokens), so the agent compacts once context passes it rather than waiting for the full model window. 0 restores the window-based default. Like model/thinking this reconfigures the agent, so it is only allowed while the session is idle.
func (*Manager) SetPermissionMode ¶
SetPermissionMode changes the permission mode for a session via bus command.
func (*Manager) SetTitle ¶
SetTitle renames a session, marking the title as manually set so background auto-titling won't overwrite it, and persists the change immediately.
func (*Manager) Shutdown ¶
func (m *Manager) Shutdown()
Shutdown synchronously flushes every active session to disk. Call it after the HTTP server has stopped accepting requests and before the process exits, so a turn that finished just before shutdown is persisted even though the async RunEnded→TreeSynced→save chain may not have drained.
A SIGTERM cancels the root context, which cancels each in-flight run. Before flushing we wait — bounded by shutdownDrainBudget across the whole process — for active sessions to leave the running/permission state, so a snapshot captures the complete final turn rather than a partial one. If the budget expires we flush regardless (best effort beats losing the turn entirely).
func (*Manager) SteerSubagent ¶
SteerSubagent queues a message for inter-step delivery to the running child agent of a subagent job. Returns ErrNotFound if the session or job doesn't exist. The bool reports whether the message was actually queued (false if the job has no live child agent yet or has already finished).
func (*Manager) ToggleMCPServer ¶
func (m *Manager) ToggleMCPServer(anchor *ManagedSession, params mcpDisableParams, server string) (mcpToggleResult, error)
ToggleMCPServer applies a disable/enable preference for one server in one scope, persisting it (project/global) and fanning it out to every affected open session in the process:
- session: only the anchor session,
- project: every open session whose canonical cwd matches the anchor's,
- global: every open session in the process.
The persisted scope also governs future session startups. Returns how many sessions applied the change now vs deferred it to quiescence. anchor must be a session that has the server configured (the caller validates that via GET).
type ManagerConfig ¶
type ManagerConfig struct {
ProviderFactory func(model core.Model) (core.Provider, error)
Transcriber core.Transcriber // optional; enables POST /api/transcribe
UsagePoller *usage.Poller // optional; enables GET /api/usage
PushStore *push.Store // optional; enables Web Push
PushDispatcher *push.Dispatcher // optional; enables Web Push
DefaultModel core.Model
WorkspaceRoot string
MoaCfg core.MoaConfig
// ConfigLoader loads configuration for an individual session CWD. When
// nil, core.LoadMoaConfig preserves the normal global/project lookup.
ConfigLoader func(cwd string) core.MoaConfig
SessionBaseDir string // root for session stores; empty = default
// SchedulePath overrides the durable schedules file. Empty stores it beside
// the session base directory.
SchedulePath string
ReleaseInfo release.Info
UpdateChecker *release.Checker
UpdateCheckEnabled bool
}
ManagerConfig configures a Manager.
type MessageEndData ¶
type MessageEndData struct {
Text string `json:"text"`
MsgID string `json:"msg_id,omitempty"`
InputTokens int `json:"input_tokens,omitempty"`
OutputTokens int `json:"output_tokens,omitempty"`
}
MessageEndData carries the full assistant text on message completion and the provider-reported usage for that message.
type PendingSteerData ¶
type PendingSteerData struct {
ID string `json:"id"`
Text string `json:"text"`
Command bool `json:"command,omitempty"`
Images int `json:"images,omitempty"`
}
PendingSteerData is one queued (not yet delivered) item in the unified queue rail, with its authoritative ID so a reconnecting client reconciles its optimistic chip by ID instead of by text. Command marks a queued slash-command barrier (Text holds its raw command line, e.g. "/compact") so the client renders a command chip; Images is the number of image blocks a queued message carries (0 for a plain-text steer or a command) so the chip can show an attachment badge.
type PermissionData ¶
type PermissionData struct {
ID string `json:"id"`
ToolName string `json:"tool_name"`
Args map[string]any `json:"args"`
AllowPattern string `json:"allow_pattern,omitempty"`
}
PermissionData is a pending permission request.
type PlanModeData ¶
PlanModeData is sent on plan mode state changes.
type RateLimitData ¶
type RateLimitData struct {
Status string `json:"status,omitempty"`
RepresentativeClaim string `json:"representative_claim,omitempty"`
OnOverage bool `json:"on_overage"`
FiveHourPct int `json:"five_hour_pct"`
SevenDayPct int `json:"seven_day_pct"`
OveragePct int `json:"overage_pct"`
}
RateLimitData carries the provider's per-request rate-limit state: plan-window utilization (as percentages, to match /api/usage) and whether this request was served from extra usage.
type RealtimeAPIKeyFunc ¶
RealtimeAPIKeyFunc returns only a normal OpenAI API key. ok must be false for missing credentials and OAuth credentials.
type RunEndData ¶
type RunEndData struct {
Text string `json:"text"`
}
RunEndData carries the final assistant text when a run completes.
type RunTokensData ¶
RunTokensData carries the current run's estimated logical input/output traffic.
type ServerOption ¶
type ServerOption func(*serverOptions)
ServerOption configures optional NewServer behavior.
func WithAllowedHosts ¶
func WithAllowedHosts(hosts []string) ServerOption
WithAllowedHosts adds extra hostnames accepted by the anti DNS-rebinding Host check (on top of localhost and any IP literal). Use it for named hosts such as a Tailscale MagicDNS name.
func WithAuthToken ¶
func WithAuthToken(token string, secureCookie bool) ServerOption
WithAuthToken enables opt-in shared-token authentication. An empty token leaves the server unauthenticated (current behavior). secureCookie marks the session cookie Secure and should be true only when served over TLS.
func WithDeviceAuthentication ¶
func WithDeviceAuthentication() ServerOption
WithDeviceAuthentication enables Pulse device pairing and credentials when Serve is embedded without a shared token. The CLI enables it by default; tests and other embedders opt in explicitly.
func WithDeviceStorePath ¶
func WithDeviceStorePath(path string) ServerOption
WithDeviceStorePath overrides the private device credential store. It is primarily useful for embedded deployments and tests; normal Serve uses ~/.config/moa/devices.json (or MOA_CONFIG_DIR/devices.json).
func WithRealtimeClientSecretBroker ¶
func WithRealtimeClientSecretBroker(key RealtimeAPIKeyFunc, client *http.Client) ServerOption
WithRealtimeClientSecretBroker supplies the narrowly scoped capability used to mint OpenAI Realtime client secrets. The key is never retained by Serve.
type SessionCostData ¶
type SessionCostData struct {
CostUSD float64 `json:"cost_usd"`
}
SessionCostData carries the accumulated session spend (main run + subagents).
type SessionInfo ¶
type SessionInfo struct {
ID string `json:"id"`
Title string `json:"title"`
Archived bool `json:"archived,omitempty"`
State SessionState `json:"state"`
Model string `json:"model"`
Provider string `json:"provider"`
Thinking string `json:"thinking"`
CWD string `json:"cwd"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
Error string `json:"error,omitempty"`
UntrustedMCP bool `json:"untrusted_mcp,omitempty"`
// MCP summarizes this session's MCP servers for the status line: a count and
// whether any is unhealthy, so the indicator can appear only when servers
// exist and turn red when one has failed or exited. The full per-server
// detail is fetched on demand from GET /api/sessions/{id}/mcp. Omitted when
// the session has no MCP servers.
MCP *MCPSummary `json:"mcp,omitempty"`
PlanMode string `json:"plan_mode,omitempty"`
PlanFile string `json:"plan_file,omitempty"`
ContextPercent int `json:"context_percent"` // 0-100, -1 if unknown
// ContextWindow is the model's usable input window in tokens — the
// denominator ContextPercent is measured against, and the scale CompactAt
// is expressed on, so a UI can show the limit as a percentage of the ring.
ContextWindow int `json:"context_window,omitempty"`
// CompactAt is the soft compaction threshold in tokens; 0 means the session
// compacts only when it approaches ContextWindow.
CompactAt int `json:"compact_at,omitempty"`
// CompactAtMin is the lowest threshold the engine honors, in tokens. A UI
// picking a threshold must not offer below it — the engine would raise the
// value and compact somewhere other than where the control says.
CompactAtMin int `json:"compact_at_min,omitempty"`
PermissionMode string `json:"permission_mode"` // "yolo", "ask", "auto"
CostUSD float64 `json:"cost_usd"` // accumulated session spend (main run + subagents)
Activity *attention.SessionActivity `json:"activity,omitempty"`
// CacheExpiresAt is when the Anthropic prompt cache for this session goes
// cold (last run + cache TTL). Zero/omitted when not applicable (no run yet,
// or a non-Anthropic model that doesn't use TTL-based prompt caching). The
// UI warns once this time has passed that a new message pays a cache write.
CacheExpiresAt time.Time `json:"cache_expires_at,omitzero"`
// RunStartedAt is when the in-progress run began; zero/omitted when idle.
// The UI anchors the activity-indicator elapsed counter to it so the counter
// stays correct across reconnects. Only meaningful while State is running or
// permission.
RunStartedAt time.Time `json:"run_started_at,omitzero"`
// BriefAttempting/BriefProgress are the cheap LLM-generated status prose:
// what the session is attempting and how it's going. Prose that can age;
// the actionable state is State/PermissionMode above (derived live), never
// baked into this prose. BriefUpdated is the freshness stamp. Empty until
// the first brief is generated. See brief.go.
BriefAttempting string `json:"brief_attempting,omitempty"`
BriefProgress string `json:"brief_progress,omitempty"`
BriefUpdated time.Time `json:"brief_updated,omitzero"`
}
SessionInfo is the public representation returned by List/Get endpoints.
type SessionState ¶
type SessionState string
SessionState describes the current state of a managed session.
const ( StateIdle SessionState = "idle" // waiting for user input StateRunning SessionState = "running" // agent is executing StatePermission SessionState = "permission" // blocked on permission approval StateError SessionState = "error" // last run errored (still usable) StateSaved SessionState = "saved" // on disk but not loaded into memory )
type StateChangeData ¶
StateChangeData is sent when the session state changes.
type SteerData ¶
type SteerData struct {
ID string `json:"id,omitempty"`
MsgID string `json:"msg_id,omitempty"`
Text string `json:"text"`
}
SteerData is sent when the user steers a running agent.
type SubagentCompleteData ¶
type SubagentCompleteData struct {
JobID string `json:"job_id"`
Task string `json:"task"`
Status string `json:"status"`
Text string `json:"text"`
}
SubagentCompleteData is sent when an async subagent finishes.
type SubagentCountData ¶
type SubagentCountData struct {
Count int `json:"count"`
}
SubagentCountData is sent when async subagent jobs start/finish.
type SubagentEndData ¶
type SubagentEndData struct {
JobID string `json:"job_id"`
Status string `json:"status"`
InputTokens int `json:"input_tokens"`
OutputTokens int `json:"output_tokens"`
CostUSD float64 `json:"cost_usd"`
}
SubagentEndData is sent when a subagent finishes, carrying its usage/cost.
type SubagentEventData ¶
SubagentEventData wraps a single translated bus event from a subagent child, namespaced by JobID. Event is produced by re-applying wsEventFromBus to the inner (already-typed) bus event — same shape as a top-level WS event.
type SubagentInitData ¶
type SubagentInitData struct {
JobID string `json:"job_id"`
OriginToolCallID string `json:"origin_tool_call_id,omitempty"`
Task string `json:"task"`
Model string `json:"model"`
Thinking string `json:"thinking"`
Status string `json:"status"`
Async bool `json:"async"`
Messages []core.AgentMessage `json:"messages"`
// StartedAtMs is the child's start time as epoch milliseconds (same
// encoding as InitData.RunStartedAtMs), so a reconnecting client resumes
// its live elapsed timer instead of restarting it. Omitted when unknown.
StartedAtMs int64 `json:"started_at_ms,omitempty"`
// InputTokens/OutputTokens/CostUSD are the child's accumulated usage/cost
// so far, so live cost doesn't reset to zero after a reconnect. Omitted
// (zero) until the child has closed at least one message.
InputTokens int `json:"input_tokens,omitempty"`
OutputTokens int `json:"output_tokens,omitempty"`
CostUSD float64 `json:"cost_usd,omitempty"`
// ContextPercent restores the child's own context reading after a
// reconnect (0-100, -1 unknown) — see SubagentUsageData.ContextPercent.
ContextPercent int `json:"context_percent"`
// AccentIndex is the subagent's stable per-session creation ordinal, used
// by the client to derive a deterministic accent color that survives
// reconnects (instead of one derived from array/map position).
AccentIndex int `json:"accent_index"`
}
SubagentInitData describes one live subagent job for reconnecting clients (WS init snapshot), so a client that connects mid-run sees the agent tray and its accumulated transcript instead of starting empty.
type SubagentStartData ¶
type SubagentStartData struct {
JobID string `json:"job_id"`
OriginToolCallID string `json:"origin_tool_call_id,omitempty"`
Task string `json:"task"`
Model string `json:"model"`
Thinking string `json:"thinking"`
Async bool `json:"async"`
// StartedAtMs is the child's start time as epoch milliseconds (same
// encoding as InitData.RunStartedAtMs), so the client can compute live
// elapsed time (now - StartedAtMs). Omitted when unknown.
StartedAtMs int64 `json:"started_at_ms,omitempty"`
// AccentIndex is the subagent's stable per-session creation ordinal (see
// SubagentInitData.AccentIndex). Never omitted: 0 is a valid ordinal
// (the session's first subagent).
AccentIndex int `json:"accent_index"`
}
SubagentStartData is sent when a subagent (sync or async) begins.
type SubagentSummary ¶
type SubagentSummary struct {
JobID string `json:"job_id"`
Task string `json:"task"`
Model string `json:"model,omitempty"`
Thinking string `json:"thinking,omitempty"`
Status string `json:"status"`
Async bool `json:"async"`
StartedAt time.Time `json:"started_at,omitempty"`
FinishedAt time.Time `json:"finished_at,omitempty"`
Source string `json:"source"`
// Usage/cost/context of the CHILD, so a client reopening a finished
// subagent shows the same figures its live view showed. ContextPercent is
// -1 when unknown; the tokens and cost are omitted when zero.
InputTokens int `json:"input_tokens,omitempty"`
OutputTokens int `json:"output_tokens,omitempty"`
CostUSD float64 `json:"cost_usd,omitempty"`
ContextPercent int `json:"context_percent"`
}
SubagentSummary describes a subagent available to an owner-authorized client, including the delegated task.
type SubagentUsageData ¶
type SubagentUsageData struct {
JobID string `json:"job_id"`
InputTokens int `json:"input_tokens"`
OutputTokens int `json:"output_tokens"`
CostUSD float64 `json:"cost_usd"`
// ContextPercent is how full the CHILD's own window is (0-100), or -1 when
// its model has no known window. Sent unconditionally (no omitempty): 0 is
// a real reading, and a client that fell back to the parent's percentage
// would be showing a number about a different agent.
ContextPercent int `json:"context_percent"`
}
SubagentUsageData carries a subagent's accumulated usage/cost while it is still running, emitted each time the child closes a message. It lets the client show live tokens/cost before the terminal subagent_end. The cost is computed the same way subagent_end computes its total, so the live value stays consistent with the final one.
type TasksUpdateData ¶
type TasksUpdateData struct {
Tasks any `json:"tasks"`
}
TasksUpdateData carries the full task list after a change.
type ToolCallDeltaData ¶
type ToolCallDeltaData struct {
ToolCallID string `json:"tool_call_id"`
Args map[string]any `json:"args"`
}
ToolCallDeltaData carries incrementally-parsed tool call arguments.
type ToolCallStreamingData ¶
type ToolCallStreamingData struct {
ToolCallID string `json:"tool_call_id"`
ToolName string `json:"tool_name"`
}
ToolStartData is sent when a tool execution begins. ToolCallStreamingData is sent when the LLM starts generating a tool call.
type ToolEndData ¶
type ToolEndData struct {
ToolCallID string `json:"tool_call_id"`
ToolName string `json:"tool_name"`
IsError bool `json:"is_error"`
Rejected bool `json:"rejected"`
Result string `json:"result"`
}
ToolEndData is sent when a tool execution completes.
type ToolStartData ¶
type ToolStartData struct {
ToolCallID string `json:"tool_call_id"`
ToolName string `json:"tool_name"`
Args map[string]any `json:"args"`
// StartLine is the real 1-based file line where an edit's oldText starts,
// so the frontend diff preview shows real line numbers before the tool
// result arrives. 0 when unknown (frontend numbers from 1). Edit tool only.
StartLine int `json:"start_line,omitempty"`
}
type ToolUpdateData ¶
ToolUpdateData carries streaming tool output.
Source Files
¶
- attachments.go
- attachments_download.go
- attachstore.go
- attachstore_unix.go
- attention.go
- autotitle.go
- brief.go
- cacheclock.go
- commands.go
- conversation.go
- device_auth.go
- device_lock_unix.go
- events.go
- files.go
- fs_complete.go
- generate.go
- guardian_ws.go
- manager.go
- mcp_toggle.go
- persist.go
- pulse_auth_api.go
- push.go
- realtime_client_secret.go
- route_auth.go
- scheduler.go
- sendfile.go
- server.go
- session_config.go
- session_lifecycle.go
- subagent_conversation.go
- ws.go