Bläddra i källkod

Fix: Fixed the loss of Await Response function on the share page and other style issues #3221 (#9216)

### What problem does this PR solve?

Fix: Fixed the loss of Await Response function on the share page and
other style issues #3221

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
tags/v0.20.1
chanx 2 månader sedan
förälder
incheckning
5f5c6a7990
Inget konto är kopplat till bidragsgivarens mejladress

+ 7
- 2
web/src/components/ui/accordion.tsx Visa fil

@@ -28,8 +28,11 @@ function AccordionItem({
function AccordionTrigger({
className,
children,
hideDownIcon = false,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {
}: React.ComponentProps<typeof AccordionPrimitive.Trigger> & {
hideDownIcon?: boolean;
}) {
return (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
@@ -41,7 +44,9 @@ function AccordionTrigger({
{...props}
>
{children}
<ChevronDownIcon className="text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200" />
{!hideDownIcon && (
<ChevronDownIcon className="text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200" />
)}
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
);

+ 1
- 0
web/src/locales/en.ts Visa fil

@@ -1322,6 +1322,7 @@ This delimiter is used to split the input text into several text pieces echo of
logTimeline: {
begin: 'Ready to begin',
agent: 'Agent is thinking',
userFillUp: 'Waiting for you',
retrieval: 'Looking up knowledge',
message: 'Agent says',
awaitResponse: 'Waiting for you',

+ 1
- 0
web/src/locales/zh.ts Visa fil

@@ -1265,6 +1265,7 @@ General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于
subject: '主题',
logTimeline: {
begin: '准备开始',
userFillUp: '等你输入',
agent: '智能体正在思考',
retrieval: '查找知识',
message: '回复',

+ 8
- 41
web/src/pages/agent/chat/box.tsx Visa fil

@@ -13,14 +13,11 @@ import {
useUploadCanvasFileWithProgress,
} from '@/hooks/use-agent-request';
import { useFetchUserInfo } from '@/hooks/user-setting-hooks';
import { Message } from '@/interfaces/database/chat';
import { buildMessageUuidWithRole } from '@/utils/chat';
import { get } from 'lodash';
import { memo, useCallback, useMemo } from 'react';
import { memo, useCallback } from 'react';
import { useParams } from 'umi';
import DebugContent from '../debug-content';
import { BeginQuery } from '../interface';
import { buildBeginQueryWithObject } from '../utils';
import { useAwaitCompentData } from '../hooks/use-chat-logic';

function AgentChatBox() {
const {
@@ -43,33 +40,12 @@ function AgentChatBox() {
const { data: canvasInfo } = useFetchAgent();
const { id: canvasId } = useParams();
const { uploadCanvasFile, loading } = useUploadCanvasFileWithProgress();
const getInputs = useCallback((message: Message) => {
return get(message, 'data.inputs', {}) as Record<string, BeginQuery>;
}, []);

const buildInputList = useCallback(
(message: Message) => {
return Object.entries(getInputs(message)).map(([key, val]) => {
return {
...val,
key,
};
});
},
[getInputs],
);

const handleOk = useCallback(
(message: Message) => (values: BeginQuery[]) => {
const inputs = getInputs(message);
const nextInputs = buildBeginQueryWithObject(inputs, values);
sendFormMessage({
inputs: nextInputs,
id: canvasId,
});
},
[canvasId, getInputs, sendFormMessage],
);
const { buildInputList, handleOk, isWaitting } = useAwaitCompentData({
derivedMessages,
sendFormMessage,
canvasId: canvasId as string,
});

const handleUploadFile: NonNullable<FileUploadProps['onUpload']> =
useCallback(
@@ -79,16 +55,7 @@ function AgentChatBox() {
},
[appendUploadResponseList, uploadCanvasFile],
);
const isWaitting = useMemo(() => {
const temp = derivedMessages?.some((message, i) => {
const flag =
message.role === MessageType.Assistant &&
derivedMessages.length - 1 === i &&
message.data;
return flag;
});
return temp;
}, [derivedMessages]);

return (
<>
<section className="flex flex-1 flex-col px-5 h-[90vh]">

+ 2
- 2
web/src/pages/agent/chat/use-send-agent-message.ts Visa fil

@@ -269,7 +269,7 @@ export const useSendAgentMessage = (

const sendFormMessage = useCallback(
(body: { id?: string; inputs: Record<string, BeginQuery> }) => {
send(body);
send({ ...body, session_id: sessionId });
addNewestOneQuestion({
content: Object.entries(body.inputs)
.map(([key, val]) => `${key}: ${val.value}`)
@@ -277,7 +277,7 @@ export const useSendAgentMessage = (
role: MessageType.User,
});
},
[addNewestOneQuestion, send],
[addNewestOneQuestion, send, sessionId],
);

// reset session

+ 60
- 0
web/src/pages/agent/hooks/use-chat-logic.ts Visa fil

@@ -0,0 +1,60 @@
import { MessageType } from '@/constants/chat';
import { Message } from '@/interfaces/database/chat';
import { IMessage } from '@/pages/chat/interface';
import { get } from 'lodash';
import { useCallback, useMemo } from 'react';
import { BeginQuery } from '../interface';
import { buildBeginQueryWithObject } from '../utils';
type IAwaitCompentData = {
derivedMessages: IMessage[];
sendFormMessage: (params: {
inputs: Record<string, BeginQuery>;
id: string;
}) => void;
canvasId: string;
};
const useAwaitCompentData = (props: IAwaitCompentData) => {
const { derivedMessages, sendFormMessage, canvasId } = props;

const getInputs = useCallback((message: Message) => {
return get(message, 'data.inputs', {}) as Record<string, BeginQuery>;
}, []);

const buildInputList = useCallback(
(message: Message) => {
return Object.entries(getInputs(message)).map(([key, val]) => {
return {
...val,
key,
};
});
},
[getInputs],
);

const handleOk = useCallback(
(message: Message) => (values: BeginQuery[]) => {
const inputs = getInputs(message);
const nextInputs = buildBeginQueryWithObject(inputs, values);
sendFormMessage({
inputs: nextInputs,
id: canvasId,
});
},
[getInputs, sendFormMessage, canvasId],
);

const isWaitting = useMemo(() => {
const temp = derivedMessages?.some((message, i) => {
const flag =
message.role === MessageType.Assistant &&
derivedMessages.length - 1 === i &&
message.data;
return flag;
});
return temp;
}, [derivedMessages]);
return { getInputs, buildInputList, handleOk, isWaitting };
};

export { useAwaitCompentData };

+ 38
- 17
web/src/pages/agent/log-sheet/toolTimelineItem.tsx Visa fil

@@ -14,24 +14,37 @@ import {
import { cn } from '@/lib/utils';
import { isEmpty } from 'lodash';
import { Operator } from '../constant';
import OperatorIcon from '../operator-icon';
import OperatorIcon, { SVGIconMap } from '../operator-icon';
import {
JsonViewer,
toLowerCaseStringAndDeleteChar,
typeMap,
} from './workFlowTimeline';
const capitalizeWords = (str: string, separator: string = '_'): string => {
if (!str) return '';
type IToolIcon =
| Operator.ArXiv
| Operator.GitHub
| Operator.Bing
| Operator.DuckDuckGo
| Operator.Google
| Operator.GoogleScholar
| Operator.PubMed
| Operator.TavilyExtract
| Operator.TavilySearch
| Operator.Wikipedia
| Operator.YahooFinance
| Operator.WenCai
| Operator.Crawler;

return str
.split(separator)
.map((word) => {
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
})
.join(' ');
const capitalizeWords = (str: string, separator: string = '_'): string[] => {
if (!str) return [''];

const resultStrArr = str.split(separator).map((word) => {
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
});
return resultStrArr;
};
const changeToolName = (toolName: any) => {
const name = 'Agent ' + capitalizeWords(toolName);
const name = 'Agent ' + capitalizeWords(toolName).join(' ');
return name;
};
const ToolTimelineItem = ({
@@ -61,6 +74,8 @@ const ToolTimelineItem = ({
return (
<>
{filteredTools?.map((tool, idx) => {
const toolName = capitalizeWords(tool.tool_name, '_').join('');

return (
<TimelineItem
key={'tool_' + idx}
@@ -105,7 +120,11 @@ const ToolTimelineItem = ({
<div className="size-6 flex items-center justify-center">
<OperatorIcon
className="size-4"
name={'Agent' as Operator}
name={
(SVGIconMap[toolName as IToolIcon]
? toolName
: 'Agent') as Operator
}
></OperatorIcon>
</div>
</div>
@@ -119,12 +138,14 @@ const ToolTimelineItem = ({
className="bg-background-card px-3"
>
<AccordionItem value={idx.toString()}>
<AccordionTrigger>
<AccordionTrigger
hideDownIcon={isShare && isEmpty(tool.arguments)}
>
<div className="flex gap-2 items-center">
{!isShare && (
<span>
{parentName(tool.path) + ' '}
{capitalizeWords(tool.tool_name, '_')}
{capitalizeWords(tool.tool_name, '_').join(' ')}
</span>
)}
{isShare && (
@@ -142,7 +163,7 @@ const ToolTimelineItem = ({
</span>
<span
className={cn(
'border-background -end-1 -top-1 size-2 rounded-full border-2 bg-dot-green',
'border-background -end-1 -top-1 size-2 rounded-full bg-dot-green',
)}
>
<span className="sr-only">Online</span>
@@ -161,7 +182,7 @@ const ToolTimelineItem = ({
)}
{isShare && !isEmpty(tool.arguments) && (
<AccordionContent>
<div className="space-y-2">
<div className="space-y-2 bg-muted p-2">
{tool &&
tool.arguments &&
Object.entries(tool.arguments).length &&
@@ -171,8 +192,8 @@ const ToolTimelineItem = ({
<div className="text-sm font-medium leading-none">
{key}
</div>
<div className="text-sm text-muted-foreground">
{val || ''}
<div className="text-sm text-muted-foreground mt-1">
{val as string}
</div>
</div>
);

+ 18
- 5
web/src/pages/agent/log-sheet/workFlowTimeline.tsx Visa fil

@@ -51,7 +51,7 @@ export function JsonViewer({
src={data}
displaySize
collapseStringsAfterLength={100000000000}
className="w-full h-[200px] break-words overflow-auto scrollbar-auto p-2 bg-slate-800"
className="w-full h-[200px] break-words overflow-auto scrollbar-auto p-2 bg-muted"
/>
</section>
);
@@ -81,11 +81,21 @@ export const typeMap = {
httpRequest: t('flow.logTimeline.httpRequest'),
wenCai: t('flow.logTimeline.wenCai'),
yahooFinance: t('flow.logTimeline.yahooFinance'),
userFillUp: t('flow.logTimeline.userFillUp'),
};
export const toLowerCaseStringAndDeleteChar = (
str: string,
char: string = '_',
) => str.toLowerCase().replace(/ /g, '').replaceAll(char, '');

// Convert all keys in typeMap to lowercase and output the new typeMap
export const typeMapLowerCase = Object.fromEntries(
Object.entries(typeMap).map(([key, value]) => [
toLowerCaseStringAndDeleteChar(key),
value,
]),
);

function getInputsOrOutputs(
nodeEventList: INodeData[],
field: 'inputs' | 'outputs',
@@ -247,16 +257,19 @@ export const WorkFlowTimeline = ({
className="bg-background-card px-3"
>
<AccordionItem value={idx.toString()}>
<AccordionTrigger>
<AccordionTrigger
hideDownIcon={isShare && !x.data?.thoughts}
>
<div className="flex gap-2 items-center">
<span>
{!isShare && getNodeName(x.data?.component_name)}
{isShare &&
typeMap[
(typeMapLowerCase[
toLowerCaseStringAndDeleteChar(
nodeLabel,
) as keyof typeof typeMap
]}
] ??
nodeLabel)}
</span>
<span className="text-text-sub-title text-xs">
{x.data.elapsed_time?.toString().slice(0, 6)}
@@ -294,7 +307,7 @@ export const WorkFlowTimeline = ({
{isShare && x.data?.thoughts && (
<AccordionContent>
<div className="space-y-2">
<div className="w-full h-[200px] break-words overflow-auto scrollbar-auto p-2 bg-slate-800">
<div className="w-full h-[200px] break-words overflow-auto scrollbar-auto p-2 bg-muted">
<HightLightMarkdown>
{x.data.thoughts || ''}
</HightLightMarkdown>

+ 1
- 1
web/src/pages/agent/operator-icon.tsx Visa fil

@@ -38,7 +38,7 @@ export const OperatorIconMap = {
[Operator.Email]: 'sendemail-0',
};

const SVGIconMap = {
export const SVGIconMap = {
[Operator.ArXiv]: ArxivIcon,
[Operator.GitHub]: GithubIcon,
[Operator.Bing]: BingIcon,

+ 1
- 1
web/src/pages/agents/agent-log-page.tsx Visa fil

@@ -231,7 +231,7 @@ const AgentLogPage: React.FC = () => {
<div className="flex justify-between items-center">
<h1 className="text-2xl font-bold mb-4">Log</h1>

<div className="flex justify-end space-x-2 mb-4">
<div className="flex justify-end space-x-2 mb-4 text-foreground">
<div className="flex items-center space-x-2">
<span>ID/Title</span>
<SearchInput

+ 33
- 5
web/src/pages/next-chats/share/index.tsx Visa fil

@@ -13,7 +13,9 @@ import {
} from '@/hooks/use-agent-request';
import { cn } from '@/lib/utils';
import i18n from '@/locales/config';
import DebugContent from '@/pages/agent/debug-content';
import { useCacheChatLog } from '@/pages/agent/hooks/use-cache-chat-log';
import { useAwaitCompentData } from '@/pages/agent/hooks/use-chat-logic';
import { IInputs } from '@/pages/agent/interface';
import { useSendButtonDisabled } from '@/pages/chat/hooks';
import { buildMessageUuidWithRole } from '@/utils/chat';
@@ -56,10 +58,15 @@ const ChatContainer = () => {
appendUploadResponseList,
parameterDialogVisible,
showParameterDialog,
sendFormMessage,
ok,
resetSession,
} = useSendNextSharedMessage(addEventList);

const { buildInputList, handleOk, isWaitting } = useAwaitCompentData({
derivedMessages,
sendFormMessage,
canvasId: conversationId as string,
});
const sendDisabled = useSendButtonDisabled(value);
const appConf = useFetchAppConf();
const { data: inputsData } = useFetchExternalAgentInputs();
@@ -171,7 +178,28 @@ const ChatContainer = () => {
showLoudspeaker={false}
showLog={false}
sendLoading={sendLoading}
></MessageItem>
>
{message.role === MessageType.Assistant &&
derivedMessages.length - 1 === i && (
<DebugContent
parameters={buildInputList(message)}
message={message}
ok={handleOk(message)}
isNext={false}
btnText={'Submit'}
></DebugContent>
)}
{message.role === MessageType.Assistant &&
derivedMessages.length - 1 !== i && (
<div>
<div>{message?.data?.tips}</div>

<div>
{buildInputList(message)?.map((item) => item.value)}
</div>
</div>
)}
</MessageItem>
);
})}
</div>
@@ -182,15 +210,15 @@ const ChatContainer = () => {
<NextMessageInput
isShared
value={value}
disabled={hasError}
sendDisabled={sendDisabled}
disabled={hasError || isWaitting}
sendDisabled={sendDisabled || isWaitting}
conversationId={conversationId}
onInputChange={handleInputChange}
onPressEnter={handlePressEnter}
sendLoading={sendLoading}
stopOutputMessage={stopOutputMessage}
onUpload={handleUploadFile}
isUploading={loading}
isUploading={loading || isWaitting}
></NextMessageInput>
</div>
</div>

+ 1
- 1
web/tailwind.css Visa fil

@@ -246,7 +246,7 @@
@layer utilities {
.scrollbar-auto {
/* hide scrollbar */
scrollbar-width: thin;
scrollbar-width: none;
scrollbar-color: transparent transparent;
}


Laddar…
Avbryt
Spara