diff --git a/apps/docs/components/icons.tsx b/apps/docs/components/icons.tsx index dfb95dab2e..c31380d81c 100644 --- a/apps/docs/components/icons.tsx +++ b/apps/docs/components/icons.tsx @@ -5532,3 +5532,18 @@ export function OnePasswordIcon(props: SVGProps) { ) } + +export function VercelIcon(props: SVGProps) { + return ( + + + + + + ) +} diff --git a/apps/docs/components/ui/icon-mapping.ts b/apps/docs/components/ui/icon-mapping.ts index dc6b16f370..171d8461be 100644 --- a/apps/docs/components/ui/icon-mapping.ts +++ b/apps/docs/components/ui/icon-mapping.ts @@ -125,6 +125,7 @@ import { TTSIcon, TwilioIcon, TypeformIcon, + VercelIcon, VideoIcon, WealthboxIcon, WebflowIcon, @@ -262,6 +263,7 @@ export const blockTypeToIconMap: Record = { twilio_sms: TwilioIcon, twilio_voice: TwilioIcon, typeform: TypeformIcon, + vercel: VercelIcon, video_generator_v2: VideoIcon, vision_v2: EyeIcon, wealthbox: WealthboxIcon, diff --git a/apps/docs/content/docs/en/tools/meta.json b/apps/docs/content/docs/en/tools/meta.json index c10640a966..e19b01b3d5 100644 --- a/apps/docs/content/docs/en/tools/meta.json +++ b/apps/docs/content/docs/en/tools/meta.json @@ -122,6 +122,7 @@ "twilio_sms", "twilio_voice", "typeform", + "vercel", "video_generator", "vision", "wealthbox", diff --git a/apps/docs/content/docs/en/tools/vercel.mdx b/apps/docs/content/docs/en/tools/vercel.mdx new file mode 100644 index 0000000000..0baacc3f61 --- /dev/null +++ b/apps/docs/content/docs/en/tools/vercel.mdx @@ -0,0 +1,1391 @@ +--- +title: Vercel +description: Manage Vercel deployments, projects, and infrastructure +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[Vercel](https://vercel.com/) describes itself as **the AI Cloud**: a platform that provides developer tools and cloud infrastructure to build, scale, and secure faster, more personalized web experiences. It is widely used to build and ship modern web apps and agentic workloads, with built-in support for Git-based workflows, preview deployments, and production delivery. + +With Vercel, you can: + +- **Automate deployments**: Deploy from Git and manage preview and production releases with minimal operational overhead +- **Manage projects and teams**: Organize projects, team access, and settings across multiple environments +- **Control infrastructure settings**: Configure domains, DNS, aliases, environment variables, and edge settings in one place +- **Monitor and troubleshoot**: Track deployment status, inspect logs, and debug build or runtime issues + +In Sim, the Vercel integration lets your agents programmatically manage deployments, projects, domains, DNS records, aliases, environment variables, edge configs, and teams directly from workflows. You can automate deployment operations, react to status changes, and run infrastructure tasks as part of reliable, end-to-end delivery workflows. +{/* MANUAL-CONTENT-END */} + + +## Usage Instructions + +Integrate with Vercel to manage deployments, projects, domains, DNS records, environment variables, aliases, edge configs, teams, and more. + + + +## Tools + +### `vercel_list_deployments` + +List deployments for a Vercel project or team + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `projectId` | string | No | Filter deployments by project ID or name | +| `target` | string | No | Filter by environment: production or staging | +| `state` | string | No | Filter by state: BUILDING, ERROR, INITIALIZING, QUEUED, READY, CANCELED | +| `app` | string | No | Filter by deployment name | +| `since` | number | No | Get deployments created after this JavaScript timestamp | +| `until` | number | No | Get deployments created before this JavaScript timestamp | +| `limit` | number | No | Maximum number of deployments to return per request | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `deployments` | array | List of deployments | +| ↳ `uid` | string | Unique deployment identifier | +| ↳ `name` | string | Deployment name | +| ↳ `url` | string | Deployment URL | +| ↳ `state` | string | Deployment state: BUILDING, ERROR, INITIALIZING, QUEUED, READY, CANCELED, DELETED | +| ↳ `target` | string | Target environment | +| ↳ `created` | number | Creation timestamp | +| ↳ `projectId` | string | Associated project ID | +| ↳ `source` | string | Deployment source: api-trigger-git-deploy, cli, clone/repo, git, import, import/repo, redeploy, v0-web | +| ↳ `inspectorUrl` | string | Vercel inspector URL | +| ↳ `creator` | object | Creator information | +| ↳ `uid` | string | Creator user ID | +| ↳ `email` | string | Creator email | +| ↳ `username` | string | Creator username | +| ↳ `meta` | object | Git provider metadata \(key-value strings\) | +| `count` | number | Number of deployments returned | +| `hasMore` | boolean | Whether more deployments are available | + +### `vercel_get_deployment` + +Get details of a specific Vercel deployment + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `deploymentId` | string | Yes | The unique deployment identifier or hostname | +| `withGitRepoInfo` | string | No | Whether to add in gitRepo information \(true/false\) | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Deployment ID | +| `name` | string | Deployment name | +| `url` | string | Unique deployment URL | +| `readyState` | string | Deployment ready state: QUEUED, BUILDING, ERROR, INITIALIZING, READY, CANCELED | +| `status` | string | Deployment status | +| `target` | string | Target environment | +| `createdAt` | number | Creation timestamp in milliseconds | +| `buildingAt` | number | Build start timestamp | +| `ready` | number | Ready timestamp | +| `source` | string | Deployment source: cli, git, redeploy, import, v0-web, etc. | +| `alias` | array | Assigned aliases | +| `regions` | array | Deployment regions | +| `inspectorUrl` | string | Vercel inspector URL | +| `projectId` | string | Associated project ID | +| `creator` | object | Creator information | +| ↳ `uid` | string | Creator user ID | +| ↳ `username` | string | Creator username | +| `project` | object | Associated project | +| ↳ `id` | string | Project ID | +| ↳ `name` | string | Project name | +| ↳ `framework` | string | Project framework | +| `meta` | object | Deployment metadata \(key-value strings\) | +| ↳ `githubCommitSha` | string | GitHub commit SHA | +| ↳ `githubCommitMessage` | string | GitHub commit message | +| ↳ `githubCommitRef` | string | GitHub branch/ref | +| ↳ `githubRepo` | string | GitHub repository | +| ↳ `githubOrg` | string | GitHub organization | +| ↳ `githubCommitAuthorName` | string | Commit author name | +| `gitSource` | object | Git source information | +| ↳ `type` | string | Git provider type \(e.g., github, gitlab, bitbucket\) | +| ↳ `ref` | string | Git ref \(branch or tag\) | +| ↳ `sha` | string | Git commit SHA | +| ↳ `repoId` | string | Repository ID | + +### `vercel_create_deployment` + +Create a new deployment or redeploy an existing one + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `name` | string | Yes | Project name for the deployment | +| `project` | string | No | Project ID \(overrides name for project lookup\) | +| `deploymentId` | string | No | Existing deployment ID to redeploy | +| `target` | string | No | Target environment: production, staging, or a custom environment identifier | +| `gitSource` | string | No | JSON string defining the Git Repository source to deploy \(e.g. \{"type":"github","repo":"owner/repo","ref":"main"\}\) | +| `forceNew` | string | No | Forces a new deployment even if there is a previous similar deployment \(0 or 1\) | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Deployment ID | +| `name` | string | Deployment name | +| `url` | string | Unique deployment URL | +| `readyState` | string | Deployment ready state: QUEUED, BUILDING, ERROR, INITIALIZING, READY, CANCELED | +| `projectId` | string | Associated project ID | +| `createdAt` | number | Creation timestamp in milliseconds | +| `alias` | array | Assigned aliases | +| `target` | string | Target environment | +| `inspectorUrl` | string | Vercel inspector URL | + +### `vercel_cancel_deployment` + +Cancel a running Vercel deployment + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `deploymentId` | string | Yes | The deployment ID to cancel | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Deployment ID | +| `name` | string | Deployment name | +| `state` | string | Deployment state after cancellation | +| `url` | string | Deployment URL | + +### `vercel_delete_deployment` + +Delete a Vercel deployment + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `deploymentId` | string | Yes | The deployment ID or URL to delete | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `uid` | string | The removed deployment ID | +| `state` | string | Deployment state after deletion \(DELETED\) | + +### `vercel_get_deployment_events` + +Get build and runtime events for a Vercel deployment + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `deploymentId` | string | Yes | The unique deployment identifier or hostname | +| `direction` | string | No | Order of events by timestamp: backward or forward \(default: forward\) | +| `follow` | number | No | When set to 1, returns live events as they happen | +| `limit` | number | No | Maximum number of events to return \(-1 for all\) | +| `since` | number | No | Timestamp to start pulling build logs from | +| `until` | number | No | Timestamp to stop pulling build logs at | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `events` | array | List of deployment events | +| ↳ `type` | string | Event type: delimiter, command, stdout, stderr, exit, deployment-state, middleware, middleware-invocation, edge-function-invocation, metric, report, fatal | +| ↳ `created` | number | Event creation timestamp | +| ↳ `date` | number | Event date timestamp | +| ↳ `text` | string | Event text content | +| ↳ `serial` | string | Event serial identifier | +| ↳ `deploymentId` | string | Associated deployment ID | +| ↳ `id` | string | Event unique identifier | +| ↳ `level` | string | Event level: error or warning | +| `count` | number | Number of events returned | + +### `vercel_list_deployment_files` + +List files in a Vercel deployment + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `deploymentId` | string | Yes | The deployment ID to list files for | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `files` | array | List of deployment files | +| ↳ `name` | string | The name of the file tree entry | +| ↳ `type` | string | File type: directory, file, symlink, lambda, middleware, or invalid | +| ↳ `uid` | string | Unique file identifier \(only valid for file type\) | +| ↳ `mode` | number | File mode indicating file type and permissions | +| ↳ `contentType` | string | Content-type of the file \(only valid for file type\) | +| ↳ `children` | array | Child files of the directory \(only valid for directory type\) | +| ↳ `name` | string | File name | +| ↳ `type` | string | Entry type | +| ↳ `uid` | string | File identifier | +| `count` | number | Number of files returned | + +### `vercel_list_projects` + +List all projects in a Vercel team or account + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `search` | string | No | Search projects by name | +| `limit` | number | No | Maximum number of projects to return | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `projects` | array | List of projects | +| ↳ `id` | string | Project ID | +| ↳ `name` | string | Project name | +| ↳ `framework` | string | Framework | +| ↳ `createdAt` | number | Creation timestamp | +| ↳ `updatedAt` | number | Last updated timestamp | +| ↳ `domains` | array | Project domains | +| `count` | number | Number of projects returned | +| `hasMore` | boolean | Whether more projects are available | + +### `vercel_get_project` + +Get details of a specific Vercel project + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `projectId` | string | Yes | Project ID or name | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Project ID | +| `name` | string | Project name | +| `framework` | string | Project framework | +| `createdAt` | number | Creation timestamp | +| `updatedAt` | number | Last updated timestamp | +| `domains` | array | Project domains | +| `link` | object | Git repository connection | +| ↳ `type` | string | Repository type \(github, gitlab, bitbucket\) | +| ↳ `repo` | string | Repository name | +| ↳ `org` | string | Organization or owner | + +### `vercel_create_project` + +Create a new Vercel project + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `name` | string | Yes | Project name | +| `framework` | string | No | Project framework \(e.g. nextjs, remix, vite\) | +| `gitRepository` | json | No | Git repository connection object with type and repo | +| `buildCommand` | string | No | Custom build command | +| `outputDirectory` | string | No | Custom output directory | +| `installCommand` | string | No | Custom install command | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Project ID | +| `name` | string | Project name | +| `framework` | string | Project framework | +| `createdAt` | number | Creation timestamp | +| `updatedAt` | number | Last updated timestamp | + +### `vercel_update_project` + +Update an existing Vercel project + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `projectId` | string | Yes | Project ID or name | +| `name` | string | No | New project name | +| `framework` | string | No | Project framework \(e.g. nextjs, remix, vite\) | +| `buildCommand` | string | No | Custom build command | +| `outputDirectory` | string | No | Custom output directory | +| `installCommand` | string | No | Custom install command | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Project ID | +| `name` | string | Project name | +| `framework` | string | Project framework | +| `updatedAt` | number | Last updated timestamp | + +### `vercel_delete_project` + +Delete a Vercel project + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `projectId` | string | Yes | Project ID or name | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `deleted` | boolean | Whether the project was successfully deleted | + +### `vercel_pause_project` + +Pause a Vercel project + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `projectId` | string | Yes | Project ID or name | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Project ID | +| `name` | string | Project name | +| `paused` | boolean | Whether the project is paused | + +### `vercel_unpause_project` + +Unpause a Vercel project + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `projectId` | string | Yes | Project ID or name | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Project ID | +| `name` | string | Project name | +| `paused` | boolean | Whether the project is paused | + +### `vercel_list_project_domains` + +List all domains for a Vercel project + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `projectId` | string | Yes | Project ID or name | +| `teamId` | string | No | Team ID to scope the request | +| `limit` | number | No | Maximum number of domains to return | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `domains` | array | List of project domains | +| ↳ `name` | string | Domain name | +| ↳ `apexName` | string | Apex domain name | +| ↳ `redirect` | string | Redirect target | +| ↳ `redirectStatusCode` | number | Redirect status code | +| ↳ `verified` | boolean | Whether the domain is verified | +| ↳ `gitBranch` | string | Git branch for the domain | +| ↳ `createdAt` | number | Creation timestamp | +| ↳ `updatedAt` | number | Last updated timestamp | +| `count` | number | Number of domains returned | +| `hasMore` | boolean | Whether more domains are available | + +### `vercel_add_project_domain` + +Add a domain to a Vercel project + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `projectId` | string | Yes | Project ID or name | +| `domain` | string | Yes | Domain name to add | +| `redirect` | string | No | Target domain for redirect | +| `redirectStatusCode` | number | No | HTTP status code for redirect \(301, 302, 307, 308\) | +| `gitBranch` | string | No | Git branch to link the domain to | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `name` | string | Domain name | +| `apexName` | string | Apex domain name | +| `verified` | boolean | Whether the domain is verified | +| `gitBranch` | string | Git branch for the domain | +| `redirect` | string | Redirect target domain | +| `redirectStatusCode` | number | HTTP status code for redirect \(301, 302, 307, 308\) | +| `createdAt` | number | Creation timestamp | +| `updatedAt` | number | Last updated timestamp | + +### `vercel_remove_project_domain` + +Remove a domain from a Vercel project + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `projectId` | string | Yes | Project ID or name | +| `domain` | string | Yes | Domain name to remove | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `deleted` | boolean | Whether the domain was successfully removed | + +### `vercel_get_env_vars` + +Retrieve environment variables for a Vercel project + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `projectId` | string | Yes | Project ID or name | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `envs` | array | List of environment variables | +| ↳ `id` | string | Environment variable ID | +| ↳ `key` | string | Variable name | +| ↳ `value` | string | Variable value | +| ↳ `type` | string | Variable type \(secret, system, encrypted, plain, sensitive\) | +| ↳ `target` | array | Target environments | +| ↳ `gitBranch` | string | Git branch filter | +| ↳ `comment` | string | Comment providing context for the variable | +| `count` | number | Number of environment variables returned | + +### `vercel_create_env_var` + +Create an environment variable for a Vercel project + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `projectId` | string | Yes | Project ID or name | +| `key` | string | Yes | Environment variable name | +| `value` | string | Yes | Environment variable value | +| `target` | string | Yes | Comma-separated list of target environments \(production, preview, development\) | +| `type` | string | No | Variable type: system, secret, encrypted, plain, or sensitive \(default: plain\) | +| `gitBranch` | string | No | Git branch to associate with the variable \(requires target to include preview\) | +| `comment` | string | No | Comment to add context to the variable \(max 500 characters\) | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Environment variable ID | +| `key` | string | Variable name | +| `value` | string | Variable value | +| `type` | string | Variable type \(secret, system, encrypted, plain, sensitive\) | +| `target` | array | Target environments | +| `gitBranch` | string | Git branch filter | +| `comment` | string | Comment providing context for the variable | + +### `vercel_update_env_var` + +Update an environment variable for a Vercel project + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `projectId` | string | Yes | Project ID or name | +| `envId` | string | Yes | Environment variable ID to update | +| `key` | string | No | New variable name | +| `value` | string | No | New variable value | +| `target` | string | No | Comma-separated list of target environments \(production, preview, development\) | +| `type` | string | No | Variable type: system, secret, encrypted, plain, or sensitive | +| `gitBranch` | string | No | Git branch to associate with the variable \(requires target to include preview\) | +| `comment` | string | No | Comment to add context to the variable \(max 500 characters\) | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Environment variable ID | +| `key` | string | Variable name | +| `value` | string | Variable value | +| `type` | string | Variable type \(secret, system, encrypted, plain, sensitive\) | +| `target` | array | Target environments | +| `gitBranch` | string | Git branch filter | +| `comment` | string | Comment providing context for the variable | + +### `vercel_delete_env_var` + +Delete an environment variable from a Vercel project + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `projectId` | string | Yes | Project ID or name | +| `envId` | string | Yes | Environment variable ID to delete | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `deleted` | boolean | Whether the environment variable was successfully deleted | + +### `vercel_list_domains` + +List all domains in a Vercel account or team + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `limit` | number | No | Maximum number of domains to return \(default 20\) | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `domains` | array | List of domains | +| ↳ `id` | string | Domain ID | +| ↳ `name` | string | Domain name | +| ↳ `verified` | boolean | Whether domain is verified | +| ↳ `createdAt` | number | Creation timestamp | +| ↳ `expiresAt` | number | Expiration timestamp | +| ↳ `serviceType` | string | Service type \(zeit.world, external, na\) | +| ↳ `nameservers` | array | Current nameservers | +| ↳ `intendedNameservers` | array | Intended nameservers | +| ↳ `renew` | boolean | Whether auto-renewal is enabled | +| ↳ `boughtAt` | number | Purchase timestamp | +| `count` | number | Number of domains returned | +| `hasMore` | boolean | Whether more domains are available | + +### `vercel_get_domain` + +Get information about a specific domain in a Vercel account + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `domain` | string | Yes | The domain name to retrieve | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Domain ID | +| `name` | string | Domain name | +| `verified` | boolean | Whether domain is verified | +| `createdAt` | number | Creation timestamp | +| `expiresAt` | number | Expiration timestamp | +| `serviceType` | string | Service type \(zeit.world, external, na\) | +| `nameservers` | array | Current nameservers | +| `intendedNameservers` | array | Intended nameservers | +| `customNameservers` | array | Custom nameservers | +| `renew` | boolean | Whether auto-renewal is enabled | +| `boughtAt` | number | Purchase timestamp | +| `transferredAt` | number | Transfer completion timestamp | + +### `vercel_add_domain` + +Add a new domain to a Vercel account or team + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `name` | string | Yes | The domain name to add | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Domain ID | +| `name` | string | Domain name | +| `verified` | boolean | Whether domain is verified | +| `createdAt` | number | Creation timestamp | +| `serviceType` | string | Service type \(zeit.world, external, na\) | +| `nameservers` | array | Current nameservers | +| `intendedNameservers` | array | Intended nameservers | + +### `vercel_delete_domain` + +Delete a domain from a Vercel account or team + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `domain` | string | Yes | The domain name to delete | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `uid` | string | The ID of the deleted domain | +| `deleted` | boolean | Whether the domain was deleted | + +### `vercel_get_domain_config` + +Get the configuration for a domain in a Vercel account + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `domain` | string | Yes | The domain name to get configuration for | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `configuredBy` | string | How the domain is configured \(CNAME, A, http, dns-01, or null\) | +| `acceptedChallenges` | array | Accepted challenge types for certificate issuance \(dns-01, http-01\) | +| `misconfigured` | boolean | Whether the domain is misconfigured for TLS certificate generation | +| `recommendedIPv4` | array | Recommended IPv4 addresses with rank values | +| ↳ `rank` | number | Priority rank \(1 is preferred\) | +| ↳ `value` | array | IPv4 addresses | +| `recommendedCNAME` | array | Recommended CNAME records with rank values | +| ↳ `rank` | number | Priority rank \(1 is preferred\) | +| ↳ `value` | string | CNAME value | + +### `vercel_list_dns_records` + +List all DNS records for a domain in a Vercel account + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `domain` | string | Yes | The domain name to list records for | +| `limit` | number | No | Maximum number of records to return | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `records` | array | List of DNS records | +| ↳ `id` | string | Record ID | +| ↳ `slug` | string | Record slug | +| ↳ `name` | string | Record name | +| ↳ `type` | string | Record type \(A, AAAA, ALIAS, CAA, CNAME, HTTPS, MX, SRV, TXT, NS\) | +| ↳ `value` | string | Record value | +| ↳ `ttl` | number | Time to live in seconds | +| ↳ `mxPriority` | number | MX record priority | +| ↳ `priority` | number | Record priority | +| ↳ `creator` | string | Creator identifier | +| ↳ `createdAt` | number | Creation timestamp | +| ↳ `updatedAt` | number | Last update timestamp | +| ↳ `comment` | string | Record comment | +| `count` | number | Number of records returned | +| `hasMore` | boolean | Whether more records are available | + +### `vercel_create_dns_record` + +Create a DNS record for a domain in a Vercel account + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `domain` | string | Yes | The domain name to create the record for | +| `recordName` | string | Yes | The subdomain or record name | +| `recordType` | string | Yes | DNS record type \(A, AAAA, ALIAS, CAA, CNAME, HTTPS, MX, SRV, TXT, NS\) | +| `value` | string | Yes | The value of the DNS record | +| `ttl` | number | No | Time to live in seconds | +| `mxPriority` | number | No | Priority for MX records | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `uid` | string | The DNS record ID | +| `updated` | number | Timestamp of the update | + +### `vercel_delete_dns_record` + +Delete a DNS record for a domain in a Vercel account + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `domain` | string | Yes | The domain name the record belongs to | +| `recordId` | string | Yes | The ID of the DNS record to delete | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `deleted` | boolean | Whether the record was deleted | + +### `vercel_list_aliases` + +List aliases for a Vercel project or team + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `projectId` | string | No | Filter aliases by project ID | +| `domain` | string | No | Filter aliases by domain | +| `limit` | number | No | Maximum number of aliases to return | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `aliases` | array | List of aliases | +| ↳ `uid` | string | Alias ID | +| ↳ `alias` | string | Alias hostname | +| ↳ `deploymentId` | string | Associated deployment ID | +| ↳ `projectId` | string | Associated project ID | +| ↳ `createdAt` | number | Creation timestamp in milliseconds | +| ↳ `updatedAt` | number | Last update timestamp in milliseconds | +| `count` | number | Number of aliases returned | +| `hasMore` | boolean | Whether more aliases are available | + +### `vercel_get_alias` + +Get details about a specific alias by ID or hostname + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `aliasId` | string | Yes | Alias ID or hostname to look up | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `uid` | string | Alias ID | +| `alias` | string | Alias hostname | +| `deploymentId` | string | Associated deployment ID | +| `projectId` | string | Associated project ID | +| `createdAt` | number | Creation timestamp in milliseconds | +| `updatedAt` | number | Last update timestamp in milliseconds | +| `redirect` | string | Target domain for redirect aliases | +| `redirectStatusCode` | number | HTTP status code for redirect \(301, 302, 307, or 308\) | + +### `vercel_create_alias` + +Assign an alias (domain/subdomain) to a deployment + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `deploymentId` | string | Yes | Deployment ID to assign the alias to | +| `alias` | string | Yes | The domain or subdomain to assign as an alias | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `uid` | string | Alias ID | +| `alias` | string | Alias hostname | +| `created` | string | Creation timestamp as ISO 8601 date-time string | +| `oldDeploymentId` | string | ID of the previously aliased deployment, if the alias was reassigned | + +### `vercel_delete_alias` + +Delete an alias by its ID + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `aliasId` | string | Yes | Alias ID to delete | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `status` | string | Deletion status \(SUCCESS\) | + +### `vercel_list_edge_configs` + +List all Edge Config stores for a team + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `edgeConfigs` | array | List of Edge Config stores | +| ↳ `id` | string | Edge Config ID | +| ↳ `slug` | string | Edge Config slug | +| ↳ `ownerId` | string | Owner ID | +| ↳ `digest` | string | Content digest hash | +| ↳ `createdAt` | number | Creation timestamp | +| ↳ `updatedAt` | number | Last update timestamp | +| ↳ `itemCount` | number | Number of items | +| ↳ `sizeInBytes` | number | Size in bytes | +| `count` | number | Number of Edge Configs returned | + +### `vercel_get_edge_config` + +Get details about a specific Edge Config store + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `edgeConfigId` | string | Yes | Edge Config ID to look up | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Edge Config ID | +| `slug` | string | Edge Config slug | +| `ownerId` | string | Owner ID | +| `digest` | string | Content digest hash | +| `createdAt` | number | Creation timestamp | +| `updatedAt` | number | Last update timestamp | +| `itemCount` | number | Number of items | +| `sizeInBytes` | number | Size in bytes | + +### `vercel_create_edge_config` + +Create a new Edge Config store + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `slug` | string | Yes | The name/slug for the new Edge Config | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Edge Config ID | +| `slug` | string | Edge Config slug | +| `ownerId` | string | Owner ID | +| `digest` | string | Content digest hash | +| `createdAt` | number | Creation timestamp | +| `updatedAt` | number | Last update timestamp | +| `itemCount` | number | Number of items | +| `sizeInBytes` | number | Size in bytes | + +### `vercel_get_edge_config_items` + +Get all items in an Edge Config store + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `edgeConfigId` | string | Yes | Edge Config ID to get items from | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `items` | array | List of Edge Config items | +| ↳ `key` | string | Item key | +| ↳ `value` | json | Item value | +| ↳ `description` | string | Item description | +| ↳ `edgeConfigId` | string | Parent Edge Config ID | +| ↳ `createdAt` | number | Creation timestamp | +| ↳ `updatedAt` | number | Last update timestamp | +| `count` | number | Number of items returned | + +### `vercel_update_edge_config_items` + +Create, update, upsert, or delete items in an Edge Config store + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `edgeConfigId` | string | Yes | Edge Config ID to update items in | +| `items` | json | Yes | Array of operations: \[\{operation: "create"\|"update"\|"upsert"\|"delete", key: string, value?: any\}\] | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `status` | string | Operation status | + +### `vercel_list_webhooks` + +List webhooks for a Vercel project or team + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `projectId` | string | No | Filter webhooks by project ID | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `webhooks` | array | List of webhooks | +| ↳ `id` | string | Webhook ID | +| ↳ `url` | string | Webhook URL | +| ↳ `events` | array | Events the webhook listens to | +| ↳ `ownerId` | string | Owner ID | +| ↳ `projectIds` | array | Associated project IDs | +| ↳ `createdAt` | number | Creation timestamp | +| ↳ `updatedAt` | number | Last updated timestamp | +| `count` | number | Number of webhooks returned | + +### `vercel_create_webhook` + +Create a new webhook for a Vercel team + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `url` | string | Yes | Webhook URL \(must be https\) | +| `events` | string | Yes | Comma-separated event names to subscribe to | +| `projectIds` | string | No | Comma-separated project IDs to scope the webhook to | +| `teamId` | string | Yes | Team ID to create the webhook for | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Webhook ID | +| `url` | string | Webhook URL | +| `secret` | string | Webhook signing secret | +| `events` | array | Events the webhook listens to | +| `ownerId` | string | Owner ID | +| `projectIds` | array | Associated project IDs | +| `createdAt` | number | Creation timestamp | +| `updatedAt` | number | Last updated timestamp | + +### `vercel_delete_webhook` + +Delete a webhook from a Vercel team + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `webhookId` | string | Yes | The webhook ID to delete | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `deleted` | boolean | Whether the webhook was successfully deleted | + +### `vercel_create_check` + +Create a new deployment check + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `deploymentId` | string | Yes | Deployment ID to create the check for | +| `name` | string | Yes | Name of the check \(max 100 characters\) | +| `blocking` | boolean | Yes | Whether the check blocks the deployment | +| `path` | string | No | Page path being checked | +| `detailsUrl` | string | No | URL with details about the check | +| `externalId` | string | No | External identifier for the check | +| `rerequestable` | boolean | No | Whether the check can be rerequested | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Check ID | +| `name` | string | Check name | +| `status` | string | Check status: registered, running, or completed | +| `conclusion` | string | Check conclusion: canceled, failed, neutral, succeeded, skipped, or stale | +| `blocking` | boolean | Whether the check blocks the deployment | +| `deploymentId` | string | Associated deployment ID | +| `integrationId` | string | Associated integration ID | +| `externalId` | string | External identifier | +| `detailsUrl` | string | URL with details about the check | +| `path` | string | Page path being checked | +| `rerequestable` | boolean | Whether the check can be rerequested | +| `createdAt` | number | Creation timestamp in milliseconds | +| `updatedAt` | number | Last update timestamp in milliseconds | +| `startedAt` | number | Start timestamp in milliseconds | +| `completedAt` | number | Completion timestamp in milliseconds | + +### `vercel_get_check` + +Get details of a specific deployment check + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `deploymentId` | string | Yes | Deployment ID the check belongs to | +| `checkId` | string | Yes | Check ID to retrieve | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Check ID | +| `name` | string | Check name | +| `status` | string | Check status: registered, running, or completed | +| `conclusion` | string | Check conclusion: canceled, failed, neutral, succeeded, skipped, or stale | +| `blocking` | boolean | Whether the check blocks the deployment | +| `deploymentId` | string | Associated deployment ID | +| `integrationId` | string | Associated integration ID | +| `externalId` | string | External identifier | +| `detailsUrl` | string | URL with details about the check | +| `path` | string | Page path being checked | +| `rerequestable` | boolean | Whether the check can be rerequested | +| `createdAt` | number | Creation timestamp in milliseconds | +| `updatedAt` | number | Last update timestamp in milliseconds | +| `startedAt` | number | Start timestamp in milliseconds | +| `completedAt` | number | Completion timestamp in milliseconds | + +### `vercel_list_checks` + +List all checks for a deployment + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `deploymentId` | string | Yes | Deployment ID to list checks for | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `checks` | array | List of deployment checks | +| ↳ `id` | string | Check ID | +| ↳ `name` | string | Check name | +| ↳ `status` | string | Check status | +| ↳ `conclusion` | string | Check conclusion | +| ↳ `blocking` | boolean | Whether the check blocks the deployment | +| ↳ `deploymentId` | string | Associated deployment ID | +| ↳ `integrationId` | string | Associated integration ID | +| ↳ `externalId` | string | External identifier | +| ↳ `detailsUrl` | string | URL with details about the check | +| ↳ `path` | string | Page path being checked | +| ↳ `rerequestable` | boolean | Whether the check can be rerequested | +| ↳ `createdAt` | number | Creation timestamp | +| ↳ `updatedAt` | number | Last update timestamp | +| ↳ `startedAt` | number | Start timestamp | +| ↳ `completedAt` | number | Completion timestamp | +| `count` | number | Total number of checks | + +### `vercel_update_check` + +Update an existing deployment check + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `deploymentId` | string | Yes | Deployment ID the check belongs to | +| `checkId` | string | Yes | Check ID to update | +| `name` | string | No | Updated name of the check | +| `status` | string | No | Updated status: running or completed | +| `conclusion` | string | No | Check conclusion: canceled, failed, neutral, succeeded, or skipped | +| `detailsUrl` | string | No | URL with details about the check | +| `externalId` | string | No | External identifier for the check | +| `path` | string | No | Page path being checked | +| `output` | string | No | JSON string with check output metrics | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Check ID | +| `name` | string | Check name | +| `status` | string | Check status: registered, running, or completed | +| `conclusion` | string | Check conclusion: canceled, failed, neutral, succeeded, skipped, or stale | +| `blocking` | boolean | Whether the check blocks the deployment | +| `deploymentId` | string | Associated deployment ID | +| `integrationId` | string | Associated integration ID | +| `externalId` | string | External identifier | +| `detailsUrl` | string | URL with details about the check | +| `path` | string | Page path being checked | +| `rerequestable` | boolean | Whether the check can be rerequested | +| `createdAt` | number | Creation timestamp in milliseconds | +| `updatedAt` | number | Last update timestamp in milliseconds | +| `startedAt` | number | Start timestamp in milliseconds | +| `completedAt` | number | Completion timestamp in milliseconds | + +### `vercel_rerequest_check` + +Rerequest a deployment check + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `deploymentId` | string | Yes | Deployment ID the check belongs to | +| `checkId` | string | Yes | Check ID to rerequest | +| `teamId` | string | No | Team ID to scope the request | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `rerequested` | boolean | Whether the check was successfully rerequested | + +### `vercel_list_teams` + +List all teams in a Vercel account + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `limit` | number | No | Maximum number of teams to return | +| `since` | number | No | Timestamp in milliseconds to only include teams created since then | +| `until` | number | No | Timestamp in milliseconds to only include teams created until then | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `teams` | array | List of teams | +| ↳ `id` | string | Team ID | +| ↳ `slug` | string | Team slug | +| ↳ `name` | string | Team name | +| ↳ `avatar` | string | Avatar file ID | +| ↳ `createdAt` | number | Creation timestamp in milliseconds | +| ↳ `updatedAt` | number | Last update timestamp in milliseconds | +| ↳ `creatorId` | string | User ID of team creator | +| ↳ `membership` | object | Current user membership details | +| ↳ `role` | string | Membership role | +| ↳ `confirmed` | boolean | Whether membership is confirmed | +| ↳ `created` | number | Membership creation timestamp | +| ↳ `uid` | string | User ID of the member | +| ↳ `teamId` | string | Team ID | +| `count` | number | Number of teams returned | +| `pagination` | object | Pagination information | +| ↳ `count` | number | Items in current page | +| ↳ `next` | number | Timestamp for next page request | +| ↳ `prev` | number | Timestamp for previous page request | + +### `vercel_get_team` + +Get information about a specific Vercel team + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `teamId` | string | Yes | The team ID to retrieve | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Team ID | +| `slug` | string | Team slug | +| `name` | string | Team name | +| `avatar` | string | Avatar file ID | +| `description` | string | Short team description | +| `createdAt` | number | Creation timestamp in milliseconds | +| `updatedAt` | number | Last update timestamp in milliseconds | +| `creatorId` | string | User ID of team creator | +| `membership` | object | Current user membership details | +| ↳ `uid` | string | User ID of the member | +| ↳ `teamId` | string | Team ID | +| ↳ `role` | string | Membership role | +| ↳ `confirmed` | boolean | Whether membership is confirmed | +| ↳ `created` | number | Membership creation timestamp | +| ↳ `createdAt` | number | Membership creation timestamp \(milliseconds\) | +| ↳ `accessRequestedAt` | number | When access was requested | +| ↳ `teamRoles` | array | Team role assignments | +| ↳ `teamPermissions` | array | Team permission assignments | + +### `vercel_list_team_members` + +List all members of a Vercel team + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | +| `teamId` | string | Yes | The team ID to list members for | +| `limit` | number | No | Maximum number of members to return | +| `role` | string | No | Filter by role \(OWNER, MEMBER, DEVELOPER, SECURITY, BILLING, VIEWER, VIEWER_FOR_PLUS, CONTRIBUTOR\) | +| `since` | number | No | Timestamp in milliseconds to only include members added since then | +| `until` | number | No | Timestamp in milliseconds to only include members added until then | +| `search` | string | No | Search team members by their name, username, and email | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `members` | array | List of team members | +| ↳ `uid` | string | Member user ID | +| ↳ `email` | string | Member email | +| ↳ `username` | string | Member username | +| ↳ `name` | string | Member full name | +| ↳ `avatar` | string | Avatar file ID | +| ↳ `role` | string | Member role | +| ↳ `confirmed` | boolean | Whether membership is confirmed | +| ↳ `createdAt` | number | Join timestamp in milliseconds | +| ↳ `joinedFrom` | object | Origin of how the member joined | +| ↳ `origin` | string | Join origin identifier | +| `count` | number | Number of members returned | +| `pagination` | object | Pagination information | +| ↳ `hasNext` | boolean | Whether there are more pages | +| ↳ `count` | number | Items in current page | + +### `vercel_get_user` + +Get information about the authenticated Vercel user + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Vercel Access Token | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | User ID | +| `email` | string | User email | +| `username` | string | Username | +| `name` | string | Display name | +| `avatar` | string | SHA1 hash of the avatar | +| `defaultTeamId` | string | Default team ID | +| `createdAt` | number | Account creation timestamp in milliseconds | +| `stagingPrefix` | string | Prefix for preview deployment URLs | +| `softBlock` | object | Account restriction details if blocked | +| ↳ `blockedAt` | number | When the account was blocked | +| ↳ `reason` | string | Reason for the block | +| `hasTrialAvailable` | boolean | Whether a trial is available | + + diff --git a/apps/sim/blocks/blocks/vercel.ts b/apps/sim/blocks/blocks/vercel.ts new file mode 100644 index 0000000000..138b2c23a6 --- /dev/null +++ b/apps/sim/blocks/blocks/vercel.ts @@ -0,0 +1,1007 @@ +import { VercelIcon } from '@/components/icons' +import type { BlockConfig } from '@/blocks/types' +import { AuthMode } from '@/blocks/types' + +export const VercelBlock: BlockConfig = { + type: 'vercel', + name: 'Vercel', + description: 'Manage Vercel deployments, projects, and infrastructure', + longDescription: + 'Integrate with Vercel to manage deployments, projects, domains, DNS records, environment variables, aliases, edge configs, teams, and more.', + docsLink: 'https://docs.sim.ai/tools/vercel', + category: 'tools', + bgColor: '#171717', + icon: VercelIcon, + authMode: AuthMode.ApiKey, + subBlocks: [ + { + id: 'operation', + title: 'Operation', + type: 'dropdown', + options: [ + // Deployments + { label: 'List Deployments', id: 'list_deployments' }, + { label: 'Get Deployment', id: 'get_deployment' }, + { label: 'Create Deployment', id: 'create_deployment' }, + { label: 'Cancel Deployment', id: 'cancel_deployment' }, + { label: 'Delete Deployment', id: 'delete_deployment' }, + { label: 'Get Deployment Logs', id: 'get_deployment_events' }, + { label: 'List Deployment Files', id: 'list_deployment_files' }, + // Projects + { label: 'List Projects', id: 'list_projects' }, + { label: 'Get Project', id: 'get_project' }, + { label: 'Create Project', id: 'create_project' }, + { label: 'Update Project', id: 'update_project' }, + { label: 'Delete Project', id: 'delete_project' }, + { label: 'Pause Project', id: 'pause_project' }, + { label: 'Unpause Project', id: 'unpause_project' }, + // Project Domains + { label: 'List Project Domains', id: 'list_project_domains' }, + { label: 'Add Project Domain', id: 'add_project_domain' }, + { label: 'Remove Project Domain', id: 'remove_project_domain' }, + // Environment Variables + { label: 'Get Environment Variables', id: 'get_env_vars' }, + { label: 'Create Environment Variable', id: 'create_env_var' }, + { label: 'Update Environment Variable', id: 'update_env_var' }, + { label: 'Delete Environment Variable', id: 'delete_env_var' }, + // Domains + { label: 'List Domains', id: 'list_domains' }, + { label: 'Get Domain', id: 'get_domain' }, + { label: 'Add Domain', id: 'add_domain' }, + { label: 'Delete Domain', id: 'delete_domain' }, + { label: 'Get Domain Config', id: 'get_domain_config' }, + // DNS + { label: 'List DNS Records', id: 'list_dns_records' }, + { label: 'Create DNS Record', id: 'create_dns_record' }, + { label: 'Delete DNS Record', id: 'delete_dns_record' }, + // Aliases + { label: 'List Aliases', id: 'list_aliases' }, + { label: 'Get Alias', id: 'get_alias' }, + { label: 'Create Alias', id: 'create_alias' }, + { label: 'Delete Alias', id: 'delete_alias' }, + // Edge Config + { label: 'List Edge Configs', id: 'list_edge_configs' }, + { label: 'Get Edge Config', id: 'get_edge_config' }, + { label: 'Create Edge Config', id: 'create_edge_config' }, + { label: 'Get Edge Config Items', id: 'get_edge_config_items' }, + { label: 'Update Edge Config Items', id: 'update_edge_config_items' }, + // Webhooks + { label: 'List Webhooks', id: 'list_webhooks' }, + { label: 'Create Webhook', id: 'create_webhook' }, + { label: 'Delete Webhook', id: 'delete_webhook' }, + // Checks + { label: 'List Checks', id: 'list_checks' }, + { label: 'Get Check', id: 'get_check' }, + { label: 'Create Check', id: 'create_check' }, + { label: 'Update Check', id: 'update_check' }, + { label: 'Rerequest Check', id: 'rerequest_check' }, + // Teams & User + { label: 'List Teams', id: 'list_teams' }, + { label: 'Get Team', id: 'get_team' }, + { label: 'List Team Members', id: 'list_team_members' }, + { label: 'Get User', id: 'get_user' }, + ], + value: () => 'list_deployments', + }, + { + id: 'apiKey', + title: 'API Key', + type: 'short-input', + placeholder: 'Enter Vercel Access Token', + required: true, + password: true, + }, + + // === Deployment fields === + { + id: 'projectId', + title: 'Project ID', + type: 'short-input', + placeholder: 'Filter by project ID or name (optional)', + condition: { field: 'operation', value: 'list_deployments' }, + }, + { + id: 'target', + title: 'Target', + type: 'dropdown', + options: [ + { label: 'All', id: '' }, + { label: 'Production', id: 'production' }, + { label: 'Staging', id: 'staging' }, + ], + condition: { field: 'operation', value: 'list_deployments' }, + }, + { + id: 'state', + title: 'State', + type: 'dropdown', + options: [ + { label: 'All', id: '' }, + { label: 'Ready', id: 'READY' }, + { label: 'Building', id: 'BUILDING' }, + { label: 'Error', id: 'ERROR' }, + { label: 'Queued', id: 'QUEUED' }, + { label: 'Canceled', id: 'CANCELED' }, + ], + condition: { field: 'operation', value: 'list_deployments' }, + }, + { + id: 'deploymentId', + title: 'Deployment ID', + type: 'short-input', + placeholder: 'Enter deployment ID or hostname', + condition: { + field: 'operation', + value: [ + 'get_deployment', + 'cancel_deployment', + 'delete_deployment', + 'get_deployment_events', + 'list_deployment_files', + ], + }, + required: { + field: 'operation', + value: [ + 'get_deployment', + 'cancel_deployment', + 'delete_deployment', + 'get_deployment_events', + 'list_deployment_files', + ], + }, + }, + // Create Deployment + { + id: 'name', + title: 'Project Name', + type: 'short-input', + placeholder: 'Project name for the deployment', + condition: { field: 'operation', value: 'create_deployment' }, + required: { field: 'operation', value: 'create_deployment' }, + }, + { + id: 'project', + title: 'Project ID', + type: 'short-input', + placeholder: 'Project ID (optional, overrides name)', + condition: { field: 'operation', value: 'create_deployment' }, + }, + { + id: 'redeployId', + title: 'Redeploy From', + type: 'short-input', + placeholder: 'Existing deployment ID to redeploy (optional)', + condition: { field: 'operation', value: 'create_deployment' }, + }, + { + id: 'deployTarget', + title: 'Target', + type: 'dropdown', + options: [ + { label: 'Preview', id: '' }, + { label: 'Production', id: 'production' }, + { label: 'Staging', id: 'staging' }, + ], + condition: { field: 'operation', value: 'create_deployment' }, + }, + + // === Project fields === + { + id: 'search', + title: 'Search', + type: 'short-input', + placeholder: 'Search projects by name (optional)', + condition: { field: 'operation', value: 'list_projects' }, + }, + { + id: 'projectId', + title: 'Project ID', + type: 'short-input', + placeholder: 'Enter project ID or name', + condition: { + field: 'operation', + value: [ + 'get_project', + 'update_project', + 'delete_project', + 'pause_project', + 'unpause_project', + 'list_project_domains', + 'add_project_domain', + 'remove_project_domain', + 'get_env_vars', + 'create_env_var', + 'update_env_var', + 'delete_env_var', + ], + }, + required: { + field: 'operation', + value: [ + 'get_project', + 'update_project', + 'delete_project', + 'pause_project', + 'unpause_project', + 'list_project_domains', + 'add_project_domain', + 'remove_project_domain', + 'get_env_vars', + 'create_env_var', + 'update_env_var', + 'delete_env_var', + ], + }, + }, + // Create Project + { + id: 'projectName', + title: 'Project Name', + type: 'short-input', + placeholder: 'Name for the new project', + condition: { field: 'operation', value: 'create_project' }, + required: { field: 'operation', value: 'create_project' }, + }, + { + id: 'framework', + title: 'Framework', + type: 'dropdown', + options: [ + { label: 'Auto-detect', id: '' }, + { label: 'Next.js', id: 'nextjs' }, + { label: 'Remix', id: 'remix' }, + { label: 'Vite', id: 'vite' }, + { label: 'Nuxt', id: 'nuxtjs' }, + { label: 'SvelteKit', id: 'sveltekit' }, + { label: 'Astro', id: 'astro' }, + { label: 'Gatsby', id: 'gatsby' }, + { label: 'Other', id: 'other' }, + ], + condition: { field: 'operation', value: ['create_project', 'update_project'] }, + }, + { + id: 'buildCommand', + title: 'Build Command', + type: 'short-input', + placeholder: 'Custom build command (optional)', + condition: { field: 'operation', value: ['create_project', 'update_project'] }, + }, + { + id: 'outputDirectory', + title: 'Output Directory', + type: 'short-input', + placeholder: 'Output directory (optional)', + condition: { field: 'operation', value: ['create_project', 'update_project'] }, + }, + { + id: 'installCommand', + title: 'Install Command', + type: 'short-input', + placeholder: 'Install command (optional)', + condition: { field: 'operation', value: ['create_project', 'update_project'] }, + }, + + // === Project Domain fields === + { + id: 'domainName', + title: 'Domain', + type: 'short-input', + placeholder: 'Enter domain name (e.g., example.com)', + condition: { + field: 'operation', + value: [ + 'add_project_domain', + 'remove_project_domain', + 'get_domain', + 'delete_domain', + 'get_domain_config', + 'list_dns_records', + 'create_dns_record', + 'delete_dns_record', + 'add_domain', + ], + }, + required: { + field: 'operation', + value: [ + 'add_project_domain', + 'remove_project_domain', + 'get_domain', + 'delete_domain', + 'get_domain_config', + 'list_dns_records', + 'create_dns_record', + 'delete_dns_record', + 'add_domain', + ], + }, + }, + + // === Environment Variable fields === + { + id: 'envId', + title: 'Env Variable ID', + type: 'short-input', + placeholder: 'Environment variable ID', + condition: { field: 'operation', value: ['update_env_var', 'delete_env_var'] }, + required: { field: 'operation', value: ['update_env_var', 'delete_env_var'] }, + }, + { + id: 'envKey', + title: 'Key', + type: 'short-input', + placeholder: 'Variable name (e.g., DATABASE_URL)', + condition: { field: 'operation', value: ['create_env_var', 'update_env_var'] }, + required: { field: 'operation', value: 'create_env_var' }, + }, + { + id: 'envValue', + title: 'Value', + type: 'short-input', + placeholder: 'Variable value', + condition: { field: 'operation', value: ['create_env_var', 'update_env_var'] }, + required: { field: 'operation', value: 'create_env_var' }, + }, + { + id: 'envTarget', + title: 'Target Environments', + type: 'short-input', + placeholder: 'production,preview,development', + condition: { field: 'operation', value: ['create_env_var', 'update_env_var'] }, + required: { field: 'operation', value: 'create_env_var' }, + }, + { + id: 'envType', + title: 'Variable Type', + type: 'dropdown', + options: [ + { label: 'Plain', id: 'plain' }, + { label: 'Secret', id: 'secret' }, + { label: 'Encrypted', id: 'encrypted' }, + { label: 'Sensitive', id: 'sensitive' }, + ], + condition: { field: 'operation', value: ['create_env_var', 'update_env_var'] }, + }, + + // === DNS fields === + { + id: 'recordName', + title: 'Record Name', + type: 'short-input', + placeholder: 'Subdomain (e.g., www)', + condition: { field: 'operation', value: 'create_dns_record' }, + required: { field: 'operation', value: 'create_dns_record' }, + }, + { + id: 'recordType', + title: 'Record Type', + type: 'dropdown', + options: [ + { label: 'A', id: 'A' }, + { label: 'AAAA', id: 'AAAA' }, + { label: 'CNAME', id: 'CNAME' }, + { label: 'TXT', id: 'TXT' }, + { label: 'MX', id: 'MX' }, + { label: 'NS', id: 'NS' }, + { label: 'ALIAS', id: 'ALIAS' }, + { label: 'SRV', id: 'SRV' }, + { label: 'CAA', id: 'CAA' }, + ], + condition: { field: 'operation', value: 'create_dns_record' }, + required: { field: 'operation', value: 'create_dns_record' }, + }, + { + id: 'recordValue', + title: 'Value', + type: 'short-input', + placeholder: 'Record value (e.g., IP address)', + condition: { field: 'operation', value: 'create_dns_record' }, + required: { field: 'operation', value: 'create_dns_record' }, + }, + { + id: 'recordId', + title: 'Record ID', + type: 'short-input', + placeholder: 'DNS record ID', + condition: { field: 'operation', value: 'delete_dns_record' }, + required: { field: 'operation', value: 'delete_dns_record' }, + }, + + // === Alias fields === + { + id: 'aliasId', + title: 'Alias ID', + type: 'short-input', + placeholder: 'Alias ID or hostname', + condition: { field: 'operation', value: ['get_alias', 'delete_alias'] }, + required: { field: 'operation', value: ['get_alias', 'delete_alias'] }, + }, + { + id: 'aliasDeploymentId', + title: 'Deployment ID', + type: 'short-input', + placeholder: 'Deployment ID to assign alias to', + condition: { field: 'operation', value: 'create_alias' }, + required: { field: 'operation', value: 'create_alias' }, + }, + { + id: 'aliasName', + title: 'Alias', + type: 'short-input', + placeholder: 'Domain or subdomain to assign (e.g., my-app.vercel.app)', + condition: { field: 'operation', value: 'create_alias' }, + required: { field: 'operation', value: 'create_alias' }, + }, + + // === Edge Config fields === + { + id: 'edgeConfigId', + title: 'Edge Config ID', + type: 'short-input', + placeholder: 'Edge Config ID', + condition: { + field: 'operation', + value: ['get_edge_config', 'get_edge_config_items', 'update_edge_config_items'], + }, + required: { + field: 'operation', + value: ['get_edge_config', 'get_edge_config_items', 'update_edge_config_items'], + }, + }, + { + id: 'edgeConfigSlug', + title: 'Slug', + type: 'short-input', + placeholder: 'Name/slug for the Edge Config', + condition: { field: 'operation', value: 'create_edge_config' }, + required: { field: 'operation', value: 'create_edge_config' }, + }, + { + id: 'edgeConfigItems', + title: 'Items', + type: 'code', + placeholder: '[{"operation":"upsert","key":"my-key","value":"my-value"}]', + condition: { field: 'operation', value: 'update_edge_config_items' }, + required: { field: 'operation', value: 'update_edge_config_items' }, + }, + + // === Webhook fields === + { + id: 'webhookUrl', + title: 'Webhook URL', + type: 'short-input', + placeholder: 'https://example.com/webhook', + condition: { field: 'operation', value: 'create_webhook' }, + required: { field: 'operation', value: 'create_webhook' }, + }, + { + id: 'webhookEvents', + title: 'Events', + type: 'short-input', + placeholder: 'deployment.created,deployment.succeeded', + condition: { field: 'operation', value: 'create_webhook' }, + required: { field: 'operation', value: 'create_webhook' }, + }, + { + id: 'webhookProjectIds', + title: 'Project IDs', + type: 'short-input', + placeholder: 'Comma-separated project IDs (optional)', + condition: { field: 'operation', value: 'create_webhook' }, + }, + { + id: 'webhookId', + title: 'Webhook ID', + type: 'short-input', + placeholder: 'Webhook ID', + condition: { field: 'operation', value: 'delete_webhook' }, + required: { field: 'operation', value: 'delete_webhook' }, + }, + + // === Check fields === + { + id: 'checkDeploymentId', + title: 'Deployment ID', + type: 'short-input', + placeholder: 'Deployment ID', + condition: { + field: 'operation', + value: ['create_check', 'get_check', 'list_checks', 'update_check', 'rerequest_check'], + }, + required: { + field: 'operation', + value: ['create_check', 'get_check', 'list_checks', 'update_check', 'rerequest_check'], + }, + }, + { + id: 'checkId', + title: 'Check ID', + type: 'short-input', + placeholder: 'Check ID', + condition: { + field: 'operation', + value: ['get_check', 'update_check', 'rerequest_check'], + }, + required: { + field: 'operation', + value: ['get_check', 'update_check', 'rerequest_check'], + }, + }, + { + id: 'checkName', + title: 'Check Name', + type: 'short-input', + placeholder: 'Name of the check (max 100 chars)', + condition: { field: 'operation', value: ['create_check', 'update_check'] }, + required: { field: 'operation', value: 'create_check' }, + }, + { + id: 'checkBlocking', + title: 'Blocking', + type: 'dropdown', + options: [ + { label: 'Yes', id: 'true' }, + { label: 'No', id: 'false' }, + ], + condition: { field: 'operation', value: 'create_check' }, + required: { field: 'operation', value: 'create_check' }, + }, + { + id: 'checkPath', + title: 'Path', + type: 'short-input', + placeholder: 'Page path being checked (optional)', + condition: { field: 'operation', value: ['create_check', 'update_check'] }, + }, + { + id: 'checkDetailsUrl', + title: 'Details URL', + type: 'short-input', + placeholder: 'URL for more details (optional)', + condition: { field: 'operation', value: ['create_check', 'update_check'] }, + }, + { + id: 'checkStatus', + title: 'Status', + type: 'dropdown', + options: [ + { label: 'Running', id: 'running' }, + { label: 'Completed', id: 'completed' }, + ], + condition: { field: 'operation', value: 'update_check' }, + }, + { + id: 'checkConclusion', + title: 'Conclusion', + type: 'dropdown', + options: [ + { label: 'Succeeded', id: 'succeeded' }, + { label: 'Failed', id: 'failed' }, + { label: 'Canceled', id: 'canceled' }, + { label: 'Neutral', id: 'neutral' }, + { label: 'Skipped', id: 'skipped' }, + ], + condition: { field: 'operation', value: 'update_check' }, + }, + + // === Team fields === + { + id: 'teamIdParam', + title: 'Team ID', + type: 'short-input', + placeholder: 'Team ID', + condition: { field: 'operation', value: ['get_team', 'list_team_members'] }, + required: { field: 'operation', value: ['get_team', 'list_team_members'] }, + }, + { + id: 'memberRole', + title: 'Role Filter', + type: 'dropdown', + options: [ + { label: 'All', id: '' }, + { label: 'Owner', id: 'OWNER' }, + { label: 'Member', id: 'MEMBER' }, + { label: 'Developer', id: 'DEVELOPER' }, + { label: 'Viewer', id: 'VIEWER' }, + { label: 'Billing', id: 'BILLING' }, + ], + condition: { field: 'operation', value: 'list_team_members' }, + }, + + // === Shared optional Team ID (for scoping requests) === + { + id: 'teamId', + title: 'Team ID (Scope)', + type: 'short-input', + placeholder: 'Team ID to scope request (optional)', + condition: { + field: 'operation', + value: [ + 'get_team', + 'list_team_members', + 'get_user', + 'create_check', + 'get_check', + 'list_checks', + 'update_check', + 'rerequest_check', + ], + not: true, + }, + }, + ], + tools: { + access: [ + // Deployments + 'vercel_list_deployments', + 'vercel_get_deployment', + 'vercel_create_deployment', + 'vercel_cancel_deployment', + 'vercel_delete_deployment', + 'vercel_get_deployment_events', + 'vercel_list_deployment_files', + // Projects + 'vercel_list_projects', + 'vercel_get_project', + 'vercel_create_project', + 'vercel_update_project', + 'vercel_delete_project', + 'vercel_pause_project', + 'vercel_unpause_project', + 'vercel_list_project_domains', + 'vercel_add_project_domain', + 'vercel_remove_project_domain', + // Environment Variables + 'vercel_get_env_vars', + 'vercel_create_env_var', + 'vercel_update_env_var', + 'vercel_delete_env_var', + // Domains + 'vercel_list_domains', + 'vercel_get_domain', + 'vercel_add_domain', + 'vercel_delete_domain', + 'vercel_get_domain_config', + // DNS + 'vercel_list_dns_records', + 'vercel_create_dns_record', + 'vercel_delete_dns_record', + // Aliases + 'vercel_list_aliases', + 'vercel_get_alias', + 'vercel_create_alias', + 'vercel_delete_alias', + // Edge Config + 'vercel_list_edge_configs', + 'vercel_get_edge_config', + 'vercel_create_edge_config', + 'vercel_get_edge_config_items', + 'vercel_update_edge_config_items', + // Webhooks + 'vercel_list_webhooks', + 'vercel_create_webhook', + 'vercel_delete_webhook', + // Checks + 'vercel_create_check', + 'vercel_get_check', + 'vercel_list_checks', + 'vercel_update_check', + 'vercel_rerequest_check', + // Teams & User + 'vercel_list_teams', + 'vercel_get_team', + 'vercel_list_team_members', + 'vercel_get_user', + ], + config: { + tool: (params) => `vercel_${params.operation}`, + params: (params) => { + const { + apiKey, + operation, + redeployId, + deployTarget, + projectName, + domainName, + envKey, + envValue, + envTarget, + envType, + recordName, + recordType, + recordValue, + recordId, + aliasId, + aliasDeploymentId, + aliasName, + edgeConfigId, + edgeConfigSlug, + edgeConfigItems, + webhookId, + webhookUrl, + webhookEvents, + webhookProjectIds, + checkDeploymentId, + checkId, + checkName, + checkBlocking, + checkPath, + checkDetailsUrl, + checkStatus, + checkConclusion, + teamIdParam, + memberRole, + ...rest + } = params + + const base = { ...rest, apiKey } + + switch (operation) { + case 'create_deployment': + return { + ...base, + ...(redeployId ? { deploymentId: redeployId } : {}), + ...(deployTarget ? { target: deployTarget } : {}), + } + case 'create_project': + return { ...base, name: projectName } + case 'update_project': + return base + case 'add_project_domain': + case 'remove_project_domain': + return { ...base, domain: domainName } + case 'get_domain': + case 'delete_domain': + case 'get_domain_config': + return { ...base, domain: domainName } + case 'add_domain': + return { ...base, name: domainName } + case 'list_dns_records': + return { ...base, domain: domainName } + case 'create_dns_record': + return { ...base, domain: domainName, recordName, recordType, value: recordValue } + case 'delete_dns_record': + return { ...base, domain: domainName, recordId } + case 'create_env_var': + return { ...base, key: envKey, value: envValue, target: envTarget, type: envType } + case 'update_env_var': + return { + ...base, + ...(envKey ? { key: envKey } : {}), + ...(envValue ? { value: envValue } : {}), + ...(envTarget ? { target: envTarget } : {}), + ...(envType ? { type: envType } : {}), + } + case 'get_alias': + case 'delete_alias': + return { ...base, aliasId } + case 'create_alias': + return { ...base, deploymentId: aliasDeploymentId, alias: aliasName } + case 'get_edge_config': + case 'get_edge_config_items': + return { ...base, edgeConfigId } + case 'create_edge_config': + return { ...base, slug: edgeConfigSlug } + case 'update_edge_config_items': + return { ...base, edgeConfigId, items: edgeConfigItems } + case 'create_webhook': + return { + ...base, + url: webhookUrl, + events: webhookEvents, + ...(webhookProjectIds ? { projectIds: webhookProjectIds } : {}), + } + case 'delete_webhook': + return { ...base, webhookId } + case 'create_check': + return { + ...base, + deploymentId: checkDeploymentId, + name: checkName, + blocking: checkBlocking === 'true', + ...(checkPath ? { path: checkPath } : {}), + ...(checkDetailsUrl ? { detailsUrl: checkDetailsUrl } : {}), + } + case 'get_check': + case 'rerequest_check': + return { ...base, deploymentId: checkDeploymentId, checkId } + case 'list_checks': + return { ...base, deploymentId: checkDeploymentId } + case 'update_check': + return { + ...base, + deploymentId: checkDeploymentId, + checkId, + ...(checkName ? { name: checkName } : {}), + ...(checkStatus ? { status: checkStatus } : {}), + ...(checkConclusion ? { conclusion: checkConclusion } : {}), + ...(checkPath ? { path: checkPath } : {}), + ...(checkDetailsUrl ? { detailsUrl: checkDetailsUrl } : {}), + } + case 'get_team': + return { ...base, teamId: teamIdParam } + case 'list_team_members': + return { ...base, teamId: teamIdParam, ...(memberRole ? { role: memberRole } : {}) } + default: + return base + } + }, + }, + }, + inputs: { + operation: { type: 'string', description: 'Operation to perform' }, + apiKey: { type: 'string', description: 'Vercel access token' }, + projectId: { type: 'string', description: 'Project ID or name' }, + deploymentId: { type: 'string', description: 'Deployment ID or hostname' }, + name: { type: 'string', description: 'Project name' }, + projectName: { type: 'string', description: 'New project name' }, + project: { type: 'string', description: 'Project ID override' }, + redeployId: { type: 'string', description: 'Deployment ID to redeploy' }, + target: { type: 'string', description: 'Target environment filter' }, + deployTarget: { type: 'string', description: 'Deployment target environment' }, + state: { type: 'string', description: 'Deployment state filter' }, + search: { type: 'string', description: 'Project search query' }, + framework: { type: 'string', description: 'Project framework' }, + buildCommand: { type: 'string', description: 'Build command' }, + outputDirectory: { type: 'string', description: 'Output directory' }, + installCommand: { type: 'string', description: 'Install command' }, + domainName: { type: 'string', description: 'Domain name' }, + envId: { type: 'string', description: 'Environment variable ID' }, + envKey: { type: 'string', description: 'Environment variable key' }, + envValue: { type: 'string', description: 'Environment variable value' }, + envTarget: { type: 'string', description: 'Target environments' }, + envType: { type: 'string', description: 'Variable type' }, + recordName: { type: 'string', description: 'DNS record name' }, + recordType: { type: 'string', description: 'DNS record type' }, + recordValue: { type: 'string', description: 'DNS record value' }, + recordId: { type: 'string', description: 'DNS record ID' }, + aliasId: { type: 'string', description: 'Alias ID' }, + aliasDeploymentId: { type: 'string', description: 'Deployment ID for alias' }, + aliasName: { type: 'string', description: 'Alias domain' }, + edgeConfigId: { type: 'string', description: 'Edge Config ID' }, + edgeConfigSlug: { type: 'string', description: 'Edge Config slug' }, + edgeConfigItems: { type: 'string', description: 'Edge Config items JSON' }, + teamId: { type: 'string', description: 'Team ID for scoping' }, + teamIdParam: { type: 'string', description: 'Team ID parameter' }, + memberRole: { type: 'string', description: 'Team member role filter' }, + webhookId: { type: 'string', description: 'Webhook ID' }, + webhookUrl: { type: 'string', description: 'Webhook URL' }, + webhookEvents: { type: 'string', description: 'Comma-separated event names' }, + webhookProjectIds: { type: 'string', description: 'Comma-separated project IDs' }, + checkDeploymentId: { type: 'string', description: 'Deployment ID for checks' }, + checkId: { type: 'string', description: 'Check ID' }, + checkName: { type: 'string', description: 'Check name' }, + checkBlocking: { type: 'string', description: 'Whether check blocks deployment' }, + checkPath: { type: 'string', description: 'Page path being checked' }, + checkDetailsUrl: { type: 'string', description: 'URL for check details' }, + checkStatus: { type: 'string', description: 'Check status' }, + checkConclusion: { type: 'string', description: 'Check conclusion' }, + }, + outputs: { + // List results + deployments: { + type: 'array', + description: 'List of deployments', + condition: { field: 'operation', value: 'list_deployments' }, + }, + projects: { + type: 'array', + description: 'List of projects', + condition: { field: 'operation', value: 'list_projects' }, + }, + domains: { + type: 'array', + description: 'List of domains', + condition: { + field: 'operation', + value: ['list_domains', 'list_project_domains'], + }, + }, + envs: { + type: 'array', + description: 'List of environment variables', + condition: { field: 'operation', value: 'get_env_vars' }, + }, + records: { + type: 'array', + description: 'List of DNS records', + condition: { field: 'operation', value: 'list_dns_records' }, + }, + aliases: { + type: 'array', + description: 'List of aliases', + condition: { field: 'operation', value: 'list_aliases' }, + }, + edgeConfigs: { + type: 'array', + description: 'List of edge configs', + condition: { field: 'operation', value: 'list_edge_configs' }, + }, + items: { + type: 'array', + description: 'Edge config items', + condition: { field: 'operation', value: 'get_edge_config_items' }, + }, + teams: { + type: 'array', + description: 'List of teams', + condition: { field: 'operation', value: 'list_teams' }, + }, + members: { + type: 'array', + description: 'List of team members', + condition: { field: 'operation', value: 'list_team_members' }, + }, + events: { + type: 'array', + description: 'Deployment build log events', + condition: { field: 'operation', value: 'get_deployment_events' }, + }, + files: { + type: 'array', + description: 'Deployment file tree', + condition: { field: 'operation', value: 'list_deployment_files' }, + }, + webhooks: { + type: 'array', + description: 'List of webhooks', + condition: { field: 'operation', value: 'list_webhooks' }, + }, + checks: { + type: 'array', + description: 'List of deployment checks', + condition: { field: 'operation', value: 'list_checks' }, + }, + // Single resource outputs + id: { + type: 'string', + description: 'Resource ID', + }, + name: { + type: 'string', + description: 'Resource name', + }, + url: { + type: 'string', + description: 'Deployment URL', + condition: { + field: 'operation', + value: ['get_deployment', 'create_deployment', 'cancel_deployment'], + }, + }, + state: { + type: 'string', + description: 'Deployment state', + condition: { + field: 'operation', + value: ['get_deployment', 'create_deployment', 'cancel_deployment', 'delete_deployment'], + }, + }, + deleted: { + type: 'boolean', + description: 'Whether the resource was deleted', + condition: { + field: 'operation', + value: [ + 'delete_deployment', + 'delete_project', + 'remove_project_domain', + 'delete_domain', + 'delete_dns_record', + 'delete_alias', + 'delete_env_var', + 'delete_webhook', + ], + }, + }, + count: { + type: 'number', + description: 'Number of items returned', + }, + hasMore: { + type: 'boolean', + description: 'Whether more results are available', + }, + }, +} diff --git a/apps/sim/blocks/registry.ts b/apps/sim/blocks/registry.ts index f51019da28..bb3193fd1f 100644 --- a/apps/sim/blocks/registry.ts +++ b/apps/sim/blocks/registry.ts @@ -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 = { twilio_sms: TwilioSMSBlock, twilio_voice: TwilioVoiceBlock, typeform: TypeformBlock, + vercel: VercelBlock, variables: VariablesBlock, video_generator: VideoGeneratorBlock, video_generator_v2: VideoGeneratorV2Block, diff --git a/apps/sim/components/icons.tsx b/apps/sim/components/icons.tsx index dfb95dab2e..c31380d81c 100644 --- a/apps/sim/components/icons.tsx +++ b/apps/sim/components/icons.tsx @@ -5532,3 +5532,18 @@ export function OnePasswordIcon(props: SVGProps) { ) } + +export function VercelIcon(props: SVGProps) { + return ( + + + + + + ) +} diff --git a/apps/sim/tools/registry.ts b/apps/sim/tools/registry.ts index 991c7e1402..f931313a15 100644 --- a/apps/sim/tools/registry.ts +++ b/apps/sim/tools/registry.ts @@ -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 = { 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, diff --git a/apps/sim/tools/vercel/add_domain.ts b/apps/sim/tools/vercel/add_domain.ts new file mode 100644 index 0000000000..7e27964597 --- /dev/null +++ b/apps/sim/tools/vercel/add_domain.ts @@ -0,0 +1,84 @@ +import type { ToolConfig } from '@/tools/types' +import type { VercelAddDomainParams, VercelAddDomainResponse } from '@/tools/vercel/types' + +export const vercelAddDomainTool: ToolConfig = { + 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' }, + }, + }, +} diff --git a/apps/sim/tools/vercel/add_project_domain.ts b/apps/sim/tools/vercel/add_project_domain.ts new file mode 100644 index 0000000000..c259498310 --- /dev/null +++ b/apps/sim/tools/vercel/add_project_domain.ts @@ -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 = { 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' }, + }, +} diff --git a/apps/sim/tools/vercel/cancel_deployment.ts b/apps/sim/tools/vercel/cancel_deployment.ts new file mode 100644 index 0000000000..c9a5b2a7ae --- /dev/null +++ b/apps/sim/tools/vercel/cancel_deployment.ts @@ -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', + }, + }, +} diff --git a/apps/sim/tools/vercel/create_alias.ts b/apps/sim/tools/vercel/create_alias.ts new file mode 100644 index 0000000000..8146005c0e --- /dev/null +++ b/apps/sim/tools/vercel/create_alias.ts @@ -0,0 +1,87 @@ +import type { ToolConfig } from '@/tools/types' +import type { VercelCreateAliasParams, VercelCreateAliasResponse } from '@/tools/vercel/types' + +export const vercelCreateAliasTool: ToolConfig = + { + 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', + }, + }, + } diff --git a/apps/sim/tools/vercel/create_check.ts b/apps/sim/tools/vercel/create_check.ts new file mode 100644 index 0000000000..06da995919 --- /dev/null +++ b/apps/sim/tools/vercel/create_check.ts @@ -0,0 +1,141 @@ +import type { ToolConfig } from '@/tools/types' +import type { VercelCheckResponse, VercelCreateCheckParams } from '@/tools/vercel/types' + +export const vercelCreateCheckTool: ToolConfig = { + 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 = { + 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, + }, + }, +} diff --git a/apps/sim/tools/vercel/create_deployment.ts b/apps/sim/tools/vercel/create_deployment.ts new file mode 100644 index 0000000000..2f5b5b36df --- /dev/null +++ b/apps/sim/tools/vercel/create_deployment.ts @@ -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 = { + 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' }, + }, +} diff --git a/apps/sim/tools/vercel/create_dns_record.ts b/apps/sim/tools/vercel/create_dns_record.ts new file mode 100644 index 0000000000..fdb64c93c2 --- /dev/null +++ b/apps/sim/tools/vercel/create_dns_record.ts @@ -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 = { + 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' }, + }, +} diff --git a/apps/sim/tools/vercel/create_edge_config.ts b/apps/sim/tools/vercel/create_edge_config.ts new file mode 100644 index 0000000000..6313533407 --- /dev/null +++ b/apps/sim/tools/vercel/create_edge_config.ts @@ -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', + }, + }, +} diff --git a/apps/sim/tools/vercel/create_env_var.ts b/apps/sim/tools/vercel/create_env_var.ts new file mode 100644 index 0000000000..c174b9fb1d --- /dev/null +++ b/apps/sim/tools/vercel/create_env_var.ts @@ -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 = { + 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, + }, + }, +} diff --git a/apps/sim/tools/vercel/create_project.ts b/apps/sim/tools/vercel/create_project.ts new file mode 100644 index 0000000000..b05e4b8361 --- /dev/null +++ b/apps/sim/tools/vercel/create_project.ts @@ -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 = { 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' }, + }, +} diff --git a/apps/sim/tools/vercel/create_webhook.ts b/apps/sim/tools/vercel/create_webhook.ts new file mode 100644 index 0000000000..e61993e850 --- /dev/null +++ b/apps/sim/tools/vercel/create_webhook.ts @@ -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 = { + 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' }, + }, +} diff --git a/apps/sim/tools/vercel/delete_alias.ts b/apps/sim/tools/vercel/delete_alias.ts new file mode 100644 index 0000000000..cc47619937 --- /dev/null +++ b/apps/sim/tools/vercel/delete_alias.ts @@ -0,0 +1,62 @@ +import type { ToolConfig } from '@/tools/types' +import type { VercelDeleteAliasParams, VercelDeleteAliasResponse } from '@/tools/vercel/types' + +export const vercelDeleteAliasTool: ToolConfig = + { + 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)', + }, + }, + } diff --git a/apps/sim/tools/vercel/delete_deployment.ts b/apps/sim/tools/vercel/delete_deployment.ts new file mode 100644 index 0000000000..b2989b7f81 --- /dev/null +++ b/apps/sim/tools/vercel/delete_deployment.ts @@ -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)', + }, + }, +} diff --git a/apps/sim/tools/vercel/delete_dns_record.ts b/apps/sim/tools/vercel/delete_dns_record.ts new file mode 100644 index 0000000000..313df6192f --- /dev/null +++ b/apps/sim/tools/vercel/delete_dns_record.ts @@ -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' }, + }, +} diff --git a/apps/sim/tools/vercel/delete_domain.ts b/apps/sim/tools/vercel/delete_domain.ts new file mode 100644 index 0000000000..dc2ab080cc --- /dev/null +++ b/apps/sim/tools/vercel/delete_domain.ts @@ -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' }, + }, +} diff --git a/apps/sim/tools/vercel/delete_env_var.ts b/apps/sim/tools/vercel/delete_env_var.ts new file mode 100644 index 0000000000..1c2f7f0ece --- /dev/null +++ b/apps/sim/tools/vercel/delete_env_var.ts @@ -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', + }, + }, +} diff --git a/apps/sim/tools/vercel/delete_project.ts b/apps/sim/tools/vercel/delete_project.ts new file mode 100644 index 0000000000..7e04e41cd8 --- /dev/null +++ b/apps/sim/tools/vercel/delete_project.ts @@ -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' }, + }, +} diff --git a/apps/sim/tools/vercel/delete_webhook.ts b/apps/sim/tools/vercel/delete_webhook.ts new file mode 100644 index 0000000000..03d483a510 --- /dev/null +++ b/apps/sim/tools/vercel/delete_webhook.ts @@ -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', + }, + }, +} diff --git a/apps/sim/tools/vercel/get_alias.ts b/apps/sim/tools/vercel/get_alias.ts new file mode 100644 index 0000000000..2d211cff6b --- /dev/null +++ b/apps/sim/tools/vercel/get_alias.ts @@ -0,0 +1,97 @@ +import type { ToolConfig } from '@/tools/types' +import type { VercelGetAliasParams, VercelGetAliasResponse } from '@/tools/vercel/types' + +export const vercelGetAliasTool: ToolConfig = { + 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)', + }, + }, +} diff --git a/apps/sim/tools/vercel/get_check.ts b/apps/sim/tools/vercel/get_check.ts new file mode 100644 index 0000000000..064b127795 --- /dev/null +++ b/apps/sim/tools/vercel/get_check.ts @@ -0,0 +1,99 @@ +import type { ToolConfig } from '@/tools/types' +import type { VercelCheckResponse, VercelGetCheckParams } from '@/tools/vercel/types' + +export const vercelGetCheckTool: ToolConfig = { + 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, + }, + }, +} diff --git a/apps/sim/tools/vercel/get_deployment.ts b/apps/sim/tools/vercel/get_deployment.ts new file mode 100644 index 0000000000..d56891448f --- /dev/null +++ b/apps/sim/tools/vercel/get_deployment.ts @@ -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 }, + }, + }, + }, +} diff --git a/apps/sim/tools/vercel/get_deployment_events.ts b/apps/sim/tools/vercel/get_deployment_events.ts new file mode 100644 index 0000000000..3e3d8cbd09 --- /dev/null +++ b/apps/sim/tools/vercel/get_deployment_events.ts @@ -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', + }, + }, +} diff --git a/apps/sim/tools/vercel/get_domain.ts b/apps/sim/tools/vercel/get_domain.ts new file mode 100644 index 0000000000..8f4c216e9b --- /dev/null +++ b/apps/sim/tools/vercel/get_domain.ts @@ -0,0 +1,94 @@ +import type { ToolConfig } from '@/tools/types' +import type { VercelGetDomainParams, VercelGetDomainResponse } from '@/tools/vercel/types' + +export const vercelGetDomainTool: ToolConfig = { + 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' }, + }, +} diff --git a/apps/sim/tools/vercel/get_domain_config.ts b/apps/sim/tools/vercel/get_domain_config.ts new file mode 100644 index 0000000000..14cbeb5d41 --- /dev/null +++ b/apps/sim/tools/vercel/get_domain_config.ts @@ -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' }, + }, + }, + }, + }, +} diff --git a/apps/sim/tools/vercel/get_edge_config.ts b/apps/sim/tools/vercel/get_edge_config.ts new file mode 100644 index 0000000000..0d15d62984 --- /dev/null +++ b/apps/sim/tools/vercel/get_edge_config.ts @@ -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', + }, + }, +} diff --git a/apps/sim/tools/vercel/get_edge_config_items.ts b/apps/sim/tools/vercel/get_edge_config_items.ts new file mode 100644 index 0000000000..252e59c330 --- /dev/null +++ b/apps/sim/tools/vercel/get_edge_config_items.ts @@ -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', + }, + }, +} diff --git a/apps/sim/tools/vercel/get_env_vars.ts b/apps/sim/tools/vercel/get_env_vars.ts new file mode 100644 index 0000000000..e6b0cca7b9 --- /dev/null +++ b/apps/sim/tools/vercel/get_env_vars.ts @@ -0,0 +1,99 @@ +import type { ToolConfig } from '@/tools/types' +import type { VercelGetEnvVarsParams, VercelGetEnvVarsResponse } from '@/tools/vercel/types' + +export const vercelGetEnvVarsTool: ToolConfig = { + 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', + }, + }, +} diff --git a/apps/sim/tools/vercel/get_project.ts b/apps/sim/tools/vercel/get_project.ts new file mode 100644 index 0000000000..4a89554e10 --- /dev/null +++ b/apps/sim/tools/vercel/get_project.ts @@ -0,0 +1,89 @@ +import type { ToolConfig } from '@/tools/types' +import type { VercelGetProjectParams, VercelGetProjectResponse } from '@/tools/vercel/types' + +export const vercelGetProjectTool: ToolConfig = { + 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' }, + }, + }, + }, +} diff --git a/apps/sim/tools/vercel/get_team.ts b/apps/sim/tools/vercel/get_team.ts new file mode 100644 index 0000000000..0d40182312 --- /dev/null +++ b/apps/sim/tools/vercel/get_team.ts @@ -0,0 +1,98 @@ +import type { ToolConfig } from '@/tools/types' +import type { VercelGetTeamParams, VercelGetTeamResponse } from '@/tools/vercel/types' + +export const vercelGetTeamTool: ToolConfig = { + 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' }, + }, + }, + }, + }, +} diff --git a/apps/sim/tools/vercel/get_user.ts b/apps/sim/tools/vercel/get_user.ts new file mode 100644 index 0000000000..115678c022 --- /dev/null +++ b/apps/sim/tools/vercel/get_user.ts @@ -0,0 +1,73 @@ +import type { ToolConfig } from '@/tools/types' +import type { VercelGetUserParams, VercelGetUserResponse } from '@/tools/vercel/types' + +export const vercelGetUserTool: ToolConfig = { + 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' }, + }, +} diff --git a/apps/sim/tools/vercel/index.ts b/apps/sim/tools/vercel/index.ts new file mode 100644 index 0000000000..c25ff0710a --- /dev/null +++ b/apps/sim/tools/vercel/index.ts @@ -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' diff --git a/apps/sim/tools/vercel/list_aliases.ts b/apps/sim/tools/vercel/list_aliases.ts new file mode 100644 index 0000000000..fc4f77574d --- /dev/null +++ b/apps/sim/tools/vercel/list_aliases.ts @@ -0,0 +1,107 @@ +import type { ToolConfig } from '@/tools/types' +import type { VercelListAliasesParams, VercelListAliasesResponse } from '@/tools/vercel/types' + +export const vercelListAliasesTool: ToolConfig = + { + 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', + }, + }, + } diff --git a/apps/sim/tools/vercel/list_checks.ts b/apps/sim/tools/vercel/list_checks.ts new file mode 100644 index 0000000000..fec286ca6b --- /dev/null +++ b/apps/sim/tools/vercel/list_checks.ts @@ -0,0 +1,99 @@ +import type { ToolConfig } from '@/tools/types' +import type { VercelListChecksParams, VercelListChecksResponse } from '@/tools/vercel/types' + +export const vercelListChecksTool: ToolConfig = { + 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) => ({ + 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' }, + }, +} diff --git a/apps/sim/tools/vercel/list_deployment_files.ts b/apps/sim/tools/vercel/list_deployment_files.ts new file mode 100644 index 0000000000..c44c8e01b5 --- /dev/null +++ b/apps/sim/tools/vercel/list_deployment_files.ts @@ -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', + }, + }, +} diff --git a/apps/sim/tools/vercel/list_deployments.ts b/apps/sim/tools/vercel/list_deployments.ts new file mode 100644 index 0000000000..51278ba0ee --- /dev/null +++ b/apps/sim/tools/vercel/list_deployments.ts @@ -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', + }, + }, +} diff --git a/apps/sim/tools/vercel/list_dns_records.ts b/apps/sim/tools/vercel/list_dns_records.ts new file mode 100644 index 0000000000..81672ababa --- /dev/null +++ b/apps/sim/tools/vercel/list_dns_records.ts @@ -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', + }, + }, +} diff --git a/apps/sim/tools/vercel/list_domains.ts b/apps/sim/tools/vercel/list_domains.ts new file mode 100644 index 0000000000..55b2da5093 --- /dev/null +++ b/apps/sim/tools/vercel/list_domains.ts @@ -0,0 +1,109 @@ +import type { ToolConfig } from '@/tools/types' +import type { VercelListDomainsParams, VercelListDomainsResponse } from '@/tools/vercel/types' + +export const vercelListDomainsTool: ToolConfig = + { + 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', + }, + }, + } diff --git a/apps/sim/tools/vercel/list_edge_configs.ts b/apps/sim/tools/vercel/list_edge_configs.ts new file mode 100644 index 0000000000..9a025ada78 --- /dev/null +++ b/apps/sim/tools/vercel/list_edge_configs.ts @@ -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', + }, + }, +} diff --git a/apps/sim/tools/vercel/list_project_domains.ts b/apps/sim/tools/vercel/list_project_domains.ts new file mode 100644 index 0000000000..8f8c370efe --- /dev/null +++ b/apps/sim/tools/vercel/list_project_domains.ts @@ -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' }, + }, +} diff --git a/apps/sim/tools/vercel/list_projects.ts b/apps/sim/tools/vercel/list_projects.ts new file mode 100644 index 0000000000..edec3835de --- /dev/null +++ b/apps/sim/tools/vercel/list_projects.ts @@ -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', + }, + }, +} diff --git a/apps/sim/tools/vercel/list_team_members.ts b/apps/sim/tools/vercel/list_team_members.ts new file mode 100644 index 0000000000..78dd2ebd2b --- /dev/null +++ b/apps/sim/tools/vercel/list_team_members.ts @@ -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' }, + }, + }, + }, +} diff --git a/apps/sim/tools/vercel/list_teams.ts b/apps/sim/tools/vercel/list_teams.ts new file mode 100644 index 0000000000..248596242b --- /dev/null +++ b/apps/sim/tools/vercel/list_teams.ts @@ -0,0 +1,132 @@ +import type { ToolConfig } from '@/tools/types' +import type { VercelListTeamsParams, VercelListTeamsResponse } from '@/tools/vercel/types' + +export const vercelListTeamsTool: ToolConfig = { + 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' }, + }, + }, + }, +} diff --git a/apps/sim/tools/vercel/list_webhooks.ts b/apps/sim/tools/vercel/list_webhooks.ts new file mode 100644 index 0000000000..df22c57439 --- /dev/null +++ b/apps/sim/tools/vercel/list_webhooks.ts @@ -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', + }, + }, +} diff --git a/apps/sim/tools/vercel/pause_project.ts b/apps/sim/tools/vercel/pause_project.ts new file mode 100644 index 0000000000..97d5ac9c8d --- /dev/null +++ b/apps/sim/tools/vercel/pause_project.ts @@ -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' }, + }, +} diff --git a/apps/sim/tools/vercel/remove_project_domain.ts b/apps/sim/tools/vercel/remove_project_domain.ts new file mode 100644 index 0000000000..e9b15caeb9 --- /dev/null +++ b/apps/sim/tools/vercel/remove_project_domain.ts @@ -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' }, + }, +} diff --git a/apps/sim/tools/vercel/rerequest_check.ts b/apps/sim/tools/vercel/rerequest_check.ts new file mode 100644 index 0000000000..f0da658b58 --- /dev/null +++ b/apps/sim/tools/vercel/rerequest_check.ts @@ -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' }, + }, +} diff --git a/apps/sim/tools/vercel/types.ts b/apps/sim/tools/vercel/types.ts new file mode 100644 index 0000000000..eb265e60e8 --- /dev/null +++ b/apps/sim/tools/vercel/types.ts @@ -0,0 +1,1025 @@ +import type { ToolResponse } from '@/tools/types' + +export interface VercelListDeploymentsParams { + apiKey: string + projectId?: string + target?: string + state?: string + app?: string + since?: number + until?: number + limit?: number + teamId?: string +} + +export interface VercelGetDeploymentParams { + apiKey: string + deploymentId: string + withGitRepoInfo?: string + teamId?: string +} + +export interface VercelListProjectsParams { + apiKey: string + search?: string + limit?: number + teamId?: string +} + +export interface VercelGetProjectParams { + apiKey: string + projectId: string + teamId?: string +} + +export interface VercelCreateDeploymentParams { + apiKey: string + name: string + project?: string + deploymentId?: string + target?: string + gitSource?: string + forceNew?: string + teamId?: string +} + +export interface VercelListDomainsParams { + apiKey: string + limit?: number + teamId?: string +} + +export interface VercelGetEnvVarsParams { + apiKey: string + projectId: string + teamId?: string +} + +export interface VercelListDeploymentsResponse extends ToolResponse { + output: { + deployments: Array<{ + uid: string + name: string + url: string | null + state: string + target: string | null + created: number + projectId: string + source: string + inspectorUrl: string + creator: { + uid: string + email: string + username: string + } + meta: Record + }> + count: number + hasMore: boolean + } +} + +export interface VercelGetDeploymentResponse extends ToolResponse { + output: { + id: string + name: string + url: string + readyState: string + status: string + target: string | null + createdAt: number + buildingAt: number | null + ready: number | null + source: string + alias: string[] + regions: string[] + inspectorUrl: string + projectId: string + creator: { + uid: string + username: string + } + project: { + id: string + name: string + framework: string | null + } | null + meta: Record + gitSource: Record | null + } +} + +export interface VercelListProjectsResponse extends ToolResponse { + output: { + projects: Array<{ + id: string + name: string + framework: string | null + createdAt: number + updatedAt: number + domains: string[] + }> + count: number + hasMore: boolean + } +} + +export interface VercelGetProjectResponse extends ToolResponse { + output: { + id: string + name: string + framework: string | null + createdAt: number + updatedAt: number + domains: string[] + link: { + type: string + repo: string + org: string + } | null + } +} + +export interface VercelCreateDeploymentResponse extends ToolResponse { + output: { + id: string + name: string + url: string + readyState: string + projectId: string + createdAt: number + alias: string[] + target: string | null + inspectorUrl: string + } +} + +export interface VercelListDomainsResponse extends ToolResponse { + output: { + domains: Array<{ + id: string + name: string + verified: boolean + createdAt: number + expiresAt: number | null + serviceType: string + nameservers: string[] + intendedNameservers: string[] + renew: boolean + boughtAt: number | null + }> + count: number + hasMore: boolean + } +} + +export interface VercelGetEnvVarsResponse extends ToolResponse { + output: { + envs: Array<{ + id: string + key: string + value: string + type: string + target: string[] + gitBranch: string | null + comment: string | null + }> + count: number + } +} + +export interface VercelCancelDeploymentParams { + apiKey: string + deploymentId: string + teamId?: string +} + +export interface VercelCancelDeploymentResponse extends ToolResponse { + output: { + id: string + name: string | null + state: string + url: string | null + } +} + +export interface VercelDeleteDeploymentParams { + apiKey: string + deploymentId: string + teamId?: string +} + +export interface VercelDeleteDeploymentResponse extends ToolResponse { + output: { + uid: string | null + state: string + } +} + +export interface VercelGetDeploymentEventsParams { + apiKey: string + deploymentId: string + direction?: string + follow?: number + limit?: number + since?: number + until?: number + teamId?: string +} + +export interface VercelGetDeploymentEventsResponse extends ToolResponse { + output: { + events: Array<{ + type: string | null + created: number | null + date: number | null + text: string | null + serial: string | null + deploymentId: string | null + id: string | null + level: string | null + }> + count: number + } +} + +export interface VercelCreateEnvVarParams { + apiKey: string + projectId: string + key: string + value: string + target: string + type?: string + gitBranch?: string + comment?: string + teamId?: string +} + +export interface VercelCreateEnvVarResponse extends ToolResponse { + output: { + id: string + key: string + value: string + type: string + target: string[] + gitBranch: string | null + comment: string | null + } +} + +export interface VercelUpdateEnvVarParams { + apiKey: string + projectId: string + envId: string + key?: string + value?: string + target?: string + type?: string + gitBranch?: string + comment?: string + teamId?: string +} + +export interface VercelUpdateEnvVarResponse extends ToolResponse { + output: { + id: string + key: string + value: string + type: string + target: string[] + gitBranch: string | null + comment: string | null + } +} + +export interface VercelDeleteEnvVarParams { + apiKey: string + projectId: string + envId: string + teamId?: string +} + +export interface VercelDeleteEnvVarResponse extends ToolResponse { + output: { + deleted: boolean + } +} + +export interface VercelListDeploymentFilesParams { + apiKey: string + deploymentId: string + teamId?: string +} + +export interface VercelListDeploymentFilesResponse extends ToolResponse { + output: { + files: Array<{ + name: string | null + type: string | null + uid: string | null + mode: number | null + contentType: string | null + children: unknown[] + }> + count: number + } +} + +export interface VercelCreateProjectParams { + apiKey: string + name: string + framework?: string + gitRepository?: { type: string; repo: string } + buildCommand?: string + outputDirectory?: string + installCommand?: string + teamId?: string +} + +export interface VercelCreateProjectResponse extends ToolResponse { + output: { + id: string + name: string + framework: string | null + createdAt: number + updatedAt: number + } +} + +export interface VercelUpdateProjectParams { + apiKey: string + projectId: string + name?: string + framework?: string + buildCommand?: string + outputDirectory?: string + installCommand?: string + teamId?: string +} + +export interface VercelUpdateProjectResponse extends ToolResponse { + output: { + id: string + name: string + framework: string | null + updatedAt: number + } +} + +export interface VercelDeleteProjectParams { + apiKey: string + projectId: string + teamId?: string +} + +export interface VercelDeleteProjectResponse extends ToolResponse { + output: { + deleted: boolean + } +} + +export interface VercelPauseProjectParams { + apiKey: string + projectId: string + teamId?: string +} + +export interface VercelPauseProjectResponse extends ToolResponse { + output: { + id: string + name: string + paused: boolean + } +} + +export interface VercelUnpauseProjectParams { + apiKey: string + projectId: string + teamId?: string +} + +export interface VercelUnpauseProjectResponse extends ToolResponse { + output: { + id: string + name: string + paused: boolean + } +} + +export interface VercelListProjectDomainsParams { + apiKey: string + projectId: string + teamId?: string + limit?: number +} + +export interface VercelListProjectDomainsResponse extends ToolResponse { + output: { + domains: Array<{ + name: string + apexName: string + redirect: string | null + redirectStatusCode: number | null + verified: boolean + gitBranch: string | null + createdAt: number + updatedAt: number + }> + count: number + hasMore: boolean + } +} + +export interface VercelAddProjectDomainParams { + apiKey: string + projectId: string + domain: string + redirect?: string + redirectStatusCode?: number + gitBranch?: string + teamId?: string +} + +export interface VercelAddProjectDomainResponse extends ToolResponse { + output: { + name: string + apexName: string + verified: boolean + gitBranch: string | null + redirect: string | null + redirectStatusCode: number | null + createdAt: number + updatedAt: number + } +} + +export interface VercelRemoveProjectDomainParams { + apiKey: string + projectId: string + domain: string + teamId?: string +} + +export interface VercelRemoveProjectDomainResponse extends ToolResponse { + output: { + deleted: boolean + } +} + +export interface VercelGetDomainParams { + apiKey: string + domain: string + teamId?: string +} + +export interface VercelGetDomainResponse extends ToolResponse { + output: { + id: string | null + name: string | null + verified: boolean + createdAt: number | null + expiresAt: number | null + serviceType: string | null + nameservers: string[] + intendedNameservers: string[] + customNameservers: string[] + renew: boolean + boughtAt: number | null + transferredAt: number | null + } +} + +export interface VercelAddDomainParams { + apiKey: string + name: string + teamId?: string +} + +export interface VercelAddDomainResponse extends ToolResponse { + output: { + id: string | null + name: string | null + verified: boolean + createdAt: number | null + serviceType: string | null + nameservers: string[] + intendedNameservers: string[] + } +} + +export interface VercelDeleteDomainParams { + apiKey: string + domain: string + teamId?: string +} + +export interface VercelDeleteDomainResponse extends ToolResponse { + output: { + uid: string | null + deleted: boolean + } +} + +export interface VercelGetDomainConfigParams { + apiKey: string + domain: string + teamId?: string +} + +export interface VercelGetDomainConfigResponse extends ToolResponse { + output: { + configuredBy: string | null + acceptedChallenges: string[] + misconfigured: boolean + recommendedIPv4: Array<{ rank: number; value: string[] }> + recommendedCNAME: Array<{ rank: number; value: string }> + } +} + +export interface VercelCreateDnsRecordParams { + apiKey: string + domain: string + recordName: string + recordType: string + value: string + ttl?: number + mxPriority?: number + teamId?: string +} + +export interface VercelCreateDnsRecordResponse extends ToolResponse { + output: { + uid: string | null + updated: number | null + } +} + +export interface VercelListDnsRecordsParams { + apiKey: string + domain: string + limit?: number + teamId?: string +} + +export interface VercelListDnsRecordsResponse extends ToolResponse { + output: { + records: Array<{ + id: string | null + slug: string | null + name: string | null + type: string | null + value: string | null + ttl: number | null + mxPriority: number | null + priority: number | null + creator: string | null + createdAt: number | null + updatedAt: number | null + comment: string | null + }> + count: number + hasMore: boolean + } +} + +export interface VercelDeleteDnsRecordParams { + apiKey: string + domain: string + recordId: string + teamId?: string +} + +export interface VercelDeleteDnsRecordResponse extends ToolResponse { + output: { + deleted: boolean + } +} + +export interface VercelListTeamsParams { + apiKey: string + limit?: number + since?: number + until?: number +} + +export interface VercelListTeamsResponse extends ToolResponse { + output: { + teams: Array<{ + id: string | null + slug: string | null + name: string | null + avatar: string | null + createdAt: number | null + updatedAt: number | null + creatorId: string | null + membership: { + role: string | null + confirmed: boolean + created: number | null + uid: string | null + teamId: string | null + } | null + }> + count: number + pagination: { + count: number + next: number | null + prev: number | null + } | null + } +} + +export interface VercelGetTeamParams { + apiKey: string + teamId: string +} + +export interface VercelGetTeamResponse extends ToolResponse { + output: { + id: string | null + slug: string | null + name: string | null + avatar: string | null + description: string | null + createdAt: number | null + updatedAt: number | null + creatorId: string | null + membership: { + uid: string | null + teamId: string | null + role: string | null + confirmed: boolean + created: number | null + createdAt: number | null + accessRequestedAt: number | null + teamRoles: string[] + teamPermissions: string[] + } | null + } +} + +export interface VercelListTeamMembersParams { + apiKey: string + teamId: string + limit?: number + role?: string + since?: number + until?: number + search?: string +} + +export interface VercelListTeamMembersResponse extends ToolResponse { + output: { + members: Array<{ + uid: string | null + email: string | null + username: string | null + name: string | null + avatar: string | null + role: string | null + confirmed: boolean + createdAt: number | null + joinedFrom: { + origin: string | null + } | null + }> + count: number + pagination: { + hasNext: boolean + count: number + } | null + } +} + +export interface VercelGetUserParams { + apiKey: string +} + +export interface VercelGetUserResponse extends ToolResponse { + output: { + id: string | null + email: string | null + username: string | null + name: string | null + avatar: string | null + defaultTeamId: string | null + createdAt: number | null + stagingPrefix: string | null + softBlock: { + blockedAt: number | null + reason: string | null + } | null + hasTrialAvailable: boolean | null + } +} + +export interface VercelListAliasesParams { + apiKey: string + projectId?: string + domain?: string + limit?: number + teamId?: string +} + +export interface VercelListAliasesResponse extends ToolResponse { + output: { + aliases: Array<{ + uid: string | null + alias: string | null + deploymentId: string | null + projectId: string | null + createdAt: number | null + updatedAt: number | null + }> + count: number + hasMore: boolean + } +} + +export interface VercelGetAliasParams { + apiKey: string + aliasId: string + teamId?: string +} + +export interface VercelGetAliasResponse extends ToolResponse { + output: { + uid: string | null + alias: string | null + deploymentId: string | null + projectId: string | null + createdAt: number | null + updatedAt: number | null + redirect: string | null + redirectStatusCode: number | null + } +} + +export interface VercelCreateAliasParams { + apiKey: string + deploymentId: string + alias: string + teamId?: string +} + +export interface VercelCreateAliasResponse extends ToolResponse { + output: { + uid: string | null + alias: string | null + created: string | null + oldDeploymentId: string | null + } +} + +export interface VercelDeleteAliasParams { + apiKey: string + aliasId: string + teamId?: string +} + +export interface VercelDeleteAliasResponse extends ToolResponse { + output: { + status: string + } +} + +export interface VercelListEdgeConfigsParams { + apiKey: string + teamId?: string +} + +export interface VercelListEdgeConfigsResponse extends ToolResponse { + output: { + edgeConfigs: Array<{ + id: string | null + slug: string | null + ownerId: string | null + digest: string | null + createdAt: number | null + updatedAt: number | null + itemCount: number + sizeInBytes: number + }> + count: number + } +} + +export interface VercelGetEdgeConfigParams { + apiKey: string + edgeConfigId: string + teamId?: string +} + +export interface VercelGetEdgeConfigResponse extends ToolResponse { + output: { + id: string | null + slug: string | null + ownerId: string | null + digest: string | null + createdAt: number | null + updatedAt: number | null + itemCount: number + sizeInBytes: number + } +} + +export interface VercelCreateEdgeConfigParams { + apiKey: string + slug: string + teamId?: string +} + +export interface VercelCreateEdgeConfigResponse extends ToolResponse { + output: { + id: string | null + slug: string | null + ownerId: string | null + digest: string | null + createdAt: number | null + updatedAt: number | null + itemCount: number + sizeInBytes: number + } +} + +export interface VercelGetEdgeConfigItemsParams { + apiKey: string + edgeConfigId: string + teamId?: string +} + +export interface VercelGetEdgeConfigItemsResponse extends ToolResponse { + output: { + items: Array<{ + key: string | null + value: any + description: string | null + edgeConfigId: string | null + createdAt: number | null + updatedAt: number | null + }> + count: number + } +} + +export interface VercelUpdateEdgeConfigItemsParams { + apiKey: string + edgeConfigId: string + items: string | Array<{ operation: string; key: string; value?: any; description?: string }> + teamId?: string +} + +export interface VercelUpdateEdgeConfigItemsResponse extends ToolResponse { + output: { + status: string + } +} + +export interface VercelListWebhooksParams { + apiKey: string + projectId?: string + teamId?: string +} + +export interface VercelListWebhooksResponse extends ToolResponse { + output: { + webhooks: Array<{ + id: string + url: string + events: string[] + ownerId: string + projectIds: string[] + createdAt: number + updatedAt: number + }> + count: number + } +} + +export interface VercelCreateWebhookParams { + apiKey: string + url: string + events: string + projectIds?: string + teamId: string +} + +export interface VercelCreateWebhookResponse extends ToolResponse { + output: { + id: string + url: string + secret: string + events: string[] + ownerId: string + projectIds: string[] + createdAt: number + updatedAt: number + } +} + +export interface VercelDeleteWebhookParams { + apiKey: string + webhookId: string + teamId?: string +} + +export interface VercelDeleteWebhookResponse extends ToolResponse { + output: { + deleted: boolean + } +} + +export interface VercelCreateCheckParams { + apiKey: string + deploymentId: string + name: string + blocking: boolean + path?: string + detailsUrl?: string + externalId?: string + rerequestable?: boolean + teamId?: string +} + +export interface VercelCheckResponse extends ToolResponse { + output: { + id: string + name: string + status: string + conclusion: string | null + blocking: boolean + deploymentId: string + integrationId: string | null + externalId: string | null + detailsUrl: string | null + path: string | null + rerequestable: boolean + createdAt: number + updatedAt: number + startedAt: number | null + completedAt: number | null + } +} + +export interface VercelGetCheckParams { + apiKey: string + deploymentId: string + checkId: string + teamId?: string +} + +export interface VercelListChecksParams { + apiKey: string + deploymentId: string + teamId?: string +} + +export interface VercelListChecksResponse extends ToolResponse { + output: { + checks: Array<{ + id: string + name: string + status: string + conclusion: string | null + blocking: boolean + deploymentId: string + integrationId: string | null + externalId: string | null + detailsUrl: string | null + path: string | null + rerequestable: boolean + createdAt: number + updatedAt: number + startedAt: number | null + completedAt: number | null + }> + count: number + } +} + +export interface VercelUpdateCheckParams { + apiKey: string + deploymentId: string + checkId: string + name?: string + status?: string + conclusion?: string + detailsUrl?: string + externalId?: string + path?: string + output?: string + teamId?: string +} + +export interface VercelRerequestCheckParams { + apiKey: string + deploymentId: string + checkId: string + teamId?: string +} + +export interface VercelRerequestCheckResponse extends ToolResponse { + output: { + rerequested: boolean + } +} diff --git a/apps/sim/tools/vercel/unpause_project.ts b/apps/sim/tools/vercel/unpause_project.ts new file mode 100644 index 0000000000..d24b20200e --- /dev/null +++ b/apps/sim/tools/vercel/unpause_project.ts @@ -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' }, + }, +} diff --git a/apps/sim/tools/vercel/update_check.ts b/apps/sim/tools/vercel/update_check.ts new file mode 100644 index 0000000000..efa047dc30 --- /dev/null +++ b/apps/sim/tools/vercel/update_check.ts @@ -0,0 +1,159 @@ +import type { ToolConfig } from '@/tools/types' +import type { VercelCheckResponse, VercelUpdateCheckParams } from '@/tools/vercel/types' + +export const vercelUpdateCheckTool: ToolConfig = { + 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 = {} + 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, + }, + }, +} diff --git a/apps/sim/tools/vercel/update_edge_config_items.ts b/apps/sim/tools/vercel/update_edge_config_items.ts new file mode 100644 index 0000000000..998a7cfbde --- /dev/null +++ b/apps/sim/tools/vercel/update_edge_config_items.ts @@ -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', + }, + }, +} diff --git a/apps/sim/tools/vercel/update_env_var.ts b/apps/sim/tools/vercel/update_env_var.ts new file mode 100644 index 0000000000..fecc82c1c5 --- /dev/null +++ b/apps/sim/tools/vercel/update_env_var.ts @@ -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 = {} + 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, + }, + }, +} diff --git a/apps/sim/tools/vercel/update_project.ts b/apps/sim/tools/vercel/update_project.ts new file mode 100644 index 0000000000..ee76b1c485 --- /dev/null +++ b/apps/sim/tools/vercel/update_project.ts @@ -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 = {} + 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' }, + }, +}