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
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:
@@ -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' },
|
||||
},
|
||||
}
|
||||
@@ -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' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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' },
|
||||
},
|
||||
}
|
||||
@@ -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' },
|
||||
},
|
||||
}
|
||||
@@ -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' },
|
||||
},
|
||||
}
|
||||
@@ -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' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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' },
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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' },
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
}
|
||||
@@ -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
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
}
|
||||
@@ -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
|
||||
@@ -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' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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' },
|
||||
},
|
||||
}
|
||||
@@ -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 },
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user