base

package
v0.21.0 Latest Latest
Warning

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

Go to latest
Published: Mar 6, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Index

Constants

View Source
const (
	DefaultDedupWindow  = 5 * time.Second
	DefaultDedupCleanup = 10 * time.Second
)

DefaultDedupWindow 默去重配置 (reduced from 30s to 5s per Issue #129) 30 second TTL was too long, causing legitimate messages to be incorrectly filtered as duplicates

View Source
const DefaultChunkLimit = 4000

DefaultChunkLimit is the default maximum chunk size.

View Source
const ErrSenderNotConfigured = "sender not configured"

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

Variables

View Source
var (
	ErrNilStore                 = errors.New("storage store is nil")
	ErrNilSessionManager        = errors.New("session manager is nil")
	ErrMissingChatSessionID     = errors.New("chat_session_id is required")
	ErrMissingEngineSessionID   = errors.New("engine_session_id is required")
	ErrMissingProviderSessionID = errors.New("provider_session_id is required")
	ErrMissingContent           = errors.New("content is required")
)

消息存储相关错误定义

View Source
var ErrBufferFull = errors.New("stream buffer full, cannot accept new chunks")

ErrBufferFull 缓冲区已满错误

View Source
var ErrNotSupported = errors.New("operation not supported on this platform")

ErrNotSupported is returned by optional interface methods when the platform does not support the requested operation.

View Source
var GlobalDangerRegistry = &DangerApprovalRegistry{}

GlobalDangerRegistry is the singleton registry for danger block approvals.

Functions

func CheckMethod added in v0.21.0

func CheckMethod(w http.ResponseWriter, r *http.Request, allowed string) bool

CheckMethod validates the HTTP method and sends error response if invalid. Returns true if method is valid, false otherwise (response already sent).

Usage:

if !base.CheckMethod(w, r, http.MethodPost) {
    return
}

func CheckMethodGET added in v0.21.0

func CheckMethodGET(w http.ResponseWriter, r *http.Request) bool

CheckMethodGET is a convenience wrapper for GET method check.

func CheckMethodPOST added in v0.21.0

func CheckMethodPOST(w http.ResponseWriter, r *http.Request) bool

CheckMethodPOST is a convenience wrapper for POST method check.

func ChunkMessage added in v0.21.0

func ChunkMessage(text string, cfg ChunkerConfig) []string

ChunkMessage splits a text message into chunks that fit within the limit. It attempts to split at word boundaries to avoid breaking words. Each chunk is prefixed with chunkNum/totalChunks if numbering is enabled.

func ChunkMessageSimple added in v0.21.0

func ChunkMessageSimple(text string, maxLen int) []string

ChunkMessageSimple splits text by byte length without word boundary preservation. Use this for platforms that don't need word-aware splitting.

func CreateDefaultStrategy added in v0.21.0

func CreateDefaultStrategy() storage.StorageStrategy

CreateDefaultStrategy 创建默认存储策略

func CreateSessionManager added in v0.21.0

func CreateSessionManager(namespace string) session.SessionManager

CreateSessionManager 创建 SessionManager

func CreateStorageFromType added in v0.21.0

func CreateStorageFromType(storageType string, config map[string]any) (storage.ChatAppMessageStore, error)

CreateStorageFromType 根据类型创建存储后端

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 ProcessWebhook added in v0.21.0

func ProcessWebhook[T any](
	h *WebhookHandler,
	w http.ResponseWriter,
	r *http.Request,
	parse ParseFunc[T],
	handle HandlerFunc[T],
) bool

ProcessWebhook executes the webhook processing pipeline: 1. Method validation (POST only) 2. Body reading 3. Signature verification (if configured) 4. Event parsing 5. Event handling

Returns true if processing was successful, false otherwise. Error responses are automatically written to the client.

func ProcessWebhookNoVerify added in v0.21.0

func ProcessWebhookNoVerify[T any](
	logger *slog.Logger,
	w http.ResponseWriter,
	r *http.Request,
	parse ParseFunc[T],
	handle HandlerFunc[T],
) bool

ProcessWebhookNoVerify is like ProcessWebhook but skips signature verification.

func ReadBody

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

func ReadBodyWithError added in v0.21.0

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

ReadBodyWithError reads the request body and returns an error on failure. This is the most basic form - just read and return.

func ReadBodyWithLog added in v0.21.0

func ReadBodyWithLog(w http.ResponseWriter, r *http.Request, logger *slog.Logger) ([]byte, bool)

ReadBodyWithLog reads the request body and logs errors using the provided logger. Returns (body, true) on success, (nil, false) on failure (response already sent).

Usage:

body, ok := base.ReadBodyWithLog(w, r, logger)
if !ok {
    return // response already sent
}

func ReadBodyWithLogAndClose added in v0.21.0

func ReadBodyWithLogAndClose(w http.ResponseWriter, r *http.Request, logger *slog.Logger) ([]byte, bool)

ReadBodyWithLogAndClose is like ReadBodyWithLog but also closes the body. Use this when you don't need the body after reading.

Usage:

body, ok := base.ReadBodyWithLogAndClose(w, r, logger)
if !ok {
    return
}

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)

func RuneCount added in v0.18.0

func RuneCount(s string) int

RuneCount counts Unicode runes (characters) instead of bytes

func TruncateByRune added in v0.18.0

func TruncateByRune(s string, maxRunes int) string

TruncateByRune truncates string by rune count, not byte count (no ellipsis)

func TruncateWithEllipsis added in v0.18.0

func TruncateWithEllipsis(s string, maxRunes int) string

TruncateWithEllipsis truncates string by rune count with ellipsis

func VerifyRequest added in v0.21.0

func VerifyRequest(verifier SignatureVerifier, r *http.Request, body []byte) bool

VerifyRequest is a convenience function that checks if a verifier is configured and verifies the request. Returns true if no verifier is configured or if verification passes.

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) AppendStream added in v0.18.0

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

AppendStream 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, threadID 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)
  • threadID: the thread/topic ID (empty if not applicable)

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) SendMessage

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

SendMessage sends a message (requires messageSender to be set)

func (*Adapter) SendThreadReply added in v0.18.0

func (a *Adapter) SendThreadReply(ctx context.Context, channelID, threadTS, text string) error

SendThreadReply is a no-op by default, overridden by platforms that support it (Space Folding)

func (*Adapter) SetAssistantStatus added in v0.18.0

func (a *Adapter) SetAssistantStatus(ctx context.Context, channelID, threadTS, status string) error

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

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) SetMessageStore added in v0.21.0

func (a *Adapter) SetMessageStore(store *MessageStorePlugin)

SetMessageStore sets the message storage plugin (thread-safe)

func (*Adapter) SetProviderType added in v0.21.0

func (a *Adapter) SetProviderType(providerType string)

SetProviderType sets the provider type for storage (thread-safe)

func (*Adapter) SetSessionManager added in v0.21.0

func (a *Adapter) SetSessionManager(mgr session.SessionManager)

SetSessionManager sets the session manager (thread-safe)

func (*Adapter) Start

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

Start starts the adapter

func (*Adapter) StartStream added in v0.18.0

func (a *Adapter) StartStream(ctx context.Context, channelID, threadTS string) (string, error)

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

func (*Adapter) Stop

func (a *Adapter) Stop() error

Stop stops the adapter

func (*Adapter) StopStream added in v0.18.0

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

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

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 WithCleanupInterval added in v0.21.0

func WithCleanupInterval(interval time.Duration) AdapterOption

WithCleanupInterval sets the session cleanup interval

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)
}

ChatAdapter is the core interface that ALL platform adapters MUST implement. This defines the minimum contract for a chat platform integration.

Required implementations:

  • Platform() - Returns platform identifier
  • SystemPrompt() - Returns system prompt for AI
  • Start(ctx) - Starts the adapter
  • Stop() - Stops the adapter
  • SendMessage(ctx, sessionID, msg) - Sends a message
  • HandleMessage(ctx, msg) - Handles incoming messages
  • SetHandler(handler) - Sets the message handler

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 ChunkerConfig added in v0.21.0

