web

package
v1.10.10 Latest Latest
Warning

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

Go to latest
Published: Jul 18, 2026 License: MIT Imports: 39 Imported by: 0

Documentation

Overview

POST /api/sessions/{id}/worktree/finish — Web parity for the TUI's W/shift+w hotkey and the `agent-deck worktree finish` CLI. Closes the "Finish worktree" MISSING row in tests/web/PARITY_MATRIX.md (issue #1126).

Index

Constants

View Source
const (
	ErrCodeUnauthorized     = "UNAUTHORIZED"
	ErrCodeForbidden        = "MUTATIONS_DISABLED"
	ErrCodeCSRF             = "CROSS_ORIGIN_BLOCKED"
	ErrCodeNotFound         = "NOT_FOUND"
	ErrCodeBadRequest       = "INVALID_REQUEST"
	ErrCodeMethodNotAllowed = "METHOD_NOT_ALLOWED"
	ErrCodeRateLimited      = "RATE_LIMITED"
	ErrCodeInternalError    = "INTERNAL_ERROR"
	ErrCodeNotImplemented   = "NOT_IMPLEMENTED"
	ErrCodeReadOnly         = "READ_ONLY"
)

Error code constants for API error responses.

View Source
const (
	MenuItemTypeGroup   = "group"
	MenuItemTypeSession = "session"
)
View Source
const DefaultUndoWindow = 30 * time.Second

DefaultUndoWindow is the default Chrome-style undo grace period for session deletes (POST /api/sessions/undelete). Mirrors the TUI ctrl+z in-memory undo stack window.

Variables

View Source
var ErrNotAWorktree = errors.New("session is not in a worktree")

ErrNotAWorktree is returned by SessionMutator.FinishWorktree when the target session exists but is not in a git/jujutsu worktree (so there is nothing to merge or clean up). The handler maps this to 400. See issue #1126.

View Source
var ErrSessionNotFound = errors.New("session not found")

ErrSessionNotFound is returned by SessionMutator.FinishWorktree when the target session id does not resolve to a live instance. The handler maps this to 404. See issue #1126.

View Source
var ErrTmuxSessionNotFound = errors.New("tmux session not found")
View Source
var ErrUndoExpired = errors.New("undo window expired")

ErrUndoExpired is returned by SessionMutator.UndoDelete when the most recent delete is older than the configured undo window.

View Source
var ErrUndoNothing = errors.New("nothing to undo")

ErrUndoNothing is returned by SessionMutator.UndoDelete when the undo stack is empty.

Functions

func CheckBindSecurity added in v1.9.41

func CheckBindSecurity(listenAddr, token string, insecureBind bool) error

CheckBindSecurity refuses an unauthenticated bind to a non-loopback address.

Authentication is opt-in (an empty token authorizes every request), so a non-loopback bind with no token turns the box into an unauthenticated remote-code-execution surface (terminal-bridge keystroke injection + POST /api/sessions). When that combination is detected and the operator has not explicitly acknowledged it via insecureBind, this returns an actionable error so the server refuses to start. See /tmp/sec-web-REPORT.md finding #1.

func EnsurePushVAPIDKeys

func EnsurePushVAPIDKeys(profile, subject string) (publicKey, privateKey string, generated bool, err error)

EnsurePushVAPIDKeys returns a persisted VAPID keypair for the given profile. If no key file exists yet, it generates one via webpush.GenerateVAPIDKeys().

Types

type Assets added in v1.5.0

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

Assets manages the manifest-based mapping from logical source paths (e.g. "app/main.js") to hashed bundle output paths (e.g. "dist/main.a1b2c3.js"). In dev mode (no manifest present) or when the AGENTDECK_WEB_BUNDLE=0 env var is set, ResolveAsset falls back to serving the unbundled source file at /static/<logical>.

PERF-H: the manifest is emitted by bundle.go (go:generate entry point) which drives github.com/evanw/esbuild/pkg/api. The dev/prod fork keeps live-reload friendly while shipping hashed, bundled JS in production.

func LoadAssets added in v1.5.0

func LoadAssets(manifestPath string) (*Assets, error)

LoadAssets reads a manifest file from a filesystem path and returns an Assets instance. A missing manifest is NOT an error — the returned instance operates in dev mode (fallback to /static/<logical>). The AGENTDECK_WEB_BUNDLE=0 env var forces dev mode even if the manifest is present, which is the rollback lever.

func LoadAssetsFromFS added in v1.5.0

func LoadAssetsFromFS(fsys fs.FS, name string) (*Assets, error)

LoadAssetsFromFS reads a manifest from an io/fs.FS (e.g. the server's embed.FS). Used by the server at startup so the manifest can travel inside the binary. Missing file → dev mode.

func (*Assets) ResolveAsset added in v1.5.0

func (a *Assets) ResolveAsset(logical string) string

ResolveAsset maps a logical source path to the URL the browser should fetch. In dev mode: "/static/<logical>". In prod mode: "/static/<hashed>". Unknown logical paths fall back to the logical form so missing-asset regressions surface as 404s rather than silent manifest lookups.

func (*Assets) SubstitutePlaceholders added in v1.5.0

func (a *Assets) SubstitutePlaceholders(template string) string

SubstitutePlaceholders replaces every {{ASSET:logical}} token in the input string with the resolved URL. Used to fill index.html at serve time so the on-disk file stays hand-written (Pitfall 3 mitigation: dirty-tree check remains clean because the bundler never writes back to index.html).

type CommandCenterCompletion added in v1.9.68

type CommandCenterCompletion struct {
	ID     string `json:"id"`
	Title  string `json:"title"`
	Status string `json:"status"` // the new status (waiting|idle)
	At     string `json:"at"`
}

CommandCenterCompletion is a running→done/waiting transition for a session.

type CommandCenterConductor added in v1.9.68

type CommandCenterConductor struct {
	Name   string `json:"name"`   // short name, e.g. "agent-deck"
	Target string `json:"target"` // routing target, e.g. "conductor-agent-deck"
	// Status mirrors the conductor session's own status (running|waiting|idle
	// |error|...). "absent" when no conductor session exists for the group.
	Status string `json:"status"`
	// Substate is the honest-status v2 refinement of the conductor session.
	Substate string `json:"substate,omitempty"`
	// CurrentlyWorkingOn is plain-language, sourced from the conductor's
	// disk status artifact (status.json headline) or its latest prompt.
	CurrentlyWorkingOn string `json:"currentlyWorkingOn,omitempty"`
	// Sessions are the conductor's active children, error/stopped filtered out.
	Sessions []CommandCenterSession `json:"sessions"`
	Counts   CommandCenterCounts    `json:"counts"`
}

CommandCenterConductor is one project/domain row: a conductor plus the live session list it manages, filtered to active work only.

type CommandCenterCounts added in v1.9.68

type CommandCenterCounts struct {
	Running int `json:"running"`
	Waiting int `json:"waiting"`
	Idle    int `json:"idle"`
}

CommandCenterCounts is the per-conductor active-session tally (the noise the user explicitly does NOT want — error/stopped — is excluded by construction).

type CommandCenterDecision added in v1.9.68

type CommandCenterDecision struct {
	ID       string `json:"id"`       // e.g. "#1361"
	Question string `json:"question"` // the plain-language ask
	// Route is the conductor that owns the decision (best-effort; defaults to
	// the agent-deck conductor). Wires the two-way "answer the card" path.
	Route string `json:"route"`
}

CommandCenterDecision is one item from OPEN-ITEMS.md §D.

type CommandCenterSession added in v1.9.68

type CommandCenterSession struct {
	ID       string `json:"id"`
	Title    string `json:"title"`
	Status   string `json:"status"`
	Substate string `json:"substate,omitempty"`
	// WorkingOn is the latest prompt/activity hint, when available.
	WorkingOn string `json:"workingOn,omitempty"`
}

CommandCenterSession is one active child session in a conductor's group.

type CommandCenterSnapshot added in v1.9.68

type CommandCenterSnapshot struct {
	Profile     string `json:"profile"`
	GeneratedAt string `json:"generatedAt"`

	Conductors []CommandCenterConductor `json:"conductors"`
	Totals     CommandCenterTotals      `json:"totals"`

	// DecisionsWaiting is the ⭐ surface: rulings/reviews waiting on Ashesh,
	// parsed from OPEN-ITEMS.md §D. Empty when the file is absent.
	DecisionsWaiting []CommandCenterDecision `json:"decisionsWaiting"`

	// RecentlyCompleted carries the running→done/waiting transitions detected
	// since the previous snapshot, so the panel can fire "✅ X just finished"
	// notifications. It is diff-derived server-side and may be empty.
	RecentlyCompleted []CommandCenterCompletion `json:"recentlyCompleted"`

	// AskTargets is the server-authoritative allowlist of two-way input
	// targets (maestro + live conductor-* sessions). The panel populates its
	// target picker from this; the /ask handler re-validates against it.
	AskTargets []string `json:"askTargets"`
}

CommandCenterSnapshot is the see-everything payload rendered by the panel. Deliberately the same shape family as MenuSnapshot (profile + generatedAt + typed items) so the frontend's data conventions and SSE plumbing carry over.

type CommandCenterTotals added in v1.9.68

type CommandCenterTotals struct {
	Running int `json:"running"`
	Waiting int `json:"waiting"`
	Idle    int `json:"idle"`
}

CommandCenterTotals is the fleet-wide active tally.

type Config

type Config struct {
	ListenAddr   string
	Profile      string
	ReadOnly     bool
	WebMutations bool // When false, POST/PATCH/DELETE endpoints return 403
	Token        string
	// InsecureBind explicitly acknowledges binding a non-loopback address
	// with no auth token (an unauthenticated RCE surface). Without it the
	// server refuses to start in that configuration. See bind.go / report #1.
	InsecureBind        bool
	MenuData            MenuDataLoader
	PushVAPIDPublicKey  string
	PushVAPIDPrivateKey string
	PushVAPIDSubject    string
	PushTestInterval    time.Duration
}

Config defines runtime options for the web server.

type CreateGroupRequest added in v1.3.4

type CreateGroupRequest struct {
	Name       string `json:"name"`
	ParentPath string `json:"parentPath,omitempty"`
}

CreateGroupRequest is the body for POST /api/groups.

type CreateSessionRequest added in v1.3.4

type CreateSessionRequest struct {
	Title       string `json:"title"`
	Tool        string `json:"tool"`
	ProjectPath string `json:"projectPath"`
	GroupPath   string `json:"groupPath,omitempty"`
	ModelID     string `json:"modelId,omitempty"`
}

CreateSessionRequest is the body for POST /api/sessions.

type MCPCatalogEntry added in v1.9.25

type MCPCatalogEntry struct {
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	Transport   string `json:"transport,omitempty"`
	Command     string `json:"command,omitempty"`
	URL         string `json:"url,omitempty"`
}

MCPCatalogEntry describes one MCP available in the catalog (config.toml).

type MCPCatalogResponse added in v1.9.25

type MCPCatalogResponse struct {
	MCPs []MCPCatalogEntry `json:"mcps"`
}

MCPCatalogResponse is returned by GET /api/mcps.

type MCPManager added in v1.9.25

type MCPManager interface {
	ListCatalog() []MCPCatalogEntry
	ListAttached(projectPath string) (map[string][]string, error)
	Attach(projectPath, name, scope string) error
	Detach(projectPath, name, scope string) error
	Move(projectPath, name, fromScope, toScope string) error
}

MCPManager is the seam between web HTTP handlers and the on-disk MCP catalog + scope-specific config files. Tests inject a fake; production gets defaultMCPManager which delegates to internal/session.

func NewDefaultMCPManager added in v1.9.25

func NewDefaultMCPManager() MCPManager

NewDefaultMCPManager returns the production MCPManager that reads/writes real config files via internal/session helpers.

type MemoryMenuData

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

MemoryMenuData is an in-memory menu snapshot store used by web mode. It can optionally fall back to a loader (e.g. storage-backed) until the first in-memory snapshot is published.

func NewMemoryMenuData

func NewMemoryMenuData(fallback MenuDataLoader) *MemoryMenuData

NewMemoryMenuData creates an in-memory menu data store.

func (*MemoryMenuData) InvalidateCache added in v1.9.73

func (m *MemoryMenuData) InvalidateCache()

InvalidateCache clears the cached snapshot so the next call to LoadMenuSnapshot reloads from the fallback storage-backed loader. Used after mutations in headless (--no-tui) mode to ensure the menu reflects the current persisted state on the next fetch.

func (*MemoryMenuData) LoadArchivedMenuSnapshot added in v1.9.55

func (m *MemoryMenuData) LoadArchivedMenuSnapshot() (*MenuSnapshot, error)

LoadArchivedMenuSnapshot returns archived sessions from the storage fallback.

func (*MemoryMenuData) LoadMenuSnapshot

func (m *MemoryMenuData) LoadMenuSnapshot() (*MenuSnapshot, error)

LoadMenuSnapshot returns the latest in-memory snapshot. If no snapshot exists yet, it falls back once to the configured loader.

func (*MemoryMenuData) SetSnapshot

func (m *MemoryMenuData) SetSnapshot(snapshot *MenuSnapshot)

SetSnapshot replaces the stored menu snapshot.

func (*MemoryMenuData) UpdateSessionStates

func (m *MemoryMenuData) UpdateSessionStates(states map[string]MenuSessionState, generatedAt time.Time)

UpdateSessionStates updates status/tool fields in-place for existing sessions.

type MenuDataLoader interface {
	LoadMenuSnapshot() (*MenuSnapshot, error)
}

MenuDataLoader provides menu snapshots for web APIs and push notifications.

type MenuGroup struct {
	Name         string `json:"name"`
	Path         string `json:"path"`
	Expanded     bool   `json:"expanded"`
	Order        int    `json:"order"`
	SessionCount int    `json:"sessionCount"`
}

MenuGroup contains metadata for a group item.

type MenuItem struct {
	Index               int          `json:"index"`
	Type                string       `json:"type"`
	Level               int          `json:"level"`
	Path                string       `json:"path,omitempty"`
	Group               *MenuGroup   `json:"group,omitempty"`
	Session             *MenuSession `json:"session,omitempty"`
	IsLastInGroup       bool         `json:"isLastInGroup,omitempty"`
	IsSubSession        bool         `json:"isSubSession,omitempty"`
	IsLastSubSession    bool         `json:"isLastSubSession,omitempty"`
	ParentIsLastInGroup bool         `json:"parentIsLastInGroup,omitempty"`
}

MenuItem represents one row in the flattened navigation list.

type MenuSession struct {
	ID           string         `json:"id"`
	Title        string         `json:"title"`
	Tool         string         `json:"tool"`
	ModelID      string         `json:"modelId,omitempty"`
	Model        string         `json:"model,omitempty"`
	ModelVersion string         `json:"modelVersion,omitempty"`
	CanFork      bool           `json:"canFork"`
	Status       session.Status `json:"status"`
	// Substate is the additive Honest-Status-v2 refinement of Status
	// (e.g. "model-unavailable", "auth-401", "idle-at-empty-prompt"). It
	// explains WHY a session is in its coarse status so consumers like the
	// Command Center can surface model-unavailable/401 distinctly instead of
	// hiding them as plain "running". Empty when there is no refinement.
	Substate        string `json:"substate,omitempty"`
	GroupPath       string `json:"groupPath"`
	ProjectPath     string `json:"projectPath"`
	ParentSessionID string `json:"parentSessionId,omitempty"`
	Order           int    `json:"order"`
	TmuxSession     string `json:"tmuxSession,omitempty"`
	// TmuxSocketName is the tmux -L selector captured at session creation
	// (Instance.TmuxSocketName). Surfaced so the web PTY bridge can reach
	// sessions running on an isolated socket (issue #687, v1.7.50).
	TmuxSocketName string    `json:"tmuxSocketName,omitempty"`
	CreatedAt      time.Time `json:"createdAt"`
	LastAccessedAt time.Time `json:"lastAccessedAt,omitempty"`
	ArchivedAt     time.Time `json:"archivedAt,omitempty"`

	IsConductor bool `json:"isConductor,omitempty"`

	ClaudeSessionID   string `json:"claudeSessionId,omitempty"`
	GeminiSessionID   string `json:"geminiSessionId,omitempty"`
	GeminiModel       string `json:"geminiModel,omitempty"`
	GeminiYoloMode    *bool  `json:"geminiYoloMode,omitempty"`
	CodexSessionID    string `json:"codexSessionId,omitempty"`
	OpenCodeSessionID string `json:"opencodeSessionId,omitempty"`

	LatestPrompt string `json:"latestPrompt,omitempty"`
	Notes        string `json:"notes,omitempty"`

	Color string `json:"color,omitempty"`

	Command         string          `json:"command,omitempty"`
	Wrapper         string          `json:"wrapper,omitempty"`
	Channels        []string        `json:"channels,omitempty"`
	ExtraArgs       []string        `json:"extraArgs,omitempty"`
	ToolOptionsJSON json.RawMessage `json:"toolOptions,omitempty"`

	Sandbox          *session.SandboxConfig `json:"sandbox,omitempty"`
	SandboxContainer string                 `json:"sandboxContainer,omitempty"`
	SSHHost          string                 `json:"sshHost,omitempty"`
	SSHRemotePath    string                 `json:"sshRemotePath,omitempty"`

	MultiRepoEnabled   bool                        `json:"multiRepoEnabled,omitempty"`
	AdditionalPaths    []string                    `json:"additionalPaths,omitempty"`
	MultiRepoTempDir   string                      `json:"multiRepoTempDir,omitempty"`
	MultiRepoWorktrees []session.MultiRepoWorktree `json:"multiRepoWorktrees,omitempty"`

	WorktreePath     string `json:"worktreePath,omitempty"`
	WorktreeRepoRoot string `json:"worktreeRepoRoot,omitempty"`
	WorktreeBranch   string `json:"worktreeBranch,omitempty"`

	TitleLocked        bool `json:"titleLocked,omitempty"`
	NoTransitionNotify bool `json:"noTransitionNotify,omitempty"`

	LoadedMCPNames []string `json:"loadedMcpNames,omitempty"`

	// claude_analytics has no underlying struct on *Instance so the matrix
	// keeps it MISSING; only gemini is exposed today.
	GeminiAnalytics *session.GeminiSessionAnalytics `json:"geminiAnalytics,omitempty"`
}

MenuSession contains metadata for a session item.

type MenuSessionState struct {
	Status session.Status
	Tool   string
}

MenuSessionState is a lightweight status/tool update for one session.

type MenuSnapshot struct {
	Profile       string     `json:"profile"`
	GeneratedAt   time.Time  `json:"generatedAt"`
	TotalGroups   int        `json:"totalGroups"`
	TotalSessions int        `json:"totalSessions"`
	Items         []MenuItem `json:"items"`
}

MenuSnapshot is a flattened, ordered representation of session navigation data.

func BuildMenuSnapshot

func BuildMenuSnapshot(profile string, instances []*session.Instance, groupsData []*session.GroupData, generatedAt time.Time) *MenuSnapshot

BuildMenuSnapshot converts in-memory session/group state into a flattened web DTO.

type ProfilesResponse added in v1.3.4

type ProfilesResponse struct {
	Current  string   `json:"current"`
	Profiles []string `json:"profiles"`
}

ProfilesResponse is returned by GET /api/profiles.

type RenameGroupRequest added in v1.3.4

type RenameGroupRequest struct {
	Name string `json:"name"`
}

RenameGroupRequest is the body for PATCH /api/groups/:path.

type SSECostEvent added in v1.3.4

type SSECostEvent struct {
	EventType string  `json:"eventType"`
	SessionID string  `json:"sessionId"`
	Cost      float64 `json:"cost"`
}

SSECostEvent is emitted on cost:updated events.

type SSEDeleteEvent added in v1.3.4

type SSEDeleteEvent struct {
	EventType string `json:"eventType"`
	ID        string `json:"id"`
}

SSEDeleteEvent is emitted on session:deleted events.

type SSEGroupDeleteEvent added in v1.3.4

type SSEGroupDeleteEvent struct {
	EventType string `json:"eventType"`
	Path      string `json:"path"`
}

SSEGroupDeleteEvent is emitted on group:deleted events.

type SSEGroupEvent added in v1.3.4

type SSEGroupEvent struct {
	EventType string     `json:"eventType"`
	Group     *MenuGroup `json:"group"`
}

SSEGroupEvent is emitted on group:created and group:updated events.

type SSESessionEvent added in v1.3.4

type SSESessionEvent struct {
	EventType string       `json:"eventType"`
	Session   *MenuSession `json:"session"`
}

SSESessionEvent is emitted on session:created and session:updated events.

type Server

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

Server wraps an HTTP server for Agent Deck web mode.

func NewServer

func NewServer(cfg Config) *Server

NewServer creates a new web server with base routes and middleware.

func (*Server) Addr

func (s *Server) Addr() string

Addr returns the listen address.

func (*Server) Handler

func (s *Server) Handler() http.Handler

Handler returns the configured HTTP handler (used by tests).

func (*Server) HasMCPManager added in v1.9.25

func (s *Server) HasMCPManager() bool

HasMCPManager reports whether the MCP manager seam is wired.

func (*Server) HasMutator added in v1.7.75

func (s *Server) HasMutator() bool

HasMutator reports whether a SessionMutator has been wired. Mutating endpoints (POST/PATCH/DELETE) return 503 NOT_IMPLEMENTED when this is false, even if WebMutations is true. Exposed for regression tests on the `agent-deck web` bootstrap path.

func (*Server) SetCostStore added in v0.26.4

func (s *Server) SetCostStore(store *costs.Store)

func (*Server) SetMCPManager added in v1.9.25

func (s *Server) SetMCPManager(m MCPManager)

SetMCPManager wires the MCP manager implementation (production or test).

func (*Server) SetMutator added in v1.3.4

func (s *Server) SetMutator(m SessionMutator)

SetMutator injects the session mutator implementation (typically *ui.WebMutator).

func (*Server) SetSkillsService added in v1.9.25

func (s *Server) SetSkillsService(svc SkillsService)

SetSkillsService injects an alternate SkillsService (used by tests). When nil, handlers fall back to defaultSkillsService.

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context) error

