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:
poduck
2025-12-18 22:59:37 -05:00
parent 9848268d34
commit 3aa7199503
16292 changed files with 1284892 additions and 4708 deletions

View File

@@ -0,0 +1,33 @@
{
"extends": [
"../../../../.eslintrc.base.json"
],
"ignorePatterns": [
"!**/*"
],
"overrides": [
{
"files": [
"*.ts",
"*.tsx",
"*.js",
"*.jsx"
],
"rules": {}
},
{
"files": [
"*.ts",
"*.tsx"
],
"rules": {}
},
{
"files": [
"*.js",
"*.jsx"
],
"rules": {}
}
]
}

View File

@@ -0,0 +1,7 @@
# pieces-cody
This library was generated with [Nx](https://nx.dev).
## Building
Run `nx build pieces-cody` to build the library.

View File

@@ -0,0 +1,10 @@
{
"name": "@activepieces/piece-cody",
"version": "0.0.3",
"type": "commonjs",
"main": "./src/index.js",
"types": "./src/index.d.ts",
"dependencies": {
"tslib": "^2.3.0"
}
}

View File

@@ -0,0 +1,65 @@
{
"name": "pieces-cody",
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/pieces/community/cody/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/cody",
"tsConfig": "packages/pieces/community/cody/tsconfig.lib.json",
"packageJson": "packages/pieces/community/cody/package.json",
"main": "packages/pieces/community/cody/src/index.ts",
"assets": [
"packages/pieces/community/cody/*.md",
{
"input": "packages/pieces/community/cody/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/cody",
"command": "bun install --no-save --silent"
},
"dependsOn": [
"^build"
]
}
}
}

View File

@@ -0,0 +1,50 @@
{
"Visit your Cody AI API Keys page to retrieve the API key.": "Besuchen Sie Ihre Cody KI API Schlüsselseite, um den API-Schlüssel abzurufen.",
"Create Document From Text": "Dokument aus Text erstellen",
"Upload File to Knowledge Base": "Datei in die Wissensdatenbank hochladen",
"Send Message": "Nachricht senden",
"Create Conversation": "Unterhaltung erstellen",
"Find Bot": "Bot finden",
"Find Conversation": "Unterhaltung finden",
"Custom API Call": "Eigener API-Aufruf",
"Upload text content to create a new document within the Cody knowledge base.": "Lade Textinhalte hoch, um ein neues Dokument innerhalb der Cody Wissensdatenbank zu erstellen.",
"Add a file directly into a specific folder in the knowledge base.": "Fügen Sie eine Datei direkt in einen bestimmten Ordner in der Wissensdatenbank ein.",
"Send your message and receive the AI-generated response.": "Senden Sie Ihre Nachricht und erhalten Sie die von der KI generierte Antwort.",
"Creates a new conversation with a bot.": "Erstellt eine neue Unterhaltung mit einem Bot.",
"Finds a bot based on its name.": "Findet einen Bot basierend auf seinem Namen.",
"Finds a conversation based on its name and/or the bot it belongs to.": "Findet ein Gespräch basierend auf seinem Namen und/oder dem Bot, zu dem es gehört.",
"Make a custom API call to a specific endpoint": "Einen benutzerdefinierten API-Aufruf an einen bestimmten Endpunkt machen",
"Folder": "Ordner",
"Document Name": "Dokumentname",
"Content": "Inhalt",
"File": "Datei",
"Conversation": "Unterhaltung",
"Message": "Nachricht",
"Bot": "Bot",
"Conversation Name": "Konversationsname",
"Document IDs (Focus Mode)": "Dokumenten-IDs (Fokus-Modus)",
"Bot Name": "Bot Name",
"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)",
"The name or title of the new document.": "Der Name oder der Titel des neuen Dokuments.",
"The text or HTML content to be added to the document. Max 768 KB.": "Der Text oder HTML-Inhalt, der dem Dokument hinzugefügt werden soll. Max 768 KB.",
"The file to upload (e.g., txt, md, rtf, pdf, ppt, docx).": "Die hochzuladende Datei (z.B. txt, md, rtf, pdf, ppt, docx).",
"The message to send to the conversation. (Max 2000 characters)": "Die Nachricht die an die Unterhaltung gesendet werden soll. (max. 2000 Zeichen)",
"The name for the new conversation.": "Der Name für die neue Unterhaltung.",
"A list of document IDs to limit the bot's knowledge base for this conversation.": "Eine Liste von Dokumenten-IDs, um die Wissensdatenbank des Bots für diese Unterhaltung zu beschränken.",
"The name of the bot to search for. The search is case-insensitive and partial.": "Der Name des Bots nach dem gesucht werden soll. Die Suche ist unabhängig von Groß-/Kleinschreibung und Teil.",
"The name of the conversation to search for (partial match).": "Der Name der zu suchenden Konversation (partielle Übereinstimmung).",
"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"
}

View File

