Skip to content

feat: Slack bot for AI agent interaction#1785

Merged
yottahmd merged 10 commits intomainfrom
slack-bot
Mar 16, 2026
Merged

feat: Slack bot for AI agent interaction#1785
yottahmd merged 10 commits intomainfrom
slack-bot

Conversation

@yottahmd
Copy link
Copy Markdown
Collaborator

@yottahmd yottahmd commented Mar 16, 2026

Summary

  • Add Slack bot integration using Socket Mode (WebSocket-based, no HTTP endpoint)
  • Mirrors Telegram bot pattern: message forwarding, interactive prompts via Block Kit buttons, session management, DAG run completion notifications
  • Supports @mentions in channels, thread replies without mention, DMs, and configurable respond_to_all mode
  • Posts "Thinking..." indicator while agent processes, deleted on first response
  • Each conversation (thread/DM) gets an independent agent session
  • Fix duplicate notifications and stale session bugs in both Slack and Telegram bots

Configuration

bots:
  provider: slack
  slack:
    bot_token: "xoxb-..."
    app_token: "xapp-..."
    allowed_channel_ids:
      - "C12345678"
    respond_to_all: true  # default: true

Slack App Requirements

  • Socket Mode enabled with connections:write app-level token
  • Bot scopes: app_mentions:read, chat:write, channels:history, groups:history, im:history
  • Event subscriptions: app_mention, message.channels (public), message.groups (private), message.im (DMs)

Test plan

  • Verify @mention in public channel starts a thread and bot responds
  • Verify thread replies work without @mention
  • Verify DMs work without @mention
  • Verify respond_to_all: true responds to all channel messages
  • Verify respond_to_all: false requires @mention
  • Verify private channels work with message.groups subscription
  • Verify "Thinking..." message appears and is deleted on response
  • Verify DAG run completion notifications are sent to allowed channels
  • Verify Telegram bot still works (no regressions from shared fixes)

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Slack bot integration supporting real-time messaging, interactive prompts, and slash commands
    • Added DAG run monitoring with AI-assisted notifications to Slack channels
    • Added Slack configuration support for bot tokens, channel allowlists, and response settings
  • Bug Fixes

    • Improved Telegram bot session management to prevent stale session reuse
    • Fixed Telegram bot notification subscription behavior to prevent duplicate messages

Add Slack bot integration following the same pattern as the Telegram bot.
Uses Slack Socket Mode (WebSocket-based, no HTTP endpoint) with support
for message forwarding, interactive prompts via Block Kit buttons,
session management, and DAG run completion notifications.
…indicator

- Clear sessionID when subscription loop ends so follow-up messages
  create a fresh session instead of hitting "session not found"
- Remove startSubscription from monitor's notifyChat/notifyChannel to
  prevent duplicate notification messages from the snapshot
- Add hourglass reaction to user messages while the agent is processing,
  removed on first response (Slack bot)

Fixes applied to both Slack and Telegram bots.
Wire Slack bot config into loader env bindings, add provider
switch in server/startall commands, and apply session-end cleanup
from Telegram bot to Slack subscribe loop. Update notification
monitor to skip subscription on already-completed sessions.
Post a "Thinking..." message and hourglass reaction when processing,
both removed when the first response arrives.
Include conversation key in user identity so DM and channel threads
get independent agent sessions instead of conflicting with each other.
- Document message.groups event and groups:history scope for private channels
- Add troubleshooting note for missing event subscriptions
- Change diagnostic logging to DEBUG level
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 16, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: df43b9a5-db86-41c3-b8e9-e18ec0f3302d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This pull request adds comprehensive Slack bot support alongside existing Telegram integration. It includes Slack dependencies, provider-driven bot selection during startup, Slack configuration structures with environment loading, a complete Slack bot service with Socket Mode support and session management, and DAG run monitoring with AI-assisted notifications. Minor Telegram bot cleanup is also included.

Changes

