@uipath/audit-tool 1.1.0 → 1.195.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 +660 -154
  2. package/dist/tool.js +660 -154
  3. package/package.json +28 -37
package/dist/tool.js CHANGED
@@ -706,6 +706,7 @@ var init_open = __esm(() => {
706
706
  });
707
707
 
708
708
  // ../../filesystem/src/node.ts
709
+ import { randomUUID } from "node:crypto";
709
710
  import { existsSync } from "node:fs";
710
711
  import * as fs6 from "node:fs/promises";
711
712
  import * as os2 from "node:os";
@@ -787,6 +788,90 @@ class NodeFileSystem {
787
788
  async mkdir(dirPath) {
788
789
  await fs6.mkdir(dirPath, { recursive: true });
789
790
  }
791
+ async acquireLock(lockPath) {
792
+ const canonicalPath = await this.canonicalizeLockTarget(lockPath);
793
+ const lockFile = `${canonicalPath}.lock`;
794
+ const ownerId = randomUUID();
795
+ const start = Date.now();
796
+ while (true) {
797
+ try {
798
+ await fs6.writeFile(lockFile, ownerId, { flag: "wx" });
799
+ return this.createLockRelease(lockFile, ownerId);
800
+ } catch (error) {
801
+ if (!this.hasErrnoCode(error, "EEXIST")) {
802
+ throw error;
803
+ }
804
+ const stats = await fs6.stat(lockFile).catch(() => null);
805
+ if (stats && Date.now() - stats.mtimeMs > LOCK_STALE_MS) {
806
+ const reclaimed = await fs6.rm(lockFile, { force: true }).then(() => true).catch(() => false);
807
+ if (reclaimed)
808
+ continue;
809
+ }
810
+ if (Date.now() - start > LOCK_MAX_WAIT_MS) {
811
+ throw new Error(`ELOCKED: timed out waiting for lock on ${canonicalPath}`);
812
+ }
813
+ await new Promise((resolve2) => setTimeout(resolve2, LOCK_RETRY_MIN_MS + Math.random() * LOCK_RETRY_JITTER_MS));
814
+ }
815
+ }
816
+ }
817
+ async canonicalizeLockTarget(lockPath) {
818
+ const absolute = path2.resolve(lockPath);
819
+ const fullReal = await fs6.realpath(absolute).catch(() => null);
820
+ if (fullReal)
821
+ return fullReal;
822
+ const parent = path2.dirname(absolute);
823
+ const base = path2.basename(absolute);
824
+ const canonicalParent = await fs6.realpath(parent).catch(() => parent);
825
+ return path2.join(canonicalParent, base);
826
+ }
827
+ createLockRelease(lockFile, ownerId) {
828
+ const heartbeatStart = Date.now();
829
+ let heartbeatTimer;
830
+ let stopped = false;
831
+ const stopHeartbeat = () => {
832
+ stopped = true;
833
+ if (heartbeatTimer)
834
+ clearTimeout(heartbeatTimer);
835
+ };
836
+ const scheduleNextHeartbeat = () => {
837
+ if (stopped)
838
+ return;
839
+ if (Date.now() - heartbeatStart >= LOCK_MAX_HOLD_MS) {
840
+ stopped = true;
841
+ return;
842
+ }
843
+ heartbeatTimer = setTimeout(() => {
844
+ runHeartbeat();
845
+ }, LOCK_HEARTBEAT_MS);
846
+ heartbeatTimer.unref?.();
847
+ };
848
+ const runHeartbeat = async () => {
849
+ if (stopped)
850
+ return;
851
+ const current = await fs6.readFile(lockFile, "utf-8").catch(() => null);
852
+ if (stopped)
853
+ return;
854
+ if (current !== ownerId) {
855
+ stopped = true;
856
+ return;
857
+ }
858
+ const now = Date.now() / 1000;
859
+ await fs6.utimes(lockFile, now, now).catch(() => {});
860
+ scheduleNextHeartbeat();
861
+ };
862
+ scheduleNextHeartbeat();
863
+ let released = false;
864
+ return async () => {
865
+ if (released)
866
+ return;
867
+ released = true;
868
+ stopHeartbeat();
869
+ const current = await fs6.readFile(lockFile, "utf-8").catch(() => null);
870
+ if (current === ownerId) {
871
+ await fs6.rm(lockFile, { force: true });
872
+ }
873
+ };
874
+ }
790
875
  async rm(filePath) {
791
876
  await fs6.rm(filePath, { recursive: true, force: true });
792
877
  }
@@ -832,9 +917,13 @@ class NodeFileSystem {
832
917
  }
833
918
  }
834
919
  isEnoent(error) {
835
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
920
+ return this.hasErrnoCode(error, "ENOENT");
921
+ }
922
+ hasErrnoCode(error, code) {
923
+ return typeof error === "object" && error !== null && "code" in error && error.code === code;
836
924
  }
837
925
  }
926
+ 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;
838
927
  var init_node = __esm(() => {
839
928
  init_open();
840
929
  });
