@uipath/maestro-builder-sdk 6.66.6 → 6.66.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/bindings-v2.d.ts +15 -1
  2. package/dist/bindings-v2.js +29 -6
  3. package/dist/bpmn/check.js +16 -113
  4. package/dist/bpmn/serialize.d.ts +41 -0
  5. package/dist/bpmn/serialize.js +103 -1
  6. package/dist/bpmn/typed-node.d.ts +12 -0
  7. package/dist/bpmn/typed-node.js +24 -0
  8. package/dist/case/check.js +5 -40
  9. package/dist/case/serialize.js +6 -0
  10. package/dist/case/task-shape.d.ts +31 -0
  11. package/dist/case/task-shape.js +48 -0
  12. package/dist/check.js +7 -43
  13. package/dist/core/agent-sidecar.d.ts +13 -3
  14. package/dist/core/agent-sidecar.js +10 -0
  15. package/dist/core/compile-refusal.d.ts +25 -0
  16. package/dist/core/compile-refusal.js +19 -0
  17. package/dist/core/process-resource.d.ts +9 -0
  18. package/dist/core/process-resource.js +4 -0
  19. package/dist/core/refusals.d.ts +47 -44
  20. package/dist/core/refusals.js +47 -44
  21. package/dist/nodes/agent/flow/check.js +14 -42
  22. package/dist/nodes/agent/flow/inline-agent.js +62 -1
  23. package/dist/nodes/agent/flow/spec.d.ts +1 -1
  24. package/dist/nodes/connector/flow/node-type.js +5 -3
  25. package/dist/nodes/data-fabric/flow/check.js +2 -4
  26. package/dist/nodes/data-fabric/flow/shared.d.ts +9 -4
  27. package/dist/nodes/data-fabric/flow/shared.js +14 -4
  28. package/dist/nodes/document/flow/ixp.js +20 -9
  29. package/dist/nodes/hitl/flow/check.js +29 -110
  30. package/dist/nodes/hitl/flow/node-type.js +170 -3
  31. package/dist/nodes/process/flow/check.js +15 -80
  32. package/dist/nodes/process/flow/node-type.js +4 -0
  33. package/dist/nodes/process/flow/refusals.d.ts +8 -0
  34. package/dist/nodes/process/flow/refusals.js +92 -0
  35. package/dist/nodes/queue/flow/check.d.ts +25 -0
  36. package/dist/nodes/queue/flow/check.js +48 -18
  37. package/dist/nodes/queue/flow/node-type.js +13 -1
  38. package/dist/nodes/transform/flow/check.js +31 -43
  39. package/dist/nodes/transform/flow/node-type.js +35 -9
  40. package/dist/serialize.js +172 -20
  41. package/package.json +2 -2
