mitra-interactions-sdk 1.0.63 → 1.0.64-rc.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.
package/dist/index.js CHANGED
@@ -386,7 +386,18 @@ function buildUrl(endpoint, params) {
386
386
  }
387
387
  return url;
388
388
  }
389
- async function tryRefreshToken() {
389
+ var refreshInFlight = null;
390
+ function tryRefreshToken() {
391
+ if (refreshInFlight) return refreshInFlight;
392
+ const attempt = doRefreshToken();
393
+ refreshInFlight = attempt;
394
+ const clear = () => {
395
+ if (refreshInFlight === attempt) refreshInFlight = null;
396
+ };
397
+ attempt.then(clear, clear);
398
+ return attempt;
399
+ }
400
+ async function doRefreshToken() {
390
401
  var _a, _b;
391
402
  const config = getConfig();
392
403
  if (!config.token || config.projectId == null || !config.baseURL) return false;
@@ -1377,6 +1388,7 @@ async function agentHttpPost(path, body) {
1377
1388
  if (typeof fetchFn !== "function") {
1378
1389
  throw new Error("Agent Chat (HTTP): fetch indispon\xEDvel. Use Node 18+ ou um browser.");
1379
1390
  }
1391
+ if (isTokenExpiring()) await tryRefreshToken();
1380
1392
  const resp = await fetchFn(`${getAgentHttpBase()}${path}`, {
1381
1393
  method: "POST",
1382
1394
  headers: {
@@ -1406,16 +1418,16 @@ async function httpSendPrompt(payload, taskId) {
1406
1418
  routeMessage({ type: "stream_end", taskId: resolvedTaskId });
1407
1419
  }
1408
1420
  }
1409
- function connect() {
1410
- if (ws && ws.readyState === WebSocket.OPEN) {
1411
- return Promise.resolve(ws);
1412
- }
1413
- if (connectPromise) return connectPromise;
1421
+ function isChannelError(err) {
1422
+ const msg = err instanceof Error ? err.message : String(err != null ? err : "");
1423
+ return /conexão fechada|timeout ao conectar|erro ao conectar/i.test(msg);
1424
+ }
1425
+ function openSocket() {
1414
1426
  const baseUrl = getWsUrl();
1415
1427
  const token = getRawToken();
1416
1428
  const separator = baseUrl.includes("?") ? "&" : "?";
1417
1429
  const url = `${baseUrl}${separator}token=${encodeURIComponent(token)}`;
1418
- connectPromise = new Promise((resolve, reject) => {
1430
+ return new Promise((resolve, reject) => {
1419
1431
  const socket = new WebSocket(url);
1420
1432
  let opened = false;
1421
1433
  const timer = setTimeout(() => {
@@ -1424,7 +1436,6 @@ function connect() {
1424
1436
  socket.close();
1425
1437
  } catch (e) {
1426
1438
  }
1427
- connectPromise = null;
1428
1439
  reject(new Error("Agent Chat: timeout ao conectar no WebSocket"));
1429
1440
  }
1430
1441
  }, 15e3);
@@ -1432,18 +1443,20 @@ function connect() {
1432
1443
  opened = true;
1433
1444
  clearTimeout(timer);
1434
1445
  ws = socket;
1435
- connectPromise = null;
1436
1446
  resolve(socket);
1437
1447
  };
1438
1448
  socket.onerror = () => {
1439
1449
  if (!opened) {
1440
1450
  clearTimeout(timer);
1441
- connectPromise = null;
1442
1451
  reject(new Error("Agent Chat: erro ao conectar no WebSocket"));
1443
1452
  }
1444
1453
  };
1445
1454
  socket.onclose = () => {
1446
1455
  if (ws === socket) ws = null;
1456
+ if (!opened) {
1457
+ clearTimeout(timer);
1458
+ reject(new Error("Agent Chat: conex\xE3o fechada"));
1459
+ }
1447
1460
  for (const [id, pending] of pendingRequests) {
1448
1461
  pending.reject(new Error("Agent Chat: conex\xE3o fechada"));
1449
1462
  pendingRequests.delete(id);
@@ -1452,7 +1465,29 @@ function connect() {
1452
1465
  };
1453
1466
  socket.onmessage = (event) => routeMessage(event.data);
1454
1467
  });
1455
- return connectPromise;
1468
+ }
1469
+ function connect() {
1470
+ if (ws && ws.readyState === WebSocket.OPEN) {
1471
+ return Promise.resolve(ws);
1472
+ }
1473
+ if (connectPromise) return connectPromise;
1474
+ const attempt = (async () => {
1475
+ if (isTokenExpiring()) await tryRefreshToken();
1476
+ try {
1477
+ return await openSocket();
1478
+ } catch (err) {
1479
+ if (!isChannelError(err)) throw err;
1480
+ const refreshed = await tryRefreshToken();
1481
+ if (!refreshed) throw err;
1482
+ return openSocket();
1483
+ }
1484
+ })();
1485
+ connectPromise = attempt;
1486
+ const clear = () => {
1487
+ if (connectPromise === attempt) connectPromise = null;
1488
+ };
1489
+ attempt.then(clear, clear);
1490
+ return attempt;
1456
1491
  }
1457
1492
  function routeMessage(raw) {
1458
1493
  var _a, _b;
@@ -1492,6 +1527,21 @@ function routeMessage(raw) {
1492
1527
  for (const handler of pendingHandlers.values()) handler(msg);
1493
1528
  }
1494
1529
  }
1530
+ function requestOverSocket(type, payload) {
1531
+ return connect().then((socket) => new Promise((resolve, reject) => {
1532
+ const requestId = nextRequestId();
1533
+ pendingRequests.set(requestId, {
1534
+ resolve: (data) => resolve(data),
1535
+ reject
1536
+ });
1537
+ try {
1538
+ socket.send(JSON.stringify({ type, requestId, payload }));
1539
+ } catch (err) {
1540
+ pendingRequests.delete(requestId);
1541
+ reject(err instanceof Error ? err : new Error(String(err)));
1542
+ }
1543
+ }));
1544
+ }
1495
1545
  var transport = {
1496
1546
  async ensureConnected() {
1497
1547
  if (isHttpEnabled()) return;
@@ -1504,20 +1554,14 @@ var transport = {
1504
1554
  if (data && data.ok === false) throw new Error(data.error || "Erro desconhecido");
1505
1555
  return (_a = data == null ? void 0 : data.data) != null ? _a : data;
1506
1556
  }
1507
- const socket = await connect();
1508
- const requestId = nextRequestId();
1509
- return new Promise((resolve, reject) => {
1510
- pendingRequests.set(requestId, {
1511
- resolve: (data) => resolve(data),
1512
- reject
1513
- });
1514
- try {
1515
- socket.send(JSON.stringify({ type, requestId, payload }));
1516
- } catch (err) {
1517
- pendingRequests.delete(requestId);
1518
- reject(err instanceof Error ? err : new Error(String(err)));
1519
- }
1520
- });
1557
+ try {
1558
+ return await requestOverSocket(type, payload);
1559
+ } catch (err) {
1560
+ if (!isChannelError(err)) throw err;
1561
+ const refreshed = await tryRefreshToken();
1562
+ if (!refreshed) throw err;
1563
+ return requestOverSocket(type, payload);
1564
+ }
1521
1565
  },
1522
1566
  send(type, payload, taskId) {
1523
1567
  if (isHttpEnabled()) {
@@ -1752,7 +1796,18 @@ function createMitraInstance(initialConfig) {
1752
1796
  }
1753
1797
  return data;
1754
1798
  }
1755
- async function tryRefreshToken2() {
1799
+ let refreshInFlight2 = null;
1800
+ function tryRefreshToken2() {
1801
+ if (refreshInFlight2) return refreshInFlight2;
1802
+ const attempt = doRefreshToken2();
1803
+ refreshInFlight2 = attempt;
1804
+ const clear = () => {
1805
+ if (refreshInFlight2 === attempt) refreshInFlight2 = null;
1806
+ };
1807
+ attempt.then(clear, clear);
1808
+ return attempt;
1809
+ }
1810
+ async function doRefreshToken2() {
1756
1811
  var _a2, _b;
1757
1812
  if (!_config.token || _config.projectId == null || !_config.baseURL) return false;
1758
1813
  try {
@@ -1771,6 +1826,7 @@ function createMitraInstance(initialConfig) {
1771
1826
  ...((_b = data.merge) == null ? void 0 : _b.integrationURL) ? { integrationURL: data.merge.integrationURL } : {}
1772
1827
  };
1773
1828
  _config = { ..._config, token: stripBearer(session.token) };
1829
+ updateGlobalToken(session.token);
1774
1830
  if (_config.onTokenRefresh) _config.onTokenRefresh(session);
1775
1831
  return true;
1776
1832
  }
@@ -1781,6 +1837,7 @@ function createMitraInstance(initialConfig) {
1781
1837
  try {
1782
1838
  const session = await refreshTokenSilently(_config.authUrl, _config.projectId);
1783
1839
  _config = { ..._config, token: stripBearer(session.token) };
1840
+ updateGlobalToken(session.token);
1784
1841
  if (_config.onTokenRefresh) _config.onTokenRefresh(session);
1785
1842
  return true;
1786
1843
  } catch (e) {
@@ -2089,6 +2146,26 @@ function stripBearer(token) {
2089
2146
  }
2090
2147
  return t;
2091
2148
  }
2149
+ function decodeJwtPayload(token) {
2150
+ try {
2151
+ const part = stripBearer(token).split(".")[1];
2152
+ if (!part) return null;
2153
+ const b64 = part.replace(/-/g, "+").replace(/_/g, "/");
2154
+ const padded = b64 + "=".repeat((4 - b64.length % 4) % 4);
2155
+ const json = typeof atob === "function" ? atob(padded) : Buffer.from(padded, "base64").toString("utf8");
2156
+ return JSON.parse(json);
2157
+ } catch (e) {
2158
+ return null;
2159
+ }
2160
+ }
2161
+ function isTokenExpiring(token, skewMs = 6e4) {
2162
+ const t = globalConfig == null ? void 0 : globalConfig.token;
2163
+ if (!t) return false;
2164
+ const payload = decodeJwtPayload(t);
2165
+ const exp = payload == null ? void 0 : payload.exp;
2166
+ if (typeof exp !== "number") return false;
2167
+ return exp * 1e3 - Date.now() < skewMs;
2168
+ }
2092
2169
  function readInjectedEnv() {
2093
2170
  if (typeof window === "undefined") return {};
2094
2171
  const env = window.__mitraEnv;