Documentation
¶
Overview ¶
Package slack holds the bot's Slack identity: a Socket Mode connection, mentions turned into inbound events, and the four ways the conductor talks back. It implements conductor.Source and knows nothing about sessions, tasks or briefs.
Index ¶
- Constants
- func ParseRef(ref string) (channel, thread, trigger string, err error)
- func Ref(channel, thread, trigger string) string
- func Split(text string, limit int) []string
- type ChannelInfo
- type Options
- type ReviewDoor
- type Source
- func (s *Source) Attach(ctx context.Context, ref string, file conductor.Attachment) error
- func (s *Source) Edit(ctx context.Context, ref, msgID string, out conductor.Outbound) error
- func (s *Source) Events() <-chan conductor.InboundEvent
- func (s *Source) FetchTranscript(ctx context.Context, ref string) ([]conductor.BriefEntry, error)
- func (s *Source) Kind() string
- func (s *Source) ListChannels(ctx context.Context) ([]ChannelInfo, error)
- func (s *Source) MirrorKey(ref string) (string, bool)
- func (s *Source) Post(ctx context.Context, ref string, out conductor.Outbound) (string, error)
- func (s *Source) React(ctx context.Context, ref string, kind conductor.Reaction) error
- func (s *Source) Run(ctx context.Context) error
- func (s *Source) SetReview(r ReviewDoor)
Constants ¶
const Kind = "slack"
Kind is the source kind Slack sessions are recorded under.
const MaxMessageChars = 4000
MaxMessageChars is Slack's own per-message limit. Longer text is split at the last newline before the limit and posted as consecutive messages.
Variables ¶
This section is empty.
Functions ¶
func Ref ¶
Ref is what the conductor carries around for one turn: the channel, the thread it posts into, and the message it reacts on. Three parts rather than two because a reaction goes on the triggering message and a reply goes into the thread, and both have to survive a restart (the ref is persisted as turns.trigger_ref).
Types ¶
type ChannelInfo ¶ added in v0.2.0
ChannelInfo is one Slack channel as ListChannels reports it.
type Options ¶
type Options struct {
// AppToken is the xapp-… app-level token with connections:write. SENSITIVE.
AppToken string
// BotToken is the xoxb-… bot token. SENSITIVE.
BotToken string
Logger *slog.Logger
// contains filtered or unexported fields
}
Options configures the source.
type ReviewDoor ¶ added in v0.2.0
type ReviewDoor interface {
LookupSlack(ctx context.Context, slackRef string) (sourceKey string, ok bool, err error)
BindSlack(ctx context.Context, slackRef, sourceKey string) error
IngestSlack(ctx context.Context, m ghreview.SlackMention) error
}
ReviewDoor is the GitHub source as Slack is allowed to see it: bind a thread to a PR review, and ingest a mention as if it had been an @ on that PR.
type Source ¶
type Source struct {
// contains filtered or unexported fields
}
Source is the Slack integration.
func (*Source) Attach ¶
Attach uploads one file into the thread.
The modern upload flow declares the length before the bytes move, so FileSize and Filename are both required and a zero source uploads nothing at all — silently. Both are checked here rather than trusted to the library.
func (*Source) Edit ¶
Edit replaces a message this source posted. Only the first part of a split message is ever edited, which is what a progress line is.
func (*Source) Events ¶
func (s *Source) Events() <-chan conductor.InboundEvent
Events implements conductor.Source. The channel closes when Run returns.
func (*Source) FetchTranscript ¶
FetchTranscript reads the thread, oldest first. The bot's own placeholder and progress messages are left out — they are noise, not conversation — and its finals are kept.
func (*Source) ListChannels ¶ added in v0.2.0
func (s *Source) ListChannels(ctx context.Context) ([]ChannelInfo, error)
ListChannels pages the conversations the bot is in. It is how the Channels screen seeds the catalogue before the first mention. Archived channels are left out.
func (*Source) MirrorKey ¶
MirrorKey is the session key a ref belongs to, so the conductor can keep a readable copy of this thread in the Podium UI. It is the same key emit builds, out of the same two parts of the ref — the channel and the thread, never the triggering message, because the copy is of the conversation and not of one turn of it.
func (*Source) Post ¶
Post says something new. Text over Slack's per-message limit is split at the last newline that fits and posted as consecutive messages; the id returned is the first one's, because that is the message progress edits address.
func (*Source) React ¶
React shows a turn's state on the message that started it, so a thread shows one state rather than a history of them. "Already reacted" and "no reaction" are both fine outcomes and not errors.
Only the running mark is ever removed, and only by the outcome that replaces it. A turn's reactions go on the message that TRIGGERED it — a message a human has just sent, which is a different message every turn — so nothing of this bot's can already be on it, and the state machine is only ever working → done | failed. Removing the two emoji it was not setting on every call meant three requests a turn that Slack answered "no_reaction" to, two of them ahead of the working mark, where somebody is waiting to see that they were heard.
func (*Source) Run ¶
Run learns the bot's own identity and then holds the Socket Mode connection until ctx is cancelled. Reconnects are the library's; this only logs and counts them.
func (*Source) SetReview ¶ added in v0.2.0
func (s *Source) SetReview(r ReviewDoor)
SetReview attaches the GitHub App source. Called from agent.New before Run; nil is "GitHub is not configured" and leaves mention handling unchanged.