chat

package module
v0.11.1 Latest Latest
Warning

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

Go to latest
Published: Apr 21, 2026 License: MIT Imports: 28 Imported by: 0

README

axon-chat

Domain package · Part of the lamina workspace

Chat service with LLM-powered agents, SSE streaming, and tool calling. Provides domain types, store interfaces, HTTP handlers, and an embedded SvelteKit frontend (//go:embed). Persistence implementations live in the consuming application's composition root.

Getting started

go get github.com/benaskins/axon-chat@latest

Requires Go 1.26.1+.

axon-chat is a domain package — it provides handlers and types but no main. You assemble it in your own composition root alongside an LLM client, store, and auth middleware:

srv := chat.NewServer(llm,
    chat.WithStore(store),
    chat.WithDefaultModel("llama3.3:70b-instruct-q8_0"),
    chat.WithEventBus(eventBus),
    chat.WithStaticFiles(&chat.StaticFiles),
    chat.WithShutdownContext(ctx),
)

handler := srv.Handler()

See example/main.go for a minimal wiring example, or the full composition root in examples/chat/ in the lamina workspace.

Key types

  • Server — HTTP server with SSE streaming and tool dispatch. Configured via Option functions.
  • Agent — configurable LLM agent with system prompt, model parameters, and tools.
  • Conversation, Message — chat domain types.
  • Store — persistence interface combining ReadStore and ReadModelWriter.
  • ToolRouter — routes tool calls to the relevant subset based on user message.
  • PageFetcher — rate-limited web page fetcher with LLM extraction.
  • chattest.MemoryStore — in-memory store for testing.

License

MIT — see LICENSE.

Documentation

Overview

Package chat provides a chat service library with LLM integration, tool calling, SSE streaming, and agent management. It defines domain types, store interfaces, and HTTP handlers for a multi-agent chat system.

Class: domain UseWhen: Building chat interfaces with LLM-backed conversations.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrAgentNotFound        = axon.ErrNotFound
	ErrConversationNotFound = errors.New("conversation not found")
	ErrUserNotFound         = errors.New("user not found")
)
View Source
var AvailableTools = func() []ToolInfo {
	infos := make([]ToolInfo, len(toolRegistry))
	for i, entry := range toolRegistry {
		infos[i] = entry.info
	}
	return infos
}()

AvailableTools returns the list of all registered tools for the frontend. Derived from toolRegistry — no separate list to keep in sync.

View Source
var StaticFiles embed.FS

Functions

func BuildSystemPrompt

func BuildSystemPrompt(a Agent) string

BuildSystemPrompt assembles the full system prompt from the freeform system_prompt, constraints, and skill guidance sections.

func BuildToolsForAgent

func BuildToolsForAgent(a Agent) []tool.ToolDef

BuildToolsForAgent returns the tool definitions for an agent's enabled tools. Derived from toolRegistry — no separate switch statement to keep in sync.

func DefaultProjectors added in v0.3.0

func DefaultProjectors(readStore ReadStore, writer ReadModelWriter) []fact.Projector

DefaultProjectors returns the standard set of projectors for axon-chat. readStore provides query access, writer provides mutation access for projections.

func EmitDefaultAgents added in v0.3.0

func EmitDefaultAgents(ctx context.Context, es fact.EventStore, userID, defaultModel string) error

EmitDefaultAgents emits agent.created events for the default agent set.

Types

type Agent

type Agent struct {
	Slug            string   `json:"slug"`
	UserID          string   `json:"user_id"`
	Name            string   `json:"name"`
	Tagline         string   `json:"tagline"`
	AvatarEmoji     string   `json:"avatar_emoji"`
	SystemPrompt    string   `json:"system_prompt"`
	Constraints     string   `json:"constraints,omitempty"`
	Greeting        string   `json:"greeting"`
	DefaultModel    string   `json:"default_model,omitempty"`
	Temperature     *float64 `json:"temperature,omitempty"`
	Think           *bool    `json:"think,omitempty"`
	TopP            *float64 `json:"top_p,omitempty"`
	TopK            *int     `json:"top_k,omitempty"`
	MinP            *float64 `json:"min_p,omitempty"`
	PresencePenalty *float64 `json:"presence_penalty,omitempty"`
	MaxTokens       *int     `json:"max_tokens,omitempty"`
	Tools           []string `json:"tools,omitempty"`
}

Agent represents a full agent definition.

