@uipath/audit-tool 1.1.0 → 1.2.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.
Files changed (3) hide show
  1. package/dist/index.js +648 -152
  2. package/dist/tool.js +648 -152
  3. package/package.json +28 -37
package/dist/index.js CHANGED
@@ -2800,6 +2800,7 @@ var init_open = __esm(() => {
2800
2800
  });
2801
2801
 
2802
2802
  // ../../filesystem/src/node.ts
2803
+ import { randomUUID } from "node:crypto";
2803
2804
  import { existsSync } from "node:fs";
2804
2805
  import * as fs6 from "node:fs/promises";
2805
2806
  import * as os2 from "node:os";
@@ -2881,6 +2882,90 @@ class NodeFileSystem {
2881
2882
  async mkdir(dirPath) {
2882
2883
  await fs6.mkdir(dirPath, { recursive: true });
2883
2884
  }
2885
+ async acquireLock(lockPath) {
2886
+ const canonicalPath = await this.canonicalizeLockTarget(lockPath);
2887
+ const lockFile = `${canonicalPath}.lock`;
2888
+ const ownerId = randomUUID();
2889
+ const start = Date.now();
2890
+ while (true) {
2891
+ try {
2892
+ await fs6.writeFile(lockFile, ownerId, { flag: "wx" });
2893
+ return this.createLockRelease(lockFile, ownerId);
2894
+ } catch (error) {
2895
+ if (!this.hasErrnoCode(error, "EEXIST")) {
2896
+ throw error;
2897
+ }
2898
+ const stats = await fs6.stat(lockFile).catch(() => null);
2899
+ if (stats && Date.now() - stats.mtimeMs > LOCK_STALE_MS) {
2900
+ const reclaimed = await fs6.rm(lockFile, { force: true }).then(() => true).catch(() => false);
2901
+ if (reclaimed)
2902
+ continue;
2903
+ }
2904
+ if (Date.now() - start > LOCK_MAX_WAIT_MS) {
2905
+ throw new Error(`ELOCKED: timed out waiting for lock on ${canonicalPath}`);
2906
+ }
2907
+ await new Promise((resolve2) => setTimeout(resolve2, LOCK_RETRY_MIN_MS + Math.random() * LOCK_RETRY_JITTER_MS));
2908
+ }
2909
+ }
2910
+ }
2911
+ async canonicalizeLockTarget(lockPath) {
2912
+ const absolute = path2.resolve(lockPath);
2913
+ const fullReal = await fs6.realpath(absolute).catch(() => null);
2914
+ if (fullReal)
2915
+ return fullReal;
2916
+ const parent = path2.dirname(absolute);
2917
+ const base = path2.basename(absolute);
2918
+ const canonicalParent = await fs6.realpath(parent).catch(() => parent);
2919
+ return path2.join(canonicalParent, base);
2920
+ }
2921
+ createLockRelease(lockFile, ownerId) {
2922
+ const heartbeatStart = Date.now();
2923
+ let heartbeatTimer;
2924
+ let stopped = false;
2925
+ const stopHeartbeat = () => {
2926
+ stopped = true;
2927
+ if (heartbeatTimer)
2928
+ clearTimeout(heartbeatTimer);
2929
+ };
2930
+ const scheduleNextHeartbeat = () => {
2931
+ if (stopped)
2932
+ return;
2933
+ if (Date.now() - heartbeatStart >= LOCK_MAX_HOLD_MS) {
2934
+ stopped = true;
2935
+ return;
2936
+ }
2937
+ heartbeatTimer = setTimeout(() => {
2938
+ runHeartbeat();
2939
+ }, LOCK_HEARTBEAT_MS);
2940
+ heartbeatTimer.unref?.();
2941
+ };
2942
+ const runHeartbeat = async () => {
2943
+ if (stopped)
2944
+ return;
2945
+ const current = await fs6.readFile(lockFile, "utf-8").catch(() => null);
2946
+ if (stopped)
2947
+ return;
2948
+ if (current !== ownerId) {
2949
+ stopped = true;
2950
+ return;
2951
+ }
2952
+ const now = Date.now() / 1000;
2953
+ await fs6.utimes(lockFile, now, now).catch(() => {});
2954
+ scheduleNextHeartbeat();
2955
+ };
2956
+ scheduleNextHeartbeat();
2957
+ let released = false;
2958
+ return async () => {
2959
+ if (released)
2960
+ return;
2961
+ released = true;
2962
+ stopHeartbeat();
2963
+ const current = await fs6.readFile(lockFile, "utf-8").catch(() => null);
2964
+ if (current === ownerId) {
2965
+ await fs6.rm(lockFile, { force: true });
2966
+ }
2967
+ };
2968
+ }
2884
2969
  async rm(filePath) {
2885
2970
  await fs6.rm(filePath, { recursive: true, force: true });
2886
2971
  }
@@ -2926,9 +3011,13 @@ class NodeFileSystem {
2926
3011
  }
2927
3012
  }
2928
3013
  isEnoent(error) {
2929
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
3014
+ return this.hasErrnoCode(error, "ENOENT");
3015
+ }
3016
+ hasErrnoCode(error, code) {
3017
+ return typeof error === "object" && error !== null && "code" in error && error.code === code;
2930
3018
  }
2931
3019
  }
3020
+ var LOCK_HEARTBEAT_MS = 5000, LOCK_STALE_MS = 15000, LOCK_MAX_WAIT_MS = 20000, LOCK_MAX_HOLD_MS = 60000, LOCK_RETRY_MIN_MS = 100, LOCK_RETRY_JITTER_MS = 200;
2932
3021
  var init_node = __esm(() => {
2933
3022
  init_open();
2934
3023
  });
