From ee2b486697419033be93cfe0021c665e40c37b75 Mon Sep 17 00:00:00 2001 From: Abraham Lopez <10536776+AbrahamLopez10@users.noreply.github.com> Date: Mon, 2 Feb 2026 14:13:58 -0500 Subject: [PATCH 1/2] chore(integrations/google-ai): override Gemini 3 model IDs (#14905) --- .../google-ai/src/actions/generate-content.ts | 8 ++++++-- integrations/google-ai/src/index.ts | 10 ++++------ integrations/google-ai/src/schemas.ts | 13 ++++++------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/integrations/google-ai/src/actions/generate-content.ts b/integrations/google-ai/src/actions/generate-content.ts index faaaafb8033..c6a43c2e8e9 100644 --- a/integrations/google-ai/src/actions/generate-content.ts +++ b/integrations/google-ai/src/actions/generate-content.ts @@ -17,7 +17,7 @@ import { FunctionDeclaration, } from '@google/genai' import crypto from 'crypto' -import { DefaultModelId, DiscontinuedModelIds, ModelId } from 'src/schemas' +import { DefaultModelId, DiscontinuedModelIds, ModelId, OverrideModelIds } from 'src/schemas' type ReasoningEffort = NonNullable @@ -127,7 +127,7 @@ async function buildGenerateContentRequest( } let defaultReasoningEffort: ReasoningEffort = 'none' - if (modelId === 'gemini-3-pro-preview') { + if (modelId === 'gemini-3-pro') { // Gemini 3 Pro doesn't support disabling reasoning, so we use the lowest reasoning effort by default. defaultReasoningEffort = 'low' } @@ -135,6 +135,10 @@ async function buildGenerateContentRequest( const thinkingBudget = ThinkingModeBudgetTokens[input.reasoningEffort ?? defaultReasoningEffort] const modelSupportsThinking = modelId !== 'models/gemini-2.0-flash' // Gemini 2.0 doesn't support thinking mode + if (OverrideModelIds[modelId]) { + modelId = OverrideModelIds[modelId] as ModelId + } + return { model: modelId, contents: await buildContents(input), diff --git a/integrations/google-ai/src/index.ts b/integrations/google-ai/src/index.ts index 144e6fec88d..c94c7d9228e 100644 --- a/integrations/google-ai/src/index.ts +++ b/integrations/google-ai/src/index.ts @@ -1,15 +1,13 @@ import { llm } from '@botpress/common' import { GoogleGenAI } from '@google/genai' import { generateContent } from './actions/generate-content' -import { ModelId } from './schemas' +import { DefaultModelId, ModelId } from './schemas' import * as bp from '.botpress' const googleAIClient = new GoogleGenAI({ apiKey: bp.secrets.GOOGLE_AI_API_KEY }) -const DEFAULT_LANGUAGE_MODEL_ID: ModelId = 'models/gemini-2.0-flash' - const languageModels: Record = { - 'gemini-3-pro-preview': { + 'gemini-3-pro': { name: 'Gemini 3 Pro (Preview)', description: "One of the best models for multimodal understanding, and Google's most powerful agentic and vibe-coding model yet, delivering richer visuals and deeper interactivity, built on a foundation of state-of-the-art reasoning.", @@ -25,7 +23,7 @@ const languageModels: Record = { maxTokens: 65_536, }, }, - 'gemini-3-flash-preview': { + 'gemini-3-flash': { name: 'Gemini 3 Flash (Preview)', description: "Google's most balanced model built for speed, scale, and frontier intelligence.", tags: ['preview', 'reasoning', 'agents', 'general-purpose', 'vision'], @@ -96,7 +94,7 @@ export default new bp.Integration({ generateContent: async ({ input, logger, metadata }) => { const output = await generateContent(input, googleAIClient, logger, { models: languageModels, - defaultModel: DEFAULT_LANGUAGE_MODEL_ID, + defaultModel: DefaultModelId, }) metadata.setCost(output.botpress.cost) return output diff --git a/integrations/google-ai/src/schemas.ts b/integrations/google-ai/src/schemas.ts index 8bae789d954..a7034c33c4b 100644 --- a/integrations/google-ai/src/schemas.ts +++ b/integrations/google-ai/src/schemas.ts @@ -3,17 +3,16 @@ import { z } from '@botpress/sdk' export const DefaultModelId: ModelId = 'gemini-2.5-flash' export const ModelId = z - .enum([ - 'gemini-3-pro-preview', - 'gemini-3-flash-preview', - 'gemini-2.5-flash', - 'gemini-2.5-pro', - 'models/gemini-2.0-flash', - ]) + .enum(['gemini-3-pro', 'gemini-3-flash', 'gemini-2.5-flash', 'gemini-2.5-pro', 'models/gemini-2.0-flash']) .describe('Model to use for content generation') .placeholder(DefaultModelId) export type ModelId = z.infer +export const OverrideModelIds: Partial> = { + 'gemini-3-pro': 'gemini-3-pro-preview', + 'gemini-3-flash': 'gemini-3-flash-preview', +} + export const DiscontinuedModelIds = [ 'models/gemini-1.5-flash-8b-001', 'models/gemini-1.5-flash-002', From c1cdcfed7b6a4b54fe895256e578955e0aed5c68 Mon Sep 17 00:00:00 2001 From: Mathieu Faucher <99497774+Math-Fauch@users.noreply.github.com> Date: Mon, 2 Feb 2026 18:21:39 -0500 Subject: [PATCH 2/2] chore(integrations): resolve linting issues (#14890) --- .../deploy-integrations-production.yml | 2 +- .../airtable/integration.definition.ts | 2 +- integrations/airtable/src/misc/sub-schemas.ts | 15 +- integrations/attio/definitions/actions.ts | 126 +++++++----- integrations/attio/definitions/events.ts | 27 ++- integrations/attio/integration.definition.ts | 2 +- integrations/attio/package.json | 1 + .../integration.definition.ts | 2 +- integrations/bigcommerce-sync/package.json | 1 + integrations/canny/integration.definition.ts | 120 +++++------ integrations/chat/integration.definition.ts | 18 +- integrations/chat/package.json | 2 +- integrations/dropbox/definitions/states.ts | 10 +- .../dropbox/integration.definition.ts | 2 +- integrations/email/integration.definition.ts | 54 +++-- integrations/email/package.json | 1 + .../definitions/actions/comments.ts | 44 ++-- .../feature-base/definitions/actions/posts.ts | 2 +- .../feature-base/integration.definition.ts | 2 +- integrations/github/integration.definition.ts | 2 +- integrations/github/src/definitions/events.ts | 4 +- .../googledrive/integration.definition.ts | 2 +- integrations/googledrive/package.json | 1 + integrations/googledrive/src/schemas.ts | 82 +++++--- integrations/hunter/definitions/schemas.ts | 188 +++++++++++------- integrations/hunter/integration.definition.ts | 2 +- integrations/loops/definitions/schemas.ts | 15 +- integrations/loops/integration.definition.ts | 2 +- .../mailchimp/integration.definition.ts | 2 +- .../mailchimp/src/misc/custom-schemas.ts | 50 ++--- .../mailchimp/src/misc/sub-schemas.ts | 112 ++++++----- integrations/notion/definitions/events.ts | 6 +- integrations/notion/integration.definition.ts | 2 +- integrations/resend/integration.definition.ts | 2 +- .../src/webhook-events/schemas/email.ts | 8 +- .../tally/definitions/schemas/tally-fields.ts | 60 +++--- .../definitions/schemas/tally-submissions.ts | 17 +- integrations/tally/integration.definition.ts | 2 +- integrations/teams/definitions/states.ts | 4 +- integrations/teams/integration.definition.ts | 2 +- integrations/webflow/definitions/actions.ts | 72 ++++--- .../webflow/integration.definition.ts | 2 +- integrations/zapier/integration.definition.ts | 2 +- integrations/zapier/src/types.ts | 2 +- .../zendesk/integration.definition.ts | 2 +- .../zendesk/src/definitions/schemas.ts | 60 +++--- packages/chat-api/src/version.ts | 2 +- 47 files changed, 666 insertions(+), 474 deletions(-) diff --git a/.github/workflows/deploy-integrations-production.yml b/.github/workflows/deploy-integrations-production.yml index 54a79372592..178ce6f41a6 100644 --- a/.github/workflows/deploy-integrations-production.yml +++ b/.github/workflows/deploy-integrations-production.yml @@ -31,7 +31,7 @@ jobs: uses: ./.github/actions/deploy-integrations with: environment: 'production' - extra_filter: "-F '!docusign' -F '!zendesk-messaging-hitl'" + extra_filter: "-F '!docusign' -F '!zendesk-messaging-hitl' -F '!zendesk'" force: ${{ github.event.inputs.force == 'true' }} sentry_auth_token: ${{ secrets.SENTRY_AUTH_TOKEN }} token_cloud_ops_account: ${{ secrets.PRODUCTION_TOKEN_CLOUD_OPS_ACCOUNT }} diff --git a/integrations/airtable/integration.definition.ts b/integrations/airtable/integration.definition.ts index 58ff8c14839..bd3a073b6a8 100644 --- a/integrations/airtable/integration.definition.ts +++ b/integrations/airtable/integration.definition.ts @@ -19,7 +19,7 @@ export default new IntegrationDefinition({ title: 'Airtable', description: 'Access and manage Airtable data to allow your chatbot to retrieve details, update records, and organize information.', - version: '1.0.1', + version: '1.0.2', readme: 'hub.md', icon: 'icon.svg', configuration: { diff --git a/integrations/airtable/src/misc/sub-schemas.ts b/integrations/airtable/src/misc/sub-schemas.ts index 4bef1595a18..ac1bcfb3b52 100644 --- a/integrations/airtable/src/misc/sub-schemas.ts +++ b/integrations/airtable/src/misc/sub-schemas.ts @@ -1,8 +1,19 @@ import { z } from '@botpress/sdk' -const fieldSchema = z.object({ name: z.string(), type: z.string() }).passthrough() +const fieldSchema = z + .object({ + name: z.string().title('Name').describe('Field name'), + type: z.string().title('Type').describe('Field type'), + }) + .passthrough() -const viewSchema = z.object({ id: z.string(), name: z.string(), type: z.string() }).passthrough() +const viewSchema = z + .object({ + id: z.string().title('ID').describe('View ID'), + name: z.string().title('Name').describe('View name'), + type: z.string().title('Type').describe('View type'), + }) + .passthrough() const tableSchema = z.object({ description: z.string().optional().describe('The description of the table').title('description'), diff --git a/integrations/attio/definitions/actions.ts b/integrations/attio/definitions/actions.ts index 94d91c2ccff..272451b82bd 100644 --- a/integrations/attio/definitions/actions.ts +++ b/integrations/attio/definitions/actions.ts @@ -3,7 +3,7 @@ import { baseIdentifierSchema } from './common' const recordSchema = z .object({ - id: baseIdentifierSchema, + id: baseIdentifierSchema.describe('The record identifier'), created_at: z.string().title('Created At').describe('RFC3339 timestamp when the record was created'), web_url: z.string().title('Web URL').describe('URL of the record in Attio UI'), values: z @@ -16,34 +16,39 @@ const recordSchema = z // Objects & Attributes const objectSchema = z .object({ - id: baseIdentifierSchema.optional(), - api_slug: z.string().optional(), - singular_noun: z.string().optional(), - plural_noun: z.string().optional(), - created_at: z.string().optional(), + id: baseIdentifierSchema.optional().describe('The object identifier'), + api_slug: z.string().optional().title('API Slug').describe('The API slug for the object'), + singular_noun: z.string().optional().title('Singular Noun').describe('The singular form of the object name'), + plural_noun: z.string().optional().title('Plural Noun').describe('The plural form of the object name'), + created_at: z.string().optional().title('Created At').describe('RFC3339 timestamp when the object was created'), }) .title('Object') const attributeSchema = z .object({ - id: baseIdentifierSchema.extend({ attribute_id: z.string().optional() }).optional(), - title: z.string().optional(), - description: z.string().nullable().optional(), - api_slug: z.string().optional(), - type: z.string().optional(), - slug: z.string().optional(), + id: baseIdentifierSchema + .extend({ attribute_id: z.string().optional().title('Attribute ID').describe('The attribute identifier') }) + .optional() + .describe('The attribute identifier object'), + title: z.string().optional().title('Title').describe('The title of the attribute'), + description: z.string().nullable().optional().title('Description').describe('The description of the attribute'), + api_slug: z.string().optional().title('API Slug').describe('The API slug for the attribute'), + type: z.string().optional().title('Type').describe('The type of the attribute'), + slug: z.string().optional().title('Slug').describe('The slug for the attribute'), options: z .array( z.object({ - id: z.string().optional(), - label: z.string().optional(), - name: z.string().optional(), - value: z.string().optional(), - title: z.string().optional(), - slug: z.string().optional(), + id: z.string().optional().title('ID').describe('The option identifier'), + label: z.string().optional().title('Label').describe('The label of the option'), + name: z.string().optional().title('Name').describe('The name of the option'), + value: z.string().optional().title('Value').describe('The value of the option'), + title: z.string().optional().title('Title').describe('The title of the option'), + slug: z.string().optional().title('Slug').describe('The slug of the option'), }) ) - .optional(), + .optional() + .title('Options') + .describe('The list of options for the attribute'), }) .title('Attribute') @@ -56,8 +61,8 @@ const listRecords: ActionDefinition = { filter: z .array( z.object({ - attribute: z.string().min(1).title('Attribute'), - value: z.string().min(1).title('Value'), + attribute: z.string().min(1).title('Attribute').describe('The attribute to filter by'), + value: z.string().min(1).title('Value').describe('The value to filter for'), }) ) .optional() @@ -66,9 +71,9 @@ const listRecords: ActionDefinition = { sorts: z .array( z.object({ - direction: z.enum(['asc', 'desc']).title('Direction'), - attribute: z.string().min(1).title('Attribute'), - field: z.string().min(1).title('Field'), + direction: z.enum(['asc', 'desc']).title('Direction').describe('The sort direction'), + attribute: z.string().min(1).title('Attribute').describe('The attribute to sort by'), + field: z.string().min(1).title('Field').describe('The field to sort by'), }) ) .optional() @@ -93,18 +98,23 @@ const getRecord: ActionDefinition = { input: { schema: z.object({ object: z.string().min(1).title('Object').describe('Object slug or UUID'), - id: baseIdentifierSchema.extend({ record_id: z.string().min(1).title('Record ID').describe('Record UUID') }), + id: baseIdentifierSchema + .extend({ record_id: z.string().min(1).title('Record ID').describe('Record UUID') }) + .describe('The record identifier'), }), }, output: { schema: z .object({ - data: z.object({ - id: baseIdentifierSchema.title('Identifier').describe('The fetched identifier'), - web_url: z.string().title('Web URL').describe('URL of the record in Attio UI'), - values: z.record(z.any()).title('Values').describe('Map of attribute slug/ID to value(s)'), - created_at: z.string().title('Created At').describe('RFC3339 timestamp when the record was created'), - }), + data: z + .object({ + id: baseIdentifierSchema.title('Identifier').describe('The fetched identifier'), + web_url: z.string().title('Web URL').describe('URL of the record in Attio UI'), + values: z.record(z.any()).title('Values').describe('Map of attribute slug/ID to value(s)'), + created_at: z.string().title('Created At').describe('RFC3339 timestamp when the record was created'), + }) + .title('Data') + .describe('The fetched record data'), }) .title('Get Record Response'), }, @@ -116,17 +126,20 @@ const createRecord: ActionDefinition = { input: { schema: z.object({ object: z.string().min(1).title('Object').describe('Object slug or UUID'), - data: z.object({ - values: z - .array( - z.object({ - attribute: z.string().min(1).title('Attribute'), - value: z.string().min(1).title('Value'), - }) - ) - .title('Values') - .describe('Array of attribute slug/ID to value(s)'), - }), + data: z + .object({ + values: z + .array( + z.object({ + attribute: z.string().min(1).title('Attribute').describe('The attribute slug or ID'), + value: z.string().min(1).title('Value').describe('The value to set for the attribute'), + }) + ) + .title('Values') + .describe('Array of attribute slug/ID to value(s)'), + }) + .title('Data') + .describe('The record data to create'), }), }, output: { @@ -144,18 +157,23 @@ const updateRecord: ActionDefinition = { input: { schema: z.object({ object: z.string().min(1).title('Object').describe('Object slug or UUID'), - id: baseIdentifierSchema.extend({ record_id: z.string().min(1).title('Record ID').describe('Record UUID') }), - data: z.object({ - values: z - .array( - z.object({ - attribute: z.string().min(1).title('Attribute'), - value: z.string().min(1).title('Value'), - }) - ) - .title('Values') - .describe('Array of attribute slug/ID to value(s) to upsert'), - }), + id: baseIdentifierSchema + .extend({ record_id: z.string().min(1).title('Record ID').describe('Record UUID') }) + .describe('The record identifier'), + data: z + .object({ + values: z + .array( + z.object({ + attribute: z.string().min(1).title('Attribute').describe('The attribute slug or ID'), + value: z.string().min(1).title('Value').describe('The value to set for the attribute'), + }) + ) + .title('Values') + .describe('Array of attribute slug/ID to value(s) to upsert'), + }) + .title('Data') + .describe('The record data to update'), }), }, output: { diff --git a/integrations/attio/definitions/events.ts b/integrations/attio/definitions/events.ts index fbc148d3f10..316f2d48998 100644 --- a/integrations/attio/definitions/events.ts +++ b/integrations/attio/definitions/events.ts @@ -3,29 +3,40 @@ import { baseIdentifierSchema } from './common' const recordEventSchema = z.object({ event_type: z.string().title('Event Type').describe('The type of event'), - id: baseIdentifierSchema.extend({ record_id: z.string().title('Record ID').describe('The record identifier') }), - actor: z.object({ - type: z.string().title('Actor Type').describe('The type of actor (e.g., workspace-member)'), - id: z.string().title('Actor ID').describe('The actor identifier'), - }), + id: baseIdentifierSchema + .extend({ record_id: z.string().title('Record ID').describe('The record identifier') }) + .describe('The record identifier object'), + actor: z + .object({ + type: z.string().title('Actor Type').describe('The type of actor (e.g., workspace-member)'), + id: z.string().title('Actor ID').describe('The actor identifier'), + }) + .title('Actor') + .describe('The actor who triggered the event'), }) const recordCreated: EventDefinition = { title: 'Record Created', description: 'A new record has been created in Attio', - schema: recordEventSchema.extend({ event_type: z.literal('record.created') }), + schema: recordEventSchema.extend({ + event_type: z.literal('record.created').title('Event Type').describe('The type of event'), + }), } const recordUpdated: EventDefinition = { title: 'Record Updated', description: 'A record has been updated in Attio', - schema: recordEventSchema.extend({ event_type: z.literal('record.updated') }), + schema: recordEventSchema.extend({ + event_type: z.literal('record.updated').title('Event Type').describe('The type of event'), + }), } const recordDeleted: EventDefinition = { title: 'Record Deleted', description: 'A record has been deleted in Attio', - schema: recordEventSchema.extend({ event_type: z.literal('record.deleted') }), + schema: recordEventSchema.extend({ + event_type: z.literal('record.deleted').title('Event Type').describe('The type of event'), + }), } export const events = { diff --git a/integrations/attio/integration.definition.ts b/integrations/attio/integration.definition.ts index ee5a45d20ff..6c537b2f55d 100644 --- a/integrations/attio/integration.definition.ts +++ b/integrations/attio/integration.definition.ts @@ -3,7 +3,7 @@ import { actions, states, events } from './definitions' export default new IntegrationDefinition({ name: 'attio', - version: '1.0.0', + version: '1.0.1', title: 'Attio', readme: 'hub.md', diff --git a/integrations/attio/package.json b/integrations/attio/package.json index c525dd530e2..31273dd4861 100644 --- a/integrations/attio/package.json +++ b/integrations/attio/package.json @@ -2,6 +2,7 @@ "name": "@botpresshub/attio", "scripts": { "check:type": "tsc --noEmit", + "check:bplint": "bp lint", "build": "bp add -y && bp build", "test": "vitest --run" }, diff --git a/integrations/bigcommerce-sync/integration.definition.ts b/integrations/bigcommerce-sync/integration.definition.ts index 974dca5ca5b..746279e2c4f 100644 --- a/integrations/bigcommerce-sync/integration.definition.ts +++ b/integrations/bigcommerce-sync/integration.definition.ts @@ -4,7 +4,7 @@ import { configuration, states, actions } from './src/definitions/index' export default new IntegrationDefinition({ name: 'bigcommerce', title: 'BigCommerce', - version: '3.2.0', + version: '3.2.1', readme: 'hub.md', icon: 'icon.svg', description: 'Sync products from BigCommerce to Botpress', diff --git a/integrations/bigcommerce-sync/package.json b/integrations/bigcommerce-sync/package.json index 63ca4c052b3..de88a89cc9d 100644 --- a/integrations/bigcommerce-sync/package.json +++ b/integrations/bigcommerce-sync/package.json @@ -2,6 +2,7 @@ "name": "@botpresshub/bigcommerce", "scripts": { "check:type": "tsc --noEmit", + "check:bplint": "bp lint", "build": "bp add -y && bp build", "test": "vitest --run" }, diff --git a/integrations/canny/integration.definition.ts b/integrations/canny/integration.definition.ts index db6ef988ab3..e35ac0250c2 100644 --- a/integrations/canny/integration.definition.ts +++ b/integrations/canny/integration.definition.ts @@ -2,7 +2,7 @@ import { z, IntegrationDefinition } from '@botpress/sdk' export default new IntegrationDefinition({ name: 'canny', - version: '0.2.0', + version: '0.2.1', title: 'Canny', description: 'Connect your Botpress bot to Canny for feature request management and customer feedback collection', readme: 'hub.md', @@ -102,17 +102,17 @@ export default new IntegrationDefinition({ schema: z.object({ post: z .object({ - id: z.string(), - title: z.string(), - details: z.string().optional(), - authorName: z.string().optional(), - authorEmail: z.string().optional(), - boardName: z.string(), - status: z.string(), - score: z.number(), - commentCount: z.number(), - created: z.string(), - url: z.string(), + id: z.string().title('ID').describe('Post ID'), + title: z.string().title('Title').describe('Post title'), + details: z.string().optional().title('Details').describe('Post details'), + authorName: z.string().optional().title('Author Name').describe('Name of the post author'), + authorEmail: z.string().optional().title('Author Email').describe('Email of the post author'), + boardName: z.string().title('Board Name').describe('Name of the board'), + status: z.string().title('Status').describe('Post status'), + score: z.number().title('Score').describe('Post score'), + commentCount: z.number().title('Comment Count').describe('Number of comments'), + created: z.string().title('Created').describe('Creation timestamp'), + url: z.string().title('URL').describe('Post URL'), }) .title('Post') .describe('The retrieved post object'), @@ -144,17 +144,17 @@ export default new IntegrationDefinition({ posts: z .array( z.object({ - id: z.string(), - title: z.string(), - details: z.string().optional(), - authorName: z.string().optional(), - authorEmail: z.string().optional(), - boardName: z.string(), - status: z.string(), - score: z.number(), - commentCount: z.number(), - created: z.string(), - url: z.string(), + id: z.string().title('ID').describe('Post ID'), + title: z.string().title('Title').describe('Post title'), + details: z.string().optional().title('Details').describe('Post details'), + authorName: z.string().optional().title('Author Name').describe('Name of the post author'), + authorEmail: z.string().optional().title('Author Email').describe('Email of the post author'), + boardName: z.string().title('Board Name').describe('Name of the board'), + status: z.string().title('Status').describe('Post status'), + score: z.number().title('Score').describe('Post score'), + commentCount: z.number().title('Comment Count').describe('Number of comments'), + created: z.string().title('Created').describe('Creation timestamp'), + url: z.string().title('URL').describe('Post URL'), }) ) .title('Posts') @@ -232,15 +232,15 @@ export default new IntegrationDefinition({ schema: z.object({ comment: z .object({ - id: z.string(), - value: z.string(), - authorName: z.string(), - authorEmail: z.string(), - postTitle: z.string(), - postId: z.string(), - created: z.string(), - internal: z.boolean(), - likeCount: z.number(), + id: z.string().title('ID').describe('Comment ID'), + value: z.string().title('Value').describe('Comment text'), + authorName: z.string().title('Author Name').describe('Name of the comment author'), + authorEmail: z.string().title('Author Email').describe('Email of the comment author'), + postTitle: z.string().title('Post Title').describe('Title of the associated post'), + postId: z.string().title('Post ID').describe('ID of the associated post'), + created: z.string().title('Created').describe('Creation timestamp'), + internal: z.boolean().title('Internal').describe('Whether this is an internal comment'), + likeCount: z.number().title('Like Count').describe('Number of likes'), }) .title('Comment') .describe('The retrieved comment object'), @@ -269,15 +269,15 @@ export default new IntegrationDefinition({ comments: z .array( z.object({ - id: z.string(), - value: z.string(), - authorName: z.string(), - authorEmail: z.string(), - postTitle: z.string(), - postId: z.string(), - created: z.string(), - internal: z.boolean(), - likeCount: z.number(), + id: z.string().title('ID').describe('Comment ID'), + value: z.string().title('Value').describe('Comment text'), + authorName: z.string().title('Author Name').describe('Name of the comment author'), + authorEmail: z.string().title('Author Email').describe('Email of the comment author'), + postTitle: z.string().title('Post Title').describe('Title of the associated post'), + postId: z.string().title('Post ID').describe('ID of the associated post'), + created: z.string().title('Created').describe('Creation timestamp'), + internal: z.boolean().title('Internal').describe('Whether this is an internal comment'), + likeCount: z.number().title('Like Count').describe('Number of likes'), }) ) .title('Comments') @@ -322,13 +322,13 @@ export default new IntegrationDefinition({ schema: z.object({ user: z .object({ - id: z.string(), - name: z.string(), - email: z.string(), - avatarURL: z.string().optional(), - userId: z.string(), - isAdmin: z.boolean(), - created: z.string(), + id: z.string().title('ID').describe('User ID'), + name: z.string().title('Name').describe('User display name'), + email: z.string().title('Email').describe('User email address'), + avatarURL: z.string().optional().title('Avatar URL').describe('User avatar URL'), + userId: z.string().title('User ID').describe('Your internal user ID'), + isAdmin: z.boolean().title('Is Admin').describe('Whether the user is an admin'), + created: z.string().title('Created').describe('User creation timestamp'), }) .title('User') .describe('The created or updated user object'), @@ -355,13 +355,13 @@ export default new IntegrationDefinition({ users: z .array( z.object({ - id: z.string(), - name: z.string(), - email: z.string(), - avatarURL: z.string().optional(), - userId: z.string(), // Can be empty string if user has no userId - isAdmin: z.boolean(), - created: z.string(), + id: z.string().title('ID').describe('User ID'), + name: z.string().title('Name').describe('User display name'), + email: z.string().title('Email').describe('User email address'), + avatarURL: z.string().optional().title('Avatar URL').describe('User avatar URL'), + userId: z.string().title('User ID').describe('Your internal user ID'), // Can be empty string if user has no userId + isAdmin: z.boolean().title('Is Admin').describe('Whether the user is an admin'), + created: z.string().title('Created').describe('User creation timestamp'), }) ) .title('Users') @@ -386,11 +386,11 @@ export default new IntegrationDefinition({ boards: z .array( z.object({ - id: z.string(), - name: z.string(), - postCount: z.number(), - url: z.string(), - created: z.string(), + id: z.string().title('ID').describe('Board ID'), + name: z.string().title('Name').describe('Board name'), + postCount: z.number().title('Post Count').describe('Number of posts in the board'), + url: z.string().title('URL').describe('Board URL'), + created: z.string().title('Created').describe('Board creation timestamp'), }) ) .title('Boards') diff --git a/integrations/chat/integration.definition.ts b/integrations/chat/integration.definition.ts index 970a200a3ac..830a0c1033a 100644 --- a/integrations/chat/integration.definition.ts +++ b/integrations/chat/integration.definition.ts @@ -38,9 +38,12 @@ export default new sdk.IntegrationDefinition({ title: 'Custom Event', description: 'Custom event sent from the chat client to the bot', schema: z.object({ - userId: z.string(), - conversationId: z.string(), - payload: z.record(z.any()), + userId: z.string().title('User ID').describe('The ID of the user who sent the custom event'), + conversationId: z + .string() + .title('Conversation ID') + .describe('The ID of the conversation where the event was sent'), + payload: z.record(z.any()).title('Payload').describe('Custom data payload sent with the event'), }), }, }, @@ -50,8 +53,11 @@ export default new sdk.IntegrationDefinition({ description: 'Send a custom event from the bot to the chat client', input: { schema: z.object({ - conversationId: z.string(), - payload: z.record(z.any()), + conversationId: z + .string() + .title('Conversation ID') + .describe('The ID of the conversation to send the event to'), + payload: z.record(z.any()).title('Payload').describe('Custom data payload to send with the event'), }), }, output: { @@ -61,6 +67,8 @@ export default new sdk.IntegrationDefinition({ }, channels: { channel: { + title: 'Chat Channel', + description: 'Web chat channel for communicating with users via HTTP requests', conversation: { tags: { owner: { title: 'Conversation Owner', description: 'ID of the user who created the conversation' }, diff --git a/integrations/chat/package.json b/integrations/chat/package.json index 349c38e8340..64b0166f5ce 100644 --- a/integrations/chat/package.json +++ b/integrations/chat/package.json @@ -2,7 +2,7 @@ "name": "@botpresshub/chat", "scripts": { "check:type": "tsc --noEmit", - "check:blint": "bp lint", + "check:bplint": "bp lint", "generate": "ts-node -T ./openapi.ts ./src/gen", "build": "bp add -y && bp build", "test": "vitest --run" diff --git a/integrations/dropbox/definitions/states.ts b/integrations/dropbox/definitions/states.ts index 59b21aeaea2..69948e8d81e 100644 --- a/integrations/dropbox/definitions/states.ts +++ b/integrations/dropbox/definitions/states.ts @@ -4,9 +4,13 @@ export const states = { authorization: { type: 'integration', schema: sdk.z.object({ - refreshToken: sdk.z.string().describe('Refresh token used to generate a new access token').secret(), - grantedScopes: sdk.z.array(sdk.z.string()).describe('Scopes granted by the user'), - accountId: sdk.z.string().describe('User ID of the authenticated user'), + refreshToken: sdk.z + .string() + .title('Refresh Token') + .describe('Refresh token used to generate a new access token') + .secret(), + grantedScopes: sdk.z.array(sdk.z.string()).title('Granted Scopes').describe('Scopes granted by the user'), + accountId: sdk.z.string().title('Account ID').describe('User ID of the authenticated user'), authorizationCode: sdk.z .string() .title('Access Code') diff --git a/integrations/dropbox/integration.definition.ts b/integrations/dropbox/integration.definition.ts index 43e12f230a2..0644d7132bc 100644 --- a/integrations/dropbox/integration.definition.ts +++ b/integrations/dropbox/integration.definition.ts @@ -5,7 +5,7 @@ import { actions, configuration, entities, secrets, states } from './definitions export default new sdk.IntegrationDefinition({ name: 'dropbox', title: 'Dropbox', - version: '1.2.0', + version: '1.2.1', description: 'Manage your files and folders effortlessly.', readme: 'hub.md', icon: 'icon.svg', diff --git a/integrations/email/integration.definition.ts b/integrations/email/integration.definition.ts index ca6ab8c97e2..55594d32269 100644 --- a/integrations/email/integration.definition.ts +++ b/integrations/email/integration.definition.ts @@ -1,17 +1,19 @@ import { z, IntegrationDefinition, messages } from '@botpress/sdk' const emailSchema = z.object({ - id: z.string(), - subject: z.string(), - inReplyTo: z.string().optional(), + id: z.string().describe('The unique identifier of the email'), + subject: z.string().describe('The subject line of the email'), + inReplyTo: z.string().optional().describe('The ID of the email this is replying to'), date: z.string().optional().describe('ISO datetime'), - sender: z.string(), - firstMessageId: z.string().optional(), + sender: z.string().describe('The email address of the sender'), + firstMessageId: z.string().optional().describe('The ID of the first message in the conversation thread'), }) export default new IntegrationDefinition({ name: 'email', - version: '0.1.0', + version: '0.1.1', + title: 'Email', + description: 'Send and receive emails using IMAP and SMTP protocols', readme: 'hub.md', icon: 'icon.svg', configuration: { @@ -30,12 +32,22 @@ export default new IntegrationDefinition({ lastSyncTimestamp: { type: 'integration', schema: z.object({ - lastSyncTimestamp: z.string().datetime(), + lastSyncTimestamp: z + .string() + .datetime() + .title('Last Sync Timestamp') + .describe('The timestamp of the last successful email synchronization'), }), }, syncLock: { type: 'integration', - schema: z.object({ currentlySyncing: z.boolean().default(false) }), + schema: z.object({ + currentlySyncing: z + .boolean() + .default(false) + .title('Currently Syncing') + .describe('Indicates whether an email synchronization is currently in progress'), + }), }, }, actions: { @@ -44,13 +56,18 @@ export default new IntegrationDefinition({ description: 'List all emails in the inbox', input: { schema: z.object({ - nextToken: z.string().optional().describe('The page number in the inbox. Starts at 0').optional(), + nextToken: z + .string() + .optional() + .title('Next Token') + .describe('The page number in the inbox. Starts at 0') + .optional(), }), }, output: { schema: z.object({ - messages: z.array(emailSchema), - nextToken: z.string().optional(), + messages: z.array(emailSchema).describe('The list of email messages'), + nextToken: z.string().optional().describe('Token for retrieving the next page of results'), }), }, }, @@ -59,12 +76,12 @@ export default new IntegrationDefinition({ description: 'Get the email with specified id from the inbox', input: { schema: z.object({ - id: z.string(), + id: z.string().title('Email ID').describe('The unique identifier of the email to retrieve'), }), }, output: { schema: emailSchema.extend({ - body: z.string().optional(), + body: z.string().optional().describe('The body content of the email'), }), }, }, @@ -81,13 +98,14 @@ export default new IntegrationDefinition({ description: 'Send an email using SMTP', input: { schema: z.object({ - to: z.string().describe('The email address of the recipient'), - subject: z.string().optional().describe('The subject of the outgoing email'), - text: z.string().optional().describe('The text contained in the body of the email'), - inReplyTo: z.string().optional().describe('The id of the email you want to reply to'), + to: z.string().title('To').describe('The email address of the recipient'), + subject: z.string().optional().title('Subject').describe('The subject of the outgoing email'), + text: z.string().optional().title('Text').describe('The text contained in the body of the email'), + inReplyTo: z.string().optional().title('In Reply To').describe('The id of the email you want to reply to'), replyTo: z .string() .optional() + .title('Reply To') .describe( 'The email address to which replies should be sent. This allows recipients to reply to a different address than the sender' ), @@ -100,6 +118,8 @@ export default new IntegrationDefinition({ }, channels: { default: { + title: 'Email', + description: 'Email channel for sending and receiving emails', message: { tags: { id: { title: 'Email id', description: 'The email id ' } } }, messages: { text: messages.defaults.text }, conversation: { diff --git a/integrations/email/package.json b/integrations/email/package.json index c28b01eaedb..3cb76f713bc 100644 --- a/integrations/email/package.json +++ b/integrations/email/package.json @@ -2,6 +2,7 @@ "name": "@botpresshub/email", "scripts": { "check:type": "tsc --noEmit", + "check:bplint": "bp lint", "build": "bp build", "test": "vitest --run" }, diff --git a/integrations/feature-base/definitions/actions/comments.ts b/integrations/feature-base/definitions/actions/comments.ts index 331af258cd6..d573ace92a5 100644 --- a/integrations/feature-base/definitions/actions/comments.ts +++ b/integrations/feature-base/definitions/actions/comments.ts @@ -46,26 +46,30 @@ export const getComments = { .array( z .object({ - id: z.string(), - upvoted: z.boolean().optional(), - downvoted: z.boolean().optional(), - inReview: z.boolean().optional(), - isSpam: z.boolean().optional(), - pinned: z.boolean().optional(), - emailSent: z.boolean().optional(), - sendNotification: z.boolean().optional(), - organization: z.string().optional(), - submission: z.string().optional(), - author: z.string().optional(), - authorId: z.string().optional(), - authorPicture: z.string().optional(), - isPrivate: z.boolean().optional(), - isDeleted: z.boolean().optional(), - content: z.string().optional(), - upvotes: z.number().optional(), - downvotes: z.number().optional(), - parentComment: z.string().nullable().optional(), - path: z.string().optional(), + id: z.string().title('ID').describe('Comment ID'), + upvoted: z.boolean().optional().title('Upvoted').describe('Whether the comment is upvoted'), + downvoted: z.boolean().optional().title('Downvoted').describe('Whether the comment is downvoted'), + inReview: z.boolean().optional().title('In Review').describe('Whether the comment is in review'), + isSpam: z.boolean().optional().title('Is Spam').describe('Whether the comment is marked as spam'), + pinned: z.boolean().optional().title('Pinned').describe('Whether the comment is pinned'), + emailSent: z.boolean().optional().title('Email Sent').describe('Whether an email notification was sent'), + sendNotification: z + .boolean() + .optional() + .title('Send Notification') + .describe('Whether to send notifications'), + organization: z.string().optional().title('Organization').describe('Organization ID'), + submission: z.string().optional().title('Submission').describe('Submission ID'), + author: z.string().optional().title('Author').describe('Author name'), + authorId: z.string().optional().title('Author ID').describe('Author ID'), + authorPicture: z.string().optional().title('Author Picture').describe('Author profile picture URL'), + isPrivate: z.boolean().optional().title('Is Private').describe('Whether the comment is private'), + isDeleted: z.boolean().optional().title('Is Deleted').describe('Whether the comment is deleted'), + content: z.string().optional().title('Content').describe('Comment content'), + upvotes: z.number().optional().title('Upvotes').describe('Number of upvotes'), + downvotes: z.number().optional().title('Downvotes').describe('Number of downvotes'), + parentComment: z.string().nullable().optional().title('Parent Comment').describe('Parent comment ID'), + path: z.string().optional().title('Path').describe('Comment path'), }) .title('Comment') .describe('Represent a single comment.') diff --git a/integrations/feature-base/definitions/actions/posts.ts b/integrations/feature-base/definitions/actions/posts.ts index 3460fe6114f..1c22c8db282 100644 --- a/integrations/feature-base/definitions/actions/posts.ts +++ b/integrations/feature-base/definitions/actions/posts.ts @@ -44,7 +44,7 @@ export const createPost = { schema: z.object({ submission: z .object({ - id: z.string(), + id: z.string().title('ID').describe('Submission ID'), }) .title('Submission') .describe('Represent the created post.'), diff --git a/integrations/feature-base/integration.definition.ts b/integrations/feature-base/integration.definition.ts index c61ed1acdfe..ad33559b991 100644 --- a/integrations/feature-base/integration.definition.ts +++ b/integrations/feature-base/integration.definition.ts @@ -5,7 +5,7 @@ import { postCreated, postUpdated, postDeleted, postVoted } from 'definitions/ev export default new IntegrationDefinition({ name: 'feature-base', - version: '1.0.0', + version: '1.0.1', title: 'Feature Base', description: 'Integration with Feature Base for Botpress', readme: 'hub.md', diff --git a/integrations/github/integration.definition.ts b/integrations/github/integration.definition.ts index 86b29d41ed5..eb31449fb5e 100644 --- a/integrations/github/integration.definition.ts +++ b/integrations/github/integration.definition.ts @@ -7,7 +7,7 @@ import { actions, events, configuration, configurations, channels, user, secrets export default new sdk.IntegrationDefinition({ name: INTEGRATION_NAME, title: 'GitHub', - version: '1.1.6', + version: '1.1.7', icon: 'icon.svg', readme: 'hub.md', description: 'Manage GitHub issues, pull requests, and repositories.', diff --git a/integrations/github/src/definitions/events.ts b/integrations/github/src/definitions/events.ts index dd09f358334..4b9fa4dd815 100644 --- a/integrations/github/src/definitions/events.ts +++ b/integrations/github/src/definitions/events.ts @@ -62,8 +62,8 @@ export const pullRequestMerged = { targets: z .object({ pullRequest: z.string().optional().title('DEPRECATED: pullRequest').describe('use pullRequest.number instead'), - issue: z.string().optional().title('DEPRECATED: issue'), - discussion: z.string().optional().title('DEPRECATED: discussion'), + issue: z.string().optional().title('DEPRECATED: issue').describe('Not needed'), + discussion: z.string().optional().title('DEPRECATED: discussion').describe('Not needed'), }) .title('DEPRECATED: targets') .describe('Not needed'), diff --git a/integrations/googledrive/integration.definition.ts b/integrations/googledrive/integration.definition.ts index 55ba0fe5a8d..ba418498309 100644 --- a/integrations/googledrive/integration.definition.ts +++ b/integrations/googledrive/integration.definition.ts @@ -24,7 +24,7 @@ export default new sdk.IntegrationDefinition({ name: 'googledrive', title: 'Google Drive', description: 'Access and manage your Google Drive files from your bot.', - version: '0.3.4', + version: '0.3.5', readme: 'hub.md', icon: 'icon.svg', configuration: { diff --git a/integrations/googledrive/package.json b/integrations/googledrive/package.json index 837b045243e..e0710ad1c52 100644 --- a/integrations/googledrive/package.json +++ b/integrations/googledrive/package.json @@ -2,6 +2,7 @@ "name": "@botpresshub/googledrive", "scripts": { "check:type": "tsc --noEmit", + "check:bplint": "bp lint", "build": "bp add -y && bp build", "test": "vitest --run" }, diff --git a/integrations/googledrive/src/schemas.ts b/integrations/googledrive/src/schemas.ts index 0a1c11241bd..a050feae369 100644 --- a/integrations/googledrive/src/schemas.ts +++ b/integrations/googledrive/src/schemas.ts @@ -4,28 +4,38 @@ import { APP_GOOGLE_FOLDER_MIMETYPE, APP_GOOGLE_SHORTCUT_MIMETYPE } from './mime // Utility schemas export const fileIdSchema = z.string().min(1).describe('The ID of the Google Drive file') export const commonFileAttrSchema = z.object({ - id: fileIdSchema, - name: z.string().min(1).describe('The name of the file'), + id: fileIdSchema.title('File ID'), + name: z.string().min(1).title('Name').describe('The name of the file'), parentId: z .string() .min(1) .optional() + .title('Parent ID') .describe("The ID of the file that is the parent of this file. If not set, 'My Drive' is the parent"), - mimeType: z.string().min(1).describe('The media type of the file'), + mimeType: z.string().min(1).title('MIME Type').describe('The media type of the file'), }) export const baseNormalFileSchema = commonFileAttrSchema.extend({ - size: z.number().nonnegative().describe('The size in bytes of the file'), - contentHash: z.string().optional().describe('The hash of the file content, or version/revision number'), - lastModifiedDate: z.string().datetime().optional().describe('The last modified date of the file in RFC 3339 format'), + size: z.number().nonnegative().title('Size').describe('The size in bytes of the file'), + contentHash: z + .string() + .optional() + .title('Content Hash') + .describe('The hash of the file content, or version/revision number'), + lastModifiedDate: z + .string() + .datetime() + .optional() + .title('Last Modified Date') + .describe('The last modified date of the file in RFC 3339 format'), }) export const baseFolderFileSchema = commonFileAttrSchema.extend({ - mimeType: z.literal(APP_GOOGLE_FOLDER_MIMETYPE), + mimeType: z.literal(APP_GOOGLE_FOLDER_MIMETYPE).title('MIME Type').describe('The media type of the folder'), }) export const baseShortcutFileSchema = commonFileAttrSchema.extend({ - mimeType: z.literal(APP_GOOGLE_SHORTCUT_MIMETYPE), + mimeType: z.literal(APP_GOOGLE_SHORTCUT_MIMETYPE).title('MIME Type').describe('The media type of the shortcut'), }) const _fileTypesArray = ['normal', 'folder', 'shortcut'] as const @@ -41,14 +51,20 @@ export const fileTypesUnionSchema = z.union([ Type is added to enable discrimination and remove/add access to properties depending on file type. */ export const baseDiscriminatedFileSchema = z.discriminatedUnion('type', [ - baseNormalFileSchema.extend({ type: z.literal(_fileTypes.normal) }), - baseFolderFileSchema.extend({ type: z.literal(_fileTypes.folder) }), - baseShortcutFileSchema.extend({ type: z.literal(_fileTypes.shortcut) }), + baseNormalFileSchema.extend({ type: z.literal(_fileTypes.normal).title('Type').describe('The type of the file') }), + baseFolderFileSchema.extend({ type: z.literal(_fileTypes.folder).title('Type').describe('The type of the file') }), + baseShortcutFileSchema.extend({ + type: z.literal(_fileTypes.shortcut).title('Type').describe('The type of the file'), + }), ]) export const baseChannelSchema = z.object({ - id: z.string().min(1).describe('The ID of the channel'), - resourceId: z.string().min(1).describe('The ID of the watched resource (different from the file ID)'), + id: z.string().min(1).title('Channel ID').describe('The ID of the channel'), + resourceId: z + .string() + .min(1) + .title('Resource ID') + .describe('The ID of the watched resource (different from the file ID)'), }) const notificationTypesSchema = z.union([ @@ -88,6 +104,7 @@ const computedFileAttrSchema = z.object({ .min(1) .describe("A component of the path of the file. It corresponds to the name of one of it's parents.") ) + .title('Path') .describe("An array of the path's components sorted by level (root to leaf)"), }) export const fileSchema = baseNormalFileSchema.merge(computedFileAttrSchema) @@ -99,7 +116,7 @@ export const genericFileSchema = z.discriminatedUnion('type', [ shortcutSchema.extend({ type: z.literal(_fileTypes.shortcut) }), ]) export const fileChannelSchema = baseChannelSchema.extend({ - fileId: fileIdSchema, + fileId: fileIdSchema.title('File ID'), }) // Action args/outputs @@ -110,25 +127,27 @@ function createListOutputSchema(itemSchema: T) { .describe( 'The list of items listed in Google Drive. Results may be paginated. If set, use nextToken to get additional results' ), - meta: z.object({ - nextToken: z - .string() - .optional() - .describe('The token to pass as input to the next call of the list action to list additional items'), - }), + meta: z + .object({ + nextToken: z + .string() + .optional() + .describe('The token to pass as input to the next call of the list action to list additional items'), + }) + .describe('Metadata about the list results, including pagination information'), }) } export const createFileArgSchema = commonFileAttrSchema.omit({ id: true, // Unknown at creation time }) -export const readFileArgSchema = z.object({ id: fileIdSchema }) +export const readFileArgSchema = z.object({ id: fileIdSchema.title('File ID') }) export const updateFileArgSchema = commonFileAttrSchema.omit({ mimeType: true, // Cannot be changed unless data is uploaded with a new type }) -export const deleteFileArgSchema = z.object({ id: fileIdSchema }) +export const deleteFileArgSchema = z.object({ id: fileIdSchema.title('File ID') }) export const listItemsInputSchema = z.object({ - nextToken: z.string().optional().describe('The token to use to get the next page of results'), + nextToken: z.string().optional().title('Next Token').describe('The token to use to get the next page of results'), }) export const listItemsOutputSchema = createListOutputSchema(z.any()) export const listFilesOutputSchema = createListOutputSchema(fileSchema) @@ -137,17 +156,22 @@ export const listFoldersOutputSchema = createListOutputSchema(folderSchema) // URL is used instead of ID because an integration can't access all files of a bot // using the files API export const uploadFileDataArgSchema = z.object({ - id: z.string().min(1), - url: z.string().min(1).describe('The URL used to access the file whose content will be uploaded to Google Drive'), + id: z.string().min(1).title('File ID').describe('The ID of the Google Drive file to upload content to'), + url: z + .string() + .min(1) + .title('File URL') + .describe('The URL used to access the file whose content will be uploaded to Google Drive'), mimeType: z .string() .min(1) .optional() + .title('MIME Type') .describe('Media type of the uploaded content. This will override any previously set media type'), }) export const downloadFileDataArgSchema = z.object({ - id: z.string().min(1).describe('The ID of the Google Drive file whose content will be downloaded'), - index: z.boolean().describe('Indicates if the file is to be indexed or not'), + id: z.string().min(1).title('File ID').describe('The ID of the Google Drive file whose content will be downloaded'), + index: z.boolean().title('Index File').describe('Indicates if the file is to be indexed or not'), }) export const downloadFileDataOutputSchema = z.object({ bpFileId: z @@ -157,8 +181,8 @@ export const downloadFileDataOutputSchema = z.object({ }) export const fileDeletedEventSchema = z.object({ - id: fileIdSchema, + id: fileIdSchema.title('File ID'), }) export const folderDeletedEventSchema = z.object({ - id: fileIdSchema, + id: fileIdSchema.title('Folder ID'), }) diff --git a/integrations/hunter/definitions/schemas.ts b/integrations/hunter/definitions/schemas.ts index 8240cec8de1..8ec5bea6043 100644 --- a/integrations/hunter/definitions/schemas.ts +++ b/integrations/hunter/definitions/schemas.ts @@ -3,36 +3,52 @@ import { z } from '@botpress/sdk' export type Lead = z.infer export const leadSchema = z .object({ - id: z.number(), - email: z.string().email(), - first_name: z.string().nullable(), - last_name: z.string().nullable(), - position: z.string().nullable(), - company: z.string().nullable(), - company_industry: z.string().nullable(), - company_size: z.string().nullable(), - confidence_score: z.number().min(0).max(100).nullable(), - website: z.string().nullable(), - country_code: z.string().nullable(), - source: z.string().nullable(), - linkedin_url: z.string().nullable(), - phone_number: z.string().nullable(), - twitter: z.string().nullable(), - sync_status: z.string().nullable(), - notes: z.string().nullable(), - sending_status: z.string().nullable(), - last_activity_at: z.string().nullable(), - last_contacted_at: z.string().nullable(), - verification: z.object({ - date: z.string().nullable(), - status: z.string().nullable(), - }), - leads_list: z.object({ - id: z.number(), - name: z.string(), - leads_count: z.number(), - }), - created_at: z.string(), + id: z.number().title('ID').describe('Unique identifier of the lead'), + email: z.string().email().title('Email').describe('Email address of the lead'), + first_name: z.string().nullable().title('First Name').describe('First name of the lead'), + last_name: z.string().nullable().title('Last Name').describe('Last name of the lead'), + position: z.string().nullable().title('Position').describe('Job position of the lead'), + company: z.string().nullable().title('Company').describe('Company name of the lead'), + company_industry: z.string().nullable().title('Company Industry').describe('Industry of the lead company'), + company_size: z.string().nullable().title('Company Size').describe('Size of the lead company'), + confidence_score: z + .number() + .min(0) + .max(100) + .nullable() + .title('Confidence Score') + .describe('Confidence score of the lead email'), + website: z.string().nullable().title('Website').describe('Website URL of the lead'), + country_code: z.string().nullable().title('Country Code').describe('Country code of the lead'), + source: z.string().nullable().title('Source').describe('Source of the lead'), + linkedin_url: z.string().nullable().title('LinkedIn URL').describe('LinkedIn profile URL of the lead'), + phone_number: z.string().nullable().title('Phone Number').describe('Phone number of the lead'), + twitter: z.string().nullable().title('Twitter').describe('Twitter handle of the lead'), + sync_status: z.string().nullable().title('Sync Status').describe('Synchronization status of the lead'), + notes: z.string().nullable().title('Notes').describe('Additional notes about the lead'), + sending_status: z.string().nullable().title('Sending Status').describe('Email sending status of the lead'), + last_activity_at: z.string().nullable().title('Last Activity At').describe('Last activity timestamp of the lead'), + last_contacted_at: z + .string() + .nullable() + .title('Last Contacted At') + .describe('Last contacted timestamp of the lead'), + verification: z + .object({ + date: z.string().nullable().title('Date').describe('Verification date of the lead email'), + status: z.string().nullable().title('Status').describe('Verification status of the lead email'), + }) + .title('Verification') + .describe('Email verification details'), + leads_list: z + .object({ + id: z.number().title('ID').describe('ID of the leads list'), + name: z.string().title('Name').describe('Name of the leads list'), + leads_count: z.number().title('Leads Count').describe('Number of leads in the list'), + }) + .title('Leads List') + .describe('Leads list information'), + created_at: z.string().title('Created At').describe('Creation timestamp of the lead'), }) .catchall(z.string().nullable()) .title('Lead') @@ -41,24 +57,34 @@ export const leadSchema = z export type LeadPayload = z.infer export const leadPayloadSchema = z .object({ - email: z.string().email(), - first_name: z.string().optional(), - last_name: z.string().optional(), - position: z.string().optional(), - company: z.string().optional(), - company_industry: z.string().optional(), - company_size: z.string().optional(), - confidence_score: z.number().min(0).max(100).optional(), - website: z.string().optional(), - country_code: z.string().optional(), - source: z.string().optional(), - linkedin_url: z.string().optional(), - phone_number: z.string().optional(), - twitter: z.string().optional(), - notes: z.string().optional(), - leads_list_id: z.number().optional(), - leads_list_ids: z.array(z.number()).optional(), - custom_attributes: z.record(z.string()).optional(), + email: z.string().email().title('Email').describe('Email address of the lead'), + first_name: z.string().optional().title('First Name').describe('First name of the lead'), + last_name: z.string().optional().title('Last Name').describe('Last name of the lead'), + position: z.string().optional().title('Position').describe('Job position of the lead'), + company: z.string().optional().title('Company').describe('Company name of the lead'), + company_industry: z.string().optional().title('Company Industry').describe('Industry of the lead company'), + company_size: z.string().optional().title('Company Size').describe('Size of the lead company'), + confidence_score: z + .number() + .min(0) + .max(100) + .optional() + .title('Confidence Score') + .describe('Confidence score of the lead email'), + website: z.string().optional().title('Website').describe('Website URL of the lead'), + country_code: z.string().optional().title('Country Code').describe('Country code of the lead'), + source: z.string().optional().title('Source').describe('Source of the lead'), + linkedin_url: z.string().optional().title('LinkedIn URL').describe('LinkedIn profile URL of the lead'), + phone_number: z.string().optional().title('Phone Number').describe('Phone number of the lead'), + twitter: z.string().optional().title('Twitter').describe('Twitter handle of the lead'), + notes: z.string().optional().title('Notes').describe('Additional notes about the lead'), + leads_list_id: z.number().optional().title('Leads List ID').describe('ID of the leads list'), + leads_list_ids: z.array(z.number()).optional().title('Leads List IDs').describe('Array of leads list IDs'), + custom_attributes: z + .record(z.string()) + .optional() + .title('Custom Attributes') + .describe('Custom attributes for the lead'), }) .title('Lead Payload') .describe('Schema for creating or updating a lead in Hunter.io') @@ -66,33 +92,53 @@ export const leadPayloadSchema = z export type SearchLeadsPayload = z.infer export const searchLeadsPayloadSchema = z .object({ - leads_list_id: z.number().optional(), - email: z.string().optional(), - first_name: z.string().optional(), - last_name: z.string().optional(), - position: z.string().optional(), - company: z.string().optional(), - industry: z.string().optional(), - website: z.string().optional(), - country_code: z.string().optional(), - company_size: z.string().optional(), - source: z.string().optional(), - twitter: z.string().optional(), - linkedin_url: z.string().optional(), - phone_number: z.string().optional(), - sync_status: z.enum(['pending', 'error', 'success']).optional(), + leads_list_id: z.number().optional().title('Leads List ID').describe('Filter by leads list ID'), + email: z.string().optional().title('Email').describe('Filter by email address'), + first_name: z.string().optional().title('First Name').describe('Filter by first name'), + last_name: z.string().optional().title('Last Name').describe('Filter by last name'), + position: z.string().optional().title('Position').describe('Filter by job position'), + company: z.string().optional().title('Company').describe('Filter by company name'), + industry: z.string().optional().title('Industry').describe('Filter by company industry'), + website: z.string().optional().title('Website').describe('Filter by website URL'), + country_code: z.string().optional().title('Country Code').describe('Filter by country code'), + company_size: z.string().optional().title('Company Size').describe('Filter by company size'), + source: z.string().optional().title('Source').describe('Filter by lead source'), + twitter: z.string().optional().title('Twitter').describe('Filter by Twitter handle'), + linkedin_url: z.string().optional().title('LinkedIn URL').describe('Filter by LinkedIn URL'), + phone_number: z.string().optional().title('Phone Number').describe('Filter by phone number'), + sync_status: z + .enum(['pending', 'error', 'success']) + .optional() + .title('Sync Status') + .describe('Filter by synchronization status'), sending_status: z .array(z.enum(['clicked', 'opened', 'sent', 'pending', 'error', 'bounced', 'unsubscribed', 'replied', '~'])) - .optional(), + .optional() + .title('Sending Status') + .describe('Filter by email sending status'), verification_status: z .array(z.enum(['accept_all', 'disposable', 'invalid', 'unknown', 'valid', 'webmail', 'pending', '~'])) - .optional(), - last_activity_at: z.enum(['*', '~']).optional(), - last_contacted_at: z.enum(['*', '~']).optional(), - custom_attributes: z.record(z.string()).optional(), - query: z.string().optional().describe('Filter on first name, last name or email'), - limit: z.number().min(1).max(1000).optional(), - offset: z.number().min(0).max(100000).optional(), + .optional() + .title('Verification Status') + .describe('Filter by email verification status'), + last_activity_at: z + .enum(['*', '~']) + .optional() + .title('Last Activity At') + .describe('Filter by last activity timestamp'), + last_contacted_at: z + .enum(['*', '~']) + .optional() + .title('Last Contacted At') + .describe('Filter by last contacted timestamp'), + custom_attributes: z + .record(z.string()) + .optional() + .title('Custom Attributes') + .describe('Filter by custom attributes'), + query: z.string().optional().title('Query').describe('Filter on first name, last name or email'), + limit: z.number().min(1).max(1000).optional().title('Limit').describe('Maximum number of results to return'), + offset: z.number().min(0).max(100000).optional().title('Offset').describe('Number of results to skip'), }) .title('Search Leads Payload') .describe('Schema for searching leads in Hunter.io') diff --git a/integrations/hunter/integration.definition.ts b/integrations/hunter/integration.definition.ts index 8d07578f9bd..5ab3867a874 100644 --- a/integrations/hunter/integration.definition.ts +++ b/integrations/hunter/integration.definition.ts @@ -3,7 +3,7 @@ import { leadSchema, leadPayloadSchema, searchLeadsPayloadSchema } from './defin export default new IntegrationDefinition({ name: 'hunter', - version: '1.0.0', + version: '1.0.1', title: 'Hunter.io', description: 'Manage leads in Hunter.io', readme: 'hub.md', diff --git a/integrations/loops/definitions/schemas.ts b/integrations/loops/definitions/schemas.ts index 400c70426b9..8af6953544c 100644 --- a/integrations/loops/definitions/schemas.ts +++ b/integrations/loops/definitions/schemas.ts @@ -4,7 +4,12 @@ export const sendTransactionalEmailInputSchema = z.object({ email: z.string().describe('The email address of the recipient.').title('Email'), transactionalId: z.string().describe('The ID of the transactional email to send.').title('Transactional ID'), dataVariables: z - .array(z.object({ key: z.string(), value: z.string() })) + .array( + z.object({ + key: z.string().title('Key').describe('The key of the data variable'), + value: z.string().title('Value').describe('The value of the data variable'), + }) + ) .describe('An object containing data as defined by the data variables added to the transactional email template.') .title('Data Variables'), addToAudience: z @@ -29,7 +34,13 @@ export const sendTransactionalEmailInputSchema = z.object({ ) .title('File IDs'), fileData: z - .array(z.object({ filename: z.string(), contentType: z.string(), data: z.string() })) + .array( + z.object({ + filename: z.string().title('Filename').describe('The name of the file'), + contentType: z.string().title('Content Type').describe('The MIME content type of the file'), + data: z.string().title('Data').describe('The base64-encoded data of the file'), + }) + ) .optional() .describe('The name, base64-encoded data, and MIME content type of custom files to be attached to the email.') .title('File Data'), diff --git a/integrations/loops/integration.definition.ts b/integrations/loops/integration.definition.ts index 182d084cecb..5277b23678b 100644 --- a/integrations/loops/integration.definition.ts +++ b/integrations/loops/integration.definition.ts @@ -5,7 +5,7 @@ export default new IntegrationDefinition({ name: 'loops', title: 'Loops', description: 'Handle transactional emails from your chatbot.', - version: '0.1.2', + version: '0.1.3', readme: 'hub.md', icon: 'icon.svg', configuration, diff --git a/integrations/mailchimp/integration.definition.ts b/integrations/mailchimp/integration.definition.ts index a9d9fa585d4..92232ce93ae 100644 --- a/integrations/mailchimp/integration.definition.ts +++ b/integrations/mailchimp/integration.definition.ts @@ -16,7 +16,7 @@ const INTEGRATION_NAME = 'mailchimp' export default new IntegrationDefinition({ name: INTEGRATION_NAME, title: 'Mailchimp', - version: '0.3.7', + version: '0.3.9', readme: 'hub.md', icon: 'icon.svg', description: 'Send mass email campaigns from within your workflows. Manage customers, campaigns, lists and more.', diff --git a/integrations/mailchimp/src/misc/custom-schemas.ts b/integrations/mailchimp/src/misc/custom-schemas.ts index 431924cf3a3..533af71a3e4 100644 --- a/integrations/mailchimp/src/misc/custom-schemas.ts +++ b/integrations/mailchimp/src/misc/custom-schemas.ts @@ -143,29 +143,33 @@ export const getAllListsInputSchema = z.object({ export const getAllCampaignsInputSchema = getAllListsInputSchema.describe('List count to retrieve').title('Lists') const campaignSchema = z.object({ - id: z.string(), - web_id: z.number(), - parent_campaign_id: z.string().optional(), - type: z.string(), - create_time: z.string(), - archive_url: z.string(), - long_archive_url: z.string(), - status: z.string(), - emails_sent: z.number(), - send_time: z.string(), - content_type: z.string(), - needs_block_refresh: z.boolean(), - resendable: z.boolean(), - recipients: recipientsSchema.optional(), - settings: settingsSchema, - variate_settings: variateSettingsSchema.optional(), - tracking: trackingSchema, - rss_opts: rssOptsSchema.optional(), - ab_split_opts: abSplitOptsSchema.optional(), - social_card: socialCardSchema.optional(), - report_summary: reportSummarySchema.optional(), - delivery_status: deliveryStatusSchema, - _links: z.array(linkSchema), + id: z.string().title('ID').describe('Campaign ID'), + web_id: z.number().title('Web ID').describe('Campaign web ID'), + parent_campaign_id: z + .string() + .optional() + .title('Parent Campaign ID') + .describe('Parent campaign ID if this is a child campaign'), + type: z.string().title('Type').describe('Campaign type'), + create_time: z.string().title('Create Time').describe('Campaign creation time'), + archive_url: z.string().title('Archive URL').describe('URL to the campaign archive'), + long_archive_url: z.string().title('Long Archive URL').describe('Long URL to the campaign archive'), + status: z.string().title('Status').describe('Campaign status'), + emails_sent: z.number().title('Emails Sent').describe('Number of emails sent'), + send_time: z.string().title('Send Time').describe('Time when the campaign was sent'), + content_type: z.string().title('Content Type').describe('Campaign content type'), + needs_block_refresh: z.boolean().title('Needs Block Refresh').describe('Whether the campaign needs block refresh'), + resendable: z.boolean().title('Resendable').describe('Whether the campaign can be resent'), + recipients: recipientsSchema.optional().title('Recipients').describe('Campaign recipients'), + settings: settingsSchema.title('Settings').describe('Campaign settings'), + variate_settings: variateSettingsSchema.optional().title('Variate Settings').describe('A/B testing settings'), + tracking: trackingSchema.title('Tracking').describe('Campaign tracking settings'), + rss_opts: rssOptsSchema.optional().title('RSS Options').describe('RSS campaign options'), + ab_split_opts: abSplitOptsSchema.optional().title('AB Split Options').describe('A/B split test options'), + social_card: socialCardSchema.optional().title('Social Card').describe('Social media card settings'), + report_summary: reportSummarySchema.optional().title('Report Summary').describe('Campaign report summary'), + delivery_status: deliveryStatusSchema.title('Delivery Status').describe('Campaign delivery status'), + _links: z.array(linkSchema).title('Links').describe('Related links'), }) export const getAllCampaignsOutputSchema = z.object({ diff --git a/integrations/mailchimp/src/misc/sub-schemas.ts b/integrations/mailchimp/src/misc/sub-schemas.ts index b5b5a2d0fd8..e9e193767d3 100644 --- a/integrations/mailchimp/src/misc/sub-schemas.ts +++ b/integrations/mailchimp/src/misc/sub-schemas.ts @@ -11,11 +11,11 @@ const HttpMethodSchema = z.union([ ]) const linkSchema = z.object({ - rel: z.string().optional(), - href: z.string().optional(), - method: HttpMethodSchema.optional(), - targetSchema: z.string().optional(), - schema: z.string().optional(), + rel: z.string().optional().title('Rel').describe('Link relation type'), + href: z.string().optional().title('Href').describe('Link URL'), + method: HttpMethodSchema.optional().title('Method').describe('HTTP method'), + targetSchema: z.string().optional().title('Target Schema').describe('Target schema URL'), + schema: z.string().optional().title('Schema').describe('Schema URL'), }) const tagsSchema = z.object({ @@ -110,28 +110,31 @@ const statsSchema = z.object({ }) const listSchema = z.object({ - id: z.string(), - web_id: z.number(), - name: z.string(), - contact: contactSchema, - permission_reminder: z.string(), - use_archive_bar: z.boolean(), - campaign_defaults: campaignDefaultsSchema, - notify_on_subscribe: z.string(), - notify_on_unsubscribe: z.string(), - date_created: z.string(), - list_rating: z.number(), - email_type_option: z.boolean(), - subscribe_url_short: z.string(), - subscribe_url_long: z.string(), - beamer_address: z.string(), - visibility: z.string(), - double_optin: z.boolean(), - has_welcome: z.boolean(), - marketing_permissions: z.boolean(), - modules: z.array(z.any()), - stats: statsSchema, - _links: z.array(linkSchema), + id: z.string().title('ID').describe('List ID'), + web_id: z.number().title('Web ID').describe('List web ID'), + name: z.string().title('Name').describe('List name'), + contact: contactSchema.title('Contact').describe('Contact information for the list'), + permission_reminder: z.string().title('Permission Reminder').describe('Permission reminder message'), + use_archive_bar: z.boolean().title('Use Archive Bar').describe('Whether to use the archive bar'), + campaign_defaults: campaignDefaultsSchema.title('Campaign Defaults').describe('Default campaign settings'), + notify_on_subscribe: z.string().title('Notify on Subscribe').describe('Email to notify on subscription'), + notify_on_unsubscribe: z.string().title('Notify on Unsubscribe').describe('Email to notify on unsubscription'), + date_created: z.string().title('Date Created').describe('Date when the list was created'), + list_rating: z.number().title('List Rating').describe('List quality rating'), + email_type_option: z.boolean().title('Email Type Option').describe('Whether email type option is enabled'), + subscribe_url_short: z.string().title('Subscribe URL Short').describe('Short subscription URL'), + subscribe_url_long: z.string().title('Subscribe URL Long').describe('Long subscription URL'), + beamer_address: z.string().title('Beamer Address').describe('Beamer email address'), + visibility: z.string().title('Visibility').describe('List visibility setting'), + double_optin: z.boolean().title('Double Opt-in').describe('Whether double opt-in is required'), + has_welcome: z.boolean().title('Has Welcome').describe('Whether the list has a welcome email'), + marketing_permissions: z + .boolean() + .title('Marketing Permissions') + .describe('Whether marketing permissions are enabled'), + modules: z.array(z.any()).title('Modules').describe('List modules'), + stats: statsSchema.title('Stats').describe('List statistics'), + _links: z.array(linkSchema).title('Links').describe('Related links'), }) const constraintsSchema = z.object({ @@ -154,7 +157,9 @@ const recipientsSchema = z match: z.string().describe('Match condition'), conditions: z.array(z.unknown()).describe('Array of conditions'), // Adjust the type accordingly }) - .partial(), + .partial() + .title('Segment Options') + .describe('Segment options for targeting specific recipients'), }) .passthrough() .describe('Recipients information') @@ -239,22 +244,26 @@ const rssOptsSchema = z .object({ feed_url: z.string().describe('URL of the RSS feed'), frequency: z.string().describe('Frequency of sending (e.g., "daily")'), - schedule: z.object({ - hour: z.number().describe('Hour of the day for sending'), - daily_send: z - .object({ - sunday: z.boolean(), - monday: z.boolean(), - tuesday: z.boolean(), - wednesday: z.boolean(), - thursday: z.boolean(), - friday: z.boolean(), - saturday: z.boolean(), - }) - .describe('Daily send options'), - weekly_send_day: z.string().describe('Day of the week for weekly sending'), - monthly_send_date: z.number().describe('Date of the month for monthly sending'), - }), + schedule: z + .object({ + hour: z.number().describe('Hour of the day for sending'), + daily_send: z + .object({ + sunday: z.boolean().title('Sunday').describe('Send on Sunday'), + monday: z.boolean().title('Monday').describe('Send on Monday'), + tuesday: z.boolean().title('Tuesday').describe('Send on Tuesday'), + wednesday: z.boolean().title('Wednesday').describe('Send on Wednesday'), + thursday: z.boolean().title('Thursday').describe('Send on Thursday'), + friday: z.boolean().title('Friday').describe('Send on Friday'), + saturday: z.boolean().title('Saturday').describe('Send on Saturday'), + }) + .title('Daily Send') + .describe('Daily send options'), + weekly_send_day: z.string().describe('Day of the week for weekly sending'), + monthly_send_date: z.number().describe('Date of the month for monthly sending'), + }) + .title('Schedule') + .describe('RSS feed schedule'), last_sent: z.string().describe('Last time the RSS feed was sent'), constrain_rss_img: z.boolean().describe('Indicates whether to constrain RSS images'), }) @@ -293,11 +302,14 @@ const reportSummarySchema = z clicks: z.number().describe('Total clicks'), subscriber_clicks: z.number().describe('Subscriber clicks'), click_rate: z.number().describe('Click rate'), - ecommerce: z.object({ - total_orders: z.number().describe('Total ecommerce orders'), - total_spent: z.number().describe('Total amount spent in ecommerce'), - total_revenue: z.number().describe('Total ecommerce revenue'), - }), + ecommerce: z + .object({ + total_orders: z.number().describe('Total ecommerce orders'), + total_spent: z.number().describe('Total amount spent in ecommerce'), + total_revenue: z.number().describe('Total ecommerce revenue'), + }) + .title('Ecommerce') + .describe('Ecommerce data for the campaign'), }) .passthrough() @@ -309,7 +321,7 @@ const deliveryStatusSchema = z.union([ emails_sent: z.number().describe('Total emails sent'), emails_canceled: z.number().describe('Total emails canceled'), }), - z.object({ enabled: z.literal(false) }), + z.object({ enabled: z.literal(false).describe('Delivery status tracking is disabled') }), ]) export { diff --git a/integrations/notion/definitions/events.ts b/integrations/notion/definitions/events.ts index c37230aa399..38fa1228462 100644 --- a/integrations/notion/definitions/events.ts +++ b/integrations/notion/definitions/events.ts @@ -4,8 +4,8 @@ export const BASE_EVENT_PAYLOAD = sdk.z.object({ workspace_id: sdk.z.string().min(1), type: sdk.z.string().min(1), entity: sdk.z.object({ - type: sdk.z.enum(['page', 'block', 'database', 'comment']), - id: sdk.z.string().min(1), + type: sdk.z.enum(['page', 'block', 'database', 'comment']).title('Type').describe('The type of entity'), + id: sdk.z.string().min(1).title('ID').describe('The ID of the entity'), }), data: sdk.z.object({}).passthrough(), }) @@ -18,7 +18,7 @@ export const events = { type: sdk.z.literal('comment.created').title('Type').describe('The type of event'), entity: BASE_EVENT_PAYLOAD.shape.entity .extend({ - type: sdk.z.literal('comment'), + type: sdk.z.literal('comment').title('Type').describe('The type of entity (comment)'), }) .title('Entity') .describe('The entity that the event is related to'), diff --git a/integrations/notion/integration.definition.ts b/integrations/notion/integration.definition.ts index e6a688d84c7..a98dd2a0d35 100644 --- a/integrations/notion/integration.definition.ts +++ b/integrations/notion/integration.definition.ts @@ -3,7 +3,7 @@ import filesReadonly from './bp_modules/files-readonly' import { actions, configuration, configurations, events, identifier, secrets, states, user } from './definitions' export const INTEGRATION_NAME = 'notion' -export const INTEGRATION_VERSION = '3.0.0' +export const INTEGRATION_VERSION = '3.0.1' export default new sdk.IntegrationDefinition({ name: INTEGRATION_NAME, diff --git a/integrations/resend/integration.definition.ts b/integrations/resend/integration.definition.ts index 80384691003..b32fcbf69e6 100644 --- a/integrations/resend/integration.definition.ts +++ b/integrations/resend/integration.definition.ts @@ -14,7 +14,7 @@ import { export default new IntegrationDefinition({ name: 'resend', title: 'Resend', - version: '0.1.7', + version: '0.1.8', readme: 'hub.md', icon: 'icon.svg', description: 'Send markdown rich-text emails using the Resend email service.', diff --git a/integrations/resend/src/webhook-events/schemas/email.ts b/integrations/resend/src/webhook-events/schemas/email.ts index 899996144ea..096a7cabab7 100644 --- a/integrations/resend/src/webhook-events/schemas/email.ts +++ b/integrations/resend/src/webhook-events/schemas/email.ts @@ -13,13 +13,13 @@ import { z } from '@botpress/sdk' // - "email.failed" export const emailHeaderSchema = z.object({ - name: z.string(), - value: z.string(), + name: z.string().title('Name').describe('The name of the header'), + value: z.string().title('Value').describe('The value of the header'), }) export const emailTagSchema = z.object({ - name: z.string(), - value: z.string(), + name: z.string().title('Name').describe('The name of the tag'), + value: z.string().title('Value').describe('The value of the tag'), }) // Check if "cc" & "bcc" are included in the "to" field (It's included in an optional "headers" field) diff --git a/integrations/tally/definitions/schemas/tally-fields.ts b/integrations/tally/definitions/schemas/tally-fields.ts index 816ea0d001c..f1ff3a30406 100644 --- a/integrations/tally/definitions/schemas/tally-fields.ts +++ b/integrations/tally/definitions/schemas/tally-fields.ts @@ -2,70 +2,72 @@ import { z } from '@botpress/sdk' const baseField = z .object({ - key: z.string().min(1), - label: z.string().nullable().optional(), - type: z.string().min(1), + key: z.string().min(1).title('Key').describe('Field key identifier'), + label: z.string().nullable().optional().title('Label').describe('Field label'), + type: z.string().min(1).title('Type').describe('Field type'), }) .passthrough() const optionSchema = z .object({ - id: z.string().min(1), - text: z.string().nullable().optional(), + id: z.string().min(1).title('ID').describe('Option ID'), + text: z.string().nullable().optional().title('Text').describe('Option text'), }) .passthrough() const fileSchema = z .object({ - id: z.string().optional(), - name: z.string().nullable().optional(), - url: z.string().url().optional(), - mimeType: z.string().nullable().optional(), - size: z.number().optional(), + id: z.string().optional().title('ID').describe('File ID'), + name: z.string().nullable().optional().title('Name').describe('File name'), + url: z.string().url().optional().title('URL').describe('File URL'), + mimeType: z.string().nullable().optional().title('MIME Type').describe('File MIME type'), + size: z.number().optional().title('Size').describe('File size in bytes'), }) .passthrough() const optionsFieldBase = baseField.extend({ - value: z.array(z.string()).nullable().optional(), - options: z.array(optionSchema).optional(), + value: z.array(z.string()).nullable().optional().title('Value').describe('Selected option values'), + options: z.array(optionSchema).optional().title('Options').describe('Available options'), }) const multiSelectField = optionsFieldBase.extend({ - type: z.literal('MULTI_SELECT'), + type: z.literal('MULTI_SELECT').title('Type').describe('Field type'), }) const dropdownField = optionsFieldBase.extend({ - type: z.literal('DROPDOWN'), + type: z.literal('DROPDOWN').title('Type').describe('Field type'), }) const multipleChoiceField = optionsFieldBase.extend({ - type: z.literal('MULTIPLE_CHOICE'), + type: z.literal('MULTIPLE_CHOICE').title('Type').describe('Field type'), }) const rankingField = optionsFieldBase.extend({ - type: z.literal('RANKING'), + type: z.literal('RANKING').title('Type').describe('Field type'), }) const checkboxesField = baseField.extend({ - type: z.literal('CHECKBOXES'), + type: z.literal('CHECKBOXES').title('Type').describe('Field type'), value: z .union([z.array(z.string()), z.boolean()]) .nullable() - .optional(), - options: z.array(optionSchema).optional(), + .optional() + .title('Value') + .describe('Checkbox values'), + options: z.array(optionSchema).optional().title('Options').describe('Available checkbox options'), }) const fileUploadField = baseField.extend({ - type: z.literal('FILE_UPLOAD'), - value: z.array(fileSchema).nullable().optional(), + type: z.literal('FILE_UPLOAD').title('Type').describe('Field type'), + value: z.array(fileSchema).nullable().optional().title('Value').describe('Uploaded files'), }) const signatureField = baseField.extend({ - type: z.literal('SIGNATURE'), - value: z.array(fileSchema).nullable().optional(), + type: z.literal('SIGNATURE').title('Type').describe('Field type'), + value: z.array(fileSchema).nullable().optional().title('Value').describe('Signature files'), }) const matrixField = baseField.extend({ - type: z.literal('MATRIX'), - value: z.record(z.array(z.string())).nullable().optional(), - rows: z.array(optionSchema).optional(), - columns: z.array(optionSchema).optional(), + type: z.literal('MATRIX').title('Type').describe('Field type'), + value: z.record(z.array(z.string())).nullable().optional().title('Value').describe('Matrix values'), + rows: z.array(optionSchema).optional().title('Rows').describe('Matrix rows'), + columns: z.array(optionSchema).optional().title('Columns').describe('Matrix columns'), }) const knownSpecialFieldSchema = z.discriminatedUnion('type', [ @@ -81,8 +83,8 @@ const knownSpecialFieldSchema = z.discriminatedUnion('type', [ const fallbackFieldSchema = baseField .extend({ - value: z.any().optional(), - options: z.any().optional(), + value: z.any().optional().title('Value').describe('Field value'), + options: z.any().optional().title('Options').describe('Field options'), }) .passthrough() diff --git a/integrations/tally/definitions/schemas/tally-submissions.ts b/integrations/tally/definitions/schemas/tally-submissions.ts index 0eed95483ef..945f0c2daca 100644 --- a/integrations/tally/definitions/schemas/tally-submissions.ts +++ b/integrations/tally/definitions/schemas/tally-submissions.ts @@ -24,13 +24,16 @@ export const listSubmissionsOuputSchema = z.object({ .array( z.object({ id: z.string().describe('Submission ID').title('Submission ID'), - responses: z.array( - z.object({ - questionId: z.string().describe('Question ID').title('Question ID'), - value: z.any().optional().describe('Response value').title('Value'), - answer: z.any().optional().describe('Response answer').title('Answer'), - }) - ), + responses: z + .array( + z.object({ + questionId: z.string().describe('Question ID').title('Question ID'), + value: z.any().optional().describe('Response value').title('Value'), + answer: z.any().optional().describe('Response answer').title('Answer'), + }) + ) + .describe('List of responses for this submission') + .title('Responses'), }) ) .describe('List of submissions') diff --git a/integrations/tally/integration.definition.ts b/integrations/tally/integration.definition.ts index 4fbffae762d..711877f14c7 100644 --- a/integrations/tally/integration.definition.ts +++ b/integrations/tally/integration.definition.ts @@ -5,7 +5,7 @@ export default new IntegrationDefinition({ name: 'tally', title: 'Tally', description: 'Integrate with Tally forms to capture form submissions and automate workflows.', - version: '0.1.0', + version: '0.1.1', readme: 'hub.md', icon: 'icon.svg', configuration: { diff --git a/integrations/teams/definitions/states.ts b/integrations/teams/definitions/states.ts index 1ddbfa51763..c6e49f64b5a 100644 --- a/integrations/teams/definitions/states.ts +++ b/integrations/teams/definitions/states.ts @@ -6,8 +6,8 @@ type Is = A extends B ? (B extends A ? true : false) : false type Expect<_T extends true> = void export const channelAccountSchema = z.object({ - id: z.string(), - name: z.string(), + id: z.string().title('ID').describe('Account ID'), + name: z.string().title('Name').describe('Account name'), }) const _convReferenceSchema = z.object({ diff --git a/integrations/teams/integration.definition.ts b/integrations/teams/integration.definition.ts index 68d31233f5d..9bcc4416923 100644 --- a/integrations/teams/integration.definition.ts +++ b/integrations/teams/integration.definition.ts @@ -5,7 +5,7 @@ import { actions, channels, user, states } from 'definitions' export default new IntegrationDefinition({ name: 'teams', - version: '2.0.1', + version: '2.0.2', title: 'Microsoft Teams', description: 'Interact with users, deliver notifications, and perform actions within Microsoft Teams.', icon: 'icon.svg', diff --git a/integrations/webflow/definitions/actions.ts b/integrations/webflow/definitions/actions.ts index 0f363fa2369..fe451f58cfc 100644 --- a/integrations/webflow/definitions/actions.ts +++ b/integrations/webflow/definitions/actions.ts @@ -37,30 +37,33 @@ const collectionSchema = z.object({ }) const collectionDetailsSchema = collectionSchema.extend({ - fields: z.array( - z.object({ - id: z.string().describe('Unique identifier for a Field').title('Field ID'), - isRequired: z.boolean().describe('define whether a field is required in a collection').title('Is Required'), - type: fieldTypeSchema - .describe('Choose these appropriate field type for your collection data') - .title('Field Type'), - displayName: z.string().describe('The name of the Field').title('Field Name'), - isEditable: z.boolean().nullable().describe('Define whether the field is editable').title('Is Editable'), - slug: z - .string() - .nullable() - .describe( - 'Slug of Field in Site URL structure. Slugs should be all lowercase with no spaces. Any spaces will be converted to "-".' - ) - .title('Field Slug'), - helpText: z - .string() - .nullable() - .describe('Additional text to help anyone filling out this field') - .title('Field Help Text'), - validation: z.any().describe('The validation for the field').title('Field Validation'), - }) - ), + fields: z + .array( + z.object({ + id: z.string().describe('Unique identifier for a Field').title('Field ID'), + isRequired: z.boolean().describe('define whether a field is required in a collection').title('Is Required'), + type: fieldTypeSchema + .describe('Choose these appropriate field type for your collection data') + .title('Field Type'), + displayName: z.string().describe('The name of the Field').title('Field Name'), + isEditable: z.boolean().nullable().describe('Define whether the field is editable').title('Is Editable'), + slug: z + .string() + .nullable() + .describe( + 'Slug of Field in Site URL structure. Slugs should be all lowercase with no spaces. Any spaces will be converted to "-".' + ) + .title('Field Slug'), + helpText: z + .string() + .nullable() + .describe('Additional text to help anyone filling out this field') + .title('Field Help Text'), + validation: z.any().describe('The validation for the field').title('Field Validation'), + }) + ) + .title('Fields') + .describe('Array of fields in the collection'), }) const itemSchemaInput = z.object({ @@ -275,15 +278,18 @@ export const actions = { .title('Collection ID'), itemIDs: z .object({ - items: z.array( - z.object({ - id: z - .string() - .min(1, 'Item ID is required') - .describe('Unique identifier for the Item') - .title('Item ID'), - }) - ), + items: z + .array( + z.object({ + id: z + .string() + .min(1, 'Item ID is required') + .describe('Unique identifier for the Item') + .title('Item ID'), + }) + ) + .title('Items') + .describe('Array of items to delete'), }) .describe('Array of item IDs to delete') .title('Item IDs'), diff --git a/integrations/webflow/integration.definition.ts b/integrations/webflow/integration.definition.ts index 196a881889f..ee95db452a1 100644 --- a/integrations/webflow/integration.definition.ts +++ b/integrations/webflow/integration.definition.ts @@ -4,7 +4,7 @@ import { actions } from './definitions/actions' export default new IntegrationDefinition({ name: 'webflow', - version: '3.1.1', + version: '3.1.2', title: 'Webflow', description: 'CRUD operations for Webflow CMS', readme: 'hub.md', diff --git a/integrations/zapier/integration.definition.ts b/integrations/zapier/integration.definition.ts index c4457c05ff0..206d4030478 100644 --- a/integrations/zapier/integration.definition.ts +++ b/integrations/zapier/integration.definition.ts @@ -4,7 +4,7 @@ import { TriggerSchema, EventSchema, ZapierTriggersStateName, ZapierTriggersStat export default new IntegrationDefinition({ name: 'zapier', - version: '0.3.6', + version: '0.3.7', title: 'Zapier', description: "Trigger workflows from Zapier or let Zapier trigger your workflows to automate tasks and enhance your bot's capabilities.", diff --git a/integrations/zapier/src/types.ts b/integrations/zapier/src/types.ts index 4fdaf5e96ff..c4132ea710f 100644 --- a/integrations/zapier/src/types.ts +++ b/integrations/zapier/src/types.ts @@ -4,7 +4,7 @@ import * as bp from '.botpress' export type Client = bp.Client export const TriggerSubscriberSchema = z.object({ - url: z.string(), + url: z.string().title('URL').describe('The webhook URL of the subscriber'), }) export type TriggerSubscriber = z.infer diff --git a/integrations/zendesk/integration.definition.ts b/integrations/zendesk/integration.definition.ts index 2a7cef8f331..ef2ac880b96 100644 --- a/integrations/zendesk/integration.definition.ts +++ b/integrations/zendesk/integration.definition.ts @@ -6,7 +6,7 @@ import { actions, events, configuration, channels, states, user } from './src/de export default new sdk.IntegrationDefinition({ name: 'zendesk', title: 'Zendesk', - version: '3.0.6', + version: '3.0.7', icon: 'icon.svg', description: 'Optimize your support workflow. Trigger workflows from ticket updates as well as manage tickets, access conversations, and engage with customers.', diff --git a/integrations/zendesk/src/definitions/schemas.ts b/integrations/zendesk/src/definitions/schemas.ts index aeab084951a..78dd7bbf67b 100644 --- a/integrations/zendesk/src/definitions/schemas.ts +++ b/integrations/zendesk/src/definitions/schemas.ts @@ -2,25 +2,29 @@ import { z } from '@botpress/sdk' import { omit } from 'lodash' const requesterSchema = z.object({ - name: z.string().optional(), - email: z.string().optional(), + name: z.string().optional().title('Name').describe('Requester name'), + email: z.string().optional().title('Email').describe('Requester email'), }) export const ticketSchema = z.object({ - id: z.number(), - subject: z.string(), - description: z.string(), - status: z.enum(['new', 'open', 'pending', 'hold', 'solved', 'closed']), - priority: z.enum(['low', 'normal', 'high', 'urgent']).nullable(), - requesterId: z.number(), - requester: requesterSchema.optional(), - assigneeId: z.number().nullable(), - createdAt: z.string(), - updatedAt: z.string(), - tags: z.array(z.string()), - externalId: z.string().nullable(), - comment: z.record(z.any()).optional(), - via: z.object({ channel: z.string().optional() }).optional(), + id: z.number().title('ID').describe('Ticket ID'), + subject: z.string().title('Subject').describe('Ticket subject'), + description: z.string().title('Description').describe('Ticket description'), + status: z.enum(['new', 'open', 'pending', 'hold', 'solved', 'closed']).title('Status').describe('Ticket status'), + priority: z.enum(['low', 'normal', 'high', 'urgent']).nullable().title('Priority').describe('Ticket priority'), + requesterId: z.number().title('Requester ID').describe('ID of the requester'), + requester: requesterSchema.optional().title('Requester').describe('Requester information'), + assigneeId: z.number().nullable().title('Assignee ID').describe('ID of the assignee'), + createdAt: z.string().title('Created At').describe('Ticket creation date'), + updatedAt: z.string().title('Updated At').describe('Ticket last update date'), + tags: z.array(z.string()).title('Tags').describe('Ticket tags'), + externalId: z.string().nullable().title('External ID').describe('External ticket ID'), + comment: z.record(z.any()).optional().title('Comment').describe('Ticket comment'), + via: z + .object({ channel: z.string().optional().title('Channel').describe('Channel name') }) + .optional() + .title('Via') + .describe('How the ticket was created'), }) const _zdTicketSchema = ticketSchema.transform((data) => ({ @@ -47,18 +51,18 @@ export const transformTicket = (ticket: ZendeskTicket): Ticket => { } export const userSchema = z.object({ - id: z.number(), - name: z.string(), - email: z.string(), - phone: z.string().nullable().optional(), - photo: z.string().nullable().optional(), - remotePhotoUrl: z.string().nullable().optional(), - role: z.enum(['end-user', 'agent', 'admin']), - tags: z.array(z.string()), - createdAt: z.string(), - updatedAt: z.string(), - externalId: z.string().nullable(), - userFields: z.record(z.string()).optional(), + id: z.number().title('ID').describe('User ID'), + name: z.string().title('Name').describe('User name'), + email: z.string().title('Email').describe('User email'), + phone: z.string().nullable().optional().title('Phone').describe('User phone number'), + photo: z.string().nullable().optional().title('Photo').describe('User photo URL'), + remotePhotoUrl: z.string().nullable().optional().title('Remote Photo URL').describe('Remote photo URL'), + role: z.enum(['end-user', 'agent', 'admin']).title('Role').describe('User role'), + tags: z.array(z.string()).title('Tags').describe('User tags'), + createdAt: z.string().title('Created At').describe('User creation date'), + updatedAt: z.string().title('Updated At').describe('User last update date'), + externalId: z.string().nullable().title('External ID').describe('External user ID'), + userFields: z.record(z.string()).optional().title('User Fields').describe('Custom user fields'), }) const _zdUserSchema = userSchema.transform((data) => ({ diff --git a/packages/chat-api/src/version.ts b/packages/chat-api/src/version.ts index 6e013080919..97101a6d276 100644 --- a/packages/chat-api/src/version.ts +++ b/packages/chat-api/src/version.ts @@ -1 +1 @@ -export const apiVersion = '0.7.4' +export const apiVersion = '0.7.5'