@uipath/admin-vpngateway-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 +767 -150
  2. package/dist/tool.js +767 -150
  3. package/package.json +28 -34
package/dist/tool.js CHANGED
@@ -3,7 +3,8 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
3
  // package.json
4
4
  var package_default = {
5
5
  name: "@uipath/admin-vpngateway-tool",
6
- version: "1.1.0",
6
+ license: "MIT",
7
+ version: "1.2.0",
7
8
  description: "CLI plugin for UiPath VPN Gateway management (Hypervisor service).",
8
9
  private: false,
9
10
  repository: {
@@ -72,6 +73,7 @@ import path from "node:path";
72
73
  import { fileURLToPath } from "node:url";
73
74
  import childProcess3 from "node:child_process";
74
75
  import fs5, { constants as fsConstants2 } from "node:fs/promises";
76
+ import { randomUUID } from "node:crypto";
75
77
  import { existsSync } from "node:fs";
76
78
  import * as fs6 from "node:fs/promises";
77
79
  import * as os2 from "node:os";
@@ -823,6 +825,90 @@ class NodeFileSystem {
823
825
  async mkdir(dirPath) {
824
826
  await fs6.mkdir(dirPath, { recursive: true });
825
827
  }
828
+ async acquireLock(lockPath) {
829
+ const canonicalPath = await this.canonicalizeLockTarget(lockPath);
830
+ const lockFile = `${canonicalPath}.lock`;
831
+ const ownerId = randomUUID();
832
+ const start = Date.now();
833
+ while (true) {
834
+ try {
835
+ await fs6.writeFile(lockFile, ownerId, { flag: "wx" });
836
+ return this.createLockRelease(lockFile, ownerId);
837
+ } catch (error) {
838
+ if (!this.hasErrnoCode(error, "EEXIST")) {
839
+ throw error;
840
+ }
841
+ const stats = await fs6.stat(lockFile).catch(() => null);
842
+ if (stats && Date.now() - stats.mtimeMs > LOCK_STALE_MS) {
843
+ const reclaimed = await fs6.rm(lockFile, { force: true }).then(() => true).catch(() => false);
844
+ if (reclaimed)
845
+ continue;
846
+ }
847
+ if (Date.now() - start > LOCK_MAX_WAIT_MS) {
848
+ throw new Error(`ELOCKED: timed out waiting for lock on ${canonicalPath}`);
849
+ }
850
+ await new Promise((resolve2) => setTimeout(resolve2, LOCK_RETRY_MIN_MS + Math.random() * LOCK_RETRY_JITTER_MS));
851
+ }
852
+ }
853
+ }
854
+ async canonicalizeLockTarget(lockPath) {
855
+ const absolute = path2.resolve(lockPath);
856
+ const fullReal = await fs6.realpath(absolute).catch(() => null);
857
+ if (fullReal)
858
+ return fullReal;
859
+ const parent = path2.dirname(absolute);
860
+ const base = path2.basename(absolute);
861
+ const canonicalParent = await fs6.realpath(parent).catch(() => parent);
862
+ return path2.join(canonicalParent, base);
863
+ }
864
+ createLockRelease(lockFile, ownerId) {
865
+ const heartbeatStart = Date.now();
866
+ let heartbeatTimer;
867
+ let stopped = false;
868
+ const stopHeartbeat = () => {
869
+ stopped = true;
870
+ if (heartbeatTimer)
871
+ clearTimeout(heartbeatTimer);
872
+ };
873
+ const scheduleNextHeartbeat = () => {
874
+ if (stopped)
875
+ return;
876
+ if (Date.now() - heartbeatStart >= LOCK_MAX_HOLD_MS) {
877
+ stopped = true;
878
+ return;
879
+ }
880
+ heartbeatTimer = setTimeout(() => {
881
+ runHeartbeat();
882
+ }, LOCK_HEARTBEAT_MS);
883
+ heartbeatTimer.unref?.();
884
+ };
885
+ const runHeartbeat = async () => {
886
+ if (stopped)
887
+ return;
888
+ const current = await fs6.readFile(lockFile, "utf-8").catch(() => null);
889
+ if (stopped)
890
+ return;
891
+ if (current !== ownerId) {
892
+ stopped = true;
893
+ return;
894
+ }
895
+ const now = Date.now() / 1000;
896
+ await fs6.utimes(lockFile, now, now).catch(() => {});
897
+ scheduleNextHeartbeat();
898
+ };
899
+ scheduleNextHeartbeat();
900
+ let released = false;
901
+ return async () => {
902
+ if (released)
903
+ return;
904
+ released = true;
905
+ stopHeartbeat();
906
+ const current = await fs6.readFile(lockFile, "utf-8").catch(() => null);
907
+ if (current === ownerId) {
908
+ await fs6.rm(lockFile, { force: true });
909
+ }
910
+ };
911
+ }
826
912
  async rm(filePath) {
827
913
  await fs6.rm(filePath, { recursive: true, force: true });
828
914
  }
@@ -868,9 +954,18 @@ class NodeFileSystem {
868
954
  }
869
955
  }
870
956
  isEnoent(error) {
871
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
957
+ return this.hasErrnoCode(error, "ENOENT");
958
+ }
959
+ hasErrnoCode(error, code) {
960
+ return typeof error === "object" && error !== null && "code" in error && error.code === code;
872
961
  }
873
962
  }
963
+ var LOCK_HEARTBEAT_MS = 5000;
964
+ var LOCK_STALE_MS = 15000;
965
+ var LOCK_MAX_WAIT_MS = 20000;
966
+ var LOCK_MAX_HOLD_MS = 60000;
967
+ var LOCK_RETRY_MIN_MS = 100;
968
+ var LOCK_RETRY_JITTER_MS = 200;
874
969
  var init_node = __esm(() => {
875
970
  init_open();
876
971
  });
@@ -882,7 +977,7 @@ var init_src = __esm(() => {
882
977
  fsInstance = new NodeFileSystem;
883
978
  });
884
979
  var require_coreipc = __commonJS((exports, module) => {
885
- var __dirname3 = "/Users/alexandru.oltean/github/cli/node_modules/@uipath/coreipc";
980
+ var __dirname3 = "/home/runner/work/cli/cli/node_modules/@uipath/coreipc";
886
981
  /*! For license information please see index.js.LICENSE.txt */
887
982
  (function(e, t) {
888
983
  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();
@@ -18682,6 +18777,135 @@ var require_dist = __commonJS((exports) => {
18682
18777
  exports.RobotProxyConstructor = RobotProxyConstructor;
18683
18778
  __exportStar(require_agent(), exports);
18684
18779
  });
18780
+ var init_server = __esm(() => {
18781
+ init_constants();
18782
+ });
18783
+ var PREFIX = "@uipath/common/";
18784
+ var _g = globalThis;
18785
+ function singleton(ctorOrName) {
18786
+ const name = typeof ctorOrName === "string" ? ctorOrName : ctorOrName.name;
18787
+ const key = Symbol.for(PREFIX + name);
18788
+ return {
18789
+ get(fallback) {
18790
+ return _g[key] ?? fallback;
18791
+ },
18792
+ set(value) {
18793
+ _g[key] = value;
18794
+ },
18795
+ clear() {
18796
+ delete _g[key];
18797
+ },
18798
+ getOrInit(factory, guard) {
18799
+ const existing = _g[key];
18800
+ if (existing != null && typeof existing === "object") {
18801
+ if (!guard || guard(existing)) {
18802
+ return existing;
18803
+ }
18804
+ }
18805
+ const instance = factory();
18806
+ _g[key] = instance;
18807
+ return instance;
18808
+ }
18809
+ };
18810
+ }
18811
+ var USER_AGENT_HEADER = "User-Agent";
18812
+ var sdkUserAgentHostToken = singleton("SdkUserAgentHostToken");
18813
+ function userAgentPatchKey(userAgent) {
18814
+ return Symbol.for(`@uipath/common/sdk-user-agent/${userAgent}`);
18815
+ }
18816
+ function splitUserAgentTokens(value) {
18817
+ return value?.trim().split(/\s+/).filter(Boolean) ?? [];
18818
+ }
18819
+ function appendUserAgentToken(value, userAgent) {
18820
+ const tokens = splitUserAgentTokens(value);
18821
+ const seen = new Set(tokens);
18822
+ for (const token of splitUserAgentTokens(userAgent)) {
18823
+ if (!seen.has(token)) {
18824
+ tokens.push(token);
18825
+ seen.add(token);
18826
+ }
18827
+ }
18828
+ return tokens.join(" ");
18829
+ }
18830
+ function getEffectiveUserAgent(userAgent) {
18831
+ return appendUserAgentToken(sdkUserAgentHostToken.get(), userAgent);
18832
+ }
18833
+ function isHeadersLike(headers) {
18834
+ return typeof headers === "object" && headers !== null && "get" in headers && typeof headers.get === "function" && "set" in headers && typeof headers.set === "function";
18835
+ }
18836
+ function getSdkUserAgentToken(pkg) {
18837
+ const packageName = pkg.name.replace(/^@uipath\//, "");
18838
+ return getEffectiveUserAgent(`${packageName}/${pkg.version}`);
18839
+ }
18840
+ function addSdkUserAgentHeader(headers, userAgent) {
18841
+ const result = { ...headers ?? {} };
18842
+ const effectiveUserAgent = getEffectiveUserAgent(userAgent);
18843
+ const headerName = Object.keys(result).find((key) => key.toLowerCase() === USER_AGENT_HEADER.toLowerCase());
18844
+ if (headerName) {
18845
+ result[headerName] = appendUserAgentToken(result[headerName], effectiveUserAgent);
18846
+ } else {
18847
+ result[USER_AGENT_HEADER] = effectiveUserAgent;
18848
+ }
18849
+ return result;
18850
+ }
18851
+ function withSdkUserAgentHeader(headers, userAgent) {
18852
+ const effectiveUserAgent = getEffectiveUserAgent(userAgent);
18853
+ if (isHeadersLike(headers)) {
18854
+ headers.set(USER_AGENT_HEADER, appendUserAgentToken(headers.get(USER_AGENT_HEADER), effectiveUserAgent));
18855
+ return headers;
18856
+ }
18857
+ if (Array.isArray(headers)) {
18858
+ const result = headers.map((entry) => {
18859
+ const [key, value] = entry;
18860
+ return [key, value];
18861
+ });
18862
+ const headerIndex = result.findIndex(([key]) => key.toLowerCase() === USER_AGENT_HEADER.toLowerCase());
18863
+ if (headerIndex >= 0) {
18864
+ const [key, value] = result[headerIndex];
18865
+ result[headerIndex] = [
18866
+ key,
18867
+ appendUserAgentToken(value, effectiveUserAgent)
18868
+ ];
18869
+ } else {
18870
+ result.push([USER_AGENT_HEADER, effectiveUserAgent]);
18871
+ }
18872
+ return result;
18873
+ }
18874
+ return addSdkUserAgentHeader(typeof headers === "object" && headers !== null ? { ...headers } : {}, effectiveUserAgent);
18875
+ }
18876
+ function withUserAgentInitOverride(initOverrides, userAgent) {
18877
+ return async (requestContext) => {
18878
+ const initWithUserAgent = {
18879
+ ...requestContext.init,
18880
+ headers: withSdkUserAgentHeader(requestContext.init.headers, userAgent)
18881
+ };
18882
+ const override = typeof initOverrides === "function" ? await initOverrides({
18883
+ ...requestContext,
18884
+ init: initWithUserAgent
18885
+ }) : initOverrides;
18886
+ return {
18887
+ ...override ?? {},
18888
+ headers: withSdkUserAgentHeader(override?.headers ?? initWithUserAgent.headers, userAgent)
18889
+ };
18890
+ };
18891
+ }
18892
+ function installSdkUserAgentHeader(BaseApiClass, userAgent) {
18893
+ const prototype = BaseApiClass.prototype;
18894
+ const patchKey = userAgentPatchKey(userAgent);
18895
+ if (prototype[patchKey]) {
18896
+ return;
18897
+ }
18898
+ if (typeof prototype.request !== "function") {
18899
+ throw new Error("Generated BaseAPI request function not found.");
18900
+ }
18901
+ const originalRequest = prototype.request;
18902
+ prototype.request = function requestWithUserAgent(context, initOverrides) {
18903
+ return originalRequest.call(this, context, withUserAgentInitOverride(initOverrides, userAgent));
18904
+ };
18905
+ Object.defineProperty(prototype, patchKey, {
18906
+ value: true
18907
+ });
18908
+ }
18685
18909
  var BASE_PATH = "http://localhost".replace(/\/+$/, "");
18686
18910
 
18687
18911
  class Configuration {
@@ -18930,6 +19154,47 @@ class VoidApiResponse {
18930
19154
  return;
18931
19155
  }
18932
19156
  }
19157
+ var package_default2 = {
19158
+ name: "@uipath/admin-vpngateway-sdk",
19159
+ license: "MIT",
19160
+ version: "1.2.0",
19161
+ description: "SDK for the UiPath Hypervisor VPN Gateway management APIs.",
19162
+ repository: {
19163
+ type: "git",
19164
+ url: "https://github.com/UiPath/cli.git",
19165
+ directory: "packages/admin/vpngateway-sdk"
19166
+ },
19167
+ publishConfig: {
19168
+ registry: "https://npm.pkg.github.com/@uipath"
19169
+ },
19170
+ keywords: ["uipath", "vpn-gateway", "hypervisor", "sdk"],
19171
+ type: "module",
19172
+ main: "./dist/index.js",
19173
+ types: "./dist/src/index.d.ts",
19174
+ exports: {
19175
+ ".": {
19176
+ types: "./dist/src/index.d.ts",
19177
+ default: "./dist/index.js"
19178
+ }
19179
+ },
19180
+ files: ["dist"],
19181
+ private: true,
19182
+ scripts: {
19183
+ build: "bun build ./src/index.ts --outdir dist --format esm --target node && tsc -p tsconfig.build.json --noCheck",
19184
+ generate: "bun run src/scripts/generate-sdk.ts",
19185
+ lint: "biome check ."
19186
+ },
19187
+ devDependencies: {
19188
+ "@openapitools/openapi-generator-cli": "^2.31.1",
19189
+ "@types/node": "^25.5.0",
19190
+ "@uipath/auth": "workspace:*",
19191
+ "@uipath/common": "workspace:*",
19192
+ "@uipath/filesystem": "workspace:*",
19193
+ typescript: "^6.0.2"
19194
+ }
19195
+ };
19196
+ var SDK_USER_AGENT = getSdkUserAgentToken(package_default2);
19197
+ installSdkUserAgentHeader(BaseAPI, SDK_USER_AGENT);
18933
19198
  function FreezingMetadataFromJSON(json) {
18934
19199
  return FreezingMetadataFromJSONTyped(json, false);
18935
19200
  }
@@ -19623,32 +19888,7 @@ class InvalidBaseUrlError extends Error {
19623
19888
  this.name = "InvalidBaseUrlError";
19624
19889
  }
19625
19890
  }
19626
- var DEFAULT_SCOPES = [
19627
- "offline_access",
19628
- "ProcessMining",
19629
- "OrchestratorApiUserAccess",
19630
- "StudioWebBackend",
19631
- "IdentityServerApi",
19632
- "ConnectionService",
19633
- "DataService",
19634
- "DataServiceApiUserAccess",
19635
- "DocumentUnderstanding",
19636
- "EnterpriseContextService",
19637
- "Directory",
19638
- "JamJamApi",
19639
- "LLMGateway",
19640
- "LLMOps",
19641
- "OMS",
19642
- "RCS.FolderAuthorization",
19643
- "RCS.TagsManagement",
19644
- "TestmanagerApiUserAccess",
19645
- "AutomationSolutions",
19646
- "StudioWebTypeCacheService",
19647
- "Docs.GPT.Search",
19648
- "Insights",
19649
- "ReferenceToken",
19650
- "Audit.Read"
19651
- ];
19891
+ var DEFAULT_SCOPES = ["openid", "profile", "offline_access"];
19652
19892
  var normalizeAndValidateBaseUrl = (rawUrl) => {
19653
19893
  let baseUrl = rawUrl;
19654
19894
  if (baseUrl.endsWith("/identity_/")) {
@@ -19698,7 +19938,8 @@ var resolveConfigAsync = async ({
19698
19938
  if (!clientSecret && fileAuth.clientSecret) {
19699
19939
  clientSecret = fileAuth.clientSecret;
19700
19940
  }
19701
- const scopes = customScopes && customScopes.length > 0 ? customScopes : fileAuth.scopes && fileAuth.scopes.length > 0 ? fileAuth.scopes : DEFAULT_SCOPES;
19941
+ const isExternalAppAuth = clientId !== DEFAULT_CLIENT_ID && Boolean(clientSecret);
19942
+ const scopes = customScopes && customScopes.length > 0 ? customScopes : fileAuth.scopes && fileAuth.scopes.length > 0 ? fileAuth.scopes : isExternalAppAuth ? [] : DEFAULT_SCOPES;
19702
19943
  return {
19703
19944
  clientId,
19704
19945
  clientSecret,
@@ -20185,6 +20426,129 @@ function normalizeTokenRefreshFailure() {
20185
20426
  function normalizeTokenRefreshUnavailableFailure() {
20186
20427
  return "token refresh failed before authentication completed";
20187
20428
  }
20429
+ function errorMessage(error) {
20430
+ return error instanceof Error ? error.message : String(error);
20431
+ }
20432
+ function computeExpirationThreshold(ensureTokenValidityMinutes) {
20433
+ return new Date(Date.now() + (ensureTokenValidityMinutes ?? 0) * 60 * 1000);
20434
+ }
20435
+ async function runRefreshLocked(inputs) {
20436
+ const {
20437
+ absolutePath,
20438
+ refreshToken: callerRefreshToken,
20439
+ customAuthority,
20440
+ ensureTokenValidityMinutes,
20441
+ loadEnvFile,
20442
+ saveEnvFile,
20443
+ refreshFn,
20444
+ resolveConfig
20445
+ } = inputs;
20446
+ const expirationThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
20447
+ let fresh;
20448
+ try {
20449
+ fresh = await loadEnvFile({ envPath: absolutePath });
20450
+ } catch (error) {
20451
+ return {
20452
+ kind: "fail",
20453
+ status: {
20454
+ loginStatus: "Refresh Failed",
20455
+ hint: "Could not read the auth file while refreshing. Retry, or run 'uip login' to re-authenticate.",
20456
+ tokenRefresh: {
20457
+ attempted: false,
20458
+ success: false,
20459
+ errorMessage: `auth file read failed: ${errorMessage(error)}`
20460
+ }
20461
+ }
20462
+ };
20463
+ }
20464
+ const freshAccess = fresh.UIPATH_ACCESS_TOKEN;
20465
+ const freshExp = freshAccess ? getTokenExpiration(freshAccess) : undefined;
20466
+ if (freshAccess && freshExp && freshExp > expirationThreshold) {
20467
+ return {
20468
+ kind: "ok",
20469
+ accessToken: freshAccess,
20470
+ refreshToken: fresh.UIPATH_REFRESH_TOKEN ?? callerRefreshToken,
20471
+ expiration: freshExp,
20472
+ tokenRefresh: { attempted: false, success: true }
20473
+ };
20474
+ }
20475
+ const tokenForIdP = fresh.UIPATH_REFRESH_TOKEN ?? callerRefreshToken;
20476
+ let refreshedAccess;
20477
+ let refreshedRefresh;
20478
+ try {
20479
+ const config = await resolveConfig({ customAuthority });
20480
+ const refreshed = await refreshFn({
20481
+ refreshToken: tokenForIdP,
20482
+ tokenEndpoint: config.tokenEndpoint,
20483
+ clientId: config.clientId,
20484
+ expectedAuthority: customAuthority
20485
+ });
20486
+ refreshedAccess = refreshed.accessToken;
20487
+ refreshedRefresh = refreshed.refreshToken;
20488
+ } catch (error) {
20489
+ const isOAuthFailure = isTokenRefreshOAuthFailure(error);
20490
+ 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.";
20491
+ const message = isOAuthFailure ? normalizeTokenRefreshFailure() : normalizeTokenRefreshUnavailableFailure();
20492
+ return {
20493
+ kind: "fail",
20494
+ status: {
20495
+ loginStatus: "Refresh Failed",
20496
+ hint,
20497
+ tokenRefresh: {
20498
+ attempted: true,
20499
+ success: false,
20500
+ errorMessage: message
20501
+ }
20502
+ }
20503
+ };
20504
+ }
20505
+ const refreshedExp = getTokenExpiration(refreshedAccess);
20506
+ if (!refreshedExp || refreshedExp <= new Date) {
20507
+ return {
20508
+ kind: "fail",
20509
+ status: {
20510
+ loginStatus: "Refresh Failed",
20511
+ hint: "The identity server returned an unusable token. Run 'uip login' to re-authenticate.",
20512
+ tokenRefresh: {
20513
+ attempted: true,
20514
+ success: false,
20515
+ errorMessage: "refreshed token has no valid expiration claim"
20516
+ }
20517
+ }
20518
+ };
20519
+ }
20520
+ try {
20521
+ await saveEnvFile({
20522
+ envPath: absolutePath,
20523
+ data: {
20524
+ UIPATH_ACCESS_TOKEN: refreshedAccess,
20525
+ UIPATH_REFRESH_TOKEN: refreshedRefresh
20526
+ },
20527
+ merge: true
20528
+ });
20529
+ return {
20530
+ kind: "ok",
20531
+ accessToken: refreshedAccess,
20532
+ refreshToken: refreshedRefresh,
20533
+ expiration: refreshedExp,
20534
+ tokenRefresh: { attempted: true, success: true }
20535
+ };
20536
+ } catch (error) {
20537
+ const msg = errorMessage(error);
20538
+ return {
20539
+ kind: "ok",
20540
+ accessToken: refreshedAccess,
20541
+ refreshToken: refreshedRefresh,
20542
+ expiration: refreshedExp,
20543
+ 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.`,
20544
+ tokenRefresh: {
20545
+ attempted: true,
20546
+ success: true,
20547
+ errorMessage: `persistence failed: ${msg}`
20548
+ }
20549
+ };
20550
+ }
20551
+ }
20188
20552
  var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
20189
20553
  const {
20190
20554
  resolveEnvFilePath = resolveEnvFilePathAsync,
@@ -20259,73 +20623,103 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
20259
20623
  let refreshToken = credentials.UIPATH_REFRESH_TOKEN;
20260
20624
  let expiration = getTokenExpiration(accessToken);
20261
20625
  let persistenceWarning;
20626
+ let lockReleaseFailed = false;
20262
20627
  let tokenRefresh;
20263
- const expirationThreshold = new Date(Date.now() + (ensureTokenValidityMinutes ?? 0) * 60 * 1000);
20264
- if (expiration && expiration <= expirationThreshold && refreshToken) {
20265
- let refreshedAccess;
20266
- let refreshedRefresh;
20628
+ const outerThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
20629
+ const tryGlobalCredsHint = async () => {
20630
+ const fs7 = getFs();
20631
+ const globalPath = fs7.path.join(fs7.env.homedir(), envFilePath);
20632
+ if (absolutePath === globalPath)
20633
+ return;
20634
+ if (!await fs7.exists(globalPath))
20635
+ return;
20267
20636
  try {
20268
- const config = await resolveConfig({
20269
- customAuthority: credentials.UIPATH_URL
20270
- });
20271
- const refreshed = await refreshTokenFn({
20272
- refreshToken,
20273
- tokenEndpoint: config.tokenEndpoint,
20274
- clientId: config.clientId,
20275
- expectedAuthority: credentials.UIPATH_URL
20276
- });
20277
- refreshedAccess = refreshed.accessToken;
20278
- refreshedRefresh = refreshed.refreshToken;
20279
- } catch (error) {
20280
- const isOAuthFailure = isTokenRefreshOAuthFailure(error);
20281
- 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.";
20282
- const errorMessage = isOAuthFailure ? normalizeTokenRefreshFailure() : normalizeTokenRefreshUnavailableFailure();
20283
- return {
20284
- loginStatus: "Refresh Failed",
20285
- hint,
20286
- tokenRefresh: {
20287
- attempted: true,
20288
- success: false,
20289
- errorMessage
20290
- }
20291
- };
20637
+ const globalCreds = await loadEnvFile({ envPath: globalPath });
20638
+ if (!globalCreds.UIPATH_ACCESS_TOKEN)
20639
+ return;
20640
+ const globalExp = getTokenExpiration(globalCreds.UIPATH_ACCESS_TOKEN);
20641
+ if (globalExp && globalExp <= new Date)
20642
+ return;
20643
+ 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.`;
20644
+ } catch {
20645
+ return;
20292
20646
  }
20293
- const refreshedExp = getTokenExpiration(refreshedAccess);
20294
- if (!refreshedExp || refreshedExp <= new Date) {
20647
+ };
20648
+ if (expiration && expiration <= outerThreshold && refreshToken) {
20649
+ let release;
20650
+ try {
20651
+ release = await getFs().acquireLock(absolutePath);
20652
+ } catch (error) {
20653
+ const msg = errorMessage(error);
20654
+ const globalHint = await tryGlobalCredsHint();
20655
+ if (globalHint) {
20656
+ return {
20657
+ loginStatus: "Expired",
20658
+ accessToken,
20659
+ refreshToken,
20660
+ baseUrl: credentials.UIPATH_URL,
20661
+ organizationName: credentials.UIPATH_ORGANIZATION_NAME,
20662
+ organizationId: credentials.UIPATH_ORGANIZATION_ID,
20663
+ tenantName: credentials.UIPATH_TENANT_NAME,
20664
+ tenantId: credentials.UIPATH_TENANT_ID,
20665
+ expiration,
20666
+ source: "file",
20667
+ hint: globalHint,
20668
+ tokenRefresh: {
20669
+ attempted: false,
20670
+ success: false,
20671
+ errorMessage: `lock acquisition failed: ${msg}`
20672
+ }
20673
+ };
20674
+ }
20295
20675
  return {
20296
20676
  loginStatus: "Refresh Failed",
20297
- hint: "The identity server returned an unusable token. Run 'uip login' to re-authenticate.",
20677
+ 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.",
20298
20678
  tokenRefresh: {
20299
- attempted: true,
20679
+ attempted: false,
20300
20680
  success: false,
20301
- errorMessage: "refreshed token has no valid expiration claim"
20681
+ errorMessage: `lock acquisition failed: ${msg}`
20302
20682
  }
20303
20683
  };
20304
20684
  }
20305
- accessToken = refreshedAccess;
20306
- refreshToken = refreshedRefresh;
20307
- expiration = refreshedExp;
20685
+ let lockedFailure;
20308
20686
  try {
20309
- await saveEnvFile({
20310
- envPath: absolutePath,
20311
- data: {
20312
- UIPATH_ACCESS_TOKEN: accessToken,
20313
- UIPATH_REFRESH_TOKEN: refreshToken
20314
- },
20315
- merge: true
20687
+ const outcome = await runRefreshLocked({
20688
+ absolutePath,
20689
+ refreshToken,
20690
+ customAuthority: credentials.UIPATH_URL,
20691
+ ensureTokenValidityMinutes,
20692
+ loadEnvFile,
20693
+ saveEnvFile,
20694
+ refreshFn: refreshTokenFn,
20695
+ resolveConfig
20316
20696
  });
20317
- tokenRefresh = {
20318
- attempted: true,
20319
- success: true
20320
- };
20321
- } catch (error) {
20322
- const msg = error instanceof Error ? error.message : String(error);
20323
- 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.`;
20324
- tokenRefresh = {
20325
- attempted: true,
20326
- success: true,
20327
- errorMessage: `persistence failed: ${msg}`
20328
- };
20697
+ if (outcome.kind === "fail") {
20698
+ lockedFailure = outcome.status;
20699
+ } else {
20700
+ accessToken = outcome.accessToken;
20701
+ refreshToken = outcome.refreshToken;
20702
+ expiration = outcome.expiration;
20703
+ tokenRefresh = outcome.tokenRefresh;
20704
+ if (outcome.persistenceWarning) {
20705
+ persistenceWarning = outcome.persistenceWarning;
20706
+ }
20707
+ }
20708
+ } finally {
20709
+ try {
20710
+ await release();
20711
+ } catch {
20712
+ lockReleaseFailed = true;
20713
+ }
20714
+ }
20715
+ if (lockedFailure) {
20716
+ const globalHint = await tryGlobalCredsHint();
20717
+ const base = globalHint ? {
20718
+ ...lockedFailure,
20719
+ loginStatus: "Expired",
20720
+ hint: globalHint
20721
+ } : lockedFailure;
20722
+ return lockReleaseFailed ? { ...base, lockReleaseFailed: true } : base;
20329
20723
  }
20330
20724
  }
20331
20725
  const result = {
@@ -20340,23 +20734,13 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
20340
20734
  expiration,
20341
20735
  source: "file",
20342
20736
  ...persistenceWarning ? { hint: persistenceWarning, persistenceFailed: true } : {},
20737
+ ...lockReleaseFailed ? { lockReleaseFailed: true } : {},
20343
20738
  ...tokenRefresh ? { tokenRefresh } : {}
20344
20739
  };
20345
20740
  if (result.loginStatus === "Expired") {
20346
- const fs7 = getFs();
20347
- const globalPath = fs7.path.join(fs7.env.homedir(), envFilePath);
20348
- if (absolutePath !== globalPath && await fs7.exists(globalPath)) {
20349
- try {
20350
- const globalCreds = await loadEnvFile({
20351
- envPath: globalPath
20352
- });
20353
- if (globalCreds.UIPATH_ACCESS_TOKEN) {
20354
- const globalExp = getTokenExpiration(globalCreds.UIPATH_ACCESS_TOKEN);
20355
- if (!globalExp || globalExp > new Date) {
20356
- 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.`;
20357
- }
20358
- }
20359
- } catch {}
20741
+ const globalHint = await tryGlobalCredsHint();
20742
+ if (globalHint) {
20743
+ result.hint = globalHint;
20360
20744
  }
20361
20745
  }
20362
20746
  return result;
@@ -20371,6 +20755,7 @@ var getLoginStatusAsync = async (options = {}) => {
20371
20755
  };
20372
20756
  init_src();
20373
20757
  init_src();
20758
+ init_server();
20374
20759
  async function resolveConfig(options) {
20375
20760
  const status = await getLoginStatusAsync();
20376
20761
  if (status.loginStatus !== "Logged in" || !status.baseUrl || !status.accessToken) {
@@ -20388,10 +20773,10 @@ async function resolveConfig(options) {
20388
20773
  return {
20389
20774
  config: new Configuration({
20390
20775
  basePath,
20391
- headers: {
20776
+ headers: addSdkUserAgentHeader({
20392
20777
  Authorization: `Bearer ${bearerToken}`,
20393
20778
  "x-uipath-source": "UiPath.CLI"
20394
- }
20779
+ }, SDK_USER_AGENT)
20395
20780
  }),
20396
20781
  organizationId: status.organizationId,
20397
20782
  tenantName: tenant
@@ -20407,6 +20792,7 @@ async function createApiClient(ApiClass, options) {
20407
20792
  }
20408
20793
 
20409
20794
  // ../../filesystem/src/node.ts
20795
+ import { randomUUID as randomUUID2 } from "node:crypto";
20410
20796
  import { existsSync as existsSync2 } from "node:fs";
20411
20797
  import * as fs13 from "node:fs/promises";
20412
20798
  import * as os5 from "node:os";
@@ -21023,6 +21409,13 @@ defineLazyProperty2(apps2, "safari", () => detectPlatformBinary2({
21023
21409
  var open_default2 = open2;
21024
21410
 
21025
21411
  // ../../filesystem/src/node.ts
21412
+ var LOCK_HEARTBEAT_MS2 = 5000;
21413
+ var LOCK_STALE_MS2 = 15000;
21414
+ var LOCK_MAX_WAIT_MS2 = 20000;
21415
+ var LOCK_MAX_HOLD_MS2 = 60000;
21416
+ var LOCK_RETRY_MIN_MS2 = 100;
21417
+ var LOCK_RETRY_JITTER_MS2 = 200;
21418
+
21026
21419
  class NodeFileSystem2 {
21027
21420
  path = {
21028
21421
  join: path5.join,
@@ -21099,6 +21492,90 @@ class NodeFileSystem2 {
21099
21492
  async mkdir(dirPath) {
21100
21493
  await fs13.mkdir(dirPath, { recursive: true });
21101
21494
  }
21495
+ async acquireLock(lockPath) {
21496
+ const canonicalPath = await this.canonicalizeLockTarget(lockPath);
21497
+ const lockFile = `${canonicalPath}.lock`;
21498
+ const ownerId = randomUUID2();
21499
+ const start = Date.now();
21500
+ while (true) {
21501
+ try {
21502
+ await fs13.writeFile(lockFile, ownerId, { flag: "wx" });
21503
+ return this.createLockRelease(lockFile, ownerId);
21504
+ } catch (error) {
21505
+ if (!this.hasErrnoCode(error, "EEXIST")) {
21506
+ throw error;
21507
+ }
21508
+ const stats = await fs13.stat(lockFile).catch(() => null);
21509
+ if (stats && Date.now() - stats.mtimeMs > LOCK_STALE_MS2) {
21510
+ const reclaimed = await fs13.rm(lockFile, { force: true }).then(() => true).catch(() => false);
21511
+ if (reclaimed)
21512
+ continue;
21513
+ }
21514
+ if (Date.now() - start > LOCK_MAX_WAIT_MS2) {
21515
+ throw new Error(`ELOCKED: timed out waiting for lock on ${canonicalPath}`);
21516
+ }
21517
+ await new Promise((resolve3) => setTimeout(resolve3, LOCK_RETRY_MIN_MS2 + Math.random() * LOCK_RETRY_JITTER_MS2));
21518
+ }
21519
+ }
21520
+ }
21521
+ async canonicalizeLockTarget(lockPath) {
21522
+ const absolute = path5.resolve(lockPath);
21523
+ const fullReal = await fs13.realpath(absolute).catch(() => null);
21524
+ if (fullReal)
21525
+ return fullReal;
21526
+ const parent = path5.dirname(absolute);
21527
+ const base = path5.basename(absolute);
21528
+ const canonicalParent = await fs13.realpath(parent).catch(() => parent);
21529
+ return path5.join(canonicalParent, base);
21530
+ }
21531
+ createLockRelease(lockFile, ownerId) {
21532
+ const heartbeatStart = Date.now();
21533
+ let heartbeatTimer;
21534
+ let stopped = false;
21535
+ const stopHeartbeat = () => {
21536
+ stopped = true;
21537
+ if (heartbeatTimer)
21538
+ clearTimeout(heartbeatTimer);
21539
+ };
21540
+ const scheduleNextHeartbeat = () => {
21541
+ if (stopped)
21542
+ return;
21543
+ if (Date.now() - heartbeatStart >= LOCK_MAX_HOLD_MS2) {
21544
+ stopped = true;
21545
+ return;
21546
+ }
21547
+ heartbeatTimer = setTimeout(() => {
21548
+ runHeartbeat();
21549
+ }, LOCK_HEARTBEAT_MS2);
21550
+ heartbeatTimer.unref?.();
21551
+ };
21552
+ const runHeartbeat = async () => {
21553
+ if (stopped)
21554
+ return;
21555
+ const current = await fs13.readFile(lockFile, "utf-8").catch(() => null);
21556
+ if (stopped)
21557
+ return;
21558
+ if (current !== ownerId) {
21559
+ stopped = true;
21560
+ return;
21561
+ }
21562
+ const now = Date.now() / 1000;
21563
+ await fs13.utimes(lockFile, now, now).catch(() => {});
21564
+ scheduleNextHeartbeat();
21565
+ };
21566
+ scheduleNextHeartbeat();
21567
+ let released = false;
21568
+ return async () => {
21569
+ if (released)
21570
+ return;
21571
+ released = true;
21572
+ stopHeartbeat();
21573
+ const current = await fs13.readFile(lockFile, "utf-8").catch(() => null);
21574
+ if (current === ownerId) {
21575
+ await fs13.rm(lockFile, { force: true });
21576
+ }
21577
+ };
21578
+ }
21102
21579
  async rm(filePath) {
21103
21580
  await fs13.rm(filePath, { recursive: true, force: true });
21104
21581
  }
@@ -21144,7 +21621,10 @@ class NodeFileSystem2 {
21144
21621
  }
21145
21622
  }
21146
21623
  isEnoent(error) {
21147
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
21624
+ return this.hasErrnoCode(error, "ENOENT");
21625
+ }
21626
+ hasErrnoCode(error, code) {
21627
+ return typeof error === "object" && error !== null && "code" in error && error.code === code;
21148
21628
  }
21149
21629
  }
21150
21630
 
@@ -21286,10 +21766,15 @@ async function extractErrorDetails(error, options) {
21286
21766
  }
21287
21767
  if (parsedBody?.errorCode && typeof parsedBody.errorCode === "string") {
21288
21768
  context.errorCode = parsedBody.errorCode;
21769
+ } else if (parsedBody?.code && typeof parsedBody.code === "string") {
21770
+ context.errorCode = parsedBody.code;
21289
21771
  }
21290
21772
  if (parsedBody?.requestId && typeof parsedBody.requestId === "string") {
21291
21773
  context.requestId = parsedBody.requestId;
21292
21774
  }
21775
+ if (parsedBody?.traceId && typeof parsedBody.traceId === "string") {
21776
+ context.traceId = parsedBody.traceId;
21777
+ }
21293
21778
  if (status === 429) {
21294
21779
  const resp = response;
21295
21780
  const headersObj = resp?.headers;
@@ -21309,7 +21794,35 @@ async function extractErrorDetails(error, options) {
21309
21794
  }
21310
21795
  }
21311
21796
  const hasContext = Object.keys(context).length > 0;
21312
- return { result, message, details, ...hasContext ? { context } : {} };
21797
+ let parsedErrors;
21798
+ if (parsedBody?.errors && typeof parsedBody.errors === "object") {
21799
+ const errors = {};
21800
+ for (const [field, raw] of Object.entries(parsedBody.errors)) {
21801
+ if (Array.isArray(raw)) {
21802
+ const messages = raw.map((entry) => {
21803
+ if (typeof entry === "string")
21804
+ return entry;
21805
+ if (entry && typeof entry === "object" && typeof entry.message === "string") {
21806
+ return entry.message;
21807
+ }
21808
+ return String(entry);
21809
+ }).filter(Boolean);
21810
+ if (messages.length > 0)
21811
+ errors[field] = messages;
21812
+ } else if (typeof raw === "string") {
21813
+ errors[field] = [raw];
21814
+ }
21815
+ }
21816
+ if (Object.keys(errors).length > 0)
21817
+ parsedErrors = errors;
21818
+ }
21819
+ return {
21820
+ result,
21821
+ message,
21822
+ details,
21823
+ ...hasContext ? { context } : {},
21824
+ ...parsedErrors ? { parsedErrors } : {}
21825
+ };
21313
21826
  }
21314
21827
  // ../../common/src/command-examples.ts
21315
21828
  import { Command } from "commander";
@@ -21319,30 +21832,30 @@ Command.prototype.examples = function(examples) {
21319
21832
  return this;
21320
21833
  };
21321
21834
  // ../../common/src/singleton.ts
21322
- var PREFIX = "@uipath/common/";
21323
- var _g = globalThis;
21324
- function singleton(ctorOrName) {
21835
+ var PREFIX2 = "@uipath/common/";
21836
+ var _g2 = globalThis;
21837
+ function singleton2(ctorOrName) {
21325
21838
  const name = typeof ctorOrName === "string" ? ctorOrName : ctorOrName.name;
21326
- const key = Symbol.for(PREFIX + name);
21839
+ const key = Symbol.for(PREFIX2 + name);
21327
21840
  return {
21328
21841
  get(fallback) {
21329
- return _g[key] ?? fallback;
21842
+ return _g2[key] ?? fallback;
21330
21843
  },
21331
21844
  set(value) {
21332
- _g[key] = value;
21845
+ _g2[key] = value;
21333
21846
  },
21334
21847
  clear() {
21335
- delete _g[key];
21848
+ delete _g2[key];
21336
21849
  },
21337
21850
  getOrInit(factory, guard) {
21338
- const existing = _g[key];
21851
+ const existing = _g2[key];
21339
21852
  if (existing != null && typeof existing === "object") {
21340
21853
  if (!guard || guard(existing)) {
21341
21854
  return existing;
21342
21855
  }
21343
21856
  }
21344
21857
  const instance = factory();
21345
- _g[key] = instance;
21858
+ _g2[key] = instance;
21346
21859
  return instance;
21347
21860
  }
21348
21861
  };
@@ -21361,8 +21874,8 @@ function createStorage() {
21361
21874
  }
21362
21875
  return new mod.AsyncLocalStorage;
21363
21876
  }
21364
- var storageSingleton = singleton("OutputStorage");
21365
- var sinkSlot = singleton("OutputSink");
21877
+ var storageSingleton = singleton2("OutputStorage");
21878
+ var sinkSlot = singleton2("OutputSink");
21366
21879
  var outputStorage = storageSingleton.getOrInit(createStorage, (v) => ("getStore" in v));
21367
21880
  var CONSOLE_FALLBACK = {
21368
21881
  writeOut: (str) => process.stdout.write(str),
@@ -21380,8 +21893,8 @@ function getOutputSink() {
21380
21893
  // ../../common/src/completer.ts
21381
21894
  var COMPLETER_SYMBOL = Symbol.for("@uipath/common/completer");
21382
21895
  // ../../common/src/console-guard.ts
21383
- var guardInstalledSlot = singleton("ConsoleGuardInstalled");
21384
- var savedOriginalsSlot = singleton("ConsoleGuardOriginals");
21896
+ var guardInstalledSlot = singleton2("ConsoleGuardInstalled");
21897
+ var savedOriginalsSlot = singleton2("ConsoleGuardOriginals");
21385
21898
  // ../../common/src/constants.ts
21386
21899
  var DEFAULT_AUTH_TIMEOUT_MS2 = 5 * 60 * 1000;
21387
21900
  // ../../common/src/error-instructions.ts
@@ -26035,7 +26548,7 @@ var safeLoadAll = renamed("safeLoadAll", "loadAll");
26035
26548
  var safeDump = renamed("safeDump", "dump");
26036
26549
 
26037
26550
  // ../../common/src/logger.ts
26038
- var logFilePathSlot = singleton("logFilePath");
26551
+ var logFilePathSlot = singleton2("logFilePath");
26039
26552
  function setGlobalLogFilePath(path4) {
26040
26553
  logFilePathSlot.set(path4);
26041
26554
  }
@@ -26219,16 +26732,16 @@ class SimpleLogger {
26219
26732
  }
26220
26733
  };
26221
26734
  }
26222
- var loggerSingleton = singleton(SimpleLogger);
26735
+ var loggerSingleton = singleton2(SimpleLogger);
26223
26736
  var logger = SimpleLogger.getInstance();
26224
26737
  function getLogFilePath() {
26225
26738
  return logger.getLogFilePath();
26226
26739
  }
26227
26740
 
26228
26741
  // ../../common/src/output-format-context.ts
26229
- var formatSlot = singleton("OutputFormat");
26230
- var formatExplicitSlot = singleton("OutputFormatExplicit");
26231
- var filterSlot = singleton("OutputFilter");
26742
+ var formatSlot = singleton2("OutputFormat");
26743
+ var formatExplicitSlot = singleton2("OutputFormatExplicit");
26744
+ var filterSlot = singleton2("OutputFilter");
26232
26745
  function getOutputFormat() {
26233
26746
  return formatSlot.get("json");
26234
26747
  }
@@ -26406,11 +26919,11 @@ class TelemetryService {
26406
26919
  }
26407
26920
  }
26408
26921
  // ../../common/src/telemetry/node-appinsights-telemetry-provider.ts
26409
- var telemetryPropsSlot = singleton("TelemetryDefaultProps");
26410
- var providerSlot = singleton("TelemetryProvider");
26922
+ var telemetryPropsSlot = singleton2("TelemetryDefaultProps");
26923
+ var providerSlot = singleton2("TelemetryProvider");
26411
26924
 
26412
26925
  // ../../common/src/telemetry/telemetry-init.ts
26413
- var telemetryInstanceSlot = singleton("TelemetryService");
26926
+ var telemetryInstanceSlot = singleton2("TelemetryService");
26414
26927
  var DEFAULT_AI_CONNECTION_STRING = atob("SW5zdHJ1bWVudGF0aW9uS2V5PTliZDM3NDgyLTgxMGUtNDQyYS1hYWE2LWQzOGVmNjVjNjY3NDtJbmdlc3Rpb25FbmRwb2ludD1odHRwczovL3dlc3RldXJvcGUtNS5pbi5hcHBsaWNhdGlvbmluc2lnaHRzLmF6dXJlLmNvbS87TGl2ZUVuZHBvaW50PWh0dHBzOi8vd2VzdGV1cm9wZS5saXZlZGlhZ25vc3RpY3MubW9uaXRvci5henVyZS5jb20vO0FwcGxpY2F0aW9uSWQ9MzU2OTdlZjEtOGJkMC00ZjE5LWEyN2MtZDg3Y2NhYzY2ZDJj");
26415
26928
  function getGlobalTelemetryInstance() {
26416
26929
  const existing = telemetryInstanceSlot.get();
@@ -26479,6 +26992,60 @@ function escapeNonAscii(jsonText) {
26479
26992
  function needsAsciiSafeJson(sink) {
26480
26993
  return process.platform === "win32" && !sink.capabilities.isInteractive;
26481
26994
  }
26995
+ function isPlainRecord(value) {
26996
+ if (value === null || typeof value !== "object")
26997
+ return false;
26998
+ const prototype = Object.getPrototypeOf(value);
26999
+ return prototype === Object.prototype || prototype === null;
27000
+ }
27001
+ function toLowerCamelCaseKey(key) {
27002
+ if (!key)
27003
+ return key;
27004
+ if (/[_\-\s]/.test(key)) {
27005
+ const [firstPart, ...restParts] = key.split(/[_\-\s]+/).filter(Boolean);
27006
+ if (!firstPart)
27007
+ return key;
27008
+ return [
27009
+ toLowerCamelCaseSimpleKey(firstPart),
27010
+ ...restParts.map((part) => {
27011
+ const normalized = toLowerCamelCaseSimpleKey(part);
27012
+ return normalized.charAt(0).toUpperCase() + normalized.slice(1);
27013
+ })
27014
+ ].join("");
27015
+ }
27016
+ return toLowerCamelCaseSimpleKey(key);
27017
+ }
27018
+ function toLowerCamelCaseSimpleKey(key) {
27019
+ if (/^[A-Z0-9]+$/.test(key))
27020
+ return key.toLowerCase();
27021
+ return key.replace(/^[A-Z]+(?=[A-Z][a-z]|\d|$)|^[A-Z]/, (match) => match.toLowerCase());
27022
+ }
27023
+ function toPascalCaseKey(key) {
27024
+ const lowerCamelKey = toLowerCamelCaseKey(key);
27025
+ return lowerCamelKey ? lowerCamelKey.charAt(0).toUpperCase() + lowerCamelKey.slice(1) : lowerCamelKey;
27026
+ }
27027
+ function toPascalCaseData(value) {
27028
+ if (Array.isArray(value))
27029
+ return value.map(toPascalCaseData);
27030
+ if (!isPlainRecord(value))
27031
+ return value;
27032
+ const result = {};
27033
+ for (const [key, nestedValue] of Object.entries(value)) {
27034
+ result[toPascalCaseKey(key)] = toPascalCaseData(nestedValue);
27035
+ }
27036
+ return result;
27037
+ }
27038
+ function normalizeDataKeys(data) {
27039
+ return toPascalCaseData(data);
27040
+ }
27041
+ function normalizeOutputKeys(data) {
27042
+ const result = {};
27043
+ for (const [key, value] of Object.entries(data)) {
27044
+ const pascalKey = toPascalCaseKey(key);
27045
+ result[pascalKey] = pascalKey === "Data" ? value : toPascalCaseData(value);
27046
+ }
27047
+ return result;
27048
+ }
26482
27049
  function printOutput(data, format = "json", logFn, asciiSafe = false) {
26483
27050
  if (!data) {
26484
27051
  logFn("Empty response object. No data to display.");
@@ -26541,7 +27108,7 @@ function wrapText(text, width) {
26541
27108
  function printTable(data, logFn, externalLogValue) {
26542
27109
  if (data.length === 0)
26543
27110
  return;
26544
- const keys = Object.keys(data[0]).filter((key) => key !== "Code" && key !== "Log");
27111
+ const keys = Object.keys(data[0]).filter((key) => !["code", "log"].includes(key.toLowerCase()));
26545
27112
  const maxWidths = keys.map((key) => Math.max(key.length, ...data.map((item) => cellToString(item[key]).length)));
26546
27113
  const header = keys.map((key, i2) => key.padEnd(maxWidths[i2])).join(" | ");
26547
27114
  logFn(header);
@@ -26556,7 +27123,7 @@ function printTable(data, logFn, externalLogValue) {
26556
27123
  }
26557
27124
  }
26558
27125
  function printVerticalTable(data, logFn = console.log, externalLogValue) {
26559
- const keys = Object.keys(data).filter((key) => key !== "Code" && key !== "Log");
27126
+ const keys = Object.keys(data).filter((key) => !["code", "log"].includes(key.toLowerCase()));
26560
27127
  if (keys.length === 0)
26561
27128
  return;
26562
27129
  const maxKeyWidth = Math.max(...keys.map((key) => key.length));
@@ -26572,7 +27139,7 @@ function printVerticalTable(data, logFn = console.log, externalLogValue) {
26572
27139
  function printResizableTable(data, logFn = console.log, externalLogValue) {
26573
27140
  if (data.length === 0)
26574
27141
  return;
26575
- const keys = Object.keys(data[0]).filter((key) => key !== "Code" && key !== "Log");
27142
+ const keys = Object.keys(data[0]).filter((key) => !["code", "log"].includes(key.toLowerCase()));
26576
27143
  if (keys.length === 0)
26577
27144
  return;
26578
27145
  if (!process.stdout.isTTY) {
@@ -26648,8 +27215,26 @@ function printResizableTable(data, logFn = console.log, externalLogValue) {
26648
27215
  function toYaml(data) {
26649
27216
  return dump(data);
26650
27217
  }
27218
+ class FilterEvaluationError extends Error {
27219
+ __brand = "FilterEvaluationError";
27220
+ filter;
27221
+ instructions;
27222
+ result = RESULTS.ValidationError;
27223
+ constructor(filter, cause) {
27224
+ const underlying = cause instanceof Error ? cause.message : String(cause);
27225
+ super(`Filter '${filter}' failed to evaluate: ${underlying}`);
27226
+ this.name = "FilterEvaluationError";
27227
+ this.filter = filter;
27228
+ 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(@)'.";
27229
+ }
27230
+ }
26651
27231
  function applyFilter(data, filter) {
26652
- const result = search(data, filter);
27232
+ let result;
27233
+ try {
27234
+ result = search(data, filter);
27235
+ } catch (err) {
27236
+ throw new FilterEvaluationError(filter, err);
27237
+ }
26653
27238
  if (result == null)
26654
27239
  return [];
26655
27240
  if (Array.isArray(result)) {
@@ -26666,13 +27251,18 @@ function applyFilter(data, filter) {
26666
27251
  }
26667
27252
  var OutputFormatter;
26668
27253
  ((OutputFormatter) => {
26669
- function success(data) {
27254
+ function success(data, options) {
26670
27255
  data.Log ??= getLogFilePath() || undefined;
27256
+ const normalize = !options?.preserveDataKeys;
27257
+ if (normalize) {
27258
+ data.Data = normalizeDataKeys(data.Data);
27259
+ }
26671
27260
  const filter = getOutputFilter();
26672
27261
  if (filter) {
26673
- data.Data = applyFilter(data.Data, filter);
27262
+ const filtered = applyFilter(data.Data, filter);
27263
+ data.Data = normalize ? normalizeDataKeys(filtered) : filtered;
26674
27264
  }
26675
- logOutput(data, getOutputFormat());
27265
+ logOutput(normalizeOutputKeys(data), getOutputFormat());
26676
27266
  }
26677
27267
  OutputFormatter.success = success;
26678
27268
  function error(data) {
@@ -26682,7 +27272,7 @@ var OutputFormatter;
26682
27272
  result: data.Result,
26683
27273
  message: data.Message
26684
27274
  });
26685
- logOutput(data, getOutputFormat());
27275
+ logOutput(normalizeOutputKeys(data), getOutputFormat());
26686
27276
  }
26687
27277
  OutputFormatter.error = error;
26688
27278
  function emitList(code, items, opts) {
@@ -26703,13 +27293,14 @@ var OutputFormatter;
26703
27293
  function log(data) {
26704
27294
  const format = getOutputFormat();
26705
27295
  const sink = getOutputSink();
27296
+ const normalized = toPascalCaseData(data);
26706
27297
  if (format === "json") {
26707
- const json2 = JSON.stringify(data);
27298
+ const json2 = JSON.stringify(normalized);
26708
27299
  const safe = needsAsciiSafeJson(sink) ? escapeNonAscii(json2) : json2;
26709
27300
  sink.writeErr(`${safe}
26710
27301
  `);
26711
27302
  } else {
26712
- for (const [key, value] of Object.entries(data)) {
27303
+ for (const [key, value] of Object.entries(normalized)) {
26713
27304
  sink.writeErr(`${key}: ${value}
26714
27305
  `);
26715
27306
  }
@@ -26718,12 +27309,16 @@ var OutputFormatter;
26718
27309
  OutputFormatter.log = log;
26719
27310
  function formatToString(data) {
26720
27311
  const filter = getOutputFilter();
26721
- if (filter && "Data" in data && data.Data != null) {
26722
- data.Data = applyFilter(data.Data, filter);
27312
+ if ("Data" in data && data.Data != null) {
27313
+ data.Data = normalizeDataKeys(data.Data);
27314
+ if (filter) {
27315
+ data.Data = normalizeDataKeys(applyFilter(data.Data, filter));
27316
+ }
26723
27317
  }
27318
+ const output = normalizeOutputKeys(data);
26724
27319
  const lines = [];
26725
27320
  const sink = getOutputSink();
26726
- printOutput(data, getOutputFormat(), (msg) => {
27321
+ printOutput(output, getOutputFormat(), (msg) => {
26727
27322
  lines.push(msg);
26728
27323
  }, needsAsciiSafeJson(sink));
26729
27324
  return lines.join(`
@@ -28138,6 +28733,22 @@ JSONPath.prototype.vm = vm;
28138
28733
  import { Option } from "commander";
28139
28734
  // ../../common/src/option-validators.ts
28140
28735
  import { InvalidArgumentError } from "commander";
28736
+ // ../../common/src/polling/types.ts
28737
+ var PollOutcome = {
28738
+ Completed: "completed",
28739
+ Timeout: "timeout",
28740
+ Interrupted: "interrupted",
28741
+ Aborted: "aborted",
28742
+ Failed: "failed"
28743
+ };
28744
+
28745
+ // ../../common/src/polling/poll-failure-mapping.ts
28746
+ var REASON_BY_OUTCOME = {
28747
+ [PollOutcome.Timeout]: "poll_timeout",
28748
+ [PollOutcome.Failed]: "poll_failed",
28749
+ [PollOutcome.Interrupted]: "poll_failed",
28750
+ [PollOutcome.Aborted]: "poll_aborted"
28751
+ };
28141
28752
  // ../../common/src/polling/terminal-statuses.ts
28142
28753
  var TERMINAL_STATUSES = new Set([
28143
28754
  "completed",
@@ -28165,8 +28776,10 @@ var ScreenLogger;
28165
28776
  }
28166
28777
  ScreenLogger.progress = progress;
28167
28778
  })(ScreenLogger ||= {});
28779
+ // ../../common/src/sdk-user-agent.ts
28780
+ var sdkUserAgentHostToken2 = singleton2("SdkUserAgentHostToken");
28168
28781
  // ../../common/src/tool-provider.ts
28169
- var factorySlot = singleton("PackagerFactoryProvider");
28782
+ var factorySlot = singleton2("PackagerFactoryProvider");
28170
28783
  // ../../common/src/trackedAction.ts
28171
28784
  import { Command as Command2 } from "commander";
28172
28785
 
@@ -28295,7 +28908,7 @@ function redactProperties(properties) {
28295
28908
  }
28296
28909
 
28297
28910
  // ../../common/src/trackedAction.ts
28298
- var pollSignalSlot = singleton("PollSignal");
28911
+ var pollSignalSlot = singleton2("PollSignal");
28299
28912
  var processContext = {
28300
28913
  exit: (code) => {
28301
28914
  process.exitCode = code;
@@ -28346,17 +28959,21 @@ Command2.prototype.trackedAction = function(context, fn, properties) {
28346
28959
  const telemetryName = deriveCommandPath(command);
28347
28960
  const props = typeof properties === "function" ? properties(...args) : properties;
28348
28961
  const startTime = performance.now();
28349
- let errorMessage;
28962
+ let errorMessage2;
28350
28963
  const [error] = await catchError2(fn(...args));
28351
28964
  if (error) {
28352
- errorMessage = error instanceof Error ? error.message : String(error);
28353
- logger.error(`[trackedAction] ${telemetryName} failed: ${errorMessage}`);
28965
+ errorMessage2 = error instanceof Error ? error.message : String(error);
28966
+ logger.debug(`[trackedAction] ${telemetryName} failed: ${errorMessage2}`);
28967
+ const typed = error;
28968
+ const customInstructions = typeof typed.instructions === "string" ? typed.instructions : undefined;
28969
+ const customResult = typeof typed.result === "string" && typed.result !== RESULTS.Success && Object.values(RESULTS).includes(typed.result) ? typed.result : undefined;
28970
+ const finalResult = customResult ?? RESULTS.Failure;
28354
28971
  OutputFormatter.error({
28355
- Result: RESULTS.Failure,
28356
- Message: errorMessage,
28357
- Instructions: "An unexpected error occurred. Run with --log-level debug for details."
28972
+ Result: finalResult,
28973
+ Message: errorMessage2,
28974
+ Instructions: customInstructions ?? "An unexpected error occurred. Run with --log-level debug for details."
28358
28975
  });
28359
- context.exit(1);
28976
+ context.exit(EXIT_CODES[finalResult]);
28360
28977
  }
28361
28978
  const durationMs = performance.now() - startTime;
28362
28979
  const success = !error && (process.exitCode === undefined || process.exitCode === 0);
@@ -28365,7 +28982,7 @@ Command2.prototype.trackedAction = function(context, fn, properties) {
28365
28982
  ...props,
28366
28983
  duration: String(durationMs),
28367
28984
  success: String(success),
28368
- ...errorMessage ? { errorMessage } : {}
28985
+ ...errorMessage2 ? { errorMessage: errorMessage2 } : {}
28369
28986
  }));
28370
28987
  });
28371
28988
  };
@@ -28390,14 +29007,14 @@ async function reportError(error, loginInstructions) {
28390
29007
  // src/helpers/validators.ts
28391
29008
  import { InvalidArgumentError as InvalidArgumentError2 } from "commander";
28392
29009
  var IPV4_OCTET = /^(25[0-5]|2[0-4]\d|[01]?\d?\d)$/;
28393
- function errorMessage(err) {
29010
+ function errorMessage2(err) {
28394
29011
  return err instanceof Error ? err.message : String(err);
28395
29012
  }
28396
29013
  function asInvalidArgument(fn) {
28397
29014
  try {
28398
29015
  return fn();
28399
29016
  } catch (err) {
28400
- throw new InvalidArgumentError2(errorMessage(err));
29017
+ throw new InvalidArgumentError2(errorMessage2(err));
28401
29018
  }
28402
29019
  }
28403
29020
  function assertIpv4(value, label) {
@@ -29072,7 +29689,7 @@ function appendTrustedCert(value, previous) {
29072
29689
  try {
29073
29690
  return [...previous, assertTrustedCertSpec(value)];
29074
29691
  } catch (err) {
29075
- throw new InvalidArgumentError3(errorMessage(err));
29692
+ throw new InvalidArgumentError3(errorMessage2(err));
29076
29693
  }
29077
29694
  }
29078
29695
  var LOGIN_INSTRUCTIONS2 = "Ensure you are logged in with 'uip login' and that your account has org-admin access to the Hypervisor service. Pass --tenant <name> to target a tenant other than your login context.";