base

package
v0.15.7 Latest Latest
Warning

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

Go to latest
Published: Mar 1, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Index

Constants

View Source
const ErrSenderNotConfigured = "sender not configured"

ErrSenderNotConfigured is returned when SendMessage is called but no sender function has been configured.

Variables

This section is empty.

Functions

func ExtractInt64FromMetadata

func ExtractInt64FromMetadata(msg *ChatMessage, key string) int64

ExtractInt64FromMetadata extracts an int64 value from message metadata. Returns 0 if the key doesn't exist or the value is not a numeric type.

func ExtractStringFromMetadata

func ExtractStringFromMetadata(msg *ChatMessage, key string) string

ExtractStringFromMetadata extracts a string value from message metadata. Returns empty string if the key doesn't exist or the value is not a string.

func ReadBody

func ReadBody(r *http.Request) ([]byte, error)

func RespondWithError

func RespondWithError(w http.ResponseWriter, code int, message string)

func RespondWithJSON

func RespondWithJSON(w http.ResponseWriter, code int, data any) error

func RespondWithText

func RespondWithText(w http.ResponseWriter, code int, text string)

Types

type Adapter

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

Adapter is the base adapter implementing common functionality

func NewAdapter

func NewAdapter(
	platform string,
	config Config,
	logger *slog.Logger,
	opts ...AdapterOption,
) *Adapter

NewAdapter creates a new base adapter

func (*Adapter) AddReaction added in v0.15.5

func (a *Adapter) AddReaction(ctx context.Context, reaction Reaction) error

AddReaction is a no-op by default, overridden by platforms that support it

func (*Adapter) DeleteMessage added in v0.15.5

func (a *Adapter) DeleteMessage(ctx context.Context, channelID, messageTS string) error

DeleteMessage is a no-op by default, overridden by platforms that support it

func (*Adapter) FindSessionByUserAndChannel added in v0.12.0

func (a *Adapter) FindSessionByUserAndChannel(userID, channelID string) *Session

FindSessionByUserAndChannel finds a session by matching user_id and channel_id This is useful for slash commands where we don't have the exact key Performance: O(1) using secondary index

func (*Adapter) GetOrCreateSession

func (a *Adapter) GetOrCreateSession(userID, botUserID, channelID string) string

GetOrCreateSession gets or creates a session using deterministic session ID generation Parameters:

  • userID: the user's ID on the platform
  • botUserID: the bot's user ID (for multi-bot scenarios, empty for single bot)
  • channelID: the channel/room ID (empty for DM)

Returns the generated session ID (deterministic based on inputs)

func (*Adapter) GetSession

func (a *Adapter) GetSession(key string) (*Session, bool)

GetSession retrieves a session by key

func (*Adapter) HandleMessage

func (a *Adapter) HandleMessage(ctx context.Context, msg *ChatMessage) error

HandleMessage handles incoming message (stub for interface compliance)

func (*Adapter) Handler

func (a *Adapter) Handler() MessageHandler

Handler returns the message handler (thread-safe)

func (*Adapter) Logger

func (a *Adapter) Logger() *slog.Logger

Logger returns the logger

func (*Adapter) Platform

func (a *Adapter) Platform() string

Platform returns the platform name

func (*Adapter) RemoveReaction added in v0.15.5

func (a *Adapter) RemoveReaction(ctx context.Context, reaction Reaction) error

RemoveReaction is a no-op by default, overridden by platforms that support it

func (*Adapter) SendMessage

func (a *Adapter) SendMessage(ctx context.Context, sessionID string, msg *ChatMessage) error

SendMessage sends a message (requires messageSender to be set)

func (*Adapter) SetHandler

func (a *Adapter) SetHandler(handler MessageHandler)

SetHandler sets the message handler (thread-safe)

func (*Adapter) SetLogger

func (a *Adapter) SetLogger(logger *slog.Logger)

SetLogger sets the logger

func (*Adapter) Start

func (a *Adapter) Start(ctx context.Context) error

Start starts the adapter

func (*Adapter) Stop

func (a *Adapter) Stop() error

Stop stops the adapter

func (*Adapter) SystemPrompt

func (a *Adapter) SystemPrompt() string

SystemPrompt returns the system prompt

func (*Adapter) UpdateMessage added in v0.15.5

func (a *Adapter) UpdateMessage(ctx context.Context, channelID, messageTS string, msg *ChatMessage) error

UpdateMessage is a no-op by default, overridden by platforms that support it

func (*Adapter) WebhookHandler

func (a *Adapter) WebhookHandler() http.Handler

WebhookHandler returns an http.Handler with all webhook endpoints registered

func (*Adapter) WebhookPath

