conversation

package
v0.6.8 Latest Latest
Warning

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

Go to latest
Published: Aug 9, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Index

Constants

View Source
const (
	MaxTitleRunes = 120
	ScopeChat     = "chat"
	ScopeProject  = "project"
	KindScratch   = "scratch"
	KindFolder    = "folder"
)

Variables

View Source
var ErrApprovalPending = errors.New("session: approval is pending")

ErrApprovalPending rejects new queued work while a tool permission decision is still waiting for the viewer.

View Source
var ErrImagesUnsupported = errors.New("session: selected model does not support images")

ErrImagesUnsupported rejects image attachments before a run is reserved when the session's selected model accepts text only.

View Source
var ErrInvalidPermissionMode = errors.New("session: invalid permission mode")

ErrInvalidPermissionMode reports a mode outside the product's supported session permission presets.

View Source
var ErrInvalidSessionScope = errors.New("session: invalid session scope")

ErrInvalidSessionScope reports a create request that is neither a standalone chat nor a project-backed conversation.

View Source
var ErrManagerClosed = errors.New("session: conversation manager is closed")

ErrManagerClosed rejects new work after product shutdown has started.

View Source
var ErrQuestionPending = errors.New("session: a question is pending")

ErrQuestionPending rejects new queued work while the agent's question is still waiting for the viewer to answer it.

View Source
var ErrQueuedMessageInFlight = errors.New("session: queued message is already being processed")

ErrQueuedMessageInFlight reports a message that already left the agent queue and can no longer be withdrawn.

View Source
var ErrQueuedMessageNotFound = errors.New("session: queued message not found")

ErrQueuedMessageNotFound reports an unknown browser-facing queue ID.

View Source
var ErrSessionActive = errors.New("session: session is running or waiting for approval")

ErrSessionActive prevents deleting a conversation while its run or approval gate still owns live resources.

View Source
var ErrSessionNotRunning = errors.New("session: session is not running")

ErrSessionNotRunning rejects a queued message after its run has ended.

Functions

func NewID

func NewID() string

NewID returns an identifier for a session or a queued message.

Types

type Delivery

type Delivery string
const (
	DeliverySteer    Delivery = "steer"
	DeliveryFollowUp Delivery = "followup"
)

type Event

type Event interface{ Event() }

Session state changes are described here as plain facts — a message was queued, a title changed — with no knowledge of how they reach a viewer. Projecting them onto a wire format belongs to whoever is delivering them.

type Manager

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

Manager owns every conversation across the registered workspaces. Metadata is kept in indexes while each transcript stays separate. Lock ordering: mu is always taken before the workspace registry's own lock. The registry never calls back into this package, so that ordering holds simply by never taking mu inside a registry call.

func NewManager

func NewManager(ctx context.Context, opts Options) (*Manager, error)

NewManager restores and validates the session index. Restored transcripts, transports, and engine sessions stay unloaded until the conversation is first opened. The ledger and registry are passed in because the HTTP layer also serves them directly.

func (*Manager) Abort

func (m *Manager) Abort(id string) error

Abort cancels the active run, if any.

func (*Manager) Close

func (m *Manager) Close()

Close stops accepting new work, cancels active runs and title generation, then releases every session-owned process. It is safe to call repeatedly.

func (*Manager) Compact

func (m *Manager) Compact(
	ctx context.Context,
	id string,
	instructions string,
) (engine.CompactionResult, error)

Compact reserves an idle session and performs one explicit context compaction. It blocks until the summary is durable.

func (*Manager) Create

func (m *Manager) Create(
	title, workspacePath, scope string,
	model llm.Model,
	thinking llm.ModelThinkingLevel,
	permissionMode permission.Mode,
) (Summary, error)

Create adds an empty, independently persisted conversation. Chat sessions receive an isolated, manager-owned workspace; project sessions use the caller-selected folder and never fall back to the process working directory.

func (*Manager) Delete

func (m *Manager) Delete(id string) error

Delete permanently removes one idle conversation and its persisted files. Files are staged under temporary names before the index is changed, so an index write failure can restore the conversation without data loss.

func (*Manager) DequeueMessage

func (m *Manager) DequeueMessage(sessionID, messageID string) error

DequeueMessage withdraws one queued message by its browser-facing ID.

func (*Manager) EnsureLoaded added in v0.6.2

func (m *Manager) EnsureLoaded(id string) error

EnsureLoaded opens one restored conversation on first use. Loading is serialized by the manager lock so concurrent history and SSE requests share one engine session and transport.

func (*Manager) List

func (m *Manager) List() []Summary

List returns newest-active first and samples each session's live state.

func (*Manager) QueueMessage

func (m *Manager) QueueMessage(id string, message QueuedMessage) error

QueueMessage submits one steer or follow-up to a running conversation.

func (*Manager) ReleaseIfIdle added in v0.6.8

func (m *Manager) ReleaseIfIdle(id string) bool

ReleaseIfIdle unloads an engine-backed runtime once its delivery layer can atomically prove that no viewer is attached. The durable record remains in the manager so a later history or SSE request restores the session lazily. Active runs, viewer decisions, title generation, and live background tasks pin the runtime because closing any of them would change user-visible work.

func (*Manager) Rename

func (m *Manager) Rename(id, customTitle string) (Summary, error)

Rename sets a user-defined custom title on the session. An empty title clears it so the display falls back to the AI or prompt-derived title.

func (*Manager) Snapshot

func (m *Manager) Snapshot(id string) (Snapshot, error)

Snapshot returns the current client-readable state without exposing the runtime that owns the engine session.

func (*Manager) StartPromptWithFiles

