@uipath/llmgw-tool 1.204.0-preview.255 → 1.205.0-preview.256

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.
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  Command,
4
4
  metadata,
5
5
  registerCommands
6
- } from "./tool-s2xfftgq.js";
6
+ } from "./tool-0b7tnx3n.js";
7
7
  import"./tool-1de529jm.js";
8
8
 
9
9
  // src/index.ts
@@ -2101,7 +2101,7 @@ var package_default = {
2101
2101
  name: "@uipath/llmgw-tool",
2102
2102
  author: "UiPath",
2103
2103
  license: "SEE LICENSE IN LICENSE.txt",
2104
- version: "1.204.0-preview.255",
2104
+ version: "1.205.0-preview.256",
2105
2105
  description: "CLI plugin for UiPath AI Trust Layer Bring-Your-Own LLM connections.",
2106
2106
  private: false,
2107
2107
  repository: {
@@ -2321,6 +2321,16 @@ class NodeFileSystem {
2321
2321
  async rename(oldPath, newPath) {
2322
2322
  await fs.rename(oldPath, newPath);
2323
2323
  }
2324
+ async isSymbolicLink(filePath) {
2325
+ try {
2326
+ return (await fs.lstat(filePath)).isSymbolicLink();
2327
+ } catch (error) {
2328
+ if (this.isEnoent(error) || this.hasErrnoCode(error, "ENOTDIR")) {
2329
+ return false;
2330
+ }
2331
+ throw error;
2332
+ }
2333
+ }
2324
2334
  async realpath(filePath) {
2325
2335
  try {
2326
2336
  return await fs.realpath(filePath);
@@ -3356,7 +3366,7 @@ function setGlobalLogFilePath(path2) {
3356
3366
  function getGlobalLogFilePath() {
3357
3367
  return logFilePathSlot.get("");
3358
3368
  }
3359
- var DEFAULT_LOG_LEVEL = 3 /* ERROR */;
3369
+ var DEFAULT_LOG_LEVEL = 2 /* WARN */;
3360
3370
 
3361
3371
  class SimpleLogger {
3362
3372
  __brand = "SimpleLogger";
@@ -3623,7 +3633,9 @@ var ErrorDimensions = {
3623
3633
  Result: "Result",
3624
3634
  ErrorCode: "ErrorCode",
3625
3635
  Retry: "Retry",
3626
- ErrorMessage: "ErrorMessage"
3636
+ ErrorMessage: "ErrorMessage",
3637
+ HttpStatus: "HttpStatus",
3638
+ UpstreamErrorCode: "UpstreamErrorCode"
3627
3639
  };
3628
3640
  var AuthDimensions = {
3629
3641
  AuthenticationMethod: "AuthenticationMethod",
@@ -4611,7 +4623,9 @@ var CLI_ERROR_CODES = [
4611
4623
  "timeout",
4612
4624
  "server_error",
4613
4625
  "method_not_allowed",
4626
+ "not_supported",
4614
4627
  "configuration_error",
4628
+ "execution_failed",
4615
4629
  "unknown_error"
4616
4630
  ];
4617
4631
  var RETRY_HINTS = [
@@ -5568,7 +5582,9 @@ var OutputFormatter;
5568
5582
  [ErrorDimensions.Result]: data.Result,
5569
5583
  [ErrorDimensions.ErrorCode]: data.ErrorCode,
5570
5584
  [ErrorDimensions.Retry]: data.Retry,
5571
- [ErrorDimensions.ErrorMessage]: data.Message
5585
+ [ErrorDimensions.ErrorMessage]: data.Message,
5586
+ [ErrorDimensions.HttpStatus]: data.Context?.httpStatus?.toString(),
5587
+ [ErrorDimensions.UpstreamErrorCode]: data.Context?.errorCode
5572
5588
  });
5573
5589
  }
5574
5590
  logOutput(normalizeOutputKeys(envelope), getOutputFormat());
@@ -6521,22 +6537,12 @@ var resolveConfigAsync = async ({
6521
6537
  baseUrl = DEFAULT_BASE_URL;
6522
6538
  }
6523
6539
  baseUrl = normalizeAndValidateBaseUrl(baseUrl);
6524
- let clientId = customClientId;
6525
- if (!clientId && fileAuth.clientId) {
6526
- clientId = fileAuth.clientId;
6527
- }
6528
- if (!clientId) {
6529
- clientId = DEFAULT_CLIENT_ID;
6530
- }
6531
- let clientSecret = customClientSecret;
6532
- if (!clientSecret && fileAuth.clientSecret) {
6533
- clientSecret = fileAuth.clientSecret;
6534
- }
6535
- const isExternalAppAuth = clientId !== DEFAULT_CLIENT_ID && (Boolean(clientSecret) || Boolean(customClientAssertion));
6540
+ const clientId = customClientId || DEFAULT_CLIENT_ID;
6541
+ const isExternalAppAuth = clientId !== DEFAULT_CLIENT_ID && (Boolean(customClientSecret) || Boolean(customClientAssertion));
6536
6542
  const scopes = resolveScopes(isExternalAppAuth, customScopes, fileAuth.scopes);
6537
6543
  return {
6538
6544
  clientId,
6539
- clientSecret,
6545
+ clientSecret: customClientSecret,
6540
6546
  scopes,
6541
6547
  baseUrl,
6542
6548
  authorizationEndpoint: `${baseUrl}/identity_/connect/authorize`,
@@ -6710,6 +6716,16 @@ var resolveIdentityType = (claims, authFlow, email) => {
6710
6716
  }
6711
6717
  return;
6712
6718
  };
6719
+ var resolveApplicationSubtype = (claims, authFlow) => {
6720
+ switch (asString(claims?.sub_type)) {
6721
+ case "service.external":
6722
+ return "External";
6723
+ case "service.internal":
6724
+ return "Internal";
6725
+ default:
6726
+ return authFlow === "client_credentials" || authFlow === "federated_credentials" ? "External" : undefined;
6727
+ }
6728
+ };
6713
6729
  var looksLikeEmail = (value) => value?.includes("@") ?? false;
6714
6730
  var pickEmail = (claims) => {
6715
6731
  for (const candidate of [claims?.email, claims?.preferred_username]) {
@@ -6751,6 +6767,12 @@ var resolveSessionIdentity = (accessToken, authFlow) => {
6751
6767
  const clientId = asString(claims?.client_id);
6752
6768
  if (clientId)
6753
6769
  identity.clientId = clientId;
6770
+ const subType = asString(claims?.sub_type);
6771
+ if (subType)
6772
+ identity.subType = subType;
6773
+ const applicationSubtype = resolveApplicationSubtype(claims, authFlow);
6774
+ if (applicationSubtype)
6775
+ identity.applicationSubtype = applicationSubtype;
6754
6776
  return identity;
6755
6777
  };
6756
6778
  var readTokenScopes = (accessToken) => accessToken ? pickScopes(decodeClaims(accessToken)) : undefined;
@@ -7043,6 +7065,40 @@ var tryRobotClientFallback = async (options = {}) => {
7043
7065
  }
7044
7066
  };
7045
7067
 
7068
+ // ../../auth/src/tenantSelection.ts
7069
+ var LOGIN_STATUS_HINT = "Run 'uip login status' to see the organization the CLI is signed in to.";
7070
+ var organizationHint = (organizationId) => `The request used '${organizationId}' as the organization. ${LOGIN_STATUS_HINT}`;
7071
+ var IDENTIFIER_STATUSES = new Set([400, 403, 404]);
7072
+ var describeNonJsonResponse = (organizationId, response, parseError) => {
7073
+ if (response.redirected) {
7074
+ return `Could not find organization '${organizationId}': the request was ` + `redirected to a sign-in page instead of the organization's tenant ` + `list. ${LOGIN_STATUS_HINT}`;
7075
+ }
7076
+ const contentType = response.headers.get("content-type") ?? "unknown";
7077
+ return `The organization service returned a '${contentType}' response instead ` + `of JSON: ${parseError.message}. ${organizationHint(organizationId)}`;
7078
+ };
7079
+ var fetchTenantsAndOrganizations = async (baseUrl, accessToken, organizationId, signal) => {
7080
+ const url = `${baseUrl}/${organizationId}/portal_/api/filtering/leftnav/tenantsAndOrganizationInfo`;
7081
+ const response = await fetch(url, {
7082
+ headers: {
7083
+ Authorization: `Bearer ${accessToken}`
7084
+ },
7085
+ ...signal ? { signal } : {}
7086
+ });
7087
+ if (!response.ok) {
7088
+ if (response.status === 401) {
7089
+ throw new Error(`Unauthorized: the access token was rejected, it was not ` + `issued for organization '${organizationId}', or ` + `'${organizationId}' was not accepted as an organization ` + `URL segment in this environment. ` + LOGIN_STATUS_HINT);
7090
+ }
7091
+ const errorText = await response.text();
7092
+ const message = `Failed to get tenants and organizations: ${response.status} ${errorText}`;
7093
+ throw new Error(IDENTIFIER_STATUSES.has(response.status) ? `${message}. ${organizationHint(organizationId)}` : message);
7094
+ }
7095
+ const [parseError, data] = await catchError2(response.json());
7096
+ if (parseError) {
7097
+ throw new Error(describeNonJsonResponse(organizationId, response, parseError));
7098
+ }
7099
+ return data;
7100
+ };
7101
+
7046
7102
  // ../../auth/src/tokenRefresh.ts
7047
7103
  var TOKEN_REFRESH_REAUTHENTICATE_MESSAGE = "Token refresh failed. Run 'uip login' to re-authenticate.";
7048
7104
 
@@ -7255,6 +7311,8 @@ var saveEnvFileAsync = async ({
7255
7311
  };
7256
7312
 
7257
7313
  // ../../auth/src/loginStatus.ts
7314
+ var defaultRobotTenantIdCache = new Map;
7315
+ var ROBOT_TENANT_LOOKUP_TIMEOUT_MS = 5000;
7258
7316
  var getLoginStatusAsync = async (options = {}) => {
7259
7317
  return getLoginStatusWithDeps(options);
7260
7318
  };
@@ -7267,12 +7325,20 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
7267
7325
  refreshToken: refreshTokenFn = refreshAccessToken,
7268
7326
  resolveConfig = resolveConfigAsync,
7269
7327
  robotFallback = tryRobotClientFallback,
7328
+ fetchTenantsAndOrgs = fetchTenantsAndOrganizations,
7329
+ robotTenantIdCache = defaultRobotTenantIdCache,
7330
+ robotTenantLookupTimeoutMs = ROBOT_TENANT_LOOKUP_TIMEOUT_MS,
7270
7331
  loadBreaker = loadRefreshBreaker,
7271
7332
  saveBreaker = saveRefreshBreaker,
7272
7333
  clearBreaker = clearRefreshBreaker
7273
7334
  } = deps;
7335
+ const robotDeps = {
7336
+ fetchTenantsAndOrgs,
7337
+ cache: robotTenantIdCache,
7338
+ lookupTimeoutMs: robotTenantLookupTimeoutMs
7339
+ };
7274
7340
  if (isRobotAuthEnforced()) {
7275
- return resolveRobotEnforcedStatus(robotFallback);
7341
+ return resolveRobotEnforcedStatus(robotFallback, robotDeps);
7276
7342
  }
7277
7343
  if (isEnvAuthEnabled()) {
7278
7344
  return readAuthFromEnv();
@@ -7290,7 +7356,7 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
7290
7356
  hint: `No credentials found for profile "${activeProfile}". Run 'uip login --profile ${activeProfile}' to authenticate this profile.`
7291
7357
  };
7292
7358
  }
7293
- return resolveBorrowedRobotStatus(robotFallback);
7359
+ return resolveBorrowedRobotStatus(robotFallback, robotDeps);
7294
7360
  }
7295
7361
  const loaded = await loadFileCredentials(loadEnvFile, absolutePath);
7296
7362
  if ("status" in loaded) {
@@ -7332,7 +7398,7 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
7332
7398
  }
7333
7399
  return buildFileStatus(tokens, credentials, globalHint);
7334
7400
  };
7335
- async function resolveRobotEnforcedStatus(robotFallback) {
7401
+ async function resolveRobotEnforcedStatus(robotFallback, deps) {
7336
7402
  if (isEnvAuthEnabled()) {
7337
7403
  throw new EnvAuthConfigError(`${ENV_AUTH_ENABLE_VAR}=true and ${ENFORCE_ROBOT_AUTH_VAR}=true ` + `are mutually exclusive. Unset one of them and re-run.`);
7338
7404
  }
@@ -7343,11 +7409,11 @@ async function resolveRobotEnforcedStatus(robotFallback) {
7343
7409
  hint: `${ENFORCE_ROBOT_AUTH_VAR}=true but the UiPath Robot ` + `session is unavailable. Start and sign in to the Assistant, ` + `or unset ${ENFORCE_ROBOT_AUTH_VAR} to fall back to file or ` + `env-var authentication.`
7344
7410
  };
7345
7411
  }
7346
- return buildRobotStatus(robotCreds);
7412
+ return buildRobotStatus(robotCreds, deps);
7347
7413
  }
7348
- async function resolveBorrowedRobotStatus(robotFallback) {
7414
+ async function resolveBorrowedRobotStatus(robotFallback, deps) {
7349
7415
  const robotCreds = await robotFallback();
7350
- return robotCreds ? buildRobotStatus(robotCreds) : { loginStatus: "Not logged in" };
7416
+ return robotCreds ? buildRobotStatus(robotCreds, deps) : { loginStatus: "Not logged in" };
7351
7417
  }
7352
7418
  async function loadFileCredentials(loadEnvFile, absolutePath) {
7353
7419
  let credentials;
@@ -7482,9 +7548,10 @@ function identityFields(accessToken, credentials) {
7482
7548
  ...scopes ? { scopes } : {}
7483
7549
  };
7484
7550
  }
7485
- function buildRobotStatus(robotCreds) {
7551
+ async function buildRobotStatus(robotCreds, deps) {
7486
7552
  const identity = resolveSessionIdentity(robotCreds.accessToken);
7487
7553
  const scopes = readTokenScopes(robotCreds.accessToken);
7554
+ const tenant = robotCreds.tenantId ? { tenantId: robotCreds.tenantId } : await resolveRobotTenantId(robotCreds, deps);
7488
7555
  return {
7489
7556
  loginStatus: "Logged in",
7490
7557
  accessToken: robotCreds.accessToken,
@@ -7492,14 +7559,62 @@ function buildRobotStatus(robotCreds) {
7492
7559
  organizationName: robotCreds.organizationName,
7493
7560
  organizationId: robotCreds.organizationId,
7494
7561
  tenantName: robotCreds.tenantName,
7495
- tenantId: robotCreds.tenantId,
7562
+ tenantId: tenant.tenantId,
7496
7563
  issuer: robotCreds.issuer,
7497
7564
  expiration: getTokenExpiration(robotCreds.accessToken),
7498
7565
  source: "robot" /* Robot */,
7566
+ ...tenant.hint ? { hint: tenant.hint } : {},
7499
7567
  ...identity ? { identity } : {},
7500
7568
  ...scopes ? { scopes } : {}
7501
7569
  };
7502
7570
  }
7571
+ async function resolveRobotTenantId(robotCreds, deps) {
7572
+ const { baseUrl, accessToken, tenantName } = robotCreds;
7573
+ const organization = robotCreds.organizationName ?? robotCreds.organizationId;
7574
+ if (!tenantName || !organization) {
7575
+ return {};
7576
+ }
7577
+ const key = `${baseUrl}|${organization}|${tenantName}|${accessToken}`;
7578
+ let pending = deps.cache.get(key);
7579
+ if (!pending) {
7580
+ pending = catchError2(lookupRobotTenantId({ baseUrl, accessToken, organization, tenantName }, deps)).then(([error, resolution]) => {
7581
+ const settled = error ? { hint: tenantLookupFailureHint(tenantName, error.message) } : resolution;
7582
+ if (!settled.tenantId) {
7583
+ deps.cache.delete(key);
7584
+ }
7585
+ return settled;
7586
+ });
7587
+ deps.cache.set(key, pending);
7588
+ }
7589
+ return pending;
7590
+ }
7591
+ async function lookupRobotTenantId(target, deps) {
7592
+ const { baseUrl, accessToken, organization, tenantName } = target;
7593
+ const [error, data] = await catchError2(deps.fetchTenantsAndOrgs(baseUrl, accessToken, organization, AbortSignal.timeout(deps.lookupTimeoutMs)));
7594
+ if (error) {
7595
+ const reason = error.name === "TimeoutError" ? `the tenant list did not answer within ${deps.lookupTimeoutMs} ms.` : error.message;
7596
+ return { hint: tenantLookupFailureHint(tenantName, reason) };
7597
+ }
7598
+ const rows = data?.tenants;
7599
+ const tenants = Array.isArray(rows) ? rows.filter((tenant) => typeof tenant?.id === "string" && typeof tenant?.name === "string") : [];
7600
+ const wantedName = decodePathSegment(tenantName);
7601
+ const wanted = wantedName.toLowerCase();
7602
+ const match = tenants.find((tenant) => tenant.name === wantedName) ?? tenants.find((tenant) => tenant.name.toLowerCase() === wanted);
7603
+ if (!match) {
7604
+ const names = tenants.map((tenant) => tenant.name).join(", ");
7605
+ return {
7606
+ hint: `The Robot session targets tenant '${tenantName}', but ` + `organization '${organization}' lists no tenant of that name` + `${names ? ` (available: ${names})` : ""}. Commands that need ` + `the tenant id will fail until it can be resolved.`
7607
+ };
7608
+ }
7609
+ return { tenantId: match.id };
7610
+ }
7611
+ function tenantLookupFailureHint(tenantName, reason) {
7612
+ return `Could not resolve the id of tenant '${tenantName}' from the ` + `Robot session: ${reason} Commands that need the tenant id will ` + `fail until it can be resolved.`;
7613
+ }
7614
+ function decodePathSegment(segment) {
7615
+ const [error, decoded] = catchError2(() => decodeURIComponent(segment));
7616
+ return error ? segment : decoded;
7617
+ }
7503
7618
  var isFileNotFoundError = (error) => {
7504
7619
  if (!(error instanceof Object))
7505
7620
  return false;
@@ -7735,9 +7850,6 @@ function normalizeTokenRefreshUnavailableFailure() {
7735
7850
  function errorMessage(error) {
7736
7851
  return error instanceof Error ? error.message : String(error);
7737
7852
  }
7738
- // ../../auth/src/tenantSelection.ts
7739
- var IDENTIFIER_STATUSES = new Set([400, 403, 404]);
7740
-
7741
7853
  // ../../auth/src/selectTenant.ts
7742
7854
  var TENANT_SELECTION_REQUIRED_CODE = "TENANT_SELECTION_REQUIRED";
7743
7855
  var INVALID_TENANT_CODE = "INVALID_TENANT";
@@ -9120,4 +9232,4 @@ var registerCommands = async (program2) => {
9120
9232
 
9121
9233
  export { Command, metadata, registerCommands };
9122
9234
 
9123
- //# debugId=AD1DAD93CCE5BC5764756E2164756E21
9235
+ //# debugId=B78446A9BC051B5E64756E2164756E21
package/dist/tool.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  metadata,
3
3
  registerCommands
4
- } from "./tool-s2xfftgq.js";
4
+ } from "./tool-0b7tnx3n.js";
5
5
  import"./tool-1de529jm.js";
6
6
  export {
7
7
  metadata,
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@uipath/llmgw-tool",
3
3
  "author": "UiPath",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
- "version": "1.204.0-preview.255",
5
+ "version": "1.205.0-preview.256",
6
6
  "description": "CLI plugin for UiPath AI Trust Layer Bring-Your-Own LLM connections.",
7
7
  "private": false,
8
8
  "repository": {
@@ -24,5 +24,5 @@
24
24
  "files": [
25
25
  "dist"
26
26
  ],
27
- "gitHead": "699c58dabb59414557755a8933bcbe40aa420df3"
27
+ "gitHead": "63740c6cbb7ff282fa9118cc16a148eb030b245f"
28
28
  }