@@ -0,0 +1,50 @@
{
"Visit your Cody AI API Keys page to retrieve the API key.": "Visite la página de claves API de Cody AI para recuperar la clave API.",
"Create Document From Text": "Crear documento desde texto",
"Upload File to Knowledge Base": "Subir archivo a la base de conocimientos",
"Send Message": "Enviar mensaje",
"Create Conversation": "Crear conversación",
"Find Bot": "Buscar bot",
"Find Conversation": "Encontrar conversación",
"Custom API Call": "Llamada API personalizada",
"Upload text content to create a new document within the Cody knowledge base.": "Sube contenido de texto para crear un nuevo documento dentro de la base de conocimiento Cody.",
"Add a file directly into a specific folder in the knowledge base.": "Añadir un archivo directamente a una carpeta específica en la base de conocimientos.",
"Send your message and receive the AI-generated response.": "Envía tu mensaje y recibe la respuesta generada por la IA.",
"Creates a new conversation with a bot.": "Crea una nueva conversación con un bot.",
"Finds a bot based on its name.": "Encuentra un bot basado en su nombre.",
"Finds a conversation based on its name and/or the bot it belongs to.": "Encuentra una conversación basada en su nombre y/o el bot al que pertenece.",
"Make a custom API call to a specific endpoint": "Hacer una llamada API personalizada a un extremo específico",
"Folder": "Carpeta",
"Document Name": "Nombre del documento",
"Content": "Contenido",
"File": "Archivo",
"Conversation": "Conversación",
"Message": "Mensaje",
"Bot": "Bot",
"Conversation Name": "Nombre de la conversación",
"Document IDs (Focus Mode)": "ID de documentos (Modo central)",
"Bot Name": "Nombre del bot",
"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)",
"The name or title of the new document.": "El nombre o título del nuevo documento.",
"The text or HTML content to be added to the document. Max 768 KB.": "El texto o el contenido HTML a añadir al documento. Máximo 768 KB.",
"The file to upload (e.g., txt, md, rtf, pdf, ppt, docx).": "El archivo a subir (por ejemplo, txt, md, rtf, pdf, ppt, docx).",
"The message to send to the conversation. (Max 2000 characters)": "El mensaje a enviar a la conversación. (Máximo 2000 caracteres)",
"The name for the new conversation.": "El nombre de la nueva conversación.",
"A list of document IDs to limit the bot's knowledge base for this conversation.": "Una lista de IDs de documentos para limitar la base de conocimiento del bot para esta conversación.",
"The name of the bot to search for. The search is case-insensitive and partial.": "El nombre del bot para buscar. La búsqueda es insensible a mayúsculas y parcial.",
"The name of the conversation to search for (partial match).": "El nombre de la conversación a buscar (coincidencia parcial).",
"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"
}

View File

@@ -0,0 +1,50 @@
{
"Visit your Cody AI API Keys page to retrieve the API key.": "Visitez votre page Cody AI API Keys pour récupérer la clé API.",
"Create Document From Text": "Créer un document à partir d'un texte",
"Upload File to Knowledge Base": "Charger un fichier vers la base de connaissances",
"Send Message": "Envoyer un message",
"Create Conversation": "Créer une conversation",
"Find Bot": "Trouver le Bot",
"Find Conversation": "Trouver une conversation",
"Custom API Call": "Appel d'API personnalisé",
"Upload text content to create a new document within the Cody knowledge base.": "Téléchargez du contenu texte pour créer un nouveau document dans la base de connaissances de Cody.",
"Add a file directly into a specific folder in the knowledge base.": "Ajouter un fichier directement dans un dossier spécifique de la base de connaissances.",
"Send your message and receive the AI-generated response.": "Envoyez votre message et recevez la réponse générée par l'IA.",
"Creates a new conversation with a bot.": "Crée une nouvelle conversation avec un bot.",
"Finds a bot based on its name.": "Trouve un bot basé sur son nom.",
"Finds a conversation based on its name and/or the bot it belongs to.": "Trouve une conversation en fonction de son nom et/ou du bot auquel elle appartient.",
"Make a custom API call to a specific endpoint": "Passer un appel API personnalisé à un endpoint spécifique",
"Folder": "Dossier",
"Document Name": "Nom du document",
"Content": "Contenus",
"File": "Ficher",
"Conversation": "Conversation",
"Message": "Message",
"Bot": "Bot",
"Conversation Name": "Nom de la conversation",
"Document IDs (Focus Mode)": "IDs de document (Mode ocus)",
"Bot Name": "Nom du bot",
"Method": "Méthode",
"Headers": "Headers",
"Query Parameters": "Paramètres de requête",
"Body": "Body",
"Response is Binary ?": "La réponse est Binaire ?",
"No Error on Failure": "Aucune erreur en cas d'échec",
"Timeout (in seconds)": "Délai d'expiration (en secondes)",
"The name or title of the new document.": "Le nom ou le titre du nouveau document.",
"The text or HTML content to be added to the document. Max 768 KB.": "Le texte ou le contenu HTML à ajouter au document. Maximum 768 KB.",
"The file to upload (e.g., txt, md, rtf, pdf, ppt, docx).": "Le fichier à télécharger (par exemple, txt, md, rtf, pdf, ppt, docx).",
"The message to send to the conversation. (Max 2000 characters)": "Le message à envoyer à la conversation. (Max 2000 caractères)",
"The name for the new conversation.": "Le nom de la nouvelle conversation.",
"A list of document IDs to limit the bot's knowledge base for this conversation.": "Une liste d'ID de document pour limiter la base de connaissances du bot pour cette conversation.",
"The name of the bot to search for. The search is case-insensitive and partial.": "Le nom du bot à rechercher. La recherche est insensible à la casse et partielle.",
"The name of the conversation to search for (partial match).": "Le nom de la conversation à rechercher (correspondance partielle).",
"Authorization headers are injected automatically from your connection.": "Les headers 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": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD"
}