func (m *Manager) StartPromptWithFiles(
	id string,
	prompt string,
	files []engine.AttachedFile,
	images ...llm.ImageContent,
) error

StartPromptWithFiles starts a prompt with validated text-file attachments.

func (*Manager) StopTask

func (m *Manager) StopTask(sessionID, taskID string) error

StopTask terminates one background task owned by the conversation.

func (*Manager) TaskOutput

func (m *Manager) TaskOutput(sessionID, taskID string) (engine.TaskOutput, error)

TaskOutput returns a bounded tail of one conversation task's logs.

func (*Manager) UpdatePermissionMode

func (m *Manager) UpdatePermissionMode(id string, mode permission.Mode) (Summary, error)

UpdatePermissionMode changes the baseline tool policy used by subsequent calls and persists it with the conversation.

func (*Manager) UpdateSettings

func (m *Manager) UpdateSettings(
	id string,
	model llm.Model,
	thinking llm.ModelThinkingLevel,
) (Summary, error)

UpdateSettings changes the model and reasoning effort used by the session's next prompt and persists the choice with that conversation.

func (*Manager) WorkspacePath

func (m *Manager) WorkspacePath(id string) (string, error)

WorkspacePath returns the tool root owned by one conversation.

type MessageAccepted

type MessageAccepted struct {
	ID       string
	Text     string
	Images   []llm.ImageContent
	Files    []engine.File
	Delivery Delivery
	Queued   bool
}

MessageAccepted reports a user message the server has taken responsibility for. Queued distinguishes one waiting behind a running turn from one the run has already picked up.

func (MessageAccepted) Event

func (MessageAccepted) Event()

type MessageCancelled

type MessageCancelled struct{ ID string }

MessageCancelled reports a queued message dropped because its run ended.

func (MessageCancelled) Event

func (MessageCancelled) Event()

type MessageDequeued

type MessageDequeued struct{ ID string }

MessageDequeued reports a queued message the user withdrew before it ran.

func (MessageDequeued) Event

func (MessageDequeued) Event()

type NewTransport

type NewTransport func(sessionID string) Transport

NewTransport builds the delivery link for one opened session. Manager calls it once when the session runtime loads and owns closing the returned transport.

type Options

type Options struct {
	DataDir      string
	Usage        *usage.Store
	Workspaces   *workspace.Registry
	NewTransport NewTransport
}

Options supplies the product services and storage root owned by a Manager.

type QueuedMessage

type QueuedMessage struct {
	ID       string
	Delivery Delivery
	Text     string
	Images   []llm.ImageContent
	Files    []engine.AttachedFile
}

type RunFailed

type RunFailed struct{ Text string }

RunFailed reports an asynchronous prompt failure to the viewer.

func (RunFailed) Event

func (RunFailed) Event()

type Snapshot

type Snapshot struct {
	History      []engine.HistoryItem
	Queue        []Event
	ContextUsage engine.ContextUsage
	Tasks        []engine.BackgroundTask
	Running      bool
	Title        string
}

Snapshot is the complete client-readable state of one conversation.

type Summary

type Summary struct {
	ID             string                 `json:"id"`
	Title          string                 `json:"title"`
	WorkspacePath  string                 `json:"workspacePath"`
	WorkspaceName  string                 `json:"workspaceName"`
	Scope          string                 `json:"scope"`
	WorkspaceKind  string                 `json:"workspaceKind"`
	CreatedAt      time.Time              `json:"createdAt"`
	UpdatedAt      time.Time              `json:"updatedAt"`
	Running        bool                   `json:"running"`
	HasApproval    bool                   `json:"hasApproval"`
	HasQuestion    bool                   `json:"hasQuestion"`
	ModelProvider  string                 `json:"modelProvider"`
	ModelID        string                 `json:"modelId"`
	ModelName      string                 `json:"modelName"`
	ThinkingLevel  llm.ModelThinkingLevel `json:"thinkingLevel"`
	PermissionMode permission.Mode        `json:"permissionMode"`
}

Summary is the browser-facing metadata for one independent coding conversation. Live state is sampled when the list is requested.

type TitleChanged

type TitleChanged struct{ Title string }

TitleChanged reports the session's current display title.

func (TitleChanged) Event

func (TitleChanged) Event()

type Transport

type Transport interface {
	// Publish delivers a state change this session raised.
	Publish(Event)
	// PublishAgent delivers an event raised by the agent underneath.
	PublishAgent(engine.Event)
	// Decide gates one tool call, blocking until answered or cancelled.
	Decide(context.Context, permission.ApprovalRequest) (permission.ApprovalResponse, error)
	// HasPendingApproval reports a gate still waiting on a viewer.
	HasPendingApproval() bool
	// OpenBrowser delivers one validated agent navigation and waits for the
	// viewer's product shell to report its terminal result.
	OpenBrowser(context.Context, tools.BrowserRequest) (tools.BrowserResult, error)
	// Ask puts the agent's multiple-choice questions to the viewer and blocks
	// until they answer or the run is cancelled.
	Ask(context.Context, []tools.Question) ([]tools.Answer, error)
	// HasPendingQuestion reports a question still waiting on a viewer.
	HasPendingQuestion() bool
	// Close releases the delivery link after its session is removed.
	Close()
}

Transport is one session's link to whatever is watching it. The delivery layer supplies an implementation per session; this package never learns how an event is encoded or who receives it.

Decide and HasPendingApproval are here rather than on a separate type because a permission gate is a conversation with the same viewer: the session cannot know whether one is answerable without asking its transport.

Jump to

Keyboard shortcuts

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