Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .commitlintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module.exports = {
'apollo-react',
'apollo-wind',
'ap-chat',
'flow-node-schema',

// Apps scopes
'apollo-vertex',
Expand Down
85 changes: 85 additions & 0 deletions .github/workflows/flow-node-schema-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: Flow Node Schema Release

on:
push:
branches:
- main
paths:
- 'packages/flow-node-schema/**'
- '.github/workflows/flow-node-schema-release.yml'

env:
GH_NPM_REGISTRY_TOKEN: ${{ secrets.GH_NPM_REGISTRY_TOKEN }}
NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
TURBO_TELEMETRY_DISABLED: 1
DO_NOT_TRACK: 1

concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false

jobs:
release:
name: Release @uipath/flow-node-schema
runs-on: ubuntu-latest
permissions:
contents: write
packages: write

steps:
- name: Checkout code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0
token: ${{ secrets.RELEASE_TOKEN }}

- name: Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4

- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 22
cache: 'pnpm'

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build flow-node-schema
run: pnpm --filter @uipath/flow-node-schema build

- name: Test flow-node-schema
run: pnpm --filter @uipath/flow-node-schema test

- name: Setup git user
run: |
git config --global user.name "semantic-release-bot"
git config --global user.email "semantic-release-bot@users.noreply.github.com"

- name: Release
env:
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
GH_NPM_REGISTRY_TOKEN: ${{ secrets.GH_NPM_REGISTRY_TOKEN }}
HUSKY: 0
working-directory: packages/flow-node-schema
run: semantic-release

- name: Commit version bump
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are we doing a separate pipeline for this? Should all work with the normal release pipeline

env:
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
run: |
if [ -n "$(git status --porcelain packages/flow-node-schema)" ]; then
git add packages/flow-node-schema/
git commit -m "chore(release): @uipath/flow-node-schema version bump [skip ci]"

if ! git push; then
echo "::error::Failed to push version bump commit"
exit 1
fi
echo "✓ Pushed version bump commit"
else
echo "No changes to commit"
fi
1 change: 1 addition & 0 deletions packages/apollo-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@
"sanitize-html": "^2.17.0",
"unist-util-visit": "^5.0.0",
"use-sync-external-store": "^1.2.0",
"@uipath/flow-node-schema": "workspace:*",
"zod": "^4.3.5",
"zustand": "^5.0.9"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,67 +1,2 @@
/**
* Category Manifest Schemas
*
* Zod schemas for category definitions.
* Supports arbitrary nesting using parent references.
* Nodes define their own category membership.
*/

import { z } from 'zod';

/**
* Category manifest from server
*
* Categories form a hierarchy using parentId references:
* - { id: 'control-flow', parentId: null } (root)
* - { id: 'decision', parentId: 'control-flow' } (child)
* - { id: 'advanced', parentId: 'decision' } (grandchild)
*
* Nodes define which categories they belong to via category property.
* This allows:
* - Stable category IDs (reorganization just changes parentId)
* - Nodes control their own categorization
*/
export const categoryManifestSchema = z.object({
/**
* Unique category identifier
*
* Should be stable by version.
* Examples: 'control-flow', 'decision', 'loops', 'advanced'
*/
id: z.string().min(1),

/** Human-readable category name */
name: z.string().min(1),

/**
* Parent category ID for nesting
*
* - null or undefined: root category
* - string: ID of parent category
*
* Categories can be reorganized by changing this field without
* affecting node references or constraint definitions.
*/
parentId: z.string().optional(),

/**
* Sort order for display within the same parent level
* Categories at the same level are sorted by this value
*/
sortOrder: z.number().int().nonnegative(),

/** Light mode color/gradient */
color: z.string().min(1),

/** Dark mode color/gradient */
colorDark: z.string().min(1),

/** Icon identifier */
icon: z.string().min(1),

/** Tags for search and filtering */
tags: z.array(z.string()),
});

// Export inferred type
export type CategoryManifest = z.infer<typeof categoryManifestSchema>;
export type { CategoryManifest } from '@uipath/flow-node-schema';
export { categoryManifestSchema } from '@uipath/flow-node-schema';
142 changes: 2 additions & 140 deletions packages/apollo-react/src/canvas/schema/node-definition/constraints.ts
Original file line number Diff line number Diff line change
@@ -1,140 +1,2 @@
/**
* Connection Constraints
*
* Defines semantic rules for valid connections between nodes and handles.
* Focus on workflow composition semantics, not just data types.
*/

import { z } from 'zod';

/**
* Specific node and handle targeting
* Used for precise semantic constraints like "Agent Model can only connect to Agent node's 'model' handle"
*/
export const handleTargetSchema = z.object({
/**
* Specific node type this can connect to
* Example: "uipath.agent" (exact match, no wildcards)
*/
nodeType: z.string(),

/**
* Specific handle ID on the target node
* Example: "model", "input", "configuration"
*/
handleId: z.string().optional(),
});

/**
* Connection constraint configuration for a handle
*/
export const connectionConstraintSchema = z.object({
/**
* Maximum number of connections allowed
* - 1: Single connection only
* - undefined: Unlimited connections
*/
maxConnections: z.number().int().positive().optional(),

/**
* Minimum number of connections required (for validation)
* Example: Trigger output must connect to at least 1 node
*/
minConnections: z.number().int().nonnegative().optional(),

/**
* WHITELIST: Allowed target nodes/handles (for source handles)
* If specified, this handle can ONLY connect to these specific targets
*
* Example: Agent Model output can only connect to Agent node's "model" handle
* ```
* allowedTargets: [
* { nodeType: "uipath.agent", handleId: "model" }
* ]
* ```
*/
allowedTargets: z.array(handleTargetSchema).optional(),

/**
* BLACKLIST: Forbidden target nodes/handles (for source handles)
* If specified, this handle CANNOT connect to these targets
*
* Example: Control flow cannot connect to triggers
* ```
* forbiddenTargets: [
* { nodeType: "uipath.trigger.*" }
* ]
* ```
*/
forbiddenTargets: z.array(handleTargetSchema).optional(),

/**
* WHITELIST: Allowed source nodes/handles (for target handles)
* If specified, this handle can ONLY accept connections from these sources
*
* Example: Agent's "model" handle can only accept Agent Model nodes
* ```
* allowedSources: [
* { nodeType: "uipath.ai.agent-model" }
* ]
* ```
*/
allowedSources: z.array(handleTargetSchema).optional(),

/**
* BLACKLIST: Forbidden source nodes/handles (for target handles)
* If specified, this handle CANNOT accept connections from these sources
*/
forbiddenSources: z.array(handleTargetSchema).optional(),

/**
* Required target categories
* If specified, can only connect to nodes in these categories
* Example: ["agent", "data-and-tools"]
*/
allowedTargetCategories: z.array(z.string()).optional(),

/**
* Forbidden target categories
* If specified, cannot connect to nodes in these categories
* Example: ["control-flow", "trigger"]
*/
forbiddenTargetCategories: z.array(z.string()).optional(),

/**
* Required source categories (for target handles)
*/
allowedSourceCategories: z.array(z.string()).optional(),

/**
* Forbidden source categories (for target handles)
*/
forbiddenSourceCategories: z.array(z.string()).optional(),

/**
* Custom validation expression
* Template expression that must evaluate to true for connection to be valid
* Context: sourceNode, targetNode, sourceHandle, targetHandle
* Example: "{sourceNode.model.agentType === targetNode.model.agentType}"
*/
customValidation: z.string().optional(),

/**
* Error message to show when connection is invalid
* Supports template expressions
* Example: "Agent Model can only connect to Agent node's model handle"
*/
validationMessage: z.string().optional(),

/**
* Severity level for constraint violations
* Controls whether violations appear as errors or warnings
* - 'error' (default): Blocks execution/publish
* - 'warning': Shows advisory badge but doesn't block
*/
severity: z.enum(['warning', 'error', 'critical', 'info']).optional(),
});

// Export inferred types
export type HandleTarget = z.infer<typeof handleTargetSchema>;
export type ConnectionConstraint = z.infer<typeof connectionConstraintSchema>;
export type { HandleTarget, ConnectionConstraint } from '@uipath/flow-node-schema';
export { handleTargetSchema, connectionConstraintSchema } from '@uipath/flow-node-schema';
Loading
Loading