@pega/sdk 0.0.6 → 0.0.8
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/dist/index.js +165 -18
- package/package.json +1 -1
- package/templates/react-sdk-reference/.ai-common/agents/implementation-expert.md +43 -23
- package/templates/react-sdk-reference/.ai-common/global/ai-agent-instructions.md +25 -9
- package/templates/react-sdk-reference/.ai-common/instructions/infra-component.md +76 -0
- package/templates/react-sdk-reference/.ai-common/mcp/claude-code.mcp.json +8 -0
- package/templates/react-sdk-reference/.ai-common/mcp/copilot.mcp.json +8 -0
- package/templates/react-sdk-reference/.ai-common/mcp/cursor.mcp.json +11 -0
- package/templates/react-sdk-reference/.ai-common/prompts/generate-all-components.md +202 -29
- package/templates/react-sdk-reference/.ai-common/prompts/generate-infra-components.md +222 -0
package/dist/index.js
CHANGED
|
@@ -547,7 +547,7 @@ async function scaffold(choices, targetDir, onProgress) {
|
|
|
547
547
|
}
|
|
548
548
|
}
|
|
549
549
|
}
|
|
550
|
-
generateAiConfigs(targetDir,
|
|
550
|
+
generateAiConfigs(targetDir, choices);
|
|
551
551
|
}
|
|
552
552
|
report("Finalizing project configuration\u2026");
|
|
553
553
|
selectReactPackageManifest(targetDir, framework, includeTemplates, componentCategories);
|
|
@@ -791,6 +791,7 @@ function cursorSkillDescription(relPath) {
|
|
|
791
791
|
if (subdir === "template-skills") return `Template component skill: ${name}`;
|
|
792
792
|
if (subdir === "widget-skills") return `Widget component skill: ${name}`;
|
|
793
793
|
if (subdir === "design-system-extension-skills") return `DSE component skill: ${name}`;
|
|
794
|
+
if (subdir === "infra-skills") return `Infra component skill: ${name}`;
|
|
794
795
|
}
|
|
795
796
|
return relPath.replace(/\.md$/, "").split("/").pop();
|
|
796
797
|
}
|
|
@@ -1013,10 +1014,26 @@ function applyPlannedFiles(files, policy, options = {}) {
|
|
|
1013
1014
|
}
|
|
1014
1015
|
return counts;
|
|
1015
1016
|
}
|
|
1016
|
-
function generateAiConfigs(targetDir,
|
|
1017
|
+
function generateAiConfigs(targetDir, choices) {
|
|
1017
1018
|
const aiCommonDir = path2.join(targetDir, ".ai-common");
|
|
1018
1019
|
if (!fs2.existsSync(aiCommonDir)) return;
|
|
1019
|
-
|
|
1020
|
+
if (choices.aiTool) {
|
|
1021
|
+
applyPlannedFiles(planAiConfigs(aiCommonDir, targetDir, choices.aiTool), "override", { markers: false });
|
|
1022
|
+
}
|
|
1023
|
+
if (choices.aiTool && choices.serverUrl && choices.appAlias && choices.clientId) {
|
|
1024
|
+
const { config: mcpConfig, destRelPath: mcpDestRelPath } = resolveMcpConfig(aiCommonDir, {
|
|
1025
|
+
aiTool: choices.aiTool,
|
|
1026
|
+
serverUrl: choices.serverUrl,
|
|
1027
|
+
appAlias: choices.appAlias,
|
|
1028
|
+
clientId: choices.clientId,
|
|
1029
|
+
mcpRuleName: choices.mcpRuleName,
|
|
1030
|
+
mcpRuleInsKey: choices.mcpRuleInsKey
|
|
1031
|
+
});
|
|
1032
|
+
writeManagedJson(path2.join(targetDir, mcpDestRelPath), mcpConfig, "override", MCP_CONFIG_USER_KEYS);
|
|
1033
|
+
if (choices.aiTool === "cursor") {
|
|
1034
|
+
ensureGitignoreEntry(targetDir, mcpDestRelPath);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1020
1037
|
fs2.rmSync(aiCommonDir, { recursive: true });
|
|
1021
1038
|
}
|
|
1022
1039
|
var EMBEDDED_GLOBAL_FILE = "ai-agent-instructions-embedded.md";
|
|
@@ -1036,6 +1053,35 @@ var SDK_CONFIG_USER_KEYS = [
|
|
|
1036
1053
|
"authConfig.mashupUserIdentifier",
|
|
1037
1054
|
"authConfig.portalClientId"
|
|
1038
1055
|
];
|
|
1056
|
+
var MCP_CONFIG_USER_KEYS = ["url", "clientId"];
|
|
1057
|
+
var MCP_CONFIG_FILES = {
|
|
1058
|
+
copilot: { source: "copilot.mcp.json", dest: path2.join(".vscode", "mcp.json") },
|
|
1059
|
+
cursor: { source: "cursor.mcp.json", dest: path2.join(".cursor", "mcp.json") },
|
|
1060
|
+
"claude-code": { source: "claude-code.mcp.json", dest: ".mcp.json" }
|
|
1061
|
+
};
|
|
1062
|
+
function resolveMcpConfig(aiCommonSrc, choices) {
|
|
1063
|
+
const { source, dest } = MCP_CONFIG_FILES[choices.aiTool];
|
|
1064
|
+
const srcPath = path2.join(aiCommonSrc, "mcp", source);
|
|
1065
|
+
if (!fs2.existsSync(srcPath)) {
|
|
1066
|
+
throw new Error(`MCP config template not found at ${srcPath}. Ensure the template source is available.`);
|
|
1067
|
+
}
|
|
1068
|
+
const tokens = {
|
|
1069
|
+
"{InfinityURL}": choices.serverUrl,
|
|
1070
|
+
"{AppAlias}": choices.appAlias,
|
|
1071
|
+
"{ClientId}": choices.clientId
|
|
1072
|
+
};
|
|
1073
|
+
if (choices.mcpRuleName) tokens["{MCPRuleName}"] = choices.mcpRuleName;
|
|
1074
|
+
if (choices.mcpRuleInsKey) tokens["{MCPRuleInsKey}"] = choices.mcpRuleInsKey;
|
|
1075
|
+
const content = applyTokens(fs2.readFileSync(srcPath, "utf-8"), tokens);
|
|
1076
|
+
return { config: JSON.parse(content), destRelPath: dest };
|
|
1077
|
+
}
|
|
1078
|
+
function ensureGitignoreEntry(targetDir, entry) {
|
|
1079
|
+
const gitignorePath = path2.join(targetDir, ".gitignore");
|
|
1080
|
+
const existing = fs2.existsSync(gitignorePath) ? fs2.readFileSync(gitignorePath, "utf-8") : "";
|
|
1081
|
+
if (existing.split(/\r?\n/).some((line) => line.trim() === entry)) return;
|
|
1082
|
+
const separator = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
|
|
1083
|
+
fs2.writeFileSync(gitignorePath, existing + separator + entry + "\n");
|
|
1084
|
+
}
|
|
1039
1085
|
function buildSdkConfig(choices) {
|
|
1040
1086
|
return {
|
|
1041
1087
|
serverConfig: {
|
|
@@ -1079,6 +1125,11 @@ function collectEmbeddedConflicts(targetDir, choices) {
|
|
|
1079
1125
|
if (isConflict(sdkConfigPath, buildSdkConfig(choices), SDK_CONFIG_USER_KEYS)) {
|
|
1080
1126
|
conflicts.push(sdkConfigPath);
|
|
1081
1127
|
}
|
|
1128
|
+
const { config: mcpConfig, destRelPath: mcpDestRelPath } = resolveMcpConfig(aiCommonSrc, choices);
|
|
1129
|
+
const mcpConfigPath = path2.join(targetDir, mcpDestRelPath);
|
|
1130
|
+
if (isConflict(mcpConfigPath, mcpConfig, MCP_CONFIG_USER_KEYS)) {
|
|
1131
|
+
conflicts.push(mcpConfigPath);
|
|
1132
|
+
}
|
|
1082
1133
|
return conflicts.map((filePath) => path2.relative(targetDir, filePath));
|
|
1083
1134
|
}
|
|
1084
1135
|
async function scaffoldEmbedded(choices, targetDir, onProgress) {
|
|
@@ -1129,6 +1180,12 @@ async function scaffoldEmbedded(choices, targetDir, onProgress) {
|
|
|
1129
1180
|
if (staticDir !== targetDir && fs2.existsSync(path2.join(targetDir, "sdk-config.json"))) {
|
|
1130
1181
|
report(`\u26A0\uFE0F A sdk-config.json also exists at the project root. The active one is ${sdkConfigPath}.`);
|
|
1131
1182
|
}
|
|
1183
|
+
report("Creating MCP server configuration\u2026");
|
|
1184
|
+
const { config: mcpConfig, destRelPath: mcpDestRelPath } = resolveMcpConfig(aiCommonSrc, choices);
|
|
1185
|
+
writeManagedJson(path2.join(targetDir, mcpDestRelPath), mcpConfig, policy, MCP_CONFIG_USER_KEYS);
|
|
1186
|
+
if (aiTool === "cursor") {
|
|
1187
|
+
ensureGitignoreEntry(targetDir, mcpDestRelPath);
|
|
1188
|
+
}
|
|
1132
1189
|
report("Installing dependencies (this may take a minute)\u2026");
|
|
1133
1190
|
let installSucceeded = true;
|
|
1134
1191
|
try {
|
|
@@ -1247,7 +1304,7 @@ Usage: ${pc.cyan("npx @pega/sdk init")}`);
|
|
|
1247
1304
|
process.exit(0);
|
|
1248
1305
|
}
|
|
1249
1306
|
p.log.info(pc.dim("\nNow let's connect to your Pega server."));
|
|
1250
|
-
const
|
|
1307
|
+
const serverUrlResult = await p.text({
|
|
1251
1308
|
message: "What is your Pega server URL?",
|
|
1252
1309
|
placeholder: "https://your-pega-server.com/prweb",
|
|
1253
1310
|
validate(value) {
|
|
@@ -1255,29 +1312,30 @@ Usage: ${pc.cyan("npx @pega/sdk init")}`);
|
|
|
1255
1312
|
if (!value.startsWith("http")) return "Must be a valid URL starting with http:// or https://";
|
|
1256
1313
|
}
|
|
1257
1314
|
});
|
|
1258
|
-
if (p.isCancel(
|
|
1315
|
+
if (p.isCancel(serverUrlResult)) {
|
|
1259
1316
|
p.cancel("Operation cancelled.");
|
|
1260
1317
|
process.exit(0);
|
|
1261
1318
|
}
|
|
1262
|
-
const
|
|
1319
|
+
const serverUrl2 = serverUrlResult.replace(/\/+$/, "");
|
|
1320
|
+
const appAlias2 = await p.text({
|
|
1263
1321
|
message: "What is your Pega application alias?",
|
|
1264
1322
|
placeholder: "MyApp",
|
|
1265
1323
|
validate(value) {
|
|
1266
1324
|
if (!value) return "Application alias is required.";
|
|
1267
1325
|
}
|
|
1268
1326
|
});
|
|
1269
|
-
if (p.isCancel(
|
|
1327
|
+
if (p.isCancel(appAlias2)) {
|
|
1270
1328
|
p.cancel("Operation cancelled.");
|
|
1271
1329
|
process.exit(0);
|
|
1272
1330
|
}
|
|
1273
|
-
const
|
|
1331
|
+
const clientId2 = await p.text({
|
|
1274
1332
|
message: "What is the OAuth Client ID for your app?",
|
|
1275
1333
|
placeholder: "Your OAuth 2.0 client identifier",
|
|
1276
1334
|
validate(value) {
|
|
1277
1335
|
if (!value) return "Client ID is required for authentication.";
|
|
1278
1336
|
}
|
|
1279
1337
|
});
|
|
1280
|
-
if (p.isCancel(
|
|
1338
|
+
if (p.isCancel(clientId2)) {
|
|
1281
1339
|
p.cancel("Operation cancelled.");
|
|
1282
1340
|
process.exit(0);
|
|
1283
1341
|
}
|
|
@@ -1292,16 +1350,37 @@ Usage: ${pc.cyan("npx @pega/sdk init")}`);
|
|
|
1292
1350
|
p.cancel("Operation cancelled.");
|
|
1293
1351
|
process.exit(0);
|
|
1294
1352
|
}
|
|
1353
|
+
p.log.info(pc.dim("\nIf you've configured an MCP server for this app, we can wire it up too (optional)."));
|
|
1354
|
+
const mcpRuleNameResult = await p.text({
|
|
1355
|
+
message: "What is your Pega MCP rule name? (press Enter to skip)",
|
|
1356
|
+
placeholder: "SDKMCP"
|
|
1357
|
+
});
|
|
1358
|
+
if (p.isCancel(mcpRuleNameResult)) {
|
|
1359
|
+
p.cancel("Operation cancelled.");
|
|
1360
|
+
process.exit(0);
|
|
1361
|
+
}
|
|
1362
|
+
const mcpRuleInsKeyResult = await p.text({
|
|
1363
|
+
message: "What is your Pega MCP rule instance key? (press Enter to skip)",
|
|
1364
|
+
placeholder: "@baseclass!SDKMCP"
|
|
1365
|
+
});
|
|
1366
|
+
if (p.isCancel(mcpRuleInsKeyResult)) {
|
|
1367
|
+
p.cancel("Operation cancelled.");
|
|
1368
|
+
process.exit(0);
|
|
1369
|
+
}
|
|
1370
|
+
const mcpRuleName2 = mcpRuleNameResult || void 0;
|
|
1371
|
+
const mcpRuleInsKey2 = mcpRuleInsKeyResult || void 0;
|
|
1295
1372
|
const embeddedTargetDir = cwd;
|
|
1296
1373
|
p.note(
|
|
1297
1374
|
[
|
|
1298
1375
|
`${pc.bold("Mode")}: Embed Pega flow`,
|
|
1299
1376
|
`${pc.bold("Directory")}: ${embeddedTargetDir}`,
|
|
1300
1377
|
`${pc.bold("AI Tool")}: ${embeddedAiTool}`,
|
|
1301
|
-
`${pc.bold("Server")}: ${
|
|
1302
|
-
`${pc.bold("App Alias")}: ${
|
|
1303
|
-
`${pc.bold("Client ID")}: ${
|
|
1304
|
-
`${pc.bold("Operator")}: ${userIdentifier}
|
|
1378
|
+
`${pc.bold("Server")}: ${serverUrl2}`,
|
|
1379
|
+
`${pc.bold("App Alias")}: ${appAlias2}`,
|
|
1380
|
+
`${pc.bold("Client ID")}: ${clientId2}`,
|
|
1381
|
+
`${pc.bold("Operator")}: ${userIdentifier}`,
|
|
1382
|
+
`${pc.bold("MCP Rule")}: ${mcpRuleName2 ?? pc.dim("(not configured \u2014 markers left in generated file)")}`,
|
|
1383
|
+
`${pc.bold("MCP Ins Key")}: ${mcpRuleInsKey2 ?? pc.dim("(not configured \u2014 markers left in generated file)")}`
|
|
1305
1384
|
].join("\n"),
|
|
1306
1385
|
"Configuration"
|
|
1307
1386
|
);
|
|
@@ -1315,10 +1394,12 @@ Usage: ${pc.cyan("npx @pega/sdk init")}`);
|
|
|
1315
1394
|
}
|
|
1316
1395
|
const embeddedChoices = {
|
|
1317
1396
|
aiTool: embeddedAiTool,
|
|
1318
|
-
serverUrl,
|
|
1319
|
-
appAlias,
|
|
1320
|
-
clientId,
|
|
1321
|
-
userIdentifier
|
|
1397
|
+
serverUrl: serverUrl2,
|
|
1398
|
+
appAlias: appAlias2,
|
|
1399
|
+
clientId: clientId2,
|
|
1400
|
+
userIdentifier,
|
|
1401
|
+
mcpRuleName: mcpRuleName2,
|
|
1402
|
+
mcpRuleInsKey: mcpRuleInsKey2
|
|
1322
1403
|
};
|
|
1323
1404
|
let conflicts = [];
|
|
1324
1405
|
try {
|
|
@@ -1407,6 +1488,11 @@ Usage: ${pc.cyan("npx @pega/sdk init")}`);
|
|
|
1407
1488
|
process.exit(0);
|
|
1408
1489
|
}
|
|
1409
1490
|
let aiTool = null;
|
|
1491
|
+
let serverUrl;
|
|
1492
|
+
let appAlias;
|
|
1493
|
+
let clientId;
|
|
1494
|
+
let mcpRuleName;
|
|
1495
|
+
let mcpRuleInsKey;
|
|
1410
1496
|
if (aiIntegration) {
|
|
1411
1497
|
const aiToolResult = await p.select({
|
|
1412
1498
|
message: "Which AI coding tool will you use?",
|
|
@@ -1433,6 +1519,62 @@ Usage: ${pc.cyan("npx @pega/sdk init")}`);
|
|
|
1433
1519
|
process.exit(0);
|
|
1434
1520
|
}
|
|
1435
1521
|
aiTool = aiToolResult;
|
|
1522
|
+
p.log.info(pc.dim("\nIf you'd like the new project to include an MCP config, we need a few connection details."));
|
|
1523
|
+
const serverUrlResult = await p.text({
|
|
1524
|
+
message: "What is your Pega server URL?",
|
|
1525
|
+
placeholder: "https://your-pega-server.com/prweb",
|
|
1526
|
+
validate(value) {
|
|
1527
|
+
if (!value) return "Server URL is required.";
|
|
1528
|
+
if (!value.startsWith("http")) return "Must be a valid URL starting with http:// or https://";
|
|
1529
|
+
}
|
|
1530
|
+
});
|
|
1531
|
+
if (p.isCancel(serverUrlResult)) {
|
|
1532
|
+
p.cancel("Operation cancelled.");
|
|
1533
|
+
process.exit(0);
|
|
1534
|
+
}
|
|
1535
|
+
const appAliasResult = await p.text({
|
|
1536
|
+
message: "What is your Pega application alias?",
|
|
1537
|
+
placeholder: "MyApp",
|
|
1538
|
+
validate(value) {
|
|
1539
|
+
if (!value) return "Application alias is required.";
|
|
1540
|
+
}
|
|
1541
|
+
});
|
|
1542
|
+
if (p.isCancel(appAliasResult)) {
|
|
1543
|
+
p.cancel("Operation cancelled.");
|
|
1544
|
+
process.exit(0);
|
|
1545
|
+
}
|
|
1546
|
+
const clientIdResult = await p.text({
|
|
1547
|
+
message: "What is the OAuth Client ID for your app?",
|
|
1548
|
+
placeholder: "Your OAuth 2.0 client identifier",
|
|
1549
|
+
validate(value) {
|
|
1550
|
+
if (!value) return "Client ID is required for authentication.";
|
|
1551
|
+
}
|
|
1552
|
+
});
|
|
1553
|
+
if (p.isCancel(clientIdResult)) {
|
|
1554
|
+
p.cancel("Operation cancelled.");
|
|
1555
|
+
process.exit(0);
|
|
1556
|
+
}
|
|
1557
|
+
const mcpRuleNameResult = await p.text({
|
|
1558
|
+
message: "What is your Pega MCP rule name? (press Enter to skip)",
|
|
1559
|
+
placeholder: "SDKMCP"
|
|
1560
|
+
});
|
|
1561
|
+
if (p.isCancel(mcpRuleNameResult)) {
|
|
1562
|
+
p.cancel("Operation cancelled.");
|
|
1563
|
+
process.exit(0);
|
|
1564
|
+
}
|
|
1565
|
+
const mcpRuleInsKeyResult = await p.text({
|
|
1566
|
+
message: "What is your Pega MCP rule instance key? (press Enter to skip)",
|
|
1567
|
+
placeholder: "@baseclass!SDKMCP"
|
|
1568
|
+
});
|
|
1569
|
+
if (p.isCancel(mcpRuleInsKeyResult)) {
|
|
1570
|
+
p.cancel("Operation cancelled.");
|
|
1571
|
+
process.exit(0);
|
|
1572
|
+
}
|
|
1573
|
+
serverUrl = String(serverUrlResult).replace(/\/+$/, "");
|
|
1574
|
+
appAlias = String(appAliasResult);
|
|
1575
|
+
clientId = String(clientIdResult);
|
|
1576
|
+
mcpRuleName = String(mcpRuleNameResult) || void 0;
|
|
1577
|
+
mcpRuleInsKey = String(mcpRuleInsKeyResult) || void 0;
|
|
1436
1578
|
}
|
|
1437
1579
|
const framework = await p.select({
|
|
1438
1580
|
message: "Select a UI framework for your Pega SDK project:",
|
|
@@ -1541,7 +1683,12 @@ Usage: ${pc.cyan("npx @pega/sdk init")}`);
|
|
|
1541
1683
|
framework,
|
|
1542
1684
|
aiTool,
|
|
1543
1685
|
includeTemplates,
|
|
1544
|
-
componentCategories
|
|
1686
|
+
componentCategories,
|
|
1687
|
+
serverUrl,
|
|
1688
|
+
appAlias,
|
|
1689
|
+
clientId,
|
|
1690
|
+
mcpRuleName,
|
|
1691
|
+
mcpRuleInsKey
|
|
1545
1692
|
};
|
|
1546
1693
|
const spinner2 = p.spinner();
|
|
1547
1694
|
spinner2.start("Scaffolding your project\u2026");
|
package/package.json
CHANGED
|
@@ -10,9 +10,10 @@ migrating the design system of components that already exist. You execute these
|
|
|
10
10
|
written, rather than improvising your own approach.
|
|
11
11
|
|
|
12
12
|
This repo is a reference implementation customers clone and re-skin: the UI components (fields, templates, widgets,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
bootstrap/auth logic) is reusable
|
|
13
|
+
design system extensions, and the three overridable infrastructure chrome components) are meant to be replaced with
|
|
14
|
+
any design system, while the SDK wiring (component map registry mechanics, the SDK-provided infrastructure
|
|
15
|
+
components, event handling helpers, the SDK bridge package, and the application bootstrap/auth logic) is reusable
|
|
16
|
+
infrastructure you must never break.
|
|
16
17
|
|
|
17
18
|
## Startup behavior
|
|
18
19
|
|
|
@@ -27,6 +28,7 @@ The **first time you respond in a conversation**, before doing any routing or fi
|
|
|
27
28
|
2. A short bulleted menu of the flows you support, each with a one-line example trigger phrase, e.g.:
|
|
28
29
|
- **Add/replace a single component** — "add a Dropdown field using Chakra UI"
|
|
29
30
|
- **Batch-generate one type** — "generate all widget components with Ant Design"
|
|
31
|
+
- **Generate infrastructure chrome** — "generate infra components with Carbon"
|
|
30
32
|
- **Generate everything** — "generate all components using Radix"
|
|
31
33
|
- **Identify components from a screenshot** — attach an image and ask "what components are in this screenshot"
|
|
32
34
|
- **Migrate the design system** — "replace all field components with Carbon" or "migrate the whole app to Chakra UI"
|
|
@@ -35,10 +37,14 @@ The **first time you respond in a conversation**, before doing any routing or fi
|
|
|
35
37
|
- **Flow**: options = Add/replace a single component | Batch-generate one type | Generate everything |
|
|
36
38
|
Identify components from a screenshot | Migrate the design system.
|
|
37
39
|
- **Component type** (skip only if "Identify from screenshot" chosen): options = Field | Template | Widget |
|
|
38
|
-
Design System Extension | **All** (`All` = Field + Template + Widget + Design System
|
|
40
|
+
Design System Extension | Infra (chrome) | **All** (`All` = Field + Template + Widget + Design System
|
|
41
|
+
Extension + Infra together).
|
|
39
42
|
Enable multi-select so the user can combine individual types into a custom subset (e.g. Field + Widget),
|
|
40
43
|
but treat **All** as its own exclusive/standalone choice — if the flow is "Generate everything", default
|
|
41
44
|
the selection to **All** and don't present it as something to combine with the individual type options.
|
|
45
|
+
For the "Generate everything" flow, **All** means every type is eligible — not that every component gets
|
|
46
|
+
generated. The concrete list comes from the portal the user picks inside
|
|
47
|
+
`generate-all-components{{PROMPT_EXT}}`, so don't ask for component names here.
|
|
42
48
|
- **Design system**: options = Ant Design | Chakra UI | Radix | Shadcn | Carbon | MUI | Other (freeform allowed).
|
|
43
49
|
Every question should list selectable options (`allowFreeformInput: true` so the user can still type something
|
|
44
50
|
not listed) instead of asking open-ended questions in plain chat text.
|
|
@@ -53,16 +59,17 @@ before writing any code**. Never paraphrase or execute steps from memory — alw
|
|
|
53
59
|
skill file it tells you to read) at the start of the task, and follow every numbered step in order without
|
|
54
60
|
skipping or shortcutting any of them.
|
|
55
61
|
|
|
56
|
-
| Request shape | Prompt file to read and follow
|
|
57
|
-
| --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
58
|
-
| One new/replacement component, one type (e.g. "add an AutoComplete field with Chakra UI") | `{{PROMPT_DIR}}/add-component{{PROMPT_EXT}}`
|
|
59
|
-
| Multiple/all field components, one design system | `{{PROMPT_DIR}}/generate-field-components{{PROMPT_EXT}}`
|
|
60
|
-
| Multiple/all template components, one design system | `{{PROMPT_DIR}}/generate-template-components{{PROMPT_EXT}}`
|
|
61
|
-
| Multiple/all widget components, one design system | `{{PROMPT_DIR}}/generate-widget-components{{PROMPT_EXT}}`
|
|
62
|
-
| Multiple/all design system extension components, one design system | `{{PROMPT_DIR}}/generate-dse-components{{PROMPT_EXT}}`
|
|
63
|
-
| Multiple
|
|
64
|
-
|
|
|
65
|
-
|
|
|
62
|
+
| Request shape | Prompt file to read and follow |
|
|
63
|
+
| --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
64
|
+
| One new/replacement component, one type (e.g. "add an AutoComplete field with Chakra UI") | `{{PROMPT_DIR}}/add-component{{PROMPT_EXT}}` |
|
|
65
|
+
| Multiple/all field components, one design system | `{{PROMPT_DIR}}/generate-field-components{{PROMPT_EXT}}` |
|
|
66
|
+
| Multiple/all template components, one design system | `{{PROMPT_DIR}}/generate-template-components{{PROMPT_EXT}}` |
|
|
67
|
+
| Multiple/all widget components, one design system | `{{PROMPT_DIR}}/generate-widget-components{{PROMPT_EXT}}` |
|
|
68
|
+
| Multiple/all design system extension components, one design system | `{{PROMPT_DIR}}/generate-dse-components{{PROMPT_EXT}}` |
|
|
69
|
+
| Multiple/all infrastructure (chrome) components, one design system | `{{PROMPT_DIR}}/generate-infra-components{{PROMPT_EXT}}` (only `ActionButtons`, `Stages`, `MultiStep` — every other infra component is SDK-provided) |
|
|
70
|
+
| Multiple component types at once, or "generate all components" | `{{PROMPT_DIR}}/generate-all-components{{PROMPT_EXT}}` (opens with a mandatory server-driven gate — pick a portal, choose landing pages and/or case types, then pick components — then wave-based orchestration over that selection only: launch subagents via `runSubagent`, respecting the ≤10-subagents-per-wave limit defined in that prompt) |
|
|
71
|
+
| A screenshot/image is attached and the user wants to know what components are in it (no migration requested) | `{{PROMPT_DIR}}/identify-components{{PROMPT_EXT}}` — output only the single `components="..."` line it specifies |
|
|
72
|
+
| Migrating/replacing the design system of components that **already exist** — full app, or scoped by folder/named-shorthand/explicit list/screenshot | `{{PROMPT_DIR}}/replace-design-system{{PROMPT_EXT}}` (reads `{{PROMPT_DIR}}/component-manifest.json` for scope resolution; targeted migration for ≤10 resolved components, full 9-wave migration otherwise) |
|
|
66
73
|
|
|
67
74
|
If a request mixes generation and migration ambiguously, use `vscode_askQuestions` to ask which they mean (options:
|
|
68
75
|
"Generate/replace" vs "Migrate existing") before picking a prompt — generation prompts assume the component
|
|
@@ -74,8 +81,8 @@ change.
|
|
|
74
81
|
- That prompt tells you to launch per-component subagents using prompts named `replace-field` (fields) and
|
|
75
82
|
`replace-component` (everything else). **These files do not exist in `{{PROMPT_DIR}}/`.** When launching those
|
|
76
83
|
subagents yourself via `runSubagent`, give each one the equivalent instructions inline instead: the relevant
|
|
77
|
-
general skill (`{{SKILL_DIR}}/field-components.md`, `template-components.md`, `widget-components.md`,
|
|
78
|
-
`design-system-extension.md`), the component-specific skill file
|
|
84
|
+
general skill (`{{SKILL_DIR}}/field-components.md`, `template-components.md`, `widget-components.md`,
|
|
85
|
+
`design-system-extension.md`, or `infra-components.md`), the component-specific skill file
|
|
79
86
|
(`{{SKILL_DIR}}/{type}-skills/<Name>.md`), the target design system, and the same "preserve visual intent /
|
|
80
87
|
keep default export name / update in place" constraints that `add-component{{PROMPT_EXT}}` uses for a single
|
|
81
88
|
component.
|
|
@@ -89,28 +96,41 @@ Every generation prompt requires: component name(s), component type, target desi
|
|
|
89
96
|
(screenshot, `components=` list, or `scope=` folder/shorthand) — if none are given, it defaults to a full 9-wave
|
|
90
97
|
migration, so confirm that's really what the user wants before proceeding. If any required input is missing or
|
|
91
98
|
ambiguous, use the `vscode_askQuestions` tool to ask — present concrete, selectable options (e.g. the known
|
|
92
|
-
design systems, the
|
|
99
|
+
design systems, the five component types, folder/named-shorthand scopes from `component-manifest.json`) rather
|
|
93
100
|
than a plain open-ended question, while still allowing freeform input for anything not listed. Do not guess a
|
|
94
101
|
design system or silently default to MUI.
|
|
95
102
|
|
|
96
103
|
## Guardrails
|
|
97
104
|
|
|
98
|
-
- **
|
|
99
|
-
|
|
100
|
-
|
|
105
|
+
- **In the "generate all components" flow, the generation set is server-resolved.** That prompt's Step 0.5 picks
|
|
106
|
+
a portal, then landing pages and/or case types within it, then a component list from those — and nothing outside
|
|
107
|
+
that selection may be generated. Do not widen it with components you expect a portal to need, and do not skip
|
|
108
|
+
the gate because the user said "everything".
|
|
109
|
+
- **One folder per component — never a shared/monolithic file.** Every component (field, template, widget,
|
|
110
|
+
designSystemExtension, or infra) must be created at `<outputPath>/<ComponentName>/` with a main implementation file
|
|
111
|
+
plus a sibling barrel/re-export file following the project's established convention — exactly as
|
|
101
112
|
Step 5/6 of `add-component{{PROMPT_EXT}}` specifies. Never write multiple components into one file, never
|
|
102
113
|
create a catch-all file like `generated/<designSystem>Components`, and never export a single bundled object
|
|
103
114
|
(e.g. `generatedComponents`) that the component map spreads in one line. This applies identically whether you
|
|
104
115
|
generate one component, a batch of one type, or "all components" via `generate-all-components{{PROMPT_EXT}}` — the
|
|
105
116
|
wave/subagent orchestration in that flow does not change the per-component file-and-folder contract.
|
|
106
117
|
- The project's component map file must get one **named import + one map entry per component**, added under the matching
|
|
107
|
-
category comment (Fields / Templates / Widgets / Design System Extension), never a single spread of a bundled
|
|
118
|
+
category comment (Fields / Templates / Widgets / Design System Extension / Infra), never a single spread of a bundled
|
|
108
119
|
object.
|
|
109
|
-
- Never modify the auth/bootstrap logic in the application's bootstrap modules, infrastructure
|
|
110
|
-
(beyond what a migration prompt explicitly directs), the event handling helper module, or anything in the
|
|
120
|
+
- Never modify the auth/bootstrap logic in the application's bootstrap modules, the SDK-provided infrastructure
|
|
121
|
+
components (beyond what a migration prompt explicitly directs), the event handling helper module, or anything in the
|
|
111
122
|
SDK bridge package. The one exception: `replace-design-system{{PROMPT_EXT}}` explicitly requires wrapping the
|
|
112
123
|
existing provider tree in the application's bootstrap module with a new design-system provider — that specific,
|
|
113
124
|
additive change is allowed only during a migration flow.
|
|
125
|
+
- **Only three infrastructure components may ever be generated** — `ActionButtons`, `Stages`, and `MultiStep`. Every
|
|
126
|
+
other infrastructure component (`NavBar`, `DeferLoad`, `VerticalTabs`, `DashboardFilter`, and anything else) is
|
|
127
|
+
SDK-provided plumbing: skip it and say why. That list never grows.
|
|
128
|
+
- An infra entry in the component map is an **override** of a component the SDK already contributes, so it must be
|
|
129
|
+
listed **after** the SDK's built-in component spread. Listed before it, the spread wins and the override silently
|
|
130
|
+
does nothing.
|
|
131
|
+
- Infrastructure components have a fixed runtime contract — inputs, callback signatures, and localization come from
|
|
132
|
+
the SDK component being replaced. Only markup and styling are yours to change. `ActionButtons` receives plain
|
|
133
|
+
display props and must not be given a PConnect accessor.
|
|
114
134
|
- Never remove the SDK's built-in component spread in the project's component map file — only add or replace entries.
|
|
115
135
|
- Field components must handle `displayMode` (`DISPLAY_ONLY` / `STACKED_LARGE_VAL`) via the field-value display
|
|
116
136
|
component, obtained through the component registry, never a hardcoded import.
|
|
@@ -20,16 +20,19 @@ This is a **reference implementation** — not a framework. The UI components (f
|
|
|
20
20
|
| Template components directory | Layout templates (OneColumn, TwoColumn, Details, etc.) |
|
|
21
21
|
| Widget components directory | Data widgets (ToDo, Attachment, CaseHistory, etc.) |
|
|
22
22
|
| DSE components directory | Extended UI (AlertBanner, FieldGroup, RichTextEditor, etc.) |
|
|
23
|
+
| Infra components directory | Overridable chrome — ActionButtons, Stages, MultiStep only |
|
|
23
24
|
|
|
24
25
|
### Infrastructure (do NOT modify unless you know what you're doing)
|
|
25
26
|
|
|
26
|
-
| Area | Purpose
|
|
27
|
-
| ---------------------------- |
|
|
28
|
-
| Application bootstrap module | Auth + bootstrap + root rendering
|
|
29
|
-
| Component map file | Registry wiring (only add/remove entries)
|
|
30
|
-
|
|
|
31
|
-
| Event handling helper module | PConnect event handler utility
|
|
32
|
-
| SDK bridge package | SDK bridge — never modify
|
|
27
|
+
| Area | Purpose |
|
|
28
|
+
| ---------------------------- | ------------------------------------------------ |
|
|
29
|
+
| Application bootstrap module | Auth + bootstrap + root rendering |
|
|
30
|
+
| Component map file | Registry wiring (only add/remove entries) |
|
|
31
|
+
| SDK-provided infra | NavBar, DeferLoad, VerticalTabs, DashboardFilter |
|
|
32
|
+
| Event handling helper module | PConnect event handler utility |
|
|
33
|
+
| SDK bridge package | SDK bridge — never modify |
|
|
34
|
+
|
|
35
|
+
Infrastructure components are the chrome the runtime draws _around_ a case or an assignment. Most of them ship from the SDK adapter package and are never generated. Exactly three are overridable — `ActionButtons`, `Stages`, and `MultiStep` — because they render inline with the form, where SDK styling is the most visible mismatch. That list never grows.
|
|
33
36
|
|
|
34
37
|
---
|
|
35
38
|
|
|
@@ -182,11 +185,24 @@ Do not skip steps or proceed without reading the required skill files first.
|
|
|
182
185
|
|
|
183
186
|
---
|
|
184
187
|
|
|
185
|
-
## 14.
|
|
188
|
+
## 14. Batch Infrastructure Component Generation
|
|
189
|
+
|
|
190
|
+
When the user asks to generate, create, or replace **infrastructure components**, **chrome components**, or **all infra components** with a design system (e.g., "generate infra components with Ant Design", "replace the infrastructure components with Chakra UI", "generate chrome components using Carbon"),
|
|
191
|
+
read the full contents of `{{PROMPT_DIR}}/generate-infra-components{{PROMPT_EXT}}` and
|
|
192
|
+
execute every step in order before writing any code.
|
|
193
|
+
Do not skip steps or proceed without reading the required skill files first.
|
|
194
|
+
|
|
195
|
+
> Only `ActionButtons`, `Stages`, and `MultiStep` may be generated. Every other infrastructure component is SDK-provided — if the user names one, skip it and say why. Infra entries in the component map must be listed **after** the SDK's built-in component spread, or the override silently does nothing.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## 15. Generate All Components (Multi-Type)
|
|
186
200
|
|
|
187
201
|
When the user asks to generate, create, or replace components across **multiple types** or **all component types** at once (e.g., "generate all components with Ant Design", "replace everything with Chakra UI", "generate field and widget components using Carbon", "regenerate all components"),
|
|
188
202
|
read the full contents of `{{PROMPT_DIR}}/generate-all-components{{PROMPT_EXT}}` and
|
|
189
203
|
execute every step in order before writing any code.
|
|
190
204
|
Do not skip steps or proceed without reading the required skill files first.
|
|
191
205
|
|
|
192
|
-
> Use this section when the request spans more than one component type. For a single type, use Sections 10–
|
|
206
|
+
> Use this section when the request spans more than one component type. For a single type, use Sections 10–14.
|
|
207
|
+
>
|
|
208
|
+
> That prompt does not generate the full catalogue. Its Step 0.5 is a mandatory gate: resolve the application's portals from the server, ask which one to generate for, ask whether to convert its landing pages, its cases, or both, resolve the components for whatever was chosen, and ask which of them to generate. Only the confirmed selection is generated.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
ai-globs: **/infra/**/*
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Infrastructure (Chrome) Component Rules
|
|
6
|
+
|
|
7
|
+
When creating or modifying infrastructure components, follow these rules:
|
|
8
|
+
|
|
9
|
+
## What Are Infrastructure Components?
|
|
10
|
+
|
|
11
|
+
Infrastructure components are the chrome the Pega runtime draws _around_ a case or an assignment — the action button row, the stage progress indicator, the step navigation — rather than the fields inside it. They differ from every other category in one important way: **they already exist**. Generating one produces an override of the SDK's implementation.
|
|
12
|
+
|
|
13
|
+
## What May Be Generated
|
|
14
|
+
|
|
15
|
+
| Component | Role | Generate? |
|
|
16
|
+
| ------------- | ---------------------------------------------------- | --------- |
|
|
17
|
+
| ActionButtons | The Cancel / Save / Submit row beneath an assignment | Yes |
|
|
18
|
+
| Stages | The case stage progress indicator | Yes |
|
|
19
|
+
| MultiStep | Step navigation within a multi-step assignment | Yes |
|
|
20
|
+
|
|
21
|
+
⛔ `NavBar`, `DeferLoad`, `VerticalTabs`, and `DashboardFilter` are structural plumbing tied to the SDK's own internals. They are always sourced from the SDK adapter package and are **never** generated. If a request names one, skip it and say why. This list never grows.
|
|
22
|
+
|
|
23
|
+
## Patterns
|
|
24
|
+
|
|
25
|
+
### Display-only chrome (no PConnect accessor)
|
|
26
|
+
|
|
27
|
+
Used for: ActionButtons
|
|
28
|
+
|
|
29
|
+
Receives everything it needs as plain display props and reports interaction through a supplied callback. It holds no local state and reads nothing from the store. This is the one exception to the rule that every Pega component receives the PConnect accessor — do not add one to it.
|
|
30
|
+
|
|
31
|
+
### Case-aware chrome (PConnect accessor, read-only)
|
|
32
|
+
|
|
33
|
+
Used for: Stages
|
|
34
|
+
|
|
35
|
+
Receives the accessor so it can read case state and localize, but never writes. Normalize the runtime's raw input through the SDK utility the component's skill file documents, read case-level state using the runtime's constants rather than literal property names, and derive a display model before rendering.
|
|
36
|
+
|
|
37
|
+
### Container chrome (renders children)
|
|
38
|
+
|
|
39
|
+
Used for: MultiStep
|
|
40
|
+
|
|
41
|
+
Wraps the form content the runtime hands it and arranges other Pega components around it. Resolve every Pega sub-component through the project's component registry, derive which part of the structure is active from the runtime's state flags (applying the documented fallback when nothing is marked active), and forward the accessor, item key, button definitions, and press callback to the resolved sub-component unchanged.
|
|
42
|
+
|
|
43
|
+
## The Contract Is Fixed
|
|
44
|
+
|
|
45
|
+
Inputs, callback signatures, derivation logic, and localization come from the SDK component being replaced. **Only markup and styling are yours to change.**
|
|
46
|
+
|
|
47
|
+
- Do not rename inputs or reshape callback signatures.
|
|
48
|
+
- Treat every array input as optional and default it to empty.
|
|
49
|
+
- Keep repeated elements stable — every item in a rendered collection needs a stable identity.
|
|
50
|
+
|
|
51
|
+
## Localization
|
|
52
|
+
|
|
53
|
+
Every label an infrastructure component renders comes from Pega, not from the component. Button and action labels resolve through the Pega locale utilities using the locale category the SDK component uses; case and stage names resolve through the localization service on the PConnect accessor. The value arriving in the input is a key, not display text — rendering it directly looks correct in an English environment and breaks in every other one.
|
|
54
|
+
|
|
55
|
+
## Visual Preservation
|
|
56
|
+
|
|
57
|
+
The replacement must look the same as the original component:
|
|
58
|
+
|
|
59
|
+
1. **Read any `.css` file in the directory first.** Note every class's visual intent (spacing, sizing, colors, layout).
|
|
60
|
+
2. Replicate those styles via the new design system's props/variants, inline styles, or by keeping the CSS import — whichever produces the closest match.
|
|
61
|
+
3. Do NOT silently drop legacy styling utility classes — map each one to an equivalent style.
|
|
62
|
+
|
|
63
|
+
## Registration
|
|
64
|
+
|
|
65
|
+
⛔ **Ordering is load-bearing for this category.** An infra entry is an override of a component the SDK already contributes, so it must be listed **after** the SDK's built-in component spread. Listed before it, the spread replaces it and the override silently does nothing.
|
|
66
|
+
|
|
67
|
+
Never remove the spread — it supplies the infrastructure components that are not overridable, and removing it breaks rendering entirely.
|
|
68
|
+
|
|
69
|
+
## Key Rules
|
|
70
|
+
|
|
71
|
+
- Only `ActionButtons`, `Stages`, and `MultiStep` may be generated
|
|
72
|
+
- The three do not share an input shape — take each one's inputs from its own skill file
|
|
73
|
+
- Chrome is display-only — these components report interaction through the callback they were given and never write to the store
|
|
74
|
+
- Resolve sub-components from the registry, never by direct import, or customer overrides are discarded
|
|
75
|
+
- Derive the display model from the runtime's raw inputs first, then render it — this is what keeps the component portable across design systems
|
|
76
|
+
- Case chrome is not assignment chrome — `Stages` belongs to the case view and never appears inside an embedded assignment; `ActionButtons` and `MultiStep` do
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
ai-description: Generate components across multiple types (field, template, widget, designSystemExtension) using any design system
|
|
2
|
+
ai-description: Generate components across multiple types (field, template, widget, designSystemExtension, infra) using any design system
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
## Step 0 — Resolve inputs
|
|
@@ -8,30 +8,32 @@ Read the user's message carefully. Extract:
|
|
|
8
8
|
|
|
9
9
|
- **Design system** — the UI library to use (e.g. `Ant Design`, `Chakra UI`, `Carbon`, `Radix UI`)
|
|
10
10
|
- **Base components folder** — the root folder that contains (or will contain) the component type subfolders (e.g. `src/components/`)
|
|
11
|
-
- **Component types in scope** —
|
|
11
|
+
- **Component types in scope** — an optional narrowing filter (default: all five if not specified)
|
|
12
12
|
|
|
13
13
|
Both **design system** and **base components folder** are required. If either is missing or ambiguous, you MUST stop and ask the user before proceeding. Do not infer any value from the project structure, `{{AI_FILE_EXT}}` files, existing folders, or any other source.
|
|
14
14
|
|
|
15
|
-
⛔ **STOP** — If the user's message does not explicitly state BOTH the design system AND the base components folder, ask for the missing items now. Do not proceed to Step
|
|
15
|
+
⛔ **STOP** — If the user's message does not explicitly state BOTH the design system AND the base components folder, ask for the missing items now. Do not proceed to Step 0.5 until you have explicit answers from the user for all required inputs.
|
|
16
|
+
|
|
17
|
+
**Which components get generated is not decided here.** That set comes from the portal, and the landing pages and/or case types the user picks within it, all resolved from the Pega server in Step 0.5. The type scope below is only a filter applied on top of that set — it can narrow it, never widen it.
|
|
16
18
|
|
|
17
19
|
Example questions (ask only the ones that are actually missing):
|
|
18
20
|
|
|
19
21
|
1. Which design system should I use? (e.g. Ant Design, Chakra UI, Carbon, Radix UI)
|
|
20
|
-
2. What is your base components folder? (e.g. `src/components/`) — subfolders `field/`, `template/`, `widget/`, and `
|
|
22
|
+
2. What is your base components folder? (e.g. `src/components/`) — subfolders `field/`, `template/`, `widget/`, `designSystemExtension/`, and `infra/` will be used under it.
|
|
21
23
|
|
|
22
24
|
### Component type scope
|
|
23
25
|
|
|
24
26
|
Extract which types the user wants from the message:
|
|
25
27
|
|
|
26
|
-
| User says | Types in scope
|
|
27
|
-
| ------------------------------------------ |
|
|
28
|
-
| "generate all components" | field + template + widget + designSystemExtension |
|
|
29
|
-
| "generate field and widget components" | field + widget
|
|
30
|
-
| "generate widget, template components" | widget + template
|
|
31
|
-
| "generate all components except templates" | field + widget + designSystemExtension |
|
|
32
|
-
| "replace everything" | field + template + widget + designSystemExtension |
|
|
28
|
+
| User says | Types in scope |
|
|
29
|
+
| ------------------------------------------ | --------------------------------------------------------- |
|
|
30
|
+
| "generate all components" | field + template + widget + designSystemExtension + infra |
|
|
31
|
+
| "generate field and widget components" | field + widget |
|
|
32
|
+
| "generate widget, template components" | widget + template |
|
|
33
|
+
| "generate all components except templates" | field + widget + designSystemExtension + infra |
|
|
34
|
+
| "replace everything" | field + template + widget + designSystemExtension + infra |
|
|
33
35
|
|
|
34
|
-
Default to **all
|
|
36
|
+
Default to **all five types** if the message does not restrict the scope. A type in scope does not mean every component of that type is generated — it means components of that type are eligible for the selection made in Step 0.5.
|
|
35
37
|
|
|
36
38
|
### Derived output paths
|
|
37
39
|
|
|
@@ -43,14 +45,102 @@ Once the base folder is known, derive the output path for each type in scope:
|
|
|
43
45
|
| template | `<base>/template/` |
|
|
44
46
|
| widget | `<base>/widget/` |
|
|
45
47
|
| designSystemExtension | `<base>/designSystemExtension/` |
|
|
48
|
+
| infra | `<base>/infra/` |
|
|
49
|
+
|
|
50
|
+
Once design system, base folder, and type scope are resolved, continue to Step 0.5.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Step 0.5 — Resolve the portal, its scope, and its components from the server (MANDATORY GATE)
|
|
55
|
+
|
|
56
|
+
⛔ **This step MUST complete before anything is read, installed, or written.** A portal renders a specific set of components, and generating the full catalogue produces components the portal will never mount. Do NOT use a hardcoded component list, and do NOT infer one from the project's existing folders.
|
|
57
|
+
|
|
58
|
+
### 0.5.1 — Resolve the portal
|
|
59
|
+
|
|
60
|
+
Execute the data source **`D_pyAvailablePortals`**, which returns the portals available in the application. Pass the name exactly as written — this data page is part of the Pega platform and does not vary between installations.
|
|
61
|
+
|
|
62
|
+
Execute it directly. Do not survey the session's capabilities first — the attempt is itself the check, and a better one: a capability survey can come back empty while the capability is present, stopping a flow that would have worked. Resolve the means of executing a Pega data source by what it does, not by what it is called; tool names and the server's label differ between editors and AI tools. Never look for a configuration file, never assume a path or a server name, and never tell the user which file to edit.
|
|
63
|
+
|
|
64
|
+
If nothing in this session can execute a Pega data source, stop. Tell the user the Pega MCP server is not available to this conversation, and name both common causes: the server is not running, or it was started after this conversation began — in which case its tools are not bound to this session and a new session is needed. Do not guess at its configuration, and do not fall back to generating the full component catalogue.
|
|
65
|
+
|
|
66
|
+
If the execution runs but fails, report the failure, and if the server's data sources can be listed, list them so the user can see whether the data page is offered at all. Do not substitute a different data page.
|
|
67
|
+
|
|
68
|
+
The response's `pxResults` array holds one entry per portal. Then:
|
|
69
|
+
|
|
70
|
+
1. If the user's message did NOT name a portal, present the returned portals as a numbered pick-list and ask which one to generate for.
|
|
71
|
+
2. If the user's message DID name one, confirm it appears in the response. If it does not, show what the server returned and ask the user to choose from that list. Never proceed on an unverified portal name.
|
|
72
|
+
3. Record the confirmed entry's **`pyPortalLayout`** value. This — not the display label shown to the user — is what Steps 0.5.3 and 0.5.4 pass to the server as `PortalName`; carry it forward exactly as the data page returned it.
|
|
73
|
+
|
|
74
|
+
### 0.5.2 — Ask what to convert
|
|
75
|
+
|
|
76
|
+
Ask the user which parts of the portal to convert: **Landing pages**, **Cases**, or **Both**. Allow selecting more than one. This is a gate — wait for the answer before continuing.
|
|
77
|
+
|
|
78
|
+
- If **Landing pages** is selected, run Step 0.5.3.
|
|
79
|
+
- If **Cases** is selected, run Step 0.5.4.
|
|
80
|
+
- If **Both** is selected, run 0.5.3 and 0.5.4 and merge their results in Step 0.5.5.
|
|
81
|
+
|
|
82
|
+
### 0.5.3 — Landing pages (skip unless selected)
|
|
83
|
+
|
|
84
|
+
Execute the data source **`D_pyPortalPages`** with `PortalName` set to the `pyPortalLayout` value recorded in Step 0.5.1. It returns the landing pages configured in that portal, in a `pxResults` array whose entries carry `pxObjClass`, `pyRuleName`, and `pyClassName`.
|
|
85
|
+
|
|
86
|
+
If `pxResults` is empty, tell the user this portal has no landing pages and, if Cases was not already selected, offer to fall back to it. If Cases was also not selected or also comes back empty, stop — there is nothing to generate.
|
|
87
|
+
|
|
88
|
+
Present the returned pages as a **checkbox list** (label each with its `pyRuleName`, and show its `pxObjClass` alongside so the user can tell a view from a landing page) and let the user select one or more. This is a gate.
|
|
89
|
+
|
|
90
|
+
For **each selected page**, resolve its components by its `pxObjClass`:
|
|
91
|
+
|
|
92
|
+
| `pxObjClass` | Data source | Parameters | Components are in |
|
|
93
|
+
| ------------------------------------------------------------ | --------------------------------- | -------------------------------------------------- | ----------------- |
|
|
94
|
+
| `Rule-UI-View` | `D_pyViewDependencies` | `ViewName = pyRuleName`, `ViewClass = pyClassName` | `pxDependencies` |
|
|
95
|
+
| `Rule-UI-View-LandingPage` (and anything else — the default) | `D_pyLandingPageComponentsByType` | `RuleName = pyRuleName`, `ClassName = pyClassName` | `pxResults` |
|
|
96
|
+
|
|
97
|
+
Do not supply `ApplicationName` or `ApplicationVersion` to `D_pyLandingPageComponentsByType` — ignore those parameters. Make one call per selected page, even when two pages resolve to the same data source. Discard malformed entries (anything that is not a plain component-name identifier) from each response, then union the results across all selected pages and drop duplicates. Keep a note of which page(s) contributed each component — Step 0.5.5 reports it.
|
|
98
|
+
|
|
99
|
+
### 0.5.4 — Cases (skip unless selected)
|
|
100
|
+
|
|
101
|
+
Execute the data source **`D_pyPortalCaseTypes`** with `PortalName` set to the `pyPortalLayout` value recorded in Step 0.5.1. It returns the case types configured in that portal, in a `pxResults` array whose entries carry `pyClassName`.
|
|
102
|
+
|
|
103
|
+
If `pxResults` is empty, tell the user this portal has no case types and, if Landing pages was not already selected, offer to fall back to it. If Landing pages was also not selected or also comes back empty, stop — there is nothing to generate.
|
|
104
|
+
|
|
105
|
+
Present the returned case types as a **checkbox list** and let the user select one or more. This is a gate.
|
|
106
|
+
|
|
107
|
+
For **each selected case type**, execute **`D_pyCaseViewComponentsByType`** with `CaseType` set to its `pyClassName`. Make one call per selected case type. Discard malformed entries from each response, then union the results across all selected case types and drop duplicates. Keep a note of which case type(s) contributed each component.
|
|
108
|
+
|
|
109
|
+
### 0.5.5 — Merge, present, and ask which components to generate
|
|
110
|
+
|
|
111
|
+
Union whatever Step 0.5.3 and Step 0.5.4 produced (only one ran unless the user chose Both) and drop duplicates across the two.
|
|
112
|
+
|
|
113
|
+
Read `{{PROMPT_DIR}}/component-manifest.json` and use its `components` and `aliases` entries to group every resulting name under its type — `field`, `template`, `widget`, `designSystemExtension`, or `infra`. List any name that matches nothing in the manifest under **Unrecognized**, carried through exactly as the server returned it, rather than dropping it or guessing a canonical name for it.
|
|
114
|
+
|
|
115
|
+
Present the grouped list — noting, for any component contributed by more than one page or case type, which ones — and ask which components to generate as a **checkbox list**, offering selecting all of them as an explicit option. Where a returned component is one the SDK provides and this prompt never generates — anything named in Step 8's never-generate list, or a structural wrapper such as `View`, `Region`, or `FlowContainer` — keep it visible in the list but mark it as not generatable and say why, so the user can see it's used without expecting a folder for it.
|
|
116
|
+
|
|
117
|
+
⛔ **Wait for the user's answer.** This is a gate, not a notification. Nothing is read, installed, or written until the selection is confirmed.
|
|
118
|
+
|
|
119
|
+
### 0.5.6 — Required additions
|
|
120
|
+
|
|
121
|
+
Add the following to the confirmed selection whether or not the user picked it, and note the addition in the Step 9 summary:
|
|
122
|
+
|
|
123
|
+
- **`FieldValueList`** — whenever the selection contains any field component. Every field renders its display-only mode through it, so the selected fields will not render correctly without it.
|
|
124
|
+
|
|
125
|
+
Layout sub-variants are not part of the selection at all — Step 5.2.1 derives them from whichever layout templates were selected, and the user never has to ask for them.
|
|
126
|
+
|
|
127
|
+
`ActionButtons`, `Stages`, and `MultiStep` are **not** added automatically. In a portal, that chrome is generated only when the user selects it.
|
|
46
128
|
|
|
47
|
-
|
|
129
|
+
### 0.5.7 — Derive the generation set
|
|
130
|
+
|
|
131
|
+
Intersect the confirmed selection with the type scope from Step 0, group the result by type, and record it as **the generation set**. It governs the rest of this prompt:
|
|
132
|
+
|
|
133
|
+
- Steps 1 and 2 read skills and discover design system components for the types present in the generation set.
|
|
134
|
+
- Step 3 checks for existing files only within the generation set.
|
|
135
|
+
- Steps 4–8 each generate only the components of their type that are in the generation set, and are skipped entirely when it holds none of their type.
|
|
136
|
+
|
|
137
|
+
Generate nothing outside the generation set. Do not add components based on assumptions about what a portal might need.
|
|
48
138
|
|
|
49
139
|
---
|
|
50
140
|
|
|
51
|
-
## Step 1 — Read general skill files (once, for each type in
|
|
141
|
+
## Step 1 — Read general skill files (once, for each type in the generation set)
|
|
52
142
|
|
|
53
|
-
Read the general skill file for every type in
|
|
143
|
+
Read the general skill file for every type present in the generation set. Do this upfront — do not re-read per component.
|
|
54
144
|
|
|
55
145
|
| Type | Skill file to read |
|
|
56
146
|
| --------------------- | ------------------------------------------ |
|
|
@@ -58,6 +148,7 @@ Read the general skill file for every type in scope. Do this upfront — do not
|
|
|
58
148
|
| template | `{{SKILL_DIR}}/template-components.md` |
|
|
59
149
|
| widget | `{{SKILL_DIR}}/widget-components.md` |
|
|
60
150
|
| designSystemExtension | `{{SKILL_DIR}}/design-system-extension.md` |
|
|
151
|
+
| infra | `{{SKILL_DIR}}/infra-components.md` |
|
|
61
152
|
|
|
62
153
|
Keep all loaded skill files active throughout the entire session.
|
|
63
154
|
|
|
@@ -69,6 +160,8 @@ Check the project's dependency manifest to determine whether the design system p
|
|
|
69
160
|
|
|
70
161
|
**Immediately after installation**, read `node_modules/<designSystem>/README.md` in full. From it, note the correct import paths, usage patterns, version-specific guidance, global CSS/styles import path, provider wrapper component name, and any peer dependency requirements. Store this information in your memory and use it for all subsequent steps — do not re-read the README later. If the README lists peer dependencies that are not already installed in the project, install them now — the design system will not function correctly without them.
|
|
71
162
|
|
|
163
|
+
**Discovery runs whether or not you had to install anything**, and the package may not sit under the project's own `node_modules/` — in a workspace or monorepo it is commonly hoisted to a parent `node_modules/`. Walk up the directory tree to find it rather than concluding it is missing, and take everything from the type definitions if the package ships no README.
|
|
164
|
+
|
|
72
165
|
You MUST also thoroughly inspect the installed design system package:
|
|
73
166
|
|
|
74
167
|
1. **Discover all available components** — browse the installed package's directory tree under `node_modules/<designSystem>/` to find every component it exports. Do not assume a specific folder structure (e.g. `dist/`) — packages vary widely in how they organize source, types, and entry points. Navigate through the package's folders, read its entry-point files and type definitions, and build a complete list of every component the package actually provides. Store all discovered component names and their import paths in your memory for reference during code generation.
|
|
@@ -115,7 +208,7 @@ Keep all DS discovery information active throughout the entire session. Referenc
|
|
|
115
208
|
|
|
116
209
|
## Step 3 — Overwrite check (all types, all at once)
|
|
117
210
|
|
|
118
|
-
For every
|
|
211
|
+
For every component in the generation set, check whether its file or directory already exists at the derived output path for its type. Components outside the generation set are not checked — they are not being generated.
|
|
119
212
|
|
|
120
213
|
Collect all existing components across all types and report them in one consolidated list:
|
|
121
214
|
|
|
@@ -127,13 +220,13 @@ Collect all existing components across all types and report them in one consolid
|
|
|
127
220
|
|
|
128
221
|
Wait for the user's answer before proceeding. If none exist, continue immediately.
|
|
129
222
|
|
|
130
|
-
⚠️ **This decision is final for the entire session.** Do NOT re-check file existence or re-ask this overwrite question during Steps 4–
|
|
223
|
+
⚠️ **This decision is final for the entire session.** Do NOT re-check file existence or re-ask this overwrite question during Steps 4–8. When you encounter a component file that already exists during generation, silently apply the decision made here (overwrite it or skip it) without prompting again. This applies even after retries, transport errors, or subagent restarts — the user's answer here governs all subsequent component generation in this conversation.
|
|
131
224
|
|
|
132
225
|
---
|
|
133
226
|
|
|
134
|
-
## Step 4 — Generate field components (skip if
|
|
227
|
+
## Step 4 — Generate field components (skip if the generation set holds no field component)
|
|
135
228
|
|
|
136
|
-
|
|
229
|
+
Generate each field component in the generation set, in order:
|
|
137
230
|
|
|
138
231
|
**For each field component:**
|
|
139
232
|
|
|
@@ -182,9 +275,9 @@ After each component: "`<ComponentName>` ✓ — using `<DS component name>`"
|
|
|
182
275
|
|
|
183
276
|
---
|
|
184
277
|
|
|
185
|
-
## Step 5 — Generate template components (skip if
|
|
278
|
+
## Step 5 — Generate template components (skip if the generation set holds no template component)
|
|
186
279
|
|
|
187
|
-
|
|
280
|
+
Generate each template component in the generation set, in order:
|
|
188
281
|
|
|
189
282
|
**For each template component:**
|
|
190
283
|
|
|
@@ -229,6 +322,8 @@ After generating **TwoColumn**, **OneColumn**, **NarrowWide**, or **WideNarrow**
|
|
|
229
322
|
|
|
230
323
|
Each sub-variant is a one-line passthrough that delegates to the base component via the project's component registry. It retrieves the base component (e.g. `TwoColumn`) from the registry and renders it with all props forwarded. Follow the same file extension and module pattern used by the rest of the project.
|
|
231
324
|
|
|
325
|
+
Sub-variants are not part of the generation set and never appear in the Step 0.5 selection — they are derived here from whichever of these four layouts was selected. Create them even though the user did not ask for them by name.
|
|
326
|
+
|
|
232
327
|
### 5.3 — Register the component
|
|
233
328
|
|
|
234
329
|
Open the project's component map file and:
|
|
@@ -243,9 +338,9 @@ After each component: "`<ComponentName>` ✓ — `<Layout | Form | Page>` templa
|
|
|
243
338
|
|
|
244
339
|
---
|
|
245
340
|
|
|
246
|
-
## Step 6 — Generate widget components (skip if
|
|
341
|
+
## Step 6 — Generate widget components (skip if the generation set holds no widget component)
|
|
247
342
|
|
|
248
|
-
|
|
343
|
+
Generate each widget component in the generation set, in order:
|
|
249
344
|
|
|
250
345
|
**For each widget component:**
|
|
251
346
|
|
|
@@ -292,9 +387,9 @@ After each component: "`<ComponentName>` ✓ — using `<DS card/list primitive>
|
|
|
292
387
|
|
|
293
388
|
---
|
|
294
389
|
|
|
295
|
-
## Step 7 — Generate design system extension components (skip if
|
|
390
|
+
## Step 7 — Generate design system extension components (skip if the generation set holds no DSE component)
|
|
296
391
|
|
|
297
|
-
|
|
392
|
+
Generate each design system extension component in the generation set, in order:
|
|
298
393
|
|
|
299
394
|
**For each DSE component:**
|
|
300
395
|
|
|
@@ -337,11 +432,80 @@ After each component: "`<ComponentName>` ✓ — Pattern `<B/A/C>`"
|
|
|
337
432
|
|
|
338
433
|
---
|
|
339
434
|
|
|
340
|
-
## Step 8 —
|
|
435
|
+
## Step 8 — Generate infrastructure components (skip if the generation set holds no infra component)
|
|
436
|
+
|
|
437
|
+
Infrastructure components are the chrome the runtime draws _around_ a case or an assignment. Most of them ship from the SDK adapter package. **Exactly three are overridable, and this list never grows:**
|
|
438
|
+
|
|
439
|
+
| Component | Pattern |
|
|
440
|
+
| ------------- | ------------------- |
|
|
441
|
+
| ActionButtons | Display-only chrome |
|
|
442
|
+
| Stages | Case-aware chrome |
|
|
443
|
+
| MultiStep | Container chrome |
|
|
444
|
+
|
|
445
|
+
⛔ **Never generate** `NavBar`, `DeferLoad`, `VerticalTabs`, `DashboardFilter`, or any other infrastructure component. They are structural plumbing tied to the SDK's own internals. This holds even when the portal reports one of them in Step 0.5 and the user selects it — skip it and say why.
|
|
446
|
+
|
|
447
|
+
Generate each infra component in the generation set that is one of the three overridable components above, in order:
|
|
448
|
+
|
|
449
|
+
**For each infra component:**
|
|
450
|
+
|
|
451
|
+
### 8.1 — Read the component-specific skill file (MANDATORY — do not skip)
|
|
452
|
+
|
|
453
|
+
Read the file `{{SKILL_DIR}}/infra-skills/<ComponentName>.md` using your file reading tool. This step is **required** for every component — do not rely solely on the general `infra-components.md`.
|
|
454
|
+
|
|
455
|
+
After reading, extract and keep active:
|
|
456
|
+
|
|
457
|
+
- **Pattern classification** — display-only chrome | case-aware chrome | container chrome
|
|
458
|
+
- **Input contract** — the exact inputs the runtime supplies, and whether the PConnect accessor is among them
|
|
459
|
+
- **Behavioral Contract** — derivation logic, callback signatures, state flags, fallback rules, edge cases
|
|
460
|
+
- **Design System Mapping** table — the recommended DS primitive for this chrome pattern
|
|
461
|
+
|
|
462
|
+
⚠️ The general skill provides the pattern skeletons. The component-specific skill provides the **exact input names, callback signatures, and derivation rules**. Both are needed.
|
|
463
|
+
|
|
464
|
+
### 8.2 — Generate the component files
|
|
465
|
+
|
|
466
|
+
Create the directory `<base>/infra/<ComponentName>/`.
|
|
467
|
+
|
|
468
|
+
Create the component's main implementation file using the file naming convention and extension appropriate to the project's framework.
|
|
469
|
+
|
|
470
|
+
Follow the implementation structure described in `infra-components.md` (loaded in Step 1) for the component's pattern classification. Use the DS primitives you identified in Step 2 for the rendered markup.
|
|
471
|
+
|
|
472
|
+
Generating an infra component produces an **override** of a component the SDK already supplies, so the contract is not yours to design — only the markup and the styling are:
|
|
473
|
+
|
|
474
|
+
- Do not reshape the input contract. Keep every input name and callback signature exactly as the runtime uses them.
|
|
475
|
+
- `ActionButtons` receives plain display props — do not give it a PConnect accessor.
|
|
476
|
+
- Localize every label through the Pega locale utilities or the localization service. Values arriving in the inputs are keys, not display text. If a skill file documents no locale source for a particular label, follow the skill file — that label arrives already localized.
|
|
477
|
+
- Resolve Pega sub-components through the project's component registry, never by direct import.
|
|
478
|
+
- Derive the display model from the runtime's raw inputs first, then render it.
|
|
479
|
+
- Where a skill file names an SDK styling helper or a derived flag that only exists to feed one — spacing classes, connector lines, last-item detection — and the DS primitive already handles it, drop it and use the primitive. Keep only what still carries meaning (state derivation, filtering, ordering), and report what you dropped.
|
|
480
|
+
|
|
481
|
+
If the project uses barrel/re-export files, create one in the same directory. Create a CSS file only if the skill file requires one for the implementation path you actually chose.
|
|
482
|
+
|
|
483
|
+
### 8.3 — Register the component
|
|
484
|
+
|
|
485
|
+
Open the project's component map file and apply the case that matches what you find there. An infra component is normally **absent from the output folder while still registered** — the SDK supplies every infrastructure component, so check the map before assuming the name is free.
|
|
486
|
+
|
|
487
|
+
**Case 1 — not registered by name** (no entry at all, or it resolves only through the SDK's built-in component spread):
|
|
488
|
+
|
|
489
|
+
1. Add an import at the top in the **Infra** section — create that section if it does not exist yet
|
|
490
|
+
2. Add an entry in the component map object under the infra comment
|
|
491
|
+
|
|
492
|
+
**Case 2 — already registered by name, imported from the SDK adapter package**: do NOT add a second import under the same name — that is a duplicate binding and will not compile. **Rebind the existing entry** instead: remove only this component's name from the SDK import, add an import for your generated implementation, and leave the existing map entry in place.
|
|
493
|
+
|
|
494
|
+
⛔ **Ordering is load-bearing for this category.** An infra entry MUST be listed **after** the SDK's built-in component spread. Listed before it, the spread replaces it and the override silently does nothing.
|
|
495
|
+
|
|
496
|
+
### 8.4 — Report progress
|
|
497
|
+
|
|
498
|
+
After each component: "`<ComponentName>` ✓ — `<display-only | case-aware | container>` chrome"
|
|
499
|
+
|
|
500
|
+
---
|
|
501
|
+
|
|
502
|
+
## Step 9 — Verify the build
|
|
341
503
|
|
|
342
504
|
Run the project's build process to confirm everything compiles without errors. Fix any TypeScript or build errors before reporting completion.
|
|
343
505
|
|
|
344
|
-
|
|
506
|
+
⚠️ **A passing build is not a passing type-check.** Many bundlers strip types without checking them, so a build can report success while generated components contain real type errors. If the project has a separate type-check step, run it too — and if it has none, invoke the type checker directly. Only errors in the files you created or edited are yours to fix; report any pre-existing errors elsewhere rather than fixing them.
|
|
507
|
+
|
|
508
|
+
### 9.1 — Validate component map key names
|
|
345
509
|
|
|
346
510
|
After a clean build, verify these key name exceptions in the component map:
|
|
347
511
|
|
|
@@ -349,10 +513,19 @@ After a clean build, verify these key name exceptions in the component map:
|
|
|
349
513
|
- [ ] `URL: URLComponent` (not `URLComponent,`)
|
|
350
514
|
- [ ] `Todo: ToDo` (not `ToDo,`)
|
|
351
515
|
|
|
352
|
-
These are cases where the Pega engine sends a component name that differs from the JavaScript variable name. If any are registered using shorthand (e.g., `ToDo,`), fix them to use explicit key mapping (e.g., `Todo: ToDo,`).
|
|
516
|
+
These are cases where the Pega engine sends a component name that differs from the JavaScript variable name. If any are registered using shorthand (e.g., `ToDo,`), fix them to use explicit key mapping (e.g., `Todo: ToDo,`). Verify only the keys whose components are in the generation set.
|
|
517
|
+
|
|
518
|
+
### 9.2 — Validate infra registration (skip if the generation set holds no infra component)
|
|
519
|
+
|
|
520
|
+
- [ ] Only `ActionButtons`, `Stages`, and `MultiStep` were generated — no other infrastructure component has a folder, or a registry entry pointing at generated code
|
|
521
|
+
- [ ] Every infra entry appears **after** the SDK's built-in component spread
|
|
522
|
+
- [ ] The SDK's built-in component spread is still present, and every registration that resolves through it or through the SDK adapter package is untouched
|
|
353
523
|
|
|
354
524
|
Report a final summary:
|
|
355
525
|
|
|
526
|
+
- The portal resolved in Step 0.5.1, the scope chosen in Step 0.5.2 (Landing pages / Cases / Both), and which pages and/or case types were selected
|
|
527
|
+
- How many components the server returned in total versus how many were selected to generate
|
|
356
528
|
- Total components generated, grouped by type
|
|
529
|
+
- `FieldValueList`, if it was added automatically under Step 0.5.6
|
|
357
530
|
- All entries added to the component map
|
|
358
|
-
- Any components skipped (if "skip existing" was chosen in Step 3)
|
|
531
|
+
- Any components skipped (if "skip existing" was chosen in Step 3, or because they are SDK-provided infrastructure)
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
---
|
|
2
|
+
ai-description: Generate all (or a subset of) infrastructure (chrome) components using any design system
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Step 0 — Resolve inputs
|
|
6
|
+
|
|
7
|
+
Read the user's message carefully. Extract:
|
|
8
|
+
|
|
9
|
+
- **Design system** — the UI library to use (e.g. `Ant Design`, `Chakra UI`, `Carbon`, `Radix UI`)
|
|
10
|
+
- **Output base path** — the folder where infrastructure components should be generated (e.g. `src/components/infra/`)
|
|
11
|
+
- **Component list** — which components to generate (default: all 3 listed below)
|
|
12
|
+
|
|
13
|
+
Both **design system** and **output base path** are required. If either is missing or ambiguous, you MUST stop and ask the user before proceeding. Do not infer any value from the project structure, `{{AI_FILE_EXT}}` files, existing folders, or any other source.
|
|
14
|
+
|
|
15
|
+
⛔ **STOP** — If the user's message does not explicitly state BOTH the design system AND the output path, ask for the missing items now. Do not proceed to Step 1 until you have explicit answers from the user for all required inputs.
|
|
16
|
+
|
|
17
|
+
Example questions (ask only the ones that are actually missing):
|
|
18
|
+
|
|
19
|
+
1. Which design system should I use? (e.g. Ant Design, Chakra UI, Carbon, Radix UI)
|
|
20
|
+
2. Where should the infrastructure components be generated? (e.g. `src/components/infra/`)
|
|
21
|
+
|
|
22
|
+
If the user specified a subset (e.g., "just ActionButtons and Stages"), restrict the list accordingly.
|
|
23
|
+
|
|
24
|
+
### Full component list (default — 3 infra components)
|
|
25
|
+
|
|
26
|
+
Infrastructure components are the chrome the Pega runtime draws _around_ a case or an assignment. Most of them ship from the SDK adapter package. **Only these three are overridable, and this list never grows:**
|
|
27
|
+
|
|
28
|
+
| Component | Role | Pattern | DS needed? |
|
|
29
|
+
| ------------- | ---------------------------------------------------- | ------------------- | ---------- |
|
|
30
|
+
| ActionButtons | The Cancel / Save / Submit row beneath an assignment | Display-only chrome | Yes |
|
|
31
|
+
| Stages | The case stage progress indicator | Case-aware chrome | Yes |
|
|
32
|
+
| MultiStep | Step navigation within a multi-step assignment | Container chrome | Yes |
|
|
33
|
+
|
|
34
|
+
⛔ **Never generate these** — they are structural plumbing tied to the SDK's own internals and are always sourced from the SDK adapter package:
|
|
35
|
+
|
|
36
|
+
| Component | Role |
|
|
37
|
+
| --------------- | ---------------------------- |
|
|
38
|
+
| NavBar | Portal navigation shell |
|
|
39
|
+
| DeferLoad | Deferred content loader |
|
|
40
|
+
| VerticalTabs | Case view tab rail |
|
|
41
|
+
| DashboardFilter | Dashboard filtering controls |
|
|
42
|
+
|
|
43
|
+
If the user names one of them — or any other infrastructure component not in the table of three — skip it, tell them it is SDK-provided and not generated, and continue with the rest of the list. Do not create a skill file, a folder, or a registry entry for it.
|
|
44
|
+
|
|
45
|
+
Once both inputs are known, continue to Step 1.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Step 1 — Read `infra-components.md` (once, for the entire session)
|
|
50
|
+
|
|
51
|
+
Read the full contents of `{{SKILL_DIR}}/infra-components.md`.
|
|
52
|
+
|
|
53
|
+
This gives you:
|
|
54
|
+
|
|
55
|
+
- The three implementation patterns (display-only chrome, case-aware chrome, container chrome)
|
|
56
|
+
- The input contract for each of the three components — they do **not** share one
|
|
57
|
+
- Localization rules, sub-component resolution rules, and the registration ordering rule
|
|
58
|
+
- The Design System Adaptation section — chrome primitive mapping and DS discovery guidance
|
|
59
|
+
|
|
60
|
+
Keep this context active throughout the entire generation session. Do not re-read it per component.
|
|
61
|
+
|
|
62
|
+
> Infrastructure components differ from every other category in one important way: **they already exist**. Generating one produces an override of the SDK's implementation. The runtime keeps calling it with the contract it already uses, so the contract is not yours to design — only the markup and the styling are.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Step 2 — Install and discover the design system (once)
|
|
67
|
+
|
|
68
|
+
Check the project's dependency manifest to determine whether the design system package is already installed. If it is **not** listed in the project's dependencies, install it using the project's package manager. Report what was installed, or report that it was already present. If installing is not possible — no network, a locked or offline environment, a package manager that refuses — stop and report exactly that. Do not carry on and generate components against a design system you could not inspect.
|
|
69
|
+
|
|
70
|
+
**Discovery runs either way.** Whether you just installed the package or found it already listed, you MUST complete the rest of this step before generating anything. An already-installed design system is the normal case for this category, and it is never a reason to skip discovery.
|
|
71
|
+
|
|
72
|
+
**Locate the installed package on disk.** It is usually under the project's own `node_modules/<designSystem>/`, but in a workspace or monorepo it is commonly hoisted to a parent `node_modules/`. If it is not under the project directory, walk up the directory tree until you find it. Not finding it immediately does **not** mean it is missing — never conclude the package is uninstalled, and never attempt a second install, before you have checked the parent `node_modules` directories.
|
|
73
|
+
|
|
74
|
+
Read the package's `README.md` in full if it has one. From it, note the correct import paths, usage patterns, version-specific guidance, global CSS/styles import path, provider wrapper component name, and any peer dependency requirements. Store this information in your memory and use it for all subsequent steps — do not re-read the README later. If the README lists peer dependencies that are not already installed in the project, install them now — the design system will not function correctly without them. **Many packages ship no README at all** — if there is none, skip straight to the inspection steps below and take everything from the type definitions instead.
|
|
75
|
+
|
|
76
|
+
You MUST also thoroughly inspect the installed design system package, focusing on chrome primitives (Button, Button group, Toolbar, Divider, Stepper, Steps, Breadcrumbs, List):
|
|
77
|
+
|
|
78
|
+
1. **Discover all available chrome primitives** — browse the installed package's directory tree to find every component it exports. Do not assume a specific folder structure (e.g. `dist/`) — packages vary widely in how they organize source, types, and entry points. Navigate through the package's folders, read its entry-point files and type definitions, and build a complete list of every primitive the package actually provides. Store all discovered component names and their import paths in your memory for reference during code generation.
|
|
79
|
+
2. **Map each infra component to the best available DS primitive** — the chrome patterns described in the skill files may not have an exact name match in the installed design system. Using the complete list you just discovered, identify which DS primitive best serves the same purpose (e.g. a stepper or breadcrumb primitive for stage progression). If no single DS component is a close match, compose the requested behavior from multiple available DS primitives. Never fabricate a component import that does not exist in the installed package.
|
|
80
|
+
3. **Read the props interface of every primitive you plan to use** — for each component you intend to use, locate and read its TypeScript type definitions (`.d.ts` files or inline types) to understand the exact prop names, types, required vs. optional status, and any relevant enums or union types. Pay special attention to **emphasis/variant prop names** (primary vs. secondary actions) and to **step state conventions** (completed / active / pending). Store this information in your memory alongside the component names.
|
|
81
|
+
4. **Use ONLY confirmed component names and prop names** — when generating code, you must exclusively use the component names and prop names you discovered from the installed package. Do not rely on training knowledge of the design system's API, as it may be outdated, inaccurate, or refer to components/props that do not exist in the installed version.
|
|
82
|
+
|
|
83
|
+
Also check:
|
|
84
|
+
|
|
85
|
+
- Whether the design system has a **companion icon package** — read its exports before using any icon name; never guess icon names. Decorative icons must be hidden from assistive technology.
|
|
86
|
+
- Whether it has **size/emphasis/variant conventions** — use built-in props rather than custom padding
|
|
87
|
+
- Whether it has a **tokens or CSS directory** — use design system CSS custom properties for spacing; never hardcode `px` values
|
|
88
|
+
|
|
89
|
+
### 2.1 — Install the DS styles package and configure global CSS (MANDATORY)
|
|
90
|
+
|
|
91
|
+
Design systems require their global stylesheet — without it, components render unstyled.
|
|
92
|
+
|
|
93
|
+
#### Known DS style requirements (examples — verify against the package you inspected):
|
|
94
|
+
|
|
95
|
+
| Design System | Styles Package (example) | CSS Import (example) | Provider Wrapper (example) |
|
|
96
|
+
| ------------- | ------------------------ | ---------------------------------------- | -------------------------- |
|
|
97
|
+
| Carbon | `@carbon/styles` | `import '@carbon/react/css/styles.css';` | `<Theme>` |
|
|
98
|
+
| Ant Design | (included) | `import 'antd/dist/reset.css';` | `<ConfigProvider>` |
|
|
99
|
+
| Radix Themes | `@radix-ui/themes` | `import '@radix-ui/themes/styles.css';` | `<Theme>` |
|
|
100
|
+
| Chakra UI | (included) | (none — runtime) | `<ChakraProvider>` |
|
|
101
|
+
| Shadcn/ui | (Tailwind) | `import './globals.css';` | None |
|
|
102
|
+
| MUI | (included) | (none — CSS-in-JS) | `<ThemeProvider>` |
|
|
103
|
+
|
|
104
|
+
Above mentioned are **examples** based on common versions. Use the import path and provider name you noted while inspecting the package — they take precedence over this table.
|
|
105
|
+
|
|
106
|
+
If in table and not already configured: install styles package (if separate), add the global CSS import as the **first import** in the application's entry file, and add the Provider wrapper in the application's providers file.
|
|
107
|
+
If not in table: browse the installed design system's folder for a `styles/` or `dist/` directory containing CSS files, and use what you find there.
|
|
108
|
+
|
|
109
|
+
Before implementing any component, verify whether design-system-specific styles are already configured in the existing codebase — check the application's entry file for a matching CSS import. If the styles are already imported and configured, skip this step and report "already configured".
|
|
110
|
+
|
|
111
|
+
Report what was installed/configured (or "already configured").
|
|
112
|
+
|
|
113
|
+
Keep all DS discovery information active throughout the entire session. Reference it whenever generating a component — do NOT re-run discovery per component.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Step 3 — Existing-implementation check (all at once)
|
|
118
|
+
|
|
119
|
+
For each component in the list, check **both** of the following — an infra component can already be live in the running application without having a single file in the output folder:
|
|
120
|
+
|
|
121
|
+
1. **The output path** — does `<outputPath>/<ComponentName>/` already exist?
|
|
122
|
+
2. **The component map** — open the project's component map file and check whether the component's Pega name is **already registered**. It usually is: the SDK contributes every infrastructure component, and the project may additionally import it by name from the SDK adapter package and list it explicitly.
|
|
123
|
+
|
|
124
|
+
> Unlike every other category, an infrastructure component is normally **absent from the output folder** while still rendering at runtime — the SDK supplies it. An empty output folder is expected and is not a reason to stop. It is also **not** evidence that the component is unregistered. Record, per component, whether an existing registration was found and where its import comes from — Step 4c needs this.
|
|
125
|
+
|
|
126
|
+
If a component already has **files at the output path**, report them all at once and ask:
|
|
127
|
+
|
|
128
|
+
> "The following N components already exist: [list]. How should I proceed?
|
|
129
|
+
>
|
|
130
|
+
> - **Overwrite all** — replace all existing implementations
|
|
131
|
+
> - **Skip existing** — only generate components that don't exist yet
|
|
132
|
+
> - **Cancel** — stop without generating anything"
|
|
133
|
+
|
|
134
|
+
Wait for the user's answer before proceeding. If none exist, continue immediately.
|
|
135
|
+
|
|
136
|
+
An existing **registration** alone is not an overwrite — do not ask about it. It is expected, and Step 4c tells you how to rebind it.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Step 4 — Generate each component (loop)
|
|
141
|
+
|
|
142
|
+
For each component in the resolved list (in the order listed in Step 0):
|
|
143
|
+
|
|
144
|
+
### 4a — Read the component-specific skill file (MANDATORY — do not skip)
|
|
145
|
+
|
|
146
|
+
Read the file `{{SKILL_DIR}}/infra-skills/<ComponentName>.md` using your file reading tool. This step is **required** for every component — do not rely solely on the general `infra-components.md`.
|
|
147
|
+
|
|
148
|
+
After reading, extract and keep active:
|
|
149
|
+
|
|
150
|
+
- **Pattern classification** — display-only chrome / case-aware chrome / container chrome
|
|
151
|
+
- **Input contract** — the exact inputs the runtime supplies, and whether the PConnect accessor is among them
|
|
152
|
+
- **Behavioral Contract** — derivation logic, callback signatures, state flags, fallback rules, edge cases
|
|
153
|
+
- **Design System Mapping** table — the recommended DS primitive for this component's chrome pattern
|
|
154
|
+
|
|
155
|
+
⚠️ The general skill file (`infra-components.md`) provides the pattern skeletons. The component-specific skill file provides the **exact input names, callback signatures, and derivation rules**. Both are needed — generating from only the general skill will produce chrome that renders but does not receive or forward what the runtime expects.
|
|
156
|
+
|
|
157
|
+
A skill file may describe SDK styling helpers or derived flags that only exist to hand-build structure a design system primitive renders for you. Read Step 4b's rule on those **before** you start writing — it decides which of them survive.
|
|
158
|
+
|
|
159
|
+
### 4b — Generate the component files
|
|
160
|
+
|
|
161
|
+
Create the directory `<outputPath>/<ComponentName>/`.
|
|
162
|
+
|
|
163
|
+
Create the component's main implementation file using the file naming convention and extension appropriate to the project's framework (determine this by examining existing components in the project).
|
|
164
|
+
|
|
165
|
+
Follow the implementation structure described in `infra-components.md` (loaded in Step 1) for the component's pattern classification, as identified in Step 4a. Use the DS primitives you identified in Step 2 for the rendered markup.
|
|
166
|
+
|
|
167
|
+
Apply the Behavioral Contract from the component skill file exactly. In particular:
|
|
168
|
+
|
|
169
|
+
- **Do not reshape the input contract.** The runtime decides it. Keep every input name and every callback signature exactly as the SDK component being replaced uses them.
|
|
170
|
+
- **Not every chrome component receives the PConnect accessor.** `ActionButtons` is handed plain display props and must not reach the runtime for its own data. Do not add an accessor to it.
|
|
171
|
+
- **Localize every label.** Values arriving in the inputs are keys, not display text — resolve them through the Pega locale utilities or the localization service, as the component's skill file specifies. Never render a raw input string as a label and never hardcode label text. If a skill file documents no locale source for a particular label, follow the skill file — that label arrives already localized, and running it through a locale lookup a second time will blank it out.
|
|
172
|
+
- **Resolve Pega sub-components through the project's component registry**, never by direct import — a direct import pins the sub-component to the SDK's version and silently discards any override.
|
|
173
|
+
- **Derive before rendering.** Compute the display model from the runtime's raw inputs first, then render it. This is what keeps the component portable across design systems.
|
|
174
|
+
- **Keep repeated elements stable.** Every item in a rendered collection needs a stable identity.
|
|
175
|
+
- Treat every array input as optional and default it to empty.
|
|
176
|
+
|
|
177
|
+
**When a skill file names an SDK styling helper — or a derived flag that exists only to feed one — that the DS primitive already handles for you**, prefer the DS primitive and drop it. Some of these exist only to hand-build structure the SDK renders itself — spacing classes, connector lines, last-item detection. A DS stepper, breadcrumb or list that owns its own connectors and item states makes them unreachable, and the class names they return refer to SDK stylesheets you are no longer using. Keep only what still carries meaning (state derivation, filtering, ordering), state in your progress report which ones you dropped and why, and never hand-roll raw markup purely to keep one alive — that defeats the point of adopting the design system. This rule overrides the skill file's wording where the two conflict; nothing else in the skill file's Behavioral Contract is negotiable.
|
|
178
|
+
|
|
179
|
+
If the project uses barrel/re-export files (check existing component directories for the convention), create one in the same directory following the same pattern. Create a CSS file only if the skill file requires one **for the implementation path you actually chose** — skill files commonly document a CSS-only fallback that does not apply once you are rendering with design system primitives.
|
|
180
|
+
|
|
181
|
+
### 4c — Register the component
|
|
182
|
+
|
|
183
|
+
Open the project's component map file (the file that maps component names to their implementations) and apply the case that matches what Step 3 recorded for this component.
|
|
184
|
+
|
|
185
|
+
**Case 1 — the component is not registered by name.** Either the map has no entry for it at all, or it resolves only through the SDK's built-in component spread. Both are the same job:
|
|
186
|
+
|
|
187
|
+
1. Add an import at the top of the file in the **Infra** section — create that section if it does not exist yet
|
|
188
|
+
2. Add an entry in the component map object under the infra comment
|
|
189
|
+
|
|
190
|
+
**Case 2 — the component is already registered by name, imported from the SDK adapter package.** Do **not** add a second import under the same name — that is a duplicate binding and will not compile. Instead **rebind the existing entry**:
|
|
191
|
+
|
|
192
|
+
1. Remove only this component's name from the SDK import — leave every other name in that import untouched
|
|
193
|
+
2. Add a new import for your generated implementation
|
|
194
|
+
3. Leave the existing map entry in place; it now resolves to your implementation
|
|
195
|
+
|
|
196
|
+
Rebinding an existing entry is the one restructuring this step permits, and only for the components you are generating. Do not reorder or restructure any other existing entries.
|
|
197
|
+
|
|
198
|
+
⛔ **Ordering is load-bearing for this category.** An infra entry is an override of a component the SDK already contributes, so it MUST be listed **after** the SDK's built-in component spread. Listed before it, the spread replaces it and the override silently does nothing.
|
|
199
|
+
|
|
200
|
+
Never remove the SDK's built-in component spread — it supplies the infrastructure components that are not overridable, and removing it breaks rendering entirely.
|
|
201
|
+
|
|
202
|
+
### 4d — Report progress
|
|
203
|
+
|
|
204
|
+
After each component: "`<ComponentName>` ✓ — `<display-only | case-aware | container>` chrome, using `<DS primitive>`"
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Step 5 — Verify the build
|
|
209
|
+
|
|
210
|
+
Run the project's build process to confirm everything compiles without errors.
|
|
211
|
+
|
|
212
|
+
⚠️ **A passing build is not a passing type-check.** Many bundlers strip types without checking them, so a build can report success while your components contain real type errors. If the project has a separate type-check step, run it too — and if it has none, invoke the type checker directly. Only errors in the files you created or edited are yours to fix; report any pre-existing errors elsewhere rather than fixing them.
|
|
213
|
+
|
|
214
|
+
Fix any errors in your own files before reporting completion.
|
|
215
|
+
|
|
216
|
+
Before reporting success, confirm:
|
|
217
|
+
|
|
218
|
+
- [ ] Only `ActionButtons`, `Stages`, and `MultiStep` were generated — no other infrastructure component has a folder, or a registry entry pointing at generated code
|
|
219
|
+
- [ ] Every generated infra entry appears **after** the SDK's built-in component spread in the component map
|
|
220
|
+
- [ ] The SDK's built-in component spread is still present, and every registration that resolves through it or through the SDK adapter package is untouched
|
|
221
|
+
|
|
222
|
+
Report a summary: list of all files created, all entries added to the component map, and any components skipped because they are SDK-provided.
|