agent

package
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Aug 2, 2026 License: Apache-2.0 Imports: 32 Imported by: 0

Documentation

Index

Constants

View Source
const MinCompactableResultTokens = 200

MinCompactableResultTokens avoids rewriting small, often stateful results.

Variables

This section is empty.

Functions

func BuildSystemBlocks added in v0.3.0

func BuildSystemBlocks(identity, instructions, gitSnapshot, dynamic string) []agentcore.SystemBlock

BuildSystemBlocks orders the system prompt from most stable to least. The cache is a strict prefix, so position decides whether a block can be cached at all — gitSnapshot never changes but would be uncacheable parked after the volatile dynamic block.

Breakpoints go on the FIRST and LAST static block, not every one: the prefix runs through the final marker, so the middle rides along for free, while the one on identity survives a reload that rewrites instructions.

func BuildToolPool added in v0.1.3

func BuildToolPool(cwd string, mainTools []agentcore.Tool, fs tools.WorkspaceFS) []agentcore.Tool

BuildToolPool returns a tool list suitable as input to FilterToolsForAgent. Read / write / edit are replaced with fresh instances sharing a sub-agent- local FileReadState so a read in a sub-agent cannot poison the parent's read-stamp cache (which would let the parent's next write of the same file silently skip its own read-before-write check). Other tools are passed through by reference — they are either stateless or already keyed by cwd.

Call this ONCE PER SUB-AGENT KIND. Two sub-agent kinds (e.g. explore and general-purpose) must NOT share the returned slice: doing so re-introduces the same cross-pollination of read state that we created this function to prevent. fs is the workspace backend the rebuilt read/write/edit instances operate on; nil falls back to the local filesystem (tools default to OSWorkspaceFS).

func ClearedToolResultMessage added in v0.3.1

func ClearedToolResultMessage(_ string, original agentcore.Message) string

ClearedToolResultMessage preserves the path of output already persisted by tools.OutputLimiter. "" selects the default cleared message.

func CodebotToolClassifier added in v0.1.0

func CodebotToolClassifier(name string) bool

func CompactionBlocks added in v0.3.1

func CompactionBlocks(strategy string) bool

CompactionBlocks reports whether a strategy may block on a model call.

func FilterToolsForAgent added in v0.1.3

func FilterToolsForAgent(in []agentcore.Tool, opts FilterOpts) []agentcore.Tool

FilterToolsForAgent returns the subset of `in` that a sub-agent may use.

Checks per tool, in order:

  1. The `subagent` tool itself is dropped (recursive spawn guard, applied unconditionally — not configurable).
  2. MCP tools (mcp__ prefix) pass through iff AllowMCP, bypassing the allow/deny lists.
  3. allAgentDisallowed is dropped.
  4. customAgentDisallowed is dropped when !IsBuiltIn.
  5. ExtraDisallowed (per-agent) is dropped.
  6. When IsAsync, only asyncAgentAllowed passes; everything else is dropped.

Types

type AgentDefinition added in v0.1.3

type AgentDefinition struct {
	// Name is the unique identifier the LLM passes to the subagent tool.
	// Must be non-empty and globally unique after merging — MergeAgents
	// resolves name collisions by source precedence (user > project > builtin).
	Name string

	// Description is shown to the LLM in the subagent tool's schema enum
	// description. Treat it like a docstring: it tells the model WHEN to
	// invoke this agent, not what the agent does internally.
	Description string

	// SystemPrompt is the agent's system prompt. For built-ins it is a Go
	// string literal; for file-loaded agents it is the markdown body that
	// follows the frontmatter.
	SystemPrompt string

	// Tools is an allow-list of tool names. nil or {"*"} means "everything
	// the filter rules allow"; otherwise the listed names are intersected
	// with the filter output. Used by file-loaded agents to scope the
	// surface further than the global filter does.
	Tools []string

	// DisallowedTools is a per-agent deny-list, applied AFTER the global
	// rules. Mapped to FilterOpts.ExtraDisallowed at BuildConfig time.
	DisallowedTools []string

	// Model is "inherit" (use the parent's model), an explicit model name,
	// or empty (defaults to inherit).
	Model string

	// MaxTurns caps the agent's loop. Zero means use the subagent default.
	MaxTurns int

	// Background, when true, marks the agent as one that should run async
	// by default. The subagent tool can still override this per call via
	// its `background` parameter.
	Background bool

	// Isolation selects the teammate's filesystem sandbox. Empty or "shared"
	// (the default) runs the teammate in the leader's cwd, sharing the working
	// tree. "worktree" gives it a private git worktree so its writes cannot
	// clobber a peer editing the same files — see team.Isolation. Honoured
	// only for teammate spawns in a git repo; a no-op elsewhere.
	Isolation string

	// Provenance — set by the loader, read by tooling that wants to point
	// the user at a definition's origin (`/agents show explore` etc.).
	Source   AgentSource
	BaseDir  string // directory the agent was loaded from, or "builtin"
	Filename string // file path within BaseDir, or "" for built-ins
}

