@lobehub/chat 1.0.11 → 1.0.13
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 +50 -0
- package/locales/ar/setting.json +5 -0
- package/locales/bg-BG/setting.json +5 -0
- package/locales/de-DE/setting.json +5 -0
- package/locales/en-US/setting.json +5 -0
- package/locales/es-ES/setting.json +5 -0
- package/locales/fr-FR/setting.json +5 -0
- package/locales/it-IT/setting.json +5 -0
- package/locales/ja-JP/setting.json +5 -0
- package/locales/ko-KR/setting.json +5 -0
- package/locales/nl-NL/setting.json +5 -0
- package/locales/pl-PL/setting.json +5 -0
- package/locales/pt-BR/setting.json +5 -0
- package/locales/ru-RU/setting.json +5 -0
- package/locales/tr-TR/setting.json +5 -0
- package/locales/vi-VN/setting.json +5 -0
- package/locales/zh-CN/setting.json +5 -0
- package/locales/zh-TW/setting.json +5 -0
- package/package.json +4 -3
- package/src/app/(main)/chat/(workspace)/@conversation/default.tsx +1 -1
- package/src/app/(main)/chat/settings/features/EditPage.tsx +2 -2
- package/src/app/(main)/settings/agent/index.tsx +1 -1
- package/src/app/(main)/settings/system-agent/features/AgentMeta.tsx +58 -0
- package/src/app/(main)/settings/system-agent/features/Topic.tsx +1 -0
- package/src/app/(main)/settings/system-agent/features/Translation.tsx +1 -0
- package/src/app/(main)/settings/system-agent/index.tsx +2 -0
- package/src/app/(main)/settings/system-agent/page.tsx +1 -1
- package/src/const/settings/systemAgent.ts +1 -0
- package/src/features/AgentSetting/AgentMeta/AutoGenerateAvatar.tsx +59 -0
- package/src/features/AgentSetting/AgentMeta/index.tsx +6 -9
- package/src/features/AgentSetting/AgentSettings.tsx +24 -0
- package/src/features/AgentSetting/AgentSettingsStore.tsx +14 -0
- package/src/features/AgentSetting/StoreUpdater.tsx +10 -5
- package/src/features/AgentSetting/hooks/useAgentSettings.ts +31 -0
- package/src/features/AgentSetting/index.tsx +3 -26
- package/src/features/AgentSetting/store/action.ts +36 -18
- package/src/features/ChatInput/useSend.ts +8 -0
- package/src/features/Conversation/Error/ErrorJsonViewer.tsx +1 -1
- package/src/features/Conversation/Messages/Assistant/ToolCalls/index.tsx +3 -2
- package/src/features/Conversation/Messages/Tool/index.tsx +3 -5
- package/src/features/Conversation/Messages/components/Arguments.tsx +20 -0
- package/src/features/Conversation/Messages/hooks/useYamlArguments.ts +11 -0
- package/src/features/ModelSelect/index.tsx +6 -4
- package/src/libs/agent-runtime/anthropic/index.test.ts +1 -31
- package/src/libs/agent-runtime/anthropic/index.ts +9 -63
- package/src/libs/agent-runtime/openai/index.test.ts +7 -7
- package/src/libs/agent-runtime/openai/index.ts +0 -6
- package/src/libs/agent-runtime/utils/anthropicHelpers.ts +2 -2
- package/src/libs/agent-runtime/utils/streams/anthropic.test.ts +102 -28
- package/src/libs/agent-runtime/utils/streams/anthropic.ts +29 -12
- package/src/libs/agent-runtime/utils/streams/protocol.ts +6 -1
- package/src/locales/default/setting.ts +5 -0
- package/src/services/message/server.ts +4 -0
- package/src/services/message/type.ts +1 -1
- package/src/store/agent/slices/chat/initialState.ts +2 -0
- package/src/store/chat/slices/message/action.ts +48 -48
- package/src/store/chat/slices/message/initialState.ts +2 -0
- package/src/store/chat/slices/message/selectors.ts +3 -0
- package/src/store/chat/slices/plugin/action.test.ts +15 -15
- package/src/store/chat/slices/plugin/action.ts +128 -115
- package/src/store/chat/utils/index.ts +19 -0
- package/src/store/user/slices/settings/action.ts +8 -2
- package/src/store/user/slices/settings/selectors/systemAgent.ts +2 -0
- package/src/types/message/index.ts +1 -1
- package/src/types/user/settings/systemAgent.ts +3 -0
- /package/src/{components/StoreHydration → app/(main)/chat/(workspace)/@conversation/features}/ChatHydration/index.tsx +0 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
|
|
3
|
+
import { useStoreApi } from '../store';
|
|
4
|
+
import { PublicAction } from '../store/action';
|
|
5
|
+
|
|
6
|
+
export type AgentSettingsInstance = PublicAction;
|
|
7
|
+
|
|
8
|
+
export const useAgentSettings = (): AgentSettingsInstance => {
|
|
9
|
+
const storeApi = useStoreApi();
|
|
10
|
+
|
|
11
|
+
const {
|
|
12
|
+
autocompleteMeta,
|
|
13
|
+
autocompleteAllMeta,
|
|
14
|
+
autocompleteAgentTitle,
|
|
15
|
+
autocompleteAgentDescription,
|
|
16
|
+
autocompleteAgentTags,
|
|
17
|
+
autoPickEmoji,
|
|
18
|
+
} = storeApi.getState();
|
|
19
|
+
|
|
20
|
+
return useMemo(
|
|
21
|
+
() => ({
|
|
22
|
+
autoPickEmoji,
|
|
23
|
+
autocompleteAgentDescription,
|
|
24
|
+
autocompleteAgentTags,
|
|
25
|
+
autocompleteAgentTitle,
|
|
26
|
+
autocompleteAllMeta,
|
|
27
|
+
autocompleteMeta,
|
|
28
|
+
}),
|
|
29
|
+
[],
|
|
30
|
+
);
|
|
31
|
+
};
|
|
@@ -1,26 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import AgentPlugin from './AgentPlugin';
|
|
5
|
-
import AgentPrompt from './AgentPrompt';
|
|
6
|
-
import AgentTTS from './AgentTTS';
|
|
7
|
-
import StoreUpdater, { StoreUpdaterProps } from './StoreUpdater';
|
|
8
|
-
import { Provider, createStore } from './store';
|
|
9
|
-
|
|
10
|
-
type AgentSettingsProps = StoreUpdaterProps;
|
|
11
|
-
|
|
12
|
-
const AgentSettings = (props: AgentSettingsProps) => {
|
|
13
|
-
return (
|
|
14
|
-
<Provider createStore={createStore}>
|
|
15
|
-
<StoreUpdater {...props} />
|
|
16
|
-
<AgentPrompt />
|
|
17
|
-
<AgentMeta />
|
|
18
|
-
<AgentChat />
|
|
19
|
-
<AgentModal />
|
|
20
|
-
<AgentTTS />
|
|
21
|
-
<AgentPlugin />
|
|
22
|
-
</Provider>
|
|
23
|
-
);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export default AgentSettings;
|
|
1
|
+
export { AgentSettings } from './AgentSettings';
|
|
2
|
+
export { AgentSettingsStore } from './AgentSettingsStore';
|
|
3
|
+
export type { AgentSettingsInstance } from './hooks/useAgentSettings';
|
|
@@ -7,9 +7,13 @@ import { chainSummaryDescription } from '@/chains/summaryDescription';
|
|
|
7
7
|
import { chainSummaryTags } from '@/chains/summaryTags';
|
|
8
8
|
import { TraceNameMap, TracePayload, TraceTopicType } from '@/const/trace';
|
|
9
9
|
import { chatService } from '@/services/chat';
|
|
10
|
+
import { useUserStore } from '@/store/user';
|
|
11
|
+
import { systemAgentSelectors } from '@/store/user/slices/settings/selectors';
|
|
10
12
|
import { LobeAgentChatConfig, LobeAgentConfig } from '@/types/agent';
|
|
11
13
|
import { MetaData } from '@/types/meta';
|
|
14
|
+
import { SystemAgentItem } from '@/types/user/settings';
|
|
12
15
|
import { MessageTextChunk } from '@/utils/fetch';
|
|
16
|
+
import { merge } from '@/utils/merge';
|
|
13
17
|
import { setNamespace } from '@/utils/storeDebug';
|
|
14
18
|
|
|
15
19
|
import { SessionLoadingState } from '../store/initialState';
|
|
@@ -17,15 +21,12 @@ import { State, initialState } from './initialState';
|
|
|
17
21
|
import { ConfigDispatch, configReducer } from './reducers/config';
|
|
18
22
|
import { MetaDataDispatch, metaDataReducer } from './reducers/meta';
|
|
19
23
|
|
|
20
|
-
|
|
21
|
-
* 设置操作
|
|
22
|
-
*/
|
|
23
|
-
export interface Action {
|
|
24
|
+
export interface PublicAction {
|
|
24
25
|
/**
|
|
25
26
|
* 自动选择表情
|
|
26
27
|
* @param id - 表情的 ID
|
|
27
28
|
*/
|
|
28
|
-
autoPickEmoji: () => void
|
|
29
|
+
autoPickEmoji: () => Promise<void>;
|
|
29
30
|
/**
|
|
30
31
|
* 自动完成代理描述
|
|
31
32
|
* @param id - 代理的 ID
|
|
@@ -44,20 +45,25 @@ export interface Action {
|
|
|
44
45
|
*/
|
|
45
46
|
autocompleteAllMeta: (replace?: boolean) => void;
|
|
46
47
|
autocompleteMeta: (key: keyof MetaData) => void;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface Action extends PublicAction {
|
|
47
51
|
dispatchConfig: (payload: ConfigDispatch) => void;
|
|
48
52
|
dispatchMeta: (payload: MetaDataDispatch) => void;
|
|
49
53
|
getCurrentTracePayload: (data: Partial<TracePayload>) => TracePayload;
|
|
50
54
|
|
|
55
|
+
internal_getSystemAgentForMeta: () => SystemAgentItem;
|
|
51
56
|
resetAgentConfig: () => void;
|
|
52
|
-
resetAgentMeta: () => void;
|
|
53
57
|
|
|
58
|
+
resetAgentMeta: () => void;
|
|
54
59
|
setAgentConfig: (config: DeepPartial<LobeAgentConfig>) => void;
|
|
55
60
|
setAgentMeta: (meta: Partial<MetaData>) => void;
|
|
56
|
-
setChatConfig: (config: Partial<LobeAgentChatConfig>) => void;
|
|
57
61
|
|
|
62
|
+
setChatConfig: (config: Partial<LobeAgentChatConfig>) => void;
|
|
58
63
|
streamUpdateMetaArray: (key: keyof MetaData) => any;
|
|
59
64
|
streamUpdateMetaString: (key: keyof MetaData) => any;
|
|
60
65
|
toggleAgentPlugin: (pluginId: string, state?: boolean) => void;
|
|
66
|
+
|
|
61
67
|
/**
|
|
62
68
|
* 更新加载状态
|
|
63
69
|
* @param key - SessionLoadingState 的键
|
|
@@ -77,17 +83,19 @@ export const store: StateCreator<Store, [['zustand/devtools', never]]> = (set, g
|
|
|
77
83
|
|
|
78
84
|
const systemRole = config.systemRole;
|
|
79
85
|
|
|
80
|
-
|
|
86
|
+
chatService.fetchPresetTaskResult({
|
|
87
|
+
onFinish: async (emoji) => {
|
|
88
|
+
dispatchMeta({ type: 'update', value: { avatar: emoji } });
|
|
89
|
+
},
|
|
81
90
|
onLoadingChange: (loading) => {
|
|
82
91
|
get().updateLoadingState('avatar', loading);
|
|
83
92
|
},
|
|
84
|
-
params:
|
|
93
|
+
params: merge(
|
|
94
|
+
get().internal_getSystemAgentForMeta(),
|
|
95
|
+
chainPickEmoji([meta.title, meta.description, systemRole].filter(Boolean).join(',')),
|
|
96
|
+
),
|
|
85
97
|
trace: get().getCurrentTracePayload({ traceName: TraceNameMap.EmojiPicker }),
|
|
86
98
|
});
|
|
87
|
-
|
|
88
|
-
if (emoji) {
|
|
89
|
-
dispatchMeta({ type: 'update', value: { avatar: emoji } });
|
|
90
|
-
}
|
|
91
99
|
},
|
|
92
100
|
autocompleteAgentDescription: async () => {
|
|
93
101
|
const { dispatchMeta, config, meta, updateLoadingState, streamUpdateMetaString } = get();
|
|
@@ -109,7 +117,7 @@ export const store: StateCreator<Store, [['zustand/devtools', never]]> = (set, g
|
|
|
109
117
|
updateLoadingState('description', loading);
|
|
110
118
|
},
|
|
111
119
|
onMessageHandle: streamUpdateMetaString('description'),
|
|
112
|
-
params: chainSummaryDescription(systemRole),
|
|
120
|
+
params: merge(get().internal_getSystemAgentForMeta(), chainSummaryDescription(systemRole)),
|
|
113
121
|
trace: get().getCurrentTracePayload({ traceName: TraceNameMap.SummaryAgentDescription }),
|
|
114
122
|
});
|
|
115
123
|
},
|
|
@@ -125,6 +133,7 @@ export const store: StateCreator<Store, [['zustand/devtools', never]]> = (set, g
|
|
|
125
133
|
// 替换为 ...
|
|
126
134
|
dispatchMeta({ type: 'update', value: { tags: ['...'] } });
|
|
127
135
|
|
|
136
|
+
// Get current agent for agentMeta
|
|
128
137
|
chatService.fetchPresetTaskResult({
|
|
129
138
|
onError: () => {
|
|
130
139
|
dispatchMeta({ type: 'update', value: { tags: preValue } });
|
|
@@ -133,8 +142,9 @@ export const store: StateCreator<Store, [['zustand/devtools', never]]> = (set, g
|
|
|
133
142
|
updateLoadingState('tags', loading);
|
|
134
143
|
},
|
|
135
144
|
onMessageHandle: streamUpdateMetaArray('tags'),
|
|
136
|
-
params:
|
|
137
|
-
|
|
145
|
+
params: merge(
|
|
146
|
+
get().internal_getSystemAgentForMeta(),
|
|
147
|
+
chainSummaryTags([meta.title, meta.description, systemRole].filter(Boolean).join(',')),
|
|
138
148
|
),
|
|
139
149
|
trace: get().getCurrentTracePayload({ traceName: TraceNameMap.SummaryAgentTags }),
|
|
140
150
|
});
|
|
@@ -159,7 +169,10 @@ export const store: StateCreator<Store, [['zustand/devtools', never]]> = (set, g
|
|
|
159
169
|
updateLoadingState('title', loading);
|
|
160
170
|
},
|
|
161
171
|
onMessageHandle: streamUpdateMetaString('title'),
|
|
162
|
-
params:
|
|
172
|
+
params: merge(
|
|
173
|
+
get().internal_getSystemAgentForMeta(),
|
|
174
|
+
chainSummaryAgentName([meta.description, systemRole].filter(Boolean).join(',')),
|
|
175
|
+
),
|
|
163
176
|
trace: get().getCurrentTracePayload({ traceName: TraceNameMap.SummaryAgentTitle }),
|
|
164
177
|
});
|
|
165
178
|
},
|
|
@@ -231,6 +244,11 @@ export const store: StateCreator<Store, [['zustand/devtools', never]]> = (set, g
|
|
|
231
244
|
topicId: TraceTopicType.AgentSettings,
|
|
232
245
|
...data,
|
|
233
246
|
}),
|
|
247
|
+
|
|
248
|
+
internal_getSystemAgentForMeta: () => {
|
|
249
|
+
return systemAgentSelectors.agentMeta(useUserStore.getState());
|
|
250
|
+
},
|
|
251
|
+
|
|
234
252
|
resetAgentConfig: () => {
|
|
235
253
|
get().dispatchConfig({ type: 'reset' });
|
|
236
254
|
},
|
|
@@ -238,13 +256,13 @@ export const store: StateCreator<Store, [['zustand/devtools', never]]> = (set, g
|
|
|
238
256
|
resetAgentMeta: () => {
|
|
239
257
|
get().dispatchMeta({ type: 'reset' });
|
|
240
258
|
},
|
|
241
|
-
|
|
242
259
|
setAgentConfig: (config) => {
|
|
243
260
|
get().dispatchConfig({ config, type: 'update' });
|
|
244
261
|
},
|
|
245
262
|
setAgentMeta: (meta) => {
|
|
246
263
|
get().dispatchMeta({ type: 'update', value: meta });
|
|
247
264
|
},
|
|
265
|
+
|
|
248
266
|
setChatConfig: (config) => {
|
|
249
267
|
get().setAgentConfig({ chatConfig: config });
|
|
250
268
|
},
|
|
@@ -31,5 +31,13 @@ export const useSendMessage = () => {
|
|
|
31
31
|
|
|
32
32
|
updateInputMessage('');
|
|
33
33
|
useFileStore.getState().clearImageList();
|
|
34
|
+
|
|
35
|
+
// const hasSystemRole = agentSelectors.hasSystemRole(useAgentStore.getState());
|
|
36
|
+
// const agentSetting = useAgentStore.getState().agentSettingInstance;
|
|
37
|
+
|
|
38
|
+
// // if there is a system role, then we need to use agent setting instance to autocomplete agent meta
|
|
39
|
+
// if (hasSystemRole && !!agentSetting) {
|
|
40
|
+
// agentSetting.autocompleteAllMeta();
|
|
41
|
+
// }
|
|
34
42
|
}, []);
|
|
35
43
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Avatar,
|
|
1
|
+
import { Avatar, Icon } from '@lobehub/ui';
|
|
2
2
|
import isEqual from 'fast-deep-equal';
|
|
3
3
|
import { Loader2, LucideChevronDown, LucideChevronRight, LucideToyBrick } from 'lucide-react';
|
|
4
4
|
import { CSSProperties, memo, useState } from 'react';
|
|
@@ -10,6 +10,7 @@ import { chatSelectors } from '@/store/chat/selectors';
|
|
|
10
10
|
import { pluginHelpers, useToolStore } from '@/store/tool';
|
|
11
11
|
import { toolSelectors } from '@/store/tool/selectors';
|
|
12
12
|
|
|
13
|
+
import Arguments from '../../components/Arguments';
|
|
13
14
|
import { useStyles } from './style';
|
|
14
15
|
|
|
15
16
|
export interface InspectorProps {
|
|
@@ -64,7 +65,7 @@ const CallItem = memo<InspectorProps>(
|
|
|
64
65
|
</Flexbox>
|
|
65
66
|
<Icon icon={open ? LucideChevronDown : LucideChevronRight} />
|
|
66
67
|
</Flexbox>
|
|
67
|
-
{(open || loading) && <
|
|
68
|
+
{(open || loading) && <Arguments arguments={requestArgs} />}
|
|
68
69
|
</Flexbox>
|
|
69
70
|
);
|
|
70
71
|
},
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Snippet } from '@lobehub/ui';
|
|
2
1
|
import { memo, useState } from 'react';
|
|
3
2
|
import { Flexbox } from 'react-layout-kit';
|
|
4
3
|
|
|
@@ -7,10 +6,11 @@ import { chatSelectors } from '@/store/chat/selectors';
|
|
|
7
6
|
import { ChatMessage } from '@/types/message';
|
|
8
7
|
|
|
9
8
|
import PluginRender from '../../Plugins/Render';
|
|
9
|
+
import Arguments from '../components/Arguments';
|
|
10
10
|
import Inspector from './Inspector';
|
|
11
11
|
|
|
12
12
|
export const ToolMessage = memo<ChatMessage>(({ id, content, plugin }) => {
|
|
13
|
-
const loading = useChatStore(chatSelectors.
|
|
13
|
+
const loading = useChatStore(chatSelectors.isPluginApiInvoking(id));
|
|
14
14
|
|
|
15
15
|
const [showRender, setShow] = useState(plugin?.type !== 'default');
|
|
16
16
|
|
|
@@ -35,9 +35,7 @@ export const ToolMessage = memo<ChatMessage>(({ id, content, plugin }) => {
|
|
|
35
35
|
type={plugin?.type}
|
|
36
36
|
/>
|
|
37
37
|
) : (
|
|
38
|
-
<
|
|
39
|
-
<Snippet>{plugin?.arguments || ''}</Snippet>
|
|
40
|
-
</Flexbox>
|
|
38
|
+
<Arguments arguments={plugin?.arguments} />
|
|
41
39
|
)}
|
|
42
40
|
</Flexbox>
|
|
43
41
|
);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Highlighter } from '@lobehub/ui';
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
|
|
4
|
+
import { useYamlArguments } from '../hooks/useYamlArguments';
|
|
5
|
+
|
|
6
|
+
export interface ArgumentsProps {
|
|
7
|
+
arguments?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const Arguments = memo<ArgumentsProps>(({ arguments: args = '' }) => {
|
|
11
|
+
const yaml = useYamlArguments(args);
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<Highlighter language={'yaml'} showLanguage={false}>
|
|
15
|
+
{yaml}
|
|
16
|
+
</Highlighter>
|
|
17
|
+
);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export default Arguments;
|
|
@@ -10,11 +10,12 @@ import { ModelProviderCard } from '@/types/llm';
|
|
|
10
10
|
|
|
11
11
|
const useStyles = createStyles(({ css, prefixCls }) => ({
|
|
12
12
|
select: css`
|
|
13
|
-
|
|
13
|
+
&.${prefixCls}-select-dropdown .${prefixCls}-select-item-option-grouped {
|
|
14
14
|
padding-inline-start: 12px;
|
|
15
15
|
}
|
|
16
16
|
`,
|
|
17
17
|
}));
|
|
18
|
+
|
|
18
19
|
interface ModelOption {
|
|
19
20
|
label: any;
|
|
20
21
|
provider: string;
|
|
@@ -23,10 +24,11 @@ interface ModelOption {
|
|
|
23
24
|
|
|
24
25
|
interface ModelSelectProps {
|
|
25
26
|
onChange?: (props: { model: string; provider: string }) => void;
|
|
27
|
+
showAbility?: boolean;
|
|
26
28
|
value?: string;
|
|
27
29
|
}
|
|
28
30
|
|
|
29
|
-
const ModelSelect = memo<ModelSelectProps>(({ value, onChange }) => {
|
|
31
|
+
const ModelSelect = memo<ModelSelectProps>(({ value, onChange, showAbility = true }) => {
|
|
30
32
|
const enabledList = useUserStore(modelProviderSelectors.modelProviderListForModelSelect, isEqual);
|
|
31
33
|
|
|
32
34
|
const { styles } = useStyles();
|
|
@@ -34,7 +36,7 @@ const ModelSelect = memo<ModelSelectProps>(({ value, onChange }) => {
|
|
|
34
36
|
const options = useMemo<SelectProps['options']>(() => {
|
|
35
37
|
const getChatModels = (provider: ModelProviderCard) =>
|
|
36
38
|
provider.chatModels.map((model) => ({
|
|
37
|
-
label: <ModelItemRender {...model} />,
|
|
39
|
+
label: <ModelItemRender {...model} showInfoTag={showAbility} />,
|
|
38
40
|
provider: provider.id,
|
|
39
41
|
value: model.id,
|
|
40
42
|
}));
|
|
@@ -53,11 +55,11 @@ const ModelSelect = memo<ModelSelectProps>(({ value, onChange }) => {
|
|
|
53
55
|
|
|
54
56
|
return (
|
|
55
57
|
<Select
|
|
56
|
-
className={styles.select}
|
|
57
58
|
onChange={(model, option) => {
|
|
58
59
|
onChange?.({ model, provider: (option as unknown as ModelOption).provider });
|
|
59
60
|
}}
|
|
60
61
|
options={options}
|
|
62
|
+
popupClassName={styles.select}
|
|
61
63
|
popupMatchSelectWidth={false}
|
|
62
64
|
value={value}
|
|
63
65
|
/>
|
|
@@ -22,10 +22,6 @@ beforeEach(() => {
|
|
|
22
22
|
|
|
23
23
|
// 使用 vi.spyOn 来模拟 chat.completions.create 方法
|
|
24
24
|
vi.spyOn(instance['client'].messages, 'create').mockReturnValue(new ReadableStream() as any);
|
|
25
|
-
|
|
26
|
-
vi.spyOn(instance['client'].beta.tools.messages, 'create').mockReturnValue({
|
|
27
|
-
content: [],
|
|
28
|
-
} as any);
|
|
29
25
|
});
|
|
30
26
|
|
|
31
27
|
afterEach(() => {
|
|
@@ -260,35 +256,9 @@ describe('LobeAnthropicAI', () => {
|
|
|
260
256
|
});
|
|
261
257
|
|
|
262
258
|
// Assert
|
|
263
|
-
expect(instance['client'].
|
|
259
|
+
expect(instance['client'].messages.create).toHaveBeenCalled();
|
|
264
260
|
expect(spyOn).toHaveBeenCalledWith(tools);
|
|
265
261
|
});
|
|
266
|
-
|
|
267
|
-
it('should handle text and tool_use content correctly in transformResponseToStream', async () => {
|
|
268
|
-
// Arrange
|
|
269
|
-
const mockResponse = {
|
|
270
|
-
content: [
|
|
271
|
-
{ type: 'text', text: 'Hello' },
|
|
272
|
-
{ type: 'tool_use', id: 'tool1', name: 'tool1', input: 'input1' },
|
|
273
|
-
],
|
|
274
|
-
};
|
|
275
|
-
// @ts-ignore
|
|
276
|
-
vi.spyOn(instance, 'transformResponseToStream').mockReturnValue(new ReadableStream());
|
|
277
|
-
vi.spyOn(instance['client'].beta.tools.messages, 'create').mockResolvedValue(
|
|
278
|
-
mockResponse as any,
|
|
279
|
-
);
|
|
280
|
-
|
|
281
|
-
// Act
|
|
282
|
-
await instance.chat({
|
|
283
|
-
messages: [{ content: 'Hello', role: 'user' }],
|
|
284
|
-
model: 'claude-3-haiku-20240307',
|
|
285
|
-
temperature: 0,
|
|
286
|
-
tools: [{ function: { name: 'tool1', description: 'desc1' }, type: 'function' }],
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
// Assert
|
|
290
|
-
expect(instance['transformResponseToStream']).toHaveBeenCalledWith(mockResponse);
|
|
291
|
-
});
|
|
292
262
|
});
|
|
293
263
|
|
|
294
264
|
describe('Error', () => {
|
|
@@ -30,41 +30,20 @@ export class LobeAnthropicAI implements LobeRuntimeAI {
|
|
|
30
30
|
async chat(payload: ChatStreamPayload, options?: ChatCompetitionOptions) {
|
|
31
31
|
try {
|
|
32
32
|
const anthropicPayload = this.buildAnthropicPayload(payload);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
{
|
|
39
|
-
signal: options?.signal,
|
|
40
|
-
},
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
const [prod, debug] = response.tee();
|
|
44
|
-
|
|
45
|
-
if (process.env.DEBUG_ANTHROPIC_CHAT_COMPLETION === '1') {
|
|
46
|
-
debugStream(debug.toReadableStream()).catch(console.error);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return StreamingResponse(AnthropicStream(prod, options?.callback), {
|
|
50
|
-
headers: options?.headers,
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// or we should call the tool API
|
|
55
|
-
const response = await this.client.beta.tools.messages.create(
|
|
56
|
-
{ ...anthropicPayload, stream: false },
|
|
57
|
-
{ signal: options?.signal },
|
|
33
|
+
const response = await this.client.messages.create(
|
|
34
|
+
{ ...anthropicPayload, stream: true },
|
|
35
|
+
{
|
|
36
|
+
signal: options?.signal,
|
|
37
|
+
},
|
|
58
38
|
);
|
|
59
39
|
|
|
40
|
+
const [prod, debug] = response.tee();
|
|
41
|
+
|
|
60
42
|
if (process.env.DEBUG_ANTHROPIC_CHAT_COMPLETION === '1') {
|
|
61
|
-
|
|
62
|
-
console.log(JSON.stringify(response) + '\n');
|
|
43
|
+
debugStream(debug.toReadableStream()).catch(console.error);
|
|
63
44
|
}
|
|
64
45
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return StreamingResponse(AnthropicStream(stream, options?.callback), {
|
|
46
|
+
return StreamingResponse(AnthropicStream(prod, options?.callback), {
|
|
68
47
|
headers: options?.headers,
|
|
69
48
|
});
|
|
70
49
|
} catch (error) {
|
|
@@ -118,43 +97,10 @@ export class LobeAnthropicAI implements LobeRuntimeAI {
|
|
|
118
97
|
model,
|
|
119
98
|
system: system_message?.content as string,
|
|
120
99
|
temperature,
|
|
121
|
-
// TODO: Anthropic sdk don't have tools interface currently
|
|
122
|
-
// @ts-ignore
|
|
123
100
|
tools: buildAnthropicTools(tools),
|
|
124
101
|
top_p,
|
|
125
102
|
} satisfies Anthropic.MessageCreateParams;
|
|
126
103
|
}
|
|
127
|
-
|
|
128
|
-
private transformResponseToStream = (response: Anthropic.Beta.Tools.ToolsBetaMessage) => {
|
|
129
|
-
return new ReadableStream<Anthropic.MessageStreamEvent>({
|
|
130
|
-
start(controller) {
|
|
131
|
-
response.content.forEach((content) => {
|
|
132
|
-
switch (content.type) {
|
|
133
|
-
case 'text': {
|
|
134
|
-
controller.enqueue({
|
|
135
|
-
delta: { text: content.text, type: 'text_delta' },
|
|
136
|
-
type: 'content_block_delta',
|
|
137
|
-
} as Anthropic.ContentBlockDeltaEvent);
|
|
138
|
-
break;
|
|
139
|
-
}
|
|
140
|
-
case 'tool_use': {
|
|
141
|
-
controller.enqueue({
|
|
142
|
-
delta: {
|
|
143
|
-
tool_use: { id: content.id, input: content.input, name: content.name },
|
|
144
|
-
type: 'tool_use',
|
|
145
|
-
},
|
|
146
|
-
type: 'content_block_delta',
|
|
147
|
-
} as any);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
controller.enqueue({ type: 'message_stop' } as Anthropic.MessageStopEvent);
|
|
153
|
-
|
|
154
|
-
controller.close();
|
|
155
|
-
},
|
|
156
|
-
});
|
|
157
|
-
};
|
|
158
104
|
}
|
|
159
105
|
|
|
160
106
|
export default LobeAnthropicAI;
|
|
@@ -49,7 +49,7 @@ describe('LobeOpenAI', () => {
|
|
|
49
49
|
});
|
|
50
50
|
|
|
51
51
|
describe('Error', () => {
|
|
52
|
-
it('should return
|
|
52
|
+
it('should return ProviderBizError with an openai error response when OpenAI.APIError is thrown', async () => {
|
|
53
53
|
// Arrange
|
|
54
54
|
const apiError = new OpenAI.APIError(
|
|
55
55
|
400,
|
|
@@ -79,7 +79,7 @@ describe('LobeOpenAI', () => {
|
|
|
79
79
|
error: { message: 'Bad Request' },
|
|
80
80
|
status: 400,
|
|
81
81
|
},
|
|
82
|
-
errorType: '
|
|
82
|
+
errorType: 'ProviderBizError',
|
|
83
83
|
provider: 'openai',
|
|
84
84
|
});
|
|
85
85
|
}
|
|
@@ -89,11 +89,11 @@ describe('LobeOpenAI', () => {
|
|
|
89
89
|
try {
|
|
90
90
|
new LobeOpenAI({});
|
|
91
91
|
} catch (e) {
|
|
92
|
-
expect(e).toEqual({ errorType: '
|
|
92
|
+
expect(e).toEqual({ errorType: 'InvalidProviderAPIKey' });
|
|
93
93
|
}
|
|
94
94
|
});
|
|
95
95
|
|
|
96
|
-
it('should return
|
|
96
|
+
it('should return ProviderBizError with the cause when OpenAI.APIError is thrown with cause', async () => {
|
|
97
97
|
// Arrange
|
|
98
98
|
const errorInfo = {
|
|
99
99
|
stack: 'abc',
|
|
@@ -119,13 +119,13 @@ describe('LobeOpenAI', () => {
|
|
|
119
119
|
cause: { message: 'api is undefined' },
|
|
120
120
|
stack: 'abc',
|
|
121
121
|
},
|
|
122
|
-
errorType: '
|
|
122
|
+
errorType: 'ProviderBizError',
|
|
123
123
|
provider: 'openai',
|
|
124
124
|
});
|
|
125
125
|
}
|
|
126
126
|
});
|
|
127
127
|
|
|
128
|
-
it('should return
|
|
128
|
+
it('should return ProviderBizError with an cause response with desensitize Url', async () => {
|
|
129
129
|
// Arrange
|
|
130
130
|
const errorInfo = {
|
|
131
131
|
stack: 'abc',
|
|
@@ -155,7 +155,7 @@ describe('LobeOpenAI', () => {
|
|
|
155
155
|
cause: { message: 'api is undefined' },
|
|
156
156
|
stack: 'abc',
|
|
157
157
|
},
|
|
158
|
-
errorType: '
|
|
158
|
+
errorType: 'ProviderBizError',
|
|
159
159
|
provider: 'openai',
|
|
160
160
|
});
|
|
161
161
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { AgentRuntimeErrorType } from '../error';
|
|
2
1
|
import { ModelProvider } from '../types';
|
|
3
2
|
import { LobeOpenAICompatibleFactory } from '../utils/openaiCompatibleFactory';
|
|
4
3
|
|
|
@@ -7,10 +6,5 @@ export const LobeOpenAI = LobeOpenAICompatibleFactory({
|
|
|
7
6
|
debug: {
|
|
8
7
|
chatCompletion: () => process.env.DEBUG_OPENAI_CHAT_COMPLETION === '1',
|
|
9
8
|
},
|
|
10
|
-
errorType: {
|
|
11
|
-
bizError: AgentRuntimeErrorType.OpenAIBizError,
|
|
12
|
-
invalidAPIKey: AgentRuntimeErrorType.NoOpenAIAPIKey,
|
|
13
|
-
},
|
|
14
|
-
|
|
15
9
|
provider: ModelProvider.OpenAI,
|
|
16
10
|
});
|
|
@@ -112,9 +112,9 @@ export const buildAnthropicMessages = (
|
|
|
112
112
|
|
|
113
113
|
export const buildAnthropicTools = (tools?: OpenAI.ChatCompletionTool[]) =>
|
|
114
114
|
tools?.map(
|
|
115
|
-
(tool): Anthropic.
|
|
115
|
+
(tool): Anthropic.Tool => ({
|
|
116
116
|
description: tool.function.description,
|
|
117
|
-
input_schema: tool.function.parameters as Anthropic.
|
|
117
|
+
input_schema: tool.function.parameters as Anthropic.Tool.InputSchema,
|
|
118
118
|
name: tool.function.name,
|
|
119
119
|
}),
|
|
120
120
|
);
|