Documentation
¶
Overview ¶
Package channel provides a unified abstraction for multi-platform messaging channels. It defines types, interfaces, and a registry for channel adapters such as Telegram and Feishu.
Index ¶
- Constants
- Variables
- func BundleFromAttachment(att Attachment) attachmentpkg.Bundle
- func ChunkMarkdownText(text string, limit int) []string
- func ChunkText(text string, limit int) []string
- func CollapseMessagePartTextLine(text string) string
- func ContainsMarkdown(text string) bool
- func DecodeConfigMap(raw []byte) (map[string]any, error)
- func ErrorReplyText(errorCode, text string) string
- func ErrorText(t *i18n.Localizer, public *apperror.Error) string
- func EscapeMessagePartLinkURL(url string) string
- func GenerateRoutingKey(platform, botID, conversationID, conversationType, senderID string) string
- func IsDataPath(raw string) bool
- func IsDataURL(raw string) bool
- func IsHTTPURL(raw string) bool
- func IsInboundQueueFull(err error) bool
- func IsPrivateConversationType(raw string) bool
- func IsPublicHost(host string) bool
- func NormalizeConversationType(raw string) string
- func NormalizeMessagePartCodeLanguage(language string) string
- func ParseActionValue(value string) (decision, approvalID string, ok bool)
- func ReadString(raw map[string]any, keys ...string) string
- func RejectReservedSkillMetadata(msg Message) error
- func RenderPartsAsMarkdown(parts []MessagePart) string
- func RenderPartsAsPlain(parts []MessagePart) string
- func RenderToolCallMessage(p ToolCallPresentation) string
- func RenderToolCallMessageMarkdown(p ToolCallPresentation) string
- func ReplyText(ctx context.Context, t *i18n.Localizer, err error, fallback string) string
- func SplitMessagePartTextLines(text string) []string
- func StripInlineMarkup(s string) string
- func SummarizeToolInput(_ string, input any) string
- func SummarizeToolResult(_ string, result any) string
- func ToolCallEmoji(toolName string) string
- type Action
- type Adapter
- type Attachment
- type AttachmentPayload
- type AttachmentResolver
- type AttachmentType
- type BaseConnection
- type BindingCriteria
- type BindingMatcher
- type BindingStore
- type ChannelCapabilities
- type ChannelConfig
- type ChannelDirectoryAdapter
- type ChannelIdentityBinding
- type ChannelType
- type Chunker
- type ChunkerMode
- type ConfigLister
- type ConfigNormalizer
- type ConfigResolver
- type ConfigSchema
- type ConfigStore
- type Connection
- type ConnectionController
- type ConnectionStatus
- type ContainerAttachmentIngester
- type Conversation
- type Descriptor
- type DirectoryEntry
- type DirectoryEntryKind
- type DirectoryQuery
- type FieldSchema
- type FieldType
- type ForwardRef
- type Identity
- type InboundHandler
- type InboundMessage
- type InboundProcessor
- type Lifecycle
- func (s *Lifecycle) DeleteBotChannelConfig(ctx context.Context, botID string, channelType ChannelType) error
- func (s *Lifecycle) ResolveBotChannelConfig(ctx context.Context, botID string, channelType ChannelType) (cfg ChannelConfig, found bool, err error)
- func (s *Lifecycle) SetBotChannelStatus(ctx context.Context, botID string, channelType ChannelType, disabled bool) (ChannelConfig, error)
- func (s *Lifecycle) UpsertBotChannelConfig(ctx context.Context, botID string, channelType ChannelType, ...) (ChannelConfig, error)
- type LifecycleStore
- type LocalRuntime
- func (r *LocalRuntime) ConnectionStatusesByBot(botID string) []ConnectionStatus
- func (r *LocalRuntime) DeleteBotChannelConfig(ctx context.Context, botID string, typ ChannelType) error
- func (r *LocalRuntime) React(ctx context.Context, botID string, typ ChannelType, req ReactRequest) error
- func (r *LocalRuntime) Send(ctx context.Context, botID string, typ ChannelType, req SendRequest) error
- func (r *LocalRuntime) SetBotChannelStatus(ctx context.Context, botID string, typ ChannelType, disabled bool) (ChannelConfig, error)
- func (r *LocalRuntime) SetWebhookEndpoint(ctx context.Context, botID string, typ ChannelType, ...) (SetWebhookEndpointResponse, error)
- func (r *LocalRuntime) UpsertBotChannelConfig(ctx context.Context, botID string, typ ChannelType, req UpsertConfigRequest) (ChannelConfig, error)
- type Manager
- func (m *Manager) AddAdapter(ctx context.Context, adapter Adapter)
- func (m *Manager) ConnectionStatusesByBot(botID string) []ConnectionStatus
- func (m *Manager) EnsureConnection(ctx context.Context, cfg ChannelConfig) error
- func (m *Manager) HandleInbound(ctx context.Context, cfg ChannelConfig, msg InboundMessage) error
- func (m *Manager) React(ctx context.Context, botID string, channelType ChannelType, req ReactRequest) error
- func (m *Manager) Refresh(ctx context.Context)
- func (m *Manager) RegisterAdapter(adapter Adapter)
- func (m *Manager) Registry() *Registry
- func (m *Manager) RemoveAdapter(ctx context.Context, channelType ChannelType)
- func (m *Manager) RemoveConnection(ctx context.Context, botID string, channelType ChannelType)
- func (m *Manager) Send(ctx context.Context, botID string, channelType ChannelType, req SendRequest) error
- func (m *Manager) SetAttachmentStore(store OutboundAttachmentStore)
- func (m *Manager) Shutdown(ctx context.Context) error
- func (m *Manager) Start(ctx context.Context)
- func (m *Manager) Stop(ctx context.Context, configID string) error
- func (m *Manager) StopByBot(ctx context.Context, botID string) error
- func (m *Manager) Use(mw ...Middleware)
- type ManagerOption
- type ManagerStore
- type Message
- type MessageEditor
- type MessageFormat
- type MessagePart
- type MessagePartType
- type MessageTextStyle
- type Middleware
- type OutboundAttachmentStore
- type OutboundCapabilityResolver
- type OutboundMessage
- type OutboundOrder
- type OutboundPolicy
- type OutboundStream
- type OutboundTargetResolver
- type PreparedAttachment
- type PreparedAttachmentKind
- type PreparedMessage
- type PreparedOutboundMessage
- type PreparedOutboundStream
- type PreparedOutboundValidator
- type PreparedStreamEvent
- type PreparedStreamFinalizePayload
- type ProcessingStatus
- type ProcessingStatusErrorFunc
- type ProcessingStatusHandle
- type ProcessingStatusInfo
- type ProcessingStatusNotifier
- type ProcessingStatusRefresher
- type ReactRequest
- type Reactor
- type Receiver
- type Registry
- func (r *Registry) BuildUserBindingConfig(channelType ChannelType, identity Identity) map[string]any
- func (r *Registry) DirectoryAdapter(channelType ChannelType) (ChannelDirectoryAdapter, bool)
- func (r *Registry) DiscoverSelf(ctx context.Context, channelType ChannelType, credentials map[string]any) (map[string]any, string, error)
- func (r *Registry) Get(channelType ChannelType) (Adapter, bool)
- func (r *Registry) GetAttachmentResolver(channelType ChannelType) (AttachmentResolver, bool)
- func (r *Registry) GetCapabilities(channelType ChannelType) (ChannelCapabilities, bool)
- func (r *Registry) GetConfigSchema(channelType ChannelType) (ConfigSchema, bool)
- func (r *Registry) GetDescriptor(channelType ChannelType) (Descriptor, bool)
- func (r *Registry) GetMessageEditor(channelType ChannelType) (MessageEditor, bool)
- func (r *Registry) GetOutboundCapabilities(channelType ChannelType, cfg ChannelConfig, target string) (ChannelCapabilities, bool)
- func (r *Registry) GetOutboundPolicy(channelType ChannelType) (OutboundPolicy, bool)
- func (r *Registry) GetProcessingStatusNotifier(channelType ChannelType) (ProcessingStatusNotifier, bool)
- func (r *Registry) GetReactor(channelType ChannelType) (Reactor, bool)
- func (r *Registry) GetReceiver(channelType ChannelType) (Receiver, bool)
- func (r *Registry) GetSender(channelType ChannelType) (Sender, bool)
- func (r *Registry) GetStreamSender(channelType ChannelType) (StreamSender, bool)
- func (r *Registry) GetUserConfigSchema(channelType ChannelType) (ConfigSchema, bool)
- func (r *Registry) GetWebhookEndpointSetter(channelType ChannelType) (WebhookEndpointSetter, bool)
- func (r *Registry) GetWebhookReceiver(channelType ChannelType) (WebhookReceiver, bool)
- func (r *Registry) IsConfigless(channelType ChannelType) bool
- func (r *Registry) IsOwnerOnly(channelType ChannelType) bool
- func (r *Registry) List() []Adapter
- func (r *Registry) ListDescriptors() []Descriptor
- func (r *Registry) MatchUserBinding(channelType ChannelType, config map[string]any, criteria BindingCriteria) bool
- func (r *Registry) MustRegister(adapter Adapter)
- func (r *Registry) NormalizeConfig(channelType ChannelType, raw map[string]any) (map[string]any, error)
- func (r *Registry) NormalizeTarget(channelType ChannelType, raw string) (string, bool)
- func (r *Registry) NormalizeUserConfig(channelType ChannelType, raw map[string]any) (map[string]any, error)
- func (r *Registry) ParseChannelType(raw string) (ChannelType, error)
- func (r *Registry) Register(adapter Adapter) error
- func (r *Registry) ResolveOutboundTarget(ctx context.Context, channelType ChannelType, cfg ChannelConfig, target string) (string, bool, error)
- func (r *Registry) ResolveTargetFromUserConfig(channelType ChannelType, config map[string]any) (string, error)
- func (r *Registry) SelfIdentityPolicy(channelType ChannelType) SelfIdentityPolicy
- func (r *Registry) Types() []ChannelType
- func (r *Registry) Unregister(channelType ChannelType) bool
- type ReplyRef
- type Runtime
- type SelfDiscoverer
- type SelfIdentityPolicy
- type SelfIdentityPolicyProvider
- type SendRequest
- type Sender
- type SetWebhookEndpointRequest
- type SetWebhookEndpointResponse
- type SpeechRequest
- type Store
- func (s *Store) DeleteConfig(ctx context.Context, botID string, channelType ChannelType) error
- func (s *Store) GetChannelIdentityConfig(ctx context.Context, channelIdentityID string, channelType ChannelType) (ChannelIdentityBinding, error)
- func (s *Store) ListBotConfigs(ctx context.Context, botID string) ([]ChannelConfig, error)
- func (s *Store) ListChannelIdentityConfigsByType(ctx context.Context, channelType ChannelType) ([]ChannelIdentityBinding, error)
- func (s *Store) ListConfigs(ctx context.Context, botID string) ([]ChannelConfig, error)
- func (s *Store) ListConfigsByType(ctx context.Context, channelType ChannelType) ([]ChannelConfig, error)
- func (s *Store) ResolveChannelIdentityBinding(ctx context.Context, channelType ChannelType, criteria BindingCriteria) (string, error)
- func (s *Store) ResolveEffectiveConfig(ctx context.Context, botID string, channelType ChannelType) (ChannelConfig, error)
- func (s *Store) SaveMatrixSyncSinceToken(ctx context.Context, configID string, since string) error
- func (s *Store) SetWebhookEndpoint(ctx context.Context, botID string, channelType ChannelType, ...) (SetWebhookEndpointResponse, error)
- func (s *Store) UpdateConfigDisabled(ctx context.Context, botID string, channelType ChannelType, disabled bool) (ChannelConfig, error)
- func (s *Store) UpsertChannelIdentityConfig(ctx context.Context, channelIdentityID string, channelType ChannelType, ...) (ChannelIdentityBinding, error)
- func (s *Store) UpsertConfig(ctx context.Context, botID string, channelType ChannelType, ...) (ChannelConfig, error)
- type StreamEvent
- type StreamEventType
- type StreamFinalizePayload
- type StreamObserver
- type StreamOptions
- type StreamPhase
- type StreamReplySender
- type StreamSender
- type StreamStatus
- type StreamToolCall
- type TargetHint
- type TargetResolver
- type TargetSpec
- type ThreadRef
- type ToolCallBlock
- type ToolCallBlockType
- type ToolCallPresentation
- type ToolCallStatus
- type UpdateChannelStatusRequest
- type UpsertChannelIdentityConfigRequest
- type UpsertConfigRequest
- type WebhookEndpointSetter
- type WebhookHandler
- type WebhookReceiver
Constants ¶
const ( ProcessingStageStarted = "processing_started" ProcessingStageRefresh = "processing_refresh" ProcessingStageCompleted = "processing_completed" ProcessingStageFailed = "processing_failed" )
Processing status stages reported to ProcessingStatusErrorFunc.
const ( ActionTypeToolApproval = "tool_approval" ActionApprove = "approve" ActionReject = "reject" )
const ( ConversationTypePrivate = "private" ConversationTypeGroup = "group" ConversationTypeThread = "thread" )
const ExternalToolCallEmoji = "⚙️"
ExternalToolCallEmoji is the emoji used for any tool not in the built-in whitelist (including MCP and federation tools).
Variables ¶
var ( // ErrSendTargetRequired means a send named neither a target nor a channel identity. ErrSendTargetRequired = errors.New("target or channel_identity_id is required") // ErrChannelBindingRequired means the recipient identity has not linked this channel. ErrChannelBindingRequired = errors.New("channel binding required") )
var ( ErrWebhookEndpointUnsupported = errors.New("channel webhook endpoint update is not supported") ErrInvalidWebhookEndpoint = errors.New("invalid webhook endpoint") )
var ErrChannelConfigNotFound = errors.New("channel config not found")
ErrChannelConfigNotFound indicates the bot has no persisted config for the channel type.
var ErrChannelDiscoveryFailed = errors.New("channel identity discovery failed")
ErrChannelDiscoveryFailed indicates that a platform-side self identity check failed.
var ErrChannelIdentityConfigNotFound = errors.New("channel user config not found")
ErrChannelIdentityConfigNotFound indicates the channel identity has no binding for the channel type.
var ErrEnableChannelFailed = errors.New("enable channel failed")
ErrEnableChannelFailed indicates that enabling the channel (e.g. EnsureConnection) failed.
var ErrInboundQueueFull = errors.New("inbound queue full")
ErrInboundQueueFull indicates the synchronous inbound queue admission failed because all worker slots are saturated.
var ErrStopNotSupported = errors.New("channel connection stop not supported")
ErrStopNotSupported is returned when a connection does not support graceful shutdown.
Functions ¶
func BundleFromAttachment ¶
func BundleFromAttachment(att Attachment) attachmentpkg.Bundle
BundleFromAttachment converts a channel attachment to the shared internal bundle shape.
func ChunkMarkdownText ¶
ChunkMarkdownText splits text at paragraph boundaries (double newlines), respecting the rune limit.
func CollapseMessagePartTextLine ¶
CollapseMessagePartTextLine normalizes block part text into one visible line.
func ContainsMarkdown ¶
ContainsMarkdown returns true if the text contains common Markdown constructs.
func DecodeConfigMap ¶
DecodeConfigMap unmarshals a JSON byte slice into a string-keyed map.
func ErrorReplyText ¶ added in v0.21.0
ErrorReplyText is the text an adapter shows for a stream error. Copy rendered from an error code is a complete sentence and is shown as it is; a bare error text is labelled as an error.
func ErrorText ¶ added in v0.22.0
ErrorText is the channel copy for a public error: errors.<code> from the channel locale with the error's args substituted, then the catalog detail. public is an answer of errs.Answer, so its code is in the catalog.
func EscapeMessagePartLinkURL ¶
EscapeMessagePartLinkURL percent-encodes characters that can break platform rich-link wrappers while preserving ordinary http(s), mailto, tel and platform-specific URL prefixes.
func GenerateRoutingKey ¶
GenerateRoutingKey builds a route key from platform, bot, conversation, and sender info. For group chats, the sender ID is appended to provide per-user context.
func IsDataPath ¶
IsDataPath reports whether raw is a container-internal data path (/data/...).
func IsInboundQueueFull ¶
IsInboundQueueFull reports whether err means the inbound queue rejected a message due to local capacity.
func IsPrivateConversationType ¶
IsPrivateConversationType reports whether the conversation is private.
func IsPublicHost ¶
IsPublicHost matches the browser-side validation in apps/web/src/utils/webhook-public-base.ts.
func NormalizeConversationType ¶
NormalizeConversationType normalizes conversation type values within the channel abstraction domain: private/group/thread.
func NormalizeMessagePartCodeLanguage ¶
NormalizeMessagePartCodeLanguage returns a safe code-fence language hint.
func ParseActionValue ¶
func ReadString ¶
ReadString looks up the first matching key in a map and returns its string representation. It tries each key in order and converts non-string values using type-safe formatting.
func RejectReservedSkillMetadata ¶
RejectReservedSkillMetadata rejects client-supplied reserved skill metadata anywhere it can ride on a message: top-level metadata, content parts, attachments, and reply attachments. This is a security boundary — reserved keys (requested_skills, skill_activation, user_message_kind, …) are trusted downstream as server-authored state. Single walker shared by every public inbound surface (web REST, web WS, channel inbound) so a future metadata-bearing location on Message only needs guarding once.
func RenderPartsAsMarkdown ¶
func RenderPartsAsMarkdown(parts []MessagePart) string
RenderPartsAsMarkdown produces a GFM-flavored Markdown string from canonical MessageParts. It is the degradation path used by coerceFormatForCaps when a target channel supports Markdown but lacks RichText capability (e.g. DingTalk, Matrix), and is the reference output the per-platform renderers (Telegram HTML / Discord MD / Feishu lark_md / Slack mrkdwn) are tested against in the canonical-parts matrix.
Attacker-controllable text and URL fields are neutralised so they cannot forge masked links, escape style wrappers, or open autolinks. The escape set mirrors what the Discord renderer applies; channels with stricter syntax (Slack mrkdwn) bypass this function via the RichText gate and run their own renderer instead.
func RenderPartsAsPlain ¶
func RenderPartsAsPlain(parts []MessagePart) string
RenderPartsAsPlain joins canonical MessageParts into a plain-text block with style markers, masked-link syntax, and code fences stripped. Used by coerceFormatForCaps as the final degradation when the target channel supports neither RichText nor Markdown.
func RenderToolCallMessage ¶
func RenderToolCallMessage(p ToolCallPresentation) string
RenderToolCallMessage renders a plain-text single-message view of a tool call state. Links are rendered as two lines: the title on one line and the URL on the next. Adapters that want Markdown link syntax should use RenderToolCallMessageMarkdown instead.
func RenderToolCallMessageMarkdown ¶
func RenderToolCallMessageMarkdown(p ToolCallPresentation) string
RenderToolCallMessageMarkdown renders a Markdown version of the tool call presentation. Links become [title](url), code blocks are fenced with triple backticks, and plain-text blocks are unchanged.
func ReplyText ¶ added in v0.22.0
ReplyText is the reply a flow sends for err. A specific public error is shown with its copy. An error errs.Answer answers with a generic code, internal or http.bad_request, is shown with fallback, the flow's own failure copy, or with the generic copy when fallback is empty. It is empty when the caller has canceled, and the flow then sends no reply.
func SplitMessagePartTextLines ¶
SplitMessagePartTextLines normalizes block part text into trimmed display lines.
func StripInlineMarkup ¶
StripInlineMarkup removes the inline Markdown markers (** and `) authored for capable channels, leaving clean text for plain-text-only channels.
Scope: only ** (bold) and ` (code) are stripped, because those are the only inline markers the command renderers emit (MdBold/MdCode/CmdRef). Other constructs ContainsMarkdown recognizes — links [a](b), headings, list bullets — are intentionally NOT stripped: the renderers never produce them, so any such characters in a body are literal user/content text and must be preserved verbatim rather than mangled. Extend this (and coerceFormatForCaps) if a renderer ever starts emitting those constructs.
func SummarizeToolInput ¶
SummarizeToolInput returns a short human-readable representation of a tool call's input payload, prioritizing known key fields (path, command, query, url, target, to, id, cron, action) before falling back to a compact JSON projection.
func SummarizeToolResult ¶
SummarizeToolResult returns a short representation of a tool call's result, surfacing status/error/count signals when present and otherwise falling back to trimmed text or a compact JSON projection.
func ToolCallEmoji ¶
ToolCallEmoji returns the emoji mapped for a tool name. Unknown / external tools fall back to ExternalToolCallEmoji.
Types ¶
type Action ¶
type Action struct {
Type string `json:"type"`
Label string `json:"label,omitempty"`
Value string `json:"value,omitempty"`
URL string `json:"url,omitempty"`
// Row groups buttons into keyboard rows for renderers that support grids
// (e.g. Telegram inline keyboards). Buttons sharing a Row render together;
// rows appear in ascending numeric order. Renderers without grid support
// ignore this field. 0 is the default (single row, prior behavior).
Row int `json:"row,omitempty"`
}
Action describes an interactive button or link in a message.
type Adapter ¶
type Adapter interface {
Type() ChannelType
Descriptor() Descriptor
}
Adapter is the base interface every channel adapter must implement.
type Attachment ¶
type Attachment struct {
Type AttachmentType `json:"type"`
URL string `json:"url,omitempty"` // HTTP(S) or data URL
Path string `json:"path,omitempty"` // workspace-local filesystem path
PlatformKey string `json:"platform_key,omitempty"`
SourcePlatform string `json:"source_platform,omitempty"`
ContentHash string `json:"content_hash,omitempty"`
Base64 string `json:"base64,omitempty"` // data URL for agent delivery
Name string `json:"name,omitempty"`
Size int64 `json:"size,omitempty"`
Mime string `json:"mime,omitempty"`
DurationMs int64 `json:"duration_ms,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
ThumbnailURL string `json:"thumbnail_url,omitempty"`
Caption string `json:"caption,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
}
Attachment represents a binary file attached to a message.
func AttachmentFromBundle ¶
func AttachmentFromBundle(bundle attachmentpkg.Bundle) Attachment
AttachmentFromBundle converts the shared internal bundle shape to a channel attachment. URL and Path are kept in their respective fields. Callers must guarantee bundle is already normalized (produced by BundleFromXxx or Normalize()).
func NormalizeInboundChannelAttachment ¶
func NormalizeInboundChannelAttachment(att Attachment) Attachment
NormalizeInboundChannelAttachment normalizes a channel attachment at adapter boundary.
func (Attachment) HasReference ¶
func (a Attachment) HasReference() bool
HasReference reports whether URL, Path, or platform key is available.
func (Attachment) Reference ¶
func (a Attachment) Reference() string
Reference returns the strongest available attachment reference. URL is preferred for cross-platform portability, then local Path, then platform key.
type AttachmentPayload ¶
type AttachmentPayload struct {
Reader io.ReadCloser
Mime string
Name string
Size int64
}
AttachmentPayload contains resolved attachment bytes and optional metadata. Caller must close Reader.
type AttachmentResolver ¶
type AttachmentResolver interface {
ResolveAttachment(ctx context.Context, cfg ChannelConfig, attachment Attachment) (AttachmentPayload, error)
}
AttachmentResolver resolves attachment references (for example platform_key) into readable bytes for persistence or transformation pipelines.
type AttachmentType ¶
type AttachmentType string
AttachmentType classifies the kind of binary attachment.
const ( AttachmentImage AttachmentType = "image" AttachmentAudio AttachmentType = "audio" AttachmentVideo AttachmentType = "video" AttachmentVoice AttachmentType = "voice" AttachmentFile AttachmentType = "file" AttachmentGIF AttachmentType = "gif" )
func InferAttachmentType ¶
func InferAttachmentType(currentType AttachmentType, mime, name string) AttachmentType
InferAttachmentType infers a canonical attachment type from type/mime/name.
type BaseConnection ¶
type BaseConnection struct {
// contains filtered or unexported fields
}
BaseConnection is a default Connection implementation backed by a stop function.
func NewConnection ¶
func NewConnection(cfg ChannelConfig, stop func(ctx context.Context) error) *BaseConnection
NewConnection creates a BaseConnection for the given config and stop function.
func (*BaseConnection) BotID ¶
func (c *BaseConnection) BotID() string
BotID returns the bot identifier that owns this connection.
func (*BaseConnection) ChannelType ¶
func (c *BaseConnection) ChannelType() ChannelType
ChannelType returns the type of channel this connection serves.
func (*BaseConnection) ConfigID ¶
func (c *BaseConnection) ConfigID() string
ConfigID returns the channel configuration identifier.
func (*BaseConnection) MarkStopped ¶
func (c *BaseConnection) MarkStopped()
MarkStopped flags the connection as no longer running without invoking its stop function. Adapters call this from internal goroutines that have given up (terminal protocol error etc.) so the manager's Running() check reflects reality and reconciliation can act on it.
func (*BaseConnection) Running ¶
func (c *BaseConnection) Running() bool
Running reports whether the connection is still active.
type BindingCriteria ¶
BindingCriteria specifies conditions for matching a user-channel binding.
func BindingCriteriaFromIdentity ¶
func BindingCriteriaFromIdentity(identity Identity) BindingCriteria
BindingCriteriaFromIdentity creates BindingCriteria from a channel Identity.
func (BindingCriteria) Attribute ¶
func (c BindingCriteria) Attribute(key string) string
Attribute returns the trimmed value for the given key, or empty string if absent.
type BindingMatcher ¶
type BindingMatcher interface {
MatchBinding(config map[string]any, criteria BindingCriteria) bool
BuildUserConfig(identity Identity) map[string]any
}
BindingMatcher matches user-channel bindings and constructs binding configs from identities.
type BindingStore ¶
type BindingStore interface {
ResolveChannelIdentityBinding(ctx context.Context, channelType ChannelType, criteria BindingCriteria) (string, error)
}
BindingStore resolves channel-identity bindings. Used by identity resolution.
type ChannelCapabilities ¶
type ChannelCapabilities struct {
Text bool `json:"text"`
Markdown bool `json:"markdown"`
RichText bool `json:"rich_text"`
Attachments bool `json:"attachments"`
Media bool `json:"media"`
Reactions bool `json:"reactions"`
Buttons bool `json:"buttons"`
URLButtons bool `json:"url_buttons"`
Reply bool `json:"reply"`
Threads bool `json:"threads"`
Streaming bool `json:"streaming"`
Polls bool `json:"polls"`
Edit bool `json:"edit"`
Unsend bool `json:"unsend"`
NativeCommands bool `json:"native_commands"`
NativeUserInput bool `json:"native_user_input"`
BlockStreaming bool `json:"block_streaming"`
ChatTypes []string `json:"chat_types,omitempty"`
}
ChannelCapabilities describes the feature matrix of a channel type. It is used by the outbound layer to validate message content before delivery.
type ChannelConfig ¶
type ChannelConfig struct {
ID string `json:"id"`
TeamID string `json:"team_id"`
BotID string `json:"bot_id"`
ChannelType ChannelType `json:"channel_type"`
Credentials map[string]any `json:"credentials"`
ExternalIdentity string `json:"external_identity"`
SelfIdentity map[string]any `json:"self_identity"`
Routing map[string]any `json:"routing"`
Disabled bool `json:"disabled"`
VerifiedAt time.Time `json:"verified_at"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
ChannelConfig holds the configuration for a bot's channel integration. Disabled: true means the channel is stopped (not connected); false means enabled.
type ChannelDirectoryAdapter ¶
type ChannelDirectoryAdapter interface {
ListPeers(ctx context.Context, cfg ChannelConfig, query DirectoryQuery) ([]DirectoryEntry, error)
ListGroups(ctx context.Context, cfg ChannelConfig, query DirectoryQuery) ([]DirectoryEntry, error)
ListGroupMembers(ctx context.Context, cfg ChannelConfig, groupID string, query DirectoryQuery) ([]DirectoryEntry, error)
ResolveEntry(ctx context.Context, cfg ChannelConfig, input string, kind DirectoryEntryKind) (DirectoryEntry, error)
}
ChannelDirectoryAdapter provides contact and group lookup for a channel platform.
type ChannelIdentityBinding ¶
type ChannelIdentityBinding struct {
ID string `json:"id"`
ChannelType ChannelType `json:"channel_type"`
ChannelIdentityID string `json:"channel_identity_id"`
Config map[string]any `json:"config"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
ChannelIdentityBinding represents a channel identity's binding to a specific channel type.
type ChannelType ¶
type ChannelType string
ChannelType identifies a messaging platform (e.g., "telegram", "feishu").
const ( ChannelTypeTelegram ChannelType = "telegram" ChannelTypeFeishu ChannelType = "feishu" ChannelTypeDingtalk ChannelType = "dingtalk" ChannelTypeMatrix ChannelType = "matrix" ChannelTypeDiscord ChannelType = "discord" ChannelTypeQQ ChannelType = "qq" ChannelTypeWecom ChannelType = "wecom" ChannelTypeWeixin ChannelType = "weixin" ChannelTypeWeChatOA ChannelType = "wechatoa" ChannelTypeLocal ChannelType = "local" ChannelTypeSlack ChannelType = "slack" ChannelTypeLine ChannelType = "line" )
Well-known ChannelType values for platforms with special handling in the core channel package. Adapter packages define their own identical constant as their package-local Type.
func (ChannelType) String ¶
func (c ChannelType) String() string
String returns the channel type as a plain string.
type Chunker ¶
Chunker splits text into pieces that respect a character limit.
func DefaultChunker ¶
func DefaultChunker(mode ChunkerMode) Chunker
DefaultChunker returns the built-in Chunker for the given mode.
type ChunkerMode ¶
type ChunkerMode string
ChunkerMode selects the text chunking strategy.
const ( ChunkerModeText ChunkerMode = "text" ChunkerModeMarkdown ChunkerMode = "markdown" )
type ConfigLister ¶
type ConfigLister interface {
ListConfigsByType(ctx context.Context, channelType ChannelType) ([]ChannelConfig, error)
}
ConfigLister lists channel configs for periodic refresh. Used by connection lifecycle.
type ConfigNormalizer ¶
type ConfigNormalizer interface {
NormalizeConfig(raw map[string]any) (map[string]any, error)
NormalizeUserConfig(raw map[string]any) (map[string]any, error)
}
ConfigNormalizer validates and normalizes channel and user-binding configurations.
type ConfigResolver ¶
type ConfigResolver interface {
ResolveEffectiveConfig(ctx context.Context, botID string, channelType ChannelType) (ChannelConfig, error)
GetChannelIdentityConfig(ctx context.Context, channelIdentityID string, channelType ChannelType) (ChannelIdentityBinding, error)
}
ConfigResolver resolves effective configs and user bindings. Used for outbound sending.
type ConfigSchema ¶
type ConfigSchema struct {
Version int `json:"version"`
Fields map[string]FieldSchema `json:"fields"`
}
ConfigSchema describes the structure of a channel or user-binding configuration.
type ConfigStore ¶
type ConfigStore interface {
ConfigLister
ConfigResolver
BindingStore
UpsertChannelIdentityConfig(ctx context.Context, channelIdentityID string, channelType ChannelType, req UpsertChannelIdentityConfigRequest) (ChannelIdentityBinding, error)
}
ConfigStore is the full persistence interface. Components should depend on smaller interfaces above; ConfigStore exists as a convenience for wiring.
type Connection ¶
type Connection interface {
ConfigID() string
BotID() string
ChannelType() ChannelType
Stop(ctx context.Context) error
Running() bool
}
Connection represents an active, long-lived link to a channel platform.
type ConnectionController ¶
type ConnectionController interface {
EnsureConnection(ctx context.Context, cfg ChannelConfig) error
RemoveConnection(ctx context.Context, botID string, channelType ChannelType)
}
ConnectionController controls runtime channel connections.
type ConnectionStatus ¶
type ConnectionStatus struct {
ConfigID string `json:"config_id"`
BotID string `json:"bot_id"`
ChannelType ChannelType `json:"channel_type"`
Running bool `json:"running"`
LastError string `json:"last_error,omitempty"`
UpdatedAt time.Time `json:"updated_at"`
}
ConnectionStatus describes runtime status for one configured channel connection.
type ContainerAttachmentIngester ¶
type ContainerAttachmentIngester interface {
IngestContainerFile(ctx context.Context, botID, containerPath string) (media.Asset, error)
}
ContainerAttachmentIngester is an optional extension of OutboundAttachmentStore for stores that can read files directly from a bot's container filesystem. Implementations must be safe for concurrent use.
type Conversation ¶
type Conversation struct {
ID string
Type string
Name string
ThreadID string
Metadata map[string]any
}
Conversation holds metadata about the chat or group context.
type Descriptor ¶
type Descriptor struct {
Type ChannelType
DisplayName string
Configless bool
AckDisabledWebhook bool
// OwnerOnly marks channels that no third party can ever reach (e.g.
// personal-assistant channels living inside the activator's own
// account). Every sender on these channels is treated as the operator:
// an unlinked sender resolves to the bot owner's account (so gates keyed
// on the account principal, such as workspace exec and external runtimes,
// see the owner), and the gates keyed on the channel identity instead —
// chat ACL and write-gated slash commands — skip their /link requirement.
OwnerOnly bool
Capabilities ChannelCapabilities
OutboundPolicy OutboundPolicy
ConfigSchema ConfigSchema
UserConfigSchema ConfigSchema
TargetSpec TargetSpec
}
Descriptor holds read-only metadata and static policy flags for a registered channel type. Request handling and platform operations are expressed through optional interfaces.
type DirectoryEntry ¶
type DirectoryEntry struct {
Kind DirectoryEntryKind `json:"kind"`
ID string `json:"id"`
Name string `json:"name,omitempty"`
Handle string `json:"handle,omitempty"`
AvatarURL string `json:"avatar_url,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
}
DirectoryEntry represents a single user or group discovered through the channel's directory.
type DirectoryEntryKind ¶
type DirectoryEntryKind string
DirectoryEntryKind classifies a directory entry as a user or a group.
const ( DirectoryEntryUser DirectoryEntryKind = "user" DirectoryEntryGroup DirectoryEntryKind = "group" )
type DirectoryQuery ¶
type DirectoryQuery struct {
Query string `json:"query,omitempty"`
Limit int `json:"limit,omitempty"`
Kind DirectoryEntryKind `json:"kind,omitempty"`
}
DirectoryQuery contains filters for directory listing operations.
type FieldSchema ¶
type FieldSchema struct {
Type FieldType `json:"type"`
Required bool `json:"required"`
Order int `json:"order,omitempty"`
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
Enum []string `json:"enum,omitempty"`
Example any `json:"example,omitempty"`
}
FieldSchema describes a single configuration field.
type FieldType ¶
type FieldType string
FieldType enumerates the supported configuration field types.
type ForwardRef ¶
type ForwardRef struct {
MessageID string `json:"message_id,omitempty"`
FromUserID string `json:"from_user_id,omitempty"`
FromConversationID string `json:"from_conversation_id,omitempty"`
Sender string `json:"sender,omitempty"`
Date int64 `json:"date,omitempty"`
AttachmentsKnown bool `json:"attachments_known,omitempty"`
}
ForwardRef describes the structured origin of a forwarded message.
type InboundHandler ¶
type InboundHandler func(ctx context.Context, cfg ChannelConfig, msg InboundMessage) error
InboundHandler is a callback invoked when a message arrives from a channel.
type InboundMessage ¶
type InboundMessage struct {
Channel ChannelType
Message Message
BotID string
ReplyTarget string
RouteKey string
Sender Identity
Conversation Conversation
ReceivedAt time.Time
Source string
Metadata map[string]any
}
InboundMessage is a message received from an external channel.
func (InboundMessage) RoutingKey ¶
func (m InboundMessage) RoutingKey() string
RoutingKey returns a stable identifier used for reply routing. Format: platform:bot_id:conversation_id[:sender_id].
type InboundProcessor ¶
type InboundProcessor interface {
HandleInbound(ctx context.Context, cfg ChannelConfig, msg InboundMessage, sender StreamReplySender) error
}
InboundProcessor handles inbound messages and replies through the given sender.
type Lifecycle ¶
type Lifecycle struct {
// contains filtered or unexported fields
}
Lifecycle coordinates persisted config updates and runtime connection state.
func NewLifecycle ¶
func NewLifecycle(store LifecycleStore, controller ConnectionController) *Lifecycle
NewLifecycle creates a lifecycle coordinator from storage and connection controller.
func (*Lifecycle) DeleteBotChannelConfig ¶
func (s *Lifecycle) DeleteBotChannelConfig(ctx context.Context, botID string, channelType ChannelType) error
DeleteBotChannelConfig removes persisted config and stops active runtime connection.
func (*Lifecycle) ResolveBotChannelConfig ¶ added in v0.21.0
func (s *Lifecycle) ResolveBotChannelConfig(ctx context.Context, botID string, channelType ChannelType) (cfg ChannelConfig, found bool, err error)
ResolveBotChannelConfig reads the bot's stored config for channelType without touching its connection. found is false when the bot has none.
func (*Lifecycle) SetBotChannelStatus ¶
func (s *Lifecycle) SetBotChannelStatus(ctx context.Context, botID string, channelType ChannelType, disabled bool) (ChannelConfig, error)
SetBotChannelStatus updates only the disabled status and applies runtime lifecycle.
func (*Lifecycle) UpsertBotChannelConfig ¶
func (s *Lifecycle) UpsertBotChannelConfig(ctx context.Context, botID string, channelType ChannelType, req UpsertConfigRequest) (ChannelConfig, error)
UpsertBotChannelConfig updates config and applies connection lifecycle. For disabled=true, it stores config and stops any active connection. For disabled=false, it stores config then starts connection; on start failure it rolls back.
type LifecycleStore ¶
type LifecycleStore interface {
ResolveEffectiveConfig(ctx context.Context, botID string, channelType ChannelType) (ChannelConfig, error)
UpsertConfig(ctx context.Context, botID string, channelType ChannelType, req UpsertConfigRequest) (ChannelConfig, error)
UpdateConfigDisabled(ctx context.Context, botID string, channelType ChannelType, disabled bool) (ChannelConfig, error)
DeleteConfig(ctx context.Context, botID string, channelType ChannelType) error
}
LifecycleStore persists channel configs for lifecycle orchestration.
type LocalRuntime ¶
func (*LocalRuntime) ConnectionStatusesByBot ¶
func (r *LocalRuntime) ConnectionStatusesByBot(botID string) []ConnectionStatus
func (*LocalRuntime) DeleteBotChannelConfig ¶
func (r *LocalRuntime) DeleteBotChannelConfig(ctx context.Context, botID string, typ ChannelType) error
func (*LocalRuntime) React ¶
func (r *LocalRuntime) React(ctx context.Context, botID string, typ ChannelType, req ReactRequest) error
func (*LocalRuntime) Send ¶
func (r *LocalRuntime) Send(ctx context.Context, botID string, typ ChannelType, req SendRequest) error
func (*LocalRuntime) SetBotChannelStatus ¶
func (r *LocalRuntime) SetBotChannelStatus(ctx context.Context, botID string, typ ChannelType, disabled bool) (ChannelConfig, error)
func (*LocalRuntime) SetWebhookEndpoint ¶
func (r *LocalRuntime) SetWebhookEndpoint(ctx context.Context, botID string, typ ChannelType, req SetWebhookEndpointRequest) (SetWebhookEndpointResponse, error)
func (*LocalRuntime) UpsertBotChannelConfig ¶
func (r *LocalRuntime) UpsertBotChannelConfig(ctx context.Context, botID string, typ ChannelType, req UpsertConfigRequest) (ChannelConfig, error)
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager coordinates channel adapters, connection lifecycle, and message dispatch. Connection lifecycle lives in connection.go, inbound dispatch in inbound.go, and outbound pipeline in outbound.go.
func NewManager ¶
func NewManager(log *slog.Logger, registry *Registry, service ManagerStore, processor InboundProcessor, opts ...ManagerOption) *Manager
NewManager creates a Manager with the given logger, registry, config store, and inbound processor.
func (*Manager) AddAdapter ¶
AddAdapter registers an adapter and triggers an immediate refresh for hot-plug support.
func (*Manager) ConnectionStatusesByBot ¶
func (m *Manager) ConnectionStatusesByBot(botID string) []ConnectionStatus
ConnectionStatusesByBot returns observed channel connection statuses for a bot.
func (*Manager) EnsureConnection ¶
func (m *Manager) EnsureConnection(ctx context.Context, cfg ChannelConfig) error
EnsureConnection starts, restarts, or stops the connection for the given config. Disabled configs are stopped and removed; enabled configs are started or restarted.
func (*Manager) HandleInbound ¶
func (m *Manager) HandleInbound(ctx context.Context, cfg ChannelConfig, msg InboundMessage) error
HandleInbound enqueues an inbound message for asynchronous processing by the worker pool.
ctx is read for the identity of the request doing the enqueuing and is deliberately not kept: the work outlives it.
func (*Manager) React ¶
func (m *Manager) React(ctx context.Context, botID string, channelType ChannelType, req ReactRequest) error
React adds or removes an emoji reaction on a channel message.
func (*Manager) Refresh ¶
Refresh performs a full reconcile of all adapter connections against the DB. Prefer EnsureConnection / RemoveConnection for targeted changes after API operations. Refresh is mainly used at startup and as a periodic safety net.
func (*Manager) RegisterAdapter ¶
RegisterAdapter adds an adapter to the registry and logs the registration.
func (*Manager) RemoveAdapter ¶
func (m *Manager) RemoveAdapter(ctx context.Context, channelType ChannelType)
RemoveAdapter unregisters an adapter and stops all its active connections.
func (*Manager) RemoveConnection ¶
func (m *Manager) RemoveConnection(ctx context.Context, botID string, channelType ChannelType)
RemoveConnection stops and removes connections matching the given bot and channel type.
func (*Manager) Send ¶
func (m *Manager) Send(ctx context.Context, botID string, channelType ChannelType, req SendRequest) error
Send delivers an outbound message to the specified channel, resolving target and config automatically.
func (*Manager) SetAttachmentStore ¶
func (m *Manager) SetAttachmentStore(store OutboundAttachmentStore)
SetAttachmentStore wires the shared outbound attachment store used by the prepared outbound layer.
func (*Manager) Shutdown ¶
Shutdown cancels the inbound worker pool and stops all active connections.
func (*Manager) Use ¶
func (m *Manager) Use(mw ...Middleware)
Use appends middleware to the inbound processing chain.
type ManagerOption ¶
type ManagerOption func(*Manager)
ManagerOption configures a Manager during construction.
func WithInboundQueueSize ¶
func WithInboundQueueSize(size int) ManagerOption
WithInboundQueueSize sets the capacity of the inbound message queue. The default is 256. Larger values trade memory for lower drop rate under burst load.
func WithInboundWorkers ¶
func WithInboundWorkers(n int) ManagerOption
WithInboundWorkers sets the number of goroutines that process inbound messages concurrently. The default is 4.
func WithRefreshInterval ¶
func WithRefreshInterval(d time.Duration) ManagerOption
WithRefreshInterval overrides the periodic connection reconcile interval. The default is 5 minutes.
type ManagerStore ¶
type ManagerStore interface {
ConfigLister
ConfigResolver
}
ManagerStore is the minimal persistence interface required by Manager.
type Message ¶
type Message struct {
ID string `json:"id,omitempty"`
Format MessageFormat `json:"format,omitempty"`
Text string `json:"text,omitempty"`
Parts []MessagePart `json:"parts,omitempty"`
Attachments []Attachment `json:"attachments,omitempty"`
Actions []Action `json:"actions,omitempty"`
Thread *ThreadRef `json:"thread,omitempty"`
Reply *ReplyRef `json:"reply,omitempty"`
Forward *ForwardRef `json:"forward,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
}
Message is the unified message structure used across all channels.
Thread routing should flow through Conversation.ThreadID at the envelope level. Thread remains for API compatibility with existing callers that still attach thread scope to the message body. Forward is populated inbound (Telegram, Misskey) and persisted to history but no adapter Send currently honors it on outbound — explicitly forwarding an existing message requires a dedicated future feature.
func BuildToolApprovalPrompt ¶
func ResolveMarkdownMessage ¶ added in v1.0.0
func ResolveMarkdownMessage(ctx context.Context, store OutboundAttachmentStore, botID string, channelType ChannelType, msg Message) Message
ResolveMarkdownMessage archives the media a message references, for an IM destination. The agent server calls it before handing a message to the Channel process, which may not reach the bot workspace.
func WithoutMarkdownMedia ¶ added in v1.0.0
WithoutMarkdownMedia drops publication metadata a caller supplied itself. Only the agent publishes media, from snapshots it archived; other senders deliver their Markdown as written.
type MessageEditor ¶
type MessageEditor interface {
Update(ctx context.Context, cfg ChannelConfig, target string, messageID string, msg PreparedMessage) error
Unsend(ctx context.Context, cfg ChannelConfig, target string, messageID string) error
}
MessageEditor updates and deletes already-sent messages when supported.
type MessageFormat ¶
type MessageFormat string
MessageFormat indicates how the message text should be rendered.
const ( MessageFormatPlain MessageFormat = "plain" MessageFormatMarkdown MessageFormat = "markdown" MessageFormatRich MessageFormat = "rich" )
type MessagePart ¶
type MessagePart struct {
Type MessagePartType `json:"type"`
Text string `json:"text,omitempty"`
URL string `json:"url,omitempty"`
Styles []MessageTextStyle `json:"styles,omitempty"`
Language string `json:"language,omitempty"`
ChannelIdentityID string `json:"channel_identity_id,omitempty"`
Emoji string `json:"emoji,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
}
MessagePart is a single element within a rich-text message.
type MessagePartType ¶
type MessagePartType string
MessagePartType identifies the kind of a rich-text message part.
const ( MessagePartText MessagePartType = "text" MessagePartLink MessagePartType = "link" MessagePartCodeBlock MessagePartType = "code_block" MessagePartMention MessagePartType = "mention" MessagePartEmoji MessagePartType = "emoji" MessagePartHeading MessagePartType = "heading" MessagePartBlockquote MessagePartType = "blockquote" MessagePartListItem MessagePartType = "list_item" )
type MessageTextStyle ¶
type MessageTextStyle string
MessageTextStyle describes inline formatting for a text part.
const ( MessageStyleBold MessageTextStyle = "bold" MessageStyleItalic MessageTextStyle = "italic" MessageStyleStrikethrough MessageTextStyle = "strikethrough" MessageStyleCode MessageTextStyle = "code" MessageStyleUnderline MessageTextStyle = "underline" MessageStyleSpoiler MessageTextStyle = "spoiler" )
type Middleware ¶
type Middleware func(next InboundHandler) InboundHandler
Middleware wraps an InboundHandler to add cross-cutting behavior.
type OutboundAttachmentStore ¶
type OutboundAttachmentStore interface {
// Stat returns asset metadata by content hash without opening the file.
Stat(ctx context.Context, botID, contentHash string) (media.Asset, error)
Open(ctx context.Context, botID, contentHash string) (io.ReadCloser, media.Asset, error)
Ingest(ctx context.Context, input media.IngestInput) (media.Asset, error)
GetByStorageKey(ctx context.Context, botID, storageKey string) (media.Asset, error)
AccessPath(ctx context.Context, asset media.Asset) string
}
OutboundAttachmentStore provides the storage operations required by the outbound attachment preparer.
type OutboundCapabilityResolver ¶
type OutboundCapabilityResolver interface {
ResolveOutboundCapabilities(cfg ChannelConfig, target string, base ChannelCapabilities) ChannelCapabilities
}
OutboundCapabilityResolver can refine static descriptor capabilities for a specific outbound config and target when platform support is runtime-gated.
type OutboundMessage ¶
OutboundMessage pairs a delivery target with the message content.
type OutboundOrder ¶
type OutboundOrder string
OutboundOrder controls the delivery order of text and media messages.
const ( OutboundOrderMediaFirst OutboundOrder = "media_first" OutboundOrderTextFirst OutboundOrder = "text_first" )
type OutboundPolicy ¶
type OutboundPolicy struct {
TextChunkLimit int `json:"text_chunk_limit,omitempty"`
RichTextChunkLimit int `json:"rich_text_chunk_limit,omitempty"`
ChunkerMode ChunkerMode `json:"chunker_mode,omitempty"`
Chunker Chunker `json:"-"`
MediaOrder OutboundOrder `json:"media_order,omitempty"`
InlineTextWithMedia bool `json:"inline_text_with_media,omitempty"`
RetryMax int `json:"retry_max,omitempty"`
RetryBackoffMs int `json:"retry_backoff_ms,omitempty"`
}
OutboundPolicy configures how outbound messages are chunked, ordered, and retried.
func NormalizeOutboundPolicy ¶
func NormalizeOutboundPolicy(policy OutboundPolicy) OutboundPolicy
NormalizeOutboundPolicy fills zero-value fields with sensible defaults.
type OutboundStream ¶
type OutboundStream interface {
Push(ctx context.Context, event StreamEvent) error
Close(ctx context.Context) error
}
OutboundStream is a live stream session for emitting outbound events. Implementations are not required to be safe for concurrent use; callers must serialize Push and Close calls within a single goroutine.
func NewTeeStream ¶
func NewTeeStream(primary OutboundStream, observer StreamObserver, botID string, source ChannelType) OutboundStream
NewTeeStream wraps primary so that every Push also notifies observer.
func NewToolCallDroppingStream ¶
func NewToolCallDroppingStream(primary OutboundStream) OutboundStream
NewToolCallDroppingStream wraps primary, replaces non-interactive tool_call_start events with segment_end and drops tool_call_end events. When primary is nil the function returns nil.
type OutboundTargetResolver ¶
type OutboundTargetResolver interface {
ResolveOutboundTarget(ctx context.Context, cfg ChannelConfig, target string) (string, error)
}
OutboundTargetResolver can resolve delivery aliases to the concrete platform target before outbound capability checks run.
type PreparedAttachment ¶
type PreparedAttachment struct {
Logical Attachment
Kind PreparedAttachmentKind
NativeRef string
PublicURL string
Name string
Mime string
Size int64
// Open must return a fresh reader each time so retries are safe.
Open func(ctx context.Context) (io.ReadCloser, error)
}
PreparedAttachment is the adapter-facing attachment model after preparation.
type PreparedAttachmentKind ¶
type PreparedAttachmentKind string
PreparedAttachmentKind identifies how an attachment should be delivered.
const ( PreparedAttachmentNativeRef PreparedAttachmentKind = "native_ref" PreparedAttachmentPublicURL PreparedAttachmentKind = "public_url" PreparedAttachmentUpload PreparedAttachmentKind = "upload" )
type PreparedMessage ¶
type PreparedMessage struct {
Message Message
Attachments []PreparedAttachment
}
PreparedMessage is the adapter-facing form of a Message.
func (PreparedMessage) LogicalMessage ¶
func (m PreparedMessage) LogicalMessage() Message
LogicalMessage converts the prepared message back to the logical channel message.
type PreparedOutboundMessage ¶
type PreparedOutboundMessage struct {
Target string
Message PreparedMessage
}
PreparedOutboundMessage is the adapter-facing form of OutboundMessage.
func PrepareOutboundMessage ¶
func PrepareOutboundMessage( ctx context.Context, store OutboundAttachmentStore, cfg ChannelConfig, msg OutboundMessage, ) (PreparedOutboundMessage, error)
PrepareOutboundMessage resolves the logical outbound message into the adapter-facing prepared model.
func (PreparedOutboundMessage) LogicalMessage ¶
func (m PreparedOutboundMessage) LogicalMessage() OutboundMessage
LogicalMessage converts the prepared outbound message back to the logical model.
type PreparedOutboundStream ¶
type PreparedOutboundStream interface {
Push(ctx context.Context, event PreparedStreamEvent) error
Close(ctx context.Context) error
}
PreparedOutboundStream is the adapter-facing stream session.
type PreparedOutboundValidator ¶
type PreparedOutboundValidator interface {
ValidatePreparedOutbound(ctx context.Context, cfg ChannelConfig, target string, msg PreparedOutboundMessage) error
}
PreparedOutboundValidator lets adapters reject platform-invalid prepared messages before a batched/chunked send starts delivering earlier items.
type PreparedStreamEvent ¶
type PreparedStreamEvent struct {
Type StreamEventType
Status StreamStatus
Delta string
Final *PreparedStreamFinalizePayload
Error string
ErrorCode string
ToolCall *StreamToolCall
Phase StreamPhase
Attachments []PreparedAttachment
Reactions []ReactRequest
Speeches []SpeechRequest
Metadata map[string]any
}
PreparedStreamEvent is the adapter-facing form of StreamEvent.
func PrepareStreamEvent ¶
func PrepareStreamEvent( ctx context.Context, store OutboundAttachmentStore, cfg ChannelConfig, event StreamEvent, ) (PreparedStreamEvent, error)
PrepareStreamEvent resolves logical stream payloads before they enter an adapter.
func (PreparedStreamEvent) LogicalEvent ¶
func (e PreparedStreamEvent) LogicalEvent() StreamEvent
LogicalEvent converts the prepared stream event back to the logical model.
type PreparedStreamFinalizePayload ¶
type PreparedStreamFinalizePayload struct {
Message PreparedMessage
}
PreparedStreamFinalizePayload is the adapter-facing stream final payload.
type ProcessingStatus ¶ added in v0.22.0
type ProcessingStatus struct {
// contains filtered or unexported fields
}
ProcessingStatus drives the platform processing indicator for one turn: Started once, Refresh on the notifier's interval while the turn runs, then exactly one of Completed or Failed. Every call is best-effort; failures go to the error func and never fail the turn. A nil notifier yields an inert session, so callers need no nil checks.
func StartProcessingStatus ¶ added in v0.22.0
func StartProcessingStatus(ctx context.Context, notifier ProcessingStatusNotifier, cfg ChannelConfig, msg InboundMessage, info ProcessingStatusInfo, onError ProcessingStatusErrorFunc) *ProcessingStatus
StartProcessingStatus reports Started and, when the notifier implements ProcessingStatusRefresher, keeps the indicator alive until StopRefresh, Complete or Fail. ctx scopes Started and the refreshes, and its cancellation ends refreshing.
func (*ProcessingStatus) Complete ¶ added in v0.22.0
func (s *ProcessingStatus) Complete(ctx context.Context)
Complete stops refreshing and reports Completed. Only the first Complete or Fail reports; later calls are no-ops.
func (*ProcessingStatus) Fail ¶ added in v0.22.0
func (s *ProcessingStatus) Fail(ctx context.Context, cause error)
Fail stops refreshing and reports Failed with cause. Only the first Complete or Fail reports; later calls are no-ops.
func (*ProcessingStatus) PauseRefresh ¶ added in v0.22.0
func (s *ProcessingStatus) PauseRefresh()
PauseRefresh holds the indicator while the turn waits on the user, such as a pending tool approval or ask_user question; the platform indicator then lapses on its own. ResumeRefresh re-sends it at once and restarts the interval.
func (*ProcessingStatus) ResumeRefresh ¶ added in v0.22.0
func (s *ProcessingStatus) ResumeRefresh()
ResumeRefresh undoes PauseRefresh. It is cheap to call when not paused.
func (*ProcessingStatus) StopRefresh ¶ added in v0.22.0
func (s *ProcessingStatus) StopRefresh()
StopRefresh ends refreshing and returns only after an in-flight refresh has returned, so no indicator is sent after the caller delivers its reply. An in-flight refresh is waited for rather than canceled: canceling a request already on the wire does not stop the platform from applying it.
type ProcessingStatusErrorFunc ¶ added in v0.22.0
ProcessingStatusErrorFunc receives the best-effort failures of a ProcessingStatus, keyed by one of the ProcessingStage constants.
type ProcessingStatusHandle ¶
type ProcessingStatusHandle struct {
Token string
}
ProcessingStatusHandle stores channel-specific state between status callbacks.
type ProcessingStatusInfo ¶
type ProcessingStatusInfo struct {
BotID string
ChatID string
RouteID string
ChannelIdentityID string
UserID string
Query string
ReplyTarget string
SourceMessageID string
}
ProcessingStatusInfo carries context for channel-level processing status updates.
type ProcessingStatusNotifier ¶
type ProcessingStatusNotifier interface {
ProcessingStarted(ctx context.Context, cfg ChannelConfig, msg InboundMessage, info ProcessingStatusInfo) (ProcessingStatusHandle, error)
ProcessingCompleted(ctx context.Context, cfg ChannelConfig, msg InboundMessage, info ProcessingStatusInfo, handle ProcessingStatusHandle) error
ProcessingFailed(ctx context.Context, cfg ChannelConfig, msg InboundMessage, info ProcessingStatusInfo, handle ProcessingStatusHandle, cause error) error
}
ProcessingStatusNotifier reports processing lifecycle updates to channel platforms. Implementations should be best-effort and idempotent.
type ProcessingStatusRefresher ¶ added in v0.22.0
type ProcessingStatusRefresher interface {
// ProcessingRefreshInterval is how often the indicator is re-sent. A
// non-positive interval disables refreshing.
ProcessingRefreshInterval() time.Duration
ProcessingRefresh(ctx context.Context, cfg ChannelConfig, msg InboundMessage, info ProcessingStatusInfo, handle ProcessingStatusHandle) error
}
ProcessingStatusRefresher is implemented by notifiers whose platform indicator expires and must be re-sent while processing continues, such as the Telegram and Discord typing actions.
type ReactRequest ¶
type ReactRequest struct {
Target string `json:"target"`
MessageID string `json:"message_id"`
Emoji string `json:"emoji"`
Remove bool `json:"remove,omitempty"`
}
ReactRequest is the input for adding or removing an emoji reaction on a message.
type Reactor ¶
type Reactor interface {
React(ctx context.Context, cfg ChannelConfig, target string, messageID string, emoji string) error
Unreact(ctx context.Context, cfg ChannelConfig, target string, messageID string, emoji string) error
}
Reactor adds or removes emoji reactions on messages.
type Receiver ¶
type Receiver interface {
Connect(ctx context.Context, cfg ChannelConfig, handler InboundHandler) (Connection, error)
}
Receiver is an adapter capable of establishing a long-lived connection to receive messages.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry holds all registered channel adapters and provides dispatch methods for configuration normalization, target resolution, and binding operations. It replaces the former global registry, and must be created via NewRegistry and passed explicitly to components that need it.
func (*Registry) BuildUserBindingConfig ¶
func (r *Registry) BuildUserBindingConfig(channelType ChannelType, identity Identity) map[string]any
BuildUserBindingConfig constructs a user-channel binding config from an Identity.
func (*Registry) DirectoryAdapter ¶
func (r *Registry) DirectoryAdapter(channelType ChannelType) (ChannelDirectoryAdapter, bool)
DirectoryAdapter returns the directory adapter for the given channel type if it implements ChannelDirectoryAdapter.
func (*Registry) DiscoverSelf ¶
func (r *Registry) DiscoverSelf(ctx context.Context, channelType ChannelType, credentials map[string]any) (map[string]any, string, error)
DiscoverSelf calls the SelfDiscoverer for the given channel type if supported.
func (*Registry) Get ¶
func (r *Registry) Get(channelType ChannelType) (Adapter, bool)
Get returns the adapter for the given channel type.
func (*Registry) GetAttachmentResolver ¶
func (r *Registry) GetAttachmentResolver(channelType ChannelType) (AttachmentResolver, bool)
GetAttachmentResolver returns the AttachmentResolver for the given channel type, or nil if unsupported.
func (*Registry) GetCapabilities ¶
func (r *Registry) GetCapabilities(channelType ChannelType) (ChannelCapabilities, bool)
GetCapabilities returns the capability matrix for the given channel type.
func (*Registry) GetConfigSchema ¶
func (r *Registry) GetConfigSchema(channelType ChannelType) (ConfigSchema, bool)
GetConfigSchema returns the configuration schema for the given channel type.
func (*Registry) GetDescriptor ¶
func (r *Registry) GetDescriptor(channelType ChannelType) (Descriptor, bool)
GetDescriptor returns the descriptor for the given channel type.
func (*Registry) GetMessageEditor ¶
func (r *Registry) GetMessageEditor(channelType ChannelType) (MessageEditor, bool)
GetMessageEditor returns the MessageEditor for the given channel type, or nil if unsupported.
func (*Registry) GetOutboundCapabilities ¶
func (r *Registry) GetOutboundCapabilities(channelType ChannelType, cfg ChannelConfig, target string) (ChannelCapabilities, bool)
GetOutboundCapabilities returns capabilities refined for one outbound target.
func (*Registry) GetOutboundPolicy ¶
func (r *Registry) GetOutboundPolicy(channelType ChannelType) (OutboundPolicy, bool)
GetOutboundPolicy returns the outbound policy for the given channel type.
func (*Registry) GetProcessingStatusNotifier ¶
func (r *Registry) GetProcessingStatusNotifier(channelType ChannelType) (ProcessingStatusNotifier, bool)
GetProcessingStatusNotifier returns the ProcessingStatusNotifier for the given channel type, or nil if unsupported.
func (*Registry) GetReactor ¶
func (r *Registry) GetReactor(channelType ChannelType) (Reactor, bool)
GetReactor returns the Reactor for the given channel type, or nil if unsupported.
func (*Registry) GetReceiver ¶
func (r *Registry) GetReceiver(channelType ChannelType) (Receiver, bool)
GetReceiver returns the Receiver for the given channel type, or nil if unsupported.
func (*Registry) GetSender ¶
func (r *Registry) GetSender(channelType ChannelType) (Sender, bool)
GetSender returns the Sender for the given channel type, or nil if unsupported.
func (*Registry) GetStreamSender ¶
func (r *Registry) GetStreamSender(channelType ChannelType) (StreamSender, bool)
GetStreamSender returns the StreamSender for the given channel type, or nil if unsupported.
func (*Registry) GetUserConfigSchema ¶
func (r *Registry) GetUserConfigSchema(channelType ChannelType) (ConfigSchema, bool)
GetUserConfigSchema returns the user-binding configuration schema.
func (*Registry) GetWebhookEndpointSetter ¶
func (r *Registry) GetWebhookEndpointSetter(channelType ChannelType) (WebhookEndpointSetter, bool)
GetWebhookEndpointSetter returns the platform webhook endpoint setter for the given channel.
func (*Registry) GetWebhookReceiver ¶
func (r *Registry) GetWebhookReceiver(channelType ChannelType) (WebhookReceiver, bool)
GetWebhookReceiver returns the WebhookReceiver for the given channel type, or nil if unsupported.
func (*Registry) IsConfigless ¶
func (r *Registry) IsConfigless(channelType ChannelType) bool
IsConfigless reports whether the channel type operates without per-bot configuration.
func (*Registry) IsOwnerOnly ¶ added in v0.21.0
func (r *Registry) IsOwnerOnly(channelType ChannelType) bool
IsOwnerOnly reports whether the given channel type is owner-only: no third party can ever become a sender there (see Descriptor.OwnerOnly).
func (*Registry) ListDescriptors ¶
func (r *Registry) ListDescriptors() []Descriptor
ListDescriptors returns descriptors for all registered channel types.
func (*Registry) MatchUserBinding ¶
func (r *Registry) MatchUserBinding(channelType ChannelType, config map[string]any, criteria BindingCriteria) bool
MatchUserBinding reports whether the given binding config matches the criteria.
func (*Registry) MustRegister ¶
MustRegister calls Register and panics on error.
func (*Registry) NormalizeConfig ¶
func (r *Registry) NormalizeConfig(channelType ChannelType, raw map[string]any) (map[string]any, error)
NormalizeConfig validates and normalizes a channel configuration map.
func (*Registry) NormalizeTarget ¶
func (r *Registry) NormalizeTarget(channelType ChannelType, raw string) (string, bool)
NormalizeTarget applies the channel-specific target normalization.
func (*Registry) NormalizeUserConfig ¶
func (r *Registry) NormalizeUserConfig(channelType ChannelType, raw map[string]any) (map[string]any, error)
NormalizeUserConfig validates and normalizes a user-channel binding configuration.
func (*Registry) ParseChannelType ¶
func (r *Registry) ParseChannelType(raw string) (ChannelType, error)
ParseChannelType validates and normalizes a raw string into a registered ChannelType.
func (*Registry) ResolveOutboundTarget ¶
func (r *Registry) ResolveOutboundTarget(ctx context.Context, channelType ChannelType, cfg ChannelConfig, target string) (string, bool, error)
ResolveOutboundTarget resolves runtime delivery aliases before outbound capability checks and adapter dispatch.
func (*Registry) ResolveTargetFromUserConfig ¶
func (r *Registry) ResolveTargetFromUserConfig(channelType ChannelType, config map[string]any) (string, error)
ResolveTargetFromUserConfig derives a delivery target from a user-channel binding.
func (*Registry) SelfIdentityPolicy ¶
func (r *Registry) SelfIdentityPolicy(channelType ChannelType) SelfIdentityPolicy
SelfIdentityPolicy returns adapter-specific persistence requirements for discovered platform bot identity. Most adapters use the zero-value best-effort policy; webhook adapters that cannot route safely without self identity can opt into stricter enable-time validation.
func (*Registry) Types ¶
func (r *Registry) Types() []ChannelType
Types returns all registered channel types.
func (*Registry) Unregister ¶
func (r *Registry) Unregister(channelType ChannelType) bool
Unregister removes a channel type from the registry.
type ReplyRef ¶
type ReplyRef struct {
Target string `json:"target,omitempty"`
MessageID string `json:"message_id,omitempty"`
Sender string `json:"sender,omitempty"`
Preview string `json:"preview,omitempty"`
Attachments []Attachment `json:"attachments,omitempty"`
AttachmentsKnown bool `json:"attachments_known,omitempty"`
}
ReplyRef points to a message being replied to.
type Runtime ¶
type Runtime interface {
UpsertBotChannelConfig(context.Context, string, ChannelType, UpsertConfigRequest) (ChannelConfig, error)
SetBotChannelStatus(context.Context, string, ChannelType, bool) (ChannelConfig, error)
DeleteBotChannelConfig(context.Context, string, ChannelType) error
SetWebhookEndpoint(context.Context, string, ChannelType, SetWebhookEndpointRequest) (SetWebhookEndpointResponse, error)
Send(context.Context, string, ChannelType, SendRequest) error
React(context.Context, string, ChannelType, ReactRequest) error
ConnectionStatusesByBot(string) []ConnectionStatus
}
Runtime is the live Channel-process surface consumed by the Server. The in-process implementation is composed from Lifecycle, Store, and Manager; production Server wiring uses the authenticated RPC implementation.
type SelfDiscoverer ¶
type SelfDiscoverer interface {
DiscoverSelf(ctx context.Context, credentials map[string]any) (identity map[string]any, externalID string, err error)
}
SelfDiscoverer retrieves the adapter bot's own identity from the platform. The returned map is merged into ChannelConfig.SelfIdentity and persisted.
type SelfIdentityPolicy ¶
type SelfIdentityPolicy struct {
RefreshOnCredentialsChange bool
RequireDiscoveryOnEnable bool
RequiredSelfIdentityKey string
DiscoveryErrorMessage string
MissingIdentityMessage string
DuplicateExternalIdentityMessage string
}
SelfIdentityPolicy describes adapter-specific requirements for persisting a platform bot identity discovered from credentials.
type SelfIdentityPolicyProvider ¶
type SelfIdentityPolicyProvider interface {
SelfIdentityPolicy() SelfIdentityPolicy
}
SelfIdentityPolicyProvider lets adapters opt into stricter self-identity discovery semantics than the default best-effort behavior.
type SendRequest ¶
type SendRequest struct {
// ExcludedTarget is checked after platform target resolution, before publication.
ExcludedTarget string `json:"excluded_target,omitempty"`
Target string `json:"target,omitempty"`
ChannelIdentityID string `json:"channel_identity_id,omitempty"`
Message Message `json:"message"`
}
SendRequest is the input for sending an outbound message through a channel.
type Sender ¶
type Sender interface {
Send(ctx context.Context, cfg ChannelConfig, msg PreparedOutboundMessage) error
}
Sender is an adapter capable of sending outbound messages.
type SetWebhookEndpointRequest ¶
type SetWebhookEndpointRequest struct {
Endpoint string `json:"endpoint"`
}
type SetWebhookEndpointResponse ¶
type SetWebhookEndpointResponse struct {
Endpoint string `json:"endpoint"`
}
type SpeechRequest ¶
type SpeechRequest struct {
Text string `json:"text"`
}
SpeechRequest carries text-to-speech synthesis text from a speech_delta stream event.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store provides CRUD operations for channel configurations, user bindings, and sessions.
func (*Store) DeleteConfig ¶
DeleteConfig removes a bot's channel configuration.
func (*Store) GetChannelIdentityConfig ¶
func (s *Store) GetChannelIdentityConfig(ctx context.Context, channelIdentityID string, channelType ChannelType) (ChannelIdentityBinding, error)
GetChannelIdentityConfig returns the channel identity's channel binding for the given channel type.
func (*Store) ListBotConfigs ¶
ListBotConfigs returns all registered channel configs for a bot. Missing configs are skipped so callers can enumerate platform state without knowing which integrations are currently configured.
func (*Store) ListChannelIdentityConfigsByType ¶
func (s *Store) ListChannelIdentityConfigsByType(ctx context.Context, channelType ChannelType) ([]ChannelIdentityBinding, error)
ListChannelIdentityConfigsByType returns all channel identity bindings for the given channel type.
func (*Store) ListConfigs ¶
ListConfigs returns all persisted channel configurations for a bot.
func (*Store) ListConfigsByType ¶
func (s *Store) ListConfigsByType(ctx context.Context, channelType ChannelType) ([]ChannelConfig, error)
ListConfigsByType returns all channel configurations of the given type.
func (*Store) ResolveChannelIdentityBinding ¶
func (s *Store) ResolveChannelIdentityBinding(ctx context.Context, channelType ChannelType, criteria BindingCriteria) (string, error)
ResolveChannelIdentityBinding finds the channel identity ID whose channel binding matches the given criteria.
func (*Store) ResolveEffectiveConfig ¶
func (s *Store) ResolveEffectiveConfig(ctx context.Context, botID string, channelType ChannelType) (ChannelConfig, error)
ResolveEffectiveConfig returns the active channel configuration for a bot. For configless channel types, a synthetic config is returned.
func (*Store) SaveMatrixSyncSinceToken ¶
SaveMatrixSyncSinceToken persists the Matrix /sync cursor without mutating channel config updated_at.
func (*Store) SetWebhookEndpoint ¶
func (s *Store) SetWebhookEndpoint(ctx context.Context, botID string, channelType ChannelType, req SetWebhookEndpointRequest) (SetWebhookEndpointResponse, error)
func (*Store) UpdateConfigDisabled ¶
func (s *Store) UpdateConfigDisabled(ctx context.Context, botID string, channelType ChannelType, disabled bool) (ChannelConfig, error)
UpdateConfigDisabled updates only the disabled flag for a bot channel config and returns latest config.
func (*Store) UpsertChannelIdentityConfig ¶
func (s *Store) UpsertChannelIdentityConfig(ctx context.Context, channelIdentityID string, channelType ChannelType, req UpsertChannelIdentityConfigRequest) (ChannelIdentityBinding, error)
UpsertChannelIdentityConfig creates or updates a channel identity's channel binding.
func (*Store) UpsertConfig ¶
func (s *Store) UpsertConfig(ctx context.Context, botID string, channelType ChannelType, req UpsertConfigRequest) (ChannelConfig, error)
UpsertConfig creates or updates a bot's channel configuration.
type StreamEvent ¶
type StreamEvent struct {
Type StreamEventType `json:"type"`
Status StreamStatus `json:"status,omitempty"`
Delta string `json:"delta,omitempty"`
Final *StreamFinalizePayload `json:"final,omitempty"`
Error string `json:"error,omitempty"`
ErrorCode string `json:"error_code,omitempty"`
ToolCall *StreamToolCall `json:"tool_call,omitempty"`
Phase StreamPhase `json:"phase,omitempty"`
Attachments []Attachment `json:"attachments,omitempty"`
Reactions []ReactRequest `json:"reactions,omitempty"`
Speeches []SpeechRequest `json:"speeches,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
}
StreamEvent represents a unified stream event routed through the channel layer. ErrorCode names the catalog code Error was rendered from: with a code, Error is complete user-facing copy; without one it is a bare error text.
func CodeEvent ¶ added in v0.22.0
CodeEvent is the stream error for a code that was recorded rather than returned: the code a failed run stored, or the code of a history event. It carries the copy for code, or the copy for runtime_run_failed when code is not in the catalog, so the text is always catalog copy and never an error's own text.
func ErrorEvent ¶ added in v0.21.0
ErrorEvent is the stream error a channel shows for err, answered by errs.Answer as an HTTP response would be: the copy for the public error, carrying its code. The error's own text is never shown; the unit's result record reports it. It reports false when the caller has canceled, which is not answered.
type StreamEventType ¶
type StreamEventType string
StreamEventType defines the kind of outbound stream event.
const ( StreamEventStatus StreamEventType = "status" StreamEventDelta StreamEventType = "delta" StreamEventFinal StreamEventType = "final" StreamEventError StreamEventType = "error" StreamEventToolCallStart StreamEventType = "tool_call_start" StreamEventToolCallEnd StreamEventType = "tool_call_end" StreamEventPhaseStart StreamEventType = "phase_start" StreamEventPhaseEnd StreamEventType = "phase_end" StreamEventAttachment StreamEventType = "attachment" StreamEventAgentStart StreamEventType = "agent_start" StreamEventAgentEnd StreamEventType = "agent_end" StreamEventReaction StreamEventType = "reaction" StreamEventSpeech StreamEventType = "speech" StreamEventProcessingStarted StreamEventType = "processing_started" StreamEventProcessingCompleted StreamEventType = "processing_completed" // StreamEventReset discards the reply text streamed so far: the agent is // retrying and regenerates it from scratch, so the next delta starts a // fresh reply instead of extending the failed attempt's partial output. StreamEventReset StreamEventType = "reset" // StreamEventSegmentEnd marks that the current assistant text segment // ended at a tool call hidden from this channel. Adapters commit the // buffered text as its own message and reset per-message streaming // state, without rendering any tool-call UI, so the text that follows // the tool call starts a fresh message. StreamEventSegmentEnd StreamEventType = "segment_end" )
type StreamFinalizePayload ¶
type StreamFinalizePayload struct {
Message Message `json:"message"`
}
StreamFinalizePayload carries the final reply message emitted by a stream.
type StreamObserver ¶
type StreamObserver interface {
// OnStreamEvent is called for every event pushed to an outbound stream.
// botID identifies the bot that owns the conversation.
// source is the channel type that originated the event (e.g. "telegram").
OnStreamEvent(ctx context.Context, botID string, source ChannelType, event StreamEvent)
}
StreamObserver receives copies of stream events for cross-channel broadcasting or external notification (e.g. webhooks). Implementations must be safe for concurrent use and should not block.
type StreamOptions ¶
type StreamOptions struct {
Reply *ReplyRef `json:"reply,omitempty"`
SourceMessageID string `json:"source_message_id,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
}
StreamOptions configures how an outbound stream is initialized.
type StreamPhase ¶
type StreamPhase string
StreamPhase labels a processing stage within a stream (e.g., reasoning, text).
const ( StreamPhaseReasoning StreamPhase = "reasoning" StreamPhaseText StreamPhase = "text" )
type StreamReplySender ¶
type StreamReplySender interface {
Send(ctx context.Context, msg OutboundMessage) error
OpenStream(ctx context.Context, target string, opts StreamOptions) (OutboundStream, error)
}
StreamReplySender sends replies within a single inbound-processing scope. It supports both one-shot delivery and streaming sessions.
type StreamSender ¶
type StreamSender interface {
OpenStream(ctx context.Context, cfg ChannelConfig, target string, opts StreamOptions) (PreparedOutboundStream, error)
}
StreamSender is an adapter capable of opening outbound stream sessions.
type StreamStatus ¶
type StreamStatus string
StreamStatus indicates the lifecycle state of a streaming reply.
const ( StreamStatusStarted StreamStatus = "started" StreamStatusCompleted StreamStatus = "completed" StreamStatusFailed StreamStatus = "failed" )
type StreamToolCall ¶
type StreamToolCall struct {
Name string `json:"name"`
CallID string `json:"call_id,omitempty"`
Locale string `json:"locale,omitempty"`
Input any `json:"input,omitempty"`
Result any `json:"result,omitempty"`
ApprovalID string `json:"approval_id,omitempty"`
ShortID int `json:"short_id,omitempty"`
Actions []Action `json:"actions,omitempty"`
}
StreamToolCall carries tool invocation data for tool_call_start / tool_call_end events.
type TargetHint ¶
type TargetHint struct {
Example string `json:"example,omitempty"`
Label string `json:"label,omitempty"`
}
TargetHint provides a display label and example for a target format.
type TargetResolver ¶
type TargetResolver interface {
NormalizeTarget(raw string) string
ResolveTarget(userConfig map[string]any) (string, error)
}
TargetResolver handles delivery target normalization and resolution from user bindings.
type TargetSpec ¶
type TargetSpec struct {
Format string `json:"format"`
Hints []TargetHint `json:"hints,omitempty"`
}
TargetSpec describes the expected format of a delivery target for a channel type.
type ThreadRef ¶
type ThreadRef struct {
ID string `json:"id"`
}
ThreadRef references a conversation thread by ID.
type ToolCallBlock ¶
type ToolCallBlock struct {
Type ToolCallBlockType
Title string
URL string
Desc string
Text string
}
ToolCallBlock is one rich element inside ToolCallPresentation.Body. Fields not applicable to the Type are ignored.
type ToolCallBlockType ¶
type ToolCallBlockType string
ToolCallBlockType distinguishes body block rendering semantics.
const ( ToolCallBlockText ToolCallBlockType = "text" // free-form line or paragraph ToolCallBlockLink ToolCallBlockType = "link" // titled hyperlink, optional description ToolCallBlockCode ToolCallBlockType = "code" // preformatted / code block )
type ToolCallPresentation ¶
type ToolCallPresentation struct {
Emoji string
ToolName string
Status ToolCallStatus
// HideToolHeader is for user-facing interactions whose implementation as
// a tool is not meaningful to the recipient, such as ask_user prompts.
HideToolHeader bool
Header string
Body []ToolCallBlock
InputSummary string
ResultSummary string
}
ToolCallPresentation is the rendered single-message view of one tool call state. Adapters call RenderToolCallMessage (or their own renderer) against this struct to produce the final IM text body.
The preferred fields are Header / Body / Footer, populated either by per-tool formatters (see toolcall_formatters.go) or by the generic builder. InputSummary / ResultSummary are retained so existing callers that expect two flat strings keep working.
func BuildToolCallEnd ¶
func BuildToolCallEnd(tc *StreamToolCall) ToolCallPresentation
BuildToolCallEnd builds a presentation for a tool_call_end event. The completed / failed status is inferred from the tool result payload (ok=false, error fields, non-zero exit codes, etc.).
func BuildToolCallStart ¶
func BuildToolCallStart(tc *StreamToolCall) ToolCallPresentation
BuildToolCallStart builds a presentation for a tool_call_start event. Returns a zero-value presentation when the payload is nil.
type ToolCallStatus ¶
type ToolCallStatus string
ToolCallStatus is the lifecycle state of a single tool call as surfaced in IM.
const ( ToolCallStatusRunning ToolCallStatus = "running" ToolCallStatusWaiting ToolCallStatus = "waiting" ToolCallStatusApprovalRequired ToolCallStatus = "approval_required" ToolCallStatusCompleted ToolCallStatus = "completed" ToolCallStatusFailed ToolCallStatus = "failed" )
type UpdateChannelStatusRequest ¶
type UpdateChannelStatusRequest struct {
Disabled bool `json:"disabled"`
}
UpdateChannelStatusRequest is the input for enabling/disabling a bot channel config.
type UpsertChannelIdentityConfigRequest ¶
UpsertChannelIdentityConfigRequest is the input for creating or updating a channel-identity binding.
type UpsertConfigRequest ¶
type UpsertConfigRequest struct {
Credentials map[string]any `json:"credentials"`
ExternalIdentity string `json:"external_identity,omitempty"`
SelfIdentity map[string]any `json:"self_identity,omitempty"`
Routing map[string]any `json:"routing,omitempty"`
Disabled *bool `json:"disabled,omitempty"`
VerifiedAt *time.Time `json:"verified_at,omitempty"`
}
UpsertConfigRequest is the input for creating or updating a channel configuration. Disabled: true to stop the channel, false to enable it. Omitted is treated as false (enabled).
type WebhookEndpointSetter ¶
type WebhookEndpointSetter interface {
SetWebhookEndpoint(ctx context.Context, credentials map[string]any, endpoint string) error
}
WebhookEndpointSetter updates the platform-side webhook endpoint.
type WebhookHandler ¶
type WebhookHandler struct {
// contains filtered or unexported fields
}
WebhookHandler dispatches public webhook callbacks to channel adapters.
func NewWebhookServerHandler ¶
func NewWebhookServerHandler(log *slog.Logger, store *Store, manager *Manager) *WebhookHandler
NewWebhookServerHandler creates the generic channel webhook handler.
func (*WebhookHandler) Handle ¶
func (h *WebhookHandler) Handle(c echo.Context) error
Handle resolves the channel config and delegates the request to the adapter.
func (*WebhookHandler) Register ¶
func (h *WebhookHandler) Register(e *echo.Echo)
Register registers generic channel webhook routes.
type WebhookReceiver ¶
type WebhookReceiver interface {
HandleWebhook(ctx context.Context, cfg ChannelConfig, handler InboundHandler, r *http.Request, w http.ResponseWriter) error
}
WebhookReceiver handles inbound HTTP webhook callbacks for webhook-style channels. Implementations typically verify the request, parse the platform payload, and forward resulting inbound messages to the provided handler.
Source Files
¶
- adapter.go
- attachment_bundle.go
- capabilities.go
- config.go
- connection.go
- directory.go
- error_text.go
- format.go
- inbound.go
- lifecycle.go
- manager.go
- markdown_media.go
- markdown_stream.go
- normalize.go
- observer.go
- outbound.go
- outbound_prepare.go
- parts_render.go
- prepared_outbound.go
- processing_status.go
- processor.go
- public_host.go
- registry.go
- runtime.go
- schema.go
- service.go
- skill_metadata.go
- target.go
- tool_approval_prompt.go
- toolcall_filter.go
- toolcall_format.go
- toolcall_formatters.go
- toolcall_summary.go
- types.go
- webhook_endpoint.go
- webhook_handler.go
Directories
¶
| Path | Synopsis |
|---|---|
|
adapters
|
|
|
dingtalk
Package dingtalk implements the DingTalk channel adapter.
|
Package dingtalk implements the DingTalk channel adapter. |
|
feishu
Package feishu implements the Feishu (Lark) channel adapter.
|
Package feishu implements the Feishu (Lark) channel adapter. |
|
feishu/wsclient
Package wsclient is a Feishu/Lark long-connection websocket client.
|
Package wsclient is a Feishu/Lark long-connection websocket client. |
|
local
Package local implements the CLI and Web channel adapters for local development.
|
Package local implements the CLI and Web channel adapters for local development. |
|
misskey
Package misskey implements the Misskey channel adapter.
|
Package misskey implements the Misskey channel adapter. |
|
telegram
Package telegram implements the Telegram channel adapter.
|
Package telegram implements the Telegram channel adapter. |
|
Package common provides shared utilities for channel adapters.
|
Package common provides shared utilities for channel adapters. |
|
Package partsfixture exposes the canonical Message.Parts fixture used by the cross-platform rendering regression tests.
|
Package partsfixture exposes the canonical Message.Parts fixture used by the cross-platform rendering regression tests. |
|
Package publicmedia defines signed public image media paths shared by channel adapters and HTTP handlers.
|
Package publicmedia defines signed public image media paths shared by channel adapters and HTTP handlers. |