AgentDefinition is codebot's spec layer for a sub-agent. It carries every piece of information needed to materialise a subagent.Config, plus provenance metadata used by callers, the UI, and `/agents` listings.

Three places construct AgentDefinitions:

  1. Built-in defaults (see builtinAgentDefinitions)
  2. agent_loader.LoadAgentsDir reading .codebot/agents/*.md frontmatter
  3. (Future) plugin contributions

All three feed MergeAgents and then BuildConfig in turn.

func BuiltinDefinitions added in v0.1.3

func BuiltinDefinitions(cwd string) []AgentDefinition

BuiltinDefinitions returns the three sub-agents that ship with codebot.

They use the same AgentDefinition shape that file-loaded agents use, so the bootstrap pipeline can treat builtin / project / user agents uniformly. Two practical consequences:

  1. A user can override `explore` by dropping their own .codebot/agents/explore.md into the project. The MergeAgents step picks up the later source by name.
  2. Built-ins go through the same Validate() and BuildConfig() pipeline as everything else, so a typo in the prompt loader can't produce a different runtime shape from a typo in a Go literal.

If you find yourself adding a fourth built-in, ask first whether it should be a built-in at all — a project-level agent in .codebot/agents/ is usually the more honest place for codebase-specific roles.

func LoadAgentsDir added in v0.1.3

func LoadAgentsDir(dir string, source AgentSource) (defs []AgentDefinition, errs []error)

LoadAgentsDir reads every *.md file under dir and parses them as agent definitions. Files that fail to parse are reported but do not abort the load — a single broken file should not block the user from using the rest of their agent library. The returned errors slice has one entry per broken file; the returned definitions slice excludes those files.

dir is allowed to not exist (returns nil, nil) — the loader is happy to be called speculatively against directories that haven't been created yet.

func MergeAgents added in v0.1.3

func MergeAgents(groups ...[]AgentDefinition) []AgentDefinition

MergeAgents combines definitions from multiple sources, with later groups overriding earlier ones by name. The expected call order is:

MergeAgents(builtin, project, user)

so a user file overrides a project file overrides a built-in. This matches the trust-vs-customisability ordering: ship sensible defaults, let teams override per-project, let individuals override per-machine.

IMPORTANT: override is WHOLE-DEFINITION replacement, not field-level merge. A user file that re-declares `explore` but omits `disallowedTools` will drop the read-only restriction the built-in version had. This is intentional — field-level merging is hard to predict ("did I inherit X from project or builtin?") and we'd rather force the user to be explicit than make them debug surprising privilege escalations. Document this in any user-facing agent-authoring guide.

Empty names are skipped silently — Validate() should catch them upstream; MergeAgents is the wrong place to surface schema errors.

func (*AgentDefinition) BuildConfig added in v0.1.3

func (d *AgentDefinition) BuildConfig(deps BuildDeps, ctxFactory func(agentcore.ChatModel) agentcore.ContextManager) (subagent.Config, error)

BuildConfig converts an AgentDefinition into a subagent.Config ready to be passed to subagent.NewRunner(...). It is responsible for:

  • Resolving the model name to a ChatModel (inherit vs explicit).
  • Calling BuildToolPool to give the sub-agent its own read/write/edit instances (independent FileReadState — see Stage 2 review).
  • Running FilterToolsForAgent with rules derived from Source/Background.
  • Applying AgentDefinition.Tools as a post-filter allow-list when set.
  • Wiring a fresh ContextManager via the factory the caller supplied.

BuildConfig is pure with respect to BuildDeps: calling it twice with the same definition and deps yields independent subagent.Config values (which is what the per-agent FileReadState invariant requires).

func (*AgentDefinition) Validate added in v0.1.3

func (d *AgentDefinition) Validate() error

Validate checks the structural invariants we can verify without the world — required fields present, tool-name strings non-empty, etc. Returns the first error encountered. Loader call sites must invoke this after parsing.

type AgentSource added in v0.1.3

type AgentSource string

AgentSource is the provenance of an AgentDefinition. It maps to a trust tier: built-in is code-controlled and trusted; project lives in version control (team-reviewed); user is per-machine and the least scrutinised.

The source is consulted at tool-pool assembly time — see FilterToolsForAgent's IsBuiltIn flag — so adding a new source means deciding whether sub-agents loaded from it should be subject to customAgentDisallowed.

const (
	SourceBuiltin AgentSource = "builtin"
	SourceProject AgentSource = "project" // .codebot/agents/
	SourceUser    AgentSource = "user"    // ~/.codebot/agents/
)

func (AgentSource) IsBuiltIn added in v0.1.3

func (s AgentSource) IsBuiltIn() bool

IsBuiltIn reports whether the source qualifies for the built-in trust tier in tool filtering. Today only SourceBuiltin does; SourceProject is kept out because a project agent file changes via PR review but executes on every collaborator's machine — different threat model from code that shipped with the binary.

type BuildDeps added in v0.1.3

type BuildDeps struct {
	// Cwd is the workspace root. Used by sub-agent prompts and by the
	// per-agent tool pool when constructing scoped read/write/edit
	// instances.
	Cwd string

	// MainTools is the parent agent's tool list AS HANDED TO buildSubAgents
	// — that is, before the subagent and Skill tools are appended. Every
	// AgentDefinition gets this list re-pooled into independent instances
	// inside BuildConfig (see BuildToolPool's contract).
	MainTools []agentcore.Tool

	// DefaultModel is the parent agent's chat model, used when the
	// AgentDefinition either omits Model or sets it to "inherit".
	DefaultModel agentcore.ChatModel

	// ContextWindow is the parent's context window size, threaded to the
	// per-agent ContextManager so summary thresholds align with the model
	// in use.
	ContextWindow int

	// ResolveModel maps an explicit model name from AgentDefinition.Model
	// to a ChatModel. May be nil when the build pipeline doesn't support
	// per-agent model override; in that case any explicit Model that
	// isn't "inherit" produces an error from BuildConfig.
	ResolveModel func(name string) (agentcore.ChatModel, error)

	// WorkspaceFS is the file backend the per-agent read/write/edit pool
	// operates on. Threaded so sub-agents share the parent's backend (e.g.
	// editor buffers under ACP). Nil means the local filesystem.
	WorkspaceFS tools.WorkspaceFS

	// SessionID is the parent session's identity, used as the base of each
	// sub-agent's prompt-cache routing key (agentcore appends "#<seq>" per
	// spawn). Empty disables the routing hint; cache breakpoints still apply.
	SessionID string

	// Middlewares wrap each tool execution inside the sub-agent. A sub-agent
	// runs its own loop and does not inherit the parent's middleware stack, so
	// anything that must apply everywhere (output limiting) is threaded here.
	Middlewares []agentcore.ToolMiddleware
}

BuildDeps carries the runtime context BuildConfig needs to materialise an AgentDefinition into a subagent.Config. It is constructed once per call to buildSubAgents and reused across every definition.

Why a struct instead of positional args: BuildConfig is called from bootstrap, and bootstrap already has eight parameters threading through subagent assembly. A struct lets us add fields (e.g. eventual MCP server inheritance) without breaking call sites.

type CacheStats added in v0.1.3

type CacheStats struct {
	Input       int
	ReadTokens  int
	WriteTokens int
	HitRate     float64
	SavedUSD    float64
}

CacheStats reports session-cumulative prompt cache metrics. Input includes CacheRead per litellm convention; HitRate is CacheRead / Input. SavedUSD estimates the dollars saved by serving CacheRead tokens at the cache-read rate instead of the full input rate.

type CompactionKind added in v0.1.0

type CompactionKind string
const (
	CompactionKindMicro CompactionKind = "micro"
	CompactionKindFull  CompactionKind = "full"
	CompactionKindTrim  CompactionKind = "trim"
	CompactionKindPrune CompactionKind = "prune"
)

type CompactionResult added in v0.0.2

type CompactionResult struct {
	Changed        bool
	TokensBefore   int
	TokensAfter    int
	Reason         string
	Strategy       string
	CompactedCount int
	KeptCount      int
	SplitTurn      bool
}

type CompactionSnapshot added in v0.1.0

type CompactionSnapshot struct {
	Kind           CompactionKind
	Strategy       string
	Reason         string
	Changed        bool
	TokensBefore   int
	TokensAfter    int
	CompactedCount int
	KeptCount      int
	SplitTurn      bool
	Timestamp      time.Time
}

type ContextBreakdown added in v0.1.0

type ContextBreakdown struct {
	UserText      int
	AssistantText int
	ToolCalls     int
	ToolResults   int
	Summaries     int
	Images        int
	Total         int
	ContextWindow int

	// TopTools lists the heaviest tools by total (call + result) tokens.
	TopTools []ToolTokenUsage
}

ContextBreakdown reports per-category token distribution in the conversation.

type ContextSuggestion added in v0.1.0

type ContextSuggestion struct {
	Severity string // "warning" or "info"
	Message  string
	Savings  int // estimated token savings, 0 if unknown
}

ContextSuggestion is an actionable recommendation to reduce context usage.

type ErrorSnapshot added in v0.1.0

type ErrorSnapshot struct {
	Category  diag.Category
	Message   string
	Detail    string
	Timestamp time.Time
}

type FilterOpts added in v0.1.3

type FilterOpts struct {
	// IsBuiltIn is true when the agent is defined in code, false when loaded
	// from a user-controlled source (.codebot/agents/, plugins).
	IsBuiltIn bool

	// IsAsync is true for background-mode runs. Async agents cannot prompt
	// the user, so they are restricted to the asyncAgentAllowed list.
	IsAsync bool

	// AllowMCP controls whether MCP tools (mcp__*) pass through. Defaults
	// false — call sites that want MCP must opt in.
	AllowMCP bool

	// ExtraDisallowed is a per-agent denylist applied on top of the global
	// rules. Used by built-in agents to scope themselves further (e.g. the
	// explore agent excludes write/edit/bash to stay read-only).
	ExtraDisallowed []string
}

FilterOpts controls how FilterToolsForAgent selects tools for a sub-agent.

type ModelFactory

type ModelFactory func(prov, model, apiKey, baseURL string, providerExtra map[string]any) (agentcore.ChatModel, error)

ModelFactory creates a chat model instance for a provider/model tuple.

type PlanModeSignal added in v0.1.3

type PlanModeSignal struct {
	Active        bool
	PlanFilePath  string
	JustCancelled bool
}

PlanModeSignal describes the plan-mode state observed at the moment the runtime polls before queueing a per-prompt reminder. Three distinct situations need different behavior:

  • Active=true: plan mode is on; emit the sparse "still read-only" reminder on its 5-turn cadence (PlanFilePath gives the writable plan file).
  • JustCancelled=true: plan mode was cancelled via /plan cancel since the last poll; emit a one-shot "you have exited plan mode" reminder so the model knows the MUST-NOT rules buried in the EnterPlanMode tool_result no longer apply.
  • All zero: plan mode is off; no reminder needed.

Active and JustCancelled are mutually exclusive — the producer (plan.Manager) guarantees that. JustCancelled is consumed on read: a second poll without a fresh Cancel() returns the zero value.

type ReminderSnapshot added in v0.1.0

type ReminderSnapshot struct {
	Kind      RuntimeReminderKind
	Mode      string
	Timestamp time.Time
}

type RuntimeMetricsSnapshot added in v0.1.0

type RuntimeMetricsSnapshot struct {
	ReminderTotal         int
	ReminderByKind        map[RuntimeReminderKind]int
	CompactionTotal       int
	CompactionChanged     int
	CompactionSaved       int
	CompactionByKind      map[CompactionKind]int
	CompactionSavedByKind map[CompactionKind]int
	ErrorTotal            int
	ErrorByCategory       map[diag.Category]int
}

type RuntimeReminderKind added in v0.1.0

type RuntimeReminderKind string
const (
	ReminderRepeatToolCall     RuntimeReminderKind = "repeat_tool_call"
	ReminderPostStopValidation RuntimeReminderKind = "post_stop_validation"
	ReminderSkillPaths         RuntimeReminderKind = "skill_paths"
	ReminderTaskManagement     RuntimeReminderKind = "task_management"
	ReminderPlanMode           RuntimeReminderKind = "plan_mode"
	ReminderGoal               RuntimeReminderKind = "goal"
	ReminderHookContext        RuntimeReminderKind = "hook_context"
	ReminderDateChange         RuntimeReminderKind = "date_change"
)

type Session

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

Session is the business-logic core that wraps Agent + session persistence. It is independent of any UI framework and drives interactive, print, and RPC modes.

State is grouped into self-guarded components — each owns its fields, its lock, and its reset; none of their methods reference Session (statically checkable by grepping the *_state.go method bodies), so component locks are leaves and no lock cycle can form. Nesting directions that do occur:

s.mu → run.mu                     (continueIfCurrentGeneration holds s.mu
                                   through beginTelemetryRun / rollback)
s.mu → agent lock                 (generation check + commit in one
                                   critical section: run launch in
                                   continueIfCurrentGeneration, SetMessages
                                   in the compaction commit; acyclic
                                   because the agent never calls back into
                                   the Session under its own lock —
                                   listener dispatch and the
                                   MessageCommitter run outside it, per the
                                   Subscribe lifecycle contract)
prompt.mu / model.mu → agent lock (sink delivery — covered by the setters'
                                   documented purity contract: pure
                                   assignment, no events, no callbacks),
                                   and prompt.mu → cache.mu (leaf delivery
                                   target)
flushMu → persist.mu              (lazy-persist drain)

s.mu itself guards generation and backgroundWakeSuppressed. Session-identity surgery (Reset / SwitchSession / ClearConversation) serializes with switchMu and freezes the run lifecycle itself with agent.HoldRuns — continuation launches then fail fast with ErrRunsHeld inside the kernel instead of coordinating through a session-side lock. Accepted cross-group snapshot windows are commented at their sites (persistLLMCall, ephemeralQuery, the dirtySeq/generation CAS in runPostStopValidation).

func NewSession

func NewSession(cfg SessionConfig) *Session

NewSession creates a Session and wires auto-persist to the agent.

func (*Session) APIKey

func (s *Session) APIKey() string

func (*Session) Abort

func (s *Session) Abort()

func (*Session) AbortSilent

func (s *Session) AbortSilent()

func (*Session) AppendGoalState added in v0.2.2

func (s *Session) AppendGoalState(entry storage.GoalStateEntry) error

func (*Session) ApplySkillDelta added in v0.1.0

func (s *Session) ApplySkillDelta(name string, delta skill.Delta) error

func (*Session) ApplySkillInvocation added in v0.1.0

func (s *Session) ApplySkillInvocation(result *skill.InvocationResult) error

func (*Session) AvailableThinkingLevels added in v0.3.0

func (s *Session) AvailableThinkingLevels() []string

func (*Session) AvailableThinkingLevelsFor added in v0.3.0

func (s *Session) AvailableThinkingLevelsFor(prov, modelName string) []string

func (*Session) BaseURL

func (s *Session) BaseURL() string

func (*Session) CacheStats added in v0.1.3

func (s *Session) CacheStats() CacheStats

func (*Session) ClearConversation

func (s *Session) ClearConversation()

func (*Session) Close

func (s *Session) Close()

func (*Session) Compact

func (s *Session) Compact() (CompactionResult, error)

func (*Session) ContextBreakdown added in v0.1.0

func (s *Session) ContextBreakdown() ContextBreakdown

ContextBreakdown computes a per-category token breakdown of the current conversation messages. It does NOT include system prompt or tool definitions.

func (*Session) ContextSnapshot added in v0.1.0

func (s *Session) ContextSnapshot() (*agentcore.ContextSnapshot, bool)

func (*Session) ContextSuggestions added in v0.1.0

func (s *Session) ContextSuggestions() []ContextSuggestion

ContextSuggestions generates actionable suggestions based on context usage and the message breakdown.

func (*Session) ContextUsage

func (s *Session) ContextUsage() *agentcore.ContextUsage

func (*Session) CostEstimate

func (s *Session) CostEstimate() (inputTokens, outputTokens int, cost float64)

func (*Session) CurrentSessionInfo

func (s *Session) CurrentSessionInfo() (storage.SessionInfo, error)

func (*Session) CurrentSnapshot added in v0.2.2

func (s *Session) CurrentSnapshot() (storage.ContextSnapshot, error)

func (*Session) Diff added in v0.2.0

func (s *Session) Diff() (string, error)

Diff returns a numstat preview of what Undo would roll back (the last turn's file changes), or "" when there is nothing to undo.

func (*Session) DynamicSystemBlock added in v0.2.0

func (s *Session) DynamicSystemBlock() *agentcore.SystemBlock

func (*Session) EnqueueBackgroundResult added in v0.3.0

func (s *Session) EnqueueBackgroundResult(msg agentcore.AgentMessage)

EnqueueBackgroundResult delivers a completed background task without interrupting an active run. If the session is idle, it starts a continuation so the result does not wait for another user prompt.

func (*Session) GenerateSuggestion added in v0.0.4

func (s *Session) GenerateSuggestion(ctx context.Context) (string, error)

GenerateSuggestion calls the current model with a condensed conversation history plus a suggestion prompt to predict the user's next input. Returns "" when no suggestion is available (first turn, no model, etc.).

func (*Session) HandleGoalChange added in v0.2.2

func (s *Session) HandleGoalChange(change goal.Change)

func (*Session) HandleOverflowRewrite added in v0.1.0

func (s *Session) HandleOverflowRewrite(info agentctx.RewriteEvent)

func (*Session) HandleProjectedRewrite added in v0.1.0

func (s *Session) HandleProjectedRewrite(info agentctx.RewriteEvent)

func (*Session) IdentitySystemBlock added in v0.3.0

func (s *Session) IdentitySystemBlock() []agentcore.SystemBlock

DynamicSystemBlock returns the current dynamic block snapshot (MCP tool inventory + active overlays), or nil when there's nothing to include.

Called by the teammate spawner at spawn time so teammates inherit the leader's MCP descriptions and overlay state. Each teammate freezes its system prompt at spawn — later leader-side changes (plan-mode toggle / MCP refresh) do NOT propagate to already-running teammates.

The block intentionally carries no CacheControl. Two reasons:

  1. Anthropic caps system-field cache_control markers; the universal base and role block already consume two — leaving the dynamic block uncached keeps headroom for the message-level marker the agent loop adds.
  2. The dynamic block can churn mid-session (plan-mode toggle, MCP reconnect); a cache breakpoint here would be invalidated frequently and would charge cache-write cost for short-lived content.

IdentitySystemBlock returns the leader current block 1 for a teammate to build on. Call it per spawn — a worktree retarget rewrites this block.

func (*Session) IsRunning

func (s *Session) IsRunning() bool

func (*Session) LastAssistantText

func (s *Session) LastAssistantText() string

func (*Session) LastCompaction added in v0.1.0

func (s *Session) LastCompaction() (CompactionSnapshot, bool)

func (*Session) LastReminder added in v0.1.0

func (s *Session) LastReminder() (ReminderSnapshot, bool)

func (*Session) LastRunSummary added in v0.1.0

func (s *Session) LastRunSummary() (agentcore.RunSummary, bool)

func (*Session) LastTurnOutcome added in v0.1.0

func (s *Session) LastTurnOutcome() TurnOutcomeSnapshot

func (*Session) ListSessions

func (s *Session) ListSessions() ([]storage.SessionInfo, error)

func (*Session) Messages added in v0.0.2

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

Messages returns the current agent message history.

func (*Session) ModelName

func (s *Session) ModelName() string

func (*Session) OverlayPrompt added in v0.1.1

func (s *Session) OverlayPrompt(key, text string)

OverlayPrompt registers or removes a named instructions overlay. Pass empty text to remove. Overlays are rendered sorted by key.

func (*Session) PostSummaryRecoveryHook added in v0.1.0

func (s *Session) PostSummaryRecoveryHook() agentctx.PostSummaryHook

func (*Session) Prompt

func (s *Session) Prompt(text string) error

func (*Session) PromptWithBlocks

func (s *Session) PromptWithBlocks(blocks []agentcore.ContentBlock) error

func (*Session) Provider

func (s *Session) Provider() string

func (*Session) RecentErrors added in v0.1.0

func (s *Session) RecentErrors(limit int) []ErrorSnapshot

func (*Session) RecentToolCalls added in v0.1.0

func (s *Session) RecentToolCalls(limit int) []ToolCallSnapshot

func (*Session) Redo added in v0.2.0

func (s *Session) Redo() (changed []string, ok bool, err error)

Redo re-applies the most recently undone turn's file changes. ok is false when there is nothing to redo (no tracker, no prior undo, or the redo branch was invalidated by a new turn).

func (*Session) Registry

func (s *Session) Registry() *provider.ModelRegistry

func (*Session) Reload

func (s *Session) Reload()

Reload re-reads context files, memory, and skills from disk, then swaps them in. The I/O runs before the prompt lock (load-then-swap).

func (*Session) ReplaceMCPTools added in v0.1.0

func (s *Session) ReplaceMCPTools(tools []agentcore.Tool)

ReplaceMCPTools installs the current MCP toolset. Output limiting needs no wiring here: it runs as middleware around every tool the agent executes, so tools registered on a refresh are covered the moment they are called.

func (*Session) Reset added in v0.1.1

func (s *Session) Reset() error

Reset closes the current session log and starts a fresh session in the same cwd. The in-memory conversation and harness state are cleared; the previous file is flushed.

func (*Session) ResetTaskList added in v0.1.0

func (s *Session) ResetTaskList() error

func (*Session) RestoreAllTools

func (s *Session) RestoreAllTools(extra ...agentcore.Tool)

func (*Session) RetargetWorkspace added in v0.3.0

func (s *Session) RetargetWorkspace(cwd string)

RetargetWorkspace moves the session to cwd: session cwd, snapshotter, and the two workspace-derived system blocks. The single primitive behind worktree enter AND exit.

The cwd-bound tools (read/write/edit/bash/glob/grep/ls) are NOT rebuilt — they resolve paths against the cwd override the session threads onto every agent-loop context (see baseRunCtx), so one set of instances serves both the main repo and a worktree sandbox. That is also why this must be called at a turn boundary: baseRunCtx reads s.cwd when the next run starts.

func (*Session) RuntimeMetrics added in v0.1.0

func (s *Session) RuntimeMetrics() RuntimeMetricsSnapshot

func (*Session) SessionID added in v0.0.4

func (s *Session) SessionID() string

func (*Session) SetBeforePrompt

func (s *Session) SetBeforePrompt(fn func())

func (*Session) SetGoalSignal added in v0.2.2

func (s *Session) SetGoalSignal(fn func() goal.Signal)

SetGoalSignal registers a callback the runtime polls at natural stop points to decide whether an explicit /goal should auto-continue.

func (*Session) SetGoalUsageLimitHandler added in v0.2.2

func (s *Session) SetGoalUsageLimitHandler(fn func(string) (goal.State, error))

func (*Session) SetIdleHook added in v0.3.0

func (s *Session) SetIdleHook(fn func())

SetIdleHook registers a callback invoked after each turn fully settles (EventAgentEnd with no pending automatic continuation). Must be cheap on its fast path — it runs on the event dispatch goroutine.

func (*Session) SetMCPInstructions added in v0.1.0

func (s *Session) SetMCPInstructions(text string)

func (*Session) SetModel

func (s *Session) SetModel(prov, model string) error

func (*Session) SetPlanModeSignal added in v0.1.3

func (s *Session) SetPlanModeSignal(fn func() PlanModeSignal)

SetPlanModeSignal registers a callback the runtime polls before every user prompt to decide whether to queue a plan-mode reminder. plan.Manager wires this so the reminder cadence stays driven by the actual plan-mode state rather than a side-channel boolean.

func (*Session) SetRewriteProgress added in v0.3.1

func (s *Session) SetRewriteProgress(fn func(strategy string) func())

SetRewriteProgress reports strategy execution to the frontend.

func (*Session) SetSkillCatalog added in v0.1.0

func (s *Session) SetSkillCatalog(catalog *skill.Catalog)

SetSkillCatalog is called from the UI goroutine on plugin reload; the catalog install and the prompt rebuild share one critical section.

func (*Session) SetTaskNotifyFn added in v0.1.0

func (s *Session) SetTaskNotifyFn(fn storage.TaskNotifyFn)

func (*Session) SetThinkingLevel

func (s *Session) SetThinkingLevel(level agentcore.ThinkingLevel)

func (*Session) SetTools

func (s *Session) SetTools(tools ...agentcore.Tool)

func (*Session) Settings

func (s *Session) Settings() config.Resolved

func (*Session) SideQuestion added in v0.0.4

func (s *Session) SideQuestion(ctx context.Context, question string) (string, error)

SideQuestion sends a one-shot question to the current model using the full conversation context but without tool definitions or conversation history mutation. The answer is ephemeral — it never enters the session store. This powers the /btw side-chain Q&A feature.

func (*Session) SkillCatalog added in v0.1.0

func (s *Session) SkillCatalog() *skill.Catalog

func (*Session) Skills

func (s *Session) Skills() []skill.Spec

func (*Session) SnapshotEnabled added in v0.2.0

func (s *Session) SnapshotEnabled() bool

SnapshotEnabled reports whether workspace snapshots are active for this session. It is false when the workspace isn't a git repository (or the snapshot setting is off), in which case Undo/Redo/Diff are inert no-ops — callers use this to explain the no-op instead of reporting "nothing to do".

func (*Session) Steer

func (s *Session) Steer(text string)

func (*Session) Subscribe

func (s *Session) Subscribe(fn func(SessionEvent)) func()

func (*Session) SwitchSession

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

func (*Session) TaskSnapshot added in v0.1.0

func (s *Session) TaskSnapshot() storage.TaskSnapshot

func (*Session) ToolOutputDir added in v0.3.1

func (s *Session) ToolOutputDir() string

ToolOutputDir resolves where this session persists oversized tool output. Resolved per call — the session directory moves on /new and /resume.

func (*Session) ToolsByName

func (s *Session) ToolsByName(names ...string) []agentcore.Tool

func (*Session) TotalTokens

func (s *Session) TotalTokens() int

func (*Session) Undo added in v0.2.0

func (s *Session) Undo() (changed []string, ok bool, err error)

Undo reverts workspace files to the start of the most recent turn that changed files, leaving conversation history untouched. ok is false when there is nothing to undo (no tracker, or no recorded changes).

func (*Session) WaitForIdle added in v0.3.0

func (s *Session) WaitForIdle()

type SessionConfig

type SessionConfig struct {
	Agent          *agentcore.Agent
	ContextManager agentcore.ContextManager
	Store          *storage.Store
	Manager        *storage.Manager
	Registry       *provider.ModelRegistry
	Settings       config.Resolved
	Cwd            string
	TaskStore      *storage.TaskStore
	// CreateModel allows tests/integrations to override model construction.
	// Defaults to provider.CreateModel when nil.
	CreateModel ModelFactory
	// LazyPersist buffers user messages and flushes them only when
	// an assistant response arrives. Disabled by default for safety.
	LazyPersist bool
	// ChatModel is the active ChatModel reference.
	ChatModel agentcore.ChatModel
	// TelemetryTracer opens agent-run spans and tool spans when telemetry is enabled.
	TelemetryTracer *telemetry.Tracer
	// HookRunner fires lifecycle hooks (notification, etc.). Nil when no hooks configured.
	HookRunner *hooks.Runner
	// Snapshotter records workspace file checkpoints at turn boundaries and
	// powers /undo. Nil disables snapshotting (e.g. outside a git repo).
	Snapshotter Snapshotter

	// Tools is the full set of tools registered with the agent.
	// Used by ToolsByName / RestoreAllTools for plan mode filtering.
	Tools []agentcore.Tool
	// ContextFiles holds the workspace context rendered into system block 2.
	// Session.Reload re-reads it from disk and rebuilds that block; nothing
	// else in the session mutates it.
	ContextFiles config.ContextFiles
	// Skills holds loaded skills for system prompt injection and /skill: commands.
	Skills []skill.Spec
	// SkillCatalog provides indexed skill lookup and reload support.
	SkillCatalog *skill.Catalog
	// SkillUsage persists cross-session usage statistics for prompt ordering.
	SkillUsage *skill.UsageTracker
	// DeferredToolsPreamble is injected as the first user message (once).
	DeferredToolsPreamble string
	// ToolMicrocompact powers the idle cleanup that runs when the prompt cache
	// has expired. Nil disables it. Same strategy instance the ContextEngine
	// uses under token pressure — only the trigger differs.
	ToolMicrocompact *agentctx.ToolResultMicrocompactStrategy
	// SkillAllowsSetter updates temporary tool allows for the active skill.
	SkillAllowsSetter func([]string)

	// ToolOutputRoot is the project's session root. The session appends its own
	// id, so the path follows /new and /resume instead of freezing at boot.
	ToolOutputRoot string

	// FileReadState records read timestamps consumed by write/edit Validators.
	// Held on the Session so Clear / Reset / SwitchSession can drop stale
	// stamps — otherwise the LLM may write based on stamps from a read it
	// no longer has in its conversation history.
	FileReadState *agenttools.FileReadState

	// FrozenIdentity is system block 1's assembly-time value; a worktree
	// retarget recomputes it for the new root. FrozenInstructions is block 2's;
	// a Reload or retarget recomputes it from ContextFiles + Skills +
	// LocalTools. See config.BuildFrozenSystemParts.
	FrozenIdentity     string
	FrozenInstructions string
	// LocalTools is the session-stable local tool inventory as rendered into
	// block 2. Held so a reload can rebuild that block without re-deriving it
	// from the live tool set, which plan mode filters.
	LocalTools []config.ToolInfo
	// InitialMCPOverlay seeds the mcp overlay when the assembly already knows
	// the MCP instructions (e.g. MCP managers that connect synchronously).
	// Written directly into the overlay store without triggering a rebuild.
	InitialMCPOverlay string

	// InitialDynamic is the assembly-time dynamic block text (MCP tool list +
	// overlays). Stored on the session so teammate spawn can read the current
	// snapshot via DynamicSystemBlock() without re-computing. Updated when
	// the prompt rebuilds (overlay change / MCP refresh).
	InitialDynamic string
}

SessionConfig configures a new Session.

type SessionEvent

type SessionEvent struct {
	Type       SessionEventType
	AgentEvent *agentcore.Event

	// Session-level fields (populated based on Type)
	ModelName    string
	Provider     string
	Level        agentcore.ThinkingLevel
	SessionID    string
	Error        error
	Reminder     string
	ReminderKind RuntimeReminderKind
	Goal         goal.State
	GoalPrevious goal.State

	// Retry fields (populated for SEAutoRetryStart / SEAutoRetryEnd)
	RetryAttempt int
	RetryMax     int
	RetryDelay   time.Duration
	RetrySuccess bool

	// Compaction reason: "overflow" or "threshold"
	CompactionReason   string
	CompactionKind     CompactionKind
	CompactionStrategy string
	CompactionChanged  bool
	TokensBefore       int
	TokensAfter        int
	CompactedCount     int
	KeptCount          int
	SplitTurn          bool
}

SessionEvent extends agent events with session-level metadata. When Type == SEAgentEvent, AgentEvent is non-nil.

type SessionEventType

type SessionEventType string

SessionEventType identifies a session-level event.

const (
	// SEAgentEvent wraps an agentcore.Event transparently.
	SEAgentEvent SessionEventType = "agent_event"

	// Session lifecycle events
	SEAutoCompactionStart    SessionEventType = "auto_compaction_start"
	SEAutoCompactionEnd      SessionEventType = "auto_compaction_end"
	SEAutoRetryStart         SessionEventType = "auto_retry_start"
	SEAutoRetryEnd           SessionEventType = "auto_retry_end"
	SEModelChanged           SessionEventType = "model_changed"
	SEReasoningEffortChanged SessionEventType = "reasoning_effort_changed"
	SESessionSwitched        SessionEventType = "session_switched"
	SERuntimeReminder        SessionEventType = "runtime_reminder"
	SEGoalUpdated            SessionEventType = "goal_updated"
	SEGoalCleared            SessionEventType = "goal_cleared"
	SEError                  SessionEventType = "session_error"
)

type Snapshotter added in v0.2.0

type Snapshotter interface {
	// Track records a checkpoint of the current workspace. changed is false
	// when nothing changed since the last checkpoint.
	Track() (changed bool, err error)
	// Undo reverts the workspace to the most recent checkpoint. ok is false
	// when there is nothing to undo; changed lists the affected paths.
	Undo() (changed []string, ok bool, err error)
	// Redo re-applies the most recently undone change. ok is false when there
	// is nothing to redo (no prior undo, or a new edit invalidated the branch).
	Redo() (changed []string, ok bool, err error)
	// DiffTop returns a numstat diff of what Undo would roll back, or "" when
	// there is nothing to undo.
	DiffTop() (string, error)
	// Rebind repoints the tracker at a session's persisted undo stack: it drops
	// the in-memory stack and loads whatever statePath holds. Called on session
	// switch/new so each session gets its own checkpoint history.
	Rebind(statePath string)
	// RebindWorkspace repoints the tracker at a different workspace (shadow
	// gitDir + workTree) and its sidecar, then reloads the persisted stack.
	// Called on worktree enter/exit, where the whole workspace moves — unlike
	// Rebind, which only swaps the sidecar for a same-cwd session switch.
	RebindWorkspace(gitDir, workTree, statePath string)
	// Close waits for any background snapshot maintenance to finish.
	Close()
}

Snapshotter captures and restores workspace file checkpoints for /undo. Implemented by internal/snapshot.Tracker and injected at assembly time, so the agent package stays decoupled from the git-shadow implementation.

type ToolCallSnapshot added in v0.1.0

type ToolCallSnapshot struct {
	Tool      string
	ArgsHash  string
	Success   bool
	Timestamp time.Time
}

type ToolTokenUsage added in v0.1.0

type ToolTokenUsage struct {
	Name         string
	CallTokens   int
	ResultTokens int
	Total        int
}

ToolTokenUsage tracks token consumption for a single tool.

type TurnOutcomeSnapshot added in v0.1.0

type TurnOutcomeSnapshot struct {
	AssistantResponded bool
	ReadOnlyToolCalls  int
	WriteLikeToolCalls int
	TaskMutations      int
	CodeEditToolCalls  int
}

Jump to

Keyboard shortcuts

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