@hivegpt/hiveai-angular 0.0.480 → 0.0.481
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/bundles/hivegpt-hiveai-angular.umd.js +113 -76
- package/bundles/hivegpt-hiveai-angular.umd.js.map +1 -1
- package/bundles/hivegpt-hiveai-angular.umd.min.js +1 -1
- package/bundles/hivegpt-hiveai-angular.umd.min.js.map +1 -1
- package/esm2015/lib/components/chat-drawer/chat-drawer.component.js +1 -3
- package/esm2015/lib/components/voice-agent/components/voice-agent-modal/voice-agent-modal.component.js +5 -9
- package/esm2015/lib/components/voice-agent/services/voice-agent.service.js +98 -56
- package/fesm2015/hivegpt-hiveai-angular.js +101 -65
- package/fesm2015/hivegpt-hiveai-angular.js.map +1 -1
- package/hivegpt-hiveai-angular.metadata.json +1 -1
- package/lib/components/chat-drawer/chat-drawer.component.d.ts.map +1 -1
- package/lib/components/voice-agent/components/voice-agent-modal/voice-agent-modal.component.d.ts.map +1 -1
- package/lib/components/voice-agent/services/voice-agent.service.d.ts +13 -9
- package/lib/components/voice-agent/services/voice-agent.service.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1587,11 +1587,15 @@
|
|
|
1587
1587
|
/** Static Daily.co room URL (used instead of dynamic room_created from backend). */
|
|
1588
1588
|
var STATIC_DAILY_ROOM_URL = 'https://cloud-4a46e9dfbc8c499daddd480d9c294b88.daily.co/voice-None-1772776583';
|
|
1589
1589
|
/**
|
|
1590
|
-
* Voice agent orchestrator.
|
|
1590
|
+
* Voice agent orchestrator. Coordinates WebSocket (signaling) and Daily.js (WebRTC audio).
|
|
1591
1591
|
*
|
|
1592
|
-
*
|
|
1593
|
-
* -
|
|
1594
|
-
* -
|
|
1592
|
+
* CRITICAL: This service must NEVER use Socket.IO or ngx-socket-io. Voice flow uses only:
|
|
1593
|
+
* - Native WebSocket (WebSocketVoiceClientService) for signaling (transcripts)
|
|
1594
|
+
* - Daily.js (DailyVoiceClientService) for WebRTC audio via STATIC_DAILY_ROOM_URL.
|
|
1595
|
+
*
|
|
1596
|
+
* - Maintains callState, statusText, duration, isMicMuted, isUserSpeaking, audioLevels
|
|
1597
|
+
* - Uses WebSocket for transcripts only (no audio)
|
|
1598
|
+
* - Uses Daily.js for all audio, mic, and real-time speaking detection
|
|
1595
1599
|
*/
|
|
1596
1600
|
var VoiceAgentService = /** @class */ (function () {
|
|
1597
1601
|
function VoiceAgentService(audioAnalyzer, wsClient, dailyClient) {
|
|
@@ -1622,10 +1626,6 @@
|
|
|
1622
1626
|
// Waveform visualization only - do NOT use for speaking state
|
|
1623
1627
|
this.subscriptions.add(this.audioAnalyzer.audioLevels$.subscribe(function (levels) { return _this.audioLevelsSubject.next(levels); }));
|
|
1624
1628
|
}
|
|
1625
|
-
/** Current call state (for checking if connection was already started). */
|
|
1626
|
-
VoiceAgentService.prototype.getCallState = function () {
|
|
1627
|
-
return this.callStateSubject.value;
|
|
1628
|
-
};
|
|
1629
1629
|
VoiceAgentService.prototype.ngOnDestroy = function () {
|
|
1630
1630
|
this.destroy$.next();
|
|
1631
1631
|
this.subscriptions.unsubscribe();
|
|
@@ -1644,92 +1644,135 @@
|
|
|
1644
1644
|
this.statusTextSubject.next('');
|
|
1645
1645
|
this.durationSubject.next('0:00');
|
|
1646
1646
|
};
|
|
1647
|
-
|
|
1648
|
-
VoiceAgentService.prototype.connect = function () {
|
|
1647
|
+
VoiceAgentService.prototype.connect = function (apiUrl, token, botId, conversationId, apiKey, eventToken, eventUrl, domainAuthority) {
|
|
1649
1648
|
return __awaiter(this, void 0, void 0, function () {
|
|
1650
|
-
var
|
|
1651
|
-
return __generator(this, function (
|
|
1652
|
-
switch (
|
|
1649
|
+
var _a, wsOk, error_1;
|
|
1650
|
+
return __generator(this, function (_b) {
|
|
1651
|
+
switch (_b.label) {
|
|
1653
1652
|
case 0:
|
|
1654
1653
|
if (this.callStateSubject.value !== 'idle') {
|
|
1655
1654
|
console.warn('Call already in progress');
|
|
1656
1655
|
return [2 /*return*/];
|
|
1657
1656
|
}
|
|
1657
|
+
_b.label = 1;
|
|
1658
|
+
case 1:
|
|
1659
|
+
_b.trys.push([1, 3, , 5]);
|
|
1658
1660
|
this.callStateSubject.next('connecting');
|
|
1659
1661
|
this.statusTextSubject.next('Connecting...');
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1662
|
+
return [4 /*yield*/, Promise.all([
|
|
1663
|
+
this.connectWebSocketSignaling(token, botId, conversationId, apiKey, eventToken, eventUrl, domainAuthority),
|
|
1664
|
+
this.dailyClient.connect(STATIC_DAILY_ROOM_URL),
|
|
1665
|
+
])];
|
|
1664
1666
|
case 2:
|
|
1665
|
-
_a.sent();
|
|
1667
|
+
_a = __read.apply(void 0, [_b.sent(), 1]), wsOk = _a[0];
|
|
1668
|
+
if (!wsOk) {
|
|
1669
|
+
throw new Error('No ws_url in response');
|
|
1670
|
+
}
|
|
1671
|
+
this.setupDailySubscriptions();
|
|
1666
1672
|
return [3 /*break*/, 5];
|
|
1667
1673
|
case 3:
|
|
1668
|
-
|
|
1669
|
-
console.error('
|
|
1674
|
+
error_1 = _b.sent();
|
|
1675
|
+
console.error('Error connecting voice agent:', error_1);
|
|
1670
1676
|
this.callStateSubject.next('ended');
|
|
1671
|
-
this.statusTextSubject.next('Connection failed');
|
|
1672
1677
|
return [4 /*yield*/, this.disconnect()];
|
|
1673
1678
|
case 4:
|
|
1674
|
-
|
|
1675
|
-
|
|
1679
|
+
_b.sent();
|
|
1680
|
+
this.statusTextSubject.next('Connection failed');
|
|
1681
|
+
throw error_1;
|
|
1676
1682
|
case 5: return [2 /*return*/];
|
|
1677
1683
|
}
|
|
1678
1684
|
});
|
|
1679
1685
|
});
|
|
1680
1686
|
};
|
|
1681
|
-
|
|
1687
|
+
/** POST for ws_url, wire transcript streams, connect WebSocket. Returns true if ws_url was found. */
|
|
1688
|
+
VoiceAgentService.prototype.connectWebSocketSignaling = function (token, botId, conversationId, apiKey, eventToken, eventUrl, domainAuthority) {
|
|
1682
1689
|
return __awaiter(this, void 0, void 0, function () {
|
|
1690
|
+
var postUrl, headers, res, json, wsUrl;
|
|
1683
1691
|
var _this = this;
|
|
1684
1692
|
return __generator(this, function (_a) {
|
|
1685
1693
|
switch (_a.label) {
|
|
1686
|
-
case 0:
|
|
1687
|
-
|
|
1688
|
-
|
|
1694
|
+
case 0:
|
|
1695
|
+
postUrl = "https://0a19-2405-201-5c02-991e-2487-d56-2543-bda8.ngrok-free.app/ai/ask-voice";
|
|
1696
|
+
headers = {
|
|
1697
|
+
'Content-Type': 'application/json',
|
|
1698
|
+
Authorization: "Bearer " + token,
|
|
1699
|
+
'domain-authority': domainAuthority,
|
|
1700
|
+
eventtoken: eventToken,
|
|
1701
|
+
eventurl: eventUrl,
|
|
1702
|
+
'hive-bot-id': botId,
|
|
1703
|
+
'x-api-key': apiKey,
|
|
1704
|
+
'ngrok-skip-browser-warning': 'true',
|
|
1705
|
+
};
|
|
1706
|
+
return [4 /*yield*/, fetch(postUrl, {
|
|
1707
|
+
method: 'POST',
|
|
1708
|
+
headers: headers,
|
|
1709
|
+
body: JSON.stringify({
|
|
1710
|
+
bot_id: botId,
|
|
1711
|
+
conversation_id: conversationId,
|
|
1712
|
+
voice: 'alloy',
|
|
1713
|
+
}),
|
|
1714
|
+
})];
|
|
1689
1715
|
case 1:
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
console.log("[VoiceDebug] First bot audio arrived \u2014 transitioning to talking \u2014 " + new Date().toISOString());
|
|
1710
|
-
_this.callStartTime = Date.now();
|
|
1711
|
-
_this.startDurationTimer();
|
|
1712
|
-
_this.callStateSubject.next('talking');
|
|
1713
|
-
return;
|
|
1714
|
-
}
|
|
1715
|
-
if (user) {
|
|
1716
|
-
_this.callStateSubject.next('listening');
|
|
1717
|
-
}
|
|
1718
|
-
else if (bot) {
|
|
1719
|
-
_this.callStateSubject.next('talking');
|
|
1720
|
-
}
|
|
1721
|
-
else if (current === 'talking' || current === 'listening') {
|
|
1722
|
-
_this.callStateSubject.next('connected');
|
|
1723
|
-
}
|
|
1724
|
-
}));
|
|
1725
|
-
this.subscriptions.add(this.dailyClient.micMuted$.subscribe(function (muted) { return _this.isMicMutedSubject.next(muted); }));
|
|
1726
|
-
console.log("[VoiceDebug] Room joined, staying in connecting until bot speaks \u2014 " + new Date().toISOString());
|
|
1727
|
-
this.statusTextSubject.next('Connecting...');
|
|
1728
|
-
return [2 /*return*/];
|
|
1716
|
+
res = _a.sent();
|
|
1717
|
+
if (!res.ok) {
|
|
1718
|
+
throw new Error("HTTP " + res.status);
|
|
1719
|
+
}
|
|
1720
|
+
return [4 /*yield*/, res.json()];
|
|
1721
|
+
case 2:
|
|
1722
|
+
json = _a.sent();
|
|
1723
|
+
wsUrl = json === null || json === void 0 ? void 0 : json.rn_ws_url;
|
|
1724
|
+
if (!wsUrl || typeof wsUrl !== 'string') {
|
|
1725
|
+
return [2 /*return*/, false];
|
|
1726
|
+
}
|
|
1727
|
+
this.subscriptions.add(this.wsClient.userTranscript$
|
|
1728
|
+
.pipe(operators.takeUntil(this.destroy$))
|
|
1729
|
+
.subscribe(function (t) { return _this.userTranscriptSubject.next(t); }));
|
|
1730
|
+
this.subscriptions.add(this.wsClient.botTranscript$
|
|
1731
|
+
.pipe(operators.takeUntil(this.destroy$))
|
|
1732
|
+
.subscribe(function (t) { return _this.botTranscriptSubject.next(t); }));
|
|
1733
|
+
this.wsClient.connect(wsUrl);
|
|
1734
|
+
return [2 /*return*/, true];
|
|
1729
1735
|
}
|
|
1730
1736
|
});
|
|
1731
1737
|
});
|
|
1732
1738
|
};
|
|
1739
|
+
/** Wire Daily client to UI state (waveform, speaking, mic muted). Call after Daily is connected. */
|
|
1740
|
+
VoiceAgentService.prototype.setupDailySubscriptions = function () {
|
|
1741
|
+
var _this = this;
|
|
1742
|
+
this.dailyClient.localStream$
|
|
1743
|
+
.pipe(operators.filter(function (s) { return s != null; }), operators.take(1))
|
|
1744
|
+
.subscribe(function (stream) {
|
|
1745
|
+
_this.audioAnalyzer.start(stream);
|
|
1746
|
+
});
|
|
1747
|
+
this.subscriptions.add(this.dailyClient.userSpeaking$.subscribe(function (s) { return _this.isUserSpeakingSubject.next(s); }));
|
|
1748
|
+
this.subscriptions.add(rxjs.combineLatest([
|
|
1749
|
+
this.dailyClient.speaking$,
|
|
1750
|
+
this.dailyClient.userSpeaking$,
|
|
1751
|
+
]).subscribe(function (_a) {
|
|
1752
|
+
var _b = __read(_a, 2), bot = _b[0], user = _b[1];
|
|
1753
|
+
var current = _this.callStateSubject.value;
|
|
1754
|
+
if (current === 'connecting' && !bot) {
|
|
1755
|
+
return;
|
|
1756
|
+
}
|
|
1757
|
+
if (current === 'connecting' && bot) {
|
|
1758
|
+
_this.callStartTime = Date.now();
|
|
1759
|
+
_this.startDurationTimer();
|
|
1760
|
+
_this.callStateSubject.next('talking');
|
|
1761
|
+
return;
|
|
1762
|
+
}
|
|
1763
|
+
if (user) {
|
|
1764
|
+
_this.callStateSubject.next('listening');
|
|
1765
|
+
}
|
|
1766
|
+
else if (bot) {
|
|
1767
|
+
_this.callStateSubject.next('talking');
|
|
1768
|
+
}
|
|
1769
|
+
else if (current === 'talking' || current === 'listening') {
|
|
1770
|
+
_this.callStateSubject.next('connected');
|
|
1771
|
+
}
|
|
1772
|
+
}));
|
|
1773
|
+
this.subscriptions.add(this.dailyClient.micMuted$.subscribe(function (muted) { return _this.isMicMutedSubject.next(muted); }));
|
|
1774
|
+
this.statusTextSubject.next('Connecting...');
|
|
1775
|
+
};
|
|
1733
1776
|
VoiceAgentService.prototype.disconnect = function () {
|
|
1734
1777
|
return __awaiter(this, void 0, void 0, function () {
|
|
1735
1778
|
return __generator(this, function (_a) {
|
|
@@ -1863,13 +1906,9 @@
|
|
|
1863
1906
|
this.subscriptions.push(this.voiceAgentService.audioLevels$.subscribe(function (levels) {
|
|
1864
1907
|
_this.audioLevels = levels;
|
|
1865
1908
|
}));
|
|
1866
|
-
//
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
if (!alreadyStarted) {
|
|
1870
|
-
this.voiceAgentService.resetToIdle();
|
|
1871
|
-
void this.startCall();
|
|
1872
|
-
}
|
|
1909
|
+
// Modal opens in idle state, then immediately starts connecting.
|
|
1910
|
+
this.voiceAgentService.resetToIdle();
|
|
1911
|
+
void this.startCall();
|
|
1873
1912
|
};
|
|
1874
1913
|
VoiceAgentModalComponent.prototype.ngOnDestroy = function () {
|
|
1875
1914
|
this.subscriptions.forEach(function (sub) { return sub.unsubscribe(); });
|
|
@@ -1887,7 +1926,7 @@
|
|
|
1887
1926
|
_g.label = 1;
|
|
1888
1927
|
case 1:
|
|
1889
1928
|
_g.trys.push([1, 3, 4, 5]);
|
|
1890
|
-
return [4 /*yield*/, this.voiceAgentService.connect()];
|
|
1929
|
+
return [4 /*yield*/, this.voiceAgentService.connect(this.apiUrl, this.token, this.botId, this.conversationId, this.apiKey, this.eventToken, this.eventUrl, this.domainAuthority)];
|
|
1891
1930
|
case 2:
|
|
1892
1931
|
_g.sent();
|
|
1893
1932
|
return [3 /*break*/, 5];
|
|
@@ -4244,8 +4283,6 @@
|
|
|
4244
4283
|
var conversationId = (_b = (_a = this.conversationKey) !== null && _a !== void 0 ? _a : this.conversationService.getKey(this.botId, false)) !== null && _b !== void 0 ? _b : '';
|
|
4245
4284
|
this.voiceModalConversationId = conversationId;
|
|
4246
4285
|
this.setupVoiceTranscripts();
|
|
4247
|
-
// Start connecting to the voice room immediately (no wait for modal to open)
|
|
4248
|
-
void this.voiceAgentService.connect();
|
|
4249
4286
|
// Close existing overlay if any
|
|
4250
4287
|
if (this.voiceModalOverlayRef) {
|
|
4251
4288
|
this.voiceModalOverlayRef.detach();
|