engine

package
v0.6.16 Latest Latest
Warning

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

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

Documentation

Overview

Package engine owns one stateful coding-agent session. It wires the reusable agent and llm libraries to the product's tools, prompt, permissions, transcript, and compaction policy.

Index

Constants

This section is empty.

Variables

View Source
var ErrBusy = errors.New("coding: a run is already in progress")

ErrBusy is returned by Prompt and Continue when a run is already in progress. Steer and FollowUp inject messages into a running session instead.

Functions

func IsNothingToCompact

func IsNothingToCompact(err error) bool

Keep errors.Is useful for product adapters without importing the compaction implementation package.

Types

type AttachedFile

type AttachedFile struct {
	File
	Content string `json:"content"`
}

AttachedFile is text or source code explicitly attached to one user message. Content is persisted for the model; transports expose only File.

type BackgroundTask

type BackgroundTask struct {
	ID          string
	Command     string
	Description string
	Status      string
	OutputPath  string
	ExitCode    *int
	StartedAt   time.Time
	CompletedAt time.Time
}

BackgroundTask is the product-neutral state of one session-owned process.

type CompactionResult

type CompactionResult struct {
	Summary          string
	FirstKeptEntryID string
	TokensBefore     int64
	TokensAfter      int64
	Usage            llm.Usage
	Provider         string
	Model            string
	ResponseModel    string
	ResponseID       string
	Timestamp        time.Time
}

type ContextBreakdown added in v0.6.9

type ContextBreakdown struct {
	Messages       int64
	SystemTools    int64
	SystemPrompt   int64
	Skills         int64
	ProjectContext int64
}

ContextBreakdown estimates how the latest measured context is distributed. The provider-measured total remains authoritative; these categories are proportionally calibrated to it because providers do not report attribution.

type ContextUsage

type ContextUsage struct {
	Provider      string
	Model         string
	UsedTokens    int64
	ContextWindow int64
	Measured      bool
	Breakdown     *ContextBreakdown
}

ContextUsage describes the latest provider-measured context for the model currently selected by a Session. UsedTokens includes the prompt and response tokens from that request. Measured is false until the selected model has completed a request; switching models deliberately invalidates the previous model's count because tokenizers and context limits differ.

type Event

type Event struct {
	Type EventType

	// User messages, assistant content, and tool-result media.
	Delta  string
	Text   string
	Images []llm.ImageContent
	Files  []File
	// SentAt records when a user message entered the active agent run.
	SentAt time.Time
	// QueueHandle identifies the queued user message represented by a
	// UserMessageCompleted event. It is zero for an ordinary prompt.
	QueueHandle QueueHandle
	// FinalResponse distinguishes a user-visible completed reply from an
	// assistant message that paused only to call tools.
	FinalResponse bool

	// Tool lifecycle data.
	ToolCallID       string
	ToolName         string
	ToolArgs         any
	ToolContentIndex int
	ToolInputBytes   int
	ToolResult       string
	// ToolOutcome is the source of truth for status, error metadata, and
	// structured product data. ToolResult remains the model-facing text fallback.
	ToolOutcome agent.ToolOutcome

	// BackgroundTask contains the latest lifecycle state for task events.
	BackgroundTask BackgroundTask
	// PlanMode is populated on PlanModeChanged.
	PlanMode bool

	// Usage is one assistant request's consumption on MessageCompleted and the
	// aggregate consumption on RunCompleted. Product adapters may accumulate
	// tool-use requests until FinalResponse to show one total per visible reply.
	Usage llm.Usage
	// ContextUsage is the provider-measured latest context plus its estimated
	// category attribution. It is populated on MessageCompleted.
	ContextUsage ContextUsage

	// Response metadata identifies the exact provider request represented by a
	// MessageCompleted event. It lets product shells build durable, per-model
	// usage reports without inferring the active model from mutable UI state.
	// ProviderRequestID is also populated on streamed content and tool events so
	// live consumers can join them to the same diagnostic request snapshot.
	ProviderRequestID string
	Provider          string
	Model             string
	ResponseModel     string
	ResponseID        string
	Timestamp         time.Time
	// Automatic distinguishes context maintenance performed inside an active run
	// from an explicit Compact call. Error is populated on CompactionFailed.
	Automatic bool
	Error     string

	// Run timing is populated on RunStarted and RunCompleted. It measures the
	// full invocation, including model calls, tools, approvals, retries, and any
	// steering or follow-up work consumed before the run ends. TurnStarted also
	// carries its owning RunID, stable TurnID, and StartedAt boundary.
	RunID       string
	TurnID      string
	StartedAt   time.Time
	CompletedAt time.Time
	// RunCompleted identifies the messages made durable by the finished run.
	// UserMessageIDs follow transcript order; AssistantMessageID is the final
	// user-visible response and excludes intermediate tool-use turns.
	UserMessageIDs     []string
	AssistantMessageID string
}