func (a *Adapter) WebhookPath() string

WebhookPath returns the primary webhook path for this adapter

type AdapterOption

type AdapterOption func(*Adapter)

AdapterOption configures the base adapter

func WithHTTPHandler

func WithHTTPHandler(path string, handler http.HandlerFunc) AdapterOption

WithHTTPHandler adds an HTTP handler

func WithMessageParser

func WithMessageParser(parser MessageParser) AdapterOption

WithMessageParser sets the message parser

func WithMessageSender

func WithMessageSender(sender MessageSender) AdapterOption

WithMessageSender sets the message sender

func WithMetadataExtractor

func WithMetadataExtractor(extractor MetadataExtractor) AdapterOption

WithMetadataExtractor sets the metadata extractor

func WithSessionIDGenerator added in v0.12.0

func WithSessionIDGenerator(generator SessionIDGenerator) AdapterOption

WithSessionIDGenerator sets the session ID generator Use this to customize session ID generation per platform

func WithSessionTimeout

func WithSessionTimeout(timeout time.Duration) AdapterOption

WithSessionTimeout sets the session timeout

func WithoutServer

func WithoutServer() AdapterOption

WithoutServer disables the embedded HTTP server Use this when running adapters under a unified server

type Attachment

type Attachment struct {
	Type     string `json:"type"`
	URL      string `json:"url"`
	Title    string `json:"title"`
	Text     string `json:"text"`
	ThumbURL string `json:"thumb_url,omitempty"`
}

type ChatAdapter

type ChatAdapter interface {
	Platform() string
	SystemPrompt() string
	Start(ctx context.Context) error
	Stop() error
	SendMessage(ctx context.Context, sessionID string, msg *ChatMessage) error
	HandleMessage(ctx context.Context, msg *ChatMessage) error
	SetHandler(MessageHandler)
}

type ChatMessage

type ChatMessage struct {
	Type        MessageType // Message type for rendering decisions
	Platform    string
	SessionID   string
	UserID      string
	Content     string
	MessageID   string
	Timestamp   time.Time
	Metadata    map[string]any
	RichContent *RichContent
}

type Config

type Config struct {
	ServerAddr   string
	SystemPrompt string
}

Config is the common configuration for all adapters

type EngineSupport added in v0.15.5

type EngineSupport interface {
	SetEngine(eng *engine.Engine)
}

EngineSupport defines optional interface for adapters that need engine integration

type HTTPClient

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

HTTPClient provides common HTTP request patterns for chat adapters. This eliminates the duplicate HTTP request building code across adapters.

func NewHTTPClient

func NewHTTPClient() *HTTPClient

NewHTTPClient creates a new HTTPClient with the default http.Client.

func NewHTTPClientWithConfig

func NewHTTPClientWithConfig(timeout time.Duration, maxRetries int) *HTTPClient

NewHTTPClientWithConfig creates a new HTTPClient with custom configuration.

func (*HTTPClient) Get

func (c *HTTPClient) Get(ctx context.Context, url string, headers map[string]string) ([]byte, error)

Get sends a GET request and returns the response body.

func (*HTTPClient) PostJSON

func (c *HTTPClient) PostJSON(ctx context.Context, url string, payload any, headers map[string]string) ([]byte, error)

PostJSON sends a POST request with a JSON body and returns the response body. headers is a map of header key-value pairs to add to the request.

func (*HTTPClient) PostJSONWithResponse

func (c *HTTPClient) PostJSONWithResponse(ctx context.Context, url string, payload any, headers map[string]string, dest any) error

PostJSONWithResponse sends a POST request and decodes the JSON response into dest.

type MessageHandler

type MessageHandler func(ctx context.Context, msg *ChatMessage) error

type MessageOperations added in v0.15.5

type MessageOperations interface {
	DeleteMessage(ctx context.Context, channelID, messageTS string) error
	AddReaction(ctx context.Context, reaction Reaction) error
	RemoveReaction(ctx context.Context, reaction Reaction) error
	UpdateMessage(ctx context.Context, channelID, messageTS string, msg *ChatMessage) error
}

MessageOperations defines platform-specific message operations

type MessageParser

type MessageParser func(body []byte, metadata map[string]any) (*ChatMessage, error)

MessageParser parses incoming requests into ChatMessage

type MessageSender

type MessageSender func(ctx context.Context, sessionID string, msg *ChatMessage) error

MessageSender sends messages to the platform

type MessageType added in v0.13.0

type MessageType string

MessageType defines the normalized message types across all chat platforms

