@hivegpt/hiveai-angular 0.0.582 → 0.0.584
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 +209 -382
- 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/hivegpt-hiveai-angular.js +4 -5
- package/esm2015/lib/components/voice-agent/services/voice-agent.service.js +174 -165
- package/esm2015/lib/components/voice-agent/voice-agent.module.js +3 -5
- package/fesm2015/hivegpt-hiveai-angular.js +173 -323
- package/fesm2015/hivegpt-hiveai-angular.js.map +1 -1
- package/hivegpt-hiveai-angular.d.ts +3 -4
- package/hivegpt-hiveai-angular.d.ts.map +1 -1
- package/hivegpt-hiveai-angular.metadata.json +1 -1
- package/lib/components/voice-agent/services/voice-agent.service.d.ts +24 -15
- package/lib/components/voice-agent/services/voice-agent.service.d.ts.map +1 -1
- package/lib/components/voice-agent/voice-agent.module.d.ts +2 -2
- package/lib/components/voice-agent/voice-agent.module.d.ts.map +1 -1
- package/package.json +1 -1
- package/esm2015/lib/components/voice-agent/services/websocket-voice-client.service.js +0 -163
- package/lib/components/voice-agent/services/websocket-voice-client.service.d.ts +0 -52
- package/lib/components/voice-agent/services/websocket-voice-client.service.d.ts.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
(function (global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/cdk/overlay'), require('@angular/cdk/portal'), require('@angular/common/http'), require('@angular/core'), require('@angular/platform-browser'), require('rxjs'), require('rxjs/operators'), require('@angular/common'), require('ngx-socket-io'), require('@angular/forms'), require('microsoft-cognitiveservices-speech-sdk'), require('marked'), require('@angular/material/icon'), require('@angular/material/sidenav'), require('ngx-quill')) :
|
|
3
|
-
typeof define === 'function' && define.amd ? define('@hivegpt/hiveai-angular', ['exports', '@angular/cdk/overlay', '@angular/cdk/portal', '@angular/common/http', '@angular/core', '@angular/platform-browser', 'rxjs', 'rxjs/operators', '@angular/common', 'ngx-socket-io', '@angular/forms', 'microsoft-cognitiveservices-speech-sdk', 'marked', '@angular/material/icon', '@angular/material/sidenav', 'ngx-quill'], factory) :
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.hivegpt = global.hivegpt || {}, global.hivegpt["hiveai-angular"] = {}), global.ng.cdk.overlay, global.ng.cdk.portal, global.ng.common.http, global.ng.core, global.ng.platformBrowser, global.rxjs, global.rxjs.operators, global.ng.common, global.ngxSocketIo, global.ng.forms, global.SpeechSDK, global.marked, global.ng.material.icon, global.ng.material.sidenav, global.ngxQuill));
|
|
5
|
-
})(this, (function (exports, overlay, portal, i1, i0, platformBrowser, rxjs, operators, common, ngxSocketIo, forms, SpeechSDK, marked, icon, sidenav, ngxQuill) { 'use strict';
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/cdk/overlay'), require('@angular/cdk/portal'), require('@angular/common/http'), require('@angular/core'), require('@angular/platform-browser'), require('rxjs'), require('rxjs/operators'), require('@angular/common'), require('ngx-socket-io'), require('@angular/forms'), require('microsoft-cognitiveservices-speech-sdk'), require('marked'), require('@pipecat-ai/client-js'), require('@pipecat-ai/websocket-transport'), require('@angular/material/icon'), require('@angular/material/sidenav'), require('ngx-quill')) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define('@hivegpt/hiveai-angular', ['exports', '@angular/cdk/overlay', '@angular/cdk/portal', '@angular/common/http', '@angular/core', '@angular/platform-browser', 'rxjs', 'rxjs/operators', '@angular/common', 'ngx-socket-io', '@angular/forms', 'microsoft-cognitiveservices-speech-sdk', 'marked', '@pipecat-ai/client-js', '@pipecat-ai/websocket-transport', '@angular/material/icon', '@angular/material/sidenav', 'ngx-quill'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.hivegpt = global.hivegpt || {}, global.hivegpt["hiveai-angular"] = {}), global.ng.cdk.overlay, global.ng.cdk.portal, global.ng.common.http, global.ng.core, global.ng.platformBrowser, global.rxjs, global.rxjs.operators, global.ng.common, global.ngxSocketIo, global.ng.forms, global.SpeechSDK, global.marked, global.clientJs, global.websocketTransport, global.ng.material.icon, global.ng.material.sidenav, global.ngxQuill));
|
|
5
|
+
})(this, (function (exports, overlay, portal, i1, i0, platformBrowser, rxjs, operators, common, ngxSocketIo, forms, SpeechSDK, marked, clientJs, websocketTransport, icon, sidenav, ngxQuill) { 'use strict';
|
|
6
6
|
|
|
7
7
|
function _interopNamespace(e) {
|
|
8
8
|
if (e && e.__esModule) return e;
|
|
@@ -1339,184 +1339,24 @@
|
|
|
1339
1339
|
];
|
|
1340
1340
|
|
|
1341
1341
|
/**
|
|
1342
|
-
*
|
|
1343
|
-
* CRITICAL: Uses native WebSocket only. NO Socket.IO, NO ngx-socket-io.
|
|
1342
|
+
* Voice agent orchestrator using the official PipecatClient SDK.
|
|
1344
1343
|
*
|
|
1345
|
-
*
|
|
1346
|
-
*
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
/** True when {@link disconnect} initiated the close (not counted as remote close). */
|
|
1353
|
-
this.closeInitiatedByClient = false;
|
|
1354
|
-
this.openedSubject = new rxjs.Subject();
|
|
1355
|
-
this.remoteCloseSubject = new rxjs.Subject();
|
|
1356
|
-
this.userTranscriptSubject = new rxjs.Subject();
|
|
1357
|
-
this.botTranscriptSubject = new rxjs.Subject();
|
|
1358
|
-
this.assistantSpeakingSubject = new rxjs.Subject();
|
|
1359
|
-
this.serverUserSpeakingSubject = new rxjs.Subject();
|
|
1360
|
-
/** Fires once each time the WebSocket reaches OPEN. */
|
|
1361
|
-
this.opened$ = this.openedSubject.asObservable();
|
|
1362
|
-
/** Fires when the socket closes without a client-initiated {@link disconnect}. */
|
|
1363
|
-
this.remoteClose$ = this.remoteCloseSubject.asObservable();
|
|
1364
|
-
this.userTranscript$ = this.userTranscriptSubject.asObservable();
|
|
1365
|
-
this.botTranscript$ = this.botTranscriptSubject.asObservable();
|
|
1366
|
-
/** Assistant/bot speaking, when the server sends explicit events (see {@link handleJsonMessage}). */
|
|
1367
|
-
this.assistantSpeaking$ = this.assistantSpeakingSubject.asObservable();
|
|
1368
|
-
/** User speaking from server-side VAD, if provided. */
|
|
1369
|
-
this.serverUserSpeaking$ = this.serverUserSpeakingSubject.asObservable();
|
|
1370
|
-
}
|
|
1371
|
-
WebSocketVoiceClientService.prototype.connect = function (wsUrl) {
|
|
1372
|
-
var _this = this;
|
|
1373
|
-
var _a;
|
|
1374
|
-
if (((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) {
|
|
1375
|
-
return;
|
|
1376
|
-
}
|
|
1377
|
-
if (this.ws) {
|
|
1378
|
-
this.closeInitiatedByClient = true;
|
|
1379
|
-
this.ws.close();
|
|
1380
|
-
}
|
|
1381
|
-
try {
|
|
1382
|
-
var socket_1 = new WebSocket(wsUrl);
|
|
1383
|
-
this.ws = socket_1;
|
|
1384
|
-
socket_1.onopen = function () {
|
|
1385
|
-
if (_this.ws !== socket_1)
|
|
1386
|
-
return;
|
|
1387
|
-
_this.ngZone.run(function () { return _this.openedSubject.next(); });
|
|
1388
|
-
};
|
|
1389
|
-
socket_1.onmessage = function (event) {
|
|
1390
|
-
if (_this.ws !== socket_1)
|
|
1391
|
-
return;
|
|
1392
|
-
if (typeof event.data !== 'string') {
|
|
1393
|
-
return;
|
|
1394
|
-
}
|
|
1395
|
-
try {
|
|
1396
|
-
var msg_1 = JSON.parse(event.data);
|
|
1397
|
-
_this.ngZone.run(function () { return _this.handleJsonMessage(msg_1); });
|
|
1398
|
-
}
|
|
1399
|
-
catch (_a) {
|
|
1400
|
-
// Ignore non-JSON
|
|
1401
|
-
}
|
|
1402
|
-
};
|
|
1403
|
-
socket_1.onerror = function () {
|
|
1404
|
-
_this.ngZone.run(function () {
|
|
1405
|
-
if (_this.ws === socket_1 && socket_1.readyState !== WebSocket.CLOSED) {
|
|
1406
|
-
socket_1.close();
|
|
1407
|
-
}
|
|
1408
|
-
});
|
|
1409
|
-
};
|
|
1410
|
-
socket_1.onclose = function () {
|
|
1411
|
-
if (_this.ws === socket_1) {
|
|
1412
|
-
_this.ws = null;
|
|
1413
|
-
}
|
|
1414
|
-
var client = _this.closeInitiatedByClient;
|
|
1415
|
-
_this.closeInitiatedByClient = false;
|
|
1416
|
-
if (!client) {
|
|
1417
|
-
_this.ngZone.run(function () { return _this.remoteCloseSubject.next(); });
|
|
1418
|
-
}
|
|
1419
|
-
};
|
|
1420
|
-
}
|
|
1421
|
-
catch (err) {
|
|
1422
|
-
console.error('WebSocketVoiceClient: connect failed', err);
|
|
1423
|
-
this.ws = null;
|
|
1424
|
-
throw err;
|
|
1425
|
-
}
|
|
1426
|
-
};
|
|
1427
|
-
WebSocketVoiceClientService.prototype.handleJsonMessage = function (msg) {
|
|
1428
|
-
var type = msg.type;
|
|
1429
|
-
var typeStr = typeof type === 'string' ? type : '';
|
|
1430
|
-
if (typeStr === 'session_ready' || typeStr === 'connected' || typeStr === 'voice_session_started') {
|
|
1431
|
-
return;
|
|
1432
|
-
}
|
|
1433
|
-
if (typeStr === 'assistant_speaking' ||
|
|
1434
|
-
typeStr === 'bot_speaking') {
|
|
1435
|
-
if (msg.active === true || msg.speaking === true) {
|
|
1436
|
-
this.assistantSpeakingSubject.next(true);
|
|
1437
|
-
}
|
|
1438
|
-
else if (msg.active === false || msg.speaking === false) {
|
|
1439
|
-
this.assistantSpeakingSubject.next(false);
|
|
1440
|
-
}
|
|
1441
|
-
return;
|
|
1442
|
-
}
|
|
1443
|
-
if (typeStr === 'user_speaking') {
|
|
1444
|
-
if (msg.active === true || msg.speaking === true) {
|
|
1445
|
-
this.serverUserSpeakingSubject.next(true);
|
|
1446
|
-
}
|
|
1447
|
-
else if (msg.active === false || msg.speaking === false) {
|
|
1448
|
-
this.serverUserSpeakingSubject.next(false);
|
|
1449
|
-
}
|
|
1450
|
-
return;
|
|
1451
|
-
}
|
|
1452
|
-
if (typeStr === 'input_audio_buffer.speech_started') {
|
|
1453
|
-
this.serverUserSpeakingSubject.next(true);
|
|
1454
|
-
return;
|
|
1455
|
-
}
|
|
1456
|
-
if (typeStr === 'input_audio_buffer.speech_stopped') {
|
|
1457
|
-
this.serverUserSpeakingSubject.next(false);
|
|
1458
|
-
return;
|
|
1459
|
-
}
|
|
1460
|
-
if (typeStr === 'response.audio.delta') {
|
|
1461
|
-
this.assistantSpeakingSubject.next(true);
|
|
1462
|
-
return;
|
|
1463
|
-
}
|
|
1464
|
-
if (typeStr === 'response.audio.done' ||
|
|
1465
|
-
typeStr === 'response.output_audio.done') {
|
|
1466
|
-
this.assistantSpeakingSubject.next(false);
|
|
1467
|
-
return;
|
|
1468
|
-
}
|
|
1469
|
-
if (typeStr === 'user_transcript' && typeof msg.text === 'string') {
|
|
1470
|
-
this.userTranscriptSubject.next({
|
|
1471
|
-
text: msg.text,
|
|
1472
|
-
final: msg.final === true,
|
|
1473
|
-
});
|
|
1474
|
-
return;
|
|
1475
|
-
}
|
|
1476
|
-
if (typeStr === 'bot_transcript' && typeof msg.text === 'string') {
|
|
1477
|
-
this.botTranscriptSubject.next(msg.text);
|
|
1478
|
-
}
|
|
1479
|
-
};
|
|
1480
|
-
WebSocketVoiceClientService.prototype.disconnect = function () {
|
|
1481
|
-
if (!this.ws) {
|
|
1482
|
-
return;
|
|
1483
|
-
}
|
|
1484
|
-
this.closeInitiatedByClient = true;
|
|
1485
|
-
this.ws.close();
|
|
1486
|
-
};
|
|
1487
|
-
Object.defineProperty(WebSocketVoiceClientService.prototype, "isConnected", {
|
|
1488
|
-
get: function () {
|
|
1489
|
-
var _a;
|
|
1490
|
-
return ((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN;
|
|
1491
|
-
},
|
|
1492
|
-
enumerable: false,
|
|
1493
|
-
configurable: true
|
|
1494
|
-
});
|
|
1495
|
-
return WebSocketVoiceClientService;
|
|
1496
|
-
}());
|
|
1497
|
-
WebSocketVoiceClientService.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function WebSocketVoiceClientService_Factory() { return new WebSocketVoiceClientService(i0__namespace.ɵɵinject(i0__namespace.NgZone)); }, token: WebSocketVoiceClientService, providedIn: "root" });
|
|
1498
|
-
WebSocketVoiceClientService.decorators = [
|
|
1499
|
-
{ type: i0.Injectable, args: [{
|
|
1500
|
-
providedIn: 'root',
|
|
1501
|
-
},] }
|
|
1502
|
-
];
|
|
1503
|
-
WebSocketVoiceClientService.ctorParameters = function () { return [
|
|
1504
|
-
{ type: i0.NgZone }
|
|
1505
|
-
]; };
|
|
1506
|
-
|
|
1507
|
-
/**
|
|
1508
|
-
* Voice agent orchestrator: single WebSocket (`ws_url` from POST /ai/ask-voice-socket)
|
|
1509
|
-
* for session events, transcripts, and optional speaking hints; local mic for capture
|
|
1510
|
-
* and waveform only (no Daily/WebRTC room).
|
|
1344
|
+
* Audio flow (mirrors the React reference implementation):
|
|
1345
|
+
* - Local mic: acquired by PipecatClient.initDevices(); local track fed to
|
|
1346
|
+
* AudioAnalyzerService for waveform visualisation.
|
|
1347
|
+
* - Bot audio: received as a MediaStreamTrack via RTVIEvent.TrackStarted,
|
|
1348
|
+
* played through a hidden <audio> element.
|
|
1349
|
+
* - All binary protobuf framing / RTVI protocol handled by
|
|
1350
|
+
* @pipecat-ai/client-js + @pipecat-ai/websocket-transport.
|
|
1511
1351
|
*/
|
|
1512
1352
|
var VoiceAgentService = /** @class */ (function () {
|
|
1513
|
-
function VoiceAgentService(audioAnalyzer,
|
|
1353
|
+
function VoiceAgentService(audioAnalyzer, platformTokenRefresh, ngZone,
|
|
1514
1354
|
/** `Object` not `object` — ngc metadata collection rejects the `object` type in DI params. */
|
|
1515
1355
|
platformId) {
|
|
1516
1356
|
var _this = this;
|
|
1517
1357
|
this.audioAnalyzer = audioAnalyzer;
|
|
1518
|
-
this.wsClient = wsClient;
|
|
1519
1358
|
this.platformTokenRefresh = platformTokenRefresh;
|
|
1359
|
+
this.ngZone = ngZone;
|
|
1520
1360
|
this.platformId = platformId;
|
|
1521
1361
|
this.callStateSubject = new rxjs.BehaviorSubject('idle');
|
|
1522
1362
|
this.statusTextSubject = new rxjs.BehaviorSubject('');
|
|
@@ -1528,8 +1368,8 @@
|
|
|
1528
1368
|
this.botTranscriptSubject = new rxjs.Subject();
|
|
1529
1369
|
this.callStartTime = 0;
|
|
1530
1370
|
this.durationInterval = null;
|
|
1531
|
-
this.
|
|
1532
|
-
this.
|
|
1371
|
+
this.pcClient = null;
|
|
1372
|
+
this.botAudioElement = null;
|
|
1533
1373
|
this.subscriptions = new rxjs.Subscription();
|
|
1534
1374
|
this.destroy$ = new rxjs.Subject();
|
|
1535
1375
|
this.callState$ = this.callStateSubject.asObservable();
|
|
@@ -1541,119 +1381,131 @@
|
|
|
1541
1381
|
this.userTranscript$ = this.userTranscriptSubject.asObservable();
|
|
1542
1382
|
this.botTranscript$ = this.botTranscriptSubject.asObservable();
|
|
1543
1383
|
this.subscriptions.add(this.audioAnalyzer.audioLevels$.subscribe(function (levels) { return _this.audioLevelsSubject.next(levels); }));
|
|
1544
|
-
this.subscriptions.add(this.wsClient.remoteClose$
|
|
1545
|
-
.pipe(operators.takeUntil(this.destroy$))
|
|
1546
|
-
.subscribe(function () { return void _this.handleRemoteClose(); }));
|
|
1547
1384
|
}
|
|
1548
1385
|
VoiceAgentService.prototype.ngOnDestroy = function () {
|
|
1549
1386
|
this.destroy$.next();
|
|
1550
1387
|
this.subscriptions.unsubscribe();
|
|
1551
|
-
this.disconnect();
|
|
1388
|
+
void this.disconnect();
|
|
1552
1389
|
};
|
|
1553
|
-
/** Reset to idle
|
|
1390
|
+
/** Reset to idle (e.g. when modal re-opens so user can click Start Call). */
|
|
1554
1391
|
VoiceAgentService.prototype.resetToIdle = function () {
|
|
1555
1392
|
if (this.callStateSubject.value === 'idle')
|
|
1556
1393
|
return;
|
|
1557
|
-
this.
|
|
1558
|
-
this.stopDurationTimer();
|
|
1559
|
-
this.callStartTime = 0;
|
|
1560
|
-
this.audioAnalyzer.stop();
|
|
1561
|
-
this.stopLocalMic();
|
|
1562
|
-
this.wsClient.disconnect();
|
|
1394
|
+
void this.disconnect();
|
|
1563
1395
|
this.callStateSubject.next('idle');
|
|
1564
1396
|
this.statusTextSubject.next('');
|
|
1565
1397
|
this.durationSubject.next('0:00');
|
|
1566
1398
|
};
|
|
1567
1399
|
VoiceAgentService.prototype.connect = function (apiUrl, token, botId, conversationId, apiKey, eventToken, eventId, eventUrl, domainAuthority, usersApiUrl) {
|
|
1568
1400
|
return __awaiter(this, void 0, void 0, function () {
|
|
1569
|
-
var accessToken, ensured, e_1, baseUrl,
|
|
1401
|
+
var accessToken, ensured, e_1, baseUrl, pcClient, requestHeaders, error_1;
|
|
1570
1402
|
var _this = this;
|
|
1571
|
-
return __generator(this, function (
|
|
1572
|
-
switch (
|
|
1403
|
+
return __generator(this, function (_d) {
|
|
1404
|
+
switch (_d.label) {
|
|
1573
1405
|
case 0:
|
|
1574
1406
|
if (this.callStateSubject.value !== 'idle') {
|
|
1575
|
-
console.warn('Call already in progress');
|
|
1407
|
+
console.warn('[HiveGpt Voice] Call already in progress');
|
|
1576
1408
|
return [2 /*return*/];
|
|
1577
1409
|
}
|
|
1578
|
-
|
|
1410
|
+
_d.label = 1;
|
|
1579
1411
|
case 1:
|
|
1580
|
-
|
|
1412
|
+
_d.trys.push([1, 8, , 10]);
|
|
1581
1413
|
this.callStateSubject.next('connecting');
|
|
1582
1414
|
this.statusTextSubject.next('Connecting...');
|
|
1583
1415
|
accessToken = token;
|
|
1584
1416
|
if (!(usersApiUrl && common.isPlatformBrowser(this.platformId))) return [3 /*break*/, 5];
|
|
1585
|
-
|
|
1417
|
+
_d.label = 2;
|
|
1586
1418
|
case 2:
|
|
1587
|
-
|
|
1419
|
+
_d.trys.push([2, 4, , 5]);
|
|
1588
1420
|
return [4 /*yield*/, this.platformTokenRefresh
|
|
1589
1421
|
.ensureValidAccessToken(token, usersApiUrl)
|
|
1590
1422
|
.pipe(operators.take(1))
|
|
1591
1423
|
.toPromise()];
|
|
1592
1424
|
case 3:
|
|
1593
|
-
ensured =
|
|
1594
|
-
if (ensured === null || ensured === void 0 ? void 0 : ensured.accessToken)
|
|
1425
|
+
ensured = _d.sent();
|
|
1426
|
+
if (ensured === null || ensured === void 0 ? void 0 : ensured.accessToken)
|
|
1595
1427
|
accessToken = ensured.accessToken;
|
|
1596
|
-
}
|
|
1597
1428
|
return [3 /*break*/, 5];
|
|
1598
1429
|
case 4:
|
|
1599
|
-
e_1 =
|
|
1600
|
-
console.warn('[HiveGpt Voice] Token refresh
|
|
1430
|
+
e_1 = _d.sent();
|
|
1431
|
+
console.warn('[HiveGpt Voice] Token refresh failed', e_1);
|
|
1601
1432
|
return [3 /*break*/, 5];
|
|
1602
1433
|
case 5:
|
|
1603
1434
|
baseUrl = apiUrl.replace(/\/$/, '');
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1435
|
+
pcClient = new clientJs.PipecatClient({
|
|
1436
|
+
transport: new websocketTransport.WebSocketTransport(),
|
|
1437
|
+
enableMic: true,
|
|
1438
|
+
enableCam: false,
|
|
1439
|
+
callbacks: {
|
|
1440
|
+
onConnected: function () { return _this.ngZone.run(function () { return _this.onPipecatConnected(); }); },
|
|
1441
|
+
onDisconnected: function () { return _this.ngZone.run(function () { return _this.onPipecatDisconnected(); }); },
|
|
1442
|
+
onBotReady: function () { return _this.ngZone.run(function () { return _this.onBotReady(); }); },
|
|
1443
|
+
onUserTranscript: function (data) { return _this.ngZone.run(function () { return _this.userTranscriptSubject.next({ text: data.text, final: !!data.final }); }); },
|
|
1444
|
+
onBotTranscript: function (data) { return _this.ngZone.run(function () { return _this.botTranscriptSubject.next(data.text); }); },
|
|
1445
|
+
onError: function (err) {
|
|
1446
|
+
_this.ngZone.run(function () {
|
|
1447
|
+
console.error('[HiveGpt Voice] PipecatClient error', err);
|
|
1448
|
+
_this.callStateSubject.next('ended');
|
|
1449
|
+
_this.statusTextSubject.next('Connection failed');
|
|
1450
|
+
});
|
|
1451
|
+
},
|
|
1452
|
+
},
|
|
1453
|
+
});
|
|
1454
|
+
this.pcClient = pcClient;
|
|
1455
|
+
// Bot audio arrives as a MediaStreamTrack — wire to a hidden <audio> element
|
|
1456
|
+
pcClient.on(clientJs.RTVIEvent.TrackStarted, function (track, participant) {
|
|
1457
|
+
if (!(participant === null || participant === void 0 ? void 0 : participant.local) && track.kind === 'audio') {
|
|
1458
|
+
_this.ngZone.run(function () { return _this.setupBotAudioTrack(track); });
|
|
1459
|
+
}
|
|
1460
|
+
});
|
|
1461
|
+
// Speaking state comes straight from RTVI events
|
|
1462
|
+
pcClient.on(clientJs.RTVIEvent.BotStartedSpeaking, function () { return _this.ngZone.run(function () { return _this.onBotStartedSpeaking(); }); });
|
|
1463
|
+
pcClient.on(clientJs.RTVIEvent.BotStoppedSpeaking, function () { return _this.ngZone.run(function () { return _this.onBotStoppedSpeaking(); }); });
|
|
1464
|
+
pcClient.on(clientJs.RTVIEvent.UserStartedSpeaking, function () { return _this.ngZone.run(function () {
|
|
1465
|
+
_this.isUserSpeakingSubject.next(true);
|
|
1466
|
+
_this.callStateSubject.next('listening');
|
|
1467
|
+
}); });
|
|
1468
|
+
pcClient.on(clientJs.RTVIEvent.UserStoppedSpeaking, function () { return _this.ngZone.run(function () {
|
|
1469
|
+
_this.isUserSpeakingSubject.next(false);
|
|
1470
|
+
if (_this.callStateSubject.value === 'listening') {
|
|
1471
|
+
_this.callStateSubject.next('connected');
|
|
1472
|
+
}
|
|
1473
|
+
}); });
|
|
1474
|
+
// Acquire mic (triggers browser permission prompt)
|
|
1475
|
+
return [4 /*yield*/, pcClient.initDevices()];
|
|
1476
|
+
case 6:
|
|
1477
|
+
// Acquire mic (triggers browser permission prompt)
|
|
1478
|
+
_d.sent();
|
|
1479
|
+
requestHeaders = new Headers();
|
|
1480
|
+
requestHeaders.append('Authorization', "Bearer " + accessToken);
|
|
1481
|
+
requestHeaders.append('x-api-key', apiKey);
|
|
1482
|
+
requestHeaders.append('hive-bot-id', botId);
|
|
1483
|
+
requestHeaders.append('domain-authority', domainAuthority);
|
|
1484
|
+
requestHeaders.append('eventUrl', eventUrl);
|
|
1485
|
+
requestHeaders.append('eventId', eventId);
|
|
1486
|
+
requestHeaders.append('eventToken', eventToken);
|
|
1487
|
+
requestHeaders.append('ngrok-skip-browser-warning', 'true');
|
|
1488
|
+
// POST to /ai/ask-voice-socket → receives { ws_url } → WebSocketTransport connects
|
|
1489
|
+
return [4 /*yield*/, pcClient.startBotAndConnect({
|
|
1490
|
+
endpoint: baseUrl + "/ai/ask-voice-socket",
|
|
1491
|
+
headers: requestHeaders,
|
|
1492
|
+
requestData: {
|
|
1620
1493
|
bot_id: botId,
|
|
1621
1494
|
conversation_id: conversationId,
|
|
1622
1495
|
voice: 'alloy',
|
|
1623
|
-
}
|
|
1496
|
+
},
|
|
1624
1497
|
})];
|
|
1625
|
-
case 6:
|
|
1626
|
-
res = _b.sent();
|
|
1627
|
-
if (!res.ok) {
|
|
1628
|
-
throw new Error("HTTP " + res.status);
|
|
1629
|
-
}
|
|
1630
|
-
return [4 /*yield*/, res.json()];
|
|
1631
1498
|
case 7:
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
(typeof (json === null || json === void 0 ? void 0 : json.rn_ws_url) === 'string' && json.rn_ws_url);
|
|
1635
|
-
if (!wsUrl) {
|
|
1636
|
-
throw new Error('No ws_url in response');
|
|
1637
|
-
}
|
|
1638
|
-
untilCallEnds$ = rxjs.merge(this.destroy$, this.endCall$);
|
|
1639
|
-
this.subscriptions.add(this.wsClient.userTranscript$
|
|
1640
|
-
.pipe(operators.takeUntil(untilCallEnds$))
|
|
1641
|
-
.subscribe(function (t) { return _this.userTranscriptSubject.next(t); }));
|
|
1642
|
-
this.subscriptions.add(this.wsClient.botTranscript$
|
|
1643
|
-
.pipe(operators.takeUntil(untilCallEnds$))
|
|
1644
|
-
.subscribe(function (t) { return _this.botTranscriptSubject.next(t); }));
|
|
1645
|
-
this.subscriptions.add(this.wsClient.opened$
|
|
1646
|
-
.pipe(operators.takeUntil(untilCallEnds$), operators.take(1))
|
|
1647
|
-
.subscribe(function () { return void _this.onWebsocketOpened(); }));
|
|
1648
|
-
this.wsClient.connect(wsUrl);
|
|
1499
|
+
// POST to /ai/ask-voice-socket → receives { ws_url } → WebSocketTransport connects
|
|
1500
|
+
_d.sent();
|
|
1649
1501
|
return [3 /*break*/, 10];
|
|
1650
1502
|
case 8:
|
|
1651
|
-
error_1 =
|
|
1652
|
-
console.error('
|
|
1503
|
+
error_1 = _d.sent();
|
|
1504
|
+
console.error('[HiveGpt Voice] connect failed', error_1);
|
|
1653
1505
|
this.callStateSubject.next('ended');
|
|
1654
|
-
return [4 /*yield*/, this.
|
|
1506
|
+
return [4 /*yield*/, this.cleanupPipecatClient()];
|
|
1655
1507
|
case 9:
|
|
1656
|
-
|
|
1508
|
+
_d.sent();
|
|
1657
1509
|
this.statusTextSubject.next('Connection failed');
|
|
1658
1510
|
throw error_1;
|
|
1659
1511
|
case 10: return [2 /*return*/];
|
|
@@ -1661,161 +1513,138 @@
|
|
|
1661
1513
|
});
|
|
1662
1514
|
});
|
|
1663
1515
|
};
|
|
1664
|
-
VoiceAgentService.prototype.
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
case 0:
|
|
1670
|
-
if (this.callStateSubject.value !== 'connecting') {
|
|
1671
|
-
return [2 /*return*/];
|
|
1672
|
-
}
|
|
1673
|
-
_b.label = 1;
|
|
1674
|
-
case 1:
|
|
1675
|
-
_b.trys.push([1, 3, , 5]);
|
|
1676
|
-
return [4 /*yield*/, this.startLocalMic()];
|
|
1677
|
-
case 2:
|
|
1678
|
-
_b.sent();
|
|
1679
|
-
this.statusTextSubject.next('Connected');
|
|
1680
|
-
this.callStateSubject.next('connected');
|
|
1681
|
-
this.wireSpeakingState();
|
|
1682
|
-
return [3 /*break*/, 5];
|
|
1683
|
-
case 3:
|
|
1684
|
-
err_1 = _b.sent();
|
|
1685
|
-
console.error('[HiveGpt Voice] Mic or session setup failed', err_1);
|
|
1686
|
-
this.callStateSubject.next('ended');
|
|
1687
|
-
this.statusTextSubject.next('Microphone unavailable');
|
|
1688
|
-
return [4 /*yield*/, this.disconnect()];
|
|
1689
|
-
case 4:
|
|
1690
|
-
_b.sent();
|
|
1691
|
-
return [3 /*break*/, 5];
|
|
1692
|
-
case 5: return [2 /*return*/];
|
|
1693
|
-
}
|
|
1694
|
-
});
|
|
1695
|
-
});
|
|
1516
|
+
VoiceAgentService.prototype.onPipecatConnected = function () {
|
|
1517
|
+
this.callStateSubject.next('connected');
|
|
1518
|
+
this.statusTextSubject.next('Connected');
|
|
1519
|
+
this.isMicMutedSubject.next(false);
|
|
1520
|
+
this.startLocalMicAnalyzer();
|
|
1696
1521
|
};
|
|
1697
|
-
VoiceAgentService.prototype.
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
this.
|
|
1710
|
-
|
|
1711
|
-
.
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1522
|
+
VoiceAgentService.prototype.onPipecatDisconnected = function () {
|
|
1523
|
+
this.stopDurationTimer();
|
|
1524
|
+
this.callStartTime = 0;
|
|
1525
|
+
this.audioAnalyzer.stop();
|
|
1526
|
+
this.stopBotAudio();
|
|
1527
|
+
this.callStateSubject.next('ended');
|
|
1528
|
+
this.statusTextSubject.next('Call Ended');
|
|
1529
|
+
};
|
|
1530
|
+
VoiceAgentService.prototype.onBotReady = function () {
|
|
1531
|
+
var _a, _b, _c;
|
|
1532
|
+
// Retry track wiring in case tracks weren't ready at onConnected
|
|
1533
|
+
this.startLocalMicAnalyzer();
|
|
1534
|
+
var botTrack = (_c = (_b = (_a = this.pcClient) === null || _a === void 0 ? void 0 : _a.tracks()) === null || _b === void 0 ? void 0 : _b.bot) === null || _c === void 0 ? void 0 : _c.audio;
|
|
1535
|
+
if (botTrack)
|
|
1536
|
+
this.setupBotAudioTrack(botTrack);
|
|
1537
|
+
};
|
|
1538
|
+
VoiceAgentService.prototype.startLocalMicAnalyzer = function () {
|
|
1539
|
+
var _a, _b, _c;
|
|
1540
|
+
var localTrack = (_c = (_b = (_a = this.pcClient) === null || _a === void 0 ? void 0 : _a.tracks()) === null || _b === void 0 ? void 0 : _b.local) === null || _c === void 0 ? void 0 : _c.audio;
|
|
1541
|
+
if (localTrack) {
|
|
1542
|
+
this.audioAnalyzer.start(new MediaStream([localTrack]));
|
|
1543
|
+
}
|
|
1544
|
+
};
|
|
1545
|
+
VoiceAgentService.prototype.onBotStartedSpeaking = function () {
|
|
1546
|
+
if (this.callStartTime === 0) {
|
|
1547
|
+
this.callStartTime = Date.now();
|
|
1548
|
+
this.startDurationTimer();
|
|
1549
|
+
}
|
|
1550
|
+
this.callStateSubject.next('talking');
|
|
1551
|
+
};
|
|
1552
|
+
VoiceAgentService.prototype.onBotStoppedSpeaking = function () {
|
|
1553
|
+
if (this.callStateSubject.value === 'talking') {
|
|
1554
|
+
this.callStateSubject.next('connected');
|
|
1555
|
+
}
|
|
1556
|
+
};
|
|
1557
|
+
VoiceAgentService.prototype.setupBotAudioTrack = function (track) {
|
|
1558
|
+
var _a;
|
|
1559
|
+
if (!this.botAudioElement) {
|
|
1560
|
+
this.botAudioElement = new Audio();
|
|
1561
|
+
this.botAudioElement.autoplay = true;
|
|
1562
|
+
}
|
|
1563
|
+
var existing = (_a = this.botAudioElement.srcObject) === null || _a === void 0 ? void 0 : _a.getAudioTracks()[0];
|
|
1564
|
+
if ((existing === null || existing === void 0 ? void 0 : existing.id) === track.id)
|
|
1565
|
+
return;
|
|
1566
|
+
this.botAudioElement.srcObject = new MediaStream([track]);
|
|
1567
|
+
this.botAudioElement.play().catch(function (err) { return console.warn('[HiveGpt Voice] Bot audio play blocked', err); });
|
|
1568
|
+
};
|
|
1569
|
+
VoiceAgentService.prototype.stopBotAudio = function () {
|
|
1570
|
+
var _a;
|
|
1571
|
+
if (this.botAudioElement) {
|
|
1572
|
+
try {
|
|
1573
|
+
this.botAudioElement.pause();
|
|
1574
|
+
(_a = this.botAudioElement.srcObject) === null || _a === void 0 ? void 0 : _a.getAudioTracks().forEach(function (t) { return t.stop(); });
|
|
1575
|
+
this.botAudioElement.srcObject = null;
|
|
1730
1576
|
}
|
|
1731
|
-
|
|
1732
|
-
|
|
1577
|
+
catch (_b) {
|
|
1578
|
+
// ignore
|
|
1733
1579
|
}
|
|
1734
|
-
|
|
1580
|
+
this.botAudioElement = null;
|
|
1581
|
+
}
|
|
1735
1582
|
};
|
|
1736
|
-
VoiceAgentService.prototype.
|
|
1583
|
+
VoiceAgentService.prototype.disconnect = function () {
|
|
1737
1584
|
return __awaiter(this, void 0, void 0, function () {
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
switch (_b.label) {
|
|
1585
|
+
return __generator(this, function (_d) {
|
|
1586
|
+
switch (_d.label) {
|
|
1741
1587
|
case 0:
|
|
1742
|
-
this.
|
|
1743
|
-
|
|
1588
|
+
this.stopDurationTimer();
|
|
1589
|
+
this.callStartTime = 0;
|
|
1590
|
+
this.audioAnalyzer.stop();
|
|
1591
|
+
this.stopBotAudio();
|
|
1592
|
+
return [4 /*yield*/, this.cleanupPipecatClient()];
|
|
1744
1593
|
case 1:
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
stream.getTracks().forEach(function (t) { return t.stop(); });
|
|
1749
|
-
throw new Error('No audio track');
|
|
1750
|
-
}
|
|
1751
|
-
this.localMicStream = stream;
|
|
1752
|
-
this.isMicMutedSubject.next(!track.enabled);
|
|
1753
|
-
this.audioAnalyzer.start(stream);
|
|
1594
|
+
_d.sent();
|
|
1595
|
+
this.callStateSubject.next('ended');
|
|
1596
|
+
this.statusTextSubject.next('Call Ended');
|
|
1754
1597
|
return [2 /*return*/];
|
|
1755
1598
|
}
|
|
1756
1599
|
});
|
|
1757
1600
|
});
|
|
1758
1601
|
};
|
|
1759
|
-
VoiceAgentService.prototype.
|
|
1760
|
-
if (this.localMicStream) {
|
|
1761
|
-
this.localMicStream.getTracks().forEach(function (t) { return t.stop(); });
|
|
1762
|
-
this.localMicStream = null;
|
|
1763
|
-
}
|
|
1764
|
-
};
|
|
1765
|
-
VoiceAgentService.prototype.handleRemoteClose = function () {
|
|
1602
|
+
VoiceAgentService.prototype.cleanupPipecatClient = function () {
|
|
1766
1603
|
return __awaiter(this, void 0, void 0, function () {
|
|
1767
|
-
var
|
|
1768
|
-
return __generator(this, function (
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
this.stopDurationTimer();
|
|
1788
|
-
this.callStartTime = 0;
|
|
1789
|
-
this.audioAnalyzer.stop();
|
|
1790
|
-
this.stopLocalMic();
|
|
1791
|
-
this.wsClient.disconnect();
|
|
1792
|
-
this.callStateSubject.next('ended');
|
|
1793
|
-
this.statusTextSubject.next('Call Ended');
|
|
1794
|
-
return [2 /*return*/];
|
|
1604
|
+
var _a_1;
|
|
1605
|
+
return __generator(this, function (_d) {
|
|
1606
|
+
switch (_d.label) {
|
|
1607
|
+
case 0:
|
|
1608
|
+
if (!this.pcClient) return [3 /*break*/, 5];
|
|
1609
|
+
_d.label = 1;
|
|
1610
|
+
case 1:
|
|
1611
|
+
_d.trys.push([1, 3, , 4]);
|
|
1612
|
+
return [4 /*yield*/, this.pcClient.disconnect()];
|
|
1613
|
+
case 2:
|
|
1614
|
+
_d.sent();
|
|
1615
|
+
return [3 /*break*/, 4];
|
|
1616
|
+
case 3:
|
|
1617
|
+
_a_1 = _d.sent();
|
|
1618
|
+
return [3 /*break*/, 4];
|
|
1619
|
+
case 4:
|
|
1620
|
+
this.pcClient = null;
|
|
1621
|
+
_d.label = 5;
|
|
1622
|
+
case 5: return [2 /*return*/];
|
|
1623
|
+
}
|
|
1795
1624
|
});
|
|
1796
1625
|
});
|
|
1797
1626
|
};
|
|
1798
1627
|
VoiceAgentService.prototype.toggleMic = function () {
|
|
1799
|
-
|
|
1628
|
+
if (!this.pcClient)
|
|
1629
|
+
return;
|
|
1800
1630
|
var nextMuted = !this.isMicMutedSubject.value;
|
|
1801
|
-
|
|
1802
|
-
if (track) {
|
|
1803
|
-
track.enabled = !nextMuted;
|
|
1804
|
-
}
|
|
1631
|
+
this.pcClient.enableMic(!nextMuted);
|
|
1805
1632
|
this.isMicMutedSubject.next(nextMuted);
|
|
1633
|
+
if (nextMuted)
|
|
1634
|
+
this.isUserSpeakingSubject.next(false);
|
|
1806
1635
|
};
|
|
1807
1636
|
VoiceAgentService.prototype.startDurationTimer = function () {
|
|
1808
1637
|
var _this = this;
|
|
1809
|
-
var
|
|
1638
|
+
var tick = function () {
|
|
1810
1639
|
if (_this.callStartTime > 0) {
|
|
1811
1640
|
var elapsed = Math.floor((Date.now() - _this.callStartTime) / 1000);
|
|
1812
|
-
var
|
|
1813
|
-
var
|
|
1814
|
-
_this.durationSubject.next(
|
|
1641
|
+
var m = Math.floor(elapsed / 60);
|
|
1642
|
+
var s = elapsed % 60;
|
|
1643
|
+
_this.durationSubject.next(m + ":" + String(s).padStart(2, '0'));
|
|
1815
1644
|
}
|
|
1816
1645
|
};
|
|
1817
|
-
|
|
1818
|
-
this.durationInterval = setInterval(
|
|
1646
|
+
tick();
|
|
1647
|
+
this.durationInterval = setInterval(tick, 1000);
|
|
1819
1648
|
};
|
|
1820
1649
|
VoiceAgentService.prototype.stopDurationTimer = function () {
|
|
1821
1650
|
if (this.durationInterval) {
|
|
@@ -1825,7 +1654,7 @@
|
|
|
1825
1654
|
};
|
|
1826
1655
|
return VoiceAgentService;
|
|
1827
1656
|
}());
|
|
1828
|
-
VoiceAgentService.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function VoiceAgentService_Factory() { return new VoiceAgentService(i0__namespace.ɵɵinject(AudioAnalyzerService), i0__namespace.ɵɵinject(
|
|
1657
|
+
VoiceAgentService.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function VoiceAgentService_Factory() { return new VoiceAgentService(i0__namespace.ɵɵinject(AudioAnalyzerService), i0__namespace.ɵɵinject(PlatformTokenRefreshService), i0__namespace.ɵɵinject(i0__namespace.NgZone), i0__namespace.ɵɵinject(i0__namespace.PLATFORM_ID)); }, token: VoiceAgentService, providedIn: "root" });
|
|
1829
1658
|
VoiceAgentService.decorators = [
|
|
1830
1659
|
{ type: i0.Injectable, args: [{
|
|
1831
1660
|
providedIn: 'root',
|
|
@@ -1833,8 +1662,8 @@
|
|
|
1833
1662
|
];
|
|
1834
1663
|
VoiceAgentService.ctorParameters = function () { return [
|
|
1835
1664
|
{ type: AudioAnalyzerService },
|
|
1836
|
-
{ type: WebSocketVoiceClientService },
|
|
1837
1665
|
{ type: PlatformTokenRefreshService },
|
|
1666
|
+
{ type: i0.NgZone },
|
|
1838
1667
|
{ type: Object, decorators: [{ type: i0.Inject, args: [i0.PLATFORM_ID,] }] }
|
|
1839
1668
|
]; };
|
|
1840
1669
|
|
|
@@ -6015,8 +5844,8 @@
|
|
|
6015
5844
|
};
|
|
6016
5845
|
|
|
6017
5846
|
/**
|
|
6018
|
-
* Voice agent module. Uses
|
|
6019
|
-
*
|
|
5847
|
+
* Voice agent module. Uses @pipecat-ai/client-js + @pipecat-ai/websocket-transport
|
|
5848
|
+
* (peer dependencies) for WebSocket transport, RTVI protocol, and audio.
|
|
6020
5849
|
*/
|
|
6021
5850
|
var VoiceAgentModule = /** @class */ (function () {
|
|
6022
5851
|
function VoiceAgentModule() {
|
|
@@ -6034,7 +5863,6 @@
|
|
|
6034
5863
|
providers: [
|
|
6035
5864
|
VoiceAgentService,
|
|
6036
5865
|
AudioAnalyzerService,
|
|
6037
|
-
WebSocketVoiceClientService
|
|
6038
5866
|
],
|
|
6039
5867
|
exports: [
|
|
6040
5868
|
VoiceAgentModalComponent
|
|
@@ -6335,10 +6163,9 @@
|
|
|
6335
6163
|
exports["ɵc"] = ConversationService;
|
|
6336
6164
|
exports["ɵd"] = NotificationSocket;
|
|
6337
6165
|
exports["ɵe"] = TranslationService;
|
|
6338
|
-
exports["ɵf"] =
|
|
6339
|
-
exports["ɵg"] =
|
|
6340
|
-
exports["ɵh"] =
|
|
6341
|
-
exports["ɵi"] = BotHtmlEditorComponent;
|
|
6166
|
+
exports["ɵf"] = VideoPlayerComponent;
|
|
6167
|
+
exports["ɵg"] = SafeHtmlPipe;
|
|
6168
|
+
exports["ɵh"] = BotHtmlEditorComponent;
|
|
6342
6169
|
|
|
6343
6170
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
6344
6171
|
|