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,79 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
import { BASE_URL, personalAiAuth } from '../../../index';
export const createChatGPTInstruction = createAction({
auth:personalAiAuth,
name: 'create_chatgpt_instruction',
displayName: 'Send ChatGPT Instruction',
description: 'Send an instruction to AI assistant using ChatGPT integration.',
// category: 'AI Interaction',
props: {
text: Property.LongText({
displayName: 'Instruction Text',
description: 'The instruction or prompt to send to ChatGPT',
required: true,
}),
context: Property.LongText({
displayName: 'Context',
description: 'Additional context for the AI response',
required: false,
}),
domainName: Property.ShortText({
displayName: 'Domain Name',
description: 'The domain identifier for the AI profile',
required: false,
}),
userName: Property.ShortText({
displayName: 'User Name',
description: 'Name of the user sending the request',
required: false,
}),
sessionId: Property.ShortText({
displayName: 'Session ID',
description: 'Use the same sessionId to continue conversation on that session',
required: false,
}),
sourceName: Property.ShortText({
displayName: 'Source Name',
description: 'Name of the source app of the inbound instruction',
required: false,
}),
isStack: Property.Checkbox({
displayName: 'Add to Memory',
description: 'Flag to also add the user instruction to memory',
required: false,
defaultValue: false,
}),
isDraft: Property.Checkbox({
displayName: 'Create Draft',
description: 'Flag to create a copilot message for the AI',
required: false,
defaultValue: false,
}),
},
async run(context) {
const { auth, propsValue: { text, context: messageContext, domainName, userName, sessionId, sourceName, isStack, isDraft } } = context;
const response = await httpClient.sendRequest({
method: HttpMethod.POST,
url: `${BASE_URL}/v1/instruction?cmd=chatgpt`,
headers: {
'Content-Type': 'application/json',
'x-api-key': auth.secret_text,
},
body: {
Text: text,
...(messageContext && { Context: messageContext }),
...(domainName && { DomainName: domainName }),
...(userName && { UserName: userName }),
...(sessionId && { SessionId: sessionId }),
...(sourceName && { SourceName: sourceName }),
...(isStack !== undefined && { is_stack: isStack }),
...(isDraft !== undefined && { is_draft: isDraft }),
},
});
return response.body;
},
});

View File

@@ -0,0 +1,79 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
import { BASE_URL, personalAiAuth } from '../../../index';
export const createCustomTraining = createAction({
auth:personalAiAuth,
name: 'create_custom_training',
displayName: 'Send Custom Training',
description: 'Send a custom training instruction to AI assistant.',
// category: 'AI Interaction',
props: {
text: Property.LongText({
displayName: 'Training Text',
description: 'The training instruction or prompt to send',
required: true,
}),
context: Property.LongText({
displayName: 'Context',
description: 'Additional context for the AI response',
required: false,
}),
domainName: Property.ShortText({
displayName: 'Domain Name',
description: 'The domain identifier for the AI profile',
required: false,
}),
userName: Property.ShortText({
displayName: 'User Name',
description: 'Name of the user sending the request',
required: false,
}),
sessionId: Property.ShortText({
displayName: 'Session ID',
description: 'Use the same sessionId to continue conversation on that session',
required: false,
}),
sourceName: Property.ShortText({
displayName: 'Source Name',
description: 'Name of the source app of the inbound training',
required: false,
}),
isStack: Property.Checkbox({
displayName: 'Add to Memory',
description: 'Flag to also add the training instruction to memory',
required: false,
defaultValue: false,
}),
isDraft: Property.Checkbox({
displayName: 'Create Draft',
description: 'Flag to create a copilot message for the AI',
required: false,
defaultValue: false,
}),
},
async run(context) {
const { auth, propsValue: { text, context: messageContext, domainName, userName, sessionId, sourceName, isStack, isDraft } } = context;
const response = await httpClient.sendRequest({
method: HttpMethod.POST,
url: `${BASE_URL}/v1/training?cmd=custom`,
headers: {
'Content-Type': 'application/json',
'x-api-key': auth.secret_text,
},
body: {
Text: text,
...(messageContext && { Context: messageContext }),
...(domainName && { DomainName: domainName }),
...(userName && { UserName: userName }),
...(sessionId && { SessionId: sessionId }),
...(sourceName && { SourceName: sourceName }),
...(isStack !== undefined && { is_stack: isStack }),
...(isDraft !== undefined && { is_draft: isDraft }),
},
});
return response.body;
},
});

