@lobehub/chat 0.145.10 → 0.145.11

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 CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 0.145.11](https://github.com/lobehub/lobe-chat/compare/v0.145.10...v0.145.11)
6
+
7
+ <sup>Released on **2024-04-03**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **misc**: Fix page crash when using browser as the stt engine.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **misc**: Fix page crash when using browser as the stt engine, closes [#1884](https://github.com/lobehub/lobe-chat/issues/1884) ([278820a](https://github.com/lobehub/lobe-chat/commit/278820a))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
5
30
  ### [Version 0.145.10](https://github.com/lobehub/lobe-chat/compare/v0.145.9...v0.145.10)
6
31
 
7
32
  <sup>Released on **2024-04-02**</sup>
package/README.md CHANGED
@@ -220,14 +220,14 @@ In addition, these plugins are not limited to news aggregation, but can also ext
220
220
 
221
221
  <!-- PLUGIN LIST -->
222
222
 
223
- | Recent Submits | Description |
224
- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
225
- | [Social Search](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **say-apps** on **2024-04-02**</sup> | The Social Search provides access to tweets, users, followers, images, media and more.<br/>`social` `twitter` `x` `search` |
226
- | [Calendar Assistant](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **cc** on **2024-03-13**</sup> | A plugin to manage your calendar events # will auto generate i18n in workflow<br/>`calendar` `schedule` `will-auto-generate-i-18-n-in-workflow` |
227
- | [TokenInsights](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **feednews** on **2024-01-27**</sup> | Get realtime crypto price, BTC, ETH, BNB, and the latest insights.The latest coin news and airdrop opportunities.<br/>`crypto` `btc` `eth` `bnb` |
228
- | [Bilibili](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2024-01-27**</sup> | Dive into Bilibili's vast content with features like keyword video search, replay access, interactive danmaku, trending video recommendations, and hot-search insights, all at your fingertips.<br/>`video` `bilibili` `search` |
223
+ | Recent Submits | Description |
224
+ | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
225
+ | [NFT Guru](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **swap** on **2024-04-03**</sup> | Discover current prices of NFTs across major platforms and keep track of the rapidly changing marketplace with real-time<br/>`crypto` `nft` |
226
+ | [Social Search](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **say-apps** on **2024-04-02**</sup> | The Social Search provides access to tweets, users, followers, images, media and more.<br/>`social` `twitter` `x` `search` |
227
+ | [Calendar Assistant](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **cc** on **2024-03-13**</sup> | A plugin to manage your calendar events # will auto generate i18n in workflow<br/>`calendar` `schedule` `will-auto-generate-i-18-n-in-workflow` |
228
+ | [TokenInsights](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **feednews** on **2024-01-27**</sup> | Get realtime crypto price, BTC, ETH, BNB, and the latest insights.The latest coin news and airdrop opportunities.<br/>`crypto` `btc` `eth` `bnb` |
229
229
 
230
- > 📊 Total plugins: [<kbd>**55**</kbd>](https://github.com/lobehub/lobe-chat-plugins)
230
+ > 📊 Total plugins: [<kbd>**56**</kbd>](https://github.com/lobehub/lobe-chat-plugins)
231
231
 
232
232
  <!-- PLUGIN LIST -->
233
233
 
@@ -259,14 +259,14 @@ Our marketplace is not just a showcase platform but also a collaborative space.
259
259
 
260
260
  <!-- AGENT LIST -->
261
261
 
262
- | Recent Submits | Description |
263
- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
264
- | [CAN](https://chat-preview.lobehub.com/market?agent=code-anything-noproblem)<br/><sup>By **[HenryWu9998](https://github.com/HenryWu9998)** on **2024-03-31**</sup> | Experienced programmer skilled in multiple languages. Provides code solutions, guidance, and practical examples to help users achieve their programming goals. "I adore coding."<br/>`programming` `coding` `programming-assistance` `code-examples` `guidance` |
265
- | [Blood Test Analyst](https://chat-preview.lobehub.com/market?agent=blood-analyst)<br/><sup>By **[SimoMay](https://github.com/SimoMay)** on **2024-03-27**</sup> | Skilled in analysing blood test results, providing clear feedback using emojis for easy understanding.<br/>`healthcare` `analysis` `results` `consulting` `summary` |
266
- | [High EQ Flattery Assistant](https://chat-preview.lobehub.com/market?agent=gpts-big-fart-chat)<br/><sup>By **[MapleEve](https://github.com/MapleEve)** on **2024-03-27**</sup> | An expert in precise chat compliments, providing suitable praise and flattery<br/>`compliments` `eq` `chat` |
267
- | [Suno.ai Music Creation Assistant](https://chat-preview.lobehub.com/market?agent=suno-music-creator)<br/><sup>By **[MapleEve](https://github.com/MapleEve)** on **2024-03-27**</sup> | Song creation and translation based on SunoAI<br/>`suno` `lyricist` `lyrics` `music-production` |
262
+ | Recent Submits | Description |
263
+ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
264
+ | [English Technology Article Reading Assistant](https://chat-preview.lobehub.com/market?agent=encn-fy)<br/><sup>By **[sangxgg](https://github.com/sangxgg)** on **2024-04-02**</sup> | A translator with rich translation experience, specializing in accurately and clearly translating various English technology articles into Simplified Chinese. Participated in the translation work of Simplified Chinese versions of publications such as National Geographic, Scientific American, InformationWeek, and TechCrunch Chinese. Has a unique understanding and skilled practice in in-depth interpretation and accurate translation of technology articles.<br/>`translation` `english-to-chinese-translation` `translation-of-english-technology-content` |
265
+ | [CAN](https://chat-preview.lobehub.com/market?agent=code-anything-noproblem)<br/><sup>By **[HenryWu9998](https://github.com/HenryWu9998)** on **2024-03-31**</sup> | Experienced programmer skilled in multiple languages. Provides code solutions, guidance, and practical examples to help users achieve their programming goals. "I adore coding."<br/>`programming` `coding` `programming-assistance` `code-examples` `guidance` |
266
+ | [Blood Test Analyst](https://chat-preview.lobehub.com/market?agent=blood-analyst)<br/><sup>By **[SimoMay](https://github.com/SimoMay)** on **2024-03-27**</sup> | Skilled in analysing blood test results, providing clear feedback using emojis for easy understanding.<br/>`healthcare` `analysis` `results` `consulting` `summary` |
267
+ | [High EQ Flattery Assistant](https://chat-preview.lobehub.com/market?agent=gpts-big-fart-chat)<br/><sup>By **[MapleEve](https://github.com/MapleEve)** on **2024-03-27**</sup> | An expert in precise chat compliments, providing suitable praise and flattery<br/>`compliments` `eq` `chat` |
268
268
 
269
- > 📊 Total agents: [<kbd>**225**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
269
+ > 📊 Total agents: [<kbd>**226**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
270
270
 
271
271
  <!-- AGENT LIST -->
272
272
 
package/README.zh-CN.md CHANGED
@@ -212,14 +212,14 @@ LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地
212
212
 
213
213
  <!-- PLUGIN LIST -->
214
214
 
215
- | 最近新增 | 插件描述 |
216
- | ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
217
- | [社交搜索](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **say-apps** on **2024-04-02**</sup> | 社交搜索提供访问推文、用户、关注者、图片、媒体等功能。<br/>`社交` `推特` `x` `搜索` |
218
- | [日历助手](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **cc** on **2024-03-13**</sup> | 一个用于管理日历事件的插件 # 将自动生成工作流程中的 i18n<br/>`日历` `日程安排` `将自动生成工作流程中的-i-18-n` |
219
- | [TokenInsights](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **feednews** on **2024-01-27**</sup> | 获取实时加密货币价格,BTC,ETH,BNB 和最新见解。最新的币新闻和空投机会。<br/>`加密货币` `btc` `eth` `bnb` |
220
- | [哔哩哔哩](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2024-01-27**</sup> | 通过关键词视频搜索、回放访问、互动弹幕、热门视频推荐和热搜洞察等功能,深入体验哔哩哔哩丰富的内容,尽在您的指尖。<br/>`视频` `哔哩哔哩` `搜索` |
215
+ | 最近新增 | 插件描述 |
216
+ | ----------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
217
+ | [NFT Guru](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **swap** on **2024-04-03**</sup> | 发现主要平台上 NFT 的当前价格,并通过实时跟踪快速变化的市场了解情况<br/>`加密货币` `nft` |
218
+ | [社交搜索](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **say-apps** on **2024-04-02**</sup> | 社交搜索提供访问推文、用户、关注者、图片、媒体等功能。<br/>`社交` `推特` `x` `搜索` |
219
+ | [日历助手](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **cc** on **2024-03-13**</sup> | 一个用于管理日历事件的插件 # 将自动生成工作流程中的 i18n<br/>`日历` `日程安排` `将自动生成工作流程中的-i-18-n` |
220
+ | [TokenInsights](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **feednews** on **2024-01-27**</sup> | 获取实时加密货币价格,BTC,ETH,BNB 和最新见解。最新的币新闻和空投机会。<br/>`加密货币` `btc` `eth` `bnb` |
221
221
 
222
- > 📊 Total plugins: [<kbd>**55**</kbd>](https://github.com/lobehub/lobe-chat-plugins)
222
+ > 📊 Total plugins: [<kbd>**56**</kbd>](https://github.com/lobehub/lobe-chat-plugins)
223
223
 
224
224
  <!-- PLUGIN LIST -->
225
225
 
@@ -247,14 +247,14 @@ LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地
247
247
 
248
248
  <!-- AGENT LIST -->
249
249
 
250
- | 最近新增 | 助手说明 |
251
- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
252
- | [CAN](https://chat-preview.lobehub.com/market?agent=code-anything-noproblem)<br/><sup>By **[HenryWu9998](https://github.com/HenryWu9998)** on **2024-03-31**</sup> | 有经验的程序员,精通多种编程语言。提供代码解决方案、指导和实际示例,帮助用户实现他们的编程目标。"我热爱编程。"<br/>`programming` `coding` `programming-assistance` `code-examples` `guidance` |
253
- | [血液检测分析师](https://chat-preview.lobehub.com/market?agent=blood-analyst)<br/><sup>By **[SimoMay](https://github.com/SimoMay)** on **2024-03-27**</sup> | 擅长分析血液检测结果,使用表情符号提供清晰反馈,便于理解。<br/>`医疗保健` `分析` `结果` `咨询` `摘要` |
254
- | [高情商马屁助手](https://chat-preview.lobehub.com/market?agent=gpts-big-fart-chat)<br/><sup>By **[MapleEve](https://github.com/MapleEve)** on **2024-03-27**</sup> | 精准的聊天夸赞专家,适宜的赞美和吹捧<br/>`夸赞` `情商` `聊天` |
255
- | [Suno.ai 音乐创作助手](https://chat-preview.lobehub.com/market?agent=suno-music-creator)<br/><sup>By **[MapleEve](https://github.com/MapleEve)** on **2024-03-27**</sup> | 基于 SunoAI 的歌曲创作与翻译<br/>`suno` `作词` `歌词` `音乐制作` |
250
+ | 最近新增 | 助手说明 |
251
+ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
252
+ | [英文科技文章阅读助手](https://chat-preview.lobehub.com/market?agent=encn-fy)<br/><sup>By **[sangxgg](https://github.com/sangxgg)** on **2024-04-02**</sup> | 一位拥有丰富翻译经验的翻译家,擅长将各类英文科技文章准确且通俗易懂的翻译成简体中文。<br/>`翻译` `英文翻译中文` `英文科技内容翻译` |
253
+ | [CAN](https://chat-preview.lobehub.com/market?agent=code-anything-noproblem)<br/><sup>By **[HenryWu9998](https://github.com/HenryWu9998)** on **2024-03-31**</sup> | 有经验的程序员,精通多种编程语言。提供代码解决方案、指导和实际示例,帮助用户实现他们的编程目标。"我热爱编程。"<br/>`programming` `coding` `programming-assistance` `code-examples` `guidance` |
254
+ | [血液检测分析师](https://chat-preview.lobehub.com/market?agent=blood-analyst)<br/><sup>By **[SimoMay](https://github.com/SimoMay)** on **2024-03-27**</sup> | 擅长分析血液检测结果,使用表情符号提供清晰反馈,便于理解。<br/>`医疗保健` `分析` `结果` `咨询` `摘要` |
255
+ | [高情商马屁助手](https://chat-preview.lobehub.com/market?agent=gpts-big-fart-chat)<br/><sup>By **[MapleEve](https://github.com/MapleEve)** on **2024-03-27**</sup> | 精准的聊天夸赞专家,适宜的赞美和吹捧<br/>`夸赞` `情商` `聊天` |
256
256
 
257
- > 📊 Total agents: [<kbd>**225**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
257
+ > 📊 Total agents: [<kbd>**226**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
258
258
 
259
259
  <!-- AGENT LIST -->
260
260
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "0.145.10",
3
+ "version": "0.145.11",
4
4
  "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
5
5
  "keywords": [
6
6
  "framework",
@@ -0,0 +1,117 @@
1
+ import { SpeechRecognitionOptions, useSpeechRecognition } from '@lobehub/tts/react';
2
+ import { isEqual } from 'lodash';
3
+ import { memo, useCallback, useState } from 'react';
4
+ import { useTranslation } from 'react-i18next';
5
+ import { SWRConfiguration } from 'swr';
6
+
7
+ import { useChatStore } from '@/store/chat';
8
+ import { useGlobalStore } from '@/store/global';
9
+ import { settingsSelectors } from '@/store/global/selectors';
10
+ import { useSessionStore } from '@/store/session';
11
+ import { agentSelectors } from '@/store/session/selectors';
12
+ import { ChatMessageError } from '@/types/message';
13
+ import { getMessageError } from '@/utils/fetch';
14
+
15
+ import CommonSTT from './common';
16
+
17
+ interface STTConfig extends SWRConfiguration {
18
+ onTextChange: (value: string) => void;
19
+ }
20
+
21
+ const useBrowserSTT = (config: STTConfig) => {
22
+ const ttsSettings = useGlobalStore(settingsSelectors.currentTTS, isEqual);
23
+ const ttsAgentSettings = useSessionStore(agentSelectors.currentAgentTTS, isEqual);
24
+ const locale = useGlobalStore(settingsSelectors.currentLanguage);
25
+
26
+ const autoStop = ttsSettings.sttAutoStop;
27
+ const sttLocale =
28
+ ttsAgentSettings?.sttLocale && ttsAgentSettings.sttLocale !== 'auto'
29
+ ? ttsAgentSettings.sttLocale
30
+ : locale;
31
+
32
+ return useSpeechRecognition(sttLocale, {
33
+ ...config,
34
+ autoStop,
35
+ } as SpeechRecognitionOptions);
36
+ };
37
+
38
+ const BrowserSTT = memo<{ mobile?: boolean }>(({ mobile }) => {
39
+ const [error, setError] = useState<ChatMessageError>();
40
+ const { t } = useTranslation('chat');
41
+
42
+ const [loading, updateInputMessage] = useChatStore((s) => [
43
+ !!s.chatLoadingId,
44
+ s.updateInputMessage,
45
+ ]);
46
+
47
+ const setDefaultError = useCallback(
48
+ (err?: any) => {
49
+ setError({ body: err, message: t('stt.responseError', { ns: 'error' }), type: 500 });
50
+ },
51
+ [t],
52
+ );
53
+
54
+ const { start, isLoading, stop, formattedTime, time, response, isRecording } = useBrowserSTT({
55
+ onError: (err) => {
56
+ stop();
57
+ setDefaultError(err);
58
+ },
59
+ onErrorRetry: (err) => {
60
+ stop();
61
+ setDefaultError(err);
62
+ },
63
+ onSuccess: async () => {
64
+ if (!response) return;
65
+ if (response.status === 200) return;
66
+ const message = await getMessageError(response);
67
+ if (message) {
68
+ setError(message);
69
+ } else {
70
+ setDefaultError();
71
+ }
72
+ stop();
73
+ },
74
+ onTextChange: (text) => {
75
+ if (loading) stop();
76
+ if (text) updateInputMessage(text);
77
+ },
78
+ });
79
+
80
+ const desc = t('stt.action');
81
+
82
+ const handleTriggerStartStop = useCallback(() => {
83
+ if (loading) return;
84
+ if (!isLoading) {
85
+ start();
86
+ } else {
87
+ stop();
88
+ }
89
+ }, [loading, isLoading, start, stop]);
90
+
91
+ const handleCloseError = useCallback(() => {
92
+ setError(undefined);
93
+ stop();
94
+ }, [stop]);
95
+
96
+ const handleRetry = useCallback(() => {
97
+ setError(undefined);
98
+ start();
99
+ }, [start]);
100
+
101
+ return (
102
+ <CommonSTT
103
+ desc={desc}
104
+ error={error}
105
+ formattedTime={formattedTime}
106
+ handleCloseError={handleCloseError}
107
+ handleRetry={handleRetry}
108
+ handleTriggerStartStop={handleTriggerStartStop}
109
+ isLoading={isLoading}
110
+ isRecording={isRecording}
111
+ mobile={mobile}
112
+ time={time}
113
+ />
114
+ );
115
+ });
116
+
117
+ export default BrowserSTT;
@@ -0,0 +1,104 @@
1
+ import { ActionIcon, Alert, Highlighter } from '@lobehub/ui';
2
+ import { Button, Dropdown } from 'antd';
3
+ import { createStyles } from 'antd-style';
4
+ import { Mic, MicOff } from 'lucide-react';
5
+ import { memo } from 'react';
6
+ import { useTranslation } from 'react-i18next';
7
+ import { Flexbox } from 'react-layout-kit';
8
+
9
+ import { ChatMessageError } from '@/types/message';
10
+
11
+ const useStyles = createStyles(({ css, token }) => ({
12
+ recording: css`
13
+ width: 8px;
14
+ height: 8px;
15
+ background: ${token.colorError};
16
+ border-radius: 50%;
17
+ `,
18
+ }));
19
+
20
+ const CommonSTT = memo<{
21
+ desc: string;
22
+ error?: ChatMessageError;
23
+ formattedTime: string;
24
+ handleCloseError: () => void;
25
+ handleRetry: () => void;
26
+ handleTriggerStartStop: () => void;
27
+ isLoading: boolean;
28
+ isRecording: boolean;
29
+ mobile?: boolean;
30
+ time: number;
31
+ }>(({
32
+ mobile,
33
+ isLoading,
34
+ formattedTime,
35
+ time,
36
+ isRecording,
37
+ error,
38
+ handleRetry,
39
+ handleTriggerStartStop,
40
+ handleCloseError,
41
+ desc,
42
+ }) => {
43
+ const { t } = useTranslation('chat');
44
+ const { styles } = useStyles();
45
+
46
+ return (
47
+ <Dropdown
48
+ dropdownRender={
49
+ error
50
+ ? () => (
51
+ <Alert
52
+ action={
53
+ <Button onClick={handleRetry} size={'small'} type={'primary'}>
54
+ {t('retry', { ns: 'common' })}
55
+ </Button>
56
+ }
57
+ closable
58
+ extra={
59
+ error.body && (
60
+ <Highlighter copyButtonSize={'small'} language={'json'} type={'pure'}>
61
+ {JSON.stringify(error.body, null, 2)}
62
+ </Highlighter>
63
+ )
64
+ }
65
+ message={error.message}
66
+ onClose={handleCloseError}
67
+ style={{ alignItems: 'center' }}
68
+ type="error"
69
+ />
70
+ )
71
+ : undefined
72
+ }
73
+ menu={{
74
+ activeKey: 'time',
75
+ items: [
76
+ {
77
+ key: 'time',
78
+ label: (
79
+ <Flexbox align={'center'} gap={8} horizontal>
80
+ <div className={styles.recording} />
81
+ {time > 0 ? formattedTime : t(isRecording ? 'stt.loading' : 'stt.prettifying')}
82
+ </Flexbox>
83
+ ),
84
+ },
85
+ ],
86
+ }}
87
+ open={!!error || isRecording || isLoading}
88
+ placement={mobile ? 'topRight' : 'top'}
89
+ trigger={['click']}
90
+ >
91
+ <ActionIcon
92
+ active={isRecording}
93
+ icon={isLoading ? MicOff : Mic}
94
+ onClick={handleTriggerStartStop}
95
+ placement={'bottom'}
96
+ size={mobile ? { blockSize: 36, fontSize: 16 } : { fontSize: 22 }}
97
+ style={{ flex: 'none' }}
98
+ title={desc}
99
+ />
100
+ </Dropdown>
101
+ );
102
+ });
103
+
104
+ export default CommonSTT;
@@ -1,145 +1,18 @@
1
- import { ActionIcon, Alert, Highlighter } from '@lobehub/ui';
2
- import { Button, Dropdown } from 'antd';
3
- import { createStyles } from 'antd-style';
4
- import { Mic, MicOff } from 'lucide-react';
5
- import { memo, useCallback, useState } from 'react';
6
- import { useTranslation } from 'react-i18next';
7
- import { Flexbox } from 'react-layout-kit';
8
-
9
- import { useSTT } from '@/hooks/useSTT';
10
- import { useChatStore } from '@/store/chat';
11
- import { ChatMessageError } from '@/types/message';
12
- import { getMessageError } from '@/utils/fetch';
13
-
14
- const useStyles = createStyles(({ css, token }) => ({
15
- recording: css`
16
- width: 8px;
17
- height: 8px;
18
- background: ${token.colorError};
19
- border-radius: 50%;
20
- `,
21
- }));
1
+ import { memo } from 'react';
2
+ import { useGlobalStore } from '@/store/global';
3
+ import { settingsSelectors } from '@/store/global/selectors';
4
+ import isEqual from 'fast-deep-equal';
5
+ import BrowserSTT from './browser';
6
+ import OpenaiSTT from './openai';
22
7
 
23
8
  const STT = memo<{ mobile?: boolean }>(({ mobile }) => {
24
- const [error, setError] = useState<ChatMessageError>();
25
- const { t } = useTranslation('chat');
26
- const { styles } = useStyles();
27
-
28
- const [loading, updateInputMessage] = useChatStore((s) => [
29
- !!s.chatLoadingId,
30
- s.updateInputMessage,
31
- ]);
32
-
33
- const setDefaultError = useCallback(
34
- (err?: any) => {
35
- setError({ body: err, message: t('stt.responseError', { ns: 'error' }), type: 500 });
36
- },
37
- [t],
38
- );
39
-
40
- const { start, isLoading, stop, formattedTime, time, response, isRecording } = useSTT({
41
- onError: (err) => {
42
- stop();
43
- setDefaultError(err);
44
- },
45
- onErrorRetry: (err) => {
46
- stop();
47
- setDefaultError(err);
48
- },
49
- onSuccess: async () => {
50
- if (!response) return;
51
- if (response.status === 200) return;
52
- const message = await getMessageError(response);
53
- if (message) {
54
- setError(message);
55
- } else {
56
- setDefaultError();
57
- }
58
- stop();
59
- },
60
- onTextChange: (text) => {
61
- if (loading) stop();
62
- if (text) updateInputMessage(text);
63
- },
64
- });
65
-
66
- const desc = t('stt.action');
67
-
68
- const handleTriggerStartStop = useCallback(() => {
69
- if (loading) return;
70
- if (!isLoading) {
71
- start();
72
- } else {
73
- stop();
9
+ const { sttServer } = useGlobalStore(settingsSelectors.currentTTS, isEqual)
10
+ switch (sttServer) {
11
+ case 'openai': {
12
+ return <OpenaiSTT mobile={mobile} />
74
13
  }
75
- }, [loading, isLoading, start, stop]);
76
-
77
- const handleCloseError = useCallback(() => {
78
- setError(undefined);
79
- stop();
80
- }, [stop]);
81
-
82
- const handleRetry = useCallback(() => {
83
- setError(undefined);
84
- start();
85
- }, [start]);
86
-
87
- return (
88
- <Dropdown
89
- dropdownRender={
90
- error
91
- ? () => (
92
- <Alert
93
- action={
94
- <Button onClick={handleRetry} size={'small'} type={'primary'}>
95
- {t('retry', { ns: 'common' })}
96
- </Button>
97
- }
98
- closable
99
- extra={
100
- error.body && (
101
- <Highlighter copyButtonSize={'small'} language={'json'} type={'pure'}>
102
- {JSON.stringify(error.body, null, 2)}
103
- </Highlighter>
104
- )
105
- }
106
- message={error.message}
107
- onClose={handleCloseError}
108
- style={{ alignItems: 'center' }}
109
- type="error"
110
- />
111
- )
112
- : undefined
113
- }
114
- menu={{
115
- activeKey: 'time',
116
- items: [
117
- {
118
- key: 'time',
119
- label: (
120
- <Flexbox align={'center'} gap={8} horizontal>
121
- <div className={styles.recording} />
122
- {time > 0 ? formattedTime : t(isRecording ? 'stt.loading' : 'stt.prettifying')}
123
- </Flexbox>
124
- ),
125
- },
126
- ],
127
- }}
128
- open={!!error || isRecording || isLoading}
129
- placement={mobile ? 'topRight' : 'top'}
130
- trigger={['click']}
131
- >
132
- <ActionIcon
133
- active={mobile}
134
- icon={isLoading ? MicOff : Mic}
135
- onClick={handleTriggerStartStop}
136
- placement={'bottom'}
137
- size={mobile ? { blockSize: 36, fontSize: 16 } : { fontSize: 22 }}
138
- style={{ flex: 'none' }}
139
- title={desc}
140
- />
141
- </Dropdown>
142
- );
143
- });
14
+ }
15
+ return <BrowserSTT mobile={mobile} />
16
+ })
144
17
 
145
- export default STT;
18
+ export default STT
@@ -0,0 +1,128 @@
1
+ import { getRecordMineType } from '@lobehub/tts';
2
+ import { OpenAISTTOptions, useOpenAISTT } from '@lobehub/tts/react';
3
+ import { isEqual } from 'lodash';
4
+ import { memo, useCallback, useState } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+ import { SWRConfiguration } from 'swr';
7
+
8
+ import { createHeaderWithOpenAI } from '@/services/_header';
9
+ import { API_ENDPOINTS } from '@/services/_url';
10
+ import { useChatStore } from '@/store/chat';
11
+ import { useGlobalStore } from '@/store/global';
12
+ import { settingsSelectors } from '@/store/global/selectors';
13
+ import { useSessionStore } from '@/store/session';
14
+ import { agentSelectors } from '@/store/session/selectors';
15
+ import { ChatMessageError } from '@/types/message';
16
+ import { getMessageError } from '@/utils/fetch';
17
+
18
+ import CommonSTT from './common';
19
+
20
+ interface STTConfig extends SWRConfiguration {
21
+ onTextChange: (value: string) => void;
22
+ }
23
+
24
+ const useOpenaiSTT = (config: STTConfig) => {
25
+ const ttsSettings = useGlobalStore(settingsSelectors.currentTTS, isEqual);
26
+ const ttsAgentSettings = useSessionStore(agentSelectors.currentAgentTTS, isEqual);
27
+ const locale = useGlobalStore(settingsSelectors.currentLanguage);
28
+
29
+ const autoStop = ttsSettings.sttAutoStop;
30
+ const sttLocale =
31
+ ttsAgentSettings?.sttLocale && ttsAgentSettings.sttLocale !== 'auto'
32
+ ? ttsAgentSettings.sttLocale
33
+ : locale;
34
+
35
+ return useOpenAISTT(sttLocale, {
36
+ ...config,
37
+ api: {
38
+ headers: createHeaderWithOpenAI(),
39
+ serviceUrl: API_ENDPOINTS.stt,
40
+ },
41
+ autoStop,
42
+ options: {
43
+ mineType: getRecordMineType(),
44
+ model: ttsSettings.openAI.sttModel,
45
+ },
46
+ } as OpenAISTTOptions);
47
+ };
48
+
49
+ const OpenaiSTT = memo<{ mobile?: boolean }>(({ mobile }) => {
50
+ const [error, setError] = useState<ChatMessageError>();
51
+ const { t } = useTranslation('chat');
52
+
53
+ const [loading, updateInputMessage] = useChatStore((s) => [
54
+ !!s.chatLoadingId,
55
+ s.updateInputMessage,
56
+ ]);
57
+
58
+ const setDefaultError = useCallback(
59
+ (err?: any) => {
60
+ setError({ body: err, message: t('stt.responseError', { ns: 'error' }), type: 500 });
61
+ },
62
+ [t],
63
+ );
64
+
65
+ const { start, isLoading, stop, formattedTime, time, response, isRecording } = useOpenaiSTT({
66
+ onError: (err) => {
67
+ stop();
68
+ setDefaultError(err);
69
+ },
70
+ onErrorRetry: (err) => {
71
+ stop();
72
+ setDefaultError(err);
73
+ },
74
+ onSuccess: async () => {
75
+ if (!response) return;
76
+ if (response.status === 200) return;
77
+ const message = await getMessageError(response);
78
+ if (message) {
79
+ setError(message);
80
+ } else {
81
+ setDefaultError();
82
+ }
83
+ stop();
84
+ },
85
+ onTextChange: (text) => {
86
+ if (loading) stop();
87
+ if (text) updateInputMessage(text);
88
+ },
89
+ });
90
+
91
+ const desc = t('stt.action');
92
+
93
+ const handleTriggerStartStop = useCallback(() => {
94
+ if (loading) return;
95
+ if (!isLoading) {
96
+ start();
97
+ } else {
98
+ stop();
99
+ }
100
+ }, [loading, isLoading, start, stop]);
101
+
102
+ const handleCloseError = useCallback(() => {
103
+ setError(undefined);
104
+ stop();
105
+ }, [stop]);
106
+
107
+ const handleRetry = useCallback(() => {
108
+ setError(undefined);
109
+ start();
110
+ }, [start]);
111
+
112
+ return (
113
+ <CommonSTT
114
+ desc={desc}
115
+ error={error}
116
+ formattedTime={formattedTime}
117
+ handleCloseError={handleCloseError}
118
+ handleRetry={handleRetry}
119
+ handleTriggerStartStop={handleTriggerStartStop}
120
+ isLoading={isLoading}
121
+ isRecording={isRecording}
122
+ mobile={mobile}
123
+ time={time}
124
+ />
125
+ );
126
+ });
127
+
128
+ export default OpenaiSTT;
@@ -40,7 +40,8 @@ export class LobeAzureOpenAI implements LobeRuntimeAI {
40
40
  params as GetChatCompletionsOptions,
41
41
  );
42
42
 
43
- const stream = OpenAIStream(response);
43
+ // TODO: we need to refactor this part in the future
44
+ const stream = OpenAIStream(response as any);
44
45
 
45
46
  const [debug, prod] = stream.tee();
46
47
 
@@ -1,62 +0,0 @@
1
- import { getRecordMineType } from '@lobehub/tts';
2
- import {
3
- OpenAISTTOptions,
4
- SpeechRecognitionOptions,
5
- useOpenAISTT,
6
- useSpeechRecognition,
7
- } from '@lobehub/tts/react';
8
- import isEqual from 'fast-deep-equal';
9
- import { SWRConfiguration } from 'swr';
10
-
11
- import { createHeaderWithOpenAI } from '@/services/_header';
12
- import { API_ENDPOINTS } from '@/services/_url';
13
- import { useGlobalStore } from '@/store/global';
14
- import { settingsSelectors } from '@/store/global/selectors';
15
- import { useSessionStore } from '@/store/session';
16
- import { agentSelectors } from '@/store/session/selectors';
17
-
18
- interface STTConfig extends SWRConfiguration {
19
- onTextChange: (value: string) => void;
20
- }
21
-
22
- export const useSTT = (config: STTConfig) => {
23
- const ttsSettings = useGlobalStore(settingsSelectors.currentTTS, isEqual);
24
- const ttsAgentSettings = useSessionStore(agentSelectors.currentAgentTTS, isEqual);
25
- const locale = useGlobalStore(settingsSelectors.currentLanguage);
26
-
27
- const autoStop = ttsSettings.sttAutoStop;
28
- const sttLocale =
29
- ttsAgentSettings?.sttLocale && ttsAgentSettings.sttLocale !== 'auto'
30
- ? ttsAgentSettings.sttLocale
31
- : locale;
32
-
33
- let useSelectedSTT;
34
- let options: any = {};
35
-
36
- switch (ttsSettings.sttServer) {
37
- case 'openai': {
38
- useSelectedSTT = useOpenAISTT;
39
- options = {
40
- api: {
41
- headers: createHeaderWithOpenAI(),
42
- serviceUrl: API_ENDPOINTS.stt,
43
- },
44
- autoStop,
45
- options: {
46
- mineType: getRecordMineType(),
47
- model: ttsSettings.openAI.sttModel,
48
- },
49
- } as OpenAISTTOptions;
50
- break;
51
- }
52
- case 'browser': {
53
- options = {
54
- autoStop,
55
- } as SpeechRecognitionOptions;
56
- useSelectedSTT = useSpeechRecognition;
57
- break;
58
- }
59
- }
60
-
61
- return useSelectedSTT(sttLocale, { ...config, ...options });
62
- };