@pega/sdk 0.0.14 → 0.0.15

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.
Files changed (130) hide show
  1. package/README.md +46 -6
  2. package/dist/index.js +50 -24
  3. package/package.json +42 -3
  4. package/templates/angular-sdk-reference/angular.json +1 -2
  5. package/templates/angular-sdk-reference/extra-webpack.config.cjs +23 -0
  6. package/templates/angular-sdk-reference/index.html +12 -0
  7. package/templates/angular-sdk-reference/package.json +0 -1
  8. package/templates/angular-sdk-reference/src/app/app.component.ts +15 -232
  9. package/templates/angular-sdk-reference/src/app/pconnect-renderer.component.ts +153 -0
  10. package/templates/angular-sdk-reference/src/components/fields/auto-complete/auto-complete.component.ts +58 -21
  11. package/templates/angular-sdk-reference/src/components/fields/checkbox/checkbox.component.ts +8 -3
  12. package/templates/angular-sdk-reference/src/components/fields/currency/currency.component.ts +22 -7
  13. package/templates/angular-sdk-reference/src/components/fields/date-input/date-input.component.ts +19 -6
  14. package/templates/angular-sdk-reference/src/components/fields/dropdown/dropdown.component.ts +24 -7
  15. package/templates/angular-sdk-reference/src/components/fields/email/email.component.ts +19 -6
  16. package/templates/angular-sdk-reference/src/components/fields/integer/integer.component.ts +19 -6
  17. package/templates/angular-sdk-reference/src/components/fields/phone/phone.component.ts +19 -6
  18. package/templates/angular-sdk-reference/src/components/fields/radio-buttons/radio-buttons.component.ts +16 -5
  19. package/templates/angular-sdk-reference/src/components/fields/text-area/text-area.component.ts +19 -6
  20. package/templates/angular-sdk-reference/src/components/fields/text-input/text-input.component.ts +19 -6
  21. package/templates/angular-sdk-reference/src/components/fields/url-input/url-input.component.ts +26 -7
  22. package/templates/angular-sdk-reference/src/components/helpers/sdk-helpers.ts +93 -0
  23. package/templates/angular-sdk-reference/src/components/infra/case-summary/case-summary.component.ts +8 -9
  24. package/templates/angular-sdk-reference/src/components/infra/case-view/case-view.component.ts +24 -12
  25. package/templates/angular-sdk-reference/src/components/infra/root-container/root-container.component.ts +21 -15
  26. package/templates/angular-sdk-reference/src/components/infra/stages/stages.component.ts +21 -10
  27. package/templates/angular-sdk-reference/src/components/infra/view/view.component.ts +14 -9
  28. package/templates/angular-sdk-reference/src/components/templates/default-form/default-form.component.ts +12 -8
  29. package/templates/angular-sdk-reference/tsconfig.app.json +13 -0
  30. package/templates/angular-sdk-reference/tsconfig.json +2 -5
  31. package/templates/react-sdk-reference/.ai-common/agents/embedded-flow-expert.md +65 -31
  32. package/templates/react-sdk-reference/.ai-common/agents/implementation-expert.md +74 -38
  33. package/templates/react-sdk-reference/.ai-common/global/ai-agent-instructions-embedded.md +33 -1
  34. package/templates/react-sdk-reference/.ai-common/global/ai-agent-instructions.md +57 -22
  35. package/templates/react-sdk-reference/.ai-common/instructions/embedded-component.md +25 -10
  36. package/templates/react-sdk-reference/.ai-common/prompts/add-component.md +40 -19
  37. package/templates/react-sdk-reference/.ai-common/prompts/component-manifest.json +55 -1
  38. package/templates/react-sdk-reference/.ai-common/prompts/embedded-component-manifest.md +26 -4
  39. package/templates/react-sdk-reference/.ai-common/prompts/generate-all-components.md +82 -33
  40. package/templates/react-sdk-reference/.ai-common/prompts/generate-dse-components.md +46 -26
  41. package/templates/react-sdk-reference/.ai-common/prompts/generate-embedded-components.md +28 -15
  42. package/templates/react-sdk-reference/.ai-common/prompts/generate-field-components.md +24 -6
  43. package/templates/react-sdk-reference/.ai-common/prompts/generate-infra-components.md +24 -6
  44. package/templates/react-sdk-reference/.ai-common/prompts/generate-template-components.md +24 -6
  45. package/templates/react-sdk-reference/.ai-common/prompts/generate-widget-components.md +24 -6
  46. package/templates/react-sdk-reference/.ai-common/prompts/identify-components.md +2 -0
  47. package/templates/react-sdk-reference/.ai-common/prompts/replace-design-system.md +44 -17
  48. package/templates/react-sdk-reference/.ai-common/skills/connect-pega-server.md +14 -1
  49. package/templates/react-sdk-reference/.ai-common/skills/design-system-extension-skills/AssignmentHeader.md +79 -0
  50. package/templates/react-sdk-reference/.ai-common/skills/design-system-extension-skills/Toast.md +96 -0
  51. package/templates/react-sdk-reference/.ai-common/skills/design-system-extension.md +56 -35
  52. package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/analyze-customer-repo.md +29 -3
  53. package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/run-and-verify-integration.md +97 -37
  54. package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/wire-integration.md +91 -60
  55. package/templates/react-sdk-reference/.ai-common/skills/field-components.md +13 -1
  56. package/templates/react-sdk-reference/.ai-common/skills/infra-components.md +13 -1
  57. package/templates/react-sdk-reference/.ai-common/skills/portal-flow/run-and-verify-portal.md +290 -0
  58. package/templates/react-sdk-reference/.ai-common/skills/template-components.md +13 -1
  59. package/templates/react-sdk-reference/.ai-common/skills/widget-components.md +13 -1
  60. package/templates/react-sdk-reference/assets/icons/trash.svg +3 -0
  61. package/templates/react-sdk-reference/index.html +0 -1
  62. package/templates/react-sdk-reference/package.json +2 -2
  63. package/templates/react-sdk-reference/package.minimal.json +2 -2
  64. package/templates/react-sdk-reference/sdk-config.json +3 -3
  65. package/templates/react-sdk-reference/src/FallbackComponent.tsx +1 -1
  66. package/templates/react-sdk-reference/src/MashupApp.tsx +33 -78
  67. package/templates/react-sdk-reference/src/PortalApp.tsx +23 -100
  68. package/templates/react-sdk-reference/src/components/component-map.ts +15 -1
  69. package/templates/react-sdk-reference/src/components/designSystemExtension/AssignmentHeader/AssignmentHeader.tsx +15 -0
  70. package/templates/react-sdk-reference/src/components/designSystemExtension/AssignmentHeader/index.tsx +1 -0
  71. package/templates/react-sdk-reference/src/components/designSystemExtension/FieldGroup/FieldGroup.tsx +1 -1
  72. package/templates/react-sdk-reference/src/components/designSystemExtension/FieldGroupList/FieldGroupList.tsx +1 -1
  73. package/templates/react-sdk-reference/src/components/designSystemExtension/FieldValueList/FieldValueList.tsx +16 -4
  74. package/templates/react-sdk-reference/src/components/designSystemExtension/ModalDialog/ModalDialog.tsx +26 -0
  75. package/templates/react-sdk-reference/src/components/designSystemExtension/ModalDialog/index.tsx +1 -0
  76. package/templates/react-sdk-reference/src/components/designSystemExtension/Toast/Toast.tsx +35 -0
  77. package/templates/react-sdk-reference/src/components/designSystemExtension/Toast/index.tsx +1 -0
  78. package/templates/react-sdk-reference/src/components/field/AutoComplete/AutoComplete.tsx +362 -24
  79. package/templates/react-sdk-reference/src/components/field/CancelAlert/CancelAlert.tsx +1 -1
  80. package/templates/react-sdk-reference/src/components/field/Checkbox/Checkbox.tsx +3 -1
  81. package/templates/react-sdk-reference/src/components/field/Currency/Currency.tsx +6 -3
  82. package/templates/react-sdk-reference/src/components/field/Date/Date.tsx +2 -1
  83. package/templates/react-sdk-reference/src/components/field/DateTime/DateTime.tsx +2 -1
  84. package/templates/react-sdk-reference/src/components/field/Decimal/Decimal.tsx +4 -3
  85. package/templates/react-sdk-reference/src/components/field/Dropdown/Dropdown.tsx +2 -0
  86. package/templates/react-sdk-reference/src/components/field/Email/Email.tsx +2 -1
  87. package/templates/react-sdk-reference/src/components/field/EmbeddedDataMulti/EmbeddedDataMulti.tsx +121 -0
  88. package/templates/react-sdk-reference/src/components/field/EmbeddedDataMulti/config-ext.json +7 -0
  89. package/templates/react-sdk-reference/src/components/field/EmbeddedDataMulti/index.tsx +1 -0
  90. package/templates/react-sdk-reference/src/components/field/Integer/Integer.tsx +2 -1
  91. package/templates/react-sdk-reference/src/components/field/Location/Location.tsx +1 -1
  92. package/templates/react-sdk-reference/src/components/field/Multiselect/Multiselect.tsx +40 -20
  93. package/templates/react-sdk-reference/src/components/field/ObjectReference/ObjectReference.tsx +554 -49
  94. package/templates/react-sdk-reference/src/components/field/ObjectReference/utils.ts +111 -20
  95. package/templates/react-sdk-reference/src/components/field/Percentage/Percentage.tsx +4 -3
  96. package/templates/react-sdk-reference/src/components/field/Phone/Phone.tsx +2 -1
  97. package/templates/react-sdk-reference/src/components/field/SelectableCard/SelectableCard.tsx +2 -1
  98. package/templates/react-sdk-reference/src/components/field/TextArea/TextArea.tsx +2 -1
  99. package/templates/react-sdk-reference/src/components/field/TextInput/TextInput.tsx +2 -1
  100. package/templates/react-sdk-reference/src/components/field/Time/Time.tsx +2 -1
  101. package/templates/react-sdk-reference/src/components/field/URL/URL.tsx +2 -1
  102. package/templates/react-sdk-reference/src/components/field/UserReference/UserReference.tsx +1 -1
  103. package/templates/react-sdk-reference/src/components/helpers/field-utils.ts +44 -0
  104. package/templates/react-sdk-reference/src/components/helpers/simpleTableHelpers.ts +19 -7
  105. package/templates/react-sdk-reference/src/components/infra/ModalViewContainer/DataViewActionButtons/DataViewActionButtons.tsx +97 -0
  106. package/templates/react-sdk-reference/src/components/infra/ModalViewContainer/DataViewActionButtons/index.tsx +1 -0
  107. package/templates/react-sdk-reference/src/components/infra/ModalViewContainer/ListViewActionButtons/ListViewActionButtons.tsx +53 -0
  108. package/templates/react-sdk-reference/src/components/infra/ModalViewContainer/ListViewActionButtons/index.tsx +1 -0
  109. package/templates/react-sdk-reference/src/components/template/AdvancedSearch/SearchGroups/SearchGroups.tsx +2 -2
  110. package/templates/react-sdk-reference/src/components/template/CaseSummary/CaseSummary.tsx +3 -1
  111. package/templates/react-sdk-reference/src/components/template/DataReference/SearchForm.tsx +4 -4
  112. package/templates/react-sdk-reference/src/components/template/HierarchicalForm/HierarchicalForm.tsx +2 -2
  113. package/templates/react-sdk-reference/src/components/template/InlineDashboard/InlineDashboard.tsx +1 -1
  114. package/templates/react-sdk-reference/src/components/template/ListView/ListView.tsx +7 -3
  115. package/templates/react-sdk-reference/src/components/template/SimpleTable/SimpleTableManual/SimpleTableManual.tsx +173 -99
  116. package/templates/react-sdk-reference/src/components/template/SimpleTable/SimpleTableSelect/SimpleTableSelect.tsx +63 -56
  117. package/templates/react-sdk-reference/src/components/widget/ToDo/ToDo.tsx +1 -1
  118. package/templates/react-sdk-reference/vite.config.ts +26 -4
  119. package/templates/angular-sdk-reference/pega-constellationjs-0.26.3-local.tgz +0 -0
  120. package/templates/angular-sdk-reference/src/helpers/event-utils.ts +0 -18
  121. package/templates/angular-sdk-reference/src/helpers/utils.ts +0 -38
  122. package/templates/angular-sdk-reference/src/helpers/versionHelpers.ts +0 -14
  123. package/templates/react-sdk-reference/.ai-common/instructions/dse-component.md +0 -47
  124. package/templates/react-sdk-reference/.ai-common/instructions/field-component.md +0 -50
  125. package/templates/react-sdk-reference/.ai-common/instructions/infra-component.md +0 -76
  126. package/templates/react-sdk-reference/.ai-common/instructions/template-component.md +0 -43
  127. package/templates/react-sdk-reference/.ai-common/instructions/widget-component.md +0 -45
  128. package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/authenticate.md +0 -311
  129. package/templates/react-sdk-reference/pega-constellationjs-0.26.3-local.tgz +0 -0
  130. package/templates/react-sdk-reference/pega-sdk-react-0.1.0.tgz +0 -0
