Documentation
¶
Overview ¶
Package session manages on-disk session entries at `<BaseDir>/sessions/<id>/`. A session is one Slack thread or one UI conversation: routing key, status, agent registry, log files, and an optional reference to a project whose folder is the agent cwd.
Sessions own no project files of their own — a project is a shared bundle (see internal/agents/project) whose folder the pool resolves to a cwd at spawn time. See agents-design.md §0.2 for the refactor that removed the per-session git worktree, and the project design (internal/planning/archive/project/design.md) for the Workspace→Project rename.
Files in this package:
- session.go — Meta + lifecycle (Create/Load/Save/Delete/SetProject)
- agents.go — per-session AgentEntry + Add/SetActive
Index ¶
- func AbandonGoal(layout agentconfig.Layout, id, note string) error
- func AddAgent(layout config.Layout, id, name, provider string) error
- func CompleteGoal(layout agentconfig.Layout, id, note string) error
- func Delete(_ context.Context, layout config.Layout, id string) error
- func HasOpenGoal(layout agentconfig.Layout, id string) bool
- func HasOpenGoalDir(sessionDir string) bool
- func List(layout config.Layout) ([]string, error)
- func OpenGoal(layout agentconfig.Layout, id, goal, note string) error
- func SaveAgents(layout config.Layout, id string, agents []AgentEntry) error
- func SaveMeta(layout config.Layout, id string, meta Meta) error
- func SetActiveAgent(layout config.Layout, id, name string) error
- func SetCLISessionID(layout config.Layout, id, name, cliID string) error
- func SetMaxTurns(layout config.Layout, id, name string, maxTurns int) error
- func SetModelID(layout config.Layout, id, name, modelID string) error
- func SetProject(_ context.Context, layout config.Layout, id, newProjectID string) error
- func SetThinkingTokens(layout config.Layout, id, name, v string) error
- type AgentEntry
- type CreateOptions
- type Goal
- type GoalStatus
- type Meta
- type Origin
- type Session
- type Status
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AbandonGoal ¶ added in v0.35.2
func AbandonGoal(layout agentconfig.Layout, id, note string) error
AbandonGoal marks the open latch abandoned. No open goal → no-op.
func AddAgent ¶
AddAgent appends a new agent entry. Errors on duplicate name within the same session.
func CompleteGoal ¶ added in v0.35.2
func CompleteGoal(layout agentconfig.Layout, id, note string) error
CompleteGoal marks the open latch done. No open goal → no-op.
func Delete ¶
Delete removes the session folder. The project it points at is left untouched — projects are shared, so deleting a session must not delete its files.
func HasOpenGoal ¶ added in v0.35.2
func HasOpenGoal(layout agentconfig.Layout, id string) bool
HasOpenGoal reports whether the session has an open goal latch.
func HasOpenGoalDir ¶ added in v0.35.2
HasOpenGoalDir is the engine-side form of HasOpenGoal.
func OpenGoal ¶ added in v0.35.2
func OpenGoal(layout agentconfig.Layout, id, goal, note string) error
OpenGoal writes/replaces an open latch.
func SaveAgents ¶
func SaveAgents(layout config.Layout, id string, agents []AgentEntry) error
SaveAgents atomically rewrites sessions/<id>/agents.json. nil becomes an empty array on disk so consumers don't have to handle `null`.
func SetActiveAgent ¶
SetActiveAgent updates meta.json's active_agent field. The named agent must already exist in agents.json.
func SetCLISessionID ¶ added in v0.15.5
SetCLISessionID writes (or clears, with "") the CLI resume id on the agent entry. No-op when the entry doesn't exist.
func SetMaxTurns ¶ added in v0.15.5
SetMaxTurns persists the per-spawn turn cap on the agent entry, creating it if missing. 0 = unlimited (provider default).
func SetModelID ¶ added in v0.34.0
SetModelID persists the pinned model id on the agent entry, creating it if missing. Empty = unset (the active provider's own default applies).
func SetProject ¶ added in v0.14.21
SetProject changes the project a session points at. No filesystem work — the next agent spawn will resolve the new project's folder as cwd. Conversation, agent registry, and logs are preserved. Empty newProjectID unscopes the session.
func SetThinkingTokens ¶ added in v0.18.7
SetThinkingTokens persists the resolved MAX_THINKING_TOKENS env value on the agent entry, creating it if missing. Empty = unset (provider default, thinking on); "0" = disabled; "<n>" = budget. Always persisted (including "") so switching a reused session back to full thinking clears a prior value.
Types ¶
type AgentEntry ¶
type AgentEntry struct {
Name string `json:"name"`
Provider string `json:"provider"`
CLISessionID string `json:"cli_session_id,omitempty"`
Status string `json:"status"`
CreatedAt time.Time `json:"created_at"`
LastActive time.Time `json:"last_active,omitempty"`
ProviderSessions map[string]string `json:"provider_sessions,omitempty"`
// MaxTurns caps agentic turns on the next spawn (--max-turns).
// 0 = unlimited (provider default). Set per workflow agent node.
MaxTurns int `json:"max_turns,omitempty"`
// ThinkingTokens is the resolved MAX_THINKING_TOKENS env value applied on
// the next spawn (claude). Empty = unset (provider default, thinking on);
// "0" = disabled; "<n>" = budget. Set per workflow agent node from its
// thinking + max_thinking_tokens inputs.
ThinkingTokens string `json:"thinking_tokens,omitempty"`
// ModelID pins a specific model id this agent uses on its next spawn,
// scoped to whichever provider Provider currently points at. Empty =
// use that provider instance's own default-model resolution. Currently
// only meaningful for wick (WickModel.ID); other provider types ignore
// it. Cleared on switching to a provider type that doesn't recognize
// it, so a later switch back doesn't resurrect a stale/foreign pin.
ModelID string `json:"model_id,omitempty"`
}
AgentEntry is one row in sessions/<id>/agents.json. CLISessionID is the resume key — wick captures it from the first stream-json event emitted by the CLI and persists it so subsequent spawns can pass `--resume <id>`. See agents-design.md §5.2.
ProviderSessions maps "type/name" provider keys to their last-known CLI session ID. When switching providers, the outgoing resume ID is saved here so switching back can resume the old conversation.
type CreateOptions ¶
type CreateOptions struct {
ID string
ProjectID string
Origin Origin
ChannelID string
// Preset is the preset name to associate with this session.
// Stored in meta.json; factory loads content from presets/<name>/agent.md on spawn.
Preset string
// UserID is the wick user who is creating this session. Stored in
// meta.json for ownership checks in MCP handlers.
UserID string
}
CreateOptions describes a new session. ProjectID is optional — a session may be created without one, in which case the pool falls back to the tools-config default project (or a per-session temp dir if no default is set).
type Goal ¶ added in v0.35.2
type Goal struct {
Goal string `json:"goal"`
Status GoalStatus `json:"status"`
Note string `json:"note,omitempty"`
UpdatedAt time.Time `json:"updated_at"`
}
Goal is the on-disk record.
func LoadGoal ¶ added in v0.35.2
func LoadGoal(layout agentconfig.Layout, id string) (*Goal, error)
LoadGoal reads the session's goal latch. Missing file → (nil, nil).
func LoadGoalDir ¶ added in v0.35.2
LoadGoalDir reads goal.json from an absolute session directory (engine path — it already holds SessionDir, not layout+id).
type GoalStatus ¶ added in v0.35.2
type GoalStatus string
GoalStatus is the lifecycle of one session goal.
const ( GoalOpen GoalStatus = "open" GoalDone GoalStatus = "done" GoalAbandoned GoalStatus = "abandoned" )
type Meta ¶
type Meta struct {
// ProjectID references the project this session belongs to. Empty =
// unscoped (pool falls back to the tools-config default project).
ProjectID string `json:"project_id,omitempty"`
Origin Origin `json:"origin"`
ChannelID string `json:"channel_id,omitempty"`
ActiveAgent string `json:"active_agent,omitempty"`
Status Status `json:"status"`
CreatedAt time.Time `json:"created_at"`
LastActive time.Time `json:"last_active"`
PendingInput []string `json:"pending_input,omitempty"`
// Label is the session title shown in the sidebar. By default it is
// the first user message truncated to 60 runes (see
// pool.setLabelIfEmpty), cached here so sidebar rendering never needs
// to open conversation.jsonl. Once a human or the agent sets an
// explicit title (TitleCustom=true) the auto-derived label no longer
// overwrites it.
Label string `json:"label,omitempty"`
// TitleCustom marks Label as an explicit title set by a human or the
// agent (via the wick_set_title MCP tool), as opposed to the
// auto-derived first-message label. When true, the first-user-message
// auto-label is skipped so it never clobbers the chosen title.
TitleCustom bool `json:"title_custom,omitempty"`
// Preset is the name of the preset active for this session.
// Factory reads the preset content from presets/<name>/agent.md on
// every spawn so edits to the preset take effect on next respawn.
Preset string `json:"preset,omitempty"`
// Subscribers is the list of user IDs that opted in to receive
// browser push notifications for this session's lifecycle
// transitions (queue → working → idle). Persisted in meta.json so
// the subscription survives wick restart. Sessions are shared
// across users (anyone can open them) but pushes target only the
// IDs in this list — no auto-subscribe on session create.
Subscribers []string `json:"subscribers,omitempty"`
// UserID is the wick user ID that created this session. Empty for
// legacy sessions created before ownership tracking was added.
// When non-empty, only the owning user (or app owner) may access it.
UserID string `json:"user_id,omitempty"`
// AutoReply marks a Slack channel thread as auto-reply: while true,
// replies in the thread are dispatched to the agent without an
// @mention. Set when the thread is created (the bot also drops a 🤖
// marker on the parent) and toggled by adding/removing that marker.
// Persisted here so the switch survives a wick restart even though
// the channel's in-memory state is lost. Only meaningful for Slack
// channel sessions; absent/false everywhere else.
AutoReply bool `json:"auto_reply,omitempty"`
}
Meta is the persisted-on-disk shape of a session. PendingInput is the message buffer that survives wick restart so a session that was queued at shutdown gets its messages drained on next boot.
func (*Meta) AddSubscriber ¶ added in v0.15.0
AddSubscriber appends userID to Subscribers if not already present. Returns true if the list changed (i.e. caller should persist Meta).
func (*Meta) IsSubscribed ¶ added in v0.15.0
IsSubscribed returns true when userID has opted in to receive lifecycle push notifications for this session.
func (*Meta) RemoveSubscriber ¶ added in v0.15.0
RemoveSubscriber drops userID from Subscribers. Returns true if the list changed.
type Origin ¶
type Origin string
Origin identifies where the session was first created from. Slack threads use thread_ts as the session ID; UI/API sessions use a UUID generated by wick.
type Session ¶
type Session struct {
ID string `json:"id"`
Meta Meta `json:"meta"`
Agents []AgentEntry `json:"agents"`
}
Session is the in-memory view: ID + meta + agent registry. Mirrors the trio of files at sessions/<id>/.