mitra-interactions-sdk 1.0.63 → 1.0.64-rc.0

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
@@ -1377,6 +1377,7 @@ async function agentHttpPost(path, body) {
1377
1377
  if (typeof fetchFn !== "function") {
1378
1378
  throw new Error("Agent Chat (HTTP): fetch indispon\xEDvel. Use Node 18+ ou um browser.");
1379
1379
  }
1380
+ if (isTokenExpiring()) await tryRefreshToken();
1380
1381
  const resp = await fetchFn(`${getAgentHttpBase()}${path}`, {
1381
1382
  method: "POST",
1382
1383
  headers: {
@@ -1406,16 +1407,16 @@ async function httpSendPrompt(payload, taskId) {
1406
1407
  routeMessage({ type: "stream_end", taskId: resolvedTaskId });
1407
1408
  }
1408
1409
  }
1409
- function connect() {
1410
- if (ws && ws.readyState === WebSocket.OPEN) {
1411
- return Promise.resolve(ws);
1412
- }
1413
- if (connectPromise) return connectPromise;
1410
+ function isChannelError(err) {
1411
+ const msg = err instanceof Error ? err.message : String(err != null ? err : "");
1412
+ return /conexão fechada|timeout ao conectar|erro ao conectar/i.test(msg);
1413
+ }
1414
+ function openSocket() {
1414
1415
  const baseUrl = getWsUrl();
1415
1416
  const token = getRawToken();
1416
1417
  const separator = baseUrl.includes("?") ? "&" : "?";
1417
1418
  const url = `${baseUrl}${separator}token=${encodeURIComponent(token)}`;
1418
- connectPromise = new Promise((resolve, reject) => {
1419
+ return new Promise((resolve, reject) => {
1419
1420
  const socket = new WebSocket(url);
1420
1421
  let opened = false;
1421
1422
  const timer = setTimeout(() => {
@@ -1424,7 +1425,6 @@ function connect() {
1424
1425
  socket.close();
1425
1426
  } catch (e) {
1426
1427
  }
1427
- connectPromise = null;
1428
1428
  reject(new Error("Agent Chat: timeout ao conectar no WebSocket"));
1429
1429
  }
1430
1430
  }, 15e3);
@@ -1432,18 +1432,20 @@ function connect() {
1432
1432
  opened = true;
1433
1433
  clearTimeout(timer);
1434
1434
  ws = socket;
1435
- connectPromise = null;
1436
1435
  resolve(socket);
1437
1436
  };
1438
1437
  socket.onerror = () => {
1439
1438
  if (!opened) {
1440
1439
  clearTimeout(timer);
1441
- connectPromise = null;
1442
1440
  reject(new Error("Agent Chat: erro ao conectar no WebSocket"));
1443
1441
  }
1444
1442
  };
1445
1443
  socket.onclose = () => {
1446
1444
  if (ws === socket) ws = null;
1445
+ if (!opened) {
1446
+ clearTimeout(timer);
1447
+ reject(new Error("Agent Chat: conex\xE3o fechada"));
1448
+ }
1447
1449
  for (const [id, pending] of pendingRequests) {
1448
1450
  pending.reject(new Error("Agent Chat: conex\xE3o fechada"));
1449
1451
  pendingRequests.delete(id);
@@ -1452,7 +1454,29 @@ function connect() {
1452
1454
  };
1453
1455
  socket.onmessage = (event) => routeMessage(event.data);
1454
1456
  });
1455
- return connectPromise;
1457
+ }
1458
+ function connect() {
1459
+ if (ws && ws.readyState === WebSocket.OPEN) {
1460
+ return Promise.resolve(ws);
1461
+ }
1462
+ if (connectPromise) return connectPromise;
1463
+ const attempt = (async () => {
1464
+ if (isTokenExpiring()) await tryRefreshToken();
1465
+ try {
1466
+ return await openSocket();
1467
+ } catch (err) {
1468
+ if (!isChannelError(err)) throw err;
1469
+ const refreshed = await tryRefreshToken();
1470
+ if (!refreshed) throw err;
1471
+ return openSocket();
1472
+ }
1473
+ })();
1474
+ connectPromise = attempt;
1475
+ const clear = () => {
1476
+ if (connectPromise === attempt) connectPromise = null;
1477
+ };
1478
+ attempt.then(clear, clear);
1479
+ return attempt;
1456
1480
  }
1457
1481
  function routeMessage(raw) {
1458
1482
  var _a, _b;
@@ -1492,6 +1516,21 @@ function routeMessage(raw) {
1492
1516
  for (const handler of pendingHandlers.values()) handler(msg);
1493
1517
  }
1494
1518
  }
1519
+ function requestOverSocket(type, payload) {
1520
+ return connect().then((socket) => new Promise((resolve, reject) => {
1521
+ const requestId = nextRequestId();
1522
+ pendingRequests.set(requestId, {
1523
+ resolve: (data) => resolve(data),
1524
+ reject
1525
+ });
1526
+ try {
1527
+ socket.send(JSON.stringify({ type, requestId, payload }));
1528
+ } catch (err) {
1529
+ pendingRequests.delete(requestId);
1530
+ reject(err instanceof Error ? err : new Error(String(err)));
1531
+ }
1532
+ }));
1533
+ }
1495
1534
  var transport = {
1496
1535
  async ensureConnected() {
1497
1536
  if (isHttpEnabled()) return;
@@ -1504,20 +1543,14 @@ var transport = {
1504
1543
  if (data && data.ok === false) throw new Error(data.error || "Erro desconhecido");
1505
1544
  return (_a = data == null ? void 0 : data.data) != null ? _a : data;
1506
1545
  }
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
- });
1546
+ try {
1547
+ return await requestOverSocket(type, payload);
1548
+ } catch (err) {
1549
+ if (!isChannelError(err)) throw err;
1550
+ const refreshed = await tryRefreshToken();
1551
+ if (!refreshed) throw err;
1552
+ return requestOverSocket(type, payload);
1553
+ }
1521
1554
  },
1522
1555
  send(type, payload, taskId) {
1523
1556
  if (isHttpEnabled()) {
@@ -1771,6 +1804,7 @@ function createMitraInstance(initialConfig) {
1771
1804
  ...((_b = data.merge) == null ? void 0 : _b.integrationURL) ? { integrationURL: data.merge.integrationURL } : {}
1772
1805
  };
1773
1806
  _config = { ..._config, token: stripBearer(session.token) };
1807
+ updateGlobalToken(session.token);
1774
1808
  if (_config.onTokenRefresh) _config.onTokenRefresh(session);
1775
1809
  return true;
1776
1810
  }
@@ -1781,6 +1815,7 @@ function createMitraInstance(initialConfig) {
1781
1815
  try {
1782
1816
  const session = await refreshTokenSilently(_config.authUrl, _config.projectId);
1783
1817
  _config = { ..._config, token: stripBearer(session.token) };
1818
+ updateGlobalToken(session.token);
1784
1819
  if (_config.onTokenRefresh) _config.onTokenRefresh(session);
1785
1820
  return true;
1786
1821
  } catch (e) {
@@ -2089,6 +2124,26 @@ function stripBearer(token) {
2089
2124
  }
2090
2125
  return t;
2091
2126
  }
2127
+ function decodeJwtPayload(token) {
2128
+ try {
2129
+ const part = stripBearer(token).split(".")[1];
2130
+ if (!part) return null;
2131
+ const b64 = part.replace(/-/g, "+").replace(/_/g, "/");
2132
+ const padded = b64 + "=".repeat((4 - b64.length % 4) % 4);
2133
+ const json = typeof atob === "function" ? atob(padded) : Buffer.from(padded, "base64").toString("utf8");
2134
+ return JSON.parse(json);
2135
+ } catch (e) {
2136
+ return null;
2137
+ }
2138
+ }
2139
+ function isTokenExpiring(token, skewMs = 6e4) {
2140
+ const t = globalConfig == null ? void 0 : globalConfig.token;
2141
+ if (!t) return false;
2142
+ const payload = decodeJwtPayload(t);
2143
+ const exp = payload == null ? void 0 : payload.exp;
2144
+ if (typeof exp !== "number") return false;
2145
+ return exp * 1e3 - Date.now() < skewMs;
2146
+ }
2092
2147
  function readInjectedEnv() {
2093
2148
  if (typeof window === "undefined") return {};
2094
2149
  const env = window.__mitraEnv;