@bytexbyte/nxtlinq-ai-agent-ui-react-development 0.4.0 → 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 +9 -3
  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 +2 -2
  12. package/src/context/ChatBotContext.tsx +9 -2
  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,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
- }