diff --git a/.github/scripts/integration-exists.sh b/.github/scripts/integration-exists.sh index 8bd841fb518..ef93ab19092 100755 --- a/.github/scripts/integration-exists.sh +++ b/.github/scripts/integration-exists.sh @@ -6,7 +6,10 @@ fi integration=$1 integration_path="integrations/$integration" -integration_def=$(pnpm bp read --work-dir "$integration_path" --json) +if ! integration_def=$(pnpm bp read --work-dir "$integration_path" --json); then + echo "Error: Failed to read integration definition for \"$integration\". Check the integration for TypeScript errors." >&2 + exit 1 +fi name=$(echo "$integration_def" | jq -r ".name") version=$(echo "$integration_def" | jq -r ".version") diff --git a/.github/scripts/integration-has-valid-category.sh b/.github/scripts/integration-has-valid-category.sh new file mode 100755 index 00000000000..776b2760d12 --- /dev/null +++ b/.github/scripts/integration-has-valid-category.sh @@ -0,0 +1,45 @@ +#!/bin/bash +if [ -z "$1" ]; then + echo "Error: integration name is not provided" >&2 + exit 1 +fi +integration=$1 + +integration_path="integrations/$integration" +if ! integration_def=$(pnpm bp read --work-dir "$integration_path" --json); then + echo "Error: Failed to read integration definition for \"$integration\". Check the integration for TypeScript errors." >&2 + exit 1 +fi + +category=$(echo "$integration_def" | jq -r '.attributes.category // empty') + +valid_categories=( + "AI Models" + "Business Operations" + "CRM & Sales" + "Communication & Channels" + "Customer Support" + "Developer Tools" + "E-commerce & Payments" + "File Management" + "Marketing & Email" + "Other" + "Project Management" +) + +if [ -z "$category" ]; then + echo "Integration \"$integration\" is missing the \"category\" attribute in its definition file" >&2 + echo "Valid categories are: $(printf '"%s", ' "${valid_categories[@]}" | sed 's/, $//')" >&2 + exit 1 +fi + +for valid_category in "${valid_categories[@]}"; do + if [ "$category" = "$valid_category" ]; then + echo "Integration \"$integration\" has a valid category: \"$category\"" + exit 0 + fi +done + +echo "Integration \"$integration\" has an invalid category: \"$category\"" >&2 +echo "Valid categories are: $(printf '"%s", ' "${valid_categories[@]}" | sed 's/, $//')" >&2 +exit 1 diff --git a/.github/workflows/check-integration-categories.yml b/.github/workflows/check-integration-categories.yml new file mode 100644 index 00000000000..751aa7f13fa --- /dev/null +++ b/.github/workflows/check-integration-categories.yml @@ -0,0 +1,46 @@ +name: Check Integration Categories + +on: pull_request + +permissions: + id-token: write + contents: read + +jobs: + check-integration-categories: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v2 + - name: Setup + uses: ./.github/actions/setup + - name: Get changed files + id: changed-files + uses: tj-actions/changed-files@v46 + with: + files: 'integrations/**/*.{ts,md,svg,vrl}' + separator: '\n' + - name: Check integration categories + env: + CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }} + run: | + modified_integrations=$(echo -e "$CHANGED_FILES" | awk -F'/' '{print $2}' | sort -u) + + should_fail=0 + + for integration in $modified_integrations; do + if [ ! -d "integrations/$integration" ]; then + continue + fi + + echo "Checking $integration" + + if ! ./.github/scripts/integration-has-valid-category.sh "$integration"; then + should_fail=1 + fi + done + + if [ "$should_fail" -ne 0 ]; then + echo "Please add a valid category attribute to your integration definition before pushing your changes." + exit 1 + fi diff --git a/integrations/freshdesk/integration.definition.ts b/integrations/freshdesk/integration.definition.ts index e6eb846d90b..a10a99900dd 100644 --- a/integrations/freshdesk/integration.definition.ts +++ b/integrations/freshdesk/integration.definition.ts @@ -7,7 +7,7 @@ export default new IntegrationDefinition({ name: 'freshdesk', title: 'Freshdesk', description: 'Connect Botpress to Freshdesk to create, read, update, delete, and search support tickets.', - version: '0.1.0', + version: '0.1.1', readme: 'hub.md', icon: 'icon.svg', configuration, @@ -18,4 +18,8 @@ export default new IntegrationDefinition({ freshdeskRequesterId: { title: 'Freshdesk Requester ID', description: 'The ID of the requester in Freshdesk' }, }, }, + attributes: { + category: 'Customer Support', + repo: 'botpress', + }, }) diff --git a/integrations/grafana/integration.definition.ts b/integrations/grafana/integration.definition.ts index 367ec786b3f..ca5a3d678f9 100644 --- a/integrations/grafana/integration.definition.ts +++ b/integrations/grafana/integration.definition.ts @@ -3,7 +3,7 @@ import { configuration, states, events, actions } from './definitions' export default new IntegrationDefinition({ name: 'grafana', - version: '0.1.0', + version: '0.1.1', title: 'Grafana', description: 'Interact with Grafana dashboards, alerts, folders, datasources, and notification policies', readme: 'hub.md', @@ -12,4 +12,8 @@ export default new IntegrationDefinition({ states, events, actions, + attributes: { + category: 'Developer Tools', + repo: 'botpress', + }, }) diff --git a/integrations/kommo/integration.definition.ts b/integrations/kommo/integration.definition.ts index 3762abb4ea1..6ac01297b6e 100644 --- a/integrations/kommo/integration.definition.ts +++ b/integrations/kommo/integration.definition.ts @@ -5,7 +5,7 @@ export default new IntegrationDefinition({ name: 'kommo', title: 'Kommo', description: 'Manage leads and contacts in your Kommo CRM directly from your chatbot.', - version: '0.1.0', + version: '0.1.1', readme: 'hub.md', icon: 'icon.svg', configuration: { @@ -18,4 +18,8 @@ export default new IntegrationDefinition({ }), }, actions, + attributes: { + category: 'CRM & Sales', + repo: 'botpress', + }, }) diff --git a/integrations/postmark/integration.definition.ts b/integrations/postmark/integration.definition.ts index b694b853eee..284c8dff5ae 100644 --- a/integrations/postmark/integration.definition.ts +++ b/integrations/postmark/integration.definition.ts @@ -20,7 +20,7 @@ export default new sdk.IntegrationDefinition({ name: 'postmark', title: 'Postmark', description: 'Send and receive emails through Postmark', - version: '0.1.0', + version: '0.1.1', readme: 'hub.md', icon: 'icon.svg', configuration: { @@ -196,6 +196,10 @@ export default new sdk.IntegrationDefinition({ schema: sdk.z.object({}), }, }, + attributes: { + category: 'Communication & Channels', + repo: 'botpress', + }, }) .extend(proactiveConversation, ({ entities }) => ({ entities: { conversation: entities.conversation }, diff --git a/integrations/zoom/integration.definition.ts b/integrations/zoom/integration.definition.ts index 0ea6bb61fee..5a8da951241 100644 --- a/integrations/zoom/integration.definition.ts +++ b/integrations/zoom/integration.definition.ts @@ -2,7 +2,7 @@ import { z, IntegrationDefinition } from '@botpress/sdk' export default new IntegrationDefinition({ name: 'zoom', - version: '0.1.0', + version: '0.1.1', title: 'Zoom', description: 'Receives Zoom webhook and processes transcript for meetings.', icon: 'icon.svg', @@ -42,4 +42,8 @@ export default new IntegrationDefinition({ }), }, }, + attributes: { + category: 'Communication & Channels', + repo: 'botpress', + }, }) diff --git a/packages/zai/e2e/micropatch.test.ts b/packages/zai/e2e/micropatch.test.ts index 7d9395274b2..61a05d41e24 100644 --- a/packages/zai/e2e/micropatch.test.ts +++ b/packages/zai/e2e/micropatch.test.ts @@ -425,8 +425,25 @@ line2 expect(result).toMatchInlineSnapshot(` "line1 REPLACED + + line3 " +`) + }) + + test('two subsequent replace ops', () => { + const source = 'line1\nline2\nline3\nline4\nline5\n' + const ops = '◼︎=2|REPLACED\n\n◼︎=5|REPLACED2' + const result = Micropatch.applyText(source, ops) + expect(result).toMatchInlineSnapshot(` +"line1 +REPLACED + +line3 +line4 +REPLACED2 +" `) }) }) diff --git a/packages/zai/package.json b/packages/zai/package.json index a11845ab973..3ab536d919d 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.6.24", + "version": "2.7.0", "main": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { diff --git a/packages/zai/src/micropatch.ts b/packages/zai/src/micropatch.ts index f937fda0c70..2f101cc5b7f 100644 --- a/packages/zai/src/micropatch.ts +++ b/packages/zai/src/micropatch.ts @@ -194,7 +194,7 @@ export class Micropatch { let j = i + 1 while (j < lines.length) { const nextLine = lines[j] - if (!nextLine || nextLine.startsWith('◼︎')) break + if (nextLine.startsWith('◼︎')) break payload.push(Micropatch._unescapeMarker(nextLine)) j++ }