@uipath/maestro-builder-sdk 6.11.2 → 6.11.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.
package/README.md CHANGED
@@ -115,7 +115,7 @@ network calls. That is what `prepare` is for: it is the one verb that does talk
115
115
  to the tenant. Run what `check` named, both fields at once:
116
116
 
117
117
  ```bash
118
- npx flow-sdk registry pull # once per machine: the connector library
118
+ uip maestro registry pull # once per machine: the connector library
119
119
 
120
120
  npx flow-sdk registry prepare uipath-salesforce-slack --action send-message-to-user \
121
121
  --resolve channel:profile.email=ada@example.com \
@@ -289,7 +289,7 @@ Keeping the names symbolic is what lets one flow move between connections: the
289
289
  code says `slack`, and only `bindings.json` knows which Slack.
290
290
 
291
291
  Discover ops and input shapes from the connector library that
292
- `npx flow-sdk registry pull` downloads and caches. A field the library does not
292
+ `uip maestro registry pull` downloads and caches. A field the library does not
293
293
  carry is connection-specific — that is the `prepare` case from the quick start.
294
294
 
295
295
  The package also exposes the low-level materializer used by the UiPath CLI to
@@ -302,7 +302,7 @@ flow-registry-materialize \
302
302
  --connectors ./connectors
303
303
  ```
304
304
 
305
- Most callers want `npx flow-sdk registry pull`, which downloads the published
305
+ Most callers want `uip maestro registry pull`, which downloads the published
306
306
  archive, verifies its checksum and then runs this transform. The low-level
307
307
  command is for SDK development, build pipelines, and troubleshooting: it only
308
308
  transforms local files that are already on disk.
@@ -322,7 +322,7 @@ The step-by-step authoring guides — `SKILL.md` for Flow, `SKILL-case.md`,
322
322
  UiPath authoring skills catalog rather than here, so a coding agent and a human
323
323
  read the same copy. The worked examples named by those guides travel with them.
324
324
 
325
- The connector library is not bundled: `npx flow-sdk registry pull` downloads it
325
+ The connector library is not bundled: `uip maestro registry pull` downloads it
326
326
  and caches it per machine. The package does carry the curated overlay that pull
327
327
  applies on top — corrections and the definitions the raw registry dump omits.
328
328
 
package/dist/check.js CHANGED
@@ -11,8 +11,9 @@ import { isLookupToken, resolvedValue, unresolvedLookupMessage, } from './core/l
11
11
  import { EVENT_FILTER_OPERATORS, readEventFilter, eventFilterProblem } from './event-filters.js';
12
12
  import { extractRefs } from './core/expr-check.js';
13
13
  import { bindingSelfNameMessage, bindingUndeclaredMessage, undeclaredBinding } from './core/binding-messages.js';
14
+ import { isAnswerField } from './core/hitl-answers.js';
14
15
  import { hitlDerivesOutcomeHandles, hitlExitModel, hitlRoutesPerOutcome } from './core/hitl-routing.js';
15
- import { declaredExits, hasExits, stopsAtEnd } from './core/step-ports.js';
16
+ import { childStepLists, declaredExits, hasExits, stopsAtEnd } from './core/step-ports.js';
16
17
  import { FLOW_SCHEMA_VERSIONS } from './format-profile.js';
17
18
  import { compareSchemaVersions, schemaVersionRefusal } from './schema-version.js';
18
19
  import { prepareCommand, resolveFlagArg } from './core/cli-spelling.js';
@@ -1141,7 +1142,8 @@ function checkFlow(built, ancestors, opts = {}) {
1141
1142
  code: 'MOCK_HAS_NO_OUTPUT',
1142
1143
  message: `Placeholder "${name}" publishes nothing, but "$vars.${name}${field ? '.' + field : ''}" reads it in "${step}". `
1143
1144
  + 'A mock() is a marker for a node that does not exist yet — its output is null at run time, always. '
1144
- + 'Replace it with the real step before reading it.',
1145
+ + 'Keep the placeholder while the real node does not exist, and have the reader use a value you supply instead (a flow input, as example/ClaimScaffold.flow.ts does). '
1146
+ + 'Replace the placeholder only with the real node, once `registry search` finds it; a script returning fixed values is not the real node.',
1145
1147
  step,
1146
1148
  });