type ChunkerConfig struct {
	// MaxLen is the maximum character limit per chunk.
	// If 0, defaults to DefaultChunkLimit.
	MaxLen int

	// PreserveWords attempts to break at word boundaries.
	// If false, may break in the middle of words.
	PreserveWords bool

	// AddNumbering prefixes chunks with [1/N] notation.
	AddNumbering bool
}

ChunkerConfig holds configuration for message chunking.

type Config

type Config struct {
	ServerAddr   string
	SystemPrompt string
}

Config is the common configuration for all adapters

type DangerApprovalRegistry added in v0.18.0

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

DangerApprovalRegistry manages pending danger block approvals. Used by chatapps to block on WAF interception until user approves/denies via Slack buttons.

func (*DangerApprovalRegistry) Cancel added in v0.18.0

func (r *DangerApprovalRegistry) Cancel(sessionID string)

Cancel removes a pending approval without resolving it (e.g. on context cancellation).

func (*DangerApprovalRegistry) Register added in v0.18.0

func (r *DangerApprovalRegistry) Register(sessionID string) chan bool

Register creates a pending approval channel for the given sessionID. Returns the channel to block on. The caller should select on ctx.Done() and this channel.

func (*DangerApprovalRegistry) Resolve added in v0.18.0

func (r *DangerApprovalRegistry) Resolve(sessionID string, approved bool) bool

Resolve resolves a pending approval for the given sessionID. Returns true if the sessionID was found and resolved, false otherwise.

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 HMACSHA256Verifier added in v0.21.0

type HMACSHA256Verifier struct {
	// Secret is the signing secret/key
	Secret string

	// SignatureHeader is the header name containing the signature
	SignatureHeader string

	// TimestampHeader is the header name containing the timestamp (optional)
	TimestampHeader string

	// Prefix is the signature prefix (e.g., "v0" for Slack, "" for others)
	Prefix string

	// IncludeTimestamp whether to include timestamp in signature computation
	IncludeTimestamp bool
}

HMACSHA256Verifier implements HMAC-SHA256 signature verification. Used by: Slack, DingTalk, Feishu

func (*HMACSHA256Verifier) Verify added in v0.21.0

func (v *HMACSHA256Verifier) Verify(r *http.Request, body []byte) bool

Verify implements SignatureVerifier for HMAC-SHA256.

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 HandlerFunc added in v0.21.0

type HandlerFunc[T any] func(event T) error

HandlerFunc is the function signature for handling parsed events.

type MessageContext added in v0.21.0

type MessageContext struct {
	// ChatApp 层信息
	ChatSessionID     string
	ChatPlatform      string
	ChatUserID        string
	ChatBotUserID     string
	ChatChannelID     string
	ChatThreadID      string
	EngineSessionID   uuid.UUID
	EngineNamespace   string
	ProviderSessionID string
	ProviderType      string
	// 消息信息
	MessageType types.MessageType
	Direction   MessageDirection
	Content     string
	Metadata    map[string]any
	// 可选追踪信息
	RequestID string
	TraceID   string
}

MessageContext 消息存储上下文

func (*MessageContext) Validate added in v0.21.0

func (mc *MessageContext) Validate() error

Validate 验证必填字段

type MessageContextBuilder added in v0.21.0

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

MessageContextBuilder 构建器模式

func NewMessageContextBuilder added in v0.21.0

func NewMessageContextBuilder() *MessageContextBuilder

NewMessageContextBuilder 创建构建器

func (*MessageContextBuilder) Build added in v0.21.0

Build 构建并验证

func (*MessageContextBuilder) WithChatSession added in v0.21.0

func (b *MessageContextBuilder) WithChatSession(sessionID, platform, userID, botUserID, channelID, threadID string) *MessageContextBuilder

WithChatSession 设置 ChatApp 层 Session 信息

func (*MessageContextBuilder) WithEngineSession added in v0.21.0

func (b *MessageContextBuilder) WithEngineSession(sessionID uuid.UUID, namespace string) *MessageContextBuilder

