@uipath/maestro-builder-sdk 6.31.2 → 6.31.4

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.
@@ -117,6 +117,23 @@ const BASELINE = ${JSON.stringify(join(base + '.baseline', basename(base) + '.fl
117
117
  const EDITED = ${JSON.stringify(join(base + '.edited', basename(base) + '.flow'))};
118
118
  const MERGED = ${JSON.stringify(base + '.merged.flow')};
119
119
 
120
+ // Options. \`--strict\` goes to step 2's merge: refuse, writing nothing, when the
121
+ // no-edit round trip (BASELINE) differs from ORIGINAL anywhere, instead of
122
+ // warning and writing. An unknown option stops the run: silently ignoring one
123
+ // would run a merge the caller did not ask for.
124
+ const USAGE = 'usage: node ' + ${JSON.stringify(basename(pipelinePath))} + ' [--strict]';
125
+ const argv = process.argv.slice(2);
126
+ if (argv.includes('-h') || argv.includes('--help')) {
127
+ console.log(USAGE + '\\n --strict merge refuses (exit 1, nothing written) when the no-edit round trip differs from the original');
128
+ process.exit(0);
129
+ }
130
+ const unknown = argv.find((a) => a !== '--strict');
131
+ if (unknown !== undefined) {
132
+ console.error(${JSON.stringify(basename(pipelinePath))} + ': unknown option ' + JSON.stringify(unknown) + '\\n' + USAGE);
133
+ process.exit(2);
134
+ }
135
+ const STRICT = argv.includes('--strict');
136
+
120
137
  // Ensure the decompiled source exists (a fresh clone may have only the .flow).
121
138
  if (!existsSync(TS)) run('decompile', [ORIGINAL, '-o', TS, '--no-pipeline']);
122
139
 
@@ -128,14 +145,6 @@ if (!existsSync(BASELINE)) {
128
145
  console.log('\\n>>> Baseline captured. Now EDIT ' + ${JSON.stringify(basename(tsPath))} + ', then re-run this script to compile + merge.');
129
146
  } else {
130
147
  // ── Step 2: compile your edits, then merge them back into the original. ──
131
- mkdirSync(dirname(EDITED), { recursive: true });
132
- run('compile', [TS, '-o', EDITED, '--no-check']);
133
-
134
- // ── DIFF GATE (seam) ──────────────────────────────────────────────────────
135
- // A future step can diff ORIGINAL vs the about-to-be-written MERGED here and
136
- // ask for confirmation before the write. Left as a no-op for now.
137
- // ---------------------------------------------------------------------------
138
-
139
148
  // \`merge <edited> --original <original>\` is the grammar; the positional
140
149
  // \`merge <original> <edited>\` pair is deprecated. A \`uip\` from before
141
150
  // UiPath/cli#4526 knows only the pair, so ask its \`merge --help\` first.
@@ -144,10 +153,27 @@ if (!existsSync(BASELINE)) {
144
153
  const mergeHelp = frontDoor.via === 'uip'
145
154
  ? spawnSync(frontDoor.file, [...frontDoor.prefix, 'merge', '--help'], { encoding: 'utf8' })
146
155
  : undefined;
147
- const namedOriginal = mergeHelp === undefined
148
- || \`\${mergeHelp.stdout ?? ''}\${mergeHelp.stderr ?? ''}\`.includes('--original');
156
+ const mergeHelpText = mergeHelp === undefined ? undefined : \`\${mergeHelp.stdout ?? ''}\${mergeHelp.stderr ?? ''}\`;
157
+ const namedOriginal = mergeHelpText === undefined || mergeHelpText.includes('--original');
158
+ // A \`uip\` from before \`merge --strict\` existed would reject the flag with a
159
+ // bare "unknown option"; name the remedy instead, and never drop the flag.
160
+ // Both checks run before the compile, so a run that cannot merge does no work.
161
+ if (STRICT && mergeHelpText !== undefined && !mergeHelpText.includes('--strict')) {
162
+ console.error(${JSON.stringify(basename(pipelinePath))} + ': --strict was asked for, but this uip has no \`maestro flow merge --strict\`. '
163
+ + 'Update uip, or run without --strict.');
164
+ process.exit(2);
165
+ }
166
+ mkdirSync(dirname(EDITED), { recursive: true });
167
+ run('compile', [TS, '-o', EDITED, '--no-check']);
168
+
169
+ // ── DIFF GATE (seam) ──────────────────────────────────────────────────────
170
+ // A future step can diff ORIGINAL vs the about-to-be-written MERGED here and
171
+ // ask for confirmation before the write. Left as a no-op for now.
172
+ // ---------------------------------------------------------------------------
173
+
149
174
  const args = namedOriginal ? [EDITED, '--original', ORIGINAL, '-o', MERGED] : [ORIGINAL, EDITED, '-o', MERGED];
150
175
  if (existsSync(BASELINE)) args.push('--baseline', BASELINE);
176
+ if (STRICT) args.push('--strict');
151
177
  run('merge', args);
152
178
  console.log('\\n>>> Wrote ' + ${JSON.stringify(base + '.merged.flow')}
153
179
  + '. Replace the original with it, together with every <source>/ file merge reports writing beside it,'
package/dist/decompile.js CHANGED
@@ -2132,8 +2132,10 @@ function droppedEdgeMessage(e) {
2132
2132
  */
2133
2133
  function droppedEdgesSeg(node, ctx) {
2134
2134
  const dropped = ctx.graph.outEdges(node.id).filter((e) => !ctx.graph.accounted.has(e));
2135
- if (dropped.length === 0)
2136
- return undefined;
2135
+ return dropped.length === 0 ? undefined : dropEdges(dropped, ctx);
2136
+ }
2137
+ /** Account `dropped` as dropped: warn each once, remember it for strict mode, and return the site's `/* TODO *\/`. */
2138
+ function dropEdges(dropped, ctx) {
2137
2139
  for (const e of dropped) {
2138
2140
  ctx.graph.accounted.add(e);
2139
2141
  runDropped.push(e);
@@ -2200,11 +2202,12 @@ function commonPostDominator(targets, ipdom) {
2200
2202
  * decompiles to that `.parallel(...)`, then the region continues from the
2201
2203
  * merge's output (flow-builder-sdk#1155).
2202
2204
  *
2203
- * Every edge in `edges` is accounted (edge accounting, #1125): the fold
2204
- * recreates each one. A fork whose arms never meet at a merge node has no
2205
- * builder spelling. Like the same shape mid-flow (`region`), it throws under
2206
- * `bestEffort: false`, and otherwise keeps the first arm behind a
2207
- * `TODO: unstructured fan-out` marker, which is what reports the other edges.
2205
+ * When the arms meet at a merge node, every edge in `edges` is accounted
2206
+ * (edge accounting, #1125): the fold recreates each one. A fork whose arms
2207
+ * never meet at a merge node has no builder spelling. Like the same shape
2208
+ * mid-flow (`region`), it throws under `bestEffort: false`, and otherwise keeps
2209
+ * the first arm behind a `TODO: unstructured fan-out` marker. Only the kept
2210
+ * first edge is accounted; the others are reported as dropped at the marker.
2208
2211
  */
2209
2212
  function forkRegion(edges, stop, scope, ipdom, ctx, refInto) {
2210
2213
  if (edges.length <= 1)
@@ -2215,10 +2218,10 @@ function forkRegion(edges, stop, scope, ipdom, ctx, refInto) {
2215
2218
  if (join === undefined || join === stop || joinNode?.type !== T.merge) {
2216
2219
  if (ctx.o.bestEffort === false)
2217
2220
  throw new Error(`decompile: unstructured fan-out (${edges.length} edges).`);
2218
- for (const e of edges)
2219
- ctx.graph.accounted.add(e);
2221
+ ctx.graph.accounted.add(edges[0]);
2220
2222
  return [
2221
2223
  `/* TODO: unstructured fan-out (${commentText(edges.length)} edges) */`,
2224
+ dropEdges(edges.slice(1), ctx),
2222
2225
  ...region(targets[0], stop, scope, ipdom, ctx, refInto),
2223
2226
  ];
2224
2227
  }
@@ -2617,13 +2620,11 @@ function region(cursor, stop, scope, ipdom, ctx, refInto) {
2617
2620
  cursor = fork.next.cursor;
2618
2621
  continue;
2619
2622
  }
2620
- // Unstructured fan-out we can't fold — best-effort marker. Its successor
2621
- // edges are what the marker reports, so they are not reported twice.
2623
+ // Unstructured fan-out we can't fold — best-effort marker.
2624
+ // No successor is walked: leave the edges unaccounted so `flagDropped` names each.
2622
2625
  if (ctx.o.bestEffort === false)
2623
2626
  throw new Error(`decompile: unstructured fan-out at "${node.id}".`);
2624
2627
  segs.push(`/* TODO: unstructured fan-out at ${commentText(node.id)} (${commentText(succ.length)} successors) */`);
2625
- for (const t of succ)
2626
- follow(ctx.graph, node.id, t);
2627
2628
  flagDropped(node, ctx, segs);
2628
2629
  return segs;
2629
2630
  }
@@ -479,8 +479,12 @@ export interface ReturnOptions extends NodeOptions {
479
479
  * Loop-specific options. Every `.loop()` emits the loop's v2.4 definition (the
480
480
  * version the registry serves: inner `start`/`continue`/`break` handles, and a
481
481
  * 1-based `currentIteration` output). The legacy 1.0.0 shape is emitted only for
482
- * an explicit `{ version: '1.0.0' }`, and that combined with any of these options
483
- * fails compilation: that definition cannot express them.
482
+ * an explicit `{ version: '1.0.0' }`. That definition declares `parallel` but no
483
+ * `completionCondition`, no `breakEnabled` and no `break` handle, so either of
484
+ * those options, or a `b.break()` in the body, fails `check` and compilation
485
+ * (`LOOP_VERSION_UNSUPPORTED`). `parallel: true` on 1.0.0 compiles, to round-trip
486
+ * a canvas loop, but `check` warns (`LOOP_PARALLEL_LEGACY`): that version is not
487
+ * confirmed to run iterations in parallel. `b.continue()` works on both versions.
484
488
  */
485
489
  export interface LoopOptions extends NodeOptions {
486
490
  /** Run iterations in parallel instead of sequentially. */
@@ -0,0 +1,41 @@
1
+ import type { LoopOptions, Step } from './flow-sdk.js';
2
+ /** The wire type of `.loop()`. */
3
+ export declare const LOOP_NODE_TYPE = "core.logic.loop";
4
+ /** The `core.logic.loop` version `.loop()` emits unless `{ version }` pins another. */
5
+ export declare const LOOP_DEFAULT_VERSION = "2.4";
6
+ /** The version `.loop()` emits for these options. */
7
+ export declare function loopVersion(options: LoopOptions | undefined): string;
8
+ /**
9
+ * True when this loop version's body runs from the inner `start` handle and goes
10
+ * back through `continue` (2.x); false for the legacy `output`/`loopBack` shape.
11
+ * A version with no bundled definition counts as 2.x; its lookup fails later.
12
+ */
13
+ export declare function loopHasInnerHandles(version: string): boolean;
14
+ /**
15
+ * The features this loop uses that its version's definition cannot express, in
16
+ * a fixed order (`parallel`, `completionCondition`, `breakEnabled`, `break()`).
17
+ * Empty when all are supported, or when no definition is bundled for the version
18
+ * (an unknown version is reported elsewhere, by the definition lookup).
19
+ */
20
+ export declare function unsupportedLoopFeatures(options: LoopOptions | undefined, usesBreak: boolean): string[];
21
+ /**
22
+ * The refusal for a loop whose options or body need a definition the requested
23
+ * version does not have, or `undefined` when there is nothing to refuse.
24
+ * `serialize` throws it; `check` reports it as `LOOP_VERSION_UNSUPPORTED` with
25
+ * the same text, so the author reads one message in both places.
26
+ */
27
+ export declare function loopVersionRefusal(name: string, options: LoopOptions | undefined, usesBreak: boolean): string | undefined;
28
+ /**
29
+ * The warning for `parallel: true` on a 1.0.0 loop, or `undefined`. The 1.0.0
30
+ * definition declares the input, so the loop compiles and a canvas 1.0.0 loop
31
+ * round-trips; whether the 1.0.0 runtime runs its iterations in parallel is not
32
+ * confirmed, so a new loop that needs that should use the default version.
33
+ * `check` reports it as `LOOP_PARALLEL_LEGACY`.
34
+ */
35
+ export declare function loopParallelWarning(name: string, options: LoopOptions | undefined): string | undefined;
36
+ /**
37
+ * True when a container body (or an arm/handler inside it, but not a NESTED
38
+ * container's body) breaks: a nested `.loop()`/`.doWhile()` owns its own
39
+ * `.break()`.
40
+ */
41
+ export declare function bodyUsesBreak(steps: Step[]): boolean;
@@ -0,0 +1,97 @@
1
+ /**
2
+ * What each `core.logic.loop` version can express, read from the bundled
3
+ * definition of that version — the one answer `serialize` and `check` share.
4
+ *
5
+ * The definition is the authority:
6
+ * - an option is supported when the definition declares an input of that name;
7
+ * - `.break()` is supported when the definition declares a `break` target handle.
8
+ */
9
+ import { BUNDLED_DEFINITIONS } from './flow-definitions.js';
10
+ /** The wire type of `.loop()`. */
11
+ export const LOOP_NODE_TYPE = 'core.logic.loop';
12
+ /** The `core.logic.loop` version `.loop()` emits unless `{ version }` pins another. */
13
+ export const LOOP_DEFAULT_VERSION = '2.4';
14
+ /** The version `.loop()` emits for these options. */
15
+ export function loopVersion(options) {
16
+ return options?.version ?? LOOP_DEFAULT_VERSION;
17
+ }
18
+ /**
19
+ * True when this loop version's body runs from the inner `start` handle and goes
20
+ * back through `continue` (2.x); false for the legacy `output`/`loopBack` shape.
21
+ * A version with no bundled definition counts as 2.x; its lookup fails later.
22
+ */
23
+ export function loopHasInnerHandles(version) {
24
+ return loopDefinition(version) ? targetHandleIds(version).has('continue') : true;
25
+ }
26
+ /** The loop options whose support depends on the version, in message order. */
27
+ const VERSIONED_OPTIONS = ['parallel', 'completionCondition', 'breakEnabled'];
28
+ /**
29
+ * The features this loop uses that its version's definition cannot express, in
30
+ * a fixed order (`parallel`, `completionCondition`, `breakEnabled`, `break()`).
31
+ * Empty when all are supported, or when no definition is bundled for the version
32
+ * (an unknown version is reported elsewhere, by the definition lookup).
33
+ */
34
+ export function unsupportedLoopFeatures(options, usesBreak) {
35
+ const def = loopDefinition(loopVersion(options));
36
+ if (!def)
37
+ return [];
38
+ const inputs = def.inputDefinition?.properties ?? {};
39
+ const out = VERSIONED_OPTIONS.filter((k) => options?.[k] !== undefined && !(k in inputs));
40
+ if (usesBreak && !targetHandleIds(loopVersion(options)).has('break'))
41
+ out.push('break()');
42
+ return out;
43
+ }
44
+ /**
45
+ * The refusal for a loop whose options or body need a definition the requested
46
+ * version does not have, or `undefined` when there is nothing to refuse.
47
+ * `serialize` throws it; `check` reports it as `LOOP_VERSION_UNSUPPORTED` with
48
+ * the same text, so the author reads one message in both places.
49
+ */
50
+ export function loopVersionRefusal(name, options, usesBreak) {
51
+ const missing = unsupportedLoopFeatures(options, usesBreak);
52
+ if (missing.length === 0)
53
+ return undefined;
54
+ const version = loopVersion(options);
55
+ return `loop "${name}": ${missing.join('/')} ${missing.length === 1 ? 'needs' : 'need'} the loop's `
56
+ + `${LOOP_DEFAULT_VERSION} definition, but { version: '${version}' } was requested. `
57
+ + `Drop the version or request ${LOOP_DEFAULT_VERSION}.`;
58
+ }
59
+ /**
60
+ * The warning for `parallel: true` on a 1.0.0 loop, or `undefined`. The 1.0.0
61
+ * definition declares the input, so the loop compiles and a canvas 1.0.0 loop
62
+ * round-trips; whether the 1.0.0 runtime runs its iterations in parallel is not
63
+ * confirmed, so a new loop that needs that should use the default version.
64
+ * `check` reports it as `LOOP_PARALLEL_LEGACY`.
65
+ */
66
+ export function loopParallelWarning(name, options) {
67
+ if (options?.parallel !== true || loopHasInnerHandles(loopVersion(options)))
68
+ return undefined;
69
+ return `loop "${name}": parallel: true on { version: '${loopVersion(options)}' } is written to the node, but `
70
+ + `that version is not confirmed to run iterations in parallel, so the loop may run them one by one. `
71
+ + `Keep it to round-trip an existing loop; for a new parallel loop, drop the version (${LOOP_DEFAULT_VERSION}).`;
72
+ }
73
+ /**
74
+ * True when a container body (or an arm/handler inside it, but not a NESTED
75
+ * container's body) breaks: a nested `.loop()`/`.doWhile()` owns its own
76
+ * `.break()`.
77
+ */
78
+ export function bodyUsesBreak(steps) {
79
+ return steps.some((s) => s.kind === 'break'
80
+ || (s.kind === 'branch' && (bodyUsesBreak(s.then) || bodyUsesBreak(s.otherwise)))
81
+ || (s.kind === 'switch' && (s.cases.some((c) => bodyUsesBreak(c.body)) || (s.default ? bodyUsesBreak(s.default) : false)))
82
+ || (s.kind === 'stepSwitch' && s.cases.some((c) => bodyUsesBreak(c.body)))
83
+ || (s.kind === 'parallel' && s.arms.some(bodyUsesBreak))
84
+ || (s.kind === 'stepToList' && bodyUsesBreak(s.body)));
85
+ }
86
+ function loopDefinition(version) {
87
+ return BUNDLED_DEFINITIONS[`${LOOP_NODE_TYPE}@${version}`];
88
+ }
89
+ function targetHandleIds(version) {
90
+ const ids = new Set();
91
+ for (const group of loopDefinition(version)?.handleConfiguration ?? []) {
92
+ for (const h of group.handles ?? [])
93
+ if (h.type === 'target')
94
+ ids.add(h.id);
95
+ }
96
+ return ids;
97
+ }
@@ -3,46 +3,81 @@ import { type Reporter } from "./reporter.js";
3
3
  export declare function bundledOverlayPath(): string;
4
4
  /** Stable identity of the curated data, so a changed overlay gets a new cache entry. */
5
5
  export declare function curatedOverlayIdentity(overlayPath?: string): Promise<string>;
6
+ /** The ledger of deliberate patches; read here, never copied into a library. */
7
+ export declare const CORRECTIONS_FILE = "overlay-corrections.json";
8
+ /** One row of {@link CORRECTIONS_FILE}. */
9
+ export interface OverlayCorrection {
10
+ path: string;
11
+ since: string;
12
+ reason: string;
13
+ /** Added to the entry's `inputSchema.fields` and the sidecar's `inputDefinition.fields` when absent. */
14
+ inputFields?: string[];
15
+ /** Top-level sidecar keys added when absent. */
16
+ sidecarKeys?: string[];
17
+ }
6
18
  export interface CuratedOverlayResult {
7
- /** Overlay files copied into the library. */
19
+ /** Files written into the library: definitions added, corrections patched, side-tables. */
8
20
  files: number;
9
21
  /** Index rows added for identities the library did not already carry. */
10
22
  entries: number;
11
23
  /**
12
24
  * Overlay entry files NOT copied, because the library resolves their
13
- * identity to a different path. POSIX-relative to the overlay, sorted. Each
14
- * one is also reported through the reporter — see {@link applyCuratedOverlay}.
25
+ * identity to a different path. POSIX-relative to the overlay, sorted.
15
26
  */
16
27
  skipped: string[];
28
+ /** Overlay entries added because the library lacked their identity. Sorted. */
29
+ added: string[];
30
+ /** Corrections patched into the library's own definition. Sorted. */
31
+ corrected: string[];
32
+ /**
33
+ * Overlay entries the library already carries at the same path, so its
34
+ * published definition was kept. Sorted. Not a problem: these are the
35
+ * directory's test fixtures, which the overlay must never copy over a
36
+ * published file (#1148).
37
+ */
38
+ kept: string[];
17
39
  }
18
40
  /**
19
- * Apply the SDK's curated corrections after extracting the raw registry dump.
41
+ * The bundled corrections, checked against the overlay they ship in. A row
42
+ * that names no indexed overlay entry, or a field that entry does not define,
43
+ * is a fault in the SDK's own data, so it throws rather than patching nothing.
44
+ */
45
+ export declare function readOverlayCorrections(overlayPath: string): Promise<OverlayCorrection[]>;
46
+ /**
47
+ * Apply the SDK's curated overlay after extracting the raw registry dump.
20
48
  *
21
- * Files replace the dump's copy, while index rows are a union where the dump
22
- * wins collisions. This is the same contract as the former unpack script: a
23
- * correction changes the referenced file, and a definition absent from the
24
- * dump (notably connector triggers) is made resolvable by its added index row.
49
+ * THE RULE. The overlay ADDS what the library lacks and never replaces what it
50
+ * carries, apart from the deliberate patches listed in {@link CORRECTIONS_FILE}:
25
51
  *
26
- * WHEN THE LIBRARY ALREADY RESOLVES THE IDENTITY ELSEWHERE, the file is not
27
- * copied at all and the skip is reported. That case is not hypothetical: four
28
- * of the bundled `event-*@1.0.0.json` files carry a (nodeType, version) the
29
- * raw dump lacks TODAY but a refreshed catalog serves at its own path — the
30
- * per-object event variants land under `<connector>/events/<object>/`, keeping
31
- * the template's nodeType. Since the union keeps the library's row, copying
32
- * anyway left a file no index row pointed at, which `--check-orphans` (the
33
- * image build passes it) rejects. The three ways out are not equal:
52
+ * - an overlay entry whose (nodeType, version) the library does not index is
53
+ * copied with its sidecar, and its index row is added. This is what makes
54
+ * the connector start triggers resolvable, which the raw dump lacks;
55
+ * - an entry the library indexes at the SAME path is kept as published. The
56
+ * overlay's copy is a snapshot, and the published library moves on: until
57
+ * #1148 every such file was copied over the download while the download's
58
+ * index row stayed, so nine 2026-07 snapshots replaced newer definitions and
59
+ * Outlook `send-email` read `send-mail` (no `saveAsDraft`, no multipart
60
+ * parts) under an index row that said `send-mail-v2`. The entry files carry
61
+ * no date or build number to compare, so "is the published one newer?" is
62
+ * not answerable per file; the answer is that the overlay never decides it;
63
+ * - a listed correction is PATCHED into the library's own definition: the
64
+ * named input fields and sidecar keys are added when absent, and nothing
65
+ * else is touched. It cannot change the operation's object or endpoint, so
66
+ * index row and entry file cannot be made to disagree. When the published
67
+ * definition already has everything, the correction is reported as no
68
+ * longer needed so its row can be removed;
69
+ * - an entry the library indexes at a DIFFERENT path is not copied: the copy
70
+ * would be a file no index row points at, which `--check-orphans` (the
71
+ * image build passes it) rejects, and stamping the flat curated file over
72
+ * each per-object variant the library serves would destroy their schemas.
73
+ * A correction in that position is warned about, since it no longer takes
74
+ * effect;
75
+ * - the SDK's side-tables (`list-envelopes.json`, `invariant-collections.json`)
76
+ * are the SDK's own data and are always copied.
34
77
  *
35
- * - copying and teaching the orphan check to tolerate the file would keep
36
- * the build green and hide the real loss, which is that the hand-verified
37
- * CORRECTION never takes effect once the index points somewhere else;
38
- * - redirecting the correction onto the indexed path cannot be done safely
39
- * here, because ONE event identity maps to MANY per-object paths in a
40
- * refreshed library, and stamping the flat curated definition over each
41
- * per-object variant would destroy the per-object schema the library just
42
- * served — a worse regression than the one being fixed;
43
- * - so the copy is skipped and said out loud. The library keeps the
44
- * definition it resolves, the tree gains no unreachable file, and the
45
- * operator is told which overlay row has been overtaken and needs
46
- * re-verifying. The image build is then green before AND after a refresh.
78
+ * What was done is reported in one line, and recorded in `.curated-overlay.json`
79
+ * beside the index, so a second application recognises its own patches: the
80
+ * record keeps a sha256 of each patched entry and sidecar, and a correction
81
+ * whose files no longer match it is patched again.
47
82
  */
48
83
  export declare function applyCuratedOverlay(libraryPath: string, overlayPath?: string, reporter?: Reporter): Promise<CuratedOverlayResult>;