ttp-agent-sdk 2.48.16 → 2.48.18
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/README.md +11 -0
- package/dist/agent-widget.dev.js +269 -109
- package/dist/agent-widget.esm.js +1 -1
- package/dist/agent-widget.js +1 -1
- package/dist/examples/pet-store.html +494 -0
- package/dist/examples/seabreeze-hotel.html +403 -0
- package/dist/index.html +111 -1
- package/examples/pet-store.html +494 -0
- package/examples/seabreeze-hotel.html +403 -0
- package/package.json +2 -1
package/dist/agent-widget.dev.js
CHANGED
|
@@ -12129,7 +12129,7 @@ var TextChatSDK = /*#__PURE__*/function (_EventEmitter) {
|
|
|
12129
12129
|
|
|
12130
12130
|
// SDK build time for debugging
|
|
12131
12131
|
if (true) {
|
|
12132
|
-
helloMessage.lastBuildTime = "2026-08-
|
|
12132
|
+
helloMessage.lastBuildTime = "2026-08-27T12:25:20.756Z";
|
|
12133
12133
|
}
|
|
12134
12134
|
try {
|
|
12135
12135
|
this.ws.send(JSON.stringify(helloMessage));
|
|
@@ -21439,8 +21439,8 @@ var VoiceSDK = _v2_VoiceSDK_js__WEBPACK_IMPORTED_MODULE_0__["default"];
|
|
|
21439
21439
|
|
|
21440
21440
|
|
|
21441
21441
|
// Version - injected at build time from package.json via webpack DefinePlugin
|
|
21442
|
-
var VERSION = "2.48.
|
|
21443
|
-
var BUILD_TIME = "2026-08-
|
|
21442
|
+
var VERSION = "2.48.18";
|
|
21443
|
+
var BUILD_TIME = "2026-08-27T12:25:20.756Z";
|
|
21444
21444
|
console.log("%c TTP Agent SDK v".concat(VERSION, " (").concat(BUILD_TIME, ") "), 'background: #4f46e5; color: white; font-size: 12px; font-weight: bold; padding: 2px 6px; border-radius: 4px;');
|
|
21445
21445
|
|
|
21446
21446
|
// Named exports
|
|
@@ -25615,6 +25615,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
25615
25615
|
/* harmony import */ var _codecs_PCMCodec_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./codecs/PCMCodec.js */ "./src/v2/codecs/PCMCodec.js");
|
|
25616
25616
|
/* harmony import */ var _codecs_PCMUCodec_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./codecs/PCMUCodec.js */ "./src/v2/codecs/PCMUCodec.js");
|
|
25617
25617
|
/* harmony import */ var _codecs_PCMACodec_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./codecs/PCMACodec.js */ "./src/v2/codecs/PCMACodec.js");
|
|
25618
|
+
/* harmony import */ var _hopPlatform_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./hopPlatform.js */ "./src/v2/hopPlatform.js");
|
|
25618
25619
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
25619
25620
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
25620
25621
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
@@ -25646,6 +25647,7 @@ function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf
|
|
|
25646
25647
|
|
|
25647
25648
|
|
|
25648
25649
|
|
|
25650
|
+
|
|
25649
25651
|
// iOS FIX: Shared AudioContext for playback that persists across AudioPlayer instances.
|
|
25650
25652
|
// iOS WebKit doesn't release audio hardware synchronously when AudioContext.close() is called,
|
|
25651
25653
|
// so creating a new AudioContext immediately after closing the old one can fail silently.
|
|
@@ -25745,6 +25747,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
25745
25747
|
_this._mediaStreamDest = null;
|
|
25746
25748
|
_this._htmlAudioRouteActive = false;
|
|
25747
25749
|
_this._htmlAudioPlayOk = false;
|
|
25750
|
+
_this._htmlAudioPlayWatchdog = null;
|
|
25748
25751
|
_this._loggedHopResample = false;
|
|
25749
25752
|
// Greeting (and other bursts) fire many playChunk()s without await.
|
|
25750
25753
|
// Serialize context creation so they cannot open two AudioContexts
|
|
@@ -27164,37 +27167,40 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27164
27167
|
}, {
|
|
27165
27168
|
key: "wantsHtmlAudioPlayback",
|
|
27166
27169
|
value: function wantsHtmlAudioPlayback() {
|
|
27167
|
-
// Debug/QA override: ?ttp_hop=0|1
|
|
27168
|
-
//
|
|
27169
|
-
|
|
27170
|
-
|
|
27171
|
-
|
|
27172
|
-
|
|
27173
|
-
|
|
27174
|
-
}
|
|
27175
|
-
} catch (e) {/* non-browser env */}
|
|
27170
|
+
// Debug/QA override: ?ttp_hop=0|1, its sessionStorage mirror (survives
|
|
27171
|
+
// same-origin full page loads that drop the query string — Borusan's
|
|
27172
|
+
// navigate_to_form), or localStorage 'ttp_hop'. Wins over config.
|
|
27173
|
+
var override = (0,_hopPlatform_js__WEBPACK_IMPORTED_MODULE_4__.readTtpHopOverride)(typeof window !== 'undefined' ? window : null);
|
|
27174
|
+
if (override !== null) {
|
|
27175
|
+
return override;
|
|
27176
|
+
}
|
|
27176
27177
|
if (typeof this.config.htmlAudioPlayback === 'boolean') {
|
|
27177
27178
|
return this.config.htmlAudioPlayback;
|
|
27178
27179
|
}
|
|
27179
|
-
// Default:
|
|
27180
|
-
//
|
|
27181
|
-
//
|
|
27182
|
-
// desktop
|
|
27183
|
-
|
|
27180
|
+
// Default: HTML hop (AudioContext → MediaStreamDestination → <audio>) gives
|
|
27181
|
+
// Safari/Chrome a far-end AEC reference on Apple mobile + macOS where Web
|
|
27182
|
+
// Audio → destination is not in the echo-cancellation loop. On Windows and
|
|
27183
|
+
// Linux desktop, Chrome-wide AEC already covers speaker echo; the hop only
|
|
27184
|
+
// adds adaptive live-stream speed wobble — keep it off there (same as Linux).
|
|
27185
|
+
var hopOn = this._needsHtmlAudioHopForAec();
|
|
27184
27186
|
if (!this._hopDefaultLogged) {
|
|
27185
27187
|
this._hopDefaultLogged = true;
|
|
27186
|
-
|
|
27188
|
+
var reason = hopOn ? 'on (mobile / macOS: AEC far-end route)' : 'off (desktop Windows/Linux: stable direct Web Audio playback)';
|
|
27189
|
+
console.log("\uD83D\uDD0A AudioPlayer: htmlAudioPlayback default \u2192 ".concat(reason));
|
|
27187
27190
|
}
|
|
27188
27191
|
return hopOn;
|
|
27189
27192
|
}
|
|
27193
|
+
|
|
27194
|
+
/** Hop default on only where Web Audio destination lacks AEC far-end reference.
|
|
27195
|
+
* Policy lives in hopPlatform.js (pure, unit-tested); this only supplies the
|
|
27196
|
+
* environment strings. */
|
|
27190
27197
|
}, {
|
|
27191
|
-
key: "
|
|
27192
|
-
value: function
|
|
27198
|
+
key: "_needsHtmlAudioHopForAec",
|
|
27199
|
+
value: function _needsHtmlAudioHopForAec() {
|
|
27193
27200
|
try {
|
|
27194
27201
|
var ua = navigator.userAgent || '';
|
|
27195
|
-
if (/Android|iPhone|iPad|iPod/i.test(ua)) return false;
|
|
27196
27202
|
var platform = navigator.userAgentData && navigator.userAgentData.platform || navigator.platform || '';
|
|
27197
|
-
return
|
|
27203
|
+
return (0,_hopPlatform_js__WEBPACK_IMPORTED_MODULE_4__.needsHtmlAudioHopForAec)(ua, platform);
|
|
27198
27204
|
} catch (e) {
|
|
27199
27205
|
return false;
|
|
27200
27206
|
}
|
|
@@ -27289,6 +27295,10 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27289
27295
|
}
|
|
27290
27296
|
if (!this.audioContext || typeof this.audioContext.createMediaStreamDestination !== 'function') {
|
|
27291
27297
|
console.warn('⚠️ AudioPlayer: MediaStreamDestination unavailable — using AudioContext.destination');
|
|
27298
|
+
this.emit('htmlAudioRoute', {
|
|
27299
|
+
state: 'fallback',
|
|
27300
|
+
reason: 'no_media_stream_destination'
|
|
27301
|
+
});
|
|
27292
27302
|
return false;
|
|
27293
27303
|
}
|
|
27294
27304
|
try {
|
|
@@ -27306,31 +27316,72 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27306
27316
|
this._htmlAudioEl = el;
|
|
27307
27317
|
this._htmlAudioRouteActive = true;
|
|
27308
27318
|
this._ensureHtmlAudioPlaying();
|
|
27319
|
+
this._armHtmlAudioPlayWatchdog(el);
|
|
27309
27320
|
console.log('🔊 AudioPlayer: Playback last-hop is HTMLAudioElement (AEC far-end route)');
|
|
27310
27321
|
return true;
|
|
27311
27322
|
} catch (e) {
|
|
27312
27323
|
console.warn('⚠️ AudioPlayer: HTML audio route failed, falling back to destination:', e);
|
|
27313
27324
|
this._teardownHtmlAudioRoute();
|
|
27325
|
+
this.emit('htmlAudioRoute', {
|
|
27326
|
+
state: 'fallback',
|
|
27327
|
+
reason: 'route_init_failed'
|
|
27328
|
+
});
|
|
27314
27329
|
return false;
|
|
27315
27330
|
}
|
|
27316
27331
|
}
|
|
27332
|
+
|
|
27333
|
+
/**
|
|
27334
|
+
* play() on a MediaStream-backed element can stay pending forever on some
|
|
27335
|
+
* WebKit builds — neither resolving nor rejecting. If the element is still
|
|
27336
|
+
* paused shortly after route creation, report it: the hop never engaged and
|
|
27337
|
+
* AEC has no far-end reference, but audio still reaches the user via the
|
|
27338
|
+
* (silent-failure) direct path only if a fallback happened — so this state
|
|
27339
|
+
* means "route exists, playback through it unconfirmed".
|
|
27340
|
+
*/
|
|
27341
|
+
}, {
|
|
27342
|
+
key: "_armHtmlAudioPlayWatchdog",
|
|
27343
|
+
value: function _armHtmlAudioPlayWatchdog(el) {
|
|
27344
|
+
var _this7 = this;
|
|
27345
|
+
this._clearHtmlAudioPlayWatchdog();
|
|
27346
|
+
this._htmlAudioPlayWatchdog = setTimeout(function () {
|
|
27347
|
+
_this7._htmlAudioPlayWatchdog = null;
|
|
27348
|
+
if (_this7._htmlAudioRouteActive && _this7._htmlAudioEl === el && !_this7._htmlAudioPlayOk && el.paused) {
|
|
27349
|
+
console.warn('⚠️ AudioPlayer: HTMLAudioElement.play() still pending after 2.5s — hop engagement unconfirmed');
|
|
27350
|
+
_this7.emit('htmlAudioRoute', {
|
|
27351
|
+
state: 'play_pending'
|
|
27352
|
+
});
|
|
27353
|
+
}
|
|
27354
|
+
}, 2500);
|
|
27355
|
+
}
|
|
27356
|
+
}, {
|
|
27357
|
+
key: "_clearHtmlAudioPlayWatchdog",
|
|
27358
|
+
value: function _clearHtmlAudioPlayWatchdog() {
|
|
27359
|
+
if (this._htmlAudioPlayWatchdog) {
|
|
27360
|
+
clearTimeout(this._htmlAudioPlayWatchdog);
|
|
27361
|
+
this._htmlAudioPlayWatchdog = null;
|
|
27362
|
+
}
|
|
27363
|
+
}
|
|
27317
27364
|
}, {
|
|
27318
27365
|
key: "_ensureHtmlAudioPlaying",
|
|
27319
27366
|
value: function _ensureHtmlAudioPlaying() {
|
|
27320
|
-
var
|
|
27367
|
+
var _this8 = this;
|
|
27321
27368
|
var el = this._htmlAudioEl;
|
|
27322
27369
|
if (!el) return;
|
|
27323
27370
|
if (!el.paused && this._htmlAudioPlayOk) return;
|
|
27324
27371
|
var playResult = el.play();
|
|
27325
27372
|
if (playResult && typeof playResult.then === 'function') {
|
|
27326
27373
|
playResult.then(function () {
|
|
27327
|
-
|
|
27374
|
+
_this8._htmlAudioPlayOk = true;
|
|
27375
|
+
_this8._clearHtmlAudioPlayWatchdog();
|
|
27376
|
+
_this8.emit('htmlAudioRoute', {
|
|
27377
|
+
state: 'established'
|
|
27378
|
+
});
|
|
27328
27379
|
}).catch(function (err) {
|
|
27329
|
-
if (
|
|
27380
|
+
if (_this8._htmlAudioPlayOk || !el.paused) {
|
|
27330
27381
|
return;
|
|
27331
27382
|
}
|
|
27332
27383
|
console.warn('⚠️ AudioPlayer: HTMLAudioElement.play() rejected — falling back to destination:', err);
|
|
27333
|
-
|
|
27384
|
+
_this8._fallbackToDestination('play_rejected');
|
|
27334
27385
|
});
|
|
27335
27386
|
}
|
|
27336
27387
|
}
|
|
@@ -27344,10 +27395,15 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27344
27395
|
this._teardownHtmlAudioRoute();
|
|
27345
27396
|
this.gainNode.connect(this.audioContext.destination);
|
|
27346
27397
|
console.warn("\u26A0\uFE0F AudioPlayer: Fell back to AudioContext.destination (".concat(reason, ")"));
|
|
27398
|
+
this.emit('htmlAudioRoute', {
|
|
27399
|
+
state: 'fallback',
|
|
27400
|
+
reason: reason
|
|
27401
|
+
});
|
|
27347
27402
|
}
|
|
27348
27403
|
}, {
|
|
27349
27404
|
key: "_teardownHtmlAudioRoute",
|
|
27350
27405
|
value: function _teardownHtmlAudioRoute() {
|
|
27406
|
+
this._clearHtmlAudioPlayWatchdog();
|
|
27351
27407
|
if (this._htmlAudioEl) {
|
|
27352
27408
|
try {
|
|
27353
27409
|
this._htmlAudioEl.pause();
|
|
@@ -27371,7 +27427,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27371
27427
|
key: "initializeAudioContext",
|
|
27372
27428
|
value: (function () {
|
|
27373
27429
|
var _initializeAudioContext = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7() {
|
|
27374
|
-
var
|
|
27430
|
+
var _this9 = this;
|
|
27375
27431
|
return _regenerator().w(function (_context8) {
|
|
27376
27432
|
while (1) switch (_context8.n) {
|
|
27377
27433
|
case 0:
|
|
@@ -27382,7 +27438,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27382
27438
|
return _context8.a(2, this._audioContextInitPromise);
|
|
27383
27439
|
case 1:
|
|
27384
27440
|
this._audioContextInitPromise = this._initializeAudioContextImpl().finally(function () {
|
|
27385
|
-
|
|
27441
|
+
_this9._audioContextInitPromise = null;
|
|
27386
27442
|
});
|
|
27387
27443
|
return _context8.a(2, this._audioContextInitPromise);
|
|
27388
27444
|
}
|
|
@@ -27397,7 +27453,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27397
27453
|
key: "_initializeAudioContextImpl",
|
|
27398
27454
|
value: function () {
|
|
27399
27455
|
var _initializeAudioContextImpl2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee8() {
|
|
27400
|
-
var
|
|
27456
|
+
var _this0 = this;
|
|
27401
27457
|
var ttsSampleRate, useHardwareRate, desiredSampleRate, contextFits, canReuseShared, setupAfterResume, ctxOpts, _t4;
|
|
27402
27458
|
return _regenerator().w(function (_context9) {
|
|
27403
27459
|
while (1) switch (_context9.p = _context9.n) {
|
|
@@ -27418,7 +27474,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27418
27474
|
_sharedPlayerSampleRate = null;
|
|
27419
27475
|
}
|
|
27420
27476
|
contextFits = function contextFits(rate) {
|
|
27421
|
-
if (useHardwareRate) return
|
|
27477
|
+
if (useHardwareRate) return _this0._isHardwarePlaybackRate(rate);
|
|
27422
27478
|
return Math.abs(rate - desiredSampleRate) <= 100;
|
|
27423
27479
|
}; // Check if current instance AudioContext exists and matches
|
|
27424
27480
|
if (!this.audioContext) {
|
|
@@ -27455,19 +27511,19 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27455
27511
|
console.log("\u267B\uFE0F AudioPlayer: Reusing shared AudioContext at ".concat(_sharedPlayerContext.sampleRate, "Hz (iOS-safe)"));
|
|
27456
27512
|
this.audioContext = _sharedPlayerContext;
|
|
27457
27513
|
setupAfterResume = function setupAfterResume() {
|
|
27458
|
-
|
|
27459
|
-
if (
|
|
27514
|
+
_this0.setupAudioContextStateMonitoring();
|
|
27515
|
+
if (_this0.gainNode) {
|
|
27460
27516
|
try {
|
|
27461
|
-
|
|
27517
|
+
_this0.gainNode.disconnect();
|
|
27462
27518
|
} catch (e) {
|
|
27463
27519
|
console.warn('⚠️ AudioPlayer: Error disconnecting old GainNode:', e);
|
|
27464
27520
|
}
|
|
27465
27521
|
}
|
|
27466
|
-
|
|
27467
|
-
|
|
27468
|
-
|
|
27469
|
-
if (!
|
|
27470
|
-
|
|
27522
|
+
_this0.gainNode = _this0.audioContext.createGain();
|
|
27523
|
+
_this0.gainNode.gain.value = 1.0;
|
|
27524
|
+
_this0._connectGainToOutput();
|
|
27525
|
+
if (!_this0._audioContextPrimed) {
|
|
27526
|
+
_this0._primeAudioContext();
|
|
27471
27527
|
}
|
|
27472
27528
|
};
|
|
27473
27529
|
if (!(this.audioContext.state === 'suspended')) {
|
|
@@ -27659,7 +27715,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27659
27715
|
* Handles mic permission grants, tab switching, browser suspension, etc.
|
|
27660
27716
|
*/
|
|
27661
27717
|
function setupAudioContextStateMonitoring() {
|
|
27662
|
-
var
|
|
27718
|
+
var _this1 = this;
|
|
27663
27719
|
if (!this.audioContext) {
|
|
27664
27720
|
return;
|
|
27665
27721
|
}
|
|
@@ -27672,38 +27728,38 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27672
27728
|
// Create handler that references this.audioContext dynamically
|
|
27673
27729
|
this._audioContextStateChangeHandler = function () {
|
|
27674
27730
|
// Null check required because audioContext may be cleaned up while handler is queued
|
|
27675
|
-
if (!
|
|
27731
|
+
if (!_this1.audioContext) {
|
|
27676
27732
|
console.warn('⚠️ AudioPlayer: State change handler fired but AudioContext is null');
|
|
27677
27733
|
return;
|
|
27678
27734
|
}
|
|
27679
|
-
console.log("\uD83C\uDFB5 AudioPlayer: AudioContext state changed to: ".concat(
|
|
27680
|
-
if (
|
|
27681
|
-
|
|
27735
|
+
console.log("\uD83C\uDFB5 AudioPlayer: AudioContext state changed to: ".concat(_this1.audioContext.state));
|
|
27736
|
+
if (_this1.audioContext.state === 'running') {
|
|
27737
|
+
_this1._ensureHtmlAudioPlaying();
|
|
27682
27738
|
}
|
|
27683
|
-
if (
|
|
27739
|
+
if (_this1.audioContext.state === 'suspended' && _this1.isPlaying) {
|
|
27684
27740
|
// AudioContext was suspended during playback (tab switch, mic permission, etc.)
|
|
27685
27741
|
console.warn('⚠️ AudioPlayer: AudioContext suspended during playback');
|
|
27686
27742
|
// Note: Playback will pause automatically, but we should handle queue processing
|
|
27687
27743
|
// The state change will be handled when we try to process next frame
|
|
27688
|
-
} else if (
|
|
27744
|
+
} else if (_this1.audioContext.state === 'running' && !_this1.isPlaying && (_this1.audioQueue.length > 0 || _this1.pcmChunkQueue.length > 0 || _this1.preparedBuffer.length > 0)) {
|
|
27689
27745
|
// AudioContext resumed and we have queued frames
|
|
27690
27746
|
// This handles: mic permission grant, tab switching back, browser resume, etc.
|
|
27691
27747
|
console.log('✅ AudioPlayer: AudioContext resumed - resuming queue processing');
|
|
27692
27748
|
|
|
27693
27749
|
// Resume queue processing if we have frames
|
|
27694
|
-
if (
|
|
27750
|
+
if (_this1.audioQueue.length > 0 && !_this1.isProcessingQueue) {
|
|
27695
27751
|
setTimeout(function () {
|
|
27696
|
-
return
|
|
27752
|
+
return _this1.processQueue();
|
|
27697
27753
|
}, 50);
|
|
27698
27754
|
}
|
|
27699
|
-
if (
|
|
27755
|
+
if (_this1.pcmChunkQueue.length > 0 && !_this1.isProcessingPcmQueue) {
|
|
27700
27756
|
setTimeout(function () {
|
|
27701
|
-
return
|
|
27757
|
+
return _this1.processPcmQueue();
|
|
27702
27758
|
}, 50);
|
|
27703
27759
|
}
|
|
27704
|
-
if (
|
|
27760
|
+
if (_this1.preparedBuffer.length > 0 && !_this1.isSchedulingFrames) {
|
|
27705
27761
|
setTimeout(function () {
|
|
27706
|
-
return
|
|
27762
|
+
return _this1.scheduleFrames();
|
|
27707
27763
|
}, 50);
|
|
27708
27764
|
}
|
|
27709
27765
|
}
|
|
@@ -27722,7 +27778,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27722
27778
|
key: "processQueue",
|
|
27723
27779
|
value: (function () {
|
|
27724
27780
|
var _processQueue = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee0() {
|
|
27725
|
-
var
|
|
27781
|
+
var _this10 = this;
|
|
27726
27782
|
var audioBlob, wasFirstPlay, audioContext, arrayBuffer, audioBuffer, shouldEmitStart, source, _t6;
|
|
27727
27783
|
return _regenerator().w(function (_context1) {
|
|
27728
27784
|
while (1) switch (_context1.p = _context1.n) {
|
|
@@ -27782,22 +27838,22 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27782
27838
|
// Handle end
|
|
27783
27839
|
|
|
27784
27840
|
source.onended = function () {
|
|
27785
|
-
|
|
27786
|
-
|
|
27841
|
+
_this10.currentSource = null;
|
|
27842
|
+
_this10.isProcessingQueue = false;
|
|
27787
27843
|
|
|
27788
27844
|
// Process next chunk
|
|
27789
27845
|
|
|
27790
|
-
if (
|
|
27846
|
+
if (_this10.audioQueue.length > 0) {
|
|
27791
27847
|
setTimeout(function () {
|
|
27792
|
-
return
|
|
27848
|
+
return _this10.processQueue();
|
|
27793
27849
|
}, 50);
|
|
27794
27850
|
} else {
|
|
27795
27851
|
// No more chunks - stop after delay
|
|
27796
27852
|
|
|
27797
27853
|
setTimeout(function () {
|
|
27798
|
-
if (
|
|
27799
|
-
|
|
27800
|
-
|
|
27854
|
+
if (_this10.audioQueue.length === 0 && !_this10.currentSource) {
|
|
27855
|
+
_this10.isPlaying = false;
|
|
27856
|
+
_this10.emit('playbackStopped');
|
|
27801
27857
|
}
|
|
27802
27858
|
}, 100);
|
|
27803
27859
|
}
|
|
@@ -27820,7 +27876,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27820
27876
|
if (this.audioQueue.length > 0) {
|
|
27821
27877
|
this.isProcessingQueue = false;
|
|
27822
27878
|
setTimeout(function () {
|
|
27823
|
-
return
|
|
27879
|
+
return _this10.processQueue();
|
|
27824
27880
|
}, 100);
|
|
27825
27881
|
} else {
|
|
27826
27882
|
this.isPlaying = false;
|
|
@@ -28043,7 +28099,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28043
28099
|
}, {
|
|
28044
28100
|
key: "markNewSentence",
|
|
28045
28101
|
value: function markNewSentence(text, synced, segmentId) {
|
|
28046
|
-
var
|
|
28102
|
+
var _this11 = this;
|
|
28047
28103
|
var wasStopped = this._isStopped;
|
|
28048
28104
|
var isCurrentlyPlaying = this.isPlaying || this.scheduledSources.size > 0;
|
|
28049
28105
|
|
|
@@ -28102,34 +28158,34 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28102
28158
|
var sentenceText = text; // Capture for timeout callback
|
|
28103
28159
|
this._emptySentenceTimeout = setTimeout(function () {
|
|
28104
28160
|
// Check if this sentence still has no chunks after timeout
|
|
28105
|
-
if (
|
|
28161
|
+
if (_this11.pendingSentenceText === sentenceText && _this11.scheduledBuffers === 0 && _this11.preparedBuffer.length === 0 && _this11.pcmChunkQueue.length === 0 && !_this11._isStopped) {
|
|
28106
28162
|
console.warn("\u26A0\uFE0F AudioPlayer: Empty sentence detected after 5s timeout - no chunks received for: \"".concat(sentenceText.substring(0, 40), "...\""));
|
|
28107
28163
|
// If this empty sentence carried a segment id, report it done (nothing was heard) and
|
|
28108
28164
|
// adopt it as current so the coarse stop below matches the backend's last-sent id.
|
|
28109
|
-
if (
|
|
28110
|
-
var emptySegId =
|
|
28111
|
-
|
|
28112
|
-
|
|
28113
|
-
|
|
28165
|
+
if (_this11.pendingSegmentId != null) {
|
|
28166
|
+
var emptySegId = _this11.pendingSegmentId;
|
|
28167
|
+
_this11.currentSegmentId = emptySegId;
|
|
28168
|
+
_this11.pendingSegmentId = null;
|
|
28169
|
+
_this11.emit('segmentDone', {
|
|
28114
28170
|
segmentId: emptySegId,
|
|
28115
28171
|
status: 'finished',
|
|
28116
28172
|
playedMs: 0
|
|
28117
28173
|
});
|
|
28118
28174
|
}
|
|
28119
28175
|
// Clear pending sentence to unblock next sentence
|
|
28120
|
-
if (
|
|
28121
|
-
|
|
28176
|
+
if (_this11.pendingSentenceText === sentenceText) {
|
|
28177
|
+
_this11.pendingSentenceText = null;
|
|
28122
28178
|
}
|
|
28123
28179
|
// Emit playbackStopped to allow next sentence to start
|
|
28124
28180
|
// Only if we're not currently playing (to avoid interrupting real playback)
|
|
28125
|
-
if (!
|
|
28181
|
+
if (!_this11.isPlaying && _this11.scheduledSources.size === 0) {
|
|
28126
28182
|
console.log('🛑 AudioPlayer: Emitting playbackStopped for empty sentence timeout');
|
|
28127
|
-
|
|
28128
|
-
segmentId:
|
|
28183
|
+
_this11.emit('playbackStopped', {
|
|
28184
|
+
segmentId: _this11.currentSegmentId
|
|
28129
28185
|
});
|
|
28130
28186
|
}
|
|
28131
28187
|
}
|
|
28132
|
-
|
|
28188
|
+
_this11._emptySentenceTimeout = null;
|
|
28133
28189
|
}, 5000); // 5 second timeout - adjust based on expected chunk arrival rate
|
|
28134
28190
|
}
|
|
28135
28191
|
|
|
@@ -28139,14 +28195,14 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28139
28195
|
}, {
|
|
28140
28196
|
key: "startTranscriptChecker",
|
|
28141
28197
|
value: function startTranscriptChecker() {
|
|
28142
|
-
var
|
|
28198
|
+
var _this12 = this;
|
|
28143
28199
|
if (this.isCheckingTranscripts) return;
|
|
28144
28200
|
this.isCheckingTranscripts = true;
|
|
28145
28201
|
console.log('📝 AudioPlayer: Transcript checker started');
|
|
28146
28202
|
var _checkLoop = function checkLoop() {
|
|
28147
|
-
if (!
|
|
28148
|
-
var currentTime =
|
|
28149
|
-
var _iterator2 = _createForOfIteratorHelper(
|
|
28203
|
+
if (!_this12.isCheckingTranscripts || !_this12.audioContext) return;
|
|
28204
|
+
var currentTime = _this12.audioContext.currentTime;
|
|
28205
|
+
var _iterator2 = _createForOfIteratorHelper(_this12.sentenceTimings),
|
|
28150
28206
|
_step2;
|
|
28151
28207
|
try {
|
|
28152
28208
|
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
@@ -28160,13 +28216,13 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28160
28216
|
eventData.synced = _timing.synced;
|
|
28161
28217
|
}
|
|
28162
28218
|
console.log("\uD83D\uDCDD AudioPlayer: Display transcript at ".concat(currentTime.toFixed(3), "s: \"").concat(_timing.text.substring(0, 40), "...\" (synced: ").concat(_timing.synced ? _timing.synced.length : 0, ")"));
|
|
28163
|
-
|
|
28219
|
+
_this12.emit('transcriptDisplay', eventData);
|
|
28164
28220
|
}
|
|
28165
28221
|
// Per-segment natural finish: this segment's audio window has fully elapsed.
|
|
28166
28222
|
if (!_timing.doneReported && _timing.endTime != null && currentTime >= _timing.endTime) {
|
|
28167
28223
|
_timing.doneReported = true;
|
|
28168
28224
|
var _playedMs = Math.round((_timing.endTime - _timing.startTime) * 1000);
|
|
28169
|
-
|
|
28225
|
+
_this12.emit('segmentDone', {
|
|
28170
28226
|
segmentId: _timing.segmentId,
|
|
28171
28227
|
status: 'finished',
|
|
28172
28228
|
playedMs: _playedMs
|
|
@@ -28178,12 +28234,12 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28178
28234
|
} finally {
|
|
28179
28235
|
_iterator2.f();
|
|
28180
28236
|
}
|
|
28181
|
-
if (
|
|
28237
|
+
if (_this12.isPlaying || _this12.scheduledBuffers > 0) {
|
|
28182
28238
|
requestAnimationFrame(_checkLoop);
|
|
28183
28239
|
} else {
|
|
28184
28240
|
// Playback drained naturally — flush any segment whose finish tick we may have missed
|
|
28185
28241
|
// (the last buffer's onended can flip isPlaying=false before this loop's next tick).
|
|
28186
|
-
var _iterator3 = _createForOfIteratorHelper(
|
|
28242
|
+
var _iterator3 = _createForOfIteratorHelper(_this12.sentenceTimings),
|
|
28187
28243
|
_step3;
|
|
28188
28244
|
try {
|
|
28189
28245
|
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
@@ -28192,7 +28248,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28192
28248
|
timing.doneReported = true;
|
|
28193
28249
|
var end = timing.endTime != null ? timing.endTime : timing.startTime;
|
|
28194
28250
|
var playedMs = Math.round((end - timing.startTime) * 1000);
|
|
28195
|
-
|
|
28251
|
+
_this12.emit('segmentDone', {
|
|
28196
28252
|
segmentId: timing.segmentId,
|
|
28197
28253
|
status: 'finished',
|
|
28198
28254
|
playedMs: playedMs
|
|
@@ -28204,7 +28260,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28204
28260
|
} finally {
|
|
28205
28261
|
_iterator3.f();
|
|
28206
28262
|
}
|
|
28207
|
-
|
|
28263
|
+
_this12.isCheckingTranscripts = false;
|
|
28208
28264
|
console.log('📝 AudioPlayer: Transcript checker stopped');
|
|
28209
28265
|
}
|
|
28210
28266
|
};
|
|
@@ -28368,8 +28424,9 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
28368
28424
|
/* harmony import */ var _core_ClientToolsRegistry_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../core/ClientToolsRegistry.js */ "./src/core/ClientToolsRegistry.js");
|
|
28369
28425
|
/* harmony import */ var _core_ClientScriptManager_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../core/ClientScriptManager.js */ "./src/core/ClientScriptManager.js");
|
|
28370
28426
|
/* harmony import */ var _core_helloFlavor_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../core/helloFlavor.js */ "./src/core/helloFlavor.js");
|
|
28371
|
-
/* harmony import */ var
|
|
28372
|
-
/* harmony import */ var
|
|
28427
|
+
/* harmony import */ var _hopPlatform_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./hopPlatform.js */ "./src/v2/hopPlatform.js");
|
|
28428
|
+
/* harmony import */ var _utils_screenshot_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../utils/screenshot.js */ "./src/utils/screenshot.js");
|
|
28429
|
+
/* harmony import */ var _utils_visual_tools_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../utils/visual-tools.js */ "./src/utils/visual-tools.js");
|
|
28373
28430
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
28374
28431
|
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
28375
28432
|
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
@@ -28405,6 +28462,7 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
|
|
|
28405
28462
|
|
|
28406
28463
|
|
|
28407
28464
|
|
|
28465
|
+
|
|
28408
28466
|
/**
|
|
28409
28467
|
|
|
28410
28468
|
* VoiceSDK v2 - Multi-codec speech-to-speech SDK
|
|
@@ -28502,23 +28560,20 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28502
28560
|
// Audio constraints for getUserMedia (optional)
|
|
28503
28561
|
// If not provided, defaults will be used: echoCancellation: true, noiseSuppression: true, autoGainControl: true
|
|
28504
28562
|
audioConstraints: config.audioConstraints || null,
|
|
28505
|
-
// Last-hop TTS playback via hidden <audio> (AEC far-end).
|
|
28506
|
-
//
|
|
28507
|
-
// QA/debug override wins over config: ?ttp_hop=0
|
|
28508
|
-
//
|
|
28563
|
+
// Last-hop TTS playback via hidden <audio> (AEC far-end). Platform default
|
|
28564
|
+
// (hop on mobile/macOS only) applies when unset; set explicitly to force.
|
|
28565
|
+
// QA/debug override wins over config: ?ttp_hop=0|1 — mirrored to
|
|
28566
|
+
// sessionStorage 'ttp_hop_pref' so it survives same-origin full page loads
|
|
28567
|
+
// (Borusan navigate_to_form) — then localStorage 'ttp_hop'.
|
|
28509
28568
|
htmlAudioPlayback: function () {
|
|
28510
28569
|
try {
|
|
28511
|
-
var
|
|
28512
|
-
|
|
28513
|
-
|
|
28514
|
-
|
|
28515
|
-
return flag === '1';
|
|
28516
|
-
}
|
|
28517
|
-
if (flag !== null && flag !== undefined) {
|
|
28518
|
-
console.log("\uD83D\uDD27 VoiceSDK v2: ttp_hop ignored (value '".concat(flag, "', expected '0' or '1')"));
|
|
28570
|
+
var override = (0,_hopPlatform_js__WEBPACK_IMPORTED_MODULE_7__.readTtpHopOverride)(typeof window !== 'undefined' ? window : null);
|
|
28571
|
+
if (override !== null) {
|
|
28572
|
+
console.log("\uD83D\uDD27 VoiceSDK v2: ttp_hop override \u2192 htmlAudioPlayback=".concat(override));
|
|
28573
|
+
return override;
|
|
28519
28574
|
}
|
|
28520
28575
|
} catch (e) {
|
|
28521
|
-
console.log('🔧 VoiceSDK v2: ttp_hop check threw
|
|
28576
|
+
console.log('🔧 VoiceSDK v2: ttp_hop check threw:', e && e.message);
|
|
28522
28577
|
}
|
|
28523
28578
|
// Pass through undefined so AudioPlayer applies the platform default
|
|
28524
28579
|
return config.htmlAudioPlayback;
|
|
@@ -28665,7 +28720,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28665
28720
|
key: "_registerBuiltInTools",
|
|
28666
28721
|
value: function _registerBuiltInTools() {
|
|
28667
28722
|
try {
|
|
28668
|
-
(0,
|
|
28723
|
+
(0,_utils_visual_tools_js__WEBPACK_IMPORTED_MODULE_9__.registerVisualTools)(this.clientToolsRegistry);
|
|
28669
28724
|
} catch (error) {
|
|
28670
28725
|
console.error('❌ VoiceSDK: Error registering built-in tools:', error);
|
|
28671
28726
|
console.error(' Error details:', error.message, error.stack);
|
|
@@ -28991,6 +29046,12 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28991
29046
|
key: "setupAudioPlayerEvents",
|
|
28992
29047
|
value: function setupAudioPlayerEvents() {
|
|
28993
29048
|
var _this3 = this;
|
|
29049
|
+
// The initial client_audio_info snapshot (at recordingStarted) predates
|
|
29050
|
+
// HTML-hop establishment, so its htmlAudioRouteActive/htmlAudioPlayOk are
|
|
29051
|
+
// always false. Re-report once the route outcome is known.
|
|
29052
|
+
this.audioPlayer.on('htmlAudioRoute', function (info) {
|
|
29053
|
+
_this3._sendClientAudioInfo(info);
|
|
29054
|
+
});
|
|
28994
29055
|
this.audioPlayer.on('playbackStarted', function (info) {
|
|
28995
29056
|
_this3.isPlaying = true;
|
|
28996
29057
|
|
|
@@ -29417,7 +29478,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29417
29478
|
// iOS in-app webviews lack "Safari" in the UA (real Safari always has it).
|
|
29418
29479
|
var webview = isAndroid && (/\bwv\b/.test(ua) || /Version\/[\d.]+.*Chrome/.test(ua)) || isIos && !/Safari/i.test(ua) || false;
|
|
29419
29480
|
var env = {
|
|
29420
|
-
sdkVersion: true ? "2.48.
|
|
29481
|
+
sdkVersion: true ? "2.48.18" : 0,
|
|
29421
29482
|
ua: ua,
|
|
29422
29483
|
platform: (uaData === null || uaData === void 0 ? void 0 : uaData.platform) || navigator.platform || '',
|
|
29423
29484
|
mobile: (_uaData$mobile = uaData === null || uaData === void 0 ? void 0 : uaData.mobile) !== null && _uaData$mobile !== void 0 ? _uaData$mobile : isAndroid || isIos,
|
|
@@ -29432,7 +29493,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29432
29493
|
} catch (e) {
|
|
29433
29494
|
console.warn('⚠️ VoiceSDK v2: Failed to build client env:', e);
|
|
29434
29495
|
return {
|
|
29435
|
-
sdkVersion: true ? "2.48.
|
|
29496
|
+
sdkVersion: true ? "2.48.18" : 0
|
|
29436
29497
|
};
|
|
29437
29498
|
}
|
|
29438
29499
|
}
|
|
@@ -29446,12 +29507,14 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29446
29507
|
*/
|
|
29447
29508
|
}, {
|
|
29448
29509
|
key: "_sendClientAudioInfo",
|
|
29449
|
-
value: function _sendClientAudioInfo() {
|
|
29510
|
+
value: function _sendClientAudioInfo(routeUpdate) {
|
|
29450
29511
|
try {
|
|
29451
29512
|
var _this$audioRecorder, _this$audioRecorder$g, _s$echoCancellation, _s$noiseSuppression, _s$autoGainControl, _s$voiceIsolation, _s$sampleRate, _s$channelCount, _this$audioRecorder2, _this$audioPlayer, _this$audioRecorder3, _this$audioPlayer2, _this$audioPlayer2$ge;
|
|
29452
29513
|
var track = (_this$audioRecorder = this.audioRecorder) === null || _this$audioRecorder === void 0 || (_this$audioRecorder = _this$audioRecorder.mediaStream) === null || _this$audioRecorder === void 0 || (_this$audioRecorder$g = _this$audioRecorder.getAudioTracks) === null || _this$audioRecorder$g === void 0 ? void 0 : _this$audioRecorder$g.call(_this$audioRecorder)[0];
|
|
29453
|
-
|
|
29454
|
-
|
|
29514
|
+
// Route updates must go out even before the mic track exists — the hop
|
|
29515
|
+
// state is the whole point of the follow-up.
|
|
29516
|
+
if (!track && !routeUpdate) return;
|
|
29517
|
+
var s = track && track.getSettings ? track.getSettings() : {};
|
|
29455
29518
|
var audio = _objectSpread({
|
|
29456
29519
|
aec: (_s$echoCancellation = s.echoCancellation) !== null && _s$echoCancellation !== void 0 ? _s$echoCancellation : null,
|
|
29457
29520
|
ns: (_s$noiseSuppression = s.noiseSuppression) !== null && _s$noiseSuppression !== void 0 ? _s$noiseSuppression : null,
|
|
@@ -29459,11 +29522,15 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29459
29522
|
voiceIsolation: (_s$voiceIsolation = s.voiceIsolation) !== null && _s$voiceIsolation !== void 0 ? _s$voiceIsolation : null,
|
|
29460
29523
|
trackRate: (_s$sampleRate = s.sampleRate) !== null && _s$sampleRate !== void 0 ? _s$sampleRate : null,
|
|
29461
29524
|
channels: (_s$channelCount = s.channelCount) !== null && _s$channelCount !== void 0 ? _s$channelCount : null,
|
|
29462
|
-
mic: track.label || null,
|
|
29525
|
+
mic: track ? track.label || null : null,
|
|
29463
29526
|
captureCtxRate: ((_this$audioRecorder2 = this.audioRecorder) === null || _this$audioRecorder2 === void 0 || (_this$audioRecorder2 = _this$audioRecorder2.audioContext) === null || _this$audioRecorder2 === void 0 ? void 0 : _this$audioRecorder2.sampleRate) || null,
|
|
29464
29527
|
playbackCtxRate: ((_this$audioPlayer = this.audioPlayer) === null || _this$audioPlayer === void 0 || (_this$audioPlayer = _this$audioPlayer.audioContext) === null || _this$audioPlayer === void 0 ? void 0 : _this$audioPlayer.sampleRate) || null,
|
|
29465
29528
|
constraintsFallback: ((_this$audioRecorder3 = this.audioRecorder) === null || _this$audioRecorder3 === void 0 || (_this$audioRecorder3 = _this$audioRecorder3.mediaStream) === null || _this$audioRecorder3 === void 0 ? void 0 : _this$audioRecorder3._ttpConstraintsFallback) === true
|
|
29466
29529
|
}, ((_this$audioPlayer2 = this.audioPlayer) === null || _this$audioPlayer2 === void 0 || (_this$audioPlayer2$ge = _this$audioPlayer2.getHtmlAudioPlaybackInfo) === null || _this$audioPlayer2$ge === void 0 ? void 0 : _this$audioPlayer2$ge.call(_this$audioPlayer2)) || {});
|
|
29530
|
+
if (routeUpdate && routeUpdate.state) {
|
|
29531
|
+
audio.routeUpdate = routeUpdate.state; // 'established' | 'fallback' | 'play_pending'
|
|
29532
|
+
if (routeUpdate.reason) audio.routeFallbackReason = routeUpdate.reason;
|
|
29533
|
+
}
|
|
29467
29534
|
this.sendMessage({
|
|
29468
29535
|
t: 'client_audio_info',
|
|
29469
29536
|
audio: audio
|
|
@@ -29574,7 +29641,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29574
29641
|
|
|
29575
29642
|
// Include SDK build time for debugging
|
|
29576
29643
|
if (true) {
|
|
29577
|
-
helloMessage.lastBuildTime = "2026-08-
|
|
29644
|
+
helloMessage.lastBuildTime = "2026-08-27T12:25:20.756Z";
|
|
29578
29645
|
}
|
|
29579
29646
|
|
|
29580
29647
|
// Client environment (device/browser/webview) for backend logs + Langfuse metadata
|
|
@@ -29818,7 +29885,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29818
29885
|
case 'get_page_context':
|
|
29819
29886
|
// Handle get_page_context request from backend
|
|
29820
29887
|
console.log('📖 [VISUAL ASSISTANT] Backend requested page context');
|
|
29821
|
-
(0,
|
|
29888
|
+
(0,_utils_visual_tools_js__WEBPACK_IMPORTED_MODULE_9__.extractPageContext)().then(function (pageContext) {
|
|
29822
29889
|
// Use existing DOM scanner
|
|
29823
29890
|
_this6.sendMessage({
|
|
29824
29891
|
t: 'page_context',
|
|
@@ -29839,7 +29906,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29839
29906
|
console.log('📸 [VISUAL ASSISTANT] Backend requested screenshot');
|
|
29840
29907
|
try {
|
|
29841
29908
|
// Use existing screenshot capture function
|
|
29842
|
-
(0,
|
|
29909
|
+
(0,_utils_screenshot_js__WEBPACK_IMPORTED_MODULE_8__.captureScreenshot)().then(function (screenshot) {
|
|
29843
29910
|
_this6.sendMessage({
|
|
29844
29911
|
t: 'screenshot',
|
|
29845
29912
|
screenshot: {
|
|
@@ -32199,6 +32266,99 @@ var PCMUCodec = /*#__PURE__*/function () {
|
|
|
32199
32266
|
|
|
32200
32267
|
/***/ }),
|
|
32201
32268
|
|
|
32269
|
+
/***/ "./src/v2/hopPlatform.js":
|
|
32270
|
+
/*!*******************************!*\
|
|
32271
|
+
!*** ./src/v2/hopPlatform.js ***!
|
|
32272
|
+
\*******************************/
|
|
32273
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
32274
|
+
|
|
32275
|
+
"use strict";
|
|
32276
|
+
__webpack_require__.r(__webpack_exports__);
|
|
32277
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
32278
|
+
/* harmony export */ TTP_HOP_SESSION_KEY: () => (/* binding */ TTP_HOP_SESSION_KEY),
|
|
32279
|
+
/* harmony export */ isMacDesktopUa: () => (/* binding */ isMacDesktopUa),
|
|
32280
|
+
/* harmony export */ isMobileUa: () => (/* binding */ isMobileUa),
|
|
32281
|
+
/* harmony export */ needsHtmlAudioHopForAec: () => (/* binding */ needsHtmlAudioHopForAec),
|
|
32282
|
+
/* harmony export */ readTtpHopOverride: () => (/* binding */ readTtpHopOverride)
|
|
32283
|
+
/* harmony export */ });
|
|
32284
|
+
/**
|
|
32285
|
+
* HTML-audio-hop platform policy + the ttp_hop QA override.
|
|
32286
|
+
*
|
|
32287
|
+
* The "hop" is AudioContext → MediaStreamDestination → hidden <audio>, used so
|
|
32288
|
+
* the browser's echo canceller sees agent TTS as a far-end reference. Chrome
|
|
32289
|
+
* renders that live stream with adaptive jitter-buffer speed control, which
|
|
32290
|
+
* audibly wobbles on Windows/Linux desktop — so the hop defaults ON only where
|
|
32291
|
+
* Web Audio → destination genuinely lacks an AEC reference (mobile + macOS).
|
|
32292
|
+
*
|
|
32293
|
+
* Kept DOM-free (all inputs passed in) so the policy is unit-testable without
|
|
32294
|
+
* a browser: see test/hop-platform.test.mjs.
|
|
32295
|
+
*/
|
|
32296
|
+
|
|
32297
|
+
/** sessionStorage key mirroring an explicit ?ttp_hop= URL value (see readTtpHopOverride). */
|
|
32298
|
+
var TTP_HOP_SESSION_KEY = 'ttp_hop_pref';
|
|
32299
|
+
function isMobileUa(ua) {
|
|
32300
|
+
return /Android|iPhone|iPad|iPod/i.test(ua || '');
|
|
32301
|
+
}
|
|
32302
|
+
function isMacDesktopUa(ua, platform) {
|
|
32303
|
+
if (/iPhone|iPad|iPod/i.test(ua || '')) return false;
|
|
32304
|
+
return /mac/i.test(platform || '') || /Mac OS X/i.test(ua || '');
|
|
32305
|
+
}
|
|
32306
|
+
|
|
32307
|
+
/**
|
|
32308
|
+
* Hop default: on only where Web Audio destination lacks an AEC far-end
|
|
32309
|
+
* reference (mobile + macOS). Windows/Linux/ChromeOS desktop: off — Chrome-wide
|
|
32310
|
+
* AEC already covers speaker echo there, and the hop only adds speed wobble.
|
|
32311
|
+
* Unknown/empty environment: off (fail toward the stable direct path).
|
|
32312
|
+
*/
|
|
32313
|
+
function needsHtmlAudioHopForAec(ua, platform) {
|
|
32314
|
+
return isMobileUa(ua) || isMacDesktopUa(ua, platform);
|
|
32315
|
+
}
|
|
32316
|
+
|
|
32317
|
+
/**
|
|
32318
|
+
* QA/debug override for the hop route. Returns true (force hop on), false
|
|
32319
|
+
* (force off), or null (no override — apply config/platform default).
|
|
32320
|
+
*
|
|
32321
|
+
* Precedence: URL ?ttp_hop=0|1 → sessionStorage mirror → localStorage 'ttp_hop'.
|
|
32322
|
+
*
|
|
32323
|
+
* An explicit URL value is mirrored into sessionStorage (TTP_HOP_SESSION_KEY)
|
|
32324
|
+
* so it survives same-origin full page loads that drop the query string —
|
|
32325
|
+
* Borusan's navigate_to_form does window.location.href = '/path' (call
|
|
32326
|
+
* 84b5af7d), which used to silently re-apply the platform default mid-call.
|
|
32327
|
+
* The mirror dies with the tab; localStorage remains the sticky manual knob
|
|
32328
|
+
* and ranks below the mirror because the URL value is the more recent intent.
|
|
32329
|
+
*
|
|
32330
|
+
* Every storage touch is individually guarded: browsers can block one storage
|
|
32331
|
+
* area but not another, and a blocked sessionStorage must not cost us the
|
|
32332
|
+
* localStorage fallback.
|
|
32333
|
+
*/
|
|
32334
|
+
function readTtpHopOverride(win) {
|
|
32335
|
+
var w = win || (typeof window !== 'undefined' ? window : null);
|
|
32336
|
+
if (!w) return null;
|
|
32337
|
+
var flag = null;
|
|
32338
|
+
try {
|
|
32339
|
+
flag = new URLSearchParams(w.location.search).get('ttp_hop');
|
|
32340
|
+
} catch (e) {/* no location in this env */}
|
|
32341
|
+
if (flag === '0' || flag === '1') {
|
|
32342
|
+
try {
|
|
32343
|
+
w.sessionStorage.setItem(TTP_HOP_SESSION_KEY, flag);
|
|
32344
|
+
} catch (e) {/* storage blocked */}
|
|
32345
|
+
return flag === '1';
|
|
32346
|
+
}
|
|
32347
|
+
var mirrored = null;
|
|
32348
|
+
try {
|
|
32349
|
+
mirrored = w.sessionStorage.getItem(TTP_HOP_SESSION_KEY);
|
|
32350
|
+
} catch (e) {/* storage blocked */}
|
|
32351
|
+
if (mirrored === '0' || mirrored === '1') return mirrored === '1';
|
|
32352
|
+
var stored = null;
|
|
32353
|
+
try {
|
|
32354
|
+
stored = w.localStorage.getItem('ttp_hop');
|
|
32355
|
+
} catch (e) {/* storage blocked */}
|
|
32356
|
+
if (stored === '0' || stored === '1') return stored === '1';
|
|
32357
|
+
return null;
|
|
32358
|
+
}
|
|
32359
|
+
|
|
32360
|
+
/***/ }),
|
|
32361
|
+
|
|
32202
32362
|
/***/ "./src/v2/utils/AudioFormatConverter.js":
|
|
32203
32363
|
/*!**********************************************!*\
|
|
32204
32364
|
!*** ./src/v2/utils/AudioFormatConverter.js ***!
|
|
@@ -35803,7 +35963,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
35803
35963
|
return;
|
|
35804
35964
|
}
|
|
35805
35965
|
this._ensureAboutStyles();
|
|
35806
|
-
var version = true ? "2.48.
|
|
35966
|
+
var version = true ? "2.48.18" : 0;
|
|
35807
35967
|
var convId = this._getLastConversationId();
|
|
35808
35968
|
var t = function t(k, fb) {
|
|
35809
35969
|
try {
|