@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.
Files changed (149) hide show
  1. package/dist/context/NxtlinqAgentContext.d.ts +12 -0
  2. package/dist/context/NxtlinqAgentContext.d.ts.map +1 -0
  3. package/dist/context/NxtlinqAgentContext.js +33 -0
  4. package/dist/createNxtlinqAgent.d.ts +9 -0
  5. package/dist/createNxtlinqAgent.d.ts.map +1 -0
  6. package/dist/createNxtlinqAgent.js +19 -0
  7. package/dist/hooks/useNxtlinqAgent.d.ts +18 -0
  8. package/dist/hooks/useNxtlinqAgent.d.ts.map +1 -0
  9. package/dist/hooks/useNxtlinqAgent.js +23 -0
  10. package/dist/hooks/useNxtlinqVoice.d.ts +21 -0
  11. package/dist/hooks/useNxtlinqVoice.d.ts.map +1 -0
  12. package/dist/hooks/useNxtlinqVoice.js +75 -0
  13. package/dist/index.d.ts +12 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +9 -0
  16. package/dist/legacy/api/nxtlinq-api.d.ts +8 -0
  17. package/dist/legacy/api/nxtlinq-api.d.ts.map +1 -0
  18. package/dist/legacy/api/nxtlinq-api.js +13 -0
  19. package/dist/legacy/api/voice.d.ts +11 -0
  20. package/dist/legacy/api/voice.d.ts.map +1 -0
  21. package/dist/legacy/api/voice.js +26 -0
  22. package/dist/legacy/core/lib/messageHistory.d.ts +2 -0
  23. package/dist/legacy/core/lib/messageHistory.d.ts.map +1 -0
  24. package/dist/legacy/core/lib/messageHistory.js +1 -0
  25. package/dist/legacy/core/lib/textToSpeech.d.ts +14 -0
  26. package/dist/legacy/core/lib/textToSpeech.d.ts.map +1 -0
  27. package/dist/legacy/core/lib/textToSpeech.js +82 -0
  28. package/dist/legacy/core/lib/useDraggable.d.ts +15 -0
  29. package/dist/legacy/core/lib/useDraggable.d.ts.map +1 -0
  30. package/dist/legacy/core/lib/useDraggable.js +158 -0
  31. package/dist/legacy/core/lib/useLocalStorage.d.ts +11 -0
  32. package/dist/legacy/core/lib/useLocalStorage.d.ts.map +1 -0
  33. package/dist/legacy/core/lib/useLocalStorage.js +83 -0
  34. package/dist/legacy/core/lib/useResizable.d.ts +17 -0
  35. package/dist/legacy/core/lib/useResizable.d.ts.map +1 -0
  36. package/dist/legacy/core/lib/useResizable.js +203 -0
  37. package/dist/legacy/core/lib/useSessionStorage.d.ts +11 -0
  38. package/dist/legacy/core/lib/useSessionStorage.d.ts.map +1 -0
  39. package/dist/legacy/core/lib/useSessionStorage.js +37 -0
  40. package/dist/legacy/core/lib/useSpeechToTextFromMic/helper.d.ts +26 -0
  41. package/dist/legacy/core/lib/useSpeechToTextFromMic/helper.d.ts.map +1 -0
  42. package/dist/legacy/core/lib/useSpeechToTextFromMic/helper.js +102 -0
  43. package/dist/legacy/core/lib/useSpeechToTextFromMic/index.d.ts +16 -0
  44. package/dist/legacy/core/lib/useSpeechToTextFromMic/index.d.ts.map +1 -0
  45. package/dist/legacy/core/lib/useSpeechToTextFromMic/index.js +92 -0
  46. package/dist/legacy/core/lib/useVoiceMode.d.ts +32 -0
  47. package/dist/legacy/core/lib/useVoiceMode.d.ts.map +1 -0
  48. package/dist/legacy/core/lib/useVoiceMode.js +373 -0
  49. package/dist/legacy/core/metakeepClient.d.ts +4 -0
  50. package/dist/legacy/core/metakeepClient.d.ts.map +1 -0
  51. package/dist/legacy/core/metakeepClient.js +10 -0
  52. package/dist/legacy/core/utils/aitUtils.d.ts +31 -0
  53. package/dist/legacy/core/utils/aitUtils.d.ts.map +1 -0
  54. package/dist/legacy/core/utils/aitUtils.js +35 -0
  55. package/dist/legacy/core/utils/ethersUtils.d.ts +8 -0
  56. package/dist/legacy/core/utils/ethersUtils.d.ts.map +1 -0
  57. package/dist/legacy/core/utils/ethersUtils.js +19 -0
  58. package/dist/legacy/core/utils/index.d.ts +3 -0
  59. package/dist/legacy/core/utils/index.d.ts.map +1 -0
  60. package/dist/legacy/core/utils/index.js +4 -0
  61. package/dist/legacy/core/utils/notificationUtils.d.ts +29 -0
  62. package/dist/legacy/core/utils/notificationUtils.d.ts.map +1 -0
  63. package/dist/legacy/core/utils/notificationUtils.js +47 -0
  64. package/dist/legacy/core/utils/urlUtils.d.ts +25 -0
  65. package/dist/legacy/core/utils/urlUtils.d.ts.map +1 -0
  66. package/dist/legacy/core/utils/urlUtils.js +135 -0
  67. package/dist/legacy/core/utils/walletTextUtils.d.ts +14 -0
  68. package/dist/legacy/core/utils/walletTextUtils.d.ts.map +1 -0
  69. package/dist/legacy/core/utils/walletTextUtils.js +23 -0
  70. package/dist/legacy/core/utils/walletUtils.d.ts +10 -0
  71. package/dist/legacy/core/utils/walletUtils.d.ts.map +1 -0
  72. package/dist/legacy/core/utils/walletUtils.js +38 -0
  73. package/dist/legacy/index.d.ts +19 -0
  74. package/dist/legacy/index.d.ts.map +1 -0
  75. package/dist/legacy/index.js +16 -0
  76. package/dist/ports/createWebPlatformPorts.d.ts +13 -0
  77. package/dist/ports/createWebPlatformPorts.d.ts.map +1 -0
  78. package/dist/ports/createWebPlatformPorts.js +25 -0
  79. package/dist/utils/fileToAttachment.d.ts +4 -0
  80. package/dist/utils/fileToAttachment.d.ts.map +1 -0
  81. package/dist/utils/fileToAttachment.js +28 -0
  82. package/dist/voice/useVoiceSilenceCommit.d.ts +11 -0
  83. package/dist/voice/useVoiceSilenceCommit.d.ts.map +1 -0
  84. package/dist/voice/useVoiceSilenceCommit.js +68 -0
  85. package/dist/voice/useVoiceTranscriptMessages.d.ts +16 -0
  86. package/dist/voice/useVoiceTranscriptMessages.d.ts.map +1 -0
  87. package/dist/voice/useVoiceTranscriptMessages.js +134 -0
  88. package/dist/voice/useWsRealtimeAudio.d.ts +18 -0
  89. package/dist/voice/useWsRealtimeAudio.d.ts.map +1 -0
  90. package/dist/voice/useWsRealtimeAudio.js +115 -0
  91. package/dist/voice/voiceMicConstants.d.ts +4 -0
  92. package/dist/voice/voiceMicConstants.d.ts.map +1 -0
  93. package/dist/voice/voiceMicConstants.js +10 -0
  94. package/dist/voice/ws/BrowserWsPcmPlayer.d.ts +23 -0
  95. package/dist/voice/ws/BrowserWsPcmPlayer.d.ts.map +1 -0
  96. package/dist/voice/ws/BrowserWsPcmPlayer.js +138 -0
  97. package/dist/voice/ws/BrowserWsPcmRecorder.d.ts +19 -0
  98. package/dist/voice/ws/BrowserWsPcmRecorder.d.ts.map +1 -0
  99. package/dist/voice/ws/BrowserWsPcmRecorder.js +76 -0
  100. package/dist/voice/ws/float32ToPcm16.d.ts +2 -0
  101. package/dist/voice/ws/float32ToPcm16.d.ts.map +1 -0
  102. package/dist/voice/ws/float32ToPcm16.js +8 -0
  103. package/dist/voice/ws/voiceSilenceConstants.d.ts +5 -0
  104. package/dist/voice/ws/voiceSilenceConstants.d.ts.map +1 -0
  105. package/dist/voice/ws/voiceSilenceConstants.js +4 -0
  106. package/dist/voice/ws/wsRealtimeConstants.d.ts +2 -0
  107. package/dist/voice/ws/wsRealtimeConstants.d.ts.map +1 -0
  108. package/dist/voice/ws/wsRealtimeConstants.js +1 -0
  109. package/dist/webAgentDefaults.d.ts +9 -0
  110. package/dist/webAgentDefaults.d.ts.map +1 -0
  111. package/dist/webAgentDefaults.js +9 -0
  112. package/package.json +55 -0
  113. package/src/context/NxtlinqAgentContext.tsx +79 -0
  114. package/src/createNxtlinqAgent.ts +36 -0
  115. package/src/hooks/useNxtlinqAgent.ts +73 -0
  116. package/src/hooks/useNxtlinqVoice.ts +143 -0
  117. package/src/index.ts +84 -0
  118. package/src/legacy/api/nxtlinq-api.ts +32 -0
  119. package/src/legacy/api/voice.ts +72 -0
  120. package/src/legacy/core/lib/messageHistory.ts +6 -0
  121. package/src/legacy/core/lib/textToSpeech.ts +127 -0
  122. package/src/legacy/core/lib/useDraggable.ts +193 -0
  123. package/src/legacy/core/lib/useLocalStorage.ts +89 -0
  124. package/src/legacy/core/lib/useResizable.ts +256 -0
  125. package/src/legacy/core/lib/useSessionStorage.ts +43 -0
  126. package/src/legacy/core/lib/useSpeechToTextFromMic/helper.ts +132 -0
  127. package/src/legacy/core/lib/useSpeechToTextFromMic/index.ts +126 -0
  128. package/src/legacy/core/lib/useVoiceMode.ts +407 -0
  129. package/src/legacy/core/metakeepClient.ts +12 -0
  130. package/src/legacy/core/utils/aitUtils.ts +55 -0
  131. package/src/legacy/core/utils/ethersUtils.ts +24 -0
  132. package/src/legacy/core/utils/index.ts +5 -0
  133. package/src/legacy/core/utils/notificationUtils.ts +64 -0
  134. package/src/legacy/core/utils/urlUtils.ts +160 -0
  135. package/src/legacy/core/utils/walletTextUtils.ts +26 -0
  136. package/src/legacy/core/utils/walletUtils.ts +53 -0
  137. package/src/legacy/index.ts +35 -0
  138. package/src/ports/createWebPlatformPorts.ts +44 -0
  139. package/src/utils/fileToAttachment.ts +32 -0
  140. package/src/voice/useVoiceSilenceCommit.ts +84 -0
  141. package/src/voice/useVoiceTranscriptMessages.ts +184 -0
  142. package/src/voice/useWsRealtimeAudio.ts +141 -0
  143. package/src/voice/voiceMicConstants.ts +13 -0
  144. package/src/voice/ws/BrowserWsPcmPlayer.ts +139 -0
  145. package/src/voice/ws/BrowserWsPcmRecorder.ts +83 -0
  146. package/src/voice/ws/float32ToPcm16.ts +8 -0
  147. package/src/voice/ws/voiceSilenceConstants.ts +4 -0
  148. package/src/voice/ws/wsRealtimeConstants.ts +1 -0
  149. package/src/webAgentDefaults.ts +12 -0