View File

@@ -0,0 +1,50 @@
{
"Visit your Cody AI API Keys page to retrieve the API key.": "API キーを取得するには、Cody AI API Keysページを参照してください。",
"Create Document From Text": "テキストからドキュメントを作成",
"Upload File to Knowledge Base": "ナレッジベースにファイルをアップロード",
"Send Message": "メッセージを送信",
"Create Conversation": "会話を作成",
"Find Bot": "ボットを見つける",
"Find Conversation": "会話を検索",
"Custom API Call": "カスタムAPI通話",
"Upload text content to create a new document within the Cody knowledge base.": "コーディのナレッジベース内で新しいドキュメントを作成するには、テキストコンテンツをアップロードしてください。",
"Add a file directly into a specific folder in the knowledge base.": "ナレッジベースの特定のフォルダに直接ファイルを追加します。",
"Send your message and receive the AI-generated response.": "メッセージを送信し、AIによって生成された応答を受信します。",
"Creates a new conversation with a bot.": "ボットとの新しい会話を作成します。",
"Finds a bot based on its name.": "名前に基づいてボットを検索します。",
"Finds a conversation based on its name and/or the bot it belongs to.": "その名前および/または所属するボットに基づいて会話を検索します。",
"Make a custom API call to a specific endpoint": "特定のエンドポイントへのカスタム API コールを実行します。",
"Folder": "Folder",
"Document Name": "ドキュメント名",
"Content": "コンテンツ",
"File": "ファイル",
"Conversation": "会話",
"Message": "メッセージ",
"Bot": "Bot",
"Conversation Name": "会話名",
"Document IDs (Focus Mode)": "ドキュメントIDフォーカスモード",
"Bot Name": "Bot名",
"Method": "方法",
"Headers": "ヘッダー",
"Query Parameters": "クエリパラメータ",
"Body": "本文",
"Response is Binary ?": "応答はバイナリですか?",
"No Error on Failure": "失敗時にエラーはありません",
"Timeout (in seconds)": "タイムアウト(秒)",
"The name or title of the new document.": "新規ドキュメントの名前またはタイトル。",
"The text or HTML content to be added to the document. Max 768 KB.": "ドキュメントに追加するテキストまたはHTMLコンテンツ。最大768 KB。",
"The file to upload (e.g., txt, md, rtf, pdf, ppt, docx).": "アップロードするファイル (例: txt, md, rtf, pdf, ppt, docx)",
"The message to send to the conversation. (Max 2000 characters)": "会話に送信するメッセージ。(最大 2000 文字)",
"The name for the new conversation.": "新しい会話の名前。",
"A list of document IDs to limit the bot's knowledge base for this conversation.": "この会話のボットのナレッジベースを制限するドキュメント ID のリスト。",
"The name of the bot to search for. The search is case-insensitive and partial.": "検索するボットの名前。検索は大文字と小文字を区別しないものです。",
"The name of the conversation to search for (partial match).": "検索する会話の名前 (部分一致)。",
"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": "頭"
}

View File