WithEngineSession 设置 Engine 层 Session 信息

func (*MessageContextBuilder) WithMessage added in v0.21.0

func (b *MessageContextBuilder) WithMessage(msgType types.MessageType, direction MessageDirection, content string) *MessageContextBuilder

WithMessage 设置消息信息

func (*MessageContextBuilder) WithMetadata added in v0.21.0

func (b *MessageContextBuilder) WithMetadata(key string, value any) *MessageContextBuilder

WithMetadata 添加元数据

func (*MessageContextBuilder) WithProviderSession added in v0.21.0

func (b *MessageContextBuilder) WithProviderSession(sessionID, providerType string) *MessageContextBuilder

WithProviderSession 设置 Provider 层 Session 信息

type MessageDirection added in v0.21.0

type MessageDirection string

MessageDirection 消息方向

const (
	DirectionUserToBot MessageDirection = "user_to_bot"
	DirectionBotToUser MessageDirection = "bot_to_user"
)

type MessageHandler

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

MessageHandler is the function signature for handling incoming messages.

type MessageOperations added in v0.15.5

type MessageOperations interface {
	DeleteMessage(ctx context.Context, channelID, messageTS string) error
	UpdateMessage(ctx context.Context, channelID, messageTS string, msg *ChatMessage) error
	// SetAssistantStatus sets the native assistant status text at the bottom of the thread
	// Used to drive dynamic status hints (e.g., "Thinking...", "Searching code...")
	SetAssistantStatus(ctx context.Context, channelID, threadTS, status string) error
	// SendThreadReply sends a message as a reply inside a thread (Space Folding)
	SendThreadReply(ctx context.Context, channelID, threadTS, text string) error
	// StartStream starts a native streaming message, returns message_ts as anchor for subsequent updates
	StartStream(ctx context.Context, channelID, threadTS string) (string, error)
	// AppendStream incrementally pushes content to an existing stream
	AppendStream(ctx context.Context, channelID, messageTS, content string) error
	// StopStream ends the stream and finalizes the message
	StopStream(ctx context.Context, channelID, messageTS string) error
}

MessageOperations is an OPTIONAL interface for advanced message operations. Implement this if your platform supports:

  • Deleting messages
  • Updating/editing messages
  • Native streaming (start/append/stop)
  • Thread replies
  • Assistant status indicators

Platforms with limited support can implement partial methods and return ErrNotSupported for unsupported 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 MessageStoreInitializer added in v0.21.0

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

MessageStoreInitializer 消息存储插件初始化器

func NewMessageStoreInitializer added in v0.21.0

func NewMessageStoreInitializer(logger *slog.Logger) *MessageStoreInitializer

NewMessageStoreInitializer 创建初始化器

func (*MessageStoreInitializer) InitializeFromConfig added in v0.21.0

InitializeFromConfig 从配置初始化消息存储插件

type MessageStorePlugin added in v0.21.0

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

MessageStorePlugin 消息存储插件 (协调器,SRP)

func BuildMessageStorePlugin added in v0.21.0

func BuildMessageStorePlugin(
	storageType string,
	storageConfig map[string]any,
	namespace string,
	providerType string,
	streamEnabled bool,
	streamTimeout time.Duration,
	streamMaxBuffers int,
) (*MessageStorePlugin, error)

BuildMessageStorePlugin 从配置构建完整的消息存储插件

func NewMessageStorePlugin added in v0.21.0

func NewMessageStorePlugin(cfg MessageStorePluginConfig) (*MessageStorePlugin, error)

NewMessageStorePlugin 创建消息存储插件

func (*MessageStorePlugin) Close added in v0.21.0

func (p *MessageStorePlugin) Close() error

Close 关闭插件

func (*MessageStorePlugin) GetSessionMeta added in v0.21.0

func (p *MessageStorePlugin) GetSessionMeta(ctx context.Context, chatSessionID string) (*storage.SessionMeta, error)

GetSessionMeta 获取会话元数据

func (*MessageStorePlugin) Initialize added in v0.21.0