Shutdown gracefully stops the server.

func (*Server) Start

func (s *Server) Start() error

Start starts the HTTP server and blocks until shutdown or error. Returns nil on graceful shutdown.

func (*Server) String

func (s *Server) String() string

type SessionActionResponse added in v1.3.4

type SessionActionResponse struct {
	SessionID string         `json:"sessionId"`
	Status    session.Status `json:"status"`
}

SessionActionResponse is returned by session action endpoints.

type SessionChildNode added in v1.9.26

type SessionChildNode struct {
	*MenuSession
	Children []*SessionChildNode `json:"children"`
}

SessionChildNode is one node in the children-tree response. It inlines the standard MenuSession fields and adds a recursive `children` array. `children` is always non-nil — even leaves render as `"children":[]` so JS consumers don't have to null-check.

type SessionChildrenResponse added in v1.9.26

type SessionChildrenResponse struct {
	SessionID string              `json:"sessionId"`
	Children  []*SessionChildNode `json:"children"`
}

SessionChildrenResponse is the body of GET /api/sessions/{id}/children.

type SessionDataService

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

SessionDataService loads profile session data and transforms it into web-friendly DTOs.

func NewSessionDataService

func NewSessionDataService(profile string) *SessionDataService

NewSessionDataService creates a SessionDataService for a profile.

