feat(hex): expand API coverage, fix ID trimming, add cursor pagination#5372
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Run and list behavior gains optional Reliability tweaks: Reviewed by Cursor Bugbot for commit d34d447. Configure here. |
Greptile SummaryThis PR expands the Hex integration with five new tools (
Confidence Score: 5/5All changes are purely additive — no existing fields renamed or removed, no existing behavior altered — making this safe to merge. Every new tool follows the established Hex tool pattern faithfully: URL trimming on path params, try/catch + Array.isArray guards on JSON array inputs, consistent transformResponse conventions, and correct block wiring end-to-end. The previously flagged issues (JSON.parse try/catch, Array.isArray on notifications) have been addressed in commits referenced in the thread. The one edge case noted (empty PATCH body in update_collection/update_group) would produce an API-level error rather than silent data corruption. No files require special attention; update_collection.ts and update_group.ts have a minor edge case around empty bodies but nothing that affects correct use. Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Block as HexBlock (hex.ts)
participant Tool as Tool Layer
participant API as Hex API
Note over Block,API: New tools added in this PR
Block->>Tool: "create_group { name, memberUserIds }"
Tool->>API: "POST /api/v1/groups { name, members: { users } }"
API-->>Tool: "{ id, name, createdAt }"
Tool-->>Block: "{ id, name, createdAt }"
Block->>Tool: "update_group { groupId, name?, addUserIds?, removeUserIds? }"
Tool->>API: "PATCH /api/v1/groups/{groupId.trim()} { name?, members: { add, remove } }"
API-->>Tool: "{ id, name, createdAt }"
Tool-->>Block: "{ id, name, createdAt }"
Block->>Tool: "delete_group { groupId }"
Tool->>API: "DELETE /api/v1/groups/{groupId.trim()}"
API-->>Tool: 204 No Content
Tool-->>Block: "{ success: true, groupId }"
Block->>Tool: "update_collection { collectionId, name?, description? }"
Tool->>API: "PATCH /api/v1/collections/{collectionId.trim()} { name?, description? }"
API-->>Tool: "{ id, name, description, creator }"
Tool-->>Block: "{ id, name, description, creator }"
Block->>Tool: "deactivate_user { userId }"
Tool->>API: "POST /api/v1/users/{userId.trim()}/deactivate"
API-->>Tool: 204 No Content
Tool-->>Block: "{ success: true, userId }"
Note over Block,API: Cursor pagination (list endpoints)
Block->>Tool: "list_projects { after?, before?, ... }"
Tool->>API: "GET /api/v1/projects?after=cursor&..."
API-->>Tool: "{ values: [...], pagination: { after, before } }"
Tool-->>Block: "{ projects, total, after, before }"
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant Block as HexBlock (hex.ts)
participant Tool as Tool Layer
participant API as Hex API
Note over Block,API: New tools added in this PR
Block->>Tool: "create_group { name, memberUserIds }"
Tool->>API: "POST /api/v1/groups { name, members: { users } }"
API-->>Tool: "{ id, name, createdAt }"
Tool-->>Block: "{ id, name, createdAt }"
Block->>Tool: "update_group { groupId, name?, addUserIds?, removeUserIds? }"
Tool->>API: "PATCH /api/v1/groups/{groupId.trim()} { name?, members: { add, remove } }"
API-->>Tool: "{ id, name, createdAt }"
Tool-->>Block: "{ id, name, createdAt }"
Block->>Tool: "delete_group { groupId }"
Tool->>API: "DELETE /api/v1/groups/{groupId.trim()}"
API-->>Tool: 204 No Content
Tool-->>Block: "{ success: true, groupId }"
Block->>Tool: "update_collection { collectionId, name?, description? }"
Tool->>API: "PATCH /api/v1/collections/{collectionId.trim()} { name?, description? }"
API-->>Tool: "{ id, name, description, creator }"
Tool-->>Block: "{ id, name, description, creator }"
Block->>Tool: "deactivate_user { userId }"
Tool->>API: "POST /api/v1/users/{userId.trim()}/deactivate"
API-->>Tool: 204 No Content
Tool-->>Block: "{ success: true, userId }"
Note over Block,API: Cursor pagination (list endpoints)
Block->>Tool: "list_projects { after?, before?, ... }"
Tool->>API: "GET /api/v1/projects?after=cursor&..."
API-->>Tool: "{ values: [...], pagination: { after, before } }"
Tool-->>Block: "{ projects, total, after, before }"
Reviews (8): Last reviewed commit: "fix(hex): validate array element types, ..." | Re-trigger Greptile |
|
@greptile review |
|
@cursor review |
|
@greptile review |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 2364c15. Configure here.
|
@greptile review |
|
@cursor review |
|
@greptile review |
|
@cursor review |
|
@greptile review |
|
@cursor review |
|
@greptile review |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 9db288f. Configure here.
- Add hex_update_collection, hex_create_group, hex_update_group, hex_delete_group, hex_deactivate_user tools + block wiring - Add missing run_project fields (viewId, notifications) and get_project_runs runTriggerFilter - Add after/before cursor pagination to list_projects, list_groups, list_data_connections, list_collections - Add .trim() on all interpolated ID path params to guard against copy-paste whitespace
Wrap JSON.parse calls for memberUserIds, addUserIds, removeUserIds, inputParams, and notifications in try/catch so malformed input throws a clear error instead of an opaque parse exception.
update_collection's params() mapping only copied collectionDescription when truthy, so clearing it to an empty string in the UI never reached the API. Untouched fields resolve to null (not undefined), so use a loose null check to distinguish "cleared" from "never touched" without sending description: null on every unrelated update.
Pulled Hex's actual OpenAPI spec (static.hex.site/openapi.json) as ground truth for a final verification pass: - list_users was missing after/before cursor pagination and the userIds filter, which the spec confirms it supports (an earlier doc-summary pass had incorrectly flagged this as unverifiable) - list_users response also exposes lastLoginDate per user, not previously surfaced - list_projects was missing includeComponents, includeTrashed, creatorEmail, ownerEmail, collectionId, categories, sortBy, and sortDirection filters that the spec confirms are real query params
Trim collectionId (list_projects filter), viewId (run_project body), and group member UUIDs (create_group/update_group) to match the .trim() convention already applied to path-segment IDs elsewhere.
categories, memberUserIds, addUserIds, and removeUserIds could parse as valid JSON that isn't an array (e.g. an object), which would throw an opaque "not iterable"/"map is not a function" error deeper in the call. Validate Array.isArray after parsing and fail with a clear message instead.
- notifications now gets the same Array.isArray guard already applied to categories/memberUserIds/addUserIds/removeUserIds - member/category array elements are now validated as strings before .trim()/append, instead of crashing on non-string entries - runTriggerFilter "All" option now sends the documented ALL enum value explicitly instead of relying on omission
9db288f to
d34d447
Compare
|
@greptile review |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit d34d447. Configure here.
Summary
hex_update_collection,hex_create_group,hex_update_group,hex_delete_group,hex_deactivate_usertools + full block wiring (subBlocks, operations, tools.config mapping, outputs, skill)run_projectfields (viewId,notifications) andget_project_runsrunTriggerFilterafter/beforecursor pagination tolist_projects,list_groups,list_data_connections,list_collections(confirmed against Hex's actual response envelope).trim()on every interpolated ID path param (projectId, runId, groupId, collectionId, dataConnectionId) across all tool files to guard against copy-paste whitespace from upstream block outputsnotificationsschema example and a missingALLenum value onrunTriggerFilterType of Change
.trim())Testing
Tested manually — typecheck clean, biome clean,
bun run check:api-validationpasses, two independent subagent audits confirmed block/tool wiring is internally consistent and 100% backward compatible (no removed/renamed fields, only additive changes).Checklist