@lobehub/lobehub 2.0.0-next.201 → 2.0.0-next.202
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/changelog/v1.json +9 -0
- package/locales/ar/chat.json +2 -0
- package/locales/ar/models.json +64 -7
- package/locales/ar/plugin.json +2 -1
- package/locales/ar/providers.json +1 -0
- package/locales/bg-BG/chat.json +2 -0
- package/locales/bg-BG/models.json +49 -5
- package/locales/bg-BG/plugin.json +2 -1
- package/locales/bg-BG/providers.json +1 -0
- package/locales/de-DE/chat.json +2 -0
- package/locales/de-DE/models.json +36 -7
- package/locales/de-DE/plugin.json +2 -1
- package/locales/de-DE/providers.json +1 -0
- package/locales/en-US/chat.json +2 -0
- package/locales/en-US/models.json +10 -10
- package/locales/en-US/plugin.json +2 -1
- package/locales/en-US/providers.json +1 -0
- package/locales/es-ES/chat.json +2 -0
- package/locales/es-ES/models.json +106 -7
- package/locales/es-ES/plugin.json +2 -1
- package/locales/es-ES/providers.json +1 -0
- package/locales/fa-IR/chat.json +2 -0
- package/locales/fa-IR/models.json +83 -5
- package/locales/fa-IR/plugin.json +2 -1
- package/locales/fa-IR/providers.json +1 -0
- package/locales/fr-FR/chat.json +2 -0
- package/locales/fr-FR/models.json +38 -7
- package/locales/fr-FR/plugin.json +2 -1
- package/locales/fr-FR/providers.json +1 -0
- package/locales/it-IT/chat.json +2 -0
- package/locales/it-IT/models.json +40 -5
- package/locales/it-IT/plugin.json +2 -1
- package/locales/it-IT/providers.json +1 -0
- package/locales/ja-JP/chat.json +2 -0
- package/locales/ja-JP/models.json +84 -7
- package/locales/ja-JP/plugin.json +2 -1
- package/locales/ja-JP/providers.json +1 -0
- package/locales/ko-KR/chat.json +2 -0
- package/locales/ko-KR/models.json +65 -7
- package/locales/ko-KR/plugin.json +2 -1
- package/locales/ko-KR/providers.json +1 -0
- package/locales/nl-NL/chat.json +2 -0
- package/locales/nl-NL/models.json +62 -5
- package/locales/nl-NL/plugin.json +2 -1
- package/locales/nl-NL/providers.json +1 -0
- package/locales/pl-PL/chat.json +2 -0
- package/locales/pl-PL/models.json +85 -0
- package/locales/pl-PL/plugin.json +2 -1
- package/locales/pl-PL/providers.json +1 -0
- package/locales/pt-BR/chat.json +2 -0
- package/locales/pt-BR/models.json +37 -6
- package/locales/pt-BR/plugin.json +2 -1
- package/locales/pt-BR/providers.json +1 -0
- package/locales/ru-RU/chat.json +2 -0
- package/locales/ru-RU/models.json +36 -7
- package/locales/ru-RU/plugin.json +2 -1
- package/locales/ru-RU/providers.json +1 -0
- package/locales/tr-TR/chat.json +2 -0
- package/locales/tr-TR/models.json +28 -7
- package/locales/tr-TR/plugin.json +2 -1
- package/locales/tr-TR/providers.json +1 -0
- package/locales/vi-VN/chat.json +2 -0
- package/locales/vi-VN/models.json +62 -5
- package/locales/vi-VN/plugin.json +2 -1
- package/locales/vi-VN/providers.json +1 -0
- package/locales/zh-CN/chat.json +2 -0
- package/locales/zh-CN/models.json +87 -6
- package/locales/zh-CN/plugin.json +2 -1
- package/locales/zh-CN/providers.json +1 -0
- package/locales/zh-TW/chat.json +2 -0
- package/locales/zh-TW/models.json +71 -7
- package/locales/zh-TW/plugin.json +2 -1
- package/locales/zh-TW/providers.json +1 -0
- package/package.json +1 -1
- package/packages/builtin-tool-gtd/src/client/Inspector/ExecTask/index.tsx +30 -15
- package/packages/builtin-tool-gtd/src/manifest.ts +1 -1
- package/packages/model-runtime/src/core/ModelRuntime.test.ts +44 -86
- package/packages/types/src/aiChat.ts +0 -1
- package/packages/types/src/message/ui/chat.ts +1 -1
- package/src/app/(backend)/middleware/auth/index.ts +16 -2
- package/src/app/(backend)/webapi/chat/[provider]/route.test.ts +30 -15
- package/src/app/(backend)/webapi/chat/[provider]/route.ts +44 -40
- package/src/app/(backend)/webapi/models/[provider]/pull/route.ts +4 -3
- package/src/app/(backend)/webapi/models/[provider]/route.test.ts +36 -13
- package/src/app/(backend)/webapi/models/[provider]/route.ts +4 -11
- package/src/features/Conversation/Messages/AssistantGroup/Tool/Render/index.tsx +21 -23
- package/src/features/Conversation/Messages/AssistantGroup/components/ContentBlock.tsx +16 -3
- package/src/features/Conversation/Messages/Task/TaskDetailPanel/index.tsx +17 -20
- package/src/features/Conversation/Messages/Tasks/shared/ErrorState.tsx +16 -11
- package/src/features/Conversation/Messages/Tasks/shared/InitializingState.tsx +6 -20
- package/src/features/Conversation/Messages/Tasks/shared/ProcessingState.tsx +10 -20
- package/src/features/User/DataStatistics.tsx +4 -4
- package/src/hooks/useQueryParam.ts +0 -2
- package/src/libs/trpc/async/asyncAuth.ts +0 -2
- package/src/libs/trpc/async/context.ts +3 -11
- package/src/locales/default/chat.ts +2 -0
- package/src/locales/default/plugin.ts +2 -1
- package/src/server/modules/AgentRuntime/RuntimeExecutors.ts +6 -6
- package/src/server/modules/AgentRuntime/__tests__/RuntimeExecutors.test.ts +3 -3
- package/src/server/modules/AgentRuntime/factory.ts +39 -20
- package/src/server/modules/ModelRuntime/index.ts +138 -1
- package/src/server/routers/async/__tests__/caller.test.ts +22 -27
- package/src/server/routers/async/caller.ts +4 -6
- package/src/server/routers/async/file.ts +10 -5
- package/src/server/routers/async/image.ts +5 -4
- package/src/server/routers/async/ragEval.ts +7 -5
- package/src/server/routers/lambda/__tests__/aiChat.test.ts +8 -37
- package/src/server/routers/lambda/aiChat.ts +5 -21
- package/src/server/routers/lambda/chunk.ts +9 -28
- package/src/server/routers/lambda/image.ts +1 -7
- package/src/server/routers/lambda/ragEval.ts +1 -1
- package/src/server/routers/lambda/userMemories/reembed.ts +4 -1
- package/src/server/routers/lambda/userMemories/search.ts +7 -7
- package/src/server/routers/lambda/userMemories/shared.ts +8 -10
- package/src/server/routers/lambda/userMemories/tools.ts +140 -118
- package/src/server/routers/lambda/userMemories.test.ts +3 -7
- package/src/server/routers/lambda/userMemories.ts +44 -29
- package/src/server/services/agentRuntime/AgentRuntimeService.test.ts +87 -0
- package/src/server/services/agentRuntime/AgentRuntimeService.ts +53 -2
- package/src/server/services/agentRuntime/__tests__/executeSync.test.ts +2 -6
- package/src/server/services/agentRuntime/__tests__/stepLifecycleCallbacks.test.ts +1 -1
- package/src/server/services/chunk/index.ts +6 -5
- package/src/server/services/toolExecution/types.ts +1 -2
- package/src/services/__tests__/_url.test.ts +0 -1
- package/src/services/_url.ts +0 -3
- package/src/services/aiChat.ts +5 -12
- package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +0 -2
- package/src/app/(backend)/webapi/text-to-image/[provider]/route.ts +0 -74
|
@@ -53,8 +53,28 @@ const Render = memo<RenderProps>(
|
|
|
53
53
|
toolMessageId,
|
|
54
54
|
isArgumentsStreaming,
|
|
55
55
|
}) => {
|
|
56
|
+
if (toolMessageId && intervention?.status === 'pending') {
|
|
57
|
+
return (
|
|
58
|
+
<Intervention
|
|
59
|
+
apiName={apiName}
|
|
60
|
+
id={toolMessageId}
|
|
61
|
+
identifier={identifier}
|
|
62
|
+
requestArgs={requestArgs || ''}
|
|
63
|
+
toolCallId={toolCallId}
|
|
64
|
+
/>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (intervention?.status === 'rejected') {
|
|
69
|
+
return <RejectedResponse reason={intervention.rejectedReason} />;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (intervention?.status === 'aborted') {
|
|
73
|
+
return <AbortResponse />;
|
|
74
|
+
}
|
|
75
|
+
|
|
56
76
|
// Handle arguments streaming state
|
|
57
|
-
if (isArgumentsStreaming) {
|
|
77
|
+
if (isArgumentsStreaming || !result) {
|
|
58
78
|
// Check if there's a custom streaming renderer for this tool
|
|
59
79
|
const StreamingRenderer = getBuiltinStreaming(identifier, apiName);
|
|
60
80
|
|
|
@@ -76,28 +96,6 @@ const Render = memo<RenderProps>(
|
|
|
76
96
|
return null;
|
|
77
97
|
}
|
|
78
98
|
|
|
79
|
-
if (toolMessageId && intervention?.status === 'pending') {
|
|
80
|
-
return (
|
|
81
|
-
<Intervention
|
|
82
|
-
apiName={apiName}
|
|
83
|
-
id={toolMessageId}
|
|
84
|
-
identifier={identifier}
|
|
85
|
-
requestArgs={requestArgs || ''}
|
|
86
|
-
toolCallId={toolCallId}
|
|
87
|
-
/>
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (intervention?.status === 'rejected') {
|
|
92
|
-
return <RejectedResponse reason={intervention.rejectedReason} />;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (intervention?.status === 'aborted') {
|
|
96
|
-
return <AbortResponse />;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (!result) return null;
|
|
100
|
-
|
|
101
99
|
// Handle error state
|
|
102
100
|
if (result.error) {
|
|
103
101
|
return (
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Flexbox } from '@lobehub/ui';
|
|
1
|
+
import { Flexbox, Highlighter } from '@lobehub/ui';
|
|
2
2
|
import { memo, useCallback } from 'react';
|
|
3
3
|
|
|
4
4
|
import { LOADING_FLAT } from '@/const/message';
|
|
@@ -33,18 +33,31 @@ const ContentBlock = memo<ContentBlockProps>(
|
|
|
33
33
|
continueGeneration(assistantId);
|
|
34
34
|
}, [id]);
|
|
35
35
|
|
|
36
|
-
if (error && (content === LOADING_FLAT || !content))
|
|
36
|
+
if (error && (content === LOADING_FLAT || !content)) {
|
|
37
37
|
return (
|
|
38
38
|
<ErrorContent
|
|
39
39
|
error={
|
|
40
40
|
errorContent && error && (content === LOADING_FLAT || !content)
|
|
41
|
-
?
|
|
41
|
+
? {
|
|
42
|
+
...errorContent,
|
|
43
|
+
extra: error?.body && (
|
|
44
|
+
<Highlighter
|
|
45
|
+
actionIconSize={'small'}
|
|
46
|
+
language={'json'}
|
|
47
|
+
padding={8}
|
|
48
|
+
variant={'borderless'}
|
|
49
|
+
>
|
|
50
|
+
{JSON.stringify(error?.body, null, 2)}
|
|
51
|
+
</Highlighter>
|
|
52
|
+
),
|
|
53
|
+
}
|
|
42
54
|
: undefined
|
|
43
55
|
}
|
|
44
56
|
id={id}
|
|
45
57
|
onRegenerate={handleRegenerate}
|
|
46
58
|
/>
|
|
47
59
|
);
|
|
60
|
+
}
|
|
48
61
|
|
|
49
62
|
return (
|
|
50
63
|
<Flexbox gap={8} id={id}>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { Block, Text } from '@lobehub/ui';
|
|
4
3
|
import { memo } from 'react';
|
|
5
4
|
|
|
6
5
|
import { type TaskDetail } from '@/types/index';
|
|
@@ -17,25 +16,23 @@ interface TaskDetailPanelProps {
|
|
|
17
16
|
taskDetail?: TaskDetail;
|
|
18
17
|
}
|
|
19
18
|
|
|
20
|
-
const TaskDetailPanel = memo<TaskDetailPanelProps>(
|
|
21
|
-
(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
},
|
|
38
|
-
);
|
|
19
|
+
const TaskDetailPanel = memo<TaskDetailPanelProps>(({ taskDetail, content, messageId }) => {
|
|
20
|
+
return (
|
|
21
|
+
<>
|
|
22
|
+
{/* Instruction Header */}
|
|
23
|
+
{/*{instruction && (*/}
|
|
24
|
+
{/* <Block padding={12}>*/}
|
|
25
|
+
{/* <Text fontSize={13} type={'secondary'}>*/}
|
|
26
|
+
{/* {instruction}*/}
|
|
27
|
+
{/* </Text>*/}
|
|
28
|
+
{/* </Block>*/}
|
|
29
|
+
{/*)}*/}
|
|
30
|
+
|
|
31
|
+
{/* Status Content */}
|
|
32
|
+
<StatusContent content={content} messageId={messageId} taskDetail={taskDetail} />
|
|
33
|
+
</>
|
|
34
|
+
);
|
|
35
|
+
});
|
|
39
36
|
|
|
40
37
|
TaskDetailPanel.displayName = 'TaskDetailPanel';
|
|
41
38
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { Alert, Flexbox } from '@lobehub/ui';
|
|
3
|
+
import { Alert, Flexbox, Highlighter } from '@lobehub/ui';
|
|
4
4
|
import { createStaticStyles } from 'antd-style';
|
|
5
5
|
import { MessageSquare, Timer, Wrench } from 'lucide-react';
|
|
6
6
|
import { memo, useMemo } from 'react';
|
|
@@ -49,23 +49,28 @@ const ErrorState = memo<ErrorStateProps>(({ taskDetail }) => {
|
|
|
49
49
|
const formattedDuration = useMemo(() => formatDuration(duration), [duration]);
|
|
50
50
|
const formattedCost = useMemo(() => formatCost(totalCost), [totalCost]);
|
|
51
51
|
|
|
52
|
-
const hasMetrics = formattedDuration || totalToolCalls || totalMessages || formattedCost;
|
|
52
|
+
const hasMetrics = !!(formattedDuration || totalToolCalls || totalMessages || formattedCost);
|
|
53
53
|
|
|
54
54
|
return (
|
|
55
55
|
<Flexbox gap={12}>
|
|
56
56
|
{/* Error Content */}
|
|
57
57
|
<Alert
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
extra={
|
|
59
|
+
error?.error?.body && (
|
|
60
|
+
<Highlighter
|
|
61
|
+
actionIconSize={'small'}
|
|
62
|
+
language={'json'}
|
|
63
|
+
padding={8}
|
|
64
|
+
variant={'borderless'}
|
|
65
|
+
>
|
|
66
|
+
{JSON.stringify(error?.error?.body, null, 2)}
|
|
67
|
+
</Highlighter>
|
|
68
|
+
)
|
|
63
69
|
}
|
|
70
|
+
title={isCancelled ? t('task.status.cancelled') : t('task.status.failed')}
|
|
64
71
|
type={'secondary'}
|
|
65
72
|
/>
|
|
66
|
-
|
|
67
|
-
{/* Footer with metrics */}
|
|
68
|
-
{hasMetrics && (
|
|
73
|
+
{hasMetrics ? (
|
|
69
74
|
<Flexbox align="center" gap={12} horizontal wrap="wrap">
|
|
70
75
|
{/* Duration */}
|
|
71
76
|
{formattedDuration && <MetricItem icon={Timer} value={formattedDuration} />}
|
|
@@ -102,7 +107,7 @@ const ErrorState = memo<ErrorStateProps>(({ taskDetail }) => {
|
|
|
102
107
|
</>
|
|
103
108
|
)}
|
|
104
109
|
</Flexbox>
|
|
105
|
-
)}
|
|
110
|
+
) : null}
|
|
106
111
|
</Flexbox>
|
|
107
112
|
);
|
|
108
113
|
});
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
import { Flexbox, Text } from '@lobehub/ui';
|
|
4
4
|
import { createStaticStyles, keyframes } from 'antd-style';
|
|
5
|
-
import { Loader2 } from 'lucide-react';
|
|
6
5
|
import { memo } from 'react';
|
|
7
6
|
import { useTranslation } from 'react-i18next';
|
|
8
7
|
|
|
8
|
+
import NeuralNetworkLoading from '@/components/NeuralNetworkLoading';
|
|
9
|
+
import { shinyTextStyles } from '@/styles';
|
|
10
|
+
|
|
9
11
|
const shimmer = keyframes`
|
|
10
12
|
0% {
|
|
11
13
|
transform: translateX(-100%);
|
|
@@ -16,20 +18,9 @@ const shimmer = keyframes`
|
|
|
16
18
|
}
|
|
17
19
|
`;
|
|
18
20
|
|
|
19
|
-
const spin = keyframes`
|
|
20
|
-
from {
|
|
21
|
-
transform: rotate(0deg);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
to {
|
|
25
|
-
transform: rotate(360deg);
|
|
26
|
-
}
|
|
27
|
-
`;
|
|
28
|
-
|
|
29
21
|
const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
30
22
|
container: css`
|
|
31
23
|
padding-block: 12px;
|
|
32
|
-
padding-inline: 16px;
|
|
33
24
|
`,
|
|
34
25
|
progress: css`
|
|
35
26
|
position: relative;
|
|
@@ -53,9 +44,6 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
|
53
44
|
|
|
54
45
|
animation: ${shimmer} 2s infinite;
|
|
55
46
|
`,
|
|
56
|
-
spin: css`
|
|
57
|
-
animation: ${spin} 1s linear infinite;
|
|
58
|
-
`,
|
|
59
47
|
}));
|
|
60
48
|
|
|
61
49
|
const InitializingState = memo(() => {
|
|
@@ -63,15 +51,13 @@ const InitializingState = memo(() => {
|
|
|
63
51
|
|
|
64
52
|
return (
|
|
65
53
|
<Flexbox className={styles.container} gap={12}>
|
|
66
|
-
{/* Status Row */}
|
|
67
54
|
<Flexbox align="center" gap={8} horizontal>
|
|
68
|
-
<
|
|
69
|
-
<Text
|
|
70
|
-
{t('task.status.initializing'
|
|
55
|
+
<NeuralNetworkLoading size={14} />
|
|
56
|
+
<Text className={shinyTextStyles.shinyText} weight={500}>
|
|
57
|
+
{t('task.status.initializing')}
|
|
71
58
|
</Text>
|
|
72
59
|
</Flexbox>
|
|
73
60
|
|
|
74
|
-
{/* Progress Bar (indeterminate) */}
|
|
75
61
|
<div className={styles.progress}>
|
|
76
62
|
<div className={styles.progressShimmer} />
|
|
77
63
|
</div>
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
import { type TaskDetail } from '@lobechat/types';
|
|
4
4
|
import { Flexbox, Text } from '@lobehub/ui';
|
|
5
5
|
import { createStaticStyles, keyframes } from 'antd-style';
|
|
6
|
-
import { Footprints,
|
|
6
|
+
import { Footprints, Timer, Wrench } from 'lucide-react';
|
|
7
7
|
import { memo, useEffect, useState } from 'react';
|
|
8
8
|
import { useTranslation } from 'react-i18next';
|
|
9
9
|
|
|
10
|
+
import NeuralNetworkLoading from '@/components/NeuralNetworkLoading';
|
|
10
11
|
import { useChatStore } from '@/store/chat';
|
|
11
12
|
|
|
12
13
|
import { MAX_PROGRESS, PROGRESS_INCREMENT, PROGRESS_INTERVAL } from './constants';
|
|
@@ -22,16 +23,6 @@ const shimmer = keyframes`
|
|
|
22
23
|
}
|
|
23
24
|
`;
|
|
24
25
|
|
|
25
|
-
const spin = keyframes`
|
|
26
|
-
from {
|
|
27
|
-
transform: rotate(0deg);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
to {
|
|
31
|
-
transform: rotate(360deg);
|
|
32
|
-
}
|
|
33
|
-
`;
|
|
34
|
-
|
|
35
26
|
const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
36
27
|
activityRow: css`
|
|
37
28
|
display: flex;
|
|
@@ -52,7 +43,7 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
|
52
43
|
|
|
53
44
|
height: 3px;
|
|
54
45
|
margin-block: 12px;
|
|
55
|
-
margin-inline:
|
|
46
|
+
margin-inline: 8px;
|
|
56
47
|
border-radius: 2px;
|
|
57
48
|
|
|
58
49
|
background: ${cssVar.colorFillSecondary};
|
|
@@ -97,9 +88,6 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
|
97
88
|
border-radius: 50%;
|
|
98
89
|
background: ${cssVar.colorTextQuaternary};
|
|
99
90
|
`,
|
|
100
|
-
spin: css`
|
|
101
|
-
animation: ${spin} 1s linear infinite;
|
|
102
|
-
`,
|
|
103
91
|
}));
|
|
104
92
|
|
|
105
93
|
export type ProcessingStateVariant = 'detail' | 'compact';
|
|
@@ -215,10 +203,12 @@ const ProcessingState = memo<ProcessingStateProps>(
|
|
|
215
203
|
{/* Current Activity */}
|
|
216
204
|
{currentActivity && (
|
|
217
205
|
<div className={styles.activityRow}>
|
|
218
|
-
<
|
|
219
|
-
<
|
|
220
|
-
<span
|
|
221
|
-
|
|
206
|
+
<Flexbox align={'center'} gap={4} horizontal>
|
|
207
|
+
<NeuralNetworkLoading size={14} />
|
|
208
|
+
<Text as={'span'} fontSize={12} type={'secondary'}>
|
|
209
|
+
{renderActivityText()}
|
|
210
|
+
</Text>
|
|
211
|
+
</Flexbox>
|
|
222
212
|
{currentActivity.contentPreview && (
|
|
223
213
|
<Text
|
|
224
214
|
as={'span'}
|
|
@@ -297,7 +287,7 @@ const ProcessingState = memo<ProcessingStateProps>(
|
|
|
297
287
|
{/* Current Activity */}
|
|
298
288
|
{currentActivity && (
|
|
299
289
|
<Flexbox align="center" gap={8} horizontal>
|
|
300
|
-
<
|
|
290
|
+
<NeuralNetworkLoading size={14} />
|
|
301
291
|
<Text
|
|
302
292
|
as={'span'}
|
|
303
293
|
ellipsis
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { Flexbox, type FlexboxProps,
|
|
3
|
+
import { Flexbox, type FlexboxProps, Tooltip } from '@lobehub/ui';
|
|
4
4
|
import { Badge } from 'antd';
|
|
5
5
|
import { createStaticStyles, cssVar } from 'antd-style';
|
|
6
6
|
import { isUndefined } from 'es-toolkit/compat';
|
|
7
|
-
import {
|
|
8
|
-
import { memo, useMemo } from 'react';
|
|
7
|
+
import { memo } from 'react';
|
|
9
8
|
import { useTranslation } from 'react-i18next';
|
|
10
9
|
|
|
10
|
+
import NeuralNetworkLoading from '@/components/NeuralNetworkLoading';
|
|
11
11
|
import { useClientDataSWR } from '@/libs/swr';
|
|
12
12
|
import { messageService } from '@/services/message';
|
|
13
13
|
import { sessionService } from '@/services/session';
|
|
@@ -65,7 +65,7 @@ const DataStatistics = memo<Omit<FlexboxProps, 'children'>>(({ style, ...rest })
|
|
|
65
65
|
|
|
66
66
|
const { t } = useTranslation('common');
|
|
67
67
|
|
|
68
|
-
const loading =
|
|
68
|
+
const loading = <NeuralNetworkLoading size={20} />;
|
|
69
69
|
|
|
70
70
|
const items = [
|
|
71
71
|
{
|
|
@@ -43,11 +43,9 @@ export const asyncAuth = asyncTrpc.middleware(async (opts) => {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
log('User authentication successful: %s', ctx.userId);
|
|
46
|
-
log('Passing jwtPayload keys: %O', Object.keys(ctx.jwtPayload || {}));
|
|
47
46
|
|
|
48
47
|
return opts.next({
|
|
49
48
|
ctx: {
|
|
50
|
-
jwtPayload: ctx.jwtPayload,
|
|
51
49
|
userId: ctx.userId,
|
|
52
50
|
},
|
|
53
51
|
});
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { type LobeChatDatabase } from '@lobechat/database';
|
|
2
|
-
import { type ClientSecretPayload } from '@lobechat/types';
|
|
3
2
|
import debug from 'debug';
|
|
4
3
|
import { type NextRequest } from 'next/server';
|
|
5
4
|
|
|
@@ -10,7 +9,6 @@ const log = debug('lobe-async:context');
|
|
|
10
9
|
|
|
11
10
|
export interface AsyncAuthContext {
|
|
12
11
|
authorizationToken?: string;
|
|
13
|
-
jwtPayload: ClientSecretPayload;
|
|
14
12
|
serverDB?: LobeChatDatabase;
|
|
15
13
|
userId?: string | null;
|
|
16
14
|
}
|
|
@@ -21,11 +19,9 @@ export interface AsyncAuthContext {
|
|
|
21
19
|
*/
|
|
22
20
|
export const createAsyncContextInner = async (params?: {
|
|
23
21
|
authorizationToken?: string;
|
|
24
|
-
jwtPayload?: ClientSecretPayload;
|
|
25
22
|
userId?: string | null;
|
|
26
23
|
}): Promise<AsyncAuthContext> => ({
|
|
27
24
|
authorizationToken: params?.authorizationToken,
|
|
28
|
-
jwtPayload: params?.jwtPayload || {},
|
|
29
25
|
userId: params?.userId,
|
|
30
26
|
});
|
|
31
27
|
|
|
@@ -60,15 +56,11 @@ export const createAsyncRouteContext = async (request: NextRequest): Promise<Asy
|
|
|
60
56
|
const { plaintext } = await gateKeeper.decrypt(lobeChatAuthorization);
|
|
61
57
|
|
|
62
58
|
log('Parsing decrypted authorization data');
|
|
63
|
-
const { userId
|
|
59
|
+
const { userId } = JSON.parse(plaintext);
|
|
64
60
|
|
|
65
|
-
log(
|
|
66
|
-
'Successfully parsed authorization data - userId: %s, payload keys: %O',
|
|
67
|
-
userId,
|
|
68
|
-
Object.keys(payload || {}),
|
|
69
|
-
);
|
|
61
|
+
log('Successfully parsed authorization data - userId: %s', userId);
|
|
70
62
|
|
|
71
|
-
return createAsyncContextInner({ authorizationToken: authorization,
|
|
63
|
+
return createAsyncContextInner({ authorizationToken: authorization, userId });
|
|
72
64
|
} catch (error) {
|
|
73
65
|
log('Error creating async route context: %O', error);
|
|
74
66
|
throw error;
|
|
@@ -322,6 +322,8 @@ export default {
|
|
|
322
322
|
'task.batchTasks': '{{count}} Batch Subtasks',
|
|
323
323
|
'task.metrics.stepsShort': 'steps',
|
|
324
324
|
'task.metrics.toolCallsShort': 'tool uses',
|
|
325
|
+
'task.status.cancelled': 'Task Cancelled',
|
|
326
|
+
'task.status.failed': 'Task Failed',
|
|
325
327
|
'task.status.initializing': 'Initializing task...',
|
|
326
328
|
'task.subtask': 'Subtask',
|
|
327
329
|
'thread.divider': 'Subtopic',
|
|
@@ -63,7 +63,8 @@ export default {
|
|
|
63
63
|
'builtins.lobe-gtd.apiName.createPlan.result': 'Create plan: <goal>{{goal}}</goal>',
|
|
64
64
|
'builtins.lobe-gtd.apiName.createTodos': 'Create todos',
|
|
65
65
|
'builtins.lobe-gtd.apiName.execTask': 'Execute task',
|
|
66
|
-
'builtins.lobe-gtd.apiName.execTask.
|
|
66
|
+
'builtins.lobe-gtd.apiName.execTask.completed': 'Task created: ',
|
|
67
|
+
'builtins.lobe-gtd.apiName.execTask.loading': 'Creating task: ',
|
|
67
68
|
'builtins.lobe-gtd.apiName.execTasks': 'Execute tasks',
|
|
68
69
|
'builtins.lobe-gtd.apiName.removeTodos': 'Delete todos',
|
|
69
70
|
'builtins.lobe-gtd.apiName.updatePlan': 'Update plan',
|
|
@@ -8,12 +8,13 @@ import {
|
|
|
8
8
|
} from '@lobechat/agent-runtime';
|
|
9
9
|
import { ToolNameResolver } from '@lobechat/context-engine';
|
|
10
10
|
import { consumeStreamUntilDone } from '@lobechat/model-runtime';
|
|
11
|
-
import { type ChatToolPayload, type
|
|
11
|
+
import { type ChatToolPayload, type MessageToolCall } from '@lobechat/types';
|
|
12
12
|
import { serializePartsForStorage } from '@lobechat/utils';
|
|
13
13
|
import debug from 'debug';
|
|
14
14
|
|
|
15
15
|
import { type MessageModel } from '@/database/models/message';
|
|
16
|
-
import {
|
|
16
|
+
import { type LobeChatDatabase } from '@/database/type';
|
|
17
|
+
import { initModelRuntimeFromDB } from '@/server/modules/ModelRuntime';
|
|
17
18
|
import { type ToolExecutionService } from '@/server/services/toolExecution';
|
|
18
19
|
|
|
19
20
|
import type { IStreamEventManager } from './types';
|
|
@@ -31,11 +32,11 @@ export interface RuntimeExecutorContext {
|
|
|
31
32
|
fileService?: any;
|
|
32
33
|
messageModel: MessageModel;
|
|
33
34
|
operationId: string;
|
|
35
|
+
serverDB: LobeChatDatabase;
|
|
34
36
|
stepIndex: number;
|
|
35
37
|
streamManager: IStreamEventManager;
|
|
36
38
|
toolExecutionService: ToolExecutionService;
|
|
37
39
|
userId?: string;
|
|
38
|
-
userPayload?: ClientSecretPayload;
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
export const createRuntimeExecutors = (
|
|
@@ -120,8 +121,8 @@ export const createRuntimeExecutors = (
|
|
|
120
121
|
let hasContentImages = false;
|
|
121
122
|
let hasReasoningImages = false;
|
|
122
123
|
|
|
123
|
-
// 初始化 ModelRuntime
|
|
124
|
-
const modelRuntime =
|
|
124
|
+
// 初始化 ModelRuntime (从数据库读取用户的 keyVaults)
|
|
125
|
+
const modelRuntime = await initModelRuntimeFromDB(ctx.serverDB, ctx.userId!, provider);
|
|
125
126
|
|
|
126
127
|
// 构造 ChatStreamPayload
|
|
127
128
|
const chatPayload = {
|
|
@@ -467,7 +468,6 @@ export const createRuntimeExecutors = (
|
|
|
467
468
|
const executionResult = await toolExecutionService.executeTool(chatToolPayload, {
|
|
468
469
|
toolManifestMap: state.toolManifestMap,
|
|
469
470
|
userId: ctx.userId,
|
|
470
|
-
userPayload: ctx.userPayload,
|
|
471
471
|
});
|
|
472
472
|
|
|
473
473
|
const executionTime = executionResult.executionTime;
|
|
@@ -5,13 +5,13 @@ import { RuntimeExecutorContext, createRuntimeExecutors } from '../RuntimeExecut
|
|
|
5
5
|
|
|
6
6
|
// Mock dependencies
|
|
7
7
|
vi.mock('@/server/modules/ModelRuntime', () => ({
|
|
8
|
-
|
|
8
|
+
initModelRuntimeFromDB: vi.fn().mockResolvedValue({
|
|
9
9
|
chat: vi.fn().mockResolvedValue({
|
|
10
10
|
[Symbol.asyncIterator]: async function* () {
|
|
11
11
|
yield { type: 'text', text: 'Hello' };
|
|
12
12
|
},
|
|
13
13
|
}),
|
|
14
|
-
})
|
|
14
|
+
}),
|
|
15
15
|
}));
|
|
16
16
|
|
|
17
17
|
vi.mock('@lobechat/model-runtime', () => ({
|
|
@@ -50,11 +50,11 @@ describe('RuntimeExecutors', () => {
|
|
|
50
50
|
ctx = {
|
|
51
51
|
messageModel: mockMessageModel,
|
|
52
52
|
operationId: 'op-123',
|
|
53
|
+
serverDB: {} as any, // Mock serverDB
|
|
53
54
|
stepIndex: 0,
|
|
54
55
|
streamManager: mockStreamManager,
|
|
55
56
|
toolExecutionService: mockToolExecutionService,
|
|
56
57
|
userId: 'user-123',
|
|
57
|
-
userPayload: {},
|
|
58
58
|
};
|
|
59
59
|
});
|
|
60
60
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import debug from 'debug';
|
|
2
2
|
|
|
3
|
+
import { appEnv } from '@/envs/app';
|
|
4
|
+
|
|
3
5
|
import { AgentStateManager } from './AgentStateManager';
|
|
4
6
|
import { inMemoryAgentStateManager } from './InMemoryAgentStateManager';
|
|
5
|
-
import {
|
|
6
|
-
inMemoryStreamEventManager,
|
|
7
|
-
} from './InMemoryStreamEventManager';
|
|
7
|
+
import { inMemoryStreamEventManager } from './InMemoryStreamEventManager';
|
|
8
8
|
import { StreamEventManager } from './StreamEventManager';
|
|
9
9
|
import { getAgentRuntimeRedisClient } from './redis';
|
|
10
10
|
import type { IAgentStateManager, IStreamEventManager } from './types';
|
|
@@ -19,33 +19,52 @@ export const isRedisAvailable = (): boolean => {
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
* Check if queue-based agent runtime is enabled
|
|
23
|
+
* When disabled (default), use InMemory implementations for local/simple deployments
|
|
24
|
+
*/
|
|
25
|
+
const isQueueModeEnabled = (): boolean => {
|
|
26
|
+
return appEnv.enableQueueAgentRuntime === true;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Create AgentStateManager based on configuration
|
|
26
31
|
*/
|
|
27
32
|
export const createAgentStateManager = (): IAgentStateManager => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
// When queue mode is disabled, always use InMemory for simplicity
|
|
34
|
+
if (!isQueueModeEnabled()) {
|
|
35
|
+
log('Queue mode disabled, using InMemoryAgentStateManager');
|
|
36
|
+
return inMemoryAgentStateManager;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Queue mode enabled, Redis is required
|
|
40
|
+
if (!isRedisAvailable()) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
'Redis is required when AGENT_RUNTIME_MODE=queue. Please configure `REDIS_URL`.',
|
|
43
|
+
);
|
|
31
44
|
}
|
|
32
45
|
|
|
33
|
-
|
|
34
|
-
return inMemoryAgentStateManager;
|
|
46
|
+
return new AgentStateManager();
|
|
35
47
|
};
|
|
36
48
|
|
|
37
49
|
/**
|
|
38
|
-
* Create StreamEventManager based on
|
|
50
|
+
* Create StreamEventManager based on configuration
|
|
39
51
|
*
|
|
40
|
-
* -
|
|
41
|
-
* -
|
|
52
|
+
* - If enableQueueAgentRuntime=false (default): InMemoryStreamEventManager
|
|
53
|
+
* - If enableQueueAgentRuntime=true: RedisStreamEventManager (requires Redis)
|
|
42
54
|
*/
|
|
43
55
|
export const createStreamEventManager = (): IStreamEventManager => {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
56
|
+
// When queue mode is disabled, always use InMemory for simplicity
|
|
57
|
+
if (!isQueueModeEnabled()) {
|
|
58
|
+
log('Queue mode disabled, using InMemoryStreamEventManager');
|
|
59
|
+
return inMemoryStreamEventManager;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Queue mode enabled, Redis is required
|
|
63
|
+
if (!isRedisAvailable()) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
'Redis is required when AGENT_RUNTIME_MODE=queue. Please configure `REDIS_URL`.',
|
|
66
|
+
);
|
|
47
67
|
}
|
|
48
68
|
|
|
49
|
-
|
|
50
|
-
return inMemoryStreamEventManager;
|
|
69
|
+
return new StreamEventManager();
|
|
51
70
|
};
|