@@ -0,0 +1,50 @@
{
"Visit your Cody AI API Keys page to retrieve the API key.": "Bezoek je Cody AI API-sleutels pagina om de API-sleutel op te halen.",
"Create Document From Text": "Document maken uit tekst",
"Upload File to Knowledge Base": "Bestand uploaden naar Kennisbank",
"Send Message": "Verstuur bericht",
"Create Conversation": "Gesprek aanmaken",
"Find Bot": "Vind Bot",
"Find Conversation": "Gesprek zoeken",
"Custom API Call": "Custom API Call",
"Upload text content to create a new document within the Cody knowledge base.": "Upload tekstinhoud om een nieuw document in de Cody knowledge base te maken.",
"Add a file directly into a specific folder in the knowledge base.": "Voeg direct een bestand toe aan een specifieke map in de kennisbasis.",
"Send your message and receive the AI-generated response.": "Stuur uw bericht en ontvang het AI-gegenereerde antwoord.",
"Creates a new conversation with a bot.": "Maakt een nieuw gesprek met een bot.",
"Finds a bot based on its name.": "Vindt een bot gebaseerd op zijn naam.",
"Finds a conversation based on its name and/or the bot it belongs to.": "Vindt een gesprek gebaseerd op de naam en/of de bot waartoe het behoort.",
"Make a custom API call to a specific endpoint": "Maak een aangepaste API call naar een specifiek eindpunt",
"Folder": "Map",
"Document Name": "Document naam",
"Content": "Inhoud",
"File": "Bestand",
"Conversation": "Gesprek",
"Message": "bericht",
"Bot": "Bot",
"Conversation Name": "Gesprek naam",
"Document IDs (Focus Mode)": "Document ID's (Focus Modus)",
"Bot Name": "Bot naam",
"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)",
"The name or title of the new document.": "De naam of titel van het nieuwe document.",
"The text or HTML content to be added to the document. Max 768 KB.": "De tekst of HTML inhoud die aan het document moet worden toegevoegd. Maximaal 768 KB.",
"The file to upload (e.g., txt, md, rtf, pdf, ppt, docx).": "Het te uploaden bestand (bijv. txt, md, rtf, pdf, ppt, docx).",
"The message to send to the conversation. (Max 2000 characters)": "Het bericht dat moet worden verzonden naar het gesprek. (Max 2000 tekens)",
"The name for the new conversation.": "De naam van het nieuwe gesprek.",
"A list of document IDs to limit the bot's knowledge base for this conversation.": "Een lijst van document IDs om de bot's kennisbank voor dit gesprek te beperken.",
"The name of the bot to search for. The search is case-insensitive and partial.": "De naam van de bot waarnaar gezocht moet worden. De zoekopdracht is hoofdletterongevoelig en partijdig.",
"The name of the conversation to search for (partial match).": "De naam van het gesprek om naar te zoeken (gedeeltelijke wedstrijde).",
"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"
}

View File

@@ -0,0 +1,50 @@
{
"Visit your Cody AI API Keys page to retrieve the API key.": "Visite a página de chaves da API Cody AI para recuperar a chave de API.",
"Create Document From Text": "Criar documento a partir do texto",
"Upload File to Knowledge Base": "Carregar arquivo para base de conhecimento",
"Send Message": "Enviar mensagem",
"Create Conversation": "Criar conversa",
"Find Bot": "Encontrar o bot",
"Find Conversation": "Localizar Conversa",
"Custom API Call": "Chamada de API personalizada",
"Upload text content to create a new document within the Cody knowledge base.": "Enviar conteúdo de texto para criar um novo documento dentro da base de conhecimento do Cody",
"Add a file directly into a specific folder in the knowledge base.": "Adicione um arquivo diretamente a uma pasta específica na base de conhecimento.",
"Send your message and receive the AI-generated response.": "Envie sua mensagem e receba a resposta gerada pela IA.",
"Creates a new conversation with a bot.": "Cria uma nova conversa com um bot.",
"Finds a bot based on its name.": "Encontra um bot com base no seu nome.",
"Finds a conversation based on its name and/or the bot it belongs to.": "Encontra uma conversa com base no nome e/ou no bot a que ela pertence.",
"Make a custom API call to a specific endpoint": "Faça uma chamada de API personalizada para um ponto de extremidade específico",
"Folder": "Pasta",
"Document Name": "Nome do documento",
"Content": "Conteúdo",
"File": "Arquivo",
"Conversation": "Conversa",
"Message": "mensagem",
"Bot": "Bot",
"Conversation Name": "Nome da conversa",
"Document IDs (Focus Mode)": "IDs de Documentos (Focus Mode)",
"Bot Name": "Nome do bot",
"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)",
"The name or title of the new document.": "O nome ou o título do novo documento.",
"The text or HTML content to be added to the document. Max 768 KB.": "O texto ou conteúdo HTML a ser adicionado ao documento. Máximo 768 KB.",
"The file to upload (e.g., txt, md, rtf, pdf, ppt, docx).": "O arquivo a ser enviado (ex.: txt, md, rtf, pdf, ppt, docx).",
"The message to send to the conversation. (Max 2000 characters)": "Mensagem a ser enviada para a conversa. (Máximo de 2000 caracteres)",
"The name for the new conversation.": "O nome para a nova conversa.",
"A list of document IDs to limit the bot's knowledge base for this conversation.": "Uma lista de IDs de documentos para limitar a base de conhecimento do bot para esta conversa.",
"The name of the bot to search for. The search is case-insensitive and partial.": "O nome do bot a ser pesquisado. A busca diferencia maiúsculas de minúsculas e parciais.",
"The name of the conversation to search for (partial match).": "O nome da conversa para pesquisar (correspondência parcial).",
"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"
}

View File

