@hautechai/sdk 2.30.2 → 2.31.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
@@ -10298,11 +10298,15 @@ import { decodeJwt } from "jose";
10298
10298
  var getConfig = (options) => ({
10299
10299
  ...options,
10300
10300
  baseUrl: options.baseUrl ?? "https://api.hautech.ai",
10301
- baseWsUrl: options.baseWsUrl ?? options.baseUrl ?? "https://api.hautech.ai"
10301
+ baseWsUrl: options.baseWsUrl ?? options.baseUrl ?? "https://api.hautech.ai",
10302
+ onRequestError: options.onRequestError,
10303
+ invalidateAuthToken: () => void 0
10302
10304
  });
10303
10305
  var getDirectoryConfig = (options) => ({
10304
10306
  baseUrl: options.baseUrl ?? "https://api-directory.hautech.ai",
10305
- authToken: options.authToken
10307
+ authToken: options.authToken,
10308
+ onRequestError: options.onRequestError,
10309
+ invalidateAuthToken: () => void 0
10306
10310
  });
10307
10311
 
10308
10312
  // src/api-utils.ts
@@ -10315,49 +10319,125 @@ var isWrappedFn = (fn) => {
10315
10319
  var isCustomWrappedFn = (fn) => {
10316
10320
  return typeof fn === "function" && fn.__customMethodWrapper === true;
10317
10321
  };
10322
+ var retryLocks = /* @__PURE__ */ new WeakMap();
10323
+ var delay = (ms) => ms > 0 ? new Promise((resolve) => setTimeout(resolve, ms)) : Promise.resolve();
10324
+ var cloneRequestConfig = (request) => ({
10325
+ ...request,
10326
+ headers: request.headers ? { ...request.headers } : request.headers
10327
+ });
10328
+ var toResponseInfo = (response) => {
10329
+ if (!response) return void 0;
10330
+ return {
10331
+ status: response.status,
10332
+ headers: response.headers,
10333
+ data: response.data
10334
+ };
10335
+ };
10336
+ var enhanceAxiosError = (error) => {
10337
+ let responseData;
10338
+ try {
10339
+ const messageFromBody = error.response?.data?.message;
10340
+ if (typeof messageFromBody === "string" && messageFromBody.length > 0) {
10341
+ responseData = messageFromBody;
10342
+ } else if (typeof error.response?.data === "string") {
10343
+ responseData = error.response.data;
10344
+ } else if (error.response?.data !== void 0) {
10345
+ responseData = JSON.stringify(error.response.data);
10346
+ } else {
10347
+ responseData = "[no response data]";
10348
+ }
10349
+ } catch {
10350
+ responseData = "[unserializable data]";
10351
+ }
10352
+ error.message = `Request error: ${error.message || "Unknown error"}.
10353
+ ${responseData}`;
10354
+ };
10355
+ var runOnRequestError = async (config, info, context) => {
10356
+ if (!config.onRequestError) {
10357
+ return void 0;
10358
+ }
10359
+ const status = info.error.response?.status;
10360
+ if (status === 401) {
10361
+ const existing = retryLocks.get(config);
10362
+ if (existing) {
10363
+ return existing;
10364
+ }
10365
+ const pending = (async () => config.onRequestError(info, context))();
10366
+ retryLocks.set(config, pending);
10367
+ try {
10368
+ return await pending;
10369
+ } finally {
10370
+ retryLocks.delete(config);
10371
+ }
10372
+ }
10373
+ return await config.onRequestError(info, context);
10374
+ };
10375
+ var MAX_ATTEMPTS = 2;
10318
10376
  var createApiCallWrapper = (getBaseURL) => {
10319
10377
  return (fn, config) => {
10320
10378
  const wrapped = async function(...args) {
10321
- const token = await config.authToken();
10322
- const baseOptions = {
10323
- baseURL: getBaseURL(config),
10324
- headers: {
10325
- Authorization: `Bearer ${token}`
10326
- }
10327
- };
10328
- const finalArgs = [...args];
10329
- const lastParamIndex = fn.length - 1;
10330
- if (looksLikeAxiosRequestOptions(args[lastParamIndex])) {
10331
- finalArgs[lastParamIndex] = {
10332
- ...args[lastParamIndex],
10333
- ...baseOptions,
10379
+ const originalArgs = [...args];
10380
+ for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
10381
+ const token = await config.authToken();
10382
+ const baseOptions = {
10383
+ baseURL: getBaseURL(config),
10334
10384
  headers: {
10335
- ...args[lastParamIndex]?.headers ?? {},
10336
10385
  Authorization: `Bearer ${token}`
10337
10386
  }
10338
10387
  };
10339
- } else {
10340
- while (finalArgs.length < fn.length - 1) {
10341
- finalArgs.push(void 0);
10388
+ const finalArgs = [...originalArgs];
10389
+ const lastParamIndex = fn.length - 1;
10390
+ if (looksLikeAxiosRequestOptions(originalArgs[lastParamIndex])) {
10391
+ finalArgs[lastParamIndex] = {
10392
+ ...originalArgs[lastParamIndex],
10393
+ ...baseOptions,
10394
+ headers: {
10395
+ ...originalArgs[lastParamIndex]?.headers ?? {},
10396
+ Authorization: `Bearer ${token}`
10397
+ }
10398
+ };
10399
+ } else {
10400
+ while (finalArgs.length < fn.length - 1) {
10401
+ finalArgs.push(void 0);
10402
+ }
10403
+ finalArgs.push(baseOptions);
10342
10404
  }
10343
- finalArgs.push(baseOptions);
10344
- }
10345
- try {
10346
- const res = await fn.call(this, ...finalArgs);
10347
- return typeof res === "object" && "headers" in res ? res.data : res;
10348
- } catch (err) {
10349
- if (axios.isAxiosError(err)) {
10350
- let responseData;
10351
- try {
10352
- responseData = err.response?.data?.message ?? (typeof err.response?.data === "string" ? err.response.data : JSON.stringify(err.response?.data));
10353
- } catch {
10354
- responseData = "[unserializable data]";
10405
+ const requestConfig = finalArgs[finalArgs.length - 1] ?? {};
10406
+ try {
10407
+ const res = await fn.call(this, ...finalArgs);
10408
+ return typeof res === "object" && "headers" in res ? res.data : res;
10409
+ } catch (err) {
10410
+ if (!axios.isAxiosError(err)) {
10411
+ throw err;
10355
10412
  }
10356
- err.message = `Request error: ${err.message || "Unknown error"}.
10357
- ${responseData}`;
10413
+ enhanceAxiosError(err);
10414
+ const context = {
10415
+ attempt,
10416
+ request: cloneRequestConfig(requestConfig)
10417
+ };
10418
+ const handlerResult = await runOnRequestError(
10419
+ config,
10420
+ {
10421
+ error: err,
10422
+ response: toResponseInfo(err.response)
10423
+ },
10424
+ context
10425
+ );
10426
+ if (handlerResult?.invalidateToken) {
10427
+ config.invalidateAuthToken();
10428
+ }
10429
+ const hasAttemptsRemaining = attempt < MAX_ATTEMPTS;
10430
+ if (handlerResult?.retry && hasAttemptsRemaining) {
10431
+ const backoffMs = handlerResult.backoffMs ?? 0;
10432
+ if (backoffMs > 0) {
10433
+ await delay(backoffMs);
10434
+ }
10435
+ continue;
10436
+ }
10437
+ throw err;
10358
10438
  }
10359
- throw err;
10360
10439
  }
10440
+ throw new Error("Request error handling exceeded maximum attempts");
10361
10441
  };
10362
10442
  wrapped.__isWrapped = true;
10363
10443
  return wrapped;
@@ -11870,7 +11950,7 @@ var getOperations = () => {
11870
11950
  };
11871
11951
 
11872
11952
  // src/sdk/api-definitions/operations.ts
11873
- var waitOperation = wrapCustomMethod(async function(operation, timeoutMs = 6e4, delay = 3e3) {
11953
+ var waitOperation = wrapCustomMethod(async function(operation, timeoutMs = 6e4, delay2 = 3e3) {
11874
11954
  const deadline = Date.now() + timeoutMs;
11875
11955
  const sdk = this;
11876
11956
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
@@ -11883,7 +11963,7 @@ var waitOperation = wrapCustomMethod(async function(operation, timeoutMs = 6e4,
11883
11963
  while (Date.now() < deadline) {
11884
11964
  const result = await poll(operation.id);
11885
11965
  if (result) return result;
11886
- await sleep(delay);
11966
+ await sleep(delay2);
11887
11967
  }
11888
11968
  throw new Error("Operation timed out");
11889
11969
  });
@@ -16667,7 +16747,7 @@ var usePipelinesApi = () => {
16667
16747
  const sdk = this;
16668
16748
  return builder(buildPipeline(sdk));
16669
16749
  }),
16670
- wait: wrapCustomMethod(async function(pipeline, timeoutMs = 6e4, delay = 3e3) {
16750
+ wait: wrapCustomMethod(async function(pipeline, timeoutMs = 6e4, delay2 = 3e3) {
16671
16751
  const sdk = this;
16672
16752
  const deadline = Date.now() + timeoutMs;
16673
16753
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
@@ -16682,7 +16762,7 @@ var usePipelinesApi = () => {
16682
16762
  while (Date.now() < deadline) {
16683
16763
  const polled = await poll(pipeline.id);
16684
16764
  if (polled) return polled;
16685
- await sleep(delay);
16765
+ await sleep(delay2);
16686
16766
  }
16687
16767
  throw new Error("Operation timed out");
16688
16768
  })
@@ -17007,6 +17087,12 @@ var WsClient = class {
17007
17087
  this.getSocket().off("server_error");
17008
17088
  }
17009
17089
  }
17090
+ disconnect() {
17091
+ if (this.socket) {
17092
+ this.socket.disconnect();
17093
+ this.socket = void 0;
17094
+ }
17095
+ }
17010
17096
  };
17011
17097
 
17012
17098
  // src/sdk/api.ts
@@ -17041,6 +17127,9 @@ var getWsClientDefinitions = (config) => ({
17041
17127
  var createSDK = (options) => {
17042
17128
  let token = void 0;
17043
17129
  const config = getConfig(options);
17130
+ config.invalidateAuthToken = () => {
17131
+ token = void 0;
17132
+ };
17044
17133
  const authToken = config.authToken;
17045
17134
  const getAuthToken = async () => {
17046
17135
  if (token) {
@@ -17062,6 +17151,9 @@ var createSDK = (options) => {
17062
17151
  var createDirectorySDK = (options) => {
17063
17152
  let token = void 0;
17064
17153
  const config = getDirectoryConfig(options);
17154
+ config.invalidateAuthToken = () => {
17155
+ token = void 0;
17156
+ };
17065
17157
  const authToken = config.authToken;
17066
17158
  const getAuthToken = async () => {
17067
17159
  if (token) {