@uipath/uipath-python-bridge 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 (2) hide show
  1. package/dist/index.js +552 -219
  2. package/package.json +26 -33
package/dist/index.js CHANGED
@@ -667,6 +667,7 @@ var init_open = __esm(() => {
667
667
  });
668
668
 
669
669
  // ../filesystem/src/node.ts
670
+ import { randomUUID } from "node:crypto";
670
671
  import { existsSync } from "node:fs";
671
672
  import * as fs6 from "node:fs/promises";
672
673
  import * as os2 from "node:os";
@@ -748,6 +749,90 @@ class NodeFileSystem {
748
749
  async mkdir(dirPath) {
749
750
  await fs6.mkdir(dirPath, { recursive: true });
750
751
  }
752
+ async acquireLock(lockPath) {
753
+ const canonicalPath = await this.canonicalizeLockTarget(lockPath);
754
+ const lockFile = `${canonicalPath}.lock`;
755
+ const ownerId = randomUUID();
756
+ const start = Date.now();
757
+ while (true) {
758
+ try {
759
+ await fs6.writeFile(lockFile, ownerId, { flag: "wx" });
760
+ return this.createLockRelease(lockFile, ownerId);
761
+ } catch (error) {
762
+ if (!this.hasErrnoCode(error, "EEXIST")) {
763
+ throw error;
764
+ }
765
+ const stats = await fs6.stat(lockFile).catch(() => null);
766
+ if (stats && Date.now() - stats.mtimeMs > LOCK_STALE_MS) {
767
+ const reclaimed = await fs6.rm(lockFile, { force: true }).then(() => true).catch(() => false);
768
+ if (reclaimed)
769
+ continue;
770
+ }
771
+ if (Date.now() - start > LOCK_MAX_WAIT_MS) {
772
+ throw new Error(`ELOCKED: timed out waiting for lock on ${canonicalPath}`);
773
+ }
774
+ await new Promise((resolve2) => setTimeout(resolve2, LOCK_RETRY_MIN_MS + Math.random() * LOCK_RETRY_JITTER_MS));
775
+ }
776
+ }
777
+ }
778
+ async canonicalizeLockTarget(lockPath) {
779
+ const absolute = path2.resolve(lockPath);
780
+ const fullReal = await fs6.realpath(absolute).catch(() => null);
781
+ if (fullReal)
782
+ return fullReal;
783
+ const parent = path2.dirname(absolute);
784
+ const base = path2.basename(absolute);
785
+ const canonicalParent = await fs6.realpath(parent).catch(() => parent);
786
+ return path2.join(canonicalParent, base);
787
+ }
788
+ createLockRelease(lockFile, ownerId) {
789
+ const heartbeatStart = Date.now();
790
+ let heartbeatTimer;
791
+ let stopped = false;
792
+ const stopHeartbeat = () => {
793
+ stopped = true;
794
+ if (heartbeatTimer)
795
+ clearTimeout(heartbeatTimer);
796
+ };
797
+ const scheduleNextHeartbeat = () => {
798
+ if (stopped)
799
+ return;
800
+ if (Date.now() - heartbeatStart >= LOCK_MAX_HOLD_MS) {
801
+ stopped = true;
802
+ return;
803
+ }
804
+ heartbeatTimer = setTimeout(() => {
805
+ runHeartbeat();
806
+ }, LOCK_HEARTBEAT_MS);
807
+ heartbeatTimer.unref?.();
808
+ };
809
+ const runHeartbeat = async () => {
810
+ if (stopped)
811
+ return;
812
+ const current = await fs6.readFile(lockFile, "utf-8").catch(() => null);
813
+ if (stopped)
814
+ return;
815
+ if (current !== ownerId) {
816
+ stopped = true;
817
+ return;
818
+ }
819
+ const now = Date.now() / 1000;
820
+ await fs6.utimes(lockFile, now, now).catch(() => {});
821
+ scheduleNextHeartbeat();
822
+ };
823
+ scheduleNextHeartbeat();
824
+ let released = false;
825
+ return async () => {
826
+ if (released)
827
+ return;
828
+ released = true;
829
+ stopHeartbeat();
830
+ const current = await fs6.readFile(lockFile, "utf-8").catch(() => null);
831
+ if (current === ownerId) {
832
+ await fs6.rm(lockFile, { force: true });
833
+ }
834
+ };
835
+ }
751
836
  async rm(filePath) {
752
837
  await fs6.rm(filePath, { recursive: true, force: true });
753
838
  }
@@ -793,9 +878,13 @@ class NodeFileSystem {
793
878
  }
794
879
  }
795
880
  isEnoent(error) {
796
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
881
+ return this.hasErrnoCode(error, "ENOENT");
882
+ }
883
+ hasErrnoCode(error, code) {
884
+ return typeof error === "object" && error !== null && "code" in error && error.code === code;
797
885
  }
798
886
  }
887
+ 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;
799
888
  var init_node = __esm(() => {
800
889
  init_open();
801
890
  });
