@uipath/flow-tool 1.201.0 → 1.202.0-preview.136

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 (234) hide show
  1. package/dist/{authoring-7r6g06c7.js → authoring-wpa6d0vf.js} +74 -48
  2. package/dist/binding-service-dh91hw9e.js +141 -0
  3. package/dist/{browser-strategy-rkcvc6tn.js → browser-strategy-6atc7v8s.js} +3 -3
  4. package/dist/connector-service-d9ph9kx1.js +948 -0
  5. package/dist/{conversion-H2VEEYLB-ng48mbf7.js → conversion-QANACVCM-zs0hhfjv.js} +39 -33
  6. package/dist/{de-5KVP66U6-f7knj511.js → de-5KVP66U6-1bnf4zt5.js} +52 -52
  7. package/dist/de-6U7ECGHH-xwsw33fk.js +35 -0
  8. package/dist/{de-5HU6GFWV-4EZK6G7N-yrh21f52.js → de-7XQXX2DK-IDWR6CAR-n4z245kt.js} +857 -845
  9. package/dist/{de-5HU6GFWV-zheyw6d2.js → de-7XQXX2DK-tqdy5n2b.js} +857 -845
  10. package/dist/{de-HKTOVV4H-d5yw5j21.js → de-HKTOVV4H-pe9w0xn8.js} +46 -46
  11. package/dist/{de-XLT4QPIP-0rtw349w.js → de-XLT4QPIP-kj81dxjc.js} +9 -9
  12. package/dist/debug-conversation-trigger-452frzyz.js +41 -0
  13. package/dist/debug-http-client-wd6xb8v4.js +31 -0
  14. package/dist/debug-service-fvyexnb1.js +58 -0
  15. package/dist/edge-service-e77bndbe.js +162 -0
  16. package/dist/{elk.bundled-pydbzeez.js → elk.bundled-vpsbxz0p.js} +3 -3
  17. package/dist/{en-MABQK6C4-REWE2WG2-8dp4cqdg.js → en-5ZGC5VQ3-EWX7ILY7-rmtj70fk.js} +898 -898
  18. package/dist/{en-MABQK6C4-nkzq2j8t.js → en-5ZGC5VQ3-h581y30k.js} +897 -897
  19. package/dist/en-EPWMLP2N-2wvge238.js +28 -0
  20. package/dist/{en-UNT7BE26-rhh65jry.js → en-LQHKFSEY-vvbe8ve9.js} +13 -11
  21. package/dist/{en-P4AS26D7-szrzfxz1.js → en-P4AS26D7-zptp77bm.js} +45 -45
  22. package/dist/{en-4KXU7N7B-66fntxa2.js → en-X3S6IZ5J-nhkg6pwn.js} +54 -60
  23. package/dist/{es-MX-H2EAXLYI-qwnqt48x.js → es-MX-H2EAXLYI-j42kfkxy.js} +46 -46
  24. package/dist/es-MX-NHTIP5YM-ar6zfx95.js +35 -0
  25. package/dist/{es-MX-OKNDG2NH-c1k1s1tg.js → es-MX-OKNDG2NH-tcac6j4g.js} +9 -9
  26. package/dist/{es-MX-POESXYP2-UW6VP5QI-cd3a79g9.js → es-MX-U2VN3SZW-KYAJ2ONK-kdram1g1.js} +857 -845
  27. package/dist/{es-MX-POESXYP2-9538722k.js → es-MX-U2VN3SZW-anynsmd8.js} +857 -845
  28. package/dist/{es-MX-XAVLOQW3-9b3cp9n8.js → es-MX-XAVLOQW3-q00km2y7.js} +52 -52
  29. package/dist/{es-NQICVYSQ-aa9z3nhs.js → es-NQICVYSQ-3dtqgget.js} +9 -9
  30. package/dist/{es-O4PAV2CR-jwfaawwk.js → es-O4PAV2CR-0g23ve3v.js} +46 -46
  31. package/dist/es-PQ3RA33Q-y4kxhjfr.js +35 -0
  32. package/dist/{es-VFPNVMP5-thm0z9sr.js → es-VFPNVMP5-bx2c337j.js} +52 -52
  33. package/dist/{es-LUTYN7U7-IY5QWOUF-k2aefzc0.js → es-ZGCPPOME-24PJEGPV-rn86z9kn.js} +857 -845
  34. package/dist/{es-LUTYN7U7-ye5zn4sn.js → es-ZGCPPOME-8gazspjj.js} +857 -845
  35. package/dist/flow-api-wv8p8xbd.js +36 -0
  36. package/dist/flow-debug-service-tfbefas6.js +741 -0
  37. package/dist/flow-eval-node-target-c6wea7rz.js +44 -0
  38. package/dist/flow-eval-run-service-01kdky72.js +961 -0
  39. package/dist/flow-eval-service-ft8e16jz.js +1338 -0
  40. package/dist/flow-init-service-mva4crty.js +35 -0
  41. package/dist/flow-io-r318sjrw.js +36 -0
  42. package/dist/flow-migrate-service-rwcdx60q.js +119 -0
  43. package/dist/flow-pack-service-p4hxyj9e.js +280 -0
  44. package/dist/flow-validate-service-j25pxpwz.js +57 -0
  45. package/dist/{fr-5YRGHXF5-q6b63yg0.js → fr-5YRGHXF5-kz1ywpv6.js} +46 -46
  46. package/dist/{fr-E5MDO4EG-exvrs7ge.js → fr-E5MDO4EG-c3mkty2t.js} +52 -52
  47. package/dist/{fr-PFHIL7YZ-cxnshwa8.js → fr-PFHIL7YZ-2n589p47.js} +9 -9
  48. package/dist/fr-R4L3OAWI-30khpsmn.js +35 -0
  49. package/dist/{fr-LJIK56LW-STG6QR3T-cextvv8q.js → fr-T3G5GZCT-TU4IKBEG-k6xz1s1f.js} +857 -845
  50. package/dist/{fr-LJIK56LW-xf3xf2kh.js → fr-T3G5GZCT-y3f7xb1q.js} +857 -845
  51. package/dist/governance-fetcher-j9cx4f1d.js +391 -0
  52. package/dist/headless-h1myzz32.js +177196 -0
  53. package/dist/hitl-service-kvt5wms4.js +256 -0
  54. package/dist/index-1kgxzh8x.js +143 -0
  55. package/dist/index-4zrwgb3c.js +111 -0
  56. package/dist/index-ev4mdg5y.js +4801 -0
  57. package/dist/{index-er6vy3jk.js → index-eybzsdcc.js} +295 -317
  58. package/dist/{index-hsadteg4.js → index-h8cph72k.js} +4 -4
  59. package/dist/{index-p50kx6jv.js → index-k5tbd184.js} +276 -276
  60. package/dist/index-n33np76r.js +630 -0
  61. package/dist/{index-9f8q2ege.js → index-p3vk57z7.js} +27 -27
  62. package/dist/{index-dhcd9b82.js → index-w0z4s69j.js} +166 -81
  63. package/dist/index.js +29 -32
  64. package/dist/{index.umd.min-drpc57vn.js → index.umd.min-fqefd9kn.js} +3 -3
  65. package/dist/init.js +24 -25
  66. package/dist/input-reader-6pwhtp8v.js +11 -0
  67. package/dist/{ja-FGEGLBJ3-w9byjhze.js → ja-BI5K3JDZ-77zat4z2.js} +857 -845
  68. package/dist/{ja-FGEGLBJ3-MG3BSWXD-vq19zt2p.js → ja-BI5K3JDZ-GTIHISTZ-s6n3r2ab.js} +857 -845
  69. package/dist/{ja-DPO5PPLO-s2a7j3nj.js → ja-DPO5PPLO-mysfmznx.js} +52 -52
  70. package/dist/{ja-P4OSE367-8ywxep9a.js → ja-P4OSE367-srr3qypg.js} +9 -9
  71. package/dist/{ja-SDAPAVCR-943p5gx7.js → ja-SDAPAVCR-kg39dfap.js} +46 -46
  72. package/dist/ja-ZHKCBE5W-x73w6x3e.js +35 -0
  73. package/dist/{js-yaml-cggj6w7q.js → js-yaml-87cdx6bm.js} +27 -19
  74. package/dist/known-types-a20evmmg.js +20 -0
  75. package/dist/ko-6W7OGLLB-mnmqc584.js +35 -0
  76. package/dist/{ko-ITOPNIYI-qz39kamf.js → ko-ITOPNIYI-hmxd2asd.js} +52 -52
  77. package/dist/{ko-TUAK3G3A-s25w0ckg.js → ko-JOBF5V7N-4bv0mjje.js} +857 -845
  78. package/dist/{ko-TUAK3G3A-TBEBKOTM-ns78t2rv.js → ko-JOBF5V7N-O7T4HKIE-ape840y0.js} +857 -845
  79. package/dist/{ko-NAGOZLC3-wb3y9yhh.js → ko-NAGOZLC3-gaxxsnd2.js} +46 -46
  80. package/dist/{ko-PYOS2KJP-5sbj5bp8.js → ko-PYOS2KJP-e7dshyxy.js} +9 -9
  81. package/dist/localization-h8a53z6p.js +47 -0
  82. package/dist/{node-gd4469ea.js → node-cnrcrrb0.js} +7973 -7166
  83. package/dist/node-service-8g5x5d2y.js +70 -0
  84. package/dist/{node-strategy-8gzp67xs.js → node-strategy-gc4sg6a2.js} +132 -16
  85. package/dist/node-sync-service-e2reh33c.js +42 -0
  86. package/dist/{packager-tool-9qecd4wb.js → packager-tool-0gctz400.js} +5 -2
  87. package/dist/{packager-tool-1cb0d5e0.js → packager-tool-0v3s8r01.js} +2 -2
  88. package/dist/{packager-tool-wckvcay0.js → packager-tool-1yh8g550.js} +9 -7
  89. package/dist/packager-tool-27avrkyk.js +15 -0
  90. package/dist/packager-tool-2wefykg9.js +106 -0
  91. package/dist/packager-tool-4fhgws0x.js +757 -0
  92. package/dist/{packager-tool-7yjpwj92.js → packager-tool-4hx14snw.js} +49 -48
  93. package/dist/{packager-tool-3wygxefb.js → packager-tool-58q3tvh7.js} +10 -10
  94. package/dist/{packager-tool-cvwr40ax.js → packager-tool-5qaxht3k.js} +1425 -550
  95. package/dist/packager-tool-5z1eg3ea.js +33289 -0
  96. package/dist/{packager-tool-17cn3xb7.js → packager-tool-6m078z5s.js} +13388 -19366
  97. package/dist/packager-tool-7b6tpg7y.js +77 -0
  98. package/dist/packager-tool-7exrv6w7.js +23 -0
  99. package/dist/packager-tool-8dszjcg5.js +4892 -0
  100. package/dist/packager-tool-8j92afwp.js +58 -0
  101. package/dist/packager-tool-94w17vf8.js +85 -0
  102. package/dist/{packager-tool-vdd02vns.js → packager-tool-9bec251q.js} +543 -1493
  103. package/dist/packager-tool-a1hbfmws.js +399 -0
  104. package/dist/{packager-tool-tq9q9m77.js → packager-tool-a42jnpy5.js} +3 -9
  105. package/dist/packager-tool-abbtfk2v.js +54 -0
  106. package/dist/packager-tool-cdwpc9fh.js +4945 -0
  107. package/dist/packager-tool-e0p2zsyc.js +97 -0
  108. package/dist/packager-tool-eebq62fq.js +540 -0
  109. package/dist/{packager-tool-m6x5sczh.js → packager-tool-em5r6g6j.js} +14 -21
  110. package/dist/packager-tool-eypvc2kv.js +23 -0
  111. package/dist/packager-tool-f0kd5kq4.js +2327 -0
  112. package/dist/packager-tool-fjaa8d3v.js +289 -0
  113. package/dist/packager-tool-g0eha8ge.js +121 -0
  114. package/dist/packager-tool-g9y14b10.js +54 -0
  115. package/dist/packager-tool-gbgfwx8f.js +2 -0
  116. package/dist/packager-tool-jc34wvrw.js +64 -0
  117. package/dist/packager-tool-k99nf3pq.js +25 -0
  118. package/dist/{packager-tool-hr0xg6q8.js → packager-tool-kn91khp6.js} +17 -13
  119. package/dist/{packager-tool-jysvpt8p.js → packager-tool-m3wkcxf5.js} +2 -2
  120. package/dist/{packager-tool-78a3szsp.js → packager-tool-m5qfverj.js} +1720 -2014
  121. package/dist/packager-tool-mwvbq6ef.js +79 -0
  122. package/dist/packager-tool-nq4rcqqg.js +87 -0
  123. package/dist/packager-tool-nxx8naxv.js +4234 -0
  124. package/dist/{packager-tool-3y0k15sv.js → packager-tool-p9stswjj.js} +2858 -19342
  125. package/dist/packager-tool-r0xpcqwg.js +188 -0
  126. package/dist/packager-tool-raq2wbwp.js +18 -0
  127. package/dist/{packager-tool-y3dezh8k.js → packager-tool-rs6jm14d.js} +6 -4
  128. package/dist/packager-tool-s9ff3kk4.js +6 -0
  129. package/dist/{packager-tool-pbsghbmj.js → packager-tool-sykgshez.js} +2 -2
  130. package/dist/packager-tool-tf3d2y8z.js +31 -0
  131. package/dist/packager-tool-tn5e7wnb.js +384 -0
  132. package/dist/packager-tool-v2rkcehq.js +457 -0
  133. package/dist/packager-tool-v86fdwvs.js +262 -0
  134. package/dist/packager-tool-v9psxdy5.js +8185 -0
  135. package/dist/packager-tool-v9rrz038.js +602 -0
  136. package/dist/packager-tool-vpqyvh4c.js +304 -0
  137. package/dist/packager-tool-wcha0e5r.js +443 -0
  138. package/dist/{packager-tool-1gt6js73.js → packager-tool-xhzfwa5p.js} +6 -4
  139. package/dist/{packager-tool-5arsyj36.js → packager-tool-yc4kw997.js} +4 -2
  140. package/dist/{packager-tool-pkq70dec.js → packager-tool-ywqc9rtf.js} +31 -3
  141. package/dist/{packager-tool-0567pxpm.js → packager-tool-z9bfhmm5.js} +10 -10
  142. package/dist/{packager-tool-gmrwvnyh.js → packager-tool-zfrp8ecz.js} +8 -58
  143. package/dist/{packager-tool-3vdpx9ng.js → packager-tool-zke08y39.js} +1121 -1846
  144. package/dist/packager-tool.js +17 -17
  145. package/dist/{pt-7TR74ZMB-1g8my56g.js → pt-7TR74ZMB-bmphh4x2.js} +46 -46
  146. package/dist/{pt-BR-7XGDXRDJ-TR5D7JYL-533wvy7p.js → pt-BR-7DYX2YPT-LZYH4YFD-bx43vx3z.js} +857 -845
  147. package/dist/{pt-BR-7XGDXRDJ-espnkgrj.js → pt-BR-7DYX2YPT-fqxqzqtf.js} +857 -845
  148. package/dist/{pt-BR-BXURWX4W-dqr4dnf9.js → pt-BR-BXURWX4W-bwfcwhk1.js} +52 -52
  149. package/dist/{pt-BR-DXXSYJDO-bn84ewp7.js → pt-BR-DXXSYJDO-a2tp13v7.js} +46 -46
  150. package/dist/pt-BR-UQCYHKMJ-q78n7q70.js +35 -0
  151. package/dist/{pt-BR-Z3TUDJHM-n7ngej6s.js → pt-BR-Z3TUDJHM-8v73x9s7.js} +9 -9
  152. package/dist/pt-D6A6MVB2-yvxca8vz.js +35 -0
  153. package/dist/{pt-TMVOOITK-myha14p9.js → pt-HTXGGX6Y-97t21dty.js} +857 -845
  154. package/dist/{pt-TMVOOITK-H2ADYHSD-ezpggv33.js → pt-HTXGGX6Y-ZHQSDFKI-vehfxadc.js} +857 -845
  155. package/dist/{pt-KSBWHAVQ-hd52bpsz.js → pt-KSBWHAVQ-mhvhgr2p.js} +9 -9
  156. package/dist/{pt-YI4VE4YQ-v7gjeg82.js → pt-YI4VE4YQ-wdkn2dcf.js} +52 -52
  157. package/dist/ro-4TMBHS5M-jz0anpt6.js +35 -0
  158. package/dist/{ro-BJFER5OI-334n28rj.js → ro-BJFER5OI-83tq8vxh.js} +46 -46
  159. package/dist/{ro-2VALF3S5-NXBJUEZN-nqw1zs33.js → ro-KTNQ3MNU-XIE6YPQN-gen8p82z.js} +857 -845
  160. package/dist/{ro-2VALF3S5-cdz5afkr.js → ro-KTNQ3MNU-y08n1x5g.js} +857 -845
  161. package/dist/{ro-RKXZUG7Z-cm3xn3fj.js → ro-RKXZUG7Z-nndrrsq7.js} +52 -52
  162. package/dist/{ro-VZUZTAMR-tccygznf.js → ro-VZUZTAMR-f4q0g3em.js} +9 -9
  163. package/dist/{ru-GSCT4ARZ-qj8dm4dp.js → ru-GSCT4ARZ-1sa9wbr8.js} +1 -1
  164. package/dist/{ru-GSCT4ARZ-FTVCGQTL-5nh4jf2e.js → ru-GSCT4ARZ-FTVCGQTL-gee86v14.js} +1 -1
  165. package/dist/{ru-T73OPRTC-mp5gn7gs.js → ru-T73OPRTC-4knxw497.js} +1 -1
  166. package/dist/{ru-WBLQ5B2U-awt245ky.js → ru-WBLQ5B2U-8r3c7v6d.js} +1 -1
  167. package/dist/ru-WBLQ5B2U-kdey8qa4.js +10 -0
  168. package/dist/{ru-WBLQ5B2U-57ezmxzz.js → ru-WBLQ5B2U-wemdzdqd.js} +1 -1
  169. package/dist/{serialization-GAW7UFOK-9hkdmmd2.js → serialization-J5QK3HPY-bgewpt6f.js} +158 -152
  170. package/dist/services/expression-validator.d.ts +28 -0
  171. package/dist/services/flow-eval-schema/types.d.ts +17 -0
  172. package/dist/services/flow-validate-service.d.ts +26 -0
  173. package/dist/services/node-validators/js-expression-syntax-validator.d.ts +6 -3
  174. package/dist/services/tidy-service.d.ts +26 -0
  175. package/dist/services/vars-reference-rule.d.ts +156 -0
  176. package/dist/shared-utils-8xdq6f04.js +20 -0
  177. package/dist/tidy-service-ashgyfwj.js +34 -0
  178. package/dist/tool.js +30 -33
  179. package/dist/{tr-AA6O2WSR-ga1xnymp.js → tr-AA6O2WSR-86ba4bdf.js} +52 -52
  180. package/dist/tr-GSQQ6SOT-hv1gyeaa.js +35 -0
  181. package/dist/{tr-RQTZ2DMS-bpgd4kma.js → tr-RQTZ2DMS-w3cwv8s4.js} +46 -46
  182. package/dist/{tr-W4AVRSQ4-bt3qqqdy.js → tr-W4AVRSQ4-hjr81xzk.js} +9 -9
  183. package/dist/{tr-RIFCEXFH-BZS7S7QK-q465b62g.js → tr-XHSSPNK7-GW5KVXR3-2w3f1ss6.js} +857 -845
  184. package/dist/{tr-RIFCEXFH-hgkb4g8y.js → tr-XHSSPNK7-cmqyc4wd.js} +857 -845
  185. package/dist/utils/handle-expansion.d.ts +16 -0
  186. package/dist/validation.js +47 -27
  187. package/dist/variable-service-er7ph4br.js +152 -0
  188. package/dist/wait-for-flow-job-45p1a444.js +134 -0
  189. package/dist/{zh-CN-IP3FMXWM-H3JI2XUM-ta4yac7h.js → zh-CN-2EHQT23P-T5XRQCVS-ac17dpc1.js} +857 -845
  190. package/dist/{zh-CN-IP3FMXWM-1cfarhcp.js → zh-CN-2EHQT23P-mr63c4xz.js} +857 -845
  191. package/dist/{zh-CN-6YRAN57T-j7jp34ws.js → zh-CN-6YRAN57T-rd7x2tqs.js} +9 -9
  192. package/dist/zh-CN-EDFRBU32-vvj7tmaq.js +35 -0
  193. package/dist/{zh-CN-R2KLHXQV-wttmznep.js → zh-CN-R2KLHXQV-agqr45ds.js} +52 -52
  194. package/dist/{zh-CN-ZC6LT4IN-vty9mvv8.js → zh-CN-ZC6LT4IN-kbzvvzz5.js} +46 -46
  195. package/dist/zh-TW-HAICM6DE-rh7k3cq7.js +35 -0
  196. package/dist/{zh-TW-AGIDXIPF-R4XZRDJZ-cgxxz5k4.js → zh-TW-MGZCE5BT-P6FLIUAR-zmq07vhs.js} +857 -845
  197. package/dist/{zh-TW-AGIDXIPF-n6r6w7vy.js → zh-TW-MGZCE5BT-c4ekmrz9.js} +857 -845
  198. package/dist/{zh-TW-R7Y5KVMU-q81f4z2p.js → zh-TW-R7Y5KVMU-m61y07e3.js} +46 -46
  199. package/dist/{zh-TW-RJGCQANM-gqn0aca0.js → zh-TW-RJGCQANM-w0x3qc1p.js} +52 -52
  200. package/dist/{zh-TW-SO2245GN-m5kh88bg.js → zh-TW-SO2245GN-n2bn1gg4.js} +9 -9
  201. package/package.json +2 -2
  202. package/dist/de-5KVP66U6-t37qr521.js +0 -161
  203. package/dist/de-WMKOGI7B-6dc1zdnp.js +0 -143
  204. package/dist/en-4KXU7N7B-24v330b5.js +0 -118
  205. package/dist/en-X4DLPKLJ-1h9gj5c1.js +0 -110
  206. package/dist/es-BVPGJUWA-0k59eqfv.js +0 -143
  207. package/dist/es-MX-U6YL5KQX-k4qvpgd4.js +0 -143
  208. package/dist/es-MX-XAVLOQW3-47a405kf.js +0 -161
  209. package/dist/es-VFPNVMP5-6sftsdxe.js +0 -161
  210. package/dist/fr-E5MDO4EG-f3x1jeqw.js +0 -161
  211. package/dist/fr-EKTTDR7Z-m2t68j0m.js +0 -143
  212. package/dist/ja-DPO5PPLO-fmbg7zt2.js +0 -161
  213. package/dist/ja-Y2YBTXNN-5sszk2zv.js +0 -143
  214. package/dist/ko-ITOPNIYI-aqy82jk8.js +0 -161
  215. package/dist/ko-S33XAV26-rfsv9myd.js +0 -143
  216. package/dist/packager-tool-0sz8se22.js +0 -10671
  217. package/dist/packager-tool-8mqydhz8.js +0 -9850
  218. package/dist/packager-tool-p9j43p8h.js +0 -115
  219. package/dist/packager-tool-v74yk918.js +0 -107
  220. package/dist/packager-tool-xj0agqpk.js +0 -11
  221. package/dist/pt-BR-BXURWX4W-xzyndmrx.js +0 -161
  222. package/dist/pt-BR-JO45SCNI-mt93s33c.js +0 -143
  223. package/dist/pt-W3NA4LIZ-fwd1q4j0.js +0 -143
  224. package/dist/pt-YI4VE4YQ-521681zf.js +0 -161
  225. package/dist/ro-RKXZUG7Z-pdztdafr.js +0 -161
  226. package/dist/ro-WLKX6HF5-b9tj8q67.js +0 -143
  227. package/dist/ru-WBLQ5B2U-8xd4gpv2.js +0 -10
  228. package/dist/ru-WBLQ5B2U-mswqs9wc.js +0 -10
  229. package/dist/tr-3U2W2XCA-43ptfc0m.js +0 -143
  230. package/dist/tr-AA6O2WSR-bj9n80k8.js +0 -161
  231. package/dist/zh-CN-IPZYQR3P-egjmvyjf.js +0 -143
  232. package/dist/zh-CN-R2KLHXQV-x6gnk2n0.js +0 -161
  233. package/dist/zh-TW-RJGCQANM-tt8j5wv2.js +0 -161
  234. package/dist/zh-TW-YPVSQVGT-b378ztph.js +0 -143
