@uipath/maestro-builder-sdk 6.20.5 → 6.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/api-index.md +72 -72
  2. package/dist/api-members.md +143 -143
  3. package/dist/check.js +34 -160
  4. package/dist/core/actions.d.ts +0 -126
  5. package/dist/core/actions.js +0 -48
  6. package/dist/core/edit-distance.d.ts +8 -0
  7. package/dist/core/edit-distance.js +26 -0
  8. package/dist/core/js-code-spans.d.ts +24 -0
  9. package/dist/core/js-code-spans.js +148 -0
  10. package/dist/core/nodes/node-type.d.ts +17 -2
  11. package/dist/core/typed-raw-node.js +0 -2
  12. package/dist/decompile.js +107 -36
  13. package/dist/flow-node-registry.js +2 -1
  14. package/dist/flow-node-type.d.ts +6 -0
  15. package/dist/flow-output-backing.d.ts +53 -0
  16. package/dist/flow-output-backing.js +200 -0
  17. package/dist/flow-sdk.d.ts +16 -0
  18. package/dist/flow-sdk.js +11 -0
  19. package/dist/flow-variables.d.ts +6 -4
  20. package/dist/flow-variables.js +6 -4
  21. package/dist/nodes/queue/flow/check.d.ts +35 -0
  22. package/dist/nodes/queue/flow/check.js +126 -0
  23. package/dist/nodes/queue/flow/factories.d.ts +49 -0
  24. package/dist/nodes/queue/flow/factories.js +50 -0
  25. package/dist/nodes/queue/flow/family.d.ts +3 -0
  26. package/dist/nodes/queue/flow/family.js +8 -0
  27. package/dist/nodes/queue/flow/index.d.ts +3 -0
  28. package/dist/nodes/queue/flow/index.js +3 -0
  29. package/dist/nodes/queue/flow/node-type.d.ts +8 -0
  30. package/dist/nodes/queue/flow/node-type.js +265 -0
  31. package/dist/nodes/queue/flow/spec.d.ts +92 -0
  32. package/dist/nodes/queue/flow/spec.js +1 -0
  33. package/dist/serialize.js +70 -183
  34. package/package.json +2 -2
  35. /package/dist/{core/queue-record.d.ts → nodes/queue/flow/record.d.ts} +0 -0
  36. /package/dist/{core/queue-record.js → nodes/queue/flow/record.js} +0 -0
package/dist/check.js CHANGED
@@ -11,14 +11,13 @@ import { planContributionBindings } from './core/contribution-bindings.js';
11
11
  import { definitionHasErrorPort, errorPortRefusal } from './core/error-port.js';
12
12
  import { actionVersion, bundledActionNodeType, bundledDefinition, perCallDefinition, resolveContributionDefinition } from './serialize.js';
13
13
  import { sdkFormFieldType } from './core/form-field-type.js';
14
- import { QUEUE_ITEM_RECORD_SCHEMA } from './core/queue-record.js';
15
14
  import { AGENTIC_PROCESS_FORMS } from './core/agentic-process-forms.js';
16
15
  import { checkEventResolution, checkEventSubscription, eventParamsFor, } from './core/event-checks.js';
17
16
  import { checkCookedEscapes } from './flow-expr-check.js';
18
17
  import { FLOW_EXPR_DIALECT, checkBindingLabels, checkBindingPresence, checkConnectorContract as coreCheckConnectorContract, checkConnectorLookups as coreCheckConnectorLookups, checkConnectorSchema as coreCheckConnectorSchema, collectConnectionUses, connectionConnectorConflicts, } from './core/connector-checks.js';
19
18
  import { prepareCommand } from './core/cli-spelling.js';
20
19
  import { commentText } from './core/comment-text.js';
21
- import { editDistance } from './core/edit-distance.js';
20
+ import { nearestName } from './core/edit-distance.js';
22
21
  import { isAnswerField } from './core/hitl-answers.js';
23
22
  import { hitlDerivesOutcomeHandles, hitlExitModel, hitlRoutesPerOutcome, outcomeIdOf } from './core/hitl-routing.js';
24
23
  import { declaredExits, hasExits } from './core/step-ports.js';
@@ -26,6 +25,7 @@ import { stopsAtEnd } from './flow-step-tree.js';
26
25
  import { FLOW_SCHEMA_VERSIONS } from './format-profile.js';
27
26
  import { compareSchemaVersions, schemaVersionRefusal } from './schema-version.js';
28
27
  import { planFlowGlobals, planSharedInputs, sharedInputRoots } from './flow-variables.js';