package/dist/serialize.js CHANGED
@@ -11,7 +11,7 @@ import { LOOP_DEFAULT_VERSION, bodyUsesBreak, loopDeclaredInputs, loopHasInnerHa
11
11
  import { Expr, toExpr, SCHEDULE_PRESETS, flatNameSegmentsOf, parallelFork } from './flow-sdk.js';
12
12
  import { FlowAction, FlowTrigger } from './core/node-classes.js';
13
13
  import { connectorRawNodeRefusal } from './core/connector-raw-node.js';
14
- import { CompileRefusal } from './core/compile-refusal.js';
14
+ import { CompileRefusal, LibraryRequiredRefusal } from './core/compile-refusal.js';
15
15
  import { nearestName } from './core/edit-distance.js';
16
16
  import { rawNodeInputProblem, registeredRawType } from './raw-node-advice.js';
17
17
  import { planContributionBindings } from './core/contribution-bindings.js';
@@ -736,17 +736,31 @@ function resolveEvent(library, kind, sub, where) {
736
736
  /**
737
737
  * LIBRARY_REQUIRED for an event subscription at `site`, after the refusals that
738
738
  * need no library: its binding labels, judged as `eventDetail` judges them, so a
739
- * run without a library (`check`'s inner loop) still hears about them.
739
+ * run without a library (`check`'s inner loop) still hears about them. The
740
+ * refusal carries the connection the node is bound to, so its collect-mode
741
+ * stand-in still takes part in the file-wide connection rule (`connectionConnectors`).
740
742
  */
741
743
  function libraryRequiredForEvent(opts, sub, nodeId, site, call) {
744
+ let use;
742
745
  if (sub !== null && typeof sub === 'object') {
746
+ // With no library no parameter is declared, so every `where` key lands in
747
+ // eventParameters and folds into the match expression, exactly as
748
+ // `eventDetail` places an undeclared key. A lookup token is a value only
749
+ // a library resolves; it is not judged here.
750
+ if (sub.where !== null && typeof sub.where === 'object') {
751
+ const scope = Object.fromEntries(Object.entries(sub.where).filter(([, v]) => !isLookupToken(v)));
752
+ eventScopeClauses(flattenWhere(scope, new Set()), nodeId);
753
+ }
743
754
  if (Array.isArray(sub.filters))
744
755
  eventFilterReads(sub.filters, nodeId);
745
756
  requireBindingPair(site, sub, eventTarget(sub));
746
- resolveBinding(opts, sub.connection, 'connection', `event node "${nodeId}"`, eventTarget(sub));
757
+ const connection = resolveBinding(opts, sub.connection, 'connection', `event node "${nodeId}"`, eventTarget(sub));
747
758
  resolveBinding(opts, sub.folder, 'folder', `event node "${nodeId}"`, eventTarget(sub));
759
+ const connector = eventTarget(sub)?.key;
760
+ if (connection !== undefined && connector !== undefined)
761
+ use = { connector, connection };
748
762
  }
749
- return new CompileRefusal('LIBRARY_REQUIRED', `${call} needs a library (pass --library / set $FLOW_SDK_LIBRARY_JSON).`);
763
+ return new LibraryRequiredRefusal(`${call} needs a library (pass --library / set $FLOW_SDK_LIBRARY_JSON).`, use);
750
764
  }
751
765
  /** The trigger kinds a `.trigger()` or `.entryPoint()` spec may carry. */
752
766
  const TRIGGER_KINDS = new Set(['manual', 'scheduled', 'event', 'form', 'conversation', 'voice']);
@@ -916,6 +930,36 @@ function eventFilterReads(filters, nodeId) {
916
930
  return read;
917
931
  });
918
932
  }
