@uipath/maestro-builder-sdk 6.32.8 → 6.33.1

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/decompile.js CHANGED
@@ -38,6 +38,7 @@ import { commentText } from './core/comment-text.js';
38
38
  import { tsLiteral, tsNumber, tsText } from './core/ts-literal.js';
39
39
  import { ownEntry } from './core/own-entry.js';
40
40
  import { CONTEXT_INDEX_DEFAULTS, CONTEXT_INDEX_DEFAULT_FILE_EXTENSION, contextIndexSlug, parseContextIndexType, } from './core/context-index.js';
41
+ import { derivedContextSource, derivedEscalationSource, derivedResourceNodeId, derivedToolSource, } from './core/agent-resource-identity.js';
41
42
  import { wireExprBody } from './core/wire-expr.js';
42
43
  import { hasExits } from './core/step-ports.js';
43
44
  import { parseIxpProjectType } from './core/actions.js';
@@ -107,6 +108,12 @@ let runWarned = new Set();
107
108
  * `.layout()` key, must use the id compile will produce, not the file's.
108
109
  */
109
110
  let runAbsorbed = new Map();
111
+ /**
112
+ * The id the recompiled flow will have: the `flow(...)` argument decompile
113
+ * writes. Compile derives a resource's directory from it, so decompile needs it
114
+ * to tell a derived directory from one the file chose.
115
+ */
116
+ let runFlowId = 'flow';
110
117
  /** `DecompileOptions.readSidecar` for the current run. */
111
118
  let runReadSidecar;