func (*SessionDataService) LoadArchivedMenuSnapshot added in v1.9.55

func (s *SessionDataService) LoadArchivedMenuSnapshot() (*MenuSnapshot, error)

LoadArchivedMenuSnapshot returns a menu containing only archived sessions.

func (*SessionDataService) LoadMenuSnapshot

func (s *SessionDataService) LoadMenuSnapshot() (*MenuSnapshot, error)

LoadMenuSnapshot loads sessions/groups and returns a deterministic flattened menu DTO.

func (*SessionDataService) Profile

func (s *SessionDataService) Profile() string

Profile returns the effective profile this service reads from.

type SessionMCPsResponse added in v1.9.25

type SessionMCPsResponse struct {
	SessionID string   `json:"sessionId"`
	Local     []string `json:"local"`
	Global    []string `json:"global"`
	User      []string `json:"user"`
}

SessionMCPsResponse is returned by GET /api/sessions/{id}/mcps.

type SessionMutator added in v1.3.4

type SessionMutator interface {
	CreateSession(title, tool, projectPath, groupPath, modelID string) (string, error)
	StartSession(sessionID string) error
	StopSession(sessionID string) error
	RestartSession(sessionID string) error
	DeleteSession(sessionID string) error
	// CloseSession stops the session process while keeping its metadata
	// in storage (TUI Shift+D — non-destructive close).
	CloseSession(sessionID string) error
	ArchiveSession(sessionID string) error
	UnarchiveSession(sessionID string) error
	ForkSession(sessionID string) (string, error)
	// UndoDelete restores the most-recently deleted session if it was
	// deleted within the implementation's undo window. Returns the
	// restored session id. Implementations should return ErrUndoNothing
	// when the stack is empty and ErrUndoExpired when the most recent
	// entry is older than the window — the handler maps both to 404.
	UndoDelete() (string, error)
	// UpdateSession applies one or more field edits to a session. updates maps
	// session.Field* constants (raw strings — see internal/session/mutators.go)
	// to their string-encoded new values; bools are "true"/"false". Returns the
	// list of fields that actually changed (a no-op subset is permitted; only
	// fields whose new value differs from the stored value are reported) and
	// whether any updated field requires a restart to take effect. Validation
	// errors (unknown field, invalid value) leave the session unchanged.
	UpdateSession(sessionID string, updates map[string]string) (updatedFields []string, restartRequired bool, err error)
	CreateGroup(name, parentPath string) (string, error)
	RenameGroup(groupPath, newName string) error
	DeleteGroup(groupPath string) error
	// FinishWorktree merges (or skips), removes the worktree, optionally
	// deletes the source branch, kills the tmux session, and removes the
	// session from storage. Mirrors the TUI W/shift+w hotkey and the
	// `agent-deck worktree finish` CLI. Returns ErrSessionNotFound when
	// the id doesn't resolve and ErrNotAWorktree when the session exists
	// but lacks worktree metadata. See issue #1126.
	FinishWorktree(sessionID string, opts WorktreeFinishOptions) (WorktreeFinishResult, error)
}

