@bytexbyte/nxtlinq-ai-agent-ui-react-development 0.3.4 → 0.4.1

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.
Files changed (133) hide show
  1. package/dist/context/ChatBotContext.d.ts.map +1 -1
  2. package/dist/context/ChatBotContext.js +19 -17
  3. package/dist/types/ChatBotTypes.d.ts +0 -5
  4. package/dist/types/ChatBotTypes.d.ts.map +1 -1
  5. package/dist/ui/ChatBotHeader.d.ts.map +1 -1
  6. package/dist/ui/ChatBotHeader.js +6 -2
  7. package/dist/ui/ChatBotUI.d.ts.map +1 -1
  8. package/dist/ui/ChatBotUI.js +8 -1
  9. package/dist/ui/styles/isolatedStyles.d.ts.map +1 -1
  10. package/dist/ui/styles/isolatedStyles.js +1 -0
  11. package/package.json +3 -3
  12. package/src/context/ChatBotContext.tsx +20 -17
  13. package/src/types/ChatBotTypes.ts +2 -6
  14. package/src/ui/ChatBotHeader.tsx +9 -3
  15. package/src/ui/ChatBotUI.tsx +8 -1
  16. package/src/ui/styles/isolatedStyles.ts +1 -0
  17. package/dist/NxtlinqAgentChat.d.ts +0 -26
  18. package/dist/NxtlinqAgentChat.d.ts.map +0 -1
  19. package/dist/NxtlinqAgentChat.js +0 -28
  20. package/dist/components/AgentAssistantShell.d.ts +0 -5
  21. package/dist/components/AgentAssistantShell.d.ts.map +0 -1
  22. package/dist/components/AgentAssistantShell.js +0 -52
  23. package/dist/components/AgentComposer.d.ts +0 -3
  24. package/dist/components/AgentComposer.d.ts.map +0 -1
  25. package/dist/components/AgentComposer.js +0 -60
  26. package/dist/components/AgentMessageList.d.ts +0 -3
  27. package/dist/components/AgentMessageList.d.ts.map +0 -1
  28. package/dist/components/AgentMessageList.js +0 -37
  29. package/dist/components/AgentRemoteAudio.d.ts +0 -4
  30. package/dist/components/AgentRemoteAudio.d.ts.map +0 -1
  31. package/dist/components/AgentRemoteAudio.js +0 -34
  32. package/dist/components/AgentVoiceBar.d.ts +0 -3
  33. package/dist/components/AgentVoiceBar.d.ts.map +0 -1
  34. package/dist/components/AgentVoiceBar.js +0 -91
  35. package/dist/components/PresetMessageChips.d.ts +0 -3
  36. package/dist/components/PresetMessageChips.d.ts.map +0 -1
  37. package/dist/components/PresetMessageChips.js +0 -23
  38. package/dist/context/AgentAssistantContext.d.ts +0 -32
  39. package/dist/context/AgentAssistantContext.d.ts.map +0 -1
  40. package/dist/context/AgentAssistantContext.js +0 -179
  41. package/dist/legacy/assets/images/adiSideItalicDataUri.d.ts +0 -2
  42. package/dist/legacy/assets/images/adiSideItalicDataUri.d.ts.map +0 -1
  43. package/dist/legacy/assets/images/adiSideItalicDataUri.js +0 -1
  44. package/dist/legacy/chatbot/ChatBot.d.ts +0 -5
  45. package/dist/legacy/chatbot/ChatBot.d.ts.map +0 -1
  46. package/dist/legacy/chatbot/ChatBot.js +0 -35
  47. package/dist/legacy/chatbot/context/ChatBotContext.d.ts +0 -5
  48. package/dist/legacy/chatbot/context/ChatBotContext.d.ts.map +0 -1
  49. package/dist/legacy/chatbot/context/ChatBotContext.js +0 -2922
  50. package/dist/legacy/chatbot/types/ChatBotTypes.d.ts +0 -166
  51. package/dist/legacy/chatbot/types/ChatBotTypes.d.ts.map +0 -1
  52. package/dist/legacy/chatbot/types/ChatBotTypes.js +0 -1
  53. package/dist/legacy/chatbot/ui/BerifyMeModal.d.ts +0 -17
  54. package/dist/legacy/chatbot/ui/BerifyMeModal.d.ts.map +0 -1
  55. package/dist/legacy/chatbot/ui/BerifyMeModal.js +0 -110
  56. package/dist/legacy/chatbot/ui/ChatBotHeader.d.ts +0 -15
  57. package/dist/legacy/chatbot/ui/ChatBotHeader.d.ts.map +0 -1
  58. package/dist/legacy/chatbot/ui/ChatBotHeader.js +0 -62
  59. package/dist/legacy/chatbot/ui/ChatBotUI.d.ts +0 -3
  60. package/dist/legacy/chatbot/ui/ChatBotUI.d.ts.map +0 -1
  61. package/dist/legacy/chatbot/ui/ChatBotUI.js +0 -557
  62. package/dist/legacy/chatbot/ui/MessageInput.d.ts +0 -3
  63. package/dist/legacy/chatbot/ui/MessageInput.d.ts.map +0 -1
  64. package/dist/legacy/chatbot/ui/MessageInput.js +0 -321
  65. package/dist/legacy/chatbot/ui/MessageList.d.ts +0 -4
  66. package/dist/legacy/chatbot/ui/MessageList.d.ts.map +0 -1
  67. package/dist/legacy/chatbot/ui/MessageList.js +0 -455
  68. package/dist/legacy/chatbot/ui/ModelSelector.d.ts +0 -4
  69. package/dist/legacy/chatbot/ui/ModelSelector.d.ts.map +0 -1
  70. package/dist/legacy/chatbot/ui/ModelSelector.js +0 -122
  71. package/dist/legacy/chatbot/ui/NotificationModal.d.ts +0 -15
  72. package/dist/legacy/chatbot/ui/NotificationModal.d.ts.map +0 -1
  73. package/dist/legacy/chatbot/ui/NotificationModal.js +0 -53
  74. package/dist/legacy/chatbot/ui/PermissionForm.d.ts +0 -8
  75. package/dist/legacy/chatbot/ui/PermissionForm.d.ts.map +0 -1
  76. package/dist/legacy/chatbot/ui/PermissionForm.js +0 -465
  77. package/dist/legacy/chatbot/ui/PresetMessages.d.ts +0 -4
  78. package/dist/legacy/chatbot/ui/PresetMessages.d.ts.map +0 -1
  79. package/dist/legacy/chatbot/ui/PresetMessages.js +0 -33
  80. package/dist/legacy/chatbot/ui/VoiceModePanel.d.ts +0 -3
  81. package/dist/legacy/chatbot/ui/VoiceModePanel.d.ts.map +0 -1
  82. package/dist/legacy/chatbot/ui/VoiceModePanel.js +0 -95
  83. package/dist/legacy/chatbot/ui/chatBotHeaderParts.d.ts +0 -15
  84. package/dist/legacy/chatbot/ui/chatBotHeaderParts.d.ts.map +0 -1
  85. package/dist/legacy/chatbot/ui/chatBotHeaderParts.js +0 -50
  86. package/dist/legacy/chatbot/ui/styles/isolatedStyles.d.ts +0 -73
  87. package/dist/legacy/chatbot/ui/styles/isolatedStyles.d.ts.map +0 -1
  88. package/dist/legacy/chatbot/ui/styles/isolatedStyles.js +0 -985
  89. package/dist/legacy/index.d.ts +0 -14
  90. package/dist/legacy/index.d.ts.map +0 -1
  91. package/dist/legacy/index.js +0 -12
  92. package/dist/theme/defaultTheme.d.ts +0 -3
  93. package/dist/theme/defaultTheme.d.ts.map +0 -1
  94. package/dist/theme/defaultTheme.js +0 -20
  95. package/dist/types.d.ts +0 -62
  96. package/dist/types.d.ts.map +0 -1
  97. package/dist/types.js +0 -1
  98. package/dist/voice/useVoiceConnectOrchestration.d.ts +0 -21
  99. package/dist/voice/useVoiceConnectOrchestration.d.ts.map +0 -1
  100. package/dist/voice/useVoiceConnectOrchestration.js +0 -86
  101. package/dist/voice/useVoiceMicState.d.ts +0 -15
  102. package/dist/voice/useVoiceMicState.d.ts.map +0 -1
  103. package/dist/voice/useVoiceMicState.js +0 -94
  104. package/dist/voice/useVoiceSilenceCommit.d.ts +0 -10
  105. package/dist/voice/useVoiceSilenceCommit.d.ts.map +0 -1
  106. package/dist/voice/useVoiceSilenceCommit.js +0 -67
  107. package/dist/voice/useVoiceTranscriptMessages.d.ts +0 -18
  108. package/dist/voice/useVoiceTranscriptMessages.d.ts.map +0 -1
  109. package/dist/voice/useVoiceTranscriptMessages.js +0 -132
  110. package/dist/voice/useWsRealtimeAudio.d.ts +0 -18
  111. package/dist/voice/useWsRealtimeAudio.d.ts.map +0 -1
  112. package/dist/voice/useWsRealtimeAudio.js +0 -102
  113. package/dist/voice/voiceMicConstants.d.ts +0 -4
  114. package/dist/voice/voiceMicConstants.d.ts.map +0 -1
  115. package/dist/voice/voiceMicConstants.js +0 -10
  116. package/dist/voice/voiceUserBubble.d.ts +0 -10
  117. package/dist/voice/voiceUserBubble.d.ts.map +0 -1
  118. package/dist/voice/voiceUserBubble.js +0 -52
  119. package/dist/voice/ws/BrowserWsPcmPlayer.d.ts +0 -23
  120. package/dist/voice/ws/BrowserWsPcmPlayer.d.ts.map +0 -1
  121. package/dist/voice/ws/BrowserWsPcmPlayer.js +0 -137
  122. package/dist/voice/ws/BrowserWsPcmRecorder.d.ts +0 -17
  123. package/dist/voice/ws/BrowserWsPcmRecorder.d.ts.map +0 -1
  124. package/dist/voice/ws/BrowserWsPcmRecorder.js +0 -71
  125. package/dist/voice/ws/float32ToPcm16.d.ts +0 -2
  126. package/dist/voice/ws/float32ToPcm16.d.ts.map +0 -1
  127. package/dist/voice/ws/float32ToPcm16.js +0 -8
  128. package/dist/voice/ws/voiceSilenceConstants.d.ts +0 -5
  129. package/dist/voice/ws/voiceSilenceConstants.d.ts.map +0 -1
  130. package/dist/voice/ws/voiceSilenceConstants.js +0 -4
  131. package/dist/voice/ws/wsRealtimeConstants.d.ts +0 -2
  132. package/dist/voice/ws/wsRealtimeConstants.d.ts.map +0 -1
  133. package/dist/voice/ws/wsRealtimeConstants.js +0 -1
