Documentation
¶
Overview ¶
Package session provides session-scoped event emission for the desktop UI.
Package session provides typed event payloads for session lifecycle events.
Package session provides session management for multiple agent sessions.
Package session provides session-scoped event emission and persistence for the desktop UI.
Index ¶
- Constants
- Variables
- func ContextWithSessionID(ctx context.Context, sessionID string) context.Context
- func SessionIDFromContext(ctx context.Context) string
- type AskUserPayload
- type AssistantDoneEventData
- type AttachmentFailure
- type AttachmentInfo
- type AttachmentsChangedData
- type BlackboardState
- type ChatMessage
- type ContextCompactionEventData
- type ContextFillEventData
- type ErrorData
- type Event
- type EventEmitter
- func (e *EventEmitter) AssistantChunk(content string)
- func (e *EventEmitter) AssistantDone(fullContent string, inputTokens, outputTokens int)
- func (e *EventEmitter) ContextCompaction(beforePercent, afterPercent float64, stepID string)
- func (e *EventEmitter) ContextFill(fillPercent float64, usedTokens, maxTokens int, status, stepID string)
- func (e *EventEmitter) EmitSessionTokens(totalIn, totalOut int, model, family string)
- func (e *EventEmitter) ExecutorDiagnostic(stepNum int, event string, details map[string]any)
- func (e *EventEmitter) Finishing(stepNum int, summary string)
- func (e *EventEmitter) GoalProgress(data map[string]any)
- func (e *EventEmitter) GoalStatus(data map[string]any)
- func (e *EventEmitter) MemoryRead(stepNum int, content string)
- func (e *EventEmitter) PlanGenerated(stepCount int, steps []orchestration.PlanStepEvent)
- func (e *EventEmitter) PlanStepComplete(stepID string, success bool, duration time.Duration, errMsg string)
- func (e *EventEmitter) PlanStepStart(stepID, description, summary string)
- func (e *EventEmitter) Reflection(reflection *orchestration.Reflection, attempt, maxAttempts int)
- func (e *EventEmitter) ReplanFailed(err error)
- func (e *EventEmitter) Retry(attempt, maxAttempts int)
- func (e *EventEmitter) Routing(mode, domain, complexity string)
- func (e *EventEmitter) Service(content string)
- func (e *EventEmitter) ServiceWithMeta(content string, meta map[string]any)
- func (e *EventEmitter) SessionTokenTotals() (inputTokens, outputTokens int)
- func (e *EventEmitter) SetAttachmentNameResolver(resolve func(attachmentID string) string)
- func (e *EventEmitter) SetCurrentStepID(id string)
- func (e *EventEmitter) SetDisplayContextWindow(window int)
- func (e *EventEmitter) SetLastModel(model, family string)
- func (e *EventEmitter) SetTokenPersist(...)
- func (e *EventEmitter) SetToolCallIDSink(fn func(tool, toolCallID string))
- func (e *EventEmitter) SkillsActivated(skillNames []string)
- func (e *EventEmitter) StepComplete(stepNum int, duration time.Duration)
- func (e *EventEmitter) StepRetry(stepID string, attempt, maxAttempts int)
- func (e *EventEmitter) StepStart(stepNum int)
- func (e *EventEmitter) StepTodoUpdate(stepID string, items []agent.TodoItem)
- func (e *EventEmitter) SubAgentComplete(stepID string, success bool, duration time.Duration)
- func (e *EventEmitter) SubAgentLaunch(stepID, description string)
- func (e *EventEmitter) Thought(stepNum int, content, reasoning string)
- func (e *EventEmitter) ToolCall(stepNum, callIdx int, toolName, argsPreview, source string)
- func (e *EventEmitter) ToolResult(stepNum, callIdx, resultLen int, preview string, isError bool)
- func (e *EventEmitter) ToolsAssigned(toolNames []string)
- func (e *EventEmitter) WithPlanStepID(id string) core.Emitter
- func (e *EventEmitter) WithRetryAttempt(attempt int) core.Emitter
- type EventPersister
- type FileCoherenceTracker
- func (t *FileCoherenceTracker) CheckRead(ctx context.Context, path string) *sdktools.CoherenceConflict
- func (t *FileCoherenceTracker) CheckWrite(ctx context.Context, path string) *sdktools.CoherenceConflict
- func (t *FileCoherenceTracker) Lock(path string)
- func (t *FileCoherenceTracker) PurgeSession(sessionID string)
- func (t *FileCoherenceTracker) RecordDelete(ctx context.Context, path string)
- func (t *FileCoherenceTracker) RecordWrite(ctx context.Context, path string)
- func (t *FileCoherenceTracker) Unlock(path string)
- type ForkReviewCloner
- type GoalProposalPayload
- type ImageAttachment
- type JudgeRequestPayload
- type JudgeResponsePayload
- type LLMTitleCaller
- type Manager
- func (m *Manager) ArchiveSession(id string) error
- func (m *Manager) AttachFiles(ctx context.Context, sessionID string, paths []string) ([]AttachmentInfo, error)
- func (m *Manager) CancelTask(id string) error
- func (m *Manager) CancelUnfinishedTask(sessionID string) error
- func (m *Manager) ClearGoal(sessionID string) error
- func (m *Manager) CreateSession(projectID, workspacePath string) (*SessionInfo, error)
- func (m *Manager) DeleteSession(id string) error
- func (m *Manager) EmitSessionEvent(sessionID, eventType string, data any)
- func (m *Manager) GetBlackboardState(sessionID string) (*BlackboardState, error)
- func (m *Manager) GetSession(id string) (*Session, bool)
- func (m *Manager) GetSessionAttachments(sessionID string) ([]AttachmentInfo, error)
- func (m *Manager) GetSessionRuntimeStatus(sessionID string) (SessionRuntimeStatus, error)
- func (m *Manager) GetSessionWorkspacePath(id string) (string, bool)
- func (m *Manager) InvalidateIgnoreCache(changedPaths []string)
- func (m *Manager) LastToolCallID(sessionID string) (id, tool string)
- func (m *Manager) ListSessions() []SessionInfo
- func (m *Manager) ListSessionsByProject(projectID string) ([]SessionInfo, error)
- func (m *Manager) PauseGoal(sessionID string) error
- func (m *Manager) PendingImageAttachments(sessionID string) ([]ImageAttachment, error)
- func (m *Manager) PendingImageMetadata(sessionID string) (json.RawMessage, error)
- func (m *Manager) PinSession(id string) error
- func (m *Manager) RemovePendingAttachment(sessionID, attachmentID string) error
- func (m *Manager) RenameSession(id, name string) error
- func (m *Manager) ResolveGoalProposal(requestID, decision, condition, verify, verificationMode string) bool
- func (m *Manager) ResumeGoal(ctx context.Context, sessionID, modelOverride, reasoningEffort string) error
- func (m *Manager) ResumeTask(ctx context.Context, id, modelOverride, reasoningEffort string) error
- func (m *Manager) SendMessage(ctx context.Context, id, text string, activeSkills, activeAgents []string, ...) error
- func (m *Manager) SetEnvInfo(info *sdktools.EnvInfo)
- func (m *Manager) SetFactory(factory OrchestratorFactory)
- func (m *Manager) SetGoalProposalResolver(fn func(requestID, decision, condition, verify, verificationMode string) bool)
- func (m *Manager) SetLogLevel(level string)
- func (m *Manager) SetLogger(l *slog.Logger)
- func (m *Manager) SetMaxSummaryLen(n int)
- func (m *Manager) SetProjectResolver(fn ProjectResolverFunc)
- func (m *Manager) SetProjectStore(store project.ProjectStore)
- func (m *Manager) SetSessionStore(store SessionStore)
- func (m *Manager) SetTaskStore(store TaskStore)
- func (m *Manager) SetTitleGenerator(gen *TitleGenerator)
- func (m *Manager) SetTokenPersist(fn TokenPersistFunc)
- func (m *Manager) Shutdown()
- func (m *Manager) StartEnvInfoCollection()
- func (m *Manager) WaitEnvInfo(ctx context.Context) error
- type MessageReceivedData
- type OrchestratorFactory
- type PersistentBlackboard
- func NewPersistentBlackboard(taskID, sessionID string, store core.TaskPersistence, logger *slog.Logger, ...) *PersistentBlackboard
- func NewPersistentBlackboardWithTimeout(taskID, sessionID string, store core.TaskPersistence, logger *slog.Logger, ...) *PersistentBlackboard
- func RestoreBlackboard(taskID, sessionID string, store core.TaskPersistence, logger *slog.Logger, ...) (*PersistentBlackboard, error)
- func (pb *PersistentBlackboard) AddAttachment(a orchestration.Attachment)
- func (pb *PersistentBlackboard) AddReflection(r orchestration.Reflection)
- func (pb *PersistentBlackboard) CancelTask()
- func (pb *PersistentBlackboard) CompleteTask(attemptCount int)
- func (pb *PersistentBlackboard) FailTask()
- func (pb *PersistentBlackboard) ReactivateTask()
- func (pb *PersistentBlackboard) RemoveAttachment(id string) bool
- func (pb *PersistentBlackboard) Routing() *router.RoutingDecision
- func (pb *PersistentBlackboard) SetEmitter(emitter core.Emitter)
- func (pb *PersistentBlackboard) SetFinalResult(result string)
- func (pb *PersistentBlackboard) SetOnChanged(fn func(changeType string))
- func (pb *PersistentBlackboard) SetOriginalRequest(req string)
- func (pb *PersistentBlackboard) SetPlan(plan *orchestration.Plan)
- func (pb *PersistentBlackboard) SetRouting(routing *router.RoutingDecision)
- func (pb *PersistentBlackboard) SetStepResult(stepID, output string, err error, steps []agent.Step)
- func (pb *PersistentBlackboard) StoreFact(fact orchestration.Fact)
- func (pb *PersistentBlackboard) TaskID() string
- type PlanApprovalPayload
- type PlanApprovalResponsePayload
- type ProjectResolverFunc
- type SQLiteSessionStore
- func (s *SQLiteSessionStore) AddTaskReflection(ctx context.Context, taskID string, reflectionJSON json.RawMessage) error
- func (s *SQLiteSessionStore) ArchiveSession(ctx context.Context, id string, archived bool) error
- func (s *SQLiteSessionStore) CancelTask(ctx context.Context, taskID string) error
- func (s *SQLiteSessionStore) Close() error
- func (s *SQLiteSessionStore) CompleteTask(ctx context.Context, taskID, finalOutput string, attemptCount int) error
- func (s *SQLiteSessionStore) DeleteMessages(ctx context.Context, sessionID string) error
- func (s *SQLiteSessionStore) DeleteSession(ctx context.Context, id string) error
- func (s *SQLiteSessionStore) DeleteSessionWorkDir(ctx context.Context, sessionID, id string) error
- func (s *SQLiteSessionStore) FailTask(ctx context.Context, taskID string) error
- func (s *SQLiteSessionStore) ForkSession(ctx context.Context, srcID string, cloneReview ForkReviewCloner) (*SessionInfo, error)
- func (s *SQLiteSessionStore) GetLatestTaskID(ctx context.Context, sessionID string) (string, error)
- func (s *SQLiteSessionStore) GetUnfinishedTask(ctx context.Context, sessionID string) (*TaskRecord, error)
- func (s *SQLiteSessionStore) ListSessionWorkDirs(ctx context.Context, sessionID string) ([]project.WorkDirectoryRecord, error)
- func (s *SQLiteSessionStore) ListSessions(ctx context.Context) ([]SessionInfo, error)
- func (s *SQLiteSessionStore) ListSessionsByProject(ctx context.Context, projectID string) ([]SessionInfo, error)
- func (s *SQLiteSessionStore) LoadAttachments(ctx context.Context, taskID string) (json.RawMessage, error)
- func (s *SQLiteSessionStore) LoadFacts(ctx context.Context, taskID string) (json.RawMessage, error)
- func (s *SQLiteSessionStore) LoadGoalState(ctx context.Context, taskID string) (json.RawMessage, error)
- func (s *SQLiteSessionStore) LoadMessages(ctx context.Context, sessionID string) ([]ChatMessage, error)
- func (s *SQLiteSessionStore) LoadSession(ctx context.Context, id string) (*SessionInfo, error)
- func (s *SQLiteSessionStore) LoadTask(ctx context.Context, taskID string) (*TaskRecord, error)
- func (s *SQLiteSessionStore) LoadTaskSteps(ctx context.Context, taskID string) ([]TaskStepRecord, error)
- func (s *SQLiteSessionStore) LoadTerminalCommands(ctx context.Context, sessionID string, limit int) ([]TerminalCommand, error)
- func (s *SQLiteSessionStore) LoadTrajectory(ctx context.Context, taskID string) (json.RawMessage, error)
- func (s *SQLiteSessionStore) PinSession(ctx context.Context, id string, pinned bool) error
- func (s *SQLiteSessionStore) ReactivateTask(ctx context.Context, taskID string) error
- func (s *SQLiteSessionStore) RenameSession(ctx context.Context, id, name string) error
- func (s *SQLiteSessionStore) ResolvePendingMessage(ctx context.Context, sessionID, role, matchField, matchValue string, ...) error
- func (s *SQLiteSessionStore) SaveAttachments(ctx context.Context, taskID string, attachmentsJSON json.RawMessage) error
- func (s *SQLiteSessionStore) SaveFacts(ctx context.Context, taskID string, factsJSON json.RawMessage) error
- func (s *SQLiteSessionStore) SaveGoalState(ctx context.Context, taskID string, goalStateJSON json.RawMessage) error
- func (s *SQLiteSessionStore) SaveMessage(ctx context.Context, msg ChatMessage) error
- func (s *SQLiteSessionStore) SaveSession(ctx context.Context, info SessionInfo) error
- func (s *SQLiteSessionStore) SaveSessionWorkDir(ctx context.Context, sessionID string, rec project.WorkDirectoryRecord) error
- func (s *SQLiteSessionStore) SaveTask(ctx context.Context, task TaskRecord) error
- func (s *SQLiteSessionStore) SaveTaskStep(ctx context.Context, taskID string, step TaskStepRecord) error
- func (s *SQLiteSessionStore) SaveTerminalCommand(ctx context.Context, sessionID, command string) error
- func (s *SQLiteSessionStore) SaveTrajectory(ctx context.Context, taskID string, stepsJSON json.RawMessage) error
- func (s *SQLiteSessionStore) SetLogger(l *slog.Logger)
- func (s *SQLiteSessionStore) UpdateSessionActivity(ctx context.Context, id string) error
- func (s *SQLiteSessionStore) UpdateSessionTokens(ctx context.Context, id string, inputTokens, outputTokens int, ...) error
- func (s *SQLiteSessionStore) UpdateSessionWorkDirDescription(ctx context.Context, sessionID, id, description string) error
- func (s *SQLiteSessionStore) UpdateTaskPlan(ctx context.Context, taskID string, plan json.RawMessage) error
- func (s *SQLiteSessionStore) UpdateTaskRouting(ctx context.Context, taskID string, routing json.RawMessage) error
- type Session
- type SessionArchivedData
- type SessionCreatedData
- type SessionDeletedData
- type SessionInfo
- type SessionPinnedData
- type SessionRenamedData
- type SessionRuntimeStatus
- type SessionStore
- type SessionTokensEventData
- type SkillsActivatedData
- type StepLimitPayload
- type StepLimitResponsePayload
- type StoredImageMetadata
- type StoredImagesMetadata
- type TaskCancelledData
- type TaskCompleteData
- type TaskFailedResumableData
- type TaskRecord
- type TaskStepRecord
- type TaskStore
- type TaskStoreAdapter
- func (a *TaskStoreAdapter) GetLatestTaskID(sessionID string) (string, error)
- func (a *TaskStoreAdapter) GetUnfinishedTaskID(sessionID string) (string, error)
- func (a *TaskStoreAdapter) LoadGoalState(taskID string) (*goal.GoalState, error)
- func (a *TaskStoreAdapter) LoadTaskState(taskID string) (*core.TaskState, error)
- func (a *TaskStoreAdapter) LoadTrajectory(taskID string) ([]agent.Step, error)
- func (a *TaskStoreAdapter) PersistAttachments(taskID string, attachments []orchestration.Attachment) error
- func (a *TaskStoreAdapter) PersistCancellation(taskID string) error
- func (a *TaskStoreAdapter) PersistCompletion(taskID, finalOutput string, attemptCount int) error
- func (a *TaskStoreAdapter) PersistFacts(taskID string, facts []orchestration.Fact) error
- func (a *TaskStoreAdapter) PersistFailure(taskID string) error
- func (a *TaskStoreAdapter) PersistGoalState(taskID string, gs *goal.GoalState) error
- func (a *TaskStoreAdapter) PersistNewTask(taskID, sessionID, originalRequest string) error
- func (a *TaskStoreAdapter) PersistPlan(taskID string, plan *orchestration.Plan) error
- func (a *TaskStoreAdapter) PersistReflection(taskID string, r orchestration.Reflection) error
- func (a *TaskStoreAdapter) PersistRouting(taskID string, routing *router.RoutingDecision) error
- func (a *TaskStoreAdapter) PersistStepResult(taskID, stepID, summary, fullOutput, errorText string, steps []agent.Step) error
- func (a *TaskStoreAdapter) ReactivateTask(taskID string) error
- func (a *TaskStoreAdapter) SaveTrajectory(taskID string, steps []agent.Step) error
- type TerminalCommand
- type ThoughtEventData
- type TitleGenerator
- type TokenPersistFunc
- type ToolConfirmPayload
- type ToolsAssignedData
Constants ¶
const ( EventStepLimit = "step_limit" EventStepLimitResponse = "step_limit_response" )
Event type constants for backend-to-frontend communication.
const SessionIDKey contextKey = "session_id"
SessionIDKey is the context key for the session ID.
Variables ¶
var ErrNoActiveTask = errors.New("no active task to cancel")
ErrNoActiveTask is returned by CancelTask when the session has no task currently running. Callers that don't care whether a task was actually cancelled (e.g. ClearGoal, which only needs the task stopped so it can persist a terminal goal state) can treat this as non-fatal via errors.Is.
Functions ¶
func ContextWithSessionID ¶
ContextWithSessionID returns a new context with the session ID attached.
func SessionIDFromContext ¶
SessionIDFromContext returns the session ID from the context, or an empty string if not found.
Types ¶
type AskUserPayload ¶
type AskUserPayload struct {
RequestID string `json:"request_id"`
Questions []coretools.AskUserQuestion `json:"questions"`
}
AskUserPayload is sent to the frontend when the agent asks the user questions.
type AssistantDoneEventData ¶
type AssistantDoneEventData struct {
Content string `json:"content"`
InputTokens int `json:"input_tokens"`
OutputTokens int `json:"output_tokens"`
PlanStepID string `json:"plan_step_id,omitempty"`
}
AssistantDoneEventData is the typed Data payload for "assistant_done" events.
type AttachmentFailure ¶
AttachmentFailure describes a single file that could not be converted or staged, surfaced to the UI so the user knows which picks were rejected.
type AttachmentInfo ¶
type AttachmentInfo struct {
ID string `json:"id"`
OriginalName string `json:"original_name"`
Format string `json:"format"`
SizeBytes int64 `json:"size_bytes"`
IsImage bool `json:"is_image"`
Thumbnail string `json:"thumbnail,omitempty"` // JPEG data URI for image attachments
}
AttachmentInfo is a JSON-friendly, metadata-only view of a pending attachment. The converted markdown content is intentionally excluded so it is never leaked to the UI (only the orchestrator reads it via the blackboard).
type AttachmentsChangedData ¶
type AttachmentsChangedData struct {
Attachments []AttachmentInfo `json:"attachments"`
Failed []AttachmentFailure `json:"failed,omitempty"`
}
AttachmentsChangedData is the payload of the "attachments:changed" session event. Attachments is the full current pending list — the UI replaces its store on every event. Failed carries per-file failures from the most recent attach operation (absent on remove/send-clear events).
type BlackboardState ¶
BlackboardState wraps a core.TaskState for the GetBlackboardState API.
type ChatMessage ¶
type ChatMessage struct {
ID int64 `json:"id"`
SessionID string `json:"session_id"`
Role string `json:"role"` // "user", "assistant", "tool_call", "tool_result", "routing", "eval", "reflection", "error"
Content string `json:"content"`
ReasoningContent *string `json:"reasoning_content,omitempty"` // chain-of-thought / reasoning content (DeepSeek)
ToolCalls *json.RawMessage `json:"tool_calls,omitempty"` // JSON-encoded tool calls (for assistant)
Metadata json.RawMessage `json:"metadata"` // JSON blob for extra data
CreatedAt string `json:"created_at"` // RFC 3339 formatted timestamp
}
ChatMessage represents a stored chat message.
type ContextCompactionEventData ¶
type ContextCompactionEventData struct {
BeforePercent float64 `json:"before_percent"`
AfterPercent float64 `json:"after_percent"`
PlanStepID string `json:"plan_step_id,omitempty"`
}
ContextCompactionEventData is the typed Data payload for "context_compaction" events.
type ContextFillEventData ¶
type ContextFillEventData struct {
FillPercent float64 `json:"fill_percent"`
UsedTokens int `json:"used_tokens"`
MaxTokens int `json:"max_tokens"`
Status string `json:"status"`
PlanStepID string `json:"plan_step_id,omitempty"`
SessionInputTokens int `json:"session_input_tokens"`
SessionOutputTokens int `json:"session_output_tokens"`
Model string `json:"model"`
Family string `json:"family"`
}
ContextFillEventData is the typed Data payload for "context_fill" events.
type Event ¶
type Event struct {
SessionID string `json:"session_id"`
Type string `json:"type"`
Data any `json:"data"`
}
Event represents a structured event emitted during agent execution.
type EventEmitter ¶
type EventEmitter struct {
// contains filtered or unexported fields
}
EventEmitter implements core.Emitter and routes events to a callback function.
Lock ordering: tokens.mu must be acquired BEFORE e.mu to avoid deadlocks. Methods that need both (e.g. AssistantDone, EmitSessionTokens, ContextFill) always lock tokens.mu first, then e.mu.
func NewEventEmitter ¶
func NewEventEmitter(sessionID string, emit func(Event)) *EventEmitter
NewEventEmitter creates a new EventEmitter for a session.
func (*EventEmitter) AssistantChunk ¶
func (e *EventEmitter) AssistantChunk(content string)
AssistantChunk emits an assistant response chunk for streaming. It accumulates all chunks and emits both the delta and the full accumulated content so the frontend can simply SET the content instead of appending.
func (*EventEmitter) AssistantDone ¶
func (e *EventEmitter) AssistantDone(fullContent string, inputTokens, outputTokens int)
AssistantDone emits an assistant response completion event and resets the accumulator. Token accumulation is handled by the UsageTracker; session totals are cached in tokenState.
func (*EventEmitter) ContextCompaction ¶
func (e *EventEmitter) ContextCompaction(beforePercent, afterPercent float64, stepID string)
ContextCompaction emits a context compaction event with before/after fill percentages.
func (*EventEmitter) ContextFill ¶
func (e *EventEmitter) ContextFill(fillPercent float64, usedTokens, maxTokens int, status, stepID string)
ContextFill emits a context fill status event, enriched with session-level token totals.
The executor reports fill relative to its internal "effective max" (context window − output limit − safety margin), which is the ceiling the agent's compaction logic manages against. The user-facing display, however, must reflect the model's advertised context window so the status bar never exposes internal compaction thresholds. When a display context window has been injected via SetDisplayContextWindow, the percent and max are recomputed relative to that real window before emission and caching.
func (*EventEmitter) EmitSessionTokens ¶
func (e *EventEmitter) EmitSessionTokens(totalIn, totalOut int, model, family string)
EmitSessionTokens emits a "session_tokens" event with the given totals. This is called by the UsageTracker observer — accumulation is handled externally. The context-window fill percent and used/max token counts are read from the shared cache (updated only by the session-root emitter in ContextFill) and forwarded for persistence and display.
func (*EventEmitter) ExecutorDiagnostic ¶
func (e *EventEmitter) ExecutorDiagnostic(stepNum int, event string, details map[string]any)
ExecutorDiagnostic logs an internal executor diagnostic at DEBUG level. These are internal diagnostics, not user-facing events.
func (*EventEmitter) Finishing ¶
func (e *EventEmitter) Finishing(stepNum int, summary string)
Finishing emits a finishing event when the agent calls the finish tool. The frontend uses this to show "Finishing..." status instead of "Running tool: finish".
func (*EventEmitter) GoalProgress ¶ added in v0.4.0
func (e *EventEmitter) GoalProgress(data map[string]any)
GoalProgress emits a dedicated goal_progress session event with turn/budget telemetry, emitted mid-loop (after a non-terminal turn) so the frontend can show live progress toward the budget.
func (*EventEmitter) GoalStatus ¶ added in v0.4.0
func (e *EventEmitter) GoalStatus(data map[string]any)
GoalStatus emits a dedicated goal_status session event carrying the full goal state snapshot. Unlike the phase-discriminated `service` channel, it is its own event type so the frontend's live subscription reliably reaches the goal store (the goal status indicator + turn transitions).
func (*EventEmitter) MemoryRead ¶
func (e *EventEmitter) MemoryRead(stepNum int, content string)
MemoryRead emits a memory_read event when the agent reads from its persistent memory.
func (*EventEmitter) PlanGenerated ¶
func (e *EventEmitter) PlanGenerated(stepCount int, steps []orchestration.PlanStepEvent)
PlanGenerated emits a plan generation event with initial progress info.
func (*EventEmitter) PlanStepComplete ¶
func (e *EventEmitter) PlanStepComplete(stepID string, success bool, duration time.Duration, errMsg string)
PlanStepComplete emits a plan step completion event with updated progress.
func (*EventEmitter) PlanStepStart ¶
func (e *EventEmitter) PlanStepStart(stepID, description, summary string)
PlanStepStart emits a plan step start event with progress info. Duplicate calls for the same step ID are suppressed — the event is emitted only the first time a step starts. This lets both the Conductor's inline todo callback and the subagent launcher call PlanStepStart without worrying about double-emission.
func (*EventEmitter) Reflection ¶
func (e *EventEmitter) Reflection(reflection *orchestration.Reflection, attempt, maxAttempts int)
Reflection emits a reflection event.
func (*EventEmitter) ReplanFailed ¶
func (e *EventEmitter) ReplanFailed(err error)
ReplanFailed logs a failed replan attempt.
func (*EventEmitter) Retry ¶
func (e *EventEmitter) Retry(attempt, maxAttempts int)
Retry emits a retry event.
func (*EventEmitter) Routing ¶
func (e *EventEmitter) Routing(mode, domain, complexity string)
Routing emits a routing decision event.
func (*EventEmitter) Service ¶
func (e *EventEmitter) Service(content string)
Service emits a general service message without metadata.
func (*EventEmitter) ServiceWithMeta ¶
func (e *EventEmitter) ServiceWithMeta(content string, meta map[string]any)
ServiceWithMeta emits a service message with metadata for frontend filtering.
func (*EventEmitter) SessionTokenTotals ¶
func (e *EventEmitter) SessionTokenTotals() (inputTokens, outputTokens int)
SessionTokenTotals returns the accumulated session-wide input and output token counts.
func (*EventEmitter) SetAttachmentNameResolver ¶
func (e *EventEmitter) SetAttachmentNameResolver(resolve func(attachmentID string) string)
SetAttachmentNameResolver wires a resolver that maps a read_attachment attachment_id to its original file name, used to enrich read_attachment tool-call events (and their persisted metadata) so cards render the file name even after restart. Wired per-task by the orchestrator from the blackboard. Scoped copies (WithPlanStepID/WithRetryAttempt) inherit the same resolver so subagents/retries resolve names against the shared blackboard.
func (*EventEmitter) SetCurrentStepID ¶
func (e *EventEmitter) SetCurrentStepID(id string)
SetCurrentStepID dynamically updates the plan_step_id injected into subsequent events emitted by this receiver. Unlike WithPlanStepID (which returns a scoped copy with a fixed planStepID), SetCurrentStepID mutates the receiver in place — use it to track the "current step" during inline Conductor execution, where a single emitter instance serves the whole ReAct loop and the active step changes via update_checklist / declare_step_complete tool calls. Pass an empty string to clear the scope.
Scoped copies created by WithPlanStepID have their own planStepID field and are unaffected by calls to this method on the original emitter.
func (*EventEmitter) SetDisplayContextWindow ¶
func (e *EventEmitter) SetDisplayContextWindow(window int)
SetDisplayContextWindow injects the model's advertised context-window size so ContextFill presents fill relative to the real window rather than the executor's internal "effective max" (window − output limit − safety margin). The orchestrator calls this after resolving the model meta, before the first context_fill. A value <= 0 clears the override and falls back to the executor-reported max.
func (*EventEmitter) SetLastModel ¶ added in v0.4.0
func (e *EventEmitter) SetLastModel(model, family string)
SetLastModel updates the cached model/family so that subsequent context_fill events report the newly-selected model immediately, before the first LLM call reports actual usage via the UsageTracker observer. It is invoked by the orchestrator's ApplyRequestOverrides when a per-request model override is applied, so the status bar does not show the previous task's stale model during a continuation or resume. A no-op when model is empty.
func (*EventEmitter) SetTokenPersist ¶
func (e *EventEmitter) SetTokenPersist(fn func(inputTokens, outputTokens int, model, family string, fillPercent float64))
SetTokenPersist sets a callback that is invoked with cumulative session token totals each time the UsageTracker observer fires. Use this to persist tokens to the store without introducing a direct store dependency in the emitter.
func (*EventEmitter) SetToolCallIDSink ¶
func (e *EventEmitter) SetToolCallIDSink(fn func(tool, toolCallID string))
SetToolCallIDSink registers a callback invoked after each ToolCall with the tool name and the generated tool_call_id. The session Manager sets it so the desktop-layer confirmation callback can attach the matching tool_call_id to the tool_confirm payload, enabling precise tool_call ↔ tool_confirm correlation on the frontend (instead of matching by tool name, which is ambiguous when two calls share a name). The sink lives on the shared gen, so scoped copies (WithPlanStepID/WithRetryAttempt) report to the same store.
func (*EventEmitter) SkillsActivated ¶
func (e *EventEmitter) SkillsActivated(skillNames []string)
SkillsActivated emits a skills_activated event listing the skills matched for the current task.
func (*EventEmitter) StepComplete ¶
func (e *EventEmitter) StepComplete(stepNum int, duration time.Duration)
StepComplete emits a step completion event.
func (*EventEmitter) StepRetry ¶
func (e *EventEmitter) StepRetry(stepID string, attempt, maxAttempts int)
StepRetry emits a step retry event.
func (*EventEmitter) StepStart ¶
func (e *EventEmitter) StepStart(stepNum int)
StepStart emits a step start event.
func (*EventEmitter) StepTodoUpdate ¶
func (e *EventEmitter) StepTodoUpdate(stepID string, items []agent.TodoItem)
StepTodoUpdate emits a step_todo_update event with the current checklist. stepID may be empty for a standalone checklist (Conductor without a plan).
func (*EventEmitter) SubAgentComplete ¶
func (e *EventEmitter) SubAgentComplete(stepID string, success bool, duration time.Duration)
SubAgentComplete emits a subagent completion event.
func (*EventEmitter) SubAgentLaunch ¶
func (e *EventEmitter) SubAgentLaunch(stepID, description string)
SubAgentLaunch emits a subagent launch event.
func (*EventEmitter) Thought ¶
func (e *EventEmitter) Thought(stepNum int, content, reasoning string)
Thought emits a thought event for LLM reasoning.
func (*EventEmitter) ToolCall ¶
func (e *EventEmitter) ToolCall(stepNum, callIdx int, toolName, argsPreview, source string)
ToolCall emits a tool call event. If argsPreview is valid JSON, a pre-parsed map is included as "parsed_args" so the frontend doesn't need to JSON.parse() at render time.
func (*EventEmitter) ToolResult ¶
func (e *EventEmitter) ToolResult(stepNum, callIdx, resultLen int, preview string, isError bool)
ToolResult emits a tool result event.
func (*EventEmitter) ToolsAssigned ¶ added in v0.5.0
func (e *EventEmitter) ToolsAssigned(toolNames []string)
ToolsAssigned emits a tools_assigned event listing the tools curated for the session by Small-LLM domain narrowing (mirrors SkillsActivated's card).
func (*EventEmitter) WithPlanStepID ¶
func (e *EventEmitter) WithPlanStepID(id string) core.Emitter
WithPlanStepID returns a shallow copy of the emitter with planStepID set. Events emitted by the copy will include "plan_step_id" in their Data map.
func (*EventEmitter) WithRetryAttempt ¶
func (e *EventEmitter) WithRetryAttempt(attempt int) core.Emitter
WithRetryAttempt returns a shallow copy of the emitter with retryAttempt set. Events emitted by the copy will include "retry_attempt" in their Data map when > 0.
type EventPersister ¶
type EventPersister struct {
// contains filtered or unexported fields
}
EventPersister persists chat-visible events to the session store (SQLite). It is decoupled from the UI — the desktop layer is responsible for emitting Wails events separately.
func NewEventPersister ¶
func NewEventPersister(store SessionStore) *EventPersister
NewEventPersister creates a new EventPersister backed by the given store. If store is nil, Persist is a no-op.
func (*EventPersister) Persist ¶
func (p *EventPersister) Persist(evt Event)
Persist saves a chat-visible event to the session store. Transient events (session_tokens, etc.) are silently skipped. Errors are logged but never returned — persistence is best-effort.
func (*EventPersister) SetLogger ¶
func (p *EventPersister) SetLogger(l *slog.Logger)
SetLogger sets the logger for the event persister.
type FileCoherenceTracker ¶
type FileCoherenceTracker struct {
// contains filtered or unexported fields
}
FileCoherenceTracker detects cross-session file conflicts by tracking per-session file signatures and comparing them before read/write operations. It implements sdktools.FileCoherenceChecker.
Lock ordering: t.mu must be acquired BEFORE t.fileMu to avoid deadlocks. pruneOrphanFileMutexesLocked follows this ordering (caller holds t.mu, then it acquires t.fileMu internally).
func NewFileCoherenceTracker ¶
func NewFileCoherenceTracker(nameResolver func(string) string) *FileCoherenceTracker
NewFileCoherenceTracker creates a new tracker instance. nameResolver should return a human-readable session name given a session ID.
func (*FileCoherenceTracker) CheckRead ¶
func (t *FileCoherenceTracker) CheckRead(ctx context.Context, path string) *sdktools.CoherenceConflict
CheckRead checks if the file at path changed since this session last read it. Always updates the session's snapshot to the current on-disk state. Returns nil on first read or when the file has not changed.
func (*FileCoherenceTracker) CheckWrite ¶
func (t *FileCoherenceTracker) CheckWrite(ctx context.Context, path string) *sdktools.CoherenceConflict
CheckWrite checks if the file at path changed since this session last read it. Does NOT update the snapshot. Returns nil if no prior read exists.
func (*FileCoherenceTracker) Lock ¶
func (t *FileCoherenceTracker) Lock(path string)
Lock acquires a per-file mutex for the given path.
func (*FileCoherenceTracker) PurgeSession ¶
func (t *FileCoherenceTracker) PurgeSession(sessionID string)
PurgeSession removes all tracked state for a session.
func (*FileCoherenceTracker) RecordDelete ¶
func (t *FileCoherenceTracker) RecordDelete(ctx context.Context, path string)
RecordDelete removes all session snapshots for the given path and logs the deletion.
func (*FileCoherenceTracker) RecordWrite ¶
func (t *FileCoherenceTracker) RecordWrite(ctx context.Context, path string)
RecordWrite updates the session's snapshot and logs the write in the activity buffer.
func (*FileCoherenceTracker) Unlock ¶
func (t *FileCoherenceTracker) Unlock(path string)
Unlock releases the per-file mutex for the given path.
type ForkReviewCloner ¶
type ForkReviewCloner func(ctx context.Context, tx *sql.Tx, srcSessionID, dstSessionID string) error
ForkReviewCloner copies review data from the source session to the forked session within the fork transaction (tx). It is invoked inside ForkSession's transaction so a review-copy failure aborts the entire fork (rolled back). A nil callback skips review cloning. The review store implements it via CloneReviewTx, sharing the caller's transaction because both stores are backed by the same *sql.DB.
type GoalProposalPayload ¶
type GoalProposalPayload struct {
RequestID string `json:"request_id"`
SessionID string `json:"session_id"`
Condition string `json:"condition"`
Verify string `json:"verify"`
// VerificationMode is the per-goal verification mode the derivation agent
// chose (see goal.VerificationMode* constants). Echoed from the proposal so
// the frontend can surface it and round-trip a user edit back into the
// resolver. Empty means the default (executable).
VerificationMode string `json:"verification_mode,omitempty"`
}
GoalProposalPayload is sent to the frontend when the derivation agent calls propose_goal to submit a candidate {condition, verify} goal for user sign-off. It surfaces as a pending action that blocks the agent until the user responds.
type ImageAttachment ¶ added in v0.4.0
type ImageAttachment struct {
ID string `json:"id"`
OriginalName string `json:"original_name"`
MediaType string `json:"media_type"` // MIME type, e.g. "image/jpeg"
Base64Data string `json:"-"` // base64-encoded image data (in-memory only, not persisted to DB)
ThumbnailB64 string `json:"thumbnail"` // JPEG data URI for UI display
FilePath string `json:"path"` // absolute path to the saved processed image (session/images/{uuid}.jpg)
SizeBytes int64 `json:"size_bytes"`
}
ImageAttachment represents a user-attached image that has been processed (decoded, optionally resized) and saved to the session's images directory. Unlike document attachments (orchestration.Attachment, converted to markdown), images are passed to the LLM as image content blocks rather than read-only text context. The Base64Data is held in memory only until the next SendMessage snapshots it into ContentBlocks; the persisted copy lives on disk at FilePath and is reconstructed from there on restart (thumbnail + path are stored in ChatMessage.Metadata, never the full base64).
type JudgeRequestPayload ¶
type JudgeRequestPayload struct {
ConfirmID string `json:"confirm_id"`
}
JudgeRequestPayload is received from the frontend when the user requests an on-demand judge verdict.
type JudgeResponsePayload ¶
type JudgeResponsePayload struct {
ConfirmID string `json:"confirm_id"`
Reasoning string `json:"reasoning"`
Error string `json:"error,omitempty"`
}
JudgeResponsePayload is sent to the frontend with the judge's verdict.
type LLMTitleCaller ¶
type LLMTitleCaller interface {
GenerateTitle(ctx context.Context, userMessage string, activeSkills []string) (string, error)
}
LLMTitleCaller is the interface for making LLM calls for title generation. This avoids importing github.com/v0lka/sp4rk/llm in the backend layer.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager manages multiple agent sessions.
func NewManager ¶
func NewManager(factory OrchestratorFactory, emitFunc func(Event), agentDir string) *Manager
NewManager creates a new session Manager.
func (*Manager) ArchiveSession ¶
ArchiveSession toggles the archived flag.
func (*Manager) AttachFiles ¶
func (m *Manager) AttachFiles(ctx context.Context, sessionID string, paths []string) ([]AttachmentInfo, error)
AttachFiles converts each supported file at the given paths to markdown via markitdown, stages the resulting attachments on the session (to be flushed into the blackboard on the next SendMessage), and returns metadata for the successfully attached files.
An "attachments:changed" event is emitted after each successful conversion (incremental UI feedback) and once more at the end carrying any per-file failures in the Failed field. The method returns a non-nil error only for system-level failures (session not found, converter init). File-level failures (unsupported format, conversion error) are reported via the event payload — not as an error — so partial success does not discard the attached files or trigger a generic error toast.
func (*Manager) CancelTask ¶
CancelTask cancels the currently running task in a session. It signals cancellation and waits (with timeout) for the task goroutine to finish.
func (*Manager) CancelUnfinishedTask ¶
CancelUnfinishedTask discards any unfinished task in the given session by marking it as cancelled in the task store. After this returns successfully, the session no longer has a resumable task and emitResumableIfUnfinished will not emit a "task_failed_resumable" event for it. Returns nil if no task store is configured or no unfinished task exists.
func (*Manager) ClearGoal ¶
ClearGoal abandons the goal for a session: it cancels any in-flight task (stopping a running goal loop) and THEN marks the persisted GoalState cancelled (a terminal state) so it will not resume on the next app restart.
Ordering matters: the cancel-and-wait happens FIRST so the running goal loop's final best-effort persist settles BEFORE we overwrite the state with cancelled. Persisting cancelled first would let the loop's exit-time persist clobber it (the loop can't see the external cancel and writes its own paused/active state). A session with no goal task is a no-op.
CancelTask's "no active task" (ErrNoActiveTask) is treated as non-fatal: the goal may have already exited its loop, in which case the cancelled-state persistence is still the part that matters.
The task is looked up via GetLatestTaskID (status-agnostic) rather than GetUnfinishedTaskID: CancelTask flips the task row to "cancelled" as part of its completion path, so a task that WAS in-progress is no longer returned by GetUnfinishedTaskID by the time CancelTask returns. The status-agnostic lookup still locates the row so the goal state can be overwritten.
func (*Manager) CreateSession ¶
func (m *Manager) CreateSession(projectID, workspacePath string) (*SessionInfo, error)
CreateSession creates a new session with a fresh orchestrator. The projectID ties the session to a project; workspacePath is the project's workspace directory.
func (*Manager) DeleteSession ¶
DeleteSession removes a session, cancelling any active task.
func (*Manager) EmitSessionEvent ¶
EmitSessionEvent emits a session-scoped event through the manager's emit pipeline (event persister included). Used by recovery flows that need to emit events outside of a live session goroutine.
func (*Manager) GetBlackboardState ¶
func (m *Manager) GetBlackboardState(sessionID string) (*BlackboardState, error)
GetBlackboardState returns the current blackboard state for a session. It uses the in-memory lastCompletedTaskID if available, otherwise falls back to the most recent task ID from the database. Returns nil, nil if no task state is available.
func (*Manager) GetSession ¶
GetSession returns a session by ID. If the session is not in memory but exists in the persistent store, it is lazily restored.
func (*Manager) GetSessionAttachments ¶
func (m *Manager) GetSessionAttachments(sessionID string) ([]AttachmentInfo, error)
GetSessionAttachments returns a defensive copy of the session's staged (pending) attachments as metadata-only AttachmentInfo values, for UI chips. Includes both document attachments and image attachments.
func (*Manager) GetSessionRuntimeStatus ¶
func (m *Manager) GetSessionRuntimeStatus(sessionID string) (SessionRuntimeStatus, error)
GetSessionRuntimeStatus returns whether a task is currently running in the session (in-memory) and whether an unfinished (resumable) task is persisted in the task store. It never restores a session as a side effect.
func (*Manager) GetSessionWorkspacePath ¶
GetSessionWorkspacePath returns the workspace path for a session.
func (*Manager) InvalidateIgnoreCache ¶ added in v0.4.0
InvalidateIgnoreCache evicts cached ignore resolvers whose root contains one of changedPaths when that path is an ignore-rule file (.gitignore/.aiignore/ .ignore). It is the invalidation half of the async ignore cache: without it, edits to ignore files would be invisible until the app restarts.
It only DELETEs cache entries — it never rebuilds synchronously. The rebuild is triggered lazily and asynchronously by the next injectIgnoreChecker call: startIgnoreBuild launches a background goroutine and deduplicates concurrent builds via a sentinel. Because the rebuild never blocks SendMessage, this cannot regress the multi-minute-build case on roots with hundreds of thousands of files — at worst the first message after invalidation runs without ignore filtering (the no-checker / sentinel path), exactly like the first message after startup, until the background walk completes.
changedPaths are expected to be absolute filesystem paths (as reported by the workspace watcher / fsnotify); the cache is keyed by symlink-resolved roots. pathutil.IsWithinPath resolves symlinks on both sides, so the match is correct even when the workspace lives behind an OS symlink.
func (*Manager) LastToolCallID ¶
LastToolCallID returns the most recently emitted tool_call_id for a session along with its tool name, or empty strings if none has been recorded. The desktop confirmation callback uses this to attach the matching tool_call_id to the tool_confirm payload so the frontend can correlate the confirmation with the exact tool_call event (rather than matching by tool name).
func (*Manager) ListSessions ¶
func (m *Manager) ListSessions() []SessionInfo
ListSessions returns metadata for all sessions, sorted by LastActiveAt descending.
func (*Manager) ListSessionsByProject ¶
func (m *Manager) ListSessionsByProject(projectID string) ([]SessionInfo, error)
ListSessionsByProject returns sessions for a project, merging in-memory active state with persistent store data. Falls back to in-memory sessions if no store.
func (*Manager) PauseGoal ¶
PauseGoal signals the currently-running goal loop (if any) for the session to pause at the top of its next turn. It is a no-op when no goal loop is active or the orchestrator is not yet built. The pause is cooperative: the loop polls the signal, transitions the goal to StatusPaused, persists it, and exits so a later ResumeGoal can re-enter.
func (*Manager) PendingImageAttachments ¶ added in v0.4.0
func (m *Manager) PendingImageAttachments(sessionID string) ([]ImageAttachment, error)
PendingImageAttachments returns a defensive copy of the session's staged (pending) image attachments, carrying the full ImageAttachment data (including FilePath and MediaType) needed to persist thumbnail + path in ChatMessage.Metadata. Used by the frontend API before SendMessage snapshots and clears the pending list.
func (*Manager) PendingImageMetadata ¶ added in v0.4.0
func (m *Manager) PendingImageMetadata(sessionID string) (json.RawMessage, error)
PendingImageMetadata returns the persistable metadata blob (JSON) for the session's staged image attachments, suitable for storing in ChatMessage.Metadata. Returns nil when there are no pending images. Used by the frontend API before SendMessage snapshots and clears the pending list.
func (*Manager) PinSession ¶
PinSession toggles the pinned flag.
func (*Manager) RemovePendingAttachment ¶
RemovePendingAttachment removes a staged attachment from the session by ID. It does not touch attachments already flushed into the blackboard. Returns nil if the attachment was not found among the pending ones. Emits an "attachments:changed" event with the remaining pending attachments.
func (*Manager) RenameSession ¶
RenameSession changes a session's display name.
func (*Manager) ResolveGoalProposal ¶
func (m *Manager) ResolveGoalProposal(requestID, decision, condition, verify, verificationMode string) bool
ResolveGoalProposal delivers a user decision on a pending goal proposal. decision is "approve" or "cancel". condition/verify carry the (possibly edited) approved values; verificationMode carries the (possibly edited) per-goal verification mode for the approve path. Returns true when a pending proposal was found and resolved, false otherwise (including when no resolver is wired).
func (*Manager) ResumeGoal ¶
func (m *Manager) ResumeGoal(ctx context.Context, sessionID, modelOverride, reasoningEffort string) error
ResumeGoal re-enters the goal loop for a paused (or still-active, non-terminal) goal. It delegates to ResumeTask, which loads the unfinished task + persisted GoalState and dispatches to the orchestrator's resume path (resumeGoalLoop for non-terminal goals, the plain Conductor path otherwise). The optional modelOverride/reasoningEffort are forwarded so a model/reasoning switch made before resuming is honored. Returns nil if there is no resumable goal/task.
func (*Manager) ResumeTask ¶
ResumeTask checks for an unfinished task in the given session and resumes it. Returns nil if no unfinished task exists or if the task store is not configured. Invoked both by the manual Resume button (with the user's current model/reasoning selection) and on app restart to resume interrupted tasks. The optional modelOverride/reasoningEffort are applied (same as a fresh SendMessage) so a model/reasoning switch the user made before resuming is honored instead of silently inheriting the interrupted task's settings.
func (*Manager) SendMessage ¶
func (m *Manager) SendMessage(ctx context.Context, id, text string, activeSkills, activeAgents []string, modelOverride, reasoningEffort string, goal bool, goalBudget string, reviewMode bool) error
Runs in a goroutine, results come via events. reviewMode, when true, marks the message as carrying code review feedback the agent must address (see core HandleOptions.ReviewMode).
func (*Manager) SetEnvInfo ¶
SetEnvInfo sets the environment info that will be injected into task contexts.
func (*Manager) SetFactory ¶
func (m *Manager) SetFactory(factory OrchestratorFactory)
SetFactory replaces the orchestrator factory used for new sessions. Existing sessions are not affected.
func (*Manager) SetGoalProposalResolver ¶
func (m *Manager) SetGoalProposalResolver(fn func(requestID, decision, condition, verify, verificationMode string) bool)
SetGoalProposalResolver installs the callback that delivers a user decision to a blocked goal-proposal channel. Desktop wires this after buildGoalProposalCallback registers its pending map. Without it, ResolveGoalProposal is a no-op (and the event-based path is the only resolution route).
func (*Manager) SetLogLevel ¶
SetLogLevel sets the log level for new session loggers.
func (*Manager) SetMaxSummaryLen ¶
SetMaxSummaryLen sets the character limit for auto-generated step summaries.
func (*Manager) SetProjectResolver ¶
func (m *Manager) SetProjectResolver(fn ProjectResolverFunc)
SetProjectResolver sets the function used to resolve a project ID to its workspace path. This is required for lazy session restoration from the database.
func (*Manager) SetProjectStore ¶
func (m *Manager) SetProjectStore(store project.ProjectStore)
SetProjectStore sets the persistent project store, used to load project-scoped auxiliary work directories into each task context.
func (*Manager) SetSessionStore ¶
func (m *Manager) SetSessionStore(store SessionStore)
SetSessionStore sets the persistent session store.
func (*Manager) SetTaskStore ¶
SetTaskStore sets the TaskStore used to persist orchestration tasks. When set, CreateSession will construct a BlackboardFactory that creates PersistentBlackboard instances backed by this store.
func (*Manager) SetTitleGenerator ¶
func (m *Manager) SetTitleGenerator(gen *TitleGenerator)
SetTitleGenerator sets the title generator for auto-naming sessions.
func (*Manager) SetTokenPersist ¶
func (m *Manager) SetTokenPersist(fn TokenPersistFunc)
SetTokenPersist sets the callback used to persist cumulative session token totals.
func (*Manager) Shutdown ¶
func (m *Manager) Shutdown()
Shutdown closes all sessions and releases resources. This should be called when the application is shutting down.
func (*Manager) StartEnvInfoCollection ¶ added in v0.4.0
func (m *Manager) StartEnvInfoCollection()
StartEnvInfoCollection launches environment-info collection in a background goroutine and stores the result via SetEnvInfo when ready. It is safe to call SendMessage/ResumeTask concurrently — they tolerate a nil envInfo until the collection completes. WaitEnvInfo allows callers (notably tests) to block until the result is available.
Calling this method more than once is a no-op: the underlying goroutine is launched exactly once (guarded by envInfoOnce), so envInfoDone is closed a single time and never panics on a double close.
func (*Manager) WaitEnvInfo ¶ added in v0.4.0
WaitEnvInfo blocks until the background environment-info collection finishes (or ctx is cancelled). It returns nil once envInfo is ready, or ctx.Err() if the context expires first. Because StartEnvInfoCollection closes envInfoDone via defer (even on panic), WaitEnvInfo never blocks forever after collection has been started.
type MessageReceivedData ¶
MessageReceivedData is the payload for "message_received" events.
type OrchestratorFactory ¶
type OrchestratorFactory func(emitter core.Emitter, logger *slog.Logger, workspacePath string, bbFactory core.BlackboardFactory, dumpWriter io.Writer, stepDumpTracker *orchestration.StepDumpTracker) (*core.Orchestrator, error)
OrchestratorFactory creates a new Orchestrator with the given emitter, logger, workspace path, and optional BlackboardFactory. The workspace path is the project workspace directory so the worktree factory can capture the correct project workspace. bbFactory may be nil, in which case the orchestrator uses an in-memory MapBlackboard. Returns an error if the orchestrator cannot be created.
type PersistentBlackboard ¶
type PersistentBlackboard struct {
// *orchestration.MapBlackboard is embedded for in-memory read operations.
// Write operations are intercepted to persist changes to the database.
*orchestration.MapBlackboard
// contains filtered or unexported fields
}
PersistentBlackboard wraps a MapBlackboard and persists write operations to a TaskPersistence store. Read methods delegate to the embedded MapBlackboard. Write methods delegate AND persist. All persistence calls are best-effort: errors are logged but do not propagate to callers. Persistence operations are executed by a single background worker goroutine with a timeout and panic recovery to prevent hangs.
func NewPersistentBlackboard ¶
func NewPersistentBlackboard(taskID, sessionID string, store core.TaskPersistence, logger *slog.Logger, opts ...orchestration.MapBlackboardOption) *PersistentBlackboard
NewPersistentBlackboard creates a PersistentBlackboard that wraps a fresh MapBlackboard. The logger is optional (nil-safe).
func NewPersistentBlackboardWithTimeout ¶
func NewPersistentBlackboardWithTimeout(taskID, sessionID string, store core.TaskPersistence, logger *slog.Logger, timeout time.Duration, opts ...orchestration.MapBlackboardOption) *PersistentBlackboard
NewPersistentBlackboardWithTimeout creates a PersistentBlackboard that wraps a fresh MapBlackboard with a configurable timeout. The logger is optional (nil-safe). If timeout is 0, defaultPersistenceTimeout is used.
func RestoreBlackboard ¶
func RestoreBlackboard(taskID, sessionID string, store core.TaskPersistence, logger *slog.Logger, opts ...orchestration.MapBlackboardOption) (*PersistentBlackboard, error)
RestoreBlackboard loads a task's state from persistence and hydrates a PersistentBlackboard. Returns nil, nil if the task is not found.
func (*PersistentBlackboard) AddAttachment ¶
func (pb *PersistentBlackboard) AddAttachment(a orchestration.Attachment)
AddAttachment appends an attachment and persists the full attachments list.
func (*PersistentBlackboard) AddReflection ¶
func (pb *PersistentBlackboard) AddReflection(r orchestration.Reflection)
AddReflection appends a reflection and persists it.
func (*PersistentBlackboard) CancelTask ¶
func (pb *PersistentBlackboard) CancelTask()
CancelTask marks the task as cancelled (user-initiated cancellation). Writes the cancellation synchronously (bypassing the worker) to guarantee the status change is persisted before returning.
func (*PersistentBlackboard) CompleteTask ¶
func (pb *PersistentBlackboard) CompleteTask(attemptCount int)
CompleteTask marks the task as completed. Called by the orchestrator after Handle() succeeds. Writes the completion synchronously (bypassing the worker) so it is guaranteed to be persisted before this method returns — a queued write that drains after the result-wait timeout would leave the task marked unfinished and trip a spurious persistence warning.
func (*PersistentBlackboard) FailTask ¶
func (pb *PersistentBlackboard) FailTask()
FailTask marks the task as failed. Writes the failure synchronously (bypassing the worker) to guarantee the status change is persisted before returning.
func (*PersistentBlackboard) ReactivateTask ¶
func (pb *PersistentBlackboard) ReactivateTask()
ReactivateTask reactivates a completed task back to in_progress.
func (*PersistentBlackboard) RemoveAttachment ¶
func (pb *PersistentBlackboard) RemoveAttachment(id string) bool
RemoveAttachment removes an attachment and persists the full attachments list when an attachment was actually removed. Read methods (GetAttachments / GetAttachment) are promoted from the embedded MapBlackboard.
func (*PersistentBlackboard) Routing ¶
func (pb *PersistentBlackboard) Routing() *router.RoutingDecision
Routing returns the cached routing decision, or nil if none has been set.
func (*PersistentBlackboard) SetEmitter ¶
func (pb *PersistentBlackboard) SetEmitter(emitter core.Emitter)
SetEmitter sets the optional emitter for surfacing persistence warnings to the user.
func (*PersistentBlackboard) SetFinalResult ¶
func (pb *PersistentBlackboard) SetFinalResult(result string)
SetFinalResult sets the final result string. Does NOT call PersistCompletion — the orchestrator calls CompleteTask() separately.
func (*PersistentBlackboard) SetOnChanged ¶
func (pb *PersistentBlackboard) SetOnChanged(fn func(changeType string))
SetOnChanged sets an optional callback invoked after every successful blackboard write. The changeType argument describes what changed (e.g. "plan", "step_result", "fact", "reflection"). The callback is nil-safe.
func (*PersistentBlackboard) SetOriginalRequest ¶
func (pb *PersistentBlackboard) SetOriginalRequest(req string)
SetOriginalRequest sets the original user request and persists a new task record.
func (*PersistentBlackboard) SetPlan ¶
func (pb *PersistentBlackboard) SetPlan(plan *orchestration.Plan)
SetPlan stores a plan and persists it.
func (*PersistentBlackboard) SetRouting ¶
func (pb *PersistentBlackboard) SetRouting(routing *router.RoutingDecision)
SetRouting persists the routing decision for the task.
func (*PersistentBlackboard) SetStepResult ¶
func (pb *PersistentBlackboard) SetStepResult(stepID, output string, err error, steps []agent.Step)
SetStepResult records a step result and persists it. The summary is generated using the same logic as MapBlackboard.
func (*PersistentBlackboard) StoreFact ¶
func (pb *PersistentBlackboard) StoreFact(fact orchestration.Fact)
StoreFact appends a fact and persists the full facts list.
func (*PersistentBlackboard) TaskID ¶
func (pb *PersistentBlackboard) TaskID() string
TaskID returns the task ID.
type PlanApprovalPayload ¶
type PlanApprovalPayload struct {
RequestID string `json:"request_id"`
PlanPath string `json:"plan_path"`
PlanContent string `json:"plan_content"`
}
PlanApprovalPayload is sent to the frontend when the Conductor calls declare_plan with mode=await_approval and the plan is ready for review.
type PlanApprovalResponsePayload ¶
type PlanApprovalResponsePayload struct {
RequestID string `json:"request_id"`
Decision string `json:"decision"` // "approve", "request_changes", or "abandon"
Feedback string `json:"feedback"` // non-empty when decision="request_changes"
}
PlanApprovalResponsePayload is received from the frontend when the user decides on a plan awaiting approval.
type ProjectResolverFunc ¶
ProjectResolverFunc resolves a project ID to its workspace directory path.
type SQLiteSessionStore ¶
type SQLiteSessionStore struct {
// contains filtered or unexported fields
}
SQLiteSessionStore implements SessionStore using SQLite.
func NewSQLiteSessionStore ¶
func NewSQLiteSessionStore(db *sql.DB) (*SQLiteSessionStore, error)
NewSQLiteSessionStore wraps an existing *sql.DB and auto-creates tables. The caller is responsible for opening the DB and applying pragmas (WAL, foreign_keys). The projects table must be created before calling this (sessions has FK to projects).
func (*SQLiteSessionStore) AddTaskReflection ¶
func (s *SQLiteSessionStore) AddTaskReflection(ctx context.Context, taskID string, reflectionJSON json.RawMessage) error
AddTaskReflection appends a reflection JSON object to the task's reflections array.
func (*SQLiteSessionStore) ArchiveSession ¶
ArchiveSession sets the archived flag on a session.
func (*SQLiteSessionStore) CancelTask ¶
func (s *SQLiteSessionStore) CancelTask(ctx context.Context, taskID string) error
CancelTask marks a task as cancelled.
func (*SQLiteSessionStore) Close ¶
func (s *SQLiteSessionStore) Close() error
Close is a no-op — the DB lifecycle is managed externally.
func (*SQLiteSessionStore) CompleteTask ¶
func (s *SQLiteSessionStore) CompleteTask(ctx context.Context, taskID, finalOutput string, attemptCount int) error
CompleteTask marks a task as completed with final output.
func (*SQLiteSessionStore) DeleteMessages ¶
func (s *SQLiteSessionStore) DeleteMessages(ctx context.Context, sessionID string) error
DeleteMessages deletes all messages for a session.
func (*SQLiteSessionStore) DeleteSession ¶
func (s *SQLiteSessionStore) DeleteSession(ctx context.Context, id string) error
DeleteSession deletes a session and all its messages (cascade).
func (*SQLiteSessionStore) DeleteSessionWorkDir ¶
func (s *SQLiteSessionStore) DeleteSessionWorkDir(ctx context.Context, sessionID, id string) error
DeleteSessionWorkDir removes a session-scoped work directory by ID. sessionID is required as a scope guard so a cross-scope ID cannot delete another session's record.
func (*SQLiteSessionStore) FailTask ¶
func (s *SQLiteSessionStore) FailTask(ctx context.Context, taskID string) error
FailTask marks a task as failed.
func (*SQLiteSessionStore) ForkSession ¶
func (s *SQLiteSessionStore) ForkSession(ctx context.Context, srcID string, cloneReview ForkReviewCloner) (*SessionInfo, error)
ForkSession creates a deep, independent copy of a session and all of its associated data — messages, terminal commands, work directories, tasks and their steps/facts/attachments/trajectory — with freshly generated identifiers (new session id, new task ids, regenerated work-directory UUIDs) so the fork shares no rows with the original.
Runtime counters (tokens, fill percent) and the model/family fields are reset: the fork keeps the conversation history but starts with fresh runtime accounting. The fork is created in the same project as the source and named "<source name> (fork N)" where N is the smallest positive integer making the name unique within the project.
If cloneReview is non-nil it is run inside the same transaction so that the whole fork (session + tasks + review) commits atomically; on any error the fork is rolled back and the source is left untouched.
The caller is responsible for ensuring the source session has no unfinished tasks (use GetUnfinishedTask) before calling this method; the store performs a faithful copy regardless of task status.
func (*SQLiteSessionStore) GetLatestTaskID ¶
GetLatestTaskID returns the ID of the most recent task for a session, regardless of status. Returns "", nil if no tasks exist.
func (*SQLiteSessionStore) GetUnfinishedTask ¶
func (s *SQLiteSessionStore) GetUnfinishedTask(ctx context.Context, sessionID string) (*TaskRecord, error)
GetUnfinishedTask returns the most recent unfinished (in-progress or failed) task for a session, or nil if none.
func (*SQLiteSessionStore) ListSessionWorkDirs ¶
func (s *SQLiteSessionStore) ListSessionWorkDirs(ctx context.Context, sessionID string) ([]project.WorkDirectoryRecord, error)
ListSessionWorkDirs returns all work directories for a session, ordered by creation time (oldest first). Returns an empty (non-nil) slice when none exist.
func (*SQLiteSessionStore) ListSessions ¶
func (s *SQLiteSessionStore) ListSessions(ctx context.Context) ([]SessionInfo, error)
ListSessions returns all sessions ordered by last activity time (newest first).
func (*SQLiteSessionStore) ListSessionsByProject ¶
func (s *SQLiteSessionStore) ListSessionsByProject(ctx context.Context, projectID string) ([]SessionInfo, error)
ListSessionsByProject returns all sessions for a given project, ordered by last activity (newest first).
func (*SQLiteSessionStore) LoadAttachments ¶
func (s *SQLiteSessionStore) LoadAttachments(ctx context.Context, taskID string) (json.RawMessage, error)
LoadAttachments loads the attachments JSON blob for a task. Returns nil, nil when no attachments have been persisted.
func (*SQLiteSessionStore) LoadFacts ¶
func (s *SQLiteSessionStore) LoadFacts(ctx context.Context, taskID string) (json.RawMessage, error)
LoadFacts loads the facts JSON blob for a task. Returns nil if not found.
func (*SQLiteSessionStore) LoadGoalState ¶
func (s *SQLiteSessionStore) LoadGoalState(ctx context.Context, taskID string) (json.RawMessage, error)
LoadGoalState loads the goal-loop state for a task. Returns nil, nil when no goal state has been persisted.
func (*SQLiteSessionStore) LoadMessages ¶
func (s *SQLiteSessionStore) LoadMessages(ctx context.Context, sessionID string) ([]ChatMessage, error)
LoadMessages loads all messages for a session ordered by creation time.
func (*SQLiteSessionStore) LoadSession ¶
func (s *SQLiteSessionStore) LoadSession(ctx context.Context, id string) (*SessionInfo, error)
LoadSession loads a session by ID.
func (*SQLiteSessionStore) LoadTask ¶
func (s *SQLiteSessionStore) LoadTask(ctx context.Context, taskID string) (*TaskRecord, error)
LoadTask loads a task by ID. Returns nil, nil if not found.
func (*SQLiteSessionStore) LoadTaskSteps ¶
func (s *SQLiteSessionStore) LoadTaskSteps(ctx context.Context, taskID string) ([]TaskStepRecord, error)
LoadTaskSteps loads all step records for a task ordered by creation time.
func (*SQLiteSessionStore) LoadTerminalCommands ¶
func (s *SQLiteSessionStore) LoadTerminalCommands(ctx context.Context, sessionID string, limit int) ([]TerminalCommand, error)
LoadTerminalCommands loads the most recent terminal commands for a session.
func (*SQLiteSessionStore) LoadTrajectory ¶
func (s *SQLiteSessionStore) LoadTrajectory(ctx context.Context, taskID string) (json.RawMessage, error)
LoadTrajectory loads the Conductor step trajectory for a task. Returns nil, nil when no trajectory has been persisted.
func (*SQLiteSessionStore) PinSession ¶
PinSession sets the pinned flag on a session.
func (*SQLiteSessionStore) ReactivateTask ¶
func (s *SQLiteSessionStore) ReactivateTask(ctx context.Context, taskID string) error
ReactivateTask reactivates a completed task back to in_progress.
func (*SQLiteSessionStore) RenameSession ¶
func (s *SQLiteSessionStore) RenameSession(ctx context.Context, id, name string) error
RenameSession updates a session's name.
func (*SQLiteSessionStore) ResolvePendingMessage ¶
func (s *SQLiteSessionStore) ResolvePendingMessage(ctx context.Context, sessionID, role, matchField, matchValue string, extra map[string]any) error
ResolvePendingMessage patches the metadata of the most recent message with the given role whose metadata JSON contains matchField==matchValue, merging the extra map into the existing metadata. If no matching message is found, the call is a no-op (not an error) — the message may not have been persisted (e.g. event fired while persister was busy) or may already have been resolved.
func (*SQLiteSessionStore) SaveAttachments ¶
func (s *SQLiteSessionStore) SaveAttachments(ctx context.Context, taskID string, attachmentsJSON json.RawMessage) error
SaveAttachments inserts or replaces the attachments JSON blob for a task.
func (*SQLiteSessionStore) SaveFacts ¶
func (s *SQLiteSessionStore) SaveFacts(ctx context.Context, taskID string, factsJSON json.RawMessage) error
SaveFacts inserts or replaces the facts JSON blob for a task.
func (*SQLiteSessionStore) SaveGoalState ¶
func (s *SQLiteSessionStore) SaveGoalState(ctx context.Context, taskID string, goalStateJSON json.RawMessage) error
SaveGoalState inserts or replaces the goal-loop state for a task.
func (*SQLiteSessionStore) SaveMessage ¶
func (s *SQLiteSessionStore) SaveMessage(ctx context.Context, msg ChatMessage) error
SaveMessage saves a chat message.
func (*SQLiteSessionStore) SaveSession ¶
func (s *SQLiteSessionStore) SaveSession(ctx context.Context, info SessionInfo) error
SaveSession saves or updates a session.
func (*SQLiteSessionStore) SaveSessionWorkDir ¶
func (s *SQLiteSessionStore) SaveSessionWorkDir(ctx context.Context, sessionID string, rec project.WorkDirectoryRecord) error
func (*SQLiteSessionStore) SaveTask ¶
func (s *SQLiteSessionStore) SaveTask(ctx context.Context, task TaskRecord) error
SaveTask inserts a new task record.
func (*SQLiteSessionStore) SaveTaskStep ¶
func (s *SQLiteSessionStore) SaveTaskStep(ctx context.Context, taskID string, step TaskStepRecord) error
SaveTaskStep inserts or replaces a task step record.
func (*SQLiteSessionStore) SaveTerminalCommand ¶
func (s *SQLiteSessionStore) SaveTerminalCommand(ctx context.Context, sessionID, command string) error
SaveTerminalCommand saves a terminal command to the history.
func (*SQLiteSessionStore) SaveTrajectory ¶
func (s *SQLiteSessionStore) SaveTrajectory(ctx context.Context, taskID string, stepsJSON json.RawMessage) error
SaveTrajectory inserts or replaces the full Conductor step trajectory (JSON-marshaled []agent.Step) for a task.
func (*SQLiteSessionStore) SetLogger ¶
func (s *SQLiteSessionStore) SetLogger(l *slog.Logger)
SetLogger sets the logger for the session store.
func (*SQLiteSessionStore) UpdateSessionActivity ¶
func (s *SQLiteSessionStore) UpdateSessionActivity(ctx context.Context, id string) error
UpdateSessionActivity updates the last_active_at timestamp for a session.
func (*SQLiteSessionStore) UpdateSessionTokens ¶
func (s *SQLiteSessionStore) UpdateSessionTokens(ctx context.Context, id string, inputTokens, outputTokens int, model, family string, fillPercent float64) error
UpdateSessionTokens updates the accumulated token counts, model info, and context-window fill percent for a session.
func (*SQLiteSessionStore) UpdateSessionWorkDirDescription ¶
func (s *SQLiteSessionStore) UpdateSessionWorkDirDescription(ctx context.Context, sessionID, id, description string) error
UpdateSessionWorkDirDescription updates the human-readable description of a session-scoped work directory by ID. sessionID is required as a scope guard: only a record owned by that session can be mutated.
func (*SQLiteSessionStore) UpdateTaskPlan ¶
func (s *SQLiteSessionStore) UpdateTaskPlan(ctx context.Context, taskID string, plan json.RawMessage) error
UpdateTaskPlan updates the plan JSON for a task.
func (*SQLiteSessionStore) UpdateTaskRouting ¶
func (s *SQLiteSessionStore) UpdateTaskRouting(ctx context.Context, taskID string, routing json.RawMessage) error
UpdateTaskRouting updates the routing decision JSON for a task.
type Session ¶
type Session struct {
ID string
ProjectID string // immutable after creation (no lock needed for reads)
Name string
CreatedAt time.Time
LastActiveAt time.Time
Archived bool
Pinned bool
WorkspacePath string // workspace directory (from project)
TempDir string // session-specific temp directory
// contains filtered or unexported fields
}
Session represents a running agent session with its own orchestrator.
func (*Session) DumpFile ¶
DumpFile returns a duplicated file handle for the session's LLM dump file, or nil if DEBUG is disabled. The caller owns the returned handle and must close it when done. Duping ensures that background goroutines (title generation, ToolJudge) have independent handles that survive session deletion.
func (*Session) GetOrchestrator ¶
func (s *Session) GetOrchestrator() *core.Orchestrator
GetOrchestrator returns the orchestrator for a session (for testing/advanced use).
type SessionArchivedData ¶
SessionArchivedData is the payload for "session_archived" / "session_unarchived" events.
type SessionCreatedData ¶
type SessionCreatedData struct {
ID string `json:"id"`
Name string `json:"name"`
CreatedAt time.Time `json:"created_at"`
}
SessionCreatedData is the payload for "session_created" events.
type SessionDeletedData ¶
type SessionDeletedData struct {
ID string `json:"id"`
}
SessionDeletedData is the payload for "session_deleted" events.
type SessionInfo ¶
type SessionInfo struct {
ID string `json:"id"`
ProjectID string `json:"project_id"`
Name string `json:"name"`
CreatedAt string `json:"created_at"` // RFC 3339 formatted timestamp
LastActiveAt string `json:"last_active_at"` // RFC 3339 formatted timestamp
Archived bool `json:"archived"`
Pinned bool `json:"pinned"`
Active bool `json:"active"`
TotalInputTokens int `json:"total_input_tokens"`
TotalOutputTokens int `json:"total_output_tokens"`
Model string `json:"model"`
Family string `json:"family"`
FillPercent float64 `json:"fill_percent"`
// HasUnfinishedTask is true when the session has an in-progress or failed
// task. Such sessions cannot be forked (the fork would duplicate a
// half-completed execution state). Populated via a correlated subquery.
HasUnfinishedTask bool `json:"has_unfinished_task"`
}
SessionInfo is the public-facing session metadata.
type SessionPinnedData ¶
SessionPinnedData is the payload for "session_pinned" / "session_unpinned" events.
type SessionRenamedData ¶
type SessionRenamedData struct {
ID string `json:"id"`
OldName string `json:"old_name"`
NewName string `json:"new_name"`
}
SessionRenamedData is the payload for "session_renamed" events.
type SessionRuntimeStatus ¶
type SessionRuntimeStatus struct {
Active bool `json:"active"`
HasUnfinishedTask bool `json:"has_unfinished_task"`
UnfinishedTaskID string `json:"unfinished_task_id,omitempty"`
}
SessionRuntimeStatus describes the live and persisted execution state of a session, so the frontend can reconstruct "is something running / resumable" after app restart or session switch instead of assuming idle.
type SessionStore ¶
type SessionStore interface {
// Session CRUD
SaveSession(ctx context.Context, info SessionInfo) error
LoadSession(ctx context.Context, id string) (*SessionInfo, error)
ListSessions(ctx context.Context) ([]SessionInfo, error)
ListSessionsByProject(ctx context.Context, projectID string) ([]SessionInfo, error)
DeleteSession(ctx context.Context, id string) error
ArchiveSession(ctx context.Context, id string, archived bool) error
PinSession(ctx context.Context, id string, pinned bool) error
RenameSession(ctx context.Context, id, name string) error
// Token tracking
UpdateSessionTokens(ctx context.Context, id string, inputTokens, outputTokens int, model, family string, fillPercent float64) error
// Activity tracking
UpdateSessionActivity(ctx context.Context, id string) error
// Message operations
SaveMessage(ctx context.Context, msg ChatMessage) error
LoadMessages(ctx context.Context, sessionID string) ([]ChatMessage, error)
DeleteMessages(ctx context.Context, sessionID string) error
// ResolvePendingMessage patches the metadata of the most recent message
// with the given role whose metadata[matchField] == matchValue, merging
// the extra fields. Used to mark HITL messages (tool_confirm, ask_user,
// step_limit, plan_review) as resolved after the user responds, so they
// don't reappear as pending on session reload.
ResolvePendingMessage(ctx context.Context, sessionID, role, matchField, matchValue string, extra map[string]any) error
// Terminal command history
SaveTerminalCommand(ctx context.Context, sessionID, command string) error
LoadTerminalCommands(ctx context.Context, sessionID string, limit int) ([]TerminalCommand, error)
// Session-scoped work directories
SaveSessionWorkDir(ctx context.Context, sessionID string, rec project.WorkDirectoryRecord) error
ListSessionWorkDirs(ctx context.Context, sessionID string) ([]project.WorkDirectoryRecord, error)
UpdateSessionWorkDirDescription(ctx context.Context, sessionID, id, description string) error
DeleteSessionWorkDir(ctx context.Context, sessionID, id string) error
// Lifecycle
Close() error
}
SessionStore provides persistent storage for sessions and messages.
type SessionTokensEventData ¶
type SessionTokensEventData struct {
SessionInputTokens int `json:"session_input_tokens"`
SessionOutputTokens int `json:"session_output_tokens"`
Model string `json:"model"`
Family string `json:"family"`
FillPercent float64 `json:"fill_percent"`
UsedTokens int `json:"used_tokens"`
MaxTokens int `json:"max_tokens"`
}
SessionTokensEventData is the typed Data payload for "session_tokens" events. UsedTokens/MaxTokens mirror the session-root (conductor) context-window fill, cached by ContextFill and forwarded here alongside FillPercent so the status bar can render a "N of M" tooltip without waiting for the next context_fill.
type SkillsActivatedData ¶
type SkillsActivatedData struct {
Skills []string `json:"skills"`
}
SkillsActivatedData is the typed Data payload for "skills_activated" events.
type StepLimitPayload ¶
type StepLimitPayload struct {
RequestID string `json:"request_id"`
CurrentStep int `json:"current_step"`
MaxSteps int `json:"max_steps"`
Reason string `json:"reason,omitempty"` // empty for normal step limit; describes circuit breaker trigger
}
StepLimitPayload is emitted when an agent reaches its tool call step limit or a circuit breaker abort threshold, prompting the user for a decision on whether to continue.
type StepLimitResponsePayload ¶
type StepLimitResponsePayload struct {
RequestID string `json:"request_id"`
Response string `json:"response"` // "allow_once", "allow_more", "allow_always", or "deny"
}
StepLimitResponsePayload carries the user's decision about continuing past the step limit.
type StoredImageMetadata ¶ added in v0.4.0
type StoredImageMetadata struct {
ID string `json:"id"`
Name string `json:"name"`
Thumbnail string `json:"thumbnail"`
Path string `json:"path"`
MediaType string `json:"media_type"`
}
StoredImageMetadata is the per-image record persisted in ChatMessage.Metadata so image attachments survive a backend restart. Only the thumbnail (data URI) and the on-disk file path are stored — never the full base64 image data — keeping the DB row small. The file at Path is read and re-encoded on restore.
type StoredImagesMetadata ¶ added in v0.4.0
type StoredImagesMetadata struct {
Images []StoredImageMetadata `json:"images"`
}
StoredImagesMetadata is the top-level metadata blob persisted in ChatMessage.Metadata for user messages carrying image attachments.
type TaskCancelledData ¶
type TaskCancelledData struct {
SessionID string `json:"session_id"`
}
TaskCancelledData is the payload for "task_cancelled" events.
type TaskCompleteData ¶
type TaskCompleteData struct {
SessionID string `json:"session_id"`
Output string `json:"output"`
RoutingDecision *router.RoutingDecision `json:"routing_decision"`
Plan *orchestration.Plan `json:"plan,omitempty"`
Reflections []orchestration.Reflection `json:"reflections,omitempty"`
// Typed success contract: Success is false for partial/failed/aborted
// executions that are still delivered as task_complete so the best-effort
// output reaches the user. Completion refines the outcome.
Success bool `json:"success"`
Completion string `json:"completion,omitempty"` // "full" | "partial" | "failed" | "aborted"
}
TaskCompleteData is the payload for "task_complete" events.
type TaskFailedResumableData ¶
type TaskFailedResumableData struct {
Message string `json:"message"`
TaskID string `json:"task_id,omitempty"`
// Reason carries a concise, contextual cause for the failure (e.g. an
// execution error or the completion outcome) so the banner can explain
// WHY the task is resumable rather than always showing a generic message.
Reason string `json:"reason,omitempty"`
}
TaskFailedResumableData is the payload for "task_failed_resumable" events. Emitted when plan execution fails but the task can be resumed. TaskID lets the persisted message be matched and resolved when the user resumes or cancels (see Manager.resolveResumableTaskMessage), so the banner does not reappear as pending on session reload.
type TaskRecord ¶
type TaskRecord struct {
ID string `json:"id"`
SessionID string `json:"session_id"`
OriginalRequest string `json:"original_request"`
RoutingDecision json.RawMessage `json:"routing_decision"`
Plan json.RawMessage `json:"plan"`
Reflections json.RawMessage `json:"reflections"`
FinalOutput string `json:"final_output"`
AttemptCount int `json:"attempt_count"`
Status string `json:"status"` // "in_progress", "completed", "failed", "cancelled"
CreatedAt time.Time `json:"created_at"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
}
TaskRecord represents a persisted task (one per Orchestrator.Handle call).
type TaskStepRecord ¶
type TaskStepRecord struct {
StepID string `json:"step_id"`
TaskID string `json:"task_id"`
Summary string `json:"summary"`
FullOutput string `json:"full_output"`
ErrorText string `json:"error_text"`
Steps json.RawMessage `json:"steps"` // JSON array of executor steps
CreatedAt time.Time `json:"created_at"`
}
TaskStepRecord represents a persisted step result.
type TaskStore ¶
type TaskStore interface {
SaveTask(ctx context.Context, task TaskRecord) error
UpdateTaskPlan(ctx context.Context, taskID string, plan json.RawMessage) error
UpdateTaskRouting(ctx context.Context, taskID string, routing json.RawMessage) error
SaveTaskStep(ctx context.Context, taskID string, step TaskStepRecord) error
AddTaskReflection(ctx context.Context, taskID string, reflectionJSON json.RawMessage) error
CompleteTask(ctx context.Context, taskID, finalOutput string, attemptCount int) error
FailTask(ctx context.Context, taskID string) error
CancelTask(ctx context.Context, taskID string) error
LoadTask(ctx context.Context, taskID string) (*TaskRecord, error)
LoadTaskSteps(ctx context.Context, taskID string) ([]TaskStepRecord, error)
SaveFacts(ctx context.Context, taskID string, factsJSON json.RawMessage) error
LoadFacts(ctx context.Context, taskID string) (json.RawMessage, error)
// SaveAttachments inserts or replaces the attachments JSON blob
// (JSON-marshaled []orchestration.Attachment) for a task.
SaveAttachments(ctx context.Context, taskID string, attachmentsJSON json.RawMessage) error
// LoadAttachments loads the attachments JSON blob for a task.
// Returns nil, nil when no attachments have been persisted.
LoadAttachments(ctx context.Context, taskID string) (json.RawMessage, error)
// SaveTrajectory inserts or replaces the full Conductor step trajectory
// (JSON-marshaled []agent.Step) for a task.
SaveTrajectory(ctx context.Context, taskID string, stepsJSON json.RawMessage) error
// LoadTrajectory loads the Conductor step trajectory for a task.
// Returns nil, nil when no trajectory has been persisted.
LoadTrajectory(ctx context.Context, taskID string) (json.RawMessage, error)
// SaveGoalState inserts or replaces the goal-loop state
// (JSON-marshaled goal.GoalState) for a task.
SaveGoalState(ctx context.Context, taskID string, goalStateJSON json.RawMessage) error
// LoadGoalState loads the goal-loop state for a task.
// Returns nil, nil when no goal state has been persisted.
LoadGoalState(ctx context.Context, taskID string) (json.RawMessage, error)
GetUnfinishedTask(ctx context.Context, sessionID string) (*TaskRecord, error)
GetLatestTaskID(ctx context.Context, sessionID string) (string, error)
ReactivateTask(ctx context.Context, taskID string) error
}
TaskStore provides persistent storage for orchestration tasks and step results.
type TaskStoreAdapter ¶
type TaskStoreAdapter struct {
// contains filtered or unexported fields
}
TaskStoreAdapter adapts a TaskStore to the core.TaskPersistence interface. It handles JSON serialization of core types for storage.
func NewTaskStoreAdapter ¶
func NewTaskStoreAdapter(store TaskStore) *TaskStoreAdapter
NewTaskStoreAdapter creates a new adapter wrapping the given TaskStore.
func (*TaskStoreAdapter) GetLatestTaskID ¶
func (a *TaskStoreAdapter) GetLatestTaskID(sessionID string) (string, error)
GetLatestTaskID returns the ID of the most recent task for the session, regardless of status, or "" if none exists. Unlike GetUnfinishedTaskID it is status-agnostic, so it still locates a task whose row was flipped to a terminal status (e.g. cancelled/completed) by CancelTask — used by ClearGoal to overwrite the goal state after the loop's exit persist has settled.
func (*TaskStoreAdapter) GetUnfinishedTaskID ¶
func (a *TaskStoreAdapter) GetUnfinishedTaskID(sessionID string) (string, error)
GetUnfinishedTaskID returns the ID of the most recent in-progress task for the given session, or "" if none exists.
func (*TaskStoreAdapter) LoadGoalState ¶
func (a *TaskStoreAdapter) LoadGoalState(taskID string) (*goal.GoalState, error)
LoadGoalState loads the goal-loop state for a task and unmarshals it into a *goal.GoalState. Returns nil, nil when no goal state has been persisted.
func (*TaskStoreAdapter) LoadTaskState ¶
func (a *TaskStoreAdapter) LoadTaskState(taskID string) (*core.TaskState, error)
LoadTaskState loads a task and its steps from the store, deserializes JSON back to core types, and returns a populated *core.TaskState. Returns nil, nil if the task is not found.
func (*TaskStoreAdapter) LoadTrajectory ¶
func (a *TaskStoreAdapter) LoadTrajectory(taskID string) ([]agent.Step, error)
LoadTrajectory loads the Conductor step trajectory for a task and unmarshals it into []agent.Step. Returns nil, nil when no trajectory has been persisted.
func (*TaskStoreAdapter) PersistAttachments ¶
func (a *TaskStoreAdapter) PersistAttachments(taskID string, attachments []orchestration.Attachment) error
PersistAttachments JSON-marshals attachments and stores them for a task.
func (*TaskStoreAdapter) PersistCancellation ¶
func (a *TaskStoreAdapter) PersistCancellation(taskID string) error
PersistCancellation marks the task as cancelled.
func (*TaskStoreAdapter) PersistCompletion ¶
func (a *TaskStoreAdapter) PersistCompletion(taskID, finalOutput string, attemptCount int) error
PersistCompletion marks the task as completed.
func (*TaskStoreAdapter) PersistFacts ¶
func (a *TaskStoreAdapter) PersistFacts(taskID string, facts []orchestration.Fact) error
PersistFacts JSON-marshals facts and stores them for a task.
func (*TaskStoreAdapter) PersistFailure ¶
func (a *TaskStoreAdapter) PersistFailure(taskID string) error
PersistFailure marks the task as failed.
func (*TaskStoreAdapter) PersistGoalState ¶
func (a *TaskStoreAdapter) PersistGoalState(taskID string, gs *goal.GoalState) error
PersistGoalState JSON-marshals the goal-loop state and stores it for a task, inserting or replacing any previously persisted goal state.
func (*TaskStoreAdapter) PersistNewTask ¶
func (a *TaskStoreAdapter) PersistNewTask(taskID, sessionID, originalRequest string) error
PersistNewTask creates a new task record with status "in_progress".
func (*TaskStoreAdapter) PersistPlan ¶
func (a *TaskStoreAdapter) PersistPlan(taskID string, plan *orchestration.Plan) error
PersistPlan JSON-marshals the plan and updates the task record.
func (*TaskStoreAdapter) PersistReflection ¶
func (a *TaskStoreAdapter) PersistReflection(taskID string, r orchestration.Reflection) error
PersistReflection JSON-marshals the reflection and appends it to the task record.
func (*TaskStoreAdapter) PersistRouting ¶
func (a *TaskStoreAdapter) PersistRouting(taskID string, routing *router.RoutingDecision) error
PersistRouting JSON-marshals the routing decision and updates the task record.
func (*TaskStoreAdapter) PersistStepResult ¶
func (a *TaskStoreAdapter) PersistStepResult(taskID, stepID, summary, fullOutput, errorText string, steps []agent.Step) error
PersistStepResult creates a TaskStepRecord with JSON-marshaled steps.
func (*TaskStoreAdapter) ReactivateTask ¶
func (a *TaskStoreAdapter) ReactivateTask(taskID string) error
ReactivateTask reactivates a completed task back to in_progress.
func (*TaskStoreAdapter) SaveTrajectory ¶
func (a *TaskStoreAdapter) SaveTrajectory(taskID string, steps []agent.Step) error
SaveTrajectory JSON-marshals the full Conductor step trajectory and stores it for a task, inserting or replacing any previously persisted trajectory.
type TerminalCommand ¶
type TerminalCommand struct {
ID int64 `json:"id"`
SessionID string `json:"session_id"`
Command string `json:"command"`
CreatedAt string `json:"created_at"` // RFC 3339 formatted timestamp
}
TerminalCommand represents a stored terminal command.
type ThoughtEventData ¶
type ThoughtEventData struct {
StepNum int `json:"step_num"`
Content string `json:"content"`
Reasoning string `json:"reasoning"`
PlanStepID string `json:"plan_step_id,omitempty"`
}
ThoughtEventData is the typed Data payload for "thought" events.
type TitleGenerator ¶
type TitleGenerator struct {
// contains filtered or unexported fields
}
TitleGenerator generates concise session titles from user messages.
func NewTitleGenerator ¶
func NewTitleGenerator(caller LLMTitleCaller) *TitleGenerator
NewTitleGenerator creates a new TitleGenerator. If caller is nil, only fallback title generation is used.
func (*TitleGenerator) Generate ¶
func (g *TitleGenerator) Generate(ctx context.Context, userMessage string, activeSkills []string) string
Generate produces a title for the given user message. It tries LLM-based generation first, falling back to extracting first words.
func (*TitleGenerator) SetLogger ¶
func (g *TitleGenerator) SetLogger(l *slog.Logger)
SetLogger sets the logger for the title generator.
type TokenPersistFunc ¶
type TokenPersistFunc func(sessionID string, inputTokens, outputTokens int, model, family string, fillPercent float64)
TokenPersistFunc is called with cumulative session token totals after each LLM call. The sessionID parameter identifies which session the tokens belong to. fillPercent is the conductor's context-window fill percent (0-100).
type ToolConfirmPayload ¶
type ToolConfirmPayload struct {
ConfirmID string `json:"confirm_id"`
Tool string `json:"tool"`
Args string `json:"args"`
Reasoning string `json:"reasoning"`
ToolCallID string `json:"tool_call_id,omitempty"`
}
ToolConfirmPayload is sent to the frontend when a tool needs user confirmation. ToolCallID carries the tool_call_id of the triggering tool_call event so the frontend can anchor the confirmation card precisely (instead of matching by tool name, which is ambiguous when two calls share a name).
type ToolsAssignedData ¶ added in v0.5.0
type ToolsAssignedData struct {
Tools []string `json:"tools"`
}
ToolsAssignedData is the typed Data payload for "tools_assigned" events, emitted when the Small-LLM domain narrowing curates the session's tool set.