Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Feature/Add tools marketplace #462

Merged
merged 2 commits into from
Jul 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions packages/server/marketplaces/tools/Add Hubspot Contact.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "add_contact_hubspot",
"description": "Add new contact to Hubspot",
"color": "linear-gradient(rgb(85,198,123), rgb(0,230,99))",
"iconSrc": "https://cdn.worldvectorlogo.com/logos/hubspot-1.svg",
"schema": "[{\"id\":1,\"property\":\"email\",\"description\":\"email address of contact\",\"type\":\"string\",\"required\":true},{\"id\":2,\"property\":\"firstname\",\"description\":\"first name of contact\",\"type\":\"string\",\"required\":false},{\"id\":3,\"property\":\"lastname\",\"description\":\"last name of contact\",\"type\":\"string\",\"required\":false}]",
"func": "const fetch = require('node-fetch');\nconst url = 'https://api.hubapi.com/crm/v3/objects/contacts'\nconst token = 'YOUR-TOKEN';\n\nconst body = {\n\t\"properties\": {\n\t \"email\": $email\n\t}\n};\n\nif ($firstname) body.properties.firstname = $firstname;\nif ($lastname) body.properties.lastname = $lastname;\n\nconst options = {\n\tmethod: 'POST',\n\theaders: {\n\t 'Authorization': `Bearer ${token}`,\n\t\t'Content-Type': 'application/json'\n\t},\n\tbody: JSON.stringify(body)\n};\n\ntry {\n\tconst response = await fetch(url, options);\n\tconst text = await response.text();\n\treturn text;\n} catch (error) {\n\tconsole.error(error);\n\treturn '';\n}"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "add_airtable",
"description": "Add column1, column2 to Airtable",
"color": "linear-gradient(rgb(125,71,222), rgb(128,102,23))",
"iconSrc": "https://raw.githubusercontent.com/gilbarbara/logos/main/logos/airtable.svg",
"schema": "[{\"id\":0,\"property\":\"column1\",\"description\":\"this is column1\",\"type\":\"string\",\"required\":true},{\"id\":1,\"property\":\"column2\",\"description\":\"this is column2\",\"type\":\"string\",\"required\":true}]",
"func": "const fetch = require('node-fetch');\nconst baseId = 'YOUR-BASE-ID';\nconst tableId = 'YOUR-TABLE-ID';\nconst token = 'YOUR-TOKEN';\n\nconst body = {\n\t\"records\": [\n\t\t{\n\t\t\t\"fields\": {\n\t\t\t\t\"column1\": $column1,\n\t\t\t\t\"column2\": $column2,\n\t\t\t}\n\t\t}\n\t]\n};\n\nconst options = {\n\tmethod: 'POST',\n\theaders: {\n\t\t'Authorization': `Bearer ${token}`,\n\t\t'Content-Type': 'application/json'\n\t},\n\tbody: JSON.stringify(body)\n};\n\nconst url = `https://api.airtable.com/v0/${baseId}/${tableId}`\n\ntry {\n\tconst response = await fetch(url, options);\n\tconst text = await response.text();\n\treturn text;\n} catch (error) {\n\tconsole.error(error);\n\treturn '';\n}"
}
8 changes: 8 additions & 0 deletions packages/server/marketplaces/tools/Get Stock Mover.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "get_stock_movers",
"description": "Get the stocks that has biggest price/volume moves, e.g. actives, gainers, losers, etc.",
"iconSrc": "https://rapidapi.com/cdn/images?url=https://rapidapi-prod-apis.s3.amazonaws.com/9c/e743343bdd41edad39a3fdffd5b974/016c33699f51603ae6fe4420c439124b.png",
"color": "linear-gradient(rgb(191,202,167), rgb(143,202,246))",
"schema": "[]",
"func": "const fetch = require('node-fetch');\nconst url = 'https://morning-star.p.rapidapi.com/market/v2/get-movers';\nconst options = {\n\tmethod: 'GET',\n\theaders: {\n\t\t'X-RapidAPI-Key': 'YOUR-API-KEY',\n\t\t'X-RapidAPI-Host': 'morning-star.p.rapidapi.com'\n\t}\n};\n\ntry {\n\tconst response = await fetch(url, options);\n\tconst result = await response.text();\n\tconsole.log(result);\n\treturn result;\n} catch (error) {\n\tconsole.error(error);\n\treturn '';\n}"
}
8 changes: 8 additions & 0 deletions packages/server/marketplaces/tools/Send Discord Message.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "send_message_to_discord_channel",
"description": "Send message to Discord channel",
"color": "linear-gradient(rgb(155,190,84), rgb(176,69,245))",
"iconSrc": "https://raw.githubusercontent.com/gilbarbara/logos/main/logos/discord-icon.svg",
"schema": "[{\"id\":1,\"property\":\"content\",\"description\":\"message to send\",\"type\":\"string\",\"required\":true}]",
"func": "const fetch = require('node-fetch');\nconst webhookUrl = 'YOUR-WEBHOOK-URL'\n\nconst body = {\n\t\"content\": $content\n};\n\nconst options = {\n\tmethod: 'POST',\n\theaders: {\n\t\t'Content-Type': 'application/json'\n\t},\n\tbody: JSON.stringify(body)\n};\n\nconst url = `${webhookUrl}?wait=true`\n\ntry {\n\tconst response = await fetch(url, options);\n\tconst text = await response.text();\n\treturn text;\n} catch (error) {\n\tconsole.error(error);\n\treturn '';\n}"
}
8 changes: 8 additions & 0 deletions packages/server/marketplaces/tools/Send Slack Message.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "send_message_to_slack_channel",
"description": "Send message to Slack channel",
"color": "linear-gradient(rgb(155,190,84), rgb(176,69,245))",
"iconSrc": "https://raw.githubusercontent.com/gilbarbara/logos/main/logos/slack-icon.svg",
"schema": "[{\"id\":1,\"property\":\"text\",\"description\":\"message to send\",\"type\":\"string\",\"required\":true}]",
"func": "const fetch = require('node-fetch');\nconst webhookUrl = 'YOUR-WEBHOOK-URL'\n\nconst body = {\n\t\"text\": $text\n};\n\nconst options = {\n\tmethod: 'POST',\n\theaders: {\n\t\t'Content-Type': 'application/json'\n\t},\n\tbody: JSON.stringify(body)\n};\n\nconst url = `${webhookUrl}`\n\ntry {\n\tconst response = await fetch(url, options);\n\tconst text = await response.text();\n\treturn text;\n} catch (error) {\n\tconsole.error(error);\n\treturn '';\n}"
}
8 changes: 8 additions & 0 deletions packages/server/marketplaces/tools/Send Teams Message.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "send_message_to_teams_channel",
"description": "Send message to Teams channel",
"color": "linear-gradient(rgb(155,190,84), rgb(176,69,245))",
"iconSrc": "https://raw.githubusercontent.com/gilbarbara/logos/main/logos/microsoft-teams.svg",
"schema": "[{\"id\":1,\"property\":\"content\",\"description\":\"message to send\",\"type\":\"string\",\"required\":true}]",
"func": "const fetch = require('node-fetch');\nconst webhookUrl = 'YOUR-WEBHOOK-URL'\n\nconst body = {\n\t\"content\": $content\n};\n\nconst options = {\n\tmethod: 'POST',\n\theaders: {\n\t\t'Content-Type': 'application/json'\n\t},\n\tbody: JSON.stringify(body)\n};\n\nconst url = `${webhookUrl}?wait=true`\n\ntry {\n\tconst response = await fetch(url, options);\n\tconst text = await response.text();\n\treturn text;\n} catch (error) {\n\tconsole.error(error);\n\treturn '';\n}"
}
8 changes: 8 additions & 0 deletions packages/server/marketplaces/tools/SendGrid Email.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "sendgrid_email",
"description": "Send email using SendGrid",
"color": "linear-gradient(rgb(230,108,70), rgb(222,4,98))",
"iconSrc": "https://raw.githubusercontent.com/gilbarbara/logos/main/logos/sendgrid-icon.svg",
"schema": "[{\"id\":0,\"property\":\"fromEmail\",\"description\":\"Email address used to send the message\",\"type\":\"string\",\"required\":true},{\"id\":1,\"property\":\"toEmail \",\"description\":\"The intended recipient's email address\",\"type\":\"string\",\"required\":true},{\"id\":2,\"property\":\"subject\",\"description\":\"The subject of email\",\"type\":\"string\",\"required\":true},{\"id\":3,\"property\":\"content\",\"description\":\"Content of email\",\"type\":\"string\",\"required\":true}]",
"func": "const fetch = require('node-fetch');\nconst url = 'https://api.sendgrid.com/v3/mail/send';\nconst api_key = 'YOUR-API-KEY';\n\nconst body = {\n \"personalizations\": [\n {\n \"to\": [{ \"email\": $toEmail }]\n }\n ],\n\t\"from\": {\n\t \"email\": $fromEmail\n\t},\n\t\"subject\": $subject,\n\t\"content\": [\n\t {\n\t \"type\": 'text/plain',\n\t \"value\": $content\n\t }\n\t]\n};\n\nconst options = {\n\tmethod: 'POST',\n\theaders: {\n\t 'Authorization': `Bearer ${api_key}`,\n\t\t'Content-Type': 'application/json'\n\t},\n\tbody: JSON.stringify(body)\n};\n\ntry {\n\tconst response = await fetch(url, options);\n\tconst text = await response.text();\n\treturn text;\n} catch (error) {\n\tconsole.error(error);\n\treturn '';\n}"
}
1 change: 1 addition & 0 deletions packages/server/src/Interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export interface ITool {
name: string
description: string
color: string
iconSrc?: string
schema?: string
func?: string
updatedDate: Date
Expand Down
3 changes: 3 additions & 0 deletions packages/server/src/entity/Tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export class Tool implements ITool {
@Column()
color: string

@Column({ nullable: true })
iconSrc?: string

@Column({ nullable: true })
schema?: string

Expand Down
25 changes: 22 additions & 3 deletions packages/server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -462,12 +462,12 @@ export class App {
// ----------------------------------------

// Get all chatflows for marketplaces
this.app.get('/api/v1/marketplaces', async (req: Request, res: Response) => {
const marketplaceDir = path.join(__dirname, '..', 'marketplaces')
this.app.get('/api/v1/marketplaces/chatflows', async (req: Request, res: Response) => {
const marketplaceDir = path.join(__dirname, '..', 'marketplaces', 'chatflows')
const jsonsInDir = fs.readdirSync(marketplaceDir).filter((file) => path.extname(file) === '.json')
const templates: any[] = []
jsonsInDir.forEach((file, index) => {
const filePath = path.join(__dirname, '..', 'marketplaces', file)
const filePath = path.join(__dirname, '..', 'marketplaces', 'chatflows', file)
const fileData = fs.readFileSync(filePath)
const fileDataObj = JSON.parse(fileData.toString())
const template = {
Expand All @@ -481,6 +481,25 @@ export class App {
return res.json(templates)
})

// Get all tools for marketplaces
this.app.get('/api/v1/marketplaces/tools', async (req: Request, res: Response) => {
const marketplaceDir = path.join(__dirname, '..', 'marketplaces', 'tools')
const jsonsInDir = fs.readdirSync(marketplaceDir).filter((file) => path.extname(file) === '.json')
const templates: any[] = []
jsonsInDir.forEach((file, index) => {
const filePath = path.join(__dirname, '..', 'marketplaces', 'tools', file)
const fileData = fs.readFileSync(filePath)
const fileDataObj = JSON.parse(fileData.toString())
const template = {
...fileDataObj,
id: index,
templateName: file.split('.json')[0]
}
templates.push(template)
})
return res.json(templates)
})

// ----------------------------------------
// API Keys
// ----------------------------------------
Expand Down
8 changes: 4 additions & 4 deletions packages/ui/public/index.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Flowise - LangchainJS UI</title>
<title>Flowise - Low-code LLM apps builder</title>
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<!-- Meta Tags-->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#2296f3" />
<meta name="title" content="Flowise - LangchainJS UI" />
<meta name="title" content="Flowise - Low-code LLM apps builder" />
<meta name="description" content="Flowise helps you to better integrate Web3 with existing Web2 applications" />
<meta name="keywords" content="react, material-ui, reactjs, reactjs, workflow automation, web3, web2, blockchain" />
<meta name="author" content="CodedThemes" />
Expand All @@ -17,13 +17,13 @@
<meta property="og:url" content="https://flowiseai.com/" />
<meta property="og:site_name" content="flowiseai.com" />
<meta property="article:publisher" content="https://www.facebook.com/codedthemes" />
<meta property="og:title" content="Flowise - LangchainJS UI" />
<meta property="og:title" content="Flowise - Low-code LLM apps builder" />
<meta property="og:description" content="Flowise helps you to better build LLM flows using Langchain in simple GUI" />
<meta property="og:image" content="https://flowiseai.com/og-image/og-facebook.png" />
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content="https://flowiseai.com" />
<meta property="twitter:title" content="Flowise - LangchainJS UI" />
<meta property="twitter:title" content="Flowise - Low-code LLM apps builder" />
<meta property="twitter:description" content="Flowise helps you to better build LLM flows using Langchain in simple GUI" />
<meta property="twitter:image" content="https://flowiseai.com/og-image/og-twitter.png" />
<meta name="twitter:creator" content="@codedthemes" />
Expand Down
6 changes: 4 additions & 2 deletions packages/ui/src/api/marketplaces.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import client from './client'

const getAllMarketplaces = () => client.get('/marketplaces')
const getAllChatflowsMarketplaces = () => client.get('/marketplaces/chatflows')
const getAllToolsMarketplaces = () => client.get('/marketplaces/tools')

export default {
getAllMarketplaces
getAllChatflowsMarketplaces,
getAllToolsMarketplaces
}
3 changes: 3 additions & 0 deletions packages/ui/src/themes/compStyleOverride.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ export default function componentStyleOverrides(theme) {
'&::placeholder': {
color: theme.darkTextSecondary,
fontSize: '0.875rem'
},
'&.Mui-disabled': {
WebkitTextFillColor: theme?.customization?.isDarkMode ? theme.colors?.grey500 : theme.darkTextSecondary
}
}
}
Expand Down
23 changes: 18 additions & 5 deletions packages/ui/src/ui-component/cards/ItemCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const CardWrapper = styled(MainCard)(({ theme }) => ({

// ===========================|| CONTRACT CARD ||=========================== //

const ItemCard = ({ isLoading, data, images, color, onClick }) => {
const ItemCard = ({ isLoading, data, images, onClick }) => {
return (
<>
{isLoading ? (
Expand All @@ -43,21 +43,35 @@ const ItemCard = ({ isLoading, data, images, color, onClick }) => {
alignItems: 'center'
}}
>
{color && (
{data.iconSrc && (
<div
style={{
width: 35,
height: 35,
marginRight: 10,
borderRadius: '50%',
background: color
background: `url(${data.iconSrc})`,
backgroundSize: 'contain',
backgroundRepeat: 'no-repeat',
backgroundPosition: 'center center'
}}
></div>
)}
{!data.iconSrc && data.color && (
<div
style={{
width: 35,
height: 35,
marginRight: 10,
borderRadius: '50%',
background: data.color
}}
></div>
)}
<Typography
sx={{ fontSize: '1.5rem', fontWeight: 500, overflowWrap: 'break-word', whiteSpace: 'pre-line' }}
>
{data.name}
{data.templateName || data.name}
</Typography>
</div>
{data.description && (
Expand Down Expand Up @@ -107,7 +121,6 @@ ItemCard.propTypes = {
isLoading: PropTypes.bool,
data: PropTypes.object,
images: PropTypes.array,
color: PropTypes.string,
onClick: PropTypes.func
}

Expand Down
14 changes: 10 additions & 4 deletions packages/ui/src/ui-component/grid/Grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,26 @@ import { DataGrid } from '@mui/x-data-grid'
import { IconPlus } from '@tabler/icons'
import { Button } from '@mui/material'

export const Grid = ({ columns, rows, style, onRowUpdate, addNewRow }) => {
export const Grid = ({ columns, rows, style, disabled = false, onRowUpdate, addNewRow }) => {
const handleProcessRowUpdate = (newRow) => {
onRowUpdate(newRow)
return newRow
}

return (
<>
<Button variant='outlined' onClick={addNewRow} startIcon={<IconPlus />}>
Add Item
</Button>
{!disabled && (
<Button variant='outlined' onClick={addNewRow} startIcon={<IconPlus />}>
Add Item
</Button>
)}
{rows && columns && (
<div style={{ marginTop: 10, height: 300, width: '100%', ...style }}>
<DataGrid
processRowUpdate={handleProcessRowUpdate}
isCellEditable={() => {
return !disabled
}}
onProcessRowUpdateError={(error) => console.error(error)}
rows={rows}
columns={columns}
Expand All @@ -32,6 +37,7 @@ Grid.propTypes = {
rows: PropTypes.array,
columns: PropTypes.array,
style: PropTypes.any,
disabled: PropTypes.bool,
addNewRow: PropTypes.func,
onRowUpdate: PropTypes.func
}
Loading