SessionMutator is implemented by internal/ui.WebMutator and injected at startup. It bridges web HTTP handlers to the TUI session/group management methods.

type SettingsResponse added in v1.3.4

type SettingsResponse struct {
	Profile      string `json:"profile"`
	ReadOnly     bool   `json:"readOnly"`
	WebMutations bool   `json:"webMutations"`
	Version      string `json:"version"`

	// show_only_installed_tools filter (issue #1259). ToolFilter reports the
	// flag is on; VisibleTools lists the tool names that resolved on PATH (the
	// web dialog intersects its static list against this); ToolFilterFallback
	// reports the empty-fallback so the dialog shows a "showing all" hint. With
	// the flag off ToolFilter is false and the dialog ignores the other fields.
	ToolFilter         bool     `json:"toolFilter"`
	VisibleTools       []string `json:"visibleTools"`
	ToolFilterFallback bool     `json:"toolFilterFallback"`

	// hidden_tools denylist from [ui]. HiddenTools is the configured list;
	// PickerTools is the ordered new-session picker after hidden_tools and
	// show_only_installed_tools ("" mapped to "shell" for web).
	HiddenTools []string `json:"hiddenTools"`
	PickerTools []string `json:"pickerTools"`
}

SettingsResponse is returned by GET /api/settings.