func (p *MessageStorePlugin) Initialize(ctx context.Context) error

Initialize 初始化插件

func (*MessageStorePlugin) ListUserSessions added in v0.21.0

func (p *MessageStorePlugin) ListUserSessions(ctx context.Context, platform, userID string) ([]string, error)

ListUserSessions 列出用户的所有会话

func (*MessageStorePlugin) OnBotResponse added in v0.21.0

func (p *MessageStorePlugin) OnBotResponse(ctx context.Context, msgCtx *MessageContext) error

OnBotResponse 处理机器人响应存储

func (*MessageStorePlugin) OnStreamComplete added in v0.21.0

func (p *MessageStorePlugin) OnStreamComplete(ctx context.Context, sessionID string, msgCtx *MessageContext) error

OnStreamComplete 标记流式消息完成并存储

func (*MessageStorePlugin) OnUserMessage added in v0.21.0

func (p *MessageStorePlugin) OnUserMessage(ctx context.Context, msgCtx *MessageContext) error

OnUserMessage 处理用户消息存储

type MessageStorePluginConfig added in v0.21.0

type MessageStorePluginConfig struct {
	Store            storage.ChatAppMessageStore
	SessionManager   session.SessionManager
	Strategy         storage.StorageStrategy
	StreamEnabled    bool
	StreamTimeout    time.Duration
	StreamMaxBuffers int
	Logger           *slog.Logger
}

MessageStorePluginConfig 配置

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 NoOpVerifier added in v0.21.0

type NoOpVerifier struct{}

NoOpVerifier is a verifier that always returns true. Use this when signature verification is disabled or not needed.

func (*NoOpVerifier) Verify added in v0.21.0

func (v *NoOpVerifier) Verify(_ *http.Request, _ []byte) bool

Verify always returns true.

type ParseFunc added in v0.21.0

type ParseFunc[T any] func(body []byte) (T, error)

ParseFunc is the function signature for parsing request body into events.

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) Stop added in v0.17.0

func (s *PendingMessageStore) Stop()

Stop stops the cleanup goroutine

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 RichContent

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

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
	ChannelID  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)
	// - threadID: the thread/topic ID (empty if not applicable)
	Generate(platform, userID, botUserID, channelID, threadID 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 is an OPTIONAL interface for session management. Implement this if your platform needs direct session access.

type SignatureVerifier added in v0.21.0

type SignatureVerifier interface {
	// Verify checks if the request signature is valid.
	// Returns true if valid, false otherwise.
	Verify(r *http.Request, body []byte) bool
}

SignatureVerifier defines the interface for webhook signature verification. Different platforms implement different verification strategies.

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, threadID string) string

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

type StatusProvider added in v0.18.0

type StatusProvider interface {
	// SetStatus sets current status, adapter converts to native API or bubble message
	// channelID and threadTS specify where to display the status
	SetStatus(ctx context.Context, channelID, threadTS string, status StatusType, text string) error

	// ClearStatus clears status indicator
	ClearStatus(ctx context.Context, channelID, threadTS string) error
}

StatusProvider defines the abstraction for status notification Follows Dependency Inversion Principle - adapters decide the concrete implementation

type StatusType added in v0.18.0

type StatusType string

StatusType defines AI working states

const (
	StatusInitializing StatusType = "initializing"
	StatusThinking     StatusType = "thinking"
	StatusToolUse      StatusType = "tool_use"
	StatusToolResult   StatusType = "tool_result"
	StatusAnswering    StatusType = "answering"
	StatusIdle         StatusType = "idle"
)

func MessageTypeToStatusType added in v0.18.0

func MessageTypeToStatusType(msgType MessageType) StatusType

MessageTypeToStatusType converts MessageType to StatusType for status notification Returns StatusIdle for unrecognized types

type StreamBuffer added in v0.21.0

type StreamBuffer struct {
	SessionID   string
	Chunks      []string
	IsComplete  bool
	LastUpdated time.Time
	// contains filtered or unexported fields
}

StreamBuffer 流式消息缓冲区 (内存)

func (*StreamBuffer) Append added in v0.21.0

