@uipath/model-hub-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-d4dtfh4p.js";
6
+ } from "./tool-k29yy9j4.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/model-hub-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 the UiPath Model Hub (LLM Gateway organization-scoped views).",
2106
2106
  private: false,
2107
2107
  repository: {
@@ -2324,6 +2324,16 @@ class NodeFileSystem {
2324
2324
  async rename(oldPath, newPath) {
2325
2325
  await fs.rename(oldPath, newPath);
2326
2326
  }
2327
+ async isSymbolicLink(filePath) {
2328
+ try {
2329
+ return (await fs.lstat(filePath)).isSymbolicLink();
2330
+ } catch (error) {
2331
+ if (this.isEnoent(error) || this.hasErrnoCode(error, "ENOTDIR")) {
2332
+ return false;
2333
+ }
2334
+ throw error;
2335
+ }
2336
+ }
2327
2337
  async realpath(filePath) {
2328
2338
  try {
2329
2339
  return await fs.realpath(filePath);
@@ -3359,7 +3369,7 @@ function setGlobalLogFilePath(path2) {
3359
3369
  function getGlobalLogFilePath() {
3360
3370
  return logFilePathSlot.get("");
3361
3371
  }
3362
- var DEFAULT_LOG_LEVEL = 3 /* ERROR */;
3372
+ var DEFAULT_LOG_LEVEL = 2 /* WARN */;
3363
3373
 
3364
3374
  class SimpleLogger {
3365
3375
  __brand = "SimpleLogger";
@@ -3626,7 +3636,9 @@ var ErrorDimensions = {
3626
3636
  Result: "Result",
3627
3637
  ErrorCode: "ErrorCode",
3628
3638
  Retry: "Retry",
3629
- ErrorMessage: "ErrorMessage"
3639
+ ErrorMessage: "ErrorMessage",
3640
+ HttpStatus: "HttpStatus",
3641
+ UpstreamErrorCode: "UpstreamErrorCode"
3630
3642
  };
3631
3643
  var AuthDimensions = {
3632
3644
  AuthenticationMethod: "AuthenticationMethod",
@@ -4614,7 +4626,9 @@ var CLI_ERROR_CODES = [
4614
4626
  "timeout",
4615
4627
  "server_error",
4616
4628
  "method_not_allowed",
4629
+ "not_supported",
4617
4630
  "configuration_error",
4631
+ "execution_failed",
4618
4632
  "unknown_error"
4619
4633
  ];
4620
4634
  var RETRY_HINTS = [
@@ -5571,7 +5585,9 @@ var OutputFormatter;
5571
5585
  [ErrorDimensions.Result]: data.Result,
5572
5586
  [ErrorDimensions.ErrorCode]: data.ErrorCode,
5573
5587
  [ErrorDimensions.Retry]: data.Retry,
5574
- [ErrorDimensions.ErrorMessage]: data.Message
5588
+ [ErrorDimensions.ErrorMessage]: data.Message,
5589
+ [ErrorDimensions.HttpStatus]: data.Context?.httpStatus?.toString(),
5590
+ [ErrorDimensions.UpstreamErrorCode]: data.Context?.errorCode
5575
5591
  });
5576
5592
  }
5577
5593
  logOutput(normalizeOutputKeys(envelope), getOutputFormat());
@@ -6524,22 +6540,12 @@ var resolveConfigAsync = async ({
6524
6540
  baseUrl = DEFAULT_BASE_URL;
6525
6541
  }
6526
6542
  baseUrl = normalizeAndValidateBaseUrl(baseUrl);
6527
- let clientId = customClientId;
6528
- if (!clientId && fileAuth.clientId) {
6529
- clientId = fileAuth.clientId;
6530
- }
6531
- if (!clientId) {
6532
- clientId = DEFAULT_CLIENT_ID;
6533
- }
6534
- let clientSecret = customClientSecret;
6535
- if (!clientSecret && fileAuth.clientSecret) {
6536
- clientSecret = fileAuth.clientSecret;
6537
- }
6538
- const isExternalAppAuth = clientId !== DEFAULT_CLIENT_ID && (Boolean(clientSecret) || Boolean(customClientAssertion));
6543
+ const clientId = customClientId || DEFAULT_CLIENT_ID;
6544
+ const isExternalAppAuth = clientId !== DEFAULT_CLIENT_ID && (Boolean(customClientSecret) || Boolean(customClientAssertion));
6539
6545
  const scopes = resolveScopes(isExternalAppAuth, customScopes, fileAuth.scopes);
6540
6546
  return {
6541
6547
  clientId,
6542
- clientSecret,
6548
+ clientSecret: customClientSecret,
6543
6549
  scopes,
6544
6550
  baseUrl,
6545
6551
  authorizationEndpoint: `${baseUrl}/identity_/connect/authorize`,
@@ -6713,6 +6719,16 @@ var resolveIdentityType = (claims, authFlow, email) => {
6713
6719
  }
6714
6720
  return;
6715
6721
  };
6722
+ var resolveApplicationSubtype = (claims, authFlow) => {
6723
+ switch (asString(claims?.sub_type)) {
6724
+ case "service.external":
6725
+ return "External";
6726
+ case "service.internal":
6727
+ return "Internal";
6728
+ default:
6729
+ return authFlow === "client_credentials" || authFlow === "federated_credentials" ? "External" : undefined;
6730
+ }
6731
+ };
6716
6732
  var looksLikeEmail = (value) => value?.includes("@") ?? false;
6717
6733
  var pickEmail = (claims) => {
6718
6734
  for (const candidate of [claims?.email, claims?.preferred_username]) {
@@ -6754,6 +6770,12 @@ var resolveSessionIdentity = (accessToken, authFlow) => {
6754
6770
  const clientId = asString(claims?.client_id);
6755
6771
  if (clientId)
6756
6772
  identity.clientId = clientId;
6773
+ const subType = asString(claims?.sub_type);
6774
+ if (subType)
6775
+ identity.subType = subType;
6776
+ const applicationSubtype = resolveApplicationSubtype(claims, authFlow);
6777
+ if (applicationSubtype)
6778
+ identity.applicationSubtype = applicationSubtype;
6757
6779
  return identity;
6758
6780
  };
6759
6781
  var readTokenScopes = (accessToken) => accessToken ? pickScopes(decodeClaims(accessToken)) : undefined;
@@ -7046,6 +7068,40 @@ var tryRobotClientFallback = async (options = {}) => {
7046
7068
  }
7047
7069
  };
7048
7070
 
7071
+ // ../../auth/src/tenantSelection.ts
7072
+ var LOGIN_STATUS_HINT = "Run 'uip login status' to see the organization the CLI is signed in to.";
7073
+ var organizationHint = (organizationId) => `The request used '${organizationId}' as the organization. ${LOGIN_STATUS_HINT}`;
7074
+ var IDENTIFIER_STATUSES = new Set([400, 403, 404]);
7075
+ var describeNonJsonResponse = (organizationId, response, parseError) => {
7076
+ if (response.redirected) {
7077
+ 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}`;
7078
+ }
7079
+ const contentType = response.headers.get("content-type") ?? "unknown";
7080
+ return `The organization service returned a '${contentType}' response instead ` + `of JSON: ${parseError.message}. ${organizationHint(organizationId)}`;
7081
+ };
7082
+ var fetchTenantsAndOrganizations = async (baseUrl, accessToken, organizationId, signal) => {
7083
+ const url = `${baseUrl}/${organizationId}/portal_/api/filtering/leftnav/tenantsAndOrganizationInfo`;
7084
+ const response = await fetch(url, {
7085
+ headers: {
7086
+ Authorization: `Bearer ${accessToken}`
7087
+ },
7088
+ ...signal ? { signal } : {}
7089
+ });
7090
+ if (!response.ok) {
7091
+ if (response.status === 401) {
7092
+ 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);
7093
+ }
7094
+ const errorText = await response.text();
7095
+ const message = `Failed to get tenants and organizations: ${response.status} ${errorText}`;
7096
+ throw new Error(IDENTIFIER_STATUSES.has(response.status) ? `${message}. ${organizationHint(organizationId)}` : message);
7097
+ }
7098
+ const [parseError, data] = await catchError2(response.json());
7099
+ if (parseError) {
7100
+ throw new Error(describeNonJsonResponse(organizationId, response, parseError));
7101
+ }
7102
+ return data;
7103
+ };
7104
+
7049
7105
  // ../../auth/src/tokenRefresh.ts
7050
7106
  var TOKEN_REFRESH_REAUTHENTICATE_MESSAGE = "Token refresh failed. Run 'uip login' to re-authenticate.";
7051
7107
 
@@ -7258,6 +7314,8 @@ var saveEnvFileAsync = async ({
7258
7314
  };
7259
7315
 
7260
7316
  // ../../auth/src/loginStatus.ts
7317
+ var defaultRobotTenantIdCache = new Map;
7318
+ var ROBOT_TENANT_LOOKUP_TIMEOUT_MS = 5000;
7261
7319
  var getLoginStatusAsync = async (options = {}) => {
7262
7320
  return getLoginStatusWithDeps(options);
7263
7321
  };
@@ -7270,12 +7328,20 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
7270
7328
  refreshToken: refreshTokenFn = refreshAccessToken,
7271
7329
  resolveConfig = resolveConfigAsync,
7272
7330
  robotFallback = tryRobotClientFallback,
7331
+ fetchTenantsAndOrgs = fetchTenantsAndOrganizations,
7332
+ robotTenantIdCache = defaultRobotTenantIdCache,
7333
+ robotTenantLookupTimeoutMs = ROBOT_TENANT_LOOKUP_TIMEOUT_MS,
7273
7334
  loadBreaker = loadRefreshBreaker,
7274
7335
  saveBreaker = saveRefreshBreaker,
7275
7336
  clearBreaker = clearRefreshBreaker
7276
7337
  } = deps;
7338
+ const robotDeps = {
7339
+ fetchTenantsAndOrgs,
7340
+ cache: robotTenantIdCache,
7341
+ lookupTimeoutMs: robotTenantLookupTimeoutMs
7342
+ };
7277
7343
  if (isRobotAuthEnforced()) {
7278
- return resolveRobotEnforcedStatus(robotFallback);
7344
+ return resolveRobotEnforcedStatus(robotFallback, robotDeps);
7279
7345
  }
7280
7346
  if (isEnvAuthEnabled()) {
7281
7347
  return readAuthFromEnv();
@@ -7293,7 +7359,7 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
7293
7359
  hint: `No credentials found for profile "${activeProfile}". Run 'uip login --profile ${activeProfile}' to authenticate this profile.`
7294
7360
  };
7295
7361
  }
7296
- return resolveBorrowedRobotStatus(robotFallback);
7362
+ return resolveBorrowedRobotStatus(robotFallback, robotDeps);
7297
7363
  }
7298
7364
  const loaded = await loadFileCredentials(loadEnvFile, absolutePath);
7299
7365
  if ("status" in loaded) {
@@ -7335,7 +7401,7 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
7335
7401
  }
7336
7402
  return buildFileStatus(tokens, credentials, globalHint);
7337
7403
  };
7338
- async function resolveRobotEnforcedStatus(robotFallback) {
7404
+ async function resolveRobotEnforcedStatus(robotFallback, deps) {
7339
7405
  if (isEnvAuthEnabled()) {
7340
7406
  throw new EnvAuthConfigError(`${ENV_AUTH_ENABLE_VAR}=true and ${ENFORCE_ROBOT_AUTH_VAR}=true ` + `are mutually exclusive. Unset one of them and re-run.`);
7341
7407
  }
@@ -7346,11 +7412,11 @@ async function resolveRobotEnforcedStatus(robotFallback) {
7346
7412
  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.`
7347
7413
  };
7348
7414
  }
7349
- return buildRobotStatus(robotCreds);
7415
+ return buildRobotStatus(robotCreds, deps);
7350
7416
  }
7351
- async function resolveBorrowedRobotStatus(robotFallback) {
7417
+ async function resolveBorrowedRobotStatus(robotFallback, deps) {
7352
7418
  const robotCreds = await robotFallback();
7353
- return robotCreds ? buildRobotStatus(robotCreds) : { loginStatus: "Not logged in" };
7419
+ return robotCreds ? buildRobotStatus(robotCreds, deps) : { loginStatus: "Not logged in" };
7354
7420
  }
7355
7421
  async function loadFileCredentials(loadEnvFile, absolutePath) {
7356
7422
  let credentials;
@@ -7485,9 +7551,10 @@ function identityFields(accessToken, credentials) {
7485
7551
  ...scopes ? { scopes } : {}
7486
7552
  };
7487
7553
  }
7488
- function buildRobotStatus(robotCreds) {
7554
+ async function buildRobotStatus(robotCreds, deps) {
7489
7555
  const identity = resolveSessionIdentity(robotCreds.accessToken);
7490
7556
  const scopes = readTokenScopes(robotCreds.accessToken);
7557
+ const tenant = robotCreds.tenantId ? { tenantId: robotCreds.tenantId } : await resolveRobotTenantId(robotCreds, deps);
7491
7558
  return {
7492
7559
  loginStatus: "Logged in",
7493
7560
  accessToken: robotCreds.accessToken,
@@ -7495,14 +7562,62 @@ function buildRobotStatus(robotCreds) {
7495
7562
  organizationName: robotCreds.organizationName,
7496
7563
  organizationId: robotCreds.organizationId,
7497
7564
  tenantName: robotCreds.tenantName,
7498
- tenantId: robotCreds.tenantId,
7565
+ tenantId: tenant.tenantId,
7499
7566
  issuer: robotCreds.issuer,
7500
7567
  expiration: getTokenExpiration(robotCreds.accessToken),
7501
7568
  source: "robot" /* Robot */,
7569
+ ...tenant.hint ? { hint: tenant.hint } : {},
7502
7570
  ...identity ? { identity } : {},
7503
7571
  ...scopes ? { scopes } : {}
7504
7572
  };
7505
7573
  }
7574
+ async function resolveRobotTenantId(robotCreds, deps) {
7575
+ const { baseUrl, accessToken, tenantName } = robotCreds;
7576
+ const organization = robotCreds.organizationName ?? robotCreds.organizationId;
7577
+ if (!tenantName || !organization) {
7578
+ return {};
7579
+ }
7580
+ const key = `${baseUrl}|${organization}|${tenantName}|${accessToken}`;
7581
+ let pending = deps.cache.get(key);
7582
+ if (!pending) {
7583
+ pending = catchError2(lookupRobotTenantId({ baseUrl, accessToken, organization, tenantName }, deps)).then(([error, resolution]) => {
7584
+ const settled = error ? { hint: tenantLookupFailureHint(tenantName, error.message) } : resolution;
7585
+ if (!settled.tenantId) {
7586
+ deps.cache.delete(key);
7587
+ }
7588
+ return settled;
7589
+ });
7590
+ deps.cache.set(key, pending);
7591
+ }
7592
+ return pending;
7593
+ }
7594
+ async function lookupRobotTenantId(target, deps) {
7595
+ const { baseUrl, accessToken, organization, tenantName } = target;
7596
+ const [error, data] = await catchError2(deps.fetchTenantsAndOrgs(baseUrl, accessToken, organization, AbortSignal.timeout(deps.lookupTimeoutMs)));
7597
+ if (error) {
7598
+ const reason = error.name === "TimeoutError" ? `the tenant list did not answer within ${deps.lookupTimeoutMs} ms.` : error.message;
7599
+ return { hint: tenantLookupFailureHint(tenantName, reason) };
7600
+ }
7601
+ const rows = data?.tenants;
7602
+ const tenants = Array.isArray(rows) ? rows.filter((tenant) => typeof tenant?.id === "string" && typeof tenant?.name === "string") : [];
7603
+ const wantedName = decodePathSegment(tenantName);
7604
+ const wanted = wantedName.toLowerCase();
7605
+ const match = tenants.find((tenant) => tenant.name === wantedName) ?? tenants.find((tenant) => tenant.name.toLowerCase() === wanted);
7606
+ if (!match) {
7607
+ const names = tenants.map((tenant) => tenant.name).join(", ");
7608
+ return {
7609
+ 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.`
7610
+ };
7611
+ }
7612
+ return { tenantId: match.id };
7613
+ }
7614
+ function tenantLookupFailureHint(tenantName, reason) {
7615
+ 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.`;
7616
+ }
7617
+ function decodePathSegment(segment) {
7618
+ const [error, decoded] = catchError2(() => decodeURIComponent(segment));
7619
+ return error ? segment : decoded;
7620
+ }
7506
7621
  var isFileNotFoundError = (error) => {
7507
7622
  if (!(error instanceof Object))
7508
7623
  return false;
@@ -7738,9 +7853,6 @@ function normalizeTokenRefreshUnavailableFailure() {
7738
7853
  function errorMessage(error) {
7739
7854
  return error instanceof Error ? error.message : String(error);
7740
7855
  }
7741
- // ../../auth/src/tenantSelection.ts
7742
- var IDENTIFIER_STATUSES = new Set([400, 403, 404]);
7743
-
7744
7856
  // ../../auth/src/selectTenant.ts
7745
7857
  var TENANT_SELECTION_REQUIRED_CODE = "TENANT_SELECTION_REQUIRED";
7746
7858
  var INVALID_TENANT_CODE = "INVALID_TENANT";
@@ -8370,4 +8482,4 @@ var registerCommands = async (program2) => {
8370
8482
 
8371
8483
  export { Command, metadata, registerCommands };
8372
8484
 
8373
- //# debugId=16BCBE778DFDA0FF64756E2164756E21
8485
+ //# debugId=75B2DEAAFA1C059A64756E2164756E21
package/dist/tool.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  metadata,
3
3
  registerCommands
4
- } from "./tool-d4dtfh4p.js";
4
+ } from "./tool-k29yy9j4.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/model-hub-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 the UiPath Model Hub (LLM Gateway organization-scoped views).",
7
7
  "private": false,
8
8
  "repository": {
@@ -27,5 +27,5 @@
27
27
  "files": [
28
28
  "dist"
29
29
  ],
30
- "gitHead": "699c58dabb59414557755a8933bcbe40aa420df3"
30
+ "gitHead": "63740c6cbb7ff282fa9118cc16a148eb030b245f"
31
31
  }