ttp-agent-sdk 2.47.2 → 2.48.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10748,7 +10748,7 @@ var ClientScriptManager = /*#__PURE__*/function () {
10748
10748
  _ref2,
10749
10749
  toolCallId,
10750
10750
  toolName,
10751
- _ref3,
10751
+ _ClientToolsRegistry$,
10752
10752
  action,
10753
10753
  args,
10754
10754
  startedAt,
@@ -10765,7 +10765,7 @@ var ClientScriptManager = /*#__PURE__*/function () {
10765
10765
  case 0:
10766
10766
  conversationId = _args.length > 1 && _args[1] !== undefined ? _args[1] : null;
10767
10767
  _ref2 = message || {}, toolCallId = _ref2.toolCallId, toolName = _ref2.toolName;
10768
- _ref3 = message && message.parameters || {}, action = _ref3.action, args = _ref3.args;
10768
+ _ClientToolsRegistry$ = _ClientToolsRegistry_js__WEBPACK_IMPORTED_MODULE_0__["default"].resolveParameters(message), action = _ClientToolsRegistry$.action, args = _ClientToolsRegistry$.args;
10769
10769
  startedAt = Date.now();
10770
10770
  console.log("".concat(LOG).concat(this._tag(), " client_tool_call dispatch action=").concat(action, " toolCallId=").concat(toolCallId));
10771
10771
  sendError = function sendError(error, errorCode) {
@@ -10888,11 +10888,11 @@ var ClientScriptManager = /*#__PURE__*/function () {
10888
10888
  key: "handleRunPartnerScript",
10889
10889
  value: (function () {
10890
10890
  var _handleRunPartnerScript = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(message) {
10891
- var _ref4, requestId, partnerId, action, args, startedAt, result, elapsedMs, ok, serializedSize, sizeKB, limitKB, reason, _elapsedMs, _t2;
10891
+ var _ref3, requestId, partnerId, action, args, startedAt, result, elapsedMs, ok, serializedSize, sizeKB, limitKB, reason, _elapsedMs, _t2;
10892
10892
  return _regenerator().w(function (_context2) {
10893
10893
  while (1) switch (_context2.p = _context2.n) {
10894
10894
  case 0:
10895
- _ref4 = message || {}, requestId = _ref4.requestId, partnerId = _ref4.partnerId, action = _ref4.action;
10895
+ _ref3 = message || {}, requestId = _ref3.requestId, partnerId = _ref3.partnerId, action = _ref3.action;
10896
10896
  args = message && message.args || {};
10897
10897
  if (requestId) {
10898
10898
  _context2.n = 1;
@@ -11009,7 +11009,8 @@ var ClientScriptManager = /*#__PURE__*/function () {
11009
11009
  }, {
11010
11010
  key: "isClientToolsToolCall",
11011
11011
  value: function isClientToolsToolCall(message) {
11012
- return !!message && message.toolName === 'run_partner_script' && !!message.parameters && message.parameters.partner_id === CLIENT_TOOLS_PARTNER_ID;
11012
+ var parameters = _ClientToolsRegistry_js__WEBPACK_IMPORTED_MODULE_0__["default"].resolveParameters(message);
11013
+ return !!message && message.toolName === 'run_partner_script' && parameters.partner_id === CLIENT_TOOLS_PARTNER_ID;
11013
11014
  }
11014
11015
  }]);
11015
11016
  }();
@@ -11127,6 +11128,20 @@ var ClientToolsRegistry = /*#__PURE__*/function () {
11127
11128
  return Array.from(this.handlers.keys());
11128
11129
  }
11129
11130
 
11131
+ /**
11132
+ * Resolve the object passed to a tool handler from a `client_tool_call` frame.
11133
+ *
11134
+ * The backend DTO (`ClientToolCallMessage`) serializes LLM args on
11135
+ * `parameters`. Handlers destructure that object (`params.selector`, …), so
11136
+ * `null` / a JSON string / an alternate field name would look like "params
11137
+ * aren't working". Always return a plain object.
11138
+ *
11139
+ * @param {Object} message
11140
+ * @returns {Object}
11141
+ */
11142
+ }, {
11143
+ key: "handleToolCall",
11144
+ value: (
11130
11145
  /**
11131
11146
  * Handle incoming client_tool_call message from backend
11132
11147
  * @param {Object} message - The tool call message
@@ -11134,19 +11149,19 @@ var ClientToolsRegistry = /*#__PURE__*/function () {
11134
11149
  * @param {string} message.toolName - Name of the tool to execute
11135
11150
  * @param {Object} message.parameters - Parameters for the tool
11136
11151
  */
11137
- }, {
11138
- key: "handleToolCall",
11139
- value: (function () {
11152
+ function () {
11140
11153
  var _handleToolCall = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(message) {
11141
- var toolCallId, toolName, parameters, startTime, receiveTimestamp, handler, registeredTools, result, executionTimeMs, _error$message, _error$message2, _executionTimeMs, errorCode, _t;
11154
+ var _ref, toolCallId, toolName, parameters, startTime, receiveTimestamp, handler, registeredTools, result, executionTimeMs, _error$message, _error$message2, _executionTimeMs, errorCode, _t;
11142
11155
  return _regenerator().w(function (_context) {
11143
11156
  while (1) switch (_context.p = _context.n) {
11144
11157
  case 0:
11145
- toolCallId = message.toolCallId, toolName = message.toolName, parameters = message.parameters;
11158
+ _ref = message || {}, toolCallId = _ref.toolCallId, toolName = _ref.toolName;
11159
+ parameters = ClientToolsRegistry.resolveParameters(message);
11146
11160
  startTime = Date.now();
11147
11161
  receiveTimestamp = new Date().toISOString();
11148
11162
  console.log("\uD83D\uDD27 ClientTools: [".concat(receiveTimestamp, "] Received tool call '").concat(toolName, "' (id: ").concat(toolCallId, ")"));
11149
11163
  console.log(" \uD83D\uDCCB Full message received:", JSON.stringify(message, null, 2));
11164
+ console.log(" \uD83D\uDCCB Resolved parameters:", parameters);
11150
11165
  console.log(" \u23F1\uFE0F Start time: ".concat(startTime, "ms (").concat(new Date(startTime).toISOString(), ")"));
11151
11166
 
11152
11167
  // Check if handler exists
@@ -11276,6 +11291,34 @@ var ClientToolsRegistry = /*#__PURE__*/function () {
11276
11291
  value: function setSendMessage(sendMessage) {
11277
11292
  this.sendMessage = sendMessage;
11278
11293
  }
11294
+ }], [{
11295
+ key: "resolveParameters",
11296
+ value: function resolveParameters(message) {
11297
+ if (!message || _typeof(message) !== 'object') return {};
11298
+ var raw = message.parameters;
11299
+ if (raw == null) raw = message.params;
11300
+ if (raw == null) raw = message.args;
11301
+ if (raw == null) return {};
11302
+ if (typeof raw === 'string') {
11303
+ var trimmed = raw.trim();
11304
+ if (!trimmed) return {};
11305
+ try {
11306
+ var parsed = JSON.parse(trimmed);
11307
+ if (parsed !== null && _typeof(parsed) === 'object') return parsed;
11308
+ return {
11309
+ value: parsed
11310
+ };
11311
+ } catch (_unused2) {
11312
+ return {
11313
+ value: raw
11314
+ };
11315
+ }
11316
+ }
11317
+ if (_typeof(raw) === 'object') return raw;
11318
+ return {
11319
+ value: raw
11320
+ };
11321
+ }
11279
11322
  }]);
11280
11323
  }();
11281
11324
  _defineProperty(ClientToolsRegistry, "MAX_RESULT_SIZE", 512000);
@@ -11384,6 +11427,7 @@ __webpack_require__.r(__webpack_exports__);
11384
11427
  /* harmony import */ var _EventEmitter_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./EventEmitter.js */ "./src/core/EventEmitter.js");
11385
11428
  /* harmony import */ var _ClientToolsRegistry_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ClientToolsRegistry.js */ "./src/core/ClientToolsRegistry.js");
11386
11429
  /* harmony import */ var _ClientScriptManager_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ClientScriptManager.js */ "./src/core/ClientScriptManager.js");
11430
+ /* harmony import */ var _helloFlavor_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./helloFlavor.js */ "./src/core/helloFlavor.js");
11387
11431
  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); }
11388
11432
  function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
11389
11433
  function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
@@ -11416,9 +11460,12 @@ function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf
11416
11460
 
11417
11461
 
11418
11462
 
11463
+
11419
11464
  var RECONNECT_DELAY_MS = 1000;
11420
11465
  var MAX_RECONNECT_ATTEMPTS = 5;
11421
11466
  var TEXT_CHAT_PATH = '/chat/text';
11467
+ /** Same interval as VoiceSDK — keeps proxies/LBs from dropping an idle text socket. */
11468
+ var KEEP_ALIVE_MS = 30000;
11422
11469
  /** Production voice/text base (path swapped to /chat/text); matches VoiceSDK v2 default. */
11423
11470
  var DEFAULT_WEBSOCKET_BASE_URL = 'wss://speech.talktopc.com/ws/conv';
11424
11471
  var TextChatSDK = /*#__PURE__*/function (_EventEmitter) {
@@ -11440,6 +11487,7 @@ var TextChatSDK = /*#__PURE__*/function (_EventEmitter) {
11440
11487
  _this.connecting = false;
11441
11488
  _this.reconnectAttempts = 0;
11442
11489
  _this.intentionalClose = false;
11490
+ _this._keepAliveInterval = null;
11443
11491
  _this.fullResponseBuffer = '';
11444
11492
  _this.queue = [];
11445
11493
  _this.inFlight = false;
@@ -11604,6 +11652,7 @@ var TextChatSDK = /*#__PURE__*/function (_EventEmitter) {
11604
11652
  _this2.connected = true;
11605
11653
  _this2.reconnectAttempts = 0;
11606
11654
  console.log('[TextChatSDK] Connected');
11655
+ _this2._startKeepAlive();
11607
11656
 
11608
11657
  // Send hello immediately on connect (same fields as voice SDK v2 hello).
11609
11658
  _this2.sendHelloMessage();
@@ -11719,13 +11768,16 @@ var TextChatSDK = /*#__PURE__*/function (_EventEmitter) {
11719
11768
  // Non-JSON or parse error; ignore
11720
11769
  }
11721
11770
  };
11771
+
11772
+ // Browser WebSocket.onerror is an Event, not an Error — emitting it would
11773
+ // render as the chat bubble "[object Event]". onclose handles recovery.
11722
11774
  this.ws.onerror = function (e) {
11723
11775
  console.error('[TextChatSDK] WebSocket error:', e);
11724
- _this2.emit('error', e);
11725
11776
  };
11726
11777
  this.ws.onclose = function (event) {
11727
11778
  _this2.connected = false;
11728
11779
  _this2.connecting = false;
11780
+ _this2._stopKeepAlive();
11729
11781
  console.log('[TextChatSDK] Disconnected, code:', event.code, 'reason:', event.reason);
11730
11782
 
11731
11783
  // Domain whitelist error — don't reconnect
@@ -11963,9 +12015,10 @@ var TextChatSDK = /*#__PURE__*/function (_EventEmitter) {
11963
12015
  v: 2
11964
12016
  };
11965
12017
 
11966
- // Flavor (partner tools: hotels, restaurants, ecommerce, etc.)
11967
- if (this.config.flavor) {
11968
- helloMessage.flavor = this.config.flavor;
12018
+ // Partner fields only — UI-only keys like callView stay local (backend Flavor DTO rejects them)
12019
+ var wireFlavor = (0,_helloFlavor_js__WEBPACK_IMPORTED_MODULE_3__.flavorForHello)(this.config.flavor);
12020
+ if (wireFlavor) {
12021
+ helloMessage.flavor = wireFlavor;
11969
12022
  }
11970
12023
 
11971
12024
  // Variables (template variables injected into agent prompt)
@@ -11994,7 +12047,7 @@ var TextChatSDK = /*#__PURE__*/function (_EventEmitter) {
11994
12047
 
11995
12048
  // SDK build time for debugging
11996
12049
  if (true) {
11997
- helloMessage.lastBuildTime = "2026-07-30T20:53:20.013Z";
12050
+ helloMessage.lastBuildTime = "2026-08-20T12:21:14.185Z";
11998
12051
  }
11999
12052
  try {
12000
12053
  this.ws.send(JSON.stringify(helloMessage));
@@ -12023,6 +12076,27 @@ var TextChatSDK = /*#__PURE__*/function (_EventEmitter) {
12023
12076
  };
12024
12077
  }
12025
12078
  }
12079
+ }, {
12080
+ key: "_startKeepAlive",
12081
+ value: function _startKeepAlive() {
12082
+ var _this4 = this;
12083
+ this._stopKeepAlive();
12084
+ this._keepAliveInterval = setInterval(function () {
12085
+ if (_this4.connected && _this4.ws && _this4.ws.readyState === WebSocket.OPEN) {
12086
+ _this4.sendRaw({
12087
+ t: 'ping'
12088
+ });
12089
+ }
12090
+ }, KEEP_ALIVE_MS);
12091
+ }
12092
+ }, {
12093
+ key: "_stopKeepAlive",
12094
+ value: function _stopKeepAlive() {
12095
+ if (this._keepAliveInterval) {
12096
+ clearInterval(this._keepAliveInterval);
12097
+ this._keepAliveInterval = null;
12098
+ }
12099
+ }
12026
12100
  }, {
12027
12101
  key: "persistConversationId",
12028
12102
  value: function persistConversationId(conversationId) {
@@ -12055,6 +12129,7 @@ var TextChatSDK = /*#__PURE__*/function (_EventEmitter) {
12055
12129
  this.queue = [];
12056
12130
  this.inFlight = false;
12057
12131
  this._currentTask = null;
12132
+ this._stopKeepAlive();
12058
12133
  if (this.ws) {
12059
12134
  try {
12060
12135
  this.ws.close();
@@ -12622,6 +12697,35 @@ var webSocketSingleton = new WebSocketSingleton();
12622
12697
 
12623
12698
  /***/ }),
12624
12699
 
12700
+ /***/ "./src/core/helloFlavor.js":
12701
+ /*!*********************************!*\
12702
+ !*** ./src/core/helloFlavor.js ***!
12703
+ \*********************************/
12704
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
12705
+
12706
+ "use strict";
12707
+ __webpack_require__.r(__webpack_exports__);
12708
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
12709
+ /* harmony export */ flavorForHello: () => (/* binding */ flavorForHello)
12710
+ /* harmony export */ });
12711
+ 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); }
12712
+ /**
12713
+ * Flavor fields the conversation backend Flavor DTO understands.
12714
+ * UI-only keys (callView, …) stay on the widget config and must not go on hello.
12715
+ */
12716
+ function flavorForHello(flavor) {
12717
+ if (!flavor || _typeof(flavor) !== 'object') return null;
12718
+ var out = {};
12719
+ if (flavor.type != null && String(flavor.type).trim() !== '') out.type = flavor.type;
12720
+ if (flavor.partnerId != null && String(flavor.partnerId).trim() !== '') out.partnerId = flavor.partnerId;
12721
+ if (flavor.shopifyDomain != null && String(flavor.shopifyDomain).trim() !== '') {
12722
+ out.shopifyDomain = flavor.shopifyDomain;
12723
+ }
12724
+ return Object.keys(out).length ? out : null;
12725
+ }
12726
+
12727
+ /***/ }),
12728
+
12625
12729
  /***/ "./src/ecommerce/CartSummary.js":
12626
12730
  /*!**************************************!*\
12627
12731
  !*** ./src/ecommerce/CartSummary.js ***!
@@ -21253,8 +21357,8 @@ var VoiceSDK = _v2_VoiceSDK_js__WEBPACK_IMPORTED_MODULE_0__["default"];
21253
21357
 
21254
21358
 
21255
21359
  // Version - injected at build time from package.json via webpack DefinePlugin
21256
- var VERSION = "2.47.2";
21257
- var BUILD_TIME = "2026-07-30T20:53:20.013Z";
21360
+ var VERSION = "2.48.0";
21361
+ var BUILD_TIME = "2026-08-20T12:21:14.185Z";
21258
21362
  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;');
21259
21363
 
21260
21364
  // Named exports
@@ -25430,6 +25534,9 @@ __webpack_require__.r(__webpack_exports__);
25430
25534
  /* harmony import */ var _codecs_PCMUCodec_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./codecs/PCMUCodec.js */ "./src/v2/codecs/PCMUCodec.js");
25431
25535
  /* harmony import */ var _codecs_PCMACodec_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./codecs/PCMACodec.js */ "./src/v2/codecs/PCMACodec.js");
25432
25536
  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); }
25537
+ 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; }
25538
+ 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; }
25539
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
25433
25540
  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; } } }; }
25434
25541
  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; } }
25435
25542
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
@@ -25505,6 +25612,15 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
25505
25612
  _this.gainNode = null; // GainNode for volume/mute control
25506
25613
  _this._audioContextPrimed = false; // Track if AudioContext has been primed with silent buffer
25507
25614
 
25615
+ // Last-hop AEC route (ElevenLabs WS pattern): play through a hidden
25616
+ // HTMLAudioElement instead of AudioContext.destination so Chrome/Safari
25617
+ // can use TTS as the echo-cancellation far-end. Scheduling / source.stop
25618
+ // still live on the AudioContext. Opt out with htmlAudioPlayback:false.
25619
+ _this._htmlAudioEl = null;
25620
+ _this._mediaStreamDest = null;
25621
+ _this._htmlAudioRouteActive = false;
25622
+ _this._htmlAudioPlayOk = false;
25623
+
25508
25624
  // Track temporary listener in waitForAudioContextReady() for cleanup
25509
25625
  _this._waitForReadyStateHandler = null;
25510
25626
  _this.audioQueue = [];
@@ -25920,6 +26036,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
25920
26036
  return _context4.a(2);
25921
26037
  case 2:
25922
26038
  this.isSchedulingFrames = true;
26039
+ this._ensureHtmlAudioPlaying();
25923
26040
 
25924
26041
  // Schedule multiple frames ahead to ensure continuous playback
25925
26042
  // This prevents gaps when frames arrive slowly or there are timing delays
@@ -26779,6 +26896,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
26779
26896
  } catch (_) {/* ignore */}
26780
26897
  this.gainNode = null;
26781
26898
  }
26899
+ this._teardownHtmlAudioRoute();
26782
26900
  if (this.audioContext === _sharedPlayerContext) {
26783
26901
  _sharedPlayerContext = null;
26784
26902
  _sharedPlayerSampleRate = null;
@@ -26921,6 +27039,124 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
26921
27039
  }
26922
27040
  return _waitForAudioContextReadyImpl;
26923
27041
  }()