@@ -0,0 +1,50 @@
{
"Visit your Cody AI API Keys page to retrieve the API key.": "Visit your Cody AI API Keys page to retrieve the API key.",
"Create Document From Text": "Create Document From Text",
"Upload File to Knowledge Base": "Upload File to Knowledge Base",
"Send Message": "Send Message",
"Create Conversation": "Create Conversation",
"Find Bot": "Find Bot",
"Find Conversation": "Find Conversation",
"Custom API Call": "Custom API Call",
"Upload text content to create a new document within the Cody knowledge base.": "Upload text content to create a new document within the Cody knowledge base.",
"Add a file directly into a specific folder in the knowledge base.": "Add a file directly into a specific folder in the knowledge base.",
"Send your message and receive the AI-generated response.": "Send your message and receive the AI-generated response.",
"Creates a new conversation with a bot.": "Creates a new conversation with a bot.",
"Finds a bot based on its name.": "Finds a bot based on its name.",
"Finds a conversation based on its name and/or the bot it belongs to.": "Finds a conversation based on its name and/or the bot it belongs to.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Folder": "Folder",
"Document Name": "Document Name",
"Content": "Content",
"File": "File",
"Conversation": "Conversation",
"Message": "Message",
"Bot": "Bot",
"Conversation Name": "Conversation Name",
"Document IDs (Focus Mode)": "Document IDs (Focus Mode)",
"Bot Name": "Bot Name",
"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)",
"The name or title of the new document.": "The name or title of the new document.",
"The text or HTML content to be added to the document. Max 768 KB.": "The text or HTML content to be added to the document. Max 768 KB.",
"The file to upload (e.g., txt, md, rtf, pdf, ppt, docx).": "The file to upload (e.g., txt, md, rtf, pdf, ppt, docx).",
"The message to send to the conversation. (Max 2000 characters)": "The message to send to the conversation. (Max 2000 characters)",
"The name for the new conversation.": "The name for the new conversation.",
"A list of document IDs to limit the bot's knowledge base for this conversation.": "A list of document IDs to limit the bot's knowledge base for this conversation.",
"The name of the bot to search for. The search is case-insensitive and partial.": "The name of the bot to search for. The search is case-insensitive and partial.",
"The name of the conversation to search for (partial match).": "The name of the conversation to search for (partial match).",
"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"
}

View File

@@ -0,0 +1,50 @@
{
"Visit your Cody AI API Keys page to retrieve the API key.": "Visit your Cody AI API Keys page to retrieve the API key.",
"Create Document From Text": "Create Document From Text",
"Upload File to Knowledge Base": "Upload File to Knowledge Base",
"Send Message": "Send Message",
"Create Conversation": "Create Conversation",
"Find Bot": "Find Bot",
"Find Conversation": "Find Conversation",
"Custom API Call": "自定义 API 呼叫",
"Upload text content to create a new document within the Cody knowledge base.": "Upload text content to create a new document within the Cody knowledge base.",
"Add a file directly into a specific folder in the knowledge base.": "Add a file directly into a specific folder in the knowledge base.",
"Send your message and receive the AI-generated response.": "Send your message and receive the AI-generated response.",
"Creates a new conversation with a bot.": "Creates a new conversation with a bot.",
"Finds a bot based on its name.": "Finds a bot based on its name.",
"Finds a conversation based on its name and/or the bot it belongs to.": "Finds a conversation based on its name and/or the bot it belongs to.",
"Make a custom API call to a specific endpoint": "将一个自定义 API 调用到一个特定的终点",
"Folder": "Folder",
"Document Name": "Document Name",
"Content": "Content",
"File": "文件",
"Conversation": "Conversation",
"Message": "Message",
"Bot": "Bot",
"Conversation Name": "Conversation Name",
"Document IDs (Focus Mode)": "Document IDs (Focus Mode)",
"Bot Name": "Bot Name",
"Method": "方法",
"Headers": "信头",
"Query Parameters": "查询参数",
"Body": "正文内容",
"Response is Binary ?": "Response is Binary ?",
"No Error on Failure": "失败时没有错误",
"Timeout (in seconds)": "超时(秒)",
"The name or title of the new document.": "The name or title of the new document.",
"The text or HTML content to be added to the document. Max 768 KB.": "The text or HTML content to be added to the document. Max 768 KB.",
"The file to upload (e.g., txt, md, rtf, pdf, ppt, docx).": "The file to upload (e.g., txt, md, rtf, pdf, ppt, docx).",
"The message to send to the conversation. (Max 2000 characters)": "The message to send to the conversation. (Max 2000 characters)",
"The name for the new conversation.": "The name for the new conversation.",
"A list of document IDs to limit the bot's knowledge base for this conversation.": "A list of document IDs to limit the bot's knowledge base for this conversation.",
"The name of the bot to search for. The search is case-insensitive and partial.": "The name of the bot to search for. The search is case-insensitive and partial.",
"The name of the conversation to search for (partial match).": "The name of the conversation to search for (partial match).",
"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": "黑色"
}

View File

