Documentation
¶
Index ¶
- func GenerateAvatarWithAI(agentID string, persona string, name string, prompt string, ...) (string, error)
- func GenerateName(persona string, userPrompt string) (string, error)
- func GeneratePersona(currentPersona string, userPrompt string) (string, error)
- func GeneratePublicProfile(persona string) (string, error)
- func GenerateSVGAvatarFile(name string) (string, error)
- func GenerateTOTPCode(secret, algorithm string, digits, period int) (string, int64, error)
- func NormalizeTOTPSecret(secret string) (string, error)
- func SaveAvatar(agentID string, src io.Reader, ext string) error
- func ServeAvatar(w http.ResponseWriter, r *http.Request, a *Agent)
- func SummarizePersona(persona string) (string, error)
- func SummarizeWithCLI(tool string, persona string) (string, error)
- func ValidInterval(minutes int) bool
- func ValidateTOTPParams(secret, algorithm string, digits, period int) (string, error)
- type Agent
- type AgentConfig
- type AgentUpdateConfig
- type ChatBackend
- type ChatEvent
- type ClaudeBackend
- type CodexBackend
- type Credential
- type CredentialStore
- func (s *CredentialStore) AddCredential(agentID, label, username, password string, totp *TOTPParams) (*Credential, error)
- func (s *CredentialStore) Close() error
- func (s *CredentialStore) DeleteAllForAgent(agentID string) error
- func (s *CredentialStore) DeleteCredential(agentID, credID string) error
- func (s *CredentialStore) GetTOTPCode(agentID, credID string) (string, int64, error)
- func (s *CredentialStore) ListCredentials(agentID string) ([]*Credential, error)
- func (s *CredentialStore) RevealPassword(agentID, credID string) (string, error)
- func (s *CredentialStore) UpdateCredential(agentID, credID string, label, username, password *string, totp *TOTPParams) (*Credential, error)
- type DirectoryEntry
- type GeminiBackend
- type GroupDM
- type GroupDMManager
- func (m *GroupDMManager) APIBase() string
- func (m *GroupDMManager) Create(name string, memberIDs []string) (*GroupDM, error)
- func (m *GroupDMManager) Delete(id string) error
- func (m *GroupDMManager) Get(id string) (*GroupDM, bool)
- func (m *GroupDMManager) GroupsForAgent(agentID string) []*GroupDM
- func (m *GroupDMManager) List() []*GroupDM
- func (m *GroupDMManager) Messages(groupID string, limit int, before string) ([]*GroupMessage, bool, error)
- func (m *GroupDMManager) PostMessage(ctx context.Context, groupID, agentID, content string, notify bool) (*GroupMessage, error)
- func (m *GroupDMManager) RemoveAgent(agentID string)
- func (m *GroupDMManager) SetAPIBase(base string)
- type GroupMember
- type GroupMessage
- type Manager
- func (m *Manager) Abort(agentID string)
- func (m *Manager) Chat(ctx context.Context, agentID string, userMessage string, role string) (<-chan ChatEvent, error)
- func (m *Manager) Create(cfg AgentConfig) (*Agent, error)
- func (m *Manager) Credentials() *CredentialStore
- func (m *Manager) CronPaused() bool
- func (m *Manager) Delete(id string) error
- func (m *Manager) Directory() []DirectoryEntry
- func (m *Manager) Get(id string) (*Agent, bool)
- func (m *Manager) HasCredentials() bool
- func (m *Manager) IsBusy(agentID string) bool
- func (m *Manager) List() []*Agent
- func (m *Manager) Messages(agentID string, limit int) ([]*Message, error)
- func (m *Manager) MessagesPaginated(agentID string, limit int, before string) ([]*Message, bool, error)
- func (m *Manager) ResetData(id string) error
- func (m *Manager) SetCronPaused(paused bool)
- func (m *Manager) SetGroupDMManager(gdm *GroupDMManager)
- func (m *Manager) Shutdown()
- func (m *Manager) Update(id string, cfg AgentUpdateConfig) (*Agent, error)
- type MemoryIndex
- func (idx *MemoryIndex) BuildContextFromQuery(query string) string
- func (idx *MemoryIndex) Close() error
- func (idx *MemoryIndex) IndexFiles(agentID string) error
- func (idx *MemoryIndex) IndexFilesIfStale(agentID string)
- func (idx *MemoryIndex) IndexMessages(agentID string) error
- func (idx *MemoryIndex) IndexNewMessages(agentID string)
- func (idx *MemoryIndex) Reindex(agentID string) error
- func (idx *MemoryIndex) Search(query string, limit int) ([]SearchResult, error)
- type Message
- type MessagePreview
- type OTPEntry
- type SearchResult
- type TOTPParams
- type ToolUse
- type Usage
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GenerateAvatarWithAI ¶
func GenerateAvatarWithAI(agentID string, persona string, name string, prompt string, logger *slog.Logger) (string, error)
GenerateAvatarWithAI generates an avatar using nanobanana.sh.
func GenerateName ¶
GenerateName generates a character name using Gemini API based on persona description.
func GeneratePersona ¶
GeneratePersona elaborates or refines a persona description using Gemini API. currentPersona may be empty (generate from scratch) or non-empty (refine existing).
func GeneratePublicProfile ¶
GeneratePublicProfile creates a short outward-facing description from a persona.
func GenerateSVGAvatarFile ¶
GenerateSVGAvatarFile creates an SVG avatar file in a temp directory and returns its path. Used as fallback when AI avatar generation is unavailable.
func GenerateTOTPCode ¶
GenerateTOTPCode generates a current TOTP code for the given secret and parameters.
func NormalizeTOTPSecret ¶
NormalizeTOTPSecret normalizes and validates a TOTP secret. Returns the canonical form (upper-case, no padding) or an error.
func SaveAvatar ¶
SaveAvatar saves an uploaded avatar file for an agent.
func ServeAvatar ¶
func ServeAvatar(w http.ResponseWriter, r *http.Request, a *Agent)
ServeAvatar serves the agent's avatar image, falling back to a generated SVG.
func SummarizePersona ¶
SummarizePersona generates a concise summary of a persona using Gemini API.
func SummarizeWithCLI ¶
SummarizeWithCLI generates a persona summary using the agent's own CLI tool. Supports "claude" (stdin to -p) and "codex" (exec -o).
func ValidInterval ¶
ValidInterval returns true if the given interval is in the allowed set.
Types ¶
type Agent ¶
type Agent struct {
ID string `json:"id"`
Name string `json:"name"`
Persona string `json:"persona"` // persona description (markdown)
Model string `json:"model"` // e.g. "sonnet", "opus"
Tool string `json:"tool"` // CLI tool: "claude", "codex", "gemini"
IntervalMinutes int `json:"intervalMinutes"` // periodic execution interval in minutes (0 = disabled)
CreatedAt string `json:"createdAt"` // RFC3339
UpdatedAt string `json:"updatedAt"` // RFC3339
// Legacy field — only used during migration from cronExpr-based configs.
// Not included in JSON output; consumed by store.Load migration.
LegacyCronExpr string `json:"cronExpr,omitempty"`
// HasAvatar indicates whether a custom avatar file exists.
HasAvatar bool `json:"hasAvatar"`
// AvatarHash is derived from the avatar file's modtime for cache busting.
AvatarHash string `json:"avatarHash,omitempty"`
// PublicProfile is a short outward-facing description generated from persona.
// Shared with other agents via the directory endpoint. Does not expose internal persona details.
PublicProfile string `json:"publicProfile,omitempty"`
PublicProfileOverride bool `json:"publicProfileOverride,omitempty"`
// LastMessage is a preview of the most recent message (for list display).
LastMessage *MessagePreview `json:"lastMessage,omitempty"`
}
Agent represents a persistent AI persona (friend).
type AgentConfig ¶
type AgentConfig struct {
Name string `json:"name"`
Persona string `json:"persona"`
Model string `json:"model"`
Tool string `json:"tool"`
IntervalMinutes *int `json:"intervalMinutes"` // nil = use default (30)
}
AgentConfig is the request body for creating an agent.
type AgentUpdateConfig ¶
type AgentUpdateConfig struct {
Name *string `json:"name"`
Persona *string `json:"persona"`
PublicProfile *string `json:"publicProfile"`
PublicProfileOverride *bool `json:"publicProfileOverride"`
Model *string `json:"model"`
Tool *string `json:"tool"`
IntervalMinutes *int `json:"intervalMinutes"`
}
AgentUpdateConfig is the request body for PATCH updates. Pointer fields distinguish "not provided" (nil) from "set to zero".
type ChatBackend ¶
type ChatBackend interface {
// Chat sends a message and returns a channel of streaming events.
// The channel is closed when the response is complete.
Chat(ctx context.Context, agent *Agent, userMessage string, systemPrompt string) (<-chan ChatEvent, error)
// Name returns the tool identifier (e.g. "claude", "codex", "gemini").
Name() string
// Available returns true if the CLI tool is installed and accessible.
Available() bool
}
ChatBackend abstracts a CLI tool for agent chat.
type ChatEvent ¶
type ChatEvent struct {
Type string `json:"type"` // "status", "text", "thinking", "tool_use", "tool_result", "done", "error"
Status string `json:"status,omitempty"`
Delta string `json:"delta,omitempty"`
ToolName string `json:"toolName,omitempty"`
ToolInput string `json:"toolInput,omitempty"`
ToolOutput string `json:"toolOutput,omitempty"`
Message *Message `json:"message,omitempty"`
Usage *Usage `json:"usage,omitempty"`
ErrorMessage string `json:"errorMessage,omitempty"`
}
ChatEvent is streamed from backend to WebSocket during a chat.
type ClaudeBackend ¶
type ClaudeBackend struct {
// contains filtered or unexported fields
}
ClaudeBackend implements ChatBackend using the Claude CLI with stream-json output.
func NewClaudeBackend ¶
func NewClaudeBackend(logger *slog.Logger) *ClaudeBackend
func (*ClaudeBackend) Available ¶
func (b *ClaudeBackend) Available() bool
func (*ClaudeBackend) Name ¶
func (b *ClaudeBackend) Name() string
type CodexBackend ¶
type CodexBackend struct {
// contains filtered or unexported fields
}
CodexBackend implements ChatBackend for the Codex CLI.
func NewCodexBackend ¶
func NewCodexBackend(logger *slog.Logger) *CodexBackend
func (*CodexBackend) Available ¶
func (b *CodexBackend) Available() bool
func (*CodexBackend) Name ¶
func (b *CodexBackend) Name() string
type Credential ¶
type Credential struct {
ID string `json:"id"`
Label string `json:"label"`
Username string `json:"username"`
Password string `json:"password"`
TOTPSecret string `json:"totpSecret,omitempty"`
TOTPAlgorithm string `json:"totpAlgorithm,omitempty"` // SHA1 (default), SHA256, SHA512
TOTPDigits int `json:"totpDigits,omitempty"` // 6 (default) or 8
TOTPPeriod int `json:"totpPeriod,omitempty"` // 30 (default)
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}
Credential represents a stored ID/password pair for an agent.
type CredentialStore ¶
type CredentialStore struct {
// contains filtered or unexported fields
}
CredentialStore manages encrypted credential storage in SQLite.
func NewCredentialStore ¶
func NewCredentialStore() (*CredentialStore, error)
NewCredentialStore opens or creates the encrypted credential store.
func (*CredentialStore) AddCredential ¶
func (s *CredentialStore) AddCredential(agentID, label, username, password string, totp *TOTPParams) (*Credential, error)
AddCredential adds a new credential for an agent.
func (*CredentialStore) Close ¶
func (s *CredentialStore) Close() error
Close closes the database connection.
func (*CredentialStore) DeleteAllForAgent ¶
func (s *CredentialStore) DeleteAllForAgent(agentID string) error
DeleteAllForAgent removes all credentials for an agent.
func (*CredentialStore) DeleteCredential ¶
func (s *CredentialStore) DeleteCredential(agentID, credID string) error
DeleteCredential removes a credential by ID.
func (*CredentialStore) GetTOTPCode ¶
func (s *CredentialStore) GetTOTPCode(agentID, credID string) (string, int64, error)
GetTOTPCode generates the current TOTP code for a credential.
func (*CredentialStore) ListCredentials ¶
func (s *CredentialStore) ListCredentials(agentID string) ([]*Credential, error)
ListCredentials returns all credentials for an agent with secrets masked. Passwords and TOTP secrets are NOT decrypted — only metadata is returned.
func (*CredentialStore) RevealPassword ¶
func (s *CredentialStore) RevealPassword(agentID, credID string) (string, error)
RevealPassword returns the plaintext password for a credential.
func (*CredentialStore) UpdateCredential ¶
func (s *CredentialStore) UpdateCredential(agentID, credID string, label, username, password *string, totp *TOTPParams) (*Credential, error)
UpdateCredential updates an existing credential. Only non-nil fields are applied.
type DirectoryEntry ¶
type DirectoryEntry struct {
ID string `json:"id"`
Name string `json:"name"`
PublicProfile string `json:"publicProfile"`
}
DirectoryEntry is the minimal public info shared with other agents.
type GeminiBackend ¶
type GeminiBackend struct {
// contains filtered or unexported fields
}
GeminiBackend implements ChatBackend for the Gemini CLI.
func NewGeminiBackend ¶
func NewGeminiBackend(logger *slog.Logger) *GeminiBackend
func (*GeminiBackend) Available ¶
func (b *GeminiBackend) Available() bool
func (*GeminiBackend) Name ¶
func (b *GeminiBackend) Name() string
type GroupDM ¶
type GroupDM struct {
ID string `json:"id"`
Name string `json:"name"`
Members []GroupMember `json:"members"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}
GroupDM represents a group conversation between agents.
type GroupDMManager ¶
type GroupDMManager struct {
// contains filtered or unexported fields
}
GroupDMManager manages group DM CRUD, message posting, and notifications.
func NewGroupDMManager ¶
func NewGroupDMManager(agentMgr *Manager, logger *slog.Logger) *GroupDMManager
NewGroupDMManager creates a new GroupDMManager.
func (*GroupDMManager) APIBase ¶
func (m *GroupDMManager) APIBase() string
APIBase returns the current API base URL.
func (*GroupDMManager) Create ¶
func (m *GroupDMManager) Create(name string, memberIDs []string) (*GroupDM, error)
Create creates a new group DM with the given members.
func (*GroupDMManager) Delete ¶
func (m *GroupDMManager) Delete(id string) error
Delete removes a group DM and its data.
func (*GroupDMManager) Get ¶
func (m *GroupDMManager) Get(id string) (*GroupDM, bool)
Get returns a group DM by ID.
func (*GroupDMManager) GroupsForAgent ¶
func (m *GroupDMManager) GroupsForAgent(agentID string) []*GroupDM
GroupsForAgent returns all groups that contain the specified agent.
func (*GroupDMManager) List ¶
func (m *GroupDMManager) List() []*GroupDM
List returns all group DMs.
func (*GroupDMManager) Messages ¶
func (m *GroupDMManager) Messages(groupID string, limit int, before string) ([]*GroupMessage, bool, error)
Messages returns paginated messages for a group.
func (*GroupDMManager) PostMessage ¶
func (m *GroupDMManager) PostMessage(ctx context.Context, groupID, agentID, content string, notify bool) (*GroupMessage, error)
PostMessage posts a message to a group and optionally notifies other members. If notify is true, other members receive a system notification in their 1:1 chat. Set notify=false for messages sent from notification-triggered chats to prevent loops.
func (*GroupDMManager) RemoveAgent ¶
func (m *GroupDMManager) RemoveAgent(agentID string)
RemoveAgent removes an agent from all groups. Groups with fewer than 2 members are deleted.
func (*GroupDMManager) SetAPIBase ¶
func (m *GroupDMManager) SetAPIBase(base string)
SetAPIBase sets the base URL for agent-facing API docs in system prompts.
type GroupMember ¶
GroupMember is a participant in a group DM.
type GroupMessage ¶
type GroupMessage struct {
ID string `json:"id"`
AgentID string `json:"agentId"`
AgentName string `json:"agentName"`
Content string `json:"content"`
Timestamp string `json:"timestamp"`
}
GroupMessage is a single message in a group DM transcript.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager manages agent CRUD, chat orchestration, and lifecycle.
func NewManager ¶
NewManager creates a new agent manager.
func (*Manager) Chat ¶
func (m *Manager) Chat(ctx context.Context, agentID string, userMessage string, role string) (<-chan ChatEvent, error)
Chat sends a message to an agent and returns a channel of streaming events. The role parameter controls how the input message is stored in the transcript ("user" for interactive chat, "system" for cron-triggered messages).
func (*Manager) Create ¶
func (m *Manager) Create(cfg AgentConfig) (*Agent, error)
Create creates a new agent.
func (*Manager) Credentials ¶
func (m *Manager) Credentials() *CredentialStore
Credentials returns the credential store. Returns nil if the store failed to initialize.
func (*Manager) CronPaused ¶
CronPaused returns whether all cron jobs are globally paused.
func (*Manager) Directory ¶
func (m *Manager) Directory() []DirectoryEntry
Directory returns minimal public info for all agents (for agent-to-agent discovery).
func (*Manager) HasCredentials ¶
HasCredentials returns true if the credential store is available.
func (*Manager) MessagesPaginated ¶
func (m *Manager) MessagesPaginated(agentID string, limit int, before string) ([]*Message, bool, error)
MessagesPaginated returns messages with cursor-based pagination.
func (*Manager) ResetData ¶
ResetData removes conversation logs and memory but keeps settings, persona, avatar, and credentials.
func (*Manager) SetCronPaused ¶
SetCronPaused sets the global cron pause state and persists it.
func (*Manager) SetGroupDMManager ¶
func (m *Manager) SetGroupDMManager(gdm *GroupDMManager)
SetGroupDMManager sets the group DM manager reference. Called after both managers are created to avoid circular dependency.
type MemoryIndex ¶
type MemoryIndex struct {
// contains filtered or unexported fields
}
MemoryIndex provides FTS5-based keyword search across agent memory.
func OpenMemoryIndex ¶
func OpenMemoryIndex(agentID string, logger *slog.Logger) (*MemoryIndex, error)
OpenMemoryIndex opens or creates the FTS5 index for an agent.
func (*MemoryIndex) BuildContextFromQuery ¶
func (idx *MemoryIndex) BuildContextFromQuery(query string) string
BuildContextFromQuery searches the index and returns formatted context for injection into system prompt. Uses hybrid search (FTS5 + vector) when embeddings are available, falls back to FTS5 only.
func (*MemoryIndex) IndexFiles ¶
func (idx *MemoryIndex) IndexFiles(agentID string) error
IndexFiles indexes MEMORY.md and daily notes.
func (*MemoryIndex) IndexFilesIfStale ¶
func (idx *MemoryIndex) IndexFilesIfStale(agentID string)
IndexFilesIfStale re-indexes files only if they've changed since last index.
func (*MemoryIndex) IndexMessages ¶
func (idx *MemoryIndex) IndexMessages(agentID string) error
IndexMessages indexes messages from the JSONL transcript.
func (*MemoryIndex) IndexNewMessages ¶
func (idx *MemoryIndex) IndexNewMessages(agentID string)
IndexNewMessages incrementally indexes only new messages since last index.
func (*MemoryIndex) Reindex ¶
func (idx *MemoryIndex) Reindex(agentID string) error
Reindex re-indexes all sources for an agent (full rebuild).
func (*MemoryIndex) Search ¶
func (idx *MemoryIndex) Search(query string, limit int) ([]SearchResult, error)
Search performs a FTS5 search and returns relevant context snippets.
type Message ¶
type Message struct {
ID string `json:"id"`
Role string `json:"role"` // "user", "assistant", "system"
Content string `json:"content"`
Thinking string `json:"thinking,omitempty"` // intermediate reasoning (shown collapsed in UI)
ToolUses []ToolUse `json:"toolUses,omitempty"`
Timestamp string `json:"timestamp"` // RFC3339
Usage *Usage `json:"usage,omitempty"`
}
Message represents a single chat message in the transcript.
type MessagePreview ¶
type MessagePreview struct {
Content string `json:"content"`
Role string `json:"role"`
Timestamp string `json:"timestamp"`
}
MessagePreview is a short summary for agent list display.
type OTPEntry ¶
type OTPEntry struct {
Label string `json:"label"`
Issuer string `json:"issuer"`
Username string `json:"username"`
Secret string `json:"totpSecret"`
Algorithm string `json:"algorithm,omitempty"`
Digits int `json:"digits,omitempty"`
Period int `json:"period,omitempty"`
}
OTPEntry represents a parsed OTP entry from a QR code or migration payload.
func DecodeQRImage ¶
DecodeQRImage decodes a QR code from an image reader and returns parsed OTP entries.
func ParseOTPURI ¶
ParseOTPURI parses an otpauth:// or otpauth-migration:// URI and returns OTP entries.
type SearchResult ¶
type SearchResult struct {
Source string `json:"source"` // "message", "memory", "daily"
Snippet string `json:"snippet"` // text snippet with context
ContentHash string `json:"contentHash"` // for dedup/merge across search methods
Timestamp string `json:"timestamp"`
Score float64 `json:"score"`
}
SearchResult represents a single search hit.
type TOTPParams ¶
type TOTPParams struct {
Secret string
Algorithm string // SHA1, SHA256, SHA512
Digits int // 6 or 8
Period int // seconds
}
TOTPParams holds TOTP configuration for a credential.