Cohort / File(s) Summary
Dependencies
go.mod
Added slack-go/slack v0.19.0 and gorilla/websocket v1.5.4 indirect dependencies for Slack integration.
Configuration
internal/cmn/config/config.go, definition.go, loader.go
Introduced BotProviderSlack constant, SlackBotConfig and SlackBotDef structs with fields for bot tokens, app tokens, allowed channels, and respond-to-all flag. Added environment variable binding for Slack configuration keys.
Bot Startup Integration
internal/cmd/server.go, startall.go
Refactored bot initialization from Telegram-only to provider-driven switch; added Slack bot instantiation and error handling alongside Telegram path; wired Slack bot lifecycle into server startup.
Slack Service Implementation
internal/service/slack/bot.go
Implemented complete Slack bot with Socket Mode support, conversation/session management across DMs and channels, interactive prompts, thread handling, command processing, message splitting, and contextual session rotation with token usage awareness.
Slack DAG Monitoring
internal/service/slack/monitor.go
Introduced DAG run monitoring loop with completion detection, AI-assisted notification generation, per-channel session creation, fallback messaging, and deduplication via seen state tracking.
Telegram Maintenance
internal/service/telegram/bot.go, monitor.go
Added session cleanup on termination to prevent stale session reuse; removed post-notification subscription to avoid duplicate messages.

Sequence Diagrams

sequenceDiagram
    participant User as Slack User
    participant SlackAPI as Slack API
    participant Bot as Slack Bot
    participant AgentAPI as Agent API
    participant Session as Session Store

    User->>SlackAPI: Send message / reaction
    SlackAPI->>Bot: Socket Mode event
    Bot->>Bot: Route event (message, interactive, slash cmd)
    Bot->>AgentAPI: CreateSession or SendMessage
    AgentAPI->>Session: Create/update session
    AgentAPI-->>Bot: Session ID / response
    Bot->>Bot: Process agent response
    Bot->>SlackAPI: Post message to channel/thread/DM
    SlackAPI-->>User: Display message
    Bot->>AgentAPI: SubscribeSession
    loop Poll for updates
        Bot->>Session: Check for new messages
        Session-->>Bot: Assistant message
        Bot->>SlackAPI: Update Slack message
    end
Loading
sequenceDiagram
    participant Monitor as DAG Monitor
    participant DAGStore as DAG Run Store
    participant AgentAPI as Agent API
    participant Bot as Slack Bot
    participant SlackAPI as Slack API

    Monitor->>DAGStore: Poll for recent runs
    DAGStore-->>Monitor: List of DAG runs
    Monitor->>Monitor: Filter completed, unseen runs
    Monitor->>AgentAPI: CreateSession (notification)
    AgentAPI-->>Monitor: Session ID
    Monitor->>AgentAPI: SendMessage (notification prompt)
    AgentAPI->>AgentAPI: Generate AI response
    Monitor->>AgentAPI: GetSessionDetail / SubscribeSession
    AgentAPI-->>Monitor: AI-generated notification text
    Monitor->>Bot: Post to allowed channels
    Bot->>SlackAPI: Send message
    SlackAPI-->>Monitor: Confirmation
    Monitor->>Monitor: Mark run as seen
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly Related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding Slack bot support for AI agent interaction, which is the core objective of this PR.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch slack-bot
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
internal/cmn/config/loader.go (1)

1102-1147: ⚠️ Potential issue | 🟠 Major

Slack env/default handling is unreachable when def.Bots == nil

Because of the early return on Line 1102, the Slack default + env override logic on Line 1123-Line 1147 is skipped for env-only setups. This causes Slack bot config to stay empty even when DAGU_BOTS_SLACK_* env vars are set.

