@uipath/llmgw-tool 1.1.0 → 1.2.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.
- package/dist/tool.js +568 -118
- package/package.json +25 -31
package/dist/tool.js
CHANGED
|
@@ -3,7 +3,8 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
3
3
|
// package.json
|
|
4
4
|
var package_default = {
|
|
5
5
|
name: "@uipath/llmgw-tool",
|
|
6
|
-
|
|
6
|
+
license: "MIT",
|
|
7
|
+
version: "1.2.0",
|
|
7
8
|
description: "CLI plugin for UiPath AI Trust Layer Bring-Your-Own LLM connections.",
|
|
8
9
|
private: false,
|
|
9
10
|
repository: {
|
|
@@ -39,6 +40,7 @@ var package_default = {
|
|
|
39
40
|
};
|
|
40
41
|
|
|
41
42
|
// ../../filesystem/src/node.ts
|
|
43
|
+
import { randomUUID } from "node:crypto";
|
|
42
44
|
import { existsSync } from "node:fs";
|
|
43
45
|
import * as fs6 from "node:fs/promises";
|
|
44
46
|
import * as os2 from "node:os";
|
|
@@ -655,6 +657,13 @@ defineLazyProperty(apps, "safari", () => detectPlatformBinary({
|
|
|
655
657
|
var open_default = open;
|
|
656
658
|
|
|
657
659
|
// ../../filesystem/src/node.ts
|
|
660
|
+
var LOCK_HEARTBEAT_MS = 5000;
|
|
661
|
+
var LOCK_STALE_MS = 15000;
|
|
662
|
+
var LOCK_MAX_WAIT_MS = 20000;
|
|
663
|
+
var LOCK_MAX_HOLD_MS = 60000;
|
|
664
|
+
var LOCK_RETRY_MIN_MS = 100;
|
|
665
|
+
var LOCK_RETRY_JITTER_MS = 200;
|
|
666
|
+
|
|
658
667
|
class NodeFileSystem {
|
|
659
668
|
path = {
|
|
660
669
|
join: path2.join,
|
|
@@ -731,6 +740,90 @@ class NodeFileSystem {
|
|
|
731
740
|
async mkdir(dirPath) {
|
|
732
741
|
await fs6.mkdir(dirPath, { recursive: true });
|
|
733
742
|
}
|
|
743
|
+
async acquireLock(lockPath) {
|
|
744
|
+
const canonicalPath = await this.canonicalizeLockTarget(lockPath);
|
|
745
|
+
const lockFile = `${canonicalPath}.lock`;
|
|
746
|
+
const ownerId = randomUUID();
|
|
747
|
+
const start = Date.now();
|
|
748
|
+
while (true) {
|
|
749
|
+
try {
|
|
750
|
+
await fs6.writeFile(lockFile, ownerId, { flag: "wx" });
|
|
751
|
+
return this.createLockRelease(lockFile, ownerId);
|
|
752
|
+
} catch (error) {
|
|
753
|
+
if (!this.hasErrnoCode(error, "EEXIST")) {
|
|
754
|
+
throw error;
|
|
755
|
+
}
|
|
756
|
+
const stats = await fs6.stat(lockFile).catch(() => null);
|
|
757
|
+
if (stats && Date.now() - stats.mtimeMs > LOCK_STALE_MS) {
|
|
758
|
+
const reclaimed = await fs6.rm(lockFile, { force: true }).then(() => true).catch(() => false);
|
|
759
|
+
if (reclaimed)
|
|
760
|
+
continue;
|
|
761
|
+
}
|
|
762
|
+
if (Date.now() - start > LOCK_MAX_WAIT_MS) {
|
|
763
|
+
throw new Error(`ELOCKED: timed out waiting for lock on ${canonicalPath}`);
|
|
764
|
+
}
|
|
765
|
+
await new Promise((resolve2) => setTimeout(resolve2, LOCK_RETRY_MIN_MS + Math.random() * LOCK_RETRY_JITTER_MS));
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
async canonicalizeLockTarget(lockPath) {
|
|
770
|
+
const absolute = path2.resolve(lockPath);
|
|
771
|
+
const fullReal = await fs6.realpath(absolute).catch(() => null);
|
|
772
|
+
if (fullReal)
|
|
773
|
+
return fullReal;
|
|
774
|
+
const parent = path2.dirname(absolute);
|
|
775
|
+
const base = path2.basename(absolute);
|
|
776
|
+
const canonicalParent = await fs6.realpath(parent).catch(() => parent);
|
|
777
|
+
return path2.join(canonicalParent, base);
|
|
778
|
+
}
|
|
779
|
+
createLockRelease(lockFile, ownerId) {
|
|
780
|
+
const heartbeatStart = Date.now();
|
|
781
|
+
let heartbeatTimer;
|
|
782
|
+
let stopped = false;
|
|
783
|
+
const stopHeartbeat = () => {
|
|
784
|
+
stopped = true;
|
|
785
|
+
if (heartbeatTimer)
|
|
786
|
+
clearTimeout(heartbeatTimer);
|
|
787
|
+
};
|
|
788
|
+
const scheduleNextHeartbeat = () => {
|
|
789
|
+
if (stopped)
|
|
790
|
+
return;
|
|
791
|
+
if (Date.now() - heartbeatStart >= LOCK_MAX_HOLD_MS) {
|
|
792
|
+
stopped = true;
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
heartbeatTimer = setTimeout(() => {
|
|
796
|
+
runHeartbeat();
|
|
797
|
+
}, LOCK_HEARTBEAT_MS);
|
|
798
|
+
heartbeatTimer.unref?.();
|
|
799
|
+
};
|
|
800
|
+
const runHeartbeat = async () => {
|
|
801
|
+
if (stopped)
|
|
802
|
+
return;
|
|
803
|
+
const current = await fs6.readFile(lockFile, "utf-8").catch(() => null);
|
|
804
|
+
if (stopped)
|
|
805
|
+
return;
|
|
806
|
+
if (current !== ownerId) {
|
|
807
|
+
stopped = true;
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
const now = Date.now() / 1000;
|
|
811
|
+
await fs6.utimes(lockFile, now, now).catch(() => {});
|
|
812
|
+
scheduleNextHeartbeat();
|
|
813
|
+
};
|
|
814
|
+
scheduleNextHeartbeat();
|
|
815
|
+
let released = false;
|
|
816
|
+
return async () => {
|
|
817
|
+
if (released)
|
|
818
|
+
return;
|
|
819
|
+
released = true;
|
|
820
|
+
stopHeartbeat();
|
|
821
|
+
const current = await fs6.readFile(lockFile, "utf-8").catch(() => null);
|
|
822
|
+
if (current === ownerId) {
|
|
823
|
+
await fs6.rm(lockFile, { force: true });
|
|
824
|
+
}
|
|
825
|
+
};
|
|
826
|
+
}
|
|
734
827
|
async rm(filePath) {
|
|
735
828
|
await fs6.rm(filePath, { recursive: true, force: true });
|
|
736
829
|
}
|
|
@@ -776,7 +869,10 @@ class NodeFileSystem {
|
|
|
776
869
|
}
|
|
777
870
|
}
|
|
778
871
|
isEnoent(error) {
|
|
779
|
-
return
|
|
872
|
+
return this.hasErrnoCode(error, "ENOENT");
|
|
873
|
+
}
|
|
874
|
+
hasErrnoCode(error, code) {
|
|
875
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
780
876
|
}
|
|
781
877
|
}
|
|
782
878
|
|
|
@@ -918,10 +1014,15 @@ async function extractErrorDetails(error, options) {
|
|
|
918
1014
|
}
|
|
919
1015
|
if (parsedBody?.errorCode && typeof parsedBody.errorCode === "string") {
|
|
920
1016
|
context.errorCode = parsedBody.errorCode;
|
|
1017
|
+
} else if (parsedBody?.code && typeof parsedBody.code === "string") {
|
|
1018
|
+
context.errorCode = parsedBody.code;
|
|
921
1019
|
}
|
|
922
1020
|
if (parsedBody?.requestId && typeof parsedBody.requestId === "string") {
|
|
923
1021
|
context.requestId = parsedBody.requestId;
|
|
924
1022
|
}
|
|
1023
|
+
if (parsedBody?.traceId && typeof parsedBody.traceId === "string") {
|
|
1024
|
+
context.traceId = parsedBody.traceId;
|
|
1025
|
+
}
|
|
925
1026
|
if (status === 429) {
|
|
926
1027
|
const resp = response;
|
|
927
1028
|
const headersObj = resp?.headers;
|
|
@@ -941,7 +1042,35 @@ async function extractErrorDetails(error, options) {
|
|
|
941
1042
|
}
|
|
942
1043
|
}
|
|
943
1044
|
const hasContext = Object.keys(context).length > 0;
|
|
944
|
-
|
|
1045
|
+
let parsedErrors;
|
|
1046
|
+
if (parsedBody?.errors && typeof parsedBody.errors === "object") {
|
|
1047
|
+
const errors = {};
|
|
1048
|
+
for (const [field, raw] of Object.entries(parsedBody.errors)) {
|
|
1049
|
+
if (Array.isArray(raw)) {
|
|
1050
|
+
const messages = raw.map((entry) => {
|
|
1051
|
+
if (typeof entry === "string")
|
|
1052
|
+
return entry;
|
|
1053
|
+
if (entry && typeof entry === "object" && typeof entry.message === "string") {
|
|
1054
|
+
return entry.message;
|
|
1055
|
+
}
|
|
1056
|
+
return String(entry);
|
|
1057
|
+
}).filter(Boolean);
|
|
1058
|
+
if (messages.length > 0)
|
|
1059
|
+
errors[field] = messages;
|
|
1060
|
+
} else if (typeof raw === "string") {
|
|
1061
|
+
errors[field] = [raw];
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
if (Object.keys(errors).length > 0)
|
|
1065
|
+
parsedErrors = errors;
|
|
1066
|
+
}
|
|
1067
|
+
return {
|
|
1068
|
+
result,
|
|
1069
|
+
message,
|
|
1070
|
+
details,
|
|
1071
|
+
...hasContext ? { context } : {},
|
|
1072
|
+
...parsedErrors ? { parsedErrors } : {}
|
|
1073
|
+
};
|
|
945
1074
|
}
|
|
946
1075
|
async function extractErrorMessage(error, options) {
|
|
947
1076
|
const { message } = await extractErrorDetails(error, options);
|
|
@@ -6072,6 +6201,60 @@ function escapeNonAscii(jsonText) {
|
|
|
6072
6201
|
function needsAsciiSafeJson(sink) {
|
|
6073
6202
|
return process.platform === "win32" && !sink.capabilities.isInteractive;
|
|
6074
6203
|
}
|
|
6204
|
+
function isPlainRecord(value) {
|
|
6205
|
+
if (value === null || typeof value !== "object")
|
|
6206
|
+
return false;
|
|
6207
|
+
const prototype = Object.getPrototypeOf(value);
|
|
6208
|
+
return prototype === Object.prototype || prototype === null;
|
|
6209
|
+
}
|
|
6210
|
+
function toLowerCamelCaseKey(key) {
|
|
6211
|
+
if (!key)
|
|
6212
|
+
return key;
|
|
6213
|
+
if (/[_\-\s]/.test(key)) {
|
|
6214
|
+
const [firstPart, ...restParts] = key.split(/[_\-\s]+/).filter(Boolean);
|
|
6215
|
+
if (!firstPart)
|
|
6216
|
+
return key;
|
|
6217
|
+
return [
|
|
6218
|
+
toLowerCamelCaseSimpleKey(firstPart),
|
|
6219
|
+
...restParts.map((part) => {
|
|
6220
|
+
const normalized = toLowerCamelCaseSimpleKey(part);
|
|
6221
|
+
return normalized.charAt(0).toUpperCase() + normalized.slice(1);
|
|
6222
|
+
})
|
|
6223
|
+
].join("");
|
|
6224
|
+
}
|
|
6225
|
+
return toLowerCamelCaseSimpleKey(key);
|
|
6226
|
+
}
|
|
6227
|
+
function toLowerCamelCaseSimpleKey(key) {
|
|
6228
|
+
if (/^[A-Z0-9]+$/.test(key))
|
|
6229
|
+
return key.toLowerCase();
|
|
6230
|
+
return key.replace(/^[A-Z]+(?=[A-Z][a-z]|\d|$)|^[A-Z]/, (match) => match.toLowerCase());
|
|
6231
|
+
}
|
|
6232
|
+
function toPascalCaseKey(key) {
|
|
6233
|
+
const lowerCamelKey = toLowerCamelCaseKey(key);
|
|
6234
|
+
return lowerCamelKey ? lowerCamelKey.charAt(0).toUpperCase() + lowerCamelKey.slice(1) : lowerCamelKey;
|
|
6235
|
+
}
|
|
6236
|
+
function toPascalCaseData(value) {
|
|
6237
|
+
if (Array.isArray(value))
|
|
6238
|
+
return value.map(toPascalCaseData);
|
|
6239
|
+
if (!isPlainRecord(value))
|
|
6240
|
+
return value;
|
|
6241
|
+
const result = {};
|
|
6242
|
+
for (const [key, nestedValue] of Object.entries(value)) {
|
|
6243
|
+
result[toPascalCaseKey(key)] = toPascalCaseData(nestedValue);
|
|
6244
|
+
}
|
|
6245
|
+
return result;
|
|
6246
|
+
}
|
|
6247
|
+
function normalizeDataKeys(data) {
|
|
6248
|
+
return toPascalCaseData(data);
|
|
6249
|
+
}
|
|
6250
|
+
function normalizeOutputKeys(data) {
|
|
6251
|
+
const result = {};
|
|
6252
|
+
for (const [key, value] of Object.entries(data)) {
|
|
6253
|
+
const pascalKey = toPascalCaseKey(key);
|
|
6254
|
+
result[pascalKey] = pascalKey === "Data" ? value : toPascalCaseData(value);
|
|
6255
|
+
}
|
|
6256
|
+
return result;
|
|
6257
|
+
}
|
|
6075
6258
|
function printOutput(data, format = "json", logFn, asciiSafe = false) {
|
|
6076
6259
|
if (!data) {
|
|
6077
6260
|
logFn("Empty response object. No data to display.");
|
|
@@ -6134,7 +6317,7 @@ function wrapText(text, width) {
|
|
|
6134
6317
|
function printTable(data, logFn, externalLogValue) {
|
|
6135
6318
|
if (data.length === 0)
|
|
6136
6319
|
return;
|
|
6137
|
-
const keys = Object.keys(data[0]).filter((key) =>
|
|
6320
|
+
const keys = Object.keys(data[0]).filter((key) => !["code", "log"].includes(key.toLowerCase()));
|
|
6138
6321
|
const maxWidths = keys.map((key) => Math.max(key.length, ...data.map((item) => cellToString(item[key]).length)));
|
|
6139
6322
|
const header = keys.map((key, i2) => key.padEnd(maxWidths[i2])).join(" | ");
|
|
6140
6323
|
logFn(header);
|
|
@@ -6149,7 +6332,7 @@ function printTable(data, logFn, externalLogValue) {
|
|
|
6149
6332
|
}
|
|
6150
6333
|
}
|
|
6151
6334
|
function printVerticalTable(data, logFn = console.log, externalLogValue) {
|
|
6152
|
-
const keys = Object.keys(data).filter((key) =>
|
|
6335
|
+
const keys = Object.keys(data).filter((key) => !["code", "log"].includes(key.toLowerCase()));
|
|
6153
6336
|
if (keys.length === 0)
|
|
6154
6337
|
return;
|
|
6155
6338
|
const maxKeyWidth = Math.max(...keys.map((key) => key.length));
|
|
@@ -6165,7 +6348,7 @@ function printVerticalTable(data, logFn = console.log, externalLogValue) {
|
|
|
6165
6348
|
function printResizableTable(data, logFn = console.log, externalLogValue) {
|
|
6166
6349
|
if (data.length === 0)
|
|
6167
6350
|
return;
|
|
6168
|
-
const keys = Object.keys(data[0]).filter((key) =>
|
|
6351
|
+
const keys = Object.keys(data[0]).filter((key) => !["code", "log"].includes(key.toLowerCase()));
|
|
6169
6352
|
if (keys.length === 0)
|
|
6170
6353
|
return;
|
|
6171
6354
|
if (!process.stdout.isTTY) {
|
|
@@ -6241,8 +6424,26 @@ function printResizableTable(data, logFn = console.log, externalLogValue) {
|
|
|
6241
6424
|
function toYaml(data) {
|
|
6242
6425
|
return dump(data);
|
|
6243
6426
|
}
|
|
6427
|
+
class FilterEvaluationError extends Error {
|
|
6428
|
+
__brand = "FilterEvaluationError";
|
|
6429
|
+
filter;
|
|
6430
|
+
instructions;
|
|
6431
|
+
result = RESULTS.ValidationError;
|
|
6432
|
+
constructor(filter, cause) {
|
|
6433
|
+
const underlying = cause instanceof Error ? cause.message : String(cause);
|
|
6434
|
+
super(`Filter '${filter}' failed to evaluate: ${underlying}`);
|
|
6435
|
+
this.name = "FilterEvaluationError";
|
|
6436
|
+
this.filter = filter;
|
|
6437
|
+
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(@)'.";
|
|
6438
|
+
}
|
|
6439
|
+
}
|
|
6244
6440
|
function applyFilter(data, filter) {
|
|
6245
|
-
|
|
6441
|
+
let result;
|
|
6442
|
+
try {
|
|
6443
|
+
result = search(data, filter);
|
|
6444
|
+
} catch (err) {
|
|
6445
|
+
throw new FilterEvaluationError(filter, err);
|
|
6446
|
+
}
|
|
6246
6447
|
if (result == null)
|
|
6247
6448
|
return [];
|
|
6248
6449
|
if (Array.isArray(result)) {
|
|
@@ -6259,13 +6460,18 @@ function applyFilter(data, filter) {
|
|
|
6259
6460
|
}
|
|
6260
6461
|
var OutputFormatter;
|
|
6261
6462
|
((OutputFormatter) => {
|
|
6262
|
-
function success(data) {
|
|
6463
|
+
function success(data, options) {
|
|
6263
6464
|
data.Log ??= getLogFilePath() || undefined;
|
|
6465
|
+
const normalize = !options?.preserveDataKeys;
|
|
6466
|
+
if (normalize) {
|
|
6467
|
+
data.Data = normalizeDataKeys(data.Data);
|
|
6468
|
+
}
|
|
6264
6469
|
const filter = getOutputFilter();
|
|
6265
6470
|
if (filter) {
|
|
6266
|
-
|
|
6471
|
+
const filtered = applyFilter(data.Data, filter);
|
|
6472
|
+
data.Data = normalize ? normalizeDataKeys(filtered) : filtered;
|
|
6267
6473
|
}
|
|
6268
|
-
logOutput(data, getOutputFormat());
|
|
6474
|
+
logOutput(normalizeOutputKeys(data), getOutputFormat());
|
|
6269
6475
|
}
|
|
6270
6476
|
OutputFormatter.success = success;
|
|
6271
6477
|
function error(data) {
|
|
@@ -6275,7 +6481,7 @@ var OutputFormatter;
|
|
|
6275
6481
|
result: data.Result,
|
|
6276
6482
|
message: data.Message
|
|
6277
6483
|
});
|
|
6278
|
-
logOutput(data, getOutputFormat());
|
|
6484
|
+
logOutput(normalizeOutputKeys(data), getOutputFormat());
|
|
6279
6485
|
}
|
|
6280
6486
|
OutputFormatter.error = error;
|
|
6281
6487
|
function emitList(code, items, opts) {
|
|
@@ -6296,13 +6502,14 @@ var OutputFormatter;
|
|
|
6296
6502
|
function log(data) {
|
|
6297
6503
|
const format = getOutputFormat();
|
|
6298
6504
|
const sink = getOutputSink();
|
|
6505
|
+
const normalized = toPascalCaseData(data);
|
|
6299
6506
|
if (format === "json") {
|
|
6300
|
-
const json2 = JSON.stringify(
|
|
6507
|
+
const json2 = JSON.stringify(normalized);
|
|
6301
6508
|
const safe = needsAsciiSafeJson(sink) ? escapeNonAscii(json2) : json2;
|
|
6302
6509
|
sink.writeErr(`${safe}
|
|
6303
6510
|
`);
|
|
6304
6511
|
} else {
|
|
6305
|
-
for (const [key, value] of Object.entries(
|
|
6512
|
+
for (const [key, value] of Object.entries(normalized)) {
|
|
6306
6513
|
sink.writeErr(`${key}: ${value}
|
|
6307
6514
|
`);
|
|
6308
6515
|
}
|
|
@@ -6311,12 +6518,16 @@ var OutputFormatter;
|
|
|
6311
6518
|
OutputFormatter.log = log;
|
|
6312
6519
|
function formatToString(data) {
|
|
6313
6520
|
const filter = getOutputFilter();
|
|
6314
|
-
if (
|
|
6315
|
-
data.Data =
|
|
6521
|
+
if ("Data" in data && data.Data != null) {
|
|
6522
|
+
data.Data = normalizeDataKeys(data.Data);
|
|
6523
|
+
if (filter) {
|
|
6524
|
+
data.Data = normalizeDataKeys(applyFilter(data.Data, filter));
|
|
6525
|
+
}
|
|
6316
6526
|
}
|
|
6527
|
+
const output = normalizeOutputKeys(data);
|
|
6317
6528
|
const lines = [];
|
|
6318
6529
|
const sink = getOutputSink();
|
|
6319
|
-
printOutput(
|
|
6530
|
+
printOutput(output, getOutputFormat(), (msg) => {
|
|
6320
6531
|
lines.push(msg);
|
|
6321
6532
|
}, needsAsciiSafeJson(sink));
|
|
6322
6533
|
return lines.join(`
|
|
@@ -7731,6 +7942,22 @@ JSONPath.prototype.vm = vm;
|
|
|
7731
7942
|
import { Option } from "commander";
|
|
7732
7943
|
// ../../common/src/option-validators.ts
|
|
7733
7944
|
import { InvalidArgumentError } from "commander";
|
|
7945
|
+
// ../../common/src/polling/types.ts
|
|
7946
|
+
var PollOutcome = {
|
|
7947
|
+
Completed: "completed",
|
|
7948
|
+
Timeout: "timeout",
|
|
7949
|
+
Interrupted: "interrupted",
|
|
7950
|
+
Aborted: "aborted",
|
|
7951
|
+
Failed: "failed"
|
|
7952
|
+
};
|
|
7953
|
+
|
|
7954
|
+
// ../../common/src/polling/poll-failure-mapping.ts
|
|
7955
|
+
var REASON_BY_OUTCOME = {
|
|
7956
|
+
[PollOutcome.Timeout]: "poll_timeout",
|
|
7957
|
+
[PollOutcome.Failed]: "poll_failed",
|
|
7958
|
+
[PollOutcome.Interrupted]: "poll_failed",
|
|
7959
|
+
[PollOutcome.Aborted]: "poll_aborted"
|
|
7960
|
+
};
|
|
7734
7961
|
// ../../common/src/polling/terminal-statuses.ts
|
|
7735
7962
|
var TERMINAL_STATUSES = new Set([
|
|
7736
7963
|
"completed",
|
|
@@ -7758,6 +7985,8 @@ var ScreenLogger;
|
|
|
7758
7985
|
}
|
|
7759
7986
|
ScreenLogger.progress = progress;
|
|
7760
7987
|
})(ScreenLogger ||= {});
|
|
7988
|
+
// ../../common/src/sdk-user-agent.ts
|
|
7989
|
+
var sdkUserAgentHostToken = singleton("SdkUserAgentHostToken");
|
|
7761
7990
|
// ../../common/src/tool-provider.ts
|
|
7762
7991
|
var factorySlot = singleton("PackagerFactoryProvider");
|
|
7763
7992
|
// ../../common/src/trackedAction.ts
|
|
@@ -7943,13 +8172,17 @@ Command2.prototype.trackedAction = function(context, fn, properties) {
|
|
|
7943
8172
|
const [error] = await catchError(fn(...args));
|
|
7944
8173
|
if (error) {
|
|
7945
8174
|
errorMessage = error instanceof Error ? error.message : String(error);
|
|
7946
|
-
logger.
|
|
8175
|
+
logger.debug(`[trackedAction] ${telemetryName} failed: ${errorMessage}`);
|
|
8176
|
+
const typed = error;
|
|
8177
|
+
const customInstructions = typeof typed.instructions === "string" ? typed.instructions : undefined;
|
|
8178
|
+
const customResult = typeof typed.result === "string" && typed.result !== RESULTS.Success && Object.values(RESULTS).includes(typed.result) ? typed.result : undefined;
|
|
8179
|
+
const finalResult = customResult ?? RESULTS.Failure;
|
|
7947
8180
|
OutputFormatter.error({
|
|
7948
|
-
Result:
|
|
8181
|
+
Result: finalResult,
|
|
7949
8182
|
Message: errorMessage,
|
|
7950
|
-
Instructions: "An unexpected error occurred. Run with --log-level debug for details."
|
|
8183
|
+
Instructions: customInstructions ?? "An unexpected error occurred. Run with --log-level debug for details."
|
|
7951
8184
|
});
|
|
7952
|
-
context.exit(
|
|
8185
|
+
context.exit(EXIT_CODES[finalResult]);
|
|
7953
8186
|
}
|
|
7954
8187
|
const durationMs = performance.now() - startTime;
|
|
7955
8188
|
const success = !error && (process.exitCode === undefined || process.exitCode === 0);
|
|
@@ -7993,6 +8226,7 @@ import path3 from "node:path";
|
|
|
7993
8226
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
7994
8227
|
import childProcess32 from "node:child_process";
|
|
7995
8228
|
import fs52, { constants as fsConstants22 } from "node:fs/promises";
|
|
8229
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
7996
8230
|
import { existsSync as existsSync2 } from "node:fs";
|
|
7997
8231
|
import * as fs62 from "node:fs/promises";
|
|
7998
8232
|
import * as os22 from "node:os";
|
|
@@ -8744,6 +8978,90 @@ class NodeFileSystem2 {
|
|
|
8744
8978
|
async mkdir(dirPath) {
|
|
8745
8979
|
await fs62.mkdir(dirPath, { recursive: true });
|
|
8746
8980
|
}
|
|
8981
|
+
async acquireLock(lockPath) {
|
|
8982
|
+
const canonicalPath = await this.canonicalizeLockTarget(lockPath);
|
|
8983
|
+
const lockFile = `${canonicalPath}.lock`;
|
|
8984
|
+
const ownerId = randomUUID2();
|
|
8985
|
+
const start = Date.now();
|
|
8986
|
+
while (true) {
|
|
8987
|
+
try {
|
|
8988
|
+
await fs62.writeFile(lockFile, ownerId, { flag: "wx" });
|
|
8989
|
+
return this.createLockRelease(lockFile, ownerId);
|
|
8990
|
+
} catch (error) {
|
|
8991
|
+
if (!this.hasErrnoCode(error, "EEXIST")) {
|
|
8992
|
+
throw error;
|
|
8993
|
+
}
|
|
8994
|
+
const stats = await fs62.stat(lockFile).catch(() => null);
|
|
8995
|
+
if (stats && Date.now() - stats.mtimeMs > LOCK_STALE_MS2) {
|
|
8996
|
+
const reclaimed = await fs62.rm(lockFile, { force: true }).then(() => true).catch(() => false);
|
|
8997
|
+
if (reclaimed)
|
|
8998
|
+
continue;
|
|
8999
|
+
}
|
|
9000
|
+
if (Date.now() - start > LOCK_MAX_WAIT_MS2) {
|
|
9001
|
+
throw new Error(`ELOCKED: timed out waiting for lock on ${canonicalPath}`);
|
|
9002
|
+
}
|
|
9003
|
+
await new Promise((resolve22) => setTimeout(resolve22, LOCK_RETRY_MIN_MS2 + Math.random() * LOCK_RETRY_JITTER_MS2));
|
|
9004
|
+
}
|
|
9005
|
+
}
|
|
9006
|
+
}
|
|
9007
|
+
async canonicalizeLockTarget(lockPath) {
|
|
9008
|
+
const absolute = path22.resolve(lockPath);
|
|
9009
|
+
const fullReal = await fs62.realpath(absolute).catch(() => null);
|
|
9010
|
+
if (fullReal)
|
|
9011
|
+
return fullReal;
|
|
9012
|
+
const parent = path22.dirname(absolute);
|
|
9013
|
+
const base = path22.basename(absolute);
|
|
9014
|
+
const canonicalParent = await fs62.realpath(parent).catch(() => parent);
|
|
9015
|
+
return path22.join(canonicalParent, base);
|
|
9016
|
+
}
|
|
9017
|
+
createLockRelease(lockFile, ownerId) {
|
|
9018
|
+
const heartbeatStart = Date.now();
|
|
9019
|
+
let heartbeatTimer;
|
|
9020
|
+
let stopped = false;
|
|
9021
|
+
const stopHeartbeat = () => {
|
|
9022
|
+
stopped = true;
|
|
9023
|
+
if (heartbeatTimer)
|
|
9024
|
+
clearTimeout(heartbeatTimer);
|
|
9025
|
+
};
|
|
9026
|
+
const scheduleNextHeartbeat = () => {
|
|
9027
|
+
if (stopped)
|
|
9028
|
+
return;
|
|
9029
|
+
if (Date.now() - heartbeatStart >= LOCK_MAX_HOLD_MS2) {
|
|
9030
|
+
stopped = true;
|
|
9031
|
+
return;
|
|
9032
|
+
}
|
|
9033
|
+
heartbeatTimer = setTimeout(() => {
|
|
9034
|
+
runHeartbeat();
|
|
9035
|
+
}, LOCK_HEARTBEAT_MS2);
|
|
9036
|
+
heartbeatTimer.unref?.();
|
|
9037
|
+
};
|
|
9038
|
+
const runHeartbeat = async () => {
|
|
9039
|
+
if (stopped)
|
|
9040
|
+
return;
|
|
9041
|
+
const current = await fs62.readFile(lockFile, "utf-8").catch(() => null);
|
|
9042
|
+
if (stopped)
|
|
9043
|
+
return;
|
|
9044
|
+
if (current !== ownerId) {
|
|
9045
|
+
stopped = true;
|
|
9046
|
+
return;
|
|
9047
|
+
}
|
|
9048
|
+
const now = Date.now() / 1000;
|
|
9049
|
+
await fs62.utimes(lockFile, now, now).catch(() => {});
|
|
9050
|
+
scheduleNextHeartbeat();
|
|
9051
|
+
};
|
|
9052
|
+
scheduleNextHeartbeat();
|
|
9053
|
+
let released = false;
|
|
9054
|
+
return async () => {
|
|
9055
|
+
if (released)
|
|
9056
|
+
return;
|
|
9057
|
+
released = true;
|
|
9058
|
+
stopHeartbeat();
|
|
9059
|
+
const current = await fs62.readFile(lockFile, "utf-8").catch(() => null);
|
|
9060
|
+
if (current === ownerId) {
|
|
9061
|
+
await fs62.rm(lockFile, { force: true });
|
|
9062
|
+
}
|
|
9063
|
+
};
|
|
9064
|
+
}
|
|
8747
9065
|
async rm(filePath) {
|
|
8748
9066
|
await fs62.rm(filePath, { recursive: true, force: true });
|
|
8749
9067
|
}
|
|
@@ -8789,9 +9107,18 @@ class NodeFileSystem2 {
|
|
|
8789
9107
|
}
|
|
8790
9108
|
}
|
|
8791
9109
|
isEnoent(error) {
|
|
8792
|
-
return
|
|
9110
|
+
return this.hasErrnoCode(error, "ENOENT");
|
|
9111
|
+
}
|
|
9112
|
+
hasErrnoCode(error, code) {
|
|
9113
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
8793
9114
|
}
|
|
8794
9115
|
}
|
|
9116
|
+
var LOCK_HEARTBEAT_MS2 = 5000;
|
|
9117
|
+
var LOCK_STALE_MS2 = 15000;
|
|
9118
|
+
var LOCK_MAX_WAIT_MS2 = 20000;
|
|
9119
|
+
var LOCK_MAX_HOLD_MS2 = 60000;
|
|
9120
|
+
var LOCK_RETRY_MIN_MS2 = 100;
|
|
9121
|
+
var LOCK_RETRY_JITTER_MS2 = 200;
|
|
8795
9122
|
var init_node = __esm(() => {
|
|
8796
9123
|
init_open();
|
|
8797
9124
|
});
|
|
@@ -8803,7 +9130,7 @@ var init_src = __esm(() => {
|
|
|
8803
9130
|
fsInstance2 = new NodeFileSystem2;
|
|
8804
9131
|
});
|
|
8805
9132
|
var require_coreipc = __commonJS((exports, module) => {
|
|
8806
|
-
var __dirname3 = "/
|
|
9133
|
+
var __dirname3 = "/home/runner/work/cli/cli/node_modules/@uipath/coreipc";
|
|
8807
9134
|
/*! For license information please see index.js.LICENSE.txt */
|
|
8808
9135
|
(function(e, t) {
|
|
8809
9136
|
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();
|
|
@@ -26603,6 +26930,9 @@ var require_dist = __commonJS((exports) => {
|
|
|
26603
26930
|
exports.RobotProxyConstructor = RobotProxyConstructor;
|
|
26604
26931
|
__exportStar(require_agent(), exports);
|
|
26605
26932
|
});
|
|
26933
|
+
var init_server = __esm(() => {
|
|
26934
|
+
init_constants();
|
|
26935
|
+
});
|
|
26606
26936
|
init_constants();
|
|
26607
26937
|
var DEFAULT_CLIENT_ID = "36dea5b8-e8bb-423d-8e7b-c808df8f1c00";
|
|
26608
26938
|
var AUTH_FILE_CONFIG_KEY = Symbol.for("@uipath/auth/AuthFileConfig");
|
|
@@ -26626,32 +26956,7 @@ class InvalidBaseUrlError extends Error {
|
|
|
26626
26956
|
this.name = "InvalidBaseUrlError";
|
|
26627
26957
|
}
|
|
26628
26958
|
}
|
|
26629
|
-
var DEFAULT_SCOPES = [
|
|
26630
|
-
"offline_access",
|
|
26631
|
-
"ProcessMining",
|
|
26632
|
-
"OrchestratorApiUserAccess",
|
|
26633
|
-
"StudioWebBackend",
|
|
26634
|
-
"IdentityServerApi",
|
|
26635
|
-
"ConnectionService",
|
|
26636
|
-
"DataService",
|
|
26637
|
-
"DataServiceApiUserAccess",
|
|
26638
|
-
"DocumentUnderstanding",
|
|
26639
|
-
"EnterpriseContextService",
|
|
26640
|
-
"Directory",
|
|
26641
|
-
"JamJamApi",
|
|
26642
|
-
"LLMGateway",
|
|
26643
|
-
"LLMOps",
|
|
26644
|
-
"OMS",
|
|
26645
|
-
"RCS.FolderAuthorization",
|
|
26646
|
-
"RCS.TagsManagement",
|
|
26647
|
-
"TestmanagerApiUserAccess",
|
|
26648
|
-
"AutomationSolutions",
|
|
26649
|
-
"StudioWebTypeCacheService",
|
|
26650
|
-
"Docs.GPT.Search",
|
|
26651
|
-
"Insights",
|
|
26652
|
-
"ReferenceToken",
|
|
26653
|
-
"Audit.Read"
|
|
26654
|
-
];
|
|
26959
|
+
var DEFAULT_SCOPES = ["openid", "profile", "offline_access"];
|
|
26655
26960
|
var normalizeAndValidateBaseUrl = (rawUrl) => {
|
|
26656
26961
|
let baseUrl = rawUrl;
|
|
26657
26962
|
if (baseUrl.endsWith("/identity_/")) {
|
|
@@ -26701,7 +27006,8 @@ var resolveConfigAsync = async ({
|
|
|
26701
27006
|
if (!clientSecret && fileAuth.clientSecret) {
|
|
26702
27007
|
clientSecret = fileAuth.clientSecret;
|
|
26703
27008
|
}
|
|
26704
|
-
const
|
|
27009
|
+
const isExternalAppAuth = clientId !== DEFAULT_CLIENT_ID && Boolean(clientSecret);
|
|
27010
|
+
const scopes = customScopes && customScopes.length > 0 ? customScopes : fileAuth.scopes && fileAuth.scopes.length > 0 ? fileAuth.scopes : isExternalAppAuth ? [] : DEFAULT_SCOPES;
|
|
26705
27011
|
return {
|
|
26706
27012
|
clientId,
|
|
26707
27013
|
clientSecret,
|
|
@@ -27188,6 +27494,129 @@ function normalizeTokenRefreshFailure() {
|
|
|
27188
27494
|
function normalizeTokenRefreshUnavailableFailure() {
|
|
27189
27495
|
return "token refresh failed before authentication completed";
|
|
27190
27496
|
}
|
|
27497
|
+
function errorMessage(error) {
|
|
27498
|
+
return error instanceof Error ? error.message : String(error);
|
|
27499
|
+
}
|
|
27500
|
+
function computeExpirationThreshold(ensureTokenValidityMinutes) {
|
|
27501
|
+
return new Date(Date.now() + (ensureTokenValidityMinutes ?? 0) * 60 * 1000);
|
|
27502
|
+
}
|
|
27503
|
+
async function runRefreshLocked(inputs) {
|
|
27504
|
+
const {
|
|
27505
|
+
absolutePath,
|
|
27506
|
+
refreshToken: callerRefreshToken,
|
|
27507
|
+
customAuthority,
|
|
27508
|
+
ensureTokenValidityMinutes,
|
|
27509
|
+
loadEnvFile,
|
|
27510
|
+
saveEnvFile,
|
|
27511
|
+
refreshFn,
|
|
27512
|
+
resolveConfig
|
|
27513
|
+
} = inputs;
|
|
27514
|
+
const expirationThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
|
|
27515
|
+
let fresh;
|
|
27516
|
+
try {
|
|
27517
|
+
fresh = await loadEnvFile({ envPath: absolutePath });
|
|
27518
|
+
} catch (error) {
|
|
27519
|
+
return {
|
|
27520
|
+
kind: "fail",
|
|
27521
|
+
status: {
|
|
27522
|
+
loginStatus: "Refresh Failed",
|
|
27523
|
+
hint: "Could not read the auth file while refreshing. Retry, or run 'uip login' to re-authenticate.",
|
|
27524
|
+
tokenRefresh: {
|
|
27525
|
+
attempted: false,
|
|
27526
|
+
success: false,
|
|
27527
|
+
errorMessage: `auth file read failed: ${errorMessage(error)}`
|
|
27528
|
+
}
|
|
27529
|
+
}
|
|
27530
|
+
};
|
|
27531
|
+
}
|
|
27532
|
+
const freshAccess = fresh.UIPATH_ACCESS_TOKEN;
|
|
27533
|
+
const freshExp = freshAccess ? getTokenExpiration(freshAccess) : undefined;
|
|
27534
|
+
if (freshAccess && freshExp && freshExp > expirationThreshold) {
|
|
27535
|
+
return {
|
|
27536
|
+
kind: "ok",
|
|
27537
|
+
accessToken: freshAccess,
|
|
27538
|
+
refreshToken: fresh.UIPATH_REFRESH_TOKEN ?? callerRefreshToken,
|
|
27539
|
+
expiration: freshExp,
|
|
27540
|
+
tokenRefresh: { attempted: false, success: true }
|
|
27541
|
+
};
|
|
27542
|
+
}
|
|
27543
|
+
const tokenForIdP = fresh.UIPATH_REFRESH_TOKEN ?? callerRefreshToken;
|
|
27544
|
+
let refreshedAccess;
|
|
27545
|
+
let refreshedRefresh;
|
|
27546
|
+
try {
|
|
27547
|
+
const config = await resolveConfig({ customAuthority });
|
|
27548
|
+
const refreshed = await refreshFn({
|
|
27549
|
+
refreshToken: tokenForIdP,
|
|
27550
|
+
tokenEndpoint: config.tokenEndpoint,
|
|
27551
|
+
clientId: config.clientId,
|
|
27552
|
+
expectedAuthority: customAuthority
|
|
27553
|
+
});
|
|
27554
|
+
refreshedAccess = refreshed.accessToken;
|
|
27555
|
+
refreshedRefresh = refreshed.refreshToken;
|
|
27556
|
+
} catch (error) {
|
|
27557
|
+
const isOAuthFailure = isTokenRefreshOAuthFailure(error);
|
|
27558
|
+
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.";
|
|
27559
|
+
const message = isOAuthFailure ? normalizeTokenRefreshFailure() : normalizeTokenRefreshUnavailableFailure();
|
|
27560
|
+
return {
|
|
27561
|
+
kind: "fail",
|
|
27562
|
+
status: {
|
|
27563
|
+
loginStatus: "Refresh Failed",
|
|
27564
|
+
hint,
|
|
27565
|
+
tokenRefresh: {
|
|
27566
|
+
attempted: true,
|
|
27567
|
+
success: false,
|
|
27568
|
+
errorMessage: message
|
|
27569
|
+
}
|
|
27570
|
+
}
|
|
27571
|
+
};
|
|
27572
|
+
}
|
|
27573
|
+
const refreshedExp = getTokenExpiration(refreshedAccess);
|
|
27574
|
+
if (!refreshedExp || refreshedExp <= new Date) {
|
|
27575
|
+
return {
|
|
27576
|
+
kind: "fail",
|
|
27577
|
+
status: {
|
|
27578
|
+
loginStatus: "Refresh Failed",
|
|
27579
|
+
hint: "The identity server returned an unusable token. Run 'uip login' to re-authenticate.",
|
|
27580
|
+
tokenRefresh: {
|
|
27581
|
+
attempted: true,
|
|
27582
|
+
success: false,
|
|
27583
|
+
errorMessage: "refreshed token has no valid expiration claim"
|
|
27584
|
+
}
|
|
27585
|
+
}
|
|
27586
|
+
};
|
|
27587
|
+
}
|
|
27588
|
+
try {
|
|
27589
|
+
await saveEnvFile({
|
|
27590
|
+
envPath: absolutePath,
|
|
27591
|
+
data: {
|
|
27592
|
+
UIPATH_ACCESS_TOKEN: refreshedAccess,
|
|
27593
|
+
UIPATH_REFRESH_TOKEN: refreshedRefresh
|
|
27594
|
+
},
|
|
27595
|
+
merge: true
|
|
27596
|
+
});
|
|
27597
|
+
return {
|
|
27598
|
+
kind: "ok",
|
|
27599
|
+
accessToken: refreshedAccess,
|
|
27600
|
+
refreshToken: refreshedRefresh,
|
|
27601
|
+
expiration: refreshedExp,
|
|
27602
|
+
tokenRefresh: { attempted: true, success: true }
|
|
27603
|
+
};
|
|
27604
|
+
} catch (error) {
|
|
27605
|
+
const msg = errorMessage(error);
|
|
27606
|
+
return {
|
|
27607
|
+
kind: "ok",
|
|
27608
|
+
accessToken: refreshedAccess,
|
|
27609
|
+
refreshToken: refreshedRefresh,
|
|
27610
|
+
expiration: refreshedExp,
|
|
27611
|
+
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.`,
|
|
27612
|
+
tokenRefresh: {
|
|
27613
|
+
attempted: true,
|
|
27614
|
+
success: true,
|
|
27615
|
+
errorMessage: `persistence failed: ${msg}`
|
|
27616
|
+
}
|
|
27617
|
+
};
|
|
27618
|
+
}
|
|
27619
|
+
}
|
|
27191
27620
|
var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
|
|
27192
27621
|
const {
|
|
27193
27622
|
resolveEnvFilePath = resolveEnvFilePathAsync,
|
|
@@ -27262,73 +27691,103 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
|
|
|
27262
27691
|
let refreshToken = credentials.UIPATH_REFRESH_TOKEN;
|
|
27263
27692
|
let expiration = getTokenExpiration(accessToken);
|
|
27264
27693
|
let persistenceWarning;
|
|
27694
|
+
let lockReleaseFailed = false;
|
|
27265
27695
|
let tokenRefresh;
|
|
27266
|
-
const
|
|
27267
|
-
|
|
27268
|
-
|
|
27269
|
-
|
|
27696
|
+
const outerThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
|
|
27697
|
+
const tryGlobalCredsHint = async () => {
|
|
27698
|
+
const fs72 = getFs();
|
|
27699
|
+
const globalPath = fs72.path.join(fs72.env.homedir(), envFilePath);
|
|
27700
|
+
if (absolutePath === globalPath)
|
|
27701
|
+
return;
|
|
27702
|
+
if (!await fs72.exists(globalPath))
|
|
27703
|
+
return;
|
|
27270
27704
|
try {
|
|
27271
|
-
const
|
|
27272
|
-
|
|
27273
|
-
|
|
27274
|
-
const
|
|
27275
|
-
|
|
27276
|
-
|
|
27277
|
-
|
|
27278
|
-
|
|
27279
|
-
|
|
27280
|
-
refreshedAccess = refreshed.accessToken;
|
|
27281
|
-
refreshedRefresh = refreshed.refreshToken;
|
|
27282
|
-
} catch (error) {
|
|
27283
|
-
const isOAuthFailure = isTokenRefreshOAuthFailure(error);
|
|
27284
|
-
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.";
|
|
27285
|
-
const errorMessage = isOAuthFailure ? normalizeTokenRefreshFailure() : normalizeTokenRefreshUnavailableFailure();
|
|
27286
|
-
return {
|
|
27287
|
-
loginStatus: "Refresh Failed",
|
|
27288
|
-
hint,
|
|
27289
|
-
tokenRefresh: {
|
|
27290
|
-
attempted: true,
|
|
27291
|
-
success: false,
|
|
27292
|
-
errorMessage
|
|
27293
|
-
}
|
|
27294
|
-
};
|
|
27705
|
+
const globalCreds = await loadEnvFile({ envPath: globalPath });
|
|
27706
|
+
if (!globalCreds.UIPATH_ACCESS_TOKEN)
|
|
27707
|
+
return;
|
|
27708
|
+
const globalExp = getTokenExpiration(globalCreds.UIPATH_ACCESS_TOKEN);
|
|
27709
|
+
if (globalExp && globalExp <= new Date)
|
|
27710
|
+
return;
|
|
27711
|
+
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.`;
|
|
27712
|
+
} catch {
|
|
27713
|
+
return;
|
|
27295
27714
|
}
|
|
27296
|
-
|
|
27297
|
-
|
|
27715
|
+
};
|
|
27716
|
+
if (expiration && expiration <= outerThreshold && refreshToken) {
|
|
27717
|
+
let release;
|
|
27718
|
+
try {
|
|
27719
|
+
release = await getFs().acquireLock(absolutePath);
|
|
27720
|
+
} catch (error) {
|
|
27721
|
+
const msg = errorMessage(error);
|
|
27722
|
+
const globalHint = await tryGlobalCredsHint();
|
|
27723
|
+
if (globalHint) {
|
|
27724
|
+
return {
|
|
27725
|
+
loginStatus: "Expired",
|
|
27726
|
+
accessToken,
|
|
27727
|
+
refreshToken,
|
|
27728
|
+
baseUrl: credentials.UIPATH_URL,
|
|
27729
|
+
organizationName: credentials.UIPATH_ORGANIZATION_NAME,
|
|
27730
|
+
organizationId: credentials.UIPATH_ORGANIZATION_ID,
|
|
27731
|
+
tenantName: credentials.UIPATH_TENANT_NAME,
|
|
27732
|
+
tenantId: credentials.UIPATH_TENANT_ID,
|
|
27733
|
+
expiration,
|
|
27734
|
+
source: "file",
|
|
27735
|
+
hint: globalHint,
|
|
27736
|
+
tokenRefresh: {
|
|
27737
|
+
attempted: false,
|
|
27738
|
+
success: false,
|
|
27739
|
+
errorMessage: `lock acquisition failed: ${msg}`
|
|
27740
|
+
}
|
|
27741
|
+
};
|
|
27742
|
+
}
|
|
27298
27743
|
return {
|
|
27299
27744
|
loginStatus: "Refresh Failed",
|
|
27300
|
-
hint: "
|
|
27745
|
+
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.",
|
|
27301
27746
|
tokenRefresh: {
|
|
27302
|
-
attempted:
|
|
27747
|
+
attempted: false,
|
|
27303
27748
|
success: false,
|
|
27304
|
-
errorMessage:
|
|
27749
|
+
errorMessage: `lock acquisition failed: ${msg}`
|
|
27305
27750
|
}
|
|
27306
27751
|
};
|
|
27307
27752
|
}
|
|
27308
|
-
|
|
27309
|
-
refreshToken = refreshedRefresh;
|
|
27310
|
-
expiration = refreshedExp;
|
|
27753
|
+
let lockedFailure;
|
|
27311
27754
|
try {
|
|
27312
|
-
await
|
|
27313
|
-
|
|
27314
|
-
|
|
27315
|
-
|
|
27316
|
-
|
|
27317
|
-
|
|
27318
|
-
|
|
27755
|
+
const outcome = await runRefreshLocked({
|
|
27756
|
+
absolutePath,
|
|
27757
|
+
refreshToken,
|
|
27758
|
+
customAuthority: credentials.UIPATH_URL,
|
|
27759
|
+
ensureTokenValidityMinutes,
|
|
27760
|
+
loadEnvFile,
|
|
27761
|
+
saveEnvFile,
|
|
27762
|
+
refreshFn: refreshTokenFn,
|
|
27763
|
+
resolveConfig
|
|
27319
27764
|
});
|
|
27320
|
-
|
|
27321
|
-
|
|
27322
|
-
|
|
27323
|
-
|
|
27324
|
-
|
|
27325
|
-
|
|
27326
|
-
|
|
27327
|
-
|
|
27328
|
-
|
|
27329
|
-
|
|
27330
|
-
|
|
27331
|
-
|
|
27765
|
+
if (outcome.kind === "fail") {
|
|
27766
|
+
lockedFailure = outcome.status;
|
|
27767
|
+
} else {
|
|
27768
|
+
accessToken = outcome.accessToken;
|
|
27769
|
+
refreshToken = outcome.refreshToken;
|
|
27770
|
+
expiration = outcome.expiration;
|
|
27771
|
+
tokenRefresh = outcome.tokenRefresh;
|
|
27772
|
+
if (outcome.persistenceWarning) {
|
|
27773
|
+
persistenceWarning = outcome.persistenceWarning;
|
|
27774
|
+
}
|
|
27775
|
+
}
|
|
27776
|
+
} finally {
|
|
27777
|
+
try {
|
|
27778
|
+
await release();
|
|
27779
|
+
} catch {
|
|
27780
|
+
lockReleaseFailed = true;
|
|
27781
|
+
}
|
|
27782
|
+
}
|
|
27783
|
+
if (lockedFailure) {
|
|
27784
|
+
const globalHint = await tryGlobalCredsHint();
|
|
27785
|
+
const base = globalHint ? {
|
|
27786
|
+
...lockedFailure,
|
|
27787
|
+
loginStatus: "Expired",
|
|
27788
|
+
hint: globalHint
|
|
27789
|
+
} : lockedFailure;
|
|
27790
|
+
return lockReleaseFailed ? { ...base, lockReleaseFailed: true } : base;
|
|
27332
27791
|
}
|
|
27333
27792
|
}
|
|
27334
27793
|
const result = {
|
|
@@ -27343,23 +27802,13 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
|
|
|
27343
27802
|
expiration,
|
|
27344
27803
|
source: "file",
|
|
27345
27804
|
...persistenceWarning ? { hint: persistenceWarning, persistenceFailed: true } : {},
|
|
27805
|
+
...lockReleaseFailed ? { lockReleaseFailed: true } : {},
|
|
27346
27806
|
...tokenRefresh ? { tokenRefresh } : {}
|
|
27347
27807
|
};
|
|
27348
27808
|
if (result.loginStatus === "Expired") {
|
|
27349
|
-
const
|
|
27350
|
-
|
|
27351
|
-
|
|
27352
|
-
try {
|
|
27353
|
-
const globalCreds = await loadEnvFile({
|
|
27354
|
-
envPath: globalPath
|
|
27355
|
-
});
|
|
27356
|
-
if (globalCreds.UIPATH_ACCESS_TOKEN) {
|
|
27357
|
-
const globalExp = getTokenExpiration(globalCreds.UIPATH_ACCESS_TOKEN);
|
|
27358
|
-
if (!globalExp || globalExp > new Date) {
|
|
27359
|
-
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.`;
|
|
27360
|
-
}
|
|
27361
|
-
}
|
|
27362
|
-
} catch {}
|
|
27809
|
+
const globalHint = await tryGlobalCredsHint();
|
|
27810
|
+
if (globalHint) {
|
|
27811
|
+
result.hint = globalHint;
|
|
27363
27812
|
}
|
|
27364
27813
|
}
|
|
27365
27814
|
return result;
|
|
@@ -27374,6 +27823,7 @@ var getLoginStatusAsync = async (options = {}) => {
|
|
|
27374
27823
|
};
|
|
27375
27824
|
init_src();
|
|
27376
27825
|
init_src();
|
|
27826
|
+
init_server();
|
|
27377
27827
|
var SERVICE_PATH = {
|
|
27378
27828
|
"llm-gateway": "llmgateway_"
|
|
27379
27829
|
};
|
package/package.json
CHANGED
|
@@ -1,33 +1,27 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"@uipath/llmgw-sdk": "1.1.0",
|
|
28
|
-
"@uipath/common": "1.1.0",
|
|
29
|
-
"commander": "^14.0.3",
|
|
30
|
-
"typescript": "^6.0.2"
|
|
31
|
-
},
|
|
32
|
-
"gitHead": "06e8c8f566df4b87da4a008635483c62f64f33f0"
|
|
2
|
+
"name": "@uipath/llmgw-tool",
|
|
3
|
+
"license": "MIT",
|
|
4
|
+
"version": "1.2.0",
|
|
5
|
+
"description": "CLI plugin for UiPath AI Trust Layer Bring-Your-Own LLM connections.",
|
|
6
|
+
"private": false,
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/UiPath/cli.git",
|
|
10
|
+
"directory": "packages/admin/llmgw-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
|
+
"files": [
|
|
24
|
+
"dist"
|
|
25
|
+
],
|
|
26
|
+
"gitHead": "65fabb84552758b2710d8ca68470e70a9b1d19bc"
|
|
33
27
|
}
|