@@ -0,0 +1,68 @@
import { PieceAuth, createPiece } from "@activepieces/pieces-framework";
import { createDocumentFromText } from "./lib/actions/create-document-from-text";
import { uploadFileAction } from "./lib/actions/upload-file";
import { sendMessageAction } from "./lib/actions/send-message";
import { createConversationAction } from "./lib/actions/create-conversation";
import { findBotAction } from "./lib/actions/find-bot";
import { findConversationAction } from "./lib/actions/find-conversation";
import { createCustomApiCallAction } from '@activepieces/pieces-common';
import { codyClient } from "./lib/common/client";
import { AppConnectionType } from "@activepieces/shared";
// Define the authentication property using PieceAuth.SecretText
// This will create a secure text input field in the UI for the user's API key.
export const codyAuth = PieceAuth.SecretText({
displayName: 'API Key',
description: `Visit your Cody AI API Keys page to retrieve the API key.`,
required: true,
validate: async ({ auth }) => {
if (auth) {
try {
await codyClient.listBots({
secret_text: auth,
type: AppConnectionType.SECRET_TEXT,
});
return {
valid: true,
}
} catch (error) {
return {
valid: false,
error: 'Invalid Api Key'
}
}
}
return {
valid: false,
error: 'Invalid Api Key'
}
},
});
export const cody = createPiece({
displayName: "Cody",
auth: codyAuth,
minimumSupportedRelease: '0.36.1',
logoUrl: "https://cdn.activepieces.com/pieces/cody.png",
authors: [ 'Pranith124','sanket-a11y' ],
actions: [
createDocumentFromText,
uploadFileAction,
sendMessageAction,
createConversationAction,
findBotAction,
findConversationAction,
createCustomApiCallAction({
auth: codyAuth,
baseUrl: () => 'https://getcody.ai/api/v1',
authMapping: async (auth) => ({
Authorization: `Bearer ${auth}`,
}),
}),
],
triggers: [
// Your triggers will go here
],
});

View File

@@ -0,0 +1,33 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { codyAuth } from '../..';
import { codyClient } from '../common/client';
import { botIdDropdown } from '../common/props';
export const createConversationAction = createAction({
auth: codyAuth,
name: 'create_conversation',
displayName: 'Create Conversation',
description: 'Creates a new conversation with a bot.',
props: {
bot_id: botIdDropdown,
name: Property.ShortText({
displayName: 'Conversation Name',
description: 'The name for the new conversation.',
required: true,
}),
document_ids: Property.Array({
displayName: 'Document IDs (Focus Mode)',
description:
"A list of document IDs to limit the bot's knowledge base for this conversation.",
required: false,
}),
},
async run(context) {
const { bot_id, name, document_ids } = context.propsValue;
const apiKey = context.auth;
const docIds = document_ids as string[] | undefined;
return await codyClient.createConversation(apiKey, bot_id, name, docIds);
},
});

View File

@@ -0,0 +1,30 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { codyAuth } from '../..';
import { codyClient } from '../common/client';
import { folderIdDropdown } from '../common/props';
export const createDocumentFromText = createAction({
auth: codyAuth,
name: 'create_document_from_text',
displayName: 'Create Document From Text',
description: 'Upload text content to create a new document within the Cody knowledge base.',
props: {
folder_id: folderIdDropdown,
name: Property.ShortText({
displayName: 'Document Name',
description: 'The name or title of the new document.',
required: true,
}),
content: Property.LongText({
displayName: 'Content',
description: 'The text or HTML content to be added to the document. Max 768 KB.',
required: true,
}),
},
async run(context) {
const { folder_id, name, content } = context.propsValue;
const apiKey = context.auth;
return await codyClient.createDocument(apiKey, name, folder_id, content);
},
});

View File

@@ -0,0 +1,30 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { codyAuth } from '../..';
import { codyClient } from '../common/client';
export const findBotAction = createAction({
auth: codyAuth,
name: 'find_bot',
displayName: 'Find Bot',
description: 'Finds a bot based on its name.',
props: {
name: Property.ShortText({
displayName: 'Bot Name',
description: 'The name of the bot to search for. The search is case-insensitive and partial.',
required: true,
})
},
async run(context) {
const { name } = context.propsValue;
const apiKey = context.auth;
const bots = await codyClient.listBots(apiKey, name);
// The API returns an array of matching bots.
// We will return the full array to the user.
return {
found: bots.length > 0,
bots: bots,
};
},
});

View File

@@ -0,0 +1,41 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { codyAuth } from '../..';
import { codyClient } from '../common/client';
import { botIdDropdown } from '../common/props';
export const findConversationAction = createAction({
auth: codyAuth,
name: 'find_conversation',
displayName: 'Find Conversation',
description: 'Finds a conversation based on its name and/or the bot it belongs to.',
props: {
bot_id: {
...botIdDropdown,
required: false,
},
name: Property.ShortText({
displayName: 'Conversation Name',
description: 'The name of the conversation to search for (partial match).',
required: false,
})
},
async run(context) {
const { bot_id, name } = context.propsValue;
const apiKey = context.auth;
if (!bot_id && !name) {
throw new Error("To find a conversation, please provide a Bot or a Conversation Name to search.");
}
const conversations = await codyClient.listConversations(apiKey, {
botId: bot_id,
keyword: name,
});
return {
found: conversations.length > 0,
conversations: conversations,
};
},
});

