@uipath/maestro-builder-sdk 6.16.3 → 6.16.5

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/check.js CHANGED
@@ -3206,14 +3206,14 @@ function checkInlineAgent(step, inputs, diags, opts = {}) {
3206
3206
  : `inputs: { ${undeclared[0]}: input('${undeclared[0]}') }`);
3207
3207
  }
3208
3208
  // Direction 3: an input bound to a COMPUTED EXPRESSION rather than to one
3209
- // reference. The platform names an agent's arguments by flat-mangling the
3210
- // references it finds in the node's prompts, so an expression spanning zero or
3211
- // several references has no single argument — and therefore no name a
3212
- // `{{input.<x>}}` token could address. Its data still reaches the agent (the
3213
- // platform derives one argument per reference inside the expression), but not
3214
- // under a name the prompt can use, so the placeholder would reach the model as
3215
- // literal text. An error rather than a warning, and for the same reason
3216
- // `INLINE_AGENT_UNDECLARED_PLACEHOLDER` is one: the value never arrives.
3209
+ // reference. The platform names each of an agent's arguments after the
3210
+ // reference path it is bound to (the shell node's `agentInputVariables`), so
3211
+ // an expression spanning zero or several references has no single argument —
3212
+ // and therefore no name a `{{input.<x>}}` token could address. The compiler
3213
+ // declares no argument for it, so its value does not reach the agent, and the
3214
+ // placeholder reaches the model as literal text. An error rather than a
3215
+ // warning, and for the same reason `INLINE_AGENT_UNDECLARED_PLACEHOLDER` is
3216
+ // one: the value never arrives.
3217
3217
  for (const [name, val] of Object.entries(inputs?.inputs ?? {})) {
3218
3218
  if (!(val instanceof Expr) || val.literal)
3219
3219
  continue;
@@ -3223,11 +3223,10 @@ function checkInlineAgent(step, inputs, diags, opts = {}) {
3223
3223
  continue;
3224
3224
  at('INLINE_AGENT_COMPOSITE_INPUT', `Inline agent step "${step}"'s input \`${name}\` is bound to a computed expression `
3225
3225
  + `(\`${val.js.length > 60 ? `${val.js.slice(0, 60)}…` : val.js}\`), and a prompt references it as `
3226
- + `\`{{input.${name}}}\`. The platform does not send the agent the names you declared: it scans the `
3227
- + `node's prompts for variable references and names each argument after the REFERENCE PATH `
3228
- + `(\`$vars.a.output.b\` → \`a__output__b\`). A computed expression is not one reference, so it has no `
3229
- + `single argument to name and the placeholder cannot be substituted — it would reach the model as `
3230
- + `that literal text.`, `compute it in a script step first, then bind the step's output: `
3226
+ + `\`{{input.${name}}}\`. The platform does not send the agent the names you declared: it names each `
3227
+ + `argument after the REFERENCE PATH the input is bound to (\`$vars.a.output.b\` → \`a__output__b\`). `
3228
+ + `A computed expression is not one reference, so it gets no argument: its value does not reach the `
3229
+ + `agent, and the placeholder reaches the model as that literal text.`, `compute it in a script step first, then bind the step's output: `
3231
3230
  + `.step('${name}Value', script({ code: 'return …;' })) … inputs: { ${name}: out('${name}Value') }`);
3232
3231
  }
3233
3232
  // A step id containing `__` makes the flat name AMBIGUOUS on the platform: the
@@ -699,15 +699,24 @@ export interface ConversationalAgentInputs {
699
699
  */
700
700
  settings: ConversationalAgentSettings;
701
701
  /**
702
- * Whether the agent's reply CLOSES the exchange. The platform's legacy
703
- * default is to end it; pass `false` to keep it open for another turn.
702
+ * Whether the agent's reply CLOSES the exchange.
703
+ *
704
+ * @deprecated Has no effect and is not emitted. The platform retired the input:
705
+ * the conversational agent's v1.7 node migration removes it, and the converter
706
+ * always sends `conversationalService.endExchange = ''`. Wait-for-message and
707
+ * the end of the conversation close open exchanges.
704
708
  */
705
709
  endExchange?: boolean;
706
710
  /** Sampling temperature, 0–1. */
707
711
  temperature?: number;
708
712
  /** Max tokens in one response. */
709
713
  maxTokenPerResponse?: number;
710
- /** The model's own context ceiling — informational. */
714
+ /**
715
+ * The model's own context ceiling.
716
+ *
717
+ * @deprecated Has no effect and is not emitted. Studio Web derives it from the
718
+ * selected model.
719
+ */
711
720
  modelMaxTokens?: number;
712
721
  /** How many tool-calling rounds one turn may take, 1–100. */
713
722
  maxIterations?: number;
@@ -1407,20 +1416,19 @@ export interface InlineAgentInputs {
1407
1416
  * ```
1408
1417
  *
1409
1418
  * Why a placeholder rather than an interpolated expression: an inline agent is two
1410
- * artifacts, and its prompt exists in THREE dialects. You write one; the compiler
1411
- * emits the other two.
1419
+ * artifacts, and its prompt exists in TWO dialects. You write one; the compiler
1420
+ * emits the other into the `agent.json` sidecar. The `.flow` node carries no copy
1421
+ * of the prompt: it is a shell, so Studio Web reads the sidecar.
1412
1422
  *
1413
1423
  * 1. yours `{{input.claim}}`
1414
- * 2. the NODE's `=js:$vars.prepare.output.claimRef` ← what the platform SCANS
1415
- * 3. the AGENT.JSON `{{input.prepare__output__claimRef}}` ← what the runtime SENDS
1424
+ * 2. the AGENT.JSON `{{input.prepare__output__claimRef}}` ← what the runtime SENDS
1416
1425
  *
1417
- * The third exists because the platform does not send an agent the names you
1418
- * declared: it scans the node's prompts for `$vars.*` references and names each
1419
- * argument after the reference PATH, `__`-joined. For a flow input the two
1420
- * coincide (`$vars.notes` → `notes`); for a step output they do not, and a sidecar
1421
- * still saying `{{input.claim}}` templates against a key that is not there — the
1422
- * literal text reaches the model. See the inline-agent node reference (`website/reference/inline-agent.md`)
1423
- * §"The three prompt DIALECTS".
1426
+ * The second exists because the platform does not send an agent the names you
1427
+ * declared: it names each argument after the bound reference PATH, `__`-joined.
1428
+ * For a flow input the two coincide (`$vars.notes` → `notes`); for a step output
1429
+ * they do not, and a sidecar still saying `{{input.claim}}` templates against a key
1430
+ * that is not there — the literal text reaches the model. See the inline-agent
1431
+ * node reference (`website/reference/inline-agent.md`) §"The prompt dialects".
1424
1432
  *
1425
1433
  * **The answer's shape is `returns`, not the prompt.** `returns` becomes the node's
1426
1434
  * `agentOutputVariables` and the `agent.json` `outputSchema` — what Studio Web's
@@ -1506,7 +1514,13 @@ export interface InlineAgentInputs {
1506
1514
  temperature?: number;
1507
1515
  /** Max tokens in one response, 0–16384. */
1508
1516
  maxTokenPerResponse?: number;
1509
- /** The model's own context ceiling — informational, e.g. `128000`. */
1517
+ /**
1518
+ * The model's own context ceiling, e.g. `128000`.
1519
+ *
1520
+ * @deprecated Has no effect and is not emitted. Studio Web derives it from the
1521
+ * selected model each time the agent is opened, and the sidecar has no field
1522
+ * for it.
1523
+ */
1510
1524
  modelMaxTokens?: number;
1511
1525
  /** How many tool-calling rounds the agent may take, 1–100. */
1512
1526
  maxIterations?: number;
@@ -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);
@@ -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;
@@ -1021,6 +1023,84 @@ function connectorObjectName(configuration) {
1021
1023
  * Returns `undefined` when the node is not one of them, so the caller can fall
1022
1024
  * through to the next arm.
1023
1025
  */
1026
+ /** The `maxIterations` Studio Web writes into every inline agent's `agent.json` (flow-workbench `getDefaultAgentContent()`). */
1027
+ const STUDIO_WEB_DEFAULT_MAX_ITERATIONS = 25;
1028
+ /**
1029
+ * The agent configuration a SHELL agent node keeps in its sidecar, read from
1030
+ * `<source>/agent.json` in the node's own input names: the prompts, the model,
1031
+ * the run settings (`temperature`, `maxTokenPerResponse`, `maxIterations`,
1032
+ * `mode`), the `guardrails` and (voice) the `voice` settings. Empty when the
1033
+ * node carries prompts itself (an embedded node, e.g. a `.flow` saved by Studio
1034
+ * Web with the self-contained flag on), or when no sidecar can be read.
1035
+ *
1036
+ * A run setting equal to the default a sidecar writer fills in (`temperature`
1037
+ * 0, `maxTokens` 16384, `mode` `'standard'`) is not recovered: recompiling
1038
+ * without it writes the same sidecar, and recovering it would add an argument
1039
+ * the author never wrote to every agent. `mode: 'standard'` is the exception on
1040
+ * a 1.3 node, where naming it is what selected that definition. The same goes
1041
+ * for the inline agent's `maxIterations` 25: the SDK omits it when unset, but
1042
+ * Studio Web always writes it (its `getDefaultAgentContent()` default), so
1043
+ * every Studio Web-saved agent would otherwise decompile with `maxIterations: 25`.
1044
+ */
1045
+ function sidecarAgentInputs(node) {
1046
+ const inputs = (node.inputs ?? {});
1047
+ if (typeof inputs.systemPrompt === 'string' || typeof inputs.userPrompt === 'string')
1048
+ return {};
1049
+ const source = unwrapSource(inputs.source);
1050
+ if (!source)
1051
+ return {};
1052
+ const path = `${source}/agent.json`;
1053
+ const raw = runReadSidecar?.(path);
1054
+ if (raw === undefined) {
1055
+ warnOnce(`agent step "${node.id}" carries no prompts and ${path} was not found beside the .flow, `
1056
+ + 'so its prompts, model and run settings decompile empty. Keep <source>/agent.json beside the .flow '
1057
+ + '(download the whole project, not just the .flow).');
1058
+ return {};
1059
+ }
1060
+ let agent;
1061
+ try {
1062
+ agent = JSON.parse(raw);
1063
+ }
1064
+ catch {
1065
+ warnOnce(`agent step "${node.id}": ${path} is not valid JSON, so its prompts, model and run settings decompile empty.`);
1066
+ return {};
1067
+ }
1068
+ const messages = (Array.isArray(agent?.messages) ? agent.messages : []);
1069
+ const content = (role) => {
1070
+ const c = messages.find((m) => m.role === role)?.content;
1071
+ return typeof c === 'string' ? c : undefined;
1072
+ };
1073
+ const settings = (agent?.settings ?? {});
1074
+ const system = content('system');
1075
+ const user = content('user');
1076
+ const isVoice = node.type === T.voiceAgent;
1077
+ const numberUnless = (v, dflt) => typeof v === 'number' && v !== dflt ? v : undefined;
1078
+ // The voice agent's temperature and token cap live in `settings.voice`, not here.
1079
+ const temperature = isVoice ? undefined : numberUnless(settings.temperature, 0);
1080
+ const maxTokenPerResponse = isVoice ? undefined : numberUnless(settings.maxTokens, 16384);
1081
+ // Studio Web's default for the inline agent; the other families keep any value.
1082
+ const maxIterations = node.type === T.inlineAgent
1083
+ ? numberUnless(settings.maxIterations, STUDIO_WEB_DEFAULT_MAX_ITERATIONS)
1084
+ : typeof settings.maxIterations === 'number' ? settings.maxIterations : undefined;
1085
+ // `mode` is a harness choice on the inline agent only; the conversational and
1086
+ // voice sidecars always carry their family's fixed value. Naming it is also
1087
+ // what selects the 1.3 definition, so on a 1.3 node even `'standard'` was the
1088
+ // author's.
1089
+ const mode = node.type === T.inlineAgent && typeof settings.mode === 'string'
1090
+ && (settings.mode !== 'standard' || node.typeVersion === '1.3')
1091
+ ? settings.mode : undefined;
1092
+ return {
1093
+ ...(system === undefined ? {} : { systemPrompt: system }),
1094
+ ...(user === undefined ? {} : { userPrompt: user }),
1095
+ ...(typeof settings.model === 'string' ? { model: settings.model } : {}),
1096
+ ...(temperature === undefined ? {} : { temperature }),
1097
+ ...(maxTokenPerResponse === undefined ? {} : { maxTokenPerResponse }),
1098
+ ...(maxIterations === undefined ? {} : { maxIterations }),
1099
+ ...(mode === undefined ? {} : { mode }),
1100
+ ...(Array.isArray(agent?.guardrails) && agent.guardrails.length > 0 ? { guardrails: agent.guardrails } : {}),
1101
+ ...(isVoice && settings.voice && typeof settings.voice === 'object' ? { voice: settings.voice } : {}),
1102
+ };
1103
+ }
1024
1104
  /**
1025
1105
  * An AGENT and its attached resources — the inline autonomous agent, the
1026
1106
  * conversational agent, and the voice agent.
@@ -1038,7 +1118,8 @@ function connectorObjectName(configuration) {
1038
1118
  * preserved exactly; only these logical names change.)
1039
1119
  */
1040
1120
  function emitAgentCluster(node, imp, inputNames, graph) {
1041
- const i = (node.inputs ?? {});
1121
+ // A key on the node wins over the sidecar's copy of it.
1122
+ const i = { ...sidecarAgentInputs(node), ...(node.inputs ?? {}) };
1042
1123
  const plain = (v) => {
1043
1124
  const raw = unwrapSource(v);
1044
1125
  return raw === undefined || raw === '' ? undefined : raw;
@@ -1047,10 +1128,12 @@ function emitAgentCluster(node, imp, inputNames, graph) {
1047
1128
  const raw = unwrapPlain(v);
1048
1129
  return typeof raw === 'number' ? String(raw) : undefined;
1049
1130
  };
1050
- // Prompts: invert `renderInlineAgentPrompt`. It replaced each
1051
- // `{{input.<name>}}` with that input's rendered binding, so the bindings in
1052
- // `agentInputVariables` are exactly what to put back — longest first, so a
1053
- // shorter binding cannot eat a longer one's prefix.
1131
+ // Prompts. A sidecar prompt already speaks `{{input.<flatName>}}`, so this
1132
+ // leaves it alone. An EMBEDDED node's prompt (Studio Web with the
1133
+ // self-contained flag on, or an SDK before #927) carries each input as its
1134
+ // rendered binding instead; the bindings in `agentInputVariables` are exactly
1135
+ // what to put back — longest first, so a shorter binding cannot eat a longer
1136
+ // one's prefix.
1054
1137
  const vars = (Array.isArray(i.agentInputVariables) ? i.agentInputVariables : []);
1055
1138
  const refs = vars
1056
1139
  .filter((v) => typeof v.id === 'string' && typeof v.binding === 'string')
@@ -1312,10 +1395,8 @@ function emitAgentCluster(node, imp, inputNames, graph) {
1312
1395
  // `settings` is required on ConversationalAgentInputs, so an empty one
1313
1396
  // stays as `{}`, which check then reports as CONV_AGENT_NO_TURN.
1314
1397
  ['settings', settingsSrc || '{}'],
1315
- ['endExchange', unwrapPlain(i.endExchange) === false ? 'false' : undefined],
1316
1398
  ['temperature', num(i.temperature)],
1317
1399
  ['maxTokenPerResponse', num(i.maxTokenPerResponse)],
1318
- ['modelMaxTokens', num(i.modelMaxTokens)],
1319
1400
  ['maxIterations', num(i.maxIterations)],
1320
1401
  ['guardrails', guardrails],
1321
1402
  ['source', str(plain(i.source) ?? '')],
@@ -1329,7 +1410,6 @@ function emitAgentCluster(node, imp, inputNames, graph) {
1329
1410
  ['returns', returns],
1330
1411
  ['temperature', num(i.temperature)],
1331
1412
  ['maxTokenPerResponse', num(i.maxTokenPerResponse)],
1332
- ['modelMaxTokens', num(i.modelMaxTokens)],
1333
1413
  ['maxIterations', num(i.maxIterations)],
1334
1414
  ['mode', plain(i.mode) !== undefined ? str(plain(i.mode)) : undefined],
1335
1415
  ['guardrails', guardrails],
@@ -2616,6 +2696,7 @@ export function decompile(flow, options = {}) {
2616
2696
  const importSpecifier = options.importSpecifier ?? './flow-sdk.js';
2617
2697
  runStrict = options.bestEffort === false;
2618
2698
  runWarn = options.warn;
2699
+ runReadSidecar = options.readSidecar;
2619
2700
  runWarned = new Set();
2620
2701
  runDefPairs = new Set((flow.definitions ?? [])
2621
2702
  .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
- * The `=js:` test is the same one `renderInlineAgentPrompt` uses, deliberately:
2208
- * both halves of the emission must agree about what is an expression, and a
2209
- * literal string that happens to begin with `=js:` is already treated as one
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,29 +5101,35 @@ 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`.
5114
+ //
5115
+ // The run settings (`mode`, `temperature`, `maxTokenPerResponse`,
5116
+ // `maxIterations`, `guardrails`) live in the sidecar too. The node keeps
5117
+ // exactly the keys Studio Web's own strip keeps (`toAgentShellInputs`,
5118
+ // @uipath/flow-schema): anything else is discarded on hydrate, and while
5119
+ // present it makes Studio Web "trust the .flow" when the sidecar folder is
5120
+ // missing (`flowNodeHasRealInputs`), flushing a prompt-less agent.json.
5121
+ // `modelMaxTokens` is written nowhere: the designer derives it from the
5122
+ // selected model.
5139
5123
  node.inputs = {
5140
5124
  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
- ...(s.mode === undefined ? {} : { mode: s.mode }),
5148
- ...(s.temperature === undefined ? {} : { temperature: s.temperature }),
5149
- ...(s.maxTokenPerResponse === undefined ? {} : { maxTokenPerResponse: s.maxTokenPerResponse }),
5150
- ...(s.modelMaxTokens === undefined ? {} : { modelMaxTokens: s.modelMaxTokens }),
5151
- ...(s.maxIterations === undefined ? {} : { maxIterations: s.maxIterations }),
5152
- ...(s.guardrails === undefined ? {} : { guardrails: s.guardrails }),
5153
5125
  // The two DESCRIPTOR ARRAYS. `agentInputVariables` entries carry the
5154
5126
  // binding expression; `agentOutputVariables` entries are name + type only,
5155
5127
  // and the runtime's structured final call fills exactly these keys.
5156
5128
  //
5157
- // `id` is the FLAT NAME, not the author's — the platform re-derives this
5158
- // array from the node's prompts and keeps a pre-existing entry only when
5159
- // its id already IS a flatName (`deriveAgentInputVariables:506-509`). One
5160
- // entry per flatName, so two logical names bound to the same reference
5161
- // claim one argument rather than two.
5129
+ // `id` is the FLAT NAME, not the author's — the name the runtime's
5130
+ // JobArguments are keyed by, and the key the CLI reconciles against the
5131
+ // sidecar's `inputSchema`. One entry per flatName, so two logical names
5132
+ // bound to the same reference claim one argument rather than two.
5162
5133
  agentInputVariables: plan.refs.map((r) => ({
5163
5134
  id: r.flatName,
5164
5135
  type: 'string',
@@ -5727,19 +5698,15 @@ export function serialize(built, opts = {}) {
5727
5698
  if (v !== undefined)
5728
5699
  settings[key] = v;
5729
5700
  }
5701
+ // A SHELL node, like the inline agent's (#927): exactly the keys
5702
+ // `toAgentShellInputs` keeps. The system prompt, the model and the run
5703
+ // settings live only in the sidecar (`metadata.isConversational` there is
5704
+ // the family flag). `endExchange` is written nowhere: the platform retired
5705
+ // it (the node's v1.7 migration drops it, and the converter always sends
5706
+ // `conversationalService.endExchange = ''`).
5730
5707
  node.inputs = {
5731
5708
  source,
5732
- systemPrompt: s.systemPrompt,
5733
- model: s.model,
5734
- // The family's own flag — every instance of this node IS conversational.
5735
- isConversational: true,
5736
5709
  conversationalAgentSettings: settings,
5737
- ...(s.endExchange === undefined ? {} : { endExchange: s.endExchange }),
5738
- ...(s.temperature === undefined ? {} : { temperature: s.temperature }),
5739
- ...(s.maxTokenPerResponse === undefined ? {} : { maxTokenPerResponse: s.maxTokenPerResponse }),
5740
- ...(s.modelMaxTokens === undefined ? {} : { modelMaxTokens: s.modelMaxTokens }),
5741
- ...(s.maxIterations === undefined ? {} : { maxIterations: s.maxIterations }),
5742
- ...(s.guardrails === undefined ? {} : { guardrails: s.guardrails }),
5743
5710
  };
5744
5711
  scope.nodes.push(node);
5745
5712
  sidecars.push({
@@ -5797,15 +5764,16 @@ export function serialize(built, opts = {}) {
5797
5764
  delete node.model;
5798
5765
  const nodeInputs = s.inputs ?? {};
5799
5766
  const plan = agentInputPlan(nodeInputs, scope.rename);
5767
+ // A SHELL node (#927): the system prompt and the `voice` settings live only
5768
+ // in the sidecar's `messages` and `settings.voice`. On a voice node either
5769
+ // one makes Studio Web treat the `.flow` as authoritative and skip the
5770
+ // sidecar (`hasEmbeddedAgentContent`). `uip maestro flow debug` builds the
5771
+ // voice agent from the sidecar (`packageInlineAgents`).
5772
+ // The node keeps exactly the keys `toAgentShellInputs` keeps;
5773
+ // `maxIterations` and `metadata.isConversational` are in the sidecar.
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
- // The platform's own flag for this family — every voice agent IS
5805
- // conversational, and the definition declares the field.
5806
- isConversational: true,
5807
- ...(s.maxIterations === undefined ? {} : { maxIterations: s.maxIterations }),
5808
- ...(s.voice === undefined ? {} : { voice: { ...s.voice } }),
5809
5777
  ...(plan.refs.length === 0 ? {} : {
5810
5778
  agentInputVariables: plan.refs.map((r) => ({
5811
5779
  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",
3
+ "version": "6.16.5",
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": "c6b0cc7e26df31a2699ad9b67f3b5a9e2532bcd4"
95
+ "gitref": "b6731e22dc81fb2ca34f4463bc1785aaae16d174"
96
96
  }