@uipath/maestro-builder-sdk 6.20.6 → 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.
- package/dist/api-index.md +72 -72
- package/dist/api-members.md +143 -143
- package/dist/check.js +19 -157
- package/dist/core/actions.d.ts +0 -126
- package/dist/core/actions.js +0 -48
- package/dist/core/edit-distance.d.ts +8 -0
- package/dist/core/edit-distance.js +26 -0
- package/dist/core/nodes/node-type.d.ts +17 -2
- package/dist/core/typed-raw-node.js +0 -2
- package/dist/decompile.js +0 -31
- package/dist/flow-node-registry.js +2 -1
- package/dist/flow-node-type.d.ts +6 -0
- package/dist/flow-sdk.d.ts +1 -0
- package/dist/flow-sdk.js +1 -0
- package/dist/nodes/queue/flow/check.d.ts +35 -0
- package/dist/nodes/queue/flow/check.js +126 -0
- package/dist/nodes/queue/flow/factories.d.ts +49 -0
- package/dist/nodes/queue/flow/factories.js +50 -0
- package/dist/nodes/queue/flow/family.d.ts +3 -0
- package/dist/nodes/queue/flow/family.js +8 -0
- package/dist/nodes/queue/flow/index.d.ts +3 -0
- package/dist/nodes/queue/flow/index.js +3 -0
- package/dist/nodes/queue/flow/node-type.d.ts +8 -0
- package/dist/nodes/queue/flow/node-type.js +265 -0
- package/dist/nodes/queue/flow/spec.d.ts +92 -0
- package/dist/nodes/queue/flow/spec.js +1 -0
- package/dist/serialize.js +1 -161
- package/package.json +2 -2
- /package/dist/{core/queue-record.d.ts → nodes/queue/flow/record.d.ts} +0 -0
- /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 {
|
|
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';
|
|
@@ -499,8 +498,6 @@ function checkFlow(built, ancestors, opts = {}) {
|
|
|
499
498
|
if (s.spec.kind === 'inlineAgent') {
|
|
500
499
|
checkInlineAgent(s.name, s.spec.inputs, diags, opts);
|
|
501
500
|
}
|
|
502
|
-
if (s.spec.kind === 'queueItem')
|
|
503
|
-
checkQueueItem(s.name, s.spec.inputs, diags);
|
|
504
501
|
{
|
|
505
502
|
const rule = OUTPUT_READ_RULES[s.spec.kind];
|
|
506
503
|
if (typeof rule === 'function') {
|
|
@@ -1177,6 +1174,22 @@ function checkFlow(built, ancestors, opts = {}) {
|
|
|
1177
1174
|
readOutput(field, rest, step, diags);
|
|
1178
1175
|
continue;
|
|
1179
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
|
+
}
|
|
1180
1193
|
// A loop step exposes a fixed set of fields, and only those resolve at run
|
|
1181
1194
|
// time — `$vars.<loop>.item` reads undefined rather than the iteration
|
|
1182
1195
|
// item. Catch the wrong spelling here, in the fast loop.
|
|
@@ -1458,32 +1471,6 @@ function surelyWritten(tails) {
|
|
|
1458
1471
|
return new Set();
|
|
1459
1472
|
return new Set([...tails[0].written].filter((n) => tails.every((t) => t.written.has(n))));
|
|
1460
1473
|
}
|
|
1461
|
-
/**
|
|
1462
|
-
* Closest of `candidates` to `name`: same word ignoring case, one contained in
|
|
1463
|
-
* the other, or within two edits (`txt` → `text`, `reveresed` → `reversed`).
|
|
1464
|
-
*
|
|
1465
|
-
* The suggestion is the whole value of these diagnostics — a subflow's input and
|
|
1466
|
-
* output names are the child's, so the author is typing them from memory.
|
|
1467
|
-
*/
|
|
1468
|
-
function nearestName(name, candidates) {
|
|
1469
|
-
const lk = name.toLowerCase();
|
|
1470
|
-
const exact = candidates.find((c) => c.toLowerCase() === lk);
|
|
1471
|
-
if (exact)
|
|
1472
|
-
return exact;
|
|
1473
|
-
const contained = candidates.find((c) => c.toLowerCase().includes(lk) || lk.includes(c.toLowerCase()));
|
|
1474
|
-
if (contained)
|
|
1475
|
-
return contained;
|
|
1476
|
-
let best;
|
|
1477
|
-
let bestD = 3;
|
|
1478
|
-
for (const c of candidates) {
|
|
1479
|
-
const d = editDistance(lk, c.toLowerCase());
|
|
1480
|
-
if (d < bestD) {
|
|
1481
|
-
bestD = d;
|
|
1482
|
-
best = c;
|
|
1483
|
-
}
|
|
1484
|
-
}
|
|
1485
|
-
return best;
|
|
1486
|
-
}
|
|
1487
1474
|
/**
|
|
1488
1475
|
* Diagnose a `subflow` step: the child flow itself, and the parent→child
|
|
1489
1476
|
* binding.
|
|
@@ -2540,7 +2527,7 @@ function checkDeclaredOutputRead(o) {
|
|
|
2540
2527
|
return;
|
|
2541
2528
|
}
|
|
2542
2529
|
const wanted = (rest ?? '').replace(/^\./, '').split('.')[0];
|
|
2543
|
-
if (!wanted)
|
|
2530
|
+
if (!wanted || o.open)
|
|
2544
2531
|
return;
|
|
2545
2532
|
if (o.declared === undefined) {
|
|
2546
2533
|
diags.push({
|
|
@@ -2572,23 +2559,6 @@ function checkRpaWorkflowRead(name, field, rest, spec, step, diags) {
|
|
|
2572
2559
|
+ `synthesizes for it.`,
|
|
2573
2560
|
});
|
|
2574
2561
|
}
|
|
2575
|
-
/**
|
|
2576
|
-
* A queue step publishes one of two shapes: a plain enqueue publishes the queue
|
|
2577
|
-
* ITEM's Orchestrator record (fixed, declared by the serializer from
|
|
2578
|
-
* `QUEUE_ITEM_RECORD_SCHEMA`), a `wait: true` publishes the processed result,
|
|
2579
|
-
* whose fields only the author's `returns` states.
|
|
2580
|
-
*/
|
|
2581
|
-
function checkQueueItemRead(name, field, rest, spec, step, diags) {
|
|
2582
|
-
const waitReturns = Object.keys(spec?.returns ?? {});
|
|
2583
|
-
checkDeclaredOutputRead({
|
|
2584
|
-
prefix: 'QUEUE', what: spec?.wait ? 'Queue wait' : 'Queue item', name, field, rest, step, diags,
|
|
2585
|
-
declared: !spec?.wait
|
|
2586
|
-
? Object.keys(QUEUE_ITEM_RECORD_SCHEMA.properties)
|
|
2587
|
-
: waitReturns.length ? waitReturns : undefined,
|
|
2588
|
-
withoutReturns: `What the consumer writes into the processed item's result is that automation's business; `
|
|
2589
|
-
+ `declare the fields you read.`,
|
|
2590
|
-
});
|
|
2591
|
-
}
|
|
2592
2562
|
/**
|
|
2593
2563
|
* THE GATE (flow-builder-sdk#850). Each `returns`-bearing kind maps to the rule
|
|
2594
2564
|
* that checks a read of its output, or to a stated reason it has none.
|
|
@@ -2609,7 +2579,7 @@ const OUTPUT_READ_RULES = {
|
|
|
2609
2579
|
agenticProcess: checkAgenticProcessRead,
|
|
2610
2580
|
agent: checkAgentRead,
|
|
2611
2581
|
inlineAgent: checkInlineAgentRead,
|
|
2612
|
-
queueItem:
|
|
2582
|
+
queueItem: { exempt: 'Registered: its node type states the fields a read may name (nodes/queue/flow/, a `fields` output contract).' },
|
|
2613
2583
|
script: {
|
|
2614
2584
|
exempt: 'Not yet: only the field-map form of a script\'s `returns` gives a list to check against (the '
|
|
2615
2585
|
+ 'type form and the inferred form do not), and script is the most-used step, so its rule lands with '
|
|
@@ -3632,31 +3602,6 @@ function checkInlineAgentRead(name, field, rest, spec, step, diags) {
|
|
|
3632
3602
|
...(nearest ? { suggestion: `out('${name}', '${nearest}')` } : {}),
|
|
3633
3603
|
});
|
|
3634
3604
|
}
|
|
3635
|
-
/**
|
|
3636
|
-
* Check a `queueItem(...)` call.
|
|
3637
|
-
*
|
|
3638
|
-
* WHAT THESE RULES CAN AND CANNOT SEE. Whether the queue exists, whether anything
|
|
3639
|
-
* drains it, and what a consumer writes into a processed item's result all live on
|
|
3640
|
-
* the tenant. So these cover the mistakes decidable from the call — plus the one
|
|
3641
|
-
* mistake the PLATFORM decides and rejects at run time, which is worth catching
|
|
3642
|
-
* here because its error arrives from Orchestrator as an HTTP 400 three layers
|
|
3643
|
-
* away:
|
|
3644
|
-
*
|
|
3645
|
-
* - a missing/blank `queue`, `folderPath` or `key`. Without the first two
|
|
3646
|
-
* nothing can resolve the node's `resourceBindings.name`, and without `key`
|
|
3647
|
-
* nothing joins the node to its bindings — both read as engine errors rather
|
|
3648
|
-
* than authoring ones.
|
|
3649
|
-
* - a `key` that is not a GUID. The commonest form is passing the queue's NAME
|
|
3650
|
-
* where its Orchestrator key belongs.
|
|
3651
|
-
* - a NESTED `item`. Orchestrator answers "Property values must be simple (like
|
|
3652
|
-
* numbers or text) and not complex or composite data types (like objects or
|
|
3653
|
-
* arrays)" — a run-time 400 for something visible in the source.
|
|
3654
|
-
* - a `priority` outside the three the node type offers. The platform normalizes
|
|
3655
|
-
* an unknown one silently, so it is a wrong RESULT, not an error.
|
|
3656
|
-
* - `returns` on a step that does not wait (there is nothing per-tenant to
|
|
3657
|
-
* declare), and a `wait: true` step whose result nothing can read.
|
|
3658
|
-
* - a non-ISO `dueDate` / `deferDate`.
|
|
3659
|
-
*/
|
|
3660
3605
|
/**
|
|
3661
3606
|
* The five forbidden inputs on an IxP node. They belonged to a prior schema and
|
|
3662
3607
|
* v1's own authoring reference calls them "the most common training-data-recall
|
|
@@ -3727,89 +3672,6 @@ function checkIxpExtract(step, inputs, diags) {
|
|
|
3727
3672
|
}
|
|
3728
3673
|
}
|
|
3729
3674
|
}
|
|
3730
|
-
function checkQueueItem(step, inputs, diags) {
|
|
3731
|
-
const at = (code, message, suggestion) => {
|
|
3732
|
-
diags.push({ level: 'error', code, message, step, ...(suggestion ? { suggestion } : {}) });
|
|
3733
|
-
};
|
|
3734
|
-
const warn = (code, message, suggestion) => {
|
|
3735
|
-
diags.push({ level: 'warning', code, message, step, ...(suggestion ? { suggestion } : {}) });
|
|
3736
|
-
};
|
|
3737
|
-
const blank = (v) => v === undefined || v === null || (typeof v === 'string' && v.trim() === '');
|
|
3738
|
-
if (blank(inputs?.queue)) {
|
|
3739
|
-
at('QUEUE_NO_NAME', `Queue step "${step}" has no \`queue\`. That is the queue's name in Orchestrator, and the `
|
|
3740
|
-
+ `runtime resolves the queue by name + folder — without it the run fails before dispatch.`, `queue: 'SupplierInvoices'`);
|
|
3741
|
-
}
|
|
3742
|
-
if (blank(inputs?.folderPath)) {
|
|
3743
|
-
at('QUEUE_NO_FOLDER', `Queue step "${step}" has no \`folderPath\`. Queues are folder-scoped, and the runtime `
|
|
3744
|
-
+ `resolves this one by name + folder.`, `folderPath: 'Shared'`);
|
|
3745
|
-
}
|
|
3746
|
-
if (blank(inputs?.key)) {
|
|
3747
|
-
at('QUEUE_NO_KEY', `Queue step "${step}" has no \`key\`. That is the queue's own Orchestrator key, and it is `
|
|
3748
|
-
+ `what joins this node to the flow's queue bindings — without it nothing says which `
|
|
3749
|
-
+ `bindings belong to the node, so it cannot be dispatched. Find it with `
|
|
3750
|
-
+ `\`uip or queues list --all-folders\`.`, `key: 'fa1a7328-cd17-4525-b5ab-29d86e399312'`);
|
|
3751
|
-
}
|
|
3752
|
-
else if (!GUID_RE.test(String(inputs.key).trim())) {
|
|
3753
|
-
at('QUEUE_KEY_NOT_GUID', `Queue step "${step}"'s \`key\` is ${JSON.stringify(inputs.key)}, which is not an `
|
|
3754
|
-
+ `Orchestrator key. \`key\` is the GUID the tenant gives the queue; the queue's NAME goes `
|
|
3755
|
-
+ `in \`queue\` and its folder in \`folderPath\`.`, `key: '<guid>', queue: ${JSON.stringify(inputs.key)}`);
|
|
3756
|
-
}
|
|
3757
|
-
// The item's data must be FLAT. This is the platform's rule, not ours, and it is
|
|
3758
|
-
// enforced at the far end: a nested value earns an HTTP 400 from Orchestrator
|
|
3759
|
-
// mid-run, which is a long way from the line that caused it.
|
|
3760
|
-
const item = inputs?.item;
|
|
3761
|
-
if (item === undefined || item === null) {
|
|
3762
|
-
warn('QUEUE_NO_ITEM', `Queue step "${step}" has no \`item\`, so it enqueues an item with no data. That is legal `
|
|
3763
|
-
+ `— a bare item with a reference is a real pattern — but if the work needs a payload, this `
|
|
3764
|
-
+ `is where it goes.`, `item: { InvoiceId: input('invoiceRef') }`);
|
|
3765
|
-
}
|
|
3766
|
-
else if (typeof item !== 'object' || Array.isArray(item)) {
|
|
3767
|
-
at('QUEUE_ITEM_NOT_OBJECT', `Queue step "${step}"'s \`item\` is ${Array.isArray(item) ? 'an array' : typeof item}. It `
|
|
3768
|
-
+ `must be an object of field names to primitive values — that object becomes the queue `
|
|
3769
|
-
+ `item's \`SpecificContent\`.`, `item: { InvoiceId: 'INV-1', Amount: 120 }`);
|
|
3770
|
-
}
|
|
3771
|
-
else {
|
|
3772
|
-
for (const [k, v] of Object.entries(item)) {
|
|
3773
|
-
// An Expr is a reference the runtime resolves — its VALUE may be anything,
|
|
3774
|
-
// and nothing local can know, so it is not flagged here.
|
|
3775
|
-
if (v instanceof Expr)
|
|
3776
|
-
continue;
|
|
3777
|
-
if (v !== null && typeof v === 'object') {
|
|
3778
|
-
at('QUEUE_ITEM_FIELD_NOT_PRIMITIVE', `Queue step "${step}"'s \`item.${k}\` is ${Array.isArray(v) ? 'an array' : 'an object'}. `
|
|
3779
|
-
+ `Orchestrator rejects a queue item whose property values are not simple: `
|
|
3780
|
-
+ `"Property values must be simple (like numbers or text) and not complex or composite `
|
|
3781
|
-
+ `data types (like objects or arrays)". Flatten it, or JSON-encode it into one string `
|
|
3782
|
-
+ `field.`, `item: { ${k}: JSON.stringify(...) } // or ${commentText(k)}Id, ${commentText(k)}Name, …`);
|
|
3783
|
-
}
|
|
3784
|
-
}
|
|
3785
|
-
}
|
|
3786
|
-
if (inputs?.priority !== undefined && !QUEUE_PRIORITIES.includes(String(inputs.priority))) {
|
|
3787
|
-
at('QUEUE_BAD_PRIORITY', `Queue step "${step}"'s \`priority\` is ${JSON.stringify(inputs.priority)}. The node type `
|
|
3788
|
-
+ `offers exactly ${QUEUE_PRIORITIES.map((p) => `"${p}"`).join(', ')} — anything else is `
|
|
3789
|
-
+ `normalized silently by the platform, so the item is enqueued at the wrong priority `
|
|
3790
|
-
+ `rather than rejected.`, `priority: '${nearestName(String(inputs.priority), QUEUE_PRIORITIES) ?? 'Normal'}'`);
|
|
3791
|
-
}
|
|
3792
|
-
for (const field of ['deferDate', 'dueDate']) {
|
|
3793
|
-
const v = inputs?.[field];
|
|
3794
|
-
if (typeof v === 'string' && v.trim() !== '' && Number.isNaN(Date.parse(v))) {
|
|
3795
|
-
at('QUEUE_BAD_DATE', `Queue step "${step}"'s \`${field}\` is ${JSON.stringify(v)}, which is not a date `
|
|
3796
|
-
+ `Orchestrator can read. It takes ISO-8601 — a full timestamp with a zone.`, `${field}: '2026-08-05T17:00:00Z'`);
|
|
3797
|
-
}
|
|
3798
|
-
}
|
|
3799
|
-
// `returns` describes what a CONSUMER produced, which only exists if the step
|
|
3800
|
-
// waited for one. On a fire-and-forget enqueue it is a misunderstanding worth
|
|
3801
|
-
// naming: the output is the queue item's own record, and the serializer already
|
|
3802
|
-
// declares its fields.
|
|
3803
|
-
if (!inputs?.wait && inputs?.returns && Object.keys(inputs.returns).length) {
|
|
3804
|
-
warn('QUEUE_RETURNS_WITHOUT_WAIT', `Queue step "${step}" declares \`returns\` but does not \`wait\`, so nothing produces those `
|
|
3805
|
-
+ `fields: a fire-and-forget enqueue publishes the queue ITEM's own Orchestrator record `
|
|
3806
|
-
+ `(\`Key\`, \`Status\`, \`Reference\`, \`SpecificContent\`, …), whose fields are already `
|
|
3807
|
-
+ `declared for you. \`returns\` describes what a CONSUMER wrote into a processed item's `
|
|
3808
|
-
+ `result, which needs \`wait: true\`.`, `wait: true`);
|
|
3809
|
-
}
|
|
3810
|
-
}
|
|
3811
|
-
/** The three priorities `core.action.queue.create[-and-wait]`'s form offers. */
|
|
3812
|
-
const QUEUE_PRIORITIES = ['Low', 'Normal', 'High'];
|
|
3813
3675
|
/** Best guess at what the author meant, for a `SCHEDULE_NOT_ISO` suggestion. */
|
|
3814
3676
|
function nearestInterval(every) {
|
|
3815
3677
|
// By far the likeliest slip: a correct duration missing the "R/" repeat marker.
|
package/dist/core/actions.d.ts
CHANGED
|
@@ -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:
|
package/dist/core/actions.js
CHANGED
|
@@ -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
|
+
}
|
|
@@ -45,12 +45,26 @@ export interface OutputRead {
|
|
|
45
45
|
/** The step whose expression contains the read. */
|
|
46
46
|
reader: string;
|
|
47
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* How the artifact words a read of a `fields` output: the code prefix its read
|
|
50
|
+
* diagnostics share (`<PREFIX>_READ_NOT_OUTPUT`, `_READ_WITHOUT_RETURNS`,
|
|
51
|
+
* `_READ_UNKNOWN_FIELD`, each in the family's catalog), how a message names the
|
|
52
|
+
* node (`'Queue item'`), and what to tell an author who declared no fields.
|
|
53
|
+
*/
|
|
54
|
+
export interface FieldsRead {
|
|
55
|
+
readonly codePrefix: string;
|
|
56
|
+
readonly label: string;
|
|
57
|
+
readonly whenUndeclared: string;
|
|
58
|
+
}
|
|
48
59
|
/**
|
|
49
60
|
* What reading a node's output yields at run time.
|
|
50
61
|
*
|
|
51
62
|
* `none` keeps the diagnostic code of the rule it replaces
|
|
52
63
|
* (`DATAFABRIC_DELETE_HAS_NO_OUTPUT`, `MOCK_HAS_NO_OUTPUT`, …) and builds the
|
|
53
|
-
* message itself, so a port changes no diagnostic an author sees.
|
|
64
|
+
* message itself, so a port changes no diagnostic an author sees. `fields`
|
|
65
|
+
* states the fields a read may name — `undefined` when the author declared none,
|
|
66
|
+
* which makes any field read its own mistake — and `read` keeps the wording of
|
|
67
|
+
* the read rule it replaces, for the same reason. `open` admits any field.
|
|
54
68
|
*/
|
|
55
69
|
export type OutputContract = {
|
|
56
70
|
readonly kind: 'none';
|
|
@@ -58,8 +72,9 @@ export type OutputContract = {
|
|
|
58
72
|
message(read: OutputRead): string;
|
|
59
73
|
} | {
|
|
60
74
|
readonly kind: 'fields';
|
|
61
|
-
readonly fields: Readonly<Record<string, TypeDesc
|
|
75
|
+
readonly fields: Readonly<Record<string, TypeDesc>> | undefined;
|
|
62
76
|
readonly open?: boolean;
|
|
77
|
+
readonly read: FieldsRead;
|
|
63
78
|
} | {
|
|
64
79
|
readonly kind: 'opaque';
|
|
65
80
|
};
|
|
@@ -23,8 +23,6 @@ import { ownEntry } from './own-entry.js';
|
|
|
23
23
|
export const TYPED_FACTORIES = {
|
|
24
24
|
'core.action.http': { factory: 'http({ managed: false })' },
|
|
25
25
|
'core.action.http.v2': { factory: 'http({ managed: true })' },
|
|
26
|
-
'core.action.queue.create': { factory: 'queueItem()' },
|
|
27
|
-
'core.action.queue.create-and-wait': { factory: 'queueItem({ wait: true })' },
|
|
28
26
|
'core.control.end': { factory: '.return()' },
|
|
29
27
|
'core.logic.decision': { factory: '.branch()' },
|
|
30
28
|
'core.logic.dowhile': { factory: '.doWhile(name, condition, body, { limit, breakEnabled })' },
|
package/dist/decompile.js
CHANGED
|
@@ -228,8 +228,6 @@ const T = {
|
|
|
228
228
|
hitlQuickForm: 'uipath.human-in-the-loop.quick-form',
|
|
229
229
|
hitlActionApp: 'uipath.human-in-the-loop.coded-action-app',
|
|
230
230
|
hitlDocValidation: 'uipath.human-in-the-loop.document-validation',
|
|
231
|
-
queueCreate: 'core.action.queue.create',
|
|
232
|
-
queueCreateAndWait: 'core.action.queue.create-and-wait',
|
|
233
231
|
summarize: 'uipath.pattern.deep-rag',
|
|
234
232
|
batchTransform: 'uipath.pattern.batch-transform',
|
|
235
233
|
sendMessage: 'uipath.conversational.send-message',
|
|
@@ -644,35 +642,6 @@ function emitStepSpec(node, imp, inputNames, o, graph) {
|
|
|
644
642
|
case T.hitlActionApp:
|
|
645
643
|
case T.hitlDocValidation:
|
|
646
644
|
return emitHitl(node, imp, inputNames, graph);
|
|
647
|
-
case T.queueCreate:
|
|
648
|
-
case T.queueCreateAndWait: {
|
|
649
|
-
// `itemData` is the node's name for the surface's `item` (the reference
|
|
650
|
-
// documents the mapping); `queue` carries the three identity fields.
|
|
651
|
-
const q = (inputs.queue ?? {});
|
|
652
|
-
const rows = Object.entries((inputs.itemData ?? {}))
|
|
653
|
-
.map(([k, v]) => [k, emitVal(v, imp, inputNames)]);
|
|
654
|
-
const optStr = (key) => {
|
|
655
|
-
const raw = unwrapSource(inputs[key]);
|
|
656
|
-
// serialize writes '' for an omitted optional — that is not an authored
|
|
657
|
-
// value, so it must not come back as one.
|
|
658
|
-
if (raw === undefined || raw === '')
|
|
659
|
-
return undefined;
|
|
660
|
-
return raw.startsWith('=js:') ? emitBareExpr(raw.slice(4), imp, inputNames) : tsLiteral(raw);
|
|
661
|
-
};
|
|
662
|
-
const priority = unwrapPlain(inputs.priority);
|
|
663
|
-
return `${imp.use('queueItem')}(${opts([
|
|
664
|
-
['queue', tsText(q.name)],
|
|
665
|
-
['folderPath', tsText(q.folderPath)],
|
|
666
|
-
['key', tsText(q.key)],
|
|
667
|
-
['item', rows.length ? objLit(rows) : '{}'],
|
|
668
|
-
// `Normal` is the definition's default — only a departure was authored.
|
|
669
|
-
['priority', typeof priority === 'string' && priority !== 'Normal' ? tsLiteral(priority) : undefined],
|
|
670
|
-
['reference', optStr('reference')],
|
|
671
|
-
['deferDate', optStr('deferDate')],
|
|
672
|
-
['dueDate', optStr('dueDate')],
|
|
673
|
-
['wait', node.type === T.queueCreateAndWait ? 'true' : undefined],
|
|
674
|
-
])})`;
|
|
675
|
-
}
|
|
676
645
|
case T.summarize:
|
|
677
646
|
case T.batchTransform: {
|
|
678
647
|
const attachment = emitVal(inputs.attachment, imp, inputNames);
|
|
@@ -12,8 +12,9 @@ import { dataFabricFlowFamily } from './nodes/data-fabric/flow/family.js';
|
|
|
12
12
|
import { delayFlowFamily } from './nodes/delay/flow/family.js';
|
|
13
13
|
import { documentFlowFamily } from './nodes/document/flow/family.js';
|
|
14
14
|
import { mockFlowFamily } from './nodes/mock/flow/family.js';
|
|
15
|
+
import { queueFlowFamily } from './nodes/queue/flow/family.js';
|
|
15
16
|
import { scriptFlowFamily } from './nodes/script/flow/family.js';
|
|
16
17
|
import { transformFlowFamily } from './nodes/transform/flow/family.js';
|
|
17
18
|
/** The families, in no significant order. Adding one is the whole of registering it. */
|
|
18
|
-
export const FLOW_NODE_FAMILIES = [dataFabricFlowFamily, delayFlowFamily, documentFlowFamily, mockFlowFamily, scriptFlowFamily, transformFlowFamily];
|
|
19
|
+
export const FLOW_NODE_FAMILIES = [dataFabricFlowFamily, delayFlowFamily, documentFlowFamily, mockFlowFamily, queueFlowFamily, scriptFlowFamily, transformFlowFamily];
|
|
19
20
|
export const FLOW_NODE_TYPES = new NodeTypeRegistry('flow', FLOW_NODE_FAMILIES, { hasBundledDefinition });
|
package/dist/flow-node-type.d.ts
CHANGED
|
@@ -75,6 +75,12 @@ export interface FlowSerializeContext {
|
|
|
75
75
|
} & Readonly<Record<string, unknown>>): void;
|
|
76
76
|
/** The bundled definition `<typeName>@<version>`, or undefined when the SDK does not ship it. */
|
|
77
77
|
definition(typeName: string, version: string): unknown;
|
|
78
|
+
/**
|
|
79
|
+
* The flow's bindings so far, by id — read-only. For a type that SHARES a
|
|
80
|
+
* binding with earlier steps on the same resource (a queue's name + folder
|
|
81
|
+
* pair) or must pick an id that is not taken; add entries through `bind`.
|
|
82
|
+
*/
|
|
83
|
+
readonly bindings: ReadonlyMap<string, Readonly<Record<string, unknown>>>;
|
|
78
84
|
}
|
|
79
85
|
/** What `deserialize` may ask of the decompiler, for one serialized node. */
|
|
80
86
|
export interface FlowDeserializeContext {
|
package/dist/flow-sdk.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export * from './nodes/data-fabric/flow/index.js';
|
|
|
22
22
|
export * from './nodes/delay/flow/index.js';
|
|
23
23
|
export * from './nodes/document/flow/index.js';
|
|
24
24
|
export * from './nodes/mock/flow/index.js';
|
|
25
|
+
export * from './nodes/queue/flow/index.js';
|
|
25
26
|
export * from './nodes/script/flow/index.js';
|
|
26
27
|
export * from './nodes/transform/flow/index.js';
|
|
27
28
|
export { resolveFlowRefs, resolveRefPath, hasFileRefs } from './ref-resolve.js';
|
package/dist/flow-sdk.js
CHANGED
|
@@ -26,6 +26,7 @@ export * from './nodes/data-fabric/flow/index.js';
|
|
|
26
26
|
export * from './nodes/delay/flow/index.js';
|
|
27
27
|
export * from './nodes/document/flow/index.js';
|
|
28
28
|
export * from './nodes/mock/flow/index.js';
|
|
29
|
+
export * from './nodes/queue/flow/index.js';
|
|
29
30
|
export * from './nodes/script/flow/index.js';
|
|
30
31
|
export * from './nodes/transform/flow/index.js';
|
|
31
32
|
// `$ref`-split ingestion (design §5): decompile resolves local-file refs into
|