View File

@@ -0,0 +1,48 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
import { BASE_URL, personalAiAuth } from '../../../index';
export const getDocument = createAction({
auth:personalAiAuth,
name: 'get_document',
displayName: 'Get Document',
description: 'Retrieve a document from AI assistant.',
// category: 'Documents',
props: {
documentId: Property.ShortText({
displayName: 'Document ID',
description: 'The unique identifier of the document to retrieve',
required: true,
}),
domainName: Property.ShortText({
displayName: 'Domain Name',
description: 'The domain identifier for the AI profile',
required: false,
}),
includeContent: Property.Checkbox({
displayName: 'Include Content',
description: 'Flag to include the document content in the response',
required: false,
defaultValue: true,
}),
},
async run(context) {
const { auth, propsValue: { documentId, domainName, includeContent } } = context;
const response = await httpClient.sendRequest({
method: HttpMethod.GET,
url: `${BASE_URL}/get-document`,
headers: {
'Content-Type': 'application/json',
'x-api-key': auth.secret_text,
},
queryParams: {
DocumentId: documentId,
...(domainName && { DomainName: domainName }),
...(includeContent !== undefined && { IncludeContent: includeContent.toString() }),
},
});
return response.body;
},
});

View File

@@ -0,0 +1,78 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
import { BASE_URL, personalAiAuth } from '../../../index';
export const updateDocument = createAction({
auth:personalAiAuth,
name: 'update_document',
displayName: 'Update Document',
description: 'Update an existing document in AI assistant.',
// category: 'Documents',
props: {
documentId: Property.ShortText({
displayName: 'Document ID',
description: 'The unique identifier of the document to update',
required: true,
}),
text: Property.LongText({
displayName: 'Document Text',
description: 'The updated text content of the document',
required: true,
}),
title: Property.ShortText({
displayName: 'Document Title',
description: 'Updated title of the document',
required: false,
}),
domainName: Property.ShortText({
displayName: 'Domain Name',
description: 'The domain identifier for the AI profile',
required: false,
}),
tags: Property.ShortText({
displayName: 'Tags',
description: 'Comma delimited list of tags for the document',
required: false,
}),
sourceName: Property.ShortText({
displayName: 'Source Name',
description: 'Name of the source or application',
required: false,
}),
createdTime: Property.ShortText({
displayName: 'Created Time',
description: 'Time (including timezone) of the document creation (e.g., Wed, 19 Sep 2023 13:31:00 PDT)',
required: false,
}),
isStack: Property.Checkbox({
displayName: 'Add to Memory',
description: 'Flag to also add the document to memory',
required: false,
defaultValue: false,
}),
},
async run(context) {
const { auth, propsValue: { documentId, text, title, domainName, tags, sourceName, createdTime, isStack } } = context;
const response = await httpClient.sendRequest({
method: HttpMethod.PUT,
url: `${BASE_URL}/update-document`,
headers: {
'Content-Type': 'application/json',
'x-api-key': auth.secret_text,
},
body: {
DocumentId: documentId,
Text: text,
...(title && { Title: title }),
...(domainName && { DomainName: domainName }),
...(tags && { Tags: tags }),
...(sourceName && { SourceName: sourceName }),
...(createdTime && { CreatedTime: createdTime }),
...(isStack !== undefined && { is_stack: isStack }),
},
});
return response.body;
},
});

View File

