@uipath/maestro-builder-sdk 6.68.4 → 6.68.5

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.
@@ -437,9 +437,10 @@ export type ConnectorSpecData = Extract<ActionSpec, {
437
437
  * and `hybrid` as `Async…Execution`, and writes the value itself into the task's
438
438
  * `executionType` context.
439
439
  *
440
- * `hybrid` is refused for now (EXTERNAL_TASK_HYBRID_UNSUPPORTED): the Designer
441
- * also writes an event pair for it (`operation`, `eventMode`) that the connector
442
- * library does not carry (#1387). Add a task on a hybrid object in Studio Web.
440
+ * An `async` or `hybrid` object also answers through an event, which the
441
+ * Designer saves next to it; pass that pair as {@link ExternalTaskOptions.event}.
442
+ * A `hybrid` task without it is refused (EXTERNAL_TASK_EVENT), since the task
443
+ * would have nothing to wait on.
443
444
  *
444
445
  * It does not decide whether the stage waits for the task. A task the stage must
445
446
  * not wait on is `.required(false)`, whatever its execution type. For example, a
@@ -447,6 +448,27 @@ export type ConnectorSpecData = Extract<ActionSpec, {
447
448
  * it.
448
449
  */
449
450
  export type ExternalExecutionMode = 'sync' | 'async' | 'hybrid';
451
+ /**
452
+ * The event an `async` or `hybrid` external object answers with, as Integration
453
+ * Service reports it for the connector object.
454
+ *
455
+ * @remarks
456
+ * Like the execution type, a property of the connector object, not a choice:
457
+ * the Case Designer reads it from the object's metadata (its first event mode
458
+ * and that mode's first event type) and saves it as the task's `operation` and
459
+ * `eventMode` context rows, and as `eventType` / `eventMode` in the metadata's
460
+ * `activityPropertyConfiguration`. Copy it from the same two rows of the
461
+ * activity's `case spec` result (`caseShape.context`). `decompile` lifts it from
462
+ * a saved task. For
463
+ * example, the Power Automate "Invoke a Flow" object (`hybrid`) answers with
464
+ * `{ operation: 'TRIGGER_CREATED', mode: 'polling' }`.
465
+ */
466
+ export interface ExternalEventPair {
467
+ /** The event operation, e.g. `TRIGGER_CREATED`: the task's `operation` context row. */
468
+ operation: string;
469
+ /** How the event is received: the task's `eventMode` context row. */
470
+ mode: 'polling' | 'webhooks';
471
+ }
450
472
  /** Required wiring and typed inputs for an external agent/workflow invocation. */
451
473
  export interface ExternalTaskOptions<I extends Record<string, unknown>> {
452
474
  /** Symbolic Integration Service connection name declared in `bindings.json`. */
@@ -460,6 +482,12 @@ export interface ExternalTaskOptions<I extends Record<string, unknown>> {
460
482
  * `.required(false)`. See {@link ExternalExecutionMode}.
461
483
  */
462
484
  mode: ExternalExecutionMode;
485
+ /**
486
+ * The event an `async` or `hybrid` object answers with. Required for `hybrid`;
487
+ * optional for `async`; refused for `sync`, which answers inline. See
488
+ * {@link ExternalEventPair}.
489
+ */
490
+ event?: ExternalEventPair;
463
491
  /** Inputs statically checked by the generated connector descriptor. */
464
492
  inputs: I;
465
493
  }
@@ -467,6 +495,8 @@ export interface ExternalTaskOptions<I extends Record<string, unknown>> {
467
495
  export interface ExternalTaskSpecData {
468
496
  /** The connector object's `executionType`. */
469
497
  mode: ExternalExecutionMode;
498
+ /** The event an `async` or `hybrid` object answers with, when given. */
499
+ event?: ExternalEventPair;
470
500
  /** Shared connector action identity, inputs, and symbolic bindings. */
471
501
  connector: ConnectorSpecData;
472
502
  }
@@ -334,6 +334,7 @@ class TaskBuilder {
334
334
  this.setKind(kind);
335
335
  this._external = {
336
336
  mode: opts.mode,
337
+ ...(opts.event !== undefined ? { event: { ...opts.event } } : {}),
337
338
  connector: makeConnector(descriptor, opts.inputs, {
338
339
  connection: opts.connection,
339
340
  folder: opts.folder,
@@ -6,7 +6,7 @@ import { schemaVersionRefusal } from '../schema-version.js';
6
6
  import { caseJsonPreservation, caseJsonPreservationErrors, preservedBindings } from './preserve.js';
7
7
  import { EQUALS_EXPR_DIALECT, checkBindingLabels, checkConnectorContract, checkConnectorLookups, checkConnectorSchema, } from '../core/connector-checks.js';
8
8
  import { checkEventResolution } from '../core/event-checks.js';
9
- import { EXTERNAL_TASK_DESCRIPTOR_CONTRACT, EXTERNAL_TASK_HYBRID_UNSUPPORTED, externalHybridRefusal, isExternalExecutionMode } from './external.js';
9
+ import { EXTERNAL_TASK_DESCRIPTOR_CONTRACT, EXTERNAL_TASK_EVENT, externalEventRefusal, isExternalExecutionMode } from './external.js';
10
10
  import { isResourceLabelRefusal, resolveResourceRef } from './resource-identity.js';
11
11
  import { taskShapeProblems } from './task-shape.js';
12
12
  import { isConnectorPlaceholder } from './connector-placeholder.js';
@@ -623,13 +623,11 @@ function checkStage(stage, diags, refStage, refPlacement, bindings) {
623
623
  message: `${family} task "${t.name}" mode must be the connector object's executionType: "sync", "async" or "hybrid".`,
624
624
  where: t.name,
625
625
  });
626
- else if (t.external.mode === 'hybrid')
627
- diags.push({
628
- level: 'error',
629
- code: EXTERNAL_TASK_HYBRID_UNSUPPORTED,
630
- message: externalHybridRefusal(`${family} task "${t.name}"`),
631
- where: t.name,
632
- });
626
+ else {
627
+ const refused = externalEventRefusal(`${family} task "${t.name}"`, t.external.mode, t.external.event);
628
+ if (refused)
629
+ diags.push({ level: 'error', code: EXTERNAL_TASK_EVENT, message: refused, where: t.name });
630
+ }
633
631
  if (!t.external.connector?.key?.trim() || !t.external.connector?.action?.trim())
634
632
  diags.push({
635
633
  level: 'error',
@@ -1,7 +1,7 @@
1
1
  import { commentText } from '../core/comment-text.js';
2
2
  import { tsLiteral, tsNumber } from '../core/ts-literal.js';
3
3
  import { CASE_FORMAT_PROFILE, CASE_SCHEMA_VERSIONS } from './format-profile.js';
4
- import { EXTERNAL_TASK_CONTEXT, externalDescriptorRefusal, externalHybridRefusal, externalServiceType, isExternalExecutionMode } from './external.js';
4
+ import { EXTERNAL_TASK_CONTEXT, EXTERNAL_TASK_EVENT_CONTEXT, externalDescriptorRefusal, externalEventRefusal, externalServiceType, isExternalExecutionMode } from './external.js';
5
5
  import { preserveSchemaVersion } from '../schema-version.js';
6
6
  import { ownEntry } from '../core/own-entry.js';
7
7
  import { isUnrestorableSlotId, taskFingerprint } from './preserve.js';
@@ -618,7 +618,9 @@ function connectorCall(task, refs, library) {
618
618
  /**
619
619
  * Lift an External Agent / External Workflow task saved in the Case Designer's
620
620
  * shape (the one `serialize` emits): a connector activity's context and input
621
- * containers plus the object's `executionType`, which becomes `mode`. The
621
+ * containers plus the object's `executionType`, which becomes `mode`, and the
622
+ * event pair an async / hybrid object answers with (`operation` and `eventMode`
623
+ * rows), which becomes `event`. The
622
624
  * service type must be the one that execution type gives, so a plan whose two
623
625
  * disagree is refused rather than lifted to a source that would compile to
624
626
  * something else.
@@ -637,19 +639,20 @@ function externalCall(task, refs, library) {
637
639
  throw new Error(`${owner} data.bindings must be an empty array; bindings live at case root.`);
638
640
  if (!Array.isArray(data.context))
639
641
  throw new Error(`${owner} requires a resolved context array.`);
640
- // A hybrid task carries an event pair the SDK cannot write back (#1387): refuse
641
- // it by name, before its extra context rows are reported as unknown.
642
- if (data.context.some((row) => row?.name === 'executionType' && row.value === 'hybrid'))
643
- throw new Error(externalHybridRefusal(owner));
644
- // Exactly the context rows serialize writes (the Designer's set): an unknown
645
- // or repeated row would be dropped by the lift and lost on recompile.
642
+ // Exactly the context rows serialize writes (the Designer's set, plus the
643
+ // event pair an async / hybrid object answers with): an unknown or repeated
644
+ // row would be dropped by the lift and lost on recompile.
646
645
  const contextNames = data.context.map((row) => String(row?.name ?? ''));
647
- const unknownContext = contextNames.find((name, at) => !EXTERNAL_TASK_CONTEXT.includes(name) || contextNames.indexOf(name) !== at);
646
+ const unknownContext = contextNames.find((name, at) => !(EXTERNAL_TASK_CONTEXT.includes(name) || EXTERNAL_TASK_EVENT_CONTEXT.includes(name)) || contextNames.indexOf(name) !== at);
648
647
  if (unknownContext !== undefined)
649
648
  throw new Error(`${owner} has unsupported or repeated context row "${unknownContext}".`);
650
649
  const absentContext = EXTERNAL_TASK_CONTEXT.find((name) => !contextNames.includes(name));
651
650
  if (absentContext)
652
651
  throw new Error(`${owner} is missing context row "${absentContext}".`);
652
+ // The pair is written whole or not at all, so half of one cannot be lifted.
653
+ const eventRows = EXTERNAL_TASK_EVENT_CONTEXT.filter((name) => contextNames.includes(name));
654
+ if (eventRows.length === 1)
655
+ throw new Error(`${owner} carries context row "${eventRows[0]}" without "${EXTERNAL_TASK_EVENT_CONTEXT.find((name) => name !== eventRows[0])}"; the event pair is saved whole.`);
653
656
  const context = contextMap(data);
654
657
  const stringValue = (name) => {
655
658
  const row = context.get(name);
@@ -672,6 +675,18 @@ function externalCall(task, refs, library) {
672
675
  const serviceType = externalServiceType(kind, mode);
673
676
  if (data.serviceType !== serviceType)
674
677
  throw new Error(`${owner} has serviceType "${String(data.serviceType ?? '')}", but its executionType "${mode}" saves as "${serviceType}".`);
678
+ // The event the object answers with, as saved: the same rule compile applies,
679
+ // so a lifted task always compiles back (a hybrid task without one does not).
680
+ const event = eventRows.length ? { operation: stringValue('operation'), mode: stringValue('eventMode') } : undefined;
681
+ // A saved plan has no `event` option to drop, so a sync task with event rows
682
+ // gets its own text naming the rows; every other case is compile's rule.
683
+ if (mode === 'sync' && event)
684
+ throw new Error(`${owner} has context rows "operation" (${JSON.stringify(event.operation)}) and "eventMode" ` +
685
+ `(${JSON.stringify(event.mode)}) on executionType "sync"; a sync object answers inline and has no event. ` +
686
+ `Remove the two rows, or fix executionType and serviceType if the object is async or hybrid.`);
687
+ const eventRefused = externalEventRefusal(owner, mode, event);
688
+ if (eventRefused)
689
+ throw new Error(eventRefused);
675
690
  const identity = library.identifyAction({
676
691
  connectorKey: stringValue('connectorKey'),
677
692
  httpMethod: stringValue('method'),
@@ -691,6 +706,7 @@ function externalCall(task, refs, library) {
691
706
  ['connection', tsLiteral(binding('connection'))],
692
707
  ['folder', tsLiteral(binding('folderKey'))],
693
708
  ['mode', tsLiteral(mode)],
709
+ ['event', event ? opts([['operation', tsLiteral(event.operation)], ['mode', tsLiteral(event.mode)]]) : undefined],
694
710
  ['inputs', tsLiteral(inputs)],
695
711
  ]);
696
712
  const method = kind === 'external-agent' ? 'externalAgent' : 'externalWorkflow';
@@ -8,32 +8,43 @@
8
8
  * `buildConnectorInputs`, which `check` already runs as `connectorInputs`.
9
9
  */
10
10
  import type { ResolvedConnector } from '../core/library.js';
11
- import type { ExternalExecutionMode } from './case-sdk.js';
11
+ import type { ExternalEventPair, ExternalExecutionMode } from './case-sdk.js';
12
12
  /**
13
13
  * The context rows `serialize` writes on an external task: the set the Case
14
14
  * Designer saves for a sync object (`uip`'s
15
15
  * `tests/fixtures/external-tasks/designer-saved.json`, the Snowflake Cortex
16
- * agent). `decompile` refuses a task with any other row, since the lift would
17
- * drop it without a word. A `hybrid` task (which also carries `operation` and
18
- * `eventMode`) is refused before this check; see {@link externalHybridRefusal}.
16
+ * agent). An `async` or `hybrid` task may also carry
17
+ * {@link EXTERNAL_TASK_EVENT_CONTEXT}. `decompile` refuses a task with any other
18
+ * row, since the lift would drop it without a word.
19
19
  */
20
20
  export declare const EXTERNAL_TASK_CONTEXT: readonly string[];
21
- /** Check's code for {@link externalHybridRefusal}. */
22
- export declare const EXTERNAL_TASK_HYBRID_UNSUPPORTED = "EXTERNAL_TASK_HYBRID_UNSUPPORTED";
23
21
  /**
24
- * Why an external task on a `hybrid` object cannot be compiled or decompiled
25
- * yet. The Case Designer saves such a task with an event pair (context
26
- * `operation`, e.g. `TRIGGER_CREATED`, and `eventMode`, e.g. `polling`, also in
27
- * the metadata's `activityPropertyConfiguration`) that it reads from live
28
- * Integration Service metadata. The connector library does not carry that pair
29
- * (#1387), so the SDK cannot write the task faithfully, and a guessed pair could
30
- * deploy a task that never completes. `check`, `serialize` and `decompile` all
31
- * refuse with this text.
22
+ * The two context rows that carry the event an `async` / `hybrid` object
23
+ * answers with (`ExternalEventPair`): `operation` (e.g. `TRIGGER_CREATED`) and
24
+ * `eventMode` (e.g. `polling`). The Designer writes them after `objectName`,
25
+ * before `executionType` (the Power Automate flow in `designer-saved.json`).
26
+ */
27
+ export declare const EXTERNAL_TASK_EVENT_CONTEXT: readonly string[];
28
+ /** Check's and compile's code for {@link externalEventRefusal}. */
29
+ export declare const EXTERNAL_TASK_EVENT = "EXTERNAL_TASK_EVENT";
30
+ /** The event modes Integration Service reports for an object's events. */
31
+ export declare function isExternalEventMode(value: unknown): value is ExternalEventPair['mode'];
32
+ /**
33
+ * Why this task's event pair cannot be written, or `undefined`.
34
+ *
35
+ * A `hybrid` object answers through an event, and the Case Designer saves that
36
+ * event with the task (context `operation` and `eventMode`, and the same pair in
37
+ * the metadata's `activityPropertyConfiguration`). Without it the task has
38
+ * nothing to wait on, so `hybrid` needs the pair. An `async` object takes it
39
+ * when given. A `sync` object answers inline and has none, so a pair there is a
40
+ * wrong `mode` or a wrong pair. `check`, `serialize` and `decompile` all use this.
32
41
  *
33
42
  * @param owner - The task as the message names it, e.g. `External Workflow task "Run"`.
34
- * @returns The refusal.
43
+ * @param mode - The task's execution type (already known to be valid).
44
+ * @param event - The authored or saved pair, if any.
45
+ * @returns The refusal, or `undefined`.
35
46
  */
36
- export declare function externalHybridRefusal(owner: string): string;
47
+ export declare function externalEventRefusal(owner: string, mode: ExternalExecutionMode, event: unknown): string | undefined;
37
48
  /** The execution types an external task accepts: the values Integration Service reports. */
38
49
  export declare function isExternalExecutionMode(value: unknown): value is ExternalExecutionMode;
39
50
  /**
@@ -3,34 +3,61 @@ import { CASE_FORMAT_PROFILE } from './format-profile.js';
3
3
  * The context rows `serialize` writes on an external task: the set the Case
4
4
  * Designer saves for a sync object (`uip`'s
5
5
  * `tests/fixtures/external-tasks/designer-saved.json`, the Snowflake Cortex
6
- * agent). `decompile` refuses a task with any other row, since the lift would
7
- * drop it without a word. A `hybrid` task (which also carries `operation` and
8
- * `eventMode`) is refused before this check; see {@link externalHybridRefusal}.
6
+ * agent). An `async` or `hybrid` task may also carry
7
+ * {@link EXTERNAL_TASK_EVENT_CONTEXT}. `decompile` refuses a task with any other
8
+ * row, since the lift would drop it without a word.
9
9
  */
10
10
  export const EXTERNAL_TASK_CONTEXT = [
11
11
  'connectorKey', 'connection', 'resourceKey', 'folderKey', 'objectName', 'method', 'path',
12
12
  'executionType', 'metadata', 'activityConfigurationVersion',
13
13
  ];
14
- /** Check's code for {@link externalHybridRefusal}. */
15
- export const EXTERNAL_TASK_HYBRID_UNSUPPORTED = 'EXTERNAL_TASK_HYBRID_UNSUPPORTED';
16
14
  /**
17
- * Why an external task on a `hybrid` object cannot be compiled or decompiled
18
- * yet. The Case Designer saves such a task with an event pair (context
19
- * `operation`, e.g. `TRIGGER_CREATED`, and `eventMode`, e.g. `polling`, also in
20
- * the metadata's `activityPropertyConfiguration`) that it reads from live
21
- * Integration Service metadata. The connector library does not carry that pair
22
- * (#1387), so the SDK cannot write the task faithfully, and a guessed pair could
23
- * deploy a task that never completes. `check`, `serialize` and `decompile` all
24
- * refuse with this text.
15
+ * The two context rows that carry the event an `async` / `hybrid` object
16
+ * answers with (`ExternalEventPair`): `operation` (e.g. `TRIGGER_CREATED`) and
17
+ * `eventMode` (e.g. `polling`). The Designer writes them after `objectName`,
18
+ * before `executionType` (the Power Automate flow in `designer-saved.json`).
19
+ */
20
+ export const EXTERNAL_TASK_EVENT_CONTEXT = ['operation', 'eventMode'];
21
+ /** Check's and compile's code for {@link externalEventRefusal}. */
22
+ export const EXTERNAL_TASK_EVENT = 'EXTERNAL_TASK_EVENT';
23
+ /** The event modes Integration Service reports for an object's events. */
24
+ export function isExternalEventMode(value) {
25
+ return value === 'polling' || value === 'webhooks';
26
+ }
27
+ /**
28
+ * Why this task's event pair cannot be written, or `undefined`.
29
+ *
30
+ * A `hybrid` object answers through an event, and the Case Designer saves that
31
+ * event with the task (context `operation` and `eventMode`, and the same pair in
32
+ * the metadata's `activityPropertyConfiguration`). Without it the task has
33
+ * nothing to wait on, so `hybrid` needs the pair. An `async` object takes it
34
+ * when given. A `sync` object answers inline and has none, so a pair there is a
35
+ * wrong `mode` or a wrong pair. `check`, `serialize` and `decompile` all use this.
25
36
  *
26
37
  * @param owner - The task as the message names it, e.g. `External Workflow task "Run"`.
27
- * @returns The refusal.
38
+ * @param mode - The task's execution type (already known to be valid).
39
+ * @param event - The authored or saved pair, if any.
40
+ * @returns The refusal, or `undefined`.
28
41
  */
29
- export function externalHybridRefusal(owner) {
30
- return (`${owner} is on a "hybrid" object, which Case cannot compile yet: the connector library does not carry ` +
31
- `the event pair the Case Designer writes for it (operation, e.g. "TRIGGER_CREATED", and eventMode, e.g. "polling"), ` +
32
- `so the task cannot be written faithfully. Add this task in Studio Web for now; ` +
33
- `https://github.com/UiPath/builder-sdk/issues/1387 tracks the library change.`);
42
+ export function externalEventRefusal(owner, mode, event) {
43
+ if (event === undefined) {
44
+ if (mode !== 'hybrid')
45
+ return undefined;
46
+ return (`${owner} is on a "hybrid" object, which answers through an event: pass the event the object reports as ` +
47
+ `event: { operation, mode } (for example { operation: "TRIGGER_CREATED", mode: "polling" }, ` +
48
+ `the "operation" and "eventMode" rows of the case spec result's caseShape.context). Without it the task has nothing to wait on.`);
49
+ }
50
+ if (mode === 'sync')
51
+ return `${owner} is on a "sync" object, which answers inline and has no event; drop event, or fix mode.`;
52
+ const pair = event;
53
+ if (typeof pair !== 'object' || pair === null || typeof pair.operation !== 'string' || !pair.operation.trim())
54
+ return `${owner} event.operation must be the object's non-empty event operation, e.g. "TRIGGER_CREATED".`;
55
+ // Written as given, and Integration Service matches it exactly: " TRIGGER_CREATED" would never match.
56
+ if (pair.operation !== pair.operation.trim())
57
+ return `${owner} event.operation ${JSON.stringify(pair.operation)} has surrounding whitespace; write it exactly as the object reports it, e.g. "TRIGGER_CREATED".`;
58
+ if (!isExternalEventMode(pair.mode))
59
+ return `${owner} event.mode must be "polling" or "webhooks"; got ${JSON.stringify(pair.mode)}.`;
60
+ return undefined;
34
61
  }
35
62
  /** The execution types an external task accepts: the values Integration Service reports. */
36
63
  export function isExternalExecutionMode(value) {
@@ -19,7 +19,7 @@ import { bindingLabelRefusal } from '../core/binding-messages.js';
19
19
  import { resolveEventWhere } from '../core/lookups.js';
20
20
  import { resolveCaseSubscription } from './subscription.js';
21
21
  import { dedupeConditionNames } from './rule-names.js';
22
- import { EXTERNAL_TASK_DESCRIPTOR_CONTRACT, EXTERNAL_TASK_HYBRID_UNSUPPORTED, externalDescriptorRefusal, externalHybridRefusal, externalServiceType, isExternalExecutionMode, } from './external.js';
22
+ import { EXTERNAL_TASK_DESCRIPTOR_CONTRACT, EXTERNAL_TASK_EVENT, externalDescriptorRefusal, externalEventRefusal, externalServiceType, isExternalExecutionMode, } from './external.js';
23
23
  import { CASE_FORMAT_PROFILE, CASE_SCHEMA_VERSIONS, caseVersionMismatch } from './format-profile.js';
24
24
  import { isResourceLabelRefusal, resolveResourceRef, resourceIdentity } from './resource-identity.js';
25
25
  import { ownEntry } from '../core/own-entry.js';
@@ -1739,7 +1739,7 @@ function businessRuleTaskData(task, resolver, elementId, ids) {
1739
1739
  * the op's output schema. Connection/folder resolve through `bindings` and are
1740
1740
  * referenced as `=bindings.<id>`, with the binding entry collected at case root.
1741
1741
  */
1742
- function connectorTaskData(spec, resolver, elementId, where, executionType) {
1742
+ function connectorTaskData(spec, resolver, elementId, where, executionType, event) {
1743
1743
  if (!resolver.library)
1744
1744
  throw new CompileRefusal('LIBRARY_REQUIRED', `connector task needs the connector library — pass { library } to serialize or use uip maestro case compile --library.`);
1745
1745
  const rc = resolver.library.resolve(spec.key, spec.action, spec.version, spec.object);
@@ -1787,7 +1787,7 @@ function connectorTaskData(spec, resolver, elementId, where, executionType) {
1787
1787
  // from the `body` slot. This used to drop the whole wire and push a filled
1788
1788
  // file part into the body, where the runtime does not look for it (#1420).
1789
1789
  const fileParts = (slots.multipartParameters ?? []).filter((part) => part.dataType.toLowerCase() === 'file');
1790
- context.push(io('metadata', 'json', { body: connectorMetadata(rc, op, slots, elementId, executionType) }));
1790
+ context.push(io('metadata', 'json', { body: connectorMetadata(rc, op, slots, elementId, executionType, event) }));
1791
1791
  const inputs = [
1792
1792
  ioSlot('pathParameters', pathParameters, `${elementId}`),
1793
1793
  ioSlot('queryParameters', queryParameters, `${elementId}`),
@@ -1816,14 +1816,20 @@ function externalTaskData(kind, spec, resolver, elementId, where) {
1816
1816
  throw new CompileRefusal(EXTERNAL_TASK_DESCRIPTOR_CONTRACT, refused);
1817
1817
  if (!isExternalExecutionMode(spec.mode))
1818
1818
  throw new CompileRefusal('EXTERNAL_TASK_MODE', `${kind} task mode must be the connector object's executionType: "sync", "async" or "hybrid".`);
1819
- if (spec.mode === 'hybrid')
1820
- throw new CompileRefusal(EXTERNAL_TASK_HYBRID_UNSUPPORTED, externalHybridRefusal(where));
1819
+ const eventRefused = externalEventRefusal(where, spec.mode, spec.event);
1820
+ if (eventRefused)
1821
+ throw new CompileRefusal(EXTERNAL_TASK_EVENT, eventRefused);
1821
1822
  if (!spec.connector.connection || !spec.connector.folder)
1822
1823
  throw new CompileRefusal(spec.connector.connection ? 'EXTERNAL_TASK_FOLDER' : 'EXTERNAL_TASK_CONNECTION', `${kind} task requires non-empty connection and folder binding names.`);
1823
- const data = connectorTaskData(spec.connector, resolver, elementId, where, spec.mode);
1824
+ const data = connectorTaskData(spec.connector, resolver, elementId, where, spec.mode, spec.event);
1824
1825
  const context = data.context;
1825
1826
  const metadataAt = context.findIndex((row) => row.name === 'metadata');
1826
- context.splice(metadataAt, 0, io('executionType', 'string', { value: spec.mode }));
1827
+ // The Designer's order: the event pair (when the object answers through one),
1828
+ // then the execution type, just before `metadata`.
1829
+ context.splice(metadataAt, 0, ...(spec.event ? [
1830
+ io('operation', 'string', { value: spec.event.operation }),
1831
+ io('eventMode', 'string', { value: spec.event.mode }),
1832
+ ] : []), io('executionType', 'string', { value: spec.mode }));
1827
1833
  context.push(io('activityConfigurationVersion', 'string', { value: 'v2' }));
1828
1834
  return { ...data, serviceType: externalServiceType(kind, spec.mode) };
1829
1835
  }
@@ -1957,7 +1963,7 @@ function folderBindingRef(resolver, name, connection, site) {
1957
1963
  * Generic activity, and the library version where the platform writes
1958
1964
  * `packageVersion: "1.0.0"` (#1420).
1959
1965
  */
1960
- function connectorMetadata(rc, op, slots, seed, executionType) {
1966
+ function connectorMetadata(rc, op, slots, seed, executionType, event) {
1961
1967
  // The part DECLARATIONS only: a file part's value rides on its `file` input.
1962
1968
  const multipartParameters = (slots.multipartParameters ?? []).map(({ name, dataType }) => ({ name, dataType }));
1963
1969
  // The configuration replays the authored values (a schema action's parent
@@ -1973,6 +1979,9 @@ function connectorMetadata(rc, op, slots, seed, executionType) {
1973
1979
  uiPathActivityTypeId: rc.activityTypeId ?? '',
1974
1980
  errorState: { issues: [] },
1975
1981
  ...(executionType ? { executionType } : {}),
1982
+ // The event an async / hybrid object answers with, named as the Designer
1983
+ // names it here (`eventType`, where the context row is `operation`).
1984
+ ...(event ? { eventType: event.operation, eventMode: event.mode } : {}),
1976
1985
  },
1977
1986
  activityMetadata: {
1978
1987
  activity: {
@@ -274,8 +274,8 @@ export declare const REFUSALS: {
274
274
  readonly EXTERNAL_TASK_DESCRIPTOR: "lint";
275
275
  readonly EXTERNAL_TASK_DESCRIPTOR_CONTRACT: "lowering";
276
276
  readonly EXTERNAL_TASK_EMPTY_DATA: "lint";
277
+ readonly EXTERNAL_TASK_EVENT: "lowering";
277
278
  readonly EXTERNAL_TASK_FOLDER: "lowering";
278
- readonly EXTERNAL_TASK_HYBRID_UNSUPPORTED: "lowering";
279
279
  readonly EXTERNAL_TASK_MODE: "lowering";
280
280
  readonly EXTRACT_SCHEMA_SHAPE: "lint";
281
281
  readonly FAKE_JOIN: "lint";
@@ -325,8 +325,8 @@ export const REFUSALS = {
325
325
  EXTERNAL_TASK_DESCRIPTOR: 'lint',
326
326
  EXTERNAL_TASK_DESCRIPTOR_CONTRACT: 'lowering',
327
327
  EXTERNAL_TASK_EMPTY_DATA: 'lint',
328
+ EXTERNAL_TASK_EVENT: 'lowering',
328
329
  EXTERNAL_TASK_FOLDER: 'lowering',
329
- EXTERNAL_TASK_HYBRID_UNSUPPORTED: 'lowering',
330
330
  EXTERNAL_TASK_MODE: 'lowering',
331
331
  EXTRACT_SCHEMA_SHAPE: 'lint',
332
332
  FAKE_JOIN: 'lint',
package/dist/index.d.ts CHANGED
@@ -21,7 +21,7 @@ export { Bindings } from './bindings.js';
21
21
  export { check } from './check.js';
22
22
  export type { Diagnostic } from './check.js';
23
23
  export { casePlan, preserveCaseJson, rule, when } from './case/case-sdk.js';
24
- export type { CaseRule, CaseRuleInput, CaseRuleGrid, WhenExpression, CaseJsonPreservation, CaseLayout, CaseNodeLayout, PreservedCaseNode, PreservedTaskFields, PreservedVariableLane, CaseRuleType, RuleOpts, BuiltCase, BuiltStage, BuiltTask, TaskKind, UnresolvedReferenceTaskKind, ExternalExecutionMode, ExternalTaskOptions, } from './case/case-sdk.js';
24
+ export type { CaseRule, CaseRuleInput, CaseRuleGrid, WhenExpression, CaseJsonPreservation, CaseLayout, CaseNodeLayout, PreservedCaseNode, PreservedTaskFields, PreservedVariableLane, CaseRuleType, RuleOpts, BuiltCase, BuiltStage, BuiltTask, TaskKind, UnresolvedReferenceTaskKind, ExternalEventPair, ExternalExecutionMode, ExternalTaskOptions, } from './case/case-sdk.js';
25
25
  export { serialize as serializeCase } from './case/serialize.js';
26
26
  export { decompile as decompileCase, decompileWithDiagnostics as decompileCaseWithDiagnostics } from './case/decompile.js';
27
27
  export { bpmn } from './bpmn/bpmn-sdk.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.68.4",
3
+ "version": "6.68.5",
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": "f879560df189ceab42f899123d36f0add5b0a562"
103
+ "gitref": "3f8f0766113501aaf0d1d7c36835ef3c8eb6c2aa"
104
104
  }