type AgentCreated added in v0.3.0

type AgentCreated struct {
	Agent Agent `json:"agent"`
}

func (AgentCreated) EventType added in v0.3.0

func (e AgentCreated) EventType() string

type AgentDeleted added in v0.3.0

type AgentDeleted struct{}

func (AgentDeleted) EventType added in v0.3.0

func (e AgentDeleted) EventType() string

type AgentDetailResponse

type AgentDetailResponse struct {
	Agent
	FullPrompt string `json:"full_prompt"`
}

AgentDetailResponse is the full agent response including the assembled full prompt.

type AgentProjector added in v0.3.0

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

AgentProjector projects agent events into the read model.

func NewAgentProjector added in v0.3.0

func NewAgentProjector(store ReadModelWriter) *AgentProjector

func (*AgentProjector) Handle added in v0.3.0

func (p *AgentProjector) Handle(ctx context.Context, e fact.Event) error

type AgentSummary

type AgentSummary struct {
	Slug         string `json:"slug"`
	Name         string `json:"name"`
	Tagline      string `json:"tagline"`
	AvatarEmoji  string `json:"avatar_emoji"`
	DefaultModel string `json:"default_model,omitempty"`
}

AgentSummary is the lightweight representation for list responses.

type AgentUpdated added in v0.3.0

type AgentUpdated struct {
	Agent Agent `json:"agent"`
}

func (AgentUpdated) EventType added in v0.3.0

func (e AgentUpdated) EventType() string

type AnalyticsClient

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

AnalyticsClient sends events to the analytics service over HTTP. Events are sent asynchronously — failures are logged but never block.

func NewAnalyticsClient

func NewAnalyticsClient(baseURL string) *AnalyticsClient

NewAnalyticsClient creates a client for the analytics service.

func (*AnalyticsClient) Emit

func (c *AnalyticsClient) Emit(events ...AnalyticsEvent)

Emit sends events to the analytics service asynchronously.

type AnalyticsEmitter

type AnalyticsEmitter interface {
	Emit(events ...AnalyticsEvent)
}

AnalyticsEmitter sends analytics events to the analytics service.

type AnalyticsEvent

type AnalyticsEvent struct {
	Type             string    `json:"type"`
	Timestamp        time.Time `json:"timestamp"`
	AgentSlug        string    `json:"agent_slug,omitempty"`
	UserID           string    `json:"user_id,omitempty"`
	ConversationID   string    `json:"conversation_id,omitempty"`
	RunID            string    `json:"run_id,omitempty"`
	Role             string    `json:"role,omitempty"`
	PromptTokens     uint32    `json:"prompt_tokens,omitempty"`
	CompletionTokens uint32    `json:"completion_tokens,omitempty"`
	DurationMs       uint32    `json:"duration_ms,omitempty"`
	ToolName         string    `json:"tool_name,omitempty"`
	Success          *bool     `json:"success,omitempty"`
	EventName        string    `json:"event_name,omitempty"`
}

AnalyticsEvent is a typed event sent to the analytics service.

func ConversationEvent

func ConversationEvent(agentSlug, userID, conversationID, eventName string) AnalyticsEvent

ConversationEvent creates a conversation lifecycle analytics event.

func MessageEvent

func MessageEvent(agentSlug, userID, conversationID, role string, durationMs int64) AnalyticsEvent

MessageEvent creates a message analytics event.

func ToolInvocationEvent

func ToolInvocationEvent(agentSlug, userID, conversationID, toolName string, success bool, durationMs int64) AnalyticsEvent

ToolInvocationEvent creates a tool invocation analytics event.

type Config

type Config struct {
	DefaultModel string
	CookieDomain string
	AuthLoginURL string

	// InternalAPIKey is required for service-to-service endpoints
	// (InternalMessagesHandler, InternalAgentHandler). Requests must
	// present this value in the X-Internal-API-Key header.
	InternalAPIKey string
}

Config holds configuration for the chat server.

type Conversation