View File

@@ -0,0 +1,25 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { codyAuth } from '../..';
import { codyClient } from '../common/client';
import { conversationIdDropdown } from '../common/props';
export const sendMessageAction = createAction({
auth: codyAuth,
name: 'send_message',
displayName: 'Send Message',
description: 'Send your message and receive the AI-generated response.',
props: {
conversation_id: conversationIdDropdown,
content: Property.LongText({
displayName: 'Message',
description: 'The message to send to the conversation. (Max 2000 characters)',
required: true,
}),
},
async run(context) {
const { conversation_id, content } = context.propsValue;
const apiKey = context.auth;
return await codyClient.sendMessage(apiKey, conversation_id, content);
},
});

View File

@@ -0,0 +1,45 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { codyAuth } from '../..';
import { codyClient } from '../common/client';
import { folderIdDropdown } from '../common/props';
import mime from 'mime-types';
export const uploadFileAction = createAction({
auth: codyAuth,
name: 'upload_file',
displayName: 'Upload File to Knowledge Base',
description: 'Add a file directly into a specific folder in the knowledge base.',
props: {
folder_id: folderIdDropdown,
file: Property.File({
displayName: 'File',
description: 'The file to upload (e.g., txt, md, rtf, pdf, ppt, docx).',
required: true,
})
},
async run(context) {
const { folder_id, file } = context.propsValue;
const apiKey = context.auth;
// Step 1: Determine Content-Type from filename using the mime-types library
const contentType = mime.lookup(file.filename) || 'application/octet-stream';
// Step 2: Get a Signed URL from the Cody API
const { url: signedUrl, key } = await codyClient.getSignedUrl(
apiKey,
file.filename,
contentType
);
// Step 3: Upload the actual file data to the signed URL
await codyClient.uploadFileToS3(signedUrl, file.data, contentType);
// Step 4: Finalize the document creation in Cody
await codyClient.createDocumentFromFile(apiKey, folder_id, key);
return {
success: true,
message: `File '${file.filename}' uploaded successfully and is being processed.`
};
},
});

View File

