chore: import upstream snapshot with attribution
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:20:55 +08:00
commit d25d482dc2
13754 changed files with 4996608 additions and 0 deletions
+70
View File
@@ -0,0 +1,70 @@
import type { HexCancelRunParams, HexCancelRunResponse } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const cancelRunTool: ToolConfig<HexCancelRunParams, HexCancelRunResponse> = {
id: 'hex_cancel_run',
name: 'Hex Cancel Run',
description: 'Cancel an active Hex project run.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The UUID of the Hex project',
},
runId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The UUID of the run to cancel',
},
},
request: {
url: (params) =>
`https://app.hex.tech/api/v1/projects/${params.projectId.trim()}/runs/${params.runId.trim()}`,
method: 'DELETE',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response, params) => {
if (response.status === 204 || response.ok) {
return {
success: true,
output: {
success: true,
projectId: params?.projectId ?? '',
runId: params?.runId ?? '',
},
}
}
const data = await response.json().catch(() => ({}))
return {
success: false,
output: {
success: false,
projectId: params?.projectId ?? '',
runId: params?.runId ?? '',
},
error: (data as Record<string, string>).message ?? 'Failed to cancel run',
}
},
outputs: {
success: { type: 'boolean', description: 'Whether the run was successfully cancelled' },
projectId: { type: 'string', description: 'Project UUID' },
runId: { type: 'string', description: 'Run UUID that was cancelled' },
},
}
+78
View File
@@ -0,0 +1,78 @@
import type { HexCreateCollectionParams, HexCreateCollectionResponse } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const createCollectionTool: ToolConfig<
HexCreateCollectionParams,
HexCreateCollectionResponse
> = {
id: 'hex_create_collection',
name: 'Hex Create Collection',
description: 'Create a new collection in the Hex workspace to organize projects.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
name: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Name for the new collection',
},
description: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Optional description for the collection',
},
},
request: {
url: 'https://app.hex.tech/api/v1/collections',
method: 'POST',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
body: (params) => {
const body: Record<string, unknown> = { name: params.name }
if (params.description) body.description = params.description
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
id: data.id ?? null,
name: data.name ?? null,
description: data.description ?? null,
creator: data.creator
? { email: data.creator.email ?? null, id: data.creator.id ?? null }
: null,
},
}
},
outputs: {
id: { type: 'string', description: 'Newly created collection UUID' },
name: { type: 'string', description: 'Collection name' },
description: { type: 'string', description: 'Collection description', optional: true },
creator: {
type: 'object',
description: 'Collection creator',
optional: true,
properties: {
email: { type: 'string', description: 'Creator email' },
id: { type: 'string', description: 'Creator UUID' },
},
},
},
}
+78
View File
@@ -0,0 +1,78 @@
import type { HexCreateGroupParams, HexCreateGroupResponse } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const createGroupTool: ToolConfig<HexCreateGroupParams, HexCreateGroupResponse> = {
id: 'hex_create_group',
name: 'Hex Create Group',
description: 'Create a new group in the Hex workspace, optionally with initial members.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
name: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Name for the new group',
},
memberUserIds: {
type: 'json',
required: false,
visibility: 'user-or-llm',
description:
'JSON array of user UUIDs to add as initial group members (e.g., ["uuid1", "uuid2"])',
},
},
request: {
url: 'https://app.hex.tech/api/v1/groups',
method: 'POST',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
body: (params) => {
const body: Record<string, unknown> = { name: params.name }
if (params.memberUserIds) {
let userIds: unknown
try {
userIds =
typeof params.memberUserIds === 'string'
? JSON.parse(params.memberUserIds)
: params.memberUserIds
} catch {
throw new Error('memberUserIds must be a valid JSON array of user UUID strings')
}
if (!Array.isArray(userIds) || !userIds.every((id) => typeof id === 'string')) {
throw new Error('memberUserIds must be a valid JSON array of user UUID strings')
}
body.members = { users: userIds.map((id: string) => ({ id: id.trim() })) }
}
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
id: data.id ?? null,
name: data.name ?? null,
createdAt: data.createdAt ?? null,
},
}
},
outputs: {
id: { type: 'string', description: 'Newly created group UUID' },
name: { type: 'string', description: 'Group name' },
createdAt: { type: 'string', description: 'Creation timestamp' },
},
}
+60
View File
@@ -0,0 +1,60 @@
import type { HexDeactivateUserParams, HexDeactivateUserResponse } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const deactivateUserTool: ToolConfig<HexDeactivateUserParams, HexDeactivateUserResponse> = {
id: 'hex_deactivate_user',
name: 'Hex Deactivate User',
description: 'Deactivate a user in the Hex workspace.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
userId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The UUID of the user to deactivate',
},
},
request: {
url: (params) => `https://app.hex.tech/api/v1/users/${params.userId.trim()}/deactivate`,
method: 'POST',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response, params) => {
if (response.status === 204 || response.ok) {
return {
success: true,
output: {
success: true,
userId: params?.userId ?? '',
},
}
}
const data = await response.json().catch(() => ({}))
return {
success: false,
output: {
success: false,
userId: params?.userId ?? '',
},
error: (data as Record<string, string>).message ?? 'Failed to deactivate user',
}
},
outputs: {
success: { type: 'boolean', description: 'Whether the user was successfully deactivated' },
userId: { type: 'string', description: 'User UUID that was deactivated' },
},
}
+60
View File
@@ -0,0 +1,60 @@
import type { HexDeleteGroupParams, HexDeleteGroupResponse } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const deleteGroupTool: ToolConfig<HexDeleteGroupParams, HexDeleteGroupResponse> = {
id: 'hex_delete_group',
name: 'Hex Delete Group',
description: 'Delete a group from the Hex workspace.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
groupId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The UUID of the group to delete',
},
},
request: {
url: (params) => `https://app.hex.tech/api/v1/groups/${params.groupId.trim()}`,
method: 'DELETE',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response, params) => {
if (response.status === 204 || response.ok) {
return {
success: true,
output: {
success: true,
groupId: params?.groupId ?? '',
},
}
}
const data = await response.json().catch(() => ({}))
return {
success: false,
output: {
success: false,
groupId: params?.groupId ?? '',
},
error: (data as Record<string, string>).message ?? 'Failed to delete group',
}
},
outputs: {
success: { type: 'boolean', description: 'Whether the group was successfully deleted' },
groupId: { type: 'string', description: 'Group UUID that was deleted' },
},
}
+64
View File
@@ -0,0 +1,64 @@
import type { HexGetCollectionParams, HexGetCollectionResponse } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const getCollectionTool: ToolConfig<HexGetCollectionParams, HexGetCollectionResponse> = {
id: 'hex_get_collection',
name: 'Hex Get Collection',
description: 'Retrieve details for a specific Hex collection by its ID.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
collectionId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The UUID of the collection',
},
},
request: {
url: (params) => `https://app.hex.tech/api/v1/collections/${params.collectionId.trim()}`,
method: 'GET',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
id: data.id ?? null,
name: data.name ?? null,
description: data.description ?? null,
creator: data.creator
? { email: data.creator.email ?? null, id: data.creator.id ?? null }
: null,
},
}
},
outputs: {
id: { type: 'string', description: 'Collection UUID' },
name: { type: 'string', description: 'Collection name' },
description: { type: 'string', description: 'Collection description', optional: true },
creator: {
type: 'object',
description: 'Collection creator',
optional: true,
properties: {
email: { type: 'string', description: 'Creator email' },
id: { type: 'string', description: 'Creator UUID' },
},
},
},
}
+77
View File
@@ -0,0 +1,77 @@
import type { HexGetDataConnectionParams, HexGetDataConnectionResponse } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const getDataConnectionTool: ToolConfig<
HexGetDataConnectionParams,
HexGetDataConnectionResponse
> = {
id: 'hex_get_data_connection',
name: 'Hex Get Data Connection',
description:
'Retrieve details for a specific data connection including type, description, and configuration flags.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
dataConnectionId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The UUID of the data connection',
},
},
request: {
url: (params) =>
`https://app.hex.tech/api/v1/data-connections/${params.dataConnectionId.trim()}`,
method: 'GET',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
id: data.id ?? null,
name: data.name ?? null,
type: data.type ?? null,
description: data.description ?? null,
connectViaSsh: data.connectViaSsh ?? null,
includeMagic: data.includeMagic ?? null,
allowWritebackCells: data.allowWritebackCells ?? null,
},
}
},
outputs: {
id: { type: 'string', description: 'Connection UUID' },
name: { type: 'string', description: 'Connection name' },
type: { type: 'string', description: 'Connection type (e.g., snowflake, postgres, bigquery)' },
description: { type: 'string', description: 'Connection description', optional: true },
connectViaSsh: {
type: 'boolean',
description: 'Whether SSH tunneling is enabled',
optional: true,
},
includeMagic: {
type: 'boolean',
description: 'Whether Magic AI features are enabled',
optional: true,
},
allowWritebackCells: {
type: 'boolean',
description: 'Whether writeback cells are allowed',
optional: true,
},
},
}
+52
View File
@@ -0,0 +1,52 @@
import type { HexGetGroupParams, HexGetGroupResponse } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const getGroupTool: ToolConfig<HexGetGroupParams, HexGetGroupResponse> = {
id: 'hex_get_group',
name: 'Hex Get Group',
description: 'Retrieve details for a specific Hex group.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
groupId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The UUID of the group',
},
},
request: {
url: (params) => `https://app.hex.tech/api/v1/groups/${params.groupId.trim()}`,
method: 'GET',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
id: data.id ?? null,
name: data.name ?? null,
createdAt: data.createdAt ?? null,
},
}
},
outputs: {
id: { type: 'string', description: 'Group UUID' },
name: { type: 'string', description: 'Group name' },
createdAt: { type: 'string', description: 'Creation timestamp' },
},
}
+78
View File
@@ -0,0 +1,78 @@
import type { HexGetProjectParams, HexGetProjectResponse } from '@/tools/hex/types'
import { HEX_PROJECT_OUTPUT_PROPERTIES } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const getProjectTool: ToolConfig<HexGetProjectParams, HexGetProjectResponse> = {
id: 'hex_get_project',
name: 'Hex Get Project',
description: 'Get metadata and details for a specific Hex project by its ID.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The UUID of the Hex project',
},
},
request: {
url: (params) => `https://app.hex.tech/api/v1/projects/${params.projectId.trim()}`,
method: 'GET',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
id: data.id ?? null,
title: data.title ?? null,
description: data.description ?? null,
status: data.status ? { name: data.status.name ?? null } : null,
type: data.type ?? null,
creator: data.creator ? { email: data.creator.email ?? null } : null,
owner: data.owner ? { email: data.owner.email ?? null } : null,
categories: Array.isArray(data.categories)
? data.categories.map((c: Record<string, string>) => ({
name: c.name ?? null,
description: c.description ?? null,
}))
: [],
lastEditedAt: data.lastEditedAt ?? null,
lastPublishedAt: data.lastPublishedAt ?? null,
createdAt: data.createdAt ?? null,
archivedAt: data.archivedAt ?? null,
trashedAt: data.trashedAt ?? null,
},
}
},
outputs: {
id: HEX_PROJECT_OUTPUT_PROPERTIES.id,
title: HEX_PROJECT_OUTPUT_PROPERTIES.title,
description: HEX_PROJECT_OUTPUT_PROPERTIES.description,
status: HEX_PROJECT_OUTPUT_PROPERTIES.status,
type: HEX_PROJECT_OUTPUT_PROPERTIES.type,
creator: HEX_PROJECT_OUTPUT_PROPERTIES.creator,
owner: HEX_PROJECT_OUTPUT_PROPERTIES.owner,
categories: HEX_PROJECT_OUTPUT_PROPERTIES.categories,
lastEditedAt: HEX_PROJECT_OUTPUT_PROPERTIES.lastEditedAt,
lastPublishedAt: HEX_PROJECT_OUTPUT_PROPERTIES.lastPublishedAt,
createdAt: HEX_PROJECT_OUTPUT_PROPERTIES.createdAt,
archivedAt: HEX_PROJECT_OUTPUT_PROPERTIES.archivedAt,
trashedAt: HEX_PROJECT_OUTPUT_PROPERTIES.trashedAt,
},
}
+130
View File
@@ -0,0 +1,130 @@
import type { HexGetProjectRunsParams, HexGetProjectRunsResponse } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const getProjectRunsTool: ToolConfig<HexGetProjectRunsParams, HexGetProjectRunsResponse> = {
id: 'hex_get_project_runs',
name: 'Hex Get Project Runs',
description:
'Retrieve API-triggered runs for a Hex project with optional filtering by status and pagination.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The UUID of the Hex project',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of runs to return (1-100, default: 25)',
},
offset: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Offset for paginated results (default: 0)',
},
statusFilter: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Filter by run status: PENDING, RUNNING, ERRORED, COMPLETED, KILLED, UNABLE_TO_ALLOCATE_KERNEL',
},
runTriggerFilter: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter by how the run was triggered: ALL, API, SCHEDULED, or APP_REFRESH',
},
},
request: {
url: (params) => {
const searchParams = new URLSearchParams()
if (params.limit) searchParams.set('limit', String(params.limit))
if (params.offset) searchParams.set('offset', String(params.offset))
if (params.statusFilter) searchParams.set('statusFilter', params.statusFilter)
if (params.runTriggerFilter) searchParams.set('runTriggerFilter', params.runTriggerFilter)
const qs = searchParams.toString()
return `https://app.hex.tech/api/v1/projects/${params.projectId.trim()}/runs${qs ? `?${qs}` : ''}`
},
method: 'GET',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
const runs = Array.isArray(data) ? data : (data.runs ?? [])
return {
success: true,
output: {
runs: runs.map((r: Record<string, unknown>) => ({
projectId: (r.projectId as string) ?? null,
runId: (r.runId as string) ?? null,
runUrl: (r.runUrl as string) ?? null,
status: (r.status as string) ?? null,
startTime: (r.startTime as string) ?? null,
endTime: (r.endTime as string) ?? null,
elapsedTime: (r.elapsedTime as number) ?? null,
traceId: (r.traceId as string) ?? null,
projectVersion: (r.projectVersion as number) ?? null,
})),
total: runs.length,
traceId: data.traceId ?? null,
nextPage: data.nextPage ?? null,
previousPage: data.previousPage ?? null,
},
}
},
outputs: {
runs: {
type: 'array',
description: 'List of project runs',
items: {
type: 'object',
properties: {
projectId: { type: 'string', description: 'Project UUID' },
runId: { type: 'string', description: 'Run UUID' },
runUrl: { type: 'string', description: 'URL to view the run', optional: true },
status: {
type: 'string',
description:
'Run status (PENDING, RUNNING, COMPLETED, ERRORED, KILLED, UNABLE_TO_ALLOCATE_KERNEL)',
},
startTime: { type: 'string', description: 'Run start time', optional: true },
endTime: { type: 'string', description: 'Run end time', optional: true },
elapsedTime: { type: 'number', description: 'Elapsed time in seconds', optional: true },
traceId: { type: 'string', description: 'Trace ID', optional: true },
projectVersion: {
type: 'number',
description: 'Project version number',
optional: true,
},
},
},
},
total: { type: 'number', description: 'Total number of runs returned' },
traceId: { type: 'string', description: 'Top-level trace ID', optional: true },
nextPage: { type: 'string', description: 'Cursor for the next page of runs', optional: true },
previousPage: {
type: 'string',
description: 'Cursor for the previous page of runs',
optional: true,
},
},
}
+81
View File
@@ -0,0 +1,81 @@
import type { HexGetQueriedTablesParams, HexGetQueriedTablesResponse } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const getQueriedTablesTool: ToolConfig<
HexGetQueriedTablesParams,
HexGetQueriedTablesResponse
> = {
id: 'hex_get_queried_tables',
name: 'Hex Get Queried Tables',
description:
'Return the warehouse tables queried by a Hex project, including data connection and table names.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The UUID of the Hex project',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of tables to return (1-100)',
},
},
request: {
url: (params) => {
const searchParams = new URLSearchParams()
if (params.limit) searchParams.set('limit', String(params.limit))
const qs = searchParams.toString()
return `https://app.hex.tech/api/v1/projects/${params.projectId.trim()}/queriedTables${qs ? `?${qs}` : ''}`
},
method: 'GET',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
const tables = Array.isArray(data) ? data : (data.values ?? [])
return {
success: true,
output: {
tables: tables.map((t: Record<string, unknown>) => ({
dataConnectionId: (t.dataConnectionId as string) ?? null,
dataConnectionName: (t.dataConnectionName as string) ?? null,
tableName: (t.tableName as string) ?? null,
})),
total: tables.length,
},
}
},
outputs: {
tables: {
type: 'array',
description: 'List of warehouse tables queried by the project',
items: {
type: 'object',
properties: {
dataConnectionId: { type: 'string', description: 'Data connection UUID' },
dataConnectionName: { type: 'string', description: 'Data connection name' },
tableName: { type: 'string', description: 'Table name' },
},
},
},
total: { type: 'number', description: 'Total number of tables returned' },
},
}
+72
View File
@@ -0,0 +1,72 @@
import type { HexGetRunStatusParams, HexGetRunStatusResponse } from '@/tools/hex/types'
import { HEX_RUN_STATUS_OUTPUT_PROPERTIES } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const getRunStatusTool: ToolConfig<HexGetRunStatusParams, HexGetRunStatusResponse> = {
id: 'hex_get_run_status',
name: 'Hex Get Run Status',
description: 'Check the status of a Hex project run by its run ID.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The UUID of the Hex project',
},
runId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The UUID of the run to check',
},
},
request: {
url: (params) =>
`https://app.hex.tech/api/v1/projects/${params.projectId.trim()}/runs/${params.runId.trim()}`,
method: 'GET',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
projectId: data.projectId ?? null,
runId: data.runId ?? null,
runUrl: data.runUrl ?? null,
status: data.status ?? null,
startTime: data.startTime ?? null,
endTime: data.endTime ?? null,
elapsedTime: data.elapsedTime ?? null,
traceId: data.traceId ?? null,
projectVersion: data.projectVersion ?? null,
},
}
},
outputs: {
projectId: HEX_RUN_STATUS_OUTPUT_PROPERTIES.projectId,
runId: HEX_RUN_STATUS_OUTPUT_PROPERTIES.runId,
runUrl: HEX_RUN_STATUS_OUTPUT_PROPERTIES.runUrl,
status: HEX_RUN_STATUS_OUTPUT_PROPERTIES.status,
startTime: HEX_RUN_STATUS_OUTPUT_PROPERTIES.startTime,
endTime: HEX_RUN_STATUS_OUTPUT_PROPERTIES.endTime,
elapsedTime: HEX_RUN_STATUS_OUTPUT_PROPERTIES.elapsedTime,
traceId: HEX_RUN_STATUS_OUTPUT_PROPERTIES.traceId,
projectVersion: HEX_RUN_STATUS_OUTPUT_PROPERTIES.projectVersion,
},
}
+43
View File
@@ -0,0 +1,43 @@
import { cancelRunTool } from '@/tools/hex/cancel_run'
import { createCollectionTool } from '@/tools/hex/create_collection'
import { createGroupTool } from '@/tools/hex/create_group'
import { deactivateUserTool } from '@/tools/hex/deactivate_user'
import { deleteGroupTool } from '@/tools/hex/delete_group'
import { getCollectionTool } from '@/tools/hex/get_collection'
import { getDataConnectionTool } from '@/tools/hex/get_data_connection'
import { getGroupTool } from '@/tools/hex/get_group'
import { getProjectTool } from '@/tools/hex/get_project'
import { getProjectRunsTool } from '@/tools/hex/get_project_runs'
import { getQueriedTablesTool } from '@/tools/hex/get_queried_tables'
import { getRunStatusTool } from '@/tools/hex/get_run_status'
import { listCollectionsTool } from '@/tools/hex/list_collections'
import { listDataConnectionsTool } from '@/tools/hex/list_data_connections'
import { listGroupsTool } from '@/tools/hex/list_groups'
import { listProjectsTool } from '@/tools/hex/list_projects'
import { listUsersTool } from '@/tools/hex/list_users'
import { runProjectTool } from '@/tools/hex/run_project'
import { updateCollectionTool } from '@/tools/hex/update_collection'
import { updateGroupTool } from '@/tools/hex/update_group'
import { updateProjectTool } from '@/tools/hex/update_project'
export const hexCancelRunTool = cancelRunTool
export const hexCreateCollectionTool = createCollectionTool
export const hexCreateGroupTool = createGroupTool
export const hexDeactivateUserTool = deactivateUserTool
export const hexDeleteGroupTool = deleteGroupTool
export const hexGetCollectionTool = getCollectionTool
export const hexGetDataConnectionTool = getDataConnectionTool
export const hexGetGroupTool = getGroupTool
export const hexGetProjectTool = getProjectTool
export const hexGetProjectRunsTool = getProjectRunsTool
export const hexGetQueriedTablesTool = getQueriedTablesTool
export const hexGetRunStatusTool = getRunStatusTool
export const hexListCollectionsTool = listCollectionsTool
export const hexListDataConnectionsTool = listDataConnectionsTool
export const hexListGroupsTool = listGroupsTool
export const hexListProjectsTool = listProjectsTool
export const hexListUsersTool = listUsersTool
export const hexRunProjectTool = runProjectTool
export const hexUpdateCollectionTool = updateCollectionTool
export const hexUpdateGroupTool = updateGroupTool
export const hexUpdateProjectTool = updateProjectTool
+116
View File
@@ -0,0 +1,116 @@
import type { HexListCollectionsParams, HexListCollectionsResponse } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const listCollectionsTool: ToolConfig<HexListCollectionsParams, HexListCollectionsResponse> =
{
id: 'hex_list_collections',
name: 'Hex List Collections',
description: 'List all collections in the Hex workspace.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of collections to return (1-500, default: 25)',
},
sortBy: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Sort by field: NAME',
},
after: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Cursor to fetch the page of results after this value',
},
before: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Cursor to fetch the page of results before this value',
},
},
request: {
url: (params) => {
const searchParams = new URLSearchParams()
if (params.limit) searchParams.set('limit', String(params.limit))
if (params.sortBy) searchParams.set('sortBy', params.sortBy)
if (params.after) searchParams.set('after', params.after)
if (params.before) searchParams.set('before', params.before)
const qs = searchParams.toString()
return `https://app.hex.tech/api/v1/collections${qs ? `?${qs}` : ''}`
},
method: 'GET',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
const collections = Array.isArray(data) ? data : (data.values ?? [])
return {
success: true,
output: {
collections: collections.map((c: Record<string, unknown>) => ({
id: (c.id as string) ?? null,
name: (c.name as string) ?? null,
description: (c.description as string) ?? null,
creator: c.creator
? {
email: (c.creator as Record<string, string>).email ?? null,
id: (c.creator as Record<string, string>).id ?? null,
}
: null,
})),
total: collections.length,
after: data.pagination?.after ?? null,
before: data.pagination?.before ?? null,
},
}
},
outputs: {
collections: {
type: 'array',
description: 'List of collections',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Collection UUID' },
name: { type: 'string', description: 'Collection name' },
description: { type: 'string', description: 'Collection description', optional: true },
creator: {
type: 'object',
description: 'Collection creator',
optional: true,
properties: {
email: { type: 'string', description: 'Creator email' },
id: { type: 'string', description: 'Creator UUID' },
},
},
},
},
},
total: { type: 'number', description: 'Total number of collections returned' },
after: { type: 'string', description: 'Cursor for the next page of results', optional: true },
before: {
type: 'string',
description: 'Cursor for the previous page of results',
optional: true,
},
},
}
+138
View File
@@ -0,0 +1,138 @@
import type {
HexListDataConnectionsParams,
HexListDataConnectionsResponse,
} from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const listDataConnectionsTool: ToolConfig<
HexListDataConnectionsParams,
HexListDataConnectionsResponse
> = {
id: 'hex_list_data_connections',
name: 'Hex List Data Connections',
description:
'List all data connections in the Hex workspace (e.g., Snowflake, PostgreSQL, BigQuery).',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of connections to return (1-500, default: 25)',
},
sortBy: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Sort by field: CREATED_AT or NAME',
},
sortDirection: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Sort direction: ASC or DESC',
},
after: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Cursor to fetch the page of results after this value',
},
before: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Cursor to fetch the page of results before this value',
},
},
request: {
url: (params) => {
const searchParams = new URLSearchParams()
if (params.limit) searchParams.set('limit', String(params.limit))
if (params.sortBy) searchParams.set('sortBy', params.sortBy)
if (params.sortDirection) searchParams.set('sortDirection', params.sortDirection)
if (params.after) searchParams.set('after', params.after)
if (params.before) searchParams.set('before', params.before)
const qs = searchParams.toString()
return `https://app.hex.tech/api/v1/data-connections${qs ? `?${qs}` : ''}`
},
method: 'GET',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
const connections = Array.isArray(data) ? data : (data.values ?? [])
return {
success: true,
output: {
connections: connections.map((c: Record<string, unknown>) => ({
id: (c.id as string) ?? null,
name: (c.name as string) ?? null,
type: (c.type as string) ?? null,
description: (c.description as string) ?? null,
connectViaSsh: (c.connectViaSsh as boolean) ?? null,
includeMagic: (c.includeMagic as boolean) ?? null,
allowWritebackCells: (c.allowWritebackCells as boolean) ?? null,
})),
total: connections.length,
after: data.pagination?.after ?? null,
before: data.pagination?.before ?? null,
},
}
},
outputs: {
connections: {
type: 'array',
description: 'List of data connections',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Connection UUID' },
name: { type: 'string', description: 'Connection name' },
type: {
type: 'string',
description:
'Connection type (e.g., athena, bigquery, databricks, postgres, redshift, snowflake)',
},
description: { type: 'string', description: 'Connection description', optional: true },
connectViaSsh: {
type: 'boolean',
description: 'Whether SSH tunneling is enabled',
optional: true,
},
includeMagic: {
type: 'boolean',
description: 'Whether Magic AI features are enabled',
optional: true,
},
allowWritebackCells: {
type: 'boolean',
description: 'Whether writeback cells are allowed',
optional: true,
},
},
},
},
total: { type: 'number', description: 'Total number of connections returned' },
after: { type: 'string', description: 'Cursor for the next page of results', optional: true },
before: {
type: 'string',
description: 'Cursor for the previous page of results',
optional: true,
},
},
}
+107
View File
@@ -0,0 +1,107 @@
import type { HexListGroupsParams, HexListGroupsResponse } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const listGroupsTool: ToolConfig<HexListGroupsParams, HexListGroupsResponse> = {
id: 'hex_list_groups',
name: 'Hex List Groups',
description: 'List all groups in the Hex workspace with optional sorting.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of groups to return (1-500, default: 25)',
},
sortBy: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Sort by field: CREATED_AT or NAME',
},
sortDirection: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Sort direction: ASC or DESC',
},
after: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Cursor to fetch the page of results after this value',
},
before: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Cursor to fetch the page of results before this value',
},
},
request: {
url: (params) => {
const searchParams = new URLSearchParams()
if (params.limit) searchParams.set('limit', String(params.limit))
if (params.sortBy) searchParams.set('sortBy', params.sortBy)
if (params.sortDirection) searchParams.set('sortDirection', params.sortDirection)
if (params.after) searchParams.set('after', params.after)
if (params.before) searchParams.set('before', params.before)
const qs = searchParams.toString()
return `https://app.hex.tech/api/v1/groups${qs ? `?${qs}` : ''}`
},
method: 'GET',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
const groups = Array.isArray(data) ? data : (data.values ?? [])
return {
success: true,
output: {
groups: groups.map((g: Record<string, unknown>) => ({
id: (g.id as string) ?? null,
name: (g.name as string) ?? null,
createdAt: (g.createdAt as string) ?? null,
})),
total: groups.length,
after: data.pagination?.after ?? null,
before: data.pagination?.before ?? null,
},
}
},
outputs: {
groups: {
type: 'array',
description: 'List of workspace groups',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Group UUID' },
name: { type: 'string', description: 'Group name' },
createdAt: { type: 'string', description: 'Creation timestamp' },
},
},
},
total: { type: 'number', description: 'Total number of groups returned' },
after: { type: 'string', description: 'Cursor for the next page of results', optional: true },
before: {
type: 'string',
description: 'Cursor for the previous page of results',
optional: true,
},
},
}
+232
View File
@@ -0,0 +1,232 @@
import type { HexListProjectsParams, HexListProjectsResponse } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const listProjectsTool: ToolConfig<HexListProjectsParams, HexListProjectsResponse> = {
id: 'hex_list_projects',
name: 'Hex List Projects',
description: 'List all projects in your Hex workspace with optional filtering by status.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of projects to return (1-100)',
},
includeArchived: {
type: 'boolean',
required: false,
visibility: 'user-only',
description: 'Include archived projects in results',
},
statusFilter: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter by status: PUBLISHED, DRAFT, or ALL',
},
includeComponents: {
type: 'boolean',
required: false,
visibility: 'user-only',
description: 'Include components in results',
},
includeTrashed: {
type: 'boolean',
required: false,
visibility: 'user-only',
description: 'Include trashed projects in results',
},
creatorEmail: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter by creator email',
},
ownerEmail: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter by owner email',
},
collectionId: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter by collection UUID',
},
categories: {
type: 'json',
required: false,
visibility: 'user-or-llm',
description: 'JSON array of category names to filter by (e.g., ["Marketing", "Finance"])',
},
sortBy: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Sort by field: CREATED_AT, LAST_EDITED_AT, or LAST_PUBLISHED_AT',
},
sortDirection: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Sort direction: ASC or DESC',
},
after: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Cursor to fetch the page of results after this value',
},
before: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Cursor to fetch the page of results before this value',
},
},
request: {
url: (params) => {
const searchParams = new URLSearchParams()
if (params.limit) searchParams.set('limit', String(params.limit))
if (params.includeArchived) searchParams.set('includeArchived', 'true')
if (params.includeComponents) searchParams.set('includeComponents', 'true')
if (params.includeTrashed) searchParams.set('includeTrashed', 'true')
if (params.statusFilter) searchParams.append('statuses[]', params.statusFilter)
if (params.creatorEmail) searchParams.set('creatorEmail', params.creatorEmail)
if (params.ownerEmail) searchParams.set('ownerEmail', params.ownerEmail)
if (params.collectionId) searchParams.set('collectionId', params.collectionId.trim())
if (params.categories) {
let categories: unknown
try {
categories =
typeof params.categories === 'string'
? JSON.parse(params.categories)
: params.categories
} catch {
throw new Error('categories must be a valid JSON array of category name strings')
}
if (!Array.isArray(categories) || !categories.every((c) => typeof c === 'string')) {
throw new Error('categories must be a valid JSON array of category name strings')
}
for (const category of categories) {
searchParams.append('categories[]', category)
}
}
if (params.sortBy) searchParams.set('sortBy', params.sortBy)
if (params.sortDirection) searchParams.set('sortDirection', params.sortDirection)
if (params.after) searchParams.set('after', params.after)
if (params.before) searchParams.set('before', params.before)
const qs = searchParams.toString()
return `https://app.hex.tech/api/v1/projects${qs ? `?${qs}` : ''}`
},
method: 'GET',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
const projects = Array.isArray(data) ? data : (data.values ?? [])
return {
success: true,
output: {
projects: projects.map((p: Record<string, unknown>) => ({
id: (p.id as string) ?? null,
title: (p.title as string) ?? null,
description: (p.description as string) ?? null,
status: p.status ? { name: (p.status as Record<string, string>).name ?? null } : null,
type: (p.type as string) ?? null,
creator: p.creator
? { email: (p.creator as Record<string, string>).email ?? null }
: null,
owner: p.owner ? { email: (p.owner as Record<string, string>).email ?? null } : null,
categories: Array.isArray(p.categories)
? (p.categories as Array<Record<string, string>>).map((c) => ({
name: c.name ?? null,
description: c.description ?? null,
}))
: [],
lastEditedAt: (p.lastEditedAt as string) ?? null,
lastPublishedAt: (p.lastPublishedAt as string) ?? null,
createdAt: (p.createdAt as string) ?? null,
archivedAt: (p.archivedAt as string) ?? null,
trashedAt: (p.trashedAt as string) ?? null,
})),
total: projects.length,
after: data.pagination?.after ?? null,
before: data.pagination?.before ?? null,
},
}
},
outputs: {
projects: {
type: 'array',
description: 'List of Hex projects',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Project UUID' },
title: { type: 'string', description: 'Project title' },
description: { type: 'string', description: 'Project description', optional: true },
status: {
type: 'object',
description: 'Project status',
properties: {
name: { type: 'string', description: 'Status name (e.g., PUBLISHED, DRAFT)' },
},
},
type: { type: 'string', description: 'Project type (PROJECT or COMPONENT)' },
creator: {
type: 'object',
description: 'Project creator',
optional: true,
properties: {
email: { type: 'string', description: 'Creator email' },
},
},
owner: {
type: 'object',
description: 'Project owner',
optional: true,
properties: {
email: { type: 'string', description: 'Owner email' },
},
},
lastEditedAt: {
type: 'string',
description: 'Last edited timestamp',
optional: true,
},
lastPublishedAt: {
type: 'string',
description: 'Last published timestamp',
optional: true,
},
createdAt: { type: 'string', description: 'Creation timestamp' },
archivedAt: { type: 'string', description: 'Archived timestamp', optional: true },
},
},
},
total: { type: 'number', description: 'Total number of projects returned' },
after: { type: 'string', description: 'Cursor for the next page of results', optional: true },
before: {
type: 'string',
description: 'Cursor for the previous page of results',
optional: true,
},
},
}
+133
View File
@@ -0,0 +1,133 @@
import type { HexListUsersParams, HexListUsersResponse } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const listUsersTool: ToolConfig<HexListUsersParams, HexListUsersResponse> = {
id: 'hex_list_users',
name: 'Hex List Users',
description: 'List all users in the Hex workspace with optional filtering and sorting.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of users to return (1-100, default: 25)',
},
sortBy: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Sort by field: NAME or EMAIL',
},
sortDirection: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Sort direction: ASC or DESC',
},
groupId: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter users by group UUID',
},
userIds: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Comma-separated list of user UUIDs to filter by',
},
after: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Cursor to fetch the page of results after this value',
},
before: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Cursor to fetch the page of results before this value',
},
},
request: {
url: (params) => {
const searchParams = new URLSearchParams()
if (params.limit) searchParams.set('limit', String(params.limit))
if (params.sortBy) searchParams.set('sortBy', params.sortBy)
if (params.sortDirection) searchParams.set('sortDirection', params.sortDirection)
if (params.groupId) searchParams.set('groupId', params.groupId)
if (params.userIds) searchParams.set('userIds', params.userIds)
if (params.after) searchParams.set('after', params.after)
if (params.before) searchParams.set('before', params.before)
const qs = searchParams.toString()
return `https://app.hex.tech/api/v1/users${qs ? `?${qs}` : ''}`
},
method: 'GET',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
const users = Array.isArray(data) ? data : (data.values ?? [])
return {
success: true,
output: {
users: users.map((u: Record<string, unknown>) => ({
id: (u.id as string) ?? null,
name: (u.name as string) ?? null,
email: (u.email as string) ?? null,
role: (u.role as string) ?? null,
lastLoginDate: (u.lastLoginDate as string) ?? null,
})),
total: users.length,
after: data.pagination?.after ?? null,
before: data.pagination?.before ?? null,
},
}
},
outputs: {
users: {
type: 'array',
description: 'List of workspace users',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'User UUID' },
name: { type: 'string', description: 'User name' },
email: { type: 'string', description: 'User email' },
role: {
type: 'string',
description:
'User role (ADMIN, MANAGER, EDITOR, EXPLORER, MEMBER, GUEST, EMBEDDED_USER, ANONYMOUS)',
},
lastLoginDate: {
type: 'string',
description: 'Last login timestamp',
optional: true,
},
},
},
},
total: { type: 'number', description: 'Total number of users returned' },
after: { type: 'string', description: 'Cursor for the next page of results', optional: true },
before: {
type: 'string',
description: 'Cursor for the previous page of results',
optional: true,
},
},
}
+141
View File
@@ -0,0 +1,141 @@
import type { HexRunProjectParams, HexRunProjectResponse } from '@/tools/hex/types'
import { HEX_RUN_OUTPUT_PROPERTIES } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const runProjectTool: ToolConfig<HexRunProjectParams, HexRunProjectResponse> = {
id: 'hex_run_project',
name: 'Hex Run Project',
description:
'Execute a published Hex project. Optionally pass input parameters and control caching behavior.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The UUID of the Hex project to run',
},
inputParams: {
type: 'json',
required: false,
visibility: 'user-or-llm',
description: 'JSON object of input parameters for the project (e.g., {"date": "2024-01-01"})',
},
dryRun: {
type: 'boolean',
required: false,
visibility: 'user-only',
description: 'If true, perform a dry run without executing the project',
},
updateCache: {
type: 'boolean',
required: false,
visibility: 'user-only',
description: '(Deprecated) If true, update the cached results after execution',
},
updatePublishedResults: {
type: 'boolean',
required: false,
visibility: 'user-only',
description: 'If true, update the published app results after execution',
},
useCachedSqlResults: {
type: 'boolean',
required: false,
visibility: 'user-only',
description: 'If true, use cached SQL results instead of re-running queries',
},
viewId: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Optional SavedView ID to use for the project run',
},
notifications: {
type: 'json',
required: false,
visibility: 'user-or-llm',
description:
'JSON array of notification details to deliver once the run completes (e.g., [{"type": "FAILURE", "slackChannelIds": ["C0123456789"], "userIds": [], "groupIds": [], "includeSuccessScreenshot": false}]). type is ALL, SUCCESS, or FAILURE.',
},
},
request: {
url: (params) => `https://app.hex.tech/api/v1/projects/${params.projectId.trim()}/runs`,
method: 'POST',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
body: (params) => {
const body: Record<string, unknown> = {}
if (params.inputParams) {
try {
body.inputParams =
typeof params.inputParams === 'string'
? JSON.parse(params.inputParams)
: params.inputParams
} catch {
throw new Error('inputParams must be valid JSON')
}
}
if (params.dryRun !== undefined) body.dryRun = params.dryRun
if (params.updateCache !== undefined) body.updateCache = params.updateCache
if (params.updatePublishedResults !== undefined)
body.updatePublishedResults = params.updatePublishedResults
if (params.useCachedSqlResults !== undefined)
body.useCachedSqlResults = params.useCachedSqlResults
if (params.viewId) body.viewId = params.viewId.trim()
if (params.notifications) {
let notifications: unknown
try {
notifications =
typeof params.notifications === 'string'
? JSON.parse(params.notifications)
: params.notifications
} catch {
throw new Error('notifications must be a valid JSON array')
}
if (!Array.isArray(notifications)) {
throw new Error('notifications must be a valid JSON array')
}
body.notifications = notifications
}
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
projectId: data.projectId ?? null,
runId: data.runId ?? null,
runUrl: data.runUrl ?? null,
runStatusUrl: data.runStatusUrl ?? null,
traceId: data.traceId ?? null,
projectVersion: data.projectVersion ?? null,
},
}
},
outputs: {
projectId: HEX_RUN_OUTPUT_PROPERTIES.projectId,
runId: HEX_RUN_OUTPUT_PROPERTIES.runId,
runUrl: HEX_RUN_OUTPUT_PROPERTIES.runUrl,
runStatusUrl: HEX_RUN_OUTPUT_PROPERTIES.runStatusUrl,
traceId: HEX_RUN_OUTPUT_PROPERTIES.traceId,
projectVersion: HEX_RUN_OUTPUT_PROPERTIES.projectVersion,
},
}
+539
View File
@@ -0,0 +1,539 @@
import type { OutputProperty, ToolResponse } from '@/tools/types'
/**
* Shared output property definitions for Hex API responses.
* Based on Hex API documentation: https://learn.hex.tech/docs/api/api-reference
*/
/**
* Output definition for project items returned by the Hex API.
* The status field is an object with a name property (e.g., { name: "PUBLISHED" }).
* The type field is a ProjectTypeApiEnum (PROJECT or COMPONENT).
*/
export const HEX_PROJECT_OUTPUT_PROPERTIES = {
id: { type: 'string', description: 'Project UUID' },
title: { type: 'string', description: 'Project title' },
description: { type: 'string', description: 'Project description', optional: true },
status: {
type: 'object',
description: 'Project status',
properties: {
name: {
type: 'string',
description: 'Status name (e.g., PUBLISHED, DRAFT)',
},
},
},
type: {
type: 'string',
description: 'Project type (PROJECT or COMPONENT)',
},
creator: {
type: 'object',
description: 'Project creator',
optional: true,
properties: {
email: { type: 'string', description: 'Creator email' },
},
},
owner: {
type: 'object',
description: 'Project owner',
optional: true,
properties: {
email: { type: 'string', description: 'Owner email' },
},
},
categories: {
type: 'array',
description: 'Project categories',
optional: true,
items: {
type: 'object',
properties: {
name: { type: 'string', description: 'Category name' },
description: { type: 'string', description: 'Category description' },
},
},
},
lastEditedAt: { type: 'string', description: 'ISO 8601 last edited timestamp', optional: true },
lastPublishedAt: {
type: 'string',
description: 'ISO 8601 last published timestamp',
optional: true,
},
createdAt: { type: 'string', description: 'ISO 8601 creation timestamp' },
archivedAt: { type: 'string', description: 'ISO 8601 archived timestamp', optional: true },
trashedAt: { type: 'string', description: 'ISO 8601 trashed timestamp', optional: true },
} as const satisfies Record<string, OutputProperty>
/**
* Output definition for run creation responses.
* POST /v1/projects/{projectId}/runs returns projectVersion but no status.
*/
export const HEX_RUN_OUTPUT_PROPERTIES = {
projectId: { type: 'string', description: 'Project UUID' },
runId: { type: 'string', description: 'Run UUID' },
runUrl: { type: 'string', description: 'URL to view the run' },
runStatusUrl: { type: 'string', description: 'URL to check run status' },
traceId: { type: 'string', description: 'Trace ID for debugging', optional: true },
projectVersion: { type: 'number', description: 'Project version number', optional: true },
} as const satisfies Record<string, OutputProperty>
/**
* Output definition for run status responses.
* GET /v1/projects/{projectId}/runs/{runId} returns full run details.
*/
export const HEX_RUN_STATUS_OUTPUT_PROPERTIES = {
projectId: { type: 'string', description: 'Project UUID' },
runId: { type: 'string', description: 'Run UUID' },
runUrl: { type: 'string', description: 'URL to view the run' },
status: {
type: 'string',
description:
'Run status (PENDING, RUNNING, COMPLETED, ERRORED, KILLED, UNABLE_TO_ALLOCATE_KERNEL)',
},
startTime: { type: 'string', description: 'ISO 8601 run start time', optional: true },
endTime: { type: 'string', description: 'ISO 8601 run end time', optional: true },
elapsedTime: { type: 'number', description: 'Elapsed time in seconds', optional: true },
traceId: { type: 'string', description: 'Trace ID for debugging', optional: true },
projectVersion: { type: 'number', description: 'Project version number', optional: true },
} as const satisfies Record<string, OutputProperty>
export interface HexListProjectsParams {
apiKey: string
limit?: number
includeArchived?: boolean
includeComponents?: boolean
includeTrashed?: boolean
statusFilter?: string
creatorEmail?: string
ownerEmail?: string
collectionId?: string
categories?: string
sortBy?: string
sortDirection?: string
after?: string
before?: string
}
export interface HexListProjectsResponse extends ToolResponse {
output: {
projects: Array<{
id: string
title: string
description: string | null
status: { name: string } | null
type: string
creator: { email: string } | null
owner: { email: string } | null
categories: Array<{ name: string; description: string }>
lastEditedAt: string | null
lastPublishedAt: string | null
createdAt: string
archivedAt: string | null
trashedAt: string | null
}>
total: number
after: string | null
before: string | null
}
}
export interface HexGetProjectParams {
apiKey: string
projectId: string
}
export interface HexGetProjectResponse extends ToolResponse {
output: {
id: string
title: string
description: string | null
status: { name: string } | null
type: string
creator: { email: string } | null
owner: { email: string } | null
categories: Array<{ name: string; description: string }>
lastEditedAt: string | null
lastPublishedAt: string | null
createdAt: string
archivedAt: string | null
trashedAt: string | null
}
}
export interface HexRunProjectParams {
apiKey: string
projectId: string
inputParams?: string
dryRun?: boolean
updateCache?: boolean
updatePublishedResults?: boolean
useCachedSqlResults?: boolean
viewId?: string
notifications?: string
}
export interface HexRunProjectResponse extends ToolResponse {
output: {
projectId: string
runId: string
runUrl: string
runStatusUrl: string
traceId: string | null
projectVersion: number | null
}
}
export interface HexGetRunStatusParams {
apiKey: string
projectId: string
runId: string
}
export interface HexGetRunStatusResponse extends ToolResponse {
output: {
projectId: string
runId: string
runUrl: string | null
status: string
startTime: string | null
endTime: string | null
elapsedTime: number | null
traceId: string | null
projectVersion: number | null
}
}
export interface HexCancelRunParams {
apiKey: string
projectId: string
runId: string
}
export interface HexCancelRunResponse extends ToolResponse {
output: {
success: boolean
projectId: string
runId: string
}
}
export interface HexGetProjectRunsParams {
apiKey: string
projectId: string
limit?: number
offset?: number
statusFilter?: string
runTriggerFilter?: string
}
export interface HexGetProjectRunsResponse extends ToolResponse {
output: {
runs: Array<{
projectId: string
runId: string
runUrl: string | null
status: string
startTime: string | null
endTime: string | null
elapsedTime: number | null
traceId: string | null
projectVersion: number | null
}>
total: number
traceId: string | null
nextPage: string | null
previousPage: string | null
}
}
export interface HexUpdateProjectParams {
apiKey: string
projectId: string
status: string
}
export interface HexUpdateProjectResponse extends ToolResponse {
output: {
id: string
title: string
description: string | null
status: { name: string } | null
type: string
creator: { email: string } | null
owner: { email: string } | null
categories: Array<{ name: string; description: string }>
lastEditedAt: string | null
lastPublishedAt: string | null
createdAt: string
archivedAt: string | null
trashedAt: string | null
}
}
export interface HexListUsersParams {
apiKey: string
limit?: number
sortBy?: string
sortDirection?: string
groupId?: string
userIds?: string
after?: string
before?: string
}
export interface HexListUsersResponse extends ToolResponse {
output: {
users: Array<{
id: string
name: string
email: string
role: string
lastLoginDate: string | null
}>
total: number
after: string | null
before: string | null
}
}
export interface HexListCollectionsParams {
apiKey: string
limit?: number
sortBy?: string
after?: string
before?: string
}
export interface HexListCollectionsResponse extends ToolResponse {
output: {
collections: Array<{
id: string
name: string
description: string | null
creator: { email: string; id: string } | null
}>
total: number
after: string | null
before: string | null
}
}
export interface HexListDataConnectionsParams {
apiKey: string
limit?: number
sortBy?: string
sortDirection?: string
after?: string
before?: string
}
export interface HexListDataConnectionsResponse extends ToolResponse {
output: {
connections: Array<{
id: string
name: string
type: string
description: string | null
connectViaSsh: boolean | null
includeMagic: boolean | null
allowWritebackCells: boolean | null
}>
total: number
after: string | null
before: string | null
}
}
export interface HexGetQueriedTablesParams {
apiKey: string
projectId: string
limit?: number
}
export interface HexGetQueriedTablesResponse extends ToolResponse {
output: {
tables: Array<{
dataConnectionId: string | null
dataConnectionName: string | null
tableName: string | null
}>
total: number
}
}
export interface HexListGroupsParams {
apiKey: string
limit?: number
sortBy?: string
sortDirection?: string
after?: string
before?: string
}
export interface HexListGroupsResponse extends ToolResponse {
output: {
groups: Array<{
id: string
name: string
createdAt: string | null
}>
total: number
after: string | null
before: string | null
}
}
export interface HexGetGroupParams {
apiKey: string
groupId: string
}
export interface HexGetGroupResponse extends ToolResponse {
output: {
id: string
name: string
createdAt: string | null
}
}
export interface HexGetDataConnectionParams {
apiKey: string
dataConnectionId: string
}
export interface HexGetDataConnectionResponse extends ToolResponse {
output: {
id: string
name: string
type: string
description: string | null
connectViaSsh: boolean | null
includeMagic: boolean | null
allowWritebackCells: boolean | null
}
}
export interface HexGetCollectionParams {
apiKey: string
collectionId: string
}
export interface HexGetCollectionResponse extends ToolResponse {
output: {
id: string
name: string
description: string | null
creator: { email: string; id: string } | null
}
}
export interface HexCreateCollectionParams {
apiKey: string
name: string
description?: string
}
export interface HexCreateCollectionResponse extends ToolResponse {
output: {
id: string
name: string
description: string | null
creator: { email: string; id: string } | null
}
}
export interface HexUpdateCollectionParams {
apiKey: string
collectionId: string
name?: string
description?: string
}
export interface HexUpdateCollectionResponse extends ToolResponse {
output: {
id: string
name: string
description: string | null
creator: { email: string; id: string } | null
}
}
export interface HexCreateGroupParams {
apiKey: string
name: string
memberUserIds?: string
}
export interface HexCreateGroupResponse extends ToolResponse {
output: {
id: string
name: string
createdAt: string | null
}
}
export interface HexUpdateGroupParams {
apiKey: string
groupId: string
name?: string
addUserIds?: string
removeUserIds?: string
}
export interface HexUpdateGroupResponse extends ToolResponse {
output: {
id: string
name: string
createdAt: string | null
}
}
export interface HexDeleteGroupParams {
apiKey: string
groupId: string
}
export interface HexDeleteGroupResponse extends ToolResponse {
output: {
success: boolean
groupId: string
}
}
export interface HexDeactivateUserParams {
apiKey: string
userId: string
}
export interface HexDeactivateUserResponse extends ToolResponse {
output: {
success: boolean
userId: string
}
}
export type HexResponse =
| HexListProjectsResponse
| HexGetProjectResponse
| HexRunProjectResponse
| HexGetRunStatusResponse
| HexCancelRunResponse
| HexGetProjectRunsResponse
| HexUpdateProjectResponse
| HexListUsersResponse
| HexListCollectionsResponse
| HexListDataConnectionsResponse
| HexGetQueriedTablesResponse
| HexListGroupsResponse
| HexGetGroupResponse
| HexGetDataConnectionResponse
| HexGetCollectionResponse
| HexCreateCollectionResponse
| HexUpdateCollectionResponse
| HexCreateGroupResponse
| HexUpdateGroupResponse
| HexDeleteGroupResponse
| HexDeactivateUserResponse
+85
View File
@@ -0,0 +1,85 @@
import type { HexUpdateCollectionParams, HexUpdateCollectionResponse } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const updateCollectionTool: ToolConfig<
HexUpdateCollectionParams,
HexUpdateCollectionResponse
> = {
id: 'hex_update_collection',
name: 'Hex Update Collection',
description: 'Update the name or description of an existing Hex collection.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
collectionId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The UUID of the collection to update',
},
name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New name for the collection',
},
description: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New description for the collection',
},
},
request: {
url: (params) => `https://app.hex.tech/api/v1/collections/${params.collectionId.trim()}`,
method: 'PATCH',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
body: (params) => {
const body: Record<string, unknown> = {}
if (params.name) body.name = params.name
if (params.description !== undefined) body.description = params.description
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
id: data.id ?? null,
name: data.name ?? null,
description: data.description ?? null,
creator: data.creator
? { email: data.creator.email ?? null, id: data.creator.id ?? null }
: null,
},
}
},
outputs: {
id: { type: 'string', description: 'Collection UUID' },
name: { type: 'string', description: 'Collection name' },
description: { type: 'string', description: 'Collection description', optional: true },
creator: {
type: 'object',
description: 'Collection creator',
optional: true,
properties: {
email: { type: 'string', description: 'Creator email' },
id: { type: 'string', description: 'Creator UUID' },
},
},
},
}
+106
View File
@@ -0,0 +1,106 @@
import type { HexUpdateGroupParams, HexUpdateGroupResponse } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const updateGroupTool: ToolConfig<HexUpdateGroupParams, HexUpdateGroupResponse> = {
id: 'hex_update_group',
name: 'Hex Update Group',
description: 'Rename a Hex group or add/remove members from it.',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
groupId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The UUID of the group to update',
},
name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New name for the group',
},
addUserIds: {
type: 'json',
required: false,
visibility: 'user-or-llm',
description: 'JSON array of user UUIDs to add to the group (e.g., ["uuid1", "uuid2"])',
},
removeUserIds: {
type: 'json',
required: false,
visibility: 'user-or-llm',
description: 'JSON array of user UUIDs to remove from the group (e.g., ["uuid1", "uuid2"])',
},
},
request: {
url: (params) => `https://app.hex.tech/api/v1/groups/${params.groupId.trim()}`,
method: 'PATCH',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
body: (params) => {
const body: Record<string, unknown> = {}
if (params.name) body.name = params.name
const parseIds = (value: unknown): string[] => {
let parsed: unknown
try {
parsed = typeof value === 'string' ? JSON.parse(value) : value
} catch {
throw new Error(
'addUserIds/removeUserIds must be a valid JSON array of user UUID strings'
)
}
if (!Array.isArray(parsed) || !parsed.every((id) => typeof id === 'string')) {
throw new Error(
'addUserIds/removeUserIds must be a valid JSON array of user UUID strings'
)
}
return parsed
}
if (params.addUserIds || params.removeUserIds) {
const members: Record<string, unknown> = {}
if (params.addUserIds) {
members.add = { users: parseIds(params.addUserIds).map((id) => ({ id: id.trim() })) }
}
if (params.removeUserIds) {
members.remove = {
users: parseIds(params.removeUserIds).map((id) => ({ id: id.trim() })),
}
}
body.members = members
}
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
id: data.id ?? null,
name: data.name ?? null,
createdAt: data.createdAt ?? null,
},
}
},
outputs: {
id: { type: 'string', description: 'Group UUID' },
name: { type: 'string', description: 'Group name' },
createdAt: { type: 'string', description: 'Creation timestamp' },
},
}
+118
View File
@@ -0,0 +1,118 @@
import type { HexUpdateProjectParams, HexUpdateProjectResponse } from '@/tools/hex/types'
import type { ToolConfig } from '@/tools/types'
export const updateProjectTool: ToolConfig<HexUpdateProjectParams, HexUpdateProjectResponse> = {
id: 'hex_update_project',
name: 'Hex Update Project',
description:
'Update a Hex project status label (e.g., endorsement or custom workspace statuses).',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Hex API token (Personal or Workspace)',
},
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The UUID of the Hex project to update',
},
status: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'New project status name (custom workspace status label)',
},
},
request: {
url: (params) => `https://app.hex.tech/api/v1/projects/${params.projectId.trim()}`,
method: 'PATCH',
headers: (params) => ({
Authorization: `Bearer ${params.apiKey}`,
'Content-Type': 'application/json',
}),
body: (params) => ({
status: params.status,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
id: data.id ?? null,
title: data.title ?? null,
description: data.description ?? null,
status: data.status ? { name: data.status.name ?? null } : null,
type: data.type ?? null,
creator: data.creator ? { email: data.creator.email ?? null } : null,
owner: data.owner ? { email: data.owner.email ?? null } : null,
categories: Array.isArray(data.categories)
? data.categories.map((c: Record<string, string>) => ({
name: c.name ?? null,
description: c.description ?? null,
}))
: [],
lastEditedAt: data.lastEditedAt ?? null,
lastPublishedAt: data.lastPublishedAt ?? null,
createdAt: data.createdAt ?? null,
archivedAt: data.archivedAt ?? null,
trashedAt: data.trashedAt ?? null,
},
}
},
outputs: {
id: { type: 'string', description: 'Project UUID' },
title: { type: 'string', description: 'Project title' },
description: { type: 'string', description: 'Project description', optional: true },
status: {
type: 'object',
description: 'Updated project status',
properties: {
name: { type: 'string', description: 'Status name (e.g., PUBLISHED, DRAFT)' },
},
},
type: { type: 'string', description: 'Project type (PROJECT or COMPONENT)' },
creator: {
type: 'object',
description: 'Project creator',
optional: true,
properties: {
email: { type: 'string', description: 'Creator email' },
},
},
owner: {
type: 'object',
description: 'Project owner',
optional: true,
properties: {
email: { type: 'string', description: 'Owner email' },
},
},
categories: {
type: 'array',
description: 'Project categories',
optional: true,
items: {
type: 'object',
properties: {
name: { type: 'string', description: 'Category name' },
description: { type: 'string', description: 'Category description' },
},
},
},
lastEditedAt: { type: 'string', description: 'Last edited timestamp', optional: true },
lastPublishedAt: { type: 'string', description: 'Last published timestamp', optional: true },
createdAt: { type: 'string', description: 'Creation timestamp' },
archivedAt: { type: 'string', description: 'Archived timestamp', optional: true },
trashedAt: { type: 'string', description: 'Trashed timestamp', optional: true },
},
}