diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts
index 34e461f7..cd964bed 100644
--- a/packages/server/src/index.ts
+++ b/packages/server/src/index.ts
@@ -140,6 +140,7 @@ export class App {
'/api/v1/verify/apikey/',
'/api/v1/chatflows/apikey/',
'/api/v1/public-chatflows',
+ '/api/v1/public-chatbotConfig',
'/api/v1/prediction/',
'/api/v1/vector/upsert/',
'/api/v1/node-icon/',
@@ -202,7 +203,7 @@ export class App {
// Get component credential via name
this.app.get('/api/v1/components-credentials/:name', (req: Request, res: Response) => {
- if (!req.params.name.includes('&')) {
+ if (!req.params.name.includes('&')) {
if (Object.prototype.hasOwnProperty.call(this.nodesPool.componentCredentials, req.params.name)) {
return res.json(this.nodesPool.componentCredentials[req.params.name])
} else {
@@ -210,7 +211,7 @@ export class App {
}
} else {
const returnResponse = []
- for (const name of req.params.name.split('&')) {
+ for (const name of req.params.name.split('&')) {
if (Object.prototype.hasOwnProperty.call(this.nodesPool.componentCredentials, name)) {
returnResponse.push(this.nodesPool.componentCredentials[name])
} else {
@@ -330,6 +331,23 @@ export class App {
return res.status(404).send(`Chatflow ${req.params.id} not found`)
})
+ // Get specific chatflow chatbotConfig via id (PUBLIC endpoint, used to retrieve config for embedded chat)
+ // Safe as public endpoint as chatbotConfig doesn't contain sensitive credential
+ this.app.get('/api/v1/public-chatbotConfig/:id', async (req: Request, res: Response) => {
+ const chatflow = await this.AppDataSource.getRepository(ChatFlow).findOneBy({
+ id: req.params.id
+ })
+ if (chatflow && chatflow.chatbotConfig) {
+ try {
+ const parsedConfig = JSON.parse(chatflow.chatbotConfig)
+ return res.json(parsedConfig)
+ } catch (e) {
+ return res.status(500).send(`Error parsing Chatbot Config for Chatflow ${req.params.id}`)
+ }
+ }
+ return res.status(404).send(`Chatbot Config for Chatflow ${req.params.id} not found`)
+ })
+
// Save chatflow
this.app.post('/api/v1/chatflows', async (req: Request, res: Response) => {
const body = req.body
diff --git a/packages/server/src/utils/XSS.ts b/packages/server/src/utils/XSS.ts
index 3e96e6c8..5d8b81e9 100644
--- a/packages/server/src/utils/XSS.ts
+++ b/packages/server/src/utils/XSS.ts
@@ -6,8 +6,15 @@ export function sanitizeMiddleware(req: Request, res: Response, next: NextFuncti
const decodedURI = decodeURI(req.url)
req.url = sanitizeHtml(decodedURI)
for (let p in req.query) {
- req.query[p] = sanitizeHtml(req.query[p] as string)
+ if (Array.isArray(req.query[p])) {
+ const sanitizedQ = []
+ for (const q of req.query[p] as string[]) {
+ sanitizedQ.push(sanitizeHtml(q))
+ }
+ req.query[p] = sanitizedQ
+ } else {
+ req.query[p] = sanitizeHtml(req.query[p] as string)
+ }
}
-
next()
}
diff --git a/packages/ui/src/menu-items/settings.js b/packages/ui/src/menu-items/settings.js
index 307bd0bd..1e0f58dd 100644
--- a/packages/ui/src/menu-items/settings.js
+++ b/packages/ui/src/menu-items/settings.js
@@ -1,8 +1,8 @@
// assets
-import { IconTrash, IconFileUpload, IconFileExport, IconCopy, IconSearch, IconMessage } from '@tabler/icons'
+import { IconTrash, IconFileUpload, IconFileExport, IconCopy, IconSearch, IconMessage, IconPictureInPictureOff } from '@tabler/icons'
// constant
-const icons = { IconTrash, IconFileUpload, IconFileExport, IconCopy, IconSearch, IconMessage }
+const icons = { IconTrash, IconFileUpload, IconFileExport, IconCopy, IconSearch, IconMessage, IconPictureInPictureOff }
// ==============================|| SETTINGS MENU ITEMS ||============================== //
@@ -11,6 +11,13 @@ const settings = {
title: '',
type: 'group',
children: [
+ {
+ id: 'conversationStarters',
+ title: 'Starter Prompts',
+ type: 'item',
+ url: '',
+ icon: icons.IconPictureInPictureOff
+ },
{
id: 'viewMessages',
title: 'View Messages',
diff --git a/packages/ui/src/ui-component/button/FlowListMenu.js b/packages/ui/src/ui-component/button/FlowListMenu.js
index 94ecdd01..16bc86f2 100644
--- a/packages/ui/src/ui-component/button/FlowListMenu.js
+++ b/packages/ui/src/ui-component/button/FlowListMenu.js
@@ -11,6 +11,7 @@ import FileCopyIcon from '@mui/icons-material/FileCopy'
import FileDownloadIcon from '@mui/icons-material/Downloading'
import FileDeleteIcon from '@mui/icons-material/Delete'
import FileCategoryIcon from '@mui/icons-material/Category'
+import PictureInPictureAltIcon from '@mui/icons-material/PictureInPictureAlt'
import Button from '@mui/material/Button'
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'
import { IconX } from '@tabler/icons'
@@ -27,6 +28,7 @@ import TagDialog from '../dialog/TagDialog'
import { generateExportFlowData } from '../../utils/genericHelper'
import useNotifier from '../../utils/useNotifier'
+import StarterPromptsDialog from '../dialog/StarterPromptsDialog'
const StyledMenu = styled((props) => (