feat(slack): implement UI for Slack Bot OAuth connect/disconnect and cursor-based log pagination#320
Conversation
- Add cursor + since_id pagination to GET /logs endpoint - Add GET /rag/sources endpoint returning distinct RAG source names - Add llm_model_override field to SlackConfig - Wire model_override into _build_llm_provider for per-request model selection
|
Claude finished @zaira-bibi's task in 2m 39s —— View job Review of PR #320
OverviewThis PR adds a well-structured Slack TA Bot frontend plugin page with OAuth connect/disconnect, cursor-based log pagination, a RAG sources endpoint, and per-request LLM model override support. The code is clean, follows existing project patterns (mirrors the googledrive plugin structure), and the test suite is thorough. Previous Review CommentsNo prior review threads found. Issues by PriorityHigh —
|
Adds the Slack plugin to the frontend: - API client - connection card with OAuth connect/disconnect flow - page shell with status loading - post-OAuth callback handling - a stub config modal Also registers the plugin in the sidebar at order 3 and adds `/dashboard/slack` to static params so the route is pre-rendered in the static export.
dfdd21d to
770e691
Compare
|
Claude finished @zaira-bibi's task in 1m 51s —— View job Re-review of PR #320 (post-sync)
Previous Review CommentsAll issues from the initial review have been addressed in commit
New Issues FoundNone. The second commit cleanly addresses the review feedback without introducing regressions. What Looks Good (unchanged from initial review + improvements)
Overall AssessmentAll blocking and non-blocking issues from the initial review have been addressed. The code is clean, well-tested, and follows project conventions. Ready to merge. |
LLMConfigAdapter.preprocess_config now rejects a model override that is not in the linked LLMConfig's provider allowlist, surfacing typos as a 400 at save time instead of a silent synthesis fallback at runtime. Also raises when llm_model_override is set but llm_config_id is null (provider is unknown). apply_preprocess is moved inside update_user_plugin_config so partial PUTs that change llm_config_id re-validate any stored llm_model_override against the new provider, closing a bypass where a stale override could persist undetected. SlackConfigAdapter registered in PLUGIN_ADAPTERS (previously missing, so Slack config had no preprocess/postprocess hooks at all). Removes the unused PluginConfigAdapter Protocol and its directory; moves PLUGIN_ADAPTERS to app/plugins/adapters.py alongside PLUGIN_CONFIG_CLASSES. Documents LLM-aware plugin config and adapter patterns in PLUGIN_GUIDE.md.
|
Claude finished @zaira-bibi's task in 3m 31s —— View job Re-review of PR #320 (post-sync — commit
|
| # | Issue | Status | Details |
|---|---|---|---|
| 1 | High — since_id pagination silently drops data |
Resolved ✓ | since_id path now uses limit + 1 pattern with correct has_more and next_cursor. Test test_since_id_has_more_when_results_exceed_limit added. |
| 2 | Medium — Browser alert()/confirm() instead of UI components |
Resolved ✓ | SlackConnectionCard.tsx now propagates errors via onError callback and uses a Radix Dialog for disconnect confirmation. |
| 3 | Low — Unused props in stub modal | Acknowledged ✓ | PR author confirmed stub will be replaced in next PR. |
| 4 | Low — Hardcoded dashboard path | Resolved ✓ | Backend uses SLACK_FRONTEND_PATH constant, frontend uses SLACK_PLUGIN_PATH. |
| 5 | Medium — llm_model_override lets any string through (@hamza-56) |
Resolved ✓ | New commit refactors adapter system and validates override against get_models_for_provider() at write time. |
All 5 review threads resolved.
New Commit Analysis (e43e6b8)
This commit introduces a clean refactoring of the plugin adapter system to validate llm_model_override at config write time:
Architecture changes:
PluginConfigAdapterProtocol (app/services/plugin_adapters/base.py) deleted — replaced byLLMConfigAdapterconcrete base class (app/llm/adapter.py)app/services/plugin_adapters/registry.py→app/plugins/adapters.py— cleaner locationChatPluginConfigAdapter→ChatConfigAdapter,SlackConfigAdapteradded- Preprocessing moved from the API layer (
user_plugins.py) intoPluginService.update_user_plugin_config()so it runs on the merged config, catching cross-field issues when only one field changes
Validation logic (app/llm/adapter.py:53-77):
- If
llm_model_overrideis set butllm_config_idisNone→ raisesValueError(can't determine provider) - If both are set → looks up the LLMConfig, calls
get_models_for_provider(llm.provider), rejects if override isn't in the allowlist LLMConfigValidationErrorextendsValueError, correctly caught by existing exception handlers inuser_plugins.py
Key design decision (good): Preprocessing now runs on the full merged config (plugin.py:292) rather than just the incoming partial dict. This catches the scenario where a user changes llm_config_id to a different provider but the stored llm_model_override is incompatible — tested in test_update_config_revalidates_stored_model_override_against_new_provider.
New Issues Found
None. The refactoring is clean, well-tested, and introduces no regressions.
What Looks Good
- Security: OAuth CSRF via
itsdangerous, all routes requirerequire_user_id, Slack signature verification, parameterized queries, encrypted tokens, model override validated against allowlist at write time. - Error handling: Specific exception types throughout, all
exceptblocks include logging — fully compliant with project guidelines. No bareexcept Exception. - Pagination: Both
since_idandcursorpaths correctly implementlimit + 1truncation withhas_moresignaling. Mutual exclusivity enforced. - Frontend architecture: Clean component decomposition with proper error propagation (
onErrorcallback), RadixDialogfor confirmation,useCallbackwith correct deps, timer cleanup inuseEffect. No React anti-patterns detected. - Adapter refactoring: Removing the
Protocolin favor of a concrete base class is the right call — theProtocolprovided no value since all adapters inherit the same implementation. Moving preprocessing intoPluginServiceis a correctness fix that prevents partial-update validation gaps. - Test coverage: Excellent — the new commit adds 10 test cases across 3 files covering: model override validation (valid, invalid, missing config ID, none override), adapter registration, cross-field revalidation on partial updates, and Slack-specific adapter behavior. Total across the PR: 20+ test functions covering OAuth, events, dispatch, pagination, RAG sources, LLM provider, and adapter validation.
- Documentation:
PLUGIN_GUIDE.mdupdated with comprehensive adapter docs including override examples.
Overall Assessment
All blocking and non-blocking issues from prior reviews have been addressed. The new commit cleanly resolves @hamza-56's feedback with a well-designed adapter refactoring and thorough test coverage. Ready to merge.
What
As part of #246, this PR extends the Slack TA Bot with cursor-based log pagination, a RAG sources endpoint, per-request LLM model override, and a frontend plugin page with OAuth connect/disconnect.
Changes
/api/v1/slack/logscursor + since_id pagination,/rag/sourcesendpoint, andllm_model_overridesupport on the Slack bot configHow to Test
/dashboard/slack?connected=true, success banner appears, and workspace name shows in the card.GET /api/v1/slack/logs?limit=10with a valid token — confirm paginated response withnext_cursorandhas_more.GET /api/v1/slack/rag/sources— confirm list of indexed RAG sources is returned.llm_model_overridein the bot config and trigger a Slack mention — confirm the override model is used for synthesis.Notes
Migration required: yes — run
make migrations(addsllm_model_overridecolumn to the Slack config table).