fix(ai-builder): Default Switch to case-insensitive in builder hints (#31044)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
José Braulio González Valido 2026-05-27 08:42:54 +01:00 committed by GitHub
parent e71837765b
commit 76c432c53f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 16 additions and 15 deletions

View File

@ -10,7 +10,7 @@
},
{
"role": "user",
"text": "JSON with `level` (high, medium, or low), `title`, and `message`. Each notification should be forwarded with title + message intact."
"text": "JSON with `level` (\"High\", \"Medium\" or \"Low\"), `title`, and `message`. Each notification should be forwarded with title + message intact."
},
{
"role": "assistant",
@ -29,19 +29,19 @@
{
"name": "high-priority",
"description": "A high-priority notification is routed to Microsoft Teams",
"dataSetup": "The webhook receives { \"level\": \"high\", \"title\": \"Server Down\", \"message\": \"Production database is unreachable\" }. The Microsoft Teams node returns a success response.",
"dataSetup": "The webhook receives { \"level\": \"High\", \"title\": \"Server Down\", \"message\": \"Production database is unreachable\" }. The Microsoft Teams node returns a success response.",
"successCriteria": "The workflow routes the high-priority notification to Microsoft Teams. The Teams message contains 'Server Down' and the database message. No other channels receive the message."
},
{
"name": "medium-priority",
"description": "A medium-priority notification is routed to Slack",
"dataSetup": "The webhook receives { \"level\": \"medium\", \"title\": \"Deployment Complete\", \"message\": \"Version 2.5.0 deployed to staging\" }. The Slack node returns a success response.",
"dataSetup": "The webhook receives { \"level\": \"Medium\", \"title\": \"Deployment Complete\", \"message\": \"Version 2.5.0 deployed to staging\" }. The Slack node returns a success response.",
"successCriteria": "The workflow routes the medium-priority notification to Slack #notifications. The Slack message contains the deployment details."
},
{
"name": "low-priority",
"description": "A low-priority notification is routed to email",
"dataSetup": "The webhook receives { \"level\": \"low\", \"title\": \"Weekly Report Ready\", \"message\": \"The weekly analytics report has been generated\" }. The Gmail node returns a success response.",
"dataSetup": "The webhook receives { \"level\": \"Low\", \"title\": \"Weekly Report Ready\", \"message\": \"The weekly analytics report has been generated\" }. The Gmail node returns a success response.",
"successCriteria": "The workflow routes the low-priority notification to Gmail. The email is sent to alerts@ourcompany.com with the report notification."
}
]

View File

@ -16,7 +16,7 @@ The Switch node routes items to different outputs based on conditions. Uses the
{
"conditions": {
"options": {
"caseSensitive": true,
"caseSensitive": false,
"leftValue": "",
"typeValidation": "strict"
},
@ -41,10 +41,11 @@ The Switch node routes items to different outputs based on conditions. Uses the
\`\`\`
#### Key Points:
1. Each entry in rules.values[] creates ONE output
2. Conditions use the same filter structure as IF node
3. Multiple conditions per rule are combined with combinator ("and" or "or")
4. Use renameOutput: true + outputKey to label outputs descriptively
1. **Default \`caseSensitive: false\` for string comparisons.** Real-world inputs vary in casing (\`"high"\` vs \`"High"\` vs \`"HIGH"\`). Only set \`caseSensitive: true\` when the user has explicitly said case matters — if you're not sure, ask them before guessing.
2. Each entry in rules.values[] creates ONE output
3. Conditions use the same filter structure as IF node
4. Multiple conditions per rule are combined with combinator ("and" or "or")
5. Use renameOutput: true + outputKey to label outputs descriptively
#### Numeric Operators
- lt: Less than
@ -68,6 +69,6 @@ Use two conditions with combinator: "and":
**String-Based Routing** (status/type values):
- Use type: "string" with operation: "equals"
- Set caseSensitive: false in options for case-insensitive matching
- Keep \`caseSensitive: false\` (the default above) unless the user explicitly asked for case-sensitive matching
`,
};

View File

@ -27,7 +27,7 @@ function createCtx(nodes: Map<string, GraphNode> = new Map()): PluginContext {
}
const VALID_CONDITIONS = {
options: { caseSensitive: true, leftValue: '', typeValidation: 'strict' },
options: { caseSensitive: false, leftValue: '', typeValidation: 'strict' },
conditions: [
{
leftValue: '={{ $json.field }}',

View File

@ -37,7 +37,7 @@ function validateFilterValue(
if (!filterValue.options || typeof filterValue.options !== 'object') {
issues.push({
code: 'FILTER_MISSING_OPTIONS',
message: `${nodeRef} is missing 'options' in ${paramPath}. Add: options: { caseSensitive: true, leftValue: '', typeValidation: 'strict' }`,
message: `${nodeRef} is missing 'options' in ${paramPath}. Add: options: { caseSensitive: false, leftValue: '', typeValidation: 'strict' }`,
severity: 'error',
nodeName,
originalName,

View File

@ -75,7 +75,7 @@ const routeByPriority = switchCase({
{
outputKey: 'urgent',
conditions: {
options: { caseSensitive: true, leftValue: '', typeValidation: 'strict' },
options: { caseSensitive: false, leftValue: '', typeValidation: 'strict' },
conditions: [{ leftValue: expr('{{ $json.priority }}'), operator: { type: 'string', operation: 'equals' }, rightValue: 'urgent' }],
combinator: 'and'
}
@ -83,7 +83,7 @@ const routeByPriority = switchCase({
{
outputKey: 'normal',
conditions: {
options: { caseSensitive: true, leftValue: '', typeValidation: 'strict' },
options: { caseSensitive: false, leftValue: '', typeValidation: 'strict' },
conditions: [{ leftValue: expr('{{ $json.priority }}'), operator: { type: 'string', operation: 'equals' }, rightValue: 'normal' }],
combinator: 'and'
}
@ -180,7 +180,7 @@ export default workflow('id', 'name')
type: 'fixedCollection',
builderHint: {
propertyHint:
"Use `rules.values` (NOT `rules.rules`). Each rule needs `outputKey` and a complete `conditions` object with these three sibling keys: `combinator` ('and' | 'or'), `conditions` (array of condition objects), `options` (`{ caseSensitive, leftValue, typeValidation }`). Same shape as IF. Wire rule outputs by zero-based index with `.onCase(index, target)`; `outputKey` is the visible output label, not the `.onCase()` argument. Unwired cases silently drop their items.",
"Use `rules.values` (NOT `rules.rules`). Each rule needs `outputKey` and a complete `conditions` object with these three sibling keys: `combinator` ('and' | 'or'), `conditions` (array of condition objects), `options` (`{ caseSensitive, leftValue, typeValidation }`). Same shape as IF. Wire rule outputs by zero-based index with `.onCase(index, target)`; `outputKey` is the visible output label, not the `.onCase()` argument. Unwired cases silently drop their items. Default `caseSensitive: false` for string equality, only set `true` when specifically requested or confirmed by the user.",
},
typeOptions: {
multipleValues: true,