diff --git a/apps/docs/components/icons.tsx b/apps/docs/components/icons.tsx index 6161069bef..ad217d5182 100644 --- a/apps/docs/components/icons.tsx +++ b/apps/docs/components/icons.tsx @@ -2056,6 +2056,32 @@ export function ConfluenceIcon(props: SVGProps) { ) } +export function ConvexIcon(props: SVGProps) { + return ( + + + + + + ) +} + export function TwilioIcon(props: SVGProps) { return ( diff --git a/apps/docs/components/ui/icon-mapping.ts b/apps/docs/components/ui/icon-mapping.ts index ebf24abb50..3b03a5909b 100644 --- a/apps/docs/components/ui/icon-mapping.ts +++ b/apps/docs/components/ui/icon-mapping.ts @@ -37,6 +37,7 @@ import { CloudWatchIcon, CodePipelineIcon, ConfluenceIcon, + ConvexIcon, CrowdStrikeIcon, CursorIcon, DagsterIcon, @@ -257,6 +258,7 @@ export const blockTypeToIconMap: Record = { codepipeline: CodePipelineIcon, confluence: ConfluenceIcon, confluence_v2: ConfluenceIcon, + convex: ConvexIcon, crowdstrike: CrowdStrikeIcon, cursor: CursorIcon, cursor_v2: CursorIcon, diff --git a/apps/docs/content/docs/en/integrations/convex.mdx b/apps/docs/content/docs/en/integrations/convex.mdx new file mode 100644 index 0000000000..91e7ad4bbf --- /dev/null +++ b/apps/docs/content/docs/en/integrations/convex.mdx @@ -0,0 +1,187 @@ +--- +title: Convex +description: Use Convex database +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[Convex](https://www.convex.dev/) is an open-source reactive backend platform that combines a document database, serverless functions, and real-time sync in one developer-friendly package. Instead of writing SQL, you define queries, mutations, and actions in TypeScript that run right next to your data, and every client subscribed to a query updates automatically when the underlying data changes. + +**Why Convex?** + +- **Functions as the API:** Queries (reads), mutations (transactional writes), and actions (side effects like calling external APIs) are the building blocks of your backend — typed, versioned, and deployed together. +- **Reactive by default:** Query results update live as data changes, with no cache invalidation or polling logic to maintain. +- **Transactional writes:** Mutations run as ACID transactions with serializable isolation, so your data stays consistent without manual locking. +- **Built-in schema awareness:** Convex tracks the shape of every table, so tooling can introspect your data model without a separate migration system. + +**Using Convex in Sim** + +Sim's Convex integration connects your workflows to any Convex deployment with two fields: the deployment URL and a deploy key from the dashboard Settings page. From there you can: + +- **Run functions:** Call query, mutation, and action functions with named JSON arguments — or use Run Function when you don't want to specify the function type. +- **Inspect your data model:** List Tables returns every table in the deployment with the JSON schema of its documents. +- **Export and sync data:** List Documents pages through a consistent snapshot of a table, and Document Deltas returns only the documents that changed since a snapshot — including deletions — making incremental syncs to warehouses, search indexes, or other tools straightforward. + +The Run Query, Run Mutation, Run Action, and Run Function operations work on every Convex plan. List Tables, List Documents, and Document Deltas use Convex's streaming export API, which is available on Convex paid plans. + +Typical patterns include agents that read and write application data through your existing Convex functions, scheduled exports to analytics destinations, and change-driven automations that react to new or updated documents. +{/* MANUAL-CONTENT-END */} + + +## Usage Instructions + +Integrate Convex into the workflow. Run query, mutation, and action functions on your deployment, list tables with their schemas, and export documents with snapshot pagination and change deltas. + + + +## Actions + +### `convex_query` + +Run a Convex query function and return its result + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `deploymentUrl` | string | Yes | Convex deployment URL \(e.g., https://your-deployment.convex.cloud\) | +| `deployKey` | string | Yes | Convex deploy key from the dashboard Settings page | +| `functionPath` | string | Yes | Path to the query function \(e.g., messages:list or folder/file:myQuery\) | +| `args` | json | No | Named arguments to pass to the function as a JSON object | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `value` | json | Result returned by the query function | +| `logLines` | array | Log lines printed during the function execution | + +### `convex_mutation` + +Run a Convex mutation function to write data and return its result + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `deploymentUrl` | string | Yes | Convex deployment URL \(e.g., https://your-deployment.convex.cloud\) | +| `deployKey` | string | Yes | Convex deploy key from the dashboard Settings page | +| `functionPath` | string | Yes | Path to the mutation function \(e.g., messages:send or folder/file:myMutation\) | +| `args` | json | No | Named arguments to pass to the function as a JSON object | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `value` | json | Result returned by the mutation function | +| `logLines` | array | Log lines printed during the function execution | + +### `convex_action` + +Run a Convex action function and return its result + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `deploymentUrl` | string | Yes | Convex deployment URL \(e.g., https://your-deployment.convex.cloud\) | +| `deployKey` | string | Yes | Convex deploy key from the dashboard Settings page | +| `functionPath` | string | Yes | Path to the action function \(e.g., emails:send or folder/file:myAction\) | +| `args` | json | No | Named arguments to pass to the function as a JSON object | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `value` | json | Result returned by the action function | +| `logLines` | array | Log lines printed during the function execution | + +### `convex_run_function` + +Run any Convex function (query, mutation, or action) by path without specifying its type + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `deploymentUrl` | string | Yes | Convex deployment URL \(e.g., https://your-deployment.convex.cloud\) | +| `deployKey` | string | Yes | Convex deploy key from the dashboard Settings page | +| `functionPath` | string | Yes | Path to the function \(e.g., messages:list or folder/file:myFunction\) | +| `args` | json | No | Named arguments to pass to the function as a JSON object | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `value` | json | Result returned by the function | +| `logLines` | array | Log lines printed during the function execution | + +### `convex_list_tables` + +List all tables in a Convex deployment along with their JSON schemas. Requires streaming export, available on Convex paid plans. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `deploymentUrl` | string | Yes | Convex deployment URL \(e.g., https://your-deployment.convex.cloud\) | +| `deployKey` | string | Yes | Convex deploy key from the dashboard Settings page | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `tables` | array | Names of the tables in the deployment | +| `schemas` | json | Map of table name to the JSON schema of its documents | + +### `convex_list_documents` + +List documents from a Convex table via a paginated snapshot. Pass the returned snapshot and page cursor back in to fetch the next page. Requires streaming export, available on Convex paid plans. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `deploymentUrl` | string | Yes | Convex deployment URL \(e.g., https://your-deployment.convex.cloud\) | +| `deployKey` | string | Yes | Convex deploy key from the dashboard Settings page | +| `tableName` | string | No | Table to list documents from. Omit to list documents from all tables. | +| `snapshot` | string | No | Snapshot timestamp from a previous page. Omit on the first request to start a new snapshot. | +| `pageCursor` | string | No | Page cursor from a previous page of the same snapshot. Omit on the first request. | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `documents` | array | Documents in this page of the snapshot | +| `hasMore` | boolean | Whether more pages remain in the snapshot | +| `snapshot` | string | Snapshot timestamp to pass back in when fetching the next page | +| `pageCursor` | string | Page cursor to pass back in when fetching the next page | + +### `convex_document_deltas` + +List documents that changed after a snapshot or previous delta cursor. Deleted documents are returned with a _deleted flag. Requires streaming export, available on Convex paid plans. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `deploymentUrl` | string | Yes | Convex deployment URL \(e.g., https://your-deployment.convex.cloud\) | +| `deployKey` | string | Yes | Convex deploy key from the dashboard Settings page | +| `cursor` | string | Yes | Timestamp cursor to read deltas after. Use the snapshot value from List Documents or the cursor from a previous Document Deltas page. | +| `tableName` | string | No | Table to read deltas from. Omit to read deltas from all tables. | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `documents` | array | Changed documents, each including _table and _ts fields | +| `hasMore` | boolean | Whether more delta pages remain | +| `cursor` | string | Cursor to pass back in when fetching the next page of deltas | + + diff --git a/apps/docs/content/docs/en/integrations/meta.json b/apps/docs/content/docs/en/integrations/meta.json index d96c79dba7..8043c5157e 100644 --- a/apps/docs/content/docs/en/integrations/meta.json +++ b/apps/docs/content/docs/en/integrations/meta.json @@ -34,6 +34,7 @@ "cloudwatch", "codepipeline", "confluence", + "convex", "crowdstrike", "cursor", "dagster", diff --git a/apps/sim/blocks/blocks/convex.ts b/apps/sim/blocks/blocks/convex.ts new file mode 100644 index 0000000000..63ed6eb1cd --- /dev/null +++ b/apps/sim/blocks/blocks/convex.ts @@ -0,0 +1,296 @@ +import { ConvexIcon } from '@/components/icons' +import { AuthMode, type BlockConfig, type BlockMeta, IntegrationType } from '@/blocks/types' +import type { ConvexResponse } from '@/tools/convex/types' + +export const ConvexBlock: BlockConfig = { + type: 'convex', + name: 'Convex', + description: 'Use Convex database', + authMode: AuthMode.ApiKey, + longDescription: + 'Integrate Convex into the workflow. Run query, mutation, and action functions on your deployment, list tables with their schemas, and export documents with snapshot pagination and change deltas.', + docsLink: 'https://docs.sim.ai/integrations/convex', + category: 'tools', + integrationType: IntegrationType.Databases, + bgColor: '#FFFFFF', + icon: ConvexIcon, + subBlocks: [ + { + id: 'operation', + title: 'Operation', + type: 'dropdown', + options: [ + { label: 'Run Query', id: 'query' }, + { label: 'Run Mutation', id: 'mutation' }, + { label: 'Run Action', id: 'action' }, + { label: 'Run Function', id: 'run_function' }, + { label: 'List Tables', id: 'list_tables' }, + { label: 'List Documents', id: 'list_documents' }, + { label: 'Document Deltas', id: 'document_deltas' }, + ], + value: () => 'query', + }, + { + id: 'deploymentUrl', + title: 'Deployment URL', + type: 'short-input', + placeholder: 'https://your-deployment.convex.cloud', + required: true, + }, + { + id: 'deployKey', + title: 'Deploy Key', + type: 'short-input', + placeholder: 'Your Convex deploy key', + password: true, + required: true, + }, + { + id: 'functionPath', + title: 'Function Path', + type: 'short-input', + placeholder: 'messages:list', + condition: { field: 'operation', value: ['query', 'mutation', 'action', 'run_function'] }, + required: true, + }, + { + id: 'args', + title: 'Function Arguments', + type: 'code', + placeholder: '{\n "key": "value"\n}', + condition: { field: 'operation', value: ['query', 'mutation', 'action', 'run_function'] }, + wandConfig: { + enabled: true, + maintainHistory: true, + prompt: `Generate a JSON object of named arguments for a Convex function based on the user's request. + +### CONTEXT +{context} + +### RULES +- Convex functions take a single object of named arguments +- Keys must match the argument names declared by the function +- Values must be JSON-serializable (strings, numbers, booleans, arrays, objects, null) + +### EXAMPLES +"send a message saying hello from sim" -> {"body": "hello from sim", "author": "sim"} +"list the 10 most recent items" -> {"limit": 10} + +Return ONLY the JSON object - no explanations, no markdown, no extra text.`, + placeholder: 'Describe the arguments to pass...', + generationType: 'json-object', + }, + }, + { + id: 'tableName', + title: 'Table', + type: 'short-input', + placeholder: 'Table name (leave empty for all tables)', + condition: { field: 'operation', value: ['list_documents', 'document_deltas'] }, + }, + { + id: 'cursor', + title: 'Cursor', + type: 'short-input', + placeholder: 'Snapshot value from List Documents or cursor from a previous page', + condition: { field: 'operation', value: 'document_deltas' }, + required: true, + }, + { + id: 'snapshot', + title: 'Snapshot', + type: 'short-input', + mode: 'advanced', + placeholder: 'Snapshot timestamp from a previous page', + condition: { field: 'operation', value: 'list_documents' }, + }, + { + id: 'pageCursor', + title: 'Cursor', + type: 'short-input', + mode: 'advanced', + placeholder: 'Cursor from a previous page', + condition: { field: 'operation', value: 'list_documents' }, + }, + ], + tools: { + access: [ + 'convex_query', + 'convex_mutation', + 'convex_action', + 'convex_run_function', + 'convex_list_tables', + 'convex_list_documents', + 'convex_document_deltas', + ], + config: { + tool: (params) => { + switch (params.operation) { + case 'query': + return 'convex_query' + case 'mutation': + return 'convex_mutation' + case 'action': + return 'convex_action' + case 'run_function': + return 'convex_run_function' + case 'list_tables': + return 'convex_list_tables' + case 'list_documents': + return 'convex_list_documents' + case 'document_deltas': + return 'convex_document_deltas' + default: + throw new Error(`Invalid Convex operation: ${params.operation}`) + } + }, + }, + }, + inputs: { + operation: { type: 'string', description: 'Operation to perform' }, + deploymentUrl: { type: 'string', description: 'Convex deployment URL' }, + deployKey: { type: 'string', description: 'Convex deploy key' }, + functionPath: { type: 'string', description: 'Function path (e.g., messages:list)' }, + args: { type: 'json', description: 'Named arguments for the function' }, + tableName: { type: 'string', description: 'Table to read from (empty for all tables)' }, + snapshot: { type: 'string', description: 'Snapshot timestamp for List Documents pagination' }, + cursor: { type: 'string', description: 'Timestamp cursor for Document Deltas' }, + pageCursor: { type: 'string', description: 'Page cursor for List Documents pagination' }, + }, + outputs: { + value: { + type: 'json', + description: 'Result returned by the query, mutation, or action function', + }, + logLines: { + type: 'array', + description: 'Log lines printed during the function execution', + }, + tables: { + type: 'array', + description: 'Names of the tables in the deployment', + }, + schemas: { + type: 'json', + description: 'Map of table name to the JSON schema of its documents', + }, + documents: { + type: 'array', + description: 'Documents returned by List Documents or Document Deltas', + }, + hasMore: { + type: 'boolean', + description: 'Whether more pages remain', + }, + snapshot: { + type: 'string', + description: 'Snapshot timestamp to pass back in for the next List Documents page', + }, + pageCursor: { + type: 'string', + description: 'Page cursor to pass back in for the next List Documents page', + }, + cursor: { + type: 'string', + description: 'Timestamp cursor to pass back in for the next Document Deltas page', + }, + }, +} + +export const ConvexBlockMeta = { + tags: ['cloud'], + templates: [ + { + icon: ConvexIcon, + title: 'Convex support ticket triage', + prompt: + 'Build a workflow that runs a Convex query to fetch open support tickets, classifies each by urgency with an agent, writes the triage label back via a Convex mutation, and posts critical tickets to Slack.', + modules: ['agent', 'workflows'], + category: 'support', + tags: ['automation', 'customer-support'], + alsoIntegrations: ['slack'], + }, + { + icon: ConvexIcon, + title: 'Convex nightly backup to S3', + prompt: + 'Create a scheduled workflow that runs each night, pages through every Convex table with List Documents, writes the exported JSON to S3 with date partitions, and records the run in an audit table.', + modules: ['scheduled', 'agent', 'workflows'], + category: 'operations', + tags: ['devops', 'sync'], + alsoIntegrations: ['s3'], + }, + { + icon: ConvexIcon, + title: 'Convex change-data alerting', + prompt: + 'Build a scheduled workflow that polls Convex Document Deltas for changed rows since the last run, filters for high-value records like fraud flags or large orders, and posts an alert with context to Slack.', + modules: ['scheduled', 'agent', 'workflows'], + category: 'operations', + tags: ['monitoring', 'automation'], + alsoIntegrations: ['slack'], + }, + { + icon: ConvexIcon, + title: 'Convex user onboarding automation', + prompt: + 'Create a workflow that receives new-signup webhooks, runs a Convex mutation to provision the user record with defaults, and sends a personalized welcome email.', + modules: ['agent', 'workflows'], + category: 'operations', + tags: ['automation', 'email'], + alsoIntegrations: ['gmail'], + }, + { + icon: ConvexIcon, + title: 'Convex daily metrics digest', + prompt: + 'Create a scheduled daily workflow that runs Convex queries for new signups, active users, and key feature usage, summarizes the numbers with an agent, and posts a digest to Slack with day-over-day trend.', + modules: ['scheduled', 'agent', 'workflows'], + category: 'productivity', + tags: ['reporting', 'product'], + alsoIntegrations: ['slack'], + }, + { + icon: ConvexIcon, + title: 'Convex search index sync', + prompt: + 'Build a scheduled workflow that uses Convex Document Deltas to mirror changed documents into an Algolia index, removes deleted documents, and writes sync lag to a tables-based monitor.', + modules: ['scheduled', 'tables', 'agent', 'workflows'], + category: 'engineering', + tags: ['engineering', 'sync'], + alsoIntegrations: ['algolia'], + }, + { + icon: ConvexIcon, + title: 'Convex schema drift monitor', + prompt: + 'Create a scheduled workflow that runs Convex List Tables, diffs the returned table schemas against the last snapshot stored in a table, and notifies the engineering channel when fields are added, removed, or change type.', + modules: ['scheduled', 'tables', 'agent', 'workflows'], + category: 'engineering', + tags: ['engineering', 'monitoring'], + alsoIntegrations: ['slack'], + }, + ], + skills: [ + { + name: 'run-convex-function', + description: + 'Run a Convex query, mutation, or action with named arguments and use its result.', + content: + '# Run a Convex Function\n\nCall a function deployed to Convex and work with its return value.\n\n## Steps\n1. Pick the operation that matches the function type: Run Query for reads, Run Mutation for writes, Run Action for side effects like calling external APIs.\n2. Provide the Deployment URL (https://your-deployment.convex.cloud) and a deploy key from the dashboard Settings page.\n3. Set Function Path in module:function form, for example messages:list or tasks/admin:reset.\n4. Pass Function Arguments as a JSON object whose keys match the argument names the function declares, for example {"limit": 10}.\n\n## Output\nThe function result is available as value, with any console output in logLines. Surface the fields downstream steps need.', + }, + { + name: 'export-convex-table', + description: + 'Page through a full Convex table snapshot with List Documents until hasMore is false.', + content: + '# Export a Convex Table\n\nRead every document in a table using snapshot pagination so the export is consistent.\n\n## Steps\n1. Use the List Documents operation with the deployment URL, deploy key, and the table name (leave empty to export all tables).\n2. On the first call leave Snapshot and Cursor empty; the response pins a snapshot timestamp.\n3. While hasMore is true, call List Documents again passing back the returned snapshot and pageCursor values.\n4. Collect the documents arrays from each page into your destination.\n\n## Output\nA complete, point-in-time set of documents for the table, each including _id and _creationTime.', + }, + { + name: 'sync-convex-changes', + description: 'Fetch only changed Convex documents since a snapshot using Document Deltas.', + content: + '# Sync Convex Changes Incrementally\n\nAfter an initial export, keep a downstream copy fresh by reading only what changed.\n\n## Steps\n1. Run an initial export with List Documents and keep the final snapshot value.\n2. On each sync run, call Document Deltas with that value as the Cursor (and optionally a table name).\n3. While hasMore is true, keep calling Document Deltas with the returned cursor; persist the last cursor for the next run.\n4. Apply each document by _id; documents with _deleted set to true should be removed downstream.\n\n## Output\nThe changed documents since the stored cursor plus a new cursor to persist, giving reliable incremental sync when documents are applied idempotently by _id.', + }, + ], +} as const satisfies BlockMeta diff --git a/apps/sim/blocks/registry.ts b/apps/sim/blocks/registry.ts index bc7d8b42bb..e538c6753e 100644 --- a/apps/sim/blocks/registry.ts +++ b/apps/sim/blocks/registry.ts @@ -37,6 +37,7 @@ import { CloudWatchBlock, CloudWatchBlockMeta } from '@/blocks/blocks/cloudwatch import { CodePipelineBlock, CodePipelineBlockMeta } from '@/blocks/blocks/codepipeline' import { ConditionBlock } from '@/blocks/blocks/condition' import { ConfluenceBlock, ConfluenceBlockMeta, ConfluenceV2Block } from '@/blocks/blocks/confluence' +import { ConvexBlock, ConvexBlockMeta } from '@/blocks/blocks/convex' import { CredentialBlock } from '@/blocks/blocks/credential' import { CrowdStrikeBlock, CrowdStrikeBlockMeta } from '@/blocks/blocks/crowdstrike' import { CursorBlock, CursorBlockMeta, CursorV2Block } from '@/blocks/blocks/cursor' @@ -361,6 +362,7 @@ const BLOCK_REGISTRY: Record = { condition: ConditionBlock, confluence: ConfluenceBlock, confluence_v2: ConfluenceV2Block, + convex: ConvexBlock, credential: CredentialBlock, crowdstrike: CrowdStrikeBlock, cursor: CursorBlock, @@ -654,6 +656,7 @@ const BLOCK_META_REGISTRY: Record = { cloudwatch: CloudWatchBlockMeta, codepipeline: CodePipelineBlockMeta, confluence: ConfluenceBlockMeta, + convex: ConvexBlockMeta, crowdstrike: CrowdStrikeBlockMeta, cursor: CursorBlockMeta, dagster: DagsterBlockMeta, diff --git a/apps/sim/components/icons.tsx b/apps/sim/components/icons.tsx index 6161069bef..ad217d5182 100644 --- a/apps/sim/components/icons.tsx +++ b/apps/sim/components/icons.tsx @@ -2056,6 +2056,32 @@ export function ConfluenceIcon(props: SVGProps) { ) } +export function ConvexIcon(props: SVGProps) { + return ( + + + + + + ) +} + export function TwilioIcon(props: SVGProps) { return ( diff --git a/apps/sim/lib/integrations/icon-mapping.ts b/apps/sim/lib/integrations/icon-mapping.ts index 7344cb8ee1..e627b9bbc8 100644 --- a/apps/sim/lib/integrations/icon-mapping.ts +++ b/apps/sim/lib/integrations/icon-mapping.ts @@ -37,6 +37,7 @@ import { CloudWatchIcon, CodePipelineIcon, ConfluenceIcon, + ConvexIcon, CrowdStrikeIcon, CursorIcon, DagsterIcon, @@ -254,6 +255,7 @@ export const blockTypeToIconMap: Record = { cloudwatch: CloudWatchIcon, codepipeline: CodePipelineIcon, confluence_v2: ConfluenceIcon, + convex: ConvexIcon, crowdstrike: CrowdStrikeIcon, cursor_v2: CursorIcon, dagster: DagsterIcon, diff --git a/apps/sim/lib/integrations/integrations.json b/apps/sim/lib/integrations/integrations.json index 72301855dd..ecee38c652 100644 --- a/apps/sim/lib/integrations/integrations.json +++ b/apps/sim/lib/integrations/integrations.json @@ -3196,6 +3196,53 @@ "integrationType": "documents", "tags": ["knowledge-base", "content-management", "note-taking"] }, + { + "type": "convex", + "slug": "convex", + "name": "Convex", + "description": "Use Convex database", + "longDescription": "Integrate Convex into the workflow. Run query, mutation, and action functions on your deployment, list tables with their schemas, and export documents with snapshot pagination and change deltas.", + "bgColor": "#FFFFFF", + "iconName": "ConvexIcon", + "docsUrl": "https://docs.sim.ai/integrations/convex", + "operations": [ + { + "name": "Run Query", + "description": "Run a Convex query function and return its result" + }, + { + "name": "Run Mutation", + "description": "Run a Convex mutation function to write data and return its result" + }, + { + "name": "Run Action", + "description": "Run a Convex action function and return its result" + }, + { + "name": "Run Function", + "description": "Run any Convex function (query, mutation, or action) by path without specifying its type" + }, + { + "name": "List Tables", + "description": "List all tables in a Convex deployment along with their JSON schemas. Requires streaming export, available on Convex paid plans." + }, + { + "name": "List Documents", + "description": "List documents from a Convex table via a paginated snapshot. Pass the returned snapshot and page cursor back in to fetch the next page. Requires streaming export, available on Convex paid plans." + }, + { + "name": "Document Deltas", + "description": "List documents that changed after a snapshot or previous delta cursor. Deleted documents are returned with a _deleted flag. Requires streaming export, available on Convex paid plans." + } + ], + "operationCount": 7, + "triggers": [], + "triggerCount": 0, + "authType": "api-key", + "category": "tools", + "integrationType": "databases", + "tags": ["cloud"] + }, { "type": "crowdstrike", "slug": "crowdstrike", diff --git a/apps/sim/tools/convex/action.ts b/apps/sim/tools/convex/action.ts new file mode 100644 index 0000000000..3d0e3ac472 --- /dev/null +++ b/apps/sim/tools/convex/action.ts @@ -0,0 +1,68 @@ +import type { ConvexFunctionCallParams, ConvexFunctionCallResponse } from '@/tools/convex/types' +import { + convexApiUrl, + convexAuthHeaders, + parseFunctionArgs, + transformFunctionCallResponse, +} from '@/tools/convex/utils' +import type { ToolConfig } from '@/tools/types' + +export const actionTool: ToolConfig = { + id: 'convex_action', + name: 'Convex Run Action', + description: 'Run a Convex action function and return its result', + version: '1.0.0', + + params: { + deploymentUrl: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Convex deployment URL (e.g., https://your-deployment.convex.cloud)', + }, + deployKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Convex deploy key from the dashboard Settings page', + }, + functionPath: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Path to the action function (e.g., emails:send or folder/file:myAction)', + }, + args: { + type: 'json', + required: false, + visibility: 'user-or-llm', + description: 'Named arguments to pass to the function as a JSON object', + }, + }, + + request: { + url: (params) => convexApiUrl(params.deploymentUrl, '/api/action'), + method: 'POST', + headers: (params) => ({ + 'Content-Type': 'application/json', + ...convexAuthHeaders(params.deployKey), + }), + body: (params) => ({ + path: params.functionPath.trim(), + args: parseFunctionArgs(params.args), + format: 'json', + }), + }, + + transformResponse: async (response: Response) => + transformFunctionCallResponse(response, 'action'), + + outputs: { + value: { type: 'json', description: 'Result returned by the action function' }, + logLines: { + type: 'array', + description: 'Log lines printed during the function execution', + items: { type: 'string' }, + }, + }, +} diff --git a/apps/sim/tools/convex/document_deltas.ts b/apps/sim/tools/convex/document_deltas.ts new file mode 100644 index 0000000000..a07fd5516b --- /dev/null +++ b/apps/sim/tools/convex/document_deltas.ts @@ -0,0 +1,92 @@ +import type { + ConvexDocumentDeltasApiResponse, + ConvexDocumentDeltasParams, + ConvexDocumentDeltasResponse, +} from '@/tools/convex/types' +import { convexApiUrl, convexAuthHeaders, parseConvexResponse } from '@/tools/convex/utils' +import type { ToolConfig } from '@/tools/types' + +export const documentDeltasTool: ToolConfig< + ConvexDocumentDeltasParams, + ConvexDocumentDeltasResponse +> = { + id: 'convex_document_deltas', + name: 'Convex Document Deltas', + description: + 'List documents that changed after a snapshot or previous delta cursor. Deleted documents are returned with a _deleted flag. Requires streaming export, available on Convex paid plans.', + version: '1.0.0', + + params: { + deploymentUrl: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Convex deployment URL (e.g., https://your-deployment.convex.cloud)', + }, + deployKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Convex deploy key from the dashboard Settings page', + }, + cursor: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: + 'Timestamp cursor to read deltas after. Use the snapshot value from List Documents or the cursor from a previous Document Deltas page.', + }, + tableName: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Table to read deltas from. Omit to read deltas from all tables.', + }, + }, + + request: { + url: (params) => { + const cursor = String(params.cursor ?? '').trim() + if (!cursor) { + throw new Error( + 'Cursor is required: pass the snapshot value from List Documents or the cursor from a previous Document Deltas page' + ) + } + const query = new URLSearchParams({ format: 'json', cursor }) + if (params.tableName?.trim()) query.set('tableName', params.tableName.trim()) + return convexApiUrl(params.deploymentUrl, `/api/document_deltas?${query.toString()}`) + }, + method: 'GET', + headers: (params) => convexAuthHeaders(params.deployKey), + }, + + transformResponse: async (response: Response) => { + const data = (await parseConvexResponse(response)) as ConvexDocumentDeltasApiResponse + + return { + success: true, + output: { + documents: data.values ?? [], + hasMore: data.hasMore ?? false, + cursor: data.cursor !== undefined && data.cursor !== null ? String(data.cursor) : null, + }, + } + }, + + outputs: { + documents: { + type: 'array', + description: 'Changed documents, each including _table and _ts fields', + items: { type: 'object' }, + }, + hasMore: { + type: 'boolean', + description: 'Whether more delta pages remain', + }, + cursor: { + type: 'string', + description: 'Cursor to pass back in when fetching the next page of deltas', + optional: true, + }, + }, +} diff --git a/apps/sim/tools/convex/index.ts b/apps/sim/tools/convex/index.ts new file mode 100644 index 0000000000..3ea3cd86a7 --- /dev/null +++ b/apps/sim/tools/convex/index.ts @@ -0,0 +1,15 @@ +import { actionTool } from '@/tools/convex/action' +import { documentDeltasTool } from '@/tools/convex/document_deltas' +import { listDocumentsTool } from '@/tools/convex/list_documents' +import { listTablesTool } from '@/tools/convex/list_tables' +import { mutationTool } from '@/tools/convex/mutation' +import { queryTool } from '@/tools/convex/query' +import { runFunctionTool } from '@/tools/convex/run_function' + +export const convexQueryTool = queryTool +export const convexMutationTool = mutationTool +export const convexActionTool = actionTool +export const convexRunFunctionTool = runFunctionTool +export const convexListTablesTool = listTablesTool +export const convexListDocumentsTool = listDocumentsTool +export const convexDocumentDeltasTool = documentDeltasTool diff --git a/apps/sim/tools/convex/list_documents.ts b/apps/sim/tools/convex/list_documents.ts new file mode 100644 index 0000000000..6c4f2650e2 --- /dev/null +++ b/apps/sim/tools/convex/list_documents.ts @@ -0,0 +1,103 @@ +import type { + ConvexListDocumentsParams, + ConvexListDocumentsResponse, + ConvexListSnapshotApiResponse, +} from '@/tools/convex/types' +import { convexApiUrl, convexAuthHeaders, parseConvexResponse } from '@/tools/convex/utils' +import type { ToolConfig } from '@/tools/types' + +export const listDocumentsTool: ToolConfig = + { + id: 'convex_list_documents', + name: 'Convex List Documents', + description: + 'List documents from a Convex table via a paginated snapshot. Pass the returned snapshot and page cursor back in to fetch the next page. Requires streaming export, available on Convex paid plans.', + version: '1.0.0', + + params: { + deploymentUrl: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Convex deployment URL (e.g., https://your-deployment.convex.cloud)', + }, + deployKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Convex deploy key from the dashboard Settings page', + }, + tableName: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Table to list documents from. Omit to list documents from all tables.', + }, + snapshot: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: + 'Snapshot timestamp from a previous page. Omit on the first request to start a new snapshot.', + }, + pageCursor: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: + 'Page cursor from a previous page of the same snapshot. Omit on the first request.', + }, + }, + + request: { + url: (params) => { + const query = new URLSearchParams({ format: 'json' }) + if (params.tableName?.trim()) query.set('tableName', params.tableName.trim()) + const snapshot = String(params.snapshot ?? '').trim() + if (snapshot) query.set('snapshot', snapshot) + const pageCursor = String(params.pageCursor ?? '').trim() + if (pageCursor) query.set('cursor', pageCursor) + return convexApiUrl(params.deploymentUrl, `/api/list_snapshot?${query.toString()}`) + }, + method: 'GET', + headers: (params) => convexAuthHeaders(params.deployKey), + }, + + transformResponse: async (response: Response) => { + const data = (await parseConvexResponse(response)) as ConvexListSnapshotApiResponse + + return { + success: true, + output: { + documents: data.values ?? [], + hasMore: data.hasMore ?? false, + snapshot: + data.snapshot !== undefined && data.snapshot !== null ? String(data.snapshot) : null, + pageCursor: + data.cursor !== undefined && data.cursor !== null ? String(data.cursor) : null, + }, + } + }, + + outputs: { + documents: { + type: 'array', + description: 'Documents in this page of the snapshot', + items: { type: 'object' }, + }, + hasMore: { + type: 'boolean', + description: 'Whether more pages remain in the snapshot', + }, + snapshot: { + type: 'string', + description: 'Snapshot timestamp to pass back in when fetching the next page', + optional: true, + }, + pageCursor: { + type: 'string', + description: 'Page cursor to pass back in when fetching the next page', + optional: true, + }, + }, + } diff --git a/apps/sim/tools/convex/list_tables.ts b/apps/sim/tools/convex/list_tables.ts new file mode 100644 index 0000000000..0b7db9feb4 --- /dev/null +++ b/apps/sim/tools/convex/list_tables.ts @@ -0,0 +1,60 @@ +import type { ConvexListTablesParams, ConvexListTablesResponse } from '@/tools/convex/types' +import { convexApiUrl, convexAuthHeaders, parseConvexResponse } from '@/tools/convex/utils' +import type { ToolConfig } from '@/tools/types' + +export const listTablesTool: ToolConfig = { + id: 'convex_list_tables', + name: 'Convex List Tables', + description: + 'List all tables in a Convex deployment along with their JSON schemas. Requires streaming export, available on Convex paid plans.', + version: '1.0.0', + + params: { + deploymentUrl: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Convex deployment URL (e.g., https://your-deployment.convex.cloud)', + }, + deployKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Convex deploy key from the dashboard Settings page', + }, + }, + + request: { + url: (params) => convexApiUrl(params.deploymentUrl, '/api/json_schemas?format=json'), + method: 'GET', + headers: (params) => convexAuthHeaders(params.deployKey), + }, + + transformResponse: async (response: Response) => { + const data = await parseConvexResponse(response) + const schemas = + data !== null && typeof data === 'object' && !Array.isArray(data) + ? (data as Record) + : {} + + return { + success: true, + output: { + tables: Object.keys(schemas).sort(), + schemas, + }, + } + }, + + outputs: { + tables: { + type: 'array', + description: 'Names of the tables in the deployment', + items: { type: 'string' }, + }, + schemas: { + type: 'json', + description: 'Map of table name to the JSON schema of its documents', + }, + }, +} diff --git a/apps/sim/tools/convex/mutation.ts b/apps/sim/tools/convex/mutation.ts new file mode 100644 index 0000000000..1bf1d6e0a3 --- /dev/null +++ b/apps/sim/tools/convex/mutation.ts @@ -0,0 +1,68 @@ +import type { ConvexFunctionCallParams, ConvexFunctionCallResponse } from '@/tools/convex/types' +import { + convexApiUrl, + convexAuthHeaders, + parseFunctionArgs, + transformFunctionCallResponse, +} from '@/tools/convex/utils' +import type { ToolConfig } from '@/tools/types' + +export const mutationTool: ToolConfig = { + id: 'convex_mutation', + name: 'Convex Run Mutation', + description: 'Run a Convex mutation function to write data and return its result', + version: '1.0.0', + + params: { + deploymentUrl: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Convex deployment URL (e.g., https://your-deployment.convex.cloud)', + }, + deployKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Convex deploy key from the dashboard Settings page', + }, + functionPath: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Path to the mutation function (e.g., messages:send or folder/file:myMutation)', + }, + args: { + type: 'json', + required: false, + visibility: 'user-or-llm', + description: 'Named arguments to pass to the function as a JSON object', + }, + }, + + request: { + url: (params) => convexApiUrl(params.deploymentUrl, '/api/mutation'), + method: 'POST', + headers: (params) => ({ + 'Content-Type': 'application/json', + ...convexAuthHeaders(params.deployKey), + }), + body: (params) => ({ + path: params.functionPath.trim(), + args: parseFunctionArgs(params.args), + format: 'json', + }), + }, + + transformResponse: async (response: Response) => + transformFunctionCallResponse(response, 'mutation'), + + outputs: { + value: { type: 'json', description: 'Result returned by the mutation function' }, + logLines: { + type: 'array', + description: 'Log lines printed during the function execution', + items: { type: 'string' }, + }, + }, +} diff --git a/apps/sim/tools/convex/query.ts b/apps/sim/tools/convex/query.ts new file mode 100644 index 0000000000..9a3873f388 --- /dev/null +++ b/apps/sim/tools/convex/query.ts @@ -0,0 +1,67 @@ +import type { ConvexFunctionCallParams, ConvexFunctionCallResponse } from '@/tools/convex/types' +import { + convexApiUrl, + convexAuthHeaders, + parseFunctionArgs, + transformFunctionCallResponse, +} from '@/tools/convex/utils' +import type { ToolConfig } from '@/tools/types' + +export const queryTool: ToolConfig = { + id: 'convex_query', + name: 'Convex Run Query', + description: 'Run a Convex query function and return its result', + version: '1.0.0', + + params: { + deploymentUrl: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Convex deployment URL (e.g., https://your-deployment.convex.cloud)', + }, + deployKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Convex deploy key from the dashboard Settings page', + }, + functionPath: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Path to the query function (e.g., messages:list or folder/file:myQuery)', + }, + args: { + type: 'json', + required: false, + visibility: 'user-or-llm', + description: 'Named arguments to pass to the function as a JSON object', + }, + }, + + request: { + url: (params) => convexApiUrl(params.deploymentUrl, '/api/query'), + method: 'POST', + headers: (params) => ({ + 'Content-Type': 'application/json', + ...convexAuthHeaders(params.deployKey), + }), + body: (params) => ({ + path: params.functionPath.trim(), + args: parseFunctionArgs(params.args), + format: 'json', + }), + }, + + transformResponse: async (response: Response) => transformFunctionCallResponse(response, 'query'), + + outputs: { + value: { type: 'json', description: 'Result returned by the query function' }, + logLines: { + type: 'array', + description: 'Log lines printed during the function execution', + items: { type: 'string' }, + }, + }, +} diff --git a/apps/sim/tools/convex/run_function.ts b/apps/sim/tools/convex/run_function.ts new file mode 100644 index 0000000000..6da50fd464 --- /dev/null +++ b/apps/sim/tools/convex/run_function.ts @@ -0,0 +1,76 @@ +import type { ConvexFunctionCallParams, ConvexFunctionCallResponse } from '@/tools/convex/types' +import { + convexApiUrl, + convexAuthHeaders, + parseFunctionArgs, + transformFunctionCallResponse, +} from '@/tools/convex/utils' +import type { ToolConfig } from '@/tools/types' + +export const runFunctionTool: ToolConfig = { + id: 'convex_run_function', + name: 'Convex Run Function', + description: + 'Run any Convex function (query, mutation, or action) by path without specifying its type', + version: '1.0.0', + + params: { + deploymentUrl: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Convex deployment URL (e.g., https://your-deployment.convex.cloud)', + }, + deployKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Convex deploy key from the dashboard Settings page', + }, + functionPath: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Path to the function (e.g., messages:list or folder/file:myFunction)', + }, + args: { + type: 'json', + required: false, + visibility: 'user-or-llm', + description: 'Named arguments to pass to the function as a JSON object', + }, + }, + + request: { + url: (params) => { + const identifier = params.functionPath + .trim() + .replace(':', '/') + .split('/') + .map(encodeURIComponent) + .join('/') + return convexApiUrl(params.deploymentUrl, `/api/run/${identifier}`) + }, + method: 'POST', + headers: (params) => ({ + 'Content-Type': 'application/json', + ...convexAuthHeaders(params.deployKey), + }), + body: (params) => ({ + args: parseFunctionArgs(params.args), + format: 'json', + }), + }, + + transformResponse: async (response: Response) => + transformFunctionCallResponse(response, 'function'), + + outputs: { + value: { type: 'json', description: 'Result returned by the function' }, + logLines: { + type: 'array', + description: 'Log lines printed during the function execution', + items: { type: 'string' }, + }, + }, +} diff --git a/apps/sim/tools/convex/types.ts b/apps/sim/tools/convex/types.ts new file mode 100644 index 0000000000..4f474a9c59 --- /dev/null +++ b/apps/sim/tools/convex/types.ts @@ -0,0 +1,103 @@ +import type { ToolResponse } from '@/tools/types' + +/** + * Shared parameter and response definitions for Convex tools. + * Based on the official Convex HTTP API documentation. + * @see https://docs.convex.dev/http-api/ + */ + +export interface ConvexBaseParams { + deploymentUrl: string + deployKey: string +} + +export interface ConvexFunctionCallParams extends ConvexBaseParams { + functionPath: string + args?: Record | string +} + +export interface ConvexFunctionCallResponse extends ToolResponse { + output: { + value: unknown + logLines: string[] + } +} + +export interface ConvexListTablesParams extends ConvexBaseParams {} + +export interface ConvexListTablesResponse extends ToolResponse { + output: { + tables: string[] + schemas: Record + } +} + +export interface ConvexListDocumentsParams extends ConvexBaseParams { + tableName?: string + snapshot?: string + pageCursor?: string +} + +export interface ConvexListDocumentsResponse extends ToolResponse { + output: { + documents: unknown[] + hasMore: boolean + snapshot: string | null + pageCursor: string | null + } +} + +export interface ConvexDocumentDeltasParams extends ConvexBaseParams { + cursor: string + tableName?: string +} + +export interface ConvexDocumentDeltasResponse extends ToolResponse { + output: { + documents: unknown[] + hasMore: boolean + cursor: string | null + } +} + +/** + * Raw wire shape of Convex function-call responses (`/api/query`, `/api/mutation`, + * `/api/action`, `/api/run/{identifier}`). + * @see https://docs.convex.dev/http-api/#post-apiquery-apimutation-apiaction + */ +export interface ConvexFunctionCallApiResponse { + status?: 'success' | 'error' + value?: unknown + logLines?: string[] + errorMessage?: string + errorData?: unknown +} + +/** Raw wire shape of `/api/list_snapshot` responses. */ +export interface ConvexListSnapshotApiResponse { + values?: unknown[] + hasMore?: boolean + snapshot?: number | string | null + cursor?: number | string | null +} + +/** Raw wire shape of `/api/document_deltas` responses. */ +export interface ConvexDocumentDeltasApiResponse { + values?: unknown[] + hasMore?: boolean + cursor?: number | string | null +} + +export interface ConvexResponse extends ToolResponse { + output: { + value?: unknown + logLines?: string[] + tables?: string[] + schemas?: Record + documents?: unknown[] + hasMore?: boolean + snapshot?: string | null + pageCursor?: string | null + cursor?: string | null + } +} diff --git a/apps/sim/tools/convex/utils.ts b/apps/sim/tools/convex/utils.ts new file mode 100644 index 0000000000..324b0f5f83 --- /dev/null +++ b/apps/sim/tools/convex/utils.ts @@ -0,0 +1,110 @@ +import { truncate } from '@sim/utils/string' +import { validateExternalUrl } from '@/lib/core/security/input-validation' +import type { + ConvexFunctionCallApiResponse, + ConvexFunctionCallResponse, +} from '@/tools/convex/types' + +/** + * Builds a Convex deployment API URL from the user-provided deployment URL. + * Accepts URLs with or without a trailing slash. + * + * The deployment URL is validated with the shared SSRF guard so invalid hosts + * fail fast with a clear message; the tool executor additionally re-validates + * with DNS resolution and pins the resolved IP for the actual request. + */ +export function convexApiUrl(deploymentUrl: string, path: string): string { + const trimmed = deploymentUrl.trim().replace(/\/+$/, '') + const validation = validateExternalUrl(trimmed, 'Deployment URL') + if (!validation.isValid) { + throw new Error(`${validation.error} (e.g., https://your-deployment.convex.cloud)`) + } + const parsed = new URL(trimmed) + if (parsed.search || parsed.hash) { + throw new Error( + 'Deployment URL must not include a query string or fragment (e.g., https://your-deployment.convex.cloud)' + ) + } + return `${trimmed}${path}` +} + +/** + * Builds the deployment admin authorization header for Convex HTTP API requests. + * @see https://docs.convex.dev/http-api/#api-authentication + */ +export function convexAuthHeaders(deployKey: string): Record { + return { Authorization: `Convex ${deployKey.trim()}` } +} + +/** + * Parses function arguments that may arrive as a JSON string or an object. + * Convex function endpoints require a named-argument object. + */ +export function parseFunctionArgs( + args: Record | string | undefined +): Record { + if (args === undefined || args === null) return {} + if (typeof args === 'string') { + const trimmed = args.trim() + if (!trimmed) return {} + let parsed: unknown + try { + parsed = JSON.parse(trimmed) + } catch { + throw new Error('Invalid function arguments: expected a JSON object like {"key": "value"}') + } + if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) { + throw new Error('Invalid function arguments: expected a JSON object, not an array or scalar') + } + return parsed as Record + } + if (typeof args !== 'object' || Array.isArray(args)) { + throw new Error('Invalid function arguments: expected a JSON object, not an array or scalar') + } + return args +} + +/** + * Parses a Convex API response body, surfacing non-OK HTTP statuses (e.g. 401 + * from an invalid deploy key) as descriptive errors instead of empty results. + */ +export async function parseConvexResponse(response: Response): Promise { + if (!response.ok) { + const text = await response.text().catch(() => '') + throw new Error( + `Convex request failed (HTTP ${response.status})${text ? `: ${truncate(text.trim(), 300)}` : ''}` + ) + } + return response.json() +} + +/** + * Transforms a Convex function-call response. Convex returns HTTP 200 with an + * in-band `status: "error"` payload when the function itself fails, so errors + * must be surfaced here rather than relying on the HTTP status code. + * @see https://docs.convex.dev/http-api/#post-apiquery-apimutation-apiaction + */ +export async function transformFunctionCallResponse( + response: Response, + functionType: 'query' | 'mutation' | 'action' | 'function' +): Promise { + const data = (await parseConvexResponse(response)) as ConvexFunctionCallApiResponse + + if (data.status === 'error') { + const details = + data.errorData !== undefined && data.errorData !== null + ? ` (${JSON.stringify(data.errorData)})` + : '' + throw new Error( + `Convex ${functionType} failed: ${data.errorMessage || 'Unknown error'}${details}` + ) + } + + return { + success: true, + output: { + value: data.value ?? null, + logLines: data.logLines ?? [], + }, + } +} diff --git a/apps/sim/tools/registry.ts b/apps/sim/tools/registry.ts index 2923847b02..2190d2e4e9 100644 --- a/apps/sim/tools/registry.ts +++ b/apps/sim/tools/registry.ts @@ -492,6 +492,15 @@ import { confluenceUpdateTool, confluenceUploadAttachmentTool, } from '@/tools/confluence' +import { + convexActionTool, + convexDocumentDeltasTool, + convexListDocumentsTool, + convexListTablesTool, + convexMutationTool, + convexQueryTool, + convexRunFunctionTool, +} from '@/tools/convex' import { crowdstrikeGetSensorAggregatesTool, crowdstrikeGetSensorDetailsTool, @@ -4422,6 +4431,13 @@ export const tools: Record = { codepipeline_retry_stage_execution: codepipelineRetryStageExecutionTool, codepipeline_start_execution: codepipelineStartExecutionTool, codepipeline_stop_execution: codepipelineStopExecutionTool, + convex_query: convexQueryTool, + convex_mutation: convexMutationTool, + convex_action: convexActionTool, + convex_run_function: convexRunFunctionTool, + convex_list_tables: convexListTablesTool, + convex_list_documents: convexListDocumentsTool, + convex_document_deltas: convexDocumentDeltasTool, crowdstrike_get_sensor_aggregates: crowdstrikeGetSensorAggregatesTool, crowdstrike_get_sensor_details: crowdstrikeGetSensorDetailsTool, crowdstrike_query_sensors: crowdstrikeQuerySensorsTool,