@uipath/cli 1.203.0-preview.203 → 1.204.0-preview.206

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.
@@ -24,7 +24,7 @@ import {
24
24
  readAuthFromEnv,
25
25
  resolveEnvFileLocationAsync,
26
26
  resolveEnvFilePathAsync
27
- } from "./index-vmn69waj.js";
27
+ } from "./index-zwnedwxc.js";
28
28
  import {
29
29
  AGENT_DEFS,
30
30
  AGENT_DISPLAY_NAMES,
@@ -34,12 +34,14 @@ import {
34
34
  DISABLE_AUTOINSTALL_ENV,
35
35
  DISABLE_TOOL_LINE_CHECK_ENV,
36
36
  HIDDEN_CHANNELS,
37
+ HostOwnedToolError,
37
38
  InstallRefusedError,
38
39
  PUBLIC_CHANNELS,
39
40
  SECRET_FIELD_PATHS,
40
41
  SkillSourceError,
41
42
  SkillsError,
42
43
  SkillsRegistryAuthError,
44
+ TOOLS_DIRS_ENV_VAR,
43
45
  TOOLS_UPDATE_PHASES,
44
46
  TOOLS_WHITELIST,
45
47
  VALID_CHANNELS,
@@ -56,6 +58,7 @@ import {
56
58
  getAvailableSkills,
57
59
  getContentStoreForRead,
58
60
  getEffectiveRegistry,
61
+ getEnvToolsDirsDeclaration,
59
62
  getGlobalNpmUipathDir,
60
63
  getInstalledTools,
61
64
  getSkillsDestinationHint,
@@ -81,10 +84,12 @@ import {
81
84
  readManifest,
82
85
  readState,
83
86
  recordToolUpdateDate,
87
+ refreshGlobalNpmUipathDir,
84
88
  rejectIfGlobalOnly,
85
89
  removeFromManifest,
86
90
  removeSkillCatalog,
87
91
  resolveConfigFilePathAsync,
92
+ resolveNpmPrefixForToolsDir,
88
93
  resolvePinnedVersion,
89
94
  resolveRootDir,
90
95
  resolveRuntimeChannel,
@@ -108,20 +113,28 @@ import {
108
113
  versionLinePrefix,
109
114
  versionMigrationNotice,
110
115
  withConfigLock
111
- } from "./index-ttatj0sp.js";
116
+ } from "./index-45h1c7ad.js";
112
117
  import {
118
+ AuthDimensions,
119
+ BaseDimensions,
120
+ CLI_APPLICATION_NAME,
113
121
  CONFIG_FILENAME,
114
122
  Command,
123
+ CommandDimensions,
124
+ CommonTelemetryEvents,
115
125
  DEFAULT_FETCH_TIMEOUT_MS,
116
126
  EXIT_CODES,
117
127
  LogLevel,
118
128
  OUTPUT_FORMATS,
129
+ Option,
119
130
  OutputFormatter,
120
131
  Pagination,
121
132
  REGISTER_EXPORT,
122
133
  RESULTS,
134
+ SkillsDimensions,
123
135
  TELEMETRY_ARG_VALUE_WITHHELD,
124
136
  UIPATH_HOME_DIR,
137
+ assertNoCuratedDimensionTargets,
125
138
  buildCommandTerminalTelemetryProperties,
126
139
  buildEnvironmentProperties,
127
140
  buildSkillEventTelemetryAttribution,
@@ -130,6 +143,7 @@ import {
130
143
  carriedInstructions,
131
144
  carriedRetry,
132
145
  catchError,
146
+ commandInvocationPath,
133
147
  commandTelemetryName,
134
148
  configureLogger,
135
149
  describeConnectivityError,
@@ -157,6 +171,7 @@ import {
157
171
  resolveEnvReference,
158
172
  runWithInvocationRequest,
159
173
  runWithTimings,
174
+ sanitizeTelemetryToken,
160
175
  setExecutionContextAuthSignal,
161
176
  setExitCode,
162
177
  setGlobalTelemetryProperties,
@@ -178,7 +193,7 @@ import {
178
193
  telemetryInit,
179
194
  telemetryShutdownWithoutFlush,
180
195
  validateOutputFilter
181
- } from "./index-7pvwjzsq.js";
196
+ } from "./index-kyn5nn3d.js";
182
197
  import {
183
198
  isBrowser
184
199
  } from "./index-0gctz400.js";
@@ -1005,7 +1020,6 @@ var FLAG_HINTS = {
1005
1020
  v: "--version"
1006
1021
  };
1007
1022
  function commandPartsFromArgs(cleanedArgs) {
1008
- const commandParts = [];
1009
1023
  const userArgs = cleanedArgs.slice(2);
1010
1024
  for (let i = 0;i < userArgs.length; i++) {
1011
1025
  const arg = userArgs[i];
@@ -1018,17 +1032,18 @@ function commandPartsFromArgs(cleanedArgs) {
1018
1032
  }
1019
1033
  continue;
1020
1034
  }
1021
- commandParts.push(arg);
1035
+ return [arg];
1022
1036
  }
1023
- return commandParts;
1037
+ return [];
1024
1038
  }
1025
1039
  function commandEventNameFromArgs(cleanedArgs) {
1026
1040
  return commandTelemetryName(commandPartsFromArgs(cleanedArgs));
1027
1041
  }
1028
- function helpInstructions(cleanedArgs) {
1029
- const commandParts = commandPartsFromArgs(cleanedArgs);
1030
- const command = ["uip", ...commandParts].join(" ");
1031
- return `Run '${command} --help' for usage information.`;
1042
+ function commandInvocationPathFromArgs(cleanedArgs) {
1043
+ return commandInvocationPath(commandPartsFromArgs(cleanedArgs));
1044
+ }
1045
+ function helpInstructions(commandPath) {
1046
+ return `Run '${commandPath} --help' for usage information.`;
1032
1047
  }
1033
1048
  function instructionsForUnknownCommand(cleanedArgs) {
1034
1049
  const firstUserToken = cleanedArgs.slice(2).find((a) => !a.startsWith("-"));
@@ -1044,10 +1059,11 @@ function isDisplayOnly(code, message) {
1044
1059
  function currentExitCode(fallback = 1) {
1045
1060
  return getExitCode() || fallback;
1046
1061
  }
1047
- function trackCommandFailure(error, eventName, exitCode, context) {
1062
+ function trackCommandFailure(error, eventName, commandPath, exitCode, context) {
1048
1063
  const recordedFailure = takeRecordedCommandFailureTelemetry();
1049
1064
  emitInvocationRequest(eventName, false, {
1050
- command: "true",
1065
+ [CommandDimensions.IsCommand]: "true",
1066
+ [CommandDimensions.CommandName]: commandPath,
1051
1067
  ...buildCommandTerminalTelemetryProperties({
1052
1068
  error,
1053
1069
  exitCode,
@@ -1068,7 +1084,7 @@ async function handleParseError(error, cleanedArgs, context, telemetryOptions) {
1068
1084
  context.exit(exitCode ?? 0);
1069
1085
  return;
1070
1086
  }
1071
- const instructions = code === "commander.unknownCommand" ? instructionsForUnknownCommand(cleanedArgs) : helpInstructions(cleanedArgs);
1087
+ const instructions = code === "commander.unknownCommand" ? instructionsForUnknownCommand(cleanedArgs) : helpInstructions(telemetryOptions.commandPath);
1072
1088
  OutputFormatter.error({
1073
1089
  Result: RESULTS.ValidationError,
1074
1090
  ErrorCode: "invalid_argument",
@@ -1077,12 +1093,12 @@ async function handleParseError(error, cleanedArgs, context, telemetryOptions) {
1077
1093
  Retry: "RetryWillNotFix"
1078
1094
  });
1079
1095
  const finalExitCode = currentExitCode();
1080
- trackCommandFailure(error, telemetryOptions.eventName, finalExitCode, context);
1096
+ trackCommandFailure(error, telemetryOptions.eventName, telemetryOptions.commandPath, finalExitCode, context);
1081
1097
  await telemetryFlushAndShutdown();
1082
1098
  context.exit(finalExitCode);
1083
1099
  return;
1084
1100
  }
1085
- trackCommandFailure(error, telemetryOptions.eventName, currentExitCode(), context);
1101
+ trackCommandFailure(error, telemetryOptions.eventName, telemetryOptions.commandPath, currentExitCode(), context);
1086
1102
  await telemetryFlushAndShutdown();
1087
1103
  context.exit(currentExitCode());
1088
1104
  }
@@ -1110,13 +1126,17 @@ function findUnknownHelpCommand(root, positionals, allArgs) {
1110
1126
  // cli.core.ts
1111
1127
  var HELP_FLAGS2 = new Set(["-h", "--help"]);
1112
1128
  var HELP_COMMAND_TOKEN = "help";
1129
+ var NO_APPLICATION_START = new Set([
1130
+ "uip track",
1131
+ `uip ${HELP_COMMAND_TOKEN}`
1132
+ ]);
1113
1133
  function findSubcommand(command, token) {
1114
1134
  return command.commands.find((subcommand) => subcommand.name() === token || subcommand.aliases().includes(token));
1115
1135
  }
1116
1136
  function optionValueTokens(userArgs, index) {
1117
1137
  return !userArgs[index].includes("=") && index + 1 < userArgs.length && !userArgs[index + 1].startsWith("-") ? 1 : 0;
1118
1138
  }
1119
- function commandEventNameFromProgram(program, cleanedArgs) {
1139
+ function commandPartsFromProgram(program, cleanedArgs) {
1120
1140
  const parts = [];
1121
1141
  let current = program;
1122
1142
  const userArgs = cleanedArgs.slice(2);
@@ -1143,15 +1163,16 @@ function commandEventNameFromProgram(program, cleanedArgs) {
1143
1163
  }
1144
1164
  break;
1145
1165
  }
1146
- return commandTelemetryName(parts);
1166
+ return parts;
1147
1167
  }
1148
- function trackRecordedCommandFailure(eventName, exitCode, context, error) {
1168
+ function trackRecordedCommandFailure(commandParts, exitCode, context, error) {
1149
1169
  const recordedFailure = takeRecordedCommandFailureTelemetry();
1150
1170
  if (!recordedFailure) {
1151
1171
  return;
1152
1172
  }
1153
- emitInvocationRequest(eventName, false, {
1154
- command: "true",
1173
+ emitInvocationRequest(commandTelemetryName(commandParts), false, {
1174
+ [CommandDimensions.IsCommand]: "true",
1175
+ [CommandDimensions.CommandName]: commandInvocationPath(commandParts),
1155
1176
  ...buildCommandTerminalTelemetryProperties({
1156
1177
  error,
1157
1178
  exitCode,
@@ -1161,8 +1182,10 @@ function trackRecordedCommandFailure(eventName, exitCode, context, error) {
1161
1182
  });
1162
1183
  }
1163
1184
  function emitEarlyExitRequest(context, options) {
1164
- emitInvocationRequest(commandEventNameFromArgs(context.args), options.success, {
1165
- ...options.delegated ? { reexec: "true" } : { command: "true" },
1185
+ const parts = options.program ? commandPartsFromProgram(options.program, context.args) : undefined;
1186
+ emitInvocationRequest(parts ? commandTelemetryName(parts) : commandEventNameFromArgs(context.args), options.success, {
1187
+ ...options.delegated ? { [CommandDimensions.IsReexec]: "true" } : { [CommandDimensions.IsCommand]: "true" },
1188
+ [CommandDimensions.CommandName]: parts ? commandInvocationPath(parts) : commandInvocationPathFromArgs(context.args),
1166
1189
  ...buildCommandTerminalTelemetryProperties({
1167
1190
  exitCode: getExitCode() || (options.success ? 0 : 1),
1168
1191
  recordedFailure: takeRecordedCommandFailureTelemetry(),
@@ -1170,6 +1193,12 @@ function emitEarlyExitRequest(context, options) {
1170
1193
  })
1171
1194
  });
1172
1195
  }
1196
+ function emitApplicationStart(context) {
1197
+ if (isHelpOrVersionInvocation(context.args) || NO_APPLICATION_START.has(commandInvocationPathFromArgs(context.args))) {
1198
+ return;
1199
+ }
1200
+ telemetry.trackEvent(CommonTelemetryEvents.Start, {});
1201
+ }
1173
1202
  function runCliInvocation(fn) {
1174
1203
  return runWithTimings(TIMING_FALLBACK_COMMAND, () => runWithInvocationRequest(fn));
1175
1204
  }
@@ -1293,13 +1322,14 @@ async function initProgram(context, hooks = {}) {
1293
1322
  })();
1294
1323
  const agent = detectAgent();
1295
1324
  const defaultTelemetryProperties = {
1296
- cli_version: package_default.version
1325
+ [BaseDimensions.ApplicationName]: CLI_APPLICATION_NAME,
1326
+ [BaseDimensions.ProductVersion]: package_default.version
1297
1327
  };
1298
1328
  if (agent !== undefined) {
1299
- defaultTelemetryProperties.agent = agent;
1329
+ defaultTelemetryProperties[BaseDimensions.Agent] = agent;
1300
1330
  const agentVersion = detectAgentVersion();
1301
1331
  if (agentVersion !== undefined) {
1302
- defaultTelemetryProperties.agent_version = agentVersion;
1332
+ defaultTelemetryProperties[BaseDimensions.AgentVersion] = agentVersion;
1303
1333
  }
1304
1334
  }
1305
1335
  const telemetryPromise = isHelpOrVersionInvocation(cleanedArgs) ? Promise.resolve() : telemetryInit({
@@ -1326,10 +1356,10 @@ function finalizeProgram(args) {
1326
1356
  async function parseAndExit(program, cleanedArgs, context) {
1327
1357
  logger.debug(`Parsing args: ${cleanedArgs.slice(2).join(" ")}`);
1328
1358
  const nameTimingCommand = () => {
1329
- setTimingCommand(commandEventNameFromProgram(program, cleanedArgs).replace(/\./g, " "));
1359
+ setTimingCommand(commandInvocationPath(commandPartsFromProgram(program, cleanedArgs)));
1330
1360
  };
1331
1361
  nameTimingCommand();
1332
- const initialCommandEventName = commandEventNameFromProgram(program, cleanedArgs);
1362
+ const initialCommandParts = commandPartsFromProgram(program, cleanedArgs);
1333
1363
  const userArgs = cleanedArgs.slice(2);
1334
1364
  const firstToken = userArgs.find((a) => !a.startsWith("-"));
1335
1365
  const unknownRoot = firstToken && findUnknownHelpCommand(program, [firstToken], userArgs);
@@ -1341,7 +1371,7 @@ async function parseAndExit(program, cleanedArgs, context) {
1341
1371
  Instructions: "Check command arguments and options. Run 'uip --help' for available commands."
1342
1372
  });
1343
1373
  const exitCode = getExitCode() || 1;
1344
- trackRecordedCommandFailure(initialCommandEventName, exitCode, context, {
1374
+ trackRecordedCommandFailure(initialCommandParts, exitCode, context, {
1345
1375
  code: "commander.unknownCommand",
1346
1376
  message
1347
1377
  });
@@ -1352,13 +1382,15 @@ async function parseAndExit(program, cleanedArgs, context) {
1352
1382
  const [parseError] = await catchError(program.parseAsync(cleanedArgs));
1353
1383
  nameTimingCommand();
1354
1384
  if (parseError) {
1385
+ const commandParts = commandPartsFromProgram(program, cleanedArgs);
1355
1386
  await handleParseError(parseError, cleanedArgs, context, {
1356
- eventName: commandEventNameFromProgram(program, cleanedArgs)
1387
+ eventName: commandTelemetryName(commandParts),
1388
+ commandPath: commandInvocationPath(commandParts)
1357
1389
  });
1358
1390
  } else {
1359
1391
  const exitCode = getExitCode();
1360
1392
  if (exitCode !== 0) {
1361
- trackRecordedCommandFailure(commandEventNameFromProgram(program, cleanedArgs), exitCode, context);
1393
+ trackRecordedCommandFailure(commandPartsFromProgram(program, cleanedArgs), exitCode, context);
1362
1394
  }
1363
1395
  }
1364
1396
  if (getExitCode() === 0) {
@@ -1649,6 +1681,11 @@ async function resolveToolsDirs(cliFilePath, cwd) {
1649
1681
  const seen = new Set;
1650
1682
  const dirs = [];
1651
1683
  const cliDir = dirname(cliFilePath);
1684
+ const declaration = await getEnvToolsDirsDeclaration();
1685
+ if (declaration) {
1686
+ logger.debug(`Using only the host-declared tool directories: [${declaration.dirs.join(", ")}]`);
1687
+ return [...declaration.dirs];
1688
+ }
1652
1689
  const localCliToolsDir = await findNearestLocalCliToolsDir(cwd);
1653
1690
  if (localCliToolsDir) {
1654
1691
  seen.add(localCliToolsDir);
@@ -2936,26 +2973,26 @@ var promptSelect = async (options, message) => {
2936
2973
  // src/services/auth.ts
2937
2974
  class NodeAuth {
2938
2975
  async interactiveLogin(options) {
2939
- const { interactiveLogin } = await import("./index-hgvsratt.js");
2976
+ const { interactiveLogin } = await import("./index-mttdq2yn.js");
2940
2977
  return await interactiveLogin({
2941
2978
  ...options,
2942
2979
  selectFromList: promptSelect
2943
2980
  });
2944
2981
  }
2945
2982
  async clientCredentialsLogin(options) {
2946
- const { clientCredentialsLogin } = await import("./index-hgvsratt.js");
2983
+ const { clientCredentialsLogin } = await import("./index-mttdq2yn.js");
2947
2984
  return await clientCredentialsLogin(options);
2948
2985
  }
2949
2986
  async getLoginStatus(options) {
2950
- const { getLoginStatusAsync: getLoginStatusAsync2 } = await import("./index-hgvsratt.js");
2987
+ const { getLoginStatusAsync: getLoginStatusAsync2 } = await import("./index-mttdq2yn.js");
2951
2988
  return getLoginStatusAsync2(options);
2952
2989
  }
2953
2990
  async fetchTenants(baseUrl, accessToken, organizationId) {
2954
- const { fetchTenantsAndOrganizations } = await import("./index-hgvsratt.js");
2991
+ const { fetchTenantsAndOrganizations } = await import("./index-mttdq2yn.js");
2955
2992
  return fetchTenantsAndOrganizations(baseUrl, accessToken, organizationId);
2956
2993
  }
2957
2994
  async saveTenantSelection(envFilePath, tenantName, tenantId) {
2958
- const { saveEnvFileAsync } = await import("./index-hgvsratt.js");
2995
+ const { saveEnvFileAsync } = await import("./index-mttdq2yn.js");
2959
2996
  await saveEnvFileAsync({
2960
2997
  envPath: envFilePath,
2961
2998
  data: {
@@ -2969,23 +3006,23 @@ class NodeAuth {
2969
3006
 
2970
3007
  class BrowserAuth {
2971
3008
  async interactiveLogin(options) {
2972
- const { interactiveLogin } = await import("./index-hgvsratt.js");
3009
+ const { interactiveLogin } = await import("./index-mttdq2yn.js");
2973
3010
  return await interactiveLogin(options);
2974
3011
  }
2975
3012
  async clientCredentialsLogin(options) {
2976
- const { clientCredentialsLogin } = await import("./index-hgvsratt.js");
3013
+ const { clientCredentialsLogin } = await import("./index-mttdq2yn.js");
2977
3014
  return await clientCredentialsLogin(options);
2978
3015
  }
2979
3016
  async getLoginStatus(options) {
2980
- const { getLoginStatusAsync: getLoginStatusAsync2 } = await import("./index-hgvsratt.js");
3017
+ const { getLoginStatusAsync: getLoginStatusAsync2 } = await import("./index-mttdq2yn.js");
2981
3018
  return getLoginStatusAsync2(options);
2982
3019
  }
2983
3020
  async fetchTenants(baseUrl, accessToken, organizationId) {
2984
- const { fetchTenantsAndOrganizations } = await import("./index-hgvsratt.js");
3021
+ const { fetchTenantsAndOrganizations } = await import("./index-mttdq2yn.js");
2985
3022
  return fetchTenantsAndOrganizations(baseUrl, accessToken, organizationId);
2986
3023
  }
2987
3024
  async saveTenantSelection(envFilePath, tenantName, tenantId) {
2988
- const { saveEnvFileAsync } = await import("./index-hgvsratt.js");
3025
+ const { saveEnvFileAsync } = await import("./index-mttdq2yn.js");
2989
3026
  await saveEnvFileAsync({
2990
3027
  envPath: envFilePath,
2991
3028
  data: {
@@ -3000,10 +3037,10 @@ var auth = isBrowser() ? new BrowserAuth : new NodeAuth;
3000
3037
 
3001
3038
  // src/services/authTelemetry.ts
3002
3039
  var AuthTelemetryEvents = {
3003
- Login: "uip.auth.login",
3004
- TenantSelected: "uip.auth.tenant-selected",
3005
- TokenRefresh: "uip.auth.token-refresh",
3006
- Logout: "uip.auth.logout"
3040
+ Login: "Authenticate.LogIn",
3041
+ TenantSelected: "Authenticate.TenantSelected",
3042
+ TokenRefresh: "Authenticate.TokenRefresh",
3043
+ Logout: "Authenticate.LogOut"
3007
3044
  };
3008
3045
  var UIPATH_EMAIL_DOMAIN = "uipath.com";
3009
3046
  var decodeTokenClaims = (accessToken) => {
@@ -3079,11 +3116,11 @@ var populateTelemetryAuthContext = async (deps = {}) => {
3079
3116
  const isInternalUser = getInternalUserFlag(claims);
3080
3117
  const envProps = identity.baseUrl ? buildEnvironmentProperties(identity.baseUrl) : {};
3081
3118
  const defaultProps = {
3082
- ...userId ? { CloudUserId: userId } : {},
3083
- ...identity.tenantId ? { CloudTenantId: identity.tenantId } : {},
3084
- ...identity.organizationId ? { CloudOrganizationId: identity.organizationId } : {},
3119
+ ...userId ? { [BaseDimensions.CloudUserId]: userId } : {},
3120
+ ...identity.tenantId ? { [BaseDimensions.CloudTenantId]: identity.tenantId } : {},
3121
+ ...identity.organizationId ? { [BaseDimensions.CloudOrganizationId]: identity.organizationId } : {},
3085
3122
  ...envProps,
3086
- ...isInternalUser !== undefined ? { IsInternalUser: isInternalUser } : {}
3123
+ ...isInternalUser !== undefined ? { [BaseDimensions.IsInternalUser]: isInternalUser } : {}
3087
3124
  };
3088
3125
  if (Object.keys(defaultProps).length === 0)
3089
3126
  return;
@@ -3093,29 +3130,31 @@ var populateTelemetryAuthContext = async (deps = {}) => {
3093
3130
  };
3094
3131
  var trackAuthLogin = (flow, result) => {
3095
3132
  telemetry.trackEvent(AuthTelemetryEvents.Login, {
3096
- flow,
3097
- success: String(result.success),
3098
- ...!result.success ? { errorMessage: result.errorMessage } : {}
3133
+ [AuthDimensions.AuthenticationMethod]: flow,
3134
+ [AuthDimensions.Success]: String(result.success),
3135
+ ...!result.success ? { [CommandDimensions.ErrorMessage]: result.errorMessage } : {}
3099
3136
  });
3100
3137
  };
3101
3138
  var trackTenantSelection = (result) => {
3102
3139
  telemetry.trackEvent(AuthTelemetryEvents.TenantSelected, {
3103
- success: String(result.success),
3104
- ...!result.success && result.errorMessage ? { errorMessage: result.errorMessage } : {}
3140
+ [AuthDimensions.Success]: String(result.success),
3141
+ ...!result.success && result.errorMessage ? { [CommandDimensions.ErrorMessage]: result.errorMessage } : {}
3105
3142
  });
3106
3143
  };
3107
3144
  var trackTokenRefresh = (status) => {
3108
3145
  if (!status.tokenRefresh?.attempted)
3109
3146
  return;
3110
3147
  telemetry.trackEvent(AuthTelemetryEvents.TokenRefresh, {
3111
- success: String(status.tokenRefresh.success),
3112
- ...status.tokenRefresh.errorMessage ? { errorMessage: status.tokenRefresh.errorMessage } : {}
3148
+ [AuthDimensions.Success]: String(status.tokenRefresh.success),
3149
+ ...status.tokenRefresh.errorMessage ? {
3150
+ [CommandDimensions.ErrorMessage]: status.tokenRefresh.errorMessage
3151
+ } : {}
3113
3152
  });
3114
3153
  };
3115
3154
  var trackAuthLogout = (result) => {
3116
3155
  telemetry.trackEvent(AuthTelemetryEvents.Logout, {
3117
- success: String(result.success),
3118
- ...!result.success && result.reason ? { reason: result.reason } : {}
3156
+ [AuthDimensions.Success]: String(result.success),
3157
+ ...!result.success && result.reason ? { [AuthDimensions.Reason]: result.reason } : {}
3119
3158
  });
3120
3159
  };
3121
3160
 
@@ -3543,6 +3582,9 @@ function buildIdentityDetail(identity) {
3543
3582
  ...identity.clientId ? { ClientId: identity.clientId } : {}
3544
3583
  };
3545
3584
  }
3585
+ function buildScopeDetail(scopes, detailed) {
3586
+ return detailed && scopes ? { Scopes: scopes } : {};
3587
+ }
3546
3588
  function buildRefreshData(status) {
3547
3589
  const data = {
3548
3590
  Status: status.loginStatus,
@@ -3728,6 +3770,21 @@ var LOGIN_STATUS_EXAMPLES = [
3728
3770
  "Expiration Date": "2026-04-18T10:30:00Z"
3729
3771
  }
3730
3772
  }
3773
+ },
3774
+ {
3775
+ Description: "Check which scopes the current token carries — the usual reason a command returns 401 or 403 while the session looks fine",
3776
+ Command: "uip login status --detailed --output json",
3777
+ Output: {
3778
+ Code: "LoginStatus",
3779
+ Data: {
3780
+ Status: "Logged in",
3781
+ Identity: "External application 4af76c75-c800-4ff5-b559-32610fa9ef1e",
3782
+ IdentityType: "Application",
3783
+ AuthFlow: "ClientCredentials",
3784
+ ClientId: "4af76c75-c800-4ff5-b559-32610fa9ef1e",
3785
+ Scopes: ["TM.Projects", "TM.TestCases", "TM.TestSets"]
3786
+ }
3787
+ }
3731
3788
  }
3732
3789
  ];
3733
3790
  var LOGIN_REFRESH_EXAMPLES = [
@@ -4034,12 +4091,12 @@ Open this URL in a browser to sign in:
4034
4091
  Data: buildLoginData(authResult ?? {})
4035
4092
  });
4036
4093
  }, (options) => ({
4037
- hasClientCredentials: !!(options.clientId && options.clientSecret),
4038
- hasTenant: !!options.tenant,
4039
- hasOrganization: !!options.organization,
4040
- interactive: canPrompt()
4094
+ HasClientCredentials: !!(options.clientId && options.clientSecret),
4095
+ HasTenant: !!options.tenant,
4096
+ HasOrganization: !!options.organization,
4097
+ Interactive: canPrompt()
4041
4098
  }));
4042
- loginCommand.command("status").description("Show current login status and session information").examples(LOGIN_STATUS_EXAMPLES).trackedAction(context, async () => {
4099
+ loginCommand.command("status").description("Show current login status and session information").addOption(new Option("--detailed", "Also show the scopes the access token carries").hideHelp()).examples(LOGIN_STATUS_EXAMPLES).trackedAction(context, async (options) => {
4043
4100
  const [statusError, status] = await catchError(auth.getLoginStatus());
4044
4101
  if (statusError) {
4045
4102
  OutputFormatter.error({
@@ -4058,6 +4115,7 @@ Open this URL in a browser to sign in:
4058
4115
  CredentialSource: credentialSourceLabel(status.source),
4059
4116
  Provider: legacyProviderLabel(status.source),
4060
4117
  ...buildIdentityDetail(status.identity),
4118
+ ...buildScopeDetail(status.scopes, options.detailed === true),
4061
4119
  ...activeProfile && status.source === "saved-login" /* SavedLogin */ ? { Profile: activeProfile } : {},
4062
4120
  BaseUrl: status.baseUrl,
4063
4121
  Organization: status.organizationName || status.organizationId || "N/A"
@@ -4109,7 +4167,7 @@ Open this URL in a browser to sign in:
4109
4167
  Data: buildRefreshData(status)
4110
4168
  });
4111
4169
  }, (options) => ({
4112
- loginValidityMinutes: options.loginValidity
4170
+ LoginValidityMinutes: options.loginValidity
4113
4171
  }));
4114
4172
  registerProfilesCommand(loginCommand, context);
4115
4173
  const tenantCommand = loginCommand.command("tenant").description("Manage tenants");
@@ -4263,7 +4321,7 @@ Open this URL in a browser to sign in:
4263
4321
  Id: matchedTenant.id
4264
4322
  }
4265
4323
  });
4266
- }, (name) => ({ tenantName: name }));
4324
+ }, (name) => ({ TenantName: name }));
4267
4325
  loginCommand.command("which").description("Print the auth source uip would use for the current cwd.").examples(LOGIN_WHICH_EXAMPLES).trackedAction(context, async () => {
4268
4326
  if (isEnvAuthEnabled()) {
4269
4327
  emitAuthEnv();
@@ -4390,7 +4448,7 @@ function registerLogoutCommand(program, context) {
4390
4448
  function registerMcpCommand(program) {
4391
4449
  const mcpCommand = program.command("mcp").description("Model Context Protocol (MCP) server");
4392
4450
  mcpCommand.command("serve").description("Start the MCP server (stdio transport)").trackedAction(processContext, async () => {
4393
- const { startMcpServer } = await import("./server-82exah8x.js");
4451
+ const { startMcpServer } = await import("./server-x6j9cv7f.js");
4394
4452
  await startMcpServer(program);
4395
4453
  });
4396
4454
  }
@@ -5074,10 +5132,10 @@ function registerFeedbackCommand(program, context) {
5074
5132
  }
5075
5133
  });
5076
5134
  }, (options) => ({
5077
- feedbackType: options.type,
5078
- priority: options.priority,
5079
- hasEmail: !!options.email,
5080
- attachmentCount: options.attachment?.length ?? 0
5135
+ FeedbackType: options.type,
5136
+ Priority: options.priority,
5137
+ HasEmail: !!options.email,
5138
+ AttachmentCount: options.attachment?.length ?? 0
5081
5139
  }));
5082
5140
  }
5083
5141
 
@@ -5787,7 +5845,8 @@ function registerInstallCommand2(toolsCommand, _context, state) {
5787
5845
  packageSpec = `${packageName}@${candidate.version}`;
5788
5846
  }
5789
5847
  await toolService.install(packageSpec, location.path, {
5790
- global: location.global
5848
+ global: location.global,
5849
+ prefix: location.prefix
5791
5850
  });
5792
5851
  logger.info(`Installed to ${location.path}`);
5793
5852
  OutputFormatter.success({
@@ -5966,7 +6025,8 @@ function registerUninstallCommand2(toolsCommand, _context, state) {
5966
6025
  }
5967
6026
  async function runUninstall(packageName, location) {
5968
6027
  const [error] = await catchError(toolService.uninstall(packageName, location.path, {
5969
- global: location.global
6028
+ global: location.global,
6029
+ prefix: location.prefix
5970
6030
  }));
5971
6031
  return error;
5972
6032
  }
@@ -6030,7 +6090,7 @@ async function uninstallAll(state) {
6030
6090
  const results = [];
6031
6091
  for (const tool of installed) {
6032
6092
  const error = await runUninstall(`@uipath/${tool.name}`, location);
6033
- results.push(error ? { name: tool.name, status: "failed", error: error.message } : { name: tool.name, status: "uninstalled" });
6093
+ results.push(!error ? { name: tool.name, status: "uninstalled" } : error instanceof HostOwnedToolError ? { name: tool.name, status: "skipped", error: error.message } : { name: tool.name, status: "failed", error: error.message });
6034
6094
  }
6035
6095
  OutputFormatter.success({
6036
6096
  Result: RESULTS.Success,
@@ -6157,37 +6217,239 @@ function registerToolsCommand(program, context, state) {
6157
6217
  registerUninstallCommand2(toolsCommand, context, state);
6158
6218
  }
6159
6219
 
6220
+ // src/commands/track-hook.ts
6221
+ var SCHEMA_VERSION = 4;
6222
+ var GENERIC_AGENT_TYPES = new Set([
6223
+ "general-purpose",
6224
+ "Explore",
6225
+ "Plan",
6226
+ "claude",
6227
+ "claude-code-guide",
6228
+ "statusline-setup",
6229
+ "fork",
6230
+ "default"
6231
+ ]);
6232
+ var FILE_TOOLS = new Set([
6233
+ "Edit",
6234
+ "Write",
6235
+ "Read",
6236
+ "Glob",
6237
+ "Grep",
6238
+ "ReadFile",
6239
+ "WriteFile",
6240
+ "EditFile",
6241
+ "LsDirectory"
6242
+ ]);
6243
+ function isPlainObject2(value) {
6244
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6245
+ }
6246
+ function str(value) {
6247
+ return typeof value === "string" ? value : "";
6248
+ }
6249
+ function isTrue(value) {
6250
+ return value === true || value === "true";
6251
+ }
6252
+ function isFalse(value) {
6253
+ return value === false || value === "false";
6254
+ }
6255
+ function extractFields(payload) {
6256
+ const input = isPlainObject2(payload.tool_input) ? payload.tool_input : {};
6257
+ const response = isPlainObject2(payload.tool_response) ? payload.tool_response : {};
6258
+ const effort = isPlainObject2(payload.effort) ? payload.effort : {};
6259
+ let agentModel = str(payload.model);
6260
+ if (!agentModel && isPlainObject2(payload.model)) {
6261
+ agentModel = str(payload.model.id) || str(payload.model.display_name);
6262
+ }
6263
+ const rawDuration = payload.duration_ms;
6264
+ const parsedDuration = typeof rawDuration === "string" && /^[0-9]+$/.test(rawDuration) ? Number(rawDuration) : rawDuration;
6265
+ const durationMs = Number.isSafeInteger(parsedDuration) && parsedDuration >= 0 ? parsedDuration : null;
6266
+ return {
6267
+ event: str(payload.hook_event_name),
6268
+ tool: str(payload.tool_name),
6269
+ permissionMode: str(payload.permission_mode),
6270
+ durationMs,
6271
+ agentType: str(payload.agent_type),
6272
+ sessionSource: str(payload.source),
6273
+ reason: str(payload.reason),
6274
+ agentModel,
6275
+ skill: str(input.skill),
6276
+ filePath: str(input.file_path),
6277
+ subagentType: str(input.subagent_type) || str(input.agent_type),
6278
+ interrupted: response.interrupted,
6279
+ success: response.success,
6280
+ resolvedModel: str(response.resolvedModel),
6281
+ effortLevel: str(effort.level),
6282
+ responseSeen: "tool_response" in payload
6283
+ };
6284
+ }
6285
+ function isUipathCall(fields) {
6286
+ if (fields.tool === "Skill") {
6287
+ return fields.skill.startsWith("uipath:") || fields.skill.startsWith("uipath-");
6288
+ }
6289
+ if (fields.tool === "Agent" || fields.tool === "spawn_agent") {
6290
+ const type = fields.subagentType;
6291
+ if (type.startsWith("uipath:") || type.startsWith("uipath-")) {
6292
+ return true;
6293
+ }
6294
+ return GENERIC_AGENT_TYPES.has(type);
6295
+ }
6296
+ if (FILE_TOOLS.has(fields.tool)) {
6297
+ return /\.(cs|flow|xaml|uipx|bpmn)$/i.test(fields.filePath) || /(^|[/\\])(agent|caseplan|project|app\.config|action-schema)\.json$/i.test(fields.filePath);
6298
+ }
6299
+ return false;
6300
+ }
6301
+ function deriveFields(fields) {
6302
+ const derived = { skillName: "", fileExtension: "" };
6303
+ if (fields.tool === "Skill") {
6304
+ derived.skillName = fields.skill;
6305
+ } else if (FILE_TOOLS.has(fields.tool)) {
6306
+ const match = fields.filePath.match(/\.[A-Za-z0-9]+$/);
6307
+ derived.fileExtension = match ? match[0] : "";
6308
+ if (fields.filePath.endsWith("agent.json")) {
6309
+ derived.fileExtension = "agent.json";
6310
+ }
6311
+ if (fields.filePath.endsWith("caseplan.json")) {
6312
+ derived.fileExtension = "caseplan.json";
6313
+ }
6314
+ }
6315
+ return derived;
6316
+ }
6317
+ function computeOutcome(fields) {
6318
+ if (isTrue(fields.interrupted)) {
6319
+ return "interrupted";
6320
+ }
6321
+ if (isFalse(fields.success)) {
6322
+ return "failure";
6323
+ }
6324
+ return fields.responseSeen ? "ok" : "unknown";
6325
+ }
6326
+ function mapEventName(event) {
6327
+ switch (event) {
6328
+ case "PostToolUse":
6329
+ return "tool-use";
6330
+ case "SessionStart":
6331
+ return "session-start";
6332
+ case "SessionEnd":
6333
+ return "session-end";
6334
+ case "Stop":
6335
+ case "StopFailure":
6336
+ return "completion";
6337
+ default:
6338
+ return "";
6339
+ }
6340
+ }
6341
+ function lifecycleOutcome(event) {
6342
+ if (event === "Stop") {
6343
+ return "ok";
6344
+ }
6345
+ if (event === "StopFailure") {
6346
+ return "failure";
6347
+ }
6348
+ return "";
6349
+ }
6350
+ function modelFamily(resolvedModel) {
6351
+ if (!resolvedModel) {
6352
+ return "";
6353
+ }
6354
+ for (const family of ["opus", "sonnet", "haiku", "fable"]) {
6355
+ if (resolvedModel.includes(family)) {
6356
+ return family;
6357
+ }
6358
+ }
6359
+ return "other";
6360
+ }
6361
+ async function readPluginSkillsVersion() {
6362
+ const fs = getFileSystem();
6363
+ const root = fs.env.getenv("CLAUDE_PLUGIN_ROOT");
6364
+ if (!root) {
6365
+ return "";
6366
+ }
6367
+ try {
6368
+ const manifest = await fs.readFile(fs.path.join(root, "version-manifest.json"), "utf-8");
6369
+ const version = manifest ? JSON.parse(manifest).skillsVersion : undefined;
6370
+ return typeof version === "string" ? version : "";
6371
+ } catch {
6372
+ return "";
6373
+ }
6374
+ }
6375
+ function deriveSkillsEventFromHookPayload(raw, skillsVersion) {
6376
+ let payload;
6377
+ try {
6378
+ payload = JSON.parse(raw);
6379
+ } catch {
6380
+ return null;
6381
+ }
6382
+ if (!isPlainObject2(payload)) {
6383
+ return null;
6384
+ }
6385
+ const fields = extractFields(payload);
6386
+ const eventName = mapEventName(fields.event);
6387
+ if (!eventName) {
6388
+ return null;
6389
+ }
6390
+ let derived = { skillName: "", fileExtension: "" };
6391
+ let outcome;
6392
+ let subagentModel = "";
6393
+ if (eventName === "tool-use") {
6394
+ if (!isUipathCall(fields)) {
6395
+ return null;
6396
+ }
6397
+ derived = deriveFields(fields);
6398
+ outcome = computeOutcome(fields);
6399
+ subagentModel = modelFamily(fields.resolvedModel);
6400
+ } else {
6401
+ outcome = lifecycleOutcome(fields.event);
6402
+ }
6403
+ const sessionSource = eventName === "session-start" ? fields.sessionSource : "";
6404
+ const reason = eventName === "session-end" ? fields.reason : "";
6405
+ return {
6406
+ schemaVersion: SCHEMA_VERSION,
6407
+ eventName: sanitizeTelemetryToken(eventName),
6408
+ skillName: sanitizeTelemetryToken(derived.skillName),
6409
+ fileExtension: sanitizeTelemetryToken(derived.fileExtension),
6410
+ outcome: sanitizeTelemetryToken(outcome),
6411
+ permissionMode: sanitizeTelemetryToken(fields.permissionMode),
6412
+ effortLevel: sanitizeTelemetryToken(fields.effortLevel),
6413
+ skillsVersion: sanitizeTelemetryToken(skillsVersion),
6414
+ subagentModel: sanitizeTelemetryToken(subagentModel),
6415
+ subagentType: sanitizeTelemetryToken(fields.subagentType),
6416
+ agentType: sanitizeTelemetryToken(fields.agentType),
6417
+ agent_model: sanitizeTelemetryToken(fields.agentModel),
6418
+ session_source: sanitizeTelemetryToken(sessionSource),
6419
+ reason: sanitizeTelemetryToken(reason),
6420
+ durationMs: fields.durationMs
6421
+ };
6422
+ }
6423
+
6160
6424
  // src/commands/track.ts
6161
6425
  var SKILLS_EVENTS = {
6162
- "tool-use": "uip.skills.tool-use",
6163
- "session-start": "uip.skills.session-start",
6164
- "session-end": "uip.skills.session-end",
6165
- completion: "uip.skills.completion"
6426
+ "tool-use": "Cli.SkillsToolUse",
6427
+ "session-start": "Cli.SkillsSessionStart",
6428
+ "session-end": "Cli.SkillsSessionEnd",
6429
+ completion: "Cli.SkillsCompletion"
6166
6430
  };
6167
6431
  var DEFAULT_EVENT_TOKEN = "tool-use";
6168
- var SOURCE_DIMENSION_KEY = "source";
6432
+ var SOURCE_DIMENSION_KEY = SkillsDimensions.Source;
6169
6433
  var SOURCE_DIMENSION_VALUE = "skills-plugin";
6170
6434
  var STDIN_TIMEOUT_MS = 1e4;
6171
- var ALLOWED_FIELDS = new Set([
6172
- "schemaVersion",
6173
- "toolName",
6174
- "skillName",
6175
- "skill_name",
6176
- "uipSubcommand",
6177
- "fileExtension",
6178
- "outcome",
6179
- "permissionMode",
6180
- "effortLevel",
6181
- "skillsVersion",
6182
- "toolUseId",
6183
- "subagentModel",
6184
- "subagentType",
6185
- "agentType",
6186
- "durationMs",
6187
- "session_source",
6188
- "reason",
6189
- "agent_model"
6190
- ]);
6435
+ var ALLOWED_FIELDS = {
6436
+ schemaVersion: SkillsDimensions.SchemaVersion,
6437
+ uipSubcommand: SkillsDimensions.UipSubcommand,
6438
+ fileExtension: SkillsDimensions.FileExtension,
6439
+ outcome: SkillsDimensions.Outcome,
6440
+ permissionMode: SkillsDimensions.PermissionMode,
6441
+ effortLevel: SkillsDimensions.EffortLevel,
6442
+ skillsVersion: SkillsDimensions.SkillsVersion,
6443
+ subagentModel: SkillsDimensions.SubagentModel,
6444
+ subagentType: SkillsDimensions.SubagentType,
6445
+ agentType: SkillsDimensions.AgentType,
6446
+ durationMs: SkillsDimensions.DurationMs,
6447
+ session_source: SkillsDimensions.SessionSource,
6448
+ reason: AuthDimensions.Reason,
6449
+ agent_model: BaseDimensions.AgentModel
6450
+ };
6451
+ var SKILL_NAME_INPUT_KEYS = ["skill_name", "skillName"];
6452
+ assertNoCuratedDimensionTargets(ALLOWED_FIELDS, "[track] ALLOWED_FIELDS");
6191
6453
  function isParsableJson(raw) {
6192
6454
  try {
6193
6455
  JSON.parse(raw);
@@ -6223,18 +6485,23 @@ function buildEventProperties(raw) {
6223
6485
  }
6224
6486
  const properties = {};
6225
6487
  for (const [key, value] of Object.entries(payload)) {
6226
- if (!ALLOWED_FIELDS.has(key)) {
6488
+ const dimension = ALLOWED_FIELDS[key];
6489
+ if (!dimension) {
6227
6490
  continue;
6228
6491
  }
6229
6492
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
6230
- properties[key] = String(value);
6493
+ properties[dimension] = String(value);
6231
6494
  }
6232
6495
  }
6233
- let attribution = buildSkillEventTelemetryAttribution(properties.skill_name ?? properties.skillName, properties.uipSubcommand);
6234
- if (!attribution.skill_name && properties.skillName !== undefined) {
6235
- attribution = buildSkillEventTelemetryAttribution(properties.skillName, properties.uipSubcommand);
6496
+ const skillNameInputs = SKILL_NAME_INPUT_KEYS.map((key) => {
6497
+ const value = payload[key];
6498
+ return typeof value === "string" ? value : undefined;
6499
+ });
6500
+ const subcommand = properties[SkillsDimensions.UipSubcommand];
6501
+ let attribution = buildSkillEventTelemetryAttribution(skillNameInputs[0] ?? skillNameInputs[1], subcommand);
6502
+ if (!attribution.SkillName && skillNameInputs[1] !== undefined) {
6503
+ attribution = buildSkillEventTelemetryAttribution(skillNameInputs[1], subcommand);
6236
6504
  }
6237
- delete properties.skill_name;
6238
6505
  Object.assign(properties, attribution);
6239
6506
  if (Object.keys(properties).length === 0) {
6240
6507
  return null;
@@ -6242,9 +6509,9 @@ function buildEventProperties(raw) {
6242
6509
  return properties;
6243
6510
  }
6244
6511
  function registerTrackCommand(program) {
6245
- program.command("track", { hidden: true }).description("Ingest a skills-plugin telemetry event from stdin").action(async () => {
6512
+ program.command("track", { hidden: true }).description("Ingest a skills-plugin telemetry event from stdin").option("--hook", "stdin carries a raw agent hook payload instead of a flat event").action(async (options) => {
6246
6513
  try {
6247
- const raw = await readStdinWithTimeout(STDIN_TIMEOUT_MS);
6514
+ let raw = await readStdinWithTimeout(STDIN_TIMEOUT_MS);
6248
6515
  if (isTelemetryDisabled()) {
6249
6516
  logger.debug("[track] telemetry disabled; dropping event.");
6250
6517
  return;
@@ -6253,6 +6520,14 @@ function registerTrackCommand(program) {
6253
6520
  logger.debug("[track] no payload on stdin.");
6254
6521
  return;
6255
6522
  }
6523
+ if (options.hook) {
6524
+ const derived = deriveSkillsEventFromHookPayload(raw, await readPluginSkillsVersion());
6525
+ if (!derived) {
6526
+ logger.debug("[track] hook payload dropped (malformed, unrecognized event, or not attributable).");
6527
+ return;
6528
+ }
6529
+ raw = JSON.stringify(derived);
6530
+ }
6256
6531
  const eventName = resolveSkillsEventName(raw);
6257
6532
  if (!eventName) {
6258
6533
  logger.debug(isParsableJson(raw) ? "[track] unknown or invalid eventName; dropping event." : "[track] malformed JSON payload; dropping event.");
@@ -6459,7 +6734,11 @@ function registerUpdateCommand3(program, _context, state) {
6459
6734
  };
6460
6735
  const [err, report] = await catchError((async () => {
6461
6736
  const isDev = await isDevMode();
6462
- const location = await state.resolveInstallPath();
6737
+ const [locationError, location] = await catchError(state.resolveInstallPath());
6738
+ if (locationError && !(locationError instanceof InstallRefusedError)) {
6739
+ throw locationError;
6740
+ }
6741
+ const hostOwnsCli = await getEnvToolsDirsDeclaration() !== null;
6463
6742
  return runUpdate({
6464
6743
  dryRun: raw.dryRun ?? false,
6465
6744
  channel,
@@ -6472,14 +6751,14 @@ function registerUpdateCommand3(program, _context, state) {
6472
6751
  agent: raw.agent,
6473
6752
  local: raw.local
6474
6753
  },
6475
- cli: { self: raw.self !== false },
6754
+ cli: { self: raw.self !== false && !hostOwnsCli },
6476
6755
  versionPin: target.pin,
6477
6756
  versionPinOrigin: target.origin
6478
6757
  }, state, {
6479
6758
  cliPkgVersion: package_default.version,
6480
- isLocal: !location.global,
6759
+ isLocal: location ? !location.global : false,
6481
6760
  isDev,
6482
- installPath: location.path
6761
+ installPath: location?.path ?? ""
6483
6762
  });
6484
6763
  })());
6485
6764
  if (err) {
@@ -6611,6 +6890,20 @@ function createInstallPathResolver(toolsDir, isBrowser2) {
6611
6890
  const { getFileSystem: getFileSystem2 } = await import("./index-hhsf00x8.js");
6612
6891
  const fsLocal = getFileSystem2();
6613
6892
  const { dirname: dirnameFn, join: joinFn } = fsLocal.path;
6893
+ const declaration = await getEnvToolsDirsDeclaration();
6894
+ if (declaration) {
6895
+ const target = declaration.installTarget;
6896
+ const prefix = target ? resolveNpmPrefixForToolsDir(target) : null;
6897
+ if (prefix) {
6898
+ const [mkdirError] = await catchError(fsLocal.mkdir(prefix));
6899
+ if (mkdirError) {
6900
+ throw new InstallRefusedError(`Cannot create the ${TOOLS_DIRS_ENV_VAR} install prefix ${prefix}: ${String(mkdirError)}`, `Make the first ${TOOLS_DIRS_ENV_VAR} entry's npm prefix writable.`);
6901
+ }
6902
+ logger.debug(`Install path resolved from ${TOOLS_DIRS_ENV_VAR}: ${prefix} (global: true)`);
6903
+ return { path: prefix, global: true, prefix };
6904
+ }
6905
+ throw new InstallRefusedError(`${TOOLS_DIRS_ENV_VAR} names no usable install target${target ? ` (${target} is not an npm global layout for this platform)` : ""}; refusing to install outside the host's tool directories.`, `Declare a writable npm global '@uipath' directory as the first ${TOOLS_DIRS_ENV_VAR} entry.`);
6906
+ }
6614
6907
  if (toolsDir) {
6615
6908
  let path = dirnameFn(dirnameFn(toolsDir));
6616
6909
  while (isInsideNodeModules(path)) {
@@ -6641,7 +6934,7 @@ function createInstallPathResolver(toolsDir, isBrowser2) {
6641
6934
  }
6642
6935
 
6643
6936
  // src/services/installTelemetry.ts
6644
- var INSTALL_ID_TELEMETRY_KEY = "install_id";
6937
+ var INSTALL_ID_TELEMETRY_KEY = BaseDimensions.InstallationId;
6645
6938
  function shouldPopulateTelemetryInstallContext(args) {
6646
6939
  return !isHelpOrVersionInvocation([...args]);
6647
6940
  }
@@ -6720,6 +7013,10 @@ async function runStartupSync(context, state) {
6720
7013
  logger.debug("Version sync skipped: dev mode (monorepo checkout)");
6721
7014
  return false;
6722
7015
  }
7016
+ if (await getEnvToolsDirsDeclaration()) {
7017
+ logger.debug("Version sync skipped: the host declared its tool directories and owns the CLI version");
7018
+ return false;
7019
+ }
6723
7020
  const [locationError, location] = await catchError(state.resolveInstallPath());
6724
7021
  if (!locationError && location && await isBundledDistribution(location.path)) {
6725
7022
  logger.debug("Version sync skipped: Studio-bundled CLI distribution");
@@ -6780,7 +7077,7 @@ async function resolveUpdateLocation(state, context) {
6780
7077
  return location;
6781
7078
  }
6782
7079
  async function runUpdateEngine(state, location, context, target) {
6783
- const { runUpdate: runUpdate2 } = await import("./updateService-e4yhztgq.js");
7080
+ const { runUpdate: runUpdate2 } = await import("./updateService-r03h6d1b.js");
6784
7081
  const spinner = await startSpinner(formatUpdateStartMessage(target));
6785
7082
  if (!spinner) {
6786
7083
  writeSyncStatus(context, formatUpdateStartMessage(target));
@@ -7062,7 +7359,14 @@ class ToolManager {
7062
7359
  this.freshVerbs.add(verb);
7063
7360
  return;
7064
7361
  }
7065
- const location = await this.resolveInstallPath();
7362
+ const [locationError, location] = await catchError(this.resolveInstallPath());
7363
+ if (locationError instanceof InstallRefusedError) {
7364
+ logger.debug(`Tool freshness check skipped: ${locationError.message}`);
7365
+ this.freshVerbs.add(verb);
7366
+ return;
7367
+ }
7368
+ if (locationError)
7369
+ throw locationError;
7066
7370
  if (await isBundledDistribution(location.path)) {
7067
7371
  logger.debug("Tool freshness check skipped: Studio-bundled CLI distribution");
7068
7372
  this.freshVerbs.add(verb);
@@ -7104,7 +7408,8 @@ class ToolManager {
7104
7408
  spinner.text = `Installing ${packageSpec}…`;
7105
7409
  }
7106
7410
  const [installErr] = await catchError(toolService.install(packageSpec, location.path, {
7107
- global: location.global
7411
+ global: location.global,
7412
+ prefix: location.prefix
7108
7413
  }));
7109
7414
  if (installErr) {
7110
7415
  throw toolInstallFailedError(installed.toolName, packageSpec, installErr);
@@ -7249,12 +7554,25 @@ class ToolManager {
7249
7554
  }
7250
7555
  logger.debug(`Installing ${packageSpec} from ${candidate.registry ?? "the configured registry"} to ${location.path} (global: ${location.global})`);
7251
7556
  await toolService.install(packageSpec, location.path, {
7252
- global: location.global
7557
+ global: location.global,
7558
+ prefix: location.prefix
7253
7559
  });
7254
7560
  logger.info(`Installed ${packageSpec} successfully.`);
7561
+ await this.includeGlobalInstallDirectory(location);
7255
7562
  await this.refreshDiscovery();
7256
7563
  await this.recordUpdateDate(packageName.replace(/^@uipath\//, ""));
7257
7564
  }
7565
+ async includeGlobalInstallDirectory(location) {
7566
+ if (!location.global || location.prefix)
7567
+ return;
7568
+ if (await getEnvToolsDirsDeclaration())
7569
+ return;
7570
+ const globalToolsDir = await refreshGlobalNpmUipathDir();
7571
+ if (globalToolsDir && !this.toolsDirs.includes(globalToolsDir)) {
7572
+ this.toolsDirs.push(globalToolsDir);
7573
+ logger.debug(`Added global tool directory after install: ${globalToolsDir}`);
7574
+ }
7575
+ }
7258
7576
  async refreshDiscovery() {
7259
7577
  logger.debug(`Re-discovering tools in [${this.toolsDirs.join(", ")}]...`);
7260
7578
  this.discoveredTools = await discoverToolPaths(this.toolsDirs);
@@ -7298,6 +7616,63 @@ async function autoInstallToolIfNeeded(args, program, toolManager, context) {
7298
7616
  }
7299
7617
 
7300
7618
  // src/utils/registerToolCommands.ts
7619
+ async function loadToolCommand(program, entry, toolCommand) {
7620
+ logger.debug(`Loading tool '${entry.toolName}'...`);
7621
+ const tool = await importTool(entry);
7622
+ if (!tool) {
7623
+ return {
7624
+ failure: {
7625
+ Result: RESULTS.ConfigError,
7626
+ Message: `Failed to load tool '${entry.toolName}' (version: ${entry.version || "unknown"}, path: ${entry.toolPath}).`,
7627
+ Instructions: `Try reinstalling with 'uip tools install ${entry.commandPrefix}'.`,
7628
+ TelemetryErrorClass: "missing_dependency"
7629
+ }
7630
+ };
7631
+ }
7632
+ setGlobalTelemetryProperties({
7633
+ [BaseDimensions.ToolName]: tool.metadata.commandPrefix,
7634
+ [BaseDimensions.ToolVersion]: tool.metadata.version
7635
+ });
7636
+ const idx = program.commands.indexOf(toolCommand);
7637
+ if (idx >= 0) {
7638
+ program.commands.splice(idx, 1);
7639
+ }
7640
+ const aliases = ALIASES_BY_COMMAND.get(entry.commandPrefix) ?? [];
7641
+ const realCommand = program.command(tool.metadata.commandPrefix).description(tool.metadata.description);
7642
+ if (aliases.length > 0)
7643
+ realCommand.aliases(aliases);
7644
+ const [regError] = await catchError(tool.registerCommands(realCommand));
7645
+ if (regError) {
7646
+ return {
7647
+ failure: {
7648
+ Result: RESULTS.Failure,
7649
+ Message: `Failed to register commands from tool '${tool.metadata.name}': ${regError.message}`,
7650
+ Instructions: "This might be due to a command name conflict with existing commands.",
7651
+ TelemetryErrorClass: "internal"
7652
+ }
7653
+ };
7654
+ }
7655
+ stripHelpTextEventsForStructuredHelp(realCommand);
7656
+ return { command: realCommand };
7657
+ }
7658
+ async function loadToolCommandsForArgs(program, discovered, context) {
7659
+ const commandToken = context.args.slice(2).find((arg) => !arg.startsWith("-"));
7660
+ const entry = discovered.find((candidate) => {
7661
+ const aliases = ALIASES_BY_COMMAND.get(candidate.commandPrefix) ?? [];
7662
+ return commandToken === candidate.commandPrefix || aliases.includes(commandToken ?? "");
7663
+ });
7664
+ if (!entry)
7665
+ return true;
7666
+ const stub = program.commands.find((command) => command.name() === entry.commandPrefix);
7667
+ if (!stub)
7668
+ return true;
7669
+ const { failure } = await loadToolCommand(program, entry, stub);
7670
+ if (failure) {
7671
+ logger.debug(`Skipped loading tool for telemetry: ${failure.Message}`);
7672
+ return false;
7673
+ }
7674
+ return true;
7675
+ }
7301
7676
  function registerToolCommands(program, discovered, context) {
7302
7677
  for (const entry of discovered) {
7303
7678
  const aliases = ALIASES_BY_COMMAND.get(entry.commandPrefix) ?? [];
@@ -7305,39 +7680,11 @@ function registerToolCommands(program, discovered, context) {
7305
7680
  if (aliases.length > 0)
7306
7681
  toolCommand.aliases(aliases);
7307
7682
  toolCommand.action(async () => {
7308
- logger.debug(`Loading tool '${entry.toolName}'...`);
7309
- const tool = await importTool(entry);
7310
- if (!tool) {
7311
- OutputFormatter.error({
7312
- Result: RESULTS.ConfigError,
7313
- Message: `Failed to load tool '${entry.toolName}' (version: ${entry.version || "unknown"}, path: ${entry.toolPath}).`,
7314
- Instructions: `Try reinstalling with 'uip tools install ${entry.commandPrefix}'.`,
7315
- TelemetryErrorClass: "missing_dependency"
7316
- });
7683
+ const { command: realCommand, failure } = await loadToolCommand(program, entry, toolCommand);
7684
+ if (failure) {
7685
+ OutputFormatter.error(failure);
7317
7686
  return;
7318
7687
  }
7319
- setGlobalTelemetryProperties({
7320
- toolName: tool.metadata.commandPrefix,
7321
- toolVersion: tool.metadata.version
7322
- });
7323
- const idx = program.commands.indexOf(toolCommand);
7324
- if (idx >= 0) {
7325
- program.commands.splice(idx, 1);
7326
- }
7327
- const realCommand = program.command(tool.metadata.commandPrefix).description(tool.metadata.description);
7328
- if (aliases.length > 0)
7329
- realCommand.aliases(aliases);
7330
- const [regError] = await catchError(tool.registerCommands(realCommand));
7331
- if (regError) {
7332
- OutputFormatter.error({
7333
- Result: RESULTS.Failure,
7334
- Message: `Failed to register commands from tool '${tool.metadata.name}': ${regError.message}`,
7335
- Instructions: "This might be due to a command name conflict with existing commands.",
7336
- TelemetryErrorClass: "internal"
7337
- });
7338
- return;
7339
- }
7340
- stripHelpTextEventsForStructuredHelp(realCommand);
7341
7688
  const toolArgs = context.args.slice(2);
7342
7689
  const candidates = [entry.commandPrefix, ...aliases];
7343
7690
  const prefixIdx = toolArgs.findIndex((a) => candidates.includes(a));
@@ -7373,6 +7720,10 @@ async function resolveToolsDirectories(context) {
7373
7720
  if (toolsDirs.length > 0) {
7374
7721
  return { toolsDirs, toolsDir };
7375
7722
  }
7723
+ if (await getEnvToolsDirsDeclaration()) {
7724
+ logger.warn(`${TOOLS_DIRS_ENV_VAR} names no usable tool directory; no tools are available.`);
7725
+ return { toolsDirs: [], toolsDir: undefined };
7726
+ }
7376
7727
  logger.warn("Unable to determine tools directory. Please ensure the CLI is installed correctly.");
7377
7728
  const { dirname, join } = fs.path;
7378
7729
  const isInstalledPackage = process.execPath.includes(join("@uipath", "cli", "dist", "uip"));
@@ -7400,7 +7751,7 @@ async function buildNodeProgram(context) {
7400
7751
  if (shouldPopulateTelemetryInstallContext(context.args)) {
7401
7752
  await populateTelemetryInstallContext();
7402
7753
  }
7403
- const { setActiveAuthProfile, setAuthFileConfig } = await import("./index-hgvsratt.js");
7754
+ const { setActiveAuthProfile, setAuthFileConfig } = await import("./index-mttdq2yn.js");
7404
7755
  setActiveAuthProfile(profile);
7405
7756
  const [configErr, config] = await catchError(loadConfigAsync());
7406
7757
  if (configErr) {
@@ -7474,7 +7825,7 @@ async function buildNodeProgram(context) {
7474
7825
  discoveredTools
7475
7826
  });
7476
7827
  logger.debug("Node program built successfully — ready to parse args");
7477
- return { program, cleanedArgs, updateState };
7828
+ return { program, cleanedArgs, updateState, discoveredTools };
7478
7829
  }
7479
7830
  async function runNode(context) {
7480
7831
  return runCliInvocation(() => runNodeInvocation(withRecordedExit(context)));
@@ -7482,6 +7833,7 @@ async function runNode(context) {
7482
7833
  async function runNodeInvocation(context) {
7483
7834
  const built = await buildNodeProgram(context);
7484
7835
  if (!built) {
7836
+ emitApplicationStart(context);
7485
7837
  emitEarlyExitRequest(context, { success: false });
7486
7838
  await telemetryFlushAndShutdown();
7487
7839
  return;
@@ -7493,13 +7845,19 @@ async function runNodeInvocation(context) {
7493
7845
  const reexeced = await maybeRunDailyVersionSync(context, built.updateState);
7494
7846
  if (reexeced) {
7495
7847
  suppressTimingReport();
7496
- emitEarlyExitRequest(context, { success: true, delegated: true });
7848
+ await loadToolCommandsForArgs(built.program, built.discoveredTools, context);
7849
+ emitEarlyExitRequest(context, {
7850
+ success: getExitCode() === 0,
7851
+ delegated: true,
7852
+ program: built.program
7853
+ });
7497
7854
  await telemetryFlushAndShutdown();
7498
7855
  return;
7499
7856
  }
7857
+ emitApplicationStart(context);
7500
7858
  await parseAndExit(built.program, built.cleanedArgs, context);
7501
7859
  }
7502
7860
 
7503
7861
  export { runNode };
7504
7862
 
7505
- //# debugId=A4A81EB58587B10164756E2164756E21
7863
+ //# debugId=614F5EF94030176764756E2164756E21