type Conversation struct {
	ID        string    `json:"id"`
	AgentSlug string    `json:"agent_slug"`
	UserID    string    `json:"user_id"`
	Title     *string   `json:"title"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

Conversation represents a chat conversation with an agent.

type ConversationCreated added in v0.3.0

type ConversationCreated struct {
	ID        string `json:"id"`
	AgentSlug string `json:"agent_slug"`
	UserID    string `json:"user_id"`
}

func (ConversationCreated) EventType added in v0.3.0

func (e ConversationCreated) EventType() string

type ConversationDeleted added in v0.3.0

type ConversationDeleted struct{}

func (ConversationDeleted) EventType added in v0.3.0

func (e ConversationDeleted) EventType() string

type ConversationProjector added in v0.3.0

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

ConversationProjector projects conversation and message events into the read model.

func NewConversationProjector added in v0.3.0

func NewConversationProjector(store ReadModelWriter) *ConversationProjector

func (*ConversationProjector) Handle added in v0.3.0

type ConversationSummary

type ConversationSummary struct {
	ID           string    `json:"id"`
	Title        *string   `json:"title"`
	CreatedAt    time.Time `json:"created_at"`
	UpdatedAt    time.Time `json:"updated_at"`
	MessageCount int       `json:"message_count"`
}

ConversationSummary is the lightweight representation for list responses.

type ConversationTitled added in v0.3.0

type ConversationTitled struct {
	Title string `json:"title"`
}

func (ConversationTitled) EventType added in v0.3.0

func (e ConversationTitled) EventType() string

type Event

type Event struct {
	Type string     `json:"type"`
	Task *TaskEvent `json:"task,omitempty"`
}

Event wraps different async event types delivered via SSE.

type IdleExtractor

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

IdleExtractor tracks conversation activity and triggers memory extraction when a conversation has been idle for a configured duration.

func NewIdleExtractor

func NewIdleExtractor(ctx context.Context, extractor MemoryExtractor, idleTimeout time.Duration) *IdleExtractor

NewIdleExtractor creates an IdleExtractor that triggers extraction after idleTimeout.

func (*IdleExtractor) FlushAll

func (ie *IdleExtractor) FlushAll()

FlushAll triggers extraction for all tracked conversations and clears state. Call this during graceful shutdown.

func (*IdleExtractor) Touch

func (ie *IdleExtractor) Touch(conversationID, agentSlug, userID string)

Touch records activity for a conversation, resetting its idle timer.

type MemoryClient

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

MemoryClient talks to the memory service over HTTP.

func NewMemoryClient

func NewMemoryClient(baseURL string) *MemoryClient

NewMemoryClient creates a client pointing at a memory service instance.

func (*MemoryClient) ExtractMemories

func (c *MemoryClient) ExtractMemories(ctx context.Context, conversationID, agentSlug, userID string) error

ExtractMemories triggers memory extraction for a conversation.

func (*MemoryClient) RecallMemories

func (c *MemoryClient) RecallMemories(ctx context.Context, agentSlug, userID, query string, limit int) (*MemoryRecallResponse, error)

RecallMemories implements MemoryRecaller by calling the memory service's recall endpoint.

type MemoryExtractor

type MemoryExtractor interface {
	ExtractMemories(ctx context.Context, conversationID, agentSlug, userID string) error
}

MemoryExtractor triggers memory extraction for conversations.

type MemoryRecallResponse

type MemoryRecallResponse struct {
	Memories            []RecalledMemory     `json:"memories"`
	RelationshipContext *RelationshipContext `json:"relationship_context"`
}

MemoryRecallResponse contains recalled memories and relationship context.

type MemoryRecaller

type MemoryRecaller interface {
	RecallMemories(ctx context.Context, agentSlug, userID, query string, limit int) (*MemoryRecallResponse, error)
}

MemoryRecaller retrieves memories relevant to a query for an agent/user pair.

type Message

type Message struct {
	ID             string    `json:"id"`
	ConversationID string    `json:"conversation_id"`
	Role           string    `json:"role"`
	Content        string    `json:"content"`
	Thinking       string    `json:"thinking,omitempty"`
	ToolCalls      string    `json:"tool_calls,omitempty"`
	Images         string    `json:"images,omitempty"`
	DurationMs     *int64    `json:"duration_ms,omitempty"`
	CreatedAt      time.Time `json:"created_at"`
}

Message represents a single message in a conversation.

type MessageAppended added in v0.3.0

type MessageAppended struct {
	ID         string `json:"id"`
	Role       string `json:"role"`
	Content    string `json:"content"`
	Thinking   string `json:"thinking,omitempty"`
	ToolCalls  string `json:"tool_calls,omitempty"`
	Images     string `json:"images,omitempty"`
	DurationMs *int64 `json:"duration_ms,omitempty"`
}

func (MessageAppended) EventType added in v0.3.0

func (e MessageAppended) EventType() string

type ModelLister

type ModelLister interface {
	ListModels(ctx context.Context) ([]string, error)
}

ModelLister lists available models from the LLM backend.

type NoopAnalytics

type NoopAnalytics struct{}

NoopAnalytics discards all events. Used when analytics is not configured.

func (NoopAnalytics) Emit

func (NoopAnalytics) Emit(events ...AnalyticsEvent)

type OpenMeteoClient

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

OpenMeteoClient uses Open-Meteo's free geocoding + weather APIs.

func NewOpenMeteoClient

func NewOpenMeteoClient() *OpenMeteoClient

NewOpenMeteoClient creates a weather client using Open-Meteo.

func (*OpenMeteoClient) GetWeather

func (c *OpenMeteoClient) GetWeather(ctx context.Context, location string) (*WeatherResult, error)

GetWeather geocodes the location and fetches current weather from Open-Meteo.

type Option added in v0.3.0

type Option func(*Server)

Option configures a Server during construction.

func WithAnalytics added in v0.3.0

func WithAnalytics(analytics AnalyticsEmitter) Option

WithAnalytics sets the analytics event emitter.

func WithAuthLoginURL added in v0.3.3

func WithAuthLoginURL(url string) Option

WithAuthLoginURL sets the external auth service login URL. The SvelteKit frontend redirects here when the user is not authenticated.

func WithCookieDomain added in v0.3.0

func WithCookieDomain(domain string) Option

WithCookieDomain sets the cookie domain for session management.

func WithDefaultModel added in v0.3.0

func WithDefaultModel(model string) Option

WithDefaultModel sets the default LLM model name.

func WithEventBus added in v0.3.0

func WithEventBus(bus *push.EventBus[Event]) Option

WithEventBus sets the SSE event bus for real-time streaming.

func WithEventStore added in v0.3.0

func WithEventStore(es fact.EventStore) Option

WithEventStore overrides the default in-memory event store. Use this to provide a durable event store (e.g., Postgres-backed). The caller is responsible for registering projectors on the provided store.

func WithExtraTools added in v0.3.0

func WithExtraTools(tools map[string]tool.ToolDef) Option

WithExtraTools registers additional tool definitions.

func WithInternalAPIKey added in v0.5.7

func WithInternalAPIKey(key string) Option

WithInternalAPIKey sets the API key required for internal service-to-service endpoints (InternalMessagesHandler, InternalAgentHandler).

func WithMemoryExtractor added in v0.3.0

func WithMemoryExtractor(extractor MemoryExtractor) Option

WithMemoryExtractor sets the memory extractor for idle conversations.

func WithMemoryRecaller added in v0.3.0

func WithMemoryRecaller(recaller MemoryRecaller) Option

WithMemoryRecaller sets the memory recall provider.

func WithModelLister added in v0.3.0

func WithModelLister(lister ModelLister) Option

WithModelLister sets the model listing backend.

func WithPageFetcher added in v0.3.0

func WithPageFetcher(fetcher *PageFetcher) Option

WithPageFetcher sets the page fetcher for URL content extraction.

func WithSearchQualifier added in v0.3.0

func WithSearchQualifier(qualifier *SearchQualifier) Option

WithSearchQualifier sets the search qualifier for query refinement.

func WithSearcher added in v0.3.0

func WithSearcher(searcher Searcher) Option

WithSearcher sets the web search provider.

func WithShutdownContext added in v0.3.0

func WithShutdownContext(ctx context.Context) Option

WithShutdownContext sets the context used for graceful shutdown coordination.

func WithStaticFiles added in v0.3.0

func WithStaticFiles(fs *embed.FS) Option

WithStaticFiles sets the embedded filesystem for the SvelteKit frontend.

func WithStore added in v0.3.0

func WithStore(store Store) Option

WithStore sets the read/write store for the chat server.

func WithTaskRunner added in v0.3.0

func WithTaskRunner(runner TaskRunner) Option

WithTaskRunner sets the async task runner.

func WithToolRouter added in v0.3.0

func WithToolRouter(router *ToolRouter) Option

WithToolRouter sets the tool routing provider.

func WithWeather added in v0.3.0

func WithWeather(provider WeatherProvider) Option

WithWeather sets the weather provider.

type PageFetcher

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

PageFetcher handles fetching web pages and extracting relevant content.

func NewPageFetcher

func NewPageFetcher(llm loop.LLMClient, model string) *PageFetcher

NewPageFetcher creates a page fetcher with the given LLM client for extraction. If model is empty, defaults to the built-in extraction model.

func (*PageFetcher) FetchAndExtract

func (f *PageFetcher) FetchAndExtract(ctx context.Context, rawURL, question string) (string, error)

FetchAndExtract fetches a URL, extracts readable content, and uses an LLM to pull out the parts relevant to the given question.

type ReadModelWriter added in v0.3.0

type ReadModelWriter interface {
	CreateUser(ctx context.Context, id string) error
	SaveAgent(ctx context.Context, agent Agent) error
	DeleteAgent(ctx context.Context, userID, slug string) error
	CreateConversationForUser(ctx context.Context, userID string, agentSlug string) (*Conversation, error)
	CreateConversationWithID(ctx context.Context, id, userID, agentSlug string) (*Conversation, error)
	UpdateConversationTitle(ctx context.Context, userID string, id string, title string) error
	DeleteConversation(ctx context.Context, userID string, id string) error
	AppendMessage(ctx context.Context, conversationID string, msg Message) error
}

ReadModelWriter provides write operations for projectors to build read models. Not used by handlers directly — handlers emit events, projectors call these.

type ReadStore added in v0.3.0

type ReadStore interface {
	// Users
	UserExists(ctx context.Context, id string) (bool, error)

	// Agents
	ListAgentsByUser(ctx context.Context, userID string) ([]AgentSummary, error)
	GetAgentByUser(ctx context.Context, userID, slug string) (*Agent, error)
	GetAgentBySlug(ctx context.Context, slug string) (*Agent, error)

	// Conversations
	ListConversationsByUser(ctx context.Context, userID string, agentSlug string) ([]ConversationSummary, error)
	GetConversationByUser(ctx context.Context, userID string, id string) (*Conversation, error)

	// Messages
	GetMessages(ctx context.Context, conversationID string) ([]Message, error)
	GetRecentMessages(ctx context.Context, conversationID string, limit int) ([]Message, error)
}

ReadStore provides read-only access to the data model. Handlers use this to query current state.

type RecalledMemory

type RecalledMemory struct {
	Type             string  `json:"type"`
	Content          string  `json:"content"`
	EmotionalContext string  `json:"emotional_context"`
	Importance       float64 `json:"importance"`
	RelevanceScore   float64 `json:"relevance_score"`
}

RecalledMemory is a memory returned from recall with relevance scoring.

type RelationshipContext

type RelationshipContext struct {
	Trust              float64 `json:"trust"`
	Intimacy           float64 `json:"intimacy"`
	Autonomy           float64 `json:"autonomy"`
	Reciprocity        float64 `json:"reciprocity"`
	Playfulness        float64 `json:"playfulness"`
	Conflict           float64 `json:"conflict"`
	PersonalityContext string  `json:"personality_context"`
	TotalConversations int     `json:"total_conversations"`
	TotalMemories      int     `json:"total_memories"`
}

RelationshipContext provides relationship state for recall responses.

type SSETaskEvent

type SSETaskEvent struct {
	TaskID      string `json:"task_id"`
	Type        string `json:"type"`   // "claude_session" | "image_generation"
	Status      string `json:"status"` // "queued" | "running"
	Description string `json:"description"`
}

SSETaskEvent represents a task submission event sent to the frontend.

type SearXNGClient

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

SearXNGClient talks to a SearXNG instance.

func NewSearXNGClient

func NewSearXNGClient(baseURL string) *SearXNGClient

NewSearXNGClient creates a client pointing at a SearXNG instance.

func (*SearXNGClient) Search

func (c *SearXNGClient) Search(ctx context.Context, query string, limit int) ([]SearchResult, error)

Search queries SearXNG and returns the top N results.

type SearchQualifier

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

SearchQualifier uses a small LLM to refine search queries based on the agent's system prompt, producing more targeted and contextually relevant search terms.

func NewSearchQualifier

func NewSearchQualifier(llm loop.LLMClient, model string) *SearchQualifier

NewSearchQualifier creates a new search qualifier. If model is empty, defaults to the built-in qualifier model.

func (*SearchQualifier) Qualify

func (sq *SearchQualifier) Qualify(ctx context.Context, query, systemPrompt string) string

Qualify takes a raw search query and the agent's system prompt, and returns a refined query that incorporates the agent's domain expertise and context. If qualification fails, returns the original query unchanged.

type SearchResult

type SearchResult struct {
	Title   string `json:"title"`
	URL     string `json:"url"`
	Snippet string `json:"content"`
}

SearchResult represents a single search result.

type Searcher

type Searcher interface {
	Search(ctx context.Context, query string, limit int) ([]SearchResult, error)
}

Searcher abstracts web search for testing.

type Server

type Server struct {

	// Optional dependencies — set before calling Handler().
	ModelLister     ModelLister
	Searcher        Searcher
	ToolRouter      *ToolRouter
	TaskRunner      TaskRunner
	Weather         WeatherProvider
	PageFetcher     *PageFetcher
	SearchQualifier *SearchQualifier

	// MemoryRecaller provides memory recall for the recall_memory tool.
	MemoryRecaller MemoryRecaller

	// MemoryExtractor triggers memory extraction for idle conversations.
	MemoryExtractor MemoryExtractor

	// Analytics emits analytics events to the analytics service.
	Analytics AnalyticsEmitter

	// ExtraTools are additional tool definitions registered by the composition root.
	// They are included in the tool map alongside built-in tools when the agent
	// has the matching skill enabled.
	ExtraTools map[string]tool.ToolDef
	// contains filtered or unexported fields
}

Server is the chat service HTTP server.

func NewServer

func NewServer(llm loop.LLMClient, opts ...Option) *Server

NewServer creates a chat server. The LLM client is the only required dependency; everything else is configured via Option functions.

func (*Server) Handler

func (s *Server) Handler() http.Handler

Handler returns an http.Handler with all API routes. Auth is not applied here — the composition root wraps with auth middleware. Call this after setting optional dependencies.

func (*Server) InternalAgentHandler

func (s *Server) InternalAgentHandler() http.Handler

InternalAgentHandler returns an http.Handler for fetching agent info by slug with internal API key auth, for service-to-service calls.

func (*Server) InternalMessagesHandler

func (s *Server) InternalMessagesHandler() http.Handler

InternalMessagesHandler returns an http.Handler for fetching conversation messages with internal API key auth, for service-to-service calls.

func (*Server) SPAHandler added in v0.5.0

func (s *Server) SPAHandler() http.Handler

SPAHandler returns an http.Handler that serves the embedded SvelteKit frontend with client-side routing fallback. Mount without auth.

func (*Server) UserCreatedHandler

func (s *Server) UserCreatedHandler() http.Handler

UserCreatedHandler returns an http.Handler for the user-created webhook.

func (*Server) WaitForBackgroundTasks

func (s *Server) WaitForBackgroundTasks()

WaitForBackgroundTasks blocks until all background tasks complete.

type Store

type Store interface {
	ReadStore
	ReadModelWriter
}

Store combines ReadStore and ReadModelWriter. Composition roots provide a concrete implementation that satisfies both interfaces.

type SyncChatResponse

type SyncChatResponse struct {
	Response   string   `json:"response"`
	Thinking   string   `json:"thinking,omitempty"`
	DurationMs int64    `json:"duration_ms"`
	ToolsUsed  []string `json:"tools_used"`
}

SyncChatResponse is the JSON response from the synchronous chat endpoint.

type TaskEvent

type TaskEvent struct {
	TaskID  string `json:"task_id"`
	Status  string `json:"status"`
	Summary string `json:"summary,omitempty"`
	Error   string `json:"error,omitempty"`
}

TaskEvent is sent when an async code change task completes or fails.

type TaskRunner

type TaskRunner interface {
	SubmitTask(ctx context.Context, req *TaskSubmitRequest) (*TaskSubmission, error)
	GetTaskStatus(ctx context.Context, taskID string) (*TaskStatus, error)
	ListTasks(ctx context.Context, agentSlug string, limit, offset int) ([]TaskStatus, error)
	IssueAgentCert(ctx context.Context, slug, username string) error
}

TaskRunner submits tasks to the task runner service.

type TaskRunnerClient

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

TaskRunnerClient is an HTTP client for the task runner service.

func NewTaskRunnerClient

func NewTaskRunnerClient(baseURL string, tlsConfig *tls.Config) *TaskRunnerClient

NewTaskRunnerClient creates a client pointing at the task runner service. Pass a non-nil tlsConfig to enable mTLS; nil uses default (plain HTTP for tests).

func (*TaskRunnerClient) GetTaskStatus

func (c *TaskRunnerClient) GetTaskStatus(ctx context.Context, taskID string) (*TaskStatus, error)

func (*TaskRunnerClient) IssueAgentCert

func (c *TaskRunnerClient) IssueAgentCert(ctx context.Context, slug, username string) error

func (*TaskRunnerClient) ListTasks

func (c *TaskRunnerClient) ListTasks(ctx context.Context, agentSlug string, limit, offset int) ([]TaskStatus, error)

func (*TaskRunnerClient) SubmitTask

func (c *TaskRunnerClient) SubmitTask(ctx context.Context, submitReq *TaskSubmitRequest) (*TaskSubmission, error)

type TaskStatus

type TaskStatus struct {
	TaskID      string  `json:"task_id"`
	Type        string  `json:"type,omitempty"`
	Status      string  `json:"status"`
	Description string  `json:"description,omitempty"`
	Summary     string  `json:"result_summary,omitempty"`
	Error       string  `json:"error,omitempty"`
	ArtifactID  string  `json:"artifact_id,omitempty"`
	RequestedBy string  `json:"requested_by,omitempty"`
	CreatedAt   *string `json:"created_at,omitempty"`
	CompletedAt *string `json:"completed_at,omitempty"`
}

TaskStatus is the response from checking a task's progress.

type TaskSubmission

type TaskSubmission struct {
	TaskID string `json:"task_id"`
	Status string `json:"status"`
}

TaskSubmission is the response from submitting a new task.

type TaskSubmitRequest

type TaskSubmitRequest struct {
	Type   string `json:"type"`   // "claude_session" | "image_generation"
	Params any    `json:"params"` // type-specific payload
}

TaskSubmitRequest is the unified request body for POST /api/tasks.

func NewClaudeSessionRequest

func NewClaudeSessionRequest(description, requestedBy, username string) *TaskSubmitRequest

NewClaudeSessionRequest creates a TaskSubmitRequest for a claude_session task.

type ToolInfo added in v0.2.0

type ToolInfo struct {
	ID          string `json:"id"`
	Label       string `json:"label"`
	Description string `json:"description"`
}

ToolInfo describes an available tool for the frontend.

type ToolRouter

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

ToolRouter uses a small LLM to decide which tools (if any) are appropriate for a given user message, preventing the conversational model from being biased toward calling tools on every turn.

func NewToolRouter

func NewToolRouter(llm loop.LLMClient, model string) *ToolRouter

NewToolRouter creates a new tool router.

func (*ToolRouter) Route

func (tr *ToolRouter) Route(ctx context.Context, userMessage string, tools []tool.ToolDef) ([]string, error)

Route evaluates the user's latest message against available tools and returns only the tool names that should be offered to the conversational model. On error or timeout, returns nil (safe default — no tools).

type UserCreated added in v0.3.0

type UserCreated struct {
	UserID string `json:"user_id"`
}

func (UserCreated) EventType added in v0.3.0

func (e UserCreated) EventType() string

type UserProjector added in v0.3.0

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

UserProjector projects user events into the read model.

func NewUserProjector added in v0.3.0

func NewUserProjector(store ReadModelWriter) *UserProjector

func (*UserProjector) Handle added in v0.3.0

func (p *UserProjector) Handle(ctx context.Context, e fact.Event) error

type WeatherProvider

type WeatherProvider interface {
	GetWeather(ctx context.Context, location string) (*WeatherResult, error)
}

WeatherProvider abstracts weather lookups for testing.

type WeatherResult

type WeatherResult struct {
	Location    string  `json:"location"`
	Latitude    float64 `json:"latitude"`
	Longitude   float64 `json:"longitude"`
	Temperature float64 `json:"temperature"`
	FeelsLike   float64 `json:"feels_like"`
	Humidity    int     `json:"humidity"`
	WindSpeed   float64 `json:"wind_speed"`
	WindDir     int     `json:"wind_direction"`
	Description string  `json:"description"`
	IsDay       bool    `json:"is_day"`
}

WeatherResult represents weather conditions for a location.

Directories

Path Synopsis
Package chattest provides in-memory mock implementations of chat.Store for testing without a database.
Package chattest provides in-memory mock implementations of chat.Store for testing without a database.

Jump to

Keyboard shortcuts

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