@@ -848,7 +937,7 @@ var init_src = __esm(() => {
848
937
 
849
938
  // ../../../node_modules/@uipath/coreipc/index.js
850
939
  var require_coreipc = __commonJS((exports, module) => {
851
- var __dirname = "/Users/alexandru.oltean/github/cli/node_modules/@uipath/coreipc";
940
+ var __dirname = "/home/runner/work/cli/cli/node_modules/@uipath/coreipc";
852
941
  /*! For license information please see index.js.LICENSE.txt */
853
942
  (function(e, t) {
854
943
  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();
@@ -19040,6 +19129,10 @@ var require_dist = __commonJS((exports) => {
19040
19129
  exports.RobotProxyConstructor = RobotProxyConstructor;
19041
19130
  __exportStar(require_agent(), exports);
19042
19131
  });
19132
+ // ../../auth/src/server.ts
19133
+ var init_server = __esm(() => {
19134
+ init_constants();
19135
+ });
19043
19136
 
19044
19137
  // ../../../node_modules/adm-zip/util/constants.js
19045
19138
  var require_constants = __commonJS((exports, module) => {
@@ -21341,7 +21434,8 @@ var require_adm_zip = __commonJS((exports, module) => {
21341
21434
  // package.json
21342
21435
  var package_default = {
21343
21436
  name: "@uipath/audit-tool",
21344
- version: "1.1.0",
21437
+ license: "MIT",
21438
+ version: "1.195.0",
21345
21439
  description: "CLI plugin for the UiPath Audit Service — query event sources, paginate events, and export ZIPs from the long-term store.",
21346
21440
  private: false,
21347
21441
  repository: {
@@ -21352,7 +21446,9 @@ var package_default = {
21352
21446
  publishConfig: {
21353
21447
  registry: "https://npm.pkg.github.com/@uipath"
21354
21448
  },
21355
- keywords: ["cli-tool"],
21449
+ keywords: [
21450
+ "cli-tool"
21451
+ ],
21356
21452
  type: "module",
21357
21453
  main: "./dist/tool.js",
21358
21454
  exports: {
@@ -21361,7 +21457,9 @@ var package_default = {
21361
21457
  bin: {
21362
21458
  "audit-tool": "./dist/index.js"
21363
21459
  },
21364
- files: ["dist"],
21460
+ files: [
21461
+ "dist"
21462
+ ],
21365
21463
  scripts: {
21366
21464
  build: "bun build ./src/tool.ts --outdir dist --format esm --target node --external commander && bun build ./src/index.ts --outdir dist --format esm --target node",
21367
21465
  package: "bun run build && bun pm pack",
@@ -21382,6 +21480,136 @@ var package_default = {
21382
21480
  }
21383
21481
  };
21384
21482
 
21483
+ // ../../common/src/singleton.ts
21484
+ var PREFIX = "@uipath/common/";
21485
+ var _g = globalThis;
21486
+ function singleton(ctorOrName) {
21487
+ const name = typeof ctorOrName === "string" ? ctorOrName : ctorOrName.name;
21488
+ const key = Symbol.for(PREFIX + name);
21489
+ return {
21490
+ get(fallback) {
21491
+ return _g[key] ?? fallback;
21492
+ },
21493
+ set(value) {
21494
+ _g[key] = value;
21495
+ },
21496
+ clear() {
21497
+ delete _g[key];
21498
+ },
21499
+ getOrInit(factory, guard) {
21500
+ const existing = _g[key];
21501
+ if (existing != null && typeof existing === "object") {
21502
+ if (!guard || guard(existing)) {
21503
+ return existing;
21504
+ }
21505
+ }
21506
+ const instance = factory();
21507
+ _g[key] = instance;
21508
+ return instance;
21509
+ }
21510
+ };
21511
+ }
21512
+
21513
+ // ../../common/src/sdk-user-agent.ts
21514
+ var USER_AGENT_HEADER = "User-Agent";
21515
+ var sdkUserAgentHostToken = singleton("SdkUserAgentHostToken");
21516
+ function userAgentPatchKey(userAgent) {
21517
+ return Symbol.for(`@uipath/common/sdk-user-agent/${userAgent}`);
21518
+ }
21519
+ function splitUserAgentTokens(value) {
21520
+ return value?.trim().split(/\s+/).filter(Boolean) ?? [];
21521
+ }
21522
+ function appendUserAgentToken(value, userAgent) {
21523
+ const tokens = splitUserAgentTokens(value);
21524
+ const seen = new Set(tokens);
21525
+ for (const token of splitUserAgentTokens(userAgent)) {
21526
+ if (!seen.has(token)) {
21527
+ tokens.push(token);
21528
+ seen.add(token);
21529
+ }
21530
+ }
21531
+ return tokens.join(" ");
21532
+ }
21533
+ function getEffectiveUserAgent(userAgent) {
21534
+ return appendUserAgentToken(sdkUserAgentHostToken.get(), userAgent);
21535
+ }
21536
+ function isHeadersLike(headers) {
21537
+ return typeof headers === "object" && headers !== null && "get" in headers && typeof headers.get === "function" && "set" in headers && typeof headers.set === "function";
21538
+ }
21539
+ function getSdkUserAgentToken(pkg) {
21540
+ const packageName = pkg.name.replace(/^@uipath\//, "");
21541
+ return getEffectiveUserAgent(`${packageName}/${pkg.version}`);
21542
+ }
21543
+ function addSdkUserAgentHeader(headers, userAgent) {
21544
+ const result = { ...headers ?? {} };
21545
+ const effectiveUserAgent = getEffectiveUserAgent(userAgent);
21546
+ const headerName = Object.keys(result).find((key) => key.toLowerCase() === USER_AGENT_HEADER.toLowerCase());
21547
+ if (headerName) {
21548
+ result[headerName] = appendUserAgentToken(result[headerName], effectiveUserAgent);
21549
+ } else {
21550
+ result[USER_AGENT_HEADER] = effectiveUserAgent;
21551
+ }
21552
+ return result;
21553
+ }
21554
+ function withSdkUserAgentHeader(headers, userAgent) {
21555
+ const effectiveUserAgent = getEffectiveUserAgent(userAgent);
21556
+ if (isHeadersLike(headers)) {
21557
+ headers.set(USER_AGENT_HEADER, appendUserAgentToken(headers.get(USER_AGENT_HEADER), effectiveUserAgent));
21558
+ return headers;
21559
+ }
21560
+ if (Array.isArray(headers)) {
21561
+ const result = headers.map((entry) => {
21562
+ const [key, value] = entry;
21563
+ return [key, value];
21564
+ });
21565
+ const headerIndex = result.findIndex(([key]) => key.toLowerCase() === USER_AGENT_HEADER.toLowerCase());
21566
+ if (headerIndex >= 0) {
21567
+ const [key, value] = result[headerIndex];
21568
+ result[headerIndex] = [
21569
+ key,
21570
+ appendUserAgentToken(value, effectiveUserAgent)
21571
+ ];
21572
+ } else {
21573
+ result.push([USER_AGENT_HEADER, effectiveUserAgent]);
21574
+ }
21575
+ return result;
21576
+ }
21577
+ return addSdkUserAgentHeader(typeof headers === "object" && headers !== null ? { ...headers } : {}, effectiveUserAgent);
21578
+ }
21579
+ function withUserAgentInitOverride(initOverrides, userAgent) {
21580
+ return async (requestContext) => {
21581
+ const initWithUserAgent = {
21582
+ ...requestContext.init,
21583
+ headers: withSdkUserAgentHeader(requestContext.init.headers, userAgent)
21584
+ };
21585
+ const override = typeof initOverrides === "function" ? await initOverrides({
21586
+ ...requestContext,
21587
+ init: initWithUserAgent
21588
+ }) : initOverrides;
21589
+ return {
21590
+ ...override ?? {},
21591
+ headers: withSdkUserAgentHeader(override?.headers ?? initWithUserAgent.headers, userAgent)
21592
+ };
21593
+ };
21594
+ }
21595
+ function installSdkUserAgentHeader(BaseApiClass, userAgent) {
21596
+ const prototype = BaseApiClass.prototype;
21597
+ const patchKey = userAgentPatchKey(userAgent);
21598
+ if (prototype[patchKey]) {
21599
+ return;
21600
+ }
21601
+ if (typeof prototype.request !== "function") {
21602
+ throw new Error("Generated BaseAPI request function not found.");
21603
+ }
21604
+ const originalRequest = prototype.request;
21605
+ prototype.request = function requestWithUserAgent(context, initOverrides) {
21606
+ return originalRequest.call(this, context, withUserAgentInitOverride(initOverrides, userAgent));
21607
+ };
21608
+ Object.defineProperty(prototype, patchKey, {
21609
+ value: true
21610
+ });
21611
+ }
21612
+
21385
21613
  // ../audit-sdk/generated/src/runtime.ts
21386
21614
  var BASE_PATH = "https://localhost:7008".replace(/\/+$/, "");
21387
21615
 
@@ -21630,6 +21858,55 @@ class VoidApiResponse {
21630
21858
  return;
21631
21859
  }
21632
21860
  }
21861
+ // ../audit-sdk/package.json
21862
+ var package_default2 = {
21863
+ name: "@uipath/audit-sdk",
21864
+ license: "MIT",
21865
+ version: "1.195.0",
21866
+ description: "SDK for the UiPath Audit Service — query audit event sources, list events, and download long-term-store exports.",
21867
+ repository: {
21868
+ type: "git",
21869
+ url: "https://github.com/UiPath/cli.git",
21870
+ directory: "packages/admin/audit-sdk"
21871
+ },
21872
+ publishConfig: {
21873
+ registry: "https://npm.pkg.github.com/@uipath"
21874
+ },
21875
+ keywords: [
21876
+ "uipath",
21877
+ "audit",
21878
+ "sdk"
21879
+ ],
21880
+ type: "module",
21881
+ main: "./dist/index.js",
21882
+ types: "./dist/src/index.d.ts",
21883
+ exports: {
21884
+ ".": {
21885
+ types: "./dist/src/index.d.ts",
21886
+ default: "./dist/index.js"
21887
+ }
21888
+ },
21889
+ files: [
21890
+ "dist"
21891
+ ],
21892
+ private: true,
21893
+ scripts: {
21894
+ build: "bun build ./src/index.ts --outdir dist --format esm --target node && tsc -p tsconfig.build.json --noCheck",
21895
+ generate: "bun run src/scripts/generate-sdk.ts",
21896
+ lint: "biome check ."
21897
+ },
21898
+ devDependencies: {
21899
+ "@openapitools/openapi-generator-cli": "^2.31.1",
21900
+ "@types/node": "^25.5.0",
21901
+ "@uipath/auth": "workspace:*",
21902
+ "@uipath/common": "workspace:*",
21903
+ typescript: "^6.0.2"
21904
+ }
21905
+ };
21906
+
21907
+ // ../audit-sdk/src/user-agent.ts
21908
+ var SDK_USER_AGENT = getSdkUserAgentToken(package_default2);
21909
+ installSdkUserAgentHeader(BaseAPI, SDK_USER_AGENT);
21633
21910
 
21634
21911
  // ../audit-sdk/generated/src/models/AuditEventStatus.ts
21635
21912
  var AuditEventStatus = {
@@ -21890,32 +22167,7 @@ class InvalidBaseUrlError extends Error {
21890
22167
  this.name = "InvalidBaseUrlError";
21891
22168
  }
21892
22169
  }
21893
- var DEFAULT_SCOPES = [
21894
- "offline_access",
21895
- "ProcessMining",
21896
- "OrchestratorApiUserAccess",
21897
- "StudioWebBackend",
21898
- "IdentityServerApi",
21899
- "ConnectionService",
21900
- "DataService",
21901
- "DataServiceApiUserAccess",
21902
- "DocumentUnderstanding",
21903
- "EnterpriseContextService",
21904
- "Directory",
21905
- "JamJamApi",
21906
- "LLMGateway",
21907
- "LLMOps",
21908
- "OMS",
21909
- "RCS.FolderAuthorization",
21910
- "RCS.TagsManagement",
21911
- "TestmanagerApiUserAccess",
21912
- "AutomationSolutions",
21913
- "StudioWebTypeCacheService",
21914
- "Docs.GPT.Search",
21915
- "Insights",
21916
- "ReferenceToken",
21917
- "Audit.Read"
21918
- ];
22170
+ var DEFAULT_SCOPES = ["openid", "profile", "offline_access"];
21919
22171
  var normalizeAndValidateBaseUrl = (rawUrl) => {
21920
22172
  let baseUrl = rawUrl;
21921
22173
  if (baseUrl.endsWith("/identity_/")) {
@@ -21965,7 +22217,8 @@ var resolveConfigAsync = async ({
21965
22217
  if (!clientSecret && fileAuth.clientSecret) {
21966
22218
  clientSecret = fileAuth.clientSecret;
21967
22219
  }
21968
- const scopes = customScopes && customScopes.length > 0 ? customScopes : fileAuth.scopes && fileAuth.scopes.length > 0 ? fileAuth.scopes : DEFAULT_SCOPES;
22220
+ const isExternalAppAuth = clientId !== DEFAULT_CLIENT_ID && Boolean(clientSecret);
22221
+ const scopes = customScopes && customScopes.length > 0 ? customScopes : fileAuth.scopes && fileAuth.scopes.length > 0 ? fileAuth.scopes : isExternalAppAuth ? [] : DEFAULT_SCOPES;
21969
22222
  return {
21970
22223
  clientId,
21971
22224
  clientSecret,
@@ -22465,6 +22718,129 @@ function normalizeTokenRefreshFailure() {
22465
22718
  function normalizeTokenRefreshUnavailableFailure() {
22466
22719
  return "token refresh failed before authentication completed";
22467
22720
  }
22721
+ function errorMessage(error) {
22722
+ return error instanceof Error ? error.message : String(error);
22723
+ }
22724
+ function computeExpirationThreshold(ensureTokenValidityMinutes) {
22725
+ return new Date(Date.now() + (ensureTokenValidityMinutes ?? 0) * 60 * 1000);
22726
+ }
22727
+ async function runRefreshLocked(inputs) {
22728
+ const {
22729
+ absolutePath,
22730
+ refreshToken: callerRefreshToken,
22731
+ customAuthority,
22732
+ ensureTokenValidityMinutes,
22733
+ loadEnvFile,
22734
+ saveEnvFile,
22735
+ refreshFn,
22736
+ resolveConfig
22737
+ } = inputs;
22738
+ const expirationThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
22739
+ let fresh;
22740
+ try {
22741
+ fresh = await loadEnvFile({ envPath: absolutePath });
22742
+ } catch (error) {
22743
+ return {
22744
+ kind: "fail",
22745
+ status: {
22746
+ loginStatus: "Refresh Failed",
22747
+ hint: "Could not read the auth file while refreshing. Retry, or run 'uip login' to re-authenticate.",
22748
+ tokenRefresh: {
22749
+ attempted: false,
22750
+ success: false,
22751
+ errorMessage: `auth file read failed: ${errorMessage(error)}`
22752
+ }
22753
+ }
22754
+ };
22755
+ }
22756
+ const freshAccess = fresh.UIPATH_ACCESS_TOKEN;
22757
+ const freshExp = freshAccess ? getTokenExpiration(freshAccess) : undefined;
22758
+ if (freshAccess && freshExp && freshExp > expirationThreshold) {
22759
+ return {
22760
+ kind: "ok",
22761
+ accessToken: freshAccess,
22762
+ refreshToken: fresh.UIPATH_REFRESH_TOKEN ?? callerRefreshToken,
22763
+ expiration: freshExp,
22764
+ tokenRefresh: { attempted: false, success: true }
22765
+ };
22766
+ }
22767
+ const tokenForIdP = fresh.UIPATH_REFRESH_TOKEN ?? callerRefreshToken;
22768
+ let refreshedAccess;
22769
+ let refreshedRefresh;
22770
+ try {
22771
+ const config = await resolveConfig({ customAuthority });
22772
+ const refreshed = await refreshFn({
22773
+ refreshToken: tokenForIdP,
22774
+ tokenEndpoint: config.tokenEndpoint,
22775
+ clientId: config.clientId,
22776
+ expectedAuthority: customAuthority
22777
+ });
22778
+ refreshedAccess = refreshed.accessToken;
22779
+ refreshedRefresh = refreshed.refreshToken;
22780
+ } catch (error) {
22781
+ const isOAuthFailure = isTokenRefreshOAuthFailure(error);
22782
+ 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.";
22783
+ const message = isOAuthFailure ? normalizeTokenRefreshFailure() : normalizeTokenRefreshUnavailableFailure();
22784
+ return {
22785
+ kind: "fail",
22786
+ status: {
22787
+ loginStatus: "Refresh Failed",
22788
+ hint,
22789
+ tokenRefresh: {
22790
+ attempted: true,
22791
+ success: false,
22792
+ errorMessage: message
22793
+ }
22794
+ }
22795
+ };
22796
+ }
22797
+ const refreshedExp = getTokenExpiration(refreshedAccess);
22798
+ if (!refreshedExp || refreshedExp <= new Date) {
22799
+ return {
22800
+ kind: "fail",
22801
+ status: {
22802
+ loginStatus: "Refresh Failed",
22803
+ hint: "The identity server returned an unusable token. Run 'uip login' to re-authenticate.",
22804
+ tokenRefresh: {
22805
+ attempted: true,
22806
+ success: false,
22807
+ errorMessage: "refreshed token has no valid expiration claim"
22808
+ }
22809
+ }
22810
+ };
22811
+ }
22812
+ try {
22813
+ await saveEnvFile({
22814
+ envPath: absolutePath,
22815
+ data: {
22816
+ UIPATH_ACCESS_TOKEN: refreshedAccess,
22817
+ UIPATH_REFRESH_TOKEN: refreshedRefresh
22818
+ },
22819
+ merge: true
22820
+ });
22821
+ return {
22822
+ kind: "ok",
22823
+ accessToken: refreshedAccess,
22824
+ refreshToken: refreshedRefresh,
22825
+ expiration: refreshedExp,
22826
+ tokenRefresh: { attempted: true, success: true }
22827
+ };
22828
+ } catch (error) {
22829
+ const msg = errorMessage(error);
22830
+ return {
22831
+ kind: "ok",
22832
+ accessToken: refreshedAccess,
22833
+ refreshToken: refreshedRefresh,
22834
+ expiration: refreshedExp,
22835
+ 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.`,
22836
+ tokenRefresh: {
22837
+ attempted: true,
22838
+ success: true,
22839
+ errorMessage: `persistence failed: ${msg}`
22840
+ }
22841
+ };
22842
+ }
22843
+ }
22468
22844
  var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
22469
22845
  const {
22470
22846
  resolveEnvFilePath = resolveEnvFilePathAsync,
@@ -22539,73 +22915,103 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
22539
22915
  let refreshToken = credentials.UIPATH_REFRESH_TOKEN;
22540
22916
  let expiration = getTokenExpiration(accessToken);
22541
22917
  let persistenceWarning;
22918
+ let lockReleaseFailed = false;
22542
22919
  let tokenRefresh;
22543
- const expirationThreshold = new Date(Date.now() + (ensureTokenValidityMinutes ?? 0) * 60 * 1000);
22544
- if (expiration && expiration <= expirationThreshold && refreshToken) {
22545
- let refreshedAccess;
22546
- let refreshedRefresh;
22920
+ const outerThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
22921
+ const tryGlobalCredsHint = async () => {
22922
+ const fs7 = getFs();
22923
+ const globalPath = fs7.path.join(fs7.env.homedir(), envFilePath);
22924
+ if (absolutePath === globalPath)
22925
+ return;
22926
+ if (!await fs7.exists(globalPath))
22927
+ return;
22547
22928
  try {
22548
- const config = await resolveConfig({
22549
- customAuthority: credentials.UIPATH_URL
22550
- });
22551
- const refreshed = await refreshTokenFn({
22552
- refreshToken,
22553
- tokenEndpoint: config.tokenEndpoint,
22554
- clientId: config.clientId,
22555
- expectedAuthority: credentials.UIPATH_URL
22556
- });
22557
- refreshedAccess = refreshed.accessToken;
22558
- refreshedRefresh = refreshed.refreshToken;
22559
- } catch (error) {
22560
- const isOAuthFailure = isTokenRefreshOAuthFailure(error);
22561
- 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.";
22562
- const errorMessage = isOAuthFailure ? normalizeTokenRefreshFailure() : normalizeTokenRefreshUnavailableFailure();
22563
- return {
22564
- loginStatus: "Refresh Failed",
22565
- hint,
22566
- tokenRefresh: {
22567
- attempted: true,
22568
- success: false,
22569
- errorMessage
22570
- }
22571
- };
22929
+ const globalCreds = await loadEnvFile({ envPath: globalPath });
22930
+ if (!globalCreds.UIPATH_ACCESS_TOKEN)
22931
+ return;
22932
+ const globalExp = getTokenExpiration(globalCreds.UIPATH_ACCESS_TOKEN);
22933
+ if (globalExp && globalExp <= new Date)
22934
+ return;
22935
+ 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.`;
22936
+ } catch {
22937
+ return;
22572
22938
  }
22573
- const refreshedExp = getTokenExpiration(refreshedAccess);
22574
- if (!refreshedExp || refreshedExp <= new Date) {
22939
+ };
22940
+ if (expiration && expiration <= outerThreshold && refreshToken) {
22941
+ let release;
22942
+ try {
22943
+ release = await getFs().acquireLock(absolutePath);
22944
+ } catch (error) {
22945
+ const msg = errorMessage(error);
22946
+ const globalHint = await tryGlobalCredsHint();
22947
+ if (globalHint) {
22948
+ return {
22949
+ loginStatus: "Expired",
22950
+ accessToken,
22951
+ refreshToken,
22952
+ baseUrl: credentials.UIPATH_URL,
22953
+ organizationName: credentials.UIPATH_ORGANIZATION_NAME,
22954
+ organizationId: credentials.UIPATH_ORGANIZATION_ID,
22955
+ tenantName: credentials.UIPATH_TENANT_NAME,
22956
+ tenantId: credentials.UIPATH_TENANT_ID,
22957
+ expiration,
22958
+ source: "file" /* File */,
22959
+ hint: globalHint,
22960
+ tokenRefresh: {
22961
+ attempted: false,
22962
+ success: false,
22963
+ errorMessage: `lock acquisition failed: ${msg}`
22964
+ }
22965
+ };
22966
+ }
22575
22967
  return {
22576
22968
  loginStatus: "Refresh Failed",
22577
- hint: "The identity server returned an unusable token. Run 'uip login' to re-authenticate.",
22969
+ 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.",
22578
22970
  tokenRefresh: {
22579
- attempted: true,
22971
+ attempted: false,
22580
22972
  success: false,
22581
- errorMessage: "refreshed token has no valid expiration claim"
22973
+ errorMessage: `lock acquisition failed: ${msg}`
22582
22974
  }
22583
22975
  };
22584
22976
  }
22585
- accessToken = refreshedAccess;
22586
- refreshToken = refreshedRefresh;
22587
- expiration = refreshedExp;
22977
+ let lockedFailure;
22588
22978
  try {
22589
- await saveEnvFile({
22590
- envPath: absolutePath,
22591
- data: {
22592
- UIPATH_ACCESS_TOKEN: accessToken,
22593
- UIPATH_REFRESH_TOKEN: refreshToken
22594
- },
22595
- merge: true
22979
+ const outcome = await runRefreshLocked({
22980
+ absolutePath,
22981
+ refreshToken,
22982
+ customAuthority: credentials.UIPATH_URL,
22983
+ ensureTokenValidityMinutes,
22984
+ loadEnvFile,
22985
+ saveEnvFile,
22986
+ refreshFn: refreshTokenFn,
22987
+ resolveConfig
22596
22988
  });
22597
- tokenRefresh = {
22598
- attempted: true,
22599
- success: true
22600
- };
22601
- } catch (error) {
22602
- const msg = error instanceof Error ? error.message : String(error);
22603
- 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.`;
22604
- tokenRefresh = {
22605
- attempted: true,
22606
- success: true,
22607
- errorMessage: `persistence failed: ${msg}`
22608
- };
22989
+ if (outcome.kind === "fail") {
22990
+ lockedFailure = outcome.status;
22991
+ } else {
22992
+ accessToken = outcome.accessToken;
22993
+ refreshToken = outcome.refreshToken;
22994
+ expiration = outcome.expiration;
22995
+ tokenRefresh = outcome.tokenRefresh;
22996
+ if (outcome.persistenceWarning) {
22997
+ persistenceWarning = outcome.persistenceWarning;
22998
+ }
22999
+ }
23000
+ } finally {
23001
+ try {
23002
+ await release();
23003
+ } catch {
23004
+ lockReleaseFailed = true;
23005
+ }
23006
+ }
23007
+ if (lockedFailure) {
23008
+ const globalHint = await tryGlobalCredsHint();
23009
+ const base = globalHint ? {
23010
+ ...lockedFailure,
23011
+ loginStatus: "Expired",
23012
+ hint: globalHint
23013
+ } : lockedFailure;
23014
+ return lockReleaseFailed ? { ...base, lockReleaseFailed: true } : base;
22609
23015
  }
22610
23016
  }
22611
23017
  const result = {
@@ -22620,23 +23026,13 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
22620
23026
  expiration,
22621
23027
  source: "file" /* File */,
22622
23028
  ...persistenceWarning ? { hint: persistenceWarning, persistenceFailed: true } : {},
23029
+ ...lockReleaseFailed ? { lockReleaseFailed: true } : {},
22623
23030
  ...tokenRefresh ? { tokenRefresh } : {}
22624
23031
  };
22625
23032
  if (result.loginStatus === "Expired") {
22626
- const fs7 = getFs();
22627
- const globalPath = fs7.path.join(fs7.env.homedir(), envFilePath);
22628
- if (absolutePath !== globalPath && await fs7.exists(globalPath)) {
22629
- try {
22630
- const globalCreds = await loadEnvFile({
22631
- envPath: globalPath
22632
- });
22633
- if (globalCreds.UIPATH_ACCESS_TOKEN) {
22634
- const globalExp = getTokenExpiration(globalCreds.UIPATH_ACCESS_TOKEN);
22635
- if (!globalExp || globalExp > new Date) {
22636
- 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.`;
22637
- }
22638
- }
22639
- } catch {}
23033
+ const globalHint = await tryGlobalCredsHint();
23034
+ if (globalHint) {
23035
+ result.hint = globalHint;
22640
23036
  }
22641
23037
  }
22642
23038
  return result;
@@ -22653,6 +23049,10 @@ var getLoginStatusAsync = async (options = {}) => {
22653
23049
  init_src();
22654
23050
  // ../../auth/src/logout.ts
22655
23051
  init_src();
23052
+
23053
+ // ../../auth/src/index.ts
23054
+ init_server();
23055
+
22656
23056
  // ../audit-sdk/src/client-factory.ts
22657
23057
  async function createAuditConfig(options) {
22658
23058
  const status = await getLoginStatusAsync({
@@ -22679,7 +23079,8 @@ async function createAuditConfig(options) {
22679
23079
  const bearerToken = options.s2sToken ?? status.accessToken;
22680
23080
  return new Configuration({
22681
23081
  basePath,
22682
- apiKey: () => `Bearer ${bearerToken}`
23082
+ apiKey: () => `Bearer ${bearerToken}`,
23083
+ headers: addSdkUserAgentHeader(undefined, SDK_USER_AGENT)
22683
23084
  });
22684
23085
  }
22685
23086
  async function createApiClient(ApiClass, options) {
@@ -22823,10 +23224,15 @@ async function extractErrorDetails(error, options) {
22823
23224
  }
22824
23225
  if (parsedBody?.errorCode && typeof parsedBody.errorCode === "string") {
22825
23226
  context.errorCode = parsedBody.errorCode;
23227
+ } else if (parsedBody?.code && typeof parsedBody.code === "string") {
23228
+ context.errorCode = parsedBody.code;
22826
23229
  }
22827
23230
  if (parsedBody?.requestId && typeof parsedBody.requestId === "string") {
22828
23231
  context.requestId = parsedBody.requestId;
22829
23232
  }
23233
+ if (parsedBody?.traceId && typeof parsedBody.traceId === "string") {
23234
+ context.traceId = parsedBody.traceId;
23235
+ }
22830
23236
  if (status === 429) {
22831
23237
  const resp = response;
22832
23238
  const headersObj = resp?.headers;
@@ -22846,7 +23252,35 @@ async function extractErrorDetails(error, options) {
22846
23252
  }
22847
23253
  }
22848
23254
  const hasContext = Object.keys(context).length > 0;
22849
- return { result, message, details, ...hasContext ? { context } : {} };
23255
+ let parsedErrors;
23256
+ if (parsedBody?.errors && typeof parsedBody.errors === "object") {
23257
+ const errors = {};
23258
+ for (const [field, raw] of Object.entries(parsedBody.errors)) {
23259
+ if (Array.isArray(raw)) {
23260
+ const messages = raw.map((entry) => {
23261
+ if (typeof entry === "string")
23262
+ return entry;
23263
+ if (entry && typeof entry === "object" && typeof entry.message === "string") {
23264
+ return entry.message;
23265
+ }
23266
+ return String(entry);
23267
+ }).filter(Boolean);
23268
+ if (messages.length > 0)
23269
+ errors[field] = messages;
23270
+ } else if (typeof raw === "string") {
23271
+ errors[field] = [raw];
23272
+ }
23273
+ }
23274
+ if (Object.keys(errors).length > 0)
23275
+ parsedErrors = errors;
23276
+ }
23277
+ return {
23278
+ result,
23279
+ message,
23280
+ details,
23281
+ ...hasContext ? { context } : {},
23282
+ ...parsedErrors ? { parsedErrors } : {}
23283
+ };
22850
23284
  }
22851
23285
  async function extractErrorMessage(error, options) {
22852
23286
  const { message } = await extractErrorDetails(error, options);
@@ -22859,36 +23293,6 @@ Command.prototype.examples = function(examples) {
22859
23293
  examplesByCommand.set(this, examples);
22860
23294
  return this;
22861
23295
  };
22862
- // ../../common/src/singleton.ts
22863
- var PREFIX = "@uipath/common/";
22864
- var _g = globalThis;
22865
- function singleton(ctorOrName) {
22866
- const name = typeof ctorOrName === "string" ? ctorOrName : ctorOrName.name;
22867
- const key = Symbol.for(PREFIX + name);
22868
- return {
22869
- get(fallback) {
22870
- return _g[key] ?? fallback;
22871
- },
22872
- set(value) {
22873
- _g[key] = value;
22874
- },
22875
- clear() {
22876
- delete _g[key];
22877
- },
22878
- getOrInit(factory, guard) {
22879
- const existing = _g[key];
22880
- if (existing != null && typeof existing === "object") {
22881
- if (!guard || guard(existing)) {
22882
- return existing;
22883
- }
22884
- }
22885
- const instance = factory();
22886
- _g[key] = instance;
22887
- return instance;
22888
- }
22889
- };
22890
- }
22891
-
22892
23296
  // ../../common/src/output-context.ts
22893
23297
  function createStorage() {
22894
23298
  const [error, mod] = catchError2(() => __require("node:async_hooks"));
@@ -27978,6 +28382,60 @@ function escapeNonAscii(jsonText) {
27978
28382
  function needsAsciiSafeJson(sink) {
27979
28383
  return process.platform === "win32" && !sink.capabilities.isInteractive;
27980
28384
  }
28385
+ function isPlainRecord(value) {
28386
+ if (value === null || typeof value !== "object")
28387
+ return false;
28388
+ const prototype = Object.getPrototypeOf(value);
28389
+ return prototype === Object.prototype || prototype === null;
28390
+ }
28391
+ function toLowerCamelCaseKey(key) {
28392
+ if (!key)
28393
+ return key;
28394
+ if (/[_\-\s]/.test(key)) {
28395
+ const [firstPart, ...restParts] = key.split(/[_\-\s]+/).filter(Boolean);
28396
+ if (!firstPart)
28397
+ return key;
28398
+ return [
28399
+ toLowerCamelCaseSimpleKey(firstPart),
28400
+ ...restParts.map((part) => {
28401
+ const normalized = toLowerCamelCaseSimpleKey(part);
28402
+ return normalized.charAt(0).toUpperCase() + normalized.slice(1);
28403
+ })
28404
+ ].join("");
28405
+ }
28406
+ return toLowerCamelCaseSimpleKey(key);
28407
+ }
28408
+ function toLowerCamelCaseSimpleKey(key) {
28409
+ if (/^[A-Z0-9]+$/.test(key))
28410
+ return key.toLowerCase();
28411
+ return key.replace(/^[A-Z]+(?=[A-Z][a-z]|\d|$)|^[A-Z]/, (match) => match.toLowerCase());
28412
+ }
28413
+ function toPascalCaseKey(key) {
28414
+ const lowerCamelKey = toLowerCamelCaseKey(key);
28415
+ return lowerCamelKey ? lowerCamelKey.charAt(0).toUpperCase() + lowerCamelKey.slice(1) : lowerCamelKey;
28416
+ }
28417
+ function toPascalCaseData(value) {
28418
+ if (Array.isArray(value))
28419
+ return value.map(toPascalCaseData);
28420
+ if (!isPlainRecord(value))
28421
+ return value;
28422
+ const result = {};
28423
+ for (const [key, nestedValue] of Object.entries(value)) {
28424
+ result[toPascalCaseKey(key)] = toPascalCaseData(nestedValue);
28425
+ }
28426
+ return result;
28427
+ }
28428
+ function normalizeDataKeys(data) {
28429
+ return toPascalCaseData(data);
28430
+ }
28431
+ function normalizeOutputKeys(data) {
28432
+ const result = {};
28433
+ for (const [key, value] of Object.entries(data)) {
28434
+ const pascalKey = toPascalCaseKey(key);
28435
+ result[pascalKey] = pascalKey === "Data" ? value : toPascalCaseData(value);
28436
+ }
28437
+ return result;
28438
+ }
27981
28439
  function printOutput(data, format = "json", logFn, asciiSafe = false) {
27982
28440
  if (!data) {
27983
28441
  logFn("Empty response object. No data to display.");
@@ -28040,7 +28498,7 @@ function wrapText(text, width) {
28040
28498
  function printTable(data, logFn, externalLogValue) {
28041
28499
  if (data.length === 0)
28042
28500
  return;
28043
- const keys = Object.keys(data[0]).filter((key) => key !== "Code" && key !== "Log");
28501
+ const keys = Object.keys(data[0]).filter((key) => !["code", "log"].includes(key.toLowerCase()));
28044
28502
  const maxWidths = keys.map((key) => Math.max(key.length, ...data.map((item) => cellToString(item[key]).length)));
28045
28503
  const header = keys.map((key, i2) => key.padEnd(maxWidths[i2])).join(" | ");
28046
28504
  logFn(header);
@@ -28055,7 +28513,7 @@ function printTable(data, logFn, externalLogValue) {
28055
28513
  }
28056
28514
  }
28057
28515
  function printVerticalTable(data, logFn = console.log, externalLogValue) {
28058
- const keys = Object.keys(data).filter((key) => key !== "Code" && key !== "Log");
28516
+ const keys = Object.keys(data).filter((key) => !["code", "log"].includes(key.toLowerCase()));
28059
28517
  if (keys.length === 0)
28060
28518
  return;
28061
28519
  const maxKeyWidth = Math.max(...keys.map((key) => key.length));
@@ -28071,7 +28529,7 @@ function printVerticalTable(data, logFn = console.log, externalLogValue) {
28071
28529
  function printResizableTable(data, logFn = console.log, externalLogValue) {
28072
28530
  if (data.length === 0)
28073
28531
  return;
28074
- const keys = Object.keys(data[0]).filter((key) => key !== "Code" && key !== "Log");
28532
+ const keys = Object.keys(data[0]).filter((key) => !["code", "log"].includes(key.toLowerCase()));
28075
28533
  if (keys.length === 0)
28076
28534
  return;
28077
28535
  if (!process.stdout.isTTY) {
@@ -28147,8 +28605,26 @@ function printResizableTable(data, logFn = console.log, externalLogValue) {
28147
28605
  function toYaml(data) {
28148
28606
  return dump(data);
28149
28607
  }
28608
+ class FilterEvaluationError extends Error {
28609
+ __brand = "FilterEvaluationError";
28610
+ filter;
28611
+ instructions;
28612
+ result = RESULTS.ValidationError;
28613
+ constructor(filter, cause) {
28614
+ const underlying = cause instanceof Error ? cause.message : String(cause);
28615
+ super(`Filter '${filter}' failed to evaluate: ${underlying}`);
28616
+ this.name = "FilterEvaluationError";
28617
+ this.filter = filter;
28618
+ 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(@)'.";
28619
+ }
28620
+ }
28150
28621
  function applyFilter(data, filter) {
28151
- const result = search(data, filter);
28622
+ let result;
28623
+ try {
28624
+ result = search(data, filter);
28625
+ } catch (err) {
28626
+ throw new FilterEvaluationError(filter, err);
28627
+ }
28152
28628
  if (result == null)
28153
28629
  return [];
28154
28630
  if (Array.isArray(result)) {
@@ -28165,13 +28641,18 @@ function applyFilter(data, filter) {
28165
28641
  }
28166
28642
  var OutputFormatter;
28167
28643
  ((OutputFormatter) => {
28168
- function success(data) {
28644
+ function success(data, options) {
28169
28645
  data.Log ??= getLogFilePath() || undefined;
28646
+ const normalize = !options?.preserveDataKeys;
28647
+ if (normalize) {
28648
+ data.Data = normalizeDataKeys(data.Data);
28649
+ }
28170
28650
  const filter = getOutputFilter();
28171
28651
  if (filter) {
28172
- data.Data = applyFilter(data.Data, filter);
28652
+ const filtered = applyFilter(data.Data, filter);
28653
+ data.Data = normalize ? normalizeDataKeys(filtered) : filtered;
28173
28654
  }
28174
- logOutput(data, getOutputFormat());
28655
+ logOutput(normalizeOutputKeys(data), getOutputFormat());
28175
28656
  }
28176
28657
  OutputFormatter.success = success;
28177
28658
  function error(data) {
@@ -28181,7 +28662,7 @@ var OutputFormatter;
28181
28662
  result: data.Result,
28182
28663
  message: data.Message
28183
28664
  });
28184
- logOutput(data, getOutputFormat());
28665
+ logOutput(normalizeOutputKeys(data), getOutputFormat());
28185
28666
  }
28186
28667
  OutputFormatter.error = error;
28187
28668
  function emitList(code, items, opts) {
@@ -28202,13 +28683,14 @@ var OutputFormatter;
28202
28683
  function log(data) {
28203
28684
  const format = getOutputFormat();
28204
28685
  const sink = getOutputSink();
28686
+ const normalized = toPascalCaseData(data);
28205
28687
  if (format === "json") {
28206
- const json2 = JSON.stringify(data);
28688
+ const json2 = JSON.stringify(normalized);
28207
28689
  const safe = needsAsciiSafeJson(sink) ? escapeNonAscii(json2) : json2;
28208
28690
  sink.writeErr(`${safe}
28209
28691
  `);
28210
28692
  } else {
28211
- for (const [key, value] of Object.entries(data)) {
28693
+ for (const [key, value] of Object.entries(normalized)) {
28212
28694
  sink.writeErr(`${key}: ${value}
28213
28695
  `);
28214
28696
  }
@@ -28217,12 +28699,16 @@ var OutputFormatter;
28217
28699
  OutputFormatter.log = log;
28218
28700
  function formatToString(data) {
28219
28701
  const filter = getOutputFilter();
28220
- if (filter && "Data" in data && data.Data != null) {
28221
- data.Data = applyFilter(data.Data, filter);
28702
+ if ("Data" in data && data.Data != null) {
28703
+ data.Data = normalizeDataKeys(data.Data);
28704
+ if (filter) {
28705
+ data.Data = normalizeDataKeys(applyFilter(data.Data, filter));
28706
+ }
28222
28707
  }
28708
+ const output = normalizeOutputKeys(data);
28223
28709
  const lines = [];
28224
28710
  const sink = getOutputSink();
28225
- printOutput(data, getOutputFormat(), (msg) => {
28711
+ printOutput(output, getOutputFormat(), (msg) => {
28226
28712
  lines.push(msg);
28227
28713
  }, needsAsciiSafeJson(sink));
28228
28714
  return lines.join(`
@@ -29654,6 +30140,22 @@ function parseBoundedInt(raw, optionName, bounds) {
29654
30140
  }
29655
30141
  return n;
29656
30142
  }
30143
+ // ../../common/src/polling/types.ts
30144
+ var PollOutcome = {
30145
+ Completed: "completed",
30146
+ Timeout: "timeout",
30147
+ Interrupted: "interrupted",
30148
+ Aborted: "aborted",
30149
+ Failed: "failed"
30150
+ };
30151
+
30152
+ // ../../common/src/polling/poll-failure-mapping.ts
30153
+ var REASON_BY_OUTCOME = {
30154
+ [PollOutcome.Timeout]: "poll_timeout",
30155
+ [PollOutcome.Failed]: "poll_failed",
30156
+ [PollOutcome.Interrupted]: "poll_failed",
30157
+ [PollOutcome.Aborted]: "poll_aborted"
30158
+ };
29657
30159
  // ../../common/src/polling/terminal-statuses.ts
29658
30160
  var TERMINAL_STATUSES = new Set([
29659
30161
  "completed",
@@ -29862,17 +30364,21 @@ Command2.prototype.trackedAction = function(context, fn, properties) {
29862
30364
  const telemetryName = deriveCommandPath(command);
29863
30365
  const props = typeof properties === "function" ? properties(...args) : properties;
29864
30366
  const startTime = performance.now();
29865
- let errorMessage;
30367
+ let errorMessage2;
29866
30368
  const [error] = await catchError2(fn(...args));
29867
30369
  if (error) {
29868
- errorMessage = error instanceof Error ? error.message : String(error);
29869
- logger.error(`[trackedAction] ${telemetryName} failed: ${errorMessage}`);
30370
+ errorMessage2 = error instanceof Error ? error.message : String(error);
30371
+ logger.debug(`[trackedAction] ${telemetryName} failed: ${errorMessage2}`);
30372
+ const typed = error;
30373
+ const customInstructions = typeof typed.instructions === "string" ? typed.instructions : undefined;
30374
+ const customResult = typeof typed.result === "string" && typed.result !== RESULTS.Success && Object.values(RESULTS).includes(typed.result) ? typed.result : undefined;
30375
+ const finalResult = customResult ?? RESULTS.Failure;
29870
30376
  OutputFormatter.error({
29871
- Result: RESULTS.Failure,
29872
- Message: errorMessage,
29873
- Instructions: "An unexpected error occurred. Run with --log-level debug for details."
30377
+ Result: finalResult,
30378
+ Message: errorMessage2,
30379
+ Instructions: customInstructions ?? "An unexpected error occurred. Run with --log-level debug for details."
29874
30380
  });
29875
- context.exit(1);
30381
+ context.exit(EXIT_CODES[finalResult]);
29876
30382
  }
29877
30383
  const durationMs = performance.now() - startTime;
29878
30384
  const success = !error && (process.exitCode === undefined || process.exitCode === 0);
@@ -29881,7 +30387,7 @@ Command2.prototype.trackedAction = function(context, fn, properties) {
29881
30387
  ...props,
29882
30388
  duration: String(durationMs),
29883
30389
  success: String(success),
29884
- ...errorMessage ? { errorMessage } : {}
30390
+ ...errorMessage2 ? { errorMessage: errorMessage2 } : {}
29885
30391
  }));
29886
30392
  });
29887
30393
  };