@uipath/maestro-builder-sdk 6.32.8 → 6.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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.0",
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": "8875d03ffd74e131e88778405d2eb401dd13d0e9"
97
97
  }