@salesforce/afv-skills 1.24.0 → 1.25.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/package.json +1 -1
- package/skills/commerce-b2b-open-code-components-replace/SKILL.md +244 -0
- package/skills/commerce-b2b-open-code-components-replace/assets/ootb-to-open-code-mapping.json +66 -0
- package/skills/dx-org-manage/SKILL.md +192 -0
- package/skills/dx-org-manage/examples/README.md +45 -0
- package/skills/dx-org-manage/examples/scratch-orgs/error_no_devhub.json +9 -0
- package/skills/dx-org-manage/examples/scratch-orgs/error_timeout.json +13 -0
- package/skills/dx-org-manage/examples/scratch-orgs/success_definition_file.json +28 -0
- package/skills/dx-org-manage/examples/scratch-orgs/success_edition.json +26 -0
- package/skills/dx-org-manage/examples/scratch-orgs/success_snapshot.json +27 -0
- package/skills/dx-org-manage/examples/snapshots/error_output.json +9 -0
- package/skills/dx-org-manage/examples/snapshots/success_output.json +15 -0
- package/skills/dx-org-manage/references/cli_flags.md +67 -0
- package/skills/dx-org-manage/references/creating-scratch-org.md +164 -0
- package/skills/dx-org-manage/references/creating-snapshot.md +103 -0
- package/skills/dx-org-manage/references/definition_file_options.md +224 -0
- package/skills/dx-org-manage/references/edition_types.md +78 -0
- package/skills/dx-org-manage/references/opening-org.md +160 -0
- package/skills/dx-org-manage/references/snapshot_usage.md +74 -0
- package/skills/dx-org-permission-set-assign/SKILL.md +98 -0
- package/skills/dx-org-permission-set-assign/examples/error_output.json +19 -0
- package/skills/dx-org-permission-set-assign/examples/success_output.json +16 -0
- package/skills/dx-org-permission-set-assign/references/cli_flags.md +68 -0
- package/skills/experience-cms-brand-apply/SKILL.md +1 -1
- package/skills/experience-ui-bundle-app-coordinate/SKILL.md +31 -19
- package/skills/experience-ui-bundle-file-upload-generate/SKILL.md +1 -1
- package/skills/experience-ui-bundle-frontend-generate/implementation/header-footer.md +1 -1
- package/skills/experience-ui-bundle-salesforce-data-access/SKILL.md +336 -581
- package/skills/experience-ui-bundle-salesforce-data-access/references/caching.md +172 -0
- package/skills/experience-ui-bundle-salesforce-data-access/references/graphiti-cli.md +373 -0
- package/skills/experience-ui-bundle-salesforce-data-access/references/graphql-hand-authoring.md +376 -0
- package/skills/experience-ui-bundle-salesforce-data-access/references/migration.md +119 -0
- package/skills/experience-ui-bundle-salesforce-data-access/references/rest-and-integration.md +152 -0
- package/skills/experience-ui-bundle-salesforce-data-access/references/sdk-api.md +217 -0
- package/skills/experience-ui-bundle-salesforce-data-access/scripts/graphql-search.sh +36 -9
- package/skills/platform-agentsetup-categories-fetch/SKILL.md +109 -0
- package/skills/platform-agentsetup-categories-fetch/references/api-response-schema.md +121 -0
- package/skills/platform-custom-object-generate/SKILL.md +62 -7
- package/skills/platform-custom-object-generate/references/description-enrichment.md +125 -0
- package/skills/platform-metadata-retrieve/SKILL.md +121 -0
- package/skills/platform-metadata-retrieve/examples/error_output.json +10 -0
- package/skills/platform-metadata-retrieve/examples/success_output.json +27 -0
- package/skills/platform-metadata-retrieve/references/cli_flags.md +138 -0
- package/skills/platform-metadata-retrieve/references/retrieval_modes.md +181 -0
- package/skills/platform-sharing-rules-generate/SKILL.md +165 -0
- package/skills/platform-sharing-rules-generate/references/rule-types.md +199 -0
- package/skills/platform-tracing-agentforce-configure/SKILL.md +118 -0
- package/skills/platform-tracing-agentforce-configure/assets/AgentforcePlatformTracing-template.xml +4 -0
- package/skills/platform-tracing-configure/SKILL.md +118 -0
- package/skills/platform-tracing-configure/assets/EventSettings-template.xml +4 -0
- package/skills/platform-trust-archive-manage/SKILL.md +25 -11
- package/skills/platform-trust-archive-manage/examples/monitor-failed-jobs.md +2 -2
- package/skills/platform-trust-archive-manage/references/archive-activity-entity.md +1 -1
- package/skills/platform-trust-archive-manage/references/connect-api-operations.md +51 -12
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# The Data SDK call API (`@salesforce/platform-sdk`)
|
|
2
|
+
|
|
3
|
+
The `query`/`mutate` namespace, typing, and error handling. For caching and the reactive
|
|
4
|
+
refresh modes see [caching.md](caching.md); for old→new conversion see [migration.md](migration.md).
|
|
5
|
+
|
|
6
|
+
## Import
|
|
7
|
+
|
|
8
|
+
```typescript
|
|
9
|
+
import { createDataSDK, gql, type CacheControl, type NodeOfConnection } from "@salesforce/platform-sdk";
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
`createDataSDK`, `gql`, `CacheControl`, and `NodeOfConnection` all come from
|
|
13
|
+
**`@salesforce/platform-sdk`**. The old `@salesforce/sdk-data` package name is dead — any
|
|
14
|
+
`@salesforce/sdk-data` string you see in the repo is a stale `dist/` build artifact, not the
|
|
15
|
+
canonical import.
|
|
16
|
+
|
|
17
|
+
## `sdk.graphql` is a NAMESPACE, not a callable
|
|
18
|
+
|
|
19
|
+
The previous SDK exposed `sdk.graphql` as a callable: `await sdk.graphql?.(query, vars)`.
|
|
20
|
+
That form is gone. `sdk.graphql` is now a namespace with two methods:
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
const sdk = await createDataSDK();
|
|
24
|
+
|
|
25
|
+
// QUERY — reactive, cached on WebApp
|
|
26
|
+
const result = await sdk.graphql!.query<TData, TVariables>({
|
|
27
|
+
query: MY_QUERY, // gql-tagged string (the `query` key)
|
|
28
|
+
variables, // optional
|
|
29
|
+
operationName, // optional
|
|
30
|
+
cacheControl, // optional — see caching.md
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// MUTATE — request/response, never cached
|
|
34
|
+
const { data, errors } = await sdk.graphql!.mutate<TData, TVariables>({
|
|
35
|
+
mutation: MY_MUTATION, // NOTE: the key is `mutation`, not `query`
|
|
36
|
+
variables,
|
|
37
|
+
operationName,
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Type signatures (from `core/data.ts`):
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
query<T, V>(options: QueryOptions<V>): Promise<QueryResult<T>>;
|
|
45
|
+
mutate<T, V>(options: MutateOptions<V>): Promise<MutationResult<T>>;
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### `sdk.graphql!` vs guard
|
|
49
|
+
|
|
50
|
+
`sdk.graphql` may still be `undefined` on surfaces that do not support data operations, so it
|
|
51
|
+
is typed `graphql?: DataSDKGraphQL`. Real consumer code asserts it is present after
|
|
52
|
+
`createDataSDK()` with the non-null assertion:
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
const result = await sdk.graphql!.query<...>({ query, variables });
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
This replaces the old optional-call `sdk.graphql?.(...)`. Do **not** reach for the dead
|
|
59
|
+
callable form. Which of `!` vs a guard you use is a **surface decision** (the spine's
|
|
60
|
+
[Surfaces](../SKILL.md#surfaces--sdkgraphql-vs-guard) table is the routing): `!` only if the
|
|
61
|
+
bundle is WebApp-exclusive; otherwise guard, because a bare `sdk.graphql!` that later ships to
|
|
62
|
+
another surface throws `Cannot read properties of undefined` at runtime — TypeScript won't catch
|
|
63
|
+
it because `!` silences exactly that check.
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
// `!` form — WebApp-only bundles; every shipped WebApp consumer uses it.
|
|
67
|
+
const result = await sdk.graphql!.query<...>({ query, variables });
|
|
68
|
+
|
|
69
|
+
// Portable guard form — safe on every surface. Use when the bundle is not WebApp-exclusive.
|
|
70
|
+
if (!sdk.graphql) {
|
|
71
|
+
// No data SDK on this surface — degrade gracefully (render empty, throw, or feature-flag off).
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const result = await sdk.graphql.query<...>({ query, variables });
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
(The same `!`-vs-guard call applies to `sdk.fetch!`.)
|
|
78
|
+
|
|
79
|
+
## `QueryResult<T>` — the reactive query handle
|
|
80
|
+
|
|
81
|
+
`query()` resolves to a `QueryResult<T>`, which IS a snapshot AND carries two reactive methods:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
interface QuerySnapshot<T> { data: T | undefined; errors?: GraphQLError[]; }
|
|
85
|
+
type QuerySubscriber<T> = (snapshot: QuerySnapshot<T>) => void;
|
|
86
|
+
type Unsubscribe = () => void;
|
|
87
|
+
|
|
88
|
+
interface QueryResult<T> extends QuerySnapshot<T> {
|
|
89
|
+
subscribe(cb: QuerySubscriber<T>): Unsubscribe;
|
|
90
|
+
refresh(): Promise<void>;
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
- `result.data` / `result.errors` — the initial snapshot at await-time (cached value on cached
|
|
95
|
+
surfaces, else the network response).
|
|
96
|
+
- `result.subscribe(cb)` — register a callback for every *subsequent* snapshot (a cache update,
|
|
97
|
+
a stale-while-revalidate refill, or an explicit `refresh()`). Returns an `Unsubscribe`. Each
|
|
98
|
+
`subscribe` is **independent** — unsubscribing one leaves the others live — and it does **not**
|
|
99
|
+
fire on registration, only on later snapshots.
|
|
100
|
+
- `result.refresh()` — re-issue the request bypassing the cache, write the fresh result back, and
|
|
101
|
+
push the new snapshot to **all** current subscribers. Returns `Promise<void>`.
|
|
102
|
+
|
|
103
|
+
*When* to reach for `subscribe`/`refresh` over the default cache, plus the uncached-surface
|
|
104
|
+
caveats, is a strategy call — see [caching.md](caching.md).
|
|
105
|
+
|
|
106
|
+
## `cacheControl` — the per-call cache policy
|
|
107
|
+
|
|
108
|
+
`cacheControl` is an optional field on the query options bag. It overrides the default cache
|
|
109
|
+
behavior for **one** call and does **not** change the cache key, so a `"no-cache"` call and a
|
|
110
|
+
default call read/write the *same* cache slot. The type:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
type CacheControlShorthand = "no-cache" | "only-if-cached";
|
|
114
|
+
interface CacheControlMaxAge { type: "max-age"; maxAge: number; }
|
|
115
|
+
type CacheControl = CacheControlShorthand | CacheControlMaxAge;
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
| `cacheControl` | Behavior |
|
|
119
|
+
|---|---|
|
|
120
|
+
| *(omitted)* | Default — return the cached entry if fresh (300s TTL), else fetch and write back. |
|
|
121
|
+
| `"no-cache"` | Skip the cache **read**, always hit the network. **Still writes the response back** for later default callers. |
|
|
122
|
+
| `"only-if-cached"` | Read from cache **only**. Hit → return; **miss → `DataNotFoundError` on `result.errors`** (no network, no throw). |
|
|
123
|
+
| `{ type: "max-age", maxAge: <seconds> }` | Custom TTL instead of 300s. `maxAge: 0` = written but immediately stale; invalid values silently fall back to 300s. |
|
|
124
|
+
|
|
125
|
+
An `only-if-cached` miss is not an exception — the Promise resolves and the miss surfaces on
|
|
126
|
+
`result.errors` as a `DataNotFoundError`. This is offline-first: a miss is **expected, not an
|
|
127
|
+
error**. Check `result.errors`, render an empty state, and **do not fall back to a network read**
|
|
128
|
+
— a fallback defeats the point of `only-if-cached`:
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
const result = await sdk.graphql!.query({ query: GET_ACCOUNTS, variables, cacheControl: "only-if-cached" });
|
|
132
|
+
if (result.errors?.length) {
|
|
133
|
+
// cold cache — render the empty state. Do NOT fall back to the network; that defeats offline-first.
|
|
134
|
+
return renderEmptyState();
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Which policy fits which goal (force-refresh button, offline-first, fast-changing data) is a
|
|
139
|
+
strategy call — see the decision matrix in [caching.md](caching.md).
|
|
140
|
+
|
|
141
|
+
## `MutationResult<T>` — one-shot, NO subscribe/refresh
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
interface MutationResult<T> { data: T | undefined; errors?: GraphQLError[]; }
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Mutations are request/response. The type deliberately has **no** `subscribe` and **no**
|
|
148
|
+
`refresh` — mutating on subscribe is incoherent, and re-running a mutation on refresh is
|
|
149
|
+
dangerous. To refresh data after a mutation, hold a query `result` and call `result.refresh()`
|
|
150
|
+
(see [caching.md](caching.md)).
|
|
151
|
+
|
|
152
|
+
## HTTP 200 ≠ success — always read `errors`
|
|
153
|
+
|
|
154
|
+
The Promise resolves even for GraphQL/parse errors; they surface on `result.errors`, never as a
|
|
155
|
+
thrown exception from `query()`/`mutate()`. Both shipped consumers gate on `errors` first:
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
// accounts.ts pattern
|
|
159
|
+
if (result.errors?.length) {
|
|
160
|
+
throw new Error(result.errors.map((e) => e.message).join("; "));
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
// graphqlClient.ts (canonical scaffold) — strict wrapper
|
|
166
|
+
export async function executeGraphQL<TData, TVariables>(
|
|
167
|
+
query: string,
|
|
168
|
+
variables?: TVariables,
|
|
169
|
+
): Promise<TData> {
|
|
170
|
+
const sdk = await createDataSDK();
|
|
171
|
+
const result = await sdk.graphql!.query<TData, TVariables>({ query, variables });
|
|
172
|
+
if (result.errors?.length) {
|
|
173
|
+
throw new Error(`GraphQL Error: ${result.errors.map((e) => e.message).join("; ")}`);
|
|
174
|
+
}
|
|
175
|
+
if (result.data == null) {
|
|
176
|
+
throw new Error("GraphQL response data is null");
|
|
177
|
+
}
|
|
178
|
+
return result.data;
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Three error-handling stances (all read `result.errors`):
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
// Strict — any errors = failure
|
|
186
|
+
if (result.errors?.length) throw new Error(result.errors.map((e) => e.message).join("; "));
|
|
187
|
+
|
|
188
|
+
// Tolerant — log, use whatever data came back (partial success)
|
|
189
|
+
if (result.errors?.length) console.warn("GraphQL partial errors:", result.errors);
|
|
190
|
+
|
|
191
|
+
// Discriminated — fail only when NO data returned
|
|
192
|
+
if (!result.data && result.errors?.length) {
|
|
193
|
+
throw new Error(result.errors.map((e) => e.message).join("; "));
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Generated types on the call
|
|
198
|
+
|
|
199
|
+
After `npm run graphql:codegen`, import the generated `<Op>Query` / `<Op>QueryVariables` types
|
|
200
|
+
and pass them as the type parameters. The call shape changed — types now go on `.query()`, not
|
|
201
|
+
the old callable:
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
import type { GetAccountsQuery, GetAccountsQueryVariables } from "../graphql-operations-types";
|
|
205
|
+
|
|
206
|
+
const result = await sdk.graphql!.query<GetAccountsQuery, GetAccountsQueryVariables>({
|
|
207
|
+
query: GET_ACCOUNTS,
|
|
208
|
+
variables,
|
|
209
|
+
});
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
`NodeOfConnection<T>` extracts a node type from a Connection for cleaner typing:
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
import { type NodeOfConnection } from "@salesforce/platform-sdk";
|
|
216
|
+
type AccountNode = NodeOfConnection<GetAccountsQuery["uiapi"]["query"]["Account"]>;
|
|
217
|
+
```
|
|
@@ -2,13 +2,20 @@
|
|
|
2
2
|
set -euo pipefail # exit on error (-e), undefined vars (-u), and propagate pipeline failures (-o pipefail)
|
|
3
3
|
# graphql-search.sh — Look up one or more Salesforce entities in schema.graphql.
|
|
4
4
|
#
|
|
5
|
-
# Run from the SFDX project root
|
|
6
|
-
# bash scripts/graphql-search.sh Account
|
|
7
|
-
# bash scripts/graphql-search.sh Account Contact Opportunity
|
|
5
|
+
# Run from the SFDX project root, where schema.graphql lives:
|
|
6
|
+
# bash <skill-dir>/scripts/graphql-search.sh Account
|
|
7
|
+
# bash <skill-dir>/scripts/graphql-search.sh Account Contact Opportunity
|
|
8
8
|
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
9
|
+
# The script does NOT search up the directory tree — an ancestor schema.graphql
|
|
10
|
+
# may belong to a DIFFERENT org, and silently matching it would validate fields
|
|
11
|
+
# against the wrong schema. If schema.graphql is not at ./ you must point the
|
|
12
|
+
# script at the right file explicitly (resolution order, first hit wins):
|
|
13
|
+
# 1. -s / --schema <path> explicit flag
|
|
14
|
+
# 2. $GRAPHQL_SCHEMA env var explicit override
|
|
15
|
+
# 3. ./schema.graphql (current working directory only)
|
|
16
|
+
#
|
|
17
|
+
# bash <skill-dir>/scripts/graphql-search.sh -s force-app/main/default/uiBundles/<app>/schema.graphql Account
|
|
18
|
+
# GRAPHQL_SCHEMA=/abs/path/schema.graphql bash <skill-dir>/scripts/graphql-search.sh Account
|
|
12
19
|
#
|
|
13
20
|
# Output sections per entity:
|
|
14
21
|
# 1. Type definition — all fields and relationships
|
|
@@ -19,7 +26,7 @@ set -euo pipefail # exit on error (-e), undefined vars (-u), and propagate pipe
|
|
|
19
26
|
# 6. Update mutation wrapper — <Entity>UpdateInput
|
|
20
27
|
# 7. Update mutation fields — <Entity>UpdateRepresentation (for update mutations)
|
|
21
28
|
|
|
22
|
-
SCHEMA="
|
|
29
|
+
SCHEMA=""
|
|
23
30
|
|
|
24
31
|
# ── Argument parsing ─────────────────────────────────────────────────────────
|
|
25
32
|
|
|
@@ -56,10 +63,26 @@ if [ $# -eq 0 ]; then
|
|
|
56
63
|
exit 1
|
|
57
64
|
fi
|
|
58
65
|
|
|
66
|
+
# ── Schema resolution ────────────────────────────────────────────────────────
|
|
67
|
+
# NO directory walk-up: resolve only from an explicit flag, an explicit env var,
|
|
68
|
+
# or schema.graphql in the CURRENT directory. Searching ancestors risks matching
|
|
69
|
+
# an unrelated project's schema and validating fields against the wrong org.
|
|
70
|
+
# Resolution order (first hit wins): -s/--schema, then $GRAPHQL_SCHEMA, then ./schema.graphql.
|
|
71
|
+
|
|
72
|
+
if [ -z "$SCHEMA" ] && [ -n "${GRAPHQL_SCHEMA-}" ]; then
|
|
73
|
+
SCHEMA="$GRAPHQL_SCHEMA"
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
if [ -z "$SCHEMA" ]; then
|
|
77
|
+
SCHEMA="./schema.graphql"
|
|
78
|
+
fi
|
|
79
|
+
|
|
59
80
|
if [ ! -f "$SCHEMA" ]; then
|
|
60
|
-
echo "ERROR: schema.graphql not found at $SCHEMA"
|
|
61
|
-
echo "
|
|
81
|
+
echo "ERROR: schema.graphql not found at '$SCHEMA'."
|
|
82
|
+
echo " This script does NOT search parent directories (an ancestor schema may be the wrong org's)."
|
|
83
|
+
echo " Run from the SFDX project root where schema.graphql lives, or point at it explicitly:"
|
|
62
84
|
echo " bash $0 --schema <path/to/schema.graphql> <EntityName>"
|
|
85
|
+
echo " GRAPHQL_SCHEMA=<path/to/schema.graphql> bash $0 <EntityName>"
|
|
63
86
|
echo " If the file is missing entirely, generate it from the UI bundle dir:"
|
|
64
87
|
echo " cd force-app/main/default/uiBundles/<app-name> && npm run graphql:schema"
|
|
65
88
|
exit 1
|
|
@@ -78,6 +101,10 @@ if [ ! -s "$SCHEMA" ]; then
|
|
|
78
101
|
exit 1
|
|
79
102
|
fi
|
|
80
103
|
|
|
104
|
+
# Announce the resolved schema so a wrong-file match is visible, not silent.
|
|
105
|
+
# stderr keeps it out of the parsed lookup output on stdout.
|
|
106
|
+
echo "[graphql-search] using schema: $SCHEMA" >&2
|
|
107
|
+
|
|
81
108
|
# ── Helper: extract lines from a grep match through the closing brace ────────
|
|
82
109
|
# Prints up to MAX_LINES lines after (and including) the first match of PATTERN.
|
|
83
110
|
# Uses a generous line count — blocks are always closed by a "}" line.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: platform-agentsetup-categories-fetch
|
|
3
|
+
description: "Fetch agentic setup prompt categories from a connected Salesforce org using the Connect API. Use this skill to call GET /agenticsetup/categories and return the list of prompt categories, optionally with their nested prompts. TRIGGER when: user asks to get, fetch, list, or show agentic setup categories, prompt categories, setup copilot categories, prompt library categories, available setup prompts, Agentforce prompt library, or copilot prompts. DO NOT TRIGGER when: user wants to create new categories, work with non-categories endpoints, or generate OpenAPI specs."
|
|
4
|
+
allowed-tools: Bash Read
|
|
5
|
+
metadata:
|
|
6
|
+
version: "1.0"
|
|
7
|
+
minApiVersion: "67.0"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# platform-agentsetup-categories-fetch
|
|
11
|
+
|
|
12
|
+
Fetch prompt categories from the Agentic Setup Categories Connect API on a connected Salesforce org.
|
|
13
|
+
|
|
14
|
+
## Scope
|
|
15
|
+
|
|
16
|
+
**In scope:**
|
|
17
|
+
- Calling `GET /services/data/{apiVersion}/agenticsetup/categories` via SF CLI
|
|
18
|
+
- Passing the `fetchPrompts` query parameter to include nested prompts
|
|
19
|
+
- Parsing and presenting the JSON response (categories, labels, prompts)
|
|
20
|
+
- Handling errors (403 when feature is disabled, auth failures)
|
|
21
|
+
|
|
22
|
+
**Out of scope — delegate elsewhere:**
|
|
23
|
+
- Creating or modifying prompt categories → not supported via this API (read-only)
|
|
24
|
+
- Org authentication setup → use `sf org login` separately
|
|
25
|
+
- Permission set assignment → assigning-permission-set
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Required Inputs
|
|
30
|
+
|
|
31
|
+
The agent needs:
|
|
32
|
+
- A connected org (already authenticated via `sf org login`)
|
|
33
|
+
- Optionally: whether to include nested prompts (`fetchPrompts=true`)
|
|
34
|
+
- Optionally: target API version (default: v67.0). Replace `v67.0` in the URL with the user-specified version if provided.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Workflow
|
|
39
|
+
|
|
40
|
+
### 1. Verify org connectivity
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
sf org display --json
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Confirm the org is authenticated and extract the instance URL. If no default org is set, ask the user which org to target with `--target-org`.
|
|
47
|
+
|
|
48
|
+
### 2. Call the Categories API
|
|
49
|
+
|
|
50
|
+
**Basic call (categories only):**
|
|
51
|
+
```bash
|
|
52
|
+
sf api request rest /services/data/v67.0/agenticsetup/categories --method GET
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**With nested prompts:**
|
|
56
|
+
```bash
|
|
57
|
+
sf api request rest "/services/data/v67.0/agenticsetup/categories?fetchPrompts=true" --method GET
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 3. Parse and present the response
|
|
61
|
+
|
|
62
|
+
The API returns a JSON object with a `categories` array. Each category has `name`, `label`, and `prompts` fields. See `references/api-response-schema.md` for the full response structure and examples for both `fetchPrompts=true` and `fetchPrompts=false`.
|
|
63
|
+
|
|
64
|
+
Present the results clearly:
|
|
65
|
+
- List categories with their name and label
|
|
66
|
+
- If `fetchPrompts=true` was used, show nested prompts under each category
|
|
67
|
+
- Note any categories with empty `prompts` arrays (means no prompts exist for that category)
|
|
68
|
+
|
|
69
|
+
### 4. Handle errors
|
|
70
|
+
|
|
71
|
+
| Error | Meaning | Action |
|
|
72
|
+
|-------|---------|--------|
|
|
73
|
+
| Success (exit 0) | 200 OK | Parse and display results |
|
|
74
|
+
| `FUNCTIONALITY_NOT_ENABLED` | Feature not enabled for this org/user | Tell user the Agentic Setup Categories feature needs to be enabled — check Setup > Einstein/Agentforce |
|
|
75
|
+
| `INVALID_SESSION_ID` | Session expired | Re-authenticate with `sf org login` |
|
|
76
|
+
| `NOT_FOUND` | Endpoint not found | API version too old or feature not deployed to this org |
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Rules / Constraints
|
|
81
|
+
|
|
82
|
+
| Rule | Rationale |
|
|
83
|
+
|------|-----------|
|
|
84
|
+
| Always use `sf api request rest` — never curl or raw HTTP | curl bypasses `~/.sfdx` session tokens and requires manual Authorization headers, making it brittle |
|
|
85
|
+
| NEVER use SOQL queries | Categories are NOT in standard objects — only available via this Connect REST API |
|
|
86
|
+
| NEVER generate files (LWC, Apex, XML) | This is a data-fetching task, not a code generation task |
|
|
87
|
+
| Default to v67.0 unless user specifies | This is the min-version where the endpoint was introduced |
|
|
88
|
+
| Don't pass fetchPrompts unless asked | Reduces payload size; prompts can be large |
|
|
89
|
+
| Categories are sorted by label | The API returns them alphabetically — don't re-sort |
|
|
90
|
+
| Prompts are sorted by text | Within each category, prompts come alphabetically |
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Output Expectations
|
|
95
|
+
|
|
96
|
+
When finishing, present:
|
|
97
|
+
|
|
98
|
+
1. **Number of categories** returned
|
|
99
|
+
2. **Category list** — name and label for each
|
|
100
|
+
3. **Prompts** (if requested) — nested under their category
|
|
101
|
+
4. **Any errors** encountered with suggested fixes
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Reference File Index
|
|
106
|
+
|
|
107
|
+
| File | When to read |
|
|
108
|
+
|------|--------------|
|
|
109
|
+
| `references/api-response-schema.md` | When you need to understand the full response structure and field descriptions |
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Agentic Setup Categories API Response Schema
|
|
2
|
+
|
|
3
|
+
## Endpoint
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
GET /services/data/v67.0/agenticsetup/categories
|
|
7
|
+
GET /services/data/v67.0/agenticsetup/categories?fetchPrompts=true
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Response Structure
|
|
11
|
+
|
|
12
|
+
### PromptCategoryListRepresentation
|
|
13
|
+
|
|
14
|
+
Top-level response object.
|
|
15
|
+
|
|
16
|
+
| Field | Type | Description |
|
|
17
|
+
|-------|------|-------------|
|
|
18
|
+
| `categories` | array of PromptCategoryRepresentation | Categories sorted alphabetically by localized label |
|
|
19
|
+
|
|
20
|
+
### PromptCategoryRepresentation
|
|
21
|
+
|
|
22
|
+
A single prompt category.
|
|
23
|
+
|
|
24
|
+
| Field | Type | Description |
|
|
25
|
+
|-------|------|-------------|
|
|
26
|
+
| `name` | string | Stable programmatic identifier (e.g., "UserManagement") |
|
|
27
|
+
| `label` | string | Localized display label (e.g., "User Management") |
|
|
28
|
+
| `prompts` | array of PromptRepresentation | Populated when `fetchPrompts=true`; empty array otherwise |
|
|
29
|
+
|
|
30
|
+
### PromptRepresentation
|
|
31
|
+
|
|
32
|
+
A single prompt entry within a category.
|
|
33
|
+
|
|
34
|
+
| Field | Type | Description |
|
|
35
|
+
|-------|------|-------------|
|
|
36
|
+
| `text` | string | User-facing prompt text to display and pass to the LLM |
|
|
37
|
+
| `description` | string | Short helper description shown next to the prompt |
|
|
38
|
+
|
|
39
|
+
## Example Response (fetchPrompts=false)
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"categories": [
|
|
44
|
+
{
|
|
45
|
+
"label": "Flow Management",
|
|
46
|
+
"name": "FlowManagement",
|
|
47
|
+
"prompts": []
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"label": "Identity",
|
|
51
|
+
"name": "Identity",
|
|
52
|
+
"prompts": []
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"label": "User Management",
|
|
56
|
+
"name": "UserManagement",
|
|
57
|
+
"prompts": []
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Example Response (fetchPrompts=true)
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"categories": [
|
|
68
|
+
{
|
|
69
|
+
"label": "Flow Management",
|
|
70
|
+
"name": "FlowManagement",
|
|
71
|
+
"prompts": [
|
|
72
|
+
{
|
|
73
|
+
"description": "Scaffold a new flow",
|
|
74
|
+
"text": "Design a flow that [describe trigger and outcome]."
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"description": "List active flows",
|
|
78
|
+
"text": "List all active flows in this org. Include the object, trigger type, and last modified date for each."
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"label": "User Management",
|
|
84
|
+
"name": "UserManagement",
|
|
85
|
+
"prompts": [
|
|
86
|
+
{
|
|
87
|
+
"description": "Activate a user",
|
|
88
|
+
"text": "Activate user [user]. Confirm what becomes accessible to them again and whether their license is still available."
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"description": "Clone a user",
|
|
92
|
+
"text": "Clone [existing user] to create a new user for [new person's name and email]."
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Error Responses
|
|
101
|
+
|
|
102
|
+
### FUNCTIONALITY_NOT_ENABLED
|
|
103
|
+
|
|
104
|
+
Returned when the Agentic Setup Categories feature is not enabled on the org.
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
[
|
|
108
|
+
{
|
|
109
|
+
"message": "This feature is not currently enabled for this user type or org: [AgenticSetupCategoriesApiFamily]",
|
|
110
|
+
"errorCode": "FUNCTIONALITY_NOT_ENABLED"
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Access Requirements
|
|
116
|
+
|
|
117
|
+
The endpoint uses a two-tier security model:
|
|
118
|
+
1. **Org-level**: `SetupCopilot.orgHasEnhancedAgenticSetup` must be true
|
|
119
|
+
2. **User-level**: `SetupCopilot.orgHasSetupHomePromptLibrary` must be true per request
|
|
120
|
+
|
|
121
|
+
If either check fails, the API returns `FUNCTIONALITY_NOT_ENABLED`.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-custom-object-generate
|
|
3
|
-
description: "Use this skill when users need to create, generate, or validate Salesforce Custom Object metadata. Trigger when users mention custom objects, creating objects, object metadata, .object files, sharing models, name fields, or validation rules on objects. Also use when users say things like \"create a custom object\", \"generate object metadata\", \"set up an object for...\", or when they're troubleshooting object deployment errors especially around sharing models and Master-Detail relationships. Always use this skill for any custom object metadata work."
|
|
3
|
+
description: "Use this skill when users need to create, generate, or validate Salesforce Custom Object metadata. Trigger when users mention custom objects, creating objects, object metadata, .object files, sharing models, name fields, or validation rules on objects. Also use when users say things like \"create a custom object\", \"generate object metadata\", \"set up an object for...\", or when they're troubleshooting object deployment errors especially around sharing models and Master-Detail relationships. Always use this skill for any custom object metadata work, including enriching and keeping the object's description current whenever its fields or validation rules change. Do NOT use this skill for non-Custom-Object metadata (Apex, Flows, LWC, Permission Sets, Custom Metadata Types) or for standard Salesforce objects."
|
|
4
4
|
metadata:
|
|
5
|
-
version: "1.
|
|
5
|
+
version: "1.1"
|
|
6
|
+
minApiVersion: "60.0"
|
|
6
7
|
---
|
|
7
8
|
|
|
8
9
|
## When to Use This Skill
|
|
@@ -13,6 +14,7 @@ Use this skill when you need to:
|
|
|
13
14
|
- Configure object sharing and security settings
|
|
14
15
|
- Set up object features and capabilities
|
|
15
16
|
- Troubleshoot deployment errors related to custom objects
|
|
17
|
+
- **Add, update, or delete a field OR a validation rule on an existing object** — any of these may make the object's `<description>` stale, so you must refresh it (propose + confirm). This applies equally to validation-rule changes, not just fields. See Section 3.B.
|
|
16
18
|
|
|
17
19
|
## Specification
|
|
18
20
|
|
|
@@ -22,6 +24,8 @@ This document defines the mandatory constraints for generating CustomObject meta
|
|
|
22
24
|
|
|
23
25
|
**File extension:** `.object-meta.xml`
|
|
24
26
|
|
|
27
|
+
> **🔔 Description freshness — applies to EVERY object change, fields AND validation rules:** Whenever you add, update, or delete a field **or a validation rule** on an object, the `<description>` may now be stale. Before finishing, refresh it per **Section 3.B** (propose, confirm with the user, write). A validation-rule change counts exactly like a field change — the change is **not** done until the description has been reconciled. This is easy to forget on validation-rule edits/deletes — don't.
|
|
28
|
+
|
|
25
29
|
---
|
|
26
30
|
|
|
27
31
|
## 2. Syntactic Essentials (Tier 1)
|
|
@@ -103,12 +107,47 @@ The agent must choose which features to enable based on the object's intended us
|
|
|
103
107
|
</nameField>
|
|
104
108
|
```
|
|
105
109
|
|
|
106
|
-
### B. Object Description
|
|
110
|
+
### B. Object Description (Enrichment)
|
|
111
|
+
|
|
112
|
+
**`<description>`**: **Mandatory** — every Custom Object MUST have one. It must read like human-written documentation, **never** a generic template ("Object used to track and manage...") or a metadata dump ("Contains 8 fields including `Project_Name__c`...").
|
|
113
|
+
|
|
114
|
+
**Always compose an enriched description** — when creating the object, and again on **any** change to it: adding, updating, or deleting a field **or a validation rule** (so it never goes stale). The change — field or validation rule — is never "done" until you've refreshed the object's description. This is not optional; do not ask *whether* to add a description.
|
|
115
|
+
|
|
116
|
+
**Confirm per change — every time.** Propose and confirm on **each** field/rule change separately. A previous "keep current" applies **only** to that one change; it is **never** standing permission to skip the proposal on a later change. Do not infer a preference from an earlier answer — re-propose and re-ask for every new change.
|
|
117
|
+
|
|
118
|
+
**Compose** the description (steps below). If the object already has one, use it as a **strong signal** — preserve the business context it carries (domain, team, intent the schema can't reveal) and fold the new field/rule in rather than discarding it.
|
|
119
|
+
|
|
120
|
+
Then branch on whether a description already exists:
|
|
121
|
+
|
|
122
|
+
- **No existing description (brand-new object):** there is nothing to overwrite — just write the composed description. **Do not prompt.**
|
|
123
|
+
- **An existing description (update, delete, or any re-enrichment):** never overwrite it silently — you can't tell from the file whether it was hand-written by an admin or generated earlier. Show the proposal, ask, and **STOP — wait for the user's reply before writing:**
|
|
124
|
+
> Proposed description for `{Object}`:
|
|
125
|
+
> `<the enriched description>`
|
|
126
|
+
> Current: `<the existing description>`
|
|
127
|
+
> Use this? (yes / keep current / edit)
|
|
128
|
+
|
|
129
|
+
**You MUST NOT write the `<description>` until the user replies** — showing the diff is not approval, even when the change looks obvious or minor. Then act: *yes* → write the proposed text · *keep current* → leave the existing one untouched (this applies to **this change only** — re-propose on the next one) · *edit* → use the user's wording.
|
|
130
|
+
|
|
131
|
+
Always end with a `<description>` written.
|
|
132
|
+
|
|
133
|
+
**Composing the description:**
|
|
107
134
|
|
|
108
|
-
|
|
135
|
+
1. **Classify each field** by how it appears in the description:
|
|
136
|
+
- **Constrained** (required, unique, externalId, restricted picklist) → selective parenthetical: `VIN (required, external ID)`, `Color (Red/Green only)`
|
|
137
|
+
- **Behavioral** (formula, roll-up) → describe what it computes: "the Age Years field auto-calculates vehicle age"
|
|
138
|
+
- **Relationship** (master-detail, lookup) → woven context: "as a child of Account" (never "(Master-Detail to Account)")
|
|
139
|
+
- **Standard** → label only
|
|
140
|
+
2. **Compose** in this order, using field **labels not API names**:
|
|
141
|
+
> Purpose → key fields → computed fields → validation rules (as business rules) → "Commonly used for {use cases}."
|
|
142
|
+
3. **Count and trim before writing (required):** count the words; aim ~45, hard ceiling 50. If over, tighten wording first, then drop whole sentences in priority order (use cases → rules → computed; never drop sentences 1–2). Recount. Do not write until ≤ 50.
|
|
143
|
+
|
|
144
|
+
**Example (Car, 46 words):**
|
|
145
|
+
```xml
|
|
146
|
+
<description>The Car object tracks vehicle inventory and maintenance. It captures Year, VIN (required, external ID), Color (Red/Green only), and Location; the Age Years field auto-calculates vehicle age. VIN is required and Black cars cannot be sold. Commonly used for fleet management, inventory tracking, and service scheduling.</description>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
→ For the full workflow and examples, read **`references/description-enrichment.md`**.
|
|
109
150
|
|
|
110
|
-
If the intent is vague, generate a summary:
|
|
111
|
-
> "Object used to track and manage [Intent] within the organization."
|
|
112
151
|
### C. Junction Object Naming
|
|
113
152
|
|
|
114
153
|
If the object is a many-to-many link between two parents, name the object by combining the two parent entities to ensure the schema remains intuitive.
|
|
@@ -234,7 +273,23 @@ Before generating the Custom Object XML, verify:
|
|
|
234
273
|
- [ ] Do validation rule names NOT end with `__c`?
|
|
235
274
|
- [ ] Do validation rule names follow alphanumeric + underscore pattern?
|
|
236
275
|
|
|
276
|
+
### Description Enrichment Quality Checks
|
|
277
|
+
- [ ] Opens with "The {Object} object..." + business purpose (not "Object used to track and manage...")
|
|
278
|
+
- [ ] Uses field **labels**, never API names; no "Contains N fields including" dump
|
|
279
|
+
- [ ] Formulas/rollups described by behavior; validations stated as business rules; relationships as context
|
|
280
|
+
- [ ] Includes common use cases ("Commonly used for...") and is **under 50 words**
|
|
281
|
+
- [ ] Folded any current description's business context into the proposed one (didn't discard it)
|
|
282
|
+
- [ ] For an existing description (update/delete/re-enrich), STOPPED and waited for the user's reply before writing — did not treat showing the diff as approval
|
|
283
|
+
|
|
237
284
|
### Architectural Checks
|
|
238
|
-
- [ ] Is `<description>` present with
|
|
285
|
+
- [ ] Is `<description>` present? (Enriched per Section B — proposed and confirmed with the user before writing.)
|
|
239
286
|
- [ ] Are `<enableSearch>` and `<enableReports>` set to `true` if user-facing?
|
|
240
287
|
- [ ] Does the filename match the intended API name?
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## Reference File Index
|
|
292
|
+
|
|
293
|
+
| File | When to read |
|
|
294
|
+
|------|-------------|
|
|
295
|
+
| `references/description-enrichment.md` | Composing or refreshing an object's `<description>` (on create, or when a field/rule changes) — full enrichment workflow, field-prioritization tiers, junction/child handling, edge cases, and more examples |
|