27042
+ }, {
27043
+ key: "wantsHtmlAudioPlayback",
27044
+ value: function wantsHtmlAudioPlayback() {
27045
+ return this.config.htmlAudioPlayback !== false;
27046
+ }
27047
+ }, {
27048
+ key: "getHtmlAudioPlaybackInfo",
27049
+ value: function getHtmlAudioPlaybackInfo() {
27050
+ return {
27051
+ htmlAudioPlayback: this.wantsHtmlAudioPlayback(),
27052
+ htmlAudioRouteActive: this._htmlAudioRouteActive,
27053
+ htmlAudioPlayOk: this._htmlAudioPlayOk
27054
+ };
27055
+ }
27056
+
27057
+ /**
27058
+ * Last hop: GainNode → MediaStreamDestination → hidden <audio>.
27059
+ * Falls back to AudioContext.destination if the HTML route cannot start.
27060
+ */
27061
+ }, {
27062
+ key: "_connectGainToOutput",
27063
+ value: function _connectGainToOutput() {
27064
+ if (!this.gainNode || !this.audioContext) {
27065
+ return;
27066
+ }
27067
+ try {
27068
+ this.gainNode.disconnect();
27069
+ } catch (_) {/* ignore */}
27070
+ if (this.wantsHtmlAudioPlayback() && this._ensureHtmlAudioRoute()) {
27071
+ this.gainNode.connect(this._mediaStreamDest);
27072
+ return;
27073
+ }
27074
+ this.gainNode.connect(this.audioContext.destination);
27075
+ this._htmlAudioRouteActive = false;
27076
+ }
27077
+ }, {
27078
+ key: "_ensureHtmlAudioRoute",
27079
+ value: function _ensureHtmlAudioRoute() {
27080
+ if (this._htmlAudioRouteActive && this._htmlAudioEl && this._mediaStreamDest) {
27081
+ this._ensureHtmlAudioPlaying();
27082
+ return true;
27083
+ }
27084
+ if (!this.audioContext || typeof this.audioContext.createMediaStreamDestination !== 'function') {
27085
+ console.warn('⚠️ AudioPlayer: MediaStreamDestination unavailable — using AudioContext.destination');
27086
+ return false;
27087
+ }
27088
+ try {
27089
+ this._mediaStreamDest = this.audioContext.createMediaStreamDestination();
27090
+ var el = document.createElement('audio');
27091
+ el.setAttribute('playsinline', '');
27092
+ el.setAttribute('webkit-playsinline', '');
27093
+ el.autoplay = true;
27094
+ el.controls = false;
27095
+ el.preload = 'auto';
27096
+ el.style.display = 'none';
27097
+ el.srcObject = this._mediaStreamDest.stream;
27098
+ document.body.appendChild(el);
27099
+ this._htmlAudioEl = el;
27100
+ this._htmlAudioRouteActive = true;
27101
+ this._ensureHtmlAudioPlaying();
27102
+ console.log('🔊 AudioPlayer: Playback last-hop is HTMLAudioElement (AEC far-end route)');
27103
+ return true;
27104
+ } catch (e) {
27105
+ console.warn('⚠️ AudioPlayer: HTML audio route failed, falling back to destination:', e);
27106
+ this._teardownHtmlAudioRoute();
27107
+ return false;
27108
+ }
27109
+ }
27110
+ }, {
27111
+ key: "_ensureHtmlAudioPlaying",
27112
+ value: function _ensureHtmlAudioPlaying() {
27113
+ var _this7 = this;
27114
+ var el = this._htmlAudioEl;
27115
+ if (!el) return;
27116
+ if (!el.paused && this._htmlAudioPlayOk) return;
27117
+ var playResult = el.play();
27118
+ if (playResult && typeof playResult.then === 'function') {
27119
+ playResult.then(function () {
27120
+ _this7._htmlAudioPlayOk = true;
27121
+ }).catch(function (err) {
27122
+ if (_this7._htmlAudioPlayOk || !el.paused) {
27123
+ return;
27124
+ }
27125
+ console.warn('⚠️ AudioPlayer: HTMLAudioElement.play() rejected — falling back to destination:', err);
27126
+ _this7._fallbackToDestination('play_rejected');
27127
+ });
27128
+ }
27129
+ }
27130
+ }, {
27131
+ key: "_fallbackToDestination",
27132
+ value: function _fallbackToDestination(reason) {
27133
+ if (!this.gainNode || !this.audioContext) return;
27134
+ try {
27135
+ this.gainNode.disconnect();
27136
+ } catch (_) {/* ignore */}
27137
+ this._teardownHtmlAudioRoute();
27138
+ this.gainNode.connect(this.audioContext.destination);
27139
+ console.warn("\u26A0\uFE0F AudioPlayer: Fell back to AudioContext.destination (".concat(reason, ")"));
27140
+ }
27141
+ }, {
27142
+ key: "_teardownHtmlAudioRoute",
27143
+ value: function _teardownHtmlAudioRoute() {
27144
+ if (this._htmlAudioEl) {
27145
+ try {
27146
+ this._htmlAudioEl.pause();
27147
+ } catch (_) {/* ignore */}
27148
+ try {
27149
+ this._htmlAudioEl.srcObject = null;
27150
+ } catch (_) {/* ignore */}
27151
+ if (this._htmlAudioEl.parentNode) {
27152
+ this._htmlAudioEl.parentNode.removeChild(this._htmlAudioEl);
27153
+ }
27154
+ this._htmlAudioEl = null;
27155
+ }
27156
+ this._mediaStreamDest = null;
27157
+ this._htmlAudioRouteActive = false;
27158
+ }
27159
+
26924
27160
  /**
26925
27161
  * Initialize audio context with correct sample rate
26926
27162
  */
@@ -26929,7 +27165,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
26929
27165
  value: (function () {
26930
27166
  var _initializeAudioContext = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7() {
26931
27167
  var _this$outputFormat5,
26932
- _this7 = this,
27168
+ _this8 = this,
26933
27169
  _this$outputFormat6;
26934
27170
  var desiredSampleRate, currentSampleRate, canReuseShared, setupAfterResume, _t4;
26935
27171
  return _regenerator().w(function (_context8) {
@@ -26970,6 +27206,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
26970
27206
  _context8.n = 3;
26971
27207
  break;
26972
27208
  case 2:
27209
+ this._ensureHtmlAudioPlaying();
26973
27210
  return _context8.a(2);
26974
27211
  case 3:
26975
27212
  // iOS FIX: Reuse shared AudioContext if available and compatible.
@@ -26983,19 +27220,19 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
26983
27220
  console.log("\u267B\uFE0F AudioPlayer: Reusing shared AudioContext at ".concat(desiredSampleRate, "Hz (iOS-safe)"));
26984
27221
  this.audioContext = _sharedPlayerContext;
26985
27222
  setupAfterResume = function setupAfterResume() {
26986
- _this7.setupAudioContextStateMonitoring();
26987
- if (_this7.gainNode) {
27223
+ _this8.setupAudioContextStateMonitoring();
27224
+ if (_this8.gainNode) {
26988
27225
  try {
26989
- _this7.gainNode.disconnect();
27226
+ _this8.gainNode.disconnect();
26990
27227
  } catch (e) {
26991
27228
  console.warn('⚠️ AudioPlayer: Error disconnecting old GainNode:', e);
26992
27229
  }
26993
27230
  }
26994
- _this7.gainNode = _this7.audioContext.createGain();
26995
- _this7.gainNode.gain.value = 1.0;
26996
- _this7.gainNode.connect(_this7.audioContext.destination);
26997
- if (!_this7._audioContextPrimed) {
26998
- _this7._primeAudioContext();
27231
+ _this8.gainNode = _this8.audioContext.createGain();
27232
+ _this8.gainNode.gain.value = 1.0;
27233
+ _this8._connectGainToOutput();
27234
+ if (!_this8._audioContextPrimed) {
27235
+ _this8._primeAudioContext();
26999
27236
  }
27000
27237
  };
27001
27238
  if (!(this.audioContext.state === 'suspended')) {
@@ -27050,7 +27287,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27050
27287
  this.setupAudioContextStateMonitoring();
27051
27288
  this.gainNode = this.audioContext.createGain();
27052
27289
  this.gainNode.gain.value = 1.0;
27053
- this.gainNode.connect(this.audioContext.destination);
27290
+ this._connectGainToOutput();
27054
27291
  console.log('✅ AudioPlayer: GainNode created for volume control');
27055
27292
  this._primeAudioContext();
27056
27293
  } catch (error) {
@@ -27062,7 +27299,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27062
27299
  this.setupAudioContextStateMonitoring();
27063
27300
  this.gainNode = this.audioContext.createGain();
27064
27301
  this.gainNode.gain.value = 1.0;
27065
- this.gainNode.connect(this.audioContext.destination);
27302
+ this._connectGainToOutput();
27066
27303
  console.log('✅ AudioPlayer: GainNode created for volume control (fallback)');
27067
27304
  this._primeAudioContext();
27068
27305
  }
@@ -27100,8 +27337,11 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27100
27337
  silentBuffer = this.audioContext.createBuffer(1, sampleRate * 0.15, sampleRate);
27101
27338
  source = this.audioContext.createBufferSource();
27102
27339
  source.buffer = silentBuffer;
27103
- source.connect(this.audioContext.destination);
27340
+ // Prime through the same last hop as real TTS so iOS treats the hidden
27341
+ // <audio> as "playing media" (ElevenLabs maybePrimeIosPlayback).
27342
+ source.connect(this.gainNode || this.audioContext.destination);
27104
27343
  source.start();
27344
+ this._ensureHtmlAudioPlaying();
27105
27345
  _context9.n = 2;
27106
27346
  return new Promise(function (resolve) {
27107
27347
  return setTimeout(resolve, 150);
@@ -27135,7 +27375,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27135
27375
  value: function _cleanupAudioContext() {
27136
27376
  console.log('[TTP AudioPlayer] 🧹 Cleaning up AudioContext (iOS-safe: keeping shared context alive)');
27137
27377
 
27138
- // Disconnect and cleanup gainNode
27378
+ // Disconnect and cleanup gainNode + HTML audio last-hop
27139
27379
  if (this.gainNode) {
27140
27380
  try {
27141
27381
  this.gainNode.disconnect();
@@ -27144,6 +27384,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27144
27384
  }
27145
27385
  this.gainNode = null;
27146
27386
  }
27387
+ this._teardownHtmlAudioRoute();
27147
27388
 
27148
27389
  // Remove state change listener first
27149
27390
  if (this._audioContextStateChangeHandler && this.audioContext) {
@@ -27184,7 +27425,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27184
27425
  * Handles mic permission grants, tab switching, browser suspension, etc.
27185
27426
  */
27186
27427
  function setupAudioContextStateMonitoring() {
27187
- var _this8 = this;
27428
+ var _this9 = this;
27188
27429
  if (!this.audioContext) {
27189
27430
  return;
27190
27431
  }
@@ -27197,35 +27438,38 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27197
27438
  // Create handler that references this.audioContext dynamically
27198
27439
  this._audioContextStateChangeHandler = function () {
27199
27440
  // Null check required because audioContext may be cleaned up while handler is queued
27200
- if (!_this8.audioContext) {
27441
+ if (!_this9.audioContext) {
27201
27442
  console.warn('⚠️ AudioPlayer: State change handler fired but AudioContext is null');
27202
27443
  return;
27203
27444
  }
27204
- console.log("\uD83C\uDFB5 AudioPlayer: AudioContext state changed to: ".concat(_this8.audioContext.state));
27205
- if (_this8.audioContext.state === 'suspended' && _this8.isPlaying) {
27445
+ console.log("\uD83C\uDFB5 AudioPlayer: AudioContext state changed to: ".concat(_this9.audioContext.state));
27446
+ if (_this9.audioContext.state === 'running') {
27447
+ _this9._ensureHtmlAudioPlaying();
27448
+ }
27449
+ if (_this9.audioContext.state === 'suspended' && _this9.isPlaying) {
27206
27450
  // AudioContext was suspended during playback (tab switch, mic permission, etc.)
27207
27451
  console.warn('⚠️ AudioPlayer: AudioContext suspended during playback');
27208
27452
  // Note: Playback will pause automatically, but we should handle queue processing
27209
27453
  // The state change will be handled when we try to process next frame
27210
- } else if (_this8.audioContext.state === 'running' && !_this8.isPlaying && (_this8.audioQueue.length > 0 || _this8.pcmChunkQueue.length > 0 || _this8.preparedBuffer.length > 0)) {
27454
+ } else if (_this9.audioContext.state === 'running' && !_this9.isPlaying && (_this9.audioQueue.length > 0 || _this9.pcmChunkQueue.length > 0 || _this9.preparedBuffer.length > 0)) {
27211
27455
  // AudioContext resumed and we have queued frames
27212
27456
  // This handles: mic permission grant, tab switching back, browser resume, etc.
27213
27457
  console.log('✅ AudioPlayer: AudioContext resumed - resuming queue processing');
27214
27458
 
27215
27459
  // Resume queue processing if we have frames
27216
- if (_this8.audioQueue.length > 0 && !_this8.isProcessingQueue) {
27460
+ if (_this9.audioQueue.length > 0 && !_this9.isProcessingQueue) {
27217
27461
  setTimeout(function () {
27218
- return _this8.processQueue();
27462
+ return _this9.processQueue();
27219
27463
  }, 50);
27220
27464
  }
27221
- if (_this8.pcmChunkQueue.length > 0 && !_this8.isProcessingPcmQueue) {
27465
+ if (_this9.pcmChunkQueue.length > 0 && !_this9.isProcessingPcmQueue) {
27222
27466
  setTimeout(function () {
27223
- return _this8.processPcmQueue();
27467
+ return _this9.processPcmQueue();
27224
27468
  }, 50);
27225
27469
  }
27226
- if (_this8.preparedBuffer.length > 0 && !_this8.isSchedulingFrames) {
27470
+ if (_this9.preparedBuffer.length > 0 && !_this9.isSchedulingFrames) {
27227
27471
  setTimeout(function () {
27228
- return _this8.scheduleFrames();
27472
+ return _this9.scheduleFrames();
27229
27473
  }, 50);
27230
27474
  }
27231
27475
  }
@@ -27244,7 +27488,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27244
27488
  key: "processQueue",
27245
27489
  value: (function () {
27246
27490
  var _processQueue = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee9() {
27247
- var _this9 = this;
27491
+ var _this0 = this;
27248
27492
  var audioBlob, wasFirstPlay, audioContext, arrayBuffer, audioBuffer, shouldEmitStart, source, _t6;
27249
27493
  return _regenerator().w(function (_context0) {
27250
27494
  while (1) switch (_context0.p = _context0.n) {
@@ -27263,6 +27507,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27263
27507
  return _context0.a(2);
27264
27508
  case 2:
27265
27509
  this.isProcessingQueue = true;
27510
+ this._ensureHtmlAudioPlaying();
27266
27511
  audioBlob = this.audioQueue.shift();
27267
27512
  if (audioBlob) {
27268
27513
  _context0.n = 3;
@@ -27303,22 +27548,22 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27303
27548
  // Handle end
27304
27549
 
27305
27550
  source.onended = function () {
27306
- _this9.currentSource = null;
27307
- _this9.isProcessingQueue = false;
27551
+ _this0.currentSource = null;
27552
+ _this0.isProcessingQueue = false;
27308
27553
 
27309
27554
  // Process next chunk
27310
27555
 
27311
- if (_this9.audioQueue.length > 0) {
27556
+ if (_this0.audioQueue.length > 0) {
27312
27557
  setTimeout(function () {
27313
- return _this9.processQueue();
27558
+ return _this0.processQueue();
27314
27559
  }, 50);
27315
27560
  } else {
27316
27561
  // No more chunks - stop after delay
27317
27562
 
27318
27563
  setTimeout(function () {
27319
- if (_this9.audioQueue.length === 0 && !_this9.currentSource) {
27320
- _this9.isPlaying = false;
27321
- _this9.emit('playbackStopped');
27564
+ if (_this0.audioQueue.length === 0 && !_this0.currentSource) {
27565
+ _this0.isPlaying = false;
27566
+ _this0.emit('playbackStopped');
27322
27567
  }
27323
27568
  }, 100);
27324
27569
  }
@@ -27341,7 +27586,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27341
27586
  if (this.audioQueue.length > 0) {
27342
27587
  this.isProcessingQueue = false;
27343
27588
  setTimeout(function () {
27344
- return _this9.processQueue();
27589
+ return _this0.processQueue();
27345
27590
  }, 100);
27346
27591
  } else {
27347
27592
  this.isPlaying = false;
@@ -27564,7 +27809,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27564
27809
  }, {
27565
27810
  key: "markNewSentence",
27566
27811
  value: function markNewSentence(text, synced, segmentId) {
27567
- var _this0 = this;
27812
+ var _this1 = this;
27568
27813
  var wasStopped = this._isStopped;
27569
27814
  var isCurrentlyPlaying = this.isPlaying || this.scheduledSources.size > 0;
27570
27815
 
@@ -27623,34 +27868,34 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27623
27868
  var sentenceText = text; // Capture for timeout callback
27624
27869
  this._emptySentenceTimeout = setTimeout(function () {
27625
27870
  // Check if this sentence still has no chunks after timeout
27626
- if (_this0.pendingSentenceText === sentenceText && _this0.scheduledBuffers === 0 && _this0.preparedBuffer.length === 0 && _this0.pcmChunkQueue.length === 0 && !_this0._isStopped) {
27871
+ if (_this1.pendingSentenceText === sentenceText && _this1.scheduledBuffers === 0 && _this1.preparedBuffer.length === 0 && _this1.pcmChunkQueue.length === 0 && !_this1._isStopped) {
27627
27872
  console.warn("\u26A0\uFE0F AudioPlayer: Empty sentence detected after 5s timeout - no chunks received for: \"".concat(sentenceText.substring(0, 40), "...\""));
27628
27873
  // If this empty sentence carried a segment id, report it done (nothing was heard) and
27629
27874
  // adopt it as current so the coarse stop below matches the backend's last-sent id.
27630
- if (_this0.pendingSegmentId != null) {
27631
- var emptySegId = _this0.pendingSegmentId;
27632
- _this0.currentSegmentId = emptySegId;
27633
- _this0.pendingSegmentId = null;
27634
- _this0.emit('segmentDone', {
27875
+ if (_this1.pendingSegmentId != null) {
27876
+ var emptySegId = _this1.pendingSegmentId;
27877
+ _this1.currentSegmentId = emptySegId;
27878
+ _this1.pendingSegmentId = null;
27879
+ _this1.emit('segmentDone', {
27635
27880
  segmentId: emptySegId,
27636
27881
  status: 'finished',
27637
27882
  playedMs: 0
27638
27883
  });
27639
27884
  }
27640
27885
  // Clear pending sentence to unblock next sentence
27641
- if (_this0.pendingSentenceText === sentenceText) {
27642
- _this0.pendingSentenceText = null;
27886
+ if (_this1.pendingSentenceText === sentenceText) {
27887
+ _this1.pendingSentenceText = null;
27643
27888
  }
27644
27889
  // Emit playbackStopped to allow next sentence to start
27645
27890
  // Only if we're not currently playing (to avoid interrupting real playback)
27646
- if (!_this0.isPlaying && _this0.scheduledSources.size === 0) {
27891
+ if (!_this1.isPlaying && _this1.scheduledSources.size === 0) {
27647
27892
  console.log('🛑 AudioPlayer: Emitting playbackStopped for empty sentence timeout');
27648
- _this0.emit('playbackStopped', {
27649
- segmentId: _this0.currentSegmentId
27893
+ _this1.emit('playbackStopped', {
27894
+ segmentId: _this1.currentSegmentId
27650
27895
  });
27651
27896
  }
27652
27897
  }
27653
- _this0._emptySentenceTimeout = null;
27898
+ _this1._emptySentenceTimeout = null;
27654
27899
  }, 5000); // 5 second timeout - adjust based on expected chunk arrival rate
27655
27900
  }
27656
27901
 
@@ -27660,14 +27905,14 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27660
27905
  }, {
27661
27906
  key: "startTranscriptChecker",
27662
27907
  value: function startTranscriptChecker() {
27663
- var _this1 = this;
27908
+ var _this10 = this;
27664
27909
  if (this.isCheckingTranscripts) return;
27665
27910
  this.isCheckingTranscripts = true;
27666
27911
  console.log('📝 AudioPlayer: Transcript checker started');
27667
27912
  var _checkLoop = function checkLoop() {
27668
- if (!_this1.isCheckingTranscripts || !_this1.audioContext) return;
27669
- var currentTime = _this1.audioContext.currentTime;
27670
- var _iterator2 = _createForOfIteratorHelper(_this1.sentenceTimings),
27913
+ if (!_this10.isCheckingTranscripts || !_this10.audioContext) return;
27914
+ var currentTime = _this10.audioContext.currentTime;
27915
+ var _iterator2 = _createForOfIteratorHelper(_this10.sentenceTimings),
27671
27916
  _step2;
27672
27917
  try {
27673
27918
  for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
@@ -27681,13 +27926,13 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27681
27926
  eventData.synced = _timing.synced;
27682
27927
  }
27683
27928
  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, ")"));
27684
- _this1.emit('transcriptDisplay', eventData);
27929
+ _this10.emit('transcriptDisplay', eventData);
27685
27930
  }
27686
27931
  // Per-segment natural finish: this segment's audio window has fully elapsed.
27687
27932
  if (!_timing.doneReported && _timing.endTime != null && currentTime >= _timing.endTime) {
27688
27933
  _timing.doneReported = true;
27689
27934
  var _playedMs = Math.round((_timing.endTime - _timing.startTime) * 1000);
27690
- _this1.emit('segmentDone', {
27935
+ _this10.emit('segmentDone', {
27691
27936
  segmentId: _timing.segmentId,
27692
27937
  status: 'finished',
27693
27938
  playedMs: _playedMs
@@ -27699,12 +27944,12 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27699
27944
  } finally {
27700
27945
  _iterator2.f();
27701
27946
  }
27702
- if (_this1.isPlaying || _this1.scheduledBuffers > 0) {
27947
+ if (_this10.isPlaying || _this10.scheduledBuffers > 0) {
27703
27948
  requestAnimationFrame(_checkLoop);
27704
27949
  } else {
27705
27950
  // Playback drained naturally — flush any segment whose finish tick we may have missed
27706
27951
  // (the last buffer's onended can flip isPlaying=false before this loop's next tick).
27707
- var _iterator3 = _createForOfIteratorHelper(_this1.sentenceTimings),
27952
+ var _iterator3 = _createForOfIteratorHelper(_this10.sentenceTimings),
27708
27953
  _step3;
27709
27954
  try {
27710
27955
  for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
@@ -27713,7 +27958,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27713
27958
  timing.doneReported = true;
27714
27959
  var end = timing.endTime != null ? timing.endTime : timing.startTime;
27715
27960
  var playedMs = Math.round((end - timing.startTime) * 1000);
27716
- _this1.emit('segmentDone', {
27961
+ _this10.emit('segmentDone', {
27717
27962
  segmentId: timing.segmentId,
27718
27963
  status: 'finished',
27719
27964
  playedMs: playedMs
@@ -27725,7 +27970,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27725
27970
  } finally {
27726
27971
  _iterator3.f();
27727
27972
  }
27728
- _this1.isCheckingTranscripts = false;
27973
+ _this10.isCheckingTranscripts = false;
27729
27974
  console.log('📝 AudioPlayer: Transcript checker stopped');
27730
27975
  }
27731
27976
  };
@@ -27831,7 +28076,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27831
28076
  }, {
27832
28077
  key: "getStatus",
27833
28078
  value: function getStatus() {
27834
- return {
28079
+ return _objectSpread({
27835
28080
  isPlaying: this.isPlaying,
27836
28081
  isProcessingQueue: this.isProcessingQueue,
27837
28082
  queueLength: this.audioQueue.length,
@@ -27840,7 +28085,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
27840
28085
  scheduledBuffers: this.scheduledBuffers,
27841
28086
  preparedBufferLength: this.preparedBuffer.length,
27842
28087
  scheduledSourcesCount: this.scheduledSources.size
27843
- };
28088
+ }, this.getHtmlAudioPlaybackInfo());
27844
28089
  }
27845
28090
 
27846
28091
  /**
@@ -27888,8 +28133,9 @@ __webpack_require__.r(__webpack_exports__);
27888
28133
  /* harmony import */ var _utils_AudioFormatConverter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./utils/AudioFormatConverter.js */ "./src/v2/utils/AudioFormatConverter.js");
27889
28134
  /* harmony import */ var _core_ClientToolsRegistry_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../core/ClientToolsRegistry.js */ "./src/core/ClientToolsRegistry.js");
27890
28135
  /* harmony import */ var _core_ClientScriptManager_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../core/ClientScriptManager.js */ "./src/core/ClientScriptManager.js");
27891
- /* harmony import */ var _utils_screenshot_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../utils/screenshot.js */ "./src/utils/screenshot.js");
27892
- /* harmony import */ var _utils_visual_tools_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../utils/visual-tools.js */ "./src/utils/visual-tools.js");
28136
+ /* harmony import */ var _core_helloFlavor_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../core/helloFlavor.js */ "./src/core/helloFlavor.js");
28137
+ /* harmony import */ var _utils_screenshot_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../utils/screenshot.js */ "./src/utils/screenshot.js");
28138
+ /* harmony import */ var _utils_visual_tools_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../utils/visual-tools.js */ "./src/utils/visual-tools.js");
27893
28139
  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); }
27894
28140
  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; } } }; }
27895
28141
  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; } }
@@ -27924,6 +28170,7 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
27924
28170
 
27925
28171
 
27926
28172
 
28173
+
27927
28174
  /**
27928
28175
 
27929
28176
  * VoiceSDK v2 - Multi-codec speech-to-speech SDK
@@ -28021,6 +28268,9 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
28021
28268
  // Audio constraints for getUserMedia (optional)
28022
28269
  // If not provided, defaults will be used: echoCancellation: true, noiseSuppression: true, autoGainControl: true
28023
28270
  audioConstraints: config.audioConstraints || null,
28271
+ // Last-hop TTS playback via hidden <audio> (AEC far-end). Default on.
28272
+ // Set false to fall back to AudioContext.destination (old path).
28273
+ htmlAudioPlayback: config.htmlAudioPlayback !== false,
28024
28274
  // Protocol version
28025
28275
 
28026
28276
  protocolVersion: config.protocolVersion || 2,
@@ -28142,7 +28392,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
28142
28392
  key: "_registerBuiltInTools",
28143
28393
  value: function _registerBuiltInTools() {
28144
28394
  try {
28145
- (0,_utils_visual_tools_js__WEBPACK_IMPORTED_MODULE_7__.registerVisualTools)(this.clientToolsRegistry);
28395
+ (0,_utils_visual_tools_js__WEBPACK_IMPORTED_MODULE_8__.registerVisualTools)(this.clientToolsRegistry);
28146
28396
  } catch (error) {
28147
28397
  console.error('❌ VoiceSDK: Error registering built-in tools:', error);
28148
28398
  console.error(' Error details:', error.message, error.stack);
@@ -28880,7 +29130,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
28880
29130
  // iOS in-app webviews lack "Safari" in the UA (real Safari always has it).
28881
29131
  var webview = isAndroid && (/\bwv\b/.test(ua) || /Version\/[\d.]+.*Chrome/.test(ua)) || isIos && !/Safari/i.test(ua) || false;
28882
29132
  var env = {
28883
- sdkVersion: true ? "2.47.2" : 0,
29133
+ sdkVersion: true ? "2.48.0" : 0,
28884
29134
  ua: ua,
28885
29135
  platform: (uaData === null || uaData === void 0 ? void 0 : uaData.platform) || navigator.platform || '',
28886
29136
  mobile: (_uaData$mobile = uaData === null || uaData === void 0 ? void 0 : uaData.mobile) !== null && _uaData$mobile !== void 0 ? _uaData$mobile : isAndroid || isIos,
@@ -28895,7 +29145,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
28895
29145
  } catch (e) {
28896
29146
  console.warn('⚠️ VoiceSDK v2: Failed to build client env:', e);
28897
29147
  return {
28898
- sdkVersion: true ? "2.47.2" : 0
29148
+ sdkVersion: true ? "2.48.0" : 0
28899
29149
  };
28900
29150
  }
28901
29151
  }
@@ -28911,11 +29161,11 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
28911
29161
  key: "_sendClientAudioInfo",
28912
29162
  value: function _sendClientAudioInfo() {
28913
29163
  try {
28914
- var _this$audioRecorder, _this$audioRecorder$g, _s$echoCancellation, _s$noiseSuppression, _s$autoGainControl, _s$voiceIsolation, _s$sampleRate, _s$channelCount, _this$audioRecorder2, _this$audioPlayer, _this$audioRecorder3;
29164
+ 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;
28915
29165
  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];
28916
29166
  if (!track) return;
28917
29167
  var s = track.getSettings ? track.getSettings() : {};
28918
- var audio = {
29168
+ var audio = _objectSpread({
28919
29169
  aec: (_s$echoCancellation = s.echoCancellation) !== null && _s$echoCancellation !== void 0 ? _s$echoCancellation : null,
28920
29170
  ns: (_s$noiseSuppression = s.noiseSuppression) !== null && _s$noiseSuppression !== void 0 ? _s$noiseSuppression : null,
28921
29171
  agc: (_s$autoGainControl = s.autoGainControl) !== null && _s$autoGainControl !== void 0 ? _s$autoGainControl : null,
@@ -28926,7 +29176,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
28926
29176
  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,
28927
29177
  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,
28928
29178
  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
28929
- };
29179
+ }, ((_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)) || {});
28930
29180
  this.sendMessage({
28931
29181
  t: 'client_audio_info',
28932
29182
  audio: audio
@@ -28940,7 +29190,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
28940
29190
  key: "sendHelloMessage",
28941
29191
  value: function () {
28942
29192
  var _sendHelloMessage = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
28943
- var inputFormat, requestedOutputFormat, inputError, outputError, helloMessage;
29193
+ var inputFormat, requestedOutputFormat, inputError, outputError, helloMessage, wireFlavor;
28944
29194
  return _regenerator().w(function (_context2) {
28945
29195
  while (1) switch (_context2.n) {
28946
29196
  case 0:
@@ -29029,14 +29279,15 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
29029
29279
  console.log('⚠️ VoiceSDK v2: Variables NOT included - condition failed');
29030
29280
  }
29031
29281
 
29032
- // Include flavor object if set (additive backward compatible)
29033
- if (this.config.flavor) {
29034
- helloMessage.flavor = this.config.flavor;
29282
+ // Partner fields only UI-only keys like callView stay local (backend Flavor DTO rejects them)
29283
+ wireFlavor = (0,_core_helloFlavor_js__WEBPACK_IMPORTED_MODULE_6__.flavorForHello)(this.config.flavor);
29284
+ if (wireFlavor) {
29285
+ helloMessage.flavor = wireFlavor;
29035
29286
  }
29036
29287
 
29037
29288
  // Include SDK build time for debugging
29038
29289
  if (true) {
29039
- helloMessage.lastBuildTime = "2026-07-30T20:53:20.013Z";
29290
+ helloMessage.lastBuildTime = "2026-08-20T12:21:14.185Z";
29040
29291
  }
29041
29292
 
29042
29293
  // Client environment (device/browser/webview) for backend logs + Langfuse metadata
@@ -29280,7 +29531,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
29280
29531
  case 'get_page_context':
29281
29532
  // Handle get_page_context request from backend
29282
29533
  console.log('📖 [VISUAL ASSISTANT] Backend requested page context');
29283
- (0,_utils_visual_tools_js__WEBPACK_IMPORTED_MODULE_7__.extractPageContext)().then(function (pageContext) {
29534
+ (0,_utils_visual_tools_js__WEBPACK_IMPORTED_MODULE_8__.extractPageContext)().then(function (pageContext) {
29284
29535
  // Use existing DOM scanner
29285
29536
  _this6.sendMessage({
29286
29537
  t: 'page_context',
@@ -29301,7 +29552,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
29301
29552
  console.log('📸 [VISUAL ASSISTANT] Backend requested screenshot');
29302
29553
  try {
29303
29554
  // Use existing screenshot capture function
29304
- (0,_utils_screenshot_js__WEBPACK_IMPORTED_MODULE_6__.captureScreenshot)().then(function (screenshot) {
29555
+ (0,_utils_screenshot_js__WEBPACK_IMPORTED_MODULE_7__.captureScreenshot)().then(function (screenshot) {
29305
29556
  _this6.sendMessage({
29306
29557
  t: 'screenshot',
29307
29558
  screenshot: {
@@ -32579,6 +32830,7 @@ var AgentSDK = /*#__PURE__*/function () {
32579
32830
  outputBitDepth: this.config.outputBitDepth || 16,
32580
32831
  // Default: 16-bit
32581
32832
  flavor: this.config.flavor || null,
32833
+ htmlAudioPlayback: this.config.htmlAudioPlayback !== false,
32582
32834
  // Shared client-tool handler map (set by TTPChatWidget so voice + text SDKs
32583
32835
  // both look up handlers in the same registration site).
32584
32836
  sharedToolHandlers: this.config.sharedToolHandlers || null,
@@ -34455,14 +34707,15 @@ var TTPChatWidget = /*#__PURE__*/function () {
34455
34707
  fontSize: ((_userConfig$text0 = userConfig.text) === null || _userConfig$text0 === void 0 || (_userConfig$text0 = _userConfig$text0.sendButtonHint) === null || _userConfig$text0 === void 0 ? void 0 : _userConfig$text0.fontSize) || ((_userConfig$panel20 = userConfig.panel) === null || _userConfig$panel20 === void 0 || (_userConfig$panel20 = _userConfig$panel20.sendButtonHint) === null || _userConfig$panel20 === void 0 ? void 0 : _userConfig$panel20.fontSize) || '14px'
34456
34708
  }, (_userConfig$text1 = userConfig.text) === null || _userConfig$text1 === void 0 ? void 0 : _userConfig$text1.sendButtonHint), (_userConfig$panel21 = userConfig.panel) === null || _userConfig$panel21 === void 0 ? void 0 : _userConfig$panel21.sendButtonHint),
34457
34709
  // Input field configuration
34458
- inputPlaceholder: ((_userConfig$text10 = userConfig.text) === null || _userConfig$text10 === void 0 ? void 0 : _userConfig$text10.inputPlaceholder) || ((_userConfig$panel22 = userConfig.panel) === null || _userConfig$panel22 === void 0 ? void 0 : _userConfig$panel22.inputPlaceholder) || 'Type your message...',
34710
+ inputPlaceholder: ((_userConfig$text10 = userConfig.text) === null || _userConfig$text10 === void 0 ? void 0 : _userConfig$text10.inputPlaceholder) || userConfig.inputPlaceholder || ((_userConfig$panel22 = userConfig.panel) === null || _userConfig$panel22 === void 0 ? void 0 : _userConfig$panel22.inputPlaceholder),
34459
34711
  inputBorderColor: ((_userConfig$text11 = userConfig.text) === null || _userConfig$text11 === void 0 ? void 0 : _userConfig$text11.inputBorderColor) || ((_userConfig$panel23 = userConfig.panel) === null || _userConfig$panel23 === void 0 ? void 0 : _userConfig$panel23.inputBorderColor) || '#E5E7EB',
34460
34712
  inputFocusColor: ((_userConfig$text12 = userConfig.text) === null || _userConfig$text12 === void 0 ? void 0 : _userConfig$text12.inputFocusColor) || ((_userConfig$panel24 = userConfig.panel) === null || _userConfig$panel24 === void 0 ? void 0 : _userConfig$panel24.inputFocusColor) || textChatAccent,
34461
34713
  inputBackgroundColor: ((_userConfig$text13 = userConfig.text) === null || _userConfig$text13 === void 0 ? void 0 : _userConfig$text13.inputBackgroundColor) || ((_userConfig$panel25 = userConfig.panel) === null || _userConfig$panel25 === void 0 ? void 0 : _userConfig$panel25.inputBackgroundColor) || '#FFFFFF',
34462
34714
  inputTextColor: ((_userConfig$text14 = userConfig.text) === null || _userConfig$text14 === void 0 ? void 0 : _userConfig$text14.inputTextColor) || ((_userConfig$panel26 = userConfig.panel) === null || _userConfig$panel26 === void 0 ? void 0 : _userConfig$panel26.inputTextColor) || '#1F2937',
34715
+ // >= 16px so iOS Safari does not auto-zoom the host page when the composer is focused
34463
34716
  inputFontSize: ((_userConfig$text15 = userConfig.text) === null || _userConfig$text15 === void 0 ? void 0 : _userConfig$text15.inputFontSize) || ((_userConfig$panel27 = userConfig.panel) === null || _userConfig$panel27 === void 0 ? void 0 : _userConfig$panel27.inputFontSize) || '16px',
34464
34717
  inputBorderRadius: ((_userConfig$text16 = userConfig.text) === null || _userConfig$text16 === void 0 ? void 0 : _userConfig$text16.inputBorderRadius) || ((_userConfig$panel28 = userConfig.panel) === null || _userConfig$panel28 === void 0 ? void 0 : _userConfig$panel28.inputBorderRadius) || 20,
34465
- inputPadding: ((_userConfig$text17 = userConfig.text) === null || _userConfig$text17 === void 0 ? void 0 : _userConfig$text17.inputPadding) || ((_userConfig$panel29 = userConfig.panel) === null || _userConfig$panel29 === void 0 ? void 0 : _userConfig$panel29.inputPadding) || '8px 16px',
34718
+ inputPadding: ((_userConfig$text17 = userConfig.text) === null || _userConfig$text17 === void 0 ? void 0 : _userConfig$text17.inputPadding) || ((_userConfig$panel29 = userConfig.panel) === null || _userConfig$panel29 === void 0 ? void 0 : _userConfig$panel29.inputPadding) || '9px 12px',
34466
34719
  /** When true (default), text chat uses the same hero gradient, primary, and bubble treatment as the voice UI. Set false for a light, panel-solid transcript. */
34467
34720
  useVoiceTheme: ((_userConfig$text18 = userConfig.text) === null || _userConfig$text18 === void 0 ? void 0 : _userConfig$text18.useVoiceTheme) !== false
34468
34721
  }, userConfig.text)
@@ -34572,7 +34825,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
34572
34825
  agentTextColor: ((_userConfig$messages8 = userConfig.messages) === null || _userConfig$messages8 === void 0 ? void 0 : _userConfig$messages8.agentTextColor) || ((_userConfig$messages9 = userConfig.messages) === null || _userConfig$messages9 === void 0 ? void 0 : _userConfig$messages9.textColor) || '#1F2937',
34573
34826
  userAvatarIcon: ((_userConfig$messages0 = userConfig.messages) === null || _userConfig$messages0 === void 0 ? void 0 : _userConfig$messages0.userAvatarIcon) || '👤',
34574
34827
  agentAvatarIcon: ((_userConfig$messages1 = userConfig.messages) === null || _userConfig$messages1 === void 0 ? void 0 : _userConfig$messages1.agentAvatarIcon) || '🤖',
34575
- fontSize: ((_userConfig$messages10 = userConfig.messages) === null || _userConfig$messages10 === void 0 ? void 0 : _userConfig$messages10.fontSize) || '16px',
34828
+ fontSize: ((_userConfig$messages10 = userConfig.messages) === null || _userConfig$messages10 === void 0 ? void 0 : _userConfig$messages10.fontSize) || '15px',
34576
34829
  borderRadius: ((_userConfig$messages11 = userConfig.messages) === null || _userConfig$messages11 === void 0 ? void 0 : _userConfig$messages11.borderRadius) || 16
34577
34830
  }, userConfig.messages),
34578
34831
  // Animation Configuration
@@ -34661,7 +34914,10 @@ var TTPChatWidget = /*#__PURE__*/function () {
34661
34914
  if (error && (error.message === 'DOMAIN_NOT_WHITELISTED' || error.message && error.message.includes('Domain not whitelisted'))) {
34662
34915
  return; // Already handled by domainError event
34663
34916
  }
34664
- _this5.textInterface.showError(error.message || error);
34917
+ // WS onerror is a browser Event (no .message) do not paint "[object Event]"
34918
+ var text = typeof error === 'string' ? error : error && error.message;
34919
+ if (!text) return;
34920
+ _this5.textInterface.showError(text);
34665
34921
  _this5.textInterface.stopStreamingState();
34666
34922
  });
34667
34923
  this.sdk.on('chunk', function (chunk) {
@@ -35081,7 +35337,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
35081
35337
  return;
35082
35338
  }
35083
35339
  this._ensureAboutStyles();
35084
- var version = true ? "2.47.2" : 0;
35340
+ var version = true ? "2.48.0" : 0;
35085
35341
  var convId = this._getLastConversationId();
35086
35342
  var t = function t(k, fb) {
35087
35343
  try {
@@ -35528,9 +35784,9 @@ var TTPChatWidget = /*#__PURE__*/function () {
35528
35784
  return _this0.showText();
35529
35785
  };
35530
35786
  }
35531
- var textUnifiedBackBtn = this.shadowRoot.getElementById('textUnifiedBackBtn');
35532
- if (textUnifiedBackBtn) {
35533
- textUnifiedBackBtn.onclick = function () {
35787
+ var textUnifiedHomeBtn = this.shadowRoot.getElementById('textUnifiedHomeBtn');
35788
+ if (textUnifiedHomeBtn) {
35789
+ textUnifiedHomeBtn.onclick = function () {
35534
35790
  var _this0$config$behavio;
35535
35791
  var widgetMode = ((_this0$config$behavio = _this0.config.behavior) === null || _this0$config$behavio === void 0 ? void 0 : _this0$config$behavio.mode) || 'unified';
35536
35792
  if (widgetMode !== 'unified') return;
@@ -35538,6 +35794,12 @@ var TTPChatWidget = /*#__PURE__*/function () {
35538
35794
  _this0._openMobileCallTextLanding();
35539
35795
  };
35540
35796
  }
35797
+ var textUnifiedCloseBtn = this.shadowRoot.getElementById('textUnifiedCloseBtn');
35798
+ if (textUnifiedCloseBtn) {
35799
+ textUnifiedCloseBtn.onclick = function () {
35800
+ return _this0._doTogglePanel();
35801
+ };
35802
+ }
35541
35803
 
35542
35804
  // Build wave bars inside the orb (desktop active call)
35543
35805
  var waveQueryRoot = this.config.useShadowDOM ? this.shadowRoot : document.getElementById('ttp-widget-container');
@@ -37449,13 +37711,22 @@ var TTPChatWidget = /*#__PURE__*/function () {
37449
37711
  "use strict";
37450
37712
  __webpack_require__.r(__webpack_exports__);
37451
37713
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
37452
- /* harmony export */ TextInterface: () => (/* binding */ TextInterface)
37714
+ /* harmony export */ MESSAGE_COLLAPSE_THRESHOLD: () => (/* binding */ MESSAGE_COLLAPSE_THRESHOLD),
37715
+ /* harmony export */ TextInterface: () => (/* binding */ TextInterface),
37716
+ /* harmony export */ collapseMessageText: () => (/* binding */ collapseMessageText),
37717
+ /* harmony export */ messageInlineOrder: () => (/* binding */ messageInlineOrder),
37718
+ /* harmony export */ resolveInputTextDirection: () => (/* binding */ resolveInputTextDirection),
37719
+ /* harmony export */ resolveMessageTextDirection: () => (/* binding */ resolveMessageTextDirection)
37453
37720
  /* harmony export */ });
37454
37721
  /* harmony import */ var _galleryHandler_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./galleryHandler.js */ "./src/widget/galleryHandler.js");
37455
37722
  /* harmony import */ var _markdown_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./markdown.js */ "./src/widget/markdown.js");
37456
37723
  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); }
37457
37724
  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 _n2 = 0, F = function F() {}; return { s: F, n: function n() { return _n2 >= r.length ? { done: !0 } : { done: !1, value: r[_n2++] }; }, 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; } } }; }
37725
+ function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
37726
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
37458
37727
  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; } }
37728
+ function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
37729
+ function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
37459
37730
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
37460
37731
  function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
37461
37732
  function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
@@ -37513,10 +37784,43 @@ function rgbTupleFromChromeColor(color, fallbackTuple) {
37513
37784
  /** Textarea single-line height and max auto-grow (px); keep in sync with `.message-input` CSS. */
37514
37785
  var TEXT_INPUT_MIN_HEIGHT_PX = 36;
37515
37786
  var TEXT_INPUT_MAX_HEIGHT_PX = 132;
37787
+ var MESSAGE_COLLAPSE_THRESHOLD = 353;
37516
37788
 
37517
37789
  /** How often a streaming agent bubble is re-rendered from its markdown buffer (ms). */
37518
37790
  var STREAM_RENDER_INTERVAL_MS = 40;
37519
37791
 
37792
+ /**
37793
+ * The time + delivery checks sit absolutely positioned in the bubble's bottom
37794
+ * corner, so the bubble reserves a physical gutter wide enough that the last
37795
+ * line of text can never run underneath them. GUTTER must stay comfortably
37796
+ * wider than INSET plus the rendered metadata ("23:59 ✓✓" — 24h time is the
37797
+ * widest case); `test/text-interface.test.mjs` asserts the two stay in step.
37798
+ */
37799
+ var MESSAGE_META_INSET_PX = 14;
37800
+ var MESSAGE_META_GUTTER_PX = 68;
37801
+ function collapseMessageText(text) {
37802
+ if (text.length <= MESSAGE_COLLAPSE_THRESHOLD) return text;
37803
+ return "".concat(text.slice(0, MESSAGE_COLLAPSE_THRESHOLD).trimEnd(), "\u2026");
37804
+ }
37805
+
37806
+ /** Uses the first strong character so typed text can override the empty-field locale. */
37807
+ function resolveInputTextDirection(text) {
37808
+ var _String$match;
37809
+ var fallbackDirection = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'ltr';
37810
+ var firstLetter = (_String$match = String(text).match(/(?:[A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u0870-\u0887\u0889-\u088F\u08A0-\u08C9\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C5C\u0C5D\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDC-\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u1711\u171F-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4C\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C8A\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7DC\uA7F1-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDD70-\uDD7A\uDD7C-\uDD8A\uDD8C-\uDD92\uDD94\uDD95\uDD97-\uDDA1\uDDA3-\uDDB1\uDDB3-\uDDB9\uDDBB\uDDBC\uDDC0-\uDDF3\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67\uDF80-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD40-\uDD59\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD23\uDD4A-\uDD65\uDD6F-\uDD85\uDE80-\uDEA9\uDEB0\uDEB1\uDEC2-\uDEC7\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDF70-\uDF81\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC71\uDC72\uDC75\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE3F\uDE40\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61\uDF80-\uDF89\uDF8B\uDF8E\uDF90-\uDFB5\uDFB7\uDFD1\uDFD3]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDEB8\uDF00-\uDF1A\uDF40-\uDF46]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCDF\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEB0-\uDEF8\uDFC0-\uDFE0]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDDB0-\uDDDB\uDEE0-\uDEF2\uDF02\uDF04-\uDF10\uDF12-\uDF33\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|\uD80B[\uDF90-\uDFF0]|[\uD80C\uD80E\uD80F\uD81C-\uD822\uD840-\uD868\uD86A-\uD86D\uD86F-\uD872\uD874-\uD879\uD880-\uD883\uD885-\uD88C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2F\uDC41-\uDC46\uDC60-\uDFFF]|\uD810[\uDC00-\uDFFA]|\uD811[\uDC00-\uDE46]|\uD818[\uDD00-\uDD1D]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE70-\uDEBE\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDD40-\uDD6C\uDE40-\uDE7F\uDEA0-\uDEB8\uDEBB-\uDED3\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3\uDFF2\uDFF3]|\uD823[\uDC00-\uDCD5\uDCFF-\uDD1E\uDD80-\uDDF2]|\uD82B[\uDFF0-\uDFF3\uDFF5-\uDFFB\uDFFD\uDFFE]|\uD82C[\uDC00-\uDD22\uDD32\uDD50-\uDD52\uDD55\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD837[\uDF00-\uDF1E\uDF25-\uDF2A]|\uD838[\uDC30-\uDC6D\uDD00-\uDD2C\uDD37-\uDD3D\uDD4E\uDE90-\uDEAD\uDEC0-\uDEEB]|\uD839[\uDCD0-\uDCEB\uDDD0-\uDDED\uDDF0\uDEC0-\uDEDE\uDEE0-\uDEE2\uDEE4\uDEE5\uDEE7-\uDEED\uDEF0-\uDEF4\uDEFE\uDEFF\uDFE0-\uDFE6\uDFE8-\uDFEB\uDFED\uDFEE\uDFF0-\uDFFE]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43\uDD4B]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDEDF\uDF00-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEAD\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0\uDFF0-\uDFFF]|\uD87B[\uDC00-\uDE5D]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A\uDF50-\uDFFF]|\uD88D[\uDC00-\uDC79])/)) === null || _String$match === void 0 ? void 0 : _String$match[0];
37811
+ if (!firstLetter) return fallbackDirection === 'rtl' ? 'rtl' : 'ltr';
37812
+ return /[\u0590-\u08FF]/.test(firstLetter) ? 'rtl' : 'ltr';
37813
+ }
37814
+ function resolveMessageTextDirection(text) {
37815
+ var fallbackDirection = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'ltr';
37816
+ return resolveInputTextDirection(text, fallbackDirection);
37817
+ }
37818
+
37819
+ /** Keeps the fixed, physical metadata area on the bubble's right edge. */
37820
+ function messageInlineOrder(direction) {
37821
+ return ['content', 'spacer'];
37822
+ }
37823
+
37520
37824
  /** Resolves voice primary / gradient strings to #rrggbb for CSS hex+alpha suffixes. */
37521
37825
  function firstHexFromVoiceColor(c, fallback) {
37522
37826
  if (c == null || typeof c !== 'string') return fallback;
@@ -37537,6 +37841,7 @@ var TextInterface = /*#__PURE__*/function () {
37537
37841
  this.config = config;
37538
37842
  this.sdk = sdk;
37539
37843
  this.streamingEl = null;
37844
+ this.streamingBubble = null;
37540
37845
  this.hasStartedStreaming = false;
37541
37846
  this.isActive = false;
37542
37847
  // Shadow root reference for DOM queries
@@ -37559,6 +37864,11 @@ var TextInterface = /*#__PURE__*/function () {
37559
37864
  var translations = ((_this$config$translat = this.config.translations) === null || _this$config$translat === void 0 ? void 0 : _this$config$translat[lang]) || ((_this$config$translat2 = this.config.translations) === null || _this$config$translat2 === void 0 ? void 0 : _this$config$translat2.en) || {};
37560
37865
  return translations[key] || key;
37561
37866
  }
37867
+ }, {
37868
+ key: "textDirection",
37869
+ get: function get() {
37870
+ return this.config.direction === 'rtl' ? 'rtl' : 'ltr';
37871
+ }
37562
37872
 
37563
37873
  /**
37564
37874
  * Generate HTML for text interface
@@ -37566,13 +37876,18 @@ var TextInterface = /*#__PURE__*/function () {
37566
37876
  }, {
37567
37877
  key: "generateHTML",
37568
37878
  value: function generateHTML() {
37569
- var _this$config$panel, _this$config$behavior, _this$config$sendButt, _this$config$panel2, _this$config$sendButt2, _this$config$panel3, _this$config$sendButt3, _this$config$panel4, _this$config$sendButt4, _this$config$panel5;
37879
+ var _this$config$panel, _this$config$header, _this$config$sendButt, _this$config$panel2, _this$config$sendButt2, _this$config$panel3, _this$config$sendButt3, _this$config$panel4, _this$config$sendButt4, _this$config$panel5;
37570
37880
  // Use text config, fallback to panel config, then translation, then default
37571
37881
  var inputPlaceholder = this.config.inputPlaceholder || ((_this$config$panel = this.config.panel) === null || _this$config$panel === void 0 ? void 0 : _this$config$panel.inputPlaceholder) || this.t('typeMessage') || 'Type your message...';
37572
- var unifiedMode = ((_this$config$behavior = this.config.behavior) === null || _this$config$behavior === void 0 ? void 0 : _this$config$behavior.mode) === 'unified';
37573
- var backArrow = this.config.direction === 'rtl' ? '→' : '';
37574
- var backBar = unifiedMode ? "\n <div class=\"text-interface-top-bar\">\n <button type=\"button\" class=\"text-interface-back-btn\" id=\"textUnifiedBackBtn\" aria-label=\"".concat(this.t('back'), "\">\n <span class=\"text-interface-back-icon\" aria-hidden=\"true\">").concat(backArrow, "</span>\n <span class=\"text-interface-back-label\">").concat(this.t('back'), "</span>\n </button>\n <button type=\"button\" class=\"ttp-info-btn\" aria-label=\"").concat(this.t('aboutTitle') || 'About', "\" title=\"").concat(this.t('aboutTitle') || 'About', "\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"9\"/>\n <line x1=\"12\" y1=\"11\" x2=\"12\" y2=\"16\"/>\n <circle cx=\"12\" cy=\"7.7\" r=\"1.05\" fill=\"currentColor\" stroke=\"none\"/>\n </svg>\n </button>\n </div>") : '';
37575
- return "<div class=\"text-interface\" id=\"textInterface\">\n ".concat(backBar, "\n <div class=\"messages-container\" id=\"messagesContainer\">\n <div class=\"empty-state\">\n <div class=\"empty-state-icon\">\uD83D\uDCAC</div>\n <div class=\"empty-state-title\">").concat(this.t('hello'), "</div>\n <div class=\"empty-state-text\">").concat(this.t('sendMessage'), "</div>\n </div>\n </div>\n <div class=\"input-container\">\n <div class=\"input-wrapper\" style=\"flex:1;\">\n <textarea class=\"message-input\" id=\"messageInput\" placeholder=\"").concat(inputPlaceholder, "\" rows=\"1\" dir=\"").concat(this.config.direction || 'ltr', "\"></textarea>\n </div>\n <button class=\"send-button\" id=\"sendButton\" aria-label=\"").concat(this.t('sendMessageAria'), "\">").concat(this.config.sendButtonText || '➤', "</button>\n ").concat((_this$config$sendButt = this.config.sendButtonHint) !== null && _this$config$sendButt !== void 0 && _this$config$sendButt.text || (_this$config$panel2 = this.config.panel) !== null && _this$config$panel2 !== void 0 && (_this$config$panel2 = _this$config$panel2.sendButtonHint) !== null && _this$config$panel2 !== void 0 && _this$config$panel2.text ? "\n <div class=\"send-button-hint\" style=\"color: ".concat(((_this$config$sendButt2 = this.config.sendButtonHint) === null || _this$config$sendButt2 === void 0 ? void 0 : _this$config$sendButt2.color) || ((_this$config$panel3 = this.config.panel) === null || _this$config$panel3 === void 0 || (_this$config$panel3 = _this$config$panel3.sendButtonHint) === null || _this$config$panel3 === void 0 ? void 0 : _this$config$panel3.color) || '#6B7280', "; font-size: ").concat(((_this$config$sendButt3 = this.config.sendButtonHint) === null || _this$config$sendButt3 === void 0 ? void 0 : _this$config$sendButt3.fontSize) || ((_this$config$panel4 = this.config.panel) === null || _this$config$panel4 === void 0 || (_this$config$panel4 = _this$config$panel4.sendButtonHint) === null || _this$config$panel4 === void 0 ? void 0 : _this$config$panel4.fontSize) || '14px', "; text-align: center; margin-top: 4px;\">\n ").concat(((_this$config$sendButt4 = this.config.sendButtonHint) === null || _this$config$sendButt4 === void 0 ? void 0 : _this$config$sendButt4.text) || ((_this$config$panel5 = this.config.panel) === null || _this$config$panel5 === void 0 || (_this$config$panel5 = _this$config$panel5.sendButtonHint) === null || _this$config$panel5 === void 0 ? void 0 : _this$config$panel5.text), "\n </div>\n ") : '', "\n </div>\n </div>");
37882
+ var textDirection = this.textDirection;
37883
+ var agentName = this.config.agentName || ((_this$config$header = this.config.header) === null || _this$config$header === void 0 ? void 0 : _this$config$header.title) || 'Chat Assistant';
37884
+ var agentInitial = agentName.trim().charAt(0).toUpperCase();
37885
+ var footer = this.config.footer || {};
37886
+ var isSpeacart = footer.brand === 'speacart';
37887
+ var brandName = isSpeacart ? 'SpeaCart' : 'TalkToPC';
37888
+ var brandUrl = isSpeacart ? 'https://speacart.com' : 'https://talktopc.com';
37889
+ var backBar = "\n <div class=\"text-interface-top-bar\" dir=\"".concat(textDirection, "\">\n <div class=\"text-interface-agent-heading\">\n <span class=\"text-interface-agent-avatar\" aria-hidden=\"true\">\n <span class=\"text-interface-agent-initial\">").concat(agentInitial, "</span>\n </span>\n <span class=\"text-interface-agent-copy\" dir=\"").concat(textDirection, "\">\n <span class=\"text-interface-agent-name\">").concat(agentName, "</span>\n <span class=\"text-interface-agent-status\"><span aria-hidden=\"true\"></span>").concat(this.t('online'), "</span>\n </span>\n </div>\n <div class=\"text-interface-top-actions\">\n <button type=\"button\" class=\"text-interface-close-btn\" id=\"textUnifiedCloseBtn\" aria-label=\"").concat(this.t('close'), "\" title=\"").concat(this.t('close'), "\">\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"m6 6 12 12M18 6 6 18\"/></svg>\n </button>\n </div>\n </div>");
37890
+ return "<div class=\"text-interface\" id=\"textInterface\" dir=\"".concat(textDirection, "\">\n ").concat(backBar, "\n <div class=\"messages-container\" id=\"messagesContainer\">\n <div class=\"empty-state\">\n <div class=\"empty-state-icon\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M20 11.5a7.5 7.5 0 0 1-7.75 7.5 8.9 8.9 0 0 1-3.5-.72L4 20l1.55-4.1A7.2 7.2 0 0 1 4.5 12 7.5 7.5 0 0 1 12.25 4.5 7.5 7.5 0 0 1 20 11.5Z\"/>\n <path d=\"M8.6 11.8h.01M12.1 11.8h.01M15.6 11.8h.01\" stroke-width=\"2.4\"/>\n </svg>\n </div>\n <div class=\"empty-state-title\">").concat(this.t('hello'), "</div>\n <div class=\"empty-state-text\">").concat(this.t('sendMessage'), "</div>\n </div>\n </div>\n <div class=\"input-container\">\n <button type=\"button\" class=\"text-interface-home-btn\" id=\"textUnifiedHomeBtn\" aria-label=\"").concat(this.t('home'), "\" title=\"").concat(this.t('home'), "\">\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M4.5 10.5 12 4l7.5 6.5v8.25a1.25 1.25 0 0 1-1.25 1.25h-4.5v-5.75h-3.5V20h-4.5a1.25 1.25 0 0 1-1.25-1.25V10.5Z\"/></svg>\n </button>\n <div class=\"input-wrapper\" style=\"flex:1;\">\n <textarea class=\"message-input\" id=\"messageInput\" placeholder=\"").concat(inputPlaceholder, "\" rows=\"1\" dir=\"").concat(textDirection, "\"></textarea>\n </div>\n <button class=\"send-button\" id=\"sendButton\" aria-label=\"").concat(this.t('sendMessageAria'), "\">\n <svg class=\"send-icon\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"m21 3-7.8 18-3.6-7.8L3 9.6 21 3Z\"/><path d=\"m9.6 13.2 4.2-3.6\"/></svg>\n </button>\n ").concat((_this$config$sendButt = this.config.sendButtonHint) !== null && _this$config$sendButt !== void 0 && _this$config$sendButt.text || (_this$config$panel2 = this.config.panel) !== null && _this$config$panel2 !== void 0 && (_this$config$panel2 = _this$config$panel2.sendButtonHint) !== null && _this$config$panel2 !== void 0 && _this$config$panel2.text ? "\n <div class=\"send-button-hint\" style=\"color: ".concat(((_this$config$sendButt2 = this.config.sendButtonHint) === null || _this$config$sendButt2 === void 0 ? void 0 : _this$config$sendButt2.color) || ((_this$config$panel3 = this.config.panel) === null || _this$config$panel3 === void 0 || (_this$config$panel3 = _this$config$panel3.sendButtonHint) === null || _this$config$panel3 === void 0 ? void 0 : _this$config$panel3.color) || '#6B7280', "; font-size: ").concat(((_this$config$sendButt3 = this.config.sendButtonHint) === null || _this$config$sendButt3 === void 0 ? void 0 : _this$config$sendButt3.fontSize) || ((_this$config$panel4 = this.config.panel) === null || _this$config$panel4 === void 0 || (_this$config$panel4 = _this$config$panel4.sendButtonHint) === null || _this$config$panel4 === void 0 ? void 0 : _this$config$panel4.fontSize) || '14px', "; text-align: center; margin-top: 4px;\">\n ").concat(((_this$config$sendButt4 = this.config.sendButtonHint) === null || _this$config$sendButt4 === void 0 ? void 0 : _this$config$sendButt4.text) || ((_this$config$panel5 = this.config.panel) === null || _this$config$panel5 === void 0 || (_this$config$panel5 = _this$config$panel5.sendButtonHint) === null || _this$config$panel5 === void 0 ? void 0 : _this$config$panel5.text), "\n </div>\n ") : '', "\n </div>\n <div class=\"text-interface-footer\">\n <span class=\"text-interface-powered\">Powered by <a href=\"").concat(brandUrl, "\" target=\"_blank\" rel=\"noopener noreferrer\"><b>").concat(brandName, "</b></a></span>\n <button type=\"button\" class=\"ttp-info-btn\" aria-label=\"").concat(this.t('aboutTitle') || 'About', "\" title=\"").concat(this.t('aboutTitle') || 'About', "\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"9\"/>\n <line x1=\"12\" y1=\"11\" x2=\"12\" y2=\"16\"/>\n <circle cx=\"12\" cy=\"7.7\" r=\"1.05\" fill=\"currentColor\" stroke=\"none\"/>\n </svg>\n </button>\n </div>\n </div>");
37576
37891
  }
37577
37892
 
37578
37893
  /**
@@ -37587,15 +37902,19 @@ var TextInterface = /*#__PURE__*/function () {
37587
37902
  var anim = this.config.animation;
37588
37903
  var useVoiceTheme = this.config.useVoiceTheme !== false;
37589
37904
  var voice = this.config.voice || {};
37905
+ var textDirection = this.textDirection;
37590
37906
 
37591
37907
  // Use text config, fallback to panel config for backward compatibility
37592
37908
  var sendButtonColor = this.config.sendButtonColor || ((_this$config$panel6 = this.config.panel) === null || _this$config$panel6 === void 0 ? void 0 : _this$config$panel6.sendButtonColor) || '#7C3AED';
37593
37909
  var sendButtonHoverColor = this.config.sendButtonHoverColor || ((_this$config$panel7 = this.config.panel) === null || _this$config$panel7 === void 0 ? void 0 : _this$config$panel7.sendButtonHoverColor) || '#6D28D9';
37594
37910
  var sendButtonTextColor = this.config.sendButtonTextColor || ((_this$config$panel8 = this.config.panel) === null || _this$config$panel8 === void 0 ? void 0 : _this$config$panel8.sendButtonTextColor) || '#FFFFFF';
37595
37911
  var inputPlaceholder = this.config.inputPlaceholder || ((_this$config$panel9 = this.config.panel) === null || _this$config$panel9 === void 0 ? void 0 : _this$config$panel9.inputPlaceholder) || 'Type your message...';
37596
- var inputFontSize = this.config.inputFontSize || ((_this$config$panel0 = this.config.panel) === null || _this$config$panel0 === void 0 ? void 0 : _this$config$panel0.inputFontSize) || '14px';
37912
+ // Keep the composer at >= 16px: iOS Safari auto-zooms the host page whenever a
37913
+ // focused field is smaller, which shifts the whole embedding site on tap.
37914
+ var inputFontSize = this.config.inputFontSize || ((_this$config$panel0 = this.config.panel) === null || _this$config$panel0 === void 0 ? void 0 : _this$config$panel0.inputFontSize) || '16px';
37597
37915
  var inputBorderRadius = this.config.inputBorderRadius || ((_this$config$panel1 = this.config.panel) === null || _this$config$panel1 === void 0 ? void 0 : _this$config$panel1.inputBorderRadius) || 20;
37598
- var inputPadding = this.config.inputPadding || ((_this$config$panel10 = this.config.panel) === null || _this$config$panel10 === void 0 ? void 0 : _this$config$panel10.inputPadding) || '6px 14px';
37916
+ var inputPadding = this.config.inputPadding || ((_this$config$panel10 = this.config.panel) === null || _this$config$panel10 === void 0 ? void 0 : _this$config$panel10.inputPadding) || '9px 12px';
37917
+ var messageFontSize = messages.fontSize || '15px';
37599
37918
  var panelLight;
37600
37919
  var topBarBg;
37601
37920
  var topBarBorder;
@@ -37630,31 +37949,31 @@ var TextInterface = /*#__PURE__*/function () {
37630
37949
  if (useVoiceTheme) {
37631
37950
  var p1 = firstHexFromVoiceColor(voice.primaryBtnGradient1 || voice.startCallButtonColor, '#6d56f5');
37632
37951
  var p2 = firstHexFromVoiceColor(voice.primaryBtnGradient2 || voice.startCallButtonColor, '#9d8df8');
37633
- var a1 = firstHexFromVoiceColor(voice.avatarGradient1, p1);
37634
- var a2 = firstHexFromVoiceColor(voice.avatarGradient2, p2);
37952
+ var a1 = firstHexFromVoiceColor(voice.avatarGradient1, '#6d56f5');
37953
+ var a2 = firstHexFromVoiceColor(voice.avatarGradient2, '#a78bfa');
37635
37954
  panelLight = false;
37636
- topBarBg = 'transparent';
37637
- topBarBorder = 'rgba(255,255,255,0.16)';
37638
- messagesAreaBg = 'rgba(255,255,255,0.09)';
37955
+ topBarBg = 'rgba(13, 8, 43, 0.9)';
37956
+ topBarBorder = 'rgba(219, 210, 255, 0.16)';
37957
+ messagesAreaBg = 'radial-gradient(circle at 22% 12%, rgba(116, 80, 255, 0.16), transparent 32%), linear-gradient(180deg, rgba(11, 7, 38, 0.4), rgba(8, 5, 29, 0.62))';
37639
37958
  backBtnColor = 'rgba(255,255,255,0.92)';
37640
37959
  backBtnHoverBg = 'rgba(255,255,255,0.14)';
37641
37960
  backBtnHoverColor = '#ffffff';
37642
37961
  emptyMuted = 'rgba(255,255,255,0.7)';
37643
37962
  emptyTitle = '#ffffff';
37644
- inputContainerBg = 'transparent';
37645
- inputContainerBorderTop = 'rgba(255,255,255,0.16)';
37646
- inputBorderColor = 'rgba(255,255,255,0.26)';
37963
+ inputContainerBg = 'rgba(12, 8, 38, 0.9)';
37964
+ inputContainerBorderTop = 'rgba(225, 219, 255, 0.18)';
37965
+ inputBorderColor = 'rgba(225, 219, 255, 0.26)';
37647
37966
  inputFocusColor = "".concat(p1, "e6");
37648
- inputBackgroundColor = 'rgba(255,255,255,0.12)';
37967
+ inputBackgroundColor = 'rgba(255,255,255,0.07)';
37649
37968
  inputTextColor = '#f8fafc';
37650
- inputFocusBg = 'rgba(255,255,255,0.18)';
37969
+ inputFocusBg = 'rgba(255,255,255,0.12)';
37651
37970
  inputFocusBoxShadow = "0 0 0 3px ".concat(p1, "59");
37652
37971
  placeholderColor = 'rgba(255,255,255,0.55)';
37653
- userBubbleBg = "".concat(p1, "73");
37972
+ userBubbleBg = '#7354e6';
37654
37973
  userBubbleTextColor = '#ffffff';
37655
- agentBubbleBg = 'rgba(255,255,255,0.16)';
37974
+ agentBubbleBg = '#35394f';
37656
37975
  agentBubbleTextColor = '#f8fafc';
37657
- agentBubbleBorder = '1px solid rgba(255,255,255,0.28)';
37976
+ agentBubbleBorder = '1px solid rgba(194, 201, 255, 0.22)';
37658
37977
  avatarAgentBg = "linear-gradient(135deg, ".concat(a1, ", ").concat(a2, ")");
37659
37978
  avatarUserBg = 'rgba(255,255,255,0.22)';
37660
37979
  avatarUserColor = 'rgba(255,255,255,0.95)';
@@ -37715,7 +38034,7 @@ var TextInterface = /*#__PURE__*/function () {
37715
38034
 
37716
38035
  // Add !important to display rules when not using Shadow DOM (to override theme CSS)
37717
38036
  var important = this.config.useShadowDOM === false ? ' !important' : '';
37718
- return "\n .text-interface-top-bar {\n flex-shrink: 0".concat(important, ";\n padding: 10px 12px 8px").concat(important, ";\n border-bottom: 1px solid ").concat(topBarBorder).concat(important, ";\n background: ").concat(topBarBg).concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: space-between").concat(important, ";\n }\n .text-interface-top-bar .ttp-info-btn {\n color: ").concat(backBtnColor).concat(important, ";\n }\n .text-interface-top-bar .ttp-info-btn:hover {\n background: ").concat(backBtnHoverBg).concat(important, ";\n color: ").concat(backBtnHoverColor).concat(important, ";\n }\n .text-interface-back-btn {\n display: inline-flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 6px").concat(important, ";\n padding: 6px 10px").concat(important, ";\n margin: 0").concat(important, ";\n border: none").concat(important, ";\n border-radius: 8px").concat(important, ";\n background: transparent").concat(important, ";\n color: ").concat(backBtnColor).concat(important, ";\n font-size: 16px").concat(important, ";\n font-weight: 600").concat(important, ";\n cursor: pointer").concat(important, ";\n font-family: inherit").concat(important, ";\n }\n .text-interface-back-btn:hover {\n background: ").concat(backBtnHoverBg).concat(important, ";\n color: ").concat(backBtnHoverColor).concat(important, ";\n }\n .text-interface-back-icon {\n font-size: 18px").concat(important, ";\n line-height: 1").concat(important, ";\n }\n .text-interface-back-label {\n line-height: 1.2").concat(important, ";\n }\n /* Messages container using new classes */\n #messagesContainer { \n flex: 1").concat(important, "; \n overflow-y: auto").concat(important, "; \n overflow-x: hidden").concat(important, "; \n padding: 20px").concat(important, "; \n background: ").concat(messagesAreaBg).concat(important, "; \n display: flex").concat(important, "; \n flex-direction: column").concat(important, "; \n gap: 16px").concat(important, "; \n min-height: 0").concat(important, "; \n }\n .empty-state { \n flex: 1").concat(important, "; \n display: flex").concat(important, "; \n flex-direction: column").concat(important, "; \n align-items: center").concat(important, "; \n justify-content: center").concat(important, "; \n gap: 12px").concat(important, "; \n color: ").concat(emptyMuted).concat(important, "; \n text-align: center").concat(important, "; \n padding: 20px").concat(important, "; \n }\n .empty-state-icon { font-size: 52px").concat(important, "; opacity: 0.3").concat(important, "; }\n .empty-state-title { font-size: 22px").concat(important, "; font-weight: 700").concat(important, "; color: ").concat(emptyTitle).concat(important, "; }\n .empty-state-text { font-size: 15px").concat(important, "; max-width: 300px").concat(important, "; line-height: 1.45").concat(important, "; }\n\n .text-interface { \n display: none").concat(important, "; \n flex: 1").concat(important, "; \n flex-direction: column").concat(important, "; \n min-height: 0").concat(important, "; \n overflow: hidden").concat(important, "; \n }\n .text-interface.active { display: flex").concat(important, "; }\n \n .message { \n display: flex").concat(important, "; \n gap: 8px").concat(important, "; \n padding: 4px 0").concat(important, "; \n max-width: 100%").concat(important, "; \n align-items: center").concat(important, "; \n }\n .message.edge-left { flex-direction: row").concat(important, "; }\n .message.edge-right { flex-direction: row-reverse").concat(important, "; }\n .message-bubble { \n padding: 14px 16px").concat(important, "; \n border-radius: ").concat(messages.borderRadius, "px").concat(important, "; \n max-width: 80%").concat(important, "; \n font-size: ").concat(messages.fontSize).concat(important, "; \n line-height: 1.45").concat(important, ";\n word-wrap: break-word").concat(important, "; \n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left').concat(important, "; \n direction: ").concat(this.config.direction || 'ltr', ";\n }\n .message.user .message-bubble { \n background: ").concat(userBubbleBg).concat(important, "; \n color: ").concat(userBubbleTextColor).concat(important, "; \n }\n .message.agent .message-bubble {\n background: ").concat(agentBubbleBg).concat(important, ";\n color: ").concat(agentBubbleTextColor).concat(important, ";\n border: ").concat(agentBubbleBorder).concat(important, ";\n max-width: 88%").concat(important, ";\n }\n\n /* ---------------------------------------------------------------\n Rendered markdown inside the agent bubble.\n Everything is scoped to .message-bubble so host-page styles can't\n reach in and the user bubble (plain text) is untouched.\n Logical properties (padding-inline-start, border-inline-start) keep\n the layout correct in RTL locales such as Hebrew.\n ---------------------------------------------------------------- */\n .message-bubble.md, .message-bubble .md-seg { line-height: 1.55").concat(important, "; }\n .message-bubble .md-seg { display: block").concat(important, "; }\n\n .message-bubble p {\n margin: 0 0 10px").concat(important, ";\n padding: 0").concat(important, ";\n }\n /* Deliberately gated on .md / .md-seg rather than a bare\n \".message-bubble > *\": the VOICE live-transcript row reuses the\n .message-bubble class in this same shadow root, and its children\n (.live-badge, .ttp-cursor) are not ours to restyle. */\n .message-bubble.md > *:last-child,\n .message-bubble .md-seg:last-child > *:last-child { margin-bottom: 0").concat(important, "; }\n .message-bubble.md > *:first-child,\n .message-bubble .md-seg:first-child > *:first-child { margin-top: 0").concat(important, "; }\n\n .message-bubble .md-h {\n margin: 16px 0 7px").concat(important, ";\n padding: 0").concat(important, ";\n font-weight: 700").concat(important, ";\n line-height: 1.3").concat(important, ";\n color: inherit").concat(important, ";\n }\n .message-bubble .md-h1 { font-size: 1.18em").concat(important, "; }\n .message-bubble .md-h2 { font-size: 1.09em").concat(important, "; }\n .message-bubble .md-h3 { font-size: 1.02em").concat(important, "; }\n .message-bubble .md-h4,\n .message-bubble .md-h5,\n .message-bubble .md-h6 {\n font-size: 0.95em").concat(important, ";\n letter-spacing: 0.02em").concat(important, ";\n color: ").concat(mdMuted).concat(important, ";\n }\n\n /* Logical properties only \u2014 a physical padding-left/border-left after\n these would resolve to the same property and silently win in LTR. */\n .message-bubble ul, .message-bubble ol {\n margin: 8px 0 11px").concat(important, ";\n padding-inline-start: 1.45em").concat(important, ";\n list-style-position: outside").concat(important, ";\n }\n .message-bubble ul { list-style-type: disc").concat(important, "; }\n .message-bubble ol { list-style-type: decimal").concat(important, "; }\n .message-bubble ul ul { list-style-type: circle").concat(important, "; }\n .message-bubble li {\n margin: 0 0 5px").concat(important, ";\n padding: 0").concat(important, ";\n line-height: 1.5").concat(important, ";\n }\n .message-bubble li:last-child { margin-bottom: 0").concat(important, "; }\n .message-bubble li::marker { color: ").concat(mdAccent).concat(important, "; }\n .message-bubble li > ul, .message-bubble li > ol { margin: 5px 0 2px").concat(important, "; }\n .message-bubble li > p { margin: 0 0 5px").concat(important, "; }\n\n .message-bubble strong, .message-bubble b { font-weight: 700").concat(important, "; }\n .message-bubble em, .message-bubble i { font-style: italic").concat(important, "; }\n .message-bubble del { text-decoration: line-through").concat(important, "; opacity: 0.7").concat(important, "; }\n\n .message-bubble a {\n color: ").concat(mdLink).concat(important, ";\n text-decoration: underline").concat(important, ";\n text-underline-offset: 2px").concat(important, ";\n word-break: break-word").concat(important, ";\n }\n .message-bubble a:hover { opacity: 0.82").concat(important, "; }\n\n .message-bubble code {\n font-family: ").concat(mdMono).concat(important, ";\n font-size: 0.88em").concat(important, ";\n background: ").concat(mdSubtleBg).concat(important, ";\n border: 1px solid ").concat(mdBorder).concat(important, ";\n border-radius: 5px").concat(important, ";\n padding: 1px 5px").concat(important, ";\n white-space: break-spaces").concat(important, ";\n word-break: break-word").concat(important, ";\n direction: ltr").concat(important, ";\n unicode-bidi: embed").concat(important, ";\n }\n .message-bubble pre {\n margin: 10px 0 11px").concat(important, ";\n padding: 10px 12px").concat(important, ";\n background: ").concat(mdSubtleBg).concat(important, ";\n border: 1px solid ").concat(mdBorder).concat(important, ";\n border-radius: 10px").concat(important, ";\n overflow-x: auto").concat(important, ";\n direction: ltr").concat(important, ";\n text-align: left").concat(important, ";\n }\n .message-bubble pre code {\n background: none").concat(important, ";\n border: none").concat(important, ";\n border-radius: 0").concat(important, ";\n padding: 0").concat(important, ";\n font-size: 0.85em").concat(important, ";\n line-height: 1.5").concat(important, ";\n white-space: pre").concat(important, ";\n word-break: normal").concat(important, ";\n }\n\n .message-bubble blockquote {\n margin: 10px 0").concat(important, ";\n padding-block: 2px").concat(important, ";\n padding-inline-start: 12px").concat(important, ";\n padding-inline-end: 0").concat(important, ";\n border-inline-start: 3px solid ").concat(mdAccent).concat(important, ";\n color: ").concat(mdMuted).concat(important, ";\n }\n .message-bubble blockquote > *:last-child { margin-bottom: 0").concat(important, "; }\n\n .message-bubble hr {\n border: none").concat(important, ";\n border-top: 1px solid ").concat(mdRule).concat(important, ";\n height: 0").concat(important, ";\n margin: 13px 0").concat(important, ";\n }\n\n .message-bubble .md-table-wrap {\n margin: 10px 0 11px").concat(important, ";\n overflow-x: auto").concat(important, ";\n border: 1px solid ").concat(mdBorder).concat(important, ";\n border-radius: 9px").concat(important, ";\n }\n .message-bubble table {\n border-collapse: collapse").concat(important, ";\n width: 100%").concat(important, ";\n font-size: 0.93em").concat(important, ";\n }\n .message-bubble th, .message-bubble td {\n padding: 7px 11px").concat(important, ";\n text-align: start").concat(important, ";\n border-bottom: 1px solid ").concat(mdBorder).concat(important, ";\n vertical-align: top").concat(important, ";\n }\n .message-bubble thead th {\n background: ").concat(mdSubtleBg).concat(important, ";\n font-weight: 700").concat(important, ";\n }\n .message-bubble tbody tr:nth-child(even) { background: ").concat(mdSubtlerBg).concat(important, "; }\n .message-bubble tbody tr:last-child td { border-bottom: none").concat(important, "; }\n\n .message-bubble .md-img {\n display: block").concat(important, ";\n max-width: 100%").concat(important, ";\n height: auto").concat(important, ";\n border-radius: 8px").concat(important, ";\n margin: 8px 0").concat(important, ";\n }\n\n .message.user { \n align-self: ").concat(this.config.direction === 'rtl' ? 'flex-start' : 'flex-end').concat(important, "; \n }\n .message.agent {\n align-self: ").concat(this.config.direction === 'rtl' ? 'flex-end' : 'flex-start').concat(important, ";\n /* structured answers can be tall \u2014 keep the avatar next to the first line */\n align-items: flex-start").concat(important, ";\n }\n .message.agent .message-avatar { margin-top: 7px").concat(important, "; }\n .message .message-bubble { \n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left', " !important; \n }\n ").concat(this.config.direction === 'rtl' ? "\n .message-bubble {\n text-align: right !important;\n }\n " : '', "\n .message-avatar { \n width: ").concat(avatarSize).concat(important, "; \n height: ").concat(avatarSize).concat(important, "; \n min-width: ").concat(avatarSize).concat(important, "; \n border-radius: 50%").concat(important, "; \n display: flex").concat(important, "; \n align-items: center").concat(important, "; \n justify-content: center").concat(important, "; \n flex-shrink: 0").concat(important, "; \n color: inherit").concat(important, "; \n font-size: ").concat(useVoiceTheme ? '14' : '20', "px").concat(important, "; \n line-height: 1").concat(important, "; \n background: transparent").concat(important, "; \n border: none").concat(important, "; \n box-sizing: border-box").concat(important, "; \n }\n .message-avatar.user { background: ").concat(avatarUserBg).concat(important, "; color: ").concat(avatarUserColor).concat(important, "; }\n .message-avatar.agent { background: ").concat(avatarAgentBg).concat(important, "; }\n \n .message.system {\n background: ").concat(messages.systemBackgroundColor, ";\n align-self: flex-start").concat(important, ";\n }\n .message.error {\n background: ").concat(messages.errorBackgroundColor, ";\n align-self: flex-start").concat(important, ";\n }\n \n .input-container {\n display: flex").concat(important, ";\n gap: 8px").concat(important, ";\n padding: 12px 16px").concat(important, ";\n background: ").concat(inputContainerBg).concat(important, ";\n border-top: 1px solid ").concat(inputContainerBorderTop).concat(important, ";\n align-items: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n flex-direction: ").concat(this.config.direction === 'rtl' ? 'row-reverse' : 'row').concat(important, ";\n }\n \n .input-wrapper {\n position: relative").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n }\n \n .message-input {\n width: 100%").concat(important, ";\n min-height: ").concat(TEXT_INPUT_MIN_HEIGHT_PX, "px").concat(important, ";\n max-height: ").concat(TEXT_INPUT_MAX_HEIGHT_PX, "px").concat(important, ";\n padding: ").concat(inputPadding, ";\n border: 1px solid ").concat(inputBorderColor, ";\n border-radius: ").concat(inputBorderRadius, "px;\n font-size: ").concat(inputFontSize, ";\n font-family: inherit").concat(important, ";\n line-height: 1.4").concat(important, ";\n resize: none").concat(important, ";\n overflow-y: auto").concat(important, ";\n background: ").concat(inputBackgroundColor, ";\n color: ").concat(inputTextColor, ";\n vertical-align: top").concat(important, ";\n margin: 0").concat(important, ";\n display: block").concat(important, ";\n white-space: pre-wrap").concat(important, ";\n word-wrap: break-word").concat(important, ";\n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left').concat(important, ";\n direction: ").concat(this.config.direction || 'ltr', ";\n -webkit-appearance: none").concat(important, ";\n appearance: none").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n \n .message-input:focus {\n outline: none").concat(important, ";\n border-color: ").concat(inputFocusColor, ";\n background: ").concat(inputFocusBg).concat(important, ";\n box-shadow: ").concat(inputFocusBoxShadow, ";\n }\n \n .message-input::placeholder {\n color: ").concat(placeholderColor).concat(important, ";\n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left').concat(important, ";\n }\n \n .send-button {\n width: 44px").concat(important, ";\n height: 44px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n background: ").concat(sendButtonColor, ";\n color: ").concat(sendButtonTextColor, ";\n font-size: ").concat(this.config.sendButtonFontSize || ((_this$config$panel15 = this.config.panel) === null || _this$config$panel15 === void 0 ? void 0 : _this$config$panel15.sendButtonFontSize) || '20px', ";\n font-weight: ").concat(this.config.sendButtonFontWeight || ((_this$config$panel16 = this.config.panel) === null || _this$config$panel16 === void 0 ? void 0 : _this$config$panel16.sendButtonFontWeight) || '500', ";\n cursor: pointer").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n transition: all 0.2s ease").concat(important, ";\n box-shadow: 0 4px 12px rgba(").concat(accentRgb[0], ", ").concat(accentRgb[1], ", ").concat(accentRgb[2], ", 0.32)").concat(important, ";\n }\n \n .send-button:hover:not(:disabled) {\n background: ").concat(sendButtonHoverColor, ";\n transform: scale(1.05)").concat(important, ";\n box-shadow: 0 6px 16px rgba(").concat(accentRgb[0], ", ").concat(accentRgb[1], ", ").concat(accentRgb[2], ", 0.42)").concat(important, ";\n }\n \n .send-button-hint {\n width: 100%").concat(important, ";\n text-align: center").concat(important, ";\n margin-top: 4px").concat(important, ";\n }\n \n .send-button:disabled {\n opacity: 0.5").concat(important, ";\n cursor: not-allowed").concat(important, ";\n }\n \n .typing-indicator {\n display: inline-flex").concat(important, ";\n gap: 4px").concat(important, ";\n align-items: center").concat(important, ";\n }\n \n .typing-dot {\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: rgba(").concat(accentRgb[0], ", ").concat(accentRgb[1], ", ").concat(accentRgb[2], ", ").concat(typingDotAlpha, ")").concat(important, ";\n animation: typingDot 1.4s ease-in-out infinite").concat(important, ";\n }\n \n .typing-dot:nth-child(2) { animation-delay: 0.2s").concat(important, "; }\n .typing-dot:nth-child(3) { animation-delay: 0.4s").concat(important, "; }\n \n @keyframes typingDot {\n 0%, 60%, 100% { transform: translateY(0); opacity: 0.7; }\n 30% { transform: translateY(-8px); opacity: 1; }\n }\n \n .error-message {\n padding: 12px").concat(important, ";\n background: ").concat(errorBubbleBg, ";\n border-radius: ").concat(messages.borderRadius, "px;\n color: ").concat(errorBubbleColor).concat(important, ";\n border: ").concat(errorBubbleBorder).concat(important, ";\n font-size: ").concat(messages.fontSize).concat(important, ";\n margin: 8px 0").concat(important, ";\n }\n \n ").concat(useVoiceTheme ? "\n #textInterface.active .input-container .send-button-hint {\n color: rgba(255,255,255,0.72)".concat(important, ";\n }\n ") : '', "\n \n @media (max-width: 768px) {\n #messagesContainer {\n padding: 12px").concat(important, ";\n gap: 12px").concat(important, ";\n }\n \n .message-bubble {\n max-width: 85%").concat(important, ";\n font-size: ").concat(messages.fontSize).concat(important, ";\n padding: 12px 14px").concat(important, ";\n }\n \n .text-input-container {\n padding: 10px").concat(important, ";\n gap: 8px").concat(important, ";\n }\n \n #text-chat-input {\n font-size: 16px !important; /* Prevents iOS zoom on focus */\n padding: 10px 14px").concat(important, ";\n min-height: 44px").concat(important, ";\n }\n \n #text-chat-send {\n min-width: 56px").concat(important, ";\n min-height: 44px").concat(important, ";\n width: 56px").concat(important, ";\n height: 44px").concat(important, ";\n }\n \n .empty-state-icon {\n font-size: 44px").concat(important, ";\n }\n \n .empty-state-title {\n font-size: 20px").concat(important, ";\n }\n \n .empty-state-text {\n font-size: 14px").concat(important, ";\n }\n }\n \n @media (max-width: 480px) {\n #messagesContainer {\n padding: 10px").concat(important, ";\n gap: 10px").concat(important, ";\n }\n \n .message-bubble {\n max-width: 90%").concat(important, ";\n font-size: ").concat(messages.fontSize).concat(important, ";\n padding: 10px 12px").concat(important, ";\n }\n \n .text-input-container {\n padding: 8px").concat(important, ";\n }\n \n #text-chat-input {\n font-size: 16px !important;\n padding: 8px 12px").concat(important, ";\n }\n }\n ");
38037
+ return "\n .text-interface-top-bar {\n flex-shrink: 0".concat(important, ";\n padding: 12px 14px").concat(important, ";\n border-bottom: 1px solid ").concat(topBarBorder).concat(important, ";\n background: ").concat(topBarBg).concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: flex-start").concat(important, ";\n gap: 10px").concat(important, ";\n direction: ").concat(textDirection).concat(important, ";\n }\n .text-interface-agent-heading {\n display: flex").concat(important, ";\n flex-direction: row").concat(important, ";\n align-items: center").concat(important, ";\n gap: 9px").concat(important, ";\n min-width: 0").concat(important, ";\n flex: 1").concat(important, ";\n margin-right: 0").concat(important, ";\n }\n .text-interface-agent-avatar {\n width: 36px").concat(important, ";\n height: 36px").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n flex: 0 0 36px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: ").concat(useVoiceTheme ? avatarAgentBg : "linear-gradient(135deg, ".concat(sendButtonColor, ", ").concat(sendButtonHoverColor, ")")).concat(important, ";\n border: none").concat(important, ";\n box-shadow: none").concat(important, ";\n }\n .text-interface-agent-initial { color: #fff").concat(important, "; font-size: 14px").concat(important, "; font-weight: 500").concat(important, "; line-height: 1").concat(important, "; }\n .text-interface-agent-copy {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n align-items: flex-start").concat(important, ";\n gap: 2px").concat(important, ";\n min-width: 0").concat(important, ";\n }\n .text-interface-agent-name {\n color: #f0eff8").concat(important, ";\n font-size: 14px").concat(important, ";\n font-weight: 500").concat(important, ";\n line-height: 1.15").concat(important, ";\n overflow: hidden").concat(important, ";\n text-overflow: ellipsis").concat(important, ";\n white-space: nowrap").concat(important, ";\n }\n .text-interface-agent-status {\n display: inline-flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 6px").concat(important, ";\n color: rgba(255,255,255,0.7)").concat(important, ";\n font-size: 10px").concat(important, ";\n }\n .text-interface-agent-status > span {\n width: 7px").concat(important, ";\n height: 7px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: #4ade80").concat(important, ";\n box-shadow: 0 0 10px rgba(74,222,128,0.75)").concat(important, ";\n }\n .text-interface-top-actions { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 4px").concat(important, "; margin-inline-start: auto").concat(important, "; }\n .text-interface-close-btn:hover,\n .text-interface-home-btn:hover,\n .text-interface-footer .ttp-info-btn:hover {\n background: rgba(255,255,255,0.22)").concat(important, ";\n color: #ffffff").concat(important, ";\n box-shadow: inset 0 1px 0 rgba(255,255,255,0.26), 0 4px 14px rgba(0,0,0,0.22)").concat(important, ";\n }\n .text-interface-close-btn,\n .text-interface-home-btn,\n .text-interface-footer .ttp-info-btn {\n width: 32px").concat(important, ";\n height: 32px").concat(important, ";\n display: grid").concat(important, ";\n place-items: center").concat(important, ";\n padding: 0").concat(important, ";\n margin: 0").concat(important, ";\n border: 1px solid rgba(255,255,255,0.14)").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: rgba(255,255,255,0.12)").concat(important, ";\n color: rgba(224,218,255,0.84)").concat(important, ";\n cursor: pointer").concat(important, ";\n font-family: inherit").concat(important, ";\n transition: background 0.18s ease, color 0.18s ease, box-shadow 0.18s ease").concat(important, ";\n box-shadow: inset 0 1px 0 rgba(255,255,255,0.14)").concat(important, ";\n }\n .text-interface-home-btn svg,\n .text-interface-close-btn svg,\n .text-interface-footer .ttp-info-btn svg { width: 18px").concat(important, "; height: 18px").concat(important, "; fill: none").concat(important, "; stroke: currentColor").concat(important, "; stroke-width: 1.9").concat(important, "; stroke-linecap: round").concat(important, "; stroke-linejoin: round").concat(important, "; }\n .text-interface-home-btn svg { fill: none").concat(important, "; stroke: currentColor").concat(important, "; width: 20px").concat(important, "; height: 20px").concat(important, "; stroke-width: 1.8").concat(important, "; }\n .input-container .text-interface-home-btn {\n width: 38px").concat(important, ";\n height: 38px").concat(important, ";\n color: rgba(224,218,255,0.84)").concat(important, ";\n background: rgba(255,255,255,0.12)").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n /* Messages container using new classes */\n #messagesContainer { \n flex: 1").concat(important, "; \n overflow-y: auto").concat(important, "; \n overflow-x: hidden").concat(important, "; \n padding: 20px").concat(important, "; \n background: ").concat(messagesAreaBg).concat(important, "; \n display: flex").concat(important, "; \n flex-direction: column").concat(important, "; \n gap: 16px").concat(important, "; \n min-height: 0").concat(important, "; \n }\n .empty-state { \n flex: 1").concat(important, "; \n display: flex").concat(important, "; \n flex-direction: column").concat(important, "; \n align-items: center").concat(important, "; \n justify-content: center").concat(important, "; \n gap: 12px").concat(important, "; \n color: ").concat(emptyMuted).concat(important, "; \n text-align: center").concat(important, "; \n padding: 20px").concat(important, "; \n }\n .empty-state-icon { font-size: 52px").concat(important, "; opacity: 0.3").concat(important, "; }\n .empty-state-title { font-size: 22px").concat(important, "; font-weight: 700").concat(important, "; color: ").concat(emptyTitle).concat(important, "; }\n .empty-state-text { font-size: 15px").concat(important, "; max-width: 300px").concat(important, "; line-height: 1.45").concat(important, "; }\n .empty-state-icon {\n width: 48px").concat(important, "; height: 48px").concat(important, "; border-radius: 16px").concat(important, ";\n display: grid").concat(important, "; place-items: center").concat(important, "; color: rgba(230,225,255,0.9)").concat(important, ";\n background: rgba(255,255,255,0.1)").concat(important, ";\n border: 1px solid rgba(225,219,255,0.18)").concat(important, ";\n }\n .empty-state-icon svg { width: 24px").concat(important, "; height: 24px").concat(important, "; }\n\n .text-interface { \n display: none").concat(important, "; \n flex: 1").concat(important, "; \n flex-direction: column").concat(important, "; \n min-height: 0").concat(important, "; \n overflow: hidden").concat(important, "; \n direction: ").concat(textDirection).concat(important, ";\n }\n .text-interface.active { display: flex").concat(important, "; }\n \n .message { \n display: flex").concat(important, "; \n flex-direction: column").concat(important, ";\n gap: 4px").concat(important, ";\n padding: 4px 0").concat(important, "; \n width: 100%").concat(important, ";\n max-width: 100%").concat(important, "; \n align-items: stretch").concat(important, ";\n }\n .message-bubble { \n position: relative").concat(important, ";\n padding: 10px ").concat(MESSAGE_META_GUTTER_PX, "px 10px 14px").concat(important, ";\n border-radius: 14px").concat(important, ";\n max-width: min(72%, 440px)").concat(important, ";\n font-size: ").concat(messageFontSize).concat(important, ";\n line-height: 1.45").concat(important, ";\n word-wrap: break-word").concat(important, "; \n box-shadow: ").concat(useVoiceTheme ? 'inset 0 1px 0 rgba(255,255,255,0.36), inset 0 -1px 0 rgba(5, 3, 26, 0.18), 0 8px 20px rgba(4, 3, 22, 0.24)' : 'none').concat(important, ";\n }\n .message-bubble[dir=\"rtl\"] { text-align: right").concat(important, "; direction: rtl").concat(important, "; }\n .message-bubble[dir=\"ltr\"] { text-align: left").concat(important, "; direction: ltr").concat(important, "; }\n .message-bubble::before {\n content: ''").concat(important, ";\n position: absolute").concat(important, ";\n top: 1px").concat(important, ";\n right: 1px").concat(important, ";\n left: 1px").concat(important, ";\n height: 48%").concat(important, ";\n border-radius: 11px 11px 8px 8px").concat(important, ";\n background: linear-gradient(180deg, rgba(255,255,255,0.19), rgba(255,255,255,0))").concat(important, ";\n pointer-events: none").concat(important, ";\n }\n .message.user .message-bubble { \n background: ").concat(userBubbleBg).concat(important, "; \n color: ").concat(userBubbleTextColor).concat(important, "; \n border-top-right-radius: 4px").concat(important, ";\n }\n .message.agent .message-bubble {\n background: ").concat(agentBubbleBg).concat(important, ";\n color: ").concat(agentBubbleTextColor).concat(important, ";\n border: ").concat(agentBubbleBorder).concat(important, ";\n border-top-left-radius: 4px").concat(important, ";\n }\n\n /* ---------------------------------------------------------------\n Rendered markdown inside the agent bubble.\n Everything is scoped to .message-bubble so host-page styles can't\n reach in and the user bubble (plain text) is untouched.\n Logical properties (padding-inline-start, border-inline-start) keep\n the layout correct in RTL locales such as Hebrew.\n ---------------------------------------------------------------- */\n .message-bubble.md, .message-bubble .md-seg { line-height: 1.55").concat(important, "; }\n .message-bubble .md-seg { display: block").concat(important, "; }\n\n .message-bubble p {\n margin: 0 0 10px").concat(important, ";\n padding: 0").concat(important, ";\n }\n /* Deliberately gated on .md / .md-seg rather than a bare\n \".message-bubble > *\": the VOICE live-transcript row reuses the\n .message-bubble class in this same shadow root, and its children\n (.live-badge, .ttp-cursor) are not ours to restyle. */\n .message-bubble.md > *:last-child,\n .message-bubble .md-seg:last-child > *:last-child { margin-bottom: 0").concat(important, "; }\n .message-bubble.md > *:first-child,\n .message-bubble .md-seg:first-child > *:first-child { margin-top: 0").concat(important, "; }\n\n .message-bubble .md-h {\n margin: 16px 0 7px").concat(important, ";\n padding: 0").concat(important, ";\n font-weight: 700").concat(important, ";\n line-height: 1.3").concat(important, ";\n color: inherit").concat(important, ";\n }\n .message-bubble .md-h1 { font-size: 1.18em").concat(important, "; }\n .message-bubble .md-h2 { font-size: 1.09em").concat(important, "; }\n .message-bubble .md-h3 { font-size: 1.02em").concat(important, "; }\n .message-bubble .md-h4,\n .message-bubble .md-h5,\n .message-bubble .md-h6 {\n font-size: 0.95em").concat(important, ";\n letter-spacing: 0.02em").concat(important, ";\n color: ").concat(mdMuted).concat(important, ";\n }\n\n /* Logical properties only \u2014 a physical padding-left/border-left after\n these would resolve to the same property and silently win in LTR. */\n .message-bubble ul, .message-bubble ol {\n margin: 8px 0 11px").concat(important, ";\n padding-inline-start: 1.45em").concat(important, ";\n list-style-position: outside").concat(important, ";\n }\n .message-bubble ul { list-style-type: disc").concat(important, "; }\n .message-bubble ol { list-style-type: decimal").concat(important, "; }\n .message-bubble ul ul { list-style-type: circle").concat(important, "; }\n .message-bubble li {\n margin: 0 0 5px").concat(important, ";\n padding: 0").concat(important, ";\n line-height: 1.5").concat(important, ";\n }\n .message-bubble li:last-child { margin-bottom: 0").concat(important, "; }\n .message-bubble li::marker { color: ").concat(mdAccent).concat(important, "; }\n .message-bubble li > ul, .message-bubble li > ol { margin: 5px 0 2px").concat(important, "; }\n .message-bubble li > p { margin: 0 0 5px").concat(important, "; }\n\n .message-bubble strong, .message-bubble b { font-weight: 700").concat(important, "; }\n .message-bubble em, .message-bubble i { font-style: italic").concat(important, "; }\n .message-bubble del { text-decoration: line-through").concat(important, "; opacity: 0.7").concat(important, "; }\n\n .message-bubble a {\n color: ").concat(mdLink).concat(important, ";\n text-decoration: underline").concat(important, ";\n text-underline-offset: 2px").concat(important, ";\n word-break: break-word").concat(important, ";\n }\n .message-bubble a:hover { opacity: 0.82").concat(important, "; }\n\n .message-bubble code {\n font-family: ").concat(mdMono).concat(important, ";\n font-size: 0.88em").concat(important, ";\n background: ").concat(mdSubtleBg).concat(important, ";\n border: 1px solid ").concat(mdBorder).concat(important, ";\n border-radius: 5px").concat(important, ";\n padding: 1px 5px").concat(important, ";\n white-space: break-spaces").concat(important, ";\n word-break: break-word").concat(important, ";\n direction: ltr").concat(important, ";\n unicode-bidi: embed").concat(important, ";\n }\n .message-bubble pre {\n margin: 10px 0 11px").concat(important, ";\n padding: 10px 12px").concat(important, ";\n background: ").concat(mdSubtleBg).concat(important, ";\n border: 1px solid ").concat(mdBorder).concat(important, ";\n border-radius: 10px").concat(important, ";\n overflow-x: auto").concat(important, ";\n direction: ltr").concat(important, ";\n text-align: left").concat(important, ";\n }\n .message-bubble pre code {\n background: none").concat(important, ";\n border: none").concat(important, ";\n border-radius: 0").concat(important, ";\n padding: 0").concat(important, ";\n font-size: 0.85em").concat(important, ";\n line-height: 1.5").concat(important, ";\n white-space: pre").concat(important, ";\n word-break: normal").concat(important, ";\n }\n\n .message-bubble blockquote {\n margin: 10px 0").concat(important, ";\n padding-block: 2px").concat(important, ";\n padding-inline-start: 12px").concat(important, ";\n padding-inline-end: 0").concat(important, ";\n border-inline-start: 3px solid ").concat(mdAccent).concat(important, ";\n color: ").concat(mdMuted).concat(important, ";\n }\n .message-bubble blockquote > *:last-child { margin-bottom: 0").concat(important, "; }\n\n .message-bubble hr {\n border: none").concat(important, ";\n border-top: 1px solid ").concat(mdRule).concat(important, ";\n height: 0").concat(important, ";\n margin: 13px 0").concat(important, ";\n }\n\n .message-bubble .md-table-wrap {\n margin: 10px 0 11px").concat(important, ";\n overflow-x: auto").concat(important, ";\n border: 1px solid ").concat(mdBorder).concat(important, ";\n border-radius: 9px").concat(important, ";\n }\n .message-bubble table {\n border-collapse: collapse").concat(important, ";\n width: 100%").concat(important, ";\n font-size: 0.93em").concat(important, ";\n }\n .message-bubble th, .message-bubble td {\n padding: 7px 11px").concat(important, ";\n text-align: start").concat(important, ";\n border-bottom: 1px solid ").concat(mdBorder).concat(important, ";\n vertical-align: top").concat(important, ";\n }\n .message-bubble thead th {\n background: ").concat(mdSubtleBg).concat(important, ";\n font-weight: 700").concat(important, ";\n }\n .message-bubble tbody tr:nth-child(even) { background: ").concat(mdSubtlerBg).concat(important, "; }\n .message-bubble tbody tr:last-child td { border-bottom: none").concat(important, "; }\n\n .message-bubble .md-img {\n display: block").concat(important, ";\n max-width: 100%").concat(important, ";\n height: auto").concat(important, ";\n border-radius: 8px").concat(important, ";\n margin: 8px 0").concat(important, ";\n }\n\n .message.user { \n align-self: stretch").concat(important, ";\n align-items: stretch").concat(important, ";\n }\n .message.agent {\n align-self: stretch").concat(important, ";\n align-items: stretch").concat(important, ";\n }\n .message.user .message-bubble {\n margin-left: auto").concat(important, ";\n margin-right: 0").concat(important, ";\n }\n .message.agent .message-bubble {\n margin-left: 0").concat(important, ";\n margin-right: auto").concat(important, ";\n }\n .message-meta {\n position: absolute").concat(important, ";\n right: ").concat(MESSAGE_META_INSET_PX, "px").concat(important, ";\n bottom: 9px").concat(important, ";\n z-index: 2").concat(important, ";\n display: inline-flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 5px").concat(important, ";\n margin: 0").concat(important, ";\n color: rgba(255,255,255,0.55)").concat(important, ";\n font-size: 10px").concat(important, ";\n line-height: 1").concat(important, ";\n direction: ltr").concat(important, ";\n white-space: nowrap").concat(important, ";\n pointer-events: none").concat(important, ";\n }\n .message.user .message-meta {\n color: rgba(255,255,255,0.74)").concat(important, ";\n }\n .message-content { position: relative").concat(important, "; z-index: 1").concat(important, "; display: inline").concat(important, "; overflow-wrap: anywhere").concat(important, "; word-break: break-word").concat(important, "; direction: inherit").concat(important, "; }\n .message-meta-spacer { display: inline-block").concat(important, "; width: 0").concat(important, "; height: 1px").concat(important, "; }\n .message-delivery-checks { color: rgba(255,255,255,0.92)").concat(important, "; font-weight: 700").concat(important, "; letter-spacing: -2px").concat(important, "; }\n .message-expand-button {\n position: relative").concat(important, ";\n z-index: 3").concat(important, ";\n margin: 0 4px").concat(important, ";\n padding: 0").concat(important, ";\n border: 0").concat(important, ";\n background: transparent").concat(important, ";\n color: #c4b5fd").concat(important, ";\n font: inherit").concat(important, ";\n font-size: 0.78em").concat(important, ";\n font-weight: 600").concat(important, ";\n line-height: inherit").concat(important, ";\n text-decoration: underline").concat(important, ";\n text-underline-offset: 2px").concat(important, ";\n cursor: pointer").concat(important, ";\n }\n .message-expand-button:hover { color: #ede9fe").concat(important, "; }\n .message-avatar { \n width: ").concat(avatarSize).concat(important, "; \n height: ").concat(avatarSize).concat(important, "; \n min-width: ").concat(avatarSize).concat(important, "; \n border-radius: 50%").concat(important, "; \n display: flex").concat(important, "; \n align-items: center").concat(important, "; \n justify-content: center").concat(important, "; \n flex-shrink: 0").concat(important, "; \n color: inherit").concat(important, "; \n font-size: ").concat(useVoiceTheme ? '14' : '20', "px").concat(important, "; \n line-height: 1").concat(important, "; \n background: transparent").concat(important, "; \n border: none").concat(important, "; \n box-sizing: border-box").concat(important, "; \n }\n .message-avatar.user { background: ").concat(avatarUserBg).concat(important, "; color: ").concat(avatarUserColor).concat(important, "; }\n .message-avatar.agent { background: ").concat(avatarAgentBg).concat(important, "; }\n \n .message.system {\n background: ").concat(messages.systemBackgroundColor, ";\n align-self: flex-start").concat(important, ";\n }\n .message.error {\n background: ").concat(messages.errorBackgroundColor, ";\n align-self: flex-start").concat(important, ";\n }\n \n .input-container {\n display: flex").concat(important, ";\n gap: 8px").concat(important, ";\n padding: 12px 16px").concat(important, ";\n background: ").concat(inputContainerBg).concat(important, ";\n border-top: 1px solid ").concat(inputContainerBorderTop).concat(important, ";\n align-items: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n flex-direction: row").concat(important, ";\n direction: ltr").concat(important, ";\n }\n .text-interface-footer {\n position: relative").concat(important, ";\n flex-shrink: 0").concat(important, ";\n min-height: 28px").concat(important, ";\n padding: 4px 12px").concat(important, ";\n background: ").concat(topBarBg).concat(important, ";\n border-top: 1px solid ").concat(inputContainerBorderTop).concat(important, ";\n display: flex").concat(important, ";\n justify-content: center").concat(important, ";\n align-items: center").concat(important, ";\n gap: 8px").concat(important, ";\n direction: ltr").concat(important, ";\n }\n .text-interface-footer .ttp-info-btn {\n position: absolute").concat(important, ";\n right: 12px").concat(important, ";\n margin-left: auto").concat(important, ";\n }\n .text-interface-powered {\n color: rgba(255,255,255,0.46)").concat(important, ";\n font-size: 10px").concat(important, ";\n line-height: 1.2").concat(important, ";\n text-align: center").concat(important, ";\n white-space: nowrap").concat(important, ";\n }\n .text-interface-powered a {\n color: ").concat(sendButtonColor).concat(important, ";\n text-decoration: none").concat(important, ";\n }\n .text-interface.active ~ .ttp-footer {\n display: none").concat(important, ";\n }\n \n .input-wrapper {\n position: relative").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n }\n \n .message-input {\n width: 100%").concat(important, ";\n min-height: ").concat(TEXT_INPUT_MIN_HEIGHT_PX, "px").concat(important, ";\n max-height: ").concat(TEXT_INPUT_MAX_HEIGHT_PX, "px").concat(important, ";\n padding: ").concat(inputPadding, ";\n border: 1px solid ").concat(inputBorderColor, ";\n border-radius: ").concat(inputBorderRadius, "px;\n font-size: ").concat(inputFontSize, ";\n font-family: inherit").concat(important, ";\n line-height: 1.4").concat(important, ";\n resize: none").concat(important, ";\n overflow-y: auto").concat(important, ";\n background: ").concat(inputBackgroundColor, ";\n color: ").concat(inputTextColor, ";\n vertical-align: top").concat(important, ";\n margin: 0").concat(important, ";\n display: block").concat(important, ";\n white-space: pre-wrap").concat(important, ";\n word-wrap: break-word").concat(important, ";\n text-align: start").concat(important, ";\n direction: ").concat(textDirection).concat(important, ";\n unicode-bidi: plaintext").concat(important, ";\n -webkit-appearance: none").concat(important, ";\n appearance: none").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n \n .message-input:focus {\n outline: none").concat(important, ";\n border-color: ").concat(inputFocusColor, ";\n background: ").concat(inputFocusBg).concat(important, ";\n box-shadow: ").concat(inputFocusBoxShadow, ";\n }\n \n .message-input::placeholder {\n color: ").concat(placeholderColor).concat(important, ";\n text-align: start").concat(important, ";\n direction: ").concat(textDirection).concat(important, ";\n }\n \n .send-button {\n width: 38px").concat(important, ";\n height: 38px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n background: linear-gradient(135deg, ").concat(sendButtonColor, ", ").concat(sendButtonHoverColor, ")").concat(important, ";\n color: ").concat(sendButtonTextColor, ";\n font-size: ").concat(this.config.sendButtonFontSize || ((_this$config$panel15 = this.config.panel) === null || _this$config$panel15 === void 0 ? void 0 : _this$config$panel15.sendButtonFontSize) || '16px', ";\n font-weight: ").concat(this.config.sendButtonFontWeight || ((_this$config$panel16 = this.config.panel) === null || _this$config$panel16 === void 0 ? void 0 : _this$config$panel16.sendButtonFontWeight) || '500', ";\n cursor: pointer").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n transition: all 0.2s ease").concat(important, ";\n box-shadow: 0 4px 12px rgba(").concat(accentRgb[0], ", ").concat(accentRgb[1], ", ").concat(accentRgb[2], ", 0.32)").concat(important, ";\n }\n .send-icon {\n width: 18px").concat(important, ";\n height: 18px").concat(important, ";\n fill: none").concat(important, ";\n stroke: currentColor").concat(important, ";\n stroke-width: 2.1").concat(important, ";\n stroke-linecap: round").concat(important, ";\n stroke-linejoin: round").concat(important, ";\n }\n \n .send-button:hover:not(:disabled) {\n background: ").concat(sendButtonHoverColor, ";\n transform: scale(1.05)").concat(important, ";\n box-shadow: 0 6px 16px rgba(").concat(accentRgb[0], ", ").concat(accentRgb[1], ", ").concat(accentRgb[2], ", 0.42)").concat(important, ";\n }\n \n .send-button-hint {\n width: 100%").concat(important, ";\n text-align: center").concat(important, ";\n margin-top: 4px").concat(important, ";\n }\n \n .send-button:disabled {\n opacity: 0.5").concat(important, ";\n cursor: not-allowed").concat(important, ";\n }\n \n .typing-indicator {\n display: inline-flex").concat(important, ";\n gap: 4px").concat(important, ";\n align-items: center").concat(important, ";\n }\n \n .typing-dot {\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: rgba(").concat(accentRgb[0], ", ").concat(accentRgb[1], ", ").concat(accentRgb[2], ", ").concat(typingDotAlpha, ")").concat(important, ";\n animation: typingDot 1.4s ease-in-out infinite").concat(important, ";\n }\n \n .typing-dot:nth-child(2) { animation-delay: 0.2s").concat(important, "; }\n .typing-dot:nth-child(3) { animation-delay: 0.4s").concat(important, "; }\n \n @keyframes typingDot {\n 0%, 60%, 100% { transform: translateY(0); opacity: 0.7; }\n 30% { transform: translateY(-8px); opacity: 1; }\n }\n \n .error-message {\n padding: 12px").concat(important, ";\n background: ").concat(errorBubbleBg, ";\n border-radius: ").concat(messages.borderRadius, "px;\n color: ").concat(errorBubbleColor).concat(important, ";\n border: ").concat(errorBubbleBorder).concat(important, ";\n font-size: ").concat(messageFontSize).concat(important, ";\n margin: 8px 0").concat(important, ";\n }\n \n ").concat(useVoiceTheme ? "\n #textInterface.active .input-container .send-button-hint {\n color: rgba(255,255,255,0.72)".concat(important, ";\n }\n ") : '', "\n \n @media (max-width: 768px) {\n #messagesContainer {\n padding: 12px").concat(important, ";\n gap: 12px").concat(important, ";\n }\n \n .message-bubble {\n max-width: 85%").concat(important, ";\n font-size: ").concat(messageFontSize).concat(important, ";\n padding: 11px ").concat(MESSAGE_META_GUTTER_PX, "px 11px 14px").concat(important, ";\n }\n \n .text-input-container {\n padding: 10px").concat(important, ";\n gap: 8px").concat(important, ";\n }\n \n #text-chat-input {\n font-size: 16px !important; /* Prevents iOS zoom on focus */\n padding: 10px 14px").concat(important, ";\n min-height: 44px").concat(important, ";\n }\n \n #text-chat-send {\n min-width: 56px").concat(important, ";\n min-height: 44px").concat(important, ";\n width: 56px").concat(important, ";\n height: 44px").concat(important, ";\n }\n \n .empty-state-icon {\n font-size: 44px").concat(important, ";\n }\n \n .empty-state-title {\n font-size: 20px").concat(important, ";\n }\n \n .empty-state-text {\n font-size: 14px").concat(important, ";\n }\n }\n \n @media (max-width: 480px) {\n #messagesContainer {\n padding: 10px").concat(important, ";\n gap: 10px").concat(important, ";\n }\n \n .message-bubble {\n max-width: 90%").concat(important, ";\n font-size: ").concat(messageFontSize).concat(important, ";\n padding: 10px ").concat(MESSAGE_META_GUTTER_PX, "px 10px 13px").concat(important, ";\n }\n \n .text-input-container {\n padding: 8px").concat(important, ";\n }\n \n #text-chat-input {\n font-size: 16px !important;\n padding: 8px 12px").concat(important, ";\n }\n }\n ");
37719
38038
  }
37720
38039
 
37721
38040
  /**
@@ -37759,7 +38078,10 @@ var TextInterface = /*#__PURE__*/function () {
37759
38078
  }, 0);
37760
38079
  }
37761
38080
  };
37762
- inputField.addEventListener('input', autoResize);
38081
+ inputField.addEventListener('input', function () {
38082
+ _this.updateInputWritingDirection(inputField);
38083
+ autoResize();
38084
+ });
37763
38085
  inputField.addEventListener('keydown', function (e) {
37764
38086
  if (e.key === 'Enter' && !e.shiftKey) {
37765
38087
  e.preventDefault();
@@ -37808,14 +38130,17 @@ var TextInterface = /*#__PURE__*/function () {
37808
38130
  // Update placeholder based on current language
37809
38131
  var inputPlaceholder = this.config.inputPlaceholder || ((_this$config$panel17 = this.config.panel) === null || _this$config$panel17 === void 0 ? void 0 : _this$config$panel17.inputPlaceholder) || this.t('typeMessage') || 'Type your message...';
37810
38132
  inputField.placeholder = inputPlaceholder;
37811
-
37812
- // Update direction
37813
- inputField.dir = this.config.direction || 'ltr';
37814
-
37815
- // Update text-align style
37816
- inputField.style.textAlign = this.config.direction === 'rtl' ? 'right' : 'left';
38133
+ this.updateInputWritingDirection(inputField);
37817
38134
  }
37818
38135
  }
38136
+ }, {
38137
+ key: "updateInputWritingDirection",
38138
+ value: function updateInputWritingDirection(inputField) {
38139
+ var direction = resolveInputTextDirection(inputField.value, this.textDirection);
38140
+ inputField.dir = direction;
38141
+ inputField.style.setProperty('direction', direction, 'important');
38142
+ inputField.style.setProperty('text-align', direction === 'rtl' ? 'right' : 'left', 'important');
38143
+ }
37819
38144
 
37820
38145
  /**
37821
38146
  * Show text interface
@@ -37901,6 +38226,7 @@ var TextInterface = /*#__PURE__*/function () {
37901
38226
  input.value = '';
37902
38227
  input.style.height = "".concat(TEXT_INPUT_MIN_HEIGHT_PX, "px");
37903
38228
  input.style.overflow = 'hidden';
38229
+ this.updateInputWritingDirection(input);
37904
38230
 
37905
38231
  // Prepare streaming bubble and send via SDK
37906
38232
  _context2.p = 3;
@@ -37947,10 +38273,38 @@ var TextInterface = /*#__PURE__*/function () {
37947
38273
  /**
37948
38274
  * Add message to UI
37949
38275
  */
38276
+ }, {
38277
+ key: "messageTime",
38278
+ value: function messageTime() {
38279
+ return new Intl.DateTimeFormat(undefined, {
38280
+ hour: '2-digit',
38281
+ minute: '2-digit',
38282
+ hour12: false
38283
+ }).format(new Date());
38284
+ }
38285
+ }, {
38286
+ key: "addMessageExpansion",
38287
+ value: function addMessageExpansion(content, text, spacer) {
38288
+ if (!spacer || text.length <= MESSAGE_COLLAPSE_THRESHOLD) return;
38289
+ var expanded = false;
38290
+ var button = document.createElement('button');
38291
+ button.type = 'button';
38292
+ button.className = 'message-expand-button';
38293
+ button.textContent = 'Read more';
38294
+ button.setAttribute('aria-expanded', 'false');
38295
+ content.textContent = collapseMessageText(text);
38296
+ button.addEventListener('click', function () {
38297
+ expanded = !expanded;
38298
+ content.textContent = expanded ? text : collapseMessageText(text);
38299
+ button.textContent = expanded ? 'Read less' : 'Read more';
38300
+ button.setAttribute('aria-expanded', String(expanded));
38301
+ });
38302
+ spacer.parentNode.insertBefore(button, spacer);
38303
+ }
37950
38304
  }, {
37951
38305
  key: "addMessage",
37952
38306
  value: function addMessage(type, text) {
37953
- var _this$config$messages, _this$config$messages2;
38307
+ var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
37954
38308
  var messages = this.shadowRoot.getElementById('messagesContainer');
37955
38309
  if (!messages) return;
37956
38310
 
@@ -37960,24 +38314,46 @@ var TextInterface = /*#__PURE__*/function () {
37960
38314
  emptyState.remove();
37961
38315
  }
37962
38316
  var message = document.createElement('div');
37963
- var edgeClass = this.config.direction === 'rtl' ? type === 'user' ? 'edge-left' : 'edge-right' : type === 'user' ? 'edge-right' : 'edge-left';
38317
+ var edgeClass = type === 'user' ? 'edge-right' : 'edge-left';
37964
38318
  message.className = "message ".concat(type, " ").concat(edgeClass);
37965
- var avatar = document.createElement('div');
37966
- avatar.className = "message-avatar ".concat(type);
37967
- var avatarIcon = type === 'user' ? ((_this$config$messages = this.config.messages) === null || _this$config$messages === void 0 ? void 0 : _this$config$messages.userAvatarIcon) || '👤' : ((_this$config$messages2 = this.config.messages) === null || _this$config$messages2 === void 0 ? void 0 : _this$config$messages2.agentAvatarIcon) || '🤖';
37968
- avatar.textContent = avatarIcon;
37969
38319
  var bubble = document.createElement('div');
37970
38320
  bubble.className = 'message-bubble';
38321
+ var messageDirection = resolveMessageTextDirection(text, this.textDirection);
38322
+ bubble.dir = messageDirection;
38323
+ var content = document.createElement(type === 'agent' ? 'div' : 'bdi');
38324
+ content.className = type === 'agent' ? 'message-content md' : 'message-content';
38325
+ content.dir = messageDirection;
37971
38326
  if (type === 'agent') {
37972
38327
  // Agent copy is markdown — render it so lists/bold/tables look designed.
37973
- bubble.classList.add('md');
37974
- (0,_markdown_js__WEBPACK_IMPORTED_MODULE_1__.renderMarkdownInto)(bubble, text);
38328
+ (0,_markdown_js__WEBPACK_IMPORTED_MODULE_1__.renderMarkdownInto)(content, text);
37975
38329
  } else {
37976
- bubble.textContent = text;
37977
- }
37978
-
37979
- // Order is controlled by edgeClass via flex-direction
37980
- message.appendChild(avatar);
38330
+ content.textContent = text;
38331
+ }
38332
+ var metaSpacer = document.createElement('span');
38333
+ metaSpacer.className = 'message-meta-spacer';
38334
+ metaSpacer.setAttribute('aria-hidden', 'true');
38335
+ var inlineElements = {
38336
+ content: content,
38337
+ spacer: metaSpacer
38338
+ };
38339
+ bubble.append.apply(bubble, _toConsumableArray(messageInlineOrder(this.textDirection).map(function (key) {
38340
+ return inlineElements[key];
38341
+ })));
38342
+ if (type !== 'agent') {
38343
+ this.addMessageExpansion(content, text, metaSpacer);
38344
+ }
38345
+ var meta = document.createElement('div');
38346
+ meta.className = 'message-meta';
38347
+ var time = document.createElement('span');
38348
+ time.textContent = options.time || this.messageTime();
38349
+ meta.appendChild(time);
38350
+ if (type === 'user') {
38351
+ var checks = document.createElement('span');
38352
+ checks.className = 'message-delivery-checks';
38353
+ checks.textContent = options.deliveryChecks === 1 ? '✓' : '✓✓';
38354
+ meta.appendChild(checks);
38355
+ }
38356
+ bubble.appendChild(meta);
37981
38357
  message.appendChild(bubble);
37982
38358
  messages.appendChild(message);
37983
38359
  messages.scrollTop = messages.scrollHeight;
@@ -37989,27 +38365,28 @@ var TextInterface = /*#__PURE__*/function () {
37989
38365
  }, {
37990
38366
  key: "beginStreaming",
37991
38367
  value: function beginStreaming() {
37992
- var _this$config$messages3;
37993
38368
  var messages = this.shadowRoot.getElementById('messagesContainer');
37994
38369
  if (!messages) return;
37995
38370
 
37996
38371
  // Clean any previous indicator
37997
38372
  this.stopStreamingState();
37998
38373
  var el = document.createElement('div');
37999
- var edgeClass = this.config.direction === 'rtl' ? 'edge-right' : 'edge-left';
38374
+ var edgeClass = 'edge-left';
38000
38375
  el.className = "message agent ".concat(edgeClass);
38001
38376
  el.id = 'agent-streaming';
38002
- var avatar = document.createElement('div');
38003
- avatar.className = 'message-avatar agent';
38004
- avatar.textContent = ((_this$config$messages3 = this.config.messages) === null || _this$config$messages3 === void 0 ? void 0 : _this$config$messages3.agentAvatarIcon) || '🤖';
38005
38377
  var bubble = document.createElement('div');
38006
38378
  bubble.className = 'message-bubble';
38379
+ bubble.dir = this.textDirection;
38007
38380
  // show typing dots until first chunk
38008
38381
  bubble.innerHTML = '<span class="typing-indicator"><span class="typing-dot"></span><span class="typing-dot"></span><span class="typing-dot"></span></span>';
38009
- el.appendChild(avatar);
38382
+ var meta = document.createElement('div');
38383
+ meta.className = 'message-meta';
38384
+ meta.textContent = this.messageTime();
38385
+ bubble.appendChild(meta);
38010
38386
  el.appendChild(bubble);
38011
38387
  messages.appendChild(el);
38012
38388
  this.streamingEl = bubble;
38389
+ this.streamingBubble = bubble;
38013
38390
  this.hasStartedStreaming = false;
38014
38391
  this._pendingMedia = []; // Buffer for images that arrive before next text chunk
38015
38392
  this._streamBuffer = ''; // Raw markdown of the segment currently being written
@@ -38039,7 +38416,9 @@ var TextInterface = /*#__PURE__*/function () {
38039
38416
  if (this._streamSegmentEl || !this.streamingEl) return this._streamSegmentEl;
38040
38417
  var seg = document.createElement('div');
38041
38418
  seg.className = 'md-seg md';
38042
- this.streamingEl.appendChild(seg);
38419
+ seg.dir = this.streamingEl.dir || this.textDirection;
38420
+ var meta = this.streamingEl.querySelector('.message-meta');
38421
+ this.streamingEl.insertBefore(seg, meta || null);
38043
38422
  this._streamSegmentEl = seg;
38044
38423
  return seg;
38045
38424
  }
@@ -38104,6 +38483,8 @@ var TextInterface = /*#__PURE__*/function () {
38104
38483
  value: function appendStreamingChunk(chunk) {
38105
38484
  if (!this.streamingEl || typeof chunk !== 'string' || chunk === '') return;
38106
38485
  this._clearTypingIndicator();
38486
+ var direction = resolveMessageTextDirection(this._streamBuffer + chunk, this.textDirection);
38487
+ if (this.streamingBubble) this.streamingBubble.dir = direction;
38107
38488
  this._streamBuffer += chunk;
38108
38489
  this._scheduleStreamRender();
38109
38490
  }
@@ -38241,6 +38622,8 @@ var TextInterface = /*#__PURE__*/function () {
38241
38622
  // so re-render from it. With media, the bubble is a mix of segments and
38242
38623
  // galleries that fullText can't describe — keep what streaming produced.
38243
38624
  if (!hasGalleries && typeof fullText === 'string' && fullText) {
38625
+ var direction = resolveMessageTextDirection(fullText, this.textDirection);
38626
+ if (this.streamingBubble) this.streamingBubble.dir = direction;
38244
38627
  this._streamBuffer = fullText;
38245
38628
  }
38246
38629
  this._renderStreamSegment();
@@ -38251,6 +38634,7 @@ var TextInterface = /*#__PURE__*/function () {
38251
38634
  var container = this.shadowRoot.getElementById('agent-streaming');
38252
38635
  if (container) container.id = '';
38253
38636
  this.streamingEl = null;
38637
+ this.streamingBubble = null;
38254
38638
  this._pendingMedia = [];
38255
38639
  }
38256
38640
  this.updateSendButtonState();
@@ -38266,6 +38650,7 @@ var TextInterface = /*#__PURE__*/function () {
38266
38650
  var existing = this.shadowRoot.getElementById('agent-streaming');
38267
38651
  if (existing) existing.remove();
38268
38652
  this.streamingEl = null;
38653
+ this.streamingBubble = null;
38269
38654
  this.hasStartedStreaming = false;
38270
38655
  this._streamBuffer = '';
38271
38656
  this._streamSegmentEl = null;
@@ -38283,11 +38668,11 @@ var TextInterface = /*#__PURE__*/function () {
38283
38668
  // Check if this is a domain validation error
38284
38669
  var isDomainError = error && (error.message === 'DOMAIN_NOT_WHITELISTED' || typeof error === 'string' && error.includes('DOMAIN_NOT_WHITELISTED') || error.message && error.message.includes('Domain not whitelisted') || typeof error === 'string' && error.includes('Domain not whitelisted'));
38285
38670
  if (isDomainError) {
38286
- var _this$config$messages4;
38671
+ var _this$config$messages;
38287
38672
  // Show domain error with title and message
38288
38673
  var errorContainer = document.createElement('div');
38289
38674
  errorContainer.className = 'error-message';
38290
- errorContainer.style.cssText = 'padding: 16px; margin: 12px; border-radius: 8px; background: ' + (((_this$config$messages4 = this.config.messages) === null || _this$config$messages4 === void 0 ? void 0 : _this$config$messages4.errorBackgroundColor) || '#FEE2E2') + ';';
38675
+ errorContainer.style.cssText = 'padding: 16px; margin: 12px; border-radius: 8px; background: ' + (((_this$config$messages = this.config.messages) === null || _this$config$messages === void 0 ? void 0 : _this$config$messages.errorBackgroundColor) || '#FEE2E2') + ';';
38291
38676
  var title = document.createElement('div');
38292
38677
  title.style.cssText = 'font-weight: 600; font-size: 17px; margin-bottom: 8px; color: #991B1B;';
38293
38678
  title.textContent = this.t('domainNotValidated');
@@ -38298,10 +38683,11 @@ var TextInterface = /*#__PURE__*/function () {
38298
38683
  errorContainer.appendChild(message);
38299
38684
  messages.appendChild(errorContainer);
38300
38685
  } else {
38301
- // Show regular error
38686
+ var text = typeof error === 'string' ? error : error && error.message;
38687
+ if (!text) return;
38302
38688
  var errorEl = document.createElement('div');
38303
38689
  errorEl.className = 'error-message';
38304
- errorEl.textContent = typeof error === 'string' ? error : (error === null || error === void 0 ? void 0 : error.message) || error;
38690
+ errorEl.textContent = text;
38305
38691
  messages.appendChild(errorEl);
38306
38692
  }
38307
38693
  messages.scrollTop = messages.scrollHeight;
@@ -44555,10 +44941,12 @@ __webpack_require__.r(__webpack_exports__);
44555
44941
  "hello": "Hello! How can I help?",
44556
44942
  "sendMessage": "Send a message to get started",
44557
44943
  "online": "Online",
44944
+ "chatAssistant": "Chat Assistant",
44558
44945
  "newChat": "New Chat",
44559
44946
  "back": "Back",
44560
44947
  "backToModeChoice": "Voice or text",
44561
44948
  "close": "Close",
44949
+ "home": "Home",
44562
44950
  "error": "Error",
44563
44951
  "typeMessage": "Type your message...",
44564
44952
  "sendMessageAria": "Send message",
@@ -44599,10 +44987,12 @@ __webpack_require__.r(__webpack_exports__);
44599
44987
  "hello": "שלום! איך אפשר לעזור?",
44600
44988
  "sendMessage": "שלח הודעה או עבור למצב קולי לשיחה בזמן אמת",
44601
44989
  "online": "מקוון",
44990
+ "chatAssistant": "עוזר צ׳אט",
44602
44991
  "newChat": "צ'אט חדש",
44603
44992
  "back": "חזור",
44604
44993
  "backToModeChoice": "קול או טקסט",
44605
44994
  "close": "סגור",
44995
+ "home": "דף הבית",
44606
44996
  "error": "שגיאה",
44607
44997
  "typeMessage": "הקלד הודעה...",
44608
44998
  "sendMessageAria": "שלח הודעה",
@@ -44643,10 +45033,12 @@ __webpack_require__.r(__webpack_exports__);
44643
45033
  "hello": "مرحبا! كيف يمكنني المساعدة؟",
44644
45034
  "sendMessage": "أرسل رسالة للبدء",
44645
45035
  "online": "متصل",
45036
+ "chatAssistant": "مساعد الدردشة",
44646
45037
  "newChat": "محادثة جديدة",
44647
45038
  "back": "رجوع",
44648
45039
  "backToModeChoice": "صوت أو نص",
44649
45040
  "close": "إغلاق",
45041
+ "home": "الرئيسية",
44650
45042
  "error": "خطأ",
44651
45043
  "typeMessage": "اكتب رسالة...",
44652
45044
  "sendMessageAria": "إرسال رسالة",
@@ -44687,10 +45079,12 @@ __webpack_require__.r(__webpack_exports__);
44687
45079
  "hello": "Привет! Как я могу помочь?",
44688
45080
  "sendMessage": "Отправьте сообщение для начала",
44689
45081
  "online": "В сети",
45082
+ "chatAssistant": "Чат-ассистент",
44690
45083
  "newChat": "Новый чат",
44691
45084
  "back": "Назад",
44692
45085
  "backToModeChoice": "Голос или текст",
44693
45086
  "close": "Закрыть",
45087
+ "home": "Главная",
44694
45088
  "error": "Ошибка",
44695
45089
  "typeMessage": "Введите сообщение...",
44696
45090
  "sendMessageAria": "Отправить сообщение",
@@ -44731,10 +45125,12 @@ __webpack_require__.r(__webpack_exports__);
44731
45125
  "hello": "¡Hola! ¿Cómo puedo ayudarte?",
44732
45126
  "sendMessage": "Envía un mensaje para comenzar",
44733
45127
  "online": "En línea",
45128
+ "chatAssistant": "Asistente de chat",
44734
45129
  "newChat": "Nuevo chat",
44735
45130
  "back": "Atrás",
44736
45131
  "backToModeChoice": "Voz o texto",
44737
45132
  "close": "Cerrar",
45133
+ "home": "Inicio",
44738
45134
  "error": "Error",
44739
45135
  "typeMessage": "Escribe un mensaje...",
44740
45136
  "sendMessageAria": "Enviar mensaje",
@@ -44775,10 +45171,12 @@ __webpack_require__.r(__webpack_exports__);
44775
45171
  "hello": "Bonjour! Comment puis-je vous aider?",
44776
45172
  "sendMessage": "Envoyez un message pour commencer",
44777
45173
  "online": "En ligne",
45174
+ "chatAssistant": "Assistant de chat",
44778
45175
  "newChat": "Nouveau chat",
44779
45176
  "back": "Retour",
44780
45177
  "backToModeChoice": "Voix ou texte",
44781
45178
  "close": "Fermer",
45179
+ "home": "Accueil",
44782
45180
  "error": "Erreur",
44783
45181
  "typeMessage": "Tapez votre message...",
44784
45182
  "sendMessageAria": "Envoyer un message",
@@ -44819,10 +45217,12 @@ __webpack_require__.r(__webpack_exports__);
44819
45217
  "hello": "Hallo! Wie kann ich helfen?",
44820
45218
  "sendMessage": "Senden Sie eine Nachricht zum Starten",
44821
45219
  "online": "Online",
45220
+ "chatAssistant": "Chat-Assistent",
44822
45221
  "newChat": "Neuer Chat",
44823
45222
  "back": "Zurück",
44824
45223
  "backToModeChoice": "Sprache oder Text",
44825
45224
  "close": "Schließen",
45225
+ "home": "Startseite",
44826
45226
  "error": "Fehler",
44827
45227
  "typeMessage": "Geben Sie eine Nachricht ein...",
44828
45228
  "sendMessageAria": "Nachricht senden",