notte-sdk 1.9.7 → 1.10.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.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var SDK_VERSION = true ? "1.9.7" : "dev";
2
+ var SDK_VERSION = true ? "1.10.0" : "dev";
3
3
  var SDK_PACKAGE_NAME = true ? "notte-sdk" : "notte-sdk";
4
4
 
5
5
  // src/version-check.ts
@@ -883,6 +883,11 @@ var createClient = (config = {}) => {
883
883
  const { opts, url } = await beforeRequest(options);
884
884
  return createSseClient({
885
885
  ...opts,
886
+ // Request interceptors can replace fetch when the stream starts.
887
+ fetch: (input, init) => {
888
+ const transport = opts.fetch;
889
+ return transport(input, init);
890
+ },
886
891
  body: opts.body,
887
892
  method,
888
893
  onRequest: async (url2, init) => {
@@ -970,11 +975,6 @@ var sessionProfileSave = (options) => (options.client ?? client).post({
970
975
  ...options.headers
971
976
  }
972
977
  });
973
- var getSessionScript = (options) => (options.client ?? client).get({
974
- security: [{ scheme: "bearer", type: "http" }],
975
- url: "/sessions/{session_id}/workflow/code",
976
- ...options
977
- });
978
978
  var sessionStop = (options) => (options.client ?? client).delete({
979
979
  security: [{ scheme: "bearer", type: "http" }],
980
980
  url: "/sessions/{session_id}/stop",
@@ -1041,11 +1041,25 @@ var sessionNetworkLogs = (options) => (options.client ?? client).get({
1041
1041
  url: "/sessions/{session_id}/network/logs",
1042
1042
  ...options
1043
1043
  });
1044
+ var sessionMouseReplay = (options) => (options.client ?? client).get({
1045
+ security: [{ scheme: "bearer", type: "http" }],
1046
+ url: "/sessions/{session_id}/replay/mouse",
1047
+ ...options
1048
+ });
1044
1049
  var sessionReplay = (options) => (options.client ?? client).get({
1045
1050
  security: [{ scheme: "bearer", type: "http" }],
1046
1051
  url: "/sessions/{session_id}/replay",
1047
1052
  ...options
1048
1053
  });
1054
+ var executeSessionFile = (options) => (options.client ?? client).post({
1055
+ security: [{ scheme: "bearer", type: "http" }],
1056
+ url: "/sessions/{session_id}/page/execute/file",
1057
+ ...options,
1058
+ headers: {
1059
+ "Content-Type": "application/json",
1060
+ ...options.headers
1061
+ }
1062
+ });
1049
1063
  var listSessionFiles = (options) => (options.client ?? client).get({
1050
1064
  security: [{ scheme: "bearer", type: "http" }],
1051
1065
  url: "/sessions/{session_id}/files",
@@ -1071,35 +1085,6 @@ var downloadSessionFile = (options) => (options.client ?? client).get({
1071
1085
  url: "/sessions/{session_id}/files/{file_id}",
1072
1086
  ...options
1073
1087
  });
1074
- var agentStart = (options) => (options.client ?? client).post({
1075
- security: [{ scheme: "bearer", type: "http" }],
1076
- url: "/agents/start",
1077
- ...options,
1078
- headers: {
1079
- "Content-Type": "application/json",
1080
- ...options.headers
1081
- }
1082
- });
1083
- var agentStatus = (options) => (options.client ?? client).get({
1084
- security: [{ scheme: "bearer", type: "http" }],
1085
- url: "/agents/{agent_id}",
1086
- ...options
1087
- });
1088
- var getScript = (options) => (options.client ?? client).get({
1089
- security: [{ scheme: "bearer", type: "http" }],
1090
- url: "/agents/{agent_id}/workflow/code",
1091
- ...options
1092
- });
1093
- var agentStop = (options) => (options.client ?? client).delete({
1094
- security: [{ scheme: "bearer", type: "http" }],
1095
- url: "/agents/{agent_id}/stop",
1096
- ...options
1097
- });
1098
- var listAgents = (options) => (options?.client ?? client).get({
1099
- security: [{ scheme: "bearer", type: "http" }],
1100
- url: "/agents",
1101
- ...options
1102
- });
1103
1088
  var functionRuntimeHealth = (options) => (options?.client ?? client).get({
1104
1089
  security: [{ scheme: "bearer", type: "http" }],
1105
1090
  url: "/functions/health",
@@ -1369,6 +1354,15 @@ var profileCookiesSet = (options) => (options.client ?? client).post({
1369
1354
  ...options.headers
1370
1355
  }
1371
1356
  });
1357
+ var profileStateSet = (options) => (options.client ?? client).post({
1358
+ security: [{ scheme: "bearer", type: "http" }],
1359
+ url: "/profiles/{profile_id}/state",
1360
+ ...options,
1361
+ headers: {
1362
+ "Content-Type": "application/json",
1363
+ ...options.headers
1364
+ }
1365
+ });
1372
1366
  var profileList = (options) => (options?.client ?? client).get({
1373
1367
  security: [{ scheme: "bearer", type: "http" }],
1374
1368
  url: "/profiles",
@@ -1563,6 +1557,215 @@ var searchWeb = (options) => (options.client ?? client).post({
1563
1557
  ...options.headers
1564
1558
  }
1565
1559
  });
1560
+ var summary = (options) => (options?.client ?? client).get({
1561
+ security: [{ scheme: "bearer", type: "http" }],
1562
+ url: "/data/analytics",
1563
+ ...options
1564
+ });
1565
+ var history_ = (options) => (options?.client ?? client).get({
1566
+ security: [{ scheme: "bearer", type: "http" }],
1567
+ url: "/data/analytics/requests",
1568
+ ...options
1569
+ });
1570
+ var detail = (options) => (options.client ?? client).get({
1571
+ security: [{ scheme: "bearer", type: "http" }],
1572
+ url: "/data/analytics/requests/{request_id}",
1573
+ ...options
1574
+ });
1575
+ var invalidate = (options) => (options?.client ?? client).delete({
1576
+ security: [{ scheme: "bearer", type: "http" }],
1577
+ url: "/data/cache",
1578
+ ...options
1579
+ });
1580
+ var getPolicy = (options) => (options?.client ?? client).get({
1581
+ security: [{ scheme: "bearer", type: "http" }],
1582
+ url: "/data/cache",
1583
+ ...options
1584
+ });
1585
+ var brandRetrieve = (options) => (options.client ?? client).post({
1586
+ security: [{ scheme: "bearer", type: "http" }],
1587
+ url: "/data/brand/retrieve",
1588
+ ...options,
1589
+ headers: {
1590
+ "Content-Type": "application/json",
1591
+ ...options.headers
1592
+ }
1593
+ });
1594
+ var extractProductEndpoint = (options) => (options.client ?? client).post({
1595
+ security: [{ scheme: "bearer", type: "http" }],
1596
+ url: "/data/products/extract",
1597
+ ...options,
1598
+ headers: {
1599
+ "Content-Type": "application/json",
1600
+ ...options.headers
1601
+ }
1602
+ });
1603
+ var styleguideEndpoint = (options) => (options?.client ?? client).get({
1604
+ security: [{ scheme: "bearer", type: "http" }],
1605
+ url: "/data/web/styleguide",
1606
+ ...options
1607
+ });
1608
+ var mapsSearch = (options) => (options.client ?? client).post({
1609
+ security: [{ scheme: "bearer", type: "http" }],
1610
+ url: "/data/maps/search",
1611
+ ...options,
1612
+ headers: {
1613
+ "Content-Type": "application/json",
1614
+ ...options.headers
1615
+ }
1616
+ });
1617
+ var listMonitors = (options) => (options?.client ?? client).get({
1618
+ security: [{ scheme: "bearer", type: "http" }],
1619
+ url: "/data/monitors",
1620
+ ...options
1621
+ });
1622
+ var create = (options) => (options.client ?? client).post({
1623
+ security: [{ scheme: "bearer", type: "http" }],
1624
+ url: "/data/monitors",
1625
+ ...options,
1626
+ headers: {
1627
+ "Content-Type": "application/json",
1628
+ ...options.headers
1629
+ }
1630
+ });
1631
+ var limits = (options) => (options?.client ?? client).get({
1632
+ security: [{ scheme: "bearer", type: "http" }],
1633
+ url: "/data/monitors/limits",
1634
+ ...options
1635
+ });
1636
+ var creditUsage = (options) => (options?.client ?? client).get({
1637
+ security: [{ scheme: "bearer", type: "http" }],
1638
+ url: "/data/monitors/credit-usage",
1639
+ ...options
1640
+ });
1641
+ var accountRuns = (options) => (options?.client ?? client).get({
1642
+ security: [{ scheme: "bearer", type: "http" }],
1643
+ url: "/data/monitors/runs",
1644
+ ...options
1645
+ });
1646
+ var accountChanges = (options) => (options?.client ?? client).get({
1647
+ security: [{ scheme: "bearer", type: "http" }],
1648
+ url: "/data/monitors/changes",
1649
+ ...options
1650
+ });
1651
+ var delete_ = (options) => (options.client ?? client).delete({
1652
+ security: [{ scheme: "bearer", type: "http" }],
1653
+ url: "/data/monitors/{monitor_id}",
1654
+ ...options
1655
+ });
1656
+ var retrieve = (options) => (options.client ?? client).get({
1657
+ security: [{ scheme: "bearer", type: "http" }],
1658
+ url: "/data/monitors/{monitor_id}",
1659
+ ...options
1660
+ });
1661
+ var update = (options) => (options.client ?? client).patch({
1662
+ security: [{ scheme: "bearer", type: "http" }],
1663
+ url: "/data/monitors/{monitor_id}",
1664
+ ...options,
1665
+ headers: {
1666
+ "Content-Type": "application/json",
1667
+ ...options.headers
1668
+ }
1669
+ });
1670
+ var runNow = (options) => (options.client ?? client).post({
1671
+ security: [{ scheme: "bearer", type: "http" }],
1672
+ url: "/data/monitors/{monitor_id}/run",
1673
+ ...options
1674
+ });
1675
+ var runs = (options) => (options.client ?? client).get({
1676
+ security: [{ scheme: "bearer", type: "http" }],
1677
+ url: "/data/monitors/{monitor_id}/runs",
1678
+ ...options
1679
+ });
1680
+ var changes = (options) => (options.client ?? client).get({
1681
+ security: [{ scheme: "bearer", type: "http" }],
1682
+ url: "/data/monitors/{monitor_id}/changes",
1683
+ ...options
1684
+ });
1685
+ var retrieveRun = (options) => (options.client ?? client).get({
1686
+ security: [{ scheme: "bearer", type: "http" }],
1687
+ url: "/data/monitors/{monitor_id}/runs/{run_id}",
1688
+ ...options
1689
+ });
1690
+ var retrieveChange = (options) => (options.client ?? client).get({
1691
+ security: [{ scheme: "bearer", type: "http" }],
1692
+ url: "/data/monitors/{monitor_id}/changes/{change_id}",
1693
+ ...options
1694
+ });
1695
+ var rotateSecret = (options) => (options.client ?? client).post({
1696
+ security: [{ scheme: "bearer", type: "http" }],
1697
+ url: "/data/monitors/{monitor_id}/webhook/rotate-secret",
1698
+ ...options
1699
+ });
1700
+ var deliveries = (options) => (options.client ?? client).post({
1701
+ security: [{ scheme: "bearer", type: "http" }],
1702
+ url: "/data/webhooks/deliveries",
1703
+ ...options,
1704
+ headers: {
1705
+ "Content-Type": "application/json",
1706
+ ...options.headers
1707
+ }
1708
+ });
1709
+ var retrieveDelivery = (options) => (options.client ?? client).get({
1710
+ security: [{ scheme: "bearer", type: "http" }],
1711
+ url: "/data/webhooks/deliveries/{delivery_id}",
1712
+ ...options
1713
+ });
1714
+ var attempts = (options) => (options.client ?? client).get({
1715
+ security: [{ scheme: "bearer", type: "http" }],
1716
+ url: "/data/webhooks/deliveries/{delivery_id}/attempts",
1717
+ ...options
1718
+ });
1719
+ var retry = (options) => (options.client ?? client).post({
1720
+ security: [{ scheme: "bearer", type: "http" }],
1721
+ url: "/data/webhooks/deliveries/{delivery_id}/retry",
1722
+ ...options,
1723
+ headers: {
1724
+ "Content-Type": "application/json",
1725
+ ...options.headers
1726
+ }
1727
+ });
1728
+ var peopleEnrich = (options) => (options.client ?? client).post({
1729
+ security: [{ scheme: "bearer", type: "http" }],
1730
+ url: "/data/people/enrich",
1731
+ ...options,
1732
+ headers: {
1733
+ "Content-Type": "application/json",
1734
+ ...options.headers
1735
+ }
1736
+ });
1737
+ var newsSearch = (options) => (options.client ?? client).post({
1738
+ security: [{ scheme: "bearer", type: "http" }],
1739
+ url: "/data/news/search",
1740
+ ...options,
1741
+ headers: {
1742
+ "Content-Type": "application/json",
1743
+ ...options.headers
1744
+ }
1745
+ });
1746
+ var fetchSpecializedData = (options) => (options.client ?? client).post({
1747
+ security: [{ scheme: "bearer", type: "http" }],
1748
+ url: "/data/web/fetch",
1749
+ ...options,
1750
+ headers: {
1751
+ "Content-Type": "application/json",
1752
+ ...options.headers
1753
+ }
1754
+ });
1755
+ var youtubeEndpoint = (options) => (options.client ?? client).post({
1756
+ security: [{ scheme: "bearer", type: "http" }],
1757
+ url: "/data/youtube/extract",
1758
+ ...options,
1759
+ headers: {
1760
+ "Content-Type": "application/json",
1761
+ ...options.headers
1762
+ }
1763
+ });
1764
+ var listDataApis = (options) => (options?.client ?? client).get({
1765
+ security: [{ scheme: "bearer", type: "http" }],
1766
+ url: "/data",
1767
+ ...options
1768
+ });
1566
1769
  var scrapeFromHtml = (options) => (options.client ?? client).post({
1567
1770
  security: [{ scheme: "bearer", type: "http" }],
1568
1771
  url: "/scrape_from_html",
@@ -1572,6 +1775,40 @@ var scrapeFromHtml = (options) => (options.client ?? client).post({
1572
1775
  ...options.headers
1573
1776
  }
1574
1777
  });
1778
+ var agentStart = (options) => (options.client ?? client).post({
1779
+ security: [{ scheme: "bearer", type: "http" }],
1780
+ url: "/agents/start",
1781
+ ...options,
1782
+ headers: {
1783
+ "Content-Type": "application/json",
1784
+ ...options.headers
1785
+ }
1786
+ });
1787
+ var agentStop = (options) => (options.client ?? client).delete({
1788
+ security: [{ scheme: "bearer", type: "http" }],
1789
+ url: "/agents/{agent_id}/stop",
1790
+ ...options
1791
+ });
1792
+ var agentStatus = (options) => (options.client ?? client).get({
1793
+ security: [{ scheme: "bearer", type: "http" }],
1794
+ url: "/agents/{agent_id}",
1795
+ ...options
1796
+ });
1797
+ var getScript = (options) => (options.client ?? client).get({
1798
+ security: [{ scheme: "bearer", type: "http" }],
1799
+ url: "/agents/{agent_id}/workflow/code",
1800
+ ...options
1801
+ });
1802
+ var listAgents = (options) => (options?.client ?? client).get({
1803
+ security: [{ scheme: "bearer", type: "http" }],
1804
+ url: "/agents",
1805
+ ...options
1806
+ });
1807
+ var getSessionScript = (options) => (options.client ?? client).get({
1808
+ security: [{ scheme: "bearer", type: "http" }],
1809
+ url: "/sessions/{session_id}/workflow/code",
1810
+ ...options
1811
+ });
1575
1812
 
1576
1813
  // src/managed-auth.ts
1577
1814
  import { setTimeout as delay } from "timers/promises";
@@ -1656,14 +1893,14 @@ var ActionExecutionError = class _ActionExecutionError extends NotteError {
1656
1893
  agentMessage;
1657
1894
  shouldRetryLater;
1658
1895
  shouldNotifyTeam;
1659
- constructor(detail) {
1660
- super(detail.dev_message || detail.user_message || detail.error_type);
1661
- this.errorType = detail.error_type;
1662
- this.devMessage = detail.dev_message;
1663
- this.userMessage = detail.user_message;
1664
- this.agentMessage = detail.agent_message;
1665
- this.shouldRetryLater = detail.should_retry_later ?? false;
1666
- this.shouldNotifyTeam = detail.should_notify_team ?? false;
1896
+ constructor(detail2) {
1897
+ super(detail2.dev_message || detail2.user_message || detail2.error_type);
1898
+ this.errorType = detail2.error_type;
1899
+ this.devMessage = detail2.dev_message;
1900
+ this.userMessage = detail2.user_message;
1901
+ this.agentMessage = detail2.agent_message;
1902
+ this.shouldRetryLater = detail2.should_retry_later ?? false;
1903
+ this.shouldNotifyTeam = detail2.should_notify_team ?? false;
1667
1904
  }
1668
1905
  static fromMessage(message, errorType = "NotteBaseError") {
1669
1906
  return new _ActionExecutionError({
@@ -1694,7 +1931,7 @@ function normalizeErrorBody(body) {
1694
1931
  return { message: typeof body === "string" ? body : String(body) };
1695
1932
  }
1696
1933
  var DEFAULT_RETRY_MESSAGE = "An error occurred while executing the function. Try again later...";
1697
- function retry(fn, options) {
1934
+ function retry2(fn, options) {
1698
1935
  const {
1699
1936
  maxTries,
1700
1937
  delayMs = 5e3,
@@ -1731,11 +1968,6 @@ function sleep(ms) {
1731
1968
  // src/managed-auth.ts
1732
1969
  var ManagedAuthError = class extends NotteError {
1733
1970
  };
1734
- function validateAuthRetry(value) {
1735
- if (!Number.isInteger(value) || value < 0 || value > 2) {
1736
- throw new InvalidRequestError("auth_retry must be an integer between 0 and 2");
1737
- }
1738
- }
1739
1971
  async function pollAuth(read, options) {
1740
1972
  const timeoutMs = options.timeoutMs ?? 615e3;
1741
1973
  const interval = options.pollIntervalMs ?? 1e3;
@@ -1816,12 +2048,10 @@ var NotteManagedAuth = class {
1816
2048
  return this.run(connectionId, "reauthenticate", options);
1817
2049
  }
1818
2050
  async run(connectionId, action, options) {
1819
- const authRetry = options.auth_retry ?? 0;
1820
- validateAuthRetry(authRetry);
1821
2051
  options.signal?.throwIfAborted();
1822
2052
  const response = await this.client.getClient().post({
1823
2053
  url: `/managed-auth/connections/${encodeURIComponent(connectionId)}/${action}`,
1824
- body: { auth_retry: authRetry },
2054
+ body: { auth_retry: options.auth_retry },
1825
2055
  headers: { "Content-Type": "application/json" },
1826
2056
  signal: options.signal,
1827
2057
  throwOnError: true
@@ -1856,7 +2086,7 @@ function createResources(client2, getApiKey) {
1856
2086
  },
1857
2087
  /** downloadSessionFile: /sessions/{session_id}/files/{file_id}. Returns the API response body. */
1858
2088
  downloadSessionFile: async (sessionId, fileId, requestOptions = {}) => {
1859
- const response = await downloadSessionFile({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId, "file_id": fileId } });
2089
+ const response = await downloadSessionFile({ client: client2, throwOnError: true, signal: requestOptions.signal, parseAs: "blob", headers: { ...requestOptions.headers }, path: { "session_id": sessionId, "file_id": fileId } });
1860
2090
  return response.data;
1861
2091
  },
1862
2092
  /** pageExecute: /sessions/{session_id}/page/execute. Returns the API response body. */
@@ -1864,6 +2094,11 @@ function createResources(client2, getApiKey) {
1864
2094
  const response = await pageExecute({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId }, body, query });
1865
2095
  return response.data;
1866
2096
  },
2097
+ /** executeSessionFile: /sessions/{session_id}/page/execute/file. Returns the API response body. */
2098
+ executeSessionFile: async (sessionId, body, query = void 0, requestOptions = {}) => {
2099
+ const response = await executeSessionFile({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId }, body, query });
2100
+ return response.data;
2101
+ },
1867
2102
  /** sessionCookiesGet: /sessions/{session_id}/cookies. Returns the API response body. */
1868
2103
  getCookies: async (sessionId, query = void 0, requestOptions = {}) => {
1869
2104
  const response = await sessionCookiesGet({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId }, query });
@@ -1884,6 +2119,11 @@ function createResources(client2, getApiKey) {
1884
2119
  const response = await listSessionFiles({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId }, query });
1885
2120
  return response.data;
1886
2121
  },
2122
+ /** sessionMouseReplay: /sessions/{session_id}/replay/mouse. Returns the API response body. */
2123
+ mouseReplay: async (sessionId, query = void 0, requestOptions = {}) => {
2124
+ const response = await sessionMouseReplay({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId }, query });
2125
+ return response.data;
2126
+ },
1887
2127
  /** sessionNetworkLogs: /sessions/{session_id}/network/logs. Returns the API response body. */
1888
2128
  networkLogs: async (sessionId, query = void 0, requestOptions = {}) => {
1889
2129
  const response = await sessionNetworkLogs({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId }, query });
@@ -1909,16 +2149,16 @@ function createResources(client2, getApiKey) {
1909
2149
  const response = await sessionProfilePreview({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId }, query });
1910
2150
  return response.data;
1911
2151
  },
1912
- /** sessionProfileSave: /sessions/{session_id}/profile/save. Returns the API response body. */
1913
- profileSave: async (sessionId, body, requestOptions = {}) => {
1914
- const response = await sessionProfileSave({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId }, body });
1915
- return response.data;
1916
- },
1917
2152
  /** sessionReplay: /sessions/{session_id}/replay. Returns the API response body. */
1918
2153
  replay: async (sessionId, requestOptions = {}) => {
1919
2154
  const response = await sessionReplay({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId } });
1920
2155
  return response.data;
1921
2156
  },
2157
+ /** sessionProfileSave: /sessions/{session_id}/profile/save. Returns the API response body. */
2158
+ saveProfile: async (sessionId, body, requestOptions = {}) => {
2159
+ const response = await sessionProfileSave({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId }, body });
2160
+ return response.data;
2161
+ },
1922
2162
  /** pageScrape: /sessions/{session_id}/page/scrape. Returns the API response body. */
1923
2163
  scrape: async (sessionId, body, query = void 0, requestOptions = {}) => {
1924
2164
  const response = await pageScrape({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId }, body, query });
@@ -1950,30 +2190,30 @@ function createResources(client2, getApiKey) {
1950
2190
  return response.data;
1951
2191
  }
1952
2192
  },
1953
- agents: {
1954
- /** getScript: /agents/{agent_id}/workflow/code. Returns the API response body. */
1955
- getScript: async (agentId, query, requestOptions = {}) => {
1956
- const response = await getScript({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "agent_id": agentId }, query });
2193
+ files: {
2194
+ /** deleteSessionFile: /sessions/{session_id}/files/{file_id}. Returns the API response body. */
2195
+ delete: async (sessionId, fileId, requestOptions = {}) => {
2196
+ const response = await deleteSessionFile({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId, "file_id": fileId } });
1957
2197
  return response.data;
1958
2198
  },
1959
- /** listAgents: /agents. Returns the API response body. */
1960
- list: async (query = void 0, requestOptions = {}) => {
1961
- const response = await listAgents({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, query });
2199
+ /** downloadSessionFile: /sessions/{session_id}/files/{file_id}. Returns the API response body. */
2200
+ download: async (sessionId, fileId, requestOptions = {}) => {
2201
+ const response = await downloadSessionFile({ client: client2, throwOnError: true, signal: requestOptions.signal, parseAs: "blob", headers: { ...requestOptions.headers }, path: { "session_id": sessionId, "file_id": fileId } });
1962
2202
  return response.data;
1963
2203
  },
1964
- /** agentStart: /agents/start. Returns the API response body. */
1965
- start: async (body, requestOptions = {}) => {
1966
- const response = await agentStart({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, body });
2204
+ /** executeSessionFile: /sessions/{session_id}/page/execute/file. Returns the API response body. */
2205
+ execute: async (sessionId, body, query = void 0, requestOptions = {}) => {
2206
+ const response = await executeSessionFile({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId }, body, query });
1967
2207
  return response.data;
1968
2208
  },
1969
- /** agentStatus: /agents/{agent_id}. Returns the API response body. */
1970
- status: async (agentId, requestOptions = {}) => {
1971
- const response = await agentStatus({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "agent_id": agentId } });
2209
+ /** listSessionFiles: /sessions/{session_id}/files. Returns the API response body. */
2210
+ list: async (sessionId, query = void 0, requestOptions = {}) => {
2211
+ const response = await listSessionFiles({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId }, query });
1972
2212
  return response.data;
1973
2213
  },
1974
- /** agentStop: /agents/{agent_id}/stop. Returns the API response body. */
1975
- stop: async (agentId, query, requestOptions = {}) => {
1976
- const response = await agentStop({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "agent_id": agentId }, query });
2214
+ /** uploadSessionFile: /sessions/{session_id}/files. Returns the API response body. */
2215
+ upload: async (sessionId, body, requestOptions = {}) => {
2216
+ const response = await uploadSessionFile({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId }, body });
1977
2217
  return response.data;
1978
2218
  }
1979
2219
  },
@@ -2054,8 +2294,8 @@ function createResources(client2, getApiKey) {
2054
2294
  return response.data;
2055
2295
  },
2056
2296
  /** functionRuntimeHealth: /functions/health. Returns the API response body. */
2057
- runtimeHealth: async (requestOptions = {}) => {
2058
- const response = await functionRuntimeHealth({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers } });
2297
+ runtimeHealth: async (requestOptions = {}, query = void 0) => {
2298
+ const response = await functionRuntimeHealth({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, query });
2059
2299
  return response.data;
2060
2300
  },
2061
2301
  /** functionScheduleSet: /functions/{function_id}/schedule. Returns the API response body. */
@@ -2069,6 +2309,43 @@ function createResources(client2, getApiKey) {
2069
2309
  return response.data;
2070
2310
  }
2071
2311
  },
2312
+ personas: {
2313
+ /** personaCreate: /personas/create. Returns the API response body. */
2314
+ create: async (body, requestOptions = {}) => {
2315
+ const response = await personaCreate({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, body });
2316
+ return response.data;
2317
+ },
2318
+ /** personaDelete: /personas/{persona_id}. Returns the API response body. */
2319
+ delete: async (personaId, requestOptions = {}) => {
2320
+ const response = await personaDelete({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "persona_id": personaId } });
2321
+ return response.data;
2322
+ },
2323
+ /** personaEmailsList: /personas/{persona_id}/emails. Returns the API response body. */
2324
+ emailsList: async (personaId, query = void 0, requestOptions = {}) => {
2325
+ const response = await personaEmailsList({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "persona_id": personaId }, query });
2326
+ return response.data;
2327
+ },
2328
+ /** personaGet: /personas/{persona_id}. Returns the API response body. */
2329
+ get: async (personaId, requestOptions = {}) => {
2330
+ const response = await personaGet({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "persona_id": personaId } });
2331
+ return response.data;
2332
+ },
2333
+ /** listPersonas: /personas. Returns the API response body. */
2334
+ list: async (query = void 0, requestOptions = {}) => {
2335
+ const response = await listPersonas({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, query });
2336
+ return response.data;
2337
+ },
2338
+ /** personaSmsList: /personas/{persona_id}/sms. Returns the API response body. */
2339
+ smsList: async (personaId, query = void 0, requestOptions = {}) => {
2340
+ const response = await personaSmsList({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "persona_id": personaId }, query });
2341
+ return response.data;
2342
+ },
2343
+ /** personaUpdate: /personas/{persona_id}. Returns the API response body. */
2344
+ update: async (personaId, body, requestOptions = {}) => {
2345
+ const response = await personaUpdate({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "persona_id": personaId }, body });
2346
+ return response.data;
2347
+ }
2348
+ },
2072
2349
  vaults: {
2073
2350
  /** vaultCreate: /vaults/create. Returns the API response body. */
2074
2351
  create: async (body, requestOptions = {}) => {
@@ -2106,60 +2383,23 @@ function createResources(client2, getApiKey) {
2106
2383
  return response.data;
2107
2384
  },
2108
2385
  /** vaultCreditCardSet: /vaults/{vault_id}/card. Returns the API response body. */
2109
- creditCardSet: async (vaultId, body, requestOptions = {}) => {
2110
- const response = await vaultCreditCardSet({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "vault_id": vaultId }, body });
2111
- return response.data;
2112
- },
2113
- /** vaultDelete: /vaults/{vault_id}. Returns the API response body. */
2114
- delete: async (vaultId, requestOptions = {}) => {
2115
- const response = await vaultDelete({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "vault_id": vaultId } });
2116
- return response.data;
2117
- },
2118
- /** listVaults: /vaults. Returns the API response body. */
2119
- list: async (query = void 0, requestOptions = {}) => {
2120
- const response = await listVaults({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, query });
2121
- return response.data;
2122
- },
2123
- /** vaultUpdate: /vaults/{vault_id}. Returns the API response body. */
2124
- update: async (vaultId, body, requestOptions = {}) => {
2125
- const response = await vaultUpdate({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "vault_id": vaultId }, body });
2126
- return response.data;
2127
- }
2128
- },
2129
- personas: {
2130
- /** personaCreate: /personas/create. Returns the API response body. */
2131
- create: async (body, requestOptions = {}) => {
2132
- const response = await personaCreate({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, body });
2133
- return response.data;
2134
- },
2135
- /** personaDelete: /personas/{persona_id}. Returns the API response body. */
2136
- delete: async (personaId, requestOptions = {}) => {
2137
- const response = await personaDelete({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "persona_id": personaId } });
2138
- return response.data;
2139
- },
2140
- /** personaEmailsList: /personas/{persona_id}/emails. Returns the API response body. */
2141
- emailsList: async (personaId, query = void 0, requestOptions = {}) => {
2142
- const response = await personaEmailsList({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "persona_id": personaId }, query });
2143
- return response.data;
2144
- },
2145
- /** personaGet: /personas/{persona_id}. Returns the API response body. */
2146
- get: async (personaId, requestOptions = {}) => {
2147
- const response = await personaGet({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "persona_id": personaId } });
2386
+ creditCardSet: async (vaultId, body, requestOptions = {}) => {
2387
+ const response = await vaultCreditCardSet({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "vault_id": vaultId }, body });
2148
2388
  return response.data;
2149
2389
  },
2150
- /** listPersonas: /personas. Returns the API response body. */
2151
- list: async (query = void 0, requestOptions = {}) => {
2152
- const response = await listPersonas({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, query });
2390
+ /** vaultDelete: /vaults/{vault_id}. Returns the API response body. */
2391
+ delete: async (vaultId, requestOptions = {}) => {
2392
+ const response = await vaultDelete({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "vault_id": vaultId } });
2153
2393
  return response.data;
2154
2394
  },
2155
- /** personaSmsList: /personas/{persona_id}/sms. Returns the API response body. */
2156
- smsList: async (personaId, query = void 0, requestOptions = {}) => {
2157
- const response = await personaSmsList({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "persona_id": personaId }, query });
2395
+ /** listVaults: /vaults. Returns the API response body. */
2396
+ list: async (query = void 0, requestOptions = {}) => {
2397
+ const response = await listVaults({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, query });
2158
2398
  return response.data;
2159
2399
  },
2160
- /** personaUpdate: /personas/{persona_id}. Returns the API response body. */
2161
- update: async (personaId, body, requestOptions = {}) => {
2162
- const response = await personaUpdate({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "persona_id": personaId }, body });
2400
+ /** vaultUpdate: /vaults/{vault_id}. Returns the API response body. */
2401
+ update: async (vaultId, body, requestOptions = {}) => {
2402
+ const response = await vaultUpdate({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "vault_id": vaultId }, body });
2163
2403
  return response.data;
2164
2404
  }
2165
2405
  },