@@ -0,0 +1,234 @@
import { HttpMethod, httpClient, HttpRequest, AuthenticationType } from "@activepieces/pieces-common";
import { AppConnectionValueForAuthProperty } from "@activepieces/pieces-framework";
import { codyAuth } from "../..";
export const CODY_BASE_URL = "https://getcody.ai/api/v1";
export interface CodyFolder {
id: string;
name: string;
}
export interface CodyListFoldersResponse {
data: CodyFolder[];
}
export interface CodyCreateDocumentResponse {
data: {
id: string;
name: string;
status: string;
content_url: string;
folder_id: string;
created_at: number;
}
}
// New interfaces for file upload
export interface CodySignedUrlResponse {
data: {
url: string;
key: string;
}
}
export interface CodyConversation {
id: string;
name: string;
}
export interface CodyListConversationsResponse {
data: CodyConversation[];
}
export interface CodyMessageResponse {
data: {
id: string;
content: string;
conversation_id: string;
machine: boolean;
failed_responding: boolean;
flagged: boolean;
created_at: number;
}
}
export interface CodyBot {
id: string;
name: string;
}
export interface CodyListBotsResponse {
data: CodyBot[];
}
export interface CodyCreateConversationResponse {
data: CodyConversation;
}
export const codyClient = {
async listFolders({secret_text}: AppConnectionValueForAuthProperty<typeof codyAuth>): Promise<CodyFolder[]> {
const response = await httpClient.sendRequest<CodyListFoldersResponse>({
method: HttpMethod.GET,
url: `${CODY_BASE_URL}/folders`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: secret_text,
},
});
return response.body.data;
},
async createDocument(
{secret_text}: AppConnectionValueForAuthProperty<typeof codyAuth>,
name: string,
folderId: string,
content: string
): Promise<CodyCreateDocumentResponse> {
const request: HttpRequest = {
method: HttpMethod.POST,
url: `${CODY_BASE_URL}/documents`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: secret_text,
},
body: {
name,
folder_id: folderId,
content,
},
};
const response = await httpClient.sendRequest<CodyCreateDocumentResponse>(request);
return response.body;
},
// New function to get the signed URL
async getSignedUrl({secret_text}: AppConnectionValueForAuthProperty<typeof codyAuth>, fileName: string, contentType: string): Promise<CodySignedUrlResponse['data']> {
const response = await httpClient.sendRequest<CodySignedUrlResponse>({
method: HttpMethod.POST,
url: `${CODY_BASE_URL}/uploads/signed-url`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: secret_text,
},
body: {
file_name: fileName,
content_type: contentType
}
});
return response.body.data;
},
// New function to upload the file buffer to S3
async uploadFileToS3(signedUrl: string, fileBuffer: Buffer, contentType: string): Promise<void> {
await httpClient.sendRequest({
method: HttpMethod.PUT,
url: signedUrl,
body: fileBuffer,
headers: {
'Content-Type': contentType,
},
});
},
// New function to finalize the document creation
async createDocumentFromFile({secret_text}: AppConnectionValueForAuthProperty<typeof codyAuth>, folderId: string, key: string): Promise<void> {
await httpClient.sendRequest({
method: HttpMethod.POST,
// This endpoint was in your first documentation dump.
url: `${CODY_BASE_URL}/documents/file`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: secret_text,
},
body: {
folder_id: folderId,
key: key,
},
});
},
async listConversations(
{secret_text}: AppConnectionValueForAuthProperty<typeof codyAuth>,
params?: { botId?: string; keyword?: string }
): Promise<CodyConversation[]> {
const queryParams: Record<string, string> = {};
if (params?.botId) {
queryParams['bot_id'] = params.botId;
}
if (params?.keyword) {
queryParams['keyword'] = params.keyword;
}
const response = await httpClient.sendRequest<CodyListConversationsResponse>({
method: HttpMethod.GET,
url: `${CODY_BASE_URL}/conversations`,
queryParams: queryParams,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: secret_text,
},
});
return response.body.data;
},
// New function to send a message
async sendMessage({secret_text}: AppConnectionValueForAuthProperty<typeof codyAuth>, conversationId: string, content: string): Promise<CodyMessageResponse> {
const response = await httpClient.sendRequest<CodyMessageResponse>({
method: HttpMethod.POST,
url: `${CODY_BASE_URL}/messages`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: secret_text,
},
body: {
conversation_id: conversationId,
content: content,
}
});
return response.body;
},
async listBots({secret_text}: AppConnectionValueForAuthProperty<typeof codyAuth>, keyword?: string): Promise<CodyBot[]> { // Add optional keyword parameter
const queryParams: Record<string, string> = {};
if (keyword) {
queryParams['keyword'] = keyword;
}
const response = await httpClient.sendRequest<CodyListBotsResponse>({
method: HttpMethod.GET,
url: `${CODY_BASE_URL}/bots`,
queryParams: queryParams, // Add queryParams to the request
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: secret_text,
},
});
return response.body.data;
},
// New function to create a conversation
async createConversation(
{secret_text}: AppConnectionValueForAuthProperty<typeof codyAuth>,
botId: string,
name: string,
documentIds?: string[]
): Promise<CodyCreateConversationResponse> {
const response = await httpClient.sendRequest<CodyCreateConversationResponse>({
method: HttpMethod.POST,
url: `${CODY_BASE_URL}/conversations`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: secret_text,
},
body: {
bot_id: botId,
name: name,
document_ids: documentIds,
}
});
return response.body;
},
};

View File

@@ -0,0 +1,122 @@
import { Property } from '@activepieces/pieces-framework';
import { codyClient } from './client';
import { codyAuth } from '../..';
export const folderIdDropdown = Property.Dropdown({
auth: codyAuth,
displayName: 'Folder',
required: true,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
placeholder: 'Connect your Cody AI account first.',
options: [],
};
}
try {
// Note: Comment removed as the endpoint is now confirmed.
const folders = await codyClient.listFolders(auth);
if (folders.length === 0) {
return {
disabled: true,
options: [],
placeholder: "No folders found. Please create a folder in Cody first.",
};
}
return {
disabled: false,
options: folders.map((folder) => ({
label: folder.name,
value: folder.id,
})),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: "Error listing folders. Check connection or API key permissions.",
};
}
},
});
export const conversationIdDropdown = Property.Dropdown({
displayName: 'Conversation',
auth: codyAuth,
required: true,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
placeholder: 'Connect your Cody AI account first.',
options: [],
};
}
try {
const conversations = await codyClient.listConversations(auth);
if (conversations.length === 0) {
return {
disabled: true,
options: [],
placeholder: "No conversations found. Please create one in Cody first.",
};
}
return {
disabled: false,
options: conversations.map((convo) => ({
label: convo.name,
value: convo.id,
})),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: "Error listing conversations.",
};
}
},
});
// Add the new dropdown for bots
export const botIdDropdown = Property.Dropdown({
auth: codyAuth,
displayName: 'Bot',
required: true,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
placeholder: 'Connect your Cody AI account first.',
options: [],
};
}
try {
const bots = await codyClient.listBots(auth);
if (bots.length === 0) {
return {
disabled: true,
options: [],
placeholder: "No bots found. Please create one in Cody first.",
};
}
return {
disabled: false,
options: bots.map((bot) => ({
label: bot.name,
value: bot.id,
})),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: "Error listing bots.",
};
}
},
});

View File

@@ -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"
}
]
}

View File

@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"include": ["src/**/*.ts"]
}