type SkillsService added in v1.9.25

type SkillsService interface {
	ListCatalog() ([]session.SkillCandidate, error)
	ListAttached(projectPath string) ([]session.ProjectSkillAttachment, error)
	Attach(projectPath, tool, skillRef, source string) (*session.ProjectSkillAttachment, error)
	Detach(projectPath, skillRef, source string) (*session.ProjectSkillAttachment, error)
}

SkillsService is the seam between web HTTP handlers and the on-disk skill catalog/attachment functions in internal/session. Tests inject a fake; production gets defaultSkillsService which delegates straight to the session package.

type UpdateSessionRequest added in v1.9.47

type UpdateSessionRequest struct {
	Title           *string `json:"title,omitempty"`
	Notes           *string `json:"notes,omitempty"`
	Color           *string `json:"color,omitempty"`
	Tool            *string `json:"tool,omitempty"`
	ExtraArgs       *string `json:"extraArgs,omitempty"`
	Plugins         *string `json:"plugins,omitempty"`
	Channels        *string `json:"channels,omitempty"`
	SkipPermissions *bool   `json:"skipPermissions,omitempty"`
	AutoMode        *bool   `json:"autoMode,omitempty"`
}

UpdateSessionRequest is the body for PATCH /api/sessions/{id}. Every field is optional; only the fields present in the request body are updated. Pointer types let the handler distinguish "not supplied" from "set to zero value" — important for booleans, where a missing field must not silently clear the flag.