💡 Proposed fix
 func (l *ConfigLoader) loadBotsConfig(cfg *Config, def Definition) {
 	// Default safe mode to true
 	cfg.Bots.SafeMode = true
+	// Default Slack respond_to_all to true
+	cfg.Bots.Slack.RespondToAll = true

 	// Check env var override for provider
 	if provider := l.v.GetString("bots.provider"); provider != "" {
 		cfg.Bots.Provider = BotProvider(provider)
 	}
@@
 	if token := l.v.GetString("bots.telegram.token"); token != "" {
 		cfg.Bots.Telegram.Token = token
 	}
+	// Slack env overrides should work even without bots section in YAML
+	if botToken := l.v.GetString("bots.slack.bot_token"); botToken != "" {
+		cfg.Bots.Slack.BotToken = botToken
+	}
+	if appToken := l.v.GetString("bots.slack.app_token"); appToken != "" {
+		cfg.Bots.Slack.AppToken = appToken
+	}
+	if channels := parseStringList(l.v.Get("bots.slack.allowed_channel_ids")); len(channels) > 0 {
+		cfg.Bots.Slack.AllowedChannelIDs = channels
+	}
+	if l.v.IsSet("bots.slack.respond_to_all") {
+		cfg.Bots.Slack.RespondToAll = l.v.GetBool("bots.slack.respond_to_all")
+	}

 	if def.Bots == nil {
 		return
 	}
@@
-	// Default Slack respond_to_all to true
-	cfg.Bots.Slack.RespondToAll = true
-
-	// Check env var override for Slack tokens
-	if botToken := l.v.GetString("bots.slack.bot_token"); botToken != "" {
-		cfg.Bots.Slack.BotToken = botToken
-	}
-	if appToken := l.v.GetString("bots.slack.app_token"); appToken != "" {
-		cfg.Bots.Slack.AppToken = appToken
-	}
-
 	if def.Bots.Slack != nil {
 		if cfg.Bots.Slack.BotToken == "" {
 			cfg.Bots.Slack.BotToken = def.Bots.Slack.BotToken
 		}
 		if cfg.Bots.Slack.AppToken == "" {
 			cfg.Bots.Slack.AppToken = def.Bots.Slack.AppToken
 		}
-		if len(def.Bots.Slack.AllowedChannelIDs) > 0 {
+		if len(cfg.Bots.Slack.AllowedChannelIDs) == 0 && len(def.Bots.Slack.AllowedChannelIDs) > 0 {
 			cfg.Bots.Slack.AllowedChannelIDs = def.Bots.Slack.AllowedChannelIDs
 		}
 		if def.Bots.Slack.RespondToAll != nil {
 			cfg.Bots.Slack.RespondToAll = *def.Bots.Slack.RespondToAll
 		}
 	}
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cmn/config/loader.go` around lines 1102 - 1147, The early return
when def.Bots == nil prevents applying Slack defaults and environment overrides;
stop returning early and instead only skip copying defaults from def.Bots while
still executing the Slack env/default logic: remove or replace the "if def.Bots
== nil { return }" with per-section nil checks (e.g., check def.Bots.Telegram,
def.Bots.Slack individually) and ensure cfg.Bots.Slack.RespondToAll = true plus
the l.v.GetString("bots.slack.bot_token") / "bots.slack.app_token" overrides and
subsequent conditional copies from def.Bots.Slack still run even when def.Bots
is nil.
internal/service/telegram/monitor.go (1)

229-243: ⚠️ Potential issue | 🟠 Major

Notification session is still persisted, so “fresh session on follow-up” won’t happen

notifyChat still stores sessionID on Line 234/Line 235, but the subscription that used to terminate/cleanup that session is no longer started. That leaves a completed notification session as active chat state and can reintroduce stale-session behavior.

💡 Proposed fix
-	// Adopt this session as the chat's active session so the user can
-	// send follow-up messages (e.g., "show me the logs", "retry it").
+	// Notification sessions are one-shot; do not adopt as active chat session.
 	cs := m.bot.getOrCreateChat(chatID)
 	m.bot.resetChat(cs)
-	cs.mu.Lock()
-	cs.sessionID = sessionID
-	cs.ownerUserID = user.UserID
-	cs.mu.Unlock()

 	m.bot.sendLongText(chatID, response)

-	// Don't start a subscription here — the notification session is already
-	// done, and subscribing would re-send the same response from the snapshot.
-	// If the user sends a follow-up, handleMessage will create a fresh session.
+	// Don't start a subscription here — this notification is complete.
+	// A follow-up message will create a fresh session.
 	return true
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/service/telegram/monitor.go` around lines 229 - 243, notifyChat is
persisting a completed notification session by setting cs.sessionID and
cs.ownerUserID even though no subscription will later clear it; update
notifyChat (around m.bot.getOrCreateChat / m.bot.resetChat / m.bot.sendLongText)
to avoid persisting the notification session: either do not assign cs.sessionID
and cs.ownerUserID for notification-only flows, or explicitly clear them (under
cs.mu) immediately after sending the long text so the chat has no active
session; keep the mutex usage (cs.mu.Lock/Unlock) when modifying cs.sessionID
and cs.ownerUserID.
🧹 Nitpick comments (4)
internal/cmn/config/config.go (1)

37-63: Consider validating bots.provider in Config.Validate()

Now that Slack is a first-class provider, an unknown provider value can silently no-op at runtime. Adding explicit validation for none|telegram|slack would fail fast on typoed config.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cmn/config/config.go` around lines 37 - 63, Add explicit validation
in Config.Validate() to ensure BotsConfig.Provider is one of the allowed
constants (BotProviderNone, BotProviderTelegram, BotProviderSlack); if not,
return an error stating the unsupported provider value. Locate the BotsConfig
struct and BotProvider constants (BotProviderNone, BotProviderTelegram,
BotProviderSlack) and add a guard in Config.Validate() that checks
cfg.Bots.Provider and fails fast on any value outside those three options
(include the invalid value in the error message for easier debugging).
internal/service/slack/monitor.go (1)

119-122: Consider using Warn level for status listing failures.

Using Debug level for the ListStatuses error may hide operational issues in production. This is an I/O operation that could fail due to database connectivity issues.

Proposed fix
 	if err != nil {
-		m.logger.Debug("Failed to list DAG run statuses", slog.String("error", err.Error()))
+		m.logger.Warn("Failed to list DAG run statuses", slog.String("error", err.Error()))
 		return
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/service/slack/monitor.go` around lines 119 - 122, Change the log
level for failures when listing DAG run statuses from Debug to Warn so
operational I/O failures are visible in production; locate the logger call that
reads m.logger.Debug("Failed to list DAG run statuses", slog.String("error",
err.Error())) (in monitor.go where ListStatuses is handled) and replace it with
m.logger.Warn (preserving the same message and error field) so the warning shows
up at the warn level without altering the error handling flow.
internal/service/slack/bot.go (2)

354-390: Consider extracting shared logic with handleTextCommand.

The slash command handlers duplicate the "new" and "cancel" logic from handleTextCommand. This is a minor maintainability concern.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/service/slack/bot.go` around lines 354 - 390, handleSlashCommand
duplicates the "/dagu-new" and "/dagu-cancel" logic found in handleTextCommand;
refactor by extracting the shared actions into helper methods (e.g.,
performNewSession and performCancelSession) that accept a chatState (cs) and
context/command metadata, then have both handleSlashCommand and
handleTextCommand call those helpers; use existing symbols like getOrCreateChat,
resetChat, sendReply, and agentAPI.CancelSession to implement the helpers so
cancel uses cs.sessionID and cs.ownerUserID and new calls resetChat and sends
the same reply messages.

137-142: Socket client errors are logged but don't stop the bot.

If RunContext returns an error (e.g., WebSocket connection failure), the error is logged but the main event loop continues running on a closed channel. Consider propagating fatal errors or implementing reconnection logic.

Consider signaling fatal errors to the main loop
+	errCh := make(chan error, 1)
 	go func() {
 		if err := b.socketClient.RunContext(ctx); err != nil {
 			b.logger.Error("Socket mode client error", slog.String("error", err.Error()))
+			errCh <- err
 		}
 	}()
 
 	for {
 		select {
 		case <-ctx.Done():
 			b.logger.Info("Slack bot stopped")
 			return nil
 
+		case err := <-errCh:
+			return fmt.Errorf("socket mode client failed: %w", err)
+
 		case evt, ok := <-b.socketClient.Events:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/service/slack/bot.go` around lines 137 - 142, The goroutine calling
b.socketClient.RunContext currently only logs errors via b.logger.Error, which
allows the main event loop to continue on a closed socket; modify the goroutine
to propagate fatal errors to the main routine by sending the error on a
dedicated error channel or invoking the shared cancellation (e.g., cancel the
context passed as ctx) so the main loop can shutdown or attempt reconnection;
specifically update the anonymous goroutine that calls
b.socketClient.RunContext(ctx) to forward returned errors to a new or existing
error handling path (instead of only calling b.logger.Error) and update the main
event loop to listen for that signal and either perform reconnection logic or
exit gracefully.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/service/slack/bot.go`:
- Around line 290-294: The code assumes strings.Fields(text) has at least one
element and will panic on whitespace-only input; before accessing [0], ensure
the fields slice is non-empty (e.g., call strings.Fields(text) into a variable,
check len(fields) > 0 or use strings.TrimSpace(text) to early-return), then
extract cmd and only call b.handleTextCommand(ctx, cs, cmd) when a command
exists; update the block around the text handling (referencing the variables
text, cmd and the method b.handleTextCommand) to perform this guard and avoid an
index out of range panic.

In `@internal/service/slack/monitor.go`:
- Around line 177-184: The current loop over m.bot.allowedChannels uses
allDelivered to decide whether to mark the run as seen, which causes retries to
re-notify channels that already succeeded; change the behavior to record
seen/delivery per-channel instead of a single allDelivered flag by updating the
run's seen state (or calling the existing markSeen-like function) each time
m.notifyChannel(ctx, channelID, s, prompt) returns true, or alternatively treat
any success as partial acceptance and do not retry channels that returned true
on subsequent polls; modify the code paths around m.notifyChannel,
m.bot.allowedChannels iteration, and where the run is marked seen so delivery
state is maintained per channel (e.g., store a map keyed by channelID or persist
per-channel markers) to prevent duplicate notifications on retry.
- Around line 214-219: resetChat is called without holding cs.mu, then cs.mu is
locked to set cs.sessionID and cs.ownerUserID, which allows another goroutine to
interleave and cause a race; fix by performing the reset and session assignment
atomically: either modify resetChat (or add a new method like
resetAndSetSession) to accept sessionID and ownerUserID and perform both the
reset and the assignments while holding cs.mu, or acquire cs.mu before calling
resetChat and ensure resetChat does not re-lock internally; update calls to use
the new API so cs.sessionID and cs.ownerUserID are set under the same lock as
the reset to eliminate the race.

---

Outside diff comments:
In `@internal/cmn/config/loader.go`:
- Around line 1102-1147: The early return when def.Bots == nil prevents applying
Slack defaults and environment overrides; stop returning early and instead only
skip copying defaults from def.Bots while still executing the Slack env/default
logic: remove or replace the "if def.Bots == nil { return }" with per-section
nil checks (e.g., check def.Bots.Telegram, def.Bots.Slack individually) and
ensure cfg.Bots.Slack.RespondToAll = true plus the
l.v.GetString("bots.slack.bot_token") / "bots.slack.app_token" overrides and
subsequent conditional copies from def.Bots.Slack still run even when def.Bots
is nil.

In `@internal/service/telegram/monitor.go`:
- Around line 229-243: notifyChat is persisting a completed notification session
by setting cs.sessionID and cs.ownerUserID even though no subscription will
later clear it; update notifyChat (around m.bot.getOrCreateChat /
m.bot.resetChat / m.bot.sendLongText) to avoid persisting the notification
session: either do not assign cs.sessionID and cs.ownerUserID for
notification-only flows, or explicitly clear them (under cs.mu) immediately
after sending the long text so the chat has no active session; keep the mutex
usage (cs.mu.Lock/Unlock) when modifying cs.sessionID and cs.ownerUserID.

---

Nitpick comments:
In `@internal/cmn/config/config.go`:
- Around line 37-63: Add explicit validation in Config.Validate() to ensure
BotsConfig.Provider is one of the allowed constants (BotProviderNone,
BotProviderTelegram, BotProviderSlack); if not, return an error stating the
unsupported provider value. Locate the BotsConfig struct and BotProvider
constants (BotProviderNone, BotProviderTelegram, BotProviderSlack) and add a
guard in Config.Validate() that checks cfg.Bots.Provider and fails fast on any
value outside those three options (include the invalid value in the error
message for easier debugging).

In `@internal/service/slack/bot.go`:
- Around line 354-390: handleSlashCommand duplicates the "/dagu-new" and
"/dagu-cancel" logic found in handleTextCommand; refactor by extracting the
shared actions into helper methods (e.g., performNewSession and
performCancelSession) that accept a chatState (cs) and context/command metadata,
then have both handleSlashCommand and handleTextCommand call those helpers; use
existing symbols like getOrCreateChat, resetChat, sendReply, and
agentAPI.CancelSession to implement the helpers so cancel uses cs.sessionID and
cs.ownerUserID and new calls resetChat and sends the same reply messages.
- Around line 137-142: The goroutine calling b.socketClient.RunContext currently
only logs errors via b.logger.Error, which allows the main event loop to
continue on a closed socket; modify the goroutine to propagate fatal errors to
the main routine by sending the error on a dedicated error channel or invoking
the shared cancellation (e.g., cancel the context passed as ctx) so the main
loop can shutdown or attempt reconnection; specifically update the anonymous
goroutine that calls b.socketClient.RunContext(ctx) to forward returned errors
to a new or existing error handling path (instead of only calling
b.logger.Error) and update the main event loop to listen for that signal and
either perform reconnection logic or exit gracefully.

In `@internal/service/slack/monitor.go`:
- Around line 119-122: Change the log level for failures when listing DAG run
statuses from Debug to Warn so operational I/O failures are visible in
production; locate the logger call that reads m.logger.Debug("Failed to list DAG
run statuses", slog.String("error", err.Error())) (in monitor.go where
ListStatuses is handled) and replace it with m.logger.Warn (preserving the same
message and error field) so the warning shows up at the warn level without
altering the error handling flow.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3703dece-1629-4bf4-898e-04ff52aa6e17

📥 Commits

Reviewing files that changed from the base of the PR and between 443f13b and f30d7bd.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (10)
  • go.mod
  • internal/cmd/server.go
  • internal/cmd/startall.go
  • internal/cmn/config/config.go
  • internal/cmn/config/definition.go
  • internal/cmn/config/loader.go
  • internal/service/slack/bot.go
  • internal/service/slack/monitor.go
  • internal/service/telegram/bot.go
  • internal/service/telegram/monitor.go

Comment thread internal/service/slack/bot.go
Comment thread internal/service/slack/monitor.go Outdated
Comment thread internal/service/slack/monitor.go
- Guard strings.Fields(text)[0] against whitespace-only panic
- Accept partial delivery in monitor to avoid duplicate notifications
- Make resetChat + session assignment atomic to prevent race condition

Applied to both Slack and Telegram bots.
@yottahmd yottahmd merged commit 7e655ab into main Mar 16, 2026
5 checks passed
@yottahmd yottahmd deleted the slack-bot branch March 16, 2026 13:46
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 16, 2026

Codecov Report

❌ Patch coverage is 0.12165% with 821 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.69%. Comparing base (443f13b) to head (21db706).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
internal/service/slack/bot.go 0.00% 520 Missing ⚠️
internal/service/slack/monitor.go 0.00% 192 Missing ⚠️
internal/cmd/startall.go 2.27% 40 Missing and 3 partials ⚠️
internal/cmd/server.go 0.00% 40 Missing and 1 partial ⚠️
internal/cmn/config/loader.go 0.00% 14 Missing ⚠️
internal/service/telegram/monitor.go 0.00% 7 Missing ⚠️
internal/service/telegram/bot.go 0.00% 4 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1785      +/-   ##
==========================================
- Coverage   68.82%   67.69%   -1.13%     
==========================================
  Files         416      418       +2     
  Lines       48602    49385     +783     
==========================================
- Hits        33448    33429      -19     
- Misses      12359    13158     +799     
- Partials     2795     2798       +3     
Files with missing lines Coverage Δ
internal/cmn/config/config.go 72.68% <ø> (ø)
internal/service/telegram/bot.go 0.00% <0.00%> (ø)
internal/service/telegram/monitor.go 0.00% <0.00%> (ø)
internal/cmn/config/loader.go 81.25% <0.00%> (-1.32%) ⬇️
internal/cmd/server.go 25.30% <0.00%> (-4.19%) ⬇️
internal/cmd/startall.go 49.18% <2.27%> (-8.51%) ⬇️
internal/service/slack/monitor.go 0.00% <0.00%> (ø)
internal/service/slack/bot.go 0.00% <0.00%> (ø)

... and 10 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 443f13b...21db706. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant