mirror of
https://github.com/simstudioai/sim.git
synced 2026-02-19 02:34:37 -05:00
feat(tools): added vercel block & tools (#3252)
* feat(vercel): add complete Vercel integration with 42 API tools Add Vercel platform management integration covering deployments, projects, environment variables, domains, DNS records, aliases, edge configs, and team/user management. All tools use API key authentication with Bearer tokens. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(vercel): add webhook and deployment check tools Add 8 new Vercel API tools: - Webhooks: list, create, delete - Deployment Checks: create, get, list, update, rerequest Brings total Vercel tools to 50. * fix(vercel): expand all object and array output definitions Expand unexpanded output types: - get_deployment: meta and gitSource objects now have properties - list_deployment_files: children array now has items definition - get_team: teamRoles and teamPermissions arrays now have items Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * update icon size, update docs --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5532,3 +5532,18 @@ export function OnePasswordIcon(props: SVGProps<SVGSVGElement>) {
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export function VercelIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
{...props}
|
||||
viewBox='0 0 256 222'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
preserveAspectRatio='xMidYMid'
|
||||
>
|
||||
<g transform='translate(19.2 16.63) scale(0.85)'>
|
||||
<polygon fill='#fafafa' points='128 0 256 221.705007 0 221.705007' />
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -125,6 +125,7 @@ import {
|
||||
TTSIcon,
|
||||
TwilioIcon,
|
||||
TypeformIcon,
|
||||
VercelIcon,
|
||||
VideoIcon,
|
||||
WealthboxIcon,
|
||||
WebflowIcon,
|
||||
@@ -262,6 +263,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
|
||||
twilio_sms: TwilioIcon,
|
||||
twilio_voice: TwilioIcon,
|
||||
typeform: TypeformIcon,
|
||||
vercel: VercelIcon,
|
||||
video_generator_v2: VideoIcon,
|
||||
vision_v2: EyeIcon,
|
||||
wealthbox: WealthboxIcon,
|
||||
|
||||
@@ -122,6 +122,7 @@
|
||||
"twilio_sms",
|
||||
"twilio_voice",
|
||||
"typeform",
|
||||
"vercel",
|
||||
"video_generator",
|
||||
"vision",
|
||||
"wealthbox",
|
||||
|
||||
1391
apps/docs/content/docs/en/tools/vercel.mdx
Normal file
1391
apps/docs/content/docs/en/tools/vercel.mdx
Normal file
File diff suppressed because it is too large
Load Diff
1007
apps/sim/blocks/blocks/vercel.ts
Normal file
1007
apps/sim/blocks/blocks/vercel.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -146,6 +146,7 @@ import { TwilioSMSBlock } from '@/blocks/blocks/twilio'
|
||||
import { TwilioVoiceBlock } from '@/blocks/blocks/twilio_voice'
|
||||
import { TypeformBlock } from '@/blocks/blocks/typeform'
|
||||
import { VariablesBlock } from '@/blocks/blocks/variables'
|
||||
import { VercelBlock } from '@/blocks/blocks/vercel'
|
||||
import { VideoGeneratorBlock, VideoGeneratorV2Block } from '@/blocks/blocks/video_generator'
|
||||
import { VisionBlock, VisionV2Block } from '@/blocks/blocks/vision'
|
||||
import { WaitBlock } from '@/blocks/blocks/wait'
|
||||
@@ -330,6 +331,7 @@ export const registry: Record<string, BlockConfig> = {
|
||||
twilio_sms: TwilioSMSBlock,
|
||||
twilio_voice: TwilioVoiceBlock,
|
||||
typeform: TypeformBlock,
|
||||
vercel: VercelBlock,
|
||||
variables: VariablesBlock,
|
||||
video_generator: VideoGeneratorBlock,
|
||||
video_generator_v2: VideoGeneratorV2Block,
|
||||
|
||||
@@ -5532,3 +5532,18 @@ export function OnePasswordIcon(props: SVGProps<SVGSVGElement>) {
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export function VercelIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
{...props}
|
||||
viewBox='0 0 256 222'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
preserveAspectRatio='xMidYMid'
|
||||
>
|
||||
<g transform='translate(19.2 16.63) scale(0.85)'>
|
||||
<polygon fill='#fafafa' points='128 0 256 221.705007 0 221.705007' />
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1693,6 +1693,58 @@ import {
|
||||
typeformUpdateFormTool,
|
||||
} from '@/tools/typeform'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
vercelAddDomainTool,
|
||||
vercelAddProjectDomainTool,
|
||||
vercelCancelDeploymentTool,
|
||||
vercelCreateAliasTool,
|
||||
vercelCreateCheckTool,
|
||||
vercelCreateDeploymentTool,
|
||||
vercelCreateDnsRecordTool,
|
||||
vercelCreateEdgeConfigTool,
|
||||
vercelCreateEnvVarTool,
|
||||
vercelCreateProjectTool,
|
||||
vercelCreateWebhookTool,
|
||||
vercelDeleteAliasTool,
|
||||
vercelDeleteDeploymentTool,
|
||||
vercelDeleteDnsRecordTool,
|
||||
vercelDeleteDomainTool,
|
||||
vercelDeleteEnvVarTool,
|
||||
vercelDeleteProjectTool,
|
||||
vercelDeleteWebhookTool,
|
||||
vercelGetAliasTool,
|
||||
vercelGetCheckTool,
|
||||
vercelGetDeploymentEventsTool,
|
||||
vercelGetDeploymentTool,
|
||||
vercelGetDomainConfigTool,
|
||||
vercelGetDomainTool,
|
||||
vercelGetEdgeConfigItemsTool,
|
||||
vercelGetEdgeConfigTool,
|
||||
vercelGetEnvVarsTool,
|
||||
vercelGetProjectTool,
|
||||
vercelGetTeamTool,
|
||||
vercelGetUserTool,
|
||||
vercelListAliasesTool,
|
||||
vercelListChecksTool,
|
||||
vercelListDeploymentFilesTool,
|
||||
vercelListDeploymentsTool,
|
||||
vercelListDnsRecordsTool,
|
||||
vercelListDomainsTool,
|
||||
vercelListEdgeConfigsTool,
|
||||
vercelListProjectDomainsTool,
|
||||
vercelListProjectsTool,
|
||||
vercelListTeamMembersTool,
|
||||
vercelListTeamsTool,
|
||||
vercelListWebhooksTool,
|
||||
vercelPauseProjectTool,
|
||||
vercelRemoveProjectDomainTool,
|
||||
vercelRerequestCheckTool,
|
||||
vercelUnpauseProjectTool,
|
||||
vercelUpdateCheckTool,
|
||||
vercelUpdateEdgeConfigItemsTool,
|
||||
vercelUpdateEnvVarTool,
|
||||
vercelUpdateProjectTool,
|
||||
} from '@/tools/vercel'
|
||||
import {
|
||||
falaiVideoTool,
|
||||
lumaVideoTool,
|
||||
@@ -2700,6 +2752,66 @@ export const tools: Record<string, ToolConfig> = {
|
||||
trello_update_card: trelloUpdateCardTool,
|
||||
trello_get_actions: trelloGetActionsTool,
|
||||
trello_add_comment: trelloAddCommentTool,
|
||||
// Vercel - Deployments
|
||||
vercel_list_deployments: vercelListDeploymentsTool,
|
||||
vercel_get_deployment: vercelGetDeploymentTool,
|
||||
vercel_create_deployment: vercelCreateDeploymentTool,
|
||||
vercel_cancel_deployment: vercelCancelDeploymentTool,
|
||||
vercel_delete_deployment: vercelDeleteDeploymentTool,
|
||||
vercel_get_deployment_events: vercelGetDeploymentEventsTool,
|
||||
vercel_list_deployment_files: vercelListDeploymentFilesTool,
|
||||
// Vercel - Projects
|
||||
vercel_list_projects: vercelListProjectsTool,
|
||||
vercel_get_project: vercelGetProjectTool,
|
||||
vercel_create_project: vercelCreateProjectTool,
|
||||
vercel_update_project: vercelUpdateProjectTool,
|
||||
vercel_delete_project: vercelDeleteProjectTool,
|
||||
vercel_pause_project: vercelPauseProjectTool,
|
||||
vercel_unpause_project: vercelUnpauseProjectTool,
|
||||
vercel_list_project_domains: vercelListProjectDomainsTool,
|
||||
vercel_add_project_domain: vercelAddProjectDomainTool,
|
||||
vercel_remove_project_domain: vercelRemoveProjectDomainTool,
|
||||
// Vercel - Environment Variables
|
||||
vercel_get_env_vars: vercelGetEnvVarsTool,
|
||||
vercel_create_env_var: vercelCreateEnvVarTool,
|
||||
vercel_update_env_var: vercelUpdateEnvVarTool,
|
||||
vercel_delete_env_var: vercelDeleteEnvVarTool,
|
||||
// Vercel - Domains
|
||||
vercel_list_domains: vercelListDomainsTool,
|
||||
vercel_get_domain: vercelGetDomainTool,
|
||||
vercel_add_domain: vercelAddDomainTool,
|
||||
vercel_delete_domain: vercelDeleteDomainTool,
|
||||
vercel_get_domain_config: vercelGetDomainConfigTool,
|
||||
// Vercel - DNS
|
||||
vercel_list_dns_records: vercelListDnsRecordsTool,
|
||||
vercel_create_dns_record: vercelCreateDnsRecordTool,
|
||||
vercel_delete_dns_record: vercelDeleteDnsRecordTool,
|
||||
// Vercel - Aliases
|
||||
vercel_list_aliases: vercelListAliasesTool,
|
||||
vercel_get_alias: vercelGetAliasTool,
|
||||
vercel_create_alias: vercelCreateAliasTool,
|
||||
vercel_delete_alias: vercelDeleteAliasTool,
|
||||
// Vercel - Edge Config
|
||||
vercel_list_edge_configs: vercelListEdgeConfigsTool,
|
||||
vercel_get_edge_config: vercelGetEdgeConfigTool,
|
||||
vercel_create_edge_config: vercelCreateEdgeConfigTool,
|
||||
vercel_get_edge_config_items: vercelGetEdgeConfigItemsTool,
|
||||
vercel_update_edge_config_items: vercelUpdateEdgeConfigItemsTool,
|
||||
// Vercel - Teams & User
|
||||
vercel_list_teams: vercelListTeamsTool,
|
||||
vercel_get_team: vercelGetTeamTool,
|
||||
vercel_list_team_members: vercelListTeamMembersTool,
|
||||
vercel_get_user: vercelGetUserTool,
|
||||
// Webhooks
|
||||
vercel_list_webhooks: vercelListWebhooksTool,
|
||||
vercel_create_webhook: vercelCreateWebhookTool,
|
||||
vercel_delete_webhook: vercelDeleteWebhookTool,
|
||||
// Checks
|
||||
vercel_create_check: vercelCreateCheckTool,
|
||||
vercel_get_check: vercelGetCheckTool,
|
||||
vercel_list_checks: vercelListChecksTool,
|
||||
vercel_update_check: vercelUpdateCheckTool,
|
||||
vercel_rerequest_check: vercelRerequestCheckTool,
|
||||
twilio_send_sms: sendSMSTool,
|
||||
twilio_voice_make_call: makeCallTool,
|
||||
twilio_voice_list_calls: listCallsTool,
|
||||
|
||||
84
apps/sim/tools/vercel/add_domain.ts
Normal file
84
apps/sim/tools/vercel/add_domain.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelAddDomainParams, VercelAddDomainResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelAddDomainTool: ToolConfig<VercelAddDomainParams, VercelAddDomainResponse> = {
|
||||
id: 'vercel_add_domain',
|
||||
name: 'Vercel Add Domain',
|
||||
description: 'Add a new domain to a Vercel account or team',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The domain name to add',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelAddDomainParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v7/domains${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params: VercelAddDomainParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: VercelAddDomainParams) => ({
|
||||
method: 'add',
|
||||
name: params.name.trim(),
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const d = data.domain ?? data
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: d.id ?? null,
|
||||
name: d.name ?? null,
|
||||
verified: d.verified ?? false,
|
||||
createdAt: d.createdAt ?? null,
|
||||
serviceType: d.serviceType ?? null,
|
||||
nameservers: d.nameservers ?? [],
|
||||
intendedNameservers: d.intendedNameservers ?? [],
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Domain ID' },
|
||||
name: { type: 'string', description: 'Domain name' },
|
||||
verified: { type: 'boolean', description: 'Whether domain is verified' },
|
||||
createdAt: { type: 'number', description: 'Creation timestamp' },
|
||||
serviceType: { type: 'string', description: 'Service type (zeit.world, external, na)' },
|
||||
nameservers: {
|
||||
type: 'array',
|
||||
description: 'Current nameservers',
|
||||
items: { type: 'string' },
|
||||
},
|
||||
intendedNameservers: {
|
||||
type: 'array',
|
||||
description: 'Intended nameservers',
|
||||
items: { type: 'string' },
|
||||
},
|
||||
},
|
||||
}
|
||||
113
apps/sim/tools/vercel/add_project_domain.ts
Normal file
113
apps/sim/tools/vercel/add_project_domain.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
VercelAddProjectDomainParams,
|
||||
VercelAddProjectDomainResponse,
|
||||
} from '@/tools/vercel/types'
|
||||
|
||||
export const vercelAddProjectDomainTool: ToolConfig<
|
||||
VercelAddProjectDomainParams,
|
||||
VercelAddProjectDomainResponse
|
||||
> = {
|
||||
id: 'vercel_add_project_domain',
|
||||
name: 'Vercel Add Project Domain',
|
||||
description: 'Add a domain to a Vercel project',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or name',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Domain name to add',
|
||||
},
|
||||
redirect: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Target domain for redirect',
|
||||
},
|
||||
redirectStatusCode: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'HTTP status code for redirect (301, 302, 307, 308)',
|
||||
},
|
||||
gitBranch: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Git branch to link the domain to',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelAddProjectDomainParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v10/projects/${params.projectId.trim()}/domains${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params: VercelAddProjectDomainParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: VercelAddProjectDomainParams) => {
|
||||
const body: Record<string, unknown> = { name: params.domain.trim() }
|
||||
if (params.redirect) body.redirect = params.redirect.trim()
|
||||
if (params.redirectStatusCode) body.redirectStatusCode = params.redirectStatusCode
|
||||
if (params.gitBranch) body.gitBranch = params.gitBranch.trim()
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
name: data.name,
|
||||
apexName: data.apexName,
|
||||
verified: data.verified,
|
||||
gitBranch: data.gitBranch ?? null,
|
||||
redirect: data.redirect ?? null,
|
||||
redirectStatusCode: data.redirectStatusCode ?? null,
|
||||
createdAt: data.createdAt,
|
||||
updatedAt: data.updatedAt,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
name: { type: 'string', description: 'Domain name' },
|
||||
apexName: { type: 'string', description: 'Apex domain name' },
|
||||
verified: { type: 'boolean', description: 'Whether the domain is verified' },
|
||||
gitBranch: { type: 'string', description: 'Git branch for the domain', optional: true },
|
||||
redirect: { type: 'string', description: 'Redirect target domain', optional: true },
|
||||
redirectStatusCode: {
|
||||
type: 'number',
|
||||
description: 'HTTP status code for redirect (301, 302, 307, 308)',
|
||||
optional: true,
|
||||
},
|
||||
createdAt: { type: 'number', description: 'Creation timestamp' },
|
||||
updatedAt: { type: 'number', description: 'Last updated timestamp' },
|
||||
},
|
||||
}
|
||||
83
apps/sim/tools/vercel/cancel_deployment.ts
Normal file
83
apps/sim/tools/vercel/cancel_deployment.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
VercelCancelDeploymentParams,
|
||||
VercelCancelDeploymentResponse,
|
||||
} from '@/tools/vercel/types'
|
||||
|
||||
export const vercelCancelDeploymentTool: ToolConfig<
|
||||
VercelCancelDeploymentParams,
|
||||
VercelCancelDeploymentResponse
|
||||
> = {
|
||||
id: 'vercel_cancel_deployment',
|
||||
name: 'Vercel Cancel Deployment',
|
||||
description: 'Cancel a running Vercel deployment',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
deploymentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The deployment ID to cancel',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelCancelDeploymentParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v12/deployments/${params.deploymentId.trim()}/cancel${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'PATCH',
|
||||
headers: (params: VercelCancelDeploymentParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id ?? data.uid,
|
||||
name: data.name ?? null,
|
||||
state: data.readyState ?? data.state ?? 'CANCELED',
|
||||
url: data.url ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'Deployment ID',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Deployment name',
|
||||
},
|
||||
state: {
|
||||
type: 'string',
|
||||
description: 'Deployment state after cancellation',
|
||||
},
|
||||
url: {
|
||||
type: 'string',
|
||||
description: 'Deployment URL',
|
||||
},
|
||||
},
|
||||
}
|
||||
87
apps/sim/tools/vercel/create_alias.ts
Normal file
87
apps/sim/tools/vercel/create_alias.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelCreateAliasParams, VercelCreateAliasResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelCreateAliasTool: ToolConfig<VercelCreateAliasParams, VercelCreateAliasResponse> =
|
||||
{
|
||||
id: 'vercel_create_alias',
|
||||
name: 'Vercel Create Alias',
|
||||
description: 'Assign an alias (domain/subdomain) to a deployment',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
deploymentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Deployment ID to assign the alias to',
|
||||
},
|
||||
alias: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The domain or subdomain to assign as an alias',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelCreateAliasParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v2/deployments/${params.deploymentId.trim()}/aliases${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params: VercelCreateAliasParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: VercelCreateAliasParams) => ({
|
||||
alias: params.alias.trim(),
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
uid: data.uid ?? null,
|
||||
alias: data.alias ?? null,
|
||||
created: data.created ?? null,
|
||||
oldDeploymentId: data.oldDeploymentId ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
uid: {
|
||||
type: 'string',
|
||||
description: 'Alias ID',
|
||||
},
|
||||
alias: {
|
||||
type: 'string',
|
||||
description: 'Alias hostname',
|
||||
},
|
||||
created: {
|
||||
type: 'string',
|
||||
description: 'Creation timestamp as ISO 8601 date-time string',
|
||||
},
|
||||
oldDeploymentId: {
|
||||
type: 'string',
|
||||
description: 'ID of the previously aliased deployment, if the alias was reassigned',
|
||||
},
|
||||
},
|
||||
}
|
||||
141
apps/sim/tools/vercel/create_check.ts
Normal file
141
apps/sim/tools/vercel/create_check.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelCheckResponse, VercelCreateCheckParams } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelCreateCheckTool: ToolConfig<VercelCreateCheckParams, VercelCheckResponse> = {
|
||||
id: 'vercel_create_check',
|
||||
name: 'Vercel Create Check',
|
||||
description: 'Create a new deployment check',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
deploymentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Deployment ID to create the check for',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Name of the check (max 100 characters)',
|
||||
},
|
||||
blocking: {
|
||||
type: 'boolean',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Whether the check blocks the deployment',
|
||||
},
|
||||
path: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page path being checked',
|
||||
},
|
||||
detailsUrl: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'URL with details about the check',
|
||||
},
|
||||
externalId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'External identifier for the check',
|
||||
},
|
||||
rerequestable: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Whether the check can be rerequested',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelCreateCheckParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v1/deployments/${params.deploymentId.trim()}/checks${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params: VercelCreateCheckParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: VercelCreateCheckParams) => {
|
||||
const body: Record<string, unknown> = {
|
||||
name: params.name.trim(),
|
||||
blocking: params.blocking,
|
||||
}
|
||||
if (params.path) body.path = params.path
|
||||
if (params.detailsUrl) body.detailsUrl = params.detailsUrl
|
||||
if (params.externalId) body.externalId = params.externalId
|
||||
if (params.rerequestable !== undefined) body.rerequestable = params.rerequestable
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
status: data.status ?? 'registered',
|
||||
conclusion: data.conclusion ?? null,
|
||||
blocking: data.blocking ?? false,
|
||||
deploymentId: data.deploymentId,
|
||||
integrationId: data.integrationId ?? null,
|
||||
externalId: data.externalId ?? null,
|
||||
detailsUrl: data.detailsUrl ?? null,
|
||||
path: data.path ?? null,
|
||||
rerequestable: data.rerequestable ?? false,
|
||||
createdAt: data.createdAt,
|
||||
updatedAt: data.updatedAt,
|
||||
startedAt: data.startedAt ?? null,
|
||||
completedAt: data.completedAt ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Check ID' },
|
||||
name: { type: 'string', description: 'Check name' },
|
||||
status: { type: 'string', description: 'Check status: registered, running, or completed' },
|
||||
conclusion: {
|
||||
type: 'string',
|
||||
description: 'Check conclusion: canceled, failed, neutral, succeeded, skipped, or stale',
|
||||
optional: true,
|
||||
},
|
||||
blocking: { type: 'boolean', description: 'Whether the check blocks the deployment' },
|
||||
deploymentId: { type: 'string', description: 'Associated deployment ID' },
|
||||
integrationId: { type: 'string', description: 'Associated integration ID', optional: true },
|
||||
externalId: { type: 'string', description: 'External identifier', optional: true },
|
||||
detailsUrl: { type: 'string', description: 'URL with details about the check', optional: true },
|
||||
path: { type: 'string', description: 'Page path being checked', optional: true },
|
||||
rerequestable: { type: 'boolean', description: 'Whether the check can be rerequested' },
|
||||
createdAt: { type: 'number', description: 'Creation timestamp in milliseconds' },
|
||||
updatedAt: { type: 'number', description: 'Last update timestamp in milliseconds' },
|
||||
startedAt: { type: 'number', description: 'Start timestamp in milliseconds', optional: true },
|
||||
completedAt: {
|
||||
type: 'number',
|
||||
description: 'Completion timestamp in milliseconds',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
136
apps/sim/tools/vercel/create_deployment.ts
Normal file
136
apps/sim/tools/vercel/create_deployment.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
VercelCreateDeploymentParams,
|
||||
VercelCreateDeploymentResponse,
|
||||
} from '@/tools/vercel/types'
|
||||
|
||||
export const vercelCreateDeploymentTool: ToolConfig<
|
||||
VercelCreateDeploymentParams,
|
||||
VercelCreateDeploymentResponse
|
||||
> = {
|
||||
id: 'vercel_create_deployment',
|
||||
name: 'Vercel Create Deployment',
|
||||
description: 'Create a new deployment or redeploy an existing one',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project name for the deployment',
|
||||
},
|
||||
project: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID (overrides name for project lookup)',
|
||||
},
|
||||
deploymentId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Existing deployment ID to redeploy',
|
||||
},
|
||||
target: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Target environment: production, staging, or a custom environment identifier',
|
||||
},
|
||||
gitSource: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON string defining the Git Repository source to deploy (e.g. {"type":"github","repo":"owner/repo","ref":"main"})',
|
||||
},
|
||||
forceNew: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Forces a new deployment even if there is a previous similar deployment (0 or 1)',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelCreateDeploymentParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.forceNew) query.set('forceNew', params.forceNew)
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v13/deployments${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params: VercelCreateDeploymentParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: VercelCreateDeploymentParams) => {
|
||||
const body: Record<string, any> = {
|
||||
name: params.name.trim(),
|
||||
}
|
||||
if (params.project) body.project = params.project.trim()
|
||||
if (params.deploymentId) body.deploymentId = params.deploymentId.trim()
|
||||
if (params.target) body.target = params.target
|
||||
if (params.gitSource) {
|
||||
try {
|
||||
body.gitSource = JSON.parse(params.gitSource)
|
||||
} catch {
|
||||
body.gitSource = params.gitSource
|
||||
}
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
url: data.url ?? '',
|
||||
readyState: data.readyState ?? 'QUEUED',
|
||||
projectId: data.projectId ?? '',
|
||||
createdAt: data.createdAt ?? data.created,
|
||||
alias: data.alias ?? [],
|
||||
target: data.target ?? null,
|
||||
inspectorUrl: data.inspectorUrl ?? '',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Deployment ID' },
|
||||
name: { type: 'string', description: 'Deployment name' },
|
||||
url: { type: 'string', description: 'Unique deployment URL' },
|
||||
readyState: {
|
||||
type: 'string',
|
||||
description: 'Deployment ready state: QUEUED, BUILDING, ERROR, INITIALIZING, READY, CANCELED',
|
||||
},
|
||||
projectId: { type: 'string', description: 'Associated project ID' },
|
||||
createdAt: { type: 'number', description: 'Creation timestamp in milliseconds' },
|
||||
alias: {
|
||||
type: 'array',
|
||||
description: 'Assigned aliases',
|
||||
items: { type: 'string', description: 'Alias domain' },
|
||||
},
|
||||
target: { type: 'string', description: 'Target environment', optional: true },
|
||||
inspectorUrl: { type: 'string', description: 'Vercel inspector URL' },
|
||||
},
|
||||
}
|
||||
107
apps/sim/tools/vercel/create_dns_record.ts
Normal file
107
apps/sim/tools/vercel/create_dns_record.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
VercelCreateDnsRecordParams,
|
||||
VercelCreateDnsRecordResponse,
|
||||
} from '@/tools/vercel/types'
|
||||
|
||||
export const vercelCreateDnsRecordTool: ToolConfig<
|
||||
VercelCreateDnsRecordParams,
|
||||
VercelCreateDnsRecordResponse
|
||||
> = {
|
||||
id: 'vercel_create_dns_record',
|
||||
name: 'Vercel Create DNS Record',
|
||||
description: 'Create a DNS record for a domain in a Vercel account',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The domain name to create the record for',
|
||||
},
|
||||
recordName: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The subdomain or record name',
|
||||
},
|
||||
recordType: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'DNS record type (A, AAAA, ALIAS, CAA, CNAME, HTTPS, MX, SRV, TXT, NS)',
|
||||
},
|
||||
value: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The value of the DNS record',
|
||||
},
|
||||
ttl: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Time to live in seconds',
|
||||
},
|
||||
mxPriority: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Priority for MX records',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelCreateDnsRecordParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v2/domains/${params.domain.trim()}/records${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params: VercelCreateDnsRecordParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: VercelCreateDnsRecordParams) => {
|
||||
const body: Record<string, unknown> = {
|
||||
name: params.recordName.trim(),
|
||||
type: params.recordType.trim(),
|
||||
value: params.value.trim(),
|
||||
}
|
||||
if (params.ttl != null) body.ttl = params.ttl
|
||||
if (params.mxPriority != null) body.mxPriority = params.mxPriority
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const d = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
uid: d.uid ?? null,
|
||||
updated: d.updated ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
uid: { type: 'string', description: 'The DNS record ID' },
|
||||
updated: { type: 'number', description: 'Timestamp of the update' },
|
||||
},
|
||||
}
|
||||
106
apps/sim/tools/vercel/create_edge_config.ts
Normal file
106
apps/sim/tools/vercel/create_edge_config.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
VercelCreateEdgeConfigParams,
|
||||
VercelCreateEdgeConfigResponse,
|
||||
} from '@/tools/vercel/types'
|
||||
|
||||
export const vercelCreateEdgeConfigTool: ToolConfig<
|
||||
VercelCreateEdgeConfigParams,
|
||||
VercelCreateEdgeConfigResponse
|
||||
> = {
|
||||
id: 'vercel_create_edge_config',
|
||||
name: 'Vercel Create Edge Config',
|
||||
description: 'Create a new Edge Config store',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
slug: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The name/slug for the new Edge Config',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelCreateEdgeConfigParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v1/edge-config${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params: VercelCreateEdgeConfigParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: VercelCreateEdgeConfigParams) => ({
|
||||
slug: params.slug.trim(),
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id ?? null,
|
||||
slug: data.slug ?? null,
|
||||
ownerId: data.ownerId ?? null,
|
||||
digest: data.digest ?? null,
|
||||
createdAt: data.createdAt ?? null,
|
||||
updatedAt: data.updatedAt ?? null,
|
||||
itemCount: data.itemCount ?? 0,
|
||||
sizeInBytes: data.sizeInBytes ?? 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'Edge Config ID',
|
||||
},
|
||||
slug: {
|
||||
type: 'string',
|
||||
description: 'Edge Config slug',
|
||||
},
|
||||
ownerId: {
|
||||
type: 'string',
|
||||
description: 'Owner ID',
|
||||
},
|
||||
digest: {
|
||||
type: 'string',
|
||||
description: 'Content digest hash',
|
||||
},
|
||||
createdAt: {
|
||||
type: 'number',
|
||||
description: 'Creation timestamp',
|
||||
},
|
||||
updatedAt: {
|
||||
type: 'number',
|
||||
description: 'Last update timestamp',
|
||||
},
|
||||
itemCount: {
|
||||
type: 'number',
|
||||
description: 'Number of items',
|
||||
},
|
||||
sizeInBytes: {
|
||||
type: 'number',
|
||||
description: 'Size in bytes',
|
||||
},
|
||||
},
|
||||
}
|
||||
145
apps/sim/tools/vercel/create_env_var.ts
Normal file
145
apps/sim/tools/vercel/create_env_var.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelCreateEnvVarParams, VercelCreateEnvVarResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelCreateEnvVarTool: ToolConfig<
|
||||
VercelCreateEnvVarParams,
|
||||
VercelCreateEnvVarResponse
|
||||
> = {
|
||||
id: 'vercel_create_env_var',
|
||||
name: 'Vercel Create Environment Variable',
|
||||
description: 'Create an environment variable for a Vercel project',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or name',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Environment variable name',
|
||||
},
|
||||
value: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Environment variable value',
|
||||
},
|
||||
target: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated list of target environments (production, preview, development)',
|
||||
},
|
||||
type: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Variable type: system, secret, encrypted, plain, or sensitive (default: plain)',
|
||||
},
|
||||
gitBranch: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Git branch to associate with the variable (requires target to include preview)',
|
||||
},
|
||||
comment: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comment to add context to the variable (max 500 characters)',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelCreateEnvVarParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v10/projects/${params.projectId.trim()}/env${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params: VercelCreateEnvVarParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: VercelCreateEnvVarParams) => {
|
||||
const body: Record<string, unknown> = {
|
||||
key: params.key,
|
||||
value: params.value,
|
||||
target: params.target.split(',').map((t) => t.trim()),
|
||||
type: params.type || 'plain',
|
||||
}
|
||||
if (params.gitBranch) body.gitBranch = params.gitBranch
|
||||
if (params.comment) body.comment = params.comment
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const env = data.created ?? data
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: env.id,
|
||||
key: env.key,
|
||||
value: env.value ?? '',
|
||||
type: env.type ?? 'plain',
|
||||
target: env.target ?? [],
|
||||
gitBranch: env.gitBranch ?? null,
|
||||
comment: env.comment ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'Environment variable ID',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
description: 'Variable name',
|
||||
},
|
||||
value: {
|
||||
type: 'string',
|
||||
description: 'Variable value',
|
||||
},
|
||||
type: {
|
||||
type: 'string',
|
||||
description: 'Variable type (secret, system, encrypted, plain, sensitive)',
|
||||
},
|
||||
target: {
|
||||
type: 'array',
|
||||
description: 'Target environments',
|
||||
items: { type: 'string', description: 'Environment name' },
|
||||
},
|
||||
gitBranch: {
|
||||
type: 'string',
|
||||
description: 'Git branch filter',
|
||||
optional: true,
|
||||
},
|
||||
comment: {
|
||||
type: 'string',
|
||||
description: 'Comment providing context for the variable',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
108
apps/sim/tools/vercel/create_project.ts
Normal file
108
apps/sim/tools/vercel/create_project.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelCreateProjectParams, VercelCreateProjectResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelCreateProjectTool: ToolConfig<
|
||||
VercelCreateProjectParams,
|
||||
VercelCreateProjectResponse
|
||||
> = {
|
||||
id: 'vercel_create_project',
|
||||
name: 'Vercel Create Project',
|
||||
description: 'Create a new Vercel project',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project name',
|
||||
},
|
||||
framework: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project framework (e.g. nextjs, remix, vite)',
|
||||
},
|
||||
gitRepository: {
|
||||
type: 'json',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Git repository connection object with type and repo',
|
||||
},
|
||||
buildCommand: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Custom build command',
|
||||
},
|
||||
outputDirectory: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Custom output directory',
|
||||
},
|
||||
installCommand: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Custom install command',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelCreateProjectParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v11/projects${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params: VercelCreateProjectParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: VercelCreateProjectParams) => {
|
||||
const body: Record<string, unknown> = { name: params.name.trim() }
|
||||
if (params.framework) body.framework = params.framework.trim()
|
||||
if (params.gitRepository) body.gitRepository = params.gitRepository
|
||||
if (params.buildCommand) body.buildCommand = params.buildCommand.trim()
|
||||
if (params.outputDirectory) body.outputDirectory = params.outputDirectory.trim()
|
||||
if (params.installCommand) body.installCommand = params.installCommand.trim()
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
framework: data.framework ?? null,
|
||||
createdAt: data.createdAt,
|
||||
updatedAt: data.updatedAt,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Project ID' },
|
||||
name: { type: 'string', description: 'Project name' },
|
||||
framework: { type: 'string', description: 'Project framework', optional: true },
|
||||
createdAt: { type: 'number', description: 'Creation timestamp' },
|
||||
updatedAt: { type: 'number', description: 'Last updated timestamp' },
|
||||
},
|
||||
}
|
||||
105
apps/sim/tools/vercel/create_webhook.ts
Normal file
105
apps/sim/tools/vercel/create_webhook.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelCreateWebhookParams, VercelCreateWebhookResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelCreateWebhookTool: ToolConfig<
|
||||
VercelCreateWebhookParams,
|
||||
VercelCreateWebhookResponse
|
||||
> = {
|
||||
id: 'vercel_create_webhook',
|
||||
name: 'Vercel Create Webhook',
|
||||
description: 'Create a new webhook for a Vercel team',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
url: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Webhook URL (must be https)',
|
||||
},
|
||||
events: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated event names to subscribe to',
|
||||
},
|
||||
projectIds: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated project IDs to scope the webhook to',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to create the webhook for',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelCreateWebhookParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v1/webhooks${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params: VercelCreateWebhookParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: VercelCreateWebhookParams) => {
|
||||
const body: Record<string, any> = {
|
||||
url: params.url.trim(),
|
||||
events: params.events.split(',').map((e) => e.trim()),
|
||||
}
|
||||
if (params.projectIds) {
|
||||
body.projectIds = params.projectIds.split(',').map((p) => p.trim())
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id ?? null,
|
||||
url: data.url ?? null,
|
||||
secret: data.secret ?? null,
|
||||
events: data.events ?? [],
|
||||
ownerId: data.ownerId ?? null,
|
||||
projectIds: data.projectIds ?? [],
|
||||
createdAt: data.createdAt ?? null,
|
||||
updatedAt: data.updatedAt ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Webhook ID' },
|
||||
url: { type: 'string', description: 'Webhook URL' },
|
||||
secret: { type: 'string', description: 'Webhook signing secret' },
|
||||
events: {
|
||||
type: 'array',
|
||||
description: 'Events the webhook listens to',
|
||||
items: { type: 'string', description: 'Event name' },
|
||||
},
|
||||
ownerId: { type: 'string', description: 'Owner ID' },
|
||||
projectIds: {
|
||||
type: 'array',
|
||||
description: 'Associated project IDs',
|
||||
items: { type: 'string', description: 'Project ID' },
|
||||
},
|
||||
createdAt: { type: 'number', description: 'Creation timestamp' },
|
||||
updatedAt: { type: 'number', description: 'Last updated timestamp' },
|
||||
},
|
||||
}
|
||||
62
apps/sim/tools/vercel/delete_alias.ts
Normal file
62
apps/sim/tools/vercel/delete_alias.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelDeleteAliasParams, VercelDeleteAliasResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelDeleteAliasTool: ToolConfig<VercelDeleteAliasParams, VercelDeleteAliasResponse> =
|
||||
{
|
||||
id: 'vercel_delete_alias',
|
||||
name: 'Vercel Delete Alias',
|
||||
description: 'Delete an alias by its ID',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
aliasId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Alias ID to delete',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelDeleteAliasParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v2/aliases/${params.aliasId.trim()}${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'DELETE',
|
||||
headers: (params: VercelDeleteAliasParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
status: data.status ?? 'SUCCESS',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
status: {
|
||||
type: 'string',
|
||||
description: 'Deletion status (SUCCESS)',
|
||||
},
|
||||
},
|
||||
}
|
||||
77
apps/sim/tools/vercel/delete_deployment.ts
Normal file
77
apps/sim/tools/vercel/delete_deployment.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
VercelDeleteDeploymentParams,
|
||||
VercelDeleteDeploymentResponse,
|
||||
} from '@/tools/vercel/types'
|
||||
|
||||
export const vercelDeleteDeploymentTool: ToolConfig<
|
||||
VercelDeleteDeploymentParams,
|
||||
VercelDeleteDeploymentResponse
|
||||
> = {
|
||||
id: 'vercel_delete_deployment',
|
||||
name: 'Vercel Delete Deployment',
|
||||
description: 'Delete a Vercel deployment',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
deploymentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The deployment ID or URL to delete',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelDeleteDeploymentParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const id = params.deploymentId.trim()
|
||||
if (id.includes('.')) {
|
||||
query.set('url', id)
|
||||
}
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v13/deployments/${id}${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'DELETE',
|
||||
headers: (params: VercelDeleteDeploymentParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
uid: data.uid ?? data.id ?? null,
|
||||
state: data.state ?? 'DELETED',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
uid: {
|
||||
type: 'string',
|
||||
description: 'The removed deployment ID',
|
||||
},
|
||||
state: {
|
||||
type: 'string',
|
||||
description: 'Deployment state after deletion (DELETED)',
|
||||
},
|
||||
},
|
||||
}
|
||||
69
apps/sim/tools/vercel/delete_dns_record.ts
Normal file
69
apps/sim/tools/vercel/delete_dns_record.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
VercelDeleteDnsRecordParams,
|
||||
VercelDeleteDnsRecordResponse,
|
||||
} from '@/tools/vercel/types'
|
||||
|
||||
export const vercelDeleteDnsRecordTool: ToolConfig<
|
||||
VercelDeleteDnsRecordParams,
|
||||
VercelDeleteDnsRecordResponse
|
||||
> = {
|
||||
id: 'vercel_delete_dns_record',
|
||||
name: 'Vercel Delete DNS Record',
|
||||
description: 'Delete a DNS record for a domain in a Vercel account',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The domain name the record belongs to',
|
||||
},
|
||||
recordId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the DNS record to delete',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelDeleteDnsRecordParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v2/domains/${params.domain.trim()}/records/${params.recordId.trim()}${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'DELETE',
|
||||
headers: (params: VercelDeleteDnsRecordParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async () => {
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
deleted: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
deleted: { type: 'boolean', description: 'Whether the record was deleted' },
|
||||
},
|
||||
}
|
||||
64
apps/sim/tools/vercel/delete_domain.ts
Normal file
64
apps/sim/tools/vercel/delete_domain.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelDeleteDomainParams, VercelDeleteDomainResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelDeleteDomainTool: ToolConfig<
|
||||
VercelDeleteDomainParams,
|
||||
VercelDeleteDomainResponse
|
||||
> = {
|
||||
id: 'vercel_delete_domain',
|
||||
name: 'Vercel Delete Domain',
|
||||
description: 'Delete a domain from a Vercel account or team',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The domain name to delete',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelDeleteDomainParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v6/domains/${params.domain.trim()}${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'DELETE',
|
||||
headers: (params: VercelDeleteDomainParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const d = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
uid: d.uid ?? null,
|
||||
deleted: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
uid: { type: 'string', description: 'The ID of the deleted domain' },
|
||||
deleted: { type: 'boolean', description: 'Whether the domain was deleted' },
|
||||
},
|
||||
}
|
||||
69
apps/sim/tools/vercel/delete_env_var.ts
Normal file
69
apps/sim/tools/vercel/delete_env_var.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelDeleteEnvVarParams, VercelDeleteEnvVarResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelDeleteEnvVarTool: ToolConfig<
|
||||
VercelDeleteEnvVarParams,
|
||||
VercelDeleteEnvVarResponse
|
||||
> = {
|
||||
id: 'vercel_delete_env_var',
|
||||
name: 'Vercel Delete Environment Variable',
|
||||
description: 'Delete an environment variable from a Vercel project',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or name',
|
||||
},
|
||||
envId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Environment variable ID to delete',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelDeleteEnvVarParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v9/projects/${params.projectId.trim()}/env/${params.envId.trim()}${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'DELETE',
|
||||
headers: (params: VercelDeleteEnvVarParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async () => {
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
deleted: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
deleted: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the environment variable was successfully deleted',
|
||||
},
|
||||
},
|
||||
}
|
||||
60
apps/sim/tools/vercel/delete_project.ts
Normal file
60
apps/sim/tools/vercel/delete_project.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelDeleteProjectParams, VercelDeleteProjectResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelDeleteProjectTool: ToolConfig<
|
||||
VercelDeleteProjectParams,
|
||||
VercelDeleteProjectResponse
|
||||
> = {
|
||||
id: 'vercel_delete_project',
|
||||
name: 'Vercel Delete Project',
|
||||
description: 'Delete a Vercel project',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or name',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelDeleteProjectParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v9/projects/${params.projectId.trim()}${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'DELETE',
|
||||
headers: (params: VercelDeleteProjectParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async () => {
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
deleted: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
deleted: { type: 'boolean', description: 'Whether the project was successfully deleted' },
|
||||
},
|
||||
}
|
||||
63
apps/sim/tools/vercel/delete_webhook.ts
Normal file
63
apps/sim/tools/vercel/delete_webhook.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelDeleteWebhookParams, VercelDeleteWebhookResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelDeleteWebhookTool: ToolConfig<
|
||||
VercelDeleteWebhookParams,
|
||||
VercelDeleteWebhookResponse
|
||||
> = {
|
||||
id: 'vercel_delete_webhook',
|
||||
name: 'Vercel Delete Webhook',
|
||||
description: 'Delete a webhook from a Vercel team',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
webhookId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The webhook ID to delete',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelDeleteWebhookParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v1/webhooks/${params.webhookId.trim()}${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'DELETE',
|
||||
headers: (params: VercelDeleteWebhookParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async () => {
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
deleted: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
deleted: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the webhook was successfully deleted',
|
||||
},
|
||||
},
|
||||
}
|
||||
97
apps/sim/tools/vercel/get_alias.ts
Normal file
97
apps/sim/tools/vercel/get_alias.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelGetAliasParams, VercelGetAliasResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelGetAliasTool: ToolConfig<VercelGetAliasParams, VercelGetAliasResponse> = {
|
||||
id: 'vercel_get_alias',
|
||||
name: 'Vercel Get Alias',
|
||||
description: 'Get details about a specific alias by ID or hostname',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
aliasId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Alias ID or hostname to look up',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelGetAliasParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v4/aliases/${params.aliasId.trim()}${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelGetAliasParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
uid: data.uid ?? null,
|
||||
alias: data.alias ?? null,
|
||||
deploymentId: data.deploymentId ?? null,
|
||||
projectId: data.projectId ?? null,
|
||||
createdAt: data.createdAt ?? null,
|
||||
updatedAt: data.updatedAt ?? null,
|
||||
redirect: data.redirect ?? null,
|
||||
redirectStatusCode: data.redirectStatusCode ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
uid: {
|
||||
type: 'string',
|
||||
description: 'Alias ID',
|
||||
},
|
||||
alias: {
|
||||
type: 'string',
|
||||
description: 'Alias hostname',
|
||||
},
|
||||
deploymentId: {
|
||||
type: 'string',
|
||||
description: 'Associated deployment ID',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
description: 'Associated project ID',
|
||||
},
|
||||
createdAt: {
|
||||
type: 'number',
|
||||
description: 'Creation timestamp in milliseconds',
|
||||
},
|
||||
updatedAt: {
|
||||
type: 'number',
|
||||
description: 'Last update timestamp in milliseconds',
|
||||
},
|
||||
redirect: {
|
||||
type: 'string',
|
||||
description: 'Target domain for redirect aliases',
|
||||
},
|
||||
redirectStatusCode: {
|
||||
type: 'number',
|
||||
description: 'HTTP status code for redirect (301, 302, 307, or 308)',
|
||||
},
|
||||
},
|
||||
}
|
||||
99
apps/sim/tools/vercel/get_check.ts
Normal file
99
apps/sim/tools/vercel/get_check.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelCheckResponse, VercelGetCheckParams } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelGetCheckTool: ToolConfig<VercelGetCheckParams, VercelCheckResponse> = {
|
||||
id: 'vercel_get_check',
|
||||
name: 'Vercel Get Check',
|
||||
description: 'Get details of a specific deployment check',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
deploymentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Deployment ID the check belongs to',
|
||||
},
|
||||
checkId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Check ID to retrieve',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelGetCheckParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v1/deployments/${params.deploymentId.trim()}/checks/${params.checkId.trim()}${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelGetCheckParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
status: data.status ?? 'registered',
|
||||
conclusion: data.conclusion ?? null,
|
||||
blocking: data.blocking ?? false,
|
||||
deploymentId: data.deploymentId,
|
||||
integrationId: data.integrationId ?? null,
|
||||
externalId: data.externalId ?? null,
|
||||
detailsUrl: data.detailsUrl ?? null,
|
||||
path: data.path ?? null,
|
||||
rerequestable: data.rerequestable ?? false,
|
||||
createdAt: data.createdAt,
|
||||
updatedAt: data.updatedAt,
|
||||
startedAt: data.startedAt ?? null,
|
||||
completedAt: data.completedAt ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Check ID' },
|
||||
name: { type: 'string', description: 'Check name' },
|
||||
status: { type: 'string', description: 'Check status: registered, running, or completed' },
|
||||
conclusion: {
|
||||
type: 'string',
|
||||
description: 'Check conclusion: canceled, failed, neutral, succeeded, skipped, or stale',
|
||||
optional: true,
|
||||
},
|
||||
blocking: { type: 'boolean', description: 'Whether the check blocks the deployment' },
|
||||
deploymentId: { type: 'string', description: 'Associated deployment ID' },
|
||||
integrationId: { type: 'string', description: 'Associated integration ID', optional: true },
|
||||
externalId: { type: 'string', description: 'External identifier', optional: true },
|
||||
detailsUrl: { type: 'string', description: 'URL with details about the check', optional: true },
|
||||
path: { type: 'string', description: 'Page path being checked', optional: true },
|
||||
rerequestable: { type: 'boolean', description: 'Whether the check can be rerequested' },
|
||||
createdAt: { type: 'number', description: 'Creation timestamp in milliseconds' },
|
||||
updatedAt: { type: 'number', description: 'Last update timestamp in milliseconds' },
|
||||
startedAt: { type: 'number', description: 'Start timestamp in milliseconds', optional: true },
|
||||
completedAt: {
|
||||
type: 'number',
|
||||
description: 'Completion timestamp in milliseconds',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
176
apps/sim/tools/vercel/get_deployment.ts
Normal file
176
apps/sim/tools/vercel/get_deployment.ts
Normal file
@@ -0,0 +1,176 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelGetDeploymentParams, VercelGetDeploymentResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelGetDeploymentTool: ToolConfig<
|
||||
VercelGetDeploymentParams,
|
||||
VercelGetDeploymentResponse
|
||||
> = {
|
||||
id: 'vercel_get_deployment',
|
||||
name: 'Vercel Get Deployment',
|
||||
description: 'Get details of a specific Vercel deployment',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
deploymentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The unique deployment identifier or hostname',
|
||||
},
|
||||
withGitRepoInfo: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Whether to add in gitRepo information (true/false)',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelGetDeploymentParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.withGitRepoInfo) query.set('withGitRepoInfo', params.withGitRepoInfo)
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v13/deployments/${params.deploymentId.trim()}${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelGetDeploymentParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
url: data.url ?? '',
|
||||
readyState: data.readyState ?? 'UNKNOWN',
|
||||
status: data.status ?? data.readyState ?? 'UNKNOWN',
|
||||
target: data.target ?? null,
|
||||
createdAt: data.createdAt ?? data.created,
|
||||
buildingAt: data.buildingAt ?? null,
|
||||
ready: data.ready ?? null,
|
||||
source: data.source ?? '',
|
||||
alias: data.alias ?? [],
|
||||
regions: data.regions ?? [],
|
||||
inspectorUrl: data.inspectorUrl ?? '',
|
||||
projectId: data.projectId ?? '',
|
||||
creator: {
|
||||
uid: data.creator?.uid ?? '',
|
||||
username: data.creator?.username ?? '',
|
||||
},
|
||||
project: data.project
|
||||
? {
|
||||
id: data.project.id,
|
||||
name: data.project.name,
|
||||
framework: data.project.framework ?? null,
|
||||
}
|
||||
: null,
|
||||
meta: data.meta ?? {},
|
||||
gitSource: data.gitSource ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Deployment ID' },
|
||||
name: { type: 'string', description: 'Deployment name' },
|
||||
url: { type: 'string', description: 'Unique deployment URL' },
|
||||
readyState: {
|
||||
type: 'string',
|
||||
description: 'Deployment ready state: QUEUED, BUILDING, ERROR, INITIALIZING, READY, CANCELED',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
description: 'Deployment status',
|
||||
},
|
||||
target: { type: 'string', description: 'Target environment', optional: true },
|
||||
createdAt: { type: 'number', description: 'Creation timestamp in milliseconds' },
|
||||
buildingAt: { type: 'number', description: 'Build start timestamp', optional: true },
|
||||
ready: { type: 'number', description: 'Ready timestamp', optional: true },
|
||||
source: {
|
||||
type: 'string',
|
||||
description: 'Deployment source: cli, git, redeploy, import, v0-web, etc.',
|
||||
},
|
||||
alias: {
|
||||
type: 'array',
|
||||
description: 'Assigned aliases',
|
||||
items: { type: 'string', description: 'Alias domain' },
|
||||
},
|
||||
regions: {
|
||||
type: 'array',
|
||||
description: 'Deployment regions',
|
||||
items: { type: 'string', description: 'Region code' },
|
||||
},
|
||||
inspectorUrl: { type: 'string', description: 'Vercel inspector URL' },
|
||||
projectId: { type: 'string', description: 'Associated project ID' },
|
||||
creator: {
|
||||
type: 'object',
|
||||
description: 'Creator information',
|
||||
properties: {
|
||||
uid: { type: 'string', description: 'Creator user ID' },
|
||||
username: { type: 'string', description: 'Creator username' },
|
||||
},
|
||||
},
|
||||
project: {
|
||||
type: 'object',
|
||||
description: 'Associated project',
|
||||
optional: true,
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Project ID' },
|
||||
name: { type: 'string', description: 'Project name' },
|
||||
framework: { type: 'string', description: 'Project framework', optional: true },
|
||||
},
|
||||
},
|
||||
meta: {
|
||||
type: 'object',
|
||||
description: 'Deployment metadata (key-value strings)',
|
||||
properties: {
|
||||
githubCommitSha: { type: 'string', description: 'GitHub commit SHA', optional: true },
|
||||
githubCommitMessage: {
|
||||
type: 'string',
|
||||
description: 'GitHub commit message',
|
||||
optional: true,
|
||||
},
|
||||
githubCommitRef: { type: 'string', description: 'GitHub branch/ref', optional: true },
|
||||
githubRepo: { type: 'string', description: 'GitHub repository', optional: true },
|
||||
githubOrg: { type: 'string', description: 'GitHub organization', optional: true },
|
||||
githubCommitAuthorName: {
|
||||
type: 'string',
|
||||
description: 'Commit author name',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
gitSource: {
|
||||
type: 'object',
|
||||
description: 'Git source information',
|
||||
optional: true,
|
||||
properties: {
|
||||
type: {
|
||||
type: 'string',
|
||||
description: 'Git provider type (e.g., github, gitlab, bitbucket)',
|
||||
},
|
||||
ref: { type: 'string', description: 'Git ref (branch or tag)' },
|
||||
sha: { type: 'string', description: 'Git commit SHA' },
|
||||
repoId: { type: 'string', description: 'Repository ID', optional: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
135
apps/sim/tools/vercel/get_deployment_events.ts
Normal file
135
apps/sim/tools/vercel/get_deployment_events.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
VercelGetDeploymentEventsParams,
|
||||
VercelGetDeploymentEventsResponse,
|
||||
} from '@/tools/vercel/types'
|
||||
|
||||
export const vercelGetDeploymentEventsTool: ToolConfig<
|
||||
VercelGetDeploymentEventsParams,
|
||||
VercelGetDeploymentEventsResponse
|
||||
> = {
|
||||
id: 'vercel_get_deployment_events',
|
||||
name: 'Vercel Get Deployment Events',
|
||||
description: 'Get build and runtime events for a Vercel deployment',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
deploymentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The unique deployment identifier or hostname',
|
||||
},
|
||||
direction: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Order of events by timestamp: backward or forward (default: forward)',
|
||||
},
|
||||
follow: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'When set to 1, returns live events as they happen',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of events to return (-1 for all)',
|
||||
},
|
||||
since: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Timestamp to start pulling build logs from',
|
||||
},
|
||||
until: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Timestamp to stop pulling build logs at',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelGetDeploymentEventsParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.direction) query.set('direction', params.direction)
|
||||
if (params.follow !== undefined) query.set('follow', String(params.follow))
|
||||
if (params.limit !== undefined) query.set('limit', String(params.limit))
|
||||
if (params.since !== undefined) query.set('since', String(params.since))
|
||||
if (params.until !== undefined) query.set('until', String(params.until))
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v3/deployments/${params.deploymentId.trim()}/events${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelGetDeploymentEventsParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const events = (Array.isArray(data) ? data : (data.events ?? [])).map((e: any) => ({
|
||||
type: e.type ?? null,
|
||||
created: e.created ?? null,
|
||||
date: e.date ?? null,
|
||||
text: e.text ?? e.payload?.text ?? null,
|
||||
serial: e.serial ?? null,
|
||||
deploymentId: e.deploymentId ?? e.payload?.deploymentId ?? null,
|
||||
id: e.id ?? null,
|
||||
level: e.level ?? null,
|
||||
}))
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
events,
|
||||
count: events.length,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
events: {
|
||||
type: 'array',
|
||||
description: 'List of deployment events',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
type: {
|
||||
type: 'string',
|
||||
description:
|
||||
'Event type: delimiter, command, stdout, stderr, exit, deployment-state, middleware, middleware-invocation, edge-function-invocation, metric, report, fatal',
|
||||
},
|
||||
created: { type: 'number', description: 'Event creation timestamp' },
|
||||
date: { type: 'number', description: 'Event date timestamp' },
|
||||
text: { type: 'string', description: 'Event text content' },
|
||||
serial: { type: 'string', description: 'Event serial identifier' },
|
||||
deploymentId: { type: 'string', description: 'Associated deployment ID' },
|
||||
id: { type: 'string', description: 'Event unique identifier' },
|
||||
level: { type: 'string', description: 'Event level: error or warning' },
|
||||
},
|
||||
},
|
||||
},
|
||||
count: {
|
||||
type: 'number',
|
||||
description: 'Number of events returned',
|
||||
},
|
||||
},
|
||||
}
|
||||
94
apps/sim/tools/vercel/get_domain.ts
Normal file
94
apps/sim/tools/vercel/get_domain.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelGetDomainParams, VercelGetDomainResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelGetDomainTool: ToolConfig<VercelGetDomainParams, VercelGetDomainResponse> = {
|
||||
id: 'vercel_get_domain',
|
||||
name: 'Vercel Get Domain',
|
||||
description: 'Get information about a specific domain in a Vercel account',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The domain name to retrieve',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelGetDomainParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v5/domains/${params.domain.trim()}${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelGetDomainParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const d = data.domain ?? data
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: d.id ?? null,
|
||||
name: d.name ?? null,
|
||||
verified: d.verified ?? false,
|
||||
createdAt: d.createdAt ?? null,
|
||||
expiresAt: d.expiresAt ?? null,
|
||||
serviceType: d.serviceType ?? null,
|
||||
nameservers: d.nameservers ?? [],
|
||||
intendedNameservers: d.intendedNameservers ?? [],
|
||||
customNameservers: d.customNameservers ?? [],
|
||||
renew: d.renew ?? false,
|
||||
boughtAt: d.boughtAt ?? null,
|
||||
transferredAt: d.transferredAt ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Domain ID' },
|
||||
name: { type: 'string', description: 'Domain name' },
|
||||
verified: { type: 'boolean', description: 'Whether domain is verified' },
|
||||
createdAt: { type: 'number', description: 'Creation timestamp' },
|
||||
expiresAt: { type: 'number', description: 'Expiration timestamp' },
|
||||
serviceType: { type: 'string', description: 'Service type (zeit.world, external, na)' },
|
||||
nameservers: {
|
||||
type: 'array',
|
||||
description: 'Current nameservers',
|
||||
items: { type: 'string' },
|
||||
},
|
||||
intendedNameservers: {
|
||||
type: 'array',
|
||||
description: 'Intended nameservers',
|
||||
items: { type: 'string' },
|
||||
},
|
||||
customNameservers: {
|
||||
type: 'array',
|
||||
description: 'Custom nameservers',
|
||||
items: { type: 'string' },
|
||||
},
|
||||
renew: { type: 'boolean', description: 'Whether auto-renewal is enabled' },
|
||||
boughtAt: { type: 'number', description: 'Purchase timestamp' },
|
||||
transferredAt: { type: 'number', description: 'Transfer completion timestamp' },
|
||||
},
|
||||
}
|
||||
107
apps/sim/tools/vercel/get_domain_config.ts
Normal file
107
apps/sim/tools/vercel/get_domain_config.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
VercelGetDomainConfigParams,
|
||||
VercelGetDomainConfigResponse,
|
||||
} from '@/tools/vercel/types'
|
||||
|
||||
export const vercelGetDomainConfigTool: ToolConfig<
|
||||
VercelGetDomainConfigParams,
|
||||
VercelGetDomainConfigResponse
|
||||
> = {
|
||||
id: 'vercel_get_domain_config',
|
||||
name: 'Vercel Get Domain Config',
|
||||
description: 'Get the configuration for a domain in a Vercel account',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The domain name to get configuration for',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelGetDomainConfigParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v6/domains/${params.domain.trim()}/config${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelGetDomainConfigParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const d = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
configuredBy: d.configuredBy ?? null,
|
||||
acceptedChallenges: d.acceptedChallenges ?? [],
|
||||
misconfigured: d.misconfigured ?? false,
|
||||
recommendedIPv4: d.recommendedIPv4 ?? [],
|
||||
recommendedCNAME: d.recommendedCNAME ?? [],
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
configuredBy: {
|
||||
type: 'string',
|
||||
description: 'How the domain is configured (CNAME, A, http, dns-01, or null)',
|
||||
},
|
||||
acceptedChallenges: {
|
||||
type: 'array',
|
||||
description: 'Accepted challenge types for certificate issuance (dns-01, http-01)',
|
||||
items: { type: 'string' },
|
||||
},
|
||||
misconfigured: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the domain is misconfigured for TLS certificate generation',
|
||||
},
|
||||
recommendedIPv4: {
|
||||
type: 'array',
|
||||
description: 'Recommended IPv4 addresses with rank values',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
rank: { type: 'number', description: 'Priority rank (1 is preferred)' },
|
||||
value: {
|
||||
type: 'array',
|
||||
description: 'IPv4 addresses',
|
||||
items: { type: 'string' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
recommendedCNAME: {
|
||||
type: 'array',
|
||||
description: 'Recommended CNAME records with rank values',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
rank: { type: 'number', description: 'Priority rank (1 is preferred)' },
|
||||
value: { type: 'string', description: 'CNAME value' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
100
apps/sim/tools/vercel/get_edge_config.ts
Normal file
100
apps/sim/tools/vercel/get_edge_config.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelGetEdgeConfigParams, VercelGetEdgeConfigResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelGetEdgeConfigTool: ToolConfig<
|
||||
VercelGetEdgeConfigParams,
|
||||
VercelGetEdgeConfigResponse
|
||||
> = {
|
||||
id: 'vercel_get_edge_config',
|
||||
name: 'Vercel Get Edge Config',
|
||||
description: 'Get details about a specific Edge Config store',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
edgeConfigId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Edge Config ID to look up',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelGetEdgeConfigParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v1/edge-config/${params.edgeConfigId.trim()}${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelGetEdgeConfigParams) => ({
|
||||
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,
|
||||
slug: data.slug ?? null,
|
||||
ownerId: data.ownerId ?? null,
|
||||
digest: data.digest ?? null,
|
||||
createdAt: data.createdAt ?? null,
|
||||
updatedAt: data.updatedAt ?? null,
|
||||
itemCount: data.itemCount ?? 0,
|
||||
sizeInBytes: data.sizeInBytes ?? 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'Edge Config ID',
|
||||
},
|
||||
slug: {
|
||||
type: 'string',
|
||||
description: 'Edge Config slug',
|
||||
},
|
||||
ownerId: {
|
||||
type: 'string',
|
||||
description: 'Owner ID',
|
||||
},
|
||||
digest: {
|
||||
type: 'string',
|
||||
description: 'Content digest hash',
|
||||
},
|
||||
createdAt: {
|
||||
type: 'number',
|
||||
description: 'Creation timestamp',
|
||||
},
|
||||
updatedAt: {
|
||||
type: 'number',
|
||||
description: 'Last update timestamp',
|
||||
},
|
||||
itemCount: {
|
||||
type: 'number',
|
||||
description: 'Number of items',
|
||||
},
|
||||
sizeInBytes: {
|
||||
type: 'number',
|
||||
description: 'Size in bytes',
|
||||
},
|
||||
},
|
||||
}
|
||||
93
apps/sim/tools/vercel/get_edge_config_items.ts
Normal file
93
apps/sim/tools/vercel/get_edge_config_items.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
VercelGetEdgeConfigItemsParams,
|
||||
VercelGetEdgeConfigItemsResponse,
|
||||
} from '@/tools/vercel/types'
|
||||
|
||||
export const vercelGetEdgeConfigItemsTool: ToolConfig<
|
||||
VercelGetEdgeConfigItemsParams,
|
||||
VercelGetEdgeConfigItemsResponse
|
||||
> = {
|
||||
id: 'vercel_get_edge_config_items',
|
||||
name: 'Vercel Get Edge Config Items',
|
||||
description: 'Get all items in an Edge Config store',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
edgeConfigId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Edge Config ID to get items from',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelGetEdgeConfigItemsParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v1/edge-config/${params.edgeConfigId.trim()}/items${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelGetEdgeConfigItemsParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const rawItems = Array.isArray(data) ? data : (data.items ?? [])
|
||||
const items = rawItems.map((item: any) => ({
|
||||
key: item.key ?? null,
|
||||
value: item.value ?? null,
|
||||
description: item.description ?? null,
|
||||
edgeConfigId: item.edgeConfigId ?? null,
|
||||
createdAt: item.createdAt ?? null,
|
||||
updatedAt: item.updatedAt ?? null,
|
||||
}))
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
items,
|
||||
count: items.length,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
items: {
|
||||
type: 'array',
|
||||
description: 'List of Edge Config items',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
key: { type: 'string', description: 'Item key' },
|
||||
value: { type: 'json', description: 'Item value' },
|
||||
description: { type: 'string', description: 'Item description' },
|
||||
edgeConfigId: { type: 'string', description: 'Parent Edge Config ID' },
|
||||
createdAt: { type: 'number', description: 'Creation timestamp' },
|
||||
updatedAt: { type: 'number', description: 'Last update timestamp' },
|
||||
},
|
||||
},
|
||||
},
|
||||
count: {
|
||||
type: 'number',
|
||||
description: 'Number of items returned',
|
||||
},
|
||||
},
|
||||
}
|
||||
99
apps/sim/tools/vercel/get_env_vars.ts
Normal file
99
apps/sim/tools/vercel/get_env_vars.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelGetEnvVarsParams, VercelGetEnvVarsResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelGetEnvVarsTool: ToolConfig<VercelGetEnvVarsParams, VercelGetEnvVarsResponse> = {
|
||||
id: 'vercel_get_env_vars',
|
||||
name: 'Vercel Get Environment Variables',
|
||||
description: 'Retrieve environment variables for a Vercel project',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or name',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelGetEnvVarsParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v10/projects/${params.projectId.trim()}/env${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelGetEnvVarsParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const envs = (data.envs ?? []).map((e: any) => ({
|
||||
id: e.id,
|
||||
key: e.key,
|
||||
value: e.value ?? '',
|
||||
type: e.type ?? 'plain',
|
||||
target: e.target ?? [],
|
||||
gitBranch: e.gitBranch ?? null,
|
||||
comment: e.comment ?? null,
|
||||
}))
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
envs,
|
||||
count: envs.length,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
envs: {
|
||||
type: 'array',
|
||||
description: 'List of environment variables',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Environment variable ID' },
|
||||
key: { type: 'string', description: 'Variable name' },
|
||||
value: { type: 'string', description: 'Variable value' },
|
||||
type: {
|
||||
type: 'string',
|
||||
description: 'Variable type (secret, system, encrypted, plain, sensitive)',
|
||||
},
|
||||
target: {
|
||||
type: 'array',
|
||||
description: 'Target environments',
|
||||
items: { type: 'string', description: 'Environment name' },
|
||||
},
|
||||
gitBranch: { type: 'string', description: 'Git branch filter', optional: true },
|
||||
comment: {
|
||||
type: 'string',
|
||||
description: 'Comment providing context for the variable',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
count: {
|
||||
type: 'number',
|
||||
description: 'Number of environment variables returned',
|
||||
},
|
||||
},
|
||||
}
|
||||
89
apps/sim/tools/vercel/get_project.ts
Normal file
89
apps/sim/tools/vercel/get_project.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelGetProjectParams, VercelGetProjectResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelGetProjectTool: ToolConfig<VercelGetProjectParams, VercelGetProjectResponse> = {
|
||||
id: 'vercel_get_project',
|
||||
name: 'Vercel Get Project',
|
||||
description: 'Get details of a specific Vercel project',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or name',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelGetProjectParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v9/projects/${params.projectId.trim()}${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelGetProjectParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
framework: data.framework ?? null,
|
||||
createdAt: data.createdAt,
|
||||
updatedAt: data.updatedAt,
|
||||
domains: data.domains ?? [],
|
||||
link: data.link
|
||||
? {
|
||||
type: data.link.type,
|
||||
repo: data.link.repo,
|
||||
org: data.link.org,
|
||||
}
|
||||
: null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Project ID' },
|
||||
name: { type: 'string', description: 'Project name' },
|
||||
framework: { type: 'string', description: 'Project framework', optional: true },
|
||||
createdAt: { type: 'number', description: 'Creation timestamp' },
|
||||
updatedAt: { type: 'number', description: 'Last updated timestamp' },
|
||||
domains: {
|
||||
type: 'array',
|
||||
description: 'Project domains',
|
||||
items: { type: 'string', description: 'Domain' },
|
||||
},
|
||||
link: {
|
||||
type: 'object',
|
||||
description: 'Git repository connection',
|
||||
optional: true,
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Repository type (github, gitlab, bitbucket)' },
|
||||
repo: { type: 'string', description: 'Repository name' },
|
||||
org: { type: 'string', description: 'Organization or owner' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
98
apps/sim/tools/vercel/get_team.ts
Normal file
98
apps/sim/tools/vercel/get_team.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelGetTeamParams, VercelGetTeamResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelGetTeamTool: ToolConfig<VercelGetTeamParams, VercelGetTeamResponse> = {
|
||||
id: 'vercel_get_team',
|
||||
name: 'Vercel Get Team',
|
||||
description: 'Get information about a specific Vercel team',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The team ID to retrieve',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelGetTeamParams) => `https://api.vercel.com/v2/teams/${params.teamId.trim()}`,
|
||||
method: 'GET',
|
||||
headers: (params: VercelGetTeamParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const d = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: d.id ?? null,
|
||||
slug: d.slug ?? null,
|
||||
name: d.name ?? null,
|
||||
avatar: d.avatar ?? null,
|
||||
description: d.description ?? null,
|
||||
createdAt: d.createdAt ?? null,
|
||||
updatedAt: d.updatedAt ?? null,
|
||||
creatorId: d.creatorId ?? null,
|
||||
membership: d.membership
|
||||
? {
|
||||
uid: d.membership.uid ?? null,
|
||||
teamId: d.membership.teamId ?? null,
|
||||
role: d.membership.role ?? null,
|
||||
confirmed: d.membership.confirmed ?? false,
|
||||
created: d.membership.created ?? null,
|
||||
createdAt: d.membership.createdAt ?? null,
|
||||
accessRequestedAt: d.membership.accessRequestedAt ?? null,
|
||||
teamRoles: d.membership.teamRoles ?? [],
|
||||
teamPermissions: d.membership.teamPermissions ?? [],
|
||||
}
|
||||
: null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Team ID' },
|
||||
slug: { type: 'string', description: 'Team slug' },
|
||||
name: { type: 'string', description: 'Team name' },
|
||||
avatar: { type: 'string', description: 'Avatar file ID' },
|
||||
description: { type: 'string', description: 'Short team description' },
|
||||
createdAt: { type: 'number', description: 'Creation timestamp in milliseconds' },
|
||||
updatedAt: { type: 'number', description: 'Last update timestamp in milliseconds' },
|
||||
creatorId: { type: 'string', description: 'User ID of team creator' },
|
||||
membership: {
|
||||
type: 'object',
|
||||
description: 'Current user membership details',
|
||||
properties: {
|
||||
uid: { type: 'string', description: 'User ID of the member' },
|
||||
teamId: { type: 'string', description: 'Team ID' },
|
||||
role: { type: 'string', description: 'Membership role' },
|
||||
confirmed: { type: 'boolean', description: 'Whether membership is confirmed' },
|
||||
created: { type: 'number', description: 'Membership creation timestamp' },
|
||||
createdAt: { type: 'number', description: 'Membership creation timestamp (milliseconds)' },
|
||||
accessRequestedAt: { type: 'number', description: 'When access was requested' },
|
||||
teamRoles: {
|
||||
type: 'array',
|
||||
description: 'Team role assignments',
|
||||
items: { type: 'string', description: 'Role name' },
|
||||
},
|
||||
teamPermissions: {
|
||||
type: 'array',
|
||||
description: 'Team permission assignments',
|
||||
items: { type: 'string', description: 'Permission name' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
73
apps/sim/tools/vercel/get_user.ts
Normal file
73
apps/sim/tools/vercel/get_user.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelGetUserParams, VercelGetUserResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelGetUserTool: ToolConfig<VercelGetUserParams, VercelGetUserResponse> = {
|
||||
id: 'vercel_get_user',
|
||||
name: 'Vercel Get User',
|
||||
description: 'Get information about the authenticated Vercel user',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => 'https://api.vercel.com/v2/user',
|
||||
method: 'GET',
|
||||
headers: (params: VercelGetUserParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const d = data.user ?? data
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: d.id ?? null,
|
||||
email: d.email ?? null,
|
||||
username: d.username ?? null,
|
||||
name: d.name ?? null,
|
||||
avatar: d.avatar ?? null,
|
||||
defaultTeamId: d.defaultTeamId ?? null,
|
||||
createdAt: d.createdAt ?? null,
|
||||
stagingPrefix: d.stagingPrefix ?? null,
|
||||
softBlock: d.softBlock
|
||||
? {
|
||||
blockedAt: d.softBlock.blockedAt ?? null,
|
||||
reason: d.softBlock.reason ?? null,
|
||||
}
|
||||
: null,
|
||||
hasTrialAvailable: d.hasTrialAvailable ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'User ID' },
|
||||
email: { type: 'string', description: 'User email' },
|
||||
username: { type: 'string', description: 'Username' },
|
||||
name: { type: 'string', description: 'Display name' },
|
||||
avatar: { type: 'string', description: 'SHA1 hash of the avatar' },
|
||||
defaultTeamId: { type: 'string', description: 'Default team ID' },
|
||||
createdAt: { type: 'number', description: 'Account creation timestamp in milliseconds' },
|
||||
stagingPrefix: { type: 'string', description: 'Prefix for preview deployment URLs' },
|
||||
softBlock: {
|
||||
type: 'object',
|
||||
description: 'Account restriction details if blocked',
|
||||
properties: {
|
||||
blockedAt: { type: 'number', description: 'When the account was blocked' },
|
||||
reason: { type: 'string', description: 'Reason for the block' },
|
||||
},
|
||||
},
|
||||
hasTrialAvailable: { type: 'boolean', description: 'Whether a trial is available' },
|
||||
},
|
||||
}
|
||||
126
apps/sim/tools/vercel/index.ts
Normal file
126
apps/sim/tools/vercel/index.ts
Normal file
@@ -0,0 +1,126 @@
|
||||
// Deployment tools
|
||||
|
||||
// Domain tools
|
||||
import { vercelAddDomainTool } from '@/tools/vercel/add_domain'
|
||||
// Project tools
|
||||
import { vercelAddProjectDomainTool } from '@/tools/vercel/add_project_domain'
|
||||
import { vercelCancelDeploymentTool } from '@/tools/vercel/cancel_deployment'
|
||||
// Alias tools
|
||||
import { vercelCreateAliasTool } from '@/tools/vercel/create_alias'
|
||||
// Check tools
|
||||
import { vercelCreateCheckTool } from '@/tools/vercel/create_check'
|
||||
import { vercelCreateDeploymentTool } from '@/tools/vercel/create_deployment'
|
||||
// DNS tools
|
||||
import { vercelCreateDnsRecordTool } from '@/tools/vercel/create_dns_record'
|
||||
// Edge Config tools
|
||||
import { vercelCreateEdgeConfigTool } from '@/tools/vercel/create_edge_config'
|
||||
// Environment variable tools
|
||||
import { vercelCreateEnvVarTool } from '@/tools/vercel/create_env_var'
|
||||
import { vercelCreateProjectTool } from '@/tools/vercel/create_project'
|
||||
// Webhook tools
|
||||
import { vercelCreateWebhookTool } from '@/tools/vercel/create_webhook'
|
||||
import { vercelDeleteAliasTool } from '@/tools/vercel/delete_alias'
|
||||
import { vercelDeleteDeploymentTool } from '@/tools/vercel/delete_deployment'
|
||||
import { vercelDeleteDnsRecordTool } from '@/tools/vercel/delete_dns_record'
|
||||
import { vercelDeleteDomainTool } from '@/tools/vercel/delete_domain'
|
||||
import { vercelDeleteEnvVarTool } from '@/tools/vercel/delete_env_var'
|
||||
import { vercelDeleteProjectTool } from '@/tools/vercel/delete_project'
|
||||
import { vercelDeleteWebhookTool } from '@/tools/vercel/delete_webhook'
|
||||
import { vercelGetAliasTool } from '@/tools/vercel/get_alias'
|
||||
import { vercelGetCheckTool } from '@/tools/vercel/get_check'
|
||||
import { vercelGetDeploymentTool } from '@/tools/vercel/get_deployment'
|
||||
import { vercelGetDeploymentEventsTool } from '@/tools/vercel/get_deployment_events'
|
||||
import { vercelGetDomainTool } from '@/tools/vercel/get_domain'
|
||||
import { vercelGetDomainConfigTool } from '@/tools/vercel/get_domain_config'
|
||||
import { vercelGetEdgeConfigTool } from '@/tools/vercel/get_edge_config'
|
||||
import { vercelGetEdgeConfigItemsTool } from '@/tools/vercel/get_edge_config_items'
|
||||
import { vercelGetEnvVarsTool } from '@/tools/vercel/get_env_vars'
|
||||
import { vercelGetProjectTool } from '@/tools/vercel/get_project'
|
||||
// Team & User tools
|
||||
import { vercelGetTeamTool } from '@/tools/vercel/get_team'
|
||||
import { vercelGetUserTool } from '@/tools/vercel/get_user'
|
||||
import { vercelListAliasesTool } from '@/tools/vercel/list_aliases'
|
||||
import { vercelListChecksTool } from '@/tools/vercel/list_checks'
|
||||
import { vercelListDeploymentFilesTool } from '@/tools/vercel/list_deployment_files'
|
||||
import { vercelListDeploymentsTool } from '@/tools/vercel/list_deployments'
|
||||
import { vercelListDnsRecordsTool } from '@/tools/vercel/list_dns_records'
|
||||
import { vercelListDomainsTool } from '@/tools/vercel/list_domains'
|
||||
import { vercelListEdgeConfigsTool } from '@/tools/vercel/list_edge_configs'
|
||||
import { vercelListProjectDomainsTool } from '@/tools/vercel/list_project_domains'
|
||||
import { vercelListProjectsTool } from '@/tools/vercel/list_projects'
|
||||
import { vercelListTeamMembersTool } from '@/tools/vercel/list_team_members'
|
||||
import { vercelListTeamsTool } from '@/tools/vercel/list_teams'
|
||||
import { vercelListWebhooksTool } from '@/tools/vercel/list_webhooks'
|
||||
import { vercelPauseProjectTool } from '@/tools/vercel/pause_project'
|
||||
import { vercelRemoveProjectDomainTool } from '@/tools/vercel/remove_project_domain'
|
||||
import { vercelRerequestCheckTool } from '@/tools/vercel/rerequest_check'
|
||||
import { vercelUnpauseProjectTool } from '@/tools/vercel/unpause_project'
|
||||
import { vercelUpdateCheckTool } from '@/tools/vercel/update_check'
|
||||
import { vercelUpdateEdgeConfigItemsTool } from '@/tools/vercel/update_edge_config_items'
|
||||
import { vercelUpdateEnvVarTool } from '@/tools/vercel/update_env_var'
|
||||
import { vercelUpdateProjectTool } from '@/tools/vercel/update_project'
|
||||
|
||||
export {
|
||||
// Deployments
|
||||
vercelListDeploymentsTool,
|
||||
vercelGetDeploymentTool,
|
||||
vercelCreateDeploymentTool,
|
||||
vercelCancelDeploymentTool,
|
||||
vercelDeleteDeploymentTool,
|
||||
vercelGetDeploymentEventsTool,
|
||||
vercelListDeploymentFilesTool,
|
||||
// Projects
|
||||
vercelListProjectsTool,
|
||||
vercelGetProjectTool,
|
||||
vercelCreateProjectTool,
|
||||
vercelUpdateProjectTool,
|
||||
vercelDeleteProjectTool,
|
||||
vercelPauseProjectTool,
|
||||
vercelUnpauseProjectTool,
|
||||
vercelListProjectDomainsTool,
|
||||
vercelAddProjectDomainTool,
|
||||
vercelRemoveProjectDomainTool,
|
||||
// Environment Variables
|
||||
vercelGetEnvVarsTool,
|
||||
vercelCreateEnvVarTool,
|
||||
vercelUpdateEnvVarTool,
|
||||
vercelDeleteEnvVarTool,
|
||||
// Domains
|
||||
vercelListDomainsTool,
|
||||
vercelGetDomainTool,
|
||||
vercelAddDomainTool,
|
||||
vercelDeleteDomainTool,
|
||||
vercelGetDomainConfigTool,
|
||||
// DNS
|
||||
vercelListDnsRecordsTool,
|
||||
vercelCreateDnsRecordTool,
|
||||
vercelDeleteDnsRecordTool,
|
||||
// Aliases
|
||||
vercelListAliasesTool,
|
||||
vercelGetAliasTool,
|
||||
vercelCreateAliasTool,
|
||||
vercelDeleteAliasTool,
|
||||
// Edge Config
|
||||
vercelListEdgeConfigsTool,
|
||||
vercelGetEdgeConfigTool,
|
||||
vercelCreateEdgeConfigTool,
|
||||
vercelGetEdgeConfigItemsTool,
|
||||
vercelUpdateEdgeConfigItemsTool,
|
||||
// Teams & User
|
||||
vercelListTeamsTool,
|
||||
vercelGetTeamTool,
|
||||
vercelListTeamMembersTool,
|
||||
vercelGetUserTool,
|
||||
// Webhooks
|
||||
vercelListWebhooksTool,
|
||||
vercelCreateWebhookTool,
|
||||
vercelDeleteWebhookTool,
|
||||
// Checks
|
||||
vercelCreateCheckTool,
|
||||
vercelGetCheckTool,
|
||||
vercelListChecksTool,
|
||||
vercelUpdateCheckTool,
|
||||
vercelRerequestCheckTool,
|
||||
}
|
||||
|
||||
export * from './types'
|
||||
107
apps/sim/tools/vercel/list_aliases.ts
Normal file
107
apps/sim/tools/vercel/list_aliases.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelListAliasesParams, VercelListAliasesResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelListAliasesTool: ToolConfig<VercelListAliasesParams, VercelListAliasesResponse> =
|
||||
{
|
||||
id: 'vercel_list_aliases',
|
||||
name: 'Vercel List Aliases',
|
||||
description: 'List aliases for a Vercel project or team',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter aliases by project ID',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter aliases by domain',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of aliases to return',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelListAliasesParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.projectId) query.set('projectId', params.projectId.trim())
|
||||
if (params.domain) query.set('domain', params.domain.trim())
|
||||
if (params.limit) query.set('limit', String(params.limit))
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v4/aliases${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelListAliasesParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const aliases = (data.aliases ?? []).map((a: any) => ({
|
||||
uid: a.uid ?? null,
|
||||
alias: a.alias ?? null,
|
||||
deploymentId: a.deploymentId ?? null,
|
||||
projectId: a.projectId ?? null,
|
||||
createdAt: a.createdAt ?? null,
|
||||
updatedAt: a.updatedAt ?? null,
|
||||
}))
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
aliases,
|
||||
count: aliases.length,
|
||||
hasMore: data.pagination?.next != null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
aliases: {
|
||||
type: 'array',
|
||||
description: 'List of aliases',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
uid: { type: 'string', description: 'Alias ID' },
|
||||
alias: { type: 'string', description: 'Alias hostname' },
|
||||
deploymentId: { type: 'string', description: 'Associated deployment ID' },
|
||||
projectId: { type: 'string', description: 'Associated project ID' },
|
||||
createdAt: { type: 'number', description: 'Creation timestamp in milliseconds' },
|
||||
updatedAt: { type: 'number', description: 'Last update timestamp in milliseconds' },
|
||||
},
|
||||
},
|
||||
},
|
||||
count: {
|
||||
type: 'number',
|
||||
description: 'Number of aliases returned',
|
||||
},
|
||||
hasMore: {
|
||||
type: 'boolean',
|
||||
description: 'Whether more aliases are available',
|
||||
},
|
||||
},
|
||||
}
|
||||
99
apps/sim/tools/vercel/list_checks.ts
Normal file
99
apps/sim/tools/vercel/list_checks.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelListChecksParams, VercelListChecksResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelListChecksTool: ToolConfig<VercelListChecksParams, VercelListChecksResponse> = {
|
||||
id: 'vercel_list_checks',
|
||||
name: 'Vercel List Checks',
|
||||
description: 'List all checks for a deployment',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
deploymentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Deployment ID to list checks for',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelListChecksParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v1/deployments/${params.deploymentId.trim()}/checks${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelListChecksParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const checks = (data.checks ?? []).map((check: Record<string, unknown>) => ({
|
||||
id: check.id,
|
||||
name: check.name,
|
||||
status: check.status ?? 'registered',
|
||||
conclusion: check.conclusion ?? null,
|
||||
blocking: check.blocking ?? false,
|
||||
deploymentId: check.deploymentId,
|
||||
integrationId: check.integrationId ?? null,
|
||||
externalId: check.externalId ?? null,
|
||||
detailsUrl: check.detailsUrl ?? null,
|
||||
path: check.path ?? null,
|
||||
rerequestable: check.rerequestable ?? false,
|
||||
createdAt: check.createdAt,
|
||||
updatedAt: check.updatedAt,
|
||||
startedAt: check.startedAt ?? null,
|
||||
completedAt: check.completedAt ?? null,
|
||||
}))
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
checks,
|
||||
count: checks.length,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
checks: {
|
||||
type: 'array',
|
||||
description: 'List of deployment checks',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Check ID' },
|
||||
name: { type: 'string', description: 'Check name' },
|
||||
status: { type: 'string', description: 'Check status' },
|
||||
conclusion: { type: 'string', description: 'Check conclusion' },
|
||||
blocking: { type: 'boolean', description: 'Whether the check blocks the deployment' },
|
||||
deploymentId: { type: 'string', description: 'Associated deployment ID' },
|
||||
integrationId: { type: 'string', description: 'Associated integration ID' },
|
||||
externalId: { type: 'string', description: 'External identifier' },
|
||||
detailsUrl: { type: 'string', description: 'URL with details about the check' },
|
||||
path: { type: 'string', description: 'Page path being checked' },
|
||||
rerequestable: { type: 'boolean', description: 'Whether the check can be rerequested' },
|
||||
createdAt: { type: 'number', description: 'Creation timestamp' },
|
||||
updatedAt: { type: 'number', description: 'Last update timestamp' },
|
||||
startedAt: { type: 'number', description: 'Start timestamp' },
|
||||
completedAt: { type: 'number', description: 'Completion timestamp' },
|
||||
},
|
||||
},
|
||||
},
|
||||
count: { type: 'number', description: 'Total number of checks' },
|
||||
},
|
||||
}
|
||||
114
apps/sim/tools/vercel/list_deployment_files.ts
Normal file
114
apps/sim/tools/vercel/list_deployment_files.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
VercelListDeploymentFilesParams,
|
||||
VercelListDeploymentFilesResponse,
|
||||
} from '@/tools/vercel/types'
|
||||
|
||||
export const vercelListDeploymentFilesTool: ToolConfig<
|
||||
VercelListDeploymentFilesParams,
|
||||
VercelListDeploymentFilesResponse
|
||||
> = {
|
||||
id: 'vercel_list_deployment_files',
|
||||
name: 'Vercel List Deployment Files',
|
||||
description: 'List files in a Vercel deployment',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
deploymentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The deployment ID to list files for',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelListDeploymentFilesParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v6/deployments/${params.deploymentId.trim()}/files${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelListDeploymentFilesParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const files = (Array.isArray(data) ? data : (data.files ?? [])).map((f: any) => ({
|
||||
name: f.name ?? null,
|
||||
type: f.type ?? null,
|
||||
uid: f.uid ?? null,
|
||||
mode: f.mode ?? null,
|
||||
contentType: f.contentType ?? null,
|
||||
children: f.children ?? [],
|
||||
}))
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
files,
|
||||
count: files.length,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
files: {
|
||||
type: 'array',
|
||||
description: 'List of deployment files',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string', description: 'The name of the file tree entry' },
|
||||
type: {
|
||||
type: 'string',
|
||||
description: 'File type: directory, file, symlink, lambda, middleware, or invalid',
|
||||
},
|
||||
uid: {
|
||||
type: 'string',
|
||||
description: 'Unique file identifier (only valid for file type)',
|
||||
optional: true,
|
||||
},
|
||||
mode: { type: 'number', description: 'File mode indicating file type and permissions' },
|
||||
contentType: {
|
||||
type: 'string',
|
||||
description: 'Content-type of the file (only valid for file type)',
|
||||
optional: true,
|
||||
},
|
||||
children: {
|
||||
type: 'array',
|
||||
description: 'Child files of the directory (only valid for directory type)',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string', description: 'File name' },
|
||||
type: { type: 'string', description: 'Entry type' },
|
||||
uid: { type: 'string', description: 'File identifier', optional: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
count: {
|
||||
type: 'number',
|
||||
description: 'Number of files returned',
|
||||
},
|
||||
},
|
||||
}
|
||||
170
apps/sim/tools/vercel/list_deployments.ts
Normal file
170
apps/sim/tools/vercel/list_deployments.ts
Normal file
@@ -0,0 +1,170 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
VercelListDeploymentsParams,
|
||||
VercelListDeploymentsResponse,
|
||||
} from '@/tools/vercel/types'
|
||||
|
||||
export const vercelListDeploymentsTool: ToolConfig<
|
||||
VercelListDeploymentsParams,
|
||||
VercelListDeploymentsResponse
|
||||
> = {
|
||||
id: 'vercel_list_deployments',
|
||||
name: 'Vercel List Deployments',
|
||||
description: 'List deployments for a Vercel project or team',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter deployments by project ID or name',
|
||||
},
|
||||
target: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter by environment: production or staging',
|
||||
},
|
||||
state: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter by state: BUILDING, ERROR, INITIALIZING, QUEUED, READY, CANCELED',
|
||||
},
|
||||
app: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter by deployment name',
|
||||
},
|
||||
since: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Get deployments created after this JavaScript timestamp',
|
||||
},
|
||||
until: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Get deployments created before this JavaScript timestamp',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of deployments to return per request',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelListDeploymentsParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.projectId) query.set('projectId', params.projectId.trim())
|
||||
if (params.target) query.set('target', params.target)
|
||||
if (params.state) query.set('state', params.state)
|
||||
if (params.app) query.set('app', params.app.trim())
|
||||
if (params.since) query.set('since', String(params.since))
|
||||
if (params.until) query.set('until', String(params.until))
|
||||
if (params.limit) query.set('limit', String(params.limit))
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v6/deployments${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelListDeploymentsParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const deployments = (data.deployments ?? []).map((d: any) => ({
|
||||
uid: d.uid,
|
||||
name: d.name,
|
||||
url: d.url ?? null,
|
||||
state: d.state ?? d.readyState ?? 'UNKNOWN',
|
||||
target: d.target ?? null,
|
||||
created: d.created ?? d.createdAt,
|
||||
projectId: d.projectId ?? '',
|
||||
source: d.source ?? '',
|
||||
inspectorUrl: d.inspectorUrl ?? '',
|
||||
creator: {
|
||||
uid: d.creator?.uid ?? '',
|
||||
email: d.creator?.email ?? '',
|
||||
username: d.creator?.username ?? '',
|
||||
},
|
||||
meta: d.meta ?? {},
|
||||
}))
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
deployments,
|
||||
count: deployments.length,
|
||||
hasMore: data.pagination?.next != null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
deployments: {
|
||||
type: 'array',
|
||||
description: 'List of deployments',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
uid: { type: 'string', description: 'Unique deployment identifier' },
|
||||
name: { type: 'string', description: 'Deployment name' },
|
||||
url: { type: 'string', description: 'Deployment URL', optional: true },
|
||||
state: {
|
||||
type: 'string',
|
||||
description:
|
||||
'Deployment state: BUILDING, ERROR, INITIALIZING, QUEUED, READY, CANCELED, DELETED',
|
||||
},
|
||||
target: { type: 'string', description: 'Target environment', optional: true },
|
||||
created: { type: 'number', description: 'Creation timestamp' },
|
||||
projectId: { type: 'string', description: 'Associated project ID' },
|
||||
source: {
|
||||
type: 'string',
|
||||
description:
|
||||
'Deployment source: api-trigger-git-deploy, cli, clone/repo, git, import, import/repo, redeploy, v0-web',
|
||||
},
|
||||
inspectorUrl: { type: 'string', description: 'Vercel inspector URL' },
|
||||
creator: {
|
||||
type: 'object',
|
||||
description: 'Creator information',
|
||||
properties: {
|
||||
uid: { type: 'string', description: 'Creator user ID' },
|
||||
email: { type: 'string', description: 'Creator email' },
|
||||
username: { type: 'string', description: 'Creator username' },
|
||||
},
|
||||
},
|
||||
meta: { type: 'object', description: 'Git provider metadata (key-value strings)' },
|
||||
},
|
||||
},
|
||||
},
|
||||
count: {
|
||||
type: 'number',
|
||||
description: 'Number of deployments returned',
|
||||
},
|
||||
hasMore: {
|
||||
type: 'boolean',
|
||||
description: 'Whether more deployments are available',
|
||||
},
|
||||
},
|
||||
}
|
||||
116
apps/sim/tools/vercel/list_dns_records.ts
Normal file
116
apps/sim/tools/vercel/list_dns_records.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelListDnsRecordsParams, VercelListDnsRecordsResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelListDnsRecordsTool: ToolConfig<
|
||||
VercelListDnsRecordsParams,
|
||||
VercelListDnsRecordsResponse
|
||||
> = {
|
||||
id: 'vercel_list_dns_records',
|
||||
name: 'Vercel List DNS Records',
|
||||
description: 'List all DNS records for a domain in a Vercel account',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The domain name to list records for',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of records to return',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelListDnsRecordsParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.limit) query.set('limit', String(params.limit))
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v4/domains/${params.domain.trim()}/records${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelListDnsRecordsParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const records = (data.records ?? []).map((r: any) => ({
|
||||
id: r.id ?? null,
|
||||
slug: r.slug ?? null,
|
||||
name: r.name ?? null,
|
||||
type: r.type ?? null,
|
||||
value: r.value ?? null,
|
||||
ttl: r.ttl ?? null,
|
||||
mxPriority: r.mxPriority ?? null,
|
||||
priority: r.priority ?? null,
|
||||
creator: r.creator ?? null,
|
||||
createdAt: r.createdAt ?? null,
|
||||
updatedAt: r.updatedAt ?? null,
|
||||
comment: r.comment ?? null,
|
||||
}))
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
records,
|
||||
count: records.length,
|
||||
hasMore: data.pagination?.next != null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
records: {
|
||||
type: 'array',
|
||||
description: 'List of DNS records',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Record ID' },
|
||||
slug: { type: 'string', description: 'Record slug' },
|
||||
name: { type: 'string', description: 'Record name' },
|
||||
type: {
|
||||
type: 'string',
|
||||
description: 'Record type (A, AAAA, ALIAS, CAA, CNAME, HTTPS, MX, SRV, TXT, NS)',
|
||||
},
|
||||
value: { type: 'string', description: 'Record value' },
|
||||
ttl: { type: 'number', description: 'Time to live in seconds' },
|
||||
mxPriority: { type: 'number', description: 'MX record priority' },
|
||||
priority: { type: 'number', description: 'Record priority' },
|
||||
creator: { type: 'string', description: 'Creator identifier' },
|
||||
createdAt: { type: 'number', description: 'Creation timestamp' },
|
||||
updatedAt: { type: 'number', description: 'Last update timestamp' },
|
||||
comment: { type: 'string', description: 'Record comment' },
|
||||
},
|
||||
},
|
||||
},
|
||||
count: {
|
||||
type: 'number',
|
||||
description: 'Number of records returned',
|
||||
},
|
||||
hasMore: {
|
||||
type: 'boolean',
|
||||
description: 'Whether more records are available',
|
||||
},
|
||||
},
|
||||
}
|
||||
109
apps/sim/tools/vercel/list_domains.ts
Normal file
109
apps/sim/tools/vercel/list_domains.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelListDomainsParams, VercelListDomainsResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelListDomainsTool: ToolConfig<VercelListDomainsParams, VercelListDomainsResponse> =
|
||||
{
|
||||
id: 'vercel_list_domains',
|
||||
name: 'Vercel List Domains',
|
||||
description: 'List all domains in a Vercel account or team',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of domains to return (default 20)',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelListDomainsParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.limit) query.set('limit', String(params.limit))
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v5/domains${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelListDomainsParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const domains = (data.domains ?? []).map((d: any) => ({
|
||||
id: d.id,
|
||||
name: d.name,
|
||||
verified: d.verified ?? false,
|
||||
createdAt: d.createdAt,
|
||||
expiresAt: d.expiresAt ?? null,
|
||||
serviceType: d.serviceType ?? 'external',
|
||||
nameservers: d.nameservers ?? [],
|
||||
intendedNameservers: d.intendedNameservers ?? [],
|
||||
renew: d.renew ?? false,
|
||||
boughtAt: d.boughtAt ?? null,
|
||||
}))
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
domains,
|
||||
count: domains.length,
|
||||
hasMore: data.pagination?.next != null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
domains: {
|
||||
type: 'array',
|
||||
description: 'List of domains',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Domain ID' },
|
||||
name: { type: 'string', description: 'Domain name' },
|
||||
verified: { type: 'boolean', description: 'Whether domain is verified' },
|
||||
createdAt: { type: 'number', description: 'Creation timestamp' },
|
||||
expiresAt: { type: 'number', description: 'Expiration timestamp' },
|
||||
serviceType: { type: 'string', description: 'Service type (zeit.world, external, na)' },
|
||||
nameservers: {
|
||||
type: 'array',
|
||||
description: 'Current nameservers',
|
||||
items: { type: 'string' },
|
||||
},
|
||||
intendedNameservers: {
|
||||
type: 'array',
|
||||
description: 'Intended nameservers',
|
||||
items: { type: 'string' },
|
||||
},
|
||||
renew: { type: 'boolean', description: 'Whether auto-renewal is enabled' },
|
||||
boughtAt: { type: 'number', description: 'Purchase timestamp' },
|
||||
},
|
||||
},
|
||||
},
|
||||
count: {
|
||||
type: 'number',
|
||||
description: 'Number of domains returned',
|
||||
},
|
||||
hasMore: {
|
||||
type: 'boolean',
|
||||
description: 'Whether more domains are available',
|
||||
},
|
||||
},
|
||||
}
|
||||
91
apps/sim/tools/vercel/list_edge_configs.ts
Normal file
91
apps/sim/tools/vercel/list_edge_configs.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
VercelListEdgeConfigsParams,
|
||||
VercelListEdgeConfigsResponse,
|
||||
} from '@/tools/vercel/types'
|
||||
|
||||
export const vercelListEdgeConfigsTool: ToolConfig<
|
||||
VercelListEdgeConfigsParams,
|
||||
VercelListEdgeConfigsResponse
|
||||
> = {
|
||||
id: 'vercel_list_edge_configs',
|
||||
name: 'Vercel List Edge Configs',
|
||||
description: 'List all Edge Config stores for a team',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelListEdgeConfigsParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v1/edge-config${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelListEdgeConfigsParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const items = Array.isArray(data) ? data : (data.edgeConfigs ?? [])
|
||||
const edgeConfigs = items.map((ec: any) => ({
|
||||
id: ec.id ?? null,
|
||||
slug: ec.slug ?? null,
|
||||
ownerId: ec.ownerId ?? null,
|
||||
digest: ec.digest ?? null,
|
||||
createdAt: ec.createdAt ?? null,
|
||||
updatedAt: ec.updatedAt ?? null,
|
||||
itemCount: ec.itemCount ?? 0,
|
||||
sizeInBytes: ec.sizeInBytes ?? 0,
|
||||
}))
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
edgeConfigs,
|
||||
count: edgeConfigs.length,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
edgeConfigs: {
|
||||
type: 'array',
|
||||
description: 'List of Edge Config stores',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Edge Config ID' },
|
||||
slug: { type: 'string', description: 'Edge Config slug' },
|
||||
ownerId: { type: 'string', description: 'Owner ID' },
|
||||
digest: { type: 'string', description: 'Content digest hash' },
|
||||
createdAt: { type: 'number', description: 'Creation timestamp' },
|
||||
updatedAt: { type: 'number', description: 'Last update timestamp' },
|
||||
itemCount: { type: 'number', description: 'Number of items' },
|
||||
sizeInBytes: { type: 'number', description: 'Size in bytes' },
|
||||
},
|
||||
},
|
||||
},
|
||||
count: {
|
||||
type: 'number',
|
||||
description: 'Number of Edge Configs returned',
|
||||
},
|
||||
},
|
||||
}
|
||||
116
apps/sim/tools/vercel/list_project_domains.ts
Normal file
116
apps/sim/tools/vercel/list_project_domains.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
VercelListProjectDomainsParams,
|
||||
VercelListProjectDomainsResponse,
|
||||
} from '@/tools/vercel/types'
|
||||
|
||||
export const vercelListProjectDomainsTool: ToolConfig<
|
||||
VercelListProjectDomainsParams,
|
||||
VercelListProjectDomainsResponse
|
||||
> = {
|
||||
id: 'vercel_list_project_domains',
|
||||
name: 'Vercel List Project Domains',
|
||||
description: 'List all domains for a Vercel project',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or name',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of domains to return',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelListProjectDomainsParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
if (params.limit) query.set('limit', String(params.limit))
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v9/projects/${params.projectId.trim()}/domains${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelListProjectDomainsParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const domains = (data.domains ?? []).map(
|
||||
(d: {
|
||||
name: string
|
||||
apexName: string
|
||||
redirect: string | null
|
||||
redirectStatusCode: number | null
|
||||
verified: boolean
|
||||
gitBranch: string | null
|
||||
createdAt: number
|
||||
updatedAt: number
|
||||
}) => ({
|
||||
name: d.name,
|
||||
apexName: d.apexName,
|
||||
redirect: d.redirect ?? null,
|
||||
redirectStatusCode: d.redirectStatusCode ?? null,
|
||||
verified: d.verified,
|
||||
gitBranch: d.gitBranch ?? null,
|
||||
createdAt: d.createdAt,
|
||||
updatedAt: d.updatedAt,
|
||||
})
|
||||
)
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
domains,
|
||||
count: domains.length,
|
||||
hasMore: data.pagination?.next != null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
domains: {
|
||||
type: 'array',
|
||||
description: 'List of project domains',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string', description: 'Domain name' },
|
||||
apexName: { type: 'string', description: 'Apex domain name' },
|
||||
redirect: { type: 'string', description: 'Redirect target', optional: true },
|
||||
redirectStatusCode: {
|
||||
type: 'number',
|
||||
description: 'Redirect status code',
|
||||
optional: true,
|
||||
},
|
||||
verified: { type: 'boolean', description: 'Whether the domain is verified' },
|
||||
gitBranch: { type: 'string', description: 'Git branch for the domain', optional: true },
|
||||
createdAt: { type: 'number', description: 'Creation timestamp' },
|
||||
updatedAt: { type: 'number', description: 'Last updated timestamp' },
|
||||
},
|
||||
},
|
||||
},
|
||||
count: { type: 'number', description: 'Number of domains returned' },
|
||||
hasMore: { type: 'boolean', description: 'Whether more domains are available' },
|
||||
},
|
||||
}
|
||||
106
apps/sim/tools/vercel/list_projects.ts
Normal file
106
apps/sim/tools/vercel/list_projects.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelListProjectsParams, VercelListProjectsResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelListProjectsTool: ToolConfig<
|
||||
VercelListProjectsParams,
|
||||
VercelListProjectsResponse
|
||||
> = {
|
||||
id: 'vercel_list_projects',
|
||||
name: 'Vercel List Projects',
|
||||
description: 'List all projects in a Vercel team or account',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
search: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Search projects by name',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of projects to return',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelListProjectsParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.search) query.set('search', params.search)
|
||||
if (params.limit) query.set('limit', String(params.limit))
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v10/projects${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelListProjectsParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const projects = (data.projects ?? []).map((p: any) => ({
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
framework: p.framework ?? null,
|
||||
createdAt: p.createdAt,
|
||||
updatedAt: p.updatedAt,
|
||||
domains: p.domains ?? [],
|
||||
}))
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
projects,
|
||||
count: projects.length,
|
||||
hasMore: data.pagination?.next != null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
projects: {
|
||||
type: 'array',
|
||||
description: 'List of projects',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Project ID' },
|
||||
name: { type: 'string', description: 'Project name' },
|
||||
framework: { type: 'string', description: 'Framework', optional: true },
|
||||
createdAt: { type: 'number', description: 'Creation timestamp' },
|
||||
updatedAt: { type: 'number', description: 'Last updated timestamp' },
|
||||
domains: {
|
||||
type: 'array',
|
||||
description: 'Project domains',
|
||||
items: { type: 'string', description: 'Domain' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
count: {
|
||||
type: 'number',
|
||||
description: 'Number of projects returned',
|
||||
},
|
||||
hasMore: {
|
||||
type: 'boolean',
|
||||
description: 'Whether more projects are available',
|
||||
},
|
||||
},
|
||||
}
|
||||
151
apps/sim/tools/vercel/list_team_members.ts
Normal file
151
apps/sim/tools/vercel/list_team_members.ts
Normal file
@@ -0,0 +1,151 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
VercelListTeamMembersParams,
|
||||
VercelListTeamMembersResponse,
|
||||
} from '@/tools/vercel/types'
|
||||
|
||||
export const vercelListTeamMembersTool: ToolConfig<
|
||||
VercelListTeamMembersParams,
|
||||
VercelListTeamMembersResponse
|
||||
> = {
|
||||
id: 'vercel_list_team_members',
|
||||
name: 'Vercel List Team Members',
|
||||
description: 'List all members of a Vercel team',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The team ID to list members for',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of members to return',
|
||||
},
|
||||
role: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Filter by role (OWNER, MEMBER, DEVELOPER, SECURITY, BILLING, VIEWER, VIEWER_FOR_PLUS, CONTRIBUTOR)',
|
||||
},
|
||||
since: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Timestamp in milliseconds to only include members added since then',
|
||||
},
|
||||
until: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Timestamp in milliseconds to only include members added until then',
|
||||
},
|
||||
search: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Search team members by their name, username, and email',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelListTeamMembersParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.limit) query.set('limit', String(params.limit))
|
||||
if (params.role) query.set('role', params.role.trim())
|
||||
if (params.since) query.set('since', String(params.since))
|
||||
if (params.until) query.set('until', String(params.until))
|
||||
if (params.search) query.set('search', params.search.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v3/teams/${params.teamId.trim()}/members${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelListTeamMembersParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const members = (data.members ?? []).map((m: any) => ({
|
||||
uid: m.uid ?? null,
|
||||
email: m.email ?? null,
|
||||
username: m.username ?? null,
|
||||
name: m.name ?? null,
|
||||
avatar: m.avatar ?? null,
|
||||
role: m.role ?? null,
|
||||
confirmed: m.confirmed ?? false,
|
||||
createdAt: m.createdAt ?? null,
|
||||
joinedFrom: m.joinedFrom
|
||||
? {
|
||||
origin: m.joinedFrom.origin ?? null,
|
||||
}
|
||||
: null,
|
||||
}))
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
members,
|
||||
count: members.length,
|
||||
pagination: data.pagination
|
||||
? {
|
||||
hasNext: data.pagination.hasNext ?? false,
|
||||
count: data.pagination.count ?? 0,
|
||||
}
|
||||
: null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
members: {
|
||||
type: 'array',
|
||||
description: 'List of team members',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
uid: { type: 'string', description: 'Member user ID' },
|
||||
email: { type: 'string', description: 'Member email' },
|
||||
username: { type: 'string', description: 'Member username' },
|
||||
name: { type: 'string', description: 'Member full name' },
|
||||
avatar: { type: 'string', description: 'Avatar file ID' },
|
||||
role: { type: 'string', description: 'Member role' },
|
||||
confirmed: { type: 'boolean', description: 'Whether membership is confirmed' },
|
||||
createdAt: { type: 'number', description: 'Join timestamp in milliseconds' },
|
||||
joinedFrom: {
|
||||
type: 'object',
|
||||
description: 'Origin of how the member joined',
|
||||
properties: {
|
||||
origin: { type: 'string', description: 'Join origin identifier' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
count: {
|
||||
type: 'number',
|
||||
description: 'Number of members returned',
|
||||
},
|
||||
pagination: {
|
||||
type: 'object',
|
||||
description: 'Pagination information',
|
||||
properties: {
|
||||
hasNext: { type: 'boolean', description: 'Whether there are more pages' },
|
||||
count: { type: 'number', description: 'Items in current page' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
132
apps/sim/tools/vercel/list_teams.ts
Normal file
132
apps/sim/tools/vercel/list_teams.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelListTeamsParams, VercelListTeamsResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelListTeamsTool: ToolConfig<VercelListTeamsParams, VercelListTeamsResponse> = {
|
||||
id: 'vercel_list_teams',
|
||||
name: 'Vercel List Teams',
|
||||
description: 'List all teams in a Vercel account',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of teams to return',
|
||||
},
|
||||
since: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Timestamp in milliseconds to only include teams created since then',
|
||||
},
|
||||
until: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Timestamp in milliseconds to only include teams created until then',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelListTeamsParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.limit) query.set('limit', String(params.limit))
|
||||
if (params.since) query.set('since', String(params.since))
|
||||
if (params.until) query.set('until', String(params.until))
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v2/teams${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelListTeamsParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const teams = (data.teams ?? []).map((t: any) => ({
|
||||
id: t.id ?? null,
|
||||
slug: t.slug ?? null,
|
||||
name: t.name ?? null,
|
||||
avatar: t.avatar ?? null,
|
||||
createdAt: t.createdAt ?? null,
|
||||
updatedAt: t.updatedAt ?? null,
|
||||
creatorId: t.creatorId ?? null,
|
||||
membership: t.membership
|
||||
? {
|
||||
role: t.membership.role ?? null,
|
||||
confirmed: t.membership.confirmed ?? false,
|
||||
created: t.membership.created ?? null,
|
||||
uid: t.membership.uid ?? null,
|
||||
teamId: t.membership.teamId ?? null,
|
||||
}
|
||||
: null,
|
||||
}))
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
teams,
|
||||
count: teams.length,
|
||||
pagination: data.pagination
|
||||
? {
|
||||
count: data.pagination.count ?? 0,
|
||||
next: data.pagination.next ?? null,
|
||||
prev: data.pagination.prev ?? null,
|
||||
}
|
||||
: null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
teams: {
|
||||
type: 'array',
|
||||
description: 'List of teams',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Team ID' },
|
||||
slug: { type: 'string', description: 'Team slug' },
|
||||
name: { type: 'string', description: 'Team name' },
|
||||
avatar: { type: 'string', description: 'Avatar file ID' },
|
||||
createdAt: { type: 'number', description: 'Creation timestamp in milliseconds' },
|
||||
updatedAt: { type: 'number', description: 'Last update timestamp in milliseconds' },
|
||||
creatorId: { type: 'string', description: 'User ID of team creator' },
|
||||
membership: {
|
||||
type: 'object',
|
||||
description: 'Current user membership details',
|
||||
properties: {
|
||||
role: { type: 'string', description: 'Membership role' },
|
||||
confirmed: { type: 'boolean', description: 'Whether membership is confirmed' },
|
||||
created: { type: 'number', description: 'Membership creation timestamp' },
|
||||
uid: { type: 'string', description: 'User ID of the member' },
|
||||
teamId: { type: 'string', description: 'Team ID' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
count: {
|
||||
type: 'number',
|
||||
description: 'Number of teams returned',
|
||||
},
|
||||
pagination: {
|
||||
type: 'object',
|
||||
description: 'Pagination information',
|
||||
properties: {
|
||||
count: { type: 'number', description: 'Items in current page' },
|
||||
next: { type: 'number', description: 'Timestamp for next page request' },
|
||||
prev: { type: 'number', description: 'Timestamp for previous page request' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
100
apps/sim/tools/vercel/list_webhooks.ts
Normal file
100
apps/sim/tools/vercel/list_webhooks.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelListWebhooksParams, VercelListWebhooksResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelListWebhooksTool: ToolConfig<
|
||||
VercelListWebhooksParams,
|
||||
VercelListWebhooksResponse
|
||||
> = {
|
||||
id: 'vercel_list_webhooks',
|
||||
name: 'Vercel List Webhooks',
|
||||
description: 'List webhooks for a Vercel project or team',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter webhooks by project ID',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelListWebhooksParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.projectId) query.set('projectId', params.projectId.trim())
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v1/webhooks${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: VercelListWebhooksParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
const webhooks = (Array.isArray(data) ? data : []).map((w: any) => ({
|
||||
id: w.id ?? null,
|
||||
url: w.url ?? null,
|
||||
events: w.events ?? [],
|
||||
ownerId: w.ownerId ?? null,
|
||||
projectIds: w.projectIds ?? [],
|
||||
createdAt: w.createdAt ?? null,
|
||||
updatedAt: w.updatedAt ?? null,
|
||||
}))
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
webhooks,
|
||||
count: webhooks.length,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
webhooks: {
|
||||
type: 'array',
|
||||
description: 'List of webhooks',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Webhook ID' },
|
||||
url: { type: 'string', description: 'Webhook URL' },
|
||||
events: {
|
||||
type: 'array',
|
||||
description: 'Events the webhook listens to',
|
||||
items: { type: 'string', description: 'Event name' },
|
||||
},
|
||||
ownerId: { type: 'string', description: 'Owner ID' },
|
||||
projectIds: {
|
||||
type: 'array',
|
||||
description: 'Associated project IDs',
|
||||
items: { type: 'string', description: 'Project ID' },
|
||||
},
|
||||
createdAt: { type: 'number', description: 'Creation timestamp' },
|
||||
updatedAt: { type: 'number', description: 'Last updated timestamp' },
|
||||
},
|
||||
},
|
||||
},
|
||||
count: {
|
||||
type: 'number',
|
||||
description: 'Number of webhooks returned',
|
||||
},
|
||||
},
|
||||
}
|
||||
65
apps/sim/tools/vercel/pause_project.ts
Normal file
65
apps/sim/tools/vercel/pause_project.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelPauseProjectParams, VercelPauseProjectResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelPauseProjectTool: ToolConfig<
|
||||
VercelPauseProjectParams,
|
||||
VercelPauseProjectResponse
|
||||
> = {
|
||||
id: 'vercel_pause_project',
|
||||
name: 'Vercel Pause Project',
|
||||
description: 'Pause a Vercel project',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or name',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelPauseProjectParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v1/projects/${params.projectId.trim()}/pause${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params: VercelPauseProjectParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
paused: data.paused ?? true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Project ID' },
|
||||
name: { type: 'string', description: 'Project name' },
|
||||
paused: { type: 'boolean', description: 'Whether the project is paused' },
|
||||
},
|
||||
}
|
||||
69
apps/sim/tools/vercel/remove_project_domain.ts
Normal file
69
apps/sim/tools/vercel/remove_project_domain.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
VercelRemoveProjectDomainParams,
|
||||
VercelRemoveProjectDomainResponse,
|
||||
} from '@/tools/vercel/types'
|
||||
|
||||
export const vercelRemoveProjectDomainTool: ToolConfig<
|
||||
VercelRemoveProjectDomainParams,
|
||||
VercelRemoveProjectDomainResponse
|
||||
> = {
|
||||
id: 'vercel_remove_project_domain',
|
||||
name: 'Vercel Remove Project Domain',
|
||||
description: 'Remove a domain from a Vercel project',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or name',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Domain name to remove',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelRemoveProjectDomainParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v9/projects/${params.projectId.trim()}/domains/${params.domain.trim()}${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'DELETE',
|
||||
headers: (params: VercelRemoveProjectDomainParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async () => {
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
deleted: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
deleted: { type: 'boolean', description: 'Whether the domain was successfully removed' },
|
||||
},
|
||||
}
|
||||
65
apps/sim/tools/vercel/rerequest_check.ts
Normal file
65
apps/sim/tools/vercel/rerequest_check.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelRerequestCheckParams, VercelRerequestCheckResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelRerequestCheckTool: ToolConfig<
|
||||
VercelRerequestCheckParams,
|
||||
VercelRerequestCheckResponse
|
||||
> = {
|
||||
id: 'vercel_rerequest_check',
|
||||
name: 'Vercel Rerequest Check',
|
||||
description: 'Rerequest a deployment check',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
deploymentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Deployment ID the check belongs to',
|
||||
},
|
||||
checkId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Check ID to rerequest',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelRerequestCheckParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v1/deployments/${params.deploymentId.trim()}/checks/${params.checkId.trim()}/rerequest${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params: VercelRerequestCheckParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async () => {
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
rerequested: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
rerequested: { type: 'boolean', description: 'Whether the check was successfully rerequested' },
|
||||
},
|
||||
}
|
||||
1025
apps/sim/tools/vercel/types.ts
Normal file
1025
apps/sim/tools/vercel/types.ts
Normal file
File diff suppressed because it is too large
Load Diff
65
apps/sim/tools/vercel/unpause_project.ts
Normal file
65
apps/sim/tools/vercel/unpause_project.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelUnpauseProjectParams, VercelUnpauseProjectResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelUnpauseProjectTool: ToolConfig<
|
||||
VercelUnpauseProjectParams,
|
||||
VercelUnpauseProjectResponse
|
||||
> = {
|
||||
id: 'vercel_unpause_project',
|
||||
name: 'Vercel Unpause Project',
|
||||
description: 'Unpause a Vercel project',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or name',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelUnpauseProjectParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v1/projects/${params.projectId.trim()}/unpause${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params: VercelUnpauseProjectParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
paused: data.paused ?? false,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Project ID' },
|
||||
name: { type: 'string', description: 'Project name' },
|
||||
paused: { type: 'boolean', description: 'Whether the project is paused' },
|
||||
},
|
||||
}
|
||||
159
apps/sim/tools/vercel/update_check.ts
Normal file
159
apps/sim/tools/vercel/update_check.ts
Normal file
@@ -0,0 +1,159 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelCheckResponse, VercelUpdateCheckParams } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelUpdateCheckTool: ToolConfig<VercelUpdateCheckParams, VercelCheckResponse> = {
|
||||
id: 'vercel_update_check',
|
||||
name: 'Vercel Update Check',
|
||||
description: 'Update an existing deployment check',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
deploymentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Deployment ID the check belongs to',
|
||||
},
|
||||
checkId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Check ID to update',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Updated name of the check',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Updated status: running or completed',
|
||||
},
|
||||
conclusion: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Check conclusion: canceled, failed, neutral, succeeded, or skipped',
|
||||
},
|
||||
detailsUrl: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'URL with details about the check',
|
||||
},
|
||||
externalId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'External identifier for the check',
|
||||
},
|
||||
path: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page path being checked',
|
||||
},
|
||||
output: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'JSON string with check output metrics',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelUpdateCheckParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v1/deployments/${params.deploymentId.trim()}/checks/${params.checkId.trim()}${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'PATCH',
|
||||
headers: (params: VercelUpdateCheckParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: VercelUpdateCheckParams) => {
|
||||
const body: Record<string, unknown> = {}
|
||||
if (params.name) body.name = params.name.trim()
|
||||
if (params.status) body.status = params.status
|
||||
if (params.conclusion) body.conclusion = params.conclusion
|
||||
if (params.detailsUrl) body.detailsUrl = params.detailsUrl
|
||||
if (params.externalId) body.externalId = params.externalId
|
||||
if (params.path) body.path = params.path
|
||||
if (params.output) {
|
||||
try {
|
||||
body.output = JSON.parse(params.output)
|
||||
} catch {
|
||||
body.output = params.output
|
||||
}
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
status: data.status ?? 'registered',
|
||||
conclusion: data.conclusion ?? null,
|
||||
blocking: data.blocking ?? false,
|
||||
deploymentId: data.deploymentId,
|
||||
integrationId: data.integrationId ?? null,
|
||||
externalId: data.externalId ?? null,
|
||||
detailsUrl: data.detailsUrl ?? null,
|
||||
path: data.path ?? null,
|
||||
rerequestable: data.rerequestable ?? false,
|
||||
createdAt: data.createdAt,
|
||||
updatedAt: data.updatedAt,
|
||||
startedAt: data.startedAt ?? null,
|
||||
completedAt: data.completedAt ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Check ID' },
|
||||
name: { type: 'string', description: 'Check name' },
|
||||
status: { type: 'string', description: 'Check status: registered, running, or completed' },
|
||||
conclusion: {
|
||||
type: 'string',
|
||||
description: 'Check conclusion: canceled, failed, neutral, succeeded, skipped, or stale',
|
||||
optional: true,
|
||||
},
|
||||
blocking: { type: 'boolean', description: 'Whether the check blocks the deployment' },
|
||||
deploymentId: { type: 'string', description: 'Associated deployment ID' },
|
||||
integrationId: { type: 'string', description: 'Associated integration ID', optional: true },
|
||||
externalId: { type: 'string', description: 'External identifier', optional: true },
|
||||
detailsUrl: { type: 'string', description: 'URL with details about the check', optional: true },
|
||||
path: { type: 'string', description: 'Page path being checked', optional: true },
|
||||
rerequestable: { type: 'boolean', description: 'Whether the check can be rerequested' },
|
||||
createdAt: { type: 'number', description: 'Creation timestamp in milliseconds' },
|
||||
updatedAt: { type: 'number', description: 'Last update timestamp in milliseconds' },
|
||||
startedAt: { type: 'number', description: 'Start timestamp in milliseconds', optional: true },
|
||||
completedAt: {
|
||||
type: 'number',
|
||||
description: 'Completion timestamp in milliseconds',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
77
apps/sim/tools/vercel/update_edge_config_items.ts
Normal file
77
apps/sim/tools/vercel/update_edge_config_items.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
VercelUpdateEdgeConfigItemsParams,
|
||||
VercelUpdateEdgeConfigItemsResponse,
|
||||
} from '@/tools/vercel/types'
|
||||
|
||||
export const vercelUpdateEdgeConfigItemsTool: ToolConfig<
|
||||
VercelUpdateEdgeConfigItemsParams,
|
||||
VercelUpdateEdgeConfigItemsResponse
|
||||
> = {
|
||||
id: 'vercel_update_edge_config_items',
|
||||
name: 'Vercel Update Edge Config Items',
|
||||
description: 'Create, update, upsert, or delete items in an Edge Config store',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
edgeConfigId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Edge Config ID to update items in',
|
||||
},
|
||||
items: {
|
||||
type: 'json',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Array of operations: [{operation: "create"|"update"|"upsert"|"delete", key: string, value?: any}]',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelUpdateEdgeConfigItemsParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v1/edge-config/${params.edgeConfigId.trim()}/items${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'PATCH',
|
||||
headers: (params: VercelUpdateEdgeConfigItemsParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: VercelUpdateEdgeConfigItemsParams) => {
|
||||
const parsedItems = typeof params.items === 'string' ? JSON.parse(params.items) : params.items
|
||||
return { items: parsedItems }
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async () => {
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
status: 'ok',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
status: {
|
||||
type: 'string',
|
||||
description: 'Operation status',
|
||||
},
|
||||
},
|
||||
}
|
||||
149
apps/sim/tools/vercel/update_env_var.ts
Normal file
149
apps/sim/tools/vercel/update_env_var.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelUpdateEnvVarParams, VercelUpdateEnvVarResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelUpdateEnvVarTool: ToolConfig<
|
||||
VercelUpdateEnvVarParams,
|
||||
VercelUpdateEnvVarResponse
|
||||
> = {
|
||||
id: 'vercel_update_env_var',
|
||||
name: 'Vercel Update Environment Variable',
|
||||
description: 'Update an environment variable for a Vercel project',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or name',
|
||||
},
|
||||
envId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Environment variable ID to update',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'New variable name',
|
||||
},
|
||||
value: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'New variable value',
|
||||
},
|
||||
target: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated list of target environments (production, preview, development)',
|
||||
},
|
||||
type: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Variable type: system, secret, encrypted, plain, or sensitive',
|
||||
},
|
||||
gitBranch: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Git branch to associate with the variable (requires target to include preview)',
|
||||
},
|
||||
comment: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comment to add context to the variable (max 500 characters)',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelUpdateEnvVarParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v9/projects/${params.projectId.trim()}/env/${params.envId.trim()}${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'PATCH',
|
||||
headers: (params: VercelUpdateEnvVarParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: VercelUpdateEnvVarParams) => {
|
||||
const body: Record<string, unknown> = {}
|
||||
if (params.key) body.key = params.key
|
||||
if (params.value) body.value = params.value
|
||||
if (params.target) body.target = params.target.split(',').map((t) => t.trim())
|
||||
if (params.type) body.type = params.type
|
||||
if (params.gitBranch) body.gitBranch = params.gitBranch
|
||||
if (params.comment) body.comment = params.comment
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
key: data.key,
|
||||
value: data.value ?? '',
|
||||
type: data.type ?? 'plain',
|
||||
target: data.target ?? [],
|
||||
gitBranch: data.gitBranch ?? null,
|
||||
comment: data.comment ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'Environment variable ID',
|
||||
},
|
||||
key: {
|
||||
type: 'string',
|
||||
description: 'Variable name',
|
||||
},
|
||||
value: {
|
||||
type: 'string',
|
||||
description: 'Variable value',
|
||||
},
|
||||
type: {
|
||||
type: 'string',
|
||||
description: 'Variable type (secret, system, encrypted, plain, sensitive)',
|
||||
},
|
||||
target: {
|
||||
type: 'array',
|
||||
description: 'Target environments',
|
||||
items: { type: 'string', description: 'Environment name' },
|
||||
},
|
||||
gitBranch: {
|
||||
type: 'string',
|
||||
description: 'Git branch filter',
|
||||
optional: true,
|
||||
},
|
||||
comment: {
|
||||
type: 'string',
|
||||
description: 'Comment providing context for the variable',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
106
apps/sim/tools/vercel/update_project.ts
Normal file
106
apps/sim/tools/vercel/update_project.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { VercelUpdateProjectParams, VercelUpdateProjectResponse } from '@/tools/vercel/types'
|
||||
|
||||
export const vercelUpdateProjectTool: ToolConfig<
|
||||
VercelUpdateProjectParams,
|
||||
VercelUpdateProjectResponse
|
||||
> = {
|
||||
id: 'vercel_update_project',
|
||||
name: 'Vercel Update Project',
|
||||
description: 'Update an existing Vercel project',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Vercel Access Token',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or name',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'New project name',
|
||||
},
|
||||
framework: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project framework (e.g. nextjs, remix, vite)',
|
||||
},
|
||||
buildCommand: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Custom build command',
|
||||
},
|
||||
outputDirectory: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Custom output directory',
|
||||
},
|
||||
installCommand: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Custom install command',
|
||||
},
|
||||
teamId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Team ID to scope the request',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: VercelUpdateProjectParams) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params.teamId) query.set('teamId', params.teamId.trim())
|
||||
const qs = query.toString()
|
||||
return `https://api.vercel.com/v9/projects/${params.projectId.trim()}${qs ? `?${qs}` : ''}`
|
||||
},
|
||||
method: 'PATCH',
|
||||
headers: (params: VercelUpdateProjectParams) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: VercelUpdateProjectParams) => {
|
||||
const body: Record<string, unknown> = {}
|
||||
if (params.name) body.name = params.name.trim()
|
||||
if (params.framework) body.framework = params.framework.trim()
|
||||
if (params.buildCommand) body.buildCommand = params.buildCommand.trim()
|
||||
if (params.outputDirectory) body.outputDirectory = params.outputDirectory.trim()
|
||||
if (params.installCommand) body.installCommand = params.installCommand.trim()
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
framework: data.framework ?? null,
|
||||
updatedAt: data.updatedAt,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Project ID' },
|
||||
name: { type: 'string', description: 'Project name' },
|
||||
framework: { type: 'string', description: 'Project framework', optional: true },
|
||||
updatedAt: { type: 'number', description: 'Last updated timestamp' },
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user