mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-22 20:37:48 +00:00
4.8.8 test fix (#2149)
* perf: code comment * feat: system plugin input guide * perf: variable avatar * feat: feishu webhook * perf: select tool config tip * perf: rename variable * fix: per inherit error * perf: docker-compose oneapi version and i18n * perf: ui tip bug * fix: ts * perf: pg log * perf: editor color * perf: update init
This commit is contained in:
2
.github/workflows/preview-image.yml
vendored
2
.github/workflows/preview-image.yml
vendored
@@ -7,7 +7,7 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-fastgpt-images:
|
preview-fastgpt-images:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
@@ -16,19 +16,35 @@ weight: 816
|
|||||||
- fastgpt 镜像 tag 修改成 v4.8.8-alpha
|
- fastgpt 镜像 tag 修改成 v4.8.8-alpha
|
||||||
- 商业版镜像 tag 修改成 v4.8.8-alpha
|
- 商业版镜像 tag 修改成 v4.8.8-alpha
|
||||||
|
|
||||||
|
### 3. 执行初始化
|
||||||
|
|
||||||
|
从任意终端,发起 1 个 HTTP 请求。其中 {{rootkey}} 替换成环境变量里的 `rootkey`;{{host}} 替换成**FastGPT 域名**。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl --location --request POST 'https://{{host}}/api/admin/initv48 8' \
|
||||||
|
--header 'rootkey: {{rootkey}}' \
|
||||||
|
--header 'Content-Type: application/json'
|
||||||
|
```
|
||||||
|
|
||||||
|
会初始化知识库的继承权限
|
||||||
|
|
||||||
-------
|
-------
|
||||||
|
|
||||||
## V4.8.8 更新说明
|
## V4.8.8 更新说明
|
||||||
|
|
||||||
1. 新增 - 重构系统插件的结构。允许向开源社区 PR 系统插件,具体可见: [如何向 FastGPT 社区提交系统插件](https://fael3z0zfze.feishu.cn/wiki/ERZnw9R26iRRG0kXZRec6WL9nwh)。
|
1. 新增 - 重构系统插件的结构。允许向开源社区 PR 系统插件,具体可见: [如何向 FastGPT 社区提交系统插件](https://fael3z0zfze.feishu.cn/wiki/ERZnw9R26iRRG0kXZRec6WL9nwh)。
|
||||||
2. 新增 - DuckDuckGo 系统插件。
|
2. 新增 - DuckDuckGo 系统插件。
|
||||||
3. 新增 - 修改变量填写方式。提示词输入框以以及工作流中所有 Textarea 输入框,支持输入 / 唤起变量选择,可直接选择所有上游输出值,无需动态引入。
|
3. 新增 - 飞书 webhook 系统插件。
|
||||||
4. 优化 - 移动端快速切换应用交互。
|
4. 新增 - 修改变量填写方式。提示词输入框以以及工作流中所有 Textarea 输入框,支持输入 / 唤起变量选择,可直接选择所有上游输出值,无需动态引入。
|
||||||
5. 优化 - 节点图标。
|
5. 商业版新增 - 知识库权限继承。
|
||||||
6. 优化 - 对话框引用增加额外复制案件,便于复制。增加引用内容折叠。
|
6. 优化 - 移动端快速切换应用交互。
|
||||||
7. 优化 - 对话框底部增加复制,简便复制交互,无需滚动到消息开头。
|
7. 优化 - 节点图标。
|
||||||
8. 优化 - OpenAI sdk 升级,并自定义了 whisper 模型接口(未仔细查看 sdk 实现,但 sdk 中 whisper 接口,似乎无法适配一般 fastapi 接口)
|
8. 优化 - 对话框引用增加额外复制案件,便于复制。增加引用内容折叠。
|
||||||
9. 修复 - Permission 表声明问题。
|
9. 优化 - 对话框底部增加复制,简便复制交互,无需滚动到消息开头。
|
||||||
10. 修复 - 并行执行节点,运行时间未正确记录。
|
10. 优化 - OpenAI sdk 升级,并自定义了 whisper 模型接口(未仔细查看 sdk 实现,但 sdk 中 whisper 接口,似乎无法适配一般 fastapi 接口)
|
||||||
11. 修复 - 简易模式,首次进入,无法正确获取知识库配置。
|
11. 修复 - Permission 表声明问题。
|
||||||
12. 修复 - Log debug level 配置无效。
|
12. 修复 - 并行执行节点,运行时间未正确记录。
|
||||||
|
13. 修复 - 运行详情未正确展示嵌套节点信息。
|
||||||
|
14. 修复 - 简易模式,首次进入,无法正确获取知识库配置。
|
||||||
|
15. 修复 - Log debug level 配置无效。
|
||||||
|
16. 修复 - 插件独立运行时,会将插件输入的值进行变量替换,可能导致后续节点变量异常。
|
@@ -179,7 +179,7 @@ services:
|
|||||||
- ./mysql:/var/lib/mysql
|
- ./mysql:/var/lib/mysql
|
||||||
oneapi:
|
oneapi:
|
||||||
container_name: oneapi
|
container_name: oneapi
|
||||||
image: ghcr.io/songquanpeng/one-api:latest
|
image: ghcr.io/songquanpeng/one-api:0.6.7
|
||||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/one-api:v0.6.6 # 阿里云
|
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/one-api:v0.6.6 # 阿里云
|
||||||
ports:
|
ports:
|
||||||
- 3001:3000
|
- 3001:3000
|
||||||
|
@@ -136,7 +136,7 @@ services:
|
|||||||
- ./mysql:/var/lib/mysql
|
- ./mysql:/var/lib/mysql
|
||||||
oneapi:
|
oneapi:
|
||||||
container_name: oneapi
|
container_name: oneapi
|
||||||
image: ghcr.io/songquanpeng/one-api:latest
|
image: ghcr.io/songquanpeng/one-api:0.6.7
|
||||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/one-api:v0.6.6 # 阿里云
|
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/one-api:v0.6.6 # 阿里云
|
||||||
ports:
|
ports:
|
||||||
- 3001:3000
|
- 3001:3000
|
||||||
|
@@ -117,7 +117,7 @@ services:
|
|||||||
- ./mysql:/var/lib/mysql
|
- ./mysql:/var/lib/mysql
|
||||||
oneapi:
|
oneapi:
|
||||||
container_name: oneapi
|
container_name: oneapi
|
||||||
image: ghcr.io/songquanpeng/one-api:latest
|
image: ghcr.io/songquanpeng/one-api:0.6.7
|
||||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/one-api:v0.6.6 # 阿里云
|
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/one-api:v0.6.6 # 阿里云
|
||||||
ports:
|
ports:
|
||||||
- 3001:3000
|
- 3001:3000
|
||||||
|
@@ -6,27 +6,29 @@ import { getAppChatConfig } from '../workflow/utils';
|
|||||||
import { StoreNodeItemType } from '../workflow/type/node';
|
import { StoreNodeItemType } from '../workflow/type/node';
|
||||||
import { DatasetSearchModeEnum } from '../dataset/constants';
|
import { DatasetSearchModeEnum } from '../dataset/constants';
|
||||||
|
|
||||||
export const getDefaultAppForm = (): AppSimpleEditFormType => ({
|
export const getDefaultAppForm = (): AppSimpleEditFormType => {
|
||||||
aiSettings: {
|
return {
|
||||||
model: 'gpt-4o-mini',
|
aiSettings: {
|
||||||
systemPrompt: '',
|
model: 'gpt-4o-mini',
|
||||||
temperature: 0,
|
systemPrompt: '',
|
||||||
isResponseAnswerText: true,
|
temperature: 0,
|
||||||
maxHistories: 6,
|
isResponseAnswerText: true,
|
||||||
maxToken: 4000
|
maxHistories: 6,
|
||||||
},
|
maxToken: 4000
|
||||||
dataset: {
|
},
|
||||||
datasets: [],
|
dataset: {
|
||||||
similarity: 0.4,
|
datasets: [],
|
||||||
limit: 1500,
|
similarity: 0.4,
|
||||||
searchMode: DatasetSearchModeEnum.embedding,
|
limit: 1500,
|
||||||
usingReRank: false,
|
searchMode: DatasetSearchModeEnum.embedding,
|
||||||
datasetSearchUsingExtensionQuery: false,
|
usingReRank: false,
|
||||||
datasetSearchExtensionBg: ''
|
datasetSearchUsingExtensionQuery: true,
|
||||||
},
|
datasetSearchExtensionBg: ''
|
||||||
selectedTools: [],
|
},
|
||||||
chatConfig: {}
|
selectedTools: [],
|
||||||
});
|
chatConfig: {}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/* format app nodes to edit form */
|
/* format app nodes to edit form */
|
||||||
export const appWorkflow2Form = ({
|
export const appWorkflow2Form = ({
|
||||||
|
@@ -6,6 +6,7 @@ export enum FlowNodeTemplateTypeEnum {
|
|||||||
|
|
||||||
search = 'search',
|
search = 'search',
|
||||||
multimodal = 'multimodal',
|
multimodal = 'multimodal',
|
||||||
|
communication = 'communication',
|
||||||
|
|
||||||
other = 'other',
|
other = 'other',
|
||||||
teamApp = 'teamApp'
|
teamApp = 'teamApp'
|
||||||
|
@@ -35,6 +35,7 @@ export type WorkflowTemplateType = {
|
|||||||
avatar: string;
|
avatar: string;
|
||||||
intro?: string;
|
intro?: string;
|
||||||
author?: string;
|
author?: string;
|
||||||
|
inputExplanationUrl?: string;
|
||||||
version: string;
|
version: string;
|
||||||
|
|
||||||
showStatus?: boolean;
|
showStatus?: boolean;
|
||||||
|
1
packages/global/core/workflow/type/node.d.ts
vendored
1
packages/global/core/workflow/type/node.d.ts
vendored
@@ -31,6 +31,7 @@ export type FlowNodeCommonType = {
|
|||||||
avatar?: string;
|
avatar?: string;
|
||||||
name: string;
|
name: string;
|
||||||
intro?: string; // template list intro
|
intro?: string; // template list intro
|
||||||
|
inputExplanationUrl?: string;
|
||||||
showStatus?: boolean; // chatting response step status
|
showStatus?: boolean; // chatting response step status
|
||||||
version: string;
|
version: string;
|
||||||
|
|
||||||
|
@@ -229,7 +229,7 @@ export const updatePluginInputByVariables = (
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const filterPluginInputVariables = (
|
export const removePluginInputVariables = (
|
||||||
variables: Record<string, any>,
|
variables: Record<string, any>,
|
||||||
nodes: RuntimeNodeItemType[]
|
nodes: RuntimeNodeItemType[]
|
||||||
) => {
|
) => {
|
||||||
@@ -268,6 +268,7 @@ export function replaceVariableLabel({
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Upstream node outputs
|
||||||
const nodeVariables = nodes
|
const nodeVariables = nodes
|
||||||
.map((node) => {
|
.map((node) => {
|
||||||
return node.outputs.map((output) => {
|
return node.outputs.map((output) => {
|
||||||
@@ -280,6 +281,7 @@ export function replaceVariableLabel({
|
|||||||
})
|
})
|
||||||
.flat();
|
.flat();
|
||||||
|
|
||||||
|
// Get runningNode inputs(Will be replaced with reference)
|
||||||
const customInputs = runningNode.inputs.flatMap((item) => {
|
const customInputs = runningNode.inputs.flatMap((item) => {
|
||||||
if (Array.isArray(item.value)) {
|
if (Array.isArray(item.value)) {
|
||||||
return [
|
return [
|
||||||
@@ -299,6 +301,7 @@ export function replaceVariableLabel({
|
|||||||
|
|
||||||
const allVariables = [...globalVariables, ...nodeVariables, ...customInputs];
|
const allVariables = [...globalVariables, ...nodeVariables, ...customInputs];
|
||||||
|
|
||||||
|
// Replace {{$xxx.xxx$}} to value
|
||||||
for (const key in allVariables) {
|
for (const key in allVariables) {
|
||||||
const val = allVariables[key];
|
const val = allVariables[key];
|
||||||
const regex = new RegExp(`\\{\\{\\$(${val.nodeId}\\.${val.id})\\$\\}\\}`, 'g');
|
const regex = new RegExp(`\\{\\{\\$(${val.nodeId}\\.${val.id})\\$\\}\\}`, 'g');
|
||||||
|
@@ -7,7 +7,14 @@ import { cloneDeep } from 'lodash';
|
|||||||
import { WorkerNameEnum, runWorker } from '@fastgpt/service/worker/utils';
|
import { WorkerNameEnum, runWorker } from '@fastgpt/service/worker/utils';
|
||||||
|
|
||||||
// Run in main thread
|
// Run in main thread
|
||||||
const staticPluginList = ['getTime', 'fetchUrl', 'Doc2X', 'Doc2X/URLPDF2text', 'Doc2X/URLImg2text'];
|
const staticPluginList = [
|
||||||
|
'getTime',
|
||||||
|
'fetchUrl',
|
||||||
|
'Doc2X',
|
||||||
|
'Doc2X/URLPDF2text',
|
||||||
|
'Doc2X/URLImg2text',
|
||||||
|
'feishu'
|
||||||
|
];
|
||||||
// Run in worker thread (Have npm packages)
|
// Run in worker thread (Have npm packages)
|
||||||
const packagePluginList = [
|
const packagePluginList = [
|
||||||
'mathExprVal',
|
'mathExprVal',
|
||||||
|
@@ -1,9 +1,10 @@
|
|||||||
{
|
{
|
||||||
"author": "",
|
"author": "Menghuan1918",
|
||||||
"version": "488",
|
"version": "488",
|
||||||
"name": "Doc2X 图像(URL)识别",
|
"name": "Doc2X 图像(URL)识别",
|
||||||
"avatar": "plugins/doc2x",
|
"avatar": "plugins/doc2x",
|
||||||
"intro": "将传入的图片(URL)发送至Doc2X进行解析,返回带LaTeX公式的markdown格式的文本",
|
"intro": "将传入的图片(URL)发送至Doc2X进行解析,返回带LaTeX公式的markdown格式的文本",
|
||||||
|
"inputExplanationUrl": "https://fael3z0zfze.feishu.cn/wiki/Rkc5witXWiJoi5kORd2cofh6nDg?fromScene=spaceOverview",
|
||||||
"showStatus": true,
|
"showStatus": true,
|
||||||
"weight": 10,
|
"weight": 10,
|
||||||
|
|
||||||
|
@@ -1,9 +1,10 @@
|
|||||||
{
|
{
|
||||||
"author": "",
|
"author": "Menghuan1918",
|
||||||
"version": "488",
|
"version": "488",
|
||||||
"name": "Doc2X PDF文件(URL)识别",
|
"name": "Doc2X PDF文件(URL)识别",
|
||||||
"avatar": "plugins/doc2x",
|
"avatar": "plugins/doc2x",
|
||||||
"intro": "将传入的PDF文件(URL)发送至Doc2X进行解析,返回带LaTeX公式的markdown格式的文本",
|
"intro": "将传入的PDF文件(URL)发送至Doc2X进行解析,返回带LaTeX公式的markdown格式的文本",
|
||||||
|
"inputExplanationUrl": "https://fael3z0zfze.feishu.cn/wiki/Rkc5witXWiJoi5kORd2cofh6nDg?fromScene=spaceOverview",
|
||||||
"showStatus": true,
|
"showStatus": true,
|
||||||
"weight": 10,
|
"weight": 10,
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"author": "",
|
"author": "Menghuan1918",
|
||||||
"version": "488",
|
"version": "488",
|
||||||
"name": "Doc2X服务",
|
"name": "Doc2X服务",
|
||||||
"avatar": "plugins/doc2x",
|
"avatar": "plugins/doc2x",
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
"avatar": "core/workflow/template/duckduckgo",
|
"avatar": "core/workflow/template/duckduckgo",
|
||||||
"intro": "DuckDuckGo 服务,包含网络搜索、图片搜索、新闻搜索等。",
|
"intro": "DuckDuckGo 服务,包含网络搜索、图片搜索、新闻搜索等。",
|
||||||
"showStatus": false,
|
"showStatus": false,
|
||||||
"weight": 10,
|
"weight": 100,
|
||||||
|
|
||||||
"isTool": true,
|
"isTool": true,
|
||||||
"templateType": "tools",
|
"templateType": "tools",
|
||||||
|
443
packages/plugins/src/feishu/template.json
Normal file
443
packages/plugins/src/feishu/template.json
Normal file
@@ -0,0 +1,443 @@
|
|||||||
|
{
|
||||||
|
"author": "",
|
||||||
|
"version": "488",
|
||||||
|
"name": "飞书机器人 webhook",
|
||||||
|
"avatar": "/imgs/app/templates/feishu.svg",
|
||||||
|
"intro": "向飞书机器人发起 webhook 请求。",
|
||||||
|
"inputExplanationUrl": "https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot#f62e72d5",
|
||||||
|
"showStatus": false,
|
||||||
|
"weight": 10,
|
||||||
|
|
||||||
|
"isTool": true,
|
||||||
|
"templateType": "communication",
|
||||||
|
|
||||||
|
"workflow": {
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"nodeId": "pluginInput",
|
||||||
|
"name": "自定义插件输入",
|
||||||
|
"intro": "可以配置插件需要哪些输入,利用这些输入来运行插件",
|
||||||
|
"avatar": "core/workflow/template/workflowStart",
|
||||||
|
"flowNodeType": "pluginInput",
|
||||||
|
"showStatus": false,
|
||||||
|
"position": {
|
||||||
|
"x": 156.37657136084977,
|
||||||
|
"y": 90.73380846709256
|
||||||
|
},
|
||||||
|
"version": "481",
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"renderTypeList": ["reference"],
|
||||||
|
"selectedTypeIndex": 0,
|
||||||
|
"valueType": "string",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "content",
|
||||||
|
"label": "content",
|
||||||
|
"description": "需要发送的消息",
|
||||||
|
"required": true,
|
||||||
|
"toolDescription": "需要发送的消息"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"renderTypeList": ["input"],
|
||||||
|
"selectedTypeIndex": 0,
|
||||||
|
"valueType": "string",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "hook_url",
|
||||||
|
"label": "hook_url",
|
||||||
|
"description": "飞书机器人地址",
|
||||||
|
"required": true,
|
||||||
|
"defaultValue": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"id": "query",
|
||||||
|
"valueType": "string",
|
||||||
|
"key": "content",
|
||||||
|
"label": "content",
|
||||||
|
"type": "hidden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hook_url",
|
||||||
|
"valueType": "string",
|
||||||
|
"key": "hook_url",
|
||||||
|
"label": "hook_url",
|
||||||
|
"type": "hidden"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nodeId": "pluginOutput",
|
||||||
|
"name": "自定义插件输出",
|
||||||
|
"intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出",
|
||||||
|
"avatar": "core/workflow/template/pluginOutput",
|
||||||
|
"flowNodeType": "pluginOutput",
|
||||||
|
"showStatus": false,
|
||||||
|
"position": {
|
||||||
|
"x": 2110.7223589692912,
|
||||||
|
"y": 120.17602722162474
|
||||||
|
},
|
||||||
|
"version": "481",
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"renderTypeList": ["reference"],
|
||||||
|
"valueType": "object",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "result",
|
||||||
|
"label": "result",
|
||||||
|
"description": "",
|
||||||
|
"value": ["vzreK6vHrPvZ", "httpRawResponse"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nodeId": "vzreK6vHrPvZ",
|
||||||
|
"name": "HTTP 请求",
|
||||||
|
"intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)",
|
||||||
|
"avatar": "core/workflow/template/httpRequest",
|
||||||
|
"flowNodeType": "httpRequest468",
|
||||||
|
"showStatus": true,
|
||||||
|
"position": {
|
||||||
|
"x": 1363.4233257919495,
|
||||||
|
"y": -182.3490463845037
|
||||||
|
},
|
||||||
|
"version": "481",
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"key": "system_addInputParam",
|
||||||
|
"renderTypeList": ["addInputParam"],
|
||||||
|
"valueType": "dynamic",
|
||||||
|
"label": "",
|
||||||
|
"required": false,
|
||||||
|
"description": "core.module.input.description.HTTP Dynamic Input",
|
||||||
|
"customInputConfig": {
|
||||||
|
"selectValueTypeList": [
|
||||||
|
"string",
|
||||||
|
"number",
|
||||||
|
"boolean",
|
||||||
|
"object",
|
||||||
|
"arrayString",
|
||||||
|
"arrayNumber",
|
||||||
|
"arrayBoolean",
|
||||||
|
"arrayObject",
|
||||||
|
"any",
|
||||||
|
"chatHistory",
|
||||||
|
"datasetQuote",
|
||||||
|
"dynamic",
|
||||||
|
"selectApp",
|
||||||
|
"selectDataset"
|
||||||
|
],
|
||||||
|
"showDescription": false,
|
||||||
|
"showDefaultValue": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpMethod",
|
||||||
|
"renderTypeList": ["custom"],
|
||||||
|
"valueType": "string",
|
||||||
|
"label": "",
|
||||||
|
"value": "POST",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpReqUrl",
|
||||||
|
"renderTypeList": ["hidden"],
|
||||||
|
"valueType": "string",
|
||||||
|
"label": "",
|
||||||
|
"description": "core.module.input.description.Http Request Url",
|
||||||
|
"placeholder": "https://api.ai.com/getInventory",
|
||||||
|
"required": false,
|
||||||
|
"value": "{{url}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpHeader",
|
||||||
|
"renderTypeList": ["custom"],
|
||||||
|
"valueType": "any",
|
||||||
|
"value": [],
|
||||||
|
"label": "",
|
||||||
|
"description": "core.module.input.description.Http Request Header",
|
||||||
|
"placeholder": "core.module.input.description.Http Request Header",
|
||||||
|
"required": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpParams",
|
||||||
|
"renderTypeList": ["hidden"],
|
||||||
|
"valueType": "any",
|
||||||
|
"value": [],
|
||||||
|
"label": "",
|
||||||
|
"required": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpJsonBody",
|
||||||
|
"renderTypeList": ["hidden"],
|
||||||
|
"valueType": "any",
|
||||||
|
"value": "{{content}}",
|
||||||
|
"label": "",
|
||||||
|
"required": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"renderTypeList": ["reference"],
|
||||||
|
"valueType": "string",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "url",
|
||||||
|
"label": "url",
|
||||||
|
"customInputConfig": {
|
||||||
|
"selectValueTypeList": [
|
||||||
|
"string",
|
||||||
|
"number",
|
||||||
|
"boolean",
|
||||||
|
"object",
|
||||||
|
"arrayString",
|
||||||
|
"arrayNumber",
|
||||||
|
"arrayBoolean",
|
||||||
|
"arrayObject",
|
||||||
|
"any",
|
||||||
|
"chatHistory",
|
||||||
|
"datasetQuote",
|
||||||
|
"dynamic",
|
||||||
|
"selectApp",
|
||||||
|
"selectDataset"
|
||||||
|
],
|
||||||
|
"showDescription": false,
|
||||||
|
"showDefaultValue": true
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"value": ["pluginInput", "hook_url"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"renderTypeList": ["reference"],
|
||||||
|
"valueType": "object",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "content",
|
||||||
|
"label": "content",
|
||||||
|
"customInputConfig": {
|
||||||
|
"selectValueTypeList": [
|
||||||
|
"string",
|
||||||
|
"number",
|
||||||
|
"boolean",
|
||||||
|
"object",
|
||||||
|
"arrayString",
|
||||||
|
"arrayNumber",
|
||||||
|
"arrayBoolean",
|
||||||
|
"arrayObject",
|
||||||
|
"any",
|
||||||
|
"chatHistory",
|
||||||
|
"datasetQuote",
|
||||||
|
"dynamic",
|
||||||
|
"selectApp",
|
||||||
|
"selectDataset"
|
||||||
|
],
|
||||||
|
"showDescription": false,
|
||||||
|
"showDefaultValue": true
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"value": ["qcJpBBVtXsGd", "system_rawResponse"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"id": "error",
|
||||||
|
"key": "error",
|
||||||
|
"label": "请求错误",
|
||||||
|
"description": "HTTP请求错误信息,成功时返回空",
|
||||||
|
"valueType": "object",
|
||||||
|
"type": "static"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "httpRawResponse",
|
||||||
|
"key": "httpRawResponse",
|
||||||
|
"label": "原始响应",
|
||||||
|
"required": true,
|
||||||
|
"description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。",
|
||||||
|
"valueType": "any",
|
||||||
|
"type": "static"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "system_addOutputParam",
|
||||||
|
"key": "system_addOutputParam",
|
||||||
|
"type": "dynamic",
|
||||||
|
"valueType": "dynamic",
|
||||||
|
"label": "",
|
||||||
|
"customFieldConfig": {
|
||||||
|
"selectValueTypeList": [
|
||||||
|
"string",
|
||||||
|
"number",
|
||||||
|
"boolean",
|
||||||
|
"object",
|
||||||
|
"arrayString",
|
||||||
|
"arrayNumber",
|
||||||
|
"arrayBoolean",
|
||||||
|
"arrayObject",
|
||||||
|
"any",
|
||||||
|
"chatHistory",
|
||||||
|
"datasetQuote",
|
||||||
|
"dynamic",
|
||||||
|
"selectApp",
|
||||||
|
"selectDataset"
|
||||||
|
],
|
||||||
|
"showDescription": false,
|
||||||
|
"showDefaultValue": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nodeId": "qcJpBBVtXsGd",
|
||||||
|
"name": "代码运行",
|
||||||
|
"intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。",
|
||||||
|
"avatar": "core/workflow/template/codeRun",
|
||||||
|
"flowNodeType": "code",
|
||||||
|
"showStatus": true,
|
||||||
|
"position": {
|
||||||
|
"x": 805.8169457909617,
|
||||||
|
"y": -159.52218926716316
|
||||||
|
},
|
||||||
|
"version": "482",
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"key": "system_addInputParam",
|
||||||
|
"renderTypeList": ["addInputParam"],
|
||||||
|
"valueType": "dynamic",
|
||||||
|
"label": "",
|
||||||
|
"required": false,
|
||||||
|
"description": "这些变量会作为代码的运行的输入参数",
|
||||||
|
"customInputConfig": {
|
||||||
|
"selectValueTypeList": [
|
||||||
|
"string",
|
||||||
|
"number",
|
||||||
|
"boolean",
|
||||||
|
"object",
|
||||||
|
"arrayString",
|
||||||
|
"arrayNumber",
|
||||||
|
"arrayBoolean",
|
||||||
|
"arrayObject",
|
||||||
|
"any",
|
||||||
|
"chatHistory",
|
||||||
|
"datasetQuote",
|
||||||
|
"dynamic",
|
||||||
|
"selectApp",
|
||||||
|
"selectDataset"
|
||||||
|
],
|
||||||
|
"showDescription": false,
|
||||||
|
"showDefaultValue": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "codeType",
|
||||||
|
"renderTypeList": ["hidden"],
|
||||||
|
"label": "",
|
||||||
|
"value": "js"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "code",
|
||||||
|
"renderTypeList": ["custom"],
|
||||||
|
"label": "",
|
||||||
|
"value": "function main({data1}){\n try{\n const parseData = JSON.parse(data1)\n if(typeof parseData === 'object') {\n return parseData\n }\n return {\n \"msg_type\": \"text\",\n content: {\n \"text\": data1\n }\n }\n } catch(err) {\n return {\n \"msg_type\": \"text\",\n content: {\n \"text\": data1\n }\n }\n }\n}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"renderTypeList": ["reference"],
|
||||||
|
"valueType": "string",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "data1",
|
||||||
|
"label": "data1",
|
||||||
|
"customInputConfig": {
|
||||||
|
"selectValueTypeList": [
|
||||||
|
"string",
|
||||||
|
"number",
|
||||||
|
"boolean",
|
||||||
|
"object",
|
||||||
|
"arrayString",
|
||||||
|
"arrayNumber",
|
||||||
|
"arrayBoolean",
|
||||||
|
"arrayObject",
|
||||||
|
"any",
|
||||||
|
"chatHistory",
|
||||||
|
"datasetQuote",
|
||||||
|
"dynamic",
|
||||||
|
"selectApp",
|
||||||
|
"selectDataset"
|
||||||
|
],
|
||||||
|
"showDescription": false,
|
||||||
|
"showDefaultValue": true
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"value": ["pluginInput", "query"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"id": "system_rawResponse",
|
||||||
|
"key": "system_rawResponse",
|
||||||
|
"label": "完整响应数据",
|
||||||
|
"valueType": "object",
|
||||||
|
"type": "static"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "error",
|
||||||
|
"key": "error",
|
||||||
|
"label": "运行错误",
|
||||||
|
"description": "代码运行错误信息,成功时返回空",
|
||||||
|
"valueType": "object",
|
||||||
|
"type": "static"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "system_addOutputParam",
|
||||||
|
"key": "system_addOutputParam",
|
||||||
|
"type": "dynamic",
|
||||||
|
"valueType": "dynamic",
|
||||||
|
"label": "",
|
||||||
|
"customFieldConfig": {
|
||||||
|
"selectValueTypeList": [
|
||||||
|
"string",
|
||||||
|
"number",
|
||||||
|
"boolean",
|
||||||
|
"object",
|
||||||
|
"arrayString",
|
||||||
|
"arrayNumber",
|
||||||
|
"arrayBoolean",
|
||||||
|
"arrayObject",
|
||||||
|
"any",
|
||||||
|
"chatHistory",
|
||||||
|
"datasetQuote",
|
||||||
|
"dynamic",
|
||||||
|
"selectApp",
|
||||||
|
"selectDataset"
|
||||||
|
],
|
||||||
|
"showDescription": false,
|
||||||
|
"showDefaultValue": false
|
||||||
|
},
|
||||||
|
"description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "qLUQfhG0ILRX",
|
||||||
|
"type": "dynamic",
|
||||||
|
"key": "content",
|
||||||
|
"valueType": "object",
|
||||||
|
"label": "content"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"edges": [
|
||||||
|
{
|
||||||
|
"source": "vzreK6vHrPvZ",
|
||||||
|
"target": "pluginOutput",
|
||||||
|
"sourceHandle": "vzreK6vHrPvZ-source-right",
|
||||||
|
"targetHandle": "pluginOutput-target-left"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "pluginInput",
|
||||||
|
"target": "qcJpBBVtXsGd",
|
||||||
|
"sourceHandle": "pluginInput-source-right",
|
||||||
|
"targetHandle": "qcJpBBVtXsGd-target-left"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "qcJpBBVtXsGd",
|
||||||
|
"target": "vzreK6vHrPvZ",
|
||||||
|
"sourceHandle": "qcJpBBVtXsGd-source-right",
|
||||||
|
"targetHandle": "vzreK6vHrPvZ-target-left"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@@ -47,8 +47,6 @@ const addCommonMiddleware = (schema: mongoose.Schema) => {
|
|||||||
|
|
||||||
if (duration > 1000) {
|
if (duration > 1000) {
|
||||||
addLog.warn(`Slow operation ${duration}ms`, warnLogData);
|
addLog.warn(`Slow operation ${duration}ms`, warnLogData);
|
||||||
} else if (duration > 3000) {
|
|
||||||
addLog.error(`Slow operation ${duration}ms`, warnLogData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import { delay } from '@fastgpt/global/common/system/utils';
|
||||||
import { addLog } from '../system/log';
|
import { addLog } from '../system/log';
|
||||||
import { connectionMongo } from './index';
|
import { connectionMongo } from './index';
|
||||||
import type { Mongoose } from 'mongoose';
|
import type { Mongoose } from 'mongoose';
|
||||||
@@ -17,9 +18,11 @@ export async function connectMongo(): Promise<Mongoose> {
|
|||||||
try {
|
try {
|
||||||
connectionMongo.set('strictQuery', true);
|
connectionMongo.set('strictQuery', true);
|
||||||
|
|
||||||
connectionMongo.connection.on('error', (error) => {
|
connectionMongo.connection.on('error', async (error) => {
|
||||||
console.log('mongo error', error);
|
console.log('mongo error', error);
|
||||||
connectionMongo.disconnect();
|
await connectionMongo.disconnect();
|
||||||
|
await delay(1000);
|
||||||
|
connectMongo();
|
||||||
});
|
});
|
||||||
connectionMongo.connection.on('disconnected', () => {
|
connectionMongo.connection.on('disconnected', () => {
|
||||||
console.log('mongo disconnected');
|
console.log('mongo disconnected');
|
||||||
@@ -44,8 +47,10 @@ export async function connectMongo(): Promise<Mongoose> {
|
|||||||
|
|
||||||
console.log('mongo connected');
|
console.log('mongo connected');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
connectionMongo.disconnect();
|
|
||||||
addLog.error('mongo connect error', error);
|
addLog.error('mongo connect error', error);
|
||||||
|
await connectionMongo.disconnect();
|
||||||
|
await delay(1000);
|
||||||
|
connectMongo();
|
||||||
}
|
}
|
||||||
|
|
||||||
return connectionMongo;
|
return connectionMongo;
|
||||||
|
@@ -10,6 +10,7 @@ import {
|
|||||||
InsertVectorControllerProps
|
InsertVectorControllerProps
|
||||||
} from '../controller.d';
|
} from '../controller.d';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
import { addLog } from '../../system/log';
|
||||||
|
|
||||||
export class PgVectorCtrl {
|
export class PgVectorCtrl {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
@@ -38,9 +39,9 @@ export class PgVectorCtrl {
|
|||||||
`CREATE INDEX CONCURRENTLY IF NOT EXISTS create_time_index ON ${DatasetVectorTableName} USING btree(createtime);`
|
`CREATE INDEX CONCURRENTLY IF NOT EXISTS create_time_index ON ${DatasetVectorTableName} USING btree(createtime);`
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log('init pg successful');
|
addLog.info('init pg successful');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('init pg error', error);
|
addLog.error('init pg error', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
insert = async (props: InsertVectorControllerProps): Promise<{ insertId: string }> => {
|
insert = async (props: InsertVectorControllerProps): Promise<{ insertId: string }> => {
|
||||||
|
@@ -82,6 +82,7 @@ export async function getPluginPreviewNode({ id }: { id: string }): Promise<Flow
|
|||||||
avatar: plugin.avatar,
|
avatar: plugin.avatar,
|
||||||
name: plugin.name,
|
name: plugin.name,
|
||||||
intro: plugin.intro,
|
intro: plugin.intro,
|
||||||
|
inputExplanationUrl: plugin.inputExplanationUrl,
|
||||||
showStatus: plugin.showStatus,
|
showStatus: plugin.showStatus,
|
||||||
isTool: plugin.isTool,
|
isTool: plugin.isTool,
|
||||||
version: plugin.version,
|
version: plugin.version,
|
||||||
|
@@ -262,13 +262,14 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
|
|||||||
/* Inject data into module input */
|
/* Inject data into module input */
|
||||||
function getNodeRunParams(node: RuntimeNodeItemType) {
|
function getNodeRunParams(node: RuntimeNodeItemType) {
|
||||||
if (node.flowNodeType === FlowNodeTypeEnum.pluginInput) {
|
if (node.flowNodeType === FlowNodeTypeEnum.pluginInput) {
|
||||||
|
// Format plugin input to object
|
||||||
return node.inputs.reduce<Record<string, any>>((acc, item) => {
|
return node.inputs.reduce<Record<string, any>>((acc, item) => {
|
||||||
acc[item.key] = valueTypeFormat(item.value, item.valueType);
|
acc[item.key] = valueTypeFormat(item.value, item.valueType);
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
// common nodes
|
// Dynamic input need to store a key.
|
||||||
const dynamicInput = node.inputs.find(
|
const dynamicInput = node.inputs.find(
|
||||||
(item) => item.renderTypeList[0] === FlowNodeInputTypeEnum.addInputParam
|
(item) => item.renderTypeList[0] === FlowNodeInputTypeEnum.addInputParam
|
||||||
);
|
);
|
||||||
@@ -281,14 +282,14 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
|
|||||||
node.inputs.forEach((input) => {
|
node.inputs.forEach((input) => {
|
||||||
if (input.key === dynamicInput?.key) return;
|
if (input.key === dynamicInput?.key) return;
|
||||||
|
|
||||||
// replace {{}} variables
|
// replace {{xx}} variables
|
||||||
let value = replaceVariable(input.value, variables);
|
let value = replaceVariable(input.value, variables);
|
||||||
|
|
||||||
// replace {{$$}} variables
|
// replace {{$xx.xx$}} variables
|
||||||
value = replaceVariableLabel({
|
value = replaceVariableLabel({
|
||||||
text: value,
|
text: value,
|
||||||
nodes: runtimeNodes,
|
nodes: runtimeNodes,
|
||||||
variables: variables,
|
variables,
|
||||||
runningNode: node
|
runningNode: node
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -299,12 +300,11 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
|
|||||||
variables
|
variables
|
||||||
});
|
});
|
||||||
|
|
||||||
// concat dynamic inputs
|
// Dynamic input is stored in the dynamic key
|
||||||
if (input.canEdit && dynamicInput && params[dynamicInput.key]) {
|
if (input.canEdit && dynamicInput && params[dynamicInput.key]) {
|
||||||
params[dynamicInput.key][input.key] = valueTypeFormat(value, input.valueType);
|
params[dynamicInput.key][input.key] = valueTypeFormat(value, input.valueType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not dynamic input
|
|
||||||
params[input.key] = valueTypeFormat(value, input.valueType);
|
params[input.key] = valueTypeFormat(value, input.valueType);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -106,6 +106,7 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<H
|
|||||||
acc[key] = valueTypeFormat(value, WorkflowIOValueTypeEnum.string);
|
acc[key] = valueTypeFormat(value, WorkflowIOValueTypeEnum.string);
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
const requestBody = await (() => {
|
const requestBody = await (() => {
|
||||||
if (!httpJsonBody) return {};
|
if (!httpJsonBody) return {};
|
||||||
try {
|
try {
|
||||||
|
@@ -89,7 +89,13 @@ export default function Editor({
|
|||||||
}, [value, variables, variableLabels]);
|
}, [value, variables, variableLabels]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box position={'relative'} width={'full'} h={`${height}px`} cursor={'text'}>
|
<Box
|
||||||
|
position={'relative'}
|
||||||
|
width={'full'}
|
||||||
|
h={`${height}px`}
|
||||||
|
cursor={'text'}
|
||||||
|
color={'myGray.700'}
|
||||||
|
>
|
||||||
<LexicalComposer initialConfig={initialConfig} key={key}>
|
<LexicalComposer initialConfig={initialConfig} key={key}>
|
||||||
<PlainTextPlugin
|
<PlainTextPlugin
|
||||||
contentEditable={
|
contentEditable={
|
||||||
|
@@ -1,36 +1,40 @@
|
|||||||
import { FlowNodeTemplateTypeEnum } from '@fastgpt/global/core/workflow/constants';
|
import { FlowNodeTemplateTypeEnum } from '@fastgpt/global/core/workflow/constants';
|
||||||
import { NodeTemplateListType } from '@fastgpt/global/core/workflow/type/node';
|
import { i18nT } from '../../i18n/utils';
|
||||||
import { TFunction } from 'next-i18next';
|
|
||||||
|
|
||||||
export const workflowNodeTemplateList = (t: TFunction): NodeTemplateListType => [
|
export const workflowNodeTemplateList = [
|
||||||
{
|
{
|
||||||
type: FlowNodeTemplateTypeEnum.systemInput,
|
type: FlowNodeTemplateTypeEnum.systemInput,
|
||||||
label: t('common:core.module.template.System input module'),
|
label: i18nT('common:core.module.template.System input module'),
|
||||||
list: []
|
list: []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: FlowNodeTemplateTypeEnum.ai,
|
type: FlowNodeTemplateTypeEnum.ai,
|
||||||
label: t('common:core.module.template.AI function'),
|
label: i18nT('common:core.module.template.AI function'),
|
||||||
list: []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: FlowNodeTemplateTypeEnum.tools,
|
|
||||||
label: t('common:core.module.template.Tool module'),
|
|
||||||
list: []
|
list: []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: FlowNodeTemplateTypeEnum.search,
|
type: FlowNodeTemplateTypeEnum.search,
|
||||||
label: t('core.workflow.template.Search'),
|
label: i18nT('common:core.workflow.template.Search'),
|
||||||
list: []
|
list: []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: FlowNodeTemplateTypeEnum.multimodal,
|
type: FlowNodeTemplateTypeEnum.multimodal,
|
||||||
label: t('core.workflow.template.Multimodal'),
|
label: i18nT('common:core.workflow.template.Multimodal'),
|
||||||
|
list: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: FlowNodeTemplateTypeEnum.tools,
|
||||||
|
label: i18nT('common:core.module.template.Tool module'),
|
||||||
|
list: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: FlowNodeTemplateTypeEnum.communication,
|
||||||
|
label: i18nT('app:workflow.template.communication'),
|
||||||
list: []
|
list: []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: FlowNodeTemplateTypeEnum.other,
|
type: FlowNodeTemplateTypeEnum.other,
|
||||||
label: t('common:common.Other'),
|
label: i18nT('common:common.Other'),
|
||||||
list: []
|
list: []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"Run": "Run",
|
"Run": "Run",
|
||||||
"ai_settings": "AI Settings",
|
"ai_settings": "AI Settings",
|
||||||
|
"all_apps": "All Apps",
|
||||||
"app": {
|
"app": {
|
||||||
"modules": {
|
"modules": {
|
||||||
"click to update": "click to update",
|
"click to update": "click to update",
|
||||||
@@ -52,6 +53,7 @@
|
|||||||
"template": {
|
"template": {
|
||||||
"simple_robot": "Simple Robot"
|
"simple_robot": "Simple Robot"
|
||||||
},
|
},
|
||||||
|
"tool_input_param_tip": "Configure related information before the plugin runs properly",
|
||||||
"transition_to_workflow": "Transition to workflow",
|
"transition_to_workflow": "Transition to workflow",
|
||||||
"transition_to_workflow_create_new_placeholder": "Create a new application instead of modifying the current one",
|
"transition_to_workflow_create_new_placeholder": "Create a new application instead of modifying the current one",
|
||||||
"transition_to_workflow_create_new_tip": "After converting to workflow, it will not be able to convert back to simple mode, please confirm!",
|
"transition_to_workflow_create_new_tip": "After converting to workflow, it will not be able to convert back to simple mode, please confirm!",
|
||||||
@@ -71,5 +73,11 @@
|
|||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"Revert success": "Revert success"
|
"Revert success": "Revert success"
|
||||||
|
},
|
||||||
|
"workflow": {
|
||||||
|
"Input guide": "Input guide",
|
||||||
|
"template": {
|
||||||
|
"communication": "Communication"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
{
|
{
|
||||||
"App": "App",
|
"App": "App",
|
||||||
"all_apps": "All Apps",
|
|
||||||
"click_to_resume": "Resume",
|
"click_to_resume": "Resume",
|
||||||
"code_editor": "Code edit",
|
"code_editor": "Code edit",
|
||||||
"Export": "Export",
|
"Export": "Export",
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"Run": "运行",
|
"Run": "运行",
|
||||||
"ai_settings": "AI 配置",
|
"ai_settings": "AI 配置",
|
||||||
|
"all_apps": "全部应用",
|
||||||
"app": {
|
"app": {
|
||||||
"modules": {
|
"modules": {
|
||||||
"click to update": "点击更新",
|
"click to update": "点击更新",
|
||||||
@@ -52,6 +53,7 @@
|
|||||||
"template": {
|
"template": {
|
||||||
"simple_robot": "简易机器人"
|
"simple_robot": "简易机器人"
|
||||||
},
|
},
|
||||||
|
"tool_input_param_tip": "该插件正常运行需要配置相关信息",
|
||||||
"transition_to_workflow": "转成工作流",
|
"transition_to_workflow": "转成工作流",
|
||||||
"transition_to_workflow_create_new_placeholder": "创建一个新的应用,而不是修改当前应用",
|
"transition_to_workflow_create_new_placeholder": "创建一个新的应用,而不是修改当前应用",
|
||||||
"transition_to_workflow_create_new_tip": "转化成工作流后,将无法转化回简易模式,请确认!",
|
"transition_to_workflow_create_new_tip": "转化成工作流后,将无法转化回简易模式,请确认!",
|
||||||
@@ -71,5 +73,11 @@
|
|||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"Revert success": "回滚成功"
|
"Revert success": "回滚成功"
|
||||||
|
},
|
||||||
|
"workflow": {
|
||||||
|
"Input guide": "填写说明",
|
||||||
|
"template": {
|
||||||
|
"communication": "通信"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
{
|
{
|
||||||
"App": "应用",
|
"App": "应用",
|
||||||
"all_apps": "全部应用",
|
|
||||||
"click_to_resume": "点击恢复",
|
"click_to_resume": "点击恢复",
|
||||||
"code_editor": "代码编辑",
|
"code_editor": "代码编辑",
|
||||||
"Export": "导出",
|
"Export": "导出",
|
||||||
|
1159
pnpm-lock.yaml
generated
1159
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -52,13 +52,14 @@
|
|||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
"react-hook-form": "7.43.1",
|
"react-hook-form": "7.43.1",
|
||||||
"react-i18next": "14.1.2",
|
"react-i18next": "14.1.2",
|
||||||
"react-markdown": "^8.0.7",
|
"react-markdown": "^9.0.1",
|
||||||
"react-syntax-highlighter": "^15.5.0",
|
"react-syntax-highlighter": "^15.5.0",
|
||||||
"reactflow": "^11.7.4",
|
"reactflow": "^11.7.4",
|
||||||
"rehype-katex": "^6.0.2",
|
"rehype-external-links": "^3.0.0",
|
||||||
"remark-breaks": "^3.0.3",
|
"rehype-katex": "^7.0.0",
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-breaks": "^4.0.0",
|
||||||
"remark-math": "^5.1.1",
|
"remark-gfm": "^4.0.0",
|
||||||
|
"remark-math": "^6.0.0",
|
||||||
"request-ip": "^3.3.0",
|
"request-ip": "^3.3.0",
|
||||||
"sass": "^1.58.3",
|
"sass": "^1.58.3",
|
||||||
"use-context-selector": "^1.4.4",
|
"use-context-selector": "^1.4.4",
|
||||||
|
@@ -36,4 +36,4 @@ const MdImage = ({ src }: { src?: string }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default React.memo(MdImage);
|
export default MdImage;
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import ReactMarkdown from 'react-markdown';
|
import ReactMarkdown from 'react-markdown';
|
||||||
import 'katex/dist/katex.min.css';
|
import 'katex/dist/katex.min.css';
|
||||||
import RemarkMath from 'remark-math';
|
import RemarkMath from 'remark-math'; // Math syntax
|
||||||
import RemarkBreaks from 'remark-breaks';
|
import RemarkBreaks from 'remark-breaks'; // Line break
|
||||||
import RehypeKatex from 'rehype-katex';
|
import RehypeKatex from 'rehype-katex'; // Math render
|
||||||
import RemarkGfm from 'remark-gfm';
|
import RemarkGfm from 'remark-gfm'; // Special markdown syntax
|
||||||
|
import RehypeExternalLinks from 'rehype-external-links';
|
||||||
|
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
@@ -15,6 +16,7 @@ import { useTranslation } from 'next-i18next';
|
|||||||
import { EventNameEnum, eventBus } from '@/web/common/utils/eventbus';
|
import { EventNameEnum, eventBus } from '@/web/common/utils/eventbus';
|
||||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||||
import { MARKDOWN_QUOTE_SIGN } from '@fastgpt/global/core/chat/constants';
|
import { MARKDOWN_QUOTE_SIGN } from '@fastgpt/global/core/chat/constants';
|
||||||
|
import { CodeClassNameEnum } from './utils';
|
||||||
|
|
||||||
const CodeLight = dynamic(() => import('./CodeLight'), { ssr: false });
|
const CodeLight = dynamic(() => import('./CodeLight'), { ssr: false });
|
||||||
const MermaidCodeBlock = dynamic(() => import('./img/MermaidCodeBlock'), { ssr: false });
|
const MermaidCodeBlock = dynamic(() => import('./img/MermaidCodeBlock'), { ssr: false });
|
||||||
@@ -24,15 +26,6 @@ const EChartsCodeBlock = dynamic(() => import('./img/EChartsCodeBlock'), { ssr:
|
|||||||
const ChatGuide = dynamic(() => import('./chat/Guide'), { ssr: false });
|
const ChatGuide = dynamic(() => import('./chat/Guide'), { ssr: false });
|
||||||
const QuestionGuide = dynamic(() => import('./chat/QuestionGuide'), { ssr: false });
|
const QuestionGuide = dynamic(() => import('./chat/QuestionGuide'), { ssr: false });
|
||||||
|
|
||||||
export enum CodeClassName {
|
|
||||||
guide = 'guide',
|
|
||||||
questionGuide = 'questionGuide',
|
|
||||||
mermaid = 'mermaid',
|
|
||||||
echarts = 'echarts',
|
|
||||||
quote = 'quote',
|
|
||||||
files = 'files'
|
|
||||||
}
|
|
||||||
|
|
||||||
const Markdown = ({
|
const Markdown = ({
|
||||||
source = '',
|
source = '',
|
||||||
showAnimation = false
|
showAnimation = false
|
||||||
@@ -51,10 +44,13 @@ const Markdown = ({
|
|||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
const formatSource = source
|
const formatSource = useMemo(() => {
|
||||||
// .replace(/\\n/g, '\n')
|
const formatSource = source
|
||||||
.replace(/(http[s]?:\/\/[^\s,。]+)([。,])/g, '$1 $2')
|
.replace(/(http[s]?:\/\/[^\s,。]+)([。,])/g, '$1 $2') // Follow the link with a space
|
||||||
.replace(/\n*(\[QUOTE SIGN\]\(.*\))/g, '$1');
|
.replace(/\n*(\[QUOTE SIGN\]\(.*\))/g, '$1');
|
||||||
|
|
||||||
|
return formatSource;
|
||||||
|
}, [source]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactMarkdown
|
<ReactMarkdown
|
||||||
@@ -62,9 +58,8 @@ const Markdown = ({
|
|||||||
${showAnimation ? `${formatSource ? styles.waitingAnimation : styles.animation}` : ''}
|
${showAnimation ? `${formatSource ? styles.waitingAnimation : styles.animation}` : ''}
|
||||||
`}
|
`}
|
||||||
remarkPlugins={[RemarkMath, [RemarkGfm, { singleTilde: false }], RemarkBreaks]}
|
remarkPlugins={[RemarkMath, [RemarkGfm, { singleTilde: false }], RemarkBreaks]}
|
||||||
rehypePlugins={[RehypeKatex]}
|
rehypePlugins={[RehypeKatex, [RehypeExternalLinks, { target: '_blank' }]]}
|
||||||
components={components}
|
components={components}
|
||||||
linkTarget={'_blank'}
|
|
||||||
>
|
>
|
||||||
{formatSource}
|
{formatSource}
|
||||||
</ReactMarkdown>
|
</ReactMarkdown>
|
||||||
@@ -73,6 +68,7 @@ const Markdown = ({
|
|||||||
|
|
||||||
export default React.memo(Markdown);
|
export default React.memo(Markdown);
|
||||||
|
|
||||||
|
/* Custom dom */
|
||||||
const Code = React.memo(function Code(e: any) {
|
const Code = React.memo(function Code(e: any) {
|
||||||
const { inline, className, children } = e;
|
const { inline, className, children } = e;
|
||||||
|
|
||||||
@@ -82,17 +78,16 @@ const Code = React.memo(function Code(e: any) {
|
|||||||
const strChildren = String(children);
|
const strChildren = String(children);
|
||||||
|
|
||||||
const Component = useMemo(() => {
|
const Component = useMemo(() => {
|
||||||
if (codeType === CodeClassName.mermaid) {
|
if (codeType === CodeClassNameEnum.mermaid) {
|
||||||
return <MermaidCodeBlock code={strChildren} />;
|
return <MermaidCodeBlock code={strChildren} />;
|
||||||
}
|
}
|
||||||
|
if (codeType === CodeClassNameEnum.guide) {
|
||||||
if (codeType === CodeClassName.guide) {
|
|
||||||
return <ChatGuide text={strChildren} />;
|
return <ChatGuide text={strChildren} />;
|
||||||
}
|
}
|
||||||
if (codeType === CodeClassName.questionGuide) {
|
if (codeType === CodeClassNameEnum.questionGuide) {
|
||||||
return <QuestionGuide text={strChildren} />;
|
return <QuestionGuide text={strChildren} />;
|
||||||
}
|
}
|
||||||
if (codeType === CodeClassName.echarts) {
|
if (codeType === CodeClassNameEnum.echarts) {
|
||||||
return <EChartsCodeBlock code={strChildren} />;
|
return <EChartsCodeBlock code={strChildren} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +100,6 @@ const Code = React.memo(function Code(e: any) {
|
|||||||
|
|
||||||
return Component;
|
return Component;
|
||||||
});
|
});
|
||||||
|
|
||||||
const Image = React.memo(function Image({ src }: { src?: string }) {
|
const Image = React.memo(function Image({ src }: { src?: string }) {
|
||||||
return <MdImage src={src} />;
|
return <MdImage src={src} />;
|
||||||
});
|
});
|
||||||
|
77
projects/app/src/components/Markdown/utils.ts
Normal file
77
projects/app/src/components/Markdown/utils.ts
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
export enum CodeClassNameEnum {
|
||||||
|
guide = 'guide',
|
||||||
|
questionGuide = 'questionGuide',
|
||||||
|
mermaid = 'mermaid',
|
||||||
|
echarts = 'echarts',
|
||||||
|
quote = 'quote',
|
||||||
|
files = 'files',
|
||||||
|
latex = 'latex'
|
||||||
|
}
|
||||||
|
|
||||||
|
function htmlTableToLatex(html: string) {
|
||||||
|
const parser = new DOMParser();
|
||||||
|
const doc = parser.parseFromString(html, 'text/html');
|
||||||
|
const table = doc.querySelector('table');
|
||||||
|
|
||||||
|
if (!table) return '';
|
||||||
|
|
||||||
|
let latex = '\\begin{tabular}{';
|
||||||
|
|
||||||
|
// 获取列数
|
||||||
|
const columns = table.querySelectorAll('tr:first-child th, tr:first-child td').length;
|
||||||
|
latex += '|' + 'c|'.repeat(columns) + '}\n\\hline\n';
|
||||||
|
|
||||||
|
// 创建一个二维数组来跟踪单元格合并情况
|
||||||
|
const cellTracker = Array.from({ length: table.rows.length }, () => Array(columns).fill(false));
|
||||||
|
|
||||||
|
// 遍历行
|
||||||
|
table.querySelectorAll('tr').forEach((row, rowIndex) => {
|
||||||
|
const cells = row.querySelectorAll('th, td');
|
||||||
|
let cellTexts: string[] = [];
|
||||||
|
let colIndex = 0;
|
||||||
|
|
||||||
|
cells.forEach((cell) => {
|
||||||
|
// 跳过已经被合并的单元格
|
||||||
|
while (cellTracker[rowIndex][colIndex]) {
|
||||||
|
colIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
const rowspan = parseInt(cell.getAttribute('rowspan') || 1, 10);
|
||||||
|
// @ts-ignore
|
||||||
|
const colspan = parseInt(cell.getAttribute('colspan') || 1, 10);
|
||||||
|
|
||||||
|
// 添加单元格内容
|
||||||
|
let cellText = cell.textContent?.trim() || '';
|
||||||
|
if (colspan > 1) {
|
||||||
|
cellText = `\\multicolumn{${colspan}}{|c|}{${cellText}}`;
|
||||||
|
}
|
||||||
|
if (rowspan > 1) {
|
||||||
|
cellText = `\\multirow{${rowspan}}{*}{${cellText}}`;
|
||||||
|
}
|
||||||
|
cellTexts.push(cellText);
|
||||||
|
|
||||||
|
// 标记合并的单元格
|
||||||
|
for (let i = 0; i < rowspan; i++) {
|
||||||
|
for (let j = 0; j < colspan; j++) {
|
||||||
|
cellTracker[rowIndex + i][colIndex + j] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
colIndex += colspan;
|
||||||
|
});
|
||||||
|
|
||||||
|
latex += cellTexts.join(' & ') + ' \\\\\n\\hline\n';
|
||||||
|
});
|
||||||
|
|
||||||
|
latex += '\\end{tabular}';
|
||||||
|
|
||||||
|
return `\`\`\`${CodeClassNameEnum.latex}
|
||||||
|
${latex}
|
||||||
|
\`\`\``;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function convertHtmlTablesToLatex(input: string) {
|
||||||
|
const tableRegex = /<table[\s\S]*?<\/table>/gi;
|
||||||
|
return input.replace(tableRegex, (match) => htmlTableToLatex(match));
|
||||||
|
}
|
@@ -16,6 +16,7 @@ import MyModal from '@fastgpt/web/components/common/MyModal';
|
|||||||
|
|
||||||
type Props = TextareaProps & {
|
type Props = TextareaProps & {
|
||||||
title?: string;
|
title?: string;
|
||||||
|
iconSrc?: string;
|
||||||
// variables: string[];
|
// variables: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -24,7 +25,11 @@ const MyTextarea = React.forwardRef<HTMLTextAreaElement, Props>(function MyTexta
|
|||||||
const TextareaRef = useRef<HTMLTextAreaElement>(null);
|
const TextareaRef = useRef<HTMLTextAreaElement>(null);
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { title = t('common:core.app.edit.Prompt Editor'), ...childProps } = props;
|
const {
|
||||||
|
title = t('common:core.app.edit.Prompt Editor'),
|
||||||
|
iconSrc = 'modal/edit',
|
||||||
|
...childProps
|
||||||
|
} = props;
|
||||||
|
|
||||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
|
|
||||||
@@ -32,7 +37,7 @@ const MyTextarea = React.forwardRef<HTMLTextAreaElement, Props>(function MyTexta
|
|||||||
<>
|
<>
|
||||||
<Editor textareaRef={TextareaRef} {...childProps} onOpenModal={onOpen} />
|
<Editor textareaRef={TextareaRef} {...childProps} onOpenModal={onOpen} />
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<MyModal iconSrc="/imgs/modal/edit.svg" title={title} isOpen onClose={onClose}>
|
<MyModal iconSrc={iconSrc} title={title} isOpen onClose={onClose}>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<Editor
|
<Editor
|
||||||
textareaRef={ModalTextareaRef}
|
textareaRef={ModalTextareaRef}
|
||||||
|
@@ -96,9 +96,7 @@ const VariableEdit = ({
|
|||||||
<Box>
|
<Box>
|
||||||
<Flex alignItems={'center'}>
|
<Flex alignItems={'center'}>
|
||||||
<MyIcon name={'core/app/simpleMode/variable'} w={'20px'} />
|
<MyIcon name={'core/app/simpleMode/variable'} w={'20px'} />
|
||||||
<FormLabel ml={2} fontWeight={'medium'}>
|
<FormLabel ml={2}>{t('common:core.module.Variable')}</FormLabel>
|
||||||
{t('common:core.module.Variable')}
|
|
||||||
</FormLabel>
|
|
||||||
<ChatFunctionTip type={'variable'} />
|
<ChatFunctionTip type={'variable'} />
|
||||||
<Box flex={1} />
|
<Box flex={1} />
|
||||||
<Button
|
<Button
|
||||||
|
@@ -17,6 +17,8 @@ const WelcomeTextConfig = (props: TextareaProps) => {
|
|||||||
<ChatFunctionTip type={'welcome'} />
|
<ChatFunctionTip type={'welcome'} />
|
||||||
</Flex>
|
</Flex>
|
||||||
<MyTextarea
|
<MyTextarea
|
||||||
|
iconSrc={'core/app/simpleMode/chat'}
|
||||||
|
title={t('common:core.app.Welcome Text')}
|
||||||
mt={2}
|
mt={2}
|
||||||
rows={6}
|
rows={6}
|
||||||
fontSize={'sm'}
|
fontSize={'sm'}
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import Markdown, { CodeClassName } from '@/components/Markdown';
|
import Markdown from '@/components/Markdown';
|
||||||
|
import { CodeClassNameEnum } from '@/components/Markdown/utils';
|
||||||
import {
|
import {
|
||||||
Accordion,
|
Accordion,
|
||||||
AccordionButton,
|
AccordionButton,
|
||||||
@@ -41,7 +42,7 @@ const AIResponseBox = ({ value, index, chat, isLastChild, isChatting, questionGu
|
|||||||
index === chat.value.length - 1
|
index === chat.value.length - 1
|
||||||
) {
|
) {
|
||||||
source = `${source}
|
source = `${source}
|
||||||
\`\`\`${CodeClassName.questionGuide}
|
\`\`\`${CodeClassNameEnum.questionGuide}
|
||||||
${JSON.stringify(questionGuides)}`;
|
${JSON.stringify(questionGuides)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,6 +14,7 @@ const SearchParamsTip = ({
|
|||||||
limit = 1500,
|
limit = 1500,
|
||||||
responseEmptyText,
|
responseEmptyText,
|
||||||
usingReRank = false,
|
usingReRank = false,
|
||||||
|
datasetSearchUsingExtensionQuery,
|
||||||
queryExtensionModel
|
queryExtensionModel
|
||||||
}: {
|
}: {
|
||||||
searchMode: `${DatasetSearchModeEnum}`;
|
searchMode: `${DatasetSearchModeEnum}`;
|
||||||
@@ -21,6 +22,7 @@ const SearchParamsTip = ({
|
|||||||
limit?: number;
|
limit?: number;
|
||||||
responseEmptyText?: string;
|
responseEmptyText?: string;
|
||||||
usingReRank?: boolean;
|
usingReRank?: boolean;
|
||||||
|
datasetSearchUsingExtensionQuery?: boolean;
|
||||||
queryExtensionModel?: string;
|
queryExtensionModel?: string;
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -32,11 +34,11 @@ const SearchParamsTip = ({
|
|||||||
|
|
||||||
const extensionModelName = useMemo(
|
const extensionModelName = useMemo(
|
||||||
() =>
|
() =>
|
||||||
queryExtensionModel
|
datasetSearchUsingExtensionQuery
|
||||||
? llmModelList.find((item) => item.model === queryExtensionModel)?.name ??
|
? llmModelList.find((item) => item.model === queryExtensionModel)?.name ??
|
||||||
llmModelList[0]?.name
|
llmModelList[0]?.name
|
||||||
: undefined,
|
: undefined,
|
||||||
[llmModelList, queryExtensionModel]
|
[datasetSearchUsingExtensionQuery, llmModelList, queryExtensionModel]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@@ -52,7 +52,7 @@ const ConfigPerModal = ({
|
|||||||
>
|
>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<HStack>
|
<HStack>
|
||||||
<Avatar src={avatar} w={'1.75rem'} />
|
<Avatar src={avatar} w={'1.75rem'} borderRadius={'md'} />
|
||||||
<Box>{name}</Box>
|
<Box>{name}</Box>
|
||||||
</HStack>
|
</HStack>
|
||||||
{!isInheritPermission && (
|
{!isInheritPermission && (
|
||||||
|
46
projects/app/src/pages/api/admin/initv488.ts
Normal file
46
projects/app/src/pages/api/admin/initv488.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
|
import { jsonRes } from '@fastgpt/service/common/response';
|
||||||
|
import { connectToDatabase } from '@/service/mongo';
|
||||||
|
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
||||||
|
import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
|
||||||
|
import { DatasetDefaultPermissionVal } from '@fastgpt/global/support/permission/dataset/constant';
|
||||||
|
|
||||||
|
/* pg 中的数据搬到 mongo dataset.datas 中,并做映射 */
|
||||||
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
|
try {
|
||||||
|
await connectToDatabase();
|
||||||
|
await authCert({ req, authRoot: true });
|
||||||
|
|
||||||
|
await MongoDataset.updateMany(
|
||||||
|
{
|
||||||
|
inheritPermission: { $exists: false }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$set: {
|
||||||
|
inheritPermission: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
await MongoDataset.updateMany(
|
||||||
|
{
|
||||||
|
defaultPermission: { $exists: false }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$set: {
|
||||||
|
defaultPermission: DatasetDefaultPermissionVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
jsonRes(res, {
|
||||||
|
message: 'success'
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
|
||||||
|
jsonRes(res, {
|
||||||
|
code: 500,
|
||||||
|
error
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@@ -89,7 +89,7 @@ async function handler(req: ApiRequestProps<AppUpdateParams, { appId: string }>)
|
|||||||
defaultPermission: updatedDefaultPermission
|
defaultPermission: updatedDefaultPermission
|
||||||
}),
|
}),
|
||||||
// Not root, update default permission
|
// Not root, update default permission
|
||||||
...(isDefaultPermissionChanged && { inheritPermission: false }),
|
...(app.parentId && isDefaultPermissionChanged && { inheritPermission: false }),
|
||||||
...(teamTags && { teamTags }),
|
...(teamTags && { teamTags }),
|
||||||
...(formatNodes && {
|
...(formatNodes && {
|
||||||
modules: formatNodes
|
modules: formatNodes
|
||||||
|
@@ -15,7 +15,7 @@ import { removeEmptyUserInput } from '@fastgpt/global/core/chat/utils';
|
|||||||
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
|
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||||
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
||||||
import {
|
import {
|
||||||
filterPluginInputVariables,
|
removePluginInputVariables,
|
||||||
updatePluginInputByVariables
|
updatePluginInputByVariables
|
||||||
} from '@fastgpt/global/core/workflow/utils';
|
} from '@fastgpt/global/core/workflow/utils';
|
||||||
import { NextAPI } from '@/service/middleware/entry';
|
import { NextAPI } from '@/service/middleware/entry';
|
||||||
@@ -66,7 +66,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
// Plugin need to replace inputs
|
// Plugin need to replace inputs
|
||||||
if (isPlugin) {
|
if (isPlugin) {
|
||||||
nodes = updatePluginInputByVariables(nodes, variables);
|
nodes = updatePluginInputByVariables(nodes, variables);
|
||||||
variables = filterPluginInputVariables(variables, nodes);
|
variables = removePluginInputVariables(variables, nodes);
|
||||||
} else {
|
} else {
|
||||||
if (!userInput) {
|
if (!userInput) {
|
||||||
throw new Error('Params Error');
|
throw new Error('Params Error');
|
||||||
|
@@ -24,7 +24,7 @@ async function handler(req: NextApiRequest) {
|
|||||||
searchMode,
|
searchMode,
|
||||||
usingReRank,
|
usingReRank,
|
||||||
|
|
||||||
datasetSearchUsingExtensionQuery = false,
|
datasetSearchUsingExtensionQuery = true,
|
||||||
datasetSearchExtensionModel,
|
datasetSearchExtensionModel,
|
||||||
datasetSearchExtensionBg = ''
|
datasetSearchExtensionBg = ''
|
||||||
} = req.body as SearchTestProps;
|
} = req.body as SearchTestProps;
|
||||||
|
@@ -78,7 +78,7 @@ async function handler(
|
|||||||
defaultPermission: updatedDefaultPermission
|
defaultPermission: updatedDefaultPermission
|
||||||
}),
|
}),
|
||||||
// update the defaultPermission
|
// update the defaultPermission
|
||||||
...(isDefaultPermissionChanged && { inheritPermission: false })
|
...(dataset.parentId && isDefaultPermissionChanged && { inheritPermission: false })
|
||||||
},
|
},
|
||||||
{ session }
|
{ session }
|
||||||
);
|
);
|
||||||
|
@@ -55,7 +55,7 @@ import { getAppLatestVersion } from '@fastgpt/service/core/app/controller';
|
|||||||
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
|
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||||
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
||||||
import {
|
import {
|
||||||
filterPluginInputVariables,
|
removePluginInputVariables,
|
||||||
updatePluginInputByVariables
|
updatePluginInputByVariables
|
||||||
} from '@fastgpt/global/core/workflow/utils';
|
} from '@fastgpt/global/core/workflow/utils';
|
||||||
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||||
@@ -238,7 +238,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
)
|
)
|
||||||
: storeNodes2RuntimeNodes(nodes, getDefaultEntryNodeIds(nodes));
|
: storeNodes2RuntimeNodes(nodes, getDefaultEntryNodeIds(nodes));
|
||||||
|
|
||||||
const runtimeVariables = filterPluginInputVariables(
|
const runtimeVariables = removePluginInputVariables(
|
||||||
variables,
|
variables,
|
||||||
storeNodes2RuntimeNodes(nodes, getDefaultEntryNodeIds(nodes))
|
storeNodes2RuntimeNodes(nodes, getDefaultEntryNodeIds(nodes))
|
||||||
);
|
);
|
||||||
|
@@ -113,8 +113,8 @@ const EditForm = ({
|
|||||||
...item,
|
...item,
|
||||||
parent: {
|
parent: {
|
||||||
id: 'VARIABLE_NODE_ID',
|
id: 'VARIABLE_NODE_ID',
|
||||||
label: '全局变量',
|
label: t('common:core.module.Variable'),
|
||||||
avatar: '/imgs/workflow/variable.png'
|
avatar: 'core/workflow/template/variable'
|
||||||
}
|
}
|
||||||
})),
|
})),
|
||||||
[appForm.chatConfig.variables, t]
|
[appForm.chatConfig.variables, t]
|
||||||
@@ -230,6 +230,7 @@ const EditForm = ({
|
|||||||
similarity={appForm.dataset.similarity}
|
similarity={appForm.dataset.similarity}
|
||||||
limit={appForm.dataset.limit}
|
limit={appForm.dataset.limit}
|
||||||
usingReRank={appForm.dataset.usingReRank}
|
usingReRank={appForm.dataset.usingReRank}
|
||||||
|
datasetSearchUsingExtensionQuery={appForm.dataset.datasetSearchUsingExtensionQuery}
|
||||||
queryExtensionModel={appForm.dataset.datasetSearchExtensionModel}
|
queryExtensionModel={appForm.dataset.datasetSearchExtensionModel}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
@@ -92,7 +92,12 @@ const Header = ({
|
|||||||
)}
|
)}
|
||||||
<Flex pt={[2, 3]} alignItems={'flex-start'} position={'relative'}>
|
<Flex pt={[2, 3]} alignItems={'flex-start'} position={'relative'}>
|
||||||
<Box flex={'1'}>
|
<Box flex={'1'}>
|
||||||
<FolderPath paths={paths} hoverStyle={{ color: 'primary.600' }} onClick={onclickRoute} />
|
<FolderPath
|
||||||
|
rootName={t('app:all_apps')}
|
||||||
|
paths={paths}
|
||||||
|
hoverStyle={{ color: 'primary.600' }}
|
||||||
|
onClick={onclickRoute}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
{isPc && (
|
{isPc && (
|
||||||
<Box position={'absolute'} left={'50%'} transform={'translateX(-50%)'}>
|
<Box position={'absolute'} left={'50%'} transform={'translateX(-50%)'}>
|
||||||
|
@@ -6,6 +6,7 @@ import {
|
|||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
Flex,
|
Flex,
|
||||||
|
HStack,
|
||||||
Input,
|
Input,
|
||||||
InputGroup,
|
InputGroup,
|
||||||
InputLeftElement,
|
InputLeftElement,
|
||||||
@@ -287,6 +288,8 @@ const RenderList = React.memo(function RenderList({
|
|||||||
</MyTooltip>
|
</MyTooltip>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
||||||
|
{/* Plugin input config */}
|
||||||
{!!configTool && (
|
{!!configTool && (
|
||||||
<MyModal
|
<MyModal
|
||||||
isOpen
|
isOpen
|
||||||
@@ -295,6 +298,19 @@ const RenderList = React.memo(function RenderList({
|
|||||||
overflow={'auto'}
|
overflow={'auto'}
|
||||||
>
|
>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
|
<HStack mb={4} spacing={1} fontSize={'sm'}>
|
||||||
|
<MyIcon name={'common/info'} w={'1.25rem'} />
|
||||||
|
<Box flex={1}>{t('app:tool_input_param_tip')}</Box>
|
||||||
|
{configTool.inputExplanationUrl && (
|
||||||
|
<Box
|
||||||
|
cursor={'pointer'}
|
||||||
|
color={'primary.500'}
|
||||||
|
onClick={() => window.open(configTool.inputExplanationUrl, '_blank')}
|
||||||
|
>
|
||||||
|
{t('app:workflow.Input guide')}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</HStack>
|
||||||
{configTool.inputs
|
{configTool.inputs
|
||||||
.filter((item) => !item.toolDescription)
|
.filter((item) => !item.toolDescription)
|
||||||
.map((input) => {
|
.map((input) => {
|
||||||
|
@@ -334,7 +334,7 @@ const RenderList = React.memo(function RenderList({
|
|||||||
const { computedNewNodeName } = useWorkflowUtils();
|
const { computedNewNodeName } = useWorkflowUtils();
|
||||||
|
|
||||||
const formatTemplates = useMemo<NodeTemplateListType>(() => {
|
const formatTemplates = useMemo<NodeTemplateListType>(() => {
|
||||||
const copy: NodeTemplateListType = cloneDeep(workflowNodeTemplateList(t));
|
const copy: NodeTemplateListType = cloneDeep(workflowNodeTemplateList);
|
||||||
templates.forEach((item) => {
|
templates.forEach((item) => {
|
||||||
const index = copy.findIndex((template) => template.type === item.templateType);
|
const index = copy.findIndex((template) => template.type === item.templateType);
|
||||||
if (index === -1) return;
|
if (index === -1) return;
|
||||||
|
@@ -1,12 +1,30 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, Flex, FlexProps } from '@chakra-ui/react';
|
import { Box, StackProps, HStack } from '@chakra-ui/react';
|
||||||
|
import { useTranslation } from 'next-i18next';
|
||||||
|
|
||||||
|
const IOTitle = ({
|
||||||
|
text,
|
||||||
|
inputExplanationUrl,
|
||||||
|
...props
|
||||||
|
}: { text?: 'Input' | 'Output' | string; inputExplanationUrl?: string } & StackProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const IOTitle = ({ text, ...props }: { text?: 'Input' | 'Output' | string } & FlexProps) => {
|
|
||||||
return (
|
return (
|
||||||
<Flex fontSize={'md'} alignItems={'center'} fontWeight={'medium'} mb={3} {...props}>
|
<HStack fontSize={'md'} alignItems={'center'} fontWeight={'medium'} mb={3} {...props}>
|
||||||
<Box w={'3px'} h={'14px'} borderRadius={'13px'} bg={'primary.600'} mr={1.5} />
|
<Box w={'3px'} h={'14px'} borderRadius={'13px'} bg={'primary.600'} />
|
||||||
{text}
|
<Box>{text}</Box>
|
||||||
</Flex>
|
<Box flex={1} />
|
||||||
|
|
||||||
|
{inputExplanationUrl && (
|
||||||
|
<Box
|
||||||
|
cursor={'pointer'}
|
||||||
|
color={'primary.500'}
|
||||||
|
onClick={() => window.open(inputExplanationUrl, '_blank')}
|
||||||
|
>
|
||||||
|
{t('app:workflow.Input guide')}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</HStack>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -37,7 +37,10 @@ const NodeSimple = ({
|
|||||||
{filterHiddenInputs.length > 0 && (
|
{filterHiddenInputs.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<Container>
|
<Container>
|
||||||
<IOTitle text={t('common:common.Input')} />
|
<IOTitle
|
||||||
|
text={t('common:common.Input')}
|
||||||
|
inputExplanationUrl={data.inputExplanationUrl}
|
||||||
|
/>
|
||||||
<RenderInput nodeId={nodeId} flowInputList={commonInputs} />
|
<RenderInput nodeId={nodeId} flowInputList={commonInputs} />
|
||||||
</Container>
|
</Container>
|
||||||
</>
|
</>
|
||||||
|
@@ -80,27 +80,36 @@ const NodeCard = (props: Props) => {
|
|||||||
|
|
||||||
const node = nodeList.find((node) => node.nodeId === nodeId);
|
const node = nodeList.find((node) => node.nodeId === nodeId);
|
||||||
const { openConfirm: onOpenConfirmSync, ConfirmModal: ConfirmSyncModal } = useConfirm({
|
const { openConfirm: onOpenConfirmSync, ConfirmModal: ConfirmSyncModal } = useConfirm({
|
||||||
content: appT('module.Confirm Sync')
|
content: t('app:module.Confirm Sync')
|
||||||
});
|
});
|
||||||
|
|
||||||
const { data: newNodeVersion, runAsync: getNodeVersion } = useRequest2(
|
const { data: nodeTemplate, runAsync: getNodeLatestTemplate } = useRequest2(
|
||||||
async () => {
|
async () => {
|
||||||
if (node?.flowNodeType === FlowNodeTypeEnum.pluginModule) {
|
if (node?.flowNodeType === FlowNodeTypeEnum.pluginModule) {
|
||||||
if (!node?.pluginId) return;
|
if (!node?.pluginId) return;
|
||||||
const template = await getPreviewPluginNode({ appId: node.pluginId });
|
const template = await getPreviewPluginNode({ appId: node.pluginId });
|
||||||
return template.version;
|
|
||||||
|
// Focus update plugin latest inputExplanationUrl
|
||||||
|
onChangeNode({
|
||||||
|
nodeId,
|
||||||
|
type: 'attr',
|
||||||
|
key: 'inputExplanationUrl',
|
||||||
|
value: template.inputExplanationUrl
|
||||||
|
});
|
||||||
|
|
||||||
|
return template;
|
||||||
} else {
|
} else {
|
||||||
const template = moduleTemplatesFlat.find(
|
const template = moduleTemplatesFlat.find(
|
||||||
(item) => item.flowNodeType === node?.flowNodeType
|
(item) => item.flowNodeType === node?.flowNodeType
|
||||||
);
|
);
|
||||||
return template?.version;
|
return template;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
manual: false
|
manual: false
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const hasNewVersion = newNodeVersion && newNodeVersion !== node?.version;
|
const hasNewVersion = nodeTemplate && nodeTemplate.version !== node?.version;
|
||||||
|
|
||||||
const { runAsync: onClickSyncVersion } = useRequest2(
|
const { runAsync: onClickSyncVersion } = useRequest2(
|
||||||
async () => {
|
async () => {
|
||||||
@@ -119,10 +128,10 @@ const NodeCard = (props: Props) => {
|
|||||||
node: getLatestNodeTemplate(node, template)
|
node: getLatestNodeTemplate(node, template)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
await getNodeVersion();
|
await getNodeLatestTemplate();
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
refreshDeps: [node, nodeId, onResetNode, getNodeVersion]
|
refreshDeps: [node, nodeId, onResetNode, getNodeLatestTemplate]
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import React, { useEffect, useMemo, useState } from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import type { RenderInputProps } from '../type';
|
import type { RenderInputProps } from '../type';
|
||||||
import { Box, Button, Flex, useDisclosure } from '@chakra-ui/react';
|
import { Flex, useDisclosure } from '@chakra-ui/react';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constants';
|
import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
|
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
|
||||||
@@ -54,7 +54,8 @@ const SelectDatasetParam = ({ inputs = [], nodeId }: RenderInputProps) => {
|
|||||||
if (data[input.key] !== undefined) {
|
if (data[input.key] !== undefined) {
|
||||||
setData((state) => ({
|
setData((state) => ({
|
||||||
...state,
|
...state,
|
||||||
[input.key]: input.value
|
// @ts-ignore
|
||||||
|
[input.key]: input.value || state[input.key]
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -82,6 +83,7 @@ const SelectDatasetParam = ({ inputs = [], nodeId }: RenderInputProps) => {
|
|||||||
similarity={data.similarity}
|
similarity={data.similarity}
|
||||||
limit={data.limit}
|
limit={data.limit}
|
||||||
usingReRank={data.usingReRank}
|
usingReRank={data.usingReRank}
|
||||||
|
datasetSearchUsingExtensionQuery={data.datasetSearchUsingExtensionQuery}
|
||||||
queryExtensionModel={data.datasetSearchExtensionModel}
|
queryExtensionModel={data.datasetSearchExtensionModel}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
@@ -10,7 +10,7 @@ const TextInput = ({ item, nodeId }: RenderInputProps) => {
|
|||||||
const Render = useMemo(() => {
|
const Render = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
<Input
|
<Input
|
||||||
placeholder={item.placeholder}
|
placeholder={item.placeholder ?? item.description}
|
||||||
defaultValue={item.value}
|
defaultValue={item.value}
|
||||||
bg={'white'}
|
bg={'white'}
|
||||||
px={3}
|
px={3}
|
||||||
|
@@ -14,7 +14,6 @@ import { AppUpdateParams } from '@/global/core/app/api';
|
|||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { useI18n } from '@/web/context/I18n';
|
import { useI18n } from '@/web/context/I18n';
|
||||||
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
||||||
import { useThrottleEffect } from 'ahooks';
|
|
||||||
const MoveModal = dynamic(() => import('@/components/common/folder/MoveModal'));
|
const MoveModal = dynamic(() => import('@/components/common/folder/MoveModal'));
|
||||||
|
|
||||||
type AppListContextType = {
|
type AppListContextType = {
|
||||||
|
@@ -131,10 +131,10 @@ const MobileDrawer = ({
|
|||||||
}}
|
}}
|
||||||
list={[
|
list={[
|
||||||
...(isTeamChat
|
...(isTeamChat
|
||||||
? [{ label: t('common:all_apps'), value: TabEnum.recently }]
|
? [{ label: t('app:all_apps'), value: TabEnum.recently }]
|
||||||
: [
|
: [
|
||||||
{ label: t('common:core.chat.Recent use'), value: TabEnum.recently },
|
{ label: t('common:core.chat.Recent use'), value: TabEnum.recently },
|
||||||
{ label: t('common:all_apps'), value: TabEnum.app }
|
{ label: t('app:all_apps'), value: TabEnum.app }
|
||||||
])
|
])
|
||||||
]}
|
]}
|
||||||
value={currentTab}
|
value={currentTab}
|
||||||
|
@@ -71,7 +71,7 @@ const Test = ({ datasetId }: { datasetId: string }) => {
|
|||||||
usingReRank: false,
|
usingReRank: false,
|
||||||
limit: 5000,
|
limit: 5000,
|
||||||
similarity: 0,
|
similarity: 0,
|
||||||
datasetSearchUsingExtensionQuery: false,
|
datasetSearchUsingExtensionQuery: true,
|
||||||
datasetSearchExtensionModel: llmModelList[0].model,
|
datasetSearchExtensionModel: llmModelList[0].model,
|
||||||
datasetSearchExtensionBg: ''
|
datasetSearchExtensionBg: ''
|
||||||
}
|
}
|
||||||
@@ -432,6 +432,7 @@ const TestResults = React.memo(function TestResults({
|
|||||||
similarity={datasetTestItem.similarity}
|
similarity={datasetTestItem.similarity}
|
||||||
limit={datasetTestItem.limit}
|
limit={datasetTestItem.limit}
|
||||||
usingReRank={datasetTestItem.usingReRank}
|
usingReRank={datasetTestItem.usingReRank}
|
||||||
|
datasetSearchUsingExtensionQuery={!!datasetTestItem.queryExtensionModel}
|
||||||
queryExtensionModel={datasetTestItem.queryExtensionModel}
|
queryExtensionModel={datasetTestItem.queryExtensionModel}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
@@ -68,7 +68,11 @@ function DatasetContextProvider({ children }: { children: React.ReactNode }) {
|
|||||||
|
|
||||||
const { parentId = null } = router.query as { parentId?: string | null };
|
const { parentId = null } = router.query as { parentId?: string | null };
|
||||||
|
|
||||||
const { data: myDatasets = [], runAsync: loadMyDatasets } = useRequest2(
|
const {
|
||||||
|
data: myDatasets = [],
|
||||||
|
runAsync: loadMyDatasets,
|
||||||
|
loading: isFetchingDatasets
|
||||||
|
} = useRequest2(
|
||||||
() =>
|
() =>
|
||||||
getDatasets({
|
getDatasets({
|
||||||
parentId
|
parentId
|
||||||
@@ -83,7 +87,7 @@ function DatasetContextProvider({ children }: { children: React.ReactNode }) {
|
|||||||
() => (parentId ? getDatasetById(parentId) : Promise.resolve(undefined)),
|
() => (parentId ? getDatasetById(parentId) : Promise.resolve(undefined)),
|
||||||
{
|
{
|
||||||
manual: false,
|
manual: false,
|
||||||
refreshDeps: [parentId, myDatasets]
|
refreshDeps: [parentId]
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -95,16 +99,8 @@ function DatasetContextProvider({ children }: { children: React.ReactNode }) {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const { runAsync: refetchDatasets, loading: isFetchingDatasets } = useRequest2(
|
|
||||||
() => loadMyDatasets(),
|
|
||||||
{
|
|
||||||
manual: false,
|
|
||||||
refreshDeps: [parentId]
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const { runAsync: onUpdateDataset } = useRequest2(putDatasetById, {
|
const { runAsync: onUpdateDataset } = useRequest2(putDatasetById, {
|
||||||
onSuccess: () => Promise.all([refetchDatasets(), refetchPaths(), loadMyDatasets()])
|
onSuccess: () => Promise.all([refetchFolderDetail(), refetchPaths(), loadMyDatasets()])
|
||||||
});
|
});
|
||||||
|
|
||||||
const onMoveDataset = useCallback(
|
const onMoveDataset = useCallback(
|
||||||
@@ -138,7 +134,6 @@ function DatasetContextProvider({ children }: { children: React.ReactNode }) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const contextValue = {
|
const contextValue = {
|
||||||
refetchDatasets,
|
|
||||||
isFetchingDatasets,
|
isFetchingDatasets,
|
||||||
setMoveDatasetId,
|
setMoveDatasetId,
|
||||||
paths,
|
paths,
|
||||||
|
@@ -40,8 +40,8 @@ export const getGlobalVariableNode = ({
|
|||||||
flowNodeType: FlowNodeTypeEnum.emptyNode,
|
flowNodeType: FlowNodeTypeEnum.emptyNode,
|
||||||
sourceHandle: getHandleConfig(false, false, false, false),
|
sourceHandle: getHandleConfig(false, false, false, false),
|
||||||
targetHandle: getHandleConfig(false, false, false, false),
|
targetHandle: getHandleConfig(false, false, false, false),
|
||||||
avatar: '/imgs/workflow/variable.png',
|
avatar: 'core/workflow/template/variable',
|
||||||
name: '全局变量',
|
name: t('common:core.module.Variable'),
|
||||||
intro: '',
|
intro: '',
|
||||||
unique: true,
|
unique: true,
|
||||||
forbidDelete: true,
|
forbidDelete: true,
|
||||||
|
Reference in New Issue
Block a user