1147
1149
  continue;
@@ -1644,20 +1646,7 @@ function checkLoopListEnvelope(loop, connectors, opts, diags) {
1644
1646
  }
1645
1647
  /** True if any step on THIS flow's own tree is a `.return()`. */
1646
1648
  function hasReturn(steps) {
1647
- for (const s of steps) {
1648
- if (s.kind === 'return')
1649
- return true;
1650
- if (s.kind === 'branch' && (hasReturn(s.then) || hasReturn(s.otherwise)))
1651
- return true;
1652
- if (s.kind === 'switch'
1653
- && (s.cases.some((c) => hasReturn(c.body)) || hasReturn(s.default ?? [])))
1654
- return true;
1655
- if (s.kind === 'parallel' && s.arms.some(hasReturn))
1656
- return true;
1657
- if ((s.kind === 'loop' || s.kind === 'doWhile') && hasReturn(s.body))
1658
- return true;
1659
- }
1660
- return false;
1649
+ return steps.some((s) => s.kind === 'return' || childStepLists(s).some(hasReturn));
1661
1650
  }
1662
1651
  /**
1663
1652
  * Closest of `candidates` to `name`: same word ignoring case, one contained in
@@ -4777,9 +4766,9 @@ function checkHitl(step, inputs, diags) {
4777
4766
  + `gets a text box and the value comes back as a string. Valid: `
4778
4767
  + `${FORM_FIELD_TYPES.join(', ')}.`, nearest !== undefined ? `type: '${nearest}'` : `type: 'text'`);
4779
4768
  }
4769
+ if (isAnswerField(f))
4770
+ answers++; // an `output`, or an `inOut` whose reviewed value comes back
4780
4771
  if (f?.direction === 'input' || f?.direction === 'inOut') {
4781
- if (f.direction === 'inOut')
4782
- answers++; // the reviewed value comes back
4783
4772
  const value = f.value;
4784
4773
  if (value === undefined || value === null) {
4785
4774
  at('HITL_FIELD_NO_VALUE', `Human task "${step}" shows the form field "${id}" to the reviewer but gives it no value, `
@@ -4800,10 +4789,7 @@ function checkHitl(step, inputs, diags) {
4800
4789
  + `Compute it in a script step first and point the field at that step's output.`, `value: out('<scriptStep>')`);
4801
4790
  }
4802
4791
  }
4803
- else if (f?.direction === 'output') {
4804
- answers++;
4805
- }
4806
- else {
4792
+ else if (f?.direction !== 'output') {
4807
4793
  at('HITL_FIELD_DIRECTION', `Human task "${step}" gives the form field "${id}" the direction `
4808
4794
  + `${JSON.stringify(f?.direction)}. A field is shown to the `
4809
4795
  + `reviewer ('input'), filled in by them ('output'), or pre-filled and editable ('inOut'); `
@@ -4926,7 +4912,7 @@ function checkHitlRead(name, field, rest, form, step, diags) {
4926
4912
  if (answer === 'Action')
4927
4913
  return; // which outcome was pressed.
4928
4914
  const answers = (form?.fields ?? [])
4929
- .filter((f) => f?.direction === 'output' && typeof f?.id === 'string')
4915
+ .filter((f) => isAnswerField(f) && typeof f?.id === 'string')
4930
4916
  .map((f) => f.id);
4931
4917
  if (answers.includes(answer))
4932
4918
  return;
@@ -4938,7 +4924,7 @@ function checkHitlRead(name, field, rest, form, step, diags) {
4938
4924
  level: 'error',
4939
4925
  code: 'HITL_READ_UNKNOWN_FIELD',
4940
4926
  message: `Human task "${name}" has no answer "${answer}" (read as "$vars.${name}.output.${answer}" in `
4941
- + `"${step}"). Its result carries only the fields the reviewer FILLS IN`
4927
+ + `"${step}"). Its result carries only the fields the reviewer FILLS IN or EDITS`
4942
4928
  + `${answers.length > 0 ? ` (${answers.join(', ')})` : ' (it declares none)'} plus "Action". `
4943
4929
  + (shown.includes(answer)
4944
4930
  ? `"${answer}" is a field the reviewer only reads, so it is not part of the answer — read the `
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Which form fields of a human task come back in its answer object — the one
3
+ * rule `serialize` (the emitted `outputs.output.properties`) and `check` (the
4
+ * answer count and every `out('<task>', '<field>')` read) all use, so they
5
+ * cannot drift. They did drift (UV-16855): `serialize` emitted `inOut` fields
6
+ * as answers and `check` counted them as answers, but the read check listed
7
+ * `output` fields only, so the documented read of an editable field —
8
+ * `out('review', 'comment')` for `{ id: 'comment', direction: 'inOut', … }` —
9
+ * failed `check` and blocked `compile`.
10
+ *
11
+ * - `output` — the reviewer fills it in; the value comes back.
12
+ * - `inOut` — pre-filled and editable; the (possibly changed) value comes back.
13
+ * - `input` — shown only; NOT an answer. Read the value bound to it instead.
14
+ */
15
+ export type AnswerDirection = 'output' | 'inOut';
16
+ /** True when the field's value comes back in the task's answer object. */
17
+ export declare function isAnswerField(field: {
18
+ direction?: unknown;
19
+ } | null | undefined): boolean;
@@ -0,0 +1,4 @@
1
+ /** True when the field's value comes back in the task's answer object. */
2
+ export function isAnswerField(field) {
3
+ return field?.direction === 'output' || field?.direction === 'inOut';
4
+ }
@@ -42,4 +42,16 @@ export declare function hasExits(r: DeclaredExit[] | NoExits): r is DeclaredExit
42
42
  * `.parallel` join waiting: a terminate ends the run, join included.
