@uipath/function-tool 1.203.0-preview.205 → 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.
package/dist/tool.js CHANGED
@@ -1,13 +1,20 @@
1
1
  import {
2
+ CommandDimensions,
2
3
  Option,
3
4
  OutputFormatter,
4
5
  RESULTS,
6
+ ScreenLogger,
7
+ ShipDimensions,
8
+ UIPATH_HOME_DIR,
9
+ catchError,
5
10
  createHiddenDeprecatedTenantOption,
11
+ getOutputFormat,
12
+ getOutputFormatExplicit,
6
13
  logger,
7
14
  processContext,
8
15
  stripHostGlobalOptions,
9
16
  trackShipSucceeded
10
- } from "./packager-tool-9331shqx.js";
17
+ } from "./packager-tool-5s8z8be9.js";
11
18
  import {
12
19
  getFileSystem
13
20
  } from "./packager-tool-g0hcxnae.js";
@@ -19,7 +26,7 @@ var package_default = {
19
26
  name: "@uipath/function-tool",
20
27
  author: "UiPath",
21
28
  license: "SEE LICENSE IN LICENSE.txt",
22
- version: "1.203.0-preview.205",
29
+ version: "1.204.0-preview.206",
23
30
  description: "UiPath CLI tool for JS/TS and Python Functions — thin passthrough to uipath-functions / uipath",
24
31
  keywords: [
25
32
  "uipcli-tool",
@@ -65,6 +72,7 @@ var package_default = {
65
72
  "@uipath/packager-tool-functions": "workspace:*",
66
73
  "@uipath/solution-sdk": "workspace:*",
67
74
  "@uipath/solutionpackager-tool-core": "workspace:*",
75
+ "@uipath/uipath-python-bridge": "workspace:*",
68
76
  commander: "^14.0.3",
69
77
  "@types/bun": "^1.3.11"
70
78
  },
@@ -77,11 +85,37 @@ var package_default = {
77
85
  import { execSync } from "node:child_process";
78
86
  var fs = getFileSystem();
79
87
  function getCacheFilePath() {
80
- return fs.path.join(fs.env.homedir(), ".uipcli", ".function-tool-cache.json");
88
+ return fs.path.join(fs.env.homedir(), UIPATH_HOME_DIR, "functions-runtime-cache.json");
81
89
  }
82
90
  function registerSetupCommand(program) {
83
- program.command("setup", { hidden: true }).description("Verify Node.js ≥20 is available (JS/TS projects only).").option("--force", "Force re-verification even if already cached", false).trackedAction(processContext, async (opts) => {
84
- await ensureSetup({ force: opts.force, log: true });
91
+ program.command("setup").description("Verify the toolchains Functions needs: Node.js for JS/TS, Python and the 'uipath' package for Python.").option("--force", "Force re-verification even if already cached", false).trackedAction(processContext, async (opts) => {
92
+ if (!await ensureSetup({ force: opts.force, log: true })) {
93
+ return;
94
+ }
95
+ await reportPythonSetup(opts.force);
96
+ OutputFormatter.log({ Message: "Setup complete." });
97
+ });
98
+ }
99
+ async function reportPythonSetup(force) {
100
+ const { getAllowedPythonVersions, getPackageName, PythonService } = await import("./index-pv66qwr4.js");
101
+ const packageName = getPackageName();
102
+ const service = new PythonService({
103
+ allowedVersions: getAllowedPythonVersions(),
104
+ packageName,
105
+ toolName: "function"
106
+ });
107
+ const result = await service.setup(packageName, force);
108
+ if (result.success) {
109
+ OutputFormatter.log({
110
+ Message: `Python ${result.pythonVersion} with ${packageName} ${result.packageVersion} ✓`
111
+ });
112
+ return;
113
+ }
114
+ OutputFormatter.log({
115
+ Message: `Python: not configured. ${result.error ?? "Detection failed."}`
116
+ });
117
+ OutputFormatter.log({
118
+ Message: result.instructions ?? `Install a supported Python version and '${packageName}', then run 'uip function setup --force'. Python Functions commands fail until then; JS/TS is unaffected.`
85
119
  });
86
120
  }
87
121
  async function ensureSetup(opts = {}) {
@@ -116,7 +150,6 @@ async function ensureSetup(opts = {}) {
116
150
  await writeCache(cache);
117
151
  if (opts.log) {
118
152
  OutputFormatter.log({ Message: `Node.js ${nodeVersion} ✓` });
119
- OutputFormatter.log({ Message: "Setup complete." });
120
153
  }
121
154
  return true;
122
155
  }
@@ -182,10 +215,9 @@ function namesRunTarget(arg) {
182
215
  }
183
216
 
184
217
  // src/services/utils.ts
185
- import { spawn } from "node:child_process";
186
218
  async function loadGlobalAuthEnv() {
187
219
  try {
188
- const { loadEnvFileAsync, resolveEnvFilePathAsync } = await import("./index-t0pqjb4h.js");
220
+ const { loadEnvFileAsync, resolveEnvFilePathAsync } = await import("./index-hkrczw69.js");
189
221
  const { absolutePath } = await resolveEnvFilePathAsync();
190
222
  if (!absolutePath) {
191
223
  return {};
@@ -195,37 +227,6 @@ async function loadGlobalAuthEnv() {
195
227
  return {};
196
228
  }
197
229
  }
198
- async function spawnAndRelay(binary, args, cwd, extraEnv = {}) {
199
- return new Promise((resolve) => {
200
- const proc = spawn(binary, args, {
201
- cwd,
202
- env: {
203
- ...process.env,
204
- ...extraEnv
205
- },
206
- stdio: "inherit"
207
- });
208
- proc.on("error", (err) => {
209
- if (err.code === "ENOENT") {
210
- OutputFormatter.error({
211
- Result: RESULTS.Failure,
212
- Message: `'${binary}' not found.`,
213
- Instructions: "Install the Python CLI with 'pip install uipath' (or 'pipx install uipath')."
214
- });
215
- } else {
216
- OutputFormatter.error({
217
- Result: RESULTS.Failure,
218
- Message: err.message,
219
- Instructions: "Run 'uip function setup' to verify your environment."
220
- });
221
- }
222
- resolve(1);
223
- });
224
- proc.on("exit", (code) => {
225
- resolve(code ?? 0);
226
- });
227
- });
228
- }
229
230
 
230
231
  // src/services/js-cli-runner.ts
231
232
  var fs2 = getFileSystem();
@@ -367,30 +368,129 @@ function flagsToDrop(verb) {
367
368
  }
368
369
 
369
370
  // src/services/python-cli-runner.ts
371
+ async function runPythonCli(args, cwd, options = {}) {
372
+ const { runUipathPythonCommand } = await import("./index-pv66qwr4.js");
373
+ return runUipathPythonCommand(buildPythonArgs(args), {
374
+ cwd,
375
+ toolName: "function",
376
+ pinNewType: "function",
377
+ stdio: options.stdio ?? "inherit"
378
+ });
379
+ }
380
+ async function spawnPythonCli(args, cwd, options = {}) {
381
+ const { reportUipathPythonFailure } = await import("./index-pv66qwr4.js");
382
+ return reportUipathPythonFailure(await runPythonCli(args, cwd, options));
383
+ }
384
+
385
+ // src/services/run-envelope.ts
370
386
  var fs4 = getFileSystem();
371
- async function spawnPythonCli(args, cwd) {
372
- const uipathExe = await resolveUipathPythonExe() ?? "uipath";
373
- const { getAuthEnv } = await import("./index-t0pqjb4h.js");
374
- const { authEnv, loginStatus } = await getAuthEnv();
375
- if (!loginStatus) {
376
- logger.debug("Auth unavailable, continuing without credentials.");
377
- }
378
- return spawnAndRelay(uipathExe, buildPythonArgs(args), cwd, authEnv);
379
- }
380
- async function resolveUipathPythonExe() {
381
- const pythonCacheFile = fs4.path.join(fs4.env.homedir(), ".uipcli", ".codedagents-tool-cache.json");
382
- if (await fs4.exists(pythonCacheFile)) {
383
- try {
384
- const content = await fs4.readFile(pythonCacheFile, "utf-8");
385
- if (content) {
386
- const cache = JSON.parse(content);
387
- if (cache.uipathExePath && await fs4.exists(cache.uipathExePath)) {
388
- return cache.uipathExePath;
389
- }
390
- }
391
- } catch {}
387
+ var ENVELOPE_FORMATS = new Set([
388
+ "json",
389
+ "yaml"
390
+ ]);
391
+ var OUTPUT_FILE_FLAG = "--output-file";
392
+ function wantsRunEnvelope(verb) {
393
+ return verb === "run" && getOutputFormatExplicit() && ENVELOPE_FORMATS.has(getOutputFormat());
394
+ }
395
+ async function runPythonWithEnvelope(args, cwd) {
396
+ const requestedFile = findOutputFile(args);
397
+ if (requestedFile !== undefined) {
398
+ return await runAndEmit(args, cwd, requestedFile);
399
+ }
400
+ const tempDir = await fs4.getTempDir();
401
+ const outputFile = fs4.path.join(tempDir, "output.json");
402
+ const exitCode = await runAndEmit([...args, OUTPUT_FILE_FLAG, outputFile], cwd, outputFile);
403
+ await catchError(fs4.rm(tempDir));
404
+ return exitCode;
405
+ }
406
+ async function runAndEmit(runArgs, cwd, outputFile) {
407
+ const [runError, result] = await catchError(runPythonCli(runArgs, cwd, { stdio: "stdout-to-stderr" }));
408
+ if (runError) {
409
+ OutputFormatter.error({
410
+ Result: RESULTS.Failure,
411
+ ErrorCode: "unknown_error",
412
+ Message: `Could not run the Python CLI: ${runError.message}`,
413
+ Instructions: "Run 'uip function setup' to check the environment, then re-run.",
414
+ Retry: "RetryWillNotFix"
415
+ });
416
+ return 1;
392
417
  }
393
- return null;
418
+ if (!result.ok) {
419
+ return await reportRunFailure(result);
420
+ }
421
+ return await emitRunOutput(outputFile);
422
+ }
423
+ async function reportRunFailure(result) {
424
+ if (result.reason !== "command_failed") {
425
+ const { reportUipathPythonFailure } = await import("./index-pv66qwr4.js");
426
+ return reportUipathPythonFailure(result);
427
+ }
428
+ OutputFormatter.error({
429
+ Result: RESULTS.Failure,
430
+ ErrorCode: "unknown_error",
431
+ Message: `The run exited with code ${result.exitCode}.`,
432
+ Instructions: "Read the error the run printed on stderr, fix what it names, then re-run 'uip function run'.",
433
+ Retry: "RetryWillNotFix"
434
+ });
435
+ return result.exitCode;
436
+ }
437
+ async function emitRunOutput(outputFile) {
438
+ if (!await fs4.exists(outputFile)) {
439
+ OutputFormatter.error({
440
+ Result: RESULTS.ConfigError,
441
+ ErrorCode: "configuration_error",
442
+ Message: `The run succeeded but wrote no output file at '${outputFile}'.`,
443
+ Instructions: "Update the Python CLI with 'pip install -U uipath' (or 'uv add -U uipath'), then re-run. Structured output needs a 'uipath' that supports '--output-file'.",
444
+ Retry: "RetryWillNotFix"
445
+ });
446
+ return 1;
447
+ }
448
+ const [readError, raw] = await catchError(fs4.readFile(outputFile, "utf-8"));
449
+ if (readError) {
450
+ OutputFormatter.error({
451
+ Result: RESULTS.Failure,
452
+ ErrorCode: "unknown_error",
453
+ Message: `Could not read the run's output file '${outputFile}': ${readError.message}`,
454
+ Instructions: "Check the path is readable, then re-run 'uip function run'.",
455
+ Retry: "RetryWillNotFix"
456
+ });
457
+ return 1;
458
+ }
459
+ const [parseError, parsed] = catchError(() => JSON.parse(String(raw)));
460
+ if (parseError) {
461
+ OutputFormatter.error({
462
+ Result: RESULTS.Failure,
463
+ ErrorCode: "unknown_error",
464
+ Message: `The run's output file '${outputFile}' is not valid JSON: ${parseError.message}`,
465
+ Instructions: "Re-run 'uip function run' without '--output' to see the run's own output, and check the function returns a serialisable result.",
466
+ Retry: "RetryWillNotFix"
467
+ });
468
+ return 1;
469
+ }
470
+ OutputFormatter.success({
471
+ Result: RESULTS.Success,
472
+ Code: "RunComplete",
473
+ Data: asData(parsed)
474
+ }, { preserveDataKeys: true });
475
+ return 0;
476
+ }
477
+ function asData(parsed) {
478
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
479
+ return parsed;
480
+ }
481
+ return { Output: parsed };
482
+ }
483
+ function findOutputFile(args) {
484
+ for (let i = 0;i < args.length; i++) {
485
+ const arg = args[i] ?? "";
486
+ if (arg === OUTPUT_FILE_FLAG) {
487
+ return args[i + 1] ?? "";
488
+ }
489
+ if (arg.startsWith(`${OUTPUT_FILE_FLAG}=`)) {
490
+ return arg.slice(OUTPUT_FILE_FLAG.length + 1);
491
+ }
492
+ }
493
+ return;
394
494
  }
395
495
 
396
496
  // src/services/dispatcher.ts
@@ -422,10 +522,10 @@ function trackShip(rawArgs) {
422
522
  return;
423
523
  }
424
524
  trackShipSucceeded({
425
- ship_kind: ship.kind,
426
- target: ship.target,
427
- project_type: "coded_function",
428
- command_name: `uip.function.${verb}`
525
+ [ShipDimensions.ShipKind]: ship.kind,
526
+ [ShipDimensions.Target]: ship.target,
527
+ [ShipDimensions.ProjectType]: "coded_function",
528
+ [CommandDimensions.CommandName]: `uip function ${verb}`
429
529
  });
430
530
  }
431
531
  async function dispatch(rawArgs) {
@@ -465,13 +565,17 @@ async function dispatch(rawArgs) {
465
565
  return;
466
566
  }
467
567
  }
568
+ const runEnvelope = wantsRunEnvelope(verb);
468
569
  switch (language) {
469
570
  case "python": {
470
- const exitCode = await spawnPythonCli(args, cwd);
571
+ const exitCode = runEnvelope ? await runPythonWithEnvelope(args, cwd) : await spawnPythonCli(args, cwd);
471
572
  processContext.exit(exitCode);
472
573
  return;
473
574
  }
474
575
  case "javascript":
576
+ if (runEnvelope) {
577
+ ScreenLogger.progress("--output is not supported by 'run' on JS/TS projects yet; " + "the function's own output follows unchanged.");
578
+ }
475
579
  return runJsCli(args, cwd);
476
580
  case "unknown":
477
581
  if (verb === "new") {
@@ -488,7 +592,7 @@ async function dispatch(rawArgs) {
488
592
  }
489
593
  }
490
594
  async function reportSolutionRegistration(projectDir, skipSolutionRegistration) {
491
- const { tryRegisterProjectInParentSolution } = await import("./index-n64hfz0c.js");
595
+ const { tryRegisterProjectInParentSolution } = await import("./index-z9tda729.js");
492
596
  const registration = await tryRegisterProjectInParentSolution(fs5, projectDir, {
493
597
  skipRegistration: skipSolutionRegistration
494
598
  });
@@ -598,16 +702,16 @@ function registerPushCommand(program) {
598
702
  // src/commands/run.ts
599
703
  var FUNCTIONS_RUN_EXAMPLES = [
600
704
  {
601
- Description: "Run the 'hello' function once with a JSON payload",
602
- Command: `uip function run hello --input '{"name":"Ada"}'`,
705
+ Description: "Python project: run the 'hello' function once with a JSON payload and read the result as JSON",
706
+ Command: `uip function run hello --input '{"name":"Ada"}' --output json`,
603
707
  Output: {
604
708
  Code: "RunComplete",
605
709
  Data: { message: "Hello, Ada!" }
606
710
  }
607
711
  },
608
712
  {
609
- Description: "Run a function with a payload kept in a file",
610
- Command: "uip function run hello --input-file ./payload.json",
713
+ Description: "Python project: run a function with a payload kept in a file",
714
+ Command: "uip function run hello --input-file ./payload.json --output json",
611
715
  Output: {
612
716
  Code: "RunComplete",
613
717
  Data: { message: "Hello, Ada!" }
@@ -671,4 +775,4 @@ export {
671
775
  registerCommands
672
776
  };
673
777
 
674
- //# debugId=A81EE4F8C8CE166164756E2164756E21
778
+ //# debugId=24E7057E7B23B84D64756E2164756E21
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@uipath/function-tool",
3
3
  "author": "UiPath",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
- "version": "1.203.0-preview.205",
5
+ "version": "1.204.0-preview.206",
6
6
  "description": "UiPath CLI tool for JS/TS and Python Functions — thin passthrough to uipath-functions / uipath",
7
7
  "keywords": [
8
8
  "uipcli-tool",
@@ -35,5 +35,5 @@
35
35
  "dependencies": {
36
36
  "typescript": "^5.7.0"
37
37
  },
38
- "gitHead": "d8d19829030cc590c630bebfc60a9d9fc7fa8c31"
38
+ "gitHead": "ea7fd32a02acccf14e8e83522e69101430627b83"
39
39
  }