@@ -2942,7 +3031,7 @@ var init_src = __esm(() => {
2942
3031
 
2943
3032
  // ../../../node_modules/@uipath/coreipc/index.js
2944
3033
  var require_coreipc = __commonJS((exports, module) => {
2945
- var __dirname = "/Users/alexandru.oltean/github/cli/node_modules/@uipath/coreipc";
3034
+ var __dirname = "/home/runner/work/cli/cli/node_modules/@uipath/coreipc";
2946
3035
  /*! For license information please see index.js.LICENSE.txt */
2947
3036
  (function(e, t) {
2948
3037
  typeof exports == "object" && typeof module == "object" ? module.exports = t() : typeof define == "function" && define.amd ? define([], t) : typeof exports == "object" ? exports.ipc = t() : e.ipc = t();
@@ -21134,6 +21223,10 @@ var require_dist = __commonJS((exports) => {
21134
21223
  exports.RobotProxyConstructor = RobotProxyConstructor;
21135
21224
  __exportStar(require_agent(), exports);
21136
21225
  });
21226
+ // ../../auth/src/server.ts
21227
+ var init_server = __esm(() => {
21228
+ init_constants();
21229
+ });
21137
21230
 
21138
21231
  // ../../../node_modules/adm-zip/util/constants.js
21139
21232
  var require_constants = __commonJS((exports, module) => {
@@ -23451,7 +23544,8 @@ var {
23451
23544
  // package.json
23452
23545
  var package_default = {
23453
23546
  name: "@uipath/audit-tool",
23454
- version: "1.1.0",
23547
+ license: "MIT",
23548
+ version: "1.2.0",
23455
23549
  description: "CLI plugin for the UiPath Audit Service — query event sources, paginate events, and export ZIPs from the long-term store.",
23456
23550
  private: false,
23457
23551
  repository: {
@@ -23492,6 +23586,136 @@ var package_default = {
23492
23586
  }
23493
23587
  };
23494
23588
 
23589
+ // ../../common/src/singleton.ts
23590
+ var PREFIX = "@uipath/common/";
23591
+ var _g = globalThis;
23592
+ function singleton(ctorOrName) {
23593
+ const name = typeof ctorOrName === "string" ? ctorOrName : ctorOrName.name;
23594
+ const key = Symbol.for(PREFIX + name);
23595
+ return {
23596
+ get(fallback) {
23597
+ return _g[key] ?? fallback;
23598
+ },
23599
+ set(value) {
23600
+ _g[key] = value;
23601
+ },
23602
+ clear() {
23603
+ delete _g[key];
23604
+ },
23605
+ getOrInit(factory, guard) {
23606
+ const existing = _g[key];
23607
+ if (existing != null && typeof existing === "object") {
23608
+ if (!guard || guard(existing)) {
23609
+ return existing;
23610
+ }
23611
+ }
23612
+ const instance = factory();
23613
+ _g[key] = instance;
23614
+ return instance;
23615
+ }
23616
+ };
23617
+ }
23618
+
23619
+ // ../../common/src/sdk-user-agent.ts
23620
+ var USER_AGENT_HEADER = "User-Agent";
23621
+ var sdkUserAgentHostToken = singleton("SdkUserAgentHostToken");
23622
+ function userAgentPatchKey(userAgent) {
23623
+ return Symbol.for(`@uipath/common/sdk-user-agent/${userAgent}`);
23624
+ }
23625
+ function splitUserAgentTokens(value) {
23626
+ return value?.trim().split(/\s+/).filter(Boolean) ?? [];
23627
+ }
23628
+ function appendUserAgentToken(value, userAgent) {
23629
+ const tokens = splitUserAgentTokens(value);
23630
+ const seen = new Set(tokens);
23631
+ for (const token of splitUserAgentTokens(userAgent)) {
23632
+ if (!seen.has(token)) {
23633
+ tokens.push(token);
23634
+ seen.add(token);
23635
+ }
23636
+ }
23637
+ return tokens.join(" ");
23638
+ }
23639
+ function getEffectiveUserAgent(userAgent) {
23640
+ return appendUserAgentToken(sdkUserAgentHostToken.get(), userAgent);
23641
+ }
23642
+ function isHeadersLike(headers) {
23643
+ return typeof headers === "object" && headers !== null && "get" in headers && typeof headers.get === "function" && "set" in headers && typeof headers.set === "function";
23644
+ }
23645
+ function getSdkUserAgentToken(pkg) {
23646
+ const packageName = pkg.name.replace(/^@uipath\//, "");
23647
+ return getEffectiveUserAgent(`${packageName}/${pkg.version}`);
23648
+ }
23649
+ function addSdkUserAgentHeader(headers, userAgent) {
23650
+ const result = { ...headers ?? {} };
23651
+ const effectiveUserAgent = getEffectiveUserAgent(userAgent);
23652
+ const headerName = Object.keys(result).find((key) => key.toLowerCase() === USER_AGENT_HEADER.toLowerCase());
23653
+ if (headerName) {
23654
+ result[headerName] = appendUserAgentToken(result[headerName], effectiveUserAgent);
23655
+ } else {
23656
+ result[USER_AGENT_HEADER] = effectiveUserAgent;
23657
+ }
23658
+ return result;
23659
+ }
23660
+ function withSdkUserAgentHeader(headers, userAgent) {
23661
+ const effectiveUserAgent = getEffectiveUserAgent(userAgent);
23662
+ if (isHeadersLike(headers)) {
23663
+ headers.set(USER_AGENT_HEADER, appendUserAgentToken(headers.get(USER_AGENT_HEADER), effectiveUserAgent));
23664
+ return headers;
23665
+ }
23666
+ if (Array.isArray(headers)) {
23667
+ const result = headers.map((entry) => {
23668
+ const [key, value] = entry;
23669
+ return [key, value];
23670
+ });
23671
+ const headerIndex = result.findIndex(([key]) => key.toLowerCase() === USER_AGENT_HEADER.toLowerCase());
23672
+ if (headerIndex >= 0) {
23673
+ const [key, value] = result[headerIndex];
23674
+ result[headerIndex] = [
23675
+ key,
23676
+ appendUserAgentToken(value, effectiveUserAgent)
23677
+ ];
23678
+ } else {
23679
+ result.push([USER_AGENT_HEADER, effectiveUserAgent]);
23680
+ }
23681
+ return result;
23682
+ }
23683
+ return addSdkUserAgentHeader(typeof headers === "object" && headers !== null ? { ...headers } : {}, effectiveUserAgent);
23684
+ }
23685
+ function withUserAgentInitOverride(initOverrides, userAgent) {
23686
+ return async (requestContext) => {
23687
+ const initWithUserAgent = {
23688
+ ...requestContext.init,
23689
+ headers: withSdkUserAgentHeader(requestContext.init.headers, userAgent)
23690
+ };
23691
+ const override = typeof initOverrides === "function" ? await initOverrides({
23692
+ ...requestContext,
23693
+ init: initWithUserAgent
23694
+ }) : initOverrides;
23695
+ return {
23696
+ ...override ?? {},
23697
+ headers: withSdkUserAgentHeader(override?.headers ?? initWithUserAgent.headers, userAgent)
23698
+ };
23699
+ };
23700
+ }
23701
+ function installSdkUserAgentHeader(BaseApiClass, userAgent) {
23702
+ const prototype = BaseApiClass.prototype;
23703
+ const patchKey = userAgentPatchKey(userAgent);
23704
+ if (prototype[patchKey]) {
23705
+ return;
23706
+ }
23707
+ if (typeof prototype.request !== "function") {
23708
+ throw new Error("Generated BaseAPI request function not found.");
23709
+ }
23710
+ const originalRequest = prototype.request;
23711
+ prototype.request = function requestWithUserAgent(context, initOverrides) {
23712
+ return originalRequest.call(this, context, withUserAgentInitOverride(initOverrides, userAgent));
23713
+ };
23714
+ Object.defineProperty(prototype, patchKey, {
23715
+ value: true
23716
+ });
23717
+ }
23718
+
23495
23719
  // ../audit-sdk/generated/src/runtime.ts
23496
23720
  var BASE_PATH = "https://localhost:7008".replace(/\/+$/, "");
23497
23721
 
@@ -23740,6 +23964,49 @@ class VoidApiResponse {
23740
23964
  return;
23741
23965
  }
23742
23966
  }
23967
+ // ../audit-sdk/package.json
23968
+ var package_default2 = {
23969
+ name: "@uipath/audit-sdk",
23970
+ license: "MIT",
23971
+ version: "1.2.0",
23972
+ description: "SDK for the UiPath Audit Service — query audit event sources, list events, and download long-term-store exports.",
23973
+ repository: {
23974
+ type: "git",
23975
+ url: "https://github.com/UiPath/cli.git",
23976
+ directory: "packages/admin/audit-sdk"
23977
+ },
23978
+ publishConfig: {
23979
+ registry: "https://npm.pkg.github.com/@uipath"
23980
+ },
23981
+ keywords: ["uipath", "audit", "sdk"],
23982
+ type: "module",
23983
+ main: "./dist/index.js",
23984
+ types: "./dist/src/index.d.ts",
23985
+ exports: {
23986
+ ".": {
23987
+ types: "./dist/src/index.d.ts",
23988
+ default: "./dist/index.js"
23989
+ }
23990
+ },
23991
+ files: ["dist"],
23992
+ private: true,
23993
+ scripts: {
23994
+ build: "bun build ./src/index.ts --outdir dist --format esm --target node && tsc -p tsconfig.build.json --noCheck",
23995
+ generate: "bun run src/scripts/generate-sdk.ts",
23996
+ lint: "biome check ."
23997
+ },
23998
+ devDependencies: {
23999
+ "@openapitools/openapi-generator-cli": "^2.31.1",
24000
+ "@types/node": "^25.5.0",
24001
+ "@uipath/auth": "workspace:*",
24002
+ "@uipath/common": "workspace:*",
24003
+ typescript: "^6.0.2"
24004
+ }
24005
+ };
24006
+
24007
+ // ../audit-sdk/src/user-agent.ts
24008
+ var SDK_USER_AGENT = getSdkUserAgentToken(package_default2);
24009
+ installSdkUserAgentHeader(BaseAPI, SDK_USER_AGENT);
23743
24010
 
23744
24011
  // ../audit-sdk/generated/src/models/AuditEventStatus.ts
23745
24012
  var AuditEventStatus = {
@@ -24000,32 +24267,7 @@ class InvalidBaseUrlError extends Error {
24000
24267
  this.name = "InvalidBaseUrlError";
24001
24268
  }
24002
24269
  }
24003
- var DEFAULT_SCOPES = [
24004
- "offline_access",
24005
- "ProcessMining",
24006
- "OrchestratorApiUserAccess",
24007
- "StudioWebBackend",
24008
- "IdentityServerApi",
24009
- "ConnectionService",
24010
- "DataService",
24011
- "DataServiceApiUserAccess",
24012
- "DocumentUnderstanding",
24013
- "EnterpriseContextService",
24014
- "Directory",
24015
- "JamJamApi",
24016
- "LLMGateway",
24017
- "LLMOps",
24018
- "OMS",
24019
- "RCS.FolderAuthorization",
24020
- "RCS.TagsManagement",
24021
- "TestmanagerApiUserAccess",
24022
- "AutomationSolutions",
24023
- "StudioWebTypeCacheService",
24024
- "Docs.GPT.Search",
24025
- "Insights",
24026
- "ReferenceToken",
24027
- "Audit.Read"
24028
- ];
24270
+ var DEFAULT_SCOPES = ["openid", "profile", "offline_access"];
24029
24271
  var normalizeAndValidateBaseUrl = (rawUrl) => {
24030
24272
  let baseUrl = rawUrl;
24031
24273
  if (baseUrl.endsWith("/identity_/")) {
@@ -24075,7 +24317,8 @@ var resolveConfigAsync = async ({
24075
24317
  if (!clientSecret && fileAuth.clientSecret) {
24076
24318
  clientSecret = fileAuth.clientSecret;
24077
24319
  }
24078
- const scopes = customScopes && customScopes.length > 0 ? customScopes : fileAuth.scopes && fileAuth.scopes.length > 0 ? fileAuth.scopes : DEFAULT_SCOPES;
24320
+ const isExternalAppAuth = clientId !== DEFAULT_CLIENT_ID && Boolean(clientSecret);
24321
+ const scopes = customScopes && customScopes.length > 0 ? customScopes : fileAuth.scopes && fileAuth.scopes.length > 0 ? fileAuth.scopes : isExternalAppAuth ? [] : DEFAULT_SCOPES;
24079
24322
  return {
24080
24323
  clientId,
24081
24324
  clientSecret,
@@ -24575,6 +24818,129 @@ function normalizeTokenRefreshFailure() {
24575
24818
  function normalizeTokenRefreshUnavailableFailure() {
24576
24819
  return "token refresh failed before authentication completed";
24577
24820
  }
24821
+ function errorMessage(error) {
24822
+ return error instanceof Error ? error.message : String(error);
24823
+ }
24824
+ function computeExpirationThreshold(ensureTokenValidityMinutes) {
24825
+ return new Date(Date.now() + (ensureTokenValidityMinutes ?? 0) * 60 * 1000);
24826
+ }
24827
+ async function runRefreshLocked(inputs) {
24828
+ const {
24829
+ absolutePath,
24830
+ refreshToken: callerRefreshToken,
24831
+ customAuthority,
24832
+ ensureTokenValidityMinutes,
24833
+ loadEnvFile,
24834
+ saveEnvFile,
24835
+ refreshFn,
24836
+ resolveConfig
24837
+ } = inputs;
24838
+ const expirationThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
24839
+ let fresh;
24840
+ try {
24841
+ fresh = await loadEnvFile({ envPath: absolutePath });
24842
+ } catch (error) {
24843
+ return {
24844
+ kind: "fail",
24845
+ status: {
24846
+ loginStatus: "Refresh Failed",
24847
+ hint: "Could not read the auth file while refreshing. Retry, or run 'uip login' to re-authenticate.",
24848
+ tokenRefresh: {
24849
+ attempted: false,
24850
+ success: false,
24851
+ errorMessage: `auth file read failed: ${errorMessage(error)}`
24852
+ }
24853
+ }
24854
+ };
24855
+ }
24856
+ const freshAccess = fresh.UIPATH_ACCESS_TOKEN;
24857
+ const freshExp = freshAccess ? getTokenExpiration(freshAccess) : undefined;
24858
+ if (freshAccess && freshExp && freshExp > expirationThreshold) {
24859
+ return {
24860
+ kind: "ok",
24861
+ accessToken: freshAccess,
24862
+ refreshToken: fresh.UIPATH_REFRESH_TOKEN ?? callerRefreshToken,
24863
+ expiration: freshExp,
24864
+ tokenRefresh: { attempted: false, success: true }
24865
+ };
24866
+ }
24867
+ const tokenForIdP = fresh.UIPATH_REFRESH_TOKEN ?? callerRefreshToken;
24868
+ let refreshedAccess;
24869
+ let refreshedRefresh;
24870
+ try {
24871
+ const config = await resolveConfig({ customAuthority });
24872
+ const refreshed = await refreshFn({
24873
+ refreshToken: tokenForIdP,
24874
+ tokenEndpoint: config.tokenEndpoint,
24875
+ clientId: config.clientId,
24876
+ expectedAuthority: customAuthority
24877
+ });
24878
+ refreshedAccess = refreshed.accessToken;
24879
+ refreshedRefresh = refreshed.refreshToken;
24880
+ } catch (error) {
24881
+ const isOAuthFailure = isTokenRefreshOAuthFailure(error);
24882
+ 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.";
24883
+ const message = isOAuthFailure ? normalizeTokenRefreshFailure() : normalizeTokenRefreshUnavailableFailure();
24884
+ return {
24885
+ kind: "fail",
24886
+ status: {
24887
+ loginStatus: "Refresh Failed",
24888
+ hint,
24889
+ tokenRefresh: {
24890
+ attempted: true,
24891
+ success: false,
24892
+ errorMessage: message
24893
+ }
24894
+ }
24895
+ };
24896
+ }
24897
+ const refreshedExp = getTokenExpiration(refreshedAccess);
24898
+ if (!refreshedExp || refreshedExp <= new Date) {
24899
+ return {
24900
+ kind: "fail",
24901
+ status: {
24902
+ loginStatus: "Refresh Failed",
24903
+ hint: "The identity server returned an unusable token. Run 'uip login' to re-authenticate.",
24904
+ tokenRefresh: {
24905
+ attempted: true,
24906
+ success: false,
24907
+ errorMessage: "refreshed token has no valid expiration claim"
24908
+ }
24909
+ }
24910
+ };
24911
+ }
24912
+ try {
24913
+ await saveEnvFile({
24914
+ envPath: absolutePath,
24915
+ data: {
24916
+ UIPATH_ACCESS_TOKEN: refreshedAccess,
24917
+ UIPATH_REFRESH_TOKEN: refreshedRefresh
24918
+ },
24919
+ merge: true
24920
+ });
24921
+ return {
24922
+ kind: "ok",
24923
+ accessToken: refreshedAccess,
24924
+ refreshToken: refreshedRefresh,
24925
+ expiration: refreshedExp,
24926
+ tokenRefresh: { attempted: true, success: true }
24927
+ };
24928
+ } catch (error) {
24929
+ const msg = errorMessage(error);
24930
+ return {
24931
+ kind: "ok",
24932
+ accessToken: refreshedAccess,
24933
+ refreshToken: refreshedRefresh,
24934
+ expiration: refreshedExp,
24935
+ persistenceWarning: `Access token refreshed in memory but could not be written to ${absolutePath}: ${msg}. The next CLI invocation will fail until the file can be updated — run 'uip login' to re-authenticate.`,
24936
+ tokenRefresh: {
24937
+ attempted: true,
24938
+ success: true,
24939
+ errorMessage: `persistence failed: ${msg}`
24940
+ }
24941
+ };
24942
+ }
24943
+ }
24578
24944
  var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
24579
24945
  const {
24580
24946
  resolveEnvFilePath = resolveEnvFilePathAsync,
@@ -24649,73 +25015,103 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
24649
25015
  let refreshToken = credentials.UIPATH_REFRESH_TOKEN;
24650
25016
  let expiration = getTokenExpiration(accessToken);
24651
25017
  let persistenceWarning;
25018
+ let lockReleaseFailed = false;
24652
25019
  let tokenRefresh;
24653
- const expirationThreshold = new Date(Date.now() + (ensureTokenValidityMinutes ?? 0) * 60 * 1000);
24654
- if (expiration && expiration <= expirationThreshold && refreshToken) {
24655
- let refreshedAccess;
24656
- let refreshedRefresh;
25020
+ const outerThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
25021
+ const tryGlobalCredsHint = async () => {
25022
+ const fs7 = getFs();
25023
+ const globalPath = fs7.path.join(fs7.env.homedir(), envFilePath);
25024
+ if (absolutePath === globalPath)
25025
+ return;
25026
+ if (!await fs7.exists(globalPath))
25027
+ return;
24657
25028
  try {
24658
- const config = await resolveConfig({
24659
- customAuthority: credentials.UIPATH_URL
24660
- });
24661
- const refreshed = await refreshTokenFn({
24662
- refreshToken,
24663
- tokenEndpoint: config.tokenEndpoint,
24664
- clientId: config.clientId,
24665
- expectedAuthority: credentials.UIPATH_URL
24666
- });
24667
- refreshedAccess = refreshed.accessToken;
24668
- refreshedRefresh = refreshed.refreshToken;
24669
- } catch (error) {
24670
- const isOAuthFailure = isTokenRefreshOAuthFailure(error);
24671
- 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.";
24672
- const errorMessage = isOAuthFailure ? normalizeTokenRefreshFailure() : normalizeTokenRefreshUnavailableFailure();
24673
- return {
24674
- loginStatus: "Refresh Failed",
24675
- hint,
24676
- tokenRefresh: {
24677
- attempted: true,
24678
- success: false,
24679
- errorMessage
24680
- }
24681
- };
25029
+ const globalCreds = await loadEnvFile({ envPath: globalPath });
25030
+ if (!globalCreds.UIPATH_ACCESS_TOKEN)
25031
+ return;
25032
+ const globalExp = getTokenExpiration(globalCreds.UIPATH_ACCESS_TOKEN);
25033
+ if (globalExp && globalExp <= new Date)
25034
+ return;
25035
+ 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.`;
25036
+ } catch {
25037
+ return;
24682
25038
  }
24683
- const refreshedExp = getTokenExpiration(refreshedAccess);
24684
- if (!refreshedExp || refreshedExp <= new Date) {
25039
+ };
25040
+ if (expiration && expiration <= outerThreshold && refreshToken) {
25041
+ let release;
25042
+ try {
25043
+ release = await getFs().acquireLock(absolutePath);
25044
+ } catch (error) {
25045
+ const msg = errorMessage(error);
25046
+ const globalHint = await tryGlobalCredsHint();
25047
+ if (globalHint) {
25048
+ return {
25049
+ loginStatus: "Expired",
25050
+ accessToken,
25051
+ refreshToken,
25052
+ baseUrl: credentials.UIPATH_URL,
25053
+ organizationName: credentials.UIPATH_ORGANIZATION_NAME,
25054
+ organizationId: credentials.UIPATH_ORGANIZATION_ID,
25055
+ tenantName: credentials.UIPATH_TENANT_NAME,
25056
+ tenantId: credentials.UIPATH_TENANT_ID,
25057
+ expiration,
25058
+ source: "file" /* File */,
25059
+ hint: globalHint,
25060
+ tokenRefresh: {
25061
+ attempted: false,
25062
+ success: false,
25063
+ errorMessage: `lock acquisition failed: ${msg}`
25064
+ }
25065
+ };
25066
+ }
24685
25067
  return {
24686
25068
  loginStatus: "Refresh Failed",
24687
- hint: "The identity server returned an unusable token. Run 'uip login' to re-authenticate.",
25069
+ 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.",
24688
25070
  tokenRefresh: {
24689
- attempted: true,
25071
+ attempted: false,
24690
25072
  success: false,
24691
- errorMessage: "refreshed token has no valid expiration claim"
25073
+ errorMessage: `lock acquisition failed: ${msg}`
24692
25074
  }
24693
25075
  };
24694
25076
  }
24695
- accessToken = refreshedAccess;
24696
- refreshToken = refreshedRefresh;
24697
- expiration = refreshedExp;
25077
+ let lockedFailure;
24698
25078
  try {
24699
- await saveEnvFile({
24700
- envPath: absolutePath,
24701
- data: {
24702
- UIPATH_ACCESS_TOKEN: accessToken,
24703
- UIPATH_REFRESH_TOKEN: refreshToken
24704
- },
24705
- merge: true
25079
+ const outcome = await runRefreshLocked({
25080
+ absolutePath,
25081
+ refreshToken,
25082
+ customAuthority: credentials.UIPATH_URL,
25083
+ ensureTokenValidityMinutes,
25084
+ loadEnvFile,
25085
+ saveEnvFile,
25086
+ refreshFn: refreshTokenFn,
25087
+ resolveConfig
24706
25088
  });
24707
- tokenRefresh = {
24708
- attempted: true,
24709
- success: true
24710
- };
24711
- } catch (error) {
24712
- const msg = error instanceof Error ? error.message : String(error);
24713
- persistenceWarning = `Access token refreshed in memory but could not be written to ${absolutePath}: ${msg}. The next CLI invocation will fail until the file can be updated — run 'uip login' to re-authenticate.`;
24714
- tokenRefresh = {
24715
- attempted: true,
24716
- success: true,
24717
- errorMessage: `persistence failed: ${msg}`
24718
- };
25089
+ if (outcome.kind === "fail") {
25090
+ lockedFailure = outcome.status;
25091
+ } else {
25092
+ accessToken = outcome.accessToken;
25093
+ refreshToken = outcome.refreshToken;
25094
+ expiration = outcome.expiration;
25095
+ tokenRefresh = outcome.tokenRefresh;
25096
+ if (outcome.persistenceWarning) {
25097
+ persistenceWarning = outcome.persistenceWarning;
25098
+ }
25099
+ }
25100
+ } finally {
25101
+ try {
25102
+ await release();
25103
+ } catch {
25104
+ lockReleaseFailed = true;
25105
+ }
25106
+ }
25107
+ if (lockedFailure) {
25108
+ const globalHint = await tryGlobalCredsHint();
25109
+ const base = globalHint ? {
25110
+ ...lockedFailure,
25111
+ loginStatus: "Expired",
25112
+ hint: globalHint
25113
+ } : lockedFailure;
25114
+ return lockReleaseFailed ? { ...base, lockReleaseFailed: true } : base;
24719
25115
  }
24720
25116
  }
24721
25117
  const result = {
@@ -24730,23 +25126,13 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
24730
25126
  expiration,
24731
25127
  source: "file" /* File */,
24732
25128
  ...persistenceWarning ? { hint: persistenceWarning, persistenceFailed: true } : {},
25129
+ ...lockReleaseFailed ? { lockReleaseFailed: true } : {},
24733
25130
  ...tokenRefresh ? { tokenRefresh } : {}
24734
25131
  };
24735
25132
  if (result.loginStatus === "Expired") {
24736
- const fs7 = getFs();
24737
- const globalPath = fs7.path.join(fs7.env.homedir(), envFilePath);
24738
- if (absolutePath !== globalPath && await fs7.exists(globalPath)) {
24739
- try {
24740
- const globalCreds = await loadEnvFile({
24741
- envPath: globalPath
24742
- });
24743
- if (globalCreds.UIPATH_ACCESS_TOKEN) {
24744
- const globalExp = getTokenExpiration(globalCreds.UIPATH_ACCESS_TOKEN);
24745
- if (!globalExp || globalExp > new Date) {
24746
- result.hint = `Local credentials file at ${absolutePath} has expired credentials. Valid credentials exist in ${globalPath}. Remove the local file or run 'uip login' to re-authenticate.`;
24747
- }
24748
- }
24749
- } catch {}
25133
+ const globalHint = await tryGlobalCredsHint();
25134
+ if (globalHint) {
25135
+ result.hint = globalHint;
24750
25136
  }
24751
25137
  }
24752
25138
  return result;
@@ -24763,6 +25149,10 @@ var getLoginStatusAsync = async (options = {}) => {
24763
25149
  init_src();
24764
25150
  // ../../auth/src/logout.ts
24765
25151
  init_src();
25152
+
25153
+ // ../../auth/src/index.ts
25154
+ init_server();
25155
+
24766
25156
  // ../audit-sdk/src/client-factory.ts
24767
25157
  async function createAuditConfig(options) {
24768
25158
  const status = await getLoginStatusAsync({
@@ -24789,7 +25179,8 @@ async function createAuditConfig(options) {
24789
25179
  const bearerToken = options.s2sToken ?? status.accessToken;
24790
25180
  return new Configuration({
24791
25181
  basePath,
24792
- apiKey: () => `Bearer ${bearerToken}`
25182
+ apiKey: () => `Bearer ${bearerToken}`,
25183
+ headers: addSdkUserAgentHeader(undefined, SDK_USER_AGENT)
24793
25184
  });
24794
25185
  }
24795
25186
  async function createApiClient(ApiClass, options) {
@@ -24933,10 +25324,15 @@ async function extractErrorDetails(error, options) {
24933
25324
  }
24934
25325
  if (parsedBody?.errorCode && typeof parsedBody.errorCode === "string") {
24935
25326
  context.errorCode = parsedBody.errorCode;
25327
+ } else if (parsedBody?.code && typeof parsedBody.code === "string") {
25328
+ context.errorCode = parsedBody.code;
24936
25329
  }
24937
25330
  if (parsedBody?.requestId && typeof parsedBody.requestId === "string") {
24938
25331
  context.requestId = parsedBody.requestId;
24939
25332
  }
25333
+ if (parsedBody?.traceId && typeof parsedBody.traceId === "string") {
25334
+ context.traceId = parsedBody.traceId;
25335
+ }
24940
25336
  if (status === 429) {
24941
25337
  const resp = response;
24942
25338
  const headersObj = resp?.headers;
@@ -24956,7 +25352,35 @@ async function extractErrorDetails(error, options) {
24956
25352
  }
24957
25353
  }
24958
25354
  const hasContext = Object.keys(context).length > 0;
24959
- return { result, message, details, ...hasContext ? { context } : {} };
25355
+ let parsedErrors;
25356
+ if (parsedBody?.errors && typeof parsedBody.errors === "object") {
25357
+ const errors = {};
25358
+ for (const [field, raw] of Object.entries(parsedBody.errors)) {
25359
+ if (Array.isArray(raw)) {
25360
+ const messages = raw.map((entry) => {
25361
+ if (typeof entry === "string")
25362
+ return entry;
25363
+ if (entry && typeof entry === "object" && typeof entry.message === "string") {
25364
+ return entry.message;
25365
+ }
25366
+ return String(entry);
25367
+ }).filter(Boolean);
25368
+ if (messages.length > 0)
25369
+ errors[field] = messages;
25370
+ } else if (typeof raw === "string") {
25371
+ errors[field] = [raw];
25372
+ }
25373
+ }
25374
+ if (Object.keys(errors).length > 0)
25375
+ parsedErrors = errors;
25376
+ }
25377
+ return {
25378
+ result,
25379
+ message,
25380
+ details,
25381
+ ...hasContext ? { context } : {},
25382
+ ...parsedErrors ? { parsedErrors } : {}
25383
+ };
24960
25384
  }
24961
25385
  async function extractErrorMessage(error, options) {
24962
25386
  const { message } = await extractErrorDetails(error, options);
@@ -24968,36 +25392,6 @@ Command.prototype.examples = function(examples) {
24968
25392
  examplesByCommand.set(this, examples);
24969
25393
  return this;
24970
25394
  };
24971
- // ../../common/src/singleton.ts
24972
- var PREFIX = "@uipath/common/";
24973
- var _g = globalThis;
24974
- function singleton(ctorOrName) {
24975
- const name = typeof ctorOrName === "string" ? ctorOrName : ctorOrName.name;
24976
- const key = Symbol.for(PREFIX + name);
24977
- return {
24978
- get(fallback) {
24979
- return _g[key] ?? fallback;
24980
- },
24981
- set(value) {
24982
- _g[key] = value;
24983
- },
24984
- clear() {
24985
- delete _g[key];
24986
- },
24987
- getOrInit(factory, guard) {
24988
- const existing = _g[key];
24989
- if (existing != null && typeof existing === "object") {
24990
- if (!guard || guard(existing)) {
24991
- return existing;
24992
- }
24993
- }
24994
- const instance = factory();
24995
- _g[key] = instance;
24996
- return instance;
24997
- }
24998
- };
24999
- }
25000
-
25001
25395
  // ../../common/src/output-context.ts
25002
25396
  function createStorage() {
25003
25397
  const [error, mod] = catchError2(() => __require("node:async_hooks"));
@@ -30087,6 +30481,60 @@ function escapeNonAscii(jsonText) {
30087
30481
  function needsAsciiSafeJson(sink) {
30088
30482
  return process.platform === "win32" && !sink.capabilities.isInteractive;
30089
30483
  }
30484
+ function isPlainRecord(value) {
30485
+ if (value === null || typeof value !== "object")
30486
+ return false;
30487
+ const prototype = Object.getPrototypeOf(value);
30488
+ return prototype === Object.prototype || prototype === null;
30489
+ }
30490
+ function toLowerCamelCaseKey(key) {
30491
+ if (!key)
30492
+ return key;
30493
+ if (/[_\-\s]/.test(key)) {
30494
+ const [firstPart, ...restParts] = key.split(/[_\-\s]+/).filter(Boolean);
30495
+ if (!firstPart)
30496
+ return key;
30497
+ return [
30498
+ toLowerCamelCaseSimpleKey(firstPart),
30499
+ ...restParts.map((part) => {
30500
+ const normalized = toLowerCamelCaseSimpleKey(part);
30501
+ return normalized.charAt(0).toUpperCase() + normalized.slice(1);
30502
+ })
30503
+ ].join("");
30504
+ }
30505
+ return toLowerCamelCaseSimpleKey(key);
30506
+ }
30507
+ function toLowerCamelCaseSimpleKey(key) {
30508
+ if (/^[A-Z0-9]+$/.test(key))
30509
+ return key.toLowerCase();
30510
+ return key.replace(/^[A-Z]+(?=[A-Z][a-z]|\d|$)|^[A-Z]/, (match) => match.toLowerCase());
30511
+ }
30512
+ function toPascalCaseKey(key) {
30513
+ const lowerCamelKey = toLowerCamelCaseKey(key);
30514
+ return lowerCamelKey ? lowerCamelKey.charAt(0).toUpperCase() + lowerCamelKey.slice(1) : lowerCamelKey;
30515
+ }
30516
+ function toPascalCaseData(value) {
30517
+ if (Array.isArray(value))
30518
+ return value.map(toPascalCaseData);
30519
+ if (!isPlainRecord(value))
30520
+ return value;
30521
+ const result = {};
30522
+ for (const [key, nestedValue] of Object.entries(value)) {
30523
+ result[toPascalCaseKey(key)] = toPascalCaseData(nestedValue);
30524
+ }
30525
+ return result;
30526
+ }
30527
+ function normalizeDataKeys(data) {
30528
+ return toPascalCaseData(data);
30529
+ }
30530
+ function normalizeOutputKeys(data) {
30531
+ const result = {};
30532
+ for (const [key, value] of Object.entries(data)) {
30533
+ const pascalKey = toPascalCaseKey(key);
30534
+ result[pascalKey] = pascalKey === "Data" ? value : toPascalCaseData(value);
30535
+ }
30536
+ return result;
30537
+ }
30090
30538
  function printOutput(data, format = "json", logFn, asciiSafe = false) {
30091
30539
  if (!data) {
30092
30540
  logFn("Empty response object. No data to display.");
@@ -30149,7 +30597,7 @@ function wrapText(text, width) {
30149
30597
  function printTable(data, logFn, externalLogValue) {
30150
30598
  if (data.length === 0)
30151
30599
  return;
30152
- const keys = Object.keys(data[0]).filter((key) => key !== "Code" && key !== "Log");
30600
+ const keys = Object.keys(data[0]).filter((key) => !["code", "log"].includes(key.toLowerCase()));
30153
30601
  const maxWidths = keys.map((key) => Math.max(key.length, ...data.map((item) => cellToString(item[key]).length)));
30154
30602
  const header = keys.map((key, i2) => key.padEnd(maxWidths[i2])).join(" | ");
30155
30603
  logFn(header);
@@ -30164,7 +30612,7 @@ function printTable(data, logFn, externalLogValue) {
30164
30612
  }
30165
30613
  }
30166
30614
  function printVerticalTable(data, logFn = console.log, externalLogValue) {
30167
- const keys = Object.keys(data).filter((key) => key !== "Code" && key !== "Log");
30615
+ const keys = Object.keys(data).filter((key) => !["code", "log"].includes(key.toLowerCase()));
30168
30616
  if (keys.length === 0)
30169
30617
  return;
30170
30618
  const maxKeyWidth = Math.max(...keys.map((key) => key.length));
@@ -30180,7 +30628,7 @@ function printVerticalTable(data, logFn = console.log, externalLogValue) {
30180
30628
  function printResizableTable(data, logFn = console.log, externalLogValue) {
30181
30629
  if (data.length === 0)
30182
30630
  return;
30183
- const keys = Object.keys(data[0]).filter((key) => key !== "Code" && key !== "Log");
30631
+ const keys = Object.keys(data[0]).filter((key) => !["code", "log"].includes(key.toLowerCase()));
30184
30632
  if (keys.length === 0)
30185
30633
  return;
30186
30634
  if (!process.stdout.isTTY) {
@@ -30256,8 +30704,26 @@ function printResizableTable(data, logFn = console.log, externalLogValue) {
30256
30704
  function toYaml(data) {
30257
30705
  return dump(data);
30258
30706
  }
30707
+ class FilterEvaluationError extends Error {
30708
+ __brand = "FilterEvaluationError";
30709
+ filter;
30710
+ instructions;
30711
+ result = RESULTS.ValidationError;
30712
+ constructor(filter, cause) {
30713
+ const underlying = cause instanceof Error ? cause.message : String(cause);
30714
+ super(`Filter '${filter}' failed to evaluate: ${underlying}`);
30715
+ this.name = "FilterEvaluationError";
30716
+ this.filter = filter;
30717
+ this.instructions = `The --output-filter expression '${filter}' failed at evaluation time. ` + "Note that --output-filter operates on the 'Data' field of the envelope, not the full object. " + "For example, on a list result use 'length(@)' instead of 'Data | length(@)'.";
30718
+ }
30719
+ }
30259
30720
  function applyFilter(data, filter) {
30260
- const result = search(data, filter);
30721
+ let result;
30722
+ try {
30723
+ result = search(data, filter);
30724
+ } catch (err) {
30725
+ throw new FilterEvaluationError(filter, err);
30726
+ }
30261
30727
  if (result == null)
30262
30728
  return [];
30263
30729
  if (Array.isArray(result)) {
@@ -30274,13 +30740,18 @@ function applyFilter(data, filter) {
30274
30740
  }
30275
30741
  var OutputFormatter;
30276
30742
  ((OutputFormatter) => {
30277
- function success(data) {
30743
+ function success(data, options) {
30278
30744
  data.Log ??= getLogFilePath() || undefined;
30745
+ const normalize = !options?.preserveDataKeys;
30746
+ if (normalize) {
30747
+ data.Data = normalizeDataKeys(data.Data);
30748
+ }
30279
30749
  const filter = getOutputFilter();
30280
30750
  if (filter) {
30281
- data.Data = applyFilter(data.Data, filter);
30751
+ const filtered = applyFilter(data.Data, filter);
30752
+ data.Data = normalize ? normalizeDataKeys(filtered) : filtered;
30282
30753
  }
30283
- logOutput(data, getOutputFormat());
30754
+ logOutput(normalizeOutputKeys(data), getOutputFormat());
30284
30755
  }
30285
30756
  OutputFormatter.success = success;
30286
30757
  function error(data) {
@@ -30290,7 +30761,7 @@ var OutputFormatter;
30290
30761
  result: data.Result,
30291
30762
  message: data.Message
30292
30763
  });
30293
- logOutput(data, getOutputFormat());
30764
+ logOutput(normalizeOutputKeys(data), getOutputFormat());
30294
30765
  }
30295
30766
  OutputFormatter.error = error;
30296
30767
  function emitList(code, items, opts) {
@@ -30311,13 +30782,14 @@ var OutputFormatter;
30311
30782
  function log(data) {
30312
30783
  const format = getOutputFormat();
30313
30784
  const sink = getOutputSink();
30785
+ const normalized = toPascalCaseData(data);
30314
30786
  if (format === "json") {
30315
- const json2 = JSON.stringify(data);
30787
+ const json2 = JSON.stringify(normalized);
30316
30788
  const safe = needsAsciiSafeJson(sink) ? escapeNonAscii(json2) : json2;
30317
30789
  sink.writeErr(`${safe}
30318
30790
  `);
30319
30791
  } else {
30320
- for (const [key, value] of Object.entries(data)) {
30792
+ for (const [key, value] of Object.entries(normalized)) {
30321
30793
  sink.writeErr(`${key}: ${value}
30322
30794
  `);
30323
30795
  }
@@ -30326,12 +30798,16 @@ var OutputFormatter;
30326
30798
  OutputFormatter.log = log;
30327
30799
  function formatToString(data) {
30328
30800
  const filter = getOutputFilter();
30329
- if (filter && "Data" in data && data.Data != null) {
30330
- data.Data = applyFilter(data.Data, filter);
30801
+ if ("Data" in data && data.Data != null) {
30802
+ data.Data = normalizeDataKeys(data.Data);
30803
+ if (filter) {
30804
+ data.Data = normalizeDataKeys(applyFilter(data.Data, filter));
30805
+ }
30331
30806
  }
30807
+ const output = normalizeOutputKeys(data);
30332
30808
  const lines = [];
30333
30809
  const sink = getOutputSink();
30334
- printOutput(data, getOutputFormat(), (msg) => {
30810
+ printOutput(output, getOutputFormat(), (msg) => {
30335
30811
  lines.push(msg);
30336
30812
  }, needsAsciiSafeJson(sink));
30337
30813
  return lines.join(`
@@ -31760,6 +32236,22 @@ function parseBoundedInt(raw, optionName, bounds) {
31760
32236
  }
31761
32237
  return n;
31762
32238
  }
32239
+ // ../../common/src/polling/types.ts
32240
+ var PollOutcome = {
32241
+ Completed: "completed",
32242
+ Timeout: "timeout",
32243
+ Interrupted: "interrupted",
32244
+ Aborted: "aborted",
32245
+ Failed: "failed"
32246
+ };
32247
+
32248
+ // ../../common/src/polling/poll-failure-mapping.ts
32249
+ var REASON_BY_OUTCOME = {
32250
+ [PollOutcome.Timeout]: "poll_timeout",
32251
+ [PollOutcome.Failed]: "poll_failed",
32252
+ [PollOutcome.Interrupted]: "poll_failed",
32253
+ [PollOutcome.Aborted]: "poll_aborted"
32254
+ };
31763
32255
  // ../../common/src/polling/terminal-statuses.ts
31764
32256
  var TERMINAL_STATUSES = new Set([
31765
32257
  "completed",
@@ -31965,17 +32457,21 @@ Command.prototype.trackedAction = function(context, fn, properties) {
31965
32457
  const telemetryName = deriveCommandPath(command);
31966
32458
  const props = typeof properties === "function" ? properties(...args) : properties;
31967
32459
  const startTime = performance.now();
31968
- let errorMessage;
32460
+ let errorMessage2;
31969
32461
  const [error] = await catchError2(fn(...args));
31970
32462
  if (error) {
31971
- errorMessage = error instanceof Error ? error.message : String(error);
31972
- logger.error(`[trackedAction] ${telemetryName} failed: ${errorMessage}`);
32463
+ errorMessage2 = error instanceof Error ? error.message : String(error);
32464
+ logger.debug(`[trackedAction] ${telemetryName} failed: ${errorMessage2}`);
32465
+ const typed = error;
32466
+ const customInstructions = typeof typed.instructions === "string" ? typed.instructions : undefined;
32467
+ const customResult = typeof typed.result === "string" && typed.result !== RESULTS.Success && Object.values(RESULTS).includes(typed.result) ? typed.result : undefined;
32468
+ const finalResult = customResult ?? RESULTS.Failure;
31973
32469
  OutputFormatter.error({
31974
- Result: RESULTS.Failure,
31975
- Message: errorMessage,
31976
- Instructions: "An unexpected error occurred. Run with --log-level debug for details."
32470
+ Result: finalResult,
32471
+ Message: errorMessage2,
32472
+ Instructions: customInstructions ?? "An unexpected error occurred. Run with --log-level debug for details."
31977
32473
  });
31978
- context.exit(1);
32474
+ context.exit(EXIT_CODES[finalResult]);
31979
32475
  }
31980
32476
  const durationMs = performance.now() - startTime;
31981
32477
  const success = !error && (process.exitCode === undefined || process.exitCode === 0);
@@ -31984,7 +32480,7 @@ Command.prototype.trackedAction = function(context, fn, properties) {
31984
32480
  ...props,
31985
32481
  duration: String(durationMs),
31986
32482
  success: String(success),
31987
- ...errorMessage ? { errorMessage } : {}
32483
+ ...errorMessage2 ? { errorMessage: errorMessage2 } : {}
31988
32484
  }));
31989
32485
  });
31990
32486
  };