package/README.md CHANGED
@@ -8,12 +8,21 @@ building right away.
8
8
  ## For AI Coding Agents
9
9
 
10
10
  Recognize these as requests to run this CLI, whether the folder is empty or already
11
- has a project in it:
12
-
13
- - "Scaffold a new Pega app / project using `@pega/sdk`" → run in an **empty folder**.
14
- - "Scaffold `@pega/sdk` / add Pega embedded flow into this repo" (or similar,
15
- said while working inside an existing host application) → run in that
16
- **existing project's folder**.
11
+ has a project in it. Users rarely use these words — judge by what they want, not
12
+ by how they say it:
13
+
14
+ - **They want a Pega form or workflow inside the app they already have** → run in
15
+ that **existing project's folder**. For example: "Scaffold `@pega/sdk` / add Pega
16
+ embedded flow into this repo", "add the service request form to my app when
17
+ someone clicks Apply", "show a Pega form inside my page", "let customers raise a
18
+ case from our website".
19
+ - **They want a new Pega app or portal** → run in an **empty folder**. For example:
20
+ "Scaffold a new Pega app / project using `@pega/sdk`", "start a new Pega app with
21
+ Chakra UI", "build me a Pega portal".
22
+
23
+ The examples are illustrations, not a complete list. Ask the user only when the
24
+ request is genuinely unclear — for example, they say "my app" but the folder is
25
+ empty.
17
26
 