933
+ /**
934
+ * The match-expression clauses of a subscription's EVENT parameters, one
935
+ * `k == '<value>'` per value, or the refusal of the first value compile cannot
936
+ * write there. The clause compares against a JMESPath string, so the value must
937
+ * be a string, number or boolean: an object or array would be stringified to
938
+ * `'[object Object]'` (or a comma list), a subscription that matches nothing
939
+ * (EVENT_WHERE_NOT_SCALAR). A string with a backslash JMESPath engines read
940
+ * apart is EVENT_FILTER_BACKSLASH. An absent or empty value (`''` or `[]`, so a
941
+ * `where` built from a possibly-empty list) writes no clause.
942
+ *
943
+ * Only event parameters fold into the expression; a query or path parameter is
944
+ * sent with the request that registers the subscription and is never read as
945
+ * JMESPath, so neither rule applies to it.
946
+ */
947
+ function eventScopeClauses(eventParameters, nodeId) {
948
+ return Object.entries(eventParameters)
949
+ .filter(([, v]) => v !== undefined && v !== null && v !== '' && !(Array.isArray(v) && v.length === 0))
950
+ .map(([k, v]) => {
951
+ if (typeof v !== 'string' && typeof v !== 'number' && typeof v !== 'boolean') {
952
+ throw new CompileRefusal('EVENT_WHERE_NOT_SCALAR', `event node "${nodeId}": \`where.${k}\` is ${Array.isArray(v) ? 'an array' : isLookupToken(v) ? 'an unresolved lookup() nested inside an object' : 'an object'}, `
953
+ + `and an event parameter is matched as one text value (\`${k} == '<value>'\`): written as it is, `
954
+ + `the subscription would compare against ${JSON.stringify(String(v))} and match nothing. `
955
+ + `Give \`${k}\` a string, number or boolean.`, `where: { '${k}': '<value>' }`);
956
+ }
957
+ const problem = jmesStringProblem(String(v));
958
+ if (problem)
959
+ throw new CompileRefusal('EVENT_FILTER_BACKSLASH', `event node "${nodeId}": \`where.${k}\`: ${problem}`);
960
+ return `${k} == ${jmesString(String(v))}`;
961
+ });
962
+ }
919
963
  function eventDetail(rc, sub, nodeId, opts, site) {
920
964
  requireBindingPair(site, sub, eventTarget(sub));
921
965
  const conn = resolveBinding(opts, sub.connection, 'connection', `event node "${nodeId}"`, eventTarget(sub));
@@ -976,14 +1020,7 @@ function eventDetail(rc, sub, nodeId, opts, site) {
976
1020
  // subscription's own scope — the mandatory clause the platform AND-joins —
977
1021
  // whereas a query or path parameter is part of the request that registers
978
1022
  // the subscription, not a property of the events it matches.
979
- const scopeClauses = Object.entries(eventParameters)
980
- .filter(([, v]) => v !== undefined && v !== null && String(v) !== '')
981
- .map(([k, v]) => {
982
- const problem = jmesStringProblem(String(v));
983
- if (problem)
984
- throw new CompileRefusal('EVENT_FILTER_BACKSLASH', `event node "${nodeId}": \`where.${k}\`: ${problem}`);
985
- return `${k} == ${jmesString(String(v))}`;
986
- });
1023
+ const scopeClauses = eventScopeClauses(eventParameters, nodeId);
987
1024
  // Each authored filter is read structurally (which operator, which value) and
988
1025
  // lowered with the designer's own grammar — see `event-filters.ts` for the
989
1026
  // measured table.
@@ -1499,6 +1536,21 @@ function terminateOutputs(scope) {
1499
1536
  }
1500
1537
  return outs;
1501
1538
  }
1539
+ /**
1540
+ * A step or entry point named `start` in a scope where `$vars.start` is
1541
+ * rewritten to the scope's start node (#1518): the root while `.triggerId()`
1542
+ * renames the trigger (`renamedTrigger`), or any subflow body (its start node
1543
+ * is `<caller>Start`). The rewrite would point the node's own readers at that
1544
+ * start node, so the name is refused instead. A step-level refusal: `check`
1545
+ * reports it on the step (or entry point), so the message names no scope.
1546
+ */
1547
+ function startReadRefusal(what, renamedTrigger, code = 'STEP_ID_COLLISION') {
1548
+ const owner = renamedTrigger !== undefined
1549
+ ? `the trigger, which .triggerId("${renamedTrigger}") renamed: compile rewrites \`$vars.start\` to \`$vars.${renamedTrigger}\``
1550
+ : "this subflow body's own start node: compile rewrites `$vars.start` to it";
1551
+ return new CompileRefusal(code, `[${code}] ${what}: \`$vars.start\` (what \`input()\` reads) names ${owner}, so reads of `
1552
+ + `${what} would go there. Give it another name.`);
1553
+ }
1502
1554
  /**
1503
1555
  * Rewrite `$vars.<step>` references through a scope's rename map.
1504
1556
  *
@@ -1716,6 +1768,13 @@ function serializeFlow(built, opts) {
1716
1768
  * placeholder check exempts them.
1717
1769
  */
1718
1770
  const unboundDrafts = new Set();
1771
+ /**
1772
+ * The connection each collect-mode stand-in was bound to, by node id: a node
1773
+ * refused only for want of a library (`LibraryRequiredRefusal`) has no
1774
+ * `detail` to read, so the file-wide connection rule (`connectionConnectors`)
1775
+ * is handed it here. Empty outside collect mode.
1776
+ */
1777
+ const standInConnections = new Map();
1719
1778
  /**
1720
1779
  * RESOURCE bindings collected while emitting, keyed by binding id — `resource:
1721
1780
  * 'process'` for the rpa family, `resource: 'queue'` for the queue family.
@@ -1877,9 +1936,16 @@ function serializeFlow(built, opts) {
1877
1936
  // trigger node's default id. When the flow renames the trigger, register that
1878
1937
  // rename so the SAME pass that rewrites step-name references rewrites these
1879
1938
  // too, rather than teaching every call site about the trigger.
1880
- if (built.triggerId && built.triggerId !== 'start') {
1881
- root.rename.nodeIds.set('start', [built.triggerId]);
1882
- }
1939
+ //
1940
+ // That rewrite cannot tell an `input()` read from a read of a node that is
1941
+ // really named `start` (`entryInput('start', 'x')` and `$vars.start.output.x`
1942
+ // in a step's code are the same text), so while the trigger is renamed the
1943
+ // name `start` is the trigger's: a step or an entry point that takes it is
1944
+ // refused (`startReadRefusal`), never rewritten to point at the trigger. A
1945
+ // subflow body renames `start` the same way, so its steps are held to it too.
1946
+ const renamedTrigger = built.triggerId && built.triggerId !== 'start' ? built.triggerId : undefined;
1947
+ if (renamedTrigger)
1948
+ root.rename.nodeIds.set('start', [renamedTrigger]);
1883
1949
  // Every node id emitted anywhere in the file. `start` is taken before
1884
1950
  // anything else: the root trigger's id is fixed, so a step named like the
1885
1951
  // trigger is refused (claimStepIds).
@@ -1984,7 +2050,9 @@ function serializeFlow(built, opts) {
1984
2050
  * thrown before any node is emitted). Renaming the second to `x2` left
1985
2051
  * `.stepToRef('x')` and `$vars.x` pointing at the first, with no word said.
1986
2052
  * - In the flow itself, a step named like the trigger is refused the same
1987
- * way (STEP_ID_COLLISION).
2053
+ * way (STEP_ID_COLLISION). So is a step named `start` wherever
2054
+ * `$vars.start` is rewritten to a start node: the flow while `.triggerId()`
2055
+ * renames the trigger, and every subflow body (#1518, `startReadRefusal`).
1988
2056
  * - A subflow body whose ids are already taken (a second copy of the same
1989
2057
  * child, or a child step sharing a name with a caller's step) is the one
1990
2058
  * place ids move: the whole copy is prefixed with the calling step's name,
@@ -2019,6 +2087,10 @@ function serializeFlow(built, opts) {
2019
2087
  // A subflow copy's named Ends (`alsoIds`) decide the prefix with its steps (#1253).
2020
2088
  const prefix = copyPrefix !== undefined && [...seen.keys(), ...alsoIds].some((id) => takenIds.has(id)) ? copyPrefix : '';
2021
2089
  for (const [safe, n] of seen) {
2090
+ // `$vars.start` names this scope's start node, not a step (see `renamedTrigger`).
2091
+ if (safe === 'start' && (copyPrefix !== undefined || renamedTrigger)) {
2092
+ refuseOn(scope, n, startReadRefusal(`step "${n}"`, copyPrefix !== undefined ? undefined : renamedTrigger));
2093
+ }
2022
2094
  if (!prefix && takenIds.has(safe)) {
2023
2095
  throw new CompileRefusal('STEP_ID_COLLISION', `${where}: [STEP_ID_COLLISION] step "${n}" has the trigger's node id "${safe}", and compile will not `
2024
2096
  + `rename it "${safe}2". Rename the step.`);
@@ -2244,6 +2316,34 @@ function serializeFlow(built, opts) {
2244
2316
  || scope.pendingEdges.some((p) => p.from.node === node && isOutcome(p.from.port));
2245
2317
  return tails.filter((t) => capsOpenTail.has(t.node) && !hasOutcomeEdge(t.node));
2246
2318
  }
2319
+ /**
2320
+ * A subflow body is started by its caller, through the one manual Start node
2321
+ * `emitSubflowBodyIn` writes. So a child's own way of starting has nowhere to
2322
+ * go in the `.flow`, and writing the body without it would silently drop what
2323
+ * the author wrote (#1067): a `.trigger(scheduled(…))` would never fire, and an
2324
+ * `.entryPoint()` root and its steps would vanish. Both are refused.
2325
+ * `.trigger(manual(), { label, version })` is allowed: it names the child's
2326
+ * Start node (#1050), and it is the form decompile writes for a renamed one.
2327
+ */
2328
+ function refuseChildRoots(child, step) {
2329
+ // `subflow(undefined, …)` is `check`'s SUBFLOW_NO_CHILD.
2330
+ if (!child || !Array.isArray(child.steps))
2331
+ return;
2332
+ const kind = child.trigger?.kind;
2333
+ if (child.trigger !== undefined && kind !== 'manual') {
2334
+ const noun = kind === 'scheduled' ? 'schedule' : kind === 'event' ? 'event subscription' : 'trigger';
2335
+ throw new CompileRefusal('SUBFLOW_CHILD_TRIGGER', `Subflow "${step}" runs a flow with its own \`.trigger(…)\`. A subflow is started by its caller, never by a `
2336
+ + `trigger of its own — the ${noun} would be dropped. Remove the .trigger() from "${child.id}" `
2337
+ + `(\`.trigger(manual(), { label })\` is allowed, to name the child's start node).`);
2338
+ }
2339
+ const roots = child.entryPoints ?? [];
2340
+ if (roots.length > 0) {
2341
+ throw new CompileRefusal('SUBFLOW_CHILD_ENTRY_POINT', `Subflow "${step}" runs a flow with ${roots.length === 1 ? 'an entry point' : 'entry points'} `
2342
+ + `(${roots.map((r) => `"${r.id}"`).join(', ')}). A subflow has one root, its caller, so the entry `
2343
+ + `${roots.length === 1 ? 'point and its steps' : 'points and their steps'} would be dropped. Call a flow `
2344
+ + `without .entryPoint(), or move each entry point's steps into a flow of its own.`);
2345
+ }
2346
+ }
2247
2347
  /**
2248
2348
  * Emit a child flow into its own scope and register it under the calling
2249
2349
  * node's id — that key is how the format names a subflow body, and how
@@ -2252,7 +2352,7 @@ function serializeFlow(built, opts) {
2252
2352
  * The child gets its own manual Start node (a subflow always starts manually
2253
2353
  * — nothing schedules a subflow; its caller is the trigger) and its own
2254
2354
  * variables. A child's `.trigger(manual(), { label, version })` sets that
2255
- * node's canvas label and exact version; `check` refuses any other kind.
2355
+ * node's canvas label and exact version; `refuseChildRoots` refuses any other kind.
2256
2356
  * Every `in` variable carries `triggerNodeId` pointing at that
2257
2357
  * Start: it is what binds the caller's value, and omitting it is the single
2258
2358
  * defect that makes a subflow validate clean and then fault at run time with
@@ -2803,8 +2903,9 @@ function serializeFlow(built, opts) {
2803
2903
  }
2804
2904
  // A type that owns a family of names (`typeNamePrefix`) is placed under the
2805
2905
  // name its definition carries — `uipath.core.function.<key>`, not the prefix.
2806
- // The bare prefix is allowed: an empty `key` builds it, check refuses that
2807
- // input (`*_NO_KEY`), and serialize alone emits what it always did.
2906
+ // The bare prefix is a name the type owns, so it is not an internal error
2907
+ // here; a type refuses a blank key itself when that is what builds it (the
2908
+ // process family's `*_NO_KEY`, nodes/process/flow/refusals.ts).
2808
2909
  const prefix = entry.type.typeNamePrefix;
2809
2910
  const nodeType = prefix !== undefined ? def?.nodeType : impl.typeName;
2810
2911
  if (prefix !== undefined && (typeof nodeType !== 'string' || !nodeType.startsWith(prefix)
@@ -2889,6 +2990,43 @@ function serializeFlow(built, opts) {
2889
2990
  throw refusal;
2890
2991
  record(refusal, stepName, scope.stepNodeId.get(stepName) ?? scope.pending.get(stepName));
2891
2992
  }
2993
+ /**
2994
+ * Refuse a `.switch()` case the node cannot hold as written (#1518). Each
2995
+ * case becomes one `{ id, expression }` row and one `case-<id>` port, so:
2996
+ * - SWITCH_CASE_FORM: a case needs exactly one of `value` (compared with
2997
+ * `on`) and `when` (its own condition). With both, only `when` would be
2998
+ * written and the value dropped; a `value` with no `on` would be written as
2999
+ * `undefined === 1`, and a case with neither as `undefined === undefined`,
3000
+ * which is always taken.
3001
+ * - SWITCH_CASE_ID: an id must be a non-empty string, and one per case. Two
3002
+ * cases on one id (an explicit `case_2` beside the positional one, #1130)
3003
+ * would share one `case-case_2` port, edges to both arms; a blank or
3004
+ * non-string id writes a `case-` / `case-5` port.
3005
+ * In collect mode each one is reported on the switch, and the node is still
3006
+ * written as authored, so the arms are judged.
3007
+ */
3008
+ function refuseSwitchCases(scope, step) {
3009
+ const s = step.name;
3010
+ const seenIds = new Set();
3011
+ step.cases.forEach((c, i) => {
3012
+ const hasValue = c.value !== undefined;
3013
+ const hasWhen = c.when !== undefined;
3014
+ if (hasValue === hasWhen || (hasValue && !step.on)) {
3015
+ refuseOn(scope, s, new CompileRefusal('SWITCH_CASE_FORM', hasValue && hasWhen
3016
+ ? `Switch "${s}" case ${i + 1} has both \`value\` and \`when\`. Give it one: \`value\` is compared with \`on\`, \`when\` is the case's own condition.`
3017
+ : hasValue
3018
+ ? `Switch "${s}" case ${i + 1} has a \`value\` but the switch has no \`on\` to compare it with. Pass \`on\`, or give the case a \`when\` condition.`
3019
+ : `Switch "${s}" case ${i + 1} has neither \`value\` nor \`when\`.`));
3020
+ }
3021
+ const caseId = c.id ?? `case_${i + 1}`;
3022
+ if (typeof caseId !== 'string' || caseId === '' || seenIds.has(caseId)) {
3023
+ refuseOn(scope, s, new CompileRefusal('SWITCH_CASE_ID', typeof caseId !== 'string' || caseId === ''
3024
+ ? `Switch "${s}" case ${i + 1} has an id that is not a non-empty string. Leave \`id\` out for the positional case_<n>.`
3025
+ : `Switch "${s}" has two cases with the id "${caseId}", so both would leave from one 'case-${caseId}' port. Give one a different \`id\`.`));
3026
+ }
3027
+ seenIds.add(String(caseId));
3028
+ });
3029
+ }
2892
3030
  /** The step whose node `nodeId` is, in `scope`. */
2893
3031
  function stepOfNode(scope, nodeId) {
2894
3032
  for (const [name, id] of scope.stepNodeId)
@@ -2911,6 +3049,8 @@ function serializeFlow(built, opts) {
2911
3049
  catch (error) {
2912
3050
  const refusal = stepRefusal(error);
2913
3051
  record(refusal, name, id);
3052
+ if (refusal instanceof LibraryRequiredRefusal && refusal.connection)
3053
+ standInConnections.set(id, refusal.connection);
2914
3054
  root.nodes.length = mark.nodes;
2915
3055
  for (const key of [...resourceBindings.keys()])
2916
3056
  if (!mark.resources.has(key))
@@ -2947,6 +3087,8 @@ function serializeFlow(built, opts) {
2947
3087
  const refusal = stepRefusal(error);
2948
3088
  const id = scope.stepNodeId.get(step.name) ?? stepUid(scope, step.name);
2949
3089
  record(refusal, step.name, id);
3090
+ if (refusal instanceof LibraryRequiredRefusal && refusal.connection)
3091
+ standInConnections.set(id, refusal.connection);
2950
3092
  scope.nodes.length = mark.nodes;
2951
3093
  scope.edges.length = mark.edges;
2952
3094
  scope.pendingEdges.length = mark.pendingEdges;
@@ -3026,6 +3168,7 @@ function serializeFlow(built, opts) {
3026
3168
  if (registered)
3027
3169
  return emitRegistered(registered, step, tails, scope, parentId);
3028
3170
  if (spec.kind === 'subflow') {
3171
+ refuseChildRoots(spec.child, step.name);
3029
3172
  const id = stepUid(scope, step.name);
3030
3173
  // `subflows` is ONE flat map for the whole file, keyed by the calling
3031
3174
  // node's id. `stepUid` draws from the file-wide allocator, including in
@@ -3387,6 +3530,7 @@ function serializeFlow(built, opts) {
3387
3530
  // the runtime — so no `=js:` prefix, same as a decision's `expression`.
3388
3531
  const id = stepUid(scope, step.name);
3389
3532
  const node = makeNode(NODE_TYPE.switch, id, step.options?.label ?? step.label ?? step.name, { parentId, requestedVersion: step.options?.version });
3533
+ refuseSwitchCases(scope, step);
3390
3534
  // `id` is the author's when given (a decompiled switch keeps the
3391
3535
  // canvas's `default-1`, …: merge keeps the original node, so the edges
3392
3536
  // must leave from ITS handles), else positional (#1130).
@@ -3785,6 +3929,14 @@ function serializeFlow(built, opts) {
3785
3929
  const firstShared = built.steps.find((st) => 'name' in st && st.kind !== 'return');
3786
3930
  const sharedTarget = firstShared && 'name' in firstShared ? root.stepNodeId.get(firstShared.name) : undefined;
3787
3931
  for (const ep of entryPoints) {
3932
+ if (ep.id === 'start' && renamedTrigger) {
3933
+ // Reported on the entry point; in collect mode it is still emitted (the
3934
+ // id `start` is free in the file), so its prefix is judged too.
3935
+ const refusal = startReadRefusal(`.entryPoint("${ep.id}")`, renamedTrigger, 'ENTRY_POINT_DUP_ID');
3936
+ if (!opts.collect)
3937
+ throw refusal;
3938
+ record(refusal, ep.id, ep.id);
3939
+ }
3788
3940
  if (takenIds.has(ep.id)) {
3789
3941
  throw new CompileRefusal('ENTRY_POINT_DUP_ID', `.entryPoint("${ep.id}"): the id collides with a step, the trigger, or another entry point.`);
3790
3942
  }
@@ -3955,7 +4107,7 @@ function serializeFlow(built, opts) {
3955
4107
  assertBindingPlaceholdersResolve(flow, unboundDrafts);
3956
4108
  assertFileWideIdsUnique(flow);
3957
4109
  assertConnectorConfigurationRestorable(flow);
3958
- connectionConnectors(flow);
4110
+ connectionConnectors(flow, standInConnections);
3959
4111
  return flow;
3960
4112
  }
3961
4113
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.66.6",
3
+ "version": "6.66.8",
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",
@@ -100,5 +100,5 @@
100
100
  "@types/node": "^22.7.0",
101
101
  "esbuild": "^0.28.1"
102
102
  },
103
- "gitref": "108478742e5fc426dc26ba07020d85a3fdbcaa66"
103
+ "gitref": "4800f0ca4d2a58eed272d12640145fc039e43a16"
104
104
  }