Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
赵月辉
/
fastgpt-migrated
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
e01c38ef
authored
Dec 07, 2023
by
Archer
Committed by
GitHub
Dec 07, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
4.6.4-alpha (#569)
parent
71afe711
Hide whitespace changes
Inline
Side-by-side
Showing
78 changed files
with
1348 additions
and
1056 deletions
+1348
-1056
docSite/content/docs/development/openapi/share.md
+135
-39
packages/global/common/error/code/outLink.ts
+7
-1
packages/global/core/chat/api.d.ts
+0
-33
packages/global/core/chat/constants.ts
+6
-0
packages/global/core/chat/type.d.ts
+12
-5
packages/global/core/dataset/api.d.ts
+1
-1
packages/global/support/outLink/api.d.ts
+7
-22
packages/global/support/outLink/type.d.ts
+0
-1
packages/global/support/user/team/constant.ts
+1
-1
packages/global/support/user/team/type.d.ts
+12
-2
packages/service/common/mongo/init.ts
+6
-2
packages/service/core/chat/chatSchema.ts
+13
-8
packages/service/core/chat/controller.ts
+22
-0
packages/service/support/outLink/schema.ts
+0
-4
packages/service/support/outLink/tools.ts
+4
-4
packages/service/support/permission/auth/app.ts
+2
-0
packages/service/support/permission/auth/chat.ts
+0
-67
packages/service/support/permission/auth/common.ts
+3
-3
packages/service/support/permission/auth/outLink.ts
+5
-7
packages/service/support/user/controller.ts
+57
-0
packages/service/support/user/team/controller.ts
+20
-49
packages/service/support/user/team/teamMemberSchema.ts
+51
-0
packages/service/support/user/team/teamSchema.ts
+41
-0
projects/app/public/locales/en/common.json
+5
-1
projects/app/public/locales/zh/common.json
+10
-6
projects/app/src/components/ChatBox/ResponseTags.tsx
+1
-1
projects/app/src/components/ChatBox/WholeResponseModal.tsx
+1
-1
projects/app/src/components/ChatBox/index.tsx
+15
-10
projects/app/src/components/core/module/DatasetParamsModal.tsx
+2
-2
projects/app/src/global/core/chat/api.d.ts
+68
-0
projects/app/src/global/core/chat/constants.ts
+15
-0
projects/app/src/global/core/prompt/AIChat.ts
+4
-6
projects/app/src/pages/account/components/PayModal.tsx
+1
-1
projects/app/src/pages/api/common/system/unlockTask.ts
+2
-20
projects/app/src/pages/api/core/app/del.ts
+4
-0
projects/app/src/pages/api/core/app/form2Modules/fastgpt-simple.ts
+1
-1
projects/app/src/pages/api/core/app/form2Modules/fastgpt-universal.ts
+1
-1
projects/app/src/pages/api/core/chat/chatTest.ts
+11
-5
projects/app/src/pages/api/core/chat/clearHistories.ts
+37
-33
projects/app/src/pages/api/core/chat/delHistory.ts
+38
-0
projects/app/src/pages/api/core/chat/feedback/adminUpdate.ts
+1
-1
projects/app/src/pages/api/core/chat/getHistories.ts
+32
-13
projects/app/src/pages/api/core/chat/init.ts
+23
-40
projects/app/src/pages/api/core/chat/initLocalShareHistoryV464.ts
+42
-0
projects/app/src/pages/api/core/chat/item/delete.ts
+11
-3
projects/app/src/pages/api/core/chat/outLink/init.ts
+85
-0
projects/app/src/pages/api/core/chat/updateHistory.ts
+12
-5
projects/app/src/pages/api/core/dataset/update.ts
+3
-3
projects/app/src/pages/api/support/outLink/init.ts
+0
-51
projects/app/src/pages/api/user/account/loginByPassword.ts
+1
-1
projects/app/src/pages/api/user/account/tokenLogin.ts
+1
-1
projects/app/src/pages/api/v1/audio/transcriptions.ts
+1
-1
projects/app/src/pages/api/v1/chat/completions.ts
+36
-21
projects/app/src/pages/api/v1/chat/getHistory.ts
+0
-73
projects/app/src/pages/app/detail/components/Logs.tsx
+2
-2
projects/app/src/pages/app/detail/index.tsx
+1
-1
projects/app/src/pages/chat/components/ChatHistorySlider.tsx
+2
-2
projects/app/src/pages/chat/index.tsx
+36
-60
projects/app/src/pages/chat/share.tsx
+173
-95
projects/app/src/service/core/dataset/data/pg.ts
+1
-10
projects/app/src/service/moduleDispatch/index.ts
+1
-1
projects/app/src/service/moduleDispatch/plugin/run.ts
+1
-1
projects/app/src/service/support/outLink/auth.ts
+0
-14
projects/app/src/service/support/permission/auth/chat.ts
+59
-0
projects/app/src/service/support/permission/auth/outLink.ts
+57
-14
projects/app/src/service/support/permission/auth/user.ts
+0
-46
projects/app/src/service/support/user/controller.ts
+0
-41
projects/app/src/service/support/wallet/bill/push.ts
+2
-2
projects/app/src/service/utils/chat/saveChat.ts
+6
-3
projects/app/src/utils/service/core/chat/index.ts
+8
-3
projects/app/src/web/common/api/fetch.ts
+1
-1
projects/app/src/web/core/app/templates.ts
+2
-2
projects/app/src/web/core/chat/api.ts
+26
-15
projects/app/src/web/core/chat/storeChat.ts
+77
-50
projects/app/src/web/core/chat/storeShareChat.ts
+18
-121
projects/app/src/web/core/dataset/store/dataset.ts
+1
-2
projects/app/src/web/support/outLink/api.ts
+0
-7
projects/app/src/web/support/wallet/pay/api.ts
+5
-13
No files found.
docSite/content/docs/development/openapi/share.md
View file @
e01c38ef
---
title
:
'
分享链接鉴权'
description
:
'
FastGPT
分享链接鉴权'
title
:
'
分享链接
身份
鉴权'
description
:
'
FastGPT
分享链接
身份
鉴权'
icon
:
'
share'
draft
:
false
toc
:
true
weight
:
860
---
## 介绍
在 FastGPT V4.6.4 中,我们修改了分享链接的数据读取方式,为每个用户生成一个 localId,用于标识用户,从云端拉取对话记录。但是这种方式仅能保障用户在同一设备同一浏览器中使用,如果切换设备或者清空浏览器缓存则会丢失这些记录。这种方式存在一定的风险,因此我们仅允许用户拉取近
`30天`
的
`20条`
记录。
分享链接身份鉴权设计的目的在于,将 FastGPT 的对话框快速、安全的接入到你现有的系统中,仅需 2 个接口即可实现。
## 使用说明
分享链接鉴权设计的目的在于,将 FastGPT 的对话框安全的接入你现有的系统中。
免登录链接配置中,你可以选择填写
`身份验证`
栏。这是一个
`POST`
请求的根地址。在填写该地址后,分享链接的初始化、开始对话以及对话结束都会向该地址的特定接口发送一条请求。下面以
`host`
来表示
`凭身份验证根地址`
。服务器接口仅需返回是否校验成功即可,不需要返回其他数据,格式如下:
免登录链接配置中,增加了
`凭证校验服务器`
后,使用分享链接时会向服务器发起请求,校验链接是否可用,并在每次对话结束后,向服务器发送对话结果。下面以
`host`
来表示
`凭证校验服务器`
。服务器接口仅需返回是否校验成功即可,不需要返回其他数据,格式如下:
### 接口统一响应格式
```
json
{
"success"
:
true
,
"message"
:
"错误提示"
,
"msg"
:
"同message, 错误提示"
"msg"
:
"同message, 错误提示"
,
"uid"
:
"用户唯一凭证"
}
```
!
[
](/imgs/sharelinkProcess.png)
`FastGPT`
将会判断
`success`
是否为
`true`
决定是允许用户继续操作。
`message`
与
`msg`
是等同的,你可以选择返回其中一个,当
`success`
不为
`true`
时,将会提示这个错误。
`uid`
是用户的唯一凭证,将会用于拉取对话记录以及保存对话记录。可参考下方实践案例。
##
配置校验地址和校验token
##
# 触发流程
### 1. 配置校验地址的`BaseURL`、
!
[
](/imgs/sharelinkProcess.png)
## 配置教程
### 1. 配置身份校验地址
!
[
](/imgs/share-setlink.jpg)
配置校验地址后,在每次分享链接使用时,都会向对应的地址发起校验和上报请求。
{{% alert icon="🤖" %}}
这里仅需配置根地址,无需具体到完整请求路径。
{{% /alert %}}
### 2. 分享链接中增加额外 query
在分享链接的地址中,增加一个额外的参数: authToken。例如:
原始的链接:https://fastgpt.run/chat/share?shareId=648aaf5ae121349a16d62192
完整链接: https://fastgpt.run/chat/share?shareId=648aaf5ae121349a16d62192&authToken=userid12345
原始的链接:
`https://fastgpt.run/chat/share?shareId=648aaf5ae121349a16d62192`
这个
`token`
通常是你系统生成的,在发出校验请求时,FastGPT 会在
`body`
中携带 token={{authToken}} 的参数。
完整链接:
`https://fastgpt.run/chat/share?shareId=648aaf5ae121349a16d62192&authToken=userid12345`
## 聊天初始化校验
这个
`authToken`
通常是你系统生成的用户唯一凭证(Token之类的)。FastGPT 会在鉴权接口的
`body`
中携带 token={{authToken}} 的参数。
**FastGPT 发出的请求**
### 3. 编写聊天初始化校验接口
{{
<
tabs
tabTotal=
"3"
>
}}
{{
<
tab
tabName=
"请求示例"
>
}}
{{
<
markdownify
>
}}
```
bash
curl
--location
--request
POST
'{{host}}/shareAuth/init'
\
--header
'Content-Type: application/json'
\
--data-raw
'{
"token": "
sintdolore
"
"token": "
{{authToken}}
"
}'
```
**响应示例**
{{
<
/
markdownify
>
}}
{{
<
/
tab
>
}}
{{
<
tab
tabName=
"鉴权成功"
>
}}
{{
<
markdownify
>
}}
```
json
{
"success"
:
true
,
"uid"
:
"username123"
,
}
```
系统会拉取该分享链接下,uid 为 username123 的对话记录。
{{
<
/
markdownify
>
}}
{{
<
/
tab
>
}}
{{
<
tab
tabName=
"鉴权失败"
>
}}
{{
<
markdownify
>
}}
```
json
{
"success"
:
false
,
"message"
:
"
分享链接无效
"
,
"message"
:
"
身份错误
"
,
}
```
## 对话前校验
{{
<
/
markdownify
>
}}
{{
<
/
tab
>
}}
{{
<
/
tabs
>
}}
**FastGPT 发出的请求**
### 4. 编写对话前校验接口
{{
<
tabs
tabTotal=
"3"
>
}}
{{
<
tab
tabName=
"请求示例"
>
}}
{{
<
markdownify
>
}}
```
bash
curl
--location
--request
POST
'{{host}}/shareAuth/start'
\
--header
'Content-Type: application/json'
\
--data-raw
'{
"token": "
sintdolore
",
"token": "
{{authToken}}
",
"question": "用户问题",
}'
```
**响应示例**
{{
<
/
markdownify
>
}}
{{
<
/
tab
>
}}
{{
<
tab
tabName=
"鉴权成功"
>
}}
{{
<
markdownify
>
}}
```
json
{
"success"
:
true
,
"uid"
:
"username123"
,
}
```
{{
<
/
markdownify
>
}}
{{
<
/
tab
>
}}
{{
<
tab
tabName=
"鉴权失败"
>
}}
{{
<
markdownify
>
}}
```
json
{
"success"
:
true
"success"
:
false
,
"message"
:
"身份验证失败"
,
}
```
```
json
{
"success"
:
false
,
"message"
:
"存在违规词"
,
}
```
## 对话结果上报
{{
<
/
markdownify
>
}}
{{
<
/
tab
>
}}
{{
<
/
tabs
>
}}
### 5. 编写对话结果上报接口(可选)
该接口无规定返回值。
响应值与
[
chat 接口格式相同
](
/docs/development/openapi/chat/#响应
)
,仅多了一个
`token`
。
可以重点关注
`responseData`
里的
`price`
值,
`price`
与实际价格的倍率为
`100000`
,即 100000=1元。
```
bash
curl
--location
--request
POST
'{{host}}/shareAuth/finish'
\
--header
'Content-Type: application/json'
\
--data-raw
'{
"token": "
sint dolore
",
"token": "
{{authToken}}
",
"responseData": [
{
"moduleName": "KB Search",
...
...
@@ -156,18 +237,18 @@ curl --location --request POST '{{host}}/shareAuth/finish' \
}'
```
响应值与 chat 接口相同,增加了一个 token。可以重点关注
`responseData`
里的值,price 与实际价格的倍率为
`100000`
。
**此接口无需响应值**
##
使用示
例
##
实践案
例
我们以
[
Laf作为服务器为例
](
https://laf.dev/
)
,展示这 3 个接口的使用方式。
我们以
[
Laf作为服务器为例
](
https://laf.dev/
)
,
简单
展示这 3 个接口的使用方式。
### 1. 创建3个Laf接口
!
[
](/imgs/share-auth1.jpg)
{{
<
tabs
tabTotal=
"3"
>
}}
{{
<
tab
tabName=
"/shareAuth/init"
>
}}
{{
<
markdownify
>
}}
...
...
@@ -179,13 +260,15 @@ import cloud from '@lafjs/cloud'
export
default
async
function
(
ctx
:
FunctionContext
)
{
const
{
token
}
=
ctx
.
body
// 此处省略 token 解码过程
if
(
token
===
'fastgpt'
)
{
return
{
success
:
true
}
return
{
success
:
true
,
data
:
{
uid
:
"user1"
}
}
}
return
{
success
:
false
,
message
:
"身份错误"
}
return
{
success
:
false
,
message
:
"身份错误"
}
}
```
{{
<
/
markdownify
>
}}
...
...
@@ -201,8 +284,8 @@ import cloud from '@lafjs/cloud'
export
default
async
function
(
ctx
:
FunctionContext
)
{
const
{
token
,
question
}
=
ctx
.
body
console
.
log
(
token
,
question
,
'start'
)
// 此处省略 token 解码过程
if
(
token
!==
'fastgpt'
)
{
return
{
success
:
false
,
message
:
"身份错误"
}
...
...
@@ -212,8 +295,9 @@ export default async function (ctx: FunctionContext) {
return
{
success
:
false
,
message
:
"内容不合规"
}
}
return
{
success
:
true
}
return
{
success
:
true
,
data
:
{
uid
:
"user1"
}
}
}
```
{{
<
/
markdownify
>
}}
...
...
@@ -229,7 +313,12 @@ import cloud from '@lafjs/cloud'
export
default
async
function
(
ctx
:
FunctionContext
)
{
const
{
token
,
responseData
}
=
ctx
.
body
console
.
log
(
token
,
responseData
,
'====='
)
const
total
=
responseData
.
reduce
((
sum
,
item
)
=>
sum
+
item
.
price
,
0
)
const
amount
=
total
/
100000
// 省略数据库操作
return
{
}
}
```
...
...
@@ -241,17 +330,24 @@ export default async function (ctx: FunctionContext) {
### 2. 配置校验地址
我们随便复制3个地址中一个接口
:https://d8dns0.laf.dev/shareAuth/finish , 去除 /shareAuth/finish 后填入 FastGPT 中: https://d8dns0.laf.dev
我们随便复制3个地址中一个接口
:
`https://d8dns0.laf.dev/shareAuth/finish`
, 去除
`/shareAuth/finish`
后填入
`身份校验`
:
`https://d8dns0.laf.dev`
!
[
](/imgs/share-auth2.jpg)
### 3. 修改分享链接参数
源分享链接:
[
https://fastgpt.run/chat/share?shareId=64be36376a438af0311e599c
](
https://fastgpt.run/chat/share?shareId=64be36376a438af0311e599c
)
源分享链接:
`https://fastgpt.run/chat/share?shareId=64be36376a438af0311e599c`
修改后:
[
https://fastgpt.run/chat/share?shareId=64be36376a438af0311e599c&authToken=fastgpt
](
https://fastgpt.run/chat/share?shareId=64be36376a438af0311e599c&authToken=fastgpt
)
修改后:
`https://fastgpt.run/chat/share?shareId=64be36376a438af0311e599c&authToken=fastgpt`
### 4. 测试效果
1.
打开源链接或者
`authToken`
不等于
`fastgpt`
的链接会提示身份错误。
2.
发送内容中包含你字,会提示内容不合规。
\ No newline at end of file
1.
打开源链接或者
`authToken`
不等于
`fastgpt`
的链接会提示身份错误。
2.
发送内容中包含你字,会提示内容不合规。
## 使用场景
这个鉴权方式通常是帮助你直接嵌入
`分享链接`
到你的应用中,在你的应用打开分享链接前,应做
`authToken`
的拼接后再打开。
除了对接已有系统的用户外,你还可以对接
`余额`
功能,通过
`结果上报`
接口扣除用户余额,通过
`对话前校验`
接口检查用户的余额。
\ No newline at end of file
packages/global/common/error/code/outLink.ts
View file @
e01c38ef
...
...
@@ -4,7 +4,9 @@ import { ErrType } from '../errorCode';
export
enum
OutLinkErrEnum
{
unExist
=
'unExist'
,
unAuthLink
=
'unAuthLink'
,
linkUnInvalid
=
'linkUnInvalid'
linkUnInvalid
=
'linkUnInvalid'
,
unAuthUser
=
'unAuthUser'
}
const
errList
=
[
{
...
...
@@ -19,6 +21,10 @@ const errList = [
code
:
501
,
statusText
:
OutLinkErrEnum
.
linkUnInvalid
,
message
:
'分享链接无效'
},
{
statusText
:
OutLinkErrEnum
.
unAuthUser
,
message
:
'身份校验失败'
}
];
export
default
errList
.
reduce
((
acc
,
cur
,
index
)
=>
{
...
...
packages/global/core/chat/api.d.ts
deleted
100644 → 0
View file @
71afe711
import
{
ModuleItemType
}
from
'../module/type'
;
import
{
AdminFbkType
,
ChatItemType
,
moduleDispatchResType
}
from
'./type'
;
export
type
UpdateHistoryProps
=
{
chatId
:
string
;
customTitle
?:
string
;
top
?:
boolean
;
};
export
type
AdminUpdateFeedbackParams
=
AdminFbkType
&
{
chatItemId
:
string
;
};
export
type
InitChatResponse
=
{
chatId
:
string
;
appId
:
string
;
app
:
{
userGuideModule
?:
ModuleItemType
;
chatModels
?:
string
[];
name
:
string
;
avatar
:
string
;
intro
:
string
;
canUse
?:
boolean
;
};
title
:
string
;
variables
:
Record
<
string
,
any
>
;
history
:
ChatItemType
[];
};
export
type
ChatHistoryItemResType
=
moduleDispatchResType
&
{
moduleType
:
`
${
FlowNodeTypeEnum
}
`
;
moduleName
:
string
;
};
packages/global/core/chat/constants.ts
View file @
e01c38ef
...
...
@@ -44,6 +44,12 @@ export const ChatSourceMap = {
}
};
export
enum
ChatStatusEnum
{
loading
=
'loading'
,
running
=
'running'
,
finish
=
'finish'
}
export
const
HUMAN_ICON
=
`/icon/human.svg`
;
export
const
LOGO_ICON
=
`/icon/logo.svg`
;
...
...
packages/global/core/chat/type.d.ts
View file @
e01c38ef
import
{
ClassifyQuestionAgentItemType
}
from
'../module/type'
;
import
{
SearchDataResponseItemType
}
from
'../dataset/type'
;
import
{
ChatRoleEnum
,
ChatSourceEnum
}
from
'./constants'
;
import
{
ChatRoleEnum
,
ChatSourceEnum
,
ChatStatusEnum
}
from
'./constants'
;
import
{
FlowNodeTypeEnum
}
from
'../module/node/constant'
;
import
{
ModuleOutputKeyEnum
}
from
'../module/constants'
;
import
{
AppSchema
}
from
'../app/type'
;
...
...
@@ -20,7 +20,7 @@ export type ChatSchema = {
variables
:
Record
<
string
,
any
>
;
source
:
`
${
ChatSourceEnum
}
`
;
shareId
?:
string
;
isInit
:
boolean
;
outLinkUid
?:
string
;
content
:
ChatItemType
[];
};
...
...
@@ -51,6 +51,7 @@ export type AdminFbkType = {
a
?:
string
;
};
/* --------- chat item ---------- */
export
type
ChatItemType
=
{
dataId
?:
string
;
obj
:
ChatItemSchema
[
'obj'
];
...
...
@@ -61,11 +62,12 @@ export type ChatItemType = {
};
export
type
ChatSiteItemType
=
ChatItemType
&
{
status
:
'loading'
|
'running'
|
'finish'
;
status
:
`
${
ChatStatusEnum
}
`
;
moduleName
?:
string
;
ttsBuffer
?:
Uint8Array
;
};
/* ---------- history ------------- */
export
type
HistoryItemType
=
{
chatId
:
string
;
updateTime
:
Date
;
...
...
@@ -77,10 +79,10 @@ export type ChatHistoryItemType = HistoryItemType & {
top
:
boolean
;
};
/
/ response data
/
* ------- response data ------------ */
export
type
moduleDispatchResType
=
{
moduleLogo
?:
string
;
price
:
number
;
price
?
:
number
;
runningTime
?:
number
;
tokens
?:
number
;
model
?:
string
;
...
...
@@ -112,3 +114,8 @@ export type moduleDispatchResType = {
// plugin output
pluginOutput
?:
Record
<
string
,
any
>
;
};
export
type
ChatHistoryItemResType
=
moduleDispatchResType
&
{
moduleType
:
`
${
FlowNodeTypeEnum
}
`
;
moduleName
:
string
;
};
packages/global/core/dataset/api.d.ts
View file @
e01c38ef
...
...
@@ -6,9 +6,9 @@ import type { LLMModelItemType } from '../ai/model.d';
export
type
DatasetUpdateBody
=
{
id
:
string
;
parentId
?:
string
;
tags
?:
string
[];
name
?:
string
;
avatar
?:
string
;
intro
?:
string
;
permission
?:
DatasetSchemaType
[
'permission'
];
agentModel
?:
LLMModelItemType
;
websiteConfig
?:
DatasetSchemaType
[
'websiteConfig'
];
...
...
packages/global/support/outLink/api.d.ts
View file @
e01c38ef
import
type
{
HistoryItemType
,
ChatSiteItemType
}
from
'../../core/chat/type.d'
;
import
type
{
InitChatResponse
}
from
'../../core/chat/api.d'
;
import
{
OutLinkSchema
}
from
'@fastgpt/global/support/outLink/type'
;
export
type
InitShareChatResponse
=
{
userAvatar
:
string
;
app
:
InitChatResponse
[
'app'
];
};
/* one page type */
export
type
ShareChatType
=
InitShareChatResponse
&
{
history
:
ShareChatHistoryItemType
;
};
/* history list item type */
export
type
ShareChatHistoryItemType
=
HistoryItemType
&
{
shareId
:
string
;
variables
?:
Record
<
string
,
any
>
;
chats
:
ChatSiteItemType
[];
};
export
type
AuthLinkChatProps
=
{
ip
?:
string
|
null
;
authToken
?:
string
;
question
:
string
};
export
type
AuthLinkLimitProps
=
AuthLinkChatProps
&
{
outLink
:
OutLinkSchema
};
export
type
AuthShareChatInitProps
=
{
authToken
?:
string
;
export
type
AuthOutLinkInitProps
=
{
outLinkUid
:
string
;
tokenUrl
?:
string
;
};
export
type
AuthOutLinkChatProps
=
{
ip
?:
string
|
null
;
outLinkUid
:
string
;
question
:
string
};
export
type
AuthOutLinkLimitProps
=
AuthOutLinkChatProps
&
{
outLink
:
OutLinkSchema
};
export
type
AuthOutLinkResponse
=
{
uid
:
string
;
};
packages/global/support/outLink/type.d.ts
View file @
e01c38ef
...
...
@@ -3,7 +3,6 @@ import { OutLinkTypeEnum } from './constant';
export
type
OutLinkSchema
=
{
_id
:
string
;
shareId
:
string
;
userId
:
string
;
teamId
:
string
;
tmbId
:
string
;
appId
:
string
;
...
...
packages/global/support/user/team/constant.ts
View file @
e01c38ef
...
...
@@ -45,4 +45,4 @@ export const TeamMemberStatusMap = {
color
:
'red.600'
}
};
export
const
l
eaveStatus
=
{
$ne
:
TeamMemberStatusEnum
.
leave
};
export
const
notL
eaveStatus
=
{
$ne
:
TeamMemberStatusEnum
.
leave
};
packages/global/support/user/team/type.d.ts
View file @
e01c38ef
import
{
UserModelSchema
}
from
'../type'
;
import
{
TeamMemberRoleEnum
,
TeamMemberStatusEnum
}
from
'./constant'
;
import
type
{
UserModelSchema
}
from
'../type'
;
import
type
{
TeamMemberRoleEnum
,
TeamMemberStatusEnum
}
from
'./constant'
;
export
type
TeamSchema
=
{
_id
:
string
;
...
...
@@ -22,6 +22,16 @@ export type TeamMemberSchema = {
defaultTeam
:
boolean
;
};
export
type
TeamMemberWithUserSchema
=
TeamMemberSchema
&
{
userId
:
UserModelSchema
;
};
export
type
TeamMemberWithTeamSchema
=
TeamMemberSchema
&
{
teamId
:
TeamSchema
;
};
export
type
TeamMemberWithTeamAndUserSchema
=
TeamMemberWithTeamSchema
&
{
userId
:
UserModelSchema
;
};
export
type
TeamItemType
=
{
userId
:
string
;
teamId
:
string
;
...
...
packages/service/common/mongo/init.ts
View file @
e01c38ef
...
...
@@ -26,9 +26,13 @@ export async function connectMongo({
bufferCommands
:
true
,
maxConnecting
:
Number
(
process
.
env
.
DB_MAX_LINK
||
5
),
maxPoolSize
:
Number
(
process
.
env
.
DB_MAX_LINK
||
5
),
minPoolSize
:
Number
(
process
.
env
.
DB_MAX_LINK
||
10
)
*
0.5
,
minPoolSize
:
Math
.
min
(
10
,
Number
(
process
.
env
.
DB_MAX_LINK
||
10
))
,
connectTimeoutMS
:
60000
,
waitQueueTimeoutMS
:
60000
waitQueueTimeoutMS
:
60000
,
socketTimeoutMS
:
60000
,
maxIdleTimeMS
:
300000
,
retryWrites
:
true
,
retryReads
:
true
});
console
.
log
(
'mongo connected'
);
...
...
packages/service/core/chat/chatSchema.ts
View file @
e01c38ef
...
...
@@ -50,10 +50,6 @@ const ChatSchema = new Schema({
top
:
{
type
:
Boolean
},
variables
:
{
type
:
Object
,
default
:
{}
},
source
:
{
type
:
String
,
enum
:
Object
.
keys
(
ChatSourceMap
),
...
...
@@ -62,9 +58,17 @@ const ChatSchema = new Schema({
shareId
:
{
type
:
String
},
isInit
:
{
type
:
Boolean
,
default
:
false
outLinkUid
:
{
type
:
String
},
variables
:
{
type
:
Object
,
default
:
{}
},
metadata
:
{
//For special storage
type
:
Object
,
default
:
{}
},
content
:
{
type
:
[
...
...
@@ -89,9 +93,10 @@ const ChatSchema = new Schema({
});
try
{
ChatSchema
.
index
({
appId
:
1
});
ChatSchema
.
index
({
tmbId
:
1
});
ChatSchema
.
index
({
shareId
:
1
});
ChatSchema
.
index
({
updateTime
:
-
1
});
ChatSchema
.
index
({
appId
:
1
});
}
catch
(
error
)
{
console
.
log
(
error
);
}
...
...
packages/service/core/chat/controller.ts
0 → 100644
View file @
e01c38ef
import
type
{
ChatItemType
}
from
'@fastgpt/global/core/chat/type'
;
import
{
MongoChatItem
}
from
'./chatItemSchema'
;
export
async
function
getChatItems
({
chatId
,
limit
=
30
,
field
}:
{
chatId
?:
string
;
limit
?:
number
;
field
:
string
;
}):
Promise
<
{
history
:
ChatItemType
[]
}
>
{
if
(
!
chatId
)
{
return
{
history
:
[]
};
}
const
history
=
await
MongoChatItem
.
find
({
chatId
},
field
).
sort
({
_id
:
-
1
}).
limit
(
limit
);
history
.
reverse
();
return
{
history
};
}
packages/service/support/outLink/schema.ts
View file @
e01c38ef
...
...
@@ -12,10 +12,6 @@ const OutLinkSchema = new Schema({
type
:
String
,
required
:
true
},
userId
:
{
type
:
Schema
.
Types
.
ObjectId
,
ref
:
'user'
},
teamId
:
{
type
:
Schema
.
Types
.
ObjectId
,
ref
:
TeamCollectionName
,
...
...
packages/service/support/outLink/tools.ts
View file @
e01c38ef
...
...
@@ -22,15 +22,15 @@ export const updateOutLinkUsage = async ({
};
export
const
pushResult2Remote
=
async
({
authToken
,
outLinkUid
,
shareId
,
responseData
}:
{
authToken
?:
string
;
outLinkUid
?:
string
;
// raw id, not parse
shareId
?:
string
;
responseData
?:
any
[];
})
=>
{
if
(
!
shareId
||
!
authToken
||
!
global
.
systemEnv
.
pluginBaseUrl
)
return
;
if
(
!
shareId
||
!
outLinkUid
||
!
global
.
systemEnv
.
pluginBaseUrl
)
return
;
try
{
const
outLink
=
await
MongoOutLink
.
findOne
({
shareId
...
...
@@ -42,7 +42,7 @@ export const pushResult2Remote = async ({
baseURL
:
outLink
.
limit
.
hookUrl
,
url
:
'/shareAuth/finish'
,
data
:
{
token
:
authToken
,
token
:
outLinkUid
,
responseData
}
});
...
...
packages/service/support/permission/auth/app.ts
View file @
e01c38ef
...
...
@@ -19,6 +19,7 @@ export async function authApp({
AuthResponseType
&
{
teamOwner
:
boolean
;
app
:
AppDetailType
;
role
:
`
${
TeamMemberRoleEnum
}
`
;
}
>
{
const
result
=
await
parseHeaderCert
(
props
);
...
...
@@ -65,6 +66,7 @@ export async function authApp({
return
{
...
result
,
app
,
role
,
isOwner
,
canWrite
,
teamOwner
:
role
===
TeamMemberRoleEnum
.
owner
...
...
packages/service/support/permission/auth/chat.ts
deleted
100644 → 0
View file @
71afe711
import
{
AuthResponseType
}
from
'@fastgpt/global/support/permission/type'
;
import
{
AuthModeType
}
from
'../type'
;
import
type
{
ChatWithAppSchema
}
from
'@fastgpt/global/core/chat/type'
;
import
{
parseHeaderCert
}
from
'../controller'
;
import
{
MongoChat
}
from
'../../../core/chat/chatSchema'
;
import
{
ChatErrEnum
}
from
'@fastgpt/global/common/error/code/chat'
;
import
{
getTeamInfoByTmbId
}
from
'../../user/team/controller'
;
import
{
TeamMemberRoleEnum
}
from
'@fastgpt/global/support/user/team/constant'
;
import
{
PermissionTypeEnum
}
from
'@fastgpt/global/support/permission/constant'
;
export
async
function
authChat
({
chatId
,
per
=
'owner'
,
...
props
}:
AuthModeType
&
{
chatId
:
string
;
}):
Promise
<
AuthResponseType
&
{
chat
:
ChatWithAppSchema
;
}
>
{
const
{
userId
,
teamId
,
tmbId
}
=
await
parseHeaderCert
(
props
);
const
{
role
}
=
await
getTeamInfoByTmbId
({
tmbId
});
const
{
chat
,
isOwner
,
canWrite
}
=
await
(
async
()
=>
{
// get chat
const
chat
=
(
await
MongoChat
.
findOne
({
chatId
,
teamId
})
.
populate
(
'appId'
)
.
lean
())
as
ChatWithAppSchema
;
if
(
!
chat
)
{
return
Promise
.
reject
(
'Chat is not exists'
);
}
const
isOwner
=
role
===
TeamMemberRoleEnum
.
owner
||
String
(
chat
.
tmbId
)
===
tmbId
;
const
canWrite
=
isOwner
;
if
(
per
===
'r'
&&
role
!==
TeamMemberRoleEnum
.
owner
&&
chat
.
appId
.
permission
!==
PermissionTypeEnum
.
public
)
{
return
Promise
.
reject
(
ChatErrEnum
.
unAuthChat
);
}
if
(
per
===
'w'
&&
!
canWrite
)
{
return
Promise
.
reject
(
ChatErrEnum
.
unAuthChat
);
}
if
(
per
===
'owner'
&&
!
isOwner
)
{
return
Promise
.
reject
(
ChatErrEnum
.
unAuthChat
);
}
return
{
chat
,
isOwner
,
canWrite
};
})();
return
{
userId
,
teamId
,
tmbId
,
chat
,
isOwner
,
canWrite
};
}
packages/service/support/permission/auth/common.ts
View file @
e01c38ef
...
...
@@ -20,11 +20,11 @@ export async function authCertAndShareId({
return
authCert
(
props
);
}
const
{
app
}
=
await
authOutLinkValid
({
shareId
});
const
{
shareChat
}
=
await
authOutLinkValid
({
shareId
});
return
{
teamId
:
String
(
app
.
teamId
),
tmbId
:
String
(
app
.
tmbId
),
teamId
:
String
(
shareChat
.
teamId
),
tmbId
:
String
(
shareChat
.
tmbId
),
authType
:
AuthUserTypeEnum
.
outLink
,
apikey
:
''
,
isOwner
:
false
,
...
...
packages/service/support/permission/auth/outLink.ts
View file @
e01c38ef
...
...
@@ -78,21 +78,19 @@ export async function authOutLinkCrud({
};
}
/* outLink exist and it app exist */
export
async
function
authOutLinkValid
({
shareId
}:
{
shareId
?:
string
})
{
if
(
!
shareId
)
{
return
Promise
.
reject
(
OutLinkErrEnum
.
linkUnInvalid
);
}
const
shareChat
=
await
MongoOutLink
.
findOne
({
shareId
});
if
(
!
shareChat
)
{
return
Promise
.
reject
(
OutLinkErrEnum
.
linkUnInvalid
);
}
const
app
=
await
MongoApp
.
findById
(
shareChat
.
appId
);
if
(
!
app
)
{
return
Promise
.
reject
(
AppErrEnum
.
unExist
);
}
return
{
app
,
app
Id
:
shareChat
.
appId
,
shareChat
};
}
packages/service/support/user/controller.ts
View file @
e01c38ef
import
{
UserType
}
from
'@fastgpt/global/support/user/type'
;
import
{
MongoUser
}
from
'./schema'
;
import
{
getTeamInfoByTmbId
,
getUserDefaultTeam
}
from
'./team/controller'
;
import
{
ERROR_ENUM
}
from
'@fastgpt/global/common/error/errorCode'
;
import
{
UserErrEnum
}
from
'@fastgpt/global/common/error/code/user'
;
export
async
function
authUserExist
({
userId
,
username
}:
{
userId
?:
string
;
username
?:
string
})
{
if
(
userId
)
{
...
...
@@ -9,3 +13,56 @@ export async function authUserExist({ userId, username }: { userId?: string; use
}
return
null
;
}
export
async
function
getUserDetail
({
tmbId
,
userId
}:
{
tmbId
?:
string
;
userId
?:
string
;
}):
Promise
<
UserType
>
{
const
team
=
await
(
async
()
=>
{
if
(
tmbId
)
{
return
getTeamInfoByTmbId
({
tmbId
});
}
if
(
userId
)
{
return
getUserDefaultTeam
({
userId
});
}
return
Promise
.
reject
(
ERROR_ENUM
.
unAuthorization
);
})();
const
user
=
await
MongoUser
.
findById
(
team
.
userId
);
if
(
!
user
)
{
return
Promise
.
reject
(
ERROR_ENUM
.
unAuthorization
);
}
return
{
_id
:
user
.
_id
,
username
:
user
.
username
,
avatar
:
user
.
avatar
,
balance
:
user
.
balance
,
timezone
:
user
.
timezone
,
promotionRate
:
user
.
promotionRate
,
openaiAccount
:
user
.
openaiAccount
,
team
};
}
export
async
function
getUserAndAuthBalance
({
tmbId
,
minBalance
}:
{
tmbId
:
string
;
minBalance
?:
number
;
})
{
const
user
=
await
getUserDetail
({
tmbId
});
if
(
!
user
)
{
return
Promise
.
reject
(
UserErrEnum
.
unAuthUser
);
}
if
(
minBalance
!==
undefined
&&
user
.
team
.
balance
<
minBalance
)
{
return
Promise
.
reject
(
UserErrEnum
.
balanceNotEnough
);
}
return
user
;
}
packages/service/support/user/team/controller.ts
View file @
e01c38ef
import
{
TeamItemType
}
from
'@fastgpt/global/support/user/team/type'
;
import
{
connectionMongo
,
Types
}
from
'../../../common/mongo'
;
import
{
TeamItemType
,
TeamMemberWithTeamSchema
}
from
'@fastgpt/global/support/user/team/type'
;
import
{
Types
}
from
'../../../common/mongo'
;
import
{
TeamMemberRoleEnum
,
TeamMemberStatusEnum
,
TeamCollectionName
,
TeamMemberCollectionName
,
leaveStatus
notLeaveStatus
}
from
'@fastgpt/global/support/user/team/constant'
;
import
{
MongoTeamMember
}
from
'./teamMemberSchema'
;
import
{
MongoTeam
}
from
'./teamSchema'
;
async
function
getTeam
(
match
:
Record
<
string
,
any
>
):
Promise
<
TeamItemType
>
{
const
db
=
connectionMongo
?.
connection
?.
db
;
const
TeamMember
=
db
.
collection
(
TeamMemberCollectionName
);
const
results
=
await
TeamMember
.
aggregate
([
{
$match
:
match
},
{
$lookup
:
{
from
:
TeamCollectionName
,
localField
:
'teamId'
,
foreignField
:
'_id'
,
as
:
'team'
}
},
{
$unwind
:
'$team'
}
]).
toArray
();
const
tmb
=
results
[
0
];
const
tmb
=
(
await
MongoTeamMember
.
findOne
(
match
).
populate
(
'teamId'
))
as
TeamMemberWithTeamSchema
;
if
(
!
tmb
)
{
return
Promise
.
reject
(
'member not exist'
);
...
...
@@ -37,17 +17,17 @@ async function getTeam(match: Record<string, any>): Promise<TeamItemType> {
return
{
userId
:
String
(
tmb
.
userId
),
teamId
:
String
(
tmb
.
teamId
),
teamName
:
tmb
.
team
.
name
,
teamId
:
String
(
tmb
.
teamId
.
_id
),
teamName
:
tmb
.
team
Id
.
name
,
memberName
:
tmb
.
name
,
avatar
:
tmb
.
team
.
avatar
,
balance
:
tmb
.
team
.
balance
,
avatar
:
tmb
.
team
Id
.
avatar
,
balance
:
tmb
.
team
Id
.
balance
,
tmbId
:
String
(
tmb
.
_id
),
role
:
tmb
.
role
,
status
:
tmb
.
status
,
defaultTeam
:
tmb
.
defaultTeam
,
canWrite
:
tmb
.
role
!==
TeamMemberRoleEnum
.
visitor
,
maxSize
:
tmb
.
team
.
maxSize
maxSize
:
tmb
.
team
Id
.
maxSize
};
}
...
...
@@ -57,7 +37,7 @@ export async function getTeamInfoByTmbId({ tmbId }: { tmbId: string }) {
}
return
getTeam
({
_id
:
new
Types
.
ObjectId
(
tmbId
),
status
:
l
eaveStatus
status
:
notL
eaveStatus
});
}
...
...
@@ -83,12 +63,8 @@ export async function createDefaultTeam({
balance
?:
number
;
maxSize
?:
number
;
})
{
const
db
=
connectionMongo
.
connection
.
db
;
const
Team
=
db
.
collection
(
TeamCollectionName
);
const
TeamMember
=
db
.
collection
(
TeamMemberCollectionName
);
// auth default team
const
tmb
=
await
TeamMember
.
findOne
({
const
tmb
=
await
Mongo
TeamMember
.
findOne
({
userId
:
new
Types
.
ObjectId
(
userId
),
defaultTeam
:
true
});
...
...
@@ -97,7 +73,7 @@ export async function createDefaultTeam({
console
.
log
(
'create default team'
,
userId
);
// create
const
{
insertedId
}
=
await
Team
.
insertOn
e
({
const
{
_id
:
insertedId
}
=
await
MongoTeam
.
creat
e
({
ownerId
:
userId
,
name
:
teamName
,
avatar
,
...
...
@@ -105,7 +81,7 @@ export async function createDefaultTeam({
maxSize
,
createTime
:
new
Date
()
});
await
TeamMember
.
insertOn
e
({
await
MongoTeamMember
.
creat
e
({
teamId
:
insertedId
,
userId
,
name
:
'Owner'
,
...
...
@@ -116,16 +92,11 @@ export async function createDefaultTeam({
});
}
else
{
console
.
log
(
'default team exist'
,
userId
);
await
Team
.
updateOne
(
{
_id
:
new
Types
.
ObjectId
(
tmb
.
teamId
)
},
{
$set
:
{
...(
balance
!==
undefined
&&
{
balance
}),
maxSize
}
await
MongoTeam
.
findByIdAndUpdate
(
tmb
.
teamId
,
{
$set
:
{
...(
balance
!==
undefined
&&
{
balance
}),
maxSize
}
);
}
);
}
}
packages/service/support/user/team/teamMemberSchema.ts
0 → 100644
View file @
e01c38ef
import
{
connectionMongo
,
type
Model
}
from
'../../../common/mongo'
;
const
{
Schema
,
model
,
models
}
=
connectionMongo
;
import
{
TeamMemberSchema
as
TeamMemberType
}
from
'@fastgpt/global/support/user/team/type.d'
;
import
{
userCollectionName
}
from
'../../user/schema'
;
import
{
TeamMemberRoleMap
,
TeamMemberStatusMap
,
TeamMemberCollectionName
,
TeamCollectionName
}
from
'@fastgpt/global/support/user/team/constant'
;
const
TeamMemberSchema
=
new
Schema
({
teamId
:
{
type
:
Schema
.
Types
.
ObjectId
,
ref
:
TeamCollectionName
,
required
:
true
},
userId
:
{
type
:
Schema
.
Types
.
ObjectId
,
ref
:
userCollectionName
,
required
:
true
},
name
:
{
type
:
String
,
default
:
'Member'
},
role
:
{
type
:
String
,
enum
:
Object
.
keys
(
TeamMemberRoleMap
)
},
status
:
{
type
:
String
,
enum
:
Object
.
keys
(
TeamMemberStatusMap
)
},
createTime
:
{
type
:
Date
,
default
:
()
=>
new
Date
()
},
defaultTeam
:
{
type
:
Boolean
,
default
:
false
}
});
try
{
}
catch
(
error
)
{
console
.
log
(
error
);
}
export
const
MongoTeamMember
:
Model
<
TeamMemberType
>
=
models
[
TeamMemberCollectionName
]
||
model
(
TeamMemberCollectionName
,
TeamMemberSchema
);
packages/service/support/user/team/teamSchema.ts
0 → 100644
View file @
e01c38ef
import
{
connectionMongo
,
type
Model
}
from
'../../../common/mongo'
;
const
{
Schema
,
model
,
models
}
=
connectionMongo
;
import
{
TeamSchema
as
TeamType
}
from
'@fastgpt/global/support/user/team/type.d'
;
import
{
userCollectionName
}
from
'../../user/schema'
;
import
{
TeamCollectionName
}
from
'@fastgpt/global/support/user/team/constant'
;
import
{
PRICE_SCALE
}
from
'@fastgpt/global/support/wallet/bill/constants'
;
const
TeamSchema
=
new
Schema
({
name
:
{
type
:
String
,
required
:
true
},
ownerId
:
{
type
:
Schema
.
Types
.
ObjectId
,
ref
:
userCollectionName
},
avatar
:
{
type
:
String
,
default
:
'/icon/logo.svg'
},
createTime
:
{
type
:
Date
,
default
:
()
=>
Date
.
now
()
},
balance
:
{
type
:
Number
,
default
:
2
*
PRICE_SCALE
},
maxSize
:
{
type
:
Number
,
default
:
5
}
});
try
{
}
catch
(
error
)
{
console
.
log
(
error
);
}
export
const
MongoTeam
:
Model
<
TeamType
>
=
models
[
TeamCollectionName
]
||
model
(
TeamCollectionName
,
TeamSchema
);
projects/app/public/locales/en/common.json
View file @
e01c38ef
...
...
@@ -327,12 +327,12 @@
"QA Prompt"
:
"QA Prompt"
,
"Start Sync Tip"
:
"Are you sure to start synchronizing data? The old data will be deleted and then re-acquired, please confirm!"
,
"Sync"
:
"Data Sync"
,
"Sync Collection"
:
"Data Sync"
,
"Website Create Success"
:
"Created successfully, data is being synchronized"
,
"Website Empty Tip"
:
"No associated website yet"
,
"Website Link"
:
"Website Link"
,
"Website Sync"
:
"Website"
,
"id"
:
"Id"
,
"Sync Collection"
:
"Data Sync"
,
"metadata"
:
{
"Chunk Size"
:
"Chunk Size"
,
"Createtime"
:
"Create Time"
,
...
...
@@ -510,6 +510,10 @@
"variable options"
:
"Options"
},
"variable add option"
:
"Add Option"
},
"shareChat"
:
{
"Init Error"
:
"Init Chat Error"
,
"Init History Error"
:
"Init History Error"
}
},
"dataset"
:
{
...
...
projects/app/public/locales/zh/common.json
View file @
e01c38ef
...
...
@@ -316,7 +316,7 @@
"Search Top K"
:
"单次搜索数量"
,
"Set Empty Result Tip"
:
",未搜索到内容时回复指定内容"
,
"Set Website Config"
:
"开始配置网站信息"
,
"Similarity"
:
"相
似
度"
,
"Similarity"
:
"相
关
度"
,
"Sync Time"
:
"最后更新时间"
,
"Virtual File"
:
"虚拟文件"
,
"Website Dataset"
:
"Web 站点同步"
,
...
...
@@ -327,12 +327,12 @@
"QA Prompt"
:
"QA 拆分引导词"
,
"Start Sync Tip"
:
"确认开始同步数据?将会删除旧数据后重新获取,请确认!"
,
"Sync"
:
"同步数据"
,
"Sync Collection"
:
"数据同步"
,
"Website Create Success"
:
"创建成功,正在同步数据"
,
"Website Empty Tip"
:
"还没有关联网站"
,
"Website Link"
:
"Web 站点地址"
,
"Website Sync"
:
"Web 站点同步"
,
"id"
:
"集合ID"
,
"Sync Collection"
:
"数据同步"
,
"metadata"
:
{
"Chunk Size"
:
"分割大小"
,
"Createtime"
:
"创建时间"
,
...
...
@@ -405,17 +405,17 @@
"search"
:
{
"Empty result response"
:
"空搜索回复"
,
"Empty result response Tips"
:
"若填写该内容,没有搜索到合适内容时,将直接回复填写的内容。"
,
"Min Similarity"
:
"最低相
似
度"
,
"Min Similarity Tips"
:
"不同索引模型的相
似度有区别,请通过搜索测试来选择合适的数值
"
,
"Min Similarity"
:
"最低相
关
度"
,
"Min Similarity Tips"
:
"不同索引模型的相
关度有区别,请通过搜索测试来选择合适的数值,使用 ReRank 时,相关度可能会很低。
"
,
"Params Setting"
:
"搜索参数设置"
,
"Top K"
:
"单次搜索上限"
,
"mode"
:
{
"embFullTextReRank"
:
"混合检索"
,
"embFullTextReRank desc"
:
"使用向量检索与全文检索混合结果进行 Rerank 进行重排,
通常效果最佳
"
,
"embFullTextReRank desc"
:
"使用向量检索与全文检索混合结果进行 Rerank 进行重排,
相关度通常差异明显,推荐。
"
,
"embedding"
:
"语义检索"
,
"embedding desc"
:
"直接进行向量 topk 相关性查询"
,
"embeddingReRank"
:
"增强语义检索"
,
"embeddingReRank desc"
:
"超额进行向量 topk 查询后再使用 Rerank 进行排序"
"embeddingReRank desc"
:
"超额进行向量 topk 查询后再使用 Rerank 进行排序
,相关度通常差异明显。
"
},
"search mode"
:
"检索模式"
},
...
...
@@ -510,6 +510,10 @@
"variable options"
:
"选项"
},
"variable add option"
:
"添加选项"
},
"shareChat"
:
{
"Init Error"
:
"初始化对话框失败"
,
"Init History Error"
:
"初始化聊天记录失败"
}
},
"dataset"
:
{
...
...
projects/app/src/components/ChatBox/ResponseTags.tsx
View file @
e01c38ef
import
React
,
{
useMemo
,
useState
}
from
'react'
;
import
type
{
ChatHistoryItemResType
}
from
'@fastgpt/global/core/chat/
api
.d'
;
import
type
{
ChatHistoryItemResType
}
from
'@fastgpt/global/core/chat/
type
.d'
;
import
type
{
ChatItemType
}
from
'@fastgpt/global/core/chat/type'
;
import
{
Flex
,
BoxProps
,
useDisclosure
,
Image
,
useTheme
,
Box
}
from
'@chakra-ui/react'
;
import
{
useTranslation
}
from
'next-i18next'
;
...
...
projects/app/src/components/ChatBox/WholeResponseModal.tsx
View file @
e01c38ef
import
React
,
{
useMemo
,
useState
}
from
'react'
;
import
{
Box
,
useTheme
,
Flex
,
Image
}
from
'@chakra-ui/react'
;
import
type
{
ChatHistoryItemResType
}
from
'@fastgpt/global/core/chat/
api
.d'
;
import
type
{
ChatHistoryItemResType
}
from
'@fastgpt/global/core/chat/
type
.d'
;
import
{
useTranslation
}
from
'next-i18next'
;
import
{
moduleTemplatesFlat
}
from
'@/web/core/modules/template/system'
;
import
Tabs
from
'../Tabs'
;
...
...
projects/app/src/components/ChatBox/index.tsx
View file @
e01c38ef
...
...
@@ -12,7 +12,7 @@ import Script from 'next/script';
import
{
throttle
}
from
'lodash'
;
import
type
{
ExportChatType
}
from
'@/types/chat.d'
;
import
type
{
ChatItemType
,
ChatSiteItemType
}
from
'@fastgpt/global/core/chat/type.d'
;
import
type
{
ChatHistoryItemResType
}
from
'@fastgpt/global/core/chat/
api
.d'
;
import
type
{
ChatHistoryItemResType
}
from
'@fastgpt/global/core/chat/
type
.d'
;
import
{
useToast
}
from
'@/web/common/hooks/useToast'
;
import
{
useAudioPlay
}
from
'@/web/common/utils/voice'
;
import
{
getErrText
}
from
'@fastgpt/global/common/error/utils'
;
...
...
@@ -80,7 +80,7 @@ export type StartChatFnProps = {
};
export
type
ComponentRef
=
{
getChatHistor
y
:
()
=>
ChatSiteItemType
[];
getChatHistor
ies
:
()
=>
ChatSiteItemType
[];
resetVariables
:
(
data
?:
Record
<
string
,
any
>
)
=>
void
;
resetHistory
:
(
history
:
ChatSiteItemType
[])
=>
void
;
scrollToBottom
:
(
behavior
?:
'smooth'
|
'auto'
)
=>
void
;
...
...
@@ -134,7 +134,7 @@ const ChatBox = (
const
router
=
useRouter
();
const
{
t
}
=
useTranslation
();
const
{
toast
}
=
useToast
();
const
{
isPc
}
=
useSystemStore
();
const
{
isPc
,
setLoading
}
=
useSystemStore
();
const
TextareaDom
=
useRef
<
HTMLTextAreaElement
>
(
null
);
const
chatController
=
useRef
(
new
AbortController
());
const
questionGuideController
=
useRef
(
new
AbortController
());
...
...
@@ -415,15 +415,20 @@ const ChatBox = (
async
(
index
:
number
)
=>
{
if
(
!
onDelMessage
)
return
;
const
delHistory
=
chatHistory
.
slice
(
index
);
setChatHistory
((
state
)
=>
(
index
===
0
?
[]
:
state
.
slice
(
0
,
index
)));
await
Promise
.
all
(
delHistory
.
map
((
item
,
i
)
=>
onDelMessage
({
contentId
:
item
.
dataId
,
index
:
index
+
i
}))
);
setLoading
(
true
);
sendPrompt
(
variables
,
delHistory
[
0
].
value
,
chatHistory
.
slice
(
0
,
index
));
try
{
await
Promise
.
all
(
delHistory
.
map
((
item
,
i
)
=>
onDelMessage
({
contentId
:
item
.
dataId
,
index
:
index
+
i
}))
);
setChatHistory
((
state
)
=>
(
index
===
0
?
[]
:
state
.
slice
(
0
,
index
)));
sendPrompt
(
variables
,
delHistory
[
0
].
value
,
chatHistory
.
slice
(
0
,
index
));
}
catch
(
error
)
{}
setLoading
(
false
);
},
[
chatHistory
,
onDelMessage
,
sendPrompt
,
variables
]
[
chatHistory
,
onDelMessage
,
sendPrompt
,
setLoading
,
variables
]
);
// delete one message
const
delOneMessage
=
useCallback
(
...
...
@@ -439,7 +444,7 @@ const ChatBox = (
// output data
useImperativeHandle
(
ref
,
()
=>
({
getChatHistor
y
:
()
=>
chatHistory
,
getChatHistor
ies
:
()
=>
chatHistory
,
resetVariables
(
e
)
{
const
defaultVal
:
Record
<
string
,
any
>
=
{};
variableModules
?.
forEach
((
item
)
=>
{
...
...
projects/app/src/components/core/module/DatasetParamsModal.tsx
View file @
e01c38ef
...
...
@@ -86,7 +86,7 @@ const DatasetParamsModal = ({
min=
{
0
}
max=
{
1
}
step=
{
0.01
}
value=
{
getValues
(
ModuleInputKeyEnum
.
datasetSimilarity
)
||
0.5
}
value=
{
getValues
(
ModuleInputKeyEnum
.
datasetSimilarity
)
??
0.5
}
onChange=
{
(
val
)
=>
{
setValue
(
ModuleInputKeyEnum
.
datasetSimilarity
,
val
);
setRefresh
(
!
refresh
);
...
...
@@ -107,7 +107,7 @@ const DatasetParamsModal = ({
]
}
min=
{
1
}
max=
{
30
}
value=
{
getValues
(
ModuleInputKeyEnum
.
datasetLimit
)
||
5
}
value=
{
getValues
(
ModuleInputKeyEnum
.
datasetLimit
)
??
5
}
onChange=
{
(
val
)
=>
{
setValue
(
ModuleInputKeyEnum
.
datasetLimit
,
val
);
setRefresh
(
!
refresh
);
...
...
projects/app/src/global/core/chat/api.d.ts
View file @
e01c38ef
import
type
{
AppTTSConfigType
}
from
'@fastgpt/global/core/module/type.d'
;
import
{
ModuleItemType
}
from
'../module/type'
;
import
{
AdminFbkType
,
ChatItemType
,
moduleDispatchResType
}
from
'@fastgpt/global/core/chat/type'
;
export
type
GetChatSpeechProps
=
{
ttsConfig
:
AppTTSConfigType
;
input
:
string
;
shareId
?:
string
;
};
/* ---------- chat ----------- */
export
type
InitChatProps
=
{
appId
?:
string
;
chatId
?:
string
;
};
export
type
InitOutLinkChatProps
=
{
chatId
?:
string
;
shareId
?:
string
;
outLinkUid
?:
string
;
};
export
type
InitChatResponse
=
{
chatId
?:
string
;
appId
:
string
;
userAvatar
?:
string
;
title
:
string
;
variables
:
Record
<
string
,
any
>
;
history
:
ChatItemType
[];
app
:
{
userGuideModule
?:
ModuleItemType
;
chatModels
?:
string
[];
name
:
string
;
avatar
:
string
;
intro
:
string
;
canUse
?:
boolean
;
};
};
/* ---------- history ----------- */
export
type
getHistoriesProps
=
{
appId
?:
string
;
// share chat
shareId
?:
string
;
outLinkUid
?:
string
;
// authToken/uid
};
export
type
UpdateHistoryProps
=
{
chatId
:
string
;
customTitle
?:
string
;
top
?:
boolean
;
shareId
?:
string
;
outLinkUid
?:
string
;
};
export
type
DelHistoryProps
=
{
chatId
:
string
;
shareId
?:
string
;
outLinkUid
?:
string
;
};
export
type
ClearHistoriesProps
=
{
appId
?:
string
;
shareId
?:
string
;
outLinkUid
?:
string
;
};
/* -------- chat item ---------- */
export
type
DeleteChatItemProps
=
{
chatId
:
string
;
contentId
:
string
;
shareId
?:
string
;
outLinkUid
?:
string
;
};
export
type
AdminUpdateFeedbackParams
=
AdminFbkType
&
{
chatItemId
:
string
;
};
projects/app/src/global/core/chat/constants.ts
0 → 100644
View file @
e01c38ef
import
{
InitChatResponse
}
from
'./api'
;
export
const
defaultChatData
:
InitChatResponse
=
{
chatId
:
''
,
appId
:
''
,
app
:
{
name
:
'Loading'
,
avatar
:
'/icon/logo.svg'
,
intro
:
''
,
canUse
:
false
},
title
:
'新对话'
,
variables
:
{},
history
:
[]
};
projects/app/src/global/core/prompt/AIChat.ts
View file @
e01c38ef
...
...
@@ -33,9 +33,8 @@ export const Prompt_QuotePromptList: PromptTemplateItem[] = [
"""
回答要求:
1. 优先使用知识库内容回答问题。
2. 你可以回答我不知道。
3. 不要提及你是从知识库获取的知识。
4. 知识库包含 markdown 内容时,按 markdown 格式返回。
2. 不要提及你是从知识库获取的知识。
3. 知识库包含 markdown 内容时,按 markdown 格式返回。
我的问题是:"{{question}}"`
},
{
...
...
@@ -47,9 +46,8 @@ export const Prompt_QuotePromptList: PromptTemplateItem[] = [
"""
回答要求:
1. 优先使用知识库内容回答问题,其中 instruction 是相关介绍,output 是预期回答或补充。
2. 你可以回答我不知道。
3. 不要提及你是从知识库获取的知识。
4. 知识库包含 markdown 内容时,按 markdown 格式返回。
2. 不要提及你是从知识库获取的知识。
3. 知识库包含 markdown 内容时,按 markdown 格式返回。
我的问题是:"{{question}}"`
},
{
...
...
projects/app/src/pages/account/components/PayModal.tsx
View file @
e01c38ef
...
...
@@ -54,7 +54,7 @@ const PayModal = ({ onClose }: { onClose: () => void }) => {
onSuccess
(
res
)
{
if
(
!
res
)
return
;
toast
({
title
:
'充值成功'
,
title
:
res
,
status
:
'success'
});
router
.
reload
();
...
...
projects/app/src/pages/api/common/system/unlockTask.ts
View file @
e01c38ef
import
type
{
NextApiRequest
,
NextApiResponse
}
from
'next'
;
import
{
jsonRes
}
from
'@fastgpt/service/common/response'
;
import
{
connectToDatabase
}
from
'@/service/mongo'
;
import
{
MongoDatasetTraining
}
from
'@fastgpt/service/core/dataset/training/schema'
;
import
{
startQueue
}
from
'@/service/utils/tools'
;
import
{
authCert
}
from
'@fastgpt/service/support/permission/auth/common'
;
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
try
{
await
connectToDatabase
();
const
{
userId
}
=
await
authCert
({
req
,
authToken
:
true
});
await
unlockTask
(
userId
);
await
authCert
({
req
,
authToken
:
true
});
startQueue
(
);
}
catch
(
error
)
{}
jsonRes
(
res
);
}
async
function
unlockTask
(
userId
:
string
)
{
try
{
await
MongoDatasetTraining
.
updateMany
(
{
userId
},
{
lockTime
:
new
Date
(
'2000/1/1'
)
}
);
startQueue
();
}
catch
(
error
)
{
unlockTask
(
userId
);
}
}
projects/app/src/pages/api/core/app/del.ts
View file @
e01c38ef
...
...
@@ -5,6 +5,7 @@ import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import
{
MongoApp
}
from
'@fastgpt/service/core/app/schema'
;
import
{
MongoOutLink
}
from
'@fastgpt/service/support/outLink/schema'
;
import
{
authApp
}
from
'@fastgpt/service/support/permission/auth/app'
;
import
{
MongoChatItem
}
from
'@fastgpt/service/core/chat/chatItemSchema'
;
/* 获取我的模型 */
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
...
...
@@ -20,6 +21,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
await
authApp
({
req
,
authToken
:
true
,
appId
,
per
:
'owner'
});
// 删除对应的聊天
await
MongoChatItem
.
deleteMany
({
appId
});
await
MongoChat
.
deleteMany
({
appId
});
...
...
projects/app/src/pages/api/core/app/form2Modules/fastgpt-simple.ts
View file @
e01c38ef
...
...
@@ -381,7 +381,7 @@ function datasetTemplate({
key
:
'similarity'
,
value
:
0.4
,
type
:
FlowNodeInputTypeEnum
.
slider
,
label
:
'相
似
度'
,
label
:
'相
关
度'
,
connected
:
true
},
{
...
...
projects/app/src/pages/api/core/app/form2Modules/fastgpt-universal.ts
View file @
e01c38ef
...
...
@@ -289,7 +289,7 @@ function datasetTemplate(formData: AppSimpleEditFormType): ModuleItemType[] {
key
:
'similarity'
,
value
:
formData
.
dataset
.
similarity
,
type
:
FlowNodeInputTypeEnum
.
slider
,
label
:
'相
似
度'
,
label
:
'相
关
度'
,
connected
:
false
},
{
...
...
projects/app/src/pages/api/core/chat/chatTest.ts
View file @
e01c38ef
...
...
@@ -8,8 +8,9 @@ import { pushChatBill } from '@/service/support/wallet/bill/push';
import
{
BillSourceEnum
}
from
'@fastgpt/global/support/wallet/bill/constants'
;
import
type
{
ChatItemType
}
from
'@fastgpt/global/core/chat/type'
;
import
{
authApp
}
from
'@fastgpt/service/support/permission/auth/app'
;
import
{
authUser
}
from
'@/service/support/permission/auth/user'
;
import
{
dispatchModules
}
from
'@/service/moduleDispatch'
;
import
{
authCert
}
from
'@fastgpt/service/support/permission/auth/common'
;
import
{
getUserAndAuthBalance
}
from
'@fastgpt/service/support/user/controller'
;
export
type
Props
=
{
history
:
ChatItemType
[];
...
...
@@ -40,15 +41,20 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
}
/* user auth */
const
[
{
teamId
,
tmbId
},
{
user
}]
=
await
Promise
.
all
([
const
[
_
,
{
teamId
,
tmbId
}]
=
await
Promise
.
all
([
authApp
({
req
,
authToken
:
true
,
appId
,
per
:
'r'
}),
auth
User
({
auth
Cert
({
req
,
authToken
:
true
,
minBalance
:
0
authToken
:
true
})
]);
// auth balance
const
user
=
await
getUserAndAuthBalance
({
tmbId
,
minBalance
:
0
});
/* start process */
const
{
responseData
}
=
await
dispatchModules
({
res
,
...
...
projects/app/src/pages/api/core/chat/
delete
.ts
→
projects/app/src/pages/api/core/chat/
clearHistories
.ts
View file @
e01c38ef
...
...
@@ -4,45 +4,49 @@ import { connectToDatabase } from '@/service/mongo';
import
{
authCert
}
from
'@fastgpt/service/support/permission/auth/common'
;
import
{
MongoChat
}
from
'@fastgpt/service/core/chat/chatSchema'
;
import
{
MongoChatItem
}
from
'@fastgpt/service/core/chat/chatItemSchema'
;
import
{
ClearHistoriesProps
}
from
'@/global/core/chat/api'
;
import
{
authOutLink
}
from
'@/service/support/permission/auth/outLink'
;
import
{
ChatSourceEnum
}
from
'@fastgpt/global/core/chat/constants'
;
type
Props
=
{
chatId
?:
string
;
appId
?:
string
;
};
/* clear chat history */
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
try
{
await
connectToDatabase
();
const
{
chatId
,
appId
}
=
req
.
query
as
Props
;
const
{
tmbId
}
=
await
authCert
({
req
,
authToken
:
true
});
if
(
chatId
)
{
await
MongoChatItem
.
deleteMany
({
chatId
,
tmbId
});
await
MongoChat
.
findOneAndRemove
({
chatId
,
tmbId
});
}
if
(
appId
)
{
const
chats
=
await
MongoChat
.
find
({
appId
,
tmbId
,
source
:
ChatSourceEnum
.
online
}).
select
(
'_id'
);
const
chatIds
=
chats
.
map
((
chat
)
=>
chat
.
_id
);
await
MongoChatItem
.
deleteMany
({
chatId
:
{
$in
:
chatIds
}
});
await
MongoChat
.
deleteMany
({
_id
:
{
$in
:
chatIds
}
});
}
const
{
appId
,
shareId
,
outLinkUid
}
=
req
.
query
as
ClearHistoriesProps
;
const
match
=
await
(
async
()
=>
{
if
(
shareId
&&
outLinkUid
)
{
const
{
uid
}
=
await
authOutLink
({
shareId
,
outLinkUid
});
return
{
shareId
,
outLinkUid
:
uid
};
}
if
(
appId
)
{
const
{
tmbId
}
=
await
authCert
({
req
,
authToken
:
true
});
return
{
appId
,
tmbId
,
source
:
ChatSourceEnum
.
online
};
}
return
Promise
.
reject
(
'Param are error'
);
})();
console
.
log
(
match
);
// find chatIds
const
list
=
await
MongoChat
.
find
(
match
,
'chatId'
).
lean
();
const
idList
=
list
.
map
((
item
)
=>
item
.
chatId
);
await
MongoChatItem
.
deleteMany
({
chatId
:
{
$in
:
idList
}
});
await
MongoChat
.
deleteMany
({
chatId
:
{
$in
:
idList
}
});
jsonRes
(
res
);
}
catch
(
err
)
{
...
...
projects/app/src/pages/api/core/chat/delHistory.ts
0 → 100644
View file @
e01c38ef
import
type
{
NextApiRequest
,
NextApiResponse
}
from
'next'
;
import
{
jsonRes
}
from
'@fastgpt/service/common/response'
;
import
{
connectToDatabase
}
from
'@/service/mongo'
;
import
{
MongoChat
}
from
'@fastgpt/service/core/chat/chatSchema'
;
import
{
MongoChatItem
}
from
'@fastgpt/service/core/chat/chatItemSchema'
;
import
{
DelHistoryProps
}
from
'@/global/core/chat/api'
;
import
{
autChatCrud
}
from
'@/service/support/permission/auth/chat'
;
/* clear chat history */
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
try
{
await
connectToDatabase
();
const
{
chatId
,
shareId
,
outLinkUid
}
=
req
.
query
as
DelHistoryProps
;
await
autChatCrud
({
req
,
authToken
:
true
,
chatId
,
shareId
,
outLinkUid
,
per
:
'w'
});
await
MongoChatItem
.
deleteMany
({
chatId
});
await
MongoChat
.
findOneAndRemove
({
chatId
});
jsonRes
(
res
);
}
catch
(
err
)
{
jsonRes
(
res
,
{
code
:
500
,
error
:
err
});
}
}
projects/app/src/pages/api/core/chat/feedback/adminUpdate.ts
View file @
e01c38ef
...
...
@@ -2,7 +2,7 @@ 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
type
{
AdminUpdateFeedbackParams
}
from
'@
fastgpt
/global/core/chat/api.d'
;
import
type
{
AdminUpdateFeedbackParams
}
from
'@/global/core/chat/api.d'
;
import
{
MongoChatItem
}
from
'@fastgpt/service/core/chat/chatItemSchema'
;
/* 初始化我的聊天框,需要身份验证 */
...
...
projects/app/src/pages/api/core/chat/
list
.ts
→
projects/app/src/pages/api/core/chat/
getHistories
.ts
View file @
e01c38ef
...
...
@@ -4,25 +4,44 @@ import { connectToDatabase } from '@/service/mongo';
import
{
MongoChat
}
from
'@fastgpt/service/core/chat/chatSchema'
;
import
type
{
ChatHistoryItemType
}
from
'@fastgpt/global/core/chat/type.d'
;
import
{
ChatSourceEnum
}
from
'@fastgpt/global/core/chat/constants'
;
import
{
authApp
}
from
'@fastgpt/service/support/permission/auth/app'
;
import
{
getHistoriesProps
}
from
'@/global/core/chat/api'
;
import
{
authOutLink
}
from
'@/service/support/permission/auth/outLink'
;
import
{
authCert
}
from
'@fastgpt/service/support/permission/auth/common'
;
/* 获取历史记录 */
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
try
{
await
connectToDatabase
();
const
{
appId
}
=
req
.
body
as
{
appId
:
string
};
const
{
tmbId
}
=
await
authApp
({
req
,
authToken
:
true
,
appId
,
per
:
'r'
});
const
{
appId
,
shareId
,
outLinkUid
}
=
req
.
body
as
getHistoriesProps
;
const
data
=
await
MongoChat
.
find
(
{
appId
,
tmbId
,
source
:
ChatSourceEnum
.
online
},
'chatId title top customTitle appId updateTime'
)
const
limit
=
shareId
&&
outLinkUid
?
20
:
30
;
const
match
=
await
(
async
()
=>
{
if
(
shareId
&&
outLinkUid
)
{
const
{
uid
}
=
await
authOutLink
({
shareId
,
outLinkUid
});
return
{
shareId
,
outLinkUid
:
uid
,
source
:
ChatSourceEnum
.
share
,
updateTime
:
{
$gte
:
new
Date
(
new
Date
().
setDate
(
new
Date
().
getDate
()
-
30
))
}
};
}
if
(
appId
)
{
const
{
tmbId
}
=
await
authCert
({
req
,
authToken
:
true
});
return
{
appId
,
tmbId
,
source
:
ChatSourceEnum
.
online
};
}
return
Promise
.
reject
(
'Params are error'
);
})();
const
data
=
await
MongoChat
.
find
(
match
,
'chatId title top customTitle appId updateTime'
)
.
sort
({
top
:
-
1
,
updateTime
:
-
1
})
.
limit
(
20
);
.
limit
(
limit
);
jsonRes
<
ChatHistoryItemType
[]
>
(
res
,
{
data
:
data
.
map
((
item
)
=>
({
...
...
projects/app/src/pages/api/core/chat/init.ts
View file @
e01c38ef
import
type
{
NextApiRequest
,
NextApiResponse
}
from
'next'
;
import
{
jsonRes
}
from
'@fastgpt/service/common/response'
;
import
{
connectToDatabase
}
from
'@/service/mongo'
;
import
{
MongoChatItem
}
from
'@fastgpt/service/core/chat/chatItemSchema'
;
import
type
{
InitChatResponse
}
from
'@fastgpt/global/core/chat/api.d'
;
import
type
{
ChatItemType
}
from
'@fastgpt/global/core/chat/type.d'
;
import
{
authApp
}
from
'@fastgpt/service/support/permission/auth/app'
;
import
{
getGuideModule
}
from
'@fastgpt/global/core/module/utils'
;
import
{
getChatModelNameListByModules
}
from
'@/service/core/app/module'
;
import
{
authChat
}
from
'@fastgpt/service/support/permission/auth/chat'
;
import
{
ModuleOutputKeyEnum
}
from
'@fastgpt/global/core/module/constants'
;
import
type
{
InitChatProps
,
InitChatResponse
}
from
'@/global/core/chat/api.d'
;
import
{
MongoChat
}
from
'@fastgpt/service/core/chat/chatSchema'
;
import
{
getChatItems
}
from
'@fastgpt/service/core/chat/controller'
;
import
{
ChatErrEnum
}
from
'@fastgpt/global/common/error/code/chat'
;
/* 初始化我的聊天框,需要身份验证 */
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
try
{
await
connectToDatabase
();
let
{
appId
,
chatId
}
=
req
.
query
as
{
appId
:
string
;
chatId
:
''
|
string
;
};
let
{
appId
,
chatId
}
=
req
.
query
as
InitChatProps
;
if
(
!
appId
)
{
return
jsonRes
(
res
,
{
...
...
@@ -27,57 +23,44 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
});
}
//
校验使用权限
const
[{
app
},
autChatResul
t
]
=
await
Promise
.
all
([
//
auth app permission
const
[{
app
,
tmbId
},
cha
t
]
=
await
Promise
.
all
([
authApp
({
req
,
authToken
:
true
,
appId
,
per
:
'r'
}),
chatId
?
authChat
({
req
,
authToken
:
true
,
chatId
,
per
:
'r'
})
:
undefined
chatId
?
MongoChat
.
findOne
({
chatId
})
:
undefined
]);
// get app and history
const
{
history
=
[]
}:
{
history
?:
ChatItemType
[]
}
=
await
(
async
()
=>
{
if
(
chatId
)
{
// auth chatId
const
history
=
await
MongoChatItem
.
find
(
{
chatId
},
`dataId obj value adminFeedback userFeedback
${
ModuleOutputKeyEnum
.
responseData
}
`
)
.
sort
({
_id
:
-
1
})
.
limit
(
30
);
// auth chat permission
if
(
!
app
.
canWrite
&&
String
(
tmbId
)
!==
String
(
chat
?.
tmbId
))
{
throw
new
Error
(
ChatErrEnum
.
unAuthChat
);
}
history
.
reverse
();
return
{
history
};
}
return
{};
})();
// get app and history
const
{
history
}
=
await
getChatItems
({
chatId
,
limit
:
30
,
field
:
`dataId obj value adminFeedback userFeedback
${
ModuleOutputKeyEnum
.
responseData
}
`
});
jsonRes
<
InitChatResponse
>
(
res
,
{
data
:
{
chatId
,
appId
,
title
:
chat
?.
title
||
'新对话'
,
userAvatar
:
undefined
,
variables
:
chat
?.
variables
||
{},
history
,
app
:
{
userGuideModule
:
getGuideModule
(
app
.
modules
),
chatModels
:
getChatModelNameListByModules
(
app
.
modules
),
name
:
app
.
name
,
avatar
:
app
.
avatar
,
intro
:
app
.
intro
},
title
:
autChatResult
?.
chat
?.
title
||
'新对话'
,
variables
:
autChatResult
?.
chat
?.
variables
||
{},
history
}
}
});
}
catch
(
err
)
{
...
...
projects/app/src/pages/api/core/chat/initLocalShareHistoryV464.ts
0 → 100644
View file @
e01c38ef
import
type
{
NextApiRequest
,
NextApiResponse
}
from
'next'
;
import
{
jsonRes
}
from
'@fastgpt/service/common/response'
;
import
{
connectToDatabase
}
from
'@/service/mongo'
;
import
{
MongoChat
}
from
'@fastgpt/service/core/chat/chatSchema'
;
import
{
ChatSourceEnum
}
from
'@fastgpt/global/core/chat/constants'
;
/* clear chat history */
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
try
{
await
connectToDatabase
();
const
{
outLinkUid
,
chatIds
}
=
req
.
body
as
{
outLinkUid
:
string
;
chatIds
:
string
[];
};
if
(
!
outLinkUid
)
{
throw
new
Error
(
'shareId or outLinkUid is required'
);
}
const
sliceIds
=
chatIds
.
slice
(
0
,
50
);
await
MongoChat
.
updateMany
(
{
chatId
:
{
$in
:
sliceIds
},
source
:
ChatSourceEnum
.
share
,
outLinkUid
:
{
$exists
:
false
}
},
{
$set
:
{
outLinkUid
}
}
);
jsonRes
(
res
);
}
catch
(
err
)
{
jsonRes
(
res
,
{
code
:
500
,
error
:
err
});
}
}
projects/app/src/pages/api/core/chat/item/delete.ts
View file @
e01c38ef
...
...
@@ -2,14 +2,22 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import
{
jsonRes
}
from
'@fastgpt/service/common/response'
;
import
{
connectToDatabase
}
from
'@/service/mongo'
;
import
{
MongoChatItem
}
from
'@fastgpt/service/core/chat/chatItemSchema'
;
import
{
authChat
}
from
'@fastgpt/service/support/permission/auth/chat'
;
import
{
autChatCrud
}
from
'@/service/support/permission/auth/chat'
;
import
type
{
DeleteChatItemProps
}
from
'@/global/core/chat/api.d'
;
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
try
{
await
connectToDatabase
();
const
{
chatId
,
contentId
}
=
req
.
query
as
{
chatId
:
string
;
contentId
:
string
}
;
const
{
chatId
,
contentId
,
shareId
,
outLinkUid
}
=
req
.
query
as
DeleteChatItemProps
;
await
authChat
({
req
,
authToken
:
true
,
chatId
,
per
:
'w'
});
await
autChatCrud
({
req
,
authToken
:
true
,
chatId
,
shareId
,
outLinkUid
,
per
:
'w'
});
await
MongoChatItem
.
deleteOne
({
dataId
:
contentId
,
...
...
projects/app/src/pages/api/core/chat/outLink/init.ts
0 → 100644
View file @
e01c38ef
import
type
{
NextApiRequest
,
NextApiResponse
}
from
'next'
;
import
{
jsonRes
}
from
'@fastgpt/service/common/response'
;
import
{
connectToDatabase
}
from
'@/service/mongo'
;
import
type
{
InitChatResponse
,
InitOutLinkChatProps
}
from
'@/global/core/chat/api.d'
;
import
{
getGuideModule
}
from
'@fastgpt/global/core/module/utils'
;
import
{
getChatModelNameListByModules
}
from
'@/service/core/app/module'
;
import
{
ModuleOutputKeyEnum
}
from
'@fastgpt/global/core/module/constants'
;
import
{
getChatItems
}
from
'@fastgpt/service/core/chat/controller'
;
import
{
MongoTeamMember
}
from
'@fastgpt/service/support/user/team/teamMemberSchema'
;
import
{
authOutLink
}
from
'@/service/support/permission/auth/outLink'
;
import
{
MongoApp
}
from
'@fastgpt/service/core/app/schema'
;
import
{
selectShareResponse
}
from
'@/utils/service/core/chat'
;
import
{
AppErrEnum
}
from
'@fastgpt/global/common/error/code/app'
;
import
{
MongoChat
}
from
'@fastgpt/service/core/chat/chatSchema'
;
import
{
ChatErrEnum
}
from
'@fastgpt/global/common/error/code/chat'
;
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
try
{
await
connectToDatabase
();
let
{
chatId
,
shareId
,
outLinkUid
}
=
req
.
query
as
InitOutLinkChatProps
;
// auth link permission
const
{
shareChat
,
uid
,
appId
}
=
await
authOutLink
({
shareId
,
outLinkUid
});
// auth app permission
const
[
tmb
,
chat
,
app
]
=
await
Promise
.
all
([
MongoTeamMember
.
findById
(
shareChat
.
tmbId
,
'_id userId'
).
populate
(
'userId'
,
'avatar'
).
lean
(),
MongoChat
.
findOne
({
chatId
,
shareId
}).
lean
(),
MongoApp
.
findById
(
appId
).
lean
()
]);
if
(
!
app
)
{
throw
new
Error
(
AppErrEnum
.
unExist
);
}
// auth chat permission
if
(
chat
&&
chat
.
outLinkUid
!==
uid
)
{
throw
new
Error
(
ChatErrEnum
.
unAuthChat
);
}
const
{
history
}
=
await
getChatItems
({
chatId
,
limit
:
30
,
field
:
`dataId obj value userFeedback
${
shareChat
.
responseDetail
?
`adminFeedback
${
ModuleOutputKeyEnum
.
responseData
}
`
:
''
}
`
});
// pick share response field
history
.
forEach
((
item
)
=>
{
item
.
responseData
=
selectShareResponse
({
responseData
:
item
.
responseData
});
});
jsonRes
<
InitChatResponse
>
(
res
,
{
data
:
{
chatId
,
appId
:
app
.
_id
,
title
:
chat
?.
title
||
'新对话'
,
//@ts-ignore
userAvatar
:
tmb
?.
userId
?.
avatar
,
variables
:
chat
?.
variables
||
{},
history
,
app
:
{
userGuideModule
:
getGuideModule
(
app
.
modules
),
chatModels
:
getChatModelNameListByModules
(
app
.
modules
),
name
:
app
.
name
,
avatar
:
app
.
avatar
,
intro
:
app
.
intro
}
}
});
}
catch
(
err
)
{
jsonRes
(
res
,
{
code
:
500
,
error
:
err
});
}
}
export
const
config
=
{
api
:
{
responseLimit
:
'10mb'
}
};
projects/app/src/pages/api/core/chat/update.ts
→
projects/app/src/pages/api/core/chat/update
History
.ts
View file @
e01c38ef
import
type
{
NextApiRequest
,
NextApiResponse
}
from
'next'
;
import
{
jsonRes
}
from
'@fastgpt/service/common/response'
;
import
{
connectToDatabase
}
from
'@/service/mongo'
;
import
{
UpdateHistoryProps
}
from
'@
fastgpt
/global/core/chat/api.d'
;
import
{
UpdateHistoryProps
}
from
'@/global/core/chat/api.d'
;
import
{
MongoChat
}
from
'@fastgpt/service/core/chat/chatSchema'
;
import
{
aut
hChat
}
from
'@fastgpt
/service/support/permission/auth/chat'
;
import
{
aut
ChatCrud
}
from
'@
/service/support/permission/auth/chat'
;
/*
更新聊天标题
*/
/*
update chat top, custom title
*/
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
try
{
await
connectToDatabase
();
const
{
chatId
,
customTitle
,
top
}
=
req
.
body
as
UpdateHistoryProps
;
const
{
chatId
,
shareId
,
outLinkUid
,
customTitle
,
top
}
=
req
.
body
as
UpdateHistoryProps
;
await
authChat
({
req
,
authToken
:
true
,
chatId
});
await
autChatCrud
({
req
,
authToken
:
true
,
chatId
,
shareId
,
outLinkUid
,
per
:
'w'
});
await
MongoChat
.
findOneAndUpdate
(
{
chatId
},
...
...
projects/app/src/pages/api/core/dataset/update.ts
View file @
e01c38ef
...
...
@@ -8,7 +8,7 @@ import { authDataset } from '@fastgpt/service/support/permission/auth/dataset';
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
try
{
await
connectToDatabase
();
const
{
id
,
parentId
,
name
,
avatar
,
tags
,
permission
,
agentModel
,
websiteConfig
,
status
}
=
const
{
id
,
parentId
,
name
,
avatar
,
intro
,
permission
,
agentModel
,
websiteConfig
,
status
}
=
req
.
body
as
DatasetUpdateBody
;
if
(
!
id
)
{
...
...
@@ -26,11 +26,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
...(
parentId
!==
undefined
&&
{
parentId
:
parentId
||
null
}),
...(
name
&&
{
name
}),
...(
avatar
&&
{
avatar
}),
...(
tags
&&
{
tags
}),
...(
permission
&&
{
permission
}),
...(
agentModel
&&
{
agentModel
:
agentModel
.
model
}),
...(
websiteConfig
&&
{
websiteConfig
}),
...(
status
&&
{
status
})
...(
status
&&
{
status
}),
...(
intro
&&
{
intro
})
}
);
...
...
projects/app/src/pages/api/support/outLink/init.ts
deleted
100644 → 0
View file @
71afe711
import
type
{
NextApiRequest
,
NextApiResponse
}
from
'next'
;
import
{
jsonRes
}
from
'@fastgpt/service/common/response'
;
import
{
connectToDatabase
}
from
'@/service/mongo'
;
import
{
MongoUser
}
from
'@fastgpt/service/support/user/schema'
;
import
type
{
InitShareChatResponse
}
from
'@fastgpt/global/support/outLink/api.d'
;
import
{
HUMAN_ICON
}
from
'@fastgpt/global/core/chat/constants'
;
import
{
getGuideModule
}
from
'@fastgpt/global/core/module/utils'
;
import
{
authShareChatInit
}
from
'@/service/support/outLink/auth'
;
import
{
getChatModelNameListByModules
}
from
'@/service/core/app/module'
;
import
{
authOutLinkValid
}
from
'@fastgpt/service/support/permission/auth/outLink'
;
/* init share chat window */
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
try
{
await
connectToDatabase
();
let
{
shareId
,
authToken
}
=
req
.
query
as
{
shareId
:
string
;
authToken
?:
string
;
};
// get shareChat
const
{
app
,
shareChat
}
=
await
authOutLinkValid
({
shareId
});
// 校验使用权限
const
[
user
]
=
await
Promise
.
all
([
MongoUser
.
findById
(
shareChat
.
userId
,
'avatar'
),
authShareChatInit
({
authToken
,
tokenUrl
:
shareChat
.
limit
?.
hookUrl
})
]);
jsonRes
<
InitShareChatResponse
>
(
res
,
{
data
:
{
userAvatar
:
user
?.
avatar
||
HUMAN_ICON
,
app
:
{
userGuideModule
:
getGuideModule
(
app
.
modules
),
chatModels
:
getChatModelNameListByModules
(
app
.
modules
),
name
:
app
.
name
,
avatar
:
app
.
avatar
,
intro
:
app
.
intro
}
}
});
}
catch
(
err
)
{
jsonRes
(
res
,
{
code
:
500
,
error
:
err
});
}
}
projects/app/src/pages/api/user/account/loginByPassword.ts
View file @
e01c38ef
...
...
@@ -3,7 +3,7 @@ import { jsonRes } from '@fastgpt/service/common/response';
import
{
MongoUser
}
from
'@fastgpt/service/support/user/schema'
;
import
{
createJWT
,
setCookie
}
from
'@fastgpt/service/support/permission/controller'
;
import
{
connectToDatabase
}
from
'@/service/mongo'
;
import
{
getUserDetail
}
from
'@/service/support/user/controller'
;
import
{
getUserDetail
}
from
'@
fastgpt
/service/support/user/controller'
;
import
type
{
PostLoginProps
}
from
'@fastgpt/global/support/user/api.d'
;
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
...
...
projects/app/src/pages/api/user/account/tokenLogin.ts
View file @
e01c38ef
...
...
@@ -2,7 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import
{
jsonRes
}
from
'@fastgpt/service/common/response'
;
import
{
authCert
}
from
'@fastgpt/service/support/permission/auth/common'
;
import
{
connectToDatabase
}
from
'@/service/mongo'
;
import
{
getUserDetail
}
from
'@/service/support/user/controller'
;
import
{
getUserDetail
}
from
'@
fastgpt
/service/support/user/controller'
;
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
try
{
...
...
projects/app/src/pages/api/v1/audio/transcriptions.ts
View file @
e01c38ef
import
type
{
NextApiRequest
,
NextApiResponse
}
from
'next'
;
import
{
jsonRes
}
from
'@fastgpt/service/common/response'
;
import
{
authCert
,
authCertAndShareId
}
from
'@fastgpt/service/support/permission/auth/common'
;
import
{
authCert
}
from
'@fastgpt/service/support/permission/auth/common'
;
import
{
withNextCors
}
from
'@fastgpt/service/common/middle/cors'
;
import
{
getUploadModel
}
from
'@fastgpt/service/common/file/upload/multer'
;
import
fs
from
'fs'
;
...
...
projects/app/src/pages/api/v1/chat/completions.ts
View file @
e01c38ef
...
...
@@ -10,11 +10,11 @@ import { dispatchModules } from '@/service/moduleDispatch';
import
type
{
ChatCompletionCreateParams
}
from
'@fastgpt/global/core/ai/type.d'
;
import
type
{
ChatMessageItemType
}
from
'@fastgpt/global/core/ai/type.d'
;
import
{
gptMessage2ChatType
,
textAdaptGptResponse
}
from
'@/utils/adapt'
;
import
{
getChat
History
}
from
'./getHistory
'
;
import
{
getChat
Items
}
from
'@fastgpt/service/core/chat/controller
'
;
import
{
saveChat
}
from
'@/service/utils/chat/saveChat'
;
import
{
responseWrite
}
from
'@fastgpt/service/common/response'
;
import
{
pushChatBill
}
from
'@/service/support/wallet/bill/push'
;
import
{
authOutLinkChat
}
from
'@/service/support/permission/auth/outLink'
;
import
{
authOutLinkChat
Start
}
from
'@/service/support/permission/auth/outLink'
;
import
{
pushResult2Remote
,
updateOutLinkUsage
}
from
'@fastgpt/service/support/outLink/tools'
;
import
requestIp
from
'request-ip'
;
import
{
getBillSourceByAuthType
}
from
'@fastgpt/global/support/wallet/bill/tools'
;
...
...
@@ -22,9 +22,10 @@ import { getBillSourceByAuthType } from '@fastgpt/global/support/wallet/bill/too
import
{
selectShareResponse
}
from
'@/utils/service/core/chat'
;
import
{
updateApiKeyUsage
}
from
'@fastgpt/service/support/openapi/tools'
;
import
{
connectToDatabase
}
from
'@/service/mongo'
;
import
{
getUserAndAuthBalance
}
from
'@
/service/support/permission/auth/us
er'
;
import
{
getUserAndAuthBalance
}
from
'@
fastgpt/service/support/user/controll
er'
;
import
{
AuthUserTypeEnum
}
from
'@fastgpt/global/support/permission/constant'
;
import
{
MongoApp
}
from
'@fastgpt/service/core/app/schema'
;
import
{
autChatCrud
}
from
'@/service/support/permission/auth/chat'
;
type
FastGptWebChatProps
=
{
chatId
?:
string
;
// undefined: nonuse history, '': new chat, 'xxxxx': use history
...
...
@@ -32,7 +33,7 @@ type FastGptWebChatProps = {
};
type
FastGptShareChatProps
=
{
shareId
?:
string
;
authToken
?:
string
;
outLinkUid
?:
string
;
};
export
type
Props
=
ChatCompletionCreateParams
&
FastGptWebChatProps
&
...
...
@@ -56,11 +57,11 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
res
.
end
();
});
le
t
{
cons
t
{
chatId
,
appId
,
shareId
,
authToken
,
outLinkUid
,
stream
=
false
,
detail
=
false
,
messages
=
[],
...
...
@@ -93,22 +94,29 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
throw
new
Error
(
'Question is empty'
);
}
/*
auth app permission */
const
{
user
,
app
,
responseDetail
,
authType
,
apikey
,
canWrite
}
=
await
(
async
()
=>
{
if
(
shareId
)
{
const
{
user
,
app
,
authType
,
responseDetail
}
=
await
authOutLinkCha
t
({
/* auth app permission */
const
{
user
,
app
,
responseDetail
,
authType
,
apikey
,
canWrite
,
uid
}
=
await
(
async
()
=>
{
if
(
shareId
&&
outLinkUid
)
{
const
{
user
,
app
Id
,
authType
,
responseDetail
,
uid
}
=
await
authOutLinkChatStar
t
({
shareId
,
ip
:
requestIp
.
getClientIp
(
req
),
authToken
,
outLinkUid
,
question
:
question
.
value
});
const
app
=
await
MongoApp
.
findById
(
appId
);
if
(
!
app
)
{
return
Promise
.
reject
(
'app is empty'
);
}
return
{
user
,
app
,
responseDetail
,
apikey
:
''
,
authType
,
canWrite
:
false
canWrite
:
false
,
uid
};
}
...
...
@@ -146,11 +154,10 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
};
}
// token auth
if
(
!
appId
)
{
return
Promise
.
reject
(
'appId is empty'
);
}
// token
const
{
app
,
canWrite
}
=
await
authApp
({
req
,
authToken
:
true
,
...
...
@@ -168,12 +175,19 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
};
})();
// auth app, get history
const
{
history
}
=
await
getChatHistory
({
chatId
,
tmbId
:
user
.
team
.
tmbId
});
const
isAppOwner
=
!
shareId
&&
String
(
user
.
team
.
tmbId
)
===
String
(
app
.
tmbId
);
// auth chat permission
await
autChatCrud
({
req
,
authToken
:
true
,
authApiKey
:
true
,
chatId
,
shareId
,
outLinkUid
,
per
:
'w'
});
/* format prompts */
// get and concat history
const
{
history
}
=
await
getChatItems
({
chatId
,
limit
:
30
,
field
:
`dataId obj value`
});
const
concatHistory
=
history
.
concat
(
chatMessages
);
/* start flow controller */
...
...
@@ -202,8 +216,9 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
teamId
:
user
.
team
.
teamId
,
tmbId
:
user
.
team
.
tmbId
,
variables
,
updateUseTime
:
isAppOwner
,
// owner update use time
updateUseTime
:
!
shareId
&&
String
(
user
.
team
.
tmbId
)
===
String
(
app
.
tmbId
)
,
// owner update use time
shareId
,
outLinkUid
:
uid
,
source
:
(()
=>
{
if
(
shareId
)
{
return
ChatSourceEnum
.
share
;
...
...
@@ -281,7 +296,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
});
if
(
shareId
)
{
pushResult2Remote
({
authToken
,
shareId
,
responseData
});
pushResult2Remote
({
outLinkUid
,
shareId
,
responseData
});
updateOutLinkUsage
({
shareId
,
total
...
...
projects/app/src/pages/api/v1/chat/getHistory.ts
deleted
100644 → 0
View file @
71afe711
import
type
{
NextApiRequest
,
NextApiResponse
}
from
'next'
;
import
{
jsonRes
}
from
'@fastgpt/service/common/response'
;
import
{
authCert
}
from
'@fastgpt/service/support/permission/auth/common'
;
import
{
connectToDatabase
}
from
'@/service/mongo'
;
import
{
MongoChatItem
}
from
'@fastgpt/service/core/chat/chatItemSchema'
;
import
{
Types
}
from
'@fastgpt/service/common/mongo'
;
import
type
{
ChatItemType
}
from
'@fastgpt/global/core/chat/type.d'
;
export
type
Props
=
{
appId
?:
string
;
chatId
?:
string
;
limit
?:
number
;
};
export
type
Response
=
{
history
:
ChatItemType
[]
};
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
try
{
await
connectToDatabase
();
const
{
tmbId
}
=
await
authCert
({
req
,
authToken
:
true
});
const
{
chatId
,
limit
}
=
req
.
body
as
Props
;
jsonRes
<
Response
>
(
res
,
{
data
:
await
getChatHistory
({
chatId
,
tmbId
,
limit
})
});
}
catch
(
err
)
{
jsonRes
(
res
,
{
code
:
500
,
error
:
err
});
}
}
export
async
function
getChatHistory
({
chatId
,
tmbId
,
limit
=
30
}:
Props
&
{
tmbId
:
string
}):
Promise
<
Response
>
{
if
(
!
chatId
)
{
return
{
history
:
[]
};
}
const
history
=
await
MongoChatItem
.
aggregate
([
{
$match
:
{
chatId
,
tmbId
:
new
Types
.
ObjectId
(
tmbId
)
}
},
{
$sort
:
{
_id
:
-
1
}
},
{
$limit
:
limit
},
{
$project
:
{
dataId
:
1
,
obj
:
1
,
value
:
1
}
}
]);
history
.
reverse
();
return
{
history
};
}
projects/app/src/pages/app/detail/components/Logs.tsx
View file @
e01c38ef
...
...
@@ -23,7 +23,7 @@ import { AppLogsListItemType } from '@/types/app';
import
{
useSystemStore
}
from
'@/web/common/system/useSystemStore'
;
import
ChatBox
,
{
type
ComponentRef
}
from
'@/components/ChatBox'
;
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
{
getInitChat
Site
Info
}
from
'@/web/core/chat/api'
;
import
{
getInitChatInfo
}
from
'@/web/core/chat/api'
;
import
Tag
from
'@/components/Tag'
;
import
MyModal
from
'@/components/MyModal'
;
import
DateRangePicker
,
{
type
DateRangeType
}
from
'@/components/DateRangePicker'
;
...
...
@@ -199,7 +199,7 @@ function DetailLogsModal({
const
{
data
:
chat
}
=
useQuery
(
[
'getChatDetail'
,
chatId
],
()
=>
getInitChat
Site
Info
({
appId
,
chatId
}),
()
=>
getInitChatInfo
({
appId
,
chatId
}),
{
onSuccess
(
res
)
{
const
history
=
res
.
history
.
map
((
item
)
=>
({
...
...
projects/app/src/pages/app/detail/index.tsx
View file @
e01c38ef
...
...
@@ -104,7 +104,7 @@ const AppDetail = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
>
<
Flex
mb=
{
4
}
alignItems=
{
'center'
}
>
<
Avatar
src=
{
appDetail
.
avatar
}
w=
{
'34px'
}
borderRadius=
{
'lg'
}
/>
<
Box
ml=
{
2
}
fontWeight=
{
'bold'
}
>
<
Box
ml=
{
2
}
fontWeight=
{
'bold'
}
fontSize=
{
'sm'
}
>
{
appDetail
.
name
}
</
Box
>
</
Flex
>
...
...
projects/app/src/pages/chat/components/ChatHistorySlider.tsx
View file @
e01c38ef
...
...
@@ -55,7 +55,7 @@ const ChatHistorySlider = ({
history
:
HistoryItemType
[];
activeChatId
:
string
;
onChangeChat
:
(
chatId
?:
string
)
=>
void
;
onDelHistory
:
(
chatId
:
string
)
=>
void
;
onDelHistory
:
(
e
:
{
chatId
:
string
}
)
=>
void
;
onClearHistory
:
()
=>
void
;
onSetHistoryTop
?:
(
e
:
{
chatId
:
string
;
top
:
boolean
})
=>
void
;
onSetCustomTitle
?:
(
e
:
{
chatId
:
string
;
title
:
string
})
=>
void
;
...
...
@@ -261,7 +261,7 @@ const ChatHistorySlider = ({
_hover=
{
{
color
:
'red.500'
}
}
onClick=
{
(
e
)
=>
{
e
.
stopPropagation
();
onDelHistory
(
item
.
id
);
onDelHistory
(
{
chatId
:
item
.
id
}
);
if
(
item
.
id
===
activeChatId
)
{
onChangeChat
();
}
...
...
projects/app/src/pages/chat/index.tsx
View file @
e01c38ef
import
React
,
{
useCallback
,
useRef
}
from
'react'
;
import
Head
from
'next/head'
;
import
{
useRouter
}
from
'next/router'
;
import
{
getInitChat
SiteInfo
,
delChatRecordById
,
putChatHistory
}
from
'@/web/core/chat/api'
;
import
{
getInitChat
Info
,
putChatHistory
}
from
'@/web/core/chat/api'
;
import
{
Box
,
Flex
,
...
...
@@ -34,6 +34,7 @@ import { serviceSideProps } from '@/web/common/utils/i18n';
import
{
useAppStore
}
from
'@/web/core/app/store/useAppStore'
;
import
{
checkChatSupportSelectFileByChatModels
}
from
'@/web/core/chat/utils'
;
import
{
chatContentReplaceBlock
}
from
'@fastgpt/global/core/chat/utils'
;
import
{
ChatStatusEnum
}
from
'@fastgpt/global/core/chat/constants'
;
const
Chat
=
({
appId
,
chatId
}:
{
appId
:
string
;
chatId
:
string
})
=>
{
const
router
=
useRouter
();
...
...
@@ -49,13 +50,15 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
setLastChatAppId
,
lastChatId
,
setLastChatId
,
history
,
loadHistory
,
histories
,
loadHistories
,
pushHistory
,
updateHistory
,
delHistory
,
clearHistor
y
,
del
One
History
,
clearHistor
ies
,
chatData
,
setChatData
setChatData
,
delOneHistoryItem
}
=
useChatStore
();
const
{
myApps
,
loadMyApps
}
=
useAppStore
();
const
{
userInfo
}
=
useUserStore
();
...
...
@@ -85,7 +88,7 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
prompts
[
1
]?.
value
?.
slice
(
0
,
20
)
||
'新对话'
;
//
update history
//
new chat
if
(
completionChatId
!==
chatId
)
{
const
newHistory
:
ChatHistoryItemType
=
{
chatId
:
completionChatId
,
...
...
@@ -94,7 +97,7 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
appId
,
top
:
false
};
update
History
(
newHistory
);
push
History
(
newHistory
);
if
(
controller
.
signal
.
reason
!==
'leave'
)
{
forbidRefresh
.
current
=
true
;
router
.
replace
({
...
...
@@ -105,7 +108,8 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
});
}
}
else
{
const
currentChat
=
history
.
find
((
item
)
=>
item
.
chatId
===
chatId
);
// update chat
const
currentChat
=
histories
.
find
((
item
)
=>
item
.
chatId
===
chatId
);
currentChat
&&
updateHistory
({
...
currentChat
,
...
...
@@ -117,30 +121,12 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
setChatData
((
state
)
=>
({
...
state
,
title
:
newTitle
,
history
:
ChatBoxRef
.
current
?.
getChatHistor
y
()
||
state
.
history
history
:
ChatBoxRef
.
current
?.
getChatHistor
ies
()
||
state
.
history
}));
return
{
responseText
,
responseData
,
isNewChat
:
forbidRefresh
.
current
};
},
[
appId
,
chatId
,
history
,
router
,
setChatData
,
updateHistory
]
);
// del one chat content
const
delOneHistoryItem
=
useCallback
(
async
({
contentId
,
index
}:
{
contentId
?:
string
;
index
:
number
})
=>
{
if
(
!
chatId
||
!
contentId
)
return
;
try
{
setChatData
((
state
)
=>
({
...
state
,
history
:
state
.
history
.
filter
((
_
,
i
)
=>
i
!==
index
)
}));
await
delChatRecordById
({
chatId
,
contentId
});
}
catch
(
err
)
{
console
.
log
(
err
);
}
},
[
chatId
,
setChatData
]
[
appId
,
chatId
,
histories
,
pushHistory
,
router
,
setChatData
,
updateHistory
]
);
// get chat app info
...
...
@@ -156,10 +142,10 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
})
=>
{
try
{
loading
&&
setIsLoading
(
true
);
const
res
=
await
getInitChat
Site
Info
({
appId
,
chatId
});
const
res
=
await
getInitChatInfo
({
appId
,
chatId
});
const
history
=
res
.
history
.
map
((
item
)
=>
({
...
item
,
status
:
'finish'
as
any
status
:
ChatStatusEnum
.
finish
}));
setChatData
({
...
...
@@ -185,8 +171,13 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
});
if
(
e
?.
code
===
501
)
{
router
.
replace
(
'/app/list'
);
}
else
{
router
.
replace
(
'/chat'
);
}
else
if
(
chatId
)
{
router
.
replace
({
query
:
{
...
router
.
query
,
chatId
:
''
}
});
}
}
setIsLoading
(
false
);
...
...
@@ -250,7 +241,7 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
});
});
useQuery
([
'loadHistor
y'
,
appId
],
()
=>
(
appId
?
loadHistory
({
appId
})
:
null
));
useQuery
([
'loadHistor
ies'
,
appId
],
()
=>
(
appId
?
loadHistories
({
appId
})
:
null
));
return
(
<
Flex
h=
{
'100%'
}
>
...
...
@@ -289,7 +280,7 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
appAvatar=
{
chatData
.
app
.
avatar
}
activeChatId=
{
chatId
}
onClose=
{
onCloseSlider
}
history=
{
histor
y
.
map
((
item
,
i
)
=>
({
history=
{
histor
ies
.
map
((
item
,
i
)
=>
({
id
:
item
.
chatId
,
title
:
item
.
title
,
customTitle
:
item
.
customTitle
,
...
...
@@ -306,39 +297,24 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
onCloseSlider
();
}
}
}
onDelHistory=
{
delHistory
}
onDelHistory=
{
del
One
History
}
onClearHistory=
{
()
=>
{
clearHistor
y
(
appId
);
clearHistor
ies
({
appId
}
);
router
.
replace
({
query
:
{
appId
}
});
}
}
onSetHistoryTop=
{
async
(
e
)
=>
{
try
{
await
putChatHistory
(
e
);
const
historyItem
=
history
.
find
((
item
)
=>
item
.
chatId
===
e
.
chatId
);
if
(
!
historyItem
)
return
;
updateHistory
({
...
historyItem
,
top
:
e
.
top
});
}
catch
(
error
)
{}
onSetHistoryTop=
{
(
e
)
=>
{
updateHistory
(
e
);
}
}
onSetCustomTitle=
{
async
(
e
)
=>
{
try
{
putChatHistory
({
chatId
:
e
.
chatId
,
customTitle
:
e
.
title
});
const
historyItem
=
history
.
find
((
item
)
=>
item
.
chatId
===
e
.
chatId
);
if
(
!
historyItem
)
return
;
updateHistory
({
...
historyItem
,
customTitle
:
e
.
title
});
}
catch
(
error
)
{}
updateHistory
({
chatId
:
e
.
chatId
,
title
:
e
.
title
,
customTitle
:
e
.
title
});
}
}
/>
)
}
...
...
@@ -372,7 +348,7 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
feedbackType=
{
'user'
}
onUpdateVariable=
{
(
e
)
=>
{}
}
onStartChat=
{
startChat
}
onDelMessage=
{
delOneHistoryItem
}
onDelMessage=
{
(
e
)
=>
delOneHistoryItem
({
...
e
,
chatId
})
}
/>
</
Box
>
</
Flex
>
...
...
projects/app/src/pages/chat/share.tsx
View file @
e01c38ef
import
React
,
{
useCallback
,
useEffect
,
use
Memo
,
use
Ref
,
useState
}
from
'react'
;
import
React
,
{
useCallback
,
useEffect
,
useRef
,
useState
}
from
'react'
;
import
Head
from
'next/head'
;
import
{
useRouter
}
from
'next/router'
;
import
{
initShareChatInfo
}
from
'@/web/support/outLink/api'
;
import
{
Box
,
Flex
,
useDisclosure
,
Drawer
,
DrawerOverlay
,
DrawerContent
}
from
'@chakra-ui/react'
;
import
{
useToast
}
from
'@/web/common/hooks/useToast'
;
import
{
useSystemStore
}
from
'@/web/common/system/useSystemStore'
;
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
{
streamFetch
}
from
'@/web/common/api/fetch'
;
import
{
useShareChatStore
,
defaultHistory
}
from
'@/web/core/chat/storeShareChat'
;
import
{
useShareChatStore
}
from
'@/web/core/chat/storeShareChat'
;
import
SideBar
from
'@/components/SideBar'
;
import
{
gptMessage2ChatType
}
from
'@/utils/adapt'
;
import
{
getErrText
}
from
'@fastgpt/global/common/error/utils'
;
import
type
{
ChatSiteItemType
}
from
'@fastgpt/global/core/chat/type.d'
;
import
type
{
Chat
HistoryItemType
,
Chat
SiteItemType
}
from
'@fastgpt/global/core/chat/type.d'
;
import
{
customAlphabet
}
from
'nanoid'
;
const
nanoid
=
customAlphabet
(
'abcdefghijklmnopqrstuvwxyz1234567890'
,
12
);
...
...
@@ -21,6 +20,13 @@ import ChatHeader from './components/ChatHeader';
import
ChatHistorySlider
from
'./components/ChatHistorySlider'
;
import
{
serviceSideProps
}
from
'@/web/common/utils/i18n'
;
import
{
checkChatSupportSelectFileByChatModels
}
from
'@/web/core/chat/utils'
;
import
{
useTranslation
}
from
'next-i18next'
;
import
{
getInitOutLinkChatInfo
}
from
'@/web/core/chat/api'
;
import
{
POST
}
from
'@/web/common/api/request'
;
import
{
chatContentReplaceBlock
}
from
'@fastgpt/global/core/chat/utils'
;
import
{
useChatStore
}
from
'@/web/core/chat/storeChat'
;
import
{
ChatStatusEnum
}
from
'@fastgpt/global/core/chat/constants'
;
import
{
OutLinkErrEnum
}
from
'@fastgpt/global/common/error/code/outLink'
;
const
OutLink
=
({
shareId
,
...
...
@@ -33,6 +39,7 @@ const OutLink = ({
showHistory
:
'0'
|
'1'
;
authToken
?:
string
;
})
=>
{
const
{
t
}
=
useTranslation
();
const
router
=
useRouter
();
const
{
toast
}
=
useToast
();
const
{
isOpen
:
isOpenSlider
,
onClose
:
onCloseSlider
,
onOpen
:
onOpenSlider
}
=
useDisclosure
();
...
...
@@ -43,18 +50,23 @@ const OutLink = ({
const
ChatBoxRef
=
useRef
<
ComponentRef
>
(
null
);
const
{
shareChatData
,
setShareChatData
,
shareChatHistory
,
saveChatResponse
,
delShareChatHistoryItemById
,
delOneShareHistoryByChatId
,
delManyShareChatHistoryByShareId
localUId
,
shareChatHistory
,
// abandon
clearLocalHistory
// abandon
}
=
useShareChatStore
();
const
history
=
useMemo
(
()
=>
shareChatHistory
.
filter
((
item
)
=>
item
.
shareId
===
shareId
),
[
shareChatHistory
,
shareId
]
);
const
{
histories
,
loadHistories
,
pushHistory
,
updateHistory
,
delOneHistory
,
chatData
,
setChatData
,
delOneHistoryItem
,
clearHistories
}
=
useChatStore
();
const
appId
=
chatData
.
appId
;
const
outLinkUid
:
string
=
authToken
||
localUId
;
const
startChat
=
useCallback
(
async
({
messages
,
controller
,
generatingMessage
,
variables
}:
StartChatFnProps
)
=>
{
...
...
@@ -67,12 +79,55 @@ const OutLink = ({
variables
,
shareId
,
chatId
:
completionChatId
,
authToken
outLinkUid
},
onMessage
:
generatingMessage
,
abortSignal
:
controller
});
const
newTitle
=
chatContentReplaceBlock
(
prompts
[
0
].
content
).
slice
(
0
,
20
)
||
prompts
[
1
]?.
value
?.
slice
(
0
,
20
)
||
'新对话'
;
// new chat
if
(
completionChatId
!==
chatId
)
{
const
newHistory
:
ChatHistoryItemType
=
{
chatId
:
completionChatId
,
updateTime
:
new
Date
(),
title
:
newTitle
,
appId
,
top
:
false
};
pushHistory
(
newHistory
);
if
(
controller
.
signal
.
reason
!==
'leave'
)
{
forbidRefresh
.
current
=
true
;
router
.
replace
({
query
:
{
...
router
.
query
,
chatId
:
completionChatId
}
});
}
}
else
{
// update chat
const
currentChat
=
histories
.
find
((
item
)
=>
item
.
chatId
===
chatId
);
currentChat
&&
updateHistory
({
...
currentChat
,
updateTime
:
new
Date
(),
title
:
newTitle
});
}
// update chat window
setChatData
((
state
)
=>
({
...
state
,
title
:
newTitle
,
history
:
ChatBoxRef
.
current
?.
getChatHistories
()
||
state
.
history
}));
/* post message to report result */
const
result
:
ChatSiteItemType
[]
=
gptMessage2ChatType
(
prompts
).
map
((
item
)
=>
({
...
item
,
status
:
'finish'
...
...
@@ -80,24 +135,6 @@ const OutLink = ({
result
[
1
].
value
=
responseText
;
result
[
1
].
responseData
=
responseData
;
/* save chat */
saveChatResponse
({
chatId
:
completionChatId
,
prompts
:
result
,
variables
,
shareId
});
if
(
completionChatId
!==
chatId
&&
controller
.
signal
.
reason
!==
'leave'
)
{
forbidRefresh
.
current
=
true
;
router
.
replace
({
query
:
{
...
router
.
query
,
chatId
:
completionChatId
}
});
}
window
.
top
?.
postMessage
(
{
type
:
'shareChatFinish'
,
...
...
@@ -111,61 +148,80 @@ const OutLink = ({
return
{
responseText
,
responseData
,
isNewChat
:
forbidRefresh
.
current
};
},
[
authToken
,
chatId
,
router
,
saveChatResponse
,
shareId
]
[
chatId
,
shareId
,
outLinkUid
,
setChatData
,
appId
,
updateHistory
,
router
,
histories
]
);
const
load
App
Info
=
useCallback
(
async
(
shareId
:
string
,
chatId
:
string
,
authToken
?:
string
)
=>
{
const
load
Chat
Info
=
useCallback
(
async
(
shareId
:
string
,
chatId
:
string
)
=>
{
if
(
!
shareId
)
return
null
;
const
history
=
shareChatHistory
.
find
((
item
)
=>
item
.
chatId
===
chatId
)
||
defaultHistory
;
ChatBoxRef
.
current
?.
resetHistory
(
history
.
chats
);
ChatBoxRef
.
current
?.
resetVariables
(
history
.
variables
);
try
{
const
chatData
=
await
(
async
()
=>
{
if
(
shareChatData
.
app
.
name
===
''
)
{
return
initShareChatInfo
({
shareId
,
authToken
});
}
return
shareChatData
;
})
(
);
const
res
=
await
getInitOutLinkChatInfo
(
{
chatId
,
shareId
,
outLinkUid
:
authToken
||
localUId
});
const
history
=
res
.
history
.
map
((
item
)
=>
({
...
item
,
status
:
ChatStatusEnum
.
finish
}));
set
Share
ChatData
({
...
chatData
,
setChatData
({
...
res
,
history
});
ChatBoxRef
.
current
?.
resetHistory
(
history
);
ChatBoxRef
.
current
?.
resetVariables
(
res
.
variables
);
if
(
res
.
history
.
length
>
0
)
{
setTimeout
(()
=>
{
ChatBoxRef
.
current
?.
scrollToBottom
(
'auto'
);
},
500
);
}
}
catch
(
e
:
any
)
{
toast
({
status
:
'error'
,
title
:
getErrText
(
e
,
'获取应用失败'
)
title
:
getErrText
(
e
,
t
(
'core.shareChat.Init Error'
)
)
});
if
(
e
?.
code
===
501
)
{
delManyShareChatHistoryByShareId
(
shareId
);
if
(
chatId
)
{
router
.
replace
({
query
:
{
...
router
.
query
,
chatId
:
''
}
});
}
if
(
e
?.
statusText
===
OutLinkErrEnum
.
linkUnInvalid
)
{
router
.
replace
(
'/'
);
}
}
if
(
history
.
chats
.
length
>
0
)
{
setTimeout
(()
=>
{
ChatBoxRef
.
current
?.
scrollToBottom
(
'auto'
);
},
500
);
}
return
history
;
return
null
;
},
[
delManyShareChatHistoryByShareId
,
setShareChatData
,
shareChatData
,
shareChatHistory
,
toast
]
[
authToken
,
localUId
,
router
,
setChatData
,
t
,
toast
]
);
useQuery
([
'init'
,
shareId
,
chatId
,
authToken
],
()
=>
{
useQuery
([
'init'
,
shareId
,
chatId
],
()
=>
{
if
(
forbidRefresh
.
current
)
{
forbidRefresh
.
current
=
false
;
return
null
;
}
return
loadAppInfo
(
shareId
,
chatId
,
authToken
);
return
loadChatInfo
(
shareId
,
chatId
);
});
// load histories
useQuery
([
'loadHistories'
,
outLinkUid
,
shareId
],
()
=>
{
if
(
shareId
&&
outLinkUid
)
{
return
loadHistories
({
shareId
,
outLinkUid
});
}
return
null
;
});
// check is embed
useEffect
(()
=>
{
if
(
window
!==
top
)
{
window
.
top
?.
postMessage
({
type
:
'shareChatReady'
},
'*'
);
...
...
@@ -173,10 +229,32 @@ const OutLink = ({
setIdEmbed
(
window
!==
top
);
},
[]);
// todo:4.6.4 init: update local chat history, add outLinkUid
useEffect
(()
=>
{
const
activeHistory
=
shareChatHistory
.
filter
((
item
)
=>
!
item
.
delete
);
if
(
!
localUId
||
!
shareId
||
activeHistory
.
length
===
0
)
return
;
(
async
()
=>
{
try
{
await
POST
(
'/core/chat/initLocalShareHistoryV464'
,
{
shareId
,
outLinkUid
:
localUId
,
chatIds
:
shareChatHistory
.
map
((
item
)
=>
item
.
chatId
)
});
clearLocalHistory
();
// router.reload();
}
catch
(
error
)
{
toast
({
status
:
'warning'
,
title
:
getErrText
(
error
,
t
(
'core.shareChat.Init Error'
))
});
}
})();
},
[
clearLocalHistory
,
localUId
,
router
,
shareChatHistory
,
shareId
,
t
,
toast
]);
return
(
<
PageContainer
{
...
(
isEmbed
?
{
p
:
'0
!
important
',
borderRadius
:
'0'
}
:
{})}
>
<
Head
>
<
title
>
{
shareC
hatData
.
app
.
name
}
</
title
>
<
title
>
{
c
hatData
.
app
.
name
}
</
title
>
</
Head
>
<
Flex
h=
{
'100%'
}
flexDirection=
{
[
'column'
,
'row'
]
}
>
{
showHistory
===
'1'
...
...
@@ -199,12 +277,14 @@ const OutLink = ({
);
})(
<
ChatHistorySlider
appName=
{
shareC
hatData
.
app
.
name
}
appAvatar=
{
shareC
hatData
.
app
.
avatar
}
appName=
{
c
hatData
.
app
.
name
}
appAvatar=
{
c
hatData
.
app
.
avatar
}
activeChatId=
{
chatId
}
history=
{
histor
y
.
map
((
item
)
=>
({
history=
{
histor
ies
.
map
((
item
)
=>
({
id
:
item
.
chatId
,
title
:
item
.
title
title
:
item
.
title
,
customTitle
:
item
.
customTitle
,
top
:
item
.
top
}))
}
onClose=
{
onCloseSlider
}
onChangeChat=
{
(
chatId
)
=>
{
...
...
@@ -218,9 +298,9 @@ const OutLink = ({
onCloseSlider
();
}
}
}
onDelHistory=
{
delOneShareHistoryByChatId
}
onDelHistory=
{
({
chatId
})
=>
delOneHistory
({
chatId
,
shareId
,
outLinkUid
})
}
onClearHistory=
{
()
=>
{
delManyShareChatHistoryByShareId
(
shareId
);
clearHistories
({
shareId
,
outLinkUid
}
);
router
.
replace
({
query
:
{
...
router
.
query
,
...
...
@@ -228,6 +308,16 @@ const OutLink = ({
}
});
}
}
onSetHistoryTop=
{
(
e
)
=>
{
updateHistory
(
e
);
}
}
onSetCustomTitle=
{
async
(
e
)
=>
{
updateHistory
({
chatId
:
e
.
chatId
,
title
:
e
.
title
,
customTitle
:
e
.
title
});
}
}
/>
)
:
null
}
...
...
@@ -242,36 +332,24 @@ const OutLink = ({
>
{
/* header */
}
<
ChatHeader
appAvatar=
{
shareC
hatData
.
app
.
avatar
}
appName=
{
shareC
hatData
.
app
.
name
}
history=
{
shareChatData
.
history
.
chats
}
appAvatar=
{
c
hatData
.
app
.
avatar
}
appName=
{
c
hatData
.
app
.
name
}
history=
{
chatData
.
history
}
onOpenSlider=
{
onOpenSlider
}
/>
{
/* chat box */
}
<
Box
flex=
{
1
}
>
<
ChatBox
active=
{
!!
shareC
hatData
.
app
.
name
}
active=
{
!!
c
hatData
.
app
.
name
}
ref=
{
ChatBoxRef
}
appAvatar=
{
shareChatData
.
app
.
avatar
}
userAvatar=
{
shareChatData
.
userAvatar
}
userGuideModule=
{
shareChatData
.
app
?.
userGuideModule
}
showFileSelector=
{
checkChatSupportSelectFileByChatModels
(
shareChatData
.
app
.
chatModels
)
}
appAvatar=
{
chatData
.
app
.
avatar
}
userAvatar=
{
chatData
.
userAvatar
}
userGuideModule=
{
chatData
.
app
?.
userGuideModule
}
showFileSelector=
{
checkChatSupportSelectFileByChatModels
(
chatData
.
app
.
chatModels
)
}
feedbackType=
{
'user'
}
onUpdateVariable=
{
(
e
)
=>
{
setShareChatData
((
state
)
=>
({
...
state
,
history
:
{
...
state
.
history
,
variables
:
e
}
}));
}
}
onUpdateVariable=
{
(
e
)
=>
{}
}
onStartChat=
{
startChat
}
onDelMessage=
{
({
contentId
,
index
})
=>
delShareChatHistoryItemById
({
chatId
,
contentId
,
index
})
}
onDelMessage=
{
(
e
)
=>
delOneHistoryItem
({
...
e
,
chatId
})
}
/>
</
Box
>
</
Flex
>
...
...
projects/app/src/service/core/dataset/data/pg.ts
View file @
e01c38ef
...
...
@@ -189,15 +189,6 @@ export async function searchDatasetData(props: SearchProps) {
})
).
filter
((
item
)
=>
item
.
score
>
similarity
);
// (It's possible that rerank failed) concat rerank results and search results
set
=
new
Set
<
string
>
(
reRankResults
.
map
((
item
)
=>
item
.
id
));
embeddingRecallResults
.
forEach
((
item
)
=>
{
if
(
!
set
.
has
(
item
.
id
)
&&
item
.
score
>=
similarity
)
{
reRankResults
.
push
(
item
);
set
.
add
(
item
.
id
);
}
});
return
{
searchRes
:
reRankResults
.
slice
(
0
,
limit
),
tokenLen
...
...
@@ -382,7 +373,7 @@ export async function reRankSearchResult({
}
catch
(
error
)
{
console
.
log
(
error
);
return
[]
;
return
data
;
}
}
// ------------------ search end ------------------
projects/app/src/service/moduleDispatch/index.ts
View file @
e01c38ef
...
...
@@ -3,7 +3,7 @@ import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
import
{
ModuleOutputKeyEnum
}
from
'@fastgpt/global/core/module/constants'
;
import
{
RunningModuleItemType
}
from
'@/types/app'
;
import
{
ModuleDispatchProps
}
from
'@/types/core/chat/type'
;
import
{
ChatHistoryItemResType
}
from
'@fastgpt/global/core/chat/api
'
;
import
type
{
ChatHistoryItemResType
}
from
'@fastgpt/global/core/chat/type.d
'
;
import
{
FlowNodeTypeEnum
}
from
'@fastgpt/global/core/module/node/constant'
;
import
{
ModuleItemType
}
from
'@fastgpt/global/core/module/type'
;
import
{
UserType
}
from
'@fastgpt/global/support/user/type'
;
...
...
projects/app/src/service/moduleDispatch/plugin/run.ts
View file @
e01c38ef
...
...
@@ -48,7 +48,7 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
answerText
,
responseData
:
{
moduleLogo
:
plugin
.
avatar
,
price
:
responseData
.
reduce
((
sum
,
item
)
=>
sum
+
item
.
price
,
0
),
price
:
responseData
.
reduce
((
sum
,
item
)
=>
sum
+
(
item
.
price
||
0
)
,
0
),
runningTime
:
responseData
.
reduce
((
sum
,
item
)
=>
sum
+
(
item
.
runningTime
||
0
),
0
),
pluginOutput
:
output
?.
pluginOutput
},
...
...
projects/app/src/service/support/outLink/auth.ts
deleted
100644 → 0
View file @
71afe711
import
{
POST
}
from
'@fastgpt/service/common/api/plusRequest'
;
import
type
{
AuthLinkLimitProps
,
AuthShareChatInitProps
}
from
'@fastgpt/global/support/outLink/api.d'
;
export
function
authOutLinkLimit
(
data
:
AuthLinkLimitProps
)
{
return
POST
(
'/support/outLink/authLimit'
,
data
);
}
export
function
authShareChatInit
(
data
:
AuthShareChatInitProps
)
{
if
(
!
global
.
feConfigs
?.
isPlus
)
return
;
return
POST
(
'/support/outLink/authShareChatInit'
,
data
);
}
projects/app/src/service/support/permission/auth/chat.ts
0 → 100644
View file @
e01c38ef
import
{
ChatSchema
}
from
'@fastgpt/global/core/chat/type'
;
import
{
MongoChat
}
from
'@fastgpt/service/core/chat/chatSchema'
;
import
{
AuthModeType
}
from
'@fastgpt/service/support/permission/type'
;
import
{
authOutLink
}
from
'./outLink'
;
import
{
ChatErrEnum
}
from
'@fastgpt/global/common/error/code/chat'
;
import
{
authUserRole
}
from
'@fastgpt/service/support/permission/auth/user'
;
import
{
TeamMemberRoleEnum
}
from
'@fastgpt/global/support/user/team/constant'
;
/*
outLink: Must be the owner
token: team owner and chat owner have all permissions
*/
export
async
function
autChatCrud
({
chatId
,
shareId
,
outLinkUid
,
per
=
'owner'
,
...
props
}:
AuthModeType
&
{
chatId
?:
string
;
shareId
?:
string
;
outLinkUid
?:
string
;
}):
Promise
<
{
chat
?:
ChatSchema
;
isOutLink
:
boolean
;
uid
?:
string
;
}
>
{
const
isOutLink
=
Boolean
(
shareId
&&
outLinkUid
);
if
(
!
chatId
)
return
{
isOutLink
,
uid
:
outLinkUid
};
const
chat
=
await
MongoChat
.
findOne
({
chatId
}).
lean
();
if
(
!
chat
)
return
{
isOutLink
,
uid
:
outLinkUid
};
const
{
uid
}
=
await
(
async
()
=>
{
// outLink Auth
if
(
shareId
&&
outLinkUid
)
{
const
{
uid
}
=
await
authOutLink
({
shareId
,
outLinkUid
});
// auth outLinkUid
if
(
chat
.
shareId
===
shareId
&&
chat
.
outLinkUid
===
uid
)
{
return
{
uid
};
}
return
Promise
.
reject
(
ChatErrEnum
.
unAuthChat
);
}
// req auth
const
{
tmbId
,
role
}
=
await
authUserRole
(
props
);
if
(
role
===
TeamMemberRoleEnum
.
owner
)
return
{
uid
:
outLinkUid
};
if
(
String
(
tmbId
)
===
String
(
chat
.
tmbId
))
return
{
uid
:
outLinkUid
};
return
Promise
.
reject
(
ChatErrEnum
.
unAuthChat
);
})();
return
{
chat
,
isOutLink
,
uid
};
}
projects/app/src/service/support/permission/auth/outLink.ts
View file @
e01c38ef
import
{
authOutLinkLimit
}
from
'@/service/support/outLink/auth'
;
import
{
AuthLinkChatProps
}
from
'@fastgpt/global/support/outLink/api.d'
;
import
{
AuthUserTypeEnum
}
from
'@fastgpt/global/support/permission/constant'
;
import
{
getUserAndAuthBalance
}
from
'./user'
;
import
{
POST
}
from
'@fastgpt/service/common/api/plusRequest'
;
import
type
{
AuthOutLinkChatProps
,
AuthOutLinkLimitProps
,
AuthOutLinkInitProps
,
AuthOutLinkResponse
}
from
'@fastgpt/global/support/outLink/api.d'
;
import
{
authOutLinkValid
}
from
'@fastgpt/service/support/permission/auth/outLink'
;
import
{
getUserAndAuthBalance
}
from
'@fastgpt/service/support/user/controller'
;
import
{
AuthUserTypeEnum
}
from
'@fastgpt/global/support/permission/constant'
;
import
{
OutLinkErrEnum
}
from
'@fastgpt/global/common/error/code/outLink'
;
import
{
OutLinkSchema
}
from
'@fastgpt/global/support/outLink/type'
;
export
function
authOutLinkInit
(
data
:
AuthOutLinkInitProps
):
Promise
<
AuthOutLinkResponse
>
{
if
(
!
global
.
feConfigs
?.
isPlus
)
return
Promise
.
resolve
({
uid
:
data
.
outLinkUid
});
return
POST
<
AuthOutLinkResponse
>
(
'/support/outLink/authInit'
,
data
);
}
export
function
authOutLinkChatLimit
(
data
:
AuthOutLinkLimitProps
):
Promise
<
AuthOutLinkResponse
>
{
if
(
!
global
.
feConfigs
?.
isPlus
)
return
Promise
.
resolve
({
uid
:
data
.
outLinkUid
});
return
POST
<
AuthOutLinkResponse
>
(
'/support/outLink/authChatStart'
,
data
);
}
export
const
authOutLink
=
async
({
shareId
,
outLinkUid
}:
{
shareId
?:
string
;
outLinkUid
?:
string
;
}):
Promise
<
{
uid
:
string
;
appId
:
string
;
shareChat
:
OutLinkSchema
;
}
>
=>
{
if
(
!
outLinkUid
)
{
return
Promise
.
reject
(
OutLinkErrEnum
.
linkUnInvalid
);
}
const
result
=
await
authOutLinkValid
({
shareId
});
const
{
uid
}
=
await
authOutLinkInit
({
outLinkUid
,
tokenUrl
:
result
.
shareChat
.
limit
?.
hookUrl
});
return
{
...
result
,
uid
};
};
export
async
function
authOutLinkChat
({
export
async
function
authOutLinkChat
Start
({
shareId
,
ip
,
authToken
,
outLinkUid
,
question
}:
AuthLinkChatProps
&
{
}:
Auth
Out
LinkChatProps
&
{
shareId
:
string
;
})
{
// get outLink
const
{
shareChat
,
app
}
=
await
authOutLinkValid
({
shareId
});
// get outLink
and app
const
{
shareChat
,
app
Id
}
=
await
authOutLinkValid
({
shareId
});
const
[
user
]
=
await
Promise
.
all
([
// check balance and chat limit
const
[
user
,
{
uid
}]
=
await
Promise
.
all
([
getUserAndAuthBalance
({
tmbId
:
shareChat
.
tmbId
,
minBalance
:
0
}),
global
.
feConfigs
?.
isPlus
?
authOutLinkLimit
({
outLink
:
shareChat
,
ip
,
authToken
,
question
})
:
undefined
authOutLinkChatLimit
({
outLink
:
shareChat
,
ip
,
outLinkUid
,
question
})
]);
return
{
authType
:
AuthUserTypeEnum
.
token
,
responseDetail
:
shareChat
.
responseDetail
,
user
,
app
appId
,
uid
};
}
projects/app/src/service/support/permission/auth/user.ts
deleted
100644 → 0
View file @
71afe711
import
{
AuthResponseType
}
from
'@fastgpt/global/support/permission/type'
;
import
{
parseHeaderCert
}
from
'@fastgpt/service/support/permission/controller'
;
import
{
AuthModeType
}
from
'@fastgpt/service/support/permission/type'
;
import
{
UserErrEnum
}
from
'@fastgpt/global/common/error/code/user'
;
import
{
UserType
}
from
'@fastgpt/global/support/user/type'
;
import
{
getUserDetail
}
from
'@/service/support/user/controller'
;
export
async
function
getUserAndAuthBalance
({
tmbId
,
minBalance
}:
{
tmbId
:
string
;
minBalance
?:
number
;
})
{
const
user
=
await
getUserDetail
({
tmbId
});
if
(
!
user
)
{
return
Promise
.
reject
(
UserErrEnum
.
unAuthUser
);
}
if
(
minBalance
!==
undefined
&&
global
.
feConfigs
.
isPlus
&&
user
.
team
.
balance
<
minBalance
)
{
return
Promise
.
reject
(
UserErrEnum
.
balanceNotEnough
);
}
return
user
;
}
/* get user */
export
async
function
authUser
({
minBalance
,
...
props
}:
AuthModeType
&
{
minBalance
?:
number
;
}):
Promise
<
AuthResponseType
&
{
user
:
UserType
;
}
>
{
const
result
=
await
parseHeaderCert
(
props
);
return
{
...
result
,
user
:
await
getUserAndAuthBalance
({
tmbId
:
result
.
tmbId
,
minBalance
}),
isOwner
:
true
,
canWrite
:
true
};
}
projects/app/src/service/support/user/controller.ts
deleted
100644 → 0
View file @
71afe711
import
{
ERROR_ENUM
}
from
'@fastgpt/global/common/error/errorCode'
;
import
{
MongoUser
}
from
'@fastgpt/service/support/user/schema'
;
import
{
UserType
}
from
'@fastgpt/global/support/user/type'
;
import
{
getTeamInfoByTmbId
,
getUserDefaultTeam
}
from
'@fastgpt/service/support/user/team/controller'
;
export
async
function
getUserDetail
({
tmbId
,
userId
}:
{
tmbId
?:
string
;
userId
?:
string
;
}):
Promise
<
UserType
>
{
const
team
=
await
(
async
()
=>
{
if
(
tmbId
)
{
return
getTeamInfoByTmbId
({
tmbId
});
}
if
(
userId
)
{
return
getUserDefaultTeam
({
userId
});
}
return
Promise
.
reject
(
ERROR_ENUM
.
unAuthorization
);
})();
const
user
=
await
MongoUser
.
findById
(
team
.
userId
);
if
(
!
user
)
{
return
Promise
.
reject
(
ERROR_ENUM
.
unAuthorization
);
}
return
{
_id
:
user
.
_id
,
username
:
user
.
username
,
avatar
:
user
.
avatar
,
balance
:
user
.
balance
,
timezone
:
user
.
timezone
,
promotionRate
:
user
.
promotionRate
,
openaiAccount
:
user
.
openaiAccount
,
team
};
}
projects/app/src/service/support/wallet/bill/push.ts
View file @
e01c38ef
import
{
BillSourceEnum
,
PRICE_SCALE
}
from
'@fastgpt/global/support/wallet/bill/constants'
;
import
{
getAudioSpeechModel
,
getQAModel
}
from
'@/service/core/ai/model'
;
import
type
{
ChatHistoryItemResType
}
from
'@fastgpt/global/core/chat/
api
.d'
;
import
type
{
ChatHistoryItemResType
}
from
'@fastgpt/global/core/chat/
type
.d'
;
import
{
formatPrice
}
from
'@fastgpt/global/support/wallet/bill/tools'
;
import
{
addLog
}
from
'@fastgpt/service/common/mongo/controller'
;
import
type
{
ConcatBillProps
,
CreateBillProps
}
from
'@fastgpt/global/support/wallet/bill/api.d'
;
...
...
@@ -41,7 +41,7 @@ export const pushChatBill = ({
source
:
`
${
BillSourceEnum
}
`
;
response
:
ChatHistoryItemResType
[];
})
=>
{
const
total
=
response
.
reduce
((
sum
,
item
)
=>
sum
+
item
.
price
,
0
);
const
total
=
response
.
reduce
((
sum
,
item
)
=>
sum
+
(
item
.
price
||
0
)
,
0
);
createBill
({
teamId
,
...
...
projects/app/src/service/utils/chat/saveChat.ts
View file @
e01c38ef
...
...
@@ -15,6 +15,7 @@ type Props = {
updateUseTime
:
boolean
;
source
:
`
${
ChatSourceEnum
}
`
;
shareId
?:
string
;
outLinkUid
?:
string
;
content
:
[
ChatItemType
,
ChatItemType
];
};
...
...
@@ -27,10 +28,11 @@ export async function saveChat({
updateUseTime
,
source
,
shareId
,
outLinkUid
,
content
}:
Props
)
{
try
{
const
chat
History
=
await
MongoChat
.
findOne
(
const
chat
=
await
MongoChat
.
findOne
(
{
chatId
,
teamId
,
...
...
@@ -57,7 +59,7 @@ export async function saveChat({
content
[
1
]?.
value
?.
slice
(
0
,
20
)
||
'Chat'
;
if
(
chat
History
)
{
if
(
chat
)
{
promise
.
push
(
MongoChat
.
updateOne
(
{
chatId
},
...
...
@@ -77,7 +79,8 @@ export async function saveChat({
variables
,
title
,
source
,
shareId
shareId
,
outLinkUid
})
);
}
...
...
projects/app/src/utils/service/core/chat/index.ts
View file @
e01c38ef
import
type
{
ChatHistoryItemResType
}
from
'@fastgpt/global/core/chat/
api
.d'
;
import
type
{
ChatHistoryItemResType
}
from
'@fastgpt/global/core/chat/
type
.d'
;
export
function
selectShareResponse
({
responseData
}:
{
responseData
:
ChatHistoryItemResType
[]
})
{
export
function
selectShareResponse
({
responseData
=
[]
}:
{
responseData
?:
ChatHistoryItemResType
[];
})
{
const
filedList
=
[
'moduleType'
,
'moduleName'
,
'moduleLogo'
,
'runningTime'
,
'historyPreview'
,
'quoteList'
,
'question'
];
...
...
@@ -17,6 +22,6 @@ export function selectShareResponse({ responseData }: { responseData: ChatHistor
obj
[
key
]
=
item
[
key
];
}
}
return
obj
;
return
obj
as
ChatHistoryItemResType
;
});
}
projects/app/src/web/common/api/fetch.ts
View file @
e01c38ef
import
{
sseResponseEventEnum
}
from
'@fastgpt/service/common/response/constant'
;
import
{
getErrText
}
from
'@fastgpt/global/common/error/utils'
;
import
{
parseStreamChunk
,
SSEParseData
}
from
'@/utils/sse'
;
import
type
{
ChatHistoryItemResType
}
from
'@fastgpt/global/core/chat/
api
.d'
;
import
type
{
ChatHistoryItemResType
}
from
'@fastgpt/global/core/chat/
type
.d'
;
import
{
StartChatFnProps
}
from
'@/components/ChatBox'
;
import
{
getToken
}
from
'@/web/support/user/auth'
;
import
{
ModuleOutputKeyEnum
}
from
'@fastgpt/global/core/module/constants'
;
...
...
projects/app/src/web/core/app/templates.ts
View file @
e01c38ef
...
...
@@ -346,7 +346,7 @@ export const appTemplates: (AppItemType & {
{
key
:
'similarity'
,
type
:
'slider'
,
label
:
'相
似
度'
,
label
:
'相
关
度'
,
value
:
0.4
,
min
:
0
,
max
:
1
,
...
...
@@ -1398,7 +1398,7 @@ export const appTemplates: (AppItemType & {
{
key
:
'similarity'
,
type
:
'slider'
,
label
:
'相
似
度'
,
label
:
'相
关
度'
,
value
:
0.76
,
min
:
0
,
max
:
1
,
...
...
projects/app/src/web/core/chat/api.ts
View file @
e01c38ef
import
{
GET
,
POST
,
DELETE
,
PUT
}
from
'@/web/common/api/request'
;
import
type
{
ChatHistoryItemType
}
from
'@fastgpt/global/core/chat/type.d'
;
import
type
{
InitChatResponse
}
from
'@fastgpt/global/core/chat/api.d'
;
import
type
{
RequestPaging
}
from
'@/types'
;
import
{
UpdateHistoryProps
}
from
'@fastgpt/global/core/chat/api.d'
;
import
type
{
AdminUpdateFeedbackParams
}
from
'@fastgpt/global/core/chat/api.d'
;
import
{
GetChatSpeechProps
}
from
'@/global/core/chat/api.d'
;
import
type
{
InitChatProps
,
InitChatResponse
,
InitOutLinkChatProps
,
getHistoriesProps
}
from
'@/global/core/chat/api.d'
;
import
type
{
AdminUpdateFeedbackParams
,
ClearHistoriesProps
,
DelHistoryProps
,
DeleteChatItemProps
,
UpdateHistoryProps
}
from
'@/global/core/chat/api.d'
;
/**
* 获取初始化聊天内容
*/
export
const
getInitChat
SiteInfo
=
(
data
:
{
appId
:
string
;
chatId
?:
string
}
)
=>
export
const
getInitChat
Info
=
(
data
:
InitChatProps
)
=>
GET
<
InitChatResponse
>
(
`/core/chat/init`
,
data
);
export
const
getInitOutLinkChatInfo
=
(
data
:
InitOutLinkChatProps
)
=>
GET
<
InitChatResponse
>
(
`/core/chat/outLink/init`
,
data
);
/**
*
获取历史记录
*
get current window history(appid or shareId)
*/
export
const
getChatHistor
y
=
(
data
:
RequestPaging
&
{
appId
:
string
}
)
=>
POST
<
ChatHistoryItemType
[]
>
(
'/core/chat/
list
'
,
data
);
export
const
getChatHistor
ies
=
(
data
:
getHistoriesProps
)
=>
POST
<
ChatHistoryItemType
[]
>
(
'/core/chat/
getHistories
'
,
data
);
/**
*
删除一条历史记录
*
delete one history
*/
export
const
delChatHistoryById
=
(
chatId
:
string
)
=>
DELETE
(
`/core/chat/delete`
,
{
chatId
}
);
export
const
delChatHistoryById
=
(
data
:
DelHistoryProps
)
=>
DELETE
(
`/core/chat/delHistory`
,
data
);
/**
* clear all history by appid
*/
export
const
clearChatHistoryByAppId
=
(
appId
:
string
)
=>
DELETE
(
`/core/chat/delete`
,
{
appId
});
export
const
clearChatHistoryByAppId
=
(
data
:
ClearHistoriesProps
)
=>
DELETE
(
`/core/chat/clearHistories`
,
data
);
/**
*
删除一句对话
*
delete one chat record
*/
export
const
delChatRecordById
=
(
data
:
{
chatId
:
string
;
contentId
:
string
}
)
=>
export
const
delChatRecordById
=
(
data
:
DeleteChatItemProps
)
=>
DELETE
(
`/core/chat/item/delete`
,
data
);
/**
* 修改历史记录: 标题/置顶
*/
export
const
putChatHistory
=
(
data
:
UpdateHistoryProps
)
=>
PUT
(
'/core/chat/update'
,
data
);
export
const
putChatHistory
=
(
data
:
UpdateHistoryProps
)
=>
PUT
(
'/core/chat/update
History
'
,
data
);
export
const
userUpdateChatFeedback
=
(
data
:
{
chatItemId
:
string
;
userFeedback
?:
string
})
=>
POST
(
'/core/chat/feedback/userUpdate'
,
data
);
...
...
projects/app/src/web/core/chat/storeChat.ts
View file @
e01c38ef
...
...
@@ -2,35 +2,36 @@ import { create } from 'zustand';
import
{
devtools
,
persist
}
from
'zustand/middleware'
;
import
{
immer
}
from
'zustand/middleware/immer'
;
import
type
{
ChatHistoryItemType
}
from
'@fastgpt/global/core/chat/type.d'
;
import
type
{
InitChatResponse
}
from
'@fastgpt/global/core/chat/api'
;
import
{
delChatHistoryById
,
getChatHistory
,
clearChatHistoryByAppId
}
from
'@/web/core/chat/api'
;
import
type
{
InitChatResponse
,
getHistoriesProps
,
ClearHistoriesProps
,
DelHistoryProps
,
UpdateHistoryProps
}
from
'@/global/core/chat/api'
;
import
{
delChatHistoryById
,
getChatHistories
,
clearChatHistoryByAppId
,
delChatRecordById
,
putChatHistory
}
from
'@/web/core/chat/api'
;
import
{
defaultChatData
}
from
'@/global/core/chat/constants'
;
type
State
=
{
history
:
ChatHistoryItemType
[];
loadHistory
:
(
data
:
{
appId
:
string
})
=>
Promise
<
null
>
;
delHistory
(
history
:
string
):
Promise
<
void
>
;
clearHistory
(
appId
:
string
):
Promise
<
void
>
;
updateHistory
:
(
history
:
ChatHistoryItemType
)
=>
void
;
histories
:
ChatHistoryItemType
[];
loadHistories
:
(
data
:
getHistoriesProps
)
=>
Promise
<
null
>
;
delOneHistory
(
data
:
DelHistoryProps
):
Promise
<
void
>
;
clearHistories
(
data
:
ClearHistoriesProps
):
Promise
<
void
>
;
pushHistory
:
(
history
:
ChatHistoryItemType
)
=>
void
;
updateHistory
:
(
e
:
UpdateHistoryProps
&
{
updateTime
?:
Date
;
title
?:
string
})
=>
Promise
<
any
>
;
chatData
:
InitChatResponse
;
setChatData
:
(
e
:
InitChatResponse
|
((
e
:
InitChatResponse
)
=>
InitChatResponse
))
=>
void
;
lastChatAppId
:
string
;
setLastChatAppId
:
(
id
:
string
)
=>
void
;
lastChatId
:
string
;
setLastChatId
:
(
id
:
string
)
=>
void
;
};
const
defaultChatData
:
InitChatResponse
=
{
chatId
:
''
,
appId
:
''
,
app
:
{
name
:
'Loading'
,
avatar
:
'/icon/logo.svg'
,
intro
:
''
,
canUse
:
false
},
title
:
'新对话'
,
variables
:
{},
history
:
[]
delOneHistoryItem
:
(
e
:
{
chatId
:
string
;
contentId
?:
string
;
index
:
number
})
=>
Promise
<
any
>
;
};
export
const
useChatStore
=
create
<
State
>
()(
...
...
@@ -49,49 +50,62 @@ export const useChatStore = create<State>()(
state
.
lastChatId
=
id
;
});
},
history
:
[],
async
loadHistory
({
appId
})
{
const
oneHistory
=
get
().
history
[
0
];
if
(
oneHistory
&&
oneHistory
.
appId
===
appId
)
return
null
;
const
data
=
await
getChatHistory
({
appId
,
pageNum
:
1
,
pageSize
:
20
});
histories
:
[],
async
loadHistories
(
e
)
{
const
data
=
await
getChatHistories
(
e
);
set
((
state
)
=>
{
state
.
histor
y
=
data
;
state
.
histor
ies
=
data
;
});
return
null
;
},
async
del
History
(
chatId
)
{
async
del
OneHistory
(
props
)
{
set
((
state
)
=>
{
state
.
histor
y
=
state
.
history
.
filter
((
item
)
=>
item
.
chatId
!==
chatId
);
state
.
histor
ies
=
state
.
histories
.
filter
((
item
)
=>
item
.
chatId
!==
props
.
chatId
);
});
await
delChatHistoryById
(
chatId
);
await
delChatHistoryById
(
props
);
},
async
clearHistor
y
(
appId
)
{
async
clearHistor
ies
(
data
)
{
set
((
state
)
=>
{
state
.
histor
y
=
[];
state
.
histor
ies
=
[];
});
await
clearChatHistoryByAppId
(
appId
);
await
clearChatHistoryByAppId
(
data
);
},
updateHistory
(
history
)
{
const
index
=
get
().
history
.
findIndex
((
item
)
=>
item
.
chatId
===
history
.
chatId
);
pushHistory
(
history
)
{
set
((
state
)
=>
{
const
newHistory
=
(()
=>
{
if
(
index
>
-
1
)
{
state
.
histories
=
[
history
,
...
state
.
histories
];
});
},
async
updateHistory
(
props
)
{
const
{
chatId
,
customTitle
,
top
,
title
,
updateTime
}
=
props
;
const
index
=
get
().
histories
.
findIndex
((
item
)
=>
item
.
chatId
===
chatId
);
if
(
index
>
-
1
)
{
const
newHistory
=
{
...
get
().
histories
[
index
],
...(
title
&&
{
title
}),
...(
updateTime
&&
{
updateTime
}),
...(
customTitle
!==
undefined
&&
{
customTitle
}),
...(
top
!==
undefined
&&
{
top
})
};
if
(
customTitle
!==
undefined
||
top
!==
undefined
)
{
try
{
putChatHistory
(
props
);
}
catch
(
error
)
{}
}
set
((
state
)
=>
{
const
newHistories
=
(()
=>
{
return
[
h
istory
,
...
get
().
histor
y
.
slice
(
0
,
index
),
...
get
().
histor
y
.
slice
(
index
+
1
)
newH
istory
,
...
get
().
histor
ies
.
slice
(
0
,
index
),
...
get
().
histor
ies
.
slice
(
index
+
1
)
];
}
else
{
return
[
history
,
...
state
.
history
];
}
})();
})();
state
.
history
=
newHistory
;
});
state
.
histories
=
newHistories
;
});
}
},
chatData
:
defaultChatData
,
setChatData
(
e
=
defaultChatData
)
{
...
...
@@ -104,6 +118,19 @@ export const useChatStore = create<State>()(
state
.
chatData
=
e
;
});
}
},
async
delOneHistoryItem
({
chatId
,
contentId
,
index
})
{
if
(
!
chatId
||
!
contentId
)
return
;
try
{
get
().
setChatData
((
state
)
=>
({
...
state
,
history
:
state
.
history
.
filter
((
_
,
i
)
=>
i
!==
index
)
}));
await
delChatRecordById
({
chatId
,
contentId
});
}
catch
(
err
)
{
console
.
log
(
err
);
}
}
})),
{
...
...
projects/app/src/web/core/chat/storeShareChat.ts
View file @
e01c38ef
import
{
create
}
from
'zustand'
;
import
{
devtools
,
persist
}
from
'zustand/middleware'
;
import
{
immer
}
from
'zustand/middleware/immer'
;
import
type
{
ShareChatHistoryItemType
,
ShareChatType
}
from
'@fastgpt/global/support/outLink/api.d'
;
import
type
{
ChatSiteItemType
}
from
'@fastgpt/global/core/chat/type.d'
;
import
{
HUMAN_ICON
}
from
'@fastgpt/global/core/chat/constants'
;
import
{
chatContentReplaceBlock
}
from
'@fastgpt/global/core/chat/utils'
;
import
type
{
ChatHistoryItemType
}
from
'@fastgpt/global/core/chat/type.d'
;
import
{
customAlphabet
}
from
'nanoid'
;
const
nanoid
=
customAlphabet
(
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWSYZ1234567890_'
,
24
);
type
State
=
{
shareChatData
:
ShareChatType
;
setShareChatData
:
(
e
:
ShareChatType
|
((
e
:
ShareChatType
)
=>
ShareChatType
))
=>
void
;
shareChatHistory
:
ShareChatHistoryItemType
[];
saveChatResponse
:
(
e
:
{
chatId
:
string
;
prompts
:
ChatSiteItemType
[];
variables
:
Record
<
string
,
any
>
;
shareId
:
string
;
})
=>
void
;
delOneShareHistoryByChatId
:
(
chatId
:
string
)
=>
void
;
delShareChatHistoryItemById
:
(
e
:
{
chatId
:
string
;
contentId
?:
string
;
index
:
number
})
=>
void
;
delManyShareChatHistoryByShareId
:
(
shareId
?:
string
)
=>
void
;
};
export
const
defaultHistory
:
ShareChatHistoryItemType
=
{
chatId
:
`
${
Date
.
now
()}
`
,
updateTime
:
new
Date
(),
title
:
'新对话'
,
shareId
:
''
,
chats
:
[]
};
const
defaultShareChatData
:
ShareChatType
=
{
userAvatar
:
HUMAN_ICON
,
app
:
{
name
:
''
,
avatar
:
'/icon/logo.svg'
,
intro
:
''
},
history
:
defaultHistory
localUId
:
string
;
shareChatHistory
:
(
ChatHistoryItemType
&
{
delete
?:
boolean
})[];
clearLocalHistory
:
(
shareId
?:
string
)
=>
void
;
};
export
const
useShareChatStore
=
create
<
State
>
()(
devtools
(
persist
(
immer
((
set
,
get
)
=>
({
shareChatData
:
defaultShareChatData
,
setShareChatData
(
e
)
{
const
val
=
(()
=>
{
if
(
typeof
e
===
'function'
)
{
return
e
(
get
().
shareChatData
);
}
else
{
return
e
;
}
})();
set
((
state
)
=>
{
state
.
shareChatData
=
val
;
// update history
state
.
shareChatHistory
=
state
.
shareChatHistory
.
map
((
item
)
=>
item
.
chatId
===
val
.
history
.
chatId
?
val
.
history
:
item
);
});
},
shareChatHistory
:
[],
saveChatResponse
({
chatId
,
prompts
,
variables
,
shareId
})
{
const
chatHistory
=
get
().
shareChatHistory
.
find
((
item
)
=>
item
.
chatId
===
chatId
);
const
newTitle
=
chatContentReplaceBlock
(
prompts
[
prompts
.
length
-
2
]?.
value
).
slice
(
0
,
20
)
||
prompts
[
prompts
.
length
-
1
]?.
value
?.
slice
(
0
,
20
)
||
'Chat'
;
const
historyList
=
(()
=>
{
if
(
chatHistory
)
{
return
get
().
shareChatHistory
.
map
((
item
)
=>
item
.
chatId
===
chatId
?
{
...
item
,
title
:
newTitle
,
updateTime
:
new
Date
(),
chats
:
chatHistory
.
chats
.
concat
(
prompts
).
slice
(
-
30
),
variables
}
:
item
);
}
return
get
().
shareChatHistory
.
concat
({
chatId
,
shareId
,
title
:
newTitle
,
updateTime
:
new
Date
(),
chats
:
prompts
,
variables
});
})();
// @ts-ignore
historyList
.
sort
((
a
,
b
)
=>
new
Date
(
b
.
updateTime
)
-
new
Date
(
a
.
updateTime
));
set
((
state
)
=>
{
state
.
shareChatHistory
=
historyList
.
slice
(
0
,
50
);
});
},
delOneShareHistoryByChatId
(
chatId
:
string
)
{
set
((
state
)
=>
{
state
.
shareChatHistory
=
state
.
shareChatHistory
.
filter
(
(
item
)
=>
item
.
chatId
!==
chatId
);
});
},
delShareChatHistoryItemById
({
chatId
,
contentId
})
{
set
((
state
)
=>
{
// update history store
const
newHistoryList
=
state
.
shareChatHistory
.
map
((
item
)
=>
item
.
chatId
===
chatId
?
{
...
item
,
chats
:
item
.
chats
.
filter
((
item
)
=>
item
.
dataId
!==
contentId
)
}
:
item
);
state
.
shareChatHistory
=
newHistoryList
;
});
},
delManyShareChatHistoryByShareId
(
shareId
?:
string
)
{
localUId
:
`shareChat-
${
Date
.
now
()}
-
${
nanoid
()}
`
,
shareChatHistory
:
[],
// old version field
clearLocalHistory
()
{
// abandon
set
((
state
)
=>
{
if
(
shareId
)
{
state
.
shareChatHistory
=
state
.
shareChatHistory
.
filter
(
(
item
)
=>
item
.
shareId
!==
shareId
);
}
else
{
state
.
shareChatHistory
=
[];
}
state
.
shareChatHistory
=
state
.
shareChatHistory
.
map
((
item
)
=>
({
...
item
,
delete
:
true
}));
});
}
})),
{
name
:
'shareChatStore'
,
partialize
:
(
state
)
=>
({
localUId
:
state
.
localUId
,
shareChatHistory
:
state
.
shareChatHistory
})
}
...
...
projects/app/src/web/core/dataset/store/dataset.ts
View file @
e01c38ef
...
...
@@ -79,8 +79,7 @@ export const useDatasetStore = create<State>()(
item
.
_id
===
data
.
id
?
{
...
item
,
...
data
,
tags
:
data
.
tags
||
[]
...
data
}
:
item
);
...
...
projects/app/src/web/support/outLink/api.ts
View file @
e01c38ef
import
{
GET
,
POST
,
DELETE
}
from
'@/web/common/api/request'
;
import
type
{
InitShareChatResponse
}
from
'@fastgpt/global/support/outLink/api.d'
;
import
type
{
OutLinkEditType
,
OutLinkSchema
}
from
'@fastgpt/global/support/outLink/type.d'
;
/**
* 初始化分享聊天
*/
export
const
initShareChatInfo
=
(
data
:
{
shareId
:
string
;
authToken
?:
string
})
=>
GET
<
InitShareChatResponse
>
(
`/support/outLink/init`
,
data
);
/**
* create a shareChat
*/
export
const
createShareChat
=
(
...
...
projects/app/src/web/support/wallet/pay/api.ts
View file @
e01c38ef
import
{
GET
}
from
'@/web/common/api/request'
;
import
type
{
PaySchema
}
from
'@fastgpt/global/support/wallet/pay/type.d'
;
import
{
delay
}
from
'@fastgpt/global/common/system/utils'
;
export
const
getPayOrders
=
()
=>
GET
<
PaySchema
[]
>
(
`/plusApi/support/wallet/pay/getPayOrders`
);
export
const
getPayCode
=
(
amount
:
number
)
=>
...
...
@@ -11,15 +9,9 @@ export const getPayCode = (amount: number) =>
}
>
(
`/plusApi/support/wallet/pay/getPayCode`
,
{
amount
});
export
const
checkPayResult
=
(
payId
:
string
)
=>
GET
<
number
>
(
`/plusApi/support/wallet/pay/checkPayResult`
,
{
payId
}).
then
(()
=>
{
async
function
startQueue
()
{
try
{
await
GET
(
'/common/system/unlockTask'
);
}
catch
(
error
)
{
await
delay
(
1000
);
startQueue
();
}
}
startQueue
();
return
'success'
;
GET
<
string
>
(
`/plusApi/support/wallet/pay/checkPayResult`
,
{
payId
}).
then
((
data
)
=>
{
try
{
GET
(
'/common/system/unlockTask'
);
}
catch
(
error
)
{}
return
data
;
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment