From ddaa8324e14241b035ea956b1bfbaf33c92340ea Mon Sep 17 00:00:00 2001 From: Sylvain Perron <1315508+slvnperron@users.noreply.github.com> Date: Fri, 7 Nov 2025 09:47:30 -0500 Subject: [PATCH 1/3] fix(zai): corner case with special char leftover (#14451) --- packages/zai/package.json | 2 +- packages/zai/src/operations/extract.ts | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/zai/package.json b/packages/zai/package.json index 0b53697c46e..84c70b9ea0f 100644 --- a/packages/zai/package.json +++ b/packages/zai/package.json @@ -1,7 +1,7 @@ { "name": "@botpress/zai", "description": "Zui AI (zai) – An LLM utility library written on top of Zui and the Botpress API", - "version": "2.4.0", + "version": "2.4.1", "main": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { diff --git a/packages/zai/src/operations/extract.ts b/packages/zai/src/operations/extract.ts index 10e465e1902..b07ada92289 100644 --- a/packages/zai/src/operations/extract.ts +++ b/packages/zai/src/operations/extract.ts @@ -45,7 +45,7 @@ declare module '@botpress/zai' { extract>(input: unknown, schema: S, options?: Options): Response } } - +const SPECIAL_CHAR = '■' const START = '■json_start■' const END = '■json_end■' const NO_MORE = '■NO_MORE_ELEMENT■' @@ -330,7 +330,12 @@ ${instructions.map((x) => `• ${x}`).join('\n')} .filter((x) => x.trim().length > 0 && x.includes('}')) .map((x) => { try { - const json = x.slice(0, x.indexOf(END)).trim() + let json = x.slice(0, x.indexOf(END)).trim() + + if (json.includes(SPECIAL_CHAR)) { + json = json.slice(0, json.indexOf(SPECIAL_CHAR)).trim() + } + const repairedJson = jsonrepair(json) const parsedJson = JSON5.parse(repairedJson) const safe = schema.safeParse(parsedJson) From 09990e093e779beae51e9610c9ef0c1fe15650f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Levasseur?= Date: Fri, 7 Nov 2025 10:16:49 -0500 Subject: [PATCH 2/3] chore: update codeowner file to include team leads --- CODEOWNERS | 112 ++++++++++++++++++++++++++--------------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 4ffdb2b92c0..ef6fc7f01e8 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -2,71 +2,71 @@ * @botpress/engineering # Client, SDK, CLI -/packages @botpress/squid +/packages @botpress/squid @botpress/leads # Bots -/packages/bots @botpress/squid +/packages/bots @botpress/squid @botpress/leads # Plugins -/plugins @botpress/squid -/plugins/hitl @pascal-botpress @franklevasseur @botpress/squid -/plugins/file-synchronizer @pascal-botpress @botpress/squid +/plugins @botpress/squid @botpress/leads +/plugins/hitl @pascal-botpress @franklevasseur @botpress/squid @botpress/leads +/plugins/file-synchronizer @pascal-botpress @botpress/squid @botpress/leads # Integrations -/integrations @botpress/squid +/integrations @botpress/squid @botpress/leads ## Utils -/integrations/browser @allardy @botpress/starfish -/integrations/charts @allardy @botpress/starfish -/integrations/pdf-generator @allardy @botpress/starfish +/integrations/browser @allardy @botpress/starfish @botpress/leads +/integrations/charts @allardy @botpress/starfish @botpress/leads +/integrations/pdf-generator @allardy @botpress/starfish @botpress/leads ## LLM -/integrations/anthropic @AbrahamLopez10 @botpress/shark -/integrations/cerebras @AbrahamLopez10 @botpress/shark -/integrations/fireworks-ai @AbrahamLopez10 @botpress/shark -/integrations/google-ai @AbrahamLopez10 @botpress/shark -/integrations/groq @AbrahamLopez10 @botpress/shark -/integrations/openai @AbrahamLopez10 @botpress/shark +/integrations/anthropic @botpress/shark @botpress/leads +/integrations/cerebras @botpress/shark @botpress/leads +/integrations/fireworks-ai @botpress/shark @botpress/leads +/integrations/google-ai @botpress/shark @botpress/leads +/integrations/groq @botpress/shark @botpress/leads +/integrations/openai @botpress/shark @botpress/leads ## Others -/integrations/airtable @botpress/squid -/integrations/asana @botpress/squid -/integrations/bigcommerce-sync @botpress/squid -/integrations/calendly @botpress/squid -/integrations/chat @botpress/squid -/integrations/clickup @botpress/squid -/integrations/confluence @botpress/squid -/integrations/dropbox @botpress/squid -/integrations/docusign @botpress/squid -/integrations/email @botpress/squid -/integrations/freshchat @botpress/squid -/integrations/github @botpress/squid -/integrations/gmail @botpress/squid -/integrations/googlecalendar @botpress/squid -/integrations/googledrive @botpress/squid -/integrations/gsheets @botpress/squid -/integrations/instagram @botpress/squid -/integrations/intercom @botpress/squid -/integrations/line @botpress/squid -/integrations/linear @botpress/squid -/integrations/mailchimp @botpress/squid -/integrations/messenger @botpress/squid -/integrations/monday @botpress/squid -/integrations/notion @botpress/squid -/integrations/resend @botpress/squid -/integrations/sendgrid @botpress/squid -/integrations/slack @botpress/squid -/integrations/stripe @botpress/squid -/integrations/sunco @botpress/squid -/integrations/teams @botpress/squid -/integrations/telegram @botpress/squid -/integrations/todoist @botpress/squid -/integrations/trello @botpress/squid -/integrations/twilio @botpress/squid -/integrations/viber @botpress/squid -/integrations/vonage @botpress/squid -/integrations/webhook @botpress/squid -/integrations/whatsapp @botpress/squid -/integrations/zapier @botpress/squid -/integrations/zendesk @botpress/squid -/integrations/zoho @botpress/squid +/integrations/airtable @botpress/squid @botpress/leads +/integrations/asana @botpress/squid @botpress/leads +/integrations/bigcommerce-sync @botpress/squid @botpress/leads +/integrations/calendly @botpress/squid @botpress/leads +/integrations/chat @botpress/squid @botpress/leads +/integrations/clickup @botpress/squid @botpress/leads +/integrations/confluence @botpress/squid @botpress/leads +/integrations/dropbox @botpress/squid @botpress/leads +/integrations/docusign @botpress/squid @botpress/leads +/integrations/email @botpress/squid @botpress/leads +/integrations/freshchat @botpress/squid @botpress/leads +/integrations/github @botpress/squid @botpress/leads +/integrations/gmail @botpress/squid @botpress/leads +/integrations/googlecalendar @botpress/squid @botpress/leads +/integrations/googledrive @botpress/squid @botpress/leads +/integrations/gsheets @botpress/squid @botpress/leads +/integrations/instagram @botpress/squid @botpress/leads +/integrations/intercom @botpress/squid @botpress/leads +/integrations/line @botpress/squid @botpress/leads +/integrations/linear @botpress/squid @botpress/leads +/integrations/mailchimp @botpress/squid @botpress/leads +/integrations/messenger @botpress/squid @botpress/leads +/integrations/monday @botpress/squid @botpress/leads +/integrations/notion @botpress/squid @botpress/leads +/integrations/resend @botpress/squid @botpress/leads +/integrations/sendgrid @botpress/squid @botpress/leads +/integrations/slack @botpress/squid @botpress/leads +/integrations/stripe @botpress/squid @botpress/leads +/integrations/sunco @botpress/squid @botpress/leads +/integrations/teams @botpress/squid @botpress/leads +/integrations/telegram @botpress/squid @botpress/leads +/integrations/todoist @botpress/squid @botpress/leads +/integrations/trello @botpress/squid @botpress/leads +/integrations/twilio @botpress/squid @botpress/leads +/integrations/viber @botpress/squid @botpress/leads +/integrations/vonage @botpress/squid @botpress/leads +/integrations/webhook @botpress/squid @botpress/leads +/integrations/whatsapp @botpress/squid @botpress/leads +/integrations/zapier @botpress/squid @botpress/leads +/integrations/zendesk @botpress/squid @botpress/leads +/integrations/zoho @botpress/squid @botpress/leads From 41bfbf2ebb1b5614031476afe5bed106702e41d4 Mon Sep 17 00:00:00 2001 From: Mathieu Faucher <99497774+Math-Fauch@users.noreply.github.com> Date: Fri, 7 Nov 2025 11:05:51 -0500 Subject: [PATCH 3/3] feat(integrations/slack): Add start channel conversation (#14449) --- integrations/slack/definitions/actions.ts | 18 +++++++++++++++ integrations/slack/integration.definition.ts | 2 +- integrations/slack/src/actions/index.ts | 2 ++ .../src/actions/start-channel-conversation.ts | 23 +++++++++++++++++++ .../slack/src/slack-api/slack-client.ts | 22 ++++++++++++++++++ 5 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 integrations/slack/src/actions/start-channel-conversation.ts diff --git a/integrations/slack/definitions/actions.ts b/integrations/slack/definitions/actions.ts index 8e304cff0b7..efbf7b0ce04 100644 --- a/integrations/slack/definitions/actions.ts +++ b/integrations/slack/definitions/actions.ts @@ -95,6 +95,24 @@ export const actions = { }, }, + startChannelConversation: { + title: 'Start Channel Conversation', + description: 'Initiate a conversation in a channel', + input: { + schema: sdk.z.object({ + channelName: sdk.z + .string() + .title('Channel Name') + .describe('The name of the channel you want the conversation to be created at'), + }), + }, + output: { + schema: sdk.z.object({ + conversationId: sdk.z.string().title('Conversation ID').describe('The ID of the new conversation'), + }), + }, + }, + startDmConversation: { title: 'Start DM Conversation', description: 'Initiate a conversation with a user in a DM', diff --git a/integrations/slack/integration.definition.ts b/integrations/slack/integration.definition.ts index 8e270c72be4..4bf25c3f152 100644 --- a/integrations/slack/integration.definition.ts +++ b/integrations/slack/integration.definition.ts @@ -17,7 +17,7 @@ export default new IntegrationDefinition({ name: 'slack', title: 'Slack', description: 'Automate interactions with your team.', - version: '3.0.0', + version: '3.1.0', icon: 'icon.svg', readme: 'hub.md', configuration, diff --git a/integrations/slack/src/actions/index.ts b/integrations/slack/src/actions/index.ts index f669dbd2ecc..d8e7067af99 100644 --- a/integrations/slack/src/actions/index.ts +++ b/integrations/slack/src/actions/index.ts @@ -2,6 +2,7 @@ import { addReaction } from './add-reaction' import { findTarget } from './find-target' import { getUserProfile } from './get-user-profile' import { retrieveMessage } from './retrieve-message' +import { startChannelConversation } from './start-channel-conversation' import { startDmConversation } from './start-dm' import { syncMembers } from './sync-members' import { startTypingIndicator, stopTypingIndicator } from './typing-indicator' @@ -14,6 +15,7 @@ export default { retrieveMessage, syncMembers, startDmConversation, + startChannelConversation, updateChannelTopic, startTypingIndicator, stopTypingIndicator, diff --git a/integrations/slack/src/actions/start-channel-conversation.ts b/integrations/slack/src/actions/start-channel-conversation.ts new file mode 100644 index 00000000000..fd1f5fe991e --- /dev/null +++ b/integrations/slack/src/actions/start-channel-conversation.ts @@ -0,0 +1,23 @@ +import { RuntimeError } from '@botpress/client' +import { wrapActionAndInjectSlackClient } from 'src/actions/action-wrapper' + +export const startChannelConversation = wrapActionAndInjectSlackClient( + { actionName: 'startChannelConversation', errorMessage: 'Failed to start Channel conversation' }, + async ({ client, logger, slackClient }, { channelName }) => { + const slackChannelInfo = await slackClient.getChannelInfo({ channelName }) + if (slackChannelInfo === undefined) { + const errorMessage = 'The channel id provided does not exist' + logger.forBot().error(errorMessage) + throw new RuntimeError(errorMessage) + } + + const { conversation } = await client.getOrCreateConversation({ + channel: 'channel', + tags: { id: slackChannelInfo?.id }, + }) + + return { + conversationId: conversation.id, + } + } +) diff --git a/integrations/slack/src/slack-api/slack-client.ts b/integrations/slack/src/slack-api/slack-client.ts index c235fe607a2..7c2445b8673 100644 --- a/integrations/slack/src/slack-api/slack-client.ts +++ b/integrations/slack/src/slack-api/slack-client.ts @@ -322,6 +322,28 @@ export class SlackClient { return response.profile } + @requireAllScopes(['channels:read', 'chat:write']) + @handleErrors('Failed to retrieve user profile') + public async getChannelInfo({ channelName }: { channelName: string }) { + const allChannels: SlackWebApi.ConversationsListResponse['channels'] = [] + for await (const page of this._slackWebClient.paginate('conversations.list', { + types: 'public_channel', + exclude_archived: true, + limit: 200, + }) as AsyncIterable) { + if (page.channels) { + allChannels.push(...page.channels) + } + } + for (const channel of allChannels) { + if (channel.name === channelName) { + return channel + } + } + + return undefined + } + private _surfaceSlackErrors(response: TResponse): TResponse { if (response.response_metadata?.warnings?.length) { this._logger.forBot().warn('Slack API emitted warnings', response.response_metadata.warnings)