V4.12.0 features (#5435)

* add logs chart (#5352)

* charts

* chart data

* log chart

* delete

* rename api

* fix

* move api

* fix

* fix

* pro config

* fix

* feat: Repository interaction (#5356)

* feat: 1好像功能没问题了,明天再测

* feat: 2 解决了昨天遗留的bug,但全选按钮又bug了

* feat: 3 第三版,解决了全选功能bug

* feat: 4 第四版,下面改小细节

* feat: 5 我勒个痘

* feat: 6

* feat: 6 pr

* feat: 7

* feat: 8

* feat: 9

* feat: 10

* feat: 11

* feat: 12

* perf: checkbox ui

* refactor: tweak login loyout (#5357)

Co-authored-by: Archer <545436317@qq.com>

* login ui

* app chat log chart pro display (#5392)

* app chat log chart pro display

* add canopen props

* perf: pro tag tip

* perf: pro tag tip

* feat: openrouter provider (#5406)

* perf: login ui

* feat: openrouter provider

* provider

* perf: custom error throw

* perf: emb batch (#5407)

* perf: emb batch

* perf: vector retry

* doc

* doc (#5411)

* doc

* fix: team folder will add to workflow

* fix: generateToc shell

* Tool price (#5376)

* resolve conflicts for cherry-pick

* fix i18n

* Enhance system plugin template data structure and update ToolSelectModal to include CostTooltip component

* refactor: update systemKeyCost type to support array of objects in plugin and workflow types

* refactor: simplify systemKeyCost type across plugin and workflow types to a single number

* refactor: streamline systemKeyCost handling in plugin and workflow components

* fix

* fix

* perf: toolset price config;fix: workflow array selector ui (#5419)

* fix: workflow array selector ui

* update default model tip

* perf: toolset price config

* doc

* fix: test

* Refactor/chat (#5418)

* refactor: add homepage configuration; add home chat page; add side bar animated collapse and layout

* fix: fix lint rules

* chore: improve logics and code

* chore: more clearer logics

* chore: adjust api

---------

Co-authored-by: Archer <545436317@qq.com>

* perf: chat setting code

* del history

* logo image

* perf: home chat ui

* feat: enhance chat response handling with external links and user info (#5427)

* feat: enhance chat response handling with external links and user info

* fix

* cite code

* perf: toolset add in workflow

* fix: test

* fix: search paraentId

* Fix/chat (#5434)

* wip: rebase了upstream

* wip: adapt mobile UI

* fix: fix chat page logic and UI

* fix: fix UI and improve some logics

* fix: model selector missing logo; vision model to retrieve file

* perf: role selector

* fix: chat ui

* optimize export app chat log (#5436)

* doc

* chore: move components to proper directory; fix the api to get app list (#5437)

* chore: improve team app panel display form (#5438)

* feat: add home chat log tab

* chore: improve team app panel display form

* chore: improve log panel

* fix: spec

* doc

* fix: log permission

* fix: dataset schema required

* add loading status

* remove ui weight

* manage log

* fix: log detail per

* doc

* fix: log menu

* rename permission

* bg color

* fix: app log per

* fix: log key selector

* fix: log

* doc

---------

Co-authored-by: heheer <zhiyu44@qq.com>
Co-authored-by: colnii <1286949794@qq.com>
Co-authored-by: 伍闲犬 <76519998+xqvvu@users.noreply.github.com>
Co-authored-by: Ctrlz <143257420+ctrlz526@users.noreply.github.com>
Co-authored-by: 伍闲犬 <whoeverimf5@gmail.com>
Co-authored-by: heheer <heheer@sealos.io>
This commit is contained in:
Archer
2025-08-12 22:22:18 +08:00
committed by GitHub
parent c6e58291f7
commit c51395b2c8
239 changed files with 9336 additions and 3128 deletions

View File

@@ -14,8 +14,8 @@ export const defaultQAModels: LLMModelItemType[] = [
{
type: ModelTypeEnum.llm,
provider: 'OpenAI',
model: 'gpt-4o-mini',
name: 'gpt-4o-mini',
model: 'gpt-5',
name: 'gpt-5',
maxContext: 16000,
maxResponse: 16000,
quoteMaxToken: 13000,

View File

@@ -21,14 +21,19 @@ export type ModelProviderIdType =
| 'Hunyuan'
| 'Baichuan'
| 'StepFun'
| 'ai360'
| 'Yi'
| 'Siliconflow'
| 'PPIO'
| 'OpenRouter'
| 'Ollama'
| 'novita'
| 'vertexai'
| 'BAAI'
| 'FishAudio'
| 'Intern'
| 'Moka'
| 'Jina'
| 'Other';
export type ModelProviderType = {
@@ -133,17 +138,16 @@ export const ModelProviderList: ModelProviderType[] = [
name: i18nT('common:model_stepfun'),
avatar: 'model/stepfun'
},
{
id: 'ai360',
name: '360 AI',
avatar: 'model/ai360'
},
{
id: 'Yi',
name: i18nT('common:model_yi'),
avatar: 'model/yi'
},
{
id: 'Ollama',
name: 'Ollama',
avatar: 'model/ollama'
},
{
id: 'BAAI',
name: i18nT('common:model_baai'),
@@ -164,6 +168,31 @@ export const ModelProviderList: ModelProviderType[] = [
name: i18nT('common:model_moka'),
avatar: 'model/moka'
},
{
id: 'Ollama',
name: 'Ollama',
avatar: 'model/ollama'
},
{
id: 'OpenRouter',
name: 'OpenRouter',
avatar: 'model/openrouter'
},
{
id: 'vertexai',
name: 'vertexai',
avatar: 'model/vertexai'
},
{
id: 'novita',
name: 'novita',
avatar: 'model/novita'
},
{
id: 'Jina',
name: 'Jina',
avatar: 'model/jina'
},
{
id: 'AliCloud',
name: i18nT('common:model_alicloud'),

View File

@@ -13,7 +13,8 @@ export enum AppTypeEnum {
plugin = 'plugin',
httpPlugin = 'httpPlugin',
toolSet = 'toolSet',
tool = 'tool'
tool = 'tool',
hidden = 'hidden'
}
export const AppFolderTypeList = [AppTypeEnum.folder, AppTypeEnum.httpPlugin];
@@ -33,7 +34,7 @@ export const defaultWhisperConfig: AppWhisperConfigType = {
export const defaultQGConfig: AppQGConfigType = {
open: false,
model: 'gpt-4o-mini',
model: 'gpt-5',
customPrompt: ''
};

29
packages/global/core/app/logs/api.d.ts vendored Normal file
View File

@@ -0,0 +1,29 @@
import type { AppLogTimespanEnum } from './constants';
import type { AppChatLogAppData, AppChatLogChatData, AppChatLogUserData } from './type';
export type getChartDataBody = {
appId: string;
dateStart: Date;
dateEnd: Date;
source?: ChatSourceEnum[];
offset: number;
userTimespan: AppLogTimespanEnum;
chatTimespan: AppLogTimespanEnum;
appTimespan: AppLogTimespanEnum;
};
export type getChartDataResponse = {
userData: AppChatLogUserData;
chatData: AppChatLogChatData;
appData: AppChatLogAppData;
};
export type getTotalDataQuery = {
appId: string;
};
export type getTotalDataResponse = {
totalUsers: number;
totalChats: number;
totalPoints: number;
};

View File

@@ -47,3 +47,290 @@ export const DefaultAppLogKeys = [
{ key: AppLogKeysEnum.RESPONSE_TIME, enable: false },
{ key: AppLogKeysEnum.ERROR_COUNT, enable: false }
];
export enum AppLogTimespanEnum {
day = 'day',
week = 'week',
month = 'month',
quarter = 'quarter'
}
export const offsetOptions = [
{ label: 'T+1', value: '1' },
{ label: 'T+3', value: '3' },
{ label: 'T+7', value: '7' },
{ label: 'T+14', value: '14' }
];
export const fakeChartData = {
user: [
{
x: '07-30',
xLabel: '07-30',
userCount: 8,
newUserCount: 5,
retentionUserCount: 3,
points: 100,
sourceCountMap: {
test: 1,
online: 1,
share: 1,
api: 2,
cronJob: 0,
team: 1,
feishu: 0,
official_account: 1,
wecom: 1,
mcp: 0
}
},
{
x: '07-31',
xLabel: '07-31',
userCount: 12,
newUserCount: 8,
retentionUserCount: 4,
points: 160,
sourceCountMap: {
test: 2,
online: 2,
share: 2,
api: 3,
cronJob: 0,
team: 2,
feishu: 0,
official_account: 1,
wecom: 1,
mcp: 0
}
},
{
x: '08-01',
xLabel: '08-01',
userCount: 18,
newUserCount: 12,
retentionUserCount: 6,
points: 220,
sourceCountMap: {
test: 2,
online: 3,
share: 2,
api: 4,
cronJob: 1,
team: 2,
feishu: 0,
official_account: 1,
wecom: 1,
mcp: 0
}
},
{
x: '08-02',
xLabel: '08-02',
userCount: 15,
newUserCount: 7,
retentionUserCount: 8,
points: 180,
sourceCountMap: {
test: 1,
online: 2,
share: 2,
api: 3,
cronJob: 1,
team: 2,
feishu: 1,
official_account: 1,
wecom: 0,
mcp: 0
}
},
{
x: '08-03',
xLabel: '08-03',
userCount: 20,
newUserCount: 15,
retentionUserCount: 5,
points: 250,
sourceCountMap: {
test: 2,
online: 4,
share: 2,
api: 5,
cronJob: 1,
team: 2,
feishu: 1,
official_account: 1,
wecom: 0,
mcp: 0
}
},
{
x: '08-04',
xLabel: '08-04',
userCount: 14,
newUserCount: 6,
retentionUserCount: 8,
points: 170,
sourceCountMap: {
test: 1,
online: 3,
share: 1,
api: 4,
cronJob: 1,
team: 2,
feishu: 1,
official_account: 1,
wecom: 0,
mcp: 0
}
},
{
x: '08-05',
xLabel: '08-05',
userCount: 22,
newUserCount: 17,
retentionUserCount: 5,
points: 280,
sourceCountMap: {
test: 2,
online: 5,
share: 2,
api: 6,
cronJob: 1,
team: 2,
feishu: 1,
official_account: 1,
wecom: 0,
mcp: 0
}
}
],
chat: [
{
x: '07-30',
xLabel: '07-30',
chatItemCount: 20,
chatCount: 12,
pointsPerChat: 5.5,
errorCount: 2,
errorRate: 0.1
},
{
x: '07-31',
xLabel: '07-31',
chatItemCount: 35,
chatCount: 20,
pointsPerChat: 8.0,
errorCount: 1,
errorRate: 0.028
},
{
x: '08-01',
xLabel: '08-01',
chatItemCount: 50,
chatCount: 30,
pointsPerChat: 7.3,
errorCount: 3,
errorRate: 0.06
},
{
x: '08-02',
xLabel: '08-02',
chatItemCount: 28,
chatCount: 18,
pointsPerChat: 6.2,
errorCount: 1,
errorRate: 0.036
},
{
x: '08-03',
xLabel: '08-03',
chatItemCount: 60,
chatCount: 40,
pointsPerChat: 7.8,
errorCount: 4,
errorRate: 0.067
},
{
x: '08-04',
xLabel: '08-04',
chatItemCount: 32,
chatCount: 22,
pointsPerChat: 6.5,
errorCount: 2,
errorRate: 0.062
},
{
x: '08-05',
xLabel: '08-05',
chatItemCount: 55,
chatCount: 35,
pointsPerChat: 8.1,
errorCount: 1,
errorRate: 0.018
}
],
app: [
{
x: '07-30',
xLabel: '07-30',
goodFeedBackCount: 2,
badFeedBackCount: 1,
avgDuration: 2.5
},
{
x: '07-31',
xLabel: '07-31',
goodFeedBackCount: 5,
badFeedBackCount: 2,
avgDuration: 2.1
},
{
x: '08-01',
xLabel: '08-01',
goodFeedBackCount: 3,
badFeedBackCount: 1,
avgDuration: 2.8
},
{
x: '08-02',
xLabel: '08-02',
goodFeedBackCount: 6,
badFeedBackCount: 3,
avgDuration: 2.0
},
{
x: '08-03',
xLabel: '08-03',
goodFeedBackCount: 4,
badFeedBackCount: 2,
avgDuration: 2.7
},
{
x: '08-04',
xLabel: '08-04',
goodFeedBackCount: 7,
badFeedBackCount: 1,
avgDuration: 2.3
},
{
x: '08-05',
xLabel: '08-05',
goodFeedBackCount: 3,
badFeedBackCount: 2,
avgDuration: 2.9
}
],
cumulative: {
userCount: 109,
points: 1360,
chatItemCount: 280,
chatCount: 177,
pointsPerChat: 7.2,
errorCount: 14,
errorRate: 0.053,
goodFeedBackCount: 30,
badFeedBackCount: 12,
avgDuration: 2.47
}
};

View File

@@ -1,3 +1,4 @@
import type { ChatSourceEnum } from '../../core/chat/constants';
import type { AppLogKeysEnum } from './constants';
export type AppLogKeysType = {
@@ -10,3 +11,55 @@ export type AppLogKeysSchemaType = {
appId: string;
logKeys: AppLogKeysType[];
};
export type AppChatLogSchema = {
_id: string;
appId: string;
teamId: string;
chatId: string;
userId: string;
source: string;
sourceName?: string;
createTime: Date;
updateTime: Date;
chatItemCount: number;
errorCount: number;
totalPoints: number;
goodFeedbackCount: number;
badFeedbackCount: number;
totalResponseTime: number;
isFirstChat: boolean; // whether this is the user's first session in the app
};
export type AppChatLogUserData = {
timestamp: number;
summary: {
userCount: number;
newUserCount: number;
retentionUserCount: number;
points: number;
sourceCountMap: Record<ChatSourceEnum, number>;
};
}[];
export type AppChatLogChatData = {
timestamp: number;
summary: {
chatItemCount: number;
chatCount: number;
errorCount: number;
points: number;
};
}[];
export type AppChatLogAppData = {
timestamp: number;
summary: {
goodFeedBackCount: number;
badFeedBackCount: number;
chatCount: number;
totalResponseTime: number;
};
}[];

View File

@@ -0,0 +1,59 @@
import dayjs from 'dayjs';
import { AppLogTimespanEnum } from './constants';
export const formatDateByTimespan = (timestamp: number, timespan: AppLogTimespanEnum) => {
const date = new Date(timestamp);
if (timespan === AppLogTimespanEnum.day) {
return {
date: dayjs(date).format('MM-DD'),
xLabel: dayjs(date).format('YYYY-MM-DD')
};
} else if (timespan === AppLogTimespanEnum.week) {
const startStr = dayjs(date).format('MM/DD');
const endStr = dayjs(date).add(6, 'day').format('MM/DD');
return {
date: `${startStr}-${endStr}`,
xLabel: `${startStr}-${endStr}`
};
} else if (timespan === AppLogTimespanEnum.month) {
return {
date: dayjs(date).format('YYYY-MM'),
xLabel: dayjs(date).format('YYYY-MM')
};
} else {
const year = date.getFullYear();
const quarter = Math.ceil((date.getMonth() + 1) / 3);
return {
date: `${year}Q${quarter}`,
xLabel: `${year}Q${quarter}`
};
}
};
export const calculateOffsetDates = (
start: Date,
end: Date,
offset: number,
timespan: AppLogTimespanEnum
) => {
const offsetStart = new Date(start);
const offsetEnd = new Date(end);
if (timespan === AppLogTimespanEnum.quarter) {
offsetStart.setMonth(offsetStart.getMonth() + offset * 3);
offsetEnd.setMonth(offsetEnd.getMonth() + offset * 3);
} else if (timespan === AppLogTimespanEnum.month) {
offsetStart.setMonth(offsetStart.getMonth() + offset);
offsetEnd.setMonth(offsetEnd.getMonth() + offset);
} else if (timespan === AppLogTimespanEnum.week) {
offsetStart.setDate(offsetStart.getDate() + offset * 7);
offsetEnd.setDate(offsetEnd.getDate() + offset * 7);
} else {
offsetStart.setDate(offsetStart.getDate() + offset);
offsetEnd.setDate(offsetEnd.getDate() + offset);
}
return { offsetStart, offsetEnd };
};

View File

@@ -19,6 +19,7 @@ export type PluginRuntimeType = {
nodes: StoreNodeItemType[];
edges: StoreEdgeItemType[];
currentCost?: number;
systemKeyCost?: number;
hasTokenFee?: boolean;
};
@@ -44,6 +45,7 @@ export type SystemPluginTemplateItemType = WorkflowTemplateType & {
// commercial plugin config
originCost?: number; // n points/one time
currentCost?: number;
systemKeyCost?: number;
hasTokenFee?: boolean;
pluginOrder?: number;
@@ -52,6 +54,7 @@ export type SystemPluginTemplateItemType = WorkflowTemplateType & {
// Admin config
inputList?: FlowNodeInputItemType['inputList'];
inputListVal?: Record<string, any>;
hasSystemSecret?: boolean;
};

View File

@@ -13,7 +13,7 @@ import pluginErrList from '../../common/error/code/plugin';
export const getDefaultAppForm = (): AppSimpleEditFormType => {
return {
aiSettings: {
model: 'gpt-4o-mini',
model: '',
systemPrompt: '',
temperature: 0,
isResponseAnswerText: true,

View File

@@ -44,34 +44,44 @@ export enum ChatSourceEnum {
export const ChatSourceMap = {
[ChatSourceEnum.test]: {
name: i18nT('common:core.chat.logs.test')
name: i18nT('common:core.chat.logs.test'),
color: '#5E8FFF'
},
[ChatSourceEnum.online]: {
name: i18nT('common:core.chat.logs.online')
name: i18nT('common:core.chat.logs.online'),
color: '#47B2FF'
},
[ChatSourceEnum.share]: {
name: i18nT('common:core.chat.logs.share')
name: i18nT('common:core.chat.logs.share'),
color: '#9E8DFB'
},
[ChatSourceEnum.api]: {
name: i18nT('common:core.chat.logs.api')
name: i18nT('common:core.chat.logs.api'),
color: '#D389F6'
},
[ChatSourceEnum.cronJob]: {
name: i18nT('chat:source_cronJob')
name: i18nT('chat:source_cronJob'),
color: '#FF81AE'
},
[ChatSourceEnum.team]: {
name: i18nT('common:core.chat.logs.team')
name: i18nT('common:core.chat.logs.team'),
color: '#42CFC6'
},
[ChatSourceEnum.feishu]: {
name: i18nT('common:core.chat.logs.feishu')
name: i18nT('common:core.chat.logs.feishu'),
color: '#39CC83'
},
[ChatSourceEnum.official_account]: {
name: i18nT('common:core.chat.logs.official_account')
name: i18nT('common:core.chat.logs.official_account'),
color: '#FDB022'
},
[ChatSourceEnum.wecom]: {
name: i18nT('common:core.chat.logs.wecom')
name: i18nT('common:core.chat.logs.wecom'),
color: '#FD853A'
},
[ChatSourceEnum.mcp]: {
name: i18nT('common:core.chat.logs.mcp')
name: i18nT('common:core.chat.logs.mcp'),
color: '#F97066'
}
};

View File

@@ -0,0 +1,28 @@
export type ChatSettingSchema = {
_id: string;
appId: string;
teamId: string;
slogan: string;
dialogTips: string;
homeTabTitle: string;
wideLogoUrl?: string;
squareLogoUrl?: string;
selectedTools: {
pluginId: string;
name: string;
avatar: string;
inputs?: Record<`${NodeInputKeyEnum}` | string, any>;
}[];
};
export type ChatSettingUpdateParams = {
slogan?: string;
dialogTips?: string;
homeTabTitle?: string;
wideLogoUrl?: string;
squareLogoUrl?: string;
selectedTools: {
pluginId: string;
inputs?: Record<`${NodeInputKeyEnum}` | string, any>;
}[];
};

View File

@@ -8,7 +8,7 @@ import type {
ChatStatusEnum
} from './constants';
import type { FlowNodeTypeEnum } from '../workflow/node/constant';
import type { NodeOutputKeyEnum } from '../workflow/constants';
import type { NodeInputKeyEnum, NodeOutputKeyEnum } from '../workflow/constants';
import type { DispatchNodeResponseKeyEnum } from '../workflow/runtime/constants';
import type { AppSchema, VariableItemType } from '../app/type';
import { AppChatConfigType } from '../app/type';
@@ -18,6 +18,7 @@ import type { DispatchNodeResponseType } from '../workflow/runtime/type.d';
import type { ChatBoxInputType } from '../../../../projects/app/src/components/core/chat/ChatContainer/ChatBox/type';
import type { WorkflowInteractiveResponseType } from '../workflow/template/system/interactive/type';
import type { FlowNodeInputItemType } from '../workflow/type/io';
import type { FlowNodeTemplateType } from '../workflow/type/node.d';
export type ChatSchema = {
_id: string;
@@ -130,6 +131,7 @@ export type ResponseTagItemType = {
totalQuoteList?: SearchDataResponseItemType[];
llmModuleAccount?: number;
historyPreviewLength?: number;
toolCiteLinks?: ToolCiteLinksType[];
};
export type ChatItemType = (UserChatItemType | SystemChatItemType | AIChatItemType) & {
@@ -149,7 +151,6 @@ export type ChatSiteItemType = (UserChatItemType | SystemChatItemType | AIChatIt
errorMsg?: string;
} & ChatBoxInputType &
ResponseTagItemType;
/* --------- team chat --------- */
export type ChatAppListSchema = {
apps: AppType[];
@@ -196,6 +197,10 @@ export type ToolModuleResponseItemType = {
functionName: string;
};
export type ToolCiteLinksType = {
name: string;
url: string;
};
/* dispatch run time */
export type RuntimeUserPromptType = {
files: UserChatItemValueItemType['file'][];

View File

@@ -26,7 +26,7 @@ export const getLLMDefaultChunkSize = (model?: LLMModelItemType) => {
export const getLLMMaxChunkSize = (model?: LLMModelItemType) => {
if (!model) return 8000;
return Math.max(model.maxContext - model.maxResponse, 2000);
return Math.max(model.maxContext, 4000);
};
// Index size

View File

@@ -29,6 +29,7 @@ import type {
WorkflowInteractiveResponseType
} from '../template/system/interactive/type';
import type { SearchDataResponseItemType } from '../../dataset/type';
import type { localeType } from '../../../common/i18n/type';
export type ExternalProviderType = {
openaiAccount?: OpenaiAccountType;
externalWorkflowVariables?: Record<string, string>;
@@ -37,6 +38,7 @@ export type ExternalProviderType = {
/* workflow props */
export type ChatDispatchProps = {
res?: NextApiResponse;
lang?: localeType;
requestOrigin?: string;
mode: 'test' | 'chat' | 'debug';
timezone: string;
@@ -49,6 +51,10 @@ export type ChatDispatchProps = {
isChildApp?: boolean;
};
runningUserInfo: {
username: string;
teamName: string;
memberName: string;
contact: string;
teamId: string;
tmbId: string;
};

View File

@@ -77,6 +77,7 @@ export type FlowNodeCommonType = {
// Not store, just computed
currentCost?: number;
systemKeyCost?: number;
hasTokenFee?: boolean;
hasSystemSecret?: boolean;
};
@@ -135,6 +136,7 @@ export type NodeTemplateListItemType = {
author?: string;
unique?: boolean; // 唯一的
currentCost?: number; // 当前积分消耗
systemKeyCost?: number; // 系统密钥费用,统一为数字
hasTokenFee?: boolean; // 是否配置积分
instructions?: string; // 使用说明
courseUrl?: string; // 教程链接