Compare commits
2 Commits
v4.8.19-al
...
v4.8.19-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c97757e4d | ||
|
|
9f33729ca9 |
BIN
docSite/assets/imgs/dataset3.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
docSite/assets/imgs/dataset4.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
docSite/assets/imgs/faq3.png
Normal file
|
After Width: | Height: | Size: 174 KiB |
BIN
docSite/assets/imgs/other1.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
docSite/assets/imgs/other2.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
docSite/assets/imgs/other3.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
docSite/assets/imgs/quizApp2.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
@@ -29,6 +29,43 @@ images: []
|
|||||||
如图
|
如图
|
||||||

|

|
||||||
|
|
||||||
|
### 数据库3306端口被占用了,启动服务失败
|
||||||
|

|
||||||
|
|
||||||
|
mysql 只有 oneAPI 用到,外面一般不需要调用,所以可以
|
||||||
|
- 把 3306:3306 的映射去掉/或者直接改一个映射。
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# 在 docker-compose.yaml 文件内
|
||||||
|
# ...
|
||||||
|
mysql:
|
||||||
|
image: mysql:8.0.36
|
||||||
|
ports:
|
||||||
|
- 3306:3306 # 这个端口被占用了!
|
||||||
|
# - 3307:3306 # 直接改一个。。和外面的不冲突
|
||||||
|
# *empty* 或者直接删了,反正外面用不到
|
||||||
|
oneapi:
|
||||||
|
container_name: oneapi
|
||||||
|
image: ghcr.io/songquanpeng/one-api:latest
|
||||||
|
environment:
|
||||||
|
- SQL_DSN=root:oneapimmysql@tcp(mysql:3306)/oneapi # 这不用改,容器内外网络是隔离的
|
||||||
|
```
|
||||||
|
- 另一种做法是可以直接连现有的 mysql, 要改 oneAPI 的环境变量。
|
||||||
|
```yaml
|
||||||
|
# 在 docker-compose.yaml 文件内
|
||||||
|
# ...
|
||||||
|
# mysql: # 要连外面的,这个玩意用不到了
|
||||||
|
# image: mysql:8.0.36
|
||||||
|
# ports:
|
||||||
|
# - 3306:3306 # 这个端口被占用了!
|
||||||
|
oneapi:
|
||||||
|
container_name: oneapi
|
||||||
|
image: ghcr.io/songquanpeng/one-api:latest
|
||||||
|
environment:
|
||||||
|
- SQL_DSN=root:oneapimmysql@tcp(mysql:3306)/oneapi # 改成外面的链接字符串
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### 本地部署的限制
|
### 本地部署的限制
|
||||||
|
|
||||||
具体内容参考https://fael3z0zfze.feishu.cn/wiki/OFpAw8XzAi36Guk8dfucrCKUnjg。
|
具体内容参考https://fael3z0zfze.feishu.cn/wiki/OFpAw8XzAi36Guk8dfucrCKUnjg。
|
||||||
|
|||||||
@@ -12,7 +12,11 @@ weight: 806
|
|||||||
|
|
||||||
1. 新增 - 工作流知识库检索支持按知识库权限进行过滤。
|
1. 新增 - 工作流知识库检索支持按知识库权限进行过滤。
|
||||||
2. 新增 - 飞书/语雀知识库查看原文。
|
2. 新增 - 飞书/语雀知识库查看原文。
|
||||||
3. 优化 - 成员列表分页加载。
|
3. 新增 - 流程等待插件,可以等待 n 毫秒后继续执行流程。
|
||||||
4. 优化 - 统一分页加载代码。
|
4. 优化 - 成员列表分页加载。
|
||||||
5. 修复 - 语雀文件库导入时,嵌套文件内容无法展开的问题。
|
5. 优化 - 统一分页加载代码。
|
||||||
6. 修复 - 工作流编排中,LLM 参数无法关闭问题。
|
6. 优化 - 对话页面加载时,可配置是否为独立页面。
|
||||||
|
7. 修复 - 语雀文件库导入时,嵌套文件内容无法展开的问题。
|
||||||
|
8. 修复 - 工作流编排中,LLM 参数无法关闭问题。
|
||||||
|
9. 修复 - 工作流编排中,代码运行节点还原模板问题。
|
||||||
|
10. 修复 - HTTP 接口适配对象字符串解析。
|
||||||
@@ -21,6 +21,19 @@ weight: 908
|
|||||||
|
|
||||||
定时执行会在应用发布后生效,会在后台生效。
|
定时执行会在应用发布后生效,会在后台生效。
|
||||||
|
|
||||||
|
## V4.8.18-FIX2中提到“ 1. 修复 HTTP 节点, {{}} 格式引用变量兼容问题。建议尽快替换 / 模式取变量, {{}} 语法已弃用。”替换{{}}引用格式是仅仅只有在http节点,还是所有节点的都会有影响?
|
||||||
|
|
||||||
|
只有 http 节点用到这个语法。
|
||||||
|
|
||||||
|
## 工作流类型的应用在运行预览可以正常提问返回,但是发布免登录窗口之后有问题。
|
||||||
|
|
||||||
|
一般是没正确发布,在工作流右上角点击【保存并发布】。
|
||||||
|
|
||||||
|
## 如何解决猜你想问使用中文回答显示
|
||||||
|
|
||||||
|
注意需要更新到V4.8.17及以上,把猜你想问的提示词改成中文。
|
||||||
|

|
||||||
|
|
||||||
## AI对话回答要求中的Markdown语法取消
|
## AI对话回答要求中的Markdown语法取消
|
||||||
|
|
||||||
修改知识库默认提示词, 默认用的是标准模板提示词,会要求按 Markdown 输出,可以去除该要求:
|
修改知识库默认提示词, 默认用的是标准模板提示词,会要求按 Markdown 输出,可以去除该要求:
|
||||||
|
|||||||
@@ -24,6 +24,17 @@ xlsx等都可以上传的,不止支持CSV。
|
|||||||
|
|
||||||
统一按gpt3.5标准。
|
统一按gpt3.5标准。
|
||||||
|
|
||||||
|
## 误删除重排模型后,重排模型怎么加入到fastgpt
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
config.json文件里面配置后就可以勾选重排模型
|
||||||
|
|
||||||
|
## 线上平台上创建了应用和知识库,到期之后如果短期内不续费,数据是否会被清理。
|
||||||
|
|
||||||
|
免费版是三十天不登录后清空知识库,应用不会动。其他付费套餐到期后自动切免费版。
|
||||||
|

|
||||||
|
|
||||||
## 基于知识库的查询,但是问题相关的答案过多。ai回答到一半就不继续回答。
|
## 基于知识库的查询,但是问题相关的答案过多。ai回答到一半就不继续回答。
|
||||||
|
|
||||||
FastGPT回复长度计算公式:
|
FastGPT回复长度计算公式:
|
||||||
|
|||||||
@@ -8,4 +8,14 @@ weight: 918
|
|||||||
|
|
||||||
## oneapi 官网是哪个
|
## oneapi 官网是哪个
|
||||||
|
|
||||||
只有开源的 README,没官网,GitHub: https://github.com/songquanpeng/one-api
|
只有开源的 README,没官网,GitHub: https://github.com/songquanpeng/one-api
|
||||||
|
|
||||||
|
## 想做多用户和多chat key
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
多用户问题:只能采取二开或者商业版
|
||||||
|
|
||||||
|
多chat key问题:1. 私有化部署情况下,oneapi解决。2. Saas或者商业版中,可以为每个团队设置单独的key。
|
||||||
|

|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: "循环执行"
|
title: "批量运行"
|
||||||
description: "FastGPT 循环运行节点介绍和使用"
|
description: "FastGPT 批量运行节点介绍和使用"
|
||||||
icon: "input"
|
icon: "input"
|
||||||
draft: false
|
draft: false
|
||||||
toc: true
|
toc: true
|
||||||
@@ -9,15 +9,15 @@ weight: 260
|
|||||||
|
|
||||||
## 节点概述
|
## 节点概述
|
||||||
|
|
||||||
【**循环运行**】节点是 FastGPT V4.8.11 版本新增的一个重要功能模块。它允许工作流对数组类型的输入数据进行迭代处理,每次处理数组中的一个元素,并自动执行后续节点,直到完成整个数组的处理。
|
【**批量运行**】节点是 FastGPT V4.8.11 版本新增的一个重要功能模块。它允许工作流对数组类型的输入数据进行迭代处理,每次处理数组中的一个元素,并自动执行后续节点,直到完成整个数组的处理。
|
||||||
|
|
||||||
这个节点的设计灵感来自编程语言中的循环结构,但以可视化的方式呈现。
|
这个节点的设计灵感来自编程语言中的循环结构,但以可视化的方式呈现。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
> 在程序中,节点可以理解为一个个 Function 或者接口。可以理解为它就是一个**步骤**。将多个节点一个个拼接起来,即可一步步的去实现最终的 AI 输出。
|
> 在程序中,节点可以理解为一个个 Function 或者接口。可以理解为它就是一个**步骤**。将多个节点一个个拼接起来,即可一步步的去实现最终的 AI 输出。
|
||||||
|
|
||||||
【**循环运行**】节点本质上也是一个 Function,它的主要职责是自动化地重复执行特定的工作流程。
|
【**批量运行**】节点本质上也是一个 Function,它的主要职责是自动化地重复执行特定的工作流程。
|
||||||
|
|
||||||
## 核心特性
|
## 核心特性
|
||||||
|
|
||||||
@@ -41,9 +41,9 @@ weight: 260
|
|||||||
|
|
||||||
## 应用场景
|
## 应用场景
|
||||||
|
|
||||||
【**循环运行**】节点的主要作用是通过自动化的方式扩展工作流的处理能力,使 FastGPT 能够更好地处理批量任务和复杂的数据处理流程。特别是在处理大规模数据或需要多轮迭代的场景下,循环运行节点能显著提升工作流的效率和自动化程度。
|
【**批量运行**】节点的主要作用是通过自动化的方式扩展工作流的处理能力,使 FastGPT 能够更好地处理批量任务和复杂的数据处理流程。特别是在处理大规模数据或需要多轮迭代的场景下,批量运行节点能显著提升工作流的效率和自动化程度。
|
||||||
|
|
||||||
【**循环运行**】节点特别适合以下场景:
|
【**批量运行**】节点特别适合以下场景:
|
||||||
|
|
||||||
1. **批量数据处理**
|
1. **批量数据处理**
|
||||||
- 批量翻译文本
|
- 批量翻译文本
|
||||||
@@ -64,7 +64,7 @@ weight: 260
|
|||||||
|
|
||||||
### 输入参数设置
|
### 输入参数设置
|
||||||
|
|
||||||
【**循环运行**】节点需要配置两个核心输入参数:
|
【**批量运行**】节点需要配置两个核心输入参数:
|
||||||
|
|
||||||
1. **数组 (必填)**:接收一个数组类型的输入,可以是:
|
1. **数组 (必填)**:接收一个数组类型的输入,可以是:
|
||||||
- 字符串数组 (`Array<string>`)
|
- 字符串数组 (`Array<string>`)
|
||||||
@@ -95,7 +95,7 @@ weight: 260
|
|||||||
|
|
||||||
### 批量处理数组
|
### 批量处理数组
|
||||||
|
|
||||||
假设我们有一个包含多个文本的数组,需要对每个文本进行 AI 处理。这是循环运行节点最基础也最常见的应用场景。
|
假设我们有一个包含多个文本的数组,需要对每个文本进行 AI 处理。这是批量运行节点最基础也最常见的应用场景。
|
||||||
|
|
||||||
#### 实现步骤
|
#### 实现步骤
|
||||||
|
|
||||||
@@ -114,9 +114,9 @@ weight: 260
|
|||||||
return { textArray: texts };
|
return { textArray: texts };
|
||||||
```
|
```
|
||||||
|
|
||||||
2. 配置循环运行节点
|
2. 配置批量运行节点
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
- 数组输入:选择上一步代码运行节点的输出变量 `textArray`。
|
- 数组输入:选择上一步代码运行节点的输出变量 `textArray`。
|
||||||
- 循环体内添加一个【AI 对话】节点,用于处理每个文本。这里我们输入的 prompt 为:`请将这段文本翻译成英文`。
|
- 循环体内添加一个【AI 对话】节点,用于处理每个文本。这里我们输入的 prompt 为:`请将这段文本翻译成英文`。
|
||||||
@@ -128,7 +128,7 @@ weight: 260
|
|||||||

|

|
||||||
|
|
||||||
1. 【代码运行】节点执行,生成测试数组
|
1. 【代码运行】节点执行,生成测试数组
|
||||||
2. 【循环运行】节点接收数组,开始遍历
|
2. 【批量运行】节点接收数组,开始遍历
|
||||||
3. 对每个数组元素:
|
3. 对每个数组元素:
|
||||||
- 【AI 对话】节点处理当前元素
|
- 【AI 对话】节点处理当前元素
|
||||||
- 【指定回复】节点输出翻译后的文本
|
- 【指定回复】节点输出翻译后的文本
|
||||||
@@ -144,7 +144,7 @@ weight: 260
|
|||||||
- 需要维护上下文的连贯性
|
- 需要维护上下文的连贯性
|
||||||
- 翻译质量需要多轮优化
|
- 翻译质量需要多轮优化
|
||||||
|
|
||||||
【**循环运行**】节点可以很好地解决这些问题。
|
【**批量运行**】节点可以很好地解决这些问题。
|
||||||
|
|
||||||
#### 实现步骤
|
#### 实现步骤
|
||||||
|
|
||||||
@@ -281,9 +281,9 @@ weight: 260
|
|||||||
|
|
||||||
这里我们用到了 [Jina AI 开源的一个强大的正则表达式](https://x.com/JinaAI_/status/1823756993108304135),它能利用所有可能的边界线索和启发式方法来精确切分文本。
|
这里我们用到了 [Jina AI 开源的一个强大的正则表达式](https://x.com/JinaAI_/status/1823756993108304135),它能利用所有可能的边界线索和启发式方法来精确切分文本。
|
||||||
|
|
||||||
2. 配置循环运行节点
|
2. 配置批量运行节点
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
- 数组输入:选择上一步代码运行节点的输出变量 `chunks`。
|
- 数组输入:选择上一步代码运行节点的输出变量 `chunks`。
|
||||||
- 循环体内添加一个【代码运行】节点,对源文本进行格式化。
|
- 循环体内添加一个【代码运行】节点,对源文本进行格式化。
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ export default async function (ctx: FunctionContext): Promise<IResponse>{
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
## 循环执行
|
## 批量运行
|
||||||
|
|
||||||
长文反思翻译比较关键的一个部分,就是对多个文本块进行循环反思翻译
|
长文反思翻译比较关键的一个部分,就是对多个文本块进行循环反思翻译
|
||||||
|
|
||||||
|
|||||||
@@ -91,9 +91,9 @@ weight: 604
|
|||||||
|
|
||||||
这个过程不仅提高了效率,还最大限度地减少了人为错误的可能性。
|
这个过程不仅提高了效率,还最大限度地减少了人为错误的可能性。
|
||||||
|
|
||||||
## 循环执行
|
## 批量运行
|
||||||
|
|
||||||
为了处理整个长字幕文件,我们需要一个循环执行机制。这是通过一个简单但有效的判断模块实现的:
|
为了处理整个长字幕文件,我们需要一个批量运行机制。这是通过一个简单但有效的判断模块实现的:
|
||||||
|
|
||||||
1. 检查当前翻译的文本块是否为最后一个。
|
1. 检查当前翻译的文本块是否为最后一个。
|
||||||
2. 如果不是,则将工作流重定向到格式化原文本块节点。
|
2. 如果不是,则将工作流重定向到格式化原文本块节点。
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export const defaultWhisperConfig: AppWhisperConfigType = {
|
|||||||
export const defaultQGConfig: AppQGConfigType = {
|
export const defaultQGConfig: AppQGConfigType = {
|
||||||
open: false,
|
open: false,
|
||||||
model: 'gpt-4o-mini',
|
model: 'gpt-4o-mini',
|
||||||
customPrompt: PROMPT_QUESTION_GUIDE
|
customPrompt: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
export const defaultChatInputGuideConfig = {
|
export const defaultChatInputGuideConfig = {
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ const staticPluginList = [
|
|||||||
'DingTalkWebhook',
|
'DingTalkWebhook',
|
||||||
'WeWorkWebhook',
|
'WeWorkWebhook',
|
||||||
'google',
|
'google',
|
||||||
'bing'
|
'bing',
|
||||||
|
'delay'
|
||||||
];
|
];
|
||||||
// Run in worker thread (Have npm packages)
|
// Run in worker thread (Have npm packages)
|
||||||
const packagePluginList = [
|
const packagePluginList = [
|
||||||
|
|||||||
18
packages/plugins/src/delay/index.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { delay } from '@fastgpt/global/common/system/utils';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
ms: number;
|
||||||
|
};
|
||||||
|
type Response = Promise<Number>;
|
||||||
|
|
||||||
|
const main = async ({ ms }: Props): Response => {
|
||||||
|
if (typeof ms !== 'number' || ms <= 0 || ms > 300000) {
|
||||||
|
return ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
await delay(ms);
|
||||||
|
|
||||||
|
return ms;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default main;
|
||||||
318
packages/plugins/src/delay/template.json
Normal file
@@ -0,0 +1,318 @@
|
|||||||
|
{
|
||||||
|
"author": "collin",
|
||||||
|
"version": "4817",
|
||||||
|
"name": "流程等待",
|
||||||
|
"avatar": "core/workflow/template/sleep",
|
||||||
|
"intro": "让工作流等待指定时间后运行",
|
||||||
|
"showStatus": true,
|
||||||
|
"weight": 1,
|
||||||
|
|
||||||
|
"isTool": true,
|
||||||
|
"templateType": "tools",
|
||||||
|
|
||||||
|
"workflow": {
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"nodeId": "pluginInput",
|
||||||
|
"name": "workflow:template.plugin_start",
|
||||||
|
"intro": "workflow:intro_plugin_input",
|
||||||
|
"avatar": "core/workflow/template/workflowStart",
|
||||||
|
"flowNodeType": "pluginInput",
|
||||||
|
"showStatus": false,
|
||||||
|
"position": {
|
||||||
|
"x": 627.6352390819724,
|
||||||
|
"y": -165.05298493910118
|
||||||
|
},
|
||||||
|
"version": "481",
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"renderTypeList": ["numberInput", "reference"],
|
||||||
|
"selectedTypeIndex": 0,
|
||||||
|
"valueType": "number",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "延迟时长",
|
||||||
|
"label": "延迟时长",
|
||||||
|
"description": "需要暂停的时间,单位毫秒",
|
||||||
|
"defaultValue": 1000,
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"label": "",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxFiles": 5,
|
||||||
|
"canSelectFile": true,
|
||||||
|
"canSelectImg": true,
|
||||||
|
"required": true,
|
||||||
|
"toolDescription": "需要暂停的时间,单位毫秒",
|
||||||
|
"max": 300000,
|
||||||
|
"min": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"id": "ms",
|
||||||
|
"valueType": "number",
|
||||||
|
"key": "延迟时长",
|
||||||
|
"label": "延迟时长",
|
||||||
|
"type": "hidden"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nodeId": "pluginOutput",
|
||||||
|
"name": "common:core.module.template.self_output",
|
||||||
|
"intro": "workflow:intro_custom_plugin_output",
|
||||||
|
"avatar": "core/workflow/template/pluginOutput",
|
||||||
|
"flowNodeType": "pluginOutput",
|
||||||
|
"showStatus": false,
|
||||||
|
"position": {
|
||||||
|
"x": 1921.839722563351,
|
||||||
|
"y": -160.05298493910115
|
||||||
|
},
|
||||||
|
"version": "481",
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"renderTypeList": ["reference"],
|
||||||
|
"valueType": "any",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "result",
|
||||||
|
"label": "result",
|
||||||
|
"isToolOutput": true,
|
||||||
|
"description": "",
|
||||||
|
"required": true,
|
||||||
|
"value": ["zCJC6zw7c14i", "httpRawResponse"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nodeId": "pluginConfig",
|
||||||
|
"name": "common:core.module.template.system_config",
|
||||||
|
"intro": "",
|
||||||
|
"avatar": "core/workflow/template/systemConfig",
|
||||||
|
"flowNodeType": "pluginConfig",
|
||||||
|
"position": {
|
||||||
|
"x": 184.66337662472682,
|
||||||
|
"y": -216.05298493910115
|
||||||
|
},
|
||||||
|
"version": "4811",
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nodeId": "zCJC6zw7c14i",
|
||||||
|
"name": "HTTP 请求",
|
||||||
|
"intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)",
|
||||||
|
"avatar": "core/workflow/template/httpRequest",
|
||||||
|
"flowNodeType": "httpRequest468",
|
||||||
|
"showStatus": true,
|
||||||
|
"position": {
|
||||||
|
"x": 1154.4041630064592,
|
||||||
|
"y": -455.0529849391012
|
||||||
|
},
|
||||||
|
"version": "481",
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"key": "system_addInputParam",
|
||||||
|
"renderTypeList": ["addInputParam"],
|
||||||
|
"valueType": "dynamic",
|
||||||
|
"label": "",
|
||||||
|
"required": false,
|
||||||
|
"description": "common:core.module.input.description.HTTP Dynamic Input",
|
||||||
|
"customInputConfig": {
|
||||||
|
"selectValueTypeList": [
|
||||||
|
"string",
|
||||||
|
"number",
|
||||||
|
"boolean",
|
||||||
|
"object",
|
||||||
|
"arrayString",
|
||||||
|
"arrayNumber",
|
||||||
|
"arrayBoolean",
|
||||||
|
"arrayObject",
|
||||||
|
"arrayAny",
|
||||||
|
"any",
|
||||||
|
"chatHistory",
|
||||||
|
"datasetQuote",
|
||||||
|
"dynamic",
|
||||||
|
"selectApp",
|
||||||
|
"selectDataset"
|
||||||
|
],
|
||||||
|
"showDescription": false,
|
||||||
|
"showDefaultValue": true
|
||||||
|
},
|
||||||
|
"valueDesc": "",
|
||||||
|
"debugLabel": "",
|
||||||
|
"toolDescription": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpMethod",
|
||||||
|
"renderTypeList": ["custom"],
|
||||||
|
"valueType": "string",
|
||||||
|
"label": "",
|
||||||
|
"value": "POST",
|
||||||
|
"required": true,
|
||||||
|
"valueDesc": "",
|
||||||
|
"description": "",
|
||||||
|
"debugLabel": "",
|
||||||
|
"toolDescription": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpTimeout",
|
||||||
|
"renderTypeList": ["custom"],
|
||||||
|
"valueType": "number",
|
||||||
|
"label": "",
|
||||||
|
"value": 30,
|
||||||
|
"min": 5,
|
||||||
|
"max": 600,
|
||||||
|
"required": true,
|
||||||
|
"valueDesc": "",
|
||||||
|
"description": "",
|
||||||
|
"debugLabel": "",
|
||||||
|
"toolDescription": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpReqUrl",
|
||||||
|
"renderTypeList": ["hidden"],
|
||||||
|
"valueType": "string",
|
||||||
|
"label": "",
|
||||||
|
"description": "common:core.module.input.description.Http Request Url",
|
||||||
|
"placeholder": "https://api.ai.com/getInventory",
|
||||||
|
"required": false,
|
||||||
|
"value": "delay",
|
||||||
|
"valueDesc": "",
|
||||||
|
"debugLabel": "",
|
||||||
|
"toolDescription": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpHeader",
|
||||||
|
"renderTypeList": ["custom"],
|
||||||
|
"valueType": "any",
|
||||||
|
"value": [],
|
||||||
|
"label": "",
|
||||||
|
"description": "common:core.module.input.description.Http Request Header",
|
||||||
|
"placeholder": "common:core.module.input.description.Http Request Header",
|
||||||
|
"required": false,
|
||||||
|
"valueDesc": "",
|
||||||
|
"debugLabel": "",
|
||||||
|
"toolDescription": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpParams",
|
||||||
|
"renderTypeList": ["hidden"],
|
||||||
|
"valueType": "any",
|
||||||
|
"value": [],
|
||||||
|
"label": "",
|
||||||
|
"required": false,
|
||||||
|
"valueDesc": "",
|
||||||
|
"description": "",
|
||||||
|
"debugLabel": "",
|
||||||
|
"toolDescription": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpJsonBody",
|
||||||
|
"renderTypeList": ["hidden"],
|
||||||
|
"valueType": "any",
|
||||||
|
"value": "{\n\"ms\": {{$pluginInput.ms$}}\n}",
|
||||||
|
"label": "",
|
||||||
|
"required": false,
|
||||||
|
"valueDesc": "",
|
||||||
|
"description": "",
|
||||||
|
"debugLabel": "",
|
||||||
|
"toolDescription": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpFormBody",
|
||||||
|
"renderTypeList": ["hidden"],
|
||||||
|
"valueType": "any",
|
||||||
|
"value": [],
|
||||||
|
"label": "",
|
||||||
|
"required": false,
|
||||||
|
"valueDesc": "",
|
||||||
|
"description": "",
|
||||||
|
"debugLabel": "",
|
||||||
|
"toolDescription": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpContentType",
|
||||||
|
"renderTypeList": ["hidden"],
|
||||||
|
"valueType": "string",
|
||||||
|
"value": "json",
|
||||||
|
"label": "",
|
||||||
|
"required": false,
|
||||||
|
"valueDesc": "",
|
||||||
|
"description": "",
|
||||||
|
"debugLabel": "",
|
||||||
|
"toolDescription": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"id": "error",
|
||||||
|
"key": "error",
|
||||||
|
"label": "workflow:request_error",
|
||||||
|
"description": "HTTP请求错误信息,成功时返回空",
|
||||||
|
"valueType": "object",
|
||||||
|
"type": "static"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "httpRawResponse",
|
||||||
|
"key": "httpRawResponse",
|
||||||
|
"required": true,
|
||||||
|
"label": "workflow:raw_response",
|
||||||
|
"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",
|
||||||
|
"arrayAny",
|
||||||
|
"any",
|
||||||
|
"chatHistory",
|
||||||
|
"datasetQuote",
|
||||||
|
"dynamic",
|
||||||
|
"selectApp",
|
||||||
|
"selectDataset"
|
||||||
|
],
|
||||||
|
"showDescription": false,
|
||||||
|
"showDefaultValue": false
|
||||||
|
},
|
||||||
|
"description": "可以通过 JSONPath 语法来提取响应值中的指定字段",
|
||||||
|
"valueDesc": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"edges": [
|
||||||
|
{
|
||||||
|
"source": "pluginInput",
|
||||||
|
"target": "zCJC6zw7c14i",
|
||||||
|
"sourceHandle": "pluginInput-source-right",
|
||||||
|
"targetHandle": "zCJC6zw7c14i-target-left"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "zCJC6zw7c14i",
|
||||||
|
"target": "pluginOutput",
|
||||||
|
"sourceHandle": "zCJC6zw7c14i-source-right",
|
||||||
|
"targetHandle": "pluginOutput-target-left"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"chatConfig": {
|
||||||
|
"welcomeText": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -72,6 +72,7 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
|
|||||||
showStatus: false
|
showStatus: false
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const runtimeVariables = {
|
const runtimeVariables = {
|
||||||
...filterSystemVariables(props.variables),
|
...filterSystemVariables(props.variables),
|
||||||
appId: String(plugin.id)
|
appId: String(plugin.id)
|
||||||
|
|||||||
@@ -127,8 +127,16 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<H
|
|||||||
if (typeof val === 'object') return JSON.stringify(val);
|
if (typeof val === 'object') return JSON.stringify(val);
|
||||||
|
|
||||||
if (typeof val === 'string') {
|
if (typeof val === 'string') {
|
||||||
const str = JSON.stringify(val);
|
try {
|
||||||
return str.startsWith('"') && str.endsWith('"') ? str.slice(1, -1) : str;
|
const parsed = JSON.parse(val);
|
||||||
|
if (typeof parsed === 'object') {
|
||||||
|
return JSON.stringify(parsed);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
} catch (error) {
|
||||||
|
const str = JSON.stringify(val);
|
||||||
|
return str.startsWith('"') && str.endsWith('"') ? str.slice(1, -1) : str;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return String(val);
|
return String(val);
|
||||||
@@ -235,7 +243,9 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<H
|
|||||||
}
|
}
|
||||||
if (!httpJsonBody) return {};
|
if (!httpJsonBody) return {};
|
||||||
if (httpContentType === ContentTypes.json) {
|
if (httpContentType === ContentTypes.json) {
|
||||||
return json5.parse(replaceJsonBodyString(httpJsonBody));
|
httpJsonBody = replaceJsonBodyString(httpJsonBody);
|
||||||
|
console.log(httpJsonBody);
|
||||||
|
return json5.parse(httpJsonBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Raw text, xml
|
// Raw text, xml
|
||||||
|
|||||||
@@ -270,6 +270,7 @@ export const iconPaths = {
|
|||||||
import('./icons/core/workflow/template/datasource.svg'),
|
import('./icons/core/workflow/template/datasource.svg'),
|
||||||
'core/workflow/template/duckduckgo': () =>
|
'core/workflow/template/duckduckgo': () =>
|
||||||
import('./icons/core/workflow/template/duckduckgo.svg'),
|
import('./icons/core/workflow/template/duckduckgo.svg'),
|
||||||
|
'core/workflow/template/sleep': () => import('./icons/core/workflow/template/sleep.svg'),
|
||||||
'core/workflow/template/extractJson': () =>
|
'core/workflow/template/extractJson': () =>
|
||||||
import('./icons/core/workflow/template/extractJson.svg'),
|
import('./icons/core/workflow/template/extractJson.svg'),
|
||||||
'core/workflow/template/fetchUrl': () => import('./icons/core/workflow/template/fetchUrl.svg'),
|
'core/workflow/template/fetchUrl': () => import('./icons/core/workflow/template/fetchUrl.svg'),
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="200" height="200">
|
||||||
|
<path d="M-70.54222222-70.54222222m582.54222222 0l0 0q582.54222222 0 582.54222222 582.54222222l0 0q0 582.54222222-582.54222222 582.54222222l0 0q-582.54222222 0-582.54222222-582.54222222l0 0q0-582.54222222 582.54222222-582.54222222Z"
|
||||||
|
fill="#1296db"/>
|
||||||
|
<path d="M422.64477924 243.86730561H243.86730561v536.26538878h178.77747363V243.86730561zM780.13269439 243.86730561h-178.77747363v536.26538878H780.13269439V243.86730561z"
|
||||||
|
fill="#ffffff"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 593 B |
@@ -135,7 +135,7 @@ const MySelect = <T = any,>(
|
|||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}, []);
|
}, [list, value]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
|
|||||||
@@ -29,8 +29,6 @@ export type ChatProviderProps = {
|
|||||||
outLinkAuthData?: OutLinkChatAuthProps;
|
outLinkAuthData?: OutLinkChatAuthProps;
|
||||||
|
|
||||||
chatType: 'log' | 'chat' | 'share' | 'team';
|
chatType: 'log' | 'chat' | 'share' | 'team';
|
||||||
showRawSource: boolean;
|
|
||||||
showNodeStatus: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type useChatStoreType = ChatProviderProps & {
|
type useChatStoreType = ChatProviderProps & {
|
||||||
@@ -132,8 +130,6 @@ const Provider = ({
|
|||||||
chatId,
|
chatId,
|
||||||
outLinkAuthData = {},
|
outLinkAuthData = {},
|
||||||
chatType = 'chat',
|
chatType = 'chat',
|
||||||
showRawSource,
|
|
||||||
showNodeStatus,
|
|
||||||
children,
|
children,
|
||||||
...props
|
...props
|
||||||
}: ChatProviderProps & {
|
}: ChatProviderProps & {
|
||||||
@@ -249,9 +245,7 @@ const Provider = ({
|
|||||||
chatId,
|
chatId,
|
||||||
outLinkAuthData,
|
outLinkAuthData,
|
||||||
getHistoryResponseData,
|
getHistoryResponseData,
|
||||||
chatType,
|
chatType
|
||||||
showRawSource,
|
|
||||||
showNodeStatus
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return <ChatBoxContext.Provider value={value}>{children}</ChatBoxContext.Provider>;
|
return <ChatBoxContext.Provider value={value}>{children}</ChatBoxContext.Provider>;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import { isEqual } from 'lodash';
|
|||||||
import { useSystem } from '@fastgpt/web/hooks/useSystem';
|
import { useSystem } from '@fastgpt/web/hooks/useSystem';
|
||||||
import { formatTimeToChatItemTime } from '@fastgpt/global/common/string/time';
|
import { formatTimeToChatItemTime } from '@fastgpt/global/common/string/time';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
import { ChatItemContext } from '@/web/core/chat/context/chatItemContext';
|
||||||
|
|
||||||
const colorMap = {
|
const colorMap = {
|
||||||
[ChatStatusEnum.loading]: {
|
[ChatStatusEnum.loading]: {
|
||||||
@@ -139,7 +140,7 @@ const ChatItem = (props: Props) => {
|
|||||||
|
|
||||||
const isChatting = useContextSelector(ChatBoxContext, (v) => v.isChatting);
|
const isChatting = useContextSelector(ChatBoxContext, (v) => v.isChatting);
|
||||||
const chatType = useContextSelector(ChatBoxContext, (v) => v.chatType);
|
const chatType = useContextSelector(ChatBoxContext, (v) => v.chatType);
|
||||||
const showNodeStatus = useContextSelector(ChatBoxContext, (v) => v.showNodeStatus);
|
const showNodeStatus = useContextSelector(ChatItemContext, (v) => v.showNodeStatus);
|
||||||
const isChatLog = chatType === 'log';
|
const isChatLog = chatType === 'log';
|
||||||
|
|
||||||
const { copyData } = useCopyData();
|
const { copyData } = useCopyData();
|
||||||
|
|||||||
@@ -9,19 +9,16 @@ import RawSourceBox from '@/components/core/dataset/RawSourceBox';
|
|||||||
import { getWebReqUrl } from '@fastgpt/web/common/system/utils';
|
import { getWebReqUrl } from '@fastgpt/web/common/system/utils';
|
||||||
import { useContextSelector } from 'use-context-selector';
|
import { useContextSelector } from 'use-context-selector';
|
||||||
import { ChatBoxContext } from '../Provider';
|
import { ChatBoxContext } from '../Provider';
|
||||||
|
import { ChatItemContext } from '@/web/core/chat/context/chatItemContext';
|
||||||
|
|
||||||
const QuoteModal = ({
|
const QuoteModal = ({
|
||||||
rawSearch = [],
|
rawSearch = [],
|
||||||
onClose,
|
onClose,
|
||||||
canEditDataset,
|
|
||||||
showRawSource,
|
|
||||||
chatItemId,
|
chatItemId,
|
||||||
metadata
|
metadata
|
||||||
}: {
|
}: {
|
||||||
rawSearch: SearchDataResponseItemType[];
|
rawSearch: SearchDataResponseItemType[];
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
canEditDataset: boolean;
|
|
||||||
showRawSource: boolean;
|
|
||||||
chatItemId: string;
|
chatItemId: string;
|
||||||
metadata?: {
|
metadata?: {
|
||||||
collectionId: string;
|
collectionId: string;
|
||||||
@@ -47,6 +44,11 @@ const QuoteModal = ({
|
|||||||
chatItemId,
|
chatItemId,
|
||||||
...(v.outLinkAuthData || {})
|
...(v.outLinkAuthData || {})
|
||||||
}));
|
}));
|
||||||
|
const showRawSource = useContextSelector(ChatItemContext, (v) => v.isShowReadRawSource);
|
||||||
|
const showRouteToDatasetDetail = useContextSelector(
|
||||||
|
ChatItemContext,
|
||||||
|
(v) => v.showRouteToDatasetDetail
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -71,12 +73,7 @@ const QuoteModal = ({
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<QuoteList
|
<QuoteList rawSearch={filterResults} chatItemId={chatItemId} />
|
||||||
rawSearch={filterResults}
|
|
||||||
canEditDataset={canEditDataset}
|
|
||||||
canViewSource={showRawSource}
|
|
||||||
chatItemId={chatItemId}
|
|
||||||
/>
|
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
</MyModal>
|
</MyModal>
|
||||||
</>
|
</>
|
||||||
@@ -87,14 +84,10 @@ export default QuoteModal;
|
|||||||
|
|
||||||
export const QuoteList = React.memo(function QuoteList({
|
export const QuoteList = React.memo(function QuoteList({
|
||||||
chatItemId,
|
chatItemId,
|
||||||
rawSearch = [],
|
rawSearch = []
|
||||||
canEditDataset,
|
|
||||||
canViewSource
|
|
||||||
}: {
|
}: {
|
||||||
chatItemId?: string;
|
chatItemId?: string;
|
||||||
rawSearch: SearchDataResponseItemType[];
|
rawSearch: SearchDataResponseItemType[];
|
||||||
canEditDataset: boolean;
|
|
||||||
canViewSource: boolean;
|
|
||||||
}) {
|
}) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
@@ -104,6 +97,11 @@ export const QuoteList = React.memo(function QuoteList({
|
|||||||
chatId: v.chatId,
|
chatId: v.chatId,
|
||||||
...(v.outLinkAuthData || {})
|
...(v.outLinkAuthData || {})
|
||||||
}));
|
}));
|
||||||
|
const showRawSource = useContextSelector(ChatItemContext, (v) => v.isShowReadRawSource);
|
||||||
|
const showRouteToDatasetDetail = useContextSelector(
|
||||||
|
ChatItemContext,
|
||||||
|
(v) => v.showRouteToDatasetDetail
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -120,8 +118,8 @@ export const QuoteList = React.memo(function QuoteList({
|
|||||||
>
|
>
|
||||||
<QuoteItem
|
<QuoteItem
|
||||||
quoteItem={item}
|
quoteItem={item}
|
||||||
canViewSource={canViewSource}
|
canViewSource={showRawSource}
|
||||||
canEditDataset={canEditDataset}
|
canEditDataset={showRouteToDatasetDetail}
|
||||||
{...RawSourceBoxProps}
|
{...RawSourceBoxProps}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ const ResponseTags = ({
|
|||||||
const [quoteFolded, setQuoteFolded] = useState<boolean>(true);
|
const [quoteFolded, setQuoteFolded] = useState<boolean>(true);
|
||||||
|
|
||||||
const chatType = useContextSelector(ChatBoxContext, (v) => v.chatType);
|
const chatType = useContextSelector(ChatBoxContext, (v) => v.chatType);
|
||||||
const showRawSource = useContextSelector(ChatBoxContext, (v) => v.showRawSource);
|
|
||||||
const notSharePage = useMemo(() => chatType !== 'share', [chatType]);
|
const notSharePage = useMemo(() => chatType !== 'share', [chatType]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -251,8 +250,6 @@ const ResponseTags = ({
|
|||||||
<QuoteModal
|
<QuoteModal
|
||||||
{...quoteModalData}
|
{...quoteModalData}
|
||||||
chatItemId={historyItem.dataId}
|
chatItemId={historyItem.dataId}
|
||||||
canEditDataset={notSharePage}
|
|
||||||
showRawSource={showRawSource}
|
|
||||||
onClose={() => setQuoteModalData(undefined)}
|
onClose={() => setQuoteModalData(undefined)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import { Box, Checkbox } from '@chakra-ui/react';
|
|||||||
import { EventNameEnum, eventBus } from '@/web/common/utils/eventbus';
|
import { EventNameEnum, eventBus } from '@/web/common/utils/eventbus';
|
||||||
import { chats2GPTMessages } from '@fastgpt/global/core/chat/adapt';
|
import { chats2GPTMessages } from '@fastgpt/global/core/chat/adapt';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { useRouter } from 'next/router';
|
|
||||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -249,14 +249,7 @@ export const WholeResponseContent = ({
|
|||||||
{activeModule.quoteList && activeModule.quoteList.length > 0 && (
|
{activeModule.quoteList && activeModule.quoteList.length > 0 && (
|
||||||
<Row
|
<Row
|
||||||
label={t('common:core.chat.response.module quoteList')}
|
label={t('common:core.chat.response.module quoteList')}
|
||||||
rawDom={
|
rawDom={<QuoteList chatItemId={dataId} rawSearch={activeModule.quoteList} />}
|
||||||
<QuoteList
|
|
||||||
canEditDataset
|
|
||||||
canViewSource
|
|
||||||
chatItemId={dataId}
|
|
||||||
rawSearch={activeModule.quoteList}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -164,8 +164,6 @@ const DetailLogsModal = ({ appId, chatId, onClose }: Props) => {
|
|||||||
showMarkIcon
|
showMarkIcon
|
||||||
showVoiceIcon={false}
|
showVoiceIcon={false}
|
||||||
chatType="log"
|
chatType="log"
|
||||||
showRawSource
|
|
||||||
showNodeStatus
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
@@ -187,7 +185,12 @@ const Render = (props: Props) => {
|
|||||||
}, [appId, chatId]);
|
}, [appId, chatId]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChatItemContextProvider>
|
<ChatItemContextProvider
|
||||||
|
showRouteToAppDetail={true}
|
||||||
|
showRouteToDatasetDetail={true}
|
||||||
|
isShowReadRawSource={true}
|
||||||
|
showNodeStatus
|
||||||
|
>
|
||||||
<ChatRecordContextProvider params={params}>
|
<ChatRecordContextProvider params={params}>
|
||||||
<DetailLogsModal {...props} />
|
<DetailLogsModal {...props} />
|
||||||
</ChatRecordContextProvider>
|
</ChatRecordContextProvider>
|
||||||
|
|||||||
@@ -91,7 +91,12 @@ const Render = ({ appForm }: Props) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChatItemContextProvider>
|
<ChatItemContextProvider
|
||||||
|
showRouteToAppDetail={true}
|
||||||
|
showRouteToDatasetDetail={true}
|
||||||
|
isShowReadRawSource={true}
|
||||||
|
showNodeStatus
|
||||||
|
>
|
||||||
<ChatRecordContextProvider params={chatRecordProviderParams}>
|
<ChatRecordContextProvider params={chatRecordProviderParams}>
|
||||||
<ChatTest appForm={appForm} />
|
<ChatTest appForm={appForm} />
|
||||||
</ChatRecordContextProvider>
|
</ChatRecordContextProvider>
|
||||||
|
|||||||
@@ -158,7 +158,12 @@ const Render = (Props: Props) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChatItemContextProvider>
|
<ChatItemContextProvider
|
||||||
|
showRouteToAppDetail={true}
|
||||||
|
showRouteToDatasetDetail={true}
|
||||||
|
isShowReadRawSource={true}
|
||||||
|
showNodeStatus
|
||||||
|
>
|
||||||
<ChatRecordContextProvider params={chatRecordProviderParams}>
|
<ChatRecordContextProvider params={chatRecordProviderParams}>
|
||||||
<ChatTest {...Props} />
|
<ChatTest {...Props} />
|
||||||
</ChatRecordContextProvider>
|
</ChatRecordContextProvider>
|
||||||
|
|||||||
@@ -14,22 +14,18 @@ import RenderToolInput from './render/RenderToolInput';
|
|||||||
import RenderOutput from './render/RenderOutput';
|
import RenderOutput from './render/RenderOutput';
|
||||||
import CodeEditor from '@fastgpt/web/components/common/Textarea/CodeEditor';
|
import CodeEditor from '@fastgpt/web/components/common/Textarea/CodeEditor';
|
||||||
import { Box, Flex } from '@chakra-ui/react';
|
import { Box, Flex } from '@chakra-ui/react';
|
||||||
import { useI18n } from '@/web/context/I18n';
|
|
||||||
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
|
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
|
||||||
import { getLatestNodeTemplate } from '@/web/core/workflow/utils';
|
import { JS_TEMPLATE } from '@fastgpt/global/core/workflow/template/system/sandbox/constants';
|
||||||
import { CodeNode } from '@fastgpt/global/core/workflow/template/system/sandbox';
|
|
||||||
|
|
||||||
const NodeCode = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
const NodeCode = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { workflowT } = useI18n();
|
|
||||||
const { nodeId, inputs, outputs } = data;
|
const { nodeId, inputs, outputs } = data;
|
||||||
const { splitToolInputs, onChangeNode, onResetNode } = useContextSelector(
|
|
||||||
WorkflowContext,
|
const splitToolInputs = useContextSelector(WorkflowContext, (ctx) => ctx.splitToolInputs);
|
||||||
(ctx) => ctx
|
const onChangeNode = useContextSelector(WorkflowContext, (ctx) => ctx.onChangeNode);
|
||||||
);
|
|
||||||
|
|
||||||
const { ConfirmModal, openConfirm } = useConfirm({
|
const { ConfirmModal, openConfirm } = useConfirm({
|
||||||
content: workflowT('code.Reset template confirm')
|
content: t('workflow:code.Reset template confirm')
|
||||||
});
|
});
|
||||||
|
|
||||||
const CustomComponent = useMemo(() => {
|
const CustomComponent = useMemo(() => {
|
||||||
@@ -38,19 +34,24 @@ const NodeCode = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
|||||||
return (
|
return (
|
||||||
<Box mt={-3}>
|
<Box mt={-3}>
|
||||||
<Flex mb={2} alignItems={'flex-end'}>
|
<Flex mb={2} alignItems={'flex-end'}>
|
||||||
<Box flex={'1'}>{'Javascript ' + workflowT('Code')}</Box>
|
<Box flex={'1'}>{'Javascript ' + t('workflow:Code')}</Box>
|
||||||
<Box
|
<Box
|
||||||
cursor={'pointer'}
|
cursor={'pointer'}
|
||||||
color={'primary.500'}
|
color={'primary.500'}
|
||||||
fontSize={'xs'}
|
fontSize={'xs'}
|
||||||
onClick={openConfirm(() => {
|
onClick={openConfirm(() => {
|
||||||
onResetNode({
|
onChangeNode({
|
||||||
id: nodeId,
|
nodeId,
|
||||||
node: getLatestNodeTemplate(data, CodeNode)
|
type: 'updateInput',
|
||||||
|
key: item.key,
|
||||||
|
value: {
|
||||||
|
...item,
|
||||||
|
value: JS_TEMPLATE
|
||||||
|
}
|
||||||
});
|
});
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{workflowT('code.Reset template')}
|
{t('workflow:code.Reset template')}
|
||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
@@ -73,37 +74,33 @@ const NodeCode = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [data, nodeId, onChangeNode, onResetNode, openConfirm, workflowT]);
|
}, [nodeId, onChangeNode, openConfirm, t]);
|
||||||
|
|
||||||
const Render = useMemo(() => {
|
const { isTool, commonInputs } = splitToolInputs(inputs, nodeId);
|
||||||
const { isTool, commonInputs } = splitToolInputs(inputs, nodeId);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodeCard minW={'400px'} selected={selected} {...data}>
|
<NodeCard minW={'400px'} selected={selected} {...data}>
|
||||||
{isTool && (
|
{isTool && (
|
||||||
<>
|
<>
|
||||||
<Container>
|
<Container>
|
||||||
<RenderToolInput nodeId={nodeId} inputs={inputs} />
|
<RenderToolInput nodeId={nodeId} inputs={inputs} />
|
||||||
</Container>
|
</Container>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<Container>
|
<Container>
|
||||||
<IOTitle text={t('common:common.Input')} mb={-1} />
|
<IOTitle text={t('common:common.Input')} mb={-1} />
|
||||||
<RenderInput
|
<RenderInput
|
||||||
nodeId={nodeId}
|
nodeId={nodeId}
|
||||||
flowInputList={commonInputs}
|
flowInputList={commonInputs}
|
||||||
CustomComponent={CustomComponent}
|
CustomComponent={CustomComponent}
|
||||||
/>
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
<Container>
|
<Container>
|
||||||
<IOTitle text={t('common:common.Output')} />
|
<IOTitle text={t('common:common.Output')} />
|
||||||
<RenderOutput nodeId={nodeId} flowOutputList={outputs} />
|
<RenderOutput nodeId={nodeId} flowOutputList={outputs} />
|
||||||
</Container>
|
</Container>
|
||||||
<ConfirmModal />
|
<ConfirmModal />
|
||||||
</NodeCard>
|
</NodeCard>
|
||||||
);
|
);
|
||||||
}, [ConfirmModal, CustomComponent, data, inputs, nodeId, outputs, selected, splitToolInputs, t]);
|
|
||||||
|
|
||||||
return Render;
|
|
||||||
};
|
};
|
||||||
export default React.memo(NodeCode);
|
export default React.memo(NodeCode);
|
||||||
|
|||||||
@@ -141,8 +141,6 @@ export const useChatTest = ({
|
|||||||
chatId={chatId}
|
chatId={chatId}
|
||||||
showMarkIcon
|
showMarkIcon
|
||||||
chatType="chat"
|
chatType="chat"
|
||||||
showRawSource
|
|
||||||
showNodeStatus
|
|
||||||
onStartChat={startChat}
|
onStartChat={startChat}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -27,13 +27,11 @@ const ChatHeader = ({
|
|||||||
history,
|
history,
|
||||||
showHistory,
|
showHistory,
|
||||||
apps,
|
apps,
|
||||||
onRouteToAppDetail,
|
|
||||||
totalRecordsCount
|
totalRecordsCount
|
||||||
}: {
|
}: {
|
||||||
history: ChatItemType[];
|
history: ChatItemType[];
|
||||||
showHistory?: boolean;
|
showHistory?: boolean;
|
||||||
apps?: AppListItemType[];
|
apps?: AppListItemType[];
|
||||||
onRouteToAppDetail?: () => void;
|
|
||||||
totalRecordsCount: number;
|
totalRecordsCount: number;
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -71,7 +69,7 @@ const ChatHeader = ({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* control */}
|
{/* control */}
|
||||||
{!isPlugin && <ToolMenu history={history} onRouteToAppDetail={onRouteToAppDetail} />}
|
{!isPlugin && <ToolMenu history={history} />}
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ type HistoryItemType = {
|
|||||||
const ChatHistorySlider = ({ confirmClearText }: { confirmClearText: string }) => {
|
const ChatHistorySlider = ({ confirmClearText }: { confirmClearText: string }) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const isUserChatPage = router.pathname === '/chat';
|
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -46,6 +45,7 @@ const ChatHistorySlider = ({ confirmClearText }: { confirmClearText: string }) =
|
|||||||
|
|
||||||
const appName = useContextSelector(ChatItemContext, (v) => v.chatBoxData?.app.name);
|
const appName = useContextSelector(ChatItemContext, (v) => v.chatBoxData?.app.name);
|
||||||
const appAvatar = useContextSelector(ChatItemContext, (v) => v.chatBoxData?.app.avatar);
|
const appAvatar = useContextSelector(ChatItemContext, (v) => v.chatBoxData?.app.avatar);
|
||||||
|
const showRouteToAppDetail = useContextSelector(ChatItemContext, (v) => v.showRouteToAppDetail);
|
||||||
|
|
||||||
const concatHistory = useMemo(() => {
|
const concatHistory = useMemo(() => {
|
||||||
const formatHistories: HistoryItemType[] = histories.map((item) => {
|
const formatHistories: HistoryItemType[] = histories.map((item) => {
|
||||||
@@ -77,8 +77,8 @@ const ChatHistorySlider = ({ confirmClearText }: { confirmClearText: string }) =
|
|||||||
});
|
});
|
||||||
|
|
||||||
const canRouteToDetail = useMemo(
|
const canRouteToDetail = useMemo(
|
||||||
() => appId && userInfo?.team.permission.hasWritePer,
|
() => appId && userInfo?.team.permission.hasWritePer && showRouteToAppDetail,
|
||||||
[appId, userInfo?.team.permission.hasWritePer]
|
[appId, userInfo?.team.permission.hasWritePer, showRouteToAppDetail]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -287,7 +287,7 @@ const ChatHistorySlider = ({ confirmClearText }: { confirmClearText: string }) =
|
|||||||
</ScrollData>
|
</ScrollData>
|
||||||
|
|
||||||
{/* exec */}
|
{/* exec */}
|
||||||
{!isPc && isUserChatPage && (
|
{!isPc && !!canRouteToDetail && (
|
||||||
<Flex
|
<Flex
|
||||||
mt={2}
|
mt={2}
|
||||||
borderTop={theme.borders.base}
|
borderTop={theme.borders.base}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import {
|
|||||||
} from '@fastgpt/global/common/parentFolder/type';
|
} from '@fastgpt/global/common/parentFolder/type';
|
||||||
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
|
import { ChatItemContext } from '@/web/core/chat/context/chatItemContext';
|
||||||
|
import { useContextSelector } from 'use-context-selector';
|
||||||
|
|
||||||
const SelectOneResource = dynamic(() => import('@/components/common/folder/SelectOneResource'));
|
const SelectOneResource = dynamic(() => import('@/components/common/folder/SelectOneResource'));
|
||||||
|
|
||||||
@@ -22,6 +24,8 @@ const SliderApps = ({ apps, activeAppId }: { apps: AppListItemType[]; activeAppI
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const isTeamChat = router.pathname === '/chat/team';
|
const isTeamChat = router.pathname === '/chat/team';
|
||||||
|
|
||||||
|
const showRouteToAppDetail = useContextSelector(ChatItemContext, (v) => v.showRouteToAppDetail);
|
||||||
|
|
||||||
const getAppList = useCallback(async ({ parentId }: GetResourceFolderListProps) => {
|
const getAppList = useCallback(async ({ parentId }: GetResourceFolderListProps) => {
|
||||||
return getMyApps({
|
return getMyApps({
|
||||||
parentId,
|
parentId,
|
||||||
@@ -50,34 +54,36 @@ const SliderApps = ({ apps, activeAppId }: { apps: AppListItemType[]; activeAppI
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex flexDirection={'column'} h={'100%'}>
|
<Flex flexDirection={'column'} h={'100%'}>
|
||||||
<Box mt={4} px={4}>
|
{showRouteToAppDetail && (
|
||||||
{!isTeamChat && (
|
<>
|
||||||
<Flex
|
<Box mt={4} px={4}>
|
||||||
alignItems={'center'}
|
<Flex
|
||||||
cursor={'pointer'}
|
alignItems={'center'}
|
||||||
py={2}
|
cursor={'pointer'}
|
||||||
px={3}
|
py={2}
|
||||||
borderRadius={'md'}
|
px={3}
|
||||||
_hover={{ bg: 'myGray.200' }}
|
borderRadius={'md'}
|
||||||
onClick={() => router.push('/app/list')}
|
_hover={{ bg: 'myGray.200' }}
|
||||||
>
|
onClick={() => router.push('/app/list')}
|
||||||
<IconButton
|
>
|
||||||
mr={3}
|
<IconButton
|
||||||
icon={<MyIcon name={'common/backFill'} w={'1rem'} color={'primary.500'} />}
|
mr={3}
|
||||||
bg={'white'}
|
icon={<MyIcon name={'common/backFill'} w={'1rem'} color={'primary.500'} />}
|
||||||
boxShadow={'1px 1px 9px rgba(0,0,0,0.15)'}
|
bg={'white'}
|
||||||
size={'smSquare'}
|
boxShadow={'1px 1px 9px rgba(0,0,0,0.15)'}
|
||||||
borderRadius={'50%'}
|
size={'smSquare'}
|
||||||
aria-label={''}
|
borderRadius={'50%'}
|
||||||
/>
|
aria-label={''}
|
||||||
{t('common:core.chat.Exit Chat')}
|
/>
|
||||||
</Flex>
|
{t('common:core.chat.Exit Chat')}
|
||||||
)}
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
|
<MyDivider h={2} my={1} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
{!isTeamChat && (
|
{!isTeamChat && (
|
||||||
<>
|
<>
|
||||||
<MyDivider h={2} my={1} />
|
|
||||||
<HStack
|
<HStack
|
||||||
px={4}
|
px={4}
|
||||||
my={2}
|
my={2}
|
||||||
|
|||||||
@@ -7,20 +7,19 @@ import MyIcon from '@fastgpt/web/components/common/Icon';
|
|||||||
import MyMenu from '@fastgpt/web/components/common/MyMenu';
|
import MyMenu from '@fastgpt/web/components/common/MyMenu';
|
||||||
import { useContextSelector } from 'use-context-selector';
|
import { useContextSelector } from 'use-context-selector';
|
||||||
import { ChatContext } from '@/web/core/chat/context/chatContext';
|
import { ChatContext } from '@/web/core/chat/context/chatContext';
|
||||||
|
import { ChatItemContext } from '@/web/core/chat/context/chatItemContext';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
const ToolMenu = ({
|
const ToolMenu = ({ history }: { history: ChatItemType[] }) => {
|
||||||
history,
|
const router = useRouter();
|
||||||
onRouteToAppDetail
|
|
||||||
}: {
|
|
||||||
history: ChatItemType[];
|
|
||||||
onRouteToAppDetail?: () => void;
|
|
||||||
}) => {
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { onExportChat } = useChatBox();
|
const { onExportChat } = useChatBox();
|
||||||
|
|
||||||
const onChangeChatId = useContextSelector(ChatContext, (v) => v.onChangeChatId);
|
const onChangeChatId = useContextSelector(ChatContext, (v) => v.onChangeChatId);
|
||||||
|
const chatData = useContextSelector(ChatItemContext, (v) => v.chatBoxData);
|
||||||
|
const showRouteToAppDetail = useContextSelector(ChatItemContext, (v) => v.showRouteToAppDetail);
|
||||||
|
|
||||||
return history.length > 0 ? (
|
return (
|
||||||
<MyMenu
|
<MyMenu
|
||||||
Button={
|
Button={
|
||||||
<IconButton
|
<IconButton
|
||||||
@@ -61,14 +60,14 @@ const ToolMenu = ({
|
|||||||
// }
|
// }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
...(onRouteToAppDetail
|
...(showRouteToAppDetail
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
icon: 'core/app/aiLight',
|
icon: 'core/app/aiLight',
|
||||||
label: t('app:app_detail'),
|
label: t('app:app_detail'),
|
||||||
onClick: onRouteToAppDetail
|
onClick: () => router.push(`/app/detail?appId=${chatData.appId}`)
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -76,8 +75,6 @@ const ToolMenu = ({
|
|||||||
: [])
|
: [])
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
) : (
|
|
||||||
<Box w={'28px'} h={'28px'} />
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { isPc } = useSystem();
|
const { isPc } = useSystem();
|
||||||
|
|
||||||
const { userInfo } = useUserStore();
|
const { userInfo } = useUserStore();
|
||||||
const { setLastChatAppId, chatId, appId, outLinkAuthData } = useChatStore();
|
const { setLastChatAppId, chatId, appId, outLinkAuthData } = useChatStore();
|
||||||
|
|
||||||
@@ -186,7 +187,6 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
|
|||||||
apps={myApps}
|
apps={myApps}
|
||||||
history={chatRecords}
|
history={chatRecords}
|
||||||
showHistory
|
showHistory
|
||||||
onRouteToAppDetail={() => router.push(`/app/detail?appId=${appId}`)}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* chat box */}
|
{/* chat box */}
|
||||||
@@ -208,8 +208,6 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
|
|||||||
feedbackType={'user'}
|
feedbackType={'user'}
|
||||||
onStartChat={onStartChat}
|
onStartChat={onStartChat}
|
||||||
chatType={'chat'}
|
chatType={'chat'}
|
||||||
showRawSource
|
|
||||||
showNodeStatus
|
|
||||||
isReady={!loading}
|
isReady={!loading}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -221,8 +219,8 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Render = (props: { appId: string }) => {
|
const Render = (props: { appId: string; isStandalone?: string }) => {
|
||||||
const { appId } = props;
|
const { appId, isStandalone } = props;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -276,7 +274,12 @@ const Render = (props: { appId: string }) => {
|
|||||||
|
|
||||||
return source === ChatSourceEnum.online ? (
|
return source === ChatSourceEnum.online ? (
|
||||||
<ChatContextProvider params={chatHistoryProviderParams}>
|
<ChatContextProvider params={chatHistoryProviderParams}>
|
||||||
<ChatItemContextProvider>
|
<ChatItemContextProvider
|
||||||
|
showRouteToAppDetail={isStandalone !== '1'}
|
||||||
|
showRouteToDatasetDetail={isStandalone !== '1'}
|
||||||
|
isShowReadRawSource={true}
|
||||||
|
showNodeStatus
|
||||||
|
>
|
||||||
<ChatRecordContextProvider params={chatRecordProviderParams}>
|
<ChatRecordContextProvider params={chatRecordProviderParams}>
|
||||||
<Chat myApps={myApps} />
|
<Chat myApps={myApps} />
|
||||||
</ChatRecordContextProvider>
|
</ChatRecordContextProvider>
|
||||||
@@ -289,6 +292,7 @@ export async function getServerSideProps(context: any) {
|
|||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
appId: context?.query?.appId || '',
|
appId: context?.query?.appId || '',
|
||||||
|
isStandalone: context?.query?.isStandalone || '',
|
||||||
...(await serviceSideProps(context, ['file', 'app', 'chat', 'workflow']))
|
...(await serviceSideProps(context, ['file', 'app', 'chat', 'workflow']))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ type Props = {
|
|||||||
const OutLink = (props: Props) => {
|
const OutLink = (props: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { showRawSource, showNodeStatus } = props;
|
|
||||||
const {
|
const {
|
||||||
shareId = '',
|
shareId = '',
|
||||||
showHistory = '1',
|
showHistory = '1',
|
||||||
@@ -287,8 +286,6 @@ const OutLink = (props: Props) => {
|
|||||||
feedbackType={'user'}
|
feedbackType={'user'}
|
||||||
onStartChat={startChat}
|
onStartChat={startChat}
|
||||||
chatType="share"
|
chatType="share"
|
||||||
showRawSource={showRawSource}
|
|
||||||
showNodeStatus={showNodeStatus}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
@@ -340,7 +337,12 @@ const Render = (props: Props) => {
|
|||||||
|
|
||||||
return source === ChatSourceEnum.share ? (
|
return source === ChatSourceEnum.share ? (
|
||||||
<ChatContextProvider params={chatHistoryProviderParams}>
|
<ChatContextProvider params={chatHistoryProviderParams}>
|
||||||
<ChatItemContextProvider>
|
<ChatItemContextProvider
|
||||||
|
showRouteToAppDetail={false}
|
||||||
|
showRouteToDatasetDetail={false}
|
||||||
|
isShowReadRawSource={props.showRawSource}
|
||||||
|
showNodeStatus={props.showNodeStatus}
|
||||||
|
>
|
||||||
<ChatRecordContextProvider params={chatRecordProviderParams}>
|
<ChatRecordContextProvider params={chatRecordProviderParams}>
|
||||||
<OutLink {...props} />
|
<OutLink {...props} />
|
||||||
</ChatRecordContextProvider>
|
</ChatRecordContextProvider>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
import React, { useCallback, useEffect, useMemo } from 'react';
|
||||||
import NextHead from '@/components/common/NextHead';
|
import NextHead from '@/components/common/NextHead';
|
||||||
import { getTeamChatInfo } from '@/web/core/chat/api';
|
import { getTeamChatInfo } from '@/web/core/chat/api';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
@@ -20,8 +20,7 @@ import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
|||||||
import ChatContextProvider, { ChatContext } from '@/web/core/chat/context/chatContext';
|
import ChatContextProvider, { ChatContext } from '@/web/core/chat/context/chatContext';
|
||||||
import { AppListItemType } from '@fastgpt/global/core/app/type';
|
import { AppListItemType } from '@fastgpt/global/core/app/type';
|
||||||
import { useContextSelector } from 'use-context-selector';
|
import { useContextSelector } from 'use-context-selector';
|
||||||
import { InitChatResponse } from '@/global/core/chat/api';
|
import { GetChatTypeEnum } from '@/global/core/chat/constants';
|
||||||
import { defaultChatData, GetChatTypeEnum } from '@/global/core/chat/constants';
|
|
||||||
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
||||||
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||||
|
|
||||||
@@ -226,8 +225,6 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
|
|||||||
feedbackType={'user'}
|
feedbackType={'user'}
|
||||||
onStartChat={startChat}
|
onStartChat={startChat}
|
||||||
chatType="team"
|
chatType="team"
|
||||||
showRawSource
|
|
||||||
showNodeStatus
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
@@ -299,7 +296,12 @@ const Render = (props: Props) => {
|
|||||||
|
|
||||||
return source === ChatSourceEnum.team ? (
|
return source === ChatSourceEnum.team ? (
|
||||||
<ChatContextProvider params={contextParams}>
|
<ChatContextProvider params={contextParams}>
|
||||||
<ChatItemContextProvider>
|
<ChatItemContextProvider
|
||||||
|
showRouteToAppDetail={false}
|
||||||
|
showRouteToDatasetDetail={false}
|
||||||
|
isShowReadRawSource={true}
|
||||||
|
showNodeStatus
|
||||||
|
>
|
||||||
<ChatRecordContextProvider params={chatRecordProviderParams}>
|
<ChatRecordContextProvider params={chatRecordProviderParams}>
|
||||||
<Chat {...props} myApps={myApps} />
|
<Chat {...props} myApps={myApps} />
|
||||||
</ChatRecordContextProvider>
|
</ChatRecordContextProvider>
|
||||||
|
|||||||
@@ -9,6 +9,12 @@ import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
|||||||
import { AppChatConfigType, VariableItemType } from '@fastgpt/global/core/app/type';
|
import { AppChatConfigType, VariableItemType } from '@fastgpt/global/core/app/type';
|
||||||
import { FlowNodeInputItemType } from '@fastgpt/global/core/workflow/type/io';
|
import { FlowNodeInputItemType } from '@fastgpt/global/core/workflow/type/io';
|
||||||
|
|
||||||
|
type ContextProps = {
|
||||||
|
showRouteToAppDetail: boolean;
|
||||||
|
showRouteToDatasetDetail: boolean;
|
||||||
|
isShowReadRawSource: boolean;
|
||||||
|
showNodeStatus: boolean;
|
||||||
|
};
|
||||||
type ChatBoxDataType = {
|
type ChatBoxDataType = {
|
||||||
appId: string;
|
appId: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
@@ -37,7 +43,7 @@ type ChatItemContextType = {
|
|||||||
chatBoxData: ChatBoxDataType;
|
chatBoxData: ChatBoxDataType;
|
||||||
setChatBoxData: React.Dispatch<React.SetStateAction<ChatBoxDataType>>;
|
setChatBoxData: React.Dispatch<React.SetStateAction<ChatBoxDataType>>;
|
||||||
isPlugin: boolean;
|
isPlugin: boolean;
|
||||||
};
|
} & ContextProps;
|
||||||
|
|
||||||
export const ChatItemContext = createContext<ChatItemContextType>({
|
export const ChatItemContext = createContext<ChatItemContextType>({
|
||||||
ChatBoxRef: null,
|
ChatBoxRef: null,
|
||||||
@@ -61,7 +67,15 @@ export const ChatItemContext = createContext<ChatItemContextType>({
|
|||||||
/*
|
/*
|
||||||
Chat 对象的上下文
|
Chat 对象的上下文
|
||||||
*/
|
*/
|
||||||
const ChatItemContextProvider = ({ children }: { children: ReactNode }) => {
|
const ChatItemContextProvider = ({
|
||||||
|
children,
|
||||||
|
showRouteToAppDetail,
|
||||||
|
showRouteToDatasetDetail,
|
||||||
|
isShowReadRawSource,
|
||||||
|
showNodeStatus
|
||||||
|
}: {
|
||||||
|
children: ReactNode;
|
||||||
|
} & ContextProps) => {
|
||||||
const ChatBoxRef = useRef<ChatComponentRef>(null);
|
const ChatBoxRef = useRef<ChatComponentRef>(null);
|
||||||
const variablesForm = useForm<ChatBoxInputFormType>();
|
const variablesForm = useForm<ChatBoxInputFormType>();
|
||||||
|
|
||||||
@@ -113,16 +127,23 @@ const ChatItemContextProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
pluginRunTab,
|
pluginRunTab,
|
||||||
setPluginRunTab,
|
setPluginRunTab,
|
||||||
resetVariables,
|
resetVariables,
|
||||||
clearChatRecords
|
clearChatRecords,
|
||||||
|
showRouteToAppDetail,
|
||||||
|
showRouteToDatasetDetail,
|
||||||
|
isShowReadRawSource,
|
||||||
|
showNodeStatus
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
chatBoxData,
|
chatBoxData,
|
||||||
setChatBoxData,
|
|
||||||
clearChatRecords,
|
|
||||||
isPlugin,
|
isPlugin,
|
||||||
|
variablesForm,
|
||||||
pluginRunTab,
|
pluginRunTab,
|
||||||
resetVariables,
|
resetVariables,
|
||||||
variablesForm
|
clearChatRecords,
|
||||||
|
showRouteToAppDetail,
|
||||||
|
showRouteToDatasetDetail,
|
||||||
|
isShowReadRawSource,
|
||||||
|
showNodeStatus
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return <ChatItemContext.Provider value={contextValue}>{children}</ChatItemContext.Provider>;
|
return <ChatItemContext.Provider value={contextValue}>{children}</ChatItemContext.Provider>;
|
||||||
|
|||||||