@@ -0,0 +1,72 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
import { BASE_URL, personalAiAuth } from '../../../index';
export const uploadDocument = createAction({
auth:personalAiAuth,
name: 'upload_document',
displayName: 'Upload Document',
description: 'Upload a text document to AI assistant.',
// category: 'Documents',
props: {
text: Property.LongText({
displayName: 'Document Text',
description: 'The text content of the document to upload',
required: true,
}),
title: Property.ShortText({
displayName: 'Document Title',
description: 'Title of the document',
required: true,
}),
domainName: Property.ShortText({
displayName: 'Domain Name',
description: 'The domain identifier for the AI profile',
required: false,
}),
tags: Property.ShortText({
displayName: 'Tags',
description: 'Comma delimited list of tags for the document',
required: false,
}),
sourceName: Property.ShortText({
displayName: 'Source Name',
description: 'Name of the source or application',
required: false,
}),
createdTime: Property.ShortText({
displayName: 'Created Time',
description: 'Time (including timezone) of the document creation (e.g., Wed, 19 Sep 2023 13:31:00 PDT)',
required: false,
}),
isStack: Property.Checkbox({
displayName: 'Add to Memory',
description: 'Flag to also add the document to memory',
required: false,
defaultValue: false,
}),
},
async run(context) {
const { auth, propsValue: { text, title, domainName, tags, sourceName, createdTime, isStack } } = context;
const response = await httpClient.sendRequest({
method: HttpMethod.POST,
url: `${BASE_URL}/v1/upload-text`,
headers: {
'Content-Type': 'application/json',
'x-api-key': auth.secret_text,
},
body: {
Text: text,
Title: title,
...(domainName && { DomainName: domainName }),
...(tags && { Tags: tags }),
...(sourceName && { SourceName: sourceName }),
...(createdTime && { CreatedTime: createdTime }),
...(isStack !== undefined && { is_stack: isStack }),
},
});
return response.body;
},
});

View File

@@ -0,0 +1,73 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
import { BASE_URL, personalAiAuth } from '../../../index';
export const uploadFile = createAction({
auth:personalAiAuth,
name: 'upload_file',
displayName: 'Upload File',
description: 'Upload a file to AI assistant.',
// category: 'Documents',
props: {
file: Property.File({
displayName: 'File',
description: 'The file to upload',
required: true,
}),
fileName: Property.ShortText({
displayName: 'File Name',
description: 'Name of the file to be uploaded',
required: true,
}),
domainName: Property.ShortText({
displayName: 'Domain Name',
description: 'The domain identifier for the AI profile',
required: false,
}),
tags: Property.ShortText({
displayName: 'Tags',
description: 'Comma delimited list of tags for the file',
required: false,
}),
sourceName: Property.ShortText({
displayName: 'Source Name',
description: 'Name of the source or application',
required: false,
}),
createdTime: Property.ShortText({
displayName: 'Created Time',
description: 'Time (including timezone) of the file creation (e.g., Wed, 19 Sep 2023 13:31:00 PDT)',
required: false,
}),
isStack: Property.Checkbox({
displayName: 'Add to Memory',
description: 'Flag to also add the file content to memory',
required: false,
defaultValue: false,
}),
},
async run(context) {
const { auth, propsValue: { file, fileName, domainName, tags, sourceName, createdTime, isStack } } = context;
// Create form data for file upload
const formData = new FormData();
const blob = new Blob([file.data as any], { type: 'application/octet-stream' });
formData.append('file', blob, fileName);
if (domainName) formData.append('DomainName', domainName);
if (tags) formData.append('Tags', tags);
if (sourceName) formData.append('SourceName', sourceName);
if (createdTime) formData.append('CreatedTime', createdTime);
if (isStack !== undefined) formData.append('is_stack', isStack.toString());
const response = await httpClient.sendRequest({
method: HttpMethod.POST,
url: `${BASE_URL}/upload-file`,
headers: {
'x-api-key': auth.secret_text as string,
},
body: formData,
});
return response.body;
},
});