@@ -2941,7 +3030,7 @@ function isBrowser() {
2941
3030
 
2942
3031
  // ../../node_modules/@uipath/coreipc/index.js
2943
3032
  var require_coreipc = __commonJS((exports, module) => {
2944
- var __dirname = "/Users/alexandru.oltean/github/cli/node_modules/@uipath/coreipc";
3033
+ var __dirname = "/home/runner/work/cli/cli/node_modules/@uipath/coreipc";
2945
3034
  /*! For license information please see index.js.LICENSE.txt */
2946
3035
  (function(e, t) {
2947
3036
  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();
@@ -21133,6 +21222,10 @@ var require_dist = __commonJS((exports) => {
21133
21222
  exports.RobotProxyConstructor = RobotProxyConstructor;
21134
21223
  __exportStar(require_agent(), exports);
21135
21224
  });
21225
+ // ../auth/src/server.ts
21226
+ var init_server = __esm(() => {
21227
+ init_constants();
21228
+ });
21136
21229
 
21137
21230
  // ../common/src/attachment-binding.ts
21138
21231
  init_src();
@@ -26306,6 +26399,60 @@ function escapeNonAscii(jsonText) {
26306
26399
  function needsAsciiSafeJson(sink) {
26307
26400
  return process.platform === "win32" && !sink.capabilities.isInteractive;
26308
26401
  }
26402
+ function isPlainRecord(value) {
26403
+ if (value === null || typeof value !== "object")
26404
+ return false;
26405
+ const prototype = Object.getPrototypeOf(value);
26406
+ return prototype === Object.prototype || prototype === null;
26407
+ }
26408
+ function toLowerCamelCaseKey(key) {
26409
+ if (!key)
26410
+ return key;
26411
+ if (/[_\-\s]/.test(key)) {
26412
+ const [firstPart, ...restParts] = key.split(/[_\-\s]+/).filter(Boolean);
26413
+ if (!firstPart)
26414
+ return key;
26415
+ return [
26416
+ toLowerCamelCaseSimpleKey(firstPart),
26417
+ ...restParts.map((part) => {
26418
+ const normalized = toLowerCamelCaseSimpleKey(part);
26419
+ return normalized.charAt(0).toUpperCase() + normalized.slice(1);
26420
+ })
26421
+ ].join("");
26422
+ }
26423
+ return toLowerCamelCaseSimpleKey(key);
26424
+ }
26425
+ function toLowerCamelCaseSimpleKey(key) {
26426
+ if (/^[A-Z0-9]+$/.test(key))
26427
+ return key.toLowerCase();
26428
+ return key.replace(/^[A-Z]+(?=[A-Z][a-z]|\d|$)|^[A-Z]/, (match) => match.toLowerCase());
26429
+ }
26430
+ function toPascalCaseKey(key) {
26431
+ const lowerCamelKey = toLowerCamelCaseKey(key);
26432
+ return lowerCamelKey ? lowerCamelKey.charAt(0).toUpperCase() + lowerCamelKey.slice(1) : lowerCamelKey;
26433
+ }
26434
+ function toPascalCaseData(value) {
26435
+ if (Array.isArray(value))
26436
+ return value.map(toPascalCaseData);
26437
+ if (!isPlainRecord(value))
26438
+ return value;
26439
+ const result = {};
26440
+ for (const [key, nestedValue] of Object.entries(value)) {
26441
+ result[toPascalCaseKey(key)] = toPascalCaseData(nestedValue);
26442
+ }
26443
+ return result;
26444
+ }
26445
+ function normalizeDataKeys(data) {
26446
+ return toPascalCaseData(data);
26447
+ }
26448
+ function normalizeOutputKeys(data) {
26449
+ const result = {};
26450
+ for (const [key, value] of Object.entries(data)) {
26451
+ const pascalKey = toPascalCaseKey(key);
26452
+ result[pascalKey] = pascalKey === "Data" ? value : toPascalCaseData(value);
26453
+ }
26454
+ return result;
26455
+ }
26309
26456
  function printOutput(data, format = "json", logFn, asciiSafe = false) {
26310
26457
  if (!data) {
26311
26458
  logFn("Empty response object. No data to display.");
@@ -26368,7 +26515,7 @@ function wrapText(text, width) {
26368
26515
  function printTable(data, logFn, externalLogValue) {
26369
26516
  if (data.length === 0)
26370
26517
  return;
26371
- const keys = Object.keys(data[0]).filter((key) => key !== "Code" && key !== "Log");
26518
+ const keys = Object.keys(data[0]).filter((key) => !["code", "log"].includes(key.toLowerCase()));
26372
26519
  const maxWidths = keys.map((key) => Math.max(key.length, ...data.map((item) => cellToString(item[key]).length)));
26373
26520
  const header = keys.map((key, i2) => key.padEnd(maxWidths[i2])).join(" | ");
26374
26521
  logFn(header);
@@ -26383,7 +26530,7 @@ function printTable(data, logFn, externalLogValue) {
26383
26530
  }
26384
26531
  }
26385
26532
  function printVerticalTable(data, logFn = console.log, externalLogValue) {
26386
- const keys = Object.keys(data).filter((key) => key !== "Code" && key !== "Log");
26533
+ const keys = Object.keys(data).filter((key) => !["code", "log"].includes(key.toLowerCase()));
26387
26534
  if (keys.length === 0)
26388
26535
  return;
26389
26536
  const maxKeyWidth = Math.max(...keys.map((key) => key.length));
@@ -26399,7 +26546,7 @@ function printVerticalTable(data, logFn = console.log, externalLogValue) {
26399
26546
  function printResizableTable(data, logFn = console.log, externalLogValue) {
26400
26547
  if (data.length === 0)
26401
26548
  return;
26402
- const keys = Object.keys(data[0]).filter((key) => key !== "Code" && key !== "Log");
26549
+ const keys = Object.keys(data[0]).filter((key) => !["code", "log"].includes(key.toLowerCase()));
26403
26550
  if (keys.length === 0)
26404
26551
  return;
26405
26552
  if (!process.stdout.isTTY) {
@@ -26475,8 +26622,26 @@ function printResizableTable(data, logFn = console.log, externalLogValue) {
26475
26622
  function toYaml(data) {
26476
26623
  return dump(data);
26477
26624
  }
26625
+ class FilterEvaluationError extends Error {
26626
+ __brand = "FilterEvaluationError";
26627
+ filter;
26628
+ instructions;
26629
+ result = RESULTS.ValidationError;
26630
+ constructor(filter, cause) {
26631
+ const underlying = cause instanceof Error ? cause.message : String(cause);
26632
+ super(`Filter '${filter}' failed to evaluate: ${underlying}`);
26633
+ this.name = "FilterEvaluationError";
26634
+ this.filter = filter;
26635
+ 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(@)'.";
26636
+ }
26637
+ }
26478
26638
  function applyFilter(data, filter) {
26479
- const result = search(data, filter);
26639
+ let result;
26640
+ try {
26641
+ result = search(data, filter);
26642
+ } catch (err) {
26643
+ throw new FilterEvaluationError(filter, err);
26644
+ }
26480
26645
  if (result == null)
26481
26646
  return [];
26482
26647
  if (Array.isArray(result)) {
@@ -26493,13 +26658,18 @@ function applyFilter(data, filter) {
26493
26658
  }
26494
26659
  var OutputFormatter;
26495
26660
  ((OutputFormatter) => {
26496
- function success(data) {
26661
+ function success(data, options) {
26497
26662
  data.Log ??= getLogFilePath() || undefined;
26663
+ const normalize = !options?.preserveDataKeys;
26664
+ if (normalize) {
26665
+ data.Data = normalizeDataKeys(data.Data);
26666
+ }
26498
26667
  const filter = getOutputFilter();
26499
26668
  if (filter) {
26500
- data.Data = applyFilter(data.Data, filter);
26669
+ const filtered = applyFilter(data.Data, filter);
26670
+ data.Data = normalize ? normalizeDataKeys(filtered) : filtered;
26501
26671
  }
26502
- logOutput(data, getOutputFormat());
26672
+ logOutput(normalizeOutputKeys(data), getOutputFormat());
26503
26673
  }
26504
26674
  OutputFormatter.success = success;
26505
26675
  function error(data) {
@@ -26509,7 +26679,7 @@ var OutputFormatter;
26509
26679
  result: data.Result,
26510
26680
  message: data.Message
26511
26681
  });
26512
- logOutput(data, getOutputFormat());
26682
+ logOutput(normalizeOutputKeys(data), getOutputFormat());
26513
26683
  }
26514
26684
  OutputFormatter.error = error;
26515
26685
  function emitList(code, items, opts) {
@@ -26530,13 +26700,14 @@ var OutputFormatter;
26530
26700
  function log(data) {
26531
26701
  const format = getOutputFormat();
26532
26702
  const sink = getOutputSink();
26703
+ const normalized = toPascalCaseData(data);
26533
26704
  if (format === "json") {
26534
- const json2 = JSON.stringify(data);
26705
+ const json2 = JSON.stringify(normalized);
26535
26706
  const safe = needsAsciiSafeJson(sink) ? escapeNonAscii(json2) : json2;
26536
26707
  sink.writeErr(`${safe}
26537
26708
  `);
26538
26709
  } else {
26539
- for (const [key, value] of Object.entries(data)) {
26710
+ for (const [key, value] of Object.entries(normalized)) {
26540
26711
  sink.writeErr(`${key}: ${value}
26541
26712
  `);
26542
26713
  }
@@ -26545,12 +26716,16 @@ var OutputFormatter;
26545
26716
  OutputFormatter.log = log;
26546
26717
  function formatToString(data) {
26547
26718
  const filter = getOutputFilter();
26548
- if (filter && "Data" in data && data.Data != null) {
26549
- data.Data = applyFilter(data.Data, filter);
26719
+ if ("Data" in data && data.Data != null) {
26720
+ data.Data = normalizeDataKeys(data.Data);
26721
+ if (filter) {
26722
+ data.Data = normalizeDataKeys(applyFilter(data.Data, filter));
26723
+ }
26550
26724
  }
26725
+ const output = normalizeOutputKeys(data);
26551
26726
  const lines = [];
26552
26727
  const sink = getOutputSink();
26553
- printOutput(data, getOutputFormat(), (msg) => {
26728
+ printOutput(output, getOutputFormat(), (msg) => {
26554
26729
  lines.push(msg);
26555
26730
  }, needsAsciiSafeJson(sink));
26556
26731
  return lines.join(`
@@ -27961,6 +28136,22 @@ JSONPath.prototype.safeVm = {
27961
28136
  Script: SafeScript
27962
28137
  };
27963
28138
  JSONPath.prototype.vm = vm;
28139
+ // ../common/src/polling/types.ts
28140
+ var PollOutcome = {
28141
+ Completed: "completed",
28142
+ Timeout: "timeout",
28143
+ Interrupted: "interrupted",
28144
+ Aborted: "aborted",
28145
+ Failed: "failed"
28146
+ };
28147
+
28148
+ // ../common/src/polling/poll-failure-mapping.ts
28149
+ var REASON_BY_OUTCOME = {
28150
+ [PollOutcome.Timeout]: "poll_timeout",
28151
+ [PollOutcome.Failed]: "poll_failed",
28152
+ [PollOutcome.Interrupted]: "poll_failed",
28153
+ [PollOutcome.Aborted]: "poll_aborted"
28154
+ };
27964
28155
  // ../common/src/polling/terminal-statuses.ts
27965
28156
  var TERMINAL_STATUSES = new Set([
27966
28157
  "completed",
@@ -27988,6 +28179,8 @@ var ScreenLogger;
27988
28179
  }
27989
28180
  ScreenLogger.progress = progress;
27990
28181
  })(ScreenLogger ||= {});
28182
+ // ../common/src/sdk-user-agent.ts
28183
+ var sdkUserAgentHostToken = singleton("SdkUserAgentHostToken");
27991
28184
  // ../common/src/tool-provider.ts
27992
28185
  var factorySlot = singleton("PackagerFactoryProvider");
27993
28186
  // ../common/src/telemetry/pii-redactor.ts
@@ -28170,13 +28363,17 @@ Command.prototype.trackedAction = function(context, fn, properties) {
28170
28363
  const [error] = await catchError(fn(...args));
28171
28364
  if (error) {
28172
28365
  errorMessage = error instanceof Error ? error.message : String(error);
28173
- logger.error(`[trackedAction] ${telemetryName} failed: ${errorMessage}`);
28366
+ logger.debug(`[trackedAction] ${telemetryName} failed: ${errorMessage}`);
28367
+ const typed = error;
28368
+ const customInstructions = typeof typed.instructions === "string" ? typed.instructions : undefined;
28369
+ const customResult = typeof typed.result === "string" && typed.result !== RESULTS.Success && Object.values(RESULTS).includes(typed.result) ? typed.result : undefined;
28370
+ const finalResult = customResult ?? RESULTS.Failure;
28174
28371
  OutputFormatter.error({
28175
- Result: RESULTS.Failure,
28372
+ Result: finalResult,
28176
28373
  Message: errorMessage,
28177
- Instructions: "An unexpected error occurred. Run with --log-level debug for details."
28374
+ Instructions: customInstructions ?? "An unexpected error occurred. Run with --log-level debug for details."
28178
28375
  });
28179
- context.exit(1);
28376
+ context.exit(EXIT_CODES[finalResult]);
28180
28377
  }
28181
28378
  const durationMs = performance.now() - startTime;
28182
28379
  const success = !error && (process.exitCode === undefined || process.exitCode === 0);
@@ -28308,32 +28505,7 @@ class InvalidBaseUrlError extends Error {
28308
28505
  this.name = "InvalidBaseUrlError";
28309
28506
  }
28310
28507
  }
28311
- var DEFAULT_SCOPES = [
28312
- "offline_access",
28313
- "ProcessMining",
28314
- "OrchestratorApiUserAccess",
28315
- "StudioWebBackend",
28316
- "IdentityServerApi",
28317
- "ConnectionService",
28318
- "DataService",
28319
- "DataServiceApiUserAccess",
28320
- "DocumentUnderstanding",
28321
- "EnterpriseContextService",
28322
- "Directory",
28323
- "JamJamApi",
28324
- "LLMGateway",
28325
- "LLMOps",
28326
- "OMS",
28327
- "RCS.FolderAuthorization",
28328
- "RCS.TagsManagement",
28329
- "TestmanagerApiUserAccess",
28330
- "AutomationSolutions",
28331
- "StudioWebTypeCacheService",
28332
- "Docs.GPT.Search",
28333
- "Insights",
28334
- "ReferenceToken",
28335
- "Audit.Read"
28336
- ];
28508
+ var DEFAULT_SCOPES = ["openid", "profile", "offline_access"];
28337
28509
  var normalizeAndValidateBaseUrl = (rawUrl) => {
28338
28510
  let baseUrl = rawUrl;
28339
28511
  if (baseUrl.endsWith("/identity_/")) {
@@ -28383,7 +28555,8 @@ var resolveConfigAsync = async ({
28383
28555
  if (!clientSecret && fileAuth.clientSecret) {
28384
28556
  clientSecret = fileAuth.clientSecret;
28385
28557
  }
28386
- const scopes = customScopes && customScopes.length > 0 ? customScopes : fileAuth.scopes && fileAuth.scopes.length > 0 ? fileAuth.scopes : DEFAULT_SCOPES;
28558
+ const isExternalAppAuth = clientId !== DEFAULT_CLIENT_ID && Boolean(clientSecret);
28559
+ const scopes = customScopes && customScopes.length > 0 ? customScopes : fileAuth.scopes && fileAuth.scopes.length > 0 ? fileAuth.scopes : isExternalAppAuth ? [] : DEFAULT_SCOPES;
28387
28560
  return {
28388
28561
  clientId,
28389
28562
  clientSecret,
@@ -28883,6 +29056,129 @@ function normalizeTokenRefreshFailure() {
28883
29056
  function normalizeTokenRefreshUnavailableFailure() {
28884
29057
  return "token refresh failed before authentication completed";
28885
29058
  }
29059
+ function errorMessage(error) {
29060
+ return error instanceof Error ? error.message : String(error);
29061
+ }
29062
+ function computeExpirationThreshold(ensureTokenValidityMinutes) {
29063
+ return new Date(Date.now() + (ensureTokenValidityMinutes ?? 0) * 60 * 1000);
29064
+ }
29065
+ async function runRefreshLocked(inputs) {
29066
+ const {
29067
+ absolutePath,
29068
+ refreshToken: callerRefreshToken,
29069
+ customAuthority,
29070
+ ensureTokenValidityMinutes,
29071
+ loadEnvFile,
29072
+ saveEnvFile,
29073
+ refreshFn,
29074
+ resolveConfig
29075
+ } = inputs;
29076
+ const expirationThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
29077
+ let fresh;
29078
+ try {
29079
+ fresh = await loadEnvFile({ envPath: absolutePath });
29080
+ } catch (error) {
29081
+ return {
29082
+ kind: "fail",
29083
+ status: {
29084
+ loginStatus: "Refresh Failed",
29085
+ hint: "Could not read the auth file while refreshing. Retry, or run 'uip login' to re-authenticate.",
29086
+ tokenRefresh: {
29087
+ attempted: false,
29088
+ success: false,
29089
+ errorMessage: `auth file read failed: ${errorMessage(error)}`
29090
+ }
29091
+ }
29092
+ };
29093
+ }
29094
+ const freshAccess = fresh.UIPATH_ACCESS_TOKEN;
29095
+ const freshExp = freshAccess ? getTokenExpiration(freshAccess) : undefined;
29096
+ if (freshAccess && freshExp && freshExp > expirationThreshold) {
29097
+ return {
29098
+ kind: "ok",
29099
+ accessToken: freshAccess,
29100
+ refreshToken: fresh.UIPATH_REFRESH_TOKEN ?? callerRefreshToken,
29101
+ expiration: freshExp,
29102
+ tokenRefresh: { attempted: false, success: true }
29103
+ };
29104
+ }
29105
+ const tokenForIdP = fresh.UIPATH_REFRESH_TOKEN ?? callerRefreshToken;
29106
+ let refreshedAccess;
29107
+ let refreshedRefresh;
29108
+ try {
29109
+ const config = await resolveConfig({ customAuthority });
29110
+ const refreshed = await refreshFn({
29111
+ refreshToken: tokenForIdP,
29112
+ tokenEndpoint: config.tokenEndpoint,
29113
+ clientId: config.clientId,
29114
+ expectedAuthority: customAuthority
29115
+ });
29116
+ refreshedAccess = refreshed.accessToken;
29117
+ refreshedRefresh = refreshed.refreshToken;
29118
+ } catch (error) {
29119
+ const isOAuthFailure = isTokenRefreshOAuthFailure(error);
29120
+ 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.";
29121
+ const message = isOAuthFailure ? normalizeTokenRefreshFailure() : normalizeTokenRefreshUnavailableFailure();
29122
+ return {
29123
+ kind: "fail",
29124
+ status: {
29125
+ loginStatus: "Refresh Failed",
29126
+ hint,
29127
+ tokenRefresh: {
29128
+ attempted: true,
29129
+ success: false,
29130
+ errorMessage: message
29131
+ }
29132
+ }
29133
+ };
29134
+ }
29135
+ const refreshedExp = getTokenExpiration(refreshedAccess);
29136
+ if (!refreshedExp || refreshedExp <= new Date) {
29137
+ return {
29138
+ kind: "fail",
29139
+ status: {
29140
+ loginStatus: "Refresh Failed",
29141
+ hint: "The identity server returned an unusable token. Run 'uip login' to re-authenticate.",
29142
+ tokenRefresh: {
29143
+ attempted: true,
29144
+ success: false,
29145
+ errorMessage: "refreshed token has no valid expiration claim"
29146
+ }
29147
+ }
29148
+ };
29149
+ }
29150
+ try {
29151
+ await saveEnvFile({
29152
+ envPath: absolutePath,
29153
+ data: {
29154
+ UIPATH_ACCESS_TOKEN: refreshedAccess,
29155
+ UIPATH_REFRESH_TOKEN: refreshedRefresh
29156
+ },
29157
+ merge: true
29158
+ });
29159
+ return {
29160
+ kind: "ok",
29161
+ accessToken: refreshedAccess,
29162
+ refreshToken: refreshedRefresh,
29163
+ expiration: refreshedExp,
29164
+ tokenRefresh: { attempted: true, success: true }
29165
+ };
29166
+ } catch (error) {
29167
+ const msg = errorMessage(error);
29168
+ return {
29169
+ kind: "ok",
29170
+ accessToken: refreshedAccess,
29171
+ refreshToken: refreshedRefresh,
29172
+ expiration: refreshedExp,
29173
+ 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.`,
29174
+ tokenRefresh: {
29175
+ attempted: true,
29176
+ success: true,
29177
+ errorMessage: `persistence failed: ${msg}`
29178
+ }
29179
+ };
29180
+ }
29181
+ }
28886
29182
  var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
28887
29183
  const {
28888
29184
  resolveEnvFilePath = resolveEnvFilePathAsync,
@@ -28957,73 +29253,103 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
28957
29253
  let refreshToken = credentials.UIPATH_REFRESH_TOKEN;
28958
29254
  let expiration = getTokenExpiration(accessToken);
28959
29255
  let persistenceWarning;
29256
+ let lockReleaseFailed = false;
28960
29257
  let tokenRefresh;
28961
- const expirationThreshold = new Date(Date.now() + (ensureTokenValidityMinutes ?? 0) * 60 * 1000);
28962
- if (expiration && expiration <= expirationThreshold && refreshToken) {
28963
- let refreshedAccess;
28964
- let refreshedRefresh;
29258
+ const outerThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
29259
+ const tryGlobalCredsHint = async () => {
29260
+ const fs7 = getFs();
29261
+ const globalPath = fs7.path.join(fs7.env.homedir(), envFilePath);
29262
+ if (absolutePath === globalPath)
29263
+ return;
29264
+ if (!await fs7.exists(globalPath))
29265
+ return;
28965
29266
  try {
28966
- const config = await resolveConfig({
28967
- customAuthority: credentials.UIPATH_URL
28968
- });
28969
- const refreshed = await refreshTokenFn({
28970
- refreshToken,
28971
- tokenEndpoint: config.tokenEndpoint,
28972
- clientId: config.clientId,
28973
- expectedAuthority: credentials.UIPATH_URL
28974
- });
28975
- refreshedAccess = refreshed.accessToken;
28976
- refreshedRefresh = refreshed.refreshToken;
28977
- } catch (error) {
28978
- const isOAuthFailure = isTokenRefreshOAuthFailure(error);
28979
- 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.";
28980
- const errorMessage = isOAuthFailure ? normalizeTokenRefreshFailure() : normalizeTokenRefreshUnavailableFailure();
28981
- return {
28982
- loginStatus: "Refresh Failed",
28983
- hint,
28984
- tokenRefresh: {
28985
- attempted: true,
28986
- success: false,
28987
- errorMessage
28988
- }
28989
- };
29267
+ const globalCreds = await loadEnvFile({ envPath: globalPath });
29268
+ if (!globalCreds.UIPATH_ACCESS_TOKEN)
29269
+ return;
29270
+ const globalExp = getTokenExpiration(globalCreds.UIPATH_ACCESS_TOKEN);
29271
+ if (globalExp && globalExp <= new Date)
29272
+ return;
29273
+ 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.`;
29274
+ } catch {
29275
+ return;
28990
29276
  }
28991
- const refreshedExp = getTokenExpiration(refreshedAccess);
28992
- if (!refreshedExp || refreshedExp <= new Date) {
29277
+ };
29278
+ if (expiration && expiration <= outerThreshold && refreshToken) {
29279
+ let release;
29280
+ try {
29281
+ release = await getFs().acquireLock(absolutePath);
29282
+ } catch (error) {
29283
+ const msg = errorMessage(error);
29284
+ const globalHint = await tryGlobalCredsHint();
29285
+ if (globalHint) {
29286
+ return {
29287
+ loginStatus: "Expired",
29288
+ accessToken,
29289
+ refreshToken,
29290
+ baseUrl: credentials.UIPATH_URL,
29291
+ organizationName: credentials.UIPATH_ORGANIZATION_NAME,
29292
+ organizationId: credentials.UIPATH_ORGANIZATION_ID,
29293
+ tenantName: credentials.UIPATH_TENANT_NAME,
29294
+ tenantId: credentials.UIPATH_TENANT_ID,
29295
+ expiration,
29296
+ source: "file" /* File */,
29297
+ hint: globalHint,
29298
+ tokenRefresh: {
29299
+ attempted: false,
29300
+ success: false,
29301
+ errorMessage: `lock acquisition failed: ${msg}`
29302
+ }
29303
+ };
29304
+ }
28993
29305
  return {
28994
29306
  loginStatus: "Refresh Failed",
28995
- hint: "The identity server returned an unusable token. Run 'uip login' to re-authenticate.",
29307
+ 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.",
28996
29308
  tokenRefresh: {
28997
- attempted: true,
29309
+ attempted: false,
28998
29310
  success: false,
28999
- errorMessage: "refreshed token has no valid expiration claim"
29311
+ errorMessage: `lock acquisition failed: ${msg}`
29000
29312
  }
29001
29313
  };
29002
29314
  }
29003
- accessToken = refreshedAccess;
29004
- refreshToken = refreshedRefresh;
29005
- expiration = refreshedExp;
29315
+ let lockedFailure;
29006
29316
  try {
29007
- await saveEnvFile({
29008
- envPath: absolutePath,
29009
- data: {
29010
- UIPATH_ACCESS_TOKEN: accessToken,
29011
- UIPATH_REFRESH_TOKEN: refreshToken
29012
- },
29013
- merge: true
29317
+ const outcome = await runRefreshLocked({
29318
+ absolutePath,
29319
+ refreshToken,
29320
+ customAuthority: credentials.UIPATH_URL,
29321
+ ensureTokenValidityMinutes,
29322
+ loadEnvFile,
29323
+ saveEnvFile,
29324
+ refreshFn: refreshTokenFn,
29325
+ resolveConfig
29014
29326
  });
29015
- tokenRefresh = {
29016
- attempted: true,
29017
- success: true
29018
- };
29019
- } catch (error) {
29020
- const msg = error instanceof Error ? error.message : String(error);
29021
- 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.`;
29022
- tokenRefresh = {
29023
- attempted: true,
29024
- success: true,
29025
- errorMessage: `persistence failed: ${msg}`
29026
- };
29327
+ if (outcome.kind === "fail") {
29328
+ lockedFailure = outcome.status;
29329
+ } else {
29330
+ accessToken = outcome.accessToken;
29331
+ refreshToken = outcome.refreshToken;
29332
+ expiration = outcome.expiration;
29333
+ tokenRefresh = outcome.tokenRefresh;
29334
+ if (outcome.persistenceWarning) {
29335
+ persistenceWarning = outcome.persistenceWarning;
29336
+ }
29337
+ }
29338
+ } finally {
29339
+ try {
29340
+ await release();
29341
+ } catch {
29342
+ lockReleaseFailed = true;
29343
+ }
29344
+ }
29345
+ if (lockedFailure) {
29346
+ const globalHint = await tryGlobalCredsHint();
29347
+ const base = globalHint ? {
29348
+ ...lockedFailure,
29349
+ loginStatus: "Expired",
29350
+ hint: globalHint
29351
+ } : lockedFailure;
29352
+ return lockReleaseFailed ? { ...base, lockReleaseFailed: true } : base;
29027
29353
  }
29028
29354
  }
29029
29355
  const result = {
@@ -29038,23 +29364,13 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
29038
29364
  expiration,
29039
29365
  source: "file" /* File */,
29040
29366
  ...persistenceWarning ? { hint: persistenceWarning, persistenceFailed: true } : {},
29367
+ ...lockReleaseFailed ? { lockReleaseFailed: true } : {},
29041
29368
  ...tokenRefresh ? { tokenRefresh } : {}
29042
29369
  };
29043
29370
  if (result.loginStatus === "Expired") {
29044
- const fs7 = getFs();
29045
- const globalPath = fs7.path.join(fs7.env.homedir(), envFilePath);
29046
- if (absolutePath !== globalPath && await fs7.exists(globalPath)) {
29047
- try {
29048
- const globalCreds = await loadEnvFile({
29049
- envPath: globalPath
29050
- });
29051
- if (globalCreds.UIPATH_ACCESS_TOKEN) {
29052
- const globalExp = getTokenExpiration(globalCreds.UIPATH_ACCESS_TOKEN);
29053
- if (!globalExp || globalExp > new Date) {
29054
- 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.`;
29055
- }
29056
- }
29057
- } catch {}
29371
+ const globalHint = await tryGlobalCredsHint();
29372
+ if (globalHint) {
29373
+ result.hint = globalHint;
29058
29374
  }
29059
29375
  }
29060
29376
  return result;
@@ -29071,6 +29387,10 @@ var getLoginStatusAsync = async (options = {}) => {
29071
29387
  init_src();
29072
29388
  // ../auth/src/logout.ts
29073
29389
  init_src();
29390
+
29391
+ // ../auth/src/index.ts
29392
+ init_server();
29393
+
29074
29394
  // src/execute.ts
29075
29395
  init_src();
29076
29396
  var ENV_FILE_NAME = ".env";
@@ -29133,121 +29453,133 @@ async function buildAuthContext() {
29133
29453
  }
29134
29454
  return { authEnv, loginStatus: status };
29135
29455
  }
29136
- function createExecuteCommand(config) {
29137
- const {
29138
- commandPrefix,
29139
- telemetryEvent,
29140
- commandRules,
29141
- commandPreflight,
29142
- requiredEnvironmentVariables = []
29143
- } = config;
29144
- const executeCommand = async (rawArgs, _options) => {
29145
- const runIndex = rawArgs.indexOf("exec");
29146
- const actualArgs = runIndex >= 0 ? rawArgs.slice(runIndex + 1) : [];
29147
- const fs7 = getFileSystem();
29148
- const cacheFile = fs7.path.join(fs7.env.homedir(), UIPATH_HOME_DIR, getCacheFileName());
29149
- const setupHint = commandPrefix ? `Run 'uip ${commandPrefix} setup' first to configure environment.` : "Run setup first to configure environment.";
29150
- const cache = await readCache(cacheFile);
29151
- if (!cache?.uipathExePath) {
29152
- OutputFormatter.error({
29153
- Result: RESULTS.ConfigError,
29154
- Message: "Python not configured.",
29155
- Instructions: setupHint
29156
- });
29157
- processContext.exit(1);
29158
- return;
29159
- }
29160
- if (!await fs7.exists(cache.uipathExePath)) {
29161
- OutputFormatter.error({
29162
- Result: RESULTS.ConfigError,
29163
- Message: "uipath executable not found.",
29164
- Instructions: setupHint
29165
- });
29166
- processContext.exit(1);
29167
- return;
29456
+ var fail = (reason, message, instructions, extras = {}) => ({
29457
+ ok: false,
29458
+ reason,
29459
+ message,
29460
+ instructions,
29461
+ exitCode: extras.exitCode ?? 1,
29462
+ stderr: extras.stderr
29463
+ });
29464
+ async function runUipathPythonCommand(args, options = {}) {
29465
+ const fs7 = getFileSystem();
29466
+ const cacheFile = fs7.path.join(fs7.env.homedir(), UIPATH_HOME_DIR, getCacheFileName());
29467
+ const setupHint = options.commandPrefix ? `Run 'uip ${options.commandPrefix} setup' first to configure environment.` : "Run setup first to configure environment.";
29468
+ const cache = await readCache(cacheFile);
29469
+ if (!cache?.uipathExePath) {
29470
+ return fail("python_not_configured", "Python not configured.", setupHint);
29471
+ }
29472
+ if (!await fs7.exists(cache.uipathExePath)) {
29473
+ return fail("uipath_exe_missing", "uipath executable not found.", setupHint);
29474
+ }
29475
+ const processed = processCommandArgs(args, options.commandRules ?? []);
29476
+ if (!processed.allowed) {
29477
+ return fail("command_disabled", processed.errorMessage || "Command disabled.", "Use of --force flag is not recommended. Favor alternate command.", { exitCode: 3 });
29478
+ }
29479
+ const commandArgs = options.commandPrefix ? [options.commandPrefix, ...processed.args] : [...processed.args];
29480
+ const requiredEnv = {};
29481
+ for (const requirement of options.requiredEnvironmentVariables ?? []) {
29482
+ const applies = matchesRequiredCommand(processed.args, requirement.commands) && (!requirement.skipWhenHelp || !isHelpCommand(processed.args));
29483
+ if (!applies) {
29484
+ continue;
29168
29485
  }
29169
- const processed = processCommandArgs(actualArgs, commandRules);
29170
- if (!processed.allowed) {
29171
- OutputFormatter.error({
29172
- Result: RESULTS.ValidationError,
29173
- Message: processed.errorMessage || "Command disabled.",
29174
- Instructions: "Use of --force flag is not recommended. Favor alternate command."
29175
- });
29176
- processContext.exit(3);
29177
- return;
29486
+ const value = await getConfiguredEnvValue(fs7, requirement.name);
29487
+ if (!value) {
29488
+ return fail("required_env_missing", `${requirement.name} environment variable not found.`, requirement.instructions);
29178
29489
  }
29179
- const commandArgs = commandPrefix ? [commandPrefix, ...processed.args] : [...processed.args];
29180
- const requiredEnv = {};
29181
- for (const requirement of requiredEnvironmentVariables) {
29182
- const applies = matchesRequiredCommand(processed.args, requirement.commands) && (!requirement.skipWhenHelp || !isHelpCommand(processed.args));
29183
- if (!applies) {
29184
- continue;
29185
- }
29186
- const value = await getConfiguredEnvValue(fs7, requirement.name);
29187
- if (!value) {
29188
- OutputFormatter.error({
29189
- Result: RESULTS.ConfigError,
29190
- Message: `${requirement.name} environment variable not found.`,
29191
- Instructions: requirement.instructions
29192
- });
29193
- processContext.exit(1);
29194
- return;
29195
- }
29196
- requiredEnv[requirement.name] = value;
29490
+ requiredEnv[requirement.name] = value;
29491
+ }
29492
+ const { authEnv, loginStatus: loginStatus2 } = await buildAuthContext();
29493
+ if (options.commandPreflight) {
29494
+ const preflight = options.commandPreflight;
29495
+ const [preflightError, preflightResult] = await catchError(Promise.resolve().then(() => preflight({
29496
+ args: commandArgs,
29497
+ loginStatus: loginStatus2,
29498
+ authEnv
29499
+ })));
29500
+ if (preflightError) {
29501
+ return fail("preflight_error", preflightError.message, "Check your credentials and configuration, then retry.");
29197
29502
  }
29198
- const { authEnv, loginStatus: loginStatus2 } = await buildAuthContext();
29199
- if (commandPreflight) {
29200
- const [preflightError, preflightResult] = await catchError(Promise.resolve().then(() => commandPreflight({
29201
- args: commandArgs,
29202
- loginStatus: loginStatus2,
29203
- authEnv
29204
- })));
29205
- if (preflightError) {
29206
- OutputFormatter.error({
29207
- Result: RESULTS.Failure,
29208
- Message: preflightError.message,
29209
- Instructions: "Check your credentials and configuration, then retry."
29210
- });
29211
- processContext.exit(1);
29212
- return;
29213
- }
29214
- if (preflightResult && !preflightResult.allowed) {
29215
- OutputFormatter.error({
29216
- Result: RESULTS.ConfigError,
29217
- Message: preflightResult.message || "Command preflight check failed.",
29218
- Instructions: preflightResult.instructions || "Update the command configuration and try again."
29219
- });
29220
- processContext.exit(preflightResult.exitCode ?? 1);
29221
- return;
29222
- }
29503
+ if (preflightResult && !preflightResult.allowed) {
29504
+ return fail("preflight_rejected", preflightResult.message || "Command preflight check failed.", preflightResult.instructions || "Update the command configuration and try again.", { exitCode: preflightResult.exitCode ?? 1 });
29223
29505
  }
29224
- const proc = spawn(cache.uipathExePath, commandArgs, {
29225
- cwd: fs7.env.cwd(),
29226
- env: {
29227
- ...process.env,
29228
- ...authEnv,
29229
- ...requiredEnv
29230
- },
29506
+ }
29507
+ const stdio = options.stdio ?? "inherit";
29508
+ const cwd = options.cwd ?? fs7.env.cwd();
29509
+ const proc = spawn(cache.uipathExePath, commandArgs, {
29510
+ cwd,
29511
+ env: {
29512
+ ...process.env,
29513
+ ...authEnv,
29514
+ ...requiredEnv
29515
+ },
29516
+ stdio: stdio === "pipe" ? ["ignore", "pipe", "pipe"] : "inherit",
29517
+ signal: options.signal
29518
+ });
29519
+ let stdout = "";
29520
+ let stderr = "";
29521
+ if (stdio === "pipe") {
29522
+ proc.stdout?.on("data", (chunk) => {
29523
+ stdout += chunk.toString("utf8");
29524
+ });
29525
+ proc.stderr?.on("data", (chunk) => {
29526
+ stderr += chunk.toString("utf8");
29527
+ });
29528
+ }
29529
+ const [spawnError, exitCode] = await catchError(new Promise((resolve2, reject) => {
29530
+ proc.on("close", (code) => resolve2(code ?? 1));
29531
+ proc.on("error", reject);
29532
+ }));
29533
+ if (spawnError) {
29534
+ return fail("spawn_failed", spawnError.message, setupHint, {
29535
+ stderr: stdio === "pipe" ? stderr : undefined
29536
+ });
29537
+ }
29538
+ if (exitCode !== 0) {
29539
+ return fail("command_failed", `Python 'uipath ${commandArgs.join(" ")}' exited with code ${exitCode}.`, stdio === "pipe" && stderr ? "See the captured stderr below for the Python tool's error output." : "Re-run with verbose flags or stream stdio inherit to diagnose.", {
29540
+ exitCode,
29541
+ stderr: stdio === "pipe" ? stderr : undefined
29542
+ });
29543
+ }
29544
+ return {
29545
+ ok: true,
29546
+ pythonExePath: cache.uipathExePath,
29547
+ exitCode: 0,
29548
+ stdout: stdio === "pipe" ? stdout : undefined,
29549
+ stderr: stdio === "pipe" ? stderr : undefined
29550
+ };
29551
+ }
29552
+ var CLI_RESULT_BY_REASON = {
29553
+ python_not_configured: RESULTS.ConfigError,
29554
+ uipath_exe_missing: RESULTS.ConfigError,
29555
+ command_disabled: RESULTS.ValidationError,
29556
+ required_env_missing: RESULTS.ConfigError,
29557
+ preflight_error: RESULTS.Failure,
29558
+ preflight_rejected: RESULTS.ConfigError,
29559
+ spawn_failed: RESULTS.Failure
29560
+ };
29561
+ function createExecuteCommand(config) {
29562
+ const executeCommand = async (rawArgs, _options) => {
29563
+ const runIndex = rawArgs.indexOf("exec");
29564
+ const actualArgs = runIndex >= 0 ? rawArgs.slice(runIndex + 1) : [];
29565
+ const result = await runUipathPythonCommand(actualArgs, {
29566
+ commandPrefix: config.commandPrefix,
29567
+ commandRules: config.commandRules,
29568
+ commandPreflight: config.commandPreflight,
29569
+ requiredEnvironmentVariables: config.requiredEnvironmentVariables,
29231
29570
  stdio: "inherit"
29232
29571
  });
29233
- const [spawnError] = await catchError(new Promise((resolve2, reject) => {
29234
- proc.on("exit", (code) => {
29235
- processContext.exit(code ?? 1);
29236
- resolve2();
29237
- });
29238
- proc.on("error", reject);
29239
- }));
29240
- if (spawnError) {
29572
+ if (!result.ok && result.reason !== "command_failed") {
29241
29573
  OutputFormatter.error({
29242
- Result: RESULTS.Failure,
29243
- Message: spawnError.message,
29244
- Instructions: setupHint
29574
+ Result: CLI_RESULT_BY_REASON[result.reason],
29575
+ Message: result.message,
29576
+ Instructions: result.instructions
29245
29577
  });
29246
- processContext.exit(1);
29247
29578
  }
29579
+ processContext.exit(result.exitCode);
29248
29580
  };
29249
29581
  const registerExecCommand = (program2) => {
29250
- program2.command("exec", { hidden: true }).description("Execute the uipath package with provided arguments").allowUnknownOption(true).allowExcessArguments(true).trackedAction(processContext, telemetryEvent, async (_options, cmd) => {
29582
+ program2.command("exec", { hidden: true }).description("Execute the uipath package with provided arguments").allowUnknownOption(true).allowExcessArguments(true).trackedAction(processContext, config.telemetryEvent, async (_options, cmd) => {
29251
29583
  await executeCommand(["_", "_", "exec", ...cmd.args], {});
29252
29584
  });
29253
29585
  };
@@ -29742,6 +30074,7 @@ function createCommandForwarder(executeCommand) {
29742
30074
  };
29743
30075
  }
29744
30076
  export {
30077
+ runUipathPythonCommand,
29745
30078
  readCache,
29746
30079
  processCommandArgs,
29747
30080
  getPackageName,
package/package.json CHANGED
@@ -1,35 +1,28 @@
1
1
  {
2
- "name": "@uipath/uipath-python-bridge",
3
- "version": "1.1.0",
4
- "description": "Shared Python detection, caching, and CLI bridge for UiPath Python SDK tools.",
5
- "keywords": [
6
- "uip",
7
- "python",
8
- "bridge"
9
- ],
10
- "type": "module",
11
- "main": "./dist/index.js",
12
- "exports": {
13
- ".": "./dist/index.js"
14
- },
15
- "files": [
16
- "dist"
17
- ],
18
- "repository": {
19
- "type": "git",
20
- "url": "https://github.com/UiPath/cli.git",
21
- "directory": "packages/uipath-python-bridge"
22
- },
23
- "publishConfig": {
24
- "registry": "https://registry.npmjs.org/"
25
- },
26
- "devDependencies": {
27
- "@uipath/auth": "1.1.0",
28
- "@uipath/common": "1.1.0",
29
- "@uipath/filesystem": "1.1.0",
30
- "@types/bun": "^1.3.11",
31
- "commander": "^14.0.3",
32
- "typescript": "^6.0.2"
33
- },
34
- "gitHead": "06e8c8f566df4b87da4a008635483c62f64f33f0"
2
+ "name": "@uipath/uipath-python-bridge",
3
+ "license": "MIT",
4
+ "version": "1.195.0",
5
+ "description": "Shared Python detection, caching, and CLI bridge for UiPath Python SDK tools.",
6
+ "keywords": [
7
+ "uip",
8
+ "python",
9
+ "bridge"
10
+ ],
11
+ "type": "module",
12
+ "main": "./dist/index.js",
13
+ "exports": {
14
+ ".": "./dist/index.js"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/UiPath/cli.git",
22
+ "directory": "packages/uipath-python-bridge"
23
+ },
24
+ "publishConfig": {
25
+ "registry": "https://registry.npmjs.org/"
26
+ },
27
+ "gitHead": "65fabb84552758b2710d8ca68470e70a9b1d19bc"
35
28
  }