@salesforce/afv-skills 1.66.0 → 1.68.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/README.md +55 -5
- package/package.json +2 -4
- package/skills/agentforce-offline-experimentation-run/SKILL.md +26 -49
- package/skills/agentforce-offline-experimentation-run/scripts/bt_compare.py +81 -0
- package/skills/agentforce-offline-experimentation-run/scripts/bt_fetch.py +358 -0
- package/skills/agentforce-offline-experimentation-run/scripts/bt_patch_agent.py +110 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/__init__.py +34 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/agentpatch.py +483 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/agentsrc.py +565 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/cache.py +95 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/compare.py +617 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/fetch.py +1012 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/judge.py +148 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/messages.py +92 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/patch.py +327 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/redact.py +40 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/results.py +288 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/scoring.py +340 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/sfap.py +238 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/splits.py +136 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/stdm.py +98 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/tokens.py +173 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/units.py +199 -0
- package/skills/agentforce-offline-experimentation-run/scripts/btlib/versions.py +194 -0
- package/skills/agentforce-offline-experimentation-run/scripts/build_report.py +366 -378
- package/skills/agentforce-offline-experimentation-run/scripts/resolve-token.sh +14 -4
- package/skills/agentforce-offline-experimentation-run/scripts/sfap_replay.py +472 -796
- package/skills/commerce-react-storefront-create/SKILL.md +350 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/SKILL.md +2 -2
- package/skills/consumer-goods-promotion-bo-api-deploy/references/generate-and-wire.md +28 -16
- package/skills/consumer-goods-promotion-bo-api-deploy/references/smoke-and-verify.md +18 -1
- package/skills/dx-lifecycle-center/SKILL.md +5 -2
- package/skills/dx-lifecycle-center/assets/widgets/connect-connected/connect-connected.json +65 -0
- package/skills/dx-lifecycle-center/assets/widgets/connect-connected/schema.json +32 -0
- package/skills/dx-lifecycle-center/assets/widgets/connect-sign-in/connect-sign-in.json +57 -0
- package/skills/dx-lifecycle-center/assets/widgets/connect-sign-in/schema.json +21 -0
- package/skills/dx-lifecycle-center/examples/workflows.md +20 -6
- package/skills/dx-lifecycle-center/references/connect-org.md +21 -2
- package/skills/dx-lifecycle-center/references/deploy.md +2 -2
- package/skills/dx-lifecycle-center/references/list-orgs.md +1 -1
- package/skills/dx-lifecycle-center/scripts/card-policy.jq +71 -0
- package/skills/dx-lifecycle-center/scripts/fill-widget.jq +29 -0
- package/skills/dx-lifecycle-center/scripts/widget.sh +28 -0
- package/skills/dx-org-devhub-configure/SKILL.md +85 -84
- package/skills/dx-org-devhub-configure/examples/status-output.md +25 -2
- package/skills/dx-org-devhub-configure/scripts/devhub.sh +265 -140
- package/skills/dx-org-devhub-configure/scripts/test-devhub.sh +100 -15
- package/skills/dx-packaging-move-to-2gp-migrate/SKILL.md +89 -0
- package/skills/dx-packaging-move-to-2gp-migrate/references/api-operations.md +164 -0
- package/skills/dx-scratch-def-configure/SKILL.md +163 -0
- package/skills/dx-scratch-def-configure/examples/confirm-card.md +53 -0
- package/skills/dx-scratch-def-configure/examples/report-recipes.md +100 -0
- package/skills/dx-scratch-def-configure/references/features.json +3270 -0
- package/skills/dx-scratch-def-configure/references/project-scratch-def.schema.json +1841 -0
- package/skills/dx-scratch-def-configure/references/settings-map.json +682 -0
- package/skills/dx-scratch-def-configure/scripts/lib_scratch_def.py +1306 -0
- package/skills/dx-scratch-def-configure/scripts/requirements.txt +3 -0
- package/skills/dx-scratch-def-configure/scripts/scrape_config_values.py +848 -0
- package/skills/education-cloud-domain-configure/SKILL.md +22 -24
- package/skills/education-cloud-domain-configure/references/dependent-features.md +9 -0
- package/skills/education-cloud-domain-configure/references/domain-features.md +15 -0
- package/skills/education-cloud-domain-configure/references/gotchas-extended.md +8 -0
- package/skills/education-cloud-domain-configure/references/setup-widgets.md +123 -0
- package/skills/education-cloud-multi-campus-configure/SKILL.md +1 -1
- package/skills/education-cloud-student-recruitment-agent-configure/SKILL.md +1 -1
- package/skills/experience-design-validate/SKILL.md +1 -1
- package/skills/experience-search-coordinate/SKILL.md +19 -13
- package/skills/experience-search-coordinate/references/content-route.md +79 -1
- package/skills/experience-search-coordinate/references/media-route.md +30 -4
- package/skills/experience-ui-bundle-features-generate/SKILL.md +1 -1
- package/skills/experience-ui-bundle-mfa-configure/SKILL.md +1 -1
- package/skills/field-service-data-capture-migrate/SKILL.md +1 -1
- package/skills/platform-apex-generate/SKILL.md +14 -11
- package/skills/platform-apex-test-generate/SKILL.md +2 -1
- package/skills/platform-datamask-run/SKILL.md +52 -71
- package/skills/platform-datamask-run/references/api-surface.md +10 -4
- package/skills/platform-datamask-run/references/policy-authoring.md +56 -7
- package/skills/platform-datamask-run/references/run-and-abort.md +17 -10
- package/skills/platform-datamask-run/scripts/poll-job.sh +15 -25
- package/skills/platform-dataspace-access-configure/SKILL.md +19 -1
- package/skills/platform-metadata-deploy/README.md +1 -1
- package/skills/platform-metadata-deploy/SKILL.md +114 -15
- package/skills/platform-metadata-deploy/references/agent-deployment-guide.md +3 -4
- package/skills/platform-metadata-deploy/references/orchestration.md +2 -3
- package/skills/platform-metadata-discovery-get/SKILL.md +185 -0
- package/skills/platform-metadata-discovery-get/references/api-map.md +25 -0
- package/skills/platform-metadata-discovery-get/references/h360-routes.md +30 -0
- package/skills/platform-metadata-discovery-get/references/scoped-soql.md +52 -0
- package/skills/platform-metadata-grounding-get/SKILL.md +170 -0
- package/skills/platform-policy-rule-generate/SKILL.md +84 -232
- package/skills/platform-policy-rule-generate/references/condition-model.md +47 -0
- package/skills/platform-policy-rule-generate/references/condition-templates.md +89 -0
- package/skills/platform-policy-rule-generate/references/conjunction-compiler.md +25 -0
- package/skills/platform-policy-rule-generate/references/conjunction-expression.md +22 -0
- package/skills/platform-policy-rule-generate/references/consumer-all.md +9 -0
- package/skills/platform-policy-rule-generate/references/consumer-datacloud-ui.md +91 -0
- package/skills/platform-policy-rule-generate/references/deploy-errors.md +24 -36
- package/skills/platform-policy-rule-generate/references/examples/ExistsJoinRLS/package.xml +12 -0
- package/skills/platform-policy-rule-generate/references/examples/ExistsJoinRLS/policyRuleDefinitionSets/ExistsJoinRLS.policyRuleDefinitionSet +6 -0
- package/skills/platform-policy-rule-generate/references/examples/ExistsJoinRLS/policyRuleDefinitions/ExistsJoinRLS_Rule_1.policyRuleDefinition +91 -0
- package/skills/platform-policy-rule-generate/references/examples/FieldReadDeny/package.xml +12 -0
- package/skills/platform-policy-rule-generate/references/examples/FieldReadDeny/policyRuleDefinitionSets/FieldReadDeny.policyRuleDefinitionSet +6 -0
- package/skills/platform-policy-rule-generate/references/examples/FieldReadDeny/policyRuleDefinitions/FieldReadDeny_Rule_1.policyRuleDefinition +72 -0
- package/skills/platform-policy-rule-generate/references/examples/LastCharactersFieldMasking/package.xml +12 -0
- package/skills/platform-policy-rule-generate/references/examples/LastCharactersFieldMasking/policyRuleDefinitionSets/LastCharactersFieldMasking.policyRuleDefinitionSet +6 -0
- package/skills/platform-policy-rule-generate/references/examples/LastCharactersFieldMasking/policyRuleDefinitions/LastCharactersFieldMasking_Rule_1.policyRuleDefinition +77 -0
- package/skills/platform-policy-rule-generate/references/examples/PrincipalFieldMatchRLS/package.xml +12 -0
- package/skills/platform-policy-rule-generate/references/examples/PrincipalFieldMatchRLS/policyRuleDefinitionSets/PrincipalFieldMatchRLS.policyRuleDefinitionSet +6 -0
- package/skills/platform-policy-rule-generate/references/examples/PrincipalFieldMatchRLS/policyRuleDefinitions/PrincipalFieldMatchRLS_Rule_1.policyRuleDefinition +77 -0
- package/skills/platform-policy-rule-generate/references/examples/TaggedObjectAccess/package.xml +12 -0
- package/skills/platform-policy-rule-generate/references/examples/TaggedObjectAccess/policyRuleDefinitionSets/TaggedObjectAccess.policyRuleDefinitionSet +4 -0
- package/skills/platform-policy-rule-generate/references/examples/TaggedObjectAccess/policyRuleDefinitions/TaggedObjectAccess_Rule_1.policyRuleDefinition +65 -0
- package/skills/platform-policy-rule-generate/references/headless-transport.md +87 -0
- package/skills/platform-policy-rule-generate/references/policy-schema-full.md +17 -10
- package/skills/platform-policy-rule-generate/references/policy-shapes.md +74 -0
- package/skills/platform-policy-rule-generate/references/principal-expression.md +31 -0
- package/skills/platform-policy-rule-generate/references/reference-resolution.md +51 -0
- package/skills/platform-policy-rule-generate/references/resource-expression.md +48 -0
- package/skills/platform-policy-rule-generate/references/runtime-context.md +9 -0
- package/skills/platform-policy-rule-generate/references/templates-access.md +11 -9
- package/skills/platform-policy-rule-generate/references/templates-advanced.md +4 -2
- package/skills/platform-policy-rule-generate/references/templates-record.md +37 -22
- package/skills/platform-policy-rule-generate/references/templates-transform.md +10 -8
- package/skills/platform-policy-rule-generate/references/templates.md +2 -2
- package/skills/platform-policy-rule-generate/references/ui-compatibility.md +35 -17
- package/skills/platform-report-generate/SKILL.md +9 -4
- package/skills/platform-report-generate/references/chart-types.md +26 -2
- package/skills/platform-report-generate/references/column-names.md +43 -0
- package/skills/platform-report-generate/references/errors-and-troubleshooting.md +1 -1
- package/skills/platform-report-generate/references/verification-checklist.md +10 -2
- package/skills/platform-value-set-generate/SKILL.md +19 -19
- package/skills/platform-widget-generate/SKILL.md +25 -51
- package/skills/platform-widget-generate/examples/formulas.json +19 -2
- package/skills/platform-widget-generate/examples/localized-labels.json +57 -0
- package/skills/platform-widget-generate/references/widget-actions.md +29 -0
- package/skills/platform-widget-generate/references/widget-bundle-validation.md +1 -0
- package/skills/platform-widget-generate/references/widget-formulas.md +24 -7
- package/skills/platform-widget-generate/references/widget-gotchas.md +10 -0
- package/skills/platform-widget-generate/references/widget-labels.md +78 -0
- package/skills/platform-widget-generate/references/widget-styling.md +12 -0
- package/skills/sales-call-scoring-configure/SKILL.md +17 -10
- package/skills/sales-call-scoring-configure/scripts/enable-call-scoring.sh +55 -33
- package/skills/service-digital-engagement-channel-configure/SKILL.md +11 -7
- package/skills/service-digital-engagement-channel-configure/assets/messaging_channel_template.xml +33 -0
- package/skills/service-digital-engagement-channel-configure/references/channel_settings.md +123 -16
- package/skills/service-digital-engagement-deployment-configure/SKILL.md +37 -100
- package/skills/service-digital-engagement-deployment-configure/assets/esd_web_update_template.xml +83 -8
- package/skills/service-digital-engagement-deployment-configure/examples/esd_web_prechat_fields.xml +74 -0
- package/skills/service-digital-engagement-deployment-configure/references/connect_api_creation.md +13 -3
- package/skills/service-digital-engagement-deployment-configure/references/deployment_settings.md +13 -78
- package/skills/service-digital-engagement-deployment-configure/references/onboarding_contract.md +5 -6
- package/skills/service-digital-engagement-deployment-configure/references/prechat_forms.md +245 -0
- package/skills/service-itsm-agentic-setup-incident-management/SKILL.md +164 -120
- package/skills/service-itsm-agentic-setup-incident-management/examples/output-templates.md +61 -37
- package/skills/service-itsm-agentic-setup-incident-management/references/audit-tracking.md +42 -0
- package/skills/service-itsm-agentic-setup-incident-management/references/broadcast-communications.md +23 -0
- package/skills/service-itsm-agentic-setup-incident-management/references/email-to-incident.md +23 -0
- package/skills/service-itsm-agentic-setup-incident-management/references/incident-dashboards.md +25 -0
- package/skills/service-itsm-agentic-setup-incident-management/references/incident-persona-psg.md +30 -146
- package/skills/service-itsm-agentic-setup-incident-management/references/incident-preferences.md +32 -136
- package/skills/service-itsm-agentic-setup-incident-management/references/major-incident-management.md +32 -155
- package/skills/service-itsm-agentic-setup-incident-management/references/manage-incidents-with-ai.md +45 -0
- package/skills/service-itsm-agentic-setup-incident-management/references/priority-matrix.md +32 -0
- package/skills/service-itsm-agentic-setup-incident-management/references/service-mgmt-privilege.md +30 -140
- package/skills/service-itsm-agentic-setup-incident-management/references/sla-milestones.md +110 -0
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Run through these checks before deploying any generated report metadata.
|
|
4
4
|
|
|
5
|
+
## Before Writing the XML
|
|
6
|
+
- [ ] Check every `<field>` in `<columns>`, `<groupingsDown>`, and `<groupingsAcross>`, every filter `<column>`, and the chart `<groupingColumn>` against the column table for the report type in `references/column-names.md` (or the MCP column list). No bare `NAME` or `USERS.NAME` — use the report type's name column (e.g. `OPPORTUNITY_NAME`, `FULL_NAME`, `OWNER`, `FIRST_NAME` + `LAST_NAME`)
|
|
7
|
+
|
|
5
8
|
## Universal Checks
|
|
6
9
|
- [ ] File extension is `.report-meta.xml`
|
|
7
10
|
- [ ] File is placed under `<sourceDir>/reports/<FolderName>/` (check sfdx-project.json for source path)
|
|
@@ -13,6 +16,8 @@ Run through these checks before deploying any generated report metadata.
|
|
|
13
16
|
- [ ] `<description>` explains the business purpose (max 255 chars)
|
|
14
17
|
- [ ] All column `<field>` values use correct platform column names
|
|
15
18
|
- [ ] Custom field columns use `<ObjectApiName>.<FieldApiName__c>` format
|
|
19
|
+
- [ ] Each `<columns>` contains exactly one `<field>`
|
|
20
|
+
- [ ] Custom report type: `<reportType>` ends in `__c` and every column uses a `<table>$<field>` path from the report type's sections
|
|
16
21
|
|
|
17
22
|
## Format-Specific Checks
|
|
18
23
|
- [ ] Tabular: no `<groupingsDown>`, no `<groupingsAcross>`, no `<chart>`, no `<aggregateTypes>`
|
|
@@ -28,6 +33,7 @@ Run through these checks before deploying any generated report metadata.
|
|
|
28
33
|
- [ ] `<timeFrameFilter>` uses a valid `<interval>` value from `references/date-intervals.md`
|
|
29
34
|
- [ ] Date columns use platform column names (e.g. `CLOSE_DATE`, not `CloseDate`)
|
|
30
35
|
- [ ] Multi-value picklist uses ONE criteriaItem with comma-separated values
|
|
36
|
+
- [ ] No `<params>` the request didn't ask for; Opportunity `probability` param is only `>0`
|
|
31
37
|
|
|
32
38
|
## Grouping Checks
|
|
33
39
|
- [ ] `<dateGranularity>` is set for every grouping (use `None` for non-date fields)
|
|
@@ -38,8 +44,10 @@ Run through these checks before deploying any generated report metadata.
|
|
|
38
44
|
- [ ] Chart is only on Summary or Matrix report
|
|
39
45
|
- [ ] `<chartType>` is a valid type from `references/chart-types.md`
|
|
40
46
|
- [ ] `<groupingColumn>` matches a grouping field
|
|
41
|
-
- [ ] `<chartSummaries>` contains valid `<aggregate>` + `<column
|
|
42
|
-
- [ ] `
|
|
47
|
+
- [ ] `<chartSummaries>` contains valid `<aggregate>` + `<column>`, or ONLY `<column>RowCount</column>` with no `<aggregate>`
|
|
48
|
+
- [ ] No `<columns><field>RowCount</field></columns>` — `RowCount` is only valid in `<chartSummaries><column>`, `<sortByName>`, or a `<calculatedFormula>`
|
|
49
|
+
- [ ] `legendPosition` omitted on single-series `HorizontalBar`/`VerticalColumn`/`Line`; on grouped/stacked charts only `Right` or `Bottom` (see `references/chart-types.md`)
|
|
50
|
+
- [ ] Every `<chart>` child element is in the allowed list in `references/chart-types.md`
|
|
43
51
|
|
|
44
52
|
## Cross-Filter Checks (if applicable)
|
|
45
53
|
- [ ] Maximum 3 cross-filters per report
|
|
@@ -37,7 +37,7 @@ For authoritative Metadata API type, field, and enum details beyond this skill,
|
|
|
37
37
|
| Root element | `<GlobalValueSet>` | `<StandardValueSet>` |
|
|
38
38
|
| Name source | filename (dev name) | `<fullName>` = fixed catalog name |
|
|
39
39
|
| Value element | `<customValue>` | `<standardValue>` |
|
|
40
|
-
| Can add NEW values? | Yes |
|
|
40
|
+
| Can add NEW values? | Yes | Yes — copy the attribute pattern of an existing value |
|
|
41
41
|
| Can create a new NAME? | Yes | No — only the fixed catalog |
|
|
42
42
|
| `*` wildcard in package.xml | Supported | Not supported |
|
|
43
43
|
|
|
@@ -50,7 +50,7 @@ For authoritative Metadata API type, field, and enum details beyond this skill,
|
|
|
50
50
|
This document defines the mandatory constraints for generating value-set metadata XML. The agent must verify these constraints before outputting XML to prevent Metadata API deployment errors.
|
|
51
51
|
|
|
52
52
|
- **GlobalValueSet** — a reusable, named set of picklist values defined once and referenced by any number of picklist/multi-select fields. Use when the same value list is shared across multiple fields.
|
|
53
|
-
- **StandardValueSet** — the value list behind a Salesforce-defined standard picklist (Industry, Lead Source, etc.). You can only
|
|
53
|
+
- **StandardValueSet** — the value list behind a Salesforce-defined standard picklist (Industry, Lead Source, etc.). You can only customize the fixed catalog of named sets, so you cannot invent a new set name, but you can modify existing values and add new ones.
|
|
54
54
|
|
|
55
55
|
---
|
|
56
56
|
|
|
@@ -142,16 +142,16 @@ In API 57.0+ orgs the platform *stores/displays* a GlobalValueSet's developer na
|
|
|
142
142
|
|
|
143
143
|
#### HARD CONSTRAINTS — read before generating
|
|
144
144
|
|
|
145
|
-
1. **
|
|
145
|
+
1. **A StandardValueSet name must come from the fixed catalog of named standard value sets.** You **cannot** create a new StandardValueSet name. You **can** add a new value to an existing standard set, but copy the full attribute pattern of an existing value in that set (for example `closed`, `forecastCategory`, `probability` and `won` on `OpportunityStage`), because omitted attributes are filled with platform defaults that can be wrong.
|
|
146
146
|
2. The root carries a `<fullName>` whose value is the **fixed enum name** (e.g. `Industry`), NOT a `masterLabel`. The filename must match this name.
|
|
147
147
|
3. Values are `<standardValue>` entries — **not** `<customValue>`.
|
|
148
|
-
4. **
|
|
148
|
+
4. **A StandardValueSet write REPLACES the whole set. Send every existing value and change only what the request names.** Read the current set first (grounding MCP or a retrieve), then include a `<standardValue>` block for every existing value, with the requested activations, deactivations, relabels or additions applied. A value you leave out is deactivated on the field: a deploy that named only `Web` in `CaseOrigin` left `Email`, `Phone` and `Agentforce` inactive. Never send only the named values, even when the set is large (for example all 30+ `Industry` entries). Request wording such as "keep *only* X active" means set X active and every other value inactive, so state that intent in the result. Verify by reading the set back and diffing it against the read taken before the write.
|
|
149
149
|
|
|
150
150
|
#### `<standardValue>` — Modifiable Sub-Elements
|
|
151
151
|
|
|
152
152
|
| Sub-element | Modifiable? | Notes |
|
|
153
153
|
|-------------|-------------|-------|
|
|
154
|
-
| `<fullName>` | Identifies the value
|
|
154
|
+
| `<fullName>` | Identifies the value | An existing value, or a new one you are adding |
|
|
155
155
|
| `<label>` | Yes | Relabel the value's UI text |
|
|
156
156
|
| `<isActive>` | Yes | `false` deactivates; omit or `true` keeps active |
|
|
157
157
|
| `<default>` | Yes | At most one value `true` |
|
|
@@ -165,7 +165,7 @@ In API 57.0+ orgs the platform *stores/displays* a GlobalValueSet's developer na
|
|
|
165
165
|
> `https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/standardvalueset_names.htm`.
|
|
166
166
|
> If the name is not in that appendix, it is **not** a StandardValueSet — it is either a GlobalValueSet or an inline CustomField picklist.
|
|
167
167
|
|
|
168
|
-
#### CORRECT — StandardValueSet (
|
|
168
|
+
#### CORRECT — StandardValueSet (the complete set, with the requested change applied)
|
|
169
169
|
|
|
170
170
|
```xml
|
|
171
171
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
@@ -183,6 +183,7 @@ In API 57.0+ orgs the platform *stores/displays* a GlobalValueSet's developer na
|
|
|
183
183
|
<label>Agriculture</label>
|
|
184
184
|
<isActive>false</isActive> <!-- deactivated, but kept in the set -->
|
|
185
185
|
</standardValue>
|
|
186
|
+
<!-- ... every other existing standardValue entry repeated unchanged ... -->
|
|
186
187
|
</StandardValueSet>
|
|
187
188
|
```
|
|
188
189
|
|
|
@@ -192,23 +193,23 @@ In API 57.0+ orgs the platform *stores/displays* a GlobalValueSet's developer na
|
|
|
192
193
|
<StandardValueSet xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
193
194
|
<masterLabel>Industry</masterLabel> <!-- WRONG: StandardValueSet uses <fullName>, not masterLabel -->
|
|
194
195
|
<customValue> <!-- WRONG: uses <standardValue>, not customValue -->
|
|
195
|
-
<fullName>Renewable Energy</fullName>
|
|
196
|
+
<fullName>Renewable Energy</fullName>
|
|
196
197
|
<label>Renewable Energy</label>
|
|
197
198
|
</customValue>
|
|
198
199
|
</StandardValueSet>
|
|
199
200
|
```
|
|
200
201
|
|
|
201
|
-
**Errors:** unknown element `masterLabel`/`customValue
|
|
202
|
+
**Errors:** unknown element `masterLabel`/`customValue` for a StandardValueSet.
|
|
202
203
|
|
|
203
204
|
---
|
|
204
205
|
|
|
205
206
|
### 4. Never Invent Values — Verify, Don't Hallucinate CRITICAL
|
|
206
207
|
|
|
207
|
-
When customizing a **StandardValueSet** (or extending a shared GlobalValueSet), **
|
|
208
|
+
When customizing a **StandardValueSet** (or extending a shared GlobalValueSet), **never invent the existing value list of a standard picklist**. Existing values must be repeated exactly as the org has them, and a new value is added only when the request names it.
|
|
208
209
|
|
|
209
|
-
For well-known standard picklists you already know the canonical values (e.g. `Industry`, `LeadSource`, `OpportunityStage`). When you are unsure
|
|
210
|
+
For well-known standard picklists you already know the canonical values (e.g. `Industry`, `LeadSource`, `OpportunityStage`). When you are unsure which values exist, you can confirm them against the live org — but treat lookup as a *confirmation* step, not a required first call:
|
|
210
211
|
|
|
211
|
-
- **Grounding MCP** (if available) exposes `search_metadata` and `query_metadata` to look up live metadata. Use them
|
|
212
|
+
- **Grounding MCP** (if available) exposes `search_metadata` and `query_metadata` to look up live metadata. Use them to read the complete current set, because a write must repeat every existing value with its exact `<fullName>`/`<label>`.
|
|
212
213
|
- **CLI fallback** — query the Tooling API directly:
|
|
213
214
|
|
|
214
215
|
```bash
|
|
@@ -216,7 +217,7 @@ sf data query --use-tooling-api \
|
|
|
216
217
|
--query "SELECT MasterLabel, Metadata FROM StandardValueSet WHERE MasterLabel = '<name>'"
|
|
217
218
|
```
|
|
218
219
|
|
|
219
|
-
> **The point is the output, not the lookup:**
|
|
220
|
+
> **The point is the output, not the lookup:** the written set must contain every existing value unchanged, plus only the changes the request names. Do not invent values the request did not ask for. (This pairs with rule 4 in §3: a write replaces the whole set.)
|
|
220
221
|
|
|
221
222
|
---
|
|
222
223
|
|
|
@@ -247,17 +248,16 @@ The agent must **reject** and explain — not silently "fix" by inventing metada
|
|
|
247
248
|
|
|
248
249
|
| Violation | Action / Message |
|
|
249
250
|
|-----------|------------------|
|
|
250
|
-
| Add a NEW value to a **StandardValueSet** | Reject. "Standard value sets cannot accept new values. Create a **GlobalValueSet** (reusable) or an inline picklist on a **CustomField** instead." |
|
|
251
251
|
| Create a NEW StandardValueSet name | Reject. The name must be in the standard catalog appendix. Otherwise it is a GlobalValueSet. |
|
|
252
252
|
| **Value set developer name** with spaces / invalid chars | Convert spaces to underscores; must start with a letter; alphanumeric + underscore only. `Priority Levels` → `Priority_Levels`. (This applies to the value SET name and the field API name — NOT to individual `<customValue><fullName>` values, which keep spaces as written.) |
|
|
253
253
|
| Duplicate value `fullName` within one set | Reject. Each `fullName` must be unique within the value set. |
|
|
254
254
|
| More than one `<default>true</default>` | Reject. At most one default value per set. |
|
|
255
255
|
|
|
256
|
-
####
|
|
256
|
+
#### Adding a value to a standard set
|
|
257
257
|
|
|
258
258
|
> "Add a `Cryptocurrency` value to the Industry picklist."
|
|
259
259
|
|
|
260
|
-
|
|
260
|
+
This is allowed. Read the complete current `Industry` set, then write it back with every existing value unchanged plus one new `<standardValue>` for `Cryptocurrency`. Copy the attribute pattern of an existing value in the set, because omitted attributes get platform defaults that can be wrong.
|
|
261
261
|
|
|
262
262
|
---
|
|
263
263
|
|
|
@@ -275,7 +275,7 @@ A value set must deploy **before** any CustomField that references it.
|
|
|
275
275
|
|
|
276
276
|
| Error / Symptom | Cause | Fix |
|
|
277
277
|
|-----------------|-------|-----|
|
|
278
|
-
|
|
|
278
|
+
| Other values of a standard picklist became inactive after a deploy | The deploy listed only some values, and a write replaces the whole set | Resend the complete set with every existing value (§3 rule 4) |
|
|
279
279
|
| `Required field missing: sorted` | GlobalValueSet missing `<sorted>` | Add `<sorted>true</sorted>` or `<sorted>false</sorted>` |
|
|
280
280
|
| Unknown element `masterLabel` (StandardValueSet) | Used `masterLabel` instead of `fullName` | StandardValueSet root uses `<fullName>` = catalog name |
|
|
281
281
|
| Unknown element `customValue` (StandardValueSet) | Used `customValue` instead of `standardValue` | Use `<standardValue>` in standard sets |
|
|
@@ -301,12 +301,12 @@ Before generating value-set XML, verify:
|
|
|
301
301
|
- [ ] When referencing from a field, is `<valueSetName>` the **bare** developer name with NO `__gvs` suffix?
|
|
302
302
|
|
|
303
303
|
### StandardValueSet Checks CRITICAL
|
|
304
|
-
- [ ]
|
|
304
|
+
- [ ] Did you read the complete current set (grounding `search_metadata`/`query_metadata` / Tooling API / retrieve) so every existing value is repeated exactly?
|
|
305
305
|
- [ ] Is the root `<StandardValueSet>` with the correct namespace?
|
|
306
306
|
- [ ] Does the root use `<fullName>` set to the fixed catalog name (NOT `masterLabel`)?
|
|
307
307
|
- [ ] Are values `<standardValue>` entries (NOT `customValue`)?
|
|
308
|
-
- [ ]
|
|
309
|
-
- [ ] Did you avoid
|
|
308
|
+
- [ ] Does the written set contain every existing value, with only the changes the request names applied?
|
|
309
|
+
- [ ] Did you avoid a new set name, and for any new value did you copy the attribute pattern of an existing value?
|
|
310
310
|
|
|
311
311
|
### Shared Checks
|
|
312
312
|
- [ ] At most one value has `<default>true</default>`?
|
|
@@ -119,6 +119,7 @@ On success, read `[0].outputValues`.
|
|
|
119
119
|
- Bind a block property to runtime data with `{!$attrs.<attrName>}`. `<attrName>` MUST match a property name in `schema.json`.
|
|
120
120
|
- Inside a `forEach`, reference the loop variable instead — e.g. `"text": "{!$item.name}"`. See `references/widget-meta-directives.md`.
|
|
121
121
|
- A binding may be a **formula expression** instead of a bare field reference. See `references/widget-formulas.md` for the full supported-function list, syntax, and gotchas.
|
|
122
|
+
- **Localization:** only when the user asks for localized or translated text (or names Custom Labels / `$Label`), write static, user-visible strings as Custom Label references — `{!$Label.c.<LabelName>}`. See `references/widget-labels.md`.
|
|
122
123
|
|
|
123
124
|
---
|
|
124
125
|
|
|
@@ -131,28 +132,7 @@ On success, read `[0].outputValues`.
|
|
|
131
132
|
| `action/openLink` | synchronous | `url` (string). Optional `target` (`_blank`\|`_self`, default `_blank`) | Opens a URL |
|
|
132
133
|
| `action/sendMessage` | asynchronous | `content` (string) | Posts a new user message back to the agent and earns a fresh turn |
|
|
133
134
|
|
|
134
|
-
|
|
135
|
-
{
|
|
136
|
-
"definition": "tile/button",
|
|
137
|
-
"attributes": {
|
|
138
|
-
"label": "Button Label",
|
|
139
|
-
"variant": "primary",
|
|
140
|
-
"actions": { "click": [ { "definition": "action/sendMessage", "attributes": { "content": "content" } } ] }
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
```json
|
|
146
|
-
{
|
|
147
|
-
"definition": "tile/button",
|
|
148
|
-
"attributes": {
|
|
149
|
-
"label": "Button Label",
|
|
150
|
-
"variant": "primary",
|
|
151
|
-
"actions": { "click": [ { "definition": "action/openLink", "attributes": { "url": "https://www.example.com", "target": "_blank" } } ] }
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
```
|
|
155
|
-
|
|
135
|
+
See `references/widget-actions.md` for complete `sendMessage` and `openLink` button JSON.
|
|
156
136
|
|
|
157
137
|
**A `tile/button` with no `actions` attribute renders disabled** — a button exists to trigger an action, so always attach a `click` action to a button meant to be interactive.
|
|
158
138
|
|
|
@@ -175,16 +155,7 @@ These conventions cover widget *structure* — how blocks are grouped and stacke
|
|
|
175
155
|
|
|
176
156
|
## Styling Best Practices
|
|
177
157
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
- **Style semantically.** Use `variant`, `size`, and other enum-typed attributes (`primary`, `destructive`, `success`, `warning`). Do not pin literal colors or pixel values.
|
|
181
|
-
- **One primary action per visible group.** At most one `tile/button` with `variant: primary`. Use `secondary` or `destructive` for additional actions (see the `tile/button` schema for the full variant enum).
|
|
182
|
-
- **Every `tile/button` needs a `click` action.** See *Actions* above — an action-less button renders disabled.
|
|
183
|
-
- **One `h1` per widget.** Use `h2`/`h3` for sub-section headings, `body` for prose, `caption` for helper text.
|
|
184
|
-
- **Use semantic state variants on state-bearing blocks** (`tile/badge`, `tile/callout`).
|
|
185
|
-
- **Accept schema defaults for `gap`, `size`** unless there is a specific reason to override.
|
|
186
|
-
- **Don't pin `width`** unless a content constraint requires it.
|
|
187
|
-
- **Use the Lucide icon set.** Pass the Lucide name (`"check"`, `"alert-circle"`); other icon libraries are not supported.
|
|
158
|
+
Style semantically (variants, not literal colors or pixels), one primary button per group, one `h1` per widget, Lucide icons only. Read `references/widget-styling.md` before assigning variants, sizes, or icons.
|
|
188
159
|
|
|
189
160
|
---
|
|
190
161
|
|
|
@@ -198,7 +169,7 @@ Widgets express *intent*, not pixels. Each surface provides a default look and f
|
|
|
198
169
|
|
|
199
170
|
3. **Select blocks.** Choose one block per widget-spec property, plus structural primitives from *Layout Best Practices*.
|
|
200
171
|
|
|
201
|
-
4. **Get block schemas (REQUIRED — do NOT skip).** Call the `getUiComponentSchemas` invocable action for the selected blocks. Review property metadata. **If `isSuccess` is `false`, `componentSchemas` is empty, or any entry has `success: false`, do not use that block — re-select a different one from step 2's results; if none works, STOP and surface the error. Never improvise from existing widgets in the project.**
|
|
172
|
+
4. **Get block schemas (REQUIRED — do NOT skip).** Call the `getUiComponentSchemas` invocable action for the selected blocks. Review property metadata, including each property's `default` — omit any attribute whose value would equal it (see `references/widget-styling.md`). **If `isSuccess` is `false`, `componentSchemas` is empty, or any entry has `success: false`, do not use that block — re-select a different one from step 2's results; if none works, STOP and surface the error. Never improvise from existing widgets in the project.**
|
|
202
173
|
|
|
203
174
|
5. **Build the UEM tree (example reads REQUIRED — do NOT skip).** First, identify which patterns match the widget spec and read each matching example file from this skill's own `examples/` directory (`<skill-root>/examples/`):
|
|
204
175
|
|
|
@@ -207,12 +178,15 @@ Widgets express *intent*, not pixels. Each surface provides a default look and f
|
|
|
207
178
|
| Single object (no iteration) | `<skill-root>/examples/single-object.json` |
|
|
208
179
|
| Any list iteration (root-level array, nested list, or list embedded in a single-object widget) | `<skill-root>/examples/list-with-foreach.json` |
|
|
209
180
|
| Conditional rendering (`if` bound to a boolean or formula) | `<skill-root>/examples/conditional.json` |
|
|
210
|
-
| Computed values, text/number transforms, or `if` driven by a formula (not a bare boolean field) | `<skill-root>/examples/formulas.json` |
|
|
181
|
+
| Computed values, text/number transforms, locale-formatted numbers/currency/dates, or `if` driven by a formula (not a bare boolean field) | `<skill-root>/examples/formulas.json` |
|
|
182
|
+
| The user asked for localized / translated text (Custom Labels) | `<skill-root>/examples/localized-labels.json` |
|
|
211
183
|
|
|
212
184
|
A spec may match multiple patterns (e.g. a list of items where some items render conditionally reads both `list-with-foreach.json` and `conditional.json`). **Read every matching example, and only those — do not skip the read because the pattern feels familiar.**
|
|
213
185
|
|
|
214
186
|
**Before writing any formula**, read `references/widget-formulas.md` in full — it is the authoritative list of supported operators and functions; do not improvise a function name or operator that isn't documented there.
|
|
215
187
|
|
|
188
|
+
**Before writing any `$Label` reference**, read `references/widget-labels.md` in full.
|
|
189
|
+
|
|
216
190
|
Then:
|
|
217
191
|
- Map each widget-spec property to a block property; preserve spec order.
|
|
218
192
|
- **Decide root iteration:** single object → properties directly under root `tile/column`. Collection → wrap repeating block in `forEach`/`forItem`. See `references/widget-meta-directives.md`.
|
|
@@ -264,6 +238,8 @@ Widgets express *intent*, not pixels. Each surface provides a default look and f
|
|
|
264
238
|
9. **Self-validate.** Before reporting, run the checks and report each result individually (`pass` or `fail (<reason>)`). Do **not** summarize as a single "all passed" line — list every check so a reviewer can spot a silent skip.
|
|
265
239
|
Run every check in `references/widget-bundle-validation.md`.
|
|
266
240
|
|
|
241
|
+
10. **Report labels.** If the widget uses `$Label`, end the response with the label report described in `references/widget-labels.md`.
|
|
242
|
+
|
|
267
243
|
---
|
|
268
244
|
|
|
269
245
|
## Rules / Constraints
|
|
@@ -281,27 +257,25 @@ Run every check in `references/widget-bundle-validation.md`.
|
|
|
281
257
|
|
|
282
258
|
## Gotchas
|
|
283
259
|
|
|
284
|
-
|
|
285
|
-
|---|---|
|
|
286
|
-
| `getUiComponentSchemas` returns a partial-failure entry | Pick a different block from `discoverUiComponents`; do not silently continue without a schema|
|
|
287
|
-
| Body references `{!$attrs.foo}` but `foo` is not under `schema.json` `properties.attributes.properties` | Add `foo` to `schema.json` `properties.attributes.properties` OR remove the body reference|
|
|
288
|
-
| Output written outside `<pkgDir>/uiWidgets/<widgetName>/` | `<pkgDir>` = `<packageDirectories[].path>/main/default` (see `references/widget-bundle-layout.md`). Dropping the `main/default/` segment is the common cause of widgets landing at `force-app/uiWidgets/...` instead of `force-app/main/default/uiWidgets/...` |
|
|
289
|
-
| `if` bound directly to a raw string or number relies on truthiness and is unreliable | Bind to a `lightning__booleanType` property, or use a formula comparison that evaluates to boolean|
|
|
290
|
-
| `tile/button` renders but does nothing when clicked | No `actions.click` entry was set — an action-less button renders disabled by design. Add one (see *Actions* above)|
|
|
291
|
-
| Using `action/sendMessage` for pure navigation, or `action/openLink` when the agent should respond | `action/openLink` is synchronous and does not consume a turn; `action/sendMessage` is asynchronous and earns a fresh turn. Pick the one matching the intended UX|
|
|
260
|
+
Known failure modes and fixes (partial schemas, unresolved bindings, wrong output path, `if` truthiness, dead buttons, action choice): see `references/widget-gotchas.md`.
|
|
292
261
|
|
|
293
262
|
---
|
|
294
263
|
|
|
295
264
|
## Reference File Index
|
|
296
265
|
|
|
297
|
-
| File | When to read|
|
|
298
|
-
|
|
299
|
-
| `references/widget-meta-directives.md` | For `forEach` / `forItem` (iteration) and `if` (conditional rendering), including nested loops|
|
|
300
|
-
| `references/schema-from-lightning-type.md` | When `lightningTypeSchema` is provided; how to derive the widget `schema.json` from an Apex-backed Lightning Type|
|
|
301
|
-
| `references/widget-bundle-layout.md` | Folder layout, `-meta.xml` shape, `<pkgDir>` resolution rules|
|
|
266
|
+
| File | When to read |
|
|
267
|
+
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
268
|
+
| `references/widget-meta-directives.md` | For `forEach` / `forItem` (iteration) and `if` (conditional rendering), including nested loops |
|
|
269
|
+
| `references/schema-from-lightning-type.md` | When `lightningTypeSchema` is provided; how to derive the widget `schema.json` from an Apex-backed Lightning Type |
|
|
270
|
+
| `references/widget-bundle-layout.md` | Folder layout, `-meta.xml` shape, `<pkgDir>` resolution rules |
|
|
302
271
|
| `references/widget-bundle-validation.md` | Step 9 — the checks to run before reporting |
|
|
303
|
-
| `references/widget-formulas.md` | Supported formula functions and operators|
|
|
304
|
-
| `
|
|
272
|
+
| `references/widget-formulas.md` | Supported formula functions and operators, including locale format functions (`FORMATNUMBER`, `FORMATCURRENCY`, `FORMATDATE`, …) |
|
|
273
|
+
| `references/widget-labels.md` | Localization — `$Label` syntax, naming and reuse, allowed attributes, combining with data, creating labels, and the label report |
|
|
274
|
+
| `references/widget-actions.md` | Complete `tile/button` JSON for `action/sendMessage` and `action/openLink` |
|
|
275
|
+
| `references/widget-styling.md` | Variant, size, heading, and icon conventions |
|
|
276
|
+
| `references/widget-gotchas.md` | Known failure modes and their fixes |
|
|
277
|
+
| `examples/single-object.json` | Single-object pattern (root binding via `{!$attrs.X}`, no iteration) |
|
|
305
278
|
| `examples/list-with-foreach.json` | Any list-iteration case — root-level collections, nested lists, and lists embedded inside a single-object widget (e.g. iterating a `List<InnerClass>` inside an outer Apex payload) |
|
|
306
|
-
| `examples/conditional.json` | Conditional pattern (`if` on `meta`, including `if` + `forEach` together)|
|
|
307
|
-
| `examples/formulas.json` | Formula usage — text/arithmetic/date transforms, `IF`/`AND`/`NOT` driving both a `tile/text` and `meta.if
|
|
279
|
+
| `examples/conditional.json` | Conditional pattern (`if` on `meta`, including `if` + `forEach` together) |
|
|
280
|
+
| `examples/formulas.json` | Formula usage — text/arithmetic/date transforms, locale format functions, `IF`/`AND`/`NOT` driving both a `tile/text` and `meta.if` |
|
|
281
|
+
| `examples/localized-labels.json` | Localization — `$Label` in a heading, caption, badge (`IF` choosing between labels), button label, and a label joined with data |
|
|
@@ -138,6 +138,23 @@
|
|
|
138
138
|
|
|
139
139
|
{ "definition": "tile/spacer", "attributes": { "size": "sm" } },
|
|
140
140
|
|
|
141
|
+
{
|
|
142
|
+
"definition": "tile/column",
|
|
143
|
+
"attributes": { "gap": "xs" },
|
|
144
|
+
"children": [
|
|
145
|
+
{ "definition": "tile/text", "attributes": { "text": "9. Locale format functions", "variant": "h3" } },
|
|
146
|
+
{ "definition": "tile/text", "attributes": { "text": "FORMATNUMBER: {!FORMATNUMBER($attrs.price)} | precision 0: {!FORMATNUMBER($attrs.price, 0)}" } },
|
|
147
|
+
{ "definition": "tile/text", "attributes": { "text": "FORMATCURRENCY: {!FORMATCURRENCY($attrs.price)}" } },
|
|
148
|
+
{ "definition": "tile/text", "attributes": { "text": "FORMATPERCENT: {!FORMATPERCENT($attrs.winProbability)} | precision 1: {!FORMATPERCENT($attrs.winProbability, 1)}" } },
|
|
149
|
+
{ "definition": "tile/text", "attributes": { "text": "FORMATDATE: {!FORMATDATE($attrs.departureDate)} | long: {!FORMATDATE($attrs.departureDate, 'long')}" } },
|
|
150
|
+
{ "definition": "tile/text", "attributes": { "text": "FORMATDATETIME: {!FORMATDATETIME($attrs.departureDateTime)} | medium: {!FORMATDATETIME($attrs.departureDateTime, 'medium')}" } },
|
|
151
|
+
{ "definition": "tile/text", "attributes": { "text": "FORMATTIME: {!FORMATTIME($attrs.departureDateTime)} | long: {!FORMATTIME($attrs.departureDateTime, 'long')}" } },
|
|
152
|
+
{ "definition": "tile/text", "attributes": { "text": "{!'Fare with tax: ' & FORMATCURRENCY($attrs.price * (1 + $attrs.taxRate))}", "variant": "h4" } }
|
|
153
|
+
]
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
{ "definition": "tile/spacer", "attributes": { "size": "sm" } },
|
|
157
|
+
|
|
141
158
|
{
|
|
142
159
|
"definition": "tile/column",
|
|
143
160
|
"meta": { "if": "{!AND($attrs.isPriority, $attrs.price > 500)}" },
|
|
@@ -147,7 +164,7 @@
|
|
|
147
164
|
"attributes": { "gap": "sm", "align": "center" },
|
|
148
165
|
"children": [
|
|
149
166
|
{ "definition": "tile/icon", "attributes": { "name": "lightning", "color": "warning" } },
|
|
150
|
-
{ "definition": "tile/text", "attributes": { "text": "
|
|
167
|
+
{ "definition": "tile/text", "attributes": { "text": "10. Formula-driven meta.if: priority fare over $500 — expedited handling" } }
|
|
151
168
|
]
|
|
152
169
|
}
|
|
153
170
|
]
|
|
@@ -160,7 +177,7 @@
|
|
|
160
177
|
"meta": { "forEach": "{!$attrs.flights}", "forItem": "$flight" },
|
|
161
178
|
"attributes": { "gap": "xs" },
|
|
162
179
|
"children": [
|
|
163
|
-
{ "definition": "tile/text", "attributes": { "text": "
|
|
180
|
+
{ "definition": "tile/text", "attributes": { "text": "11. forEach + per-row formula", "variant": "h3" } },
|
|
164
181
|
{
|
|
165
182
|
"definition": "tile/row",
|
|
166
183
|
"attributes": { "justify": "between", "align": "center" },
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "lightning__agentforceWidget",
|
|
3
|
+
"contentBody": {
|
|
4
|
+
"widgetBody": {
|
|
5
|
+
"definition": "tile/widget",
|
|
6
|
+
"children": [
|
|
7
|
+
{
|
|
8
|
+
"definition": "tile/column",
|
|
9
|
+
"attributes": { "gap": "md" },
|
|
10
|
+
"children": [
|
|
11
|
+
{
|
|
12
|
+
"definition": "tile/text",
|
|
13
|
+
"attributes": { "text": "{!$Label.c.OrderStatus_Heading}", "variant": "h1" }
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"definition": "tile/row",
|
|
17
|
+
"attributes": { "gap": "sm", "align": "center" },
|
|
18
|
+
"children": [
|
|
19
|
+
{
|
|
20
|
+
"definition": "tile/text",
|
|
21
|
+
"attributes": { "text": "{!$Label.c.OrderStatus_OrderNumberCaption}", "variant": "caption" }
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"definition": "tile/text",
|
|
25
|
+
"attributes": { "text": "{!$attrs.orderNumber}" }
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"definition": "tile/badge",
|
|
31
|
+
"attributes": {
|
|
32
|
+
"label": "{!IF($attrs.isShipped, $Label.c.OrderStatus_ShippedStatus, $Label.c.OrderStatus_ProcessingStatus)}",
|
|
33
|
+
"variant": "{!IF($attrs.isShipped, 'success', 'info')}"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"definition": "tile/text",
|
|
38
|
+
"attributes": { "text": "{!$Label.c.OrderStatus_ItemsPrefix & ' ' & TEXT($attrs.itemCount)}" }
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"definition": "tile/button",
|
|
42
|
+
"attributes": {
|
|
43
|
+
"label": "{!$Label.c.OrderStatus_TrackButton}",
|
|
44
|
+
"variant": "primary",
|
|
45
|
+
"actions": {
|
|
46
|
+
"click": [
|
|
47
|
+
{ "definition": "action/openLink", "attributes": { "url": "{!$attrs.trackingUrl}" } }
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Widget Actions
|
|
2
|
+
|
|
3
|
+
Complete `tile/button` examples for the two supported action definitions. The action table and the action-less-button rule live in SKILL.md *Actions*.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## `action/sendMessage` and `action/openLink`
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"definition": "tile/button",
|
|
12
|
+
"attributes": {
|
|
13
|
+
"label": "Button Label",
|
|
14
|
+
"variant": "primary",
|
|
15
|
+
"actions": { "click": [ { "definition": "action/sendMessage", "attributes": { "content": "content" } } ] }
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"definition": "tile/button",
|
|
23
|
+
"attributes": {
|
|
24
|
+
"label": "Button Label",
|
|
25
|
+
"variant": "primary",
|
|
26
|
+
"actions": { "click": [ { "definition": "action/openLink", "attributes": { "url": "https://www.example.com" } } ] }
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
@@ -12,3 +12,4 @@ Report each check individually as `pass` or `fail (<reason>)`.
|
|
|
12
12
|
- **`metaxml-elements`** — `<widgetName>.uiwidget-meta.xml` has root `<UiWidgetBundle>` and contains `<masterLabel>` (non-empty), `<description>` (non-empty), and `<widgetType>JSON</widgetType>`.
|
|
13
13
|
- **`files-present`** — all three files exist at the resolved `<pkgDir>/uiWidgets/<widgetName>/` path.
|
|
14
14
|
- **`button-actions-present`** — every `tile/button` in `<widgetName>.json` has an `actions.click` action node whose `definition` is `action/openLink` or `action/sendMessage`.
|
|
15
|
+
- **`labels-valid`** — if the user did not ask for localization, `<widgetName>.json` contains no `$Label` (report `pass (not requested)`). Otherwise every `$Label` follows the rules in `references/widget-labels.md` and appears in the step 10 report.
|
|
@@ -17,6 +17,7 @@ Every formula expression is wrapped in `{!...}`, similar to a plain binding:
|
|
|
17
17
|
- Functions and operators are case-sensitive UPPERCASE.
|
|
18
18
|
- A formula can nest functions and mix functions with operators: `{!TEXT(ROUND($attrs.property, 2))}`, `{!LEFT($attrs.property, 5) & "..."}`.
|
|
19
19
|
- A formula-bearing attribute is still bound to schema properties the same way as a plain binding — every `$attrs.X` / `$item.X` referenced inside a formula must resolve to a real schema property or loop variable, per the `bindings-resolve` self-validation check.
|
|
20
|
+
- A Custom Label reference `$Label.c.<LabelName>` can be used as a text value inside a formula. See `references/widget-labels.md`.
|
|
20
21
|
|
|
21
22
|
---
|
|
22
23
|
|
|
@@ -34,7 +35,7 @@ Only the operators/functions listed here are confirmed supported — do not inve
|
|
|
34
35
|
| `/` | Divide | `$attrs.operand1 / $attrs.operand2` |
|
|
35
36
|
| `^` | Exponent | `$attrs.operand1 ^ $attrs.operand2` |
|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
Unary minus (`-$attrs.fieldName`) is also supported. Precedence, lowest to highest: `||`, `&&`, equality, relational, `+` `-` `&`, `^`, `*` `/`, unary. Note that `*` and `/` bind tighter than `^`, so `2 * 3 ^ 2` is `(2 * 3) ^ 2`; parenthesize to be explicit.
|
|
38
39
|
|
|
39
40
|
### 2. Comparison operators
|
|
40
41
|
|
|
@@ -47,36 +48,40 @@ Return `true`/`false`; commonly used inside `IF()` or `meta.if`.
|
|
|
47
48
|
| `>` / `<` | Greater / less than | `$attrs.property > 1000` |
|
|
48
49
|
| `>=` / `<=` | Greater-or-equal / less-or-equal | `$attrs.property1 >= $attrs.property2` |
|
|
49
50
|
|
|
51
|
+
`==` and `!=` are accepted as aliases for `=` and `<>`. Both operands must have the same type; text is never compared with a number.
|
|
52
|
+
|
|
50
53
|
### 3. Logical functions
|
|
51
54
|
|
|
52
55
|
| Function | Description | Example |
|
|
53
56
|
|---|---|------------------------------------------------------------------------------------------------------|
|
|
54
|
-
| `IF(cond, then, else)` | Conditional value; nests for multi-branch logic | `IF($attrs.property > value, 'result1', 'result2')` |
|
|
57
|
+
| `IF(cond, then, else)` | Conditional value; nests for multi-branch logic. `cond` must be a boolean (`IF($attrs.count > 0, …)`, not `IF($attrs.count, …)`) and both branches must have the same type | `IF($attrs.property > value, 'result1', 'result2')` |
|
|
55
58
|
| `CASE(expr, val1, res1, val2, res2, ..., default)` | Multi-way match, cleaner than nested `IF` for 3+ branches | `CASE($attrs.property, 'value1', 'result1', 'value2', 'result2', 'value3', 'result3', 'defaultResult')` |
|
|
56
59
|
| `AND(...)` | All conditions true | `AND($attrs.property1, $attrs.property2 > value)` |
|
|
57
60
|
| `OR(...)` | Any condition true | `OR($attrs.property1, $attrs.property2 > value)` |
|
|
58
61
|
| `NOT(val)` | Negate a boolean | `NOT($attrs.property)` |
|
|
59
|
-
|
|
|
62
|
+
| `&&` / `\|\|` / `!` (operators) | Aliases for `AND` / `OR` / `NOT` | `$attrs.property1 && !$attrs.property2` |
|
|
63
|
+
| `ISNULL(val)` | True if the value is null. Always false for text — use `ISBLANK` for strings | `IF(ISNULL($attrs.property), 'null', 'has-value')` |
|
|
60
64
|
| `ISBLANK(val)` | True if null or empty string | `IF(ISBLANK($attrs.property), 'blank', 'has-value')` |
|
|
61
65
|
|
|
62
66
|
### 4. Text functions
|
|
63
67
|
|
|
64
68
|
| Function | Description | Example |
|
|
65
69
|
|---|---|-----------------------------------------------------|
|
|
66
|
-
| `UPPER(str)` / `LOWER(str)` | Case conversion | `UPPER($attrs.property)` |
|
|
70
|
+
| `UPPER(str[, locale])` / `LOWER(str[, locale])` | Case conversion, optionally for a locale such as `'tr'` | `UPPER($attrs.property)` |
|
|
67
71
|
| `LEFT(str, n)` / `RIGHT(str, n)` | First/last `n` characters | `LEFT($attrs.property, 3)` |
|
|
68
72
|
| `MID(str, start, len)` | Substring, **1-based** start index (first character is position 1, not 0) | `MID($attrs.property, 1, 3)` |
|
|
73
|
+
| `SUBSTR(str, start[, len])` | Substring with a **1-based** start; a negative `start` counts from the end; without `len`, runs to the end | `SUBSTR($attrs.property, -4)` |
|
|
69
74
|
| `LEN(val)` | Length of a string | `LEN($attrs.property)` |
|
|
70
75
|
| `TRIM(str)` | Strip leading/trailing whitespace | `TRIM($attrs.property)` |
|
|
71
76
|
| `REVERSE(str)` | Reverse a string | `REVERSE($attrs.property)` |
|
|
72
77
|
| `SUBSTITUTE(str, old, new)` | Replace all occurrences | `SUBSTITUTE($attrs.property, 'string1', 'string2')` |
|
|
73
|
-
| `FIND(search, str)` | 1-based index of `search` in `str`, or
|
|
78
|
+
| `FIND(search, str[, start])` | 1-based index of `search` in `str`, or `0` if absent; optional 1-based `start` position | `FIND('string', $attrs.property)` |
|
|
74
79
|
| `LPAD(str, len, pad)` / `RPAD(str, len, pad)` | Pad to a fixed width | `LPAD($attrs.property, 12, '.')` |
|
|
75
80
|
| `TEXT(val)` | Coerce a non-string value to text (commonly paired with `ROUND`) | `TEXT(ROUND($attrs.property, 2))` |
|
|
76
81
|
| `VALUE(str)` | Parse text to a number (inverse of `TEXT`) | `VALUE($attrs.property)` |
|
|
77
82
|
| `CONTAINS(str, sub)` | String contains substring — boolean, pair with `IF` | `CONTAINS($attrs.property, 'string')` |
|
|
78
83
|
| `BEGINS(str, prefix)` | String starts with — boolean, pair with `IF` | `BEGINS($attrs.property, 'string')` |
|
|
79
|
-
| `&` (operator) | Concatenate strings | `$attrs.property1 & ' — ' & $attrs.property2` |
|
|
84
|
+
| `&` (operator) | Concatenate strings. Both sides must be text, so wrap numbers and dates in `TEXT()` — `'Total: ' & TEXT($attrs.total)` | `$attrs.property1 & ' — ' & $attrs.property2` |
|
|
80
85
|
|
|
81
86
|
### 5. Math functions
|
|
82
87
|
|
|
@@ -99,7 +104,7 @@ Return `true`/`false`; commonly used inside `IF()` or `meta.if`.
|
|
|
99
104
|
| `DAY(date)` / `MONTH(date)` / `YEAR(date)` | Extract date components | `DAY(DATEVALUE($attrs.fieldName))` |
|
|
100
105
|
| `WEEKDAY(date)` | Day of week, `1`=Sunday … `7`=Saturday | `WEEKDAY(DATEVALUE($attrs.fieldName))` |
|
|
101
106
|
| `ADDMONTHS(date, n)` | Add `n` whole months to a date | `ADDMONTHS(DATEVALUE($attrs.fieldName), 3)` |
|
|
102
|
-
| `TODAY()` / `NOW()` / `TIMENOW()` | Current
|
|
107
|
+
| `TODAY()` / `NOW()` / `TIMENOW()` | Current date / datetime / time in UTC — no arguments | `TODAY()` |
|
|
103
108
|
| `DATE(year, month, day)` | Construct a date literal | `DATE(2026, 12, 31)` |
|
|
104
109
|
| `HOUR(dt)` / `MINUTE(dt)` / `SECOND(dt)` / `MILLISECOND(dt)` | Extract time components from a datetime | `HOUR(NOW())` |
|
|
105
110
|
|
|
@@ -121,3 +126,15 @@ A raw date/datetime **string** attribute (e.g. an ISO string from `$attrs`) must
|
|
|
121
126
|
| `ISNUMBER(val)` | True if the value parses as a number | `ISNUMBER($attrs.fieldName)` |
|
|
122
127
|
| `REGEX(str, pattern)` | True if `str` matches the regex `pattern` (standard regex string) | `REGEX($attrs.fieldName, '^[A-Z]{2} [0-9]+$')` |
|
|
123
128
|
|
|
129
|
+
### 9. Locale formatting functions
|
|
130
|
+
|
|
131
|
+
Format values for the viewer's locale. A null or blank input returns null. The optional last argument is a decimal count for the number functions and `'short'` (default), `'medium'` or `'long'` for the date and time functions.
|
|
132
|
+
|
|
133
|
+
| Function | Description | Example |
|
|
134
|
+
|---|---|---|
|
|
135
|
+
| `FORMATNUMBER(num[, decimals])` | Locale-formatted number | `FORMATNUMBER($attrs.fieldName, 2)` |
|
|
136
|
+
| `FORMATPERCENT(num[, decimals])` | Locale-formatted percent (`0.25` → `25%`) | `FORMATPERCENT($attrs.fieldName, 1)` |
|
|
137
|
+
| `FORMATCURRENCY(num)` | Currency code followed by the amount, e.g. `USD 1,234.50` (no currency symbol) | `FORMATCURRENCY($attrs.fieldName)` |
|
|
138
|
+
| `FORMATDATE(date[, style])` | Locale date | `FORMATDATE($attrs.fieldName, 'medium')` |
|
|
139
|
+
| `FORMATDATETIME(dt[, style])` | Locale date and time | `FORMATDATETIME($attrs.fieldName, 'long')` |
|
|
140
|
+
| `FORMATTIME(time[, style])` | Locale time | `FORMATTIME($attrs.fieldName)` |
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Widget Generation Gotchas
|
|
2
|
+
|
|
3
|
+
| Issue | Resolution |
|
|
4
|
+
|---|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
5
|
+
| `getUiComponentSchemas` returns a partial-failure entry | Pick a different block from `discoverUiComponents`; do not silently continue without a schema |
|
|
6
|
+
| Body references `{!$attrs.foo}` but `foo` is not under `schema.json` `properties.attributes.properties` | Add `foo` to `schema.json` `properties.attributes.properties` OR remove the body reference |
|
|
7
|
+
| Output written outside `<pkgDir>/uiWidgets/<widgetName>/` | `<pkgDir>` = `<packageDirectories[].path>/main/default` (see `references/widget-bundle-layout.md`). Dropping the `main/default/` segment is the common cause of widgets landing at `force-app/uiWidgets/...` instead of `force-app/main/default/uiWidgets/...` |
|
|
8
|
+
| `if` bound directly to a raw string or number relies on truthiness and is unreliable | Bind to a `lightning__booleanType` property, or use a formula comparison that evaluates to boolean |
|
|
9
|
+
| `tile/button` renders but does nothing when clicked | No `actions.click` entry was set — an action-less button renders disabled by design. Add one (see SKILL.md *Actions*) |
|
|
10
|
+
| Using `action/sendMessage` for pure navigation, or `action/openLink` when the agent should respond | `action/openLink` is synchronous and does not consume a turn; `action/sendMessage` is asynchronous and earns a fresh turn. Pick the one matching the intended UX |
|