View File

@@ -0,0 +1,72 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
import { BASE_URL, personalAiAuth } from '../../../index';
export const uploadUrl = createAction({
auth:personalAiAuth,
name: 'upload_url',
displayName: 'Upload URL Content',
description: 'Upload content from a URL to AI assistant.',
// category: 'Documents',
props: {
url: Property.ShortText({
displayName: 'URL',
description: 'The URL of the content to upload',
required: true,
}),
title: Property.ShortText({
displayName: 'Title',
description: 'Title for the uploaded content',
required: true,
}),
domainName: Property.ShortText({
displayName: 'Domain Name',
description: 'The domain identifier for the AI profile',
required: false,
}),
tags: Property.ShortText({
displayName: 'Tags',
description: 'Comma delimited list of tags for the content',
required: false,
}),
sourceName: Property.ShortText({
displayName: 'Source Name',
description: 'Name of the source or application',
required: false,
}),
createdTime: Property.ShortText({
displayName: 'Created Time',
description: 'Time (including timezone) of the content creation (e.g., Wed, 19 Sep 2023 13:31:00 PDT)',
required: false,
}),
isStack: Property.Checkbox({
displayName: 'Add to Memory',
description: 'Flag to also add the content to memory',
required: false,
defaultValue: false,
}),
},
async run(context) {
const { auth, propsValue: { url, title, domainName, tags, sourceName, createdTime, isStack } } = context;
const response = await httpClient.sendRequest({
method: HttpMethod.POST,
url: `${BASE_URL}/upload-url`,
headers: {
'Content-Type': 'application/json',
'x-api-key': auth.secret_text,
},
body: {
Url: url,
Title: title,
...(domainName && { DomainName: domainName }),
...(tags && { Tags: tags }),
...(sourceName && { SourceName: sourceName }),
...(createdTime && { CreatedTime: createdTime }),
...(isStack !== undefined && { is_stack: isStack }),
},
});
return response.body;
},
});

View File

@@ -0,0 +1,65 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
import { BASE_URL, personalAiAuth } from '../../../index';
export const createMemory = createAction({
auth:personalAiAuth,
name: 'create_memory',
displayName: 'Create Memory',
description: 'Upload memories to your AI assistant stack.',
// category: 'Memory',
props: {
text: Property.LongText({
displayName: 'Memory Text',
description: 'Plain text memories to upload to your stack',
required: true,
}),
sourceName: Property.ShortText({
displayName: 'Source Name',
description: 'The source or application of memory to help you recall where it is from',
required: true,
}),
createdTime: Property.ShortText({
displayName: 'Created Time',
description: 'Time (including timezone) of the memory (e.g., Wed, 19 Sep 2023 13:31:00 PDT)',
required: false,
}),
rawFeedText: Property.LongText({
displayName: 'Raw Feed Text',
description: 'The formatted text that can be stored as it is',
required: false,
}),
domainName: Property.ShortText({
displayName: 'Domain Name',
description: 'The domain identifier for the AI persona',
required: false,
}),
tags: Property.ShortText({
displayName: 'Tags',
description: 'Comma delimited list of tags for the memory',
required: false,
}),
},
async run(context) {
const { auth, propsValue: { text, sourceName, createdTime, rawFeedText, domainName, tags } } = context;
const response = await httpClient.sendRequest({
method: HttpMethod.POST,
url: `${BASE_URL}/v1/memory`,
headers: {
'Content-Type': 'application/json',
'x-api-key': auth.secret_text,
},
body: {
Text: text,
SourceName: sourceName,
...(createdTime && { CreatedTime: createdTime }),
...(rawFeedText && { RawFeedText: rawFeedText }),
...(domainName && { DomainName: domainName }),
...(tags && { Tags: tags }),
},
});
return response.body;
},
});

View File

