@uipath/packager-tool-workflowcompiler 1.199.0 → 1.201.0-preview.115

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.
@@ -28,7 +28,7 @@ export declare const en: {
28
28
  readonly checkingNuGetCache: "[PathResolver] Checking NuGet cache: {path}";
29
29
  readonly foundInNuGetCache: "[PathResolver] Found compiler in NuGet cache";
30
30
  readonly notFoundStartingInstall: "[PathResolver] Compiler not found, starting dotnet restore...";
31
- readonly restoringPackage: "[PathResolver] Restoring NuGet package \"{packageName}\" v{version} for platform \"{platform}\" via dotnet restore...";
31
+ readonly restoringPackage: '[PathResolver] Restoring NuGet package "{packageName}" v{version} for platform "{platform}" via dotnet restore...';
32
32
  readonly runningDotnetRestore: "[PathResolver] Running dotnet restore...";
33
33
  readonly restoreCompleted: "[PathResolver] dotnet restore completed";
34
34
  readonly installCompleted: "[PathResolver] Compiler restored successfully";
package/dist/index.js CHANGED
@@ -789,7 +789,7 @@ function addSdkUserAgentHeader(headers, userAgent) {
789
789
  }
790
790
  var package_default = {
791
791
  name: "@uipath/packager-orchestrator-client",
792
- version: "1.199.0",
792
+ version: "1.201.0",
793
793
  description: "UiPath packager client for Orchestrator package-feed interaction (feed discovery + NuGet source composition)",
794
794
  type: "module",
795
795
  private: true,
@@ -828,7 +828,7 @@ var package_default = {
828
828
  "@uipath/common": "workspace:*",
829
829
  "@uipath/solutionpackager-tool-core": "workspace:*",
830
830
  "@vitest/coverage-v8": "^4.1.6",
831
- typescript: "^6.0.2",
831
+ typescript: "^7.0.2",
832
832
  vitest: "^4.1.6"
833
833
  }
834
834
  };
@@ -992,7 +992,7 @@ import {
992
992
  TemporaryStorageService as TemporaryStorageService2,
993
993
  translate as translate3
994
994
  } from "@uipath/solutionpackager-tool-core";
995
- var NUGET_FEED_URL = "https://uipath.pkgs.visualstudio.com/Public.Feeds/_packaging/UiPath-Internal/nuget/v3/index.json";
995
+ var NUGET_FEED_URL = "https://pkgs.uipath.com/internal/index.json";
996
996
  var WORKFLOW_COMPILER_DLL_NAME = "UiPath.WorkflowCompiler.dll";
997
997
  var PLATFORM_PACKAGE_IDS = {
998
998
  win32: "UiPath.WorkflowCompiler.Windows",
@@ -1157,6 +1157,7 @@ class WorkflowCompilerExecutor {
1157
1157
  return new Promise((resolve) => {
1158
1158
  let result = null;
1159
1159
  const fallbackErrors = [];
1160
+ const analyzerFindings = [];
1160
1161
  const childProcess = this.spawnProcess(executable, commandArgs, workflowCompilerConfig.dotnetEnv);
1161
1162
  let stdoutEnded = false;
1162
1163
  let stderrEnded = false;
@@ -1172,7 +1173,7 @@ class WorkflowCompilerExecutor {
1172
1173
  errorCode: result.errorCode
1173
1174
  }));
1174
1175
  const toolResult = new ToolResult(result.errorCode, result.message, result.outputPackages);
1175
- toolResult.details = getAdditionalResultDetails(result);
1176
+ toolResult.details = withAnalyzerFindings(getAdditionalResultDetails(result), analyzerFindings);
1176
1177
  resolve(toolResult);
1177
1178
  } else {
1178
1179
  const exitCode = childProcess.exitCode ?? -1;
@@ -1202,8 +1203,8 @@ class WorkflowCompilerExecutor {
1202
1203
  checkComplete();
1203
1204
  }
1204
1205
  };
1205
- this.setupStdoutHandling(childProcess, streamCompletion, (r) => result = r);
1206
- this.setupStderrHandling(childProcess, streamCompletion, fallbackErrors);
1206
+ this.setupStdoutHandling(childProcess, streamCompletion, (r) => result = r, analyzerFindings);
1207
+ this.setupStderrHandling(childProcess, streamCompletion, fallbackErrors, analyzerFindings);
1207
1208
  this.setupProcessEventHandlers(childProcess, streamCompletion, resolve);
1208
1209
  this.setupCancellationHandler(childProcess, cancellationToken, resolve);
1209
1210
  });
