Uh oh!
There was an error while loading. Please reload this page.
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 |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
waleedlatif1
commented
Jul 2, 2026
@greptile review |
waleedlatif1
commented
Jul 2, 2026
@cursor review |
Uh oh!
There was an error while loading. Please reload this page.
waleedlatif1
commented
Jul 2, 2026
@greptile review |
waleedlatif1
commented
Jul 2, 2026
@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.
waleedlatif1
commented
Jul 2, 2026
@greptile review |
waleedlatif1
commented
Jul 2, 2026
@cursor review |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
waleedlatif1
commented
Jul 2, 2026
@greptile review |
waleedlatif1
commented
Jul 2, 2026
@cursor review |
Uh oh!
There was an error while loading. Please reload this page.
waleedlatif1
commented
Jul 2, 2026
@greptile review |
waleedlatif1
commented
Jul 2, 2026
@cursor review |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
waleedlatif1
commented
Jul 2, 2026
@greptile review |
waleedlatif1
commented
Jul 2, 2026
@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
d34d447Comparewaleedlatif1
commented
Jul 2, 2026
@greptile review |
waleedlatif1
commented
Jul 2, 2026
@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