Event is the stable event contract exposed by Session. Fields are populated according to Type; presentation-specific concerns such as ANSI styling, JSON field names, SSE framing, and Markdown rendering stay in product adapters.

type EventType

type EventType string

EventType identifies a UI-neutral coding-session event. Product adapters render these events for their own transport instead of depending on the lower-level agent event model.

const (
	RunStarted           EventType = "run_started"
	TurnStarted          EventType = "turn_started"
	UserMessageCompleted EventType = "user_message_completed"
	TextDelta            EventType = "text_delta"
	ThinkingDelta        EventType = "thinking_delta"
	ToolInputStarted     EventType = "tool_input_started"
	ToolInputDelta       EventType = "tool_input_delta"
	ToolInputCompleted   EventType = "tool_input_completed"
	ToolStarted          EventType = "tool_started"
	ToolFinished         EventType = "tool_finished"
	MessageCompleted     EventType = "message_completed"
	TurnDiscarded        EventType = "turn_discarded"
	CompactionStarted    EventType = "compaction_started"
	CompactionCompleted  EventType = "compaction_completed"
	CompactionFailed     EventType = "compaction_failed"
	TaskStarted          EventType = "task_started"
	TaskCompleted        EventType = "task_completed"
	PlanModeChanged      EventType = "plan_mode_changed"
	RunCompleted         EventType = "run_completed"
)

type File

type File struct {
	Name     string `json:"name"`
	MIMEType string `json:"mimeType"`
	Size     int    `json:"size"`
}

File is display-safe metadata retained for an attached file.

type HistoryItem

type HistoryItem struct {
	Type HistoryItemType
	// RunID is the durable lifecycle identity shared with local diagnostics.
	// It is populated for HistoryRun once run/start has been persisted.
	RunID string
	// MessageID is the durable transcript entry ID for persisted user and
	// assistant messages. Live messages remain empty until they are checkpointed.
	MessageID string
	// SentAt is the durable transcript timestamp for a persisted user message.
	SentAt time.Time

	Text   string
	Images []llm.ImageContent
	Files  []File
	// FinalResponse is true for the assistant item that completes one visible
	// reply. Tool-use pauses remain false even when they contain explanatory text.
	FinalResponse bool
	Provider      string
	Model         string

	ToolCallID string
	ToolName   string
	ToolArgs   any
	ToolResult string
	// ToolOutcome is restored from the transcript's product-facing entries.
	ToolOutcome agent.ToolOutcome

	// Usage is populated for HistoryUsage and aggregates every assistant model
	// request that contributed to the preceding final response.
	Usage llm.Usage

	// Run timing is populated for HistoryRun. CompletedAt is also populated for
	// the final assistant response associated with a completed run.
	StartedAt   time.Time
	CompletedAt time.Time
}

HistoryItem is the displayable, product-neutral history contract exposed by Session. Product shells can render it without knowing the lower-level agent or LLM message representations.

type HistoryItemType

type HistoryItemType string

HistoryItemType identifies one UI-neutral item reconstructed from the persisted conversation transcript.

const (
	HistoryUser       HistoryItemType = "user"
	HistoryAssistant  HistoryItemType = "assistant"
	HistoryThinking   HistoryItemType = "thinking"
	HistoryToolCall   HistoryItemType = "tool_call"
	HistoryToolResult HistoryItemType = "tool_result"
	HistoryUsage      HistoryItemType = "usage"
	HistoryRun        HistoryItemType = "run"
)

type Options

