@uipath/maestro-builder-sdk 6.19.0 → 6.20.1
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/api-index.md +107 -107
- package/dist/api-members.md +358 -356
- package/dist/check.js +181 -45
- package/dist/cli/commands/flow.js +3 -0
- package/dist/compile-cli.js +51 -0
- package/dist/core/actions.d.ts +13 -5
- package/dist/core/actions.js +1 -1
- package/dist/core/binding-identity.d.ts +22 -0
- package/dist/core/binding-identity.js +28 -0
- package/dist/core/context-index.d.ts +34 -0
- package/dist/core/context-index.js +38 -0
- package/dist/core/definitionless-node-types.d.ts +16 -0
- package/dist/core/definitionless-node-types.js +16 -0
- package/dist/core/form-field-type.d.ts +33 -0
- package/dist/core/form-field-type.js +30 -0
- package/dist/core/hitl-routing.d.ts +8 -0
- package/dist/core/hitl-routing.js +17 -1
- package/dist/core/process-resource-sort-order.d.ts +40 -0
- package/dist/core/process-resource-sort-order.js +44 -0
- package/dist/core/wire-expr.d.ts +27 -0
- package/dist/core/wire-expr.js +34 -0
- package/dist/decompile-cli.js +11 -1
- package/dist/decompile.d.ts +8 -3
- package/dist/decompile.js +680 -104
- package/dist/flow-expr-check.js +1 -1
- package/dist/flow-sdk.d.ts +33 -1
- package/dist/flow-sdk.js +21 -2
- package/dist/flow-step-tree.js +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/merge-cli.js +25 -8
- package/dist/merge-roundtrip.d.ts +81 -0
- package/dist/merge-roundtrip.js +404 -0
- package/dist/merge.d.ts +35 -6
- package/dist/merge.js +124 -24
- package/dist/node-placement.d.ts +93 -0
- package/dist/node-placement.js +163 -0
- package/dist/nodes/transform/flow/node-type.js +2 -1
- package/dist/registry/uip/pipeline-front-door.js +5 -3
- package/dist/serialize.js +112 -61
- package/package.json +2 -2
package/dist/serialize.js
CHANGED
|
@@ -10,9 +10,10 @@ import { readFileSync } from 'node:fs';
|
|
|
10
10
|
import { createHash } from 'node:crypto';
|
|
11
11
|
import { fileURLToPath } from 'node:url';
|
|
12
12
|
import { dirname, join } from 'node:path';
|
|
13
|
-
import { BUNDLED_DEFINITIONS } from './flow-definitions.js';
|
|
13
|
+
import { BUNDLED_DEFINITIONS, bundledVersions } from './flow-definitions.js';
|
|
14
14
|
import { Expr, toExpr, SCHEDULE_PRESETS, parseIxpProjectType, flatNameOf, flatNameSegmentsOf } from './flow-sdk.js';
|
|
15
15
|
import { FlowAction, FlowTrigger } from './core/node-classes.js';
|
|
16
|
+
import { contextIndexType } from './core/context-index.js';
|
|
16
17
|
import { connectorRawNodeRefusal } from './core/connector-raw-node.js';
|
|
17
18
|
import { rawNodeInputProblem, registeredRawType } from './raw-node-advice.js';
|
|
18
19
|
import { planContributionBindings } from './core/contribution-bindings.js';
|
|
@@ -24,7 +25,9 @@ import { connectionConnectors } from './bindings-v2.js';
|
|
|
24
25
|
import { BindingRefusal, GUID_RE, bindingLabelRefusal, bindingMissingMessage, missingBindingLabels } from './core/binding-messages.js';
|
|
25
26
|
import { ByoaRefusal, byoaUnverified } from './core/byoa.js';
|
|
26
27
|
import { genericEventObjectRefusal } from './core/event-checks.js';
|
|
27
|
-
import { OUTCOME_HANDLE_NODE_TYPES, assertHitlExitInvariant, hitlExitModel, hitlExitViolation, outcomeSlug } from './core/hitl-routing.js';
|
|
28
|
+
import { OUTCOME_HANDLE_NODE_TYPES, assertHitlExitInvariant, hitlExitModel, hitlExitViolation, outcomeIdOf, outcomeSlug } from './core/hitl-routing.js';
|
|
29
|
+
import { STICKY_NOTE_TYPE, STICKY_NOTE_TYPE_VERSION } from './core/definitionless-node-types.js';
|
|
30
|
+
import { placeholderPosition } from './node-placement.js';
|
|
28
31
|
import { declaredExits, hasExits } from './core/step-ports.js';
|
|
29
32
|
import { stopsAtEnd } from './flow-step-tree.js';
|
|
30
33
|
import { assertNodeEnvelope } from './core/node-envelope.js';
|
|
@@ -55,6 +58,7 @@ import { planFlowGlobals, planSharedInputs, sharedInputRoots } from './flow-vari
|
|
|
55
58
|
import { prepareCommand } from './core/cli-spelling.js';
|
|
56
59
|
import { QUEUE_ITEM_RECORD_SCHEMA } from './core/queue-record.js';
|
|
57
60
|
import { AGENTIC_PROCESS_FORMS } from './core/agentic-process-forms.js';
|
|
61
|
+
import { resourceNodeSortOrder } from './core/process-resource-sort-order.js';
|
|
58
62
|
import { types } from './core/expr.js';
|
|
59
63
|
import { ownEntry } from './core/own-entry.js';
|
|
60
64
|
import { jsonClone } from './core/json-file.js';
|
|
@@ -206,6 +210,9 @@ function processResourceLocation(spec) {
|
|
|
206
210
|
* `icon: 'rpa'`, the `bpmn:ServiceTask` / `Orchestrator.StartJob` / `v2` model,
|
|
207
211
|
* `section: 'Published'` (42/45), `debug.runtime: 'bpmnEngine'`, and the
|
|
208
212
|
* `<bindings.name>` / `<bindings.folderPath>` context placeholders.
|
|
213
|
+
* `sortOrder` is not one of those constants any more: flow-core derives it from
|
|
214
|
+
* the category, and renumbered after 07-29, so it comes from
|
|
215
|
+
* `resourceNodeSortOrder` (#1045).
|
|
209
216
|
*
|
|
210
217
|
* Two fields are derived from the author's call rather than from the tenant, and
|
|
211
218
|
* that limit is real:
|
|
@@ -236,7 +243,7 @@ function rpaWorkflowDef(spec) {
|
|
|
236
243
|
runtimeConstraints: { exclude: ['api-function'] },
|
|
237
244
|
description: loc.description,
|
|
238
245
|
tags: loc.tags,
|
|
239
|
-
sortOrder:
|
|
246
|
+
sortOrder: resourceNodeSortOrder('rpa-workflow'),
|
|
240
247
|
supportsErrorHandling: true,
|
|
241
248
|
display: { label: spec.name, icon: 'rpa' },
|
|
242
249
|
handleConfiguration: [
|
|
@@ -316,7 +323,7 @@ const API_WORKFLOW_PREFIX = 'uipath.core.api-workflow.';
|
|
|
316
323
|
* AGREE on, not invented: 42 `uipath.core.api-workflow.*` instances across 42
|
|
317
324
|
* dated `skill-flow-api-workflow` artifacts (2026-05-18 → 07-29), cross-checked
|
|
318
325
|
* against `registry get` for today's workflow. Every one is unanimous —
|
|
319
|
-
* `category: 'api-workflow'`, `sortOrder: 510`, `supportsErrorHandling`,
|
|
326
|
+
* `category: 'api-workflow'`, `sortOrder: 510` (now 640, see `resourceNodeSortOrder`, #1045), `supportsErrorHandling`,
|
|
320
327
|
* `icon: 'api'`, the `bpmn:ServiceTask` / `Orchestrator.ExecuteApiWorkflowAsync` /
|
|
321
328
|
* `v2` model, `section: 'Published'` (37/42; the 5 without are the in-solution
|
|
322
329
|
* shape, a bare-GUID resourceKey — rpa's 3/45 split again), `resourceSubType:
|
|
@@ -354,7 +361,7 @@ function apiWorkflowDef(spec) {
|
|
|
354
361
|
runtimeConstraints: { exclude: ['api-function'] },
|
|
355
362
|
description: `(${spec.folderPath})`,
|
|
356
363
|
tags: [],
|
|
357
|
-
sortOrder:
|
|
364
|
+
sortOrder: resourceNodeSortOrder('api-workflow'),
|
|
358
365
|
supportsErrorHandling: true,
|
|
359
366
|
display: { label: spec.name, icon: 'api' },
|
|
360
367
|
handleConfiguration: [
|
|
@@ -435,7 +442,7 @@ function publishedFunctionDef(spec) {
|
|
|
435
442
|
category: 'function',
|
|
436
443
|
description: `(${spec.folderPath})`,
|
|
437
444
|
tags: [],
|
|
438
|
-
sortOrder:
|
|
445
|
+
sortOrder: resourceNodeSortOrder('function'),
|
|
439
446
|
supportsErrorHandling: true,
|
|
440
447
|
display: { label: spec.name, icon: 'function' },
|
|
441
448
|
handleConfiguration: [
|
|
@@ -513,7 +520,8 @@ function publishedFunctionDef(spec) {
|
|
|
513
520
|
*
|
|
514
521
|
* - `uip maestro flow registry get uipath.core.agentic-process.<key>` for ALL
|
|
515
522
|
* THREE agentic processes on the tenant (2026-07-29): `category:
|
|
516
|
-
* 'agentic-process'`, `sortOrder: 507
|
|
523
|
+
* 'agentic-process'`, `sortOrder: 507` (now 610 for bpmn, 600 flow, 620 case:
|
|
524
|
+
* `resourceNodeSortOrder`, #1045), `supportsErrorHandling`, `icon:
|
|
517
525
|
* 'agentic-process'`, `version: '1.0.0'`, the `bpmn:ServiceTask` /
|
|
518
526
|
* `Orchestrator.StartAgenticProcess` / `v2` model, `section: 'Published'`,
|
|
519
527
|
* `resourceSubType: 'ProcessOrchestration'`, `orchestratorType:
|
|
@@ -556,7 +564,7 @@ function agenticProcessDef(spec) {
|
|
|
556
564
|
runtimeConstraints: { exclude: ['api-function'] },
|
|
557
565
|
description: loc.description,
|
|
558
566
|
tags: loc.tags,
|
|
559
|
-
sortOrder:
|
|
567
|
+
sortOrder: resourceNodeSortOrder(form.category),
|
|
560
568
|
supportsErrorHandling: true,
|
|
561
569
|
display: { label: spec.name, icon: form.icon },
|
|
562
570
|
handleConfiguration: [
|
|
@@ -637,7 +645,8 @@ const INLINE_AGENT_TYPE = 'uipath.agent.autonomous';
|
|
|
637
645
|
* checkable rather than asserted:
|
|
638
646
|
*
|
|
639
647
|
* - `uip maestro flow registry get uipath.core.agent.<key>` for ALL NINE agents on
|
|
640
|
-
* the tenant (2026-07-29): `category: 'agent'`, `sortOrder: 505
|
|
648
|
+
* the tenant (2026-07-29): `category: 'agent'`, `sortOrder: 505` (510 since flow-core's
|
|
649
|
+
* renumber: the 54 runs from 09-01 below carry 510; `resourceNodeSortOrder`, #1045),
|
|
641
650
|
* `supportsErrorHandling: true`, `version: '1.0.0'`, the `bpmn:ServiceTask` /
|
|
642
651
|
* `Orchestrator.StartAgentJob` / `v2` model, `section: 'Published'`,
|
|
643
652
|
* `resourceSubType: 'Agent'`, `orchestratorType: 'agent'`,
|
|
@@ -691,7 +700,7 @@ function agentDef(spec) {
|
|
|
691
700
|
runtimeConstraints: { exclude: ['api-function'] },
|
|
692
701
|
description: loc.description,
|
|
693
702
|
tags: loc.tags,
|
|
694
|
-
sortOrder:
|
|
703
|
+
sortOrder: resourceNodeSortOrder('agent'),
|
|
695
704
|
supportsErrorHandling: true,
|
|
696
705
|
display: {
|
|
697
706
|
label: spec.name,
|
|
@@ -836,21 +845,6 @@ function contextIndexDef(spec) {
|
|
|
836
845
|
},
|
|
837
846
|
};
|
|
838
847
|
}
|
|
839
|
-
/**
|
|
840
|
-
* The node type for a context index: `…context.index.<slug>.<uuid>`.
|
|
841
|
-
*
|
|
842
|
-
* The slug is the index's display name lower-cased with every run of
|
|
843
|
-
* non-alphanumerics collapsed to a single `-`. Measured against the platform's own
|
|
844
|
-
* type for "Billing Dispute SOP Index" → `billing-dispute-sop-index`, and pinned
|
|
845
|
-
* by a test — because a derived identifier that disagrees with the registry's is a
|
|
846
|
-
* node type the tenant has never heard of.
|
|
847
|
-
*/
|
|
848
|
-
function contextIndexSlug(name) {
|
|
849
|
-
return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
|
|
850
|
-
}
|
|
851
|
-
function contextIndexType(spec) {
|
|
852
|
-
return `uipath.agent.resource.context.index.${contextIndexSlug(spec.name)}.${spec.id}`;
|
|
853
|
-
}
|
|
854
848
|
/**
|
|
855
849
|
* Render an index's retrieval query into the platform's MODE-TAGGED object.
|
|
856
850
|
*
|
|
@@ -2958,9 +2952,14 @@ function connectionResourceBindings(spec, existing) {
|
|
|
2958
2952
|
* create, or the author's `returns` for a create-and-wait. Without a schema a
|
|
2959
2953
|
* downstream read is unresolvable.
|
|
2960
2954
|
*/
|
|
2961
|
-
function queueItemDef(spec, stepName, ids) {
|
|
2955
|
+
function queueItemDef(spec, stepName, ids, version) {
|
|
2962
2956
|
const nodeType = spec.wait ? NODE_TYPE.queueCreateAndWait : NODE_TYPE.queueCreate;
|
|
2963
|
-
|
|
2957
|
+
// The template at the AUTHOR'S version, when the bundle has it. Starting from
|
|
2958
|
+
// the default and handing it to makeNode with the pin refused every other
|
|
2959
|
+
// bundled version — the bug #988 fixed for inline agents (#1128). An
|
|
2960
|
+
// unbundled pin falls back to the default, and makeNode's exact-version
|
|
2961
|
+
// refusal names what is bundled.
|
|
2962
|
+
const base = (version !== undefined ? DEFS[`${nodeType}@${version}`] : undefined) ?? defByType.get(nodeType);
|
|
2964
2963
|
if (!base)
|
|
2965
2964
|
throw new Error(`no bundled definition for "${nodeType}"`);
|
|
2966
2965
|
const def = jsonClone(base);
|
|
@@ -3199,7 +3198,7 @@ function hitlInputs(inputs, nodeId, flowId, label, rename) {
|
|
|
3199
3198
|
const outcomes = (inputs?.outcomes ?? []).map((o, i) => {
|
|
3200
3199
|
const name = typeof o === 'string' ? o : o?.name;
|
|
3201
3200
|
const action = typeof o === 'string' ? 'Continue' : (o?.action ?? 'Continue');
|
|
3202
|
-
return { id:
|
|
3201
|
+
return { id: outcomeIdOf(o, i), name, type: 'string', isPrimary: i === 0, action };
|
|
3203
3202
|
});
|
|
3204
3203
|
const properties = {};
|
|
3205
3204
|
for (const f of inputs?.fields ?? []) {
|
|
@@ -3475,8 +3474,6 @@ const NO_RENAME = { nodeIds: new Map(), errorEnvelopes: new Map() };
|
|
|
3475
3474
|
const ERROR_ENVELOPE_VAR = {
|
|
3476
3475
|
[NODE_TYPE.httpV2]: 'output',
|
|
3477
3476
|
};
|
|
3478
|
-
/** The `typeVersion` Studio Web stamps on a sticky note. The type has no manifest to take it from. */
|
|
3479
|
-
const STICKY_NOTE_TYPE_VERSION = '1.0.0';
|
|
3480
3477
|
/**
|
|
3481
3478
|
* Append the flow's `.stickyNotes()` as real `stickyNote` nodes.
|
|
3482
3479
|
*
|
|
@@ -3527,7 +3524,7 @@ function emitStickyNotes(built, scope, claimNoteId) {
|
|
|
3527
3524
|
// `flow validate`, manifest or not (#869).
|
|
3528
3525
|
scope.nodes.push({
|
|
3529
3526
|
id: emittedId,
|
|
3530
|
-
type:
|
|
3527
|
+
type: STICKY_NOTE_TYPE,
|
|
3531
3528
|
typeVersion: STICKY_NOTE_TYPE_VERSION,
|
|
3532
3529
|
ui: {
|
|
3533
3530
|
position: { x: note.x, y: note.y },
|
|
@@ -3849,11 +3846,6 @@ export function resolveContributionDefinition(ref, requestedVersion, where) {
|
|
|
3849
3846
|
}
|
|
3850
3847
|
throw new Error(`${where}: unknown DefinitionReference source "${ref.source}".`);
|
|
3851
3848
|
}
|
|
3852
|
-
/**
|
|
3853
|
-
* The forward port of a contribution-lowered node, derived from its
|
|
3854
|
-
* definition's handles: the source handle marked `isDefaultForType`, else the
|
|
3855
|
-
* first non-error source handle, else the conventional `output`.
|
|
3856
|
-
*/
|
|
3857
3849
|
/**
|
|
3858
3850
|
* Whether `def` declares `port` as a forward source handle: an exact id, or a
|
|
3859
3851
|
* templated one (`outcome-{item.id}` declares every `outcome-<slug>`). `error` is
|
|
@@ -3873,10 +3865,17 @@ function declaresForwardPort(def, port) {
|
|
|
3873
3865
|
return port.length > head.length + tail.length && port.startsWith(head) && port.endsWith(tail);
|
|
3874
3866
|
});
|
|
3875
3867
|
}
|
|
3868
|
+
/**
|
|
3869
|
+
* Forward port: the first concrete source handle (`isDefaultForType` wins), else `output`;
|
|
3870
|
+
* `undefined` when every forward source handle is templated (`case-{item.id}`).
|
|
3871
|
+
*/
|
|
3876
3872
|
function contributionPort(def) {
|
|
3877
3873
|
const handles = (def?.handleConfiguration ?? []).flatMap((g) => g?.handles ?? []);
|
|
3878
3874
|
const sources = handles.filter((h) => h?.type === 'source' && h?.id !== 'error');
|
|
3879
|
-
|
|
3875
|
+
const concrete = sources.filter((h) => typeof h?.id === 'string' && !h.id.includes('{'));
|
|
3876
|
+
if (concrete.length === 0 && sources.length > 0)
|
|
3877
|
+
return undefined;
|
|
3878
|
+
return concrete.find((h) => h?.isDefaultForType)?.id ?? concrete[0]?.id ?? 'output';
|
|
3880
3879
|
}
|
|
3881
3880
|
/**
|
|
3882
3881
|
* Render a switch case value as a JS literal for the case expression.
|
|
@@ -4726,6 +4725,8 @@ export function serialize(built, opts = {}) {
|
|
|
4726
4725
|
* `.stepToRef` rejoins now do come through here, #938).
|
|
4727
4726
|
*/
|
|
4728
4727
|
const hitlNodes = new Map();
|
|
4728
|
+
/** Step name → node id of a step whose every forward exit is templated (see `contributionPort`). */
|
|
4729
|
+
const routerNodes = new Map();
|
|
4729
4730
|
/**
|
|
4730
4731
|
* Human tasks with an outcome whose path stops at an End while another
|
|
4731
4732
|
* outcome continues — read by `.parallel`, whose join would wait forever for
|
|
@@ -4757,8 +4758,16 @@ export function serialize(built, opts = {}) {
|
|
|
4757
4758
|
if (o.requestedVersion !== undefined && def?.version !== o.requestedVersion) {
|
|
4758
4759
|
const exact = o.def ? undefined : DEFS[`${type}@${o.requestedVersion}`];
|
|
4759
4760
|
if (!exact) {
|
|
4761
|
+
// Name every version the SDK could have resolved: every bundled
|
|
4762
|
+
// version of the type, else (a type built per resource, a connector)
|
|
4763
|
+
// the definition in hand. Naming only the default sent the reader
|
|
4764
|
+
// looking for a version that was shipped all along (#1128:
|
|
4765
|
+
// quick-form bundles 1.0 AND 1.1, and the message said 1.0).
|
|
4766
|
+
const bundled = bundledVersions(type);
|
|
4767
|
+
const resolvable = bundled.length > 0 ? bundled
|
|
4768
|
+
: [def?.version].filter((v) => typeof v === 'string');
|
|
4760
4769
|
throw new Error(`"${label ?? id}" requests ${type}@${o.requestedVersion}, but this SDK resolves only `
|
|
4761
|
-
+ `${type}@${
|
|
4770
|
+
+ `${type}@${resolvable.join(', ') || '<none>'}. Versions are exact — omit { version } to use `
|
|
4762
4771
|
+ `the pinned default, or request a version this SDK ships.`);
|
|
4763
4772
|
}
|
|
4764
4773
|
def = exact;
|
|
@@ -4771,7 +4780,7 @@ export function serialize(built, opts = {}) {
|
|
|
4771
4780
|
id,
|
|
4772
4781
|
type,
|
|
4773
4782
|
typeVersion: def?.version ?? '1.0.0',
|
|
4774
|
-
ui: { position:
|
|
4783
|
+
ui: { position: placeholderPosition(col, Boolean(o.parentId)), size: { width: 96, height: 96 }, collapsed: false },
|
|
4775
4784
|
display: { label: label ?? def?.display?.label ?? id, ...(def?.display?.icon ? { icon: def.display.icon } : {}) },
|
|
4776
4785
|
};
|
|
4777
4786
|
col++;
|
|
@@ -5075,7 +5084,14 @@ export function serialize(built, opts = {}) {
|
|
|
5075
5084
|
scope.nodes.push(node);
|
|
5076
5085
|
for (const t of o.tails)
|
|
5077
5086
|
addEdge(scope, t, id);
|
|
5078
|
-
|
|
5087
|
+
const port = contribution.port ?? contributionPort(def);
|
|
5088
|
+
if (port === undefined) {
|
|
5089
|
+
// Only templated exits: no main path leaves this node. Remember it so a
|
|
5090
|
+
// following `.stepToList` / side-exit `.stepToRef` can still attach.
|
|
5091
|
+
routerNodes.set(o.stepName, id);
|
|
5092
|
+
return [];
|
|
5093
|
+
}
|
|
5094
|
+
return [{ node: id, port }];
|
|
5079
5095
|
}
|
|
5080
5096
|
/**
|
|
5081
5097
|
* Lower a step whose kind is a registered node type (flow-node-registry.ts):
|
|
@@ -5413,6 +5429,13 @@ export function serialize(built, opts = {}) {
|
|
|
5413
5429
|
const contexts = s.context === undefined ? []
|
|
5414
5430
|
: Array.isArray(s.context) ? s.context : [s.context];
|
|
5415
5431
|
for (const cx of contexts) {
|
|
5432
|
+
// `check`'s AGENT_CONTEXT_NO_ID, again for `--no-check`: a blank id builds
|
|
5433
|
+
// the type `…context.index.<slug>.`, which no tenant serves, and nothing
|
|
5434
|
+
// after this point would say so.
|
|
5435
|
+
if (typeof cx?.id !== 'string' || !GUID_RE.test(cx.id)) {
|
|
5436
|
+
throw Object.assign(new Error(`inline agent "${step.name}": context index "${cx?.name ?? ''}" needs its index id (a GUID) as \`id\`; `
|
|
5437
|
+
+ `got ${JSON.stringify(cx?.id)}. \`uip solution resources list --kind Index --source remote --search "<name>"\` returns it as \`Key\`.`), { code: 'AGENT_CONTEXT_NO_ID' });
|
|
5438
|
+
}
|
|
5416
5439
|
const cdef = contextIndexDef({ name: cx.name, id: cx.id });
|
|
5417
5440
|
// `<step>Context`, deduped by `uid` for a second index on the same agent.
|
|
5418
5441
|
// Not slugged from the index NAME: an id is the author's handle on the node
|
|
@@ -5876,7 +5899,7 @@ export function serialize(built, opts = {}) {
|
|
|
5876
5899
|
const { ids, entries } = queueItemBindings(s, resourceBindings);
|
|
5877
5900
|
for (const b of entries)
|
|
5878
5901
|
resourceBindings.set(b.id, b);
|
|
5879
|
-
const def = queueItemDef(s, step.name, ids);
|
|
5902
|
+
const def = queueItemDef(s, step.name, ids, step.options?.version);
|
|
5880
5903
|
const id = stepUid(scope, step.name);
|
|
5881
5904
|
// The result is read as `$vars.<step>.output`, like every other family: the
|
|
5882
5905
|
// node's own output block maps the runtime `response` onto the variable
|
|
@@ -6359,8 +6382,13 @@ export function serialize(built, opts = {}) {
|
|
|
6359
6382
|
* from a non-default port is a side exit. Only the seed differs from an ordinary
|
|
6360
6383
|
* list — the same node, a different port.
|
|
6361
6384
|
*/
|
|
6362
|
-
function emitPortList(step, source, tails, scope, parentId,
|
|
6385
|
+
function emitPortList(step, source, tails, scope, parentId, loopExits) {
|
|
6363
6386
|
const handler = step.body;
|
|
6387
|
+
// A node whose exits are all templated hands on no tail; its port lists
|
|
6388
|
+
// leave from the node itself.
|
|
6389
|
+
const router = tails.length === 0 ? routerNodes.get(source) : undefined;
|
|
6390
|
+
if (router !== undefined)
|
|
6391
|
+
tails = [{ node: router, port: step.port }];
|
|
6364
6392
|
// `emitAction` returns one tail for every action kind — the node's own
|
|
6365
6393
|
// success port — except a fan-out human task, which returns one per outcome
|
|
6366
6394
|
// from the SAME node. Tails from two nodes mean a new action shape reached
|
|
@@ -6379,7 +6407,7 @@ export function serialize(built, opts = {}) {
|
|
|
6379
6407
|
refuseErrorEdgeWithoutPort(nodeId, source);
|
|
6380
6408
|
node.inputs = { ...(node.inputs ?? {}), errorHandlingEnabled: true };
|
|
6381
6409
|
}
|
|
6382
|
-
const handlerTails = emit(handler, [{ node: nodeId, port: step.port }], scope, parentId,
|
|
6410
|
+
const handlerTails = emit(handler, [{ node: nodeId, port: step.port }], scope, parentId, loopExits);
|
|
6383
6411
|
// A body that runs out of steps ends the run on an End of its own (no
|
|
6384
6412
|
// merge-back is inferred). That End maps the outputs like any other, so a
|
|
6385
6413
|
// body that set them with `{ updates }` still answers (#742).
|
|
@@ -6387,13 +6415,13 @@ export function serialize(built, opts = {}) {
|
|
|
6387
6415
|
const endId = uid(scope, `${source}${step.port === 'error' ? 'Error' : step.port.charAt(0).toUpperCase() + step.port.slice(1)}End`);
|
|
6388
6416
|
emitEnd(scope, endId, handlerTails, { parentId });
|
|
6389
6417
|
}
|
|
6390
|
-
return tails;
|
|
6418
|
+
return router !== undefined ? [] : tails;
|
|
6391
6419
|
}
|
|
6392
6420
|
function emit(steps, incoming, scope, parentId,
|
|
6393
|
-
// The enclosing container's break
|
|
6394
|
-
// Branch/switch/parallel arms and error handlers INHERIT
|
|
6395
|
-
// container replaces
|
|
6396
|
-
|
|
6421
|
+
// The enclosing container's break and continue handles, when inside a
|
|
6422
|
+
// loop/do-while body. Branch/switch/parallel arms and error handlers INHERIT
|
|
6423
|
+
// them; a nested container replaces them for its own body.
|
|
6424
|
+
loopExits) {
|
|
6397
6425
|
let tails = incoming;
|
|
6398
6426
|
// The action a port-scoped edge leaves. `.stepToList('error', …)` and
|
|
6399
6427
|
// `.stepToRef('error', …)` are list MEMBERS that follow the step they attach
|
|
@@ -6437,6 +6465,14 @@ export function serialize(built, opts = {}) {
|
|
|
6437
6465
|
node.display = { ...(node.display ?? {}), label };
|
|
6438
6466
|
};
|
|
6439
6467
|
for (const [stepIndex, step] of steps.entries()) {
|
|
6468
|
+
// After a node whose exits are all templated, only its port lists may
|
|
6469
|
+
// follow: nothing continues from it, so a step here would hang off no edge.
|
|
6470
|
+
const router = lastAction !== undefined && tails.length === 0 ? routerNodes.get(lastAction) : undefined;
|
|
6471
|
+
if (router !== undefined && step.kind !== 'stepToList' && step.kind !== 'stepToRef') {
|
|
6472
|
+
throw new Error(`step "${lastAction}": its definition declares only templated exits (such as case-{item.id}), so no `
|
|
6473
|
+
+ `path continues from it and ${'name' in step ? `"${step.name}"` : `.${step.kind}()`} after it would `
|
|
6474
|
+
+ `have no incoming edge. Route each exit with .stepToList('<port>', …), e.g. .stepToList('case-<id>', …).`);
|
|
6475
|
+
}
|
|
6440
6476
|
if (step.kind === 'action') {
|
|
6441
6477
|
tails = emitAction(step, tails, scope, parentId);
|
|
6442
6478
|
applyUpdates(step);
|
|
@@ -6465,7 +6501,7 @@ export function serialize(built, opts = {}) {
|
|
|
6465
6501
|
}
|
|
6466
6502
|
}
|
|
6467
6503
|
else if (step.kind === 'stepToList') {
|
|
6468
|
-
tails = emitPortList(step, lastAction ?? '?', tails, scope, parentId,
|
|
6504
|
+
tails = emitPortList(step, lastAction ?? '?', tails, scope, parentId, loopExits);
|
|
6469
6505
|
}
|
|
6470
6506
|
else if (step.kind === 'stepSwitch') {
|
|
6471
6507
|
// The action, then EVERY exit it declares as an arm — no tacit tail.
|
|
@@ -6510,7 +6546,7 @@ export function serialize(built, opts = {}) {
|
|
|
6510
6546
|
// from all of them. (`.stepToList` instead gives an arm that runs out
|
|
6511
6547
|
// of steps an End of its own; `emitEnd` maps the outputs on it,
|
|
6512
6548
|
// flow-builder-sdk#742.)
|
|
6513
|
-
const caseTails = emit(c.body, [{ node: nodeId, port: exit.port }], scope, parentId,
|
|
6549
|
+
const caseTails = emit(c.body, [{ node: nodeId, port: exit.port }], scope, parentId, loopExits);
|
|
6514
6550
|
if (caseTails.length === 0 && stopsAtEnd(c.body))
|
|
6515
6551
|
stopped.push(String(c.value));
|
|
6516
6552
|
armTails.push(...(hitlNodes.has(nodeId)
|
|
@@ -6555,8 +6591,8 @@ export function serialize(built, opts = {}) {
|
|
|
6555
6591
|
scope.nodes.push(node);
|
|
6556
6592
|
for (const t of tails)
|
|
6557
6593
|
addEdge(scope, t, id);
|
|
6558
|
-
const thenTails = emit(step.then, [{ node: id, port: 'true' }], scope, parentId,
|
|
6559
|
-
const elseTails = emit(step.otherwise, [{ node: id, port: 'false' }], scope, parentId,
|
|
6594
|
+
const thenTails = emit(step.then, [{ node: id, port: 'true' }], scope, parentId, loopExits);
|
|
6595
|
+
const elseTails = emit(step.otherwise, [{ node: id, port: 'false' }], scope, parentId, loopExits);
|
|
6560
6596
|
tails = [...thenTails, ...elseTails];
|
|
6561
6597
|
}
|
|
6562
6598
|
else if (step.kind === 'switch') {
|
|
@@ -6571,8 +6607,11 @@ export function serialize(built, opts = {}) {
|
|
|
6571
6607
|
// the runtime — so no `=js:` prefix, same as a decision's `expression`.
|
|
6572
6608
|
const id = stepUid(scope, step.name);
|
|
6573
6609
|
const node = makeNode(NODE_TYPE.switch, id, step.options?.label ?? step.label ?? step.name, { parentId, requestedVersion: step.options?.version });
|
|
6610
|
+
// `id` is the author's when given (a decompiled switch keeps the
|
|
6611
|
+
// canvas's `default-1`, …: merge keeps the original node, so the edges
|
|
6612
|
+
// must leave from ITS handles), else positional (#1130).
|
|
6574
6613
|
const cases = step.cases.map((c, i) => ({
|
|
6575
|
-
id: `case_${i + 1}`,
|
|
6614
|
+
id: c.id ?? `case_${i + 1}`,
|
|
6576
6615
|
label: c.label ?? `Case ${caseLiteral(c.value)}`,
|
|
6577
6616
|
expression: `${renameRefs(step.on.js, scope.rename)} === ${caseLiteral(c.value)}`,
|
|
6578
6617
|
}));
|
|
@@ -6585,9 +6624,9 @@ export function serialize(built, opts = {}) {
|
|
|
6585
6624
|
// merge node; the convergence point is found by graph search).
|
|
6586
6625
|
const armTails = [];
|
|
6587
6626
|
for (const [i, c] of step.cases.entries())
|
|
6588
|
-
armTails.push(...emit(c.body, [{ node: id, port: `case-${cases[i].id}` }], scope, parentId,
|
|
6627
|
+
armTails.push(...emit(c.body, [{ node: id, port: `case-${cases[i].id}` }], scope, parentId, loopExits));
|
|
6589
6628
|
if (step.default !== undefined)
|
|
6590
|
-
armTails.push(...emit(step.default, [{ node: id, port: 'default' }], scope, parentId));
|
|
6629
|
+
armTails.push(...emit(step.default, [{ node: id, port: 'default' }], scope, parentId, loopExits));
|
|
6591
6630
|
tails = armTails;
|
|
6592
6631
|
}
|
|
6593
6632
|
else if (step.kind === 'parallel') {
|
|
@@ -6620,7 +6659,7 @@ export function serialize(built, opts = {}) {
|
|
|
6620
6659
|
const armTails = [];
|
|
6621
6660
|
const endsBefore = hitlEndExits.length;
|
|
6622
6661
|
for (const arm of step.arms) {
|
|
6623
|
-
const t = emit(arm, tails, scope, parentId,
|
|
6662
|
+
const t = emit(arm, tails, scope, parentId, loopExits);
|
|
6624
6663
|
// An arm hands the join ONE edge, or several that are alternatives —
|
|
6625
6664
|
// `.branch` / `.switch` / `.stepSwitch` arms, a fan-out task's
|
|
6626
6665
|
// outcomes — of which only one fires. Refused when any of them is a
|
|
@@ -6705,7 +6744,7 @@ export function serialize(built, opts = {}) {
|
|
|
6705
6744
|
addEdge(scope, t, id);
|
|
6706
6745
|
const bodyPort = v24 ? 'start' : 'output';
|
|
6707
6746
|
const backPort = v24 ? 'continue' : 'loopBack';
|
|
6708
|
-
const bodyTails = emit(step.body, [{ node: id, port: bodyPort }], scope, id, v24 ? { node: id,
|
|
6747
|
+
const bodyTails = emit(step.body, [{ node: id, port: bodyPort }], scope, id, v24 ? { node: id, break: 'break', continue: backPort } : { node: id, continue: backPort });
|
|
6709
6748
|
for (const bt of bodyTails)
|
|
6710
6749
|
addEdge(scope, bt, id, backPort);
|
|
6711
6750
|
applyUpdates(step);
|
|
@@ -6724,18 +6763,29 @@ export function serialize(built, opts = {}) {
|
|
|
6724
6763
|
scope.nodes.push(node);
|
|
6725
6764
|
for (const t of tails)
|
|
6726
6765
|
addEdge(scope, t, id);
|
|
6727
|
-
const bodyTails = emit(step.body, [{ node: id, port: 'start' }], scope, id, { node: id,
|
|
6766
|
+
const bodyTails = emit(step.body, [{ node: id, port: 'start' }], scope, id, { node: id, break: 'break', continue: 'continue' });
|
|
6728
6767
|
for (const bt of bodyTails)
|
|
6729
6768
|
addEdge(scope, bt, id, 'continue');
|
|
6730
6769
|
applyUpdates(step);
|
|
6731
6770
|
tails = [{ node: id, port: 'success' }];
|
|
6732
6771
|
}
|
|
6733
6772
|
else if (step.kind === 'break') {
|
|
6734
|
-
if (!
|
|
6773
|
+
if (!loopExits?.break) {
|
|
6735
6774
|
throw new Error('.break() has no enclosing .loop()/.doWhile() body to exit — it is only valid inside a container.');
|
|
6736
6775
|
}
|
|
6737
6776
|
for (const t of tails)
|
|
6738
|
-
addEdge(scope, t,
|
|
6777
|
+
addEdge(scope, t, loopExits.node, loopExits.break);
|
|
6778
|
+
tails = [];
|
|
6779
|
+
}
|
|
6780
|
+
else if (step.kind === 'continue') {
|
|
6781
|
+
// The same edge a body's last step gets, from wherever this path has got
|
|
6782
|
+
// to — so a handler or an arm can go on to the next iteration instead of
|
|
6783
|
+
// ending the run on an End of its own (#1129).
|
|
6784
|
+
if (!loopExits) {
|
|
6785
|
+
throw new Error('.continue() has no enclosing .loop()/.doWhile() body to go back to — it is only valid inside a container.');
|
|
6786
|
+
}
|
|
6787
|
+
for (const t of tails)
|
|
6788
|
+
addEdge(scope, t, loopExits.node, loopExits.continue);
|
|
6739
6789
|
tails = [];
|
|
6740
6790
|
}
|
|
6741
6791
|
else if (step.kind === 'terminate') {
|
|
@@ -6773,7 +6823,8 @@ export function serialize(built, opts = {}) {
|
|
|
6773
6823
|
else {
|
|
6774
6824
|
// Any other port is a SIDE EXIT from the step just emitted. The main
|
|
6775
6825
|
// path is untouched, so `tails` survives and chaining continues.
|
|
6776
|
-
const
|
|
6826
|
+
const router = tails.length === 0 && lastAction !== undefined ? routerNodes.get(lastAction) : undefined;
|
|
6827
|
+
const from = tails[0] ?? (router !== undefined ? { node: router, port: step.port } : undefined);
|
|
6777
6828
|
if (!from)
|
|
6778
6829
|
throw new Error(`.stepToRef('${step.port}', '${step.target}') has no step to leave from.`);
|
|
6779
6830
|
refuseRewire('.stepToRef', step.port, lastAction ?? '?', tails);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/maestro-builder-sdk",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.20.1",
|
|
4
4
|
"description": "Build UiPath Flow, Case, and BPMN artifacts by writing TypeScript.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://docs.uipath.com/maestro",
|
|
@@ -92,5 +92,5 @@
|
|
|
92
92
|
"@types/node": "^22.7.0",
|
|
93
93
|
"esbuild": "^0.28.1"
|
|
94
94
|
},
|
|
95
|
-
"gitref": "
|
|
95
|
+
"gitref": "5440c25e8e833aced459eb5a0ae9109ac3c973ae"
|
|
96
96
|
}
|