@uipath/agent-sdk 1.196.0 → 1.197.0-preview.59

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.
Files changed (2) hide show
  1. package/dist/index.js +514 -270
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -19164,6 +19164,9 @@ function singleton(ctorOrName) {
19164
19164
  };
19165
19165
  }
19166
19166
 
19167
+ // ../common/src/telemetry/global-telemetry-properties.ts
19168
+ var telemetryPropsSlot = singleton("TelemetryDefaultProps");
19169
+
19167
19170
  // ../common/src/sdk-user-agent.ts
19168
19171
  var USER_AGENT_HEADER = "User-Agent";
19169
19172
  var sdkUserAgentHostToken = singleton("SdkUserAgentHostToken");
@@ -19187,8 +19190,8 @@ function appendUserAgentToken(value, userAgent) {
19187
19190
  function getEffectiveUserAgent(userAgent) {
19188
19191
  return appendUserAgentToken(sdkUserAgentHostToken.get(), userAgent);
19189
19192
  }
19190
- function isHeadersLike(headers) {
19191
- return typeof headers === "object" && headers !== null && "get" in headers && typeof headers.get === "function" && "set" in headers && typeof headers.set === "function";
19193
+ function getHeaderName(headers, headerName) {
19194
+ return Object.keys(headers).find((key) => key.toLowerCase() === headerName.toLowerCase());
19192
19195
  }
19193
19196
  function getSdkUserAgentToken(pkg) {
19194
19197
  const packageName = pkg.name.replace(/^@uipath\//, "");
@@ -19196,59 +19199,31 @@ function getSdkUserAgentToken(pkg) {
19196
19199
  }
19197
19200
  function addSdkUserAgentHeader(headers, userAgent) {
19198
19201
  const result = { ...headers ?? {} };
19199
- const effectiveUserAgent = getEffectiveUserAgent(userAgent);
19200
- const headerName = Object.keys(result).find((key) => key.toLowerCase() === USER_AGENT_HEADER.toLowerCase());
19201
- if (headerName) {
19202
- result[headerName] = appendUserAgentToken(result[headerName], effectiveUserAgent);
19203
- } else {
19204
- result[USER_AGENT_HEADER] = effectiveUserAgent;
19205
- }
19202
+ const headerName = getHeaderName(result, USER_AGENT_HEADER);
19203
+ result[headerName ?? USER_AGENT_HEADER] = appendUserAgentToken(headerName ? result[headerName] : undefined, getEffectiveUserAgent(userAgent));
19206
19204
  return result;
19207
19205
  }
19208
- function withSdkUserAgentHeader(headers, userAgent) {
19209
- const effectiveUserAgent = getEffectiveUserAgent(userAgent);
19210
- if (isHeadersLike(headers)) {
19211
- headers.set(USER_AGENT_HEADER, appendUserAgentToken(headers.get(USER_AGENT_HEADER), effectiveUserAgent));
19212
- return headers;
19213
- }
19214
- if (Array.isArray(headers)) {
19215
- const result = headers.map((entry) => {
19216
- const [key, value] = entry;
19217
- return [key, value];
19218
- });
19219
- const headerIndex = result.findIndex(([key]) => key.toLowerCase() === USER_AGENT_HEADER.toLowerCase());
19220
- if (headerIndex >= 0) {
19221
- const [key, value] = result[headerIndex];
19222
- result[headerIndex] = [
19223
- key,
19224
- appendUserAgentToken(value, effectiveUserAgent)
19225
- ];
19226
- } else {
19227
- result.push([USER_AGENT_HEADER, effectiveUserAgent]);
19228
- }
19229
- return result;
19230
- }
19231
- return addSdkUserAgentHeader(typeof headers === "object" && headers !== null ? { ...headers } : {}, effectiveUserAgent);
19206
+ function asHeaderRecord(headers) {
19207
+ return typeof headers === "object" && headers !== null ? { ...headers } : {};
19232
19208
  }
19233
- function withUserAgentInitOverride(initOverrides, userAgent) {
19209
+ function withForwardedHeadersInitOverride(initOverrides, forward) {
19234
19210
  return async (requestContext) => {
19235
- const initWithUserAgent = {
19211
+ const initWithHeaders = {
19236
19212
  ...requestContext.init,
19237
- headers: withSdkUserAgentHeader(requestContext.init.headers, userAgent)
19213
+ headers: forward(asHeaderRecord(requestContext.init.headers))
19238
19214
  };
19239
19215
  const override = typeof initOverrides === "function" ? await initOverrides({
19240
19216
  ...requestContext,
19241
- init: initWithUserAgent
19217
+ init: initWithHeaders
19242
19218
  }) : initOverrides;
19243
19219
  return {
19244
19220
  ...override ?? {},
19245
- headers: withSdkUserAgentHeader(override?.headers ?? initWithUserAgent.headers, userAgent)
19221
+ headers: forward(asHeaderRecord(override?.headers ?? initWithHeaders.headers))
19246
19222
  };
19247
19223
  };
19248
19224
  }
19249
- function installSdkUserAgentHeader(BaseApiClass, userAgent) {
19225
+ function installRequestHeaderForwarding(BaseApiClass, patchKey, forward) {
19250
19226
  const prototype = BaseApiClass.prototype;
19251
- const patchKey = userAgentPatchKey(userAgent);
19252
19227
  if (prototype[patchKey]) {
19253
19228
  return;
19254
19229
  }
@@ -19256,13 +19231,16 @@ function installSdkUserAgentHeader(BaseApiClass, userAgent) {
19256
19231
  throw new Error("Generated BaseAPI request function not found.");
19257
19232
  }
19258
19233
  const originalRequest = prototype.request;
19259
- prototype.request = function requestWithUserAgent(context, initOverrides) {
19260
- return originalRequest.call(this, context, withUserAgentInitOverride(initOverrides, userAgent));
19234
+ prototype.request = function requestWithForwardedHeaders(context, initOverrides) {
19235
+ return originalRequest.call(this, context, withForwardedHeadersInitOverride(initOverrides, forward));
19261
19236
  };
19262
19237
  Object.defineProperty(prototype, patchKey, {
19263
19238
  value: true
19264
19239
  });
19265
19240
  }
19241
+ function installSdkUserAgentHeader(BaseApiClass, userAgent) {
19242
+ installRequestHeaderForwarding(BaseApiClass, userAgentPatchKey(userAgent), (headers) => addSdkUserAgentHeader(headers, userAgent));
19243
+ }
19266
19244
 
19267
19245
  // generated/src/runtime.ts
19268
19246
  var BASE_PATH = "http://localhost".replace(/\/+$/, "");
@@ -19575,7 +19553,7 @@ class TextApiResponse {
19575
19553
  var package_default = {
19576
19554
  name: "@uipath/agent-sdk",
19577
19555
  license: "MIT",
19578
- version: "1.196.0",
19556
+ version: "1.197.0-preview.59",
19579
19557
  description: "SDK for the UiPath Agent Runtime API — evaluation execution and debug sessions.",
19580
19558
  repository: {
19581
19559
  type: "git",
@@ -19604,7 +19582,7 @@ var package_default = {
19604
19582
  "dist"
19605
19583
  ],
19606
19584
  scripts: {
19607
- build: "bun build ./src/index.ts --outdir dist --format esm --target node && tsc -p tsconfig.build.json --noCheck",
19585
+ build: "bun build ./src/index.ts --outdir dist --format esm --target node --sourcemap=linked && tsc -p tsconfig.build.json --noCheck",
19608
19586
  generate: "bun run src/scripts/generate-sdk.ts",
19609
19587
  test: "vitest run",
19610
19588
  "test:coverage": "vitest run --coverage",
@@ -22607,6 +22585,12 @@ var normalizeAndValidateBaseUrl = (rawUrl) => {
22607
22585
  }
22608
22586
  return url.pathname.length > 1 ? url.origin : baseUrl;
22609
22587
  };
22588
+ var resolveScopes = (isExternalAppAuth, customScopes, fileScopes) => {
22589
+ const requestedScopes = customScopes?.length ? customScopes : fileScopes ?? [];
22590
+ if (isExternalAppAuth)
22591
+ return requestedScopes;
22592
+ return [...new Set([...DEFAULT_SCOPES, ...requestedScopes])];
22593
+ };
22610
22594
  var resolveConfigAsync = async ({
22611
22595
  customAuthority,
22612
22596
  customClientId,
@@ -22637,7 +22621,7 @@ var resolveConfigAsync = async ({
22637
22621
  clientSecret = fileAuth.clientSecret;
22638
22622
  }
22639
22623
  const isExternalAppAuth = clientId !== DEFAULT_CLIENT_ID && Boolean(clientSecret);
22640
- const scopes = customScopes && customScopes.length > 0 ? customScopes : fileAuth.scopes && fileAuth.scopes.length > 0 ? fileAuth.scopes : isExternalAppAuth ? [] : DEFAULT_SCOPES;
22624
+ const scopes = resolveScopes(isExternalAppAuth, customScopes, fileAuth.scopes);
22641
22625
  return {
22642
22626
  clientId,
22643
22627
  clientSecret,
@@ -22652,6 +22636,76 @@ var resolveConfigAsync = async ({
22652
22636
  init_constants();
22653
22637
  // ../auth/src/loginStatus.ts
22654
22638
  init_src();
22639
+
22640
+ // ../auth/src/authProfile.ts
22641
+ init_src();
22642
+ init_constants();
22643
+ var DEFAULT_AUTH_PROFILE = "default";
22644
+ var PROFILE_DIR = "profiles";
22645
+ var PROFILE_NAME_RE = /^[A-Za-z0-9._-]+$/;
22646
+ var ACTIVE_AUTH_PROFILE_KEY = Symbol.for("@uipath/auth/ActiveAuthProfile");
22647
+ var AUTH_PROFILE_STORAGE_KEY = Symbol.for("@uipath/auth/ProfileStorage");
22648
+ var globalSlot2 = globalThis;
22649
+ function isAuthProfileStorage(value) {
22650
+ return value !== null && typeof value === "object" && "getStore" in value && "run" in value;
22651
+ }
22652
+ function createProfileStorage() {
22653
+ const [error, mod] = catchError(() => __require("node:async_hooks"));
22654
+ if (error || typeof mod?.AsyncLocalStorage !== "function") {
22655
+ return {
22656
+ getStore: () => {
22657
+ return;
22658
+ },
22659
+ run: (_store, fn) => fn()
22660
+ };
22661
+ }
22662
+ return new mod.AsyncLocalStorage;
22663
+ }
22664
+ function getProfileStorage() {
22665
+ const existing = globalSlot2[AUTH_PROFILE_STORAGE_KEY];
22666
+ if (isAuthProfileStorage(existing)) {
22667
+ return existing;
22668
+ }
22669
+ const storage = createProfileStorage();
22670
+ globalSlot2[AUTH_PROFILE_STORAGE_KEY] = storage;
22671
+ return storage;
22672
+ }
22673
+ var profileStorage = getProfileStorage();
22674
+
22675
+ class AuthProfileValidationError extends Error {
22676
+ constructor(message) {
22677
+ super(message);
22678
+ this.name = "AuthProfileValidationError";
22679
+ }
22680
+ }
22681
+ function normalizeAuthProfileName(profile) {
22682
+ if (profile === undefined || profile === DEFAULT_AUTH_PROFILE) {
22683
+ return;
22684
+ }
22685
+ if (profile.length === 0 || profile === "." || profile === ".." || !PROFILE_NAME_RE.test(profile)) {
22686
+ throw new AuthProfileValidationError(`Invalid profile name "${profile}". Profile names may contain only letters, numbers, '.', '_', and '-'.`);
22687
+ }
22688
+ return profile;
22689
+ }
22690
+ function getActiveAuthProfile() {
22691
+ const scopedState = profileStorage.getStore();
22692
+ if (scopedState !== undefined) {
22693
+ return scopedState.profile;
22694
+ }
22695
+ return globalSlot2[ACTIVE_AUTH_PROFILE_KEY]?.profile;
22696
+ }
22697
+ function resolveAuthProfileFilePath(profile) {
22698
+ const normalized = normalizeAuthProfileName(profile);
22699
+ if (normalized === undefined) {
22700
+ throw new AuthProfileValidationError(`"${DEFAULT_AUTH_PROFILE}" is the built-in profile and does not have a profile file path.`);
22701
+ }
22702
+ const fs7 = getFileSystem();
22703
+ return fs7.path.join(fs7.env.homedir(), UIPATH_HOME_DIR, PROFILE_DIR, normalized, AUTH_FILENAME);
22704
+ }
22705
+ function getActiveAuthProfileFilePath() {
22706
+ const profile = getActiveAuthProfile();
22707
+ return profile ? resolveAuthProfileFilePath(profile) : undefined;
22708
+ }
22655
22709
  // ../auth/src/utils/jwt.ts
22656
22710
  class InvalidIssuerError extends Error {
22657
22711
  expected;
@@ -22780,23 +22834,74 @@ var readAuthFromEnv = () => {
22780
22834
  organizationId,
22781
22835
  tenantName,
22782
22836
  tenantId,
22783
- expiration
22837
+ expiration,
22838
+ source: "env" /* Env */
22784
22839
  };
22785
22840
  };
22786
22841
 
22842
+ // ../auth/src/refreshCircuitBreaker.ts
22843
+ init_src();
22844
+ var BREAKER_SUFFIX = ".refresh-state";
22845
+ var BACKOFF_BASE_MS = 60000;
22846
+ var BACKOFF_CAP_MS = 60 * 60 * 1000;
22847
+ var SURFACE_WINDOW_MS = 60 * 60 * 1000;
22848
+ async function refreshTokenFingerprint(refreshToken) {
22849
+ const bytes = new TextEncoder().encode(refreshToken);
22850
+ if (globalThis.crypto?.subtle) {
22851
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", bytes);
22852
+ return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, "0")).join("").slice(0, 16);
22853
+ }
22854
+ const { createHash } = await import("node:crypto");
22855
+ return createHash("sha256").update(refreshToken).digest("hex").slice(0, 16);
22856
+ }
22857
+ function breakerPathFor(authPath) {
22858
+ return `${authPath}${BREAKER_SUFFIX}`;
22859
+ }
22860
+ async function loadRefreshBreaker(authPath) {
22861
+ const fs7 = getFileSystem();
22862
+ try {
22863
+ const content = await fs7.readFile(breakerPathFor(authPath), "utf-8");
22864
+ if (!content)
22865
+ return {};
22866
+ const parsed = JSON.parse(content);
22867
+ return parsed && typeof parsed === "object" ? parsed : {};
22868
+ } catch {
22869
+ return {};
22870
+ }
22871
+ }
22872
+ async function saveRefreshBreaker(authPath, state) {
22873
+ try {
22874
+ const fs7 = getFileSystem();
22875
+ const path3 = breakerPathFor(authPath);
22876
+ await fs7.mkdir(fs7.path.dirname(path3));
22877
+ const tempPath = `${path3}.tmp`;
22878
+ await fs7.writeFile(tempPath, JSON.stringify(state));
22879
+ await fs7.rename(tempPath, path3);
22880
+ } catch {}
22881
+ }
22882
+ async function clearRefreshBreaker(authPath) {
22883
+ const fs7 = getFileSystem();
22884
+ const path3 = breakerPathFor(authPath);
22885
+ try {
22886
+ if (await fs7.exists(path3)) {
22887
+ await fs7.rm(path3);
22888
+ }
22889
+ } catch {}
22890
+ }
22891
+ function nextBackoffMs(attempts) {
22892
+ const shift = Math.max(0, attempts - 1);
22893
+ return Math.min(BACKOFF_BASE_MS * 2 ** shift, BACKOFF_CAP_MS);
22894
+ }
22895
+ function shouldSurface(state, nowMs) {
22896
+ if (state.lastSurfacedAtMs === undefined)
22897
+ return true;
22898
+ return nowMs - state.lastSurfacedAtMs >= SURFACE_WINDOW_MS;
22899
+ }
22900
+
22787
22901
  // ../auth/src/robotClientFallback.ts
22788
22902
  init_src();
22789
22903
  var DEFAULT_TIMEOUT_MS = 1000;
22790
22904
  var CLOSE_TIMEOUT_MS = 500;
22791
- var NOTICE_SENTINEL = Symbol.for("@uipath/auth/robotFallbackNoticePrinted");
22792
- var printNoticeOnce = () => {
22793
- const slot = globalThis;
22794
- if (slot[NOTICE_SENTINEL])
22795
- return;
22796
- slot[NOTICE_SENTINEL] = true;
22797
- catchError(() => process.stderr.write(`Using UiPath Robot credentials. Run 'uip login' for a dedicated session.
22798
- `));
22799
- };
22800
22905
  var ROBOT_USER_SERVICES_PIPE = "UiPathUserServices";
22801
22906
  var ROBOT_USER_SERVICES_ALTERNATE_PIPE = `${ROBOT_USER_SERVICES_PIPE}Alternate`;
22802
22907
  var PIPE_NAME_MAX_LENGTH = 103;
@@ -22912,7 +23017,6 @@ var tryRobotClientFallback = async (options = {}) => {
22912
23017
  issuerFromToken = issClaim;
22913
23018
  }
22914
23019
  }
22915
- printNoticeOnce();
22916
23020
  return {
22917
23021
  accessToken,
22918
23022
  baseUrl: parsedUrl.baseUrl,
@@ -23137,18 +23241,327 @@ var saveEnvFileAsync = async ({
23137
23241
  };
23138
23242
 
23139
23243
  // ../auth/src/loginStatus.ts
23140
- function normalizeTokenRefreshFailure() {
23141
- return "stored refresh token is invalid or expired";
23244
+ var getLoginStatusAsync = async (options = {}) => {
23245
+ return getLoginStatusWithDeps(options);
23246
+ };
23247
+ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
23248
+ const {
23249
+ resolveEnvFilePath = resolveEnvFilePathAsync,
23250
+ loadEnvFile = loadEnvFileAsync,
23251
+ saveEnvFile = saveEnvFileAsync,
23252
+ getFs = getFileSystem,
23253
+ refreshToken: refreshTokenFn = refreshAccessToken,
23254
+ resolveConfig = resolveConfigAsync,
23255
+ robotFallback = tryRobotClientFallback,
23256
+ loadBreaker = loadRefreshBreaker,
23257
+ saveBreaker = saveRefreshBreaker,
23258
+ clearBreaker = clearRefreshBreaker
23259
+ } = deps;
23260
+ if (isRobotAuthEnforced()) {
23261
+ return resolveRobotEnforcedStatus(robotFallback);
23262
+ }
23263
+ if (isEnvAuthEnabled()) {
23264
+ return readAuthFromEnv();
23265
+ }
23266
+ const activeProfile = getActiveAuthProfile();
23267
+ const activeProfileFilePath = getActiveAuthProfileFilePath();
23268
+ const usingActiveProfile = activeProfile !== undefined && (options.envFilePath === undefined || options.envFilePath === activeProfileFilePath);
23269
+ const envFilePath = options.envFilePath ?? activeProfileFilePath ?? DEFAULT_ENV_FILENAME;
23270
+ const { ensureTokenValidityMinutes } = options;
23271
+ const { absolutePath } = await resolveEnvFilePath(envFilePath);
23272
+ if (absolutePath === undefined) {
23273
+ if (usingActiveProfile) {
23274
+ return {
23275
+ loginStatus: "Not logged in",
23276
+ hint: `No credentials found for profile "${activeProfile}". Run 'uip login --profile ${activeProfile}' to authenticate this profile.`
23277
+ };
23278
+ }
23279
+ return resolveBorrowedRobotStatus(robotFallback);
23280
+ }
23281
+ const loaded = await loadFileCredentials(loadEnvFile, absolutePath);
23282
+ if ("status" in loaded) {
23283
+ return loaded.status;
23284
+ }
23285
+ const { credentials } = loaded;
23286
+ const globalHint = () => usingActiveProfile ? Promise.resolve(undefined) : getGlobalCredsHint(getFs, loadEnvFile, absolutePath, envFilePath);
23287
+ const expiration = getTokenExpiration(credentials.UIPATH_ACCESS_TOKEN);
23288
+ const outerThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
23289
+ let tokens = {
23290
+ accessToken: credentials.UIPATH_ACCESS_TOKEN,
23291
+ refreshToken: credentials.UIPATH_REFRESH_TOKEN,
23292
+ expiration,
23293
+ lockReleaseFailed: false
23294
+ };
23295
+ const refreshToken = credentials.UIPATH_REFRESH_TOKEN;
23296
+ if (expiration && expiration <= outerThreshold && refreshToken) {
23297
+ const refreshed = await attemptRefresh({
23298
+ absolutePath,
23299
+ credentials,
23300
+ accessToken: credentials.UIPATH_ACCESS_TOKEN,
23301
+ refreshToken,
23302
+ expiration,
23303
+ ensureTokenValidityMinutes,
23304
+ getFs,
23305
+ loadEnvFile,
23306
+ saveEnvFile,
23307
+ refreshFn: refreshTokenFn,
23308
+ resolveConfig,
23309
+ loadBreaker,
23310
+ saveBreaker,
23311
+ clearBreaker,
23312
+ globalHint
23313
+ });
23314
+ if (refreshed.kind === "terminal") {
23315
+ return refreshed.status;
23316
+ }
23317
+ tokens = refreshed.tokens;
23318
+ }
23319
+ return buildFileStatus(tokens, credentials, globalHint);
23320
+ };
23321
+ async function resolveRobotEnforcedStatus(robotFallback) {
23322
+ if (isEnvAuthEnabled()) {
23323
+ throw new EnvAuthConfigError(`${ENV_AUTH_ENABLE_VAR}=true and ${ENFORCE_ROBOT_AUTH_VAR}=true ` + `are mutually exclusive. Unset one of them and re-run.`);
23324
+ }
23325
+ const robotCreds = await robotFallback({ force: true });
23326
+ if (!robotCreds) {
23327
+ return {
23328
+ loginStatus: "Not logged in",
23329
+ hint: `${ENFORCE_ROBOT_AUTH_VAR}=true but the UiPath Robot ` + `session is unavailable. Start and sign in to the Assistant, ` + `or unset ${ENFORCE_ROBOT_AUTH_VAR} to fall back to file or ` + `env-var authentication.`
23330
+ };
23331
+ }
23332
+ return buildRobotStatus(robotCreds);
23142
23333
  }
23143
- function normalizeTokenRefreshUnavailableFailure() {
23144
- return "token refresh failed before authentication completed";
23334
+ async function resolveBorrowedRobotStatus(robotFallback) {
23335
+ const robotCreds = await robotFallback();
23336
+ return robotCreds ? buildRobotStatus(robotCreds) : { loginStatus: "Not logged in" };
23145
23337
  }
23146
- function errorMessage(error) {
23147
- return error instanceof Error ? error.message : String(error);
23338
+ async function loadFileCredentials(loadEnvFile, absolutePath) {
23339
+ let credentials;
23340
+ try {
23341
+ credentials = await loadEnvFile({ envPath: absolutePath });
23342
+ } catch (error) {
23343
+ if (isFileNotFoundError(error)) {
23344
+ return { status: { loginStatus: "Not logged in" } };
23345
+ }
23346
+ throw error;
23347
+ }
23348
+ if (!credentials.UIPATH_ACCESS_TOKEN) {
23349
+ return { status: { loginStatus: "Not logged in" } };
23350
+ }
23351
+ return { credentials };
23352
+ }
23353
+ async function getGlobalCredsHint(getFs, loadEnvFile, absolutePath, envFilePath) {
23354
+ const fs7 = getFs();
23355
+ const globalPath = fs7.path.join(fs7.env.homedir(), envFilePath);
23356
+ if (absolutePath === globalPath)
23357
+ return;
23358
+ if (!await fs7.exists(globalPath))
23359
+ return;
23360
+ try {
23361
+ const globalCreds = await loadEnvFile({ envPath: globalPath });
23362
+ if (!globalCreds.UIPATH_ACCESS_TOKEN)
23363
+ return;
23364
+ const globalExp = getTokenExpiration(globalCreds.UIPATH_ACCESS_TOKEN);
23365
+ if (globalExp && globalExp <= new Date)
23366
+ return;
23367
+ return `Local credentials file at ${absolutePath} has expired credentials. Valid credentials exist in ${globalPath}. Remove the local file or run 'uip login' to re-authenticate.`;
23368
+ } catch {
23369
+ return;
23370
+ }
23148
23371
  }
23149
23372
  function computeExpirationThreshold(ensureTokenValidityMinutes) {
23150
23373
  return new Date(Date.now() + (ensureTokenValidityMinutes ?? 0) * 60 * 1000);
23151
23374
  }
23375
+ async function attemptRefresh(ctx) {
23376
+ const shortCircuit = await circuitBreakerShortCircuit(ctx);
23377
+ if (shortCircuit) {
23378
+ return { kind: "terminal", status: shortCircuit };
23379
+ }
23380
+ let release;
23381
+ try {
23382
+ release = await ctx.getFs().acquireLock(ctx.absolutePath);
23383
+ } catch (error) {
23384
+ return {
23385
+ kind: "terminal",
23386
+ status: await lockAcquireFailureStatus(ctx, error)
23387
+ };
23388
+ }
23389
+ let lockedFailure;
23390
+ let lockReleaseFailed = false;
23391
+ let success;
23392
+ try {
23393
+ const outcome = await runRefreshLocked({
23394
+ absolutePath: ctx.absolutePath,
23395
+ refreshToken: ctx.refreshToken,
23396
+ customAuthority: ctx.credentials.UIPATH_URL,
23397
+ ensureTokenValidityMinutes: ctx.ensureTokenValidityMinutes,
23398
+ loadEnvFile: ctx.loadEnvFile,
23399
+ saveEnvFile: ctx.saveEnvFile,
23400
+ refreshFn: ctx.refreshFn,
23401
+ resolveConfig: ctx.resolveConfig,
23402
+ loadBreaker: ctx.loadBreaker,
23403
+ saveBreaker: ctx.saveBreaker,
23404
+ clearBreaker: ctx.clearBreaker
23405
+ });
23406
+ if (outcome.kind === "fail") {
23407
+ lockedFailure = outcome.status;
23408
+ } else {
23409
+ success = outcome;
23410
+ }
23411
+ } finally {
23412
+ try {
23413
+ await release();
23414
+ } catch {
23415
+ lockReleaseFailed = true;
23416
+ }
23417
+ }
23418
+ if (lockedFailure) {
23419
+ const globalHint = await ctx.globalHint();
23420
+ const base = globalHint ? { ...lockedFailure, loginStatus: "Expired", hint: globalHint } : lockedFailure;
23421
+ return {
23422
+ kind: "terminal",
23423
+ status: lockReleaseFailed ? { ...base, lockReleaseFailed: true } : base
23424
+ };
23425
+ }
23426
+ return {
23427
+ kind: "refreshed",
23428
+ tokens: {
23429
+ accessToken: success?.accessToken,
23430
+ refreshToken: success?.refreshToken,
23431
+ expiration: success?.expiration,
23432
+ tokenRefresh: success?.tokenRefresh,
23433
+ persistenceWarning: success?.persistenceWarning,
23434
+ lockReleaseFailed
23435
+ }
23436
+ };
23437
+ }
23438
+ async function buildFileStatus(tokens, credentials, globalHint) {
23439
+ const result = {
23440
+ loginStatus: tokens.expiration && tokens.expiration <= new Date ? "Expired" : "Logged in",
23441
+ accessToken: tokens.accessToken,
23442
+ refreshToken: tokens.refreshToken,
23443
+ baseUrl: credentials.UIPATH_URL,
23444
+ organizationName: credentials.UIPATH_ORGANIZATION_NAME,
23445
+ organizationId: credentials.UIPATH_ORGANIZATION_ID,
23446
+ tenantName: credentials.UIPATH_TENANT_NAME,
23447
+ tenantId: credentials.UIPATH_TENANT_ID,
23448
+ expiration: tokens.expiration,
23449
+ source: "file" /* File */,
23450
+ ...tokens.persistenceWarning ? { hint: tokens.persistenceWarning, persistenceFailed: true } : {},
23451
+ ...tokens.lockReleaseFailed ? { lockReleaseFailed: true } : {},
23452
+ ...tokens.tokenRefresh ? { tokenRefresh: tokens.tokenRefresh } : {}
23453
+ };
23454
+ if (result.loginStatus === "Expired") {
23455
+ const hint = await globalHint();
23456
+ if (hint) {
23457
+ result.hint = hint;
23458
+ }
23459
+ }
23460
+ return result;
23461
+ }
23462
+ function buildRobotStatus(robotCreds) {
23463
+ return {
23464
+ loginStatus: "Logged in",
23465
+ accessToken: robotCreds.accessToken,
23466
+ baseUrl: robotCreds.baseUrl,
23467
+ organizationName: robotCreds.organizationName,
23468
+ organizationId: robotCreds.organizationId,
23469
+ tenantName: robotCreds.tenantName,
23470
+ tenantId: robotCreds.tenantId,
23471
+ issuer: robotCreds.issuer,
23472
+ expiration: getTokenExpiration(robotCreds.accessToken),
23473
+ source: "robot" /* Robot */
23474
+ };
23475
+ }
23476
+ var isFileNotFoundError = (error) => {
23477
+ if (!(error instanceof Object))
23478
+ return false;
23479
+ return error.code === "ENOENT";
23480
+ };
23481
+ async function circuitBreakerShortCircuit(ctx) {
23482
+ const {
23483
+ absolutePath,
23484
+ refreshToken,
23485
+ accessToken,
23486
+ credentials,
23487
+ expiration,
23488
+ loadBreaker,
23489
+ saveBreaker,
23490
+ clearBreaker
23491
+ } = ctx;
23492
+ const fingerprint = await refreshTokenFingerprint(refreshToken);
23493
+ const breaker = await loadBreaker(absolutePath).catch(() => ({}));
23494
+ if (breaker.deadTokenFp && breaker.deadTokenFp !== fingerprint) {
23495
+ await clearBreaker(absolutePath);
23496
+ breaker.deadTokenFp = undefined;
23497
+ }
23498
+ const nowMs = Date.now();
23499
+ const tokenIsDead = breaker.deadTokenFp === fingerprint;
23500
+ const inBackoff = breaker.backoffUntilMs !== undefined && nowMs < breaker.backoffUntilMs;
23501
+ if (!tokenIsDead && !inBackoff)
23502
+ return;
23503
+ const globalHint = await ctx.globalHint();
23504
+ const suppressed = !shouldSurface(breaker, nowMs);
23505
+ if (!suppressed) {
23506
+ await saveBreaker(absolutePath, {
23507
+ ...breaker,
23508
+ lastSurfacedAtMs: nowMs
23509
+ });
23510
+ }
23511
+ const deadHint = "Run 'uip login' to re-authenticate — the stored refresh token is invalid or expired. In a non-interactive context, authenticate with: uip login --client-id <id> --client-secret <secret> -t <tenant>.";
23512
+ const backoffHint = "Token refresh is temporarily backed off after a recent network error and will retry automatically once the backoff window elapses.";
23513
+ return {
23514
+ loginStatus: globalHint ? "Expired" : "Refresh Failed",
23515
+ ...globalHint ? {
23516
+ accessToken,
23517
+ refreshToken,
23518
+ baseUrl: credentials.UIPATH_URL,
23519
+ organizationName: credentials.UIPATH_ORGANIZATION_NAME,
23520
+ organizationId: credentials.UIPATH_ORGANIZATION_ID,
23521
+ tenantName: credentials.UIPATH_TENANT_NAME,
23522
+ tenantId: credentials.UIPATH_TENANT_ID,
23523
+ expiration,
23524
+ source: "file" /* File */
23525
+ } : {},
23526
+ hint: globalHint ?? (tokenIsDead ? deadHint : backoffHint),
23527
+ refreshCircuitOpen: true,
23528
+ refreshTelemetrySuppressed: suppressed,
23529
+ tokenRefresh: { attempted: false, success: false }
23530
+ };
23531
+ }
23532
+ async function lockAcquireFailureStatus(ctx, error) {
23533
+ const msg = errorMessage(error);
23534
+ const globalHint = await ctx.globalHint();
23535
+ if (globalHint) {
23536
+ return {
23537
+ loginStatus: "Expired",
23538
+ accessToken: ctx.accessToken,
23539
+ refreshToken: ctx.refreshToken,
23540
+ baseUrl: ctx.credentials.UIPATH_URL,
23541
+ organizationName: ctx.credentials.UIPATH_ORGANIZATION_NAME,
23542
+ organizationId: ctx.credentials.UIPATH_ORGANIZATION_ID,
23543
+ tenantName: ctx.credentials.UIPATH_TENANT_NAME,
23544
+ tenantId: ctx.credentials.UIPATH_TENANT_ID,
23545
+ expiration: ctx.expiration,
23546
+ source: "file" /* File */,
23547
+ hint: globalHint,
23548
+ tokenRefresh: {
23549
+ attempted: false,
23550
+ success: false,
23551
+ errorMessage: `lock acquisition failed: ${msg}`
23552
+ }
23553
+ };
23554
+ }
23555
+ return {
23556
+ loginStatus: "Refresh Failed",
23557
+ hint: "Could not acquire the auth-file lock — too many concurrent `uip` processes, or a permission issue on the auth directory. Retry, or run 'uip login' to re-authenticate.",
23558
+ tokenRefresh: {
23559
+ attempted: false,
23560
+ success: false,
23561
+ errorMessage: `lock acquisition failed: ${msg}`
23562
+ }
23563
+ };
23564
+ }
23152
23565
  async function runRefreshLocked(inputs) {
23153
23566
  const {
23154
23567
  absolutePath,
@@ -23158,7 +23571,10 @@ async function runRefreshLocked(inputs) {
23158
23571
  loadEnvFile,
23159
23572
  saveEnvFile,
23160
23573
  refreshFn,
23161
- resolveConfig
23574
+ resolveConfig,
23575
+ loadBreaker,
23576
+ saveBreaker,
23577
+ clearBreaker
23162
23578
  } = inputs;
23163
23579
  const expirationThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
23164
23580
  let fresh;
@@ -23181,6 +23597,7 @@ async function runRefreshLocked(inputs) {
23181
23597
  const freshAccess = fresh.UIPATH_ACCESS_TOKEN;
23182
23598
  const freshExp = freshAccess ? getTokenExpiration(freshAccess) : undefined;
23183
23599
  if (freshAccess && freshExp && freshExp > expirationThreshold) {
23600
+ await clearBreaker(absolutePath);
23184
23601
  return {
23185
23602
  kind: "ok",
23186
23603
  accessToken: freshAccess,
@@ -23204,8 +23621,21 @@ async function runRefreshLocked(inputs) {
23204
23621
  refreshedRefresh = refreshed.refreshToken;
23205
23622
  } catch (error) {
23206
23623
  const isOAuthFailure = isTokenRefreshOAuthFailure(error);
23207
- const hint = isOAuthFailure ? "Run 'uip login' to re-authenticate — the stored refresh token is invalid or expired." : "Token refresh failed. Check your network connection, then retry or run 'uip login' to re-authenticate.";
23624
+ const hint = isOAuthFailure ? "Run 'uip login' to re-authenticate — the stored refresh token is invalid or expired. In a non-interactive context, authenticate with: uip login --client-id <id> --client-secret <secret> -t <tenant>." : "Token refresh failed. Check your network connection, then retry or run 'uip login' to re-authenticate.";
23208
23625
  const message = isOAuthFailure ? normalizeTokenRefreshFailure() : normalizeTokenRefreshUnavailableFailure();
23626
+ const fp = await refreshTokenFingerprint(tokenForIdP);
23627
+ if (isOAuthFailure) {
23628
+ await saveBreaker(absolutePath, { deadTokenFp: fp });
23629
+ } else {
23630
+ const prior = await loadBreaker(absolutePath).catch(() => ({}));
23631
+ const attempts = (prior.attempts ?? 0) + 1;
23632
+ await saveBreaker(absolutePath, {
23633
+ ...prior,
23634
+ deadTokenFp: undefined,
23635
+ attempts,
23636
+ backoffUntilMs: Date.now() + nextBackoffMs(attempts)
23637
+ });
23638
+ }
23209
23639
  return {
23210
23640
  kind: "fail",
23211
23641
  status: {
@@ -23234,6 +23664,7 @@ async function runRefreshLocked(inputs) {
23234
23664
  }
23235
23665
  };
23236
23666
  }
23667
+ await clearBreaker(absolutePath);
23237
23668
  try {
23238
23669
  await saveEnvFile({
23239
23670
  envPath: absolutePath,
@@ -23266,212 +23697,15 @@ async function runRefreshLocked(inputs) {
23266
23697
  };
23267
23698
  }
23268
23699
  }
23269
- var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
23270
- const {
23271
- resolveEnvFilePath = resolveEnvFilePathAsync,
23272
- loadEnvFile = loadEnvFileAsync,
23273
- saveEnvFile = saveEnvFileAsync,
23274
- getFs = getFileSystem,
23275
- refreshToken: refreshTokenFn = refreshAccessToken,
23276
- resolveConfig = resolveConfigAsync,
23277
- robotFallback = tryRobotClientFallback
23278
- } = deps;
23279
- if (isRobotAuthEnforced()) {
23280
- if (isEnvAuthEnabled()) {
23281
- throw new EnvAuthConfigError(`${ENV_AUTH_ENABLE_VAR}=true and ${ENFORCE_ROBOT_AUTH_VAR}=true ` + `are mutually exclusive. Unset one of them and re-run.`);
23282
- }
23283
- const robotCreds = await robotFallback({ force: true });
23284
- if (!robotCreds) {
23285
- return {
23286
- loginStatus: "Not logged in",
23287
- hint: `${ENFORCE_ROBOT_AUTH_VAR}=true but the UiPath Robot ` + `session is unavailable. Start and sign in to the Assistant, ` + `or unset ${ENFORCE_ROBOT_AUTH_VAR} to fall back to file or ` + `env-var authentication.`
23288
- };
23289
- }
23290
- const expiration2 = getTokenExpiration(robotCreds.accessToken);
23291
- return {
23292
- loginStatus: "Logged in",
23293
- accessToken: robotCreds.accessToken,
23294
- baseUrl: robotCreds.baseUrl,
23295
- organizationName: robotCreds.organizationName,
23296
- organizationId: robotCreds.organizationId,
23297
- tenantName: robotCreds.tenantName,
23298
- tenantId: robotCreds.tenantId,
23299
- issuer: robotCreds.issuer,
23300
- expiration: expiration2,
23301
- source: "robot" /* Robot */
23302
- };
23303
- }
23304
- if (isEnvAuthEnabled()) {
23305
- return readAuthFromEnv();
23306
- }
23307
- const { envFilePath = DEFAULT_ENV_FILENAME, ensureTokenValidityMinutes } = options;
23308
- const { absolutePath } = await resolveEnvFilePath(envFilePath);
23309
- if (absolutePath === undefined) {
23310
- const robotCreds = await robotFallback();
23311
- if (robotCreds) {
23312
- const expiration2 = getTokenExpiration(robotCreds.accessToken);
23313
- const status = {
23314
- loginStatus: "Logged in",
23315
- accessToken: robotCreds.accessToken,
23316
- baseUrl: robotCreds.baseUrl,
23317
- organizationName: robotCreds.organizationName,
23318
- organizationId: robotCreds.organizationId,
23319
- tenantName: robotCreds.tenantName,
23320
- tenantId: robotCreds.tenantId,
23321
- issuer: robotCreds.issuer,
23322
- expiration: expiration2,
23323
- source: "robot" /* Robot */
23324
- };
23325
- return status;
23326
- }
23327
- return { loginStatus: "Not logged in" };
23328
- }
23329
- let credentials;
23330
- try {
23331
- credentials = await loadEnvFile({ envPath: absolutePath });
23332
- } catch (error) {
23333
- if (isFileNotFoundError(error)) {
23334
- return { loginStatus: "Not logged in" };
23335
- }
23336
- throw error;
23337
- }
23338
- if (!credentials.UIPATH_ACCESS_TOKEN) {
23339
- return { loginStatus: "Not logged in" };
23340
- }
23341
- let accessToken = credentials.UIPATH_ACCESS_TOKEN;
23342
- let refreshToken = credentials.UIPATH_REFRESH_TOKEN;
23343
- let expiration = getTokenExpiration(accessToken);
23344
- let persistenceWarning;
23345
- let lockReleaseFailed = false;
23346
- let tokenRefresh;
23347
- const outerThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
23348
- const tryGlobalCredsHint = async () => {
23349
- const fs7 = getFs();
23350
- const globalPath = fs7.path.join(fs7.env.homedir(), envFilePath);
23351
- if (absolutePath === globalPath)
23352
- return;
23353
- if (!await fs7.exists(globalPath))
23354
- return;
23355
- try {
23356
- const globalCreds = await loadEnvFile({ envPath: globalPath });
23357
- if (!globalCreds.UIPATH_ACCESS_TOKEN)
23358
- return;
23359
- const globalExp = getTokenExpiration(globalCreds.UIPATH_ACCESS_TOKEN);
23360
- if (globalExp && globalExp <= new Date)
23361
- return;
23362
- return `Local credentials file at ${absolutePath} has expired credentials. Valid credentials exist in ${globalPath}. Remove the local file or run 'uip login' to re-authenticate.`;
23363
- } catch {
23364
- return;
23365
- }
23366
- };
23367
- if (expiration && expiration <= outerThreshold && refreshToken) {
23368
- let release;
23369
- try {
23370
- release = await getFs().acquireLock(absolutePath);
23371
- } catch (error) {
23372
- const msg = errorMessage(error);
23373
- const globalHint = await tryGlobalCredsHint();
23374
- if (globalHint) {
23375
- return {
23376
- loginStatus: "Expired",
23377
- accessToken,
23378
- refreshToken,
23379
- baseUrl: credentials.UIPATH_URL,
23380
- organizationName: credentials.UIPATH_ORGANIZATION_NAME,
23381
- organizationId: credentials.UIPATH_ORGANIZATION_ID,
23382
- tenantName: credentials.UIPATH_TENANT_NAME,
23383
- tenantId: credentials.UIPATH_TENANT_ID,
23384
- expiration,
23385
- source: "file" /* File */,
23386
- hint: globalHint,
23387
- tokenRefresh: {
23388
- attempted: false,
23389
- success: false,
23390
- errorMessage: `lock acquisition failed: ${msg}`
23391
- }
23392
- };
23393
- }
23394
- return {
23395
- loginStatus: "Refresh Failed",
23396
- hint: "Could not acquire the auth-file lock — too many concurrent `uip` processes, or a permission issue on the auth directory. Retry, or run 'uip login' to re-authenticate.",
23397
- tokenRefresh: {
23398
- attempted: false,
23399
- success: false,
23400
- errorMessage: `lock acquisition failed: ${msg}`
23401
- }
23402
- };
23403
- }
23404
- let lockedFailure;
23405
- try {
23406
- const outcome = await runRefreshLocked({
23407
- absolutePath,
23408
- refreshToken,
23409
- customAuthority: credentials.UIPATH_URL,
23410
- ensureTokenValidityMinutes,
23411
- loadEnvFile,
23412
- saveEnvFile,
23413
- refreshFn: refreshTokenFn,
23414
- resolveConfig
23415
- });
23416
- if (outcome.kind === "fail") {
23417
- lockedFailure = outcome.status;
23418
- } else {
23419
- accessToken = outcome.accessToken;
23420
- refreshToken = outcome.refreshToken;
23421
- expiration = outcome.expiration;
23422
- tokenRefresh = outcome.tokenRefresh;
23423
- if (outcome.persistenceWarning) {
23424
- persistenceWarning = outcome.persistenceWarning;
23425
- }
23426
- }
23427
- } finally {
23428
- try {
23429
- await release();
23430
- } catch {
23431
- lockReleaseFailed = true;
23432
- }
23433
- }
23434
- if (lockedFailure) {
23435
- const globalHint = await tryGlobalCredsHint();
23436
- const base = globalHint ? {
23437
- ...lockedFailure,
23438
- loginStatus: "Expired",
23439
- hint: globalHint
23440
- } : lockedFailure;
23441
- return lockReleaseFailed ? { ...base, lockReleaseFailed: true } : base;
23442
- }
23443
- }
23444
- const result = {
23445
- loginStatus: expiration && expiration <= new Date ? "Expired" : "Logged in",
23446
- accessToken,
23447
- refreshToken,
23448
- baseUrl: credentials.UIPATH_URL,
23449
- organizationName: credentials.UIPATH_ORGANIZATION_NAME,
23450
- organizationId: credentials.UIPATH_ORGANIZATION_ID,
23451
- tenantName: credentials.UIPATH_TENANT_NAME,
23452
- tenantId: credentials.UIPATH_TENANT_ID,
23453
- expiration,
23454
- source: "file" /* File */,
23455
- ...persistenceWarning ? { hint: persistenceWarning, persistenceFailed: true } : {},
23456
- ...lockReleaseFailed ? { lockReleaseFailed: true } : {},
23457
- ...tokenRefresh ? { tokenRefresh } : {}
23458
- };
23459
- if (result.loginStatus === "Expired") {
23460
- const globalHint = await tryGlobalCredsHint();
23461
- if (globalHint) {
23462
- result.hint = globalHint;
23463
- }
23464
- }
23465
- return result;
23466
- };
23467
- var isFileNotFoundError = (error) => {
23468
- if (!(error instanceof Object))
23469
- return false;
23470
- return error.code === "ENOENT";
23471
- };
23472
- var getLoginStatusAsync = async (options = {}) => {
23473
- return getLoginStatusWithDeps(options);
23474
- };
23700
+ function normalizeTokenRefreshFailure() {
23701
+ return "stored refresh token is invalid or expired";
23702
+ }
23703
+ function normalizeTokenRefreshUnavailableFailure() {
23704
+ return "token refresh failed before authentication completed";
23705
+ }
23706
+ function errorMessage(error) {
23707
+ return error instanceof Error ? error.message : String(error);
23708
+ }
23475
23709
 
23476
23710
  // ../auth/src/authContext.ts
23477
23711
  var getAuthContext = async (options = {}) => {
@@ -23506,6 +23740,14 @@ var getAuthContext = async (options = {}) => {
23506
23740
  };
23507
23741
  // ../auth/src/interactive.ts
23508
23742
  init_src();
23743
+
23744
+ // ../auth/src/selectTenant.ts
23745
+ var TENANT_SELECTION_REQUIRED_CODE = "TENANT_SELECTION_REQUIRED";
23746
+ var INVALID_TENANT_CODE = "INVALID_TENANT";
23747
+ var TENANT_SELECTION_CODES = new Set([
23748
+ TENANT_SELECTION_REQUIRED_CODE,
23749
+ INVALID_TENANT_CODE
23750
+ ]);
23509
23751
  // ../auth/src/logout.ts
23510
23752
  init_src();
23511
23753
 
@@ -24042,3 +24284,5 @@ export {
24042
24284
  AgentAppearanceFromJSONTyped,
24043
24285
  AgentAppearanceFromJSON
24044
24286
  };
24287
+
24288
+ //# debugId=DDC3689ECCE6BAF664756E2164756E21
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@uipath/agent-sdk",
3
3
  "license": "MIT",
4
- "version": "1.196.0",
4
+ "version": "1.197.0-preview.59",
5
5
  "description": "SDK for the UiPath Agent Runtime API — evaluation execution and debug sessions.",
6
6
  "repository": {
7
7
  "type": "git",
@@ -29,5 +29,5 @@
29
29
  "files": [
30
30
  "dist"
31
31
  ],
32
- "gitHead": "94d71f9c52214980a1f0ae62b3f5372095788553"
32
+ "gitHead": "df0e2b8140cced13f463b487214927c82bc0f85b"
33
33
  }