type Options struct {
	// SessionID is the product conversation identity attached to diagnostic
	// events. Empty keeps embedded and test sessions anonymous.
	SessionID string
	// Recorder receives bounded, privacy-safe lifecycle records. Nil disables
	// observability without changing session behavior.
	Recorder observability.Recorder
	// Model is the model used for turns. Required.
	Model llm.Model
	// ThinkingLevel sets the reasoning effort for each turn.
	ThinkingLevel llm.ModelThinkingLevel
	// Cwd is the workspace root the tools operate in. Empty uses the process
	// working directory.
	Cwd string
	// Tools is the tool set. Nil uses the built-in tools rooted at Cwd.
	Tools []tools.Tool
	// AdditionalTools are appended to either the built-in or caller-supplied
	// tool set. Product integrations use this to inject stable tool snapshots.
	AdditionalTools []tools.Tool
	// Skills is the initial immutable skill snapshot. The Skill tool is advertised
	// only while the active snapshot contains at least one Skill.
	Skills []skills.Skill
	// SkillLoader refreshes the resolved skill snapshot once at session
	// construction and once before every top-level Prompt or Continue. Nil keeps
	// Skills static. The loader is deliberately not called for provider retries,
	// tool-loop turns, or context-overflow recovery.
	SkillLoader func() []skills.Skill
	// PermissionMode controls which tool calls require approval. Missing or
	// unknown values use the conservative ask mode.
	PermissionMode permission.Mode
	// Approver obtains decisions for calls that require approval. Nil denies them.
	Approver permission.Approver
	// Browser delivers navigation and read-only observation requests to the
	// product shell and waits for their acknowledgements. Nil makes those tools
	// fail closed.
	Browser tools.BrowserController
	// Asker puts a multiple-choice question to the user and blocks until they
	// answer. Nil advertises no question tool at all, so a session with nobody
	// at the keyboard never sees one it cannot use.
	Asker tools.Asker
	// Store persists the transcript and seeds it on construction. Nil disables
	// persistence.
	Store transcript.Store
	// Compactor creates checkpoint summaries. Nil uses a native, tool-free LLM
	// request configured from StreamFn, StreamOptions, and GetAPIKey.
	Compactor compaction.Compactor
	// Instructions overrides the base system-prompt preamble. Empty uses
	// prompt.DefaultInstructions.
	Instructions string
	// MaxRetries caps how many times a transient turn failure is retried above
	// the provider SDK's own request retries. Nil uses defaultMaxRetries; a
	// pointer to 0 disables app-level retries.
	MaxRetries *int

	// StreamOptions are the base per-request options for every turn.
	StreamOptions llm.StreamOptions
	// StreamFn reaches a model for one turn. Nil uses the agent default.
	StreamFn agent.StreamFn
	// GetAPIKey resolves the provider API key before each turn, for short-lived
	// tokens.
	GetAPIKey func(provider string) string
}

Options configures a Session. Only Model is required; the rest have working defaults.

type PlanModeSnapshot added in v0.6.15

type PlanModeSnapshot struct {
	Active bool `json:"active"`
}

PlanModeSnapshot is the latest committed planning mode for a session.

type QueueHandle

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

QueueHandle identifies one message submitted to this Session's queue. The identity remains stable when the message enters the run.

type Session

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

Session is a stateful coding conversation. Prompt and Continue block until a run completes and are mutually exclusive; a concurrent call returns ErrBusy. Steer, FollowUp, Abort, Subscribe, and Snapshot are safe during a run.

func New

func New(ctx context.Context, opts Options) (*Session, error)

New builds a Session. When a Store is configured, its transcript is loaded and used to seed the agent, so the session resumes where it left off.

func (*Session) Abort

func (s *Session) Abort()

Abort cancels an in-progress run.

func (*Session) CancelQueuedMessage

func (s *Session) CancelQueuedMessage(handle QueueHandle) bool

CancelQueuedMessage removes one message that has not entered the transcript.

func (*Session) ClearQueuedMessages

func (s *Session) ClearQueuedMessages()

ClearQueuedMessages drops steering and follow-up messages that have not yet entered the transcript. Product adapters use it when a run is stopped or otherwise finishes before a queued message can be consumed.

func (*Session) Close

func (s *Session) Close()

Close releases resources the session owns. It stops any background tasks the default tool set started so long-lived processes do not outlive the session. It does not abort an in-progress run; call Abort first if one may be active. Close is safe to call more than once, and a no-op when the session was built with a caller-supplied tool set.

func (*Session) Compact

func (s *Session) Compact(ctx context.Context, instructions string) (CompactionResult, error)

Compact summarizes old complete turns and appends a durable compaction boundary. The original entries remain in the session log.

func (*Session) ContextUsage

func (s *Session) ContextUsage() ContextUsage

ContextUsage returns the newest context measurement when it belongs to the model currently selected by the Session.

func (*Session) Continue

func (s *Session) Continue(ctx context.Context) error

Continue resumes a run from the current transcript without adding a message. It returns ErrBusy if a run is already in progress.

func (*Session) Entries

func (s *Session) Entries() []transcript.Entry

Entries returns a detached snapshot of the durable session log.

func (*Session) ExitPlanMode added in v0.6.15

func (s *Session) ExitPlanMode(ctx context.Context) error

ExitPlanMode implements tools.PlanModeState for the in-run review tool.

func (*Session) FollowUp

func (s *Session) FollowUp(text string, images ...llm.ImageContent) QueueHandle