@@ -2198,6 +2438,11 @@ function createResources(client2, getApiKey) {
2198
2438
  list: async (query = void 0, requestOptions = {}) => {
2199
2439
  const response = await profileList({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, query });
2200
2440
  return response.data;
2441
+ },
2442
+ /** profileStateSet: /profiles/{profile_id}/state. Returns the API response body. */
2443
+ stateSet: async (profileId, body, requestOptions = {}) => {
2444
+ const response = await profileStateSet({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "profile_id": profileId }, body });
2445
+ return response.data;
2201
2446
  }
2202
2447
  }
2203
2448
  };
@@ -2562,10 +2807,16 @@ async function createOrAppendCookiesToFile(cookieFile, cookies) {
2562
2807
  throw error;
2563
2808
  }
2564
2809
  }
2565
- existing.push(...cookies);
2566
- await writeFile(cookieFile, JSON.stringify(existing), "utf-8");
2810
+ const merged = /* @__PURE__ */ new Map();
2811
+ for (const cookie of [...existing, ...cookies]) {
2812
+ merged.set(cookieIdentity(cookie), cookie);
2813
+ }
2814
+ await writeFile(cookieFile, JSON.stringify([...merged.values()]), "utf-8");
2567
2815
  });
2568
2816
  }
2817
+ function cookieIdentity(cookie) {
2818
+ return JSON.stringify([cookie.name, cookie.domain ?? null, cookie.path ?? null, cookie.partitionKey ?? null]);
2819
+ }
2569
2820
  var fileLocks = /* @__PURE__ */ new Map();