const (
	// MessageTypeThinking indicates the AI is reasoning or thinking
	MessageTypeThinking MessageType = "thinking"
	// MessageTypeAnswer indicates text output from the AI
	MessageTypeAnswer MessageType = "answer"
	// MessageTypeToolUse indicates a tool invocation is starting
	MessageTypeToolUse MessageType = "tool_use"
	// MessageTypeToolResult indicates a tool execution result
	MessageTypeToolResult MessageType = "tool_result"
	// MessageTypeError indicates an error occurred
	MessageTypeError MessageType = "error"
	// MessageTypePlanMode indicates AI is in plan mode and generating a plan
	MessageTypePlanMode MessageType = "plan_mode"
	// MessageTypeExitPlanMode indicates AI completed planning and requests user approval
	MessageTypeExitPlanMode MessageType = "exit_plan_mode"
	// MessageTypeAskUserQuestion indicates AI is asking a clarifying question
	MessageTypeAskUserQuestion MessageType = "ask_user_question"
	// MessageTypeDangerBlock indicates a dangerous operation confirmation block
	MessageTypeDangerBlock MessageType = "danger_block"
	// MessageTypeSessionStats indicates session statistics
	MessageTypeSessionStats MessageType = "session_stats"
	// MessageTypeCommandProgress indicates a slash command is executing with progress updates
	MessageTypeCommandProgress MessageType = "command_progress"
	// MessageTypeCommandComplete indicates a slash command has completed
	MessageTypeCommandComplete MessageType = "command_complete"
	// MessageTypeSystem indicates a system-level message
	MessageTypeSystem MessageType = "system"
	// MessageTypeUser indicates a user message reflection
	MessageTypeUser MessageType = "user"
	// MessageTypeStepStart indicates a new step/milestone (OpenCode specific)
	MessageTypeStepStart MessageType = "step_start"
	// MessageTypeStepFinish indicates a step/milestone completed (OpenCode specific)
	MessageTypeStepFinish MessageType = "step_finish"
	// MessageTypeRaw indicates unparsed raw output (fallback)
	MessageTypeRaw MessageType = "raw"
	// MessageTypeSessionStart indicates a new session is starting (cold start)
	MessageTypeSessionStart MessageType = "session_start"
	// MessageTypeEngineStarting indicates the engine is starting up
	MessageTypeEngineStarting MessageType = "engine_starting"
	// MessageTypeUserMessageReceived indicates user message has been received
	MessageTypeUserMessageReceived MessageType = "user_message_received"
	// MessageTypePermissionRequest indicates a permission request from Claude Code
	MessageTypePermissionRequest MessageType = "permission_request"
)

type MetadataExtractor

type MetadataExtractor func(update any) map[string]any

MetadataExtractor extracts platform-specific metadata from incoming requests

type ParseMode

type ParseMode string
const (
	ParseModeNone     ParseMode = ""
	ParseModeMarkdown ParseMode = "markdown"
	ParseModeHTML     ParseMode = "html"
)

type PendingMessage added in v0.15.7

type PendingMessage struct {
	SessionID   string
	ChannelID   string
	MessageTS   string
	OriginalMsg *ChatMessage
	CreatedAt   time.Time
	Reason      string
}

PendingMessage represents a message pending approval

type PendingMessageStore added in v0.15.7

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

PendingMessageStore stores pending messages awaiting approval

func NewPendingMessageStore added in v0.15.7

func NewPendingMessageStore(ttl time.Duration) *PendingMessageStore

NewPendingMessageStore creates a new pending message store

func (*PendingMessageStore) Delete added in v0.15.7

func (s *PendingMessageStore) Delete(sessionID string)

Delete removes a pending message from the store

func (*PendingMessageStore) Get added in v0.15.7

func (s *PendingMessageStore) Get(sessionID string) (*PendingMessage, bool)

Get retrieves a pending message by session ID

func (*PendingMessageStore) Store added in v0.15.7

func (s *PendingMessageStore) Store(sessionID string, msg *PendingMessage)

Store adds a pending message to the store

type Reaction added in v0.11.1

type Reaction struct {
	Name      string // emoji name (e.g., "thumbsup", "+1")
	Channel   string
	Timestamp string // message timestamp to react to
}

Reaction represents a reaction to add to a message

type RichContent

type RichContent struct {
	ParseMode      ParseMode
	InlineKeyboard any
	Blocks         []any
	Embeds         []any
	Attachments    []Attachment
	Reactions      []Reaction
}

type SenderFunc

type SenderFunc func(ctx context.Context, sessionID string, msg *ChatMessage) error

SenderFunc is the function signature for sending messages to a platform.

type SenderWithMutex

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

SenderWithMutex provides thread-safe sender management for chat adapters. This eliminates the duplicate sender/senderMu pattern across all adapters.