@@ -0,0 +1,135 @@
1
+ /**
2
+ * URL utility functions for detecting and converting URLs to clickable links
3
+ */
4
+ import * as React from 'react';
5
+ /**
6
+ * Regular expression to match Markdown-style links
7
+ * Matches [text](url) format
8
+ */
9
+ const MARKDOWN_LINK_REGEX = /\[([^\]]+)\]\(([^)]+)\)/g;
10
+ /**
11
+ * Regular expression to match URLs
12
+ * Supports http, https, ftp, and www protocols
13
+ */
14
+ const URL_REGEX = /(https?:\/\/[^\s]+|www\.[^\s]+|[a-zA-Z0-9-]+\.[a-zA-Z]{2,}(?:\/[^\s]*)?)/g;
15
+ /**
16
+ * Check if a string contains URLs
17
+ * @param text - The text to check
18
+ * @returns boolean indicating if URLs are found
19
+ */
20
+ export const containsUrls = (text) => {
21
+ return URL_REGEX.test(text);
22
+ };
23
+ /**
24
+ * Convert text with line breaks to JSX elements with <br/> tags
25
+ * @param text - The text containing line breaks
26
+ * @param keyPrefix - Prefix for React keys
27
+ * @returns Array of JSX elements and strings
28
+ */
29
+ const convertLineBreaks = (text, keyPrefix = '') => {
30
+ const parts = [];
31
+ const lines = text.split('\n');
32
+ lines.forEach((line, index) => {
33
+ if (index > 0) {
34
+ parts.push(React.createElement('br', { key: `${keyPrefix}-br-${index}` }));
35
+ }
36
+ if (line) {
37
+ parts.push(line);
38
+ }
39
+ });
40
+ return parts;
41
+ };
42
+ /**
43
+ * Convert text with URLs to JSX elements with clickable links
44
+ * Supports both Markdown format [text](url) and plain URLs
45
+ * Also handles line breaks (\n)
46
+ * @param text - The text containing URLs
47
+ * @returns Array of JSX elements and strings
48
+ */
49
+ export const convertUrlsToLinks = (text) => {
50
+ const parts = [];
51
+ let lastIndex = 0;
52
+ let keyCounter = 0;
53
+ // First, find all markdown links and plain URLs
54
+ const items = [];
55
+ // Find markdown links
56
+ let markdownMatch;
57
+ MARKDOWN_LINK_REGEX.lastIndex = 0;
58
+ while ((markdownMatch = MARKDOWN_LINK_REGEX.exec(text)) !== null) {
59
+ items.push({
60
+ type: 'markdown',
61
+ start: markdownMatch.index,
62
+ end: markdownMatch.index + markdownMatch[0].length,
63
+ text: markdownMatch[1],
64
+ url: markdownMatch[2]
65
+ });
66
+ }
67
+ // Find plain URLs (but exclude those already matched as markdown links)
68
+ let urlMatch;
69
+ URL_REGEX.lastIndex = 0;
70
+ while ((urlMatch = URL_REGEX.exec(text)) !== null) {
71
+ const start = urlMatch.index;
72
+ const end = start + urlMatch[0].length;
73
+ // Check if this URL is already part of a markdown link
74
+ const isPartOfMarkdown = items.some(item => item.type === 'markdown' && start >= item.start && end <= item.end);
75
+ if (!isPartOfMarkdown) {
76
+ items.push({
77
+ type: 'url',
78
+ start,
79
+ end,
80
+ url: urlMatch[0]
81
+ });
82
+ }
83
+ }
84
+ // Sort items by start position
85
+ items.sort((a, b) => a.start - b.start);
86
+ // Build the result
87
+ items.forEach(item => {
88
+ // Add text before this item (with line breaks)
89
+ if (item.start > lastIndex) {
90
+ const textBefore = text.slice(lastIndex, item.start);
91
+ const textBeforeParts = convertLineBreaks(textBefore, `text-${keyCounter}`);
92
+ parts.push(...textBeforeParts);
93
+ keyCounter++;
94
+ }
95
+ // Create clickable link
96
+ const href = item.url.startsWith('http') ? item.url : `https://${item.url}`;
97
+ const displayText = item.type === 'markdown' ? item.text : item.url;
98
+ parts.push(React.createElement('a', {
99
+ key: `link-${keyCounter++}`,
100
+ href: href,
101
+ target: '_blank',
102
+ rel: 'noopener noreferrer',
103
+ style: {
104
+ color: '#007bff',
105
+ textDecoration: 'underline',
106
+ cursor: 'pointer'
107
+ },
108
+ className: 'ai-agent-url-link',
109
+ onClick: (e) => {
110
+ e.preventDefault(); // Prevent default browser behavior
111
+ e.stopPropagation();
112
+ window.open(href, '_blank', 'noopener,noreferrer');
113
+ }
114
+ }, displayText));
115
+ lastIndex = item.end;
116
+ });
117
+ // Add remaining text after the last link (with line breaks)
118
+ if (lastIndex < text.length) {
119
+ const textAfter = text.slice(lastIndex);
120
+ const textAfterParts = convertLineBreaks(textAfter, `text-${keyCounter}`);
121
+ parts.push(...textAfterParts);
122
+ }
123
+ return parts.length > 0 ? parts : convertLineBreaks(text, 'default');
124
+ };
125
+ /**
126
+ * Simple function to wrap URLs in anchor tags for basic HTML rendering
127
+ * @param text - The text containing URLs
128
+ * @returns HTML string with clickable links
129
+ */
130
+ export const convertUrlsToHtml = (text) => {
131
+ return text.replace(URL_REGEX, (url) => {
132
+ const href = url.startsWith('http') ? url : `https://${url}`;
133
+ return `<a href="${href}" target="_blank" rel="noopener noreferrer" style="color: #007bff; text-decoration: underline; cursor: pointer;">${url}</a>`;
134
+ });
135
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Adilas Service ID constant
3
+ */
4
+ export declare const ADILAS_SERVICE_ID = "e48fc2b9-a7d1-49e3-85cb-9d621a0bf774";
5
+ /**
6
+ * Check if the given serviceId is the Adilas service
7
+ */
8
+ export declare const isAdilasService: (serviceId: string | undefined | null) => boolean;
9
+ /**
10
+ * Replace "wallet" with "account" in text when serviceId is Adilas service
11
+ * Preserves the original case of the word
12
+ */
13
+ export declare const getWalletText: (defaultText: string, serviceId: string | undefined | null) => string;
14
+ //# sourceMappingURL=walletTextUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walletTextUtils.d.ts","sourceRoot":"","sources":["../../../../src/legacy/core/utils/walletTextUtils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,iBAAiB,yCAAyC,CAAC;AAExE;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,WAAW,MAAM,GAAG,SAAS,GAAG,IAAI,KAAG,OAEtE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,aAAa,MAAM,EAAE,WAAW,MAAM,GAAG,SAAS,GAAG,IAAI,KAAG,MAQzF,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Adilas Service ID constant
3
+ */
4
+ export const ADILAS_SERVICE_ID = 'e48fc2b9-a7d1-49e3-85cb-9d621a0bf774';
5
+ /**
6
+ * Check if the given serviceId is the Adilas service
7
+ */
8
+ export const isAdilasService = (serviceId) => {
9
+ return serviceId ? serviceId.trim() === ADILAS_SERVICE_ID : false;
10
+ };
11
+ /**
12
+ * Replace "wallet" with "account" in text when serviceId is Adilas service
13
+ * Preserves the original case of the word
14
+ */
15
+ export const getWalletText = (defaultText, serviceId) => {
16
+ if (!isAdilasService(serviceId))
17
+ return defaultText;
18
+ // Replace wallet with account, preserving case
19
+ return defaultText.replace(/\bwallet\b/gi, (match) => {
20
+ // Preserve original case: 'Wallet' -> 'Account', 'wallet' -> 'account'
21
+ return match.charAt(0) === 'W' ? 'Account' : 'account';
22
+ });
23
+ };
@@ -0,0 +1,10 @@
1
+ import { ethers } from 'ethers';
2
+ export interface WalletConnectionResult {
3
+ address: string;
4
+ signer: ethers.JsonRpcSigner;
5
+ }
6
+ export declare const connectWallet: () => Promise<WalletConnectionResult>;
7
+ export declare const disconnectWallet: () => void;
8
+ export declare const getStoredWalletAddress: () => string | null;
9
+ export declare const validateToken: (token: string, expectedAddress: string) => boolean;
10
+ //# sourceMappingURL=walletUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walletUtils.d.ts","sourceRoot":"","sources":["../../../../src/legacy/core/utils/walletUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,aAAa,CAAC;CAC9B;AAED,eAAO,MAAM,aAAa,QAAa,OAAO,CAAC,sBAAsB,CAwBpE,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAO,IAEnC,CAAC;AAEF,eAAO,MAAM,sBAAsB,QAAO,MAAM,GAAG,IAElD,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,EAAE,iBAAiB,MAAM,KAAG,OAStE,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { ethers } from 'ethers';
2
+ import metakeepClient from '../metakeepClient';
3
+ import { getEthers } from './ethersUtils';
4
+ export const connectWallet = async () => {
5
+ if (typeof window === 'undefined') {
6
+ throw new Error('Web3 is not available in server-side rendering');
7
+ }
8
+ getEthers();
9
+ const web3Provider = await metakeepClient.ethereum;
10
+ if (!web3Provider) {
11
+ throw new Error('Web3 provider not available');
12
+ }
13
+ await web3Provider.enable();
14
+ // ethers v6: Use BrowserProvider instead of Web3Provider
15
+ const ethersProvider = new ethers.BrowserProvider(web3Provider);
16
+ // ethers v6: getSigner() and getAddress() are now async
17
+ const signer = await ethersProvider.getSigner();
18
+ const address = await signer.getAddress();
19
+ localStorage.setItem('walletAddress', address);
20
+ return { address, signer };
21
+ };
22
+ export const disconnectWallet = () => {
23
+ localStorage.removeItem('walletAddress');
24
+ };
25
+ export const getStoredWalletAddress = () => {
26
+ return localStorage.getItem('walletAddress');
27
+ };
28
+ export const validateToken = (token, expectedAddress) => {
29
+ try {
30
+ const payload = JSON.parse(atob(token.split('.')[1]));
31
+ const address = payload.address;
32
+ return address === expectedAddress;
33
+ }
34
+ catch (error) {
35
+ console.error('Error parsing token:', error);
36
+ return false;
37
+ }
38
+ };
@@ -0,0 +1,19 @@
1
+ export { createNxtlinqApi, setApiHosts, getAiAgentApiHost } from './api/nxtlinq-api';
2
+ export { startVoiceSession, createVoiceApi } from './api/voice';
3
+ export type * from './api/voice';
4
+ export { useDraggable } from './core/lib/useDraggable';
5
+ export { default as useLocalStorage } from './core/lib/useLocalStorage';
6
+ export { default as useSessionStorage } from './core/lib/useSessionStorage';
7
+ export { useResizable } from './core/lib/useResizable';
8
+ export type { ResizeCorner } from './core/lib/useResizable';
9
+ export { synthesizeSpeechToBuffer } from './core/lib/textToSpeech';
10
+ export { useSpeechToTextFromMic } from './core/lib/useSpeechToTextFromMic';
11
+ export { useVoiceMode } from './core/lib/useVoiceMode';
12
+ export { default as metakeepClient } from './core/metakeepClient';
13
+ export { getEthers, sleep } from './core/utils';
14
+ export * as walletTextUtils from './core/utils/walletTextUtils';
15
+ export { connectWallet, disconnectWallet, validateToken, } from './core/utils/walletUtils';
16
+ export { createAITMetadata, generateAITId, prepareAITCreation, } from './core/utils/aitUtils';
17
+ export { createNotification, getNotificationIcon, } from './core/utils/notificationUtils';
18
+ export { containsUrls, convertUrlsToLinks, convertUrlsToHtml, } from './core/utils/urlUtils';
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/legacy/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAChE,mBAAmB,aAAa,CAAC;AAEjC,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,eAAe,MAAM,8BAA8B,CAAC;AAChE,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,aAAa,GACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,16 @@
1
+ export { createNxtlinqApi, setApiHosts, getAiAgentApiHost } from './api/nxtlinq-api';
2
+ export { startVoiceSession, createVoiceApi } from './api/voice';
3
+ export { useDraggable } from './core/lib/useDraggable';
4
+ export { default as useLocalStorage } from './core/lib/useLocalStorage';
5
+ export { default as useSessionStorage } from './core/lib/useSessionStorage';
6
+ export { useResizable } from './core/lib/useResizable';
7
+ export { synthesizeSpeechToBuffer } from './core/lib/textToSpeech';
8
+ export { useSpeechToTextFromMic } from './core/lib/useSpeechToTextFromMic';
9
+ export { useVoiceMode } from './core/lib/useVoiceMode';
10
+ export { default as metakeepClient } from './core/metakeepClient';
11
+ export { getEthers, sleep } from './core/utils';
12
+ export * as walletTextUtils from './core/utils/walletTextUtils';
13
+ export { connectWallet, disconnectWallet, validateToken, } from './core/utils/walletUtils';
14
+ export { createAITMetadata, generateAITId, prepareAITCreation, } from './core/utils/aitUtils';
15
+ export { createNotification, getNotificationIcon, } from './core/utils/notificationUtils';
16
+ export { containsUrls, convertUrlsToLinks, convertUrlsToHtml, } from './core/utils/urlUtils';
@@ -0,0 +1,13 @@
1
+ import type { PlatformPorts, StoragePort, WebRTCPort } from '@bytexbyte/nxtlinq-ai-agent-core-development';
2
+ export type CreateWebPlatformPortsOptions = {
3
+ /** Override default `localStorage` port. */
4
+ storage?: StoragePort;
5
+ fetchImpl?: typeof fetch;
6
+ getTimezone?: () => string;
7
+ /** Pre-built WebRTC port (overrides browser default). */
8
+ webrtc?: WebRTCPort;
9
+ /** Set `false` to disable voice (no WebRTC port). */
10
+ enableWebRTC?: boolean;
11
+ };
12
+ export declare function createWebPlatformPorts(options?: CreateWebPlatformPortsOptions): PlatformPorts;
13
+ //# sourceMappingURL=createWebPlatformPorts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createWebPlatformPorts.d.ts","sourceRoot":"","sources":["../../src/ports/createWebPlatformPorts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAY,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,8CAA8C,CAAC;AAOrH,MAAM,MAAM,6BAA6B,GAAG;IAC1C,4CAA4C;IAC5C,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,MAAM,CAAC;IAC3B,yDAAyD;IACzD,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,qDAAqD;IACrD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAOF,wBAAgB,sBAAsB,CACpC,OAAO,GAAE,6BAAkC,GAC1C,aAAa,CAkBf"}
@@ -0,0 +1,25 @@
1
+ import { createBrowserStoragePort, createBrowserWebRTCPort, createDefaultHttpPort, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
2
+ function resolveHttpPort(fetchImpl) {
3
+ if (!fetchImpl)
4
+ return createDefaultHttpPort();
5
+ return { fetch: fetchImpl };
6
+ }
7
+ export function createWebPlatformPorts(options = {}) {
8
+ const enableWebRTC = options.enableWebRTC !== false;
9
+ return {
10
+ storage: options.storage ?? createBrowserStoragePort(),
11
+ http: resolveHttpPort(options.fetchImpl),
12
+ webrtc: enableWebRTC
13
+ ? (options.webrtc ?? createBrowserWebRTCPort())
14
+ : undefined,
15
+ getTimezone: options.getTimezone
16
+ ?? (() => {
17
+ try {
18
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
19
+ }
20
+ catch {
21
+ return 'UTC';
22
+ }
23
+ }),
24
+ };
25
+ }
@@ -0,0 +1,4 @@
1
+ import type { Attachment } from '@bytexbyte/nxtlinq-ai-agent-core-development';
2
+ /** Build an {@link Attachment} from a browser {@link File}. */
3
+ export declare function fileToAttachment(file: File): Promise<Attachment>;
4
+ //# sourceMappingURL=fileToAttachment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileToAttachment.d.ts","sourceRoot":"","sources":["../../src/utils/fileToAttachment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8CAA8C,CAAC;AAqB/E,+DAA+D;AAC/D,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,CAStE"}
@@ -0,0 +1,28 @@
1
+ function readFileAsDataUri(file) {
2
+ return new Promise((resolve, reject) => {
3
+ const reader = new FileReader();
4
+ reader.onload = () => {
5
+ if (typeof reader.result === 'string') {
6
+ resolve(reader.result);
7
+ return;
8
+ }
9
+ reject(new Error('fileToAttachment: failed to read file'));
10
+ };
11
+ reader.onerror = () => reject(reader.error ?? new Error('fileToAttachment: read error'));
12
+ reader.readAsDataURL(file);
13
+ });
14
+ }
15
+ function attachmentType(mimeType) {
16
+ return mimeType.startsWith('image/') ? 'image' : 'file';
17
+ }
18
+ /** Build an {@link Attachment} from a browser {@link File}. */
19
+ export async function fileToAttachment(file) {
20
+ const url = await readFileAsDataUri(file);
21
+ return {
22
+ type: attachmentType(file.type || 'application/octet-stream'),
23
+ url,
24
+ name: file.name,
25
+ mimeType: file.type || 'application/octet-stream',
26
+ size: file.size,
27
+ };
28
+ }
@@ -0,0 +1,11 @@
1
+ import type { VoiceSession, VoiceStatus } from '@bytexbyte/nxtlinq-ai-agent-core-development';
2
+ export declare function useVoiceSilenceCommit(getSession: () => VoiceSession | null, onMutedAfterCommit: () => void, voiceStatus: VoiceStatus): {
3
+ startPoll: () => void;
4
+ clearPoll: () => void;
5
+ resetTurn: () => void;
6
+ onSpeechRms: (rms: number) => void;
7
+ tryCommit: (reason: "silence" | "manual") => void;
8
+ consumeSkipCommitOnMute: () => boolean;
9
+ hasHadSpeech: () => boolean;
10
+ };
11
+ //# sourceMappingURL=useVoiceSilenceCommit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVoiceSilenceCommit.d.ts","sourceRoot":"","sources":["../../src/voice/useVoiceSilenceCommit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8CAA8C,CAAC;AAU9F,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,YAAY,GAAG,IAAI,EACrC,kBAAkB,EAAE,MAAM,IAAI,EAC9B,WAAW,EAAE,WAAW;;;;uBAmDc,MAAM;wBAhCL,SAAS,GAAG,QAAQ;;;EAmD5D"}
@@ -0,0 +1,68 @@
1
+ import { useCallback, useRef } from 'react';
2
+ import { ASSISTANT_MIC_HOLD_STATUSES } from './voiceMicConstants';
3
+ import { MIC_BARGE_IN_RMS_THRESHOLD, MIC_SILENCE_COMMIT_MS, MIC_SILENCE_POLL_MS, MIC_SPEECH_RMS_THRESHOLD, } from './ws/voiceSilenceConstants';
4
+ export function useVoiceSilenceCommit(getSession, onMutedAfterCommit, voiceStatus) {
5
+ const lastSpeechAtRef = useRef(0);
6
+ const hadSpeechRef = useRef(false);
7
+ const commitInFlightRef = useRef(false);
8
+ const skipCommitOnMuteRef = useRef(false);
9
+ const pollRef = useRef(null);
10
+ const voiceStatusRef = useRef(voiceStatus);
11
+ voiceStatusRef.current = voiceStatus;
12
+ const onMutedAfterCommitRef = useRef(onMutedAfterCommit);
13
+ onMutedAfterCommitRef.current = onMutedAfterCommit;
14
+ const clearPoll = useCallback(() => {
15
+ if (pollRef.current) {
16
+ clearInterval(pollRef.current);
17
+ pollRef.current = null;
18
+ }
19
+ }, []);
20
+ const tryCommit = useCallback((reason) => {
21
+ const session = getSession();
22
+ if (commitInFlightRef.current)
23
+ return;
24
+ if (!hadSpeechRef.current) {
25
+ session?.clearInputAudio?.();
26
+ return;
27
+ }
28
+ commitInFlightRef.current = true;
29
+ hadSpeechRef.current = false;
30
+ session?.commitInputAudio?.();
31
+ if (reason === 'silence') {
32
+ skipCommitOnMuteRef.current = true;
33
+ onMutedAfterCommitRef.current();
34
+ }
35
+ queueMicrotask(() => { commitInFlightRef.current = false; });
36
+ }, [getSession]);
37
+ const startPoll = useCallback(() => {
38
+ clearPoll();
39
+ pollRef.current = setInterval(() => {
40
+ if (commitInFlightRef.current || !hadSpeechRef.current)
41
+ return;
42
+ if (Date.now() - lastSpeechAtRef.current < MIC_SILENCE_COMMIT_MS)
43
+ return;
44
+ tryCommit('silence');
45
+ }, MIC_SILENCE_POLL_MS);
46
+ }, [clearPoll, tryCommit]);
47
+ const resetTurn = useCallback(() => {
48
+ hadSpeechRef.current = false;
49
+ lastSpeechAtRef.current = Date.now();
50
+ getSession()?.clearInputAudio?.();
51
+ }, [getSession]);
52
+ const onSpeechRms = useCallback((rms) => {
53
+ const threshold = ASSISTANT_MIC_HOLD_STATUSES.has(voiceStatusRef.current)
54
+ ? MIC_BARGE_IN_RMS_THRESHOLD
55
+ : MIC_SPEECH_RMS_THRESHOLD;
56
+ if (rms >= threshold) {
57
+ lastSpeechAtRef.current = Date.now();
58
+ hadSpeechRef.current = true;
59
+ }
60
+ }, []);
61
+ const consumeSkipCommitOnMute = useCallback(() => {
62
+ const skip = skipCommitOnMuteRef.current;
63
+ skipCommitOnMuteRef.current = false;
64
+ return skip;
65
+ }, []);
66
+ const hasHadSpeech = useCallback(() => hadSpeechRef.current, []);
67
+ return { startPoll, clearPoll, resetTurn, onSpeechRms, tryCommit, consumeSkipCommitOnMute, hasHadSpeech };
68
+ }
@@ -0,0 +1,16 @@
1
+ import type { Message, VoiceDoneEvent, VoiceTranscriptEvent } from '@bytexbyte/nxtlinq-ai-agent-core-development';
2
+ type InteractionMode = 'text' | 'voice';
3
+ type VoiceTranscriptAgentApi = {
4
+ getMessages: () => Message[];
5
+ setMessages: (messages: Message[]) => void;
6
+ syncVoiceTurnHistory: (options?: {
7
+ last?: number;
8
+ }) => Promise<void>;
9
+ };
10
+ export declare function useVoiceTranscriptMessages(api: VoiceTranscriptAgentApi, interactionMode: InteractionMode, voiceSessionId: string | null, getVoiceSessionId?: () => string | null): {
11
+ handleTranscript: (event: VoiceTranscriptEvent) => void;
12
+ handleDone: (event: VoiceDoneEvent) => void;
13
+ clearVoiceStream: () => void;
14
+ };
15
+ export {};
16
+ //# sourceMappingURL=useVoiceTranscriptMessages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVoiceTranscriptMessages.d.ts","sourceRoot":"","sources":["../../src/voice/useVoiceTranscriptMessages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,oBAAoB,EACrB,MAAM,8CAA8C,CAAC;AAKtD,KAAK,eAAe,GAAG,MAAM,GAAG,OAAO,CAAC;AAExC,KAAK,uBAAuB,GAAG;IAC7B,WAAW,EAAE,MAAM,OAAO,EAAE,CAAC;IAC7B,WAAW,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAC3C,oBAAoB,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtE,CAAC;AAWF,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,uBAAuB,EAC5B,eAAe,EAAE,eAAe,EAChC,cAAc,EAAE,MAAM,GAAG,IAAI,EAC7B,iBAAiB,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI;8BAqG7B,oBAAoB;wBA4BpB,cAAc;;EAwBzB"}
@@ -0,0 +1,134 @@
1
+ import { mergeStreamingTranscript } from '@bytexbyte/nxtlinq-ai-agent-core-development';
2
+ import { useCallback, useRef } from 'react';
3
+ import { flushSync } from 'react-dom';
4
+ const STREAM_PREFIX = 'voice-stream-';
5
+ function voiceMeta(sessionId) {
6
+ return {
7
+ voiceRealtime: true,
8
+ voiceSessionId: sessionId ?? undefined,
9
+ };
10
+ }
11
+ export function useVoiceTranscriptMessages(api, interactionMode, voiceSessionId, getVoiceSessionId) {
12
+ const streamIdRef = useRef(null);
13
+ const sessionIdRef = useRef(voiceSessionId);
14
+ sessionIdRef.current = voiceSessionId;
15
+ const resolveSessionId = useCallback(() => getVoiceSessionId?.() ?? sessionIdRef.current, [getVoiceSessionId]);
16
+ const isVoiceUiActive = useCallback(() => interactionMode === 'voice', [interactionMode]);
17
+ const upsertStreaming = useCallback((text) => {
18
+ const messages = api.getMessages();
19
+ let streamId = streamIdRef.current;
20
+ if (!streamId) {
21
+ streamId = `${STREAM_PREFIX}${Date.now()}`;
22
+ streamIdRef.current = streamId;
23
+ }
24
+ const idx = messages.findIndex((m) => m.id === streamId);
25
+ const partialContent = idx >= 0
26
+ ? mergeStreamingTranscript(messages[idx]?.partialContent ?? '', text)
27
+ : text;
28
+ const meta = voiceMeta(resolveSessionId());
29
+ const apply = () => {
30
+ if (idx >= 0) {
31
+ api.setMessages(messages.map((m, i) => i === idx
32
+ ? { ...m, partialContent, isStreaming: true, metadata: { ...m.metadata, ...meta } }
33
+ : m));
34
+ return;
35
+ }
36
+ api.setMessages([
37
+ ...messages,
38
+ {
39
+ id: streamId,
40
+ role: 'assistant',
41
+ content: '',
42
+ partialContent,
43
+ isStreaming: true,
44
+ timestamp: new Date().toISOString(),
45
+ metadata: meta,
46
+ },
47
+ ]);
48
+ };
49
+ flushSync(apply);
50
+ }, [api, resolveSessionId]);
51
+ const finalizeAssistant = useCallback((text, messageId) => {
52
+ const trimmed = text.trim();
53
+ streamIdRef.current = null;
54
+ if (!trimmed)
55
+ return;
56
+ const messages = api.getMessages();
57
+ const streamIdx = messages.findIndex((m) => m.isStreaming && m.role === 'assistant');
58
+ if (streamIdx >= 0) {
59
+ api.setMessages(messages.map((m, i) => i === streamIdx
60
+ ? {
61
+ ...m,
62
+ id: messageId ?? m.id,
63
+ content: trimmed,
64
+ partialContent: undefined,
65
+ isStreaming: false,
66
+ metadata: { ...m.metadata, ...voiceMeta(resolveSessionId()) },
67
+ }
68
+ : m));
69
+ return;
70
+ }
71
+ const last = messages[messages.length - 1];
72
+ if (last?.role === 'assistant' && last.content === trimmed)
73
+ return;
74
+ api.setMessages([
75
+ ...messages,
76
+ {
77
+ id: messageId ?? `voice-asst-${Date.now()}`,
78
+ role: 'assistant',
79
+ content: trimmed,
80
+ timestamp: new Date().toISOString(),
81
+ metadata: voiceMeta(resolveSessionId()),
82
+ },
83
+ ]);
84
+ }, [api, resolveSessionId]);
85
+ const handleTranscript = useCallback((event) => {
86
+ if (!isVoiceUiActive())
87
+ return;
88
+ const text = event.text?.trim() ?? '';
89
+ if (event.role === 'assistant') {
90
+ // Keep one streaming bubble for the whole turn; finalize only in handleDone.
91
+ if (text)
92
+ upsertStreaming(text);
93
+ return;
94
+ }
95
+ if (event.role === 'user' && !event.interim && text) {
96
+ const messages = api.getMessages();
97
+ const last = messages[messages.length - 1];
98
+ if (last?.role === 'user' && last.content === text)
99
+ return;
100
+ api.setMessages([
101
+ ...messages,
102
+ {
103
+ id: `voice-user-${Date.now()}`,
104
+ role: 'user',
105
+ content: text,
106
+ timestamp: new Date().toISOString(),
107
+ metadata: voiceMeta(resolveSessionId()),
108
+ },
109
+ ]);
110
+ }
111
+ }, [api, finalizeAssistant, isVoiceUiActive, resolveSessionId, upsertStreaming]);
112
+ const handleDone = useCallback((event) => {
113
+ if (!isVoiceUiActive())
114
+ return;
115
+ if (event.guardrailsBlocked || event.billingBlocked || event.error) {
116
+ streamIdRef.current = null;
117
+ return;
118
+ }
119
+ const reply = event.replyText?.trim() ?? '';
120
+ if (reply) {
121
+ finalizeAssistant(reply, event.assistantMessageId ?? undefined);
122
+ }
123
+ else {
124
+ streamIdRef.current = null;
125
+ }
126
+ void api.syncVoiceTurnHistory({ last: 20 }).catch((err) => {
127
+ console.warn('[nxtlinq] syncVoiceTurnHistory after voice turn failed', err);
128
+ });
129
+ }, [api, finalizeAssistant, isVoiceUiActive]);
130
+ const clearVoiceStream = useCallback(() => {
131
+ streamIdRef.current = null;
132
+ }, []);
133
+ return { handleTranscript, handleDone, clearVoiceStream };
134
+ }
@@ -0,0 +1,18 @@
1
+ import type { VoiceSession, VoiceStatus } from '@bytexbyte/nxtlinq-ai-agent-core-development';
2
+ type WsVoiceCallbacks = {
3
+ onOpen?: () => void;
4
+ onAudioDelta?: (pcm16: Int16Array | ArrayBuffer) => void;
5
+ onClose?: (reason: string) => void;
6
+ onError?: (err: Error) => void;
7
+ };
8
+ export type UseWsRealtimeAudioOptions = {
9
+ voiceStatus: VoiceStatus;
10
+ muteAfterSilenceCommit: () => void;
11
+ };
12
+ export declare function useWsRealtimeAudio(isCaptureActive: boolean, isVoiceActive: boolean, options: UseWsRealtimeAudioOptions): {
13
+ bindSession: (session: VoiceSession | null, captureWhenUnmuted?: boolean) => void;
14
+ buildCallbacks: (overrides?: Partial<WsVoiceCallbacks>) => WsVoiceCallbacks;
15
+ getOutputAudioLevel: () => number;
16
+ };
17
+ export {};
18
+ //# sourceMappingURL=useWsRealtimeAudio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWsRealtimeAudio.d.ts","sourceRoot":"","sources":["../../src/voice/useWsRealtimeAudio.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8CAA8C,CAAC;AAM9F,KAAK,gBAAgB,GAAG;IACtB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,KAAK,IAAI,CAAC;IACzD,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,WAAW,EAAE,WAAW,CAAC;IACzB,sBAAsB,EAAE,MAAM,IAAI,CAAC;CACpC,CAAC;AAEF,wBAAgB,kBAAkB,CAChC,eAAe,EAAE,OAAO,EACxB,aAAa,EAAE,OAAO,EACtB,OAAO,EAAE,yBAAyB;2BA+EQ,YAAY,GAAG,IAAI;iCAQb,OAAO,CAAC,gBAAgB,CAAC,KAAG,gBAAgB;;EAgC7F"}