@bytexbyte/nxtlinq-ai-agent-web-development 0.1.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.
- package/dist/context/NxtlinqAgentContext.d.ts +12 -0
- package/dist/context/NxtlinqAgentContext.d.ts.map +1 -0
- package/dist/context/NxtlinqAgentContext.js +33 -0
- package/dist/createNxtlinqAgent.d.ts +9 -0
- package/dist/createNxtlinqAgent.d.ts.map +1 -0
- package/dist/createNxtlinqAgent.js +19 -0
- package/dist/hooks/useNxtlinqAgent.d.ts +18 -0
- package/dist/hooks/useNxtlinqAgent.d.ts.map +1 -0
- package/dist/hooks/useNxtlinqAgent.js +23 -0
- package/dist/hooks/useNxtlinqVoice.d.ts +21 -0
- package/dist/hooks/useNxtlinqVoice.d.ts.map +1 -0
- package/dist/hooks/useNxtlinqVoice.js +75 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/legacy/api/nxtlinq-api.d.ts +8 -0
- package/dist/legacy/api/nxtlinq-api.d.ts.map +1 -0
- package/dist/legacy/api/nxtlinq-api.js +13 -0
- package/dist/legacy/api/voice.d.ts +11 -0
- package/dist/legacy/api/voice.d.ts.map +1 -0
- package/dist/legacy/api/voice.js +26 -0
- package/dist/legacy/core/lib/messageHistory.d.ts +2 -0
- package/dist/legacy/core/lib/messageHistory.d.ts.map +1 -0
- package/dist/legacy/core/lib/messageHistory.js +1 -0
- package/dist/legacy/core/lib/textToSpeech.d.ts +14 -0
- package/dist/legacy/core/lib/textToSpeech.d.ts.map +1 -0
- package/dist/legacy/core/lib/textToSpeech.js +82 -0
- package/dist/legacy/core/lib/useDraggable.d.ts +15 -0
- package/dist/legacy/core/lib/useDraggable.d.ts.map +1 -0
- package/dist/legacy/core/lib/useDraggable.js +158 -0
- package/dist/legacy/core/lib/useLocalStorage.d.ts +11 -0
- package/dist/legacy/core/lib/useLocalStorage.d.ts.map +1 -0
- package/dist/legacy/core/lib/useLocalStorage.js +83 -0
- package/dist/legacy/core/lib/useResizable.d.ts +17 -0
- package/dist/legacy/core/lib/useResizable.d.ts.map +1 -0
- package/dist/legacy/core/lib/useResizable.js +203 -0
- package/dist/legacy/core/lib/useSessionStorage.d.ts +11 -0
- package/dist/legacy/core/lib/useSessionStorage.d.ts.map +1 -0
- package/dist/legacy/core/lib/useSessionStorage.js +37 -0
- package/dist/legacy/core/lib/useSpeechToTextFromMic/helper.d.ts +26 -0
- package/dist/legacy/core/lib/useSpeechToTextFromMic/helper.d.ts.map +1 -0
- package/dist/legacy/core/lib/useSpeechToTextFromMic/helper.js +102 -0
- package/dist/legacy/core/lib/useSpeechToTextFromMic/index.d.ts +16 -0
- package/dist/legacy/core/lib/useSpeechToTextFromMic/index.d.ts.map +1 -0
- package/dist/legacy/core/lib/useSpeechToTextFromMic/index.js +92 -0
- package/dist/legacy/core/lib/useVoiceMode.d.ts +32 -0
- package/dist/legacy/core/lib/useVoiceMode.d.ts.map +1 -0
- package/dist/legacy/core/lib/useVoiceMode.js +373 -0
- package/dist/legacy/core/metakeepClient.d.ts +4 -0
- package/dist/legacy/core/metakeepClient.d.ts.map +1 -0
- package/dist/legacy/core/metakeepClient.js +10 -0
- package/dist/legacy/core/utils/aitUtils.d.ts +31 -0
- package/dist/legacy/core/utils/aitUtils.d.ts.map +1 -0
- package/dist/legacy/core/utils/aitUtils.js +35 -0
- package/dist/legacy/core/utils/ethersUtils.d.ts +8 -0
- package/dist/legacy/core/utils/ethersUtils.d.ts.map +1 -0
- package/dist/legacy/core/utils/ethersUtils.js +19 -0
- package/dist/legacy/core/utils/index.d.ts +3 -0
- package/dist/legacy/core/utils/index.d.ts.map +1 -0
- package/dist/legacy/core/utils/index.js +4 -0
- package/dist/legacy/core/utils/notificationUtils.d.ts +29 -0
- package/dist/legacy/core/utils/notificationUtils.d.ts.map +1 -0
- package/dist/legacy/core/utils/notificationUtils.js +47 -0
- package/dist/legacy/core/utils/urlUtils.d.ts +25 -0
- package/dist/legacy/core/utils/urlUtils.d.ts.map +1 -0
- package/dist/legacy/core/utils/urlUtils.js +135 -0
- package/dist/legacy/core/utils/walletTextUtils.d.ts +14 -0
- package/dist/legacy/core/utils/walletTextUtils.d.ts.map +1 -0
- package/dist/legacy/core/utils/walletTextUtils.js +23 -0
- package/dist/legacy/core/utils/walletUtils.d.ts +10 -0
- package/dist/legacy/core/utils/walletUtils.d.ts.map +1 -0
- package/dist/legacy/core/utils/walletUtils.js +38 -0
- package/dist/legacy/index.d.ts +19 -0
- package/dist/legacy/index.d.ts.map +1 -0
- package/dist/legacy/index.js +16 -0
- package/dist/ports/createWebPlatformPorts.d.ts +13 -0
- package/dist/ports/createWebPlatformPorts.d.ts.map +1 -0
- package/dist/ports/createWebPlatformPorts.js +25 -0
- package/dist/utils/fileToAttachment.d.ts +4 -0
- package/dist/utils/fileToAttachment.d.ts.map +1 -0
- package/dist/utils/fileToAttachment.js +28 -0
- package/dist/voice/useVoiceSilenceCommit.d.ts +11 -0
- package/dist/voice/useVoiceSilenceCommit.d.ts.map +1 -0
- package/dist/voice/useVoiceSilenceCommit.js +68 -0
- package/dist/voice/useVoiceTranscriptMessages.d.ts +16 -0
- package/dist/voice/useVoiceTranscriptMessages.d.ts.map +1 -0
- package/dist/voice/useVoiceTranscriptMessages.js +134 -0
- package/dist/voice/useWsRealtimeAudio.d.ts +18 -0
- package/dist/voice/useWsRealtimeAudio.d.ts.map +1 -0
- package/dist/voice/useWsRealtimeAudio.js +115 -0
- package/dist/voice/voiceMicConstants.d.ts +4 -0
- package/dist/voice/voiceMicConstants.d.ts.map +1 -0
- package/dist/voice/voiceMicConstants.js +10 -0
- package/dist/voice/ws/BrowserWsPcmPlayer.d.ts +23 -0
- package/dist/voice/ws/BrowserWsPcmPlayer.d.ts.map +1 -0
- package/dist/voice/ws/BrowserWsPcmPlayer.js +138 -0
- package/dist/voice/ws/BrowserWsPcmRecorder.d.ts +19 -0
- package/dist/voice/ws/BrowserWsPcmRecorder.d.ts.map +1 -0
- package/dist/voice/ws/BrowserWsPcmRecorder.js +76 -0
- package/dist/voice/ws/float32ToPcm16.d.ts +2 -0
- package/dist/voice/ws/float32ToPcm16.d.ts.map +1 -0
- package/dist/voice/ws/float32ToPcm16.js +8 -0
- package/dist/voice/ws/voiceSilenceConstants.d.ts +5 -0
- package/dist/voice/ws/voiceSilenceConstants.d.ts.map +1 -0
- package/dist/voice/ws/voiceSilenceConstants.js +4 -0
- package/dist/voice/ws/wsRealtimeConstants.d.ts +2 -0
- package/dist/voice/ws/wsRealtimeConstants.d.ts.map +1 -0
- package/dist/voice/ws/wsRealtimeConstants.js +1 -0
- package/dist/webAgentDefaults.d.ts +9 -0
- package/dist/webAgentDefaults.d.ts.map +1 -0
- package/dist/webAgentDefaults.js +9 -0
- package/package.json +55 -0
- package/src/context/NxtlinqAgentContext.tsx +79 -0
- package/src/createNxtlinqAgent.ts +36 -0
- package/src/hooks/useNxtlinqAgent.ts +73 -0
- package/src/hooks/useNxtlinqVoice.ts +143 -0
- package/src/index.ts +84 -0
- package/src/legacy/api/nxtlinq-api.ts +32 -0
- package/src/legacy/api/voice.ts +72 -0
- package/src/legacy/core/lib/messageHistory.ts +6 -0
- package/src/legacy/core/lib/textToSpeech.ts +127 -0
- package/src/legacy/core/lib/useDraggable.ts +193 -0
- package/src/legacy/core/lib/useLocalStorage.ts +89 -0
- package/src/legacy/core/lib/useResizable.ts +256 -0
- package/src/legacy/core/lib/useSessionStorage.ts +43 -0
- package/src/legacy/core/lib/useSpeechToTextFromMic/helper.ts +132 -0
- package/src/legacy/core/lib/useSpeechToTextFromMic/index.ts +126 -0
- package/src/legacy/core/lib/useVoiceMode.ts +407 -0
- package/src/legacy/core/metakeepClient.ts +12 -0
- package/src/legacy/core/utils/aitUtils.ts +55 -0
- package/src/legacy/core/utils/ethersUtils.ts +24 -0
- package/src/legacy/core/utils/index.ts +5 -0
- package/src/legacy/core/utils/notificationUtils.ts +64 -0
- package/src/legacy/core/utils/urlUtils.ts +160 -0
- package/src/legacy/core/utils/walletTextUtils.ts +26 -0
- package/src/legacy/core/utils/walletUtils.ts +53 -0
- package/src/legacy/index.ts +35 -0
- package/src/ports/createWebPlatformPorts.ts +44 -0
- package/src/utils/fileToAttachment.ts +32 -0
- package/src/voice/useVoiceSilenceCommit.ts +84 -0
- package/src/voice/useVoiceTranscriptMessages.ts +184 -0
- package/src/voice/useWsRealtimeAudio.ts +141 -0
- package/src/voice/voiceMicConstants.ts +13 -0
- package/src/voice/ws/BrowserWsPcmPlayer.ts +139 -0
- package/src/voice/ws/BrowserWsPcmRecorder.ts +83 -0
- package/src/voice/ws/float32ToPcm16.ts +8 -0
- package/src/voice/ws/voiceSilenceConstants.ts +4 -0
- package/src/voice/ws/wsRealtimeConstants.ts +1 -0
- package/src/webAgentDefaults.ts +12 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { NxtlinqAgent, type AgentConfig } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
2
|
+
import React, { type ReactNode } from 'react';
|
|
3
|
+
import { type CreateNxtlinqAgentWebOptions } from '../createNxtlinqAgent';
|
|
4
|
+
type WebAgentInternalProps = 'voiceTransport' | 'voiceMode' | 'defaultModel' | 'enableWebRTC';
|
|
5
|
+
export type NxtlinqAgentProviderProps = Omit<CreateNxtlinqAgentWebOptions, WebAgentInternalProps> & {
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
resetOnIdentityChange?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare function NxtlinqAgentProvider({ children, resetOnIdentityChange, ...options }: NxtlinqAgentProviderProps): React.ReactElement;
|
|
10
|
+
export declare function useNxtlinqAgentContext(): NxtlinqAgent;
|
|
11
|
+
export type { AgentConfig };
|
|
12
|
+
//# sourceMappingURL=NxtlinqAgentContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NxtlinqAgentContext.d.ts","sourceRoot":"","sources":["../../src/context/NxtlinqAgentContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,KAAK,WAAW,EACjB,MAAM,8CAA8C,CAAC;AACtD,OAAO,KAAK,EAAE,EAKZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,uBAAuB,CAAC;AAI/B,KAAK,qBAAqB,GACtB,gBAAgB,GAChB,WAAW,GACX,cAAc,GACd,cAAc,CAAC;AAEnB,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAC1C,4BAA4B,EAC5B,qBAAqB,CACtB,GAAG;IACF,QAAQ,EAAE,SAAS,CAAC;IACpB,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,EACnC,QAAQ,EACR,qBAA4B,EAC5B,GAAG,OAAO,EACX,EAAE,yBAAyB,GAAG,KAAK,CAAC,YAAY,CA8BhD;AAED,wBAAgB,sBAAsB,IAAI,YAAY,CAQrD;AAED,YAAY,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext, useEffect, useMemo, } from 'react';
|
|
3
|
+
import { createNxtlinqAgentWeb, } from '../createNxtlinqAgent';
|
|
4
|
+
const NxtlinqAgentContext = createContext(null);
|
|
5
|
+
export function NxtlinqAgentProvider({ children, resetOnIdentityChange = true, ...options }) {
|
|
6
|
+
const agent = useMemo(() => createNxtlinqAgentWeb(options), [
|
|
7
|
+
options.serviceId,
|
|
8
|
+
options.apiKey,
|
|
9
|
+
options.apiSecret,
|
|
10
|
+
options.environment,
|
|
11
|
+
options.pseudoId,
|
|
12
|
+
options.externalId,
|
|
13
|
+
options.conversationId,
|
|
14
|
+
options.storage,
|
|
15
|
+
options.fetchImpl,
|
|
16
|
+
options.getTimezone,
|
|
17
|
+
options.webrtc,
|
|
18
|
+
]);
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (!resetOnIdentityChange)
|
|
21
|
+
return;
|
|
22
|
+
agent.setMessages([]);
|
|
23
|
+
}, [agent, resetOnIdentityChange, options.pseudoId, options.externalId, options.conversationId]);
|
|
24
|
+
useEffect(() => () => agent.destroy(), [agent]);
|
|
25
|
+
return (_jsx(NxtlinqAgentContext.Provider, { value: agent, children: children }));
|
|
26
|
+
}
|
|
27
|
+
export function useNxtlinqAgentContext() {
|
|
28
|
+
const agent = useContext(NxtlinqAgentContext);
|
|
29
|
+
if (!agent) {
|
|
30
|
+
throw new Error('useNxtlinqAgentContext must be used within <NxtlinqAgentProvider>');
|
|
31
|
+
}
|
|
32
|
+
return agent;
|
|
33
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { NxtlinqAgent, type AgentConfig } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
2
|
+
import { type CreateWebPlatformPortsOptions } from './ports/createWebPlatformPorts';
|
|
3
|
+
export type CreateNxtlinqAgentWebOptions = AgentConfig & CreateWebPlatformPortsOptions;
|
|
4
|
+
/**
|
|
5
|
+
* Create a platform-ready {@link NxtlinqAgent} for React Web custom UIs.
|
|
6
|
+
* Applies browser defaults (`voiceTransport: webrtc`, `defaultModel`).
|
|
7
|
+
*/
|
|
8
|
+
export declare function createNxtlinqAgentWeb(options: CreateNxtlinqAgentWebOptions): NxtlinqAgent;
|
|
9
|
+
//# sourceMappingURL=createNxtlinqAgent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createNxtlinqAgent.d.ts","sourceRoot":"","sources":["../src/createNxtlinqAgent.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,KAAK,WAAW,EAEjB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EAEL,KAAK,6BAA6B,EACnC,MAAM,gCAAgC,CAAC;AAGxC,MAAM,MAAM,4BAA4B,GAAG,WAAW,GAAG,6BAA6B,CAAC;AAEvF;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,GAAG,YAAY,CAkBzF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { NxtlinqAgent, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
2
|
+
import { createWebPlatformPorts, } from './ports/createWebPlatformPorts';
|
|
3
|
+
import { applyWebAgentDefaults } from './webAgentDefaults';
|
|
4
|
+
/**
|
|
5
|
+
* Create a platform-ready {@link NxtlinqAgent} for React Web custom UIs.
|
|
6
|
+
* Applies browser defaults (`voiceTransport: webrtc`, `defaultModel`).
|
|
7
|
+
*/
|
|
8
|
+
export function createNxtlinqAgentWeb(options) {
|
|
9
|
+
const { storage, fetchImpl, getTimezone, webrtc, enableWebRTC, ...rawConfig } = options;
|
|
10
|
+
const config = applyWebAgentDefaults(rawConfig);
|
|
11
|
+
const ports = createWebPlatformPorts({
|
|
12
|
+
storage,
|
|
13
|
+
fetchImpl,
|
|
14
|
+
getTimezone,
|
|
15
|
+
webrtc,
|
|
16
|
+
enableWebRTC,
|
|
17
|
+
});
|
|
18
|
+
return new NxtlinqAgent(config, ports);
|
|
19
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Message, NxtlinqAgentSnapshot, PostTextTtsResult, SendMessageOptions } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
2
|
+
import { useNxtlinqAgentContext } from '../context/NxtlinqAgentContext';
|
|
3
|
+
export type UseNxtlinqAgentResult = NxtlinqAgentSnapshot & {
|
|
4
|
+
agent: ReturnType<typeof useNxtlinqAgentContext>;
|
|
5
|
+
sendMessage: (text: string, options?: Omit<SendMessageOptions, 'text'>) => Promise<void>;
|
|
6
|
+
loadHistory: (options?: {
|
|
7
|
+
last?: number;
|
|
8
|
+
}) => Promise<void>;
|
|
9
|
+
syncVoiceTurnHistory: (options?: {
|
|
10
|
+
last?: number;
|
|
11
|
+
}) => Promise<void>;
|
|
12
|
+
setMessages: (messages: Message[]) => void;
|
|
13
|
+
postTextTts: (text: string) => Promise<PostTextTtsResult>;
|
|
14
|
+
buildTextTtsPlaybackUri: (result: PostTextTtsResult) => string;
|
|
15
|
+
};
|
|
16
|
+
/** Subscribe to {@link NxtlinqAgent} state for custom Web chat UIs. */
|
|
17
|
+
export declare function useNxtlinqAgent(): UseNxtlinqAgentResult;
|
|
18
|
+
//# sourceMappingURL=useNxtlinqAgent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useNxtlinqAgent.d.ts","sourceRoot":"","sources":["../../src/hooks/useNxtlinqAgent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,8CAA8C,CAAC;AAEtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAExE,MAAM,MAAM,qBAAqB,GAAG,oBAAoB,GAAG;IACzD,KAAK,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC;IACjD,WAAW,EAAE,CACX,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC,KACvC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,WAAW,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,oBAAoB,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,WAAW,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAC3C,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC1D,uBAAuB,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,MAAM,CAAC;CAChE,CAAC;AAEF,uEAAuE;AACvE,wBAAgB,eAAe,IAAI,qBAAqB,CAiDvD"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useCallback, useSyncExternalStore } from 'react';
|
|
2
|
+
import { useNxtlinqAgentContext } from '../context/NxtlinqAgentContext';
|
|
3
|
+
/** Subscribe to {@link NxtlinqAgent} state for custom Web chat UIs. */
|
|
4
|
+
export function useNxtlinqAgent() {
|
|
5
|
+
const agent = useNxtlinqAgentContext();
|
|
6
|
+
const snapshot = useSyncExternalStore((onStoreChange) => agent.subscribe(onStoreChange), () => agent.getSnapshot(), () => agent.getSnapshot());
|
|
7
|
+
const sendMessage = useCallback((text, options) => agent.sendMessage(text, options), [agent]);
|
|
8
|
+
const loadHistory = useCallback((options) => agent.loadHistory(options), [agent]);
|
|
9
|
+
const syncVoiceTurnHistory = useCallback((options) => agent.syncVoiceTurnHistory(options), [agent]);
|
|
10
|
+
const setMessages = useCallback((messages) => agent.setMessages(messages), [agent]);
|
|
11
|
+
const postTextTts = useCallback((text) => agent.postTextTts(text), [agent]);
|
|
12
|
+
const buildTextTtsPlaybackUri = useCallback((result) => agent.buildTextTtsPlaybackUri(result), [agent]);
|
|
13
|
+
return {
|
|
14
|
+
agent,
|
|
15
|
+
...snapshot,
|
|
16
|
+
sendMessage,
|
|
17
|
+
loadHistory,
|
|
18
|
+
syncVoiceTurnHistory,
|
|
19
|
+
setMessages,
|
|
20
|
+
postTextTts,
|
|
21
|
+
buildTextTtsPlaybackUri,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { StartVoiceSessionOptions, VoiceGreetingOptions, VoiceSession, VoiceStatus, VoiceUserInputOptions } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
2
|
+
export type UseNxtlinqVoiceOptions = Partial<Omit<StartVoiceSessionOptions, 'apiKey' | 'apiSecret' | 'pseudoId'>>;
|
|
3
|
+
export type UseNxtlinqVoiceResult = {
|
|
4
|
+
voiceStatus: VoiceStatus;
|
|
5
|
+
voiceSessionId: string | null;
|
|
6
|
+
isVoiceActive: boolean;
|
|
7
|
+
startVoice: (options?: UseNxtlinqVoiceOptions) => Promise<VoiceSession>;
|
|
8
|
+
stopVoice: (reason?: string) => Promise<void>;
|
|
9
|
+
muteMic: (muted: boolean) => void;
|
|
10
|
+
interrupt: () => void;
|
|
11
|
+
getRemoteAudioStream: () => MediaStream | null;
|
|
12
|
+
getOutputAudioLevel: () => number;
|
|
13
|
+
sendVoiceUserInput: (options: VoiceUserInputOptions) => void;
|
|
14
|
+
triggerVoiceGreeting: (options: VoiceGreetingOptions, greetOptions?: {
|
|
15
|
+
waitForChannel?: boolean;
|
|
16
|
+
timeoutMs?: number;
|
|
17
|
+
}) => Promise<void>;
|
|
18
|
+
};
|
|
19
|
+
/** Voice controls for custom Web UIs (browser WebRTC). */
|
|
20
|
+
export declare function useNxtlinqVoice(): UseNxtlinqVoiceResult;
|
|
21
|
+
//# sourceMappingURL=useNxtlinqVoice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useNxtlinqVoice.d.ts","sourceRoot":"","sources":["../../src/hooks/useNxtlinqVoice.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EACxB,oBAAoB,EACpB,YAAY,EACZ,WAAW,EACX,qBAAqB,EACtB,MAAM,8CAA8C,CAAC;AAKtD,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAC1C,IAAI,CAAC,wBAAwB,EAAE,QAAQ,GAAG,WAAW,GAAG,UAAU,CAAC,CACpE,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,CAAC,OAAO,CAAC,EAAE,sBAAsB,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IACxE,SAAS,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAClC,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,oBAAoB,EAAE,MAAM,WAAW,GAAG,IAAI,CAAC;IAC/C,mBAAmB,EAAE,MAAM,MAAM,CAAC;IAClC,kBAAkB,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAC7D,oBAAoB,EAAE,CACpB,OAAO,EAAE,oBAAoB,EAC7B,YAAY,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAC5D,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,CAAC;AAEF,0DAA0D;AAC1D,wBAAgB,eAAe,IAAI,qBAAqB,CA6GvD"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { VoiceNotSupportedError } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
2
|
+
import { useCallback, useMemo, useRef, useSyncExternalStore } from 'react';
|
|
3
|
+
import { useNxtlinqAgentContext } from '../context/NxtlinqAgentContext';
|
|
4
|
+
/** Voice controls for custom Web UIs (browser WebRTC). */
|
|
5
|
+
export function useNxtlinqVoice() {
|
|
6
|
+
const agent = useNxtlinqAgentContext();
|
|
7
|
+
const sessionRef = useRef(null);
|
|
8
|
+
const snapshot = useSyncExternalStore((onStoreChange) => agent.subscribe(onStoreChange), () => agent.getSnapshot(), () => agent.getSnapshot());
|
|
9
|
+
const refreshSessionRef = useCallback(() => {
|
|
10
|
+
sessionRef.current = agent.getVoiceSession();
|
|
11
|
+
}, [agent]);
|
|
12
|
+
const startVoice = useCallback(async (options) => {
|
|
13
|
+
try {
|
|
14
|
+
const session = await agent.startVoice(options);
|
|
15
|
+
sessionRef.current = session;
|
|
16
|
+
return session;
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
if (err instanceof VoiceNotSupportedError) {
|
|
20
|
+
throw new Error('Voice is not available — check NxtlinqAgentProvider config and pseudoId.');
|
|
21
|
+
}
|
|
22
|
+
throw err;
|
|
23
|
+
}
|
|
24
|
+
}, [agent]);
|
|
25
|
+
const stopVoice = useCallback(async (reason) => {
|
|
26
|
+
await agent.stopVoice(reason);
|
|
27
|
+
sessionRef.current = null;
|
|
28
|
+
}, [agent]);
|
|
29
|
+
const muteMic = useCallback((muted) => {
|
|
30
|
+
refreshSessionRef();
|
|
31
|
+
sessionRef.current?.muteMic(muted);
|
|
32
|
+
}, [refreshSessionRef]);
|
|
33
|
+
const interrupt = useCallback(() => {
|
|
34
|
+
refreshSessionRef();
|
|
35
|
+
sessionRef.current?.interrupt();
|
|
36
|
+
}, [refreshSessionRef]);
|
|
37
|
+
const getRemoteAudioStream = useCallback(() => agent.getVoiceSession()?.getRemoteAudioStream() ?? null, [agent]);
|
|
38
|
+
const getOutputAudioLevel = useCallback(() => {
|
|
39
|
+
refreshSessionRef();
|
|
40
|
+
return sessionRef.current?.getOutputAudioLevel() ?? agent.getOutputAudioLevel();
|
|
41
|
+
}, [refreshSessionRef, agent]);
|
|
42
|
+
const sendVoiceUserInput = useCallback((options) => {
|
|
43
|
+
refreshSessionRef();
|
|
44
|
+
if (sessionRef.current) {
|
|
45
|
+
sessionRef.current.sendVoiceUserInput(options);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
agent.sendVoiceUserInput(options);
|
|
49
|
+
}, [refreshSessionRef, agent]);
|
|
50
|
+
const triggerVoiceGreeting = useCallback((options, greetOptions) => agent.triggerVoiceGreeting(options, greetOptions), [agent]);
|
|
51
|
+
return useMemo(() => ({
|
|
52
|
+
voiceStatus: snapshot.voiceStatus,
|
|
53
|
+
voiceSessionId: snapshot.voiceSessionId,
|
|
54
|
+
isVoiceActive: snapshot.voiceSessionId != null,
|
|
55
|
+
startVoice,
|
|
56
|
+
stopVoice,
|
|
57
|
+
muteMic,
|
|
58
|
+
interrupt,
|
|
59
|
+
getRemoteAudioStream,
|
|
60
|
+
getOutputAudioLevel,
|
|
61
|
+
sendVoiceUserInput,
|
|
62
|
+
triggerVoiceGreeting,
|
|
63
|
+
}), [
|
|
64
|
+
snapshot.voiceStatus,
|
|
65
|
+
snapshot.voiceSessionId,
|
|
66
|
+
startVoice,
|
|
67
|
+
stopVoice,
|
|
68
|
+
muteMic,
|
|
69
|
+
interrupt,
|
|
70
|
+
getRemoteAudioStream,
|
|
71
|
+
getOutputAudioLevel,
|
|
72
|
+
sendVoiceUserInput,
|
|
73
|
+
triggerVoiceGreeting,
|
|
74
|
+
]);
|
|
75
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { createNxtlinqAgentWeb, type CreateNxtlinqAgentWebOptions, } from './createNxtlinqAgent';
|
|
2
|
+
export { NxtlinqAgentProvider, useNxtlinqAgentContext, type NxtlinqAgentProviderProps, type AgentConfig, } from './context/NxtlinqAgentContext';
|
|
3
|
+
export { useNxtlinqAgent, type UseNxtlinqAgentResult } from './hooks/useNxtlinqAgent';
|
|
4
|
+
export { useNxtlinqVoice, type UseNxtlinqVoiceResult, type UseNxtlinqVoiceOptions, } from './hooks/useNxtlinqVoice';
|
|
5
|
+
export { createWebPlatformPorts, type CreateWebPlatformPortsOptions, } from './ports/createWebPlatformPorts';
|
|
6
|
+
export { WEB_AGENT_DEFAULTS, applyWebAgentDefaults } from './webAgentDefaults';
|
|
7
|
+
export { fileToAttachment } from './utils/fileToAttachment';
|
|
8
|
+
export type { Message, Attachment, AgentResponse, SendMessageOptions, NxtlinqAgentSnapshot, ToolUse, StartVoiceSessionOptions, VoiceSession, VoiceStatus, VoiceTranscriptEvent, VoiceDoneEvent, VoiceUserInputOptions, VoiceGreetingOptions, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
9
|
+
export { NxtlinqAgent, setApiHosts, createBrowserWebRTCPort, createBrowserStoragePort, createDefaultHttpPort, VoiceNotSupportedError, mapServerHistoryToMessages, appendServerHistoryIntoMessages, STORAGE_KEYS, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
10
|
+
export { createNxtlinqApi, getAiAgentApiHost, startVoiceSession, createVoiceApi, useDraggable, useLocalStorage, useSessionStorage, useResizable, synthesizeSpeechToBuffer, useSpeechToTextFromMic, useVoiceMode, metakeepClient, getEthers, sleep, walletTextUtils, connectWallet, disconnectWallet, validateToken, createAITMetadata, generateAITId, prepareAITCreation, createNotification, getNotificationIcon, containsUrls, convertUrlsToLinks, convertUrlsToHtml, } from './legacy';
|
|
11
|
+
export type { ResizeCorner } from './legacy';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,KAAK,4BAA4B,GAClC,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,WAAW,GACjB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAAE,eAAe,EAAE,KAAK,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACtF,OAAO,EACL,eAAe,EACf,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,GAC5B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,sBAAsB,EACtB,KAAK,6BAA6B,GACnC,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,YAAY,EACV,OAAO,EACP,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,oBAAoB,EACpB,OAAO,EACP,wBAAwB,EACxB,YAAY,EACZ,WAAW,EACX,oBAAoB,EACpB,cAAc,EACd,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,8CAA8C,CAAC;AAEtD,OAAO,EACL,YAAY,EACZ,WAAW,EACX,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,EACrB,sBAAsB,EACtB,0BAA0B,EAC1B,+BAA+B,EAC/B,YAAY,GACb,MAAM,8CAA8C,CAAC;AAEtD,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,wBAAwB,EACxB,sBAAsB,EACtB,YAAY,EACZ,cAAc,EACd,SAAS,EACT,KAAK,EACL,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,UAAU,CAAC;AAElB,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { createNxtlinqAgentWeb, } from './createNxtlinqAgent';
|
|
2
|
+
export { NxtlinqAgentProvider, useNxtlinqAgentContext, } from './context/NxtlinqAgentContext';
|
|
3
|
+
export { useNxtlinqAgent } from './hooks/useNxtlinqAgent';
|
|
4
|
+
export { useNxtlinqVoice, } from './hooks/useNxtlinqVoice';
|
|
5
|
+
export { createWebPlatformPorts, } from './ports/createWebPlatformPorts';
|
|
6
|
+
export { WEB_AGENT_DEFAULTS, applyWebAgentDefaults } from './webAgentDefaults';
|
|
7
|
+
export { fileToAttachment } from './utils/fileToAttachment';
|
|
8
|
+
export { NxtlinqAgent, setApiHosts, createBrowserWebRTCPort, createBrowserStoragePort, createDefaultHttpPort, VoiceNotSupportedError, mapServerHistoryToMessages, appendServerHistoryIntoMessages, STORAGE_KEYS, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
9
|
+
export { createNxtlinqApi, getAiAgentApiHost, startVoiceSession, createVoiceApi, useDraggable, useLocalStorage, useSessionStorage, useResizable, synthesizeSpeechToBuffer, useSpeechToTextFromMic, useVoiceMode, metakeepClient, getEthers, sleep, walletTextUtils, connectWallet, disconnectWallet, validateToken, createAITMetadata, generateAITId, prepareAITCreation, createNotification, getNotificationIcon, containsUrls, convertUrlsToLinks, convertUrlsToHtml, } from './legacy';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Web SDK wrapper: default browser storage + voice API from browser module.
|
|
3
|
+
*/
|
|
4
|
+
import type { AITApi } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
5
|
+
export { setApiHosts, getAiAgentApiHost, createNxtlinqApiWithDeps, createBrowserStoragePort, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
6
|
+
export type { CoreAITApi, ApiClientDeps } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
7
|
+
export declare const createNxtlinqApi: (apiKey: string, apiSecret: string) => AITApi;
|
|
8
|
+
//# sourceMappingURL=nxtlinq-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nxtlinq-api.d.ts","sourceRoot":"","sources":["../../../src/legacy/api/nxtlinq-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,8CAA8C,CAAC;AAU3E,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,8CAA8C,CAAC;AAEtD,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,8CAA8C,CAAC;AAE9F,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,EAAE,WAAW,MAAM,KAAG,MASpE,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createBrowserStoragePort, createDefaultHttpPort, createNxtlinqApiWithDeps, getAiAgentApiHost, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
2
|
+
import { createVoiceApi } from './voice';
|
|
3
|
+
export { setApiHosts, getAiAgentApiHost, createNxtlinqApiWithDeps, createBrowserStoragePort, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
4
|
+
export const createNxtlinqApi = (apiKey, apiSecret) => {
|
|
5
|
+
const core = createNxtlinqApiWithDeps(apiKey, apiSecret, {
|
|
6
|
+
storage: createBrowserStoragePort(),
|
|
7
|
+
http: createDefaultHttpPort(),
|
|
8
|
+
});
|
|
9
|
+
return {
|
|
10
|
+
...core,
|
|
11
|
+
voice: createVoiceApi(() => getAiAgentApiHost()),
|
|
12
|
+
};
|
|
13
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { normalizeTranscriptKey, mergeStreamingTranscript, appendTranscriptSegment, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
2
|
+
export type { VoicePhase, VoiceStatus, VoicePhaseExtra, VoiceTranscriptEvent, VoiceToolCallEvent, VoiceToolResultEvent, VoicePermissionRequiredEvent, VoiceBillingBlockedEvent, VoiceTtsWordEvent, VoiceDoneEvent, StartVoiceSessionOptions, VoiceSession, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
3
|
+
import type { StartVoiceSessionOptions, VoiceSession } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
4
|
+
/**
|
|
5
|
+
* Start a cascade voice agent session. Browser-only (uses {@link createBrowserWebRTCPort}).
|
|
6
|
+
*/
|
|
7
|
+
export declare function startVoiceSession(apiAgentHost: string, options: StartVoiceSessionOptions): Promise<VoiceSession>;
|
|
8
|
+
export declare const createVoiceApi: (apiAgentHost: string | (() => string)) => {
|
|
9
|
+
startSession: (options: StartVoiceSessionOptions) => Promise<VoiceSession>;
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=voice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voice.d.ts","sourceRoot":"","sources":["../../../src/legacy/api/voice.ts"],"names":[],"mappings":"AASA,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,8CAA8C,CAAC;AAEtD,YAAY,EACV,UAAU,EACV,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,EACpB,4BAA4B,EAC5B,wBAAwB,EACxB,iBAAiB,EACjB,cAAc,EACd,wBAAwB,EACxB,YAAY,GACb,MAAM,8CAA8C,CAAC;AAEtD,OAAO,KAAK,EAAE,wBAAwB,EAAE,YAAY,EAAE,MAAM,8CAA8C,CAAC;AAE3G;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,YAAY,CAAC,CAyBvB;AAED,eAAO,MAAM,cAAc,GAAI,cAAc,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC;4BAC1C,wBAAwB,KAAG,OAAO,CAAC,YAAY,CAAC;CAKxE,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Web voice client — thin wrapper over core {@link startVoiceSessionWithPort}.
|
|
3
|
+
*/
|
|
4
|
+
import { createBrowserWebRTCPort, startVoiceSessionWithPort, startWsRealtimeSession, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
5
|
+
export { normalizeTranscriptKey, mergeStreamingTranscript, appendTranscriptSegment, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
6
|
+
/**
|
|
7
|
+
* Start a cascade voice agent session. Browser-only (uses {@link createBrowserWebRTCPort}).
|
|
8
|
+
*/
|
|
9
|
+
export async function startVoiceSession(apiAgentHost, options) {
|
|
10
|
+
const baseUrl = (options.baseUrl ?? apiAgentHost ?? '').replace(/\/+$/, '');
|
|
11
|
+
if (!baseUrl) {
|
|
12
|
+
throw new Error('startVoiceSession: API host is empty. Did you forget to call setApiHosts() before createNxtlinqApi()?');
|
|
13
|
+
}
|
|
14
|
+
const transport = options.transport ?? 'ws-realtime';
|
|
15
|
+
if (transport === 'ws-realtime') {
|
|
16
|
+
return startWsRealtimeSession({ baseUrl, fetchFn: fetch }, { ...options, baseUrl, transport });
|
|
17
|
+
}
|
|
18
|
+
return startVoiceSessionWithPort({
|
|
19
|
+
baseUrl,
|
|
20
|
+
webrtc: createBrowserWebRTCPort(),
|
|
21
|
+
fetchFn: fetch,
|
|
22
|
+
}, { ...options, baseUrl });
|
|
23
|
+
}
|
|
24
|
+
export const createVoiceApi = (apiAgentHost) => ({
|
|
25
|
+
startSession: (options) => startVoiceSession(typeof apiAgentHost === 'function' ? apiAgentHost() : apiAgentHost, options),
|
|
26
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messageHistory.d.ts","sourceRoot":"","sources":["../../../../src/legacy/core/lib/messageHistory.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,+BAA+B,EAC/B,yBAAyB,EACzB,0BAA0B,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,8CAA8C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { appendServerHistoryIntoMessages, isVoicePlaceholderMessage, mapServerHistoryToMessages, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ClientTtsVoiceSettings } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
2
|
+
/**
|
|
3
|
+
* TTS for chat playback: Azure (browser Speech SDK + token from Agent) or OpenAI (audio via Agent proxy).
|
|
4
|
+
*/
|
|
5
|
+
export declare function synthesizeSpeechToBuffer(params: {
|
|
6
|
+
text: string;
|
|
7
|
+
apiKey: string;
|
|
8
|
+
apiSecret: string;
|
|
9
|
+
settings?: ClientTtsVoiceSettings;
|
|
10
|
+
}): Promise<{
|
|
11
|
+
buffer: ArrayBuffer;
|
|
12
|
+
mimeType: string;
|
|
13
|
+
} | undefined>;
|
|
14
|
+
//# sourceMappingURL=textToSpeech.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textToSpeech.d.ts","sourceRoot":"","sources":["../../../../src/legacy/core/lib/textToSpeech.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8CAA8C,CAAC;AA8E3F;;GAEG;AACH,wBAAsB,wBAAwB,CAAC,MAAM,EAAE;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,sBAAsB,CAAC;CACnC,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC,CAsCjE"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { SpeechConfig, SpeechSynthesizer } from 'microsoft-cognitiveservices-speech-sdk';
|
|
2
|
+
import { getAiAgentApiHost } from '../../api/nxtlinq-api';
|
|
3
|
+
const DEFAULT_AZURE_VOICE = 'en-US-JennyNeural';
|
|
4
|
+
async function fetchAzureTokenFromAgent(agentHost, apiKey, apiSecret) {
|
|
5
|
+
try {
|
|
6
|
+
const res = await fetch(`${agentHost}/api/cognitive/token`, {
|
|
7
|
+
method: 'GET',
|
|
8
|
+
headers: {
|
|
9
|
+
'X-API-Key': apiKey,
|
|
10
|
+
'X-API-Secret': apiSecret,
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
const data = (await res.json());
|
|
14
|
+
if (!res.ok || !data.token || !data.region) {
|
|
15
|
+
return { error: data.error || 'Failed to get speech token' };
|
|
16
|
+
}
|
|
17
|
+
return { token: data.token, region: data.region };
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
return { error: e instanceof Error ? e.message : 'Network error' };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async function synthesizeAzureToBuffer(text, authToken, region, voiceName) {
|
|
24
|
+
const speechConfig = SpeechConfig.fromAuthorizationToken(authToken, region);
|
|
25
|
+
speechConfig.speechSynthesisVoiceName =
|
|
26
|
+
voiceName?.trim() ? voiceName.trim() : DEFAULT_AZURE_VOICE;
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
28
|
+
// @ts-ignore — SDK typing allows null audio config
|
|
29
|
+
const synthesizer = new SpeechSynthesizer(speechConfig, null);
|
|
30
|
+
const res = await new Promise((resolve) => {
|
|
31
|
+
synthesizer.speakTextAsync(text, (result) => {
|
|
32
|
+
resolve(result);
|
|
33
|
+
}, (err) => resolve(err));
|
|
34
|
+
});
|
|
35
|
+
synthesizer.close();
|
|
36
|
+
if (typeof res === 'string') {
|
|
37
|
+
console.error('Text-to-speech error:', res);
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
return res.audioData;
|
|
41
|
+
}
|
|
42
|
+
async function synthesizeOpenAiToBuffer(agentHost, apiKey, apiSecret, text) {
|
|
43
|
+
const res = await fetch(`${agentHost}/api/tts/openai`, {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
headers: { 'Content-Type': 'application/json' },
|
|
46
|
+
body: JSON.stringify({ apiKey, apiSecret, text }),
|
|
47
|
+
});
|
|
48
|
+
if (!res.ok) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
return res.arrayBuffer();
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* TTS for chat playback: Azure (browser Speech SDK + token from Agent) or OpenAI (audio via Agent proxy).
|
|
55
|
+
*/
|
|
56
|
+
export async function synthesizeSpeechToBuffer(params) {
|
|
57
|
+
const agentHost = getAiAgentApiHost();
|
|
58
|
+
if (!agentHost) {
|
|
59
|
+
console.error('AI Agent API host is not set (call setApiHosts first)');
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
const provider = params.settings?.provider ?? 'azure';
|
|
63
|
+
const resolvedVoice = params.settings?.resolvedVoice?.trim();
|
|
64
|
+
if (provider === 'openai' && resolvedVoice) {
|
|
65
|
+
const buffer = await synthesizeOpenAiToBuffer(agentHost, params.apiKey, params.apiSecret, params.text);
|
|
66
|
+
if (!buffer) {
|
|
67
|
+
console.warn('OpenAI TTS failed, falling back to Azure');
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
return { buffer, mimeType: 'audio/mpeg' };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const tok = await fetchAzureTokenFromAgent(agentHost, params.apiKey, params.apiSecret);
|
|
74
|
+
if ('error' in tok) {
|
|
75
|
+
console.error('Azure speech token:', tok.error);
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
const buffer = await synthesizeAzureToBuffer(params.text, tok.token, tok.region, provider === 'azure' ? resolvedVoice : undefined);
|
|
79
|
+
if (!buffer)
|
|
80
|
+
return undefined;
|
|
81
|
+
return { buffer, mimeType: 'audio/wav' };
|
|
82
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface Position {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
}
|
|
5
|
+
export declare const useDraggable: (dimensions: {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}) => {
|
|
9
|
+
position: Position;
|
|
10
|
+
handleDragStart: (event: React.PointerEvent<HTMLDivElement>) => void;
|
|
11
|
+
isDragging: boolean;
|
|
12
|
+
updatePosition: (newPosition: Position) => void;
|
|
13
|
+
};
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=useDraggable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDraggable.d.ts","sourceRoot":"","sources":["../../../../src/legacy/core/lib/useDraggable.ts"],"names":[],"mappings":"AAGA,UAAU,QAAQ;IAChB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAKD,eAAO,MAAM,YAAY,GAAI,YAAY;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;;6BAuFxC,KAAK,CAAC,YAAY,CAAC,cAAc,CAAC;;kCA8EjB,QAAQ;CAgB1D,CAAC"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { useState, useRef, useCallback, useEffect } from 'react';
|
|
2
|
+
import useLocalStorage from './useLocalStorage';
|
|
3
|
+
const DEFAULT_POSITION = { x: 0, y: 0 }; // Default position, will be calculated
|
|
4
|
+
const VIEWPORT_MARGIN = 20; // Keep space from viewport edges
|
|
5
|
+
export const useDraggable = (dimensions) => {
|
|
6
|
+
const dragState = useRef({
|
|
7
|
+
startX: 0,
|
|
8
|
+
startY: 0,
|
|
9
|
+
startPosition: DEFAULT_POSITION
|
|
10
|
+
});
|
|
11
|
+
// Keep track of current position for saving
|
|
12
|
+
const currentPositionRef = useRef(DEFAULT_POSITION);
|
|
13
|
+
// Track if we've already loaded from localStorage to prevent loops
|
|
14
|
+
const hasLoadedFromStorage = useRef(false);
|
|
15
|
+
// Clamp position to keep window within viewport
|
|
16
|
+
const clampPosition = useCallback((pos, dims) => {
|
|
17
|
+
if (typeof window === 'undefined') {
|
|
18
|
+
return pos;
|
|
19
|
+
}
|
|
20
|
+
const maxX = Math.max(VIEWPORT_MARGIN, window.innerWidth - dims.width - VIEWPORT_MARGIN);
|
|
21
|
+
const maxY = Math.max(VIEWPORT_MARGIN, window.innerHeight - dims.height - VIEWPORT_MARGIN);
|
|
22
|
+
return {
|
|
23
|
+
x: Math.max(VIEWPORT_MARGIN, Math.min(pos.x, maxX)),
|
|
24
|
+
y: Math.max(VIEWPORT_MARGIN, Math.min(pos.y, maxY))
|
|
25
|
+
};
|
|
26
|
+
}, []);
|
|
27
|
+
// Calculate initial position from bottom/right (default behavior)
|
|
28
|
+
const calculateInitialPosition = useCallback(() => {
|
|
29
|
+
if (typeof window === 'undefined') {
|
|
30
|
+
return DEFAULT_POSITION;
|
|
31
|
+
}
|
|
32
|
+
// Default position: bottom-right corner with margin
|
|
33
|
+
const initialPos = {
|
|
34
|
+
x: window.innerWidth - dimensions.width - VIEWPORT_MARGIN,
|
|
35
|
+
y: window.innerHeight - dimensions.height - VIEWPORT_MARGIN
|
|
36
|
+
};
|
|
37
|
+
return clampPosition(initialPos, dimensions);
|
|
38
|
+
}, [dimensions.width, dimensions.height, clampPosition]);
|
|
39
|
+
// Load position from localStorage or use default
|
|
40
|
+
const [savedPosition, setSavedPosition, isPositionInitialized] = useLocalStorage('chat-window-position', null);
|
|
41
|
+
const [position, setPosition] = useState(() => {
|
|
42
|
+
// Always start with calculated initial position
|
|
43
|
+
// Will be updated when savedPosition loads from localStorage
|
|
44
|
+
const initialPos = calculateInitialPosition();
|
|
45
|
+
currentPositionRef.current = initialPos;
|
|
46
|
+
return initialPos;
|
|
47
|
+
});
|
|
48
|
+
// Update position when saved position loads from localStorage (only once)
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
if (isPositionInitialized && !hasLoadedFromStorage.current) {
|
|
51
|
+
if (savedPosition) {
|
|
52
|
+
// Use saved position
|
|
53
|
+
const clampedPos = clampPosition(savedPosition, dimensions);
|
|
54
|
+
currentPositionRef.current = clampedPos;
|
|
55
|
+
setPosition(clampedPos);
|
|
56
|
+
}
|
|
57
|
+
// Mark as loaded regardless of whether we have saved position
|
|
58
|
+
hasLoadedFromStorage.current = true;
|
|
59
|
+
}
|
|
60
|
+
}, [isPositionInitialized, savedPosition, dimensions, clampPosition]);
|
|
61
|
+
// Update position when dimensions change (to keep window in viewport, but only after initial load)
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
if (!isPositionInitialized || !hasLoadedFromStorage.current)
|
|
64
|
+
return;
|
|
65
|
+
setPosition((current) => {
|
|
66
|
+
const clampedPosition = clampPosition(current, dimensions);
|
|
67
|
+
if (clampedPosition.x !== current.x || clampedPosition.y !== current.y) {
|
|
68
|
+
currentPositionRef.current = clampedPosition;
|
|
69
|
+
return clampedPosition;
|
|
70
|
+
}
|
|
71
|
+
return current;
|
|
72
|
+
});
|
|
73
|
+
}, [dimensions.width, dimensions.height, isPositionInitialized, clampPosition]);
|
|
74
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
75
|
+
const handleDragStart = (event) => {
|
|
76
|
+
// Don't start dragging if clicking on buttons or interactive elements
|
|
77
|
+
const target = event.target;
|
|
78
|
+
if (target.tagName === 'BUTTON' ||
|
|
79
|
+
target.closest('button') ||
|
|
80
|
+
target.closest('[role="button"]') ||
|
|
81
|
+
target.closest('input') ||
|
|
82
|
+
target.closest('select') ||
|
|
83
|
+
target.closest('textarea')) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
event.preventDefault();
|
|
87
|
+
event.stopPropagation();
|
|
88
|
+
dragState.current = {
|
|
89
|
+
startX: event.clientX,
|
|
90
|
+
startY: event.clientY,
|
|
91
|
+
startPosition: position
|
|
92
|
+
};
|
|
93
|
+
setIsDragging(true);
|
|
94
|
+
document.body.style.userSelect = 'none';
|
|
95
|
+
document.body.style.cursor = 'grabbing';
|
|
96
|
+
};
|
|
97
|
+
// Handle pointer move and up events
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
if (!isDragging) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const handlePointerMove = (event) => {
|
|
103
|
+
const deltaX = event.clientX - dragState.current.startX;
|
|
104
|
+
const deltaY = event.clientY - dragState.current.startY;
|
|
105
|
+
const newPosition = {
|
|
106
|
+
x: dragState.current.startPosition.x + deltaX,
|
|
107
|
+
y: dragState.current.startPosition.y + deltaY
|
|
108
|
+
};
|
|
109
|
+
const clampedPos = clampPosition(newPosition, dimensions);
|
|
110
|
+
currentPositionRef.current = clampedPos;
|
|
111
|
+
setPosition(clampedPos);
|
|
112
|
+
};
|
|
113
|
+
const handlePointerUp = () => {
|
|
114
|
+
setIsDragging(false);
|
|
115
|
+
document.body.style.userSelect = '';
|
|
116
|
+
document.body.style.cursor = '';
|
|
117
|
+
// Save position to localStorage (only after initial load)
|
|
118
|
+
if (hasLoadedFromStorage.current) {
|
|
119
|
+
setSavedPosition(currentPositionRef.current);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
document.addEventListener('pointermove', handlePointerMove);
|
|
123
|
+
document.addEventListener('pointerup', handlePointerUp);
|
|
124
|
+
return () => {
|
|
125
|
+
document.removeEventListener('pointermove', handlePointerMove);
|
|
126
|
+
document.removeEventListener('pointerup', handlePointerUp);
|
|
127
|
+
document.body.style.userSelect = '';
|
|
128
|
+
document.body.style.cursor = '';
|
|
129
|
+
};
|
|
130
|
+
}, [isDragging, clampPosition, dimensions, setSavedPosition]);
|
|
131
|
+
// Handle window resize to keep window in viewport
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
const handleResize = () => {
|
|
134
|
+
setPosition((current) => {
|
|
135
|
+
const clamped = clampPosition(current, dimensions);
|
|
136
|
+
currentPositionRef.current = clamped;
|
|
137
|
+
return clamped;
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
window.addEventListener('resize', handleResize);
|
|
141
|
+
return () => window.removeEventListener('resize', handleResize);
|
|
142
|
+
}, [clampPosition, dimensions]);
|
|
143
|
+
const updatePosition = useCallback((newPosition) => {
|
|
144
|
+
const clamped = clampPosition(newPosition, dimensions);
|
|
145
|
+
currentPositionRef.current = clamped;
|
|
146
|
+
setPosition(clamped);
|
|
147
|
+
// Save position to localStorage when updated (only after initial load)
|
|
148
|
+
if (hasLoadedFromStorage.current) {
|
|
149
|
+
setSavedPosition(clamped);
|
|
150
|
+
}
|
|
151
|
+
}, [clampPosition, dimensions, setSavedPosition]);
|
|
152
|
+
return {
|
|
153
|
+
position,
|
|
154
|
+
handleDragStart,
|
|
155
|
+
isDragging,
|
|
156
|
+
updatePosition
|
|
157
|
+
};
|
|
158
|
+
};
|