Field names mirror session.Field* constants so the handler can dispatch directly through session.SetField without a translation table.

type UpdateSessionResponse added in v1.9.47

type UpdateSessionResponse struct {
	SessionID       string   `json:"sessionId"`
	UpdatedFields   []string `json:"updatedFields"`
	RestartRequired bool     `json:"restartRequired"`
}

UpdateSessionResponse confirms a PATCH succeeded. RestartRequired is true when any updated field only takes effect on next launch (tool, extra-args, plugins, skip-permissions, auto-mode). Clients use it to prompt before/after issuing a separate POST .../restart.

type WorktreeFinishOptions added in v1.9.30

type WorktreeFinishOptions struct {
	// Into is the target branch to merge the worktree branch into. When
	// empty the backend's default branch is used (matches the
	// `agent-deck worktree finish --into` flag).
	Into string
	// NoMerge skips the merge step (mirrors --no-merge). The branch is
	// still removed (unless KeepBranch) and the worktree torn down.
	NoMerge bool
	// KeepBranch leaves the source branch in place after finishing
	// (mirrors --keep-branch). Useful when the branch already lives on a
	// remote PR.
	KeepBranch bool
	// Force skips the dirty-worktree safety check and forces branch
	// deletion even if the merge fast-forward didn't succeed.
	Force bool
}