func (b *StreamBuffer) Append(chunk string)

Append 追加 chunk 到缓冲区

func (*StreamBuffer) Clear added in v0.21.0

func (b *StreamBuffer) Clear()

Clear 清空缓冲区

func (*StreamBuffer) IsExpired added in v0.21.0

func (b *StreamBuffer) IsExpired(timeout time.Duration) bool

IsExpired 检查缓冲区是否超时

func (*StreamBuffer) Merge added in v0.21.0

func (b *StreamBuffer) Merge() string

Merge 合并所有 chunk 为完整消息

type StreamMessageStore added in v0.21.0

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

StreamMessageStore 流式消息存储管理器

func NewStreamMessageStore added in v0.21.0

func NewStreamMessageStore(store storage.ChatAppMessageStore, timeout time.Duration, maxBuffers int, logger *slog.Logger) *StreamMessageStore

NewStreamMessageStore 创建流式消息存储管理器

func (*StreamMessageStore) Close added in v0.21.0

func (s *StreamMessageStore) Close()

Close 停止清理 goroutine

func (*StreamMessageStore) GetBuffer added in v0.21.0

func (s *StreamMessageStore) GetBuffer(sessionID string) *StreamBuffer

GetBuffer 获取指定 session 的缓冲区 (用于调试/监控)

func (*StreamMessageStore) GetBufferCount added in v0.21.0

func (s *StreamMessageStore) GetBufferCount() int

GetBufferCount 获取当前活跃的缓冲区数量

func (*StreamMessageStore) OnStreamChunk added in v0.21.0

func (s *StreamMessageStore) OnStreamChunk(ctx context.Context, sessionID, chunk string) error

OnStreamChunk 接收流式消息块 (不存储,仅缓存)

func (*StreamMessageStore) OnStreamComplete added in v0.21.0

func (s *StreamMessageStore) OnStreamComplete(ctx context.Context, sessionID string, msg *storage.ChatAppMessage) error

OnStreamComplete 流式消息完成 (合并后存储)

type StreamWriter added in v0.18.0

type StreamWriter interface {
	io.Writer
	io.Closer
	// MessageTS returns the message timestamp after stream starts
	MessageTS() string
}

StreamWriter defines the interface for streaming message writes Platform-agnostic abstraction for native streaming support

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, threadID string) string

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

type WebhookHandler added in v0.21.0

type WebhookHandler struct {
	Logger   *slog.Logger
	Verifier SignatureVerifier
}

WebhookHandler provides common utilities for webhook processing.

func NewWebhookHandler added in v0.21.0

func NewWebhookHandler(logger *slog.Logger, verifier SignatureVerifier) *WebhookHandler

NewWebhookHandler creates a new WebhookHandler.

func (*WebhookHandler) RespondJSON added in v0.21.0

func (h *WebhookHandler) RespondJSON(w http.ResponseWriter, status int, data any)

RespondJSON writes a JSON response.

func (*WebhookHandler) RespondOK added in v0.21.0

func (h *WebhookHandler) RespondOK(w http.ResponseWriter)

RespondOK writes a simple OK response.

func (*WebhookHandler) RespondText added in v0.21.0

func (h *WebhookHandler) RespondText(w http.ResponseWriter, status int, text string)

RespondText writes a plain text response.

type WebhookProvider

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

WebhookProvider is an OPTIONAL interface for adapters that use webhooks. Implement this if your platform receives events via HTTP webhooks.

Platforms NOT requiring this: Socket Mode (Slack), long polling (Telegram)

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, opts ...WebhookRunnerOption) *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. Implements event deduplication to prevent duplicate processing.

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.

type WebhookRunnerOption added in v0.21.0

type WebhookRunnerOption func(*WebhookRunner)

WebhookRunnerOption configures the WebhookRunner

func WithDeduplication added in v0.21.0

func WithDeduplication(window, cleanup time.Duration, strategy dedup.KeyStrategy) WebhookRunnerOption

WithDeduplication enables event deduplication with custom settings

Jump to

Keyboard shortcuts

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