mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-11 07:58:06 -05:00
Compare commits
3 Commits
v0.5.22
...
feat/zapie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3696658b03 | ||
|
|
4d9ae94047 | ||
|
|
ce72880935 |
@@ -4151,7 +4151,7 @@ export function DuckDuckGoIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg {...props} xmlns='http://www.w3.org/2000/svg' viewBox='-108 -108 216 216'>
|
||||
<circle r='108' fill='#d53' />
|
||||
<circle r='96' fill='none' stroke='#ffffff' stroke-width='7' />
|
||||
<circle r='96' fill='none' stroke='#ffffff' strokeWidth='7' />
|
||||
<path
|
||||
d='M-32-55C-62-48-51-6-51-6l19 93 7 3M-39-73h-8l11 4s-11 0-11 7c24-1 35 5 35 5'
|
||||
fill='#ddd'
|
||||
@@ -4199,3 +4199,25 @@ export function RssIcon(props: SVGProps<SVGSVGElement>) {
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export function ZapierIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
{...props}
|
||||
width='800px'
|
||||
height='800px'
|
||||
viewBox='0 0 256 256'
|
||||
version='1.1'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
xmlnsXlink='http://www.w3.org/1999/xlink'
|
||||
>
|
||||
<g>
|
||||
<path
|
||||
d='M128.080089,-0.000183105 C135.311053,0.0131003068 142.422517,0.624138494 149.335663,1.77979593 L149.335663,1.77979593 L149.335663,76.2997796 L202.166953,23.6044907 C208.002065,27.7488446 213.460883,32.3582023 218.507811,37.3926715 C223.557281,42.4271407 228.192318,47.8867213 232.346817,53.7047992 L232.346817,53.7047992 L179.512985,106.400063 L254.227854,106.400063 C255.387249,113.29414 256,120.36111 256,127.587243 L256,127.587243 L256,127.759881 C256,134.986013 255.387249,142.066204 254.227854,148.960282 L254.227854,148.960282 L179.500273,148.960282 L232.346817,201.642324 C228.192318,207.460402 223.557281,212.919983 218.523066,217.954452 L218.523066,217.954452 L218.507811,217.954452 C213.460883,222.988921 208.002065,227.6115 202.182208,231.742607 L202.182208,231.742607 L149.335663,179.04709 L149.335663,253.5672 C142.435229,254.723036 135.323765,255.333244 128.092802,255.348499 L128.092802,255.348499 L127.907197,255.348499 C120.673691,255.333244 113.590195,254.723036 106.677048,253.5672 L106.677048,253.5672 L106.677048,179.04709 L53.8457596,231.742607 C42.1780766,223.466917 31.977435,213.278734 23.6658953,201.642324 L23.6658953,201.642324 L76.4997269,148.960282 L1.78485803,148.960282 C0.612750404,142.052729 0,134.946095 0,127.719963 L0,127.719963 L0,127.349037 C0.0121454869,125.473817 0.134939797,123.182933 0.311311815,120.812834 L0.36577283,120.099764 C0.887996182,113.428547 1.78485803,106.400063 1.78485803,106.400063 L1.78485803,106.400063 L76.4997269,106.400063 L23.6658953,53.7047992 C27.8076812,47.8867213 32.4300059,42.4403618 37.4769335,37.4193681 L37.4769335,37.4193681 L37.5023588,37.3926715 C42.5391163,32.3582023 48.0106469,27.7488446 53.8457596,23.6044907 L53.8457596,23.6044907 L106.677048,76.2997796 L106.677048,1.77979593 C113.590195,0.624138494 120.688946,0.0131003068 127.932622,-0.000183105 L127.932622,-0.000183105 L128.080089,-0.000183105 Z M128.067377,95.7600714 L127.945335,95.7600714 C118.436262,95.7600714 109.32891,97.5001809 100.910584,100.661566 C97.7553011,109.043534 96.0085811,118.129275 95.9958684,127.613685 L95.9958684,127.733184 C96.0085811,137.217594 97.7553011,146.303589 100.923296,154.685303 C109.32891,157.846943 118.436262,159.587052 127.945335,159.587052 L128.067377,159.587052 C137.576449,159.587052 146.683802,157.846943 155.089415,154.685303 C158.257411,146.290368 160.004131,137.217594 160.004131,127.733184 L160.004131,127.613685 C160.004131,118.129275 158.257411,109.043534 155.089415,100.661566 C146.683802,97.5001809 137.576449,95.7600714 128.067377,95.7600714 Z'
|
||||
fill='#FF4A00'
|
||||
fillRule='nonzero'
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -110,6 +110,7 @@ import {
|
||||
WordpressIcon,
|
||||
xIcon,
|
||||
YouTubeIcon,
|
||||
ZapierIcon,
|
||||
ZendeskIcon,
|
||||
ZepIcon,
|
||||
ZoomIcon,
|
||||
@@ -121,6 +122,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
|
||||
zoom: ZoomIcon,
|
||||
zep: ZepIcon,
|
||||
zendesk: ZendeskIcon,
|
||||
zapier: ZapierIcon,
|
||||
youtube: YouTubeIcon,
|
||||
x: xIcon,
|
||||
wordpress: WordpressIcon,
|
||||
|
||||
@@ -30,19 +30,15 @@ Verwende den Start-Block für alles, was aus dem Editor, deploy-to-API oder depl
|
||||
<Card title="Schedule" href="/triggers/schedule">
|
||||
Cron- oder intervallbasierte Ausführung
|
||||
</Card>
|
||||
<Card title="RSS Feed" href="/triggers/rss">
|
||||
RSS- und Atom-Feeds auf neue Inhalte überwachen
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
## Schneller Vergleich
|
||||
|
||||
| Trigger | Startbedingung |
|
||||
|---------|-----------------|
|
||||
| **Start** | Editor-Ausführungen, Deploy-to-API-Anfragen oder Chat-Nachrichten |
|
||||
| **Start** | Editor-Ausführungen, deploy-to-API Anfragen oder Chat-Nachrichten |
|
||||
| **Schedule** | Timer, der im Schedule-Block verwaltet wird |
|
||||
| **Webhook** | Bei eingehender HTTP-Anfrage |
|
||||
| **RSS Feed** | Neues Element im Feed veröffentlicht |
|
||||
|
||||
> Der Start-Block stellt immer `input`, `conversationId` und `files` Felder bereit. Füge benutzerdefinierte Felder zum Eingabeformat für zusätzliche strukturierte Daten hinzu.
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
---
|
||||
title: RSS-Feed
|
||||
---
|
||||
|
||||
import { Callout } from 'fumadocs-ui/components/callout'
|
||||
import { Image } from '@/components/ui/image'
|
||||
|
||||
Der RSS-Feed-Block überwacht RSS- und Atom-Feeds – wenn neue Einträge veröffentlicht werden, wird Ihr Workflow automatisch ausgelöst.
|
||||
|
||||
<div className="flex justify-center">
|
||||
<Image
|
||||
src="/static/blocks/rss.png"
|
||||
alt="RSS-Feed-Block"
|
||||
width={500}
|
||||
height={400}
|
||||
className="my-6"
|
||||
/>
|
||||
</div>
|
||||
|
||||
## Konfiguration
|
||||
|
||||
1. **RSS-Feed-Block hinzufügen** - Ziehen Sie den RSS-Feed-Block, um Ihren Workflow zu starten
|
||||
2. **Feed-URL eingeben** - Fügen Sie die URL eines beliebigen RSS- oder Atom-Feeds ein
|
||||
3. **Bereitstellen** - Stellen Sie Ihren Workflow bereit, um das Polling zu aktivieren
|
||||
|
||||
Nach der Bereitstellung wird der Feed jede Minute auf neue Einträge überprüft.
|
||||
|
||||
## Ausgabefelder
|
||||
|
||||
| Feld | Typ | Beschreibung |
|
||||
|-------|------|-------------|
|
||||
| `title` | string | Titel des Eintrags |
|
||||
| `link` | string | Link des Eintrags |
|
||||
| `pubDate` | string | Veröffentlichungsdatum |
|
||||
| `item` | object | Rohdaten des Eintrags mit allen Feldern |
|
||||
| `feed` | object | Rohdaten der Feed-Metadaten |
|
||||
|
||||
Greifen Sie direkt auf zugeordnete Felder zu (`<rss.title>`) oder verwenden Sie die Rohobjekte für beliebige Felder (`<rss.item.author>`, `<rss.feed.language>`).
|
||||
|
||||
## Anwendungsfälle
|
||||
|
||||
- **Inhaltsüberwachung** - Verfolgen Sie Blogs, Nachrichtenseiten oder Updates von Wettbewerbern
|
||||
- **Podcast-Automatisierung** - Lösen Sie Workflows aus, wenn neue Episoden erscheinen
|
||||
- **Release-Tracking** - Überwachen Sie GitHub-Releases, Changelogs oder Produkt-Updates
|
||||
- **Social-Media-Aggregation** - Sammeln Sie Inhalte von Plattformen, die RSS-Feeds anbieten
|
||||
|
||||
<Callout>
|
||||
RSS-Trigger werden nur für Einträge ausgelöst, die nach dem Speichern des Triggers veröffentlicht wurden. Bestehende Feed-Einträge werden nicht verarbeitet.
|
||||
</Callout>
|
||||
@@ -110,6 +110,7 @@
|
||||
"wordpress",
|
||||
"x",
|
||||
"youtube",
|
||||
"zapier",
|
||||
"zendesk",
|
||||
"zep",
|
||||
"zoom"
|
||||
|
||||
275
apps/docs/content/docs/en/tools/zapier.mdx
Normal file
275
apps/docs/content/docs/en/tools/zapier.mdx
Normal file
@@ -0,0 +1,275 @@
|
||||
---
|
||||
title: Zapier
|
||||
description: Execute actions across 7,000+ apps using Zapier AI Actions
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="zapier"
|
||||
color="#FFFFFF"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
[Zapier](https://zapier.com/) connects 7,000+ apps and automates workflows without manual coding. The Zapier integration in Sim empowers you to execute, search, build, and manage powerful AI-driven actions across thousands of applications—all with plain English instructions.
|
||||
|
||||
With Zapier AI Actions in Sim, you can:
|
||||
|
||||
- **Execute Actions:** Instantly trigger any stored AI Action in your Zapier account. Launch emails, messages, project updates, document workflows, CRM updates, and much more.
|
||||
- **List Actions:** Retrieve a list of your available AI Actions configured in Zapier. Discover what's possible and find the right tool for your workflow.
|
||||
- **Search Apps:** Find apps in Zapier’s ecosystem by name or keyword. Easily check if the app you need is supported before building automations.
|
||||
- **Find Actions (Guess):** Describe what you want to accomplish in plain English (e.g., "send a Slack message", "create a Google Sheet row"), and let Zapier’s AI suggest matching actions—even across unfamiliar apps or APIs.
|
||||
- **Create Actions:** Programmatically define new AI Actions by specifying the target app, action type (write, read, search), and required parameters, directly from your workflow.
|
||||
|
||||
By combining these capabilities, you can search for apps, define new AI Actions, discover possible automations, list available actions, and execute any workflow—fully automated, with the power of both Sim and Zapier.
|
||||
{/* MANUAL-CONTENT-END */}
|
||||
|
||||
|
||||
## Usage Instructions
|
||||
|
||||
Connect to Zapier AI Actions to execute any of 30,000+ actions across 7,000+ apps. Send emails, create documents, update CRMs, post messages, and more - all through natural language instructions. Requires a Zapier AI Actions API key.
|
||||
|
||||
|
||||
|
||||
## Tools
|
||||
|
||||
### `zapier_execute_action`
|
||||
|
||||
Execute a stored AI Action in Zapier. Runs any of the 30,000+ actions across 7,000+ apps that Zapier supports.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Zapier AI Actions API key from actions.zapier.com/credentials |
|
||||
| `actionId` | string | Yes | The ID of the AI Action to execute |
|
||||
| `instructions` | string | Yes | Plain English instructions for what the action should do \(e.g., "Send a message about the weekly report to #general"\) |
|
||||
| `previewOnly` | boolean | No | If true, preview the execution without actually running it |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `executionLogId` | string | Unique identifier for this execution \(can be used for feedback\) |
|
||||
| `actionUsed` | string | Name of the action that was executed |
|
||||
| `inputParams` | json | Parameters that were passed to the API |
|
||||
| `resolvedParams` | json | Parameters that the AI resolved for execution |
|
||||
| `results` | json | Results from the action execution |
|
||||
| `resultFieldLabels` | json | Human-readable labels for result fields |
|
||||
| `status` | string | Execution status: success, error, empty, preview, or halted |
|
||||
| `error` | string | Error message if execution failed |
|
||||
|
||||
### `zapier_list_actions`
|
||||
|
||||
List all AI Actions configured in your Zapier account. Returns stored actions that can be executed.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Zapier AI Actions API key from actions.zapier.com/credentials |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `actions` | json | Array of configured AI Actions with id, description, actionType, app, appLabel, action, actionLabel, params, accountId, authenticationId, needs |
|
||||
| `configurationLink` | string | Link to configure more actions in Zapier |
|
||||
|
||||
### `zapier_search_apps`
|
||||
|
||||
Search for apps available in Zapier. Returns apps with their available action counts.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Zapier AI Actions API key from actions.zapier.com/credentials |
|
||||
| `query` | string | No | Optional search query to filter apps by name |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `apps` | json | Array of apps with app, name, logoUrl, authType, actions \(raw counts by type\), actionCount, writeActionCount, searchActionCount, readActionCount |
|
||||
|
||||
### `zapier_guess_actions`
|
||||
|
||||
Find relevant Zapier actions using natural language. Searches across 30,000+ actions to find the best matches for your query.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Zapier AI Actions API key from actions.zapier.com/credentials |
|
||||
| `query` | string | Yes | Natural language description of what you want to do \(e.g., "send a Slack message", "create a Google Doc"\) |
|
||||
| `actionTypes` | array | No | Types of actions to search for: write, search, read. If not specified, returns all types. |
|
||||
| `count` | number | No | Maximum number of results to return \(default: 25\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `actions` | json | Array of matching actions with app, action, actionType, name \(combined app/action name\), description, image, and score |
|
||||
|
||||
### `zapier_create_action`
|
||||
|
||||
Create a new stored AI Action in Zapier. The action can then be executed with zapier_execute_action.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Zapier AI Actions API key from actions.zapier.com/credentials |
|
||||
| `app` | string | Yes | The app identifier \(e.g., "slack", "gmail", "google-docs"\) |
|
||||
| `action` | string | Yes | The action identifier \(e.g., "send_channel_message", "send_email"\) |
|
||||
| `actionType` | string | No | Type of action: write, search, or read. Defaults to write. |
|
||||
| `accountId` | number | No | Zapier account ID |
|
||||
| `authenticationId` | number | No | Authentication ID for the app connection |
|
||||
| `meta` | json | No | Metadata object with params labels, app_label, action_label, authentication_label, app_needs_auth |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `id` | string | The ID of the created AI Action \(use this with execute_action\) |
|
||||
| `description` | string | Description of the action |
|
||||
| `actionType` | string | Type of action \(write, search, read, read_bulk, search_or_write, search_and_write\) |
|
||||
| `app` | string | App identifier |
|
||||
| `appLabel` | string | Human-readable app label from meta |
|
||||
| `action` | string | Action identifier |
|
||||
| `actionLabel` | string | Human-readable action label from meta |
|
||||
|
||||
### `zapier_stateless_execute`
|
||||
|
||||
Execute any Zapier action directly without creating a stored AI Action first. Provide the app, action, and instructions.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Zapier AI Actions API key from actions.zapier.com/credentials |
|
||||
| `app` | string | Yes | The app to use \(e.g., "SlackAPI", "GoogleSheetsV2API", "GmailV2API"\) |
|
||||
| `action` | string | Yes | The action to run \(e.g., "direct_message", "add_row", "send_email"\) |
|
||||
| `instructions` | string | Yes | Plain English instructions about how to run the action \(e.g., "Send a message saying hello to #general"\) |
|
||||
| `actionType` | string | No | Type of action: write, search, read, read_bulk, search_or_write, search_and_write |
|
||||
| `previewOnly` | boolean | No | If true, preview the execution without actually running it |
|
||||
| `authenticationId` | number | No | Authentication ID for the app connection |
|
||||
| `accountId` | number | No | Zapier account ID |
|
||||
| `providerId` | string | No | Provider ID for AI Actions |
|
||||
| `tokenBudget` | number | No | Max tokens per field \(default: 1000\) |
|
||||
| `skipParamGuessing` | boolean | No | Skip AI parameter guessing |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `executionLogId` | string | Unique identifier for this execution |
|
||||
| `actionUsed` | string | Name of the action that was executed |
|
||||
| `inputParams` | json | Parameters that were passed to the API |
|
||||
| `resolvedParams` | json | Parameters that the AI resolved for execution |
|
||||
| `results` | json | Results from the action execution |
|
||||
| `resultFieldLabels` | json | Human-readable labels for result fields |
|
||||
| `status` | string | Execution status: success, error, empty, preview, or halted |
|
||||
| `error` | string | Error message if execution failed |
|
||||
|
||||
### `zapier_search_app_actions`
|
||||
|
||||
Search for available actions within a specific Zapier app. Returns all actions the app supports.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Zapier AI Actions API key from actions.zapier.com/credentials |
|
||||
| `app` | string | Yes | The app identifier to search actions for \(e.g., "SlackAPI", "GmailV2API"\) |
|
||||
| `query` | string | No | Optional search query to filter actions by name or description |
|
||||
| `actionTypes` | array | No | Filter by action types: write, search, read, read_bulk, search_or_write, search_and_write. Defaults to write and search. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `actions` | json | Array of actions with app, action, actionType, displayName, description, relevancyScore, appNeedsAuth, appInfo |
|
||||
|
||||
### `zapier_get_action_details`
|
||||
|
||||
Get detailed information about a specific action including its required inputs (needs) and outputs (gives).
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Zapier AI Actions API key from actions.zapier.com/credentials |
|
||||
| `app` | string | Yes | The app identifier \(e.g., "SlackAPI", "GmailV2API"\) |
|
||||
| `action` | string | Yes | The action identifier \(e.g., "send_channel_message", "send_email"\) |
|
||||
| `actionType` | string | No | Type of action: write, search, read. Defaults to write. |
|
||||
| `includeNeeds` | boolean | No | Include input requirements \(needs\). Defaults to true. |
|
||||
| `includeGives` | boolean | No | Include output specifications \(gives\). Defaults to false. |
|
||||
| `includeSample` | boolean | No | Include sample execution result. Defaults to false. |
|
||||
| `accountId` | number | No | Zapier account ID |
|
||||
| `authenticationId` | number | No | Authentication ID for the app connection |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `action` | json | Action metadata including type, key, name, noun, and description |
|
||||
| `needs` | json | Array of input requirements with key, type, label, required, helpText, defaultValue, choices, dependsOn |
|
||||
| `gives` | json | Array of output fields with key, label, type, important, sample |
|
||||
| `sample` | json | Sample execution result if requested |
|
||||
| `customNeedsProbability` | number | Probability \(0-1\) that this action has custom/dynamic input fields |
|
||||
|
||||
### `zapier_update_action`
|
||||
|
||||
Update an existing stored AI Action configuration in Zapier.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Zapier AI Actions API key from actions.zapier.com/credentials |
|
||||
| `actionId` | string | Yes | The ID of the AI Action to update |
|
||||
| `app` | string | Yes | The app identifier \(e.g., "SlackAPI", "GmailV2API"\) |
|
||||
| `action` | string | Yes | The action identifier \(e.g., "send_channel_message", "send_email"\) |
|
||||
| `actionType` | string | No | Type of action: write, search, read, read_bulk, search_or_write, search_and_write |
|
||||
| `accountId` | number | No | Zapier account ID |
|
||||
| `authenticationId` | number | No | Authentication ID for the app connection |
|
||||
| `meta` | json | No | Metadata object with params labels, app_label, action_label, authentication_label, app_needs_auth |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `id` | string | The ID of the updated AI Action |
|
||||
| `description` | string | Description of the action |
|
||||
| `actionType` | string | Type of action |
|
||||
| `app` | string | App identifier |
|
||||
| `appLabel` | string | Human-readable app label |
|
||||
| `action` | string | Action identifier |
|
||||
| `actionLabel` | string | Human-readable action label |
|
||||
|
||||
### `zapier_delete_action`
|
||||
|
||||
Delete a stored AI Action from Zapier.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | Zapier AI Actions API key from actions.zapier.com/credentials |
|
||||
| `actionId` | string | Yes | The ID of the AI Action to delete |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `deleted` | boolean | Whether the action was successfully deleted |
|
||||
| `message` | string | Status message |
|
||||
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
- Category: `tools`
|
||||
- Type: `zapier`
|
||||
@@ -1,184 +0,0 @@
|
||||
---
|
||||
title: SFTP
|
||||
description: Transferir archivos a través de SFTP (Protocolo de transferencia de
|
||||
archivos SSH)
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="sftp"
|
||||
color="#2D3748"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
[SFTP (Protocolo de transferencia de archivos SSH)](https://en.wikipedia.org/wiki/SSH_File_Transfer_Protocol) es un protocolo de red seguro que te permite subir, descargar y gestionar archivos en servidores remotos. SFTP opera sobre SSH, lo que lo hace ideal para transferencias de archivos automatizadas y cifradas, así como para la gestión remota de archivos dentro de flujos de trabajo modernos.
|
||||
|
||||
Con las herramientas SFTP integradas en Sim, puedes automatizar fácilmente el movimiento de archivos entre tus agentes de IA y sistemas o servidores externos. Esto permite a tus agentes gestionar intercambios críticos de datos, copias de seguridad, generación de documentos y orquestación de sistemas remotos, todo con una seguridad robusta.
|
||||
|
||||
**Funcionalidades clave disponibles a través de las herramientas SFTP:**
|
||||
|
||||
- **Subir archivos:** Transfiere sin problemas archivos de cualquier tipo desde tu flujo de trabajo a un servidor remoto, con soporte tanto para autenticación por contraseña como por clave privada SSH.
|
||||
- **Descargar archivos:** Recupera archivos de servidores SFTP remotos directamente para su procesamiento, archivo o automatización adicional.
|
||||
- **Listar y gestionar archivos:** Enumera directorios, elimina o crea archivos y carpetas, y gestiona permisos del sistema de archivos de forma remota.
|
||||
- **Autenticación flexible:** Conéctate usando contraseñas tradicionales o claves SSH, con soporte para frases de contraseña y control de permisos.
|
||||
- **Soporte para archivos grandes:** Gestiona programáticamente cargas y descargas de archivos grandes, con límites de tamaño incorporados para mayor seguridad.
|
||||
|
||||
Al integrar SFTP en Sim, puedes automatizar operaciones seguras de archivos como parte de cualquier flujo de trabajo, ya sea recopilación de datos, informes, mantenimiento de sistemas remotos o intercambio dinámico de contenido entre plataformas.
|
||||
|
||||
Las secciones a continuación describen las principales herramientas SFTP disponibles:
|
||||
|
||||
- **sftp_upload:** Sube uno o más archivos a un servidor remoto.
|
||||
- **sftp_download:** Descarga archivos desde un servidor remoto a tu flujo de trabajo.
|
||||
- **sftp_list:** Lista el contenido de directorios en un servidor SFTP remoto.
|
||||
- **sftp_delete:** Elimina archivos o directorios de un servidor remoto.
|
||||
- **sftp_create:** Crea nuevos archivos en un servidor SFTP remoto.
|
||||
- **sftp_mkdir:** Crea nuevos directorios de forma remota.
|
||||
|
||||
Consulta la documentación de la herramienta a continuación para conocer los parámetros detallados de entrada y salida para cada operación.
|
||||
{/* MANUAL-CONTENT-END */}
|
||||
|
||||
## Instrucciones de uso
|
||||
|
||||
Sube, descarga, lista y gestiona archivos en servidores remotos a través de SFTP. Compatible con autenticación por contraseña y clave privada para transferencias seguras de archivos.
|
||||
|
||||
## Herramientas
|
||||
|
||||
### `sftp_upload`
|
||||
|
||||
Subir archivos a un servidor SFTP remoto
|
||||
|
||||
#### Entrada
|
||||
|
||||
| Parámetro | Tipo | Obligatorio | Descripción |
|
||||
| --------- | ---- | ----------- | ----------- |
|
||||
| `host` | string | Sí | Nombre de host o dirección IP del servidor SFTP |
|
||||
| `port` | number | Sí | Puerto del servidor SFTP \(predeterminado: 22\) |
|
||||
| `username` | string | Sí | Nombre de usuario SFTP |
|
||||
| `password` | string | No | Contraseña para autenticación \(si no se usa clave privada\) |
|
||||
| `privateKey` | string | No | Clave privada para autenticación \(formato OpenSSH\) |
|
||||
| `passphrase` | string | No | Frase de contraseña para clave privada cifrada |
|
||||
| `remotePath` | string | Sí | Directorio de destino en el servidor remoto |
|
||||
| `files` | file[] | No | Archivos para subir |
|
||||
| `fileContent` | string | No | Contenido directo del archivo para subir \(para archivos de texto\) |
|
||||
| `fileName` | string | No | Nombre del archivo cuando se usa contenido directo |
|
||||
| `overwrite` | boolean | No | Si se deben sobrescribir archivos existentes \(predeterminado: true\) |
|
||||
| `permissions` | string | No | Permisos del archivo \(p. ej., 0644\) |
|
||||
|
||||
#### Salida
|
||||
|
||||
| Parámetro | Tipo | Descripción |
|
||||
| --------- | ---- | ----------- |
|
||||
| `success` | boolean | Si la subida fue exitosa |
|
||||
| `uploadedFiles` | json | Array de detalles de archivos subidos \(nombre, rutaRemota, tamaño\) |
|
||||
| `message` | string | Mensaje de estado de la operación |
|
||||
|
||||
### `sftp_download`
|
||||
|
||||
Descargar un archivo desde un servidor SFTP remoto
|
||||
|
||||
#### Entrada
|
||||
|
||||
| Parámetro | Tipo | Obligatorio | Descripción |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | Sí | Nombre de host o dirección IP del servidor SFTP |
|
||||
| `port` | number | Sí | Puerto del servidor SFTP \(predeterminado: 22\) |
|
||||
| `username` | string | Sí | Nombre de usuario SFTP |
|
||||
| `password` | string | No | Contraseña para autenticación \(si no se usa clave privada\) |
|
||||
| `privateKey` | string | No | Clave privada para autenticación \(formato OpenSSH\) |
|
||||
| `passphrase` | string | No | Frase de contraseña para clave privada cifrada |
|
||||
| `remotePath` | string | Sí | Ruta al archivo en el servidor remoto |
|
||||
| `encoding` | string | No | Codificación de salida: utf-8 para texto, base64 para binario \(predeterminado: utf-8\) |
|
||||
|
||||
#### Salida
|
||||
|
||||
| Parámetro | Tipo | Descripción |
|
||||
| --------- | ---- | ----------- |
|
||||
| `success` | boolean | Si la descarga fue exitosa |
|
||||
| `fileName` | string | Nombre del archivo descargado |
|
||||
| `content` | string | Contenido del archivo \(texto o codificado en base64\) |
|
||||
| `size` | number | Tamaño del archivo en bytes |
|
||||
| `encoding` | string | Codificación del contenido \(utf-8 o base64\) |
|
||||
| `message` | string | Mensaje de estado de la operación |
|
||||
|
||||
### `sftp_list`
|
||||
|
||||
Listar archivos y directorios en un servidor SFTP remoto
|
||||
|
||||
#### Entrada
|
||||
|
||||
| Parámetro | Tipo | Obligatorio | Descripción |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | Sí | Nombre de host o dirección IP del servidor SFTP |
|
||||
| `port` | number | Sí | Puerto del servidor SFTP \(predeterminado: 22\) |
|
||||
| `username` | string | Sí | Nombre de usuario SFTP |
|
||||
| `password` | string | No | Contraseña para autenticación \(si no se usa clave privada\) |
|
||||
| `privateKey` | string | No | Clave privada para autenticación \(formato OpenSSH\) |
|
||||
| `passphrase` | string | No | Frase de contraseña para clave privada cifrada |
|
||||
| `remotePath` | string | Sí | Ruta del directorio en el servidor remoto |
|
||||
| `detailed` | boolean | No | Incluir información detallada de archivos \(tamaño, permisos, fecha de modificación\) |
|
||||
|
||||
#### Salida
|
||||
|
||||
| Parámetro | Tipo | Descripción |
|
||||
| --------- | ---- | ----------- |
|
||||
| `success` | boolean | Si la operación fue exitosa |
|
||||
| `path` | string | Ruta del directorio que fue listado |
|
||||
| `entries` | json | Array de entradas del directorio con nombre, tipo, tamaño, permisos, modifiedAt |
|
||||
| `count` | number | Número de entradas en el directorio |
|
||||
| `message` | string | Mensaje de estado de la operación |
|
||||
|
||||
### `sftp_delete`
|
||||
|
||||
Eliminar un archivo o directorio en un servidor SFTP remoto
|
||||
|
||||
#### Entrada
|
||||
|
||||
| Parámetro | Tipo | Requerido | Descripción |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | Sí | Nombre de host o dirección IP del servidor SFTP |
|
||||
| `port` | number | Sí | Puerto del servidor SFTP \(predeterminado: 22\) |
|
||||
| `username` | string | Sí | Nombre de usuario SFTP |
|
||||
| `password` | string | No | Contraseña para autenticación \(si no se usa clave privada\) |
|
||||
| `privateKey` | string | No | Clave privada para autenticación \(formato OpenSSH\) |
|
||||
| `passphrase` | string | No | Frase de contraseña para clave privada cifrada |
|
||||
| `remotePath` | string | Sí | Ruta al archivo o directorio a eliminar |
|
||||
| `recursive` | boolean | No | Eliminar directorios recursivamente |
|
||||
|
||||
#### Salida
|
||||
|
||||
| Parámetro | Tipo | Descripción |
|
||||
| --------- | ---- | ----------- |
|
||||
| `success` | boolean | Si la eliminación fue exitosa |
|
||||
| `deletedPath` | string | Ruta que fue eliminada |
|
||||
| `message` | string | Mensaje de estado de la operación |
|
||||
|
||||
### `sftp_mkdir`
|
||||
|
||||
Crear un directorio en un servidor SFTP remoto
|
||||
|
||||
#### Entrada
|
||||
|
||||
| Parámetro | Tipo | Obligatorio | Descripción |
|
||||
| --------- | ---- | ----------- | ----------- |
|
||||
| `host` | string | Sí | Nombre de host o dirección IP del servidor SFTP |
|
||||
| `port` | number | Sí | Puerto del servidor SFTP \(predeterminado: 22\) |
|
||||
| `username` | string | Sí | Nombre de usuario SFTP |
|
||||
| `password` | string | No | Contraseña para autenticación \(si no se usa clave privada\) |
|
||||
| `privateKey` | string | No | Clave privada para autenticación \(formato OpenSSH\) |
|
||||
| `passphrase` | string | No | Frase de contraseña para clave privada cifrada |
|
||||
| `remotePath` | string | Sí | Ruta para el nuevo directorio |
|
||||
| `recursive` | boolean | No | Crear directorios principales si no existen |
|
||||
|
||||
#### Salida
|
||||
|
||||
| Parámetro | Tipo | Descripción |
|
||||
| --------- | ---- | ----------- |
|
||||
| `success` | boolean | Si el directorio se creó correctamente |
|
||||
| `createdPath` | string | Ruta del directorio creado |
|
||||
| `message` | string | Mensaje de estado de la operación |
|
||||
|
||||
## Notas
|
||||
|
||||
- Categoría: `tools`
|
||||
- Tipo: `sftp`
|
||||
@@ -30,9 +30,6 @@ Utiliza el bloque Start para todo lo que se origina desde el editor, despliegue
|
||||
<Card title="Schedule" href="/triggers/schedule">
|
||||
Ejecución basada en cron o intervalos
|
||||
</Card>
|
||||
<Card title="RSS Feed" href="/triggers/rss">
|
||||
Monitorea feeds RSS y Atom para nuevo contenido
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
## Comparación rápida
|
||||
@@ -42,7 +39,6 @@ Utiliza el bloque Start para todo lo que se origina desde el editor, despliegue
|
||||
| **Start** | Ejecuciones del editor, solicitudes de despliegue a API o mensajes de chat |
|
||||
| **Schedule** | Temporizador gestionado en el bloque de programación |
|
||||
| **Webhook** | Al recibir una solicitud HTTP entrante |
|
||||
| **RSS Feed** | Nuevo elemento publicado en el feed |
|
||||
|
||||
> El bloque Start siempre expone los campos `input`, `conversationId` y `files`. Añade campos personalizados al formato de entrada para datos estructurados adicionales.
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
---
|
||||
title: Feed RSS
|
||||
---
|
||||
|
||||
import { Callout } from 'fumadocs-ui/components/callout'
|
||||
import { Image } from '@/components/ui/image'
|
||||
|
||||
El bloque de Feed RSS monitorea feeds RSS y Atom – cuando se publican nuevos elementos, tu flujo de trabajo se activa automáticamente.
|
||||
|
||||
<div className="flex justify-center">
|
||||
<Image
|
||||
src="/static/blocks/rss.png"
|
||||
alt="Bloque de Feed RSS"
|
||||
width={500}
|
||||
height={400}
|
||||
className="my-6"
|
||||
/>
|
||||
</div>
|
||||
|
||||
## Configuración
|
||||
|
||||
1. **Añadir bloque de Feed RSS** - Arrastra el bloque de Feed RSS para iniciar tu flujo de trabajo
|
||||
2. **Introducir URL del feed** - Pega la URL de cualquier feed RSS o Atom
|
||||
3. **Implementar** - Implementa tu flujo de trabajo para activar el sondeo
|
||||
|
||||
Una vez implementado, el feed se comprueba cada minuto en busca de nuevos elementos.
|
||||
|
||||
## Campos de salida
|
||||
|
||||
| Campo | Tipo | Descripción |
|
||||
|-------|------|-------------|
|
||||
| `title` | string | Título del elemento |
|
||||
| `link` | string | Enlace del elemento |
|
||||
| `pubDate` | string | Fecha de publicación |
|
||||
| `item` | object | Elemento en bruto con todos los campos |
|
||||
| `feed` | object | Metadatos en bruto del feed |
|
||||
|
||||
Accede a los campos mapeados directamente (`<rss.title>`) o utiliza los objetos en bruto para cualquier campo (`<rss.item.author>`, `<rss.feed.language>`).
|
||||
|
||||
## Casos de uso
|
||||
|
||||
- **Monitoreo de contenido** - Sigue blogs, sitios de noticias o actualizaciones de competidores
|
||||
- **Automatización de podcasts** - Activa flujos de trabajo cuando se publican nuevos episodios
|
||||
- **Seguimiento de lanzamientos** - Monitorea lanzamientos de GitHub, registros de cambios o actualizaciones de productos
|
||||
- **Agregación social** - Recopila contenido de plataformas que exponen feeds RSS
|
||||
|
||||
<Callout>
|
||||
Los disparadores RSS solo se activan para elementos publicados después de guardar el disparador. Los elementos existentes en el feed no se procesan.
|
||||
</Callout>
|
||||
@@ -21,28 +21,24 @@ import { Image } from '@/components/ui/image'
|
||||
Utilisez le bloc Démarrer pour tout ce qui provient de l'éditeur, du déploiement vers l'API ou des expériences de déploiement vers le chat. D'autres déclencheurs restent disponibles pour les flux de travail basés sur des événements :
|
||||
|
||||
<Cards>
|
||||
<Card title="Start" href="/triggers/start">
|
||||
<Card title="Démarrer" href="/triggers/start">
|
||||
Point d'entrée unifié qui prend en charge les exécutions de l'éditeur, les déploiements d'API et les déploiements de chat
|
||||
</Card>
|
||||
<Card title="Webhook" href="/triggers/webhook">
|
||||
Recevoir des charges utiles de webhook externes
|
||||
</Card>
|
||||
<Card title="Schedule" href="/triggers/schedule">
|
||||
<Card title="Planification" href="/triggers/schedule">
|
||||
Exécution basée sur cron ou intervalle
|
||||
</Card>
|
||||
<Card title="RSS Feed" href="/triggers/rss">
|
||||
Surveiller les flux RSS et Atom pour du nouveau contenu
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
## Comparaison rapide
|
||||
|
||||
| Déclencheur | Condition de démarrage |
|
||||
|---------|-----------------|
|
||||
| **Start** | Exécutions de l'éditeur, requêtes de déploiement d'API ou messages de chat |
|
||||
| **Schedule** | Minuteur géré dans le bloc de planification |
|
||||
| **Démarrer** | Exécutions de l'éditeur, requêtes de déploiement vers l'API ou messages de chat |
|
||||
| **Planification** | Minuteur géré dans le bloc de planification |
|
||||
| **Webhook** | Sur requête HTTP entrante |
|
||||
| **RSS Feed** | Nouvel élément publié dans le flux |
|
||||
|
||||
> Le bloc Démarrer expose toujours les champs `input`, `conversationId` et `files`. Ajoutez des champs personnalisés au format d'entrée pour des données structurées supplémentaires.
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
---
|
||||
title: Flux RSS
|
||||
---
|
||||
|
||||
import { Callout } from 'fumadocs-ui/components/callout'
|
||||
import { Image } from '@/components/ui/image'
|
||||
|
||||
Le bloc Flux RSS surveille les flux RSS et Atom – lorsque de nouveaux éléments sont publiés, votre workflow se déclenche automatiquement.
|
||||
|
||||
<div className="flex justify-center">
|
||||
<Image
|
||||
src="/static/blocks/rss.png"
|
||||
alt="Bloc Flux RSS"
|
||||
width={500}
|
||||
height={400}
|
||||
className="my-6"
|
||||
/>
|
||||
</div>
|
||||
|
||||
## Configuration
|
||||
|
||||
1. **Ajouter le bloc Flux RSS** - Faites glisser le bloc Flux RSS pour démarrer votre workflow
|
||||
2. **Saisir l'URL du flux** - Collez l'URL de n'importe quel flux RSS ou Atom
|
||||
3. **Déployer** - Déployez votre workflow pour activer l'interrogation
|
||||
|
||||
Une fois déployé, le flux est vérifié chaque minute pour détecter de nouveaux éléments.
|
||||
|
||||
## Champs de sortie
|
||||
|
||||
| Champ | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `title` | string | Titre de l'élément |
|
||||
| `link` | string | Lien de l'élément |
|
||||
| `pubDate` | string | Date de publication |
|
||||
| `item` | object | Élément brut avec tous les champs |
|
||||
| `feed` | object | Métadonnées brutes du flux |
|
||||
|
||||
Accédez directement aux champs mappés (`<rss.title>`) ou utilisez les objets bruts pour n'importe quel champ (`<rss.item.author>`, `<rss.feed.language>`).
|
||||
|
||||
## Cas d'utilisation
|
||||
|
||||
- **Surveillance de contenu** - Suivez les blogs, sites d'actualités ou mises à jour des concurrents
|
||||
- **Automatisation de podcast** - Déclenchez des workflows lors de la sortie de nouveaux épisodes
|
||||
- **Suivi des versions** - Surveillez les versions GitHub, les journaux de modifications ou les mises à jour de produits
|
||||
- **Agrégation sociale** - Collectez du contenu à partir de plateformes qui exposent des flux RSS
|
||||
|
||||
<Callout>
|
||||
Les déclencheurs RSS ne s'activent que pour les éléments publiés après l'enregistrement du déclencheur. Les éléments existants du flux ne sont pas traités.
|
||||
</Callout>
|
||||
@@ -21,28 +21,24 @@ import { Image } from '@/components/ui/image'
|
||||
エディタ、APIへのデプロイ、またはチャットへのデプロイエクスペリエンスから始まるすべてのものにはスタートブロックを使用します。イベント駆動型ワークフローには他のトリガーも利用可能です:
|
||||
|
||||
<Cards>
|
||||
<Card title="Start" href="/triggers/start">
|
||||
<Card title="スタート" href="/triggers/start">
|
||||
エディタ実行、APIデプロイメント、チャットデプロイメントをサポートする統合エントリーポイント
|
||||
</Card>
|
||||
<Card title="Webhook" href="/triggers/webhook">
|
||||
外部のwebhookペイロードを受信
|
||||
<Card title="ウェブフック" href="/triggers/webhook">
|
||||
外部ウェブフックペイロードを受信
|
||||
</Card>
|
||||
<Card title="Schedule" href="/triggers/schedule">
|
||||
<Card title="スケジュール" href="/triggers/schedule">
|
||||
Cronまたは間隔ベースの実行
|
||||
</Card>
|
||||
<Card title="RSS Feed" href="/triggers/rss">
|
||||
新しいコンテンツのRSSとAtomフィードを監視
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
## クイック比較
|
||||
|
||||
| トリガー | 開始条件 |
|
||||
|---------|-----------------|
|
||||
| **Start** | エディタ実行、APIへのデプロイリクエスト、またはチャットメッセージ |
|
||||
| **Schedule** | スケジュールブロックで管理されるタイマー |
|
||||
| **Webhook** | 受信HTTPリクエスト時 |
|
||||
| **RSS Feed** | フィードに新しいアイテムが公開された時 |
|
||||
| **スタート** | エディタ実行、APIへのデプロイリクエスト、またはチャットメッセージ |
|
||||
| **スケジュール** | スケジュールブロックで管理されるタイマー |
|
||||
| **ウェブフック** | 受信HTTPリクエスト時 |
|
||||
|
||||
> スタートブロックは常に `input`、`conversationId`、および `files` フィールドを公開します。追加の構造化データには入力フォーマットにカスタムフィールドを追加してください。
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
---
|
||||
title: RSSフィード
|
||||
---
|
||||
|
||||
import { Callout } from 'fumadocs-ui/components/callout'
|
||||
import { Image } from '@/components/ui/image'
|
||||
|
||||
RSSフィードブロックはRSSとAtomフィードを監視します - 新しいアイテムが公開されると、ワークフローが自動的にトリガーされます。
|
||||
|
||||
<div className="flex justify-center">
|
||||
<Image
|
||||
src="/static/blocks/rss.png"
|
||||
alt="RSSフィードブロック"
|
||||
width={500}
|
||||
height={400}
|
||||
className="my-6"
|
||||
/>
|
||||
</div>
|
||||
|
||||
## 設定
|
||||
|
||||
1. **RSSフィードブロックを追加** - RSSフィードブロックをドラッグしてワークフローを開始
|
||||
2. **フィードURLを入力** - 任意のRSSまたはAtomフィードのURLを貼り付け
|
||||
3. **デプロイ** - ワークフローをデプロイしてポーリングを有効化
|
||||
|
||||
デプロイ後、フィードは1分ごとに新しいアイテムをチェックします。
|
||||
|
||||
## 出力フィールド
|
||||
|
||||
| フィールド | 型 | 説明 |
|
||||
|-------|------|-------------|
|
||||
| `title` | string | アイテムのタイトル |
|
||||
| `link` | string | アイテムのリンク |
|
||||
| `pubDate` | string | 公開日 |
|
||||
| `item` | object | すべてのフィールドを含む生のアイテム |
|
||||
| `feed` | object | 生のフィードメタデータ |
|
||||
|
||||
マッピングされたフィールドに直接アクセスするか(`<rss.title>`)、任意のフィールドに生のオブジェクトを使用します(`<rss.item.author>`、`<rss.feed.language>`)。
|
||||
|
||||
## ユースケース
|
||||
|
||||
- **コンテンツ監視** - ブログ、ニュースサイト、または競合他社の更新を追跡
|
||||
- **ポッドキャスト自動化** - 新しいエピソードが公開されたときにワークフローをトリガー
|
||||
- **リリース追跡** - GitHubリリース、変更ログ、または製品アップデートを監視
|
||||
- **ソーシャルアグリゲーション** - RSSフィードを公開しているプラットフォームからコンテンツを収集
|
||||
|
||||
<Callout>
|
||||
RSSトリガーは、トリガーを保存した後に公開されたアイテムに対してのみ実行されます。既存のフィードアイテムは処理されません。
|
||||
</Callout>
|
||||
@@ -21,28 +21,24 @@ import { Image } from '@/components/ui/image'
|
||||
使用 Start 块处理从编辑器、部署到 API 或部署到聊天的所有操作。其他触发器可用于事件驱动的工作流:
|
||||
|
||||
<Cards>
|
||||
<Card title="开始" href="/triggers/start">
|
||||
<Card title="Start" href="/triggers/start">
|
||||
支持编辑器运行、API 部署和聊天部署的统一入口点
|
||||
</Card>
|
||||
<Card title="Webhook" href="/triggers/webhook">
|
||||
接收外部 webhook 负载
|
||||
</Card>
|
||||
<Card title="计划" href="/triggers/schedule">
|
||||
<Card title="Schedule" href="/triggers/schedule">
|
||||
基于 Cron 或间隔的执行
|
||||
</Card>
|
||||
<Card title="RSS 源" href="/triggers/rss">
|
||||
监控 RSS 和 Atom 源的新内容
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
## 快速对比
|
||||
|
||||
| 触发器 | 启动条件 |
|
||||
|---------|-----------------|
|
||||
| **开始** | 编辑器运行、部署到 API 请求或聊天消息 |
|
||||
| **计划** | 在计划块中管理的计时器 |
|
||||
| **Webhook** | 收到入站 HTTP 请求时 |
|
||||
| **RSS 源** | 源中发布了新项目 |
|
||||
| **Start** | 编辑器运行、部署到 API 请求或聊天消息 |
|
||||
| **Schedule** | 在 Schedule 块中管理的计时器 |
|
||||
| **Webhook** | 收到入站 HTTP 请求 |
|
||||
|
||||
> Start 块始终公开 `input`、`conversationId` 和 `files` 字段。通过向输入格式添加自定义字段来增加结构化数据。
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
---
|
||||
title: RSS 订阅源
|
||||
---
|
||||
|
||||
import { Callout } from 'fumadocs-ui/components/callout'
|
||||
import { Image } from '@/components/ui/image'
|
||||
|
||||
RSS 订阅源模块监控 RSS 和 Atom 订阅源——当有新内容发布时,您的工作流会自动触发。
|
||||
|
||||
<div className="flex justify-center">
|
||||
<Image
|
||||
src="/static/blocks/rss.png"
|
||||
alt="RSS 订阅源模块"
|
||||
width={500}
|
||||
height={400}
|
||||
className="my-6"
|
||||
/>
|
||||
</div>
|
||||
|
||||
## 配置
|
||||
|
||||
1. **添加 RSS 订阅源模块** - 拖动 RSS 订阅源模块以开始您的工作流
|
||||
2. **输入订阅源 URL** - 粘贴任意 RSS 或 Atom 订阅源的 URL
|
||||
3. **部署** - 部署您的工作流以激活轮询
|
||||
|
||||
部署后,订阅源每分钟检查一次是否有新内容。
|
||||
|
||||
## 输出字段
|
||||
|
||||
| 字段 | 类型 | 描述 |
|
||||
|-------|------|-------------|
|
||||
| `title` | string | 内容标题 |
|
||||
| `link` | string | 内容链接 |
|
||||
| `pubDate` | string | 发布日期 |
|
||||
| `item` | object | 包含所有字段的原始内容 |
|
||||
| `feed` | object | 原始订阅源元数据 |
|
||||
|
||||
可以直接访问映射字段 (`<rss.title>`),或者使用原始对象访问任意字段 (`<rss.item.author>`, `<rss.feed.language>`)。
|
||||
|
||||
## 使用场景
|
||||
|
||||
- **内容监控** - 跟踪博客、新闻网站或竞争对手的更新
|
||||
- **播客自动化** - 当新剧集发布时触发工作流
|
||||
- **版本跟踪** - 监控 GitHub 发布、更新日志或产品更新
|
||||
- **社交聚合** - 收集支持 RSS 订阅源的平台内容
|
||||
|
||||
<Callout>
|
||||
RSS 触发器仅对您保存触发器后发布的内容生效。现有的订阅源内容不会被处理。
|
||||
</Callout>
|
||||
@@ -5760,9 +5760,9 @@ checksums:
|
||||
content/1: e71056df0f7b2eb3b2f271f21d0052cc
|
||||
content/2: da2b445db16c149f56558a4ea876a5f0
|
||||
content/3: cec18f48b2cd7974eb556880e6604f7f
|
||||
content/4: b200402d6a01ab565fd56d113c530ef6
|
||||
content/4: c187ae3362455acfe43282399f0d163a
|
||||
content/5: 4c3a5708af82c1ee42a12d14fd34e950
|
||||
content/6: 64fbd5b16f4cff18ba976492a275c05e
|
||||
content/6: 12a43b499c1e8bb06b050964053ebde3
|
||||
content/7: a28151eeb5ba3518b33809055b04f0f6
|
||||
content/8: cffe5b901d78ebf2000d07dc7579533e
|
||||
content/9: 73486253d24eeff7ac44dfd0c8868d87
|
||||
@@ -49300,17 +49300,3 @@ checksums:
|
||||
content/42: dc2cfed837ea55adfa23bd7c87d5299d
|
||||
content/43: b3f310d5ef115bea5a8b75bf25d7ea9a
|
||||
content/44: df2ef65659b8ea0a13916358943f965b
|
||||
ebed3bd73520bf81399749586796f9d0:
|
||||
meta/title: 1763bebd6001500cdfc1b5127b0c1cde
|
||||
content/0: eb0ed7078f192304703144f4cac3442f
|
||||
content/1: ba5ba29787a0eb35c46dacb3544bafe1
|
||||
content/2: 5ed74bf0e91235f71eeceb25712ad2d3
|
||||
content/3: 0441638444240cd20a6c69ea1d3afbb1
|
||||
content/4: ef102e10f1402df7290680c1e9df8a5e
|
||||
content/5: 95afa83a30cb01724b932b19dd69f20b
|
||||
content/6: 8ebc5e005f61d253c006824168abaf22
|
||||
content/7: df81a49b54d378523fb74aa0b0fb8be1
|
||||
content/8: c5fb77d31bae86aa85f2b2b84ce0beab
|
||||
content/9: 7a3be8a3771ee428ecf09008e42c0e2e
|
||||
content/10: 42e4caf9b036a8d7726a8968f3ed201f
|
||||
content/11: e74f8ee79105babdaa8dfec520ecdf74
|
||||
|
||||
@@ -262,6 +262,8 @@ const SCOPE_DESCRIPTIONS: Record<string, string> = {
|
||||
'sharing.write': 'Share files and folders with others',
|
||||
// WordPress.com scopes
|
||||
global: 'Full access to manage your WordPress.com sites, posts, pages, media, and settings',
|
||||
// Zapier AI Actions scopes
|
||||
'nla:exposed_actions:execute': 'Execute Zapier AI Actions on your behalf',
|
||||
}
|
||||
|
||||
function getScopeDescription(scope: string): string {
|
||||
|
||||
808
apps/sim/blocks/blocks/zapier.ts
Normal file
808
apps/sim/blocks/blocks/zapier.ts
Normal file
@@ -0,0 +1,808 @@
|
||||
import { ZapierIcon } from '@/components/icons'
|
||||
import type { BlockConfig } from '@/blocks/types'
|
||||
import { AuthMode } from '@/blocks/types'
|
||||
import type { ZapierResponse } from '@/tools/zapier/types'
|
||||
|
||||
export const ZapierBlock: BlockConfig<ZapierResponse> = {
|
||||
type: 'zapier',
|
||||
name: 'Zapier',
|
||||
description: 'Execute actions across 7,000+ apps using Zapier AI Actions',
|
||||
authMode: AuthMode.OAuth,
|
||||
longDescription:
|
||||
'Connect to Zapier AI Actions to execute any of 30,000+ actions across 7,000+ apps. Send emails, create documents, update CRMs, post messages, and more - all through natural language instructions.',
|
||||
docsLink: 'https://docs.sim.ai/tools/zapier',
|
||||
category: 'tools',
|
||||
bgColor: '#FFFFFF',
|
||||
icon: ZapierIcon,
|
||||
subBlocks: [
|
||||
{
|
||||
id: 'operation',
|
||||
title: 'Operation',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'Execute Action', id: 'execute' },
|
||||
{ label: 'Stateless Execute', id: 'stateless_execute' },
|
||||
{ label: 'List Actions', id: 'list' },
|
||||
{ label: 'Search Apps', id: 'search_apps' },
|
||||
{ label: 'Search App Actions', id: 'search_app_actions' },
|
||||
{ label: 'Find Actions', id: 'guess' },
|
||||
{ label: 'Get Action Details', id: 'get_action_details' },
|
||||
{ label: 'Create Action', id: 'create' },
|
||||
{ label: 'Update Action', id: 'update' },
|
||||
{ label: 'Delete Action', id: 'delete' },
|
||||
],
|
||||
value: () => 'execute',
|
||||
},
|
||||
{
|
||||
id: 'credential',
|
||||
title: 'Zapier Account',
|
||||
type: 'oauth-input',
|
||||
serviceId: 'zapier',
|
||||
requiredScopes: ['openid', 'nla:exposed_actions:execute'],
|
||||
placeholder: 'Select Zapier account',
|
||||
required: true,
|
||||
},
|
||||
// Execute Action fields
|
||||
{
|
||||
id: 'actionId',
|
||||
title: 'Action ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter the AI Action ID to execute',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'execute',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'instructions',
|
||||
title: 'Instructions',
|
||||
type: 'long-input',
|
||||
placeholder:
|
||||
'Describe what you want to do in plain English (e.g., "Send a message to #general saying hello")',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'execute',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'params',
|
||||
title: 'Parameters',
|
||||
type: 'code',
|
||||
placeholder: '{\n "channel": {"mode": "locked", "value": "#general"}\n}',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'execute',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'previewOnly',
|
||||
title: 'Preview Mode',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'Execute', id: 'false' },
|
||||
{ label: 'Preview Only', id: 'true' },
|
||||
],
|
||||
value: () => 'false',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'execute',
|
||||
},
|
||||
},
|
||||
// Search Apps fields
|
||||
{
|
||||
id: 'searchQuery',
|
||||
title: 'Search Query',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter app name to search (e.g., "slack", "google")',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'search_apps',
|
||||
},
|
||||
},
|
||||
// Guess Actions fields
|
||||
{
|
||||
id: 'guessQuery',
|
||||
title: 'What do you want to do?',
|
||||
type: 'long-input',
|
||||
placeholder:
|
||||
'Describe in plain English (e.g., "send a Slack message", "create a Google Doc")',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'guess',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'actionTypes',
|
||||
title: 'Action Types',
|
||||
type: 'checkbox-list',
|
||||
options: [
|
||||
{ label: 'Write (Create/Send)', id: 'actionTypes_write' },
|
||||
{ label: 'Search (Find)', id: 'actionTypes_search' },
|
||||
{ label: 'Read (Get)', id: 'actionTypes_read' },
|
||||
],
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'guess',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'resultCount',
|
||||
title: 'Max Results',
|
||||
type: 'short-input',
|
||||
placeholder: '25',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'guess',
|
||||
},
|
||||
},
|
||||
// Create Action fields
|
||||
{
|
||||
id: 'app',
|
||||
title: 'App',
|
||||
type: 'short-input',
|
||||
placeholder: 'App identifier (e.g., "slack", "gmail")',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'create',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'action',
|
||||
title: 'Action',
|
||||
type: 'short-input',
|
||||
placeholder: 'Action identifier (e.g., "send_channel_message")',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'create',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'createActionType',
|
||||
title: 'Action Type',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'Write', id: 'write' },
|
||||
{ label: 'Search', id: 'search' },
|
||||
{ label: 'Read', id: 'read' },
|
||||
],
|
||||
value: () => 'write',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'create',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'createParams',
|
||||
title: 'Parameters',
|
||||
type: 'code',
|
||||
placeholder: '{\n "channel": "#general"\n}',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'create',
|
||||
},
|
||||
},
|
||||
// Stateless Execute fields
|
||||
{
|
||||
id: 'statelessApp',
|
||||
title: 'App',
|
||||
type: 'short-input',
|
||||
placeholder: 'App identifier (e.g., "SlackAPI", "GmailV2API")',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'stateless_execute',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'statelessAction',
|
||||
title: 'Action',
|
||||
type: 'short-input',
|
||||
placeholder: 'Action identifier (e.g., "send_channel_message")',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'stateless_execute',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'statelessInstructions',
|
||||
title: 'Instructions',
|
||||
type: 'long-input',
|
||||
placeholder: 'Describe what you want to do in plain English',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'stateless_execute',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'statelessActionType',
|
||||
title: 'Action Type',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'Write', id: 'write' },
|
||||
{ label: 'Search', id: 'search' },
|
||||
{ label: 'Read', id: 'read' },
|
||||
],
|
||||
value: () => 'write',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'stateless_execute',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'statelessParams',
|
||||
title: 'Parameters',
|
||||
type: 'code',
|
||||
placeholder: '{\n "channel": {"mode": "locked", "value": "#general"}\n}',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'stateless_execute',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'statelessPreviewOnly',
|
||||
title: 'Preview Mode',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'Execute', id: 'false' },
|
||||
{ label: 'Preview Only', id: 'true' },
|
||||
],
|
||||
value: () => 'false',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'stateless_execute',
|
||||
},
|
||||
},
|
||||
// Search App Actions fields
|
||||
{
|
||||
id: 'searchAppActionsApp',
|
||||
title: 'App',
|
||||
type: 'short-input',
|
||||
placeholder: 'App identifier (e.g., "SlackAPI", "GmailV2API")',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'search_app_actions',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'searchAppActionsQuery',
|
||||
title: 'Search Query',
|
||||
type: 'short-input',
|
||||
placeholder: 'Optional: filter actions by name',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'search_app_actions',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'searchAppActionsTypes',
|
||||
title: 'Action Types',
|
||||
type: 'checkbox-list',
|
||||
options: [
|
||||
{ label: 'Write (Create/Send)', id: 'searchAppActionsTypes_write' },
|
||||
{ label: 'Search (Find)', id: 'searchAppActionsTypes_search' },
|
||||
{ label: 'Read (Get)', id: 'searchAppActionsTypes_read' },
|
||||
],
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'search_app_actions',
|
||||
},
|
||||
},
|
||||
// Get Action Details fields
|
||||
{
|
||||
id: 'detailsApp',
|
||||
title: 'App',
|
||||
type: 'short-input',
|
||||
placeholder: 'App identifier (e.g., "SlackAPI", "GmailV2API")',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'get_action_details',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'detailsAction',
|
||||
title: 'Action',
|
||||
type: 'short-input',
|
||||
placeholder: 'Action identifier (e.g., "send_channel_message")',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'get_action_details',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'detailsActionType',
|
||||
title: 'Action Type',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'Write', id: 'write' },
|
||||
{ label: 'Search', id: 'search' },
|
||||
{ label: 'Read', id: 'read' },
|
||||
],
|
||||
value: () => 'write',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'get_action_details',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'includeNeeds',
|
||||
title: 'Include Inputs (Needs)',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'Yes', id: 'true' },
|
||||
{ label: 'No', id: 'false' },
|
||||
],
|
||||
value: () => 'true',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'get_action_details',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'includeGives',
|
||||
title: 'Include Outputs (Gives)',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'Yes', id: 'true' },
|
||||
{ label: 'No', id: 'false' },
|
||||
],
|
||||
value: () => 'false',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'get_action_details',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'includeSample',
|
||||
title: 'Include Sample',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'Yes', id: 'true' },
|
||||
{ label: 'No', id: 'false' },
|
||||
],
|
||||
value: () => 'false',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'get_action_details',
|
||||
},
|
||||
},
|
||||
// Update Action fields
|
||||
{
|
||||
id: 'updateActionId',
|
||||
title: 'Action ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'The ID of the AI Action to update',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'update',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'updateApp',
|
||||
title: 'App',
|
||||
type: 'short-input',
|
||||
placeholder: 'App identifier (e.g., "SlackAPI")',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'update',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'updateAction',
|
||||
title: 'Action',
|
||||
type: 'short-input',
|
||||
placeholder: 'Action identifier (e.g., "send_channel_message")',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'update',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'updateActionType',
|
||||
title: 'Action Type',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'Write', id: 'write' },
|
||||
{ label: 'Search', id: 'search' },
|
||||
{ label: 'Read', id: 'read' },
|
||||
],
|
||||
value: () => 'write',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'update',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'updateParams',
|
||||
title: 'Parameters',
|
||||
type: 'code',
|
||||
placeholder: '{\n "channel": "#general"\n}',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'update',
|
||||
},
|
||||
},
|
||||
// Delete Action fields
|
||||
{
|
||||
id: 'deleteActionId',
|
||||
title: 'Action ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'The ID of the AI Action to delete',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'delete',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
tools: {
|
||||
access: [
|
||||
'zapier_execute_action',
|
||||
'zapier_list_actions',
|
||||
'zapier_search_apps',
|
||||
'zapier_guess_actions',
|
||||
'zapier_create_action',
|
||||
'zapier_stateless_execute',
|
||||
'zapier_search_app_actions',
|
||||
'zapier_get_action_details',
|
||||
'zapier_update_action',
|
||||
'zapier_delete_action',
|
||||
],
|
||||
config: {
|
||||
tool: (params) => {
|
||||
switch (params.operation) {
|
||||
case 'execute':
|
||||
return 'zapier_execute_action'
|
||||
case 'stateless_execute':
|
||||
return 'zapier_stateless_execute'
|
||||
case 'list':
|
||||
return 'zapier_list_actions'
|
||||
case 'search_apps':
|
||||
return 'zapier_search_apps'
|
||||
case 'search_app_actions':
|
||||
return 'zapier_search_app_actions'
|
||||
case 'guess':
|
||||
return 'zapier_guess_actions'
|
||||
case 'get_action_details':
|
||||
return 'zapier_get_action_details'
|
||||
case 'create':
|
||||
return 'zapier_create_action'
|
||||
case 'update':
|
||||
return 'zapier_update_action'
|
||||
case 'delete':
|
||||
return 'zapier_delete_action'
|
||||
default:
|
||||
throw new Error(`Invalid Zapier operation: ${params.operation}`)
|
||||
}
|
||||
},
|
||||
params: (params) => {
|
||||
const {
|
||||
operation,
|
||||
credential,
|
||||
actionId,
|
||||
instructions,
|
||||
params: execParams,
|
||||
previewOnly,
|
||||
searchQuery,
|
||||
guessQuery,
|
||||
resultCount,
|
||||
app,
|
||||
action,
|
||||
createActionType,
|
||||
createParams,
|
||||
statelessApp,
|
||||
statelessAction,
|
||||
statelessInstructions,
|
||||
statelessActionType,
|
||||
statelessParams,
|
||||
statelessPreviewOnly,
|
||||
searchAppActionsApp,
|
||||
searchAppActionsQuery,
|
||||
detailsApp,
|
||||
detailsAction,
|
||||
detailsActionType,
|
||||
includeNeeds,
|
||||
includeGives,
|
||||
includeSample,
|
||||
updateActionId,
|
||||
updateApp,
|
||||
updateAction,
|
||||
updateActionType,
|
||||
updateParams,
|
||||
deleteActionId,
|
||||
} = params
|
||||
|
||||
const baseParams: Record<string, any> = { credential }
|
||||
|
||||
// Helper to parse JSON params
|
||||
const parseJsonParams = (jsonParams: any) => {
|
||||
if (!jsonParams) return undefined
|
||||
try {
|
||||
return typeof jsonParams === 'string' ? JSON.parse(jsonParams) : jsonParams
|
||||
} catch {
|
||||
throw new Error('Invalid JSON in parameters field')
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to collect checkbox-list values
|
||||
// Use truthy check since values may be boolean true or string "true" after serialization
|
||||
const collectActionTypes = (prefix: string) => {
|
||||
const types: string[] = []
|
||||
const writeVal = params[`${prefix}_write`]
|
||||
const searchVal = params[`${prefix}_search`]
|
||||
const readVal = params[`${prefix}_read`]
|
||||
if (writeVal === true || writeVal === 'true') types.push('write')
|
||||
if (searchVal === true || searchVal === 'true') types.push('search')
|
||||
if (readVal === true || readVal === 'true') types.push('read')
|
||||
return types.length > 0 ? types : undefined
|
||||
}
|
||||
|
||||
switch (operation) {
|
||||
case 'execute':
|
||||
baseParams.actionId = actionId
|
||||
baseParams.instructions = instructions
|
||||
baseParams.params = parseJsonParams(execParams)
|
||||
baseParams.previewOnly = previewOnly === 'true'
|
||||
break
|
||||
|
||||
case 'stateless_execute':
|
||||
baseParams.app = statelessApp
|
||||
baseParams.action = statelessAction
|
||||
baseParams.instructions = statelessInstructions
|
||||
baseParams.actionType = statelessActionType || 'write'
|
||||
baseParams.params = parseJsonParams(statelessParams)
|
||||
baseParams.previewOnly = statelessPreviewOnly === 'true'
|
||||
break
|
||||
|
||||
case 'list':
|
||||
break
|
||||
|
||||
case 'search_apps':
|
||||
if (searchQuery) baseParams.query = searchQuery
|
||||
break
|
||||
|
||||
case 'search_app_actions':
|
||||
baseParams.app = searchAppActionsApp
|
||||
if (searchAppActionsQuery) baseParams.query = searchAppActionsQuery
|
||||
baseParams.actionTypes = collectActionTypes('searchAppActionsTypes')
|
||||
break
|
||||
|
||||
case 'guess': {
|
||||
baseParams.query = guessQuery
|
||||
// Checkbox-list values are stored under prefixed option IDs (actionTypes_write, etc.)
|
||||
baseParams.actionTypes = collectActionTypes('actionTypes')
|
||||
if (resultCount) {
|
||||
const count = Number.parseInt(resultCount, 10)
|
||||
if (!Number.isNaN(count)) baseParams.count = count
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case 'get_action_details':
|
||||
baseParams.app = detailsApp
|
||||
baseParams.action = detailsAction
|
||||
baseParams.actionType = detailsActionType || 'write'
|
||||
baseParams.includeNeeds = includeNeeds !== 'false'
|
||||
baseParams.includeGives = includeGives === 'true'
|
||||
baseParams.includeSample = includeSample === 'true'
|
||||
break
|
||||
|
||||
case 'create':
|
||||
baseParams.app = app
|
||||
baseParams.action = action
|
||||
baseParams.actionType = createActionType || 'write'
|
||||
baseParams.params = parseJsonParams(createParams)
|
||||
break
|
||||
|
||||
case 'update':
|
||||
baseParams.actionId = updateActionId
|
||||
baseParams.app = updateApp
|
||||
baseParams.action = updateAction
|
||||
baseParams.actionType = updateActionType || 'write'
|
||||
baseParams.params = parseJsonParams(updateParams)
|
||||
break
|
||||
|
||||
case 'delete':
|
||||
baseParams.actionId = deleteActionId
|
||||
break
|
||||
}
|
||||
|
||||
return baseParams
|
||||
},
|
||||
},
|
||||
},
|
||||
inputs: {
|
||||
operation: { type: 'string', description: 'Operation to perform' },
|
||||
credential: { type: 'string', description: 'Zapier OAuth credential' },
|
||||
// Execute inputs
|
||||
actionId: { type: 'string', description: 'AI Action ID to execute' },
|
||||
instructions: { type: 'string', description: 'Plain English instructions for the action' },
|
||||
params: { type: 'json', description: 'Optional parameter constraints' },
|
||||
previewOnly: { type: 'string', description: 'Whether to preview without executing' },
|
||||
// Stateless execute inputs
|
||||
statelessApp: { type: 'string', description: 'App identifier for stateless execute' },
|
||||
statelessAction: { type: 'string', description: 'Action identifier for stateless execute' },
|
||||
statelessInstructions: { type: 'string', description: 'Instructions for stateless execute' },
|
||||
statelessActionType: { type: 'string', description: 'Action type for stateless execute' },
|
||||
statelessParams: { type: 'json', description: 'Parameters for stateless execute' },
|
||||
statelessPreviewOnly: { type: 'string', description: 'Preview mode for stateless execute' },
|
||||
// Search inputs
|
||||
searchQuery: { type: 'string', description: 'App search query' },
|
||||
// Search app actions inputs
|
||||
searchAppActionsApp: { type: 'string', description: 'App to search actions for' },
|
||||
searchAppActionsQuery: { type: 'string', description: 'Query to filter actions' },
|
||||
searchAppActionsTypes_write: { type: 'boolean', description: 'Include write actions' },
|
||||
searchAppActionsTypes_search: { type: 'boolean', description: 'Include search actions' },
|
||||
searchAppActionsTypes_read: { type: 'boolean', description: 'Include read actions' },
|
||||
// Guess inputs
|
||||
guessQuery: { type: 'string', description: 'Natural language query to find actions' },
|
||||
actionTypes_write: { type: 'boolean', description: 'Include write actions' },
|
||||
actionTypes_search: { type: 'boolean', description: 'Include search actions' },
|
||||
actionTypes_read: { type: 'boolean', description: 'Include read actions' },
|
||||
resultCount: { type: 'string', description: 'Maximum number of results' },
|
||||
// Get action details inputs
|
||||
detailsApp: { type: 'string', description: 'App identifier for action details' },
|
||||
detailsAction: { type: 'string', description: 'Action identifier for action details' },
|
||||
detailsActionType: { type: 'string', description: 'Action type for action details' },
|
||||
includeNeeds: { type: 'string', description: 'Include input requirements' },
|
||||
includeGives: { type: 'string', description: 'Include output specifications' },
|
||||
includeSample: { type: 'string', description: 'Include sample data' },
|
||||
// Create inputs
|
||||
app: { type: 'string', description: 'App identifier' },
|
||||
action: { type: 'string', description: 'Action identifier' },
|
||||
createActionType: { type: 'string', description: 'Type of action to create' },
|
||||
createParams: { type: 'json', description: 'Pre-configured parameters' },
|
||||
// Update inputs
|
||||
updateActionId: { type: 'string', description: 'AI Action ID to update' },
|
||||
updateApp: { type: 'string', description: 'App identifier for update' },
|
||||
updateAction: { type: 'string', description: 'Action identifier for update' },
|
||||
updateActionType: { type: 'string', description: 'Action type for update' },
|
||||
updateParams: { type: 'json', description: 'Parameters for update' },
|
||||
// Delete inputs
|
||||
deleteActionId: { type: 'string', description: 'AI Action ID to delete' },
|
||||
},
|
||||
outputs: {
|
||||
// Execute Action outputs
|
||||
executionLogId: {
|
||||
type: 'string',
|
||||
description: 'Unique identifier for the execution',
|
||||
},
|
||||
actionUsed: {
|
||||
type: 'string',
|
||||
description: 'Name of the action that was executed',
|
||||
},
|
||||
inputParams: {
|
||||
type: 'json',
|
||||
description: 'Parameters passed to the API',
|
||||
},
|
||||
resolvedParams: {
|
||||
type: 'json',
|
||||
description: 'Parameters resolved by AI for execution',
|
||||
},
|
||||
results: {
|
||||
type: 'json',
|
||||
description: 'Results from action execution',
|
||||
},
|
||||
resultFieldLabels: {
|
||||
type: 'json',
|
||||
description: 'Human-readable labels for result fields',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
description: 'Execution status (success, error, preview, etc.)',
|
||||
},
|
||||
error: {
|
||||
type: 'string',
|
||||
description: 'Error message if execution failed',
|
||||
},
|
||||
// List Actions outputs
|
||||
actions: {
|
||||
type: 'json',
|
||||
description:
|
||||
'Array of AI Actions with id, description, actionType, app, appLabel, action, actionLabel, params, accountId, authenticationId, configurationLink (list) or guessed actions (find)',
|
||||
},
|
||||
configurationLink: {
|
||||
type: 'string',
|
||||
description: 'Link to configure actions in Zapier (list operation only)',
|
||||
},
|
||||
// Search Apps outputs
|
||||
apps: {
|
||||
type: 'json',
|
||||
description:
|
||||
'Array of apps with app, name, logoUrl, authType, actionCount, writeActionCount, searchActionCount, readActionCount',
|
||||
},
|
||||
// Guess Actions outputs (in addition to 'actions' above)
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Combined app and action name (find operation)',
|
||||
},
|
||||
image: {
|
||||
type: 'string',
|
||||
description: 'App logo URL (find operation)',
|
||||
},
|
||||
score: {
|
||||
type: 'number',
|
||||
description: 'Relevance score for guessed actions (find operation)',
|
||||
},
|
||||
// Create Action outputs
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'ID of the created AI Action',
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
description: 'Description of the action',
|
||||
},
|
||||
actionType: {
|
||||
type: 'string',
|
||||
description:
|
||||
'Type of action (write, search, read, read_bulk, search_or_write, search_and_write)',
|
||||
},
|
||||
app: {
|
||||
type: 'string',
|
||||
description: 'App identifier',
|
||||
},
|
||||
appLabel: {
|
||||
type: 'string',
|
||||
description: 'Human-readable app label',
|
||||
},
|
||||
action: {
|
||||
type: 'string',
|
||||
description: 'Action identifier',
|
||||
},
|
||||
actionLabel: {
|
||||
type: 'string',
|
||||
description: 'Human-readable action label',
|
||||
},
|
||||
params: {
|
||||
type: 'json',
|
||||
description: 'Configured parameter values',
|
||||
},
|
||||
accountId: {
|
||||
type: 'number',
|
||||
description: 'Zapier account ID',
|
||||
},
|
||||
authenticationId: {
|
||||
type: 'number',
|
||||
description: 'Authentication ID used for the app',
|
||||
},
|
||||
// Get Action Details outputs
|
||||
needs: {
|
||||
type: 'json',
|
||||
description: 'Array of input requirements for the action',
|
||||
},
|
||||
gives: {
|
||||
type: 'json',
|
||||
description: 'Array of output fields from the action',
|
||||
},
|
||||
sample: {
|
||||
type: 'json',
|
||||
description: 'Sample execution result',
|
||||
},
|
||||
customNeedsProbability: {
|
||||
type: 'number',
|
||||
description: 'Probability that action has custom/dynamic input fields',
|
||||
},
|
||||
// Delete Action outputs
|
||||
deleted: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the action was successfully deleted',
|
||||
},
|
||||
message: {
|
||||
type: 'string',
|
||||
description: 'Status message for delete operation',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -133,6 +133,7 @@ import { WorkflowBlock } from '@/blocks/blocks/workflow'
|
||||
import { WorkflowInputBlock } from '@/blocks/blocks/workflow_input'
|
||||
import { XBlock } from '@/blocks/blocks/x'
|
||||
import { YouTubeBlock } from '@/blocks/blocks/youtube'
|
||||
import { ZapierBlock } from '@/blocks/blocks/zapier'
|
||||
import { ZendeskBlock } from '@/blocks/blocks/zendesk'
|
||||
import { ZepBlock } from '@/blocks/blocks/zep'
|
||||
import { ZoomBlock } from '@/blocks/blocks/zoom'
|
||||
@@ -275,8 +276,9 @@ export const registry: Record<string, BlockConfig> = {
|
||||
workflow_input: WorkflowInputBlock,
|
||||
x: XBlock,
|
||||
youtube: YouTubeBlock,
|
||||
zep: ZepBlock,
|
||||
zapier: ZapierBlock,
|
||||
zendesk: ZendeskBlock,
|
||||
zep: ZepBlock,
|
||||
zoom: ZoomBlock,
|
||||
}
|
||||
|
||||
|
||||
@@ -4151,7 +4151,7 @@ export function DuckDuckGoIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg {...props} xmlns='http://www.w3.org/2000/svg' viewBox='-108 -108 216 216'>
|
||||
<circle r='108' fill='#d53' />
|
||||
<circle r='96' fill='none' stroke='#ffffff' stroke-width='7' />
|
||||
<circle r='96' fill='none' stroke='#ffffff' strokeWidth='7' />
|
||||
<path
|
||||
d='M-32-55C-62-48-51-6-51-6l19 93 7 3M-39-73h-8l11 4s-11 0-11 7c24-1 35 5 35 5'
|
||||
fill='#ddd'
|
||||
@@ -4199,3 +4199,25 @@ export function RssIcon(props: SVGProps<SVGSVGElement>) {
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export function ZapierIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
{...props}
|
||||
width='800px'
|
||||
height='800px'
|
||||
viewBox='0 0 256 256'
|
||||
version='1.1'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
xmlnsXlink='http://www.w3.org/1999/xlink'
|
||||
>
|
||||
<g>
|
||||
<path
|
||||
d='M128.080089,-0.000183105 C135.311053,0.0131003068 142.422517,0.624138494 149.335663,1.77979593 L149.335663,1.77979593 L149.335663,76.2997796 L202.166953,23.6044907 C208.002065,27.7488446 213.460883,32.3582023 218.507811,37.3926715 C223.557281,42.4271407 228.192318,47.8867213 232.346817,53.7047992 L232.346817,53.7047992 L179.512985,106.400063 L254.227854,106.400063 C255.387249,113.29414 256,120.36111 256,127.587243 L256,127.587243 L256,127.759881 C256,134.986013 255.387249,142.066204 254.227854,148.960282 L254.227854,148.960282 L179.500273,148.960282 L232.346817,201.642324 C228.192318,207.460402 223.557281,212.919983 218.523066,217.954452 L218.523066,217.954452 L218.507811,217.954452 C213.460883,222.988921 208.002065,227.6115 202.182208,231.742607 L202.182208,231.742607 L149.335663,179.04709 L149.335663,253.5672 C142.435229,254.723036 135.323765,255.333244 128.092802,255.348499 L128.092802,255.348499 L127.907197,255.348499 C120.673691,255.333244 113.590195,254.723036 106.677048,253.5672 L106.677048,253.5672 L106.677048,179.04709 L53.8457596,231.742607 C42.1780766,223.466917 31.977435,213.278734 23.6658953,201.642324 L23.6658953,201.642324 L76.4997269,148.960282 L1.78485803,148.960282 C0.612750404,142.052729 0,134.946095 0,127.719963 L0,127.719963 L0,127.349037 C0.0121454869,125.473817 0.134939797,123.182933 0.311311815,120.812834 L0.36577283,120.099764 C0.887996182,113.428547 1.78485803,106.400063 1.78485803,106.400063 L1.78485803,106.400063 L76.4997269,106.400063 L23.6658953,53.7047992 C27.8076812,47.8867213 32.4300059,42.4403618 37.4769335,37.4193681 L37.4769335,37.4193681 L37.5023588,37.3926715 C42.5391163,32.3582023 48.0106469,27.7488446 53.8457596,23.6044907 L53.8457596,23.6044907 L106.677048,76.2997796 L106.677048,1.77979593 C113.590195,0.624138494 120.688946,0.0131003068 127.932622,-0.000183105 L127.932622,-0.000183105 L128.080089,-0.000183105 Z M128.067377,95.7600714 L127.945335,95.7600714 C118.436262,95.7600714 109.32891,97.5001809 100.910584,100.661566 C97.7553011,109.043534 96.0085811,118.129275 95.9958684,127.613685 L95.9958684,127.733184 C96.0085811,137.217594 97.7553011,146.303589 100.923296,154.685303 C109.32891,157.846943 118.436262,159.587052 127.945335,159.587052 L128.067377,159.587052 C137.576449,159.587052 146.683802,157.846943 155.089415,154.685303 C158.257411,146.290368 160.004131,137.217594 160.004131,127.733184 L160.004131,127.613685 C160.004131,118.129275 158.257411,109.043534 155.089415,100.661566 C146.683802,97.5001809 137.576449,95.7600714 128.067377,95.7600714 Z'
|
||||
fill='#FF4A00'
|
||||
fillRule='nonzero'
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1847,6 +1847,59 @@ export const auth = betterAuth({
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
// Zapier AI Actions provider
|
||||
{
|
||||
providerId: 'zapier',
|
||||
clientId: env.ZAPIER_CLIENT_ID as string,
|
||||
clientSecret: env.ZAPIER_CLIENT_SECRET as string,
|
||||
authorizationUrl: 'https://actions.zapier.com/oauth/authorize/',
|
||||
tokenUrl: 'https://actions.zapier.com/oauth/token/',
|
||||
userInfoUrl: 'https://actions.zapier.com/api/v2/check/',
|
||||
scopes: ['openid', 'nla:exposed_actions:execute'],
|
||||
responseType: 'code',
|
||||
pkce: true,
|
||||
accessType: 'offline',
|
||||
prompt: 'consent',
|
||||
redirectURI: `${getBaseUrl()}/api/auth/oauth2/callback/zapier`,
|
||||
getUserInfo: async (tokens) => {
|
||||
try {
|
||||
logger.info('Fetching Zapier user profile')
|
||||
|
||||
// Zapier's check endpoint returns account info when using OAuth
|
||||
const response = await fetch('https://actions.zapier.com/api/v2/check/', {
|
||||
headers: {
|
||||
Authorization: `Bearer ${tokens.accessToken}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
logger.error('Failed to fetch Zapier user info', {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
})
|
||||
throw new Error('Failed to fetch user info')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
// Zapier check endpoint returns account_id and other info
|
||||
const userId = data.account_id || data.user_id || `zapier-${Date.now()}`
|
||||
|
||||
return {
|
||||
id: userId.toString(),
|
||||
name: data.email || 'Zapier User',
|
||||
email: data.email || `${userId}@zapier.user`,
|
||||
emailVerified: !!data.email,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error in Zapier getUserInfo:', { error })
|
||||
return null
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
// Include SSO plugin when enabled
|
||||
|
||||
@@ -230,6 +230,8 @@ export const env = createEnv({
|
||||
ZOOM_CLIENT_SECRET: z.string().optional(), // Zoom OAuth client secret
|
||||
WORDPRESS_CLIENT_ID: z.string().optional(), // WordPress.com OAuth client ID
|
||||
WORDPRESS_CLIENT_SECRET: z.string().optional(), // WordPress.com OAuth client secret
|
||||
ZAPIER_CLIENT_ID: z.string().optional(), // Zapier AI Actions OAuth client ID
|
||||
ZAPIER_CLIENT_SECRET: z.string().optional(), // Zapier AI Actions OAuth client secret
|
||||
|
||||
// E2B Remote Code Execution
|
||||
E2B_ENABLED: z.string().optional(), // Enable E2B remote code execution
|
||||
|
||||
@@ -37,6 +37,7 @@ import {
|
||||
WebflowIcon,
|
||||
WordpressIcon,
|
||||
xIcon,
|
||||
ZapierIcon,
|
||||
ZoomIcon,
|
||||
} from '@/components/icons'
|
||||
import { env } from '@/lib/core/config/env'
|
||||
@@ -70,6 +71,7 @@ export type OAuthProvider =
|
||||
| 'shopify'
|
||||
| 'zoom'
|
||||
| 'wordpress'
|
||||
| 'zapier'
|
||||
| string
|
||||
|
||||
export type OAuthService =
|
||||
@@ -111,6 +113,7 @@ export type OAuthService =
|
||||
| 'shopify'
|
||||
| 'zoom'
|
||||
| 'wordpress'
|
||||
| 'zapier'
|
||||
export interface OAuthProviderConfig {
|
||||
id: OAuthProvider
|
||||
name: string
|
||||
@@ -891,6 +894,23 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
|
||||
},
|
||||
defaultService: 'wordpress',
|
||||
},
|
||||
zapier: {
|
||||
id: 'zapier',
|
||||
name: 'Zapier',
|
||||
icon: (props) => ZapierIcon(props),
|
||||
services: {
|
||||
zapier: {
|
||||
id: 'zapier',
|
||||
name: 'Zapier AI Actions',
|
||||
description: 'Execute actions across 7,000+ apps using Zapier AI Actions.',
|
||||
providerId: 'zapier',
|
||||
icon: (props) => ZapierIcon(props),
|
||||
baseProviderIcon: (props) => ZapierIcon(props),
|
||||
scopes: ['openid', 'nla:exposed_actions:execute'],
|
||||
},
|
||||
},
|
||||
defaultService: 'zapier',
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1470,6 +1490,20 @@ function getProviderAuthConfig(provider: string): ProviderAuthConfig {
|
||||
supportsRefreshTokenRotation: false,
|
||||
}
|
||||
}
|
||||
case 'zapier': {
|
||||
// Zapier AI Actions OAuth - tokens expire after 10 hours
|
||||
const { clientId, clientSecret } = getCredentials(
|
||||
env.ZAPIER_CLIENT_ID,
|
||||
env.ZAPIER_CLIENT_SECRET
|
||||
)
|
||||
return {
|
||||
tokenEndpoint: 'https://actions.zapier.com/oauth/token/',
|
||||
clientId,
|
||||
clientSecret,
|
||||
useBasicAuth: false,
|
||||
supportsRefreshTokenRotation: true,
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw new Error(`Unsupported provider: ${provider}`)
|
||||
}
|
||||
|
||||
@@ -115,10 +115,6 @@ export class Serializer {
|
||||
safeParallels
|
||||
)
|
||||
|
||||
if (validateRequired) {
|
||||
this.validateSubflowsBeforeExecution(blocks, safeLoops, safeParallels)
|
||||
}
|
||||
|
||||
return {
|
||||
version: '1.0',
|
||||
blocks: Object.values(blocks).map((block) =>
|
||||
@@ -139,18 +135,6 @@ export class Serializer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate loop and parallel subflows for required inputs when running in "each/collection" modes
|
||||
*/
|
||||
private validateSubflowsBeforeExecution(
|
||||
blocks: Record<string, BlockState>,
|
||||
loops: Record<string, Loop>,
|
||||
parallels: Record<string, Parallel>
|
||||
): void {
|
||||
// Note: Empty collections in forEach loops and parallel collection mode are handled gracefully
|
||||
// at runtime - the loop/parallel will simply be skipped. No build-time validation needed.
|
||||
}
|
||||
|
||||
private serializeBlock(
|
||||
block: BlockState,
|
||||
options: {
|
||||
@@ -367,6 +351,15 @@ export class Serializer {
|
||||
) {
|
||||
params[id] = subBlock.value
|
||||
}
|
||||
|
||||
if (subBlockConfig?.type === 'checkbox-list' && Array.isArray(subBlockConfig.options)) {
|
||||
subBlockConfig.options.forEach((option: { id: string; label: string }) => {
|
||||
const optionSubBlock = block.subBlocks[option.id]
|
||||
if (optionSubBlock !== undefined) {
|
||||
params[option.id] = optionSubBlock.value
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Then check for any subBlocks with default values
|
||||
|
||||
@@ -1260,6 +1260,18 @@ import {
|
||||
youtubeSearchTool,
|
||||
youtubeVideoDetailsTool,
|
||||
} from '@/tools/youtube'
|
||||
import {
|
||||
zapierCreateAiActionTool,
|
||||
zapierDeleteAiActionTool,
|
||||
zapierExecuteActionTool,
|
||||
zapierGetActionDetailsTool,
|
||||
zapierGuessActionsTool,
|
||||
zapierListActionsTool,
|
||||
zapierSearchAppActionsTool,
|
||||
zapierSearchAppsTool,
|
||||
zapierStatelessExecuteTool,
|
||||
zapierUpdateAiActionTool,
|
||||
} from '@/tools/zapier'
|
||||
import {
|
||||
zendeskAutocompleteOrganizationsTool,
|
||||
zendeskCreateOrganizationsBulkTool,
|
||||
@@ -2501,4 +2513,16 @@ export const tools: Record<string, ToolConfig> = {
|
||||
zoom_get_meeting_recordings: zoomGetMeetingRecordingsTool,
|
||||
zoom_delete_recording: zoomDeleteRecordingTool,
|
||||
zoom_list_past_participants: zoomListPastParticipantsTool,
|
||||
|
||||
// Zapier tools
|
||||
zapier_execute_action: zapierExecuteActionTool,
|
||||
zapier_list_actions: zapierListActionsTool,
|
||||
zapier_search_apps: zapierSearchAppsTool,
|
||||
zapier_guess_actions: zapierGuessActionsTool,
|
||||
zapier_create_action: zapierCreateAiActionTool,
|
||||
zapier_stateless_execute: zapierStatelessExecuteTool,
|
||||
zapier_search_app_actions: zapierSearchAppActionsTool,
|
||||
zapier_get_action_details: zapierGetActionDetailsTool,
|
||||
zapier_update_action: zapierUpdateAiActionTool,
|
||||
zapier_delete_action: zapierDeleteAiActionTool,
|
||||
}
|
||||
|
||||
172
apps/sim/tools/zapier/create_action.ts
Normal file
172
apps/sim/tools/zapier/create_action.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ZapierCreateAiActionParams, ZapierCreateAiActionResponse } from '@/tools/zapier/types'
|
||||
|
||||
export const zapierCreateAiActionTool: ToolConfig<
|
||||
ZapierCreateAiActionParams,
|
||||
ZapierCreateAiActionResponse
|
||||
> = {
|
||||
id: 'zapier_create_action',
|
||||
name: 'Zapier Create AI Action',
|
||||
description:
|
||||
'Create a new stored AI Action in Zapier. The action can then be executed with zapier_execute_action.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
app: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'The app identifier (e.g., "slack", "gmail", "google-docs")',
|
||||
},
|
||||
action: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'The action identifier (e.g., "send_channel_message", "send_email")',
|
||||
},
|
||||
actionType: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Type of action: write, search, or read. Defaults to write.',
|
||||
default: 'write',
|
||||
},
|
||||
params: {
|
||||
type: 'json',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Pre-configured parameter values for the action',
|
||||
},
|
||||
accountId: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Zapier account ID',
|
||||
},
|
||||
authenticationId: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Authentication ID for the app connection',
|
||||
},
|
||||
meta: {
|
||||
type: 'json',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description:
|
||||
'Metadata object with params labels, app_label, action_label, authentication_label, app_needs_auth',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const queryParams = new URLSearchParams()
|
||||
if (params.accountId !== undefined) {
|
||||
queryParams.append('account_id', String(params.accountId))
|
||||
}
|
||||
if (params.authenticationId !== undefined) {
|
||||
queryParams.append('authentication_id', String(params.authenticationId))
|
||||
}
|
||||
const query = queryParams.toString()
|
||||
return `https://actions.zapier.com/api/v2/ai-actions/${query ? `?${query}` : ''}`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => ({
|
||||
app: params.app,
|
||||
action: params.action,
|
||||
action_type: params.actionType || 'write',
|
||||
params: params.params || {},
|
||||
meta: params.meta || { params: {} },
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || data.detail || `Zapier API error: ${response.status}`)
|
||||
}
|
||||
|
||||
// API response includes: id, description, account_id, authentication_id, app, action, action_type, params, meta, needs
|
||||
// Labels come from meta object if available
|
||||
const appLabel = data.meta?.app_label || ''
|
||||
const actionLabel = data.meta?.action_label || ''
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id || '',
|
||||
description: data.description || '',
|
||||
actionType: data.action_type || '',
|
||||
app: data.app || '',
|
||||
appLabel,
|
||||
action: data.action || '',
|
||||
actionLabel,
|
||||
params: data.params || {},
|
||||
accountId: data.account_id ?? null,
|
||||
authenticationId: data.authentication_id ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'The ID of the created AI Action (use this with execute_action)',
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
description: 'Description of the action',
|
||||
},
|
||||
actionType: {
|
||||
type: 'string',
|
||||
description:
|
||||
'Type of action (write, search, read, read_bulk, search_or_write, search_and_write)',
|
||||
},
|
||||
app: {
|
||||
type: 'string',
|
||||
description: 'App identifier',
|
||||
},
|
||||
appLabel: {
|
||||
type: 'string',
|
||||
description: 'Human-readable app label from meta',
|
||||
},
|
||||
action: {
|
||||
type: 'string',
|
||||
description: 'Action identifier',
|
||||
},
|
||||
actionLabel: {
|
||||
type: 'string',
|
||||
description: 'Human-readable action label from meta',
|
||||
},
|
||||
params: {
|
||||
type: 'json',
|
||||
description: 'Configured parameter values',
|
||||
},
|
||||
accountId: {
|
||||
type: 'number',
|
||||
description: 'Zapier account ID',
|
||||
optional: true,
|
||||
},
|
||||
authenticationId: {
|
||||
type: 'number',
|
||||
description: 'Authentication ID used for the app',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
73
apps/sim/tools/zapier/delete_action.ts
Normal file
73
apps/sim/tools/zapier/delete_action.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ZapierDeleteAiActionParams, ZapierDeleteAiActionResponse } from '@/tools/zapier/types'
|
||||
|
||||
export const zapierDeleteAiActionTool: ToolConfig<
|
||||
ZapierDeleteAiActionParams,
|
||||
ZapierDeleteAiActionResponse
|
||||
> = {
|
||||
id: 'zapier_delete_action',
|
||||
name: 'Zapier Delete AI Action',
|
||||
description: 'Delete a stored AI Action from Zapier.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
actionId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'The ID of the AI Action to delete',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`https://actions.zapier.com/api/v2/ai-actions/${encodeURIComponent(params.actionId)}/`,
|
||||
method: 'DELETE',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
// DELETE returns a boolean directly
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || data.detail || `Zapier API error: ${response.status}`)
|
||||
}
|
||||
|
||||
// API returns true if deleted, false if not found
|
||||
const deleted = data === true
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
deleted,
|
||||
message: deleted ? 'AI Action deleted successfully' : 'AI Action not found',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
deleted: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the action was successfully deleted',
|
||||
},
|
||||
message: {
|
||||
type: 'string',
|
||||
description: 'Status message',
|
||||
},
|
||||
},
|
||||
}
|
||||
136
apps/sim/tools/zapier/execute_action.ts
Normal file
136
apps/sim/tools/zapier/execute_action.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ZapierExecuteActionParams, ZapierExecuteActionResponse } from '@/tools/zapier/types'
|
||||
|
||||
export const zapierExecuteActionTool: ToolConfig<
|
||||
ZapierExecuteActionParams,
|
||||
ZapierExecuteActionResponse
|
||||
> = {
|
||||
id: 'zapier_execute_action',
|
||||
name: 'Zapier Execute Action',
|
||||
description:
|
||||
'Execute a stored AI Action in Zapier. Runs any of the 30,000+ actions across 7,000+ apps that Zapier supports.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
actionId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'The ID of the AI Action to execute',
|
||||
},
|
||||
instructions: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Plain English instructions for what the action should do (e.g., "Send a message about the weekly report to #general")',
|
||||
},
|
||||
params: {
|
||||
type: 'json',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Optional parameter constraints. Each key maps to {mode: "locked"|"guess"|"choose_from"|"ignored", value: string}',
|
||||
},
|
||||
previewOnly: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'If true, preview the execution without actually running it',
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`https://actions.zapier.com/api/v2/ai-actions/${encodeURIComponent(params.actionId)}/execute/${params.previewOnly ? '?preview_only=true' : ''}`,
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {
|
||||
instructions: params.instructions,
|
||||
}
|
||||
if (params.params !== undefined) {
|
||||
body.params = params.params
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || data.detail || `Zapier API error: ${response.status}`)
|
||||
}
|
||||
|
||||
const isSuccess = data.status === 'success' || data.status === 'preview'
|
||||
const errorMessage =
|
||||
data.error || (isSuccess ? undefined : `Zapier action ${data.status || 'failed'}`)
|
||||
|
||||
return {
|
||||
success: isSuccess,
|
||||
error: errorMessage, // Top-level error for the framework to capture
|
||||
output: {
|
||||
executionLogId: data.execution_log_id || '',
|
||||
actionUsed: data.action_used || '',
|
||||
inputParams: data.input_params || {},
|
||||
resolvedParams: data.resolved_params || {},
|
||||
results: data.results || [],
|
||||
resultFieldLabels: data.result_field_labels || {},
|
||||
status: data.status || 'error',
|
||||
error: data.error || undefined,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
executionLogId: {
|
||||
type: 'string',
|
||||
description: 'Unique identifier for this execution (can be used for feedback)',
|
||||
},
|
||||
actionUsed: {
|
||||
type: 'string',
|
||||
description: 'Name of the action that was executed',
|
||||
},
|
||||
inputParams: {
|
||||
type: 'json',
|
||||
description: 'Parameters that were passed to the API',
|
||||
},
|
||||
resolvedParams: {
|
||||
type: 'json',
|
||||
description: 'Parameters that the AI resolved for execution',
|
||||
},
|
||||
results: {
|
||||
type: 'json',
|
||||
description: 'Results from the action execution',
|
||||
},
|
||||
resultFieldLabels: {
|
||||
type: 'json',
|
||||
description: 'Human-readable labels for result fields',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
description: 'Execution status: success, error, empty, preview, or halted',
|
||||
},
|
||||
error: {
|
||||
type: 'string',
|
||||
description: 'Error message if execution failed',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
202
apps/sim/tools/zapier/get_action_details.ts
Normal file
202
apps/sim/tools/zapier/get_action_details.ts
Normal file
@@ -0,0 +1,202 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
ZapierGetActionDetailsParams,
|
||||
ZapierGetActionDetailsResponse,
|
||||
} from '@/tools/zapier/types'
|
||||
|
||||
export const zapierGetActionDetailsTool: ToolConfig<
|
||||
ZapierGetActionDetailsParams,
|
||||
ZapierGetActionDetailsResponse
|
||||
> = {
|
||||
id: 'zapier_get_action_details',
|
||||
name: 'Zapier Get Action Details',
|
||||
description:
|
||||
'Get detailed information about a specific action including its required inputs (needs) and outputs (gives).',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
app: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The app identifier (e.g., "SlackAPI", "GmailV2API")',
|
||||
},
|
||||
action: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The action identifier (e.g., "send_channel_message", "send_email")',
|
||||
},
|
||||
actionType: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Type of action: write, search, read. Defaults to write.',
|
||||
},
|
||||
includeNeeds: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Include input requirements (needs). Defaults to true.',
|
||||
},
|
||||
includeGives: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Include output specifications (gives). Defaults to false.',
|
||||
},
|
||||
includeSample: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Include sample execution result. Defaults to false.',
|
||||
},
|
||||
params: {
|
||||
type: 'json',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Optional params to pass for dynamic field resolution',
|
||||
},
|
||||
accountId: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Zapier account ID',
|
||||
},
|
||||
authenticationId: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Authentication ID for the app connection',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const queryParams = new URLSearchParams()
|
||||
if (params.actionType) {
|
||||
queryParams.append('action_type', params.actionType)
|
||||
}
|
||||
if (params.accountId !== undefined) {
|
||||
queryParams.append('account_id', String(params.accountId))
|
||||
}
|
||||
if (params.authenticationId !== undefined) {
|
||||
queryParams.append('authentication_id', String(params.authenticationId))
|
||||
}
|
||||
// Build action_extra array based on flags
|
||||
const actionExtra: string[] = []
|
||||
if (params.includeNeeds !== false) {
|
||||
actionExtra.push('action_needs')
|
||||
}
|
||||
if (params.includeGives) {
|
||||
actionExtra.push('action_gives')
|
||||
}
|
||||
if (params.includeSample) {
|
||||
actionExtra.push('action_sample')
|
||||
}
|
||||
actionExtra.forEach((extra) => {
|
||||
queryParams.append('action_extra', extra)
|
||||
})
|
||||
const query = queryParams.toString()
|
||||
return `https://actions.zapier.com/api/v2/apps/${encodeURIComponent(params.app)}/actions/${encodeURIComponent(params.action)}/${query ? `?${query}` : ''}`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => ({
|
||||
params: params.params || {},
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || data.detail || `Zapier API error: ${response.status}`)
|
||||
}
|
||||
|
||||
const results = data.results || []
|
||||
const result = results[0] || {}
|
||||
|
||||
// Transform needs array
|
||||
const needs = (result.action_needs || []).map((need: any) => ({
|
||||
key: need.key || '',
|
||||
type: need.type || '',
|
||||
label: need.label || '',
|
||||
required: need.required || false,
|
||||
helpText: need.help_text || '',
|
||||
defaultValue: need.default ?? null,
|
||||
choices: need.choices || null,
|
||||
dependsOn: need.depends_on || null,
|
||||
customField: need.custom_field || false,
|
||||
}))
|
||||
|
||||
// Transform gives array
|
||||
const gives = (result.action_gives || []).map((give: any) => ({
|
||||
key: give.key || '',
|
||||
label: give.label || '',
|
||||
type: give.type || '',
|
||||
score: give.score ?? null,
|
||||
subscore: give.subscore ?? null,
|
||||
important: give.important || false,
|
||||
sample: give.zap_meta_sample ?? null,
|
||||
}))
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
action: result.action
|
||||
? {
|
||||
type: result.action.type || '',
|
||||
key: result.action.key || '',
|
||||
name: result.action.name || '',
|
||||
noun: result.action.noun || '',
|
||||
description: result.action.description || '',
|
||||
}
|
||||
: null,
|
||||
needs,
|
||||
gives,
|
||||
sample: result.action_sample || null,
|
||||
customNeedsProbability: result.action_has_custom_needs_probability ?? 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
action: {
|
||||
type: 'json',
|
||||
description: 'Action metadata including type, key, name, noun, and description',
|
||||
},
|
||||
needs: {
|
||||
type: 'json',
|
||||
description:
|
||||
'Array of input requirements with key, type, label, required, helpText, defaultValue, choices, dependsOn',
|
||||
},
|
||||
gives: {
|
||||
type: 'json',
|
||||
description: 'Array of output fields with key, label, type, important, sample',
|
||||
},
|
||||
sample: {
|
||||
type: 'json',
|
||||
description: 'Sample execution result if requested',
|
||||
optional: true,
|
||||
},
|
||||
customNeedsProbability: {
|
||||
type: 'number',
|
||||
description: 'Probability (0-1) that this action has custom/dynamic input fields',
|
||||
},
|
||||
},
|
||||
}
|
||||
103
apps/sim/tools/zapier/guess_actions.ts
Normal file
103
apps/sim/tools/zapier/guess_actions.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ZapierGuessActionsParams, ZapierGuessActionsResponse } from '@/tools/zapier/types'
|
||||
|
||||
export const zapierGuessActionsTool: ToolConfig<
|
||||
ZapierGuessActionsParams,
|
||||
ZapierGuessActionsResponse
|
||||
> = {
|
||||
id: 'zapier_guess_actions',
|
||||
name: 'Zapier Guess Actions',
|
||||
description:
|
||||
'Find relevant Zapier actions using natural language. Searches across 30,000+ actions to find the best matches for your query.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
query: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Natural language description of what you want to do (e.g., "send a Slack message", "create a Google Doc")',
|
||||
},
|
||||
actionTypes: {
|
||||
type: 'array',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description:
|
||||
'Types of actions to search for: write, search, read. If not specified, returns all types.',
|
||||
},
|
||||
count: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Maximum number of results to return (default: 25)',
|
||||
default: 25,
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://actions.zapier.com/api/v2/guess-actions/',
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {
|
||||
query: params.query,
|
||||
count: params.count || 25,
|
||||
}
|
||||
// Only include action_types if explicitly provided (user selected filters)
|
||||
// If not provided, API returns all action types
|
||||
if (params.actionTypes && params.actionTypes.length > 0) {
|
||||
body.action_types = params.actionTypes
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || data.detail || `Zapier API error: ${response.status}`)
|
||||
}
|
||||
|
||||
const actions = Array.isArray(data) ? data : data.results || []
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
actions: actions.map((action: any) => ({
|
||||
// API returns: app, action, action_type, name (combined), description, image, score
|
||||
app: action.app || '',
|
||||
action: action.action || '',
|
||||
actionType: action.action_type || '',
|
||||
name: action.name || '', // Combined app and action name from API
|
||||
description: action.description || '',
|
||||
image: action.image || '',
|
||||
score: action.score || 0,
|
||||
})),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
actions: {
|
||||
type: 'json',
|
||||
description:
|
||||
'Array of matching actions with app, action, actionType, name (combined app/action name), description, image, and score',
|
||||
},
|
||||
},
|
||||
}
|
||||
23
apps/sim/tools/zapier/index.ts
Normal file
23
apps/sim/tools/zapier/index.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { zapierCreateAiActionTool } from '@/tools/zapier/create_action'
|
||||
import { zapierDeleteAiActionTool } from '@/tools/zapier/delete_action'
|
||||
import { zapierExecuteActionTool } from '@/tools/zapier/execute_action'
|
||||
import { zapierGetActionDetailsTool } from '@/tools/zapier/get_action_details'
|
||||
import { zapierGuessActionsTool } from '@/tools/zapier/guess_actions'
|
||||
import { zapierListActionsTool } from '@/tools/zapier/list_actions'
|
||||
import { zapierSearchAppActionsTool } from '@/tools/zapier/search_app_actions'
|
||||
import { zapierSearchAppsTool } from '@/tools/zapier/search_apps'
|
||||
import { zapierStatelessExecuteTool } from '@/tools/zapier/stateless_execute'
|
||||
import { zapierUpdateAiActionTool } from '@/tools/zapier/update_action'
|
||||
|
||||
export {
|
||||
zapierExecuteActionTool,
|
||||
zapierListActionsTool,
|
||||
zapierSearchAppsTool,
|
||||
zapierGuessActionsTool,
|
||||
zapierCreateAiActionTool,
|
||||
zapierStatelessExecuteTool,
|
||||
zapierSearchAppActionsTool,
|
||||
zapierGetActionDetailsTool,
|
||||
zapierUpdateAiActionTool,
|
||||
zapierDeleteAiActionTool,
|
||||
}
|
||||
78
apps/sim/tools/zapier/list_actions.ts
Normal file
78
apps/sim/tools/zapier/list_actions.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ZapierListActionsParams, ZapierListActionsResponse } from '@/tools/zapier/types'
|
||||
|
||||
export const zapierListActionsTool: ToolConfig<ZapierListActionsParams, ZapierListActionsResponse> =
|
||||
{
|
||||
id: 'zapier_list_actions',
|
||||
name: 'Zapier List Actions',
|
||||
description:
|
||||
'List all AI Actions configured in your Zapier account. Returns stored actions that can be executed.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://actions.zapier.com/api/v2/ai-actions/',
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || data.detail || `Zapier API error: ${response.status}`)
|
||||
}
|
||||
|
||||
// API returns an array of actions and a configuration_link
|
||||
const actions = Array.isArray(data) ? data : data.results || []
|
||||
const configurationLink = data.configuration_link || 'https://actions.zapier.com/providers/'
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
actions: actions.map((action: any) => ({
|
||||
id: action.id || '',
|
||||
description: action.description || '',
|
||||
actionType: action.action_type || '',
|
||||
app: action.app || '',
|
||||
appLabel: action.meta?.app_label || '',
|
||||
action: action.action || '',
|
||||
actionLabel: action.meta?.action_label || '',
|
||||
params: action.params || {},
|
||||
accountId: action.account_id ?? null,
|
||||
authenticationId: action.authentication_id ?? null,
|
||||
needs: action.needs || null,
|
||||
})),
|
||||
configurationLink,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
actions: {
|
||||
type: 'json',
|
||||
description:
|
||||
'Array of configured AI Actions with id, description, actionType, app, appLabel, action, actionLabel, params, accountId, authenticationId, needs',
|
||||
},
|
||||
configurationLink: {
|
||||
type: 'string',
|
||||
description: 'Link to configure more actions in Zapier',
|
||||
},
|
||||
},
|
||||
}
|
||||
111
apps/sim/tools/zapier/search_app_actions.ts
Normal file
111
apps/sim/tools/zapier/search_app_actions.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
ZapierSearchAppActionsParams,
|
||||
ZapierSearchAppActionsResponse,
|
||||
} from '@/tools/zapier/types'
|
||||
|
||||
export const zapierSearchAppActionsTool: ToolConfig<
|
||||
ZapierSearchAppActionsParams,
|
||||
ZapierSearchAppActionsResponse
|
||||
> = {
|
||||
id: 'zapier_search_app_actions',
|
||||
name: 'Zapier Search App Actions',
|
||||
description:
|
||||
'Search for available actions within a specific Zapier app. Returns all actions the app supports.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
app: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The app identifier to search actions for (e.g., "SlackAPI", "GmailV2API")',
|
||||
},
|
||||
query: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Optional search query to filter actions by name or description',
|
||||
},
|
||||
actionTypes: {
|
||||
type: 'array',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description:
|
||||
'Filter by action types: write, search, read, read_bulk, search_or_write, search_and_write. Defaults to write and search.',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const queryParams = new URLSearchParams()
|
||||
if (params.query) {
|
||||
queryParams.append('query', params.query)
|
||||
}
|
||||
if (params.actionTypes && params.actionTypes.length > 0) {
|
||||
params.actionTypes.forEach((type: string) => {
|
||||
queryParams.append('filter_action_type', type)
|
||||
})
|
||||
}
|
||||
const query = queryParams.toString()
|
||||
return `https://actions.zapier.com/api/v2/apps/${encodeURIComponent(params.app)}/actions/${query ? `?${query}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || data.detail || `Zapier API error: ${response.status}`)
|
||||
}
|
||||
|
||||
const actions = data.results || []
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
actions: actions.map((action: any) => ({
|
||||
app: action.app || '',
|
||||
action: action.action || '',
|
||||
actionType: action.type || '',
|
||||
displayName: action.display_name || '',
|
||||
description: action.description || '',
|
||||
relevancyScore: action.search_relevancy_score || 0,
|
||||
appNeedsAuth: action.app_needs_auth || false,
|
||||
appInfo: action.app_info
|
||||
? {
|
||||
app: action.app_info.app || '',
|
||||
name: action.app_info.name || '',
|
||||
logoUrl: action.app_info.logo_url || '',
|
||||
authType: action.app_info.auth_type || '',
|
||||
}
|
||||
: null,
|
||||
})),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
actions: {
|
||||
type: 'json',
|
||||
description:
|
||||
'Array of actions with app, action, actionType, displayName, description, relevancyScore, appNeedsAuth, appInfo',
|
||||
},
|
||||
},
|
||||
}
|
||||
106
apps/sim/tools/zapier/search_apps.ts
Normal file
106
apps/sim/tools/zapier/search_apps.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ZapierSearchAppsParams, ZapierSearchAppsResponse } from '@/tools/zapier/types'
|
||||
|
||||
export const zapierSearchAppsTool: ToolConfig<ZapierSearchAppsParams, ZapierSearchAppsResponse> = {
|
||||
id: 'zapier_search_apps',
|
||||
name: 'Zapier Search Apps',
|
||||
description:
|
||||
'Search for apps available in Zapier. Returns apps with their available action counts.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
query: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Optional search query to filter apps by name',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const baseUrl = 'https://actions.zapier.com/api/v2/apps/search/'
|
||||
if (params.query) {
|
||||
return `${baseUrl}?query=${encodeURIComponent(params.query)}`
|
||||
}
|
||||
return baseUrl
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || data.detail || `Zapier API error: ${response.status}`)
|
||||
}
|
||||
|
||||
const apps = Array.isArray(data) ? data : data.results || []
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
apps: apps.map((app: any) => {
|
||||
// The API returns an 'actions' dictionary with action type counts
|
||||
// Keys can be: write, search, read, read_bulk, search_or_write, search_and_write
|
||||
const actions = app.actions || {}
|
||||
|
||||
// Sum all action counts
|
||||
const actionCount =
|
||||
typeof actions === 'object'
|
||||
? Object.values(actions).reduce(
|
||||
(sum: number, count: any) => sum + (typeof count === 'number' ? count : 0),
|
||||
0
|
||||
)
|
||||
: 0
|
||||
|
||||
// Sum write-type actions (write, search_or_write, search_and_write)
|
||||
const writeActionCount =
|
||||
(actions.write || 0) + (actions.search_or_write || 0) + (actions.search_and_write || 0)
|
||||
|
||||
// Sum search-type actions (search, search_or_write, search_and_write)
|
||||
const searchActionCount =
|
||||
(actions.search || 0) + (actions.search_or_write || 0) + (actions.search_and_write || 0)
|
||||
|
||||
// Sum read-type actions (read, read_bulk)
|
||||
const readActionCount = (actions.read || 0) + (actions.read_bulk || 0)
|
||||
|
||||
return {
|
||||
app: app.app || '',
|
||||
name: app.name || '',
|
||||
logoUrl: app.logo_url || '',
|
||||
authType: app.auth_type ?? null,
|
||||
actions,
|
||||
actionCount,
|
||||
writeActionCount,
|
||||
searchActionCount,
|
||||
readActionCount,
|
||||
}
|
||||
}),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
apps: {
|
||||
type: 'json',
|
||||
description:
|
||||
'Array of apps with app, name, logoUrl, authType, actions (raw counts by type), actionCount, writeActionCount, searchActionCount, readActionCount',
|
||||
},
|
||||
},
|
||||
}
|
||||
207
apps/sim/tools/zapier/stateless_execute.ts
Normal file
207
apps/sim/tools/zapier/stateless_execute.ts
Normal file
@@ -0,0 +1,207 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
ZapierStatelessExecuteParams,
|
||||
ZapierStatelessExecuteResponse,
|
||||
} from '@/tools/zapier/types'
|
||||
|
||||
export const zapierStatelessExecuteTool: ToolConfig<
|
||||
ZapierStatelessExecuteParams,
|
||||
ZapierStatelessExecuteResponse
|
||||
> = {
|
||||
id: 'zapier_stateless_execute',
|
||||
name: 'Zapier Stateless Execute',
|
||||
description:
|
||||
'Execute any Zapier action directly without creating a stored AI Action first. Provide the app, action, and instructions.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
app: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The app to use (e.g., "SlackAPI", "GoogleSheetsV2API", "GmailV2API")',
|
||||
},
|
||||
action: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The action to run (e.g., "direct_message", "add_row", "send_email")',
|
||||
},
|
||||
instructions: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Plain English instructions about how to run the action (e.g., "Send a message saying hello to #general")',
|
||||
},
|
||||
actionType: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description:
|
||||
'Type of action: write, search, read, read_bulk, search_or_write, search_and_write',
|
||||
},
|
||||
params: {
|
||||
type: 'json',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Optional parameter constraints. Each key maps to {mode: "locked"|"guess"|"choose_from"|"ignored", value: any}',
|
||||
},
|
||||
previewOnly: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'If true, preview the execution without actually running it',
|
||||
},
|
||||
authenticationId: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Authentication ID for the app connection',
|
||||
},
|
||||
accountId: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Zapier account ID',
|
||||
},
|
||||
providerId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Provider ID for AI Actions',
|
||||
},
|
||||
tokenBudget: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Max tokens per field (default: 1000)',
|
||||
},
|
||||
skipParamGuessing: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Skip AI parameter guessing',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const queryParams = new URLSearchParams()
|
||||
if (params.previewOnly) {
|
||||
queryParams.append('preview_only', 'true')
|
||||
}
|
||||
if (params.providerId) {
|
||||
queryParams.append('provider_id', params.providerId)
|
||||
}
|
||||
if (params.tokenBudget !== undefined) {
|
||||
queryParams.append('token_budget', String(params.tokenBudget))
|
||||
}
|
||||
if (params.skipParamGuessing) {
|
||||
queryParams.append('skip_param_guessing', 'true')
|
||||
}
|
||||
const query = queryParams.toString()
|
||||
return `https://actions.zapier.com/api/v2/execute/${query ? `?${query}` : ''}`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {
|
||||
instructions: params.instructions,
|
||||
app: params.app,
|
||||
action: params.action,
|
||||
}
|
||||
if (params.actionType) {
|
||||
body.action_type = params.actionType
|
||||
}
|
||||
if (params.params) {
|
||||
body.params = params.params
|
||||
}
|
||||
if (params.authenticationId !== undefined) {
|
||||
body.authentication_id = params.authenticationId
|
||||
}
|
||||
if (params.accountId !== undefined) {
|
||||
body.account_id = params.accountId
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || data.detail || `Zapier API error: ${response.status}`)
|
||||
}
|
||||
|
||||
const isSuccess = data.status === 'success' || data.status === 'preview'
|
||||
const errorMessage =
|
||||
data.error || (isSuccess ? undefined : `Zapier action ${data.status || 'failed'}`)
|
||||
|
||||
return {
|
||||
success: isSuccess,
|
||||
error: errorMessage,
|
||||
output: {
|
||||
executionLogId: data.execution_log_id || '',
|
||||
actionUsed: data.action_used || '',
|
||||
inputParams: data.input_params || {},
|
||||
resolvedParams: data.resolved_params || {},
|
||||
results: data.results || [],
|
||||
resultFieldLabels: data.result_field_labels || {},
|
||||
status: data.status || 'error',
|
||||
error: data.error || undefined,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
executionLogId: {
|
||||
type: 'string',
|
||||
description: 'Unique identifier for this execution',
|
||||
},
|
||||
actionUsed: {
|
||||
type: 'string',
|
||||
description: 'Name of the action that was executed',
|
||||
},
|
||||
inputParams: {
|
||||
type: 'json',
|
||||
description: 'Parameters that were passed to the API',
|
||||
},
|
||||
resolvedParams: {
|
||||
type: 'json',
|
||||
description: 'Parameters that the AI resolved for execution',
|
||||
},
|
||||
results: {
|
||||
type: 'json',
|
||||
description: 'Results from the action execution',
|
||||
},
|
||||
resultFieldLabels: {
|
||||
type: 'json',
|
||||
description: 'Human-readable labels for result fields',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
description: 'Execution status: success, error, empty, preview, or halted',
|
||||
},
|
||||
error: {
|
||||
type: 'string',
|
||||
description: 'Error message if execution failed',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
330
apps/sim/tools/zapier/types.ts
Normal file
330
apps/sim/tools/zapier/types.ts
Normal file
@@ -0,0 +1,330 @@
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
// Base params - all Zapier tools require OAuth access token
|
||||
export interface ZapierBaseParams {
|
||||
accessToken: string
|
||||
}
|
||||
|
||||
// Parameter constraint for execute action
|
||||
export interface ZapierParamConstraint {
|
||||
mode: 'locked' | 'guess' | 'choose_from' | 'ignored'
|
||||
value?: string | number | boolean | any[] | Record<string, any>
|
||||
label?: string | any[] | Record<string, any>
|
||||
}
|
||||
|
||||
// Action types supported by Zapier API
|
||||
export type ZapierActionType =
|
||||
| 'write'
|
||||
| 'search'
|
||||
| 'read'
|
||||
| 'read_bulk'
|
||||
| 'search_or_write'
|
||||
| 'search_and_write'
|
||||
|
||||
// Execute Action params
|
||||
export interface ZapierExecuteActionParams extends ZapierBaseParams {
|
||||
actionId: string
|
||||
instructions: string
|
||||
params?: Record<string, ZapierParamConstraint>
|
||||
previewOnly?: boolean
|
||||
}
|
||||
|
||||
// List Actions params
|
||||
export interface ZapierListActionsParams extends ZapierBaseParams {}
|
||||
|
||||
// Search Apps params
|
||||
export interface ZapierSearchAppsParams extends ZapierBaseParams {
|
||||
query?: string
|
||||
}
|
||||
|
||||
// Guess Actions params (find actions based on natural language)
|
||||
export interface ZapierGuessActionsParams extends ZapierBaseParams {
|
||||
query: string
|
||||
actionTypes?: ZapierActionType[]
|
||||
count?: number
|
||||
}
|
||||
|
||||
// Create AI Action params
|
||||
export interface ZapierCreateAiActionParams extends ZapierBaseParams {
|
||||
app: string
|
||||
action: string
|
||||
actionType?: ZapierActionType
|
||||
params?: Record<string, string | string[]>
|
||||
accountId?: number
|
||||
authenticationId?: number
|
||||
meta?: {
|
||||
params?: Record<string, { label?: string }>
|
||||
app_label?: string
|
||||
action_label?: string
|
||||
authentication_label?: string
|
||||
app_needs_auth?: boolean
|
||||
}
|
||||
}
|
||||
|
||||
// Stateless Execute params
|
||||
export interface ZapierStatelessExecuteParams extends ZapierBaseParams {
|
||||
app: string
|
||||
action: string
|
||||
instructions: string
|
||||
actionType?: ZapierActionType
|
||||
params?: Record<string, ZapierParamConstraint>
|
||||
previewOnly?: boolean
|
||||
authenticationId?: number
|
||||
accountId?: number
|
||||
providerId?: string
|
||||
tokenBudget?: number
|
||||
skipParamGuessing?: boolean
|
||||
}
|
||||
|
||||
// Search App Actions params
|
||||
export interface ZapierSearchAppActionsParams extends ZapierBaseParams {
|
||||
app: string
|
||||
query?: string
|
||||
actionTypes?: ZapierActionType[]
|
||||
}
|
||||
|
||||
// Get Action Details params
|
||||
export interface ZapierGetActionDetailsParams extends ZapierBaseParams {
|
||||
app: string
|
||||
action: string
|
||||
actionType?: ZapierActionType
|
||||
includeNeeds?: boolean
|
||||
includeGives?: boolean
|
||||
includeSample?: boolean
|
||||
params?: Record<string, any>
|
||||
accountId?: number
|
||||
authenticationId?: number
|
||||
}
|
||||
|
||||
// Update AI Action params
|
||||
export interface ZapierUpdateAiActionParams extends ZapierBaseParams {
|
||||
actionId: string
|
||||
app: string
|
||||
action: string
|
||||
actionType?: ZapierActionType
|
||||
params?: Record<string, string | string[]>
|
||||
accountId?: number
|
||||
authenticationId?: number
|
||||
meta?: {
|
||||
params?: Record<string, { label?: string }>
|
||||
app_label?: string
|
||||
action_label?: string
|
||||
authentication_label?: string
|
||||
app_needs_auth?: boolean
|
||||
}
|
||||
}
|
||||
|
||||
// Delete AI Action params
|
||||
export interface ZapierDeleteAiActionParams extends ZapierBaseParams {
|
||||
actionId: string
|
||||
}
|
||||
|
||||
// Execute Action response
|
||||
export interface ZapierExecuteActionResponse extends ToolResponse {
|
||||
output: {
|
||||
executionLogId: string
|
||||
actionUsed: string
|
||||
inputParams: Record<string, any>
|
||||
resolvedParams: Record<string, any>
|
||||
results: any[]
|
||||
resultFieldLabels: Record<string, string>
|
||||
status: 'success' | 'error' | 'empty' | 'preview' | 'halted'
|
||||
error?: string
|
||||
}
|
||||
}
|
||||
|
||||
// List Actions response
|
||||
export interface ZapierAiAction {
|
||||
id: string
|
||||
description: string
|
||||
actionType: string
|
||||
app: string
|
||||
appLabel: string
|
||||
action: string
|
||||
actionLabel: string
|
||||
params: Record<string, any>
|
||||
accountId: number | null
|
||||
authenticationId: number | null
|
||||
needs: any[] | null
|
||||
}
|
||||
|
||||
export interface ZapierListActionsResponse extends ToolResponse {
|
||||
output: {
|
||||
actions: ZapierAiAction[]
|
||||
configurationLink: string
|
||||
}
|
||||
}
|
||||
|
||||
// Search Apps response
|
||||
export interface ZapierAppActions {
|
||||
write?: number
|
||||
search?: number
|
||||
read?: number
|
||||
read_bulk?: number
|
||||
search_or_write?: number
|
||||
search_and_write?: number
|
||||
}
|
||||
|
||||
export interface ZapierApp {
|
||||
app: string
|
||||
name: string
|
||||
logoUrl: string
|
||||
authType: string | null
|
||||
actions: ZapierAppActions
|
||||
actionCount: number
|
||||
writeActionCount: number
|
||||
searchActionCount: number
|
||||
readActionCount: number
|
||||
}
|
||||
|
||||
export interface ZapierSearchAppsResponse extends ToolResponse {
|
||||
output: {
|
||||
apps: ZapierApp[]
|
||||
}
|
||||
}
|
||||
|
||||
// Guess Actions response - matches exact API response structure
|
||||
export interface ZapierGuessedAction {
|
||||
app: string
|
||||
action: string
|
||||
actionType: string
|
||||
name: string // Combined app and action name from API
|
||||
description: string
|
||||
image: string
|
||||
score: number
|
||||
}
|
||||
|
||||
export interface ZapierGuessActionsResponse extends ToolResponse {
|
||||
output: {
|
||||
actions: ZapierGuessedAction[]
|
||||
}
|
||||
}
|
||||
|
||||
// Create AI Action response - matches exact API response structure
|
||||
export interface ZapierCreateAiActionResponse extends ToolResponse {
|
||||
output: {
|
||||
id: string
|
||||
description: string
|
||||
actionType: string
|
||||
app: string
|
||||
appLabel: string
|
||||
action: string
|
||||
actionLabel: string
|
||||
params: Record<string, any>
|
||||
accountId: number | null
|
||||
authenticationId: number | null
|
||||
}
|
||||
}
|
||||
|
||||
// Stateless Execute response - same as Execute Action response
|
||||
export interface ZapierStatelessExecuteResponse extends ToolResponse {
|
||||
output: {
|
||||
executionLogId: string
|
||||
actionUsed: string
|
||||
inputParams: Record<string, any>
|
||||
resolvedParams: Record<string, any>
|
||||
results: any[]
|
||||
resultFieldLabels: Record<string, string>
|
||||
status: 'success' | 'error' | 'empty' | 'preview' | 'halted'
|
||||
error?: string
|
||||
}
|
||||
}
|
||||
|
||||
// Search App Actions response
|
||||
export interface ZapierAppAction {
|
||||
app: string
|
||||
action: string
|
||||
actionType: string
|
||||
displayName: string
|
||||
description: string
|
||||
relevancyScore: number
|
||||
appNeedsAuth: boolean
|
||||
appInfo: {
|
||||
app: string
|
||||
name: string
|
||||
logoUrl: string
|
||||
authType: string
|
||||
} | null
|
||||
}
|
||||
|
||||
export interface ZapierSearchAppActionsResponse extends ToolResponse {
|
||||
output: {
|
||||
actions: ZapierAppAction[]
|
||||
}
|
||||
}
|
||||
|
||||
// Get Action Details response
|
||||
export interface ZapierActionNeed {
|
||||
key: string
|
||||
type: string
|
||||
label: string
|
||||
required: boolean
|
||||
helpText: string
|
||||
defaultValue: any
|
||||
choices: any[] | null
|
||||
dependsOn: string[] | null
|
||||
customField: boolean
|
||||
}
|
||||
|
||||
export interface ZapierActionGive {
|
||||
key: string
|
||||
label: string
|
||||
type: string
|
||||
score: number | null
|
||||
subscore: number | null
|
||||
important: boolean
|
||||
sample: any
|
||||
}
|
||||
|
||||
export interface ZapierGetActionDetailsResponse extends ToolResponse {
|
||||
output: {
|
||||
action: {
|
||||
type: string
|
||||
key: string
|
||||
name: string
|
||||
noun: string
|
||||
description: string
|
||||
} | null
|
||||
needs: ZapierActionNeed[]
|
||||
gives: ZapierActionGive[]
|
||||
sample: any
|
||||
customNeedsProbability: number
|
||||
}
|
||||
}
|
||||
|
||||
// Update AI Action response - same as Create AI Action response
|
||||
export interface ZapierUpdateAiActionResponse extends ToolResponse {
|
||||
output: {
|
||||
id: string
|
||||
description: string
|
||||
actionType: string
|
||||
app: string
|
||||
appLabel: string
|
||||
action: string
|
||||
actionLabel: string
|
||||
params: Record<string, any>
|
||||
accountId: number | null
|
||||
authenticationId: number | null
|
||||
}
|
||||
}
|
||||
|
||||
// Delete AI Action response
|
||||
export interface ZapierDeleteAiActionResponse extends ToolResponse {
|
||||
output: {
|
||||
deleted: boolean
|
||||
message: string
|
||||
}
|
||||
}
|
||||
|
||||
// Union type for all Zapier responses
|
||||
export type ZapierResponse =
|
||||
| ZapierExecuteActionResponse
|
||||
| ZapierListActionsResponse
|
||||
| ZapierSearchAppsResponse
|
||||
| ZapierGuessActionsResponse
|
||||
| ZapierCreateAiActionResponse
|
||||
| ZapierStatelessExecuteResponse
|
||||
| ZapierSearchAppActionsResponse
|
||||
| ZapierGetActionDetailsResponse
|
||||
| ZapierUpdateAiActionResponse
|
||||
| ZapierDeleteAiActionResponse
|
||||
174
apps/sim/tools/zapier/update_action.ts
Normal file
174
apps/sim/tools/zapier/update_action.ts
Normal file
@@ -0,0 +1,174 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ZapierUpdateAiActionParams, ZapierUpdateAiActionResponse } from '@/tools/zapier/types'
|
||||
|
||||
export const zapierUpdateAiActionTool: ToolConfig<
|
||||
ZapierUpdateAiActionParams,
|
||||
ZapierUpdateAiActionResponse
|
||||
> = {
|
||||
id: 'zapier_update_action',
|
||||
name: 'Zapier Update AI Action',
|
||||
description: 'Update an existing stored AI Action configuration in Zapier.',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zapier',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'Access token for Zapier AI Actions API',
|
||||
},
|
||||
actionId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'The ID of the AI Action to update',
|
||||
},
|
||||
app: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'The app identifier (e.g., "SlackAPI", "GmailV2API")',
|
||||
},
|
||||
action: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'The action identifier (e.g., "send_channel_message", "send_email")',
|
||||
},
|
||||
actionType: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description:
|
||||
'Type of action: write, search, read, read_bulk, search_or_write, search_and_write',
|
||||
},
|
||||
params: {
|
||||
type: 'json',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Pre-configured parameter values for the action',
|
||||
},
|
||||
accountId: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Zapier account ID',
|
||||
},
|
||||
authenticationId: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Authentication ID for the app connection',
|
||||
},
|
||||
meta: {
|
||||
type: 'json',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description:
|
||||
'Metadata object with params labels, app_label, action_label, authentication_label, app_needs_auth',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const queryParams = new URLSearchParams()
|
||||
if (params.accountId !== undefined) {
|
||||
queryParams.append('account_id', String(params.accountId))
|
||||
}
|
||||
if (params.authenticationId !== undefined) {
|
||||
queryParams.append('authentication_id', String(params.authenticationId))
|
||||
}
|
||||
const query = queryParams.toString()
|
||||
return `https://actions.zapier.com/api/v2/ai-actions/${encodeURIComponent(params.actionId)}/${query ? `?${query}` : ''}`
|
||||
},
|
||||
method: 'PUT',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => ({
|
||||
app: params.app,
|
||||
action: params.action,
|
||||
action_type: params.actionType || 'write',
|
||||
params: params.params || {},
|
||||
meta: params.meta || { params: {} },
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || data.detail || `Zapier API error: ${response.status}`)
|
||||
}
|
||||
|
||||
const appLabel = data.meta?.app_label || ''
|
||||
const actionLabel = data.meta?.action_label || ''
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id || '',
|
||||
description: data.description || '',
|
||||
actionType: data.action_type || '',
|
||||
app: data.app || '',
|
||||
appLabel,
|
||||
action: data.action || '',
|
||||
actionLabel,
|
||||
params: data.params || {},
|
||||
accountId: data.account_id ?? null,
|
||||
authenticationId: data.authentication_id ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'The ID of the updated AI Action',
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
description: 'Description of the action',
|
||||
},
|
||||
actionType: {
|
||||
type: 'string',
|
||||
description: 'Type of action',
|
||||
},
|
||||
app: {
|
||||
type: 'string',
|
||||
description: 'App identifier',
|
||||
},
|
||||
appLabel: {
|
||||
type: 'string',
|
||||
description: 'Human-readable app label',
|
||||
},
|
||||
action: {
|
||||
type: 'string',
|
||||
description: 'Action identifier',
|
||||
},
|
||||
actionLabel: {
|
||||
type: 'string',
|
||||
description: 'Human-readable action label',
|
||||
},
|
||||
params: {
|
||||
type: 'json',
|
||||
description: 'Configured parameter values',
|
||||
},
|
||||
accountId: {
|
||||
type: 'number',
|
||||
description: 'Zapier account ID',
|
||||
optional: true,
|
||||
},
|
||||
authenticationId: {
|
||||
type: 'number',
|
||||
description: 'Authentication ID used for the app',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user