@uipath/docsai-tool 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/tool.js +457 -136
  2. package/package.json +28 -35
package/dist/tool.js CHANGED
@@ -680,6 +680,7 @@ var init_open = __esm(() => {
680
680
  });
681
681
 
682
682
  // ../filesystem/src/node.ts
683
+ import { randomUUID } from "node:crypto";
683
684
  import { existsSync } from "node:fs";
684
685
  import * as fs6 from "node:fs/promises";
685
686
  import * as os2 from "node:os";
@@ -761,6 +762,90 @@ class NodeFileSystem {
761
762
  async mkdir(dirPath) {
762
763
  await fs6.mkdir(dirPath, { recursive: true });
763
764
  }
765
+ async acquireLock(lockPath) {
766
+ const canonicalPath = await this.canonicalizeLockTarget(lockPath);
767
+ const lockFile = `${canonicalPath}.lock`;
768
+ const ownerId = randomUUID();
769
+ const start = Date.now();
770
+ while (true) {
771
+ try {
772
+ await fs6.writeFile(lockFile, ownerId, { flag: "wx" });
773
+ return this.createLockRelease(lockFile, ownerId);
774
+ } catch (error) {
775
+ if (!this.hasErrnoCode(error, "EEXIST")) {
776
+ throw error;
777
+ }
778
+ const stats = await fs6.stat(lockFile).catch(() => null);
779
+ if (stats && Date.now() - stats.mtimeMs > LOCK_STALE_MS) {
780
+ const reclaimed = await fs6.rm(lockFile, { force: true }).then(() => true).catch(() => false);
781
+ if (reclaimed)
782
+ continue;
783
+ }
784
+ if (Date.now() - start > LOCK_MAX_WAIT_MS) {
785
+ throw new Error(`ELOCKED: timed out waiting for lock on ${canonicalPath}`);
786
+ }
787
+ await new Promise((resolve2) => setTimeout(resolve2, LOCK_RETRY_MIN_MS + Math.random() * LOCK_RETRY_JITTER_MS));
788
+ }
789
+ }
790
+ }
791
+ async canonicalizeLockTarget(lockPath) {
792
+ const absolute = path2.resolve(lockPath);
793
+ const fullReal = await fs6.realpath(absolute).catch(() => null);
794
+ if (fullReal)
795
+ return fullReal;
796
+ const parent = path2.dirname(absolute);
797
+ const base = path2.basename(absolute);
798
+ const canonicalParent = await fs6.realpath(parent).catch(() => parent);
799
+ return path2.join(canonicalParent, base);
800
+ }
801
+ createLockRelease(lockFile, ownerId) {
802
+ const heartbeatStart = Date.now();
803
+ let heartbeatTimer;
804
+ let stopped = false;
805
+ const stopHeartbeat = () => {
806
+ stopped = true;
807
+ if (heartbeatTimer)
808
+ clearTimeout(heartbeatTimer);
809
+ };
810
+ const scheduleNextHeartbeat = () => {
811
+ if (stopped)
812
+ return;
813
+ if (Date.now() - heartbeatStart >= LOCK_MAX_HOLD_MS) {
814
+ stopped = true;
815
+ return;
816
+ }
817
+ heartbeatTimer = setTimeout(() => {
818
+ runHeartbeat();
819
+ }, LOCK_HEARTBEAT_MS);
820
+ heartbeatTimer.unref?.();
821
+ };
822
+ const runHeartbeat = async () => {
823
+ if (stopped)
824
+ return;
825
+ const current = await fs6.readFile(lockFile, "utf-8").catch(() => null);
826
+ if (stopped)
827
+ return;
828
+ if (current !== ownerId) {
829
+ stopped = true;
830
+ return;
831
+ }
832
+ const now = Date.now() / 1000;
833
+ await fs6.utimes(lockFile, now, now).catch(() => {});
834
+ scheduleNextHeartbeat();
835
+ };
836
+ scheduleNextHeartbeat();
837
+ let released = false;
838
+ return async () => {
839
+ if (released)
840
+ return;
841
+ released = true;
842
+ stopHeartbeat();
843
+ const current = await fs6.readFile(lockFile, "utf-8").catch(() => null);
844
+ if (current === ownerId) {
845
+ await fs6.rm(lockFile, { force: true });
846
+ }
847
+ };
848
+ }
764
849
  async rm(filePath) {
765
850
  await fs6.rm(filePath, { recursive: true, force: true });
766
851
  }
@@ -806,9 +891,13 @@ class NodeFileSystem {
806
891
  }
807
892
  }
808
893
  isEnoent(error) {
809
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
894
+ return this.hasErrnoCode(error, "ENOENT");
895
+ }
896
+ hasErrnoCode(error, code) {
897
+ return typeof error === "object" && error !== null && "code" in error && error.code === code;
810
898
  }
811
899
  }
900
+ 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;
812
901
  var init_node = __esm(() => {
813
902
  init_open();
814
903
  });
