@uipath/maestro-builder-sdk 5.2.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/LICENSE +21 -0
- package/README.md +322 -0
- package/dist/bindings-v2.d.ts +37 -0
- package/dist/bindings-v2.js +155 -0
- package/dist/bindings.d.ts +6 -0
- package/dist/bindings.js +6 -0
- package/dist/bpmn/bpmn-expr-check.d.ts +41 -0
- package/dist/bpmn/bpmn-expr-check.js +218 -0
- package/dist/bpmn/bpmn-sdk.d.ts +2257 -0
- package/dist/bpmn/bpmn-sdk.js +1476 -0
- package/dist/bpmn/check-cli.d.ts +3 -0
- package/dist/bpmn/check-cli.js +32 -0
- package/dist/bpmn/check.d.ts +25 -0
- package/dist/bpmn/check.js +430 -0
- package/dist/bpmn/compile-cli.d.ts +3 -0
- package/dist/bpmn/compile-cli.js +60 -0
- package/dist/bpmn/connector.d.ts +56 -0
- package/dist/bpmn/connector.js +199 -0
- package/dist/bpmn/decompile-cli.d.ts +8 -0
- package/dist/bpmn/decompile-cli.js +54 -0
- package/dist/bpmn/decompile.d.ts +6 -0
- package/dist/bpmn/decompile.js +1108 -0
- package/dist/bpmn/format-profile.d.ts +27 -0
- package/dist/bpmn/format-profile.js +11 -0
- package/dist/bpmn/intsvc.d.ts +77 -0
- package/dist/bpmn/intsvc.js +155 -0
- package/dist/bpmn/load.d.ts +4 -0
- package/dist/bpmn/load.js +22 -0
- package/dist/bpmn/merge-cli.d.ts +3 -0
- package/dist/bpmn/merge-cli.js +45 -0
- package/dist/bpmn/merge.d.ts +19 -0
- package/dist/bpmn/merge.js +293 -0
- package/dist/bpmn/registry-types.json +1869 -0
- package/dist/bpmn/serialize.d.ts +28 -0
- package/dist/bpmn/serialize.js +757 -0
- package/dist/bpmn/tidy-cli.d.ts +2 -0
- package/dist/bpmn/tidy-cli.js +39 -0
- package/dist/bpmn/typed-node.d.ts +382 -0
- package/dist/bpmn/typed-node.js +551 -0
- package/dist/bpmn/uipath-moddle.v1.json +823 -0
- package/dist/bpmn/xml-ranges.d.ts +45 -0
- package/dist/bpmn/xml-ranges.js +151 -0
- package/dist/case/case-expr-check.d.ts +35 -0
- package/dist/case/case-expr-check.js +85 -0
- package/dist/case/case-sdk.d.ts +1282 -0
- package/dist/case/case-sdk.js +923 -0
- package/dist/case/check-cli.d.ts +3 -0
- package/dist/case/check-cli.js +31 -0
- package/dist/case/check.d.ts +18 -0
- package/dist/case/check.js +456 -0
- package/dist/case/compile-cli.d.ts +3 -0
- package/dist/case/compile-cli.js +291 -0
- package/dist/case/decompile-cli.d.ts +9 -0
- package/dist/case/decompile-cli.js +117 -0
- package/dist/case/decompile.d.ts +187 -0
- package/dist/case/decompile.js +1170 -0
- package/dist/case/entry-points.d.ts +79 -0
- package/dist/case/entry-points.js +118 -0
- package/dist/case/format-profile.d.ts +60 -0
- package/dist/case/format-profile.js +79 -0
- package/dist/case/ids.d.ts +24 -0
- package/dist/case/ids.js +76 -0
- package/dist/case/load.d.ts +12 -0
- package/dist/case/load.js +32 -0
- package/dist/case/preserve.d.ts +133 -0
- package/dist/case/preserve.js +105 -0
- package/dist/case/serialize.d.ts +10 -0
- package/dist/case/serialize.js +1414 -0
- package/dist/check-cli.d.ts +3 -0
- package/dist/check-cli.js +118 -0
- package/dist/check.d.ts +146 -0
- package/dist/check.js +4898 -0
- package/dist/cli/commands/bpmn.d.ts +2 -0
- package/dist/cli/commands/bpmn.js +73 -0
- package/dist/cli/commands/case.d.ts +2 -0
- package/dist/cli/commands/case.js +60 -0
- package/dist/cli/commands/flow.d.ts +2 -0
- package/dist/cli/commands/flow.js +99 -0
- package/dist/cli/commands/registry.d.ts +10 -0
- package/dist/cli/commands/registry.js +170 -0
- package/dist/cli/common.d.ts +30 -0
- package/dist/cli/common.js +92 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +18 -0
- package/dist/cli-run.d.ts +2 -0
- package/dist/cli-run.js +42 -0
- package/dist/compile-cli.d.ts +3 -0
- package/dist/compile-cli.js +160 -0
- package/dist/config.d.ts +47 -0
- package/dist/config.js +201 -0
- package/dist/core/actions.d.ts +3244 -0
- package/dist/core/actions.js +1062 -0
- package/dist/core/binding-messages.d.ts +1 -0
- package/dist/core/binding-messages.js +16 -0
- package/dist/core/bindings.d.ts +12 -0
- package/dist/core/bindings.js +67 -0
- package/dist/core/ceql.d.ts +73 -0
- package/dist/core/ceql.js +272 -0
- package/dist/core/cli-spelling.d.ts +39 -0
- package/dist/core/cli-spelling.js +62 -0
- package/dist/core/connector-raw-node.d.ts +21 -0
- package/dist/core/connector-raw-node.js +47 -0
- package/dist/core/connectors.d.ts +184 -0
- package/dist/core/connectors.js +128 -0
- package/dist/core/expr-check.d.ts +93 -0
- package/dist/core/expr-check.js +186 -0
- package/dist/core/expr.d.ts +323 -0
- package/dist/core/expr.js +400 -0
- package/dist/core/index.d.ts +10 -0
- package/dist/core/index.js +10 -0
- package/dist/core/library.d.ts +440 -0
- package/dist/core/library.js +1183 -0
- package/dist/core/list-envelope.d.ts +45 -0
- package/dist/core/list-envelope.js +97 -0
- package/dist/core/lookup-store.d.ts +22 -0
- package/dist/core/lookup-store.js +85 -0
- package/dist/core/lookups.d.ts +227 -0
- package/dist/core/lookups.js +231 -0
- package/dist/core/node-classes.d.ts +234 -0
- package/dist/core/node-classes.js +158 -0
- package/dist/core/script-return.d.ts +68 -0
- package/dist/core/script-return.js +197 -0
- package/dist/core/stable-id.d.ts +28 -0
- package/dist/core/stable-id.js +37 -0
- package/dist/core-definitions.json +16249 -0
- package/dist/decompile-cli.d.ts +3 -0
- package/dist/decompile-cli.js +131 -0
- package/dist/decompile.d.ts +138 -0
- package/dist/decompile.js +2482 -0
- package/dist/emit.d.ts +10 -0
- package/dist/emit.js +60 -0
- package/dist/event-filters.d.ts +130 -0
- package/dist/event-filters.js +137 -0
- package/dist/flow-expr-check.d.ts +17 -0
- package/dist/flow-expr-check.js +193 -0
- package/dist/flow-sdk.d.ts +1341 -0
- package/dist/flow-sdk.js +1164 -0
- package/dist/flow-variables.d.ts +13 -0
- package/dist/flow-variables.js +42 -0
- package/dist/format-profile.d.ts +72 -0
- package/dist/format-profile.js +97 -0
- package/dist/generators/_connections.py +287 -0
- package/dist/generators/_events.py +355 -0
- package/dist/generators/_lookups.py +114 -0
- package/dist/generators/_naming.py +185 -0
- package/dist/generators/_objects.py +299 -0
- package/dist/generators/_resolve.py +273 -0
- package/dist/generators/convert_library_to_md.py +1441 -0
- package/dist/generators/extract_library.py +125 -0
- package/dist/generators/generate_connectors_ts.py +936 -0
- package/dist/generators/generate_library_json.py +2527 -0
- package/dist/generators/generate_triggers_ts.py +110 -0
- package/dist/generators/materialize_registry.py +155 -0
- package/dist/generators/prepare_connector.py +1688 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +35 -0
- package/dist/ixp-definition.json +1982 -0
- package/dist/library.d.ts +6 -0
- package/dist/library.js +6 -0
- package/dist/load.d.ts +16 -0
- package/dist/load.js +95 -0
- package/dist/merge-cli.d.ts +3 -0
- package/dist/merge-cli.js +47 -0
- package/dist/merge.d.ts +125 -0
- package/dist/merge.js +0 -0
- package/dist/migrate.d.ts +15 -0
- package/dist/migrate.js +245 -0
- package/dist/node-runtime.d.ts +3 -0
- package/dist/node-runtime.js +22 -0
- package/dist/package-name.d.ts +17 -0
- package/dist/package-name.js +17 -0
- package/dist/ref-resolve.d.ts +77 -0
- package/dist/ref-resolve.js +170 -0
- package/dist/registry/cache.d.ts +55 -0
- package/dist/registry/cache.js +134 -0
- package/dist/registry/curated-overlay.d.ts +16 -0
- package/dist/registry/curated-overlay.js +62 -0
- package/dist/registry/extractor.d.ts +22 -0
- package/dist/registry/extractor.js +18 -0
- package/dist/registry/materialize-bin.d.ts +2 -0
- package/dist/registry/materialize-bin.js +7 -0
- package/dist/registry/materialize-cli.d.ts +1 -0
- package/dist/registry/materialize-cli.js +46 -0
- package/dist/registry/materializer.d.ts +23 -0
- package/dist/registry/materializer.js +34 -0
- package/dist/registry/path-cli.d.ts +1 -0
- package/dist/registry/path-cli.js +56 -0
- package/dist/registry/prepare-cli.d.ts +62 -0
- package/dist/registry/prepare-cli.js +185 -0
- package/dist/registry/pull-cli.d.ts +1 -0
- package/dist/registry/pull-cli.js +274 -0
- package/dist/registry/python.d.ts +26 -0
- package/dist/registry/python.js +46 -0
- package/dist/registry/search-cli.d.ts +52 -0
- package/dist/registry/search-cli.js +159 -0
- package/dist/schema-version.d.ts +165 -0
- package/dist/schema-version.js +148 -0
- package/dist/serialize.d.ts +64 -0
- package/dist/serialize.js +6398 -0
- package/lib/README.md +112 -0
- package/lib/library-json.samples/index.json +158 -0
- package/lib/library-json.samples/invariant-collections.json +83 -0
- package/lib/library-json.samples/list-envelopes.json +123 -0
- package/lib/library-json.samples/uipath-atlassian-jira/create-issue@1.0.0.json +131 -0
- package/lib/library-json.samples/uipath-atlassian-jira/create-issue@1.0.0.v1def.json +306 -0
- package/lib/library-json.samples/uipath-atlassian-jira/generic/create_issue/create@1.0.0.json +86 -0
- package/lib/library-json.samples/uipath-atlassian-jira/generic/create_issue/create@1.0.0.v1def.json +208 -0
- package/lib/library-json.samples/uipath-atlassian-jira/get-issue@1.0.0.json +2040 -0
- package/lib/library-json.samples/uipath-atlassian-jira/get-issue@1.0.0.v1def.json +195 -0
- package/lib/library-json.samples/uipath-google-vertex/execute-google-vertex-agent@1.0.0.json +169 -0
- package/lib/library-json.samples/uipath-google-vertex/execute-google-vertex-agent@1.0.0.v1def.json +209 -0
- package/lib/library-json.samples/uipath-http-webhook/event-http-webhook@1.0.0.json +63 -0
- package/lib/library-json.samples/uipath-http-webhook/event-http-webhook@1.0.0.v1def.json +262 -0
- package/lib/library-json.samples/uipath-http-webhook/trigger-http-webhook@1.0.0.json +63 -0
- package/lib/library-json.samples/uipath-http-webhook/trigger-http-webhook@1.0.0.v1def.json +213 -0
- package/lib/library-json.samples/uipath-microsoft-azureactivedirectory/list-groups@1.0.0.json +227 -0
- package/lib/library-json.samples/uipath-microsoft-azureactivedirectory/list-groups@1.0.0.v1def.json +373 -0
- package/lib/library-json.samples/uipath-microsoft-onedrive/event-file-created@1.0.0.json +116 -0
- package/lib/library-json.samples/uipath-microsoft-onedrive/event-file-created@1.0.0.v1def.json +369 -0
- package/lib/library-json.samples/uipath-microsoft-onedrive/event-list-item-added@1.0.0.json +56 -0
- package/lib/library-json.samples/uipath-microsoft-onedrive/event-list-item-added@1.0.0.v1def.json +256 -0
- package/lib/library-json.samples/uipath-microsoft-onedrive/trigger-file-created@1.0.0.json +116 -0
- package/lib/library-json.samples/uipath-microsoft-onedrive/trigger-file-created@1.0.0.v1def.json +320 -0
- package/lib/library-json.samples/uipath-microsoft-onedrive/trigger-list-item-added@1.0.0.json +56 -0
- package/lib/library-json.samples/uipath-microsoft-onedrive/trigger-list-item-added@1.0.0.v1def.json +207 -0
- package/lib/library-json.samples/uipath-microsoft-outlook365/event-email-received@1.0.0.json +107 -0
- package/lib/library-json.samples/uipath-microsoft-outlook365/event-email-received@1.0.0.v1def.json +264 -0
- package/lib/library-json.samples/uipath-microsoft-outlook365/send-email@1.0.0.json +142 -0
- package/lib/library-json.samples/uipath-microsoft-outlook365/send-email@1.0.0.v1def.json +306 -0
- package/lib/library-json.samples/uipath-microsoft-outlook365/trigger-email-received@1.0.0.json +107 -0
- package/lib/library-json.samples/uipath-microsoft-outlook365/trigger-email-received@1.0.0.v1def.json +217 -0
- package/lib/library-json.samples/uipath-microsoft-powerautomate/invoke-a-microsoft-power-automate-flow@1.0.0.json +85 -0
- package/lib/library-json.samples/uipath-microsoft-powerautomate/invoke-a-microsoft-power-automate-flow@1.0.0.v1def.json +209 -0
- package/lib/library-json.samples/uipath-salesforce-slack/send-message-to-user@1.0.0.json +755 -0
- package/lib/library-json.samples/uipath-salesforce-slack/send-message-to-user@1.0.0.v1def.json +513 -0
- package/lib/library-json.samples/uipath-uipath-dataservice/query-entity-records@1.0.0.json +122 -0
- package/lib/library-json.samples/uipath-uipath-dataservice/query-entity-records@1.0.0.v1def.json +227 -0
- package/package.json +85 -0
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
const require = createRequire(import.meta.url);
|
|
3
|
+
const REGISTRY = require('./registry-types.json');
|
|
4
|
+
/** Every extension type in the snapshot, sorted. */
|
|
5
|
+
export function registryTypeNames() {
|
|
6
|
+
return Object.keys(REGISTRY.types).sort();
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The spec for one extension type.
|
|
10
|
+
*
|
|
11
|
+
* @param type - The extension type, e.g. `'Intsvc.UnifiedHttpRequest'`.
|
|
12
|
+
* @returns Its emission spec.
|
|
13
|
+
* @throws If the type is not in the committed snapshot — which means either a
|
|
14
|
+
* typo or a registry refresh the snapshot has not caught up with.
|
|
15
|
+
*/
|
|
16
|
+
export function registryType(type) {
|
|
17
|
+
const spec = REGISTRY.types[type];
|
|
18
|
+
if (!spec) {
|
|
19
|
+
throw new Error(`unknown extension type "${type}". The committed registry snapshot has ${REGISTRY.provenance.typeCount} types; ` +
|
|
20
|
+
'refresh it with `node scripts/materialize-bpmn-registry.mjs` if the platform added one.');
|
|
21
|
+
}
|
|
22
|
+
return spec;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Facts the platform enforces but the registry does not state.
|
|
26
|
+
*
|
|
27
|
+
* Every entry here was found by probing `uip maestro bpmn validate`, not read out
|
|
28
|
+
* of a spec — so every entry is a liability: it can drift without the snapshot
|
|
29
|
+
* changing, and nothing upstream promises it. Keeping them in one visible table
|
|
30
|
+
* beats burying them in a builder method, and each is pinned by a test so a
|
|
31
|
+
* platform change fails loudly instead of silently emitting a rejected artifact.
|
|
32
|
+
*
|
|
33
|
+
* `resourceSubType` — `Orchestrator.StartAgentJob` requires its process bindings to
|
|
34
|
+
* carry `resourceSubType="Agent"` on top of the `resource`/`propertyAttribute` the
|
|
35
|
+
* registry does give:
|
|
36
|
+
*
|
|
37
|
+
* [error] Orchestrator.StartAgentJob binding "x" must target Agent name.
|
|
38
|
+
*
|
|
39
|
+
* `resource="Agent"` and `resource="agent"` are both rejected; only
|
|
40
|
+
* `resource="process"` + `resourceSubType="Agent"` validates. The string matches the
|
|
41
|
+
* field's `DisplayName`, but nothing says that is the rule, so it is recorded as a
|
|
42
|
+
* constant for the one type known to need it rather than derived.
|
|
43
|
+
*/
|
|
44
|
+
export const REGISTRY_GAPS = {
|
|
45
|
+
'Orchestrator.StartAgentJob': { resourceSubType: 'Agent' },
|
|
46
|
+
// `notEnforcedInputs` — required InputFields the platform does NOT actually enforce.
|
|
47
|
+
//
|
|
48
|
+
// MEASURED, on a real trigger that carries `connection`, `folderKey`, `connectorKey`,
|
|
49
|
+
// `operation`, `objectName` in its `uipath:context` and none of them as `uipath:input`
|
|
50
|
+
// rows. `uip maestro bpmn validate` reports exactly ONE error for it —
|
|
51
|
+
// `connectionId` — so it satisfies required fields from context (which
|
|
52
|
+
// `missingRequiredInputs` now does too) and does not ask for `folderId` or
|
|
53
|
+
// `folderPath` at all, though the registry marks both required.
|
|
54
|
+
//
|
|
55
|
+
// Without this the SDK rejects a trigger the CLI accepts. An earlier attempt
|
|
56
|
+
// suppressed the whole type instead, on the unfounded belief that the CLI accepted
|
|
57
|
+
// that artifact — it does not, and that made the SDK accept what the platform
|
|
58
|
+
// rejects. This is the narrow, checked version of that.
|
|
59
|
+
'Intsvc.EventTrigger': { notEnforcedInputs: ['folderId', 'folderPath'] },
|
|
60
|
+
'Intsvc.WaitForEvent': { notEnforcedInputs: ['folderId', 'folderPath'] },
|
|
61
|
+
// `extraContext` — context fields the PLATFORM accepts for a type but the
|
|
62
|
+
// registry's `ContextFields` does not list. Found when `bpmn-decompile`
|
|
63
|
+
// round-tripped a connector task and the strict unknown-field guard rejected
|
|
64
|
+
// `activity` and `resourceKey`, which `bpmn/connector.ts` has always emitted and
|
|
65
|
+
// which `uip maestro bpmn validate` has always accepted. So the guard was right
|
|
66
|
+
// that they are undeclared and wrong that they are invalid — recorded here rather
|
|
67
|
+
// than by loosening the guard, which is what catches an author's typo.
|
|
68
|
+
'Intsvc.ActivityExecution': { extraContext: ['activity', 'resourceKey'] },
|
|
69
|
+
// `outputRowsFixed` — the type permits EXACTLY the output row its spec declares.
|
|
70
|
+
// A mapped second row is refused:
|
|
71
|
+
//
|
|
72
|
+
// [error] Maestro.ReceiveMessageEvent output name must be "response".
|
|
73
|
+
// [error] Maestro.ReceiveMessageEvent output type must be "Maestro.ReceiveMessageEvent".
|
|
74
|
+
//
|
|
75
|
+
// Recorded rather than derived because the registry gives no way to tell. Compare
|
|
76
|
+
// `Actions.HITL`: a structurally IDENTICAL output declaration (typed row, no
|
|
77
|
+
// `source`, `relative: true`) which accepts a mapped second row — and has to, since
|
|
78
|
+
// that row is the only thing an offline approval branch can read. Two types, the
|
|
79
|
+
// same spec, opposite enforcement.
|
|
80
|
+
'Maestro.ReceiveMessageEvent': { outputRowsFixed: true },
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* An output name reduced to something an expression can actually read.
|
|
84
|
+
*
|
|
85
|
+
* Registry output names are DISPLAY names, and some contain spaces — the whole
|
|
86
|
+
* Orchestrator job family calls its output `Process response`. Interpolated
|
|
87
|
+
* straight into a default variable that yields `start_Process response`, which no
|
|
88
|
+
* `vars.<name>` reference can address. Camel-casing the words keeps the default
|
|
89
|
+
* predictable (`start_processResponse`) and legal; an author who wants a nicer name
|
|
90
|
+
* passes `outputVar`.
|
|
91
|
+
*/
|
|
92
|
+
function identifierize(name) {
|
|
93
|
+
const words = name.split(/[^A-Za-z0-9]+/).filter(Boolean);
|
|
94
|
+
if (words.length === 0)
|
|
95
|
+
return 'response';
|
|
96
|
+
return words
|
|
97
|
+
.map((w, i) => (i === 0 ? w.charAt(0).toLowerCase() + w.slice(1) : w.charAt(0).toUpperCase() + w.slice(1)))
|
|
98
|
+
.join('');
|
|
99
|
+
}
|
|
100
|
+
/** The variable a typed node's output row writes, or `undefined` when it has none. */
|
|
101
|
+
export function typedNodeOutputVar(id, type, outputVar) {
|
|
102
|
+
const spec = registryType(type);
|
|
103
|
+
if (!spec.output)
|
|
104
|
+
return undefined;
|
|
105
|
+
return outputVar ?? `${id}_${identifierize(spec.output.name)}`;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* `uipath:context` — one scalar `uipath:input` per field the author supplied, or
|
|
109
|
+
* that the registry gives a default.
|
|
110
|
+
*
|
|
111
|
+
* A field is emitted when the author set it OR the registry declares a default.
|
|
112
|
+
* The registry's defaults are not cosmetic: `Intsvc.UnifiedHttpRequest` declares
|
|
113
|
+
* `mode: "manual"` as REQUIRED and HIDDEN, so an author never passes it and the
|
|
114
|
+
* artifact fails validation without it.
|
|
115
|
+
*/
|
|
116
|
+
/**
|
|
117
|
+
* A `json` context field's CDATA body.
|
|
118
|
+
*
|
|
119
|
+
* The field IS JSON — `metadata`, `headers`, `parameters`, `body`, `decisions` and
|
|
120
|
+
* the two case-rule fields are all declared `type="json"` in the registry — so an
|
|
121
|
+
* author writes the value, not a hand-encoded string of it. Before this,
|
|
122
|
+
* `String(value)` wrote `[object Object]` into the artifact for anything but a
|
|
123
|
+
* string, silently, and nothing offline caught it.
|
|
124
|
+
*
|
|
125
|
+
* A string still goes through untouched, which is both what every existing artifact
|
|
126
|
+
* and every prior caller passes, and the only way to write a body this SDK could
|
|
127
|
+
* not otherwise spell.
|
|
128
|
+
*/
|
|
129
|
+
function jsonBody(value) {
|
|
130
|
+
return typeof value === 'string' ? value : JSON.stringify(value);
|
|
131
|
+
}
|
|
132
|
+
function contextRows(m, type, spec, supplied, verbatim = false) {
|
|
133
|
+
const rows = [];
|
|
134
|
+
const emitted = new Set();
|
|
135
|
+
if (verbatim) {
|
|
136
|
+
// Supplied order, supplied fields, nothing added. The declared TYPE is still
|
|
137
|
+
// honoured, so a json field lands in the body rather than an attribute.
|
|
138
|
+
const byName = new Map(spec.context.map((f) => [f.name, f]));
|
|
139
|
+
for (const [name, value] of Object.entries(supplied)) {
|
|
140
|
+
if (value === undefined || value === null)
|
|
141
|
+
continue;
|
|
142
|
+
const fieldType = byName.get(name)?.type ?? 'string';
|
|
143
|
+
rows.push(fieldType === 'json'
|
|
144
|
+
? m.create('uipath:Input', { name, type: fieldType, body: jsonBody(value) })
|
|
145
|
+
: m.create('uipath:Input', { name, type: fieldType, value: String(value) }));
|
|
146
|
+
}
|
|
147
|
+
return rows;
|
|
148
|
+
}
|
|
149
|
+
for (const field of spec.context) {
|
|
150
|
+
const value = supplied[field.name] ?? field.default;
|
|
151
|
+
if (value === undefined || value === null)
|
|
152
|
+
continue;
|
|
153
|
+
emitted.add(field.name);
|
|
154
|
+
// A `json` field goes in the CDATA BODY, not a `value` attribute. The product
|
|
155
|
+
// validator parses that field as JSON and reads the attribute WITHOUT XML
|
|
156
|
+
// entity decoding, so an attribute-borne object arrives as
|
|
157
|
+
// `{"a":1}` and is reported as `context input "…" contains malformed
|
|
158
|
+
// JSON`. The connector emitter has always used the body for json inputs; this
|
|
159
|
+
// matches it. (Neither offline validator catches this — only the CLI does.)
|
|
160
|
+
rows.push(field.type === 'json'
|
|
161
|
+
? m.create('uipath:Input', { name: field.name, type: field.type, body: jsonBody(value) })
|
|
162
|
+
: m.create('uipath:Input', { name: field.name, type: field.type, value: String(value) }));
|
|
163
|
+
}
|
|
164
|
+
// A value the registry does not declare is USUALLY a typo — the platform ignores
|
|
165
|
+
// it and the author never learns why their setting did nothing — so it is
|
|
166
|
+
// refused. The exception is a type with a recorded `extraContext` gap, where the
|
|
167
|
+
// platform is known to accept fields the registry omits.
|
|
168
|
+
const known = new Set([...spec.context.map((f) => f.name), ...(REGISTRY_GAPS[type]?.extraContext ?? [])]);
|
|
169
|
+
const unknown = Object.keys(supplied).filter((k) => !known.has(k));
|
|
170
|
+
if (unknown.length) {
|
|
171
|
+
throw new Error(`context field(s) ${unknown.map((u) => `"${u}"`).join(', ')} are not declared by this extension type. ` +
|
|
172
|
+
`Declared: ${[...known].join(', ') || '(none)'}.`);
|
|
173
|
+
}
|
|
174
|
+
// Permitted-but-undeclared fields (a recorded `extraContext` gap) still have to
|
|
175
|
+
// be WRITTEN. The loop above walks the registry's own list, so without this they
|
|
176
|
+
// passed the guard and were then silently dropped — which a round-trip caught.
|
|
177
|
+
for (const [name, value] of Object.entries(supplied)) {
|
|
178
|
+
if (emitted.has(name) || value === undefined || value === null)
|
|
179
|
+
continue;
|
|
180
|
+
rows.push(m.create('uipath:Input', { name, type: 'string', value: String(value) }));
|
|
181
|
+
}
|
|
182
|
+
return rows;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* The payload rows, per the type's `inputPattern`.
|
|
186
|
+
*
|
|
187
|
+
* - `none` — the type takes no payload; anything supplied is an author error.
|
|
188
|
+
* - `mergedBody` / `splitInputsItemData` — one json input under the spec's
|
|
189
|
+
* `inputName`/`inputTarget`, carrying the whole object.
|
|
190
|
+
* - `separateInputs` — the payload's own keys become sibling json inputs, which is
|
|
191
|
+
* how the HTTP node's `headers`/`parameters`/`body` are addressed individually.
|
|
192
|
+
* - `scriptArgs` — handled by the script-task emitter, not here.
|
|
193
|
+
*/
|
|
194
|
+
function inputRows(m, spec, inputs) {
|
|
195
|
+
const keys = Object.keys(inputs);
|
|
196
|
+
if (spec.inputPattern === 'none') {
|
|
197
|
+
if (keys.length) {
|
|
198
|
+
throw new Error(`this extension type takes no inputs, but ${keys.length} were supplied (${keys.join(', ')}).`);
|
|
199
|
+
}
|
|
200
|
+
return [];
|
|
201
|
+
}
|
|
202
|
+
if (spec.inputPattern === 'separateInputs') {
|
|
203
|
+
// Sibling rows, one per supplied key.
|
|
204
|
+
//
|
|
205
|
+
// The target is NOT `spec.inputTarget`. That field names the single target for
|
|
206
|
+
// the one-row patterns, and applying it here collapsed every sibling onto the
|
|
207
|
+
// same target: a connector's three rows all came out `target="body"` instead of
|
|
208
|
+
// `pathParameters` / `queryParameters` / `body`, so an artifact authored through
|
|
209
|
+
// the generic `.activity()` sent path and query parameters in the request body.
|
|
210
|
+
//
|
|
211
|
+
// Nor is it always the key. The key was the fix for that collapse, and it is
|
|
212
|
+
// right for a type whose inputs are DYNAMIC — a connector's fields come from
|
|
213
|
+
// the connector library, not the registry, so the key is the only thing to go
|
|
214
|
+
// on. But a type that DECLARES its payload fields declares their target too,
|
|
215
|
+
// and the key is then wrong: `Maestro.ReceiveMessageEvent.Reference` targets
|
|
216
|
+
// `bodyField`, so keying it produced `target="Reference"` — a target the
|
|
217
|
+
// platform does not read, and one no validator complains about.
|
|
218
|
+
//
|
|
219
|
+
// So: the declared field decides when there is one, the key when there is not.
|
|
220
|
+
const declared = new Map(spec.inputs.map((f) => [f.name, f]));
|
|
221
|
+
return keys.map((k) => {
|
|
222
|
+
const field = declared.get(k);
|
|
223
|
+
return payloadInput(m, k, field?.target ?? k, inputs[k], field?.type ?? 'json');
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
if (!spec.inputName)
|
|
227
|
+
return [];
|
|
228
|
+
return [jsonInput(m, spec.inputName, spec.inputTarget ?? 'body', inputs)];
|
|
229
|
+
}
|
|
230
|
+
function jsonInput(m, name, target, value) {
|
|
231
|
+
const props = { name, type: 'json', body: JSON.stringify(value ?? {}) };
|
|
232
|
+
if (target)
|
|
233
|
+
props.target = target;
|
|
234
|
+
return m.create('uipath:Input', props);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* One payload row, typed as the registry declares the field.
|
|
238
|
+
*
|
|
239
|
+
* The body/attribute split is the same rule `contextRows` follows and for the same
|
|
240
|
+
* measured reason: a structured value must be a CDATA BODY, because the product
|
|
241
|
+
* validator reads a `value` attribute without XML entity decoding and an
|
|
242
|
+
* object-bearing attribute comes back as `{"a":1}`. A SCALAR is the
|
|
243
|
+
* opposite — JSON-encoding it into a body double-quotes it, so a string
|
|
244
|
+
* correlation reference arrived as `"ORD-1"` rather than `ORD-1`. Neither
|
|
245
|
+
* offline validator catches either direction.
|
|
246
|
+
*
|
|
247
|
+
* A structured field stays in the body even when its value is an `=`-expression.
|
|
248
|
+
* That is deliberate rather than an oversight: an expression inside a JSON body IS
|
|
249
|
+
* resolved — `<uipath:input name="ItemData" type="json" target="body">
|
|
250
|
+
* {"Reference":"=vars.ref"}` reports `VARIABLE_DOES_NOT_EXIST` against an
|
|
251
|
+
* undeclared variable, so the platform is reading it — whereas an expression in a
|
|
252
|
+
* `type="json"` ATTRIBUTE is a shape nothing here has verified.
|
|
253
|
+
*/
|
|
254
|
+
function payloadInput(m, name, target, value, type) {
|
|
255
|
+
const structured = type === 'json' || type === 'object' || type === 'array' || type === 'jsonSchema';
|
|
256
|
+
const props = structured
|
|
257
|
+
? { name, type: 'json', body: JSON.stringify(value ?? {}) }
|
|
258
|
+
: { name, type, value: String(value ?? '') };
|
|
259
|
+
if (target)
|
|
260
|
+
props.target = target;
|
|
261
|
+
return m.create('uipath:Input', props);
|
|
262
|
+
}
|
|
263
|
+
/** The `uipath:output` row, when the type declares one. */
|
|
264
|
+
function outputRow(m, spec, varName) {
|
|
265
|
+
if (!spec.output)
|
|
266
|
+
return undefined;
|
|
267
|
+
const props = { name: spec.output.name, type: spec.output.type, var: varName };
|
|
268
|
+
// Only when the registry gives one: several types declare an output with no
|
|
269
|
+
// source at all, and inventing `=<name>` for them would not round-trip.
|
|
270
|
+
if (spec.output.source)
|
|
271
|
+
props.source = spec.output.source;
|
|
272
|
+
return m.create('uipath:Output', props);
|
|
273
|
+
}
|
|
274
|
+
/** The moddle type name for an instance tag, e.g. `uipath:activity` → `uipath:Activity`. */
|
|
275
|
+
function moddleTypeOf(tag) {
|
|
276
|
+
const [ns, local] = tag.split(':');
|
|
277
|
+
return `${ns}:${local.charAt(0).toUpperCase()}${local.slice(1)}`;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Emit a registry-backed typed node.
|
|
281
|
+
*
|
|
282
|
+
* @param m - The moddle instance to create elements with.
|
|
283
|
+
* @param id - The BPMN element id.
|
|
284
|
+
* @param type - The extension type, e.g. `'Intsvc.UnifiedHttpRequest'`.
|
|
285
|
+
* @param input - Author-supplied name, context, payload, output variable and skip.
|
|
286
|
+
* @returns The moddle element, ready for the serializer to wire flows onto.
|
|
287
|
+
*/
|
|
288
|
+
export function createTypedNode(m, id, type, input,
|
|
289
|
+
/**
|
|
290
|
+
* Declared Maestro `type` for a variable id, for typing the extra output rows below.
|
|
291
|
+
* Optional so a caller with no variable context still gets today's behaviour.
|
|
292
|
+
*/
|
|
293
|
+
varType) {
|
|
294
|
+
const spec = registryType(type);
|
|
295
|
+
if (!spec.element || !spec.tag) {
|
|
296
|
+
throw new Error(`extension type "${type}" has no element/tag in the registry snapshot; it cannot be authored.`);
|
|
297
|
+
}
|
|
298
|
+
const payload = {
|
|
299
|
+
version: 'v1',
|
|
300
|
+
type: m.create('uipath:Type', { value: type, version: input.typeVersion ?? 'v1' }),
|
|
301
|
+
};
|
|
302
|
+
// `skipCondition` exists on the activity/event tags only — a mapping cannot
|
|
303
|
+
// carry it, and moddle would silently drop it (see ActivityOpts in bpmn-sdk).
|
|
304
|
+
if (input.skipCondition !== undefined) {
|
|
305
|
+
if (spec.tag === 'uipath:mapping') {
|
|
306
|
+
throw new Error(`extension type "${type}" serializes a uipath:mapping, which cannot carry a skipCondition.`);
|
|
307
|
+
}
|
|
308
|
+
payload.skipCondition = input.skipCondition;
|
|
309
|
+
}
|
|
310
|
+
const ctx = input.contextRows
|
|
311
|
+
? input.contextRows.map((row) => {
|
|
312
|
+
const props = { name: row.name, type: row.type ?? 'string' };
|
|
313
|
+
if (row.required)
|
|
314
|
+
props.required = 'true';
|
|
315
|
+
if (row.target !== undefined)
|
|
316
|
+
props.target = row.target;
|
|
317
|
+
if (row.value !== undefined)
|
|
318
|
+
props.value = row.value;
|
|
319
|
+
if (row.body !== undefined)
|
|
320
|
+
props.body = jsonBody(row.body);
|
|
321
|
+
return m.create('uipath:Input', props);
|
|
322
|
+
})
|
|
323
|
+
: contextRows(m, type, spec, input.context ?? {}, input.contextVerbatim);
|
|
324
|
+
// The schema is a sibling of the context's rows, and can be the only thing in it —
|
|
325
|
+
// a script task's context carries an inputSchema and no rows at all.
|
|
326
|
+
if (ctx.length || input.inputSchema !== undefined) {
|
|
327
|
+
const context = {};
|
|
328
|
+
if (ctx.length)
|
|
329
|
+
context.input = ctx;
|
|
330
|
+
if (input.inputSchema !== undefined) {
|
|
331
|
+
context.inputSchema = m.create('uipath:InputSchema', {
|
|
332
|
+
type: 'jsonSchema',
|
|
333
|
+
body: typeof input.inputSchema === 'string' ? input.inputSchema : JSON.stringify(input.inputSchema),
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
payload.context = m.create('uipath:Context', context);
|
|
337
|
+
}
|
|
338
|
+
const ins = inputRows(m, spec, input.inputs ?? {});
|
|
339
|
+
if (ins.length)
|
|
340
|
+
payload.input = ins;
|
|
341
|
+
const rows = [];
|
|
342
|
+
if (input.outputRows) {
|
|
343
|
+
// Spelled out by the caller: emit exactly these, deriving nothing. See
|
|
344
|
+
// TypedNodeInput.outputRows — this is what lets a connector's response schema
|
|
345
|
+
// survive a round trip.
|
|
346
|
+
rows.push(...verbatimOutputRows(m, input.outputRows));
|
|
347
|
+
if (rows.length)
|
|
348
|
+
payload.output = rows;
|
|
349
|
+
return finish(m, spec, id, input.name, payload);
|
|
350
|
+
}
|
|
351
|
+
const outVar = typedNodeOutputVar(id, type, input.outputVar);
|
|
352
|
+
const out = outVar ? outputRow(m, spec, outVar) : undefined;
|
|
353
|
+
if (out)
|
|
354
|
+
rows.push(out);
|
|
355
|
+
for (const [varId, source] of Object.entries(input.outputs ?? {})) {
|
|
356
|
+
// Type the row from the variable it writes, not `'string'` unconditionally.
|
|
357
|
+
//
|
|
358
|
+
// The runtime coerces a value by switching on this `type`, so a boolean captured as
|
|
359
|
+
// `type="string"` is the D1 hazard one layer along: the local engine evaluates the
|
|
360
|
+
// expression and gets a real boolean, but the platform is told the row is a string, and a
|
|
361
|
+
// gateway guarded on it can then branch on the truthy string `"false"`. It also made a
|
|
362
|
+
// boolean HITL decision unauthorable — `check_quality_boolean_decision.py` requires an
|
|
363
|
+
// output whose `type` is boolean and whose `var` binds a boolean variable.
|
|
364
|
+
//
|
|
365
|
+
// `'string'` remains the fallback for a variable this node writes without declaring,
|
|
366
|
+
// which is what every row did before.
|
|
367
|
+
rows.push(m.create('uipath:Output', { name: varId, type: varType?.(varId) ?? 'string', source, var: varId }));
|
|
368
|
+
}
|
|
369
|
+
if (rows.length)
|
|
370
|
+
payload.output = rows;
|
|
371
|
+
return finish(m, spec, id, input.name, payload);
|
|
372
|
+
}
|
|
373
|
+
/** `uipath:Output` rows exactly as the caller spelled them, deriving nothing. */
|
|
374
|
+
export function verbatimOutputRows(m, rows) {
|
|
375
|
+
return rows.map((row) => {
|
|
376
|
+
const props = { name: row.name, type: row.type ?? 'string' };
|
|
377
|
+
if (row.source !== undefined)
|
|
378
|
+
props.source = row.source;
|
|
379
|
+
if (row.var !== undefined)
|
|
380
|
+
props.var = row.var;
|
|
381
|
+
if (row.custom)
|
|
382
|
+
props.custom = true;
|
|
383
|
+
if (row.description !== undefined)
|
|
384
|
+
props.description = row.description;
|
|
385
|
+
if (row.target !== undefined)
|
|
386
|
+
props.target = row.target;
|
|
387
|
+
if (row.schema !== undefined) {
|
|
388
|
+
props.body = typeof row.schema === 'string' ? row.schema : JSON.stringify(row.schema);
|
|
389
|
+
}
|
|
390
|
+
return m.create('uipath:Output', props);
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* The extension payload for a type and its output rows, with NO element around it.
|
|
395
|
+
*
|
|
396
|
+
* `createTypedNode` takes the element from the registry, which is right for an
|
|
397
|
+
* activity and wrong everywhere the product uses a payload as DECORATION: a
|
|
398
|
+
* `uipath:mapping` on a start event, an end event or a sub-process, a
|
|
399
|
+
* `uipath:activity` on an error boundary. Those arms of `createNode` build their
|
|
400
|
+
* own element and attach this to it, rather than letting `BPMN.Variables` turn a
|
|
401
|
+
* start event into a `bpmn:Task`.
|
|
402
|
+
*
|
|
403
|
+
* @param m - The moddle instance.
|
|
404
|
+
* @param type - The extension type, e.g. `BPMN.Variables` or `uipath:Activity`.
|
|
405
|
+
* @param rows - Output rows, emitted verbatim.
|
|
406
|
+
* @returns The payload element, ready to go inside a `bpmn:ExtensionElements`.
|
|
407
|
+
*/
|
|
408
|
+
export function createExtensionPayload(m, type, rows) {
|
|
409
|
+
const spec = registryType(type);
|
|
410
|
+
if (!spec.tag) {
|
|
411
|
+
throw new Error(`extension type "${type}" has no tag in the registry snapshot; it cannot be authored.`);
|
|
412
|
+
}
|
|
413
|
+
const payload = {
|
|
414
|
+
version: 'v1',
|
|
415
|
+
type: m.create('uipath:Type', { value: type, version: 'v1' }),
|
|
416
|
+
};
|
|
417
|
+
const out = verbatimOutputRows(m, rows);
|
|
418
|
+
if (out.length)
|
|
419
|
+
payload.output = out;
|
|
420
|
+
return m.create(moddleTypeOf(spec.tag), payload);
|
|
421
|
+
}
|
|
422
|
+
/** Wrap a finished payload in its BPMN element. */
|
|
423
|
+
function finish(m, spec, id, name, payload) {
|
|
424
|
+
const props = {
|
|
425
|
+
id,
|
|
426
|
+
name,
|
|
427
|
+
extensionElements: m.create('bpmn:ExtensionElements', { values: [m.create(moddleTypeOf(spec.tag), payload)] }),
|
|
428
|
+
};
|
|
429
|
+
// What makes a message event a message event — without it the platform reads a
|
|
430
|
+
// plain intermediate event and the correlation never happens.
|
|
431
|
+
if (spec.eventDefinition) {
|
|
432
|
+
props.eventDefinitions = [m.create(moddleTypeOf(spec.eventDefinition), {})];
|
|
433
|
+
}
|
|
434
|
+
return m.create(moddleElementOf(spec.element), props);
|
|
435
|
+
}
|
|
436
|
+
/** `bpmn:SendTask` is already the moddle type name; keep it, but validate the shape. */
|
|
437
|
+
function moddleElementOf(element) {
|
|
438
|
+
if (!/^bpmn:[A-Z]/.test(element)) {
|
|
439
|
+
throw new Error(`registry element "${element}" is not a moddle type name (expected e.g. bpmn:SendTask).`);
|
|
440
|
+
}
|
|
441
|
+
return element;
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* The context fields this type requires to be a `=bindings.<id>` reference rather
|
|
445
|
+
* than a literal.
|
|
446
|
+
*
|
|
447
|
+
* Narrower than it looks, and the narrowness is measured. `binding: true` marks a
|
|
448
|
+
* field the designer OFFERS a binding picker for — `Intsvc.UnifiedHttpRequest`'s
|
|
449
|
+
* `url` is one, and a literal URL validates fine. What the platform actually
|
|
450
|
+
* enforces is `bindingInfo` AND `required`, which today selects exactly
|
|
451
|
+
* `Orchestrator.StartAgentJob`'s `name` and `folderPath`:
|
|
452
|
+
*
|
|
453
|
+
* [error] Orchestrator.StartAgentJob context input "name" must reference project bindings.
|
|
454
|
+
* [error] Orchestrator.StartAgentJob binding "x" must target Agent name.
|
|
455
|
+
*
|
|
456
|
+
* Both halves are enforced — a literal is rejected, and so is a binding pointing
|
|
457
|
+
* at the wrong property.
|
|
458
|
+
*
|
|
459
|
+
* @param type - The extension type.
|
|
460
|
+
* @returns Its fields that must be bound, with the target each binding needs.
|
|
461
|
+
*/
|
|
462
|
+
export function bindingRequiredFields(type) {
|
|
463
|
+
return registryType(type).context.filter((f) => f.bindingInfo !== null && f.required);
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Required context fields the author left unset and the registry cannot default.
|
|
467
|
+
*
|
|
468
|
+
* Separate from emission so `check()` can report them at authoring time. Missing
|
|
469
|
+
* them is what `uip maestro bpmn validate` reports as `EMPTY_REQUIRED_FIELD`, and
|
|
470
|
+
* hearing it from the SDK is faster than hearing it from the CLI.
|
|
471
|
+
*
|
|
472
|
+
* @param type - The extension type.
|
|
473
|
+
* @param context - The context values the author supplied.
|
|
474
|
+
* @returns The names of required fields with no value and no default.
|
|
475
|
+
*/
|
|
476
|
+
export function missingRequiredContext(type, context = {}) {
|
|
477
|
+
return registryType(type)
|
|
478
|
+
.context.filter((f) => f.required && context[f.name] === undefined && (f.default ?? '') === '')
|
|
479
|
+
.map((f) => f.name);
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Required PAYLOAD fields the author left unset.
|
|
483
|
+
*
|
|
484
|
+
* The counterpart of {@link missingRequiredContext}, and reported the same way: the
|
|
485
|
+
* platform's `RequiredFieldsRule` draws on `InputFields` as well as `ContextFields`,
|
|
486
|
+
* so an unset required payload field is the same `EMPTY_REQUIRED_FIELD` the CLI
|
|
487
|
+
* would report a build later.
|
|
488
|
+
*
|
|
489
|
+
* @param type - The extension type.
|
|
490
|
+
* @param inputs - The payload the author supplied.
|
|
491
|
+
* @returns The names of required payload fields with no value and no default.
|
|
492
|
+
*/
|
|
493
|
+
export function missingRequiredInputs(type, inputs = {},
|
|
494
|
+
/**
|
|
495
|
+
* The node's `uipath:context` values, which SATISFY a required payload field too.
|
|
496
|
+
*
|
|
497
|
+
* The platform's `RequiredFieldsRule` draws on both, and a trigger is where that
|
|
498
|
+
* shows: `Intsvc.EventTrigger` declares seven required inputs, and a real one
|
|
499
|
+
* carries every one of them as a `uipath:context` row rather than a
|
|
500
|
+
* `uipath:input`. Checking inputs alone reported all seven; `uip maestro bpmn
|
|
501
|
+
* validate` reports exactly one — `connectionId`, the only name the artifact
|
|
502
|
+
* genuinely does not spell (it writes `connection`). Reading both makes this
|
|
503
|
+
* agree with the CLI instead of guessing on either side of it.
|
|
504
|
+
*/
|
|
505
|
+
context = {}) {
|
|
506
|
+
const notEnforced = new Set(REGISTRY_GAPS[type]?.notEnforcedInputs ?? []);
|
|
507
|
+
return registryType(type)
|
|
508
|
+
.inputs.filter((f) => f.required &&
|
|
509
|
+
!notEnforced.has(f.name) &&
|
|
510
|
+
inputs[f.name] === undefined &&
|
|
511
|
+
context[f.name] === undefined &&
|
|
512
|
+
(f.default ?? '') === '')
|
|
513
|
+
.map((f) => f.name);
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Whether this type's required payload fields are UNSATISFIABLE on the wire.
|
|
517
|
+
*
|
|
518
|
+
* A platform defect, recorded here because the SDK cannot emit its way around it.
|
|
519
|
+
* `RequiredFieldsRule` builds its required-name set from `InputFields` and then
|
|
520
|
+
* fires when a name is absent from the serialized rows **by name**. Under
|
|
521
|
+
* `mergedBody` and `splitInputsItemData` every payload field collapses into ONE row
|
|
522
|
+
* — named `body` or `ItemData` — so a required input field is never present by
|
|
523
|
+
* name and the rule fires however the node is filled in:
|
|
524
|
+
*
|
|
525
|
+
* [error] [call] EMPTY_REQUIRED_FIELD: The field 'agentUrl' in node 'call' is
|
|
526
|
+
* required but has no value.
|
|
527
|
+
*
|
|
528
|
+
* Note the registry's own `XmlTemplate` for `A2A.AgentExecution` emits exactly the
|
|
529
|
+
* body-only shape that fails, which is the clearest statement that the two halves
|
|
530
|
+
* of the platform disagree rather than that the SDK is writing the wrong thing.
|
|
531
|
+
*
|
|
532
|
+
* Whether a workaround exists is per-type and not derivable from the spec, so it is
|
|
533
|
+
* not encoded here. Measured: `A2A.AgentExecution` accepts redundant sibling rows
|
|
534
|
+
* alongside the merged body (`Valid`); `Maestro.SendMessageEvent` refuses them
|
|
535
|
+
* outright — `does not support input payload "Reference"` as a row, `does not
|
|
536
|
+
* support context input "Reference"` in context, and `ItemData`'s `target="body"`
|
|
537
|
+
* is enforced — so for that type NO artifact satisfies both gates.
|
|
538
|
+
*
|
|
539
|
+
* Selects exactly `A2A.AgentExecution` and `Maestro.SendMessageEvent` today. The
|
|
540
|
+
* three other types with required payload fields are `separateInputs`, whose rows
|
|
541
|
+
* DO carry their own names, and are unaffected.
|
|
542
|
+
*
|
|
543
|
+
* @param type - The extension type.
|
|
544
|
+
* @returns The required payload field names that cannot be expressed, or `[]`.
|
|
545
|
+
*/
|
|
546
|
+
export function unsatisfiableRequiredInputs(type) {
|
|
547
|
+
const spec = registryType(type);
|
|
548
|
+
if (spec.inputPattern !== 'mergedBody' && spec.inputPattern !== 'splitInputsItemData')
|
|
549
|
+
return [];
|
|
550
|
+
return spec.inputs.filter((f) => f.required).map((f) => f.name);
|
|
551
|
+
}
|