@botonic/nx-plugin 2.29.0 → 2.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/package.json +3 -2
- package/src/executors/deploy-local-runtime/executor.js +10 -6
- package/src/generators/bot-app/files/src/client/webchat/index.tsx.template +2 -0
- package/src/generators/bot-app/files/src/client/webchat/webchat.tsx.template +111 -0
- package/src/generators/bot-app/files/src/server/bot/plugins/flow-builder/index.ts.template +13 -4
- package/src/generators/bot-app/files/src/server/bot/plugins/index.ts.template +0 -3
- package/src/generators/bot-app/files/src/server/lambda/handler.js.template +1 -1
- package/src/generators/bot-app/files/src/server/lambda/package.json +3 -3
- package/src/generators/bot-app/files/vite/botonic-ssr-deps.ts.template +56 -0
- package/src/generators/bot-app/files/vite/node.config.ts.template +7 -4
- package/src/generators/bot-app/files/vite/webchat.config.ts.template +20 -1
- package/src/generators/bot-app/generator.js +6 -5
- package/src/generators/bot-app/lilara-version.json +1 -1
- package/src/lib/bot-config.d.ts +10 -7
- package/src/lib/bot-config.js +5 -1
- package/src/lib/util/executor-helpers.d.ts +11 -0
- package/src/lib/util/executor-helpers.js +17 -6
- package/src/plugin.js +1 -1
- package/src/generators/bot-app/files/src/server/bot/tracking.ts.template +0 -35
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
## 2.30.0 (2026-06-11)
|
|
2
|
+
|
|
3
|
+
### 🚀 Features
|
|
4
|
+
|
|
5
|
+
- update botonic-basic-template ([#932](https://github.com/metis-ai/hubtype-product/pull/932))
|
|
6
|
+
- update plugins to last botonicV0 changes #BLT-2370 ([#920](https://github.com/metis-ai/hubtype-product/pull/920))
|
|
7
|
+
- **@botonic/dx-bundling:** derive Lambda noExternal deps programmatically ([#918](https://github.com/metis-ai/hubtype-product/pull/918))
|
|
8
|
+
- support botonic v2 preview in flow builder ([#916](https://github.com/metis-ai/hubtype-product/pull/916))
|
|
9
|
+
- wire plugin-hubtype-analytics into bot apps ([#909](https://github.com/metis-ai/hubtype-product/pull/909))
|
|
10
|
+
|
|
11
|
+
### 🩹 Fixes
|
|
12
|
+
|
|
13
|
+
- allow multiple, only picking webchat app id ([#896](https://github.com/metis-ai/hubtype-product/pull/896))
|
|
14
|
+
|
|
15
|
+
### ❤️ Thank You
|
|
16
|
+
|
|
17
|
+
- Marc Rabat @vanbasten17
|
|
18
|
+
- Oriol Raventós @Iru89
|
|
19
|
+
|
|
1
20
|
## 2.29.0 (2026-05-12)
|
|
2
21
|
|
|
3
22
|
### 🚀 Features
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botonic/nx-plugin",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.30.0",
|
|
4
4
|
"description": "Nx plugin for creating Botonic bot applications",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"types": "./src/index.d.ts",
|
|
@@ -42,7 +42,8 @@
|
|
|
42
42
|
"fs-extra": "^11.1.1",
|
|
43
43
|
"qs": "^6.11.0",
|
|
44
44
|
"yaml": "^2.6.1",
|
|
45
|
-
"zip-a-folder": "^1.1.0"
|
|
45
|
+
"zip-a-folder": "^1.1.0",
|
|
46
|
+
"zod": "^4.4.3"
|
|
46
47
|
},
|
|
47
48
|
"peerDependencies": {
|
|
48
49
|
"nx": ">=21.0.0"
|
|
@@ -130,12 +130,16 @@ async function deployLocalRuntime(botonicApiService, projectRoot, params) {
|
|
|
130
130
|
lambdaEndpoint
|
|
131
131
|
});
|
|
132
132
|
const allProviders = await botonicApiService.getProviders();
|
|
133
|
-
const appId = allProviders.data
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
133
|
+
const appId = (0, import_executor_helpers.getActiveTestWebchatProviderAppId)(allProviders.data?.results);
|
|
134
|
+
if (!appId) {
|
|
135
|
+
console.error(
|
|
136
|
+
"\u274C No active test webchat provider found. Local runtime needs a webchat test provider on this bot."
|
|
137
|
+
);
|
|
138
|
+
} else {
|
|
139
|
+
console.log("\u2705 Local runtime deployment completed!");
|
|
140
|
+
updateEnvLocal(projectRoot, appId);
|
|
141
|
+
console.log(`\u{1F194} APP_ID: ${appId}`);
|
|
142
|
+
}
|
|
139
143
|
} catch (error) {
|
|
140
144
|
console.error("\u274C Local runtime deployment failed");
|
|
141
145
|
console.error(`${String(error)}`);
|
|
@@ -66,8 +66,10 @@ function App({
|
|
|
66
66
|
<WebchatTrigger
|
|
67
67
|
appId={webchatConfig.appId}
|
|
68
68
|
position='bottom-right'
|
|
69
|
+
loader={() => import('./webchat')}
|
|
69
70
|
onReady={handleReady}
|
|
70
71
|
webchatConfig={{
|
|
72
|
+
...webchatConfig,
|
|
71
73
|
avatarConfig,
|
|
72
74
|
customMessages,
|
|
73
75
|
title: options.title || '<%= className %>',
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { WebchatController } from '@botonic/webchat-core'
|
|
2
|
+
import type {
|
|
3
|
+
WebchatCompositionExtras,
|
|
4
|
+
WebchatCompositionProps,
|
|
5
|
+
} from '@botonic/webchat-react'
|
|
6
|
+
import {
|
|
7
|
+
useWebchatContext,
|
|
8
|
+
WebchatContainer,
|
|
9
|
+
WebchatHeader,
|
|
10
|
+
WebchatInput,
|
|
11
|
+
WebchatMessages,
|
|
12
|
+
WebchatProvider,
|
|
13
|
+
} from '@botonic/webchat-react'
|
|
14
|
+
import { useEffect, useRef } from 'react'
|
|
15
|
+
|
|
16
|
+
function WebchatContent({
|
|
17
|
+
isOpen,
|
|
18
|
+
onClose,
|
|
19
|
+
onControllerReady,
|
|
20
|
+
title,
|
|
21
|
+
placeholder,
|
|
22
|
+
showBranding,
|
|
23
|
+
}: {
|
|
24
|
+
isOpen: boolean
|
|
25
|
+
onClose: () => void
|
|
26
|
+
onControllerReady: (controller: WebchatController) => void
|
|
27
|
+
title?: string
|
|
28
|
+
placeholder?: string
|
|
29
|
+
showBranding?: boolean
|
|
30
|
+
}) {
|
|
31
|
+
const { controller } = useWebchatContext()
|
|
32
|
+
const hasNotifiedRef = useRef(false)
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
if (controller && !hasNotifiedRef.current) {
|
|
36
|
+
hasNotifiedRef.current = true
|
|
37
|
+
onControllerReady(controller)
|
|
38
|
+
}
|
|
39
|
+
}, [controller, onControllerReady])
|
|
40
|
+
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (!controller) return
|
|
43
|
+
const snapshot = controller.machine.getSnapshot()
|
|
44
|
+
const currentIsOpen = snapshot.context.isOpen ?? false
|
|
45
|
+
if (isOpen && !currentIsOpen) {
|
|
46
|
+
controller.open()
|
|
47
|
+
} else if (!isOpen && currentIsOpen) {
|
|
48
|
+
controller.close()
|
|
49
|
+
}
|
|
50
|
+
}, [isOpen, controller])
|
|
51
|
+
|
|
52
|
+
const handleClose = () => {
|
|
53
|
+
controller?.close()
|
|
54
|
+
onClose()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<WebchatContainer layout='default'>
|
|
59
|
+
<WebchatHeader title={title} onClose={handleClose} />
|
|
60
|
+
<WebchatMessages variant='default' />
|
|
61
|
+
<WebchatInput
|
|
62
|
+
placeholder={placeholder}
|
|
63
|
+
showBranding={showBranding ?? true}
|
|
64
|
+
variant='default'
|
|
65
|
+
/>
|
|
66
|
+
</WebchatContainer>
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export default function Webchat({
|
|
71
|
+
appId,
|
|
72
|
+
isOpen,
|
|
73
|
+
onClose,
|
|
74
|
+
onControllerReady,
|
|
75
|
+
...extras
|
|
76
|
+
}: WebchatCompositionProps) {
|
|
77
|
+
// `WebchatCompositionProps` exposes extras via a `[key: string]: unknown`
|
|
78
|
+
// index signature, so assert the concrete shape once instead of per field.
|
|
79
|
+
const {
|
|
80
|
+
title,
|
|
81
|
+
placeholder,
|
|
82
|
+
showBranding,
|
|
83
|
+
customMessages = {},
|
|
84
|
+
avatarConfig,
|
|
85
|
+
webchatClientSettings,
|
|
86
|
+
enableResponsiveHeroHeader,
|
|
87
|
+
storage,
|
|
88
|
+
previewUtils,
|
|
89
|
+
} = extras as WebchatCompositionExtras
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<WebchatProvider
|
|
93
|
+
appId={appId}
|
|
94
|
+
customMessages={customMessages}
|
|
95
|
+
avatarConfig={avatarConfig}
|
|
96
|
+
webchatClientSettings={webchatClientSettings}
|
|
97
|
+
enableResponsiveHeroHeader={enableResponsiveHeroHeader}
|
|
98
|
+
storage={storage}
|
|
99
|
+
previewUtils={previewUtils}
|
|
100
|
+
>
|
|
101
|
+
<WebchatContent
|
|
102
|
+
isOpen={isOpen}
|
|
103
|
+
onClose={onClose}
|
|
104
|
+
onControllerReady={onControllerReady}
|
|
105
|
+
title={title}
|
|
106
|
+
placeholder={placeholder}
|
|
107
|
+
showBranding={showBranding}
|
|
108
|
+
/>
|
|
109
|
+
</WebchatProvider>
|
|
110
|
+
)
|
|
111
|
+
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
import { BotonicContext } from '@botonic/core'
|
|
1
2
|
import { AiAgentArgs } from '@botonic/plugin-ai-agents'
|
|
3
|
+
import { BotonicPluginHubtypeAnalytics } from '@botonic/plugin-hubtype-analytics'
|
|
2
4
|
import {
|
|
3
5
|
BotonicPluginFlowBuilder,
|
|
4
6
|
BotonicPluginFlowBuilderOptions,
|
|
5
7
|
FlowBuilderJSONVersion,
|
|
6
8
|
} from '@botonic/plugin-flow-builder'
|
|
7
|
-
import {
|
|
9
|
+
import { EventAction, HtEventProps } from '@botonic/shared'
|
|
8
10
|
|
|
9
|
-
import { trackEventToHubtypeAnalytics } from '../../tracking'
|
|
10
11
|
import { isLambdaLocal } from '../../utils'
|
|
11
12
|
import { getAiAgentResponse } from '../ai-agents'
|
|
12
13
|
|
|
@@ -14,8 +15,16 @@ export const flowBuilderConfig: BotonicPluginFlowBuilderOptions = {
|
|
|
14
15
|
flowVersion: isLambdaLocal()
|
|
15
16
|
? FlowBuilderJSONVersion.DRAFT
|
|
16
17
|
: FlowBuilderJSONVersion.LATEST,
|
|
17
|
-
trackEvent: async (
|
|
18
|
-
|
|
18
|
+
trackEvent: async (
|
|
19
|
+
context: BotonicContext,
|
|
20
|
+
eventAction: EventAction,
|
|
21
|
+
args: Omit<HtEventProps, 'action'>
|
|
22
|
+
): Promise<void> => {
|
|
23
|
+
const analyticsPlugin = new BotonicPluginHubtypeAnalytics()
|
|
24
|
+
await analyticsPlugin.trackEvent(context, {
|
|
25
|
+
action: eventAction,
|
|
26
|
+
...args,
|
|
27
|
+
} as HtEventProps)
|
|
19
28
|
},
|
|
20
29
|
getAiAgentResponse: async (
|
|
21
30
|
botonicContext: BotonicContext,
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { BotonicPluginHubtypeAnalytics } from '@botonic/plugin-hubtype-analytics'
|
|
2
|
-
|
|
3
1
|
import { aiAgentsPlugin } from './ai-agents'
|
|
4
2
|
import { flowBuilderPlugin } from './flow-builder'
|
|
5
3
|
|
|
@@ -7,5 +5,4 @@ export const plugins = {
|
|
|
7
5
|
flowBuilder: flowBuilderPlugin,
|
|
8
6
|
// AI Agents plugin is only loaded if AZURE_OPENAI_API_KEY or OPENAI_API_KEY is set
|
|
9
7
|
...(aiAgentsPlugin && { aiAgents: aiAgentsPlugin }),
|
|
10
|
-
hubtypeAnalytics: new BotonicPluginHubtypeAnalytics(),
|
|
11
8
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/*
|
|
4
4
|
In lambda functions, it only have access to all files the first time it's invoked,
|
|
5
5
|
and placed into memory, after that it only calls the function that have the information
|
|
6
|
-
|
|
6
|
+
loaded in memory. For this reason, we initialize the bot the first time, and then we
|
|
7
7
|
only execute the input function
|
|
8
8
|
|
|
9
9
|
https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { readFileSync, readdirSync } from 'fs'
|
|
2
|
+
import { resolve } from 'path'
|
|
3
|
+
|
|
4
|
+
// Build-only tools — never needed at Lambda runtime.
|
|
5
|
+
const BUILD_ONLY_DEPS = new Set(['tslib', 'vite', 'vitest'])
|
|
6
|
+
|
|
7
|
+
// Browser/UI-only packages pulled in by client-side @botonic/* packages
|
|
8
|
+
// (webchat-react, webchat-core). They are never imported by the server entry.
|
|
9
|
+
const BROWSER_ONLY_DEPS = new Set([
|
|
10
|
+
'react',
|
|
11
|
+
'react-dom',
|
|
12
|
+
'react-aria',
|
|
13
|
+
'@xstate/react',
|
|
14
|
+
'@lilara/foundations',
|
|
15
|
+
'@lilara/ui-web-react',
|
|
16
|
+
'class-variance-authority',
|
|
17
|
+
'react-markdown',
|
|
18
|
+
'rehype-external-links',
|
|
19
|
+
'remark-breaks',
|
|
20
|
+
'remark-gfm',
|
|
21
|
+
])
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Collects all third-party dependencies declared by the @botonic/* packages
|
|
25
|
+
* installed in this app's node_modules. The result is used in the Lambda node
|
|
26
|
+
* build's `ssr.noExternal` so that these packages are bundled into the artifact,
|
|
27
|
+
* where no node_modules are available at runtime.
|
|
28
|
+
*
|
|
29
|
+
* Deriving the list from the installed @botonic/* package.json files keeps it
|
|
30
|
+
* correct as plugins add new dependencies, instead of a hand-maintained array.
|
|
31
|
+
*/
|
|
32
|
+
export function getBotonicThirdPartyDeps(appRoot: string): string[] {
|
|
33
|
+
const botonicDir = resolve(appRoot, 'node_modules/@botonic')
|
|
34
|
+
const thirdParty = new Set<string>()
|
|
35
|
+
for (const name of readdirSync(botonicDir)) {
|
|
36
|
+
try {
|
|
37
|
+
const pkgPath = resolve(botonicDir, name, 'package.json')
|
|
38
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'))
|
|
39
|
+
for (const dep of Object.keys({
|
|
40
|
+
...pkg.dependencies,
|
|
41
|
+
...pkg.peerDependencies,
|
|
42
|
+
})) {
|
|
43
|
+
if (
|
|
44
|
+
!dep.startsWith('@botonic/') &&
|
|
45
|
+
!BUILD_ONLY_DEPS.has(dep) &&
|
|
46
|
+
!BROWSER_ONLY_DEPS.has(dep)
|
|
47
|
+
) {
|
|
48
|
+
thirdParty.add(dep)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
} catch {
|
|
52
|
+
// skip packages without a readable package.json
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return [...thirdParty]
|
|
56
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { resolve } from 'path'
|
|
2
2
|
import type { UserConfig } from 'vite'
|
|
3
3
|
|
|
4
|
+
import { getBotonicThirdPartyDeps } from './botonic-ssr-deps'
|
|
4
5
|
import { BUILD_CONFIG } from './build.config'
|
|
5
6
|
|
|
6
7
|
const projectRoot = resolve(__dirname, '..')
|
|
@@ -12,11 +13,13 @@ export function getNodeConfig(): UserConfig {
|
|
|
12
13
|
root: projectRoot,
|
|
13
14
|
cacheDir: resolve(projectRoot, BUILD_CONFIG.CACHE_DIR.node),
|
|
14
15
|
|
|
15
|
-
//
|
|
16
|
-
// By default
|
|
17
|
-
//
|
|
16
|
+
// Bundle all @botonic/* packages and their third-party deps into the Lambda
|
|
17
|
+
// artifact. By default Vite SSR externalizes node_modules, but Lambda has no
|
|
18
|
+
// node_modules at runtime so everything must be self-contained.
|
|
19
|
+
// Third-party deps are derived programmatically from the @botonic/* package.json
|
|
20
|
+
// files so this list stays correct as plugins add new dependencies.
|
|
18
21
|
ssr: {
|
|
19
|
-
noExternal: [/@botonic
|
|
22
|
+
noExternal: [/@botonic\/.*/, ...getBotonicThirdPartyDeps(projectRoot)],
|
|
20
23
|
},
|
|
21
24
|
|
|
22
25
|
build: {
|
|
@@ -9,6 +9,25 @@ const projectRoot = resolve(__dirname, '..')
|
|
|
9
9
|
const output = BUILD_CONFIG.OUTPUT.webchat
|
|
10
10
|
const server = BUILD_CONFIG.SERVER.webchat
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Returns the Vite `base` for the webchat bundle.
|
|
14
|
+
*
|
|
15
|
+
* Why this matters: the dashboard's flow-builder preview panel
|
|
16
|
+
* (`PreviewWebchatAppV2`) loads this bundle cross-origin from the bot's Netlify
|
|
17
|
+
* deploy while running on a different origin (localhost:4200 in dev, the
|
|
18
|
+
* dashboard domain in prod). With an absolute base ('/'), Vite resolves the
|
|
19
|
+
* bundle's dynamically-imported chunks as `/chunk.js` against the *host page's*
|
|
20
|
+
* origin — so the preview requests them from the dashboard origin and they 404.
|
|
21
|
+
*
|
|
22
|
+
* A relative base ('') makes those chunks resolve against the entry module's own
|
|
23
|
+
* origin (import.meta.url = Netlify) instead, so the preview loads the whole
|
|
24
|
+
* bundle from Netlify with no chunk 404s and no service-worker proxy. The dev
|
|
25
|
+
* server keeps '/' so its own HMR/asset paths keep working.
|
|
26
|
+
*/
|
|
27
|
+
function getCrossOriginSafeBase(command: 'serve' | 'build'): string {
|
|
28
|
+
return command === 'build' ? '' : '/'
|
|
29
|
+
}
|
|
30
|
+
|
|
12
31
|
export function getWebchatConfig(command: 'serve' | 'build'): UserConfig {
|
|
13
32
|
const openPath =
|
|
14
33
|
command === 'serve' && process.env.LOG_VIEWER_PORT
|
|
@@ -26,7 +45,7 @@ export function getWebchatConfig(command: 'serve' | 'build'): UserConfig {
|
|
|
26
45
|
cacheDir: resolve(projectRoot, BUILD_CONFIG.CACHE_DIR.webchat),
|
|
27
46
|
publicDir: resolve(projectRoot, BUILD_CONFIG.PUBLIC_DIR),
|
|
28
47
|
appType: 'spa',
|
|
29
|
-
base:
|
|
48
|
+
base: getCrossOriginSafeBase(command),
|
|
30
49
|
|
|
31
50
|
server: {
|
|
32
51
|
port: server.port,
|
|
@@ -158,10 +158,11 @@ function createPackageJson(tree, options, botonicVersion, lilaraVersion) {
|
|
|
158
158
|
"@lilara/ui-web": lilaraVersion,
|
|
159
159
|
"@lilara/ui-web-react": lilaraVersion,
|
|
160
160
|
react: "18.3.1",
|
|
161
|
-
"react-dom": "18.3.1"
|
|
161
|
+
"react-dom": "18.3.1",
|
|
162
|
+
zod: "^4.4.3"
|
|
162
163
|
},
|
|
163
164
|
devDependencies: {
|
|
164
|
-
"@nx/vite": "21.6.
|
|
165
|
+
"@nx/vite": "21.6.11",
|
|
165
166
|
"@types/node": "22.13.0",
|
|
166
167
|
"@types/react": "18.3.1",
|
|
167
168
|
"@types/react-dom": "18.3.0",
|
|
@@ -169,7 +170,7 @@ function createPackageJson(tree, options, botonicVersion, lilaraVersion) {
|
|
|
169
170
|
"@vitejs/plugin-react-swc": "^3.5.0",
|
|
170
171
|
typescript: "5.7.3",
|
|
171
172
|
vite: "7.1.9",
|
|
172
|
-
vitest: "
|
|
173
|
+
vitest: "4.1.1"
|
|
173
174
|
}
|
|
174
175
|
};
|
|
175
176
|
(0, import_devkit.writeJson)(tree, `${options.projectRoot}/package.json`, packageJson);
|
|
@@ -257,7 +258,7 @@ function addBotonicDependencies(tree, botonicVersion) {
|
|
|
257
258
|
},
|
|
258
259
|
// devDependencies
|
|
259
260
|
{
|
|
260
|
-
"@nx/vite": "21.6.
|
|
261
|
+
"@nx/vite": "21.6.11",
|
|
261
262
|
"@types/node": "22.13.0",
|
|
262
263
|
"@types/react": "18.3.1",
|
|
263
264
|
"@types/react-dom": "18.3.0",
|
|
@@ -265,7 +266,7 @@ function addBotonicDependencies(tree, botonicVersion) {
|
|
|
265
266
|
"@vitejs/plugin-react-swc": "3.5.0",
|
|
266
267
|
typescript: "5.7.3",
|
|
267
268
|
vite: "7.1.9",
|
|
268
|
-
vitest: "
|
|
269
|
+
vitest: "4.1.1"
|
|
269
270
|
}
|
|
270
271
|
);
|
|
271
272
|
}
|
package/src/lib/bot-config.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
export interface ToolConfigJSON {
|
|
2
|
+
name: string;
|
|
3
|
+
schema?: Record<string, unknown>;
|
|
4
|
+
description: string;
|
|
5
|
+
}
|
|
6
|
+
export interface WebviewConfigJSON {
|
|
7
|
+
name: string;
|
|
8
|
+
}
|
|
1
9
|
export interface BotConfigJSON {
|
|
2
10
|
build_info: {
|
|
3
11
|
node_version: string;
|
|
@@ -7,14 +15,9 @@ export interface BotConfigJSON {
|
|
|
7
15
|
packages: Record<string, {
|
|
8
16
|
version: string;
|
|
9
17
|
}>;
|
|
10
|
-
tools:
|
|
11
|
-
name: string;
|
|
12
|
-
description: string;
|
|
13
|
-
}>;
|
|
18
|
+
tools: ToolConfigJSON[];
|
|
14
19
|
payloads: string[];
|
|
15
|
-
webviews:
|
|
16
|
-
name: string;
|
|
17
|
-
}>;
|
|
20
|
+
webviews: WebviewConfigJSON[];
|
|
18
21
|
}
|
|
19
22
|
export declare class BotConfig {
|
|
20
23
|
static get(projectRoot: string): Promise<BotConfigJSON>;
|
package/src/lib/bot-config.js
CHANGED
|
@@ -35,6 +35,7 @@ var childProcess = __toESM(require("child_process"));
|
|
|
35
35
|
var import_fs = require("fs");
|
|
36
36
|
var import_path = require("path");
|
|
37
37
|
var util = __toESM(require("util"));
|
|
38
|
+
var import_zod = require("zod");
|
|
38
39
|
const CONSTANTS_PATH = "src/shared/constants";
|
|
39
40
|
const TOOLS_PATH = "src/server/bot/tools";
|
|
40
41
|
class BotConfig {
|
|
@@ -108,7 +109,10 @@ class BotConfig {
|
|
|
108
109
|
return toolsModule.customTools.map(
|
|
109
110
|
(tool) => ({
|
|
110
111
|
name: tool.name,
|
|
111
|
-
description: tool.description
|
|
112
|
+
description: tool.description,
|
|
113
|
+
schema: import_zod.z.toJSONSchema(tool.schema, {
|
|
114
|
+
target: "draft-07"
|
|
115
|
+
})
|
|
112
116
|
})
|
|
113
117
|
);
|
|
114
118
|
}
|
|
@@ -71,6 +71,17 @@ export declare function writeLocalRuntimeBotToAppFolder(projectRoot: string, bot
|
|
|
71
71
|
*/
|
|
72
72
|
export declare function removeAppBotonicJson(projectRoot: string): void;
|
|
73
73
|
export declare function ensureLocalRuntimeBot(botonicApiService: BotonicAPIService): Promise<void>;
|
|
74
|
+
export type ProviderAccountListItem = {
|
|
75
|
+
id: string;
|
|
76
|
+
provider?: string;
|
|
77
|
+
is_test?: boolean;
|
|
78
|
+
is_active?: boolean;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* APP_ID for local runtime must be the webchat test provider — not WhatsApp
|
|
82
|
+
* or other channels, which may also be test+active on the same bot.
|
|
83
|
+
*/
|
|
84
|
+
export declare function getActiveTestWebchatProviderAppId(results: ProviderAccountListItem[] | undefined): string | undefined;
|
|
74
85
|
export interface PerformDeployLocalRuntimeOptions {
|
|
75
86
|
email?: string;
|
|
76
87
|
password?: string;
|
|
@@ -26,6 +26,7 @@ __export(executor_helpers_exports, {
|
|
|
26
26
|
ensureLocalRuntimeBot: () => ensureLocalRuntimeBot,
|
|
27
27
|
ensureLocalRuntimeBotBeforeTunnel: () => ensureLocalRuntimeBotBeforeTunnel,
|
|
28
28
|
findMatchingConfigurationKey: () => findMatchingConfigurationKey,
|
|
29
|
+
getActiveTestWebchatProviderAppId: () => getActiveTestWebchatProviderAppId,
|
|
29
30
|
getAppIdFromEnvFile: () => getAppIdFromEnvFile,
|
|
30
31
|
getAppIdFromEnvFileForConfig: () => getAppIdFromEnvFileForConfig,
|
|
31
32
|
getAvailableBots: () => getAvailableBots,
|
|
@@ -500,6 +501,12 @@ async function ensureLocalRuntimeBot(botonicApiService) {
|
|
|
500
501
|
throw new Error("Bot selection failed");
|
|
501
502
|
}
|
|
502
503
|
}
|
|
504
|
+
const WEBCHAT_PROVIDER = "webchat";
|
|
505
|
+
function getActiveTestWebchatProviderAppId(results) {
|
|
506
|
+
return results?.find(
|
|
507
|
+
(p) => Boolean(p.is_test) && Boolean(p.is_active) && p.provider === WEBCHAT_PROVIDER
|
|
508
|
+
)?.id;
|
|
509
|
+
}
|
|
503
510
|
async function performDeployLocalRuntimeWithEndpoint(context, projectRoot, endpoint, options = {}) {
|
|
504
511
|
const { targetEnvironment, environmentVariables } = resolveHubtypeEnvironment(
|
|
505
512
|
context,
|
|
@@ -534,15 +541,18 @@ async function performDeployLocalRuntimeWithEndpoint(context, projectRoot, endpo
|
|
|
534
541
|
lambdaEndpoint: endpoint
|
|
535
542
|
});
|
|
536
543
|
const providersResp = await botonicApiService.getProviders();
|
|
537
|
-
const appId =
|
|
538
|
-
|
|
539
|
-
)
|
|
544
|
+
const appId = getActiveTestWebchatProviderAppId(
|
|
545
|
+
providersResp.data.results
|
|
546
|
+
);
|
|
547
|
+
if (!appId) {
|
|
548
|
+
throw new Error(
|
|
549
|
+
"No active test webchat provider found for this bot. Local runtime requires a webchat test provider account."
|
|
550
|
+
);
|
|
551
|
+
}
|
|
540
552
|
const resolvedTargetEnv = TARGET_ENV_NAMES.includes(
|
|
541
553
|
targetEnvironment
|
|
542
554
|
) ? targetEnvironment : "local";
|
|
543
|
-
|
|
544
|
-
await writeAppIdToEnvFile(projectRoot, appId, resolvedTargetEnv);
|
|
545
|
-
}
|
|
555
|
+
await writeAppIdToEnvFile(projectRoot, appId, resolvedTargetEnv);
|
|
546
556
|
botonicApiService.saveAllCredentials();
|
|
547
557
|
return {
|
|
548
558
|
botId: botonicApiService.botInfo().id,
|
|
@@ -572,6 +582,7 @@ async function performDeployLocalRuntimeWithEndpoint(context, projectRoot, endpo
|
|
|
572
582
|
ensureLocalRuntimeBot,
|
|
573
583
|
ensureLocalRuntimeBotBeforeTunnel,
|
|
574
584
|
findMatchingConfigurationKey,
|
|
585
|
+
getActiveTestWebchatProviderAppId,
|
|
575
586
|
getAppIdFromEnvFile,
|
|
576
587
|
getAppIdFromEnvFileForConfig,
|
|
577
588
|
getAvailableBots,
|
package/src/plugin.js
CHANGED
|
@@ -102,7 +102,7 @@ const configurations = {
|
|
|
102
102
|
dev: {
|
|
103
103
|
configuration: "dev",
|
|
104
104
|
env: {
|
|
105
|
-
VITE_HUBTYPE_CLIENT_ID: "
|
|
105
|
+
VITE_HUBTYPE_CLIENT_ID: "WlvymZ703Y5zGnmaCZ9Da5vf0lNX08jFvgC4pRMT",
|
|
106
106
|
VITE_HUBTYPE_API_URL: "https://api.dev.dev.dev.hubtype.com",
|
|
107
107
|
VITE_PUSHER_API_PREFIX: "dev-dev-dev"
|
|
108
108
|
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BotonicPluginHubtypeAnalytics,
|
|
3
|
-
EventAction,
|
|
4
|
-
HtEventProps,
|
|
5
|
-
} from '@botonic/plugin-hubtype-analytics'
|
|
6
|
-
import { BotonicContext } from '@botonic/core'
|
|
7
|
-
|
|
8
|
-
import { BotPlugins } from './types'
|
|
9
|
-
|
|
10
|
-
export async function trackEventToHubtypeAnalytics(
|
|
11
|
-
botonicContext: BotonicContext<BotPlugins>,
|
|
12
|
-
eventName: EventAction,
|
|
13
|
-
args: Omit<HtEventProps, 'action'>
|
|
14
|
-
): Promise<void> {
|
|
15
|
-
const hubtypeAnalyticsPlugin = botonicContext.plugins.hubtypeAnalytics
|
|
16
|
-
const htEventProps = {
|
|
17
|
-
action: eventName,
|
|
18
|
-
...args,
|
|
19
|
-
} as HtEventProps
|
|
20
|
-
|
|
21
|
-
if (
|
|
22
|
-
!hubtypeAnalyticsPlugin ||
|
|
23
|
-
!(hubtypeAnalyticsPlugin instanceof BotonicPluginHubtypeAnalytics)
|
|
24
|
-
) {
|
|
25
|
-
console.log('Hubtype Analytics Plugin not found')
|
|
26
|
-
return
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const response = await hubtypeAnalyticsPlugin.trackEvent(
|
|
30
|
-
botonicContext,
|
|
31
|
-
htEventProps
|
|
32
|
-
)
|
|
33
|
-
console.log('TrackEvent Response', response, args)
|
|
34
|
-
return
|
|
35
|
-
}
|