@uipath/maestro-builder-sdk 6.21.2 → 6.23.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.
Files changed (42) hide show
  1. package/dist/api-index.md +138 -138
  2. package/dist/api-members.md +407 -407
  3. package/dist/check.js +43 -331
  4. package/dist/core/actions.d.ts +0 -287
  5. package/dist/core/actions.js +0 -95
  6. package/dist/core/expr.d.ts +1 -1
  7. package/dist/core/expr.js +2 -2
  8. package/dist/core/nodes/node-type.d.ts +15 -0
  9. package/dist/core/step-ports.js +7 -23
  10. package/dist/core/typed-raw-node.js +0 -4
  11. package/dist/decompile.js +44 -115
  12. package/dist/flow-node-registry.js +3 -1
  13. package/dist/flow-node-type.d.ts +59 -0
  14. package/dist/flow-sdk.d.ts +2 -0
  15. package/dist/flow-sdk.js +2 -0
  16. package/dist/flow-step-exits.d.ts +12 -0
  17. package/dist/flow-step-exits.js +30 -0
  18. package/dist/nodes/ai-patterns/flow/factories.d.ts +83 -0
  19. package/dist/nodes/ai-patterns/flow/factories.js +86 -0
  20. package/dist/nodes/ai-patterns/flow/family.d.ts +3 -0
  21. package/dist/nodes/ai-patterns/flow/family.js +8 -0
  22. package/dist/nodes/ai-patterns/flow/index.d.ts +3 -0
  23. package/dist/nodes/ai-patterns/flow/index.js +3 -0
  24. package/dist/nodes/ai-patterns/flow/node-type.d.ts +11 -0
  25. package/dist/nodes/ai-patterns/flow/node-type.js +106 -0
  26. package/dist/nodes/ai-patterns/flow/spec.d.ts +75 -0
  27. package/dist/nodes/ai-patterns/flow/spec.js +1 -0
  28. package/dist/nodes/http/flow/check.d.ts +58 -0
  29. package/dist/nodes/http/flow/check.js +248 -0
  30. package/dist/nodes/http/flow/factories.d.ts +14 -0
  31. package/dist/nodes/http/flow/factories.js +20 -0
  32. package/dist/nodes/http/flow/family.d.ts +8 -0
  33. package/dist/nodes/http/flow/family.js +13 -0
  34. package/dist/nodes/http/flow/index.d.ts +3 -0
  35. package/dist/nodes/http/flow/index.js +3 -0
  36. package/dist/nodes/http/flow/node-type.d.ts +7 -0
  37. package/dist/nodes/http/flow/node-type.js +411 -0
  38. package/dist/nodes/http/flow/spec.d.ts +151 -0
  39. package/dist/nodes/http/flow/spec.js +1 -0
  40. package/dist/serialize.d.ts +2 -2
  41. package/dist/serialize.js +20 -316
  42. package/package.json +2 -2
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 { contextIndexSlug, parseContextIndexType } from './core/context-index.js';
40
40
  import { wireExprBody } from './core/wire-expr.js';
41
+ import { hasExits } from './core/step-ports.js';
41
42
  import { parseIxpProjectType } from './core/actions.js';
42
43
  import { readFlowGlobals } from './flow-variables.js';
43
44
  import { outputBackingGlobal, outputBackingName } from './flow-output-backing.js';
