@uipath/maestro-builder-sdk 6.27.1 → 6.29.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 +6 -6
- package/dist/api-members.md +38 -36
- package/dist/cli/commands/flow.js +8 -2
- package/dist/core/connector-inputs.d.ts +6 -0
- package/dist/core/connector-inputs.js +7 -2
- package/dist/decompile.js +7 -0
- package/dist/flow-node-type.d.ts +6 -0
- package/dist/flow-sdk.d.ts +46 -0
- package/dist/flow-sdk.js +44 -0
- package/dist/merge-cli.d.ts +1 -1
- package/dist/merge-cli.js +75 -8
- package/dist/merge-compile.d.ts +55 -0
- package/dist/merge-compile.js +104 -0
- package/dist/merge.d.ts +9 -0
- package/dist/merge.js +22 -1
- package/dist/nodes/hitl/flow/node-type.js +1 -0
- package/dist/serialize.d.ts +26 -0
- package/dist/serialize.js +84 -10
- package/package.json +2 -2
package/dist/api-index.md
CHANGED
|
@@ -57,13 +57,13 @@ could hand you spans for a version you do not have.
|
|
|
57
57
|
| `apiWorkflow` | function | `dist/core/actions.d.ts:1658-1692` | Actions | Invoke a deployed API workflow — a coded workflow published to Orchestrator, run as a serverless job rather than by a… |
|
|
58
58
|
| `ApiWorkflowInputs` | interface | `dist/core/actions.d.ts:411-442` | Option shapes | 5 field(s) |
|
|
59
59
|
| `AppRef` | interface | `dist/nodes/hitl/flow/spec.d.ts:140-185` | Supporting types | A deployed Action App that supplies a human task's form — the `'action-app'` variant's subject. |
|
|
60
|
-
| `ArmBuilder` | class | `dist/flow-sdk.d.ts:
|
|
60
|
+
| `ArmBuilder` | class | `dist/flow-sdk.d.ts:1230-1253` | Builders | The sub-builder an ARM callback receives — a `StepList` that can also name itself with `.label(...)`. |
|
|
61
61
|
| `AskedField` | interface | `dist/core/actions.d.ts:79-89` | Supporting types | A value the reviewer FILLS IN: read downstream with `out('<step>', '<id>')`. |
|
|
62
62
|
| `batchTransform` | function | `dist/nodes/ai-patterns/flow/factories.d.ts:49-83` | Actions | Add AI-generated columns to a CSV — the platform's **Batch transform** node, `uipath.pattern.batch-transform` (service… |
|
|
63
63
|
| `BatchTransformInputs` | interface | `dist/nodes/ai-patterns/flow/spec.d.ts:48-63` | Option shapes | 4 field(s) |
|
|
64
64
|
| `BindingContribution` | interface | `dist/core/node-classes.d.ts:80-101` | Supporting types | A resource binding a contribution hoists to the flow's top-level `bindings` array — the shape the `.flow` format… |
|
|
65
65
|
| `BuiltEntryPoint` | interface | `dist/flow-sdk.d.ts:719-731` | Supporting types | One additional flow root, built by `.entryPoint()`. |
|
|
66
|
-
| `BuiltFlow` | interface | `dist/flow-sdk.d.ts:732-
|
|
66
|
+
| `BuiltFlow` | interface | `dist/flow-sdk.d.ts:732-779` | Supporting types | 17 field(s) |
|
|
67
67
|
| `BuiltinToolName` | type | `dist/core/actions.d.ts:1066-1067` | Supporting types | The three platform-shipped built-in tools (fixed registry types). |
|
|
68
68
|
| `BuiltinToolRef` | interface | `dist/core/actions.d.ts:1199-1219` | Supporting types | A platform built-in tool. |
|
|
69
69
|
| `BuiltInValidatorGuardrail` | interface | `dist/core/actions.d.ts:762-803` | Supporting types | A platform-shipped validator, configured by parameters. |
|
|
@@ -128,11 +128,11 @@ could hand you spans for a version you do not have.
|
|
|
128
128
|
| `FilterCondition` | type | `dist/nodes/transform/flow/spec.d.ts:10-11` | Supporting types | Comparison a filter rule applies to a field. |
|
|
129
129
|
| `FilterMatch` | type | `dist/nodes/transform/flow/spec.d.ts:8-9` | Supporting types | How a filter combines its rules: every rule must match, or any one. |
|
|
130
130
|
| `FilterRule` | interface | `dist/nodes/transform/flow/spec.d.ts:12-24` | Supporting types | 3 field(s) |
|
|
131
|
-
| `flow` | function | `dist/flow-sdk.d.ts:
|
|
131
|
+
| `flow` | function | `dist/flow-sdk.d.ts:1618-1633` | Flow construction | Start building a flow with the given id. |
|
|
132
132
|
| `FlowAction` | class | `dist/core/node-classes.d.ts:162-168` | Supporting types | A node placed as a step — pass an instance to `.step(name, …)`. |
|
|
133
133
|
| `FlowActionSpec` | type | `dist/flow-sdk.d.ts:53-54` | Supporting types | What `.step()` accepts here: the shared actions plus this SDK's subflow. |
|
|
134
134
|
| `FlowActionSpecs` | interface | `dist/core/actions.d.ts:1443-1520` | Supporting types | Every action kind, keyed by kind, to the body of its spec — the arm's fields other than `kind`. |
|
|
135
|
-
| `FlowBuilder` | class | `dist/flow-sdk.d.ts:
|
|
135
|
+
| `FlowBuilder` | class | `dist/flow-sdk.d.ts:1254-1617` | Builders | 15 member(s) |
|
|
136
136
|
| `FlowLayout` | interface | `dist/flow-sdk.d.ts:705-718` | Supporting types | Designer layout for a flow, keyed by AUTHOR-level ids: node entries by step name (plus the trigger id and `end`), edge… |
|
|
137
137
|
| `FlowNode` | class | `dist/core/node-classes.d.ts:126-161` | Supporting types | The abstract root of every definition-backed node the builder can place. |
|
|
138
138
|
| `FlowResource` | class | `dist/core/node-classes.d.ts:176-183` | Supporting types | A node attached to another semantic node — an inline agent's tool, context, memory, or escalation. |
|
|
@@ -225,11 +225,11 @@ could hand you spans for a version you do not have.
|
|
|
225
225
|
| `SendMessageInputs` | interface | `dist/nodes/conversation/flow/spec.d.ts:8-27` | Option shapes | 4 field(s) |
|
|
226
226
|
| `ShownField` | interface | `dist/core/actions.d.ts:63-78` | Supporting types | A value the reviewer READS: shown on the form, filled in from the flow. |
|
|
227
227
|
| `Step` | type | `dist/flow-sdk.d.ts:508-627` | Supporting types | |
|
|
228
|
-
| `StepList` | class | `dist/flow-sdk.d.ts:
|
|
228
|
+
| `StepList` | class | `dist/flow-sdk.d.ts:780-1229` | Builders | Collects a sequence of steps. |
|
|
229
229
|
| `STICKY_NOTE_COLORS` | const | `dist/flow-sdk.d.ts:658-663` | Flow construction | The designer's sticky-note palette. |
|
|
230
230
|
| `StickyNote` | interface | `dist/flow-sdk.d.ts:670-704` | Supporting types | A canvas sticky note — free text pinned to the diagram, for the humans reading it. |
|
|
231
231
|
| `StickyNoteColor` | type | `dist/flow-sdk.d.ts:664-669` | Supporting types | A sticky note's swatch. |
|
|
232
|
-
| `subflow` | function | `dist/flow-sdk.d.ts:
|
|
232
|
+
| `subflow` | function | `dist/flow-sdk.d.ts:1634-1673` | Flow construction | Run another flow as one step, and read back what it returns. |
|
|
233
233
|
| `SubflowSpec` | interface | `dist/flow-sdk.d.ts:45-52` | Supporting types | A step that runs a child flow. |
|
|
234
234
|
| `summarize` | function | `dist/nodes/ai-patterns/flow/factories.d.ts:8-48` | Actions | Summarize a document with citations — the platform's **Summarize** node. |
|
|
235
235
|
| `SummarizeInputs` | interface | `dist/nodes/ai-patterns/flow/spec.d.ts:8-40` | Option shapes | 3 field(s) |
|
package/dist/api-members.md
CHANGED
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
|
|
6
6
|
# Maestro Builder SDK — member index
|
|
7
7
|
|
|
8
|
-
**A lookup table of
|
|
8
|
+
**A lookup table of 1118 rows — match one name in it, do not read it.**
|
|
9
9
|
Grep or search for the member you have; the row it lands on is the whole
|
|
10
10
|
answer. Reading top to bottom costs ~20x what the one row does and tells you
|
|
11
11
|
nothing you asked for.
|
|
12
12
|
|
|
13
|
-
Every field and method of every exported shape —
|
|
13
|
+
Every field and method of every exported shape — 1118 across
|
|
14
14
|
200 interfaces and classes — keyed by the MEMBER's own name.
|
|
15
15
|
|
|
16
16
|
**Use this when the name you have is a field or a method**, which is usually
|
|
@@ -28,7 +28,7 @@ truncated summary would, for less. Read the span.
|
|
|
28
28
|
Member names repeat across shapes (`name` is declared on 69 of them), so the
|
|
29
29
|
`Declared on` column is what makes a match actionable. For the whole shape
|
|
30
30
|
rather than the one field, look that name up in [`api-index.md`](api-index.md) —
|
|
31
|
-
which is why its span is not repeated on all
|
|
31
|
+
which is why its span is not repeated on all 1118 rows here.
|
|
32
32
|
|
|
33
33
|
**A name that misses both indexes is probably not part of the API.** The one
|
|
34
34
|
that comes up is a RUNTIME output key — a human task's `Action`, a step's
|
|
@@ -66,7 +66,7 @@ not find it either.
|
|
|
66
66
|
| `app` | property | `HumanTaskOpts` | `dist/bpmn/bpmn-sdk.d.ts:1337-1338` |
|
|
67
67
|
| `appSystemName` | property | `AppRef` | `dist/nodes/hitl/flow/spec.d.ts:170-175` |
|
|
68
68
|
| `appVersion` | property | `HumanTaskOpts` | `dist/bpmn/bpmn-sdk.d.ts:1339-1340` |
|
|
69
|
-
| `armLabel` | property | `ArmBuilder` | `dist/flow-sdk.d.ts:
|
|
69
|
+
| `armLabel` | property | `ArmBuilder` | `dist/flow-sdk.d.ts:1242` |
|
|
70
70
|
| `assignee` | property | `HitlRecipient` | `dist/nodes/hitl/flow/spec.d.ts:52-63` |
|
|
71
71
|
| `async` | property | `OrchestratorAsyncOpts` | `dist/bpmn/bpmn-sdk.d.ts:1281-1285` |
|
|
72
72
|
| `atRiskPercentage` | property | `EscalationOpts` | `dist/case/case-sdk.d.ts:132-137` |
|
|
@@ -97,14 +97,14 @@ not find it either.
|
|
|
97
97
|
| `body` | property | `TypedContextRow` | `dist/bpmn/typed-node.d.ts:176-181` |
|
|
98
98
|
| `body` | property | `TypedInputRow` | `dist/bpmn/typed-node.d.ts:207-208` |
|
|
99
99
|
| `boundaryEvent` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:2239-2246` |
|
|
100
|
-
| `branch` | method | `StepList` | `dist/flow-sdk.d.ts:
|
|
100
|
+
| `branch` | method | `StepList` | `dist/flow-sdk.d.ts:979-997` |
|
|
101
101
|
| `branches` | property | `HttpInputsBase` | `dist/nodes/http/flow/spec.d.ts:25-30` |
|
|
102
|
-
| `break` | method | `StepList` | `dist/flow-sdk.d.ts:
|
|
102
|
+
| `break` | method | `StepList` | `dist/flow-sdk.d.ts:1114-1123` |
|
|
103
103
|
| `breakEnabled` | property | `DoWhileOptions` | `dist/flow-sdk.d.ts:505-506` |
|
|
104
104
|
| `breakEnabled` | property | `LoopOptions` | `dist/flow-sdk.d.ts:492-496` |
|
|
105
105
|
| `build` | method | `BpmnBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3483-3488` |
|
|
106
106
|
| `build` | method | `CaseBuilder` | `dist/case/case-sdk.d.ts:1269-1274` |
|
|
107
|
-
| `build` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:
|
|
107
|
+
| `build` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1610-1616` |
|
|
108
108
|
| `businessRule` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:2527-2573` |
|
|
109
109
|
| `by` | property | `LookupResolution` | `dist/core/lookups.d.ts:164` |
|
|
110
110
|
| `by` | property | `LookupSpec` | `dist/core/lookups.d.ts:27-28` |
|
|
@@ -172,7 +172,7 @@ not find it either.
|
|
|
172
172
|
| `context` | property | `RegistryTypeSpec` | `dist/bpmn/typed-node.d.ts:87` |
|
|
173
173
|
| `contextRows` | property | `ActivityNodeOpts` | `dist/bpmn/bpmn-sdk.d.ts:1528-1535` |
|
|
174
174
|
| `contextVerbatim` | property | `ActivityNodeOpts` | `dist/bpmn/bpmn-sdk.d.ts:1600-1605` |
|
|
175
|
-
| `continue` | method | `StepList` | `dist/flow-sdk.d.ts:
|
|
175
|
+
| `continue` | method | `StepList` | `dist/flow-sdk.d.ts:1124-1138` |
|
|
176
176
|
| `contribute` | method | `FlowNode` | `dist/core/node-classes.d.ts:144-153` |
|
|
177
177
|
| `conversationalAgent` | property | `FlowActionSpecs` | `dist/core/actions.d.ts:1479-1482` |
|
|
178
178
|
| `conversationContext` | property | `FlowActionSpecs` | `dist/nodes/conversation/flow/spec.d.ts:55-58` |
|
|
@@ -208,7 +208,7 @@ not find it either.
|
|
|
208
208
|
| `deferDate` | property | `QueueItemInputs` | `dist/nodes/queue/flow/spec.d.ts:48-49` |
|
|
209
209
|
| `definition` | property | `NodeContribution` | `dist/core/node-classes.d.ts:111-112` |
|
|
210
210
|
| `definitions` | property | `BuiltFlow` | `dist/flow-sdk.d.ts:758-763` |
|
|
211
|
-
| `definitions` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:
|
|
211
|
+
| `definitions` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1471-1511` |
|
|
212
212
|
| `delay` | property | `FlowActionSpecs` | `dist/nodes/delay/flow/spec.d.ts:38-41` |
|
|
213
213
|
| `dependsOn` | property | `LookupSpec` | `dist/core/lookups.d.ts:34-35` |
|
|
214
214
|
| `description` | property | `AgentMemoryRef` | `dist/core/actions.d.ts:1187` |
|
|
@@ -225,7 +225,7 @@ not find it either.
|
|
|
225
225
|
| `description` | property | `CustomGuardrail` | `dist/core/actions.d.ts:755` |
|
|
226
226
|
| `description` | property | `EscalationRef` | `dist/core/actions.d.ts:1349-1350` |
|
|
227
227
|
| `description` | property | `EventTriggerOpts` | `dist/case/case-sdk.d.ts:241` |
|
|
228
|
-
| `description` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:
|
|
228
|
+
| `description` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1280-1287` |
|
|
229
229
|
| `description` | property | `HttpRequestToolRef` | `dist/core/actions.d.ts:1154` |
|
|
230
230
|
| `description` | property | `IxpExtractInputs` | `dist/core/actions.d.ts:337-344` |
|
|
231
231
|
| `description` | property | `IxpToolRef` | `dist/core/actions.d.ts:1327-1328` |
|
|
@@ -267,7 +267,7 @@ not find it either.
|
|
|
267
267
|
| `document` | property | `HitlInputs` | `dist/nodes/hitl/flow/spec.d.ts:252-256` |
|
|
268
268
|
| `documentClassify` | property | `FlowActionSpecs` | `dist/nodes/document/flow/spec.d.ts:56-59` |
|
|
269
269
|
| `documentId` | property | `DocValidationInputs` | `dist/nodes/hitl/flow/spec.d.ts:84-85` |
|
|
270
|
-
| `doWhile` | method | `StepList` | `dist/flow-sdk.d.ts:
|
|
270
|
+
| `doWhile` | method | `StepList` | `dist/flow-sdk.d.ts:1089-1113` |
|
|
271
271
|
| `dueDate` | property | `QueueItemInputs` | `dist/nodes/queue/flow/spec.d.ts:50-51` |
|
|
272
272
|
| `duration` | property | `TimerSpec` | `dist/bpmn/bpmn-sdk.d.ts:33-34` |
|
|
273
273
|
| `dynamicExtract` | property | `FlowActionSpecs` | `dist/nodes/document/flow/spec.d.ts:60-63` |
|
|
@@ -291,12 +291,12 @@ not find it either.
|
|
|
291
291
|
| `entity` | property | `DataServiceOpts` | `dist/bpmn/bpmn-sdk.d.ts:1090-1091` |
|
|
292
292
|
| `entry` | property | `BuiltStage` | `dist/case/case-sdk.d.ts:528` |
|
|
293
293
|
| `entry` | property | `BuiltTask` | `dist/case/case-sdk.d.ts:520` |
|
|
294
|
-
| `entryPoint` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:
|
|
294
|
+
| `entryPoint` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1346-1396` |
|
|
295
295
|
| `entryPointId` | property | `ProcessMetadata` | `dist/bpmn/bpmn-sdk.d.ts:534-539` |
|
|
296
296
|
| `entryPoints` | property | `BuiltFlow` | `dist/flow-sdk.d.ts:764-765` |
|
|
297
297
|
| `entryWhen` | method | `StageBuilder` | `dist/case/case-sdk.d.ts:1004-1011` |
|
|
298
298
|
| `entryWhen` | method | `TaskBuilder` | `dist/case/case-sdk.d.ts:947-956` |
|
|
299
|
-
| `err` | method | `StepList` | `dist/flow-sdk.d.ts:
|
|
299
|
+
| `err` | method | `StepList` | `dist/flow-sdk.d.ts:788-813` |
|
|
300
300
|
| `error` | property | `BoundaryOpts` | `dist/bpmn/bpmn-sdk.d.ts:750-754` |
|
|
301
301
|
| `error` | property | `EndOpts` | `dist/bpmn/bpmn-sdk.d.ts:696-706` |
|
|
302
302
|
| `error` | property | `EventSubProcessOpts` | `dist/bpmn/bpmn-sdk.d.ts:1842-1847` |
|
|
@@ -461,7 +461,7 @@ not find it either.
|
|
|
461
461
|
| `inclusiveGateway` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:2266-2273` |
|
|
462
462
|
| `inlineAgent` | property | `FlowActionSpecs` | `dist/core/actions.d.ts:1491-1494` |
|
|
463
463
|
| `input` | method | `CaseBuilder` | `dist/case/case-sdk.d.ts:1160-1185` |
|
|
464
|
-
| `input` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:
|
|
464
|
+
| `input` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1551-1563` |
|
|
465
465
|
| `input` | property | `HumanTaskOpts` | `dist/bpmn/bpmn-sdk.d.ts:1355-1356` |
|
|
466
466
|
| `input` | property | `OrchestratorOpts` | `dist/bpmn/bpmn-sdk.d.ts:1241-1242` |
|
|
467
467
|
| `input` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3068-3076` |
|
|
@@ -534,7 +534,7 @@ not find it either.
|
|
|
534
534
|
| `kind` | property | `SubflowSpec` | `dist/flow-sdk.d.ts:47` |
|
|
535
535
|
| `kind` | property | `WhenExpression` | `dist/case/case-sdk.d.ts:99-100` |
|
|
536
536
|
| `kValue` | property | `AgentMemoryRef` | `dist/core/actions.d.ts:1194-1195` |
|
|
537
|
-
| `label` | method | `ArmBuilder` | `dist/flow-sdk.d.ts:
|
|
537
|
+
| `label` | method | `ArmBuilder` | `dist/flow-sdk.d.ts:1243-1252` |
|
|
538
538
|
| `label` | property | `AskedField` | `dist/core/actions.d.ts:83-84` |
|
|
539
539
|
| `label` | property | `BuiltStage` | `dist/case/case-sdk.d.ts:523` |
|
|
540
540
|
| `label` | property | `InOutField` | `dist/core/actions.d.ts:99-100` |
|
|
@@ -548,7 +548,7 @@ not find it either.
|
|
|
548
548
|
| `layout` | property | `BuiltCase` | `dist/case/case-sdk.d.ts:646-647` |
|
|
549
549
|
| `layout` | property | `BuiltFlow` | `dist/flow-sdk.d.ts:754-755` |
|
|
550
550
|
| `layout` | method | `CaseBuilder` | `dist/case/case-sdk.d.ts:1139-1159` |
|
|
551
|
-
| `layout` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:
|
|
551
|
+
| `layout` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1288-1298` |
|
|
552
552
|
| `limit` | property | `DataFabricReadInputs` | `dist/nodes/data-fabric/flow/spec.d.ts:95-100` |
|
|
553
553
|
| `limit` | property | `DoWhileOptions` | `dist/flow-sdk.d.ts:503-504` |
|
|
554
554
|
| `literal` | property | `Expr` | `dist/core/expr.d.ts:18` |
|
|
@@ -558,7 +558,7 @@ not find it either.
|
|
|
558
558
|
| `lookups` | property | `ConnectorMeta` | `dist/core/connectors.d.ts:76-87` |
|
|
559
559
|
| `loop` | property | `ActivityNodeFields` | `dist/bpmn/bpmn-sdk.d.ts:335-336` |
|
|
560
560
|
| `loop` | property | `ActivityOpts` | `dist/bpmn/bpmn-sdk.d.ts:832-833` |
|
|
561
|
-
| `loop` | method | `StepList` | `dist/flow-sdk.d.ts:
|
|
561
|
+
| `loop` | method | `StepList` | `dist/flow-sdk.d.ts:1077-1088` |
|
|
562
562
|
| `managed` | property | `HttpInputsBase` | `dist/nodes/http/flow/spec.d.ts:37-67` |
|
|
563
563
|
| `marksCaseComplete` | property | `BuiltCaseExitCondition` | `dist/case/case-sdk.d.ts:354` |
|
|
564
564
|
| `marksStageComplete` | property | `BuiltExitCondition` | `dist/case/case-sdk.d.ts:321` |
|
|
@@ -647,7 +647,7 @@ not find it either.
|
|
|
647
647
|
| `name` | property | `EventSubProcessOpts` | `dist/bpmn/bpmn-sdk.d.ts:1840-1841` |
|
|
648
648
|
| `name` | property | `EventTriggerOpts` | `dist/case/case-sdk.d.ts:240` |
|
|
649
649
|
| `name` | property | `ExternalTaskOpts` | `dist/bpmn/bpmn-sdk.d.ts:1499-1500` |
|
|
650
|
-
| `name` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:
|
|
650
|
+
| `name` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1272-1279` |
|
|
651
651
|
| `name` | property | `FlowOpts` | `dist/bpmn/bpmn-sdk.d.ts:1637-1638` |
|
|
652
652
|
| `name` | property | `GatewayOpts` | `dist/bpmn/bpmn-sdk.d.ts:760-761` |
|
|
653
653
|
| `name` | property | `HandlerOpts` | `dist/bpmn/bpmn-sdk.d.ts:1735-1736` |
|
|
@@ -709,11 +709,13 @@ not find it either.
|
|
|
709
709
|
| `onError` | method | `ActivityBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3259-3266` |
|
|
710
710
|
| `onError` | method | `ActivityBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3267-3274` |
|
|
711
711
|
| `onError` | method | `ActivityBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3275-3283` |
|
|
712
|
-
| `onError` | method | `StepList` | `dist/flow-sdk.d.ts:
|
|
712
|
+
| `onError` | method | `StepList` | `dist/flow-sdk.d.ts:868-928` |
|
|
713
713
|
| `onMessage` | method | `ActivityBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3302-3310` |
|
|
714
714
|
| `onMessage` | method | `ActivityBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3311-3319` |
|
|
715
715
|
| `onTimer` | method | `ActivityBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3284-3292` |
|
|
716
716
|
| `onTimer` | method | `ActivityBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3293-3301` |
|
|
717
|
+
| `openTails` | property | `BuiltFlow` | `dist/flow-sdk.d.ts:773-778` |
|
|
718
|
+
| `openTails` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1512-1550` |
|
|
717
719
|
| `operation` | property | `Aggregation` | `dist/nodes/transform/flow/spec.d.ts:37` |
|
|
718
720
|
| `operation` | property | `ConnectorToolRef` | `dist/core/actions.d.ts:1230-1231` |
|
|
719
721
|
| `operation` | property | `WaitConnectorPlaceholderSpec` | `dist/case/case-sdk.d.ts:368-369` |
|
|
@@ -727,7 +729,7 @@ not find it either.
|
|
|
727
729
|
| `outcomes` | property | `EscalationRef` | `dist/core/actions.d.ts:1395-1400` |
|
|
728
730
|
| `outcomes` | property | `HitlInputs` | `dist/nodes/hitl/flow/spec.d.ts:211-225` |
|
|
729
731
|
| `output` | method | `CaseBuilder` | `dist/case/case-sdk.d.ts:1186-1198` |
|
|
730
|
-
| `output` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:
|
|
732
|
+
| `output` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1564-1599` |
|
|
731
733
|
| `output` | property | `RegistryTypeSpec` | `dist/bpmn/typed-node.d.ts:90` |
|
|
732
734
|
| `output` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3077-3085` |
|
|
733
735
|
| `outputColumns` | property | `BatchTransformInputs` | `dist/nodes/ai-patterns/flow/spec.d.ts:56-60` |
|
|
@@ -763,7 +765,7 @@ not find it either.
|
|
|
763
765
|
| `pageRange` | property | `DynamicExtractInputs` | `dist/nodes/document/flow/spec.d.ts:49-50` |
|
|
764
766
|
| `pageRange` | property | `IxpExtractInputs` | `dist/core/actions.d.ts:326-327` |
|
|
765
767
|
| `parallel` | property | `LoopOptions` | `dist/flow-sdk.d.ts:485-486` |
|
|
766
|
-
| `parallel` | method | `StepList` | `dist/flow-sdk.d.ts:
|
|
768
|
+
| `parallel` | method | `StepList` | `dist/flow-sdk.d.ts:1041-1076` |
|
|
767
769
|
| `parallelGateway` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:2256-2265` |
|
|
768
770
|
| `parameters` | property | `ConnectorEventOpts` | `dist/bpmn/bpmn-sdk.d.ts:1479-1480` |
|
|
769
771
|
| `parameters` | property | `HttpOpts` | `dist/bpmn/bpmn-sdk.d.ts:1140-1145` |
|
|
@@ -862,7 +864,7 @@ not find it either.
|
|
|
862
864
|
| `retry` | property | `ActivityOpts` | `dist/bpmn/bpmn-sdk.d.ts:830-831` |
|
|
863
865
|
| `retryable` | property | `ErrorMappingRow` | `dist/bpmn/bpmn-sdk.d.ts:308-309` |
|
|
864
866
|
| `retryCount` | property | `HttpInputsBase` | `dist/nodes/http/flow/spec.d.ts:109-123` |
|
|
865
|
-
| `return` | method | `StepList` | `dist/flow-sdk.d.ts:
|
|
867
|
+
| `return` | method | `StepList` | `dist/flow-sdk.d.ts:1219-1228` |
|
|
866
868
|
| `returnCitations` | property | `SummarizeInputs` | `dist/nodes/ai-patterns/flow/spec.d.ts:34-39` |
|
|
867
869
|
| `returns` | property | `AgentInputs` | `dist/core/actions.d.ts:641-660` |
|
|
868
870
|
| `returns` | property | `ApiWorkflowInputs` | `dist/core/actions.d.ts:429-441` |
|
|
@@ -903,7 +905,7 @@ not find it either.
|
|
|
903
905
|
| `schemaVersion` | method | `BpmnBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3375-3404` |
|
|
904
906
|
| `schemaVersion` | property | `BuiltFlow` | `dist/flow-sdk.d.ts:738-744` |
|
|
905
907
|
| `schemaVersion` | method | `CaseBuilder` | `dist/case/case-sdk.d.ts:1068-1094` |
|
|
906
|
-
| `schemaVersion` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:
|
|
908
|
+
| `schemaVersion` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1431-1470` |
|
|
907
909
|
| `scope` | property | `EscalationRecipient` | `dist/case/case-sdk.d.ts:121` |
|
|
908
910
|
| `scopes` | property | `GuardrailSelector` | `dist/core/actions.d.ts:701` |
|
|
909
911
|
| `script` | property | `FlowActionSpecs` | `dist/nodes/script/flow/spec.d.ts:47-50` |
|
|
@@ -975,16 +977,16 @@ not find it either.
|
|
|
975
977
|
| `startName` | property | `EventSubProcessOpts` | `dist/bpmn/bpmn-sdk.d.ts:1887-1888` |
|
|
976
978
|
| `startPayload` | property | `EventSubProcessOpts` | `dist/bpmn/bpmn-sdk.d.ts:1889-1890` |
|
|
977
979
|
| `startProcess` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:2459-2478` |
|
|
978
|
-
| `step` | method | `StepList` | `dist/flow-sdk.d.ts:
|
|
980
|
+
| `step` | method | `StepList` | `dist/flow-sdk.d.ts:814-824` |
|
|
979
981
|
| `steps` | property | `BuiltEntryPoint` | `dist/flow-sdk.d.ts:729-730` |
|
|
980
982
|
| `steps` | property | `BuiltFlow` | `dist/flow-sdk.d.ts:748` |
|
|
981
|
-
| `steps` | property | `StepList` | `dist/flow-sdk.d.ts:
|
|
982
|
-
| `stepSwitch` | method | `StepList` | `dist/flow-sdk.d.ts:
|
|
983
|
-
| `stepToList` | method | `StepList` | `dist/flow-sdk.d.ts:
|
|
984
|
-
| `stepToRef` | method | `StepList` | `dist/flow-sdk.d.ts:
|
|
985
|
-
| `stepToRef` | method | `StepList` | `dist/flow-sdk.d.ts:
|
|
983
|
+
| `steps` | property | `StepList` | `dist/flow-sdk.d.ts:782` |
|
|
984
|
+
| `stepSwitch` | method | `StepList` | `dist/flow-sdk.d.ts:825-867` |
|
|
985
|
+
| `stepToList` | method | `StepList` | `dist/flow-sdk.d.ts:942-970` |
|
|
986
|
+
| `stepToRef` | method | `StepList` | `dist/flow-sdk.d.ts:1170-1198` |
|
|
987
|
+
| `stepToRef` | method | `StepList` | `dist/flow-sdk.d.ts:1199-1218` |
|
|
986
988
|
| `stickyNotes` | property | `BuiltFlow` | `dist/flow-sdk.d.ts:756-757` |
|
|
987
|
-
| `stickyNotes` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:
|
|
989
|
+
| `stickyNotes` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1299-1324` |
|
|
988
990
|
| `storageBucket` | property | `DocValidationInputs` | `dist/nodes/hitl/flow/spec.d.ts:82-83` |
|
|
989
991
|
| `strategy` | property | `LookupSpec` | `dist/core/lookups.d.ts:33` |
|
|
990
992
|
| `style` | property | `CaseNodeLayout` | `dist/case/case-sdk.d.ts:597-598` |
|
|
@@ -997,7 +999,7 @@ not find it either.
|
|
|
997
999
|
| `subType` | property | `VarSpec` | `dist/flow-sdk.d.ts:84-85` |
|
|
998
1000
|
| `summarize` | property | `FlowActionSpecs` | `dist/nodes/ai-patterns/flow/spec.d.ts:66-69` |
|
|
999
1001
|
| `summary` | property | `CaseAppConfig` | `dist/case/case-sdk.d.ts:585-586` |
|
|
1000
|
-
| `switch` | method | `StepList` | `dist/flow-sdk.d.ts:
|
|
1002
|
+
| `switch` | method | `StepList` | `dist/flow-sdk.d.ts:998-1040` |
|
|
1001
1003
|
| `systemPrompt` | property | `ConversationalAgentInputs` | `dist/core/actions.d.ts:134-139` |
|
|
1002
1004
|
| `systemPrompt` | property | `InlineAgentInputs` | `dist/core/actions.d.ts:814-863` |
|
|
1003
1005
|
| `systemPrompt` | property | `VoiceAgentInputs` | `dist/core/actions.d.ts:221-226` |
|
|
@@ -1022,7 +1024,7 @@ not find it either.
|
|
|
1022
1024
|
| `temperature` | property | `InlineAgentInputs` | `dist/core/actions.d.ts:924-925` |
|
|
1023
1025
|
| `temperature` | property | `VoiceSettings` | `dist/core/actions.d.ts:213-214` |
|
|
1024
1026
|
| `terminate` | property | `EndOpts` | `dist/bpmn/bpmn-sdk.d.ts:692-693` |
|
|
1025
|
-
| `terminate` | method | `StepList` | `dist/flow-sdk.d.ts:
|
|
1027
|
+
| `terminate` | method | `StepList` | `dist/flow-sdk.d.ts:1139-1169` |
|
|
1026
1028
|
| `threshold` | property | `ContextIndexRef` | `dist/core/actions.d.ts:1438-1439` |
|
|
1027
1029
|
| `timeCycle` | property | `BuiltTrigger` | `dist/case/case-sdk.d.ts:201-202` |
|
|
1028
1030
|
| `timeout` | property | `HttpInputsBase` | `dist/nodes/http/flow/spec.d.ts:91-108` |
|
|
@@ -1046,11 +1048,11 @@ not find it either.
|
|
|
1046
1048
|
| `trigger` | property | `BuiltFlow` | `dist/flow-sdk.d.ts:749-751` |
|
|
1047
1049
|
| `trigger` | method | `CaseBuilder` | `dist/case/case-sdk.d.ts:1224-1232` |
|
|
1048
1050
|
| `trigger` | property | `EscalationOpts` | `dist/case/case-sdk.d.ts:128-129` |
|
|
1049
|
-
| `trigger` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:
|
|
1051
|
+
| `trigger` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1325-1345` |
|
|
1050
1052
|
| `trigger` | property | `StartOpts` | `dist/bpmn/bpmn-sdk.d.ts:624-671` |
|
|
1051
1053
|
| `triggeredByEvent` | property | `SubProcessOpts` | `dist/bpmn/bpmn-sdk.d.ts:976-977` |
|
|
1052
1054
|
| `triggerId` | property | `BuiltFlow` | `dist/flow-sdk.d.ts:766-772` |
|
|
1053
|
-
| `triggerId` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:
|
|
1055
|
+
| `triggerId` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1397-1416` |
|
|
1054
1056
|
| `triggerOptions` | property | `BuiltFlow` | `dist/flow-sdk.d.ts:752-753` |
|
|
1055
1057
|
| `triggers` | property | `BuiltCase` | `dist/case/case-sdk.d.ts:644-645` |
|
|
1056
1058
|
| `triggers` | property | `CaseLayout` | `dist/case/case-sdk.d.ts:620-621` |
|
|
@@ -1106,7 +1108,7 @@ not find it either.
|
|
|
1106
1108
|
| `value` | property | `TypedInputRow` | `dist/bpmn/typed-node.d.ts:205-206` |
|
|
1107
1109
|
| `values` | property | `DataFabricCreateInputs` | `dist/nodes/data-fabric/flow/spec.d.ts:132-137` |
|
|
1108
1110
|
| `var` | method | `CaseBuilder` | `dist/case/case-sdk.d.ts:1199-1223` |
|
|
1109
|
-
| `var` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:
|
|
1111
|
+
| `var` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1600-1609` |
|
|
1110
1112
|
| `var` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3059-3067` |
|
|
1111
1113
|
| `var` | property | `TaskOutputBinding` | `dist/case/case-sdk.d.ts:494-495` |
|
|
1112
1114
|
| `var` | property | `TypedOutputRow` | `dist/bpmn/typed-node.d.ts:251-252` |
|
|
@@ -1129,7 +1131,7 @@ not find it either.
|
|
|
1129
1131
|
| `version` | property | `ConnectorToolRef` | `dist/core/actions.d.ts:1232-1233` |
|
|
1130
1132
|
| `version` | property | `EventSubscription` | `dist/core/actions.d.ts:2116` |
|
|
1131
1133
|
| `version` | property | `ExternalTaskOpts` | `dist/bpmn/bpmn-sdk.d.ts:1507-1508` |
|
|
1132
|
-
| `version` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:
|
|
1134
|
+
| `version` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1417-1430` |
|
|
1133
1135
|
| `version` | property | `NodeOptions` | `dist/flow-sdk.d.ts:397-404` |
|
|
1134
1136
|
| `version` | property | `TriggerMeta` | `dist/core/connectors.d.ts:126` |
|
|
1135
1137
|
| `version` | property | `TriggerOptions` | `dist/core/actions.d.ts:2073-2074` |
|
|
@@ -104,11 +104,14 @@ export function registerFlowCommands(program) {
|
|
|
104
104
|
});
|
|
105
105
|
flow.command('merge')
|
|
106
106
|
.description('Merge an edited flow with its original artifact.')
|
|
107
|
-
.argument('<edited>', 'edited .flow path')
|
|
107
|
+
.argument('<edited>', 'edited .flow path, or the edited .flow.ts source (merge compiles it, tolerating untouched draft nodes)')
|
|
108
108
|
.option('--original <file>', '(required) original .flow path, the artifact to merge into')
|
|
109
109
|
.option('-o, --output <file>', 'merged output path')
|
|
110
110
|
.option('--baseline <file>', 'compiled pristine decompile')
|
|
111
|
-
.option('--
|
|
111
|
+
.option('--baseline-from <file>', 'build the baseline from this original .flow (decompile + compile, tolerating draft nodes) instead of --baseline')
|
|
112
|
+
.option('--library <dir>', 'connector library, for compiling with --baseline-from or a .flow.ts edited source')
|
|
113
|
+
.option('--bindings <file>', 'bindings.json, for the same compiles')
|
|
114
|
+
.option('--strict', 'refuse when the no-edit round trip (the baseline) differs from the original')
|
|
112
115
|
.allowExcessArguments()
|
|
113
116
|
.action(async (_edited, options, command) => {
|
|
114
117
|
const pair = namedOrLegacySecond(command, {
|
|
@@ -121,6 +124,9 @@ export function registerFlowCommands(program) {
|
|
|
121
124
|
const argv = [original, edited];
|
|
122
125
|
addValue(argv, '-o', options.output);
|
|
123
126
|
addValue(argv, '--baseline', options.baseline);
|
|
127
|
+
addValue(argv, '--baseline-from', options.baselineFrom);
|
|
128
|
+
addValue(argv, '--library', options.library);
|
|
129
|
+
addValue(argv, '--bindings', options.bindings);
|
|
124
130
|
if (options.strict)
|
|
125
131
|
argv.push('--strict');
|
|
126
132
|
await invoke('flow merge', () => import('../../merge-cli.js'), argv);
|
|
@@ -37,6 +37,12 @@ export interface ConnectorInputOpts {
|
|
|
37
37
|
lookups?: Readonly<Record<string, LookupSpec>>;
|
|
38
38
|
/** `ignore` skips an unresolved lookup instead of refusing it — what `check` wants. */
|
|
39
39
|
unresolvedLookups?: 'error' | 'ignore';
|
|
40
|
+
/**
|
|
41
|
+
* Receives a missing REQUIRED input instead of refusing it — the draft
|
|
42
|
+
* tolerance of a merge-owned compile (#1134). Every other input error still
|
|
43
|
+
* refuses.
|
|
44
|
+
*/
|
|
45
|
+
onMissingRequired?: (message: string) => void;
|
|
40
46
|
}
|
|
41
47
|
/** Flow's dialect, re-exported so `serialize.ts` need not reach past this module. */
|
|
42
48
|
export { FLOW_EXPR_DIALECT } from './connector-checks.js';
|
|
@@ -116,8 +116,13 @@ export function buildConnectorInputs(rc, inputs, opts) {
|
|
|
116
116
|
// not know what to put in it than because they forgot it exists: name the
|
|
117
117
|
// id it sends and the helper that finds one, so "(string)" is not read as
|
|
118
118
|
// "any string" — an e-mail into `fields.reporter.id` is exactly that misreading.
|
|
119
|
-
if (f.required)
|
|
120
|
-
|
|
119
|
+
if (f.required) {
|
|
120
|
+
const message = `missing required input "${f.name}" (${f.type ?? 'value'})${missingLookupHint(f.name, lookups[f.name], rc, dialect.descriptors)}`;
|
|
121
|
+
if (opts.onMissingRequired)
|
|
122
|
+
opts.onMissingRequired(message);
|
|
123
|
+
else
|
|
124
|
+
errs.push(message);
|
|
125
|
+
}
|
|
121
126
|
continue;
|
|
122
127
|
}
|
|
123
128
|
// An unresolved lookup is swapped for its recorded id, or reported. It is
|
package/dist/decompile.js
CHANGED
|
@@ -2861,6 +2861,8 @@ function emitChildFlow(name, child, ctx) {
|
|
|
2861
2861
|
o: ctx.o,
|
|
2862
2862
|
};
|
|
2863
2863
|
const parts = [`${ctx.imp.use('flow')}(${tsLiteral(name)})`];
|
|
2864
|
+
// As for the root flow (emitFlow): every End is explicit, so nothing is implicit.
|
|
2865
|
+
parts.push('.openTails()');
|
|
2864
2866
|
// Variables.
|
|
2865
2867
|
const shape = (dir) => `{ ${globals.filter((g) => g.direction === dir).map((g) => `${key(g.name ?? g.id)}: ${declExpr(g, dir !== 'inout', ctx.imp)}`).join(', ')} }`;
|
|
2866
2868
|
if (globals.some((g) => g.direction === 'in'))
|
|
@@ -3050,6 +3052,11 @@ export function decompile(flow, options = {}) {
|
|
|
3050
3052
|
}
|
|
3051
3053
|
if (runCarried.size > 0)
|
|
3052
3054
|
e.line(d, `.definitions([${[...runCarried.values()].join(', ')}])`);
|
|
3055
|
+
// Every End in the file decompiles to an explicit `.return(...)` or
|
|
3056
|
+
// `.terminate(...)`, so the source needs no implicit End: one would only add
|
|
3057
|
+
// an End to a path the file leaves open (#1142). Always saying so, rather
|
|
3058
|
+
// than detecting open tails, keeps this from drifting from what serialize caps.
|
|
3059
|
+
e.line(d, '.openTails()');
|
|
3053
3060
|
// Trigger nodes. One root is the default: the isDefaultEntryPoint carrier
|
|
3054
3061
|
// when the file marks one (a multi-root flow always does), else `start`.
|
|
3055
3062
|
// A node's TYPE is not enough: `uipath.connector.event.<key>.<event>` is a
|
package/dist/flow-node-type.d.ts
CHANGED
|
@@ -288,6 +288,12 @@ export interface FlowNodeType<Spec> extends NodeType<Spec, FlowNodeContribution,
|
|
|
288
288
|
* envelope is in `<step>.output` (instance 430d43ad-4583-40c0-8f74-b49d2c4904e4).
|
|
289
289
|
*/
|
|
290
290
|
readonly errorEnvelope?: string;
|
|
291
|
+
/**
|
|
292
|
+
* `true`: a path that ends on this node is capped with an End even under
|
|
293
|
+
* `.openTails()`. A human task sets it: the product's `hitl-completed`
|
|
294
|
+
* rule wants an edge after the task.
|
|
295
|
+
*/
|
|
296
|
+
readonly capsOpenTail?: boolean;
|
|
291
297
|
/**
|
|
292
298
|
* The exits the AUTHOR named on this step — an HTTP call's response branches,
|
|
293
299
|
* and the port each leaves on — or why it has none to route. What
|
package/dist/flow-sdk.d.ts
CHANGED
|
@@ -770,6 +770,12 @@ export interface BuiltFlow {
|
|
|
770
770
|
* follows.
|
|
771
771
|
*/
|
|
772
772
|
triggerId?: string;
|
|
773
|
+
/**
|
|
774
|
+
* `true` when `.openTails()` was called: a path that runs out of steps
|
|
775
|
+
* stops on its last node, with no End node added. Absent means the default —
|
|
776
|
+
* every such path is capped with an End.
|
|
777
|
+
*/
|
|
778
|
+
openTails?: true;
|
|
773
779
|
}
|
|
774
780
|
/** Collects a sequence of steps. Used for the flow body and each branch/loop arm. */
|
|
775
781
|
declare class StepList {
|
|
@@ -1261,6 +1267,7 @@ declare class FlowBuilder extends StepList {
|
|
|
1261
1267
|
private _triggerOptions?;
|
|
1262
1268
|
private _entryPoints;
|
|
1263
1269
|
private _triggerId?;
|
|
1270
|
+
private _openTails;
|
|
1264
1271
|
constructor(_id: string);
|
|
1265
1272
|
/**
|
|
1266
1273
|
* Set the flow's display name.
|
|
@@ -1502,6 +1509,45 @@ declare class FlowBuilder extends StepList {
|
|
|
1502
1509
|
* @throws Error when a manifest is not a node manifest, or two differ for one `nodeType@version`.
|
|
1503
1510
|
*/
|
|
1504
1511
|
definitions(manifests: readonly Record<string, unknown>[]): this;
|
|
1512
|
+
/**
|
|
1513
|
+
* Leave a path that runs out of steps open, instead of ending it on an End node.
|
|
1514
|
+
*
|
|
1515
|
+
* @remarks
|
|
1516
|
+
* By default compile caps every path that falls off the end of its
|
|
1517
|
+
* step list with a `core.control.end` node, and that End maps the flow's
|
|
1518
|
+
* outputs, so the run answers with them. The places this applies are the
|
|
1519
|
+
* flow's own body, a subflow's body, and an `.onError` / `.stepToList` body.
|
|
1520
|
+
*
|
|
1521
|
+
* `.openTails()` leaves such a path open: its last node simply has no outgoing edge.
|
|
1522
|
+
* It is the shape the classic CLI and the canvas write for a flow nobody gave
|
|
1523
|
+
* an End node, and `uip maestro flow validate` accepts it. `flow-decompile`
|
|
1524
|
+
* emits `.openTails()` for every file it decompiles (each End the file
|
|
1525
|
+
* has becomes an explicit `.return(...)`), so a no-edit decompile → compile →
|
|
1526
|
+
* merge does not add an End the author never drew.
|
|
1527
|
+
*
|
|
1528
|
+
* It changes only paths that fall off. `.return(...)`, `.terminate(...)`, a
|
|
1529
|
+
* `.stepSwitch` exit with no arm and a human-task outcome with
|
|
1530
|
+
* `action: 'End'` still emit their End. A human task that ends a path is
|
|
1531
|
+
* still capped with an End (the product's `hitl-completed` rule wants an edge
|
|
1532
|
+
* after it), so a file whose human task has no outgoing edge gains one on a
|
|
1533
|
+
* round trip. A path left open maps no outputs, so a flow that declares
|
|
1534
|
+
* `.output(...)` answers nothing on that path. Use `.return(...)` on the
|
|
1535
|
+
* paths that must answer.
|
|
1536
|
+
*
|
|
1537
|
+
* A subflow's child flow has its own setting; it does not inherit the
|
|
1538
|
+
* caller's.
|
|
1539
|
+
*
|
|
1540
|
+
* @example
|
|
1541
|
+
* **Keep a classic flow's open tail open**
|
|
1542
|
+
* ```ts
|
|
1543
|
+
* flow('notify')
|
|
1544
|
+
* .openTails()
|
|
1545
|
+
* .step('send', script({ code: 'return { sent: true };' }))
|
|
1546
|
+
* ```
|
|
1547
|
+
*
|
|
1548
|
+
* @returns This builder, so calls chain.
|
|
1549
|
+
*/
|
|
1550
|
+
openTails(): this;
|
|
1505
1551
|
/**
|
|
1506
1552
|
* Declare the flow's inputs. Read them with `input('<name>')`.
|
|
1507
1553
|
*
|
package/dist/flow-sdk.js
CHANGED
|
@@ -909,6 +909,7 @@ class FlowBuilder extends StepList {
|
|
|
909
909
|
_triggerOptions;
|
|
910
910
|
_entryPoints = [];
|
|
911
911
|
_triggerId;
|
|
912
|
+
_openTails = false;
|
|
912
913
|
constructor(_id) {
|
|
913
914
|
super();
|
|
914
915
|
this._id = _id;
|
|
@@ -1211,6 +1212,48 @@ class FlowBuilder extends StepList {
|
|
|
1211
1212
|
this._definitions = [...known.values()];
|
|
1212
1213
|
return this;
|
|
1213
1214
|
}
|
|
1215
|
+
/**
|
|
1216
|
+
* Leave a path that runs out of steps open, instead of ending it on an End node.
|
|
1217
|
+
*
|
|
1218
|
+
* @remarks
|
|
1219
|
+
* By default compile caps every path that falls off the end of its
|
|
1220
|
+
* step list with a `core.control.end` node, and that End maps the flow's
|
|
1221
|
+
* outputs, so the run answers with them. The places this applies are the
|
|
1222
|
+
* flow's own body, a subflow's body, and an `.onError` / `.stepToList` body.
|
|
1223
|
+
*
|
|
1224
|
+
* `.openTails()` leaves such a path open: its last node simply has no outgoing edge.
|
|
1225
|
+
* It is the shape the classic CLI and the canvas write for a flow nobody gave
|
|
1226
|
+
* an End node, and `uip maestro flow validate` accepts it. `flow-decompile`
|
|
1227
|
+
* emits `.openTails()` for every file it decompiles (each End the file
|
|
1228
|
+
* has becomes an explicit `.return(...)`), so a no-edit decompile → compile →
|
|
1229
|
+
* merge does not add an End the author never drew.
|
|
1230
|
+
*
|
|
1231
|
+
* It changes only paths that fall off. `.return(...)`, `.terminate(...)`, a
|
|
1232
|
+
* `.stepSwitch` exit with no arm and a human-task outcome with
|
|
1233
|
+
* `action: 'End'` still emit their End. A human task that ends a path is
|
|
1234
|
+
* still capped with an End (the product's `hitl-completed` rule wants an edge
|
|
1235
|
+
* after it), so a file whose human task has no outgoing edge gains one on a
|
|
1236
|
+
* round trip. A path left open maps no outputs, so a flow that declares
|
|
1237
|
+
* `.output(...)` answers nothing on that path. Use `.return(...)` on the
|
|
1238
|
+
* paths that must answer.
|
|
1239
|
+
*
|
|
1240
|
+
* A subflow's child flow has its own setting; it does not inherit the
|
|
1241
|
+
* caller's.
|
|
1242
|
+
*
|
|
1243
|
+
* @example
|
|
1244
|
+
* **Keep a classic flow's open tail open**
|
|
1245
|
+
* ```ts
|
|
1246
|
+
* flow('notify')
|
|
1247
|
+
* .openTails()
|
|
1248
|
+
* .step('send', script({ code: 'return { sent: true };' }))
|
|
1249
|
+
* ```
|
|
1250
|
+
*
|
|
1251
|
+
* @returns This builder, so calls chain.
|
|
1252
|
+
*/
|
|
1253
|
+
openTails() {
|
|
1254
|
+
this._openTails = true;
|
|
1255
|
+
return this;
|
|
1256
|
+
}
|
|
1214
1257
|
/**
|
|
1215
1258
|
* Declare the flow's inputs. Read them with `input('<name>')`.
|
|
1216
1259
|
*
|
|
@@ -1310,6 +1353,7 @@ class FlowBuilder extends StepList {
|
|
|
1310
1353
|
...(this._triggerOptions !== undefined ? { triggerOptions: this._triggerOptions } : {}),
|
|
1311
1354
|
...(this._entryPoints.length ? { entryPoints: this._entryPoints } : {}),
|
|
1312
1355
|
...(this._triggerId !== undefined ? { triggerId: this._triggerId } : {}),
|
|
1356
|
+
...(this._openTails ? { openTails: true } : {}),
|
|
1313
1357
|
};
|
|
1314
1358
|
// First-level validation, intrinsic to running the SDK: catch a definitely-
|
|
1315
1359
|
// broken expression HERE, before the model is serialized, rather than three
|
package/dist/merge-cli.d.ts
CHANGED
package/dist/merge-cli.js
CHANGED
|
@@ -3,7 +3,13 @@
|
|
|
3
3
|
* merge-cli — merge an edited flow back into the original `.flow` (bin `flow-merge`)
|
|
4
4
|
*
|
|
5
5
|
* Usage:
|
|
6
|
-
* flow-merge <original.flow> <edited.flow> [-o merged.flow]
|
|
6
|
+
* flow-merge <original.flow> <edited.flow | Edited.flow.ts> [-o merged.flow]
|
|
7
|
+
* [--baseline <baseline.flow> | --baseline-from <original.flow>] [--strict]
|
|
8
|
+
*
|
|
9
|
+
* `--baseline-from <original.flow>` makes merge build the baseline itself
|
|
10
|
+
* (decompile + compile, nothing written), and an edited `.flow.ts` makes merge
|
|
11
|
+
* compile it: both compiles tolerate DRAFT nodes, and merge refuses a draft
|
|
12
|
+
* only where it would take the node from the edited flow. See merge-compile.ts.
|
|
7
13
|
*
|
|
8
14
|
* `edited.flow` is compile(decompile(original) after your edits). `--baseline`
|
|
9
15
|
* is compile(decompile(original)) BEFORE any edit — supplying it enables the
|
|
@@ -19,27 +25,88 @@ import { readFileSync } from 'node:fs';
|
|
|
19
25
|
import { basename, resolve } from 'node:path';
|
|
20
26
|
import { MergeRefusedError, mergeFlow } from './merge.js';
|
|
21
27
|
import { flagValue, runWhenInvokedDirectly } from './cli-run.js';
|
|
22
|
-
|
|
28
|
+
import { ensureTypeScriptRuntime } from './node-runtime.js';
|
|
29
|
+
import { flowCheckOpts, openCliLibrary } from './cli-library.js';
|
|
30
|
+
import { Bindings } from './bindings.js';
|
|
31
|
+
import { defaultBindingsFile } from './workdir.js';
|
|
32
|
+
import { baselineFromOriginal, checkEdited, classifyDrafts, compileSourceDraftTolerant } from './merge-compile.js';
|
|
33
|
+
const USAGE = 'usage: flow-merge <original.flow> <edited.flow | Edited.flow.ts> [-o merged.flow] '
|
|
34
|
+
+ '[--baseline <baseline.flow> | --baseline-from <original.flow>] [--library <dir>] [--bindings <file>] [--strict]';
|
|
35
|
+
export async function run(argv) {
|
|
23
36
|
if (argv.length === 0 || argv[0] === '-h' || argv[0] === '--help') {
|
|
24
|
-
console.error(
|
|
37
|
+
console.error(USAGE);
|
|
25
38
|
return 2;
|
|
26
39
|
}
|
|
27
|
-
const flags = new Set(['-o', '--baseline']);
|
|
40
|
+
const flags = new Set(['-o', '--baseline', '--baseline-from', '--library', '--bindings', '--connectors-local']);
|
|
28
41
|
const positionals = argv.filter((a, i) => !flags.has(a) && !flags.has(argv[i - 1]) && !a.startsWith('-'));
|
|
29
42
|
const [originalPath, editedPath] = positionals;
|
|
30
43
|
if (!originalPath || !editedPath) {
|
|
31
44
|
console.error('flow-merge: need <original.flow> and <edited.flow>');
|
|
32
45
|
return 2;
|
|
33
46
|
}
|
|
34
|
-
const original = JSON.parse(readFileSync(originalPath, 'utf8'));
|
|
35
|
-
const edited = JSON.parse(readFileSync(editedPath, 'utf8'));
|
|
36
47
|
const baselinePath = flagValue(argv, '--baseline');
|
|
37
|
-
const
|
|
48
|
+
const baselineFrom = flagValue(argv, '--baseline-from');
|
|
49
|
+
if (baselinePath && baselineFrom) {
|
|
50
|
+
console.error('flow-merge: pass --baseline or --baseline-from, not both');
|
|
51
|
+
return 2;
|
|
52
|
+
}
|
|
53
|
+
const editedIsSource = /\.ts$/.test(editedPath);
|
|
54
|
+
// Merge compiles a side itself only for --baseline-from or a .flow.ts edited
|
|
55
|
+
// source; both load TypeScript, so both need the type-stripping runtime.
|
|
56
|
+
if (baselineFrom || editedIsSource)
|
|
57
|
+
ensureTypeScriptRuntime();
|
|
58
|
+
const library = baselineFrom || editedIsSource ? openCliLibrary(argv) : undefined;
|
|
59
|
+
const bindings = baselineFrom || editedIsSource ? new Bindings(flagValue(argv, '--bindings') ?? defaultBindingsFile()) : undefined;
|
|
60
|
+
const compileOpts = { library, bindings };
|
|
61
|
+
const original = JSON.parse(readFileSync(originalPath, 'utf8'));
|
|
62
|
+
let drafts = [];
|
|
63
|
+
let diagnostics = [];
|
|
64
|
+
let edited;
|
|
65
|
+
if (editedIsSource) {
|
|
66
|
+
// The edited source gets what `compile` gives it: check() with the same
|
|
67
|
+
// options, and the serializer's warnings (CONNECTION_STUB, ...) printed.
|
|
68
|
+
const compiled = await compileSourceDraftTolerant(resolve(editedPath), {
|
|
69
|
+
...compileOpts,
|
|
70
|
+
warn: (w) => console.error(` ⚠ [${w.code}] ${w.message}`),
|
|
71
|
+
});
|
|
72
|
+
edited = compiled.flow;
|
|
73
|
+
drafts = compiled.drafts;
|
|
74
|
+
diagnostics = checkEdited(compiled.built, edited, flowCheckOpts(library, bindings));
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
edited = JSON.parse(readFileSync(editedPath, 'utf8'));
|
|
78
|
+
}
|
|
79
|
+
const baseline = baselineFrom
|
|
80
|
+
? (await baselineFromOriginal(baselineFrom, compileOpts, (m) => console.error(`flow-merge: decompile warning: ${m}`))).flow
|
|
81
|
+
: baselinePath ? JSON.parse(readFileSync(baselinePath, 'utf8')) : undefined;
|
|
38
82
|
const strict = argv.includes('--strict');
|
|
39
83
|
if (strict && !baseline) {
|
|
40
|
-
console.error('flow-merge: --strict compares the no-edit round trip with the original; pass --baseline <baseline.flow>');
|
|
84
|
+
console.error('flow-merge: --strict compares the no-edit round trip with the original; pass --baseline <baseline.flow> or --baseline-from <original.flow>');
|
|
41
85
|
return 2;
|
|
42
86
|
}
|
|
87
|
+
// A draft node (no connection, an empty required input, no object) is
|
|
88
|
+
// acceptable only where merge restores the ORIGINAL node; one the author
|
|
89
|
+
// changed or added gets the strict compile's refusal (#1134).
|
|
90
|
+
// check()'s errors follow the same rule; its warnings are printed as compile prints them.
|
|
91
|
+
const { kept, refused } = classifyDrafts(original, edited, baseline, drafts);
|
|
92
|
+
const checked = classifyDrafts(original, edited, baseline, diagnostics.filter((d) => d.level === 'error'));
|
|
93
|
+
for (const d of diagnostics)
|
|
94
|
+
if (d.level === 'warning')
|
|
95
|
+
console.error(` ⚠ [${d.code}] ${d.message}`);
|
|
96
|
+
for (const d of [...kept, ...checked.kept]) {
|
|
97
|
+
console.error(` ⚠ [DRAFT_NODE_KEPT] "${d.nodeId}" is unfinished in the original (${d.code}); it is untouched, so the original node is kept as is.`);
|
|
98
|
+
}
|
|
99
|
+
const errors = [...refused, ...checked.refused];
|
|
100
|
+
if (errors.length) {
|
|
101
|
+
for (const d of errors) {
|
|
102
|
+
const where = d.nodeId === '' ? 'the edited flow'
|
|
103
|
+
: d.reason === 'subflow' ? `"${d.nodeId}" is inside a subflow, which merge takes whole; finish it`
|
|
104
|
+
: `"${d.nodeId}" is changed or new in the edited flow`;
|
|
105
|
+
console.error(` ✗ [${d.code}] ${where}: ${d.message}`);
|
|
106
|
+
}
|
|
107
|
+
console.error(`flow-merge: ${errors.length} error(s) in nodes merge takes from the edited flow; finish them or revert the edit. Nothing written.`);
|
|
108
|
+
return 1;
|
|
109
|
+
}
|
|
43
110
|
let merged;
|
|
44
111
|
try {
|
|
45
112
|
merged = mergeFlow(original, edited, {
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type DraftFinding, type SerializeOpts } from './serialize.js';
|
|
2
|
+
import { type CheckOpts, type Diagnostic } from './check.js';
|
|
3
|
+
import type { BuiltFlow } from './flow-sdk.js';
|
|
4
|
+
/** A compile's flow and the draft refusals it reported instead of throwing. */
|
|
5
|
+
export interface DraftTolerantCompile {
|
|
6
|
+
flow: any;
|
|
7
|
+
drafts: DraftFinding[];
|
|
8
|
+
}
|
|
9
|
+
/** Compile `built` with draft tolerance. Every other refusal still throws. */
|
|
10
|
+
export declare function compileDraftTolerant(built: BuiltFlow, opts?: Omit<SerializeOpts, 'draft'>): DraftTolerantCompile;
|
|
11
|
+
/**
|
|
12
|
+
* Load a `.flow.ts` source and compile it with draft tolerance.
|
|
13
|
+
* The caller has already called `ensureTypeScriptRuntime()`.
|
|
14
|
+
*/
|
|
15
|
+
export declare function compileSourceDraftTolerant(file: string, opts?: Omit<SerializeOpts, 'draft'>): Promise<DraftTolerantCompile & {
|
|
16
|
+
built: BuiltFlow;
|
|
17
|
+
}>;
|
|
18
|
+
/**
|
|
19
|
+
* The baseline of `originalPath`: decompile it (reading agent sidecars beside
|
|
20
|
+
* it, as `flow decompile` does), then compile the source with draft tolerance.
|
|
21
|
+
* The source goes to a temporary directory that is removed afterwards.
|
|
22
|
+
*/
|
|
23
|
+
export declare function baselineFromOriginal(originalPath: string, opts?: Omit<SerializeOpts, 'draft'>, warn?: (message: string) => void): Promise<DraftTolerantCompile>;
|
|
24
|
+
/** Why merge takes a node from the edited flow, so a finding on it is an error. */
|
|
25
|
+
export type TakenReason = 'edited' | 'subflow';
|
|
26
|
+
/** A finding on a node merge takes from the edited flow, with the reason it takes it. */
|
|
27
|
+
export type Refused<T> = T & {
|
|
28
|
+
reason: TakenReason;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Sort each finding by what merge does with its node: `refused` when the node
|
|
32
|
+
* comes from the edited flow (reason `edited`: the author changed or added it;
|
|
33
|
+
* reason `subflow`: it sits in a subflow, which merge takes from `edited`
|
|
34
|
+
* whole), `kept` when merge restores the original node.
|
|
35
|
+
*
|
|
36
|
+
* For instance a Slack node with no connection that the author did not touch
|
|
37
|
+
* is `kept`; the same node with a new message text is `refused` as `edited`.
|
|
38
|
+
*/
|
|
39
|
+
export declare function classifyDrafts<T extends {
|
|
40
|
+
nodeId: string;
|
|
41
|
+
}>(original: any, edited: any, baseline: any, findings: readonly T[]): {
|
|
42
|
+
kept: T[];
|
|
43
|
+
refused: Refused<T>[];
|
|
44
|
+
};
|
|
45
|
+
/** A `check()` diagnostic, placed on the root node its step emitted (`''` when it names no root step). */
|
|
46
|
+
export type PlacedDiagnostic = Diagnostic & {
|
|
47
|
+
nodeId: string;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Run `check()` on the edited source, as `compile` does, and place each
|
|
51
|
+
* diagnostic on the node its step emitted in `editedFlow`, so
|
|
52
|
+
* {@link classifyDrafts} can sort it. A diagnostic with no step, or a step
|
|
53
|
+
* with no root node, gets nodeId `''`, which is always refused.
|
|
54
|
+
*/
|
|
55
|
+
export declare function checkEdited(built: BuiltFlow, editedFlow: any, opts: CheckOpts): PlacedDiagnostic[];
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* merge-compile — the compiles `flow merge --baseline-from` runs itself (#1134).
|
|
3
|
+
*
|
|
4
|
+
* Both compiles tolerate draft nodes (`SerializeOpts.draft`). A draft on a node
|
|
5
|
+
* merge keeps from the original is a warning; a draft or `check()` error on a
|
|
6
|
+
* node merge takes from the edited flow is an error. Nothing draft-tolerant is
|
|
7
|
+
* written to disk.
|
|
8
|
+
*/
|
|
9
|
+
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
10
|
+
import { tmpdir } from 'node:os';
|
|
11
|
+
import { dirname, join, resolve } from 'node:path';
|
|
12
|
+
import { decompile } from './decompile.js';
|
|
13
|
+
import { loadBuiltFlow } from './load.js';
|
|
14
|
+
import { serialize } from './serialize.js';
|
|
15
|
+
import { check } from './check.js';
|
|
16
|
+
import { nodesTakenFromEdited } from './merge.js';
|
|
17
|
+
import { PACKAGE_NAME } from './package-name.js';
|
|
18
|
+
/** Compile `built` with draft tolerance. Every other refusal still throws. */
|
|
19
|
+
export function compileDraftTolerant(built, opts = {}) {
|
|
20
|
+
const drafts = [];
|
|
21
|
+
const flow = serialize(built, { ...opts, draft: (f) => drafts.push(f) });
|
|
22
|
+
return { flow, drafts };
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Load a `.flow.ts` source and compile it with draft tolerance.
|
|
26
|
+
* The caller has already called `ensureTypeScriptRuntime()`.
|
|
27
|
+
*/
|
|
28
|
+
export async function compileSourceDraftTolerant(file, opts = {}) {
|
|
29
|
+
const built = await loadBuiltFlow(file);
|
|
30
|
+
return { ...compileDraftTolerant(built, opts), built };
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The baseline of `originalPath`: decompile it (reading agent sidecars beside
|
|
34
|
+
* it, as `flow decompile` does), then compile the source with draft tolerance.
|
|
35
|
+
* The source goes to a temporary directory that is removed afterwards.
|
|
36
|
+
*/
|
|
37
|
+
export async function baselineFromOriginal(originalPath, opts = {}, warn) {
|
|
38
|
+
const original = JSON.parse(readFileSync(originalPath, 'utf8'));
|
|
39
|
+
const source = decompile(original, {
|
|
40
|
+
importSpecifier: PACKAGE_NAME,
|
|
41
|
+
warn,
|
|
42
|
+
readSidecar: (relativePath) => {
|
|
43
|
+
try {
|
|
44
|
+
return readFileSync(join(dirname(resolve(originalPath)), relativePath), 'utf8');
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
const dir = mkdtempSync(join(tmpdir(), 'flow-merge-baseline-'));
|
|
52
|
+
try {
|
|
53
|
+
writeFileSync(join(dir, 'package.json'), '{"type":"module"}\n');
|
|
54
|
+
const file = join(dir, 'Baseline.flow.ts');
|
|
55
|
+
writeFileSync(file, source);
|
|
56
|
+
return await compileSourceDraftTolerant(file, opts);
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
rmSync(dir, { recursive: true, force: true });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Sort each finding by what merge does with its node: `refused` when the node
|
|
64
|
+
* comes from the edited flow (reason `edited`: the author changed or added it;
|
|
65
|
+
* reason `subflow`: it sits in a subflow, which merge takes from `edited`
|
|
66
|
+
* whole), `kept` when merge restores the original node.
|
|
67
|
+
*
|
|
68
|
+
* For instance a Slack node with no connection that the author did not touch
|
|
69
|
+
* is `kept`; the same node with a new message text is `refused` as `edited`.
|
|
70
|
+
*/
|
|
71
|
+
export function classifyDrafts(original, edited, baseline, findings) {
|
|
72
|
+
const fromEdited = new Set(nodesTakenFromEdited(original, edited, baseline));
|
|
73
|
+
const rootIds = new Set((edited?.nodes ?? []).map((n) => n.id));
|
|
74
|
+
const kept = [];
|
|
75
|
+
const refused = [];
|
|
76
|
+
for (const f of findings) {
|
|
77
|
+
if (!rootIds.has(f.nodeId))
|
|
78
|
+
refused.push({ ...f, reason: 'subflow' });
|
|
79
|
+
else if (fromEdited.has(f.nodeId))
|
|
80
|
+
refused.push({ ...f, reason: 'edited' });
|
|
81
|
+
else
|
|
82
|
+
kept.push(f);
|
|
83
|
+
}
|
|
84
|
+
return { kept, refused };
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Run `check()` on the edited source, as `compile` does, and place each
|
|
88
|
+
* diagnostic on the node its step emitted in `editedFlow`, so
|
|
89
|
+
* {@link classifyDrafts} can sort it. A diagnostic with no step, or a step
|
|
90
|
+
* with no root node, gets nodeId `''`, which is always refused.
|
|
91
|
+
*/
|
|
92
|
+
export function checkEdited(built, editedFlow, opts) {
|
|
93
|
+
const byStep = new Map();
|
|
94
|
+
for (const n of editedFlow?.nodes ?? []) {
|
|
95
|
+
const label = n?.display?.label;
|
|
96
|
+
if (typeof label === 'string' && !byStep.has(label))
|
|
97
|
+
byStep.set(label, n.id);
|
|
98
|
+
}
|
|
99
|
+
const ids = new Set((editedFlow?.nodes ?? []).map((n) => n.id));
|
|
100
|
+
return check(built, opts).map((d) => ({
|
|
101
|
+
...d,
|
|
102
|
+
nodeId: d.step === undefined ? '' : byStep.get(d.step) ?? (ids.has(d.step) ? d.step : ''),
|
|
103
|
+
}));
|
|
104
|
+
}
|
package/dist/merge.d.ts
CHANGED
|
@@ -152,4 +152,13 @@ export interface MergeOptions {
|
|
|
152
152
|
*/
|
|
153
153
|
strict?: boolean;
|
|
154
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* The ids of the root nodes {@link mergeFlow} takes from `edited` rather than
|
|
157
|
+
* restoring from `original`: every node that is new, or that differs from its
|
|
158
|
+
* `baseline` counterpart. With no baseline, that is every node.
|
|
159
|
+
*
|
|
160
|
+
* For instance, with a baseline equal to `edited` and every node present in
|
|
161
|
+
* `original`, the answer is `[]` — a no-edit merge keeps them all.
|
|
162
|
+
*/
|
|
163
|
+
export declare function nodesTakenFromEdited(original: AnyFlow, edited: AnyFlow, baseline?: AnyFlow): string[];
|
|
155
164
|
export declare function mergeFlow(original: AnyFlow, edited: AnyFlow, options?: MergeOptions): AnyFlow;
|
package/dist/merge.js
CHANGED
|
@@ -97,6 +97,27 @@ function nodeUnchanged(a, b) {
|
|
|
97
97
|
return false;
|
|
98
98
|
return JSON.stringify(a.inputs ?? {}) === JSON.stringify(b.inputs ?? {});
|
|
99
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* The ids of the root nodes {@link mergeFlow} takes from `edited` rather than
|
|
102
|
+
* restoring from `original`: every node that is new, or that differs from its
|
|
103
|
+
* `baseline` counterpart. With no baseline, that is every node.
|
|
104
|
+
*
|
|
105
|
+
* For instance, with a baseline equal to `edited` and every node present in
|
|
106
|
+
* `original`, the answer is `[]` — a no-edit merge keeps them all.
|
|
107
|
+
*/
|
|
108
|
+
export function nodesTakenFromEdited(original, edited, baseline) {
|
|
109
|
+
const origNodes = byId(original.nodes);
|
|
110
|
+
const baseNodes = byId(baseline?.nodes);
|
|
111
|
+
return (edited.nodes ?? []).filter((e) => !isKept(e, origNodes, baseNodes, baseline)).map((e) => e.id);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Whether merge restores `e`'s ORIGINAL node instead of taking `e`: there is a
|
|
115
|
+
* baseline, the original has the node, and `e` equals its baseline counterpart.
|
|
116
|
+
* {@link mergeFlow}'s node loop and {@link nodesTakenFromEdited} both ask this.
|
|
117
|
+
*/
|
|
118
|
+
function isKept(e, origNodes, baseNodes, baseline) {
|
|
119
|
+
return !!baseline && origNodes.has(e.id) && nodeUnchanged(e, baseNodes.get(e.id));
|
|
120
|
+
}
|
|
100
121
|
/**
|
|
101
122
|
* Give an edited node the original's position, by id.
|
|
102
123
|
*
|
|
@@ -132,7 +153,7 @@ export function mergeFlow(original, edited, options = {}) {
|
|
|
132
153
|
const finalNodes = [];
|
|
133
154
|
for (const e of edited.nodes ?? []) {
|
|
134
155
|
const orig = origNodes.get(e.id);
|
|
135
|
-
if (options.baseline && orig
|
|
156
|
+
if (isKept(e, origNodes, baseNodes, options.baseline) && orig) {
|
|
136
157
|
// Untouched by the user (equal to the faithful baseline) → keep the
|
|
137
158
|
// original node exactly, placeholder-safe.
|
|
138
159
|
finalNodes.push(jsonClone(orig));
|
|
@@ -518,6 +518,7 @@ function hitlAt(typeName, version, factory) {
|
|
|
518
518
|
return {
|
|
519
519
|
kind: 'hitl', typeName, version, factory: 'hitl', definition: 'bundled',
|
|
520
520
|
rawNode: { factory },
|
|
521
|
+
capsOpenTail: true,
|
|
521
522
|
serialize: ({ inputs }, ctx) => {
|
|
522
523
|
// How the task leaves its node — `hitlExitModel` (core/hitl-routing.ts)
|
|
523
524
|
// has the product rule and what `.step()` means after each shape. An
|
package/dist/serialize.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { DefinitionReference } from './core/node-classes.js';
|
|
2
2
|
import type { BuiltFlow } from './flow-sdk.js';
|
|
3
3
|
import type { Library } from './library.js';
|
|
4
|
+
import { type BindingRefusalCode } from './core/binding-messages.js';
|
|
4
5
|
import type { Bindings } from './bindings.js';
|
|
5
6
|
import { connectorInputErrors as coreConnectorInputErrors } from './core/connector-inputs.js';
|
|
6
7
|
/**
|
|
@@ -47,6 +48,18 @@ export interface SerializeWarning {
|
|
|
47
48
|
code: string;
|
|
48
49
|
message: string;
|
|
49
50
|
}
|
|
51
|
+
/** A required connector input left empty — the one draft code with no error class of its own. */
|
|
52
|
+
export declare const CONNECTOR_INPUT_MISSING = "CONNECTOR_INPUT_MISSING";
|
|
53
|
+
/** The refusals a draft-tolerant compile reports instead of throwing. */
|
|
54
|
+
export type DraftCode = BindingRefusalCode | typeof CONNECTOR_INPUT_MISSING | 'CONNECTOR_OBJECT_REQUIRED';
|
|
55
|
+
/** A refusal a draft-tolerant compile reported instead of throwing (see {@link SerializeOpts.draft}). */
|
|
56
|
+
export interface DraftFinding {
|
|
57
|
+
/** The emitted node's id. */
|
|
58
|
+
nodeId: string;
|
|
59
|
+
code: DraftCode;
|
|
60
|
+
/** The sentence the strict compile refuses with. */
|
|
61
|
+
message: string;
|
|
62
|
+
}
|
|
50
63
|
export interface SerializeOpts {
|
|
51
64
|
library?: Library;
|
|
52
65
|
bindings?: Bindings;
|
|
@@ -56,6 +69,19 @@ export interface SerializeOpts {
|
|
|
56
69
|
* hears nothing, which keeps `serialize()` silent in tests and libraries.
|
|
57
70
|
*/
|
|
58
71
|
warn?: (warning: SerializeWarning) => void;
|
|
72
|
+
/**
|
|
73
|
+
* Draft tolerance, for a compile whose output only `merge` reads (#1134).
|
|
74
|
+
*
|
|
75
|
+
* A canvas flow often holds DRAFT nodes — a connector with no connection, an
|
|
76
|
+
* empty required input, a generic operation with no object — which the
|
|
77
|
+
* canvas saves and compile refuses. In a brownfield merge an untouched node
|
|
78
|
+
* is restored from the original anyway, so refusing it only blocks the edit.
|
|
79
|
+
* When this callback is given, those three refusals are reported here, with
|
|
80
|
+
* the node's id, and the node is emitted with what it has; `merge` then
|
|
81
|
+
* refuses any such node it would take from the edited flow. Absent (every
|
|
82
|
+
* ordinary compile), behaviour is unchanged.
|
|
83
|
+
*/
|
|
84
|
+
draft?: (finding: DraftFinding) => void;
|
|
59
85
|
/**
|
|
60
86
|
* Filled in by `serialize` with the extra files the flow needs beside the
|
|
61
87
|
* `.flow`, relative to it: one `<source>/agent.json` per inline agent, plus a
|
package/dist/serialize.js
CHANGED
|
@@ -20,6 +20,7 @@ import { stepExits } from './flow-step-exits.js';
|
|
|
20
20
|
import { resolveVersionCarried } from './core/nodes/versioned.js';
|
|
21
21
|
import { indexCarriedDefinitions } from './core/carried-definitions.js';
|
|
22
22
|
import { FORM_FIELD_JSON_TYPE } from './core/form-field-type.js';
|
|
23
|
+
import { ConnectorResolveError } from './core/library.js';
|
|
23
24
|
import { connectionConnectors } from './bindings-v2.js';
|
|
24
25
|
import { BindingRefusal, GUID_RE, bindingLabelRefusal, bindingMissingMessage, missingBindingLabels } from './core/binding-messages.js';
|
|
25
26
|
import { ByoaRefusal, byoaUnverified } from './core/byoa.js';
|
|
@@ -2999,6 +3000,8 @@ function scheduleInputs(inputs, nodeId) {
|
|
|
2999
3000
|
function outcomeId(name, index) {
|
|
3000
3001
|
return outcomeSlug(name, index);
|
|
3001
3002
|
}
|
|
3003
|
+
/** A required connector input left empty — the one draft code with no error class of its own. */
|
|
3004
|
+
export const CONNECTOR_INPUT_MISSING = 'CONNECTOR_INPUT_MISSING';
|
|
3002
3005
|
/**
|
|
3003
3006
|
* `serialize`, plus the extra files the flow needs on disk beside it.
|
|
3004
3007
|
*
|
|
@@ -3890,6 +3893,7 @@ function newScope(outputs, vars = [], backing = new Map(), backingReads = backin
|
|
|
3890
3893
|
agentSchemas: [],
|
|
3891
3894
|
stepNodeId: new Map(),
|
|
3892
3895
|
pendingEdges: [],
|
|
3896
|
+
openTails: false,
|
|
3893
3897
|
};
|
|
3894
3898
|
}
|
|
3895
3899
|
/**
|
|
@@ -4366,6 +4370,7 @@ export function serialize(built, opts = {}) {
|
|
|
4366
4370
|
const subflows = {};
|
|
4367
4371
|
const rootGlobals = emittableGlobals(built, `flow "${built.id}"`);
|
|
4368
4372
|
const root = newScope(rootGlobals.outputs, rootGlobals.vars, rootGlobals.backing, rootGlobals.backingReads);
|
|
4373
|
+
root.openTails = built.openTails === true;
|
|
4369
4374
|
// `input('x')` lowers eagerly to `$vars.start.output.x` — `start` being the
|
|
4370
4375
|
// trigger node's default id. When the flow renames the trigger, register that
|
|
4371
4376
|
// rename so the SAME pass that rewrites step-name references rewrites these
|
|
@@ -4529,6 +4534,21 @@ export function serialize(built, opts = {}) {
|
|
|
4529
4534
|
addEdge(scope, t, id);
|
|
4530
4535
|
return node;
|
|
4531
4536
|
}
|
|
4537
|
+
/** Node ids whose type sets `capsOpenTail` (see {@link tailsToCap}). */
|
|
4538
|
+
const capsOpenTail = new Set();
|
|
4539
|
+
/**
|
|
4540
|
+
* The tails of a path that ran out of steps which still need an End node.
|
|
4541
|
+
*
|
|
4542
|
+
* All of them by default. Under `.openTails()` (#1142) only the tails
|
|
4543
|
+
* of a node whose type sets `capsOpenTail` (a human task: the product's
|
|
4544
|
+
* `hitl-completed` rule wants an edge after it). Every other tail is left
|
|
4545
|
+
* open, which is the shape the classic CLI and the canvas write.
|
|
4546
|
+
*/
|
|
4547
|
+
function tailsToCap(scope, tails) {
|
|
4548
|
+
if (!scope.openTails)
|
|
4549
|
+
return [...tails];
|
|
4550
|
+
return tails.filter((t) => capsOpenTail.has(t.node));
|
|
4551
|
+
}
|
|
4532
4552
|
/**
|
|
4533
4553
|
* Emit a child flow into its own scope and register it under the calling
|
|
4534
4554
|
* node's id — that key is how the format names a subflow body, and how
|
|
@@ -4556,6 +4576,7 @@ export function serialize(built, opts = {}) {
|
|
|
4556
4576
|
function emitSubflowBodyIn(child, nodeId) {
|
|
4557
4577
|
const childGlobals = emittableGlobals(child, `subflow "${nodeId}"`, 'subflow');
|
|
4558
4578
|
const scope = newScope(childGlobals.outputs, childGlobals.vars, childGlobals.backing, childGlobals.backingReads);
|
|
4579
|
+
scope.openTails = child.openTails === true;
|
|
4559
4580
|
// Claim this copy's node ids UP FRONT, so the rename map is complete before
|
|
4560
4581
|
// the first expression renders. A child's step names are free the first
|
|
4561
4582
|
// time it runs; if any of them is already taken — which is what a second
|
|
@@ -4586,8 +4607,9 @@ export function serialize(built, opts = {}) {
|
|
|
4586
4607
|
const tails = emit(child.steps, [{ node: startId, port: 'output' }], scope);
|
|
4587
4608
|
// Same as the root's implicit End — mapped against the SUBFLOW's own
|
|
4588
4609
|
// outputs, which is the scope the product validates a subflow body in.
|
|
4589
|
-
|
|
4590
|
-
|
|
4610
|
+
const capped = tailsToCap(scope, tails);
|
|
4611
|
+
if (capped.length)
|
|
4612
|
+
emitEnd(scope, uid(scope, 'end'), capped);
|
|
4591
4613
|
const globals = [];
|
|
4592
4614
|
for (const inp of child.inputs)
|
|
4593
4615
|
globals.push({ id: inp.name, name: inp.name, direction: 'in', type: inp.type, triggerNodeId: startId, ...varMeta(inp) });
|
|
@@ -4835,6 +4857,8 @@ export function serialize(built, opts = {}) {
|
|
|
4835
4857
|
const impl = resolved.impl;
|
|
4836
4858
|
const version = resolved.version;
|
|
4837
4859
|
const id = stepUid(scope, step.name);
|
|
4860
|
+
if (impl.capsOpenTail)
|
|
4861
|
+
capsOpenTail.add(id);
|
|
4838
4862
|
// As for every typed family: record the failure-envelope boundary before any
|
|
4839
4863
|
// expression renders, so a handler reading this step resolves correctly.
|
|
4840
4864
|
if (impl.errorEnvelope)
|
|
@@ -4958,20 +4982,67 @@ export function serialize(built, opts = {}) {
|
|
|
4958
4982
|
if (spec.kind === 'connector') {
|
|
4959
4983
|
if (!opts.library)
|
|
4960
4984
|
throw new Error(`connector "${step.name}" needs a library (pass --library / set $FLOW_SDK_LIBRARY_JSON).`);
|
|
4961
|
-
|
|
4985
|
+
let rc;
|
|
4986
|
+
try {
|
|
4987
|
+
rc = opts.library.resolve(spec.key, spec.action, spec.version, spec.object);
|
|
4988
|
+
}
|
|
4989
|
+
catch (error) {
|
|
4990
|
+
if (!opts.draft || !(error instanceof ConnectorResolveError) || error.code !== 'CONNECTOR_OBJECT_REQUIRED')
|
|
4991
|
+
throw error;
|
|
4992
|
+
// A generic operation saved before its object was picked has no
|
|
4993
|
+
// definition to emit against. Draft tolerance emits a stable stand-in
|
|
4994
|
+
// under the node's id; merge restores the original when it is untouched
|
|
4995
|
+
// and refuses it otherwise.
|
|
4996
|
+
const id = stepUid(scope, step.name);
|
|
4997
|
+
opts.draft({ nodeId: id, code: error.code, message: error.message });
|
|
4998
|
+
// It leaves on the port every connector action leaves on, so the
|
|
4999
|
+
// no-edit round trip rewires nothing. Its inputs carry what the author
|
|
5000
|
+
// wrote, so an edit to the node (an input, a connection) shows up as a
|
|
5001
|
+
// change and merge refuses it instead of restoring the original.
|
|
5002
|
+
const type = `uipath.connector.${spec.key}.${spec.action}`;
|
|
5003
|
+
scope.nodes.push({
|
|
5004
|
+
id, type, typeVersion: spec.version ?? '1.0.0',
|
|
5005
|
+
...(parentId ? { parentId } : {}), display: { label: step.name },
|
|
5006
|
+
inputs: {
|
|
5007
|
+
draft: true,
|
|
5008
|
+
spec: renderDeep(spec.inputs ?? {}, scope.rename),
|
|
5009
|
+
...(spec.connection !== undefined ? { connection: spec.connection } : {}),
|
|
5010
|
+
...(spec.folder !== undefined ? { folder: spec.folder } : {}),
|
|
5011
|
+
},
|
|
5012
|
+
});
|
|
5013
|
+
for (const t of tails)
|
|
5014
|
+
addEdge(scope, t, id);
|
|
5015
|
+
return [{ node: id, port: successPort(type) }];
|
|
5016
|
+
}
|
|
4962
5017
|
const id = stepUid(scope, step.name);
|
|
4963
5018
|
const node = makeNode(rc.nodeType, id, step.name, { parentId, requestedVersion: step.options?.version, def: rc.v1def });
|
|
4964
5019
|
declareListOutputType(node, rc);
|
|
4965
|
-
|
|
5020
|
+
// A draft that names no connection gets no binding rows either: there
|
|
5021
|
+
// is nothing to bind, and rows with an empty resourceKey would leak into
|
|
5022
|
+
// the merged file through merge's bindings union.
|
|
5023
|
+
let unbound = false;
|
|
5024
|
+
try {
|
|
5025
|
+
requireBindingPair(`connector "${step.name}"`, spec, { key: spec.key, action: spec.action });
|
|
5026
|
+
}
|
|
5027
|
+
catch (error) {
|
|
5028
|
+
if (!opts.draft || !(error instanceof BindingRefusal))
|
|
5029
|
+
throw error;
|
|
5030
|
+
opts.draft({ nodeId: id, code: error.code, message: error.message });
|
|
5031
|
+
unbound = true;
|
|
5032
|
+
}
|
|
4966
5033
|
const conn = resolveBinding(opts, spec.connection, 'connection', `connector "${step.name}"`, { key: spec.key, action: spec.action });
|
|
4967
5034
|
const folder = resolveBinding(opts, spec.folder, 'folder', `connector "${step.name}"`, { key: spec.key, action: spec.action });
|
|
4968
5035
|
// The platform reaches the connection through the flow's `bindings[]`,
|
|
4969
5036
|
// never through `inputs.detail` — without this pair the run faults with
|
|
4970
5037
|
// `[102010]` (board G-19; see connectionResourceBindings).
|
|
4971
5038
|
const { entries: connBindings } = connectionResourceBindings({ def: rc.v1def, connectorKey: rc.connectorKey, connectionId: conn, folderKey: folder }, resourceBindings);
|
|
4972
|
-
|
|
4973
|
-
|
|
5039
|
+
if (!unbound)
|
|
5040
|
+
for (const b of connBindings)
|
|
5041
|
+
resourceBindings.set(b.id, b);
|
|
4974
5042
|
const connectorInputs = buildConnectorInputs(rc, spec.inputs, {
|
|
5043
|
+
...(opts.draft
|
|
5044
|
+
? { onMissingRequired: (m) => opts.draft({ nodeId: id, code: CONNECTOR_INPUT_MISSING, message: `connector ${rc.nodeType}: ${m}` }) }
|
|
5045
|
+
: {}),
|
|
4975
5046
|
dialect: FLOW_EXPR_DIALECT,
|
|
4976
5047
|
render: (value) => renderDeep(value, scope.rename),
|
|
4977
5048
|
resolutions: opts.library.lookupResolutions ?? {},
|
|
@@ -5967,9 +6038,10 @@ export function serialize(built, opts = {}) {
|
|
|
5967
6038
|
// A body that runs out of steps ends the run on an End of its own (no
|
|
5968
6039
|
// merge-back is inferred). That End maps the outputs like any other, so a
|
|
5969
6040
|
// body that set them with `{ updates }` still answers (#742).
|
|
5970
|
-
|
|
6041
|
+
const capped = tailsToCap(scope, handlerTails);
|
|
6042
|
+
if (capped.length) {
|
|
5971
6043
|
const endId = uid(scope, `${source}${step.port === 'error' ? 'Error' : step.port.charAt(0).toUpperCase() + step.port.slice(1)}End`);
|
|
5972
|
-
emitEnd(scope, endId,
|
|
6044
|
+
emitEnd(scope, endId, capped, { parentId });
|
|
5973
6045
|
}
|
|
5974
6046
|
return router !== undefined ? [] : tails;
|
|
5975
6047
|
}
|
|
@@ -6435,8 +6507,10 @@ export function serialize(built, opts = {}) {
|
|
|
6435
6507
|
// The implicit End a flow falls off the bottom into still terminates the
|
|
6436
6508
|
// flow, so it maps the flow's outputs — each to itself, since no `.return`
|
|
6437
6509
|
// named a value here.
|
|
6438
|
-
|
|
6439
|
-
|
|
6510
|
+
// `.openTails()` leaves those tails open instead (#1142).
|
|
6511
|
+
const finalCapped = tailsToCap(root, finalTails);
|
|
6512
|
+
if (finalCapped.length)
|
|
6513
|
+
emitEnd(root, uid(root, 'end'), finalCapped);
|
|
6440
6514
|
// ── Additional entry points (design §5.1) ────────────────────────────────
|
|
6441
6515
|
// Emitted AFTER the shared body so their prefixes can join it by name. Once a
|
|
6442
6516
|
// flow has more than one root, every root carries the platform's entry-point
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/maestro-builder-sdk",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.29.0",
|
|
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": "
|
|
95
|
+
"gitref": "af71b0c21f732f056d19e802af1c987fd8528336"
|
|
96
96
|
}
|