@@ -0,0 +1,4234 @@
1
+ import {
2
+ DEFAULT_INTERVAL_MS,
3
+ DEFAULT_TIMEOUT_MS,
4
+ pendingSecondsFor,
5
+ pendingStallInstructions
6
+ } from "./packager-tool-tf3d2y8z.js";
7
+ import {
8
+ package_default
9
+ } from "./packager-tool-7b6tpg7y.js";
10
+ import {
11
+ VALID_RESOURCE_TYPES
12
+ } from "./packager-tool-27avrkyk.js";
13
+ import {
14
+ evaluatorTypeAliases
15
+ } from "./packager-tool-a1hbfmws.js";
16
+ import {
17
+ registerRegistryCommand,
18
+ registerSharedDebugInstanceCommands,
19
+ registerSharedIncidentCommands,
20
+ registerSharedInstanceCommands,
21
+ registerSharedProcessCommands,
22
+ registerSharedProcessesCommands
23
+ } from "./packager-tool-cdwpc9fh.js";
24
+ import {
25
+ setAgentProjectMetadataReader
26
+ } from "./packager-tool-v9psxdy5.js";
27
+ import {
28
+ ATTACHMENT_INSTRUCTIONS,
29
+ ATTACHMENT_UPLOAD_INSTRUCTIONS,
30
+ OutputFormatter,
31
+ RESULTS,
32
+ ScreenLogger,
33
+ appendOption,
34
+ catchError,
35
+ createHiddenDeprecatedTenantOption,
36
+ extractErrorMessage,
37
+ extractErrorMessageSync,
38
+ instructionsFor,
39
+ isPreviewBuild,
40
+ logger,
41
+ mapPackageMetadataOptions,
42
+ parseAttachmentSpec,
43
+ processContext,
44
+ registerPackageMetadataOptions,
45
+ resolveAttachmentInputs,
46
+ splitPackagedName,
47
+ summarizePlatformBody,
48
+ trackShipSucceeded
49
+ } from "./packager-tool-5qaxht3k.js";
50
+ import {
51
+ getFileSystem
52
+ } from "./packager-tool-0v3s8r01.js";
53
+ import {
54
+ __require
55
+ } from "./packager-tool-1yh8g550.js";
56
+
57
+ // src/commands/binding.ts
58
+ var BINDING_LIST_EXAMPLES = [
59
+ {
60
+ Description: "List all bindings in a flow file",
61
+ Command: "uip maestro flow binding list flow.json",
62
+ Output: {
63
+ Code: "BindingListSuccess",
64
+ Data: {
65
+ Bindings: [
66
+ {
67
+ id: "a1b2c3d4-0000-0000-0000-000000000001",
68
+ name: "InvoiceProcess",
69
+ resource: "process",
70
+ defaultValue: "InvoiceProcess"
71
+ }
72
+ ],
73
+ Count: 1
74
+ }
75
+ }
76
+ }
77
+ ];
78
+ var BINDING_ADD_EXAMPLES = [
79
+ {
80
+ Description: "Add a process binding to a flow",
81
+ Command: 'uip maestro flow binding add flow.json "Invoice" process "InvoiceProcess" --property-attribute name',
82
+ Output: {
83
+ Code: "BindingAddSuccess",
84
+ Data: {
85
+ Binding: {
86
+ id: "a1b2c3d4-0000-0000-0000-000000000001",
87
+ name: "Invoice",
88
+ resource: "process",
89
+ defaultValue: "InvoiceProcess",
90
+ propertyAttribute: "name"
91
+ }
92
+ }
93
+ }
94
+ }
95
+ ];
96
+ var BINDING_DELETE_EXAMPLES = [
97
+ {
98
+ Description: "Remove all bindings by resource key",
99
+ Command: "uip maestro flow binding remove flow.json a1b2c3d4-0000-0000-0000-000000000001",
100
+ Output: {
101
+ Code: "BindingRemoveSuccess",
102
+ Data: {
103
+ DeletedBindings: [
104
+ {
105
+ id: "a1b2c3d4-0000-0000-0000-000000000001",
106
+ name: "Invoice"
107
+ }
108
+ ],
109
+ Count: 1
110
+ }
111
+ }
112
+ }
113
+ ];
114
+ var registerBindingCommand = (program) => {
115
+ const binding = program.command("binding").description("Manage bindings in a Flow file");
116
+ binding.command("list").description("List all bindings in a Flow file").argument("<file>", "Path to the .flow file").examples(BINDING_LIST_EXAMPLES).trackedAction(processContext, async (file) => {
117
+ const { listBindingsInFlow } = await import("./binding-service-dh91hw9e.js");
118
+ const [error, result] = await catchError(listBindingsInFlow(file));
119
+ if (error) {
120
+ OutputFormatter.error({
121
+ Result: RESULTS.Failure,
122
+ Message: "Error listing bindings",
123
+ Instructions: extractErrorMessageSync(error)
124
+ });
125
+ processContext.exit(1);
126
+ return;
127
+ }
128
+ OutputFormatter.success({
129
+ Result: RESULTS.Success,
130
+ Code: "BindingListSuccess",
131
+ Data: {
132
+ Bindings: result.bindings,
133
+ Count: result.count
134
+ }
135
+ });
136
+ });
137
+ binding.command("add").description(`Add a binding to a Flow file.
138
+ ` + `Valid resource types: ${VALID_RESOURCE_TYPES.join(", ")}`).argument("<file>", "Path to the .flow file").argument("<name>", "Binding display name").argument("<resource>", "Resource type").argument("<default-value>", "Default value for the binding").option("--resource-key <key>", "Resource catalog identifier").option("--property-attribute <attr>", "Target node property (e.g., name, folderPath, connection)").option("--resource-sub-type <type>", "Resource sub-classification (e.g., Agent, Process)").examples(BINDING_ADD_EXAMPLES).trackedAction(processContext, async (file, name, resource, defaultValue, options) => {
139
+ const { addBindingToFlow } = await import("./binding-service-dh91hw9e.js");
140
+ const [error, result] = await catchError(addBindingToFlow(file, name, resource, defaultValue, {
141
+ resourceKey: options.resourceKey,
142
+ propertyAttribute: options.propertyAttribute,
143
+ resourceSubType: options.resourceSubType
144
+ }));
145
+ if (error) {
146
+ OutputFormatter.error({
147
+ Result: RESULTS.Failure,
148
+ Message: "Error adding binding",
149
+ Instructions: extractErrorMessageSync(error)
150
+ });
151
+ processContext.exit(1);
152
+ return;
153
+ }
154
+ OutputFormatter.success({
155
+ Result: RESULTS.Success,
156
+ Code: "BindingAddSuccess",
157
+ Data: {
158
+ Binding: result.binding
159
+ }
160
+ });
161
+ });
162
+ binding.command("remove").description("Remove all bindings with a given resource key from a Flow file").argument("<file>", "Path to the .flow file").argument("<resource-key>", "Resource key of the bindings to remove").examples(BINDING_DELETE_EXAMPLES).trackedAction(processContext, async (file, resourceKey) => {
163
+ const { deleteBindingFromFlow } = await import("./binding-service-dh91hw9e.js");
164
+ const [error, result] = await catchError(deleteBindingFromFlow(file, resourceKey));
165
+ if (error) {
166
+ OutputFormatter.error({
167
+ Result: RESULTS.Failure,
168
+ Message: "Error deleting binding",
169
+ Instructions: extractErrorMessageSync(error)
170
+ });
171
+ processContext.exit(1);
172
+ return;
173
+ }
174
+ OutputFormatter.success({
175
+ Result: RESULTS.Success,
176
+ Code: "BindingRemoveSuccess",
177
+ Data: {
178
+ DeletedBindings: result.deletedBindings,
179
+ Count: result.count
180
+ }
181
+ });
182
+ });
183
+ };
184
+
185
+ // src/commands/debug.ts
186
+ function buildHttpFailureOutput(err) {
187
+ const stageLabel = err.stage ?? "request";
188
+ const where = `${err.method} ${err.endpoint}`;
189
+ const traceSuffix = err.parsedTraceId ? ` (traceId=${err.parsedTraceId})` : "";
190
+ const attemptSuffix = (err.attempts ?? 1) > 1 ? `, ${err.attempts} attempts` : "";
191
+ const Message = `Failed during ${stageLabel}: HTTP ${err.httpStatus} on ${where}${traceSuffix}${attemptSuffix}`;
192
+ const Instructions = pickInstructions(err);
193
+ const Context = {
194
+ httpStatus: err.httpStatus,
195
+ stage: err.stage,
196
+ endpoint: err.endpoint,
197
+ method: err.method
198
+ };
199
+ if (err.parsedErrorCode !== undefined) {
200
+ Context.errorCode = err.parsedErrorCode;
201
+ }
202
+ if (err.parsedRequestId !== undefined) {
203
+ Context.requestId = err.parsedRequestId;
204
+ }
205
+ if (err.parsedTraceId !== undefined) {
206
+ Context.traceId = err.parsedTraceId;
207
+ }
208
+ if (err.attempts !== undefined) {
209
+ Context.attempts = err.attempts;
210
+ }
211
+ const output = {
212
+ Result: RESULTS.Failure,
213
+ Message,
214
+ Instructions,
215
+ Context
216
+ };
217
+ const Retry = pickRetryHint(err);
218
+ if (Retry !== undefined) {
219
+ output.Retry = Retry;
220
+ }
221
+ return output;
222
+ }
223
+ function pickRetryHint(err) {
224
+ if (err.httpStatus < 500 || err.httpStatus >= 600) {
225
+ return;
226
+ }
227
+ return (err.attempts ?? 1) > 1 ? "RetryWillNotFix" : "RetryAfter30Seconds";
228
+ }
229
+ function pickInstructions(err) {
230
+ const isOpaque5xx = err.httpStatus >= 500 && err.httpStatus < 600 && (err.parsedErrorCode === undefined || err.parsedErrorCode === "0");
231
+ if (isOpaque5xx) {
232
+ const stage = err.stage ?? "request";
233
+ const traceIds = err.traceIds?.length ? err.traceIds : err.parsedTraceId ? [err.parsedTraceId] : [];
234
+ const traceHint = traceIds.length ? ` traceIds: ${traceIds.join(", ")}.` : "";
235
+ const escalationTraces = traceIds.length ? ` and traceIds: ${traceIds.join(", ")}` : "";
236
+ if ((err.attempts ?? 1) > 1) {
237
+ return `${err.method} ${err.endpoint} returned ${err.httpStatus} on all ${err.attempts} attempts ` + `during '${stage}', so the backend runtime is down rather than blipping. ` + `Do not re-run 'debug' — escalate to the owning service team with the endpoint${escalationTraces}. ` + `To keep working meanwhile, run the project instead of debugging it: ` + `'uip solution pack <solution-path> <out-dir>', 'uip solution publish <out-dir>/<name>.zip', ` + `'uip solution deploy run', then 'uip maestro flow process run'.`;
238
+ }
239
+ return `The backend returned an unstructured ${err.httpStatus} during '${stage}'.${traceHint} ` + `This is often transient — wait ~30s and retry once. If it fails again, capture the traceId ` + `and ${err.method} ${err.endpoint} and escalate to the owning service team.`;
240
+ }
241
+ if (err.httpStatus === 401 || err.httpStatus === 403) {
242
+ return `Authentication/authorization rejected by ${err.method} ${err.endpoint}. ` + `Run 'uip login' and verify the active tenant has access.`;
243
+ }
244
+ if (err.httpStatus === 404) {
245
+ const isStructured = err.parsedErrorMessage !== undefined || err.parsedErrorCode !== undefined;
246
+ if (!isStructured) {
247
+ const body = summarizePlatformBody(err.body);
248
+ const bodySuffix = body ? ` Platform response: "${body}".` : "";
249
+ return `${err.method} ${err.endpoint} returned 404 during '${err.stage ?? "request"}', ` + `but the response was not a structured Orchestrator error — the request likely ` + `did not reach the tenant. This usually means the organization or tenant in your ` + `login session is wrong or was renamed. Run 'uip login tenant list' to see the ` + `current tenant names, re-select with 'uip login tenant set <name>' (or re-run ` + `'uip login'), then retry. Do not create a new workspace or retry as-is — the ` + `resource likely exists under the current tenant name.${bodySuffix}`;
250
+ }
251
+ const detail2 = err.parsedErrorMessage ? ` Backend reported: "${err.parsedErrorMessage}".` : "";
252
+ return `${err.method} ${err.endpoint} returned 404 during '${err.stage ?? "request"}'. ` + `The target resource may not exist — verify upstream IDs (solutionId, instanceId) ` + `and re-run.${detail2}`;
253
+ }
254
+ const detail = err.parsedErrorMessage ? ` Backend reported: "${err.parsedErrorMessage}".` : "";
255
+ return `${err.method} ${err.endpoint} failed with HTTP ${err.httpStatus} during ` + `'${err.stage ?? "request"}'.${detail} Inspect the response body for details ` + `and retry once before reporting.`;
256
+ }
257
+ function summarizeIncidents(incidents) {
258
+ return incidents.map((inc) => {
259
+ const code = inc.errorCode ? `[${inc.errorCode}] ` : "";
260
+ const element = inc.elementId ? ` (element ${inc.elementId})` : "";
261
+ return `${code}${inc.errorMessage}${element}`;
262
+ });
263
+ }
264
+ function buildIncidentInstructions(incidents, instanceId) {
265
+ const lines = summarizeIncidents(incidents);
266
+ const first = incidents[0];
267
+ const traceHint = first?.traceId ? ` traceId=${first.traceId}.` : "";
268
+ const detailHint = `Run 'uip maestro flow debug-instance incidents ${instanceId}' for ` + `the full backend payload (incidentId, errorDetails, AI summary).`;
269
+ return `Incident(s):
270
+ - ${lines.join(`
271
+ - `)}
272
+ ${detailHint}${traceHint}`;
273
+ }
274
+ var CONVERSATIONAL_DEBUG_WARNING = "This flow, which starts on a conversation trigger, can only be debugged from a chat UI. " + `Debug it using the chat panel from either:
275
+ ` + " 1. Studio Web — open the debug URL printed once the solution uploads " + `(also 'Data.studioWebUrl' in the result).
276
+ ` + " 2. UiPath Maestro VS Code extension — open the flow and hit Debug.";
277
+ async function projectStartsOnConversationTrigger(projectPath) {
278
+ const [error, found] = await catchError((async () => {
279
+ const { readFlowWorkflow, resolveProjectFlowFile } = await import("./flow-io-r318sjrw.js");
280
+ const { startsOnConversationTrigger } = await import("./debug-conversation-trigger-452frzyz.js");
281
+ const flowFilePath = await resolveProjectFlowFile(projectPath);
282
+ const { workflow } = await readFlowWorkflow(flowFilePath);
283
+ return startsOnConversationTrigger(workflow);
284
+ })());
285
+ if (error) {
286
+ logger.info(`Skipped the conversational pre-flight scan: ${error.message}`);
287
+ return false;
288
+ }
289
+ return found === true;
290
+ }
291
+ var FLOW_DEBUG_EXAMPLES = [
292
+ {
293
+ Description: "Debug a local flow project via Studio Web",
294
+ Command: "uip maestro flow debug ./my-flow-project",
295
+ Output: {
296
+ Code: "FlowDebug",
297
+ Data: {
298
+ jobKey: "b2c3d4e5-0000-0000-0000-000000000001",
299
+ instanceId: "c3d4e5f6-0000-0000-0000-000000000001",
300
+ runId: "d4e5f6a7-0000-0000-0000-000000000001",
301
+ finalStatus: "Completed",
302
+ solutionId: "e5f6a7b8-0000-0000-0000-000000000001",
303
+ studioWebUrl: "https://cloud.uipath.com/org/tenant/studio_/debug/e5f6a7b8",
304
+ elementExecutions: [
305
+ { elementId: "Node_1", status: "Completed" }
306
+ ]
307
+ }
308
+ }
309
+ },
310
+ {
311
+ Description: "Conversational flow (core.trigger.conversation) — uploaded to Studio Web and handed off, since only a chat UI can drive it. No debug session is started",
312
+ Command: "uip maestro flow debug ./my-chat-flow --open-in-browser",
313
+ Output: {
314
+ Code: "FlowDebugStudioWebHandoff",
315
+ Data: {
316
+ solutionId: "e5f6a7b8-0000-0000-0000-000000000001",
317
+ studioWebUrl: "https://cloud.uipath.com/org/studio_/designer/a1b2c3d4?solutionId=e5f6a7b8",
318
+ handedOff: true
319
+ }
320
+ }
321
+ },
322
+ {
323
+ Description: 'Faulted debug — emitted as a Result: "Failure" envelope (exit 1) with incident details (errorCode, errorMessage, elementId) inline on Data.incidents, so no follow-up command is needed',
324
+ Command: "uip maestro flow debug ./my-flow-project",
325
+ Output: {
326
+ Code: "FlowDebug",
327
+ Data: {
328
+ jobKey: "b2c3d4e5-0000-0000-0000-000000000001",
329
+ instanceId: "c3d4e5f6-0000-0000-0000-000000000001",
330
+ runId: "d4e5f6a7-0000-0000-0000-000000000001",
331
+ finalStatus: "Faulted",
332
+ incidents: [
333
+ {
334
+ incidentId: "inc-1",
335
+ elementId: "Node_3",
336
+ errorCode: "Process.UnhandledException",
337
+ errorMessage: "Object reference not set to an instance of an object."
338
+ }
339
+ ]
340
+ }
341
+ }
342
+ }
343
+ ];
344
+ var LOGIN_INSTRUCTIONS = "Run 'uip login' and select an organization, tenant, and folder with Studio Web access, then retry.";
345
+ var INPUT_INSTRUCTIONS = "Provide --inputs as a valid JSON object or a readable @file.json path.";
346
+ var NUMBER_OPTION_INSTRUCTIONS = "Use a positive numeric value. Provide --poll-interval in milliseconds and --timeout in seconds.";
347
+ var FOLDER_ID_INSTRUCTIONS = "Provide --folder-id as a positive integer (the Orchestrator folder Id, e.g. 12345).";
348
+ var FOLDER_TARGETING_INSTRUCTIONS = "Pass at most one of --folder-id, --folder-key, or --folder-path. Use 'uip or folders list' to discover values.";
349
+ var FOLDER_RESOLUTION_INSTRUCTIONS = "Provide a valid --folder-key (UUID) or --folder-path. Use 'uip or folders list' to confirm the key or path.";
350
+ var FOLDER_RESOLUTION_NETWORK_INSTRUCTIONS = "The folder lookup itself failed (network / Orchestrator API). Re-authenticate with 'uip login', verify connectivity, and retry.";
351
+ var DEBUG_FAILURE_INSTRUCTIONS = "Check that the flow project is valid, the selected folder is accessible, and Studio Web debug is available, then retry.";
352
+ async function openInBrowserOrWarn(url) {
353
+ const [openError] = await catchError(async () => {
354
+ await getFileSystem().utils.open(url);
355
+ });
356
+ if (openError) {
357
+ OutputFormatter.log({
358
+ Warning: `Could not open the browser automatically: ${openError.message}`
359
+ });
360
+ }
361
+ }
362
+ function buildHandoffInstructions(studioWebUrl) {
363
+ return "This flow can only be driven from a chat UI, so no debug session was started. " + `Debug it using the chat panel from either:
364
+ ` + ` 1. Studio Web — open ${studioWebUrl}.
365
+ ` + " 2. UiPath Maestro VS Code extension — open the flow and hit Debug.";
366
+ }
367
+ function isFolderInputError(err) {
368
+ if ("response" in err)
369
+ return false;
370
+ if (err.name === "FetchError")
371
+ return false;
372
+ return true;
373
+ }
374
+ function parsePositiveNumberOption(value, optionName) {
375
+ const parsed = Number(value);
376
+ if (!Number.isFinite(parsed) || parsed <= 0) {
377
+ return {
378
+ ok: false,
379
+ message: `${optionName} must be a positive number.`
380
+ };
381
+ }
382
+ return { ok: true, value: parsed };
383
+ }
384
+ function parsePositiveIntegerOption(value, optionName) {
385
+ const parsed = Number(value);
386
+ if (!Number.isInteger(parsed) || parsed <= 0) {
387
+ return {
388
+ ok: false,
389
+ message: `${optionName} must be a positive integer.`
390
+ };
391
+ }
392
+ return { ok: true, value: parsed };
393
+ }
394
+ function registerDebugCommand(program) {
395
+ program.command("debug").description("Debug a flow project by uploading to Studio Web and running a debug session").argument("<project-path>", "Path to the flow project directory (must contain project.uiproj)").option("--folder-id <id>", "Orchestrator folder ID (OrganizationUnitId) as a positive integer. Mutually exclusive with --folder-key/--folder-path. Auto-detected if none are provided.").option("--folder-key <key>", "Orchestrator folder key (UUID). The CLI resolves it to the folder ID. Mutually exclusive with --folder-id/--folder-path.").option("--folder-path <path>", "Orchestrator folder path (e.g. 'Shared/Sub'). The CLI resolves it to the folder ID. Mutually exclusive with --folder-id/--folder-key.").option("--poll-interval <ms>", "Polling interval in milliseconds", "2000").option("--timeout <seconds>", "Maximum seconds to wait for debug completion").option("-i, --inputs <json>", "Input parameters as JSON string or @file.json").option("--attachment <name=path>", "Upload a file as a file-typed workflow input variable (repeatable). " + "Example: --attachment file1=./resume.pdf", appendOption, []).option("--open-in-browser", "Open the Studio Web URL in the browser once it is known.").option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).examples(FLOW_DEBUG_EXAMPLES).trackedAction(processContext, async (projectPath, options) => {
396
+ const { getLoginStatusAsync } = await import("./index-1kgxzh8x.js");
397
+ const isConversational = await projectStartsOnConversationTrigger(projectPath);
398
+ if (isConversational) {
399
+ OutputFormatter.log({
400
+ Warning: CONVERSATIONAL_DEBUG_WARNING
401
+ });
402
+ if (options.timeout !== undefined) {
403
+ OutputFormatter.log({
404
+ Warning: "--timeout has no effect here: the CLI uploads and hands off without polling a run."
405
+ });
406
+ }
407
+ }
408
+ let urlReported = false;
409
+ const [loginError, login] = await catchError(getLoginStatusAsync({
410
+ ensureTokenValidityMinutes: options.loginValidity
411
+ }));
412
+ if (loginError) {
413
+ OutputFormatter.error({
414
+ Result: RESULTS.Failure,
415
+ Message: loginError.message,
416
+ Instructions: LOGIN_INSTRUCTIONS
417
+ });
418
+ processContext.exit(1);
419
+ return;
420
+ }
421
+ const {
422
+ loginStatus,
423
+ baseUrl,
424
+ accessToken,
425
+ organizationId,
426
+ tenantId,
427
+ tenantName,
428
+ organizationUnitId,
429
+ organizationName
430
+ } = login;
431
+ if (loginStatus !== "Logged in" || !baseUrl) {
432
+ OutputFormatter.error({
433
+ Result: RESULTS.Failure,
434
+ Message: "Not logged in. Run 'uip login' first.",
435
+ Instructions: LOGIN_INSTRUCTIONS
436
+ });
437
+ processContext.exit(1);
438
+ return;
439
+ }
440
+ if (!organizationId) {
441
+ OutputFormatter.error({
442
+ Result: RESULTS.Failure,
443
+ Message: "Organization ID not available from login.",
444
+ Instructions: LOGIN_INSTRUCTIONS
445
+ });
446
+ processContext.exit(1);
447
+ return;
448
+ }
449
+ if (!tenantId) {
450
+ OutputFormatter.error({
451
+ Result: RESULTS.Failure,
452
+ Message: "Tenant ID not available from login.",
453
+ Instructions: LOGIN_INSTRUCTIONS
454
+ });
455
+ processContext.exit(1);
456
+ return;
457
+ }
458
+ if (!tenantName) {
459
+ OutputFormatter.error({
460
+ Result: RESULTS.Failure,
461
+ Message: "Tenant name not available from login.",
462
+ Instructions: LOGIN_INSTRUCTIONS
463
+ });
464
+ processContext.exit(1);
465
+ return;
466
+ }
467
+ if (!accessToken) {
468
+ OutputFormatter.error({
469
+ Result: RESULTS.Failure,
470
+ Message: "Access token not available from login.",
471
+ Instructions: LOGIN_INSTRUCTIONS
472
+ });
473
+ processContext.exit(1);
474
+ return;
475
+ }
476
+ if (!organizationName) {
477
+ OutputFormatter.error({
478
+ Result: RESULTS.Failure,
479
+ Message: "Organization name not available from login. Required for Studio Web debug.",
480
+ Instructions: LOGIN_INSTRUCTIONS
481
+ });
482
+ processContext.exit(1);
483
+ return;
484
+ }
485
+ const folderTargetingFlags = [
486
+ options.folderId !== undefined ? "--folder-id" : undefined,
487
+ options.folderKey !== undefined ? "--folder-key" : undefined,
488
+ options.folderPath !== undefined ? "--folder-path" : undefined
489
+ ].filter((flag) => flag !== undefined);
490
+ if (folderTargetingFlags.length > 1) {
491
+ OutputFormatter.error({
492
+ Result: RESULTS.ValidationError,
493
+ Message: `Cannot combine ${folderTargetingFlags.join(", ")}.`,
494
+ Instructions: FOLDER_TARGETING_INSTRUCTIONS
495
+ });
496
+ processContext.exit(3);
497
+ return;
498
+ }
499
+ let userProvidedFolderId;
500
+ if (options.folderId !== undefined) {
501
+ const parsed = parsePositiveIntegerOption(options.folderId, "--folder-id");
502
+ if (!parsed.ok) {
503
+ OutputFormatter.error({
504
+ Result: RESULTS.ValidationError,
505
+ Message: parsed.message,
506
+ Instructions: FOLDER_ID_INSTRUCTIONS
507
+ });
508
+ processContext.exit(3);
509
+ return;
510
+ }
511
+ userProvidedFolderId = parsed.value;
512
+ } else if (options.folderKey !== undefined || options.folderPath !== undefined) {
513
+ const { resolveFolder } = await import("./index-ev4mdg5y.js");
514
+ const [folderError, folder] = await catchError(resolveFolder({
515
+ folderKey: options.folderKey,
516
+ folderPath: options.folderPath
517
+ }, { loginValidity: options.loginValidity }));
518
+ if (folderError || !folder) {
519
+ const inputProblem = !folderError || isFolderInputError(folderError);
520
+ const message = folderError ? `Could not resolve folder: ${folderError.message}` : "Folder targeting requested but no folder resolved.";
521
+ OutputFormatter.error({
522
+ Result: inputProblem ? RESULTS.ValidationError : RESULTS.Failure,
523
+ Message: message,
524
+ Instructions: inputProblem ? FOLDER_RESOLUTION_INSTRUCTIONS : FOLDER_RESOLUTION_NETWORK_INSTRUCTIONS
525
+ });
526
+ processContext.exit(inputProblem ? 3 : 1);
527
+ return;
528
+ }
529
+ userProvidedFolderId = folder.id;
530
+ logger.info(`Resolved folder '${folder.path}' to ID ${folder.id} (key ${folder.key}).`);
531
+ }
532
+ const studioWebConfig = {
533
+ baseUrl,
534
+ organizationId,
535
+ tenantId,
536
+ tenantName,
537
+ authToken: accessToken,
538
+ organizationUnitId: userProvidedFolderId ?? organizationUnitId,
539
+ organizationName,
540
+ userProvidedFolderId
541
+ };
542
+ logger.info("Login verified successfully.");
543
+ logger.info(` Organization: ${organizationName} (${organizationId})`);
544
+ logger.info(` Tenant: ${tenantName} (${tenantId})`);
545
+ logger.info(` Base URL: ${baseUrl}`);
546
+ const {
547
+ FlowDebugService,
548
+ InboundVoiceDebugError,
549
+ MissingSolutionWrapperError,
550
+ UnregisteredProjectError
551
+ } = await import("./flow-debug-service-tfbefas6.js");
552
+ const { MaestroHttpError } = await import("./debug-http-client-wd6xb8v4.js");
553
+ const {
554
+ buildPollTimeoutFailureOutput,
555
+ DebugPollTimeoutError,
556
+ isSuccessfulDebugStatus
557
+ } = await import("./debug-service-fvyexnb1.js");
558
+ const {
559
+ buildSolutionUploadFailureOutput,
560
+ isSolutionUploadHttpError
561
+ } = await import("./index-n33np76r.js");
562
+ const service = new FlowDebugService;
563
+ const parsedPollInterval = parsePositiveNumberOption(options.pollInterval || "2000", "--poll-interval");
564
+ if (!parsedPollInterval.ok) {
565
+ OutputFormatter.error({
566
+ Result: RESULTS.Failure,
567
+ Message: parsedPollInterval.message,
568
+ Instructions: NUMBER_OPTION_INSTRUCTIONS
569
+ });
570
+ processContext.exit(1);
571
+ return;
572
+ }
573
+ const pollInterval = parsedPollInterval.value;
574
+ let maxPolls;
575
+ if (options.timeout !== undefined) {
576
+ const parsedTimeout = parsePositiveNumberOption(options.timeout, "--timeout");
577
+ if (!parsedTimeout.ok) {
578
+ OutputFormatter.error({
579
+ Result: RESULTS.Failure,
580
+ Message: parsedTimeout.message,
581
+ Instructions: NUMBER_OPTION_INSTRUCTIONS
582
+ });
583
+ processContext.exit(1);
584
+ return;
585
+ }
586
+ maxPolls = Math.max(1, Math.ceil(parsedTimeout.value * 1000 / pollInterval));
587
+ }
588
+ let inputs;
589
+ if (options.inputs) {
590
+ const { parseFlowInputs } = await import("./flow-api-wv8p8xbd.js");
591
+ const [parseError, parsed] = await catchError(parseFlowInputs(options.inputs));
592
+ if (parseError) {
593
+ OutputFormatter.error({
594
+ Result: RESULTS.Failure,
595
+ Message: `Failed to parse inputs: ${parseError.message}`,
596
+ Instructions: INPUT_INSTRUCTIONS
597
+ });
598
+ processContext.exit(1);
599
+ return;
600
+ }
601
+ inputs = parsed;
602
+ }
603
+ const attachmentSpecs = options.attachment ?? [];
604
+ if (attachmentSpecs.length > 0) {
605
+ const [parseError, specs] = catchError(() => attachmentSpecs.map(parseAttachmentSpec));
606
+ if (parseError) {
607
+ OutputFormatter.error({
608
+ Result: RESULTS.Failure,
609
+ Message: parseError.message,
610
+ Instructions: ATTACHMENT_INSTRUCTIONS
611
+ });
612
+ processContext.exit(1);
613
+ return;
614
+ }
615
+ const { uploadJobAttachment } = await import("./index-ev4mdg5y.js");
616
+ const [uploadError, resolved] = await catchError(resolveAttachmentInputs(specs, (bytes, fileName) => uploadJobAttachment(bytes, fileName, {
617
+ tenant: tenantName
618
+ })));
619
+ if (uploadError) {
620
+ OutputFormatter.error({
621
+ Result: RESULTS.Failure,
622
+ Message: uploadError.message,
623
+ Instructions: ATTACHMENT_UPLOAD_INSTRUCTIONS
624
+ });
625
+ processContext.exit(1);
626
+ return;
627
+ }
628
+ inputs = inputs ?? {};
629
+ for (const { name, path, reference } of resolved) {
630
+ if (name in inputs) {
631
+ logger.warn(`--attachment '${name}' overrides the value provided in --inputs.`);
632
+ }
633
+ inputs[name] = reference;
634
+ logger.info(`Uploaded '${path}' as attachment ${reference.ID} (variable '${name}').`);
635
+ }
636
+ }
637
+ if (inputs !== undefined) {
638
+ logger.info(`Inputs: ${JSON.stringify(inputs)}`);
639
+ }
640
+ const debugOptions = {
641
+ inputs,
642
+ ...maxPolls === undefined ? {} : { maxPolls },
643
+ ...isConversational ? { uploadOnly: true } : {}
644
+ };
645
+ logger.info(`Starting Studio Web debug session for: ${projectPath}`);
646
+ const [executeError, result] = await catchError(service.executeProjectViaStudioWeb(projectPath, studioWebConfig, {
647
+ onStatusChange: (st, executions) => {
648
+ const completed = executions.filter((e) => e.status === "Completed").length;
649
+ const total = executions.length;
650
+ logger.info(`Status: ${st} (${completed}/${total} elements completed)`);
651
+ for (const exec of executions) {
652
+ const icon = exec.status === "Completed" ? "v" : exec.status === "InProgress" ? ">" : "-";
653
+ logger.info(` ${icon} ${exec.elementId} [${exec.status}]`);
654
+ }
655
+ },
656
+ onIncident: (incidents2) => {
657
+ logger.warn(`Incidents: ${JSON.stringify(incidents2)}`);
658
+ },
659
+ onStudioWebUrl: (url) => {
660
+ if (options.openInBrowser !== true)
661
+ return;
662
+ if (urlReported)
663
+ return;
664
+ urlReported = true;
665
+ OutputFormatter.log({
666
+ Message: `Studio Web debug URL: ${url}`
667
+ });
668
+ openInBrowserOrWarn(url);
669
+ }
670
+ }, pollInterval, debugOptions));
671
+ if (executeError) {
672
+ if (executeError instanceof MissingSolutionWrapperError) {
673
+ OutputFormatter.error({
674
+ Result: RESULTS.ValidationError,
675
+ Message: executeError.message,
676
+ Instructions: executeError.instructions
677
+ });
678
+ processContext.exit(3);
679
+ return;
680
+ }
681
+ if (executeError instanceof InboundVoiceDebugError) {
682
+ OutputFormatter.error({
683
+ Result: RESULTS.ValidationError,
684
+ Message: executeError.message,
685
+ Instructions: executeError.instructions
686
+ });
687
+ processContext.exit(3);
688
+ return;
689
+ }
690
+ if (executeError instanceof UnregisteredProjectError) {
691
+ OutputFormatter.error({
692
+ Result: RESULTS.ValidationError,
693
+ Message: executeError.message,
694
+ Instructions: executeError.instructions
695
+ });
696
+ processContext.exit(3);
697
+ return;
698
+ }
699
+ if (executeError instanceof DebugPollTimeoutError) {
700
+ OutputFormatter.error(buildPollTimeoutFailureOutput(executeError, "uip maestro flow debug-instance incidents"));
701
+ } else if (executeError instanceof MaestroHttpError) {
702
+ OutputFormatter.error(buildHttpFailureOutput(executeError));
703
+ } else if (isSolutionUploadHttpError(executeError)) {
704
+ OutputFormatter.error(buildSolutionUploadFailureOutput(executeError, {
705
+ subject: "flow",
706
+ importCheckHint: "Run 'uip maestro flow validate' to confirm the project is well-formed."
707
+ }));
708
+ } else {
709
+ OutputFormatter.error({
710
+ Result: RESULTS.Failure,
711
+ Message: executeError.message,
712
+ Instructions: DEBUG_FAILURE_INSTRUCTIONS
713
+ });
714
+ }
715
+ processContext.exit(1);
716
+ return;
717
+ }
718
+ if ("uploadedOnly" in result) {
719
+ OutputFormatter.success({
720
+ Result: RESULTS.Success,
721
+ Code: "FlowDebugStudioWebHandoff",
722
+ Data: {
723
+ solutionId: result.solutionId,
724
+ studioWebUrl: result.studioWebUrl,
725
+ handedOff: true
726
+ },
727
+ Instructions: buildHandoffInstructions(result.studioWebUrl)
728
+ }, { preserveDataKeys: true });
729
+ processContext.exit(0);
730
+ return;
731
+ }
732
+ const success = isSuccessfulDebugStatus(result.finalStatus);
733
+ const data = {
734
+ jobKey: result.jobKey,
735
+ instanceId: result.instanceId,
736
+ runId: result.runId,
737
+ folderKey: result.folderKey,
738
+ finalStatus: result.finalStatus,
739
+ solutionId: result.solutionId,
740
+ studioWebUrl: result.studioWebUrl,
741
+ elementExecutions: result.elementExecutions,
742
+ variables: result.variables,
743
+ variablesError: result.variablesError,
744
+ incidents: result.incidents
745
+ };
746
+ if (success) {
747
+ const instructions = result.variablesError ? `Debug completed with status: ${result.finalStatus}, but the output variables could not be read after ${result.variablesError.attempts} attempt(s): ${result.variablesError.message}. ` + `Data.variables is absent and Data.variablesError explains why — treat the outputs as UNKNOWN, not empty. ` + `Retry with 'uip maestro flow debug-instance variables ${result.instanceId}'.` : `Debug completed with status: ${result.finalStatus}`;
748
+ OutputFormatter.success({
749
+ Result: RESULTS.Success,
750
+ Code: "FlowDebug",
751
+ Data: data,
752
+ Instructions: instructions
753
+ }, { preserveDataKeys: true });
754
+ processContext.exit(0);
755
+ return;
756
+ }
757
+ const incidents = result.incidents ?? [];
758
+ const summary = summarizeIncidents(incidents);
759
+ const Message = incidents.length ? `Debug session ${result.finalStatus}. ${summary[0]}` : `Debug session ${result.finalStatus}. No incident details returned by PIMS.`;
760
+ const Instructions = incidents.length ? buildIncidentInstructions(incidents, result.instanceId) : `Run 'uip maestro flow debug-instance incidents ${result.instanceId}' to inspect the backend payload, then 'uip maestro flow incident summary' to confirm whether the process recorded a tenant-level incident.`;
761
+ const Context = {};
762
+ if (incidents[0]?.errorCode) {
763
+ Context.errorCode = incidents[0].errorCode;
764
+ }
765
+ if (incidents[0]?.traceId) {
766
+ Context.traceId = incidents[0].traceId;
767
+ }
768
+ OutputFormatter.error({
769
+ Result: RESULTS.Failure,
770
+ Code: "FlowDebug",
771
+ Message,
772
+ Instructions,
773
+ ...Object.keys(Context).length > 0 ? { Context } : {},
774
+ Data: data
775
+ });
776
+ processContext.exit(1);
777
+ });
778
+ }
779
+ // src/commands/debug-instances.ts
780
+ var registerDebugInstancesCommand = (program) => {
781
+ registerSharedDebugInstanceCommands(program, {
782
+ toolLabel: "Flow"
783
+ });
784
+ };
785
+
786
+ // src/commands/edge.ts
787
+ var EDGE_LIST_EXAMPLES = [
788
+ {
789
+ Description: "List all edges in a flow file",
790
+ Command: "uip maestro flow edge list flow.json",
791
+ Output: {
792
+ Code: "EdgeListSuccess",
793
+ Data: {
794
+ Edges: [
795
+ {
796
+ id: "edge_a1b2c3d4",
797
+ source: "Node_1",
798
+ target: "Node_2"
799
+ }
800
+ ],
801
+ Count: 1
802
+ }
803
+ }
804
+ }
805
+ ];
806
+ var EDGE_ADD_EXAMPLES = [
807
+ {
808
+ Description: "Add an edge between two nodes in a flow",
809
+ Command: "uip maestro flow edge add flow.json Node_1 Node_2",
810
+ Output: {
811
+ Code: "EdgeAddSuccess",
812
+ Data: {
813
+ Edge: {
814
+ id: "edge_a1b2c3d4",
815
+ source: "Node_1",
816
+ target: "Node_2",
817
+ sourcePort: "output",
818
+ targetPort: "input"
819
+ }
820
+ }
821
+ }
822
+ },
823
+ {
824
+ Description: "Re-running with the same arguments is idempotent: returns the existing edge id with code EdgeAlreadyExists and a stderr warning.",
825
+ Command: "uip maestro flow edge add flow.json Node_1 Node_2",
826
+ Output: {
827
+ Code: "EdgeAlreadyExists",
828
+ Data: {
829
+ Edge: {
830
+ id: "edge_a1b2c3d4",
831
+ source: "Node_1",
832
+ target: "Node_2",
833
+ sourcePort: "output",
834
+ targetPort: "input"
835
+ }
836
+ }
837
+ }
838
+ }
839
+ ];
840
+ var EDGE_DELETE_EXAMPLES = [
841
+ {
842
+ Description: "Delete an edge by ID",
843
+ Command: "uip maestro flow edge delete flow.json edge_a1b2c3d4",
844
+ Output: {
845
+ Code: "EdgeDeleteSuccess",
846
+ Data: {
847
+ DeletedEdge: {
848
+ id: "edge_a1b2c3d4",
849
+ source: "Node_1",
850
+ target: "Node_2"
851
+ }
852
+ }
853
+ }
854
+ }
855
+ ];
856
+ var EDGE_REMOVE_EXAMPLES = [
857
+ {
858
+ Description: "Remove an edge by ID",
859
+ Command: "uip maestro flow edge remove flow.json edge_a1b2c3d4",
860
+ Output: {
861
+ Code: "EdgeRemoveSuccess",
862
+ Data: {
863
+ DeletedEdge: {
864
+ id: "edge_a1b2c3d4",
865
+ source: "Node_1",
866
+ target: "Node_2"
867
+ }
868
+ }
869
+ }
870
+ }
871
+ ];
872
+ function getDeleteEdgeInstructions(file) {
873
+ return `Check that "${file}" exists and run 'uip maestro flow edge list ${file}' to find a valid edge ID, then retry.`;
874
+ }
875
+ async function runDeleteEdge(file, edgeId, code) {
876
+ const { deleteEdgeFromFlow } = await import("./edge-service-e77bndbe.js");
877
+ const normalizedEdgeId = edgeId.trim();
878
+ const [error, result] = await catchError(deleteEdgeFromFlow(file, normalizedEdgeId));
879
+ if (error) {
880
+ OutputFormatter.error({
881
+ Result: RESULTS.Failure,
882
+ Message: "Error deleting edge",
883
+ Instructions: getDeleteEdgeInstructions(file)
884
+ });
885
+ processContext.exit(1);
886
+ return;
887
+ }
888
+ OutputFormatter.success({
889
+ Result: RESULTS.Success,
890
+ Code: code,
891
+ Data: {
892
+ DeletedEdge: result.deletedEdge
893
+ }
894
+ });
895
+ }
896
+ var registerEdgeCommand = (program) => {
897
+ const edge = program.command("edge").description("Manage edges in a Flow file");
898
+ edge.command("list").description("List all edges in a Flow file").argument("<file>", "Path to the .flow file").examples(EDGE_LIST_EXAMPLES).trackedAction(processContext, async (file) => {
899
+ const { listEdgesInFlow } = await import("./edge-service-e77bndbe.js");
900
+ const [error, result] = await catchError(listEdgesInFlow(file));
901
+ if (error) {
902
+ OutputFormatter.error({
903
+ Result: RESULTS.Failure,
904
+ Message: "Error listing edges",
905
+ Instructions: error.message
906
+ });
907
+ processContext.exit(1);
908
+ return;
909
+ }
910
+ OutputFormatter.success({
911
+ Result: RESULTS.Success,
912
+ Code: "EdgeListSuccess",
913
+ Data: {
914
+ Edges: result.edges,
915
+ Count: result.count
916
+ }
917
+ });
918
+ });
919
+ edge.command("add").description("Add an edge between two nodes in a Flow file").argument("<file>", "Path to the .flow file").argument("<source-id>", "ID of the source node").argument("<target-id>", "ID of the target node").option("--source-port <port>", 'Source port name (defaults to "output")').option("--target-port <port>", 'Target port name (defaults to "input")').examples(EDGE_ADD_EXAMPLES).trackedAction(processContext, async (file, sourceId, targetId, options) => {
920
+ const { addEdgeToFlow } = await import("./edge-service-e77bndbe.js");
921
+ const [error, result] = await catchError(addEdgeToFlow(file, sourceId, targetId, {
922
+ sourcePort: options.sourcePort,
923
+ targetPort: options.targetPort
924
+ }));
925
+ if (error) {
926
+ OutputFormatter.error({
927
+ Result: RESULTS.Failure,
928
+ Message: "Error adding edge",
929
+ Instructions: error.message
930
+ });
931
+ processContext.exit(1);
932
+ return;
933
+ }
934
+ if (result.alreadyExists) {
935
+ const warning = `Edge already exists with id "${result.edge.id}" for (${result.edge.sourceNodeId}:${result.edge.sourcePort} -> ${result.edge.targetNodeId}:${result.edge.targetPort}). No changes written.`;
936
+ logger.warn(warning);
937
+ OutputFormatter.success({
938
+ Result: RESULTS.Success,
939
+ Code: "EdgeAlreadyExists",
940
+ Instructions: warning,
941
+ Data: {
942
+ Edge: result.edge
943
+ }
944
+ });
945
+ return;
946
+ }
947
+ OutputFormatter.success({
948
+ Result: RESULTS.Success,
949
+ Code: "EdgeAddSuccess",
950
+ Data: {
951
+ Edge: result.edge
952
+ }
953
+ });
954
+ });
955
+ edge.command("delete").description(`Delete an edge from a Flow file.
956
+ Use 'uip maestro flow edge list' to find the edge ID.`).argument("<file>", "Path to the .flow file").argument("<edge-id>", "ID of the edge to delete").examples(EDGE_DELETE_EXAMPLES).trackedAction(processContext, async (file, edgeId) => runDeleteEdge(file, edgeId, "EdgeDeleteSuccess"));
957
+ edge.command("remove").description(`Remove an edge from a Flow file.
958
+ Alias for 'edge delete'. Use 'uip maestro flow edge list' to find the edge ID.`).argument("<file>", "Path to the .flow file").argument("<edge-id>", "ID of the edge to remove").examples(EDGE_REMOVE_EXAMPLES).trackedAction(processContext, async (file, edgeId) => runDeleteEdge(file, edgeId, "EdgeRemoveSuccess"));
959
+ };
960
+
961
+ // src/services/flow-eval-run-format.ts
962
+ function formatDuration(durationMs) {
963
+ if (durationMs === null || durationMs === undefined) {
964
+ return "-";
965
+ }
966
+ return `${(durationMs / 1000).toFixed(1)}s`;
967
+ }
968
+ function formatEvaluatorScores(scores, evaluators) {
969
+ if (!scores || scores.length === 0) {
970
+ return "-";
971
+ }
972
+ return scores.map((score) => {
973
+ const evaluator = evaluators.find((item) => item.id === score.evaluatorId);
974
+ return `${evaluator?.name ?? score.evaluatorId}: ${score.value}`;
975
+ }).join(", ");
976
+ }
977
+ function evaluatorSnapshotName(snapshot) {
978
+ if (typeof snapshot === "object" && snapshot !== null && !Array.isArray(snapshot) && typeof snapshot.name === "string") {
979
+ return snapshot.name;
980
+ }
981
+ return;
982
+ }
983
+ function remoteEvaluatorName(evaluatorId, evaluatorSnapshot, evaluators) {
984
+ return evaluators.find((item) => item.id === evaluatorId)?.name ?? evaluatorSnapshotName(evaluatorSnapshot) ?? evaluatorId;
985
+ }
986
+ function remoteRunScore(run) {
987
+ if (run.result?.scores && run.result.scores.length > 0) {
988
+ const sum = run.result.scores.reduce((total, score) => total + score.value, 0);
989
+ return Number((sum / run.result.scores.length).toFixed(4));
990
+ }
991
+ const value = run.result?.score?.value;
992
+ return typeof value === "number" || typeof value === "boolean" ? value : "-";
993
+ }
994
+ function formatRemoteEvalRunRow(run, evaluators, verbose = false) {
995
+ let evaluatorScores = "-";
996
+ let justifications = "-";
997
+ if (run.evaluatorRuns && run.evaluatorRuns.length > 0) {
998
+ evaluatorScores = run.evaluatorRuns.map((evaluatorRun) => {
999
+ const name = remoteEvaluatorName(evaluatorRun.evaluatorId, evaluatorRun.evaluatorSnapshot, evaluators);
1000
+ const score = evaluatorRun.result?.score;
1001
+ if (score?.type === "error") {
1002
+ return `${name}: Error`;
1003
+ }
1004
+ return `${name}: ${score?.value ?? "-"}`;
1005
+ }).join(", ");
1006
+ const justificationParts = run.evaluatorRuns.filter((evaluatorRun) => evaluatorRun.result?.score?.justification).map((evaluatorRun) => {
1007
+ const name = remoteEvaluatorName(evaluatorRun.evaluatorId, evaluatorRun.evaluatorSnapshot, evaluators);
1008
+ return `[${name}] ${evaluatorRun.result?.score?.justification}`;
1009
+ });
1010
+ if (justificationParts.length > 0) {
1011
+ justifications = justificationParts.join(" | ");
1012
+ }
1013
+ } else if (run.result?.scores && run.result.scores.length > 0) {
1014
+ evaluatorScores = formatEvaluatorScores(run.result.scores, evaluators);
1015
+ }
1016
+ const tokens = run.completionMetrics?.tokens;
1017
+ const duration = run.completionMetrics?.duration;
1018
+ const error = run.errorMessage ?? (typeof run.error === "string" ? run.error : run.error?.message) ?? "-";
1019
+ const row = {
1020
+ DataPoint: run.evalSnapshot?.name ?? run.id,
1021
+ Status: run.status,
1022
+ Score: remoteRunScore(run),
1023
+ EvaluatorScores: evaluatorScores,
1024
+ Tokens: typeof tokens === "number" && tokens > 0 ? tokens : "-",
1025
+ Duration: typeof duration === "number" ? formatDuration(duration) : "-",
1026
+ Error: error
1027
+ };
1028
+ if (verbose) {
1029
+ row.Justifications = justifications;
1030
+ }
1031
+ return row;
1032
+ }
1033
+ function isFailedRemoteRun(run) {
1034
+ const status = run.status.toLowerCase();
1035
+ if (status === "failed" || status === "workloadfailed" || run.errorMessage || run.error) {
1036
+ return true;
1037
+ }
1038
+ if (run.result?.score?.type === "error") {
1039
+ return true;
1040
+ }
1041
+ return run.evaluatorRuns?.some((evaluatorRun) => evaluatorRun.result?.score?.type === "error" || evaluatorRun.result?.score?.value === false) ?? false;
1042
+ }
1043
+ function isTerminalRemoteStatus(status) {
1044
+ return ["completed", "partiallycompleted", "failed"].includes(status.toLowerCase());
1045
+ }
1046
+ function formatEvalSetRunRow(run, evaluators) {
1047
+ return {
1048
+ EvalSetRunId: run.id,
1049
+ Status: run.status,
1050
+ Score: run.score ?? "-",
1051
+ DataPoints: run.numberOfEvalsExecuted ?? "-",
1052
+ Duration: formatDuration(run.durationMilliseconds),
1053
+ EvaluatorScores: formatEvaluatorScores(run.evaluatorScores, evaluators),
1054
+ CreatedAt: run.createdAt
1055
+ };
1056
+ }
1057
+
1058
+ // src/commands/eval-run.ts
1059
+ var FLOW_EVAL_PATH_OPTION_DESCRIPTION = "Path to a Flow project directory, or a solution directory with exactly one Flow project";
1060
+ var POLL_INTERVAL_MS = 5000;
1061
+ var POLL_TIMEOUT_MS = 600000;
1062
+ var FLOW_EVAL_RUN_START_EXAMPLES = [
1063
+ {
1064
+ Description: "Start a Studio Web Flow evaluation run",
1065
+ Command: 'uip maestro flow eval run start --set "Default Evaluation Set" --path ./my-solution/Flow',
1066
+ Output: {
1067
+ Code: "FlowEvalRunStarted",
1068
+ Data: {
1069
+ EvalSetRunId: "a1b2c3d4-0000-0000-0000-000000000101",
1070
+ EvalSetName: "Default Evaluation Set",
1071
+ DataPoints: 3,
1072
+ Evaluators: 2
1073
+ }
1074
+ }
1075
+ }
1076
+ ];
1077
+ var FLOW_EVAL_RUN_STATUS_EXAMPLES = [
1078
+ {
1079
+ Description: "Check the status of a Studio Web Flow evaluation run",
1080
+ Command: 'uip maestro flow eval run status a1b2c3d4-0000-0000-0000-000000000101 --set "Default Evaluation Set" --path ./my-solution/Flow',
1081
+ Output: {
1082
+ Code: "FlowEvalRunStatus",
1083
+ Data: {
1084
+ EvalSetRunId: "a1b2c3d4-0000-0000-0000-000000000101",
1085
+ Status: "Completed",
1086
+ Score: 0.86,
1087
+ Duration: "42.5s"
1088
+ }
1089
+ }
1090
+ }
1091
+ ];
1092
+ var FLOW_EVAL_RUN_RESULTS_EXAMPLES = [
1093
+ {
1094
+ Description: "Show detailed per-data-point results for a Flow run",
1095
+ Command: 'uip maestro flow eval run results a1b2c3d4-0000-0000-0000-000000000101 --set "Default Evaluation Set" --path ./my-solution/Flow',
1096
+ Output: {
1097
+ Code: "FlowEvalRunResults",
1098
+ Data: [
1099
+ {
1100
+ DataPoint: "simple-greeting",
1101
+ Status: "completed",
1102
+ EvaluatorScores: "Exact: true",
1103
+ Duration: "1.8s",
1104
+ Error: "-"
1105
+ }
1106
+ ]
1107
+ }
1108
+ }
1109
+ ];
1110
+ var FLOW_EVAL_RUN_LIST_EXAMPLES = [
1111
+ {
1112
+ Description: "List Studio Web evaluation runs for a Flow eval set",
1113
+ Command: 'uip maestro flow eval run list --set "Default Evaluation Set" --path ./my-solution/Flow',
1114
+ Output: {
1115
+ Code: "FlowEvalRunList",
1116
+ Data: [
1117
+ {
1118
+ EvalSetRunId: "a1b2c3d4-0000-0000-0000-000000000101",
1119
+ Status: "Completed",
1120
+ Score: 0.86,
1121
+ DataPoints: 3,
1122
+ Duration: "42.5s",
1123
+ CreatedAt: "2026-04-15T10:30:00Z"
1124
+ }
1125
+ ]
1126
+ }
1127
+ }
1128
+ ];
1129
+ var FLOW_EVAL_RUN_COMPARE_EXAMPLES = [
1130
+ {
1131
+ Description: "Compare two Studio Web Flow evaluation runs",
1132
+ Command: 'uip maestro flow eval run compare a1b2c3d4-0000-0000-0000-000000000101 --compare-to a1b2c3d4-0000-0000-0000-000000000102 --set "Default Evaluation Set" --path ./my-solution/Flow',
1133
+ Output: {
1134
+ Code: "FlowEvalRunComparison",
1135
+ Data: {
1136
+ RunA: {
1137
+ Id: "a1b2c3d4-0000-0000-0000-000000000101",
1138
+ Score: 0.86,
1139
+ Status: "Completed"
1140
+ },
1141
+ RunB: {
1142
+ Id: "a1b2c3d4-0000-0000-0000-000000000102",
1143
+ Score: 0.8,
1144
+ Status: "Completed"
1145
+ },
1146
+ ScoreDelta: 0.06
1147
+ }
1148
+ }
1149
+ }
1150
+ ];
1151
+ function addTargetOptions(command) {
1152
+ return command.requiredOption("--set <name>", "Evaluation set name or ID").option("--solution-id <id>", "Solution ID from Studio Web").option("--project-id <id>", "Flow project ID from Studio Web (reads from parent .uipx or SolutionStorage.json if not provided)").option("--path <path>", FLOW_EVAL_PATH_OPTION_DESCRIPTION, ".");
1153
+ }
1154
+ function addStartOptions(command) {
1155
+ return addTargetOptions(command).option("--entry-point <entry>", "Flow entry point path (/Main.bpmn#start) or start node ID").option("--folder-key <key>", "Orchestrator folder key. Uses the personal workspace if not provided.").option("--debug-mode <mode>", "Studio Web debug mode override", (value) => Number.parseInt(value, 10));
1156
+ }
1157
+ function outputError(message, error) {
1158
+ OutputFormatter.error({
1159
+ Result: RESULTS.Failure,
1160
+ Message: message,
1161
+ Instructions: error.message
1162
+ });
1163
+ processContext.exit(1);
1164
+ }
1165
+ async function resolveStudioWebConfig() {
1166
+ const { getLoginStatusAsync } = await import("./index-1kgxzh8x.js");
1167
+ const [loginError, login] = await catchError(getLoginStatusAsync());
1168
+ if (loginError) {
1169
+ throw new Error(loginError.message);
1170
+ }
1171
+ if (login.loginStatus !== "Logged in" || !login.baseUrl) {
1172
+ throw new Error("Not logged in. Run 'uip login' first.");
1173
+ }
1174
+ if (!login.organizationId) {
1175
+ throw new Error("Organization ID not available from login.");
1176
+ }
1177
+ if (!login.tenantId) {
1178
+ throw new Error("Tenant ID not available from login.");
1179
+ }
1180
+ if (!login.tenantName) {
1181
+ throw new Error("Tenant name not available from login.");
1182
+ }
1183
+ if (!login.accessToken) {
1184
+ throw new Error("Access token not available from login.");
1185
+ }
1186
+ if (!login.organizationName) {
1187
+ throw new Error("Organization name not available from login. Required for Studio Web evaluation.");
1188
+ }
1189
+ return {
1190
+ baseUrl: login.baseUrl,
1191
+ organizationId: login.organizationId,
1192
+ tenantId: login.tenantId,
1193
+ tenantName: login.tenantName,
1194
+ authToken: login.accessToken,
1195
+ organizationName: login.organizationName
1196
+ };
1197
+ }
1198
+ async function pollRemoteEvalSetRun(service, config, workloadId, evalSetRunId, timeoutMs) {
1199
+ const start = Date.now();
1200
+ while (Date.now() - start < timeoutMs) {
1201
+ const [error, run] = await catchError(service.getRemoteEvalSetRun(config, workloadId, evalSetRunId));
1202
+ if (error) {
1203
+ OutputFormatter.log({
1204
+ Message: `Polling error: ${error.message}. Retrying...`
1205
+ });
1206
+ } else if (run) {
1207
+ if (isTerminalRemoteStatus(run.status)) {
1208
+ return run;
1209
+ }
1210
+ OutputFormatter.log({
1211
+ Message: `Status: ${run.status}... (${Math.round((Date.now() - start) / 1000)}s)`
1212
+ });
1213
+ }
1214
+ await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
1215
+ }
1216
+ throw new Error(`Evaluation timed out after ${timeoutMs / 1000} seconds`);
1217
+ }
1218
+ async function outputCompletedRemoteRun(service, config, projectPath, startResult, timeoutSeconds) {
1219
+ const timeoutMs = timeoutSeconds !== undefined ? timeoutSeconds * 1000 : POLL_TIMEOUT_MS;
1220
+ const finalRun = await pollRemoteEvalSetRun(service, config, startResult.context.workloadId, startResult.evalSetRunId, timeoutMs);
1221
+ const [evalRuns, evaluators] = await Promise.all([
1222
+ service.getRemoteEvalRuns(config, startResult.context.workloadId, startResult.evalSetRunId),
1223
+ service.listEvaluators(projectPath)
1224
+ ]);
1225
+ OutputFormatter.success({
1226
+ Result: RESULTS.Success,
1227
+ Code: "FlowEvalRunCompleted",
1228
+ Data: {
1229
+ Status: finalRun.status,
1230
+ Score: finalRun.score ?? "-",
1231
+ Duration: formatDuration(finalRun.durationMilliseconds),
1232
+ EvaluatorScores: formatEvaluatorScores(finalRun.evaluatorScores, evaluators),
1233
+ DataPoints: evalRuns.length
1234
+ }
1235
+ });
1236
+ if (evalRuns.length > 0) {
1237
+ OutputFormatter.success({
1238
+ Result: RESULTS.Success,
1239
+ Code: "FlowEvalRunResults",
1240
+ Data: evalRuns.map((run) => formatRemoteEvalRunRow(run, evaluators))
1241
+ });
1242
+ }
1243
+ }
1244
+ async function exportRows(exportFormat, rows) {
1245
+ const fs = getFileSystem();
1246
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
1247
+ if (exportFormat === "json") {
1248
+ const filePath = fs.path.resolve(`flow-eval-results-${timestamp}.json`);
1249
+ await fs.writeFile(filePath, JSON.stringify(rows, null, 2));
1250
+ OutputFormatter.success({
1251
+ Result: RESULTS.Success,
1252
+ Code: "FlowEvalRunExported",
1253
+ Data: { Format: "json", File: filePath, Records: rows.length }
1254
+ });
1255
+ return;
1256
+ }
1257
+ if (exportFormat === "csv") {
1258
+ const filePath = fs.path.resolve(`flow-eval-results-${timestamp}.csv`);
1259
+ const headers = Object.keys(rows[0] ?? {});
1260
+ const csvRows = [
1261
+ headers.join(","),
1262
+ ...rows.map((row) => headers.map((header) => {
1263
+ const value = String(row[header] ?? "");
1264
+ return value.includes(",") || value.includes('"') || value.includes(`
1265
+ `) ? `"${value.replace(/"/g, '""')}"` : value;
1266
+ }).join(","))
1267
+ ];
1268
+ await fs.writeFile(filePath, csvRows.join(`
1269
+ `));
1270
+ OutputFormatter.success({
1271
+ Result: RESULTS.Success,
1272
+ Code: "FlowEvalRunExported",
1273
+ Data: { Format: "csv", File: filePath, Records: rows.length }
1274
+ });
1275
+ return;
1276
+ }
1277
+ throw new Error(`Unknown export format "${exportFormat}". Use "json" or "csv".`);
1278
+ }
1279
+ async function resolveRemoteTarget(service, options, config, requireSolutionId = false) {
1280
+ return service.resolveRemoteEvalTarget(options.path, options.set, {
1281
+ solutionId: options.solutionId,
1282
+ projectId: options.projectId
1283
+ }, requireSolutionId, config);
1284
+ }
1285
+ function registerEvalRunCommand(evalCmd) {
1286
+ const runCmd = evalCmd.command("run").description("Run Flow evaluation sets in Studio Web");
1287
+ addStartOptions(runCmd.command("start").description("Start a Studio Web evaluation run (Flow solution must be available in Studio Web)")).option("--wait", "Wait for the evaluation to complete and show results").option("--timeout <seconds>", "Timeout in seconds for --wait polling", (value) => Number.parseInt(value, 10)).examples(FLOW_EVAL_RUN_START_EXAMPLES).trackedAction(processContext, async (options) => {
1288
+ const [error] = await catchError((async () => {
1289
+ const config = await resolveStudioWebConfig();
1290
+ const { FlowEvalRunService } = await import("./flow-eval-run-service-01kdky72.js");
1291
+ const service = new FlowEvalRunService;
1292
+ const result = await service.startRemoteEvalRun(options.path, options.set, config, {
1293
+ solutionId: options.solutionId,
1294
+ projectId: options.projectId,
1295
+ entryPoint: options.entryPoint,
1296
+ folderKey: options.folderKey,
1297
+ debugMode: options.debugMode
1298
+ });
1299
+ OutputFormatter.success({
1300
+ Result: RESULTS.Success,
1301
+ Code: "FlowEvalRunStarted",
1302
+ Data: {
1303
+ EvalSetRunId: result.evalSetRunId,
1304
+ EvalSetName: result.evalSetName,
1305
+ DataPoints: result.dataPoints,
1306
+ Evaluators: result.evaluators,
1307
+ Status: result.status
1308
+ },
1309
+ Instructions: options.wait ? "Waiting for completion..." : `Monitor with: uip maestro flow eval run status ${result.evalSetRunId} --set "${options.set}" --path ${options.path}`
1310
+ });
1311
+ if (options.wait) {
1312
+ await outputCompletedRemoteRun(service, config, options.path, result, options.timeout);
1313
+ }
1314
+ })());
1315
+ if (error) {
1316
+ outputError("Failed to start flow evaluation run", error);
1317
+ }
1318
+ });
1319
+ addTargetOptions(runCmd.command("status").description("Check the status of a Studio Web Flow evaluation run").argument("<evalSetRunId>", "Evaluation set run ID")).examples(FLOW_EVAL_RUN_STATUS_EXAMPLES).trackedAction(processContext, async (evalSetRunId, options) => {
1320
+ const [error] = await catchError((async () => {
1321
+ const config = await resolveStudioWebConfig();
1322
+ const { FlowEvalRunService } = await import("./flow-eval-run-service-01kdky72.js");
1323
+ const service = new FlowEvalRunService;
1324
+ const target = await resolveRemoteTarget(service, options, config);
1325
+ const [run, evaluators] = await Promise.all([
1326
+ service.getRemoteEvalSetRun(config, target.workloadId, evalSetRunId),
1327
+ service.listEvaluators(target.projectPath)
1328
+ ]);
1329
+ OutputFormatter.success({
1330
+ Result: RESULTS.Success,
1331
+ Code: "FlowEvalRunStatus",
1332
+ Data: {
1333
+ EvalSetRunId: run.id,
1334
+ Status: run.status,
1335
+ Score: run.score ?? "-",
1336
+ Duration: formatDuration(run.durationMilliseconds),
1337
+ EvaluatorScores: formatEvaluatorScores(run.evaluatorScores, evaluators)
1338
+ }
1339
+ });
1340
+ })());
1341
+ if (error) {
1342
+ outputError("Failed to get flow evaluation run status", error);
1343
+ }
1344
+ });
1345
+ addTargetOptions(runCmd.command("results").description("Get detailed results for a Studio Web Flow evaluation run").argument("<evalSetRunId>", "Evaluation set run ID")).option("--only-failed", "Show only failed or errored data points").option("--verbose", "Include evaluator justifications in output").option("--export-format <json|csv>", "Export results to file (json or csv)").examples(FLOW_EVAL_RUN_RESULTS_EXAMPLES).trackedAction(processContext, async (evalSetRunId, options) => {
1346
+ const [error] = await catchError((async () => {
1347
+ const config = await resolveStudioWebConfig();
1348
+ const { FlowEvalRunService } = await import("./flow-eval-run-service-01kdky72.js");
1349
+ const service = new FlowEvalRunService;
1350
+ const target = await resolveRemoteTarget(service, options, config);
1351
+ let evalRuns = await service.getRemoteEvalRuns(config, target.workloadId, evalSetRunId);
1352
+ if (options.onlyFailed) {
1353
+ evalRuns = evalRuns.filter(isFailedRemoteRun);
1354
+ }
1355
+ if (evalRuns.length === 0) {
1356
+ OutputFormatter.success({
1357
+ Result: RESULTS.Success,
1358
+ Code: "FlowEvalRunResults",
1359
+ Data: []
1360
+ });
1361
+ return;
1362
+ }
1363
+ const evaluators = await service.listEvaluators(target.projectPath);
1364
+ const rows = evalRuns.map((run) => formatRemoteEvalRunRow(run, evaluators, options.verbose));
1365
+ if (options.exportFormat) {
1366
+ await exportRows(options.exportFormat, rows);
1367
+ return;
1368
+ }
1369
+ OutputFormatter.success({
1370
+ Result: RESULTS.Success,
1371
+ Code: "FlowEvalRunResults",
1372
+ Data: rows
1373
+ });
1374
+ })());
1375
+ if (error) {
1376
+ outputError("Failed to get flow evaluation results", error);
1377
+ }
1378
+ });
1379
+ addTargetOptions(runCmd.command("list").description("List Studio Web evaluation runs for a Flow eval set")).examples(FLOW_EVAL_RUN_LIST_EXAMPLES).trackedAction(processContext, async (options) => {
1380
+ const [error] = await catchError((async () => {
1381
+ const config = await resolveStudioWebConfig();
1382
+ const { FlowEvalRunService } = await import("./flow-eval-run-service-01kdky72.js");
1383
+ const service = new FlowEvalRunService;
1384
+ const target = await resolveRemoteTarget(service, options, config);
1385
+ const runs = await service.listRemoteEvalSetRuns(config, target.workloadId, target.evalSet.id);
1386
+ if (runs.length === 0) {
1387
+ OutputFormatter.success({
1388
+ Result: RESULTS.Success,
1389
+ Code: "FlowEvalRunList",
1390
+ Data: []
1391
+ });
1392
+ return;
1393
+ }
1394
+ const evaluators = await service.listEvaluators(target.projectPath);
1395
+ OutputFormatter.success({
1396
+ Result: RESULTS.Success,
1397
+ Code: "FlowEvalRunList",
1398
+ Data: runs.map((run) => formatEvalSetRunRow(run, evaluators))
1399
+ });
1400
+ })());
1401
+ if (error) {
1402
+ outputError("Failed to list flow evaluation runs", error);
1403
+ }
1404
+ });
1405
+ addTargetOptions(runCmd.command("compare").description("Compare results of two Studio Web Flow evaluation runs").argument("<evalSetRunId>", "First evaluation set run ID").requiredOption("--compare-to <id>", "Second evaluation set run ID to compare against")).examples(FLOW_EVAL_RUN_COMPARE_EXAMPLES).trackedAction(processContext, async (evalSetRunId, options) => {
1406
+ const [error] = await catchError((async () => {
1407
+ const config = await resolveStudioWebConfig();
1408
+ const { FlowEvalRunService } = await import("./flow-eval-run-service-01kdky72.js");
1409
+ const service = new FlowEvalRunService;
1410
+ const target = await resolveRemoteTarget(service, options, config);
1411
+ const [runsA, runsB, runMetaA, runMetaB] = await Promise.all([
1412
+ service.getRemoteEvalRuns(config, target.workloadId, evalSetRunId),
1413
+ service.getRemoteEvalRuns(config, target.workloadId, options.compareTo),
1414
+ service.getRemoteEvalSetRun(config, target.workloadId, evalSetRunId),
1415
+ service.getRemoteEvalSetRun(config, target.workloadId, options.compareTo)
1416
+ ]);
1417
+ OutputFormatter.success({
1418
+ Result: RESULTS.Success,
1419
+ Code: "FlowEvalRunComparison",
1420
+ Data: buildComparison(evalSetRunId, options.compareTo, runMetaA, runMetaB, runsA, runsB)
1421
+ });
1422
+ })());
1423
+ if (error) {
1424
+ outputError("Failed to compare flow evaluation runs", error);
1425
+ }
1426
+ });
1427
+ }
1428
+ function buildComparison(evalSetRunId, compareTo, runMetaA, runMetaB, runsA, runsB) {
1429
+ const runsBByName = new Map;
1430
+ for (const run of runsB) {
1431
+ runsBByName.set(run.evalSnapshot?.name ?? run.id, run);
1432
+ }
1433
+ const dataPoints = runsA.map((runA) => {
1434
+ const name = runA.evalSnapshot?.name ?? runA.id;
1435
+ const runB = runsBByName.get(name);
1436
+ const scoreA = remoteRunScore(runA);
1437
+ const scoreB = runB ? remoteRunScore(runB) : "-";
1438
+ let delta = "-";
1439
+ if (typeof scoreA === "number" && typeof scoreB === "number") {
1440
+ delta = Number((scoreA - scoreB).toFixed(4));
1441
+ }
1442
+ return {
1443
+ DataPoint: name,
1444
+ ScoreA: scoreA,
1445
+ ScoreB: scoreB,
1446
+ Delta: delta,
1447
+ StatusA: runA.status,
1448
+ StatusB: runB?.status ?? "-"
1449
+ };
1450
+ });
1451
+ return {
1452
+ RunA: {
1453
+ Id: evalSetRunId,
1454
+ Score: runMetaA.score ?? "-",
1455
+ Status: runMetaA.status
1456
+ },
1457
+ RunB: {
1458
+ Id: compareTo,
1459
+ Score: runMetaB.score ?? "-",
1460
+ Status: runMetaB.status
1461
+ },
1462
+ ScoreDelta: typeof runMetaA.score === "number" && typeof runMetaB.score === "number" ? Number((runMetaA.score - runMetaB.score).toFixed(4)) : "-",
1463
+ DataPoints: dataPoints
1464
+ };
1465
+ }
1466
+
1467
+ // src/commands/eval.ts
1468
+ var FLOW_EVAL_PATH_OPTION_DESCRIPTION2 = "Path to a Flow project directory, or a solution directory with exactly one Flow project";
1469
+ function parseJsonValue(raw, label) {
1470
+ try {
1471
+ return JSON.parse(raw);
1472
+ } catch (err) {
1473
+ const message = err instanceof Error ? err.message : String(err);
1474
+ throw new Error(`Invalid JSON for ${label}: ${message}`);
1475
+ }
1476
+ }
1477
+ function parseJsonObject(raw, label) {
1478
+ const parsed = JSON.parse(raw);
1479
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
1480
+ throw new Error(`${label} must be a JSON object`);
1481
+ }
1482
+ return parsed;
1483
+ }
1484
+ function parseCriteriaOption(raw) {
1485
+ const parsed = parseJsonObject(raw, "--criteria");
1486
+ const criteria = {};
1487
+ for (const [key, value] of Object.entries(parsed)) {
1488
+ if (value === null || value === undefined) {
1489
+ criteria[key] = value;
1490
+ } else if (typeof value === "object" && !Array.isArray(value)) {
1491
+ criteria[key] = value;
1492
+ } else {
1493
+ throw new Error(`--criteria value for "${key}" must be a JSON object or null`);
1494
+ }
1495
+ }
1496
+ return criteria;
1497
+ }
1498
+ function parseCommaSeparated(value) {
1499
+ if (value === undefined) {
1500
+ return;
1501
+ }
1502
+ return value.split(",").map((item) => item.trim()).filter(Boolean);
1503
+ }
1504
+ function collectInputFile(value, previous) {
1505
+ return [...previous, value];
1506
+ }
1507
+ function parseInputFiles(raw) {
1508
+ return raw.map((entry) => {
1509
+ const eq = entry.indexOf("=");
1510
+ if (eq <= 0 || eq === entry.length - 1) {
1511
+ throw new Error(`--input-file must be "<key>=<path>" (got "${entry}")`);
1512
+ }
1513
+ const key = entry.slice(0, eq).trim();
1514
+ const sourcePath = entry.slice(eq + 1).trim();
1515
+ if (!key || !sourcePath) {
1516
+ throw new Error(`--input-file must be "<key>=<path>" (got "${entry}")`);
1517
+ }
1518
+ return { key, sourcePath };
1519
+ });
1520
+ }
1521
+ function outputError2(message, error) {
1522
+ OutputFormatter.error({
1523
+ Result: RESULTS.Failure,
1524
+ Message: message,
1525
+ Instructions: error.message
1526
+ });
1527
+ processContext.exit(1);
1528
+ }
1529
+ function registerEvalCommand(program) {
1530
+ const evalCmd = program.command("eval").description("Manage and run Flow evaluation sets");
1531
+ registerEvaluatorCommands(evalCmd);
1532
+ registerEvalSetCommands(evalCmd);
1533
+ registerEvaluationCommands(evalCmd);
1534
+ registerSimulationCommands(evalCmd);
1535
+ registerEvalRunCommand(evalCmd);
1536
+ }
1537
+ function registerEvaluatorCommands(evalCmd) {
1538
+ const evaluator = evalCmd.command("evaluator").description("Manage Flow evaluators");
1539
+ evaluator.command("add").description("Add an evaluator to the flow project").argument("<name>", "Evaluator name").requiredOption("--type <type>", `Evaluator type: ${evaluatorTypeAliases().join(", ")}`).option("--description <text>", "Evaluator description").option("--target-key <key>", "Target output key", "*").option("--model <model>", "LLM model for LLM judge evaluators").option("--prompt <prompt>", "Custom LLM judge prompt").option("--path <path>", FLOW_EVAL_PATH_OPTION_DESCRIPTION2, ".").trackedAction(processContext, async (name, options) => {
1540
+ const [error] = await catchError((async () => {
1541
+ const { FlowEvalService } = await import("./flow-eval-service-ft8e16jz.js");
1542
+ const service = new FlowEvalService;
1543
+ const created = await service.addEvaluator(options.path, {
1544
+ name,
1545
+ type: options.type,
1546
+ description: options.description,
1547
+ targetOutputKey: options.targetKey,
1548
+ model: options.model,
1549
+ prompt: options.prompt
1550
+ });
1551
+ OutputFormatter.success({
1552
+ Result: RESULTS.Success,
1553
+ Code: "FlowEvalEvaluatorAdd",
1554
+ Data: {
1555
+ Name: created.name,
1556
+ Id: created.id,
1557
+ Type: created.evaluatorTypeId,
1558
+ File: created.fileName
1559
+ }
1560
+ });
1561
+ })());
1562
+ if (error) {
1563
+ outputError2("Failed to add evaluator", error);
1564
+ }
1565
+ });
1566
+ evaluator.command("list").description("List evaluators in a flow project").option("--path <path>", FLOW_EVAL_PATH_OPTION_DESCRIPTION2, ".").trackedAction(processContext, async (options) => {
1567
+ const [error] = await catchError((async () => {
1568
+ const { FlowEvalService } = await import("./flow-eval-service-ft8e16jz.js");
1569
+ const service = new FlowEvalService;
1570
+ const evaluators = await service.listEvaluators(options.path);
1571
+ OutputFormatter.success({
1572
+ Result: RESULTS.Success,
1573
+ Code: "FlowEvalEvaluatorList",
1574
+ Data: evaluators.map((item) => ({
1575
+ Name: item.name ?? String(item.evaluatorConfig.name ?? ""),
1576
+ Id: item.id,
1577
+ Type: item.evaluatorTypeId,
1578
+ TargetKey: item.evaluatorConfig.targetOutputKey ?? "*",
1579
+ File: item.fileName
1580
+ }))
1581
+ });
1582
+ })());
1583
+ if (error) {
1584
+ outputError2("Failed to list evaluators", error);
1585
+ }
1586
+ });
1587
+ evaluator.command("remove").description("Remove an evaluator from a flow project").argument("<id>", "Evaluator ID, name, or file base name").option("--path <path>", FLOW_EVAL_PATH_OPTION_DESCRIPTION2, ".").trackedAction(processContext, async (id, options) => {
1588
+ const [error] = await catchError((async () => {
1589
+ const { FlowEvalService } = await import("./flow-eval-service-ft8e16jz.js");
1590
+ const service = new FlowEvalService;
1591
+ const removed = await service.removeEvaluator(options.path, id);
1592
+ if (!removed) {
1593
+ throw new Error(`Evaluator "${id}" not found`);
1594
+ }
1595
+ OutputFormatter.success({
1596
+ Result: RESULTS.Success,
1597
+ Code: "FlowEvalEvaluatorRemove",
1598
+ Data: { Status: "Evaluator removed", Id: id }
1599
+ });
1600
+ })());
1601
+ if (error) {
1602
+ outputError2("Failed to remove evaluator", error);
1603
+ }
1604
+ });
1605
+ }
1606
+ function registerEvalSetCommands(evalCmd) {
1607
+ const set = evalCmd.command("set").description("Manage evaluation sets");
1608
+ set.command("add").description("Create an evaluation set").argument("<name>", "Evaluation set name").option("--evaluators <refs>", "Comma-separated evaluator IDs or file base names (default: all)").option("--entry-point <id>", "Entry point node id stored as the eval set's selectedEntrypoint. An agent node id creates a node-scoped eval set (evaluates that node in isolation)").option("--path <path>", FLOW_EVAL_PATH_OPTION_DESCRIPTION2, ".").trackedAction(processContext, async (name, options) => {
1609
+ const [error] = await catchError((async () => {
1610
+ const { FlowEvalService } = await import("./flow-eval-service-ft8e16jz.js");
1611
+ const { readEvalSetScope, readNodeTargetId } = await import("./flow-eval-node-target-c6wea7rz.js");
1612
+ const service = new FlowEvalService;
1613
+ const created = await service.addEvalSet(options.path, {
1614
+ name,
1615
+ evaluatorRefs: parseCommaSeparated(options.evaluators),
1616
+ entryPoint: options.entryPoint
1617
+ });
1618
+ const targetNode = readNodeTargetId(created);
1619
+ OutputFormatter.success({
1620
+ Result: RESULTS.Success,
1621
+ Code: "FlowEvalSetAdd",
1622
+ Data: {
1623
+ Name: created.name,
1624
+ Id: created.id,
1625
+ Evaluators: created.evaluatorRefs.length,
1626
+ File: created.fileName,
1627
+ Scope: readEvalSetScope(created),
1628
+ ...targetNode !== undefined ? { TargetNode: targetNode } : {}
1629
+ }
1630
+ });
1631
+ })());
1632
+ if (error) {
1633
+ outputError2("Failed to create evaluation set", error);
1634
+ }
1635
+ });
1636
+ set.command("list").description("List evaluation sets").option("--path <path>", FLOW_EVAL_PATH_OPTION_DESCRIPTION2, ".").trackedAction(processContext, async (options) => {
1637
+ const [error] = await catchError((async () => {
1638
+ const { FlowEvalService } = await import("./flow-eval-service-ft8e16jz.js");
1639
+ const { readEvalSetScope, readNodeTargetId } = await import("./flow-eval-node-target-c6wea7rz.js");
1640
+ const service = new FlowEvalService;
1641
+ const sets = await service.listEvalSets(options.path);
1642
+ OutputFormatter.success({
1643
+ Result: RESULTS.Success,
1644
+ Code: "FlowEvalSetList",
1645
+ Data: sets.map((item) => {
1646
+ const targetNode = readNodeTargetId(item);
1647
+ return {
1648
+ Name: item.name,
1649
+ Id: item.id,
1650
+ DataPoints: item.evaluations.length,
1651
+ Evaluators: item.evaluatorRefs.length,
1652
+ File: item.fileName,
1653
+ Scope: readEvalSetScope(item),
1654
+ ...targetNode !== undefined ? { TargetNode: targetNode } : {}
1655
+ };
1656
+ })
1657
+ });
1658
+ })());
1659
+ if (error) {
1660
+ outputError2("Failed to list evaluation sets", error);
1661
+ }
1662
+ });
1663
+ set.command("remove").description("Remove an evaluation set").argument("<id>", "Evaluation set ID, name, or file base name").option("--path <path>", FLOW_EVAL_PATH_OPTION_DESCRIPTION2, ".").trackedAction(processContext, async (id, options) => {
1664
+ const [error] = await catchError((async () => {
1665
+ const { FlowEvalService } = await import("./flow-eval-service-ft8e16jz.js");
1666
+ const service = new FlowEvalService;
1667
+ const removed = await service.removeEvalSet(options.path, id);
1668
+ if (!removed) {
1669
+ throw new Error(`Evaluation set "${id}" not found`);
1670
+ }
1671
+ OutputFormatter.success({
1672
+ Result: RESULTS.Success,
1673
+ Code: "FlowEvalSetRemove",
1674
+ Data: { Status: "Evaluation set removed", Id: id }
1675
+ });
1676
+ })());
1677
+ if (error) {
1678
+ outputError2("Failed to remove evaluation set", error);
1679
+ }
1680
+ });
1681
+ }
1682
+ function registerEvaluationCommands(evalCmd) {
1683
+ evalCmd.command("add").description("Add a data point to an evaluation set").argument("<name>", "Data point name").requiredOption("--set <name>", "Evaluation set name or ID").option("--inputs <json>", "Input values as a JSON object").option("--input-file <key=path>", "Attach a file as input <key>; repeatable", collectInputFile, []).option("--expected <json>", "Expected output as a JSON object").option("--criteria <json>", "Per-evaluator criteria JSON object keyed by evaluator id").option("--search-text <text>", "Search text for contains evaluators").option("--path <path>", FLOW_EVAL_PATH_OPTION_DESCRIPTION2, ".").trackedAction(processContext, async (name, options) => {
1684
+ const [error] = await catchError((async () => {
1685
+ if (options.inputs === undefined && options.inputFile.length === 0) {
1686
+ throw new Error("Provide --inputs and/or --input-file");
1687
+ }
1688
+ const inputs = options.inputs === undefined ? {} : parseJsonObject(options.inputs, "--inputs");
1689
+ const inputFiles = parseInputFiles(options.inputFile);
1690
+ const expectedOutput = options.expected ? parseJsonObject(options.expected, "--expected") : undefined;
1691
+ const criteria = options.criteria ? parseCriteriaOption(options.criteria) : undefined;
1692
+ const { FlowEvalService } = await import("./flow-eval-service-ft8e16jz.js");
1693
+ const service = new FlowEvalService;
1694
+ const evaluation = await service.addEvaluation(options.path, options.set, {
1695
+ name,
1696
+ inputs,
1697
+ inputFiles,
1698
+ expectedOutput,
1699
+ criteria,
1700
+ searchText: options.searchText
1701
+ });
1702
+ OutputFormatter.success({
1703
+ Result: RESULTS.Success,
1704
+ Code: "FlowEvalAdd",
1705
+ Data: {
1706
+ Status: "Data point added",
1707
+ Name: evaluation.name,
1708
+ Id: evaluation.id,
1709
+ Set: options.set
1710
+ }
1711
+ });
1712
+ })());
1713
+ if (error) {
1714
+ outputError2("Failed to add evaluation data point", error);
1715
+ }
1716
+ });
1717
+ evalCmd.command("list").description("List data points in an evaluation set").requiredOption("--set <name>", "Evaluation set name or ID").option("--path <path>", FLOW_EVAL_PATH_OPTION_DESCRIPTION2, ".").trackedAction(processContext, async (options) => {
1718
+ const [error] = await catchError((async () => {
1719
+ const { FlowEvalService } = await import("./flow-eval-service-ft8e16jz.js");
1720
+ const service = new FlowEvalService;
1721
+ const evaluations = await service.listEvaluations(options.path, options.set);
1722
+ OutputFormatter.success({
1723
+ Result: RESULTS.Success,
1724
+ Code: "FlowEvalList",
1725
+ Data: evaluations.map((item) => ({
1726
+ Name: item.name,
1727
+ Id: item.id,
1728
+ Inputs: JSON.stringify(item.inputs),
1729
+ Expected: item.expectedOutput ? JSON.stringify(item.expectedOutput) : "-",
1730
+ Evaluators: Object.keys(item.evaluationCriterias ?? {}).length
1731
+ }))
1732
+ });
1733
+ })());
1734
+ if (error) {
1735
+ outputError2("Failed to list evaluation data points", error);
1736
+ }
1737
+ });
1738
+ evalCmd.command("remove").description("Remove a data point from an evaluation set").argument("<id>", "Data point ID or name").requiredOption("--set <name>", "Evaluation set name or ID").option("--path <path>", FLOW_EVAL_PATH_OPTION_DESCRIPTION2, ".").trackedAction(processContext, async (id, options) => {
1739
+ const [error] = await catchError((async () => {
1740
+ const { FlowEvalService } = await import("./flow-eval-service-ft8e16jz.js");
1741
+ const service = new FlowEvalService;
1742
+ const removed = await service.removeEvaluation(options.path, options.set, id);
1743
+ if (!removed) {
1744
+ throw new Error(`Data point "${id}" not found`);
1745
+ }
1746
+ OutputFormatter.success({
1747
+ Result: RESULTS.Success,
1748
+ Code: "FlowEvalRemove",
1749
+ Data: { Status: "Data point removed", Id: id }
1750
+ });
1751
+ })());
1752
+ if (error) {
1753
+ outputError2("Failed to remove evaluation data point", error);
1754
+ }
1755
+ });
1756
+ }
1757
+ function registerSimulationCommands(evalCmd) {
1758
+ const simulation = evalCmd.command("simulation").description("Manage simulations on eval data points");
1759
+ simulation.command("add").description("Add or update a simulation on a data point").argument("<component-id>", "Component ID to simulate").requiredOption("--set <name>", "Evaluation set name or ID").requiredOption("--data-point <id>", "Data point name or ID").requiredOption("--strategy <strategy>", "Simulation strategy: Static or Llm").option("--component-type <type>", "Component type (defaults to Node when --parent is used)").option("--component-description <text>", "Component description").option("--simulation-instructions <text>", "Simulation instructions (for Llm strategy)").option("--mock-value <json>", "Mock output value as JSON (for Static strategy)").option("--parent <component-id>", "Parent agent component ID. When set, the simulation is added as a child tool simulation on the parent agent node.").option("--path <path>", FLOW_EVAL_PATH_OPTION_DESCRIPTION2, ".").trackedAction(processContext, async (componentId, options) => {
1760
+ const [error] = await catchError((async () => {
1761
+ const strategy = options.strategy;
1762
+ if (strategy !== "Static" && strategy !== "Llm") {
1763
+ throw new Error(`--strategy must be Static or Llm (got "${strategy}")`);
1764
+ }
1765
+ const componentType = options.componentType ?? (options.parent !== undefined ? "Node" : undefined);
1766
+ if (componentType === undefined) {
1767
+ throw new Error("--component-type is required (or use --parent to default to Node)");
1768
+ }
1769
+ if (strategy === "Static" && options.mockValue === undefined) {
1770
+ throw new Error("--mock-value is required for the Static strategy");
1771
+ }
1772
+ if (strategy === "Llm" && options.simulationInstructions === undefined) {
1773
+ throw new Error("--simulation-instructions is required for the Llm strategy");
1774
+ }
1775
+ const mockValue = options.mockValue !== undefined ? parseJsonValue(options.mockValue, "--mock-value") : undefined;
1776
+ const simulation2 = {
1777
+ componentId,
1778
+ componentType,
1779
+ componentDescription: options.componentDescription,
1780
+ simulationStrategy: strategy,
1781
+ simulationInstruction: options.simulationInstructions,
1782
+ mockValue
1783
+ };
1784
+ const { FlowEvalService } = await import("./flow-eval-service-ft8e16jz.js");
1785
+ const service = new FlowEvalService;
1786
+ if (options.parent !== undefined) {
1787
+ const created = await service.addChildSimulation(options.path, options.set, options.dataPoint, options.parent, simulation2);
1788
+ OutputFormatter.success({
1789
+ Result: RESULTS.Success,
1790
+ Code: "FlowEvalChildSimulationAdd",
1791
+ Data: {
1792
+ ComponentId: created.componentId,
1793
+ ComponentType: created.componentType,
1794
+ Strategy: created.simulationStrategy,
1795
+ Parent: options.parent,
1796
+ DataPoint: options.dataPoint,
1797
+ Set: options.set
1798
+ }
1799
+ });
1800
+ } else {
1801
+ const created = await service.addSimulation(options.path, options.set, options.dataPoint, simulation2);
1802
+ OutputFormatter.success({
1803
+ Result: RESULTS.Success,
1804
+ Code: "FlowEvalSimulationAdd",
1805
+ Data: {
1806
+ ComponentId: created.componentId,
1807
+ ComponentType: created.componentType,
1808
+ Strategy: created.simulationStrategy,
1809
+ DataPoint: options.dataPoint,
1810
+ Set: options.set
1811
+ }
1812
+ });
1813
+ }
1814
+ })());
1815
+ if (error) {
1816
+ outputError2("Failed to add simulation", error);
1817
+ }
1818
+ });
1819
+ simulation.command("list").description("List simulations on a data point").requiredOption("--set <name>", "Evaluation set name or ID").requiredOption("--data-point <id>", "Data point name or ID").option("--parent <component-id>", "Parent agent component ID. When set, lists child tool simulations on the parent agent node.").option("--path <path>", FLOW_EVAL_PATH_OPTION_DESCRIPTION2, ".").trackedAction(processContext, async (options) => {
1820
+ const [error] = await catchError((async () => {
1821
+ const { FlowEvalService } = await import("./flow-eval-service-ft8e16jz.js");
1822
+ const service = new FlowEvalService;
1823
+ const simulations = options.parent !== undefined ? await service.listChildSimulations(options.path, options.set, options.dataPoint, options.parent) : await service.listSimulations(options.path, options.set, options.dataPoint);
1824
+ OutputFormatter.success({
1825
+ Result: RESULTS.Success,
1826
+ Code: options.parent !== undefined ? "FlowEvalChildSimulationList" : "FlowEvalSimulationList",
1827
+ Data: simulations.map((s) => ({
1828
+ ComponentId: s.componentId,
1829
+ ComponentType: s.componentType,
1830
+ ComponentDescription: s.componentDescription ?? "-",
1831
+ Strategy: s.simulationStrategy,
1832
+ Instruction: s.simulationInstruction ?? "-",
1833
+ ...options.parent !== undefined ? { Parent: options.parent } : {}
1834
+ }))
1835
+ });
1836
+ })());
1837
+ if (error) {
1838
+ outputError2("Failed to list simulations", error);
1839
+ }
1840
+ });
1841
+ simulation.command("remove").description("Remove a simulation from a data point").argument("<component-id>", "Component ID to remove").requiredOption("--set <name>", "Evaluation set name or ID").requiredOption("--data-point <id>", "Data point name or ID").option("--parent <component-id>", "Parent agent component ID. When set, removes a child tool simulation from the parent agent node.").option("--path <path>", FLOW_EVAL_PATH_OPTION_DESCRIPTION2, ".").trackedAction(processContext, async (componentId, options) => {
1842
+ const [error] = await catchError((async () => {
1843
+ const { FlowEvalService } = await import("./flow-eval-service-ft8e16jz.js");
1844
+ const service = new FlowEvalService;
1845
+ const removed = options.parent !== undefined ? await service.removeChildSimulation(options.path, options.set, options.dataPoint, options.parent, componentId) : await service.removeSimulation(options.path, options.set, options.dataPoint, componentId);
1846
+ if (!removed) {
1847
+ throw new Error(options.parent !== undefined ? `Child simulation for component "${componentId}" not found on parent "${options.parent}"` : `Simulation for component "${componentId}" not found`);
1848
+ }
1849
+ OutputFormatter.success({
1850
+ Result: RESULTS.Success,
1851
+ Code: options.parent !== undefined ? "FlowEvalChildSimulationRemove" : "FlowEvalSimulationRemove",
1852
+ Data: {
1853
+ Status: options.parent !== undefined ? "Child simulation removed" : "Simulation removed",
1854
+ ComponentId: componentId,
1855
+ ...options.parent !== undefined ? { Parent: options.parent } : {}
1856
+ }
1857
+ });
1858
+ })());
1859
+ if (error) {
1860
+ outputError2("Failed to remove simulation", error);
1861
+ }
1862
+ });
1863
+ }
1864
+
1865
+ // src/commands/hitl.ts
1866
+ var VALID_PRIORITIES = ["Low", "Medium", "High"];
1867
+ function parsePosition(value) {
1868
+ const parts = value.split(",");
1869
+ if (parts.length !== 2) {
1870
+ throw new Error(`Invalid position format: "${value}". Expected "x,y" (e.g. 250,150)`);
1871
+ }
1872
+ const x = Number(parts[0]);
1873
+ const y = Number(parts[1]);
1874
+ if (Number.isNaN(x) || Number.isNaN(y)) {
1875
+ throw new Error(`Invalid position values: "${value}". x and y must be numbers`);
1876
+ }
1877
+ return { x, y };
1878
+ }
1879
+ function parsePositionOption(raw) {
1880
+ return catchError(() => parsePosition(raw));
1881
+ }
1882
+ function parseSchemaOption(raw) {
1883
+ const [parseErr, parsed] = catchError(() => JSON.parse(raw));
1884
+ if (parseErr)
1885
+ return [parseErr, undefined];
1886
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
1887
+ return [new Error("--schema must be a JSON object"), undefined];
1888
+ }
1889
+ const obj = parsed;
1890
+ for (const key of ["inputs", "outputs", "inOuts", "outcomes"]) {
1891
+ const val = obj[key];
1892
+ if (val === undefined)
1893
+ continue;
1894
+ if (!Array.isArray(val)) {
1895
+ return [new Error(`--schema "${key}" must be an array`), undefined];
1896
+ }
1897
+ const missing = val.findIndex((item) => item === null || typeof item !== "object" || typeof item.name !== "string");
1898
+ if (missing !== -1) {
1899
+ return [
1900
+ new Error(`--schema "${key}[${missing}]" must have a "name" string field`),
1901
+ undefined
1902
+ ];
1903
+ }
1904
+ }
1905
+ return [undefined, parsed];
1906
+ }
1907
+ var FLOW_HITL_ADD_EXAMPLES = [
1908
+ {
1909
+ Description: "Add a bare HITL node with no schema fields",
1910
+ Command: "uip maestro flow hitl add workflow.flow",
1911
+ Output: {
1912
+ Code: "HitlNodeAdded",
1913
+ Data: {
1914
+ NodeId: "humanInTheLoop1",
1915
+ NodeType: "uipath.human-in-the-loop",
1916
+ Label: "Human in the Loop",
1917
+ DefinitionAdded: true
1918
+ }
1919
+ }
1920
+ },
1921
+ {
1922
+ Description: "Add a HITL node with label, priority, and group assignee",
1923
+ Command: 'uip maestro flow hitl add workflow.flow --label "Invoice Review" --priority High --assignee finance-approvers',
1924
+ Output: {
1925
+ Code: "HitlNodeAdded",
1926
+ Data: {
1927
+ NodeId: "invoiceReview1",
1928
+ NodeType: "uipath.human-in-the-loop",
1929
+ Label: "Invoice Review",
1930
+ DefinitionAdded: true
1931
+ }
1932
+ }
1933
+ },
1934
+ {
1935
+ Description: "Add a HITL node with full schema (inputs, outputs, and outcomes)",
1936
+ Command: `uip maestro flow hitl add workflow.flow --label "Approval" --schema '{"inputs":[{"name":"invoiceId","binding":"fetchInvoice1.result.invoiceId"}],"outputs":[{"name":"decision","required":true}],"outcomes":[{"name":"Approve"},{"name":"Reject"}]}'`,
1937
+ Output: {
1938
+ Code: "HitlNodeAdded",
1939
+ Data: {
1940
+ NodeId: "approval1",
1941
+ NodeType: "uipath.human-in-the-loop",
1942
+ Label: "Approval",
1943
+ DefinitionAdded: true
1944
+ }
1945
+ }
1946
+ }
1947
+ ];
1948
+ var registerHitlCommand = (program) => {
1949
+ const hitl = program.command("hitl").description("Add HITL (Human-in-the-Loop) nodes to a Flow file");
1950
+ hitl.command("add").description("Add a Human-in-the-Loop node to a .flow file. Pauses flow execution and waits for a human to complete a task in Action Center.").argument("<file>", "Path to the .flow file").option("--schema <json>", 'Task schema. inputs pre-fill from flow variables (add "binding":"varName"), outputs write back (add "variable":"varName"). ' + `e.g. '{"title":"Invoice Approval","inputs":[{"name":"invoiceId"}],"outputs":[{"name":"decision","variable":"approvalDecision","required":true}],"outcomes":[{"name":"Approve"},{"name":"Reject"}]}'`).option("--priority <level>", "Task priority: Low, Medium, High (default: Low)").option("--position <x,y>", "Canvas position for the node (e.g. 250,300)").option("--label <label>", "Display label for the node").option("--assignee <email-or-group>", "Assignment criteria: user email (e.g. reviewer@company.com) or group name (e.g. finance-approvers)").examples(FLOW_HITL_ADD_EXAMPLES).trackedAction(processContext, async (file, options) => {
1951
+ if (options.priority !== undefined && !VALID_PRIORITIES.includes(options.priority)) {
1952
+ OutputFormatter.error({
1953
+ Result: RESULTS.Failure,
1954
+ Message: "Invalid priority",
1955
+ Instructions: `Priority must be one of: ${VALID_PRIORITIES.join(", ")}`
1956
+ });
1957
+ processContext.exit(1);
1958
+ return;
1959
+ }
1960
+ let position;
1961
+ if (options.position !== undefined) {
1962
+ const [posError, parsed] = parsePositionOption(options.position);
1963
+ if (posError) {
1964
+ OutputFormatter.error({
1965
+ Result: RESULTS.Failure,
1966
+ Message: "Invalid --position value",
1967
+ Instructions: extractErrorMessageSync(posError)
1968
+ });
1969
+ processContext.exit(1);
1970
+ return;
1971
+ }
1972
+ position = parsed;
1973
+ }
1974
+ let schema;
1975
+ if (options.schema !== undefined) {
1976
+ const [schemaError, parsed] = parseSchemaOption(options.schema);
1977
+ if (schemaError) {
1978
+ OutputFormatter.error({
1979
+ Result: RESULTS.Failure,
1980
+ Message: "Invalid --schema JSON",
1981
+ Instructions: extractErrorMessageSync(schemaError)
1982
+ });
1983
+ processContext.exit(1);
1984
+ return;
1985
+ }
1986
+ schema = parsed;
1987
+ }
1988
+ const { addHitlNode } = await import("./hitl-service-kvt5wms4.js");
1989
+ const [error, result] = await catchError(addHitlNode(file, {
1990
+ schema,
1991
+ priority: options.priority,
1992
+ position,
1993
+ label: options.label,
1994
+ assignee: options.assignee
1995
+ }));
1996
+ if (error) {
1997
+ OutputFormatter.error({
1998
+ Result: RESULTS.Failure,
1999
+ Message: "Failed to add HITL node",
2000
+ Instructions: extractErrorMessageSync(error)
2001
+ });
2002
+ processContext.exit(1);
2003
+ return;
2004
+ }
2005
+ OutputFormatter.success({
2006
+ Result: RESULTS.Success,
2007
+ Code: "HitlNodeAdded",
2008
+ Data: {
2009
+ NodeId: result.nodeId,
2010
+ NodeType: result.nodeType,
2011
+ Label: result.label,
2012
+ DefinitionAdded: result.definitionAdded
2013
+ }
2014
+ });
2015
+ });
2016
+ };
2017
+
2018
+ // src/commands/incidents.ts
2019
+ var registerIncidentsCommand = (program) => {
2020
+ registerSharedIncidentCommands(program, {
2021
+ toolLabel: "Flow"
2022
+ });
2023
+ };
2024
+
2025
+ // src/commands/init.ts
2026
+ var FLOW_INIT_EXAMPLES = [
2027
+ {
2028
+ Description: "Create a new flow project. If the current directory is not already inside a solution, a parent solution named '<project>Solution' is created automatically and the flow project is nested inside it.",
2029
+ Command: "uip maestro flow init my-flow-project",
2030
+ Output: {
2031
+ Code: "FlowInit",
2032
+ Data: {
2033
+ Status: "Created successfully",
2034
+ Path: "/workspace/my-flow-projectSolution/my-flow-project",
2035
+ SolutionRegistration: {
2036
+ Status: "Registered",
2037
+ Message: "Project registered in parent solution.",
2038
+ Solution: "/workspace/my-flow-projectSolution/my-flow-projectSolution.uipx",
2039
+ Project: "my-flow-project/project.uiproj",
2040
+ ProjectId: "00000000-0000-0000-0000-000000000000",
2041
+ Instructions: `The project is listed in the parent solution manifest.
2042
+ Packing or uploading the solution will sync solution resources automatically.`
2043
+ },
2044
+ AutoCreatedSolution: {
2045
+ Name: "my-flow-projectSolution",
2046
+ Path: "/workspace/my-flow-projectSolution",
2047
+ SolutionFile: "/workspace/my-flow-projectSolution/my-flow-projectSolution.uipx"
2048
+ },
2049
+ ProjectArtifacts: { Created: true },
2050
+ NextSteps: `The project is listed in the parent solution manifest.
2051
+ Packing or uploading the solution will sync solution resources automatically.`
2052
+ }
2053
+ }
2054
+ }
2055
+ ];
2056
+ var registerInitCommand = (program) => {
2057
+ program.command("init").description("Create a new Flow project with boilerplate files. If run outside an existing solution, a parent '<name>Solution' is scaffolded automatically and the flow project is created inside it. If run inside an existing solution, the project is added to that solution.").argument("<name>", "Flow project name").option("--force", "Force initialization even if target directory exists and is not empty").option("--skip-solution-registration", "Do not auto-register this project in the surrounding solution").examples(FLOW_INIT_EXAMPLES).trackedAction(processContext, async (name, options) => {
2058
+ const { flowInitAsync } = await import("./flow-init-service-mva4crty.js");
2059
+ const [error, result] = await catchError(flowInitAsync(name, {
2060
+ force: options.force,
2061
+ skipRegistration: options.skipSolutionRegistration === true
2062
+ }));
2063
+ if (error) {
2064
+ OutputFormatter.error({
2065
+ Result: RESULTS.Failure,
2066
+ Message: "Failed to create flow project",
2067
+ Instructions: error.message
2068
+ });
2069
+ processContext.exit(1);
2070
+ return;
2071
+ }
2072
+ const data = {
2073
+ Status: "Created successfully",
2074
+ Path: result.projectDir,
2075
+ SolutionRegistration: result.registration
2076
+ };
2077
+ if (result.autoCreatedSolution) {
2078
+ data.AutoCreatedSolution = result.autoCreatedSolution;
2079
+ }
2080
+ if (result.projectArtifacts) {
2081
+ data.ProjectArtifacts = result.projectArtifacts;
2082
+ }
2083
+ if (result.registration.Instructions) {
2084
+ data.NextSteps = result.registration.Instructions;
2085
+ }
2086
+ OutputFormatter.success({
2087
+ Result: RESULTS.Success,
2088
+ Code: "FlowInit",
2089
+ Data: data
2090
+ });
2091
+ });
2092
+ };
2093
+
2094
+ // src/commands/instances.ts
2095
+ var registerInstancesCommand = (program) => {
2096
+ registerSharedInstanceCommands(program, {
2097
+ toolLabel: "Flow",
2098
+ assetType: "flow",
2099
+ processType: "Flow"
2100
+ });
2101
+ };
2102
+
2103
+ // src/commands/job.ts
2104
+ var VALID_JOB_STATES = [
2105
+ "Pending",
2106
+ "Running",
2107
+ "Successful",
2108
+ "Faulted",
2109
+ "Stopped",
2110
+ "Stopping",
2111
+ "Suspended",
2112
+ "Resumed",
2113
+ "Terminating"
2114
+ ];
2115
+ var DEFAULT_JOB_LIST_LIMIT = "50";
2116
+ var DEFAULT_JOB_LIST_OFFSET = "0";
2117
+ var DEFAULT_JOB_LIST_ORDER_BY = "Id desc";
2118
+ var FLOW_JOB_LIST_EXAMPLES = [
2119
+ {
2120
+ Description: "List recent Flow jobs in a folder",
2121
+ Command: "uip maestro flow job list --folder-key c3d4e5f6-0000-0000-0000-000000000001 --limit 2",
2122
+ Output: {
2123
+ Code: "FlowJobList",
2124
+ Data: [
2125
+ {
2126
+ key: "b2c3d4e5-0000-0000-0000-000000000001",
2127
+ state: "Successful",
2128
+ processName: "InvoiceFlow",
2129
+ source: "Manual",
2130
+ startTime: "2025-04-15T10:30:00Z",
2131
+ endTime: "2025-04-15T10:32:11Z"
2132
+ }
2133
+ ]
2134
+ }
2135
+ }
2136
+ ];
2137
+ var FLOW_JOB_STATUS_EXAMPLES = [
2138
+ {
2139
+ Description: "Get detailed status of a flow job",
2140
+ Command: "uip maestro flow job status b2c3d4e5-0000-0000-0000-000000000001",
2141
+ Output: {
2142
+ Code: "FlowJobStatus",
2143
+ Data: {
2144
+ key: "b2c3d4e5-0000-0000-0000-000000000001",
2145
+ state: "Successful",
2146
+ startTime: "2025-04-15T10:30:00Z",
2147
+ endTime: "2025-04-15T10:32:11Z",
2148
+ releaseName: "InvoiceFlow",
2149
+ processKey: "a1b2c3d4-0000-0000-0000-000000000001"
2150
+ }
2151
+ }
2152
+ }
2153
+ ];
2154
+ var FLOW_JOB_TRACES_ERROR_INSTRUCTIONS = "Check that the job started successfully and that traces are available before calling this command.";
2155
+ function parsePositiveInteger(value, flag) {
2156
+ const candidate = value ?? "";
2157
+ if (!/^\d+$/.test(candidate)) {
2158
+ throw new Error(`Invalid ${flag} value`);
2159
+ }
2160
+ const parsed = Number.parseInt(candidate, 10);
2161
+ if (parsed <= 0) {
2162
+ throw new Error(`Invalid ${flag} value`);
2163
+ }
2164
+ return parsed;
2165
+ }
2166
+ function parseNonNegativeInteger(value, flag) {
2167
+ const candidate = value ?? "";
2168
+ if (!/^\d+$/.test(candidate)) {
2169
+ throw new Error(`Invalid ${flag} value`);
2170
+ }
2171
+ return Number.parseInt(candidate, 10);
2172
+ }
2173
+ function normalizeOptionalOption(value) {
2174
+ return value === undefined ? undefined : value.trim();
2175
+ }
2176
+ function formatDate(value) {
2177
+ if (!value) {
2178
+ return "";
2179
+ }
2180
+ const date = value instanceof Date ? value : new Date(value);
2181
+ return Number.isNaN(date.getTime()) ? String(value) : date.toISOString();
2182
+ }
2183
+ function formatFlowJob(job) {
2184
+ return {
2185
+ key: job.key ?? "",
2186
+ state: job.state ?? "",
2187
+ processName: job.releaseName ?? "",
2188
+ releaseKey: job.release?.key ?? "",
2189
+ processKey: job.release?.processKey ?? "",
2190
+ source: job.sourceType ?? "",
2191
+ type: job.type ?? "",
2192
+ priority: job.jobPriority ?? "",
2193
+ machine: job.hostMachineName ?? "",
2194
+ machineKey: job.machine?.key ?? "",
2195
+ folderKey: job.folderKey ?? "",
2196
+ startTime: formatDate(job.startTime),
2197
+ endTime: formatDate(job.endTime),
2198
+ creationTime: formatDate(job.creationTime)
2199
+ };
2200
+ }
2201
+ function registerJobCommand(program) {
2202
+ const jobCmd = program.command("job").description("Manage Flow jobs");
2203
+ jobCmd.command("list").description("List Flow jobs in a folder").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).option("--folder-key <key>", "Folder key (GUID, defaults to authenticated folder)").option("--state <state>", `Filter by job state (${VALID_JOB_STATES.join(", ")})`).option("--process-name <name>", "Filter by Flow process name (contains match)").option("-l, --limit <number>", "Number of items to return", DEFAULT_JOB_LIST_LIMIT).option("--offset <number>", "Number of items to skip", DEFAULT_JOB_LIST_OFFSET).option("--sort-by <field>", "Sort results by field (e.g., 'Id desc')", DEFAULT_JOB_LIST_ORDER_BY).option("--all-fields", "Return all fields from the API response instead of a curated summary").option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", (value) => Number.parseInt(value, 10), 10).examples(FLOW_JOB_LIST_EXAMPLES).trackedAction(processContext, async (options) => {
2204
+ const { getLoginStatusAsync } = await import("./index-1kgxzh8x.js");
2205
+ const [loginError, loginStatus] = await catchError(getLoginStatusAsync({
2206
+ ensureTokenValidityMinutes: options.loginValidity
2207
+ }));
2208
+ if (loginError) {
2209
+ OutputFormatter.error({
2210
+ Result: RESULTS.Failure,
2211
+ Message: loginError.message,
2212
+ Instructions: instructionsFor("auth", loginError)
2213
+ });
2214
+ processContext.exit(1);
2215
+ return;
2216
+ }
2217
+ if (loginStatus.loginStatus !== "Logged in" || !loginStatus.baseUrl) {
2218
+ OutputFormatter.error({
2219
+ Result: RESULTS.Failure,
2220
+ Message: "Not logged in. Run 'uip login' first.",
2221
+ Instructions: instructionsFor("auth")
2222
+ });
2223
+ processContext.exit(1);
2224
+ return;
2225
+ }
2226
+ const normalizedOptions = {
2227
+ tenant: normalizeOptionalOption(options.tenant),
2228
+ folderKey: normalizeOptionalOption(options.folderKey),
2229
+ state: normalizeOptionalOption(options.state),
2230
+ processName: normalizeOptionalOption(options.processName),
2231
+ orderBy: normalizeOptionalOption(options.sortBy)
2232
+ };
2233
+ const tenantName = normalizedOptions.tenant || loginStatus.tenantName;
2234
+ if (!tenantName || !loginStatus.organizationId) {
2235
+ OutputFormatter.error({
2236
+ Result: RESULTS.Failure,
2237
+ Message: "Missing tenant or organization info.",
2238
+ Instructions: instructionsFor("identity")
2239
+ });
2240
+ processContext.exit(1);
2241
+ return;
2242
+ }
2243
+ const state = normalizedOptions.state;
2244
+ if (state && !VALID_JOB_STATES.includes(state)) {
2245
+ OutputFormatter.error({
2246
+ Result: RESULTS.Failure,
2247
+ Message: "Invalid --state value.",
2248
+ Instructions: `Use one of: ${VALID_JOB_STATES.join(", ")}.`
2249
+ });
2250
+ processContext.exit(1);
2251
+ return;
2252
+ }
2253
+ let limit;
2254
+ let offset;
2255
+ try {
2256
+ limit = parsePositiveInteger(options.limit ?? DEFAULT_JOB_LIST_LIMIT, "--limit");
2257
+ offset = parseNonNegativeInteger(options.offset ?? DEFAULT_JOB_LIST_OFFSET, "--offset");
2258
+ } catch (error) {
2259
+ OutputFormatter.error({
2260
+ Result: RESULTS.Failure,
2261
+ Message: error instanceof Error ? error.message : "Invalid pagination value.",
2262
+ Instructions: "Use a positive integer for --limit and a non-negative integer for --offset."
2263
+ });
2264
+ processContext.exit(1);
2265
+ return;
2266
+ }
2267
+ const config = {
2268
+ processKey: "",
2269
+ folderKey: normalizedOptions.folderKey ?? "",
2270
+ inputs: {},
2271
+ authToken: loginStatus.accessToken ?? "",
2272
+ organizationId: loginStatus.organizationId,
2273
+ tenantName,
2274
+ tenantId: loginStatus.tenantId,
2275
+ baseUrl: loginStatus.baseUrl
2276
+ };
2277
+ const { listFlowJobs } = await import("./flow-api-wv8p8xbd.js");
2278
+ const [listError, jobs] = await catchError(listFlowJobs(config, {
2279
+ state,
2280
+ processName: normalizedOptions.processName,
2281
+ limit,
2282
+ offset,
2283
+ orderBy: normalizedOptions.orderBy || DEFAULT_JOB_LIST_ORDER_BY
2284
+ }));
2285
+ if (listError) {
2286
+ OutputFormatter.error({
2287
+ Result: RESULTS.Failure,
2288
+ Message: listError.message,
2289
+ Instructions: instructionsFor("backend", listError)
2290
+ });
2291
+ processContext.exit(1);
2292
+ return;
2293
+ }
2294
+ const items = jobs ?? [];
2295
+ OutputFormatter.success({
2296
+ Result: RESULTS.Success,
2297
+ Code: "FlowJobList",
2298
+ Data: options.allFields ? items : items.map(formatFlowJob),
2299
+ Pagination: {
2300
+ Returned: items.length,
2301
+ Limit: limit,
2302
+ Offset: offset,
2303
+ HasMore: items.length >= limit
2304
+ }
2305
+ });
2306
+ });
2307
+ jobCmd.command("traces").description("Stream traces for a running job").argument("<job-key>", "Job key (GUID from run command)").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).option("--poll-interval <ms>", "Polling interval in milliseconds", "2000").option("--traces-service <name>", "Traces service name (default: llmopstenant_)", "llmopstenant_").option("--pretty", "Show traces in human-readable format instead of raw JSON").option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).trackedAction(processContext, async (jobKey, options) => {
2308
+ const { getLoginStatusAsync } = await import("./index-1kgxzh8x.js");
2309
+ const [loginError, loginStatus] = await catchError(getLoginStatusAsync({
2310
+ ensureTokenValidityMinutes: options.loginValidity
2311
+ }));
2312
+ if (loginError) {
2313
+ OutputFormatter.error({
2314
+ Result: RESULTS.Failure,
2315
+ Message: loginError.message,
2316
+ Instructions: instructionsFor("auth", loginError)
2317
+ });
2318
+ processContext.exit(1);
2319
+ return;
2320
+ }
2321
+ if (loginStatus.loginStatus !== "Logged in" || !loginStatus.baseUrl) {
2322
+ OutputFormatter.error({
2323
+ Result: RESULTS.Failure,
2324
+ Message: "Not logged in. Run 'uip login' first.",
2325
+ Instructions: instructionsFor("auth")
2326
+ });
2327
+ processContext.exit(1);
2328
+ return;
2329
+ }
2330
+ const tenantName = options.tenant || loginStatus.tenantName;
2331
+ if (!tenantName || !loginStatus.organizationId) {
2332
+ OutputFormatter.error({
2333
+ Result: RESULTS.Failure,
2334
+ Message: "Missing tenant or organization info.",
2335
+ Instructions: instructionsFor("identity")
2336
+ });
2337
+ processContext.exit(1);
2338
+ return;
2339
+ }
2340
+ const config = {
2341
+ processKey: "",
2342
+ folderKey: "",
2343
+ inputs: {},
2344
+ authToken: loginStatus.accessToken ?? "",
2345
+ organizationId: loginStatus.organizationId,
2346
+ tenantName,
2347
+ tenantId: loginStatus.tenantId,
2348
+ baseUrl: loginStatus.baseUrl,
2349
+ tracesServiceName: options.tracesService
2350
+ };
2351
+ const pollIntervalMs = parseInt(options.pollInterval || "2000", 10);
2352
+ if (!Number.isFinite(pollIntervalMs) || pollIntervalMs <= 0) {
2353
+ OutputFormatter.error({
2354
+ Result: RESULTS.Failure,
2355
+ Message: `Invalid poll-interval: ${options.pollInterval}. Must be a positive number.`,
2356
+ Instructions: "Provide a positive number in milliseconds."
2357
+ });
2358
+ processContext.exit(1);
2359
+ return;
2360
+ }
2361
+ const pollSeconds = pollIntervalMs / 1000;
2362
+ logger.info(`Streaming traces for job: ${jobKey}
2363
+ Polling every ${pollSeconds}s...`);
2364
+ const { formatTraceLine } = await import("./shared-utils-8xdq6f04.js");
2365
+ const { streamJobTraces } = await import("./flow-api-wv8p8xbd.js");
2366
+ const [tracesError, result] = await catchError(streamJobTraces(config, jobKey, {
2367
+ onTrace: (trace) => {
2368
+ if (options.pretty) {
2369
+ ScreenLogger.progress(formatTraceLine(trace));
2370
+ } else {
2371
+ ScreenLogger.progress(JSON.stringify(trace));
2372
+ }
2373
+ },
2374
+ onComplete: (result2) => {
2375
+ ScreenLogger.progress(`Job ${jobKey}: ${result2.finalState} (${result2.duration}ms)`);
2376
+ },
2377
+ onError: (error) => {
2378
+ ScreenLogger.progress(`Error: ${error.message}`);
2379
+ },
2380
+ pollInterval: pollIntervalMs
2381
+ }));
2382
+ if (tracesError) {
2383
+ OutputFormatter.error({
2384
+ Result: RESULTS.Failure,
2385
+ Message: tracesError.message,
2386
+ Instructions: FLOW_JOB_TRACES_ERROR_INSTRUCTIONS
2387
+ });
2388
+ processContext.exit(1);
2389
+ return;
2390
+ }
2391
+ if (!result.success && result.error) {
2392
+ OutputFormatter.error({
2393
+ Result: RESULTS.Failure,
2394
+ Message: result.error,
2395
+ Instructions: FLOW_JOB_TRACES_ERROR_INSTRUCTIONS
2396
+ });
2397
+ processContext.exit(1);
2398
+ return;
2399
+ }
2400
+ processContext.exit(result.success ? 0 : 1);
2401
+ });
2402
+ jobCmd.command("status").description("Get detailed status of a Flow job").argument("<job-key>", "Job key (GUID from run command)").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).option("--folder-key <key>", "Folder key (GUID from list command, defaults to authenticated folder)").option("--detailed", "Show full response with all fields").option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).examples(FLOW_JOB_STATUS_EXAMPLES).trackedAction(processContext, async (jobKey, options) => {
2403
+ const { getLoginStatusAsync } = await import("./index-1kgxzh8x.js");
2404
+ const [loginError, loginStatus] = await catchError(getLoginStatusAsync({
2405
+ ensureTokenValidityMinutes: options.loginValidity
2406
+ }));
2407
+ if (loginError) {
2408
+ OutputFormatter.error({
2409
+ Result: RESULTS.Failure,
2410
+ Message: loginError.message,
2411
+ Instructions: instructionsFor("auth", loginError)
2412
+ });
2413
+ processContext.exit(1);
2414
+ return;
2415
+ }
2416
+ if (loginStatus.loginStatus !== "Logged in" || !loginStatus.baseUrl) {
2417
+ OutputFormatter.error({
2418
+ Result: RESULTS.Failure,
2419
+ Message: "Not logged in. Run 'uip login' first.",
2420
+ Instructions: instructionsFor("auth")
2421
+ });
2422
+ processContext.exit(1);
2423
+ return;
2424
+ }
2425
+ const tenantName = options.tenant || loginStatus.tenantName;
2426
+ if (!tenantName || !loginStatus.organizationId) {
2427
+ OutputFormatter.error({
2428
+ Result: RESULTS.Failure,
2429
+ Message: "Missing tenant or organization info.",
2430
+ Instructions: instructionsFor("identity")
2431
+ });
2432
+ processContext.exit(1);
2433
+ return;
2434
+ }
2435
+ const config = {
2436
+ processKey: "",
2437
+ folderKey: options.folderKey ?? "",
2438
+ inputs: {},
2439
+ authToken: loginStatus.accessToken ?? "",
2440
+ organizationId: loginStatus.organizationId,
2441
+ tenantName,
2442
+ tenantId: loginStatus.tenantId,
2443
+ baseUrl: loginStatus.baseUrl
2444
+ };
2445
+ const { getJobStatusDetailed } = await import("./flow-api-wv8p8xbd.js");
2446
+ const [statusError, status] = await catchError(getJobStatusDetailed(config, jobKey));
2447
+ if (statusError) {
2448
+ OutputFormatter.error({
2449
+ Result: RESULTS.Failure,
2450
+ Message: statusError.message,
2451
+ Instructions: instructionsFor("backend", statusError)
2452
+ });
2453
+ processContext.exit(1);
2454
+ return;
2455
+ }
2456
+ const outputData = options.detailed ? status : {
2457
+ key: status.key,
2458
+ state: status.state,
2459
+ runtimeType: status.runtimeType,
2460
+ processType: status.processType,
2461
+ startTime: status.startTime,
2462
+ endTime: status.endTime,
2463
+ creationTime: status.creationTime,
2464
+ inputArguments: status.inputArguments,
2465
+ outputArguments: status.outputArguments,
2466
+ info: status.info,
2467
+ releaseName: status.release?.name,
2468
+ processKey: status.release?.processKey,
2469
+ robotName: status.robot?.name,
2470
+ hostMachineName: status.hostMachineName
2471
+ };
2472
+ const pendingSeconds = pendingSecondsFor(status.state, status.creationTime);
2473
+ OutputFormatter.success({
2474
+ Result: RESULTS.Success,
2475
+ Code: "FlowJobStatus",
2476
+ Data: pendingSeconds === undefined ? outputData : { ...outputData, pendingSeconds },
2477
+ ...pendingSeconds === undefined ? {} : {
2478
+ Instructions: pendingStallInstructions(pendingSeconds)
2479
+ }
2480
+ });
2481
+ });
2482
+ }
2483
+
2484
+ // src/commands/migrate.ts
2485
+ var FLOW_MIGRATE_EXAMPLES = [
2486
+ {
2487
+ Description: "Migrate a .flow file to the current schema version",
2488
+ Command: "uip maestro flow migrate ./my-flow/my-flow.flow",
2489
+ Output: {
2490
+ Code: "FlowMigrate",
2491
+ Data: {
2492
+ Migrated: true,
2493
+ FromVersion: "1.0.0",
2494
+ ToVersion: "1.0",
2495
+ WorkflowSteps: ["1.0.0 -> 1.0"]
2496
+ }
2497
+ }
2498
+ },
2499
+ {
2500
+ Description: "Preview changes without writing the file",
2501
+ Command: "uip maestro flow migrate ./my-flow/my-flow.flow --dry-run",
2502
+ Output: {
2503
+ Code: "FlowMigrate",
2504
+ Data: {
2505
+ Migrated: true,
2506
+ DryRun: true,
2507
+ FromVersion: "1.0.0",
2508
+ ToVersion: "1.0",
2509
+ WorkflowSteps: ["1.0.0 -> 1.0"]
2510
+ }
2511
+ }
2512
+ },
2513
+ {
2514
+ Description: "Skip optional node migrations (e.g. typeVersion normalization)",
2515
+ Command: "uip maestro flow migrate ./my-flow/my-flow.flow --no-include-optional",
2516
+ Output: {
2517
+ Code: "FlowMigrate",
2518
+ Data: {
2519
+ Migrated: true,
2520
+ FromVersion: "1.0.0",
2521
+ ToVersion: "1.0",
2522
+ NodeMigrations: { OptionalApplied: 0 }
2523
+ }
2524
+ }
2525
+ }
2526
+ ];
2527
+ var registerMigrateCommand = (program) => {
2528
+ program.command("migrate").description("Migrate a .flow file to the current workflow and node schema versions").argument("<file>", "Path to the .flow file").option("--dry-run", "Show what would change without writing the file").option("--no-include-optional", "Skip optional node migrations (e.g. typeVersion normalization). Default: optional migrations are applied.").examples(FLOW_MIGRATE_EXAMPLES).trackedAction(processContext, async (file, options) => {
2529
+ const { migrateFlow } = await import("./flow-migrate-service-rwcdx60q.js");
2530
+ const [error, result] = await catchError(migrateFlow(file, {
2531
+ dryRun: options.dryRun,
2532
+ includeOptional: options.includeOptional
2533
+ }));
2534
+ if (error) {
2535
+ OutputFormatter.error({
2536
+ Result: RESULTS.Failure,
2537
+ Message: "Failed to migrate flow",
2538
+ Instructions: error.message
2539
+ });
2540
+ processContext.exit(1);
2541
+ return;
2542
+ }
2543
+ const instructions = result.migrated ? result.dryRun ? "Dry-run: file not modified. Re-run without --dry-run to apply." : `Migrated ${result.fromVersion} → ${result.toVersion}` : `Already at version ${result.toVersion}`;
2544
+ OutputFormatter.success({
2545
+ Result: RESULTS.Success,
2546
+ Code: "FlowMigrate",
2547
+ Data: {
2548
+ File: result.file,
2549
+ Migrated: result.migrated,
2550
+ DryRun: result.dryRun,
2551
+ FromVersion: result.fromVersion,
2552
+ ToVersion: result.toVersion,
2553
+ WorkflowSteps: result.workflowSteps,
2554
+ NodeMigrations: {
2555
+ ForcedAvailable: result.forcedNodeMigrations,
2556
+ OptionalAvailable: result.optionalNodeMigrations,
2557
+ OptionalApplied: result.optionalApplied,
2558
+ Failed: result.failedNodeMigrations
2559
+ }
2560
+ },
2561
+ Instructions: instructions
2562
+ });
2563
+ });
2564
+ };
2565
+
2566
+ // src/commands/node.ts
2567
+ var NODE_ADD_EXAMPLES = [
2568
+ {
2569
+ Description: "Add a manual trigger node to a flow",
2570
+ Command: 'uip maestro flow node add flow.json core.trigger.manual --label "Start"',
2571
+ Output: {
2572
+ Code: "NodeAddSuccess",
2573
+ Data: {
2574
+ Node: {
2575
+ id: "node_a1b2c3d4",
2576
+ type: "core.trigger.manual"
2577
+ },
2578
+ DefinitionAdded: true,
2579
+ BindingsCreated: 0,
2580
+ VariableCount: 0
2581
+ }
2582
+ }
2583
+ }
2584
+ ];
2585
+ var NODE_CONFIGURE_EXAMPLES = [
2586
+ {
2587
+ Description: "Configure a connector node with connection details",
2588
+ Command: `uip maestro flow node configure flow.json node_a1b2c3d4 --detail '{"connectionId":"b2c3d4e5-0000-0000-0000-000000000001","folderKey":"c3d4e5f6-0000-0000-0000-000000000001","method":"POST","endpoint":"/issues"}'`,
2589
+ Output: {
2590
+ Code: "NodeConfigureSuccess",
2591
+ Data: {
2592
+ NodeId: "node_a1b2c3d4",
2593
+ BindingsCreated: 2,
2594
+ DetailPopulated: true
2595
+ }
2596
+ }
2597
+ },
2598
+ {
2599
+ Description: "Configure a generic connector activity (e.g. SFDC InsertRecord) — requires objectName",
2600
+ Command: `uip maestro flow node configure flow.json node_a1b2c3d4 --detail '{"connectionId":"b2c3d4e5-0000-0000-0000-000000000001","folderKey":"c3d4e5f6-0000-0000-0000-000000000001","method":"POST","endpoint":"/Account","objectName":"Account","bodyParameters":{"Name":"Acme Corp"}}'`,
2601
+ Output: {
2602
+ Code: "NodeConfigureSuccess",
2603
+ Data: {
2604
+ NodeId: "node_a1b2c3d4",
2605
+ BindingsCreated: 2,
2606
+ DetailPopulated: true
2607
+ }
2608
+ }
2609
+ },
2610
+ {
2611
+ Description: "Configure a param bound to another node's output — must use $vars., not the bare node id",
2612
+ Command: `uip maestro flow node configure flow.json node_a1b2c3d4 --detail '{"connectionId":"b2c3d4e5-0000-0000-0000-000000000001","folderKey":"c3d4e5f6-0000-0000-0000-000000000001","method":"POST","endpoint":"/Account","bodyParameters":{"recordId":"=js:$vars.createEntityRecord1.output.Id"}}'`,
2613
+ Output: {
2614
+ Code: "NodeConfigureSuccess",
2615
+ Data: {
2616
+ NodeId: "node_a1b2c3d4",
2617
+ BindingsCreated: 2,
2618
+ DetailPopulated: true
2619
+ }
2620
+ }
2621
+ }
2622
+ ];
2623
+ var NODE_LIST_EXAMPLES = [
2624
+ {
2625
+ Description: "List all nodes in a flow file",
2626
+ Command: "uip maestro flow node list flow.json",
2627
+ Output: {
2628
+ Code: "NodeListSuccess",
2629
+ Data: {
2630
+ Nodes: [
2631
+ { id: "start", type: "core.trigger.manual" },
2632
+ { id: "node_a1b2c3d4", type: "core.action.http.v2" }
2633
+ ],
2634
+ Count: 2
2635
+ }
2636
+ }
2637
+ }
2638
+ ];
2639
+ var NODE_DELETE_EXAMPLES = [
2640
+ {
2641
+ Description: "Delete a node and its connections from a flow",
2642
+ Command: "uip maestro flow node delete flow.json node_a1b2c3d4",
2643
+ Output: {
2644
+ Code: "NodeDeleteSuccess",
2645
+ Data: {
2646
+ DeletedNode: {
2647
+ id: "node_a1b2c3d4",
2648
+ type: "core.action.http.v2"
2649
+ },
2650
+ EdgesRemoved: 1,
2651
+ BindingsRemoved: 0,
2652
+ DefinitionsRemoved: 0,
2653
+ VariablesRemoved: 0,
2654
+ VariableUpdatesRemoved: 0
2655
+ }
2656
+ }
2657
+ }
2658
+ ];
2659
+ var NODE_REMOVE_EXAMPLES = [
2660
+ {
2661
+ Description: "Remove a node and its connections from a flow",
2662
+ Command: "uip maestro flow node remove flow.json node_a1b2c3d4",
2663
+ Output: {
2664
+ Code: "NodeRemoveSuccess",
2665
+ Data: {
2666
+ DeletedNode: {
2667
+ id: "node_a1b2c3d4",
2668
+ type: "core.action.http.v2"
2669
+ },
2670
+ EdgesRemoved: 1,
2671
+ BindingsRemoved: 0,
2672
+ DefinitionsRemoved: 0,
2673
+ VariablesRemoved: 0,
2674
+ VariableUpdatesRemoved: 0
2675
+ }
2676
+ }
2677
+ }
2678
+ ];
2679
+ function parsePosition2(value) {
2680
+ const parts = value.split(",");
2681
+ if (parts.length !== 2) {
2682
+ throw new Error(`Invalid position format: "${value}". Expected "x,y" (e.g. 250,150)`);
2683
+ }
2684
+ const x = Number(parts[0]);
2685
+ const y = Number(parts[1]);
2686
+ if (Number.isNaN(x) || Number.isNaN(y)) {
2687
+ throw new Error(`Invalid position values: "${value}". x and y must be numbers`);
2688
+ }
2689
+ return { x, y };
2690
+ }
2691
+ function getDeleteNodeInstructions(file) {
2692
+ return `Check that "${file}" exists and run 'uip maestro flow node list ${file}' to find a valid node ID, then retry.`;
2693
+ }
2694
+ async function runDeleteNode(file, nodeId, code) {
2695
+ const { deleteNodeFromFlow } = await import("./node-service-8g5x5d2y.js");
2696
+ const normalizedNodeId = nodeId.trim();
2697
+ const [error, result] = await catchError(deleteNodeFromFlow(file, normalizedNodeId));
2698
+ if (error) {
2699
+ OutputFormatter.error({
2700
+ Result: RESULTS.Failure,
2701
+ Message: "Error deleting node",
2702
+ Instructions: getDeleteNodeInstructions(file)
2703
+ });
2704
+ processContext.exit(1);
2705
+ return;
2706
+ }
2707
+ OutputFormatter.success({
2708
+ Result: RESULTS.Success,
2709
+ Code: code,
2710
+ Data: {
2711
+ DeletedNode: result.deletedNode,
2712
+ EdgesRemoved: result.edgesRemoved,
2713
+ BindingsRemoved: result.bindingsRemoved,
2714
+ DefinitionsRemoved: result.definitionsRemoved,
2715
+ VariablesRemoved: result.variablesRemoved,
2716
+ VariableUpdatesRemoved: result.variableUpdatesRemoved
2717
+ }
2718
+ });
2719
+ }
2720
+ var registerNodeCommand = (program) => {
2721
+ const node = program.command("node").description("Manage nodes in a Flow file");
2722
+ node.command("add").description(`Add a node to a Flow file.
2723
+ ` + "For connector nodes (type uipath.connector), do NOT pass --input here — " + `run 'node configure' afterwards to supply connection and endpoint details.
2724
+ Example: uip maestro flow node add flow.flow uipath.connector.jira.createIssue --label 'Create Jira Issue'`).argument("<file>", "Path to the .flow file").argument("<node-type>", "Node type identifier (e.g. core.trigger.manual)").option("-i, --input <json>", `JSON object of input values to set on the node (e.g. '{"script": "..."}')`).option("--position <x,y>", "Node position in the canvas (e.g. 250,150)").option("--label <label>", "Display label for the node").option("--source <uuid>", "Source UUID for nodes whose manifest declares a source dependency. Use the agent's ProjectId (inline agent nodes) or the resource id from the parent inline agent's resources[] (agent-tool resource nodes). Populates inputs.source.").option("--parent <node-id>", "Id of the existing node that should contain this node. Set when authoring a loop body whose containment cannot be " + "inferred from edges alone — typically the id of a " + "core.logic.loop node.").examples(NODE_ADD_EXAMPLES).trackedAction(processContext, async (file, nodeType, options) => {
2725
+ let inputs;
2726
+ if (options.input !== undefined) {
2727
+ const [parseError, parsed] = catchError(() => JSON.parse(options.input));
2728
+ if (parseError) {
2729
+ OutputFormatter.error({
2730
+ Result: RESULTS.Failure,
2731
+ Message: "Invalid --input JSON",
2732
+ Instructions: parseError.message
2733
+ });
2734
+ processContext.exit(1);
2735
+ return;
2736
+ }
2737
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
2738
+ OutputFormatter.error({
2739
+ Result: RESULTS.Failure,
2740
+ Message: "Invalid --input JSON",
2741
+ Instructions: `--input must be a JSON object (e.g. '{"key": "value"}')`
2742
+ });
2743
+ processContext.exit(1);
2744
+ return;
2745
+ }
2746
+ inputs = parsed;
2747
+ }
2748
+ let position;
2749
+ if (options.position !== undefined) {
2750
+ const [posError, parsed] = catchError(() => parsePosition2(options.position));
2751
+ if (posError) {
2752
+ OutputFormatter.error({
2753
+ Result: RESULTS.Failure,
2754
+ Message: "Invalid --position value",
2755
+ Instructions: posError.message
2756
+ });
2757
+ processContext.exit(1);
2758
+ return;
2759
+ }
2760
+ position = parsed;
2761
+ }
2762
+ const {
2763
+ addNodeToFlow,
2764
+ NodeTypeNotEnabledError,
2765
+ NodeTypeNotFoundError,
2766
+ SourceRequiredError
2767
+ } = await import("./node-service-8g5x5d2y.js");
2768
+ const [error, result] = await catchError(addNodeToFlow(file, nodeType, {
2769
+ position,
2770
+ label: options.label,
2771
+ inputs,
2772
+ source: options.source,
2773
+ parent: options.parent
2774
+ }));
2775
+ if (error) {
2776
+ if (error instanceof NodeTypeNotEnabledError || error instanceof NodeTypeNotFoundError || error instanceof SourceRequiredError) {
2777
+ OutputFormatter.error({
2778
+ Result: RESULTS.Failure,
2779
+ Message: error.message,
2780
+ Instructions: error.instructions
2781
+ });
2782
+ processContext.exit(1);
2783
+ return;
2784
+ }
2785
+ OutputFormatter.error({
2786
+ Result: RESULTS.Failure,
2787
+ Message: "Error adding node",
2788
+ Instructions: error.message
2789
+ });
2790
+ processContext.exit(1);
2791
+ return;
2792
+ }
2793
+ OutputFormatter.success({
2794
+ Result: RESULTS.Success,
2795
+ Code: "NodeAddSuccess",
2796
+ Data: {
2797
+ Node: result.node,
2798
+ DefinitionAdded: result.definitionAdded,
2799
+ BindingsCreated: result.bindingsCreated,
2800
+ VariableCount: result.variableCount
2801
+ }
2802
+ });
2803
+ });
2804
+ node.command("configure").description(`Configure a connector or managed HTTP node with connection and method details.
2805
+ ` + `Run this after 'node add' — populates inputs.detail and creates workflow bindings.
2806
+ ` + `Use 'node list' to find the node ID.
2807
+
2808
+ CONNECTOR ACTIVITIES (type uipath.connector.*, NOT *.trigger.*)
2809
+ Required: connectionId, folderKey, method, endpoint.
2810
+ Generic activities (manifest activityType='Generic', e.g. *.insert-record,
2811
+ *.list-records) also require objectName. Discover with:
2812
+ uip is resources list <connector-key> --operation <op> --connection-id <uuid>
2813
+ uip is resources describe <connector-key> <object> --operation <op> --connection-id <uuid>
2814
+ Curated activities: get method/endpoint from connectorMethodInfo in 'registry get'.
2815
+ Optional: bodyParameters, queryParameters, pathParameters, filter,
2816
+ customFieldsRequestDetails ({ objectActionName, parameterValues: [[k,v],...] });
2817
+ Examples:
2818
+ --detail '{"connectionId":"<uuid>","folderKey":"<uuid>","method":"POST","endpoint":"/issues","bodyParameters":{"summary":"Bug"}}'
2819
+ --detail '{"connectionId":"<uuid>","folderKey":"<uuid>","method":"POST","endpoint":"/Account","objectName":"Account","bodyParameters":{"Name":"Acme"}}'
2820
+ Cross-node bindings (referencing another node's output) require the
2821
+ ` + ` "$vars." prefix inside the "=js:" expression — the bare form
2822
+ ` + ` (e.g. "=js:createEntityRecord1.output.Id") resolves to undefined at runtime:
2823
+ --detail '{"connectionId":"<uuid>","folderKey":"<uuid>","method":"POST","endpoint":"/Account","bodyParameters":{"recordId":"=js:$vars.createEntityRecord1.output.Id"}}'
2824
+
2825
+ CONNECTOR TRIGGERS (type uipath.connector.trigger.*)
2826
+ Required: connectionId, folderKey, eventMode (e.g. 'polling' or 'webhook').
2827
+ Generic triggers (manifest activityType='GenericTrigger', e.g. Data Fabric
2828
+ ` + ` *.record-created) also require objectName — the object to subscribe to.
2829
+ ` + ` Discover with: uip is triggers objects <connector-key> <eventType> --connection-id <uuid>
2830
+ Optional: eventParameters, queryParameters, pathParameters,
2831
+ filter (structured FilterTree, not a raw expression).
2832
+ Discover eventMode with:
2833
+ uip is triggers describe <connector-key> <eventType> <object> --connection-id <uuid>
2834
+ Examples:
2835
+ --detail '{"connectionId":"<uuid>","folderKey":"<uuid>","eventMode":"polling"}'
2836
+ --detail '{"connectionId":"<uuid>","folderKey":"<uuid>","eventMode":"webhooks","objectName":"MyEntity"}'
2837
+
2838
+ CONNECTOR WAIT-FOR EVENTS (type uipath.connector.event.*)
2839
+ Mid-flow Receive Task that pauses execution until the event fires.
2840
+ ` + ` Same detail shape as connector triggers — only activityType differs internally.
2841
+ ` + ` Required: connectionId, folderKey, eventMode (e.g. 'polling' or 'webhooks').
2842
+ Generic event nodes also require objectName (same rule as triggers).
2843
+ Optional: eventParameters, queryParameters, pathParameters,
2844
+ filter (structured FilterTree, not a raw expression).
2845
+ Discover eventMode with:
2846
+ uip is triggers describe <connector-key> <eventType> <object> --connection-id <uuid>
2847
+ Example:
2848
+ --detail '{"connectionId":"<uuid>","folderKey":"<uuid>","eventMode":"polling","queryParameters":{"repo":"cli"}}'
2849
+
2850
+ MANAGED HTTP NODES (type core.action.http.v2)
2851
+ ` + ` Two authentication modes — set via the 'authentication' key:
2852
+
2853
+ ` + ` Connector mode (authentication='connector'):
2854
+ Uses an Integration Service connection for auth.
2855
+ Required: authentication, method (GET/POST/PUT/PATCH/DELETE/OPTIONS/HEAD),
2856
+ connectionId (target connector connection UUID),
2857
+ folderKey, targetConnector (e.g. uipath-microsoft-outlook365)
2858
+ Optional: url (path appended to connector base URL), headers, query, body
2859
+ Example:
2860
+ --detail '{"authentication":"connector","targetConnector":"uipath-microsoft-outlook365","connectionId":"<uuid>","folderKey":"<uuid>","method":"GET","url":"/me"}'
2861
+
2862
+ Manual mode (authentication='manual'):
2863
+ ` + ` No connector auth — provide the full URL and any auth headers yourself.
2864
+ ` + ` Required: authentication, method, url (full URL)
2865
+ Optional: headers, query, body (string, can be expression e.g. '=js:({...})')
2866
+ Example:
2867
+ --detail '{"authentication":"manual","method":"GET","url":"https://api.example.com/data","headers":{"Authorization":"Bearer <token>"}}'`).argument("<file>", "Path to the .flow file").argument("<node-id>", "ID of the node to configure").option("--detail <json>", "Configuration as JSON (connectionId, folderKey, method, endpoint, objectName for generic activities, bodyParameters, etc.)").examples(NODE_CONFIGURE_EXAMPLES).trackedAction(processContext, async (file, nodeId, options) => {
2868
+ if (!options.detail) {
2869
+ OutputFormatter.error({
2870
+ Result: RESULTS.Failure,
2871
+ Message: "Missing --detail",
2872
+ Instructions: "--detail is required (JSON with connectionId, folderKey, etc.)"
2873
+ });
2874
+ processContext.exit(1);
2875
+ return;
2876
+ }
2877
+ const [parseError, parsed] = catchError(() => JSON.parse(options.detail));
2878
+ if (parseError) {
2879
+ OutputFormatter.error({
2880
+ Result: RESULTS.Failure,
2881
+ Message: "Invalid --detail JSON",
2882
+ Instructions: parseError.message
2883
+ });
2884
+ processContext.exit(1);
2885
+ return;
2886
+ }
2887
+ const { configureConnectorNode, InvalidDetailError } = await import("./connector-service-d9ph9kx1.js");
2888
+ const [error, result] = await catchError(configureConnectorNode(file, nodeId, parsed));
2889
+ if (error) {
2890
+ const message = error instanceof InvalidDetailError ? "Invalid --detail" : "Error configuring node";
2891
+ OutputFormatter.error({
2892
+ Result: RESULTS.Failure,
2893
+ Message: message,
2894
+ Instructions: error.message
2895
+ });
2896
+ processContext.exit(1);
2897
+ return;
2898
+ }
2899
+ OutputFormatter.success({
2900
+ Result: RESULTS.Success,
2901
+ Code: "NodeConfigureSuccess",
2902
+ Data: {
2903
+ NodeId: nodeId,
2904
+ BindingsCreated: result.bindingsCreated,
2905
+ DetailPopulated: result.detailPopulated,
2906
+ ...result.warnings && result.warnings.length > 0 && {
2907
+ Warnings: result.warnings
2908
+ }
2909
+ }
2910
+ });
2911
+ });
2912
+ node.command("list").description("List all nodes in a Flow file").argument("<file>", "Path to the .flow file").examples(NODE_LIST_EXAMPLES).trackedAction(processContext, async (file) => {
2913
+ const { listNodesInFlow } = await import("./node-service-8g5x5d2y.js");
2914
+ const [error, result] = await catchError(listNodesInFlow(file));
2915
+ if (error) {
2916
+ OutputFormatter.error({
2917
+ Result: RESULTS.Failure,
2918
+ Message: "Error listing nodes",
2919
+ Instructions: error.message
2920
+ });
2921
+ processContext.exit(1);
2922
+ return;
2923
+ }
2924
+ OutputFormatter.success({
2925
+ Result: RESULTS.Success,
2926
+ Code: "NodeListSuccess",
2927
+ Data: {
2928
+ Nodes: result.nodes,
2929
+ Count: result.count
2930
+ }
2931
+ });
2932
+ });
2933
+ node.command("delete").description(`Delete a node from a Flow file.
2934
+ Automatically removes connected edges, orphaned bindings, orphaned definitions, and node variables owned by the deleted node.
2935
+ Use 'node list' to find the node ID.`).argument("<file>", "Path to the .flow file").argument("<node-id>", "ID of the node to delete").examples(NODE_DELETE_EXAMPLES).trackedAction(processContext, async (file, nodeId) => runDeleteNode(file, nodeId, "NodeDeleteSuccess"));
2936
+ node.command("remove").description(`Remove a node from a Flow file.
2937
+ Alias for 'node delete'. Automatically removes connected edges, orphaned bindings, orphaned definitions, and node variables owned by the removed node.
2938
+ Use 'node list' to find the node ID.`).argument("<file>", "Path to the .flow file").argument("<node-id>", "ID of the node to remove").examples(NODE_REMOVE_EXAMPLES).trackedAction(processContext, async (file, nodeId) => runDeleteNode(file, nodeId, "NodeRemoveSuccess"));
2939
+ };
2940
+
2941
+ // src/commands/pack.ts
2942
+ var FLOW_PACK_EXAMPLES = [
2943
+ {
2944
+ Description: "Pack a flow project into a .nupkg file",
2945
+ Command: "uip maestro flow pack ./my-flow-project ./dist --version 1.2.0",
2946
+ Output: {
2947
+ Code: "FlowPack",
2948
+ Data: {
2949
+ Package: "my-flow-project.1.2.0.nupkg",
2950
+ Output: "./dist/my-flow-project.1.2.0.nupkg"
2951
+ }
2952
+ }
2953
+ }
2954
+ ];
2955
+ var registerPackCommand = (program) => {
2956
+ const command = program.command("pack").description("Pack a Flow project into a .nupkg file").argument("<project-path>", "Path to the Flow project directory").argument("<output-path>", "Output directory where the .nupkg will be saved").option("-n, --name <name>", "Package name (default: project folder name)").option("-v, --version <version>", "Package version (default: 1.0.0)", "1.0.0");
2957
+ registerPackageMetadataOptions(command).examples(FLOW_PACK_EXAMPLES).trackedAction(processContext, async (projectPath, outputPath, options) => {
2958
+ const { FlowPackService } = await import("./flow-pack-service-p4hxyj9e.js");
2959
+ const service = new FlowPackService;
2960
+ const exitCode = await service.execute(projectPath, {
2961
+ output: outputPath,
2962
+ name: options.name,
2963
+ version: options.version,
2964
+ ...mapPackageMetadataOptions(options)
2965
+ });
2966
+ if (exitCode) {
2967
+ processContext.exit(exitCode);
2968
+ }
2969
+ });
2970
+ };
2971
+
2972
+ // src/commands/process.ts
2973
+ var FLOW_PROCESS_LIST_EXAMPLES = [
2974
+ {
2975
+ Description: "List available flow projects in a folder by key",
2976
+ Command: "uip maestro flow process list --folder-key c3d4e5f6-0000-0000-0000-000000000001",
2977
+ Output: {
2978
+ Code: "FlowProjectList",
2979
+ Data: [
2980
+ {
2981
+ name: "InvoiceFlow",
2982
+ processKey: "a1b2c3d4-0000-0000-0000-000000000001:1.0.0",
2983
+ releaseKey: "e5f6a7b8-0000-0000-0000-000000000001",
2984
+ folderKey: "c3d4e5f6-0000-0000-0000-000000000001",
2985
+ feedId: "default",
2986
+ folderId: 42,
2987
+ releaseActive: "Yes",
2988
+ releaseLatest: "Yes"
2989
+ }
2990
+ ]
2991
+ }
2992
+ },
2993
+ {
2994
+ Description: "List available flow projects in a folder by path",
2995
+ Command: 'uip maestro flow process list --folder-path "Shared/Invoices"',
2996
+ Output: {
2997
+ Code: "FlowProjectList",
2998
+ Data: [
2999
+ {
3000
+ name: "InvoiceFlow",
3001
+ processKey: "a1b2c3d4-0000-0000-0000-000000000001:1.0.0",
3002
+ releaseKey: "e5f6a7b8-0000-0000-0000-000000000001",
3003
+ folderKey: "c3d4e5f6-0000-0000-0000-000000000001",
3004
+ feedId: "default",
3005
+ folderId: 42,
3006
+ active: "Yes",
3007
+ latest: "Yes"
3008
+ }
3009
+ ]
3010
+ }
3011
+ }
3012
+ ];
3013
+ var FLOW_PROCESS_GET_EXAMPLES = [
3014
+ {
3015
+ Description: "Get a flow project's entry point schema",
3016
+ Command: "uip maestro flow process get a1b2c3d4-0000-0000-0000-000000000001 default --folder-key c3d4e5f6-0000-0000-0000-000000000001",
3017
+ Output: {
3018
+ Code: "FlowProjectGet",
3019
+ Data: [
3020
+ {
3021
+ Path: "/content/main.flow",
3022
+ DisplayName: "Main",
3023
+ Type: "Flow",
3024
+ InputSchema: '{"type":"object","properties":{}}',
3025
+ OutputSchema: '{"type":"object","properties":{}}'
3026
+ }
3027
+ ]
3028
+ }
3029
+ }
3030
+ ];
3031
+ var FLOW_PROCESS_RUN_EXAMPLES = [
3032
+ {
3033
+ Description: "Run a flow project with JSON inputs",
3034
+ Command: `uip maestro flow process run a1b2c3d4-0000-0000-0000-000000000001 c3d4e5f6-0000-0000-0000-000000000001 --inputs '{"amount":100}'`,
3035
+ Output: {
3036
+ Code: "FlowJobStarted",
3037
+ Data: {
3038
+ jobKey: "b2c3d4e5-0000-0000-0000-000000000001",
3039
+ state: "Pending",
3040
+ traceId: "d4e5f6a7-0000-0000-0000-000000000001",
3041
+ folderKey: "c3d4e5f6-0000-0000-0000-000000000001"
3042
+ }
3043
+ }
3044
+ },
3045
+ {
3046
+ Description: "Run a flow project and bind a local file to a file-typed input variable",
3047
+ Command: "uip maestro flow process run a1b2c3d4-0000-0000-0000-000000000001 c3d4e5f6-0000-0000-0000-000000000001 --attachment file1=./resume.pdf",
3048
+ Output: {
3049
+ Code: "FlowJobStarted",
3050
+ Data: {
3051
+ jobKey: "b2c3d4e5-0000-0000-0000-000000000001",
3052
+ state: "Pending",
3053
+ traceId: "d4e5f6a7-0000-0000-0000-000000000001",
3054
+ folderKey: "c3d4e5f6-0000-0000-0000-000000000001"
3055
+ }
3056
+ }
3057
+ }
3058
+ ];
3059
+ function flowProcessRunErrorCode(error) {
3060
+ return error.message.toLowerCase().includes("release key is required") ? "FlowReleaseKeyRequired" : undefined;
3061
+ }
3062
+ async function resolveReleaseKey(config, processKey) {
3063
+ const separator = processKey.lastIndexOf(":");
3064
+ const key = separator === -1 ? processKey : processKey.slice(0, separator);
3065
+ const version = separator === -1 ? undefined : processKey.slice(separator + 1);
3066
+ const { listFlowProcesses } = await import("./flow-api-wv8p8xbd.js");
3067
+ const processes = await listFlowProcesses(config);
3068
+ const matches = processes.filter((candidate) => candidate.processKey === key && (version === undefined || candidate.processVersion === version));
3069
+ const [releaseKey, ...extra] = matches.map((match) => match.key).filter((candidate) => Boolean(candidate));
3070
+ if (releaseKey === undefined) {
3071
+ throw new Error(`No Flow release matches process key '${processKey}' in folder ${config.folderKey}.`);
3072
+ }
3073
+ if (extra.length > 0) {
3074
+ throw new Error(`${matches.length} Flow releases match process key '${processKey}' in folder ${config.folderKey}: ${matches.map((match) => `${match.processVersion} (${match.key})`).join(", ")}.`);
3075
+ }
3076
+ return releaseKey;
3077
+ }
3078
+ async function resolveFolderForList(options) {
3079
+ const { resolveFolder } = await import("./index-ev4mdg5y.js");
3080
+ if (options.folderKey && options.folderPath) {
3081
+ const [pathError, pathFolder] = await catchError(resolveFolder({ folderPath: options.folderPath }, {
3082
+ tenant: options.tenant,
3083
+ loginValidity: options.loginValidity
3084
+ }));
3085
+ if (pathError || !pathFolder) {
3086
+ throw new Error(`Failed to resolve --folder-path '${options.folderPath}': ${pathError?.message ?? "folder not found"}.`);
3087
+ }
3088
+ if (options.folderKey.toLowerCase() !== pathFolder.key.toLowerCase()) {
3089
+ throw new Error(`--folder-key '${options.folderKey}' and --folder-path '${options.folderPath}' refer to different folders. Provide just one, or make them consistent.`);
3090
+ }
3091
+ return options.folderKey;
3092
+ }
3093
+ if (options.folderPath) {
3094
+ const [resolveError, resolved] = await catchError(resolveFolder({ folderPath: options.folderPath }, {
3095
+ tenant: options.tenant,
3096
+ loginValidity: options.loginValidity
3097
+ }));
3098
+ if (resolveError || !resolved) {
3099
+ throw new Error(`Failed to resolve --folder-path '${options.folderPath}': ${resolveError?.message ?? "folder not found"}.`);
3100
+ }
3101
+ return resolved.key;
3102
+ }
3103
+ if (!options.folderKey) {
3104
+ throw new Error("unreachable: folderKey must be defined when folderPath is absent");
3105
+ }
3106
+ return options.folderKey;
3107
+ }
3108
+ function registerProcessCommand(program) {
3109
+ const processCmd = program.command("process").description("Manage Flow processes");
3110
+ registerSharedProcessCommands(processCmd, { toolLabel: "Flow" });
3111
+ processCmd.command("list").description("List available Flow projects. The releaseActive and releaseLatest fields reflect Orchestrator release-level state (whether the release is marked active or the highest version on the manifest) and do not indicate whether the process is deployed or runnable.").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).option("--filter <odata>", "Additional OData filter").option("-f, --folder-key <key>", "Folder key (GUID)").option("--folder-path <path>", "Folder path (e.g. 'Shared/Invoices'). Alternative to --folder-key.").option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).examples(FLOW_PROCESS_LIST_EXAMPLES).trackedAction(processContext, async (options) => {
3112
+ const { getLoginStatusAsync } = await import("./index-1kgxzh8x.js");
3113
+ if (options.folderKey === undefined && options.folderPath === undefined) {
3114
+ OutputFormatter.error({
3115
+ Result: RESULTS.ValidationError,
3116
+ Message: "Missing required option --folder-key or --folder-path.",
3117
+ Instructions: "Provide --folder-key <key> or --folder-path <path> and try again."
3118
+ });
3119
+ processContext.exit(3);
3120
+ return;
3121
+ }
3122
+ const [loginError, loginStatus] = await catchError(getLoginStatusAsync({
3123
+ ensureTokenValidityMinutes: options.loginValidity
3124
+ }));
3125
+ if (loginError) {
3126
+ OutputFormatter.error({
3127
+ Result: RESULTS.Failure,
3128
+ Message: loginError.message,
3129
+ Instructions: instructionsFor("auth")
3130
+ });
3131
+ processContext.exit(1);
3132
+ return;
3133
+ }
3134
+ if (loginStatus.loginStatus !== "Logged in" || !loginStatus.baseUrl) {
3135
+ OutputFormatter.error({
3136
+ Result: RESULTS.Failure,
3137
+ Message: "Not logged in. Run 'uip login' first.",
3138
+ Instructions: instructionsFor("auth")
3139
+ });
3140
+ processContext.exit(1);
3141
+ return;
3142
+ }
3143
+ const tenantName = options.tenant || loginStatus.tenantName;
3144
+ if (!tenantName) {
3145
+ OutputFormatter.error({
3146
+ Result: RESULTS.Failure,
3147
+ Message: "Tenant not provided and not available from login. Run 'uip login' or 'uip login tenant set <tenant>'.",
3148
+ Instructions: instructionsFor("identity")
3149
+ });
3150
+ processContext.exit(1);
3151
+ return;
3152
+ }
3153
+ if (!loginStatus.organizationId) {
3154
+ OutputFormatter.error({
3155
+ Result: RESULTS.Failure,
3156
+ Message: "Organization ID not available from login.",
3157
+ Instructions: instructionsFor("identity")
3158
+ });
3159
+ processContext.exit(1);
3160
+ return;
3161
+ }
3162
+ const [resolveError, resolvedFolderKey] = await catchError(resolveFolderForList(options));
3163
+ if (resolveError) {
3164
+ OutputFormatter.error({
3165
+ Result: RESULTS.ValidationError,
3166
+ Message: resolveError.message,
3167
+ Instructions: "Provide a valid --folder-key or --folder-path, then retry."
3168
+ });
3169
+ processContext.exit(3);
3170
+ return;
3171
+ }
3172
+ const config = {
3173
+ processKey: "",
3174
+ folderKey: resolvedFolderKey,
3175
+ inputs: {},
3176
+ authToken: loginStatus.accessToken || "",
3177
+ organizationId: loginStatus.organizationId,
3178
+ tenantName,
3179
+ baseUrl: loginStatus.baseUrl
3180
+ };
3181
+ const { listFlowProcesses } = await import("./flow-api-wv8p8xbd.js");
3182
+ const [listError, processes] = await catchError(listFlowProcesses(config, options.filter));
3183
+ if (listError) {
3184
+ OutputFormatter.error({
3185
+ Result: RESULTS.Failure,
3186
+ Message: listError.message,
3187
+ Instructions: instructionsFor("backend", listError)
3188
+ });
3189
+ processContext.exit(1);
3190
+ return;
3191
+ }
3192
+ const formattedData = processes.map((p) => ({
3193
+ name: p.name,
3194
+ processKey: `${p.processKey}:${p.processVersion}`,
3195
+ releaseKey: p.key,
3196
+ folderKey: p.folderKey,
3197
+ feedId: p.feedId || "",
3198
+ folderId: p.organizationUnitId || "",
3199
+ releaseActive: p.isActive ? "Yes" : "No",
3200
+ releaseLatest: p.isLatestVersion ? "Yes" : "No"
3201
+ }));
3202
+ OutputFormatter.emitList("FlowProjectList", formattedData, {
3203
+ emptyInstructions: "No Flow projects found. Check folder permissions or try a different folder."
3204
+ });
3205
+ });
3206
+ processCmd.command("get").description("Get Flow project schema and details").argument("<process-key>", "Process key (e.g., MyFlow.flow.Flow:1.0.0)").argument("<feed-id>", "Feed ID (from 'flow project list')").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).requiredOption("-f, --folder-key <key>", "Folder key (GUID)").option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).examples(FLOW_PROCESS_GET_EXAMPLES).trackedAction(processContext, async (processKey, feedId, options) => {
3207
+ const { getLoginStatusAsync } = await import("./index-1kgxzh8x.js");
3208
+ const [loginError, loginStatus] = await catchError(getLoginStatusAsync({
3209
+ ensureTokenValidityMinutes: options.loginValidity
3210
+ }));
3211
+ if (loginError) {
3212
+ OutputFormatter.error({
3213
+ Result: RESULTS.Failure,
3214
+ Message: loginError.message,
3215
+ Instructions: instructionsFor("auth")
3216
+ });
3217
+ processContext.exit(1);
3218
+ return;
3219
+ }
3220
+ if (loginStatus.loginStatus !== "Logged in" || !loginStatus.baseUrl) {
3221
+ OutputFormatter.error({
3222
+ Result: RESULTS.Failure,
3223
+ Message: "Not logged in. Run 'uip login' first.",
3224
+ Instructions: instructionsFor("auth")
3225
+ });
3226
+ processContext.exit(1);
3227
+ return;
3228
+ }
3229
+ const tenantName = options.tenant || loginStatus.tenantName;
3230
+ if (!tenantName) {
3231
+ OutputFormatter.error({
3232
+ Result: RESULTS.Failure,
3233
+ Message: "Tenant not provided and not available from login. Run 'uip login' or 'uip login tenant set <tenant>'.",
3234
+ Instructions: instructionsFor("identity")
3235
+ });
3236
+ processContext.exit(1);
3237
+ return;
3238
+ }
3239
+ if (!loginStatus.organizationId) {
3240
+ OutputFormatter.error({
3241
+ Result: RESULTS.Failure,
3242
+ Message: "Organization ID not available from login.",
3243
+ Instructions: instructionsFor("identity")
3244
+ });
3245
+ processContext.exit(1);
3246
+ return;
3247
+ }
3248
+ const config = {
3249
+ processKey,
3250
+ folderKey: options.folderKey,
3251
+ inputs: {},
3252
+ authToken: loginStatus.accessToken || "",
3253
+ organizationId: loginStatus.organizationId,
3254
+ tenantName,
3255
+ baseUrl: loginStatus.baseUrl,
3256
+ feedId
3257
+ };
3258
+ const { getFlowEntryPoints } = await import("./flow-api-wv8p8xbd.js");
3259
+ const [entryPointsError, entryPoints] = await catchError(getFlowEntryPoints(config));
3260
+ if (entryPointsError) {
3261
+ OutputFormatter.error({
3262
+ Result: RESULTS.Failure,
3263
+ Message: entryPointsError.message,
3264
+ Instructions: instructionsFor("backend", entryPointsError)
3265
+ });
3266
+ processContext.exit(1);
3267
+ return;
3268
+ }
3269
+ if (entryPoints.length === 0) {
3270
+ OutputFormatter.error({
3271
+ Result: RESULTS.Failure,
3272
+ Message: "No entry points found for this process.",
3273
+ Instructions: "Verify the process key is correct and published."
3274
+ });
3275
+ processContext.exit(1);
3276
+ return;
3277
+ }
3278
+ const formattedData = entryPoints.map((ep) => {
3279
+ const [, inputSchema] = catchError(() => JSON.parse(ep.InputArguments));
3280
+ const [, outputSchema] = catchError(() => JSON.parse(ep.OutputArguments));
3281
+ return {
3282
+ Path: ep.Path,
3283
+ DisplayName: ep.DisplayName,
3284
+ Type: ep.Type,
3285
+ InputSchema: JSON.stringify(inputSchema ?? {}, null, 2),
3286
+ OutputSchema: JSON.stringify(outputSchema ?? {}, null, 2)
3287
+ };
3288
+ });
3289
+ OutputFormatter.success({
3290
+ Result: RESULTS.Success,
3291
+ Code: "FlowProjectGet",
3292
+ Data: formattedData,
3293
+ Instructions: `Found ${entryPoints.length} entry point(s) for ${processKey}`
3294
+ });
3295
+ });
3296
+ processCmd.command("run").description("Run a Flow project with inputs").argument("<process-key>", "Process key (e.g., MyFlow.flow.Flow:1.0.0)").argument("<folder-key>", "Folder key (GUID)").option("-i, --inputs <json>", "Input parameters as JSON string or @file.json").option("--attachment <name=path>", "Upload a local file as a file-typed workflow input variable (repeatable). Example: --attachment file1=./resume.pdf", appendOption, []).addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).option("--release-key <key>", "Release key (GUID, from list command)").option("--feed-id <id>", "Feed ID for package lookup (optional)").option("--robot-ids <ids>", "Comma-separated robot IDs (optional)").option("--validate", "Validate inputs against project schema (basic: required fields + primitive types)").option("--login-validity <minutes>", "Minimum minutes before token expiration to trigger a refresh (default: 10)", parseInt, 10).option("--wait", "Block until the job reaches a terminal state (Successful, Faulted, Stopped)").option("--timeout <seconds>", "Maximum seconds to wait (0 = no timeout). Requires --wait.", String(DEFAULT_TIMEOUT_MS / 1000)).option("--poll-interval <seconds>", "Seconds between status checks. Requires --wait.", String(DEFAULT_INTERVAL_MS / 1000)).examples(FLOW_PROCESS_RUN_EXAMPLES).trackedAction(processContext, async (processKey, folderKey, options) => {
3297
+ const { getLoginStatusAsync } = await import("./index-1kgxzh8x.js");
3298
+ const {
3299
+ parseFlowInputs,
3300
+ startFlowProjectJob,
3301
+ validateFlowInputs
3302
+ } = await import("./flow-api-wv8p8xbd.js");
3303
+ const [loginError, loginStatus] = await catchError(getLoginStatusAsync({
3304
+ ensureTokenValidityMinutes: options.loginValidity
3305
+ }));
3306
+ if (loginError) {
3307
+ OutputFormatter.error({
3308
+ Result: RESULTS.Failure,
3309
+ Message: loginError.message,
3310
+ Instructions: instructionsFor("auth")
3311
+ });
3312
+ processContext.exit(1);
3313
+ return;
3314
+ }
3315
+ if (loginStatus.loginStatus !== "Logged in" || !loginStatus.baseUrl) {
3316
+ OutputFormatter.error({
3317
+ Result: RESULTS.Failure,
3318
+ Message: "Not logged in. Run 'uip login' first.",
3319
+ Instructions: instructionsFor("auth")
3320
+ });
3321
+ processContext.exit(1);
3322
+ return;
3323
+ }
3324
+ const tenantName = options.tenant || loginStatus.tenantName;
3325
+ if (!tenantName) {
3326
+ OutputFormatter.error({
3327
+ Result: RESULTS.Failure,
3328
+ Message: "Tenant not provided and not available from login. Run 'uip login' or 'uip login tenant set <tenant>'.",
3329
+ Instructions: instructionsFor("identity")
3330
+ });
3331
+ processContext.exit(1);
3332
+ return;
3333
+ }
3334
+ if (!loginStatus.organizationId) {
3335
+ OutputFormatter.error({
3336
+ Result: RESULTS.Failure,
3337
+ Message: "Organization ID not available from login.",
3338
+ Instructions: instructionsFor("identity")
3339
+ });
3340
+ processContext.exit(1);
3341
+ return;
3342
+ }
3343
+ let inputs = {};
3344
+ if (options.inputs) {
3345
+ const [parseError, parsed] = await catchError(parseFlowInputs(options.inputs));
3346
+ if (parseError) {
3347
+ OutputFormatter.error({
3348
+ Result: RESULTS.Failure,
3349
+ Message: parseError.message,
3350
+ Instructions: instructionsFor("input-parse")
3351
+ });
3352
+ processContext.exit(1);
3353
+ return;
3354
+ }
3355
+ inputs = parsed;
3356
+ } else {
3357
+ const { readStdin } = await import("./input-reader-6pwhtp8v.js");
3358
+ const [stdinError, stdinData] = await catchError(readStdin());
3359
+ if (stdinError) {
3360
+ OutputFormatter.error({
3361
+ Result: RESULTS.Failure,
3362
+ Message: stdinError.message,
3363
+ Instructions: instructionsFor("input-parse")
3364
+ });
3365
+ processContext.exit(1);
3366
+ return;
3367
+ }
3368
+ if (stdinData) {
3369
+ const [parseError, parsed] = await catchError(parseFlowInputs(stdinData));
3370
+ if (parseError) {
3371
+ OutputFormatter.error({
3372
+ Result: RESULTS.Failure,
3373
+ Message: parseError.message,
3374
+ Instructions: instructionsFor("input-parse")
3375
+ });
3376
+ processContext.exit(1);
3377
+ return;
3378
+ }
3379
+ inputs = parsed;
3380
+ }
3381
+ }
3382
+ const attachmentSpecs = options.attachment ?? [];
3383
+ if (attachmentSpecs.length > 0) {
3384
+ const [parseError, specs] = catchError(() => attachmentSpecs.map(parseAttachmentSpec));
3385
+ if (parseError) {
3386
+ OutputFormatter.error({
3387
+ Result: RESULTS.Failure,
3388
+ Message: parseError.message,
3389
+ Instructions: ATTACHMENT_INSTRUCTIONS
3390
+ });
3391
+ processContext.exit(1);
3392
+ return;
3393
+ }
3394
+ const { uploadJobAttachment } = await import("./index-ev4mdg5y.js");
3395
+ const [uploadError, resolved] = await catchError(resolveAttachmentInputs(specs, (bytes, fileName) => uploadJobAttachment(bytes, fileName, {
3396
+ tenant: tenantName
3397
+ })));
3398
+ if (uploadError) {
3399
+ OutputFormatter.error({
3400
+ Result: RESULTS.Failure,
3401
+ Message: uploadError.message,
3402
+ Instructions: ATTACHMENT_UPLOAD_INSTRUCTIONS
3403
+ });
3404
+ processContext.exit(1);
3405
+ return;
3406
+ }
3407
+ for (const { name, path, reference } of resolved) {
3408
+ if (name in inputs) {
3409
+ logger.warn(`--attachment '${name}' overrides the value provided in --inputs.`);
3410
+ }
3411
+ inputs[name] = reference;
3412
+ logger.info(`Uploaded '${path}' as attachment ${reference.ID} (variable '${name}').`);
3413
+ }
3414
+ }
3415
+ const config = {
3416
+ processKey,
3417
+ folderKey,
3418
+ inputs,
3419
+ authToken: loginStatus.accessToken || "",
3420
+ organizationId: loginStatus.organizationId,
3421
+ tenantName,
3422
+ tenantId: loginStatus.tenantId,
3423
+ baseUrl: loginStatus.baseUrl,
3424
+ releaseKey: options.releaseKey,
3425
+ feedId: options.feedId
3426
+ };
3427
+ if (options.robotIds) {
3428
+ config.robotIds = options.robotIds.split(",").map((id) => parseInt(id.trim(), 10));
3429
+ if (config.robotIds.some((id) => Number.isNaN(id))) {
3430
+ OutputFormatter.error({
3431
+ Result: RESULTS.Failure,
3432
+ Message: `Invalid robot-ids: ${options.robotIds}. Must be comma-separated numbers.`,
3433
+ Instructions: instructionsFor("flag-format")
3434
+ });
3435
+ processContext.exit(1);
3436
+ return;
3437
+ }
3438
+ }
3439
+ if (options.validate) {
3440
+ const [valError, validation] = await catchError(validateFlowInputs(config, inputs));
3441
+ if (valError) {
3442
+ const code = flowProcessRunErrorCode(valError);
3443
+ OutputFormatter.error({
3444
+ Result: RESULTS.Failure,
3445
+ ...code ? { Code: code } : {},
3446
+ Message: valError.message,
3447
+ Instructions: instructionsFor("backend", valError)
3448
+ });
3449
+ processContext.exit(1);
3450
+ return;
3451
+ }
3452
+ if (!validation.valid) {
3453
+ const validationErrors = validation.errors ?? [];
3454
+ const errorList = validationErrors.length > 0 ? validationErrors.map((error) => `- ${error}`).join(`
3455
+ `) : "No validation details returned.";
3456
+ OutputFormatter.error({
3457
+ Result: RESULTS.Failure,
3458
+ Message: `Input validation failed:
3459
+ ${errorList}`,
3460
+ Instructions: instructionsFor("input-validate")
3461
+ });
3462
+ processContext.exit(1);
3463
+ return;
3464
+ }
3465
+ logger.info("✅ Input validation passed");
3466
+ }
3467
+ let timeoutMs;
3468
+ let intervalMs;
3469
+ if (options.wait) {
3470
+ const timeoutS = Number(options.timeout);
3471
+ const intervalS = Number(options.pollInterval);
3472
+ if (!Number.isFinite(timeoutS) || timeoutS < 0) {
3473
+ OutputFormatter.error({
3474
+ Result: "Failure",
3475
+ Message: `Invalid --timeout value: '${options.timeout}'. Must be a non-negative number.`,
3476
+ Instructions: "Pass seconds, e.g. --timeout 300"
3477
+ });
3478
+ processContext.exit(1);
3479
+ return;
3480
+ }
3481
+ if (!Number.isFinite(intervalS) || intervalS <= 0) {
3482
+ OutputFormatter.error({
3483
+ Result: "Failure",
3484
+ Message: `Invalid --poll-interval value: '${options.pollInterval}'. Must be a positive number.`,
3485
+ Instructions: "Pass seconds, e.g. --poll-interval 10"
3486
+ });
3487
+ processContext.exit(1);
3488
+ return;
3489
+ }
3490
+ timeoutMs = timeoutS * 1000;
3491
+ intervalMs = intervalS * 1000;
3492
+ }
3493
+ if (config.releaseKey === undefined) {
3494
+ const [resolveError, resolvedReleaseKey] = await catchError(resolveReleaseKey(config, processKey));
3495
+ if (resolveError) {
3496
+ OutputFormatter.error({
3497
+ Result: RESULTS.Failure,
3498
+ Code: "FlowReleaseKeyRequired",
3499
+ Message: resolveError.message,
3500
+ Instructions: `Run 'uip maestro flow process list --folder-key ${folderKey}' and pass the matching releaseKey as --release-key.`
3501
+ });
3502
+ processContext.exit(1);
3503
+ return;
3504
+ }
3505
+ config.releaseKey = resolvedReleaseKey;
3506
+ logger.info(`Resolved --release-key ${resolvedReleaseKey} for process ${processKey}.`);
3507
+ }
3508
+ const [jobError, job] = await catchError(startFlowProjectJob(config));
3509
+ if (jobError) {
3510
+ const code = flowProcessRunErrorCode(jobError);
3511
+ OutputFormatter.error({
3512
+ Result: RESULTS.Failure,
3513
+ ...code ? { Code: code } : {},
3514
+ Message: jobError.message,
3515
+ Instructions: instructionsFor("backend", jobError)
3516
+ });
3517
+ processContext.exit(1);
3518
+ return;
3519
+ }
3520
+ OutputFormatter.success({
3521
+ Result: RESULTS.Success,
3522
+ Code: "FlowJobStarted",
3523
+ Data: {
3524
+ jobKey: job.key,
3525
+ state: job.state,
3526
+ traceId: job.traceId,
3527
+ folderKey
3528
+ },
3529
+ Instructions: `Watch traces: uip maestro flow job traces ${job.key} --folder-key ${folderKey}`
3530
+ });
3531
+ if (!options.wait) {
3532
+ processContext.exit(0);
3533
+ return;
3534
+ }
3535
+ if (!job.key) {
3536
+ OutputFormatter.error({
3537
+ Result: "Failure",
3538
+ Message: "Job started but no key returned — cannot wait",
3539
+ Instructions: "Check the job in Orchestrator or retry without --wait."
3540
+ });
3541
+ processContext.exit(1);
3542
+ return;
3543
+ }
3544
+ const { handleFlowJobWait } = await import("./wait-for-flow-job-45p1a444.js");
3545
+ await handleFlowJobWait(job.key, {
3546
+ config,
3547
+ timeoutMs,
3548
+ intervalMs
3549
+ });
3550
+ });
3551
+ }
3552
+
3553
+ // src/commands/processes.ts
3554
+ var registerProcessesCommand = (program) => {
3555
+ registerSharedProcessesCommands(program, {
3556
+ toolLabel: "Flow",
3557
+ processType: "Flow"
3558
+ });
3559
+ };
3560
+
3561
+ // src/commands/publish.ts
3562
+ var FLOW_PUBLISH_EXAMPLES = [
3563
+ {
3564
+ Description: "Pack and publish a Flow project to Orchestrator",
3565
+ Command: "uip maestro flow publish ./my-flow-project --version 1.2.0",
3566
+ Output: {
3567
+ Code: "FlowPublish",
3568
+ Data: {
3569
+ Package: "my-flow-project@1.2.0",
3570
+ PackagePath: "/tmp/flow-publish-1710000000000/my-flow-project.flow.Flow.1.2.0.nupkg",
3571
+ Upload: [
3572
+ {
3573
+ key: "my-flow-project.flow.Flow.1.2.0.nupkg",
3574
+ status: "Created"
3575
+ }
3576
+ ]
3577
+ }
3578
+ }
3579
+ }
3580
+ ];
3581
+ function getDefaultOutputPath(fs = getFileSystem()) {
3582
+ return fs.path.join(fs.env.tmpdir(), `flow-publish-${Date.now()}`);
3583
+ }
3584
+ var registerPublishCommand = (program) => {
3585
+ program.command("publish").description("Pack a Flow project and upload the resulting .nupkg to Orchestrator packages").argument("<project-path>", "Path to the Flow project directory").argument("[output-path]", "Output directory where the generated .nupkg will be saved").option("-n, --name <name>", "Package name (default: project folder name)").option("-v, --version <version>", "Package version (default: 1.0.0)", "1.0.0").addOption(createHiddenDeprecatedTenantOption("-t, --tenant <tenant-name>")).option("--feed-id <feedId>", "Feed ID (optional, defaults to tenant feed). Mutually exclusive with --folder-key/--folder-path.").option("--folder-key <key>", "Folder key (GUID) of an Orchestrator folder hierarchy feed. The CLI resolves the folder's feed ID automatically. Mutually exclusive with --feed-id and --folder-path.").option("--folder-path <path>", "Folder path (e.g. 'Shared/Sub') of an Orchestrator folder hierarchy feed. The CLI resolves the folder's feed ID automatically. Mutually exclusive with --feed-id and --folder-key.").examples(FLOW_PUBLISH_EXAMPLES).trackedAction(processContext, async (projectPath, outputPath, options) => {
3586
+ const { getLoginStatusAsync } = await import("./index-1kgxzh8x.js");
3587
+ const {
3588
+ createApiClient,
3589
+ PackageFeedsApi,
3590
+ ProcessesApi,
3591
+ resolveFolder
3592
+ } = await import("./index-ev4mdg5y.js");
3593
+ const fs = getFileSystem();
3594
+ const shouldCleanupOutput = outputPath === undefined;
3595
+ const packageOutputPath = outputPath ?? getDefaultOutputPath(fs);
3596
+ try {
3597
+ const [loginError, loginStatus] = await catchError(getLoginStatusAsync());
3598
+ if (loginError) {
3599
+ OutputFormatter.error({
3600
+ Result: RESULTS.Failure,
3601
+ Message: loginError.message,
3602
+ Instructions: instructionsFor("auth", loginError)
3603
+ });
3604
+ processContext.exit(1);
3605
+ return;
3606
+ }
3607
+ if (loginStatus.loginStatus !== "Logged in" || !loginStatus.baseUrl) {
3608
+ OutputFormatter.error({
3609
+ Result: RESULTS.Failure,
3610
+ Message: "Not logged in. Run 'uip login' first.",
3611
+ Instructions: instructionsFor("auth")
3612
+ });
3613
+ processContext.exit(1);
3614
+ return;
3615
+ }
3616
+ const folderTargetingSpecified = options.folderKey !== undefined || options.folderPath !== undefined;
3617
+ if (folderTargetingSpecified && options.feedId) {
3618
+ OutputFormatter.error({
3619
+ Result: RESULTS.ValidationError,
3620
+ Message: "Cannot combine --feed-id with --folder-key/--folder-path.",
3621
+ Instructions: "Pass either --feed-id (raw feed) or --folder-key/--folder-path (the CLI resolves the feed) — not both."
3622
+ });
3623
+ processContext.exit(3);
3624
+ return;
3625
+ }
3626
+ if (options.folderKey !== undefined && options.folderPath !== undefined) {
3627
+ OutputFormatter.error({
3628
+ Result: RESULTS.ValidationError,
3629
+ Message: "Cannot combine --folder-key with --folder-path.",
3630
+ Instructions: "Pass either --folder-key or --folder-path to identify the folder feed — not both."
3631
+ });
3632
+ processContext.exit(3);
3633
+ return;
3634
+ }
3635
+ let resolvedFeedId = options.feedId;
3636
+ if (folderTargetingSpecified) {
3637
+ const [folderError, folder] = await catchError(resolveFolder({
3638
+ folderKey: options.folderKey,
3639
+ folderPath: options.folderPath
3640
+ }, { tenant: options.tenant }));
3641
+ if (folderError || !folder) {
3642
+ const message = folderError ? `Could not resolve folder: ${folderError.message}` : "Folder targeting requested but no folder resolved.";
3643
+ OutputFormatter.error({
3644
+ Result: RESULTS.ValidationError,
3645
+ Message: message,
3646
+ Instructions: "Provide a valid --folder-key or --folder-path. Use 'uip or folders list' to confirm the key or path."
3647
+ });
3648
+ processContext.exit(3);
3649
+ return;
3650
+ }
3651
+ const [feedsApiError, feedsApi] = await catchError(createApiClient(PackageFeedsApi, {
3652
+ tenant: options.tenant
3653
+ }));
3654
+ if (feedsApiError) {
3655
+ OutputFormatter.error({
3656
+ Result: RESULTS.Failure,
3657
+ Message: "Flow publish failed",
3658
+ Instructions: "Could not create the feeds API client. Re-authenticate and verify the tenant name before trying again."
3659
+ });
3660
+ processContext.exit(1);
3661
+ return;
3662
+ }
3663
+ const [feedLookupError, folderFeedId] = await catchError(feedsApi.packageFeedsGetFolderFeed({
3664
+ folderId: folder.id
3665
+ }));
3666
+ if (feedLookupError || !folderFeedId) {
3667
+ const detail = feedLookupError ? await extractErrorMessage(feedLookupError) : "Folder has no associated package feed.";
3668
+ OutputFormatter.error({
3669
+ Result: RESULTS.Failure,
3670
+ Message: `Could not resolve folder feed for '${folder.path}': ${detail}`,
3671
+ Instructions: "Confirm the folder has FeedType 'FolderHierarchy' (see 'uip or folders get'). Tenant-scoped folders use the default tenant feed and don't need folder targeting."
3672
+ });
3673
+ processContext.exit(1);
3674
+ return;
3675
+ }
3676
+ resolvedFeedId = folderFeedId;
3677
+ }
3678
+ const { FlowPackService } = await import("./flow-pack-service-p4hxyj9e.js");
3679
+ const service = new FlowPackService;
3680
+ const [packError, packResult] = await catchError(service.executeAsync(projectPath, {
3681
+ output: packageOutputPath,
3682
+ name: options.name,
3683
+ version: options.version
3684
+ }));
3685
+ if (packError) {
3686
+ OutputFormatter.error({
3687
+ Result: RESULTS.Failure,
3688
+ Message: `Flow publish failed: ${packError.message}`,
3689
+ Instructions: "Fix the Flow project packaging error and run the command again."
3690
+ });
3691
+ processContext.exit(1);
3692
+ return;
3693
+ }
3694
+ if (!packResult.success || !packResult.outputPath) {
3695
+ OutputFormatter.error({
3696
+ Result: RESULTS.Failure,
3697
+ Message: `Flow publish failed: ${packResult.message || "Could not pack the Flow project."}`,
3698
+ Instructions: "Fix the Flow project packaging error and run the command again."
3699
+ });
3700
+ processContext.exit(1);
3701
+ return;
3702
+ }
3703
+ const [apiError, api] = await catchError(createApiClient(ProcessesApi, {
3704
+ tenant: options.tenant
3705
+ }));
3706
+ if (apiError) {
3707
+ OutputFormatter.error({
3708
+ Result: RESULTS.Failure,
3709
+ Message: "Flow publish failed",
3710
+ Instructions: "Authenticate with 'uip auth login' and verify the tenant name before trying again."
3711
+ });
3712
+ processContext.exit(1);
3713
+ return;
3714
+ }
3715
+ const [readError, fileBuffer] = await catchError(fs.readFile(packResult.outputPath));
3716
+ if (readError) {
3717
+ OutputFormatter.error({
3718
+ Result: RESULTS.Failure,
3719
+ Message: `Flow publish failed: ${readError.message}`,
3720
+ Instructions: `Verify the generated package exists at '${packResult.outputPath}' and that the current user can read it.`
3721
+ });
3722
+ processContext.exit(1);
3723
+ return;
3724
+ }
3725
+ const fileName = fs.path.basename(packResult.outputPath);
3726
+ const file = new File([fileBuffer], fileName, {
3727
+ type: "application/octet-stream"
3728
+ });
3729
+ const [uploadError, uploadResult] = await catchError(api.processesUploadPackage({
3730
+ file,
3731
+ feedId: resolvedFeedId
3732
+ }));
3733
+ if (uploadError) {
3734
+ const errorMessage = await extractErrorMessage(uploadError);
3735
+ OutputFormatter.error({
3736
+ Result: RESULTS.Failure,
3737
+ Message: `Flow package upload failed: ${errorMessage}`,
3738
+ Instructions: "Verify the tenant or feed ID, confirm you have package upload permissions, and retry with a new package version if the version already exists."
3739
+ });
3740
+ processContext.exit(1);
3741
+ return;
3742
+ }
3743
+ const shipped = packResult.packageName ? splitPackagedName(packResult.packageName) : undefined;
3744
+ trackShipSucceeded({
3745
+ ship_kind: "publish",
3746
+ target: folderTargetingSpecified ? "orchestrator_folder_package_feed" : resolvedFeedId ? "orchestrator_package_feed" : "orchestrator_tenant_package_feed",
3747
+ project_type: "flow",
3748
+ command_name: "uip.flow.publish",
3749
+ ...shipped ? { package_name: shipped.name } : {},
3750
+ ...shipped?.version ? { package_version: shipped.version } : {}
3751
+ });
3752
+ OutputFormatter.success({
3753
+ Result: RESULTS.Success,
3754
+ Code: "FlowPublish",
3755
+ Data: {
3756
+ Package: packResult.packageName ?? "",
3757
+ PackagePath: packResult.outputPath,
3758
+ Upload: uploadResult.value ?? []
3759
+ }
3760
+ });
3761
+ } finally {
3762
+ if (shouldCleanupOutput) {
3763
+ await catchError(fs.rm(packageOutputPath));
3764
+ }
3765
+ }
3766
+ });
3767
+ };
3768
+
3769
+ // src/commands/registry.ts
3770
+ var registerRegistryCommand2 = (program) => {
3771
+ registerRegistryCommand(program, "maestro flow");
3772
+ };
3773
+
3774
+ // src/commands/tidy.ts
3775
+ var registerTidyCommand = (program) => {
3776
+ program.command("format").description("Format a .flow file by auto-laying out nodes to prevent overlaps and arrange in a clean flow").argument("<file>", "Path to the .flow file").trackedAction(processContext, async (file) => {
3777
+ const { tidyFlow } = await import("./tidy-service-ashgyfwj.js");
3778
+ const [error, result] = await catchError(tidyFlow(file));
3779
+ if (error) {
3780
+ OutputFormatter.error({
3781
+ Result: RESULTS.Failure,
3782
+ Message: "Failed to tidy flow",
3783
+ Instructions: error.message
3784
+ });
3785
+ processContext.exit(1);
3786
+ return;
3787
+ }
3788
+ const changes = [];
3789
+ if (result.nodesRepositioned > 0) {
3790
+ changes.push(`Repositioned ${result.nodesRepositioned} of ${result.nodeCount} nodes`);
3791
+ }
3792
+ if (result.nodesResized > 0) {
3793
+ changes.push(`Set canonical size on ${result.nodesResized} node(s)`);
3794
+ }
3795
+ if (result.subflowsTidied > 0) {
3796
+ changes.push(`Tidied ${result.subflowsTidied} subflow(s)`);
3797
+ }
3798
+ OutputFormatter.success({
3799
+ Result: RESULTS.Success,
3800
+ Code: "FlowFormat",
3801
+ Data: {
3802
+ File: file,
3803
+ NodesTotal: result.nodeCount,
3804
+ EdgesTotal: result.edgeCount,
3805
+ NodesRepositioned: result.nodesRepositioned,
3806
+ NodesResized: result.nodesResized,
3807
+ SubflowsTidied: result.subflowsTidied,
3808
+ VariableCount: result.variableCount
3809
+ },
3810
+ Instructions: changes.length > 0 ? changes.join(". ") : "All nodes already in optimal positions"
3811
+ });
3812
+ });
3813
+ };
3814
+
3815
+ // src/commands/validate.ts
3816
+ var STRICT_EXPRESSIONS_DEFAULT = false;
3817
+ var FLOW_VALIDATE_EXAMPLES = [
3818
+ {
3819
+ Description: "Validate a .flow file against the flow schema",
3820
+ Command: "uip maestro flow validate flow.json",
3821
+ Output: {
3822
+ Code: "FlowValidate",
3823
+ Data: {
3824
+ File: "flow.json",
3825
+ Status: "Valid"
3826
+ }
3827
+ }
3828
+ },
3829
+ {
3830
+ Description: "Validate with governance policy checks (requires login)",
3831
+ Command: "uip maestro flow validate flow.json --governance",
3832
+ Output: {
3833
+ Code: "FlowValidate",
3834
+ Data: {
3835
+ File: "flow.json",
3836
+ Status: "Valid"
3837
+ }
3838
+ }
3839
+ },
3840
+ {
3841
+ Description: "Treat connector-shaped Managed HTTP nodes without a binding as errors (CI-grade gate)",
3842
+ Command: "uip maestro flow validate flow.json --strict-bindings",
3843
+ Output: {
3844
+ Code: "FlowValidate",
3845
+ Data: {
3846
+ File: "flow.json",
3847
+ Status: "Valid"
3848
+ }
3849
+ }
3850
+ },
3851
+ {
3852
+ Description: "Validate a project directory — resolves the project's .flow (project.uiproj MainFile)",
3853
+ Command: "uip maestro flow validate ./my-flow-project",
3854
+ Output: {
3855
+ Code: "FlowValidate",
3856
+ Data: {
3857
+ File: "my-flow-project/Main.flow",
3858
+ Status: "Valid"
3859
+ }
3860
+ }
3861
+ },
3862
+ {
3863
+ Description: "Fail validation on expression and script type errors (they are warnings by default)",
3864
+ Command: "uip maestro flow validate flow.json --strict-expressions",
3865
+ Output: {
3866
+ Code: "FlowValidate",
3867
+ Data: {
3868
+ File: "flow.json",
3869
+ Status: "Valid"
3870
+ }
3871
+ }
3872
+ }
3873
+ ];
3874
+ var registerValidateCommand = (program) => {
3875
+ program.command("validate").description("Validate a .flow file (or a project directory containing one) against the Flow schema").argument("<flowFile>", "Path to the .flow file (or a project directory containing one) to validate").option("--governance", "Validate agent nodes against organization governance policies (requires login)").option("--strict-bindings", "Fail validation when a Managed HTTP node (core.action.http.v2) carries a connector-shaped label but no Integration Service binding. Default: warn only.").option("--strict-expressions", "Fail validation when an expression or script body has a type error. The check always runs, using the shared Flow expression checker (the same engine the canvas runs); its findings are warnings by default. Default: warn only.").examples(FLOW_VALIDATE_EXAMPLES).trackedAction(processContext, async (flowFile, options) => {
3876
+ let governanceEnforcements;
3877
+ let availableModelNames;
3878
+ if (options.governance) {
3879
+ const { fetchGovernanceData } = await import("./governance-fetcher-j9cx4f1d.js");
3880
+ const [error, data] = await catchError(fetchGovernanceData());
3881
+ if (error) {
3882
+ OutputFormatter.error({
3883
+ Result: RESULTS.Failure,
3884
+ Message: `Could not fetch governance data: ${error.message}`,
3885
+ Instructions: "Ensure you are logged in and the platform is reachable, or omit --governance to skip policy checks."
3886
+ });
3887
+ processContext.exit(1);
3888
+ return;
3889
+ }
3890
+ governanceEnforcements = data.enforcements;
3891
+ availableModelNames = data.modelNames;
3892
+ }
3893
+ const { FlowValidateService } = await import("./flow-validate-service-j25pxpwz.js");
3894
+ const service = new FlowValidateService({
3895
+ governanceEnforcements,
3896
+ availableModelNames,
3897
+ validateCurrentManifests: true,
3898
+ strictBindings: options.strictBindings === true,
3899
+ strictExpressions: options.strictExpressions ?? STRICT_EXPRESSIONS_DEFAULT
3900
+ });
3901
+ const exitCode = await service.execute(flowFile);
3902
+ if (exitCode) {
3903
+ processContext.exit(exitCode);
3904
+ }
3905
+ });
3906
+ };
3907
+
3908
+ // src/commands/variable.ts
3909
+ var VARIABLE_ADD_EXAMPLES = [
3910
+ {
3911
+ Description: "Add a string input variable to a flow (auto-bound to the flow's trigger node, making it an entry-point input)",
3912
+ Command: "uip maestro flow variable add flow.json myInput --direction in --type string",
3913
+ Output: {
3914
+ Code: "VariableAddSuccess",
3915
+ Data: {
3916
+ Variable: {
3917
+ id: "myInput",
3918
+ direction: "in",
3919
+ type: "string",
3920
+ triggerNodeId: "manualTrigger1"
3921
+ }
3922
+ }
3923
+ }
3924
+ },
3925
+ {
3926
+ Description: "Bind an input to a specific trigger when the flow has several entry points",
3927
+ Command: "uip maestro flow variable add flow.json myInput --direction in --type string --trigger-node-id timerTrigger1",
3928
+ Output: {
3929
+ Code: "VariableAddSuccess",
3930
+ Data: {
3931
+ Variable: {
3932
+ id: "myInput",
3933
+ direction: "in",
3934
+ type: "string",
3935
+ triggerNodeId: "timerTrigger1"
3936
+ }
3937
+ }
3938
+ }
3939
+ }
3940
+ ];
3941
+ var VARIABLE_DELETE_EXAMPLES = [
3942
+ {
3943
+ Description: "Remove a variable from a flow",
3944
+ Command: "uip maestro flow variable remove flow.json myInput",
3945
+ Output: {
3946
+ Code: "VariableRemoveSuccess",
3947
+ Data: {
3948
+ DeletedVariable: {
3949
+ id: "myInput",
3950
+ direction: "in",
3951
+ type: "string"
3952
+ }
3953
+ }
3954
+ }
3955
+ }
3956
+ ];
3957
+ var VARIABLE_LIST_EXAMPLES = [
3958
+ {
3959
+ Description: "List all variables in a flow file",
3960
+ Command: "uip maestro flow variable list flow.json",
3961
+ Output: {
3962
+ Code: "VariableListSuccess",
3963
+ Data: {
3964
+ Variables: [
3965
+ { id: "myInput", direction: "in", type: "string" },
3966
+ { id: "result", direction: "out", type: "object" }
3967
+ ],
3968
+ Count: 2
3969
+ }
3970
+ }
3971
+ }
3972
+ ];
3973
+ var VALID_TYPES = ["string", "number", "boolean", "object", "array", "file"];
3974
+ var VALID_DIRECTIONS = ["in", "out", "inout"];
3975
+ function parseDefaultValue(value, type) {
3976
+ switch (type) {
3977
+ case "string":
3978
+ return { parsed: value };
3979
+ case "number": {
3980
+ const num = parseFloat(value);
3981
+ if (Number.isNaN(num)) {
3982
+ return {
3983
+ error: `Invalid default value for type 'number': '${value}'`
3984
+ };
3985
+ }
3986
+ return { parsed: num };
3987
+ }
3988
+ case "boolean": {
3989
+ if (value !== "true" && value !== "false") {
3990
+ return {
3991
+ error: `Invalid default value for type 'boolean': '${value}'. Must be 'true' or 'false'`
3992
+ };
3993
+ }
3994
+ return { parsed: value === "true" };
3995
+ }
3996
+ case "object":
3997
+ case "array": {
3998
+ const [parseErr, parsedValue] = catchError(() => JSON.parse(value));
3999
+ if (parseErr) {
4000
+ return {
4001
+ error: `Invalid default value for type '${type}': must be valid JSON`
4002
+ };
4003
+ }
4004
+ if (type === "object" && (typeof parsedValue !== "object" || parsedValue === null || Array.isArray(parsedValue))) {
4005
+ return {
4006
+ error: `Invalid default value for type 'object': must be a JSON object`
4007
+ };
4008
+ }
4009
+ if (type === "array" && !Array.isArray(parsedValue)) {
4010
+ return {
4011
+ error: `Invalid default value for type 'array': must be a JSON array`
4012
+ };
4013
+ }
4014
+ return { parsed: parsedValue };
4015
+ }
4016
+ default:
4017
+ return { parsed: value };
4018
+ }
4019
+ }
4020
+ var registerVariableCommand = (program) => {
4021
+ const variable = program.command("variable").description("Manage variables in a Flow file");
4022
+ variable.command("add").description("Add a variable to a Flow file").argument("<file>", "Path to the .flow file").argument("<variable-id>", "Variable identifier (e.g. myInputVar)").requiredOption("-d, --direction <direction>", `Variable direction (${VALID_DIRECTIONS.join(", ")})`).option("-t, --type <type>", `Data type (${VALID_TYPES.join(", ")})`, "string").option("--default-value <value>", "Default value (parsed based on --type)").option("--description <text>", "Human-readable description").option("--schema <json>", "JSON schema for object/array types").option("--sub-type <subType>", "Sub-type for complex types").option("--trigger-node-id <nodeId>", "Trigger node an input variable belongs to (defaults to the flow's only trigger node; required when the flow has several)").examples(VARIABLE_ADD_EXAMPLES).trackedAction(processContext, async (file, variableId, options) => {
4023
+ const { validateIdentifier } = await import("./index-4zrwgb3c.js");
4024
+ const identifierError = validateIdentifier(variableId, []);
4025
+ if (identifierError) {
4026
+ OutputFormatter.error({
4027
+ Result: RESULTS.Failure,
4028
+ Message: `Invalid variable id '${variableId}'`,
4029
+ Instructions: identifierError
4030
+ });
4031
+ processContext.exit(1);
4032
+ return;
4033
+ }
4034
+ if (!VALID_DIRECTIONS.includes(options.direction)) {
4035
+ OutputFormatter.error({
4036
+ Result: RESULTS.Failure,
4037
+ Message: `Invalid --direction '${options.direction}'`,
4038
+ Instructions: `Must be one of: ${VALID_DIRECTIONS.join(", ")}`
4039
+ });
4040
+ processContext.exit(1);
4041
+ return;
4042
+ }
4043
+ if (!VALID_TYPES.includes(options.type)) {
4044
+ OutputFormatter.error({
4045
+ Result: RESULTS.Failure,
4046
+ Message: `Invalid --type '${options.type}'`,
4047
+ Instructions: `Must be one of: ${VALID_TYPES.join(", ")}`
4048
+ });
4049
+ processContext.exit(1);
4050
+ return;
4051
+ }
4052
+ let defaultValue;
4053
+ if (options.defaultValue !== undefined) {
4054
+ const result = parseDefaultValue(options.defaultValue, options.type);
4055
+ if ("error" in result) {
4056
+ OutputFormatter.error({
4057
+ Result: RESULTS.Failure,
4058
+ Message: result.error,
4059
+ Instructions: "Provide a valid default value for the specified type"
4060
+ });
4061
+ processContext.exit(1);
4062
+ return;
4063
+ }
4064
+ defaultValue = result.parsed;
4065
+ }
4066
+ let schema;
4067
+ if (options.schema !== undefined) {
4068
+ const [parseError, parsed] = catchError(() => JSON.parse(options.schema));
4069
+ if (parseError) {
4070
+ OutputFormatter.error({
4071
+ Result: RESULTS.Failure,
4072
+ Message: "Invalid --schema JSON",
4073
+ Instructions: parseError.message
4074
+ });
4075
+ processContext.exit(1);
4076
+ return;
4077
+ }
4078
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
4079
+ OutputFormatter.error({
4080
+ Result: RESULTS.Failure,
4081
+ Message: "Invalid --schema value",
4082
+ Instructions: `--schema must be a JSON object (e.g. '{"type": "string"}')`
4083
+ });
4084
+ processContext.exit(1);
4085
+ return;
4086
+ }
4087
+ schema = parsed;
4088
+ }
4089
+ const { addVariableToFlow } = await import("./variable-service-er7ph4br.js");
4090
+ const [error, variable2] = await catchError(addVariableToFlow(file, {
4091
+ id: variableId,
4092
+ direction: options.direction,
4093
+ type: options.type,
4094
+ subType: options.subType,
4095
+ defaultValue,
4096
+ description: options.description,
4097
+ schema,
4098
+ triggerNodeId: options.triggerNodeId
4099
+ }));
4100
+ if (error) {
4101
+ OutputFormatter.error({
4102
+ Result: RESULTS.Failure,
4103
+ Message: "Error adding variable",
4104
+ Instructions: error.message
4105
+ });
4106
+ processContext.exit(1);
4107
+ return;
4108
+ }
4109
+ OutputFormatter.success({
4110
+ Result: RESULTS.Success,
4111
+ Code: "VariableAddSuccess",
4112
+ Data: {
4113
+ Variable: variable2
4114
+ }
4115
+ });
4116
+ });
4117
+ variable.command("remove").description("Remove a variable from a Flow file").argument("<file>", "Path to the .flow file").argument("<variable-id>", "Variable identifier to remove").examples(VARIABLE_DELETE_EXAMPLES).trackedAction(processContext, async (file, variableId) => {
4118
+ const { validateIdentifier } = await import("./index-4zrwgb3c.js");
4119
+ const identifierError = validateIdentifier(variableId, []);
4120
+ if (identifierError) {
4121
+ OutputFormatter.error({
4122
+ Result: RESULTS.Failure,
4123
+ Message: `Invalid variable id '${variableId}'`,
4124
+ Instructions: identifierError
4125
+ });
4126
+ processContext.exit(1);
4127
+ return;
4128
+ }
4129
+ const { deleteVariableFromFlow } = await import("./variable-service-er7ph4br.js");
4130
+ const [error, deletedVariable] = await catchError(deleteVariableFromFlow(file, variableId));
4131
+ if (error) {
4132
+ OutputFormatter.error({
4133
+ Result: RESULTS.Failure,
4134
+ Message: "Error deleting variable",
4135
+ Instructions: error.message
4136
+ });
4137
+ processContext.exit(1);
4138
+ return;
4139
+ }
4140
+ OutputFormatter.success({
4141
+ Result: RESULTS.Success,
4142
+ Code: "VariableRemoveSuccess",
4143
+ Data: {
4144
+ DeletedVariable: deletedVariable
4145
+ }
4146
+ });
4147
+ });
4148
+ variable.command("list").description("List all variables in a Flow file").argument("<file>", "Path to the .flow file").examples(VARIABLE_LIST_EXAMPLES).trackedAction(processContext, async (file) => {
4149
+ const { listVariablesInFlow } = await import("./variable-service-er7ph4br.js");
4150
+ const [error, result] = await catchError(listVariablesInFlow(file));
4151
+ if (error) {
4152
+ OutputFormatter.error({
4153
+ Result: RESULTS.Failure,
4154
+ Message: "Error listing variables",
4155
+ Instructions: error.message
4156
+ });
4157
+ processContext.exit(1);
4158
+ return;
4159
+ }
4160
+ OutputFormatter.success({
4161
+ Result: RESULTS.Success,
4162
+ Code: "VariableListSuccess",
4163
+ Data: {
4164
+ Variables: result.variables,
4165
+ Count: result.count
4166
+ }
4167
+ });
4168
+ });
4169
+ };
4170
+
4171
+ // src/services/project-metadata-reader.ts
4172
+ async function readAgentProjectMetadata(projectDir) {
4173
+ const fs = getFileSystem();
4174
+ const [readError, content] = await catchError(fs.readFile(fs.path.join(projectDir, "agent.json"), "utf-8"));
4175
+ if (readError || typeof content !== "string") {
4176
+ logger.debug(`No readable agent.json in ${projectDir}; the node will describe an autonomous agent.`);
4177
+ return {};
4178
+ }
4179
+ const [parseError, parsed] = catchError(() => JSON.parse(content));
4180
+ if (parseError) {
4181
+ logger.debug(`Unparseable agent.json in ${projectDir}: ${parseError.message}. The node will describe an autonomous agent.`);
4182
+ return {};
4183
+ }
4184
+ const metadata = {};
4185
+ const isConversational = parsed.metadata?.isConversational;
4186
+ if (typeof isConversational === "boolean") {
4187
+ metadata.isConversational = isConversational;
4188
+ }
4189
+ const targetRuntime = parsed.metadata?.targetRuntime;
4190
+ if (typeof targetRuntime === "string") {
4191
+ metadata.targetRuntime = targetRuntime;
4192
+ }
4193
+ return metadata;
4194
+ }
4195
+ var agentProjectMetadataReader = (projectDir, projectType) => projectType === "Agent" ? readAgentProjectMetadata(projectDir) : Promise.resolve({});
4196
+
4197
+ // src/tool.ts
4198
+ var metadata = {
4199
+ name: "flow-tool",
4200
+ version: package_default.version,
4201
+ description: "Create, debug, and run UiPath Flow projects and jobs.",
4202
+ commandPrefix: "flow"
4203
+ };
4204
+ var registerCommands = async (program) => {
4205
+ setAgentProjectMetadataReader(agentProjectMetadataReader);
4206
+ if (isPreviewBuild()) {
4207
+ const { registerFlowAuthoringCommands } = await import("./authoring-wpa6d0vf.js");
4208
+ registerFlowAuthoringCommands(program);
4209
+ }
4210
+ registerInitCommand(program);
4211
+ registerPackCommand(program);
4212
+ registerPublishCommand(program);
4213
+ registerValidateCommand(program);
4214
+ registerDebugCommand(program);
4215
+ registerDebugInstancesCommand(program);
4216
+ registerEvalCommand(program);
4217
+ registerMigrateCommand(program);
4218
+ registerNodeCommand(program);
4219
+ registerEdgeCommand(program);
4220
+ registerBindingCommand(program);
4221
+ registerProcessCommand(program);
4222
+ registerJobCommand(program);
4223
+ registerRegistryCommand2(program);
4224
+ registerInstancesCommand(program);
4225
+ registerProcessesCommand(program);
4226
+ registerHitlCommand(program);
4227
+ registerIncidentsCommand(program);
4228
+ registerTidyCommand(program);
4229
+ registerVariableCommand(program);
4230
+ };
4231
+
4232
+ export { metadata, registerCommands };
4233
+
4234
+ //# debugId=FE9DC859F1DB521864756E2164756E21