28
+ import { planOutputBacking } from './flow-output-backing.js';
29
29
  import { ownEntry } from './core/own-entry.js';
30
30
  import { FLOW_NODE_TYPES } from './flow-node-registry.js';
31
31
  import { resolveVersion } from './core/nodes/versioned.js';
@@ -498,8 +498,6 @@ function checkFlow(built, ancestors, opts = {}) {
498
498
  if (s.spec.kind === 'inlineAgent') {
499
499
  checkInlineAgent(s.name, s.spec.inputs, diags, opts);
500
500
  }
501
- if (s.spec.kind === 'queueItem')
502
- checkQueueItem(s.name, s.spec.inputs, diags);
503
501
  {
504
502
  const rule = OUTPUT_READ_RULES[s.spec.kind];
505
503
  if (typeof rule === 'function') {
@@ -1176,6 +1174,22 @@ function checkFlow(built, ancestors, opts = {}) {
1176
1174
  readOutput(field, rest, step, diags);
1177
1175
  continue;
1178
1176
  }
1177
+ // A registered node type that states its output's fields: the same read
1178
+ // rule, worded by its contract and reported through its family's catalog.
1179
+ const fieldsPlaced = registeredSteps.get(name);
1180
+ const fieldsContract = fieldsPlaced?.impl.output(fieldsPlaced.spec);
1181
+ if (fieldsPlaced && fieldsContract?.kind === 'fields') {
1182
+ const found = [];
1183
+ checkDeclaredOutputRead({
1184
+ prefix: fieldsContract.read.codePrefix, what: fieldsContract.read.label, name, field, rest, step,
1185
+ diags: found, withoutReturns: fieldsContract.read.whenUndeclared,
1186
+ declared: fieldsContract.fields === undefined ? undefined : Object.keys(fieldsContract.fields),
1187
+ open: fieldsContract.open,
1188
+ });
1189
+ for (const d of found)
1190
+ diags.push(catalogued(fieldsPlaced.entry, step, d.code, d.message, d.suggestion));
1191
+ continue;
1192
+ }
1179
1193
  // A loop step exposes a fixed set of fields, and only those resolve at run
1180
1194
  // time — `$vars.<loop>.item` reads undefined rather than the iteration
1181
1195
  // item. Catch the wrong spelling here, in the fast loop.
@@ -1302,8 +1316,9 @@ function checkLoopListEnvelope(loop, connectors, opts, diags) {
1302
1316
  * it never rejoins the main path, and when it runs out of steps `emitPortList`
1303
1317
  * gives it an End of its own. `writtenTails` collects those bodies' tails.
1304
1318
  *
1305
- * Every such End maps every output from its own variable
1306
- * (`result <- $vars.result`), the same as a `.return()` that names no value.
1319
+ * Every such End maps every output from what set it on the way (its backing
1320
+ * Variable, `result <- $vars.resultValue`, #1092), or `null` when nothing could,
1321
+ * the same as a `.return()` that names no value.
1307
1322
  * That loses nothing when the flow declares no outputs, or when each output
1308
1323
  * was set on the way: by a `default`, a `{ shared }` input that every root
1309
1324
  * feeds, or `{ updates }` on a step of that path. One warning per End: it
@@ -1456,32 +1471,6 @@ function surelyWritten(tails) {
1456
1471
  return new Set();
1457
1472
  return new Set([...tails[0].written].filter((n) => tails.every((t) => t.written.has(n))));
1458
1473
  }
1459
- /**
1460
- * Closest of `candidates` to `name`: same word ignoring case, one contained in
1461
- * the other, or within two edits (`txt` → `text`, `reveresed` → `reversed`).
1462
- *
1463
- * The suggestion is the whole value of these diagnostics — a subflow's input and
1464
- * output names are the child's, so the author is typing them from memory.
1465
- */
1466
- function nearestName(name, candidates) {
1467
- const lk = name.toLowerCase();
1468
- const exact = candidates.find((c) => c.toLowerCase() === lk);
1469
- if (exact)
1470
- return exact;
1471
- const contained = candidates.find((c) => c.toLowerCase().includes(lk) || lk.includes(c.toLowerCase()));
1472
- if (contained)
1473
- return contained;
1474
- let best;
1475
- let bestD = 3;
1476
- for (const c of candidates) {
1477
- const d = editDistance(lk, c.toLowerCase());
1478
- if (d < bestD) {
1479
- bestD = d;
1480
- best = c;
1481
- }
1482
- }
1483
- return best;
1484
- }
1485
1474
  /**
1486
1475
  * Diagnose a `subflow` step: the child flow itself, and the parent→child
1487
1476
  * binding.
@@ -1778,7 +1767,17 @@ function checkGlobalNames(built, diags) {
1778
1767
  diags.push({ level: p.level, code: p.code, message: p.message, ...(p.suggestion ? { suggestion: p.suggestion } : {}) });
1779
1768
  }
1780
1769
  const vars = [...(built.vars ?? []), ...shared.autoVars];
1781
- for (const p of planFlowGlobals({ inputs: built.inputs ?? [], outputs: built.outputs ?? [], vars }).problems) {
1770
+ const plan = planFlowGlobals({ inputs: built.inputs ?? [], outputs: built.outputs ?? [], vars });
1771
+ for (const p of plan.problems) {
1772
+ diags.push({ level: 'error', code: p.code, message: p.message, ...(p.suggestion ? { suggestion: p.suggestion } : {}) });
1773
+ }
1774
+ if (plan.problems.length)
1775
+ return;
1776
+ // An output the flow sets from inside is emitted with an `inout` Variable
1777
+ // `<output>Value` behind it (#1092); that id must be free. Same plan as
1778
+ // `emittableGlobals`, so a name check passes is one serialize can emit.
1779
+ const sharedOutputs = new Set(shared.targets.filter((t) => t.declaredAs === 'output').map((t) => t.name));
1780
+ for (const p of planOutputBacking(built, plan.outputs, plan.vars, sharedOutputs).problems) {
1782
1781
  diags.push({ level: 'error', code: p.code, message: p.message, ...(p.suggestion ? { suggestion: p.suggestion } : {}) });
1783
1782
  }
1784
1783
  }
@@ -2528,7 +2527,7 @@ function checkDeclaredOutputRead(o) {
2528
2527
  return;
2529
2528
  }
2530
2529
  const wanted = (rest ?? '').replace(/^\./, '').split('.')[0];
2531
- if (!wanted)
2530
+ if (!wanted || o.open)
2532
2531
  return;
2533
2532
  if (o.declared === undefined) {
2534
2533
  diags.push({
@@ -2560,23 +2559,6 @@ function checkRpaWorkflowRead(name, field, rest, spec, step, diags) {
2560
2559
  + `synthesizes for it.`,
2561
2560
  });
2562
2561
  }
2563
- /**
2564
- * A queue step publishes one of two shapes: a plain enqueue publishes the queue
2565
- * ITEM's Orchestrator record (fixed, declared by the serializer from
2566
- * `QUEUE_ITEM_RECORD_SCHEMA`), a `wait: true` publishes the processed result,
2567
- * whose fields only the author's `returns` states.
2568
- */
2569
- function checkQueueItemRead(name, field, rest, spec, step, diags) {
2570
- const waitReturns = Object.keys(spec?.returns ?? {});
2571
- checkDeclaredOutputRead({
2572
- prefix: 'QUEUE', what: spec?.wait ? 'Queue wait' : 'Queue item', name, field, rest, step, diags,
2573
- declared: !spec?.wait
2574
- ? Object.keys(QUEUE_ITEM_RECORD_SCHEMA.properties)
2575
- : waitReturns.length ? waitReturns : undefined,
2576
- withoutReturns: `What the consumer writes into the processed item's result is that automation's business; `
2577
- + `declare the fields you read.`,
2578
- });
2579
- }
2580
2562
  /**
2581
2563
  * THE GATE (flow-builder-sdk#850). Each `returns`-bearing kind maps to the rule
2582
2564
  * that checks a read of its output, or to a stated reason it has none.
@@ -2597,7 +2579,7 @@ const OUTPUT_READ_RULES = {
2597
2579
  agenticProcess: checkAgenticProcessRead,
2598
2580
  agent: checkAgentRead,
2599
2581
  inlineAgent: checkInlineAgentRead,
2600
- queueItem: checkQueueItemRead,
2582
+ queueItem: { exempt: 'Registered: its node type states the fields a read may name (nodes/queue/flow/, a `fields` output contract).' },
2601
2583
  script: {
2602
2584
  exempt: 'Not yet: only the field-map form of a script\'s `returns` gives a list to check against (the '
2603
2585
  + 'type form and the inferred form do not), and script is the most-used step, so its rule lands with '
@@ -3620,31 +3602,6 @@ function checkInlineAgentRead(name, field, rest, spec, step, diags) {
3620
3602
  ...(nearest ? { suggestion: `out('${name}', '${nearest}')` } : {}),
3621
3603
  });
3622
3604
  }
3623
- /**
3624
- * Check a `queueItem(...)` call.
3625
- *
3626
- * WHAT THESE RULES CAN AND CANNOT SEE. Whether the queue exists, whether anything
3627
- * drains it, and what a consumer writes into a processed item's result all live on
3628
- * the tenant. So these cover the mistakes decidable from the call — plus the one
3629
- * mistake the PLATFORM decides and rejects at run time, which is worth catching
3630
- * here because its error arrives from Orchestrator as an HTTP 400 three layers
3631
- * away:
3632
- *
3633
- * - a missing/blank `queue`, `folderPath` or `key`. Without the first two
3634
- * nothing can resolve the node's `resourceBindings.name`, and without `key`
3635
- * nothing joins the node to its bindings — both read as engine errors rather
3636
- * than authoring ones.
3637
- * - a `key` that is not a GUID. The commonest form is passing the queue's NAME
3638
- * where its Orchestrator key belongs.
3639
- * - a NESTED `item`. Orchestrator answers "Property values must be simple (like
3640
- * numbers or text) and not complex or composite data types (like objects or
3641
- * arrays)" — a run-time 400 for something visible in the source.
3642
- * - a `priority` outside the three the node type offers. The platform normalizes
3643
- * an unknown one silently, so it is a wrong RESULT, not an error.
3644
- * - `returns` on a step that does not wait (there is nothing per-tenant to
3645
- * declare), and a `wait: true` step whose result nothing can read.
3646
- * - a non-ISO `dueDate` / `deferDate`.
3647
- */
3648
3605
  /**
3649
3606
  * The five forbidden inputs on an IxP node. They belonged to a prior schema and
3650
3607
  * v1's own authoring reference calls them "the most common training-data-recall
@@ -3715,89 +3672,6 @@ function checkIxpExtract(step, inputs, diags) {
3715
3672
  }
3716
3673
  }
3717
3674
  }
3718
- function checkQueueItem(step, inputs, diags) {
3719
- const at = (code, message, suggestion) => {
3720
- diags.push({ level: 'error', code, message, step, ...(suggestion ? { suggestion } : {}) });
3721
- };
3722
- const warn = (code, message, suggestion) => {
3723
- diags.push({ level: 'warning', code, message, step, ...(suggestion ? { suggestion } : {}) });
3724
- };
3725
- const blank = (v) => v === undefined || v === null || (typeof v === 'string' && v.trim() === '');
3726
- if (blank(inputs?.queue)) {
3727
- at('QUEUE_NO_NAME', `Queue step "${step}" has no \`queue\`. That is the queue's name in Orchestrator, and the `
3728
- + `runtime resolves the queue by name + folder — without it the run fails before dispatch.`, `queue: 'SupplierInvoices'`);
3729
- }
3730
- if (blank(inputs?.folderPath)) {
3731
- at('QUEUE_NO_FOLDER', `Queue step "${step}" has no \`folderPath\`. Queues are folder-scoped, and the runtime `
3732
- + `resolves this one by name + folder.`, `folderPath: 'Shared'`);
3733
- }
3734
- if (blank(inputs?.key)) {
3735
- at('QUEUE_NO_KEY', `Queue step "${step}" has no \`key\`. That is the queue's own Orchestrator key, and it is `
3736
- + `what joins this node to the flow's queue bindings — without it nothing says which `
3737
- + `bindings belong to the node, so it cannot be dispatched. Find it with `
3738
- + `\`uip or queues list --all-folders\`.`, `key: 'fa1a7328-cd17-4525-b5ab-29d86e399312'`);
3739
- }
3740
- else if (!GUID_RE.test(String(inputs.key).trim())) {
3741
- at('QUEUE_KEY_NOT_GUID', `Queue step "${step}"'s \`key\` is ${JSON.stringify(inputs.key)}, which is not an `
3742
- + `Orchestrator key. \`key\` is the GUID the tenant gives the queue; the queue's NAME goes `
3743
- + `in \`queue\` and its folder in \`folderPath\`.`, `key: '<guid>', queue: ${JSON.stringify(inputs.key)}`);
3744
- }
3745
- // The item's data must be FLAT. This is the platform's rule, not ours, and it is
3746
- // enforced at the far end: a nested value earns an HTTP 400 from Orchestrator
3747
- // mid-run, which is a long way from the line that caused it.
3748
- const item = inputs?.item;
3749
- if (item === undefined || item === null) {
3750
- warn('QUEUE_NO_ITEM', `Queue step "${step}" has no \`item\`, so it enqueues an item with no data. That is legal `
3751
- + `— a bare item with a reference is a real pattern — but if the work needs a payload, this `
3752
- + `is where it goes.`, `item: { InvoiceId: input('invoiceRef') }`);
3753
- }
3754
- else if (typeof item !== 'object' || Array.isArray(item)) {
3755
- at('QUEUE_ITEM_NOT_OBJECT', `Queue step "${step}"'s \`item\` is ${Array.isArray(item) ? 'an array' : typeof item}. It `
3756
- + `must be an object of field names to primitive values — that object becomes the queue `
3757
- + `item's \`SpecificContent\`.`, `item: { InvoiceId: 'INV-1', Amount: 120 }`);
3758
- }
3759
- else {
3760
- for (const [k, v] of Object.entries(item)) {
3761
- // An Expr is a reference the runtime resolves — its VALUE may be anything,
3762
- // and nothing local can know, so it is not flagged here.
3763
- if (v instanceof Expr)
3764
- continue;
3765
- if (v !== null && typeof v === 'object') {
3766
- at('QUEUE_ITEM_FIELD_NOT_PRIMITIVE', `Queue step "${step}"'s \`item.${k}\` is ${Array.isArray(v) ? 'an array' : 'an object'}. `
3767
- + `Orchestrator rejects a queue item whose property values are not simple: `
3768
- + `"Property values must be simple (like numbers or text) and not complex or composite `
3769
- + `data types (like objects or arrays)". Flatten it, or JSON-encode it into one string `
3770
- + `field.`, `item: { ${k}: JSON.stringify(...) } // or ${commentText(k)}Id, ${commentText(k)}Name, …`);
3771
- }
3772
- }
3773
- }
3774
- if (inputs?.priority !== undefined && !QUEUE_PRIORITIES.includes(String(inputs.priority))) {
3775
- at('QUEUE_BAD_PRIORITY', `Queue step "${step}"'s \`priority\` is ${JSON.stringify(inputs.priority)}. The node type `
3776
- + `offers exactly ${QUEUE_PRIORITIES.map((p) => `"${p}"`).join(', ')} — anything else is `
3777
- + `normalized silently by the platform, so the item is enqueued at the wrong priority `
3778
- + `rather than rejected.`, `priority: '${nearestName(String(inputs.priority), QUEUE_PRIORITIES) ?? 'Normal'}'`);
3779
- }
3780
- for (const field of ['deferDate', 'dueDate']) {
3781
- const v = inputs?.[field];
3782
- if (typeof v === 'string' && v.trim() !== '' && Number.isNaN(Date.parse(v))) {
3783
- at('QUEUE_BAD_DATE', `Queue step "${step}"'s \`${field}\` is ${JSON.stringify(v)}, which is not a date `
3784
- + `Orchestrator can read. It takes ISO-8601 — a full timestamp with a zone.`, `${field}: '2026-08-05T17:00:00Z'`);
3785
- }
3786
- }
3787
- // `returns` describes what a CONSUMER produced, which only exists if the step
3788
- // waited for one. On a fire-and-forget enqueue it is a misunderstanding worth
3789
- // naming: the output is the queue item's own record, and the serializer already
3790
- // declares its fields.
3791
- if (!inputs?.wait && inputs?.returns && Object.keys(inputs.returns).length) {
3792
- warn('QUEUE_RETURNS_WITHOUT_WAIT', `Queue step "${step}" declares \`returns\` but does not \`wait\`, so nothing produces those `
3793
- + `fields: a fire-and-forget enqueue publishes the queue ITEM's own Orchestrator record `
3794
- + `(\`Key\`, \`Status\`, \`Reference\`, \`SpecificContent\`, …), whose fields are already `
3795
- + `declared for you. \`returns\` describes what a CONSUMER wrote into a processed item's `
3796
- + `result, which needs \`wait: true\`.`, `wait: true`);
3797
- }
3798
- }
3799
- /** The three priorities `core.action.queue.create[-and-wait]`'s form offers. */
3800
- const QUEUE_PRIORITIES = ['Low', 'Normal', 'High'];
3801
3675
  /** Best guess at what the author meant, for a `SCHEDULE_NOT_ISO` suggestion. */
3802
3676
  function nearestInterval(every) {
3803
3677
  // By far the likeliest slip: a correct duration missing the "R/" repeat marker.
@@ -1916,82 +1916,6 @@ export interface ContextIndexRef {
1916
1916
  /** Restrict to one file type; `'All'` (the platform's default) or e.g. `'pdf'`. */
1917
1917
  fileExtension?: string;
1918
1918
  }
1919
- /** The three priorities an Orchestrator queue item can carry. */
1920
- export type QueuePriority = 'Low' | 'Normal' | 'High';
1921
- export interface QueueItemInputs {
1922
- /** The queue's name in Orchestrator — e.g. `'SupplierInvoices'`. */
1923
- queue: string;
1924
- /** The Orchestrator folder holding the queue — e.g. `'Shared'`. */
1925
- folderPath: string;
1926
- /**
1927
- * The queue's own Orchestrator key (a GUID). It is the JOIN between this node
1928
- * and the flow's queue bindings — a node which does not reference its bindings
1929
- * cannot be dispatched — and it is what
1930
- * the designer's queue picker writes. The RUNTIME resolves the queue by
1931
- * `queue` + `folderPath`, so all three are needed and none is redundant.
1932
- *
1933
- * Find it with `uip or queues list --all-folders`.
1934
- */
1935
- key: string;
1936
- /**
1937
- * The work item's own data: a FLAT object of primitive values. It becomes the
1938
- * item's `SpecificContent`, and Orchestrator rejects a nested object or array
1939
- * with "Property values must be simple (like numbers or text)".
1940
- */
1941
- item: Record<string, unknown>;
1942
- /** Processing priority. Defaults to `'Normal'`, as the node type does. */
1943
- priority?: QueuePriority;
1944
- /**
1945
- * A reference string for the item. Optional in general — but a queue created
1946
- * with "enforce unique reference" REQUIRES one and rejects a repeat with
1947
- * `HTTP 409: Duplicate Reference`, so derive it from the flow's input rather
1948
- * than hard-coding it.
1949
- *
1950
- * Which is why it takes an {@link Expr} as well as a literal: the serializer
1951
- * renders it through the same path as any other value, so
1952
- * `reference: input('invoiceRef')` and
1953
- * ``reference: js`${input('invoiceRef')} + "-review"` `` both emit. Typing it
1954
- * as a bare `string` contradicted the advice directly above and stopped two
1955
- * of the SDK's own examples compiling.
1956
- */
1957
- reference?: string | Expr;
1958
- /** Earliest the item may be processed, ISO-8601 (e.g. `'2026-08-01T09:00:00Z'`). */
1959
- deferDate?: string;
1960
- /** Latest the item should be processed, ISO-8601. What an SLA is measured against. */
1961
- dueDate?: string;
1962
- /**
1963
- * `false` (the default) enqueues and moves on — `core.action.queue.create`.
1964
- * `true` PARKS the flow until whatever consumes the queue has processed the
1965
- * item, and publishes that result — `core.action.queue.create-and-wait`.
1966
- *
1967
- * The two are one construct with two data paths, so this is one field rather
1968
- * than two factories. Waiting is not free: nothing completes the item but a
1969
- * consumer (an RPA process bound to the queue), so a flow that waits on a queue
1970
- * nobody drains waits forever.
1971
- */
1972
- wait?: boolean;
1973
- /**
1974
- * Only for `wait: true`: the fields the PROCESSED item's result carries, and
1975
- * their types (e.g. `{ approved: 'boolean' }`). Required if anything reads the
1976
- * step's output.
1977
- *
1978
- * Why you have to say: what a consumer writes into a transaction's `Output` is
1979
- * that automation's business, not the queue's — no definition declares it and
1980
- * authoring happens offline. Without it `$vars.<step>.output.<field>` reads from
1981
- * an object with no declared fields, and nothing could tell a real field from
1982
- * a typo.
1983
- *
1984
- * `wait: false` needs none: what it publishes is the queue ITEM's own
1985
- * Orchestrator record (`Key`, `Status`, `Reference`, `SpecificContent`, …),
1986
- * which is the same for every queue, so the serializer declares it for you.
1987
- *
1988
- * @enforcedBy QUEUE_READ_UNKNOWN_FIELD A read must name a field of the record
1989
- * (`wait: false`) or of this `returns` (`wait: true`).
1990
- * @enforcedBy QUEUE_READ_WITHOUT_RETURNS Reading a field off a `wait: true` result
1991
- * requires declaring it here.
1992
- */
1993
- returns?: Record<string, ReturnFieldType>;
1994
- }
1995
1919
  /**
1996
1920
  * Every action kind, keyed by kind, to the body of its spec — the arm's fields
1997
1921
  * other than `kind`. {@link ActionSpec} is built from it.
@@ -2064,10 +1988,6 @@ export interface FlowActionSpecs {
2064
1988
  inlineAgent: {
2065
1989
  inputs: InlineAgentInputs;
2066
1990
  };
2067
- /** The spec {@link queueItem} builds. */
2068
- queueItem: {
2069
- inputs: QueueItemInputs;
2070
- };
2071
1991
  /** The spec {@link summarize} builds. */
2072
1992
  summarize: {
2073
1993
  inputs: SummarizeInputs;
@@ -2713,52 +2633,6 @@ export declare function agent(inputs: AgentInputs): ActionSpec;
2713
2633
  * @returns An action spec to pass to `.step(name, …)`.
2714
2634
  */
2715
2635
  export declare function inlineAgent(inputs: InlineAgentInputs): ActionSpec;
2716
- /**
2717
- * Declare an Orchestrator QUEUE ITEM step.
2718
- *
2719
- * @remarks
2720
- * A queue is Orchestrator's work list: something puts items on it, and an
2721
- * automation bound to the queue takes them off one at a time. This step is the
2722
- * putting-on half.
2723
- *
2724
- * `queue` + `folderPath` are what the runtime resolves the queue by, and `key` is
2725
- * the queue's own Orchestrator key: it joins this node to the flow's queue
2726
- * bindings, which the serializer emits and points the node at. All three, for the
2727
- * same reason `rpaWorkflow` takes three — the key is the AUTHORING identity, the
2728
- * two bindings are the RUNTIME one.
2729
- *
2730
- * `item` is the work item's data. It becomes the item's `SpecificContent`, and it
2731
- * must be FLAT: Orchestrator rejects a nested object or array outright.
2732
- *
2733
- * **`wait`** picks between the family's two node types, which are one construct
2734
- * with two data paths. Default `false` enqueues and moves on, publishing the queue
2735
- * item's own Orchestrator record — read a field with `out('<step>', 'Key')`, and
2736
- * nothing extra has to be declared because that record's shape is the same for
2737
- * every queue. `wait: true` PARKS the flow until the item has been processed and
2738
- * publishes the consumer's result instead, which is per-automation — so a read of
2739
- * it needs `returns`, exactly as an rpa process's output does.
2740
- *
2741
- * What no rung can tell you: whether anything actually drains this queue. A
2742
- * `wait: true` step on a queue with no consumer waits until it times out.
2743
- *
2744
- * @example
2745
- * **Enqueue a work item and read its Orchestrator key**
2746
- * ```ts
2747
- * .step('enqueue', queueItem({
2748
- * queue: 'SupplierInvoices',
2749
- * folderPath: 'Shared',
2750
- * key: 'fa1a7328-cd17-4525-b5ab-29d86e399312',
2751
- * item: { InvoiceId: input('invoiceRef'), Amount: input('amount') },
2752
- * reference: 'INV-2031',
2753
- * }))
2754
- * .return({ itemKey: out('enqueue', 'Key') })
2755
- * ```
2756
- *
2757
- * @param inputs - The `queue` and `folderPath`, the `item` to add, and whether
2758
- * to `wait` for it to be processed.
2759
- * @returns An action spec to pass to `.step(name, …)`.
2760
- */
2761
- export declare function queueItem(inputs: QueueItemInputs): ActionSpec;
2762
2636
  /**
2763
2637
  * Declare an Integration Service connector action — the typed form, where a
2764
2638
  * generated descriptor supplies the nodeType and statically-checked input types:
@@ -711,54 +711,6 @@ export function agent(inputs) {
711
711
  export function inlineAgent(inputs) {
712
712
  return builtinActionSpec({ kind: 'inlineAgent', inputs });
713
713
  }
714
- /**
715
- * Declare an Orchestrator QUEUE ITEM step.
716
- *
717
- * @remarks
718
- * A queue is Orchestrator's work list: something puts items on it, and an
719
- * automation bound to the queue takes them off one at a time. This step is the
720
- * putting-on half.
721
- *
722
- * `queue` + `folderPath` are what the runtime resolves the queue by, and `key` is
723
- * the queue's own Orchestrator key: it joins this node to the flow's queue
724
- * bindings, which the serializer emits and points the node at. All three, for the
725
- * same reason `rpaWorkflow` takes three — the key is the AUTHORING identity, the
726
- * two bindings are the RUNTIME one.
727
- *
728
- * `item` is the work item's data. It becomes the item's `SpecificContent`, and it
729
- * must be FLAT: Orchestrator rejects a nested object or array outright.
730
- *
731
- * **`wait`** picks between the family's two node types, which are one construct
732
- * with two data paths. Default `false` enqueues and moves on, publishing the queue
733
- * item's own Orchestrator record — read a field with `out('<step>', 'Key')`, and
734
- * nothing extra has to be declared because that record's shape is the same for
735
- * every queue. `wait: true` PARKS the flow until the item has been processed and
736
- * publishes the consumer's result instead, which is per-automation — so a read of
737
- * it needs `returns`, exactly as an rpa process's output does.
738
- *
739
- * What no rung can tell you: whether anything actually drains this queue. A
740
- * `wait: true` step on a queue with no consumer waits until it times out.
741
- *
742
- * @example
743
- * **Enqueue a work item and read its Orchestrator key**
744
- * ```ts
745
- * .step('enqueue', queueItem({
746
- * queue: 'SupplierInvoices',
747
- * folderPath: 'Shared',
748
- * key: 'fa1a7328-cd17-4525-b5ab-29d86e399312',
749
- * item: { InvoiceId: input('invoiceRef'), Amount: input('amount') },
750
- * reference: 'INV-2031',
751
- * }))
752
- * .return({ itemKey: out('enqueue', 'Key') })
753
- * ```
754
- *
755
- * @param inputs - The `queue` and `folderPath`, the `item` to add, and whether
756
- * to `wait` for it to be processed.
757
- * @returns An action spec to pass to `.step(name, …)`.
758
- */
759
- export function queueItem(inputs) {
760
- return builtinActionSpec({ kind: 'queueItem', inputs });
761
- }
762
714
  export function connector(a, b, c, d) {
763
715
  if (typeof a === 'string') {
764
716
  const opts = (d ?? {});
@@ -8,3 +8,11 @@
8
8
  */
9
9
  /** Levenshtein distance, two rows. Short strings only (names and ids). */
10
10
  export declare function editDistance(a: string, b: string): number;
11
+ /**
12
+ * Closest of `candidates` to `name`: same word ignoring case, one contained in
13
+ * the other, or within two edits (`txt` → `text`, `reveresed` → `reversed`).
14
+ *
15
+ * Shared by Flow's `check` and the node families' rules, so a family's
16
+ * suggestion matches the pipeline's.
17
+ */
18
+ export declare function nearestName(name: string, candidates: string[]): string | undefined;
@@ -18,3 +18,29 @@ export function editDistance(a, b) {
18
18
  }
19
19
  return prev[b.length];
20
20
  }
21
+ /**
22
+ * Closest of `candidates` to `name`: same word ignoring case, one contained in
23
+ * the other, or within two edits (`txt` → `text`, `reveresed` → `reversed`).
24
+ *
25
+ * Shared by Flow's `check` and the node families' rules, so a family's
26
+ * suggestion matches the pipeline's.
27
+ */
28
+ export function nearestName(name, candidates) {
29
+ const lk = name.toLowerCase();
30
+ const exact = candidates.find((c) => c.toLowerCase() === lk);
31
+ if (exact)
32
+ return exact;
33
+ const contained = candidates.find((c) => c.toLowerCase().includes(lk) || lk.includes(c.toLowerCase()));
34
+ if (contained)
35
+ return contained;
36
+ let best;
37
+ let bestD = 3;
38
+ for (const c of candidates) {
39
+ const d = editDistance(lk, c.toLowerCase());
40
+ if (d < bestD) {
41
+ bestD = d;
42
+ best = c;
43
+ }
44
+ }
45
+ return best;
46
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The parts of a JavaScript expression or script body that are code.
3
+ *
4
+ * Short version: `$vars.summary` inside a quoted string is text, not a read.
5
+ * A rewrite that renames `$vars.<name>` (a step's node id, an output's backing
6
+ * Variable, #1092) must leave string literals, comments and regex literals
7
+ * alone, or it changes what the flow does:
8
+ *
9
+ * ```js
10
+ * return "$vars.summary" + $vars.summary;
11
+ * // ^^^^^^^^^^^^^^^ text: kept ^^^^^^^^^^^^^ code: renamed
12
+ * ```
13
+ *
14
+ * A template literal's text is kept too, and its `${…}` holes are code.
15
+ *
16
+ * This is a scanner, not a parser. It tells a regex literal from a division by
17
+ * the character before the `/` (the usual heuristic), so `return /"/` is read
18
+ * as a division. Nothing in a flow's expressions depends on that case.
19
+ */
20
+ /**
21
+ * `text` with `fn` applied to each run of code, and every string, template
22
+ * text, comment and regex literal copied as written.
23
+ */
24
+ export declare function mapJsCode(text: string, fn: (code: string) => string): string;