Add Activepieces integration for workflow automation
- Add Activepieces fork with SmoothSchedule custom piece - Create integrations app with Activepieces service layer - Add embed token endpoint for iframe integration - Create Automations page with embedded workflow builder - Add sidebar visibility fix for embed mode - Add list inactive customers endpoint to Public API - Include SmoothSchedule triggers: event created/updated/cancelled - Include SmoothSchedule actions: create/update/cancel events, list resources/services/customers 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": ["../../../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# pieces-browse-ai
|
||||
|
||||
This library was generated with [Nx](https://nx.dev).
|
||||
|
||||
## Building
|
||||
|
||||
Run `nx build pieces-browse-ai` to build the library.
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "@activepieces/piece-browse-ai",
|
||||
"version": "0.0.6",
|
||||
"type": "commonjs",
|
||||
"main": "./src/index.js",
|
||||
"types": "./src/index.d.ts",
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"name": "pieces-browse-ai",
|
||||
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "packages/pieces/community/browse-ai/src",
|
||||
"projectType": "library",
|
||||
"release": {
|
||||
"version": {
|
||||
"manifestRootsToUpdate": [
|
||||
"dist/{projectRoot}"
|
||||
],
|
||||
"currentVersionResolver": "git-tag",
|
||||
"fallbackCurrentVersionResolver": "disk"
|
||||
}
|
||||
},
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@nx/js:tsc",
|
||||
"outputs": [
|
||||
"{options.outputPath}"
|
||||
],
|
||||
"options": {
|
||||
"outputPath": "dist/packages/pieces/community/browse-ai",
|
||||
"tsConfig": "packages/pieces/community/browse-ai/tsconfig.lib.json",
|
||||
"packageJson": "packages/pieces/community/browse-ai/package.json",
|
||||
"main": "packages/pieces/community/browse-ai/src/index.ts",
|
||||
"assets": [
|
||||
"packages/pieces/community/browse-ai/*.md",
|
||||
{
|
||||
"input": "packages/pieces/community/browse-ai/src/i18n",
|
||||
"output": "./src/i18n",
|
||||
"glob": "**/!(i18n.json)"
|
||||
}
|
||||
],
|
||||
"buildableProjectDepsInPackageJsonType": "dependencies",
|
||||
"updateBuildableProjectDepsInPackageJson": true
|
||||
},
|
||||
"dependsOn": [
|
||||
"^build",
|
||||
"prebuild"
|
||||
]
|
||||
},
|
||||
"nx-release-publish": {
|
||||
"options": {
|
||||
"packageRoot": "dist/{projectRoot}"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nx/eslint:lint",
|
||||
"outputs": [
|
||||
"{options.outputFile}"
|
||||
]
|
||||
},
|
||||
"prebuild": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"cwd": "packages/pieces/community/browse-ai",
|
||||
"command": "bun install --no-save --silent"
|
||||
},
|
||||
"dependsOn": [
|
||||
"^build"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"You can find your Browse AI API key on the dashboard under Settings → API Key.": "Unter Einstellungen → API-Schlüssel finden Sie den AI-API-Schlüssel auf dem Dashboard.",
|
||||
"Get Task Details": "Aufgabendetails abrufen",
|
||||
"List Robots": "List Robots",
|
||||
"Run a Robot": "Roboter ausführen",
|
||||
"Custom API Call": "Eigener API-Aufruf",
|
||||
"Retrieves the details of a specific task executed by a Browse AI robot.": "Ruft die Details einer bestimmten Aufgabe ab, die von einem Browse AI Roboter ausgeführt wird.",
|
||||
"Retrieves all robots available in your account.": "Ruft alle Roboter in deinem Account ab.",
|
||||
"Runs a robot on-demand with custom input parameters.": "Führt einen Roboter auf Abruf mit benutzerdefinierten Eingabeparametern aus.",
|
||||
"Make a custom API call to a specific endpoint": "Einen benutzerdefinierten API-Aufruf an einen bestimmten Endpunkt machen",
|
||||
"Robot": "Robot",
|
||||
"Task": "Aufgabe",
|
||||
"Record Video": "Video aufnehmen",
|
||||
"Input Parameters": "Eingabeparameter",
|
||||
"Method": "Methode",
|
||||
"Headers": "Kopfzeilen",
|
||||
"Query Parameters": "Abfrageparameter",
|
||||
"Body": "Körper",
|
||||
"Response is Binary ?": "Antwort ist binär?",
|
||||
"No Error on Failure": "Kein Fehler bei Fehler",
|
||||
"Timeout (in seconds)": "Timeout (in Sekunden)",
|
||||
"Select a robot from your Browse AI account": "Wählen Sie einen Roboter aus Ihrem Browse KI Konto",
|
||||
"Select a task associated with the selected robot": "Wählen Sie eine Aufgabe, die mit dem ausgewählten Roboter verknüpft ist",
|
||||
"Try to record a video while running the task.": "Versuchen Sie, ein Video aufzuzeichnen, während Sie die Aufgabe ausführen.",
|
||||
"Authorization headers are injected automatically from your connection.": "Autorisierungs-Header werden automatisch von Ihrer Verbindung injiziert.",
|
||||
"Enable for files like PDFs, images, etc..": "Aktivieren für Dateien wie PDFs, Bilder, etc..",
|
||||
"GET": "ERHALTEN",
|
||||
"POST": "POST",
|
||||
"PATCH": "PATCH",
|
||||
"PUT": "PUT",
|
||||
"DELETE": "LÖSCHEN",
|
||||
"HEAD": "HEAD",
|
||||
"Task Finished with Error": "Aufgabe abgeschlossen mit Fehler",
|
||||
"Task Finished Successfully": "Aufgabe erfolgreich beendet",
|
||||
"Triggers when a robot task run fails with an error.": "Wird ausgelöst, wenn ein Roboter-Task mit einem Fehler fehlschlägt.",
|
||||
"Triggers when a robot finishes a task successfully.": "Wird ausgelöst, wenn ein Roboter eine Aufgabe erfolgreich erledigt."
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"You can find your Browse AI API key on the dashboard under Settings → API Key.": "Puede encontrar su clave API de navegación en el panel de control en Configuración → Clave API.",
|
||||
"Get Task Details": "Obtener Detalles de Tarea",
|
||||
"List Robots": "List Robots",
|
||||
"Run a Robot": "Ejecutar un Robot",
|
||||
"Custom API Call": "Llamada API personalizada",
|
||||
"Retrieves the details of a specific task executed by a Browse AI robot.": "Devuelve los detalles de una tarea específica ejecutada por un robot de exploración de IA.",
|
||||
"Retrieves all robots available in your account.": "Recupera todos los robots disponibles en tu cuenta.",
|
||||
"Runs a robot on-demand with custom input parameters.": "Ejecuta un robot bajo demanda con parámetros de entrada personalizados.",
|
||||
"Make a custom API call to a specific endpoint": "Hacer una llamada API personalizada a un extremo específico",
|
||||
"Robot": "Robot",
|
||||
"Task": "Tarea",
|
||||
"Record Video": "Grabar vídeo",
|
||||
"Input Parameters": "Parámetros de entrada",
|
||||
"Method": "Método",
|
||||
"Headers": "Encabezados",
|
||||
"Query Parameters": "Parámetros de consulta",
|
||||
"Body": "Cuerpo",
|
||||
"Response is Binary ?": "¿Respuesta es binaria?",
|
||||
"No Error on Failure": "No hay ningún error en fallo",
|
||||
"Timeout (in seconds)": "Tiempo de espera (en segundos)",
|
||||
"Select a robot from your Browse AI account": "Selecciona un robot de tu cuenta de exploración de IA",
|
||||
"Select a task associated with the selected robot": "Seleccione una tarea asociada con el robot seleccionado",
|
||||
"Try to record a video while running the task.": "Intenta grabar un vídeo mientras ejecutas la tarea.",
|
||||
"Authorization headers are injected automatically from your connection.": "Las cabeceras de autorización se inyectan automáticamente desde tu conexión.",
|
||||
"Enable for files like PDFs, images, etc..": "Activar para archivos como PDFs, imágenes, etc.",
|
||||
"GET": "RECOGER",
|
||||
"POST": "POST",
|
||||
"PATCH": "PATCH",
|
||||
"PUT": "PUT",
|
||||
"DELETE": "BORRAR",
|
||||
"HEAD": "LIMPIO",
|
||||
"Task Finished with Error": "Tarea Terminada con Error",
|
||||
"Task Finished Successfully": "Tarea finalizada con éxito",
|
||||
"Triggers when a robot task run fails with an error.": "Dispara cuando una tarea de robot falle con un error.",
|
||||
"Triggers when a robot finishes a task successfully.": "Dispara cuando un robot finaliza una tarea con éxito."
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"You can find your Browse AI API key on the dashboard under Settings → API Key.": "Vous pouvez trouver votre clé API Parcourir l'IA dans le tableau de bord sous Paramètres → Clé API.",
|
||||
"Get Task Details": "Obtenir les détails de la tâche",
|
||||
"List Robots": "List Robots",
|
||||
"Run a Robot": "Exécuter un robot",
|
||||
"Custom API Call": "Appel API personnalisé",
|
||||
"Retrieves the details of a specific task executed by a Browse AI robot.": "Récupère les détails d'une tâche spécifique exécutée par un robot Parcourir les IA.",
|
||||
"Retrieves all robots available in your account.": "Récupère tous les robots disponibles dans votre compte.",
|
||||
"Runs a robot on-demand with custom input parameters.": "Exécute un robot à la demande avec des paramètres d'entrée personnalisés.",
|
||||
"Make a custom API call to a specific endpoint": "Passez un appel API personnalisé à un point de terminaison spécifique",
|
||||
"Robot": "Robot",
|
||||
"Task": "Tâche",
|
||||
"Record Video": "Enregistrer la vidéo",
|
||||
"Input Parameters": "Paramètres d'entrée",
|
||||
"Method": "Méthode",
|
||||
"Headers": "En-têtes",
|
||||
"Query Parameters": "Paramètres de requête",
|
||||
"Body": "Corps",
|
||||
"Response is Binary ?": "La réponse est Binaire ?",
|
||||
"No Error on Failure": "Aucune erreur en cas d'échec",
|
||||
"Timeout (in seconds)": "Délai d'attente (en secondes)",
|
||||
"Select a robot from your Browse AI account": "Sélectionnez un robot dans votre compte Parcourir les AI",
|
||||
"Select a task associated with the selected robot": "Sélectionnez une tâche associée au robot sélectionné",
|
||||
"Try to record a video while running the task.": "Essayez d'enregistrer une vidéo pendant l'exécution de la tâche.",
|
||||
"Authorization headers are injected automatically from your connection.": "Les en-têtes d'autorisation sont injectés automatiquement à partir de votre connexion.",
|
||||
"Enable for files like PDFs, images, etc..": "Activer pour les fichiers comme les PDFs, les images, etc.",
|
||||
"GET": "OBTENIR",
|
||||
"POST": "POSTER",
|
||||
"PATCH": "PATCH",
|
||||
"PUT": "EFFACER",
|
||||
"DELETE": "SUPPRIMER",
|
||||
"HEAD": "TÊTE",
|
||||
"Task Finished with Error": "Tâche terminée avec erreur",
|
||||
"Task Finished Successfully": "Tâche terminée avec succès",
|
||||
"Triggers when a robot task run fails with an error.": "Déclenche quand une tâche de robot échoue avec une erreur.",
|
||||
"Triggers when a robot finishes a task successfully.": "Déclenche quand un robot termine une tâche avec succès."
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"You can find your Browse AI API key on the dashboard under Settings → API Key.": "ダッシュボードの format@@0 → format@@1 キーで、AI API キーを参照できます。",
|
||||
"Get Task Details": "タスクの詳細を取得する",
|
||||
"List Robots": "List Robots",
|
||||
"Run a Robot": "ロボットを実行する",
|
||||
"Custom API Call": "カスタムAPI通話",
|
||||
"Retrieves the details of a specific task executed by a Browse AI robot.": "ブラウズAIロボットで実行される特定のタスクの詳細を取得します。",
|
||||
"Retrieves all robots available in your account.": "アカウントで利用可能なすべてのロボットを取得します。",
|
||||
"Runs a robot on-demand with custom input parameters.": "カスタム入力パラメータでロボットをオンデマンドで実行します。",
|
||||
"Make a custom API call to a specific endpoint": "特定のエンドポイントへのカスタム API コールを実行します。",
|
||||
"Robot": "Robot",
|
||||
"Task": "タスク",
|
||||
"Record Video": "ビデオを録画する",
|
||||
"Input Parameters": "入力パラメータ",
|
||||
"Method": "方法",
|
||||
"Headers": "ヘッダー",
|
||||
"Query Parameters": "クエリパラメータ",
|
||||
"Body": "本文",
|
||||
"Response is Binary ?": "応答はバイナリですか?",
|
||||
"No Error on Failure": "失敗時にエラーはありません",
|
||||
"Timeout (in seconds)": "タイムアウト(秒)",
|
||||
"Select a robot from your Browse AI account": "ブラウズAIアカウントからロボットを選択します",
|
||||
"Select a task associated with the selected robot": "選択したロボットに関連付けられているタスクを選択します",
|
||||
"Try to record a video while running the task.": "タスクの実行中にビデオを録画してみてください。",
|
||||
"Authorization headers are injected automatically from your connection.": "認証ヘッダは接続から自動的に注入されます。",
|
||||
"Enable for files like PDFs, images, etc..": "PDF、画像などのファイルを有効にします。",
|
||||
"GET": "取得",
|
||||
"POST": "POST",
|
||||
"PATCH": "PATCH",
|
||||
"PUT": "PUT",
|
||||
"DELETE": "削除",
|
||||
"HEAD": "頭",
|
||||
"Task Finished with Error": "タスクがエラーで終了しました",
|
||||
"Task Finished Successfully": "タスクが完了しました",
|
||||
"Triggers when a robot task run fails with an error.": "ロボットタスクの実行がエラーで失敗したときにトリガーします。",
|
||||
"Triggers when a robot finishes a task successfully.": "ロボットがタスクを正常に終了したときにトリガーします。"
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"You can find your Browse AI API key on the dashboard under Settings → API Key.": "Je kunt je Blader API-sleutel vinden op het dashboard onder Instellingen → API Key.",
|
||||
"Get Task Details": "Verkrijg Taakgegevens",
|
||||
"List Robots": "List Robots",
|
||||
"Run a Robot": "Voer een robot uit",
|
||||
"Custom API Call": "Custom API Call",
|
||||
"Retrieves the details of a specific task executed by a Browse AI robot.": "Haal de details op van een specifieke taak uitgevoerd door een Browse AI robot.",
|
||||
"Retrieves all robots available in your account.": "Haal alle robots op die in je account beschikbaar zijn.",
|
||||
"Runs a robot on-demand with custom input parameters.": "Voer een robot op aanvraag uit met aangepaste invoerparameters.",
|
||||
"Make a custom API call to a specific endpoint": "Maak een aangepaste API call naar een specifiek eindpunt",
|
||||
"Robot": "Robot",
|
||||
"Task": "Opdracht",
|
||||
"Record Video": "Video opnemen",
|
||||
"Input Parameters": "Invoer parameters",
|
||||
"Method": "Methode",
|
||||
"Headers": "Kopteksten",
|
||||
"Query Parameters": "Query parameters",
|
||||
"Body": "Lichaam",
|
||||
"Response is Binary ?": "Antwoord is binair?",
|
||||
"No Error on Failure": "Geen fout bij fout",
|
||||
"Timeout (in seconds)": "Time-out (in seconden)",
|
||||
"Select a robot from your Browse AI account": "Selecteer een robot in uw account Blader AI",
|
||||
"Select a task associated with the selected robot": "Selecteer een taak gekoppeld aan de geselecteerde robot",
|
||||
"Try to record a video while running the task.": "Probeer een video op te nemen tijdens het uitvoeren van de taak.",
|
||||
"Authorization headers are injected automatically from your connection.": "Autorisatie headers worden automatisch geïnjecteerd vanuit uw verbinding.",
|
||||
"Enable for files like PDFs, images, etc..": "Inschakelen voor bestanden zoals PDF's, afbeeldingen etc..",
|
||||
"GET": "KRIJG",
|
||||
"POST": "POSTE",
|
||||
"PATCH": "BEKIJK",
|
||||
"PUT": "PUT",
|
||||
"DELETE": "VERWIJDEREN",
|
||||
"HEAD": "HOOFD",
|
||||
"Task Finished with Error": "Taak beëindigd met een fout",
|
||||
"Task Finished Successfully": "Taak Succesvol Voltooid",
|
||||
"Triggers when a robot task run fails with an error.": "Taak van een robot wordt uitgevoerd met een fout.",
|
||||
"Triggers when a robot finishes a task successfully.": "Triggert een robot met succes een taak af."
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"You can find your Browse AI API key on the dashboard under Settings → API Key.": "Você pode encontrar sua chave de Navegação API no painel em Configurações → Chave de API.",
|
||||
"Get Task Details": "Obter Detalhes da Tarefa",
|
||||
"List Robots": "List Robots",
|
||||
"Run a Robot": "Executar um robô",
|
||||
"Custom API Call": "Chamada de API personalizada",
|
||||
"Retrieves the details of a specific task executed by a Browse AI robot.": "Obtém detalhes de uma tarefa específica executada por um robô AI.",
|
||||
"Retrieves all robots available in your account.": "Recupera todos os robôs disponíveis em sua conta.",
|
||||
"Runs a robot on-demand with custom input parameters.": "Executa um robô sob demanda com parâmetros de entrada personalizados.",
|
||||
"Make a custom API call to a specific endpoint": "Faça uma chamada de API personalizada para um ponto de extremidade específico",
|
||||
"Robot": "Robot",
|
||||
"Task": "Tarefas",
|
||||
"Record Video": "Gravar Vídeo",
|
||||
"Input Parameters": "Parâmetros de entrada",
|
||||
"Method": "Método",
|
||||
"Headers": "Cabeçalhos",
|
||||
"Query Parameters": "Parâmetros da consulta",
|
||||
"Body": "Conteúdo",
|
||||
"Response is Binary ?": "A resposta é binária ?",
|
||||
"No Error on Failure": "Nenhum erro no Failure",
|
||||
"Timeout (in seconds)": "Tempo limite (em segundos)",
|
||||
"Select a robot from your Browse AI account": "Selecione um robô de sua conta de Navegação IA",
|
||||
"Select a task associated with the selected robot": "Selecione uma tarefa associada com o robô selecionado",
|
||||
"Try to record a video while running the task.": "Tente gravar um vídeo durante a execução da tarefa.",
|
||||
"Authorization headers are injected automatically from your connection.": "Os cabeçalhos de autorização são inseridos automaticamente a partir da sua conexão.",
|
||||
"Enable for files like PDFs, images, etc..": "Habilitar para arquivos como PDFs, imagens, etc..",
|
||||
"GET": "OBTER",
|
||||
"POST": "POSTAR",
|
||||
"PATCH": "COMPRAR",
|
||||
"PUT": "COLOCAR",
|
||||
"DELETE": "EXCLUIR",
|
||||
"HEAD": "CABEÇA",
|
||||
"Task Finished with Error": "Tarefa concluída com erro",
|
||||
"Task Finished Successfully": "Tarefa concluída com sucesso",
|
||||
"Triggers when a robot task run fails with an error.": "Aciona quando uma tarefa do robô executada falha com um erro.",
|
||||
"Triggers when a robot finishes a task successfully.": "Aciona quando um robô termina uma tarefa com sucesso."
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"Browse AI": "Просмотр ИИ",
|
||||
"You can find your Browse AI API key on the dashboard under Settings → API Key.": "Вы можете найти ваш Browse AI API ключ на приборной панели в меню Настройки → API Key.",
|
||||
"Get Task Details": "Получить детали задачи",
|
||||
"List Robots": "List Robots",
|
||||
"Run a Robot": "Запустить робота",
|
||||
"Custom API Call": "Пользовательский вызов API",
|
||||
"Retrieves the details of a specific task executed by a Browse AI robot.": "Возвращает детали конкретной задачи, выполненной роботом Обзор ИИ.",
|
||||
"Retrieves all robots available in your account.": "Возвращает все роботы, доступные в вашей учетной записи.",
|
||||
"Runs a robot on-demand with custom input parameters.": "Выполняет робот по требованию с пользовательскими параметрами ввода.",
|
||||
"Make a custom API call to a specific endpoint": "Сделать пользовательский API вызов к определенной конечной точке",
|
||||
"Robot": "Robot",
|
||||
"Task": "Задача",
|
||||
"Record Video": "Запись видео",
|
||||
"Input Parameters": "Входные параметры",
|
||||
"Method": "Метод",
|
||||
"Headers": "Заголовки",
|
||||
"Query Parameters": "Параметры запроса",
|
||||
"Body": "Тело",
|
||||
"No Error on Failure": "Нет ошибок при ошибке",
|
||||
"Timeout (in seconds)": "Таймаут (в секундах)",
|
||||
"Select a robot from your Browse AI account": "Выберите робота из Browse AI аккаунта",
|
||||
"Select a task associated with the selected robot": "Выберите задачу, связанную с выбранным роботом",
|
||||
"Try to record a video while running the task.": "Попробуйте записать видео во время выполнения задачи.",
|
||||
"Authorization headers are injected automatically from your connection.": "Заголовки авторизации включаются автоматически из вашего соединения.",
|
||||
"GET": "ПОЛУЧИТЬ",
|
||||
"POST": "ПОСТ",
|
||||
"PATCH": "ПАТЧ",
|
||||
"PUT": "ПОКУПИТЬ",
|
||||
"DELETE": "УДАЛИТЬ",
|
||||
"HEAD": "HEAD",
|
||||
"Task Finished with Error": "Задача завершена с ошибкой",
|
||||
"Task Finished Successfully": "Задание успешно завершено",
|
||||
"Triggers when a robot task run fails with an error.": "Срабатывает при запуске задачи робота с ошибкой.",
|
||||
"Triggers when a robot finishes a task successfully.": "Триггеры, когда робот успешно завершил задачу."
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"You can find your Browse AI API key on the dashboard under Settings → API Key.": "You can find your Browse AI API key on the dashboard under Settings → API Key.",
|
||||
"Get Task Details": "Get Task Details",
|
||||
"List Robots": "List Robots",
|
||||
"Run a Robot": "Run a Robot",
|
||||
"Custom API Call": "Custom API Call",
|
||||
"Retrieves the details of a specific task executed by a Browse AI robot.": "Retrieves the details of a specific task executed by a Browse AI robot.",
|
||||
"Retrieves all robots available in your account.": "Retrieves all robots available in your account.",
|
||||
"Runs a robot on-demand with custom input parameters.": "Runs a robot on-demand with custom input parameters.",
|
||||
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
|
||||
"Robot": "Robot",
|
||||
"Task": "Task",
|
||||
"Record Video": "Record Video",
|
||||
"Input Parameters": "Input Parameters",
|
||||
"Method": "Method",
|
||||
"Headers": "Headers",
|
||||
"Query Parameters": "Query Parameters",
|
||||
"Body": "Body",
|
||||
"Response is Binary ?": "Response is Binary ?",
|
||||
"No Error on Failure": "No Error on Failure",
|
||||
"Timeout (in seconds)": "Timeout (in seconds)",
|
||||
"Select a robot from your Browse AI account": "Select a robot from your Browse AI account",
|
||||
"Select a task associated with the selected robot": "Select a task associated with the selected robot",
|
||||
"Try to record a video while running the task.": "Try to record a video while running the task.",
|
||||
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
|
||||
"Enable for files like PDFs, images, etc..": "Enable for files like PDFs, images, etc..",
|
||||
"GET": "GET",
|
||||
"POST": "POST",
|
||||
"PATCH": "PATCH",
|
||||
"PUT": "PUT",
|
||||
"DELETE": "DELETE",
|
||||
"HEAD": "HEAD",
|
||||
"Task Finished with Error": "Task Finished with Error",
|
||||
"Task Finished Successfully": "Task Finished Successfully",
|
||||
"Triggers when a robot task run fails with an error.": "Triggers when a robot task run fails with an error.",
|
||||
"Triggers when a robot finishes a task successfully.": "Triggers when a robot finishes a task successfully."
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"Browse AI": "Browse AI",
|
||||
"You can find your Browse AI API key on the dashboard under Settings → API Key.": "You can find your Browse AI API key on the dashboard under Settings → API Key.",
|
||||
"Get Task Details": "Get Task Details",
|
||||
"List Robots": "List Robots",
|
||||
"Run a Robot": "Run a Robot",
|
||||
"Custom API Call": "Custom API Call",
|
||||
"Retrieves the details of a specific task executed by a Browse AI robot.": "Retrieves the details of a specific task executed by a Browse AI robot.",
|
||||
"Retrieves all robots available in your account.": "Retrieves all robots available in your account.",
|
||||
"Runs a robot on-demand with custom input parameters.": "Runs a robot on-demand with custom input parameters.",
|
||||
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
|
||||
"Robot": "Robot",
|
||||
"Task": "Task",
|
||||
"Record Video": "Record Video",
|
||||
"Input Parameters": "Input Parameters",
|
||||
"Method": "Method",
|
||||
"Headers": "Headers",
|
||||
"Query Parameters": "Query Parameters",
|
||||
"Body": "Body",
|
||||
"No Error on Failure": "No Error on Failure",
|
||||
"Timeout (in seconds)": "Timeout (in seconds)",
|
||||
"Select a robot from your Browse AI account": "Select a robot from your Browse AI account",
|
||||
"Select a task associated with the selected robot": "Select a task associated with the selected robot",
|
||||
"Try to record a video while running the task.": "Try to record a video while running the task.",
|
||||
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
|
||||
"GET": "GET",
|
||||
"POST": "POST",
|
||||
"PATCH": "PATCH",
|
||||
"PUT": "PUT",
|
||||
"DELETE": "DELETE",
|
||||
"HEAD": "HEAD",
|
||||
"Task Finished with Error": "Task Finished with Error",
|
||||
"Task Finished Successfully": "Task Finished Successfully",
|
||||
"Triggers when a robot task run fails with an error.": "Triggers when a robot task run fails with an error.",
|
||||
"Triggers when a robot finishes a task successfully.": "Triggers when a robot finishes a task successfully."
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"You can find your Browse AI API key on the dashboard under Settings → API Key.": "You can find your Browse AI API key on the dashboard under Settings → API Key.",
|
||||
"Get Task Details": "Get Task Details",
|
||||
"List Robots": "List Robots",
|
||||
"Run a Robot": "Run a Robot",
|
||||
"Custom API Call": "自定义 API 呼叫",
|
||||
"Retrieves the details of a specific task executed by a Browse AI robot.": "Retrieves the details of a specific task executed by a Browse AI robot.",
|
||||
"Retrieves all robots available in your account.": "Retrieves all robots available in your account.",
|
||||
"Runs a robot on-demand with custom input parameters.": "Runs a robot on-demand with custom input parameters.",
|
||||
"Make a custom API call to a specific endpoint": "将一个自定义 API 调用到一个特定的终点",
|
||||
"Robot": "Robot",
|
||||
"Task": "Task",
|
||||
"Record Video": "Record Video",
|
||||
"Input Parameters": "Input Parameters",
|
||||
"Method": "方法",
|
||||
"Headers": "信头",
|
||||
"Query Parameters": "查询参数",
|
||||
"Body": "正文内容",
|
||||
"Response is Binary ?": "Response is Binary ?",
|
||||
"No Error on Failure": "失败时没有错误",
|
||||
"Timeout (in seconds)": "超时(秒)",
|
||||
"Select a robot from your Browse AI account": "Select a robot from your Browse AI account",
|
||||
"Select a task associated with the selected robot": "Select a task associated with the selected robot",
|
||||
"Try to record a video while running the task.": "Try to record a video while running the task.",
|
||||
"Authorization headers are injected automatically from your connection.": "授权头自动从您的连接中注入。",
|
||||
"Enable for files like PDFs, images, etc..": "Enable for files like PDFs, images, etc..",
|
||||
"GET": "获取",
|
||||
"POST": "帖子",
|
||||
"PATCH": "PATCH",
|
||||
"PUT": "弹出",
|
||||
"DELETE": "删除",
|
||||
"HEAD": "黑色",
|
||||
"Task Finished with Error": "Task Finished with Error",
|
||||
"Task Finished Successfully": "Task Finished Successfully",
|
||||
"Triggers when a robot task run fails with an error.": "Triggers when a robot task run fails with an error.",
|
||||
"Triggers when a robot finishes a task successfully.": "Triggers when a robot finishes a task successfully."
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { createCustomApiCallAction } from '@activepieces/pieces-common';
|
||||
import { createPiece } from '@activepieces/pieces-framework';
|
||||
import { browseAiAuth } from './lib/common/auth';
|
||||
import { getTaskDetailsAction } from './lib/actions/get-task-details';
|
||||
import { listRobotsAction } from './lib/actions/list-robots';
|
||||
import { runRobotAction } from './lib/actions/run-robot';
|
||||
import { taskFinishedWithErrorTrigger } from './lib/triggers/task-finished-with-error';
|
||||
import { taskFinishedSuccessfullyTrigger } from './lib/triggers/task-finished-successfully';
|
||||
import { PieceCategory } from '@activepieces/shared';
|
||||
|
||||
export const browseAi = createPiece({
|
||||
displayName: 'Browse AI',
|
||||
auth: browseAiAuth,
|
||||
minimumSupportedRelease: '0.36.1',
|
||||
logoUrl: 'https://cdn.activepieces.com/pieces/browse-ai.png',
|
||||
categories:[PieceCategory.PRODUCTIVITY],
|
||||
authors: ['aryel780'],
|
||||
actions: [
|
||||
getTaskDetailsAction,
|
||||
listRobotsAction,
|
||||
runRobotAction,
|
||||
createCustomApiCallAction({
|
||||
auth: browseAiAuth,
|
||||
baseUrl: () => 'https://api.browse.ai/v2',
|
||||
authMapping: async (auth) => ({
|
||||
Authorization: `Bearer ${auth.secret_text}`,
|
||||
}),
|
||||
}),
|
||||
],
|
||||
triggers: [
|
||||
taskFinishedWithErrorTrigger,
|
||||
taskFinishedSuccessfullyTrigger,
|
||||
],
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { browseAiApiCall } from '../common/client';
|
||||
import { browseAiAuth } from '../common/auth';
|
||||
import { robotIdDropdown, taskIdDropdown } from '../common/props';
|
||||
|
||||
export const getTaskDetailsAction = createAction({
|
||||
name: 'get-task-details',
|
||||
auth: browseAiAuth,
|
||||
displayName: 'Get Task Details',
|
||||
description:
|
||||
'Retrieves the details of a specific task executed by a Browse AI robot.',
|
||||
props: {
|
||||
robotId: robotIdDropdown,
|
||||
taskId: taskIdDropdown,
|
||||
},
|
||||
async run(context) {
|
||||
const { robotId, taskId } = context.propsValue;
|
||||
|
||||
try {
|
||||
const response = await browseAiApiCall({
|
||||
auth: { apiKey: context.auth.secret_text },
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/robots/${robotId}/tasks/${taskId}`,
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error: any) {
|
||||
if (error.response?.status === 404) {
|
||||
throw new Error(
|
||||
'Task not found. Please verify the Robot ID and Task ID.'
|
||||
);
|
||||
}
|
||||
|
||||
if (error.response?.status === 401) {
|
||||
throw new Error('Authentication failed. Please check your API key.');
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Failed to fetch task details: ${
|
||||
error.message || 'Unknown error occurred'
|
||||
}`
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { browseAiApiCall } from '../common/client';
|
||||
import { browseAiAuth } from '../common/auth';
|
||||
|
||||
export const listRobotsAction = createAction({
|
||||
name: 'list-robots',
|
||||
auth: browseAiAuth,
|
||||
displayName: 'List Robots',
|
||||
description: 'Retrieves all robots available in your account.',
|
||||
props: {},
|
||||
async run(context) {
|
||||
try {
|
||||
const response = await browseAiApiCall({
|
||||
auth: { apiKey: context.auth.secret_text },
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: '/robots',
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error: any) {
|
||||
if (error.response?.status === 401) {
|
||||
throw new Error('Authentication failed. Please check your API key.');
|
||||
}
|
||||
|
||||
if (error.response?.status === 429) {
|
||||
throw new Error('Rate limit exceeded. Please wait before retrying.');
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Failed to fetch robots: ${error.message || 'Unknown error occurred'}`
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,59 @@
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { browseAiApiCall } from '../common/client';
|
||||
import { browseAiAuth } from '../common/auth';
|
||||
import { robotIdDropdown, robotParameters } from '../common/props';
|
||||
|
||||
export const runRobotAction = createAction({
|
||||
name: 'run-robot',
|
||||
auth: browseAiAuth,
|
||||
displayName: 'Run a Robot',
|
||||
description:
|
||||
'Runs a robot on-demand with custom input parameters.',
|
||||
props: {
|
||||
robotId: robotIdDropdown,
|
||||
recordVideo: Property.Checkbox({
|
||||
displayName: 'Record Video',
|
||||
description:
|
||||
'Try to record a video while running the task.',
|
||||
required: false,
|
||||
defaultValue: false,
|
||||
}),
|
||||
robotParams: robotParameters,
|
||||
},
|
||||
async run(context) {
|
||||
const { robotId, recordVideo } = context.propsValue;
|
||||
|
||||
const inputParameters = context.propsValue.robotParams ?? {};
|
||||
|
||||
try {
|
||||
const response = await browseAiApiCall({
|
||||
method: HttpMethod.POST,
|
||||
resourceUri: `/robots/${robotId}/tasks`,
|
||||
auth: { apiKey: context.auth.secret_text },
|
||||
body: {
|
||||
recordVideo: recordVideo || false,
|
||||
inputParameters,
|
||||
},
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error: any) {
|
||||
if (error.response?.status === 401) {
|
||||
throw new Error('Authentication failed. Please check your API key.');
|
||||
}
|
||||
|
||||
if (error.response?.status === 404) {
|
||||
throw new Error('Robot not found. Please verify the robot ID.');
|
||||
}
|
||||
|
||||
if (error.response?.status === 429) {
|
||||
throw new Error('Rate limit exceeded. Please wait before retrying.');
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Failed to run robot: ${error.message || 'Unknown error occurred'}`
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
import { PieceAuth } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { browseAiApiCall } from './client';
|
||||
|
||||
export const browseAiAuth = PieceAuth.SecretText({
|
||||
displayName: 'API Key',
|
||||
description: 'You can find your Browse AI API key on the dashboard under Settings → API Key.',
|
||||
required: true,
|
||||
validate: async ({ auth }) => {
|
||||
try {
|
||||
await browseAiApiCall({
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: '/status',
|
||||
auth: { apiKey: auth },
|
||||
});
|
||||
return { valid: true };
|
||||
} catch {
|
||||
return {
|
||||
valid: false,
|
||||
error: 'Invalid API Key. Please check your Browse AI credentials.',
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,85 @@
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
HttpRequest,
|
||||
HttpMessageBody,
|
||||
QueryParams,
|
||||
} from '@activepieces/pieces-common';
|
||||
|
||||
export type BrowseAiAuthProps = {
|
||||
apiKey: string;
|
||||
};
|
||||
|
||||
export type BrowseAiApiCallParams = {
|
||||
method: HttpMethod;
|
||||
resourceUri: string;
|
||||
query?: Record<string, string | number | string[] | undefined>;
|
||||
body?: unknown;
|
||||
auth: BrowseAiAuthProps;
|
||||
};
|
||||
|
||||
export async function browseAiApiCall<T extends HttpMessageBody>({
|
||||
method,
|
||||
resourceUri,
|
||||
query,
|
||||
body,
|
||||
auth,
|
||||
}: BrowseAiApiCallParams): Promise<T> {
|
||||
const { apiKey } = auth;
|
||||
|
||||
if (!apiKey) {
|
||||
throw new Error('Browse AI API key is required for authentication');
|
||||
}
|
||||
|
||||
const queryParams: QueryParams = {};
|
||||
|
||||
if (query) {
|
||||
for (const [key, value] of Object.entries(query)) {
|
||||
if (value !== null && value !== undefined) {
|
||||
queryParams[key] = String(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const baseUrl = `https://api.browse.ai/v2`;
|
||||
|
||||
const request: HttpRequest = {
|
||||
method,
|
||||
url: `${baseUrl}${resourceUri}`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
queryParams,
|
||||
body,
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await httpClient.sendRequest<T>(request);
|
||||
return response.body;
|
||||
} catch (error: any) {
|
||||
const statusCode = error.response?.status;
|
||||
const errorData = error.response?.data;
|
||||
|
||||
switch (statusCode) {
|
||||
case 400:
|
||||
throw new Error(`Bad Request: ${errorData?.message || 'Invalid parameters'}`);
|
||||
case 401:
|
||||
throw new Error('Unauthorized: Invalid API key. Please check your credentials.');
|
||||
case 403:
|
||||
throw new Error('Forbidden: You do not have permission to access this resource.');
|
||||
case 404:
|
||||
throw new Error('Not Found: The requested resource does not exist.');
|
||||
case 429:
|
||||
throw new Error('Rate Limit Exceeded: Please slow down your requests.');
|
||||
case 500:
|
||||
throw new Error('Internal Server Error: Something went wrong on Browse AI’s side.');
|
||||
default:
|
||||
{
|
||||
const message = errorData?.message || error.message || 'Unknown error';
|
||||
throw new Error(`Browse AI API Error (${statusCode || 'Unknown'}): ${message}`);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
import { DynamicPropsValue, Property } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { browseAiApiCall } from './client';
|
||||
import { browseAiAuth } from './auth';
|
||||
|
||||
interface BrowseAiRobot {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface BrowseAiTask {
|
||||
id: string;
|
||||
status: string;
|
||||
createdAt?: number;
|
||||
}
|
||||
|
||||
interface BrowseAiTasksResponse {
|
||||
statusCode: number;
|
||||
messageCode: string;
|
||||
result: {
|
||||
robotTasks: {
|
||||
totalCount: number;
|
||||
pageNumber: number;
|
||||
hasMore: boolean;
|
||||
items: BrowseAiTask[];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
interface BrowseAiRobotResponse {
|
||||
robot: {
|
||||
id: string;
|
||||
name: string;
|
||||
inputParameters: {
|
||||
type: string;
|
||||
name: string;
|
||||
label: string;
|
||||
required: boolean;
|
||||
options?: { label: string; value: string }[];
|
||||
}[];
|
||||
};
|
||||
}
|
||||
|
||||
export const robotIdDropdown = Property.Dropdown({
|
||||
auth: browseAiAuth,
|
||||
displayName: 'Robot',
|
||||
description: 'Select a robot from your Browse AI account',
|
||||
required: true,
|
||||
refreshers: [],
|
||||
options: async ({ auth }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'Please connect your Browse AI account first.',
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await browseAiApiCall<{
|
||||
robots: { items: BrowseAiRobot[] };
|
||||
}>({
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: '/robots',
|
||||
auth: { apiKey: auth.secret_text },
|
||||
});
|
||||
|
||||
const robots = response?.robots?.items ?? [];
|
||||
|
||||
if (robots.length === 0) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'No robots found in your account.',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options: robots.map((robot) => ({
|
||||
label: robot.name,
|
||||
value: robot.id,
|
||||
})),
|
||||
};
|
||||
} catch (error: any) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder:
|
||||
'Failed to load robots. Please check your API key and try again.',
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export const taskIdDropdown = Property.Dropdown({
|
||||
auth: browseAiAuth,
|
||||
displayName: 'Task',
|
||||
description: 'Select a task associated with the selected robot',
|
||||
required: true,
|
||||
refreshers: ['robotId'],
|
||||
options: async ({ auth, robotId }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'Please connect your Browse AI account.',
|
||||
};
|
||||
}
|
||||
|
||||
if (!robotId) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'Please select a robot first.',
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await browseAiApiCall<BrowseAiTasksResponse>({
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/robots/${robotId}/tasks`,
|
||||
auth: { apiKey: auth.secret_text },
|
||||
});
|
||||
|
||||
const tasks = response.result?.robotTasks?.items ?? [];
|
||||
|
||||
if (tasks.length === 0) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'No tasks found for the selected robot.',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options: tasks.map((task) => {
|
||||
const createdDate = task.createdAt
|
||||
? new Date(task.createdAt).toLocaleDateString()
|
||||
: 'Unknown date';
|
||||
return {
|
||||
label: `${task.id} - ${task.status} (${createdDate})`,
|
||||
value: task.id,
|
||||
};
|
||||
}),
|
||||
};
|
||||
} catch (e) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: `Error fetching tasks: ${
|
||||
e instanceof Error ? e.message : 'Unknown error'
|
||||
}`,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export const robotParameters = Property.DynamicProperties({
|
||||
auth: browseAiAuth,
|
||||
displayName: 'Input Parameters',
|
||||
refreshers: ['robotId'],
|
||||
required: true,
|
||||
props: async ({ auth, robotId }) => {
|
||||
if (!auth || !robotId) return {};
|
||||
|
||||
try {
|
||||
const response = await browseAiApiCall<BrowseAiRobotResponse>({
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/robots/${robotId}`,
|
||||
auth: { apiKey: auth.secret_text },
|
||||
});
|
||||
|
||||
const props: DynamicPropsValue = {};
|
||||
|
||||
const params = response.robot.inputParameters ?? [];
|
||||
|
||||
for (const param of params) {
|
||||
switch (param.type) {
|
||||
case 'number':
|
||||
props[param.name] = Property.Number({
|
||||
displayName: param.label,
|
||||
required: param.required,
|
||||
});
|
||||
break;
|
||||
case 'url':
|
||||
case 'string':
|
||||
props[param.name] = Property.ShortText({
|
||||
displayName: param.label,
|
||||
required: param.required,
|
||||
});
|
||||
break;
|
||||
case 'select':
|
||||
props[param.name] = Property.StaticDropdown({
|
||||
displayName: param.label,
|
||||
required: param.required,
|
||||
options: {
|
||||
disabled: false,
|
||||
options: param.options ? param.options : [],
|
||||
},
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return props;
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,135 @@
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
|
||||
import { isNil } from '@activepieces/shared';
|
||||
import { browseAiAuth } from '../common/auth';
|
||||
import { browseAiApiCall } from '../common/client';
|
||||
import { robotIdDropdown } from '../common/props';
|
||||
|
||||
const TRIGGER_KEY = 'browse-ai-task_finished_successfully';
|
||||
|
||||
export const taskFinishedSuccessfullyTrigger = createTrigger({
|
||||
auth: browseAiAuth,
|
||||
name: 'task_finished_successfully',
|
||||
displayName: 'Task Finished Successfully',
|
||||
description:
|
||||
'Triggers when a robot finishes a task successfully.',
|
||||
type: TriggerStrategy.WEBHOOK,
|
||||
props: {
|
||||
robotId: robotIdDropdown,
|
||||
},
|
||||
|
||||
async onEnable(context) {
|
||||
const { robotId } = context.propsValue;
|
||||
const apiKey = context.auth.secret_text;
|
||||
|
||||
try {
|
||||
// Verify robot exists and we have access
|
||||
await browseAiApiCall({
|
||||
method: HttpMethod.GET,
|
||||
auth: { apiKey },
|
||||
resourceUri: `/robots/${robotId}`,
|
||||
});
|
||||
|
||||
const response = await browseAiApiCall<{
|
||||
webhook: { id: string; url: string; status: string };
|
||||
}>({
|
||||
method: HttpMethod.POST,
|
||||
auth: { apiKey },
|
||||
resourceUri: `/robots/${robotId}/webhooks`,
|
||||
body: {
|
||||
hookUrl: context.webhookUrl,
|
||||
eventType: 'taskFinishedSuccessfully',
|
||||
},
|
||||
});
|
||||
|
||||
await context.store.put<string>(TRIGGER_KEY, response.webhook.id);
|
||||
} catch (error: any) {
|
||||
if (error.response?.status === 404) {
|
||||
throw new Error(
|
||||
`Robot not found: The robot with ID "${robotId}" does not exist or you do not have access to it. Please verify the robot ID and your permissions.`
|
||||
);
|
||||
}
|
||||
|
||||
if (error.response?.status === 403) {
|
||||
throw new Error(
|
||||
'Access denied: You do not have permission to set up webhooks for this robot. Please check your Browse AI account permissions and ensure you have webhook access.'
|
||||
);
|
||||
}
|
||||
|
||||
if (error.response?.status === 400) {
|
||||
throw new Error(
|
||||
`Invalid webhook configuration: ${
|
||||
error.response?.data?.message || error.message
|
||||
}. Please check your webhook URL and robot ID.`
|
||||
);
|
||||
}
|
||||
|
||||
if (error.response?.status === 429) {
|
||||
throw new Error(
|
||||
'Rate limit exceeded: Too many webhook requests. Please wait a moment and try again.'
|
||||
);
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Failed to set up webhook: ${
|
||||
error.message || 'Unknown error occurred'
|
||||
}. Please check your robot ID and try again.`
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
async onDisable(context) {
|
||||
const { robotId } = context.propsValue;
|
||||
|
||||
const webhookId = await context.store.get<string>(TRIGGER_KEY);
|
||||
const apiKey = context.auth.secret_text;
|
||||
|
||||
if (!isNil(webhookId)) {
|
||||
try {
|
||||
await browseAiApiCall({
|
||||
method: HttpMethod.DELETE,
|
||||
auth: { apiKey },
|
||||
resourceUri: `/robots/${robotId}/webhooks/${webhookId}`,
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.warn(
|
||||
`Warning: Failed to clean up webhook ${webhookId}:`,
|
||||
error.message
|
||||
);
|
||||
|
||||
// Clean up the stored webhook ID even if deletion failed
|
||||
await context.store.delete(TRIGGER_KEY);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const payload = context.payload.body as {
|
||||
task: Record<string, any>;
|
||||
event: string;
|
||||
};
|
||||
|
||||
if (payload.event !== 'task.finishedSuccessfully') return [];
|
||||
|
||||
return [payload.task];
|
||||
},
|
||||
|
||||
async test(context) {
|
||||
const { robotId } = context.propsValue;
|
||||
|
||||
const apiKey = context.auth.secret_text;
|
||||
|
||||
const response = await browseAiApiCall<{
|
||||
result: { robotTasks: { items: { id: string }[] } };
|
||||
}>({
|
||||
method: HttpMethod.GET,
|
||||
auth: { apiKey },
|
||||
resourceUri: `/robots/${robotId}/tasks`,
|
||||
query: { status: 'successful', sort: '-createdAt' },
|
||||
});
|
||||
|
||||
return response.result.robotTasks.items;
|
||||
},
|
||||
|
||||
sampleData: {},
|
||||
});
|
||||
@@ -0,0 +1,134 @@
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
|
||||
import { isNil } from '@activepieces/shared';
|
||||
import { browseAiAuth } from '../common/auth';
|
||||
import { browseAiApiCall } from '../common/client';
|
||||
import { robotIdDropdown } from '../common/props';
|
||||
|
||||
const TRIGGER_KEY = 'browse-ai-task_finished_with_error';
|
||||
|
||||
export const taskFinishedWithErrorTrigger = createTrigger({
|
||||
auth: browseAiAuth,
|
||||
name: 'task_finished_with_error',
|
||||
displayName: 'Task Finished with Error',
|
||||
description: 'Triggers when a robot task run fails with an error.',
|
||||
type: TriggerStrategy.WEBHOOK,
|
||||
props: {
|
||||
robotId: robotIdDropdown,
|
||||
},
|
||||
|
||||
async onEnable(context) {
|
||||
const { robotId } = context.propsValue;
|
||||
const apiKey = context.auth.secret_text;
|
||||
|
||||
try {
|
||||
// Verify robot exists and we have access
|
||||
await browseAiApiCall({
|
||||
method: HttpMethod.GET,
|
||||
auth: { apiKey },
|
||||
resourceUri: `/robots/${robotId}`,
|
||||
});
|
||||
|
||||
const response = await browseAiApiCall<{
|
||||
webhook: { id: string; url: string; status: string };
|
||||
}>({
|
||||
method: HttpMethod.POST,
|
||||
auth: { apiKey },
|
||||
resourceUri: `/robots/${robotId}/webhooks`,
|
||||
body: {
|
||||
hookUrl: context.webhookUrl,
|
||||
eventType: 'taskFinishedWithError',
|
||||
},
|
||||
});
|
||||
|
||||
await context.store.put<string>(TRIGGER_KEY, response.webhook.id);
|
||||
} catch (error: any) {
|
||||
if (error.response?.status === 404) {
|
||||
throw new Error(
|
||||
`Robot not found: The robot with ID "${robotId}" does not exist or you do not have access to it. Please verify the robot ID and your permissions.`
|
||||
);
|
||||
}
|
||||
|
||||
if (error.response?.status === 403) {
|
||||
throw new Error(
|
||||
'Access denied: You do not have permission to set up webhooks for this robot. Please check your Browse AI account permissions and ensure you have webhook access.'
|
||||
);
|
||||
}
|
||||
|
||||
if (error.response?.status === 400) {
|
||||
throw new Error(
|
||||
`Invalid webhook configuration: ${
|
||||
error.response?.data?.message || error.message
|
||||
}. Please check your webhook URL and robot ID.`
|
||||
);
|
||||
}
|
||||
|
||||
if (error.response?.status === 429) {
|
||||
throw new Error(
|
||||
'Rate limit exceeded: Too many webhook requests. Please wait a moment and try again.'
|
||||
);
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Failed to set up webhook: ${
|
||||
error.message || 'Unknown error occurred'
|
||||
}. Please check your robot ID and try again.`
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
async onDisable(context) {
|
||||
const { robotId } = context.propsValue;
|
||||
|
||||
const webhookId = await context.store.get<string>(TRIGGER_KEY);
|
||||
const apiKey = context.auth.secret_text;
|
||||
|
||||
if (!isNil(webhookId)) {
|
||||
try {
|
||||
await browseAiApiCall({
|
||||
method: HttpMethod.DELETE,
|
||||
auth: { apiKey },
|
||||
resourceUri: `/robots/${robotId}/webhooks/${webhookId}`,
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.warn(
|
||||
`Warning: Failed to clean up webhook ${webhookId}:`,
|
||||
error.message
|
||||
);
|
||||
|
||||
// Clean up the stored webhook ID even if deletion failed
|
||||
await context.store.delete(TRIGGER_KEY);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const payload = context.payload.body as {
|
||||
task: Record<string, any>;
|
||||
event: string;
|
||||
};
|
||||
|
||||
if (payload.event !== 'task.finishedWithError') return [];
|
||||
|
||||
return [payload.task];
|
||||
},
|
||||
|
||||
async test(context) {
|
||||
const { robotId } = context.propsValue;
|
||||
|
||||
const apiKey = context.auth.secret_text;
|
||||
|
||||
const response = await browseAiApiCall<{
|
||||
result: { robotTasks: { items: { id: string }[] } };
|
||||
}>({
|
||||
method: HttpMethod.GET,
|
||||
auth: { apiKey },
|
||||
resourceUri: `/robots/${robotId}/tasks`,
|
||||
query: { status: 'failed', sort: '-createdAt' },
|
||||
});
|
||||
|
||||
return response.result.robotTasks.items;
|
||||
},
|
||||
|
||||
sampleData: {},
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"extends": "../../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"importHelpers": true,
|
||||
"noImplicitOverride": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noPropertyAccessFromIndexSignature": true
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../../../dist/out-tsc",
|
||||
"declaration": true,
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user