FollowUp queues a message to process once the run would otherwise stop.

func (*Session) FollowUpWithFiles

func (s *Session) FollowUpWithFiles(
	text string,
	files []AttachedFile,
	images ...llm.ImageContent,
) QueueHandle

FollowUpWithFiles queues a follow-up with product-owned attached file context.

func (*Session) History

func (s *Session) History() []HistoryItem

History returns a displayable snapshot of the conversation in transcript order. The returned slice is detached from the agent's mutable state.

func (*Session) Messages

func (s *Session) Messages() []agent.AgentMessage

Messages returns every original message on the current transcript path. A compacted session therefore still exposes its complete history.

func (*Session) PlanMode added in v0.6.15

func (s *Session) PlanMode() PlanModeSnapshot

PlanMode returns the latest committed plan-mode state.

func (*Session) PlanModeActive added in v0.6.15

func (s *Session) PlanModeActive() bool

PlanModeActive implements tools.PlanModeState.

func (*Session) Prompt

func (s *Session) Prompt(ctx context.Context, text string, images ...llm.ImageContent) error

Prompt starts a run from a text message and optional images, blocking until it completes. Newly appended messages are persisted. It returns ErrBusy if a run is already in progress.

func (*Session) PromptWithFiles

func (s *Session) PromptWithFiles(
	ctx context.Context,
	text string,
	files []AttachedFile,
	images ...llm.ImageContent,
) error

PromptWithFiles starts a run with text files that remain product-owned context rather than becoming a new LLM SDK content type.

func (*Session) RequestSnapshots added in v0.6.16

func (s *Session) RequestSnapshots() (snapshot.SessionReader, error)

RequestSnapshots opens one immutable diagnostic view of the committed transcript. Multiple provider requests loaded from it share one session projection.

func (*Session) SetModel

func (s *Session) SetModel(model llm.Model)

SetModel replaces the model used by the next run. Call it only while the session is idle; an in-flight run has already captured its model.

func (*Session) SetPermissionMode added in v0.6.9

func (s *Session) SetPermissionMode(mode permission.Mode)

SetPermissionMode changes the permission mode used by subsequent tool calls. Call it only while the session is idle.

func (*Session) SetPlanMode added in v0.6.15

func (s *Session) SetPlanMode(ctx context.Context, active bool) error

SetPlanMode changes plan mode while the session is idle.

func (*Session) SetThinkingLevel

func (s *Session) SetThinkingLevel(level llm.ModelThinkingLevel)

SetThinkingLevel replaces the reasoning effort used by the next run. Call it only while the session is idle.

func (*Session) Snapshot

func (s *Session) Snapshot() agent.State

Snapshot returns a read-only snapshot of the underlying agent state.

func (*Session) Steer

func (s *Session) Steer(text string, images ...llm.ImageContent) QueueHandle

Steer queues a message to inject after the current turn's tool calls finish.

func (*Session) SteerWithFiles

func (s *Session) SteerWithFiles(
	text string,
	files []AttachedFile,
	images ...llm.ImageContent,
) QueueHandle

SteerWithFiles queues guidance with product-owned attached file context.

func (*Session) StopTask

func (s *Session) StopTask(id string) error

StopTask terminates one session-owned background task.

func (*Session) Subscribe

func (s *Session) Subscribe(listener func(Event)) (unsubscribe func())

Subscribe registers a listener for UI-neutral coding events and returns a function that removes it.

func (*Session) TaskOutput

func (s *Session) TaskOutput(id string) (TaskOutput, error)

TaskOutput returns a bounded tail of one session-owned task's logs.

func (*Session) Tasks

func (s *Session) Tasks() []BackgroundTask

Tasks returns every managed task's latest state in creation order.

func (*Session) Todos added in v0.6.15

func (s *Session) Todos() *TodoSnapshot

Todos returns the latest committed checklist for the current turn. The returned value is detached from the live projection.

type TaskOutput

type TaskOutput struct {
	Content   string
	Truncated bool
}

TaskOutput is a bounded tail of one background task's combined output.

type TodoItem added in v0.6.15

type TodoItem struct {
	Content string `json:"content"`
	Status  string `json:"status"`
}

TodoItem is one product-neutral execution-checklist row.

type TodoSnapshot added in v0.6.15

type TodoSnapshot struct {
	Todos []TodoItem `json:"todos"`
}

TodoSnapshot is the current turn's complete execution checklist. A nil snapshot means the current turn has not written a checklist; a non-nil empty Todos slice means todo_write explicitly cleared it.

Jump to

Keyboard shortcuts

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