@@ -1225,7 +1226,7 @@ class WorkflowCompilerExecutor {
1225
1226
  command: fullCommand.join(" ")
1226
1227
  }));
1227
1228
  }
1228
- setupStdoutHandling(childProcess, streamCompletion, onResult) {
1229
+ setupStdoutHandling(childProcess, streamCompletion, onResult, analyzerFindings) {
1229
1230
  if (!childProcess.stdout) {
1230
1231
  streamCompletion.markStdoutEnded();
1231
1232
  return;
@@ -1239,24 +1240,29 @@ class WorkflowCompilerExecutor {
1239
1240
  for (const line of lines) {
1240
1241
  if (!line.trim())
1241
1242
  continue;
1242
- this.processOutputLine(line, onResult);
1243
+ this.processOutputLine(line, onResult, analyzerFindings);
1243
1244
  }
1244
1245
  });
1245
1246
  childProcess.stdout.on("end", () => {
1246
1247
  if (buffer.trim()) {
1247
- this.processOutputLine(buffer, onResult);
1248
+ this.processOutputLine(buffer, onResult, analyzerFindings);
1248
1249
  }
1249
1250
  streamCompletion.markStdoutEnded();
1250
1251
  });
1251
1252
  }
1252
- processOutputLine(line, onResult) {
1253
+ processOutputLine(line, onResult, analyzerFindings) {
1253
1254
  const entry = this.parseOutputEntry(line);
1254
1255
  if (!entry)
1255
1256
  return;
1256
1257
  if (entry.type === "Result") {
1257
1258
  onResult(entry);
1258
1259
  } else if (entry.type === "Log") {
1259
- this.logMessage(entry);
1260
+ const log = entry;
1261
+ const finding = toAnalyzerFinding(log);
1262
+ if (finding) {
1263
+ analyzerFindings.push(finding);
1264
+ }
1265
+ this.logMessage(log);
1260
1266
  } else if (entry.type === "Progress") {
1261
1267
  this.logProgress(entry);
1262
1268
  }
@@ -1279,7 +1285,7 @@ class WorkflowCompilerExecutor {
1279
1285
  const separator = percent && progress.message ? " - " : "";
1280
1286
  this.logger.progress(`${percent}${separator}${progress.message ?? ""}`);
1281
1287
  }
1282
- setupStderrHandling(childProcess, streamCompletion, fallbackErrors) {
1288
+ setupStderrHandling(childProcess, streamCompletion, fallbackErrors, analyzerFindings) {
1283
1289
  if (!childProcess.stderr) {
1284
1290
  streamCompletion.markStderrEnded();
1285
1291
  return;
@@ -1293,20 +1299,25 @@ class WorkflowCompilerExecutor {
1293
1299
  for (const line of lines) {
1294
1300
  if (!line.trim())
1295
1301
  continue;
1296
- this.processErrorLine(line, fallbackErrors);
1302
+ this.processErrorLine(line, fallbackErrors, analyzerFindings);
1297
1303
  }
1298
1304
  });
1299
1305
  childProcess.stderr.on("end", () => {
1300
1306
  if (buffer.trim()) {
1301
- this.processErrorLine(buffer, fallbackErrors);
1307
+ this.processErrorLine(buffer, fallbackErrors, analyzerFindings);
1302
1308
  }
1303
1309
  streamCompletion.markStderrEnded();
1304
1310
  });
1305
1311
  }
1306
- processErrorLine(line, fallbackErrors) {
1312
+ processErrorLine(line, fallbackErrors, analyzerFindings) {
1307
1313
  const entry = this.parseOutputEntry(line);
1308
1314
  if (entry && entry.type === "Log") {
1309
- this.logger.error(entry.message);
1315
+ const log = entry;
1316
+ const finding = toAnalyzerFinding(log);
1317
+ if (finding) {
1318
+ analyzerFindings.push(finding);
1319
+ }
1320
+ this.logger.error(log.message);
1310
1321
  } else {
1311
1322
  fallbackErrors.push(line);
1312
1323
  this.logger.error(line);
@@ -1370,8 +1381,68 @@ function getAdditionalResultDetails(result) {
1370
1381
  }
1371
1382
  return Object.keys(details).length > 0 ? details : undefined;
1372
1383
  }
1384
+ var ANALYZER_LOG_SOURCE = "Analyzer";
1385
+ function withAnalyzerFindings(details, findings) {
1386
+ const fromEnvelope = details?.findings;
1387
+ if (findings.length === 0 || Array.isArray(fromEnvelope) && fromEnvelope.length > 0) {
1388
+ return details;
1389
+ }
1390
+ return { ...details, findings };
1391
+ }
1392
+ function toAnalyzerFinding(log) {
1393
+ if (log.source !== ANALYZER_LOG_SOURCE) {
1394
+ return;
1395
+ }
1396
+ const message = parseAnalyzerMessage(log.data) ?? {};
1397
+ const activityId = message.ActivityId;
1398
+ const item = message.Item;
1399
+ return {
1400
+ ...message,
1401
+ ErrorCode: message.ErrorCode ?? log.code,
1402
+ Description: message.Description ?? log.message,
1403
+ FilePath: message.FilePath ?? log.filePath,
1404
+ ErrorSeverity: message.ErrorSeverity ?? toErrorSeverity(log.logLevel),
1405
+ ActivityIdRef: activityId?.IdRef ?? log.id,
1406
+ AnalyzerItemName: item?.Name,
1407
+ AnalyzerItemType: item?.Type
1408
+ };
1409
+ }
1410
+ function toErrorSeverity(logLevel) {
1411
+ switch (logLevel) {
1412
+ case "Debug":
1413
+ case "Trace":
1414
+ return "Verbose";
1415
+ case "Information":
1416
+ return "Info";
1417
+ default:
1418
+ return logLevel;
1419
+ }
1420
+ }
1421
+ function parseAnalyzerMessage(data) {
1422
+ if (!data) {
1423
+ return;
1424
+ }
1425
+ try {
1426
+ const parsed = JSON.parse(data);
1427
+ return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : undefined;
1428
+ } catch {
1429
+ return;
1430
+ }
1431
+ }
1373
1432
 
1374
1433
  // src/workflow-compiler-tool.ts
1434
+ var NO_CLEANUP_SOURCE_FILES_MESSAGE = "no workflow xamls or coded source files";
1435
+ var CLEANUP_SOURCE_FILE_EXTENSIONS = [".xaml", ".cs", ".vb"];
1436
+ var CLEANUP_SOURCE_SCAN_SKIP_DIRS = new Set([
1437
+ ".git",
1438
+ ".local",
1439
+ ".project",
1440
+ "bin",
1441
+ "dist",
1442
+ "node_modules",
1443
+ "obj"
1444
+ ]);
1445
+
1375
1446
  class WorkflowCompilerTool extends ProjectTool {
1376
1447
  context;
1377
1448
  executor;
@@ -1575,9 +1646,52 @@ class WorkflowCompilerTool extends ProjectTool {
1575
1646
  args.push(`--nuget-config`, paths.userNugetConfigPath);
1576
1647
  }
1577
1648
  const result = await this.executor.executeAsync("remove-unused-dependencies", args, cancellationToken);
1649
+ if (await this.shouldRetryCleanupNoSourceFalseNegativeAsync(result, options.projectPath)) {
1650
+ this.logger.warn("[WorkflowCompiler] remove-unused-dependencies reported no workflow/source files even though the project contains source files; retrying once.");
1651
+ const retryResult = await this.executor.executeAsync("remove-unused-dependencies", args, cancellationToken);
1652
+ return this.toProjectCleanupResult(retryResult);
1653
+ }
1578
1654
  return this.toProjectCleanupResult(result);
1579
1655
  });
1580
1656
  }
1657
+ async shouldRetryCleanupNoSourceFalseNegativeAsync(result, projectPath) {
1658
+ if (result.isSuccess) {
1659
+ return false;
1660
+ }
1661
+ const message = result.message?.toLowerCase();
1662
+ if (!message?.includes(NO_CLEANUP_SOURCE_FILES_MESSAGE)) {
1663
+ return false;
1664
+ }
1665
+ return await this.hasCleanupSourceFilesAsync(projectPath);
1666
+ }
1667
+ async hasCleanupSourceFilesAsync(projectPath) {
1668
+ let entries;
1669
+ try {
1670
+ entries = await this.fileSystem.readdir(projectPath);
1671
+ } catch {
1672
+ return false;
1673
+ }
1674
+ for (const entry of entries) {
1675
+ const lowerEntry = entry.toLowerCase();
1676
+ const fullPath = this.fileSystem.path.join(projectPath, entry);
1677
+ let stats;
1678
+ try {
1679
+ stats = await this.fileSystem.stat(fullPath);
1680
+ } catch {
1681
+ continue;
1682
+ }
1683
+ if (!stats) {
1684
+ continue;
1685
+ }
1686
+ if (stats.isFile() && CLEANUP_SOURCE_FILE_EXTENSIONS.some((extension) => lowerEntry.endsWith(extension))) {
1687
+ return true;
1688
+ }
1689
+ if (stats.isDirectory() && !CLEANUP_SOURCE_SCAN_SKIP_DIRS.has(lowerEntry) && await this.hasCleanupSourceFilesAsync(fullPath)) {
1690
+ return true;
1691
+ }
1692
+ }
1693
+ return false;
1694
+ }
1581
1695
  toProjectCleanupResult(result) {
1582
1696
  const raw = result.details?.removeUnusedDependencies;
1583
1697
  if (!raw) {
@@ -1666,4 +1780,4 @@ export {
1666
1780
  WorkflowCompilerToolFactory
1667
1781
  };
1668
1782
 
1669
- //# debugId=D679068934126E3664756E2164756E21
1783
+ //# debugId=8617FFB8E317023F64756E2164756E21
@@ -15,12 +15,18 @@ export interface IOutputMessage {
15
15
  inputId?: string;
16
16
  }
17
17
  /**
18
- * Log message from workflow compiler output
18
+ * Log message from workflow compiler output. Analyzer findings are reported only here.
19
19
  */
20
20
  export interface IOutputLog extends IOutputMessage {
21
21
  type: OutputMessageType.Log;
22
22
  message: string;
23
- logLevel: "Information" | "Warning" | "Error";
23
+ logLevel: "Trace" | "Debug" | "Information" | "Warning" | "Error" | "None";
24
+ source?: string;
25
+ code?: string;
26
+ filePath?: string;
27
+ id?: string;
28
+ /** Serialized `AnalyzerMessage`. */
29
+ data?: string;
24
30
  }
25
31
  /**
26
32
  * Progress update from workflow compiler output
@@ -13,6 +13,8 @@ export declare class WorkflowCompilerTool extends ProjectTool {
13
13
  buildAsync(options: IProjectBuildOptions, cancellationToken?: AbortSignal): Promise<ToolResult>;
14
14
  packAsync(options: IProjectPackOptions, cancellationToken?: AbortSignal): Promise<ToolResult>;
15
15
  cleanupAsync(options: IProjectCleanupOptions, cancellationToken?: AbortSignal): Promise<ToolResult>;
16
+ private shouldRetryCleanupNoSourceFalseNegativeAsync;
17
+ private hasCleanupSourceFilesAsync;
16
18
  /**
17
19
  * Convert the WorkflowCompiler's raw `remove-unused-dependencies` payload
18
20
  * into the generic {@link ProjectCleanupInfo} the cleanup pipeline expects,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/packager-tool-workflowcompiler",
3
- "version": "1.199.0",
3
+ "version": "1.201.0-preview.115",
4
4
  "description": "UiPath Workflow Compiler tool implementation",
5
5
  "type": "module",
6
6
  "exports": {
@@ -25,8 +25,8 @@
25
25
  "author": "",
26
26
  "license": "ISC",
27
27
  "peerDependencies": {
28
- "@uipath/solutionpackager-tool-core": "1.199.0"
28
+ "@uipath/solutionpackager-tool-core": "1.201.0"
29
29
  },
30
30
  "dependencies": {},
31
- "gitHead": "723e6801b77b5926ba75e75b6a756cc38b1b7adc"
31
+ "gitHead": "f1086b73654d7728cb71f280588b3e0c77d535fc"
32
32
  }
@@ -17,12 +17,18 @@ export interface IOutputMessage {
17
17
  }
18
18
 
19
19
  /**
20
- * Log message from workflow compiler output
20
+ * Log message from workflow compiler output. Analyzer findings are reported only here.
21
21
  */
22
22
  export interface IOutputLog extends IOutputMessage {
23
23
  type: OutputMessageType.Log;
24
24
  message: string;
25
- logLevel: "Information" | "Warning" | "Error";
25
+ logLevel: "Trace" | "Debug" | "Information" | "Warning" | "Error" | "None";
26
+ source?: string;
27
+ code?: string;
28
+ filePath?: string;
29
+ id?: string;
30
+ /** Serialized `AnalyzerMessage`. */
31
+ data?: string;
26
32
  }
27
33
 
28
34
  /**
@@ -82,6 +82,7 @@ export class WorkflowCompilerExecutor {
82
82
  return new Promise((resolve) => {
83
83
  let result: IOutputResult | null = null;
84
84
  const fallbackErrors: string[] = [];
85
+ const analyzerFindings: Record<string, unknown>[] = [];
85
86
 
86
87
  const childProcess = this.spawnProcess(
87
88
  executable,
@@ -115,7 +116,10 @@ export class WorkflowCompilerExecutor {
115
116
  result.message,
116
117
  result.outputPackages,
117
118
  );
118
- toolResult.details = getAdditionalResultDetails(result);
119
+ toolResult.details = withAnalyzerFindings(
120
+ getAdditionalResultDetails(result),
121
+ analyzerFindings,
122
+ );
119
123
  resolve(toolResult);
120
124
  } else {
121
125
  const exitCode = childProcess.exitCode ?? -1;
@@ -163,11 +167,13 @@ export class WorkflowCompilerExecutor {
163
167
  childProcess,
164
168
  streamCompletion,
165
169
  (r) => (result = r),
170
+ analyzerFindings,
166
171
  );
167
172
  this.setupStderrHandling(
168
173
  childProcess,
169
174
  streamCompletion,
170
175
  fallbackErrors,
176
+ analyzerFindings,
171
177
  );
172
178
  this.setupProcessEventHandlers(
173
179
  childProcess,
@@ -219,6 +225,7 @@ export class WorkflowCompilerExecutor {
219
225
  childProcess: ChildProcess,
220
226
  streamCompletion: StreamCompletion,
221
227
  onResult: (result: IOutputResult) => void,
228
+ analyzerFindings: Record<string, unknown>[],
222
229
  ): void {
223
230
  if (!childProcess.stdout) {
224
231
  streamCompletion.markStdoutEnded();
@@ -233,13 +240,13 @@ export class WorkflowCompilerExecutor {
233
240
  buffer = lines.pop()!;
234
241
  for (const line of lines) {
235
242
  if (!line.trim()) continue;
236
- this.processOutputLine(line, onResult);
243
+ this.processOutputLine(line, onResult, analyzerFindings);
237
244
  }
238
245
  });
239
246
 
240
247
  childProcess.stdout.on("end", () => {
241
248
  if (buffer.trim()) {
242
- this.processOutputLine(buffer, onResult);
249
+ this.processOutputLine(buffer, onResult, analyzerFindings);
243
250
  }
244
251
  streamCompletion.markStdoutEnded();
245
252
  });
@@ -248,6 +255,7 @@ export class WorkflowCompilerExecutor {
248
255
  private processOutputLine(
249
256
  line: string,
250
257
  onResult: (result: IOutputResult) => void,
258
+ analyzerFindings: Record<string, unknown>[],
251
259
  ): void {
252
260
  const entry = this.parseOutputEntry(line);
253
261
  if (!entry) return;
@@ -255,7 +263,12 @@ export class WorkflowCompilerExecutor {
255
263
  if (entry.type === "Result") {
256
264
  onResult(entry as IOutputResult);
257
265
  } else if (entry.type === "Log") {
258
- this.logMessage(entry as IOutputLog);
266
+ const log = entry as IOutputLog;
267
+ const finding = toAnalyzerFinding(log);
268
+ if (finding) {
269
+ analyzerFindings.push(finding);
270
+ }
271
+ this.logMessage(log);
259
272
  } else if (entry.type === "Progress") {
260
273
  this.logProgress(entry as IOutputProgress);
261
274
  }
@@ -285,6 +298,7 @@ export class WorkflowCompilerExecutor {
285
298
  childProcess: ChildProcess,
286
299
  streamCompletion: StreamCompletion,
287
300
  fallbackErrors: string[],
301
+ analyzerFindings: Record<string, unknown>[],
288
302
  ): void {
289
303
  if (!childProcess.stderr) {
290
304
  streamCompletion.markStderrEnded();
@@ -298,23 +312,32 @@ export class WorkflowCompilerExecutor {
298
312
  buffer = lines.pop()!;
299
313
  for (const line of lines) {
300
314
  if (!line.trim()) continue;
301
- this.processErrorLine(line, fallbackErrors);
315
+ this.processErrorLine(line, fallbackErrors, analyzerFindings);
302
316
  }
303
317
  });
304
318
 
305
319
  childProcess.stderr.on("end", () => {
306
320
  if (buffer.trim()) {
307
- this.processErrorLine(buffer, fallbackErrors);
321
+ this.processErrorLine(buffer, fallbackErrors, analyzerFindings);
308
322
  }
309
323
  streamCompletion.markStderrEnded();
310
324
  });
311
325
  }
312
326
 
313
- private processErrorLine(line: string, fallbackErrors: string[]): void {
327
+ private processErrorLine(
328
+ line: string,
329
+ fallbackErrors: string[],
330
+ analyzerFindings: Record<string, unknown>[],
331
+ ): void {
314
332
  const entry = this.parseOutputEntry(line);
315
333
 
316
334
  if (entry && entry.type === "Log") {
317
- this.logger.error((entry as IOutputLog).message);
335
+ const log = entry as IOutputLog;
336
+ const finding = toAnalyzerFinding(log);
337
+ if (finding) {
338
+ analyzerFindings.push(finding);
339
+ }
340
+ this.logger.error(log.message);
318
341
  } else {
319
342
  fallbackErrors.push(line);
320
343
  this.logger.error(line);
@@ -434,3 +457,74 @@ function getAdditionalResultDetails(
434
457
 
435
458
  return Object.keys(details).length > 0 ? details : undefined;
436
459
  }
460
+
461
+ const ANALYZER_LOG_SOURCE = "Analyzer";
462
+
463
+ /** Only a *populated* envelope array wins — `CommandResult` defaults its lists to `[]`. */
464
+ function withAnalyzerFindings(
465
+ details: Record<string, unknown> | undefined,
466
+ findings: Record<string, unknown>[],
467
+ ): Record<string, unknown> | undefined {
468
+ const fromEnvelope = details?.findings;
469
+ if (
470
+ findings.length === 0 ||
471
+ (Array.isArray(fromEnvelope) && fromEnvelope.length > 0)
472
+ ) {
473
+ return details;
474
+ }
475
+ return { ...details, findings };
476
+ }
477
+
478
+ /** Flattened because consumers match flat keys only; the payload omits null members. */
479
+ function toAnalyzerFinding(
480
+ log: IOutputLog,
481
+ ): Record<string, unknown> | undefined {
482
+ if (log.source !== ANALYZER_LOG_SOURCE) {
483
+ return undefined;
484
+ }
485
+
486
+ const message = parseAnalyzerMessage(log.data) ?? {};
487
+ const activityId = message.ActivityId as { IdRef?: string } | undefined;
488
+ const item = message.Item as { Name?: string; Type?: string } | undefined;
489
+ return {
490
+ ...message,
491
+ ErrorCode: message.ErrorCode ?? log.code,
492
+ Description: message.Description ?? log.message,
493
+ FilePath: message.FilePath ?? log.filePath,
494
+ ErrorSeverity: message.ErrorSeverity ?? toErrorSeverity(log.logLevel),
495
+ ActivityIdRef: activityId?.IdRef ?? log.id,
496
+ AnalyzerItemName: item?.Name,
497
+ AnalyzerItemType: item?.Type,
498
+ };
499
+ }
500
+
501
+ /** Undo the compiler's `TraceLevel` → `LogLevel` mapping, so a consumer's lookup still matches. */
502
+ function toErrorSeverity(logLevel: IOutputLog["logLevel"]): string {
503
+ switch (logLevel) {
504
+ case "Debug":
505
+ case "Trace":
506
+ return "Verbose";
507
+ case "Information":
508
+ return "Info";
509
+ default:
510
+ return logLevel;
511
+ }
512
+ }
513
+
514
+ function parseAnalyzerMessage(
515
+ data: string | undefined,
516
+ ): Record<string, unknown> | undefined {
517
+ if (!data) {
518
+ return undefined;
519
+ }
520
+ try {
521
+ const parsed: unknown = JSON.parse(data);
522
+ return typeof parsed === "object" &&
523
+ parsed !== null &&
524
+ !Array.isArray(parsed)
525
+ ? (parsed as Record<string, unknown>)
526
+ : undefined;
527
+ } catch {
528
+ return undefined;
529
+ }
530
+ }
@@ -11,8 +11,7 @@ import {
11
11
  } from "@uipath/solutionpackager-tool-core";
12
12
  import { workflowCompilerConfig } from "./workflow-compiler-config.js";
13
13
 
14
- const NUGET_FEED_URL =
15
- "https://uipath.pkgs.visualstudio.com/Public.Feeds/_packaging/UiPath-Internal/nuget/v3/index.json";
14
+ const NUGET_FEED_URL = "https://pkgs.uipath.com/internal/index.json";
16
15
 
17
16
  const WORKFLOW_COMPILER_DLL_NAME = "UiPath.WorkflowCompiler.dll";
18
17
 
@@ -1,5 +1,6 @@
1
1
  import { OrchestratorFeedComposer } from "@uipath/packager-orchestrator-client";
2
2
  import {
3
+ type FileSystemStats,
3
4
  type IFileSystem,
4
5
  type IProjectBuildOptions,
5
6
  type IProjectCleanupOptions,
@@ -25,6 +26,19 @@ import { WorkflowCompilerExecutor } from "./workflow-compiler-executor.js";
25
26
  */
26
27
  type RawRemoveUnusedDependenciesResult = WorkflowCompilerCleanupPayload;
27
28
 
29
+ const NO_CLEANUP_SOURCE_FILES_MESSAGE =
30
+ "no workflow xamls or coded source files";
31
+ const CLEANUP_SOURCE_FILE_EXTENSIONS = [".xaml", ".cs", ".vb"];
32
+ const CLEANUP_SOURCE_SCAN_SKIP_DIRS = new Set([
33
+ ".git",
34
+ ".local",
35
+ ".project",
36
+ "bin",
37
+ "dist",
38
+ "node_modules",
39
+ "obj",
40
+ ]);
41
+
28
42
  /**
29
43
  * The two NuGet-source channels the WorkflowCompiler accepts, kept apart on
30
44
  * purpose:
@@ -325,10 +339,86 @@ export class WorkflowCompilerTool extends ProjectTool {
325
339
  args,
326
340
  cancellationToken,
327
341
  );
342
+ if (
343
+ await this.shouldRetryCleanupNoSourceFalseNegativeAsync(
344
+ result,
345
+ options.projectPath,
346
+ )
347
+ ) {
348
+ this.logger.warn(
349
+ "[WorkflowCompiler] remove-unused-dependencies reported no workflow/source files even though the project contains source files; retrying once.",
350
+ );
351
+ const retryResult = await this.executor.executeAsync(
352
+ "remove-unused-dependencies",
353
+ args,
354
+ cancellationToken,
355
+ );
356
+ return this.toProjectCleanupResult(retryResult);
357
+ }
328
358
  return this.toProjectCleanupResult(result);
329
359
  });
330
360
  }
331
361
 
362
+ private async shouldRetryCleanupNoSourceFalseNegativeAsync(
363
+ result: ToolResult,
364
+ projectPath: string,
365
+ ): Promise<boolean> {
366
+ if (result.isSuccess) {
367
+ return false;
368
+ }
369
+
370
+ const message = result.message?.toLowerCase();
371
+ if (!message?.includes(NO_CLEANUP_SOURCE_FILES_MESSAGE)) {
372
+ return false;
373
+ }
374
+
375
+ return await this.hasCleanupSourceFilesAsync(projectPath);
376
+ }
377
+
378
+ private async hasCleanupSourceFilesAsync(
379
+ projectPath: string,
380
+ ): Promise<boolean> {
381
+ let entries: string[];
382
+ try {
383
+ entries = await this.fileSystem.readdir(projectPath);
384
+ } catch {
385
+ return false;
386
+ }
387
+
388
+ for (const entry of entries) {
389
+ const lowerEntry = entry.toLowerCase();
390
+ const fullPath = this.fileSystem.path.join(projectPath, entry);
391
+ let stats: FileSystemStats | null;
392
+ try {
393
+ stats = await this.fileSystem.stat(fullPath);
394
+ } catch {
395
+ continue;
396
+ }
397
+ if (!stats) {
398
+ continue;
399
+ }
400
+
401
+ if (
402
+ stats.isFile() &&
403
+ CLEANUP_SOURCE_FILE_EXTENSIONS.some((extension) =>
404
+ lowerEntry.endsWith(extension),
405
+ )
406
+ ) {
407
+ return true;
408
+ }
409
+
410
+ if (
411
+ stats.isDirectory() &&
412
+ !CLEANUP_SOURCE_SCAN_SKIP_DIRS.has(lowerEntry) &&
413
+ (await this.hasCleanupSourceFilesAsync(fullPath))
414
+ ) {
415
+ return true;
416
+ }
417
+ }
418
+
419
+ return false;
420
+ }
421
+
332
422
  /**
333
423
  * Convert the WorkflowCompiler's raw `remove-unused-dependencies` payload
334
424
  * into the generic {@link ProjectCleanupInfo} the cleanup pipeline expects,