@@ -228,16 +229,12 @@ const T = {
228
229
  hitlQuickForm: 'uipath.human-in-the-loop.quick-form',
229
230
  hitlActionApp: 'uipath.human-in-the-loop.coded-action-app',
230
231
  hitlDocValidation: 'uipath.human-in-the-loop.document-validation',
231
- summarize: 'uipath.pattern.deep-rag',
232
- batchTransform: 'uipath.pattern.batch-transform',
233
232
  sendMessage: 'uipath.conversational.send-message',
234
233
  waitForMessage: 'uipath.conversational.wait-for-message',
235
234
  conversationContext: 'uipath.conversational.get-conversation-context',
236
235
  triggerVoice: 'core.trigger.voice',
237
236
  createOutgoingCall: 'uipath.conversational.voice.create-outgoing-call',
238
237
  endCall: 'uipath.conversational.voice.end-call',
239
- http: 'core.action.http',
240
- httpV2: 'core.action.http.v2',
241
238
  decision: 'core.logic.decision',
242
239
  switch: 'core.logic.switch',
243
240
  merge: 'core.logic.merge',
@@ -547,21 +544,29 @@ function specValue(raw) {
547
544
  return raw;
548
545
  }
549
546
  /**
550
- * Print a node whose type is registered (flow-node-registry.ts): the node type
551
- * deserializes it to its spec and prints the factory call. A node at a version
552
- * the type does not register is lifted by its default version's implementation —
553
- * as every built-in family lifts any version — and `verClause` omits a
554
- * `{ version }` the type does not register, with a warning. `undefined` when the type is not registered, or the node type declines
555
- * the node; the caller's branches take it from there.
547
+ * The registered implementation a node of this type and version lifts with: its
548
+ * own version's, else the type's default (as every built-in family lifts any
549
+ * version); undefined when the type is not registered.
556
550
  */
557
- function emitRegisteredSpec(node, imp, inputNames) {
551
+ function registeredImpl(node) {
558
552
  const entry = typeof node.type === 'string' ? FLOW_NODE_TYPES.byTypeName(node.type) : undefined;
559
553
  if (!entry)
560
554
  return undefined;
561
555
  const version = String(node.typeVersion ?? '');
562
- const impl = (Object.hasOwn(entry.type.versions, version)
556
+ return (Object.hasOwn(entry.type.versions, version)
563
557
  ? entry.type.versions[version]
564
558
  : entry.type.versions[entry.type.defaultVersion]);
559
+ }
560
+ /**
561
+ * A node of a registered type (flow-node-registry.ts), lifted to its spec by the
562
+ * type's own `deserialize`: undefined when the type is not registered or declines
563
+ * the node. A node at a version the type does not register is lifted by its
564
+ * default version's implementation, as every built-in family lifts any version.
565
+ */
566
+ function liftRegistered(node, impl = registeredImpl(node)) {
567
+ if (!impl)
568
+ return undefined;
569
+ const version = String(node.typeVersion ?? '');
565
570
  const ctx = {
566
571
  nodeId: node.id,
567
572
  expr: specValue,
@@ -574,8 +579,21 @@ function emitRegisteredSpec(node, imp, inputNames) {
574
579
  warn: warnOnce,
575
580
  };
576
581
  const spec = impl.deserialize(node, ctx);
577
- if (spec === undefined)
582
+ return spec === undefined ? undefined : { impl, spec };
583
+ }
584
+ /**
585
+ * Print a node whose type is registered (flow-node-registry.ts): the node type
586
+ * deserializes it to its spec and prints the factory call. A node at a version
587
+ * the type does not register is lifted by its default version's implementation —
588
+ * as every built-in family lifts any version — and `verClause` omits a
589
+ * `{ version }` the type does not register, with a warning. `undefined` when the type is not registered, or the node type declines
590
+ * the node; the caller's branches take it from there.
591
+ */
592
+ function emitRegisteredSpec(node, imp, inputNames) {
593
+ const lifted = liftRegistered(node);
594
+ if (!lifted)
578
595
  return undefined;
596
+ const { impl, spec } = lifted;
579
597
  // A spec value as source, recursing into arrays and plain objects so an Expr
580
598
  // nested in one (a filter row's value) prints as the helper an author writes —
581
599
  // in the `{ k: v }` / `[a, b]` spelling the hand-written printers use.
@@ -617,7 +635,6 @@ function emitStepSpec(node, imp, inputNames, o, graph) {
617
635
  const lifted = emitRegisteredSpec(node, imp, inputNames);
618
636
  if (lifted !== undefined)
619
637
  return lifted;
620
- const inputs = node.inputs ?? {};
621
638
  switch (node.type) {
622
639
  case T.createOutgoingCall:
623
640
  case T.endCall: {
@@ -642,30 +659,6 @@ function emitStepSpec(node, imp, inputNames, o, graph) {
642
659
  case T.hitlActionApp:
643
660
  case T.hitlDocValidation:
644
661
  return emitHitl(node, imp, inputNames, graph);
645
- case T.summarize:
646
- case T.batchTransform: {
647
- const attachment = emitVal(inputs.attachment, imp, inputNames);
648
- const prompt = emitVal(inputs.prompt, imp, inputNames);
649
- if (node.type === T.summarize) {
650
- return `${imp.use('summarize')}(${opts([
651
- ['attachment', attachment],
652
- ['prompt', prompt],
653
- // Both flags default to false in the emitted node; only `true` was authored.
654
- ['returnCitations', unwrapPlain(inputs.returnCitations) === true ? 'true' : undefined],
655
- ])})`;
656
- }
657
- const cols = Array.isArray(inputs.outputColumns) ? inputs.outputColumns : [];
658
- const colSrc = `[${cols.map((c) => opts([
659
- ['name', emitVal(c.name, imp, inputNames)],
660
- ['description', emitVal(c.description, imp, inputNames)],
661
- ])).join(', ')}]`;
662
- return `${imp.use('batchTransform')}(${opts([
663
- ['attachment', attachment],
664
- ['prompt', prompt],
665
- ['outputColumns', colSrc],
666
- ['enableWebSearchGrounding', unwrapPlain(inputs.enableWebSearchGrounding) === true ? 'true' : undefined],
667
- ])})`;
668
- }
669
662
  case T.sendMessage:
670
663
  case T.waitForMessage:
671
664
  case T.conversationContext: {
@@ -707,10 +700,6 @@ function emitStepSpec(node, imp, inputNames, o, graph) {
707
700
  ['exchangeLimit', num(i.exchangeLimit) === '20' ? undefined : num(i.exchangeLimit)],
708
701
  ])})`;
709
702
  }
710
- case T.http:
711
- return emitHttp(node, false, imp, inputNames);
712
- case T.httpV2:
713
- return emitHttp(node, true, imp, inputNames);
714
703
  default:
715
704
  // A connector action node: `uipath.connector.<key>.<action>` (but NOT the
716
705
  // event nodes `uipath.connector.event.*` / `.trigger.*`, which are triggers).
@@ -767,66 +756,6 @@ function emitStepSpec(node, imp, inputNames, o, graph) {
767
756
  return unsupportedSpec(node, imp, o);
768
757
  }
769
758
  }
770
- /**
771
- * Invert an HTTP node. The plain node (`core.action.http`) keeps its request at
772
- * the top level (`url` / `method` / `headers` / `queryParams` / `body` /
773
- * `contentType`); the managed node (`core.action.http.v2`) nests the request
774
- * inside `detail.bodyParameters` and routes through IS. Request settings
775
- * (`timeout` / `retryCount`) sit at the top level on both. Emitted only-when-off
776
- * their definition defaults, exactly as serialize writes them, so the round-trip
777
- * stays minimal. The response schema (`returns`) is a Phase-2 refinement.
778
- */
779
- function emitHttp(node, managed, imp, inputNames) {
780
- const inputs = node.inputs ?? {};
781
- const detail = managed
782
- ? (inputs.detail ?? {})
783
- : {};
784
- const req = managed
785
- ? detail.bodyParameters ?? {}
786
- : inputs;
787
- const method = typeof req.method === 'string' ? req.method : 'GET';
788
- const headers = managed ? req.headers : inputs.headers;
789
- const query = managed ? req.query : inputs.queryParams;
790
- const bodySrc = req.body !== undefined && req.body !== '' ? emitVal(req.body, imp, inputNames) : undefined;
791
- const headersSrc = emitValMap(headers, imp, inputNames) || undefined;
792
- const querySrc = emitValMap(query, imp, inputNames) || undefined;
793
- const contentType = !managed && typeof inputs.contentType === 'string' && inputs.contentType !== 'application/json'
794
- ? tsLiteral(inputs.contentType) : undefined;
795
- const timeout = typeof inputs.timeout === 'string' && inputs.timeout !== 'PT15M' ? tsLiteral(inputs.timeout) : undefined;
796
- const retry = inputs.retryCount !== undefined && Number(inputs.retryCount) !== 0 ? tsNumber(inputs.retryCount) : undefined;
797
- const branchRows = Array.isArray(inputs.branches) ? inputs.branches : [];
798
- const branchesSrc = branchRows.length
799
- ? `[${branchRows.map((b) => {
800
- const cond = unwrapSource(b.conditionExpression) ?? '';
801
- const expr = emitBareExpr(wireExprBody(cond), imp, inputNames);
802
- return `{ name: ${tsText(b.name ?? b.id)}, condition: ${expr} }`;
803
- }).join(', ')}]`
804
- : undefined;
805
- const connectionValue = detail.connectionId ?? detail.connectionResourceId ?? req.connection;
806
- const connection = managed && typeof connectionValue === 'string' && connectionValue !== 'ImplicitConnection'
807
- ? tsLiteral(connectionValue) : undefined;
808
- const folder = managed && typeof detail.connectionFolderKey === 'string' && detail.connectionFolderKey.length > 0
809
- ? tsLiteral(detail.connectionFolderKey) : undefined;
810
- const targetConnector = managed && typeof req.targetConnector === 'string'
811
- && req.targetConnector !== 'uipath-uipath-http'
812
- ? tsLiteral(req.targetConnector) : undefined;
813
- const spec = opts([
814
- ['url', emitVal(req.url ?? '', imp, inputNames)],
815
- ['method', method !== 'GET' ? tsLiteral(method) : undefined],
816
- ['headers', headersSrc],
817
- ['query', querySrc],
818
- ['body', bodySrc],
819
- ['contentType', contentType],
820
- ['managed', boolLit(managed)],
821
- ['connection', connection],
822
- ['folder', folder],
823
- ['targetConnector', targetConnector],
824
- ['timeout', timeout],
825
- ['retryCount', retry],
826
- ['branches', branchesSrc],
827
- ]);
828
- return `${imp.use('http')}(${spec})`;
829
- }
830
759
  /**
831
760
  * Split a connector `nodeType` (`uipath.connector.<key>.<action>`) into key +
832
761
  * action. Mirrors `core/connectors.ts`'s `splitConnectorNodeType`.
@@ -2715,9 +2644,9 @@ function outcomeIdsOfNode(node) {
2715
2644
  * The exits a node declares, read back off the EMITTED artifact rather than off
2716
2645
  * an authored spec — `inputs.schema.outcomes` for a base or quick-form human
2717
2646
  * task (the product draws one `outcome-<id>` handle per outcome on both, at
2718
- * every version), `inputs.branches` plus `default` for an HTTP call. The
2719
- * authoring-side twin is `declaredExits` in `core/step-ports.ts`; they answer
2720
- * about different inputs, which is why this is not a call into it.
2647
+ * every version), and a registered type's own `exits` over the spec its lift
2648
+ * recovers (an HTTP call's `inputs.branches` plus `default`). The authoring-side
2649
+ * twin is `stepExits` in `flow-step-exits.ts`.
2721
2650
  */
2722
2651
  function declaredExitsOfNode(node) {
2723
2652
  const inputs = (node.inputs ?? {});
@@ -2729,16 +2658,16 @@ function declaredExitsOfNode(node) {
2729
2658
  return undefined;
2730
2659
  return outcomes.map((o) => ({ value: String(o?.name ?? ''), port: `outcome-${o?.id ?? ''}` }));
2731
2660
  }
2732
- if (node.type === T.http || node.type === T.httpV2) {
2733
- const branches = (inputs.branches ?? []);
2734
- if (branches.length === 0)
2735
- return undefined;
2736
- return [
2737
- ...branches.map((b) => ({ value: String(b?.name ?? ''), port: `branch-${b?.name ?? ''}` })),
2738
- { value: 'default', port: 'default' },
2739
- ];
2740
- }
2741
- return undefined;
2661
+ // A registered type that declares exits answers from its own spec, lifted off
2662
+ // this node; one that declares none is not lifted at all (this runs per edge).
2663
+ const impl = registeredImpl(node);
2664
+ if (!impl?.exits)
2665
+ return undefined;
2666
+ const lifted = liftRegistered(node, impl);
2667
+ const exits = lifted && impl.exits(lifted.spec);
2668
+ if (!exits || !hasExits(exits))
2669
+ return undefined;
2670
+ return exits.map((e) => ({ value: e.value, port: e.port }));
2742
2671
  }
2743
2672
  /**
2744
2673
  * Split a switch case expression into `<discriminant> === <literal>`, the only
@@ -8,13 +8,15 @@
8
8
  */
9
9
  import { NodeTypeRegistry } from './core/nodes/registry.js';
10
10
  import { hasBundledDefinition } from './flow-definitions.js';
11
+ import { aiPatternsFlowFamily } from './nodes/ai-patterns/flow/family.js';
11
12
  import { dataFabricFlowFamily } from './nodes/data-fabric/flow/family.js';
12
13
  import { delayFlowFamily } from './nodes/delay/flow/family.js';
13
14
  import { documentFlowFamily } from './nodes/document/flow/family.js';
15
+ import { httpFlowFamily } from './nodes/http/flow/family.js';
14
16
  import { mockFlowFamily } from './nodes/mock/flow/family.js';
15
17
  import { queueFlowFamily } from './nodes/queue/flow/family.js';
16
18
  import { scriptFlowFamily } from './nodes/script/flow/family.js';
17
19
  import { transformFlowFamily } from './nodes/transform/flow/family.js';
18
20
  /** The families, in no significant order. Adding one is the whole of registering it. */
19
- export const FLOW_NODE_FAMILIES = [dataFabricFlowFamily, delayFlowFamily, documentFlowFamily, mockFlowFamily, queueFlowFamily, scriptFlowFamily, transformFlowFamily];
21
+ export const FLOW_NODE_FAMILIES = [aiPatternsFlowFamily, dataFabricFlowFamily, delayFlowFamily, documentFlowFamily, httpFlowFamily, mockFlowFamily, queueFlowFamily, scriptFlowFamily, transformFlowFamily];
20
22
  export const FLOW_NODE_TYPES = new NodeTypeRegistry('flow', FLOW_NODE_FAMILIES, { hasBundledDefinition });
@@ -14,6 +14,7 @@ import type { VersionedNodeType } from './core/nodes/versioned.js';
14
14
  import type { NodeFamily, Placement } from './core/nodes/family.js';
15
15
  import type { DefinitionReference, NodeContribution } from './core/node-classes.js';
16
16
  import type { CheckOpts } from './check.js';
17
+ import type { DeclaredExit, NoExits } from './core/step-ports.js';
17
18
  /**
18
19
  * What a Flow node type's `serialize` returns: the node's type-owned fields.
19
20
  *
@@ -81,6 +82,28 @@ export interface FlowSerializeContext {
81
82
  * pair) or must pick an id that is not taken; add entries through `bind`.
82
83
  */
83
84
  readonly bindings: ReadonlyMap<string, Readonly<Record<string, unknown>>>;
85
+ /**
86
+ * A symbolic `connection` or `folder` label resolved through the flow's
87
+ * bindings.json, as a connector step's is: a self-referential label throws the
88
+ * refusal check reports, and a value that cannot be a tenant id is warned about
89
+ * (`CONNECTION_STUB`). `where` names the site in both, e.g. `managed http "fetch"`.
90
+ */
91
+ resolveBinding(name: string, attribute: 'connection' | 'folder', where: string): string;
92
+ /**
93
+ * Hoist the Integration Service connection pair a definition's `model`
94
+ * references (`<bindings.NAME>` for its connection id and folder key), deduped
95
+ * against the flow's existing entries by name, resource key and attribute. An
96
+ * unresolved connection still gets its entries (no `default`), so the
97
+ * definition's references always close.
98
+ */
99
+ bindConnection(o: {
100
+ model: unknown;
101
+ connectorKey: string;
102
+ connectionId: string;
103
+ folderKey?: string;
104
+ /** The entries' `resourceKey`; defaults to `connectionId`. */
105
+ resourceKey?: string;
106
+ }): void;
84
107
  }
85
108
  /** What `deserialize` may ask of the decompiler, for one serialized node. */
86
109
  export interface FlowDeserializeContext {
@@ -146,6 +169,20 @@ export interface FlowCheckContext {
146
169
  } | undefined;
147
170
  /** The options `check` was called with (the connector-library views among them). */
148
171
  readonly options: CheckOpts;
172
+ /**
173
+ * Check a step's symbolic `connection` / `folder` labels against bindings.json,
174
+ * as a connector step's are, reporting `BINDING_SELF_NAME` / `BINDING_UNDECLARED`.
175
+ * Those codes are the pipeline's, shared by every family that binds a
176
+ * connection, so they belong to no family catalog. `use` names the connector
177
+ * the connection must belong to, for the cross-step connection-owner rule.
178
+ */
179
+ bindingLabels(where: string, labels: {
180
+ connection?: unknown;
181
+ folder?: unknown;
182
+ }, use?: {
183
+ id: string;
184
+ connector: string | undefined;
185
+ }): void;
149
186
  }
150
187
  /** What a family-level `check` may ask of the checker. */
151
188
  export interface FlowFamilyCheckContext {
@@ -199,6 +236,28 @@ export interface FlowNodeType<Spec> extends NodeType<Spec, FlowNodeContribution,
199
236
  readonly nodeModel?: 'definition' | 'omit';
200
237
  /** What `rawNode` reports for a raw node of this type. */
201
238
  readonly rawNode?: FlowRawNodeAdvice;
239
+ /**
240
+ * The runtime variable a failed node's envelope is published under, when it is
241
+ * not `error`. `err()` writes one shape for every family
242
+ * (`$vars.<step>.error.<field>`), and serialize rewrites a handler's reads to
243
+ * this variable.
244
+ *
245
+ * Measured on the product, one debug run per family (2026-09-10): six of the
246
+ * seven families probed publish it as `<step>.error`, which is what the
247
+ * definitions declare (`outputDefinition.error.var`). The exception is
248
+ * `core.action.http.v2`, whose `<step>.error` is the boolean `true` and whose
249
+ * envelope is in `<step>.output` (instance 430d43ad-4583-40c0-8f74-b49d2c4904e4).
250
+ */
251
+ readonly errorEnvelope?: string;
252
+ /**
253
+ * The exits the AUTHOR named on this step — an HTTP call's response branches,
254
+ * and the port each leaves on — or why it has none to route. What
255
+ * `.stepSwitch()` routes over, what an arm's `value` and a `.stepToList` port
256
+ * are checked against, and what decompile reads a fully wired node back as.
257
+ * Omitted: the type has no author-declared fan-out. The `error` port is never
258
+ * one of these (`.onError()` routes it).
259
+ */
260
+ exits?(spec: Spec): DeclaredExit[] | NoExits;
202
261
  }
203
262
  /** A Flow node type with several versions. */
204
263
  export type FlowVersionedNodeType<Spec> = VersionedNodeType<Spec, FlowNodeContribution, FlowContexts, FlowNodeType<Spec>>;
@@ -18,9 +18,11 @@
18
18
  */
19
19
  export * from './core/expr.js';
20
20
  export * from './core/actions.js';
21
+ export * from './nodes/ai-patterns/flow/index.js';
21
22
  export * from './nodes/data-fabric/flow/index.js';
22
23
  export * from './nodes/delay/flow/index.js';
23
24
  export * from './nodes/document/flow/index.js';
25
+ export * from './nodes/http/flow/index.js';
24
26
  export * from './nodes/mock/flow/index.js';
25
27
  export * from './nodes/queue/flow/index.js';
26
28
  export * from './nodes/script/flow/index.js';
package/dist/flow-sdk.js CHANGED
@@ -22,9 +22,11 @@
22
22
  export * from './core/expr.js';
23
23
  export * from './core/actions.js';
24
24
  // Node families' public surfaces (docs/NODE_TYPE_ARCHITECTURE_DESIGN.md §8).
25
+ export * from './nodes/ai-patterns/flow/index.js';
25
26
  export * from './nodes/data-fabric/flow/index.js';
26
27
  export * from './nodes/delay/flow/index.js';
27
28
  export * from './nodes/document/flow/index.js';
29
+ export * from './nodes/http/flow/index.js';
28
30
  export * from './nodes/mock/flow/index.js';
29
31
  export * from './nodes/queue/flow/index.js';
30
32
  export * from './nodes/script/flow/index.js';
@@ -0,0 +1,12 @@
1
+ import { type DeclaredExit, type NoExits } from './core/step-ports.js';
2
+ /**
3
+ * The author-declared exits of a step's spec: a registered type's own `exits`,
4
+ * at the version the step resolves to (its pin, else the type's choice; an
5
+ * unregistered pin falls back to that choice, as check's other rules do), and
6
+ * `declaredExits` for a kind not yet registered. `serialize` and `check` ask
7
+ * here, so they agree on what a port means.
8
+ */
9
+ export declare function stepExits(spec: {
10
+ kind?: unknown;
11
+ inputs?: unknown;
12
+ } | undefined, pinnedVersion?: string): DeclaredExit[] | NoExits;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The exits the author declared on a step — what `.stepSwitch()` routes over and
3
+ * a `.stepToList('<port>')` names — answered by the step's node type when its kind
4
+ * is registered (`FlowNodeType.exits`), else by `core/step-ports.ts` for a kind
5
+ * not yet ported. A module of its own so a test that swaps the registry
6
+ * (`vi.mock('./flow-node-registry.js')`) swaps what this asks too.
7
+ */
8
+ import { resolveVersion } from './core/nodes/versioned.js';
9
+ import { declaredExits } from './core/step-ports.js';
10
+ import { FLOW_NODE_TYPES } from './flow-node-registry.js';
11
+ /**
12
+ * The author-declared exits of a step's spec: a registered type's own `exits`,
13
+ * at the version the step resolves to (its pin, else the type's choice; an
14
+ * unregistered pin falls back to that choice, as check's other rules do), and
15
+ * `declaredExits` for a kind not yet registered. `serialize` and `check` ask
16
+ * here, so they agree on what a port means.
17
+ */
18
+ export function stepExits(spec, pinnedVersion) {
19
+ const entry = typeof spec?.kind === 'string' ? FLOW_NODE_TYPES.byKind(spec.kind, spec) : undefined;
20
+ if (!entry)
21
+ return declaredExits(spec, pinnedVersion);
22
+ let impl;
23
+ try {
24
+ impl = resolveVersion(entry.type, spec, pinnedVersion, 'exits');
25
+ }
26
+ catch {
27
+ impl = resolveVersion(entry.type, spec, undefined, 'exits');
28
+ }
29
+ return impl.exits?.(spec) ?? declaredExits(spec, pinnedVersion);
30
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * The AI-pattern factories, `summarize()` and `batchTransform()`. Moved from
3
+ * core/actions.ts in Phase 4 of docs/NODE_TYPE_ARCHITECTURE_DESIGN.md; the
4
+ * package entry re-exports them.
5
+ */
6
+ import { type ActionSpec } from '../../../core/actions.js';
7
+ import type { BatchTransformInputs, SummarizeInputs } from './spec.js';
8
+ /**
9
+ * Summarize a document with citations — the platform's **Summarize** node.
10
+ *
11
+ * @remarks
12
+ * **The node type is `uipath.pattern.deep-rag`.** The canvas calls it
13
+ * *Summarize*, its properties panel is titled *Summarize Configuration*, and
14
+ * the wire type stays `deep-rag` — it is the same node, under the name the
15
+ * backend service contract uses (`ECS.DeepRag`). There is no
16
+ * `uipath.pattern.summarize`. (A same-named inline-agent TOOL,
17
+ * `uipath.agent.resource.tool.builtin.summarize`, is a different family.)
18
+ *
19
+ * The answer's fields are **PascalCase** — `content.Text`,
20
+ * `content.Citations[].{Ordinal, PageNumber, Source, Reference}`. Lowercase
21
+ * `content.text` resolves to nothing at run time.
22
+ *
23
+ * A local run cannot reach the service: it returns the baked
24
+ * fixture shape, and only a real platform run (`uip maestro flow debug
25
+ * --attachment <var>=<file>`) calls the model.
26
+ *
27
+ * @example
28
+ * **Summarize an attached contract, with citations**
29
+ * ```ts
30
+ * flow('SummarizeDemo')
31
+ * .input({ documentFile: types.file })
32
+ * .output({ summary: types.string, citations: types.array })
33
+ * .step('summarizeContract', summarize({
34
+ * attachment: out('start', 'documentFile'),
35
+ * prompt: 'Write a 5-bullet executive summary covering scope, term and SLAs.',
36
+ * returnCitations: true,
37
+ * }))
38
+ * .return({
39
+ * summary: out('summarizeContract', 'content.Text'),
40
+ * citations: out('summarizeContract', 'content.Citations'),
41
+ * })
42
+ * ```
43
+ *
44
+ * @param inputs - The document (`attachment`), the question to answer (`prompt`),
45
+ * and whether to return citations.
46
+ * @returns An action spec to pass to `.step(name, …)`.
47
+ */
48
+ export declare function summarize(inputs: SummarizeInputs): ActionSpec;
49
+ /**
50
+ * Add AI-generated columns to a CSV — the platform's **Batch transform** node,
51
+ * `uipath.pattern.batch-transform` (service contract `ECS.BatchTransform`).
52
+ *
53
+ * @remarks
54
+ * The output is a **file handle for the enriched CSV**, not the rows:
55
+ * `{ ID, FullName, MimeType }` — the service writes a new
56
+ * `batch-transform-<uuid>.csv` and hands back its attachment. Note `ID`, two
57
+ * capitals: that is what the platform returns.
58
+ *
59
+ * Same dispatch story as {@link summarize} — dry-run fixture locally, a real
60
+ * model call only on a platform run.
61
+ *
62
+ * @example
63
+ * **Categorize each CSV row with two generated columns**
64
+ * ```ts
65
+ * flow('BatchTransformDemo')
66
+ * .input({ csvFile: types.file })
67
+ * .output({ result: types.file })
68
+ * .step('categorizeRows', batchTransform({
69
+ * attachment: out('start', 'csvFile'),
70
+ * prompt: 'Classify each row by category and write a one-line summary.',
71
+ * outputColumns: [
72
+ * { name: 'Category', description: 'One of: Utility, Software, Travel, Other' },
73
+ * { name: 'Summary', description: 'Plain-English one-line summary of the row' },
74
+ * ],
75
+ * }))
76
+ * .return({ result: out('categorizeRows') })
77
+ * ```
78
+ *
79
+ * @param inputs - The CSV (`attachment`), the instruction (`prompt`), and the
80
+ * `outputColumns` to add to each row.
81
+ * @returns An action spec to pass to `.step(name, …)`.
82
+ */
83
+ export declare function batchTransform(inputs: BatchTransformInputs): ActionSpec;
@@ -0,0 +1,86 @@
1
+ /**
2
+ * The AI-pattern factories, `summarize()` and `batchTransform()`. Moved from
3
+ * core/actions.ts in Phase 4 of docs/NODE_TYPE_ARCHITECTURE_DESIGN.md; the
4
+ * package entry re-exports them.
5
+ */
6
+ import { builtinActionSpec } from '../../../core/actions.js';
7
+ /**
8
+ * Summarize a document with citations — the platform's **Summarize** node.
9
+ *
10
+ * @remarks
11
+ * **The node type is `uipath.pattern.deep-rag`.** The canvas calls it
12
+ * *Summarize*, its properties panel is titled *Summarize Configuration*, and
13
+ * the wire type stays `deep-rag` — it is the same node, under the name the
14
+ * backend service contract uses (`ECS.DeepRag`). There is no
15
+ * `uipath.pattern.summarize`. (A same-named inline-agent TOOL,
16
+ * `uipath.agent.resource.tool.builtin.summarize`, is a different family.)
17
+ *
18
+ * The answer's fields are **PascalCase** — `content.Text`,
19
+ * `content.Citations[].{Ordinal, PageNumber, Source, Reference}`. Lowercase
20
+ * `content.text` resolves to nothing at run time.
21
+ *
22
+ * A local run cannot reach the service: it returns the baked
23
+ * fixture shape, and only a real platform run (`uip maestro flow debug
24
+ * --attachment <var>=<file>`) calls the model.
25
+ *
26
+ * @example
27
+ * **Summarize an attached contract, with citations**
28
+ * ```ts
29
+ * flow('SummarizeDemo')
30
+ * .input({ documentFile: types.file })
31
+ * .output({ summary: types.string, citations: types.array })
32
+ * .step('summarizeContract', summarize({
33
+ * attachment: out('start', 'documentFile'),
34
+ * prompt: 'Write a 5-bullet executive summary covering scope, term and SLAs.',
35
+ * returnCitations: true,
36
+ * }))
37
+ * .return({
38
+ * summary: out('summarizeContract', 'content.Text'),
39
+ * citations: out('summarizeContract', 'content.Citations'),
40
+ * })
41
+ * ```
42
+ *
43
+ * @param inputs - The document (`attachment`), the question to answer (`prompt`),
44
+ * and whether to return citations.
45
+ * @returns An action spec to pass to `.step(name, …)`.
46
+ */
47
+ export function summarize(inputs) {
48
+ return builtinActionSpec({ kind: 'summarize', inputs });
49
+ }
50
+ /**
51
+ * Add AI-generated columns to a CSV — the platform's **Batch transform** node,
52
+ * `uipath.pattern.batch-transform` (service contract `ECS.BatchTransform`).
53
+ *
54
+ * @remarks
55
+ * The output is a **file handle for the enriched CSV**, not the rows:
56
+ * `{ ID, FullName, MimeType }` — the service writes a new
57
+ * `batch-transform-<uuid>.csv` and hands back its attachment. Note `ID`, two
58
+ * capitals: that is what the platform returns.
59
+ *
60
+ * Same dispatch story as {@link summarize} — dry-run fixture locally, a real
61
+ * model call only on a platform run.
62
+ *
63
+ * @example
64
+ * **Categorize each CSV row with two generated columns**
65
+ * ```ts
66
+ * flow('BatchTransformDemo')
67
+ * .input({ csvFile: types.file })
68
+ * .output({ result: types.file })
69
+ * .step('categorizeRows', batchTransform({
70
+ * attachment: out('start', 'csvFile'),
71
+ * prompt: 'Classify each row by category and write a one-line summary.',
72
+ * outputColumns: [
73
+ * { name: 'Category', description: 'One of: Utility, Software, Travel, Other' },
74
+ * { name: 'Summary', description: 'Plain-English one-line summary of the row' },
75
+ * ],
76
+ * }))
77
+ * .return({ result: out('categorizeRows') })
78
+ * ```
79
+ *
80
+ * @param inputs - The CSV (`attachment`), the instruction (`prompt`), and the
81
+ * `outputColumns` to add to each row.
82
+ * @returns An action spec to pass to `.step(name, …)`.
83
+ */
84
+ export function batchTransform(inputs) {
85
+ return builtinActionSpec({ kind: 'batchTransform', inputs });
86
+ }
@@ -0,0 +1,3 @@
1
+ /** The AI-pattern node family, as flow-node-registry.ts lists it: `uipath.pattern.deep-rag` and `uipath.pattern.batch-transform`. */
2
+ import type { FlowNodeFamily } from '../../../flow-node-type.js';
3
+ export declare const aiPatternsFlowFamily: FlowNodeFamily;
@@ -0,0 +1,8 @@
1
+ import { aiPatternNodeTypes } from './node-type.js';
2
+ export const aiPatternsFlowFamily = {
3
+ id: 'ai-patterns',
4
+ title: 'AI patterns',
5
+ types: aiPatternNodeTypes,
6
+ // No node-local rules: what an AI-pattern step could get wrong is the service's to say.
7
+ diagnostics: {},
8
+ };
@@ -0,0 +1,3 @@
1
+ /** The AI-pattern family's public surface, which the package entry re-exports. */
2
+ export * from './spec.js';
3
+ export * from './factories.js';
@@ -0,0 +1,3 @@
1
+ /** The AI-pattern family's public surface, which the package entry re-exports. */
2
+ export * from './spec.js';
3
+ export * from './factories.js';
@@ -0,0 +1,11 @@
1
+ import type { FlowNodeType } from '../../../flow-node-type.js';
2
+ import type { BatchTransformInputs, SummarizeInputs } from './spec.js';
3
+ export type SummarizeSpec = {
4
+ kind: 'summarize';
5
+ inputs: SummarizeInputs;
6
+ };
7
+ export type BatchTransformSpec = {
8
+ kind: 'batchTransform';
9
+ inputs: BatchTransformInputs;
10
+ };
11
+ export declare const aiPatternNodeTypes: (FlowNodeType<SummarizeSpec> | FlowNodeType<BatchTransformSpec>)[];