[FE Feat] Tools catalog category sections#5062
Conversation
Add a "Browse by category" rail to the tool catalog: connections pinned at the
top, an independently-scrolling category list below, and a single-select filter
(all / category / connection) driving the grid. Full-bleed recessed rail, and
per-context loading / empty / error states.
Backend: the shared gateway catalog gains a category filter on list_integrations
(passed to Composio /toolkits?category=) plus a new list_categories that derives
a focused, results-guaranteed nav from the most-used toolkits' own tags —
Composio's /toolkits/categories returns ~800 raw tags, most matching nothing.
New /catalog/providers/{provider}/categories/ route.
Frontend: category atom + categories hook (atomWithQuery), category pass-through
on the Fern integrations call, dedupe of integrations/categories to keep React
keys unique across pagination, and search that flattens across categories.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThis PR adds tool-catalog category listing and category-based filtering across the backend API, gateway/service layers, frontend data access, and the shared catalog chooser UI. ChangesTool catalog categories
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant CatalogChooser
participant useToolCatalogIntegrations
participant fetchToolIntegrations
participant ToolsRouter
participant ToolsService
participant CatalogService
participant ComposioCatalogAdapter
User->>CatalogChooser: select category
CatalogChooser->>useToolCatalogIntegrations: setCategory(id)
useToolCatalogIntegrations->>fetchToolIntegrations: request(category)
fetchToolIntegrations->>ToolsRouter: GET /catalog/providers/{key}/integrations?category=
ToolsRouter->>ToolsService: list_integrations(category)
ToolsService->>CatalogService: list_integrations(category)
CatalogService->>ComposioCatalogAdapter: list_integrations(category)
ComposioCatalogAdapter-->>CatalogService: filtered integrations
CatalogService-->>ToolsService: filtered integrations
ToolsService-->>ToolsRouter: filtered integrations
ToolsRouter-->>fetchToolIntegrations: response
fetchToolIntegrations-->>useToolCatalogIntegrations: page data
useToolCatalogIntegrations-->>CatalogChooser: deduplicated integrations
CatalogChooser-->>User: render filtered grid
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
web/packages/agenta-entities/src/gatewayTool/hooks/useToolCatalogIntegrations.ts (1)
60-74: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winAdd regression tests for the duplicate-key dedup logic.
This dedup-by-
keylogic (and its sibling dedup-by-idinuseToolCatalogCategories.ts) exists specifically to prevent a documented React duplicate-key render crash. Neither has test coverage, so a future refactor to pagination or the category filter could silently reintroduce the crash.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: abe13313-5c7c-4810-b07f-07ca7ebaa7c8
📒 Files selected for processing (18)
api/oss/src/apis/fastapi/tools/models.pyapi/oss/src/apis/fastapi/tools/router.pyapi/oss/src/core/gateway/catalog/dtos.pyapi/oss/src/core/gateway/catalog/interfaces.pyapi/oss/src/core/gateway/catalog/providers/composio/adapter.pyapi/oss/src/core/gateway/catalog/service.pyapi/oss/src/core/tools/dtos.pyapi/oss/src/core/tools/service.pyweb/packages/agenta-entities/src/gatewayTool/api/api.tsweb/packages/agenta-entities/src/gatewayTool/api/index.tsweb/packages/agenta-entities/src/gatewayTool/core/index.tsweb/packages/agenta-entities/src/gatewayTool/core/types.tsweb/packages/agenta-entities/src/gatewayTool/hooks/index.tsweb/packages/agenta-entities/src/gatewayTool/hooks/useToolCatalogCategories.tsweb/packages/agenta-entities/src/gatewayTool/hooks/useToolCatalogIntegrations.tsweb/packages/agenta-entities/src/gatewayTool/index.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentTemplate/AgentIntegrationDrawer.tsxweb/packages/agenta-entity-ui/src/drawers/shared/CatalogChooser.tsx
| // Picking any rail filter clears an active search (search and filter are mutually exclusive). | ||
| const clearSearch = () => { | ||
| setSearchInput("") | ||
| setSearch("") | ||
| } | ||
| const pickAll = () => { | ||
| setSelected(null) | ||
| setCategoryState(null) | ||
| setCategory?.(null) | ||
| clearSearch() | ||
| } | ||
| const pickCategory = (cat: {id: string; name: string}) => { | ||
| setSelected(null) | ||
| setCategoryState(cat) | ||
| setCategory?.(cat.id) | ||
| clearSearch() | ||
| } | ||
| const pickConn = (id: string) => { | ||
| setSelected({kind: "conn", id}) | ||
| clearSearch() |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Clear category state when search or connection selection takes over.
After selecting a category, typing in search only updates searchInput, so the upstream category filter remains active while the header says “Results”. pickConn also leaves the prior category active, so returning from a pinned connection can restore a stale category view and can make byKey miss app metadata for connections outside that category.
Suggested fix
+ const clearCategory = () => {
+ setCategoryState(null)
+ setCategory?.(null)
+ }
+
const clearSearch = () => {
setSearchInput("")
setSearch("")
}
const pickAll = () => {
setSelected(null)
- setCategoryState(null)
- setCategory?.(null)
+ clearCategory()
clearSearch()
}
@@
const pickConn = (id: string) => {
setSelected({kind: "conn", id})
+ clearCategory()
clearSearch()
}
@@
- onChange={(e) => setSearchInput(e.target.value)}
+ onChange={(e) => {
+ const next = e.target.value
+ setSearchInput(next)
+ if (next.trim()) clearCategory()
+ }}Also applies to: 881-889
- Validate fetchToolCategories at the boundary via zod (only non-Fern call); derive the category types from the schema so type and validator can't drift. - Clear the category filter when a connection is picked so the browse query isn't left filtered behind the detail view or restored stale on Back. - Resolve connection integration metadata from a monotonic union of loaded integrations so a category/search filter no longer drops name+logo. - Extract the catalog dedup crash-guard into a shared dedupeBy helper used by both catalog hooks and cover it with unit tests.
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
🧹 Nitpick comments (2)
web/packages/agenta-entities/src/gatewayTool/core/types.ts (1)
41-45: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueComment block exceeds one-line guideline.
This 5-line comment exceeds the repo's comment-length convention. Consider trimming to a single concise line, or keep only if the constraint truly needs the extra context.
As per coding guidelines, "Keep in-code comments to one short line maximum unless a genuinely surprising constraint requires a brief exception."
Source: Coding guidelines
web/packages/agenta-entities/tests/unit/gatewayTool-dedupe.test.ts (1)
1-7: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueComment block exceeds one-line guideline.
This 7-line file-header comment exceeds the repo's comment-length convention.
As per coding guidelines, "Keep in-code comments to one short line maximum unless a genuinely surprising constraint requires a brief exception."
Source: Coding guidelines
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 4c6bba2c-59c5-4b4f-84c0-5a95cb6abcaf
📒 Files selected for processing (8)
web/packages/agenta-entities/src/gatewayTool/api/api.tsweb/packages/agenta-entities/src/gatewayTool/core/dedupe.tsweb/packages/agenta-entities/src/gatewayTool/core/index.tsweb/packages/agenta-entities/src/gatewayTool/core/types.tsweb/packages/agenta-entities/src/gatewayTool/hooks/useToolCatalogCategories.tsweb/packages/agenta-entities/src/gatewayTool/hooks/useToolCatalogIntegrations.tsweb/packages/agenta-entities/tests/unit/gatewayTool-dedupe.test.tsweb/packages/agenta-entity-ui/src/drawers/shared/CatalogChooser.tsx
✅ Files skipped from review due to trivial changes (2)
- web/packages/agenta-entities/src/gatewayTool/core/dedupe.ts
- web/packages/agenta-entities/src/gatewayTool/core/index.ts
🚧 Files skipped from review as they are similar to previous changes (4)
- web/packages/agenta-entities/src/gatewayTool/hooks/useToolCatalogCategories.ts
- web/packages/agenta-entities/src/gatewayTool/hooks/useToolCatalogIntegrations.ts
- web/packages/agenta-entities/src/gatewayTool/api/api.ts
- web/packages/agenta-entity-ui/src/drawers/shared/CatalogChooser.tsx
…hold The header flipped to "Results" and un-highlighted the category at 1 typed char, but the browse query only treats a search as active at >=3 chars, so a 1-2 char query still showed category-filtered results under a "Results" label. Gate the searching state on a searchMinChars prop (default 3, matching the consumer hooks) so the UI reflects when the search actually applies and the category context is preserved until then.
|
@coderabbitai review |
✅ Action performedReview finished.
|
Summary
tba
Testing
tba
QA follow-up
Checklist
Contributor Resources