@uipath/maestro-builder-sdk 6.31.6 → 6.31.8
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 +74 -73
- package/dist/api-members.md +241 -241
- package/dist/check.js +2 -2
- package/dist/core/actions.d.ts +15 -4
- package/dist/core/form-field-type.d.ts +78 -33
- package/dist/core/form-field-type.js +182 -48
- package/dist/decompile.js +2 -2
- package/dist/merge-embedded-agent.d.ts +90 -0
- package/dist/merge-embedded-agent.js +260 -0
- package/dist/merge-roundtrip.d.ts +3 -2
- package/dist/merge-sidecars.js +22 -11
- package/dist/merge.d.ts +12 -1
- package/dist/merge.js +90 -3
- package/dist/nodes/hitl/flow/check.js +2 -2
- package/dist/nodes/hitl/flow/node-type.js +5 -5
- package/dist/serialize.js +2 -2
- package/package.json +2 -2
package/dist/check.js
CHANGED
|
@@ -10,7 +10,7 @@ import { FlowNode } from './core/node-classes.js';
|
|
|
10
10
|
import { planContributionBindings } from './core/contribution-bindings.js';
|
|
11
11
|
import { definitionHasErrorPort, errorPortRefusal } from './core/error-port.js';
|
|
12
12
|
import { actionVersion, bundledActionNodeType, bundledContainerDefinition, bundledDefinition, perCallDefinition, resolveContributionDefinition } from './serialize.js';
|
|
13
|
-
import { FORM_FIELD_TYPES, formFieldTypeHint, formFieldTypeWhy } from './core/form-field-type.js';
|
|
13
|
+
import { FORM_FIELD_TYPES, formFieldTypeHint, formFieldTypeWhy, validFormFieldTypesText } from './core/form-field-type.js';
|
|
14
14
|
import { AGENTIC_PROCESS_FORMS } from './core/agentic-process-forms.js';
|
|
15
15
|
import { checkEventResolution, checkEventSubscription, eventParamsFor, } from './core/event-checks.js';
|
|
16
16
|
import { checkCookedEscapes } from './flow-expr-check.js';
|
|
@@ -3416,7 +3416,7 @@ function checkInlineAgent(step, inputs, diags, opts = {}) {
|
|
|
3416
3416
|
if (!FORM_FIELD_TYPES.includes(String(f?.type))) {
|
|
3417
3417
|
at('INLINE_AGENT_ESCALATION_FIELD_TYPE_UNKNOWN', `Inline agent step "${step}"'s quick-form escalation gives the field "${String(f?.id ?? '?')}" the type `
|
|
3418
3418
|
+ `${JSON.stringify(f?.type)}, ${formFieldTypeWhy(f?.type, `which the form does not recognize — it would `
|
|
3419
|
-
+ `be published as a plain string`)}. Valid: ${
|
|
3419
|
+
+ `be published as a plain string`)}. Valid: ${validFormFieldTypesText()}.`, formFieldTypeHint(f?.type));
|
|
3420
3420
|
}
|
|
3421
3421
|
}
|
|
3422
3422
|
continue;
|
package/dist/core/actions.d.ts
CHANGED
|
@@ -55,11 +55,22 @@ export interface ConnectorOpts {
|
|
|
55
55
|
object?: string;
|
|
56
56
|
}
|
|
57
57
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
58
|
+
* The platform's 11 canonical quick-form field types (`@uipath/hitl-schema-types`
|
|
59
|
+
* `fieldType`), which the designer saves. Each has its own value shape:
|
|
60
|
+
* `integer` → a JSON integer, `date` → `'2026-10-15'`, `datetime` → an ISO
|
|
61
|
+
* date-time, `file` → a binary-format string, `object` / `array` → JSON.
|
|
61
62
|
*/
|
|
62
|
-
export type
|
|
63
|
+
export type CanonicalFormFieldType = 'string' | 'number' | 'integer' | 'float' | 'double' | 'boolean' | 'date' | 'datetime' | 'file' | 'object' | 'array';
|
|
64
|
+
/**
|
|
65
|
+
* A form field's type: one of the platform's canonical types, or `'text'` /
|
|
66
|
+
* `'date-time'`, the SDK's older spellings of `'string'` / `'datetime'` (the
|
|
67
|
+
* platform resolves both). A quick form with any other type fails the
|
|
68
|
+
* platform's validation, which is why `check` rejects it.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* hitl({ fields: [{ id: 'dueOn', type: 'date', direction: 'output' }], outcomes: ['Done'] })
|
|
72
|
+
*/
|
|
73
|
+
export type FormFieldType = CanonicalFormFieldType | 'text' | 'date-time';
|
|
63
74
|
/** A value the reviewer READS: shown on the form, filled in from the flow. */
|
|
64
75
|
export interface ShownField {
|
|
65
76
|
/** Field id — the key the answer object uses. Must be unique on the form. */
|
|
@@ -1,49 +1,94 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
2
|
+
* The quick-form field-type vocabulary: the product's own, transcribed.
|
|
3
3
|
*
|
|
4
4
|
* A quick form's field `type` is read by the product through
|
|
5
|
-
* `@uipath/hitl-schema-types` `
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
5
|
+
* `@uipath/hitl-schema-types` (`fieldType`, `resolveFieldType`,
|
|
6
|
+
* `FIELD_TYPE_TO_JSON_SCHEMA`). It has 11 canonical stored values — `string`,
|
|
7
|
+
* `number`, `integer`, `float`, `double`, `boolean`, `date`, `datetime`, `file`,
|
|
8
|
+
* `object`, `array` — and it resolves aliases onto them: `text` is a legacy
|
|
9
|
+
* alias of `string`, `date-time` of `datetime`, and .NET names such as
|
|
10
|
+
* `System.Int32` resolve too. A `quick` form whose type resolves to none of the
|
|
11
|
+
* 11 fails the product's validation.
|
|
11
12
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
13
|
+
* That package is published only to GitHub Packages, so the SDK cannot depend
|
|
14
|
+
* on it at runtime. This module is a transcription, and
|
|
15
|
+
* `tests/hitl-field-type-contract.test.ts` runs the real package against it:
|
|
16
|
+
* the canonical set, each type's JSON Schema, and every alias below must agree
|
|
17
|
+
* with the pinned `@uipath/hitl-schema-types`. A canonical-set or JSON Schema
|
|
18
|
+
* change upstream fails there; a new alias does not. The test also pins how the
|
|
19
|
+
* package resolves the spellings this module leaves out, so a change in those
|
|
20
|
+
* shows up.
|
|
17
21
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* are not a plain text box).
|
|
22
|
+
* Every SDK path reads field types from here: `check` (human tasks and inline
|
|
23
|
+
* agent quick-form escalations), decompile, and the serializers' output
|
|
24
|
+
* schemas.
|
|
22
25
|
*/
|
|
23
|
-
import type {
|
|
26
|
+
import type { CanonicalFormFieldType } from './actions.js';
|
|
27
|
+
/** The product's 11 canonical quick-form field types, in its own order. */
|
|
28
|
+
export declare const CANONICAL_FORM_FIELD_TYPES: CanonicalFormFieldType[];
|
|
29
|
+
/** The SDK's legacy spellings (`text`, `date-time`), for diagnostics that list them. */
|
|
30
|
+
export declare const LEGACY_FORM_FIELD_TYPES: string[];
|
|
31
|
+
/** Every form-field type the SDK accepts in source: the 11 canonical ones and the SDK's legacy aliases. */
|
|
32
|
+
export declare const FORM_FIELD_TYPES: string[];
|
|
33
|
+
/**
|
|
34
|
+
* The tail of a "Valid: …" diagnostic: the canonical types, then the legacy
|
|
35
|
+
* spellings in parentheses.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* validFormFieldTypesText() // 'string, number, …, array (or the older text, date-time)'
|
|
39
|
+
*/
|
|
40
|
+
export declare function validFormFieldTypesText(): string;
|
|
41
|
+
/** The product aliases, for the contract test. */
|
|
42
|
+
export declare const FORM_FIELD_TYPE_ALIASES: Readonly<Record<string, CanonicalFormFieldType>>;
|
|
43
|
+
/**
|
|
44
|
+
* The canonical type a wire or source spelling names, or `undefined` when it
|
|
45
|
+
* names none the SDK models.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* canonicalFormFieldType('integer') // 'integer'
|
|
49
|
+
* canonicalFormFieldType('text') // 'string'
|
|
50
|
+
* canonicalFormFieldType('System.Int32') // 'integer'
|
|
51
|
+
* canonicalFormFieldType('string[]') // 'array'
|
|
52
|
+
* canonicalFormFieldType('string | null') // 'string'
|
|
53
|
+
* canonicalFormFieldType('singleSelect') // undefined
|
|
54
|
+
*/
|
|
55
|
+
export declare function canonicalFormFieldType(type: unknown): CanonicalFormFieldType | undefined;
|
|
24
56
|
/**
|
|
25
|
-
* The
|
|
26
|
-
*
|
|
57
|
+
* The spelling decompile writes into source for a wire field type: a canonical
|
|
58
|
+
* type or an SDK alias stays as written, so a canvas form (`"integer"`,
|
|
59
|
+
* `"date"`) and a classic-CLI form (`"text"`) both compile back to the bytes
|
|
60
|
+
* they came from; a product alias the SDK does not accept in source
|
|
61
|
+
* (`"System.Int32"`, `"string[]"`) becomes its canonical type; anything else
|
|
62
|
+
* stays verbatim for `check` to report.
|
|
27
63
|
*
|
|
28
64
|
* @example
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
65
|
+
* sourceFormFieldType('date') // 'date'
|
|
66
|
+
* sourceFormFieldType('text') // 'text'
|
|
67
|
+
* sourceFormFieldType('System.String') // 'string'
|
|
68
|
+
* sourceFormFieldType('string[]') // 'array'
|
|
69
|
+
* sourceFormFieldType('singleSelect') // 'singleSelect'
|
|
32
70
|
*/
|
|
33
|
-
export declare function
|
|
71
|
+
export declare function sourceFormFieldType(wire: unknown): string;
|
|
34
72
|
/**
|
|
35
|
-
* Why a form-field type is refused: a product
|
|
36
|
-
*
|
|
37
|
-
* the SDK does not model
|
|
38
|
-
*
|
|
73
|
+
* Why a form-field type is refused: a product alias the SDK does not accept in
|
|
74
|
+
* source (`"System.Int32"` is the platform's .NET name for `integer`), a control
|
|
75
|
+
* spelling the platform accepts but the SDK does not model yet
|
|
76
|
+
* (`"singleSelect"`), or a type the product does not recognize at all.
|
|
77
|
+
* `unknownWhy` is the caller's reason for the last case; the default is a human
|
|
78
|
+
* task's.
|
|
39
79
|
*/
|
|
40
80
|
export declare function formFieldTypeWhy(type: unknown, unknownWhy?: string): string;
|
|
41
|
-
/** The form-field
|
|
42
|
-
export declare const FORM_FIELD_TYPES: string[];
|
|
43
|
-
/** The `suggestion` for an unknown form-field type: the nearest valid one, else `type: 'text'`. */
|
|
81
|
+
/** The `suggestion` for an unknown form-field type: its canonical type, the nearest valid one, else `type: 'string'`. */
|
|
44
82
|
export declare function formFieldTypeHint(type: unknown): string;
|
|
45
|
-
/**
|
|
46
|
-
|
|
83
|
+
/**
|
|
84
|
+
* The JSON Schema of a field's value, for the output (and escalation input)
|
|
85
|
+
* schemas the serializers write; `undefined` for a type the SDK does not model.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* formFieldJsonSchema('date') // { type: 'string', format: 'date' }
|
|
89
|
+
* formFieldJsonSchema('text') // { type: 'string' }
|
|
90
|
+
*/
|
|
91
|
+
export declare function formFieldJsonSchema(type: unknown): {
|
|
47
92
|
type: string;
|
|
48
93
|
format?: string;
|
|
49
|
-
}
|
|
94
|
+
} | undefined;
|
|
@@ -1,63 +1,197 @@
|
|
|
1
1
|
import { nearestName } from './edit-distance.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
import { ownEntry } from './own-entry.js';
|
|
3
|
+
/**
|
|
4
|
+
* Each canonical type's JSON Schema, as `FIELD_TYPE_TO_JSON_SCHEMA` gives it.
|
|
5
|
+
* `Record<CanonicalFormFieldType, …>` makes tsc refuse a missing or extra one.
|
|
6
|
+
* `float` and `double` are both `number`: JSON Schema has no precision; `file`
|
|
7
|
+
* is `format: 'binary'` (the OpenAPI convention for an upload).
|
|
8
|
+
*/
|
|
9
|
+
const CANONICAL_JSON_SCHEMA = {
|
|
10
|
+
string: { type: 'string' },
|
|
11
|
+
number: { type: 'number' },
|
|
12
|
+
integer: { type: 'integer' },
|
|
13
|
+
float: { type: 'number' },
|
|
14
|
+
double: { type: 'number' },
|
|
15
|
+
boolean: { type: 'boolean' },
|
|
16
|
+
date: { type: 'string', format: 'date' },
|
|
17
|
+
datetime: { type: 'string', format: 'date-time' },
|
|
18
|
+
file: { type: 'string', format: 'binary' },
|
|
19
|
+
object: { type: 'object' },
|
|
20
|
+
array: { type: 'array' },
|
|
21
|
+
};
|
|
22
|
+
/** The product's 11 canonical quick-form field types, in its own order. */
|
|
23
|
+
export const CANONICAL_FORM_FIELD_TYPES = Object.keys(CANONICAL_JSON_SCHEMA);
|
|
24
|
+
/**
|
|
25
|
+
* The SDK's own legacy spellings, accepted in source: `text` (what the SDK,
|
|
26
|
+
* flow-v1's serializer and `uip maestro flow hitl add` have always written) and
|
|
27
|
+
* `date-time`. The product resolves both.
|
|
28
|
+
*/
|
|
29
|
+
const SDK_ALIASES = {
|
|
30
|
+
text: 'string',
|
|
31
|
+
'date-time': 'datetime',
|
|
32
|
+
};
|
|
33
|
+
/** The SDK's legacy spellings (`text`, `date-time`), for diagnostics that list them. */
|
|
34
|
+
export const LEGACY_FORM_FIELD_TYPES = Object.keys(SDK_ALIASES);
|
|
35
|
+
/** Every form-field type the SDK accepts in source: the 11 canonical ones and the SDK's legacy aliases. */
|
|
36
|
+
export const FORM_FIELD_TYPES = [...CANONICAL_FORM_FIELD_TYPES, ...LEGACY_FORM_FIELD_TYPES];
|
|
37
|
+
/**
|
|
38
|
+
* The tail of a "Valid: …" diagnostic: the canonical types, then the legacy
|
|
39
|
+
* spellings in parentheses.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* validFormFieldTypesText() // 'string, number, …, array (or the older text, date-time)'
|
|
43
|
+
*/
|
|
44
|
+
export function validFormFieldTypesText() {
|
|
45
|
+
return `${CANONICAL_FORM_FIELD_TYPES.join(', ')} (or the older ${LEGACY_FORM_FIELD_TYPES.join(', ')})`;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The product's other data-type spellings, each with the canonical type it
|
|
49
|
+
* resolves to (`resolveFieldType` in `@uipath/hitl-schema-types` 1.2.0). The
|
|
50
|
+
* .NET names come from forms built by RPA / agent tooling. The scope-walker
|
|
51
|
+
* shapes (`union`, `intersection`, `ref`, `any`) reach `field.type` when a
|
|
52
|
+
* canvas author binds a Flow variable; they carry no narrower shape, so they
|
|
53
|
+
* resolve to `string`. `T[]` and `a | b` are matched by pattern in
|
|
54
|
+
* `canonicalFormFieldType`.
|
|
55
|
+
*
|
|
56
|
+
* Deliberately left out: the CONTROL spellings `singleSelect`, `multiSelect`
|
|
57
|
+
* and `enum` (`CONTROL_FORM_FIELD_TYPES`). The product infers a `controlType`
|
|
58
|
+
* from those, so rewriting one to its data type would change how the form
|
|
59
|
+
* renders. Decompile keeps them as written, and `check` reports them.
|
|
60
|
+
*/
|
|
61
|
+
const PRODUCT_ALIASES = {
|
|
62
|
+
...SDK_ALIASES,
|
|
63
|
+
String: 'string',
|
|
64
|
+
'System.String': 'string',
|
|
65
|
+
'System.Char': 'string',
|
|
66
|
+
Char: 'string',
|
|
10
67
|
Number: 'number',
|
|
11
|
-
|
|
68
|
+
Int32: 'integer',
|
|
69
|
+
Int64: 'integer',
|
|
70
|
+
'System.Int32': 'integer',
|
|
71
|
+
'System.Int64': 'integer',
|
|
72
|
+
'System.Byte': 'integer',
|
|
73
|
+
'System.Int16': 'integer',
|
|
74
|
+
Byte: 'integer',
|
|
75
|
+
Int16: 'integer',
|
|
76
|
+
UInt16: 'integer',
|
|
77
|
+
UInt32: 'integer',
|
|
78
|
+
UInt64: 'integer',
|
|
79
|
+
Float: 'float',
|
|
80
|
+
Single: 'float',
|
|
81
|
+
'System.Single': 'float',
|
|
82
|
+
Double: 'double',
|
|
83
|
+
Decimal: 'double',
|
|
84
|
+
'System.Double': 'double',
|
|
85
|
+
'System.Decimal': 'double',
|
|
12
86
|
Boolean: 'boolean',
|
|
13
87
|
'System.Boolean': 'boolean',
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
88
|
+
Date: 'date',
|
|
89
|
+
'System.DateOnly': 'date',
|
|
90
|
+
DateOnly: 'date',
|
|
91
|
+
dateTime: 'datetime',
|
|
92
|
+
DateTime: 'datetime',
|
|
93
|
+
'System.DateTime': 'datetime',
|
|
94
|
+
File: 'file',
|
|
95
|
+
Object: 'object',
|
|
96
|
+
DataTable: 'object',
|
|
97
|
+
QueueItem: 'object',
|
|
98
|
+
Array: 'array',
|
|
99
|
+
GenericValue: 'array',
|
|
100
|
+
list: 'array',
|
|
101
|
+
List: 'array',
|
|
102
|
+
union: 'string',
|
|
103
|
+
intersection: 'string',
|
|
104
|
+
ref: 'string',
|
|
105
|
+
any: 'string',
|
|
19
106
|
};
|
|
20
107
|
/**
|
|
21
|
-
* The
|
|
22
|
-
*
|
|
108
|
+
* The product's control spellings: it accepts them as a field `type` and infers
|
|
109
|
+
* a picker control from them (`CONTROL_FOR_DECLARED_TYPE`). The SDK does not
|
|
110
|
+
* model them yet.
|
|
111
|
+
*/
|
|
112
|
+
const CONTROL_FORM_FIELD_TYPES = ['singleSelect', 'multiSelect', 'enum'];
|
|
113
|
+
/** The product aliases, for the contract test. */
|
|
114
|
+
export const FORM_FIELD_TYPE_ALIASES = PRODUCT_ALIASES;
|
|
115
|
+
const isCanonical = (t) => typeof t === 'string' && Object.hasOwn(CANONICAL_JSON_SCHEMA, t);
|
|
116
|
+
/**
|
|
117
|
+
* The canonical type a wire or source spelling names, or `undefined` when it
|
|
118
|
+
* names none the SDK models.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* canonicalFormFieldType('integer') // 'integer'
|
|
122
|
+
* canonicalFormFieldType('text') // 'string'
|
|
123
|
+
* canonicalFormFieldType('System.Int32') // 'integer'
|
|
124
|
+
* canonicalFormFieldType('string[]') // 'array'
|
|
125
|
+
* canonicalFormFieldType('string | null') // 'string'
|
|
126
|
+
* canonicalFormFieldType('singleSelect') // undefined
|
|
127
|
+
*/
|
|
128
|
+
export function canonicalFormFieldType(type) {
|
|
129
|
+
if (isCanonical(type))
|
|
130
|
+
return type;
|
|
131
|
+
if (typeof type !== 'string')
|
|
132
|
+
return undefined;
|
|
133
|
+
// The package's own order: the two scope-walker patterns before the names.
|
|
134
|
+
if (type.endsWith('[]'))
|
|
135
|
+
return 'array';
|
|
136
|
+
if (type.includes(' | '))
|
|
137
|
+
return 'string';
|
|
138
|
+
return Object.hasOwn(PRODUCT_ALIASES, type) ? PRODUCT_ALIASES[type] : undefined;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* The spelling decompile writes into source for a wire field type: a canonical
|
|
142
|
+
* type or an SDK alias stays as written, so a canvas form (`"integer"`,
|
|
143
|
+
* `"date"`) and a classic-CLI form (`"text"`) both compile back to the bytes
|
|
144
|
+
* they came from; a product alias the SDK does not accept in source
|
|
145
|
+
* (`"System.Int32"`, `"string[]"`) becomes its canonical type; anything else
|
|
146
|
+
* stays verbatim for `check` to report.
|
|
23
147
|
*
|
|
24
148
|
* @example
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
149
|
+
* sourceFormFieldType('date') // 'date'
|
|
150
|
+
* sourceFormFieldType('text') // 'text'
|
|
151
|
+
* sourceFormFieldType('System.String') // 'string'
|
|
152
|
+
* sourceFormFieldType('string[]') // 'array'
|
|
153
|
+
* sourceFormFieldType('singleSelect') // 'singleSelect'
|
|
28
154
|
*/
|
|
29
|
-
export function
|
|
30
|
-
|
|
155
|
+
export function sourceFormFieldType(wire) {
|
|
156
|
+
if (typeof wire === 'string' && FORM_FIELD_TYPES.includes(wire))
|
|
157
|
+
return wire;
|
|
158
|
+
return canonicalFormFieldType(wire) ?? String(wire);
|
|
31
159
|
}
|
|
32
160
|
/**
|
|
33
|
-
* Why a form-field type is refused: a product
|
|
34
|
-
*
|
|
35
|
-
* the SDK does not model
|
|
36
|
-
*
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
161
|
+
* Why a form-field type is refused: a product alias the SDK does not accept in
|
|
162
|
+
* source (`"System.Int32"` is the platform's .NET name for `integer`), a control
|
|
163
|
+
* spelling the platform accepts but the SDK does not model yet
|
|
164
|
+
* (`"singleSelect"`), or a type the product does not recognize at all.
|
|
165
|
+
* `unknownWhy` is the caller's reason for the last case; the default is a human
|
|
166
|
+
* task's.
|
|
167
|
+
*/
|
|
168
|
+
export function formFieldTypeWhy(type, unknownWhy = `which is not a quick-form field type: the platform rejects the form`) {
|
|
169
|
+
const canonical = canonicalFormFieldType(type);
|
|
170
|
+
if (canonical !== undefined)
|
|
171
|
+
return `which is the platform's alias of '${canonical}' — the SDK writes '${canonical}'`;
|
|
172
|
+
if (typeof type === 'string' && CONTROL_FORM_FIELD_TYPES.includes(type)) {
|
|
173
|
+
return `which the platform accepts as a picker control but the SDK does not model yet`;
|
|
174
|
+
}
|
|
175
|
+
return unknownWhy;
|
|
44
176
|
}
|
|
45
|
-
/**
|
|
46
|
-
const FORM_FIELD_TYPE_SET = { text: true, number: true, boolean: true, 'date-time': true };
|
|
47
|
-
/** The form-field types the SDK models. */
|
|
48
|
-
export const FORM_FIELD_TYPES = Object.keys(FORM_FIELD_TYPE_SET);
|
|
49
|
-
/** The `suggestion` for an unknown form-field type: the nearest valid one, else `type: 'text'`. */
|
|
177
|
+
/** The `suggestion` for an unknown form-field type: its canonical type, the nearest valid one, else `type: 'string'`. */
|
|
50
178
|
export function formFieldTypeHint(type) {
|
|
51
|
-
const
|
|
52
|
-
if (
|
|
53
|
-
return `type: '${
|
|
179
|
+
const canonical = canonicalFormFieldType(type);
|
|
180
|
+
if (canonical !== undefined)
|
|
181
|
+
return `type: '${canonical}'`;
|
|
54
182
|
const nearest = nearestName(String(type), FORM_FIELD_TYPES);
|
|
55
|
-
return nearest !== undefined ? `type: '${nearest}'` : `type: '
|
|
183
|
+
return nearest !== undefined ? `type: '${nearest}'` : `type: 'string'`;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* The JSON Schema of a field's value, for the output (and escalation input)
|
|
187
|
+
* schemas the serializers write; `undefined` for a type the SDK does not model.
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* formFieldJsonSchema('date') // { type: 'string', format: 'date' }
|
|
191
|
+
* formFieldJsonSchema('text') // { type: 'string' }
|
|
192
|
+
*/
|
|
193
|
+
export function formFieldJsonSchema(type) {
|
|
194
|
+
const canonical = canonicalFormFieldType(type);
|
|
195
|
+
const schema = canonical === undefined ? undefined : ownEntry(CANONICAL_JSON_SCHEMA, canonical);
|
|
196
|
+
return schema === undefined ? undefined : { ...schema };
|
|
56
197
|
}
|
|
57
|
-
/** JSON-Schema type per form-field type, as flow-v1's form serializer maps them (quick-form escalations and human tasks). */
|
|
58
|
-
export const FORM_FIELD_JSON_TYPE = {
|
|
59
|
-
text: { type: 'string' },
|
|
60
|
-
number: { type: 'number' },
|
|
61
|
-
boolean: { type: 'boolean' },
|
|
62
|
-
'date-time': { type: 'string', format: 'date-time' },
|
|
63
|
-
};
|
package/dist/decompile.js
CHANGED
|
@@ -50,7 +50,7 @@ import { OUTCOME_HANDLE_NODE_TYPES } from './core/hitl-routing.js';
|
|
|
50
50
|
import { contributionPort, forwardFanOut } from './core/definition-handles.js';
|
|
51
51
|
import { STICKY_NOTE_TYPE } from './core/definitionless-node-types.js';
|
|
52
52
|
import { eventFilterFromTreeLeaf } from './core/event-filters.js';
|
|
53
|
-
import {
|
|
53
|
+
import { sourceFormFieldType } from './core/form-field-type.js';
|
|
54
54
|
/**
|
|
55
55
|
* The trigger id of the flow currently being decompiled, so a reference through a
|
|
56
56
|
* RENAMED trigger is still recognized as `input('x')` rather than falling back to
|
|
@@ -1304,7 +1304,7 @@ function emitAgentCluster(node, imp, inputNames, graph) {
|
|
|
1304
1304
|
['description', rPlain(e, 'description') !== undefined ? tsLiteral(rPlain(e, 'description')) : undefined],
|
|
1305
1305
|
['fields', rows.length ? `[${rows.map((f) => opts([
|
|
1306
1306
|
['id', tsText(f.id)],
|
|
1307
|
-
['type', tsLiteral(
|
|
1307
|
+
['type', tsLiteral(sourceFormFieldType(f.type ?? 'string'))],
|
|
1308
1308
|
['direction', tsLiteral(String(f.direction ?? 'output'))],
|
|
1309
1309
|
])).join(', ')}]` : undefined],
|
|
1310
1310
|
['app', app === undefined ? undefined : opts([
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* merge-embedded-agent — keep an EMBEDDED agent embedded when a brownfield edit
|
|
3
|
+
* touches it (flow-builder-sdk#1220).
|
|
4
|
+
*
|
|
5
|
+
* An agent node stores its configuration (prompts, model, run settings) in one
|
|
6
|
+
* of two places:
|
|
7
|
+
*
|
|
8
|
+
* - embedded: on the node itself (`inputs.systemPrompt`, `inputs.model`, …).
|
|
9
|
+
* Older Studio Web saves, and any save with the self-contained flag on.
|
|
10
|
+
* - shell: the node keeps only its structural keys (`source`,
|
|
11
|
+
* `agentInputVariables`, `agentOutputVariables`, …) and the configuration
|
|
12
|
+
* lives in `<source>/agent.json`.
|
|
13
|
+
*
|
|
14
|
+
* The runtime and Studio Web pick the copy by `hasEmbeddedAgentContent`
|
|
15
|
+
* (`@uipath/flow-schema`): any prompt string on the node makes the node win and
|
|
16
|
+
* the sidecar is never read. Since #927 compile emits only shells. So when an
|
|
17
|
+
* edit changed an embedded agent's node (an input, an output, the label), the
|
|
18
|
+
* old merge took the edited SHELL node whole, and the agent's storage form
|
|
19
|
+
* flipped: the runtime then read the project's `<source>/agent.json`, which an
|
|
20
|
+
* embedded node had been shadowing and which is often stale. On corpus fixture
|
|
21
|
+
* `01-agent-input-binding` that silently changed the model from
|
|
22
|
+
* `gpt-4o-2024-11-20` to `gpt-5.4` and emptied the system prompt.
|
|
23
|
+
*
|
|
24
|
+
* The rule here is the same delta rule merge applies everywhere: the original
|
|
25
|
+
* node, plus what the author changed (`edited` minus `baseline`). The baseline
|
|
26
|
+
* and the edited node are both shells, so the configuration keys never appear in
|
|
27
|
+
* that delta and stay exactly as the original has them. Only the structural
|
|
28
|
+
* keys the author changed are taken from the edit. Without a baseline (a two-way
|
|
29
|
+
* merge), the edited node is taken, and every key the original has that the
|
|
30
|
+
* shell does not (the configuration) is put back.
|
|
31
|
+
*
|
|
32
|
+
* A prompt or model edit in the source does NOT reach an embedded agent: it
|
|
33
|
+
* lands in the edited `<source>/agent.json`, which the embedded node shadows.
|
|
34
|
+
* Merge reports that ({@link embeddedAgentFindings}), and refuses under
|
|
35
|
+
* `strict` any merged node that would no longer carry the original's embedded
|
|
36
|
+
* configuration, or whose kept prompt names an input the node no longer
|
|
37
|
+
* declares.
|
|
38
|
+
*/
|
|
39
|
+
import type { MergeFinding } from './merge-roundtrip.js';
|
|
40
|
+
interface AgentNode {
|
|
41
|
+
id: string;
|
|
42
|
+
type: string;
|
|
43
|
+
inputs?: Record<string, unknown>;
|
|
44
|
+
[k: string]: unknown;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Whether `node` is an agent whose configuration is on the node, by
|
|
48
|
+
* `@uipath/flow-schema`'s `hasEmbeddedAgentContent`: a prompt string, or, on
|
|
49
|
+
* the voice node only, a `voice` settings object.
|
|
50
|
+
*/
|
|
51
|
+
export declare function isEmbeddedAgent(node: {
|
|
52
|
+
type?: string;
|
|
53
|
+
inputs?: Record<string, unknown>;
|
|
54
|
+
} | undefined): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* The merged node for an embedded original whose edited node is a shell: the
|
|
57
|
+
* original, plus the author's change to the node.
|
|
58
|
+
*
|
|
59
|
+
* @param orig - The original node (embedded).
|
|
60
|
+
* @param edited - The edited compile's node (a shell).
|
|
61
|
+
* @param base - The baseline compile's node, when the merge has a baseline.
|
|
62
|
+
* @returns The original node with the edit's changed structural inputs and changed top-level keys applied.
|
|
63
|
+
*/
|
|
64
|
+
export declare function mergeEmbeddedAgentNode<N extends AgentNode>(orig: N, edited: N, base: N | undefined): N;
|
|
65
|
+
/**
|
|
66
|
+
* What a merged embedded agent needs said, per original embedded agent (root
|
|
67
|
+
* and subflows, matched by scope and node id):
|
|
68
|
+
*
|
|
69
|
+
* - `agent-storage` (refuses): the merged node no longer carries the original's
|
|
70
|
+
* embedded configuration, so the runtime would read `<source>/agent.json`
|
|
71
|
+
* instead — a model or prompt change the author never wrote.
|
|
72
|
+
* - `agent-prompt-input` (refuses): a kept prompt names `{{input.X}}` but the
|
|
73
|
+
* merged node declares no input `X` (the edit removed or renamed it), so the
|
|
74
|
+
* prompt would render the placeholder empty.
|
|
75
|
+
* - `agent-embedded-edit` (warns): the author edited the node; merge applied the
|
|
76
|
+
* node change and kept the original's prompts, model and settings, so a
|
|
77
|
+
* prompt or model edit in the source did not reach this agent.
|
|
78
|
+
*
|
|
79
|
+
* @param hasBaseline - Whether the merge had a baseline. Without one, merge
|
|
80
|
+
* cannot tell the author's change from the round trip's, so the
|
|
81
|
+
* `agent-embedded-edit` warning says the node may have been edited.
|
|
82
|
+
* @param scopes - Per scope (`''` = root, otherwise the subflow key): the original, merged and edited-node-ids.
|
|
83
|
+
*/
|
|
84
|
+
export declare function embeddedAgentFindings(hasBaseline: boolean, scopes: Array<{
|
|
85
|
+
scope: string;
|
|
86
|
+
original: AgentNode[];
|
|
87
|
+
merged: AgentNode[];
|
|
88
|
+
edited: ReadonlySet<string>;
|
|
89
|
+
}>): MergeFinding[];
|
|
90
|
+
export {};
|