mirror of https://github.com/chaitin/PandaWiki.git
Compare commits
19 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
fe2d70bfa9 | |
|
|
c9f3a61e86 | |
|
|
7b75f1bf55 | |
|
|
07646f0823 | |
|
|
63a8d8a743 | |
|
|
587c2842be | |
|
|
fd34bb4c55 | |
|
|
46afba778f | |
|
|
79234c2394 | |
|
|
67e796dbb7 | |
|
|
55c563cc48 | |
|
|
cfdc546d20 | |
|
|
7f58308dae | |
|
|
f34864621a | |
|
|
da9039ff37 | |
|
|
797e0c033d | |
|
|
ea6f958d24 | |
|
|
d3502e105a | |
|
|
df4937aeb2 |
|
|
@ -24,6 +24,7 @@ const (
|
|||
SourceTypeDiscordBot SourceType = "discord_bot"
|
||||
SourceTypeWechatOfficialAccount SourceType = "wechat_official_account"
|
||||
SourceTypeOpenAIAPI SourceType = "openai_api"
|
||||
SourceTypeMcpServer SourceType = "mcp_server"
|
||||
)
|
||||
|
||||
func (s SourceType) Name() string {
|
||||
|
|
@ -46,6 +47,8 @@ func (s SourceType) Name() string {
|
|||
return "Discord 机器人"
|
||||
case SourceTypeWechatOfficialAccount:
|
||||
return "微信公众号"
|
||||
case SourceTypeMcpServer:
|
||||
return "MCP 服务器"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -240,7 +240,8 @@ const docTemplate = `{
|
|||
"wechat_service_bot",
|
||||
"discord_bot",
|
||||
"wechat_official_account",
|
||||
"openai_api"
|
||||
"openai_api",
|
||||
"mcp_server"
|
||||
],
|
||||
"type": "string",
|
||||
"x-enum-varnames": [
|
||||
|
|
@ -260,7 +261,8 @@ const docTemplate = `{
|
|||
"SourceTypeWechatServiceBot",
|
||||
"SourceTypeDiscordBot",
|
||||
"SourceTypeWechatOfficialAccount",
|
||||
"SourceTypeOpenAIAPI"
|
||||
"SourceTypeOpenAIAPI",
|
||||
"SourceTypeMcpServer"
|
||||
],
|
||||
"name": "source_type",
|
||||
"in": "query",
|
||||
|
|
@ -4268,7 +4270,8 @@ const docTemplate = `{
|
|||
"wechat_service_bot",
|
||||
"discord_bot",
|
||||
"wechat_official_account",
|
||||
"openai_api"
|
||||
"openai_api",
|
||||
"mcp_server"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"SourceTypeDingTalk",
|
||||
|
|
@ -4287,7 +4290,8 @@ const docTemplate = `{
|
|||
"SourceTypeWechatServiceBot",
|
||||
"SourceTypeDiscordBot",
|
||||
"SourceTypeWechatOfficialAccount",
|
||||
"SourceTypeOpenAIAPI"
|
||||
"SourceTypeOpenAIAPI",
|
||||
"SourceTypeMcpServer"
|
||||
]
|
||||
},
|
||||
"consts.StatDay": {
|
||||
|
|
@ -4512,9 +4516,6 @@ const docTemplate = `{
|
|||
}
|
||||
]
|
||||
},
|
||||
"auto_sitemap": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"body_code": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
@ -4623,6 +4624,14 @@ const docTemplate = `{
|
|||
}
|
||||
]
|
||||
},
|
||||
"mcp_server_settings": {
|
||||
"description": "MCP Server Settings",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/domain.MCPServerSettings"
|
||||
}
|
||||
]
|
||||
},
|
||||
"openai_api_bot_settings": {
|
||||
"description": "OpenAI API Bot settings",
|
||||
"allOf": [
|
||||
|
|
@ -4794,9 +4803,6 @@ const docTemplate = `{
|
|||
}
|
||||
]
|
||||
},
|
||||
"auto_sitemap": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"body_code": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
@ -4896,6 +4902,14 @@ const docTemplate = `{
|
|||
}
|
||||
]
|
||||
},
|
||||
"mcp_server_settings": {
|
||||
"description": "MCP Server Settings",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/domain.MCPServerSettings"
|
||||
}
|
||||
]
|
||||
},
|
||||
"openai_api_bot_settings": {
|
||||
"description": "OpenAI API settings",
|
||||
"allOf": [
|
||||
|
|
@ -5056,7 +5070,8 @@ const docTemplate = `{
|
|||
8,
|
||||
9,
|
||||
10,
|
||||
11
|
||||
11,
|
||||
12
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"AppTypeWeb",
|
||||
|
|
@ -5069,7 +5084,8 @@ const docTemplate = `{
|
|||
"AppTypeWechatOfficialAccount",
|
||||
"AppTypeOpenAIAPI",
|
||||
"AppTypeWecomAIBot",
|
||||
"AppTypeLarkBot"
|
||||
"AppTypeLarkBot",
|
||||
"AppTypeMcpServer"
|
||||
]
|
||||
},
|
||||
"domain.AuthUserInfo": {
|
||||
|
|
@ -6378,6 +6394,31 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"domain.MCPServerSettings": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"docs_tool_settings": {
|
||||
"$ref": "#/definitions/domain.MCPToolSettings"
|
||||
},
|
||||
"is_enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sample_auth": {
|
||||
"$ref": "#/definitions/domain.SimpleAuth"
|
||||
}
|
||||
}
|
||||
},
|
||||
"domain.MCPToolSettings": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"desc": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"domain.MessageContent": {
|
||||
"type": "object"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -233,7 +233,8 @@
|
|||
"wechat_service_bot",
|
||||
"discord_bot",
|
||||
"wechat_official_account",
|
||||
"openai_api"
|
||||
"openai_api",
|
||||
"mcp_server"
|
||||
],
|
||||
"type": "string",
|
||||
"x-enum-varnames": [
|
||||
|
|
@ -253,7 +254,8 @@
|
|||
"SourceTypeWechatServiceBot",
|
||||
"SourceTypeDiscordBot",
|
||||
"SourceTypeWechatOfficialAccount",
|
||||
"SourceTypeOpenAIAPI"
|
||||
"SourceTypeOpenAIAPI",
|
||||
"SourceTypeMcpServer"
|
||||
],
|
||||
"name": "source_type",
|
||||
"in": "query",
|
||||
|
|
@ -4261,7 +4263,8 @@
|
|||
"wechat_service_bot",
|
||||
"discord_bot",
|
||||
"wechat_official_account",
|
||||
"openai_api"
|
||||
"openai_api",
|
||||
"mcp_server"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"SourceTypeDingTalk",
|
||||
|
|
@ -4280,7 +4283,8 @@
|
|||
"SourceTypeWechatServiceBot",
|
||||
"SourceTypeDiscordBot",
|
||||
"SourceTypeWechatOfficialAccount",
|
||||
"SourceTypeOpenAIAPI"
|
||||
"SourceTypeOpenAIAPI",
|
||||
"SourceTypeMcpServer"
|
||||
]
|
||||
},
|
||||
"consts.StatDay": {
|
||||
|
|
@ -4505,9 +4509,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"auto_sitemap": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"body_code": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
@ -4616,6 +4617,14 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"mcp_server_settings": {
|
||||
"description": "MCP Server Settings",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/domain.MCPServerSettings"
|
||||
}
|
||||
]
|
||||
},
|
||||
"openai_api_bot_settings": {
|
||||
"description": "OpenAI API Bot settings",
|
||||
"allOf": [
|
||||
|
|
@ -4787,9 +4796,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"auto_sitemap": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"body_code": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
@ -4889,6 +4895,14 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"mcp_server_settings": {
|
||||
"description": "MCP Server Settings",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/domain.MCPServerSettings"
|
||||
}
|
||||
]
|
||||
},
|
||||
"openai_api_bot_settings": {
|
||||
"description": "OpenAI API settings",
|
||||
"allOf": [
|
||||
|
|
@ -5049,7 +5063,8 @@
|
|||
8,
|
||||
9,
|
||||
10,
|
||||
11
|
||||
11,
|
||||
12
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"AppTypeWeb",
|
||||
|
|
@ -5062,7 +5077,8 @@
|
|||
"AppTypeWechatOfficialAccount",
|
||||
"AppTypeOpenAIAPI",
|
||||
"AppTypeWecomAIBot",
|
||||
"AppTypeLarkBot"
|
||||
"AppTypeLarkBot",
|
||||
"AppTypeMcpServer"
|
||||
]
|
||||
},
|
||||
"domain.AuthUserInfo": {
|
||||
|
|
@ -6371,6 +6387,31 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"domain.MCPServerSettings": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"docs_tool_settings": {
|
||||
"$ref": "#/definitions/domain.MCPToolSettings"
|
||||
},
|
||||
"is_enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sample_auth": {
|
||||
"$ref": "#/definitions/domain.SimpleAuth"
|
||||
}
|
||||
}
|
||||
},
|
||||
"domain.MCPToolSettings": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"desc": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"domain.MessageContent": {
|
||||
"type": "object"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -245,6 +245,7 @@ definitions:
|
|||
- discord_bot
|
||||
- wechat_official_account
|
||||
- openai_api
|
||||
- mcp_server
|
||||
type: string
|
||||
x-enum-varnames:
|
||||
- SourceTypeDingTalk
|
||||
|
|
@ -264,6 +265,7 @@ definitions:
|
|||
- SourceTypeDiscordBot
|
||||
- SourceTypeWechatOfficialAccount
|
||||
- SourceTypeOpenAIAPI
|
||||
- SourceTypeMcpServer
|
||||
consts.StatDay:
|
||||
enum:
|
||||
- 1
|
||||
|
|
@ -418,8 +420,6 @@ definitions:
|
|||
allOf:
|
||||
- $ref: '#/definitions/domain.AIFeedbackSettings'
|
||||
description: AI feedback
|
||||
auto_sitemap:
|
||||
type: boolean
|
||||
body_code:
|
||||
type: string
|
||||
btns:
|
||||
|
|
@ -488,6 +488,10 @@ definitions:
|
|||
allOf:
|
||||
- $ref: '#/definitions/domain.LarkBotSettings'
|
||||
description: LarkBot
|
||||
mcp_server_settings:
|
||||
allOf:
|
||||
- $ref: '#/definitions/domain.MCPServerSettings'
|
||||
description: MCP Server Settings
|
||||
openai_api_bot_settings:
|
||||
allOf:
|
||||
- $ref: '#/definitions/domain.OpenAIAPIBotSettings'
|
||||
|
|
@ -595,8 +599,6 @@ definitions:
|
|||
allOf:
|
||||
- $ref: '#/definitions/domain.AIFeedbackSettings'
|
||||
description: AI feedback
|
||||
auto_sitemap:
|
||||
type: boolean
|
||||
body_code:
|
||||
type: string
|
||||
btns:
|
||||
|
|
@ -660,6 +662,10 @@ definitions:
|
|||
allOf:
|
||||
- $ref: '#/definitions/domain.LarkBotSettings'
|
||||
description: LarkBot
|
||||
mcp_server_settings:
|
||||
allOf:
|
||||
- $ref: '#/definitions/domain.MCPServerSettings'
|
||||
description: MCP Server Settings
|
||||
openai_api_bot_settings:
|
||||
allOf:
|
||||
- $ref: '#/definitions/domain.OpenAIAPIBotSettings'
|
||||
|
|
@ -767,6 +773,7 @@ definitions:
|
|||
- 9
|
||||
- 10
|
||||
- 11
|
||||
- 12
|
||||
format: int32
|
||||
type: integer
|
||||
x-enum-varnames:
|
||||
|
|
@ -781,6 +788,7 @@ definitions:
|
|||
- AppTypeOpenAIAPI
|
||||
- AppTypeWecomAIBot
|
||||
- AppTypeLarkBot
|
||||
- AppTypeMcpServer
|
||||
domain.AuthUserInfo:
|
||||
properties:
|
||||
avatar_url:
|
||||
|
|
@ -1625,6 +1633,22 @@ definitions:
|
|||
url:
|
||||
type: string
|
||||
type: object
|
||||
domain.MCPServerSettings:
|
||||
properties:
|
||||
docs_tool_settings:
|
||||
$ref: '#/definitions/domain.MCPToolSettings'
|
||||
is_enabled:
|
||||
type: boolean
|
||||
sample_auth:
|
||||
$ref: '#/definitions/domain.SimpleAuth'
|
||||
type: object
|
||||
domain.MCPToolSettings:
|
||||
properties:
|
||||
desc:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
type: object
|
||||
domain.MessageContent:
|
||||
type: object
|
||||
domain.MessageFrom:
|
||||
|
|
@ -3359,6 +3383,7 @@ paths:
|
|||
- discord_bot
|
||||
- wechat_official_account
|
||||
- openai_api
|
||||
- mcp_server
|
||||
in: query
|
||||
name: source_type
|
||||
required: true
|
||||
|
|
@ -3381,6 +3406,7 @@ paths:
|
|||
- SourceTypeDiscordBot
|
||||
- SourceTypeWechatOfficialAccount
|
||||
- SourceTypeOpenAIAPI
|
||||
- SourceTypeMcpServer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ const (
|
|||
AppTypeOpenAIAPI
|
||||
AppTypeWecomAIBot
|
||||
AppTypeLarkBot
|
||||
AppTypeMcpServer
|
||||
)
|
||||
|
||||
var AppTypes = []AppType{
|
||||
|
|
@ -38,6 +39,7 @@ var AppTypes = []AppType{
|
|||
AppTypeOpenAIAPI,
|
||||
AppTypeWecomAIBot,
|
||||
AppTypeLarkBot,
|
||||
AppTypeMcpServer,
|
||||
}
|
||||
|
||||
func (t AppType) ToSourceType() consts.SourceType {
|
||||
|
|
@ -64,6 +66,8 @@ func (t AppType) ToSourceType() consts.SourceType {
|
|||
return consts.SourceTypeOpenAIAPI
|
||||
case AppTypeLarkBot:
|
||||
return consts.SourceTypeLarkBot
|
||||
case AppTypeMcpServer:
|
||||
return consts.SourceTypeMcpServer
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
|
@ -92,9 +96,8 @@ type AppSettings struct {
|
|||
RecommendQuestions []string `json:"recommend_questions,omitempty"`
|
||||
RecommendNodeIDs []string `json:"recommend_node_ids,omitempty"`
|
||||
// seo
|
||||
Desc string `json:"desc,omitempty"`
|
||||
Keyword string `json:"keyword,omitempty"`
|
||||
AutoSitemap bool `json:"auto_sitemap,omitempty"`
|
||||
Desc string `json:"desc,omitempty"`
|
||||
Keyword string `json:"keyword,omitempty"`
|
||||
// inject code
|
||||
HeadCode string `json:"head_code,omitempty"`
|
||||
BodyCode string `json:"body_code,omitempty"`
|
||||
|
|
@ -167,6 +170,8 @@ type AppSettings struct {
|
|||
ContributeSettings ContributeSettings `json:"contribute_settings"`
|
||||
HomePageSetting consts.HomePageSetting `json:"home_page_setting"`
|
||||
ConversationSetting ConversationSetting `json:"conversation_setting"`
|
||||
// MCP Server Settings
|
||||
MCPServerSettings MCPServerSettings `json:"mcp_server_settings,omitempty"`
|
||||
}
|
||||
|
||||
type ConversationSetting struct {
|
||||
|
|
@ -178,6 +183,17 @@ type WebAppLandingTheme struct {
|
|||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type MCPServerSettings struct {
|
||||
IsEnabled bool `json:"is_enabled"`
|
||||
DocsToolSettings MCPToolSettings `json:"docs_tool_settings"`
|
||||
SampleAuth SimpleAuth `json:"sample_auth"`
|
||||
}
|
||||
|
||||
type MCPToolSettings struct {
|
||||
Name string `json:"name"`
|
||||
Desc string `json:"desc"`
|
||||
}
|
||||
|
||||
type LarkBotSettings struct {
|
||||
IsEnabled *bool `json:"is_enabled"`
|
||||
AppID string `json:"app_id"`
|
||||
|
|
@ -467,9 +483,8 @@ type AppSettingsResp struct {
|
|||
RecommendQuestions []string `json:"recommend_questions,omitempty"`
|
||||
RecommendNodeIDs []string `json:"recommend_node_ids,omitempty"`
|
||||
// seo
|
||||
Desc string `json:"desc,omitempty"`
|
||||
Keyword string `json:"keyword,omitempty"`
|
||||
AutoSitemap bool `json:"auto_sitemap,omitempty"`
|
||||
Desc string `json:"desc,omitempty"`
|
||||
Keyword string `json:"keyword,omitempty"`
|
||||
// inject code
|
||||
HeadCode string `json:"head_code,omitempty"`
|
||||
BodyCode string `json:"body_code,omitempty"`
|
||||
|
|
@ -544,6 +559,8 @@ type AppSettingsResp struct {
|
|||
WebAppLandingTheme WebAppLandingTheme `json:"web_app_landing_theme"`
|
||||
HomePageSetting consts.HomePageSetting `json:"home_page_setting"`
|
||||
ConversationSetting ConversationSetting `json:"conversation_setting"`
|
||||
// MCP Server Settings
|
||||
MCPServerSettings MCPServerSettings `json:"mcp_server_settings,omitempty"`
|
||||
}
|
||||
|
||||
type WebAppLandingConfigResp struct {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,15 @@ type ChatRequest struct {
|
|||
Info ConversationInfo `json:"-"`
|
||||
}
|
||||
|
||||
type ChatRagOnlyRequest struct {
|
||||
Message string `json:"message" validate:"required"`
|
||||
|
||||
KBID string `json:"-" validate:"required"`
|
||||
|
||||
UserInfo UserInfo `json:"user_info"`
|
||||
AppType AppType `json:"app_type" validate:"required,oneof=1 2"`
|
||||
}
|
||||
|
||||
type ConversationInfo struct {
|
||||
UserInfo UserInfo `json:"user_info"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ type BaseEditionLimitation struct {
|
|||
AllowWatermark bool `json:"allow_watermark"` // 支持水印
|
||||
AllowCopyProtection bool `json:"allow_copy_protection"` // 支持内容复制保护
|
||||
AllowOpenAIBotSettings bool `json:"allow_open_ai_bot_settings"` // 支持问答机器人
|
||||
AllowMCPServer bool `json:"allow_mcp_server"` // 支持创建MCP Server
|
||||
}
|
||||
|
||||
var baseEditionLimitationDefault = BaseEditionLimitation{
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ require (
|
|||
github.com/larksuite/oapi-sdk-go/v3 v3.4.20
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20250508043914-ed57fa5c5274
|
||||
github.com/mark3labs/mcp-go v0.43.0
|
||||
github.com/microcosm-cc/bluemonday v1.0.27
|
||||
github.com/mileusna/useragent v1.3.5
|
||||
github.com/minio/minio-go/v7 v7.0.91
|
||||
|
|
@ -137,6 +138,7 @@ require (
|
|||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/invopop/jsonschema v0.13.0 // indirect
|
||||
github.com/invopop/yaml v0.1.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
|
|
@ -186,6 +188,7 @@ require (
|
|||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||
github.com/yargevad/filepathx v1.0.0 // indirect
|
||||
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||
|
|
|
|||
|
|
@ -321,6 +321,8 @@ github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/C
|
|||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
|
||||
github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
|
||||
github.com/invopop/yaml v0.1.0 h1:YW3WGUoJEXYfzWBjn00zIlrw7brGVD0fUKRYDPAPhrc=
|
||||
github.com/invopop/yaml v0.1.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
|
|
@ -396,6 +398,8 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN
|
|||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
|
||||
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/mark3labs/mcp-go v0.43.0 h1:lgiKcWMddh4sngbU+hoWOZ9iAe/qp/m851RQpj3Y7jA=
|
||||
github.com/mark3labs/mcp-go v0.43.0/go.mod h1:YnJfOL382MIWDx1kMY+2zsRHU/q78dBg9aFb8W6Thdw=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
|
|
@ -576,6 +580,8 @@ github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJ
|
|||
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
|
||||
github.com/yargevad/filepathx v1.0.0 h1:SYcT+N3tYGi+NvazubCNlvgIPbzAk7i7y2dwg3I5FYc=
|
||||
github.com/yargevad/filepathx v1.0.0/go.mod h1:BprfX/gpYNJHJfc35GjRRpVcwWXS89gGulUIU5tK3tA=
|
||||
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
|
||||
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import (
|
|||
|
||||
"github.com/labstack/echo/v4"
|
||||
|
||||
"github.com/chaitin/panda-wiki/domain"
|
||||
"github.com/chaitin/panda-wiki/handler"
|
||||
"github.com/chaitin/panda-wiki/log"
|
||||
"github.com/chaitin/panda-wiki/usecase"
|
||||
|
|
@ -37,13 +36,6 @@ func (h *ShareSitemapHandler) GetSitemap(c echo.Context) error {
|
|||
if kbID == "" {
|
||||
return h.NewResponseWithError(c, "kb_id is required", nil)
|
||||
}
|
||||
appInfo, err := h.appUsecase.ShareGetWebAppInfo(c.Request().Context(), kbID, domain.GetAuthID(c))
|
||||
if err != nil {
|
||||
return h.NewResponseWithError(c, "web app not found", err)
|
||||
}
|
||||
if !appInfo.Settings.AutoSitemap {
|
||||
return h.NewResponseWithError(c, "未开启自动生成站点地图功能", nil)
|
||||
}
|
||||
|
||||
xml, err := h.sitemapUsecase.GetSitemap(c.Request().Context(), kbID)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit f6497a225d4b6ad76fe2dbedb427bd0e464a7662
|
||||
Subproject commit 7771d31053770721d75e194d1c6e7a4b60fb58aa
|
||||
|
|
@ -2,5 +2,7 @@ package backend
|
|||
|
||||
import (
|
||||
_ "github.com/jinzhu/copier"
|
||||
_ "github.com/mark3labs/mcp-go/mcp"
|
||||
_ "github.com/mark3labs/mcp-go/server"
|
||||
_ "google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ func (r *KnowledgeBaseRepository) SyncKBAccessSettingsToCaddy(ctx context.Contex
|
|||
{
|
||||
"match": []map[string]any{
|
||||
{
|
||||
"path": []string{"/share/v1/chat/completions", "/share/v1/app/wechat/app", "/share/v1/app/wechat/service", "/sitemap.xml", "/share/v1/app/wechat/official_account", "/share/v1/app/wechat/service/answer"},
|
||||
"path": []string{"/share/v1/chat/completions", "/share/v1/app/wechat/app", "/share/v1/app/wechat/service", "/sitemap.xml", "/share/v1/app/wechat/official_account", "/share/v1/app/wechat/service/answer", "/mcp"},
|
||||
},
|
||||
},
|
||||
"handle": []map[string]any{
|
||||
|
|
@ -341,12 +341,11 @@ func (r *KnowledgeBaseRepository) CreateKnowledgeBase(ctx context.Context, maxKB
|
|||
Name: kb.Name,
|
||||
Type: domain.AppTypeWeb,
|
||||
Settings: domain.AppSettings{
|
||||
Title: kb.Name,
|
||||
Desc: kb.Name,
|
||||
Keyword: kb.Name,
|
||||
AutoSitemap: true,
|
||||
Icon: domain.DefaultPandaWikiIconB64,
|
||||
WelcomeStr: fmt.Sprintf("欢迎使用%s", kb.Name),
|
||||
Title: kb.Name,
|
||||
Desc: kb.Name,
|
||||
Keyword: kb.Name,
|
||||
Icon: domain.DefaultPandaWikiIconB64,
|
||||
WelcomeStr: fmt.Sprintf("欢迎使用%s", kb.Name),
|
||||
Btns: []any{
|
||||
AppBtn{
|
||||
ID: uuid.New().String(),
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
DROP TABLE IF EXISTS mcp_calls;
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
CREATE TABLE IF NOT EXISTS mcp_calls (
|
||||
id SERIAL PRIMARY KEY,
|
||||
mcp_session_id TEXT NOT NULL,
|
||||
kb_id TEXT NOT NULL,
|
||||
remote_ip TEXT,
|
||||
initialize_req JSONB,
|
||||
initialize_resp JSONB,
|
||||
tool_call_req JSONB,
|
||||
tool_call_resp TEXT,
|
||||
created_at timestamptz NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
|
@ -125,7 +125,16 @@ func (u *AppUsecase) ValidateUpdateApp(ctx context.Context, id string, req *doma
|
|||
if app.Settings.WidgetBotSettings.CopyrightHideEnabled != req.Settings.WidgetBotSettings.CopyrightHideEnabled || app.Settings.WidgetBotSettings.CopyrightInfo != req.Settings.WidgetBotSettings.CopyrightInfo {
|
||||
return domain.ErrPermissionDenied
|
||||
}
|
||||
if app.Settings.ConversationSetting.CopyrightHideEnabled != req.Settings.ConversationSetting.CopyrightHideEnabled || app.Settings.ConversationSetting.CopyrightInfo != req.Settings.ConversationSetting.CopyrightInfo {
|
||||
if app.Settings.ConversationSetting.CopyrightHideEnabled != req.Settings.ConversationSetting.CopyrightHideEnabled {
|
||||
return domain.ErrPermissionDenied
|
||||
}
|
||||
if req.Settings.ConversationSetting.CopyrightInfo != domain.SettingCopyrightInfo && app.Settings.ConversationSetting.CopyrightInfo != req.Settings.ConversationSetting.CopyrightInfo {
|
||||
return domain.ErrPermissionDenied
|
||||
}
|
||||
}
|
||||
|
||||
if !limitation.AllowMCPServer {
|
||||
if app.Settings.MCPServerSettings.IsEnabled != req.Settings.MCPServerSettings.IsEnabled {
|
||||
return domain.ErrPermissionDenied
|
||||
}
|
||||
}
|
||||
|
|
@ -453,7 +462,6 @@ func (u *AppUsecase) GetAppDetailByKBIDAndAppType(ctx context.Context, kbID stri
|
|||
RecommendNodeIDs: app.Settings.RecommendNodeIDs,
|
||||
Desc: app.Settings.Desc,
|
||||
Keyword: app.Settings.Keyword,
|
||||
AutoSitemap: app.Settings.AutoSitemap,
|
||||
HeadCode: app.Settings.HeadCode,
|
||||
BodyCode: app.Settings.BodyCode,
|
||||
// DingTalkBot
|
||||
|
|
@ -524,6 +532,8 @@ func (u *AppUsecase) GetAppDetailByKBIDAndAppType(ctx context.Context, kbID stri
|
|||
ConversationSetting: app.Settings.ConversationSetting,
|
||||
|
||||
WecomAIBotSettings: app.Settings.WecomAIBotSettings,
|
||||
|
||||
MCPServerSettings: app.Settings.MCPServerSettings,
|
||||
}
|
||||
|
||||
if !domain.GetBaseEditionLimitation(ctx).AllowCustomCopyright {
|
||||
|
|
@ -553,6 +563,19 @@ func (u *AppUsecase) GetAppDetailByKBIDAndAppType(ctx context.Context, kbID stri
|
|||
return appDetailResp, nil
|
||||
}
|
||||
|
||||
func (u *AppUsecase) GetMCPServerAppInfo(ctx context.Context, kbID string) (*domain.AppInfoResp, error) {
|
||||
apiApp, err := u.repo.GetOrCreateAppByKBIDAndType(ctx, kbID, domain.AppTypeMcpServer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
appInfo := &domain.AppInfoResp{
|
||||
Settings: domain.AppSettingsResp{
|
||||
MCPServerSettings: apiApp.Settings.MCPServerSettings,
|
||||
},
|
||||
}
|
||||
return appInfo, nil
|
||||
}
|
||||
|
||||
func (u *AppUsecase) ShareGetWebAppInfo(ctx context.Context, kbID string, authId uint) (*domain.AppInfoResp, error) {
|
||||
app, err := u.repo.GetOrCreateAppByKBIDAndType(ctx, kbID, domain.AppTypeWeb)
|
||||
if err != nil {
|
||||
|
|
@ -599,7 +622,6 @@ func (u *AppUsecase) ShareGetWebAppInfo(ctx context.Context, kbID string, authId
|
|||
RecommendNodeIDs: app.Settings.RecommendNodeIDs,
|
||||
Desc: app.Settings.Desc,
|
||||
Keyword: app.Settings.Keyword,
|
||||
AutoSitemap: app.Settings.AutoSitemap,
|
||||
HeadCode: app.Settings.HeadCode,
|
||||
BodyCode: app.Settings.BodyCode,
|
||||
// theme
|
||||
|
|
|
|||
|
|
@ -301,6 +301,64 @@ func (u *ChatUsecase) Chat(ctx context.Context, req *domain.ChatRequest) (<-chan
|
|||
return eventCh, nil
|
||||
}
|
||||
|
||||
func (u *ChatUsecase) ChatRagOnly(ctx context.Context, req *domain.ChatRagOnlyRequest) (<-chan domain.SSEEvent, error) {
|
||||
eventCh := make(chan domain.SSEEvent, 100)
|
||||
go func() {
|
||||
defer close(eventCh)
|
||||
|
||||
// extra1. if user set question block words then check it
|
||||
blockWords, err := u.blockWordRepo.GetBlockWords(ctx, req.KBID)
|
||||
if err != nil {
|
||||
u.logger.Error("failed to get question block words", log.Error(err))
|
||||
eventCh <- domain.SSEEvent{Type: "error", Content: "failed to get question block words"}
|
||||
return
|
||||
}
|
||||
if len(blockWords) > 0 { // check --> filter
|
||||
questionFilter := utils.GetDFA(req.KBID)
|
||||
if err := questionFilter.DFA.Check(req.Message); err != nil { // exist then return err
|
||||
answer := "**您的问题包含敏感词, AI 无法回答您的问题。**"
|
||||
eventCh <- domain.SSEEvent{Type: "error", Content: answer}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if req.UserInfo.AuthUserID == 0 {
|
||||
auth, _ := u.AuthRepo.GetAuthBySourceType(ctx, req.AppType.ToSourceType())
|
||||
if auth != nil {
|
||||
req.UserInfo.AuthUserID = auth.ID
|
||||
}
|
||||
}
|
||||
|
||||
groupIds, err := u.AuthRepo.GetAuthGroupIdsWithParentsByAuthId(ctx, req.UserInfo.AuthUserID)
|
||||
if err != nil {
|
||||
u.logger.Error("failed to get auth groupIds", log.Error(err))
|
||||
eventCh <- domain.SSEEvent{Type: "error", Content: "failed to get auth groupIds"}
|
||||
return
|
||||
}
|
||||
|
||||
// retrieve documents
|
||||
kb, err := u.kbRepo.GetKnowledgeBaseByID(ctx, req.KBID)
|
||||
if err != nil {
|
||||
u.logger.Error("failed to get kb", log.Error(err))
|
||||
eventCh <- domain.SSEEvent{Type: "error", Content: "failed to get kb"}
|
||||
return
|
||||
}
|
||||
rankedNodes, err := u.llmUsecase.GetRankNodes(ctx, []string{kb.DatasetID}, req.Message, groupIds, 0, nil)
|
||||
if err != nil {
|
||||
u.logger.Error("failed to get rank nodes", log.Error(err))
|
||||
eventCh <- domain.SSEEvent{Type: "error", Content: "failed to get rank nodes"}
|
||||
return
|
||||
}
|
||||
documents := domain.FormatNodeChunks(rankedNodes, kb.AccessSettings.BaseURL)
|
||||
u.logger.Debug("documents", log.String("documents", documents))
|
||||
|
||||
// send only the documents part
|
||||
eventCh <- domain.SSEEvent{Type: "data", Content: documents}
|
||||
eventCh <- domain.SSEEvent{Type: "done"}
|
||||
}()
|
||||
return eventCh, nil
|
||||
}
|
||||
|
||||
func (u *ChatUsecase) CreateAcOnChunk(ctx context.Context, kbID string, answer *string, eventCh chan<- domain.SSEEvent, blockWords []string) (func(ctx context.Context, dataType, chunk string) error,
|
||||
func(ctx context.Context, dataType string)) {
|
||||
var buffer strings.Builder
|
||||
|
|
|
|||
|
|
@ -2,13 +2,18 @@ package utils
|
|||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func GetClientIPFromRemoteAddr(c echo.Context) string {
|
||||
addr := c.Request().RemoteAddr
|
||||
return ExtractHostFromRemoteAddr(c.Request())
|
||||
}
|
||||
|
||||
func ExtractHostFromRemoteAddr(r *http.Request) string {
|
||||
addr := r.RemoteAddr
|
||||
if addr == "" {
|
||||
return ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -323,7 +323,6 @@ export type WelcomeSetting = {
|
|||
export type SEOSetting = {
|
||||
keyword: string;
|
||||
desc: string;
|
||||
auto_sitemap: boolean;
|
||||
};
|
||||
|
||||
export type CustomCodeSetting = {
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ const Step1Model: React.FC<Step1ModelProps> = ({ ref }) => {
|
|||
}, [modelList]);
|
||||
|
||||
const onSubmit = async () => {
|
||||
await modelConfigRef.current?.onSubmit?.();
|
||||
// 检查模型模式设置
|
||||
try {
|
||||
const modeSetting = await getApiV1ModelModeSetting();
|
||||
|
|
@ -112,6 +113,7 @@ const Step1Model: React.FC<Step1ModelProps> = ({ ref }) => {
|
|||
getModelList={getModelList}
|
||||
hideDocumentationHint={true}
|
||||
showTip={true}
|
||||
showSaveBtn={false}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { copyText } from '@/utils';
|
|||
import { Box, Stack } from '@mui/material';
|
||||
import { Ellipsis } from '@ctzhian/ui';
|
||||
import { IconFuzhi } from '@panda-wiki/icons';
|
||||
import { message } from '@ctzhian/ui';
|
||||
|
||||
interface ShowTextProps {
|
||||
text: string[];
|
||||
|
|
@ -10,6 +11,7 @@ interface ShowTextProps {
|
|||
noEllipsis?: boolean;
|
||||
icon?: React.ReactNode;
|
||||
onClick?: () => void;
|
||||
forceCopy?: boolean;
|
||||
}
|
||||
|
||||
const ShowText = ({
|
||||
|
|
@ -21,6 +23,7 @@ const ShowText = ({
|
|||
),
|
||||
onClick,
|
||||
noEllipsis = false,
|
||||
forceCopy = false,
|
||||
}: ShowTextProps) => {
|
||||
return (
|
||||
<Stack
|
||||
|
|
@ -48,8 +51,32 @@ const ShowText = ({
|
|||
onClick={
|
||||
copyable
|
||||
? () => {
|
||||
copyText(text.join('\n'));
|
||||
onClick?.();
|
||||
const content = text.join('\n');
|
||||
if (forceCopy) {
|
||||
try {
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(content);
|
||||
message.success('复制成功');
|
||||
} else {
|
||||
const ta = document.createElement('textarea');
|
||||
ta.style.position = 'fixed';
|
||||
ta.style.opacity = '0';
|
||||
ta.style.left = '-9999px';
|
||||
ta.style.top = '-9999px';
|
||||
ta.value = content;
|
||||
document.body.appendChild(ta);
|
||||
ta.focus();
|
||||
ta.select();
|
||||
const ok = document.execCommand('copy');
|
||||
if (ok) message.success('复制成功');
|
||||
document.body.removeChild(ta);
|
||||
}
|
||||
} catch (e) {}
|
||||
onClick?.();
|
||||
} else {
|
||||
copyText(content);
|
||||
onClick?.();
|
||||
}
|
||||
}
|
||||
: onClick
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ const ModelModal = lazy(() =>
|
|||
export interface ModelConfigRef {
|
||||
getAutoConfigFormData: () => { apiKey: string; selectedModel: string } | null;
|
||||
handleClose: () => void;
|
||||
onSubmit: () => Promise<void>;
|
||||
}
|
||||
|
||||
interface ModelConfigProps {
|
||||
|
|
@ -57,6 +58,7 @@ interface ModelConfigProps {
|
|||
autoSwitchToAutoMode?: boolean;
|
||||
hideDocumentationHint?: boolean;
|
||||
showTip?: boolean;
|
||||
showSaveBtn?: boolean;
|
||||
}
|
||||
|
||||
const ModelConfig = forwardRef<ModelConfigRef, ModelConfigProps>(
|
||||
|
|
@ -73,6 +75,7 @@ const ModelConfig = forwardRef<ModelConfigRef, ModelConfigProps>(
|
|||
autoSwitchToAutoMode = false,
|
||||
hideDocumentationHint = false,
|
||||
showTip = false,
|
||||
showSaveBtn = true,
|
||||
} = props;
|
||||
|
||||
const [autoConfigMode, setAutoConfigMode] = useState(false);
|
||||
|
|
@ -182,51 +185,58 @@ const ModelConfig = forwardRef<ModelConfigRef, ModelConfigProps>(
|
|||
}
|
||||
return null;
|
||||
},
|
||||
onSubmit: handleSave,
|
||||
handleClose: handleCloseModal,
|
||||
}));
|
||||
|
||||
const handleSave = async () => {
|
||||
setIsSaving(true);
|
||||
try {
|
||||
const requestData: {
|
||||
mode: 'auto' | 'manual';
|
||||
auto_mode_api_key?: string;
|
||||
chat_model?: string;
|
||||
} = {
|
||||
mode: tempMode,
|
||||
};
|
||||
if (tempMode !== savedMode || hasConfigChanged) {
|
||||
setIsSaving(true);
|
||||
try {
|
||||
const requestData: {
|
||||
mode: 'auto' | 'manual';
|
||||
auto_mode_api_key?: string;
|
||||
chat_model?: string;
|
||||
} = {
|
||||
mode: tempMode,
|
||||
};
|
||||
|
||||
// 如果是自动模式,获取用户输入的 API Key 和 model
|
||||
if (tempMode === 'auto' && autoConfigRef.current) {
|
||||
const formData = autoConfigRef.current.getFormData();
|
||||
if (formData) {
|
||||
requestData.auto_mode_api_key = formData.apiKey;
|
||||
requestData.chat_model = formData.selectedModel;
|
||||
// 如果是自动模式,获取用户输入的 API Key 和 model
|
||||
if (tempMode === 'auto' && autoConfigRef.current) {
|
||||
const formData = autoConfigRef.current.getFormData();
|
||||
if (formData) {
|
||||
requestData.auto_mode_api_key = formData.apiKey;
|
||||
requestData.chat_model = formData.selectedModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await postApiV1ModelSwitchMode(requestData);
|
||||
setSavedMode(tempMode);
|
||||
setAutoConfigMode(tempMode === 'auto');
|
||||
setHasConfigChanged(false); // 重置变更标记
|
||||
await postApiV1ModelSwitchMode(requestData);
|
||||
setSavedMode(tempMode);
|
||||
setAutoConfigMode(tempMode === 'auto');
|
||||
setHasConfigChanged(false); // 重置变更标记
|
||||
|
||||
// 更新保存的初始值
|
||||
if (tempMode === 'auto' && autoConfigRef.current) {
|
||||
const formData = autoConfigRef.current.getFormData();
|
||||
if (formData) {
|
||||
setInitialApiKey(formData.apiKey);
|
||||
setInitialChatModel(formData.selectedModel);
|
||||
// 更新保存的初始值
|
||||
if (tempMode === 'auto' && autoConfigRef.current) {
|
||||
const formData = autoConfigRef.current.getFormData();
|
||||
if (formData) {
|
||||
setInitialApiKey(formData.apiKey);
|
||||
setInitialChatModel(formData.selectedModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
message.success(
|
||||
tempMode === 'auto' ? '已切换为自动配置模式' : '已切换为手动配置模式',
|
||||
);
|
||||
getModelList(); // 刷新模型列表
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
if (showSaveBtn) {
|
||||
message.success(
|
||||
tempMode === 'auto'
|
||||
? '已切换为自动配置模式'
|
||||
: '已切换为手动配置模式',
|
||||
);
|
||||
}
|
||||
getModelList(); // 刷新模型列表
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -310,7 +320,7 @@ const ModelConfig = forwardRef<ModelConfigRef, ModelConfigProps>(
|
|||
/>
|
||||
</RadioGroup>
|
||||
</Box>
|
||||
{(tempMode !== savedMode || hasConfigChanged) && (
|
||||
{(tempMode !== savedMode || hasConfigChanged) && showSaveBtn && (
|
||||
<Button
|
||||
variant='contained'
|
||||
size='small'
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { VersionInfoMap } from '@/constant/version';
|
||||
import { useVersionInfo } from '@/hooks';
|
||||
import { ConstsLicenseEdition } from '@/request/types';
|
||||
import { styled, SxProps } from '@mui/material';
|
||||
import { styled, SxProps, Tooltip } from '@mui/material';
|
||||
import React from 'react';
|
||||
|
||||
const StyledMaskWrapper = styled('div')(({ theme }) => ({
|
||||
|
|
@ -95,24 +95,48 @@ export const VersionCanUse = ({
|
|||
ConstsLicenseEdition.LicenseEditionEnterprise,
|
||||
],
|
||||
sx,
|
||||
mode = 'text',
|
||||
}: {
|
||||
permission?: ConstsLicenseEdition[];
|
||||
sx?: SxProps;
|
||||
mode?: 'icon' | 'text';
|
||||
}) => {
|
||||
const versionInfo = useVersionInfo();
|
||||
const hasPermission = permission.includes(versionInfo.permission);
|
||||
if (hasPermission) return null;
|
||||
const nextVersionInfo = VersionInfoMap[permission[0]];
|
||||
return (
|
||||
<StyledMaskContent sx={{ width: 'auto', ml: 1, ...sx }}>
|
||||
<StyledMaskVersion sx={{ backgroundColor: nextVersionInfo.bgColor }}>
|
||||
<img
|
||||
src={nextVersionInfo.image}
|
||||
style={{ width: 12, objectFit: 'contain', marginTop: 1 }}
|
||||
alt={nextVersionInfo.label}
|
||||
/>
|
||||
{nextVersionInfo?.label}可用
|
||||
</StyledMaskVersion>
|
||||
<StyledMaskContent
|
||||
sx={{
|
||||
width: 'auto',
|
||||
ml: mode === 'icon' ? 0.5 : 1,
|
||||
// 允许 Tooltip 在 disabled 的父元素中正常工作
|
||||
pointerEvents: 'auto',
|
||||
...sx,
|
||||
}}
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}}
|
||||
>
|
||||
{mode === 'icon' ? (
|
||||
<Tooltip title={nextVersionInfo.label + '可用'} placement='top' arrow>
|
||||
<img
|
||||
src={nextVersionInfo.image}
|
||||
style={{ width: 14, objectFit: 'contain' }}
|
||||
alt={nextVersionInfo.label}
|
||||
/>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<StyledMaskVersion sx={{ backgroundColor: nextVersionInfo.bgColor }}>
|
||||
<img
|
||||
src={nextVersionInfo.image}
|
||||
style={{ width: 12, objectFit: 'contain', marginTop: 1 }}
|
||||
alt={nextVersionInfo.label}
|
||||
/>
|
||||
{nextVersionInfo?.label}可用
|
||||
</StyledMaskVersion>
|
||||
)}
|
||||
</StyledMaskContent>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { uploadFile } from '@/api';
|
||||
import Emoji from '@/components/Emoji';
|
||||
import { BUSINESS_VERSION_PERMISSION } from '@/constant/version';
|
||||
import { postApiV1CreationTabComplete, putApiV1NodeDetail } from '@/request';
|
||||
import { V1NodeDetailResp } from '@/request/types';
|
||||
import { useAppSelector } from '@/store';
|
||||
|
|
@ -13,6 +14,12 @@ import {
|
|||
} from '@ctzhian/tiptap';
|
||||
import { message } from '@ctzhian/ui';
|
||||
import { Box, Stack, TextField, Tooltip } from '@mui/material';
|
||||
import {
|
||||
IconAShijian2,
|
||||
IconDJzhinengzhaiyao,
|
||||
IconTianjiawendang,
|
||||
IconZiti,
|
||||
} from '@panda-wiki/icons';
|
||||
import dayjs from 'dayjs';
|
||||
import { debounce } from 'lodash-es';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
|
@ -29,13 +36,6 @@ import Header from './Header';
|
|||
import Summary from './Summary';
|
||||
import Toc from './Toc';
|
||||
import Toolbar from './Toolbar';
|
||||
import { BUSINESS_VERSION_PERMISSION } from '@/constant/version';
|
||||
import {
|
||||
IconTianjiawendang,
|
||||
IconAShijian2,
|
||||
IconZiti,
|
||||
IconDJzhinengzhaiyao,
|
||||
} from '@panda-wiki/icons';
|
||||
|
||||
interface WrapProps {
|
||||
detail: V1NodeDetailResp;
|
||||
|
|
@ -202,23 +202,32 @@ const Wrap = ({ detail: defaultDetail }: WrapProps) => {
|
|||
onAiWritingGetSuggestion: handleAiWritingGetSuggestion,
|
||||
});
|
||||
|
||||
const exportFile = (value: string, type: string) => {
|
||||
if (!value) return;
|
||||
const content = completeIncompleteLinks(value);
|
||||
const blob = new Blob([content], { type: `text/${type}` });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = `${nodeDetail?.name}.${type}`;
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
message.success('导出成功');
|
||||
};
|
||||
|
||||
const handleExport = useCallback(
|
||||
async (type: string) => {
|
||||
if (editorRef) {
|
||||
let value = nodeDetail?.content || '';
|
||||
if (!isMarkdown) {
|
||||
value = editorRef.getContent() || '';
|
||||
if (type === 'html') {
|
||||
const value = editorRef.getHTML() || '';
|
||||
exportFile(value, type);
|
||||
} else if (type === 'md') {
|
||||
if (isMarkdown) {
|
||||
let value = nodeDetail?.content || '';
|
||||
exportFile(value, type);
|
||||
} else if (editorRef) {
|
||||
const value = editorRef.getMarkdown() || '';
|
||||
exportFile(value, type);
|
||||
}
|
||||
if (!value) return;
|
||||
const content = completeIncompleteLinks(value);
|
||||
const blob = new Blob([content], { type: `text/${type}` });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = `${nodeDetail?.name}.${type}`;
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
message.success('导出成功');
|
||||
}
|
||||
},
|
||||
[editorRef, nodeDetail?.content, nodeDetail?.name, isMarkdown],
|
||||
|
|
@ -672,7 +681,19 @@ const Wrap = ({ detail: defaultDetail }: WrapProps) => {
|
|||
</Box>
|
||||
<Box
|
||||
sx={{ ...(fixedToc && { display: 'flex' }) }}
|
||||
onKeyDown={event => event.stopPropagation()}
|
||||
onKeyDown={event => {
|
||||
if ((event.ctrlKey || event.metaKey) && event.key === 's') {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
isMarkdown &&
|
||||
(event.ctrlKey || event.metaKey) &&
|
||||
event.key === 'b'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
event.stopPropagation();
|
||||
}}
|
||||
>
|
||||
{isMarkdown ? (
|
||||
<Box
|
||||
|
|
|
|||
|
|
@ -0,0 +1,272 @@
|
|||
import { DomainKnowledgeBaseDetail } from '@/request/types';
|
||||
import {
|
||||
Box,
|
||||
FormControl,
|
||||
FormControlLabel,
|
||||
Radio,
|
||||
RadioGroup,
|
||||
TextField,
|
||||
Stack,
|
||||
} from '@mui/material';
|
||||
import { SettingCardItem, FormItem } from './Common';
|
||||
import ShowText from '@/components/ShowText';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import { useMemo, useState, useEffect } from 'react';
|
||||
import { message } from '@ctzhian/ui';
|
||||
import { getApiV1AppDetail, putApiV1App } from '@/request/App';
|
||||
import { DomainAppDetailResp, ConstsLicenseEdition } from '@/request/types';
|
||||
|
||||
interface CardMCPProps {
|
||||
kb: DomainKnowledgeBaseDetail;
|
||||
}
|
||||
|
||||
const CardMCP = ({ kb }: CardMCPProps) => {
|
||||
const [isEdit, setIsEdit] = useState(false);
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
watch,
|
||||
setValue,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
defaultValues: {
|
||||
is_enabled: false,
|
||||
access: 'open' as 'open' | 'auth',
|
||||
token: '',
|
||||
tool_name: 'get_docs',
|
||||
tool_desc: '为解决用户的问题从知识库中检索文档',
|
||||
},
|
||||
});
|
||||
|
||||
const isEnabled = watch('is_enabled');
|
||||
const access = watch('access');
|
||||
const [detail, setDetail] = useState<DomainAppDetailResp | null>(null);
|
||||
|
||||
const mcpUrl = useMemo(() => {
|
||||
const hostRaw = kb?.access_settings?.hosts?.[0] || window.location.hostname;
|
||||
const host = hostRaw === '*' ? window.location.hostname : hostRaw;
|
||||
const sslPorts = kb?.access_settings?.ssl_ports || [];
|
||||
const httpPorts = kb?.access_settings?.ports || [];
|
||||
const isHttps = sslPorts.length > 0;
|
||||
const protocol = isHttps ? 'https' : 'http';
|
||||
if (!host) {
|
||||
return `${protocol}://${window.location.hostname}${isHttps ? '' : `:${window.location.port}`}/mcp`;
|
||||
}
|
||||
if (isHttps) {
|
||||
return `${protocol}://${host}/mcp`;
|
||||
}
|
||||
const port = httpPorts[0];
|
||||
if (!port) return `${protocol}://${host}/mcp`;
|
||||
return `${protocol}://${host}:${port}/mcp`;
|
||||
}, [kb]);
|
||||
|
||||
const onSubmit = handleSubmit(() => {
|
||||
if (!kb || !detail) return;
|
||||
const payload: any = {
|
||||
kb_id: kb.id!,
|
||||
settings: {
|
||||
mcp_server_settings: {
|
||||
is_enabled: isEnabled,
|
||||
docs_tool_settings: {
|
||||
name: watch('tool_name'),
|
||||
desc: watch('tool_desc'),
|
||||
},
|
||||
sample_auth: {
|
||||
enabled: access === 'auth',
|
||||
password: access === 'auth' ? watch('token') : '',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
putApiV1App({ id: detail.id! }, payload).then(() => {
|
||||
message.success('保存成功');
|
||||
setIsEdit(false);
|
||||
getDetail();
|
||||
});
|
||||
});
|
||||
|
||||
const getDetail = () => {
|
||||
getApiV1AppDetail({ kb_id: kb.id!, type: '12' }).then(res => {
|
||||
setDetail(res);
|
||||
const is_enabled =
|
||||
(res.settings as any)?.mcp_server_settings?.is_enabled ?? false;
|
||||
const auth =
|
||||
(res.settings as any)?.mcp_server_settings?.sample_auth ?? {};
|
||||
const accessVal = auth.enabled ? 'auth' : 'open';
|
||||
const tokenVal = auth.password ?? '';
|
||||
const toolName =
|
||||
(res.settings as any)?.mcp_server_settings?.docs_tool_settings?.name ??
|
||||
'';
|
||||
const toolDesc =
|
||||
(res.settings as any)?.mcp_server_settings?.docs_tool_settings?.desc ??
|
||||
'';
|
||||
setValue('is_enabled', is_enabled);
|
||||
setValue('access', accessVal);
|
||||
setValue('token', tokenVal);
|
||||
setValue('tool_name', toolName);
|
||||
setValue('tool_desc', toolDesc);
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!kb) return;
|
||||
getDetail();
|
||||
}, [kb]);
|
||||
|
||||
return (
|
||||
<Box sx={{ width: 1000, margin: 'auto', pb: 4 }}>
|
||||
<SettingCardItem
|
||||
title='MCP 设置'
|
||||
isEdit={isEdit}
|
||||
onSubmit={onSubmit}
|
||||
permission={[
|
||||
ConstsLicenseEdition.LicenseEditionBusiness,
|
||||
ConstsLicenseEdition.LicenseEditionEnterprise,
|
||||
]}
|
||||
more={{
|
||||
type: 'link',
|
||||
href: 'https://pandawiki.docs.baizhi.cloud/node/019aa45c-90c1-7e6f-b17a-74ab1b200153',
|
||||
target: '_blank',
|
||||
text: '使用方法',
|
||||
}}
|
||||
>
|
||||
<FormItem label='MCP Server'>
|
||||
<FormControl>
|
||||
<Controller
|
||||
control={control}
|
||||
name='is_enabled'
|
||||
render={({ field }) => (
|
||||
<RadioGroup
|
||||
{...field}
|
||||
onChange={e => {
|
||||
field.onChange(e.target.value === 'true');
|
||||
setIsEdit(true);
|
||||
}}
|
||||
>
|
||||
<Stack direction={'row'}>
|
||||
<FormControlLabel
|
||||
value={true}
|
||||
control={<Radio size='small' />}
|
||||
label={<Box sx={{ width: 100 }}>启用</Box>}
|
||||
/>
|
||||
<FormControlLabel
|
||||
value={false}
|
||||
control={<Radio size='small' />}
|
||||
label={<Box sx={{ width: 100 }}>禁用</Box>}
|
||||
/>
|
||||
</Stack>
|
||||
</RadioGroup>
|
||||
)}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
|
||||
{isEnabled && (
|
||||
<>
|
||||
<FormItem label='MCP URL'>
|
||||
<ShowText
|
||||
text={[mcpUrl]}
|
||||
copyable={true}
|
||||
noEllipsis={true}
|
||||
forceCopy={true}
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem label='MCP Tool名称'>
|
||||
<Controller
|
||||
control={control}
|
||||
name='tool_name'
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
placeholder='自定义检索文档MCP Tool名称'
|
||||
onChange={e => {
|
||||
field.onChange(e.target.value);
|
||||
setIsEdit(true);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem label='MCP Tool描述'>
|
||||
<Controller
|
||||
control={control}
|
||||
name='tool_desc'
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
placeholder='自定义检索文档MCP Tool描述'
|
||||
onChange={e => {
|
||||
field.onChange(e.target.value);
|
||||
setIsEdit(true);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem label='访问控制'>
|
||||
<FormControl>
|
||||
<Controller
|
||||
control={control}
|
||||
name='access'
|
||||
render={({ field }) => (
|
||||
<RadioGroup
|
||||
{...field}
|
||||
onChange={e => {
|
||||
field.onChange(e.target.value);
|
||||
setIsEdit(true);
|
||||
}}
|
||||
>
|
||||
<Stack direction={'row'}>
|
||||
<FormControlLabel
|
||||
value={'open'}
|
||||
control={<Radio size='small' />}
|
||||
label={<Box sx={{ width: 100 }}>完全公开</Box>}
|
||||
/>
|
||||
<FormControlLabel
|
||||
value={'auth'}
|
||||
control={<Radio size='small' />}
|
||||
label={<Box sx={{ width: 100 }}>需要认证</Box>}
|
||||
/>
|
||||
</Stack>
|
||||
</RadioGroup>
|
||||
)}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
|
||||
{access === 'auth' && (
|
||||
<FormItem label='访问口令' required>
|
||||
<Controller
|
||||
control={control}
|
||||
name='token'
|
||||
rules={{ required: '访问口令不能为空' }}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
placeholder='访问口令'
|
||||
onChange={e => {
|
||||
field.onChange(e.target.value);
|
||||
setIsEdit(true);
|
||||
}}
|
||||
error={!!errors.token}
|
||||
helperText={errors.token?.message}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormItem>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</SettingCardItem>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default CardMCP;
|
||||
|
|
@ -15,6 +15,7 @@ import CardKB from './component/CardKB';
|
|||
import CardRobot from './component/CardRobot';
|
||||
import CardSecurity from './component/CardSecurity';
|
||||
import CardWeb from './component/CardWeb';
|
||||
import CardMCP from './component/CardMCP';
|
||||
|
||||
const SettingTabs: { label: string; id: string }[] = [
|
||||
{ label: '门户网站', id: 'portal-website' },
|
||||
|
|
@ -23,6 +24,7 @@ const SettingTabs: { label: string; id: string }[] = [
|
|||
{ label: '反馈设置', id: 'feedback' },
|
||||
{ label: '安全设置', id: 'security' },
|
||||
{ label: '访问控制', id: 'backend-info' },
|
||||
{ label: 'MCP 设置', id: 'mcp' },
|
||||
];
|
||||
|
||||
const Setting = () => {
|
||||
|
|
@ -116,6 +118,7 @@ const Setting = () => {
|
|||
{activeTab === 'feedback' && <CardFeedback kb={kb} />}
|
||||
{activeTab === 'robot' && <CardRobot kb={kb} url={url} />}
|
||||
{activeTab === 'portal-website' && <CardWeb kb={kb} refresh={getKb} />}
|
||||
{activeTab === 'mcp' && <CardMCP kb={kb} />}
|
||||
</Card>
|
||||
</Box>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -36,9 +36,17 @@ const Statistic = () => {
|
|||
{ label: '近 24 小时', value: 1, disabled: false },
|
||||
{
|
||||
label: (
|
||||
<Stack direction={'row'} alignItems={'center'} gap={0.5}>
|
||||
<Stack
|
||||
direction={'row'}
|
||||
alignItems={'center'}
|
||||
gap={0.5}
|
||||
sx={{ lineHeight: 1 }}
|
||||
>
|
||||
<span>近 7 天</span>
|
||||
<VersionCanUse permission={PROFESSION_VERSION_PERMISSION} />
|
||||
<VersionCanUse
|
||||
permission={PROFESSION_VERSION_PERMISSION}
|
||||
mode='icon'
|
||||
/>
|
||||
</Stack>
|
||||
),
|
||||
value: 7,
|
||||
|
|
@ -46,9 +54,17 @@ const Statistic = () => {
|
|||
},
|
||||
{
|
||||
label: (
|
||||
<Stack direction={'row'} alignItems={'center'} gap={0.5}>
|
||||
<Stack
|
||||
direction={'row'}
|
||||
alignItems={'center'}
|
||||
gap={0.5}
|
||||
sx={{ lineHeight: 1 }}
|
||||
>
|
||||
<span>近 30 天</span>
|
||||
<VersionCanUse permission={BUSINESS_VERSION_PERMISSION} />
|
||||
<VersionCanUse
|
||||
permission={BUSINESS_VERSION_PERMISSION}
|
||||
mode='icon'
|
||||
/>
|
||||
</Stack>
|
||||
),
|
||||
value: 30,
|
||||
|
|
@ -56,9 +72,17 @@ const Statistic = () => {
|
|||
},
|
||||
{
|
||||
label: (
|
||||
<Stack direction={'row'} alignItems={'center'} gap={0.5}>
|
||||
<Stack
|
||||
direction={'row'}
|
||||
alignItems={'center'}
|
||||
gap={0.5}
|
||||
sx={{ lineHeight: 1 }}
|
||||
>
|
||||
<span>近 90 天</span>
|
||||
<VersionCanUse permission={BUSINESS_VERSION_PERMISSION} />
|
||||
<VersionCanUse
|
||||
permission={BUSINESS_VERSION_PERMISSION}
|
||||
mode='icon'
|
||||
/>
|
||||
</Stack>
|
||||
),
|
||||
value: 90,
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ export enum ConstsSourceType {
|
|||
SourceTypeDiscordBot = "discord_bot",
|
||||
SourceTypeWechatOfficialAccount = "wechat_official_account",
|
||||
SourceTypeOpenAIAPI = "openai_api",
|
||||
SourceTypeMcpServer = "mcp_server",
|
||||
}
|
||||
|
||||
/** @format int32 */
|
||||
|
|
@ -591,7 +592,8 @@ export interface GetApiProV1AuthGetParams {
|
|||
| "wechat_service_bot"
|
||||
| "discord_bot"
|
||||
| "wechat_official_account"
|
||||
| "openai_api";
|
||||
| "openai_api"
|
||||
| "mcp_server";
|
||||
}
|
||||
|
||||
export interface DeleteApiProV1AuthGroupDeleteParams {
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ export enum DomainAppType {
|
|||
AppTypeOpenAIAPI = 9,
|
||||
AppTypeWecomAIBot = 10,
|
||||
AppTypeLarkBot = 11,
|
||||
AppTypeMcpServer = 12,
|
||||
}
|
||||
|
||||
export enum ConstsWatermarkSetting {
|
||||
|
|
@ -132,6 +133,7 @@ export enum ConstsSourceType {
|
|||
SourceTypeDiscordBot = "discord_bot",
|
||||
SourceTypeWechatOfficialAccount = "wechat_official_account",
|
||||
SourceTypeOpenAIAPI = "openai_api",
|
||||
SourceTypeMcpServer = "mcp_server",
|
||||
}
|
||||
|
||||
export enum ConstsNodeRagInfoStatus {
|
||||
|
|
@ -298,7 +300,6 @@ export interface DomainAppInfoResp {
|
|||
export interface DomainAppSettings {
|
||||
/** AI feedback */
|
||||
ai_feedback_settings?: DomainAIFeedbackSettings;
|
||||
auto_sitemap?: boolean;
|
||||
body_code?: string;
|
||||
btns?: unknown[];
|
||||
/** catalog settings */
|
||||
|
|
@ -333,6 +334,8 @@ export interface DomainAppSettings {
|
|||
keyword?: string;
|
||||
/** LarkBot */
|
||||
lark_bot_settings?: DomainLarkBotSettings;
|
||||
/** MCP Server Settings */
|
||||
mcp_server_settings?: DomainMCPServerSettings;
|
||||
/** OpenAI API Bot settings */
|
||||
openai_api_bot_settings?: DomainOpenAIAPIBotSettings;
|
||||
recommend_node_ids?: string[];
|
||||
|
|
@ -384,7 +387,6 @@ export interface DomainAppSettings {
|
|||
export interface DomainAppSettingsResp {
|
||||
/** AI feedback */
|
||||
ai_feedback_settings?: DomainAIFeedbackSettings;
|
||||
auto_sitemap?: boolean;
|
||||
body_code?: string;
|
||||
btns?: unknown[];
|
||||
/** catalog settings */
|
||||
|
|
@ -419,6 +421,8 @@ export interface DomainAppSettingsResp {
|
|||
keyword?: string;
|
||||
/** LarkBot */
|
||||
lark_bot_settings?: DomainLarkBotSettings;
|
||||
/** MCP Server Settings */
|
||||
mcp_server_settings?: DomainMCPServerSettings;
|
||||
/** OpenAI API settings */
|
||||
openai_api_bot_settings?: DomainOpenAIAPIBotSettings;
|
||||
recommend_node_ids?: string[];
|
||||
|
|
@ -926,6 +930,17 @@ export interface DomainLink {
|
|||
url?: string;
|
||||
}
|
||||
|
||||
export interface DomainMCPServerSettings {
|
||||
docs_tool_settings?: DomainMCPToolSettings;
|
||||
is_enabled?: boolean;
|
||||
sample_auth?: DomainSimpleAuth;
|
||||
}
|
||||
|
||||
export interface DomainMCPToolSettings {
|
||||
desc?: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export type DomainMessageContent = Record<string, any>;
|
||||
|
||||
export interface DomainMetricsConfig {
|
||||
|
|
@ -1796,7 +1811,8 @@ export interface GetApiV1AuthGetParams {
|
|||
| "wechat_service_bot"
|
||||
| "discord_bot"
|
||||
| "wechat_official_account"
|
||||
| "openai_api";
|
||||
| "openai_api"
|
||||
| "mcp_server";
|
||||
}
|
||||
|
||||
export interface GetApiV1CommentParams {
|
||||
|
|
|
|||
|
|
@ -69,7 +69,6 @@ export interface KBDetail {
|
|||
recommend_node_ids: string[];
|
||||
desc: string;
|
||||
keyword: string;
|
||||
auto_sitemap: boolean;
|
||||
head_code: string;
|
||||
body_code: string;
|
||||
theme_mode?: 'light' | 'dark';
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ export enum ConstsSourceType {
|
|||
SourceTypeDiscordBot = "discord_bot",
|
||||
SourceTypeWechatOfficialAccount = "wechat_official_account",
|
||||
SourceTypeOpenAIAPI = "openai_api",
|
||||
SourceTypeMcpServer = "mcp_server",
|
||||
}
|
||||
|
||||
/** @format int32 */
|
||||
|
|
@ -591,7 +592,8 @@ export interface GetApiProV1AuthGetParams {
|
|||
| "wechat_service_bot"
|
||||
| "discord_bot"
|
||||
| "wechat_official_account"
|
||||
| "openai_api";
|
||||
| "openai_api"
|
||||
| "mcp_server";
|
||||
}
|
||||
|
||||
export interface DeleteApiProV1AuthGroupDeleteParams {
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ export enum DomainAppType {
|
|||
AppTypeOpenAIAPI = 9,
|
||||
AppTypeWecomAIBot = 10,
|
||||
AppTypeLarkBot = 11,
|
||||
AppTypeMcpServer = 12,
|
||||
}
|
||||
|
||||
export enum ConstsWatermarkSetting {
|
||||
|
|
@ -132,6 +133,7 @@ export enum ConstsSourceType {
|
|||
SourceTypeDiscordBot = "discord_bot",
|
||||
SourceTypeWechatOfficialAccount = "wechat_official_account",
|
||||
SourceTypeOpenAIAPI = "openai_api",
|
||||
SourceTypeMcpServer = "mcp_server",
|
||||
}
|
||||
|
||||
export enum ConstsNodeRagInfoStatus {
|
||||
|
|
@ -298,7 +300,6 @@ export interface DomainAppInfoResp {
|
|||
export interface DomainAppSettings {
|
||||
/** AI feedback */
|
||||
ai_feedback_settings?: DomainAIFeedbackSettings;
|
||||
auto_sitemap?: boolean;
|
||||
body_code?: string;
|
||||
btns?: unknown[];
|
||||
/** catalog settings */
|
||||
|
|
@ -333,6 +334,8 @@ export interface DomainAppSettings {
|
|||
keyword?: string;
|
||||
/** LarkBot */
|
||||
lark_bot_settings?: DomainLarkBotSettings;
|
||||
/** MCP Server Settings */
|
||||
mcp_server_settings?: DomainMCPServerSettings;
|
||||
/** OpenAI API Bot settings */
|
||||
openai_api_bot_settings?: DomainOpenAIAPIBotSettings;
|
||||
recommend_node_ids?: string[];
|
||||
|
|
@ -384,7 +387,6 @@ export interface DomainAppSettings {
|
|||
export interface DomainAppSettingsResp {
|
||||
/** AI feedback */
|
||||
ai_feedback_settings?: DomainAIFeedbackSettings;
|
||||
auto_sitemap?: boolean;
|
||||
body_code?: string;
|
||||
btns?: unknown[];
|
||||
/** catalog settings */
|
||||
|
|
@ -419,6 +421,8 @@ export interface DomainAppSettingsResp {
|
|||
keyword?: string;
|
||||
/** LarkBot */
|
||||
lark_bot_settings?: DomainLarkBotSettings;
|
||||
/** MCP Server Settings */
|
||||
mcp_server_settings?: DomainMCPServerSettings;
|
||||
/** OpenAI API settings */
|
||||
openai_api_bot_settings?: DomainOpenAIAPIBotSettings;
|
||||
recommend_node_ids?: string[];
|
||||
|
|
@ -926,6 +930,17 @@ export interface DomainLink {
|
|||
url?: string;
|
||||
}
|
||||
|
||||
export interface DomainMCPServerSettings {
|
||||
docs_tool_settings?: DomainMCPToolSettings;
|
||||
is_enabled?: boolean;
|
||||
sample_auth?: DomainSimpleAuth;
|
||||
}
|
||||
|
||||
export interface DomainMCPToolSettings {
|
||||
desc?: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export type DomainMessageContent = Record<string, any>;
|
||||
|
||||
export interface DomainMetricsConfig {
|
||||
|
|
@ -1796,7 +1811,8 @@ export interface GetApiV1AuthGetParams {
|
|||
| "wechat_service_bot"
|
||||
| "discord_bot"
|
||||
| "wechat_official_account"
|
||||
| "openai_api";
|
||||
| "openai_api"
|
||||
| "mcp_server";
|
||||
}
|
||||
|
||||
export interface GetApiV1CommentParams {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
"license": "ISC",
|
||||
"packageManager": "pnpm@10.12.1",
|
||||
"dependencies": {
|
||||
"@ctzhian/tiptap": "^1.13.4",
|
||||
"@ctzhian/tiptap": "^2.1.7",
|
||||
"@ctzhian/ui": "^7.0.5",
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@emotion/styled": "^11.14.1",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue