Documentation
¶
Index ¶
- type CreateSlackBotRequest
- type Handlers
- type SlackBotController
- func (c *SlackBotController) CreateSlackBot(ctx echo.Context) error
- func (c *SlackBotController) DeleteSlackBot(ctx echo.Context) error
- func (c *SlackBotController) GetSlackBot(ctx echo.Context) error
- func (c *SlackBotController) ListSlackBots(ctx echo.Context) error
- func (c *SlackBotController) UpdateSlackBot(ctx echo.Context) error
- type SlackBotEventHandler
- type SlackBotResponse
- type SlackBotSessionConfig
- type SlackBotSessionParams
- type SlackChannelResolver
- func (r *SlackChannelResolver) FetchThreadReplies(ctx context.Context, channel, threadTS, botToken string) ([]SlackMessage, error)
- func (r *SlackChannelResolver) GetBotToken(ctx context.Context, secretName, secretKey string) (string, error)
- func (r *SlackChannelResolver) PostMessage(ctx context.Context, channel, threadTS, text, botToken string) error
- func (r *SlackChannelResolver) ResolveChannelName(ctx context.Context, channelID, botToken string) (string, error)
- func (r *SlackChannelResolver) WithSlackAPIBase(base string) *SlackChannelResolver
- type SlackEvent
- type SlackMessage
- type SlackPayload
- type SlackSocketManager
- type SlackSocketManagerConfig
- type SlackSocketWorker
- type UpdateSlackBotRequest
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CreateSlackBotRequest ¶
type CreateSlackBotRequest struct {
Name string `json:"name"`
Scope entities.ResourceScope `json:"scope,omitempty"`
TeamID string `json:"team_id,omitempty"`
Status entities.SlackBotStatus `json:"status,omitempty"`
// Teams is an explicit list of team IDs (e.g. ["org/team-slug"]) whose settings
// (MCP servers, env vars, Bedrock config, etc.) will be merged into sessions
// created by this bot. When omitted, the server falls back to the authenticated
// user's team memberships at creation time.
Teams []string `json:"teams,omitempty"`
BotTokenSecretName string `json:"bot_token_secret_name,omitempty"`
BotTokenSecretKey string `json:"bot_token_secret_key,omitempty"`
AllowedEventTypes []string `json:"allowed_event_types,omitempty"`
AllowedChannelNames []string `json:"allowed_channel_names,omitempty"`
// AllowedUserIDs is the list of Slack user IDs allowed to trigger the bot.
// Empty means all users are allowed. Matching is exact (e.g., "U012AB3CD").
AllowedUserIDs []string `json:"allowed_user_ids,omitempty"`
SessionConfig *SlackBotSessionConfig `json:"session_config,omitempty"`
MaxSessions int `json:"max_sessions,omitempty"`
// NotifyOnSessionCreated controls whether the bot posts a Slack message with
// the session URL when a new session is created. Defaults to true.
NotifyOnSessionCreated *bool `json:"notify_on_session_created,omitempty"`
// AllowBotMessages controls whether the bot processes messages posted by other bots.
// Defaults to false to prevent recursive session creation.
AllowBotMessages *bool `json:"allow_bot_messages,omitempty"`
// BotToken is the Slack bot token (xoxb-...). Write-only: stored in K8s Secret, never returned.
BotToken string `json:"bot_token,omitempty"`
// AppToken is the Slack app-level token (xapp-...). Write-only: stored in K8s Secret, never returned.
AppToken string `json:"app_token,omitempty"`
}
CreateSlackBotRequest is the request body for creating a SlackBot
type Handlers ¶
type Handlers struct {
// contains filtered or unexported fields
}
Handlers provides SlackBot management REST API, implementing app.CustomHandler
func NewHandlers ¶
func NewHandlers(repo repositories.SlackBotRepository) *Handlers
NewHandlers creates a new SlackBot Handlers instance (management API only). Socket Mode event handling is managed separately by SlackSocketManager.
type SlackBotController ¶
type SlackBotController struct {
// contains filtered or unexported fields
}
SlackBotController handles SlackBot management API requests
func NewSlackBotController ¶
func NewSlackBotController(repo repositories.SlackBotRepository) *SlackBotController
NewSlackBotController creates a new SlackBotController
func (*SlackBotController) CreateSlackBot ¶
func (c *SlackBotController) CreateSlackBot(ctx echo.Context) error
CreateSlackBot handles POST /slackbots
func (*SlackBotController) DeleteSlackBot ¶
func (c *SlackBotController) DeleteSlackBot(ctx echo.Context) error
DeleteSlackBot handles DELETE /slackbots/:id
func (*SlackBotController) GetSlackBot ¶
func (c *SlackBotController) GetSlackBot(ctx echo.Context) error
GetSlackBot handles GET /slackbots/:id
func (*SlackBotController) ListSlackBots ¶
func (c *SlackBotController) ListSlackBots(ctx echo.Context) error
ListSlackBots handles GET /slackbots
func (*SlackBotController) UpdateSlackBot ¶
func (c *SlackBotController) UpdateSlackBot(ctx echo.Context) error
UpdateSlackBot handles PUT /slackbots/:id
type SlackBotEventHandler ¶
type SlackBotEventHandler struct {
// contains filtered or unexported fields
}
SlackBotEventHandler handles incoming Slack events (via Socket Mode) and manages sessions
func NewSlackBotEventHandler ¶
func NewSlackBotEventHandler( repo repositories.SlackBotRepository, sessionManager repositories.SessionManager, defaultBotTokenSecretName string, defaultBotTokenSecretKey string, channelResolver *SlackChannelResolver, baseURL string, dryRun bool, memoryRepo repositories.MemoryRepository, sessionProfileRepo repositories.SessionProfileRepository, ) *SlackBotEventHandler
NewSlackBotEventHandler creates a new SlackBotEventHandler
func (*SlackBotEventHandler) ProcessEvent ¶
func (h *SlackBotEventHandler) ProcessEvent(ctx context.Context, botID string, payload SlackPayload) error
ProcessEvent processes a parsed Slack event received via Socket Mode. botID should be the SlackBot entity ID or slackBotDefaultID ("default"). This method is called by SlackSocketWorker after acknowledging the event to Slack.
type SlackBotResponse ¶
type SlackBotResponse struct {
ID string `json:"id"`
Name string `json:"name"`
UserID string `json:"user_id"`
Scope entities.ResourceScope `json:"scope,omitempty"`
TeamID string `json:"team_id,omitempty"`
Teams []string `json:"teams,omitempty"`
Status entities.SlackBotStatus `json:"status"`
BotTokenSecretName string `json:"bot_token_secret_name,omitempty"`
BotTokenSecretKey string `json:"bot_token_secret_key,omitempty"`
AllowedEventTypes []string `json:"allowed_event_types,omitempty"`
AllowedChannelNames []string `json:"allowed_channel_names,omitempty"`
AllowedUserIDs []string `json:"allowed_user_ids,omitempty"`
SessionConfig *SlackBotSessionConfig `json:"session_config,omitempty"`
MaxSessions int `json:"max_sessions"`
NotifyOnSessionCreated bool `json:"notify_on_session_created"`
AllowBotMessages bool `json:"allow_bot_messages"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
SlackBotResponse is the API response for a SlackBot
type SlackBotSessionConfig ¶
type SlackBotSessionConfig struct {
InitialMessageTemplate string `json:"initial_message_template,omitempty"`
ReuseMessageTemplate string `json:"reuse_message_template,omitempty"`
Tags map[string]string `json:"tags,omitempty"`
Environment map[string]string `json:"environment,omitempty"`
Params *SlackBotSessionParams `json:"params,omitempty"`
MemoryKey map[string]string `json:"memory_key,omitempty"`
SessionProfileID string `json:"session_profile_id,omitempty"`
}
SlackBotSessionConfig is the session configuration for a SlackBot
type SlackBotSessionParams ¶
type SlackBotSessionParams struct {
AgentType string `json:"agent_type,omitempty"`
Oneshot bool `json:"oneshot,omitempty"`
AuthProxy *bool `json:"auth_proxy,omitempty"`
// RepoFullName is the full name of the GitHub repository to clone (e.g. "org/repo").
// When set, this repository is always used for sessions created by this SlackBot,
// taking priority over any repository auto-detected from the Slack message text.
RepoFullName string `json:"repo_full_name,omitempty"`
}
SlackBotSessionParams contains session parameters for SlackBot sessions
type SlackChannelResolver ¶
type SlackChannelResolver struct {
// contains filtered or unexported fields
}
SlackChannelResolver resolves Slack channel IDs to names using the Slack API, with a two-level cache: in-memory (sync.Map) and a Kubernetes ConfigMap for persistence.
func NewSlackChannelResolver ¶
func NewSlackChannelResolver(kubeClient kubernetes.Interface, namespace string) *SlackChannelResolver
NewSlackChannelResolver creates a new SlackChannelResolver
func (*SlackChannelResolver) FetchThreadReplies ¶
func (r *SlackChannelResolver) FetchThreadReplies(ctx context.Context, channel, threadTS, botToken string) ([]SlackMessage, error)
FetchThreadReplies fetches all messages in a Slack thread using the conversations.replies API. channel is the Slack channel ID and threadTS is the root message timestamp. Returns messages sorted by timestamp (oldest first), including the root message. Requires a bot token with channels:history or groups:history scope.
func (*SlackChannelResolver) GetBotToken ¶
func (r *SlackChannelResolver) GetBotToken(ctx context.Context, secretName, secretKey string) (string, error)
GetBotToken retrieves the Slack bot token from a Kubernetes Secret.
func (*SlackChannelResolver) PostMessage ¶
func (r *SlackChannelResolver) PostMessage(ctx context.Context, channel, threadTS, text, botToken string) error
PostMessage posts a message to a Slack channel, optionally in a thread. If threadTS is non-empty, the message is posted as a thread reply. Requires a bot token with chat:write scope.
func (*SlackChannelResolver) ResolveChannelName ¶
func (r *SlackChannelResolver) ResolveChannelName(ctx context.Context, channelID, botToken string) (string, error)
ResolveChannelName resolves a Slack channel ID to its name. Resolution order:
- In-memory cache
- Kubernetes ConfigMap (persistent)
- Slack API conversations.info (requires bot token with channels:read / groups:read scope)
func (*SlackChannelResolver) WithSlackAPIBase ¶
func (r *SlackChannelResolver) WithSlackAPIBase(base string) *SlackChannelResolver
WithSlackAPIBase overrides the Slack API base URL. Intended for testing only; production callers should use the default (https://slack.com/api).
type SlackEvent ¶
type SlackEvent struct {
Type string `json:"type"`
SubType string `json:"subtype,omitempty"`
BotID string `json:"bot_id,omitempty"`
Text string `json:"text"`
User string `json:"user"`
Channel string `json:"channel"`
Ts string `json:"ts"`
ThreadTs string `json:"thread_ts,omitempty"`
}
SlackEvent represents the inner Slack event
type SlackMessage ¶
type SlackMessage struct {
User string `json:"user"`
BotID string `json:"bot_id,omitempty"`
Text string `json:"text"`
Ts string `json:"ts"`
SubType string `json:"subtype,omitempty"`
}
SlackMessage represents a single Slack message returned by conversations.replies.
type SlackPayload ¶
type SlackPayload struct {
Type string `json:"type"`
Challenge string `json:"challenge,omitempty"`
TeamID string `json:"team_id,omitempty"`
Event *SlackEvent `json:"event,omitempty"`
}
SlackPayload represents the outer Slack event payload structure
type SlackSocketManager ¶
type SlackSocketManager struct {
// contains filtered or unexported fields
}
SlackSocketManager discovers registered SlackBots and manages one leader-elected socket worker per bot group:
- "default": all bots with no custom bot token secret
- <slackbot-id>: each bot with a custom BotTokenSecretName
func NewSlackSocketManager ¶
func NewSlackSocketManager( kubeClient kubernetes.Interface, namespace string, repo repoports.SlackBotRepository, eventHandler *SlackBotEventHandler, channelResolver *SlackChannelResolver, cfg SlackSocketManagerConfig, ) *SlackSocketManager
NewSlackSocketManager creates a new SlackSocketManager
func (*SlackSocketManager) Run ¶
func (m *SlackSocketManager) Run(ctx context.Context)
Run starts the reconciliation loop. On each tick, it discovers SlackBots and starts/stops leader-elected socket workers.
func (*SlackSocketManager) Stop ¶
func (m *SlackSocketManager) Stop()
Stop cancels all running workers
type SlackSocketManagerConfig ¶
type SlackSocketManagerConfig struct {
DefaultAppTokenSecretName string
DefaultAppTokenSecretKey string
DefaultBotTokenSecretName string
DefaultBotTokenSecretKey string
ReconcileInterval time.Duration
LeaderElectionConfig schedule.LeaderElectionConfig
}
SlackSocketManagerConfig holds configuration for SlackSocketManager
type SlackSocketWorker ¶
type SlackSocketWorker struct {
// contains filtered or unexported fields
}
SlackSocketWorker manages one Socket Mode WebSocket connection for a Slack App. For the "default" group (bots with no custom token), botID is "default". For custom bots, botID is the SlackBot entity ID.
func NewSlackSocketWorker ¶
func NewSlackSocketWorker( botID string, appTokenSecretName string, appTokenSecretKey string, botTokenSecretName string, botTokenSecretKey string, channelResolver *SlackChannelResolver, eventHandler *SlackBotEventHandler, ) *SlackSocketWorker
NewSlackSocketWorker creates a new SlackSocketWorker
func (*SlackSocketWorker) Run ¶
func (w *SlackSocketWorker) Run(ctx context.Context)
Run connects to Slack via Socket Mode and processes events until ctx is cancelled. If the connection drops unexpectedly, it retries with exponential backoff.
type UpdateSlackBotRequest ¶
type UpdateSlackBotRequest struct {
Name string `json:"name,omitempty"`
Status entities.SlackBotStatus `json:"status,omitempty"`
// Teams is an explicit list of team IDs (e.g. ["org/team-slug"]) whose settings
// will be merged into sessions created by this bot. When omitted, the server
// refreshes from the authenticated user's current team memberships.
Teams []string `json:"teams,omitempty"`
// BotTokenSecretName is a pointer to allow clearing the value by passing an empty string "".
// nil means "not provided / do not change"; "" means "clear (revert to global default)".
BotTokenSecretName *string `json:"bot_token_secret_name"`
BotTokenSecretKey *string `json:"bot_token_secret_key"`
AllowedEventTypes []string `json:"allowed_event_types,omitempty"`
AllowedChannelNames []string `json:"allowed_channel_names,omitempty"`
// AllowedUserIDs is the list of Slack user IDs allowed to trigger the bot.
// Empty means all users are allowed. Matching is exact (e.g., "U012AB3CD").
AllowedUserIDs []string `json:"allowed_user_ids,omitempty"`
SessionConfig *SlackBotSessionConfig `json:"session_config,omitempty"`
MaxSessions int `json:"max_sessions,omitempty"`
// NotifyOnSessionCreated controls whether the bot posts a Slack message with
// the session URL when a new session is created. Defaults to true.
NotifyOnSessionCreated *bool `json:"notify_on_session_created,omitempty"`
// AllowBotMessages controls whether the bot processes messages posted by other bots.
// Defaults to false to prevent recursive session creation.
AllowBotMessages *bool `json:"allow_bot_messages,omitempty"`
// BotToken is the Slack bot token (xoxb-...). Write-only: stored in K8s Secret, never returned.
BotToken string `json:"bot_token,omitempty"`
// AppToken is the Slack app-level token (xapp-...). Write-only: stored in K8s Secret, never returned.
AppToken string `json:"app_token,omitempty"`
}
UpdateSlackBotRequest is the request body for updating a SlackBot