43
43
  */
44
44
  export declare function stopsAtEnd(steps: readonly Step[]): boolean;
45
+ /**
46
+ * The step lists nested DIRECTLY inside `step` — the bodies a walk over this
47
+ * flow's own tree must descend into. Exhaustive over `Step['kind']`, so a new
48
+ * container kind fails to compile here instead of being silently skipped by
49
+ * every walker. That is how `check`'s return scan came to miss `.stepSwitch`
50
+ * arms and `.stepToList` / `.onError` bodies, and warned NO_RETURN on flows
51
+ * whose every path ends in `.return()` (UV-16855).
52
+ *
53
+ * A subflow's child flow is deliberately NOT a child here: it is another
54
+ * flow's tree, and its returns say nothing about whether THIS flow ends.
55
+ */
56
+ export declare function childStepLists(step: Step): readonly Step[][];
45
57
  export {};
@@ -107,3 +107,40 @@ export function stopsAtEnd(steps) {
107
107
  || (st.kind === 'switch' && st.default !== undefined && has(st.default, kinds)));
108
108
  return has(steps, new Set(['return'])) && !has(steps, new Set(['terminate', 'break']));
109
109
  }
110
+ /**
111
+ * The step lists nested DIRECTLY inside `step` — the bodies a walk over this
112
+ * flow's own tree must descend into. Exhaustive over `Step['kind']`, so a new
113
+ * container kind fails to compile here instead of being silently skipped by
114
+ * every walker. That is how `check`'s return scan came to miss `.stepSwitch`
115
+ * arms and `.stepToList` / `.onError` bodies, and warned NO_RETURN on flows
116
+ * whose every path ends in `.return()` (UV-16855).
117
+ *
118
+ * A subflow's child flow is deliberately NOT a child here: it is another
119
+ * flow's tree, and its returns say nothing about whether THIS flow ends.
120
+ */
121
+ export function childStepLists(step) {
122
+ switch (step.kind) {
123
+ case 'branch':
124
+ return [step.then, step.otherwise];
125
+ case 'switch':
126
+ return [...step.cases.map((c) => c.body), ...(step.default ? [step.default] : [])];
127
+ case 'stepSwitch':
128
+ return step.cases.map((c) => c.body);
129
+ case 'loop':
130
+ case 'doWhile':
131
+ case 'stepToList':
132
+ return [step.body];
133
+ case 'parallel':
134
+ return step.arms;
135
+ case 'action':
136
+ case 'break':
137
+ case 'terminate':
138
+ case 'stepToRef':
139
+ case 'return':
140
+ return [];
141
+ default: {
142
+ const unhandled = step;
143
+ throw new Error(`childStepLists: unhandled step kind ${JSON.stringify(unhandled.kind)}`);
144
+ }
145
+ }
146
+ }
@@ -21,6 +21,15 @@
21
21
  export declare const LIBRARY_JSON_DIR = "library-json";
