Skip to content

Commit 13b3d45

Browse files
song-zhao-25claude
andauthored
fix(maestro-case): structured filter tree docs, reference-ID reuse warning (#426)
1. Structured filter tree (MST-8802 / Skills#304): - connector-trigger-common.md §7: replace flat JMESPath table with structured filter tree shape, operators (13 listed + SDK enum ref), examples (single, multi-AND, nested AND/OR) - essentialConfiguration: filter is now <filter-tree-or-null> - Input body: CLI auto-generates JMESPath from tree - What NOT to Do: "don't hand-write JMESPath" + "don't use filterExpression" - Dynamic =vars.X limitation documented 2. Reference-ID reuse warning (Skills#348): - connector-trigger-common.md + connector-activity/impl-json.md: "Never reuse reference IDs across connections" 3. connector-integration.md: add structured tree note to Filter Syntax section Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 27eef16 commit 13b3d45

3 files changed

Lines changed: 84 additions & 10 deletions

File tree

skills/uipath-maestro-case/references/connector-integration.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ Input keys come from the `describe` response (Step 4): typically `body`, `queryP
9292
9393
## Filter Expression Syntax
9494
95+
> **Note:** The direct JSON write path uses structured filter trees (see [connector-trigger-common.md §7](connector-trigger-common.md#7-build-input-values-and-filter)) instead of flat filter expressions. The CLI internally converts event parameters to a structured filter tree.
96+
9597
Trigger `data.filter` (or `node.data.uipath.filter` for event triggers) uses the connector's filter DSL. Common patterns:
9698
9799
| Pattern | Example |

skills/uipath-maestro-case/references/connector-trigger-common.md

Lines changed: 81 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,83 @@ If an SDD input matches an `eventParameters` field name, it's an event parameter
8282
{"parentFolderId": "AAMkADNm..."}
8383
```
8484
85-
**filter** — translate SDD filter criteria using `filterFields` from Step 3. Use JMESPath syntax. Supports `=vars.X` for runtime case variable references:
85+
**filter** — translate SDD filter criteria using `filterFields` from Step 3. Build a **structured filter tree** (NOT a flat JMESPath string). The CLI converts the tree to a JMESPath expression automatically.
8686
87-
| Pattern | JMESPath |
87+
#### Filter tree shape
88+
89+
```json
90+
{
91+
"groupOperator": 0,
92+
"index": 0,
93+
"filters": [
94+
{
95+
"id": "<fieldName from filterFields>",
96+
"operator": "<PascalCase operator>",
97+
"value": { "value": "<literal>", "rawString": "\"<literal>\"", "isLiteral": true }
98+
}
99+
],
100+
"groups": []
101+
}
102+
```
103+
104+
- `groupOperator`: `0` (And) or `1` (Or) — combines sibling filters and groups
105+
- `filters[]`: leaf conditions. `id` must be a field name from `filterFields` (Step 3)
106+
- `groups[]`: nested sub-trees for mixed AND/OR logic (empty for simple cases)
107+
108+
#### Operators
109+
110+
| Pattern | Operator |
88111
|---|---|
89-
| Exact match (static) | `(fieldName == 'value')` |
90-
| Exact match (dynamic variable) | `(fieldName == '=vars.variableName')` |
91-
| Substring match | `(contains(fieldName, 'value'))` |
92-
| Multiple conditions | `(fieldA == 'x' && fieldB == 'y')` |
112+
| Exact match | `"Equals"` |
113+
| Not equal | `"NotEquals"` |
114+
| Substring match | `"Contains"` |
115+
| Does not contain | `"NotContains"` |
116+
| Starts with | `"StartsWith"` |
117+
| Greater than | `"GreaterThan"` |
118+
| Less than | `"LessThan"` |
119+
| Is empty | `"IsEmpty"` |
120+
| Is not empty | `"IsNotEmpty"` |
121+
| One of (multi-value) | `"In"` |
122+
| Not one of | `"NotIn"` |
123+
| Is null | `"IsNull"` |
124+
| Is not null | `"IsNotNull"` |
125+
126+
> See the IS SDK `FilterOperator` enum for the complete list (includes `Like`, `NotLike`, datetime operators, etc.).
127+
128+
#### Examples
129+
130+
Single filter (AND with one leaf):
131+
```json
132+
{ "groupOperator": 0, "index": 0, "filters": [
133+
{ "id": "subject", "operator": "Contains", "value": { "value": "urgent", "rawString": "\"urgent\"", "isLiteral": true } }
134+
], "groups": [] }
135+
```
136+
137+
Multiple conditions (AND):
138+
```json
139+
{ "groupOperator": 0, "index": 0, "filters": [
140+
{ "id": "project", "operator": "Equals", "value": { "value": "PROJ", "rawString": "\"PROJ\"", "isLiteral": true } },
141+
{ "id": "issuetype", "operator": "Equals", "value": { "value": "Bug", "rawString": "\"Bug\"", "isLiteral": true } }
142+
], "groups": [] }
143+
```
144+
145+
Nested AND/OR (e.g., "status is Open AND (priority > 3 OR assignee is null)"):
146+
```json
147+
{ "groupOperator": 0, "index": 0, "filters": [
148+
{ "id": "status", "operator": "Equals", "value": { "value": "Open", "rawString": "\"Open\"", "isLiteral": true } }
149+
], "groups": [
150+
{ "groupOperator": 1, "index": 1, "filters": [
151+
{ "id": "priority", "operator": "GreaterThan", "value": { "value": 3, "rawString": "\"3\"", "isLiteral": true } },
152+
{ "id": "assignee", "operator": "IsNull", "value": null }
153+
], "groups": [] }
154+
] }
155+
```
156+
157+
No filter (trigger fires on all events): omit `filter` from the tasks.md entry entirely.
158+
159+
#### Dynamic variable limitation
160+
161+
The filter tree only supports `isLiteral: true` values. When a filter requires runtime case variable references (`=vars.X`), write the `body.filters.expression` JMESPath string directly and leave `essentialConfiguration.filter` as `null`. This is a known SDK limitation shared with flow-tool.
93162
94163
Only use field names that appear in `filterFields`. If a filter cannot be translated unambiguously, **AskUserQuestion**.
95164
@@ -183,16 +252,16 @@ Every context entry MUST include `"type": "string"` (or `"type": "json"` for met
183252
### essentialConfiguration
184253
185254
```
186-
=jsonString:{"essentialConfiguration":{"instanceParameters":{"connectorKey":"<connector-key>","objectName":"<object-name>","activityType":"CuratedWaitFor","version":"<Config.version>","eventOperation":"<enrichment.operation>","eventMode":"<event-mode>","supportsStreaming":<Config.supportsStreaming>},"objectName":"<object-name>","packageVersion":"<Config.version>","connectorVersion":"<enrichment.connectorVersion>","executionType":null,"httpMethod":null,"path":null,"filter":null}}
255+
=jsonString:{"essentialConfiguration":{"instanceParameters":{"connectorKey":"<connector-key>","objectName":"<object-name>","activityType":"CuratedWaitFor","version":"<Config.version>","eventOperation":"<enrichment.operation>","eventMode":"<event-mode>","supportsStreaming":<Config.supportsStreaming>},"objectName":"<object-name>","packageVersion":"<Config.version>","connectorVersion":"<enrichment.connectorVersion>","executionType":null,"httpMethod":null,"path":null,"filter":<filter-tree-or-null>}}
187256
```
188257
189258
> **Critical:** `activityType` MUST be `"CuratedWaitFor"` — NOT `Config.activityType` (which is `"CuratedTrigger"`).
190259
191-
> `filter` is always `null` in essentialConfiguration. The filter goes in `inputs[].body.filters.expression` only.
260+
> When a structured filter tree is provided (from §7), store it in `essentialConfiguration.filter` so Studio Web can round-trip the filter UI. The derived JMESPath expression goes in `inputs[].body.filters.expression`. When no filter is needed, `filter` stays `null`.
192261
193262
### Input body (from tasks.md values)
194263
195-
If `input-values` has event parameters, convert to JMESPath + combine with `filter`:
264+
If `input-values` has event parameters, the CLI auto-generates the JMESPath expression from the structured filter tree. The body contains:
196265
197266
```json
198267
{
@@ -225,7 +294,9 @@ After writing root bindings, populate IS connection cache per [bindings-v2-sync.
225294
## What NOT to Do (shared)
226295
227296
- **Do NOT use `CuratedTrigger`** in essentialConfiguration. It MUST be `CuratedWaitFor`.
228-
- **Do NOT put filter in `essentialConfiguration.filter`.** It stays `null`. Filter goes in `body.filters.expression`.
297+
- **Do NOT hand-write JMESPath filter expressions.** Build a structured filter tree (§7); the CLI derives the expression automatically.
298+
- **Do NOT use `filterExpression` as a CLI input.** The CLI rejects raw `filterExpression` strings (MST-8802).
299+
- **Never reuse a reference ID from a prior case or session.** Reference IDs (mailbox folders, Slack channels, Jira projects) are scoped to the authenticated account behind each connection. Always resolve fresh via `uip is resources execute list` against the current `--connection-id`.
229300
- **Do NOT add `body.parameters`.** Only `body.filters.expression` + `body.queryParams`.
230301
- **Do NOT auto-inject `entryConditions`** (for tasks). Step 10 handles them.
231302

skills/uipath-maestro-case/references/plugins/tasks/connector-activity/impl-json.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ All issues appended to the shared issue list per [logging/impl-json.md](../../lo
280280
- **Do NOT omit `file` input** when `enrichment.multipartParameters` has a file entry. Include it even when empty.
281281
- **Do NOT add `data.name`.** The FE does not use it for connector tasks.
282282
- **Do NOT auto-inject `entryConditions`.** Step 10 handles them — injecting here creates duplicates.
283+
- **Never reuse a reference ID from a prior case or session.** Reference IDs (e.g., Jira project keys, Slack channel IDs) are scoped to the authenticated account behind each connection. Always resolve fresh via `uip is resources execute list` against the current `--connection-id`.
283284
284285
## Known Limitation
285286

0 commit comments

Comments
 (0)