mirror of
https://github.com/csunny/DB-GPT.git
synced 2025-07-24 12:45:45 +00:00
feat: UI component rendering in agent dialog mode (#1083)
Co-authored-by: csunny <cfqsunny@163.com>
This commit is contained in:
parent
674104eb7c
commit
0936856c3a
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@
|
||||
self.__BUILD_MANIFEST=function(s,c,a,t,e,n,k,d,f,h,b,i,u,j){return{__rewrites:{beforeFiles:[],afterFiles:[],fallback:[]},"/":["static/chunks/29107295-90b90cb30c825230.js",s,c,t,a,k,d,f,b,"static/chunks/861-78929b4f98dbbfd6.js","static/chunks/161-96143606b49cf4a1.js","static/chunks/pages/index-06183caf17230eba.js"],"/_error":["static/chunks/pages/_error-dee72aff9b2e2c12.js"],"/agent":[s,c,a,e,k,n,"static/chunks/pages/agent-2503b783a880d8dd.js"],"/chat":["static/chunks/pages/chat-a869c66578892120.js"],"/database":[s,c,t,a,e,n,f,h,"static/chunks/643-467e61c6d77597ec.js","static/chunks/pages/database-3f935c41115f9437.js"],"/knowledge":[i,s,c,a,e,k,n,f,u,h,b,"static/chunks/221-c10c5bf4eb885ce7.js","static/chunks/549-a7015f243d580f77.js","static/chunks/pages/knowledge-1848ba7d6a088e19.js"],"/knowledge/chunk":[s,t,e,d,n,"static/chunks/pages/knowledge/chunk-866a4383a7183b98.js"],"/models":[i,s,c,t,a,j,h,"static/chunks/pages/models-12ab4fc3d6a6b72c.js"],"/prompt":[s,c,t,a,j,d,u,"static/chunks/346-8340afd21e100a59.js","static/chunks/607-ecec81b815dc298b.js","static/chunks/pages/prompt-09aa8ca136c58eb8.js"],sortedPages:["/","/_app","/_error","/agent","/chat","/database","/knowledge","/knowledge/chunk","/models","/prompt"]}}("static/chunks/113-15fc0b8bd2b5b9a1.js","static/chunks/17-26dc9ac6c4adec30.js","static/chunks/479-784a3b3622f6eb73.js","static/chunks/9-31700d34ab596955.js","static/chunks/442-d388a67ef689277f.js","static/chunks/813-cce9482e33f2430c.js","static/chunks/553-a89ad624ca0f1ffa.js","static/chunks/810-120b98a5da95cba3.js","static/chunks/411-b5d3e7f64bee2335.js","static/chunks/928-5a69f9ff4dc4129f.js","static/chunks/234-42f62dc360b2d9e4.js","static/chunks/75fc9c18-a784766a129ec5fb.js","static/chunks/45-9ff739c09925ea35.js","static/chunks/947-5980a3ff49069ddd.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
|
@ -0,0 +1 @@
|
||||
self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()
|
File diff suppressed because one or more lines are too long
29
dbgpt/app/static/_next/static/chunks/341.9dc08d6acf941db1.js
Normal file
29
dbgpt/app/static/_next/static/chunks/341.9dc08d6acf941db1.js
Normal file
File diff suppressed because one or more lines are too long
537
dbgpt/app/static/_next/static/chunks/739.c531bc8e1d8566bc.js
Normal file
537
dbgpt/app/static/_next/static/chunks/739.c531bc8e1d8566bc.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
dbgpt/app/static/_next/static/css/9a8743052c8f63f7.css
Normal file
3
dbgpt/app/static/_next/static/css/9a8743052c8f63f7.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -16,10 +16,10 @@ interface IChatContext {
|
||||
model: string;
|
||||
dbParam?: string;
|
||||
modelList: Array<string>;
|
||||
agentList: string[];
|
||||
agent: string;
|
||||
dialogueList?: DialogueListResponse;
|
||||
setAgent?: (val: string) => void;
|
||||
setMode: (mode: ThemeMode) => void;
|
||||
setAgentList?: (val: string[]) => void;
|
||||
setModel: (val: string) => void;
|
||||
setIsContract: (val: boolean) => void;
|
||||
setIsMenuExpand: (val: boolean) => void;
|
||||
@ -47,8 +47,8 @@ const ChatContext = createContext<IChatContext>({
|
||||
model: '',
|
||||
dbParam: undefined,
|
||||
dialogueList: [],
|
||||
agentList: [],
|
||||
setAgentList: () => {},
|
||||
agent: '',
|
||||
setAgent: () => {},
|
||||
setModel: () => {},
|
||||
setIsContract: () => {},
|
||||
setIsMenuExpand: () => {},
|
||||
@ -72,7 +72,7 @@ const ChatContextProvider = ({ children }: { children: React.ReactElement }) =>
|
||||
const [model, setModel] = useState<string>('');
|
||||
const [isMenuExpand, setIsMenuExpand] = useState<boolean>(scene !== 'chat_dashboard');
|
||||
const [dbParam, setDbParam] = useState<string>(db_param);
|
||||
const [agentList, setAgentList] = useState<string[]>([]);
|
||||
const [agent, setAgent] = useState<string>('');
|
||||
const [history, setHistory] = useState<ChatHistoryResponse>([]);
|
||||
const [docId, setDocId] = useState<number>();
|
||||
const [mode, setMode] = useState<ThemeMode>('light');
|
||||
@ -91,6 +91,13 @@ const ChatContextProvider = ({ children }: { children: React.ReactElement }) =>
|
||||
},
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (dialogueList.length && scene === 'chat_agent') {
|
||||
const agent = dialogueList.find((item) => item.conv_uid === chatId)?.select_param;
|
||||
agent && setAgent(agent);
|
||||
}
|
||||
}, [dialogueList, scene, chatId]);
|
||||
|
||||
const { data: modelList = [] } = useRequest(async () => {
|
||||
const [, res] = await apiInterceptors(getUsableModels());
|
||||
return res ?? [];
|
||||
@ -114,10 +121,10 @@ const ChatContextProvider = ({ children }: { children: React.ReactElement }) =>
|
||||
model,
|
||||
dbParam: dbParam || db_param,
|
||||
dialogueList,
|
||||
agentList,
|
||||
agent,
|
||||
setAgent,
|
||||
mode,
|
||||
setMode,
|
||||
setAgentList,
|
||||
setModel,
|
||||
setIsContract,
|
||||
setIsMenuExpand,
|
||||
|
@ -179,12 +179,15 @@ const en = {
|
||||
Retry: 'Retry',
|
||||
Load_more: 'load more',
|
||||
new_chat: 'New Chat',
|
||||
choice_agent_tip: 'Please choose an agent',
|
||||
no_context_tip: 'Please enter your question',
|
||||
Terminal: 'Terminal',
|
||||
} as const;
|
||||
|
||||
type I18nKeys = keyof typeof en;
|
||||
export type I18nKeys = keyof typeof en;
|
||||
|
||||
export interface Resources {
|
||||
translation: Record<I18nKeys, string> & { [key: string]: string };
|
||||
translation: Record<I18nKeys, string>;
|
||||
}
|
||||
|
||||
const zh: Resources['translation'] = {
|
||||
@ -364,6 +367,9 @@ const zh: Resources['translation'] = {
|
||||
Retry: '重试',
|
||||
Load_more: '加载更多',
|
||||
new_chat: '创建会话',
|
||||
choice_agent_tip: '请选择代理',
|
||||
no_context_tip: '请输入你的问题',
|
||||
Terminal: '终端',
|
||||
} as const;
|
||||
|
||||
i18n.use(initReactI18next).init({
|
||||
|
@ -11,7 +11,13 @@ import {
|
||||
PostEditorSQLRunParams,
|
||||
PostSQLEditorSubmitParams,
|
||||
} from '@/types/editor';
|
||||
import { PostAgentHubUpdateParams, PostAgentQueryParams, PostAgentPluginResponse, PostAgentMyPluginResponse } from '@/types/agent';
|
||||
import {
|
||||
PostAgentHubUpdateParams,
|
||||
PostAgentQueryParams,
|
||||
PostAgentPluginResponse,
|
||||
PostAgentMyPluginResponse,
|
||||
GetDBGPTsListResponse,
|
||||
} from '@/types/agent';
|
||||
import {
|
||||
AddKnowledgeParams,
|
||||
ArgumentsParams,
|
||||
@ -211,6 +217,9 @@ export const postAgentUpload = (user = '', data: FormData, config?: Omit<AxiosRe
|
||||
...config,
|
||||
});
|
||||
};
|
||||
export const getDbgptsList = () => {
|
||||
return GET<undefined, GetDBGPTsListResponse>('/api/v1/dbgpts/list');
|
||||
};
|
||||
|
||||
/** chat feedback **/
|
||||
export const getChatFeedBackSelect = () => {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Empty, Row, Col, Select, Tooltip } from 'antd';
|
||||
import { Advice, Advisor } from '@antv/ava';
|
||||
import { Chart } from '@berryv/g2-react';
|
||||
import i18n from '@/app/i18n';
|
||||
import i18n, { I18nKeys } from '@/app/i18n';
|
||||
import { customizeAdvisor, getVisAdvices } from './advisor/pipeline';
|
||||
import { useContext, useEffect, useMemo, useState } from 'react';
|
||||
import { defaultAdvicesFilter } from './advisor/utils';
|
||||
@ -62,6 +62,8 @@ export const AutoChart = (props: AutoChartProps) => {
|
||||
options={{
|
||||
...spec,
|
||||
theme: mode,
|
||||
autoFit: true,
|
||||
height: 300,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
@ -83,7 +85,7 @@ export const AutoChart = (props: AutoChartProps) => {
|
||||
size={'small'}
|
||||
>
|
||||
{advices?.map((item) => {
|
||||
const name = i18n.t(item.type);
|
||||
const name = i18n.t(item.type as I18nKeys);
|
||||
|
||||
return (
|
||||
<Option key={item.type} value={item.type}>
|
||||
|
40
web/components/chat/agent-content.tsx
Normal file
40
web/components/chat/agent-content.tsx
Normal file
@ -0,0 +1,40 @@
|
||||
import { ChatContext } from '@/app/chat-context';
|
||||
import { IChatDialogueMessageSchema } from '@/types/chat';
|
||||
import classNames from 'classnames';
|
||||
import { memo, useContext } from 'react';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import markdownComponents from './chat-content/config';
|
||||
import rehypeRaw from 'rehype-raw';
|
||||
|
||||
interface Props {
|
||||
content: IChatDialogueMessageSchema;
|
||||
}
|
||||
|
||||
function formatMarkdownVal(val: string) {
|
||||
return val.replace(/<table(\w*=[^>]+)>/gi, '<table $1>').replace(/<tr(\w*=[^>]+)>/gi, '<tr $1>');
|
||||
}
|
||||
|
||||
function AgentContent({ content }: Props) {
|
||||
const { scene } = useContext(ChatContext);
|
||||
|
||||
const isView = content.role === 'view';
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames('relative w-full p-2 md:p-4 rounded-xl break-words', {
|
||||
'bg-white dark:bg-[#232734]': isView,
|
||||
'lg:w-full xl:w-full pl-0': ['chat_with_db_execute', 'chat_dashboard'].includes(scene),
|
||||
})}
|
||||
>
|
||||
{isView ? (
|
||||
<ReactMarkdown components={markdownComponents} rehypePlugins={[rehypeRaw]}>
|
||||
{formatMarkdownVal(content.context)}
|
||||
</ReactMarkdown>
|
||||
) : (
|
||||
<div className="">{content.context}</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default memo(AgentContent);
|
@ -15,7 +15,7 @@ import { getInitMessage } from '@/utils';
|
||||
|
||||
const ChatContainer = () => {
|
||||
const searchParams = useSearchParams();
|
||||
const { scene, chatId, model, setModel, history, setHistory } = useContext(ChatContext);
|
||||
const { scene, chatId, model, agent, setModel, history, setHistory } = useContext(ChatContext);
|
||||
const chat = useChat({});
|
||||
const initMessage = (searchParams && searchParams.get('initMessage')) ?? '';
|
||||
|
||||
@ -95,7 +95,7 @@ const ChatContainer = () => {
|
||||
});
|
||||
});
|
||||
},
|
||||
[history, chat, model],
|
||||
[history, chat, chatId, model, agent, scene],
|
||||
);
|
||||
|
||||
return (
|
||||
@ -122,7 +122,7 @@ const ChatContainer = () => {
|
||||
)}
|
||||
{/** chat panel */}
|
||||
<div
|
||||
className={classNames('flex flex-1 flex-col', {
|
||||
className={classNames('flex flex-1 flex-col overflow-hidden', {
|
||||
'px-0 xl:pl-4 h-2/5 w-full xl:w-auto xl:h-full border-t xl:border-t-0 xl:border-l dark:border-gray-800': scene === 'chat_dashboard',
|
||||
'h-full lg:px-8': scene !== 'chat_dashboard',
|
||||
})}
|
||||
|
39
web/components/chat/chat-content/agent-messages.tsx
Normal file
39
web/components/chat/chat-content/agent-messages.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import markdownComponents from './config';
|
||||
import { renderModelIcon } from '../header/model-selector';
|
||||
import { SwapRightOutlined } from '@ant-design/icons';
|
||||
|
||||
interface Props {
|
||||
data: {
|
||||
sender: string;
|
||||
receiver: string;
|
||||
model: string | null;
|
||||
markdown: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
function AgentMessages({ data }: Props) {
|
||||
if (!data || !data.length) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{data.map((item, index) => (
|
||||
<div key={index} className="rounded my-4 md:my-6">
|
||||
<div className="flex items-center mb-3 text-sm">
|
||||
{item.model ? renderModelIcon(item.model) : <div className="rounded-full w-6 h-6 bg-gray-100" />}
|
||||
<div className="ml-2 opacity-70">
|
||||
{item.sender}
|
||||
<SwapRightOutlined className="mx-2 text-base" />
|
||||
{item.receiver}
|
||||
</div>
|
||||
</div>
|
||||
<div className="whitespace-normal text-sm">
|
||||
<ReactMarkdown components={markdownComponents}>{item.markdown}</ReactMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default AgentMessages;
|
46
web/components/chat/chat-content/agent-plans.tsx
Normal file
46
web/components/chat/chat-content/agent-plans.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import { CaretRightOutlined, CheckOutlined, ClockCircleOutlined } from '@ant-design/icons';
|
||||
import { Collapse } from 'antd';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import markdownComponents from './config';
|
||||
|
||||
interface Props {
|
||||
data: {
|
||||
name: string;
|
||||
num: number;
|
||||
status: 'complete' | 'todo';
|
||||
agent: string;
|
||||
markdown: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
function AgentPlans({ data }: Props) {
|
||||
if (!data || !data.length) return null;
|
||||
|
||||
return (
|
||||
<Collapse
|
||||
bordered
|
||||
className="my-3"
|
||||
expandIcon={({ isActive }) => <CaretRightOutlined rotate={isActive ? 90 : 0} />}
|
||||
items={data.map((item, index) => {
|
||||
return {
|
||||
key: index,
|
||||
label: (
|
||||
<div className="whitespace-normal">
|
||||
<span>
|
||||
{item.name} - {item.agent}
|
||||
</span>
|
||||
{item.status === 'complete' ? (
|
||||
<CheckOutlined className="!text-green-500 ml-2" />
|
||||
) : (
|
||||
<ClockCircleOutlined className="!text-gray-500 ml-2" />
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
children: <ReactMarkdown components={markdownComponents}>{item.markdown}</ReactMarkdown>,
|
||||
};
|
||||
})}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default AgentPlans;
|
38
web/components/chat/chat-content/chart-view.tsx
Normal file
38
web/components/chat/chat-content/chart-view.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import { Datum } from '@antv/ava';
|
||||
import { Table, Tabs, TabsProps } from 'antd';
|
||||
import React from 'react';
|
||||
import { format } from 'sql-formatter';
|
||||
import { AutoChart, BackEndChartType, getChartType } from '@/components/chart/autoChart';
|
||||
import { CodePreview } from './code-preview';
|
||||
|
||||
function ChartView({ data, type, sql }: { data: Datum[]; type: BackEndChartType; sql: string }) {
|
||||
const columns = data?.[0]
|
||||
? Object.keys(data?.[0])?.map((item) => {
|
||||
return {
|
||||
title: item,
|
||||
dataIndex: item,
|
||||
key: item,
|
||||
};
|
||||
})
|
||||
: [];
|
||||
const ChartItem = {
|
||||
key: 'chart',
|
||||
label: 'Chart',
|
||||
children: <AutoChart data={data} chartType={getChartType(type)} />,
|
||||
};
|
||||
const SqlItem = {
|
||||
key: 'sql',
|
||||
label: 'SQL',
|
||||
children: <CodePreview language="sql" code={format(sql, { language: 'mysql' }) as string} />,
|
||||
};
|
||||
const DataItem = {
|
||||
key: 'data',
|
||||
label: 'Data',
|
||||
children: <Table dataSource={data} columns={columns} />,
|
||||
};
|
||||
const TabItems: TabsProps['items'] = type === 'response_table' ? [DataItem, SqlItem] : [ChartItem, SqlItem, DataItem];
|
||||
|
||||
return <Tabs defaultActiveKey={type === 'response_table' ? 'data' : 'chart'} items={TabItems} size="small" />;
|
||||
}
|
||||
|
||||
export default ChartView;
|
@ -3,10 +3,18 @@ import { CopyOutlined } from '@ant-design/icons';
|
||||
import { oneDark, coldarkDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { useContext } from 'react';
|
||||
import { CSSProperties, useContext } from 'react';
|
||||
import { ChatContext } from '@/app/chat-context';
|
||||
|
||||
export function CodePreview({ code, language }: { code: string; language: string }) {
|
||||
interface Props {
|
||||
code: string;
|
||||
language: string;
|
||||
customStyle?: CSSProperties;
|
||||
light?: { [key: string]: CSSProperties };
|
||||
dark?: { [key: string]: CSSProperties };
|
||||
}
|
||||
|
||||
export function CodePreview({ code, light, dark, language, customStyle }: Props) {
|
||||
const { mode } = useContext(ChatContext);
|
||||
|
||||
return (
|
||||
@ -20,7 +28,7 @@ export function CodePreview({ code, language }: { code: string; language: string
|
||||
message[success ? 'success' : 'error'](success ? 'Copy success' : 'Copy failed');
|
||||
}}
|
||||
/>
|
||||
<SyntaxHighlighter language={language} style={mode === 'dark' ? coldarkDark : oneDark}>
|
||||
<SyntaxHighlighter customStyle={customStyle} language={language} style={mode === 'dark' ? dark ?? coldarkDark : light ?? oneDark}>
|
||||
{code}
|
||||
</SyntaxHighlighter>
|
||||
</div>
|
||||
|
@ -8,6 +8,13 @@ import { CodePreview } from './code-preview';
|
||||
import { Datum } from '@antv/ava';
|
||||
import rehypeRaw from 'rehype-raw';
|
||||
import { IChunk } from '@/types/knowledge';
|
||||
import AgentPlans from './agent-plans';
|
||||
import AgentMessages from './agent-messages';
|
||||
import VisConvertError from './vis-convert-error';
|
||||
import VisChart from './vis-chart';
|
||||
import VisDashboard from './vis-dashboard';
|
||||
import VisPlugin from './vis-plugin';
|
||||
import VisCode from './vis-code';
|
||||
|
||||
type MarkdownComponent = Parameters<typeof ReactMarkdown>['0']['components'];
|
||||
|
||||
@ -27,18 +34,82 @@ function matchCustomeTagValues(context: string) {
|
||||
|
||||
const basicComponents: MarkdownComponent = {
|
||||
code({ inline, node, className, children, style, ...props }) {
|
||||
const content = String(children);
|
||||
/**
|
||||
* @description
|
||||
* In some cases, tags are nested within code syntax,
|
||||
* so it is necessary to extract the tags present in the code block and render them separately.
|
||||
*/
|
||||
const { context, matchValues } = matchCustomeTagValues(Array.isArray(children) ? children.join('\n') : children);
|
||||
const match = /language-(\w+)/.exec(className || '');
|
||||
const { context, matchValues } = matchCustomeTagValues(content);
|
||||
const lang = className?.replace('language-', '') || 'javascript';
|
||||
|
||||
if (lang === 'agent-plans') {
|
||||
try {
|
||||
const data = JSON.parse(content) as Parameters<typeof AgentPlans>[0]['data'];
|
||||
return <AgentPlans data={data} />;
|
||||
} catch (e) {
|
||||
return <CodePreview language={lang} code={content} />;
|
||||
}
|
||||
}
|
||||
|
||||
if (lang === 'agent-messages') {
|
||||
try {
|
||||
const data = JSON.parse(content) as Parameters<typeof AgentMessages>[0]['data'];
|
||||
return <AgentMessages data={data} />;
|
||||
} catch (e) {
|
||||
return <CodePreview language={lang} code={content} />;
|
||||
}
|
||||
}
|
||||
|
||||
if (lang === 'vis-convert-error') {
|
||||
try {
|
||||
const data = JSON.parse(content) as Parameters<typeof VisConvertError>[0]['data'];
|
||||
return <VisConvertError data={data} />;
|
||||
} catch (e) {
|
||||
return <CodePreview language={lang} code={content} />;
|
||||
}
|
||||
}
|
||||
|
||||
if (lang === 'vis-dashboard') {
|
||||
try {
|
||||
const data = JSON.parse(content) as Parameters<typeof VisDashboard>[0]['data'];
|
||||
return <VisDashboard data={data} />;
|
||||
} catch (e) {
|
||||
return <CodePreview language={lang} code={content} />;
|
||||
}
|
||||
}
|
||||
|
||||
if (lang === 'vis-chart') {
|
||||
try {
|
||||
const data = JSON.parse(content) as Parameters<typeof VisChart>[0]['data'];
|
||||
return <VisChart data={data} />;
|
||||
} catch (e) {
|
||||
return <CodePreview language={lang} code={content} />;
|
||||
}
|
||||
}
|
||||
|
||||
if (lang === 'vis-plugin') {
|
||||
try {
|
||||
const data = JSON.parse(content) as Parameters<typeof VisPlugin>[0]['data'];
|
||||
return <VisPlugin data={data} />;
|
||||
} catch (e) {
|
||||
return <CodePreview language={lang} code={content} />;
|
||||
}
|
||||
}
|
||||
|
||||
if (lang === 'vis-code') {
|
||||
try {
|
||||
const data = JSON.parse(content) as Parameters<typeof VisCode>[0]['data'];
|
||||
return <VisCode data={data} />;
|
||||
} catch (e) {
|
||||
return <CodePreview language={lang} code={content} />;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{!inline ? (
|
||||
<CodePreview code={context} language={match?.[1] ?? 'javascript'} />
|
||||
<CodePreview code={context} language={lang} />
|
||||
) : (
|
||||
<code {...props} style={style} className="p-1 mx-1 rounded bg-theme-light dark:bg-theme-dark text-sm">
|
||||
{children}
|
||||
@ -61,7 +132,7 @@ const basicComponents: MarkdownComponent = {
|
||||
},
|
||||
table({ children }) {
|
||||
return (
|
||||
<table className="my-2 rounded-tl-md rounded-tr-md max-w-full bg-white dark:bg-gray-900 text-sm rounded-lg overflow-hidden">{children}</table>
|
||||
<table className="my-2 rounded-tl-md rounded-tr-md max-w-full bg-white dark:bg-gray-800 text-sm rounded-lg overflow-hidden">{children}</table>
|
||||
);
|
||||
},
|
||||
thead({ children }) {
|
||||
|
19
web/components/chat/chat-content/vis-chart.tsx
Normal file
19
web/components/chat/chat-content/vis-chart.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import { BackEndChartType } from '@/components/chart';
|
||||
import ChartView from './chart-view';
|
||||
import { Datum } from '@antv/ava';
|
||||
|
||||
interface Props {
|
||||
data: {
|
||||
data: Datum[];
|
||||
describe: string;
|
||||
title: string;
|
||||
type: BackEndChartType;
|
||||
sql: string;
|
||||
};
|
||||
}
|
||||
|
||||
function VisChart({ data }: Props) {
|
||||
return <ChartView data={data.data} type={data.type} sql={data.sql} />;
|
||||
}
|
||||
|
||||
export default VisChart;
|
69
web/components/chat/chat-content/vis-code.tsx
Normal file
69
web/components/chat/chat-content/vis-code.tsx
Normal file
@ -0,0 +1,69 @@
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import markdownComponents from './config';
|
||||
import { CodePreview } from './code-preview';
|
||||
import classNames from 'classnames';
|
||||
import { useState } from 'react';
|
||||
import { CheckOutlined, CloseOutlined } from '@ant-design/icons';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { oneLight, oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
||||
|
||||
interface Props {
|
||||
data: {
|
||||
code: string[];
|
||||
exit_success: true;
|
||||
language: string;
|
||||
log: string;
|
||||
};
|
||||
}
|
||||
|
||||
function VisCode({ data }: Props) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [show, setShow] = useState(0);
|
||||
|
||||
return (
|
||||
<div className="bg-[#EAEAEB] rounded overflow-hidden border border-theme-primary dark:bg-theme-dark text-sm">
|
||||
<div>
|
||||
<div className="flex">
|
||||
{data.code.map((item, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={classNames('px-4 py-2 text-[#121417] dark:text-white cursor-pointer', {
|
||||
'bg-white dark:bg-theme-dark-container': index === show,
|
||||
})}
|
||||
onClick={() => {
|
||||
setShow(index);
|
||||
}}
|
||||
>
|
||||
CODE {index + 1}: {item[0]}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{data.code.length && (
|
||||
<CodePreview
|
||||
language={data.code[show][0]}
|
||||
code={data.code[show][1]}
|
||||
customStyle={{ maxHeight: 300, margin: 0 }}
|
||||
light={oneLight}
|
||||
dark={oneDark}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex">
|
||||
<div className="bg-white dark:bg-theme-dark-container px-4 py-2 text-[#121417] dark:text-white">
|
||||
{t('Terminal')} {data.exit_success ? <CheckOutlined className="text-green-600" /> : <CloseOutlined className="text-red-600" />}
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4 max-h-72 overflow-y-auto whitespace-normal bg-white dark:dark:bg-theme-dark">
|
||||
<ReactMarkdown components={markdownComponents} remarkPlugins={[remarkGfm]}>
|
||||
{data.log}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default VisCode;
|
24
web/components/chat/chat-content/vis-convert-error.tsx
Normal file
24
web/components/chat/chat-content/vis-convert-error.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import { format } from 'sql-formatter';
|
||||
import { CodePreview } from './code-preview';
|
||||
|
||||
interface Props {
|
||||
data: {
|
||||
display_type: string;
|
||||
sql: string;
|
||||
thought: string;
|
||||
};
|
||||
}
|
||||
|
||||
function VisConvertError({ data }: Props) {
|
||||
return (
|
||||
<div className="rounded overflow-hidden">
|
||||
<div className="p-3 text-white bg-red-500 whitespace-normal">{data.display_type}</div>
|
||||
<div className="p-3 bg-red-50">
|
||||
<div className="mb-2 whitespace-normal">{data.thought}</div>
|
||||
<CodePreview code={format(data.sql)} language="sql" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default VisConvertError;
|
58
web/components/chat/chat-content/vis-dashboard.tsx
Normal file
58
web/components/chat/chat-content/vis-dashboard.tsx
Normal file
@ -0,0 +1,58 @@
|
||||
import { AutoChart, BackEndChartType, getChartType } from '@/components/chart';
|
||||
import { Datum } from '@antv/ava';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
interface Props {
|
||||
data: {
|
||||
data: {
|
||||
data: Datum[];
|
||||
describe: string;
|
||||
title: string;
|
||||
type: BackEndChartType;
|
||||
sql: string;
|
||||
}[];
|
||||
title: string | null;
|
||||
display_strategy: string;
|
||||
chart_count: number;
|
||||
};
|
||||
}
|
||||
|
||||
const chartLayout = [[2], [1, 2], [1, 3], [2, 1, 2], [2, 1, 3], [3, 1, 3], [3, 2, 3]];
|
||||
|
||||
function VisDashboard({ data }: Props) {
|
||||
const charts = useMemo(() => {
|
||||
if (data.chart_count > 1) {
|
||||
const layout = chartLayout[data.chart_count - 2];
|
||||
let prevIndex = 0;
|
||||
return layout.map((item) => {
|
||||
const items = data.data.slice(prevIndex, prevIndex + item);
|
||||
prevIndex = item;
|
||||
return items;
|
||||
});
|
||||
}
|
||||
return [data.data];
|
||||
}, [data.data, data.chart_count]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
{charts.map((row, index) => (
|
||||
<div key={`row-${index}`} className="flex gap-3">
|
||||
{row.map((chart, subIndex) => (
|
||||
<div
|
||||
key={`chart-${subIndex}`}
|
||||
className="flex flex-1 flex-col justify-between p-4 rounded border border-gray-200 dark:border-gray-500 whitespace-normal"
|
||||
>
|
||||
<div>
|
||||
{chart.title && <div className="mb-2 text-lg">{chart.title}</div>}
|
||||
{chart.describe && <div className="mb-4 text-sm text-gray-500">{chart.describe}</div>}
|
||||
</div>
|
||||
<AutoChart data={chart.data} chartType={getChartType(chart.type)} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default VisDashboard;
|
64
web/components/chat/chat-content/vis-plugin.tsx
Normal file
64
web/components/chat/chat-content/vis-plugin.tsx
Normal file
@ -0,0 +1,64 @@
|
||||
import { CheckOutlined, ClockCircleOutlined, CloseOutlined, LoadingOutlined } from '@ant-design/icons';
|
||||
import classNames from 'classnames';
|
||||
import { ReactNode } from 'react';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import markdownComponents from './config';
|
||||
import rehypeRaw from 'rehype-raw';
|
||||
|
||||
interface IVisPlugin {
|
||||
name: string;
|
||||
args: {
|
||||
query: string;
|
||||
};
|
||||
status: 'todo' | 'runing' | 'failed' | 'complete' | (string & {});
|
||||
logo: string | null;
|
||||
result: string;
|
||||
err_msg: string | null;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
data: IVisPlugin;
|
||||
}
|
||||
|
||||
const pluginViewStatusMapper: Record<IVisPlugin['status'], { bgClass: string; icon: ReactNode }> = {
|
||||
todo: {
|
||||
bgClass: 'bg-gray-500',
|
||||
icon: <ClockCircleOutlined className="ml-2" />,
|
||||
},
|
||||
runing: {
|
||||
bgClass: 'bg-blue-500',
|
||||
icon: <LoadingOutlined className="ml-2" />,
|
||||
},
|
||||
failed: {
|
||||
bgClass: 'bg-red-500',
|
||||
icon: <CloseOutlined className="ml-2" />,
|
||||
},
|
||||
complete: {
|
||||
bgClass: 'bg-green-500',
|
||||
icon: <CheckOutlined className="ml-2" />,
|
||||
},
|
||||
};
|
||||
|
||||
function VisPlugin({ data }: Props) {
|
||||
const { bgClass, icon } = pluginViewStatusMapper[data.status] ?? {};
|
||||
|
||||
return (
|
||||
<div className="bg-theme-light dark:bg-theme-dark-container rounded overflow-hidden my-2 flex flex-col lg:max-w-[80%]">
|
||||
<div className={classNames('flex px-4 md:px-6 py-2 items-center text-white text-sm', bgClass)}>
|
||||
{data.name}
|
||||
{icon}
|
||||
</div>
|
||||
{data.result ? (
|
||||
<div className="px-4 md:px-6 py-4 text-sm whitespace-normal">
|
||||
<ReactMarkdown components={markdownComponents} rehypePlugins={[rehypeRaw]}>
|
||||
{data.result ?? ''}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
) : (
|
||||
<div className="px-4 md:px-6 py-4 text-sm">{data.err_msg}</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default VisPlugin;
|
@ -19,6 +19,7 @@ import { CopyOutlined, RedoOutlined } from '@ant-design/icons';
|
||||
import { getInitMessage } from '@/utils';
|
||||
import { apiInterceptors, getChatFeedBackSelect } from '@/client/api';
|
||||
import useSummary from '@/hooks/use-summary';
|
||||
import AgentContent from './agent-content';
|
||||
|
||||
type Props = {
|
||||
messages: IChatDialogueMessageSchema[];
|
||||
@ -26,7 +27,7 @@ type Props = {
|
||||
};
|
||||
|
||||
const Completion = ({ messages, onSubmit }: Props) => {
|
||||
const { dbParam, currentDialogue, scene, model, refreshDialogList, chatId, agentList, docId } = useContext(ChatContext);
|
||||
const { dbParam, currentDialogue, scene, model, refreshDialogList, chatId, agent, docId } = useContext(ChatContext);
|
||||
const { t } = useTranslation();
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
@ -47,19 +48,23 @@ const Completion = ({ messages, onSubmit }: Props) => {
|
||||
const selectParam = useMemo(() => {
|
||||
switch (scene) {
|
||||
case 'chat_agent':
|
||||
return agentList.join(',');
|
||||
return agent;
|
||||
case 'chat_excel':
|
||||
return currentDialogue?.select_param;
|
||||
default:
|
||||
return spaceNameOriginal || dbParam;
|
||||
}
|
||||
}, [scene, agentList, currentDialogue, dbParam, spaceNameOriginal]);
|
||||
}, [scene, agent, currentDialogue, dbParam, spaceNameOriginal]);
|
||||
|
||||
const handleChat = async (message: string) => {
|
||||
if (isLoading || !message.trim()) return;
|
||||
const handleChat = async (content: string) => {
|
||||
if (isLoading || !content.trim()) return;
|
||||
if (scene === 'chat_agent' && !agent) {
|
||||
message.warning(t('choice_agent_tip'));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
setIsLoading(true);
|
||||
await onSubmit(message, {
|
||||
await onSubmit(content, {
|
||||
select_param: selectParam ?? '',
|
||||
});
|
||||
} finally {
|
||||
@ -145,6 +150,9 @@ const Completion = ({ messages, onSubmit }: Props) => {
|
||||
<div className="flex items-center flex-1 flex-col text-sm leading-6 text-slate-900 dark:text-slate-300 sm:text-base sm:leading-7">
|
||||
{showMessages.length ? (
|
||||
showMessages.map((content, index) => {
|
||||
if (scene === 'chat_agent') {
|
||||
return <AgentContent key={index} content={content} />;
|
||||
}
|
||||
return (
|
||||
<ChatContent
|
||||
key={index}
|
||||
|
@ -1,49 +1,28 @@
|
||||
import { ChatContext } from '@/app/chat-context';
|
||||
import { apiInterceptors, postAgentMy } from '@/client/api';
|
||||
import { apiInterceptors, getDbgptsList } from '@/client/api';
|
||||
import { useRequest } from 'ahooks';
|
||||
import { Button, Select } from 'antd';
|
||||
import { useRouter } from 'next/router';
|
||||
import { Select } from 'antd';
|
||||
import { useContext } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
function AgentSelector() {
|
||||
const { push } = useRouter();
|
||||
const { t } = useTranslation();
|
||||
const { agentList, setAgentList } = useContext(ChatContext);
|
||||
const { agent, setAgent } = useContext(ChatContext);
|
||||
|
||||
const { data = [] } = useRequest(async () => {
|
||||
const [, res] = await apiInterceptors(postAgentMy());
|
||||
if (res && res.length) {
|
||||
setAgentList?.([res[0].name]);
|
||||
}
|
||||
const [, res] = await apiInterceptors(getDbgptsList());
|
||||
return res ?? [];
|
||||
});
|
||||
|
||||
if (!data.length) {
|
||||
return (
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
push('/agent');
|
||||
}}
|
||||
>
|
||||
{t('To_Plugin_Market')}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Select
|
||||
className="w-60"
|
||||
value={agentList}
|
||||
mode="multiple"
|
||||
maxTagCount={1}
|
||||
maxTagTextLength={12}
|
||||
value={agent}
|
||||
placeholder={t('Select_Plugins')}
|
||||
options={data.map((item) => ({ label: item.name, value: item.name }))}
|
||||
options={data.map((item) => ({ label: item.gpts_describe, value: item.gpts_name }))}
|
||||
allowClear
|
||||
onChange={(val) => {
|
||||
setAgentList?.(val);
|
||||
setAgent?.(val);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
@ -54,7 +54,8 @@ function smallMenuItemStyle(active?: boolean) {
|
||||
}
|
||||
|
||||
function SideBar() {
|
||||
const { chatId, scene, isMenuExpand, dialogueList, queryDialogueList, refreshDialogList, setIsMenuExpand, mode, setMode } = useContext(ChatContext);
|
||||
const { chatId, scene, isMenuExpand, dialogueList, queryDialogueList, refreshDialogList, setIsMenuExpand, setAgent, mode, setMode } =
|
||||
useContext(ChatContext);
|
||||
const { pathname, replace } = useRouter();
|
||||
const { t, i18n } = useTranslation();
|
||||
|
||||
@ -192,6 +193,12 @@ function SideBar() {
|
||||
[refreshDialogList],
|
||||
);
|
||||
|
||||
const handleClickChatItem = (item: IChatDialogueSchema) => {
|
||||
if (item.chat_mode === 'chat_agent' && item.select_param) {
|
||||
setAgent?.(item.select_param);
|
||||
}
|
||||
};
|
||||
|
||||
const copyLink = useCallback((item: IChatDialogueSchema) => {
|
||||
const success = copy(`${location.origin}/chat?scene=${item.chat_mode}&id=${item.conv_uid}`);
|
||||
message[success ? 'success' : 'error'](success ? 'Copy success' : 'Copy failed');
|
||||
@ -223,7 +230,13 @@ function SideBar() {
|
||||
|
||||
return (
|
||||
<Tooltip key={item.conv_uid} title={item.user_name || item.user_input} placement="right">
|
||||
<Link href={`/chat?scene=${item.chat_mode}&id=${item.conv_uid}`} className={smallMenuItemStyle(active)}>
|
||||
<Link
|
||||
href={`/chat?scene=${item.chat_mode}&id=${item.conv_uid}`}
|
||||
className={smallMenuItemStyle(active)}
|
||||
onClick={() => {
|
||||
handleClickChatItem(item);
|
||||
}}
|
||||
>
|
||||
<MessageOutlined />
|
||||
</Link>
|
||||
</Tooltip>
|
||||
@ -271,7 +284,14 @@ function SideBar() {
|
||||
const active = item.conv_uid === chatId && item.chat_mode === scene;
|
||||
|
||||
return (
|
||||
<Link key={item.conv_uid} href={`/chat?scene=${item.chat_mode}&id=${item.conv_uid}`} className={`group/item ${menuItemStyle(active)}`}>
|
||||
<Link
|
||||
key={item.conv_uid}
|
||||
href={`/chat?scene=${item.chat_mode}&id=${item.conv_uid}`}
|
||||
className={`group/item ${menuItemStyle(active)}`}
|
||||
onClick={() => {
|
||||
handleClickChatItem(item);
|
||||
}}
|
||||
>
|
||||
<MessageOutlined className="text-base" />
|
||||
<div className="flex-1 line-clamp-1 mx-2 text-sm">{item.user_name || item.user_input}</div>
|
||||
<div
|
||||
|
@ -10,6 +10,7 @@ type Props = {
|
||||
type ChatParams = {
|
||||
chatId: string;
|
||||
data?: Record<string, any>;
|
||||
query?: Record<string, string>;
|
||||
onMessage: (message: string) => void;
|
||||
onClose?: () => void;
|
||||
onDone?: () => void;
|
||||
@ -22,7 +23,7 @@ const useChat = ({ queryAgentURL = '/api/v1/chat/completions' }: Props) => {
|
||||
const chat = useCallback(
|
||||
async ({ data, chatId, onMessage, onClose, onDone, onError }: ChatParams) => {
|
||||
if (!data?.user_input && !data?.doc_id) {
|
||||
message.warning(i18n.t('NoContextTip'));
|
||||
message.warning(i18n.t('no_context_tip'));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -58,7 +59,12 @@ const useChat = ({ queryAgentURL = '/api/v1/chat/completions' }: Props) => {
|
||||
throw new Error(err);
|
||||
},
|
||||
onmessage: (event) => {
|
||||
const message = event.data?.replaceAll('\\n', '\n');
|
||||
let message = event.data;
|
||||
try {
|
||||
message = JSON.parse(message).vis;
|
||||
} catch (e) {
|
||||
message.replaceAll('\\n', '\n');
|
||||
}
|
||||
if (message === '[DONE]') {
|
||||
onDone?.();
|
||||
} else if (message?.startsWith('[ERROR]')) {
|
||||
|
229
web/package-lock.json
generated
229
web/package-lock.json
generated
@ -35,6 +35,7 @@
|
||||
"react-markdown": "^8.0.7",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"rehype-raw": "6.1.1",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"sql-formatter": "^12.2.4",
|
||||
"tailwindcss": "3.3.2",
|
||||
"tailwindcss-animated": "^1.0.1",
|
||||
@ -3314,6 +3315,15 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/ccount": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/ccount/download/ccount-2.0.1.tgz",
|
||||
"integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/center-align": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
|
||||
@ -6144,6 +6154,11 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/longest-streak": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/longest-streak/download/longest-streak-3.1.0.tgz",
|
||||
"integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="
|
||||
},
|
||||
"node_modules/loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
@ -6168,6 +6183,11 @@
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/markdown-table": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/markdown-table/download/markdown-table-3.0.3.tgz",
|
||||
"integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw=="
|
||||
},
|
||||
"node_modules/mdast-util-definitions": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz",
|
||||
@ -6182,6 +6202,25 @@
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-find-and-replace": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/mdast-util-find-and-replace/download/mdast-util-find-and-replace-2.2.2.tgz",
|
||||
"integrity": "sha512-MTtdFRz/eMDHXzeK6W3dO7mXUlF82Gom4y0oOgvHhh/HXZAGvIQDUvQ0SuUx+j2tv44b8xTHOm8K/9OoRFnXKw==",
|
||||
"dependencies": {
|
||||
"@types/mdast": "^3.0.0",
|
||||
"escape-string-regexp": "^5.0.0",
|
||||
"unist-util-is": "^5.0.0",
|
||||
"unist-util-visit-parents": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/escape-string-regexp/download/escape-string-regexp-5.0.0.tgz",
|
||||
"integrity": "sha1-RoMSa1ALYXYvLb66zhgG6L4xscg=",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-from-markdown": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz",
|
||||
@ -6205,6 +6244,79 @@
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-gfm": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/mdast-util-gfm/download/mdast-util-gfm-2.0.2.tgz",
|
||||
"integrity": "sha512-qvZ608nBppZ4icQlhQQIAdc6S3Ffj9RGmzwUKUWuEICFnd1LVkN3EktF7ZHAgfcEdvZB5owU9tQgt99e2TlLjg==",
|
||||
"dependencies": {
|
||||
"mdast-util-from-markdown": "^1.0.0",
|
||||
"mdast-util-gfm-autolink-literal": "^1.0.0",
|
||||
"mdast-util-gfm-footnote": "^1.0.0",
|
||||
"mdast-util-gfm-strikethrough": "^1.0.0",
|
||||
"mdast-util-gfm-table": "^1.0.0",
|
||||
"mdast-util-gfm-task-list-item": "^1.0.0",
|
||||
"mdast-util-to-markdown": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-gfm-autolink-literal": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/mdast-util-gfm-autolink-literal/download/mdast-util-gfm-autolink-literal-1.0.3.tgz",
|
||||
"integrity": "sha512-My8KJ57FYEy2W2LyNom4n3E7hKTuQk/0SES0u16tjA9Z3oFkF4RrC/hPAPgjlSpezsOvI8ObcXcElo92wn5IGA==",
|
||||
"dependencies": {
|
||||
"@types/mdast": "^3.0.0",
|
||||
"ccount": "^2.0.0",
|
||||
"mdast-util-find-and-replace": "^2.0.0",
|
||||
"micromark-util-character": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-gfm-footnote": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/mdast-util-gfm-footnote/download/mdast-util-gfm-footnote-1.0.2.tgz",
|
||||
"integrity": "sha512-56D19KOGbE00uKVj3sgIykpwKL179QsVFwx/DCW0u/0+URsryacI4MAdNJl0dh+u2PSsD9FtxPFbHCzJ78qJFQ==",
|
||||
"dependencies": {
|
||||
"@types/mdast": "^3.0.0",
|
||||
"mdast-util-to-markdown": "^1.3.0",
|
||||
"micromark-util-normalize-identifier": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-gfm-strikethrough": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/mdast-util-gfm-strikethrough/download/mdast-util-gfm-strikethrough-1.0.3.tgz",
|
||||
"integrity": "sha512-DAPhYzTYrRcXdMjUtUjKvW9z/FNAMTdU0ORyMcbmkwYNbKocDpdk+PX1L1dQgOID/+vVs1uBQ7ElrBQfZ0cuiQ==",
|
||||
"dependencies": {
|
||||
"@types/mdast": "^3.0.0",
|
||||
"mdast-util-to-markdown": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-gfm-table": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/mdast-util-gfm-table/download/mdast-util-gfm-table-1.0.7.tgz",
|
||||
"integrity": "sha512-jjcpmNnQvrmN5Vx7y7lEc2iIOEytYv7rTvu+MeyAsSHTASGCCRA79Igg2uKssgOs1i1po8s3plW0sTu1wkkLGg==",
|
||||
"dependencies": {
|
||||
"@types/mdast": "^3.0.0",
|
||||
"markdown-table": "^3.0.0",
|
||||
"mdast-util-from-markdown": "^1.0.0",
|
||||
"mdast-util-to-markdown": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-gfm-task-list-item": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/mdast-util-gfm-task-list-item/download/mdast-util-gfm-task-list-item-1.0.2.tgz",
|
||||
"integrity": "sha512-PFTA1gzfp1B1UaiJVyhJZA1rm0+Tzn690frc/L8vNX1Jop4STZgOE6bxUhnzdVSB+vm2GU1tIsuQcA9bxTQpMQ==",
|
||||
"dependencies": {
|
||||
"@types/mdast": "^3.0.0",
|
||||
"mdast-util-to-markdown": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-phrasing": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/mdast-util-phrasing/download/mdast-util-phrasing-3.0.1.tgz",
|
||||
"integrity": "sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==",
|
||||
"dependencies": {
|
||||
"@types/mdast": "^3.0.0",
|
||||
"unist-util-is": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-to-hast": {
|
||||
"version": "12.3.0",
|
||||
"resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz",
|
||||
@ -6224,6 +6336,21 @@
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-to-markdown": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/mdast-util-to-markdown/download/mdast-util-to-markdown-1.5.0.tgz",
|
||||
"integrity": "sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==",
|
||||
"dependencies": {
|
||||
"@types/mdast": "^3.0.0",
|
||||
"@types/unist": "^2.0.0",
|
||||
"longest-streak": "^3.0.0",
|
||||
"mdast-util-phrasing": "^3.0.0",
|
||||
"mdast-util-to-string": "^3.0.0",
|
||||
"micromark-util-decode-string": "^1.0.0",
|
||||
"unist-util-visit": "^4.0.0",
|
||||
"zwitch": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-to-string": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz",
|
||||
@ -6311,6 +6438,92 @@
|
||||
"uvu": "^0.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/micromark-extension-gfm": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/micromark-extension-gfm/download/micromark-extension-gfm-2.0.3.tgz",
|
||||
"integrity": "sha512-vb9OoHqrhCmbRidQv/2+Bc6pkP0FrtlhurxZofvOEy5o8RtuuvTq+RQ1Vw5ZDNrVraQZu3HixESqbG+0iKk/MQ==",
|
||||
"dependencies": {
|
||||
"micromark-extension-gfm-autolink-literal": "^1.0.0",
|
||||
"micromark-extension-gfm-footnote": "^1.0.0",
|
||||
"micromark-extension-gfm-strikethrough": "^1.0.0",
|
||||
"micromark-extension-gfm-table": "^1.0.0",
|
||||
"micromark-extension-gfm-tagfilter": "^1.0.0",
|
||||
"micromark-extension-gfm-task-list-item": "^1.0.0",
|
||||
"micromark-util-combine-extensions": "^1.0.0",
|
||||
"micromark-util-types": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/micromark-extension-gfm-autolink-literal": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/micromark-extension-gfm-autolink-literal/download/micromark-extension-gfm-autolink-literal-1.0.5.tgz",
|
||||
"integrity": "sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg==",
|
||||
"dependencies": {
|
||||
"micromark-util-character": "^1.0.0",
|
||||
"micromark-util-sanitize-uri": "^1.0.0",
|
||||
"micromark-util-symbol": "^1.0.0",
|
||||
"micromark-util-types": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/micromark-extension-gfm-footnote": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/micromark-extension-gfm-footnote/download/micromark-extension-gfm-footnote-1.1.2.tgz",
|
||||
"integrity": "sha512-Yxn7z7SxgyGWRNa4wzf8AhYYWNrwl5q1Z8ii+CSTTIqVkmGZF1CElX2JI8g5yGoM3GAman9/PVCUFUSJ0kB/8Q==",
|
||||
"dependencies": {
|
||||
"micromark-core-commonmark": "^1.0.0",
|
||||
"micromark-factory-space": "^1.0.0",
|
||||
"micromark-util-character": "^1.0.0",
|
||||
"micromark-util-normalize-identifier": "^1.0.0",
|
||||
"micromark-util-sanitize-uri": "^1.0.0",
|
||||
"micromark-util-symbol": "^1.0.0",
|
||||
"micromark-util-types": "^1.0.0",
|
||||
"uvu": "^0.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/micromark-extension-gfm-strikethrough": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/micromark-extension-gfm-strikethrough/download/micromark-extension-gfm-strikethrough-1.0.7.tgz",
|
||||
"integrity": "sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw==",
|
||||
"dependencies": {
|
||||
"micromark-util-chunked": "^1.0.0",
|
||||
"micromark-util-classify-character": "^1.0.0",
|
||||
"micromark-util-resolve-all": "^1.0.0",
|
||||
"micromark-util-symbol": "^1.0.0",
|
||||
"micromark-util-types": "^1.0.0",
|
||||
"uvu": "^0.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/micromark-extension-gfm-table": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/micromark-extension-gfm-table/download/micromark-extension-gfm-table-1.0.7.tgz",
|
||||
"integrity": "sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw==",
|
||||
"dependencies": {
|
||||
"micromark-factory-space": "^1.0.0",
|
||||
"micromark-util-character": "^1.0.0",
|
||||
"micromark-util-symbol": "^1.0.0",
|
||||
"micromark-util-types": "^1.0.0",
|
||||
"uvu": "^0.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/micromark-extension-gfm-tagfilter": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/micromark-extension-gfm-tagfilter/download/micromark-extension-gfm-tagfilter-1.0.2.tgz",
|
||||
"integrity": "sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g==",
|
||||
"dependencies": {
|
||||
"micromark-util-types": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/micromark-extension-gfm-task-list-item": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/micromark-extension-gfm-task-list-item/download/micromark-extension-gfm-task-list-item-1.0.5.tgz",
|
||||
"integrity": "sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ==",
|
||||
"dependencies": {
|
||||
"micromark-factory-space": "^1.0.0",
|
||||
"micromark-util-character": "^1.0.0",
|
||||
"micromark-util-symbol": "^1.0.0",
|
||||
"micromark-util-types": "^1.0.0",
|
||||
"uvu": "^0.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/micromark-factory-destination": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz",
|
||||
@ -8459,6 +8672,22 @@
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/remark-gfm": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npm.alibaba-inc.com/remark-gfm/download/remark-gfm-3.0.1.tgz",
|
||||
"integrity": "sha1-CxgPCV4wNlRend2sDo3z+lz+5U8=",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/mdast": "^3.0.0",
|
||||
"mdast-util-gfm": "^2.0.0",
|
||||
"micromark-extension-gfm": "^2.0.0",
|
||||
"unified": "^10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/remark-parse": {
|
||||
"version": "10.0.2",
|
||||
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.2.tgz",
|
||||
|
@ -38,6 +38,7 @@
|
||||
"react-markdown": "^8.0.7",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"rehype-raw": "6.1.1",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"sql-formatter": "^12.2.4",
|
||||
"tailwindcss": "3.3.2",
|
||||
"tailwindcss-animated": "^1.0.1",
|
||||
@ -62,4 +63,4 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"repository": "https://github.com/eosphoros-ai/DB-GPT-Web.git"
|
||||
}
|
||||
}
|
||||
|
@ -59,3 +59,20 @@ export type IMyPlugin = {
|
||||
};
|
||||
|
||||
export type PostAgentMyPluginResponse = IMyPlugin[];
|
||||
|
||||
export type GetDBGPTsListResponse = {
|
||||
gpts_name: string;
|
||||
gpts_describe: string;
|
||||
resource_db: string;
|
||||
resource_knowledge: string;
|
||||
gpts_models: string;
|
||||
language: string;
|
||||
sys_code: string;
|
||||
updated_at: string;
|
||||
team_mode: string;
|
||||
id: number;
|
||||
resource_internet: string;
|
||||
gpts_agents: string;
|
||||
user_code: string;
|
||||
created_at: string;
|
||||
}[];
|
||||
|
@ -36,7 +36,15 @@ export type IChatDialogueSchema = {
|
||||
conv_uid: string;
|
||||
user_input: string;
|
||||
user_name: string;
|
||||
chat_mode: 'chat_with_db_execute' | 'chat_excel' | 'chat_with_db_qa' | 'chat_knowledge' | 'chat_dashboard' | 'chat_execution' | 'chat_agent';
|
||||
chat_mode:
|
||||
| 'chat_with_db_execute'
|
||||
| 'chat_excel'
|
||||
| 'chat_with_db_qa'
|
||||
| 'chat_knowledge'
|
||||
| 'chat_dashboard'
|
||||
| 'chat_execution'
|
||||
| 'chat_agent'
|
||||
| (string & {});
|
||||
select_param: string;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user