mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-09 23:17:59 -05:00
Compare commits
7 Commits
v0.5.13
...
feat/workf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
198a9ca69a | ||
|
|
0ae7eb197a | ||
|
|
304b5d9c7e | ||
|
|
ee3e1e8cf9 | ||
|
|
ede41af674 | ||
|
|
cb0c55c6f6 | ||
|
|
d22b21c8d1 |
File diff suppressed because one or more lines are too long
@@ -24,7 +24,7 @@ export function BlockInfoCard({
|
||||
<div className='flex items-center justify-center p-6'>
|
||||
<div
|
||||
className='flex h-20 w-20 items-center justify-center rounded-lg'
|
||||
style={{ backgroundColor: color }}
|
||||
style={{ background: color }}
|
||||
>
|
||||
{ResolvedIcon ? (
|
||||
<ResolvedIcon className='h-10 w-10 text-white' />
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
ConfluenceIcon,
|
||||
DiscordIcon,
|
||||
DocumentIcon,
|
||||
DynamoDBIcon,
|
||||
ElevenLabsIcon,
|
||||
ExaAIIcon,
|
||||
EyeIcon,
|
||||
@@ -64,6 +65,7 @@ import {
|
||||
PosthogIcon,
|
||||
PylonIcon,
|
||||
QdrantIcon,
|
||||
RDSIcon,
|
||||
RedditIcon,
|
||||
ResendIcon,
|
||||
S3Icon,
|
||||
@@ -134,6 +136,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
|
||||
s3: S3Icon,
|
||||
resend: ResendIcon,
|
||||
reddit: RedditIcon,
|
||||
rds: RDSIcon,
|
||||
qdrant: QdrantIcon,
|
||||
pylon: PylonIcon,
|
||||
posthog: PosthogIcon,
|
||||
@@ -182,6 +185,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
|
||||
file: DocumentIcon,
|
||||
exa: ExaAIIcon,
|
||||
elevenlabs: ElevenLabsIcon,
|
||||
dynamodb: DynamoDBIcon,
|
||||
discord: DiscordIcon,
|
||||
confluence: ConfluenceIcon,
|
||||
clay: ClayIcon,
|
||||
|
||||
188
apps/docs/content/docs/de/tools/dynamodb.mdx
Normal file
188
apps/docs/content/docs/de/tools/dynamodb.mdx
Normal file
@@ -0,0 +1,188 @@
|
||||
---
|
||||
title: Amazon DynamoDB
|
||||
description: Verbindung zu Amazon DynamoDB
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="dynamodb"
|
||||
color="linear-gradient(45deg, #2E27AD 0%, #527FFF 100%)"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
[Amazon DynamoDB](https://aws.amazon.com/dynamodb/) ist ein vollständig verwalteter NoSQL-Datenbankdienst von AWS, der schnelle und vorhersehbare Leistung mit nahtloser Skalierbarkeit bietet. Mit DynamoDB können Sie beliebige Datenmengen speichern und abrufen und jede Art von Anforderungsverkehr bedienen, ohne dass Sie Hardware oder Infrastruktur verwalten müssen.
|
||||
|
||||
Mit DynamoDB können Sie:
|
||||
|
||||
- **Elemente abrufen**: Elemente in Ihren Tabellen mithilfe von Primärschlüsseln nachschlagen
|
||||
- **Elemente einfügen**: Elemente in Ihren Tabellen hinzufügen oder ersetzen
|
||||
- **Elemente abfragen**: Mehrere Elemente mithilfe von Abfragen über Indizes abrufen
|
||||
- **Tabellen scannen**: Alle oder einen Teil der Daten in einer Tabelle lesen
|
||||
- **Elemente aktualisieren**: Bestimmte Attribute vorhandener Elemente ändern
|
||||
- **Elemente löschen**: Datensätze aus Ihren Tabellen entfernen
|
||||
|
||||
In Sim ermöglicht die DynamoDB-Integration Ihren Agenten den sicheren Zugriff auf DynamoDB-Tabellen und deren Manipulation mithilfe von AWS-Anmeldeinformationen. Zu den unterstützten Operationen gehören:
|
||||
|
||||
- **Get**: Ein Element anhand seines Schlüssels abrufen
|
||||
- **Put**: Elemente einfügen oder überschreiben
|
||||
- **Query**: Abfragen mit Schlüsselbedingungen und Filtern ausführen
|
||||
- **Scan**: Mehrere Elemente durch Scannen der Tabelle oder des Index lesen
|
||||
- **Update**: Bestimmte Attribute eines oder mehrerer Elemente ändern
|
||||
- **Delete**: Ein Element aus einer Tabelle entfernen
|
||||
|
||||
Diese Integration ermöglicht es Sim-Agenten, Datenverwaltungsaufgaben innerhalb Ihrer DynamoDB-Tabellen programmatisch zu automatisieren, sodass Sie Workflows erstellen können, die skalierbare NoSQL-Daten ohne manuellen Aufwand oder Serververwaltung verwalten, ändern und abrufen.
|
||||
{/* MANUAL-CONTENT-END */}
|
||||
|
||||
## Nutzungsanweisungen
|
||||
|
||||
Integrieren Sie Amazon DynamoDB in Workflows. Unterstützt Get-, Put-, Query-, Scan-, Update- und Delete-Operationen auf DynamoDB-Tabellen.
|
||||
|
||||
## Tools
|
||||
|
||||
### `dynamodb_get`
|
||||
|
||||
Ein Element aus einer DynamoDB-Tabelle anhand des Primärschlüssels abrufen
|
||||
|
||||
#### Eingabe
|
||||
|
||||
| Parameter | Typ | Erforderlich | Beschreibung |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Ja | AWS-Region (z.B. us-east-1) |
|
||||
| `accessKeyId` | string | Ja | AWS-Zugriffsschlüssel-ID |
|
||||
| `secretAccessKey` | string | Ja | AWS-Geheimzugriffsschlüssel |
|
||||
| `tableName` | string | Ja | DynamoDB-Tabellenname |
|
||||
| `key` | object | Ja | Primärschlüssel des abzurufenden Elements |
|
||||
| `consistentRead` | boolean | Nein | Stark konsistentes Lesen verwenden |
|
||||
|
||||
#### Ausgabe
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Statusmeldung der Operation |
|
||||
| `item` | object | Abgerufenes Element |
|
||||
|
||||
### `dynamodb_put`
|
||||
|
||||
Ein Element in eine DynamoDB-Tabelle einfügen
|
||||
|
||||
#### Eingabe
|
||||
|
||||
| Parameter | Typ | Erforderlich | Beschreibung |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Ja | AWS-Region (z.B. us-east-1) |
|
||||
| `accessKeyId` | string | Ja | AWS-Zugriffsschlüssel-ID |
|
||||
| `secretAccessKey` | string | Ja | AWS-Geheimzugriffsschlüssel |
|
||||
| `tableName` | string | Ja | DynamoDB-Tabellenname |
|
||||
| `item` | object | Ja | Element, das in die Tabelle eingefügt werden soll |
|
||||
|
||||
#### Ausgabe
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Statusmeldung der Operation |
|
||||
| `item` | object | Erstelltes Element |
|
||||
|
||||
### `dynamodb_query`
|
||||
|
||||
Abfrage von Elementen aus einer DynamoDB-Tabelle mit Schlüsselbedingungen
|
||||
|
||||
#### Eingabe
|
||||
|
||||
| Parameter | Typ | Erforderlich | Beschreibung |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Ja | AWS-Region (z.B. us-east-1) |
|
||||
| `accessKeyId` | string | Ja | AWS-Zugriffsschlüssel-ID |
|
||||
| `secretAccessKey` | string | Ja | AWS-Geheimzugriffsschlüssel |
|
||||
| `tableName` | string | Ja | DynamoDB-Tabellenname |
|
||||
| `keyConditionExpression` | string | Ja | Schlüsselbedingungsausdruck (z.B. "pk = :pk") |
|
||||
| `filterExpression` | string | Nein | Filterausdruck für Ergebnisse |
|
||||
| `expressionAttributeNames` | object | Nein | Attributnamenzuordnungen für reservierte Wörter |
|
||||
| `expressionAttributeValues` | object | Nein | Ausdrucksattributwerte |
|
||||
| `indexName` | string | Nein | Name des sekundären Index für die Abfrage |
|
||||
| `limit` | number | Nein | Maximale Anzahl der zurückzugebenden Elemente |
|
||||
|
||||
#### Ausgabe
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Statusmeldung der Operation |
|
||||
| `items` | array | Array der zurückgegebenen Elemente |
|
||||
| `count` | number | Anzahl der zurückgegebenen Elemente |
|
||||
|
||||
### `dynamodb_scan`
|
||||
|
||||
Alle Elemente in einer DynamoDB-Tabelle scannen
|
||||
|
||||
#### Eingabe
|
||||
|
||||
| Parameter | Typ | Erforderlich | Beschreibung |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Ja | AWS-Region (z.B. us-east-1) |
|
||||
| `accessKeyId` | string | Ja | AWS-Zugriffsschlüssel-ID |
|
||||
| `secretAccessKey` | string | Ja | AWS-Geheimzugriffsschlüssel |
|
||||
| `tableName` | string | Ja | DynamoDB-Tabellenname |
|
||||
| `filterExpression` | string | Nein | Filterausdruck für Ergebnisse |
|
||||
| `projectionExpression` | string | Nein | Abzurufende Attribute |
|
||||
| `expressionAttributeNames` | object | Nein | Attributnamenzuordnungen für reservierte Wörter |
|
||||
| `expressionAttributeValues` | object | Nein | Ausdrucksattributwerte |
|
||||
| `limit` | number | Nein | Maximale Anzahl der zurückzugebenden Elemente |
|
||||
|
||||
#### Ausgabe
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Statusmeldung der Operation |
|
||||
| `items` | array | Array der zurückgegebenen Elemente |
|
||||
| `count` | number | Anzahl der zurückgegebenen Elemente |
|
||||
|
||||
### `dynamodb_update`
|
||||
|
||||
Ein Element in einer DynamoDB-Tabelle aktualisieren
|
||||
|
||||
#### Eingabe
|
||||
|
||||
| Parameter | Typ | Erforderlich | Beschreibung |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Ja | AWS-Region (z.B. us-east-1) |
|
||||
| `accessKeyId` | string | Ja | AWS-Zugriffsschlüssel-ID |
|
||||
| `secretAccessKey` | string | Ja | AWS-Geheimzugriffsschlüssel |
|
||||
| `tableName` | string | Ja | Name der DynamoDB-Tabelle |
|
||||
| `key` | object | Ja | Primärschlüssel des zu aktualisierenden Elements |
|
||||
| `updateExpression` | string | Ja | Aktualisierungsausdruck (z.B. "SET #name = :name") |
|
||||
| `expressionAttributeNames` | object | Nein | Attributnamenzuordnungen für reservierte Wörter |
|
||||
| `expressionAttributeValues` | object | Nein | Ausdrucksattributwerte |
|
||||
| `conditionExpression` | string | Nein | Bedingung, die erfüllt sein muss, damit die Aktualisierung erfolgreich ist |
|
||||
|
||||
#### Ausgabe
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Statusmeldung der Operation |
|
||||
| `item` | object | Aktualisiertes Element |
|
||||
|
||||
### `dynamodb_delete`
|
||||
|
||||
Ein Element aus einer DynamoDB-Tabelle löschen
|
||||
|
||||
#### Eingabe
|
||||
|
||||
| Parameter | Typ | Erforderlich | Beschreibung |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Ja | AWS-Region (z.B. us-east-1) |
|
||||
| `accessKeyId` | string | Ja | AWS-Zugriffsschlüssel-ID |
|
||||
| `secretAccessKey` | string | Ja | AWS-Geheimzugriffsschlüssel |
|
||||
| `tableName` | string | Ja | Name der DynamoDB-Tabelle |
|
||||
| `key` | object | Ja | Primärschlüssel des zu löschenden Elements |
|
||||
| `conditionExpression` | string | Nein | Bedingung, die erfüllt sein muss, damit das Löschen erfolgreich ist |
|
||||
|
||||
#### Ausgabe
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Statusmeldung der Operation |
|
||||
|
||||
## Hinweise
|
||||
|
||||
- Kategorie: `tools`
|
||||
- Typ: `dynamodb`
|
||||
168
apps/docs/content/docs/de/tools/rds.mdx
Normal file
168
apps/docs/content/docs/de/tools/rds.mdx
Normal file
@@ -0,0 +1,168 @@
|
||||
---
|
||||
title: Amazon RDS
|
||||
description: Verbindung zu Amazon RDS über Data API
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="rds"
|
||||
color="linear-gradient(45deg, #2E27AD 0%, #527FFF 100%)"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
[Amazon RDS Aurora Serverless](https://aws.amazon.com/rds/aurora/serverless/) ist eine vollständig verwaltete relationale Datenbank, die automatisch startet, herunterfährt und ihre Kapazität basierend auf den Anforderungen Ihrer Anwendung skaliert. Sie ermöglicht es Ihnen, SQL-Datenbanken in der Cloud zu betreiben, ohne Datenbankserver verwalten zu müssen.
|
||||
|
||||
Mit RDS Aurora Serverless können Sie:
|
||||
|
||||
- **Daten abfragen**: Flexible SQL-Abfragen über Ihre Tabellen ausführen
|
||||
- **Neue Datensätze einfügen**: Automatisch Daten zu Ihrer Datenbank hinzufügen
|
||||
- **Bestehende Datensätze aktualisieren**: Daten in Ihren Tabellen mit benutzerdefinierten Filtern ändern
|
||||
- **Datensätze löschen**: Unerwünschte Daten mit präzisen Kriterien entfernen
|
||||
- **Raw-SQL ausführen**: Jeden gültigen SQL-Befehl ausführen, der von Aurora unterstützt wird
|
||||
|
||||
In Sim ermöglicht die RDS-Integration Ihren Agenten, sicher und programmatisch mit Amazon Aurora Serverless-Datenbanken zu arbeiten. Zu den unterstützten Operationen gehören:
|
||||
|
||||
- **Abfrage**: SELECT und andere SQL-Abfragen ausführen, um Zeilen aus Ihrer Datenbank abzurufen
|
||||
- **Einfügen**: Neue Datensätze mit strukturierten Daten in Tabellen einfügen
|
||||
- **Aktualisieren**: Daten in Zeilen ändern, die Ihren angegebenen Bedingungen entsprechen
|
||||
- **Löschen**: Datensätze aus einer Tabelle nach benutzerdefinierten Filtern oder Kriterien entfernen
|
||||
- **Ausführen**: Raw-SQL für fortgeschrittene Szenarien ausführen
|
||||
|
||||
Diese Integration ermöglicht es Ihren Agenten, eine breite Palette von Datenbankoperationen ohne manuelle Eingriffe zu automatisieren. Durch die Verbindung von Sim mit Amazon RDS können Sie Agenten erstellen, die relationale Daten innerhalb Ihrer Workflows verwalten, aktualisieren und abrufen – alles ohne Datenbankinfrastruktur oder -verbindungen zu verwalten.
|
||||
{/* MANUAL-CONTENT-END */}
|
||||
|
||||
## Nutzungsanweisungen
|
||||
|
||||
Integrieren Sie Amazon RDS Aurora Serverless in den Workflow mit der Data API. Kann Daten abfragen, einfügen, aktualisieren, löschen und Raw-SQL ausführen, ohne Datenbankverbindungen verwalten zu müssen.
|
||||
|
||||
## Tools
|
||||
|
||||
### `rds_query`
|
||||
|
||||
Führen Sie eine SELECT-Abfrage auf Amazon RDS mit der Data API aus
|
||||
|
||||
#### Eingabe
|
||||
|
||||
| Parameter | Typ | Erforderlich | Beschreibung |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Ja | AWS-Region (z.B. us-east-1) |
|
||||
| `accessKeyId` | string | Ja | AWS-Zugriffsschlüssel-ID |
|
||||
| `secretAccessKey` | string | Ja | AWS-Geheimzugriffsschlüssel |
|
||||
| `resourceArn` | string | Ja | ARN des Aurora-DB-Clusters |
|
||||
| `secretArn` | string | Ja | ARN des Secrets Manager-Geheimnisses mit DB-Anmeldedaten |
|
||||
| `database` | string | Nein | Datenbankname (optional) |
|
||||
| `query` | string | Ja | SQL-SELECT-Abfrage zur Ausführung |
|
||||
|
||||
#### Ausgabe
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Statusmeldung der Operation |
|
||||
| `rows` | array | Array der zurückgegebenen Zeilen aus der Abfrage |
|
||||
| `rowCount` | number | Anzahl der zurückgegebenen Zeilen |
|
||||
|
||||
### `rds_insert`
|
||||
|
||||
Daten in eine Amazon RDS-Tabelle mit der Data API einfügen
|
||||
|
||||
#### Eingabe
|
||||
|
||||
| Parameter | Typ | Erforderlich | Beschreibung |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Ja | AWS-Region (z.B. us-east-1) |
|
||||
| `accessKeyId` | string | Ja | AWS-Zugriffsschlüssel-ID |
|
||||
| `secretAccessKey` | string | Ja | AWS-Geheimzugriffsschlüssel |
|
||||
| `resourceArn` | string | Ja | ARN des Aurora-DB-Clusters |
|
||||
| `secretArn` | string | Ja | ARN des Secrets Manager-Geheimnisses mit DB-Anmeldedaten |
|
||||
| `database` | string | Nein | Datenbankname (optional) |
|
||||
| `table` | string | Ja | Tabellenname zum Einfügen |
|
||||
| `data` | object | Ja | Einzufügende Daten als Schlüssel-Wert-Paare |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Statusmeldung der Operation |
|
||||
| `rows` | array | Array der eingefügten Zeilen |
|
||||
| `rowCount` | number | Anzahl der eingefügten Zeilen |
|
||||
|
||||
### `rds_update`
|
||||
|
||||
Daten in einer Amazon RDS-Tabelle über die Data API aktualisieren
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Typ | Erforderlich | Beschreibung |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Ja | AWS-Region (z.B. us-east-1) |
|
||||
| `accessKeyId` | string | Ja | AWS-Zugriffsschlüssel-ID |
|
||||
| `secretAccessKey` | string | Ja | AWS-Geheimzugriffsschlüssel |
|
||||
| `resourceArn` | string | Ja | ARN des Aurora-DB-Clusters |
|
||||
| `secretArn` | string | Ja | ARN des Secrets Manager-Geheimnisses mit DB-Anmeldedaten |
|
||||
| `database` | string | Nein | Datenbankname (optional) |
|
||||
| `table` | string | Ja | Name der zu aktualisierenden Tabelle |
|
||||
| `data` | object | Ja | Zu aktualisierende Daten als Schlüssel-Wert-Paare |
|
||||
| `conditions` | object | Ja | Bedingungen für die Aktualisierung (z.B. `{"id": 1}`) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Statusmeldung der Operation |
|
||||
| `rows` | array | Array der aktualisierten Zeilen |
|
||||
| `rowCount` | number | Anzahl der aktualisierten Zeilen |
|
||||
|
||||
### `rds_delete`
|
||||
|
||||
Daten aus einer Amazon RDS-Tabelle über die Data API löschen
|
||||
|
||||
#### Eingabe
|
||||
|
||||
| Parameter | Typ | Erforderlich | Beschreibung |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Ja | AWS-Region (z.B. us-east-1) |
|
||||
| `accessKeyId` | string | Ja | AWS-Zugriffsschlüssel-ID |
|
||||
| `secretAccessKey` | string | Ja | AWS geheimer Zugriffsschlüssel |
|
||||
| `resourceArn` | string | Ja | ARN des Aurora-DB-Clusters |
|
||||
| `secretArn` | string | Ja | ARN des Secrets Manager-Geheimnisses mit DB-Anmeldedaten |
|
||||
| `database` | string | Nein | Datenbankname (optional) |
|
||||
| `table` | string | Ja | Tabellenname, aus dem gelöscht werden soll |
|
||||
| `conditions` | object | Ja | Bedingungen für das Löschen (z.B. `{"id": 1}`) |
|
||||
|
||||
#### Ausgabe
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Statusmeldung der Operation |
|
||||
| `rows` | array | Array der gelöschten Zeilen |
|
||||
| `rowCount` | number | Anzahl der gelöschten Zeilen |
|
||||
|
||||
### `rds_execute`
|
||||
|
||||
Rohes SQL auf Amazon RDS über die Data API ausführen
|
||||
|
||||
#### Eingabe
|
||||
|
||||
| Parameter | Typ | Erforderlich | Beschreibung |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Ja | AWS-Region (z.B. us-east-1) |
|
||||
| `accessKeyId` | string | Ja | AWS-Zugriffsschlüssel-ID |
|
||||
| `secretAccessKey` | string | Ja | AWS geheimer Zugriffsschlüssel |
|
||||
| `resourceArn` | string | Ja | ARN des Aurora-DB-Clusters |
|
||||
| `secretArn` | string | Ja | ARN des Secrets Manager-Geheimnisses mit DB-Anmeldedaten |
|
||||
| `database` | string | Nein | Datenbankname (optional) |
|
||||
| `query` | string | Ja | Rohe SQL-Abfrage zur Ausführung |
|
||||
|
||||
#### Ausgabe
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Statusmeldung der Operation |
|
||||
| `rows` | array | Array der zurückgegebenen oder betroffenen Zeilen |
|
||||
| `rowCount` | number | Anzahl der betroffenen Zeilen |
|
||||
|
||||
## Hinweise
|
||||
|
||||
- Kategorie: `tools`
|
||||
- Typ: `rds`
|
||||
@@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="s3"
|
||||
color="#E0E0E0"
|
||||
color="linear-gradient(45deg, #1B660F 0%, #6CAE3E 100%)"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
|
||||
193
apps/docs/content/docs/en/tools/dynamodb.mdx
Normal file
193
apps/docs/content/docs/en/tools/dynamodb.mdx
Normal file
@@ -0,0 +1,193 @@
|
||||
---
|
||||
title: Amazon DynamoDB
|
||||
description: Connect to Amazon DynamoDB
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="dynamodb"
|
||||
color="linear-gradient(45deg, #2E27AD 0%, #527FFF 100%)"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
[Amazon DynamoDB](https://aws.amazon.com/dynamodb/) is a fully managed NoSQL database service offered by AWS that provides fast and predictable performance with seamless scalability. DynamoDB lets you store and retrieve any amount of data and serves any level of request traffic, without the need for you to manage hardware or infrastructure.
|
||||
|
||||
With DynamoDB, you can:
|
||||
|
||||
- **Get items**: Look up items in your tables using primary keys
|
||||
- **Put items**: Add or replace items in your tables
|
||||
- **Query items**: Retrieve multiple items using queries across indexes
|
||||
- **Scan tables**: Read all or part of the data in a table
|
||||
- **Update items**: Modify specific attributes of existing items
|
||||
- **Delete items**: Remove records from your tables
|
||||
|
||||
In Sim, the DynamoDB integration enables your agents to securely access and manipulate DynamoDB tables using AWS credentials. Supported operations include:
|
||||
|
||||
- **Get**: Retrieve an item by its key
|
||||
- **Put**: Insert or overwrite items
|
||||
- **Query**: Run queries using key conditions and filters
|
||||
- **Scan**: Read multiple items by scanning the table or index
|
||||
- **Update**: Change specific attributes of one or more items
|
||||
- **Delete**: Remove an item from a table
|
||||
|
||||
This integration empowers Sim agents to automate data management tasks within your DynamoDB tables programmatically, so you can build workflows that manage, modify, and retrieve scalable NoSQL data without manual effort or server management.
|
||||
{/* MANUAL-CONTENT-END */}
|
||||
|
||||
|
||||
## Usage Instructions
|
||||
|
||||
Integrate Amazon DynamoDB into workflows. Supports Get, Put, Query, Scan, Update, and Delete operations on DynamoDB tables.
|
||||
|
||||
|
||||
|
||||
## Tools
|
||||
|
||||
### `dynamodb_get`
|
||||
|
||||
Get an item from a DynamoDB table by primary key
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Yes | AWS region \(e.g., us-east-1\) |
|
||||
| `accessKeyId` | string | Yes | AWS access key ID |
|
||||
| `secretAccessKey` | string | Yes | AWS secret access key |
|
||||
| `tableName` | string | Yes | DynamoDB table name |
|
||||
| `key` | object | Yes | Primary key of the item to retrieve |
|
||||
| `consistentRead` | boolean | No | Use strongly consistent read |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Operation status message |
|
||||
| `item` | object | Retrieved item |
|
||||
|
||||
### `dynamodb_put`
|
||||
|
||||
Put an item into a DynamoDB table
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Yes | AWS region \(e.g., us-east-1\) |
|
||||
| `accessKeyId` | string | Yes | AWS access key ID |
|
||||
| `secretAccessKey` | string | Yes | AWS secret access key |
|
||||
| `tableName` | string | Yes | DynamoDB table name |
|
||||
| `item` | object | Yes | Item to put into the table |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Operation status message |
|
||||
| `item` | object | Created item |
|
||||
|
||||
### `dynamodb_query`
|
||||
|
||||
Query items from a DynamoDB table using key conditions
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Yes | AWS region \(e.g., us-east-1\) |
|
||||
| `accessKeyId` | string | Yes | AWS access key ID |
|
||||
| `secretAccessKey` | string | Yes | AWS secret access key |
|
||||
| `tableName` | string | Yes | DynamoDB table name |
|
||||
| `keyConditionExpression` | string | Yes | Key condition expression \(e.g., "pk = :pk"\) |
|
||||
| `filterExpression` | string | No | Filter expression for results |
|
||||
| `expressionAttributeNames` | object | No | Attribute name mappings for reserved words |
|
||||
| `expressionAttributeValues` | object | No | Expression attribute values |
|
||||
| `indexName` | string | No | Secondary index name to query |
|
||||
| `limit` | number | No | Maximum number of items to return |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Operation status message |
|
||||
| `items` | array | Array of items returned |
|
||||
| `count` | number | Number of items returned |
|
||||
|
||||
### `dynamodb_scan`
|
||||
|
||||
Scan all items in a DynamoDB table
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Yes | AWS region \(e.g., us-east-1\) |
|
||||
| `accessKeyId` | string | Yes | AWS access key ID |
|
||||
| `secretAccessKey` | string | Yes | AWS secret access key |
|
||||
| `tableName` | string | Yes | DynamoDB table name |
|
||||
| `filterExpression` | string | No | Filter expression for results |
|
||||
| `projectionExpression` | string | No | Attributes to retrieve |
|
||||
| `expressionAttributeNames` | object | No | Attribute name mappings for reserved words |
|
||||
| `expressionAttributeValues` | object | No | Expression attribute values |
|
||||
| `limit` | number | No | Maximum number of items to return |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Operation status message |
|
||||
| `items` | array | Array of items returned |
|
||||
| `count` | number | Number of items returned |
|
||||
|
||||
### `dynamodb_update`
|
||||
|
||||
Update an item in a DynamoDB table
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Yes | AWS region \(e.g., us-east-1\) |
|
||||
| `accessKeyId` | string | Yes | AWS access key ID |
|
||||
| `secretAccessKey` | string | Yes | AWS secret access key |
|
||||
| `tableName` | string | Yes | DynamoDB table name |
|
||||
| `key` | object | Yes | Primary key of the item to update |
|
||||
| `updateExpression` | string | Yes | Update expression \(e.g., "SET #name = :name"\) |
|
||||
| `expressionAttributeNames` | object | No | Attribute name mappings for reserved words |
|
||||
| `expressionAttributeValues` | object | No | Expression attribute values |
|
||||
| `conditionExpression` | string | No | Condition that must be met for the update to succeed |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Operation status message |
|
||||
| `item` | object | Updated item |
|
||||
|
||||
### `dynamodb_delete`
|
||||
|
||||
Delete an item from a DynamoDB table
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Yes | AWS region \(e.g., us-east-1\) |
|
||||
| `accessKeyId` | string | Yes | AWS access key ID |
|
||||
| `secretAccessKey` | string | Yes | AWS secret access key |
|
||||
| `tableName` | string | Yes | DynamoDB table name |
|
||||
| `key` | object | Yes | Primary key of the item to delete |
|
||||
| `conditionExpression` | string | No | Condition that must be met for the delete to succeed |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Operation status message |
|
||||
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
- Category: `tools`
|
||||
- Type: `dynamodb`
|
||||
@@ -11,6 +11,7 @@
|
||||
"clay",
|
||||
"confluence",
|
||||
"discord",
|
||||
"dynamodb",
|
||||
"elevenlabs",
|
||||
"exa",
|
||||
"file",
|
||||
@@ -59,6 +60,7 @@
|
||||
"posthog",
|
||||
"pylon",
|
||||
"qdrant",
|
||||
"rds",
|
||||
"reddit",
|
||||
"resend",
|
||||
"s3",
|
||||
|
||||
173
apps/docs/content/docs/en/tools/rds.mdx
Normal file
173
apps/docs/content/docs/en/tools/rds.mdx
Normal file
@@ -0,0 +1,173 @@
|
||||
---
|
||||
title: Amazon RDS
|
||||
description: Connect to Amazon RDS via Data API
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="rds"
|
||||
color="linear-gradient(45deg, #2E27AD 0%, #527FFF 100%)"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
[Amazon RDS Aurora Serverless](https://aws.amazon.com/rds/aurora/serverless/) is a fully managed relational database that automatically starts up, shuts down, and scales capacity based on your application's needs. It allows you to run SQL databases in the cloud without managing database servers.
|
||||
|
||||
With RDS Aurora Serverless, you can:
|
||||
|
||||
- **Query data**: Run flexible SQL queries across your tables
|
||||
- **Insert new records**: Add data to your database automatically
|
||||
- **Update existing records**: Modify data in your tables using custom filters
|
||||
- **Delete records**: Remove unwanted data using precise criteria
|
||||
- **Execute raw SQL**: Run any valid SQL command supported by Aurora
|
||||
|
||||
In Sim, the RDS integration enables your agents to work with Amazon Aurora Serverless databases securely and programmatically. Supported operations include:
|
||||
|
||||
- **Query**: Run SELECT and other SQL queries to fetch rows from your database
|
||||
- **Insert**: Insert new records into tables with structured data
|
||||
- **Update**: Change data in rows that match your specified conditions
|
||||
- **Delete**: Remove records from a table by custom filters or criteria
|
||||
- **Execute**: Run raw SQL for advanced scenarios
|
||||
|
||||
This integration allows your agents to automate a wide range of database operations without manual intervention. By connecting Sim with Amazon RDS, you can build agents that manage, update, and retrieve relational data within your workflows—all without handling database infrastructure or connections.
|
||||
{/* MANUAL-CONTENT-END */}
|
||||
|
||||
|
||||
## Usage Instructions
|
||||
|
||||
Integrate Amazon RDS Aurora Serverless into the workflow using the Data API. Can query, insert, update, delete, and execute raw SQL without managing database connections.
|
||||
|
||||
|
||||
|
||||
## Tools
|
||||
|
||||
### `rds_query`
|
||||
|
||||
Execute a SELECT query on Amazon RDS using the Data API
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Yes | AWS region \(e.g., us-east-1\) |
|
||||
| `accessKeyId` | string | Yes | AWS access key ID |
|
||||
| `secretAccessKey` | string | Yes | AWS secret access key |
|
||||
| `resourceArn` | string | Yes | ARN of the Aurora DB cluster |
|
||||
| `secretArn` | string | Yes | ARN of the Secrets Manager secret containing DB credentials |
|
||||
| `database` | string | No | Database name \(optional\) |
|
||||
| `query` | string | Yes | SQL SELECT query to execute |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Operation status message |
|
||||
| `rows` | array | Array of rows returned from the query |
|
||||
| `rowCount` | number | Number of rows returned |
|
||||
|
||||
### `rds_insert`
|
||||
|
||||
Insert data into an Amazon RDS table using the Data API
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Yes | AWS region \(e.g., us-east-1\) |
|
||||
| `accessKeyId` | string | Yes | AWS access key ID |
|
||||
| `secretAccessKey` | string | Yes | AWS secret access key |
|
||||
| `resourceArn` | string | Yes | ARN of the Aurora DB cluster |
|
||||
| `secretArn` | string | Yes | ARN of the Secrets Manager secret containing DB credentials |
|
||||
| `database` | string | No | Database name \(optional\) |
|
||||
| `table` | string | Yes | Table name to insert into |
|
||||
| `data` | object | Yes | Data to insert as key-value pairs |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Operation status message |
|
||||
| `rows` | array | Array of inserted rows |
|
||||
| `rowCount` | number | Number of rows inserted |
|
||||
|
||||
### `rds_update`
|
||||
|
||||
Update data in an Amazon RDS table using the Data API
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Yes | AWS region \(e.g., us-east-1\) |
|
||||
| `accessKeyId` | string | Yes | AWS access key ID |
|
||||
| `secretAccessKey` | string | Yes | AWS secret access key |
|
||||
| `resourceArn` | string | Yes | ARN of the Aurora DB cluster |
|
||||
| `secretArn` | string | Yes | ARN of the Secrets Manager secret containing DB credentials |
|
||||
| `database` | string | No | Database name \(optional\) |
|
||||
| `table` | string | Yes | Table name to update |
|
||||
| `data` | object | Yes | Data to update as key-value pairs |
|
||||
| `conditions` | object | Yes | Conditions for the update \(e.g., \{"id": 1\}\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Operation status message |
|
||||
| `rows` | array | Array of updated rows |
|
||||
| `rowCount` | number | Number of rows updated |
|
||||
|
||||
### `rds_delete`
|
||||
|
||||
Delete data from an Amazon RDS table using the Data API
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Yes | AWS region \(e.g., us-east-1\) |
|
||||
| `accessKeyId` | string | Yes | AWS access key ID |
|
||||
| `secretAccessKey` | string | Yes | AWS secret access key |
|
||||
| `resourceArn` | string | Yes | ARN of the Aurora DB cluster |
|
||||
| `secretArn` | string | Yes | ARN of the Secrets Manager secret containing DB credentials |
|
||||
| `database` | string | No | Database name \(optional\) |
|
||||
| `table` | string | Yes | Table name to delete from |
|
||||
| `conditions` | object | Yes | Conditions for the delete \(e.g., \{"id": 1\}\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Operation status message |
|
||||
| `rows` | array | Array of deleted rows |
|
||||
| `rowCount` | number | Number of rows deleted |
|
||||
|
||||
### `rds_execute`
|
||||
|
||||
Execute raw SQL on Amazon RDS using the Data API
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Yes | AWS region \(e.g., us-east-1\) |
|
||||
| `accessKeyId` | string | Yes | AWS access key ID |
|
||||
| `secretAccessKey` | string | Yes | AWS secret access key |
|
||||
| `resourceArn` | string | Yes | ARN of the Aurora DB cluster |
|
||||
| `secretArn` | string | Yes | ARN of the Secrets Manager secret containing DB credentials |
|
||||
| `database` | string | No | Database name \(optional\) |
|
||||
| `query` | string | Yes | Raw SQL query to execute |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Operation status message |
|
||||
| `rows` | array | Array of rows returned or affected |
|
||||
| `rowCount` | number | Number of rows affected |
|
||||
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
- Category: `tools`
|
||||
- Type: `rds`
|
||||
@@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="s3"
|
||||
color="#E0E0E0"
|
||||
color="linear-gradient(45deg, #1B660F 0%, #6CAE3E 100%)"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
|
||||
188
apps/docs/content/docs/es/tools/dynamodb.mdx
Normal file
188
apps/docs/content/docs/es/tools/dynamodb.mdx
Normal file
@@ -0,0 +1,188 @@
|
||||
---
|
||||
title: Amazon DynamoDB
|
||||
description: Conectar a Amazon DynamoDB
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="dynamodb"
|
||||
color="linear-gradient(45deg, #2E27AD 0%, #527FFF 100%)"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
[Amazon DynamoDB](https://aws.amazon.com/dynamodb/) es un servicio de base de datos NoSQL completamente administrado ofrecido por AWS que proporciona un rendimiento rápido y predecible con escalabilidad perfecta. DynamoDB te permite almacenar y recuperar cualquier cantidad de datos y atender cualquier nivel de tráfico de solicitudes, sin necesidad de administrar hardware o infraestructura.
|
||||
|
||||
Con DynamoDB, puedes:
|
||||
|
||||
- **Obtener elementos**: Buscar elementos en tus tablas usando claves primarias
|
||||
- **Poner elementos**: Añadir o reemplazar elementos en tus tablas
|
||||
- **Consultar elementos**: Recuperar múltiples elementos usando consultas a través de índices
|
||||
- **Escanear tablas**: Leer todos o parte de los datos en una tabla
|
||||
- **Actualizar elementos**: Modificar atributos específicos de elementos existentes
|
||||
- **Eliminar elementos**: Eliminar registros de tus tablas
|
||||
|
||||
En Sim, la integración con DynamoDB permite a tus agentes acceder y manipular de forma segura las tablas de DynamoDB utilizando credenciales de AWS. Las operaciones compatibles incluyen:
|
||||
|
||||
- **Get**: Recuperar un elemento por su clave
|
||||
- **Put**: Insertar o sobrescribir elementos
|
||||
- **Query**: Ejecutar consultas utilizando condiciones de clave y filtros
|
||||
- **Scan**: Leer múltiples elementos escaneando la tabla o índice
|
||||
- **Update**: Cambiar atributos específicos de uno o más elementos
|
||||
- **Delete**: Eliminar un elemento de una tabla
|
||||
|
||||
Esta integración permite a los agentes de Sim automatizar tareas de gestión de datos dentro de tus tablas de DynamoDB de forma programática, para que puedas crear flujos de trabajo que gestionen, modifiquen y recuperen datos NoSQL escalables sin esfuerzo manual ni gestión de servidores.
|
||||
{/* MANUAL-CONTENT-END */}
|
||||
|
||||
## Instrucciones de uso
|
||||
|
||||
Integra Amazon DynamoDB en flujos de trabajo. Compatible con operaciones Get, Put, Query, Scan, Update y Delete en tablas de DynamoDB.
|
||||
|
||||
## Herramientas
|
||||
|
||||
### `dynamodb_get`
|
||||
|
||||
Obtener un elemento de una tabla DynamoDB mediante clave primaria
|
||||
|
||||
#### Entrada
|
||||
|
||||
| Parámetro | Tipo | Obligatorio | Descripción |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Sí | Región de AWS \(p. ej., us-east-1\) |
|
||||
| `accessKeyId` | string | Sí | ID de clave de acceso de AWS |
|
||||
| `secretAccessKey` | string | Sí | Clave de acceso secreta de AWS |
|
||||
| `tableName` | string | Sí | Nombre de la tabla DynamoDB |
|
||||
| `key` | object | Sí | Clave primaria del elemento a recuperar |
|
||||
| `consistentRead` | boolean | No | Usar lectura fuertemente consistente |
|
||||
|
||||
#### Salida
|
||||
|
||||
| Parámetro | Tipo | Descripción |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Mensaje de estado de la operación |
|
||||
| `item` | object | Elemento recuperado |
|
||||
|
||||
### `dynamodb_put`
|
||||
|
||||
Poner un elemento en una tabla DynamoDB
|
||||
|
||||
#### Entrada
|
||||
|
||||
| Parámetro | Tipo | Obligatorio | Descripción |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Sí | Región de AWS \(p. ej., us-east-1\) |
|
||||
| `accessKeyId` | string | Sí | ID de clave de acceso de AWS |
|
||||
| `secretAccessKey` | string | Sí | Clave de acceso secreta de AWS |
|
||||
| `tableName` | string | Sí | Nombre de la tabla DynamoDB |
|
||||
| `item` | object | Sí | Elemento a poner en la tabla |
|
||||
|
||||
#### Salida
|
||||
|
||||
| Parámetro | Tipo | Descripción |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Mensaje de estado de la operación |
|
||||
| `item` | object | Elemento creado |
|
||||
|
||||
### `dynamodb_query`
|
||||
|
||||
Consultar elementos de una tabla DynamoDB usando condiciones de clave
|
||||
|
||||
#### Entrada
|
||||
|
||||
| Parámetro | Tipo | Obligatorio | Descripción |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Sí | Región de AWS \(p. ej., us-east-1\) |
|
||||
| `accessKeyId` | string | Sí | ID de clave de acceso de AWS |
|
||||
| `secretAccessKey` | string | Sí | Clave de acceso secreta de AWS |
|
||||
| `tableName` | string | Sí | Nombre de la tabla DynamoDB |
|
||||
| `keyConditionExpression` | string | Sí | Expresión de condición de clave \(p. ej., "pk = :pk"\) |
|
||||
| `filterExpression` | string | No | Expresión de filtro para resultados |
|
||||
| `expressionAttributeNames` | object | No | Mapeos de nombres de atributos para palabras reservadas |
|
||||
| `expressionAttributeValues` | object | No | Valores de atributos de expresión |
|
||||
| `indexName` | string | No | Nombre del índice secundario para consultar |
|
||||
| `limit` | number | No | Número máximo de elementos a devolver |
|
||||
|
||||
#### Salida
|
||||
|
||||
| Parámetro | Tipo | Descripción |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Mensaje de estado de la operación |
|
||||
| `items` | array | Array de elementos devueltos |
|
||||
| `count` | number | Número de elementos devueltos |
|
||||
|
||||
### `dynamodb_scan`
|
||||
|
||||
Escanear todos los elementos en una tabla DynamoDB
|
||||
|
||||
#### Entrada
|
||||
|
||||
| Parámetro | Tipo | Obligatorio | Descripción |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Sí | Región de AWS \(p. ej., us-east-1\) |
|
||||
| `accessKeyId` | string | Sí | ID de clave de acceso de AWS |
|
||||
| `secretAccessKey` | string | Sí | Clave de acceso secreta de AWS |
|
||||
| `tableName` | string | Sí | Nombre de la tabla DynamoDB |
|
||||
| `filterExpression` | string | No | Expresión de filtro para resultados |
|
||||
| `projectionExpression` | string | No | Atributos a recuperar |
|
||||
| `expressionAttributeNames` | object | No | Mapeos de nombres de atributos para palabras reservadas |
|
||||
| `expressionAttributeValues` | object | No | Valores de atributos de expresión |
|
||||
| `limit` | number | No | Número máximo de elementos a devolver |
|
||||
|
||||
#### Salida
|
||||
|
||||
| Parámetro | Tipo | Descripción |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Mensaje de estado de la operación |
|
||||
| `items` | array | Array de elementos devueltos |
|
||||
| `count` | number | Número de elementos devueltos |
|
||||
|
||||
### `dynamodb_update`
|
||||
|
||||
Actualizar un elemento en una tabla de DynamoDB
|
||||
|
||||
#### Entrada
|
||||
|
||||
| Parámetro | Tipo | Obligatorio | Descripción |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Sí | Región de AWS \(p. ej., us-east-1\) |
|
||||
| `accessKeyId` | string | Sí | ID de clave de acceso de AWS |
|
||||
| `secretAccessKey` | string | Sí | Clave de acceso secreta de AWS |
|
||||
| `tableName` | string | Sí | Nombre de la tabla de DynamoDB |
|
||||
| `key` | object | Sí | Clave primaria del elemento a actualizar |
|
||||
| `updateExpression` | string | Sí | Expresión de actualización \(p. ej., "SET #name = :name"\) |
|
||||
| `expressionAttributeNames` | object | No | Mapeos de nombres de atributos para palabras reservadas |
|
||||
| `expressionAttributeValues` | object | No | Valores de atributos de expresión |
|
||||
| `conditionExpression` | string | No | Condición que debe cumplirse para que la actualización tenga éxito |
|
||||
|
||||
#### Salida
|
||||
|
||||
| Parámetro | Tipo | Descripción |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Mensaje de estado de la operación |
|
||||
| `item` | object | Elemento actualizado |
|
||||
|
||||
### `dynamodb_delete`
|
||||
|
||||
Eliminar un elemento de una tabla de DynamoDB
|
||||
|
||||
#### Entrada
|
||||
|
||||
| Parámetro | Tipo | Obligatorio | Descripción |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Sí | Región de AWS \(p. ej., us-east-1\) |
|
||||
| `accessKeyId` | string | Sí | ID de clave de acceso de AWS |
|
||||
| `secretAccessKey` | string | Sí | Clave de acceso secreta de AWS |
|
||||
| `tableName` | string | Sí | Nombre de la tabla de DynamoDB |
|
||||
| `key` | object | Sí | Clave primaria del elemento a eliminar |
|
||||
| `conditionExpression` | string | No | Condición que debe cumplirse para que la eliminación tenga éxito |
|
||||
|
||||
#### Salida
|
||||
|
||||
| Parámetro | Tipo | Descripción |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Mensaje de estado de la operación |
|
||||
|
||||
## Notas
|
||||
|
||||
- Categoría: `tools`
|
||||
- Tipo: `dynamodb`
|
||||
168
apps/docs/content/docs/es/tools/rds.mdx
Normal file
168
apps/docs/content/docs/es/tools/rds.mdx
Normal file
@@ -0,0 +1,168 @@
|
||||
---
|
||||
title: Amazon RDS
|
||||
description: Conéctate a Amazon RDS a través de Data API
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="rds"
|
||||
color="linear-gradient(45deg, #2E27AD 0%, #527FFF 100%)"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
[Amazon RDS Aurora Serverless](https://aws.amazon.com/rds/aurora/serverless/) es una base de datos relacional completamente administrada que se inicia, se apaga y escala automáticamente según las necesidades de tu aplicación. Te permite ejecutar bases de datos SQL en la nube sin tener que administrar servidores de bases de datos.
|
||||
|
||||
Con RDS Aurora Serverless, puedes:
|
||||
|
||||
- **Consultar datos**: Ejecutar consultas SQL flexibles en tus tablas
|
||||
- **Insertar nuevos registros**: Añadir datos a tu base de datos automáticamente
|
||||
- **Actualizar registros existentes**: Modificar datos en tus tablas usando filtros personalizados
|
||||
- **Eliminar registros**: Quitar datos no deseados utilizando criterios precisos
|
||||
- **Ejecutar SQL puro**: Ejecutar cualquier comando SQL válido compatible con Aurora
|
||||
|
||||
En Sim, la integración con RDS permite a tus agentes trabajar con bases de datos Amazon Aurora Serverless de forma segura y programática. Las operaciones compatibles incluyen:
|
||||
|
||||
- **Consulta**: Ejecutar SELECT y otras consultas SQL para obtener filas de tu base de datos
|
||||
- **Inserción**: Insertar nuevos registros en tablas con datos estructurados
|
||||
- **Actualización**: Cambiar datos en filas que coincidan con tus condiciones especificadas
|
||||
- **Eliminación**: Eliminar registros de una tabla mediante filtros o criterios personalizados
|
||||
- **Ejecución**: Ejecutar SQL puro para escenarios avanzados
|
||||
|
||||
Esta integración permite a tus agentes automatizar una amplia gama de operaciones de bases de datos sin intervención manual. Al conectar Sim con Amazon RDS, puedes crear agentes que gestionen, actualicen y recuperen datos relacionales dentro de tus flujos de trabajo, todo sin tener que manejar infraestructura o conexiones de bases de datos.
|
||||
{/* MANUAL-CONTENT-END */}
|
||||
|
||||
## Instrucciones de uso
|
||||
|
||||
Integra Amazon RDS Aurora Serverless en el flujo de trabajo utilizando la Data API. Puede consultar, insertar, actualizar, eliminar y ejecutar SQL puro sin administrar conexiones de base de datos.
|
||||
|
||||
## Herramientas
|
||||
|
||||
### `rds_query`
|
||||
|
||||
Ejecutar una consulta SELECT en Amazon RDS utilizando la API de datos
|
||||
|
||||
#### Entrada
|
||||
|
||||
| Parámetro | Tipo | Obligatorio | Descripción |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Sí | Región de AWS (p. ej., us-east-1) |
|
||||
| `accessKeyId` | string | Sí | ID de clave de acceso de AWS |
|
||||
| `secretAccessKey` | string | Sí | Clave de acceso secreta de AWS |
|
||||
| `resourceArn` | string | Sí | ARN del clúster de Aurora DB |
|
||||
| `secretArn` | string | Sí | ARN del secreto de Secrets Manager que contiene las credenciales de la base de datos |
|
||||
| `database` | string | No | Nombre de la base de datos (opcional) |
|
||||
| `query` | string | Sí | Consulta SQL SELECT para ejecutar |
|
||||
|
||||
#### Salida
|
||||
|
||||
| Parámetro | Tipo | Descripción |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Mensaje de estado de la operación |
|
||||
| `rows` | array | Array de filas devueltas por la consulta |
|
||||
| `rowCount` | number | Número de filas devueltas |
|
||||
|
||||
### `rds_insert`
|
||||
|
||||
Insertar datos en una tabla de Amazon RDS utilizando la API de datos
|
||||
|
||||
#### Entrada
|
||||
|
||||
| Parámetro | Tipo | Obligatorio | Descripción |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Sí | Región de AWS (p. ej., us-east-1) |
|
||||
| `accessKeyId` | string | Sí | ID de clave de acceso de AWS |
|
||||
| `secretAccessKey` | string | Sí | Clave de acceso secreta de AWS |
|
||||
| `resourceArn` | string | Sí | ARN del clúster de Aurora DB |
|
||||
| `secretArn` | string | Sí | ARN del secreto de Secrets Manager que contiene las credenciales de la base de datos |
|
||||
| `database` | string | No | Nombre de la base de datos (opcional) |
|
||||
| `table` | string | Sí | Nombre de la tabla donde insertar |
|
||||
| `data` | object | Sí | Datos a insertar como pares clave-valor |
|
||||
|
||||
#### Salida
|
||||
|
||||
| Parámetro | Tipo | Descripción |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Mensaje de estado de la operación |
|
||||
| `rows` | array | Array de filas insertadas |
|
||||
| `rowCount` | number | Número de filas insertadas |
|
||||
|
||||
### `rds_update`
|
||||
|
||||
Actualizar datos en una tabla de Amazon RDS utilizando la API de datos
|
||||
|
||||
#### Entrada
|
||||
|
||||
| Parámetro | Tipo | Obligatorio | Descripción |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Sí | Región de AWS (p. ej., us-east-1) |
|
||||
| `accessKeyId` | string | Sí | ID de clave de acceso de AWS |
|
||||
| `secretAccessKey` | string | Sí | Clave de acceso secreta de AWS |
|
||||
| `resourceArn` | string | Sí | ARN del clúster de Aurora DB |
|
||||
| `secretArn` | string | Sí | ARN del secreto de Secrets Manager que contiene las credenciales de la base de datos |
|
||||
| `database` | string | No | Nombre de la base de datos (opcional) |
|
||||
| `table` | string | Sí | Nombre de la tabla a actualizar |
|
||||
| `data` | object | Sí | Datos a actualizar como pares clave-valor |
|
||||
| `conditions` | object | Sí | Condiciones para la actualización (p. ej., `{"id": 1}`) |
|
||||
|
||||
#### Salida
|
||||
|
||||
| Parámetro | Tipo | Descripción |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Mensaje de estado de la operación |
|
||||
| `rows` | array | Array de filas actualizadas |
|
||||
| `rowCount` | number | Número de filas actualizadas |
|
||||
|
||||
### `rds_delete`
|
||||
|
||||
Eliminar datos de una tabla de Amazon RDS utilizando la API de datos
|
||||
|
||||
#### Entrada
|
||||
|
||||
| Parámetro | Tipo | Obligatorio | Descripción |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Sí | Región de AWS (p. ej., us-east-1) |
|
||||
| `accessKeyId` | string | Sí | ID de clave de acceso de AWS |
|
||||
| `secretAccessKey` | string | Sí | Clave de acceso secreta de AWS |
|
||||
| `resourceArn` | string | Sí | ARN del clúster de Aurora DB |
|
||||
| `secretArn` | string | Sí | ARN del secreto de Secrets Manager que contiene las credenciales de la base de datos |
|
||||
| `database` | string | No | Nombre de la base de datos (opcional) |
|
||||
| `table` | string | Sí | Nombre de la tabla de la que eliminar |
|
||||
| `conditions` | object | Sí | Condiciones para la eliminación (p. ej., `{"id": 1}`) |
|
||||
|
||||
#### Salida
|
||||
|
||||
| Parámetro | Tipo | Descripción |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Mensaje de estado de la operación |
|
||||
| `rows` | array | Array de filas eliminadas |
|
||||
| `rowCount` | number | Número de filas eliminadas |
|
||||
|
||||
### `rds_execute`
|
||||
|
||||
Ejecutar SQL sin procesar en Amazon RDS usando la API de datos
|
||||
|
||||
#### Entrada
|
||||
|
||||
| Parámetro | Tipo | Obligatorio | Descripción |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Sí | Región de AWS (p. ej., us-east-1) |
|
||||
| `accessKeyId` | string | Sí | ID de clave de acceso de AWS |
|
||||
| `secretAccessKey` | string | Sí | Clave de acceso secreta de AWS |
|
||||
| `resourceArn` | string | Sí | ARN del clúster de Aurora DB |
|
||||
| `secretArn` | string | Sí | ARN del secreto de Secrets Manager que contiene las credenciales de la base de datos |
|
||||
| `database` | string | No | Nombre de la base de datos (opcional) |
|
||||
| `query` | string | Sí | Consulta SQL sin procesar para ejecutar |
|
||||
|
||||
#### Salida
|
||||
|
||||
| Parámetro | Tipo | Descripción |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Mensaje de estado de la operación |
|
||||
| `rows` | array | Array de filas devueltas o afectadas |
|
||||
| `rowCount` | number | Número de filas afectadas |
|
||||
|
||||
## Notas
|
||||
|
||||
- Categoría: `tools`
|
||||
- Tipo: `rds`
|
||||
@@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="s3"
|
||||
color="#E0E0E0"
|
||||
color="linear-gradient(45deg, #1B660F 0%, #6CAE3E 100%)"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
|
||||
188
apps/docs/content/docs/fr/tools/dynamodb.mdx
Normal file
188
apps/docs/content/docs/fr/tools/dynamodb.mdx
Normal file
@@ -0,0 +1,188 @@
|
||||
---
|
||||
title: Amazon DynamoDB
|
||||
description: Connexion à Amazon DynamoDB
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="dynamodb"
|
||||
color="linear-gradient(45deg, #2E27AD 0%, #527FFF 100%)"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
[Amazon DynamoDB](https://aws.amazon.com/dynamodb/) est un service de base de données NoSQL entièrement géré proposé par AWS qui offre des performances rapides et prévisibles avec une évolutivité transparente. DynamoDB vous permet de stocker et de récupérer n'importe quelle quantité de données et gère n'importe quel niveau de trafic de requêtes, sans que vous ayez à gérer le matériel ou l'infrastructure.
|
||||
|
||||
Avec DynamoDB, vous pouvez :
|
||||
|
||||
- **Obtenir des éléments** : rechercher des éléments dans vos tables à l'aide de clés primaires
|
||||
- **Mettre des éléments** : ajouter ou remplacer des éléments dans vos tables
|
||||
- **Interroger des éléments** : récupérer plusieurs éléments à l'aide de requêtes sur les index
|
||||
- **Scanner des tables** : lire tout ou partie des données d'une table
|
||||
- **Mettre à jour des éléments** : modifier des attributs spécifiques d'éléments existants
|
||||
- **Supprimer des éléments** : supprimer des enregistrements de vos tables
|
||||
|
||||
Dans Sim, l'intégration DynamoDB permet à vos agents d'accéder en toute sécurité aux tables DynamoDB et de les manipuler à l'aide des identifiants AWS. Les opérations prises en charge comprennent :
|
||||
|
||||
- **Get** : récupérer un élément par sa clé
|
||||
- **Put** : insérer ou écraser des éléments
|
||||
- **Query** : exécuter des requêtes à l'aide de conditions de clé et de filtres
|
||||
- **Scan** : lire plusieurs éléments en scannant la table ou l'index
|
||||
- **Update** : modifier des attributs spécifiques d'un ou plusieurs éléments
|
||||
- **Delete** : supprimer un élément d'une table
|
||||
|
||||
Cette intégration permet aux agents Sim d'automatiser les tâches de gestion de données au sein de vos tables DynamoDB de manière programmatique, afin que vous puissiez créer des flux de travail qui gèrent, modifient et récupèrent des données NoSQL évolutives sans effort manuel ni gestion de serveur.
|
||||
{/* MANUAL-CONTENT-END */}
|
||||
|
||||
## Instructions d'utilisation
|
||||
|
||||
Intégrez Amazon DynamoDB dans les flux de travail. Prend en charge les opérations Get, Put, Query, Scan, Update et Delete sur les tables DynamoDB.
|
||||
|
||||
## Outils
|
||||
|
||||
### `dynamodb_get`
|
||||
|
||||
Récupérer un élément d'une table DynamoDB par clé primaire
|
||||
|
||||
#### Entrée
|
||||
|
||||
| Paramètre | Type | Obligatoire | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | chaîne | Oui | Région AWS (par ex., us-east-1) |
|
||||
| `accessKeyId` | chaîne | Oui | ID de clé d'accès AWS |
|
||||
| `secretAccessKey` | chaîne | Oui | Clé d'accès secrète AWS |
|
||||
| `tableName` | chaîne | Oui | Nom de la table DynamoDB |
|
||||
| `key` | objet | Oui | Clé primaire de l'élément à récupérer |
|
||||
| `consistentRead` | booléen | Non | Utiliser une lecture fortement cohérente |
|
||||
|
||||
#### Sortie
|
||||
|
||||
| Paramètre | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | chaîne | Message d'état de l'opération |
|
||||
| `item` | objet | Élément récupéré |
|
||||
|
||||
### `dynamodb_put`
|
||||
|
||||
Mettre un élément dans une table DynamoDB
|
||||
|
||||
#### Entrée
|
||||
|
||||
| Paramètre | Type | Obligatoire | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | chaîne | Oui | Région AWS (par ex., us-east-1) |
|
||||
| `accessKeyId` | chaîne | Oui | ID de clé d'accès AWS |
|
||||
| `secretAccessKey` | chaîne | Oui | Clé d'accès secrète AWS |
|
||||
| `tableName` | chaîne | Oui | Nom de la table DynamoDB |
|
||||
| `item` | objet | Oui | Élément à mettre dans la table |
|
||||
|
||||
#### Sortie
|
||||
|
||||
| Paramètre | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | chaîne | Message d'état de l'opération |
|
||||
| `item` | objet | Élément créé |
|
||||
|
||||
### `dynamodb_query`
|
||||
|
||||
Interroger les éléments d'une table DynamoDB à l'aide de conditions de clé
|
||||
|
||||
#### Entrée
|
||||
|
||||
| Paramètre | Type | Obligatoire | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | chaîne | Oui | Région AWS (par ex., us-east-1) |
|
||||
| `accessKeyId` | chaîne | Oui | ID de clé d'accès AWS |
|
||||
| `secretAccessKey` | chaîne | Oui | Clé d'accès secrète AWS |
|
||||
| `tableName` | chaîne | Oui | Nom de la table DynamoDB |
|
||||
| `keyConditionExpression` | chaîne | Oui | Expression de condition de clé (par ex., "pk = :pk") |
|
||||
| `filterExpression` | chaîne | Non | Expression de filtre pour les résultats |
|
||||
| `expressionAttributeNames` | objet | Non | Mappages de noms d'attributs pour les mots réservés |
|
||||
| `expressionAttributeValues` | objet | Non | Valeurs d'attributs d'expression |
|
||||
| `indexName` | chaîne | Non | Nom de l'index secondaire à interroger |
|
||||
| `limit` | nombre | Non | Nombre maximum d'éléments à retourner |
|
||||
|
||||
#### Sortie
|
||||
|
||||
| Paramètre | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | chaîne | Message d'état de l'opération |
|
||||
| `items` | tableau | Tableau des éléments retournés |
|
||||
| `count` | nombre | Nombre d'éléments retournés |
|
||||
|
||||
### `dynamodb_scan`
|
||||
|
||||
Scanner tous les éléments d'une table DynamoDB
|
||||
|
||||
#### Entrée
|
||||
|
||||
| Paramètre | Type | Obligatoire | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | chaîne | Oui | Région AWS (par ex., us-east-1) |
|
||||
| `accessKeyId` | chaîne | Oui | ID de clé d'accès AWS |
|
||||
| `secretAccessKey` | chaîne | Oui | Clé d'accès secrète AWS |
|
||||
| `tableName` | chaîne | Oui | Nom de la table DynamoDB |
|
||||
| `filterExpression` | chaîne | Non | Expression de filtre pour les résultats |
|
||||
| `projectionExpression` | chaîne | Non | Attributs à récupérer |
|
||||
| `expressionAttributeNames` | objet | Non | Mappages de noms d'attributs pour les mots réservés |
|
||||
| `expressionAttributeValues` | objet | Non | Valeurs d'attributs d'expression |
|
||||
| `limit` | nombre | Non | Nombre maximum d'éléments à retourner |
|
||||
|
||||
#### Sortie
|
||||
|
||||
| Paramètre | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Message d'état de l'opération |
|
||||
| `items` | array | Tableau des éléments retournés |
|
||||
| `count` | number | Nombre d'éléments retournés |
|
||||
|
||||
### `dynamodb_update`
|
||||
|
||||
Mettre à jour un élément dans une table DynamoDB
|
||||
|
||||
#### Entrée
|
||||
|
||||
| Paramètre | Type | Obligatoire | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Oui | Région AWS (par ex., us-east-1) |
|
||||
| `accessKeyId` | string | Oui | ID de clé d'accès AWS |
|
||||
| `secretAccessKey` | string | Oui | Clé d'accès secrète AWS |
|
||||
| `tableName` | string | Oui | Nom de la table DynamoDB |
|
||||
| `key` | object | Oui | Clé primaire de l'élément à mettre à jour |
|
||||
| `updateExpression` | string | Oui | Expression de mise à jour (par ex., "SET #name = :name") |
|
||||
| `expressionAttributeNames` | object | Non | Mappages de noms d'attributs pour les mots réservés |
|
||||
| `expressionAttributeValues` | object | Non | Valeurs d'attributs d'expression |
|
||||
| `conditionExpression` | string | Non | Condition qui doit être remplie pour que la mise à jour réussisse |
|
||||
|
||||
#### Sortie
|
||||
|
||||
| Paramètre | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Message d'état de l'opération |
|
||||
| `item` | object | Élément mis à jour |
|
||||
|
||||
### `dynamodb_delete`
|
||||
|
||||
Supprimer un élément d'une table DynamoDB
|
||||
|
||||
#### Entrée
|
||||
|
||||
| Paramètre | Type | Obligatoire | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Oui | Région AWS (par ex., us-east-1) |
|
||||
| `accessKeyId` | string | Oui | ID de clé d'accès AWS |
|
||||
| `secretAccessKey` | string | Oui | Clé d'accès secrète AWS |
|
||||
| `tableName` | string | Oui | Nom de la table DynamoDB |
|
||||
| `key` | object | Oui | Clé primaire de l'élément à supprimer |
|
||||
| `conditionExpression` | string | Non | Condition qui doit être remplie pour que la suppression réussisse |
|
||||
|
||||
#### Sortie
|
||||
|
||||
| Paramètre | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Message d'état de l'opération |
|
||||
|
||||
## Notes
|
||||
|
||||
- Catégorie : `tools`
|
||||
- Type : `dynamodb`
|
||||
168
apps/docs/content/docs/fr/tools/rds.mdx
Normal file
168
apps/docs/content/docs/fr/tools/rds.mdx
Normal file
@@ -0,0 +1,168 @@
|
||||
---
|
||||
title: Amazon RDS
|
||||
description: Connexion à Amazon RDS via l'API Data
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="rds"
|
||||
color="linear-gradient(45deg, #2E27AD 0%, #527FFF 100%)"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
[Amazon RDS Aurora Serverless](https://aws.amazon.com/rds/aurora/serverless/) est une base de données relationnelle entièrement gérée qui démarre, s'arrête et adapte automatiquement sa capacité en fonction des besoins de votre application. Elle vous permet d'exécuter des bases de données SQL dans le cloud sans avoir à gérer des serveurs de base de données.
|
||||
|
||||
Avec RDS Aurora Serverless, vous pouvez :
|
||||
|
||||
- **Interroger des données** : exécuter des requêtes SQL flexibles sur vos tables
|
||||
- **Insérer de nouveaux enregistrements** : ajouter automatiquement des données à votre base de données
|
||||
- **Mettre à jour des enregistrements existants** : modifier des données dans vos tables à l'aide de filtres personnalisés
|
||||
- **Supprimer des enregistrements** : éliminer les données indésirables en utilisant des critères précis
|
||||
- **Exécuter du SQL brut** : lancer toute commande SQL valide prise en charge par Aurora
|
||||
|
||||
Dans Sim, l'intégration RDS permet à vos agents de travailler avec les bases de données Amazon Aurora Serverless de manière sécurisée et programmatique. Les opérations prises en charge comprennent :
|
||||
|
||||
- **Requête** : exécuter des requêtes SELECT et autres requêtes SQL pour récupérer des lignes de votre base de données
|
||||
- **Insertion** : insérer de nouveaux enregistrements dans les tables avec des données structurées
|
||||
- **Mise à jour** : modifier les données dans les lignes qui correspondent à vos conditions spécifiées
|
||||
- **Suppression** : supprimer des enregistrements d'une table par filtres ou critères personnalisés
|
||||
- **Exécution** : exécuter du SQL brut pour des scénarios avancés
|
||||
|
||||
Cette intégration permet à vos agents d'automatiser un large éventail d'opérations de base de données sans intervention manuelle. En connectant Sim avec Amazon RDS, vous pouvez créer des agents qui gèrent, mettent à jour et récupèrent des données relationnelles dans vos flux de travail, le tout sans avoir à gérer l'infrastructure ou les connexions de base de données.
|
||||
{/* MANUAL-CONTENT-END */}
|
||||
|
||||
## Instructions d'utilisation
|
||||
|
||||
Intégrez Amazon RDS Aurora Serverless dans le flux de travail en utilisant l'API Data. Possibilité d'interroger, d'insérer, de mettre à jour, de supprimer et d'exécuter du SQL brut sans gérer les connexions à la base de données.
|
||||
|
||||
## Outils
|
||||
|
||||
### `rds_query`
|
||||
|
||||
Exécuter une requête SELECT sur Amazon RDS en utilisant l'API Data
|
||||
|
||||
#### Entrée
|
||||
|
||||
| Paramètre | Type | Obligatoire | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | chaîne | Oui | Région AWS \(ex., us-east-1\) |
|
||||
| `accessKeyId` | chaîne | Oui | ID de clé d'accès AWS |
|
||||
| `secretAccessKey` | chaîne | Oui | Clé d'accès secrète AWS |
|
||||
| `resourceArn` | chaîne | Oui | ARN du cluster Aurora DB |
|
||||
| `secretArn` | chaîne | Oui | ARN du secret Secrets Manager contenant les identifiants de la base de données |
|
||||
| `database` | chaîne | Non | Nom de la base de données \(facultatif\) |
|
||||
| `query` | chaîne | Oui | Requête SQL SELECT à exécuter |
|
||||
|
||||
#### Sortie
|
||||
|
||||
| Paramètre | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | chaîne | Message d'état de l'opération |
|
||||
| `rows` | tableau | Tableau des lignes retournées par la requête |
|
||||
| `rowCount` | nombre | Nombre de lignes retournées |
|
||||
|
||||
### `rds_insert`
|
||||
|
||||
Insérer des données dans une table Amazon RDS en utilisant l'API Data
|
||||
|
||||
#### Entrée
|
||||
|
||||
| Paramètre | Type | Obligatoire | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | chaîne | Oui | Région AWS \(ex., us-east-1\) |
|
||||
| `accessKeyId` | chaîne | Oui | ID de clé d'accès AWS |
|
||||
| `secretAccessKey` | chaîne | Oui | Clé d'accès secrète AWS |
|
||||
| `resourceArn` | chaîne | Oui | ARN du cluster Aurora DB |
|
||||
| `secretArn` | chaîne | Oui | ARN du secret Secrets Manager contenant les identifiants de la base de données |
|
||||
| `database` | chaîne | Non | Nom de la base de données \(facultatif\) |
|
||||
| `table` | chaîne | Oui | Nom de la table dans laquelle insérer |
|
||||
| `data` | objet | Oui | Données à insérer sous forme de paires clé-valeur |
|
||||
|
||||
#### Sortie
|
||||
|
||||
| Paramètre | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Message d'état de l'opération |
|
||||
| `rows` | array | Tableau des lignes insérées |
|
||||
| `rowCount` | number | Nombre de lignes insérées |
|
||||
|
||||
### `rds_update`
|
||||
|
||||
Mettre à jour des données dans une table Amazon RDS en utilisant l'API Data
|
||||
|
||||
#### Entrée
|
||||
|
||||
| Paramètre | Type | Obligatoire | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | Oui | Région AWS (par ex., us-east-1) |
|
||||
| `accessKeyId` | string | Oui | ID de clé d'accès AWS |
|
||||
| `secretAccessKey` | string | Oui | Clé d'accès secrète AWS |
|
||||
| `resourceArn` | string | Oui | ARN du cluster de base de données Aurora |
|
||||
| `secretArn` | string | Oui | ARN du secret Secrets Manager contenant les identifiants de la base de données |
|
||||
| `database` | string | Non | Nom de la base de données (facultatif) |
|
||||
| `table` | string | Oui | Nom de la table à mettre à jour |
|
||||
| `data` | object | Oui | Données à mettre à jour sous forme de paires clé-valeur |
|
||||
| `conditions` | object | Oui | Conditions pour la mise à jour (par ex., `{"id": 1}`) |
|
||||
|
||||
#### Sortie
|
||||
|
||||
| Paramètre | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Message d'état de l'opération |
|
||||
| `rows` | array | Tableau des lignes mises à jour |
|
||||
| `rowCount` | number | Nombre de lignes mises à jour |
|
||||
|
||||
### `rds_delete`
|
||||
|
||||
Supprimer des données d'une table Amazon RDS en utilisant l'API Data
|
||||
|
||||
#### Entrée
|
||||
|
||||
| Paramètre | Type | Obligatoire | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | chaîne | Oui | Région AWS (par ex., us-east-1) |
|
||||
| `accessKeyId` | chaîne | Oui | ID de clé d'accès AWS |
|
||||
| `secretAccessKey` | chaîne | Oui | Clé d'accès secrète AWS |
|
||||
| `resourceArn` | chaîne | Oui | ARN du cluster de base de données Aurora |
|
||||
| `secretArn` | chaîne | Oui | ARN du secret Secrets Manager contenant les identifiants de la base de données |
|
||||
| `database` | chaîne | Non | Nom de la base de données (facultatif) |
|
||||
| `table` | chaîne | Oui | Nom de la table à supprimer |
|
||||
| `conditions` | objet | Oui | Conditions pour la suppression (par ex., `{"id": 1}`) |
|
||||
|
||||
#### Sortie
|
||||
|
||||
| Paramètre | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | chaîne | Message d'état de l'opération |
|
||||
| `rows` | tableau | Tableau des lignes supprimées |
|
||||
| `rowCount` | nombre | Nombre de lignes supprimées |
|
||||
|
||||
### `rds_execute`
|
||||
|
||||
Exécuter du SQL brut sur Amazon RDS en utilisant l'API Data
|
||||
|
||||
#### Entrée
|
||||
|
||||
| Paramètre | Type | Obligatoire | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | chaîne | Oui | Région AWS (par ex., us-east-1) |
|
||||
| `accessKeyId` | chaîne | Oui | ID de clé d'accès AWS |
|
||||
| `secretAccessKey` | chaîne | Oui | Clé d'accès secrète AWS |
|
||||
| `resourceArn` | chaîne | Oui | ARN du cluster de base de données Aurora |
|
||||
| `secretArn` | chaîne | Oui | ARN du secret Secrets Manager contenant les identifiants de la base de données |
|
||||
| `database` | chaîne | Non | Nom de la base de données (facultatif) |
|
||||
| `query` | chaîne | Oui | Requête SQL brute à exécuter |
|
||||
|
||||
#### Sortie
|
||||
|
||||
| Paramètre | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | Message d'état de l'opération |
|
||||
| `rows` | array | Tableau des lignes retournées ou affectées |
|
||||
| `rowCount` | number | Nombre de lignes affectées |
|
||||
|
||||
## Notes
|
||||
|
||||
- Catégorie : `tools`
|
||||
- Type : `rds`
|
||||
@@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="s3"
|
||||
color="#E0E0E0"
|
||||
color="linear-gradient(45deg, #1B660F 0%, #6CAE3E 100%)"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
|
||||
188
apps/docs/content/docs/ja/tools/dynamodb.mdx
Normal file
188
apps/docs/content/docs/ja/tools/dynamodb.mdx
Normal file
@@ -0,0 +1,188 @@
|
||||
---
|
||||
title: Amazon DynamoDB
|
||||
description: Amazon DynamoDBに接続する
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="dynamodb"
|
||||
color="linear-gradient(45deg, #2E27AD 0%, #527FFF 100%)"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
[Amazon DynamoDB](https://aws.amazon.com/dynamodb/)はAWSが提供する完全マネージド型のNoSQLデータベースサービスで、シームレスなスケーラビリティを備えた高速で予測可能なパフォーマンスを提供します。DynamoDBを使用すると、ハードウェアやインフラストラクチャを管理する必要なく、任意の量のデータを保存および取得し、あらゆるレベルのリクエストトラフィックに対応できます。
|
||||
|
||||
DynamoDBでは、以下のことが可能です:
|
||||
|
||||
- **アイテムの取得**:プライマリキーを使用してテーブル内のアイテムを検索
|
||||
- **アイテムの配置**:テーブルにアイテムを追加または置換
|
||||
- **アイテムのクエリ**:インデックス全体でクエリを使用して複数のアイテムを取得
|
||||
- **テーブルのスキャン**:テーブル内のデータの全部または一部を読み取り
|
||||
- **アイテムの更新**:既存のアイテムの特定の属性を変更
|
||||
- **アイテムの削除**:テーブルからレコードを削除
|
||||
|
||||
Simでは、DynamoDB統合により、エージェントがAWS認証情報を使用してDynamoDBテーブルに安全にアクセスし操作することができます。サポートされている操作には以下が含まれます:
|
||||
|
||||
- **Get**:キーによるアイテムの取得
|
||||
- **Put**:アイテムの挿入または上書き
|
||||
- **Query**:キー条件とフィルターを使用したクエリの実行
|
||||
- **Scan**:テーブルまたはインデックスをスキャンして複数のアイテムを読み取り
|
||||
- **Update**:1つ以上のアイテムの特定の属性を変更
|
||||
- **Delete**:テーブルからアイテムを削除
|
||||
|
||||
この統合により、SimエージェントはプログラムによってDynamoDBテーブル内のデータ管理タスクを自動化できるようになり、手動の作業やサーバー管理なしでスケーラブルなNoSQLデータを管理、変更、取得するワークフローを構築できます。
|
||||
{/* MANUAL-CONTENT-END */}
|
||||
|
||||
## 使用方法
|
||||
|
||||
Amazon DynamoDBをワークフローに統合します。DynamoDBテーブルに対するGet、Put、Query、Scan、Update、Delete操作をサポートしています。
|
||||
|
||||
## ツール
|
||||
|
||||
### `dynamodb_get`
|
||||
|
||||
プライマリキーを使用してDynamoDBテーブルからアイテムを取得する
|
||||
|
||||
#### 入力
|
||||
|
||||
| パラメータ | 型 | 必須 | 説明 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | はい | AWSリージョン(例:us-east-1) |
|
||||
| `accessKeyId` | string | はい | AWSアクセスキーID |
|
||||
| `secretAccessKey` | string | はい | AWSシークレットアクセスキー |
|
||||
| `tableName` | string | はい | DynamoDBテーブル名 |
|
||||
| `key` | object | はい | 取得するアイテムのプライマリキー |
|
||||
| `consistentRead` | boolean | いいえ | 強力な整合性のある読み取りを使用する |
|
||||
|
||||
#### 出力
|
||||
|
||||
| パラメータ | 型 | 説明 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作ステータスメッセージ |
|
||||
| `item` | object | 取得したアイテム |
|
||||
|
||||
### `dynamodb_put`
|
||||
|
||||
DynamoDBテーブルにアイテムを追加する
|
||||
|
||||
#### 入力
|
||||
|
||||
| パラメータ | 型 | 必須 | 説明 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | はい | AWSリージョン(例:us-east-1) |
|
||||
| `accessKeyId` | string | はい | AWSアクセスキーID |
|
||||
| `secretAccessKey` | string | はい | AWSシークレットアクセスキー |
|
||||
| `tableName` | string | はい | DynamoDBテーブル名 |
|
||||
| `item` | object | はい | テーブルに追加するアイテム |
|
||||
|
||||
#### 出力
|
||||
|
||||
| パラメータ | 型 | 説明 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作ステータスメッセージ |
|
||||
| `item` | object | 作成されたアイテム |
|
||||
|
||||
### `dynamodb_query`
|
||||
|
||||
キー条件を使用してDynamoDBテーブルからアイテムをクエリする
|
||||
|
||||
#### 入力
|
||||
|
||||
| パラメータ | 型 | 必須 | 説明 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | はい | AWSリージョン(例:us-east-1) |
|
||||
| `accessKeyId` | string | はい | AWSアクセスキーID |
|
||||
| `secretAccessKey` | string | はい | AWSシークレットアクセスキー |
|
||||
| `tableName` | string | はい | DynamoDBテーブル名 |
|
||||
| `keyConditionExpression` | string | はい | キー条件式(例:"pk = :pk") |
|
||||
| `filterExpression` | string | いいえ | 結果のフィルター式 |
|
||||
| `expressionAttributeNames` | object | いいえ | 予約語の属性名マッピング |
|
||||
| `expressionAttributeValues` | object | いいえ | 式の属性値 |
|
||||
| `indexName` | string | いいえ | クエリするセカンダリインデックス名 |
|
||||
| `limit` | number | いいえ | 返すアイテムの最大数 |
|
||||
|
||||
#### 出力
|
||||
|
||||
| パラメータ | 型 | 説明 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作ステータスメッセージ |
|
||||
| `items` | array | 返されたアイテムの配列 |
|
||||
| `count` | number | 返されたアイテムの数 |
|
||||
|
||||
### `dynamodb_scan`
|
||||
|
||||
DynamoDBテーブル内のすべてのアイテムをスキャンする
|
||||
|
||||
#### 入力
|
||||
|
||||
| パラメータ | 型 | 必須 | 説明 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | はい | AWSリージョン(例:us-east-1) |
|
||||
| `accessKeyId` | string | はい | AWSアクセスキーID |
|
||||
| `secretAccessKey` | string | はい | AWSシークレットアクセスキー |
|
||||
| `tableName` | string | はい | DynamoDBテーブル名 |
|
||||
| `filterExpression` | string | いいえ | 結果のフィルター式 |
|
||||
| `projectionExpression` | string | いいえ | 取得する属性 |
|
||||
| `expressionAttributeNames` | object | いいえ | 予約語の属性名マッピング |
|
||||
| `expressionAttributeValues` | object | いいえ | 式の属性値 |
|
||||
| `limit` | number | いいえ | 返すアイテムの最大数 |
|
||||
|
||||
#### 出力
|
||||
|
||||
| パラメータ | 型 | 説明 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作ステータスメッセージ |
|
||||
| `items` | array | 返されたアイテムの配列 |
|
||||
| `count` | number | 返されたアイテム数 |
|
||||
|
||||
### `dynamodb_update`
|
||||
|
||||
DynamoDBテーブル内のアイテムを更新する
|
||||
|
||||
#### 入力
|
||||
|
||||
| パラメータ | 型 | 必須 | 説明 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | はい | AWSリージョン(例:us-east-1) |
|
||||
| `accessKeyId` | string | はい | AWSアクセスキーID |
|
||||
| `secretAccessKey` | string | はい | AWSシークレットアクセスキー |
|
||||
| `tableName` | string | はい | DynamoDBテーブル名 |
|
||||
| `key` | object | はい | 更新するアイテムのプライマリキー |
|
||||
| `updateExpression` | string | はい | 更新式(例:"SET #name = :name") |
|
||||
| `expressionAttributeNames` | object | いいえ | 予約語の属性名マッピング |
|
||||
| `expressionAttributeValues` | object | いいえ | 式の属性値 |
|
||||
| `conditionExpression` | string | いいえ | 更新が成功するために満たす必要がある条件 |
|
||||
|
||||
#### 出力
|
||||
|
||||
| パラメータ | 型 | 説明 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作ステータスメッセージ |
|
||||
| `item` | object | 更新されたアイテム |
|
||||
|
||||
### `dynamodb_delete`
|
||||
|
||||
DynamoDBテーブルからアイテムを削除する
|
||||
|
||||
#### 入力
|
||||
|
||||
| パラメータ | 型 | 必須 | 説明 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | はい | AWSリージョン(例:us-east-1) |
|
||||
| `accessKeyId` | string | はい | AWSアクセスキーID |
|
||||
| `secretAccessKey` | string | はい | AWSシークレットアクセスキー |
|
||||
| `tableName` | string | はい | DynamoDBテーブル名 |
|
||||
| `key` | object | はい | 削除するアイテムのプライマリキー |
|
||||
| `conditionExpression` | string | いいえ | 削除が成功するために満たす必要がある条件 |
|
||||
|
||||
#### 出力
|
||||
|
||||
| パラメータ | 型 | 説明 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作ステータスメッセージ |
|
||||
|
||||
## 注意事項
|
||||
|
||||
- カテゴリー: `tools`
|
||||
- タイプ: `dynamodb`
|
||||
168
apps/docs/content/docs/ja/tools/rds.mdx
Normal file
168
apps/docs/content/docs/ja/tools/rds.mdx
Normal file
@@ -0,0 +1,168 @@
|
||||
---
|
||||
title: Amazon RDS
|
||||
description: Data APIを通じてAmazon RDSに接続
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="rds"
|
||||
color="linear-gradient(45deg, #2E27AD 0%, #527FFF 100%)"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
[Amazon RDS Aurora Serverless](https://aws.amazon.com/rds/aurora/serverless/)は、アプリケーションのニーズに基づいて自動的に起動、シャットダウン、容量のスケーリングを行う完全マネージド型のリレーショナルデータベースです。データベースサーバーを管理することなく、クラウドでSQLデータベースを実行できます。
|
||||
|
||||
RDS Aurora Serverlessでは、以下のことが可能です:
|
||||
|
||||
- **データのクエリ**: テーブル間で柔軟なSQLクエリを実行
|
||||
- **新しいレコードの挿入**: データベースに自動的にデータを追加
|
||||
- **既存レコードの更新**: カスタムフィルターを使用してテーブル内のデータを変更
|
||||
- **レコードの削除**: 正確な条件を使用して不要なデータを削除
|
||||
- **生のSQLの実行**: Auroraでサポートされている有効なSQLコマンドを実行
|
||||
|
||||
Simでは、RDS統合により、エージェントがAmazon Aurora Serverlessデータベースを安全かつプログラム的に操作できるようになります。サポートされている操作には以下が含まれます:
|
||||
|
||||
- **クエリ**: SELECTやその他のSQLクエリを実行してデータベースから行を取得
|
||||
- **挿入**: 構造化データを使用してテーブルに新しいレコードを挿入
|
||||
- **更新**: 指定した条件に一致する行のデータを変更
|
||||
- **削除**: カスタムフィルターや条件によってテーブルからレコードを削除
|
||||
- **実行**: 高度なシナリオ向けに生のSQLを実行
|
||||
|
||||
この統合により、エージェントは手動介入なしに幅広いデータベース操作を自動化できます。SimとAmazon RDSを接続することで、ワークフロー内でリレーショナルデータを管理、更新、取得するエージェントを構築できます—すべてデータベースインフラストラクチャや接続を扱うことなく実現できます。
|
||||
{/* MANUAL-CONTENT-END */}
|
||||
|
||||
## 使用手順
|
||||
|
||||
Data APIを使用してAmazon RDS Aurora Serverlessをワークフローに統合します。データベース接続を管理することなく、クエリ、挿入、更新、削除、生のSQLの実行が可能です。
|
||||
|
||||
## ツール
|
||||
|
||||
### `rds_query`
|
||||
|
||||
Data APIを使用してAmazon RDSでSELECTクエリを実行する
|
||||
|
||||
#### 入力
|
||||
|
||||
| パラメータ | 型 | 必須 | 説明 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | はい | AWSリージョン(例:us-east-1) |
|
||||
| `accessKeyId` | string | はい | AWSアクセスキーID |
|
||||
| `secretAccessKey` | string | はい | AWSシークレットアクセスキー |
|
||||
| `resourceArn` | string | はい | Aurora DBクラスターのARN |
|
||||
| `secretArn` | string | はい | DB認証情報を含むSecrets ManagerシークレットのARN |
|
||||
| `database` | string | いいえ | データベース名(オプション) |
|
||||
| `query` | string | はい | 実行するSQL SELECTクエリ |
|
||||
|
||||
#### 出力
|
||||
|
||||
| パラメータ | 型 | 説明 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作ステータスメッセージ |
|
||||
| `rows` | array | クエリから返された行の配列 |
|
||||
| `rowCount` | number | 返された行数 |
|
||||
|
||||
### `rds_insert`
|
||||
|
||||
Data APIを使用してAmazon RDSテーブルにデータを挿入する
|
||||
|
||||
#### 入力
|
||||
|
||||
| パラメータ | 型 | 必須 | 説明 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | はい | AWSリージョン(例:us-east-1) |
|
||||
| `accessKeyId` | string | はい | AWSアクセスキーID |
|
||||
| `secretAccessKey` | string | はい | AWSシークレットアクセスキー |
|
||||
| `resourceArn` | string | はい | Aurora DBクラスターのARN |
|
||||
| `secretArn` | string | はい | DB認証情報を含むSecrets ManagerシークレットのARN |
|
||||
| `database` | string | いいえ | データベース名(オプション) |
|
||||
| `table` | string | はい | 挿入先のテーブル名 |
|
||||
| `data` | object | はい | キーと値のペアとして挿入するデータ |
|
||||
|
||||
#### 出力
|
||||
|
||||
| パラメータ | 型 | 説明 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作ステータスメッセージ |
|
||||
| `rows` | array | 挿入された行の配列 |
|
||||
| `rowCount` | number | 挿入された行数 |
|
||||
|
||||
### `rds_update`
|
||||
|
||||
Data APIを使用してAmazon RDSテーブルのデータを更新する
|
||||
|
||||
#### 入力
|
||||
|
||||
| パラメータ | 型 | 必須 | 説明 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | はい | AWSリージョン(例:us-east-1) |
|
||||
| `accessKeyId` | string | はい | AWSアクセスキーID |
|
||||
| `secretAccessKey` | string | はい | AWSシークレットアクセスキー |
|
||||
| `resourceArn` | string | はい | Aurora DBクラスターのARN |
|
||||
| `secretArn` | string | はい | DB認証情報を含むSecrets ManagerシークレットのARN |
|
||||
| `database` | string | いいえ | データベース名(オプション) |
|
||||
| `table` | string | はい | 更新するテーブル名 |
|
||||
| `data` | object | はい | キーと値のペアとして更新するデータ |
|
||||
| `conditions` | object | はい | 更新の条件(例:`{"id": 1}`) |
|
||||
|
||||
#### 出力
|
||||
|
||||
| パラメータ | 型 | 説明 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作ステータスメッセージ |
|
||||
| `rows` | array | 更新された行の配列 |
|
||||
| `rowCount` | number | 更新された行数 |
|
||||
|
||||
### `rds_delete`
|
||||
|
||||
Data APIを使用してAmazon RDSテーブルからデータを削除する
|
||||
|
||||
#### 入力
|
||||
|
||||
| パラメータ | 型 | 必須 | 説明 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | はい | AWS リージョン(例:us-east-1) |
|
||||
| `accessKeyId` | string | はい | AWS アクセスキーID |
|
||||
| `secretAccessKey` | string | はい | AWS シークレットアクセスキー |
|
||||
| `resourceArn` | string | はい | Aurora DBクラスターのARN |
|
||||
| `secretArn` | string | はい | DB認証情報を含むSecrets ManagerシークレットのARN |
|
||||
| `database` | string | いいえ | データベース名(オプション) |
|
||||
| `table` | string | はい | 削除対象のテーブル名 |
|
||||
| `conditions` | object | はい | 削除条件(例:`{"id": 1}`) |
|
||||
|
||||
#### 出力
|
||||
|
||||
| パラメータ | 型 | 説明 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作ステータスメッセージ |
|
||||
| `rows` | array | 削除された行の配列 |
|
||||
| `rowCount` | number | 削除された行数 |
|
||||
|
||||
### `rds_execute`
|
||||
|
||||
Data APIを使用してAmazon RDSで生のSQLを実行する
|
||||
|
||||
#### 入力
|
||||
|
||||
| パラメータ | 型 | 必須 | 説明 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | はい | AWS リージョン(例:us-east-1) |
|
||||
| `accessKeyId` | string | はい | AWS アクセスキーID |
|
||||
| `secretAccessKey` | string | はい | AWS シークレットアクセスキー |
|
||||
| `resourceArn` | string | はい | Aurora DBクラスターのARN |
|
||||
| `secretArn` | string | はい | DB認証情報を含むSecrets ManagerシークレットのARN |
|
||||
| `database` | string | いいえ | データベース名(オプション) |
|
||||
| `query` | string | はい | 実行する生のSQLクエリ |
|
||||
|
||||
#### 出力
|
||||
|
||||
| パラメータ | 型 | 説明 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作ステータスメッセージ |
|
||||
| `rows` | array | 返却または影響を受けた行の配列 |
|
||||
| `rowCount` | number | 影響を受けた行数 |
|
||||
|
||||
## 注意事項
|
||||
|
||||
- カテゴリー: `tools`
|
||||
- タイプ: `rds`
|
||||
@@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="s3"
|
||||
color="#E0E0E0"
|
||||
color="linear-gradient(45deg, #1B660F 0%, #6CAE3E 100%)"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
|
||||
188
apps/docs/content/docs/zh/tools/dynamodb.mdx
Normal file
188
apps/docs/content/docs/zh/tools/dynamodb.mdx
Normal file
@@ -0,0 +1,188 @@
|
||||
---
|
||||
title: Amazon DynamoDB
|
||||
description: 连接到 Amazon DynamoDB
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="dynamodb"
|
||||
color="linear-gradient(45deg, #2E27AD 0%, #527FFF 100%)"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
[Amazon DynamoDB](https://aws.amazon.com/dynamodb/) 是 AWS 提供的一项完全托管的 NoSQL 数据库服务,具有快速且可预测的性能,并支持无缝扩展。DynamoDB 允许您存储和检索任意数量的数据,并处理任何级别的请求流量,而无需您管理硬件或基础设施。
|
||||
|
||||
使用 DynamoDB,您可以:
|
||||
|
||||
- **获取项目**:使用主键查找表中的项目
|
||||
- **添加项目**:在表中添加或替换项目
|
||||
- **查询项目**:通过索引查询检索多个项目
|
||||
- **扫描表**:读取表中的全部或部分数据
|
||||
- **更新项目**:修改现有项目的特定属性
|
||||
- **删除项目**:从表中移除记录
|
||||
|
||||
在 Sim 中,DynamoDB 集成使您的代理能够使用 AWS 凭证安全地访问和操作 DynamoDB 表。支持的操作包括:
|
||||
|
||||
- **获取**:通过键检索项目
|
||||
- **添加**:插入或覆盖项目
|
||||
- **查询**:使用键条件和过滤器运行查询
|
||||
- **扫描**:通过扫描表或索引读取多个项目
|
||||
- **更新**:更改一个或多个项目的特定属性
|
||||
- **删除**:从表中移除项目
|
||||
|
||||
此集成使 Sim 代理能够以编程方式自动化管理 DynamoDB 表中的数据管理任务,从而构建无需手动操作或服务器管理的工作流,来管理、修改和检索可扩展的 NoSQL 数据。
|
||||
{/* MANUAL-CONTENT-END */}
|
||||
|
||||
## 使用说明
|
||||
|
||||
将 Amazon DynamoDB 集成到工作流中。支持对 DynamoDB 表执行获取、添加、查询、扫描、更新和删除操作。
|
||||
|
||||
## 工具
|
||||
|
||||
### `dynamodb_get`
|
||||
|
||||
通过主键从 DynamoDB 表中获取一个项目
|
||||
|
||||
#### 输入
|
||||
|
||||
| 参数 | 类型 | 必需 | 描述 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | 是 | AWS 区域 \(例如,us-east-1\) |
|
||||
| `accessKeyId` | string | 是 | AWS 访问密钥 ID |
|
||||
| `secretAccessKey` | string | 是 | AWS 秘密访问密钥 |
|
||||
| `tableName` | string | 是 | DynamoDB 表名 |
|
||||
| `key` | object | 是 | 要检索的项目主键 |
|
||||
| `consistentRead` | boolean | 否 | 使用强一致性读取 |
|
||||
|
||||
#### 输出
|
||||
|
||||
| 参数 | 类型 | 描述 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作状态消息 |
|
||||
| `item` | object | 检索到的项目 |
|
||||
|
||||
### `dynamodb_put`
|
||||
|
||||
将一个项目放入 DynamoDB 表中
|
||||
|
||||
#### 输入
|
||||
|
||||
| 参数 | 类型 | 必需 | 描述 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | 是 | AWS 区域 \(例如,us-east-1\) |
|
||||
| `accessKeyId` | string | 是 | AWS 访问密钥 ID |
|
||||
| `secretAccessKey` | string | 是 | AWS 秘密访问密钥 |
|
||||
| `tableName` | string | 是 | DynamoDB 表名 |
|
||||
| `item` | object | 是 | 要放入表中的项目 |
|
||||
|
||||
#### 输出
|
||||
|
||||
| 参数 | 类型 | 描述 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作状态消息 |
|
||||
| `item` | object | 创建的项目 |
|
||||
|
||||
### `dynamodb_query`
|
||||
|
||||
使用键条件从 DynamoDB 表中查询项目
|
||||
|
||||
#### 输入
|
||||
|
||||
| 参数 | 类型 | 必需 | 描述 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | 是 | AWS 区域 \(例如,us-east-1\) |
|
||||
| `accessKeyId` | string | 是 | AWS 访问密钥 ID |
|
||||
| `secretAccessKey` | string | 是 | AWS 秘密访问密钥 |
|
||||
| `tableName` | string | 是 | DynamoDB 表名 |
|
||||
| `keyConditionExpression` | string | 是 | 键条件表达式 \(例如,"pk = :pk"\) |
|
||||
| `filterExpression` | string | 否 | 结果的过滤表达式 |
|
||||
| `expressionAttributeNames` | object | 否 | 保留字的属性名称映射 |
|
||||
| `expressionAttributeValues` | object | 否 | 表达式属性值 |
|
||||
| `indexName` | string | 否 | 要查询的二级索引名称 |
|
||||
| `limit` | number | 否 | 要返回的最大项目数 |
|
||||
|
||||
#### 输出
|
||||
|
||||
| 参数 | 类型 | 描述 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作状态消息 |
|
||||
| `items` | array | 返回的项目数组 |
|
||||
| `count` | number | 返回的项目数量 |
|
||||
|
||||
### `dynamodb_scan`
|
||||
|
||||
扫描 DynamoDB 表中的所有项目
|
||||
|
||||
#### 输入
|
||||
|
||||
| 参数 | 类型 | 必需 | 描述 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | 是 | AWS 区域 \(例如,us-east-1\) |
|
||||
| `accessKeyId` | string | 是 | AWS 访问密钥 ID |
|
||||
| `secretAccessKey` | string | 是 | AWS 秘密访问密钥 |
|
||||
| `tableName` | string | 是 | DynamoDB 表名 |
|
||||
| `filterExpression` | string | 否 | 结果的过滤表达式 |
|
||||
| `projectionExpression` | string | 否 | 要检索的属性 |
|
||||
| `expressionAttributeNames` | object | 否 | 保留字的属性名称映射 |
|
||||
| `expressionAttributeValues` | object | 否 | 表达式属性值 |
|
||||
| `limit` | number | 否 | 要返回的最大项目数 |
|
||||
|
||||
#### 输出
|
||||
|
||||
| 参数 | 类型 | 描述 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作状态消息 |
|
||||
| `items` | array | 返回的项目数组 |
|
||||
| `count` | number | 返回的项目数量 |
|
||||
|
||||
### `dynamodb_update`
|
||||
|
||||
更新 DynamoDB 表中的项目
|
||||
|
||||
#### 输入
|
||||
|
||||
| 参数 | 类型 | 必需 | 描述 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | 是 | AWS 区域 \(例如,us-east-1\) |
|
||||
| `accessKeyId` | string | 是 | AWS 访问密钥 ID |
|
||||
| `secretAccessKey` | string | 是 | AWS 秘密访问密钥 |
|
||||
| `tableName` | string | 是 | DynamoDB 表名 |
|
||||
| `key` | object | 是 | 要更新项目的主键 |
|
||||
| `updateExpression` | string | 是 | 更新表达式 \(例如,"SET #name = :name"\) |
|
||||
| `expressionAttributeNames` | object | 否 | 保留字的属性名称映射 |
|
||||
| `expressionAttributeValues` | object | 否 | 表达式属性值 |
|
||||
| `conditionExpression` | string | 否 | 更新成功所需满足的条件 |
|
||||
|
||||
#### 输出
|
||||
|
||||
| 参数 | 类型 | 描述 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作状态消息 |
|
||||
| `item` | object | 更新后的项目 |
|
||||
|
||||
### `dynamodb_delete`
|
||||
|
||||
从 DynamoDB 表中删除项目
|
||||
|
||||
#### 输入
|
||||
|
||||
| 参数 | 类型 | 必需 | 描述 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | 是 | AWS 区域 \(例如,us-east-1\) |
|
||||
| `accessKeyId` | string | 是 | AWS 访问密钥 ID |
|
||||
| `secretAccessKey` | string | 是 | AWS 秘密访问密钥 |
|
||||
| `tableName` | string | 是 | DynamoDB 表名 |
|
||||
| `key` | object | 是 | 要删除项目的主键 |
|
||||
| `conditionExpression` | string | 否 | 删除成功所需满足的条件 |
|
||||
|
||||
#### 输出
|
||||
|
||||
| 参数 | 类型 | 描述 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作状态消息 |
|
||||
|
||||
## 注意
|
||||
|
||||
- 类别: `tools`
|
||||
- 类型: `dynamodb`
|
||||
168
apps/docs/content/docs/zh/tools/rds.mdx
Normal file
168
apps/docs/content/docs/zh/tools/rds.mdx
Normal file
@@ -0,0 +1,168 @@
|
||||
---
|
||||
title: Amazon RDS
|
||||
description: 通过 Data API 连接到 Amazon RDS
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="rds"
|
||||
color="linear-gradient(45deg, #2E27AD 0%, #527FFF 100%)"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
[Amazon RDS Aurora Serverless](https://aws.amazon.com/rds/aurora/serverless/) 是一种完全托管的关系型数据库,它会根据您的应用需求自动启动、关闭并调整容量。它允许您在云中运行 SQL 数据库,而无需管理数据库服务器。
|
||||
|
||||
使用 RDS Aurora Serverless,您可以:
|
||||
|
||||
- **查询数据**:在表中运行灵活的 SQL 查询
|
||||
- **插入新记录**:自动向数据库添加数据
|
||||
- **更新现有记录**:使用自定义筛选条件修改表中的数据
|
||||
- **删除记录**:通过精确的条件删除不需要的数据
|
||||
- **执行原始 SQL**:运行 Aurora 支持的任何有效 SQL 命令
|
||||
|
||||
在 Sim 中,RDS 集成使您的代理能够以安全且编程的方式与 Amazon Aurora Serverless 数据库交互。支持的操作包括:
|
||||
|
||||
- **查询**:运行 SELECT 和其他 SQL 查询以从数据库中获取行
|
||||
- **插入**:将新记录插入到具有结构化数据的表中
|
||||
- **更新**:更改符合指定条件的行中的数据
|
||||
- **删除**:通过自定义筛选条件从表中删除记录
|
||||
- **执行**:运行原始 SQL 以应对高级场景
|
||||
|
||||
此集成允许您的代理在无需人工干预的情况下自动化各种数据库操作。通过将 Sim 与 Amazon RDS 连接,您可以构建能够在工作流中管理、更新和检索关系数据的代理——无需处理数据库基础设施或连接。
|
||||
{/* MANUAL-CONTENT-END */}
|
||||
|
||||
## 使用说明
|
||||
|
||||
通过 Data API 将 Amazon RDS Aurora Serverless 集成到工作流中。可以查询、插入、更新、删除以及执行原始 SQL,而无需管理数据库连接。
|
||||
|
||||
## 工具
|
||||
|
||||
### `rds_query`
|
||||
|
||||
使用数据 API 在 Amazon RDS 上执行 SELECT 查询
|
||||
|
||||
#### 输入
|
||||
|
||||
| 参数 | 类型 | 必需 | 描述 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | 是 | AWS 区域 \(例如,us-east-1\) |
|
||||
| `accessKeyId` | string | 是 | AWS 访问密钥 ID |
|
||||
| `secretAccessKey` | string | 是 | AWS 秘密访问密钥 |
|
||||
| `resourceArn` | string | 是 | Aurora 数据库集群的 ARN |
|
||||
| `secretArn` | string | 是 | 包含数据库凭据的 Secrets Manager 密钥的 ARN |
|
||||
| `database` | string | 否 | 数据库名称 \(可选\) |
|
||||
| `query` | string | 是 | 要执行的 SQL SELECT 查询 |
|
||||
|
||||
#### 输出
|
||||
|
||||
| 参数 | 类型 | 描述 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作状态消息 |
|
||||
| `rows` | array | 查询返回的行数组 |
|
||||
| `rowCount` | number | 返回的行数 |
|
||||
|
||||
### `rds_insert`
|
||||
|
||||
使用数据 API 将数据插入 Amazon RDS 表
|
||||
|
||||
#### 输入
|
||||
|
||||
| 参数 | 类型 | 必需 | 描述 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | 是 | AWS 区域 \(例如,us-east-1\) |
|
||||
| `accessKeyId` | string | 是 | AWS 访问密钥 ID |
|
||||
| `secretAccessKey` | string | 是 | AWS 秘密访问密钥 |
|
||||
| `resourceArn` | string | 是 | Aurora 数据库集群的 ARN |
|
||||
| `secretArn` | string | 是 | 包含数据库凭据的 Secrets Manager 密钥的 ARN |
|
||||
| `database` | string | 否 | 数据库名称 \(可选\) |
|
||||
| `table` | string | 是 | 要插入的表名 |
|
||||
| `data` | object | 是 | 要插入的数据,作为键值对 |
|
||||
|
||||
#### 输出
|
||||
|
||||
| 参数 | 类型 | 描述 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作状态消息 |
|
||||
| `rows` | array | 插入行的数组 |
|
||||
| `rowCount` | number | 插入的行数 |
|
||||
|
||||
### `rds_update`
|
||||
|
||||
使用 Data API 更新 Amazon RDS 表中的数据
|
||||
|
||||
#### 输入
|
||||
|
||||
| 参数 | 类型 | 必需 | 描述 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | 是 | AWS 区域 \(例如,us-east-1\) |
|
||||
| `accessKeyId` | string | 是 | AWS 访问密钥 ID |
|
||||
| `secretAccessKey` | string | 是 | AWS 秘密访问密钥 |
|
||||
| `resourceArn` | string | 是 | Aurora 数据库集群的 ARN |
|
||||
| `secretArn` | string | 是 | 包含数据库凭据的 Secrets Manager 密钥的 ARN |
|
||||
| `database` | string | 否 | 数据库名称 \(可选\) |
|
||||
| `table` | string | 是 | 要更新的表名 |
|
||||
| `data` | object | 是 | 要更新的数据,作为键值对 |
|
||||
| `conditions` | object | 是 | 更新条件 \(例如,\{"id": 1\}\) |
|
||||
|
||||
#### 输出
|
||||
|
||||
| 参数 | 类型 | 描述 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作状态消息 |
|
||||
| `rows` | array | 更新行的数组 |
|
||||
| `rowCount` | number | 更新的行数 |
|
||||
|
||||
### `rds_delete`
|
||||
|
||||
使用 Data API 从 Amazon RDS 表中删除数据
|
||||
|
||||
#### 输入
|
||||
|
||||
| 参数 | 类型 | 必需 | 描述 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | 是 | AWS 区域 \(例如,us-east-1\) |
|
||||
| `accessKeyId` | string | 是 | AWS 访问密钥 ID |
|
||||
| `secretAccessKey` | string | 是 | AWS 秘密访问密钥 |
|
||||
| `resourceArn` | string | 是 | Aurora 数据库集群的 ARN |
|
||||
| `secretArn` | string | 是 | 包含数据库凭据的 Secrets Manager 密钥的 ARN |
|
||||
| `database` | string | 否 | 数据库名称 \(可选\) |
|
||||
| `table` | string | 是 | 要删除的表名 |
|
||||
| `conditions` | object | 是 | 删除条件 \(例如,\{"id": 1\}\) |
|
||||
|
||||
#### 输出
|
||||
|
||||
| 参数 | 类型 | 描述 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作状态消息 |
|
||||
| `rows` | array | 已删除行的数组 |
|
||||
| `rowCount` | number | 已删除行的数量 |
|
||||
|
||||
### `rds_execute`
|
||||
|
||||
使用 Data API 在 Amazon RDS 上执行原始 SQL
|
||||
|
||||
#### 输入
|
||||
|
||||
| 参数 | 类型 | 必需 | 描述 |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `region` | string | 是 | AWS 区域 \(例如,us-east-1\) |
|
||||
| `accessKeyId` | string | 是 | AWS 访问密钥 ID |
|
||||
| `secretAccessKey` | string | 是 | AWS 秘密访问密钥 |
|
||||
| `resourceArn` | string | 是 | Aurora 数据库集群的 ARN |
|
||||
| `secretArn` | string | 是 | 包含数据库凭据的 Secrets Manager 密钥的 ARN |
|
||||
| `database` | string | 否 | 数据库名称 \(可选\) |
|
||||
| `query` | string | 是 | 要执行的原始 SQL 查询 |
|
||||
|
||||
#### 输出
|
||||
|
||||
| 参数 | 类型 | 描述 |
|
||||
| --------- | ---- | ----------- |
|
||||
| `message` | string | 操作状态消息 |
|
||||
| `rows` | array | 返回或受影响的行数组 |
|
||||
| `rowCount` | number | 受影响的行数 |
|
||||
|
||||
## 注意
|
||||
|
||||
- 类别: `tools`
|
||||
- 类型: `rds`
|
||||
@@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="s3"
|
||||
color="#E0E0E0"
|
||||
color="linear-gradient(45deg, #1B660F 0%, #6CAE3E 100%)"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
|
||||
@@ -1028,7 +1028,7 @@ checksums:
|
||||
meta/title: cce1ae862f9851c02137f7be070e87bf
|
||||
meta/description: 9c24136d13767cf42d598ecd2cd7895b
|
||||
content/0: 1b031fb0c62c46b177aeed5c3d3f8f80
|
||||
content/1: 5cc75c9b77c8b8ee90fd3727b3b3e71a
|
||||
content/1: 4897888e9b93f43cfa08f08e01d63d45
|
||||
content/2: bd6df7d7d47e2f5a3562df04bb4c2be5
|
||||
content/3: a8184d3faf141c4c38d8a31b6374830d
|
||||
content/4: b0425d5c200cae7c869529ea3b8f7214
|
||||
@@ -47386,3 +47386,101 @@ checksums:
|
||||
content/14: 387026e7559d9305d0c39edb833e5dcc
|
||||
content/15: b3f310d5ef115bea5a8b75bf25d7ea9a
|
||||
content/16: 448c1ded449bcd1a71f9b589990e1e63
|
||||
0329dfb025ed7a18c4270a67b8e53e1d:
|
||||
meta/title: 985458a8500ac43c5066b77c5b7172a7
|
||||
meta/description: 3a9a5e355c6305088436e9e5295e5e74
|
||||
content/0: 1b031fb0c62c46b177aeed5c3d3f8f80
|
||||
content/1: 69eb63bb56f5c92f9a06a409fd06e127
|
||||
content/2: ceb73025bb48cd3988b5b75eef739ff8
|
||||
content/3: 155060ca67bead6a56e501f66d2a6f3e
|
||||
content/4: 7b84fdc9aa957bab919fe8e445a00127
|
||||
content/5: 35bef9915378b9fae2950c43b28d4c66
|
||||
content/6: c037e5ef2321d91a39c29c68b423e7d0
|
||||
content/7: 805694c6320ddd125301f4bd80948bc4
|
||||
content/8: 821e6394b0a953e2b0842b04ae8f3105
|
||||
content/9: 7b3b50d86217fa5327e2060db6dc79b1
|
||||
content/10: 9c8aa3f09c9b2bd50ea4cdff3598ea4e
|
||||
content/11: 4a83970297f02d066a140ace7a3ea574
|
||||
content/12: 3d0fd2cbd2fd3e61f4dfb545c979cc96
|
||||
content/13: 371d0e46b4bd2c23f559b8bc112f6955
|
||||
content/14: c6324e539565645847c9b7dc307edbb7
|
||||
content/15: bcadfc362b69078beee0088e5936c98b
|
||||
content/16: d2ae8b29edb03c531de32ab61bdb8199
|
||||
content/17: afae946bba1f0a5067cdeacb54f5ff31
|
||||
content/18: 9a9d552a9a22b6bd6ee4817cf156548c
|
||||
content/19: 371d0e46b4bd2c23f559b8bc112f6955
|
||||
content/20: 26c5931909354e24571974ccfd8e18f8
|
||||
content/21: bcadfc362b69078beee0088e5936c98b
|
||||
content/22: a6062bdeb33b01cee6c6341254b4f2ad
|
||||
content/23: 26f3623886a41211d0f929ea6877c370
|
||||
content/24: b7e6e86ed0a93dda08569bf6151ee889
|
||||
content/25: 371d0e46b4bd2c23f559b8bc112f6955
|
||||
content/26: 00608072da9103c89fe5a185645516d0
|
||||
content/27: bcadfc362b69078beee0088e5936c98b
|
||||
content/28: 1afd7403b0fe00913c06e1d69761b7eb
|
||||
content/29: acf650b1fbe371415a38e1740cba105d
|
||||
content/30: 01f378c57892b72e3d2d275aca9eaadf
|
||||
content/31: 371d0e46b4bd2c23f559b8bc112f6955
|
||||
content/32: abedb3d9f6ed8f86b76d315d08a2e42b
|
||||
content/33: bcadfc362b69078beee0088e5936c98b
|
||||
content/34: 8000c9a9f17a94f6145ebf73becfe558
|
||||
content/35: f4a9c229ff71084944a3a7684369a01f
|
||||
content/36: 7adc475d3c445bd57a77aedb9616da9a
|
||||
content/37: 371d0e46b4bd2c23f559b8bc112f6955
|
||||
content/38: 48c59e09ee36b3d9af3313be2ae5c6d0
|
||||
content/39: bcadfc362b69078beee0088e5936c98b
|
||||
content/40: 59480e97be4e274ddfe5dd8d7f695f05
|
||||
content/41: b3f310d5ef115bea5a8b75bf25d7ea9a
|
||||
content/42: 901ec146345636911d3cc074b6ebfd74
|
||||
451a43cd6440c2447809c9fdc08c7829:
|
||||
meta/title: cf7ddc77722328e80e5c60d3f42d5577
|
||||
meta/description: b6a942fcfafc8821473cacceb558b1f2
|
||||
content/0: 1b031fb0c62c46b177aeed5c3d3f8f80
|
||||
content/1: 4cf45dd008600c03d0c0549a05110d19
|
||||
content/2: 1543a4668fafc72bbba8fe509d5dae57
|
||||
content/3: aac6c43b00d999ae7b17b75ef4dc4fc0
|
||||
content/4: d083836bb2cd4e5a2876b554e3cd4ae8
|
||||
content/5: f1fad0adc2cd25d9a94d5e8d3d275a95
|
||||
content/6: 228f96649fa48a0fd2d234d21670ce2f
|
||||
content/7: 5c2e954b6ee98bea3f3fc6245549c362
|
||||
content/8: 821e6394b0a953e2b0842b04ae8f3105
|
||||
content/9: b57dad4eb1172e3b0f53009b7d1da96e
|
||||
content/10: 9c8aa3f09c9b2bd50ea4cdff3598ea4e
|
||||
content/11: 8562eed524a2e830528798b198c96561
|
||||
content/12: 6d9d0007b39670c814a81d610501932e
|
||||
content/13: 371d0e46b4bd2c23f559b8bc112f6955
|
||||
content/14: 6bf3965f5e253d978b652829301399dc
|
||||
content/15: bcadfc362b69078beee0088e5936c98b
|
||||
content/16: b7d1fb5e3ccc4a184957e304704a403a
|
||||
content/17: 808c733932b8cce795b7af43940d88fb
|
||||
content/18: bd99763a4125a2964039ae6220cfa9b8
|
||||
content/19: 371d0e46b4bd2c23f559b8bc112f6955
|
||||
content/20: 058c6fe90a3d5d08068c818c6ab1bce1
|
||||
content/21: bcadfc362b69078beee0088e5936c98b
|
||||
content/22: 55600ea367d0b75b0d731dfafe3c4d03
|
||||
content/23: af471c6ba3cf808dc02acc3aa174c6ac
|
||||
content/24: 6cf95280ce4e38cbb1236063867bb681
|
||||
content/25: 371d0e46b4bd2c23f559b8bc112f6955
|
||||
content/26: e8e70139db1670b1cce1a481ee6a4fec
|
||||
content/27: bcadfc362b69078beee0088e5936c98b
|
||||
content/28: f368f6303c8e1cd9670addb972c40dc7
|
||||
content/29: bc15e59ce2303dafb4f903468041ebfa
|
||||
content/30: 59c94fb79703463b63635dc5adf9dea8
|
||||
content/31: 371d0e46b4bd2c23f559b8bc112f6955
|
||||
content/32: ff866c458970452e2d9d0b418ece0466
|
||||
content/33: bcadfc362b69078beee0088e5936c98b
|
||||
content/34: f368f6303c8e1cd9670addb972c40dc7
|
||||
content/35: 32e29c637f05979f7609c5275ad8b4d6
|
||||
content/36: 667d37e37c9f801b9aabe30ad900686d
|
||||
content/37: 371d0e46b4bd2c23f559b8bc112f6955
|
||||
content/38: 7c963e0dcecc7000e73fa5a47a138953
|
||||
content/39: bcadfc362b69078beee0088e5936c98b
|
||||
content/40: 26051148e989cb79677c897f49d4f226
|
||||
content/41: 62cc98976187ecb6d598f16648eb4604
|
||||
content/42: e095759a2cc2de3b86130dfc21e87ff9
|
||||
content/43: 371d0e46b4bd2c23f559b8bc112f6955
|
||||
content/44: f5084008138beb64b1321b1bff0b6ccd
|
||||
content/45: bcadfc362b69078beee0088e5936c98b
|
||||
content/46: 1696af7fda8206f857591de089cea25c
|
||||
content/47: b3f310d5ef115bea5a8b75bf25d7ea9a
|
||||
content/48: 076d05c494cf5c494ed98e011b27b289
|
||||
|
||||
@@ -1,10 +1,39 @@
|
||||
'use client'
|
||||
|
||||
import type { SVGProps } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { StatusDotIcon } from '@/components/icons'
|
||||
import type { StatusType } from '@/app/api/status/types'
|
||||
import { useStatus } from '@/hooks/queries/status'
|
||||
|
||||
interface StatusDotIconProps extends SVGProps<SVGSVGElement> {
|
||||
status: 'operational' | 'degraded' | 'outage' | 'maintenance' | 'loading' | 'error'
|
||||
}
|
||||
|
||||
export function StatusDotIcon({ status, className, ...props }: StatusDotIconProps) {
|
||||
const colors = {
|
||||
operational: '#10B981',
|
||||
degraded: '#F59E0B',
|
||||
outage: '#EF4444',
|
||||
maintenance: '#3B82F6',
|
||||
loading: '#9CA3AF',
|
||||
error: '#9CA3AF',
|
||||
}
|
||||
|
||||
return (
|
||||
<svg
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
width={6}
|
||||
height={6}
|
||||
viewBox='0 0 6 6'
|
||||
fill='none'
|
||||
className={className}
|
||||
{...props}
|
||||
>
|
||||
<circle cx={3} cy={3} r={3} fill={colors[status]} />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
const STATUS_COLORS: Record<StatusType, string> = {
|
||||
operational: 'text-[#10B981] hover:text-[#059669]',
|
||||
degraded: 'text-[#F59E0B] hover:text-[#D97706]',
|
||||
|
||||
159
apps/sim/app/api/admin/import-workflow/route.ts
Normal file
159
apps/sim/app/api/admin/import-workflow/route.ts
Normal file
@@ -0,0 +1,159 @@
|
||||
import { db } from '@sim/db'
|
||||
import { user, workflow, workflowDeploymentVersion } from '@sim/db/schema'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { loadWorkflowFromNormalizedTables } from '@/lib/workflows/db-helpers'
|
||||
import { sanitizeForExport } from '@/lib/workflows/json-sanitizer'
|
||||
|
||||
const logger = createLogger('AdminImportWorkflowAPI')
|
||||
|
||||
const ImportWorkflowSchema = z.object({
|
||||
workflowId: z.string().min(1, 'Workflow ID is required'),
|
||||
targetWorkspaceId: z.string().min(1, 'Target workspace ID is required'),
|
||||
deploymentVersion: z.number().int().positive().optional(),
|
||||
})
|
||||
|
||||
/**
|
||||
* POST /api/admin/import-workflow
|
||||
* Export a workflow from database by ID (superuser only)
|
||||
*/
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const session = await getSession()
|
||||
if (!session?.user?.id) {
|
||||
logger.warn(`[${requestId}] Unauthorized import attempt`)
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
// Check if user is superuser
|
||||
const currentUser = await db
|
||||
.select({ isSuperUser: user.isSuperUser })
|
||||
.from(user)
|
||||
.where(eq(user.id, session.user.id))
|
||||
.limit(1)
|
||||
|
||||
if (!currentUser[0]?.isSuperUser) {
|
||||
logger.warn(`[${requestId}] Non-superuser attempted workflow import: ${session.user.id}`)
|
||||
return NextResponse.json({ error: 'Forbidden - Superuser access required' }, { status: 403 })
|
||||
}
|
||||
|
||||
const body = await request.json()
|
||||
const validation = ImportWorkflowSchema.safeParse(body)
|
||||
|
||||
if (!validation.success) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid request', details: validation.error.errors },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
const { workflowId, targetWorkspaceId, deploymentVersion } = validation.data
|
||||
|
||||
// Fetch workflow metadata
|
||||
const [workflowData] = await db
|
||||
.select()
|
||||
.from(workflow)
|
||||
.where(eq(workflow.id, workflowId))
|
||||
.limit(1)
|
||||
|
||||
if (!workflowData) {
|
||||
return NextResponse.json({ error: 'Workflow not found' }, { status: 404 })
|
||||
}
|
||||
|
||||
let workflowState: any
|
||||
let sourceLabel = 'current state'
|
||||
|
||||
if (deploymentVersion !== undefined) {
|
||||
// Load from deployment version
|
||||
const [deployedVersion] = await db
|
||||
.select({ state: workflowDeploymentVersion.state })
|
||||
.from(workflowDeploymentVersion)
|
||||
.where(
|
||||
and(
|
||||
eq(workflowDeploymentVersion.workflowId, workflowId),
|
||||
eq(workflowDeploymentVersion.version, deploymentVersion)
|
||||
)
|
||||
)
|
||||
.limit(1)
|
||||
|
||||
if (!deployedVersion?.state) {
|
||||
return NextResponse.json({ error: `Deployment version ${deploymentVersion} not found` }, { status: 404 })
|
||||
}
|
||||
|
||||
const deployedState = deployedVersion.state as any
|
||||
workflowState = {
|
||||
blocks: deployedState.blocks || {},
|
||||
edges: Array.isArray(deployedState.edges) ? deployedState.edges : [],
|
||||
loops: deployedState.loops || {},
|
||||
parallels: deployedState.parallels || {},
|
||||
metadata: {
|
||||
name: workflowData.name,
|
||||
description: workflowData.description ?? undefined,
|
||||
color: workflowData.color ?? undefined,
|
||||
},
|
||||
variables: Array.isArray(deployedState.variables) ? deployedState.variables : [],
|
||||
}
|
||||
sourceLabel = `deployment v${deploymentVersion}`
|
||||
} else {
|
||||
// Load current state from normalized tables
|
||||
const normalizedData = await loadWorkflowFromNormalizedTables(workflowId)
|
||||
|
||||
if (!normalizedData) {
|
||||
return NextResponse.json({ error: 'Workflow has no data' }, { status: 404 })
|
||||
}
|
||||
|
||||
let workflowVariables: any[] = []
|
||||
if (workflowData.variables && typeof workflowData.variables === 'object') {
|
||||
workflowVariables = Object.values(workflowData.variables).map((v: any) => ({
|
||||
id: v.id,
|
||||
name: v.name,
|
||||
type: v.type,
|
||||
value: v.value,
|
||||
}))
|
||||
}
|
||||
|
||||
workflowState = {
|
||||
blocks: normalizedData.blocks || {},
|
||||
edges: Array.isArray(normalizedData.edges) ? normalizedData.edges : [],
|
||||
loops: normalizedData.loops || {},
|
||||
parallels: normalizedData.parallels || {},
|
||||
metadata: {
|
||||
name: workflowData.name,
|
||||
description: workflowData.description ?? undefined,
|
||||
color: workflowData.color ?? undefined,
|
||||
},
|
||||
variables: workflowVariables,
|
||||
}
|
||||
}
|
||||
|
||||
const exportState = sanitizeForExport(workflowState)
|
||||
|
||||
logger.info(`[${requestId}] Exported workflow ${workflowId} (${sourceLabel})`)
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
workflow: exportState,
|
||||
metadata: {
|
||||
originalId: workflowId,
|
||||
originalName: workflowData.name,
|
||||
originalDescription: workflowData.description,
|
||||
targetWorkspaceId,
|
||||
deploymentVersion: deploymentVersion ?? null,
|
||||
source: sourceLabel,
|
||||
},
|
||||
})
|
||||
} catch (error) {
|
||||
logger.error(`[${requestId}] Error importing workflow:`, error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Failed to import workflow' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
65
apps/sim/app/api/admin/workflow-deployments/route.ts
Normal file
65
apps/sim/app/api/admin/workflow-deployments/route.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { db } from '@sim/db'
|
||||
import { user, workflowDeploymentVersion } from '@sim/db/schema'
|
||||
import { desc, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
|
||||
const logger = createLogger('AdminWorkflowDeploymentsAPI')
|
||||
|
||||
/**
|
||||
* GET /api/admin/workflow-deployments?workflowId=xxx
|
||||
* List all deployment versions for a workflow (superuser only)
|
||||
*/
|
||||
export async function GET(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const session = await getSession()
|
||||
if (!session?.user?.id) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
// Check if user is superuser
|
||||
const currentUser = await db
|
||||
.select({ isSuperUser: user.isSuperUser })
|
||||
.from(user)
|
||||
.where(eq(user.id, session.user.id))
|
||||
.limit(1)
|
||||
|
||||
if (!currentUser[0]?.isSuperUser) {
|
||||
return NextResponse.json({ error: 'Forbidden - Superuser access required' }, { status: 403 })
|
||||
}
|
||||
|
||||
const { searchParams } = new URL(request.url)
|
||||
const workflowId = searchParams.get('workflowId')
|
||||
|
||||
if (!workflowId) {
|
||||
return NextResponse.json({ error: 'workflowId query parameter is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
const versions = await db
|
||||
.select({
|
||||
id: workflowDeploymentVersion.id,
|
||||
version: workflowDeploymentVersion.version,
|
||||
name: workflowDeploymentVersion.name,
|
||||
isActive: workflowDeploymentVersion.isActive,
|
||||
createdAt: workflowDeploymentVersion.createdAt,
|
||||
createdBy: workflowDeploymentVersion.createdBy,
|
||||
deployedBy: user.name,
|
||||
})
|
||||
.from(workflowDeploymentVersion)
|
||||
.leftJoin(user, eq(workflowDeploymentVersion.createdBy, user.id))
|
||||
.where(eq(workflowDeploymentVersion.workflowId, workflowId))
|
||||
.orderBy(desc(workflowDeploymentVersion.version))
|
||||
|
||||
logger.info(`[${requestId}] Retrieved ${versions.length} deployments for workflow ${workflowId}`)
|
||||
|
||||
return NextResponse.json({ success: true, versions })
|
||||
} catch (error) {
|
||||
logger.error(`[${requestId}] Error listing deployments:`, error)
|
||||
return NextResponse.json({ error: 'Failed to list deployments' }, { status: 500 })
|
||||
}
|
||||
}
|
||||
|
||||
41
apps/sim/app/api/tools/dynamodb/delete/route.ts
Normal file
41
apps/sim/app/api/tools/dynamodb/delete/route.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { createDynamoDBClient, deleteItem } from '@/app/api/tools/dynamodb/utils'
|
||||
|
||||
const DeleteSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
tableName: z.string().min(1, 'Table name is required'),
|
||||
key: z.record(z.unknown()).refine((val) => Object.keys(val).length > 0, {
|
||||
message: 'Key is required',
|
||||
}),
|
||||
conditionExpression: z.string().optional(),
|
||||
})
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const body = await request.json()
|
||||
const validatedData = DeleteSchema.parse(body)
|
||||
|
||||
const client = createDynamoDBClient({
|
||||
region: validatedData.region,
|
||||
accessKeyId: validatedData.accessKeyId,
|
||||
secretAccessKey: validatedData.secretAccessKey,
|
||||
})
|
||||
|
||||
await deleteItem(
|
||||
client,
|
||||
validatedData.tableName,
|
||||
validatedData.key,
|
||||
validatedData.conditionExpression
|
||||
)
|
||||
|
||||
return NextResponse.json({
|
||||
message: 'Item deleted successfully',
|
||||
})
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'DynamoDB delete failed'
|
||||
return NextResponse.json({ error: errorMessage }, { status: 500 })
|
||||
}
|
||||
}
|
||||
48
apps/sim/app/api/tools/dynamodb/get/route.ts
Normal file
48
apps/sim/app/api/tools/dynamodb/get/route.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { createDynamoDBClient, getItem } from '@/app/api/tools/dynamodb/utils'
|
||||
|
||||
const GetSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
tableName: z.string().min(1, 'Table name is required'),
|
||||
key: z.record(z.unknown()).refine((val) => Object.keys(val).length > 0, {
|
||||
message: 'Key is required',
|
||||
}),
|
||||
consistentRead: z
|
||||
.union([z.boolean(), z.string()])
|
||||
.optional()
|
||||
.transform((val) => {
|
||||
if (val === true || val === 'true') return true
|
||||
return undefined
|
||||
}),
|
||||
})
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const body = await request.json()
|
||||
const validatedData = GetSchema.parse(body)
|
||||
|
||||
const client = createDynamoDBClient({
|
||||
region: validatedData.region,
|
||||
accessKeyId: validatedData.accessKeyId,
|
||||
secretAccessKey: validatedData.secretAccessKey,
|
||||
})
|
||||
|
||||
const result = await getItem(
|
||||
client,
|
||||
validatedData.tableName,
|
||||
validatedData.key,
|
||||
validatedData.consistentRead
|
||||
)
|
||||
|
||||
return NextResponse.json({
|
||||
message: result.item ? 'Item retrieved successfully' : 'Item not found',
|
||||
item: result.item,
|
||||
})
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'DynamoDB get failed'
|
||||
return NextResponse.json({ error: errorMessage }, { status: 500 })
|
||||
}
|
||||
}
|
||||
36
apps/sim/app/api/tools/dynamodb/put/route.ts
Normal file
36
apps/sim/app/api/tools/dynamodb/put/route.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { createDynamoDBClient, putItem } from '@/app/api/tools/dynamodb/utils'
|
||||
|
||||
const PutSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
tableName: z.string().min(1, 'Table name is required'),
|
||||
item: z.record(z.unknown()).refine((val) => Object.keys(val).length > 0, {
|
||||
message: 'Item is required',
|
||||
}),
|
||||
})
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const body = await request.json()
|
||||
const validatedData = PutSchema.parse(body)
|
||||
|
||||
const client = createDynamoDBClient({
|
||||
region: validatedData.region,
|
||||
accessKeyId: validatedData.accessKeyId,
|
||||
secretAccessKey: validatedData.secretAccessKey,
|
||||
})
|
||||
|
||||
await putItem(client, validatedData.tableName, validatedData.item)
|
||||
|
||||
return NextResponse.json({
|
||||
message: 'Item created successfully',
|
||||
item: validatedData.item,
|
||||
})
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'DynamoDB put failed'
|
||||
return NextResponse.json({ error: errorMessage }, { status: 500 })
|
||||
}
|
||||
}
|
||||
51
apps/sim/app/api/tools/dynamodb/query/route.ts
Normal file
51
apps/sim/app/api/tools/dynamodb/query/route.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { createDynamoDBClient, queryItems } from '@/app/api/tools/dynamodb/utils'
|
||||
|
||||
const QuerySchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
tableName: z.string().min(1, 'Table name is required'),
|
||||
keyConditionExpression: z.string().min(1, 'Key condition expression is required'),
|
||||
filterExpression: z.string().optional(),
|
||||
expressionAttributeNames: z.record(z.string()).optional(),
|
||||
expressionAttributeValues: z.record(z.unknown()).optional(),
|
||||
indexName: z.string().optional(),
|
||||
limit: z.number().positive().optional(),
|
||||
})
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const body = await request.json()
|
||||
const validatedData = QuerySchema.parse(body)
|
||||
|
||||
const client = createDynamoDBClient({
|
||||
region: validatedData.region,
|
||||
accessKeyId: validatedData.accessKeyId,
|
||||
secretAccessKey: validatedData.secretAccessKey,
|
||||
})
|
||||
|
||||
const result = await queryItems(
|
||||
client,
|
||||
validatedData.tableName,
|
||||
validatedData.keyConditionExpression,
|
||||
{
|
||||
filterExpression: validatedData.filterExpression,
|
||||
expressionAttributeNames: validatedData.expressionAttributeNames,
|
||||
expressionAttributeValues: validatedData.expressionAttributeValues,
|
||||
indexName: validatedData.indexName,
|
||||
limit: validatedData.limit,
|
||||
}
|
||||
)
|
||||
|
||||
return NextResponse.json({
|
||||
message: `Query returned ${result.count} items`,
|
||||
items: result.items,
|
||||
count: result.count,
|
||||
})
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'DynamoDB query failed'
|
||||
return NextResponse.json({ error: errorMessage }, { status: 500 })
|
||||
}
|
||||
}
|
||||
45
apps/sim/app/api/tools/dynamodb/scan/route.ts
Normal file
45
apps/sim/app/api/tools/dynamodb/scan/route.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { createDynamoDBClient, scanItems } from '@/app/api/tools/dynamodb/utils'
|
||||
|
||||
const ScanSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
tableName: z.string().min(1, 'Table name is required'),
|
||||
filterExpression: z.string().optional(),
|
||||
projectionExpression: z.string().optional(),
|
||||
expressionAttributeNames: z.record(z.string()).optional(),
|
||||
expressionAttributeValues: z.record(z.unknown()).optional(),
|
||||
limit: z.number().positive().optional(),
|
||||
})
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const body = await request.json()
|
||||
const validatedData = ScanSchema.parse(body)
|
||||
|
||||
const client = createDynamoDBClient({
|
||||
region: validatedData.region,
|
||||
accessKeyId: validatedData.accessKeyId,
|
||||
secretAccessKey: validatedData.secretAccessKey,
|
||||
})
|
||||
|
||||
const result = await scanItems(client, validatedData.tableName, {
|
||||
filterExpression: validatedData.filterExpression,
|
||||
projectionExpression: validatedData.projectionExpression,
|
||||
expressionAttributeNames: validatedData.expressionAttributeNames,
|
||||
expressionAttributeValues: validatedData.expressionAttributeValues,
|
||||
limit: validatedData.limit,
|
||||
})
|
||||
|
||||
return NextResponse.json({
|
||||
message: `Scan returned ${result.count} items`,
|
||||
items: result.items,
|
||||
count: result.count,
|
||||
})
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'DynamoDB scan failed'
|
||||
return NextResponse.json({ error: errorMessage }, { status: 500 })
|
||||
}
|
||||
}
|
||||
50
apps/sim/app/api/tools/dynamodb/update/route.ts
Normal file
50
apps/sim/app/api/tools/dynamodb/update/route.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { createDynamoDBClient, updateItem } from '@/app/api/tools/dynamodb/utils'
|
||||
|
||||
const UpdateSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
tableName: z.string().min(1, 'Table name is required'),
|
||||
key: z.record(z.unknown()).refine((val) => Object.keys(val).length > 0, {
|
||||
message: 'Key is required',
|
||||
}),
|
||||
updateExpression: z.string().min(1, 'Update expression is required'),
|
||||
expressionAttributeNames: z.record(z.string()).optional(),
|
||||
expressionAttributeValues: z.record(z.unknown()).optional(),
|
||||
conditionExpression: z.string().optional(),
|
||||
})
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const body = await request.json()
|
||||
const validatedData = UpdateSchema.parse(body)
|
||||
|
||||
const client = createDynamoDBClient({
|
||||
region: validatedData.region,
|
||||
accessKeyId: validatedData.accessKeyId,
|
||||
secretAccessKey: validatedData.secretAccessKey,
|
||||
})
|
||||
|
||||
const result = await updateItem(
|
||||
client,
|
||||
validatedData.tableName,
|
||||
validatedData.key,
|
||||
validatedData.updateExpression,
|
||||
{
|
||||
expressionAttributeNames: validatedData.expressionAttributeNames,
|
||||
expressionAttributeValues: validatedData.expressionAttributeValues,
|
||||
conditionExpression: validatedData.conditionExpression,
|
||||
}
|
||||
)
|
||||
|
||||
return NextResponse.json({
|
||||
message: 'Item updated successfully',
|
||||
item: result.attributes,
|
||||
})
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'DynamoDB update failed'
|
||||
return NextResponse.json({ error: errorMessage }, { status: 500 })
|
||||
}
|
||||
}
|
||||
174
apps/sim/app/api/tools/dynamodb/utils.ts
Normal file
174
apps/sim/app/api/tools/dynamodb/utils.ts
Normal file
@@ -0,0 +1,174 @@
|
||||
import { DynamoDBClient } from '@aws-sdk/client-dynamodb'
|
||||
import {
|
||||
DeleteCommand,
|
||||
DynamoDBDocumentClient,
|
||||
GetCommand,
|
||||
PutCommand,
|
||||
QueryCommand,
|
||||
ScanCommand,
|
||||
UpdateCommand,
|
||||
} from '@aws-sdk/lib-dynamodb'
|
||||
import type { DynamoDBConnectionConfig } from '@/tools/dynamodb/types'
|
||||
|
||||
export function createDynamoDBClient(config: DynamoDBConnectionConfig): DynamoDBDocumentClient {
|
||||
const client = new DynamoDBClient({
|
||||
region: config.region,
|
||||
credentials: {
|
||||
accessKeyId: config.accessKeyId,
|
||||
secretAccessKey: config.secretAccessKey,
|
||||
},
|
||||
})
|
||||
|
||||
return DynamoDBDocumentClient.from(client, {
|
||||
marshallOptions: {
|
||||
removeUndefinedValues: true,
|
||||
convertEmptyValues: false,
|
||||
},
|
||||
unmarshallOptions: {
|
||||
wrapNumbers: false,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export async function getItem(
|
||||
client: DynamoDBDocumentClient,
|
||||
tableName: string,
|
||||
key: Record<string, unknown>,
|
||||
consistentRead?: boolean
|
||||
): Promise<{ item: Record<string, unknown> | null }> {
|
||||
const command = new GetCommand({
|
||||
TableName: tableName,
|
||||
Key: key,
|
||||
ConsistentRead: consistentRead,
|
||||
})
|
||||
|
||||
const response = await client.send(command)
|
||||
return {
|
||||
item: (response.Item as Record<string, unknown>) || null,
|
||||
}
|
||||
}
|
||||
|
||||
export async function putItem(
|
||||
client: DynamoDBDocumentClient,
|
||||
tableName: string,
|
||||
item: Record<string, unknown>
|
||||
): Promise<{ success: boolean }> {
|
||||
const command = new PutCommand({
|
||||
TableName: tableName,
|
||||
Item: item,
|
||||
})
|
||||
|
||||
await client.send(command)
|
||||
return { success: true }
|
||||
}
|
||||
|
||||
export async function queryItems(
|
||||
client: DynamoDBDocumentClient,
|
||||
tableName: string,
|
||||
keyConditionExpression: string,
|
||||
options?: {
|
||||
filterExpression?: string
|
||||
expressionAttributeNames?: Record<string, string>
|
||||
expressionAttributeValues?: Record<string, unknown>
|
||||
indexName?: string
|
||||
limit?: number
|
||||
}
|
||||
): Promise<{ items: Record<string, unknown>[]; count: number }> {
|
||||
const command = new QueryCommand({
|
||||
TableName: tableName,
|
||||
KeyConditionExpression: keyConditionExpression,
|
||||
...(options?.filterExpression && { FilterExpression: options.filterExpression }),
|
||||
...(options?.expressionAttributeNames && {
|
||||
ExpressionAttributeNames: options.expressionAttributeNames,
|
||||
}),
|
||||
...(options?.expressionAttributeValues && {
|
||||
ExpressionAttributeValues: options.expressionAttributeValues,
|
||||
}),
|
||||
...(options?.indexName && { IndexName: options.indexName }),
|
||||
...(options?.limit && { Limit: options.limit }),
|
||||
})
|
||||
|
||||
const response = await client.send(command)
|
||||
return {
|
||||
items: (response.Items as Record<string, unknown>[]) || [],
|
||||
count: response.Count || 0,
|
||||
}
|
||||
}
|
||||
|
||||
export async function scanItems(
|
||||
client: DynamoDBDocumentClient,
|
||||
tableName: string,
|
||||
options?: {
|
||||
filterExpression?: string
|
||||
projectionExpression?: string
|
||||
expressionAttributeNames?: Record<string, string>
|
||||
expressionAttributeValues?: Record<string, unknown>
|
||||
limit?: number
|
||||
}
|
||||
): Promise<{ items: Record<string, unknown>[]; count: number }> {
|
||||
const command = new ScanCommand({
|
||||
TableName: tableName,
|
||||
...(options?.filterExpression && { FilterExpression: options.filterExpression }),
|
||||
...(options?.projectionExpression && { ProjectionExpression: options.projectionExpression }),
|
||||
...(options?.expressionAttributeNames && {
|
||||
ExpressionAttributeNames: options.expressionAttributeNames,
|
||||
}),
|
||||
...(options?.expressionAttributeValues && {
|
||||
ExpressionAttributeValues: options.expressionAttributeValues,
|
||||
}),
|
||||
...(options?.limit && { Limit: options.limit }),
|
||||
})
|
||||
|
||||
const response = await client.send(command)
|
||||
return {
|
||||
items: (response.Items as Record<string, unknown>[]) || [],
|
||||
count: response.Count || 0,
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateItem(
|
||||
client: DynamoDBDocumentClient,
|
||||
tableName: string,
|
||||
key: Record<string, unknown>,
|
||||
updateExpression: string,
|
||||
options?: {
|
||||
expressionAttributeNames?: Record<string, string>
|
||||
expressionAttributeValues?: Record<string, unknown>
|
||||
conditionExpression?: string
|
||||
}
|
||||
): Promise<{ attributes: Record<string, unknown> | null }> {
|
||||
const command = new UpdateCommand({
|
||||
TableName: tableName,
|
||||
Key: key,
|
||||
UpdateExpression: updateExpression,
|
||||
...(options?.expressionAttributeNames && {
|
||||
ExpressionAttributeNames: options.expressionAttributeNames,
|
||||
}),
|
||||
...(options?.expressionAttributeValues && {
|
||||
ExpressionAttributeValues: options.expressionAttributeValues,
|
||||
}),
|
||||
...(options?.conditionExpression && { ConditionExpression: options.conditionExpression }),
|
||||
ReturnValues: 'ALL_NEW',
|
||||
})
|
||||
|
||||
const response = await client.send(command)
|
||||
return {
|
||||
attributes: (response.Attributes as Record<string, unknown>) || null,
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteItem(
|
||||
client: DynamoDBDocumentClient,
|
||||
tableName: string,
|
||||
key: Record<string, unknown>,
|
||||
conditionExpression?: string
|
||||
): Promise<{ success: boolean }> {
|
||||
const command = new DeleteCommand({
|
||||
TableName: tableName,
|
||||
Key: key,
|
||||
...(conditionExpression && { ConditionExpression: conditionExpression }),
|
||||
})
|
||||
|
||||
await client.send(command)
|
||||
return { success: true }
|
||||
}
|
||||
74
apps/sim/app/api/tools/rds/delete/route.ts
Normal file
74
apps/sim/app/api/tools/rds/delete/route.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { createRdsClient, executeDelete } from '@/app/api/tools/rds/utils'
|
||||
|
||||
const logger = createLogger('RDSDeleteAPI')
|
||||
|
||||
const DeleteSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
resourceArn: z.string().min(1, 'Resource ARN is required'),
|
||||
secretArn: z.string().min(1, 'Secret ARN is required'),
|
||||
database: z.string().optional(),
|
||||
table: z.string().min(1, 'Table name is required'),
|
||||
conditions: z.record(z.unknown()).refine((obj) => Object.keys(obj).length > 0, {
|
||||
message: 'At least one condition is required',
|
||||
}),
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const body = await request.json()
|
||||
const params = DeleteSchema.parse(body)
|
||||
|
||||
logger.info(`[${requestId}] Deleting from RDS table ${params.table} in ${params.database}`)
|
||||
|
||||
const client = createRdsClient({
|
||||
region: params.region,
|
||||
accessKeyId: params.accessKeyId,
|
||||
secretAccessKey: params.secretAccessKey,
|
||||
resourceArn: params.resourceArn,
|
||||
secretArn: params.secretArn,
|
||||
database: params.database,
|
||||
})
|
||||
|
||||
try {
|
||||
const result = await executeDelete(
|
||||
client,
|
||||
params.resourceArn,
|
||||
params.secretArn,
|
||||
params.database,
|
||||
params.table,
|
||||
params.conditions
|
||||
)
|
||||
|
||||
logger.info(`[${requestId}] Delete executed successfully, affected ${result.rowCount} rows`)
|
||||
|
||||
return NextResponse.json({
|
||||
message: `Delete executed successfully. ${result.rowCount} row(s) deleted.`,
|
||||
rows: result.rows,
|
||||
rowCount: result.rowCount,
|
||||
})
|
||||
} finally {
|
||||
client.destroy()
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
logger.warn(`[${requestId}] Invalid request data`, { errors: error.errors })
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid request data', details: error.errors },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'
|
||||
logger.error(`[${requestId}] RDS delete failed:`, error)
|
||||
|
||||
return NextResponse.json({ error: `RDS delete failed: ${errorMessage}` }, { status: 500 })
|
||||
}
|
||||
}
|
||||
70
apps/sim/app/api/tools/rds/execute/route.ts
Normal file
70
apps/sim/app/api/tools/rds/execute/route.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { createRdsClient, executeStatement } from '@/app/api/tools/rds/utils'
|
||||
|
||||
const logger = createLogger('RDSExecuteAPI')
|
||||
|
||||
const ExecuteSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
resourceArn: z.string().min(1, 'Resource ARN is required'),
|
||||
secretArn: z.string().min(1, 'Secret ARN is required'),
|
||||
database: z.string().optional(),
|
||||
query: z.string().min(1, 'Query is required'),
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const body = await request.json()
|
||||
const params = ExecuteSchema.parse(body)
|
||||
|
||||
logger.info(`[${requestId}] Executing raw SQL on RDS database ${params.database}`)
|
||||
|
||||
const client = createRdsClient({
|
||||
region: params.region,
|
||||
accessKeyId: params.accessKeyId,
|
||||
secretAccessKey: params.secretAccessKey,
|
||||
resourceArn: params.resourceArn,
|
||||
secretArn: params.secretArn,
|
||||
database: params.database,
|
||||
})
|
||||
|
||||
try {
|
||||
const result = await executeStatement(
|
||||
client,
|
||||
params.resourceArn,
|
||||
params.secretArn,
|
||||
params.database,
|
||||
params.query
|
||||
)
|
||||
|
||||
logger.info(`[${requestId}] Execute completed successfully, affected ${result.rowCount} rows`)
|
||||
|
||||
return NextResponse.json({
|
||||
message: `Query executed successfully. ${result.rowCount} row(s) affected.`,
|
||||
rows: result.rows,
|
||||
rowCount: result.rowCount,
|
||||
})
|
||||
} finally {
|
||||
client.destroy()
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
logger.warn(`[${requestId}] Invalid request data`, { errors: error.errors })
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid request data', details: error.errors },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'
|
||||
logger.error(`[${requestId}] RDS execute failed:`, error)
|
||||
|
||||
return NextResponse.json({ error: `RDS execute failed: ${errorMessage}` }, { status: 500 })
|
||||
}
|
||||
}
|
||||
74
apps/sim/app/api/tools/rds/insert/route.ts
Normal file
74
apps/sim/app/api/tools/rds/insert/route.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { createRdsClient, executeInsert } from '@/app/api/tools/rds/utils'
|
||||
|
||||
const logger = createLogger('RDSInsertAPI')
|
||||
|
||||
const InsertSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
resourceArn: z.string().min(1, 'Resource ARN is required'),
|
||||
secretArn: z.string().min(1, 'Secret ARN is required'),
|
||||
database: z.string().optional(),
|
||||
table: z.string().min(1, 'Table name is required'),
|
||||
data: z.record(z.unknown()).refine((obj) => Object.keys(obj).length > 0, {
|
||||
message: 'Data object must have at least one field',
|
||||
}),
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const body = await request.json()
|
||||
const params = InsertSchema.parse(body)
|
||||
|
||||
logger.info(`[${requestId}] Inserting into RDS table ${params.table} in ${params.database}`)
|
||||
|
||||
const client = createRdsClient({
|
||||
region: params.region,
|
||||
accessKeyId: params.accessKeyId,
|
||||
secretAccessKey: params.secretAccessKey,
|
||||
resourceArn: params.resourceArn,
|
||||
secretArn: params.secretArn,
|
||||
database: params.database,
|
||||
})
|
||||
|
||||
try {
|
||||
const result = await executeInsert(
|
||||
client,
|
||||
params.resourceArn,
|
||||
params.secretArn,
|
||||
params.database,
|
||||
params.table,
|
||||
params.data
|
||||
)
|
||||
|
||||
logger.info(`[${requestId}] Insert executed successfully, affected ${result.rowCount} rows`)
|
||||
|
||||
return NextResponse.json({
|
||||
message: `Insert executed successfully. ${result.rowCount} row(s) inserted.`,
|
||||
rows: result.rows,
|
||||
rowCount: result.rowCount,
|
||||
})
|
||||
} finally {
|
||||
client.destroy()
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
logger.warn(`[${requestId}] Invalid request data`, { errors: error.errors })
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid request data', details: error.errors },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'
|
||||
logger.error(`[${requestId}] RDS insert failed:`, error)
|
||||
|
||||
return NextResponse.json({ error: `RDS insert failed: ${errorMessage}` }, { status: 500 })
|
||||
}
|
||||
}
|
||||
77
apps/sim/app/api/tools/rds/query/route.ts
Normal file
77
apps/sim/app/api/tools/rds/query/route.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { createRdsClient, executeStatement, validateQuery } from '@/app/api/tools/rds/utils'
|
||||
|
||||
const logger = createLogger('RDSQueryAPI')
|
||||
|
||||
const QuerySchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
resourceArn: z.string().min(1, 'Resource ARN is required'),
|
||||
secretArn: z.string().min(1, 'Secret ARN is required'),
|
||||
database: z.string().optional(),
|
||||
query: z.string().min(1, 'Query is required'),
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const body = await request.json()
|
||||
const params = QuerySchema.parse(body)
|
||||
|
||||
logger.info(`[${requestId}] Executing RDS query on ${params.database}`)
|
||||
|
||||
// Validate the query
|
||||
const validation = validateQuery(params.query)
|
||||
if (!validation.isValid) {
|
||||
logger.warn(`[${requestId}] Query validation failed: ${validation.error}`)
|
||||
return NextResponse.json({ error: validation.error }, { status: 400 })
|
||||
}
|
||||
|
||||
const client = createRdsClient({
|
||||
region: params.region,
|
||||
accessKeyId: params.accessKeyId,
|
||||
secretAccessKey: params.secretAccessKey,
|
||||
resourceArn: params.resourceArn,
|
||||
secretArn: params.secretArn,
|
||||
database: params.database,
|
||||
})
|
||||
|
||||
try {
|
||||
const result = await executeStatement(
|
||||
client,
|
||||
params.resourceArn,
|
||||
params.secretArn,
|
||||
params.database,
|
||||
params.query
|
||||
)
|
||||
|
||||
logger.info(`[${requestId}] Query executed successfully, returned ${result.rowCount} rows`)
|
||||
|
||||
return NextResponse.json({
|
||||
message: `Query executed successfully. ${result.rowCount} row(s) returned.`,
|
||||
rows: result.rows,
|
||||
rowCount: result.rowCount,
|
||||
})
|
||||
} finally {
|
||||
client.destroy()
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
logger.warn(`[${requestId}] Invalid request data`, { errors: error.errors })
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid request data', details: error.errors },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'
|
||||
logger.error(`[${requestId}] RDS query failed:`, error)
|
||||
|
||||
return NextResponse.json({ error: `RDS query failed: ${errorMessage}` }, { status: 500 })
|
||||
}
|
||||
}
|
||||
78
apps/sim/app/api/tools/rds/update/route.ts
Normal file
78
apps/sim/app/api/tools/rds/update/route.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { createRdsClient, executeUpdate } from '@/app/api/tools/rds/utils'
|
||||
|
||||
const logger = createLogger('RDSUpdateAPI')
|
||||
|
||||
const UpdateSchema = z.object({
|
||||
region: z.string().min(1, 'AWS region is required'),
|
||||
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
|
||||
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
|
||||
resourceArn: z.string().min(1, 'Resource ARN is required'),
|
||||
secretArn: z.string().min(1, 'Secret ARN is required'),
|
||||
database: z.string().optional(),
|
||||
table: z.string().min(1, 'Table name is required'),
|
||||
data: z.record(z.unknown()).refine((obj) => Object.keys(obj).length > 0, {
|
||||
message: 'Data object must have at least one field',
|
||||
}),
|
||||
conditions: z.record(z.unknown()).refine((obj) => Object.keys(obj).length > 0, {
|
||||
message: 'At least one condition is required',
|
||||
}),
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const body = await request.json()
|
||||
const params = UpdateSchema.parse(body)
|
||||
|
||||
logger.info(`[${requestId}] Updating RDS table ${params.table} in ${params.database}`)
|
||||
|
||||
const client = createRdsClient({
|
||||
region: params.region,
|
||||
accessKeyId: params.accessKeyId,
|
||||
secretAccessKey: params.secretAccessKey,
|
||||
resourceArn: params.resourceArn,
|
||||
secretArn: params.secretArn,
|
||||
database: params.database,
|
||||
})
|
||||
|
||||
try {
|
||||
const result = await executeUpdate(
|
||||
client,
|
||||
params.resourceArn,
|
||||
params.secretArn,
|
||||
params.database,
|
||||
params.table,
|
||||
params.data,
|
||||
params.conditions
|
||||
)
|
||||
|
||||
logger.info(`[${requestId}] Update executed successfully, affected ${result.rowCount} rows`)
|
||||
|
||||
return NextResponse.json({
|
||||
message: `Update executed successfully. ${result.rowCount} row(s) updated.`,
|
||||
rows: result.rows,
|
||||
rowCount: result.rowCount,
|
||||
})
|
||||
} finally {
|
||||
client.destroy()
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
logger.warn(`[${requestId}] Invalid request data`, { errors: error.errors })
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid request data', details: error.errors },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'
|
||||
logger.error(`[${requestId}] RDS update failed:`, error)
|
||||
|
||||
return NextResponse.json({ error: `RDS update failed: ${errorMessage}` }, { status: 500 })
|
||||
}
|
||||
}
|
||||
266
apps/sim/app/api/tools/rds/utils.ts
Normal file
266
apps/sim/app/api/tools/rds/utils.ts
Normal file
@@ -0,0 +1,266 @@
|
||||
import {
|
||||
ExecuteStatementCommand,
|
||||
type ExecuteStatementCommandOutput,
|
||||
type Field,
|
||||
RDSDataClient,
|
||||
type SqlParameter,
|
||||
} from '@aws-sdk/client-rds-data'
|
||||
import type { RdsConnectionConfig } from '@/tools/rds/types'
|
||||
|
||||
export function createRdsClient(config: RdsConnectionConfig): RDSDataClient {
|
||||
return new RDSDataClient({
|
||||
region: config.region,
|
||||
credentials: {
|
||||
accessKeyId: config.accessKeyId,
|
||||
secretAccessKey: config.secretAccessKey,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export async function executeStatement(
|
||||
client: RDSDataClient,
|
||||
resourceArn: string,
|
||||
secretArn: string,
|
||||
database: string | undefined,
|
||||
sql: string,
|
||||
parameters?: SqlParameter[]
|
||||
): Promise<{ rows: Record<string, unknown>[]; rowCount: number }> {
|
||||
const command = new ExecuteStatementCommand({
|
||||
resourceArn,
|
||||
secretArn,
|
||||
...(database && { database }),
|
||||
sql,
|
||||
...(parameters && parameters.length > 0 && { parameters }),
|
||||
includeResultMetadata: true,
|
||||
})
|
||||
|
||||
const response = await client.send(command)
|
||||
const rows = parseRdsResponse(response)
|
||||
|
||||
return {
|
||||
rows,
|
||||
rowCount: response.numberOfRecordsUpdated ?? rows.length,
|
||||
}
|
||||
}
|
||||
|
||||
function parseRdsResponse(response: ExecuteStatementCommandOutput): Record<string, unknown>[] {
|
||||
if (!response.records || !response.columnMetadata) {
|
||||
return []
|
||||
}
|
||||
|
||||
const columnNames = response.columnMetadata.map((col) => col.name || col.label || 'unknown')
|
||||
|
||||
return response.records.map((record) => {
|
||||
const row: Record<string, unknown> = {}
|
||||
record.forEach((field, index) => {
|
||||
const columnName = columnNames[index] || `column_${index}`
|
||||
row[columnName] = parseFieldValue(field)
|
||||
})
|
||||
return row
|
||||
})
|
||||
}
|
||||
|
||||
function parseFieldValue(field: Field): unknown {
|
||||
if (field.isNull) return null
|
||||
if (field.stringValue !== undefined) return field.stringValue
|
||||
if (field.longValue !== undefined) return field.longValue
|
||||
if (field.doubleValue !== undefined) return field.doubleValue
|
||||
if (field.booleanValue !== undefined) return field.booleanValue
|
||||
if (field.blobValue !== undefined) return Buffer.from(field.blobValue).toString('base64')
|
||||
if (field.arrayValue !== undefined) {
|
||||
const arr = field.arrayValue
|
||||
if (arr.stringValues) return arr.stringValues
|
||||
if (arr.longValues) return arr.longValues
|
||||
if (arr.doubleValues) return arr.doubleValues
|
||||
if (arr.booleanValues) return arr.booleanValues
|
||||
if (arr.arrayValues) return arr.arrayValues.map((f) => parseFieldValue({ arrayValue: f }))
|
||||
return []
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export function validateQuery(query: string): { isValid: boolean; error?: string } {
|
||||
const trimmedQuery = query.trim().toLowerCase()
|
||||
|
||||
const dangerousPatterns = [
|
||||
/drop\s+database/i,
|
||||
/drop\s+schema/i,
|
||||
/drop\s+user/i,
|
||||
/create\s+user/i,
|
||||
/create\s+role/i,
|
||||
/grant\s+/i,
|
||||
/revoke\s+/i,
|
||||
/alter\s+user/i,
|
||||
/alter\s+role/i,
|
||||
/set\s+role/i,
|
||||
/reset\s+role/i,
|
||||
]
|
||||
|
||||
for (const pattern of dangerousPatterns) {
|
||||
if (pattern.test(query)) {
|
||||
return {
|
||||
isValid: false,
|
||||
error: `Query contains potentially dangerous operation: ${pattern.source}`,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const allowedStatements = /^(select|insert|update|delete|with|explain|show)\s+/i
|
||||
if (!allowedStatements.test(trimmedQuery)) {
|
||||
return {
|
||||
isValid: false,
|
||||
error: 'Only SELECT, INSERT, UPDATE, DELETE, WITH, EXPLAIN, and SHOW statements are allowed',
|
||||
}
|
||||
}
|
||||
|
||||
return { isValid: true }
|
||||
}
|
||||
|
||||
export function sanitizeIdentifier(identifier: string): string {
|
||||
if (identifier.includes('.')) {
|
||||
const parts = identifier.split('.')
|
||||
return parts.map((part) => sanitizeSingleIdentifier(part)).join('.')
|
||||
}
|
||||
|
||||
return sanitizeSingleIdentifier(identifier)
|
||||
}
|
||||
|
||||
function sanitizeSingleIdentifier(identifier: string): string {
|
||||
const cleaned = identifier.replace(/`/g, '').replace(/"/g, '')
|
||||
|
||||
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(cleaned)) {
|
||||
throw new Error(
|
||||
`Invalid identifier: ${identifier}. Identifiers must start with a letter or underscore and contain only letters, numbers, and underscores.`
|
||||
)
|
||||
}
|
||||
|
||||
return cleaned
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a JS value to an RDS Data API SqlParameter value
|
||||
*/
|
||||
function toSqlParameterValue(value: unknown): SqlParameter['value'] {
|
||||
if (value === null || value === undefined) {
|
||||
return { isNull: true }
|
||||
}
|
||||
if (typeof value === 'boolean') {
|
||||
return { booleanValue: value }
|
||||
}
|
||||
if (typeof value === 'number') {
|
||||
if (Number.isInteger(value)) {
|
||||
return { longValue: value }
|
||||
}
|
||||
return { doubleValue: value }
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return { stringValue: value }
|
||||
}
|
||||
if (value instanceof Uint8Array || Buffer.isBuffer(value)) {
|
||||
return { blobValue: value }
|
||||
}
|
||||
// Objects/arrays as JSON strings
|
||||
return { stringValue: JSON.stringify(value) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Build parameterized INSERT query
|
||||
*/
|
||||
export async function executeInsert(
|
||||
client: RDSDataClient,
|
||||
resourceArn: string,
|
||||
secretArn: string,
|
||||
database: string | undefined,
|
||||
table: string,
|
||||
data: Record<string, unknown>
|
||||
): Promise<{ rows: Record<string, unknown>[]; rowCount: number }> {
|
||||
const sanitizedTable = sanitizeIdentifier(table)
|
||||
const columns = Object.keys(data)
|
||||
const sanitizedColumns = columns.map((col) => sanitizeIdentifier(col))
|
||||
|
||||
const placeholders = columns.map((col) => `:${col}`)
|
||||
const parameters: SqlParameter[] = columns.map((col) => ({
|
||||
name: col,
|
||||
value: toSqlParameterValue(data[col]),
|
||||
}))
|
||||
|
||||
const sql = `INSERT INTO ${sanitizedTable} (${sanitizedColumns.join(', ')}) VALUES (${placeholders.join(', ')})`
|
||||
|
||||
return executeStatement(client, resourceArn, secretArn, database, sql, parameters)
|
||||
}
|
||||
|
||||
/**
|
||||
* Build parameterized UPDATE query with conditions
|
||||
*/
|
||||
export async function executeUpdate(
|
||||
client: RDSDataClient,
|
||||
resourceArn: string,
|
||||
secretArn: string,
|
||||
database: string | undefined,
|
||||
table: string,
|
||||
data: Record<string, unknown>,
|
||||
conditions: Record<string, unknown>
|
||||
): Promise<{ rows: Record<string, unknown>[]; rowCount: number }> {
|
||||
const sanitizedTable = sanitizeIdentifier(table)
|
||||
|
||||
// Build SET clause with parameters
|
||||
const dataColumns = Object.keys(data)
|
||||
const setClause = dataColumns.map((col) => `${sanitizeIdentifier(col)} = :set_${col}`).join(', ')
|
||||
|
||||
// Build WHERE clause with parameters
|
||||
const conditionColumns = Object.keys(conditions)
|
||||
if (conditionColumns.length === 0) {
|
||||
throw new Error('At least one condition is required for UPDATE operations')
|
||||
}
|
||||
const whereClause = conditionColumns
|
||||
.map((col) => `${sanitizeIdentifier(col)} = :where_${col}`)
|
||||
.join(' AND ')
|
||||
|
||||
// Build parameters array (prefixed to avoid name collisions)
|
||||
const parameters: SqlParameter[] = [
|
||||
...dataColumns.map((col) => ({
|
||||
name: `set_${col}`,
|
||||
value: toSqlParameterValue(data[col]),
|
||||
})),
|
||||
...conditionColumns.map((col) => ({
|
||||
name: `where_${col}`,
|
||||
value: toSqlParameterValue(conditions[col]),
|
||||
})),
|
||||
]
|
||||
|
||||
const sql = `UPDATE ${sanitizedTable} SET ${setClause} WHERE ${whereClause}`
|
||||
|
||||
return executeStatement(client, resourceArn, secretArn, database, sql, parameters)
|
||||
}
|
||||
|
||||
/**
|
||||
* Build parameterized DELETE query with conditions
|
||||
*/
|
||||
export async function executeDelete(
|
||||
client: RDSDataClient,
|
||||
resourceArn: string,
|
||||
secretArn: string,
|
||||
database: string | undefined,
|
||||
table: string,
|
||||
conditions: Record<string, unknown>
|
||||
): Promise<{ rows: Record<string, unknown>[]; rowCount: number }> {
|
||||
const sanitizedTable = sanitizeIdentifier(table)
|
||||
|
||||
// Build WHERE clause with parameters
|
||||
const conditionColumns = Object.keys(conditions)
|
||||
if (conditionColumns.length === 0) {
|
||||
throw new Error('At least one condition is required for DELETE operations')
|
||||
}
|
||||
const whereClause = conditionColumns
|
||||
.map((col) => `${sanitizeIdentifier(col)} = :${col}`)
|
||||
.join(' AND ')
|
||||
|
||||
const parameters: SqlParameter[] = conditionColumns.map((col) => ({
|
||||
name: col,
|
||||
value: toSqlParameterValue(conditions[col]),
|
||||
}))
|
||||
|
||||
const sql = `DELETE FROM ${sanitizedTable} WHERE ${whereClause}`
|
||||
|
||||
return executeStatement(client, resourceArn, secretArn, database, sql, parameters)
|
||||
}
|
||||
@@ -232,7 +232,7 @@ function TemplateCardInner({
|
||||
key={index}
|
||||
className='flex h-[18px] w-[18px] flex-shrink-0 items-center justify-center rounded-[4px]'
|
||||
style={{
|
||||
backgroundColor: blockConfig.bgColor || 'gray',
|
||||
background: blockConfig.bgColor || 'gray',
|
||||
marginLeft: index > 0 ? '-4px' : '0',
|
||||
}}
|
||||
>
|
||||
@@ -257,7 +257,7 @@ function TemplateCardInner({
|
||||
key={index}
|
||||
className='flex h-[18px] w-[18px] flex-shrink-0 items-center justify-center rounded-[4px]'
|
||||
style={{
|
||||
backgroundColor: blockConfig.bgColor || 'gray',
|
||||
background: blockConfig.bgColor || 'gray',
|
||||
marginLeft: index > 0 ? '-4px' : '0',
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -196,7 +196,7 @@ export const NoteBlock = memo(function NoteBlock({ id, data }: NodeProps<NoteBlo
|
||||
<div className='flex min-w-0 flex-1 items-center gap-[10px]'>
|
||||
<div
|
||||
className='flex h-[24px] w-[24px] flex-shrink-0 items-center justify-center rounded-[6px]'
|
||||
style={{ backgroundColor: isEnabled ? config.bgColor : 'gray' }}
|
||||
style={{ background: isEnabled ? config.bgColor : 'gray' }}
|
||||
>
|
||||
<config.icon className='h-[16px] w-[16px] text-white' />
|
||||
</div>
|
||||
|
||||
@@ -176,7 +176,7 @@ export function MentionMenu({
|
||||
icon: (
|
||||
<div
|
||||
className='relative flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center overflow-hidden rounded-[4px]'
|
||||
style={{ backgroundColor: blk.bgColor || '#6B7280' }}
|
||||
style={{ background: blk.bgColor || '#6B7280' }}
|
||||
>
|
||||
{Icon && <Icon className='!h-[10px] !w-[10px] text-white' />}
|
||||
</div>
|
||||
@@ -198,7 +198,7 @@ export function MentionMenu({
|
||||
icon: (
|
||||
<div
|
||||
className='relative flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center overflow-hidden rounded-[4px]'
|
||||
style={{ backgroundColor: blk.bgColor || '#6B7280' }}
|
||||
style={{ background: blk.bgColor || '#6B7280' }}
|
||||
>
|
||||
{Icon && <Icon className='!h-[10px] !w-[10px] text-white' />}
|
||||
</div>
|
||||
@@ -474,7 +474,7 @@ export function MentionMenu({
|
||||
>
|
||||
<div
|
||||
className='relative flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center overflow-hidden rounded-[4px]'
|
||||
style={{ backgroundColor: blk.bgColor || '#6B7280' }}
|
||||
style={{ background: blk.bgColor || '#6B7280' }}
|
||||
>
|
||||
{Icon && <Icon className='!h-[10px] !w-[10px] text-white' />}
|
||||
</div>
|
||||
@@ -503,7 +503,7 @@ export function MentionMenu({
|
||||
>
|
||||
<div
|
||||
className='relative flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center overflow-hidden rounded-[4px]'
|
||||
style={{ backgroundColor: blk.bgColor || '#6B7280' }}
|
||||
style={{ background: blk.bgColor || '#6B7280' }}
|
||||
>
|
||||
{Icon && <Icon className='!h-[10px] !w-[10px] text-white' />}
|
||||
</div>
|
||||
@@ -680,7 +680,7 @@ export function MentionMenu({
|
||||
<PopoverItem key={blk.id} onClick={() => insertBlockMention(blk)}>
|
||||
<div
|
||||
className='relative flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center overflow-hidden rounded-[4px]'
|
||||
style={{ backgroundColor: blk.bgColor || '#6B7280' }}
|
||||
style={{ background: blk.bgColor || '#6B7280' }}
|
||||
>
|
||||
{Icon && <Icon className='!h-[10px] !w-[10px] text-white' />}
|
||||
</div>
|
||||
@@ -709,7 +709,7 @@ export function MentionMenu({
|
||||
<PopoverItem key={blk.id} onClick={() => insertWorkflowBlockMention(blk)}>
|
||||
<div
|
||||
className='relative flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center overflow-hidden rounded-[4px]'
|
||||
style={{ backgroundColor: blk.bgColor || '#6B7280' }}
|
||||
style={{ background: blk.bgColor || '#6B7280' }}
|
||||
>
|
||||
{Icon && <Icon className='!h-[10px] !w-[10px] text-white' />}
|
||||
</div>
|
||||
|
||||
@@ -130,7 +130,7 @@ function ConnectionItem({
|
||||
>
|
||||
<div
|
||||
className='relative flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center overflow-hidden rounded-[4px]'
|
||||
style={{ backgroundColor: bgColor }}
|
||||
style={{ background: bgColor }}
|
||||
>
|
||||
{Icon && (
|
||||
<Icon
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { useParams } from 'next/navigation'
|
||||
import { Tooltip } from '@/components/emcn'
|
||||
import { getProviderIdFromServiceId } from '@/lib/oauth/oauth'
|
||||
import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/selector-combobox/selector-combobox'
|
||||
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
|
||||
import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential'
|
||||
@@ -41,8 +42,11 @@ export function ChannelSelectorInput({
|
||||
const effectiveCredential = previewContextValues?.credential ?? connectedCredential
|
||||
const [_channelInfo, setChannelInfo] = useState<string | null>(null)
|
||||
|
||||
const provider = subBlock.provider || 'slack'
|
||||
const isSlack = provider === 'slack'
|
||||
// Use serviceId to identify the service and derive providerId for credential lookup
|
||||
const serviceId = subBlock.serviceId || ''
|
||||
const effectiveProviderId = useMemo(() => getProviderIdFromServiceId(serviceId), [serviceId])
|
||||
const isSlack = serviceId === 'slack'
|
||||
|
||||
// Central dependsOn gating
|
||||
const { finalDisabled, dependsOn } = useDependsOnGate(blockId, subBlock, {
|
||||
disabled,
|
||||
@@ -58,7 +62,7 @@ export function ChannelSelectorInput({
|
||||
|
||||
// Determine if connected OAuth credential is foreign (not applicable for bot tokens)
|
||||
const { isForeignCredential } = useForeignCredential(
|
||||
'slack',
|
||||
effectiveProviderId,
|
||||
(effectiveAuthMethod as string) === 'bot_token' ? '' : (effectiveCredential as string) || ''
|
||||
)
|
||||
|
||||
@@ -87,11 +91,11 @@ export function ChannelSelectorInput({
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger asChild>
|
||||
<div className='w-full rounded border border-dashed p-4 text-center text-muted-foreground text-sm'>
|
||||
Channel selector not supported for provider: {provider}
|
||||
Channel selector not supported for service: {serviceId || 'unknown'}
|
||||
</div>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content side='top'>
|
||||
<p>This channel selector is not yet implemented for {provider}</p>
|
||||
<p>This channel selector is not yet implemented for {serviceId || 'unknown'}</p>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
)
|
||||
|
||||
@@ -11,7 +11,7 @@ import type { SubBlockConfig } from '@/blocks/types'
|
||||
/**
|
||||
* Constants for ComboBox component behavior
|
||||
*/
|
||||
const DEFAULT_MODEL = 'gpt-4o'
|
||||
const DEFAULT_MODEL = 'claude-sonnet-4-5'
|
||||
const ZOOM_FACTOR_BASE = 0.96
|
||||
const MIN_ZOOM = 0.1
|
||||
const MAX_ZOOM = 1
|
||||
@@ -99,18 +99,18 @@ export function ComboBox({
|
||||
|
||||
/**
|
||||
* Determines the default option value to use.
|
||||
* Priority: explicit defaultValue > gpt-4o for model field > first option
|
||||
* Priority: explicit defaultValue > claude-sonnet-4-5 for model field > first option
|
||||
*/
|
||||
const defaultOptionValue = useMemo(() => {
|
||||
if (defaultValue !== undefined) {
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
// For model field, default to gpt-4o if available
|
||||
// For model field, default to claude-sonnet-4-5 if available
|
||||
if (subBlockId === 'model') {
|
||||
const gpt4o = evaluatedOptions.find((opt) => getOptionValue(opt) === DEFAULT_MODEL)
|
||||
if (gpt4o) {
|
||||
return getOptionValue(gpt4o)
|
||||
const claudeSonnet45 = evaluatedOptions.find((opt) => getOptionValue(opt) === DEFAULT_MODEL)
|
||||
if (claudeSonnet45) {
|
||||
return getOptionValue(claudeSonnet45)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import { createLogger } from '@/lib/logs/console/logger'
|
||||
import {
|
||||
getCanonicalScopesForProvider,
|
||||
getProviderIdFromServiceId,
|
||||
getServiceIdFromScopes,
|
||||
OAUTH_PROVIDERS,
|
||||
type OAuthProvider,
|
||||
parseProvider,
|
||||
@@ -42,23 +41,19 @@ export function CredentialSelector({
|
||||
const { activeWorkflowId } = useWorkflowRegistry()
|
||||
const [storeValue, setStoreValue] = useSubBlockValue<string | null>(blockId, subBlock.id)
|
||||
|
||||
const provider = subBlock.provider as OAuthProvider
|
||||
const requiredScopes = subBlock.requiredScopes || []
|
||||
const label = subBlock.placeholder || 'Select credential'
|
||||
const serviceId = subBlock.serviceId
|
||||
const serviceId = subBlock.serviceId || ''
|
||||
|
||||
const effectiveValue = isPreview && previewValue !== undefined ? previewValue : storeValue
|
||||
const selectedId = typeof effectiveValue === 'string' ? effectiveValue : ''
|
||||
|
||||
const effectiveServiceId = useMemo(
|
||||
() => serviceId || getServiceIdFromScopes(provider, requiredScopes),
|
||||
[provider, requiredScopes, serviceId]
|
||||
)
|
||||
|
||||
// serviceId is now the canonical identifier - derive provider from it
|
||||
const effectiveProviderId = useMemo(
|
||||
() => getProviderIdFromServiceId(effectiveServiceId),
|
||||
[effectiveServiceId]
|
||||
() => getProviderIdFromServiceId(serviceId) as OAuthProvider,
|
||||
[serviceId]
|
||||
)
|
||||
const provider = effectiveProviderId
|
||||
|
||||
const {
|
||||
data: credentials = [],
|
||||
@@ -259,7 +254,7 @@ export function CredentialSelector({
|
||||
toolName={getProviderName(provider)}
|
||||
requiredScopes={getCanonicalScopesForProvider(effectiveProviderId)}
|
||||
newScopes={missingRequiredScopes}
|
||||
serviceId={effectiveServiceId}
|
||||
serviceId={serviceId}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { useMemo } from 'react'
|
||||
import { useParams } from 'next/navigation'
|
||||
import { Tooltip } from '@/components/emcn'
|
||||
import { getProviderIdFromServiceId } from '@/lib/oauth'
|
||||
import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/selector-combobox/selector-combobox'
|
||||
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
|
||||
import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential'
|
||||
@@ -59,10 +60,11 @@ export function FileSelectorInput({
|
||||
? ((connectedCredential as Record<string, any>).id ?? '')
|
||||
: ''
|
||||
|
||||
const { isForeignCredential } = useForeignCredential(
|
||||
subBlock.serviceId || subBlock.provider,
|
||||
normalizedCredentialId
|
||||
)
|
||||
// Derive provider from serviceId using OAuth config (same pattern as credential-selector)
|
||||
const serviceId = subBlock.serviceId || ''
|
||||
const effectiveProviderId = useMemo(() => getProviderIdFromServiceId(serviceId), [serviceId])
|
||||
|
||||
const { isForeignCredential } = useForeignCredential(effectiveProviderId, normalizedCredentialId)
|
||||
|
||||
const selectorResolution = useMemo<SelectorResolution | null>(() => {
|
||||
return resolveSelectorForSubBlock(subBlock, {
|
||||
@@ -109,11 +111,11 @@ export function FileSelectorInput({
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger asChild>
|
||||
<div className='w-full rounded border border-dashed p-4 text-center text-muted-foreground text-sm'>
|
||||
File selector not supported for provider: {subBlock.provider || subBlock.serviceId}
|
||||
File selector not supported for service: {serviceId || 'unknown'}
|
||||
</div>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content side='top'>
|
||||
<p>This file selector is not implemented for {subBlock.provider || subBlock.serviceId}</p>
|
||||
<p>This file selector is not implemented for {serviceId || 'unknown'}</p>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { getProviderIdFromServiceId } from '@/lib/oauth'
|
||||
import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/selector-combobox/selector-combobox'
|
||||
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
|
||||
import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential'
|
||||
@@ -30,14 +31,18 @@ export function FolderSelectorInput({
|
||||
const { collaborativeSetSubblockValue } = useCollaborativeWorkflow()
|
||||
const { activeWorkflowId } = useWorkflowRegistry()
|
||||
const [selectedFolderId, setSelectedFolderId] = useState<string>('')
|
||||
const providerKey = (subBlock.provider ?? subBlock.serviceId ?? '').toLowerCase()
|
||||
const credentialProvider = subBlock.serviceId ?? subBlock.provider
|
||||
|
||||
// Derive provider from serviceId using OAuth config (same pattern as credential-selector)
|
||||
const serviceId = subBlock.serviceId || ''
|
||||
const effectiveProviderId = useMemo(() => getProviderIdFromServiceId(serviceId), [serviceId])
|
||||
const providerKey = serviceId.toLowerCase()
|
||||
|
||||
const isCopyDestinationSelector =
|
||||
subBlock.canonicalParamId === 'copyDestinationId' ||
|
||||
subBlock.id === 'copyDestinationFolder' ||
|
||||
subBlock.id === 'manualCopyDestinationFolder'
|
||||
const { isForeignCredential } = useForeignCredential(
|
||||
credentialProvider,
|
||||
effectiveProviderId,
|
||||
(connectedCredential as string) || ''
|
||||
)
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { useParams } from 'next/navigation'
|
||||
import { Tooltip } from '@/components/emcn'
|
||||
import { getProviderIdFromServiceId } from '@/lib/oauth'
|
||||
import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/selector-combobox/selector-combobox'
|
||||
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
|
||||
import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential'
|
||||
@@ -46,8 +47,13 @@ export function ProjectSelectorInput({
|
||||
const linearTeamId = previewContextValues?.teamId ?? linearTeamIdFromStore
|
||||
const jiraDomain = previewContextValues?.domain ?? jiraDomainFromStore
|
||||
|
||||
// Derive provider from serviceId using OAuth config
|
||||
const serviceId = subBlock.serviceId || ''
|
||||
const effectiveProviderId = useMemo(() => getProviderIdFromServiceId(serviceId), [serviceId])
|
||||
const isLinear = serviceId === 'linear'
|
||||
|
||||
const { isForeignCredential } = useForeignCredential(
|
||||
subBlock.provider || subBlock.serviceId || 'jira',
|
||||
effectiveProviderId,
|
||||
(connectedCredential as string) || ''
|
||||
)
|
||||
const activeWorkflowId = useWorkflowRegistry((s) => s.activeWorkflowId) as string | null
|
||||
@@ -58,10 +64,6 @@ export function ProjectSelectorInput({
|
||||
previewContextValues,
|
||||
})
|
||||
|
||||
// Get provider-specific values
|
||||
const provider = subBlock.provider || 'jira'
|
||||
const isLinear = provider === 'linear'
|
||||
|
||||
// Jira/Discord upstream fields - use values from previewContextValues or store
|
||||
const jiraCredential = connectedCredential
|
||||
const domain = (jiraDomain as string) || ''
|
||||
@@ -121,7 +123,7 @@ export function ProjectSelectorInput({
|
||||
/>
|
||||
) : (
|
||||
<div className='w-full rounded border border-dashed p-4 text-center text-muted-foreground text-sm'>
|
||||
Project selector not supported for provider: {subBlock.provider || 'unknown'}
|
||||
Project selector not supported for service: {serviceId}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -84,7 +84,7 @@ export function McpToolsList({
|
||||
>
|
||||
<div
|
||||
className='flex h-[15px] w-[15px] flex-shrink-0 items-center justify-center rounded'
|
||||
style={{ backgroundColor: mcpTool.bgColor }}
|
||||
style={{ background: mcpTool.bgColor }}
|
||||
>
|
||||
<IconComponent icon={mcpTool.icon} className='h-[11px] w-[11px] text-white' />
|
||||
</div>
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Toggle } from '@/components/ui/toggle'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import {
|
||||
getCanonicalScopesForProvider,
|
||||
getProviderIdFromServiceId,
|
||||
type OAuthProvider,
|
||||
type OAuthService,
|
||||
} from '@/lib/oauth/oauth'
|
||||
@@ -168,7 +169,6 @@ function FileSelectorSyncWrapper({
|
||||
id: paramId,
|
||||
type: 'file-selector' as const,
|
||||
title: paramId,
|
||||
provider: uiComponent.provider,
|
||||
serviceId: uiComponent.serviceId,
|
||||
mimeType: uiComponent.mimeType,
|
||||
requiredScopes: uiComponent.requiredScopes || [],
|
||||
@@ -467,7 +467,7 @@ function ChannelSelectorSyncWrapper({
|
||||
id: paramId,
|
||||
type: 'channel-selector' as const,
|
||||
title: paramId,
|
||||
provider: uiComponent.provider || 'slack',
|
||||
serviceId: uiComponent.serviceId,
|
||||
placeholder: uiComponent.placeholder,
|
||||
dependsOn: uiComponent.dependsOn,
|
||||
}}
|
||||
@@ -1404,7 +1404,6 @@ export function ToolInput({
|
||||
id: `tool-${toolIndex || 0}-${param.id}`,
|
||||
type: 'project-selector' as const,
|
||||
title: param.id,
|
||||
provider: uiComponent.provider || 'jira',
|
||||
serviceId: uiComponent.serviceId,
|
||||
placeholder: uiComponent.placeholder,
|
||||
requiredScopes: uiComponent.requiredScopes,
|
||||
@@ -1421,7 +1420,7 @@ export function ToolInput({
|
||||
<ToolCredentialSelector
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
provider={(uiComponent.provider || uiComponent.serviceId) as OAuthProvider}
|
||||
provider={getProviderIdFromServiceId(uiComponent.serviceId || '') as OAuthProvider}
|
||||
serviceId={uiComponent.serviceId as OAuthService}
|
||||
disabled={disabled}
|
||||
requiredScopes={uiComponent.requiredScopes || []}
|
||||
@@ -1729,7 +1728,7 @@ export function ToolInput({
|
||||
>
|
||||
<div
|
||||
className='flex h-[15px] w-[15px] flex-shrink-0 items-center justify-center rounded'
|
||||
style={{ backgroundColor: block.bgColor }}
|
||||
style={{ background: block.bgColor }}
|
||||
>
|
||||
<IconComponent
|
||||
icon={block.icon}
|
||||
@@ -2258,7 +2257,7 @@ export function ToolInput({
|
||||
>
|
||||
<div
|
||||
className='flex h-[15px] w-[15px] flex-shrink-0 items-center justify-center rounded'
|
||||
style={{ backgroundColor: block.bgColor }}
|
||||
style={{ background: block.bgColor }}
|
||||
>
|
||||
<IconComponent
|
||||
icon={block.icon}
|
||||
|
||||
@@ -346,10 +346,11 @@ function SubBlockComponent({
|
||||
| undefined
|
||||
|
||||
// Use dependsOn gating to compute final disabled state
|
||||
// Only pass previewContextValues when in preview mode to avoid format mismatches
|
||||
const { finalDisabled: gatedDisabled } = useDependsOnGate(blockId, config, {
|
||||
disabled,
|
||||
isPreview,
|
||||
previewContextValues: subBlockValues,
|
||||
previewContextValues: isPreview ? subBlockValues : undefined,
|
||||
})
|
||||
|
||||
const isDisabled = gatedDisabled
|
||||
@@ -611,7 +612,7 @@ function SubBlockComponent({
|
||||
disabled={isDisabled}
|
||||
isPreview={isPreview}
|
||||
previewValue={previewValue}
|
||||
previewContextValues={subBlockValues}
|
||||
previewContextValues={isPreview ? subBlockValues : undefined}
|
||||
/>
|
||||
)
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ export function Editor() {
|
||||
{(blockConfig || isSubflow) && (
|
||||
<div
|
||||
className='flex h-[18px] w-[18px] items-center justify-center rounded-[4px]'
|
||||
style={{ backgroundColor: isSubflow ? subflowBgColor : blockConfig?.bgColor }}
|
||||
style={{ background: isSubflow ? subflowBgColor : blockConfig?.bgColor }}
|
||||
>
|
||||
<IconComponent
|
||||
icon={isSubflow ? subflowIcon : blockConfig?.icon}
|
||||
@@ -353,7 +353,6 @@ export function Editor() {
|
||||
blockId={currentBlockId}
|
||||
config={subBlock}
|
||||
isPreview={false}
|
||||
subBlockValues={subBlockState}
|
||||
disabled={!userPermissions.canEdit}
|
||||
fieldDiffStatus={undefined}
|
||||
allowExpandInPreview={false}
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
import { useMemo } from 'react'
|
||||
import { useParams } from 'next/navigation'
|
||||
import { Tooltip } from '@/components/emcn'
|
||||
import { getProviderIdFromServiceId } from '@/lib/oauth'
|
||||
import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/selector-combobox/selector-combobox'
|
||||
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
|
||||
import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential'
|
||||
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
||||
import type { SubBlockConfig } from '@/blocks/types'
|
||||
import type { SelectorContext, SelectorKey } from '@/hooks/selectors/types'
|
||||
import { resolveSelectorForSubBlock, type SelectorResolution } from '@/hooks/selectors/resolution'
|
||||
import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow'
|
||||
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
|
||||
|
||||
@@ -59,27 +60,23 @@ export function FileSelectorInput({
|
||||
? ((connectedCredential as Record<string, any>).id ?? '')
|
||||
: ''
|
||||
|
||||
const { isForeignCredential } = useForeignCredential(
|
||||
subBlock.provider || subBlock.serviceId || 'google-drive',
|
||||
normalizedCredentialId
|
||||
)
|
||||
// Derive provider from serviceId using OAuth config
|
||||
const serviceId = subBlock.serviceId || ''
|
||||
const effectiveProviderId = useMemo(() => getProviderIdFromServiceId(serviceId), [serviceId])
|
||||
|
||||
const selectorResolution = useMemo(() => {
|
||||
return resolveSelector({
|
||||
provider: subBlock.provider || '',
|
||||
serviceId: subBlock.serviceId,
|
||||
mimeType: subBlock.mimeType,
|
||||
const { isForeignCredential } = useForeignCredential(effectiveProviderId, normalizedCredentialId)
|
||||
|
||||
const selectorResolution = useMemo<SelectorResolution | null>(() => {
|
||||
return resolveSelectorForSubBlock(subBlock, {
|
||||
credentialId: normalizedCredentialId,
|
||||
workflowId: workflowIdFromUrl,
|
||||
domain: (domainValue as string) || '',
|
||||
projectId: (projectIdValue as string) || '',
|
||||
planId: (planIdValue as string) || '',
|
||||
teamId: (teamIdValue as string) || '',
|
||||
domain: (domainValue as string) || undefined,
|
||||
projectId: (projectIdValue as string) || undefined,
|
||||
planId: (planIdValue as string) || undefined,
|
||||
teamId: (teamIdValue as string) || undefined,
|
||||
})
|
||||
}, [
|
||||
subBlock.provider,
|
||||
subBlock.serviceId,
|
||||
subBlock.mimeType,
|
||||
subBlock,
|
||||
normalizedCredentialId,
|
||||
workflowIdFromUrl,
|
||||
domainValue,
|
||||
@@ -90,15 +87,15 @@ export function FileSelectorInput({
|
||||
|
||||
const missingCredential = !normalizedCredentialId
|
||||
const missingDomain =
|
||||
selectorResolution.key &&
|
||||
selectorResolution?.key &&
|
||||
(selectorResolution.key === 'confluence.pages' || selectorResolution.key === 'jira.issues') &&
|
||||
!selectorResolution.context.domain
|
||||
const missingProject =
|
||||
selectorResolution.key === 'jira.issues' &&
|
||||
selectorResolution?.key === 'jira.issues' &&
|
||||
subBlock.dependsOn?.includes('projectId') &&
|
||||
!selectorResolution.context.projectId
|
||||
!selectorResolution?.context.projectId
|
||||
const missingPlan =
|
||||
selectorResolution.key === 'microsoft.planner' && !selectorResolution.context.planId
|
||||
selectorResolution?.key === 'microsoft.planner' && !selectorResolution?.context.planId
|
||||
|
||||
const disabledReason =
|
||||
finalDisabled ||
|
||||
@@ -107,18 +104,18 @@ export function FileSelectorInput({
|
||||
missingDomain ||
|
||||
missingProject ||
|
||||
missingPlan ||
|
||||
selectorResolution.key === null
|
||||
!selectorResolution?.key
|
||||
|
||||
if (selectorResolution.key === null) {
|
||||
if (!selectorResolution?.key) {
|
||||
return (
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger asChild>
|
||||
<div className='w-full rounded border border-dashed p-4 text-center text-muted-foreground text-sm'>
|
||||
File selector not supported for provider: {subBlock.provider || subBlock.serviceId}
|
||||
File selector not supported for service: {serviceId}
|
||||
</div>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content side='top'>
|
||||
<p>This file selector is not implemented for {subBlock.provider || subBlock.serviceId}</p>
|
||||
<p>This file selector is not implemented for {serviceId}</p>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
)
|
||||
@@ -143,69 +140,3 @@ export function FileSelectorInput({
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
interface SelectorParams {
|
||||
provider: string
|
||||
serviceId?: string
|
||||
mimeType?: string
|
||||
credentialId: string
|
||||
workflowId: string
|
||||
domain?: string
|
||||
projectId?: string
|
||||
planId?: string
|
||||
teamId?: string
|
||||
}
|
||||
|
||||
function resolveSelector(params: SelectorParams): {
|
||||
key: SelectorKey | null
|
||||
context: SelectorContext
|
||||
allowSearch: boolean
|
||||
} {
|
||||
const baseContext: SelectorContext = {
|
||||
credentialId: params.credentialId,
|
||||
workflowId: params.workflowId,
|
||||
domain: params.domain,
|
||||
projectId: params.projectId,
|
||||
planId: params.planId,
|
||||
teamId: params.teamId,
|
||||
mimeType: params.mimeType,
|
||||
}
|
||||
|
||||
switch (params.provider) {
|
||||
case 'google-calendar':
|
||||
return { key: 'google.calendar', context: baseContext, allowSearch: false }
|
||||
case 'confluence':
|
||||
return { key: 'confluence.pages', context: baseContext, allowSearch: true }
|
||||
case 'jira':
|
||||
return { key: 'jira.issues', context: baseContext, allowSearch: true }
|
||||
case 'microsoft-teams':
|
||||
return { key: 'microsoft.teams', context: baseContext, allowSearch: true }
|
||||
case 'wealthbox':
|
||||
return { key: 'wealthbox.contacts', context: baseContext, allowSearch: true }
|
||||
case 'microsoft-planner':
|
||||
return { key: 'microsoft.planner', context: baseContext, allowSearch: true }
|
||||
case 'microsoft-excel':
|
||||
return { key: 'microsoft.excel', context: baseContext, allowSearch: true }
|
||||
case 'microsoft-word':
|
||||
return { key: 'microsoft.word', context: baseContext, allowSearch: true }
|
||||
case 'google-drive':
|
||||
return { key: 'google.drive', context: baseContext, allowSearch: true }
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if (params.serviceId === 'onedrive') {
|
||||
const key: SelectorKey = params.mimeType === 'file' ? 'onedrive.files' : 'onedrive.folders'
|
||||
return { key, context: baseContext, allowSearch: true }
|
||||
}
|
||||
|
||||
if (params.serviceId === 'sharepoint') {
|
||||
return { key: 'sharepoint.sites', context: baseContext, allowSearch: true }
|
||||
}
|
||||
|
||||
if (params.serviceId === 'google-drive') {
|
||||
return { key: 'google.drive', context: baseContext, allowSearch: true }
|
||||
}
|
||||
|
||||
return { key: null, context: baseContext, allowSearch: true }
|
||||
}
|
||||
|
||||
@@ -570,7 +570,7 @@ export const Toolbar = forwardRef<ToolbarRef, ToolbarProps>(function Toolbar(
|
||||
>
|
||||
<div
|
||||
className='relative flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center overflow-hidden rounded-[4px]'
|
||||
style={{ backgroundColor: trigger.bgColor }}
|
||||
style={{ background: trigger.bgColor }}
|
||||
>
|
||||
{Icon && (
|
||||
<Icon
|
||||
@@ -659,7 +659,7 @@ export const Toolbar = forwardRef<ToolbarRef, ToolbarProps>(function Toolbar(
|
||||
>
|
||||
<div
|
||||
className='relative flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center overflow-hidden rounded-[4px]'
|
||||
style={{ backgroundColor: block.bgColor }}
|
||||
style={{ background: block.bgColor }}
|
||||
>
|
||||
{Icon && (
|
||||
<Icon
|
||||
|
||||
@@ -6,6 +6,7 @@ import { Tooltip } from '@/components/emcn/components/tooltip/tooltip'
|
||||
import { getEnv, isTruthy } from '@/lib/env'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { createMcpToolId } from '@/lib/mcp/utils'
|
||||
import { getProviderIdFromServiceId } from '@/lib/oauth'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
|
||||
import {
|
||||
@@ -272,9 +273,12 @@ const SubBlockRow = ({
|
||||
|
||||
const credentialSourceId =
|
||||
subBlock?.type === 'oauth-input' && typeof rawValue === 'string' ? rawValue : undefined
|
||||
const credentialProviderId = subBlock?.serviceId
|
||||
? getProviderIdFromServiceId(subBlock.serviceId)
|
||||
: undefined
|
||||
const { displayName: credentialName } = useCredentialName(
|
||||
credentialSourceId,
|
||||
subBlock?.provider,
|
||||
credentialProviderId,
|
||||
workflowId
|
||||
)
|
||||
|
||||
@@ -844,7 +848,7 @@ export const WorkflowBlock = memo(function WorkflowBlock({
|
||||
<div
|
||||
className='flex h-[24px] w-[24px] flex-shrink-0 items-center justify-center rounded-[6px]'
|
||||
style={{
|
||||
backgroundColor: isEnabled ? config.bgColor : 'gray',
|
||||
background: isEnabled ? config.bgColor : 'gray',
|
||||
}}
|
||||
>
|
||||
<config.icon className='h-[16px] w-[16px] text-white' />
|
||||
|
||||
@@ -12,3 +12,4 @@ export { SettingsNavigation } from './settings-navigation/settings-navigation'
|
||||
export { SSO } from './sso/sso'
|
||||
export { Subscription } from './subscription/subscription'
|
||||
export { TeamManagement } from './team-management/team-management'
|
||||
export { WorkflowImport } from './workflow-import/workflow-import'
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useQueryClient } from '@tanstack/react-query'
|
||||
import {
|
||||
Bot,
|
||||
CreditCard,
|
||||
Download,
|
||||
FileCode,
|
||||
Files,
|
||||
Home,
|
||||
@@ -27,6 +28,7 @@ import { generalSettingsKeys } from '@/hooks/queries/general-settings'
|
||||
import { organizationKeys, useOrganizations } from '@/hooks/queries/organization'
|
||||
import { ssoKeys, useSSOProviders } from '@/hooks/queries/sso'
|
||||
import { subscriptionKeys, useSubscriptionData } from '@/hooks/queries/subscription'
|
||||
import { useSuperUserStatus } from '@/hooks/queries/super-user'
|
||||
|
||||
const isBillingEnabled = isTruthy(getEnv('NEXT_PUBLIC_BILLING_ENABLED'))
|
||||
|
||||
@@ -48,6 +50,7 @@ interface SettingsNavigationProps {
|
||||
| 'copilot'
|
||||
| 'mcp'
|
||||
| 'custom-tools'
|
||||
| 'workflow-import'
|
||||
) => void
|
||||
hasOrganization: boolean
|
||||
}
|
||||
@@ -68,6 +71,7 @@ type NavigationItem = {
|
||||
| 'privacy'
|
||||
| 'mcp'
|
||||
| 'custom-tools'
|
||||
| 'workflow-import'
|
||||
label: string
|
||||
icon: React.ComponentType<{ className?: string }>
|
||||
hideWhenBillingDisabled?: boolean
|
||||
@@ -75,6 +79,7 @@ type NavigationItem = {
|
||||
requiresEnterprise?: boolean
|
||||
requiresOwner?: boolean
|
||||
requiresHosted?: boolean
|
||||
requiresSuperUser?: boolean
|
||||
}
|
||||
|
||||
const allNavigationItems: NavigationItem[] = [
|
||||
@@ -155,6 +160,12 @@ const allNavigationItems: NavigationItem[] = [
|
||||
requiresEnterprise: true,
|
||||
requiresOwner: true,
|
||||
},
|
||||
{
|
||||
id: 'workflow-import',
|
||||
label: 'Workflow Import',
|
||||
icon: Download,
|
||||
requiresSuperUser: true,
|
||||
},
|
||||
]
|
||||
|
||||
export function SettingsNavigation({
|
||||
@@ -176,6 +187,10 @@ export function SettingsNavigation({
|
||||
const subscriptionStatus = getSubscriptionStatus(subscriptionData?.data)
|
||||
const hasEnterprisePlan = subscriptionStatus.isEnterprise
|
||||
|
||||
// Check superuser status
|
||||
const { data: superUserData } = useSuperUserStatus()
|
||||
const isSuperUser = superUserData?.isSuperUser ?? false
|
||||
|
||||
// Use React Query to check SSO provider ownership (with proper caching)
|
||||
// Only fetch if not hosted (hosted uses billing/org checks)
|
||||
const { data: ssoProvidersData, isLoading: isLoadingSSO } = useSSOProviders()
|
||||
@@ -224,9 +239,13 @@ export function SettingsNavigation({
|
||||
return false
|
||||
}
|
||||
|
||||
if (item.requiresSuperUser && !isSuperUser) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
}, [hasOrganization, hasEnterprisePlan, canManageSSO, isSSOProviderOwner, isOwner])
|
||||
}, [hasOrganization, hasEnterprisePlan, canManageSSO, isSSOProviderOwner, isOwner, isSuperUser])
|
||||
|
||||
// Prefetch functions for React Query
|
||||
const prefetchGeneral = () => {
|
||||
|
||||
@@ -0,0 +1,325 @@
|
||||
'use client'
|
||||
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useParams, useRouter } from 'next/navigation'
|
||||
import { Download, Loader2 } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { Switch } from '@/components/ui/switch'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/select'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { parseWorkflowJson } from '@/stores/workflows/json/importer'
|
||||
import { useCreateWorkflow, workflowKeys } from '@/hooks/queries/workflows'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { useWorkflowDiffStore } from '@/stores/workflow-diff/store'
|
||||
import { useSuperUserStatus } from '@/hooks/queries/super-user'
|
||||
|
||||
const logger = createLogger('WorkflowImport')
|
||||
|
||||
/**
|
||||
* WorkflowImport Settings Component
|
||||
* Allows superusers to import workflows by ID from the database
|
||||
*/
|
||||
export function WorkflowImport() {
|
||||
const params = useParams()
|
||||
const router = useRouter()
|
||||
const queryClient = useQueryClient()
|
||||
const createWorkflowMutation = useCreateWorkflow()
|
||||
const { data: superUserData, isLoading: loadingSuperUser } = useSuperUserStatus()
|
||||
|
||||
const workspaceId = params?.workspaceId as string
|
||||
const isSuperUser = superUserData?.isSuperUser ?? false
|
||||
|
||||
const [workflowId, setWorkflowId] = useState('')
|
||||
const [useDeployment, setUseDeployment] = useState(false)
|
||||
const [deployments, setDeployments] = useState<any[]>([])
|
||||
const [selectedDeployment, setSelectedDeployment] = useState<string>('')
|
||||
const [loadingDeployments, setLoadingDeployments] = useState(false)
|
||||
const [isImporting, setIsImporting] = useState(false)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [success, setSuccess] = useState<string | null>(null)
|
||||
|
||||
// Fetch deployments when workflow ID changes and useDeployment is enabled
|
||||
useEffect(() => {
|
||||
const fetchDeployments = async () => {
|
||||
if (!useDeployment || !workflowId.trim()) {
|
||||
setDeployments([])
|
||||
setSelectedDeployment('')
|
||||
return
|
||||
}
|
||||
|
||||
setLoadingDeployments(true)
|
||||
setError(null)
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/admin/workflow-deployments?workflowId=${workflowId.trim()}`)
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json()
|
||||
throw new Error(errorData.error || 'Failed to fetch deployments')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
setDeployments(data.versions || [])
|
||||
|
||||
if (data.versions && data.versions.length > 0) {
|
||||
setSelectedDeployment(String(data.versions[0].version))
|
||||
} else {
|
||||
setSelectedDeployment('')
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error('Failed to fetch deployments:', err)
|
||||
setError(err instanceof Error ? err.message : 'Failed to fetch deployments')
|
||||
setDeployments([])
|
||||
setSelectedDeployment('')
|
||||
} finally {
|
||||
setLoadingDeployments(false)
|
||||
}
|
||||
}
|
||||
|
||||
fetchDeployments()
|
||||
}, [useDeployment, workflowId])
|
||||
|
||||
/**
|
||||
* Handle workflow import
|
||||
*/
|
||||
const handleImport = async () => {
|
||||
if (!workflowId.trim()) {
|
||||
setError('Please enter a workflow ID')
|
||||
return
|
||||
}
|
||||
|
||||
setIsImporting(true)
|
||||
setError(null)
|
||||
setSuccess(null)
|
||||
|
||||
try {
|
||||
// Build request
|
||||
const requestBody: any = {
|
||||
workflowId: workflowId.trim(),
|
||||
targetWorkspaceId: workspaceId,
|
||||
}
|
||||
|
||||
if (useDeployment && selectedDeployment) {
|
||||
requestBody.deploymentVersion = Number.parseInt(selectedDeployment, 10)
|
||||
}
|
||||
|
||||
// Fetch workflow data from admin API
|
||||
const response = await fetch('/api/admin/import-workflow', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(requestBody),
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json()
|
||||
throw new Error(errorData.error || 'Failed to fetch workflow')
|
||||
}
|
||||
|
||||
const { workflow: exportState, metadata } = await response.json()
|
||||
|
||||
// Parse the workflow JSON (regenerate IDs)
|
||||
const { data: workflowData, errors: parseErrors } = parseWorkflowJson(
|
||||
JSON.stringify(exportState),
|
||||
true
|
||||
)
|
||||
|
||||
if (!workflowData || parseErrors.length > 0) {
|
||||
throw new Error(`Failed to parse workflow: ${parseErrors.join(', ')}`)
|
||||
}
|
||||
|
||||
// Clear diff state
|
||||
useWorkflowDiffStore.getState().clearDiff()
|
||||
|
||||
// Create new workflow
|
||||
const importSuffix = metadata.deploymentVersion
|
||||
? ` (Imported v${metadata.deploymentVersion})`
|
||||
: ' (Imported)'
|
||||
|
||||
const workflowColor = exportState.state?.metadata?.color || '#3972F6'
|
||||
|
||||
const result = await createWorkflowMutation.mutateAsync({
|
||||
name: `${metadata.originalName}${importSuffix}`,
|
||||
description: metadata.originalDescription || `Imported from ${metadata.source}`,
|
||||
workspaceId,
|
||||
color: workflowColor,
|
||||
})
|
||||
const newWorkflowId = result.id
|
||||
|
||||
// Save workflow state
|
||||
const stateResponse = await fetch(`/api/workflows/${newWorkflowId}/state`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(workflowData),
|
||||
})
|
||||
|
||||
if (!stateResponse.ok) {
|
||||
// Clean up on failure
|
||||
await fetch(`/api/workflows/${newWorkflowId}`, { method: 'DELETE' })
|
||||
throw new Error('Failed to save workflow state')
|
||||
}
|
||||
|
||||
// Save variables if present
|
||||
if (workflowData.variables && Array.isArray(workflowData.variables) && workflowData.variables.length > 0) {
|
||||
const variablesPayload = workflowData.variables.map((v: any) => ({
|
||||
id: v.id,
|
||||
workflowId: newWorkflowId,
|
||||
name: v.name,
|
||||
type: v.type,
|
||||
value: v.value,
|
||||
}))
|
||||
|
||||
await fetch(`/api/workflows/${newWorkflowId}/variables`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ variables: variablesPayload }),
|
||||
})
|
||||
}
|
||||
|
||||
// Refresh workflow list
|
||||
await queryClient.invalidateQueries({ queryKey: workflowKeys.list(workspaceId) })
|
||||
|
||||
const successMsg = metadata.deploymentVersion
|
||||
? `Imported "${metadata.originalName}" v${metadata.deploymentVersion}`
|
||||
: `Imported "${metadata.originalName}"`
|
||||
|
||||
setSuccess(successMsg)
|
||||
setWorkflowId('')
|
||||
|
||||
// Navigate to new workflow
|
||||
setTimeout(() => {
|
||||
router.push(`/workspace/${workspaceId}/w/${newWorkflowId}`)
|
||||
}, 1000)
|
||||
} catch (err) {
|
||||
logger.error('Failed to import workflow:', err)
|
||||
setError(err instanceof Error ? err.message : 'Import failed')
|
||||
} finally {
|
||||
setIsImporting(false)
|
||||
}
|
||||
}
|
||||
|
||||
if (loadingSuperUser) {
|
||||
return (
|
||||
<div className='flex h-full items-center justify-center'>
|
||||
<Loader2 className='h-6 w-6 animate-spin text-[var(--text-40)]' />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (!isSuperUser) {
|
||||
return (
|
||||
<div className='flex h-full items-center justify-center'>
|
||||
<p className='text-[var(--text-40)]'>This feature is only available to superusers.</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='h-full overflow-y-auto p-6'>
|
||||
<div className='mx-auto max-w-2xl space-y-6'>
|
||||
<div>
|
||||
<h2 className='text-lg font-semibold text-[var(--text-90)]'>Import Workflow</h2>
|
||||
<p className='mt-1 text-sm text-[var(--text-40)]'>
|
||||
Import a workflow from the database by ID into this workspace.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className='space-y-4'>
|
||||
<div className='space-y-2'>
|
||||
<Label htmlFor='workflow-id'>Workflow ID</Label>
|
||||
<Input
|
||||
id='workflow-id'
|
||||
placeholder='Enter workflow ID'
|
||||
value={workflowId}
|
||||
onChange={(e) => setWorkflowId(e.target.value)}
|
||||
disabled={isImporting}
|
||||
className='font-mono'
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='flex items-center justify-between rounded-md border border-[var(--surface-11)] p-3'>
|
||||
<div>
|
||||
<Label htmlFor='use-deployment'>Load from deployment</Label>
|
||||
<p className='text-xs text-[var(--text-40)]'>Import a deployed version</p>
|
||||
</div>
|
||||
<Switch
|
||||
id='use-deployment'
|
||||
checked={useDeployment}
|
||||
onCheckedChange={setUseDeployment}
|
||||
disabled={isImporting}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{useDeployment && (
|
||||
<div className='space-y-2'>
|
||||
<Label>Deployment Version</Label>
|
||||
{loadingDeployments ? (
|
||||
<div className='flex items-center gap-2 rounded-md border border-[var(--surface-11)] p-3 text-sm text-[var(--text-40)]'>
|
||||
<Loader2 className='h-4 w-4 animate-spin' />
|
||||
Loading...
|
||||
</div>
|
||||
) : deployments.length === 0 ? (
|
||||
<div className='rounded-md border border-[var(--surface-11)] p-3 text-sm text-[var(--text-40)]'>
|
||||
{workflowId.trim() ? 'No deployments found' : 'Enter a workflow ID'}
|
||||
</div>
|
||||
) : (
|
||||
<Select value={selectedDeployment} onValueChange={setSelectedDeployment} disabled={isImporting}>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder='Select version' />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{deployments.map((d) => (
|
||||
<SelectItem key={d.version} value={String(d.version)}>
|
||||
v{d.version}{d.name ? ` - ${d.name}` : ''}{d.isActive ? ' (Active)' : ''}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{error && (
|
||||
<div className='rounded-md bg-red-500/10 p-3 text-sm text-red-500'>{error}</div>
|
||||
)}
|
||||
|
||||
{success && (
|
||||
<div className='rounded-md bg-green-500/10 p-3 text-sm text-green-500'>{success}</div>
|
||||
)}
|
||||
|
||||
<Button
|
||||
onClick={handleImport}
|
||||
disabled={isImporting || !workflowId.trim() || (useDeployment && !selectedDeployment)}
|
||||
className='w-full'
|
||||
>
|
||||
{isImporting ? (
|
||||
<>
|
||||
<Loader2 className='mr-2 h-4 w-4 animate-spin' />
|
||||
Importing...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Download className='mr-2 h-4 w-4' />
|
||||
Import Workflow
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className='rounded-md border border-yellow-500/20 bg-yellow-500/5 p-4'>
|
||||
<p className='text-xs text-yellow-600 dark:text-yellow-500'>
|
||||
⚠️ Superuser Only - Use responsibly
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
SSO,
|
||||
Subscription,
|
||||
TeamManagement,
|
||||
WorkflowImport,
|
||||
} from '@/app/workspace/[workspaceId]/w/components/sidebar/components-new/settings-modal/components'
|
||||
import { CreatorProfile } from '@/app/workspace/[workspaceId]/w/components/sidebar/components-new/settings-modal/components/creator-profile/creator-profile'
|
||||
import { useGeneralSettings } from '@/hooks/queries/general-settings'
|
||||
@@ -49,6 +50,7 @@ type SettingsSection =
|
||||
| 'copilot'
|
||||
| 'mcp'
|
||||
| 'custom-tools'
|
||||
| 'workflow-import'
|
||||
|
||||
export function SettingsModal({ open, onOpenChange }: SettingsModalProps) {
|
||||
const [activeSection, setActiveSection] = useState<SettingsSection>('general')
|
||||
@@ -212,6 +214,11 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) {
|
||||
<CustomTools />
|
||||
</div>
|
||||
)}
|
||||
{activeSection === 'workflow-import' && (
|
||||
<div className='h-full'>
|
||||
<WorkflowImport />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</ModalContent>
|
||||
|
||||
@@ -90,6 +90,7 @@ export const AgentBlock: BlockConfig<AgentResponse> = {
|
||||
type: 'combobox',
|
||||
placeholder: 'Type or select a model...',
|
||||
required: true,
|
||||
defaultValue: 'claude-sonnet-4-5',
|
||||
options: () => {
|
||||
const providersState = useProvidersStore.getState()
|
||||
const baseModels = providersState.providers.base.models
|
||||
@@ -245,7 +246,7 @@ export const AgentBlock: BlockConfig<AgentResponse> = {
|
||||
type: 'slider',
|
||||
min: 0,
|
||||
max: 1,
|
||||
defaultValue: 0.5,
|
||||
defaultValue: 0.3,
|
||||
condition: () => ({
|
||||
field: 'model',
|
||||
value: (() => {
|
||||
@@ -262,7 +263,7 @@ export const AgentBlock: BlockConfig<AgentResponse> = {
|
||||
type: 'slider',
|
||||
min: 0,
|
||||
max: 2,
|
||||
defaultValue: 1,
|
||||
defaultValue: 0.3,
|
||||
condition: () => ({
|
||||
field: 'model',
|
||||
value: (() => {
|
||||
@@ -383,7 +384,7 @@ Example 3 (Array Input):
|
||||
],
|
||||
config: {
|
||||
tool: (params: Record<string, any>) => {
|
||||
const model = params.model || 'gpt-4o'
|
||||
const model = params.model || 'claude-sonnet-4-5'
|
||||
if (!model) {
|
||||
throw new Error('No model selected')
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ export const AirtableBlock: BlockConfig<AirtableResponse> = {
|
||||
id: 'credential',
|
||||
title: 'Airtable Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'airtable',
|
||||
serviceId: 'airtable',
|
||||
requiredScopes: [
|
||||
'data.records:read',
|
||||
|
||||
@@ -34,7 +34,6 @@ export const AsanaBlock: BlockConfig<AsanaResponse> = {
|
||||
type: 'oauth-input',
|
||||
|
||||
required: true,
|
||||
provider: 'asana',
|
||||
serviceId: 'asana',
|
||||
requiredScopes: ['default'],
|
||||
placeholder: 'Select Asana account',
|
||||
|
||||
@@ -48,7 +48,6 @@ export const ConfluenceBlock: BlockConfig<ConfluenceResponse> = {
|
||||
id: 'credential',
|
||||
title: 'Confluence Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'confluence',
|
||||
serviceId: 'confluence',
|
||||
requiredScopes: [
|
||||
'read:confluence-content.all',
|
||||
@@ -82,7 +81,6 @@ export const ConfluenceBlock: BlockConfig<ConfluenceResponse> = {
|
||||
title: 'Select Page',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'pageId',
|
||||
provider: 'confluence',
|
||||
serviceId: 'confluence',
|
||||
placeholder: 'Select Confluence page',
|
||||
dependsOn: ['credential', 'domain'],
|
||||
|
||||
@@ -71,7 +71,6 @@ export const DiscordBlock: BlockConfig<DiscordResponse> = {
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter Discord server ID',
|
||||
required: true,
|
||||
provider: 'discord',
|
||||
serviceId: 'discord',
|
||||
},
|
||||
// Channel ID - for operations that need it
|
||||
@@ -81,7 +80,6 @@ export const DiscordBlock: BlockConfig<DiscordResponse> = {
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter Discord channel ID',
|
||||
required: true,
|
||||
provider: 'discord',
|
||||
serviceId: 'discord',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
|
||||
372
apps/sim/blocks/blocks/dynamodb.ts
Normal file
372
apps/sim/blocks/blocks/dynamodb.ts
Normal file
@@ -0,0 +1,372 @@
|
||||
import { DynamoDBIcon } from '@/components/icons'
|
||||
import type { BlockConfig } from '@/blocks/types'
|
||||
import type { DynamoDBResponse } from '@/tools/dynamodb/types'
|
||||
|
||||
export const DynamoDBBlock: BlockConfig<DynamoDBResponse> = {
|
||||
type: 'dynamodb',
|
||||
name: 'Amazon DynamoDB',
|
||||
description: 'Connect to Amazon DynamoDB',
|
||||
longDescription:
|
||||
'Integrate Amazon DynamoDB into workflows. Supports Get, Put, Query, Scan, Update, and Delete operations on DynamoDB tables.',
|
||||
docsLink: 'https://docs.sim.ai/tools/dynamodb',
|
||||
category: 'tools',
|
||||
bgColor: 'linear-gradient(45deg, #2E27AD 0%, #527FFF 100%)',
|
||||
icon: DynamoDBIcon,
|
||||
subBlocks: [
|
||||
{
|
||||
id: 'operation',
|
||||
title: 'Operation',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'Get Item', id: 'get' },
|
||||
{ label: 'Put Item', id: 'put' },
|
||||
{ label: 'Query', id: 'query' },
|
||||
{ label: 'Scan', id: 'scan' },
|
||||
{ label: 'Update Item', id: 'update' },
|
||||
{ label: 'Delete Item', id: 'delete' },
|
||||
],
|
||||
value: () => 'get',
|
||||
},
|
||||
{
|
||||
id: 'region',
|
||||
title: 'AWS Region',
|
||||
type: 'short-input',
|
||||
placeholder: 'us-east-1',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'accessKeyId',
|
||||
title: 'AWS Access Key ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'AKIA...',
|
||||
password: true,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'secretAccessKey',
|
||||
title: 'AWS Secret Access Key',
|
||||
type: 'short-input',
|
||||
placeholder: 'Your secret access key',
|
||||
password: true,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'tableName',
|
||||
title: 'Table Name',
|
||||
type: 'short-input',
|
||||
placeholder: 'my-table',
|
||||
required: true,
|
||||
},
|
||||
// Key field for get, update, delete operations
|
||||
{
|
||||
id: 'key',
|
||||
title: 'Key (JSON)',
|
||||
type: 'code',
|
||||
placeholder: '{\n "pk": "user#123"\n}',
|
||||
condition: { field: 'operation', value: 'get' },
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'key',
|
||||
title: 'Key (JSON)',
|
||||
type: 'code',
|
||||
placeholder: '{\n "pk": "user#123"\n}',
|
||||
condition: { field: 'operation', value: 'update' },
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'key',
|
||||
title: 'Key (JSON)',
|
||||
type: 'code',
|
||||
placeholder: '{\n "pk": "user#123"\n}',
|
||||
condition: { field: 'operation', value: 'delete' },
|
||||
required: true,
|
||||
},
|
||||
// Consistent read for get
|
||||
{
|
||||
id: 'consistentRead',
|
||||
title: 'Consistent Read',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'Eventually Consistent', id: 'false' },
|
||||
{ label: 'Strongly Consistent', id: 'true' },
|
||||
],
|
||||
value: () => 'false',
|
||||
condition: { field: 'operation', value: 'get' },
|
||||
},
|
||||
// Item for put operation
|
||||
{
|
||||
id: 'item',
|
||||
title: 'Item (JSON)',
|
||||
type: 'code',
|
||||
placeholder:
|
||||
'{\n "pk": "user#123",\n "name": "John Doe",\n "email": "john@example.com"\n}',
|
||||
condition: { field: 'operation', value: 'put' },
|
||||
required: true,
|
||||
},
|
||||
// Key condition expression for query
|
||||
{
|
||||
id: 'keyConditionExpression',
|
||||
title: 'Key Condition Expression',
|
||||
type: 'short-input',
|
||||
placeholder: 'pk = :pk',
|
||||
condition: { field: 'operation', value: 'query' },
|
||||
required: true,
|
||||
},
|
||||
// Update expression for update operation
|
||||
{
|
||||
id: 'updateExpression',
|
||||
title: 'Update Expression',
|
||||
type: 'short-input',
|
||||
placeholder: 'SET #name = :name',
|
||||
condition: { field: 'operation', value: 'update' },
|
||||
required: true,
|
||||
},
|
||||
// Filter expression for query and scan
|
||||
{
|
||||
id: 'filterExpression',
|
||||
title: 'Filter Expression',
|
||||
type: 'short-input',
|
||||
placeholder: 'attribute_exists(email)',
|
||||
condition: { field: 'operation', value: 'query' },
|
||||
},
|
||||
{
|
||||
id: 'filterExpression',
|
||||
title: 'Filter Expression',
|
||||
type: 'short-input',
|
||||
placeholder: 'attribute_exists(email)',
|
||||
condition: { field: 'operation', value: 'scan' },
|
||||
},
|
||||
// Projection expression for scan
|
||||
{
|
||||
id: 'projectionExpression',
|
||||
title: 'Projection Expression',
|
||||
type: 'short-input',
|
||||
placeholder: 'pk, #name, email',
|
||||
condition: { field: 'operation', value: 'scan' },
|
||||
},
|
||||
// Expression attribute names for query, scan, update
|
||||
{
|
||||
id: 'expressionAttributeNames',
|
||||
title: 'Expression Attribute Names (JSON)',
|
||||
type: 'code',
|
||||
placeholder: '{\n "#name": "name"\n}',
|
||||
condition: { field: 'operation', value: 'query' },
|
||||
},
|
||||
{
|
||||
id: 'expressionAttributeNames',
|
||||
title: 'Expression Attribute Names (JSON)',
|
||||
type: 'code',
|
||||
placeholder: '{\n "#name": "name"\n}',
|
||||
condition: { field: 'operation', value: 'scan' },
|
||||
},
|
||||
{
|
||||
id: 'expressionAttributeNames',
|
||||
title: 'Expression Attribute Names (JSON)',
|
||||
type: 'code',
|
||||
placeholder: '{\n "#name": "name"\n}',
|
||||
condition: { field: 'operation', value: 'update' },
|
||||
},
|
||||
// Expression attribute values for query, scan, update
|
||||
{
|
||||
id: 'expressionAttributeValues',
|
||||
title: 'Expression Attribute Values (JSON)',
|
||||
type: 'code',
|
||||
placeholder: '{\n ":pk": "user#123",\n ":name": "Jane"\n}',
|
||||
condition: { field: 'operation', value: 'query' },
|
||||
},
|
||||
{
|
||||
id: 'expressionAttributeValues',
|
||||
title: 'Expression Attribute Values (JSON)',
|
||||
type: 'code',
|
||||
placeholder: '{\n ":status": "active"\n}',
|
||||
condition: { field: 'operation', value: 'scan' },
|
||||
},
|
||||
{
|
||||
id: 'expressionAttributeValues',
|
||||
title: 'Expression Attribute Values (JSON)',
|
||||
type: 'code',
|
||||
placeholder: '{\n ":name": "Jane Doe"\n}',
|
||||
condition: { field: 'operation', value: 'update' },
|
||||
},
|
||||
// Index name for query
|
||||
{
|
||||
id: 'indexName',
|
||||
title: 'Index Name',
|
||||
type: 'short-input',
|
||||
placeholder: 'GSI1',
|
||||
condition: { field: 'operation', value: 'query' },
|
||||
},
|
||||
// Limit for query and scan
|
||||
{
|
||||
id: 'limit',
|
||||
title: 'Limit',
|
||||
type: 'short-input',
|
||||
placeholder: '100',
|
||||
condition: { field: 'operation', value: 'query' },
|
||||
},
|
||||
{
|
||||
id: 'limit',
|
||||
title: 'Limit',
|
||||
type: 'short-input',
|
||||
placeholder: '100',
|
||||
condition: { field: 'operation', value: 'scan' },
|
||||
},
|
||||
// Condition expression for update and delete
|
||||
{
|
||||
id: 'conditionExpression',
|
||||
title: 'Condition Expression',
|
||||
type: 'short-input',
|
||||
placeholder: 'attribute_exists(pk)',
|
||||
condition: { field: 'operation', value: 'update' },
|
||||
},
|
||||
{
|
||||
id: 'conditionExpression',
|
||||
title: 'Condition Expression',
|
||||
type: 'short-input',
|
||||
placeholder: 'attribute_exists(pk)',
|
||||
condition: { field: 'operation', value: 'delete' },
|
||||
},
|
||||
],
|
||||
tools: {
|
||||
access: [
|
||||
'dynamodb_get',
|
||||
'dynamodb_put',
|
||||
'dynamodb_query',
|
||||
'dynamodb_scan',
|
||||
'dynamodb_update',
|
||||
'dynamodb_delete',
|
||||
],
|
||||
config: {
|
||||
tool: (params) => {
|
||||
switch (params.operation) {
|
||||
case 'get':
|
||||
return 'dynamodb_get'
|
||||
case 'put':
|
||||
return 'dynamodb_put'
|
||||
case 'query':
|
||||
return 'dynamodb_query'
|
||||
case 'scan':
|
||||
return 'dynamodb_scan'
|
||||
case 'update':
|
||||
return 'dynamodb_update'
|
||||
case 'delete':
|
||||
return 'dynamodb_delete'
|
||||
default:
|
||||
throw new Error(`Invalid DynamoDB operation: ${params.operation}`)
|
||||
}
|
||||
},
|
||||
params: (params) => {
|
||||
const {
|
||||
operation,
|
||||
key,
|
||||
item,
|
||||
expressionAttributeNames,
|
||||
expressionAttributeValues,
|
||||
consistentRead,
|
||||
limit,
|
||||
...rest
|
||||
} = params
|
||||
|
||||
// Parse JSON fields
|
||||
const parseJson = (value: unknown, fieldName: string) => {
|
||||
if (!value) return undefined
|
||||
if (typeof value === 'object') return value
|
||||
if (typeof value === 'string' && value.trim()) {
|
||||
try {
|
||||
return JSON.parse(value)
|
||||
} catch (parseError) {
|
||||
const errorMsg =
|
||||
parseError instanceof Error ? parseError.message : 'Unknown JSON error'
|
||||
throw new Error(`Invalid JSON in ${fieldName}: ${errorMsg}`)
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
const parsedKey = parseJson(key, 'key')
|
||||
const parsedItem = parseJson(item, 'item')
|
||||
const parsedExpressionAttributeNames = parseJson(
|
||||
expressionAttributeNames,
|
||||
'expressionAttributeNames'
|
||||
)
|
||||
const parsedExpressionAttributeValues = parseJson(
|
||||
expressionAttributeValues,
|
||||
'expressionAttributeValues'
|
||||
)
|
||||
|
||||
// Build connection config
|
||||
const connectionConfig = {
|
||||
region: rest.region,
|
||||
accessKeyId: rest.accessKeyId,
|
||||
secretAccessKey: rest.secretAccessKey,
|
||||
}
|
||||
|
||||
// Build params object
|
||||
const result: Record<string, unknown> = {
|
||||
...connectionConfig,
|
||||
tableName: rest.tableName,
|
||||
}
|
||||
|
||||
if (parsedKey !== undefined) result.key = parsedKey
|
||||
if (parsedItem !== undefined) result.item = parsedItem
|
||||
if (rest.keyConditionExpression) result.keyConditionExpression = rest.keyConditionExpression
|
||||
if (rest.updateExpression) result.updateExpression = rest.updateExpression
|
||||
if (rest.filterExpression) result.filterExpression = rest.filterExpression
|
||||
if (rest.projectionExpression) result.projectionExpression = rest.projectionExpression
|
||||
if (parsedExpressionAttributeNames !== undefined) {
|
||||
result.expressionAttributeNames = parsedExpressionAttributeNames
|
||||
}
|
||||
if (parsedExpressionAttributeValues !== undefined) {
|
||||
result.expressionAttributeValues = parsedExpressionAttributeValues
|
||||
}
|
||||
if (rest.indexName) result.indexName = rest.indexName
|
||||
if (limit) result.limit = Number.parseInt(String(limit), 10)
|
||||
if (rest.conditionExpression) result.conditionExpression = rest.conditionExpression
|
||||
// Handle consistentRead - dropdown sends 'true'/'false' strings or boolean
|
||||
if (consistentRead === 'true' || consistentRead === true) {
|
||||
result.consistentRead = true
|
||||
}
|
||||
|
||||
return result
|
||||
},
|
||||
},
|
||||
},
|
||||
inputs: {
|
||||
operation: { type: 'string', description: 'DynamoDB operation to perform' },
|
||||
region: { type: 'string', description: 'AWS region' },
|
||||
accessKeyId: { type: 'string', description: 'AWS access key ID' },
|
||||
secretAccessKey: { type: 'string', description: 'AWS secret access key' },
|
||||
tableName: { type: 'string', description: 'DynamoDB table name' },
|
||||
key: { type: 'json', description: 'Primary key for get/update/delete operations' },
|
||||
item: { type: 'json', description: 'Item to put into the table' },
|
||||
keyConditionExpression: { type: 'string', description: 'Key condition for query operations' },
|
||||
updateExpression: { type: 'string', description: 'Update expression for update operations' },
|
||||
filterExpression: { type: 'string', description: 'Filter expression for query/scan' },
|
||||
projectionExpression: { type: 'string', description: 'Attributes to retrieve in scan' },
|
||||
expressionAttributeNames: { type: 'json', description: 'Attribute name mappings' },
|
||||
expressionAttributeValues: { type: 'json', description: 'Expression attribute values' },
|
||||
indexName: { type: 'string', description: 'Secondary index name for query' },
|
||||
limit: { type: 'number', description: 'Maximum items to return' },
|
||||
conditionExpression: { type: 'string', description: 'Condition for update/delete' },
|
||||
consistentRead: { type: 'string', description: 'Use strongly consistent read' },
|
||||
},
|
||||
outputs: {
|
||||
message: {
|
||||
type: 'string',
|
||||
description: 'Success or error message describing the operation outcome',
|
||||
},
|
||||
item: {
|
||||
type: 'json',
|
||||
description: 'Single item returned from get or update operation',
|
||||
},
|
||||
items: {
|
||||
type: 'array',
|
||||
description: 'Array of items returned from query or scan',
|
||||
},
|
||||
count: {
|
||||
type: 'number',
|
||||
description: 'Number of items returned',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -43,7 +43,6 @@ export const GmailBlock: BlockConfig<GmailToolResponse> = {
|
||||
id: 'credential',
|
||||
title: 'Gmail Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'google-email',
|
||||
serviceId: 'gmail',
|
||||
requiredScopes: [
|
||||
'https://www.googleapis.com/auth/gmail.send',
|
||||
@@ -157,7 +156,6 @@ export const GmailBlock: BlockConfig<GmailToolResponse> = {
|
||||
title: 'Label',
|
||||
type: 'folder-selector',
|
||||
canonicalParamId: 'folder',
|
||||
provider: 'google-email',
|
||||
serviceId: 'gmail',
|
||||
requiredScopes: ['https://www.googleapis.com/auth/gmail.labels'],
|
||||
placeholder: 'Select Gmail label/folder',
|
||||
@@ -232,7 +230,6 @@ export const GmailBlock: BlockConfig<GmailToolResponse> = {
|
||||
title: 'Move To Label',
|
||||
type: 'folder-selector',
|
||||
canonicalParamId: 'addLabelIds',
|
||||
provider: 'google-email',
|
||||
serviceId: 'gmail',
|
||||
requiredScopes: ['https://www.googleapis.com/auth/gmail.labels'],
|
||||
placeholder: 'Select destination label',
|
||||
@@ -258,7 +255,6 @@ export const GmailBlock: BlockConfig<GmailToolResponse> = {
|
||||
title: 'Remove From Label',
|
||||
type: 'folder-selector',
|
||||
canonicalParamId: 'removeLabelIds',
|
||||
provider: 'google-email',
|
||||
serviceId: 'gmail',
|
||||
requiredScopes: ['https://www.googleapis.com/auth/gmail.labels'],
|
||||
placeholder: 'Select label to remove',
|
||||
@@ -311,7 +307,6 @@ export const GmailBlock: BlockConfig<GmailToolResponse> = {
|
||||
title: 'Label',
|
||||
type: 'folder-selector',
|
||||
canonicalParamId: 'labelIds',
|
||||
provider: 'google-email',
|
||||
serviceId: 'gmail',
|
||||
requiredScopes: ['https://www.googleapis.com/auth/gmail.labels'],
|
||||
placeholder: 'Select label',
|
||||
|
||||
@@ -33,7 +33,6 @@ export const GoogleCalendarBlock: BlockConfig<GoogleCalendarResponse> = {
|
||||
title: 'Google Calendar Account',
|
||||
type: 'oauth-input',
|
||||
required: true,
|
||||
provider: 'google-calendar',
|
||||
serviceId: 'google-calendar',
|
||||
requiredScopes: ['https://www.googleapis.com/auth/calendar'],
|
||||
placeholder: 'Select Google Calendar account',
|
||||
@@ -44,7 +43,6 @@ export const GoogleCalendarBlock: BlockConfig<GoogleCalendarResponse> = {
|
||||
title: 'Calendar',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'calendarId',
|
||||
provider: 'google-calendar',
|
||||
serviceId: 'google-calendar',
|
||||
requiredScopes: ['https://www.googleapis.com/auth/calendar'],
|
||||
placeholder: 'Select calendar',
|
||||
|
||||
@@ -33,7 +33,6 @@ export const GoogleDocsBlock: BlockConfig<GoogleDocsResponse> = {
|
||||
title: 'Google Account',
|
||||
type: 'oauth-input',
|
||||
required: true,
|
||||
provider: 'google-docs',
|
||||
serviceId: 'google-docs',
|
||||
requiredScopes: [
|
||||
'https://www.googleapis.com/auth/drive.file',
|
||||
@@ -47,7 +46,6 @@ export const GoogleDocsBlock: BlockConfig<GoogleDocsResponse> = {
|
||||
title: 'Select Document',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'documentId',
|
||||
provider: 'google-docs',
|
||||
serviceId: 'google-docs',
|
||||
requiredScopes: [],
|
||||
mimeType: 'application/vnd.google-apps.document',
|
||||
@@ -82,7 +80,6 @@ export const GoogleDocsBlock: BlockConfig<GoogleDocsResponse> = {
|
||||
title: 'Select Parent Folder',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'folderId',
|
||||
provider: 'google-docs',
|
||||
serviceId: 'google-docs',
|
||||
requiredScopes: [],
|
||||
mimeType: 'application/vnd.google-apps.folder',
|
||||
|
||||
@@ -34,7 +34,6 @@ export const GoogleDriveBlock: BlockConfig<GoogleDriveResponse> = {
|
||||
title: 'Google Drive Account',
|
||||
type: 'oauth-input',
|
||||
required: true,
|
||||
provider: 'google-drive',
|
||||
serviceId: 'google-drive',
|
||||
requiredScopes: [
|
||||
'https://www.googleapis.com/auth/drive.file',
|
||||
@@ -104,7 +103,6 @@ export const GoogleDriveBlock: BlockConfig<GoogleDriveResponse> = {
|
||||
title: 'Select Parent Folder',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'folderId',
|
||||
provider: 'google-drive',
|
||||
serviceId: 'google-drive',
|
||||
requiredScopes: [
|
||||
'https://www.googleapis.com/auth/drive.file',
|
||||
@@ -177,7 +175,6 @@ export const GoogleDriveBlock: BlockConfig<GoogleDriveResponse> = {
|
||||
title: 'Select Parent Folder',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'folderId',
|
||||
provider: 'google-drive',
|
||||
serviceId: 'google-drive',
|
||||
requiredScopes: [
|
||||
'https://www.googleapis.com/auth/drive.file',
|
||||
@@ -205,7 +202,6 @@ export const GoogleDriveBlock: BlockConfig<GoogleDriveResponse> = {
|
||||
title: 'Select Folder',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'folderId',
|
||||
provider: 'google-drive',
|
||||
serviceId: 'google-drive',
|
||||
requiredScopes: [
|
||||
'https://www.googleapis.com/auth/drive.file',
|
||||
@@ -247,7 +243,6 @@ export const GoogleDriveBlock: BlockConfig<GoogleDriveResponse> = {
|
||||
title: 'Select File',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'fileId',
|
||||
provider: 'google-drive',
|
||||
serviceId: 'google-drive',
|
||||
requiredScopes: [
|
||||
'https://www.googleapis.com/auth/drive.file',
|
||||
|
||||
@@ -18,7 +18,6 @@ export const GoogleFormsBlock: BlockConfig = {
|
||||
title: 'Google Account',
|
||||
type: 'oauth-input',
|
||||
required: true,
|
||||
provider: 'google-forms',
|
||||
serviceId: 'google-forms',
|
||||
requiredScopes: [
|
||||
'https://www.googleapis.com/auth/userinfo.email',
|
||||
|
||||
@@ -34,7 +34,6 @@ export const GoogleSheetsBlock: BlockConfig<GoogleSheetsResponse> = {
|
||||
title: 'Google Account',
|
||||
type: 'oauth-input',
|
||||
required: true,
|
||||
provider: 'google-sheets',
|
||||
serviceId: 'google-sheets',
|
||||
requiredScopes: [
|
||||
'https://www.googleapis.com/auth/drive.file',
|
||||
@@ -48,7 +47,6 @@ export const GoogleSheetsBlock: BlockConfig<GoogleSheetsResponse> = {
|
||||
title: 'Select Sheet',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'spreadsheetId',
|
||||
provider: 'google-sheets',
|
||||
serviceId: 'google-sheets',
|
||||
requiredScopes: [
|
||||
'https://www.googleapis.com/auth/drive.file',
|
||||
|
||||
@@ -35,7 +35,6 @@ export const GoogleVaultBlock: BlockConfig = {
|
||||
title: 'Google Vault Account',
|
||||
type: 'oauth-input',
|
||||
required: true,
|
||||
provider: 'google-vault',
|
||||
serviceId: 'google-vault',
|
||||
requiredScopes: [
|
||||
'https://www.googleapis.com/auth/ediscovery',
|
||||
|
||||
@@ -39,7 +39,6 @@ export const HubSpotBlock: BlockConfig<HubSpotResponse> = {
|
||||
id: 'credential',
|
||||
title: 'HubSpot Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'hubspot',
|
||||
serviceId: 'hubspot',
|
||||
requiredScopes: [
|
||||
'crm.objects.contacts.read',
|
||||
|
||||
@@ -58,7 +58,6 @@ export const JiraBlock: BlockConfig<JiraResponse> = {
|
||||
title: 'Jira Account',
|
||||
type: 'oauth-input',
|
||||
required: true,
|
||||
provider: 'jira',
|
||||
serviceId: 'jira',
|
||||
requiredScopes: [
|
||||
'read:jira-work',
|
||||
@@ -100,7 +99,6 @@ export const JiraBlock: BlockConfig<JiraResponse> = {
|
||||
title: 'Select Project',
|
||||
type: 'project-selector',
|
||||
canonicalParamId: 'projectId',
|
||||
provider: 'jira',
|
||||
serviceId: 'jira',
|
||||
placeholder: 'Select Jira project',
|
||||
dependsOn: ['credential', 'domain'],
|
||||
@@ -122,7 +120,6 @@ export const JiraBlock: BlockConfig<JiraResponse> = {
|
||||
title: 'Select Issue',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'issueKey',
|
||||
provider: 'jira',
|
||||
serviceId: 'jira',
|
||||
placeholder: 'Select Jira issue',
|
||||
dependsOn: ['credential', 'domain', 'projectId'],
|
||||
|
||||
@@ -129,7 +129,6 @@ export const LinearBlock: BlockConfig<LinearResponse> = {
|
||||
id: 'credential',
|
||||
title: 'Linear Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'linear',
|
||||
serviceId: 'linear',
|
||||
requiredScopes: ['read', 'write'],
|
||||
placeholder: 'Select Linear account',
|
||||
@@ -141,7 +140,6 @@ export const LinearBlock: BlockConfig<LinearResponse> = {
|
||||
title: 'Team',
|
||||
type: 'project-selector',
|
||||
canonicalParamId: 'teamId',
|
||||
provider: 'linear',
|
||||
serviceId: 'linear',
|
||||
placeholder: 'Select a team',
|
||||
dependsOn: ['credential'],
|
||||
@@ -218,7 +216,6 @@ export const LinearBlock: BlockConfig<LinearResponse> = {
|
||||
title: 'Project',
|
||||
type: 'project-selector',
|
||||
canonicalParamId: 'projectId',
|
||||
provider: 'linear',
|
||||
serviceId: 'linear',
|
||||
placeholder: 'Select a project',
|
||||
dependsOn: ['credential', 'teamId'],
|
||||
|
||||
@@ -32,7 +32,6 @@ export const LinkedInBlock: BlockConfig<LinkedInResponse> = {
|
||||
id: 'credential',
|
||||
title: 'LinkedIn Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'linkedin',
|
||||
serviceId: 'linkedin',
|
||||
requiredScopes: ['profile', 'openid', 'email', 'w_member_social'],
|
||||
placeholder: 'Select LinkedIn account',
|
||||
|
||||
@@ -31,7 +31,6 @@ export const MicrosoftExcelBlock: BlockConfig<MicrosoftExcelResponse> = {
|
||||
id: 'credential',
|
||||
title: 'Microsoft Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'microsoft-excel',
|
||||
serviceId: 'microsoft-excel',
|
||||
requiredScopes: [
|
||||
'openid',
|
||||
@@ -49,7 +48,6 @@ export const MicrosoftExcelBlock: BlockConfig<MicrosoftExcelResponse> = {
|
||||
title: 'Select Sheet',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'spreadsheetId',
|
||||
provider: 'microsoft-excel',
|
||||
serviceId: 'microsoft-excel',
|
||||
requiredScopes: [],
|
||||
mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
|
||||
@@ -61,7 +61,6 @@ export const MicrosoftPlannerBlock: BlockConfig<MicrosoftPlannerResponse> = {
|
||||
id: 'credential',
|
||||
title: 'Microsoft Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'microsoft-planner',
|
||||
serviceId: 'microsoft-planner',
|
||||
requiredScopes: [
|
||||
'openid',
|
||||
@@ -94,7 +93,7 @@ export const MicrosoftPlannerBlock: BlockConfig<MicrosoftPlannerResponse> = {
|
||||
title: 'Task ID',
|
||||
type: 'file-selector',
|
||||
placeholder: 'Select a task',
|
||||
provider: 'microsoft-planner',
|
||||
serviceId: 'microsoft-planner',
|
||||
condition: { field: 'operation', value: ['read_task'] },
|
||||
dependsOn: ['credential', 'planId'],
|
||||
mode: 'basic',
|
||||
|
||||
@@ -43,7 +43,6 @@ export const MicrosoftTeamsBlock: BlockConfig<MicrosoftTeamsResponse> = {
|
||||
id: 'credential',
|
||||
title: 'Microsoft Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'microsoft-teams',
|
||||
serviceId: 'microsoft-teams',
|
||||
requiredScopes: [
|
||||
'openid',
|
||||
@@ -75,7 +74,6 @@ export const MicrosoftTeamsBlock: BlockConfig<MicrosoftTeamsResponse> = {
|
||||
title: 'Select Team',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'teamId',
|
||||
provider: 'microsoft-teams',
|
||||
serviceId: 'microsoft-teams',
|
||||
requiredScopes: [],
|
||||
placeholder: 'Select a team',
|
||||
@@ -119,7 +117,6 @@ export const MicrosoftTeamsBlock: BlockConfig<MicrosoftTeamsResponse> = {
|
||||
title: 'Select Chat',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'chatId',
|
||||
provider: 'microsoft-teams',
|
||||
serviceId: 'microsoft-teams',
|
||||
requiredScopes: [],
|
||||
placeholder: 'Select a chat',
|
||||
@@ -147,7 +144,6 @@ export const MicrosoftTeamsBlock: BlockConfig<MicrosoftTeamsResponse> = {
|
||||
title: 'Select Channel',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'channelId',
|
||||
provider: 'microsoft-teams',
|
||||
serviceId: 'microsoft-teams',
|
||||
requiredScopes: [],
|
||||
placeholder: 'Select a channel',
|
||||
|
||||
@@ -34,7 +34,6 @@ export const NotionBlock: BlockConfig<NotionResponse> = {
|
||||
id: 'credential',
|
||||
title: 'Notion Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'notion',
|
||||
serviceId: 'notion',
|
||||
requiredScopes: ['workspace.content', 'workspace.name', 'page.read', 'page.write'],
|
||||
placeholder: 'Select Notion account',
|
||||
|
||||
@@ -38,7 +38,6 @@ export const OneDriveBlock: BlockConfig<OneDriveResponse> = {
|
||||
id: 'credential',
|
||||
title: 'Microsoft Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'onedrive',
|
||||
serviceId: 'onedrive',
|
||||
requiredScopes: [
|
||||
'openid',
|
||||
@@ -144,7 +143,6 @@ export const OneDriveBlock: BlockConfig<OneDriveResponse> = {
|
||||
title: 'Select Parent Folder',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'folderId',
|
||||
provider: 'microsoft',
|
||||
serviceId: 'onedrive',
|
||||
requiredScopes: [
|
||||
'openid',
|
||||
@@ -182,7 +180,6 @@ export const OneDriveBlock: BlockConfig<OneDriveResponse> = {
|
||||
title: 'Select Parent Folder',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'folderId',
|
||||
provider: 'microsoft',
|
||||
serviceId: 'onedrive',
|
||||
requiredScopes: [
|
||||
'openid',
|
||||
@@ -215,7 +212,6 @@ export const OneDriveBlock: BlockConfig<OneDriveResponse> = {
|
||||
title: 'Select Folder',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'folderId',
|
||||
provider: 'microsoft',
|
||||
serviceId: 'onedrive',
|
||||
requiredScopes: [
|
||||
'openid',
|
||||
@@ -262,7 +258,6 @@ export const OneDriveBlock: BlockConfig<OneDriveResponse> = {
|
||||
title: 'Select File',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'fileId',
|
||||
provider: 'microsoft',
|
||||
serviceId: 'onedrive',
|
||||
requiredScopes: [
|
||||
'openid',
|
||||
@@ -302,7 +297,6 @@ export const OneDriveBlock: BlockConfig<OneDriveResponse> = {
|
||||
title: 'Select File to Delete',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'fileId',
|
||||
provider: 'microsoft',
|
||||
serviceId: 'onedrive',
|
||||
requiredScopes: [
|
||||
'openid',
|
||||
|
||||
@@ -38,7 +38,6 @@ export const OutlookBlock: BlockConfig<OutlookResponse> = {
|
||||
id: 'credential',
|
||||
title: 'Microsoft Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'outlook',
|
||||
serviceId: 'outlook',
|
||||
requiredScopes: [
|
||||
'Mail.ReadWrite',
|
||||
@@ -175,7 +174,6 @@ export const OutlookBlock: BlockConfig<OutlookResponse> = {
|
||||
title: 'Folder',
|
||||
type: 'folder-selector',
|
||||
canonicalParamId: 'folder',
|
||||
provider: 'outlook',
|
||||
serviceId: 'outlook',
|
||||
requiredScopes: ['Mail.ReadWrite', 'Mail.ReadBasic', 'Mail.Read'],
|
||||
placeholder: 'Select Outlook folder',
|
||||
@@ -221,7 +219,6 @@ export const OutlookBlock: BlockConfig<OutlookResponse> = {
|
||||
title: 'Move To Folder',
|
||||
type: 'folder-selector',
|
||||
canonicalParamId: 'destinationId',
|
||||
provider: 'outlook',
|
||||
serviceId: 'outlook',
|
||||
requiredScopes: ['Mail.ReadWrite', 'Mail.ReadBasic', 'Mail.Read'],
|
||||
placeholder: 'Select destination folder',
|
||||
@@ -268,7 +265,6 @@ export const OutlookBlock: BlockConfig<OutlookResponse> = {
|
||||
title: 'Copy To Folder',
|
||||
type: 'folder-selector',
|
||||
canonicalParamId: 'copyDestinationId',
|
||||
provider: 'outlook',
|
||||
serviceId: 'outlook',
|
||||
requiredScopes: ['Mail.ReadWrite', 'Mail.ReadBasic', 'Mail.Read'],
|
||||
placeholder: 'Select destination folder',
|
||||
|
||||
@@ -45,7 +45,6 @@ export const PipedriveBlock: BlockConfig<PipedriveResponse> = {
|
||||
id: 'credential',
|
||||
title: 'Pipedrive Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'pipedrive',
|
||||
serviceId: 'pipedrive',
|
||||
requiredScopes: [
|
||||
'base',
|
||||
|
||||
326
apps/sim/blocks/blocks/rds.ts
Normal file
326
apps/sim/blocks/blocks/rds.ts
Normal file
@@ -0,0 +1,326 @@
|
||||
import { RDSIcon } from '@/components/icons'
|
||||
import type { BlockConfig } from '@/blocks/types'
|
||||
import type { RdsResponse } from '@/tools/rds/types'
|
||||
|
||||
export const RDSBlock: BlockConfig<RdsResponse> = {
|
||||
type: 'rds',
|
||||
name: 'Amazon RDS',
|
||||
description: 'Connect to Amazon RDS via Data API',
|
||||
longDescription:
|
||||
'Integrate Amazon RDS Aurora Serverless into the workflow using the Data API. Can query, insert, update, delete, and execute raw SQL without managing database connections.',
|
||||
docsLink: 'https://docs.sim.ai/tools/rds',
|
||||
category: 'tools',
|
||||
bgColor: 'linear-gradient(45deg, #2E27AD 0%, #527FFF 100%)',
|
||||
icon: RDSIcon,
|
||||
subBlocks: [
|
||||
{
|
||||
id: 'operation',
|
||||
title: 'Operation',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'Query (SELECT)', id: 'query' },
|
||||
{ label: 'Insert Data', id: 'insert' },
|
||||
{ label: 'Update Data', id: 'update' },
|
||||
{ label: 'Delete Data', id: 'delete' },
|
||||
{ label: 'Execute Raw SQL', id: 'execute' },
|
||||
],
|
||||
value: () => 'query',
|
||||
},
|
||||
{
|
||||
id: 'region',
|
||||
title: 'AWS Region',
|
||||
type: 'short-input',
|
||||
placeholder: 'us-east-1',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'accessKeyId',
|
||||
title: 'AWS Access Key ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'AKIA...',
|
||||
password: true,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'secretAccessKey',
|
||||
title: 'AWS Secret Access Key',
|
||||
type: 'short-input',
|
||||
placeholder: 'Your secret access key',
|
||||
password: true,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'resourceArn',
|
||||
title: 'Resource ARN',
|
||||
type: 'short-input',
|
||||
placeholder: 'arn:aws:rds:us-east-1:123456789:cluster:my-cluster',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'secretArn',
|
||||
title: 'Secret ARN',
|
||||
type: 'short-input',
|
||||
placeholder: 'arn:aws:secretsmanager:us-east-1:123456789:secret:my-secret',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'database',
|
||||
title: 'Database Name',
|
||||
type: 'short-input',
|
||||
placeholder: 'your_database',
|
||||
required: false,
|
||||
},
|
||||
// Table field for insert/update/delete operations
|
||||
{
|
||||
id: 'table',
|
||||
title: 'Table Name',
|
||||
type: 'short-input',
|
||||
placeholder: 'users',
|
||||
condition: { field: 'operation', value: 'insert' },
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'table',
|
||||
title: 'Table Name',
|
||||
type: 'short-input',
|
||||
placeholder: 'users',
|
||||
condition: { field: 'operation', value: 'update' },
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'table',
|
||||
title: 'Table Name',
|
||||
type: 'short-input',
|
||||
placeholder: 'users',
|
||||
condition: { field: 'operation', value: 'delete' },
|
||||
required: true,
|
||||
},
|
||||
// SQL Query field
|
||||
{
|
||||
id: 'query',
|
||||
title: 'SQL Query',
|
||||
type: 'code',
|
||||
placeholder: 'SELECT * FROM users WHERE active = true',
|
||||
condition: { field: 'operation', value: 'query' },
|
||||
required: true,
|
||||
wandConfig: {
|
||||
enabled: true,
|
||||
maintainHistory: true,
|
||||
prompt: `You are an expert SQL database developer. Write SQL queries based on the user's request.
|
||||
|
||||
### CONTEXT
|
||||
{context}
|
||||
|
||||
### CRITICAL INSTRUCTION
|
||||
Return ONLY the SQL query. Do not include any explanations, markdown formatting, comments, or additional text. Just the raw SQL query.
|
||||
|
||||
### QUERY GUIDELINES
|
||||
1. **Syntax**: Use standard SQL syntax compatible with both MySQL and PostgreSQL
|
||||
2. **Performance**: Write efficient queries with proper indexing considerations
|
||||
3. **Security**: Use parameterized queries when applicable
|
||||
4. **Readability**: Format queries with proper indentation and spacing
|
||||
5. **Best Practices**: Follow standard SQL naming conventions
|
||||
|
||||
### EXAMPLES
|
||||
|
||||
**Simple Select**: "Get all active users"
|
||||
→ SELECT id, name, email, created_at
|
||||
FROM users
|
||||
WHERE active = true
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
**Complex Join**: "Get users with their order counts and total spent"
|
||||
→ SELECT
|
||||
u.id,
|
||||
u.name,
|
||||
u.email,
|
||||
COUNT(o.id) as order_count,
|
||||
COALESCE(SUM(o.total), 0) as total_spent
|
||||
FROM users u
|
||||
LEFT JOIN orders o ON u.id = o.user_id
|
||||
WHERE u.active = true
|
||||
GROUP BY u.id, u.name, u.email
|
||||
HAVING COUNT(o.id) > 0
|
||||
ORDER BY total_spent DESC;
|
||||
|
||||
### REMEMBER
|
||||
Return ONLY the SQL query - no explanations, no markdown, no extra text.`,
|
||||
placeholder: 'Describe the SQL query you need...',
|
||||
generationType: 'sql-query',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'query',
|
||||
title: 'SQL Query',
|
||||
type: 'code',
|
||||
placeholder: 'SELECT * FROM table_name',
|
||||
condition: { field: 'operation', value: 'execute' },
|
||||
required: true,
|
||||
wandConfig: {
|
||||
enabled: true,
|
||||
maintainHistory: true,
|
||||
prompt: `You are an expert SQL database developer. Write SQL queries based on the user's request.
|
||||
|
||||
### CONTEXT
|
||||
{context}
|
||||
|
||||
### CRITICAL INSTRUCTION
|
||||
Return ONLY the SQL query. Do not include any explanations, markdown formatting, comments, or additional text. Just the raw SQL query.
|
||||
|
||||
### QUERY GUIDELINES
|
||||
1. **Syntax**: Use standard SQL syntax compatible with both MySQL and PostgreSQL
|
||||
2. **Performance**: Write efficient queries with proper indexing considerations
|
||||
3. **Security**: Use parameterized queries when applicable
|
||||
4. **Readability**: Format queries with proper indentation and spacing
|
||||
5. **Best Practices**: Follow standard SQL naming conventions
|
||||
|
||||
### EXAMPLES
|
||||
|
||||
**Simple Select**: "Get all active users"
|
||||
→ SELECT id, name, email, created_at
|
||||
FROM users
|
||||
WHERE active = true
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
**Create Table**: "Create a users table"
|
||||
→ CREATE TABLE users (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
email VARCHAR(255) UNIQUE NOT NULL,
|
||||
active BOOLEAN DEFAULT true,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
### REMEMBER
|
||||
Return ONLY the SQL query - no explanations, no markdown, no extra text.`,
|
||||
placeholder: 'Describe the SQL query you need...',
|
||||
generationType: 'sql-query',
|
||||
},
|
||||
},
|
||||
// Data for insert operations
|
||||
{
|
||||
id: 'data',
|
||||
title: 'Data (JSON)',
|
||||
type: 'code',
|
||||
placeholder: '{\n "name": "John Doe",\n "email": "john@example.com",\n "active": true\n}',
|
||||
condition: { field: 'operation', value: 'insert' },
|
||||
required: true,
|
||||
},
|
||||
// Set clause for updates
|
||||
{
|
||||
id: 'data',
|
||||
title: 'Update Data (JSON)',
|
||||
type: 'code',
|
||||
placeholder: '{\n "name": "Jane Doe",\n "email": "jane@example.com"\n}',
|
||||
condition: { field: 'operation', value: 'update' },
|
||||
required: true,
|
||||
},
|
||||
// Conditions for update/delete (parameterized for SQL injection prevention)
|
||||
{
|
||||
id: 'conditions',
|
||||
title: 'Conditions (JSON)',
|
||||
type: 'code',
|
||||
placeholder: '{\n "id": 1\n}',
|
||||
condition: { field: 'operation', value: 'update' },
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'conditions',
|
||||
title: 'Conditions (JSON)',
|
||||
type: 'code',
|
||||
placeholder: '{\n "id": 1\n}',
|
||||
condition: { field: 'operation', value: 'delete' },
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
tools: {
|
||||
access: ['rds_query', 'rds_insert', 'rds_update', 'rds_delete', 'rds_execute'],
|
||||
config: {
|
||||
tool: (params) => {
|
||||
switch (params.operation) {
|
||||
case 'query':
|
||||
return 'rds_query'
|
||||
case 'insert':
|
||||
return 'rds_insert'
|
||||
case 'update':
|
||||
return 'rds_update'
|
||||
case 'delete':
|
||||
return 'rds_delete'
|
||||
case 'execute':
|
||||
return 'rds_execute'
|
||||
default:
|
||||
throw new Error(`Invalid RDS operation: ${params.operation}`)
|
||||
}
|
||||
},
|
||||
params: (params) => {
|
||||
const { operation, data, conditions, ...rest } = params
|
||||
|
||||
// Parse JSON fields
|
||||
const parseJson = (value: unknown, fieldName: string) => {
|
||||
if (!value) return undefined
|
||||
if (typeof value === 'object') return value
|
||||
if (typeof value === 'string' && value.trim()) {
|
||||
try {
|
||||
return JSON.parse(value)
|
||||
} catch (parseError) {
|
||||
const errorMsg =
|
||||
parseError instanceof Error ? parseError.message : 'Unknown JSON error'
|
||||
throw new Error(`Invalid JSON in ${fieldName}: ${errorMsg}`)
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
const parsedData = parseJson(data, 'data')
|
||||
const parsedConditions = parseJson(conditions, 'conditions')
|
||||
|
||||
// Build connection config
|
||||
const connectionConfig = {
|
||||
region: rest.region,
|
||||
accessKeyId: rest.accessKeyId,
|
||||
secretAccessKey: rest.secretAccessKey,
|
||||
resourceArn: rest.resourceArn,
|
||||
secretArn: rest.secretArn,
|
||||
database: rest.database,
|
||||
}
|
||||
|
||||
// Build params object
|
||||
const result: Record<string, unknown> = { ...connectionConfig }
|
||||
|
||||
if (rest.table) result.table = rest.table
|
||||
if (rest.query) result.query = rest.query
|
||||
if (parsedConditions !== undefined) result.conditions = parsedConditions
|
||||
if (parsedData !== undefined) result.data = parsedData
|
||||
|
||||
return result
|
||||
},
|
||||
},
|
||||
},
|
||||
inputs: {
|
||||
operation: { type: 'string', description: 'Database operation to perform' },
|
||||
region: { type: 'string', description: 'AWS region' },
|
||||
accessKeyId: { type: 'string', description: 'AWS access key ID' },
|
||||
secretAccessKey: { type: 'string', description: 'AWS secret access key' },
|
||||
resourceArn: { type: 'string', description: 'Aurora DB cluster ARN' },
|
||||
secretArn: { type: 'string', description: 'Secrets Manager secret ARN' },
|
||||
database: { type: 'string', description: 'Database name' },
|
||||
table: { type: 'string', description: 'Table name' },
|
||||
query: { type: 'string', description: 'SQL query to execute' },
|
||||
data: { type: 'json', description: 'Data for insert/update operations' },
|
||||
conditions: { type: 'json', description: 'Conditions for update/delete (e.g., {"id": 1})' },
|
||||
},
|
||||
outputs: {
|
||||
message: {
|
||||
type: 'string',
|
||||
description: 'Success or error message describing the operation outcome',
|
||||
},
|
||||
rows: {
|
||||
type: 'array',
|
||||
description: 'Array of rows returned from the query',
|
||||
},
|
||||
rowCount: {
|
||||
type: 'number',
|
||||
description: 'Number of rows affected by the operation',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -42,7 +42,6 @@ export const RedditBlock: BlockConfig<RedditResponse> = {
|
||||
id: 'credential',
|
||||
title: 'Reddit Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'reddit',
|
||||
serviceId: 'reddit',
|
||||
requiredScopes: [
|
||||
'identity',
|
||||
|
||||
@@ -12,7 +12,7 @@ export const S3Block: BlockConfig<S3Response> = {
|
||||
'Integrate S3 into the workflow. Upload files, download objects, list bucket contents, delete objects, and copy objects between buckets. Requires AWS access key and secret access key.',
|
||||
docsLink: 'https://docs.sim.ai/tools/s3',
|
||||
category: 'tools',
|
||||
bgColor: '#E0E0E0',
|
||||
bgColor: 'linear-gradient(45deg, #1B660F 0%, #6CAE3E 100%)',
|
||||
icon: S3Icon,
|
||||
subBlocks: [
|
||||
// Operation selector
|
||||
|
||||
@@ -51,7 +51,6 @@ export const SalesforceBlock: BlockConfig<SalesforceResponse> = {
|
||||
id: 'credential',
|
||||
title: 'Salesforce Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'salesforce',
|
||||
serviceId: 'salesforce',
|
||||
requiredScopes: ['api', 'refresh_token', 'openid'],
|
||||
placeholder: 'Select Salesforce account',
|
||||
|
||||
@@ -37,7 +37,6 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
|
||||
id: 'credential',
|
||||
title: 'Microsoft Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'sharepoint',
|
||||
serviceId: 'sharepoint',
|
||||
requiredScopes: [
|
||||
'openid',
|
||||
@@ -56,7 +55,6 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
|
||||
title: 'Select Site',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'siteId',
|
||||
provider: 'microsoft',
|
||||
serviceId: 'sharepoint',
|
||||
requiredScopes: [
|
||||
'openid',
|
||||
|
||||
@@ -48,7 +48,6 @@ export const SlackBlock: BlockConfig<SlackResponse> = {
|
||||
id: 'credential',
|
||||
title: 'Slack Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'slack',
|
||||
serviceId: 'slack',
|
||||
requiredScopes: [
|
||||
'channels:read',
|
||||
@@ -85,7 +84,7 @@ export const SlackBlock: BlockConfig<SlackResponse> = {
|
||||
title: 'Channel',
|
||||
type: 'channel-selector',
|
||||
canonicalParamId: 'channel',
|
||||
provider: 'slack',
|
||||
serviceId: 'slack',
|
||||
placeholder: 'Select Slack channel',
|
||||
mode: 'basic',
|
||||
dependsOn: ['credential', 'authMethod'],
|
||||
|
||||
@@ -41,7 +41,6 @@ export const TrelloBlock: BlockConfig<ToolResponse> = {
|
||||
id: 'credential',
|
||||
title: 'Trello Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'trello',
|
||||
serviceId: 'trello',
|
||||
requiredScopes: ['read', 'write'],
|
||||
placeholder: 'Select Trello account',
|
||||
|
||||
@@ -33,7 +33,6 @@ export const WealthboxBlock: BlockConfig<WealthboxResponse> = {
|
||||
id: 'credential',
|
||||
title: 'Wealthbox Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'wealthbox',
|
||||
serviceId: 'wealthbox',
|
||||
requiredScopes: ['login', 'data'],
|
||||
placeholder: 'Select Wealthbox account',
|
||||
@@ -50,7 +49,6 @@ export const WealthboxBlock: BlockConfig<WealthboxResponse> = {
|
||||
id: 'contactId',
|
||||
title: 'Select Contact',
|
||||
type: 'file-selector',
|
||||
provider: 'wealthbox',
|
||||
serviceId: 'wealthbox',
|
||||
requiredScopes: ['login', 'data'],
|
||||
placeholder: 'Enter Contact ID',
|
||||
|
||||
@@ -34,7 +34,6 @@ export const WebflowBlock: BlockConfig<WebflowResponse> = {
|
||||
id: 'credential',
|
||||
title: 'Webflow Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'webflow',
|
||||
serviceId: 'webflow',
|
||||
requiredScopes: ['sites:read', 'sites:write', 'cms:read', 'cms:write'],
|
||||
placeholder: 'Select Webflow account',
|
||||
|
||||
@@ -90,7 +90,6 @@ export const WebhookBlock: BlockConfig = {
|
||||
id: 'gmailCredential',
|
||||
title: 'Gmail Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'google-email',
|
||||
serviceId: 'gmail',
|
||||
requiredScopes: [
|
||||
'https://www.googleapis.com/auth/gmail.modify',
|
||||
@@ -104,7 +103,6 @@ export const WebhookBlock: BlockConfig = {
|
||||
id: 'outlookCredential',
|
||||
title: 'Microsoft Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'outlook',
|
||||
serviceId: 'outlook',
|
||||
requiredScopes: [
|
||||
'Mail.ReadWrite',
|
||||
|
||||
@@ -31,7 +31,6 @@ export const XBlock: BlockConfig<XResponse> = {
|
||||
id: 'credential',
|
||||
title: 'X Account',
|
||||
type: 'oauth-input',
|
||||
provider: 'x',
|
||||
serviceId: 'x',
|
||||
requiredScopes: ['tweet.read', 'tweet.write', 'users.read', 'offline.access'],
|
||||
placeholder: 'Select X account',
|
||||
|
||||
@@ -13,6 +13,7 @@ import { ClayBlock } from '@/blocks/blocks/clay'
|
||||
import { ConditionBlock } from '@/blocks/blocks/condition'
|
||||
import { ConfluenceBlock } from '@/blocks/blocks/confluence'
|
||||
import { DiscordBlock } from '@/blocks/blocks/discord'
|
||||
import { DynamoDBBlock } from '@/blocks/blocks/dynamodb'
|
||||
import { ElevenLabsBlock } from '@/blocks/blocks/elevenlabs'
|
||||
import { EvaluatorBlock } from '@/blocks/blocks/evaluator'
|
||||
import { ExaBlock } from '@/blocks/blocks/exa'
|
||||
@@ -70,6 +71,7 @@ import { PostgreSQLBlock } from '@/blocks/blocks/postgresql'
|
||||
import { PostHogBlock } from '@/blocks/blocks/posthog'
|
||||
import { PylonBlock } from '@/blocks/blocks/pylon'
|
||||
import { QdrantBlock } from '@/blocks/blocks/qdrant'
|
||||
import { RDSBlock } from '@/blocks/blocks/rds'
|
||||
import { RedditBlock } from '@/blocks/blocks/reddit'
|
||||
import { ResendBlock } from '@/blocks/blocks/resend'
|
||||
import { ResponseBlock } from '@/blocks/blocks/response'
|
||||
@@ -189,6 +191,8 @@ export const registry: Record<string, BlockConfig> = {
|
||||
posthog: PostHogBlock,
|
||||
pylon: PylonBlock,
|
||||
qdrant: QdrantBlock,
|
||||
rds: RDSBlock,
|
||||
dynamodb: DynamoDBBlock,
|
||||
reddit: RedditBlock,
|
||||
resend: ResendBlock,
|
||||
response: ResponseBlock,
|
||||
|
||||
@@ -222,8 +222,7 @@ export interface SubBlockConfig {
|
||||
generationType?: GenerationType
|
||||
collapsible?: boolean // Whether the code block can be collapsed
|
||||
defaultCollapsed?: boolean // Whether the code block is collapsed by default
|
||||
// OAuth specific properties
|
||||
provider?: string
|
||||
// OAuth specific properties - serviceId is the canonical identifier for OAuth services
|
||||
serviceId?: string
|
||||
requiredScopes?: string[]
|
||||
// File selector specific properties
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -157,7 +157,7 @@ export const HTTP = {
|
||||
} as const
|
||||
|
||||
export const AGENT = {
|
||||
DEFAULT_MODEL: 'gpt-4o',
|
||||
DEFAULT_MODEL: 'claude-sonnet-4-5',
|
||||
DEFAULT_FUNCTION_TIMEOUT: 5000,
|
||||
REQUEST_TIMEOUT: 120000,
|
||||
CUSTOM_TOOL_PREFIX: 'custom_',
|
||||
|
||||
24
apps/sim/hooks/queries/super-user.ts
Normal file
24
apps/sim/hooks/queries/super-user.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
|
||||
export const superUserKeys = {
|
||||
status: () => ['superUserStatus'] as const,
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to fetch the current user's superuser status
|
||||
*/
|
||||
export function useSuperUserStatus() {
|
||||
return useQuery({
|
||||
queryKey: superUserKeys.status(),
|
||||
queryFn: async () => {
|
||||
const response = await fetch('/api/user/super-user')
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch super user status')
|
||||
}
|
||||
return response.json() as Promise<{ isSuperUser: boolean }>
|
||||
},
|
||||
staleTime: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
})
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user