slack-channel-monitor: poll thread messages and reuse thread conversations#289
Open
rbren wants to merge 2 commits into
Open
slack-channel-monitor: poll thread messages and reuse thread conversations#289rbren wants to merge 2 commits into
rbren wants to merge 2 commits into
Conversation
The poller previously fetched conversations.replies only for threads that already had an active OpenHands conversation, so a trigger phrase posted as a reply inside an untracked thread was never seen. Changes: - Discover thread parents from each channel's history (any message with reply_count > 0) and persist them in a new state.known_threads map so their replies remain pollable after the parent ages out of the history window. - Poll conversations.replies for every tracked-conversation thread plus every entry in known_threads (capped at 50 per channel to stay under Slack Tier 3 limits). - Unify the main message loop: if a thread already has an open conversation, forward every in-thread message to it (trigger phrases and plain replies alike) instead of creating a duplicate conversation. - Use thread-scoped context (parent + earlier replies) when a trigger arrives inside a thread; keep channel-wide context for top-level triggers. - Update SKILL.md, README.md, slack-api.md, and state-schema.md to reflect the new behaviour and state field. Co-authored-by: openhands <openhands@all-hands.dev>
The previous template wrote the context block as:
Recent channel context (oldest -> newest):
---
[U1]: ...
[U2]: ...
---
CommonMark interprets a line of text followed by '---' on the next line
as a setext H2 heading, so both the context label *and* the context
block itself were being rendered as huge headings in the conversation
UI.
Switch to a 4-backtick fenced code block instead. This:
* eliminates the setext-heading collision entirely,
* makes the rendered output a clearly demarcated monospace block
signalling 'this is data, not prose', and
* prevents markdown-looking characters in user-supplied Slack text
(# foo, * bar, _baz_, triple-backticks) from rendering as markdown
when the conversation is displayed.
Verified with markdown_it (CommonMark): the rendered HTML now contains
zero headings; the context label is a paragraph; the context block is
a <pre><code> with all special characters preserved verbatim.
Co-authored-by: openhands <openhands@all-hands.dev>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The Slack channel monitor previously only saw top-level channel messages. Triggers posted as replies inside threads were invisible unless the thread already had an active OpenHands conversation. This PR extends the poller to look at messages inside threads too, and ensures that when a thread already has an open conversation we reuse it instead of spawning a duplicate.
Behavior changes (
scripts/main.py)conversations.historywithreply_count > 0is registered as a known thread; replies for each known thread are fetched on every run viaconversations.replies.state["known_threads"]map ({channel_id: {thread_ts: latest_reply_ts}}) keeps threads pollable even after the parent message ages out of the channel history window. Capped atMAX_KNOWN_THREADS_PER_CHANNEL = 50(oldest bylatest_reply_tspruned first) so the worst-caseconversations.repliescall count stays well under Slack Tier 3 limits. Entries for unmonitored channels are dropped.Docs updated
SKILL.mdRuntime Behaviour: thread polling,known_threads, conversation-reuse rule.README.mdFeatures / How-It-Works: thread-aware polling + per-thread conversation reuse.references/state-schema.md: documentsknown_threadswith schema, pruning rules, and example.references/slack-api.md: updatedconversations.repliesrate-limit row.Verification
python3 -m py_compile skills/slack-channel-monitor/scripts/main.pypasses.python3 scripts/sync_extensions.py --checkis clean (only the pre-existing unrelated coverage warning forplugins/issue-duplicate-checker)._prune_known_threadsenforces the per-channel cap and drops unmonitored channels._poll_new_messagesdiscovers new thread parents from history, polls both newly-discovered and pre-existing known threads, updatesknown_threadswith the most recent reply ts, and returns top-level + reply messages sorted chronologically.This PR was opened by an AI agent (OpenHands) on behalf of @rbren.