@uipath/maestro-builder-sdk 6.16.3 → 6.16.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api-index.md +68 -68
- package/dist/api-members.md +165 -165
- package/dist/core/actions.d.ts +11 -12
- package/dist/decompile-cli.js +10 -1
- package/dist/decompile.d.ts +11 -0
- package/dist/decompile.js +49 -1
- package/dist/serialize.js +25 -53
- package/package.json +2 -2
package/dist/core/actions.d.ts
CHANGED
|
@@ -1407,20 +1407,19 @@ export interface InlineAgentInputs {
|
|
|
1407
1407
|
* ```
|
|
1408
1408
|
*
|
|
1409
1409
|
* Why a placeholder rather than an interpolated expression: an inline agent is two
|
|
1410
|
-
* artifacts, and its prompt exists in
|
|
1411
|
-
* emits the other
|
|
1410
|
+
* artifacts, and its prompt exists in TWO dialects. You write one; the compiler
|
|
1411
|
+
* emits the other into the `agent.json` sidecar. The `.flow` node carries no copy
|
|
1412
|
+
* of the prompt: it is a shell, so Studio Web reads the sidecar.
|
|
1412
1413
|
*
|
|
1413
1414
|
* 1. yours `{{input.claim}}`
|
|
1414
|
-
* 2. the
|
|
1415
|
-
*
|
|
1416
|
-
*
|
|
1417
|
-
*
|
|
1418
|
-
*
|
|
1419
|
-
*
|
|
1420
|
-
*
|
|
1421
|
-
*
|
|
1422
|
-
* literal text reaches the model. See the inline-agent node reference (`website/reference/inline-agent.md`)
|
|
1423
|
-
* §"The three prompt DIALECTS".
|
|
1415
|
+
* 2. the AGENT.JSON `{{input.prepare__output__claimRef}}` ← what the runtime SENDS
|
|
1416
|
+
*
|
|
1417
|
+
* The second exists because the platform does not send an agent the names you
|
|
1418
|
+
* declared: it names each argument after the bound reference PATH, `__`-joined.
|
|
1419
|
+
* For a flow input the two coincide (`$vars.notes` → `notes`); for a step output
|
|
1420
|
+
* they do not, and a sidecar still saying `{{input.claim}}` templates against a key
|
|
1421
|
+
* that is not there — the literal text reaches the model. See the inline-agent
|
|
1422
|
+
* node reference (`website/reference/inline-agent.md`) §"The prompt dialects".
|
|
1424
1423
|
*
|
|
1425
1424
|
* **The answer's shape is `returns`, not the prompt.** `returns` becomes the node's
|
|
1426
1425
|
* `agentOutputVariables` and the `agent.json` `outputSchema` — what Studio Web's
|
package/dist/decompile-cli.js
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
*/
|
|
20
20
|
import { reportResult } from './cli-result.js';
|
|
21
21
|
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
22
|
-
import { basename, join, resolve } from 'node:path';
|
|
22
|
+
import { basename, dirname, join, resolve } from 'node:path';
|
|
23
23
|
import { defaultSourceOut, workDirBeside, writeSource } from './workdir.js';
|
|
24
24
|
import { decompile } from './decompile.js';
|
|
25
25
|
import { resolveFlowRefs } from './ref-resolve.js';
|
|
@@ -65,6 +65,15 @@ export function run(argv) {
|
|
|
65
65
|
// writable band) go to stderr, where the agent running the brownfield loop
|
|
66
66
|
// reads them before compile refuses.
|
|
67
67
|
warn: (message) => console.error(`flow-decompile: warning: ${message}`),
|
|
68
|
+
// A shell agent node's prompts live in `<source>/agent.json` beside the .flow.
|
|
69
|
+
readSidecar: (relativePath) => {
|
|
70
|
+
try {
|
|
71
|
+
return readFileSync(join(dirname(resolve(pos)), relativePath), 'utf8');
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
},
|
|
68
77
|
});
|
|
69
78
|
const out = opt(argv, '-o') ?? defaultSourceOut(`${baseName(flow)}.flow.ts`);
|
|
70
79
|
writeSource(out, ts);
|
package/dist/decompile.d.ts
CHANGED
|
@@ -133,6 +133,17 @@ export interface DecompileOptions {
|
|
|
133
133
|
* `compile` will refuse it). The CLI prints these on stderr.
|
|
134
134
|
*/
|
|
135
135
|
warn?: (message: string) => void;
|
|
136
|
+
/**
|
|
137
|
+
* Reads a file of the flow's project, by path relative to the `.flow`'s
|
|
138
|
+
* directory; returns `undefined` when it is absent. Used for an agent node
|
|
139
|
+
* that is a SHELL (no prompts on the node, the shape compile writes since
|
|
140
|
+
* #927): its prompts, model and voice settings are read back from
|
|
141
|
+
* `<source>/agent.json`. The sidecar speaks flat input names
|
|
142
|
+
* (`{{input.start__output__notes}}`), so the recovered source declares its
|
|
143
|
+
* inputs under those names — the same flow, not the same spelling. Without a
|
|
144
|
+
* reader, a shell agent decompiles with empty prompts and a warning.
|
|
145
|
+
*/
|
|
146
|
+
readSidecar?: (relativePath: string) => string | undefined;
|
|
136
147
|
}
|
|
137
148
|
export declare function decompile(flow: FlowFile, options?: DecompileOptions): string;
|
|
138
149
|
export {};
|
package/dist/decompile.js
CHANGED
|
@@ -79,6 +79,8 @@ let runStrict = false;
|
|
|
79
79
|
/** `DecompileOptions.warn` for the current run, and the messages already sent to it (one line per finding). */
|
|
80
80
|
let runWarn;
|
|
81
81
|
let runWarned = new Set();
|
|
82
|
+
/** `DecompileOptions.readSidecar` for the current run. */
|
|
83
|
+
let runReadSidecar;
|
|
82
84
|
function warnOnce(message) {
|
|
83
85
|
if (runWarned.has(message))
|
|
84
86
|
return;
|
|
@@ -1037,8 +1039,53 @@ function connectorObjectName(configuration) {
|
|
|
1037
1039
|
* arguments reach the model, spelled the platform's way. (Node ids are
|
|
1038
1040
|
* preserved exactly; only these logical names change.)
|
|
1039
1041
|
*/
|
|
1042
|
+
/**
|
|
1043
|
+
* The agent configuration a SHELL agent node keeps in its sidecar: the prompts,
|
|
1044
|
+
* the model and (voice) the `voice` settings, read from `<source>/agent.json`
|
|
1045
|
+
* in the node's own input names. Empty when the node carries prompts itself (an
|
|
1046
|
+
* embedded node, e.g. a `.flow` saved by Studio Web with the self-contained
|
|
1047
|
+
* flag on), or when no sidecar can be read.
|
|
1048
|
+
*/
|
|
1049
|
+
function sidecarAgentInputs(node) {
|
|
1050
|
+
const inputs = (node.inputs ?? {});
|
|
1051
|
+
if (typeof inputs.systemPrompt === 'string' || typeof inputs.userPrompt === 'string')
|
|
1052
|
+
return {};
|
|
1053
|
+
const source = unwrapSource(inputs.source);
|
|
1054
|
+
if (!source)
|
|
1055
|
+
return {};
|
|
1056
|
+
const path = `${source}/agent.json`;
|
|
1057
|
+
const raw = runReadSidecar?.(path);
|
|
1058
|
+
if (raw === undefined) {
|
|
1059
|
+
warnOnce(`agent step "${node.id}" carries no prompts and ${path} was not found beside the .flow, `
|
|
1060
|
+
+ 'so its prompts and model decompile empty. Decompile the .flow from inside its project directory.');
|
|
1061
|
+
return {};
|
|
1062
|
+
}
|
|
1063
|
+
let agent;
|
|
1064
|
+
try {
|
|
1065
|
+
agent = JSON.parse(raw);
|
|
1066
|
+
}
|
|
1067
|
+
catch {
|
|
1068
|
+
warnOnce(`agent step "${node.id}": ${path} is not valid JSON, so its prompts and model decompile empty.`);
|
|
1069
|
+
return {};
|
|
1070
|
+
}
|
|
1071
|
+
const messages = (Array.isArray(agent?.messages) ? agent.messages : []);
|
|
1072
|
+
const content = (role) => {
|
|
1073
|
+
const c = messages.find((m) => m.role === role)?.content;
|
|
1074
|
+
return typeof c === 'string' ? c : undefined;
|
|
1075
|
+
};
|
|
1076
|
+
const settings = (agent?.settings ?? {});
|
|
1077
|
+
const system = content('system');
|
|
1078
|
+
const user = content('user');
|
|
1079
|
+
return {
|
|
1080
|
+
...(system === undefined ? {} : { systemPrompt: system }),
|
|
1081
|
+
...(user === undefined ? {} : { userPrompt: user }),
|
|
1082
|
+
...(typeof settings.model === 'string' ? { model: settings.model } : {}),
|
|
1083
|
+
...(node.type === T.voiceAgent && settings.voice && typeof settings.voice === 'object' ? { voice: settings.voice } : {}),
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1040
1086
|
function emitAgentCluster(node, imp, inputNames, graph) {
|
|
1041
|
-
|
|
1087
|
+
// A key on the node wins over the sidecar's copy of it.
|
|
1088
|
+
const i = { ...sidecarAgentInputs(node), ...(node.inputs ?? {}) };
|
|
1042
1089
|
const plain = (v) => {
|
|
1043
1090
|
const raw = unwrapSource(v);
|
|
1044
1091
|
return raw === undefined || raw === '' ? undefined : raw;
|
|
@@ -2616,6 +2663,7 @@ export function decompile(flow, options = {}) {
|
|
|
2616
2663
|
const importSpecifier = options.importSpecifier ?? './flow-sdk.js';
|
|
2617
2664
|
runStrict = options.bestEffort === false;
|
|
2618
2665
|
runWarn = options.warn;
|
|
2666
|
+
runReadSidecar = options.readSidecar;
|
|
2619
2667
|
runWarned = new Set();
|
|
2620
2668
|
runDefPairs = new Set((flow.definitions ?? [])
|
|
2621
2669
|
.filter((d) => typeof d?.nodeType === 'string' && typeof d?.version === 'string')
|
package/dist/serialize.js
CHANGED
|
@@ -2204,10 +2204,9 @@ function inlineAgentDef(spec) {
|
|
|
2204
2204
|
/**
|
|
2205
2205
|
* Classify a RENDERED input value (the output of {@link renderValue}).
|
|
2206
2206
|
*
|
|
2207
|
-
*
|
|
2208
|
-
*
|
|
2209
|
-
*
|
|
2210
|
-
* there.
|
|
2207
|
+
* A rendered value is an expression exactly when it starts with `=js:` — the
|
|
2208
|
+
* same test the rest of the serializer applies, so a literal string that
|
|
2209
|
+
* happens to begin with `=js:` is treated as one everywhere.
|
|
2211
2210
|
*/
|
|
2212
2211
|
function classifyAgentInput(rendered) {
|
|
2213
2212
|
if (typeof rendered !== 'string' || !rendered.startsWith('=js:')) {
|
|
@@ -2471,40 +2470,6 @@ function promptTokens(content) {
|
|
|
2471
2470
|
tokens.push({ type: 'simpleText', rawString: content.slice(last) });
|
|
2472
2471
|
return tokens.length ? tokens : [{ type: 'simpleText', rawString: content }];
|
|
2473
2472
|
}
|
|
2474
|
-
/**
|
|
2475
|
-
* Render an inline agent's prompt for the NODE, which speaks a different dialect
|
|
2476
|
-
* from the `agent.json`.
|
|
2477
|
-
*
|
|
2478
|
-
* The author writes `{{input.<name>}}`, which is what the agent's own template
|
|
2479
|
-
* language uses and what goes into `agent.json` verbatim. The node's copy has to
|
|
2480
|
-
* carry the FLOW expression instead: flow-v1's `preDeriveAgentInputDefinitions`
|
|
2481
|
-
* builds the deployed input list by scanning the node's prompts for `$vars.*`
|
|
2482
|
-
* references, and — when its caller prunes — drops any `agentInputVariables` entry no
|
|
2483
|
-
* such reference points at. A prompt with no references can therefore deploy an agent
|
|
2484
|
-
* that receives nothing, with the authored list sitting in the file unused.
|
|
2485
|
-
*
|
|
2486
|
-
* So each placeholder becomes the rendered binding of that input, `=js:`-prefixed the
|
|
2487
|
-
* way an embedded expression is read. One caveat that comes with that encoding:
|
|
2488
|
-
* an embedded run has no terminator, so it is read to
|
|
2489
|
-
* end-of-line and then backed off token by token until a prefix evaluates. That
|
|
2490
|
-
* resolves `"Notes: =js:$vars.notes and then some"` correctly, but a placeholder
|
|
2491
|
-
* followed by more text on the same line is doing more work than one at end of line.
|
|
2492
|
-
*
|
|
2493
|
-
* A placeholder naming something `inputs` does not declare is left ALONE rather than
|
|
2494
|
-
* silently deleted: it reaches the model as literal `{{input.x}}`, which is visible,
|
|
2495
|
-
* and `check` names it.
|
|
2496
|
-
*/
|
|
2497
|
-
function renderInlineAgentPrompt(template, inputs, rename) {
|
|
2498
|
-
return template.replace(INPUT_PLACEHOLDER, (whole, name) => {
|
|
2499
|
-
if (!Object.prototype.hasOwnProperty.call(inputs, name))
|
|
2500
|
-
return whole;
|
|
2501
|
-
const rendered = renderValue(inputs[name], rename);
|
|
2502
|
-
// A literal binding needs no expression at all — inline the value.
|
|
2503
|
-
if (typeof rendered === 'string' && rendered.startsWith('=js:'))
|
|
2504
|
-
return rendered;
|
|
2505
|
-
return String(rendered);
|
|
2506
|
-
});
|
|
2507
|
-
}
|
|
2508
2473
|
/**
|
|
2509
2474
|
* The parts every `uipath.ixp.*` definition shares, bundled verbatim from
|
|
2510
2475
|
* `uip maestro flow registry get` (2026-07-31, after `registry pull --force`).
|
|
@@ -5136,14 +5101,18 @@ export function serialize(built, opts = {}) {
|
|
|
5136
5101
|
// What the PLATFORM will call each of these — computed once and shared by
|
|
5137
5102
|
// the descriptor array below and the sidecar. See `agentInputPlan`.
|
|
5138
5103
|
const plan = agentInputPlan(nodeInputs, scope.rename);
|
|
5104
|
+
// A SHELL node (#927): the prompts and the model live only in the
|
|
5105
|
+
// `<source>/agent.json` sidecar written below, never on the node. Studio
|
|
5106
|
+
// Web decides which copy wins by `hasEmbeddedAgentContent`
|
|
5107
|
+
// (@uipath/flow-schema): any `systemPrompt`/`userPrompt` string on the node
|
|
5108
|
+
// makes the `.flow` authoritative and the sidecar is skipped, so a node copy
|
|
5109
|
+
// shadowed the sidecar and lost the input tokens and the tool configuration
|
|
5110
|
+
// on the first save. With no prompt strings the converter also keeps the
|
|
5111
|
+
// `agentInputVariables` below as written (`canPruneAgentInputs` is false),
|
|
5112
|
+
// and `uip maestro flow debug` reconciles them against the sidecar's
|
|
5113
|
+
// `inputSchema` — the shape the v1 skill and `uip agent refresh` write.
|
|
5139
5114
|
node.inputs = {
|
|
5140
5115
|
source,
|
|
5141
|
-
// The NODE's dialect: `{{input.x}}` → the flow expression, so flow-v1's
|
|
5142
|
-
// input-derivation pre-pass can see the reference. See
|
|
5143
|
-
// `renderInlineAgentPrompt`.
|
|
5144
|
-
systemPrompt: renderInlineAgentPrompt(s.systemPrompt, nodeInputs, scope.rename),
|
|
5145
|
-
userPrompt: renderInlineAgentPrompt(s.userPrompt, nodeInputs, scope.rename),
|
|
5146
|
-
model: s.model,
|
|
5147
5116
|
...(s.mode === undefined ? {} : { mode: s.mode }),
|
|
5148
5117
|
...(s.temperature === undefined ? {} : { temperature: s.temperature }),
|
|
5149
5118
|
...(s.maxTokenPerResponse === undefined ? {} : { maxTokenPerResponse: s.maxTokenPerResponse }),
|
|
@@ -5154,11 +5123,10 @@ export function serialize(built, opts = {}) {
|
|
|
5154
5123
|
// binding expression; `agentOutputVariables` entries are name + type only,
|
|
5155
5124
|
// and the runtime's structured final call fills exactly these keys.
|
|
5156
5125
|
//
|
|
5157
|
-
// `id` is the FLAT NAME, not the author's — the
|
|
5158
|
-
//
|
|
5159
|
-
//
|
|
5160
|
-
//
|
|
5161
|
-
// claim one argument rather than two.
|
|
5126
|
+
// `id` is the FLAT NAME, not the author's — the name the runtime's
|
|
5127
|
+
// JobArguments are keyed by, and the key the CLI reconciles against the
|
|
5128
|
+
// sidecar's `inputSchema`. One entry per flatName, so two logical names
|
|
5129
|
+
// bound to the same reference claim one argument rather than two.
|
|
5162
5130
|
agentInputVariables: plan.refs.map((r) => ({
|
|
5163
5131
|
id: r.flatName,
|
|
5164
5132
|
type: 'string',
|
|
@@ -5727,10 +5695,11 @@ export function serialize(built, opts = {}) {
|
|
|
5727
5695
|
if (v !== undefined)
|
|
5728
5696
|
settings[key] = v;
|
|
5729
5697
|
}
|
|
5698
|
+
// A SHELL node, like the inline agent's (#927): the system prompt and the
|
|
5699
|
+
// model live only in the sidecar, so Studio Web reads the sidecar instead
|
|
5700
|
+
// of letting a node copy shadow it.
|
|
5730
5701
|
node.inputs = {
|
|
5731
5702
|
source,
|
|
5732
|
-
systemPrompt: s.systemPrompt,
|
|
5733
|
-
model: s.model,
|
|
5734
5703
|
// The family's own flag — every instance of this node IS conversational.
|
|
5735
5704
|
isConversational: true,
|
|
5736
5705
|
conversationalAgentSettings: settings,
|
|
@@ -5797,15 +5766,18 @@ export function serialize(built, opts = {}) {
|
|
|
5797
5766
|
delete node.model;
|
|
5798
5767
|
const nodeInputs = s.inputs ?? {};
|
|
5799
5768
|
const plan = agentInputPlan(nodeInputs, scope.rename);
|
|
5769
|
+
// A SHELL node (#927): the system prompt and the `voice` settings live only
|
|
5770
|
+
// in the sidecar's `messages` and `settings.voice`. On a voice node either
|
|
5771
|
+
// one makes Studio Web treat the `.flow` as authoritative and skip the
|
|
5772
|
+
// sidecar (`hasEmbeddedAgentContent`). `uip maestro flow debug` builds the
|
|
5773
|
+
// voice agent from the sidecar (`packageInlineAgents`).
|
|
5800
5774
|
node.inputs = {
|
|
5801
5775
|
source,
|
|
5802
|
-
systemPrompt: renderInlineAgentPrompt(s.systemPrompt, nodeInputs, scope.rename),
|
|
5803
5776
|
callContext: renderValue(toExpr(s.callContext), scope.rename),
|
|
5804
5777
|
// The platform's own flag for this family — every voice agent IS
|
|
5805
5778
|
// conversational, and the definition declares the field.
|
|
5806
5779
|
isConversational: true,
|
|
5807
5780
|
...(s.maxIterations === undefined ? {} : { maxIterations: s.maxIterations }),
|
|
5808
|
-
...(s.voice === undefined ? {} : { voice: { ...s.voice } }),
|
|
5809
5781
|
...(plan.refs.length === 0 ? {} : {
|
|
5810
5782
|
agentInputVariables: plan.refs.map((r) => ({
|
|
5811
5783
|
id: r.flatName,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/maestro-builder-sdk",
|
|
3
|
-
"version": "6.16.
|
|
3
|
+
"version": "6.16.4",
|
|
4
4
|
"description": "Build UiPath Flow, Case, and BPMN artifacts by writing TypeScript.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://docs.uipath.com/maestro",
|
|
@@ -92,5 +92,5 @@
|
|
|
92
92
|
"@types/node": "^22.7.0",
|
|
93
93
|
"esbuild": "^0.28.1"
|
|
94
94
|
},
|
|
95
|
-
"gitref": "
|
|
95
|
+
"gitref": "eac0393e29eed1fe0992c8923b88964e50483eaf"
|
|
96
96
|
}
|