22
22
  export declare const LIBRARY_MARKDOWN_DIR = "library-md";
23
23
  export declare const CURRENT_LINK = "current";
24
+ /**
25
+ * The command a message tells a person or agent to run when the cache is
26
+ * empty. It is `uip`, not `npx flow-sdk registry pull`: `uip maestro registry
27
+ * pull` runs this package's pull and fills the same cache, and it is the one
28
+ * command the authoring skill teaches. Each message used to spell the command
29
+ * out by hand, so they kept naming the SDK's own entry point after the skill
30
+ * moved to `uip`. Name it here once.
31
+ */
32
+ export declare const PULL_COMMAND = "uip maestro registry pull";
24
33
  /**
25
34
  * Root of the library cache. `UIP_FLOW_SDK_LIBRARY_CACHE` overrides it.
26
35
  *
@@ -24,6 +24,15 @@ import { join } from "node:path";
24
24
  export const LIBRARY_JSON_DIR = "library-json";
25
25
  export const LIBRARY_MARKDOWN_DIR = "library-md";
26
26
  export const CURRENT_LINK = "current";
27
+ /**
28
+ * The command a message tells a person or agent to run when the cache is
29
+ * empty. It is `uip`, not `npx flow-sdk registry pull`: `uip maestro registry
30
+ * pull` runs this package's pull and fills the same cache, and it is the one
31
+ * command the authoring skill teaches. Each message used to spell the command
32
+ * out by hand, so they kept naming the SDK's own entry point after the skill
33
+ * moved to `uip`. Name it here once.
34
+ */
35
+ export const PULL_COMMAND = "uip maestro registry pull";
27
36
  /**
28
37
  * Root of the library cache. `UIP_FLOW_SDK_LIBRARY_CACHE` overrides it.
29
38
  *
@@ -1,6 +1,6 @@
1
1
  import { reportResult } from '../cli-result.js';
2
2
  import { join } from "node:path";
3
- import { CURRENT_LINK, currentEntrySha, libraryCacheRoot, resolveCachedLibrary, resolveCachedMarkdown, } from "./cache.js";
3
+ import { CURRENT_LINK, PULL_COMMAND, currentEntrySha, libraryCacheRoot, resolveCachedLibrary, resolveCachedMarkdown, } from "./cache.js";
4
4
  /**
5
5
  * Say where the connector library is.
6
6
  *
@@ -34,7 +34,7 @@ export async function run(argv) {
34
34
  const single = (field, value) => {
35
35
  reportResult({ [field]: value ?? null });
36
36
  if (!value) {
37
- console.error("No connector library in the cache yet. Run `flow-sdk registry pull`.");
37
+ console.error(`No connector library in the cache yet. Run \`${PULL_COMMAND}\`.`);
38
38
  return 1;
39
39
  }
40
40
  console.log(value);
@@ -1,6 +1,6 @@
1
1
  import { reportResult } from '../cli-result.js';
2
2
  import { readFile, stat } from "node:fs/promises";
3
- import { resolveLibraryDir } from "./cache.js";
3
+ import { PULL_COMMAND, resolveLibraryDir } from "./cache.js";
4
4
  import { dirname, join } from "node:path";
5
5
  export const DEFAULT_SEARCH_LIMIT = 20;
6
6
  const USAGE = "Usage: flow-sdk registry search [query] [--library <dir>] [--library-md <dir>] [--connector <key>] [--limit <n>]";
@@ -52,7 +52,7 @@ export async function searchRegistryOperations(options) {
52
52
  content = await readFile(indexPath, "utf-8");
53
53
  }
54
54
  catch {
55
- throw new Error(`Could not read ${indexPath}. Run \`flow-sdk registry pull\`, or point` +
55
+ throw new Error(`Could not read ${indexPath}. Run \`${PULL_COMMAND}\`, or point` +
56
56
  " --library at an extracted connector library.");
57
57
  }
58
58
  let parsed;
@@ -120,6 +120,10 @@ export async function run(argv) {
120
120
  // verbs defaulted it was the inconsistency an author hit first.
121
121
  const libraryPath = resolveLibraryDir(value(argv, "--library"));
122
122
  if (!libraryPath) {
123
+ // Say why. A bare usage line here read as "no match" to an agent deciding
124
+ // between a connector and http(): it took the failed search for a miss.
125
+ console.error(`No connector library is cached. Run \`${PULL_COMMAND}\`, or pass` +
126
+ " --library <dir>.");
123
127
  console.error(USAGE);
124
128
  return 2;
125
129
  }
package/dist/serialize.js CHANGED
@@ -14,6 +14,7 @@ import { Expr, toExpr, SCHEDULE_PRESETS, DELAY_PRESETS, parseIxpProjectType, fla
14
14
  import { FlowAction, FlowTrigger } from './core/node-classes.js';
15
15
  import { connectorRawNodeRefusal } from './core/connector-raw-node.js';
16
16
  import { dataFabricUnknownInputs } from './core/typed-raw-node.js';
17
+ import { isAnswerField } from './core/hitl-answers.js';
17
18
  import { BindingRefusal, GUID_RE, bindingSelfNameMessage, bindingUndeclaredMessage, undeclaredBinding } from './core/binding-messages.js';
18
19
  import { OUTCOME_HANDLE_NODE_TYPES, assertHitlExitInvariant, hitlExitModel, hitlExitViolation, outcomeSlug } from './core/hitl-routing.js';
19
20
  import { declaredExits, hasExits, stopsAtEnd } from './core/step-ports.js';
@@ -2800,7 +2801,7 @@ function hitlInputs(inputs, nodeId, flowId, label, rename) {
2800
2801
  const properties = {};
2801
2802
  for (const f of inputs?.fields ?? []) {
2802
2803
  // inOut fields land in the answers too — their reviewed value flows back.
2803
- if (f.direction !== 'output' && f.direction !== 'inOut')
2804
+ if (!isAnswerField(f))
2804
2805
  continue;
2805
2806
  properties[f.id] = { ...FORM_FIELD_JSON_TYPE[f.type] };
2806
2807
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.11.2",
3
+ "version": "6.11.4",
4
4
  "description": "Build UiPath Flow, Case, and BPMN artifacts by writing TypeScript.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://docs.uipath.com/maestro",
@@ -92,5 +92,5 @@
92
92
  "@types/node": "^22.7.0",
93
93
  "esbuild": "^0.28.1"
94
94
  },
95
- "gitref": "0e144a44d84cd717eaec74c8c43fe864026e7339"
95
+ "gitref": "8c18e5efb6f8dd4b2599f9591cabdff42feaf275"
96
96
  }