112
119
  function warnOnce(message) {
@@ -1160,20 +1167,45 @@ function emitAgentCluster(node, imp, inputNames, graph) {
1160
1167
  // spec order is this edge order: the first is `<agent><Kind>`, the n-th
1161
1168
  // `<agent><Kind><n>` (claimId's dedupe). Only the first memory is recovered,
1162
1169
  // so every further memory maps to `undefined`.
1170
+ //
1171
+ // When a port's nodes do not ALL carry those ids (the canvas or the CLI named
1172
+ // them), every resource on the port is written with its own `nodeId`, and
1173
+ // compile keeps the file's ids. All of them, not only the odd one: compile
1174
+ // numbers the derived ids in order, so a derived id after an explicit one
1175
+ // would come out one lower than the file's.
1163
1176
  // This reads the edges directly, not through `resource()`: it must see EVERY
1164
1177
  // artifact edge, including ones the spec does not carry, and it must not
1165
1178
  // account for any edge.
1179
+ const keepIds = new Set();
1166
1180
  for (const [port, kind, emittedCount] of [
1167
1181
  ['context', 'Context', Infinity], ['tool', 'Tool', Infinity],
1168
1182
  ['escalation', 'Escalation', Infinity], ['memory', 'Memory', 1],
1169
1183
  ]) {
1170
- const base = `${node.id}${kind}`.replace(/[^A-Za-z0-9_]/g, '_');
1171
- (graph?.outEdges(node.id) ?? [])
1184
+ const targets = (graph?.outEdges(node.id) ?? [])
1172
1185
  .filter((e) => e.sourcePort === port && graph.byId.has(e.targetNodeId))
1173
- .forEach((e, k) => {
1174
- runAbsorbed.set(e.targetNodeId, k >= emittedCount ? undefined : k === 0 ? base : `${base}${k + 1}`);
1186
+ .map((e) => e.targetNodeId);
1187
+ const keep = port !== 'memory'
1188
+ && targets.some((id, k) => id !== derivedResourceNodeId(node.id, kind, k));
1189
+ targets.forEach((id, k) => {
1190
+ if (keep)
1191
+ keepIds.add(id);
1192
+ runAbsorbed.set(id, keep ? id : k >= emittedCount ? undefined : derivedResourceNodeId(node.id, kind, k));
1175
1193
  });
1176
1194
  }
1195
+ /**
1196
+ * The `nodeId` / `source` entries for resource node `r`: each only when it
1197
+ * differs from what compile derives (`derivedSource`), so a flow compile
1198
+ * wrote decompiles without them.
1199
+ */
1200
+ const placement = (r, derivedSource) => {
1201
+ const source = unwrapSource((r.inputs ?? {}).source);
1202
+ return [
1203
+ ['nodeId', keepIds.has(r.id) ? tsLiteral(r.id) : undefined],
1204
+ ['source', source !== undefined && source !== '' && source !== derivedSource ? tsLiteral(source) : undefined],
1205
+ ];
1206
+ };
1207
+ /** A tool's options plus its placement; `seed` is the ref compile derives the tool's directory from. */
1208
+ const toolOpts = (t, seed, entries) => opts([...entries, ...placement(t, derivedToolSource(runFlowId, node.id, seed))]);
1177
1209
  const rInputs = (n) => (n.inputs ?? {});
1178
1210
  const rPlain = (n, k) => {
1179
1211
  const raw = unwrapSource(rInputs(n)[k]);
@@ -1189,7 +1221,7 @@ function emitAgentCluster(node, imp, inputNames, graph) {
1189
1221
  return undefined;
1190
1222
  return objLit(Object.entries(props).map(([k, x]) => [k, tsLiteral(String(x?.type ?? 'string'))]));
1191
1223
  };
1192
- return opts([
1224
+ return toolOpts(t, { kind: 'clientside', name: rPlain(t, 'name') ?? '' }, [
1193
1225
  ['kind', tsLiteral('clientside')],
1194
1226
  ['name', tsLiteral(rPlain(t, 'name') ?? '')],
1195
1227
  ['description', rPlain(t, 'description') !== undefined ? tsLiteral(rPlain(t, 'description')) : undefined],
@@ -1206,7 +1238,8 @@ function emitAgentCluster(node, imp, inputNames, graph) {
1206
1238
  const v = row.textValue;
1207
1239
  return typeof v === 'number' ? String(v) : typeof v === 'string' ? tsLiteral(v) : JSON.stringify(v);
1208
1240
  };
1209
- return opts([
1241
+ // `name` is not recovered, so compile derives the directory from the default.
1242
+ return toolOpts(t, { kind: 'httpRequest' }, [
1210
1243
  ['kind', tsLiteral('httpRequest')],
1211
1244
  ['url', fixed('url')], ['method', fixed('method')],
1212
1245
  ['headers', fixed('headers')], ['params', fixed('params')],
@@ -1214,7 +1247,7 @@ function emitAgentCluster(node, imp, inputNames, graph) {
1214
1247
  ]);
1215
1248
  }
1216
1249
  if (type.startsWith('uipath.agent.resource.tool.mcp.')) {
1217
- return opts([
1250
+ return toolOpts(t, { kind: 'mcp', name: '', key: rPlain(t, 'referenceKey') ?? '' }, [
1218
1251
  ['kind', tsLiteral('mcp')],
1219
1252
  ['name', tsLiteral(rPlain(t, 'name') ?? '')],
1220
1253
  ['key', tsLiteral(rPlain(t, 'referenceKey') ?? '')],
@@ -1225,7 +1258,7 @@ function emitAgentCluster(node, imp, inputNames, graph) {
1225
1258
  ]);
1226
1259
  }
1227
1260
  if (type.startsWith('uipath.agent.resource.tool.a2a.')) {
1228
- return opts([
1261
+ return toolOpts(t, { kind: 'a2a', name: '', slug: '', key: rPlain(t, 'referenceKey') ?? '' }, [
1229
1262
  ['kind', tsLiteral('a2a')],
1230
1263
  ['name', tsLiteral(rPlain(t, 'name') ?? '')],
1231
1264
  ['key', tsLiteral(rPlain(t, 'referenceKey') ?? '')],
@@ -1234,17 +1267,19 @@ function emitAgentCluster(node, imp, inputNames, graph) {
1234
1267
  ]);
1235
1268
  }
1236
1269
  if (type.startsWith('uipath.agent.resource.tool.builtin.')) {
1237
- return opts([
1270
+ const tool = type.slice('uipath.agent.resource.tool.builtin.'.length);
1271
+ return toolOpts(t, { kind: 'builtin', tool }, [
1238
1272
  ['kind', tsLiteral('builtin')],
1239
- ['tool', tsLiteral(type.slice('uipath.agent.resource.tool.builtin.'.length))],
1273
+ ['tool', tsLiteral(tool)],
1240
1274
  ['description', rPlain(t, 'description') !== undefined ? tsLiteral(rPlain(t, 'description')) : undefined],
1241
1275
  ]);
1242
1276
  }
1243
1277
  if (type.startsWith('uipath.agent.resource.tool.ixp.')) {
1244
1278
  const tail = type.slice('uipath.agent.resource.tool.ixp.'.length);
1245
- return opts([
1279
+ const projectId = tail.slice(tail.indexOf('.') + 1);
1280
+ return toolOpts(t, { kind: 'ixp', name: '', projectId }, [
1246
1281
  ['kind', tsLiteral('ixp')],
1247
- ['projectId', tsLiteral(tail.slice(tail.indexOf('.') + 1))],
1282
+ ['projectId', tsLiteral(projectId)],
1248
1283
  ['name', tsLiteral(rPlain(t, 'name') ?? '')],
1249
1284
  ]);
1250
1285
  }
@@ -1266,9 +1301,10 @@ function emitAgentCluster(node, imp, inputNames, graph) {
1266
1301
  const row = values.find((v) => v.name === n);
1267
1302
  return typeof row?.default === 'string' ? row.default : undefined;
1268
1303
  };
1269
- return opts([
1304
+ const key = type.slice(ns[0].length);
1305
+ return toolOpts(t, { kind: 'process', name: '', folderPath: '', key }, [
1270
1306
  ['kind', tsLiteral(ns[1])],
1271
- ['key', tsLiteral(type.slice(ns[0].length))],
1307
+ ['key', tsLiteral(key)],
1272
1308
  ['name', tsLiteral(bound('name') ?? rPlain(t, 'name') ?? '')],
1273
1309
  ['folderPath', tsLiteral(bound('folderPath') ?? '')],
1274
1310
  ]);
@@ -1277,6 +1313,9 @@ function emitAgentCluster(node, imp, inputNames, graph) {
1277
1313
  });
1278
1314
  const contextSrc = resource('context').map((c) => {
1279
1315
  const { name, id, folderPath, sidecar } = contextIndexIdentity(node, c, rPlain);
1316
+ // Compile labels the node with `name`; a canvas rename is kept as `label`.
1317
+ const label = typeof c.display?.label === 'string' && c.display.label !== '' && c.display.label !== name
1318
+ ? c.display.label : undefined;
1280
1319
  return opts([
1281
1320
  ['name', tsLiteral(name)],
1282
1321
  ['id', tsLiteral(id)],
@@ -1284,6 +1323,8 @@ function emitAgentCluster(node, imp, inputNames, graph) {
1284
1323
  ['folderKey', rPlain(c, 'folderKey') !== undefined ? tsLiteral(rPlain(c, 'folderKey')) : undefined],
1285
1324
  // `query` and the retrieval settings, from resource.json or the node (#1183).
1286
1325
  ...contextIndexSettings(node, c, sidecar),
1326
+ ['label', label !== undefined ? tsLiteral(label) : undefined],
1327
+ ...placement(c, derivedContextSource(runFlowId, node.id, id)),
1287
1328
  ]);
1288
1329
  });
1289
1330
  const escalationSrc = resource('escalation').map((e) => {
@@ -1323,6 +1364,7 @@ function emitAgentCluster(node, imp, inputNames, graph) {
1323
1364
  ['taskTitle', typeof extra.taskTitle === 'string' && extra.taskTitle !== '' ? tsLiteral(extra.taskTitle) : undefined],
1324
1365
  // 'medium' is the platform default.
1325
1366
  ['priority', typeof extra.priority === 'string' && extra.priority !== 'medium' ? tsLiteral(extra.priority) : undefined],
1367
+ ...placement(e, derivedEscalationSource(runFlowId, node.id, rPlain(e, 'name') ?? '')),
1326
1368
  ]);
1327
1369
  });
1328
1370
  const mem = resource('memory', 1)[0];
@@ -3249,6 +3291,7 @@ export function decompile(flow, options = {}) {
3249
3291
  runDefs = new Map();
3250
3292
  runRawManifests = [];
3251
3293
  runAbsorbed = new Map();
3294
+ runFlowId = slugId(flow);
3252
3295
  for (const d of (flow.definitions ?? [])) {
3253
3296
  if (typeof d?.nodeType !== 'string')
3254
3297
  continue;
package/dist/serialize.js CHANGED
@@ -34,6 +34,7 @@ import { stopsAtEnd } from './flow-step-tree.js';
34
34
  import { assertNodeEnvelope } from './core/node-envelope.js';
35
35
  import { buildConfiguration } from './config.js';
36
36
  import { fnv1aX4Uuid, schemaId, stableId } from './core/stable-id.js';
37
+ import { derivedContextSource, derivedEscalationSource, derivedToolSource, } from './core/agent-resource-identity.js';
37
38
  import { readEventFilter, eventFilterProblem, eventFilterJmes, eventFilterTreeLeaf, jmesString, jmesStringProblem } from './core/event-filters.js';
38
39
  import { FLOW_EXPR_DIALECT } from './core/connector-checks.js';
39
40
  import { buildConnectorInputs, connectorInputErrors as coreConnectorInputErrors, multipartBodyFieldName, transportHttpMethod } from './core/connector-inputs.js';
@@ -4398,6 +4399,26 @@ export function serialize(built, opts = {}) {
4398
4399
  * gets them and one that does not is unaffected.
4399
4400
  */
4400
4401
  const sidecars = opts.sidecars ?? [];
4402
+ /** The sidecar paths a resource's explicit `source` chose. */
4403
+ const explicitSidecars = new Set();
4404
+ /**
4405
+ * Add one sidecar file. A resource whose explicit `source` names a directory
4406
+ * another resource also writes would have the second file silently replace
4407
+ * the first: index A's node would read B's settings. That is refused; `check`
4408
+ * reports it first (INLINE_AGENT_RESOURCE_SOURCE_DUP). The same file twice (a
4409
+ * subflow body emitted for two callers) is not a clash.
4410
+ */
4411
+ const addSidecar = (file, explicitSource = false) => {
4412
+ const earlier = sidecars.find((f) => f.path === file.path);
4413
+ if (earlier !== undefined && JSON.stringify(earlier.json) !== JSON.stringify(file.json)
4414
+ && (explicitSource || explicitSidecars.has(file.path))) {
4415
+ throw Object.assign(new Error(`two resources would both write "${file.path}" with different content, so the second would replace the first. `
4416
+ + 'Give each resource its own `source`, or omit `source` to derive one.'), { code: 'INLINE_AGENT_RESOURCE_SOURCE_DUP' });
4417
+ }
4418
+ if (explicitSource)
4419
+ explicitSidecars.add(file.path);
4420
+ sidecars.push(file);
4421
+ };
4401
4422
  /**
4402
4423
  * An agent step's folder uuid (`source`): the one the step carries, else one
4403
4424
  * derived from the flow id + step name rather than random, so a recompile is
@@ -4566,6 +4587,24 @@ export function serialize(built, opts = {}) {
4566
4587
  }
4567
4588
  return prefix;
4568
4589
  }
4590
+ /**
4591
+ * The node id of an agent resource: the author's `nodeId` exactly as written
4592
+ * (decompile writes the id the original file had, and a changed id is a
4593
+ * dropped node plus an added one to merge), else `uid`'s derived one. A
4594
+ * `nodeId` another node already holds is refused rather than renamed, for
4595
+ * the same reason; check reports it first (INLINE_AGENT_RESOURCE_NODE_ID).
4596
+ */
4597
+ function resourceNodeId(scope, nodeId, derivedBase, where) {
4598
+ if (nodeId === undefined)
4599
+ return uid(scope, derivedBase);
4600
+ if (nodeId.trim() === '' || takenIds.has(nodeId)) {
4601
+ throw Object.assign(new Error(`${where}: \`nodeId\` ${JSON.stringify(nodeId)} `
4602
+ + (nodeId.trim() === '' ? 'is blank.' : 'is already the id of another node in this flow.')
4603
+ + ' Give the resource node an id no other node has, or omit `nodeId` to derive one.'), { code: 'INLINE_AGENT_RESOURCE_NODE_ID' });
4604
+ }
4605
+ takenIds.add(nodeId);
4606
+ return nodeId;
4607
+ }
4569
4608
  /**
4570
4609
  * The node id of an author's step: the one `claimStepIds` claimed for it,
4571
4610
  * recorded so `.stepToRef('<step>')` can find it.
@@ -5419,7 +5458,7 @@ export function serialize(built, opts = {}) {
5419
5458
  source,
5420
5459
  name: step.name,
5421
5460
  });
5422
- sidecars.push({ path: `${source}/agent.json`, json: agentJson });
5461
+ addSidecar({ path: `${source}/agent.json`, json: agentJson });
5423
5462
  // The schema's property TYPES need this scope's finished variables, which
5424
5463
  // do not exist yet — park them (the `properties` object is filled in
5425
5464
  // place when the scope closes). See `typeAgentInputSchemas`.
@@ -5443,11 +5482,12 @@ export function serialize(built, opts = {}) {
5443
5482
  + `got ${JSON.stringify(cx?.id)}. \`uip solution resources list --kind Index --source remote --search "<name>"\` returns it as \`Key\`.`), { code: 'AGENT_CONTEXT_NO_ID' });
5444
5483
  }
5445
5484
  const cdef = contextIndexDef({ name: cx.name, id: cx.id });
5446
- // `<step>Context`, deduped by `uid` for a second index on the same agent.
5447
- // Not slugged from the index NAME: an id is the author's handle on the node
5448
- // and a 40-character one helps nobody.
5449
- const cid = uid(scope, `${step.name}Context`);
5450
- const cnode = makeNode(cdef.nodeType, cid, cx.name, { parentId, def: cdef });
5485
+ // `<step>Context`, deduped by `uid` for a second index on the same agent,
5486
+ // unless the author placed it (`nodeId`, which decompile writes for a
5487
+ // node the canvas named). Not slugged from the index NAME: an id is the
5488
+ // author's handle on the node and a 40-character one helps nobody.
5489
+ const cid = resourceNodeId(scope, cx.nodeId, `${step.name}Context`, `inline agent "${step.name}": context index "${cx.name}"`);
5490
+ const cnode = makeNode(cdef.nodeType, cid, cx.label ?? cx.name, { parentId, def: cdef });
5451
5491
  // A resource is drawn as a circle, and `makeNode` copies only the icon.
5452
5492
  cnode.display = { ...cnode.display, shape: 'circle' };
5453
5493
  // Same rule as the agent's: the resource `model` lives on the DEFINITION.
@@ -5459,7 +5499,7 @@ export function serialize(built, opts = {}) {
5459
5499
  // resource's `id` are the same uuid, because that is what joins them. The
5460
5500
  // platform validator says so in its own refusal text — *"the resource id
5461
5501
  // from the parent inline agent's `resources[]`"*.
5462
- const contextResourceId = fnv1aX4Uuid(`${built.id}/${step.name}/context/${cx.id}`);
5502
+ const contextResourceId = cx.source ?? derivedContextSource(built.id, step.name, cx.id);
5463
5503
  const contextQuery = renderContextQuery(cx.query, scope.rename);
5464
5504
  cnode.inputs = {
5465
5505
  // REQUIRED, and the platform's validator is what says so — measured
@@ -5469,6 +5509,7 @@ export function serialize(built, opts = {}) {
5469
5509
  // node"* (MST-9265). It is the resource's own identity inside the
5470
5510
  // project, so it is derived from flow + step + index rather than random,
5471
5511
  // exactly like the agent's `source`: a recompile must not be a diff.
5512
+ // An author's `source` (a canvas directory decompile carried) wins.
5472
5513
  source: contextResourceId,
5473
5514
  indexId: cx.id,
5474
5515
  indexName: cx.name,
@@ -5492,10 +5533,10 @@ export function serialize(built, opts = {}) {
5492
5533
  addEdge(scope, { node: id, port: 'context' }, cid, 'input');
5493
5534
  // The other half — without it the node is inert: see
5494
5535
  // `contextResourceJson`.
5495
- sidecars.push({
5536
+ addSidecar({
5496
5537
  path: `${source}/resources/${contextResourceId}/resource.json`,
5497
5538
  json: contextResourceJson(cx, { id: contextResourceId, query: contextQuery }),
5498
- });
5539
+ }, cx.source !== undefined);
5499
5540
  }
5500
5541
  // TOOLS — one resource node per tool, joined to the agent's `tool` handle;
5501
5542
  // the same artifact shape as context (no incoming control flow, no output,
@@ -5660,7 +5701,7 @@ export function serialize(built, opts = {}) {
5660
5701
  // copy puts it — emitting it on the node too would set inputs the
5661
5702
  // def's own schema does not declare (our own output would be flagged).
5662
5703
  }
5663
- const tid = uid(scope, `${step.name}Tool`);
5704
+ const tid = resourceNodeId(scope, tr.nodeId, `${step.name}Tool`, `inline agent "${step.name}": ${tr.kind} tool "${label}"`);
5664
5705
  const tnode = makeNode(tdef.nodeType, tid, label, { parentId, def: tdef });
5665
5706
  tnode.display = { ...tnode.display, shape: 'circle' };
5666
5707
  // `uip agent refresh` reads the tool's description off the node's display
@@ -5670,13 +5711,7 @@ export function serialize(built, opts = {}) {
5670
5711
  // The resource model lives on the DEFINITION only (CX's rule for
5671
5712
  // context, and what the deployed corpus carries for tools).
5672
5713
  delete tnode.model;
5673
- const toolSeed = tr.kind === 'builtin' ? tr.tool
5674
- : tr.kind === 'connector' ? `${tr.connector}.${tr.operation}`
5675
- : tr.kind === 'ixp' ? tr.projectId
5676
- : tr.kind === 'clientside' ? `clientside.${tr.name}`
5677
- : tr.kind === 'httpRequest' ? `httprequest.${tr.name ?? 'default'}`
5678
- : tr.key;
5679
- const toolResourceId = fnv1aX4Uuid(`${built.id}/${step.name}/tool/${toolSeed}`);
5714
+ const toolResourceId = tr.source ?? derivedToolSource(built.id, step.name, tr);
5680
5715
  tnode.inputs = {
5681
5716
  source: toolResourceId,
5682
5717
  ...extraInputs,
@@ -5694,10 +5729,10 @@ export function serialize(built, opts = {}) {
5694
5729
  ? httpRequestToolResourceJson(label, tnode.inputs, { id: toolResourceId, canvasNodeId: tid })
5695
5730
  : toolResourceJson(tr, { id: toolResourceId });
5696
5731
  if (toolResource !== undefined) {
5697
- sidecars.push({
5732
+ addSidecar({
5698
5733
  path: `${source}/resources/${toolResourceId}/resource.json`,
5699
5734
  json: toolResource,
5700
- });
5735
+ }, tr.source !== undefined);
5701
5736
  }
5702
5737
  }
5703
5738
  // ESCALATION — the agent's TOP handle; an Action Center app task a human
@@ -5711,7 +5746,7 @@ export function serialize(built, opts = {}) {
5711
5746
  // quick form carries, on the bundled `.quick-form` definition (the
5712
5747
  // tenant registry does not serve the family).
5713
5748
  const qdef = jsonClone(DEFS['uipath.agent.resource.escalation.quick-form@1.2']);
5714
- const qid = uid(scope, `${step.name}Escalation`);
5749
+ const qid = resourceNodeId(scope, esc.nodeId, `${step.name}Escalation`, `inline agent "${step.name}": escalation "${esc.name}"`);
5715
5750
  const qnode = makeNode(qdef.nodeType, qid, esc.name, { parentId, def: qdef });
5716
5751
  qnode.display = { ...qnode.display, shape: 'circle' };
5717
5752
  delete qnode.model;
@@ -5726,7 +5761,7 @@ export function serialize(built, opts = {}) {
5726
5761
  ...(options !== undefined ? { options } : {}),
5727
5762
  };
5728
5763
  });
5729
- const qsource = fnv1aX4Uuid(`${built.id}/${step.name}/escalation/${esc.name}`);
5764
+ const qsource = esc.source ?? derivedEscalationSource(built.id, step.name, esc.name);
5730
5765
  qnode.inputs = {
5731
5766
  source: qsource,
5732
5767
  name: esc.name,
@@ -5758,23 +5793,23 @@ export function serialize(built, opts = {}) {
5758
5793
  addEdge(scope, { node: id, port: 'escalation' }, qid, 'input');
5759
5794
  // The other half — without it the escalation is inert: see
5760
5795
  // `escalationResourceJson`.
5761
- sidecars.push({
5796
+ addSidecar({
5762
5797
  path: `${source}/resources/${qsource}/resource.json`,
5763
5798
  json: escalationResourceJson(esc, {
5764
5799
  id: qsource,
5765
5800
  channelId: fnv1aX4Uuid(`${built.id}/${step.name}/escalation/${esc.name}/channel`),
5766
5801
  quickFormSchema: qnode.inputs.schema,
5767
5802
  }),
5768
- });
5803
+ }, esc.source !== undefined);
5769
5804
  continue;
5770
5805
  }
5771
5806
  const app = esc.app;
5772
5807
  const edef = escalationDef();
5773
- const eid = uid(scope, `${step.name}Escalation`);
5808
+ const eid = resourceNodeId(scope, esc.nodeId, `${step.name}Escalation`, `inline agent "${step.name}": escalation "${esc.name}"`);
5774
5809
  const enode = makeNode(edef.nodeType, eid, esc.name, { parentId, def: edef });
5775
5810
  enode.display = { ...enode.display, shape: 'circle' };
5776
5811
  delete enode.model;
5777
- const esource = fnv1aX4Uuid(`${built.id}/${step.name}/escalation/${esc.name}`);
5812
+ const esource = esc.source ?? derivedEscalationSource(built.id, step.name, esc.name);
5778
5813
  enode.inputs = {
5779
5814
  source: esource,
5780
5815
  name: esc.name,
@@ -5807,13 +5842,13 @@ export function serialize(built, opts = {}) {
5807
5842
  };
5808
5843
  scope.nodes.push(enode);
5809
5844
  addEdge(scope, { node: id, port: 'escalation' }, eid, 'input');
5810
- sidecars.push({
5845
+ addSidecar({
5811
5846
  path: `${source}/resources/${esource}/resource.json`,
5812
5847
  json: escalationResourceJson(esc, {
5813
5848
  id: esource,
5814
5849
  channelId: fnv1aX4Uuid(`${built.id}/${step.name}/escalation/${esc.name}/channel`),
5815
5850
  }),
5816
- });
5851
+ }, esc.source !== undefined);
5817
5852
  }
5818
5853
  // MEMORY — one episodic-memory resource on the agent's `memory` handle
5819
5854
  // (the 1.4 definition selected above). Same artifact shape as context.
@@ -5946,7 +5981,7 @@ export function serialize(built, opts = {}) {
5946
5981
  conversationalAgentSettings: settings,
5947
5982
  };
5948
5983
  scope.nodes.push(node);
5949
- sidecars.push({
5984
+ addSidecar({
5950
5985
  path: `${source}/agent.json`,
5951
5986
  json: conversationalAgentJson({
5952
5987
  model: s.model, systemPrompt: s.systemPrompt, temperature: s.temperature,
@@ -6023,7 +6058,7 @@ export function serialize(built, opts = {}) {
6023
6058
  // The sidecar half, in the voice dialect: `settings.voice` carries the
6024
6059
  // audio configuration (the storage layer's own StoredVoiceSettings
6025
6060
  // shape), and the messages carry the system prompt alone.
6026
- sidecars.push({
6061
+ addSidecar({
6027
6062
  path: `${source}/agent.json`,
6028
6063
  json: voiceAgentJson({
6029
6064
  systemPrompt: s.systemPrompt,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.32.8",
3
+ "version": "6.33.1",
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",
@@ -93,5 +93,5 @@
93
93
  "@types/node": "^22.7.0",
94
94
  "esbuild": "^0.28.1"
95
95
  },
96
- "gitref": "fad79d44a992f72b8a8d0ba0f9c61d8ea5705ed7"
96
+ "gitref": "a27439803ad2ab68ce5be0c4299649d3f4d92e0b"
97
97
  }