2570
2821
  async function withFileLock(path, fn) {
2571
2822
  const key = resolve(path);
@@ -2724,8 +2975,8 @@ async function buildScrapeBody(options) {
2724
2975
  if (json_schema) {
2725
2976
  body.response_format = json_schema;
2726
2977
  } else {
2727
- const { z: z2 } = await import("zod");
2728
- body.response_format = normalizeJsonSchema(z2.toJSONSchema(response_format));
2978
+ const { z } = await import("zod");
2979
+ body.response_format = normalizeJsonSchema(z.toJSONSchema(response_format));
2729
2980
  }
2730
2981
  } else if (response_format) {
2731
2982
  body.response_format = response_format;
@@ -2737,9 +2988,6 @@ function processScrapeResponse(scrapeResponse, options) {
2737
2988
  throw new ScrapeFailedError("empty response");
2738
2989
  }
2739
2990
  const raiseOnFailure = options.raiseOnFailure ?? true;
2740
- if (options.only_images) {
2741
- return scrapeResponse.images ?? [];
2742
- }
2743
2991
  if (requiresSchema(options)) {
2744
2992
  const structured = scrapeResponse.structured;
2745
2993
  if (!structured) {
@@ -2762,10 +3010,126 @@ function processScrapeResponse(scrapeResponse, options) {
2762
3010
  return scrapeResponse.markdown;
2763
3011
  }
2764
3012
 
3013
+ // src/retry.ts
3014
+ var DEFAULT_MAX_RETRIES = 3;
3015
+ var RETRY_BASE_DELAY_MS = 1e3;
3016
+ var RETRY_MAX_DELAY_MS = 1e4;
3017
+ var RETRY_AFTER_MAX_MS = 2e4;
3018
+ var IDEMPOTENT_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "OPTIONS", "PUT", "DELETE"]);
3019
+ var REFUSED_STATUSES = /* @__PURE__ */ new Set([503, 529]);
3020
+ var GATEWAY_STATUSES = /* @__PURE__ */ new Set([502, 504]);
3021
+ var NOT_SENT_ERROR_CODES = /* @__PURE__ */ new Set([
3022
+ "ECONNREFUSED",
3023
+ "EAI_AGAIN",
3024
+ "ENETUNREACH",
3025
+ "EHOSTUNREACH",
3026
+ "UND_ERR_CONNECT_TIMEOUT"
3027
+ ]);
3028
+ var BROKEN_CONNECTION_ERROR_CODES = /* @__PURE__ */ new Set([
3029
+ "ECONNRESET",
3030
+ "EPIPE",
3031
+ "ETIMEDOUT",
3032
+ "UND_ERR_SOCKET",
3033
+ "UND_ERR_CLOSED"
3034
+ ]);
3035
+ function isIdempotentMethod(method) {
3036
+ return IDEMPOTENT_METHODS.has(method.toUpperCase());
3037
+ }
3038
+ function isRetryableStatus(status, method) {
3039
+ return REFUSED_STATUSES.has(status) || GATEWAY_STATUSES.has(status) && isIdempotentMethod(method);
3040
+ }
3041
+ function isRetryableNetworkError(error, method) {
3042
+ const code = networkErrorCode(error);
3043
+ if (code === void 0) return false;
3044
+ return NOT_SENT_ERROR_CODES.has(code) || BROKEN_CONNECTION_ERROR_CODES.has(code) && isIdempotentMethod(method);
3045
+ }
3046
+ function networkErrorCode(error, depth = 0) {
3047
+ if (typeof error !== "object" || error === null || depth > 4) return void 0;
3048
+ const { code, cause, errors } = error;
3049
+ if (typeof code === "string") return code;
3050
+ if (Array.isArray(errors) && errors.length > 0) return networkErrorCode(errors[0], depth + 1);
3051
+ return networkErrorCode(cause, depth + 1);
3052
+ }
3053
+ function parseRetryAfter(header, now = Date.now()) {
3054
+ if (!header) return void 0;
3055
+ const value = header.trim();
3056
+ if (/^\d+(\.\d+)?$/.test(value)) return Number(value) * 1e3;
3057
+ const date = Date.parse(value);
3058
+ return Number.isNaN(date) ? void 0 : Math.max(0, date - now);
3059
+ }
3060
+ function backoffDelayMs(attempt, random = Math.random) {
3061
+ return random() * Math.min(RETRY_MAX_DELAY_MS, RETRY_BASE_DELAY_MS * 2 ** attempt);
3062
+ }
3063
+ function retryDelayMs(attempt, retryAfter, random) {
3064
+ const requested = parseRetryAfter(retryAfter);
3065
+ if (requested === void 0) return backoffDelayMs(attempt, random);
3066
+ return requested <= RETRY_AFTER_MAX_MS ? requested : void 0;
3067
+ }
3068
+ function createRetryingFetch(options) {
3069
+ const wait2 = options.sleep ?? abortableSleep;
3070
+ return async (input, init) => {
3071
+ const baseFetch = options.fetch ?? globalThis.fetch;
3072
+ const request = input instanceof Request ? input : void 0;
3073
+ const method = (request?.method ?? init?.method ?? "GET").toUpperCase();
3074
+ const signal = init?.signal ?? request?.signal;
3075
+ const maxRetries = Math.max(0, Math.floor(options.maxRetries(signal) || 0));
3076
+ const send = (last) => request && request.body !== null && !last ? baseFetch(request.clone(), init) : baseFetch(input, init);
3077
+ for (let attempt = 0; ; attempt++) {
3078
+ const last = attempt >= maxRetries;
3079
+ let response;
3080
+ try {
3081
+ response = await send(last);
3082
+ } catch (error) {
3083
+ if (last || !isRetryableNetworkError(error, method)) throw error;
3084
+ const delay4 = backoffDelayMs(attempt, options.random);
3085
+ if (!fitsDeadline(delay4)) throw error;
3086
+ warn(`${method} request failed (${networkErrorCode(error)})`, delay4, attempt, maxRetries);
3087
+ await wait2(delay4, signal);
3088
+ continue;
3089
+ }
3090
+ if (last || !isRetryableStatus(response.status, method)) return response;
3091
+ const delay3 = retryDelayMs(attempt, response.headers.get("retry-after"), options.random);
3092
+ if (delay3 === void 0 || !fitsDeadline(delay3)) return response;
3093
+ await response.body?.cancel().catch(() => void 0);
3094
+ warn(`${method} request returned ${response.status}`, delay3, attempt, maxRetries);
3095
+ await wait2(delay3, signal);
3096
+ }
3097
+ function fitsDeadline(delay3) {
3098
+ const deadline = options.deadline?.(signal);
3099
+ return deadline === void 0 || Date.now() + delay3 < deadline;
3100
+ }
3101
+ };
3102
+ }
3103
+ function warn(reason, delay3, attempt, maxRetries) {
3104
+ console.warn(`${reason}, retrying in ${(delay3 / 1e3).toFixed(1)}s (${attempt + 1}/${maxRetries})`);
3105
+ }
3106
+ function abortableSleep(ms, signal) {
3107
+ return new Promise((resolve3, reject) => {
3108
+ if (signal?.aborted) {
3109
+ reject(signal.reason);
3110
+ return;
3111
+ }
3112
+ const onAbort = () => {
3113
+ clearTimeout(timer);
3114
+ reject(signal?.reason);
3115
+ };
3116
+ const timer = setTimeout(() => {
3117
+ signal?.removeEventListener("abort", onAbort);
3118
+ resolve3();
3119
+ }, ms);
3120
+ signal?.addEventListener("abort", onAbort, { once: true });
3121
+ });
3122
+ }
3123
+
2765
3124
  // src/session.ts
2766
3125
  var SESSION_START_TRIES = 3;
2767
3126
  var CLUSTER_OVERLOAD_RETRY_DELAY_MS = 3e4;
2768
3127
  var CAPTCHA_SOLVE_TIMEOUT_MS = 1e5;
3128
+ var OBSERVE_MIGRATION_URL = "https://docs.notte.cc/features/sessions/observe-migration";
3129
+ var OBSERVE_DEPRECATIONS = {
3130
+ instructions: `\`observe({ instructions })\` is deprecated and will be removed on December 1, 2026; <<ALTERNATIVE FOR instructions: session.act() \u2014 pending>>. See ${OBSERVE_MIGRATION_URL}`,
3131
+ deep: `\`perception_type: 'deep'\` is deprecated and will be removed on December 1, 2026; use \`perception_type: 'fast'\` (the default). See ${OBSERVE_MIGRATION_URL}`
3132
+ };
2769
3133
  function observeServerOwnedDialog(_dialog) {
2770
3134
  }
2771
3135
  function installServerOwnedDialogPolicy(browser) {
@@ -2780,6 +3144,7 @@ var Session = class {
2780
3144
  legacyHeadless;
2781
3145
  defaultRaiseOnFailure;
2782
3146
  defaultPerceptionType;
3147
+ warnedObserveDeprecations = /* @__PURE__ */ new Set();
2783
3148
  cookieFile;
2784
3149
  cookiesLoaded = false;
2785
3150
  cookieLoadPromise;
@@ -2815,9 +3180,11 @@ var Session = class {
2815
3180
  /**
2816
3181
  * Start the session: creates a new session on the server.
2817
3182
  *
2818
- * Retries up to `SESSION_START_TRIES` times on 5xx errors, waiting
2819
- * `CLUSTER_OVERLOAD_RETRY_DELAY_MS` on HTTP 529 (cluster overload). 4xx
2820
- * errors are never retried.
3183
+ * 503, 529, and refused connections follow the client's retry policy
3184
+ * (`NotteClientConfig.maxRetries`, honoring `Retry-After`). Other 5xx
3185
+ * errors are retried up to `SESSION_START_TRIES` times. With client
3186
+ * retries disabled, 529 waits `CLUSTER_OVERLOAD_RETRY_DELAY_MS` instead.
3187
+ * 4xx errors are never retried.
2821
3188
  *
2822
3189
  * Managed-auth sessions wait for readiness by default. Pass
2823
3190
  * `{ wait_for_authentication: false }` for an explicit nonblocking start,
@@ -2830,11 +3197,6 @@ var Session = class {
2830
3197
  * await session.start();
2831
3198
  */
2832
3199
  async start(options = {}) {
2833
- if (this.legacyHeadless === false) {
2834
- throw new Error(
2835
- "Remote `headless: false` is no longer supported. `headless: true` sessions still include session replays and access to the live viewer."
2836
- );
2837
- }
2838
3200
  if (this.legacyHeadless === true) {
2839
3201
  console.warn("`headless: true` is deprecated and ignored; remote sessions always use the supported browser launch mode.");
2840
3202
  this.legacyHeadless = void 0;
@@ -2843,42 +3205,60 @@ var Session = class {
2843
3205
  throw new Error("Session is already active");
2844
3206
  }
2845
3207
  options.signal?.throwIfAborted();
2846
- validateAuthRetry(this.options.auth_retry ?? 0);
2847
3208
  const { auth_retry, wait_for_authentication, ...request } = this.options;
2848
3209
  const body = {
2849
3210
  ...request,
2850
- ...request.auth_ids?.length ? { auth_retry: auth_retry ?? 0, wait_for_authentication: false } : {}
3211
+ ...this.legacyHeadless !== void 0 ? { headless: this.legacyHeadless } : {},
3212
+ ...auth_retry !== void 0 ? { auth_retry } : {},
3213
+ ...request.auth_ids?.length ? { wait_for_authentication: false } : {}
2851
3214
  };
2852
3215
  const shouldWait = options.wait_for_authentication ?? wait_for_authentication ?? true;
3216
+ const maxRetries = this.client.getConfig().maxRetries ?? 0;
3217
+ const timeoutMs = this.client.getConfig().timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
3218
+ const deadline = timeoutMs > 0 ? Date.now() + timeoutMs : void 0;
3219
+ const fitsDeadline = (wait2) => deadline === void 0 || Date.now() + wait2 < deadline;
3220
+ let transientRetries = 0;
2853
3221
  let tries = SESSION_START_TRIES;
2854
3222
  const origTries = tries;
2855
3223
  let sessionData;
2856
3224
  while (tries > 0) {
2857
3225
  options.signal?.throwIfAborted();
2858
- tries -= 1;
3226
+ if (!fitsDeadline(0)) throw new NotteTimeoutError(`Session start timed out after ${timeoutMs}ms`);
2859
3227
  try {
2860
- const response = await sessionStart({ client: this.client.getClient(), body, throwOnError: true });
3228
+ const response = await sessionStart({
3229
+ client: this.client.getClient(),
3230
+ body,
3231
+ throwOnError: true,
3232
+ headers: {
3233
+ [MAX_RETRIES_HEADER]: "0",
3234
+ ...deadline === void 0 ? {} : { [TIMEOUT_HEADER]: String(Math.max(1, deadline - Date.now())) }
3235
+ }
3236
+ });
2861
3237
  sessionData = response.data;
2862
3238
  break;
2863
3239
  } catch (error) {
3240
+ const transient = error instanceof NotteAPIError ? isRetryableStatus(error.statusCode, "POST") : isRetryableNetworkError(error, "POST");
3241
+ if (maxRetries > 0 && transient) {
3242
+ const wait2 = transientRetries >= maxRetries ? void 0 : error instanceof NotteAPIError ? retryDelayMs(transientRetries, error.response?.headers.get("retry-after")) : backoffDelayMs(transientRetries);
3243
+ if (wait2 === void 0 || !fitsDeadline(wait2)) throw error;
3244
+ transientRetries += 1;
3245
+ console.warn(
3246
+ `Failed to start session (${error instanceof NotteAPIError ? error.statusCode : "connection error"}), retrying in ${(wait2 / 1e3).toFixed(1)}s (${transientRetries}/${maxRetries})`
3247
+ );
3248
+ await pauseStart(wait2, options.signal);
3249
+ continue;
3250
+ }
3251
+ tries -= 1;
2864
3252
  if (tries === 0 || !(error instanceof NotteAPIError) || error.statusCode < 500) {
2865
3253
  throw error;
2866
3254
  }
2867
3255
  const retryStr = `${origTries - tries}/${origTries - 1}`;
3256
+ if (!fitsDeadline(error.statusCode === 529 ? CLUSTER_OVERLOAD_RETRY_DELAY_MS : 0)) throw error;
2868
3257
  if (error.statusCode === 529) {
2869
3258
  console.warn(
2870
3259
  `Failed to start session due to cluster overload, retrying in ${CLUSTER_OVERLOAD_RETRY_DELAY_MS / 1e3} seconds (${retryStr})...`
2871
3260
  );
2872
- if (options.signal) {
2873
- try {
2874
- await delay2(CLUSTER_OVERLOAD_RETRY_DELAY_MS, void 0, { signal: options.signal });
2875
- } catch (error2) {
2876
- options.signal.throwIfAborted();
2877
- throw error2;
2878
- }
2879
- } else {
2880
- await sleep(CLUSTER_OVERLOAD_RETRY_DELAY_MS);
2881
- }
3261
+ await pauseStart(CLUSTER_OVERLOAD_RETRY_DELAY_MS, options.signal);
2882
3262
  } else {
2883
3263
  console.warn(`Failed to start session: retrying (${retryStr})`);
2884
3264
  }
@@ -2896,6 +3276,7 @@ var Session = class {
2896
3276
  this.fileStorage = this.fileStorage?.forSession(sessionData.session_id);
2897
3277
  try {
2898
3278
  options.signal?.throwIfAborted();
3279
+ if (!fitsDeadline(0)) throw new NotteTimeoutError(`Session start timed out after ${timeoutMs}ms`);
2899
3280
  if (shouldWait) await this.waitForAuth(options);
2900
3281
  if (this.openViewer) {
2901
3282
  this.openViewerInBrowser();
@@ -3220,9 +3601,7 @@ var Session = class {
3220
3601
  * start-time profile settings are not changed, so a session started with `persist: true`
3221
3602
  * still saves again when it stops.
3222
3603
  *
3223
- * @example
3224
- * const profile = await session.saveProfile({ name: 'github' });
3225
- * // later: client.Session({ profile: { id: profile.profile_id } })
3604
+ * See [Browser Profiles](/features/sessions/browser-profiles) for the tested Python and TypeScript example.
3226
3605
  */
3227
3606
  async saveProfile(options = {}) {
3228
3607
  const { profile_id, name } = options;
@@ -3455,19 +3834,30 @@ var Session = class {
3455
3834
  * The `perception_type` defaults to the session option (`fast`). A bare
3456
3835
  * string argument is accepted as the perception type.
3457
3836
  *
3837
+ * Deprecated: `perception_type: 'deep'` and `instructions` are removed on
3838
+ * December 1, 2026, and each warns once per session. Use `perception_type:
3839
+ * 'fast'` (the default) instead of `'deep'`. For `instructions`:
3840
+ * `<<ALTERNATIVE FOR instructions: session.act() — pending>>`. See https://docs.notte.cc/features/sessions/observe-migration
3841
+ *
3458
3842
  * @param options - Observation settings, including an optional URL, or a perception-mode string.
3459
3843
  * @returns Structured page analysis, available actions, and page metadata.
3460
3844
  * @throws NotteAPIError if observation fails.
3461
3845
  * @example
3462
3846
  * const obs = await session.observe();
3463
3847
  * console.log(obs.space.description);
3464
- * const deep = await session.observe({ perception_type: 'deep', max_nb_actions: 50 });
3848
+ * const firstActions = await session.observe({ max_nb_actions: 50 });
3465
3849
  */
3466
3850
  async observe(options = {}) {
3467
3851
  const body = typeof options === "string" ? { perception_type: options } : { ...options };
3468
3852
  if (body.perception_type == null) {
3469
3853
  body.perception_type = this.defaultPerceptionType;
3470
3854
  }
3855
+ if (body.instructions != null) {
3856
+ this.warnObserveDeprecation("instructions");
3857
+ }
3858
+ if (body.perception_type !== "fast") {
3859
+ this.warnObserveDeprecation("deep");
3860
+ }
3471
3861
  const response = await pageObserve({
3472
3862
  client: this.client.getClient(),
3473
3863
  path: { session_id: this.requireSessionId() },
@@ -3476,6 +3866,12 @@ var Session = class {
3476
3866
  });
3477
3867
  return response.data;
3478
3868
  }
3869
+ warnObserveDeprecation(option) {
3870
+ if (!this.warnedObserveDeprecations.has(option)) {
3871
+ this.warnedObserveDeprecations.add(option);
3872
+ console.warn(OBSERVE_DEPRECATIONS[option]);
3873
+ }
3874
+ }
3479
3875
  async scrape(options = {}) {
3480
3876
  const sessionId = this.requireSessionId();
3481
3877
  const body = await buildScrapeBody(options);
@@ -3543,424 +3939,18 @@ var Session = class {
3543
3939
  }
3544
3940
  }
3545
3941
  };
3546
-
3547
- // src/agent.ts
3548
- import WebSocket from "ws";
3549
- import { z } from "zod";
3550
- function prepareAgentRequest(data) {
3551
- const apiData = { ...data };
3552
- const rf = data.response_format;
3553
- if (rf && typeof rf.parse === "function" && typeof rf.safeParse === "function") {
3554
- apiData.response_format = normalizeJsonSchema(z.toJSONSchema(rf));
3555
- return { apiData, zodSchema: rf };
3556
- }
3557
- return { apiData, zodSchema: null };
3558
- }
3559
- function parseAgentStatusMessage(parsed, agentId) {
3560
- if (parsed?.status === "agent_stop" && parsed.agent && parsed.agent.agent_id === agentId && parsed.agent.task !== void 0 && parsed.agent.status !== void 0) {
3561
- return parsed.agent;
3562
- }
3563
- if (parsed?.agent_id === agentId && parsed.task !== void 0 && parsed.status !== void 0) {
3564
- return parsed;
3565
- }
3566
- return null;
3567
- }
3568
- function validatePersonaOption(persona, persona_id) {
3569
- if (persona) {
3570
- try {
3571
- const personaId = persona.personaId;
3572
- if (!personaId || personaId.length === 0) {
3573
- throw new Error("Persona ID cannot be empty");
3574
- }
3575
- return personaId;
3576
- } catch (error) {
3577
- throw new Error(`Invalid persona object: ${error instanceof Error ? error.message : String(error)}`);
3578
- }
3579
- } else if (persona_id) {
3580
- if (persona_id.length === 0) {
3581
- throw new Error("Persona ID cannot be empty");
3582
- }
3583
- return persona_id;
3584
- }
3585
- return void 0;
3586
- }
3587
- function validateVaultOption(vault, vault_id) {
3588
- if (vault) {
3589
- try {
3590
- const vaultId = vault.vaultId;
3591
- if (!vaultId || vaultId.length === 0) {
3592
- throw new Error("Vault ID cannot be empty");
3593
- }
3594
- return vaultId;
3595
- } catch (error) {
3596
- throw new Error(`Invalid vault object: ${error instanceof Error ? error.message : String(error)}`);
3597
- }
3598
- } else if (vault_id) {
3599
- if (vault_id.length === 0) {
3600
- throw new Error("Vault ID cannot be empty");
3601
- }
3602
- return vault_id;
3603
- }
3604
- return void 0;
3605
- }
3606
- function validateSessionOption(session) {
3607
- const sessionId = session.getId();
3608
- if (!sessionId || sessionId.length === 0) {
3609
- throw new Error("Session ID cannot be empty");
3942
+ async function pauseStart(ms, signal) {
3943
+ if (!signal) {
3944
+ await sleep(ms);
3945
+ return;
3610
3946
  }
3611
- return sessionId;
3612
- }
3613
- function validateAgentIdOption(agent_id) {
3614
- if (agent_id.length === 0) {
3615
- throw new Error("Agent ID cannot be empty");
3947
+ try {
3948
+ await delay2(ms, void 0, { signal });
3949
+ } catch (error) {
3950
+ signal.throwIfAborted();
3951
+ throw error;
3616
3952
  }
3617
3953
  }
3618
- var defaultStepLogger = (stepData, stepCounter, agentId) => {
3619
- console.log(`\u2728 Step ${stepCounter} (agent: ${agentId})`);
3620
- if (stepData && typeof stepData === "object") {
3621
- if (stepData.state) {
3622
- const state = stepData.state;
3623
- if (state.page_summary) {
3624
- console.log(`\u{1F4DD} Current page: ${state.page_summary}`);
3625
- }
3626
- if (state.previous_goal_eval) {
3627
- const statusEmoji = state.previous_goal_status === "success" ? "\u2705" : state.previous_goal_status === "failure" ? "\u274C" : "\u2753";
3628
- console.log(`\u{1F52C} Previous goal: ${statusEmoji} ${state.previous_goal_eval}`);
3629
- }
3630
- if (state.memory) {
3631
- console.log(`\u{1F9E0} Memory: ${state.memory}`);
3632
- }
3633
- if (state.next_goal) {
3634
- console.log(`\u{1F3AF} Next goal: ${state.next_goal}`);
3635
- }
3636
- if (state.relevant_interactions && state.relevant_interactions.length > 0) {
3637
- console.log(`\u{1F194} Relevant ids:`);
3638
- state.relevant_interactions.forEach((interaction) => {
3639
- console.log(` \u25B6 ${interaction.id}: ${interaction.reason}`);
3640
- });
3641
- }
3642
- }
3643
- if (stepData.action) {
3644
- const action = stepData.action;
3645
- let actionStr = `\u26A1 Taking action:
3646
- \u25B6 ${action.name || action.type || "Unknown action"}`;
3647
- if (action.id) {
3648
- actionStr += ` with id ${action.id}`;
3649
- } else if (action.param && action.param.name && action[action.param.name]) {
3650
- actionStr += ` with ${action.param.name}=${action[action.param.name]}`;
3651
- }
3652
- console.log(actionStr);
3653
- }
3654
- } else {
3655
- console.log(stepData);
3656
- }
3657
- console.log("");
3658
- };
3659
- var Agent = class {
3660
- client;
3661
- request;
3662
- response = null;
3663
- websocket = null;
3664
- existingAgent;
3665
- constructor(client2, options) {
3666
- this.client = client2;
3667
- if ("agent_id" in options && options.agent_id) {
3668
- if (options.session) {
3669
- throw new Error("Either session (for running a new agent) or agent_id (for accessing an existing agent) have to be provided, not both");
3670
- }
3671
- validateAgentIdOption(options.agent_id);
3672
- this.existingAgent = true;
3673
- this.response = { agent_id: options.agent_id };
3674
- } else if ("session" in options && options.session) {
3675
- if (options.agent_id) {
3676
- throw new Error("Either session (for running a new agent) or agent_id (for accessing an existing agent) have to be provided, not both");
3677
- }
3678
- this.existingAgent = false;
3679
- const { session, vault, persona, ...requestData } = options;
3680
- const sessionId = validateSessionOption(session);
3681
- const vaultId = validateVaultOption(vault, options.vault_id);
3682
- const personaId = validatePersonaOption(persona, options.persona_id);
3683
- this.request = {
3684
- session_id: sessionId,
3685
- vault_id: vaultId,
3686
- persona_id: personaId,
3687
- ...requestData
3688
- };
3689
- } else {
3690
- throw new Error("Either session (for running a new agent) or agent_id (for accessing an existing agent) have to be provided");
3691
- }
3692
- }
3693
- async start(data) {
3694
- if (this.existingAgent) {
3695
- throw new Error("You cannot call start() on an agent instantiated from agent id");
3696
- }
3697
- if (!this.request) {
3698
- throw new Error("Agent not properly initialized with session");
3699
- }
3700
- try {
3701
- const { apiData } = prepareAgentRequest(data);
3702
- const requestBody = {
3703
- ...this.request,
3704
- ...apiData
3705
- };
3706
- const response = await agentStart({
3707
- client: this.client.getClient(),
3708
- body: requestBody
3709
- });
3710
- if (response?.error) {
3711
- throw new Error(`Failed to start agent: ${formatError(response.error)}`);
3712
- }
3713
- this.response = response.data;
3714
- return this.response;
3715
- } catch (error) {
3716
- throw new Error(`Failed to start agent: ${error instanceof Error ? error.message : String(error)}`);
3717
- }
3718
- }
3719
- async run(data) {
3720
- if (this.existingAgent) {
3721
- throw new Error("You cannot call run() on an agent instantiated from agent id");
3722
- }
3723
- const { apiData, zodSchema } = prepareAgentRequest(data);
3724
- this.response = await this.start(apiData);
3725
- console.log(`[Agent] ${this.agentId} started`);
3726
- const result = await this.watchLogsAndWait(true, data.updateHandler || null);
3727
- if (zodSchema && result && result.answer !== void 0 && result.answer !== null) {
3728
- let candidate;
3729
- try {
3730
- candidate = typeof result.answer === "string" ? JSON.parse(result.answer) : result.answer;
3731
- } catch {
3732
- throw new Error(`Agent answer is not valid JSON and cannot be validated against the schema`);
3733
- }
3734
- try {
3735
- result.answer = zodSchema.parse(candidate);
3736
- } catch (error) {
3737
- throw new Error(`Agent answer schema validation failed: ${error instanceof Error ? error.message : String(error)}`);
3738
- }
3739
- }
3740
- return result;
3741
- }
3742
- /**
3743
- * Watch logs and wait for completion - mirrors Python watch_logs_and_wait
3744
- */
3745
- async watchLogsAndWait(log = true, updateHandler = null) {
3746
- if (this.existingAgent) {
3747
- throw new Error("You cannot call watchLogsAndWait() on an agent instantiated from agent id");
3748
- }
3749
- if (!this.response) {
3750
- throw new Error("Agent not started");
3751
- }
3752
- const deadline = Date.now() + 3e5;
3753
- try {
3754
- const result = await this.watchLogs(log, updateHandler, deadline);
3755
- if (result && result.status !== "active") {
3756
- return result;
3757
- }
3758
- } catch (error) {
3759
- console.warn(`[Agent] ${this.agentId} log stream unavailable; polling for completion.`);
3760
- }
3761
- while (Date.now() < deadline) {
3762
- const result = await this.status(AbortSignal.timeout(Math.max(1, deadline - Date.now())));
3763
- if (result.status !== "active") {
3764
- updateHandler?.({ type: "completion", data: result, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
3765
- return result;
3766
- }
3767
- await new Promise((resolve3) => setTimeout(resolve3, 1e3));
3768
- }
3769
- throw new Error(`Agent ${this.agentId} did not complete before the polling timeout; retrieve status() later.`);
3770
- }
3771
- /**
3772
- * Watch logs via WebSocket - mirrors Python watch_logs method
3773
- */
3774
- async watchLogs(log = true, updateHandler = null, deadline = Date.now() + 3e5) {
3775
- if (this.existingAgent) {
3776
- throw new Error("You cannot call watchLogs() on an agent instantiated from agent id");
3777
- }
3778
- if (!this.response) {
3779
- throw new Error("Agent not started");
3780
- }
3781
- const config = this.client.getConfig();
3782
- if (config.baseUrl?.startsWith("/")) return null;
3783
- const agentId = this.response.agent_id;
3784
- const sessionId = this.response.session_id;
3785
- const debug = await sessionDebugInfo({
3786
- client: this.client.getClient(),
3787
- path: { session_id: sessionId },
3788
- throwOnError: true,
3789
- signal: AbortSignal.timeout(Math.max(1, deadline - Date.now()))
3790
- });
3791
- const wsUrl = new URL(this.client.withDbPreview(debug.data.ws.logs));
3792
- const token = wsUrl.searchParams.get("token");
3793
- if (!token || token === config.apiKey || wsUrl.protocol !== "wss:") return null;
3794
- wsUrl.pathname = `/agents/${encodeURIComponent(agentId)}/debug/logs`;
3795
- wsUrl.searchParams.set("session_id", sessionId);
3796
- return new Promise((resolve3, reject) => {
3797
- this.websocket = new WebSocket(wsUrl);
3798
- const socket = this.websocket;
3799
- const timeout = setTimeout(() => finish(null), Math.max(0, deadline - Date.now()));
3800
- let settled = false;
3801
- const finish = (result) => {
3802
- if (settled) return;
3803
- settled = true;
3804
- clearTimeout(timeout);
3805
- if (this.websocket === socket) this.websocket = null;
3806
- if (socket.readyState !== WebSocket.CLOSED) socket.terminate();
3807
- resolve3(result);
3808
- };
3809
- let counter = 0;
3810
- this.websocket.on("open", () => {
3811
- });
3812
- this.websocket.on("error", (error) => {
3813
- console.error(`Connection error: ${agentId} ${error.message}`);
3814
- finish(null);
3815
- });
3816
- this.websocket.on("message", (data) => {
3817
- try {
3818
- const message = data.toString();
3819
- let parsed;
3820
- try {
3821
- parsed = JSON.parse(message);
3822
- } catch {
3823
- return;
3824
- }
3825
- const finalStatus = parseAgentStatusMessage(parsed, agentId);
3826
- if (finalStatus) {
3827
- if (updateHandler) {
3828
- updateHandler({
3829
- type: "completion",
3830
- data: finalStatus,
3831
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
3832
- });
3833
- } else if (!finalStatus.success) {
3834
- console.error(finalStatus.answer);
3835
- }
3836
- finish(finalStatus);
3837
- return;
3838
- }
3839
- if (log) {
3840
- counter++;
3841
- if (updateHandler) {
3842
- updateHandler({
3843
- type: "step",
3844
- data: parsed,
3845
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
3846
- });
3847
- } else {
3848
- defaultStepLogger(parsed, counter, agentId);
3849
- }
3850
- }
3851
- } catch (error) {
3852
- console.error(`Error processing WebSocket message: ${error}`);
3853
- }
3854
- });
3855
- this.websocket.on("close", () => {
3856
- finish(null);
3857
- });
3858
- });
3859
- }
3860
- /**
3861
- * Get agent status - mirrors Python status method
3862
- */
3863
- async status(signal) {
3864
- if (!this.response) {
3865
- throw new Error("Agent not started or not accessible");
3866
- }
3867
- const response = await agentStatus({
3868
- client: this.client.getClient(),
3869
- signal,
3870
- path: {
3871
- agent_id: this.response.agent_id
3872
- }
3873
- });
3874
- if (response?.error) {
3875
- throw new Error(`Failed to get agent status: ${formatError(response.error)}`);
3876
- }
3877
- return response.data;
3878
- }
3879
- /**
3880
- * Stop the agent - mirrors Python stop method
3881
- */
3882
- async stop() {
3883
- if (this.existingAgent) {
3884
- throw new Error("You cannot call stop() on an agent instantiated from agent id");
3885
- }
3886
- if (!this.response) {
3887
- throw new Error("Agent not started");
3888
- }
3889
- try {
3890
- console.log(`[Agent] ${this.response.agent_id} is stopping`);
3891
- const response = await agentStop({
3892
- client: this.client.getClient(),
3893
- path: {
3894
- agent_id: this.response.agent_id
3895
- },
3896
- query: { session_id: this.response.session_id }
3897
- });
3898
- if (response?.error) {
3899
- throw new Error(`Failed to stop agent: ${formatError(response.error)}`);
3900
- }
3901
- console.log(`[Agent] ${this.response.agent_id} stopped`);
3902
- return response.data;
3903
- } catch (error) {
3904
- console.warn(`Failed to stop agent: ${error instanceof Error ? error.message : String(error)}`);
3905
- throw error;
3906
- } finally {
3907
- this.disconnectWebSocket();
3908
- }
3909
- }
3910
- /**
3911
- * Disconnect WebSocket
3912
- */
3913
- disconnectWebSocket() {
3914
- if (this.websocket) {
3915
- this.websocket.close();
3916
- this.websocket = null;
3917
- }
3918
- }
3919
- /**
3920
- * Get agent ID - mirrors Python agent_id property
3921
- */
3922
- get agentId() {
3923
- if (!this.response) {
3924
- throw new Error("You need to run the agent first to get the agent id");
3925
- }
3926
- return this.response.agent_id;
3927
- }
3928
- /**
3929
- * Get session ID - mirrors Python session_id property
3930
- */
3931
- get sessionId() {
3932
- if (!this.response) {
3933
- throw new Error("You need to run the agent first to get the session id");
3934
- }
3935
- return this.response.session_id;
3936
- }
3937
- /**
3938
- * Whether `start()`/`run()` was called on this instance (or it was built from an agent id).
3939
- * This is a local check and does not contact the API.
3940
- */
3941
- hasStarted() {
3942
- return this.response !== null;
3943
- }
3944
- /**
3945
- * Whether the agent is still active on the server. Fetches the current status,
3946
- * like calling `agent.status()` in Python; an agent that was never started is not active.
3947
- */
3948
- async isActive() {
3949
- if (!this.response) {
3950
- return false;
3951
- }
3952
- const status = await this.status();
3953
- return status.status === "active";
3954
- }
3955
- /**
3956
- * @deprecated Only reports whether this instance was started; it does not
3957
- * contact the API. Use `hasStarted()` for that check or `isActive()` for the
3958
- * live server status.
3959
- */
3960
- isRunning() {
3961
- return this.hasStarted();
3962
- }
3963
- };
3964
3954
 
3965
3955
  // src/vaults.ts
3966
3956
  import { getDomain } from "tldts";
@@ -4120,9 +4110,9 @@ var NotteVault = class {
4120
4110
  await this.delete();
4121
4111
  }
4122
4112
  /**
4123
- * Add or update the credentials stored for a website. The URL is reduced to
4124
- * its root domain (`https://github.com/login` → `github.com`) before it is
4125
- * sent, like Python's `AddCredentialsRequest`.
4113
+ * Add or update the credentials stored for a website. Values are sent as
4114
+ * supplied; the API validates credentials and reduces the URL to its root
4115
+ * domain (`https://github.com/login` → `github.com`).
4126
4116
  *
4127
4117
  * ```ts
4128
4118
  * await vault.addCredentials('https://github.com/', {
@@ -4133,13 +4123,11 @@ var NotteVault = class {
4133
4123
  * ```
4134
4124
  */
4135
4125
  async addCredentials(url, credentials) {
4136
- const domain = validateUrl(url);
4137
- validateCredentials(credentials);
4138
4126
  const vaultId = await this.ensureInitialized();
4139
4127
  await vaultCredentialsAdd({
4140
4128
  client: this.client.getClient(),
4141
4129
  path: { vault_id: vaultId },
4142
- body: { url: domain, credentials },
4130
+ body: { url, credentials },
4143
4131
  throwOnError: true
4144
4132
  });
4145
4133
  }
@@ -4153,12 +4141,11 @@ var NotteVault = class {
4153
4141
  * ```
4154
4142
  */
4155
4143
  async getCredentials(url) {
4156
- const domain = validateUrl(url);
4157
4144
  const vaultId = await this.ensureInitialized();
4158
4145
  const response = await vaultCredentialsGet({
4159
4146
  client: this.client.getClient(),
4160
4147
  path: { vault_id: vaultId },
4161
- query: { url: domain },
4148
+ query: { url },
4162
4149
  throwOnError: true
4163
4150
  });
4164
4151
  return response.data.credentials;
@@ -4186,12 +4173,11 @@ var NotteVault = class {
4186
4173
  * ```
4187
4174
  */
4188
4175
  async deleteCredentials(url) {
4189
- const domain = validateUrl(url);
4190
4176
  const vaultId = await this.ensureInitialized();
4191
4177
  await vaultCredentialsDelete({
4192
4178
  client: this.client.getClient(),
4193
4179
  path: { vault_id: vaultId },
4194
- query: { url: domain },
4180
+ query: { url },
4195
4181
  throwOnError: true
4196
4182
  });
4197
4183
  }
@@ -4236,7 +4222,7 @@ var NotteVault = class {
4236
4222
  * ```
4237
4223
  */
4238
4224
  async addCredentialsFromEnv(url) {
4239
- const rootDomain = validateUrl(url);
4225
+ const rootDomain = getRootDomain(url);
4240
4226
  const prefix = rootDomain.replace(/\./g, "_").toUpperCase();
4241
4227
  const credentials = {};
4242
4228
  const variableNames = [];
@@ -4312,6 +4298,10 @@ var NotteVault = class {
4312
4298
  };
4313
4299
 
4314
4300
  // src/personas.ts
4301
+ function withPersonaDefaults(persona) {
4302
+ if (!persona || persona.email_provider) return persona;
4303
+ return { ...persona, email_provider: "notte" };
4304
+ }
4315
4305
  var NottePersona = class {
4316
4306
  client;
4317
4307
  _initRequest;
@@ -4371,7 +4361,7 @@ var NottePersona = class {
4371
4361
  if (response?.error) {
4372
4362
  throw new Error(`Failed to get persona: ${formatError(response.error)}`);
4373
4363
  }
4374
- this.response = response.data;
4364
+ this.response = withPersonaDefaults(response.data);
4375
4365
  return this.response;
4376
4366
  }
4377
4367
  async initNewPersona(createData) {
@@ -4382,7 +4372,7 @@ var NottePersona = class {
4382
4372
  if (response?.error) {
4383
4373
  throw new Error(`Failed to create persona: ${formatError(response.error)}`);
4384
4374
  }
4385
- this.response = response.data;
4375
+ this.response = withPersonaDefaults(response.data);
4386
4376
  console.warn(
4387
4377
  `[Persona] ${this.response.persona_id} created since no persona id was provided. Please store this to retrieve it later.`
4388
4378
  );
@@ -4611,11 +4601,10 @@ async function offloadRunPayloads(client2, path, fields) {
4611
4601
  if (payload.length > MAX_PAYLOAD_BYTES) throw new Error(`Function run ${field} exceeds the payload limit`);
4612
4602
  if (payload.length <= INLINE_FIELD_BYTES) continue;
4613
4603
  const checksum = createHash("sha256").update(payload).digest("base64");
4614
- const prepared = await client2.post({
4615
- url: "/functions/{function_id}/runs/{run_id}/payloads/{field}/upload",
4604
+ const prepared = await prepareRunPayloadUpload({
4605
+ client: client2,
4616
4606
  path: { ...path, field },
4617
4607
  body: { size_bytes: payload.length, sha256: checksum },
4618
- headers: { "Content-Type": "application/json" },
4619
4608
  throwOnError: true
4620
4609
  });
4621
4610
  const upload = prepared.data;
@@ -4691,7 +4680,6 @@ var FUNCTION_RUN_ENDPOINTS = {
4691
4680
  start: "/functions/{function_id}/runs/{run_id}"
4692
4681
  };
4693
4682
  var RUN_API_KEY_HEADER = "x-notte-api-key";
4694
- var FUNCTION_RUNTIMES = ["standard", "extended"];
4695
4683
  var FUNCTION_RUN_STATUSES = ["closed", "active", "failed"];
4696
4684
  var NotteFunction = class {
4697
4685
  client;
@@ -4794,7 +4782,7 @@ var NotteFunction = class {
4794
4782
  throwOnError: true,
4795
4783
  path: { function_id: functionId },
4796
4784
  query: {
4797
- restricted: options.restricted ?? true,
4785
+ restricted: options.restricted,
4798
4786
  ...options.version !== void 0 ? { version: options.version } : {}
4799
4787
  },
4800
4788
  body: { file }
@@ -4891,7 +4879,7 @@ var NotteFunction = class {
4891
4879
  client: this.client.getClient(),
4892
4880
  throwOnError: true,
4893
4881
  path: { function_id: functionId },
4894
- query: { restricted: options.restricted ?? true },
4882
+ query: { restricted: options.restricted },
4895
4883
  body: { version: options.version }
4896
4884
  });
4897
4885
  return response.data;
@@ -4987,7 +4975,7 @@ var NotteFunction = class {
4987
4975
  client: this.client.getClient(),
4988
4976
  throwOnError: true,
4989
4977
  path: { function_id: functionId },
4990
- query: { ...options, only_active: options.only_active ?? false }
4978
+ query: options
4991
4979
  });
4992
4980
  return response.data;
4993
4981
  }
@@ -5020,9 +5008,6 @@ var NotteFunction = class {
5020
5008
  if (!(timeoutMs > 0)) {
5021
5009
  throw new InvalidRequestError("timeoutMs must be a positive number");
5022
5010
  }
5023
- if (options.runtime !== void 0 && !FUNCTION_RUNTIMES.includes(options.runtime)) {
5024
- throw new InvalidRequestError(`runtime must be one of ${FUNCTION_RUNTIMES.join(", ")}, got '${String(options.runtime)}'`);
5025
- }
5026
5011
  const functionId = await this.ensureInitialized();
5027
5012
  const functionRunId = options.functionRunId ?? (await this.createRun()).function_run_id;
5028
5013
  const body = {
@@ -5365,7 +5350,7 @@ var SessionFiles = class {
5365
5350
  const response = await listSessionFiles({
5366
5351
  client: this.client,
5367
5352
  path: { session_id: this.sessionId },
5368
- query: { limit: options.limit ?? 100, offset: options.offset ?? 0, source: options.source },
5353
+ query: options,
5369
5354
  throwOnError: true
5370
5355
  });
5371
5356
  return response.data;
@@ -5774,6 +5759,7 @@ var DEFAULT_NOTTE_API_URL = "https://api.notte.cc";
5774
5759
  var DEFAULT_REQUEST_TIMEOUT_MS = 6e4;
5775
5760
  var REQUEST_ORIGIN = "sdk-node";
5776
5761
  var TIMEOUT_HEADER = "x-notte-timeout-ms";
5762
+ var MAX_RETRIES_HEADER = "x-notte-max-retries";
5777
5763
  var DB_PREVIEW_ENV = "NOTTE_DB_PREVIEW_BRANCH";
5778
5764
  var DB_PREVIEW_HEADER = "x-db-preview";
5779
5765
  var EXECUTION_ERROR_CLASS = "NotteApiExecutionError";
@@ -5796,6 +5782,10 @@ var NotteClient3 = class {
5796
5782
  if (!(timeoutMs >= 0)) {
5797
5783
  throw new InvalidRequestError("timeoutMs must be a non-negative number");
5798
5784
  }
5785
+ const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
5786
+ if (!Number.isInteger(maxRetries) || maxRetries < 0) {
5787
+ throw new InvalidRequestError("maxRetries must be a non-negative integer");
5788
+ }
5799
5789
  const isProxyMode = isRelativeProxyUrl(baseUrl);
5800
5790
  if (!isProxyMode) {
5801
5791
  const url = new URL(baseUrl);
@@ -5811,7 +5801,15 @@ var NotteClient3 = class {
5811
5801
  "NOTTE_API_KEY needs to be provided. Pass config.apiKey or set the NOTTE_API_KEY environment variable."
5812
5802
  );
5813
5803
  }
5814
- this.config = { baseUrl, apiKey, timeoutMs, captchaTimeoutSeconds, dbPreview, verbose: config.verbose ?? false };
5804
+ this.config = {
5805
+ baseUrl,
5806
+ apiKey,
5807
+ timeoutMs,
5808
+ captchaTimeoutSeconds,
5809
+ dbPreview,
5810
+ maxRetries,
5811
+ verbose: config.verbose ?? false
5812
+ };
5815
5813
  if (baseUrl !== DEFAULT_NOTTE_API_URL && !isProxyMode) {
5816
5814
  console.warn(`NOTTE_API_URL is set to: ${baseUrl}`);
5817
5815
  }
@@ -5820,7 +5818,7 @@ var NotteClient3 = class {
5820
5818
  redirect: "manual",
5821
5819
  throwOnError: true
5822
5820
  });
5823
- this.client.interceptors.request.use((request) => {
5821
+ this.client.interceptors.request.use((request, opts) => {
5824
5822
  const headers = new Headers(request.headers);
5825
5823
  if (this.config.apiKey) headers.set("Authorization", `Bearer ${this.config.apiKey}`);
5826
5824
  headers.set("x-notte-request-origin", REQUEST_ORIGIN);
@@ -5828,16 +5826,25 @@ var NotteClient3 = class {
5828
5826
  if (this.config.dbPreview) headers.set(DB_PREVIEW_HEADER, this.config.dbPreview);
5829
5827
  const override = headers.get(TIMEOUT_HEADER);
5830
5828
  headers.delete(TIMEOUT_HEADER);
5829
+ const retriesOverride = headers.get(MAX_RETRIES_HEADER);
5830
+ headers.delete(MAX_RETRIES_HEADER);
5831
5831
  const timeoutMs2 = override !== null ? Number(override) : this.config.timeoutMs;
5832
5832
  if (this.config.verbose) {
5833
5833
  console.info(`Making \`${request.method}\` request to \`${request.url}\``);
5834
5834
  }
5835
- if (!(timeoutMs2 > 0)) {
5836
- return new Request(request, { headers });
5837
- }
5838
- const deadline = withTimeout(request.signal, timeoutMs2);
5839
- const timed = new Request(request, { headers, signal: deadline.signal });
5840
- pendingDeadlines.set(timed, deadline.release);
5835
+ const callerSignal = opts.signal ?? request.signal;
5836
+ const deadline = timeoutMs2 > 0 ? withTimeout(callerSignal, timeoutMs2) : void 0;
5837
+ const signal = deadline?.signal ?? callerSignal;
5838
+ const timed = new Request(request, { headers, signal });
5839
+ pendingRequests.set(timed, { signal, release: deadline?.release ?? (() => void 0), expiresAt: deadline?.expiresAt ?? Infinity });
5840
+ const transport = originalTransports.get(opts) ?? opts.fetch ?? globalThis.fetch;
5841
+ originalTransports.set(opts, transport);
5842
+ const retrying = createRetryingFetch({
5843
+ fetch: transport,
5844
+ maxRetries: () => retriesOverride !== null ? Number(retriesOverride) : this.config.maxRetries,
5845
+ deadline: () => deadline?.expiresAt
5846
+ });
5847
+ opts.fetch = (input, init) => retrying(input, { ...init, signal });
5841
5848
  return timed;
5842
5849
  });
5843
5850
  this.client.interceptors.response.use(async (response, request, opts) => {
@@ -5875,7 +5882,7 @@ var NotteClient3 = class {
5875
5882
  method: request.method,
5876
5883
  headers: headerRecord,
5877
5884
  body: opts.serializedBody ?? void 0,
5878
- signal: request.signal,
5885
+ signal: requestSignal(request),
5879
5886
  redirect: "manual"
5880
5887
  });
5881
5888
  currentUrl = location;
@@ -5923,14 +5930,15 @@ var NotteClient3 = class {
5923
5930
  if (error instanceof NotteAPIError) {
5924
5931
  return error;
5925
5932
  }
5926
- if (request?.signal.aborted) {
5927
- error = request.signal.reason ?? error;
5933
+ const signal = request && requestSignal(request);
5934
+ if (signal?.aborted) {
5935
+ error = signal.reason ?? error;
5928
5936
  }
5929
5937
  if (isTimeoutAbort(error)) {
5930
5938
  const target = request ? ` to \`${requestPath(request)}\`` : "";
5931
5939
  return new NotteTimeoutError(`Request${target} ${error.message}`, { cause: error });
5932
5940
  }
5933
- if (request?.signal.aborted) return error;
5941
+ if (signal?.aborted) return error;
5934
5942
  if (response) {
5935
5943
  const path = requestPath(request, response);
5936
5944
  const body = normalizeErrorBody(error);
@@ -5980,6 +5988,10 @@ var NotteClient3 = class {
5980
5988
  Session(options = {}) {
5981
5989
  return new Session(this, options);
5982
5990
  }
5991
+ /** Generated file operations; use Files(sessionId) for local file IO helpers. */
5992
+ get files() {
5993
+ return this.resources.files;
5994
+ }
5983
5995
  /** Access files owned by a specific session, including closed sessions. */
5984
5996
  Files(sessionId) {
5985
5997
  return new SessionFiles(this.getClient(), sessionId);
@@ -5998,12 +6010,6 @@ var NotteClient3 = class {
5998
6010
  FileStorage(sessionId) {
5999
6011
  return new RemoteFileStorage(this, sessionId);
6000
6012
  }
6001
- /**
6002
- * Create a new agent
6003
- */
6004
- Agent(options) {
6005
- return new Agent(this, options);
6006
- }
6007
6013
  /**
6008
6014
  * Create or access a vault
6009
6015
  */
@@ -6036,16 +6042,6 @@ var NotteClient3 = class {
6036
6042
  }
6037
6043
  };
6038
6044
  }
6039
- /** Client-bound agent API operations. `list()` retains its array return value. */
6040
- get agents() {
6041
- return {
6042
- ...this.resources.agents,
6043
- list: async (options = {}) => {
6044
- const response = await listAgents({ client: this.getClient(), query: options });
6045
- return response.data?.items ?? [];
6046
- }
6047
- };
6048
- }
6049
6045
  /** Client-bound vault API operations. `list()` retains its array return value. */
6050
6046
  get vaults() {
6051
6047
  return {
@@ -6094,14 +6090,18 @@ var NotteClient3 = class {
6094
6090
  * Personas client for listing and managing personas
6095
6091
  */
6096
6092
  get personas() {
6093
+ const personas = this.resources.personas;
6097
6094
  return {
6098
- ...this.resources.personas,
6095
+ ...personas,
6096
+ create: async (...args) => withPersonaDefaults(await personas.create(...args)),
6097
+ get: async (...args) => withPersonaDefaults(await personas.get(...args)),
6098
+ update: async (...args) => withPersonaDefaults(await personas.update(...args)),
6099
6099
  list: async (options) => {
6100
6100
  const response = await listPersonas({
6101
6101
  client: this.getClient(),
6102
6102
  query: options || {}
6103
6103
  });
6104
- return response.data?.items || [];
6104
+ return (response.data?.items || []).map(withPersonaDefaults);
6105
6105
  }
6106
6106
  };
6107
6107
  }
@@ -6147,18 +6147,18 @@ function isTimeoutAbort(error) {
6147
6147
  function timeoutReason(timeoutMs) {
6148
6148
  return new DOMException(`timed out after ${timeoutMs}ms`, "TimeoutError");
6149
6149
  }
6150
- var pendingDeadlines = /* @__PURE__ */ new WeakMap();
6150
+ var pendingRequests = /* @__PURE__ */ new WeakMap();
6151
+ var originalTransports = /* @__PURE__ */ new WeakMap();
6152
+ function requestSignal(request) {
6153
+ return pendingRequests.get(request)?.signal ?? request.signal;
6154
+ }
6151
6155
  function releaseDeadline(request) {
6152
- if (!request) return;
6153
- const release = pendingDeadlines.get(request);
6154
- if (release) {
6155
- pendingDeadlines.delete(request);
6156
- release();
6157
- }
6156
+ if (request) pendingRequests.get(request)?.release();
6158
6157
  }
6159
6158
  function withTimeout(signal, timeoutMs) {
6160
6159
  const controller = new AbortController();
6161
6160
  const timer = setTimeout(() => controller.abort(timeoutReason(timeoutMs)), timeoutMs);
6161
+ const expiresAt = Date.now() + timeoutMs;
6162
6162
  timer.unref?.();
6163
6163
  let detach = () => void 0;
6164
6164
  let composite;
@@ -6185,7 +6185,7 @@ function withTimeout(signal, timeoutMs) {
6185
6185
  detach();
6186
6186
  };
6187
6187
  composite.addEventListener("abort", release, { once: true });
6188
- return { signal: composite, release };
6188
+ return { signal: composite, release, expiresAt };
6189
6189
  }
6190
6190
 
6191
6191
  // src/actions.ts
@@ -6278,11 +6278,11 @@ var createClient2 = (config) => {
6278
6278
  };
6279
6279
  export {
6280
6280
  ActionExecutionError,
6281
- Agent,
6282
6281
  AuthenticationError,
6283
6282
  CAPTCHA_SOLVE_TIMEOUT_MS,
6284
6283
  CLUSTER_OVERLOAD_RETRY_DELAY_MS,
6285
6284
  CREDENTIAL_FIELDS,
6285
+ DEFAULT_MAX_RETRIES,
6286
6286
  DEFAULT_NOTTE_API_URL,
6287
6287
  DEFAULT_REQUEST_TIMEOUT_MS,
6288
6288
  Encryption,
@@ -6317,12 +6317,17 @@ export {
6317
6317
  Session,
6318
6318
  SessionFiles,
6319
6319
  TIMEOUT_HEADER,
6320
+ accountChanges,
6321
+ accountRuns,
6320
6322
  actions,
6321
6323
  agentStart,
6322
6324
  agentStatus,
6323
6325
  agentStop,
6324
6326
  anythingStart,
6327
+ attempts,
6328
+ brandRetrieve,
6325
6329
  buildFetchScript,
6330
+ changes,
6326
6331
  checkForLatestVersion,
6327
6332
  client,
6328
6333
  connectLinkContext,
@@ -6332,15 +6337,23 @@ export {
6332
6337
  connectLinkStatus,
6333
6338
  connectLinkSubmit,
6334
6339
  connectPaymentWallet,
6340
+ create,
6335
6341
  createClient2 as createClient,
6336
6342
  createOrAppendCookiesToFile,
6337
6343
  createPayment,
6344
+ creditUsage,
6338
6345
  NotteClient3 as default,
6339
6346
  deleteSecret,
6340
6347
  deleteSessionFile,
6348
+ delete_,
6349
+ deliveries,
6350
+ detail,
6341
6351
  disconnectPaymentWallet,
6342
6352
  downloadRunPayload,
6343
6353
  downloadSessionFile,
6354
+ executeSessionFile,
6355
+ extractProductEndpoint,
6356
+ fetchSpecializedData,
6344
6357
  functionCreate,
6345
6358
  functionDelete,
6346
6359
  functionDownloadUrl,
@@ -6356,6 +6369,7 @@ export {
6356
6369
  functionScheduleSet,
6357
6370
  functionUpdate,
6358
6371
  getPayment,
6372
+ getPolicy,
6359
6373
  getRootDomain,
6360
6374
  getScript,
6361
6375
  getSecret,
@@ -6363,13 +6377,18 @@ export {
6363
6377
  getUsage,
6364
6378
  getUsageLogs,
6365
6379
  healthCheck,
6380
+ history_,
6366
6381
  installServerOwnedDialogPolicy,
6382
+ invalidate,
6367
6383
  isCaptchaSolveAction,
6368
6384
  isValidMfaSecret,
6385
+ limits,
6369
6386
  listAgents,
6370
6387
  listAuditEvents,
6388
+ listDataApis,
6371
6389
  listFunctionRunsByFunctionId,
6372
6390
  listFunctions,
6391
+ listMonitors,
6373
6392
  listPersonas,
6374
6393
  listSecrets,
6375
6394
  listSessionFiles,
@@ -6382,19 +6401,20 @@ export {
6382
6401
  mailboxSync,
6383
6402
  mailboxUpdate,
6384
6403
  managedAuthConnectLinkCreate,
6404
+ mapsSearch,
6405
+ newsSearch,
6385
6406
  observeServerOwnedDialog,
6386
6407
  pageExecute,
6387
6408
  pageObserve,
6388
6409
  pageScrape,
6389
6410
  pageScreenshot,
6390
- parseAgentStatusMessage,
6411
+ peopleEnrich,
6391
6412
  personaCreate,
6392
6413
  personaDelete,
6393
6414
  personaEmailsList,
6394
6415
  personaGet,
6395
6416
  personaSmsList,
6396
6417
  personaUpdate,
6397
- prepareAgentRequest,
6398
6418
  prepareRunPayloadUpload,
6399
6419
  processScrapeResponse,
6400
6420
  profileCookiesGet,
@@ -6404,18 +6424,29 @@ export {
6404
6424
  profileDuplicate,
6405
6425
  profileGet,
6406
6426
  profileList,
6427
+ profileStateSet,
6407
6428
  readCookiesFile,
6408
6429
  readyCheck,
6409
6430
  responseFromEvaluated,
6410
- retry,
6431
+ retrieve,
6432
+ retrieveChange,
6433
+ retrieveDelivery,
6434
+ retrieveRun,
6435
+ retry2 as retry,
6436
+ retry as retryWebhookDelivery,
6437
+ rotateSecret,
6438
+ runNow,
6439
+ runs,
6411
6440
  sanitizeFilename,
6412
6441
  scrapeFromHtml,
6442
+ fetchSpecializedData as scrapeSpecializedData,
6413
6443
  scrapeWebpage,
6414
6444
  searchWeb,
6415
6445
  sessionAuthReadiness,
6416
6446
  sessionCookiesGet,
6417
6447
  sessionCookiesSet,
6418
6448
  sessionDebugInfo,
6449
+ sessionMouseReplay,
6419
6450
  sessionNetworkLogs,
6420
6451
  sessionOffset,
6421
6452
  sessionProfilePreview,
@@ -6426,6 +6457,9 @@ export {
6426
6457
  sessionStop,
6427
6458
  startVersionCheck,
6428
6459
  storeSecret,
6460
+ styleguideEndpoint,
6461
+ summary,
6462
+ update,
6429
6463
  uploadSessionFile,
6430
6464
  validateCredentials,
6431
6465
  validateMfaSecret,
@@ -6439,6 +6473,7 @@ export {
6439
6473
  vaultCreditCardGet,
6440
6474
  vaultCreditCardSet,
6441
6475
  vaultDelete,
6442
- vaultUpdate
6476
+ vaultUpdate,
6477
+ youtubeEndpoint
6443
6478
  };
6444
6479
  //# sourceMappingURL=index.mjs.map