@uipath/flow-tool 1.202.2 → 1.203.0-preview.180
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/THIRD-PARTY-NOTICES.md +48 -49
- package/dist/{authoring-cyybnqy9.js → authoring-tv4dh80p.js} +31 -9
- package/dist/{binding-service-xq110a7q.js → binding-service-1hjkvp7f.js} +37 -29
- package/dist/{connector-service-1jp3gvb1.js → connector-service-f50vt5ar.js} +225 -57
- package/dist/{conversion-FQTRFHRX-j8vsrk1c.js → conversion-FQTRFHRX-5bww6cg9.js} +11 -10
- package/dist/de-FGHEJRCI-gn4cf5gh.js +2697 -0
- package/dist/de-MUJPA4EB-dpg7t2rw.js +173 -0
- package/dist/{debug-conversation-trigger-q5jwq1x7.js → debug-conversation-trigger-nmd9v41y.js} +21 -18
- package/dist/{debug-http-client-4ev9xna7.js → debug-http-client-53qk6pc5.js} +2 -2
- package/dist/{debug-service-2skv6t3q.js → debug-service-nyk0s6mc.js} +3 -3
- package/dist/{edge-service-crgn8x3q.js → edge-service-qs0fmj4c.js} +19 -16
- package/dist/{index-4b8634za.js → embedded-file-reader-0sjt4nkj.js} +96 -16641
- package/dist/{en-TBNO2WUV-rfe87pgh.js → en-BWGKA5OE-1qkvb9rn.js} +2 -2
- package/dist/en-FBPVNKFN-dqt573xn.js +138 -0
- package/dist/en-TBNO2WUV-9nan43e5.js +1936 -0
- package/dist/es-7SE7HX2X-8yh1aj2y.js +173 -0
- package/dist/es-KR3ZSNMP-0cszm2n3.js +2697 -0
- package/dist/es-MX-2MYFZU7X-3rek4r73.js +173 -0
- package/dist/es-MX-XXZJGC4R-b4fbwe9d.js +2697 -0
- package/dist/first-party-service-srxaftkn.js +27 -0
- package/dist/{flow-api-p1jy8t6k.js → flow-api-f49qbvf6.js} +8 -8
- package/dist/{flow-debug-service-gtz48pcs.js → flow-debug-service-nvx6c5fm.js} +65 -40
- package/dist/{flow-eval-node-target-d4q72qzz.js → flow-eval-node-target-rv41h6g2.js} +24 -17
- package/dist/flow-eval-run-api-1bw5e0k4.js +13 -0
- package/dist/{flow-eval-run-service-bteardyh.js → flow-eval-run-service-bnpf0zhb.js} +105 -220
- package/dist/{flow-eval-service-8wn40enf.js → flow-eval-service-p0fbctsk.js} +350 -306
- package/dist/flow-init-service-6c5tj22g.js +42 -0
- package/dist/{flow-io-91tv36v5.js → flow-io-c05c9hc7.js} +18 -15
- package/dist/{flow-migrate-service-4mxge029.js → flow-migrate-service-6dky7rrg.js} +27 -23
- package/dist/{flow-pack-service-9s7wmwpf.js → flow-pack-service-3ms1t8nv.js} +44 -36
- package/dist/flow-validate-service-hq93ye0w.js +65 -0
- package/dist/fr-MDFKNZ4C-h4a122k9.js +173 -0
- package/dist/fr-Y6NPVODW-q5ef3htr.js +2697 -0
- package/dist/{governance-fetcher-kn29e4eb.js → governance-fetcher-7b0a301w.js} +6 -5
- package/dist/{headless-my7j1typ.js → headless-rkxtgwts.js} +42909 -1756
- package/dist/{hitl-service-fmrkamr4.js → hitl-service-fpdb3tf5.js} +18 -15
- package/dist/{index-1kgxzh8x.js → index-3ts7y9d3.js} +15 -3
- package/dist/{index-gbfvfhkw.js → index-4hhb8jhe.js} +6 -4
- package/dist/{index-apf8q9y0.js → index-51z10z84.js} +4 -4
- package/dist/{index-d1yqqk6q.js → index-55cym5j7.js} +6 -4
- package/dist/index-kmp9fmhb.js +25 -0
- package/dist/index-sc7ddh21.js +16742 -0
- package/dist/{index-acd6bpqc.js → index-ymsd3pyx.js} +12 -15
- package/dist/index.js +13 -24
- package/dist/init.js +23 -19
- package/dist/{input-reader-mm2ydeh5.js → input-reader-tw0j373f.js} +1 -1
- package/dist/ja-Q5PXKJ2V-tzf2rvz2.js +2697 -0
- package/dist/ja-UTQEAP34-8e0q6swp.js +173 -0
- package/dist/known-types-8dhhqk35.js +19 -0
- package/dist/ko-AXCHW2OK-askct7f6.js +173 -0
- package/dist/ko-AYBDSRZG-am0h0m2r.js +2697 -0
- package/dist/{maestro-automate-entry-6bxz7zxn.js → maestro-automate-entry-pqy9xqm3.js} +2 -2
- package/dist/{node-2ja52fbg.js → node-98psr4wc.js} +2344 -376
- package/dist/{node-service-1ygyqaed.js → node-service-yfyzjg1s.js} +37 -29
- package/dist/{node-sync-service-a4grwf1e.js → node-sync-service-zq2ptsep.js} +15 -15
- package/dist/{packager-tool-nnm6kw3x.js → packager-tool-0egkaa38.js} +1 -1
- package/dist/{packager-tool-0hrz9qfd.js → packager-tool-10t52r3c.js} +7 -7
- package/dist/{packager-tool-eb48j42f.js → packager-tool-13xbv18n.js} +100 -127
- package/dist/{packager-tool-nq4rcqqg.js → packager-tool-1frs4sr4.js} +32 -2
- package/dist/{packager-tool-bddj2zb4.js → packager-tool-1r5dnt9q.js} +1 -1
- package/dist/{packager-tool-f0kd5kq4.js → packager-tool-26ydwf12.js} +130 -15
- package/dist/{packager-tool-9ydywwp2.js → packager-tool-321a1806.js} +1 -1
- package/dist/packager-tool-35hg551a.js +1889 -0
- package/dist/{packager-tool-2csx1z2z.js → packager-tool-3j8sdsc2.js} +31 -30
- package/dist/{packager-tool-kscf0zaz.js → packager-tool-4rvnss1x.js} +15 -56
- package/dist/{packager-tool-t6exvxxr.js → packager-tool-5060zp48.js} +2 -2
- package/dist/packager-tool-53w8skv5.js +262 -0
- package/dist/{packager-tool-rew0hp2h.js → packager-tool-6k8s7pt9.js} +269 -23
- package/dist/{packager-tool-29eg86w6.js → packager-tool-6rsegsby.js} +6 -7
- package/dist/packager-tool-795gzq9k.js +208 -0
- package/dist/packager-tool-7q6z6npd.js +1937 -0
- package/dist/{packager-tool-h1mds3r4.js → packager-tool-8dj442ex.js} +5 -4
- package/dist/packager-tool-8qp60s20.js +12 -0
- package/dist/{packager-tool-114a3x6s.js → packager-tool-9kx94sj5.js} +16 -6
- package/dist/packager-tool-asvprb1k.js +3513 -0
- package/dist/{packager-tool-0d7tcvg1.js → packager-tool-b1xs6aty.js} +4 -1
- package/dist/{packager-tool-nmqwgqp7.js → packager-tool-bzry3t7v.js} +9 -9
- package/dist/{packager-tool-nt7g81h7.js → packager-tool-carzh1jy.js} +10 -10
- package/dist/packager-tool-d88rqwk8.js +135 -0
- package/dist/{packager-tool-pm3qh1hy.js → packager-tool-dh5nppv4.js} +1 -1
- package/dist/{packager-tool-r87gxwqa.js → packager-tool-e87tzg4y.js} +2 -2
- package/dist/{packager-tool-d0w3423x.js → packager-tool-e9yc5m6b.js} +1 -1
- package/dist/packager-tool-fvm2dddf.js +6297 -0
- package/dist/{packager-tool-3bra2c4j.js → packager-tool-gctpkdzs.js} +1 -1
- package/dist/packager-tool-gdtpsdn7.js +342 -0
- package/dist/{packager-tool-aa481g36.js → packager-tool-gpwec9sp.js} +6 -6
- package/dist/{packager-tool-a1hbfmws.js → packager-tool-gzpvdcnw.js} +124 -2
- package/dist/{packager-tool-03hjxcd7.js → packager-tool-h9d8c9rf.js} +1 -1
- package/dist/packager-tool-j78fwwhq.js +16 -0
- package/dist/packager-tool-jysvpt8p.js +11 -0
- package/dist/{packager-tool-5kd7msdf.js → packager-tool-nsmy7aap.js} +5 -5
- package/dist/packager-tool-paq9c70w.js +1332 -0
- package/dist/{packager-tool-tv33t02p.js → packager-tool-pszx10r5.js} +310 -13
- package/dist/{packager-tool-7qzyj26r.js → packager-tool-r45r9gk6.js} +209 -199
- package/dist/{packager-tool-sc5tddfj.js → packager-tool-s0mzv3sx.js} +1 -1
- package/dist/{packager-tool-pdg7hwvw.js → packager-tool-t9c77psy.js} +3098 -3179
- package/dist/{packager-tool-0880myh2.js → packager-tool-v31s32s4.js} +23 -5
- package/dist/{packager-tool-vfb74f9p.js → packager-tool-vbser1d9.js} +7 -7
- package/dist/packager-tool-vcjq9xkc.js +1895 -0
- package/dist/{packager-tool-w20r6n9v.js → packager-tool-vck7ct1e.js} +2877 -2221
- package/dist/{packager-tool-e8td7b01.js → packager-tool-vdc8r21p.js} +10328 -16610
- package/dist/{packager-tool-yr3bws42.js → packager-tool-vqcnvaae.js} +15 -15
- package/dist/{packager-tool-n7x6kxph.js → packager-tool-w22107ex.js} +8 -8
- package/dist/packager-tool-w5a1hhyj.js +13 -0
- package/dist/{packager-tool-rmh1jea6.js → packager-tool-xsta8jfz.js} +4 -3
- package/dist/packager-tool-yvva2vc5.js +261 -0
- package/dist/{packager-tool-9y5am147.js → packager-tool-z185rq2a.js} +4 -4
- package/dist/{packager-tool-gbzpz3qn.js → packager-tool-z894s8rx.js} +10 -13
- package/dist/packager-tool.js +17 -14
- package/dist/pt-3DIO5QWG-59b3f4bc.js +173 -0
- package/dist/pt-BR-TKHNHMET-dn6zxk1d.js +2697 -0
- package/dist/pt-BR-Y6K6XHXK-mp3hwhw1.js +173 -0
- package/dist/pt-ROXU257Y-yd80gx6s.js +2697 -0
- package/dist/ro-AVAWPKOO-42m6am1w.js +2697 -0
- package/dist/ro-BWR3ONRR-vzx3hy8a.js +173 -0
- package/dist/ru-GSCT4ARZ-jrxwev63.js +10 -0
- package/dist/ru-WBLQ5B2U-s4em88p0.js +10 -0
- package/dist/{serialization-BXU6AKAN-n5b0v0kd.js → serialization-BXU6AKAN-z0vcrhpz.js} +13 -12
- package/dist/services/connector-binding-validator.d.ts +10 -1
- package/dist/services/definitions-lookup.d.ts +27 -0
- package/dist/services/flow-debug-service.d.ts +290 -0
- package/dist/services/flow-eval-types.d.ts +2 -2
- package/dist/services/flow-eval-utils.d.ts +29 -0
- package/dist/services/flow-validate-service.d.ts +39 -0
- package/dist/services/node-validators/connector-validator.d.ts +8 -0
- package/dist/services/vars-reference-rule.d.ts +113 -13
- package/dist/{shared-utils-ka4xn0nn.js → shared-utils-wv356cvj.js} +1 -1
- package/dist/tidy-service-cxpm6pcy.js +39 -0
- package/dist/tool.js +13 -24
- package/dist/tr-5IIHSFW5-hw4cewew.js +173 -0
- package/dist/tr-JMIP7ZSL-fb67ft9w.js +2696 -0
- package/dist/utils/handle-expansion.d.ts +34 -0
- package/dist/utils/write-resolved-flow.d.ts +7 -0
- package/dist/validation.js +46 -39
- package/dist/{variable-service-caa9axmz.js → variable-service-c1f91388.js} +22 -19
- package/dist/{wait-for-flow-job-xtnb6zfc.js → wait-for-flow-job-yp3mhy43.js} +8 -8
- package/dist/zh-CN-IFFXSEJS-tke4mzty.js +2697 -0
- package/dist/zh-CN-R2KU4U5L-tc1hat59.js +173 -0
- package/dist/zh-TW-GNKMELBF-j674515r.js +173 -0
- package/dist/zh-TW-IYBNYAMG-wcan0qpb.js +2697 -0
- package/package.json +3 -2
- package/dist/flow-init-service-a4td40wm.js +0 -38
- package/dist/flow-validate-service-bd4zxhfx.js +0 -59
- package/dist/known-types-eq32py2n.js +0 -20
- package/dist/packager-tool-2wefykg9.js +0 -106
- package/dist/packager-tool-7t3rgb7f.js +0 -4945
- package/dist/packager-tool-8j92afwp.js +0 -58
- package/dist/packager-tool-jjpc0yka.js +0 -304
- package/dist/tidy-service-44n8x2mn.js +0 -36
- /package/dist/{localization-w8ada88j.js → localization-y790z9vm.js} +0 -0
|
@@ -0,0 +1,1889 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveJsonInput
|
|
3
|
+
} from "./packager-tool-h9d8c9rf.js";
|
|
4
|
+
import {
|
|
5
|
+
DEBUG_MODE_MAP,
|
|
6
|
+
SIMULATION_MODE_MAP,
|
|
7
|
+
beginDebugSession,
|
|
8
|
+
createDebugInstance,
|
|
9
|
+
getPersonalFolderKey
|
|
10
|
+
} from "./packager-tool-9kx94sj5.js";
|
|
11
|
+
import {
|
|
12
|
+
debugPimsGet,
|
|
13
|
+
debugPimsPatch,
|
|
14
|
+
debugPimsPost,
|
|
15
|
+
debugPimsPut
|
|
16
|
+
} from "./packager-tool-s0mzv3sx.js";
|
|
17
|
+
import {
|
|
18
|
+
getAuthContext,
|
|
19
|
+
getLoginStatusAsync
|
|
20
|
+
} from "./packager-tool-26ydwf12.js";
|
|
21
|
+
import {
|
|
22
|
+
DEFAULT_PAGE_SIZE,
|
|
23
|
+
EXIT_CODES,
|
|
24
|
+
InvalidArgumentError,
|
|
25
|
+
OutputFormatter,
|
|
26
|
+
Pagination,
|
|
27
|
+
RESULTS,
|
|
28
|
+
catchError,
|
|
29
|
+
extractErrorMessage,
|
|
30
|
+
isGuid,
|
|
31
|
+
logger,
|
|
32
|
+
parseBoundedInt,
|
|
33
|
+
parseLimit,
|
|
34
|
+
parseOffset,
|
|
35
|
+
processContext
|
|
36
|
+
} from "./packager-tool-6k8s7pt9.js";
|
|
37
|
+
import {
|
|
38
|
+
__require
|
|
39
|
+
} from "./packager-tool-1yh8g550.js";
|
|
40
|
+
|
|
41
|
+
// ../maestro-sdk/src/client.ts
|
|
42
|
+
function parseBackendErrorBody(body) {
|
|
43
|
+
if (!body)
|
|
44
|
+
return {};
|
|
45
|
+
const [parseErr, parsed] = catchError(() => JSON.parse(body));
|
|
46
|
+
if (parseErr || !parsed || typeof parsed !== "object")
|
|
47
|
+
return {};
|
|
48
|
+
const result = {};
|
|
49
|
+
if (typeof parsed.message === "string")
|
|
50
|
+
result.message = parsed.message;
|
|
51
|
+
if (typeof parsed.errorCode === "number" || typeof parsed.errorCode === "string") {
|
|
52
|
+
result.errorCode = String(parsed.errorCode);
|
|
53
|
+
}
|
|
54
|
+
if (typeof parsed.traceId === "string")
|
|
55
|
+
result.traceId = parsed.traceId;
|
|
56
|
+
if (typeof parsed.requestId === "string") {
|
|
57
|
+
result.requestId = parsed.requestId;
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
class PimsApiError extends Error {
|
|
63
|
+
method;
|
|
64
|
+
endpoint;
|
|
65
|
+
url;
|
|
66
|
+
httpStatus;
|
|
67
|
+
statusText;
|
|
68
|
+
body;
|
|
69
|
+
parsedErrorMessage;
|
|
70
|
+
parsedErrorCode;
|
|
71
|
+
parsedTraceId;
|
|
72
|
+
parsedRequestId;
|
|
73
|
+
constructor(details) {
|
|
74
|
+
const parsed = parseBackendErrorBody(details.body);
|
|
75
|
+
const messageSuffix = parsed.message ? ` - ${parsed.message}` : "";
|
|
76
|
+
super(`PIMS API request failed: ${details.httpStatus} ${details.statusText} on ${details.method} ${details.endpoint}${messageSuffix}`);
|
|
77
|
+
this.name = "PimsApiError";
|
|
78
|
+
this.method = details.method;
|
|
79
|
+
this.endpoint = details.endpoint;
|
|
80
|
+
this.url = details.url;
|
|
81
|
+
this.httpStatus = details.httpStatus;
|
|
82
|
+
this.statusText = details.statusText;
|
|
83
|
+
this.body = details.body;
|
|
84
|
+
this.parsedErrorMessage = parsed.message;
|
|
85
|
+
this.parsedErrorCode = parsed.errorCode;
|
|
86
|
+
this.parsedTraceId = parsed.traceId;
|
|
87
|
+
this.parsedRequestId = parsed.requestId;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function buildPimsUrl(config, path) {
|
|
91
|
+
return `${config.baseUrl}/${config.organizationId}/${config.tenantId}/pims_/api/v1${path}`;
|
|
92
|
+
}
|
|
93
|
+
function buildHeaders(config, options) {
|
|
94
|
+
const headers = {
|
|
95
|
+
Authorization: `Bearer ${config.authToken}`,
|
|
96
|
+
"Content-Type": "application/json",
|
|
97
|
+
Accept: "application/json"
|
|
98
|
+
};
|
|
99
|
+
if (options?.folderKey) {
|
|
100
|
+
headers["x-uipath-folderkey"] = options.folderKey;
|
|
101
|
+
}
|
|
102
|
+
return headers;
|
|
103
|
+
}
|
|
104
|
+
async function pimsGet(config, path, options) {
|
|
105
|
+
const url = buildPimsUrl(config, path);
|
|
106
|
+
const headers = buildHeaders(config, options);
|
|
107
|
+
const response = await fetch(url, {
|
|
108
|
+
method: "GET",
|
|
109
|
+
headers
|
|
110
|
+
});
|
|
111
|
+
if (!response.ok) {
|
|
112
|
+
const errorText = await response.text();
|
|
113
|
+
throw new PimsApiError({
|
|
114
|
+
method: "GET",
|
|
115
|
+
endpoint: path,
|
|
116
|
+
url,
|
|
117
|
+
httpStatus: response.status,
|
|
118
|
+
statusText: response.statusText,
|
|
119
|
+
body: errorText
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
const contentType = response.headers.get("content-type") || "";
|
|
123
|
+
if (contentType.includes("application/xml") || contentType.includes("text/xml")) {
|
|
124
|
+
return await response.text();
|
|
125
|
+
}
|
|
126
|
+
const text = await response.text();
|
|
127
|
+
if (!text)
|
|
128
|
+
return {};
|
|
129
|
+
const [parseErr, parsed] = catchError(() => JSON.parse(text));
|
|
130
|
+
if (parseErr)
|
|
131
|
+
throw new Error(`Failed to parse API response body: ${parseErr.message}`);
|
|
132
|
+
return parsed;
|
|
133
|
+
}
|
|
134
|
+
async function pimsRequest(config, method, path, body, options) {
|
|
135
|
+
const url = buildPimsUrl(config, path);
|
|
136
|
+
const headers = buildHeaders(config, options);
|
|
137
|
+
const response = await fetch(url, {
|
|
138
|
+
method,
|
|
139
|
+
headers,
|
|
140
|
+
body: body ? JSON.stringify(body) : undefined
|
|
141
|
+
});
|
|
142
|
+
if (!response.ok) {
|
|
143
|
+
const errorText = await response.text();
|
|
144
|
+
throw new PimsApiError({
|
|
145
|
+
method,
|
|
146
|
+
endpoint: path,
|
|
147
|
+
url,
|
|
148
|
+
httpStatus: response.status,
|
|
149
|
+
statusText: response.statusText,
|
|
150
|
+
body: errorText
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
const text = await response.text();
|
|
154
|
+
if (!text)
|
|
155
|
+
return {};
|
|
156
|
+
const [parseErr, parsed] = catchError(() => JSON.parse(text));
|
|
157
|
+
if (parseErr) {
|
|
158
|
+
throw new Error(`Failed to parse API response body: ${parseErr.message}`);
|
|
159
|
+
}
|
|
160
|
+
return parsed;
|
|
161
|
+
}
|
|
162
|
+
async function pimsPost(config, path, body, options) {
|
|
163
|
+
return pimsRequest(config, "POST", path, body, options);
|
|
164
|
+
}
|
|
165
|
+
async function pimsPut(config, path, body, options) {
|
|
166
|
+
return pimsRequest(config, "PUT", path, body, options);
|
|
167
|
+
}
|
|
168
|
+
async function pimsPatch(config, path, body, options) {
|
|
169
|
+
return pimsRequest(config, "PATCH", path, body, options);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ../maestro-sdk/src/client-factory.ts
|
|
173
|
+
async function createPimsConfig() {
|
|
174
|
+
const ctx = await getAuthContext({
|
|
175
|
+
ensureTokenValidityMinutes: 10,
|
|
176
|
+
requireOrganizationId: true,
|
|
177
|
+
requireTenantId: true
|
|
178
|
+
});
|
|
179
|
+
return {
|
|
180
|
+
baseUrl: ctx.baseUrl,
|
|
181
|
+
organizationId: ctx.organizationId,
|
|
182
|
+
tenantId: ctx.tenantId,
|
|
183
|
+
authToken: ctx.accessToken
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// ../maestro-sdk/src/query-string.ts
|
|
188
|
+
function buildQueryString(params) {
|
|
189
|
+
const entries = [];
|
|
190
|
+
for (const [key, value] of Object.entries(params)) {
|
|
191
|
+
if (value === undefined)
|
|
192
|
+
continue;
|
|
193
|
+
if (Array.isArray(value)) {
|
|
194
|
+
for (const item of value) {
|
|
195
|
+
entries.push([key, item]);
|
|
196
|
+
}
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
entries.push([key, String(value)]);
|
|
200
|
+
}
|
|
201
|
+
if (entries.length === 0)
|
|
202
|
+
return "";
|
|
203
|
+
return `?${new URLSearchParams(entries).toString()}`;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// ../maestro-sdk/src/registry/filter-parser.ts
|
|
207
|
+
class FilterParseError extends Error {
|
|
208
|
+
code;
|
|
209
|
+
token;
|
|
210
|
+
constructor(message, code, token) {
|
|
211
|
+
super(message);
|
|
212
|
+
this.code = code;
|
|
213
|
+
this.token = token;
|
|
214
|
+
this.name = "FilterParseError";
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function parseFilterString(filterString) {
|
|
218
|
+
if (!filterString || filterString.trim() === "") {
|
|
219
|
+
return { filters: [], logic: "AND" };
|
|
220
|
+
}
|
|
221
|
+
const parts = filterString.split(/,(?=[a-zA-Z_][a-zA-Z0-9_]*(?::[a-zA-Z]+)?=)/);
|
|
222
|
+
const conditions = [];
|
|
223
|
+
for (const part of parts) {
|
|
224
|
+
const condition = parseFilterCondition(part.trim());
|
|
225
|
+
conditions.push(condition);
|
|
226
|
+
}
|
|
227
|
+
return {
|
|
228
|
+
filters: conditions,
|
|
229
|
+
logic: "AND"
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
function parseFilterCondition(conditionString) {
|
|
233
|
+
const match = conditionString.match(/^([^:=]+)(?::([^=]+))?=(.+)$/);
|
|
234
|
+
if (!match) {
|
|
235
|
+
throw new FilterParseError(`Invalid filter format: '${conditionString}'. Expected 'field=value' or 'field:operator=value'.`, "INVALID_FORMAT", conditionString);
|
|
236
|
+
}
|
|
237
|
+
const [, fieldStr, operatorStr, valueStr] = match;
|
|
238
|
+
const field = normalizeField(fieldStr.trim());
|
|
239
|
+
const operator = operatorStr?.trim() || "equals";
|
|
240
|
+
const value = valueStr.trim();
|
|
241
|
+
if (!isValidField(field)) {
|
|
242
|
+
throw new FilterParseError(`Invalid filter field: '${field}'. Supported fields: category, type, tags, displayname, nodetype, description.`, "INVALID_FIELD", field);
|
|
243
|
+
}
|
|
244
|
+
if (!isValidOperator(operator)) {
|
|
245
|
+
throw new FilterParseError(`Invalid filter operator: '${operator}'. Supported operators: equals, contains, in, startsWith, endsWith.`, "INVALID_OPERATOR", operator);
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
field,
|
|
249
|
+
operator,
|
|
250
|
+
value
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function normalizeField(field) {
|
|
254
|
+
const fieldMap = {
|
|
255
|
+
category: "category",
|
|
256
|
+
cat: "category",
|
|
257
|
+
type: "type",
|
|
258
|
+
nodetype: "nodetype",
|
|
259
|
+
node_type: "nodetype",
|
|
260
|
+
tags: "tags",
|
|
261
|
+
tag: "tags",
|
|
262
|
+
displayname: "displayname",
|
|
263
|
+
display_name: "displayname",
|
|
264
|
+
displayName: "displayname",
|
|
265
|
+
name: "displayname",
|
|
266
|
+
label: "displayname"
|
|
267
|
+
};
|
|
268
|
+
const normalized = field.toLowerCase().replace(/[-_\s]/g, "");
|
|
269
|
+
return fieldMap[normalized] || field;
|
|
270
|
+
}
|
|
271
|
+
function isValidField(field) {
|
|
272
|
+
const validFields = [
|
|
273
|
+
"category",
|
|
274
|
+
"type",
|
|
275
|
+
"tags",
|
|
276
|
+
"displayname",
|
|
277
|
+
"nodetype",
|
|
278
|
+
"description"
|
|
279
|
+
];
|
|
280
|
+
return validFields.includes(field);
|
|
281
|
+
}
|
|
282
|
+
function isValidOperator(operator) {
|
|
283
|
+
const validOperators = [
|
|
284
|
+
"equals",
|
|
285
|
+
"contains",
|
|
286
|
+
"in",
|
|
287
|
+
"startsWith",
|
|
288
|
+
"endsWith"
|
|
289
|
+
];
|
|
290
|
+
return validOperators.includes(operator);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// ../maestro-sdk/src/registry/command.ts
|
|
294
|
+
function flattenNodeForDisplay(n) {
|
|
295
|
+
return {
|
|
296
|
+
NodeType: n.nodeType,
|
|
297
|
+
Category: n.category ?? "",
|
|
298
|
+
DisplayName: n.display?.label ?? "",
|
|
299
|
+
Description: n.description ?? n.display?.description ?? "",
|
|
300
|
+
Version: n.version ?? "",
|
|
301
|
+
Tags: (n.tags ?? []).join(", ")
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
function flattenNodeWithAvailability(n, availableOnTenant) {
|
|
305
|
+
return {
|
|
306
|
+
...flattenNodeForDisplay(n),
|
|
307
|
+
AvailableOnTenant: availableOnTenant
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
async function mergeWithKnownSdkNodes(tenantNodes) {
|
|
311
|
+
const { listKnownSdkNodes } = await import("./known-types-8dhhqk35.js");
|
|
312
|
+
const tenantTypes = new Set(tenantNodes.map((n) => n.nodeType?.toLowerCase()).filter((t) => typeof t === "string"));
|
|
313
|
+
const merged = tenantNodes.map((node) => ({ node, availableOnTenant: true }));
|
|
314
|
+
for (const known of listKnownSdkNodes()) {
|
|
315
|
+
const type = known.nodeType?.toLowerCase();
|
|
316
|
+
if (typeof type !== "string")
|
|
317
|
+
continue;
|
|
318
|
+
if (tenantTypes.has(type))
|
|
319
|
+
continue;
|
|
320
|
+
merged.push({ node: known, availableOnTenant: false });
|
|
321
|
+
}
|
|
322
|
+
return merged;
|
|
323
|
+
}
|
|
324
|
+
var registerRegistryCommand = (program, commandPrefix) => {
|
|
325
|
+
const cmd = `uip ${commandPrefix} registry`;
|
|
326
|
+
const registry = program.command("registry").description(`Browse and search the ${commandPrefix} node registry to discover available activities and connectors (OOTB + authenticated). Use 'pull' to sync, 'search' to find nodes, 'get' to inspect a node's full input/output schema.`).addHelpText("after", `
|
|
327
|
+
Typical workflow:
|
|
328
|
+
0. Login for full registry (optional, OOTB nodes available without login):
|
|
329
|
+
uip login
|
|
330
|
+
1. Sync the registry: ${cmd} pull
|
|
331
|
+
2. Search for a node: ${cmd} search slack
|
|
332
|
+
3. Inspect its schema: ${cmd} get <node-type>
|
|
333
|
+
4. Extract input fields: ${cmd} get <node-type> --output-filter "Node.inputDefinition.fields"
|
|
334
|
+
|
|
335
|
+
Note: Without login, only built-in (OOTB) nodes are available. Login to access the full node registry including custom connectors.
|
|
336
|
+
|
|
337
|
+
In-solution discovery (--local):
|
|
338
|
+
Run from inside a solution project directory (with a .uipx file in CWD, parent, or grandparent).
|
|
339
|
+
Shows sibling projects (Agent, Process, Flow, Api) as invokable nodes.
|
|
340
|
+
cd MySolution/MyFlow && ${cmd} list --local
|
|
341
|
+
|
|
342
|
+
Subcommands:
|
|
343
|
+
pull Fetch and cache the full node registry (run once per session)
|
|
344
|
+
list List cached nodes (default: first 20, --limit -1 for everything)
|
|
345
|
+
search Find nodes by keyword and/or field filters ← start here
|
|
346
|
+
get Get full schema for a single node (with connector input/output enrichment)`);
|
|
347
|
+
const pullExamples = [
|
|
348
|
+
{
|
|
349
|
+
Description: "Sync the node registry",
|
|
350
|
+
Command: `${cmd} pull`,
|
|
351
|
+
Output: {
|
|
352
|
+
Code: "NodePullSuccess",
|
|
353
|
+
Data: {
|
|
354
|
+
NodesCount: 184,
|
|
355
|
+
FromCache: false,
|
|
356
|
+
Source: "authenticated",
|
|
357
|
+
CacheWritten: true,
|
|
358
|
+
Message: "Synced fresh nodes"
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
];
|
|
363
|
+
const listExamples = [
|
|
364
|
+
{
|
|
365
|
+
Description: "List cached nodes (every row carries AvailableOnTenant; FF-gated SDK-known nodes are included)",
|
|
366
|
+
Command: `${cmd} list --limit 2`,
|
|
367
|
+
Output: {
|
|
368
|
+
Code: "NodeListSuccess",
|
|
369
|
+
Data: [
|
|
370
|
+
{
|
|
371
|
+
NodeType: "uipath.slack.connector.send-message",
|
|
372
|
+
Category: "connector",
|
|
373
|
+
DisplayName: "Send Message",
|
|
374
|
+
Description: "Post a message to a Slack channel",
|
|
375
|
+
Version: "1.0.0",
|
|
376
|
+
Tags: "slack, messaging",
|
|
377
|
+
AvailableOnTenant: true
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
NodeType: "uipath.human-in-the-loop",
|
|
381
|
+
Category: "human-task",
|
|
382
|
+
DisplayName: "Human in the Loop",
|
|
383
|
+
Description: "Assign a task to a human and wait for completion",
|
|
384
|
+
Version: "1.0.0",
|
|
385
|
+
Tags: "human-task, hitl, human-in-the-loop, approval",
|
|
386
|
+
AvailableOnTenant: false
|
|
387
|
+
}
|
|
388
|
+
]
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
];
|
|
392
|
+
const searchExamples = [
|
|
393
|
+
{
|
|
394
|
+
Description: "Search nodes by keyword (every row carries AvailableOnTenant; FF-gated SDK-known nodes are included)",
|
|
395
|
+
Command: `${cmd} search slack`,
|
|
396
|
+
Output: {
|
|
397
|
+
Code: "NodeSearchSuccess",
|
|
398
|
+
Data: [
|
|
399
|
+
{
|
|
400
|
+
NodeType: "uipath.slack.connector.send-message",
|
|
401
|
+
Category: "connector",
|
|
402
|
+
DisplayName: "Send Message",
|
|
403
|
+
Description: "Post a message to a Slack channel",
|
|
404
|
+
Version: "1.0.0",
|
|
405
|
+
Tags: "slack, messaging",
|
|
406
|
+
AvailableOnTenant: true
|
|
407
|
+
}
|
|
408
|
+
]
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
];
|
|
412
|
+
const getExamples = [
|
|
413
|
+
{
|
|
414
|
+
Description: "Get the full schema for a node",
|
|
415
|
+
Command: `${cmd} get uipath.slack.connector.send-message`,
|
|
416
|
+
Output: {
|
|
417
|
+
Code: "NodeGetSuccess",
|
|
418
|
+
Data: {
|
|
419
|
+
Node: {
|
|
420
|
+
nodeType: "uipath.slack.connector.send-message",
|
|
421
|
+
category: "connector",
|
|
422
|
+
display: { label: "Send Message" },
|
|
423
|
+
inputDefinition: {
|
|
424
|
+
fields: [{ name: "channel", required: true }]
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
];
|
|
431
|
+
registry.command("pull").description(`Pull and sync node data from ${commandPrefix} registry (login first for full registry)`).option("-f, --force", "Force refresh, ignore cache").examples(pullExamples).trackedAction(processContext, async (options) => {
|
|
432
|
+
const { pullNodes } = await import("./node-sync-service-zq2ptsep.js");
|
|
433
|
+
const [error, result] = await catchError(pullNodes({
|
|
434
|
+
force: options.force
|
|
435
|
+
}));
|
|
436
|
+
if (error) {
|
|
437
|
+
OutputFormatter.error({
|
|
438
|
+
Result: RESULTS.Failure,
|
|
439
|
+
Message: "Error pulling nodes",
|
|
440
|
+
Instructions: error.message
|
|
441
|
+
});
|
|
442
|
+
processContext.exit(1);
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
const message = result.fromCache ? `Using cached nodes (age: ${result.ageMinutes}m)` : "Synced fresh nodes";
|
|
446
|
+
const finalMessage = result.info ? `${message}. ${result.info}` : message;
|
|
447
|
+
OutputFormatter.success({
|
|
448
|
+
Result: RESULTS.Success,
|
|
449
|
+
Code: "NodePullSuccess",
|
|
450
|
+
Data: {
|
|
451
|
+
NodesCount: result.syncedCount,
|
|
452
|
+
FromCache: result.fromCache,
|
|
453
|
+
AgeMinutes: result.ageMinutes,
|
|
454
|
+
Source: result.source,
|
|
455
|
+
CacheWritten: result.cacheWritten,
|
|
456
|
+
Message: finalMessage,
|
|
457
|
+
Info: result.info
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
});
|
|
461
|
+
registry.command("list").description("Sample cached nodes to inspect their config structure (default: first 20). Output merges tenant nodes with the SDK-known catalog; every row carries `AvailableOnTenant` so callers can filter FF-gated rows. Use 'search' to find nodes — use --limit -1 only if you need the full list (the result can be huge and unreadable).").addHelpText("after", `
|
|
462
|
+
Examples:
|
|
463
|
+
${cmd} list
|
|
464
|
+
${cmd} list --limit 200
|
|
465
|
+
${cmd} list --limit -1
|
|
466
|
+
|
|
467
|
+
In-solution (--local):
|
|
468
|
+
cd MySolution/MyFlow && ${cmd} list --local`).option("-l, --limit <n>", "Number of nodes to return (default: 20, -1 for all)", (v) => Number.parseInt(v, 10), 20).option("--local", "Show only in-solution project nodes (requires .uipx in CWD, parent, or grandparent). Omits `AvailableOnTenant` (no tenant lookup).").examples(listExamples).trackedAction(processContext, async (options) => {
|
|
469
|
+
if (Number.isNaN(options.limit) || options.limit < 1 && options.limit !== -1) {
|
|
470
|
+
OutputFormatter.error({
|
|
471
|
+
Result: RESULTS.Failure,
|
|
472
|
+
Message: "Invalid --limit value",
|
|
473
|
+
Instructions: "Provide a positive integer (e.g. --limit 100) or -1 for all nodes"
|
|
474
|
+
});
|
|
475
|
+
processContext.exit(1);
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
const { listNodes } = await import("./node-sync-service-zq2ptsep.js");
|
|
479
|
+
const [error, tenantNodes] = await catchError(listNodes({ local: options.local }));
|
|
480
|
+
if (error) {
|
|
481
|
+
OutputFormatter.error({
|
|
482
|
+
Result: RESULTS.Failure,
|
|
483
|
+
Message: "Error listing nodes",
|
|
484
|
+
Instructions: error.message
|
|
485
|
+
});
|
|
486
|
+
processContext.exit(1);
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
const showAll = options.limit === -1;
|
|
490
|
+
if (options.local) {
|
|
491
|
+
const totalCount2 = tenantNodes.length;
|
|
492
|
+
const effectiveLimit2 = showAll ? totalCount2 : options.limit;
|
|
493
|
+
const nodes = tenantNodes.slice(0, effectiveLimit2);
|
|
494
|
+
const truncated2 = nodes.length < totalCount2;
|
|
495
|
+
OutputFormatter.success({
|
|
496
|
+
Result: RESULTS.Success,
|
|
497
|
+
Code: "NodeListSuccess",
|
|
498
|
+
Data: nodes.map(flattenNodeForDisplay)
|
|
499
|
+
});
|
|
500
|
+
if (truncated2) {
|
|
501
|
+
logger.info(`Showing first ${nodes.length} of ${totalCount2}. Use --limit or --limit -1 to get more, or use 'search' to filter.`);
|
|
502
|
+
}
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
const merged = await mergeWithKnownSdkNodes(tenantNodes);
|
|
506
|
+
const totalCount = merged.length;
|
|
507
|
+
const effectiveLimit = showAll ? totalCount : options.limit;
|
|
508
|
+
const slice = merged.slice(0, effectiveLimit);
|
|
509
|
+
const truncated = slice.length < totalCount;
|
|
510
|
+
const gatedCount = merged.filter((m) => !m.availableOnTenant).length;
|
|
511
|
+
OutputFormatter.success({
|
|
512
|
+
Result: RESULTS.Success,
|
|
513
|
+
Code: "NodeListSuccess",
|
|
514
|
+
Data: slice.map((m) => flattenNodeWithAvailability(m.node, m.availableOnTenant))
|
|
515
|
+
});
|
|
516
|
+
if (truncated) {
|
|
517
|
+
logger.info(`Showing first ${slice.length} of ${totalCount} (${gatedCount} not enabled on this tenant). Use --limit or --limit -1 to get more.`);
|
|
518
|
+
} else if (gatedCount > 0) {
|
|
519
|
+
logger.info(`${gatedCount} of ${totalCount} node type(s) are not enabled on this tenant (AvailableOnTenant=false).`);
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
registry.command("search").description("Find nodes by keyword and/or field filters").addHelpText("after", `
|
|
523
|
+
Filter syntax:
|
|
524
|
+
field=value equality (default operator)
|
|
525
|
+
field:contains=value field contains value
|
|
526
|
+
field:startsWith=value field starts with value
|
|
527
|
+
field:endsWith=value field ends with value
|
|
528
|
+
field:in=value1,value2 field matches any of the values
|
|
529
|
+
field1=v1,field2=v2 multiple conditions (AND logic)
|
|
530
|
+
|
|
531
|
+
Filterable fields:
|
|
532
|
+
category / cat e.g. "connector", "agent"
|
|
533
|
+
type / nodetype node type identifier
|
|
534
|
+
tags / tag node tags
|
|
535
|
+
displayname / name / label human-readable display name
|
|
536
|
+
|
|
537
|
+
Examples:
|
|
538
|
+
${cmd} search slack
|
|
539
|
+
${cmd} search --filter "category=connector"
|
|
540
|
+
${cmd} search --filter "displayname:contains=send message"
|
|
541
|
+
${cmd} search slack --filter "category=connector"
|
|
542
|
+
${cmd} search --filter "tags:in=ai,automation"
|
|
543
|
+
${cmd} search --filter "category=connector,displayname:contains=slack"
|
|
544
|
+
|
|
545
|
+
Tip: pipe through --output-filter to extract just the nodeType values:
|
|
546
|
+
${cmd} search slack --output-filter "[*].NodeType"
|
|
547
|
+
|
|
548
|
+
In-solution (--local):
|
|
549
|
+
cd MySolution/MyFlow && ${cmd} search agent --local`).argument("[keyword]", "Search term matched against nodeType, category, tags, display name, and description").option("-f, --filter <filter>", "Structured field filter: field=value or field:operator=value. Comma-separated = AND. Fields: category, type, tags, displayname, description.").option("--local", "Search only in-solution project nodes (requires .uipx in CWD, parent, or grandparent). Omits `AvailableOnTenant` (no tenant lookup).").examples(searchExamples).trackedAction(processContext, async (keyword, options) => {
|
|
550
|
+
let parsedFilters;
|
|
551
|
+
if (options.filter) {
|
|
552
|
+
const [parseError, parsed] = catchError(() => parseFilterString(options.filter));
|
|
553
|
+
if (parseError) {
|
|
554
|
+
if (parseError instanceof FilterParseError) {
|
|
555
|
+
OutputFormatter.error({
|
|
556
|
+
Result: RESULTS.Failure,
|
|
557
|
+
Message: "Invalid filter syntax",
|
|
558
|
+
Instructions: `${parseError.message} Examples: category=agent, displayname:contains=http, tags:in=ai,automation.`
|
|
559
|
+
});
|
|
560
|
+
processContext.exit(1);
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
OutputFormatter.error({
|
|
564
|
+
Result: RESULTS.Failure,
|
|
565
|
+
Message: "Error searching nodes",
|
|
566
|
+
Instructions: parseError.message
|
|
567
|
+
});
|
|
568
|
+
processContext.exit(1);
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
parsedFilters = parsed;
|
|
572
|
+
}
|
|
573
|
+
if (!keyword && !parsedFilters) {
|
|
574
|
+
OutputFormatter.error({
|
|
575
|
+
Result: RESULTS.Failure,
|
|
576
|
+
Message: "Search requires either a keyword or filters",
|
|
577
|
+
Instructions: "Provide a keyword or use --filter flag"
|
|
578
|
+
});
|
|
579
|
+
processContext.exit(1);
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
const {
|
|
583
|
+
searchNodeSummariesWithAvailability,
|
|
584
|
+
searchNodes,
|
|
585
|
+
searchNodesWithFilters
|
|
586
|
+
} = await import("./node-sync-service-zq2ptsep.js");
|
|
587
|
+
if (options.local) {
|
|
588
|
+
const [searchError2, results2] = await catchError(parsedFilters ? searchNodesWithFilters(keyword, parsedFilters, {
|
|
589
|
+
local: true
|
|
590
|
+
}) : searchNodes(keyword, { local: true }));
|
|
591
|
+
if (searchError2) {
|
|
592
|
+
OutputFormatter.error({
|
|
593
|
+
Result: RESULTS.Failure,
|
|
594
|
+
Message: "Error searching nodes",
|
|
595
|
+
Instructions: searchError2.message
|
|
596
|
+
});
|
|
597
|
+
processContext.exit(1);
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
OutputFormatter.success({
|
|
601
|
+
Result: RESULTS.Success,
|
|
602
|
+
Code: "NodeSearchSuccess",
|
|
603
|
+
Data: results2.map(flattenNodeForDisplay)
|
|
604
|
+
});
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
const [searchError, results] = await catchError(searchNodeSummariesWithAvailability(keyword, parsedFilters));
|
|
608
|
+
if (searchError) {
|
|
609
|
+
OutputFormatter.error({
|
|
610
|
+
Result: RESULTS.Failure,
|
|
611
|
+
Message: "Error searching nodes",
|
|
612
|
+
Instructions: searchError.message
|
|
613
|
+
});
|
|
614
|
+
processContext.exit(1);
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
OutputFormatter.success({
|
|
618
|
+
Result: RESULTS.Success,
|
|
619
|
+
Code: "NodeSearchSuccess",
|
|
620
|
+
Data: results.map((result) => flattenNodeWithAvailability(result.node, result.availableOnTenant))
|
|
621
|
+
});
|
|
622
|
+
});
|
|
623
|
+
registry.command("get").description("Get the full schema for a single node. For connector nodes (uipath.connector.*), the base manifest is automatically enriched with live metadata from Integration Service.").addHelpText("after", `
|
|
624
|
+
IS-enriched fields (connector nodes only, fetched live from Integration Service):
|
|
625
|
+
|
|
626
|
+
Activity nodes (uipath.connector.*, not trigger):
|
|
627
|
+
inputDefinition.fields Fields to configure. Each field has: name, displayName, type, required, and optionally reference (lookup: objectName, path, lookupValue, lookupNames, childPath; 4.0.0 activities carry scriptRef instead of objectName — resolve with 'uip is resources run script --script-ref') or enum.
|
|
628
|
+
outputResponseDefinition Fields produced after the node runs.
|
|
629
|
+
connectorMethodInfo HTTP details (method, path, operationId).
|
|
630
|
+
--connection-id optional — adds custom fields specific to that account.
|
|
631
|
+
|
|
632
|
+
Trigger nodes (uipath.connector.trigger.*):
|
|
633
|
+
eventParameters Fields that configure the trigger (e.g. which folder to watch).
|
|
634
|
+
filterFields Fields used to filter which events fire the trigger.
|
|
635
|
+
outputResponseDefinition Fields produced by the trigger event payload.
|
|
636
|
+
eventMode "webhooks" or "polling".
|
|
637
|
+
login + --connection-id required — without both, no enrichment is returned.
|
|
638
|
+
|
|
639
|
+
Examples:
|
|
640
|
+
${cmd} get uipath.slack.connector.send-message
|
|
641
|
+
${cmd} get uipath.connector.uipath-salesforce-slack.send-message --connection-id <id>
|
|
642
|
+
${cmd} get uipath.connector.trigger.uipath-microsoft-outlook365.email-received --connection-id <id>
|
|
643
|
+
|
|
644
|
+
In-solution (--local):
|
|
645
|
+
cd MySolution/MyFlow && ${cmd} get <node-type> --local`).argument("<node-type>", `Node type identifier — get it from '${cmd} search'`).option("--connection-id <id>", "Connection ID for Integration Service connector node enrichment. Required for connector trigger nodes; optional for connector activity nodes.").option("--local", "Get node from in-solution projects only (requires .uipx in CWD, parent, or grandparent)").examples(getExamples).trackedAction(processContext, async (nodeType, options) => {
|
|
646
|
+
const { getNodeEnriched } = await import("./node-sync-service-zq2ptsep.js");
|
|
647
|
+
const [error, result] = await catchError(getNodeEnriched(nodeType, options.connectionId, {
|
|
648
|
+
local: options.local
|
|
649
|
+
}));
|
|
650
|
+
if (error) {
|
|
651
|
+
OutputFormatter.error({
|
|
652
|
+
Result: RESULTS.Failure,
|
|
653
|
+
Message: "Error retrieving node",
|
|
654
|
+
Instructions: error.message
|
|
655
|
+
});
|
|
656
|
+
processContext.exit(1);
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
if (!result) {
|
|
660
|
+
OutputFormatter.error({
|
|
661
|
+
Result: RESULTS.Failure,
|
|
662
|
+
Message: "Node not found",
|
|
663
|
+
Instructions: `No node found with node type: ${nodeType}`
|
|
664
|
+
});
|
|
665
|
+
processContext.exit(1);
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
OutputFormatter.success({
|
|
669
|
+
Result: RESULTS.Success,
|
|
670
|
+
Code: "NodeGetSuccess",
|
|
671
|
+
Data: {
|
|
672
|
+
Node: result
|
|
673
|
+
}
|
|
674
|
+
}, { preserveDataKeys: true });
|
|
675
|
+
});
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
// ../maestro-sdk/src/with-debug-pims-call.ts
|
|
679
|
+
async function createDebugPimsConfig() {
|
|
680
|
+
const status = await getLoginStatusAsync({
|
|
681
|
+
ensureTokenValidityMinutes: 10
|
|
682
|
+
});
|
|
683
|
+
if (status.loginStatus !== "Logged in" || !status.baseUrl || !status.accessToken) {
|
|
684
|
+
throw new Error(status.hint ? `Not logged in. ${status.hint}` : "Not logged in. Run 'uip login' first.");
|
|
685
|
+
}
|
|
686
|
+
if (!status.organizationId) {
|
|
687
|
+
throw new Error("Organization ID not available. Ensure you are logged in with an organization context.");
|
|
688
|
+
}
|
|
689
|
+
if (!status.tenantId) {
|
|
690
|
+
throw new Error("Tenant ID not available. Ensure UIPATH_TENANT_ID is set.");
|
|
691
|
+
}
|
|
692
|
+
if (!status.tenantName) {
|
|
693
|
+
throw new Error("Tenant name not available. Ensure you are logged in with a tenant context.");
|
|
694
|
+
}
|
|
695
|
+
return {
|
|
696
|
+
baseUrl: status.baseUrl,
|
|
697
|
+
organizationId: status.organizationId,
|
|
698
|
+
tenantName: status.tenantName,
|
|
699
|
+
tenantId: status.tenantId,
|
|
700
|
+
authToken: status.accessToken
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
async function withDebugPimsCall(fn, errorMessage) {
|
|
704
|
+
const [configError, config] = await catchError(createDebugPimsConfig());
|
|
705
|
+
if (configError) {
|
|
706
|
+
logger.warn(`${errorMessage}: ${configError.message}`);
|
|
707
|
+
OutputFormatter.error({
|
|
708
|
+
Result: RESULTS.Failure,
|
|
709
|
+
Message: errorMessage,
|
|
710
|
+
Instructions: configError.message
|
|
711
|
+
});
|
|
712
|
+
processContext.exit(1);
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
if (!config.folderKey) {
|
|
716
|
+
const [folderError, folder] = await catchError(getPersonalFolderKey(config));
|
|
717
|
+
if (folderError) {
|
|
718
|
+
logger.warn(`Could not resolve personal folder: ${folderError.message}`);
|
|
719
|
+
} else {
|
|
720
|
+
config.folderKey = folder.key;
|
|
721
|
+
config.organizationUnitId = folder.id;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
const [error, result] = await catchError(fn(config));
|
|
725
|
+
if (error) {
|
|
726
|
+
const msg = await extractErrorMessage(error);
|
|
727
|
+
logger.warn(`${errorMessage}: ${msg}`);
|
|
728
|
+
OutputFormatter.error({
|
|
729
|
+
Result: RESULTS.Failure,
|
|
730
|
+
Message: errorMessage,
|
|
731
|
+
Instructions: msg
|
|
732
|
+
});
|
|
733
|
+
processContext.exit(1);
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
return result;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
// ../maestro-sdk/src/shared-commands/debug-instances.ts
|
|
740
|
+
var DEBUG_API_PREFIX = "/api/v1/debug-instances";
|
|
741
|
+
var VALID_DEBUG_MODES = Object.keys(DEBUG_MODE_MAP);
|
|
742
|
+
var VALID_SIMULATION_MODES = Object.keys(SIMULATION_MODE_MAP);
|
|
743
|
+
var registerSharedDebugInstanceCommands = (program, config) => {
|
|
744
|
+
const { toolLabel } = config;
|
|
745
|
+
const debugInstance = program.command("debug-instance").description(`Manage ${toolLabel} debug instance operations`);
|
|
746
|
+
debugInstance.command("create").description(`Create a ${toolLabel} debug instance from an already-uploaded solution`).requiredOption("--solution-id <id>", "Solution ID (from a previous upload or Studio Web)").requiredOption("--project-id <id>", "Studio Web project ID within the solution").requiredOption("--entry-point <path>", 'Entry point path (e.g. "/Main.bpmn#start")').option("--process-type <type>", "Process type", "processOrchestration").option("--debug-mode <mode>", "Debug mode: Default (pause at breakpoints), StepByStep (pause at every step), SingleStep (one step only)", "Default").option("--simulation-mode <mode>", "Simulation mode: None, All (simulate all elements), Selective (simulate except opt-outs)", "None").option("-i, --inputs <json>", "Input arguments as JSON string", "{}").trackedAction(processContext, async (options) => {
|
|
747
|
+
if (!VALID_DEBUG_MODES.includes(options.debugMode)) {
|
|
748
|
+
OutputFormatter.error({
|
|
749
|
+
Result: RESULTS.Failure,
|
|
750
|
+
Message: `Invalid --debug-mode "${options.debugMode}". Valid values: ${VALID_DEBUG_MODES.join(", ")}.`,
|
|
751
|
+
Instructions: ""
|
|
752
|
+
});
|
|
753
|
+
processContext.exit(1);
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
if (!VALID_SIMULATION_MODES.includes(options.simulationMode)) {
|
|
757
|
+
OutputFormatter.error({
|
|
758
|
+
Result: RESULTS.Failure,
|
|
759
|
+
Message: `Invalid --simulation-mode "${options.simulationMode}". Valid values: ${VALID_SIMULATION_MODES.join(", ")}.`,
|
|
760
|
+
Instructions: ""
|
|
761
|
+
});
|
|
762
|
+
processContext.exit(1);
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
const [configError, config2] = await catchError(createDebugPimsConfig());
|
|
766
|
+
if (configError) {
|
|
767
|
+
OutputFormatter.error({
|
|
768
|
+
Result: RESULTS.Failure,
|
|
769
|
+
Message: "Error creating debug instance",
|
|
770
|
+
Instructions: configError.message
|
|
771
|
+
});
|
|
772
|
+
processContext.exit(1);
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
const [folderError, folder] = await catchError(getPersonalFolderKey(config2));
|
|
776
|
+
if (folderError) {
|
|
777
|
+
OutputFormatter.error({
|
|
778
|
+
Result: RESULTS.Failure,
|
|
779
|
+
Message: "Error getting personal workspace folder",
|
|
780
|
+
Instructions: folderError.message
|
|
781
|
+
});
|
|
782
|
+
processContext.exit(1);
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
config2.folderKey = folder.key;
|
|
786
|
+
config2.organizationUnitId = folder.id;
|
|
787
|
+
const [sessionError, session] = await catchError(beginDebugSession(config2, options.inputs));
|
|
788
|
+
if (sessionError) {
|
|
789
|
+
OutputFormatter.error({
|
|
790
|
+
Result: RESULTS.Failure,
|
|
791
|
+
Message: "Error beginning debug session",
|
|
792
|
+
Instructions: sessionError.message
|
|
793
|
+
});
|
|
794
|
+
processContext.exit(1);
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
const [createError, result] = await catchError(createDebugInstance(config2, session.jobKey, options.solutionId, options.projectId, options.entryPoint, options.processType, options.debugMode, options.simulationMode));
|
|
798
|
+
if (createError) {
|
|
799
|
+
OutputFormatter.error({
|
|
800
|
+
Result: RESULTS.Failure,
|
|
801
|
+
Message: "Error creating debug instance",
|
|
802
|
+
Instructions: createError.message
|
|
803
|
+
});
|
|
804
|
+
processContext.exit(1);
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
807
|
+
OutputFormatter.success({
|
|
808
|
+
Result: RESULTS.Success,
|
|
809
|
+
Code: "DebugInstanceCreated",
|
|
810
|
+
Data: {
|
|
811
|
+
instanceId: result.instanceId,
|
|
812
|
+
runId: result.runId,
|
|
813
|
+
jobKey: session.jobKey
|
|
814
|
+
},
|
|
815
|
+
Instructions: "Use 'debug-instance status <instance-id>' to check the run. Use 'debug-instance incidents <instance-id>' or 'debug-instance variables <instance-id>' to inspect it."
|
|
816
|
+
});
|
|
817
|
+
});
|
|
818
|
+
debugInstance.command("status").description(`Get the current status of a ${toolLabel} debug instance`).argument("<instance-id>", "Debug instance ID").trackedAction(processContext, async (instanceId) => {
|
|
819
|
+
const result = await withDebugPimsCall((cfg) => debugPimsGet(cfg, `${DEBUG_API_PREFIX}/${instanceId}/element-executions`, "get-debug-instance-status"), "Error getting debug instance status");
|
|
820
|
+
if (!result)
|
|
821
|
+
return;
|
|
822
|
+
OutputFormatter.success({
|
|
823
|
+
Result: RESULTS.Success,
|
|
824
|
+
Code: "DebugInstanceStatus",
|
|
825
|
+
Data: result
|
|
826
|
+
});
|
|
827
|
+
});
|
|
828
|
+
debugInstance.command("breakpoints").description(`Update breakpoints for a ${toolLabel} debug instance`).argument("<instance-id>", "Debug instance ID").option("--inputs <value>", "Breakpoints payload as JSON string, @file path, or piped via stdin").trackedAction(processContext, async (instanceId, options) => {
|
|
829
|
+
const [readError, data] = await catchError(resolveJsonInput({
|
|
830
|
+
inline: options.inputs,
|
|
831
|
+
allowStdin: true
|
|
832
|
+
}));
|
|
833
|
+
if (readError) {
|
|
834
|
+
OutputFormatter.error({
|
|
835
|
+
Result: RESULTS.Failure,
|
|
836
|
+
Message: "Error reading breakpoints input",
|
|
837
|
+
Instructions: readError.message
|
|
838
|
+
});
|
|
839
|
+
processContext.exit(1);
|
|
840
|
+
return;
|
|
841
|
+
}
|
|
842
|
+
const body = data ?? {
|
|
843
|
+
breakpoints: []
|
|
844
|
+
};
|
|
845
|
+
const result = await withDebugPimsCall((cfg) => debugPimsPut(cfg, `${DEBUG_API_PREFIX}/${instanceId}/breakpoints`, body), "Error updating breakpoints");
|
|
846
|
+
if (!result)
|
|
847
|
+
return;
|
|
848
|
+
OutputFormatter.success({
|
|
849
|
+
Result: RESULTS.Success,
|
|
850
|
+
Code: "DebugInstanceBreakpointsUpdated",
|
|
851
|
+
Data: result
|
|
852
|
+
});
|
|
853
|
+
});
|
|
854
|
+
debugInstance.command("cancel").description(`Cancel a ${toolLabel} debug instance`).argument("<instance-id>", "Debug instance ID").trackedAction(processContext, async (instanceId) => {
|
|
855
|
+
const result = await withDebugPimsCall((cfg) => debugPimsPost(cfg, `${DEBUG_API_PREFIX}/${instanceId}/cancel`, { comment: "" }), "Error canceling debug instance");
|
|
856
|
+
if (!result)
|
|
857
|
+
return;
|
|
858
|
+
OutputFormatter.success({
|
|
859
|
+
Result: RESULTS.Success,
|
|
860
|
+
Code: "DebugInstanceCanceled",
|
|
861
|
+
Data: result
|
|
862
|
+
});
|
|
863
|
+
});
|
|
864
|
+
debugInstance.command("continue").description(`Continue execution on a paused ${toolLabel} debug instance`).argument("<instance-id>", "Debug instance ID").option("--inputs <value>", "Continue payload as JSON string, @file path, or piped via stdin").trackedAction(processContext, async (instanceId, options) => {
|
|
865
|
+
const [readError, data] = await catchError(resolveJsonInput({
|
|
866
|
+
inline: options.inputs,
|
|
867
|
+
allowStdin: true
|
|
868
|
+
}));
|
|
869
|
+
if (readError) {
|
|
870
|
+
OutputFormatter.error({
|
|
871
|
+
Result: RESULTS.Failure,
|
|
872
|
+
Message: "Error reading continue input",
|
|
873
|
+
Instructions: readError.message
|
|
874
|
+
});
|
|
875
|
+
processContext.exit(1);
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
const body = data ?? {
|
|
879
|
+
nextStep: false
|
|
880
|
+
};
|
|
881
|
+
const result = await withDebugPimsCall((cfg) => debugPimsPost(cfg, `${DEBUG_API_PREFIX}/${instanceId}/continue`, body), "Error continuing debug instance");
|
|
882
|
+
if (!result)
|
|
883
|
+
return;
|
|
884
|
+
OutputFormatter.success({
|
|
885
|
+
Result: RESULTS.Success,
|
|
886
|
+
Code: "DebugInstanceContinued",
|
|
887
|
+
Data: result
|
|
888
|
+
});
|
|
889
|
+
});
|
|
890
|
+
debugInstance.command("incidents").description(`Get incidents for a ${toolLabel} debug instance`).argument("<instance-id>", "Debug instance ID").trackedAction(processContext, async (instanceId) => {
|
|
891
|
+
const result = await withDebugPimsCall((cfg) => debugPimsGet(cfg, `${DEBUG_API_PREFIX}/${instanceId}/incidents`), "Error getting debug instance incidents");
|
|
892
|
+
if (!result)
|
|
893
|
+
return;
|
|
894
|
+
OutputFormatter.success({
|
|
895
|
+
Result: RESULTS.Success,
|
|
896
|
+
Code: "DebugInstanceIncidents",
|
|
897
|
+
Data: result ?? []
|
|
898
|
+
});
|
|
899
|
+
});
|
|
900
|
+
debugInstance.command("variables").description(`Get variables for a ${toolLabel} debug instance`).argument("<instance-id>", "Debug instance ID").option("--parent-element-id <id>", "Filter variables by parent element ID").trackedAction(processContext, async (instanceId, options) => {
|
|
901
|
+
const query = buildQueryString({
|
|
902
|
+
parentElementId: options.parentElementId
|
|
903
|
+
});
|
|
904
|
+
const result = await withDebugPimsCall((cfg) => debugPimsGet(cfg, `${DEBUG_API_PREFIX}/${instanceId}/variables${query}`), "Error getting debug instance variables");
|
|
905
|
+
if (!result)
|
|
906
|
+
return;
|
|
907
|
+
OutputFormatter.success({
|
|
908
|
+
Result: RESULTS.Success,
|
|
909
|
+
Code: "DebugInstanceVariables",
|
|
910
|
+
Data: result
|
|
911
|
+
});
|
|
912
|
+
});
|
|
913
|
+
debugInstance.command("variables-set").description(`Update variables for a ${toolLabel} debug instance`).argument("<instance-id>", "Debug instance ID").option("--inputs <value>", "Patch variables payload as JSON string, @file path, or piped via stdin").option("--parent-element-id <id>", "Filter by parent element ID").trackedAction(processContext, async (instanceId, options) => {
|
|
914
|
+
const [readError, data] = await catchError(resolveJsonInput({
|
|
915
|
+
inline: options.inputs,
|
|
916
|
+
allowStdin: true
|
|
917
|
+
}));
|
|
918
|
+
if (readError) {
|
|
919
|
+
OutputFormatter.error({
|
|
920
|
+
Result: RESULTS.Failure,
|
|
921
|
+
Message: "Error reading variables payload",
|
|
922
|
+
Instructions: readError.message
|
|
923
|
+
});
|
|
924
|
+
processContext.exit(1);
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
if (data === undefined) {
|
|
928
|
+
OutputFormatter.error({
|
|
929
|
+
Result: RESULTS.Failure,
|
|
930
|
+
Message: "Missing variables payload",
|
|
931
|
+
Instructions: "Provide --inputs <json|@file> or pipe JSON via stdin."
|
|
932
|
+
});
|
|
933
|
+
processContext.exit(1);
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
const body = data;
|
|
937
|
+
const query = buildQueryString({
|
|
938
|
+
parentElementId: options.parentElementId
|
|
939
|
+
});
|
|
940
|
+
const result = await withDebugPimsCall((cfg) => debugPimsPatch(cfg, `${DEBUG_API_PREFIX}/${instanceId}/variables${query}`, body), "Error updating debug instance variables");
|
|
941
|
+
if (!result)
|
|
942
|
+
return;
|
|
943
|
+
OutputFormatter.success({
|
|
944
|
+
Result: RESULTS.Success,
|
|
945
|
+
Code: "DebugInstanceVariablesSet",
|
|
946
|
+
Data: result
|
|
947
|
+
});
|
|
948
|
+
});
|
|
949
|
+
debugInstance.command("variables-all").description(`Get all variables including subprocesses for a ${toolLabel} debug instance`).argument("<instance-id>", "Debug instance ID").trackedAction(processContext, async (instanceId) => {
|
|
950
|
+
const result = await withDebugPimsCall((cfg) => debugPimsGet(cfg, `${DEBUG_API_PREFIX}/${instanceId}/variables-all`), "Error getting all debug instance variables");
|
|
951
|
+
if (!result)
|
|
952
|
+
return;
|
|
953
|
+
OutputFormatter.success({
|
|
954
|
+
Result: RESULTS.Success,
|
|
955
|
+
Code: "DebugInstanceVariablesAll",
|
|
956
|
+
Data: result
|
|
957
|
+
});
|
|
958
|
+
});
|
|
959
|
+
};
|
|
960
|
+
|
|
961
|
+
// ../maestro-sdk/src/with-pims-call.ts
|
|
962
|
+
var NETWORK_ERROR_CODES = new Set([
|
|
963
|
+
"ECONNREFUSED",
|
|
964
|
+
"ECONNRESET",
|
|
965
|
+
"ENOTFOUND",
|
|
966
|
+
"EAI_AGAIN",
|
|
967
|
+
"ETIMEDOUT",
|
|
968
|
+
"EPIPE",
|
|
969
|
+
"EHOSTUNREACH",
|
|
970
|
+
"ENETUNREACH",
|
|
971
|
+
"EAI_FAIL"
|
|
972
|
+
]);
|
|
973
|
+
function capitalise(value) {
|
|
974
|
+
if (value.length === 0) {
|
|
975
|
+
return value;
|
|
976
|
+
}
|
|
977
|
+
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
978
|
+
}
|
|
979
|
+
function isNetworkError(error) {
|
|
980
|
+
if (error === null || typeof error !== "object") {
|
|
981
|
+
return false;
|
|
982
|
+
}
|
|
983
|
+
const err = error;
|
|
984
|
+
const code = typeof err.code === "string" ? err.code : undefined;
|
|
985
|
+
if (code && NETWORK_ERROR_CODES.has(code)) {
|
|
986
|
+
return true;
|
|
987
|
+
}
|
|
988
|
+
const cause = err.cause;
|
|
989
|
+
if (cause && typeof cause === "object") {
|
|
990
|
+
const causeCode = typeof cause.code === "string" ? cause.code : undefined;
|
|
991
|
+
if (causeCode && NETWORK_ERROR_CODES.has(causeCode)) {
|
|
992
|
+
return true;
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
return false;
|
|
996
|
+
}
|
|
997
|
+
function pimsFailureContext(error) {
|
|
998
|
+
return {
|
|
999
|
+
httpStatus: error.httpStatus,
|
|
1000
|
+
endpoint: error.endpoint,
|
|
1001
|
+
method: error.method,
|
|
1002
|
+
...error.parsedErrorCode ? { errorCode: error.parsedErrorCode } : {},
|
|
1003
|
+
...error.parsedRequestId ? { requestId: error.parsedRequestId } : {},
|
|
1004
|
+
...error.parsedTraceId ? { traceId: error.parsedTraceId } : {}
|
|
1005
|
+
};
|
|
1006
|
+
}
|
|
1007
|
+
function pimsFailureInstructions(error) {
|
|
1008
|
+
const lines = [
|
|
1009
|
+
`Status: ${error.httpStatus} ${error.statusText}`,
|
|
1010
|
+
`Resource: ${error.method} ${error.endpoint}`
|
|
1011
|
+
];
|
|
1012
|
+
if (error.parsedErrorMessage) {
|
|
1013
|
+
lines.push(`Message: ${error.parsedErrorMessage}`);
|
|
1014
|
+
} else if (error.body.trim()) {
|
|
1015
|
+
lines.push(`Body: ${compactPimsErrorBody(error.body)}`);
|
|
1016
|
+
}
|
|
1017
|
+
if (error.parsedErrorCode) {
|
|
1018
|
+
lines.push(`Error code: ${error.parsedErrorCode}`);
|
|
1019
|
+
}
|
|
1020
|
+
if (error.parsedTraceId) {
|
|
1021
|
+
lines.push(`Trace ID: ${error.parsedTraceId}`);
|
|
1022
|
+
} else if (error.parsedRequestId) {
|
|
1023
|
+
lines.push(`Request ID: ${error.parsedRequestId}`);
|
|
1024
|
+
}
|
|
1025
|
+
lines.push("Remediation: verify the folder scope and identifiers, then retry. If the error persists, contact UiPath support with the status, resource, and trace/request ID.");
|
|
1026
|
+
return lines.join(`
|
|
1027
|
+
`);
|
|
1028
|
+
}
|
|
1029
|
+
function compactPimsErrorBody(body) {
|
|
1030
|
+
const text = body.split(/\s+/).filter(Boolean).join(" ");
|
|
1031
|
+
return text.length <= 700 ? text : `${text.slice(0, 699)}...`;
|
|
1032
|
+
}
|
|
1033
|
+
function resolvePimsEnvelope(error, errorMessage, hint) {
|
|
1034
|
+
const status = error.httpStatus;
|
|
1035
|
+
if (status === 404) {
|
|
1036
|
+
const message = hint?.resource && hint.id ? `${capitalise(hint.resource)} not found: ${hint.id}` : hint?.resource ? `${capitalise(hint.resource)} not found` : errorMessage;
|
|
1037
|
+
return { result: RESULTS.Failure, code: "NotFound", message };
|
|
1038
|
+
}
|
|
1039
|
+
if (status === 401) {
|
|
1040
|
+
return {
|
|
1041
|
+
result: RESULTS.AuthenticationError,
|
|
1042
|
+
code: "Unauthorized",
|
|
1043
|
+
message: errorMessage
|
|
1044
|
+
};
|
|
1045
|
+
}
|
|
1046
|
+
if (status === 403) {
|
|
1047
|
+
return {
|
|
1048
|
+
result: RESULTS.AuthenticationError,
|
|
1049
|
+
code: "Forbidden",
|
|
1050
|
+
message: errorMessage
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
if (status >= 500 && status < 600) {
|
|
1054
|
+
return {
|
|
1055
|
+
result: RESULTS.Failure,
|
|
1056
|
+
code: `ServerError_${status}`,
|
|
1057
|
+
message: errorMessage
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
return {
|
|
1061
|
+
result: RESULTS.Failure,
|
|
1062
|
+
code: `Http_${status}`,
|
|
1063
|
+
message: errorMessage
|
|
1064
|
+
};
|
|
1065
|
+
}
|
|
1066
|
+
async function withPimsCall(fn, errorMessage, hint) {
|
|
1067
|
+
const [configError, config] = await catchError(createPimsConfig());
|
|
1068
|
+
if (configError) {
|
|
1069
|
+
logger.warn(`${errorMessage}: ${configError.message}`);
|
|
1070
|
+
OutputFormatter.error({
|
|
1071
|
+
Result: RESULTS.Failure,
|
|
1072
|
+
Code: "ConfigError",
|
|
1073
|
+
Message: errorMessage,
|
|
1074
|
+
Instructions: configError.message
|
|
1075
|
+
});
|
|
1076
|
+
processContext.exit(1);
|
|
1077
|
+
return;
|
|
1078
|
+
}
|
|
1079
|
+
const [error, result] = await catchError(fn(config));
|
|
1080
|
+
if (error) {
|
|
1081
|
+
if (isNetworkError(error)) {
|
|
1082
|
+
const msg2 = await extractErrorMessage(error);
|
|
1083
|
+
logger.warn(`${errorMessage}: ${msg2}`);
|
|
1084
|
+
OutputFormatter.error({
|
|
1085
|
+
Result: RESULTS.Failure,
|
|
1086
|
+
Code: "NetworkError",
|
|
1087
|
+
Message: errorMessage,
|
|
1088
|
+
Instructions: msg2
|
|
1089
|
+
});
|
|
1090
|
+
processContext.exit(1);
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
1093
|
+
if (error instanceof PimsApiError) {
|
|
1094
|
+
const envelope = resolvePimsEnvelope(error, errorMessage, hint);
|
|
1095
|
+
logger.warn(`${envelope.message}: ${error.message}`);
|
|
1096
|
+
OutputFormatter.error({
|
|
1097
|
+
Result: envelope.result,
|
|
1098
|
+
Code: envelope.code,
|
|
1099
|
+
Message: envelope.message,
|
|
1100
|
+
Instructions: pimsFailureInstructions(error),
|
|
1101
|
+
Context: pimsFailureContext(error)
|
|
1102
|
+
});
|
|
1103
|
+
processContext.exit(1);
|
|
1104
|
+
return;
|
|
1105
|
+
}
|
|
1106
|
+
const msg = await extractErrorMessage(error);
|
|
1107
|
+
logger.warn(`${errorMessage}: ${msg}`);
|
|
1108
|
+
OutputFormatter.error({
|
|
1109
|
+
Result: RESULTS.Failure,
|
|
1110
|
+
Code: "UnknownError",
|
|
1111
|
+
Message: errorMessage,
|
|
1112
|
+
Instructions: msg
|
|
1113
|
+
});
|
|
1114
|
+
processContext.exit(1);
|
|
1115
|
+
return;
|
|
1116
|
+
}
|
|
1117
|
+
return result;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
// ../maestro-sdk/src/shared-commands/incidents.ts
|
|
1121
|
+
var registerSharedIncidentCommands = (program, config) => {
|
|
1122
|
+
const { toolLabel } = config;
|
|
1123
|
+
const incident = program.command("incident").description(`Manage ${toolLabel} incidents`);
|
|
1124
|
+
incident.command("summary").description(`Get ${toolLabel} incident summaries across processes`).option("--folder-key <key>", "Folder key").option("-l, --limit <number>", "Number of items to return (1-10000)", parseLimit).option("--offset <number>", "Number of items to skip (0-1000000)", parseOffset, 0).option("--process-key <process-key>", "Filter by process key").option("--status <status>", "Filter by incident status").option("--severity <severity>", "Filter by incident severity").trackedAction(processContext, async (options) => {
|
|
1125
|
+
const query = buildQueryString({
|
|
1126
|
+
processKey: options.processKey,
|
|
1127
|
+
incidentStatus: options.status,
|
|
1128
|
+
incidentSeverity: options.severity,
|
|
1129
|
+
$top: options.limit,
|
|
1130
|
+
$skip: options.offset !== 0 ? options.offset : undefined
|
|
1131
|
+
});
|
|
1132
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1133
|
+
const result = await withPimsCall((config2) => pimsGet(config2, `/incidents/summary${query}`, reqOptions), "Error listing incidents");
|
|
1134
|
+
if (!result)
|
|
1135
|
+
return;
|
|
1136
|
+
OutputFormatter.success({
|
|
1137
|
+
Result: RESULTS.Success,
|
|
1138
|
+
Code: "IncidentSummary",
|
|
1139
|
+
Data: result
|
|
1140
|
+
});
|
|
1141
|
+
});
|
|
1142
|
+
incident.command("get").description(`Get a single ${toolLabel} incident by ID`).argument("<incident-id>", "Incident ID").requiredOption("-f, --folder-key <key>", "Folder key").trackedAction(processContext, async (incidentId, options) => {
|
|
1143
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1144
|
+
const result = await withPimsCall((config2) => pimsGet(config2, `/incidents/${encodeURIComponent(incidentId)}`, reqOptions), "Error getting incident", { resource: "incident", id: incidentId });
|
|
1145
|
+
if (!result)
|
|
1146
|
+
return;
|
|
1147
|
+
OutputFormatter.success({
|
|
1148
|
+
Result: RESULTS.Success,
|
|
1149
|
+
Code: "IncidentGet",
|
|
1150
|
+
Data: result
|
|
1151
|
+
});
|
|
1152
|
+
});
|
|
1153
|
+
};
|
|
1154
|
+
|
|
1155
|
+
// ../maestro-sdk/src/instance-status.ts
|
|
1156
|
+
var INSTANCE_STATUSES = [
|
|
1157
|
+
"Canceling",
|
|
1158
|
+
"Cancelled",
|
|
1159
|
+
"Completed",
|
|
1160
|
+
"Faulted",
|
|
1161
|
+
"Paused",
|
|
1162
|
+
"Pausing",
|
|
1163
|
+
"Pending",
|
|
1164
|
+
"Resuming",
|
|
1165
|
+
"Retrying",
|
|
1166
|
+
"Running",
|
|
1167
|
+
"Upgrading"
|
|
1168
|
+
];
|
|
1169
|
+
var STATUS_ALIASES = new Map([
|
|
1170
|
+
["successful", "Completed"],
|
|
1171
|
+
["success", "Completed"],
|
|
1172
|
+
["canceled", "Cancelled"]
|
|
1173
|
+
]);
|
|
1174
|
+
var CANONICAL_BY_LOWER = new Map(INSTANCE_STATUSES.map((status) => [status.toLowerCase(), status]));
|
|
1175
|
+
function resolveInstanceStatus(raw) {
|
|
1176
|
+
const normalized = raw.trim().toLowerCase();
|
|
1177
|
+
return CANONICAL_BY_LOWER.get(normalized) ?? STATUS_ALIASES.get(normalized);
|
|
1178
|
+
}
|
|
1179
|
+
var INSTANCE_STATUS_LIST = INSTANCE_STATUSES.join(", ");
|
|
1180
|
+
function resolveInstanceStatuses(raw) {
|
|
1181
|
+
const statuses = [];
|
|
1182
|
+
const invalid = [];
|
|
1183
|
+
for (const value of raw) {
|
|
1184
|
+
const resolved = resolveInstanceStatus(value);
|
|
1185
|
+
if (resolved === undefined) {
|
|
1186
|
+
invalid.push(value);
|
|
1187
|
+
continue;
|
|
1188
|
+
}
|
|
1189
|
+
if (!statuses.includes(resolved)) {
|
|
1190
|
+
statuses.push(resolved);
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
return { statuses, invalid };
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
// ../maestro-sdk/src/shared-commands/instances.ts
|
|
1197
|
+
var collectStatus = (raw, prev) => [...prev, raw];
|
|
1198
|
+
var MAX_INSTANCE_PAGE_SIZE = 500;
|
|
1199
|
+
var parseInstanceLimit = (raw) => parseBoundedInt(raw, "--limit", { min: 1, max: MAX_INSTANCE_PAGE_SIZE });
|
|
1200
|
+
function extractProcessInstances(result) {
|
|
1201
|
+
if (Array.isArray(result)) {
|
|
1202
|
+
return result;
|
|
1203
|
+
}
|
|
1204
|
+
return result.instances ?? result.value ?? result.items ?? [];
|
|
1205
|
+
}
|
|
1206
|
+
function extractInstanceCursor(result) {
|
|
1207
|
+
if (Array.isArray(result)) {
|
|
1208
|
+
return { hasMore: false };
|
|
1209
|
+
}
|
|
1210
|
+
const nextPage = result.nextPage ?? undefined;
|
|
1211
|
+
return {
|
|
1212
|
+
nextPage,
|
|
1213
|
+
hasMore: result.hasMoreResults ?? nextPage !== undefined
|
|
1214
|
+
};
|
|
1215
|
+
}
|
|
1216
|
+
var failListFilter = (message, instructions) => {
|
|
1217
|
+
OutputFormatter.error({
|
|
1218
|
+
Result: RESULTS.ValidationError,
|
|
1219
|
+
Message: message,
|
|
1220
|
+
Instructions: instructions
|
|
1221
|
+
});
|
|
1222
|
+
processContext.exit(EXIT_CODES.ValidationError);
|
|
1223
|
+
return null;
|
|
1224
|
+
};
|
|
1225
|
+
function resolveListFilters(options) {
|
|
1226
|
+
if (options.offset !== undefined && Number(options.offset) !== 0) {
|
|
1227
|
+
return failListFilter("--offset is not supported when listing process instances", "The instances API pages by cursor, not by offset. Drop --offset, " + "then pass the Pagination.NextPage value from the previous " + "response to --next-page.");
|
|
1228
|
+
}
|
|
1229
|
+
if (options.processKey !== undefined && !isGuid(options.processKey)) {
|
|
1230
|
+
return failListFilter(`--process-key expects a process key (GUID), got '${options.processKey}'`, "Pass the instance's processKey. For the dotted package " + "identifier that `uip or processes list` prints as ProcessKey, " + "use --package-id instead.");
|
|
1231
|
+
}
|
|
1232
|
+
const { statuses, invalid } = resolveInstanceStatuses(options.status ?? []);
|
|
1233
|
+
if (invalid.length > 0) {
|
|
1234
|
+
return failListFilter(`Invalid --status value${invalid.length > 1 ? "s" : ""}: ${invalid.join(", ")}`, `Valid values: ${INSTANCE_STATUS_LIST}.`);
|
|
1235
|
+
}
|
|
1236
|
+
return { statuses: statuses.length > 0 ? statuses : undefined };
|
|
1237
|
+
}
|
|
1238
|
+
var registerSharedInstanceCommands = (program, config) => {
|
|
1239
|
+
const {
|
|
1240
|
+
toolLabel,
|
|
1241
|
+
assetType,
|
|
1242
|
+
processType,
|
|
1243
|
+
includeElementExecutions = true,
|
|
1244
|
+
folderKeyRequired = true,
|
|
1245
|
+
listFolderKeyRequired = folderKeyRequired
|
|
1246
|
+
} = config;
|
|
1247
|
+
const withFolderKey = (cmd, required = folderKeyRequired) => required ? cmd.requiredOption("-f, --folder-key <key>", "Folder key (GUID)") : cmd.option("-f, --folder-key <key>", "Folder key (GUID)");
|
|
1248
|
+
const instances = program.command("instance").description(`Manage ${toolLabel} process instances`);
|
|
1249
|
+
const listCmd = instances.command("list").description(`List ${toolLabel} process instances. Filters are applied by the ` + "server: --status narrows by run status, --process-key by " + "process key (GUID), --package-id by package identifier, and " + "--from-date/--to-date by start time. Results page by cursor " + "— read Pagination.NextPage and pass it back via --next-page.");
|
|
1250
|
+
withFolderKey(listCmd, listFolderKeyRequired).option("-l, --limit <number>", `Number of items to return (1-${MAX_INSTANCE_PAGE_SIZE})`, parseInstanceLimit, DEFAULT_PAGE_SIZE).option("--offset <number>", "Not supported by the instances API — use --next-page instead").option("--next-page <cursor>", "Cursor from a previous response's Pagination.NextPage").option("--process-key <process-key>", "Filter by process key (GUID). For the dotted package " + "identifier use --package-id.").option("--package-id <id>", "Filter by package ID").option("--error-code <code>", "Filter by error code").option("--status <status>", "Filter by instance status (repeatable; OR-semantics). " + `Values: ${INSTANCE_STATUS_LIST}.`, collectStatus, []).option("--from-date <iso-8601>", "Only include instances started at or after this ISO-8601 " + "timestamp (e.g. 2026-01-01T00:00:00Z).").option("--to-date <iso-8601>", "Only include instances started at or before this ISO-8601 " + "timestamp (e.g. 2026-02-01T00:00:00Z).").trackedAction(processContext, async (options) => {
|
|
1251
|
+
const filters = resolveListFilters(options);
|
|
1252
|
+
if (!filters)
|
|
1253
|
+
return;
|
|
1254
|
+
const query = buildQueryString({
|
|
1255
|
+
processKey: options.processKey,
|
|
1256
|
+
packageId: options.packageId,
|
|
1257
|
+
errorCode: options.errorCode,
|
|
1258
|
+
statuses: filters.statuses?.join(","),
|
|
1259
|
+
startedTimeUtcStart: options.fromDate,
|
|
1260
|
+
startedTimeUtcEnd: options.toDate,
|
|
1261
|
+
processType,
|
|
1262
|
+
pageSize: options.limit,
|
|
1263
|
+
nextPage: options.nextPage
|
|
1264
|
+
});
|
|
1265
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1266
|
+
const result = await withPimsCall((config2) => pimsGet(config2, `/instances${query}`, reqOptions), "Error listing instances");
|
|
1267
|
+
if (!result)
|
|
1268
|
+
return;
|
|
1269
|
+
const instanceList = extractProcessInstances(result);
|
|
1270
|
+
const cursor = extractInstanceCursor(result);
|
|
1271
|
+
OutputFormatter.success({
|
|
1272
|
+
Result: RESULTS.Success,
|
|
1273
|
+
Code: "InstanceList",
|
|
1274
|
+
Data: instanceList,
|
|
1275
|
+
Pagination: new Pagination({
|
|
1276
|
+
returned: instanceList.length,
|
|
1277
|
+
limit: options.limit,
|
|
1278
|
+
hasMore: cursor.hasMore,
|
|
1279
|
+
nextPage: cursor.nextPage
|
|
1280
|
+
})
|
|
1281
|
+
});
|
|
1282
|
+
});
|
|
1283
|
+
const getCmd = instances.command("get").description(`Get a ${toolLabel} process instance by ID`).argument("<instance-id>", "Process instance ID");
|
|
1284
|
+
withFolderKey(getCmd).trackedAction(processContext, async (instanceId, options) => {
|
|
1285
|
+
const result = await withPimsCall((config2) => pimsGet(config2, `/instances/${instanceId}`, { folderKey: options.folderKey }), "Error getting instance", { resource: "instance", id: instanceId });
|
|
1286
|
+
if (!result)
|
|
1287
|
+
return;
|
|
1288
|
+
OutputFormatter.success({
|
|
1289
|
+
Result: RESULTS.Success,
|
|
1290
|
+
Code: "InstanceGet",
|
|
1291
|
+
Data: result
|
|
1292
|
+
});
|
|
1293
|
+
});
|
|
1294
|
+
const pauseCmd = instances.command("pause").description(`Pause a running ${toolLabel} process instance`).argument("<instance-id>", "Process instance ID");
|
|
1295
|
+
withFolderKey(pauseCmd).option("--comment <text>", "Optional comment for the operation").trackedAction(processContext, async (instanceId, options) => {
|
|
1296
|
+
const body = { comment: options.comment || "" };
|
|
1297
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1298
|
+
const result = await withPimsCall((config2) => pimsPost(config2, `/instances/${instanceId}/pause`, body, reqOptions), "Error pausing instance");
|
|
1299
|
+
if (!result)
|
|
1300
|
+
return;
|
|
1301
|
+
OutputFormatter.success({
|
|
1302
|
+
Result: RESULTS.Success,
|
|
1303
|
+
Code: "InstancePaused",
|
|
1304
|
+
Data: result
|
|
1305
|
+
});
|
|
1306
|
+
});
|
|
1307
|
+
const resumeCmd = instances.command("resume").description(`Resume a paused ${toolLabel} process instance`).argument("<instance-id>", "Process instance ID");
|
|
1308
|
+
withFolderKey(resumeCmd).option("--comment <text>", "Optional comment for the operation").trackedAction(processContext, async (instanceId, options) => {
|
|
1309
|
+
const body = { comment: options.comment || "" };
|
|
1310
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1311
|
+
const result = await withPimsCall((config2) => pimsPost(config2, `/instances/${instanceId}/resume`, body, reqOptions), "Error resuming instance");
|
|
1312
|
+
if (!result)
|
|
1313
|
+
return;
|
|
1314
|
+
OutputFormatter.success({
|
|
1315
|
+
Result: RESULTS.Success,
|
|
1316
|
+
Code: "InstanceResumed",
|
|
1317
|
+
Data: result
|
|
1318
|
+
});
|
|
1319
|
+
});
|
|
1320
|
+
const cancelCmd = instances.command("cancel").description(`Cancel a ${toolLabel} process instance`).argument("<instance-id>", "Process instance ID");
|
|
1321
|
+
withFolderKey(cancelCmd).option("--comment <text>", "Optional comment for the operation").trackedAction(processContext, async (instanceId, options) => {
|
|
1322
|
+
const body = { comment: options.comment || "" };
|
|
1323
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1324
|
+
const result = await withPimsCall((config2) => pimsPost(config2, `/instances/${instanceId}/cancel`, body, reqOptions), "Error canceling instance");
|
|
1325
|
+
if (!result)
|
|
1326
|
+
return;
|
|
1327
|
+
OutputFormatter.success({
|
|
1328
|
+
Result: RESULTS.Success,
|
|
1329
|
+
Code: "InstanceCanceled",
|
|
1330
|
+
Data: result
|
|
1331
|
+
});
|
|
1332
|
+
});
|
|
1333
|
+
const variablesCmd = instances.command("variables").description(`Get variables for a ${toolLabel} process instance`).argument("<instance-id>", "Process instance ID");
|
|
1334
|
+
withFolderKey(variablesCmd).option("--parent-element-id <id>", "Filter variables by parent element ID").trackedAction(processContext, async (instanceId, options) => {
|
|
1335
|
+
const query = buildQueryString({
|
|
1336
|
+
parentElementId: options.parentElementId
|
|
1337
|
+
});
|
|
1338
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1339
|
+
const result = await withPimsCall((config2) => pimsGet(config2, `/instances/${instanceId}/variables${query}`, reqOptions), "Error getting variables");
|
|
1340
|
+
if (!result)
|
|
1341
|
+
return;
|
|
1342
|
+
OutputFormatter.success({
|
|
1343
|
+
Result: RESULTS.Success,
|
|
1344
|
+
Code: "InstanceVariables",
|
|
1345
|
+
Data: result
|
|
1346
|
+
});
|
|
1347
|
+
});
|
|
1348
|
+
const incidentsCmd = instances.command("incidents").description(`Get incidents for a ${toolLabel} process instance`).argument("<instance-id>", "Process instance ID");
|
|
1349
|
+
withFolderKey(incidentsCmd).trackedAction(processContext, async (instanceId, options) => {
|
|
1350
|
+
const result = await withPimsCall((config2) => pimsGet(config2, `/instances/${instanceId}/incidents`, { folderKey: options.folderKey }), "Error getting incidents");
|
|
1351
|
+
if (!result)
|
|
1352
|
+
return;
|
|
1353
|
+
OutputFormatter.success({
|
|
1354
|
+
Result: RESULTS.Success,
|
|
1355
|
+
Code: "InstanceIncidents",
|
|
1356
|
+
Data: result
|
|
1357
|
+
});
|
|
1358
|
+
});
|
|
1359
|
+
const assetCmd = instances.command("asset").description(`Get the ${toolLabel} definition for a process instance`).argument("<instance-id>", "Process instance ID");
|
|
1360
|
+
withFolderKey(assetCmd).trackedAction(processContext, async (instanceId, options) => {
|
|
1361
|
+
const result = await withPimsCall((config2) => pimsGet(config2, `/instances/${instanceId}/asset?type=${assetType}`, { folderKey: options.folderKey }), "Error getting asset");
|
|
1362
|
+
if (!result)
|
|
1363
|
+
return;
|
|
1364
|
+
OutputFormatter.success({
|
|
1365
|
+
Result: RESULTS.Success,
|
|
1366
|
+
Code: "InstanceAsset",
|
|
1367
|
+
Data: result
|
|
1368
|
+
});
|
|
1369
|
+
});
|
|
1370
|
+
const retryCmd = instances.command("retry").description(`Retry a faulted ${toolLabel} process instance`).argument("<instance-id>", "Process instance ID");
|
|
1371
|
+
withFolderKey(retryCmd).option("--comment <text>", "Optional comment for the operation").trackedAction(processContext, async (instanceId, options) => {
|
|
1372
|
+
const body = { comment: options.comment || "" };
|
|
1373
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1374
|
+
const result = await withPimsCall((config2) => pimsPost(config2, `/instances/${instanceId}/retry`, body, reqOptions), "Error retrying instance");
|
|
1375
|
+
if (!result)
|
|
1376
|
+
return;
|
|
1377
|
+
OutputFormatter.success({
|
|
1378
|
+
Result: RESULTS.Success,
|
|
1379
|
+
Code: "InstanceRetried",
|
|
1380
|
+
Data: result
|
|
1381
|
+
});
|
|
1382
|
+
});
|
|
1383
|
+
const migrateCmd = instances.command("migrate").description(`Migrate a ${toolLabel} process instance to a different package version`).argument("<instance-id>", "Process instance ID").argument("<new-version>", "Target package version");
|
|
1384
|
+
withFolderKey(migrateCmd).option("--comment <text>", "Optional comment for the operation").trackedAction(processContext, async (instanceId, newVersion, options) => {
|
|
1385
|
+
const body = {
|
|
1386
|
+
newVersion,
|
|
1387
|
+
comment: options.comment || ""
|
|
1388
|
+
};
|
|
1389
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1390
|
+
const result = await withPimsCall((config2) => pimsPost(config2, `/instances/${instanceId}/upgrade`, body, reqOptions), "Error migrating instance");
|
|
1391
|
+
if (!result)
|
|
1392
|
+
return;
|
|
1393
|
+
OutputFormatter.success({
|
|
1394
|
+
Result: RESULTS.Success,
|
|
1395
|
+
Code: "InstanceMigrated",
|
|
1396
|
+
Data: result
|
|
1397
|
+
});
|
|
1398
|
+
});
|
|
1399
|
+
const gotoCmd = instances.command("goto").description("Move execution cursor from one element to another").argument("<instance-id>", "Process instance ID").argument("<transitions>", `JSON array of transitions, e.g. '[{"sourceElementId":"A","targetElementId":"B"}]'`);
|
|
1400
|
+
withFolderKey(gotoCmd).trackedAction(processContext, async (instanceId, transitionsJson, options) => {
|
|
1401
|
+
const [parseError, transitions] = catchError(() => JSON.parse(transitionsJson));
|
|
1402
|
+
const isValidShape = !parseError && Array.isArray(transitions) && transitions.every((t) => t?.sourceElementId != null && t?.targetElementId != null);
|
|
1403
|
+
if (!isValidShape) {
|
|
1404
|
+
OutputFormatter.error({
|
|
1405
|
+
Result: RESULTS.Failure,
|
|
1406
|
+
Message: "Error applying goto",
|
|
1407
|
+
Instructions: parseError ? `Invalid transitions JSON: ${parseError.message}` : 'Each transition must have "sourceElementId" and "targetElementId"'
|
|
1408
|
+
});
|
|
1409
|
+
processContext.exit(1);
|
|
1410
|
+
return;
|
|
1411
|
+
}
|
|
1412
|
+
const body = { transitions };
|
|
1413
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1414
|
+
const result = await withPimsCall((config2) => pimsPost(config2, `/instances/${instanceId}/goto`, body, reqOptions), "Error applying goto");
|
|
1415
|
+
if (!result)
|
|
1416
|
+
return;
|
|
1417
|
+
OutputFormatter.success({
|
|
1418
|
+
Result: RESULTS.Success,
|
|
1419
|
+
Code: "InstanceGoto",
|
|
1420
|
+
Data: result
|
|
1421
|
+
});
|
|
1422
|
+
});
|
|
1423
|
+
const cursorsCmd = instances.command("cursors").description(`Get current execution cursor positions for a ${toolLabel} process instance`).argument("<instance-id>", "Process instance ID");
|
|
1424
|
+
withFolderKey(cursorsCmd).trackedAction(processContext, async (instanceId, options) => {
|
|
1425
|
+
const result = await withPimsCall((config2) => pimsGet(config2, `/instances/${instanceId}/goto/cursors`, { folderKey: options.folderKey }), "Error getting cursors");
|
|
1426
|
+
if (!result)
|
|
1427
|
+
return;
|
|
1428
|
+
OutputFormatter.success({
|
|
1429
|
+
Result: RESULTS.Success,
|
|
1430
|
+
Code: "InstanceCursors",
|
|
1431
|
+
Data: result
|
|
1432
|
+
});
|
|
1433
|
+
});
|
|
1434
|
+
const messageCmd = instances.command("message").description(`Manage ${toolLabel} instance messages`);
|
|
1435
|
+
messageCmd.command("send").description(`Send a message to ${toolLabel} workflow subscriptions`).requiredOption("-f, --folder-key <key>", "Folder key (GUID)").option("--inputs <value>", "Message payload as JSON string, @file path, or piped via stdin").trackedAction(processContext, async (options) => {
|
|
1436
|
+
const [readError, body] = await catchError(resolveJsonInput({
|
|
1437
|
+
inline: options.inputs,
|
|
1438
|
+
allowStdin: true
|
|
1439
|
+
}));
|
|
1440
|
+
if (readError) {
|
|
1441
|
+
OutputFormatter.error({
|
|
1442
|
+
Result: RESULTS.Failure,
|
|
1443
|
+
Message: "Error reading message input",
|
|
1444
|
+
Instructions: readError.message
|
|
1445
|
+
});
|
|
1446
|
+
processContext.exit(1);
|
|
1447
|
+
return;
|
|
1448
|
+
}
|
|
1449
|
+
if (body === undefined) {
|
|
1450
|
+
OutputFormatter.error({
|
|
1451
|
+
Result: RESULTS.Failure,
|
|
1452
|
+
Message: "Missing message payload",
|
|
1453
|
+
Instructions: "Provide --inputs <json|@file> or pipe JSON via stdin."
|
|
1454
|
+
});
|
|
1455
|
+
processContext.exit(1);
|
|
1456
|
+
return;
|
|
1457
|
+
}
|
|
1458
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1459
|
+
const result = await withPimsCall((config2) => pimsPost(config2, "/instances/messages/send", body, reqOptions), "Error sending message");
|
|
1460
|
+
if (!result)
|
|
1461
|
+
return;
|
|
1462
|
+
OutputFormatter.success({
|
|
1463
|
+
Result: RESULTS.Success,
|
|
1464
|
+
Code: "MessageSent",
|
|
1465
|
+
Data: result
|
|
1466
|
+
});
|
|
1467
|
+
});
|
|
1468
|
+
if (includeElementExecutions) {
|
|
1469
|
+
const elementExeCmd = instances.command("element-executions").description(`Get element executions for a ${toolLabel} process instance`).argument("<instance-id>", "Process instance ID");
|
|
1470
|
+
withFolderKey(elementExeCmd).trackedAction(processContext, async (instanceId, options) => {
|
|
1471
|
+
const result = await withPimsCall((config2) => pimsGet(config2, `/instances/${instanceId}/element-executions`, { folderKey: options.folderKey }), "Error getting element executions");
|
|
1472
|
+
if (!result)
|
|
1473
|
+
return;
|
|
1474
|
+
OutputFormatter.success({
|
|
1475
|
+
Result: RESULTS.Success,
|
|
1476
|
+
Code: "InstanceElementExecutions",
|
|
1477
|
+
Data: result
|
|
1478
|
+
});
|
|
1479
|
+
});
|
|
1480
|
+
}
|
|
1481
|
+
const variablesSetCmd = instances.command("variables-set").description(`Update variables for a ${toolLabel} process instance`).argument("<instance-id>", "Process instance ID");
|
|
1482
|
+
withFolderKey(variablesSetCmd).option("--inputs <value>", "Patch variables payload as JSON string, @file path, or piped via stdin").trackedAction(processContext, async (instanceId, options) => {
|
|
1483
|
+
const [readError, data] = await catchError(resolveJsonInput({
|
|
1484
|
+
inline: options.inputs,
|
|
1485
|
+
allowStdin: true
|
|
1486
|
+
}));
|
|
1487
|
+
if (readError) {
|
|
1488
|
+
OutputFormatter.error({
|
|
1489
|
+
Result: RESULTS.Failure,
|
|
1490
|
+
Message: "Error reading variables input",
|
|
1491
|
+
Instructions: readError.message
|
|
1492
|
+
});
|
|
1493
|
+
processContext.exit(1);
|
|
1494
|
+
return;
|
|
1495
|
+
}
|
|
1496
|
+
if (data === undefined) {
|
|
1497
|
+
OutputFormatter.error({
|
|
1498
|
+
Result: RESULTS.Failure,
|
|
1499
|
+
Message: "Missing variables payload",
|
|
1500
|
+
Instructions: "Provide --inputs <json|@file> or pipe JSON via stdin."
|
|
1501
|
+
});
|
|
1502
|
+
processContext.exit(1);
|
|
1503
|
+
return;
|
|
1504
|
+
}
|
|
1505
|
+
const body = data;
|
|
1506
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1507
|
+
const result = await withPimsCall((config2) => pimsPatch(config2, `/instances/${instanceId}/variables`, body, reqOptions), "Error updating variables");
|
|
1508
|
+
if (!result)
|
|
1509
|
+
return;
|
|
1510
|
+
OutputFormatter.success({
|
|
1511
|
+
Result: RESULTS.Success,
|
|
1512
|
+
Code: "InstanceVariablesSet",
|
|
1513
|
+
Data: result
|
|
1514
|
+
});
|
|
1515
|
+
});
|
|
1516
|
+
const variablesAllCmd = instances.command("variables-all").description(`Get all variables (including subprocesses) for a ${toolLabel} process instance`).argument("<instance-id>", "Process instance ID");
|
|
1517
|
+
withFolderKey(variablesAllCmd).trackedAction(processContext, async (instanceId, options) => {
|
|
1518
|
+
const result = await withPimsCall((config2) => pimsGet(config2, `/instances/${instanceId}/variables-all`, { folderKey: options.folderKey }), "Error getting all variables");
|
|
1519
|
+
if (!result)
|
|
1520
|
+
return;
|
|
1521
|
+
OutputFormatter.success({
|
|
1522
|
+
Result: RESULTS.Success,
|
|
1523
|
+
Code: "InstanceVariablesAll",
|
|
1524
|
+
Data: result
|
|
1525
|
+
});
|
|
1526
|
+
});
|
|
1527
|
+
const globalVarsCmd = instances.command("global-variables").description(`Get global variables for a ${toolLabel} process instance`).argument("<instance-id>", "Process instance ID");
|
|
1528
|
+
withFolderKey(globalVarsCmd).trackedAction(processContext, async (instanceId, options) => {
|
|
1529
|
+
const result = await withPimsCall((config2) => pimsGet(config2, `/instances/${instanceId}/global-variables`, { folderKey: options.folderKey }), "Error getting global variables");
|
|
1530
|
+
if (!result)
|
|
1531
|
+
return;
|
|
1532
|
+
OutputFormatter.success({
|
|
1533
|
+
Result: RESULTS.Success,
|
|
1534
|
+
Code: "InstanceGlobalVariables",
|
|
1535
|
+
Data: result
|
|
1536
|
+
});
|
|
1537
|
+
});
|
|
1538
|
+
const element = instances.command("element").description(`Manage elements within a ${toolLabel} process instance`);
|
|
1539
|
+
const elementCancelCmd = element.command("cancel").description(`Cancel a specific element in a ${toolLabel} process instance`).argument("<instance-id>", "Process instance ID").argument("<element-id>", "Element ID");
|
|
1540
|
+
withFolderKey(elementCancelCmd).option("--comment <text>", "Optional comment for the operation").trackedAction(processContext, async (instanceId, elementId, options) => {
|
|
1541
|
+
const body = { comment: options.comment || "" };
|
|
1542
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1543
|
+
const result = await withPimsCall((config2) => pimsPost(config2, `/instances/${instanceId}/element/${elementId}/cancel`, body, reqOptions), "Error canceling element");
|
|
1544
|
+
if (!result)
|
|
1545
|
+
return;
|
|
1546
|
+
OutputFormatter.success({
|
|
1547
|
+
Result: RESULTS.Success,
|
|
1548
|
+
Code: "ElementCanceled",
|
|
1549
|
+
Data: result
|
|
1550
|
+
});
|
|
1551
|
+
});
|
|
1552
|
+
const elementRetryCmd = element.command("retry").description(`Retry a faulted element in a ${toolLabel} process instance`).argument("<instance-id>", "Process instance ID").argument("<element-id>", "Element ID");
|
|
1553
|
+
withFolderKey(elementRetryCmd).option("--comment <text>", "Optional comment for the operation").trackedAction(processContext, async (instanceId, elementId, options) => {
|
|
1554
|
+
const body = { comment: options.comment || "" };
|
|
1555
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1556
|
+
const result = await withPimsCall((config2) => pimsPost(config2, `/instances/${instanceId}/element/${elementId}/retry`, body, reqOptions), "Error retrying element");
|
|
1557
|
+
if (!result)
|
|
1558
|
+
return;
|
|
1559
|
+
OutputFormatter.success({
|
|
1560
|
+
Result: RESULTS.Success,
|
|
1561
|
+
Code: "ElementRetried",
|
|
1562
|
+
Data: result
|
|
1563
|
+
});
|
|
1564
|
+
});
|
|
1565
|
+
};
|
|
1566
|
+
|
|
1567
|
+
// ../maestro-sdk/src/shared-commands/process.ts
|
|
1568
|
+
var SEARCHABLE_TAG = "Searchable";
|
|
1569
|
+
var parseBooleanFlag = (value) => {
|
|
1570
|
+
if (value === "true")
|
|
1571
|
+
return true;
|
|
1572
|
+
if (value === "false")
|
|
1573
|
+
return false;
|
|
1574
|
+
throw new InvalidArgumentError(`Expected 'true' or 'false', got '${value}'.`);
|
|
1575
|
+
};
|
|
1576
|
+
var collectValue = (value, previous) => [
|
|
1577
|
+
...previous,
|
|
1578
|
+
value
|
|
1579
|
+
];
|
|
1580
|
+
var parseTagList = (csv) => csv === undefined ? [] : csv.split(",").map((tag) => tag.trim()).filter((tag) => tag.length > 0);
|
|
1581
|
+
var applyFriendlyVariableTags = (variableTags, flags) => {
|
|
1582
|
+
const elements = variableTags.elements ?? {};
|
|
1583
|
+
const allOutputs = Object.entries(elements).flatMap(([elementId, el]) => (el.outputs ?? []).map((output) => ({ elementId, output })));
|
|
1584
|
+
const available = allOutputs.map((o) => `${o.output.name} (element ${o.elementId})`).join(", ");
|
|
1585
|
+
let targets;
|
|
1586
|
+
if (flags.all) {
|
|
1587
|
+
if (allOutputs.length === 0) {
|
|
1588
|
+
throw new Error("This process has no taggable variables.");
|
|
1589
|
+
}
|
|
1590
|
+
targets = allOutputs;
|
|
1591
|
+
} else {
|
|
1592
|
+
const seen = new Set;
|
|
1593
|
+
targets = [];
|
|
1594
|
+
for (const name of flags.variable ?? []) {
|
|
1595
|
+
const matches = allOutputs.filter((o) => o.output.name === name && (flags.elementId === undefined || o.elementId === flags.elementId));
|
|
1596
|
+
if (matches.length === 0) {
|
|
1597
|
+
throw new Error(available ? `No variable matched "${name}"${flags.elementId ? ` in element ${flags.elementId}` : ""}. Available: ${available}.` : "This process has no taggable variables.");
|
|
1598
|
+
}
|
|
1599
|
+
if (flags.elementId === undefined && new Set(matches.map((m) => m.elementId)).size > 1) {
|
|
1600
|
+
const where = matches.map((m) => m.elementId).join(", ");
|
|
1601
|
+
throw new Error(`Variable "${name}" exists in multiple elements (${where}). Pass --element-id to disambiguate (one --variable at a time), or --all to tag every occurrence.`);
|
|
1602
|
+
}
|
|
1603
|
+
for (const m of matches) {
|
|
1604
|
+
if (!seen.has(m.output)) {
|
|
1605
|
+
seen.add(m.output);
|
|
1606
|
+
targets.push(m);
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
const replaceTags = flags.tags !== undefined ? parseTagList(flags.tags) : undefined;
|
|
1612
|
+
const addTags = parseTagList(flags.addTags);
|
|
1613
|
+
const removeSet = new Set(parseTagList(flags.removeTags));
|
|
1614
|
+
return targets.map(({ elementId, output }) => {
|
|
1615
|
+
const next = replaceTags !== undefined ? [...new Set(replaceTags)] : [...new Set([...output.tags ?? [], ...addTags])].filter((tag) => !removeSet.has(tag));
|
|
1616
|
+
output.tags = next;
|
|
1617
|
+
return { elementId, name: output.name, tags: next };
|
|
1618
|
+
});
|
|
1619
|
+
};
|
|
1620
|
+
var buildSettingsPath = (processKey) => `/processes/${encodeURIComponent(processKey)}/settings`;
|
|
1621
|
+
var validateFriendlyTagFlags = (options) => {
|
|
1622
|
+
const variableCount = options.variable.length;
|
|
1623
|
+
if (variableCount > 0 && options.all) {
|
|
1624
|
+
return "Use either --variable or --all, not both.";
|
|
1625
|
+
}
|
|
1626
|
+
if (variableCount === 0 && !options.all) {
|
|
1627
|
+
return "Specify the target with --variable <name> (repeatable, plus optional --element-id) or --all.";
|
|
1628
|
+
}
|
|
1629
|
+
if (variableCount > 1 && options.elementId !== undefined) {
|
|
1630
|
+
return "--element-id only works with a single --variable; pass one --variable, or drop --element-id.";
|
|
1631
|
+
}
|
|
1632
|
+
const hasSearchable = options.searchable !== undefined;
|
|
1633
|
+
const hasReplace = options.tags !== undefined;
|
|
1634
|
+
const hasIncremental = options.addTags !== undefined || options.removeTags !== undefined;
|
|
1635
|
+
if (hasSearchable && (hasReplace || hasIncremental)) {
|
|
1636
|
+
return "Use --searchable <true|false>, or the low-level --tags/--add-tags/--remove-tags flags — not both.";
|
|
1637
|
+
}
|
|
1638
|
+
if (!hasSearchable && !hasReplace && !hasIncremental) {
|
|
1639
|
+
return "Specify --searchable <true|false> to mark the variable searchable, or --tags/--add-tags/--remove-tags for other tags.";
|
|
1640
|
+
}
|
|
1641
|
+
if (hasReplace && hasIncremental) {
|
|
1642
|
+
return "Use --tags to replace tags, or --add-tags/--remove-tags to adjust them — not both.";
|
|
1643
|
+
}
|
|
1644
|
+
return null;
|
|
1645
|
+
};
|
|
1646
|
+
var resolveTagFlags = (options) => {
|
|
1647
|
+
if (options.searchable === undefined)
|
|
1648
|
+
return options;
|
|
1649
|
+
return {
|
|
1650
|
+
variable: options.variable,
|
|
1651
|
+
elementId: options.elementId,
|
|
1652
|
+
all: options.all,
|
|
1653
|
+
addTags: options.searchable ? SEARCHABLE_TAG : undefined,
|
|
1654
|
+
removeTags: options.searchable ? undefined : SEARCHABLE_TAG
|
|
1655
|
+
};
|
|
1656
|
+
};
|
|
1657
|
+
var setVariableTagsFromPayload = async (processKey, options) => {
|
|
1658
|
+
const [fileError, variableTags] = await catchError(resolveJsonInput({ inline: options.inputs, allowStdin: true }));
|
|
1659
|
+
if (fileError) {
|
|
1660
|
+
OutputFormatter.error({
|
|
1661
|
+
Result: RESULTS.Failure,
|
|
1662
|
+
Message: "Error reading variable tags input",
|
|
1663
|
+
Instructions: fileError.message
|
|
1664
|
+
});
|
|
1665
|
+
processContext.exit(1);
|
|
1666
|
+
return;
|
|
1667
|
+
}
|
|
1668
|
+
if (variableTags === undefined) {
|
|
1669
|
+
OutputFormatter.error({
|
|
1670
|
+
Result: RESULTS.Failure,
|
|
1671
|
+
Message: "Missing variable tags payload",
|
|
1672
|
+
Instructions: "Provide --inputs <json|@file>, pipe JSON via stdin, or use the --variable/--all flags."
|
|
1673
|
+
});
|
|
1674
|
+
processContext.exit(1);
|
|
1675
|
+
return;
|
|
1676
|
+
}
|
|
1677
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1678
|
+
const currentSettings = await withPimsCall((config) => pimsGet(config, buildSettingsPath(processKey), reqOptions), "Error reading current process settings");
|
|
1679
|
+
if (!currentSettings)
|
|
1680
|
+
return;
|
|
1681
|
+
const merged = { ...currentSettings, variableTags };
|
|
1682
|
+
const result = await withPimsCall((config) => pimsPut(config, buildSettingsPath(processKey), merged, reqOptions), "Error updating variable tags");
|
|
1683
|
+
if (!result)
|
|
1684
|
+
return;
|
|
1685
|
+
OutputFormatter.success({
|
|
1686
|
+
Result: RESULTS.Success,
|
|
1687
|
+
Code: "ProcessVariableTagsSet",
|
|
1688
|
+
Data: result
|
|
1689
|
+
});
|
|
1690
|
+
};
|
|
1691
|
+
var setVariableTagsFromFlags = async (processKey, options) => {
|
|
1692
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1693
|
+
const currentSettings = await withPimsCall((config) => pimsGet(config, buildSettingsPath(processKey), reqOptions), "Error reading current process settings");
|
|
1694
|
+
if (!currentSettings)
|
|
1695
|
+
return;
|
|
1696
|
+
const variableTags = currentSettings.variableTags ?? {
|
|
1697
|
+
elements: {},
|
|
1698
|
+
sourcePackageVersion: "",
|
|
1699
|
+
lastUpdateTimeUtc: ""
|
|
1700
|
+
};
|
|
1701
|
+
const [mutateError, updated] = catchError(() => applyFriendlyVariableTags(variableTags, resolveTagFlags(options)));
|
|
1702
|
+
if (mutateError) {
|
|
1703
|
+
OutputFormatter.error({
|
|
1704
|
+
Result: RESULTS.Failure,
|
|
1705
|
+
Message: "Error updating variable tags",
|
|
1706
|
+
Instructions: mutateError.message
|
|
1707
|
+
});
|
|
1708
|
+
processContext.exit(1);
|
|
1709
|
+
return;
|
|
1710
|
+
}
|
|
1711
|
+
const merged = { ...currentSettings, variableTags };
|
|
1712
|
+
const result = await withPimsCall((config) => pimsPut(config, buildSettingsPath(processKey), merged, reqOptions), "Error updating variable tags");
|
|
1713
|
+
if (!result)
|
|
1714
|
+
return;
|
|
1715
|
+
OutputFormatter.success({
|
|
1716
|
+
Result: RESULTS.Success,
|
|
1717
|
+
Code: "ProcessVariableTagsSet",
|
|
1718
|
+
Data: { updated, variableTags }
|
|
1719
|
+
});
|
|
1720
|
+
};
|
|
1721
|
+
var registerSharedProcessCommands = (processCmd, config) => {
|
|
1722
|
+
const { toolLabel } = config;
|
|
1723
|
+
const settingsCmd = processCmd.command("settings").description(`Manage ${toolLabel} process settings`);
|
|
1724
|
+
settingsCmd.command("get").description(`Get settings for a ${toolLabel} process`).argument("<process-key>", "Process definition key").requiredOption("-f, --folder-key <key>", "Folder key (GUID)").trackedAction(processContext, async (processKey, options) => {
|
|
1725
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1726
|
+
const result = await withPimsCall((config2) => pimsGet(config2, `/processes/${encodeURIComponent(processKey)}/settings`, reqOptions), "Error getting process settings", { resource: "process", id: processKey });
|
|
1727
|
+
if (!result)
|
|
1728
|
+
return;
|
|
1729
|
+
OutputFormatter.success({
|
|
1730
|
+
Result: RESULTS.Success,
|
|
1731
|
+
Code: "ProcessSettingsGet",
|
|
1732
|
+
Data: result
|
|
1733
|
+
});
|
|
1734
|
+
});
|
|
1735
|
+
settingsCmd.command("set").description(`Update settings for a ${toolLabel} process`).argument("<process-key>", "Process definition key").requiredOption("-f, --folder-key <key>", "Folder key (GUID)").option("--inputs <value>", "Settings payload as JSON string, @file path, or piped via stdin").trackedAction(processContext, async (processKey, options) => {
|
|
1736
|
+
const [fileError, body] = await catchError(resolveJsonInput({
|
|
1737
|
+
inline: options.inputs,
|
|
1738
|
+
allowStdin: true
|
|
1739
|
+
}));
|
|
1740
|
+
if (fileError) {
|
|
1741
|
+
OutputFormatter.error({
|
|
1742
|
+
Result: RESULTS.Failure,
|
|
1743
|
+
Message: "Error reading settings input",
|
|
1744
|
+
Instructions: fileError.message
|
|
1745
|
+
});
|
|
1746
|
+
processContext.exit(1);
|
|
1747
|
+
return;
|
|
1748
|
+
}
|
|
1749
|
+
if (body === undefined) {
|
|
1750
|
+
OutputFormatter.error({
|
|
1751
|
+
Result: RESULTS.Failure,
|
|
1752
|
+
Message: "Missing settings payload",
|
|
1753
|
+
Instructions: "Provide --inputs <json|@file> or pipe JSON via stdin."
|
|
1754
|
+
});
|
|
1755
|
+
processContext.exit(1);
|
|
1756
|
+
return;
|
|
1757
|
+
}
|
|
1758
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1759
|
+
const result = await withPimsCall((config2) => pimsPut(config2, `/processes/${encodeURIComponent(processKey)}/settings`, body, reqOptions), "Error updating process settings");
|
|
1760
|
+
if (!result)
|
|
1761
|
+
return;
|
|
1762
|
+
OutputFormatter.success({
|
|
1763
|
+
Result: RESULTS.Success,
|
|
1764
|
+
Code: "ProcessSettingsSet",
|
|
1765
|
+
Data: result
|
|
1766
|
+
});
|
|
1767
|
+
});
|
|
1768
|
+
const variableTagsCmd = processCmd.command("variable-tags").description(`Manage ${toolLabel} process variable tags`);
|
|
1769
|
+
variableTagsCmd.command("get").description(`Get variable tags for a ${toolLabel} process`).argument("<process-key>", "Process definition key").requiredOption("-f, --folder-key <key>", "Folder key (GUID)").trackedAction(processContext, async (processKey, options) => {
|
|
1770
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1771
|
+
const result = await withPimsCall((config2) => pimsGet(config2, `/processes/${encodeURIComponent(processKey)}/settings`, reqOptions), "Error getting variable tags", { resource: "process", id: processKey });
|
|
1772
|
+
if (!result)
|
|
1773
|
+
return;
|
|
1774
|
+
OutputFormatter.success({
|
|
1775
|
+
Result: RESULTS.Success,
|
|
1776
|
+
Code: "ProcessVariableTagsGet",
|
|
1777
|
+
Data: result.variableTags ?? {}
|
|
1778
|
+
});
|
|
1779
|
+
});
|
|
1780
|
+
variableTagsCmd.command("set").description(`Update variable tags for a ${toolLabel} process`).argument("<process-key>", "Process definition key").requiredOption("-f, --folder-key <key>", "Folder key (GUID)").option("--variable <name>", "Name of a variable (output) to tag. Repeatable — pass it multiple times to tag several variables in one call.", collectValue, []).option("--element-id <id>", "Element that owns the variable (disambiguates when the same name appears in multiple elements). Only valid with a single --variable.").option("--all", "Apply the change to every taggable variable").option("--searchable <boolean>", "Mark the variable searchable for instance filtering ('true' or 'false')", parseBooleanFlag).option("--tags <list>", "Advanced: comma-separated tags to set, replacing the variable's current tags (empty value clears them)").option("--add-tags <list>", "Comma-separated tags to add to the variable's current tags").option("--remove-tags <list>", "Comma-separated tags to remove from the variable's current tags").option("--inputs <value>", "Full variable tags payload as JSON string, @file path, or piped via stdin").trackedAction(processContext, async (processKey, options) => {
|
|
1781
|
+
const friendlyRequested = options.variable.length > 0 || options.elementId !== undefined || options.all === true || options.searchable !== undefined || options.tags !== undefined || options.addTags !== undefined || options.removeTags !== undefined;
|
|
1782
|
+
if (options.inputs !== undefined && friendlyRequested) {
|
|
1783
|
+
OutputFormatter.error({
|
|
1784
|
+
Result: RESULTS.Failure,
|
|
1785
|
+
Message: "Error updating variable tags",
|
|
1786
|
+
Instructions: "Provide either --inputs (full JSON payload) or the --searchable/--variable/--all flags, not both."
|
|
1787
|
+
});
|
|
1788
|
+
processContext.exit(1);
|
|
1789
|
+
return;
|
|
1790
|
+
}
|
|
1791
|
+
if (friendlyRequested) {
|
|
1792
|
+
const validationError = validateFriendlyTagFlags(options);
|
|
1793
|
+
if (validationError) {
|
|
1794
|
+
OutputFormatter.error({
|
|
1795
|
+
Result: RESULTS.Failure,
|
|
1796
|
+
Message: "Error updating variable tags",
|
|
1797
|
+
Instructions: validationError
|
|
1798
|
+
});
|
|
1799
|
+
processContext.exit(1);
|
|
1800
|
+
return;
|
|
1801
|
+
}
|
|
1802
|
+
await setVariableTagsFromFlags(processKey, options);
|
|
1803
|
+
return;
|
|
1804
|
+
}
|
|
1805
|
+
await setVariableTagsFromPayload(processKey, options);
|
|
1806
|
+
});
|
|
1807
|
+
};
|
|
1808
|
+
|
|
1809
|
+
// ../maestro-sdk/src/shared-commands/processes.ts
|
|
1810
|
+
function findProcessSummary(summaries, processKey) {
|
|
1811
|
+
return summaries.find((summary) => summary.processKey === processKey) ?? null;
|
|
1812
|
+
}
|
|
1813
|
+
var registerSharedProcessesCommands = (program, config) => {
|
|
1814
|
+
const { toolLabel, processType } = config;
|
|
1815
|
+
const processes = program.command("processes").description(`Manage ${toolLabel} process summaries`);
|
|
1816
|
+
processes.command("list").description(`List all ${toolLabel} process summaries`).option("--folder-key <key>", "Folder key").option("-l, --limit <number>", "Number of items to return (1-10000)", parseLimit).option("--offset <number>", "Number of items to skip (0-1000000)", parseOffset, 0).option("--status <status>", "Filter by process status").trackedAction(processContext, async (options) => {
|
|
1817
|
+
const query = buildQueryString({
|
|
1818
|
+
processType,
|
|
1819
|
+
status: options.status,
|
|
1820
|
+
$top: options.limit,
|
|
1821
|
+
$skip: options.offset !== 0 ? options.offset : undefined
|
|
1822
|
+
});
|
|
1823
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1824
|
+
const result = await withPimsCall((config2) => pimsGet(config2, `/processes/summary${query}`, reqOptions), "Error listing processes");
|
|
1825
|
+
if (!result)
|
|
1826
|
+
return;
|
|
1827
|
+
OutputFormatter.success({
|
|
1828
|
+
Result: RESULTS.Success,
|
|
1829
|
+
Code: "ProcessList",
|
|
1830
|
+
Data: result
|
|
1831
|
+
});
|
|
1832
|
+
});
|
|
1833
|
+
processes.command("incidents").description(`Get incidents for a specific ${toolLabel} process`).argument("<process-key>", "Process definition key").requiredOption("--folder-key <key>", "Folder key").trackedAction(processContext, async (processKey, options) => {
|
|
1834
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1835
|
+
const result = await withPimsCall((config2) => pimsGet(config2, `/incidents/process/${encodeURIComponent(processKey)}`, reqOptions), "Error getting process incidents", { resource: "process", id: processKey });
|
|
1836
|
+
if (!result)
|
|
1837
|
+
return;
|
|
1838
|
+
OutputFormatter.success({
|
|
1839
|
+
Result: RESULTS.Success,
|
|
1840
|
+
Code: "ProcessIncidents",
|
|
1841
|
+
Data: result
|
|
1842
|
+
});
|
|
1843
|
+
});
|
|
1844
|
+
processes.command("diagnose").description(`Correlate ${toolLabel} process summary, incidents, and error codes`).argument("<process-key>", "Process definition key").requiredOption("--folder-key <key>", "Folder key").trackedAction(processContext, async (processKey, options) => {
|
|
1845
|
+
const result = await withPimsCall(async (config2) => {
|
|
1846
|
+
const query = processType ? buildQueryString({ processType }) : "";
|
|
1847
|
+
const summaries = await pimsGet(config2, `/processes/summary${query}`);
|
|
1848
|
+
const incidents = await pimsGet(config2, `/incidents/process/${encodeURIComponent(processKey)}`, { folderKey: options.folderKey });
|
|
1849
|
+
const errorCodes = await pimsGet(config2, `/incidents/process/${encodeURIComponent(processKey)}/error-codes`, { folderKey: options.folderKey });
|
|
1850
|
+
return {
|
|
1851
|
+
summary: findProcessSummary(summaries, processKey),
|
|
1852
|
+
incidents,
|
|
1853
|
+
errorCodes: errorCodes.errorCodes || []
|
|
1854
|
+
};
|
|
1855
|
+
}, "Error diagnosing process");
|
|
1856
|
+
if (!result)
|
|
1857
|
+
return;
|
|
1858
|
+
OutputFormatter.success({
|
|
1859
|
+
Result: RESULTS.Success,
|
|
1860
|
+
Code: "ProcessDiagnostics",
|
|
1861
|
+
Data: {
|
|
1862
|
+
ProcessKey: processKey,
|
|
1863
|
+
FolderKey: options.folderKey,
|
|
1864
|
+
Summary: result.summary,
|
|
1865
|
+
FaultedCount: result.summary?.faultedCount ?? null,
|
|
1866
|
+
RunningCount: result.summary?.runningCount ?? null,
|
|
1867
|
+
Incidents: result.incidents,
|
|
1868
|
+
IncidentCount: result.incidents.length,
|
|
1869
|
+
ErrorCodes: result.errorCodes,
|
|
1870
|
+
ErrorCodeCount: result.errorCodes.length
|
|
1871
|
+
}
|
|
1872
|
+
});
|
|
1873
|
+
});
|
|
1874
|
+
processes.command("error-codes").description(`Get unique error codes for a specific ${toolLabel} process`).argument("<process-key>", "Process definition key").requiredOption("--folder-key <key>", "Folder key").trackedAction(processContext, async (processKey, options) => {
|
|
1875
|
+
const reqOptions = { folderKey: options.folderKey };
|
|
1876
|
+
const result = await withPimsCall((config2) => pimsGet(config2, `/incidents/process/${encodeURIComponent(processKey)}/error-codes`, reqOptions), "Error getting process error codes", { resource: "process", id: processKey });
|
|
1877
|
+
if (!result)
|
|
1878
|
+
return;
|
|
1879
|
+
OutputFormatter.success({
|
|
1880
|
+
Result: RESULTS.Success,
|
|
1881
|
+
Code: "ProcessIncidentErrorCodes",
|
|
1882
|
+
Data: result.errorCodes || []
|
|
1883
|
+
});
|
|
1884
|
+
});
|
|
1885
|
+
};
|
|
1886
|
+
|
|
1887
|
+
export { registerRegistryCommand, registerSharedDebugInstanceCommands, registerSharedIncidentCommands, registerSharedInstanceCommands, registerSharedProcessCommands, registerSharedProcessesCommands };
|
|
1888
|
+
|
|
1889
|
+
//# debugId=74DC721665AE8F4764756E2164756E21
|