func NewSenderWithMutex

func NewSenderWithMutex() *SenderWithMutex

NewSenderWithMutex creates a new SenderWithMutex with no sender configured.

func NewSenderWithMutexFunc

func NewSenderWithMutexFunc(sender SenderFunc) *SenderWithMutex

NewSenderWithMutexFunc creates a new SenderWithMutex with an initial sender.

func (*SenderWithMutex) HasSender

func (s *SenderWithMutex) HasSender() bool

HasSender returns true if a sender has been configured.

func (*SenderWithMutex) SendMessage

func (s *SenderWithMutex) SendMessage(ctx context.Context, sessionID string, msg *ChatMessage) error

SendMessage sends a message using the configured sender. Thread-safe. Returns ErrSenderNotConfigured if no sender has been set.

func (*SenderWithMutex) Sender

func (s *SenderWithMutex) Sender() SenderFunc

Sender returns the current sender function (may be nil). Note: This does not acquire the lock, so the caller should ensure thread-safety if the sender might be modified concurrently.

func (*SenderWithMutex) SetSender

func (s *SenderWithMutex) SetSender(fn SenderFunc)

SetSender sets the sender function. Thread-safe.

type Session

type Session struct {
	SessionID  string
	UserID     string
	Platform   string
	LastActive time.Time
}

Session represents a user session in a chat platform

type SessionIDGenerator added in v0.12.0

type SessionIDGenerator interface {
	// Generate creates a deterministic session ID based on:
	// - platform: the platform name (e.g., "slack", "telegram")
	// - userID: the user's ID on the platform
	// - botUserID: the bot's user ID (for multi-bot scenarios)
	// - channelID: the channel/room ID (empty for DM)
	Generate(platform, userID, botUserID, channelID string) string
}

SessionIDGenerator generates deterministic session IDs

type SessionOperations added in v0.15.5

type SessionOperations interface {
	GetSession(key string) (*Session, bool)
	FindSessionByUserAndChannel(userID, channelID string) *Session
}

SessionOperations defines platform-specific session operations Note: Session is defined in base/adapter.go to avoid circular dependencies

type SimpleKeyGenerator added in v0.12.0

type SimpleKeyGenerator struct{}

SimpleKeyGenerator generates session IDs using a simple concatenated key This is useful for debugging or when you don't need UUID format

func NewSimpleKeyGenerator added in v0.12.0

func NewSimpleKeyGenerator() *SimpleKeyGenerator

NewSimpleKeyGenerator creates a new simple key generator

func (*SimpleKeyGenerator) Generate added in v0.12.0

func (g *SimpleKeyGenerator) Generate(platform, userID, botUserID, channelID string) string

Generate creates a session ID by concatenating all components Format: platform:userID:botUserID:channelID

type UUID5Generator added in v0.12.0

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

UUID5Generator generates session IDs using UUID5 (SHA1 hash) This ensures the same inputs always produce the same session ID

func NewUUID5Generator added in v0.12.0

func NewUUID5Generator(namespace string) *UUID5Generator

NewUUID5Generator creates a new UUID5 generator with the given namespace

func (*UUID5Generator) Generate added in v0.12.0

func (g *UUID5Generator) Generate(platform, userID, botUserID, channelID string) string

Generate creates a deterministic session ID Format: UUID5(namespace + ":session:" + platform + ":" + userID + ":" + botUserID + ":" + channelID)

type WebhookProvider

type WebhookProvider interface {
	WebhookPath() string
	WebhookHandler() http.Handler
}

WebhookProvider exposes HTTP handlers for unified server integration

type WebhookRunner

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

WebhookRunner manages the lifecycle of webhook processing goroutines. This eliminates the duplicate webhookWg pattern across all adapters.

func NewWebhookRunner

func NewWebhookRunner(logger *slog.Logger) *WebhookRunner

NewWebhookRunner creates a new WebhookRunner.

func (*WebhookRunner) Run

func (r *WebhookRunner) Run(ctx context.Context, handler MessageHandler, msg *ChatMessage)

Run executes the handler in a goroutine and tracks its completion. If handler is nil, this is a no-op.

func (*WebhookRunner) Stop

func (r *WebhookRunner) Stop() bool

Stop is an alias for WaitDefault for API consistency with adapters.

func (*WebhookRunner) Wait

func (r *WebhookRunner) Wait(timeout time.Duration) bool

Wait blocks until all running goroutines complete or timeout occurs. Returns true if all goroutines completed, false if timeout occurred.

func (*WebhookRunner) WaitDefault

func (r *WebhookRunner) WaitDefault() bool

WaitDefault blocks with the default 5 second timeout.

Jump to

Keyboard shortcuts

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