@@ -1,60 +0,0 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
2
- import React from 'react';
3
- import { useAgentAssistant } from '../context/AgentAssistantContext';
4
- export function AgentComposer() {
5
- const { theme, placeholder, inputText, setInputText, sendText, isLoading, isVoiceAvailable, interactionMode, startVoice, isVoiceConnecting, enableFileUpload, sendMessage, } = useAgentAssistant();
6
- const fileInputRef = React.useRef(null);
7
- if (interactionMode === 'voice') {
8
- return null;
9
- }
10
- const handleFiles = async (files) => {
11
- if (!files?.length)
12
- return;
13
- const { fileToAttachment } = await import('@bytexbyte/nxtlinq-ai-agent-web-development');
14
- const attachments = await Promise.all(Array.from(files).map((file) => fileToAttachment(file)));
15
- await sendMessage(attachments.length ? `Uploaded ${attachments.length} file(s)` : '', { attachments });
16
- if (fileInputRef.current)
17
- fileInputRef.current.value = '';
18
- };
19
- return (_jsxs("div", { style: {
20
- borderTop: `1px solid ${theme.colors.border}`,
21
- backgroundColor: theme.colors.surface,
22
- padding: theme.spacing.md,
23
- }, children: [_jsxs("div", { style: { display: 'flex', gap: theme.spacing.sm, alignItems: 'flex-end' }, children: [enableFileUpload ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", onClick: () => fileInputRef.current?.click(), disabled: isLoading, style: {
24
- width: 36,
25
- height: 36,
26
- borderRadius: theme.radius.button,
27
- border: `1px solid ${theme.colors.border}`,
28
- backgroundColor: theme.colors.surface,
29
- cursor: 'pointer',
30
- }, "aria-label": "Upload file", children: "+" }), _jsx("input", { ref: fileInputRef, type: "file", multiple: true, accept: "image/*,.pdf,.doc,.docx,.txt", style: { display: 'none' }, onChange: (e) => void handleFiles(e.target.files) })] })) : null, _jsx("textarea", { value: inputText, onChange: (e) => setInputText(e.target.value), placeholder: placeholder, rows: 2, disabled: isLoading, maxLength: 4000, style: {
31
- flex: 1,
32
- resize: 'none',
33
- border: `1px solid ${theme.colors.border}`,
34
- borderRadius: theme.radius.panel,
35
- padding: theme.spacing.sm,
36
- fontSize: theme.typography.bodySize,
37
- color: theme.colors.assistantText,
38
- } }), _jsx("button", { type: "button", onClick: () => void sendText(), disabled: isLoading || !inputText.trim(), style: {
39
- backgroundColor: theme.colors.primary,
40
- color: theme.colors.primaryText,
41
- border: 'none',
42
- borderRadius: theme.radius.button,
43
- padding: `${theme.spacing.sm}px ${theme.spacing.md}px`,
44
- fontWeight: 600,
45
- opacity: isLoading || !inputText.trim() ? 0.5 : 1,
46
- cursor: 'pointer',
47
- }, children: "Send" })] }), isVoiceAvailable ? (_jsx("button", { type: "button", onClick: () => {
48
- startVoice().catch((err) => {
49
- console.warn('[nxtlinq] startVoice failed:', err);
50
- });
51
- }, disabled: isVoiceConnecting, style: {
52
- display: 'block',
53
- margin: `${theme.spacing.sm}px auto 0`,
54
- border: 'none',
55
- background: 'none',
56
- color: theme.colors.primary,
57
- fontSize: theme.typography.captionSize,
58
- cursor: 'pointer',
59
- }, children: isVoiceConnecting ? 'Connecting voice…' : 'Switch to voice mode' })) : null] }));
60
- }
@@ -1,3 +0,0 @@
1
- import React from 'react';
2
- export declare function AgentMessageList(): React.ReactElement;
3
- //# sourceMappingURL=AgentMessageList.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AgentMessageList.d.ts","sourceRoot":"","sources":["../../src/components/AgentMessageList.tsx"],"names":[],"mappings":"AACA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAyCjD,wBAAgB,gBAAgB,IAAI,KAAK,CAAC,YAAY,CAmCrD"}
@@ -1,37 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
2
- import { useEffect, useRef } from 'react';
3
- import { useAgentAssistant } from '../context/AgentAssistantContext';
4
- function MessageBubble({ message }) {
5
- const { theme } = useAgentAssistant();
6
- const isUser = message.role === 'user';
7
- const displayText = message.partialContent && message.isStreaming
8
- ? message.partialContent
9
- : message.content;
10
- return (_jsx("div", { style: {
11
- display: 'flex',
12
- justifyContent: isUser ? 'flex-end' : 'flex-start',
13
- marginBottom: theme.spacing.sm,
14
- }, children: _jsxs("div", { style: {
15
- maxWidth: '85%',
16
- padding: `${theme.spacing.sm}px ${theme.spacing.md}px`,
17
- borderRadius: theme.radius.bubble,
18
- backgroundColor: isUser ? theme.colors.userBubble : theme.colors.assistantBubble,
19
- color: isUser ? theme.colors.userText : theme.colors.assistantText,
20
- fontSize: theme.typography.bodySize,
21
- whiteSpace: 'pre-wrap',
22
- }, children: [displayText || ' ', message.error ? (_jsx("div", { style: { color: theme.colors.error, fontSize: theme.typography.captionSize }, children: message.error })) : null] }) }));
23
- }
24
- export function AgentMessageList() {
25
- const { messages, isLoading, theme } = useAgentAssistant();
26
- const endRef = useRef(null);
27
- useEffect(() => {
28
- endRef.current?.scrollIntoView({ behavior: 'smooth' });
29
- }, [messages.length, messages[messages.length - 1]?.content, messages[messages.length - 1]?.partialContent]);
30
- return (_jsxs("div", { style: {
31
- flex: 1,
32
- minHeight: 0,
33
- overflowY: 'auto',
34
- padding: theme.spacing.md,
35
- backgroundColor: theme.colors.background,
36
- }, children: [messages.length === 0 ? (_jsx("p", { style: { textAlign: 'center', color: theme.colors.mutedText, marginTop: 40 }, children: "Send a message to start the conversation." })) : (messages.map((message) => (_jsx(MessageBubble, { message: message }, message.id)))), isLoading ? (_jsx("p", { style: { color: theme.colors.mutedText, fontSize: theme.typography.captionSize }, children: "Thinking\u2026" })) : null, _jsx("div", { ref: endRef })] }));
37
- }
@@ -1,4 +0,0 @@
1
- import React from 'react';
2
- /** Plays assistant WebRTC remote audio with retry until stream is ready. */
3
- export declare function AgentRemoteAudio(): React.ReactElement | null;
4
- //# sourceMappingURL=AgentRemoteAudio.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AgentRemoteAudio.d.ts","sourceRoot":"","sources":["../../src/components/AgentRemoteAudio.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAGjD,4EAA4E;AAC5E,wBAAgB,gBAAgB,IAAI,KAAK,CAAC,YAAY,GAAG,IAAI,CA6B5D"}
@@ -1,34 +0,0 @@
1
- import { jsx as _jsx } from "@emotion/react/jsx-runtime";
2
- import { useEffect, useRef } from 'react';
3
- import { useAgentAssistant } from '../context/AgentAssistantContext';
4
- /** Plays assistant WebRTC remote audio with retry until stream is ready. */
5
- export function AgentRemoteAudio() {
6
- const { getRemoteAudioStream, isVoiceActive, isVoiceChannelReady } = useAgentAssistant();
7
- const audioRef = useRef(null);
8
- useEffect(() => {
9
- const audio = audioRef.current;
10
- if (!audio || !isVoiceActive)
11
- return;
12
- let cancelled = false;
13
- const attach = () => {
14
- if (cancelled)
15
- return;
16
- const stream = getRemoteAudioStream();
17
- if (!stream)
18
- return;
19
- audio.srcObject = stream;
20
- void audio.play().catch(() => undefined);
21
- };
22
- attach();
23
- const timer = window.setInterval(attach, 120);
24
- return () => {
25
- cancelled = true;
26
- window.clearInterval(timer);
27
- audio.pause();
28
- audio.srcObject = null;
29
- };
30
- }, [getRemoteAudioStream, isVoiceActive, isVoiceChannelReady]);
31
- if (!isVoiceActive)
32
- return null;
33
- return _jsx("audio", { ref: audioRef, autoPlay: true, playsInline: true, style: { display: 'none' } });
34
- }
@@ -1,3 +0,0 @@
1
- import React from 'react';
2
- export declare function AgentVoiceBar(): React.ReactElement | null;
3
- //# sourceMappingURL=AgentVoiceBar.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AgentVoiceBar.d.ts","sourceRoot":"","sources":["../../src/components/AgentVoiceBar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsB,MAAM,OAAO,CAAC;AAsC3C,wBAAgB,aAAa,IAAI,KAAK,CAAC,YAAY,GAAG,IAAI,CAsIzD"}
@@ -1,91 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
2
- import { useCallback } from 'react';
3
- import { useAgentAssistant, voiceStatusLabel, } from '../context/AgentAssistantContext';
4
- function statusDotColor(status, theme) {
5
- switch (status) {
6
- case 'listening':
7
- return theme.colors.voiceActive;
8
- case 'speaking':
9
- return theme.colors.voiceSpeaking;
10
- case 'idle':
11
- return theme.colors.mutedText;
12
- default:
13
- return theme.colors.primary;
14
- }
15
- }
16
- function MicIcon({ color }) {
17
- return (_jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: color, "aria-hidden": true, children: _jsx("path", { d: "M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5-3c0 2.76-2.24 5-5 5s-5-2.24-5-5H5c0 3.53 2.61 6.43 6 6.92V21h2v-3.08c3.39-.49 6-3.39 6-6.92h-2z" }) }));
18
- }
19
- function MicOffIcon() {
20
- return (_jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "#ef4444", "aria-hidden": true, children: _jsx("path", { d: "M19 11h-1.7c0 .74-.16 1.43-.43 2.05l1.23 1.23c.56-.98.9-2.09.9-3.28zm-4.02.17c0-.06.02-.11.02-.17V5c0-1.66-1.34-3-3-3s-3 1.34-3 3v.18l5.98 5.99zM4.27 3L3 4.27l6.01 6.01V11c0 1.66 1.33 3 2.99 3 .22 0 .44-.03.65-.08l1.66 1.66c-.71.33-1.5.52-2.31.52-2.76 0-5.3-2.1-5.3-5.1H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c.91-.13 1.77-.45 2.54-.9L19.73 21 21 19.73 4.27 3z" }) }));
21
- }
22
- export function AgentVoiceBar() {
23
- const { theme, interactionMode, voiceStatus, voiceSessionId, isVoiceConnecting, isVoiceChannelReady, stopVoice, isVoiceAvailable, isMicMuted, isMicHeldForAssistant, toggleVoiceMicMute, } = useAgentAssistant();
24
- const returnToTextMode = useCallback(() => {
25
- void stopVoice();
26
- }, [stopVoice]);
27
- if (!isVoiceAvailable)
28
- return null;
29
- if (interactionMode !== 'voice' && !isVoiceConnecting)
30
- return null;
31
- const showConnecting = isVoiceConnecting;
32
- const awaitingChannel = Boolean(voiceSessionId) &&
33
- !isVoiceConnecting &&
34
- !isVoiceChannelReady &&
35
- voiceStatus === 'idle';
36
- const statusHint = showConnecting
37
- ? 'Tap Back to text mode below to cancel'
38
- : awaitingChannel
39
- ? 'Waiting for voice channel…'
40
- : isMicHeldForAssistant
41
- ? 'Assistant is responding — tap mic to interrupt and speak'
42
- : isMicMuted
43
- ? 'Mic is off — tap the mic when ready to speak'
44
- : voiceStatus === 'listening'
45
- ? 'Start speaking'
46
- : voiceStatus === 'speaking'
47
- ? 'Assistant is speaking…'
48
- : voiceStatus === 'thinking'
49
- ? 'Thinking…'
50
- : '';
51
- return (_jsxs("div", { style: {
52
- borderTop: `1px solid ${theme.colors.border}`,
53
- backgroundColor: theme.colors.surface,
54
- padding: theme.spacing.md,
55
- }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 10 }, children: [_jsxs("div", { style: {
56
- flex: 1,
57
- minWidth: 0,
58
- border: `1px solid ${theme.colors.border}`,
59
- borderRadius: 12,
60
- backgroundColor: theme.colors.background,
61
- padding: '8px 10px',
62
- }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 6 }, children: [_jsx("span", { style: {
63
- width: 8,
64
- height: 8,
65
- borderRadius: 4,
66
- backgroundColor: statusDotColor(voiceStatus, theme),
67
- flexShrink: 0,
68
- } }), _jsx("span", { style: {
69
- color: theme.colors.assistantText,
70
- fontSize: theme.typography.captionSize,
71
- fontWeight: 600,
72
- }, children: showConnecting || awaitingChannel ? 'Connecting' : voiceStatusLabel(voiceStatus) }), showConnecting ? (_jsx("span", { style: { color: theme.colors.mutedText, fontSize: theme.typography.captionSize }, children: "\u2026" })) : null] }), statusHint ? (_jsx("p", { style: {
73
- margin: '4px 0 0',
74
- color: theme.colors.mutedText,
75
- fontSize: theme.typography.captionSize - 1,
76
- }, children: statusHint })) : null] }), _jsx("button", { type: "button", onClick: toggleVoiceMicMute, disabled: showConnecting || awaitingChannel, style: {
77
- border: 'none',
78
- background: 'none',
79
- padding: 8,
80
- cursor: showConnecting || awaitingChannel ? 'not-allowed' : 'pointer',
81
- opacity: showConnecting || awaitingChannel ? 0.45 : 1,
82
- }, "aria-label": isMicMuted ? 'Unmute microphone' : 'Mute microphone', children: isMicMuted ? _jsx(MicOffIcon, {}) : _jsx(MicIcon, { color: theme.colors.assistantText }) })] }), _jsx("button", { type: "button", onClick: returnToTextMode, style: {
83
- display: 'block',
84
- margin: `${theme.spacing.sm}px auto 0`,
85
- border: 'none',
86
- background: 'none',
87
- color: theme.colors.primary,
88
- fontSize: theme.typography.captionSize,
89
- cursor: 'pointer',
90
- }, children: "Back to text mode" })] }));
91
- }
@@ -1,3 +0,0 @@
1
- import React from 'react';
2
- export declare function PresetMessageChips(): React.ReactElement | null;
3
- //# sourceMappingURL=PresetMessageChips.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PresetMessageChips.d.ts","sourceRoot":"","sources":["../../src/components/PresetMessageChips.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,wBAAgB,kBAAkB,IAAI,KAAK,CAAC,YAAY,GAAG,IAAI,CAoC9D"}
@@ -1,23 +0,0 @@
1
- import { jsx as _jsx } from "@emotion/react/jsx-runtime";
2
- import { useAgentAssistant } from '../context/AgentAssistantContext';
3
- export function PresetMessageChips() {
4
- const { presetMessages, selectPreset, theme, interactionMode } = useAgentAssistant();
5
- if (!presetMessages.length || interactionMode === 'voice') {
6
- return null;
7
- }
8
- return (_jsx("div", { style: {
9
- display: 'flex',
10
- flexWrap: 'wrap',
11
- gap: theme.spacing.sm,
12
- padding: `${theme.spacing.sm}px ${theme.spacing.md}px`,
13
- borderBottom: `1px solid ${theme.colors.border}`,
14
- }, children: presetMessages.map((preset, index) => (_jsx("button", { type: "button", onClick: () => void selectPreset(preset), style: {
15
- border: `1px solid ${theme.colors.border}`,
16
- borderRadius: theme.radius.button,
17
- padding: `${theme.spacing.xs}px ${theme.spacing.sm}px`,
18
- backgroundColor: theme.colors.surface,
19
- color: theme.colors.assistantText,
20
- fontSize: theme.typography.captionSize,
21
- cursor: 'pointer',
22
- }, children: preset.text }, `${preset.text}-${index}`))) }));
23
- }
@@ -1,32 +0,0 @@
1
- import type { VoiceStatus } from '@bytexbyte/nxtlinq-ai-agent-core-development';
2
- import { type UseNxtlinqAgentResult, type UseNxtlinqVoiceResult } from '@bytexbyte/nxtlinq-ai-agent-web-development';
3
- import React, { type ReactNode } from 'react';
4
- import type { AgentAssistantTheme, NxtlinqAgentChatProps, PresetMessage } from '../types';
5
- export type InteractionMode = 'text' | 'voice';
6
- export type AgentAssistantContextValue = UseNxtlinqAgentResult & UseNxtlinqVoiceResult & {
7
- theme: AgentAssistantTheme;
8
- title: string;
9
- placeholder: string;
10
- presetMessages: PresetMessage[];
11
- interactionMode: InteractionMode;
12
- setInteractionMode: (mode: InteractionMode) => void;
13
- inputText: string;
14
- setInputText: (text: string) => void;
15
- isVoiceAvailable: boolean;
16
- isVoiceConnecting: boolean;
17
- isMicMuted: boolean;
18
- isMicHeldForAssistant: boolean;
19
- toggleVoiceMicMute: () => void;
20
- isVoiceChannelReady: boolean;
21
- enableFileUpload: boolean;
22
- sendText: () => Promise<void>;
23
- selectPreset: (preset: PresetMessage) => Promise<void>;
24
- };
25
- export type AgentAssistantProviderProps = {
26
- children: ReactNode;
27
- ui: Pick<NxtlinqAgentChatProps, 'title' | 'placeholder' | 'presetMessages' | 'enableVoice' | 'enableFileUpload' | 'theme' | 'startWithMicMuted' | 'holdMicDuringAssistant'>;
28
- };
29
- export declare function AgentAssistantProvider({ children, ui, }: AgentAssistantProviderProps): React.ReactElement;
30
- export declare function useAgentAssistant(): AgentAssistantContextValue;
31
- export declare function voiceStatusLabel(status: VoiceStatus): string;
32
- //# sourceMappingURL=AgentAssistantContext.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AgentAssistantContext.d.ts","sourceRoot":"","sources":["../../src/context/AgentAssistantContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,WAAW,EAAE,MAAM,8CAA8C,CAAC;AACzF,OAAO,EAGL,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC3B,MAAM,6CAA6C,CAAC;AACrD,OAAO,KAAK,EAAE,EAOZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAK1F,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,OAAO,CAAC;AAE/C,MAAM,MAAM,0BAA0B,GAAG,qBAAqB,GAC5D,qBAAqB,GAAG;IACxB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,eAAe,EAAE,eAAe,CAAC;IACjC,kBAAkB,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC;IACpB,qBAAqB,EAAE,OAAO,CAAC;IAC/B,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,YAAY,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD,CAAC;AAIF,MAAM,MAAM,2BAA2B,GAAG;IACxC,QAAQ,EAAE,SAAS,CAAC;IACpB,EAAE,EAAE,IAAI,CACN,qBAAqB,EACnB,OAAO,GACP,aAAa,GACb,gBAAgB,GAChB,aAAa,GACb,kBAAkB,GAClB,OAAO,GACP,mBAAmB,GACnB,wBAAwB,CAC3B,CAAC;CACH,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,EAAE,GACH,EAAE,2BAA2B,GAAG,KAAK,CAAC,YAAY,CA8MlD;AAED,wBAAgB,iBAAiB,IAAI,0BAA0B,CAQ9D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAU5D"}
@@ -1,179 +0,0 @@
1
- import { jsx as _jsx } from "@emotion/react/jsx-runtime";
2
- import { useNxtlinqAgent, useNxtlinqVoice, } from '@bytexbyte/nxtlinq-ai-agent-web-development';
3
- import { createContext, useCallback, useContext, useEffect, useMemo, useState, } from 'react';
4
- import { defaultAgentAssistantTheme } from '../theme/defaultTheme';
5
- import { useVoiceConnectOrchestration } from '../voice/useVoiceConnectOrchestration';
6
- import { useVoiceMicState } from '../voice/useVoiceMicState';
7
- import { useVoiceTranscriptMessages } from '../voice/useVoiceTranscriptMessages';
8
- const AgentAssistantContext = createContext(null);
9
- export function AgentAssistantProvider({ children, ui, }) {
10
- const agent = useNxtlinqAgent();
11
- const voice = useNxtlinqVoice();
12
- const [interactionMode, setInteractionModeState] = useState('text');
13
- const [inputText, setInputText] = useState('');
14
- const [isVoiceConnecting, setIsVoiceConnecting] = useState(false);
15
- const isVoiceAvailable = ui.enableVoice !== false;
16
- const micStartsMuted = ui.startWithMicMuted ?? true;
17
- const handleVoiceBargeIn = useCallback(() => {
18
- voice.interrupt();
19
- }, [voice]);
20
- const { isMicMuted, isMicHeldForAssistant, toggleVoiceMicMute, prepareForVoiceConnect, resetMicState, clearAssistantMicHold, } = useVoiceMicState(voice, isVoiceConnecting, {
21
- startWithMicMuted: micStartsMuted,
22
- holdMicDuringAssistant: ui.holdMicDuringAssistant ?? true,
23
- onBargeIn: handleVoiceBargeIn,
24
- });
25
- const voiceTranscriptApi = useMemo(() => ({
26
- getMessages: () => agent.agent.getSnapshot().messages,
27
- updateMessages: (updater) => {
28
- agent.setMessages(updater(agent.agent.getSnapshot().messages));
29
- },
30
- syncVoiceTurnHistory: agent.syncVoiceTurnHistory,
31
- }), [agent.agent, agent.setMessages, agent.syncVoiceTurnHistory]);
32
- const { handleTranscript, handleDone, clearVoiceStream } = useVoiceTranscriptMessages(voiceTranscriptApi, interactionMode, voice.voiceSessionId);
33
- const setInteractionMode = useCallback((mode) => {
34
- if (mode === 'text' && interactionMode === 'voice') {
35
- void voice.stopVoice('switch_to_text').then(() => {
36
- clearVoiceStream();
37
- resetMicState();
38
- });
39
- }
40
- setInteractionModeState(mode);
41
- }, [interactionMode, voice, resetMicState, clearVoiceStream]);
42
- useEffect(() => {
43
- if (interactionMode === 'text' && voice.voiceSessionId != null) {
44
- void voice.stopVoice('mode_text_cleanup').then(() => {
45
- clearVoiceStream();
46
- resetMicState();
47
- });
48
- }
49
- }, [interactionMode, voice.voiceSessionId, voice, resetMicState, clearVoiceStream]);
50
- const orchestrationCallbacks = useMemo(() => ({
51
- handleTranscript,
52
- handleDone,
53
- clearVoiceStream,
54
- prepareForVoiceConnect,
55
- resetMicState,
56
- clearAssistantMicHold,
57
- setInteractionMode,
58
- setIsVoiceConnecting,
59
- }), [
60
- handleTranscript,
61
- handleDone,
62
- clearVoiceStream,
63
- prepareForVoiceConnect,
64
- resetMicState,
65
- clearAssistantMicHold,
66
- setInteractionMode,
67
- ]);
68
- const { wrappedStartVoice, wrappedStopVoice, wrappedInterrupt, isVoiceChannelReady, } = useVoiceConnectOrchestration(agent, voice, interactionMode, micStartsMuted, orchestrationCallbacks);
69
- // iOS 切換 App 或相機後返回時,若 WebRTC App Channel 已斷開則自動停止語音 session,
70
- // 避免麥克風圖示顯示活躍但狀態卡在 Idle 的問題。
71
- useEffect(() => {
72
- if (typeof document === 'undefined')
73
- return;
74
- const handleVisibilityChange = () => {
75
- if (document.visibilityState !== 'visible')
76
- return;
77
- if (voice.voiceSessionId == null)
78
- return;
79
- const session = agent.agent.getVoiceSession();
80
- if (!session?.isAppChannelOpen()) {
81
- void wrappedStopVoice();
82
- }
83
- };
84
- document.addEventListener('visibilitychange', handleVisibilityChange);
85
- return () => document.removeEventListener('visibilitychange', handleVisibilityChange);
86
- }, [voice.voiceSessionId, agent.agent, wrappedStopVoice]);
87
- const theme = useMemo(() => ({
88
- ...defaultAgentAssistantTheme,
89
- ...ui.theme,
90
- colors: { ...defaultAgentAssistantTheme.colors, ...ui.theme?.colors },
91
- spacing: { ...defaultAgentAssistantTheme.spacing, ...ui.theme?.spacing },
92
- radius: { ...defaultAgentAssistantTheme.radius, ...ui.theme?.radius },
93
- typography: {
94
- ...defaultAgentAssistantTheme.typography,
95
- ...ui.theme?.typography,
96
- },
97
- }), [ui.theme]);
98
- const sendText = useCallback(async () => {
99
- const text = inputText.trim();
100
- if (!text || agent.isLoading)
101
- return;
102
- setInputText('');
103
- await agent.sendMessage(text);
104
- }, [agent, inputText]);
105
- const selectPreset = useCallback(async (preset) => {
106
- if (preset.autoSend) {
107
- await agent.sendMessage(preset.text);
108
- }
109
- else {
110
- setInputText(preset.text);
111
- }
112
- }, [agent]);
113
- const value = useMemo(() => ({
114
- ...agent,
115
- ...voice,
116
- startVoice: wrappedStartVoice,
117
- stopVoice: wrappedStopVoice,
118
- interrupt: wrappedInterrupt,
119
- theme,
120
- title: ui.title ?? 'AI Assistant',
121
- placeholder: ui.placeholder ?? 'Type a message…',
122
- presetMessages: ui.presetMessages ?? [],
123
- interactionMode,
124
- setInteractionMode,
125
- inputText,
126
- setInputText,
127
- isVoiceAvailable,
128
- isVoiceConnecting,
129
- isMicMuted,
130
- isMicHeldForAssistant,
131
- toggleVoiceMicMute,
132
- isVoiceChannelReady,
133
- enableFileUpload: ui.enableFileUpload !== false,
134
- sendText,
135
- selectPreset,
136
- }), [
137
- agent,
138
- voice,
139
- wrappedStartVoice,
140
- wrappedStopVoice,
141
- wrappedInterrupt,
142
- theme,
143
- ui.title,
144
- ui.placeholder,
145
- ui.presetMessages,
146
- ui.enableFileUpload,
147
- interactionMode,
148
- setInteractionMode,
149
- inputText,
150
- isVoiceAvailable,
151
- isVoiceConnecting,
152
- isMicMuted,
153
- isMicHeldForAssistant,
154
- toggleVoiceMicMute,
155
- isVoiceChannelReady,
156
- sendText,
157
- selectPreset,
158
- voice.voiceStatus,
159
- ]);
160
- return (_jsx(AgentAssistantContext.Provider, { value: value, children: children }));
161
- }
162
- export function useAgentAssistant() {
163
- const ctx = useContext(AgentAssistantContext);
164
- if (!ctx) {
165
- throw new Error('useAgentAssistant must be used within <NxtlinqAgentChat> or <AgentAssistantProvider>');
166
- }
167
- return ctx;
168
- }
169
- export function voiceStatusLabel(status) {
170
- const labels = {
171
- idle: 'Ready',
172
- listening: 'Listening',
173
- transcribing: 'Transcribing',
174
- thinking: 'Thinking',
175
- generating: 'Generating',
176
- speaking: 'Speaking',
177
- };
178
- return labels[status] ?? status;
179
- }