@uipath/maestro-builder-sdk 6.11.6 → 6.12.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.
@@ -22,7 +22,9 @@
22
22
  import type { TypeDesc } from '../core/expr.js';
23
23
  import { type ConnectorOpts } from '../core/actions.js';
24
24
  import type { ConnectorDescriptor } from '../core/connectors.js';
25
- import type { TypedContextRow, TypedOutputRow } from './typed-node.js';
25
+ import type { RegistryTypeSpec, TypedContextRow, TypedInputRow, TypedOutputRow } from './typed-node.js';
26
+ import { type DataServiceOperation } from './data-service.js';
27
+ export type { DataServiceOperation } from './data-service.js';
26
28
  export { BpmnBuildError } from './bpmn-expr-check.js';
27
29
  export type { BpmnLocatedDiagnostic } from './bpmn-expr-check.js';
28
30
  /** ISO-8601 timer specification (one of duration / date / cycle). */
@@ -103,6 +105,12 @@ export type BpmnNode = {
103
105
  };
104
106
  /** A `uipath:mapping` / `uipath:activity` payload on the event — see {@link ExtensionPayload}. */
105
107
  payload?: ExtensionPayload;
108
+ /**
109
+ * `false` marks a NON-interrupting start (`isInterrupting="false"`), which only an
110
+ * event sub-process's start can be — see {@link StartOpts.interrupting}. Unset means
111
+ * BPMN's default, interrupting, and writes no attribute.
112
+ */
113
+ interrupting?: boolean;
106
114
  } | {
107
115
  kind: 'boundaryEvent';
108
116
  id: string;
@@ -123,6 +131,8 @@ export type BpmnNode = {
123
131
  name?: string;
124
132
  script: string;
125
133
  scriptFormat: string;
134
+ /** The `uipath:scriptVersion` value — see {@link ScriptTaskOpts.scriptVersion}. */
135
+ scriptVersion: string;
126
136
  inputs: Record<string, string>;
127
137
  outputs: Record<string, string>;
128
138
  /** The mapping's extension type — see {@link ScriptTaskOpts.type}. */
@@ -164,6 +174,8 @@ export type BpmnNode = {
164
174
  context: Record<string, unknown>;
165
175
  /** The payload, shaped by the type's `inputPattern`. */
166
176
  inputs: Record<string, unknown>;
177
+ /** Payload rows spelled out, replacing `inputs` — see {@link TypedInputRow}. */
178
+ inputRows?: TypedInputRow[];
167
179
  /** Variable the output lands in; defaults to `<id>_<outputName>`. */
168
180
  outputVar?: string;
169
181
  /** Extra output rows: variable id → `=`-expression against the node's result. */
@@ -178,6 +190,8 @@ export type BpmnNode = {
178
190
  contextRows?: TypedContextRow[];
179
191
  /** `=`-expression that skips the node when truthy. */
180
192
  skipCondition?: string;
193
+ /** The type's emission spec, supplied inline — see {@link ActivityNodeOpts.spec}. */
194
+ spec?: RegistryTypeSpec;
181
195
  /** Emit `context` exactly as given — for importers; see `TypedNodeInput`. */
182
196
  contextVerbatim?: boolean;
183
197
  }) | (ActivityNodeFields & {
@@ -326,6 +340,14 @@ export interface BpmnFlow {
326
340
  name?: string;
327
341
  /** `=`-expression gating this flow (exclusive/inclusive gateway outgoing). Read a declared process variable as `=vars.<id>`. */
328
342
  condition?: string;
343
+ /**
344
+ * Set on a flow the builder wrote by implication — an arm's chain, a handler's path,
345
+ * a construct's join, or a `flowMode('sequence')` sibling — rather than from an
346
+ * explicit `.sequenceFlow()`. `bpmn check --graph` marks these, so what was inferred
347
+ * can be reviewed against what was typed. Not serialized; an explicit
348
+ * `.sequenceFlow()` that restates the edge clears it.
349
+ */
350
+ implied?: true;
329
351
  }
330
352
  /**
331
353
  * How a variable is exposed: `'input'` (read-only entry input), `'output'` (a
@@ -344,8 +366,14 @@ export interface BpmnVarDecl {
344
366
  direction: VarDirection;
345
367
  /** Optional initial value. */
346
368
  default?: unknown;
347
- /** When set, the variable is scoped to that element rather than root/global. */
348
- elementId?: string;
369
+ /**
370
+ * The element the declaration belongs to — see {@link VarOpts.elementId}. `undefined`
371
+ * is written as the SDK's default for the declaration's kind — the manual start event
372
+ * for a top-level `input`, the end event that writes it for a top-level `output`, the
373
+ * owning scope (process or sub-process id) otherwise; `null` writes no `elementId` at
374
+ * all, which only a decompiled legacy artifact asks for.
375
+ */
376
+ elementId?: string | null;
349
377
  /** The declaration's body — a JSON Schema for a structured variable. */
350
378
  schema?: unknown;
351
379
  /** Mark the declaration `required="true"`, as a process input can be. */
@@ -437,7 +465,11 @@ export interface ProcessMetadata {
437
465
  * builders use for the same concept, and is what `bpmn-decompile` emits.
438
466
  */
439
467
  migrationVersion?: string;
440
- /** The root start event's package entry-point id (`uipath:entryPointId`). */
468
+ /**
469
+ * The root start event's package entry-point id (`uipath:entryPointId`). A GUID —
470
+ * the one `bpmn init` assigned, or `crypto.randomUUID()`; `validate` refuses any
471
+ * other value and `check` reports `ENTRYPOINT_ID_NOT_GUID`.
472
+ */
441
473
  entryPointId?: string;
442
474
  /** Free-form document tags (`uipath:tags` / `uipath:tag`). */
443
475
  tags?: string[];
@@ -573,6 +605,16 @@ export interface StartOpts {
573
605
  };
574
606
  /** A `uipath:mapping` mapping process inputs onto variables — see {@link ExtensionPayload}. */
575
607
  payload?: ExtensionPayload;
608
+ /**
609
+ * `false` makes a message or timer start NON-interrupting: the event sub-process it
610
+ * starts runs beside the container instead of cancelling it (`isInterrupting="false"`).
611
+ *
612
+ * Only meaningful on the start event of an event sub-process, and never for an
613
+ * `error` start, which BPMN defines as interrupting — the throw has already ended its
614
+ * scope. Defaults to `true`, the BPMN default, which writes no attribute.
615
+ * {@link ScopeBuilder.eventSubProcess} sets this from its own `interrupting` option.
616
+ */
617
+ interrupting?: boolean;
576
618
  }
577
619
  /**
578
620
  * Options for `.endEvent()`. `terminate`, `error`, or `message` picks the event
@@ -743,6 +785,20 @@ export interface ScriptTaskOpts extends ActivityOpts {
743
785
  script: string;
744
786
  /** The script language marker. Defaults to `'JavaScript'` (Jint). */
745
787
  scriptFormat?: string;
788
+ /**
789
+ * The `uipath:scriptVersion` the runtime reads to pick the result shape. Defaults
790
+ * to `'v3'`, the contract the rest of this surface is written for: the script may
791
+ * return any value and `=result.response` is that value.
792
+ *
793
+ * Only worth setting on an import. `v2` means the same wrapper and round-trips
794
+ * unchanged; `v1` (what an ABSENT element means to the runtime) spreads the
795
+ * returned object's fields instead, so a script written for it reads
796
+ * `=result.<field>` and would silently read `undefined` if the version were
797
+ * stamped up to `v3` on recompile — which is what this SDK did before the field
798
+ * existed. `bpmn-decompile` therefore emits the source's value whenever it is not
799
+ * `v3`, spelling an absent element as `'v1'`.
800
+ */
801
+ scriptVersion?: string;
746
802
  /** `uipath:input` rows: field name → `=`-expression read into the script. */
747
803
  inputs?: Record<string, string>;
748
804
  /**
@@ -860,6 +916,55 @@ export interface BindingOpts {
860
916
  */
861
917
  resourceSubType?: string;
862
918
  }
919
+ /**
920
+ * Options for `.dataService()` — one UiPath Data Fabric (Data Service) record or
921
+ * file operation. Combine with a {@link DataServiceOperation} for the operation half:
922
+ *
923
+ * ```ts
924
+ * .binding('dataFabric', { resource: 'Connection', propertyAttribute: 'ConnectionId', value: CONNECTION_KEY })
925
+ * .binding('dataFabricFolder', { resource: 'Connection', propertyAttribute: 'folderKey', value: FOLDER_KEY })
926
+ * .dataService('create', { entity: 'ContractRegistry', connection: 'dataFabric', folder: 'dataFabricFolder',
927
+ * op: 'create', record: { contractTitle: '=vars.title', status: 'Open' } })
928
+ * .dataService('lookup', { entity: 'ContractRegistry', connection: 'dataFabric', folder: 'dataFabricFolder',
929
+ * op: 'get', recordId: '=vars.create_response.Id', expansionLevel: 3 })
930
+ * ```
931
+ */
932
+ export interface DataServiceOpts extends ActivityOpts {
933
+ /** Display name the designer shows. Defaults to one built from the operation, e.g. `Create ContractRegistry`. */
934
+ name?: string;
935
+ /** The Data Service entity the operation addresses, e.g. `'ContractRegistry'`. */
936
+ entity: string;
937
+ /**
938
+ * The Data Fabric connection: the id of a `.binding()` declared with
939
+ * `propertyAttribute: 'ConnectionId'` (with or without the `=bindings.` prefix), or
940
+ * the connection key itself, for which a binding is declared on your behalf and
941
+ * shared by every node that names the same key.
942
+ */
943
+ connection: string;
944
+ /**
945
+ * The folder the connection lives in: the id of a `.binding()` declared with
946
+ * `propertyAttribute: 'folderKey'`, or the folder key itself. Optional on the
947
+ * wire, but the platform resolves the connection through it, so a process meant
948
+ * to run should set it.
949
+ *
950
+ * A folder binding is a COMPANION of its connection: its `resourceKey` is the
951
+ * connection's key, and only its `default` is the folder key. That is how every
952
+ * real export writes the pair, and `uip maestro bpmn validate` reports
953
+ * `MISSING_BINDING` when the resource key is the folder's own. The builder writes
954
+ * the companion form whichever way the folder was given.
955
+ */
956
+ folder?: string;
957
+ /** Variable the response lands in. Defaults to `<id>_response`; the error payload always lands in `<id>_Error`. */
958
+ outputVar?: string;
959
+ /**
960
+ * A JSON Schema for the response, when its shape matters downstream — the created
961
+ * record's fields, say. Typed `jsonSchema` with no body otherwise, which is what the
962
+ * converter writes.
963
+ */
964
+ schema?: unknown;
965
+ /** `=`-expression that skips the operation when truthy. */
966
+ skipCondition?: string;
967
+ }
863
968
  /**
864
969
  * Options for `.http()` — an `Intsvc.UnifiedHttpRequest` node.
865
970
  *
@@ -1159,6 +1264,30 @@ export interface ActivityNodeOpts extends ActivityOpts {
1159
1264
  contextRows?: TypedContextRow[];
1160
1265
  /** The payload, shaped by the type's `inputPattern`. */
1161
1266
  inputs?: Record<string, unknown>;
1267
+ /**
1268
+ * The payload rows spelled out, replacing `inputs` — see {@link TypedInputRow}.
1269
+ *
1270
+ * For a `separateInputs` type whose rows carry what the record cannot say: a
1271
+ * `target` that is not the key (a connector parameter's `path` / `query`), or a
1272
+ * type the registry does not declare. `bpmn-decompile` writes this form when the
1273
+ * artifact needs it; an author reaches for it to reproduce a real export exactly.
1274
+ */
1275
+ inputRows?: TypedInputRow[];
1276
+ /**
1277
+ * The type's emission spec, supplied inline — the escape hatch for a registry type
1278
+ * the committed snapshot does not carry and no `uip` on this machine can describe,
1279
+ * or one the snapshot describes wrongly. Used as is: which BPMN element and
1280
+ * `uipath:*` tag to write, the context fields and their defaults, how the payload
1281
+ * rows are shaped, and the output row. The shape is {@link RegistryTypeSpec}; the
1282
+ * quickest way to a correct one is `uip maestro bpmn registry get <Type> --output json`
1283
+ * on a machine that has it, then `node scripts/materialize-bpmn-registry.mjs` to add it
1284
+ * to the snapshot for good.
1285
+ *
1286
+ * `bpmn-decompile` cannot recover this — it reads the artifact, not the registry — so
1287
+ * an import of such a node comes back as a plain `.activity()` that needs the spec
1288
+ * added by hand.
1289
+ */
1290
+ spec?: RegistryTypeSpec;
1162
1291
  /** Variable the type's own output lands in. Defaults to `<id>_<outputName>`. */
1163
1292
  outputVar?: string;
1164
1293
  /** Extra output rows: variable id → `=`-expression against the node's result. */
@@ -1219,6 +1348,17 @@ export interface PlainTaskOpts extends ActivityOpts {
1219
1348
  /** Which task element to emit. Defaults to `bpmn:task`. */
1220
1349
  element?: PlainTaskElement;
1221
1350
  }
1351
+ /**
1352
+ * One implied edge whose id is pinned — see {@link ScopeBuilder.flowIds}.
1353
+ */
1354
+ export interface PinnedFlowId {
1355
+ /** The element the edge leaves. */
1356
+ source: string;
1357
+ /** The element it flows into. */
1358
+ target: string;
1359
+ /** The id to give it instead of the derived `Flow_<source>_<target>`. */
1360
+ id: string;
1361
+ }
1222
1362
  /** Options for `.sequenceFlow()`. */
1223
1363
  export interface FlowOpts {
1224
1364
  /** The flow's element id. Defaults to `Flow_<source>_<target>`. */
@@ -1234,8 +1374,30 @@ export interface VarOpts {
1234
1374
  name?: string;
1235
1375
  /** Optional initial value. */
1236
1376
  default?: unknown;
1237
- /** When set, the variable is scoped to that element rather than root/global. */
1238
- elementId?: string;
1377
+ /**
1378
+ * The element this declaration belongs to, written as `elementId` on the wire.
1379
+ *
1380
+ * Left out, the declaration is written where the platform's own tools put one of
1381
+ * its kind. A `.var()` belongs to the scope it is declared in — the process id at
1382
+ * the top level, the sub-process id inside one. A top-level `.input()` belongs to
1383
+ * the process's manual START event and a top-level `.output()` to the END event
1384
+ * whose mapping writes it (or the only end event): that is how every Studio Web
1385
+ * export and converter output declares a process's public contract, and what the
1386
+ * canvas, the entry-point derivation and the graders read it from. The engine itself
1387
+ * resolves `vars.<id>` by id whatever the scope, so a script may read an input
1388
+ * directly with no start-event bridge. `uip maestro bpmn validate` (1.203+) requires
1389
+ * SOME `elementId`: a declaration with none is `ROOT_VARIABLE_MISSING_ELEMENT_ID`,
1390
+ * and every `vars.<id>` read of it fails `VARIABLE_DOES_NOT_EXIST`. Name an element
1391
+ * to scope the variable to it explicitly (the node whose output fills it, a specific
1392
+ * end event). `null` writes no `elementId` — the shape older exports have;
1393
+ * `decompile` emits it so such an artifact round-trips byte for byte.
1394
+ *
1395
+ * At the start of a run, the platform matches supplied input values to declarations
1396
+ * by their display `name` (`BpmnModelBuilder.AddProcessVariable` reads
1397
+ * `inputOverrides[name]`), so an input given a display name is supplied under that
1398
+ * name, not its id.
1399
+ */
1400
+ elementId?: string | null;
1239
1401
  /**
1240
1402
  * The declaration's BODY — a JSON Schema describing the shape of a `jsonSchema`
1241
1403
  * (or `json`) variable.
@@ -1253,6 +1415,269 @@ export interface VarOpts {
1253
1415
  /** Mark the declaration `required="true"`, as a process input can be. */
1254
1416
  required?: boolean;
1255
1417
  }
1418
+ /**
1419
+ * Boundary events declared on the activity they attach to — the callback every
1420
+ * activity method accepts as its last argument. See {@link ActivityBuilder}.
1421
+ */
1422
+ export type ActivityBodyFn = (t: ActivityBuilder) => void;
1423
+ /** The elements of one branch arm or boundary-handler path — see {@link PathBuilder}. */
1424
+ export type ArmBodyFn = (b: PathBuilder) => void;
1425
+ /**
1426
+ * What every boundary handler on an {@link ActivityBuilder} accepts —
1427
+ * `.onError()`, `.onTimer()`, `.onMessage()`.
1428
+ */
1429
+ export interface HandlerOpts {
1430
+ /**
1431
+ * The boundary event's element id. Defaults to `<activityId>_onError`,
1432
+ * `<activityId>_onTimer` or `<activityId>_onMessage`: a pure function of the ids the
1433
+ * author wrote, never of position, so `merge` keys stay stable when a line is
1434
+ * inserted above. A second handler of the same kind on one activity must name its own.
1435
+ */
1436
+ id?: string;
1437
+ /** Display name the designer shows on the boundary event. */
1438
+ name?: string;
1439
+ /** A `uipath:activity` payload on the boundary event — see {@link ExtensionPayload}. */
1440
+ payload?: ExtensionPayload;
1441
+ }
1442
+ /** Options for {@link ActivityBuilder.onError}. An error boundary always interrupts. */
1443
+ export interface ErrorHandlerOpts extends HandlerOpts {
1444
+ /**
1445
+ * Capture the error payload into this variable, the way the product does on every
1446
+ * error boundary it writes: a `uipath:activity` output row reading `=Error` into the
1447
+ * variable, plus the variable's declaration — `jsonSchema` typed, displayed as `Error`,
1448
+ * scoped to the boundary event — unless the author declared that id already.
1449
+ * Downstream, read `=vars.<errorVar>.code`, `.message`, `.detail`, `.status`.
1450
+ *
1451
+ * Mutually exclusive with `payload`, which spells the row out by hand.
1452
+ */
1453
+ errorVar?: string;
1454
+ }
1455
+ /** Options for {@link ActivityBuilder.onTimer}. */
1456
+ export interface TimerHandlerOpts extends HandlerOpts {
1457
+ /**
1458
+ * Whether firing cancels the activity. Defaults to `true`, BPMN's default
1459
+ * (`cancelActivity="true"`); `false` lets the activity carry on beside the handler
1460
+ * path, as a reminder does.
1461
+ *
1462
+ * The two continue differently. An INTERRUPTING handler's path rejoins the process at
1463
+ * the next statement after the activity, exactly as the activity's own path would
1464
+ * have. A NON-INTERRUPTING one runs beside a token that is still going to reach that
1465
+ * statement, so letting the handler reach it too would run everything after it twice.
1466
+ * Its path must therefore end — with an end event, `.goto()`, or an explicit
1467
+ * `.sequenceFlow()` off its last element — and the builder refuses one that does not.
1468
+ */
1469
+ interrupting?: boolean;
1470
+ }
1471
+ /** Options for {@link ActivityBuilder.onMessage}. */
1472
+ export interface MessageHandlerOpts extends HandlerOpts {
1473
+ /** Whether the message cancels the activity — see {@link TimerHandlerOpts.interrupting}. */
1474
+ interrupting?: boolean;
1475
+ }
1476
+ /**
1477
+ * One arm of {@link ScopeBuilder.choose}: a `when` condition, or the single
1478
+ * `otherwise` fallback. Exactly one of the two, checked by the type system, so an
1479
+ * arm nobody gave a condition cannot be written.
1480
+ */
1481
+ export type ChooseArm = {
1482
+ /** `=`-expression selecting this arm, e.g. `'=vars.action == "Approved"'`. */
1483
+ when: string;
1484
+ /** Not on a conditioned arm. */
1485
+ otherwise?: never;
1486
+ /** Edge label the designer shows on the arm's flow. */
1487
+ label?: string;
1488
+ /**
1489
+ * The arm's elements, in order. Omitted, the arm goes straight on to whatever
1490
+ * follows the `choose` — an empty branch.
1491
+ */
1492
+ body?: ArmBodyFn;
1493
+ } | {
1494
+ /** The fallback taken when no `when` holds — the gateway's default flow. */
1495
+ otherwise: true;
1496
+ /** Not on the fallback arm. */
1497
+ when?: never;
1498
+ /** Edge label the designer shows on the arm's flow. */
1499
+ label?: string;
1500
+ /** The arm's elements, in order; omitted, an empty branch. */
1501
+ body?: ArmBodyFn;
1502
+ };
1503
+ /**
1504
+ * The join gateway a construct emits when more than one arm falls through.
1505
+ *
1506
+ * Its id defaults to `<split>_join`, a pure function of the id the author wrote.
1507
+ * Naming it is for an IMPORT: `decompile --style nested` lifts a flat process's
1508
+ * gateway into `choose` / `fork` / `race`, and the join it finds already has an id
1509
+ * (and often a name) that `merge` and the canvas key on, which the default could
1510
+ * not reproduce.
1511
+ */
1512
+ export interface JoinOpts {
1513
+ /** The join gateway's element id. Defaults to `<split>_join`. */
1514
+ id?: string;
1515
+ /** Display name the designer shows on the join gateway. */
1516
+ name?: string;
1517
+ }
1518
+ /** Options for {@link ScopeBuilder.choose}. */
1519
+ export interface ChooseOpts {
1520
+ /** Display name the designer shows on the splitting gateway. */
1521
+ name?: string;
1522
+ /**
1523
+ * `true` emits an INCLUSIVE gateway — every arm whose `when` holds is taken, not
1524
+ * only the first — and the arms rejoin through an inclusive join.
1525
+ */
1526
+ inclusive?: boolean;
1527
+ /** The join gateway's id and name, when the defaults will not do — see {@link JoinOpts}. */
1528
+ join?: JoinOpts;
1529
+ }
1530
+ /** Options for {@link ScopeBuilder.fork} and {@link ScopeBuilder.race}. */
1531
+ export interface SplitOpts {
1532
+ /** Display name the designer shows on the splitting gateway. */
1533
+ name?: string;
1534
+ /** The join gateway's id and name, when the defaults will not do — see {@link JoinOpts}. */
1535
+ join?: JoinOpts;
1536
+ }
1537
+ /**
1538
+ * Options for {@link ScopeBuilder.eventSubProcess}. Exactly one of `error` /
1539
+ * `message` / `timer` names what starts it.
1540
+ */
1541
+ export interface EventSubProcessOpts {
1542
+ /** Display name the designer shows on the sub-process. */
1543
+ name?: string;
1544
+ /**
1545
+ * Start when an error is thrown anywhere in the enclosing container that nothing
1546
+ * closer caught: `true` for any error, or a declared kind — see {@link ErrorLike}.
1547
+ * Always interrupting.
1548
+ */
1549
+ error?: ErrorLike;
1550
+ /** Start when this message arrives while the container is active. */
1551
+ message?: string;
1552
+ /** Start on a timer measured from the container's own start. */
1553
+ timer?: TimerLike;
1554
+ /**
1555
+ * For a `message` or `timer` start: `false` lets the container keep running while
1556
+ * the sub-process handles the event (`isInterrupting="false"`). Defaults to `true`.
1557
+ * Refused with `error`, which BPMN defines as interrupting.
1558
+ */
1559
+ interrupting?: boolean;
1560
+ /**
1561
+ * With `error`: the variable the caught error is captured into, through the same
1562
+ * `=Error` output row {@link ErrorHandlerOpts.errorVar} writes on a boundary,
1563
+ * declared `jsonSchema` and scoped to the start event unless the author declared
1564
+ * that id already.
1565
+ *
1566
+ * Defaults to `` `${id}_Error` ``, so the body reads `=vars.<net>_Error.code`,
1567
+ * `.message`, `.detail`, `.status` with nothing more written.
1568
+ *
1569
+ * It used to default to the bare `'Error'`, which is what the designer calls the
1570
+ * variable but not what it names it. Measured over the five real exports in
1571
+ * `research/bpmn-roundtrip/corpus/`: 285 error captures, every one declared with a
1572
+ * UNIQUE id (`error`, `error2`, `error3`, …) and the display `name="Error"`, and
1573
+ * every expression reading its own — `vars.error18`, `vars.error5`. `vars.Error`
1574
+ * appears exactly 0 times. The `Error` spelling that IS load-bearing is the capture
1575
+ * row's `source="=Error"`, the key the engine seeds the payload under, which is
1576
+ * written for you either way; the row's `var` is free, and the designer keeps it
1577
+ * distinct. A shared id is also wrong on the wire: the runtime resolves `vars.<id>`
1578
+ * in ONE flat scope whatever a declaration's `elementId` says, and two declarations
1579
+ * with one id is `DUPLICATE_DOCUMENT_ID`, so two nets defaulting to `Error` could
1580
+ * only ever share a single slot. `<id>_Error` matches what `.connector()` and the
1581
+ * typed nodes have always written for their own error payload.
1582
+ *
1583
+ * Name something else to choose the id; pass `false` to write no capture row at all,
1584
+ * which is what a decompiled artifact whose error start carries none asks for.
1585
+ */
1586
+ errorVar?: string | false;
1587
+ /** The synthesized start event's id. Defaults to `<id>_start`. */
1588
+ startId?: string;
1589
+ /** Display name the designer shows on the start event. */
1590
+ startName?: string;
1591
+ /** A payload on the start event, spelled out by hand — see {@link ExtensionPayload}. Exclusive with `errorVar`. */
1592
+ startPayload?: ExtensionPayload;
1593
+ /** `uipath:tags` on the sub-process — see {@link ActivityOpts.tags}. */
1594
+ tags?: Record<string, string>;
1595
+ /** A `uipath:mapping` on the sub-process itself — see {@link SubProcessOpts.payload}. */
1596
+ payload?: ExtensionPayload;
1597
+ }
1598
+ /**
1599
+ * How a scope wires elements no explicit `.sequenceFlow()` covers — see
1600
+ * {@link ScopeBuilder.flowMode}.
1601
+ *
1602
+ * `explicit`, the default for the process root and every `.subProcess()` body: nothing
1603
+ * is implied between siblings, and only the exits of a nested construct (a `choose`, a
1604
+ * handler) continue to the next element placed. `sequence`: consecutive elements are
1605
+ * wired in order. The inside of an arm, a handler and an `eventSubProcess` body is
1606
+ * always `sequence`.
1607
+ */
1608
+ export type FlowMode = 'explicit' | 'sequence';
1609
+ /** The builder-internal spelling of {@link FlowMode}, kept so the field types read as what they are. */
1610
+ type WiringMode = FlowMode;
1611
+ /** A gateway node of the built graph. */
1612
+ type GatewayNode = Extract<BpmnNode, {
1613
+ kind: GatewayKind;
1614
+ }>;
1615
+ /**
1616
+ * An edge waiting for the element that continues it: the open end of an arm, a
1617
+ * handler, or a join, plus what the flow should carry when it is finally written.
1618
+ */
1619
+ interface PendingExit {
1620
+ /** The element the edge leaves. */
1621
+ source: string;
1622
+ /** Condition to put on the flow — an empty arm's `when`. */
1623
+ condition?: string;
1624
+ /** Label to put on the flow. */
1625
+ name?: string;
1626
+ /** The gateway whose `default` must name the flow once it exists — an `otherwise` arm. */
1627
+ defaultOf?: GatewayNode;
1628
+ /**
1629
+ * Where this exit came from — an arm, a handler, a join — for the message when
1630
+ * nothing ever consumes it. Absent for the plain tail of a sequence, which is
1631
+ * described by the scope it is in.
1632
+ */
1633
+ origin?: string;
1634
+ }
1635
+ /** The arrays an arm shares with the scope it is written into. */
1636
+ interface ScopeStorage {
1637
+ /** The scope's elements, in placement order. */
1638
+ nodes: BpmnNode[];
1639
+ /** The scope's sequence flows, explicit and implied alike. */
1640
+ flows: BpmnFlow[];
1641
+ /** The variables declared in the scope. */
1642
+ vars: BpmnVarDecl[];
1643
+ /** Elements whose path must be ended or wired by hand, checked when the real scope closes. */
1644
+ mustClose: Array<{
1645
+ id: string;
1646
+ reason: string;
1647
+ }>;
1648
+ }
1649
+ /** Bookkeeping the nesting sugar shares across every scope of one process. */
1650
+ declare class SugarRegistry {
1651
+ /** Flow ids the builder wrote by implication rather than from an explicit `.sequenceFlow()`. */
1652
+ readonly impliedFlowIds: Set<string>;
1653
+ /**
1654
+ * Ids to give implied edges, keyed `source\u0000target` — see {@link ScopeBuilder.flowIds}.
1655
+ *
1656
+ * An implied edge has no call of its own, so there is nowhere to name it and its id
1657
+ * is derived. This is the one place an author (in practice, `decompile`) can say what
1658
+ * a derived id should be instead.
1659
+ */
1660
+ readonly pinnedFlowIds: Map<string, string>;
1661
+ /** Variables an `errorVar` asked for — declared at build unless the author declared the id. */
1662
+ readonly autoVars: Array<{
1663
+ id: string;
1664
+ vars: BpmnVarDecl[];
1665
+ elementId: string;
1666
+ }>;
1667
+ }
1668
+ /**
1669
+ * Whether the node serializes to a start event — nothing may flow INTO it.
1670
+ *
1671
+ * Exported because `graph.ts` needs the SAME answer: `check --graph` decides what is
1672
+ * `[NO INCOMING]` and what is merely an entry point, and a second copy of this test
1673
+ * drifted — it missed the `typed` arm, so a registry type whose element IS a start
1674
+ * event was reported unreachable.
1675
+ *
1676
+ * @param n - The node.
1677
+ * @returns True when the node is an entry point of its own.
1678
+ * @internal
1679
+ */
1680
+ export declare function isStartLike(n: BpmnNode): boolean;
1256
1681
  /**
1257
1682
  * Collects `uipath:binding` declarations, de-duped by id.
1258
1683
  *
@@ -1318,14 +1743,160 @@ declare abstract class ScopeBuilder {
1318
1743
  protected readonly _defs: DefinitionsRegistry;
1319
1744
  /** @internal */
1320
1745
  protected readonly _bindingRegistry: BindingsRegistry;
1746
+ /** @internal */
1747
+ protected readonly _storage: ScopeStorage;
1748
+ /** @internal */
1749
+ protected readonly _sugar: SugarRegistry;
1750
+ /** @internal How THIS scope wires siblings — an arm's is always `sequence`. */
1751
+ protected _mode: WiringMode;
1752
+ /** @internal The mode of the real scope this builder writes into, which a nested `.subProcess()` inherits. */
1753
+ protected _scopeMode: WiringMode;
1754
+ /** @internal Whether this builder is an arm or handler path rather than a real scope. */
1755
+ protected _isArm: boolean;
1756
+ /** @internal The id of a start event the builder synthesized for this scope (an event sub-process body). */
1757
+ protected _synthesizedStart?: string;
1758
+ /** @internal Elements placed in a `sequence` scope with nothing leading into them, checked at close. */
1759
+ protected readonly _unattached: Array<{
1760
+ id: string;
1761
+ after: string;
1762
+ }>;
1763
+ /** @internal Edges waiting for the element that continues them. */
1764
+ protected _open: PendingExit[];
1765
+ /** @internal Whether anything has been placed yet, so an unreachable element can be told from the first. */
1766
+ protected _started: boolean;
1767
+ /** @internal What left this path for good (`.goto()`), after which nothing may follow. */
1768
+ protected _closedBy?: string;
1321
1769
  /**
1322
1770
  * @param defs - Definitions-level message/error declarations, shared with every scope.
1323
1771
  * @param bindings - `uipath:binding` declarations, shared so a typed node can
1324
1772
  * declare one from inside a sub-process.
1773
+ * @param storage - The arrays to write into; an arm shares its enclosing scope's,
1774
+ * a real scope gets its own.
1775
+ * @param mode - How siblings no explicit flow covers are wired — see `WiringMode`.
1776
+ * @param sugar - Process-wide bookkeeping for the nesting sugar.
1325
1777
  * @returns The scope builder.
1326
1778
  */
1327
- constructor(defs: DefinitionsRegistry, bindings: BindingsRegistry);
1779
+ constructor(defs: DefinitionsRegistry, bindings: BindingsRegistry, storage?: ScopeStorage, mode?: WiringMode, sugar?: SugarRegistry);
1780
+ /**
1781
+ * Choose how this scope wires the elements no explicit `.sequenceFlow()` covers.
1782
+ *
1783
+ * @remarks
1784
+ * `'explicit'` is the default: siblings are not wired to each other, only the exits
1785
+ * of a nested construct continue to the next element. `'sequence'` wires consecutive
1786
+ * siblings in order, so a linear process needs no `.sequenceFlow()` at all.
1787
+ *
1788
+ * Three rules keep `'sequence'` local and reviewable. **Explicit wins**: an element
1789
+ * that already has an explicit outgoing flow is not also wired to the next one, so a
1790
+ * hand-written edge never gains a silent twin. **A bare gateway implies nothing
1791
+ * outward**: it is wired into, but its outgoing flows are yours to write (or use
1792
+ * `.choose()` / `.fork()` / `.race()`, which imply theirs). **Nothing dangles
1793
+ * silently**: an element nothing leads into, or a path that does not end, is refused
1794
+ * at `.build()` rather than emitted. `bpmn check --graph` prints the wiring that
1795
+ * resulted, implied edges marked, so a change can be reviewed against what was
1796
+ * inferred rather than what was typed.
1797
+ *
1798
+ * Must come before the scope's first element. A `.subProcess()` body inherits its
1799
+ * enclosing scope's mode and may set its own; an arm or handler body is always
1800
+ * `sequence` and refuses the call.
1801
+ *
1802
+ * @example
1803
+ * **A linear process with no sequence flows written**
1804
+ * ```ts
1805
+ * bpmn('intake')
1806
+ * .flowMode('sequence')
1807
+ * .var('note', 'string', { default: '' })
1808
+ * .startEvent('start')
1809
+ * .task('assign', { set: { note: 'hello' } })
1810
+ * .scriptTask('log', { script: 'return note;', inputs: { note: '=vars.note' } })
1811
+ * .endEvent('done')
1812
+ * .build();
1813
+ * ```
1814
+ *
1815
+ * @param mode - `'explicit'` or `'sequence'`.
1816
+ * @returns This builder, so calls chain.
1817
+ * @throws If called inside an arm or handler body, or after an element has been placed.
1818
+ */
1819
+ flowMode(mode: FlowMode): this;
1328
1820
  private push;
1821
+ /**
1822
+ * Place an activity and run its body, in which boundary events are declared.
1823
+ *
1824
+ * @param node - The activity node.
1825
+ * @param body - Its boundary handlers, if any.
1826
+ * @returns This builder, so calls chain.
1827
+ */
1828
+ private pushActivity;
1829
+ /**
1830
+ * Place a node: wire every pending exit into it, record it, and — in a
1831
+ * `sequence` scope — leave it as the open end the next element continues from.
1832
+ *
1833
+ * @param node - The node to place.
1834
+ * @param viaSugar - Set when the builder itself is placing a gateway it synthesized,
1835
+ * which a `sequence` scope otherwise refuses.
1836
+ * @internal
1837
+ */
1838
+ protected place(node: BpmnNode, viaSugar?: boolean): void;
1839
+ /** Wire every pending exit into `target`, except one the author already wired by hand. */
1840
+ private continueTo;
1841
+ private hasExplicitOutgoing;
1842
+ /**
1843
+ * Write the flow a pending exit stands for, now that its target is known.
1844
+ *
1845
+ * @param exit - The exit.
1846
+ * @param target - The element it flows into.
1847
+ * @internal
1848
+ */
1849
+ protected writeImpliedFlow(exit: PendingExit, target: string): void;
1850
+ /**
1851
+ * Check the implied wiring of a real scope once its author's function has
1852
+ * returned: every path a handler had to end has ended, and every exit a construct
1853
+ * left open reached something.
1854
+ *
1855
+ * @param what - The scope, for the message.
1856
+ * @internal
1857
+ */
1858
+ protected closeScope(what: string): void;
1859
+ /**
1860
+ * The definitions registry, for the activity builder to intern a message or error.
1861
+ *
1862
+ * @returns The registry shared by every scope of this process.
1863
+ * @internal
1864
+ */
1865
+ _defsOf(): DefinitionsRegistry;
1866
+ /**
1867
+ * This scope's variable declarations, for an `errorVar` to be declared into.
1868
+ *
1869
+ * @returns The array the scope declares variables into.
1870
+ * @internal
1871
+ */
1872
+ _varsOf(): BpmnVarDecl[];
1873
+ /**
1874
+ * Attach a boundary event to an activity of this scope and run its handler path.
1875
+ *
1876
+ * @param activityId - The activity the boundary attaches to.
1877
+ * @param suffix - `onError` / `onTimer` / `onMessage`, for the derived id.
1878
+ * @param spec - The event definition and the options it came with.
1879
+ * @param body - The handler path.
1880
+ * @internal
1881
+ */
1882
+ _attach(activityId: string, suffix: 'onError' | 'onTimer' | 'onMessage', spec: {
1883
+ event: EventDef;
1884
+ interrupting: boolean;
1885
+ opts: HandlerOpts & {
1886
+ errorVar?: string;
1887
+ };
1888
+ }, body: ArmBodyFn | undefined): void;
1889
+ /**
1890
+ * The shared lowering of `choose` / `fork` / `race`: a splitting gateway, one
1891
+ * arm per branch, and a join only when more than one arm falls through.
1892
+ *
1893
+ * @param split - The gateway that opens the construct.
1894
+ * @param joinKind - The gateway kind that closes it, when one is needed.
1895
+ * @param arms - Each arm's entry edge and body.
1896
+ * @param what - The construct, for messages.
1897
+ * @param mustWait - `race`: each arm has to begin with something that waits.
1898
+ */
1899
+ private branch;
1329
1900
  /**
1330
1901
  * A start event (authorable definitions: none / message / timer).
1331
1902
  *
@@ -1417,17 +1988,19 @@ declare abstract class ScopeBuilder {
1417
1988
  *
1418
1989
  * @param id - The element id, unique in the process and used by `sequenceFlow`.
1419
1990
  * @param opts - The Jint JavaScript `script`, and its input/output mappings.
1991
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1420
1992
  * @returns This builder, so calls chain.
1421
1993
  */
1422
- scriptTask(id: string, opts: ScriptTaskOpts): this;
1994
+ scriptTask(id: string, opts: ScriptTaskOpts, body?: ActivityBodyFn): this;
1423
1995
  /**
1424
1996
  * A plain task that assigns variables (`BPMN.Variables`).
1425
1997
  *
1426
1998
  * @param id - The element id, unique in the process and used by `sequenceFlow`.
1427
1999
  * @param opts - `name`, and the variable assignments the task makes.
2000
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1428
2001
  * @returns This builder, so calls chain.
1429
2002
  */
1430
- task(id: string, opts?: TaskOpts): this;
2003
+ task(id: string, opts?: TaskOpts, body?: ActivityBodyFn): this;
1431
2004
  /**
1432
2005
  * A task element carrying NO `uipath:*` payload — an abstract task, in BPMN's terms.
1433
2006
  *
@@ -1446,6 +2019,7 @@ declare abstract class ScopeBuilder {
1446
2019
  *
1447
2020
  * @param id - The element id, unique in the process and used by `sequenceFlow`.
1448
2021
  * @param opts - `name`, and which task `element` to emit (default `bpmn:task`).
2022
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1449
2023
  * @returns This builder, so calls chain.
1450
2024
  *
1451
2025
  * @example
@@ -1456,7 +2030,7 @@ declare abstract class ScopeBuilder {
1456
2030
  * .endEvent('e')
1457
2031
  * ```
1458
2032
  */
1459
- plainTask(id: string, opts?: PlainTaskOpts): this;
2033
+ plainTask(id: string, opts?: PlainTaskOpts, body?: ActivityBodyFn): this;
1460
2034
  /**
1461
2035
  * An Integration Service **connector** service task (`bpmn:sendTask` +
1462
2036
  * `uipath:activity` / `Intsvc.ActivityExecution`) — the typed form, where a
@@ -1474,9 +2048,10 @@ declare abstract class ScopeBuilder {
1474
2048
  * @param inputs - The activity's inputs, typed by the descriptor.
1475
2049
  * @param opts - `name`, plus symbolic `connection` / `folder`, an action
1476
2050
  * `version`, and the `object` a generic operation addresses.
2051
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1477
2052
  * @returns This builder, so calls chain.
1478
2053
  */
1479
- connector<I extends Record<string, unknown>, O>(id: string, descriptor: ConnectorDescriptor<I, O>, inputs: I, opts?: BpmnConnectorOpts): this;
2054
+ connector<I extends Record<string, unknown>, O>(id: string, descriptor: ConnectorDescriptor<I, O>, inputs: I, opts?: BpmnConnectorOpts, body?: ActivityBodyFn): this;
1480
2055
  /**
1481
2056
  * Stringly form, for a connector with no prepared module.
1482
2057
  *
@@ -1486,9 +2061,10 @@ declare abstract class ScopeBuilder {
1486
2061
  * @param inputs - The activity's inputs.
1487
2062
  * @param opts - `name`, plus symbolic `connection` / `folder`, an action
1488
2063
  * `version`, and the `object` a generic operation addresses.
2064
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1489
2065
  * @returns This builder, so calls chain.
1490
2066
  */
1491
- connector(id: string, key: string, action: string, inputs?: Record<string, unknown>, opts?: BpmnConnectorOpts): this;
2067
+ connector(id: string, key: string, action: string, inputs?: Record<string, unknown>, opts?: BpmnConnectorOpts, body?: ActivityBodyFn): this;
1492
2068
  /**
1493
2069
  * An **HTTP request** service task (`bpmn:sendTask` +
1494
2070
  * `uipath:activity` / `Intsvc.UnifiedHttpRequest`).
@@ -1520,9 +2096,44 @@ declare abstract class ScopeBuilder {
1520
2096
  *
1521
2097
  * @param id - The element id, unique in the process and used by `sequenceFlow`.
1522
2098
  * @param opts - The request, plus `name`, `outputVar`, and the shared activity options.
2099
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1523
2100
  * @returns This builder, so calls chain.
1524
2101
  */
1525
- http(id: string, opts: HttpOpts): this;
2102
+ http(id: string, opts: HttpOpts, body?: ActivityBodyFn): this;
2103
+ /**
2104
+ * A UiPath **Data Fabric** (Data Service) record or file operation — create,
2105
+ * update, get, query, delete a record, or download / upload / delete a record's
2106
+ * file field — as an `Intsvc.ActivityExecution` send task in the exact shape the
2107
+ * Flow→BPMN converter and Studio Web write.
2108
+ *
2109
+ * @remarks
2110
+ * The connector library ships one Data Service operation, so `.connector()` cannot
2111
+ * author the rest, and hand-filling `.activity('Intsvc.ActivityExecution', …)` gets
2112
+ * the wire details wrong in ways `validate` does not catch (a `recordId` in the body,
2113
+ * a curated `objectName` on an entity-form path, a folder binding keyed by the folder).
2114
+ * This writes each of the eight operations the way the platform's own tools do:
2115
+ * create and update in the ENTITY form (`POST /<Entity>`, `PUT /<Entity>/{id}`,
2116
+ * `objectName` = the entity), the others in the CURATED form (`entityName` as a
2117
+ * path parameter, `objectName` = the curated operation), every parameter its own
2118
+ * `path` / `query` / `file` row and the record as the one json `body` row. Needs no
2119
+ * connector library at compile time.
2120
+ *
2121
+ * The response lands in `outputVar` (default `<id>_response`) and the error payload in
2122
+ * `<id>_Error`, both declared for you.
2123
+ *
2124
+ * @param id - The element id, unique in the process and used by `sequenceFlow`.
2125
+ * @param opts - The entity, connection and folder, plus the operation and its parameters — see {@link DataServiceOpts} and {@link DataServiceOperation}.
2126
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
2127
+ * @returns This builder, so calls chain.
2128
+ */
2129
+ dataService(id: string, opts: DataServiceOpts & DataServiceOperation, body?: ActivityBodyFn): this;
2130
+ /**
2131
+ * @internal Resolve a `.dataService()` connection or folder to a `=bindings.<id>`
2132
+ * reference: an existing binding by id, else one already declared for the same
2133
+ * key, else a new one declared on the author's behalf. `companionKey` is the
2134
+ * connection's key a folder binding must carry as its `resourceKey`.
2135
+ */
2136
+ private dataServiceBinding;
1526
2137
  /**
1527
2138
  * @internal Turn a literal into a binding reference where the platform demands
1528
2139
  * one, declaring the binding on the author's behalf.
@@ -1555,35 +2166,39 @@ declare abstract class ScopeBuilder {
1555
2166
  *
1556
2167
  * @param id - The element id, unique in the process and used by `sequenceFlow`.
1557
2168
  * @param opts - Which process, folder, and input arguments.
2169
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1558
2170
  * @returns This builder, so calls chain.
1559
2171
  */
1560
- startProcess(id: string, opts: OrchestratorOpts): this;
2172
+ startProcess(id: string, opts: OrchestratorOpts, body?: ActivityBodyFn): this;
1561
2173
  /**
1562
2174
  * Start an **agent** and wait for it (`Orchestrator.StartAgentJob`).
1563
2175
  *
1564
2176
  * @param id - The element id, unique in the process and used by `sequenceFlow`.
1565
2177
  * @param opts - Which agent process, folder, and input arguments.
2178
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1566
2179
  * @returns This builder, so calls chain.
1567
2180
  */
1568
- startAgent(id: string, opts: OrchestratorOpts): this;
2181
+ startAgent(id: string, opts: OrchestratorOpts, body?: ActivityBodyFn): this;
1569
2182
  /**
1570
2183
  * Invoke an **agentic process** as a call activity
1571
2184
  * (`Orchestrator.StartAgenticProcess`, or `…Async` when `async` is set).
1572
2185
  *
1573
2186
  * @param id - The element id, unique in the process and used by `sequenceFlow`.
1574
2187
  * @param opts - Which process, folder, input arguments, and whether to wait.
2188
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1575
2189
  * @returns This builder, so calls chain.
1576
2190
  */
1577
- startAgenticProcess(id: string, opts: OrchestratorAsyncOpts): this;
2191
+ startAgenticProcess(id: string, opts: OrchestratorAsyncOpts, body?: ActivityBodyFn): this;
1578
2192
  /**
1579
2193
  * Invoke a **case-management process** as a call activity
1580
2194
  * (`Orchestrator.StartCaseMgmtProcess`, or `…Async` when `async` is set).
1581
2195
  *
1582
2196
  * @param id - The element id, unique in the process and used by `sequenceFlow`.
1583
2197
  * @param opts - Which case process, folder, input arguments, and whether to wait.
2198
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1584
2199
  * @returns This builder, so calls chain.
1585
2200
  */
1586
- startCaseProcess(id: string, opts: OrchestratorAsyncOpts): this;
2201
+ startCaseProcess(id: string, opts: OrchestratorAsyncOpts, body?: ActivityBodyFn): this;
1587
2202
  /**
1588
2203
  * Execute an **API workflow**, fire-and-forget
1589
2204
  * (`Orchestrator.ExecuteApiWorkflowAsync`).
@@ -1594,9 +2209,10 @@ declare abstract class ScopeBuilder {
1594
2209
  *
1595
2210
  * @param id - The element id, unique in the process and used by `sequenceFlow`.
1596
2211
  * @param opts - Which workflow, folder, and input arguments.
2212
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1597
2213
  * @returns This builder, so calls chain.
1598
2214
  */
1599
- executeApiWorkflow(id: string, opts: OrchestratorOpts): this;
2215
+ executeApiWorkflow(id: string, opts: OrchestratorOpts, body?: ActivityBodyFn): this;
1600
2216
  /**
1601
2217
  * Execute a **business rule** and wait for it (`Orchestrator.BusinessRules`, on a
1602
2218
  * `bpmn:businessRuleTask`).
@@ -1640,9 +2256,10 @@ declare abstract class ScopeBuilder {
1640
2256
  * @param opts - Which rule package, folder, and input arguments. `outputVar` defaults
1641
2257
  * to `<id>_businessRuleResponse` — see the note in the implementation for why this one
1642
2258
  * type does not take its default from the spec.
2259
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1643
2260
  * @returns This builder, so calls chain.
1644
2261
  */
1645
- businessRule(id: string, opts: OrchestratorOpts): this;
2262
+ businessRule(id: string, opts: OrchestratorOpts, body?: ActivityBodyFn): this;
1646
2263
  /**
1647
2264
  * Add an item to an Orchestrator **queue** (`Orchestrator.CreateQueueItem`, or
1648
2265
  * `Orchestrator.CreateAndWaitForQueueItem` when `wait` is set).
@@ -1660,9 +2277,10 @@ declare abstract class ScopeBuilder {
1660
2277
  *
1661
2278
  * @param id - The element id, unique in the process and used by `sequenceFlow`.
1662
2279
  * @param opts - Which queue and folder, the item content, and whether to wait for it.
2280
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1663
2281
  * @returns This builder, so calls chain.
1664
2282
  */
1665
- queueItem(id: string, opts: QueueItemOpts): this;
2283
+ queueItem(id: string, opts: QueueItemOpts, body?: ActivityBodyFn): this;
1666
2284
  /**
1667
2285
  * A **human task** — an Action App task a person completes (`bpmn:userTask` +
1668
2286
  * `uipath:activity` / `Actions.HITL`).
@@ -1711,9 +2329,10 @@ declare abstract class ScopeBuilder {
1711
2329
  * @param id - The element id, unique in the process and used by `sequenceFlow`.
1712
2330
  * @param opts - The app, the outcomes offered, what the human sees, and which
1713
2331
  * response fields to keep.
2332
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1714
2333
  * @returns This builder, so calls chain.
1715
2334
  */
1716
- humanTask(id: string, opts: HumanTaskOpts): this;
2335
+ humanTask(id: string, opts: HumanTaskOpts, body?: ActivityBodyFn): this;
1717
2336
  /**
1718
2337
  * Wait for an internal message from another Maestro process
1719
2338
  * (`Maestro.ReceiveMessageEvent` on a `bpmn:intermediateCatchEvent`).
@@ -1751,9 +2370,10 @@ declare abstract class ScopeBuilder {
1751
2370
  *
1752
2371
  * @param id - The element id, unique in the process and used by `sequenceFlow`.
1753
2372
  * @param opts - The message name, the correlation reference, and what to keep.
2373
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1754
2374
  * @returns This builder, so calls chain.
1755
2375
  */
1756
- receiveMessage(id: string, opts: ReceiveMessageOpts): this;
2376
+ receiveMessage(id: string, opts: ReceiveMessageOpts, body?: ActivityBodyFn): this;
1757
2377
  /**
1758
2378
  * Wait mid-flow for an Integration Service connector event
1759
2379
  * (`Intsvc.WaitForEvent` on a `bpmn:receiveTask`).
@@ -1792,9 +2412,10 @@ declare abstract class ScopeBuilder {
1792
2412
  * @param connector - The connector key, e.g. `'uipath-microsoft-outlook365'`.
1793
2413
  * @param event - The event name, e.g. `'email-received'`.
1794
2414
  * @param opts - Connection/folder bindings, the `where` scope, and what to keep.
2415
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1795
2416
  * @returns This builder, so calls chain.
1796
2417
  */
1797
- waitForEvent(id: string, connector: string, event: string, opts: ConnectorEventOpts): this;
2418
+ waitForEvent(id: string, connector: string, event: string, opts: ConnectorEventOpts, body?: ActivityBodyFn): this;
1798
2419
  /**
1799
2420
  * START the process when an Integration Service connector event fires
1800
2421
  * (`Intsvc.EventTrigger` on a `bpmn:startEvent` carrying a message event
@@ -1851,9 +2472,10 @@ declare abstract class ScopeBuilder {
1851
2472
  * @param action - The `AgentExecution` operation name.
1852
2473
  * @param inputs - The invocation payload.
1853
2474
  * @param opts - `mode`, the connection/folder bindings, and what to keep.
2475
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1854
2476
  * @returns This builder, so calls chain.
1855
2477
  */
1856
- externalAgent(id: string, connector: string, action: string, inputs: Record<string, unknown>, opts: ExternalTaskOpts): this;
2478
+ externalAgent(id: string, connector: string, action: string, inputs: Record<string, unknown>, opts: ExternalTaskOpts, body?: ActivityBodyFn): this;
1857
2479
  /**
1858
2480
  * Invoke an external workflow through an Integration Service connector
1859
2481
  * (`Intsvc.SyncWorkflowExecution` / `Intsvc.AsyncWorkflowExecution`).
@@ -1867,9 +2489,10 @@ declare abstract class ScopeBuilder {
1867
2489
  * @param action - The `ProcessExecution` operation name.
1868
2490
  * @param inputs - The invocation payload.
1869
2491
  * @param opts - `mode`, the connection/folder bindings, and what to keep.
2492
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1870
2493
  * @returns This builder, so calls chain.
1871
2494
  */
1872
- externalWorkflow(id: string, connector: string, action: string, inputs: Record<string, unknown>, opts: ExternalTaskOpts): this;
2495
+ externalWorkflow(id: string, connector: string, action: string, inputs: Record<string, unknown>, opts: ExternalTaskOpts, body?: ActivityBodyFn): this;
1873
2496
  /** @internal Shared body of the two external-invocation methods. */
1874
2497
  private externalTask;
1875
2498
  /**
@@ -1902,18 +2525,217 @@ declare abstract class ScopeBuilder {
1902
2525
  * @param id - The element id, unique in the process and used by `sequenceFlow`.
1903
2526
  * @param type - The registry extension type, e.g. `'A2A.AgentExecution'`.
1904
2527
  * @param opts - Context values, payload, output mapping and the shared activity options.
2528
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1905
2529
  * @returns This builder, so calls chain.
1906
2530
  */
1907
- activity(id: string, type: string, opts?: ActivityNodeOpts): this;
2531
+ activity(id: string, type: string, opts?: ActivityNodeOpts, body?: ActivityBodyFn): this;
1908
2532
  /**
1909
2533
  * A sub-process — a scope of its own, with its own elements and flows (`bpmn:subProcess`).
1910
2534
  *
1911
2535
  * @param id - The element id, unique in the process and used by `sequenceFlow`.
1912
2536
  * @param fn - Receives a sub-builder for the elements inside it.
1913
2537
  * @param opts - `name`, and the loop characteristics when it repeats.
2538
+ * @param body - Boundary events attached to this activity, declared on the {@link ActivityBuilder} it receives.
1914
2539
  * @returns This builder, so calls chain.
1915
2540
  */
1916
- subProcess(id: string, fn: (sp: SubProcessBuilder) => void, opts?: SubProcessOpts): this;
2541
+ subProcess(id: string, fn: (sp: SubProcessBuilder) => void, opts?: SubProcessOpts, body?: ActivityBodyFn): this;
2542
+ /**
2543
+ * An EVENT sub-process — a handler that lives inside this scope and starts when
2544
+ * an error, a message, or a timer occurs anywhere in it (`bpmn:subProcess
2545
+ * triggeredByEvent="true"`, with its single start event synthesized).
2546
+ *
2547
+ * @remarks
2548
+ * The construct BPMN has for a safety net: it has no incoming flow, and it
2549
+ * catches what nothing closer to the failing element caught. Distinct from a
2550
+ * boundary handler (`.onError()` on one activity), which guards one element; this
2551
+ * guards the whole container it sits in, so where it sits is what it guards — put
2552
+ * it inside a multi-instance sub-process to fail one iteration rather than the
2553
+ * whole run.
2554
+ *
2555
+ * Its body is written in order: elements chain from the synthesized start, and
2556
+ * branch with `.choose()` / `.fork()` / `.race()`. Every path must end — with an
2557
+ * end event or an explicit `.sequenceFlow()` off its last element — because an
2558
+ * event sub-process has nowhere else to go.
2559
+ *
2560
+ * @example
2561
+ * **A central failure net that classifies on the error it caught**
2562
+ * ```ts
2563
+ * bpmn('payroll')
2564
+ * .var('outcome', 'string', { default: 'RUNNING' })
2565
+ * .startEvent('start')
2566
+ * .scriptTask('calculate', { script: 'return { ok: true };' })
2567
+ * .endEvent('done')
2568
+ * .sequenceFlow('start', 'calculate')
2569
+ * .sequenceFlow('calculate', 'done')
2570
+ * .eventSubProcess('failures', { error: true, name: 'Failure net' }, (h) =>
2571
+ * h.choose('kind', [
2572
+ * {
2573
+ * // The start captures the error into `vars.Error` by default (`errorVar`).
2574
+ * when: '=js:String(vars.Error.code).indexOf("DATA") >= 0',
2575
+ * label: 'Bad data',
2576
+ * body: (b) => b.task('flagData', { set: { outcome: 'FAILED_BAD_DATA' } }).endEvent('badData', { name: 'Bad data handled' }),
2577
+ * },
2578
+ * {
2579
+ * otherwise: true,
2580
+ * label: 'Outage',
2581
+ * body: (b) => b.task('flagOutage', { set: { outcome: 'FAILED_OUTAGE' } }).endEvent('outage', { name: 'Outage escalated' }),
2582
+ * },
2583
+ * ]),
2584
+ * )
2585
+ * .build();
2586
+ * ```
2587
+ *
2588
+ * @param id - The sub-process's element id. The start event is `<id>_start` unless `startId` says otherwise.
2589
+ * @param opts - What starts it — exactly one of `error` / `message` / `timer` — and the rest of {@link EventSubProcessOpts}.
2590
+ * @param fn - Receives the body builder; elements chain in the order they are written.
2591
+ * @returns This builder, so calls chain.
2592
+ * @throws If none or several of `error` / `message` / `timer` are given, if an error start
2593
+ * is asked to be non-interrupting, or if a path in the body is left open.
2594
+ */
2595
+ eventSubProcess(id: string, opts: EventSubProcessOpts, fn: (sp: SubProcessBuilder) => void): this;
2596
+ /**
2597
+ * An exclusive decision whose arms are written in place — the splitting gateway,
2598
+ * each arm's conditioned flow, the arm's elements and the rejoining gateway, from
2599
+ * one call.
2600
+ *
2601
+ * @remarks
2602
+ * Each arm has a `when` condition or is the single `otherwise` fallback, so an arm
2603
+ * with no condition cannot be written, and the fallback is the gateway's default
2604
+ * flow without anyone naming a flow id. Arms rejoin at the next element placed
2605
+ * after the `choose`; a join gateway (`<id>_join`) is emitted only when more than
2606
+ * one arm actually reaches it, so an arm that ends in an end event adds no join.
2607
+ *
2608
+ * Inside an arm, consecutive elements are wired in order, and an arm may nest
2609
+ * further `choose` / `fork` / `race` calls, activities with boundary handlers, or
2610
+ * `.goto()` to jump to an element written elsewhere. An arm with no body is an
2611
+ * empty branch straight to the continuation.
2612
+ *
2613
+ * @example
2614
+ * **Approve or reject, then carry on**
2615
+ * ```ts
2616
+ * bpmn('review')
2617
+ * .var('action', 'string')
2618
+ * .var('status', 'string')
2619
+ * .startEvent('start')
2620
+ * .task('decide', { set: { action: 'Approved' } })
2621
+ * .choose('approved', [
2622
+ * { when: '=vars.action == "Approved"', label: 'Yes', body: (b) => b.task('post', { set: { status: 'posted' } }) },
2623
+ * { otherwise: true, label: 'No', body: (b) => b.task('reject', { set: { status: 'rejected' } }) },
2624
+ * ])
2625
+ * .endEvent('done')
2626
+ * .sequenceFlow('start', 'decide')
2627
+ * .sequenceFlow('decide', 'approved')
2628
+ * .build();
2629
+ * ```
2630
+ *
2631
+ * @param id - The splitting gateway's element id; the join, when emitted, is `<id>_join`.
2632
+ * @param arms - The arms — see {@link ChooseArm}.
2633
+ * @param opts - `name`, `inclusive` for an inclusive gateway, and `join` to name the join gateway.
2634
+ * @returns This builder, so calls chain.
2635
+ * @throws If there are no arms, more than one `otherwise`, or more than one empty arm.
2636
+ */
2637
+ choose(id: string, arms: ChooseArm[], opts?: ChooseOpts): this;
2638
+ /**
2639
+ * A parallel split whose arms are written in place: every arm runs, and they
2640
+ * rejoin through a parallel join (`<id>_join`) before the next element.
2641
+ *
2642
+ * @example
2643
+ * **Two lookups at once, then one summary**
2644
+ * ```ts
2645
+ * bpmn('enrich')
2646
+ * .startEvent('start')
2647
+ * .fork('gather', [
2648
+ * (b) => b.http('poLookup', { method: 'GET', url: 'https://erp.example.com/po/1' }),
2649
+ * (b) => b.http('vendorLookup', { method: 'GET', url: 'https://erp.example.com/vendor/1' }),
2650
+ * ])
2651
+ * .scriptTask('summarise', { script: 'return { ok: true };' })
2652
+ * .endEvent('done')
2653
+ * .sequenceFlow('start', 'gather')
2654
+ * .sequenceFlow('summarise', 'done')
2655
+ * .build();
2656
+ * ```
2657
+ *
2658
+ * @param id - The splitting gateway's element id; the join is `<id>_join`.
2659
+ * @param arms - One body per parallel arm.
2660
+ * @param opts - `name` for the splitting gateway, and `join` to name the join gateway.
2661
+ * @returns This builder, so calls chain.
2662
+ */
2663
+ fork(id: string, arms: ArmBodyFn[], opts?: SplitOpts): this;
2664
+ /**
2665
+ * An event-based gateway whose arms are written in place: each arm begins with
2666
+ * something to wait for, the first to happen wins, and the rest are cancelled.
2667
+ *
2668
+ * @remarks
2669
+ * An arm must begin with an `intermediateCatchEvent` (message or timer), a
2670
+ * `receiveMessage`, or a `waitForEvent` — that is what the gateway waits on, and
2671
+ * the builder refuses anything else in first position. Arms rejoin through an
2672
+ * exclusive join (`<id>_join`) when more than one falls through.
2673
+ *
2674
+ * @example
2675
+ * **A reply, or a three-day timeout**
2676
+ * ```ts
2677
+ * bpmn('vendor')
2678
+ * .startEvent('start')
2679
+ * .race('waitForEither', [
2680
+ * (b) => b.intermediateCatchEvent('reply', { message: 'VendorReplied' }),
2681
+ * (b) => b.intermediateCatchEvent('timeout', { timer: 'P3D' }).endEvent('gaveUp', { name: 'No reply' }),
2682
+ * ])
2683
+ * .endEvent('done')
2684
+ * .sequenceFlow('start', 'waitForEither')
2685
+ * .build();
2686
+ * ```
2687
+ *
2688
+ * @param id - The gateway's element id; the join, when emitted, is `<id>_join`.
2689
+ * @param arms - One body per alternative, each beginning with the event it waits for.
2690
+ * @param opts - `name` for the gateway, and `join` to name the join gateway.
2691
+ * @returns This builder, so calls chain.
2692
+ * @throws If an arm does not begin with something that waits.
2693
+ */
2694
+ race(id: string, arms: ArmBodyFn[], opts?: SplitOpts): this;
2695
+ /**
2696
+ * Give the edges the nesting constructs IMPLY the ids you choose.
2697
+ *
2698
+ * @remarks
2699
+ * A construct's edges have no call of their own — you write `.choose()` or place two
2700
+ * statements in a sequence scope, and the edge between them follows — so there is
2701
+ * nowhere to name one, and its id is derived as `Flow_<source>_<target>`. That is
2702
+ * fine for a new process and wrong for an edited one: a `.bpmn` that came from
2703
+ * somewhere carries ids like `edge_zOoHdO`, and `uip maestro bpmn merge` keys every
2704
+ * element by id, flows included. Re-derive them and the merge treats every flow as
2705
+ * new, deletes the originals, and takes their diagram edges with them — and any
2706
+ * gateway `default` preserved from the original is left naming an id that no longer
2707
+ * exists, which `uip maestro bpmn validate` then rejects.
2708
+ *
2709
+ * So this is how a decompiled process keeps the ids it arrived with while still
2710
+ * being written in the constructs. `bpmn decompile --style nested` emits one call
2711
+ * listing every implied edge whose original id is not the derived one.
2712
+ *
2713
+ * Only implied edges: an explicit `.sequenceFlow()` already takes an `id`, and a
2714
+ * pair listed here that no implied edge ever connects is simply unused.
2715
+ *
2716
+ * @example
2717
+ * **Keep an import's edge ids through a lift**
2718
+ * ```ts
2719
+ * bpmn('orders')
2720
+ * .var('total', 'number', { default: 0 })
2721
+ * .flowIds([
2722
+ * { source: 'Gw_1', target: 'Review', id: 'edge_zOoHdO' },
2723
+ * { source: 'Gw_1', target: 'Pay', id: 'edge_Kp2mQ1' },
2724
+ * ])
2725
+ * .startEvent('Start_1')
2726
+ * .choose('Gw_1', [
2727
+ * { when: '=vars.total > 1000', body: (b) => b.task('Review').goto('Done') },
2728
+ * { otherwise: true, body: (b) => b.task('Pay').goto('Done') },
2729
+ * ])
2730
+ * .endEvent('Done')
2731
+ * .sequenceFlow('Start_1', 'Gw_1')
2732
+ * .build();
2733
+ * ```
2734
+ *
2735
+ * @param entries - The edges to pin, by their endpoints.
2736
+ * @returns This builder, so calls chain.
2737
+ */
2738
+ flowIds(entries: PinnedFlowId[]): this;
1917
2739
  /**
1918
2740
  * A sequence flow from `source` to `target` (1-1 with `bpmn:sequenceFlow`).
1919
2741
  *
@@ -2031,9 +2853,186 @@ export declare function typedNodeDeclaredVars(n: Extract<BpmnNode, {
2031
2853
  export declare function nodeDeclaredVars(n: BpmnNode): string[];
2032
2854
  /** A sub-process body: the same graph methods, plus an internal node builder. */
2033
2855
  export declare class SubProcessBuilder extends ScopeBuilder {
2856
+ /**
2857
+ * Open an event sub-process body on its synthesized start event.
2858
+ *
2859
+ * @param start - The start event node.
2860
+ * @internal
2861
+ */
2862
+ _begin(start: BpmnNode): void;
2863
+ /**
2864
+ * Close a body written in order: every path in it must have ended.
2865
+ *
2866
+ * @param what - The scope, for the message.
2867
+ * @internal
2868
+ */
2869
+ _finishBody(what: string): void;
2034
2870
  /** @internal */
2035
2871
  _buildNode(id: string, opts: SubProcessOpts): BpmnNode;
2036
2872
  }
2873
+ /**
2874
+ * One arm of a `choose` / `fork` / `race`, or one boundary handler's path: the same
2875
+ * graph methods as any scope, written INTO the enclosing scope, with consecutive
2876
+ * elements wired in order.
2877
+ *
2878
+ * @remarks
2879
+ * An arm creates no BPMN scope of its own — its elements and flows belong to the
2880
+ * scope the construct was written in, and variables declared here are that scope's
2881
+ * — so an explicit `.sequenceFlow()` may reach any element of that scope, and
2882
+ * `.goto()` jumps to one without leaving the nesting. Its path ends with an end
2883
+ * event or `.goto()`, or falls through to whatever follows the construct.
2884
+ *
2885
+ * Inside an arm, branch with `.choose()` / `.fork()` / `.race()`; a bare gateway is
2886
+ * refused, because its outgoing flows cannot be implied.
2887
+ */
2888
+ export declare class PathBuilder extends ScopeBuilder {
2889
+ /** @internal The first element placed — what a `race` arm waits on. */
2890
+ _first?: BpmnNode;
2891
+ /**
2892
+ * @param defs - The process's message/error declarations.
2893
+ * @param bindings - The process's bindings.
2894
+ * @param storage - The enclosing scope's arrays, which this arm writes into.
2895
+ * @param sugar - Process-wide bookkeeping for the nesting sugar.
2896
+ * @param entry - The edge(s) this arm continues from.
2897
+ * @param scopeMode - The mode of the real scope the arm writes into, for a nested `.subProcess()` to inherit.
2898
+ * @internal
2899
+ */
2900
+ constructor(defs: DefinitionsRegistry, bindings: BindingsRegistry, storage: ScopeStorage, sugar: SugarRegistry, entry: PendingExit[], scopeMode: WiringMode);
2901
+ /** @internal */
2902
+ protected place(node: BpmnNode, viaSugar?: boolean): void;
2903
+ /**
2904
+ * Leave this arm for an element written elsewhere — a loop back to an earlier
2905
+ * step, a jump into another arm, a shared exit — writing the edge without leaving
2906
+ * the nesting. Nothing may follow it in the arm.
2907
+ *
2908
+ * @example
2909
+ * **Retry from the top when the check fails**
2910
+ * ```ts
2911
+ * bpmn('retrying')
2912
+ * .var('ok', 'boolean')
2913
+ * .startEvent('start')
2914
+ * .scriptTask('attempt', { script: 'return { ok: true };', outputs: { ok: '=result.ok' } })
2915
+ * .choose('worked', [
2916
+ * { when: '=vars.ok == true', body: (b) => b.endEvent('done') },
2917
+ * { otherwise: true, body: (b) => b.goto('attempt') },
2918
+ * ])
2919
+ * .sequenceFlow('start', 'attempt')
2920
+ * .sequenceFlow('attempt', 'worked')
2921
+ * .build();
2922
+ * ```
2923
+ *
2924
+ * @param target - The id of the element to continue at.
2925
+ * @returns This builder; nothing more may be placed on this arm.
2926
+ */
2927
+ goto(target: string): this;
2928
+ /**
2929
+ * Finish the arm and hand its open ends back to the construct that owns it.
2930
+ *
2931
+ * @returns The exits still open — empty when every path ended.
2932
+ * @internal
2933
+ */
2934
+ _finish(): PendingExit[];
2935
+ }
2936
+ /**
2937
+ * The boundary events of one activity, declared on the activity itself — what the
2938
+ * body callback every activity method accepts receives.
2939
+ *
2940
+ * @remarks
2941
+ * `attachedTo` is the receiver: a handler declared here is attached to the activity
2942
+ * whose body it is written in, so a boundary event on nothing, or on a gateway,
2943
+ * cannot be written. Each handler's path is written in place, in order, and
2944
+ * continues as {@link TimerHandlerOpts.interrupting} describes: an interrupting
2945
+ * handler rejoins at the statement after the activity, a non-interrupting one must
2946
+ * end on its own.
2947
+ *
2948
+ * @example
2949
+ * **A human task with a reminder and a failure exit**
2950
+ * ```ts
2951
+ * bpmn('approval')
2952
+ * .var('reminded', 'string')
2953
+ * .startEvent('start')
2954
+ * .humanTask('approve', { app: 'InvoiceApproval', actions: ['Approve', 'Reject'] }, (t) => {
2955
+ * t.onTimer('PT1H', { interrupting: false }, (b) =>
2956
+ * b.task('remind', { set: { reminded: 'true' } }).endEvent('reminded'));
2957
+ * t.onError((b) => b.endEvent('failed', { name: 'Approval failed' }));
2958
+ * })
2959
+ * .endEvent('done')
2960
+ * .sequenceFlow('start', 'approve')
2961
+ * .sequenceFlow('approve', 'done')
2962
+ * .build();
2963
+ * ```
2964
+ */
2965
+ export declare class ActivityBuilder {
2966
+ private readonly scope;
2967
+ private readonly activity;
2968
+ /**
2969
+ * @param scope - The scope the activity was placed in.
2970
+ * @param activity - The activity's id.
2971
+ * @internal
2972
+ */
2973
+ constructor(scope: ScopeBuilder, activity: string);
2974
+ /**
2975
+ * Catch an error the activity throws — any error, or one declared kind — on an
2976
+ * interrupting error boundary, and handle it on the path written here.
2977
+ *
2978
+ * @param body - The handler path; omitted, the error simply continues to the next statement.
2979
+ * @returns This builder, so handlers chain.
2980
+ */
2981
+ onError(body?: ArmBodyFn): this;
2982
+ /**
2983
+ * Catch a specific error — see {@link ErrorLike} — or `true` for any.
2984
+ *
2985
+ * @param error - What to catch.
2986
+ * @param body - The handler path.
2987
+ * @returns This builder, so handlers chain.
2988
+ */
2989
+ onError(error: ErrorLike, body?: ArmBodyFn): this;
2990
+ /**
2991
+ * Catch an error with options — an `id`, a `name`, an `errorVar` to capture it into.
2992
+ *
2993
+ * @param error - What to catch: `true` for any error, or a declared kind.
2994
+ * @param opts - See {@link ErrorHandlerOpts}.
2995
+ * @param body - The handler path.
2996
+ * @returns This builder, so handlers chain.
2997
+ */
2998
+ onError(error: ErrorLike, opts: ErrorHandlerOpts, body?: ArmBodyFn): this;
2999
+ /**
3000
+ * Fire a timer while the activity runs — a deadline that cancels it, or a
3001
+ * reminder that does not (`interrupting: false`).
3002
+ *
3003
+ * @param timer - An ISO-8601 duration string, or a full {@link TimerSpec}.
3004
+ * @param body - The handler path.
3005
+ * @returns This builder, so handlers chain.
3006
+ */
3007
+ onTimer(timer: TimerLike, body?: ArmBodyFn): this;
3008
+ /**
3009
+ * Fire a timer with options — `interrupting`, an `id`, a `name`.
3010
+ *
3011
+ * @param timer - An ISO-8601 duration string, or a full {@link TimerSpec}.
3012
+ * @param opts - See {@link TimerHandlerOpts}.
3013
+ * @param body - The handler path.
3014
+ * @returns This builder, so handlers chain.
3015
+ */
3016
+ onTimer(timer: TimerLike, opts: TimerHandlerOpts, body?: ArmBodyFn): this;
3017
+ /**
3018
+ * Catch a message while the activity runs — declaring or reusing the
3019
+ * definitions-level `bpmn:message`.
3020
+ *
3021
+ * @param message - The message's name.
3022
+ * @param body - The handler path.
3023
+ * @returns This builder, so handlers chain.
3024
+ */
3025
+ onMessage(message: string, body?: ArmBodyFn): this;
3026
+ /**
3027
+ * Catch a message with options — `interrupting`, an `id`, a `name`.
3028
+ *
3029
+ * @param message - The message's name.
3030
+ * @param opts - See {@link MessageHandlerOpts}.
3031
+ * @param body - The handler path.
3032
+ * @returns This builder, so handlers chain.
3033
+ */
3034
+ onMessage(message: string, opts: MessageHandlerOpts, body?: ArmBodyFn): this;
3035
+ }
2037
3036
  /**
2038
3037
  * The top-level process builder `bpmn()` returns — every graph method of the
2039
3038
  * shared scope (events, gateways, tasks, sub-processes, flows, variables) plus