@botonic/nx-plugin 2.25.0 → 2.27.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 +29 -0
- package/README.md +4 -4
- package/generators.json +0 -26
- package/migrations.json +1 -38
- package/package.json +1 -1
- package/src/executors/e2e-webchat/botonic-package-publish.spec.ts +3 -3
- package/src/executors/serve-bot/executor.js +98 -16
- package/src/executors/serve-bot/schema.json +10 -0
- package/src/generators/action/files/__name__.spec.ts.template +4 -4
- package/src/generators/action/files/__name__.ts.template +5 -5
- package/src/generators/action/generator.js +1 -1
- package/src/generators/bot-app/files/.eslintrc.json.template +30 -1
- package/src/generators/bot-app/files/src/client/webchat/index.tsx.template +1 -6
- package/src/generators/bot-app/files/src/server/bot/actions/not-found.ts.template +7 -6
- package/src/generators/bot-app/files/src/server/bot/actions/welcome.ts.template +7 -6
- package/src/generators/bot-app/files/src/server/bot/index.ts.template +9 -11
- package/src/generators/bot-app/files/src/server/bot/plugins/ai-agents/index.ts.template +4 -4
- package/src/generators/bot-app/files/src/server/bot/plugins/flow-builder/index.ts.template +5 -5
- package/src/generators/bot-app/files/src/server/bot/routes.ts.template +5 -5
- package/src/generators/bot-app/files/src/server/bot/tracking.ts.template +4 -4
- package/src/generators/bot-app/files/src/server/lambda/handler.js.template +1 -6
- package/src/generators/bot-app/files/vite/plugins/dev-log-viewer-html.plugin.ts.template +65 -0
- package/src/generators/bot-app/files/vite/webchat.config.ts.template +14 -1
- package/src/generators/bot-app/generator.js +6 -2
- package/src/generators/bot-app/lilara-version.json +1 -1
- package/src/generators/bot-app/schema.d.ts +1 -0
- package/src/generators/bot-app/schema.json +4 -0
- package/src/generators/custom-message/files/__name__-output.ts.template +12 -10
- package/src/generators/custom-message/generator.js +1 -1
- package/src/{cursor-commands → generators/preset/files/.claude/commands}/update-bot.md +7 -7
- package/src/{cursor-commands → generators/preset/files/.claude/commands}/update-botonic.md +5 -3
- package/src/{migrations/add-botonic-update-bots-skill/files/.cursor → generators/preset/files/.claude}/scripts/update-bot/discover-bots.sh +1 -1
- package/src/generators/preset/files/{.cursor → .claude}/skills/botonic-action/SKILL.md +21 -21
- package/src/generators/preset/files/{.cursor → .claude}/skills/botonic-custom-message/SKILL.md +11 -12
- package/src/generators/preset/files/{.cursor → .claude}/skills/botonic-webview/SKILL.md +8 -8
- package/src/generators/preset/files/.cursor/commands/update-bot.md +1 -3
- package/src/generators/preset/files/.cursor/commands/update-botonic.md +1 -3
- package/src/lib/util/executor-helpers.d.ts +0 -1
- package/src/lib/util/executor-helpers.js +1 -8
- package/src/generators/bot-app-migrations/migrate-fix-css-code-split/generator.d.ts +0 -5
- package/src/generators/bot-app-migrations/migrate-fix-css-code-split/generator.js +0 -92
- package/src/generators/bot-app-migrations/migrate-fix-css-code-split/schema.json +0 -15
- package/src/generators/bot-app-migrations/migrate-pnpm-compat/generator.d.ts +0 -5
- package/src/generators/bot-app-migrations/migrate-pnpm-compat/generator.js +0 -97
- package/src/generators/bot-app-migrations/migrate-pnpm-compat/schema.json +0 -15
- package/src/generators/bot-app-migrations/migrate-webchat-trigger/generator.d.ts +0 -5
- package/src/generators/bot-app-migrations/migrate-webchat-trigger/generator.js +0 -165
- package/src/generators/bot-app-migrations/migrate-webchat-trigger/schema.json +0 -15
- package/src/generators/preset/files/.cursor/scripts/update-bot/discover-bots.sh +0 -67
- package/src/migrations/add-botonic-update-bots-skill/add-botonic-update-bots-skill.migration.d.ts +0 -2
- package/src/migrations/add-botonic-update-bots-skill/add-botonic-update-bots-skill.migration.js +0 -52
- package/src/migrations/add-botonic-update-bots-skill/add-botonic-update-bots-skill.migration.md +0 -23
- package/src/migrations/add-botonic-update-bots-skill/files/.cursor/commands/update-bot.md +0 -5
- package/src/migrations/add-botonic-update-bots-skill/files/.cursor/commands/update-botonic.md +0 -5
- package/src/migrations/add-botonic-update-bots-skill/files/.cursor/scripts/update-bot/find-migration-guides.sh +0 -70
- package/src/migrations/add-botonic-update-bots-skill/schema.json +0 -5
- package/src/migrations/add-lilara-registry/add-lilara-registry.migration.d.ts +0 -2
- package/src/migrations/add-lilara-registry/add-lilara-registry.migration.js +0 -49
- package/src/migrations/add-lilara-registry/schema.json +0 -5
- package/src/migrations/fix-css-code-split/fix-css-code-split.migration.md +0 -45
- package/src/migrations/remove-codeartifact-registry/remove-codeartifact-registry.migration.d.ts +0 -2
- package/src/migrations/remove-codeartifact-registry/remove-codeartifact-registry.migration.js +0 -59
- package/src/migrations/remove-codeartifact-registry/schema.json +0 -5
- package/src/migrations/sync-pending-bot-migrations/schema.json +0 -5
- package/src/migrations/sync-pending-bot-migrations/sync-pending-bot-migrations.migration.d.ts +0 -2
- package/src/migrations/sync-pending-bot-migrations/sync-pending-bot-migrations.migration.js +0 -137
- package/src/migrations/sync-pending-bot-migrations/sync-pending-bot-migrations.migration.md +0 -19
- package/src/migrations/update-cursor-commands-to-stubs/schema.json +0 -5
- package/src/migrations/update-cursor-commands-to-stubs/update-cursor-commands-to-stubs.migration.d.ts +0 -2
- package/src/migrations/update-cursor-commands-to-stubs/update-cursor-commands-to-stubs.migration.js +0 -61
- package/src/migrations/update-pnpm-workspace-scripts/schema.json +0 -4
- package/src/migrations/update-pnpm-workspace-scripts/update-pnpm-workspace-scripts.migration.d.ts +0 -2
- package/src/migrations/update-pnpm-workspace-scripts/update-pnpm-workspace-scripts.migration.js +0 -47
- /package/src/generators/preset/files/{.cursor → .claude}/scripts/update-bot/find-migration-guides.sh +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
## 2.27.0 (2026-04-29)
|
|
2
|
+
|
|
3
|
+
### 🚀 Features
|
|
4
|
+
|
|
5
|
+
- **webchat-react:** add design system gateway for @lilara/ui-web-react (BLT-2334) ([#859](https://github.com/metis-ai/hubtype-product/pull/859))
|
|
6
|
+
- Hero Header transitions ([#860](https://github.com/metis-ai/hubtype-product/pull/860))
|
|
7
|
+
- **botonic:** session and Hubtype API adaptations (non-webviews) ([#810](https://github.com/metis-ai/hubtype-product/pull/810))
|
|
8
|
+
|
|
9
|
+
### 🩹 Fixes
|
|
10
|
+
|
|
11
|
+
- **nx-plugin:** stabilize vitest execution ([#798](https://github.com/metis-ai/hubtype-product/pull/798))
|
|
12
|
+
- **nx-plugin:** inject lilara version into bot-app generator ([#795](https://github.com/metis-ai/hubtype-product/pull/795))
|
|
13
|
+
|
|
14
|
+
### ❤️ Thank You
|
|
15
|
+
|
|
16
|
+
- David Hidalgo @Davidhidalgo
|
|
17
|
+
- Marc Rabat @vanbasten17
|
|
18
|
+
|
|
19
|
+
## 2.26.0 (2026-03-31)
|
|
20
|
+
|
|
21
|
+
### 🚀 Features
|
|
22
|
+
|
|
23
|
+
- **webchat-react:** chat input action bar and contextual send/mic #BLT-2290 ([#788](https://github.com/metis-ai/hubtype-product/pull/788))
|
|
24
|
+
- **botonic:** allow Cloudflare tunnel hostnames in Vite webchat ([#780](https://github.com/metis-ai/hubtype-product/pull/780))
|
|
25
|
+
|
|
26
|
+
### ❤️ Thank You
|
|
27
|
+
|
|
28
|
+
- David Hidalgo @Davidhidalgo
|
|
29
|
+
|
|
1
30
|
## 2.25.0 (2026-03-27)
|
|
2
31
|
|
|
3
32
|
This was a version bump only for @botonic/nx-plugin to align it with other projects, there were no code changes.
|
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ nx g @botonic/nx-plugin:bot-app my-bot
|
|
|
37
37
|
|
|
38
38
|
#### What it creates:
|
|
39
39
|
|
|
40
|
-
- **Modern Actions**: Async functions using `
|
|
40
|
+
- **Modern Actions**: Async functions using `BotonicContext` instead of React class components
|
|
41
41
|
- **React 18 Webchat**: Uses `@botonic/webchat` with `createRoot` and `StrictMode`
|
|
42
42
|
- **Current Dependencies**: Uses modern Botonic packages and avoids legacy packages
|
|
43
43
|
- **Custom Messages Structure**: Empty structure ready for your custom components
|
|
@@ -173,11 +173,11 @@ export class Welcome extends React.Component {
|
|
|
173
173
|
**After (modern async function):**
|
|
174
174
|
|
|
175
175
|
```typescript
|
|
176
|
-
import {
|
|
176
|
+
import { BotonicContext } from '@botonic/core'
|
|
177
177
|
import { MessageAction } from '@botonic/shared'
|
|
178
178
|
|
|
179
|
-
export async function Welcome({
|
|
180
|
-
await
|
|
179
|
+
export async function Welcome({ sendMessages }: BotonicContext) {
|
|
180
|
+
await sendMessages([
|
|
181
181
|
{
|
|
182
182
|
type: 'text',
|
|
183
183
|
data: { text: "Hello! I'm your bot 🤖\nWelcome to Botonic!" },
|
package/generators.json
CHANGED
|
@@ -30,32 +30,6 @@
|
|
|
30
30
|
"factory": "./src/generators/webview/generator",
|
|
31
31
|
"schema": "./src/generators/webview/schema.json",
|
|
32
32
|
"description": "Create a webview component for Botonic"
|
|
33
|
-
},
|
|
34
|
-
"migrate-webchat-trigger": {
|
|
35
|
-
"factory": "./src/generators/bot-app-migrations/migrate-webchat-trigger/generator",
|
|
36
|
-
"schema": "./src/generators/bot-app-migrations/migrate-webchat-trigger/schema.json",
|
|
37
|
-
"description": "Migrate a bot app to use @botonic/webchat-react/trigger lazy-loading entry point",
|
|
38
|
-
"hidden": true,
|
|
39
|
-
"x-bot-app-migration": true,
|
|
40
|
-
"x-introduced-in": "2.18.0",
|
|
41
|
-
"x-migration-guide": "src/generators/bot-app-migrations/migrate-webchat-trigger/migrate-webchat-trigger.md"
|
|
42
|
-
},
|
|
43
|
-
"migrate-fix-css-code-split": {
|
|
44
|
-
"factory": "./src/generators/bot-app-migrations/migrate-fix-css-code-split/generator",
|
|
45
|
-
"schema": "./src/generators/bot-app-migrations/migrate-fix-css-code-split/schema.json",
|
|
46
|
-
"description": "Add cssCodeSplit: false to vite webchat and webviews configs",
|
|
47
|
-
"hidden": true,
|
|
48
|
-
"x-bot-app-migration": true,
|
|
49
|
-
"x-introduced-in": "2.18.0"
|
|
50
|
-
},
|
|
51
|
-
"migrate-pnpm-compat": {
|
|
52
|
-
"factory": "./src/generators/bot-app-migrations/migrate-pnpm-compat/generator",
|
|
53
|
-
"schema": "./src/generators/bot-app-migrations/migrate-pnpm-compat/schema.json",
|
|
54
|
-
"description": "Add **/node_modules/** to eslint ignorePatterns and update README npm refs to pnpm",
|
|
55
|
-
"hidden": true,
|
|
56
|
-
"x-bot-app-migration": true,
|
|
57
|
-
"x-introduced-in": "2.18.0",
|
|
58
|
-
"x-migration-guide": "src/generators/bot-app-migrations/migrate-pnpm-compat/migrate-pnpm-compat.md"
|
|
59
33
|
}
|
|
60
34
|
}
|
|
61
35
|
}
|
package/migrations.json
CHANGED
|
@@ -1,40 +1,3 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generators": {
|
|
3
|
-
"add-botonic-update-bots-skill": {
|
|
4
|
-
"version": "2.17.0",
|
|
5
|
-
"description": "Add /update-botonic and /update-bot Cursor commands for workspace and per-bot version migrations",
|
|
6
|
-
"cli": "nx",
|
|
7
|
-
"implementation": "./src/migrations/add-botonic-update-bots-skill/add-botonic-update-bots-skill.migration"
|
|
8
|
-
},
|
|
9
|
-
"sync-pending-bot-migrations": {
|
|
10
|
-
"version": "2.17.0",
|
|
11
|
-
"description": "Write .botonic/pending-bot-migrations.json with bot-app generators pending for each bot",
|
|
12
|
-
"cli": "nx",
|
|
13
|
-
"implementation": "./src/migrations/sync-pending-bot-migrations/sync-pending-bot-migrations.migration"
|
|
14
|
-
},
|
|
15
|
-
"update-pnpm-workspace-scripts": {
|
|
16
|
-
"version": "2.18.0",
|
|
17
|
-
"description": "Update find-migration-guides.sh to reference pnpm instead of npm",
|
|
18
|
-
"cli": "nx",
|
|
19
|
-
"implementation": "./src/migrations/update-pnpm-workspace-scripts/update-pnpm-workspace-scripts.migration"
|
|
20
|
-
},
|
|
21
|
-
"update-cursor-commands-to-stubs": {
|
|
22
|
-
"version": "2.18.0",
|
|
23
|
-
"description": "Replace full-content .cursor/commands/*.md with stable stubs that reference the canonical source in node_modules",
|
|
24
|
-
"cli": "nx",
|
|
25
|
-
"implementation": "./src/migrations/update-cursor-commands-to-stubs/update-cursor-commands-to-stubs.migration"
|
|
26
|
-
},
|
|
27
|
-
"add-lilara-registry": {
|
|
28
|
-
"version": "2.19.0",
|
|
29
|
-
"description": "(Legacy) Add @hubtype-lilara:registry for CodeArtifact; run remove-codeartifact-registry (2.23+) for public npm",
|
|
30
|
-
"cli": "nx",
|
|
31
|
-
"implementation": "./src/migrations/add-lilara-registry/add-lilara-registry.migration"
|
|
32
|
-
},
|
|
33
|
-
"remove-codeartifact-registry": {
|
|
34
|
-
"version": "2.23.0",
|
|
35
|
-
"description": "Remove CodeArtifact @botonic / @hubtype-lilara registry and auth lines from .npmrc (switch to public npm)",
|
|
36
|
-
"cli": "nx",
|
|
37
|
-
"implementation": "./src/migrations/remove-codeartifact-registry/remove-codeartifact-registry.migration"
|
|
38
|
-
}
|
|
39
|
-
}
|
|
2
|
+
"generators": {}
|
|
40
3
|
}
|
package/package.json
CHANGED
|
@@ -70,12 +70,12 @@ test.describe('Botonic Publish E2E', () => {
|
|
|
70
70
|
await ensureWebchatOpen(page)
|
|
71
71
|
|
|
72
72
|
const input = page.locator('textarea').first()
|
|
73
|
-
const sendButton = page.locator('button[class*="send-button"]').first()
|
|
74
|
-
|
|
75
73
|
await expect(input).toBeVisible({ timeout: 5000 })
|
|
76
|
-
await expect(sendButton).toBeVisible()
|
|
77
74
|
|
|
78
75
|
await input.fill('test message')
|
|
76
|
+
|
|
77
|
+
const sendButton = page.getByRole('button', { name: 'Send message' })
|
|
78
|
+
await expect(sendButton).toBeVisible()
|
|
79
79
|
await sendButton.click()
|
|
80
80
|
|
|
81
81
|
const messages = page.locator('[class*="message-module"]')
|
|
@@ -51,6 +51,77 @@ const colors = {
|
|
|
51
51
|
dim: "\x1B[2m",
|
|
52
52
|
bold: "\x1B[1m"
|
|
53
53
|
};
|
|
54
|
+
let logFilePath = null;
|
|
55
|
+
function initLogFile(projectRoot) {
|
|
56
|
+
const logsDir = (0, import_path.join)(projectRoot, ".botonic", "logs");
|
|
57
|
+
(0, import_fs.mkdirSync)(logsDir, { recursive: true });
|
|
58
|
+
const logPath = (0, import_path.join)(logsDir, "serve-bot.log");
|
|
59
|
+
(0, import_fs.writeFileSync)(logPath, "");
|
|
60
|
+
return logPath;
|
|
61
|
+
}
|
|
62
|
+
function writeToLogFile(line) {
|
|
63
|
+
if (logFilePath) {
|
|
64
|
+
try {
|
|
65
|
+
(0, import_fs.appendFileSync)(logFilePath, `${line}
|
|
66
|
+
`);
|
|
67
|
+
} catch {
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function checkFrontailInstalled(cwd) {
|
|
72
|
+
try {
|
|
73
|
+
(0, import_child_process.execSync)("npx --no frontail --help", { stdio: "pipe", cwd });
|
|
74
|
+
return true;
|
|
75
|
+
} catch {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function startFrontail(logPath, port, cwd) {
|
|
80
|
+
if (!checkFrontailInstalled(cwd)) {
|
|
81
|
+
console.warn(`${colors.bold}\u26A0\uFE0F frontail is not installed.${colors.reset}`);
|
|
82
|
+
console.warn(
|
|
83
|
+
` Run: ${colors.dim}pnpm install${colors.reset} to install dependencies
|
|
84
|
+
`
|
|
85
|
+
);
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
const frontailProcess = (0, import_child_process.spawn)(
|
|
89
|
+
"npx",
|
|
90
|
+
[
|
|
91
|
+
"--no",
|
|
92
|
+
"frontail",
|
|
93
|
+
"--port",
|
|
94
|
+
port.toString(),
|
|
95
|
+
"--theme",
|
|
96
|
+
"dark",
|
|
97
|
+
"--lines",
|
|
98
|
+
"500",
|
|
99
|
+
"--ui-hide-topbar",
|
|
100
|
+
logPath
|
|
101
|
+
],
|
|
102
|
+
{
|
|
103
|
+
cwd,
|
|
104
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
105
|
+
detached: false
|
|
106
|
+
}
|
|
107
|
+
);
|
|
108
|
+
frontailProcess.on("error", (error) => {
|
|
109
|
+
console.error(
|
|
110
|
+
`${colors.dim}[log-viewer]${colors.reset} Error: ${error.message}`
|
|
111
|
+
);
|
|
112
|
+
});
|
|
113
|
+
return frontailProcess;
|
|
114
|
+
}
|
|
115
|
+
function tryReadWebchatDevPort(projectRoot) {
|
|
116
|
+
try {
|
|
117
|
+
const configPath = (0, import_path.join)(projectRoot, "vite", "build.config.ts");
|
|
118
|
+
const content = (0, import_fs.readFileSync)(configPath, "utf8");
|
|
119
|
+
const match = content.match(/webchat:\s*\{\s*port:\s*(\d+)/);
|
|
120
|
+
if (match) return parseInt(match[1], 10);
|
|
121
|
+
} catch {
|
|
122
|
+
}
|
|
123
|
+
return 4201;
|
|
124
|
+
}
|
|
54
125
|
function getAppIdFromEnvFile(projectRoot) {
|
|
55
126
|
const envFilePath = (0, import_path.join)(projectRoot, ".env.local");
|
|
56
127
|
if (!(0, import_fs.existsSync)(envFilePath)) {
|
|
@@ -77,9 +148,9 @@ function prefixOutput(stream, prefix, color) {
|
|
|
77
148
|
const rl = readline.createInterface({ input: stream });
|
|
78
149
|
rl.on("line", (line) => {
|
|
79
150
|
const timestamp = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false });
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
);
|
|
151
|
+
const formattedLine = `${colors.dim}${timestamp}${colors.reset} ${color}[${prefix}]${colors.reset} ${line}`;
|
|
152
|
+
console.log(formattedLine);
|
|
153
|
+
writeToLogFile(`${timestamp} [${prefix}] ${line}`);
|
|
83
154
|
});
|
|
84
155
|
}
|
|
85
156
|
function spawnProcess(command, name, color, cwd) {
|
|
@@ -134,11 +205,21 @@ async function serveBotExecutor(options, context) {
|
|
|
134
205
|
`${colors.dim}[lambda] No previous Lambda container to clean up.${colors.reset}`
|
|
135
206
|
);
|
|
136
207
|
}
|
|
208
|
+
const logViewerEnabled = options.logViewer === true;
|
|
209
|
+
logFilePath = null;
|
|
210
|
+
const logViewerPort = options.logViewerPort ?? 9001;
|
|
211
|
+
const webchatDevPort = tryReadWebchatDevPort(fullProjectRoot);
|
|
212
|
+
let frontailProcess = null;
|
|
213
|
+
if (logViewerEnabled) {
|
|
214
|
+
logFilePath = initLogFile(fullProjectRoot);
|
|
215
|
+
frontailProcess = startFrontail(logFilePath, logViewerPort, context.root);
|
|
216
|
+
}
|
|
217
|
+
const logViewerInfo = logViewerEnabled ? `${colors.dim}Webchat:${colors.reset} ${colors.bold}http://localhost:${webchatDevPort}/?logs=${logViewerPort}${colors.reset} (with logs panel)
|
|
218
|
+
${colors.dim}Log viewer:${colors.reset} http://localhost:${logViewerPort}` : "";
|
|
137
219
|
const useTunnel = true;
|
|
138
220
|
const tunnelPort = options.tunnelPort ?? 3001;
|
|
139
221
|
let effectiveLambdaEndpoint = options.lambdaEndpoint;
|
|
140
222
|
let startLambda = !options.skipLambda && !effectiveLambdaEndpoint;
|
|
141
|
-
let tunnelBotId;
|
|
142
223
|
let tunnelDeployResult;
|
|
143
224
|
if (useTunnel) {
|
|
144
225
|
await (0, import_executor_helpers.ensureHubtypeLoginBeforeTunnel)(context, fullProjectRoot, {
|
|
@@ -183,7 +264,6 @@ async function serveBotExecutor(options, context) {
|
|
|
183
264
|
tunnelUrl,
|
|
184
265
|
{ env: options.env, configuration }
|
|
185
266
|
);
|
|
186
|
-
tunnelBotId = deployResult.botId;
|
|
187
267
|
tunnelDeployResult = {
|
|
188
268
|
targetEnvironment: deployResult.targetEnvironment,
|
|
189
269
|
environmentVariables: deployResult.environmentVariables
|
|
@@ -194,6 +274,9 @@ async function serveBotExecutor(options, context) {
|
|
|
194
274
|
} catch (tunnelError) {
|
|
195
275
|
const msg = tunnelError instanceof Error ? tunnelError.message : String(tunnelError);
|
|
196
276
|
console.error(`\u274C Tunnel flow failed: ${msg}`);
|
|
277
|
+
if (frontailProcess) {
|
|
278
|
+
frontailProcess.kill("SIGTERM");
|
|
279
|
+
}
|
|
197
280
|
return { success: false };
|
|
198
281
|
}
|
|
199
282
|
let effectiveAppId = appId;
|
|
@@ -206,14 +289,6 @@ async function serveBotExecutor(options, context) {
|
|
|
206
289
|
}
|
|
207
290
|
if (configuration !== "local" && effectiveAppId) {
|
|
208
291
|
await (0, import_executor_helpers.writeAppIdToEnvFile)(fullProjectRoot, effectiveAppId, configuration);
|
|
209
|
-
if (tunnelBotId) {
|
|
210
|
-
(0, import_executor_helpers.writeEnvVarToEnvFile)(
|
|
211
|
-
fullProjectRoot,
|
|
212
|
-
"VITE_HUBTYPE_BOT_ID",
|
|
213
|
-
tunnelBotId,
|
|
214
|
-
configuration
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
292
|
}
|
|
218
293
|
const useExternalLambda = Boolean(effectiveLambdaEndpoint);
|
|
219
294
|
if (!useTunnel) {
|
|
@@ -227,6 +302,7 @@ ${colors.bold}\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
|
227
302
|
${colors.dim}Project:${colors.reset} ${context.projectName}
|
|
228
303
|
${colors.dim}Configuration:${colors.reset} ${configuration}
|
|
229
304
|
${colors.dim}App ID:${colors.reset} ${effectiveAppId}
|
|
305
|
+
${logViewerInfo}
|
|
230
306
|
${useExternalLambda ? `${colors.dim}Lambda (external):${colors.reset} ${effectiveLambdaEndpoint}
|
|
231
307
|
` : ""}
|
|
232
308
|
${colors.bot}[bot]${colors.reset} - Node/Lambda build watcher
|
|
@@ -264,13 +340,13 @@ ${colors.webviews}[webviews]${colors.reset} - Webviews Vite dev server
|
|
|
264
340
|
}
|
|
265
341
|
const noOpenEnv = options.open === false ? "VITE_SERVE_OPEN=false " : "";
|
|
266
342
|
const viteEnvAppId = `VITE_HUBTYPE_APP_ID=${effectiveAppId}`;
|
|
267
|
-
const
|
|
268
|
-
const webchatCommand = `${noOpenEnv}${
|
|
343
|
+
const logViewerEnv = logViewerEnabled ? `LOG_VIEWER_PORT=${logViewerPort} ` : "";
|
|
344
|
+
const webchatCommand = `${noOpenEnv}${logViewerEnv}${viteEnvAppId} TARGET_APP=webchat MODE=${configuration} vite --config ${configPath}`;
|
|
269
345
|
processes.push(
|
|
270
346
|
spawnProcess(webchatCommand, "webchat", colors.webchat, fullProjectRoot)
|
|
271
347
|
);
|
|
272
348
|
if (!options.skipWebviews) {
|
|
273
|
-
const webviewsCommand = `${noOpenEnv}${viteEnvAppId}
|
|
349
|
+
const webviewsCommand = `${noOpenEnv}${viteEnvAppId} TARGET_APP=webviews MODE=${configuration} vite --config ${configPath}`;
|
|
274
350
|
processes.push(
|
|
275
351
|
spawnProcess(
|
|
276
352
|
webviewsCommand,
|
|
@@ -292,6 +368,12 @@ ${colors.bold}\u{1F6D1} Shutting down all processes...${colors.reset}`
|
|
|
292
368
|
console.log(`${color}[${name}]${colors.reset} Stopping...`);
|
|
293
369
|
proc.kill("SIGTERM");
|
|
294
370
|
});
|
|
371
|
+
if (frontailProcess) {
|
|
372
|
+
console.log(
|
|
373
|
+
`${colors.dim}[log-viewer]${colors.reset} Stopping log viewer...`
|
|
374
|
+
);
|
|
375
|
+
frontailProcess.kill("SIGTERM");
|
|
376
|
+
}
|
|
295
377
|
};
|
|
296
378
|
process.on("SIGINT", cleanup);
|
|
297
379
|
process.on("SIGTERM", cleanup);
|
|
@@ -34,6 +34,16 @@
|
|
|
34
34
|
"type": "number",
|
|
35
35
|
"description": "Local port the Lambda listens on (used for cloudflared --url). Default 3001.",
|
|
36
36
|
"default": 3001
|
|
37
|
+
},
|
|
38
|
+
"logViewer": {
|
|
39
|
+
"type": "boolean",
|
|
40
|
+
"description": "When true, start a web-based log viewer (frontail) and open webchat with an embedded logs panel.",
|
|
41
|
+
"default": false
|
|
42
|
+
},
|
|
43
|
+
"logViewerPort": {
|
|
44
|
+
"type": "number",
|
|
45
|
+
"description": "Port for the log viewer web interface",
|
|
46
|
+
"default": 9001
|
|
37
47
|
}
|
|
38
48
|
},
|
|
39
49
|
"required": []
|
|
@@ -3,13 +3,13 @@ import { describe, expect, it, vi } from 'vitest'
|
|
|
3
3
|
import { <%= className %> } from './<%= fileName %>'
|
|
4
4
|
|
|
5
5
|
describe('<%= className %>', () => {
|
|
6
|
-
it('should call
|
|
7
|
-
const
|
|
8
|
-
const mockContext = {
|
|
6
|
+
it('should call sendMessages and return OK', async () => {
|
|
7
|
+
const sendMessages = vi.fn().mockResolvedValue(undefined)
|
|
8
|
+
const mockContext = { sendMessages } as any
|
|
9
9
|
|
|
10
10
|
const result = await <%= className %>(mockContext)
|
|
11
11
|
|
|
12
|
-
expect(
|
|
12
|
+
expect(sendMessages).toHaveBeenCalledOnce()
|
|
13
13
|
expect(result).toEqual({ status: 200, response: 'OK' })
|
|
14
14
|
})
|
|
15
15
|
})
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BotonicContext, BotServerMessageFactory } from '@botonic/shared'
|
|
2
2
|
|
|
3
|
-
export async function <%= className %>({
|
|
3
|
+
export async function <%= className %>({ sendMessages }: BotonicContext) {
|
|
4
4
|
// TODO: Implement your action logic here
|
|
5
|
-
await
|
|
5
|
+
await sendMessages([
|
|
6
6
|
BotServerMessageFactory.createText({
|
|
7
7
|
text: 'Hello from <%= className %>!',
|
|
8
|
-
})
|
|
9
|
-
)
|
|
8
|
+
}),
|
|
9
|
+
])
|
|
10
10
|
|
|
11
11
|
return {
|
|
12
12
|
status: 200,
|
|
@@ -80,7 +80,7 @@ function updateRoutes(tree, options) {
|
|
|
80
80
|
(0, import_bot_app_utils.insertRouteBeforeFlowBuilder)(tree, options.routesPath, [
|
|
81
81
|
` {`,
|
|
82
82
|
` text: '${options.resolvedRouteMatcher}',`,
|
|
83
|
-
` action: async () => await ${options.className}(
|
|
83
|
+
` action: async () => await ${options.className}(botonicContext),`,
|
|
84
84
|
` },`
|
|
85
85
|
]);
|
|
86
86
|
}
|
|
@@ -4,7 +4,36 @@
|
|
|
4
4
|
"overrides": [
|
|
5
5
|
{
|
|
6
6
|
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
|
7
|
-
"rules": {
|
|
7
|
+
"rules": {
|
|
8
|
+
"no-restricted-imports": [
|
|
9
|
+
"warn",
|
|
10
|
+
{
|
|
11
|
+
"paths": [
|
|
12
|
+
{
|
|
13
|
+
"name": "@lilara/ui-web-react",
|
|
14
|
+
"message": "Import UI components from '@botonic/webchat-react' instead of '@lilara/ui-web-react'."
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"name": "@lilara/ui-web",
|
|
18
|
+
"message": "Import UI components from '@botonic/webchat-react' instead of '@lilara/ui-web'."
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"patterns": [
|
|
22
|
+
{
|
|
23
|
+
"group": [
|
|
24
|
+
"@lilara/ui-web-react/*",
|
|
25
|
+
"!@lilara/ui-web-react/styles.css"
|
|
26
|
+
],
|
|
27
|
+
"message": "Import UI components from '@botonic/webchat-react' instead of '@lilara/ui-web-react'."
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"group": ["@lilara/ui-web/*"],
|
|
31
|
+
"message": "Import UI components from '@botonic/webchat-react' instead of '@lilara/ui-web'."
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|
|
8
37
|
},
|
|
9
38
|
{
|
|
10
39
|
"files": ["*.ts", "*.tsx"],
|
|
@@ -41,12 +41,7 @@ function App({
|
|
|
41
41
|
options: WebchatOptions
|
|
42
42
|
}) {
|
|
43
43
|
// Default avatar SVG
|
|
44
|
-
const defaultAvatarSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="
|
|
45
|
-
<circle cx="8.5" cy="9" r="8.5" fill="#24252C"/>
|
|
46
|
-
<path d="M5.9647 5.03898C5.9647 4.61514 5.80479 4.45386 5.36004 4.45386C4.90405 4.45386 4.74414 4.61639 4.74414 5.03898C4.74414 5.46281 4.90405 5.6241 5.36004 5.6241C5.80479 5.6241 5.9647 5.46281 5.9647 5.03898Z" fill="white"/>
|
|
47
|
-
<path d="M11.1872 4.45386C10.7312 4.45386 10.5713 4.61639 10.5713 5.03898C10.5713 5.46281 10.7312 5.6241 11.1872 5.6241C11.6307 5.6241 11.7919 5.46156 11.7919 5.03898C11.7906 4.61514 11.6307 4.45386 11.1872 4.45386Z" fill="white"/>
|
|
48
|
-
<path d="M10.99 6.47729H10.7063C10.4352 6.47729 10.3365 6.60233 10.2503 6.99995L9.32574 10.8498C9.15332 11.4975 8.95591 11.6726 8.40117 11.6726H8.13005C7.5878 11.6726 7.3779 11.4988 7.20548 10.8498L6.28092 6.99995C6.19471 6.60108 6.1085 6.47729 5.83737 6.47729H5.55376C5.30762 6.47729 5.19643 6.6636 5.29513 7.04996L6.37962 11.2112C6.56453 11.9339 6.93436 12.2953 7.56406 12.4315C7.72399 12.4691 7.8102 12.5566 7.8102 12.7304V14.5884C7.8102 14.7997 7.94638 14.9373 8.15504 14.9373H8.38993C8.58733 14.9373 8.73476 14.7997 8.73476 14.5884V12.7316C8.73476 12.5566 8.82097 12.4703 8.9809 12.4328C9.59686 12.2953 9.96793 11.9339 10.1641 11.2124L11.2486 7.05121C11.3473 6.66485 11.2361 6.47729 10.99 6.47729Z" fill="white"/>
|
|
49
|
-
</svg>`
|
|
44
|
+
const defaultAvatarSvg = `<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="16" height="16" rx="6" fill="#24252C"/><rect x="0.2" y="0.2" width="15.6" height="15.6" rx="5.8" stroke="white" stroke-opacity="0.2" stroke-width="0.4"/><path d="M7.94153 11.5381C8.09581 11.5381 8.20905 11.5664 8.28235 11.6396C8.35546 11.7129 8.38095 11.8235 8.38098 11.9688C8.38098 12.1147 8.35354 12.2258 8.27942 12.2988C8.20522 12.3717 8.09189 12.3994 7.94153 12.3994C7.78327 12.3994 7.66826 12.3719 7.59387 12.2988C7.51926 12.2255 7.49329 12.1143 7.49329 11.9688C7.49332 11.8227 7.52127 11.7117 7.5968 11.6387C7.67209 11.5659 7.78719 11.5381 7.94153 11.5381Z" fill="white" stroke="white" stroke-width="0.0694444"/><path d="M5.7464 3.29785C5.90068 3.29785 6.01392 3.32621 6.08722 3.39941C6.16033 3.47263 6.18582 3.58322 6.18585 3.72852C6.18585 3.87448 6.15839 3.98553 6.08429 4.05859C6.01009 4.13148 5.89676 4.15918 5.7464 4.15918C5.58813 4.15917 5.47313 4.13167 5.39874 4.05859C5.32414 3.98529 5.29816 3.87409 5.29816 3.72852C5.29819 3.58251 5.32614 3.47149 5.40167 3.39844C5.47696 3.32567 5.59206 3.29786 5.7464 3.29785Z" fill="white" stroke="white" stroke-width="0.0694444"/><path d="M10.0797 3.29785C10.234 3.29785 10.3472 3.32621 10.4205 3.39941C10.4936 3.47263 10.5191 3.58322 10.5192 3.72852C10.5192 3.87449 10.4917 3.98554 10.4176 4.05859C10.3434 4.13148 10.2301 4.15918 10.0797 4.15918C9.92145 4.15917 9.80644 4.13166 9.73206 4.05859C9.65744 3.9853 9.63147 3.87409 9.63147 3.72852C9.6315 3.5825 9.65945 3.47149 9.73499 3.39844C9.81027 3.32568 9.92538 3.29786 10.0797 3.29785Z" fill="white" stroke="white" stroke-width="0.0694444"/><path d="M6.29785 4.92285C6.39622 4.92286 6.46906 4.94612 6.52344 5.01172C6.57475 5.07369 6.60632 5.17037 6.63574 5.30469H6.63477L7.25879 7.89648L7.30371 8.04395C7.35035 8.17596 7.40297 8.26354 7.46875 8.32129C7.55517 8.39706 7.67153 8.42676 7.84961 8.42676H8.03418C8.21668 8.42676 8.33272 8.39686 8.41797 8.32129C8.50461 8.24437 8.56623 8.11445 8.625 7.89648L9.24805 5.30469L9.29785 5.12988C9.31646 5.08141 9.33846 5.04164 9.36523 5.01074C9.42164 4.94591 9.49655 4.92285 9.59473 4.92285H9.78809C9.88168 4.92285 9.95707 4.9593 9.99609 5.03809C10.0332 5.11348 10.0335 5.22116 9.99902 5.35449L9.26562 8.1582V8.15918C9.19723 8.40664 9.09972 8.59529 8.96387 8.73438C8.86165 8.83893 8.73882 8.91483 8.59277 8.96582L8.43848 9.00879C8.38813 9.02043 8.35392 9.03858 8.33203 9.06348C8.31053 9.08814 8.29688 9.12375 8.29688 9.17676V10.4229C8.29688 10.5029 8.2682 10.571 8.21875 10.6191C8.16946 10.6671 8.1018 10.6933 8.02637 10.6934H7.86621C7.78698 10.6934 7.71857 10.6677 7.66992 10.6191C7.62126 10.5705 7.5957 10.5021 7.5957 10.4229V9.17676C7.5957 9.12375 7.58205 9.08814 7.56055 9.06348C7.53862 9.03845 7.50373 9.02045 7.45312 9.00879V9.00781C7.23793 8.9604 7.06298 8.87439 6.92578 8.73535C6.82281 8.63087 6.74253 8.49757 6.68164 8.33301L6.62695 8.1582L5.89355 5.35449C5.8591 5.22116 5.85838 5.11348 5.89551 5.03809C5.93444 4.95924 6.01001 4.92295 6.10352 4.92285H6.29785Z" fill="white" stroke="white" stroke-width="0.0694444"/></svg>`
|
|
50
45
|
|
|
51
46
|
const avatarConfig = {
|
|
52
47
|
bot: {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BotonicContext, BotServerMessageFactory } from '@botonic/shared'
|
|
2
2
|
|
|
3
|
-
export async function NotFound({
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
export async function NotFound({ sendMessages }: BotonicContext) {
|
|
4
|
+
await sendMessages([
|
|
5
|
+
BotServerMessageFactory.createText({
|
|
6
|
+
text: 'Sorry, I didn\'t understand that.\n\nTry saying "hello" to get started!',
|
|
7
|
+
}),
|
|
8
|
+
])
|
|
8
9
|
|
|
9
10
|
return {
|
|
10
11
|
status: 200,
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BotonicContext, BotServerMessageFactory } from '@botonic/shared'
|
|
2
2
|
|
|
3
|
-
export async function Welcome({
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
export async function Welcome({ sendMessages }: BotonicContext) {
|
|
4
|
+
await sendMessages([
|
|
5
|
+
BotServerMessageFactory.createText({
|
|
6
|
+
text: `Hello! I'm <%= className %> 🤖\n\nWelcome to your new Botonic bot! You can start building your conversation flow by editing the routes and actions.`,
|
|
7
|
+
}),
|
|
8
|
+
])
|
|
8
9
|
|
|
9
10
|
return {
|
|
10
11
|
status: 200,
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
2
2
|
import { CoreBot } from '@botonic/core'
|
|
3
|
-
import {
|
|
3
|
+
import { BotonicContext, BotServerMessageFactory } from '@botonic/shared'
|
|
4
4
|
|
|
5
5
|
import { plugins } from './plugins'
|
|
6
6
|
import { routes } from './routes'
|
|
7
7
|
|
|
8
|
-
const DefaultFallbackAction = async ({
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
const DefaultFallbackAction = async ({ sendMessages }: BotonicContext) => {
|
|
9
|
+
await sendMessages([
|
|
10
|
+
BotServerMessageFactory.createText({
|
|
11
|
+
text: "I don't understand you",
|
|
12
|
+
}),
|
|
13
|
+
])
|
|
13
14
|
|
|
14
15
|
return {
|
|
15
16
|
status: 200,
|
|
@@ -17,10 +18,10 @@ const DefaultFallbackAction = async ({ sendMessage }: BotContext) => {
|
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
const defaultRoutes = (
|
|
21
|
+
const defaultRoutes = (botonicContext: BotonicContext) => [
|
|
21
22
|
{
|
|
22
23
|
path: '404',
|
|
23
|
-
action: async () => await DefaultFallbackAction(
|
|
24
|
+
action: async () => await DefaultFallbackAction(botonicContext),
|
|
24
25
|
},
|
|
25
26
|
]
|
|
26
27
|
|
|
@@ -35,9 +36,6 @@ export class NodeApp {
|
|
|
35
36
|
this.bot = new CoreBot(config)
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
input(args: any) {
|
|
39
|
-
return this.bot.input(args)
|
|
40
|
-
}
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
export const app = new NodeApp({ routes, plugins })
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AiAgentArgs, BotonicPluginAiAgents } from '@botonic/plugin-ai-agents'
|
|
2
|
-
import {
|
|
2
|
+
import { BotonicContext } from '@botonic/shared'
|
|
3
3
|
|
|
4
4
|
import { customTools } from '../../tools'
|
|
5
5
|
import { BotPlugins } from '../../types'
|
|
@@ -16,15 +16,15 @@ export const aiAgentsPlugin = hasAiAgentsConfig
|
|
|
16
16
|
: null
|
|
17
17
|
|
|
18
18
|
export async function getAiAgentResponse(
|
|
19
|
-
|
|
19
|
+
botonicContext: BotonicContext<BotPlugins>,
|
|
20
20
|
aiAgentArgs: AiAgentArgs
|
|
21
21
|
) {
|
|
22
|
-
const aiAgentPlugin =
|
|
22
|
+
const aiAgentPlugin = botonicContext.plugins.aiAgents
|
|
23
23
|
if (!aiAgentPlugin) {
|
|
24
24
|
throw new Error(
|
|
25
25
|
'AI Agents plugin is not configured. Please set AZURE_OPENAI_API_KEY or OPENAI_API_KEY environment variable.'
|
|
26
26
|
)
|
|
27
27
|
}
|
|
28
|
-
const response = await aiAgentPlugin.getInference(
|
|
28
|
+
const response = await aiAgentPlugin.getInference(botonicContext, aiAgentArgs)
|
|
29
29
|
return response
|
|
30
30
|
}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
BotonicPluginFlowBuilderOptions,
|
|
5
5
|
FlowBuilderJSONVersion,
|
|
6
6
|
} from '@botonic/plugin-flow-builder'
|
|
7
|
-
import {
|
|
7
|
+
import { BotonicContext } from '@botonic/shared'
|
|
8
8
|
|
|
9
9
|
import { trackEventToHubtypeAnalytics } from '../../tracking'
|
|
10
10
|
import { isLambdaLocal } from '../../utils'
|
|
@@ -14,14 +14,14 @@ export const flowBuilderConfig: BotonicPluginFlowBuilderOptions = {
|
|
|
14
14
|
flowVersion: isLambdaLocal()
|
|
15
15
|
? FlowBuilderJSONVersion.DRAFT
|
|
16
16
|
: FlowBuilderJSONVersion.LATEST,
|
|
17
|
-
trackEvent: async (
|
|
18
|
-
await trackEventToHubtypeAnalytics(
|
|
17
|
+
trackEvent: async (botonicContext: BotonicContext, eventAction, args) => {
|
|
18
|
+
await trackEventToHubtypeAnalytics(botonicContext, eventAction, args)
|
|
19
19
|
},
|
|
20
20
|
getAiAgentResponse: async (
|
|
21
|
-
|
|
21
|
+
botonicContext: BotonicContext,
|
|
22
22
|
aiAgentArgs: AiAgentArgs
|
|
23
23
|
) => {
|
|
24
|
-
return getAiAgentResponse(
|
|
24
|
+
return getAiAgentResponse(botonicContext, aiAgentArgs)
|
|
25
25
|
},
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { FlowBuilderAction } from '@botonic/plugin-flow-builder'
|
|
2
|
-
import {
|
|
2
|
+
import { BotonicContext } from '@botonic/shared'
|
|
3
3
|
|
|
4
4
|
import { Welcome, NotFound } from './actions'
|
|
5
5
|
|
|
6
|
-
export const routes = (
|
|
6
|
+
export const routes = (botonicContext: BotonicContext) => {
|
|
7
7
|
return [
|
|
8
8
|
{
|
|
9
9
|
text: /^(hi|hello|start|hola)$/i,
|
|
10
|
-
action: async () => await Welcome(
|
|
10
|
+
action: async () => await Welcome(botonicContext),
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
13
|
path: 'flow-builder',
|
|
14
14
|
text: /.*/,
|
|
15
15
|
payload: /.*/,
|
|
16
|
-
action: async () => await FlowBuilderAction.botonicInit(
|
|
16
|
+
action: async () => await FlowBuilderAction.botonicInit(botonicContext),
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
19
|
path: 'not-found',
|
|
20
|
-
action: async () => await NotFound(
|
|
20
|
+
action: async () => await NotFound(botonicContext),
|
|
21
21
|
},
|
|
22
22
|
]
|
|
23
23
|
}
|