@rimori/react-client 0.4.11-next.3 → 0.4.11-next.4

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.
@@ -10,6 +10,8 @@ interface Props {
10
10
  autoStartConversation?: FirstMessages;
11
11
  className?: string;
12
12
  knowledgeId?: string;
13
+ /** Set to true to disable automatic dialect TTS from userInfo. Default: false (dialect enabled). */
14
+ disableDialect?: boolean;
13
15
  }
14
- export declare function Avatar({ avatarImageUrl, voiceId, agentTools, autoStartConversation, children, circleSize, className, cache, knowledgeId, }: Props): import("react/jsx-runtime").JSX.Element;
16
+ export declare function Avatar({ avatarImageUrl, voiceId, agentTools, autoStartConversation, children, circleSize, className, cache, knowledgeId, disableDialect, }: Props): import("react/jsx-runtime").JSX.Element;
15
17
  export {};
@@ -7,12 +7,18 @@ import { useChat } from '../../hooks/UseChatHook';
7
7
  import { useRimori } from '../../providers/PluginProvider';
8
8
  import { getFirstMessages } from './utils';
9
9
  import { useTheme } from '../../hooks/ThemeSetter';
10
- export function Avatar({ avatarImageUrl, voiceId, agentTools, autoStartConversation, children, circleSize = '300px', className, cache = false, knowledgeId, }) {
11
- const { ai, event, plugin } = useRimori();
10
+ export function Avatar({ avatarImageUrl, voiceId, agentTools, autoStartConversation, children, circleSize = '300px', className, cache = false, knowledgeId, disableDialect = false, }) {
11
+ const { ai, event, plugin, userInfo } = useRimori();
12
12
  const { isDark: isDarkThemeValue } = useTheme(plugin.theme);
13
13
  const [agentReplying, setAgentReplying] = useState(false);
14
14
  const [isProcessingMessage, setIsProcessingMessage] = useState(false);
15
+ const dialectTtsInstruction = !disableDialect && (userInfo === null || userInfo === void 0 ? void 0 : userInfo.dialect)
16
+ ? `Speak with a ${userInfo.dialect} accent and pronunciation.`
17
+ : undefined;
15
18
  const sender = useMemo(() => new MessageSender((...args) => ai.getVoice(...args), voiceId, cache), [voiceId, ai, cache]);
19
+ useEffect(() => {
20
+ sender.setInstructions(dialectTtsInstruction);
21
+ }, [sender, dialectTtsInstruction]);
16
22
  const { messages, append, isLoading, lastMessage, setMessages } = useChat(agentTools, { knowledgeId });
17
23
  useEffect(() => {
18
24
  console.log('messages', messages);
@@ -15,5 +15,7 @@ export interface BuddyAssistantProps {
15
15
  className?: string;
16
16
  voiceSpeed?: number;
17
17
  tools?: Tool[];
18
+ /** Set to true to disable automatic dialect from userInfo. Default: false (dialect enabled). */
19
+ disableDialect?: boolean;
18
20
  }
19
- export declare function BuddyAssistant({ systemPrompt, autoStartConversation, circleSize, chatPlaceholder, bottomAction, className, voiceSpeed, tools, }: BuddyAssistantProps): JSX.Element;
21
+ export declare function BuddyAssistant({ systemPrompt, autoStartConversation, circleSize, chatPlaceholder, bottomAction, className, voiceSpeed, tools, disableDialect, }: BuddyAssistantProps): JSX.Element;
@@ -9,11 +9,16 @@ import { HiMiniSpeakerWave, HiMiniSpeakerXMark } from 'react-icons/hi2';
9
9
  import { BiSolidRightArrow } from 'react-icons/bi';
10
10
  let idCounter = 0;
11
11
  const genId = () => `ba-${++idCounter}`;
12
- export function BuddyAssistant({ systemPrompt, autoStartConversation, circleSize = '160px', chatPlaceholder, bottomAction, className, voiceSpeed = 1, tools, }) {
12
+ export function BuddyAssistant({ systemPrompt, autoStartConversation, circleSize = '160px', chatPlaceholder, bottomAction, className, voiceSpeed = 1, tools, disableDialect = false, }) {
13
13
  var _a;
14
- const { ai, event, plugin } = useRimori();
14
+ const { ai, event, plugin, userInfo } = useRimori();
15
15
  const { isDark } = useTheme(plugin.theme);
16
16
  const buddy = (_a = plugin.getUserInfo()) === null || _a === void 0 ? void 0 : _a.study_buddy;
17
+ const dialect = !disableDialect ? userInfo === null || userInfo === void 0 ? void 0 : userInfo.dialect : undefined;
18
+ const dialectSystemSuffix = dialect
19
+ ? `\n\nThe user is learning the regional ${dialect} dialect. Occasionally use typical regional vocabulary and expressions from this dialect to help them learn local language naturally.`
20
+ : '';
21
+ const dialectTtsInstruction = dialect ? `Speak with a ${dialect} accent and pronunciation.` : undefined;
17
22
  const [ttsEnabled, setTtsEnabled] = useState(true);
18
23
  const [chatInput, setChatInput] = useState('');
19
24
  const [messages, setMessages] = useState([]);
@@ -24,6 +29,9 @@ export function BuddyAssistant({ systemPrompt, autoStartConversation, circleSize
24
29
  ttsEnabledRef.current = ttsEnabled;
25
30
  }, [ttsEnabled]);
26
31
  const sender = useMemo(() => { var _a; return new MessageSender((...args) => ai.getVoice(...args), (_a = buddy === null || buddy === void 0 ? void 0 : buddy.voiceId) !== null && _a !== void 0 ? _a : ''); }, [buddy === null || buddy === void 0 ? void 0 : buddy.voiceId, ai]);
32
+ useEffect(() => {
33
+ sender.setInstructions(dialectTtsInstruction);
34
+ }, [sender, dialectTtsInstruction]);
27
35
  // Setup sender callbacks and cleanup
28
36
  useEffect(() => {
29
37
  sender.setVoiceSpeed(voiceSpeed);
@@ -31,9 +39,9 @@ export function BuddyAssistant({ systemPrompt, autoStartConversation, circleSize
31
39
  sender.setOnEndOfSpeech(() => setIsSpeaking(false));
32
40
  return () => sender.cleanup();
33
41
  }, [sender]);
34
- // Build full API message list with system prompt
42
+ // Build full API message list with system prompt (dialect appended when enabled)
35
43
  const buildApiMessages = (history) => [
36
- { role: 'system', content: systemPrompt },
44
+ { role: 'system', content: systemPrompt + dialectSystemSuffix },
37
45
  ...history.map((m) => ({ role: m.role, content: m.content })),
38
46
  ];
39
47
  const triggerAI = (history) => {
@@ -10,6 +10,10 @@ type AudioPlayerProps = {
10
10
  enableSpeedAdjustment?: boolean;
11
11
  playListenerEvent?: string;
12
12
  size?: string;
13
+ /** Explicit TTS instruction string. If provided, overrides auto-dialect. */
14
+ ttsInstructions?: string;
15
+ /** Set to true to disable automatic dialect from userInfo. Default: false (dialect enabled). */
16
+ disableDialect?: boolean;
13
17
  };
14
18
  export declare const AudioPlayOptions: number[];
15
19
  export type AudioPlayOptionType = 0.8 | 0.9 | 1.0 | 1.1 | 1.2 | 1.5;
@@ -14,12 +14,12 @@ import { useRimori } from '../../providers/PluginProvider';
14
14
  import { EventBus } from '@rimori/client';
15
15
  export const AudioPlayOptions = [0.8, 0.9, 1.0, 1.1, 1.2, 1.5];
16
16
  let isFetchingAudio = false;
17
- export const AudioPlayer = ({ text, voice, language, hide, playListenerEvent, initialSpeed = 1.0, playOnMount = false, enableSpeedAdjustment = false, cache = true, size = '25px', }) => {
17
+ export const AudioPlayer = ({ text, voice, language, hide, playListenerEvent, initialSpeed = 1.0, playOnMount = false, enableSpeedAdjustment = false, cache = true, size = '25px', ttsInstructions, disableDialect = false, }) => {
18
18
  const [audioUrl, setAudioUrl] = useState(null);
19
19
  const [speed, setSpeed] = useState(initialSpeed);
20
20
  const [isPlaying, setIsPlaying] = useState(false);
21
21
  const [isLoading, setIsLoading] = useState(false);
22
- const { ai } = useRimori();
22
+ const { ai, userInfo } = useRimori();
23
23
  const audioRef = useRef(null);
24
24
  const eventBusListenerRef = useRef(null);
25
25
  useEffect(() => {
@@ -33,7 +33,8 @@ export const AudioPlayer = ({ text, voice, language, hide, playListenerEvent, in
33
33
  // Function to generate audio from text using API
34
34
  const generateAudio = () => __awaiter(void 0, void 0, void 0, function* () {
35
35
  setIsLoading(true);
36
- const blob = yield ai.getVoice(text, voice || (language ? 'aws_default' : 'openai_alloy'), 1, language, cache);
36
+ const effectiveInstructions = ttsInstructions !== null && ttsInstructions !== void 0 ? ttsInstructions : (!disableDialect && (userInfo === null || userInfo === void 0 ? void 0 : userInfo.dialect) ? `Speak with a ${userInfo.dialect} accent and pronunciation.` : undefined);
37
+ const blob = yield ai.getVoice(text, voice || (language ? 'aws_default' : 'openai_alloy'), 1, language, cache, effectiveInstructions);
37
38
  setAudioUrl(URL.createObjectURL(blob));
38
39
  setIsLoading(false);
39
40
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rimori/react-client",
3
- "version": "0.4.11-next.3",
3
+ "version": "0.4.11-next.4",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,7 +24,7 @@
24
24
  "format": "prettier --write ."
25
25
  },
26
26
  "peerDependencies": {
27
- "@rimori/client": "2.5.19-next.5",
27
+ "@rimori/client": "2.5.20-next.1",
28
28
  "react": "^18.1.0",
29
29
  "react-dom": "^18.1.0"
30
30
  },
@@ -47,7 +47,7 @@
47
47
  },
48
48
  "devDependencies": {
49
49
  "@eslint/js": "^9.37.0",
50
- "@rimori/client": "2.5.19-next.5",
50
+ "@rimori/client": "2.5.20-next.1",
51
51
  "@types/react": "^18.3.21",
52
52
  "eslint-config-prettier": "^10.1.8",
53
53
  "eslint-plugin-prettier": "^5.5.4",
@@ -19,6 +19,8 @@ interface Props {
19
19
  autoStartConversation?: FirstMessages;
20
20
  className?: string;
21
21
  knowledgeId?: string;
22
+ /** Set to true to disable automatic dialect TTS from userInfo. Default: false (dialect enabled). */
23
+ disableDialect?: boolean;
22
24
  }
23
25
 
24
26
  export function Avatar({
@@ -31,15 +33,23 @@ export function Avatar({
31
33
  className,
32
34
  cache = false,
33
35
  knowledgeId,
36
+ disableDialect = false,
34
37
  }: Props) {
35
- const { ai, event, plugin } = useRimori();
38
+ const { ai, event, plugin, userInfo } = useRimori();
36
39
  const { isDark: isDarkThemeValue } = useTheme(plugin.theme);
37
40
  const [agentReplying, setAgentReplying] = useState(false);
38
41
  const [isProcessingMessage, setIsProcessingMessage] = useState(false);
42
+ const dialectTtsInstruction = !disableDialect && userInfo?.dialect
43
+ ? `Speak with a ${userInfo.dialect} accent and pronunciation.`
44
+ : undefined;
39
45
  const sender = useMemo(
40
46
  () => new MessageSender((...args) => ai.getVoice(...args), voiceId, cache),
41
47
  [voiceId, ai, cache],
42
48
  );
49
+
50
+ useEffect(() => {
51
+ sender.setInstructions(dialectTtsInstruction);
52
+ }, [sender, dialectTtsInstruction]);
43
53
  const { messages, append, isLoading, lastMessage, setMessages } = useChat(agentTools, { knowledgeId });
44
54
 
45
55
  useEffect(() => {
@@ -25,6 +25,8 @@ export interface BuddyAssistantProps {
25
25
  className?: string;
26
26
  voiceSpeed?: number;
27
27
  tools?: Tool[];
28
+ /** Set to true to disable automatic dialect from userInfo. Default: false (dialect enabled). */
29
+ disableDialect?: boolean;
28
30
  }
29
31
 
30
32
  let idCounter = 0;
@@ -39,10 +41,16 @@ export function BuddyAssistant({
39
41
  className,
40
42
  voiceSpeed = 1,
41
43
  tools,
44
+ disableDialect = false,
42
45
  }: BuddyAssistantProps): JSX.Element {
43
- const { ai, event, plugin } = useRimori();
46
+ const { ai, event, plugin, userInfo } = useRimori();
44
47
  const { isDark } = useTheme(plugin.theme);
45
48
  const buddy = plugin.getUserInfo()?.study_buddy;
49
+ const dialect = !disableDialect ? userInfo?.dialect : undefined;
50
+ const dialectSystemSuffix = dialect
51
+ ? `\n\nThe user is learning the regional ${dialect} dialect. Occasionally use typical regional vocabulary and expressions from this dialect to help them learn local language naturally.`
52
+ : '';
53
+ const dialectTtsInstruction = dialect ? `Speak with a ${dialect} accent and pronunciation.` : undefined;
46
54
 
47
55
  const [ttsEnabled, setTtsEnabled] = useState(true);
48
56
  const [chatInput, setChatInput] = useState('');
@@ -60,6 +68,10 @@ export function BuddyAssistant({
60
68
  [buddy?.voiceId, ai],
61
69
  );
62
70
 
71
+ useEffect(() => {
72
+ sender.setInstructions(dialectTtsInstruction);
73
+ }, [sender, dialectTtsInstruction]);
74
+
63
75
  // Setup sender callbacks and cleanup
64
76
  useEffect(() => {
65
77
  sender.setVoiceSpeed(voiceSpeed);
@@ -68,9 +80,9 @@ export function BuddyAssistant({
68
80
  return () => sender.cleanup();
69
81
  }, [sender]);
70
82
 
71
- // Build full API message list with system prompt
83
+ // Build full API message list with system prompt (dialect appended when enabled)
72
84
  const buildApiMessages = (history: ChatMessage[]) => [
73
- { role: 'system' as const, content: systemPrompt },
85
+ { role: 'system' as const, content: systemPrompt + dialectSystemSuffix },
74
86
  ...history.map((m) => ({ role: m.role, content: m.content })),
75
87
  ];
76
88
 
@@ -14,6 +14,10 @@ type AudioPlayerProps = {
14
14
  enableSpeedAdjustment?: boolean;
15
15
  playListenerEvent?: string;
16
16
  size?: string;
17
+ /** Explicit TTS instruction string. If provided, overrides auto-dialect. */
18
+ ttsInstructions?: string;
19
+ /** Set to true to disable automatic dialect from userInfo. Default: false (dialect enabled). */
20
+ disableDialect?: boolean;
17
21
  };
18
22
 
19
23
  export const AudioPlayOptions = [0.8, 0.9, 1.0, 1.1, 1.2, 1.5];
@@ -32,12 +36,14 @@ export const AudioPlayer: React.FC<AudioPlayerProps> = ({
32
36
  enableSpeedAdjustment = false,
33
37
  cache = true,
34
38
  size = '25px',
39
+ ttsInstructions,
40
+ disableDialect = false,
35
41
  }) => {
36
42
  const [audioUrl, setAudioUrl] = useState<string | null>(null);
37
43
  const [speed, setSpeed] = useState(initialSpeed);
38
44
  const [isPlaying, setIsPlaying] = useState(false);
39
45
  const [isLoading, setIsLoading] = useState(false);
40
- const { ai } = useRimori();
46
+ const { ai, userInfo } = useRimori();
41
47
  const audioRef = useRef<HTMLAudioElement | null>(null);
42
48
  const eventBusListenerRef = useRef<{ off: () => void } | null>(null);
43
49
 
@@ -52,7 +58,9 @@ export const AudioPlayer: React.FC<AudioPlayerProps> = ({
52
58
  const generateAudio = async () => {
53
59
  setIsLoading(true);
54
60
 
55
- const blob = await ai.getVoice(text, voice || (language ? 'aws_default' : 'openai_alloy'), 1, language, cache);
61
+ const effectiveInstructions = ttsInstructions
62
+ ?? (!disableDialect && userInfo?.dialect ? `Speak with a ${userInfo.dialect} accent and pronunciation.` : undefined);
63
+ const blob = await ai.getVoice(text, voice || (language ? 'aws_default' : 'openai_alloy'), 1, language, cache, effectiveInstructions);
56
64
  setAudioUrl(URL.createObjectURL(blob));
57
65
  setIsLoading(false);
58
66
  };