@uipath/maestro-builder-sdk 6.16.14 → 6.17.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 (60) hide show
  1. package/dist/api-index.md +108 -107
  2. package/dist/api-members.md +295 -291
  3. package/dist/bindings-v2.d.ts +39 -1
  4. package/dist/bindings-v2.js +289 -9
  5. package/dist/bpmn/compile-cli.js +11 -2
  6. package/dist/bpmn/decompile.js +2 -1
  7. package/dist/bpmn/registry-fallback.js +9 -7
  8. package/dist/case/compile-cli.js +16 -6
  9. package/dist/case/decompile-cli.js +2 -1
  10. package/dist/case/decompile.js +3 -2
  11. package/dist/case/merge-cli.js +3 -2
  12. package/dist/check.js +219 -37
  13. package/dist/cli-result.d.ts +9 -0
  14. package/dist/cli-result.js +12 -0
  15. package/dist/compile-cli.js +78 -53
  16. package/dist/core/actions.d.ts +70 -16
  17. package/dist/core/agentic-process-forms.d.ts +51 -0
  18. package/dist/core/agentic-process-forms.js +49 -0
  19. package/dist/core/binding-messages.d.ts +5 -0
  20. package/dist/core/comment-text.d.ts +29 -0
  21. package/dist/core/comment-text.js +40 -0
  22. package/dist/core/contribution-bindings.d.ts +73 -0
  23. package/dist/core/contribution-bindings.js +105 -0
  24. package/dist/core/expr-check.js +7 -2
  25. package/dist/core/json-file.d.ts +1 -0
  26. package/dist/core/json-file.js +12 -0
  27. package/dist/core/script-return.js +4 -1
  28. package/dist/core/typed-raw-node.js +1 -0
  29. package/dist/core/typescript-module.d.ts +2 -0
  30. package/dist/core/typescript-module.js +18 -0
  31. package/dist/core-definitions.json +210 -0
  32. package/dist/decompile-cli.js +2 -1
  33. package/dist/decompile.js +64 -24
  34. package/dist/emit.js +4 -3
  35. package/dist/flow-sdk.d.ts +14 -9
  36. package/dist/flow-sdk.js +14 -4
  37. package/dist/flow-step-tree.d.ts +2 -3
  38. package/dist/flow-step-tree.js +2 -3
  39. package/dist/load.js +1 -1
  40. package/dist/merge-cli.js +3 -2
  41. package/dist/merge.d.ts +2 -1
  42. package/dist/merge.js +0 -0
  43. package/dist/path-within.d.ts +33 -0
  44. package/dist/path-within.js +41 -0
  45. package/dist/registry/archive/extract.js +2 -5
  46. package/dist/registry/curated-overlay.js +3 -2
  47. package/dist/registry/generators/descriptors.js +20 -18
  48. package/dist/registry/generators/triggers.js +4 -4
  49. package/dist/registry/prepare/messages.js +2 -1
  50. package/dist/registry/prepare/source-labels.js +60 -1
  51. package/dist/registry/prepare-cli.js +14 -4
  52. package/dist/registry/pull-cli.js +3 -2
  53. package/dist/registry/uip/client.d.ts +28 -3
  54. package/dist/registry/uip/client.js +95 -34
  55. package/dist/registry/uip/host.d.ts +41 -0
  56. package/dist/registry/uip/host.js +312 -0
  57. package/dist/serialize.d.ts +7 -0
  58. package/dist/serialize.js +390 -270
  59. package/dist/workdir.js +1 -1
  60. package/package.json +3 -3
@@ -981,21 +981,48 @@ export type DelayInputs = {
981
981
  /** Impossible together with `until` — a delay waits one way or the other. */
982
982
  duration?: never;
983
983
  };
984
+ /**
985
+ * Where a process resource lives: deployed to an Orchestrator folder
986
+ * (`'published'`, the default) or a sibling project of the SAME solution
987
+ * (`'in-solution'`). Shared by `rpaWorkflow`, `agenticProcess` and `agent`.
988
+ */
989
+ export type ProcessLocation = 'published' | 'in-solution';
984
990
  export interface RpaWorkflowInputs {
985
991
  /**
986
992
  * The published process's release key (a GUID). It becomes part of the node's
987
993
  * type, `uipath.core.rpa-workflow.<key>`. Find it with
988
994
  * `uip or processes list --all-folders --process-type Process` (the row's `Key`)
989
995
  * or `uip maestro flow registry search "uipath.core.rpa-workflow"`.
996
+ *
997
+ * For an in-solution sibling it is `resource.key` from
998
+ * `resources/solution_folder/process/process/<project>.json` — the suffix of the
999
+ * node type `uip maestro flow registry list --local` shows.
990
1000
  */
991
1001
  key: string;
992
1002
  /** The process's name in Orchestrator — e.g. `'RPA Workflow'`. */
993
1003
  name: string;
1004
+ /**
1005
+ * Where the process lives. `'published'` (the default) is a process deployed
1006
+ * to `folderPath`. `'in-solution'` is a sibling RPA project of the same
1007
+ * solution: it needs `projectId` and no `folderPath`.
1008
+ */
1009
+ location?: ProcessLocation;
994
1010
  /**
995
1011
  * The Orchestrator folder holding the process — e.g.
996
- * `'Shared/uipath-maestro-flow/ProjectEuler RPA'`.
1012
+ * `'Shared/uipath-maestro-flow/ProjectEuler RPA'`. Required for a published
1013
+ * process; omit it for an in-solution sibling.
1014
+ *
1015
+ * @enforcedBy RPA_NO_FOLDER A published process needs its folder.
997
1016
  */
998
- folderPath: string;
1017
+ folderPath?: string;
1018
+ /**
1019
+ * The sibling RPA project's `resource.projectKey`, read from
1020
+ * `resources/solution_folder/process/process/<project>.json`. Required only
1021
+ * when `location` is `'in-solution'`.
1022
+ *
1023
+ * @enforcedBy RPA_LOCAL_NO_PROJECT_ID An in-solution process needs its project id.
1024
+ */
1025
+ projectId?: string;
999
1026
  /**
1000
1027
  * The PROCESS's own input arguments, by its own argument names (e.g.
1001
1028
  * `{ problemId: 123 }`). Not a fixed schema — every process declares its own,
@@ -1101,11 +1128,33 @@ interface AgenticProcessInputsBase {
1101
1128
  key: string;
1102
1129
  /** The process's name in Orchestrator — e.g. `'ProcurementProcess'`. */
1103
1130
  name: string;
1131
+ /**
1132
+ * Where the process lives. `'published'` (the default) is a process deployed
1133
+ * to `folderPath`. `'in-solution'` is a sibling Flow of the same solution, so
1134
+ * it needs `form: 'flow'`, `projectId` and no `folderPath`; `key` is the
1135
+ * sibling's `resource.key` from `resources/solution_folder/process/flow/<project>.json`.
1136
+ * Only the Flow form has been run in-solution; `'bpmn'` and `'case'` siblings
1137
+ * are refused until they are.
1138
+ *
1139
+ * @enforcedBy AGENTIC_LOCAL_FORM_UNVERIFIED In-solution is supported for `form: 'flow'` only.
1140
+ */
1141
+ location?: ProcessLocation;
1104
1142
  /**
1105
1143
  * The Orchestrator folder holding it — e.g.
1106
- * `'Shared/uipath-agents/ProcurementProcess'`.
1144
+ * `'Shared/uipath-agents/ProcurementProcess'`. Required for a published
1145
+ * process; omit it for an in-solution sibling.
1146
+ *
1147
+ * @enforcedBy AGENTIC_NO_FOLDER A published process needs its folder.
1107
1148
  */
1108
- folderPath: string;
1149
+ folderPath?: string;
1150
+ /**
1151
+ * The sibling project's `resource.projectKey`, read from the same resource
1152
+ * file as `key` (`resources/solution_folder/process/flow/<project>.json`).
1153
+ * Required only when `location` is `'in-solution'`.
1154
+ *
1155
+ * @enforcedBy AGENTIC_LOCAL_NO_PROJECT_ID An in-solution process needs its project id.
1156
+ */
1157
+ projectId?: string;
1109
1158
  /**
1110
1159
  * The PROCESS's own input arguments, by its own argument names (e.g.
1111
1160
  * `{ productId: 1 }`). Not a fixed schema — every agentic process declares its
@@ -1167,7 +1216,7 @@ export type AgenticProcessInputs = AgenticProcessInputsBase & AgenticProcessComp
1167
1216
  * resource. Display-only — see {@link AgentInputs.flavour}.
1168
1217
  */
1169
1218
  export type AgentFlavour = 'coded' | 'lowcode';
1170
- export type AgentLocation = 'published' | 'in-solution';
1219
+ export type AgentLocation = ProcessLocation;
1171
1220
  export interface AgentInputs {
1172
1221
  /**
1173
1222
  * The agent resource key (a GUID). It becomes the node's TYPE,
@@ -1526,15 +1575,15 @@ export interface InlineAgentInputs {
1526
1575
  maxIterations?: number;
1527
1576
  /**
1528
1577
  * The harness the agent runs on — `'standard'` (the default) or
1529
- * `'advanced'`. Naming it selects the node's **1.3** definition (the
1530
- * registry's current, which adds the field); omitting it emits the 1.2
1531
- * definition byte-identically.
1578
+ * `'advanced'`, written to the `agent.json`'s `settings.mode`. It does not
1579
+ * change the node's version: every inline agent emits the bundle's newest
1580
+ * `uipath.agent.autonomous` definition (1.4).
1532
1581
  */
1533
1582
  mode?: 'standard' | 'advanced';
1534
1583
  /**
1535
1584
  * Safety rails over the agent's inputs, outputs, LLM calls and tools — the
1536
- * platform's own array shape ({@link AgentGuardrail}), carried on the node
1537
- * (its 1.2 definition already declares the input) and in the `agent.json`.
1585
+ * platform's own array shape ({@link AgentGuardrail}), carried in the
1586
+ * `agent.json` (every bundled definition declares the input).
1538
1587
  *
1539
1588
  * ```ts
1540
1589
  * guardrails: [{
@@ -1550,8 +1599,8 @@ export interface InlineAgentInputs {
1550
1599
  guardrails?: AgentGuardrail[];
1551
1600
  /**
1552
1601
  * Attach an episodic memory so the agent learns from past runs — one
1553
- * {@link AgentMemoryRef}, wired to the agent's `memory` handle (its 1.4
1554
- * definition; naming one selects it).
1602
+ * {@link AgentMemoryRef}, wired to the agent's `memory` handle (declared by
1603
+ * the bundled 1.4 definition, which every inline agent uses).
1555
1604
  */
1556
1605
  memory?: AgentMemoryRef;
1557
1606
  /**
@@ -1764,9 +1813,9 @@ export interface HttpRequestToolRef {
1764
1813
  * An episodic memory the agent learns from across runs, wired to the agent's
1765
1814
  * own `memory` handle. Node type
1766
1815
  * `uipath.agent.resource.memory.<name-slug>.<id-slug>`, minted exactly as the
1767
- * platform's mapper does. Naming one selects the agent's **1.4** definition
1768
- * (which adds the handle) — transcribed from workbench source; the tenant
1769
- * registry serves 1.3 (same availability note as do-while).
1816
+ * platform's mapper does. The handle is LOCAL content on the bundled
1817
+ * `uipath.agent.autonomous@1.4` (#431): the registry's own 1.4 declares no
1818
+ * `memory` handle, so `check` refuses this today (AGENT_MEMORY_NOT_AUTHORABLE).
1770
1819
  */
1771
1820
  export interface AgentMemoryRef {
1772
1821
  /** The memory's display name on the tenant. */
@@ -1960,7 +2009,12 @@ export interface EscalationRef {
1960
2009
  key: string;
1961
2010
  /** The app's name, e.g. `'ContentReviewApp'`. */
1962
2011
  name: string;
1963
- /** The Orchestrator folder the app lives in. */
2012
+ /**
2013
+ * The Orchestrator folder the app lives in, e.g. `'Shared/Approvals'`.
2014
+ * Omit it for an app that ships in this solution: compile then writes
2015
+ * `'solution_folder'`, the `Folder` `uip solution resources list` reports
2016
+ * for a solution-internal app.
2017
+ */
1964
2018
  folderPath?: string;
1965
2019
  /** The fields the agent hands the reviewer — becomes the app's `inputSchema`. */
1966
2020
  inputs?: Record<string, InlineAgentFieldType>;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * The three published forms under the Agentic Process umbrella (design §2.1).
3
+ * One public factory, three wire identities — transcribed from flow-v1's
4
+ * `RESOURCE_TYPE_METADATA` (ProcessOrchestration / Flow / CaseManagement):
5
+ * node-type segment, category, icon, resource subtype, `orchestratorType`
6
+ * (`resourceType.toLowerCase()`, per `createModel`), and the sync/async
7
+ * service-type pair. All three declare the fire-and-forget switch.
8
+ *
9
+ * `solutionFolder` is the folder under `resources/solution_folder/process/`
10
+ * that holds an in-solution sibling's resource file (e.g. a sibling Flow lands in
11
+ * `process/flow/Notifier.json`). The solution writer names it
12
+ * `toLowerFirstChar(resource.type)`: `@uipath/resource-builder-sdk`
13
+ * `MultiFileSolutionDefinitionProvider.buildResourceRelativePath`, with the
14
+ * process types `flow`, `processOrchestration` and `caseManagement` from that
15
+ * package's resource-type catalog.
16
+ *
17
+ * Shared by the serializer (which emits the node) and `check` (which names the
18
+ * resource file in `AGENTIC_LOCAL_NO_PROJECT_ID`), so the two can never disagree
19
+ * about what a form is.
20
+ */
21
+ export declare const AGENTIC_PROCESS_FORMS: {
22
+ readonly bpmn: {
23
+ readonly prefix: "uipath.core.agentic-process.";
24
+ readonly category: "agentic-process";
25
+ readonly icon: "agentic-process";
26
+ readonly resourceSubType: "ProcessOrchestration";
27
+ readonly orchestratorType: "processorchestration";
28
+ readonly serviceType: "Orchestrator.StartAgenticProcess";
29
+ readonly solutionFolder: "processOrchestration";
30
+ };
31
+ readonly flow: {
32
+ readonly prefix: "uipath.core.flow.";
33
+ readonly category: "flow";
34
+ readonly icon: "flow-project";
35
+ readonly resourceSubType: "Flow";
36
+ readonly orchestratorType: "flow";
37
+ readonly serviceType: "Orchestrator.StartFlowProcess";
38
+ readonly solutionFolder: "flow";
39
+ };
40
+ readonly case: {
41
+ readonly prefix: "uipath.core.case-management.";
42
+ readonly category: "case-management";
43
+ readonly icon: "case-management";
44
+ readonly resourceSubType: "CaseManagement";
45
+ readonly orchestratorType: "casemanagement";
46
+ readonly serviceType: "Orchestrator.StartCaseMgmtProcess";
47
+ readonly solutionFolder: "caseManagement";
48
+ };
49
+ };
50
+ /** An `agenticProcess` form: `'bpmn' | 'flow' | 'case'`. */
51
+ export type AgenticProcessForm = keyof typeof AGENTIC_PROCESS_FORMS;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * The three published forms under the Agentic Process umbrella (design §2.1).
3
+ * One public factory, three wire identities — transcribed from flow-v1's
4
+ * `RESOURCE_TYPE_METADATA` (ProcessOrchestration / Flow / CaseManagement):
5
+ * node-type segment, category, icon, resource subtype, `orchestratorType`
6
+ * (`resourceType.toLowerCase()`, per `createModel`), and the sync/async
7
+ * service-type pair. All three declare the fire-and-forget switch.
8
+ *
9
+ * `solutionFolder` is the folder under `resources/solution_folder/process/`
10
+ * that holds an in-solution sibling's resource file (e.g. a sibling Flow lands in
11
+ * `process/flow/Notifier.json`). The solution writer names it
12
+ * `toLowerFirstChar(resource.type)`: `@uipath/resource-builder-sdk`
13
+ * `MultiFileSolutionDefinitionProvider.buildResourceRelativePath`, with the
14
+ * process types `flow`, `processOrchestration` and `caseManagement` from that
15
+ * package's resource-type catalog.
16
+ *
17
+ * Shared by the serializer (which emits the node) and `check` (which names the
18
+ * resource file in `AGENTIC_LOCAL_NO_PROJECT_ID`), so the two can never disagree
19
+ * about what a form is.
20
+ */
21
+ export const AGENTIC_PROCESS_FORMS = {
22
+ bpmn: {
23
+ prefix: 'uipath.core.agentic-process.',
24
+ category: 'agentic-process',
25
+ icon: 'agentic-process',
26
+ resourceSubType: 'ProcessOrchestration',
27
+ orchestratorType: 'processorchestration',
28
+ serviceType: 'Orchestrator.StartAgenticProcess',
29
+ solutionFolder: 'processOrchestration',
30
+ },
31
+ flow: {
32
+ prefix: 'uipath.core.flow.',
33
+ category: 'flow',
34
+ icon: 'flow-project',
35
+ resourceSubType: 'Flow',
36
+ orchestratorType: 'flow',
37
+ serviceType: 'Orchestrator.StartFlowProcess',
38
+ solutionFolder: 'flow',
39
+ },
40
+ case: {
41
+ prefix: 'uipath.core.case-management.',
42
+ category: 'case-management',
43
+ icon: 'case-management',
44
+ resourceSubType: 'CaseManagement',
45
+ orchestratorType: 'casemanagement',
46
+ serviceType: 'Orchestrator.StartCaseMgmtProcess',
47
+ solutionFolder: 'caseManagement',
48
+ },
49
+ };
@@ -4,6 +4,11 @@ export declare const GUID_RE: RegExp;
4
4
  export type BindingRefusalCode = 'BINDING_SELF_NAME' | 'BINDING_UNDECLARED'
5
5
  /** An emitted definition's `<bindings.NAME>` placeholder has no `bindings[]` entry named NAME (#865). */
6
6
  | 'BINDING_PLACEHOLDER_UNRESOLVED'
7
+ /**
8
+ * A custom node's definition references a `<bindings.NAME>` the contribution did not
9
+ * supply and the definition cannot close (no `resourceKey`, or no `values` row) (#942).
10
+ */
11
+ | 'CONTRIBUTION_BINDING_UNRESOLVED'
7
12
  /** Two steps on one connection disagree on which connector it belongs to (#866). */
8
13
  | 'CONNECTION_CONNECTOR_CONFLICT'
9
14
  /** A connector-bound node names no `connection` or no `folder` label (#890). */
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Text that is safe inside a generated `//` or `/* … *\/` comment.
3
+ *
4
+ * A decompiler or generator that splices an input string into a comment hands that
5
+ * string the rest of the comment: a line terminator ends a `//` comment, `*\/` ends a
6
+ * block, and whatever follows is CODE in a file `compile` later executes. Those are the
7
+ * only two ways out of a JavaScript comment, so replacing both (line terminators — LF,
8
+ * CR, U+2028, U+2029 — with one space, `*\/` with `* /`) is complete, not a denylist.
9
+ * The replacements are the ones registry/generators already used, so their output keeps
10
+ * its bytes. FB006 holds every comment interpolation to this function.
11
+ *
12
+ * The result is ONE line: a multi-line value is flattened, which is right for a `//`
13
+ * line or a single ` * ` body line. To keep a value's line breaks, use `commentLines`
14
+ * (one escaped, prefixed line per input line) or `docComment` (a whole `/** … *\/`).
15
+ */
16
+ export declare function commentText(value: string | number): string;
17
+ /**
18
+ * `value` split on its line terminators, each line escaped by `commentText` and
19
+ * given `prefix` (`'// '`, `' * '`), trailing whitespace trimmed so a blank line is
20
+ * a bare `//` or ` *`. The lines are joined with `\n` by the caller, so a value's
21
+ * paragraph breaks survive and none of them can end the comment.
22
+ */
23
+ export declare function commentLines(value: string | number, prefix?: string): string[];
24
+ /**
25
+ * A JSDoc comment holding `value`, at `indent`. A one-line value keeps the
26
+ * one-line form, `/** value *\/`, so its bytes do not change; a multi-line value
27
+ * gets an open block with one ` * ` line per input line.
28
+ */
29
+ export declare function docComment(value: string | number, indent?: string): string[];
@@ -0,0 +1,40 @@
1
+ /** The line terminators (LF, CR, CRLF, U+2028, U+2029): the one way out of a `//` comment. */
2
+ const LINE_BREAK = /\r\n?|[\n\u2028\u2029]/g;
3
+ /**
4
+ * Text that is safe inside a generated `//` or `/* … *\/` comment.
5
+ *
6
+ * A decompiler or generator that splices an input string into a comment hands that
7
+ * string the rest of the comment: a line terminator ends a `//` comment, `*\/` ends a
8
+ * block, and whatever follows is CODE in a file `compile` later executes. Those are the
9
+ * only two ways out of a JavaScript comment, so replacing both (line terminators — LF,
10
+ * CR, U+2028, U+2029 — with one space, `*\/` with `* /`) is complete, not a denylist.
11
+ * The replacements are the ones registry/generators already used, so their output keeps
12
+ * its bytes. FB006 holds every comment interpolation to this function.
13
+ *
14
+ * The result is ONE line: a multi-line value is flattened, which is right for a `//`
15
+ * line or a single ` * ` body line. To keep a value's line breaks, use `commentLines`
16
+ * (one escaped, prefixed line per input line) or `docComment` (a whole `/** … *\/`).
17
+ */
18
+ export function commentText(value) {
19
+ return String(value).replace(LINE_BREAK, ' ').replaceAll('*/', '* /');
20
+ }
21
+ /**
22
+ * `value` split on its line terminators, each line escaped by `commentText` and
23
+ * given `prefix` (`'// '`, `' * '`), trailing whitespace trimmed so a blank line is
24
+ * a bare `//` or ` *`. The lines are joined with `\n` by the caller, so a value's
25
+ * paragraph breaks survive and none of them can end the comment.
26
+ */
27
+ export function commentLines(value, prefix = '') {
28
+ return String(value).split(LINE_BREAK).map((line) => `${prefix}${commentText(line)}`.trimEnd());
29
+ }
30
+ /**
31
+ * A JSDoc comment holding `value`, at `indent`. A one-line value keeps the
32
+ * one-line form, `/** value *\/`, so its bytes do not change; a multi-line value
33
+ * gets an open block with one ` * ` line per input line.
34
+ */
35
+ export function docComment(value, indent = '') {
36
+ const body = commentLines(value);
37
+ if (body.length === 1)
38
+ return [`${indent}/** ${commentText(value)} */`];
39
+ return [`${indent}/**`, ...body.map((line) => `${indent} * ${line}`.trimEnd()), `${indent} */`];
40
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * The `bindings[]` entries a contribution-lowered node needs and did not supply
3
+ * (flow-builder-sdk#942).
4
+ *
5
+ * A definition's `model.context` names its resource through `<bindings.NAME>`
6
+ * placeholders, and declares each NAME in `model.bindings.values`. The typed
7
+ * emitters (rpa, api-workflow, queue, ixp, connector) close those names by hand.
8
+ * A `rawNode` or a hand-written `FlowAction` returns a definition and inputs, and
9
+ * usually no `bindings` — so before this, nothing closed them, and compile failed
10
+ * at `BINDING_PLACEHOLDER_UNRESOLVED` while `check` passed.
11
+ *
12
+ * For instance, the manifest `registry get --local` returns for a sibling Flow:
13
+ *
14
+ * ```json
15
+ * "model": { "bindings": { "resource": "process", "resourceSubType": "Flow", "resourceKey": "k1",
16
+ * "values": [{ "name": "name", "default": "Notifier" }, { "name": "folderPath", "default": "" }] },
17
+ * "context": [{ "name": "name", "value": "<bindings.name>" }, { "name": "folderPath", "value": "<bindings.folderPath>" }] }
18
+ * ```
19
+ *
20
+ * needs two `process` entries keyed `k1`: `name` = "Notifier" and `folderPath` = "".
21
+ * {@link planContributionBindings} reads exactly those facts off the definition.
22
+ *
23
+ * `connection` resources are out of scope: a connector definition's entries are
24
+ * keyed by the tenant connection id, which the definition does not carry. A raw
25
+ * connector node is refused for that reason (`connector-raw-node.ts`).
26
+ *
27
+ * Pure: `serialize` lowers with it, and `check` runs it dry so the two agree.
28
+ */
29
+ /** One `bindings[]` entry, as the flow file carries it. */
30
+ export interface PlannedBinding {
31
+ name: string;
32
+ type: string;
33
+ resource: string;
34
+ resourceKey: string;
35
+ default?: string;
36
+ propertyAttribute: string;
37
+ resourceSubType?: string;
38
+ }
39
+ /** What one definition needs: the entries to build, and the names it cannot close. */
40
+ export interface ContributionBindingPlan {
41
+ /** The resource kind (`model.bindings.resource`), when it is one this plan closes. */
42
+ resource?: string;
43
+ /** The resource key every entry carries (`model.bindings.resourceKey`). */
44
+ resourceKey?: string;
45
+ /** One entry per referenced name the contribution did not supply. */
46
+ entries: PlannedBinding[];
47
+ /** One sentence per referenced name that cannot be closed, and why. Empty when every name closes. */
48
+ problems: string[];
49
+ }
50
+ /** The `<bindings.NAME>` names a definition's `model.context` references, in order, once each. */
51
+ export declare function referencedBindingNames(model: any): string[];
52
+ /**
53
+ * Plan the entries a contribution-lowered node needs: for each `<bindings.NAME>`
54
+ * its definition's `model.context` references and `supplied` does not cover, one
55
+ * entry built from the definition — `resource`, `resourceKey`, `resourceSubType`
56
+ * from `model.bindings`, and `name`, `default`, `propertyAttribute` from the
57
+ * matching `model.bindings.values` row.
58
+ *
59
+ * A supplied entry covers a name when it has the same `resource` and `name`: the
60
+ * contributor's own bindings win, as they always did.
61
+ *
62
+ * A name is a problem (not an entry) when the definition declares no
63
+ * `values` row for it, or carries no `resourceKey` — a per-tenant template such
64
+ * as the bundled `core.action.queue.create` (`resourceKey: ""`), which only a
65
+ * typed factory can fill.
66
+ *
67
+ * @param def - The resolved definition.
68
+ * @param supplied - The bindings the contribution returned.
69
+ */
70
+ export declare function planContributionBindings(def: any, supplied?: readonly {
71
+ resource?: string;
72
+ name?: string;
73
+ }[]): ContributionBindingPlan;
@@ -0,0 +1,105 @@
1
+ /**
2
+ * The `bindings[]` entries a contribution-lowered node needs and did not supply
3
+ * (flow-builder-sdk#942).
4
+ *
5
+ * A definition's `model.context` names its resource through `<bindings.NAME>`
6
+ * placeholders, and declares each NAME in `model.bindings.values`. The typed
7
+ * emitters (rpa, api-workflow, queue, ixp, connector) close those names by hand.
8
+ * A `rawNode` or a hand-written `FlowAction` returns a definition and inputs, and
9
+ * usually no `bindings` — so before this, nothing closed them, and compile failed
10
+ * at `BINDING_PLACEHOLDER_UNRESOLVED` while `check` passed.
11
+ *
12
+ * For instance, the manifest `registry get --local` returns for a sibling Flow:
13
+ *
14
+ * ```json
15
+ * "model": { "bindings": { "resource": "process", "resourceSubType": "Flow", "resourceKey": "k1",
16
+ * "values": [{ "name": "name", "default": "Notifier" }, { "name": "folderPath", "default": "" }] },
17
+ * "context": [{ "name": "name", "value": "<bindings.name>" }, { "name": "folderPath", "value": "<bindings.folderPath>" }] }
18
+ * ```
19
+ *
20
+ * needs two `process` entries keyed `k1`: `name` = "Notifier" and `folderPath` = "".
21
+ * {@link planContributionBindings} reads exactly those facts off the definition.
22
+ *
23
+ * `connection` resources are out of scope: a connector definition's entries are
24
+ * keyed by the tenant connection id, which the definition does not carry. A raw
25
+ * connector node is refused for that reason (`connector-raw-node.ts`).
26
+ *
27
+ * Pure: `serialize` lowers with it, and `check` runs it dry so the two agree.
28
+ */
29
+ /** The `<bindings.NAME>` names a definition's `model.context` references, in order, once each. */
30
+ export function referencedBindingNames(model) {
31
+ const names = [];
32
+ for (const row of Array.isArray(model?.context) ? model.context : []) {
33
+ const name = typeof row?.value === 'string' ? /^<bindings\.(.+)>$/.exec(row.value)?.[1] : undefined;
34
+ if (name !== undefined && !names.includes(name))
35
+ names.push(name);
36
+ }
37
+ return names;
38
+ }
39
+ /**
40
+ * Plan the entries a contribution-lowered node needs: for each `<bindings.NAME>`
41
+ * its definition's `model.context` references and `supplied` does not cover, one
42
+ * entry built from the definition — `resource`, `resourceKey`, `resourceSubType`
43
+ * from `model.bindings`, and `name`, `default`, `propertyAttribute` from the
44
+ * matching `model.bindings.values` row.
45
+ *
46
+ * A supplied entry covers a name when it has the same `resource` and `name`: the
47
+ * contributor's own bindings win, as they always did.
48
+ *
49
+ * A name is a problem (not an entry) when the definition declares no
50
+ * `values` row for it, or carries no `resourceKey` — a per-tenant template such
51
+ * as the bundled `core.action.queue.create` (`resourceKey: ""`), which only a
52
+ * typed factory can fill.
53
+ *
54
+ * @param def - The resolved definition.
55
+ * @param supplied - The bindings the contribution returned.
56
+ */
57
+ export function planContributionBindings(def, supplied = []) {
58
+ const model = def?.model;
59
+ const names = referencedBindingNames(model);
60
+ const resource = model?.bindings?.resource;
61
+ // Connection (or undeclared) resources are keyed by a tenant connection id the
62
+ // definition does not carry; the connector paths own them.
63
+ if (names.length === 0 || typeof resource !== 'string' || !resource || resource === 'connection') {
64
+ return { entries: [], problems: [] };
65
+ }
66
+ const open = names.filter((n) => !supplied.some((b) => b?.resource === resource && b?.name === n));
67
+ if (open.length === 0)
68
+ return { resource, entries: [], problems: [] };
69
+ const label = `${def?.nodeType}@${def?.version}`;
70
+ const resourceKey = model.bindings.resourceKey;
71
+ if (typeof resourceKey !== 'string' || !resourceKey) {
72
+ return {
73
+ resource,
74
+ entries: [],
75
+ problems: open.map((n) => `${label} references "<bindings.${n}>", and its model.bindings carries no resourceKey, so no `
76
+ + `"${resource}" binding can be built for it. This definition is a per-tenant template, not a resolved `
77
+ + `manifest: use the typed factory for the family, or the manifest \`uip maestro flow registry get `
78
+ + `${def?.nodeType}\` returns for a real resource, or return the bindings from contribute().`),
79
+ };
80
+ }
81
+ const values = Array.isArray(model.bindings.values) ? model.bindings.values : [];
82
+ const subType = model.bindings.resourceSubType;
83
+ const entries = [];
84
+ const problems = [];
85
+ for (const n of open) {
86
+ const row = values.find((r) => r?.name === n);
87
+ if (!row) {
88
+ problems.push(`${label} references "<bindings.${n}>", but its model.bindings.values declares no "${n}" row, so `
89
+ + `there is no default to bind it to. Pass the manifest exactly as \`uip maestro flow registry get\` `
90
+ + `returns it, or return the "${n}" binding from contribute().`);
91
+ continue;
92
+ }
93
+ entries.push({
94
+ name: n,
95
+ type: typeof row.type === 'string' && row.type ? row.type : 'string',
96
+ resource,
97
+ resourceKey,
98
+ ...(typeof row.default === 'string' ? { default: row.default } : {}),
99
+ propertyAttribute: typeof row.propertyAttribute === 'string' && row.propertyAttribute
100
+ ? row.propertyAttribute : n,
101
+ ...(typeof subType === 'string' && subType ? { resourceSubType: subType } : {}),
102
+ });
103
+ }
104
+ return { resource, resourceKey, entries, problems };
105
+ }
@@ -29,7 +29,7 @@
29
29
  * and gets back diagnostics with no location. The caller stamps the location
30
30
  * (which node / task / field) it came from.
31
31
  */
32
- import * as ts from 'typescript';
32
+ import { typescript } from './typescript-module.js';
33
33
  /**
34
34
  * A JSONPath wildcard/filter step — the spelling that reaches for JavaScript and
35
35
  * misses. Used only to add a suggestion; the parse decides.
@@ -47,15 +47,18 @@ const JSONPATH_WILDCARD = /\[\s*(?:\*|\?|'[^']*'|"[^"]*")\s*\]|\.\.[A-Za-z_$]/;
47
47
  * `ts.createSourceFile` is a parse, not an evaluation — nothing in `expr` runs.
48
48
  * TypeScript is already a runtime dependency of this package (see
49
49
  * `core/script-return.ts`, which infers a script's return type the same way), so
50
- * this adds no dependency.
50
+ * this adds no dependency. It is loaded on the first check, not at import
51
+ * (`core/typescript-module.ts`).
51
52
  */
52
53
  function syntaxError(expr) {
54
+ const ts = typescript();
53
55
  const problems = parseExpression(expr).problems;
54
56
  if (problems.length === 0)
55
57
  return undefined;
56
58
  return ts.flattenDiagnosticMessageText(problems[0].messageText, ' ');
57
59
  }
58
60
  function parseExpression(expr) {
61
+ const ts = typescript();
59
62
  const source = ts.createSourceFile('expression.ts', `(${expr}\n)`, ts.ScriptTarget.ES2020,
60
63
  /* setParentNodes */ false);
61
64
  // `parseDiagnostics` is where the scanner records syntax problems. It is not on
@@ -77,6 +80,7 @@ function retype(expr, escapes, keepCooked) {
77
80
  }
78
81
  /** The value a leaf denotes — a name, or a literal's value (a regular expression's is its source). */
79
82
  function leafValue(node) {
83
+ const ts = typescript();
80
84
  if (ts.isIdentifier(node) || ts.isPrivateIdentifier(node))
81
85
  return node.text;
82
86
  // NumericLiteral … TemplateTail: every literal and template piece carries `.text`.
@@ -86,6 +90,7 @@ function leafValue(node) {
86
90
  return undefined;
87
91
  }
88
92
  function children(node) {
93
+ const ts = typescript();
89
94
  const out = [];
90
95
  ts.forEachChild(node, (c) => { out.push(c); });
91
96
  return out;
@@ -0,0 +1 @@
1
+ export declare function writeJsonFile(path: string, value: unknown): void;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Write `value` as an emitted JSON artifact: 2-space indent and a trailing newline.
3
+ *
4
+ * Every emitted `.flow`, caseplan, entry-points, bindings_v2 and library file is
5
+ * byte-locked, and twelve call sites each spelled this out by hand; a copy that dropped
6
+ * the `'\n'` would break byte-lock on that one artifact only. FB007 holds pretty-printed
7
+ * JSON writes to this function. Creating the parent directory stays the caller's job.
8
+ */
9
+ import { writeFileSync } from 'node:fs';
10
+ export function writeJsonFile(path, value) {
11
+ writeFileSync(path, JSON.stringify(value, null, 2) + '\n');
12
+ }
@@ -28,7 +28,7 @@
28
28
  * into a designer error — the exact defect this file exists to remove, pointed
29
29
  * the other way.
30
30
  */
31
- import * as ts from 'typescript';
31
+ import { typescript } from './typescript-module.js';
32
32
  /** Normalize whatever the author wrote into the emitted shape. */
33
33
  export function declaredScriptShape(returns) {
34
34
  if (typeof returns === 'string')
@@ -59,6 +59,7 @@ export function declaredScriptShape(returns) {
59
59
  * fields written down says so with `returns: {…}`.
60
60
  */
61
61
  export function inferScriptShape(code) {
62
+ const ts = typescript();
62
63
  // Wrap so a top-level `return` parses — this is how the runtime executes it.
63
64
  const sf = ts.createSourceFile('script.ts', `function __block() {\n${code}\n}`, ts.ScriptTarget.ES2020, true);
64
65
  // `var d = Math.floor(...); return { days: d }` is how these bodies are
@@ -99,6 +100,7 @@ export function inferScriptShape(code) {
99
100
  }
100
101
  /** The type of one expression, or undefined when it is not written down. */
101
102
  function typeOf(expr, locals, depth) {
103
+ const ts = typescript();
102
104
  // Bounded: a local initialized from another local is followed, a cycle is not.
103
105
  if (depth > 8)
104
106
  return undefined;
@@ -163,6 +165,7 @@ function typeOf(expr, locals, depth) {
163
165
  }
164
166
  /** `a + b`, comparisons, and the short-circuit operators. */
165
167
  function binaryShape(e, locals, depth) {
168
+ const ts = typescript();
166
169
  const op = e.operatorToken.kind;
167
170
  // A comparison is a boolean whatever its operands are.
168
171
  if (op === ts.SyntaxKind.EqualsEqualsToken || op === ts.SyntaxKind.EqualsEqualsEqualsToken
@@ -55,6 +55,7 @@ export const TYPED_FACTORIES = {
55
55
  'core.logic.switch': { factory: '.switch()', bundled: ['1.0.0', '1.1'] },
56
56
  'core.logic.terminate': { factory: '.terminate()', bundled: ['1.0.0', '1.0'] },
57
57
  'core.subflow': { factory: 'subflow(child, inputs)', bundled: ['1.0.0', '1.0'] },
58
+ 'uipath.agent.autonomous': { factory: 'inlineAgent()', bundled: ['1.2', '1.3', '1.4'] },
58
59
  'uipath.agent.conversational': { factory: 'conversationalAgent()', bundled: ['1.6', '1.7'] },
59
60
  'uipath.agent.voice': { factory: 'voiceAgent()', bundled: ['1.0', '1.1'] },
60
61
  'uipath.conversational.get-conversation-context': { factory: 'conversationContext()', bundled: ['1.0'] },
@@ -0,0 +1,2 @@
1
+ import type * as TS from 'typescript';
2
+ export declare function typescript(): typeof TS;
@@ -0,0 +1,18 @@
1
+ /// <reference types="node" />
2
+ /**
3
+ * The TypeScript compiler, loaded on first use.
4
+ *
5
+ * Every builder entry reaches the expression and script checkers, and loading the compiler
6
+ * costs ~120 ms that a flow which never runs those checks should not pay (FB009). The
7
+ * specifier stays a literal at the call so the architecture lint sees the edge (as a lazy
8
+ * one); FB005 keeps this the only definition.
9
+ *
10
+ * The triple-slash reference: tests type-check generated code against `flow-sdk.ts`'s
11
+ * import graph without `@types/node` in scope, and this is the one `node:` import in that
12
+ * graph. Without it they fail with TS2307 on 'node:module'. It is not emitted into the .d.ts.
13
+ */
14
+ import { createRequire } from 'node:module';
15
+ let typescriptModule;
16
+ export function typescript() {
17
+ return (typescriptModule ??= createRequire(import.meta.url)('typescript'));
18
+ }