18
27
  In both cases, run `npx --yes @pega/sdk init` non-interactively — see
19
28
  [Non-Interactive / Scripted Usage](#non-interactive--scripted-usage) below for the
@@ -36,6 +45,12 @@ about or guess:
36
45
  | `--mode` (auto-detected from whether `package.json` exists in the cwd) | none — these are all optional and not needed to scaffold |
37
46
  | `--ai-tool` (set it to yourself: GitHub Copilot → `copilot`, Cursor → `cursor`, Claude Code → `claude-code`) | |
38
47
  | `--framework`, `--name`, `--templates`, `--categories` (infer from the request, or ask only if genuinely ambiguous) | |
48
+ | `--conflict-policy` (embedded mode only — see below) | |
49
+
50
+ `--conflict-policy` applies only in embedded mode and is ignored in new-project
51
+ mode. Leave it at `merge` (the default): it keeps the host's existing files, adds
52
+ Pega content inside marked blocks, and fills in missing JSON keys. Pass `override`
53
+ only when the user explicitly asks to replace their existing files.
39
54
 
40
55
  Server connection details (Pega server URL, app alias, OAuth client ID, MCP rule
41
56
  name/instance key) are never asked at scaffold time, in either mode — the scaffold
@@ -44,6 +59,31 @@ placeholder markers. An AI coding assistant gathers these from the user in chat
44
59
  and fills both files in automatically the first time a workflow needs them (see
45
60
  [Configure Your Pega Server](#configure-your-pega-server)).
46
61
 
62
+ ### After the command finishes
63
+
64
+ When `--ai-tool` is set, the CLI prints the project folder, the agent to continue
65
+ with, and its files. Files written during your current turn are not in your context
66
+ yet, so do not carry on from memory:
67
+
68
+ | Mode | Agent | Continue when |
69
+ | ----------- | ------------------------- | -------------------------------------------------------------------------------------------------------------- |
70
+ | Embedded | **Embedded Flow Expert** | Always |
71
+ | New project | **Implementation Expert** | Only when the user asked for more than a new project (e.g. "…with Chakra UI"); otherwise give plain next steps |
72
+
73
+ | AI tool | Project instructions | Agent file | What to do |
74
+ | ----------- | --------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
75
+ | Copilot | `.github/copilot-instructions.md` | `.github/agents/<agent>.agent.md` | Stop. Tell the user to choose the agent in the agent menu and say "continue" |
76
+ | Cursor | `.cursor/rules/pega-sdk.mdrules` | `.cursor/rules/agents/<agent>.mdrules` | Stop. Tell the user to `@`-mention the agent (e.g. `@embedded-flow-expert`) in chat |
77
+ | Claude Code | `AGENTS.md` | `.claude/agents/<agent>.md` | Read both files, then continue the user's original request in this chat. Suggest a new session for later requests, so the project instructions load from the start |
78
+
79
+ - **Say it in plain words**, for example: "Setup is done. To continue, choose
80
+ **Embedded Flow Expert** in the agent menu and say 'continue'." For Copilot and
81
+ Cursor, repeat the user's original request so they can paste it.
82
+ - **New project:** the AI tools find these files only at the top of the open
83
+ folder, so the user must open the printed project folder first, in every tool.
84
+ - **No agent printed** (a framework without AI files, or `--ai-tool none`): give
85
+ plain next steps only.
86
+
47
87
  ## Requirements
48
88
 
49
89
  - **Node.js** 20 or later
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@
4
4
  import * as p from "@clack/prompts";
5
5
  import pc from "picocolors";
6
6
  import path4 from "path";
7
+ import fs4 from "fs";
7
8
  import { createRequire } from "module";
8
9
 
9
10
  // src/scaffold.ts
@@ -206,6 +207,10 @@ var DSE_COMPONENTS = [
206
207
  importName: "AlertBanner",
207
208
  importPath: "./designSystemExtension/AlertBanner"
208
209
  },
210
+ {
211
+ importName: "AssignmentHeader",
212
+ importPath: "./designSystemExtension/AssignmentHeader"
213
+ },
209
214
  { importName: "Banner", importPath: "./designSystemExtension/Banner" },
210
215
  {
211
216
  importName: "CaseSummaryFields",
@@ -233,6 +238,7 @@ var DSE_COMPONENTS = [
233
238
  importName: "RichTextEditor",
234
239
  importPath: "./designSystemExtension/RichTextEditor"
235
240
  },
241
+ { importName: "Toast", importPath: "./designSystemExtension/Toast" },
236
242
  {
237
243
  importName: "WssQuickCreate",
238
244
  importPath: "./designSystemExtension/WssQuickCreate"
@@ -762,6 +768,15 @@ var AI_GEN_CONFIGS = {
762
768
  }
763
769
  }
764
770
  };
771
+ var GLOBAL_INSTRUCTIONS_PATHS = {
772
+ copilot: ".github/copilot-instructions.md",
773
+ cursor: ".cursor/rules/pega-sdk.mdrules",
774
+ "claude-code": "AGENTS.md"
775
+ };
776
+ function aiAgentFiles(aiTool, agent) {
777
+ const cfg = AI_GEN_CONFIGS[aiTool];
778
+ return { agentFile: `${cfg.agentsDir}/${agent}.${cfg.agentExt}`, globalFile: GLOBAL_INSTRUCTIONS_PATHS[aiTool] };
779
+ }
765
780
  function parseAiMeta(content) {
766
781
  const match = content.match(/^---\n([\s\S]*?)\n---\n\n?/);
767
782
  if (!match) return { meta: {}, body: content };
@@ -954,21 +969,21 @@ description: "${description}"
954
969
  const body = applyTokens(fs2.readFileSync(globalSrc, "utf-8"), tokens);
955
970
  if (aiTool === "copilot") {
956
971
  planned.push({
957
- destPath: path2.join(targetDir, ".github", "copilot-instructions.md"),
972
+ destPath: path2.join(targetDir, GLOBAL_INSTRUCTIONS_PATHS.copilot),
958
973
  frontmatter: "",
959
974
  body,
960
975
  kind: "md"
961
976
  });
962
977
  } else if (aiTool === "cursor") {
963
978
  planned.push({
964
- destPath: path2.join(targetDir, ".cursor", "rules", "pega-sdk.mdrules"),
979
+ destPath: path2.join(targetDir, GLOBAL_INSTRUCTIONS_PATHS.cursor),
965
980
  frontmatter: "---\ndescription: Core rules for working with Pega SDK components\nalwaysApply: true\n---\n\n",
966
981
  body,
967
982
  kind: "md"
968
983
  });
969
984
  } else if (aiTool === "claude-code") {
970
985
  planned.push({
971
- destPath: path2.join(targetDir, "AGENTS.md"),
986
+ destPath: path2.join(targetDir, GLOBAL_INSTRUCTIONS_PATHS["claude-code"]),
972
987
  frontmatter: "",
973
988
  body,
974
989
  kind: "md"
@@ -1122,32 +1137,23 @@ async function scaffoldEmbedded(choices, targetDir, onProgress) {
1122
1137
  `Wrote ${planned.length} file(s): ${counts.created} new, ${counts["block-replaced"]} updated, ${counts.appended} merged, ${counts.overwritten} replaced.`
1123
1138
  );
1124
1139
  report("Copying SDK packages\u2026");
1125
- const tgzFiles = fs2.readdirSync(sampleDir).filter((f) => f.endsWith(".tgz"));
1126
- for (const tgz of tgzFiles) {
1127
- const src = path2.join(sampleDir, tgz);
1128
- const dest = path2.join(targetDir, tgz);
1129
- fs2.copyFileSync(src, dest);
1140
+ const samplePkgJson = JSON.parse(fs2.readFileSync(path2.join(sampleDir, "package.json"), "utf-8"));
1141
+ const pegaDependencies = {};
1142
+ for (const pkgName of ["@pega/auth", "@pega/constellationjs", "@pega/sdk-react", "@pega/sdk-types"]) {
1143
+ const spec = samplePkgJson.dependencies?.[pkgName];
1144
+ if (!spec) continue;
1145
+ pegaDependencies[pkgName] = spec;
1146
+ if (spec.startsWith("file:")) {
1147
+ const tgz = spec.slice("file:".length);
1148
+ fs2.copyFileSync(path2.join(sampleDir, tgz), path2.join(targetDir, tgz));
1149
+ }
1130
1150
  }
1131
1151
  report("Adding SDK dependencies\u2026");
1132
1152
  const pkgJsonPath = path2.join(targetDir, "package.json");
1133
1153
  if (fs2.existsSync(pkgJsonPath)) {
1134
1154
  const pkgJson = JSON.parse(fs2.readFileSync(pkgJsonPath, "utf-8"));
1135
1155
  if (!pkgJson.dependencies) pkgJson.dependencies = {};
1136
- const TGZ_PACKAGE_MAP = {
1137
- "pega-auth": "@pega/auth",
1138
- "pega-constellationjs": "@pega/constellationjs",
1139
- "pega-sdk-react": "@pega/sdk-react",
1140
- "pega-sdk-types": "@pega/sdk-types"
1141
- };
1142
- for (const tgz of tgzFiles) {
1143
- const match = tgz.match(/^(pega-[\w-]+?)-\d/);
1144
- if (match) {
1145
- const pkgName = TGZ_PACKAGE_MAP[match[1]];
1146
- if (pkgName) {
1147
- pkgJson.dependencies[pkgName] = `file:${tgz}`;
1148
- }
1149
- }
1150
- }
1156
+ Object.assign(pkgJson.dependencies, pegaDependencies);
1151
1157
  fs2.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2) + "\n");
1152
1158
  }
1153
1159
  report("Creating SDK configuration\u2026");
@@ -1254,7 +1260,17 @@ do not need to pass --mode.
1254
1260
  about. GitHub Copilot -> copilot, Cursor -> cursor, Claude Code -> claude-code.
1255
1261
  Always pass it: it decides which agent config files get written, and a repo can
1256
1262
  contain another assistant's config left behind by someone else.
1257
- `.trim();
1263
+
1264
+ Users often ask in plain words ("add the service request form to my app when
1265
+ someone clicks Apply", "start a new Pega app") \u2014 judge by intent, not wording.
1266
+
1267
+ When it finishes, the CLI prints the agent to continue with and its files.
1268
+ Copilot / Cursor: stop. Tell the user, in plain words, to switch to that agent
1269
+ (Copilot: pick it in the agent menu; Cursor: @-mention it in chat), then
1270
+ repeat their original request so they can paste it.
1271
+ Claude Code: read the printed instructions and agent files, then continue the
1272
+ user's original request in this chat.
1273
+ New project: the user must open the printed project folder first.`.trim();
1258
1274
  var HELP_TEXT = `
1259
1275
  Usage: npx --yes @pega/sdk init [flags]
1260
1276
 
@@ -1423,6 +1439,14 @@ function resolveNonInteractiveEmbeddedChoices(args, cwd) {
1423
1439
  // src/index.ts
1424
1440
  var require2 = createRequire(import.meta.url);
1425
1441
  var { version: sdkVersion } = require2("../package.json");
1442
+ function printAgentFiles(projectDir, aiTool, agent, agentName) {
1443
+ if (!aiTool) return;
1444
+ const { agentFile, globalFile } = aiAgentFiles(aiTool, agent);
1445
+ if (!fs4.existsSync(path4.join(projectDir, agentFile)) || !fs4.existsSync(path4.join(projectDir, globalFile))) return;
1446
+ console.log(`Project folder: ${projectDir}`);
1447
+ console.log(`Agent: ${agentName} \u2014 ${agentFile}`);
1448
+ console.log(`Project instructions: ${globalFile}`);
1449
+ }
1426
1450
  async function runNonInteractive(cwd, flags) {
1427
1451
  try {
1428
1452
  const mode = flags.mode ?? (detectExistingProject(cwd) ? "embedded" : "new");
@@ -1438,11 +1462,13 @@ async function runNonInteractive(cwd, flags) {
1438
1462
  }
1439
1463
  await scaffoldEmbedded(choices, cwd, (message) => console.log(pc.dim(message)));
1440
1464
  console.log(pc.green("Embedded flow ready!"));
1465
+ printAgentFiles(cwd, choices.aiTool, "embedded-flow-expert", "Embedded Flow Expert");
1441
1466
  } else {
1442
1467
  const choices = resolveNonInteractiveUserChoices(flags);
1443
1468
  const targetDir = path4.resolve(cwd, choices.projectName);
1444
1469
  await scaffold(choices, targetDir, (message) => console.log(pc.dim(message)));
1445
1470
  console.log(pc.green("Project scaffolded successfully!"));
1471
+ printAgentFiles(targetDir, choices.aiTool, "implementation-expert", "Implementation Expert");
1446
1472
  }
1447
1473
  } catch (err) {
1448
1474
  console.error(pc.red(err instanceof CliValidationError || err instanceof Error ? err.message : String(err)));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pega/sdk",
3
- "version": "0.0.14",
4
- "description": "Scaffold a Pega SDK application project",
3
+ "version": "0.0.15",
4
+ "description": "CLI to scaffold Pega SDK apps (React, Angular, Web Components) or embed Pega cases and forms into an existing app, with design-matched components and AI agent setup for Copilot, Cursor, and Claude Code",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "sdk": "./dist/index.js"
@@ -39,7 +39,46 @@
39
39
  "sdk",
40
40
  "scaffold",
41
41
  "cli",
42
- "create-app"
42
+ "create-app",
43
+ "embed",
44
+ "embedded",
45
+ "mashup",
46
+ "constellation",
47
+ "pega-infinity",
48
+ "case",
49
+ "form",
50
+ "forms",
51
+ "workflow",
52
+ "ui",
53
+ "components",
54
+ "design-system",
55
+ "pega-sdk",
56
+ "pega-constellation",
57
+ "constellation-sdk",
58
+ "pega-mashup",
59
+ "pega-react-sdk",
60
+ "pega-angular-sdk",
61
+ "web-embed",
62
+ "embed-form",
63
+ "embed-case",
64
+ "case-management",
65
+ "workflow-automation",
66
+ "low-code",
67
+ "react",
68
+ "angular",
69
+ "web-components",
70
+ "react-native",
71
+ "typescript",
72
+ "vite",
73
+ "starter",
74
+ "boilerplate",
75
+ "template",
76
+ "ai-agent",
77
+ "copilot",
78
+ "cursor",
79
+ "claude-code",
80
+ "mcp",
81
+ "oauth"
43
82
  ],
44
83
  "license": "Apache-2.0"
45
84
  }
@@ -19,13 +19,12 @@
19
19
  "tsConfig": "tsconfig.json",
20
20
  "assets": ["src/assets", "src/sdk-config.json"],
21
21
  "styles": ["src/styles.css"],
22
- "scripts": ["../../node_modules/@pega/constellationjs/dist/constellation-core-web.js"]
22
+ "scripts": []
23
23
  }
24
24
  },
25
25
  "serve": {
26
26
  "builder": "@angular-devkit/build-angular:dev-server",
27
27
  "options": {
28
- "buildTarget": "angular-sdk-reference:build",
29
28
  "port": 3501
30
29
  }
31
30
  }
@@ -0,0 +1,23 @@
1
+ 'use strict';
2
+
3
+ const CopyWebpackPlugin = require('copy-webpack-plugin');
4
+
5
+ // comment this code out, if you have an "ENOENT: no such file or directory" build error and re-build
6
+ // to see the real Angular errors, then uncomment onces fixed
7
+ module.exports = (config) => {
8
+ config.plugins.push(
9
+ new CopyWebpackPlugin({
10
+ patterns: [
11
+ {
12
+ from: '../../node_modules/@pega/auth/lib/oauth-client/authDone.html',
13
+ to: './auth.html',
14
+ },
15
+ {
16
+ from: '../../node_modules/@pega/auth/lib/oauth-client/authDone.js',
17
+ to: './',
18
+ },
19
+ ],
20
+ }),
21
+ );
22
+ return config;
23
+ };
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>Pega SDK Angular Reference</title>
6
+ <base href="/" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
8
+ </head>
9
+ <body>
10
+ <app-root></app-root>
11
+ </body>
12
+ </html>
@@ -17,7 +17,6 @@
17
17
  "@angular/platform-browser": "^21.2.0",
18
18
  "@angular/platform-browser-dynamic": "^21.2.0",
19
19
  "@angular/router": "^21.2.0",
20
- "@pega/constellationjs": "file:pega-constellationjs-0.26.3-local.tgz",
21
20
  "@pega/sdk-angular": "^0.1.0",
22
21
  "rxjs": "~7.8.2",
23
22
  "tslib": "^2.8.1",
@@ -1,72 +1,25 @@
1
- /**
2
- * Angular Mashup sample — demonstrates @pega/sdk-core + @pega/sdk-angular
3
- * in embedded/mashup mode using PegaRuntimeService.
4
- *
5
- * Flow:
6
- * 1. PegaRuntimeService.initialize() handles auth + bootstrap
7
- * 2. Subscribe to state$ for reactive isReady/isLoading/error
8
- * 3. Show "Create Case" button
9
- * 4. On click → PCore.getMashupApi().createCase()
10
- * 5. PConnectRendererComponent renders the case form tree
11
- */
12
-
13
- import { ChangeDetectorRef, Component, NgZone, OnInit, OnDestroy } from '@angular/core';
1
+ import { Component, OnInit } from '@angular/core';
14
2
  import { CommonModule } from '@angular/common';
15
- import { Subscription } from 'rxjs';
16
- import { PegaRuntimeService, PConnectBridgeComponent, type RuntimeState } from '@pega/sdk-angular';
17
- import { registerSampleAngularComponents } from '../components/component-map';
18
- import { getSdkConfig } from '@pega/auth/lib/sdk-auth-manager';
19
- import { compareSdkPCoreVersions } from '../helpers/versionHelpers';
20
3
 
21
4
  @Component({
22
5
  selector: 'app-root',
23
6
  standalone: true,
24
- imports: [CommonModule, PConnectBridgeComponent],
7
+ imports: [CommonModule],
25
8
  template: `
26
- <!-- Loading state -->
27
- <div *ngIf="!isPegaReady" class="loading-container">
28
- <span class="loading-text">
29
- {{ errorMessage ? errorMessage : 'Authenticating and loading Pega...' }}
30
- </span>
9
+ <div *ngIf="!isReady" class="loading-container">
10
+ <span class="loading-text">Authenticating and loading Pega...</span>
31
11
  </div>
32
-
33
- <!-- Main UI -->
34
- <div *ngIf="isPegaReady" id="pega-root">
35
- <!-- Header -->
12
+ <div *ngIf="isReady" id="pega-root">
36
13
  <div class="header">
37
- <span class="header-title">Pega SDK — Angular Mashup Sample</span>
38
- <button type="button" class="btn-logout" (click)="logout()">Logout</button>
14
+ <span class="header-title">Pega SDK — Angular Reference</span>
39
15
  </div>
40
-
41
- <div class="main-content">
42
- <!-- Create Case button -->
43
- <div *ngIf="!showForm" class="create-case-section">
44
- <h2>Ready to go</h2>
45
- <p class="subtitle">Click below to create a new case and see the Pega form components in action.</p>
46
- <button type="button" class="btn-create" (click)="handleCreateCase()">Create Case</button>
47
- </div>
48
-
49
- <!-- Pega form area -->
50
- <div class="form-container">
51
- <div *ngIf="loading" class="loading-form">Loading case form...</div>
52
- <pconnect-bridge *ngIf="!loading && rootPConnect" [getPConnect]="rootPConnectGetter!"></pconnect-bridge>
53
- </div>
16
+ <div class="content">
17
+ <p>Pega SDK Angular app is ready. Implement your components here.</p>
54
18
  </div>
55
19
  </div>
56
20
  `,
57
21
  styles: [
58
22
  `
59
- .loading-container {
60
- display: flex;
61
- justify-content: center;
62
- align-items: center;
63
- height: 100vh;
64
- font-family: system-ui, sans-serif;
65
- }
66
- .loading-text {
67
- color: #64748b;
68
- font-size: 1rem;
69
- }
70
23
  .header {
71
24
  padding: 1rem 1.5rem;
72
25
  background: #1e293b;
@@ -78,194 +31,24 @@ import { compareSdkPCoreVersions } from '../helpers/versionHelpers';
78
31
  .header-title {
79
32
  font-weight: 600;
80
33
  }
81
- .btn-logout {
82
- background: transparent;
83
- border: 1px solid #64748b;
84
- color: #94a3b8;
85
- padding: 0.375rem 0.75rem;
86
- border-radius: 0.375rem;
87
- cursor: pointer;
88
- font-size: 0.8125rem;
89
- }
90
- .main-content {
34
+ .content {
91
35
  max-width: 720px;
92
36
  margin: 2rem auto;
93
37
  padding: 0 1.5rem;
94
- font-family: system-ui, sans-serif;
95
- }
96
- .create-case-section {
97
- text-align: center;
98
- margin-bottom: 2rem;
99
- }
100
- .create-case-section h2 {
101
- font-size: 1.5rem;
102
- font-weight: 600;
103
- margin-bottom: 0.75rem;
104
- }
105
- .subtitle {
106
- color: #64748b;
107
- margin-bottom: 1.5rem;
108
- }
109
- .btn-create {
110
- background: #2563eb;
111
- color: #fff;
112
- border: none;
113
- padding: 0.625rem 1.5rem;
114
- border-radius: 0.375rem;
115
- font-size: 0.9375rem;
116
- font-weight: 500;
117
- cursor: pointer;
118
- }
119
- .form-container {
120
- background: #fff;
121
- border: 1px solid #e2e8f0;
122
- border-radius: 0.75rem;
123
- padding: 1.5rem;
124
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
125
- }
126
- .loading-form {
127
- text-align: center;
128
- padding: 2rem;
129
- color: #64748b;
130
38
  }
131
39
  `,
132
40
  ],
133
41
  })
134
- export class AppComponent implements OnInit, OnDestroy {
135
- isPegaReady = false;
136
- rootPConnect: typeof PConnect | null = null;
137
- rootPConnectGetter: (() => typeof PConnect) | null = null;
138
- showForm = false;
139
- loading = false;
140
- errorMessage: string | undefined;
141
-
142
- private runtime = new PegaRuntimeService();
143
- private stateSub: Subscription | undefined;
144
- private cancelSubId = 'angularMashup-cancel';
145
- private doneSubId = 'angularMashup-assignmentDone';
146
-
147
- constructor(
148
- private ngZone: NgZone,
149
- private cdr: ChangeDetectorRef,
150
- ) {}
42
+ export class AppComponent implements OnInit {
43
+ isReady = false;
151
44
 
152
- ngOnInit(): void {
153
- this.stateSub = this.runtime.state$.subscribe((state: RuntimeState) => {
154
- console.log('Runtime state update:', state);
155
- this.ngZone.run(() => {
156
- this.isPegaReady = state.isReady;
157
- this.errorMessage = state.error;
158
-
159
- if (state.isReady && state.bootstrapResult) {
160
- const rootProps = state.bootstrapResult.rootProps as Record<string, unknown> | undefined;
161
- const getPConnect = rootProps?.['getPConnect'] as (() => typeof PConnect) | undefined;
162
- this.rootPConnect = getPConnect?.() ?? null;
163
- this.rootPConnectGetter = getPConnect ?? null;
164
- this.subscribeToPubSub();
165
- }
166
-
167
- this.cdr.detectChanges();
168
- });
169
- });
170
-
171
- this.bootstrap();
172
- }
173
-
174
- ngOnDestroy(): void {
175
- this.stateSub?.unsubscribe();
176
-
177
- if (this.isPegaReady) {
178
- PCore.getPubSubUtils().unsubscribe(PCore.getConstants().PUB_SUB_EVENTS.EVENT_CANCEL, this.cancelSubId);
179
- PCore.getPubSubUtils().unsubscribe(
180
- PCore.getConstants().PUB_SUB_EVENTS.CASE_EVENTS.END_OF_ASSIGNMENT_PROCESSING,
181
- this.doneSubId,
182
- );
183
- }
184
- }
185
-
186
- async bootstrap(): Promise<void> {
187
- const sdkConfig = await getSdkConfig();
188
- const config = sdkConfig as Record<string, Record<string, unknown>>;
189
-
190
- await this.runtime.initialize(
191
- {
192
- serverConfig: {
193
- infinityRestServerUrl: config['serverConfig']['infinityRestServerUrl'] as string,
194
- appAlias: config['serverConfig']['appAlias'] as string,
195
- },
196
- authConfig: {
197
- clientId: (config['authConfig']['mashupClientId'] ?? '') as string,
198
- authorizeUri: (config['authConfig']['authorizeUri'] ?? '') as string,
199
- tokenUri: (config['authConfig']['tokenUri'] ?? '') as string,
200
- revokeUri: (config['authConfig']['revokeUri'] ?? '') as string,
201
- redirectUri: (config['authConfig']['redirectUri'] ?? '') as string,
202
- },
203
- },
204
- 'pega-root',
205
- {
206
- onPCoreReady: () => {
207
- console.log('PCore is ready, running onPCoreReady callback');
208
- // Register component creator so PCore uses our bridge
209
- PCore.registerComponentCreator((c11nEnv: unknown) => c11nEnv);
210
- registerSampleAngularComponents();
211
- compareSdkPCoreVersions();
212
-
213
- // Initialize container session gates (required by ViewContainer/FlowContainer)
214
- sessionStorage.setItem('hasViewContainer', 'false');
215
- sessionStorage.setItem('okToInitFlowContainer', 'true');
216
- },
217
- },
218
- );
219
- }
220
-
221
- private subscribeToPubSub(): void {
222
- PCore.getPubSubUtils().subscribe(
223
- PCore.getConstants().PUB_SUB_EVENTS.EVENT_CANCEL,
224
- () => {
225
- this.ngZone.run(() => {
226
- this.showForm = false;
227
- });
228
- },
229
- this.cancelSubId,
230
- );
231
-
232
- PCore.getPubSubUtils().subscribe(
233
- PCore.getConstants().PUB_SUB_EVENTS.CASE_EVENTS.END_OF_ASSIGNMENT_PROCESSING,
234
- () => {
235
- this.ngZone.run(() => {
236
- this.showForm = false;
237
- });
238
- },
239
- this.doneSubId,
240
- );
241
- }
242
-
243
- async handleCreateCase(): Promise<void> {
244
- this.loading = true;
245
- this.showForm = true;
45
+ constructor() {}
246
46
 
47
+ async ngOnInit() {
247
48
  try {
248
- const sdkConfig = await getSdkConfig();
249
- const mashupCaseType = (sdkConfig as Record<string, Record<string, unknown>>).serverConfig[
250
- 'appMashupCaseType'
251
- ] as string;
252
-
253
- await PCore.getMashupApi().createCase(mashupCaseType, PCore.getConstants().APP.APP, {
254
- pageName: 'pyEmbedAssignment',
255
- startingFields: {},
256
- });
49
+ this.isReady = true;
257
50
  } catch (err) {
258
- console.error('Error creating case:', err);
259
- this.showForm = false;
260
- } finally {
261
- this.ngZone.run(() => {
262
- this.loading = false;
263
- this.cdr.detectChanges();
264
- });
51
+ console.error('Failed to initialize Pega SDK:', err);
265
52
  }
266
53
  }
267
-
268
- logout(): void {
269
- this.runtime.authClient.logout();
270
- }
271
54
  }