@@ -2954,7 +3043,7 @@ function isBrowser() {
2954
3043
 
2955
3044
  // ../../node_modules/@uipath/coreipc/index.js
2956
3045
  var require_coreipc = __commonJS((exports, module) => {
2957
- var __dirname = "/Users/alexandru.oltean/github/cli/node_modules/@uipath/coreipc";
3046
+ var __dirname = "/home/runner/work/cli/cli/node_modules/@uipath/coreipc";
2958
3047
  /*! For license information please see index.js.LICENSE.txt */
2959
3048
  (function(e, t) {
2960
3049
  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();
@@ -21146,6 +21235,10 @@ var require_dist = __commonJS((exports) => {
21146
21235
  exports.RobotProxyConstructor = RobotProxyConstructor;
21147
21236
  __exportStar(require_agent(), exports);
21148
21237
  });
21238
+ // ../auth/src/server.ts
21239
+ var init_server = __esm(() => {
21240
+ init_constants();
21241
+ });
21149
21242
 
21150
21243
  // ../../node_modules/ajv/dist/compile/codegen/code.js
21151
21244
  var require_code = __commonJS((exports) => {
@@ -27708,7 +27801,8 @@ var require_dist2 = __commonJS((exports, module) => {
27708
27801
  // package.json
27709
27802
  var package_default = {
27710
27803
  name: "@uipath/docsai-tool",
27711
- version: "1.1.0",
27804
+ license: "MIT",
27805
+ version: "1.195.0",
27712
27806
  description: "Search UiPath documentation with AI-powered answers.",
27713
27807
  private: false,
27714
27808
  repository: {
@@ -32939,6 +33033,60 @@ function escapeNonAscii(jsonText) {
32939
33033
  function needsAsciiSafeJson(sink) {
32940
33034
  return process.platform === "win32" && !sink.capabilities.isInteractive;
32941
33035
  }
33036
+ function isPlainRecord(value) {
33037
+ if (value === null || typeof value !== "object")
33038
+ return false;
33039
+ const prototype = Object.getPrototypeOf(value);
33040
+ return prototype === Object.prototype || prototype === null;
33041
+ }
33042
+ function toLowerCamelCaseKey(key) {
33043
+ if (!key)
33044
+ return key;
33045
+ if (/[_\-\s]/.test(key)) {
33046
+ const [firstPart, ...restParts] = key.split(/[_\-\s]+/).filter(Boolean);
33047
+ if (!firstPart)
33048
+ return key;
33049
+ return [
33050
+ toLowerCamelCaseSimpleKey(firstPart),
33051
+ ...restParts.map((part) => {
33052
+ const normalized = toLowerCamelCaseSimpleKey(part);
33053
+ return normalized.charAt(0).toUpperCase() + normalized.slice(1);
33054
+ })
33055
+ ].join("");
33056
+ }
33057
+ return toLowerCamelCaseSimpleKey(key);
33058
+ }
33059
+ function toLowerCamelCaseSimpleKey(key) {
33060
+ if (/^[A-Z0-9]+$/.test(key))
33061
+ return key.toLowerCase();
33062
+ return key.replace(/^[A-Z]+(?=[A-Z][a-z]|\d|$)|^[A-Z]/, (match) => match.toLowerCase());
33063
+ }
33064
+ function toPascalCaseKey(key) {
33065
+ const lowerCamelKey = toLowerCamelCaseKey(key);
33066
+ return lowerCamelKey ? lowerCamelKey.charAt(0).toUpperCase() + lowerCamelKey.slice(1) : lowerCamelKey;
33067
+ }
33068
+ function toPascalCaseData(value) {
33069
+ if (Array.isArray(value))
33070
+ return value.map(toPascalCaseData);
33071
+ if (!isPlainRecord(value))
33072
+ return value;
33073
+ const result = {};
33074
+ for (const [key, nestedValue] of Object.entries(value)) {
33075
+ result[toPascalCaseKey(key)] = toPascalCaseData(nestedValue);
33076
+ }
33077
+ return result;
33078
+ }
33079
+ function normalizeDataKeys(data) {
33080
+ return toPascalCaseData(data);
33081
+ }
33082
+ function normalizeOutputKeys(data) {
33083
+ const result = {};
33084
+ for (const [key, value] of Object.entries(data)) {
33085
+ const pascalKey = toPascalCaseKey(key);
33086
+ result[pascalKey] = pascalKey === "Data" ? value : toPascalCaseData(value);
33087
+ }
33088
+ return result;
33089
+ }
32942
33090
  function printOutput(data, format = "json", logFn, asciiSafe = false) {
32943
33091
  if (!data) {
32944
33092
  logFn("Empty response object. No data to display.");
@@ -33001,7 +33149,7 @@ function wrapText(text, width) {
33001
33149
  function printTable(data, logFn, externalLogValue) {
33002
33150
  if (data.length === 0)
33003
33151
  return;
33004
- const keys = Object.keys(data[0]).filter((key) => key !== "Code" && key !== "Log");
33152
+ const keys = Object.keys(data[0]).filter((key) => !["code", "log"].includes(key.toLowerCase()));
33005
33153
  const maxWidths = keys.map((key) => Math.max(key.length, ...data.map((item) => cellToString(item[key]).length)));
33006
33154
  const header = keys.map((key, i2) => key.padEnd(maxWidths[i2])).join(" | ");
33007
33155
  logFn(header);
@@ -33016,7 +33164,7 @@ function printTable(data, logFn, externalLogValue) {
33016
33164
  }
33017
33165
  }
33018
33166
  function printVerticalTable(data, logFn = console.log, externalLogValue) {
33019
- const keys = Object.keys(data).filter((key) => key !== "Code" && key !== "Log");
33167
+ const keys = Object.keys(data).filter((key) => !["code", "log"].includes(key.toLowerCase()));
33020
33168
  if (keys.length === 0)
33021
33169
  return;
33022
33170
  const maxKeyWidth = Math.max(...keys.map((key) => key.length));
@@ -33032,7 +33180,7 @@ function printVerticalTable(data, logFn = console.log, externalLogValue) {
33032
33180
  function printResizableTable(data, logFn = console.log, externalLogValue) {
33033
33181
  if (data.length === 0)
33034
33182
  return;
33035
- const keys = Object.keys(data[0]).filter((key) => key !== "Code" && key !== "Log");
33183
+ const keys = Object.keys(data[0]).filter((key) => !["code", "log"].includes(key.toLowerCase()));
33036
33184
  if (keys.length === 0)
33037
33185
  return;
33038
33186
  if (!process.stdout.isTTY) {
@@ -33108,8 +33256,26 @@ function printResizableTable(data, logFn = console.log, externalLogValue) {
33108
33256
  function toYaml(data) {
33109
33257
  return dump(data);
33110
33258
  }
33259
+ class FilterEvaluationError extends Error {
33260
+ __brand = "FilterEvaluationError";
33261
+ filter;
33262
+ instructions;
33263
+ result = RESULTS.ValidationError;
33264
+ constructor(filter, cause) {
33265
+ const underlying = cause instanceof Error ? cause.message : String(cause);
33266
+ super(`Filter '${filter}' failed to evaluate: ${underlying}`);
33267
+ this.name = "FilterEvaluationError";
33268
+ this.filter = filter;
33269
+ 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(@)'.";
33270
+ }
33271
+ }
33111
33272
  function applyFilter(data, filter) {
33112
- const result = search(data, filter);
33273
+ let result;
33274
+ try {
33275
+ result = search(data, filter);
33276
+ } catch (err) {
33277
+ throw new FilterEvaluationError(filter, err);
33278
+ }
33113
33279
  if (result == null)
33114
33280
  return [];
33115
33281
  if (Array.isArray(result)) {
@@ -33126,13 +33292,18 @@ function applyFilter(data, filter) {
33126
33292
  }
33127
33293
  var OutputFormatter;
33128
33294
  ((OutputFormatter) => {
33129
- function success(data) {
33295
+ function success(data, options) {
33130
33296
  data.Log ??= getLogFilePath() || undefined;
33297
+ const normalize = !options?.preserveDataKeys;
33298
+ if (normalize) {
33299
+ data.Data = normalizeDataKeys(data.Data);
33300
+ }
33131
33301
  const filter = getOutputFilter();
33132
33302
  if (filter) {
33133
- data.Data = applyFilter(data.Data, filter);
33303
+ const filtered = applyFilter(data.Data, filter);
33304
+ data.Data = normalize ? normalizeDataKeys(filtered) : filtered;
33134
33305
  }
33135
- logOutput(data, getOutputFormat());
33306
+ logOutput(normalizeOutputKeys(data), getOutputFormat());
33136
33307
  }
33137
33308
  OutputFormatter.success = success;
33138
33309
  function error(data) {
@@ -33142,7 +33313,7 @@ var OutputFormatter;
33142
33313
  result: data.Result,
33143
33314
  message: data.Message
33144
33315
  });
33145
- logOutput(data, getOutputFormat());
33316
+ logOutput(normalizeOutputKeys(data), getOutputFormat());
33146
33317
  }
33147
33318
  OutputFormatter.error = error;
33148
33319
  function emitList(code, items, opts) {
@@ -33163,13 +33334,14 @@ var OutputFormatter;
33163
33334
  function log(data) {
33164
33335
  const format = getOutputFormat();
33165
33336
  const sink = getOutputSink();
33337
+ const normalized = toPascalCaseData(data);
33166
33338
  if (format === "json") {
33167
- const json2 = JSON.stringify(data);
33339
+ const json2 = JSON.stringify(normalized);
33168
33340
  const safe = needsAsciiSafeJson(sink) ? escapeNonAscii(json2) : json2;
33169
33341
  sink.writeErr(`${safe}
33170
33342
  `);
33171
33343
  } else {
33172
- for (const [key, value] of Object.entries(data)) {
33344
+ for (const [key, value] of Object.entries(normalized)) {
33173
33345
  sink.writeErr(`${key}: ${value}
33174
33346
  `);
33175
33347
  }
@@ -33178,12 +33350,16 @@ var OutputFormatter;
33178
33350
  OutputFormatter.log = log;
33179
33351
  function formatToString(data) {
33180
33352
  const filter = getOutputFilter();
33181
- if (filter && "Data" in data && data.Data != null) {
33182
- data.Data = applyFilter(data.Data, filter);
33353
+ if ("Data" in data && data.Data != null) {
33354
+ data.Data = normalizeDataKeys(data.Data);
33355
+ if (filter) {
33356
+ data.Data = normalizeDataKeys(applyFilter(data.Data, filter));
33357
+ }
33183
33358
  }
33359
+ const output = normalizeOutputKeys(data);
33184
33360
  const lines = [];
33185
33361
  const sink = getOutputSink();
33186
- printOutput(data, getOutputFormat(), (msg) => {
33362
+ printOutput(output, getOutputFormat(), (msg) => {
33187
33363
  lines.push(msg);
33188
33364
  }, needsAsciiSafeJson(sink));
33189
33365
  return lines.join(`
@@ -34611,6 +34787,22 @@ function warnDeprecatedTenantOption(tenant) {
34611
34787
  return;
34612
34788
  warnDeprecatedOptionAlias("--tenant", TENANT_SWITCH_COMMAND);
34613
34789
  }
34790
+ // ../common/src/polling/types.ts
34791
+ var PollOutcome = {
34792
+ Completed: "completed",
34793
+ Timeout: "timeout",
34794
+ Interrupted: "interrupted",
34795
+ Aborted: "aborted",
34796
+ Failed: "failed"
34797
+ };
34798
+
34799
+ // ../common/src/polling/poll-failure-mapping.ts
34800
+ var REASON_BY_OUTCOME = {
34801
+ [PollOutcome.Timeout]: "poll_timeout",
34802
+ [PollOutcome.Failed]: "poll_failed",
34803
+ [PollOutcome.Interrupted]: "poll_failed",
34804
+ [PollOutcome.Aborted]: "poll_aborted"
34805
+ };
34614
34806
  // ../common/src/polling/terminal-statuses.ts
34615
34807
  var TERMINAL_STATUSES = new Set([
34616
34808
  "completed",
@@ -34638,6 +34830,8 @@ var ScreenLogger;
34638
34830
  }
34639
34831
  ScreenLogger.progress = progress;
34640
34832
  })(ScreenLogger ||= {});
34833
+ // ../common/src/sdk-user-agent.ts
34834
+ var sdkUserAgentHostToken = singleton("SdkUserAgentHostToken");
34641
34835
  // ../common/src/tool-provider.ts
34642
34836
  var factorySlot = singleton("PackagerFactoryProvider");
34643
34837
  // ../common/src/telemetry/pii-redactor.ts
@@ -34820,13 +35014,17 @@ Command.prototype.trackedAction = function(context, fn, properties) {
34820
35014
  const [error] = await catchError(fn(...args));
34821
35015
  if (error) {
34822
35016
  errorMessage = error instanceof Error ? error.message : String(error);
34823
- logger.error(`[trackedAction] ${telemetryName} failed: ${errorMessage}`);
35017
+ logger.debug(`[trackedAction] ${telemetryName} failed: ${errorMessage}`);
35018
+ const typed = error;
35019
+ const customInstructions = typeof typed.instructions === "string" ? typed.instructions : undefined;
35020
+ const customResult = typeof typed.result === "string" && typed.result !== RESULTS.Success && Object.values(RESULTS).includes(typed.result) ? typed.result : undefined;
35021
+ const finalResult = customResult ?? RESULTS.Failure;
34824
35022
  OutputFormatter.error({
34825
- Result: RESULTS.Failure,
35023
+ Result: finalResult,
34826
35024
  Message: errorMessage,
34827
- Instructions: "An unexpected error occurred. Run with --log-level debug for details."
35025
+ Instructions: customInstructions ?? "An unexpected error occurred. Run with --log-level debug for details."
34828
35026
  });
34829
- context.exit(1);
35027
+ context.exit(EXIT_CODES[finalResult]);
34830
35028
  }
34831
35029
  const durationMs = performance.now() - startTime;
34832
35030
  const success = !error && (process.exitCode === undefined || process.exitCode === 0);
@@ -34863,32 +35061,7 @@ class InvalidBaseUrlError extends Error {
34863
35061
  this.name = "InvalidBaseUrlError";
34864
35062
  }
34865
35063
  }
34866
- var DEFAULT_SCOPES = [
34867
- "offline_access",
34868
- "ProcessMining",
34869
- "OrchestratorApiUserAccess",
34870
- "StudioWebBackend",
34871
- "IdentityServerApi",
34872
- "ConnectionService",
34873
- "DataService",
34874
- "DataServiceApiUserAccess",
34875
- "DocumentUnderstanding",
34876
- "EnterpriseContextService",
34877
- "Directory",
34878
- "JamJamApi",
34879
- "LLMGateway",
34880
- "LLMOps",
34881
- "OMS",
34882
- "RCS.FolderAuthorization",
34883
- "RCS.TagsManagement",
34884
- "TestmanagerApiUserAccess",
34885
- "AutomationSolutions",
34886
- "StudioWebTypeCacheService",
34887
- "Docs.GPT.Search",
34888
- "Insights",
34889
- "ReferenceToken",
34890
- "Audit.Read"
34891
- ];
35064
+ var DEFAULT_SCOPES = ["openid", "profile", "offline_access"];
34892
35065
  var normalizeAndValidateBaseUrl = (rawUrl) => {
34893
35066
  let baseUrl = rawUrl;
34894
35067
  if (baseUrl.endsWith("/identity_/")) {
@@ -34938,7 +35111,8 @@ var resolveConfigAsync = async ({
34938
35111
  if (!clientSecret && fileAuth.clientSecret) {
34939
35112
  clientSecret = fileAuth.clientSecret;
34940
35113
  }
34941
- const scopes = customScopes && customScopes.length > 0 ? customScopes : fileAuth.scopes && fileAuth.scopes.length > 0 ? fileAuth.scopes : DEFAULT_SCOPES;
35114
+ const isExternalAppAuth = clientId !== DEFAULT_CLIENT_ID && Boolean(clientSecret);
35115
+ const scopes = customScopes && customScopes.length > 0 ? customScopes : fileAuth.scopes && fileAuth.scopes.length > 0 ? fileAuth.scopes : isExternalAppAuth ? [] : DEFAULT_SCOPES;
34942
35116
  return {
34943
35117
  clientId,
34944
35118
  clientSecret,
@@ -35438,6 +35612,129 @@ function normalizeTokenRefreshFailure() {
35438
35612
  function normalizeTokenRefreshUnavailableFailure() {
35439
35613
  return "token refresh failed before authentication completed";
35440
35614
  }
35615
+ function errorMessage(error) {
35616
+ return error instanceof Error ? error.message : String(error);
35617
+ }
35618
+ function computeExpirationThreshold(ensureTokenValidityMinutes) {
35619
+ return new Date(Date.now() + (ensureTokenValidityMinutes ?? 0) * 60 * 1000);
35620
+ }
35621
+ async function runRefreshLocked(inputs) {
35622
+ const {
35623
+ absolutePath,
35624
+ refreshToken: callerRefreshToken,
35625
+ customAuthority,
35626
+ ensureTokenValidityMinutes,
35627
+ loadEnvFile,
35628
+ saveEnvFile,
35629
+ refreshFn,
35630
+ resolveConfig
35631
+ } = inputs;
35632
+ const expirationThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
35633
+ let fresh;
35634
+ try {
35635
+ fresh = await loadEnvFile({ envPath: absolutePath });
35636
+ } catch (error) {
35637
+ return {
35638
+ kind: "fail",
35639
+ status: {
35640
+ loginStatus: "Refresh Failed",
35641
+ hint: "Could not read the auth file while refreshing. Retry, or run 'uip login' to re-authenticate.",
35642
+ tokenRefresh: {
35643
+ attempted: false,
35644
+ success: false,
35645
+ errorMessage: `auth file read failed: ${errorMessage(error)}`
35646
+ }
35647
+ }
35648
+ };
35649
+ }
35650
+ const freshAccess = fresh.UIPATH_ACCESS_TOKEN;
35651
+ const freshExp = freshAccess ? getTokenExpiration(freshAccess) : undefined;
35652
+ if (freshAccess && freshExp && freshExp > expirationThreshold) {
35653
+ return {
35654
+ kind: "ok",
35655
+ accessToken: freshAccess,
35656
+ refreshToken: fresh.UIPATH_REFRESH_TOKEN ?? callerRefreshToken,
35657
+ expiration: freshExp,
35658
+ tokenRefresh: { attempted: false, success: true }
35659
+ };
35660
+ }
35661
+ const tokenForIdP = fresh.UIPATH_REFRESH_TOKEN ?? callerRefreshToken;
35662
+ let refreshedAccess;
35663
+ let refreshedRefresh;
35664
+ try {
35665
+ const config = await resolveConfig({ customAuthority });
35666
+ const refreshed = await refreshFn({
35667
+ refreshToken: tokenForIdP,
35668
+ tokenEndpoint: config.tokenEndpoint,
35669
+ clientId: config.clientId,
35670
+ expectedAuthority: customAuthority
35671
+ });
35672
+ refreshedAccess = refreshed.accessToken;
35673
+ refreshedRefresh = refreshed.refreshToken;
35674
+ } catch (error) {
35675
+ const isOAuthFailure = isTokenRefreshOAuthFailure(error);
35676
+ 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.";
35677
+ const message = isOAuthFailure ? normalizeTokenRefreshFailure() : normalizeTokenRefreshUnavailableFailure();
35678
+ return {
35679
+ kind: "fail",
35680
+ status: {
35681
+ loginStatus: "Refresh Failed",
35682
+ hint,
35683
+ tokenRefresh: {
35684
+ attempted: true,
35685
+ success: false,
35686
+ errorMessage: message
35687
+ }
35688
+ }
35689
+ };
35690
+ }
35691
+ const refreshedExp = getTokenExpiration(refreshedAccess);
35692
+ if (!refreshedExp || refreshedExp <= new Date) {
35693
+ return {
35694
+ kind: "fail",
35695
+ status: {
35696
+ loginStatus: "Refresh Failed",
35697
+ hint: "The identity server returned an unusable token. Run 'uip login' to re-authenticate.",
35698
+ tokenRefresh: {
35699
+ attempted: true,
35700
+ success: false,
35701
+ errorMessage: "refreshed token has no valid expiration claim"
35702
+ }
35703
+ }
35704
+ };
35705
+ }
35706
+ try {
35707
+ await saveEnvFile({
35708
+ envPath: absolutePath,
35709
+ data: {
35710
+ UIPATH_ACCESS_TOKEN: refreshedAccess,
35711
+ UIPATH_REFRESH_TOKEN: refreshedRefresh
35712
+ },
35713
+ merge: true
35714
+ });
35715
+ return {
35716
+ kind: "ok",
35717
+ accessToken: refreshedAccess,
35718
+ refreshToken: refreshedRefresh,
35719
+ expiration: refreshedExp,
35720
+ tokenRefresh: { attempted: true, success: true }
35721
+ };
35722
+ } catch (error) {
35723
+ const msg = errorMessage(error);
35724
+ return {
35725
+ kind: "ok",
35726
+ accessToken: refreshedAccess,
35727
+ refreshToken: refreshedRefresh,
35728
+ expiration: refreshedExp,
35729
+ 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.`,
35730
+ tokenRefresh: {
35731
+ attempted: true,
35732
+ success: true,
35733
+ errorMessage: `persistence failed: ${msg}`
35734
+ }
35735
+ };
35736
+ }
35737
+ }
35441
35738
  var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
35442
35739
  const {
35443
35740
  resolveEnvFilePath = resolveEnvFilePathAsync,
@@ -35512,73 +35809,103 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
35512
35809
  let refreshToken = credentials.UIPATH_REFRESH_TOKEN;
35513
35810
  let expiration = getTokenExpiration(accessToken);
35514
35811
  let persistenceWarning;
35812
+ let lockReleaseFailed = false;
35515
35813
  let tokenRefresh;
35516
- const expirationThreshold = new Date(Date.now() + (ensureTokenValidityMinutes ?? 0) * 60 * 1000);
35517
- if (expiration && expiration <= expirationThreshold && refreshToken) {
35518
- let refreshedAccess;
35519
- let refreshedRefresh;
35814
+ const outerThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
35815
+ const tryGlobalCredsHint = async () => {
35816
+ const fs7 = getFs();
35817
+ const globalPath = fs7.path.join(fs7.env.homedir(), envFilePath);
35818
+ if (absolutePath === globalPath)
35819
+ return;
35820
+ if (!await fs7.exists(globalPath))
35821
+ return;
35520
35822
  try {
35521
- const config = await resolveConfig({
35522
- customAuthority: credentials.UIPATH_URL
35523
- });
35524
- const refreshed = await refreshTokenFn({
35525
- refreshToken,
35526
- tokenEndpoint: config.tokenEndpoint,
35527
- clientId: config.clientId,
35528
- expectedAuthority: credentials.UIPATH_URL
35529
- });
35530
- refreshedAccess = refreshed.accessToken;
35531
- refreshedRefresh = refreshed.refreshToken;
35532
- } catch (error) {
35533
- const isOAuthFailure = isTokenRefreshOAuthFailure(error);
35534
- 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.";
35535
- const errorMessage = isOAuthFailure ? normalizeTokenRefreshFailure() : normalizeTokenRefreshUnavailableFailure();
35536
- return {
35537
- loginStatus: "Refresh Failed",
35538
- hint,
35539
- tokenRefresh: {
35540
- attempted: true,
35541
- success: false,
35542
- errorMessage
35543
- }
35544
- };
35823
+ const globalCreds = await loadEnvFile({ envPath: globalPath });
35824
+ if (!globalCreds.UIPATH_ACCESS_TOKEN)
35825
+ return;
35826
+ const globalExp = getTokenExpiration(globalCreds.UIPATH_ACCESS_TOKEN);
35827
+ if (globalExp && globalExp <= new Date)
35828
+ return;
35829
+ 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.`;
35830
+ } catch {
35831
+ return;
35545
35832
  }
35546
- const refreshedExp = getTokenExpiration(refreshedAccess);
35547
- if (!refreshedExp || refreshedExp <= new Date) {
35833
+ };
35834
+ if (expiration && expiration <= outerThreshold && refreshToken) {
35835
+ let release;
35836
+ try {
35837
+ release = await getFs().acquireLock(absolutePath);
35838
+ } catch (error) {
35839
+ const msg = errorMessage(error);
35840
+ const globalHint = await tryGlobalCredsHint();
35841
+ if (globalHint) {
35842
+ return {
35843
+ loginStatus: "Expired",
35844
+ accessToken,
35845
+ refreshToken,
35846
+ baseUrl: credentials.UIPATH_URL,
35847
+ organizationName: credentials.UIPATH_ORGANIZATION_NAME,
35848
+ organizationId: credentials.UIPATH_ORGANIZATION_ID,
35849
+ tenantName: credentials.UIPATH_TENANT_NAME,
35850
+ tenantId: credentials.UIPATH_TENANT_ID,
35851
+ expiration,
35852
+ source: "file" /* File */,
35853
+ hint: globalHint,
35854
+ tokenRefresh: {
35855
+ attempted: false,
35856
+ success: false,
35857
+ errorMessage: `lock acquisition failed: ${msg}`
35858
+ }
35859
+ };
35860
+ }
35548
35861
  return {
35549
35862
  loginStatus: "Refresh Failed",
35550
- hint: "The identity server returned an unusable token. Run 'uip login' to re-authenticate.",
35863
+ 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.",
35551
35864
  tokenRefresh: {
35552
- attempted: true,
35865
+ attempted: false,
35553
35866
  success: false,
35554
- errorMessage: "refreshed token has no valid expiration claim"
35867
+ errorMessage: `lock acquisition failed: ${msg}`
35555
35868
  }
35556
35869
  };
35557
35870
  }
35558
- accessToken = refreshedAccess;
35559
- refreshToken = refreshedRefresh;
35560
- expiration = refreshedExp;
35871
+ let lockedFailure;
35561
35872
  try {
35562
- await saveEnvFile({
35563
- envPath: absolutePath,
35564
- data: {
35565
- UIPATH_ACCESS_TOKEN: accessToken,
35566
- UIPATH_REFRESH_TOKEN: refreshToken
35567
- },
35568
- merge: true
35873
+ const outcome = await runRefreshLocked({
35874
+ absolutePath,
35875
+ refreshToken,
35876
+ customAuthority: credentials.UIPATH_URL,
35877
+ ensureTokenValidityMinutes,
35878
+ loadEnvFile,
35879
+ saveEnvFile,
35880
+ refreshFn: refreshTokenFn,
35881
+ resolveConfig
35569
35882
  });
35570
- tokenRefresh = {
35571
- attempted: true,
35572
- success: true
35573
- };
35574
- } catch (error) {
35575
- const msg = error instanceof Error ? error.message : String(error);
35576
- 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.`;
35577
- tokenRefresh = {
35578
- attempted: true,
35579
- success: true,
35580
- errorMessage: `persistence failed: ${msg}`
35581
- };
35883
+ if (outcome.kind === "fail") {
35884
+ lockedFailure = outcome.status;
35885
+ } else {
35886
+ accessToken = outcome.accessToken;
35887
+ refreshToken = outcome.refreshToken;
35888
+ expiration = outcome.expiration;
35889
+ tokenRefresh = outcome.tokenRefresh;
35890
+ if (outcome.persistenceWarning) {
35891
+ persistenceWarning = outcome.persistenceWarning;
35892
+ }
35893
+ }
35894
+ } finally {
35895
+ try {
35896
+ await release();
35897
+ } catch {
35898
+ lockReleaseFailed = true;
35899
+ }
35900
+ }
35901
+ if (lockedFailure) {
35902
+ const globalHint = await tryGlobalCredsHint();
35903
+ const base = globalHint ? {
35904
+ ...lockedFailure,
35905
+ loginStatus: "Expired",
35906
+ hint: globalHint
35907
+ } : lockedFailure;
35908
+ return lockReleaseFailed ? { ...base, lockReleaseFailed: true } : base;
35582
35909
  }
35583
35910
  }
35584
35911
  const result = {
@@ -35593,23 +35920,13 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
35593
35920
  expiration,
35594
35921
  source: "file" /* File */,
35595
35922
  ...persistenceWarning ? { hint: persistenceWarning, persistenceFailed: true } : {},
35923
+ ...lockReleaseFailed ? { lockReleaseFailed: true } : {},
35596
35924
  ...tokenRefresh ? { tokenRefresh } : {}
35597
35925
  };
35598
35926
  if (result.loginStatus === "Expired") {
35599
- const fs7 = getFs();
35600
- const globalPath = fs7.path.join(fs7.env.homedir(), envFilePath);
35601
- if (absolutePath !== globalPath && await fs7.exists(globalPath)) {
35602
- try {
35603
- const globalCreds = await loadEnvFile({
35604
- envPath: globalPath
35605
- });
35606
- if (globalCreds.UIPATH_ACCESS_TOKEN) {
35607
- const globalExp = getTokenExpiration(globalCreds.UIPATH_ACCESS_TOKEN);
35608
- if (!globalExp || globalExp > new Date) {
35609
- 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.`;
35610
- }
35611
- }
35612
- } catch {}
35927
+ const globalHint = await tryGlobalCredsHint();
35928
+ if (globalHint) {
35929
+ result.hint = globalHint;
35613
35930
  }
35614
35931
  }
35615
35932
  return result;
@@ -35626,6 +35943,10 @@ var getLoginStatusAsync = async (options = {}) => {
35626
35943
  init_src();
35627
35944
  // ../auth/src/logout.ts
35628
35945
  init_src();
35946
+
35947
+ // ../auth/src/index.ts
35948
+ init_server();
35949
+
35629
35950
  // ../../node_modules/zod/v4/core/core.js
35630
35951
  var _a;
35631
35952
  var NEVER = /* @__PURE__ */ Object.freeze({
@@ -41884,8 +42205,8 @@ class Protocol {
41884
42205
  if (queuedMessage.type === "response") {
41885
42206
  resolver(message);
41886
42207
  } else {
41887
- const errorMessage = message;
41888
- const error2 = new McpError(errorMessage.error.code, errorMessage.error.message, errorMessage.error.data);
42208
+ const errorMessage2 = message;
42209
+ const error2 = new McpError(errorMessage2.error.code, errorMessage2.error.message, errorMessage2.error.data);
41889
42210
  resolver(error2);
41890
42211
  }
41891
42212
  } else {
@@ -42931,8 +43252,8 @@ class Client extends Protocol {
42931
43252
  const wrappedHandler = async (request, extra) => {
42932
43253
  const validatedRequest = safeParse2(ElicitRequestSchema, request);
42933
43254
  if (!validatedRequest.success) {
42934
- const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
42935
- throw new McpError(ErrorCode.InvalidParams, `Invalid elicitation request: ${errorMessage}`);
43255
+ const errorMessage2 = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
43256
+ throw new McpError(ErrorCode.InvalidParams, `Invalid elicitation request: ${errorMessage2}`);
42936
43257
  }
42937
43258
  const { params } = validatedRequest.data;
42938
43259
  params.mode = params.mode ?? "form";
@@ -42947,15 +43268,15 @@ class Client extends Protocol {
42947
43268
  if (params.task) {
42948
43269
  const taskValidationResult = safeParse2(CreateTaskResultSchema, result);
42949
43270
  if (!taskValidationResult.success) {
42950
- const errorMessage = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
42951
- throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage}`);
43271
+ const errorMessage2 = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
43272
+ throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage2}`);
42952
43273
  }
42953
43274
  return taskValidationResult.data;
42954
43275
  }
42955
43276
  const validationResult = safeParse2(ElicitResultSchema, result);
42956
43277
  if (!validationResult.success) {
42957
- const errorMessage = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
42958
- throw new McpError(ErrorCode.InvalidParams, `Invalid elicitation result: ${errorMessage}`);
43278
+ const errorMessage2 = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
43279
+ throw new McpError(ErrorCode.InvalidParams, `Invalid elicitation result: ${errorMessage2}`);
42959
43280
  }
42960
43281
  const validatedResult = validationResult.data;
42961
43282
  const requestedSchema = params.mode === "form" ? params.requestedSchema : undefined;
@@ -42974,16 +43295,16 @@ class Client extends Protocol {
42974
43295
  const wrappedHandler = async (request, extra) => {
42975
43296
  const validatedRequest = safeParse2(CreateMessageRequestSchema, request);
42976
43297
  if (!validatedRequest.success) {
42977
- const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
42978
- throw new McpError(ErrorCode.InvalidParams, `Invalid sampling request: ${errorMessage}`);
43298
+ const errorMessage2 = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
43299
+ throw new McpError(ErrorCode.InvalidParams, `Invalid sampling request: ${errorMessage2}`);
42979
43300
  }
42980
43301
  const { params } = validatedRequest.data;
42981
43302
  const result = await Promise.resolve(handler(request, extra));
42982
43303
  if (params.task) {
42983
43304
  const taskValidationResult = safeParse2(CreateTaskResultSchema, result);
42984
43305
  if (!taskValidationResult.success) {
42985
- const errorMessage = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
42986
- throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage}`);
43306
+ const errorMessage2 = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
43307
+ throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage2}`);
42987
43308
  }
42988
43309
  return taskValidationResult.data;
42989
43310
  }
@@ -42991,8 +43312,8 @@ class Client extends Protocol {
42991
43312
  const resultSchema = hasTools ? CreateMessageResultWithToolsSchema : CreateMessageResultSchema;
42992
43313
  const validationResult = safeParse2(resultSchema, result);
42993
43314
  if (!validationResult.success) {
42994
- const errorMessage = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
42995
- throw new McpError(ErrorCode.InvalidParams, `Invalid sampling result: ${errorMessage}`);
43315
+ const errorMessage2 = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
43316
+ throw new McpError(ErrorCode.InvalidParams, `Invalid sampling result: ${errorMessage2}`);
42996
43317
  }
42997
43318
  return validationResult.data;
42998
43319
  };
@@ -43695,8 +44016,8 @@ async function parseErrorResponse(input) {
43695
44016
  const errorClass = OAUTH_ERRORS[error2] || ServerError;
43696
44017
  return new errorClass(error_description || "", error_uri);
43697
44018
  } catch (error2) {
43698
- const errorMessage = `${statusCode ? `HTTP ${statusCode}: ` : ""}Invalid OAuth error response: ${error2}. Raw body: ${body}`;
43699
- return new ServerError(errorMessage);
44019
+ const errorMessage2 = `${statusCode ? `HTTP ${statusCode}: ` : ""}Invalid OAuth error response: ${error2}. Raw body: ${body}`;
44020
+ return new ServerError(errorMessage2);
43700
44021
  }
43701
44022
  }
43702
44023
  async function auth(provider, options) {
@@ -44827,11 +45148,11 @@ var registerAskCommand = (program2) => {
44827
45148
  }
44828
45149
  const [clientError, client] = await catchError(createMcpClient(options.tenant));
44829
45150
  if (clientError) {
44830
- const errorMessage = extractErrorMessageSync(clientError);
45151
+ const errorMessage2 = extractErrorMessageSync(clientError);
44831
45152
  OutputFormatter.error({
44832
45153
  Result: RESULTS.Failure,
44833
45154
  Message: "Error querying DocsAI",
44834
- Instructions: errorMessage
45155
+ Instructions: errorMessage2
44835
45156
  });
44836
45157
  processContext.exit(1);
44837
45158
  return;
@@ -44842,11 +45163,11 @@ var registerAskCommand = (program2) => {
44842
45163
  }));
44843
45164
  await catchError(client.close());
44844
45165
  if (callError) {
44845
- const errorMessage = extractErrorMessageSync(callError);
45166
+ const errorMessage2 = extractErrorMessageSync(callError);
44846
45167
  OutputFormatter.error({
44847
45168
  Result: RESULTS.Failure,
44848
45169
  Message: "Error querying DocsAI",
44849
- Instructions: errorMessage
45170
+ Instructions: errorMessage2
44850
45171
  });
44851
45172
  processContext.exit(1);
44852
45173
  return;
package/package.json CHANGED
@@ -1,37 +1,30 @@
1
1
  {
2
- "name": "@uipath/docsai-tool",
3
- "version": "1.1.0",
4
- "description": "Search UiPath documentation with AI-powered answers.",
5
- "private": false,
6
- "repository": {
7
- "type": "git",
8
- "url": "https://github.com/UiPath/cli.git",
9
- "directory": "packages/docsai-tool"
10
- },
11
- "publishConfig": {
12
- "registry": "https://registry.npmjs.org/"
13
- },
14
- "keywords": [
15
- "cli-tool"
16
- ],
17
- "type": "module",
18
- "main": "./dist/tool.js",
19
- "exports": {
20
- ".": "./dist/tool.js"
21
- },
22
- "bin": {
23
- "docsai-tool": "./dist/index.js"
24
- },
25
- "files": [
26
- "dist"
27
- ],
28
- "devDependencies": {
29
- "@uipath/auth": "1.1.0",
30
- "@uipath/common": "1.1.0",
31
- "@modelcontextprotocol/sdk": "^1.26.0",
32
- "@types/node": "^25.5.2",
33
- "commander": "^14.0.3",
34
- "typescript": "^6.0.2"
35
- },
36
- "gitHead": "06e8c8f566df4b87da4a008635483c62f64f33f0"
2
+ "name": "@uipath/docsai-tool",
3
+ "license": "MIT",
4
+ "version": "1.195.0",
5
+ "description": "Search UiPath documentation with AI-powered answers.",
6
+ "private": false,
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/UiPath/cli.git",
10
+ "directory": "packages/docsai-tool"
11
+ },
12
+ "publishConfig": {
13
+ "registry": "https://registry.npmjs.org/"
14
+ },
15
+ "keywords": [
16
+ "cli-tool"
17
+ ],
18
+ "type": "module",
19
+ "main": "./dist/tool.js",
20
+ "exports": {
21
+ ".": "./dist/tool.js"
22
+ },
23
+ "bin": {
24
+ "docsai-tool": "./dist/index.js"
25
+ },
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "gitHead": "65fabb84552758b2710d8ca68470e70a9b1d19bc"
37
30
  }