WorktreeFinishOptions configures a SessionMutator.FinishWorktree call. All fields are optional; the zero value asks the implementation to auto-detect the target branch, perform the merge, delete the source branch, and refuse if the worktree is dirty.

type WorktreeFinishRequest added in v1.9.30

type WorktreeFinishRequest struct {
	Into       string `json:"into,omitempty"`
	NoMerge    bool   `json:"noMerge,omitempty"`
	KeepBranch bool   `json:"keepBranch,omitempty"`
	Force      bool   `json:"force,omitempty"`
}

WorktreeFinishRequest is the body for POST /api/sessions/{id}/worktree/finish. All fields are optional. Mirrors `agent-deck worktree finish` CLI flags. See issue #1126.

type WorktreeFinishResponse added in v1.9.30

type WorktreeFinishResponse struct {
	SessionID     string `json:"sessionId"`
	Branch        string `json:"branch"`
	MergedInto    string `json:"mergedInto,omitempty"`
	Merged        bool   `json:"merged"`
	BranchDeleted bool   `json:"branchDeleted"`
}

WorktreeFinishResponse is returned by POST /api/sessions/{id}/worktree/finish.

type WorktreeFinishResult added in v1.9.30

type WorktreeFinishResult struct {
	SessionID     string
	Branch        string
	MergedInto    string
	Merged        bool
	BranchDeleted bool
}

WorktreeFinishResult is what SessionMutator.FinishWorktree returns on success. Mirrors the JSON-output payload of `agent-deck worktree finish --json`.

Jump to

Keyboard shortcuts

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