@@ -0,0 +1,79 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
import { BASE_URL, personalAiAuth } from '../../../index';
export const createMessage = createAction({
auth:personalAiAuth,
name: 'create_message',
displayName: 'Send Message',
description: 'Send a message to the AI assistant for a response.',
// category: 'Messaging',
props: {
text: Property.LongText({
displayName: 'Message Text',
description: 'Message to send to your AI for a response',
required: true,
}),
context: Property.LongText({
displayName: 'Context',
description: 'Additional context for the AI response (Similar to Reply function)',
required: false,
}),
domainName: Property.ShortText({
displayName: 'Domain Name',
description: 'The domain identifier for the AI profile',
required: false,
}),
userName: Property.ShortText({
displayName: 'User Name',
description: 'Name of the user sending the request',
required: false,
}),
sessionId: Property.ShortText({
displayName: 'Session ID',
description: 'Use the same sessionId to continue conversation on that session',
required: false,
}),
sourceName: Property.ShortText({
displayName: 'Source Name',
description: 'Name of the source app of the inbound message',
required: false,
}),
isStack: Property.Checkbox({
displayName: 'Add to Memory',
description: 'Flag to also add the user message to memory',
required: false,
defaultValue: false,
}),
isDraft: Property.Checkbox({
displayName: 'Create Draft',
description: 'Flag to create a copilot message for the AI',
required: false,
defaultValue: false,
}),
},
async run(context) {
const { auth, propsValue: { text, context: messageContext, domainName, userName, sessionId, sourceName, isStack, isDraft } } = context;
const response = await httpClient.sendRequest({
method: HttpMethod.POST,
url: `${BASE_URL}/v1/message`,
headers: {
'Content-Type': 'application/json',
'x-api-key': auth.secret_text,
},
body: {
Text: text,
...(messageContext && { Context: messageContext }),
...(domainName && { DomainName: domainName }),
...(userName && { UserName: userName }),
...(sessionId && { SessionId: sessionId }),
...(sourceName && { SourceName: sourceName }),
...(isStack !== undefined && { is_stack: isStack }),
...(isDraft !== undefined && { is_draft: isDraft }),
},
});
return response.body;
},
});

View File

@@ -0,0 +1,71 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
import { BASE_URL, personalAiAuth } from '../../../index';
export const getConversation = createAction({
auth:personalAiAuth,
name: 'get_conversation',
displayName: 'Get Conversation History',
description: 'Retrieve conversation history from AI assistant.',
// category: 'Messaging',
props: {
channelId: Property.ShortText({
displayName: 'Channel ID',
description: 'The unique identifier for the conversation channel',
required: true,
}),
domainName: Property.ShortText({
displayName: 'Domain Name',
description: 'The domain identifier for the AI profile',
required: false,
}),
userName: Property.ShortText({
displayName: 'User Name',
description: 'Name of the user requesting the conversation',
required: false,
}),
sessionId: Property.ShortText({
displayName: 'Session ID',
description: 'Filter conversation by specific session ID',
required: false,
}),
sourceName: Property.ShortText({
displayName: 'Source Name',
description: 'Filter conversation by source application',
required: false,
}),
limit: Property.Number({
displayName: 'Limit',
description: 'Maximum number of messages to return',
required: false,
}),
skip: Property.Number({
displayName: 'Skip',
description: 'Number of messages to skip (for pagination)',
required: false,
}),
},
async run(context) {
const { auth, propsValue: { channelId, domainName, userName, sessionId, sourceName, limit, skip } } = context;
const response = await httpClient.sendRequest({
method: HttpMethod.POST,
url: `${BASE_URL}/v1/conversation`,
headers: {
'Content-Type': 'application/json',
'x-api-key': auth.secret_text,
},
body: {
ChannelId: channelId,
...(domainName && { DomainName: domainName }),
...(userName && { UserName: userName }),
...(sessionId && { SessionId: sessionId }),
...(sourceName && { SourceName: sourceName }),
...(limit !== undefined && { Limit: limit }),
...(skip !== undefined && { Skip: skip }),
},
});
return response.body;
},
});