@salesforce/afv-skills 1.14.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (365) hide show
  1. package/package.json +1 -1
  2. package/skills/activating-datacloud/SKILL.md +0 -1
  3. package/skills/analyzing-omnistudio-dependencies/SKILL.md +0 -1
  4. package/skills/applying-slds/SKILL.md +322 -0
  5. package/skills/applying-slds/checklists.md +83 -0
  6. package/skills/applying-slds/examples.md +283 -0
  7. package/skills/applying-slds/guidance/README.md +83 -0
  8. package/skills/applying-slds/guidance/blueprints-index.md +213 -0
  9. package/skills/applying-slds/guidance/icons-guidance.md +186 -0
  10. package/skills/applying-slds/guidance/overviews/borders.md +236 -0
  11. package/skills/applying-slds/guidance/overviews/color.md +266 -0
  12. package/skills/applying-slds/guidance/overviews/display-density.md +366 -0
  13. package/skills/applying-slds/guidance/overviews/icons.md +240 -0
  14. package/skills/applying-slds/guidance/overviews/illustrations.md +235 -0
  15. package/skills/applying-slds/guidance/overviews/shadows.md +176 -0
  16. package/skills/applying-slds/guidance/overviews/spacing.md +216 -0
  17. package/skills/applying-slds/guidance/overviews/typography.md +323 -0
  18. package/skills/applying-slds/guidance/overviews/utilities.md +542 -0
  19. package/skills/applying-slds/guidance/slds-development-guide.md +288 -0
  20. package/skills/applying-slds/guidance/styling-hooks/borders.md +202 -0
  21. package/skills/applying-slds/guidance/styling-hooks/color/expressive-palette-hooks.md +153 -0
  22. package/skills/applying-slds/guidance/styling-hooks/color/index.md +171 -0
  23. package/skills/applying-slds/guidance/styling-hooks/color/semantic/accent-hooks.md +204 -0
  24. package/skills/applying-slds/guidance/styling-hooks/color/semantic/feedback-hooks.md +768 -0
  25. package/skills/applying-slds/guidance/styling-hooks/color/semantic/surface-hooks.md +337 -0
  26. package/skills/applying-slds/guidance/styling-hooks/color/system-hooks.md +132 -0
  27. package/skills/applying-slds/guidance/styling-hooks/index.md +327 -0
  28. package/skills/applying-slds/guidance/styling-hooks/shadows.md +238 -0
  29. package/skills/applying-slds/guidance/styling-hooks/spacing.md +254 -0
  30. package/skills/applying-slds/guidance/styling-hooks/typography.md +448 -0
  31. package/skills/applying-slds/guidance/utilities/alignment.md +119 -0
  32. package/skills/applying-slds/guidance/utilities/borders.md +131 -0
  33. package/skills/applying-slds/guidance/utilities/box.md +125 -0
  34. package/skills/applying-slds/guidance/utilities/color.md +165 -0
  35. package/skills/applying-slds/guidance/utilities/dark-mode.md +111 -0
  36. package/skills/applying-slds/guidance/utilities/description-list.md +168 -0
  37. package/skills/applying-slds/guidance/utilities/floats.md +117 -0
  38. package/skills/applying-slds/guidance/utilities/grid.md +264 -0
  39. package/skills/applying-slds/guidance/utilities/horizontal-list.md +110 -0
  40. package/skills/applying-slds/guidance/utilities/hyphenation.md +84 -0
  41. package/skills/applying-slds/guidance/utilities/index.md +205 -0
  42. package/skills/applying-slds/guidance/utilities/interactions.md +89 -0
  43. package/skills/applying-slds/guidance/utilities/layout.md +109 -0
  44. package/skills/applying-slds/guidance/utilities/line-clamp.md +131 -0
  45. package/skills/applying-slds/guidance/utilities/margin.md +155 -0
  46. package/skills/applying-slds/guidance/utilities/media-object.md +161 -0
  47. package/skills/applying-slds/guidance/utilities/name-value-list.md +152 -0
  48. package/skills/applying-slds/guidance/utilities/padding.md +155 -0
  49. package/skills/applying-slds/guidance/utilities/position.md +177 -0
  50. package/skills/applying-slds/guidance/utilities/print.md +114 -0
  51. package/skills/applying-slds/guidance/utilities/scrollable.md +126 -0
  52. package/skills/applying-slds/guidance/utilities/sizing.md +190 -0
  53. package/skills/applying-slds/guidance/utilities/themes.md +121 -0
  54. package/skills/applying-slds/guidance/utilities/truncate.md +127 -0
  55. package/skills/applying-slds/guidance/utilities/typography.md +166 -0
  56. package/skills/applying-slds/guidance/utilities/vertical-list.md +166 -0
  57. package/skills/applying-slds/guidance/utilities/visibility.md +228 -0
  58. package/skills/applying-slds/metadata/README.md +84 -0
  59. package/skills/applying-slds/metadata/blueprints/components/accordion.yaml +304 -0
  60. package/skills/applying-slds/metadata/blueprints/components/activity-timeline.yaml +92 -0
  61. package/skills/applying-slds/metadata/blueprints/components/alert.yaml +103 -0
  62. package/skills/applying-slds/metadata/blueprints/components/app-launcher.yaml +94 -0
  63. package/skills/applying-slds/metadata/blueprints/components/avatar-group.yaml +81 -0
  64. package/skills/applying-slds/metadata/blueprints/components/avatar.yaml +97 -0
  65. package/skills/applying-slds/metadata/blueprints/components/badges.yaml +102 -0
  66. package/skills/applying-slds/metadata/blueprints/components/brand-band.yaml +198 -0
  67. package/skills/applying-slds/metadata/blueprints/components/breadcrumbs.yaml +95 -0
  68. package/skills/applying-slds/metadata/blueprints/components/builder-header.yaml +192 -0
  69. package/skills/applying-slds/metadata/blueprints/components/button-groups.yaml +82 -0
  70. package/skills/applying-slds/metadata/blueprints/components/button-icons.yaml +295 -0
  71. package/skills/applying-slds/metadata/blueprints/components/buttons.yaml +230 -0
  72. package/skills/applying-slds/metadata/blueprints/components/cards.yaml +124 -0
  73. package/skills/applying-slds/metadata/blueprints/components/carousel.yaml +140 -0
  74. package/skills/applying-slds/metadata/blueprints/components/chat.yaml +179 -0
  75. package/skills/applying-slds/metadata/blueprints/components/checkbox-button-group.yaml +192 -0
  76. package/skills/applying-slds/metadata/blueprints/components/checkbox-button.yaml +204 -0
  77. package/skills/applying-slds/metadata/blueprints/components/checkbox-toggle.yaml +177 -0
  78. package/skills/applying-slds/metadata/blueprints/components/checkbox.yaml +108 -0
  79. package/skills/applying-slds/metadata/blueprints/components/color-picker.yaml +172 -0
  80. package/skills/applying-slds/metadata/blueprints/components/combobox.yaml +136 -0
  81. package/skills/applying-slds/metadata/blueprints/components/counter.yaml +147 -0
  82. package/skills/applying-slds/metadata/blueprints/components/data-tables.yaml +157 -0
  83. package/skills/applying-slds/metadata/blueprints/components/datepickers.yaml +130 -0
  84. package/skills/applying-slds/metadata/blueprints/components/datetime-picker.yaml +155 -0
  85. package/skills/applying-slds/metadata/blueprints/components/docked-composer.yaml +201 -0
  86. package/skills/applying-slds/metadata/blueprints/components/docked-form-footer.yaml +161 -0
  87. package/skills/applying-slds/metadata/blueprints/components/docked-utility-bar.yaml +175 -0
  88. package/skills/applying-slds/metadata/blueprints/components/drop-zone.yaml +115 -0
  89. package/skills/applying-slds/metadata/blueprints/components/dueling-picklist.yaml +196 -0
  90. package/skills/applying-slds/metadata/blueprints/components/dynamic-icons.yaml +128 -0
  91. package/skills/applying-slds/metadata/blueprints/components/dynamic-menu.yaml +141 -0
  92. package/skills/applying-slds/metadata/blueprints/components/expandable-section.yaml +115 -0
  93. package/skills/applying-slds/metadata/blueprints/components/expression.yaml +143 -0
  94. package/skills/applying-slds/metadata/blueprints/components/feeds.yaml +125 -0
  95. package/skills/applying-slds/metadata/blueprints/components/file-selector.yaml +154 -0
  96. package/skills/applying-slds/metadata/blueprints/components/files.yaml +119 -0
  97. package/skills/applying-slds/metadata/blueprints/components/form-element.yaml +145 -0
  98. package/skills/applying-slds/metadata/blueprints/components/global-header.yaml +120 -0
  99. package/skills/applying-slds/metadata/blueprints/components/global-navigation.yaml +100 -0
  100. package/skills/applying-slds/metadata/blueprints/components/icons.yaml +138 -0
  101. package/skills/applying-slds/metadata/blueprints/components/illustration.yaml +205 -0
  102. package/skills/applying-slds/metadata/blueprints/components/input.yaml +151 -0
  103. package/skills/applying-slds/metadata/blueprints/components/list-builder.yaml +127 -0
  104. package/skills/applying-slds/metadata/blueprints/components/lookups.yaml +132 -0
  105. package/skills/applying-slds/metadata/blueprints/components/map.yaml +118 -0
  106. package/skills/applying-slds/metadata/blueprints/components/menus.yaml +134 -0
  107. package/skills/applying-slds/metadata/blueprints/components/modals.yaml +152 -0
  108. package/skills/applying-slds/metadata/blueprints/components/notifications.yaml +88 -0
  109. package/skills/applying-slds/metadata/blueprints/components/page-headers.yaml +135 -0
  110. package/skills/applying-slds/metadata/blueprints/components/panels.yaml +149 -0
  111. package/skills/applying-slds/metadata/blueprints/components/path.yaml +154 -0
  112. package/skills/applying-slds/metadata/blueprints/components/picklist.yaml +125 -0
  113. package/skills/applying-slds/metadata/blueprints/components/pills.yaml +154 -0
  114. package/skills/applying-slds/metadata/blueprints/components/popovers.yaml +120 -0
  115. package/skills/applying-slds/metadata/blueprints/components/progress-bar.yaml +110 -0
  116. package/skills/applying-slds/metadata/blueprints/components/progress-indicator.yaml +133 -0
  117. package/skills/applying-slds/metadata/blueprints/components/progress-ring.yaml +102 -0
  118. package/skills/applying-slds/metadata/blueprints/components/prompt.yaml +126 -0
  119. package/skills/applying-slds/metadata/blueprints/components/publishers.yaml +178 -0
  120. package/skills/applying-slds/metadata/blueprints/components/radio-button-group.yaml +172 -0
  121. package/skills/applying-slds/metadata/blueprints/components/radio-group.yaml +112 -0
  122. package/skills/applying-slds/metadata/blueprints/components/rich-text-editor.yaml +135 -0
  123. package/skills/applying-slds/metadata/blueprints/components/scoped-notifications.yaml +188 -0
  124. package/skills/applying-slds/metadata/blueprints/components/scoped-tabs.yaml +97 -0
  125. package/skills/applying-slds/metadata/blueprints/components/select.yaml +127 -0
  126. package/skills/applying-slds/metadata/blueprints/components/setup-assistant.yaml +152 -0
  127. package/skills/applying-slds/metadata/blueprints/components/slider.yaml +111 -0
  128. package/skills/applying-slds/metadata/blueprints/components/spinners.yaml +135 -0
  129. package/skills/applying-slds/metadata/blueprints/components/split-view.yaml +112 -0
  130. package/skills/applying-slds/metadata/blueprints/components/summary-detail.yaml +103 -0
  131. package/skills/applying-slds/metadata/blueprints/components/tabs.yaml +138 -0
  132. package/skills/applying-slds/metadata/blueprints/components/textarea.yaml +116 -0
  133. package/skills/applying-slds/metadata/blueprints/components/tiles.yaml +108 -0
  134. package/skills/applying-slds/metadata/blueprints/components/timepicker.yaml +111 -0
  135. package/skills/applying-slds/metadata/blueprints/components/toast.yaml +154 -0
  136. package/skills/applying-slds/metadata/blueprints/components/tooltips.yaml +107 -0
  137. package/skills/applying-slds/metadata/blueprints/components/tree-grid.yaml +116 -0
  138. package/skills/applying-slds/metadata/blueprints/components/trees.yaml +116 -0
  139. package/skills/applying-slds/metadata/blueprints/components/trial-bar.yaml +112 -0
  140. package/skills/applying-slds/metadata/blueprints/components/vertical-navigation.yaml +130 -0
  141. package/skills/applying-slds/metadata/blueprints/components/vertical-tabs.yaml +140 -0
  142. package/skills/applying-slds/metadata/blueprints/components/visual-picker.yaml +150 -0
  143. package/skills/applying-slds/metadata/blueprints/components/welcome-mat.yaml +136 -0
  144. package/skills/applying-slds/metadata/hooks-index.json +6272 -0
  145. package/skills/applying-slds/metadata/icon-metadata.json +38466 -0
  146. package/skills/applying-slds/metadata/utilities-index.json +21912 -0
  147. package/skills/applying-slds/references/component-selection.md +112 -0
  148. package/skills/applying-slds/references/icons-decision-guide.md +124 -0
  149. package/skills/applying-slds/references/styling-decision-guide.md +228 -0
  150. package/skills/applying-slds/references/utilities-quick-ref.md +125 -0
  151. package/skills/applying-slds/scripts/search-blueprints.cjs +117 -0
  152. package/skills/applying-slds/scripts/search-hooks.cjs +139 -0
  153. package/skills/applying-slds/scripts/search-icons.cjs +174 -0
  154. package/skills/applying-slds/scripts/search-utilities.cjs +161 -0
  155. package/skills/building-mobile-apps/SKILL.md +0 -1
  156. package/skills/building-omnistudio-callable-apex/SKILL.md +0 -1
  157. package/skills/building-omnistudio-datamapper/SKILL.md +0 -1
  158. package/skills/building-omnistudio-flexcard/SKILL.md +0 -1
  159. package/skills/building-omnistudio-integration-procedure/SKILL.md +0 -1
  160. package/skills/building-omnistudio-omniscript/SKILL.md +0 -1
  161. package/skills/building-sf-integrations/SKILL.md +0 -1
  162. package/skills/configuring-connected-apps/SKILL.md +0 -1
  163. package/skills/connecting-datacloud/SKILL.md +0 -1
  164. package/skills/creating-b2b-commerce-store/SKILL.md +0 -1
  165. package/skills/debugging-apex-logs/SKILL.md +0 -1
  166. package/skills/deploying-metadata/SKILL.md +0 -1
  167. package/skills/deploying-omnistudio-datapacks/SKILL.md +0 -1
  168. package/skills/developing-agentforce/SKILL.md +0 -1
  169. package/skills/fetching-salesforce-docs/SKILL.md +0 -1
  170. package/skills/generating-custom-lightning-type/SKILL.md +17 -39
  171. package/skills/generating-custom-lightning-type/assets/primitive-types-and-constraints.md +41 -0
  172. package/skills/generating-custom-lightning-type/references/widget-rendition.md +124 -0
  173. package/skills/generating-lwc-components/SKILL.md +0 -1
  174. package/skills/generating-mermaid-diagrams/SKILL.md +0 -1
  175. package/skills/generating-visual-diagrams/SKILL.md +0 -1
  176. package/skills/handling-sf-data/SKILL.md +0 -1
  177. package/skills/harmonizing-datacloud/SKILL.md +0 -1
  178. package/skills/integrating-b2b-commerce-open-code-components/SKILL.md +0 -1
  179. package/skills/investigating-agentforce-architecture/README.md +156 -0
  180. package/skills/investigating-agentforce-architecture/SKILL.md +230 -0
  181. package/skills/investigating-agentforce-architecture/assets/cli/describe_sobject.yaml +16 -0
  182. package/skills/investigating-agentforce-architecture/assets/cli/describe_tooling_sobject.yaml +17 -0
  183. package/skills/investigating-agentforce-architecture/assets/cli/list_metadata_genaiprompttemplate.yaml +17 -0
  184. package/skills/investigating-agentforce-architecture/assets/cli/org_display.yaml +15 -0
  185. package/skills/investigating-agentforce-architecture/assets/cli/retrieve_genai_plugin.yaml +18 -0
  186. package/skills/investigating-agentforce-architecture/assets/cli/show_access_token.yaml +27 -0
  187. package/skills/investigating-agentforce-architecture/assets/mermaid/action_tree.mmd +20 -0
  188. package/skills/investigating-agentforce-architecture/assets/mermaid/data_flow.mmd +19 -0
  189. package/skills/investigating-agentforce-architecture/assets/mermaid/dependency_graph.mmd +19 -0
  190. package/skills/investigating-agentforce-architecture/assets/mermaid/invocation_sequence.mmd +20 -0
  191. package/skills/investigating-agentforce-architecture/assets/mermaid/planner_state.mmd +18 -0
  192. package/skills/investigating-agentforce-architecture/assets/soql/apex_class_bodies_by_ids.soql +3 -0
  193. package/skills/investigating-agentforce-architecture/assets/soql/apex_class_bodies_by_names.soql +3 -0
  194. package/skills/investigating-agentforce-architecture/assets/soql/bot_definition_details.soql +3 -0
  195. package/skills/investigating-agentforce-architecture/assets/soql/bot_version_lookup.soql +4 -0
  196. package/skills/investigating-agentforce-architecture/assets/soql/flow_definition_by_ids.soql +3 -0
  197. package/skills/investigating-agentforce-architecture/assets/soql/flow_definition_ids_by_names.soql +3 -0
  198. package/skills/investigating-agentforce-architecture/assets/soql/flow_definition_view_by_durable_ids.soql +4 -0
  199. package/skills/investigating-agentforce-architecture/assets/soql/flow_metadata_by_id.soql +3 -0
  200. package/skills/investigating-agentforce-architecture/assets/soql/functions_by_plugins.soql +5 -0
  201. package/skills/investigating-agentforce-architecture/assets/soql/planner_attrs_by_parent_ids.soql +3 -0
  202. package/skills/investigating-agentforce-architecture/assets/soql/planner_bundle_functions.soql +3 -0
  203. package/skills/investigating-agentforce-architecture/assets/soql/planner_definition_by_agent_chain.soql +3 -0
  204. package/skills/investigating-agentforce-architecture/assets/soql/plugin_functions_by_plugin_ids.soql +3 -0
  205. package/skills/investigating-agentforce-architecture/assets/soql/plugin_instructions_by_plugin_ids.soql +3 -0
  206. package/skills/investigating-agentforce-architecture/assets/soql/plugins_by_planner.soql +4 -0
  207. package/skills/investigating-agentforce-architecture/references/architecture_sections.md +243 -0
  208. package/skills/investigating-agentforce-architecture/references/contract.json +244 -0
  209. package/skills/investigating-agentforce-architecture/references/soql_fields.md +512 -0
  210. package/skills/investigating-agentforce-architecture/scripts/_shared/__init__.py +1 -0
  211. package/skills/investigating-agentforce-architecture/scripts/_shared/fs_guard.py +329 -0
  212. package/skills/investigating-agentforce-architecture/scripts/_shared/paths.py +110 -0
  213. package/skills/investigating-agentforce-architecture/scripts/_shared/runtime.py +59 -0
  214. package/skills/investigating-agentforce-architecture/scripts/_shared/sql.py +10 -0
  215. package/skills/investigating-agentforce-architecture/scripts/cache_check.py +234 -0
  216. package/skills/investigating-agentforce-architecture/scripts/config.py +131 -0
  217. package/skills/investigating-agentforce-architecture/scripts/fetch_soql.py +689 -0
  218. package/skills/investigating-agentforce-architecture/scripts/finalize.py +295 -0
  219. package/skills/investigating-agentforce-architecture/scripts/main.py +2835 -0
  220. package/skills/investigating-agentforce-architecture/scripts/metadata_listing.py +265 -0
  221. package/skills/investigating-agentforce-architecture/scripts/parallel_retrieve.py +69 -0
  222. package/skills/investigating-agentforce-architecture/scripts/parse_bundle.py +215 -0
  223. package/skills/investigating-agentforce-architecture/scripts/parse_wave.py +845 -0
  224. package/skills/investigating-agentforce-architecture/scripts/probe_channels.py +302 -0
  225. package/skills/investigating-agentforce-architecture/scripts/render_architecture.py +1043 -0
  226. package/skills/investigating-agentforce-architecture/scripts/resolve_bot.py +255 -0
  227. package/skills/investigating-agentforce-architecture/scripts/resolve_invocation_target.py +130 -0
  228. package/skills/investigating-agentforce-architecture/scripts/rest_client.py +763 -0
  229. package/skills/investigating-agentforce-architecture/scripts/retrieve_planner.py +13 -0
  230. package/skills/investigating-agentforce-architecture/scripts/sf_cli.py +242 -0
  231. package/skills/investigating-agentforce-architecture/scripts/soql_loader.py +253 -0
  232. package/skills/investigating-agentforce-architecture/scripts/summarize_tree.py +143 -0
  233. package/skills/investigating-agentforce-architecture/scripts/tests/__init__.py +0 -0
  234. package/skills/investigating-agentforce-architecture/scripts/tests/_bootstrap.py +23 -0
  235. package/skills/investigating-agentforce-architecture/scripts/tests/fixtures/__init__.py +0 -0
  236. package/skills/investigating-agentforce-architecture/scripts/tests/fixtures/genai_payloads.py +400 -0
  237. package/skills/investigating-agentforce-architecture/scripts/tests/test_cache_check.py +307 -0
  238. package/skills/investigating-agentforce-architecture/scripts/tests/test_cache_check_main.py +283 -0
  239. package/skills/investigating-agentforce-architecture/scripts/tests/test_config.py +115 -0
  240. package/skills/investigating-agentforce-architecture/scripts/tests/test_end_to_end_fixture.py +651 -0
  241. package/skills/investigating-agentforce-architecture/scripts/tests/test_finalize.py +278 -0
  242. package/skills/investigating-agentforce-architecture/scripts/tests/test_flow_children_inflation.py +582 -0
  243. package/skills/investigating-agentforce-architecture/scripts/tests/test_fs_guard.py +113 -0
  244. package/skills/investigating-agentforce-architecture/scripts/tests/test_iterative_wave_b.py +478 -0
  245. package/skills/investigating-agentforce-architecture/scripts/tests/test_main_pipeline.py +3359 -0
  246. package/skills/investigating-agentforce-architecture/scripts/tests/test_parallel_retrieve.py +131 -0
  247. package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_bundle.py +400 -0
  248. package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave.py +644 -0
  249. package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave_classifiers.py +224 -0
  250. package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave_helpers.py +380 -0
  251. package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave_main.py +397 -0
  252. package/skills/investigating-agentforce-architecture/scripts/tests/test_per_branch_visited.py +244 -0
  253. package/skills/investigating-agentforce-architecture/scripts/tests/test_probe_channels.py +359 -0
  254. package/skills/investigating-agentforce-architecture/scripts/tests/test_probe_cli_recipes.py +185 -0
  255. package/skills/investigating-agentforce-architecture/scripts/tests/test_render_architecture.py +810 -0
  256. package/skills/investigating-agentforce-architecture/scripts/tests/test_resolve_bot.py +203 -0
  257. package/skills/investigating-agentforce-architecture/scripts/tests/test_resolve_creds.py +157 -0
  258. package/skills/investigating-agentforce-architecture/scripts/tests/test_resolve_invocation_target.py +145 -0
  259. package/skills/investigating-agentforce-architecture/scripts/tests/test_rest_client.py +1253 -0
  260. package/skills/investigating-agentforce-architecture/scripts/tests/test_runtime_override.py +100 -0
  261. package/skills/investigating-agentforce-architecture/scripts/tests/test_sf_cli.py +261 -0
  262. package/skills/investigating-agentforce-architecture/scripts/tests/test_signature_stamping.py +466 -0
  263. package/skills/investigating-agentforce-architecture/scripts/tests/test_soql_loader.py +501 -0
  264. package/skills/investigating-agentforce-architecture/scripts/tests/test_summarize_tree.py +241 -0
  265. package/skills/investigating-agentforce-architecture/scripts/tests/test_write_emit_ctx.py +480 -0
  266. package/skills/investigating-agentforce-architecture/tools/emit_env.py +157 -0
  267. package/skills/investigating-agentforce-architecture/tools/emit_result.py +262 -0
  268. package/skills/investigating-agentforce-architecture/tools/sanitize.py +33 -0
  269. package/skills/investigating-agentforce-architecture/tools/write_emit_ctx.py +332 -0
  270. package/skills/investigating-agentforce-d360/README.md +123 -0
  271. package/skills/investigating-agentforce-d360/SKILL.md +163 -0
  272. package/skills/investigating-agentforce-d360/assets/dc/app_generation.sql +51 -0
  273. package/skills/investigating-agentforce-d360/assets/dc/content_category.sql +44 -0
  274. package/skills/investigating-agentforce-d360/assets/dc/content_quality.sql +41 -0
  275. package/skills/investigating-agentforce-d360/assets/dc/discover_sessions.sql +36 -0
  276. package/skills/investigating-agentforce-d360/assets/dc/feedback.sql +47 -0
  277. package/skills/investigating-agentforce-d360/assets/dc/feedback_details.sql +38 -0
  278. package/skills/investigating-agentforce-d360/assets/dc/gateway_records.sql +45 -0
  279. package/skills/investigating-agentforce-d360/assets/dc/gateway_request_llm.sql +50 -0
  280. package/skills/investigating-agentforce-d360/assets/dc/gateway_request_metadata.sql +44 -0
  281. package/skills/investigating-agentforce-d360/assets/dc/gateway_request_tags.sql +42 -0
  282. package/skills/investigating-agentforce-d360/assets/dc/gateway_requests.sql +89 -0
  283. package/skills/investigating-agentforce-d360/assets/dc/gateway_responses.sql +43 -0
  284. package/skills/investigating-agentforce-d360/assets/dc/generations.sql +52 -0
  285. package/skills/investigating-agentforce-d360/assets/dc/interactions.sql +53 -0
  286. package/skills/investigating-agentforce-d360/assets/dc/messages.sql +53 -0
  287. package/skills/investigating-agentforce-d360/assets/dc/messaging_session.sql +37 -0
  288. package/skills/investigating-agentforce-d360/assets/dc/moment_interactions.sql +34 -0
  289. package/skills/investigating-agentforce-d360/assets/dc/moments.sql +39 -0
  290. package/skills/investigating-agentforce-d360/assets/dc/participants.sql +48 -0
  291. package/skills/investigating-agentforce-d360/assets/dc/sessions.sql +78 -0
  292. package/skills/investigating-agentforce-d360/assets/dc/steps.sql +64 -0
  293. package/skills/investigating-agentforce-d360/assets/dc/tag_associations.sql +46 -0
  294. package/skills/investigating-agentforce-d360/assets/dc/tag_definition_associations.sql +37 -0
  295. package/skills/investigating-agentforce-d360/assets/dc/tag_definitions.sql +50 -0
  296. package/skills/investigating-agentforce-d360/assets/dc/tags.sql +37 -0
  297. package/skills/investigating-agentforce-d360/assets/dc/telemetry_spans.sql +55 -0
  298. package/skills/investigating-agentforce-d360/references/artifacts.md +50 -0
  299. package/skills/investigating-agentforce-d360/references/dc_dmo_fields.md +823 -0
  300. package/skills/investigating-agentforce-d360/references/dc_pipeline_contract.md +608 -0
  301. package/skills/investigating-agentforce-d360/scripts/_shared/__init__.py +2 -0
  302. package/skills/investigating-agentforce-d360/scripts/_shared/cli_override.py +98 -0
  303. package/skills/investigating-agentforce-d360/scripts/_shared/fs_guard.py +334 -0
  304. package/skills/investigating-agentforce-d360/scripts/_shared/paths.py +155 -0
  305. package/skills/investigating-agentforce-d360/scripts/_shared/runtime.py +59 -0
  306. package/skills/investigating-agentforce-d360/scripts/_shared/sql.py +14 -0
  307. package/skills/investigating-agentforce-d360/scripts/assemble_dc.py +1624 -0
  308. package/skills/investigating-agentforce-d360/scripts/config.py +45 -0
  309. package/skills/investigating-agentforce-d360/scripts/dc.py +188 -0
  310. package/skills/investigating-agentforce-d360/scripts/discover_sessions.py +556 -0
  311. package/skills/investigating-agentforce-d360/scripts/fetch_dc.py +1045 -0
  312. package/skills/investigating-agentforce-d360/scripts/render_dc.py +1750 -0
  313. package/skills/investigating-agentforce-d360/scripts/resolve_session.py +264 -0
  314. package/skills/investigating-agentforce-d360/scripts/storage.py +92 -0
  315. package/skills/investigating-agentforce-d360/scripts/tests/__init__.py +0 -0
  316. package/skills/investigating-agentforce-d360/scripts/tests/_bootstrap.py +15 -0
  317. package/skills/investigating-agentforce-d360/scripts/tests/fixtures/__init__.py +0 -0
  318. package/skills/investigating-agentforce-d360/scripts/tests/fixtures/synthetic_session.py +424 -0
  319. package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_bootstrap_and_mode.py +115 -0
  320. package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_gateway_direct.py +220 -0
  321. package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_gateway_direct_integration.py +158 -0
  322. package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_helpers.py +287 -0
  323. package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_integration.py +247 -0
  324. package/skills/investigating-agentforce-d360/scripts/tests/test_dc_and_resolve_session.py +433 -0
  325. package/skills/investigating-agentforce-d360/scripts/tests/test_discover_sessions.py +458 -0
  326. package/skills/investigating-agentforce-d360/scripts/tests/test_discover_sessions_grep_ci.py +193 -0
  327. package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_helpers.py +266 -0
  328. package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_identity.py +528 -0
  329. package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_main.py +251 -0
  330. package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_waterfall.py +229 -0
  331. package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_waterfall_full.py +283 -0
  332. package/skills/investigating-agentforce-d360/scripts/tests/test_identity_coherence.py +327 -0
  333. package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_branches.py +256 -0
  334. package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_gateway_direct.py +130 -0
  335. package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_helpers.py +291 -0
  336. package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_integration.py +220 -0
  337. package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_planner_llm_calls.py +284 -0
  338. package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_show_prompts_gating.py +215 -0
  339. package/skills/investigating-agentforce-d360/scripts/tests/test_resolve_from_disk.py +100 -0
  340. package/skills/investigating-agentforce-d360/scripts/tests/test_resolve_session_main.py +149 -0
  341. package/skills/investigating-agentforce-d360/scripts/tests/test_runtime_override.py +104 -0
  342. package/skills/investigating-agentforce-d360/scripts/tests/test_session_shape.py +95 -0
  343. package/skills/investigating-agentforce-d360/scripts/tests/test_session_shape_dropped_by_stdm.py +85 -0
  344. package/skills/managing-managed-event-subscription/SKILL.md +152 -0
  345. package/skills/managing-managed-event-subscription/assets/managed-event-subscription-template.xml +20 -0
  346. package/skills/managing-managed-event-subscription/references/delete-guide.md +57 -0
  347. package/skills/managing-managed-event-subscription/references/topic-name-formats.md +26 -0
  348. package/skills/managing-managed-event-subscription/references/update-constraints.md +30 -0
  349. package/skills/modeling-omnistudio-epc-catalog/SKILL.md +0 -1
  350. package/skills/observing-agentforce/SKILL.md +0 -1
  351. package/skills/orchestrating-datacloud/SKILL.md +0 -1
  352. package/skills/preparing-datacloud/SKILL.md +0 -1
  353. package/skills/querying-soql/SKILL.md +0 -1
  354. package/skills/retrieving-datacloud/SKILL.md +0 -1
  355. package/skills/running-apex-tests/SKILL.md +0 -1
  356. package/skills/running-code-analyzer/SKILL.md +0 -1
  357. package/skills/segmenting-datacloud/SKILL.md +0 -1
  358. package/skills/testing-agentforce/SKILL.md +0 -1
  359. package/skills/uplifting-components-to-slds2/SKILL.md +3 -2
  360. package/skills/uplifting-components-to-slds2/references/color-hooks-decision-guide.md +30 -9
  361. package/skills/uplifting-components-to-slds2/references/examples.md +24 -6
  362. package/skills/validating-slds/SKILL.md +262 -0
  363. package/skills/validating-slds/references/quality-checks.md +308 -0
  364. package/skills/validating-slds/references/report-format.md +302 -0
  365. package/skills/validating-slds/scripts/analyze-quality.cjs +521 -0
@@ -0,0 +1,265 @@
1
+ """Metadata API listMetadata wrappers — for sObjects that are NOT
2
+ exposed via SOQL on Tooling or Data API (e.g. GenAiPromptTemplate).
3
+
4
+ Wraps the sf CLI `sf org list metadata` recipe. Not a REST client call —
5
+ uses subprocess via sf_cli.run_sf. Failure semantics mirror the rest:
6
+ returns [] on known-missing + surfaces unresolved reasons upstream;
7
+ raises SfCliError / AuthRequired on unknown failures.
8
+ """
9
+ from __future__ import annotations
10
+
11
+ import subprocess
12
+ import xml.etree.ElementTree as ET
13
+ import zipfile
14
+ from pathlib import Path
15
+ from typing import Any, Dict, List
16
+
17
+ from rest_client import redact_error
18
+ from sf_cli import (
19
+ AuthRequired,
20
+ _redact_subprocess_stderr,
21
+ _stderr_matches_auth,
22
+ run_sf,
23
+ )
24
+
25
+
26
+ # Metadata XML default namespace — same as parse_bundle.NS. Duplicated
27
+ # (rather than imported) to keep the "no intra-skill imports" convention
28
+ # documented throughout the pipeline.
29
+ _NS = {"sf": "http://soap.sforce.com/2006/04/metadata"}
30
+
31
+
32
+ def list_prompt_template_metadata(org_alias: str) -> List[Dict[str, str]]:
33
+ """Return every GenAiPromptTemplate metadata component in the org.
34
+
35
+ Each row has the shape produced by `sf org list metadata --json`:
36
+ {"id": "0hfUv...", "fullName": "AGNT_...", "type": "GenAiPromptTemplate",
37
+ "namespacePrefix": "...", ...}
38
+
39
+ Empty list on success with no templates. Raises SfCliError on CLI
40
+ failure (caller decides whether to treat as fatal).
41
+ """
42
+ data = run_sf("list_metadata_genaiprompttemplate", ORG_ALIAS=org_alias)
43
+ result = data.get("result")
44
+ if not isinstance(result, list):
45
+ return []
46
+ return [r for r in result if isinstance(r, dict)]
47
+
48
+
49
+ def _find_text(el: ET.Element | None, path: str) -> str | None:
50
+ if el is None:
51
+ return None
52
+ found = el.find(path, _NS)
53
+ if found is None:
54
+ return None
55
+ return found.text
56
+
57
+
58
+ def _parse_prompt_template_xml(xml_bytes: bytes) -> Dict[str, Any] | None:
59
+ """Parse a single .genAiPromptTemplate XML file into a body dict.
60
+
61
+ Returns None on parse failure so the caller can log + skip. The
62
+ returned dict carries developerName/masterLabel/activeVersionIdentifier/
63
+ content/inputs — absent optional fields become None or empty lists.
64
+
65
+ Version selection: if multiple <templateVersions> elements exist,
66
+ prefer the one whose `versionIdentifier` matches the template-level
67
+ `activeVersionIdentifier`; otherwise fall back to the first version.
68
+ """
69
+ try:
70
+ root = ET.fromstring(xml_bytes)
71
+ except ET.ParseError:
72
+ return None
73
+
74
+ developer_name = _find_text(root, "sf:developerName")
75
+ master_label = _find_text(root, "sf:masterLabel")
76
+ active_version = _find_text(root, "sf:activeVersionIdentifier")
77
+
78
+ versions = root.findall("sf:templateVersions", _NS)
79
+ picked: ET.Element | None = None
80
+ if versions:
81
+ if active_version:
82
+ for v in versions:
83
+ vid = _find_text(v, "sf:versionIdentifier")
84
+ if vid and vid == active_version:
85
+ picked = v
86
+ break
87
+ if picked is None:
88
+ picked = versions[0]
89
+
90
+ content = _find_text(picked, "sf:content") if picked is not None else None
91
+
92
+ inputs: List[Dict[str, str]] = []
93
+ if picked is not None:
94
+ for inp in picked.findall("sf:inputs", _NS):
95
+ name = _find_text(inp, "sf:apiName") or _find_text(inp, "sf:name")
96
+ data_type = _find_text(inp, "sf:dataType")
97
+ if name is None and data_type is None:
98
+ continue
99
+ entry: Dict[str, str] = {}
100
+ if name is not None:
101
+ entry["name"] = name
102
+ if data_type is not None:
103
+ entry["dataType"] = data_type
104
+ inputs.append(entry)
105
+
106
+ return {
107
+ "developerName": developer_name,
108
+ "masterLabel": master_label,
109
+ "activeVersionIdentifier": active_version,
110
+ "content": content,
111
+ "inputs": inputs,
112
+ }
113
+
114
+
115
+ # Timeout for `sf project retrieve start` — matches the prior YAML recipe's
116
+ # `timeout_seconds: 300`. Kept as a module constant (rather than a literal
117
+ # at the call site) so future adjustments have a single home.
118
+ _RETRIEVE_TIMEOUT_SECONDS = 300
119
+
120
+ # stderr patterns that mean "the CLI ran but there is no authenticated org
121
+ # for this alias" — reraised as AuthRequired. Mirrors the prior recipe's
122
+ # `auth_required_stderr_patterns` field.
123
+ _RETRIEVE_AUTH_PATTERNS = ("NoOrgAuthenticationError", "AuthInfoError")
124
+
125
+
126
+ def _run_retrieve(argv: List[str], timeout: int) -> "subprocess.CompletedProcess[str]":
127
+ """Thin wrapper over `subprocess.run` for the retrieve-start call.
128
+
129
+ Exists so tests can mock the subprocess boundary without also mocking
130
+ the argv-construction logic — see `RetrievePromptTemplatesTests`.
131
+ """
132
+ return subprocess.run(
133
+ argv,
134
+ capture_output=True,
135
+ text=True,
136
+ timeout=timeout,
137
+ check=False,
138
+ )
139
+
140
+
141
+ def retrieve_prompt_templates(
142
+ org_alias: str,
143
+ template_names: List[str],
144
+ work_dir: Path,
145
+ ) -> Dict[str, Dict[str, Any]]:
146
+ """Retrieve GenAiPromptTemplate bodies via `sf project retrieve start`.
147
+
148
+ The sf plugin's `--metadata` flag is REPEATED once per requested
149
+ template (`--metadata GenAiPromptTemplate:A --metadata
150
+ GenAiPromptTemplate:B ...`). A comma-joined value is NOT a valid list;
151
+ the CLI treats the whole comma-joined string as a single malformed
152
+ member name, silently skips it, and the resulting zip contains only
153
+ `package.xml` (observed 2026-05-05 against my-org-alias). Hence we
154
+ bypass the YAML recipe loader here — `run_sf` substitutes
155
+ `{{METADATA_SPEC}}` single-shot and has no list-expansion primitive.
156
+
157
+ The resulting `unpackaged.zip` carries one `.genAiPromptTemplate` XML
158
+ file per template under `unpackaged/genAiPromptTemplates/`.
159
+
160
+ Returns a dict keyed by `developerName`. Templates the retrieve
161
+ didn't produce a file for are OMITTED (caller handles missing by
162
+ leaving them in `_pending_fetches`).
163
+
164
+ Failure modes:
165
+ - Empty `template_names` → short-circuits with `{}` and no sf call.
166
+ - `AuthRequired` (stderr matches auth patterns) → re-raised.
167
+ - `SfCliError` (any other non-zero exit, timeout, etc) → swallowed;
168
+ returns `{}`. Caller logs the retrieval-failure reason at the
169
+ call site.
170
+ - Zip missing or malformed → returns `{}`.
171
+ - XML parse failure on a specific file → that file is skipped; the
172
+ other templates in the same zip still parse and return.
173
+ """
174
+ if not template_names:
175
+ return {}
176
+
177
+ retrieve_dir = work_dir / "prompt_template_retrieve"
178
+ retrieve_dir.mkdir(parents=True, exist_ok=True)
179
+ # Nuke stale files from a prior invocation so we don't trust an old
180
+ # unpackaged.zip if this run's sf call fails before writing one.
181
+ for path in retrieve_dir.iterdir():
182
+ if path.is_file():
183
+ path.unlink()
184
+ elif path.is_dir():
185
+ _rm_tree(path)
186
+
187
+ argv: List[str] = [
188
+ "sf",
189
+ "project",
190
+ "retrieve",
191
+ "start",
192
+ "--target-org",
193
+ org_alias,
194
+ "--target-metadata-dir",
195
+ str(retrieve_dir),
196
+ "--json",
197
+ ]
198
+ for name in template_names:
199
+ argv.extend(["--metadata", f"GenAiPromptTemplate:{name}"])
200
+
201
+ try:
202
+ cp = _run_retrieve(argv, _RETRIEVE_TIMEOUT_SECONDS)
203
+ except subprocess.TimeoutExpired as e:
204
+ # timeout exceptions may carry stderr; route through
205
+ # redact_error before surfacing — then swallow as non-fatal, same
206
+ # contract the old run_sf-based path had for SfCliError.
207
+ _ = redact_error(e)
208
+ return {}
209
+ except (OSError, subprocess.SubprocessError) as e:
210
+ _ = redact_error(e)
211
+ return {}
212
+
213
+ if cp.returncode != 0:
214
+ # Classify: auth failure re-raises, everything else is non-fatal.
215
+ if _stderr_matches_auth(cp.stderr, _RETRIEVE_AUTH_PATTERNS):
216
+ safe_stderr = _redact_subprocess_stderr(cp.stderr)
217
+ raise AuthRequired(safe_stderr or "auth required")
218
+ return {}
219
+
220
+ zip_path = retrieve_dir / "unpackaged.zip"
221
+ if not zip_path.exists():
222
+ return {}
223
+
224
+ results: Dict[str, Dict[str, Any]] = {}
225
+ try:
226
+ with zipfile.ZipFile(zip_path) as zf:
227
+ for info in zf.infolist():
228
+ name = info.filename
229
+ if not name.endswith(".genAiPromptTemplate"):
230
+ continue
231
+ if "genAiPromptTemplates/" not in name:
232
+ continue
233
+ try:
234
+ xml_bytes = zf.read(info)
235
+ except (KeyError, zipfile.BadZipFile):
236
+ continue
237
+ body = _parse_prompt_template_xml(xml_bytes)
238
+ if not body:
239
+ continue
240
+ dev_name = body.get("developerName")
241
+ if not dev_name:
242
+ # Fall back to the file stem if the XML somehow lacks
243
+ # a <developerName> element — keeps the caller's
244
+ # lookup working.
245
+ stem = Path(name).stem
246
+ if stem:
247
+ body["developerName"] = stem
248
+ dev_name = stem
249
+ if dev_name:
250
+ results[dev_name] = body
251
+ except zipfile.BadZipFile:
252
+ return {}
253
+
254
+ return results
255
+
256
+
257
+ def _rm_tree(path: Path) -> None:
258
+ """Recursively delete a directory tree. stdlib-only, no shutil import
259
+ at module top to keep the import surface minimal."""
260
+ for child in path.iterdir():
261
+ if child.is_dir():
262
+ _rm_tree(child)
263
+ else:
264
+ child.unlink()
265
+ path.rmdir()
@@ -0,0 +1,69 @@
1
+ """ThreadPoolExecutor orchestrator for Wave B body fetches.
2
+
3
+ one failure MUST NOT abort the whole run. Callers merge failed kinds
4
+ into `_unresolved[]` with `reason=f'{kind}-fetch-failed:{redact_error(exc)}'`
5
+ and emit STATUS=PARTIAL_OK. We return a mixed list of (ok, result_or_exc)
6
+ tuples instead of raising on the first failure — which is what
7
+ `ThreadPoolExecutor.map` would do (and silently cancel remaining work in
8
+ the process).
9
+
10
+ Exception identity is preserved on the failure path: callers get the exact
11
+ exception object back so they can run it through `rest_client.redact_error`
12
+ at the point of logging. We intentionally do NOT stringify here — doing so
13
+ would lose structured info (urllib.error.HTTPError.code, etc.) and could
14
+ leak tokens into intermediate strings before redaction runs.
15
+ """
16
+ from __future__ import annotations
17
+
18
+ from concurrent.futures import ThreadPoolExecutor, as_completed
19
+ from typing import Callable
20
+
21
+
22
+ def fetch_bodies_parallel(
23
+ tasks: list[Callable[[], object]],
24
+ *,
25
+ max_workers: int = 5,
26
+ ) -> list[tuple[bool, object]]:
27
+ """Run zero-arg callables in parallel; return (ok, result_or_exc) per task.
28
+
29
+ contract:
30
+ * Each `task` is a zero-arg callable (use `functools.partial` to bind
31
+ args at the call site).
32
+ * On success, `(True, return_value)` is appended.
33
+ * On any exception, `(False, exc)` is appended — the EXC object itself,
34
+ not a stringification. Callers run it through `rest_client.redact_error`
35
+ before logging.
36
+ * Results are returned in INPUT ORDER, not completion order. Callers
37
+ frequently zip results back to their input tasks to identify which
38
+ target failed; completion order would break that contract.
39
+ * Empty task list returns `[]` without spinning up a pool.
40
+ * `max_workers=1` serializes — tasks run sequentially but the as_completed
41
+ path is still used (deterministic ordering preserved via index map).
42
+ * This function NEVER raises on a task failure. It may propagate
43
+ programmer errors (e.g., a non-callable in `tasks`) at submit time;
44
+ that's a bug surface, not a runtime failure mode.
45
+ """
46
+ if not tasks:
47
+ return []
48
+
49
+ # Pre-size the results list so we can assign by input index. This keeps
50
+ # output ordering deterministic and independent of completion timing,
51
+ # which matters for callers that identify failures positionally.
52
+ results: list[tuple[bool, object] | None] = [None] * len(tasks)
53
+
54
+ with ThreadPoolExecutor(max_workers=max_workers) as pool:
55
+ future_to_idx = {pool.submit(task): i for i, task in enumerate(tasks)}
56
+ for fut in as_completed(future_to_idx):
57
+ idx = future_to_idx[fut]
58
+ try:
59
+ results[idx] = (True, fut.result())
60
+ except Exception as exc: # noqa: BLE001 — see contract above
61
+ # Preserve exc identity; do NOT stringify here. Callers run
62
+ # this through rest_client.redact_error at log time .
63
+ # We catch Exception (not BaseException) so KeyboardInterrupt
64
+ # / SystemExit still propagate — those signal shutdown, not a
65
+ # task failure.
66
+ results[idx] = (False, exc)
67
+
68
+ # All slots filled by construction — futures/indexes are 1:1 with input.
69
+ return [r for r in results if r is not None] # type: ignore[return-value]
@@ -0,0 +1,215 @@
1
+ #!/usr/bin/env python3
2
+ """Parse Bot.bot + GenAiPlannerBundle → _bundle_parsed.json + PLANNER_NAME.
3
+
4
+ Replaces old agent Phase 2a (Bot.bot planner-name extraction via XPath-ish
5
+ walk) + Phase 2c (bundle XML → topics/plannerActions + generation classifier).
6
+
7
+ Step 1 — planner name:
8
+ Read $WORK_DIR/sf_meta/wave1_bot/unpackaged/bots/*.bot XML.
9
+ Path: /Bot/botVersions[fullName==$AGENT_VERSION]/conversationDefinitionPlanners[0]
10
+ /genAiPlannerName (fallback: plannerName, fullName)
11
+
12
+ Step 2 — bundle (only if planner name resolved AND bundle dir exists):
13
+ Read $WORK_DIR/sf_meta/wave1_bundle/unpackaged/genAiPlannerBundles/<plannerName>/
14
+ *.genAiPlannerBundle
15
+ Extract: plannerType, description, masterLabel, localTopics[] with inline
16
+ localActions[], and (classic-only) plannerActions[].
17
+ Classify generation:
18
+ plannerType startswith "AiCopilot__" → classic
19
+ plannerType startswith "Atlas__" → nga
20
+ else → unknown
21
+
22
+ Emits:
23
+ $WORK_DIR/_bundle_parsed.json (full structured extraction)
24
+ $WORK_DIR/_agent_generation.txt (generation string, newline-terminated)
25
+ stdout: `PLANNER_NAME=<shlex-quoted>\nAGENT_GENERATION=<shlex-quoted>`
26
+ + log lines (topic counts, action counts) for human readability.
27
+
28
+ If Bot.bot has no <conversationDefinitionPlanners>, prints `PLANNER_NAME=''`
29
+ and exits 0 — caller treats the tree as partial.
30
+
31
+ Usage:
32
+ eval "$(python3 parse_bundle.py)"
33
+
34
+ Inputs (env):
35
+ WORK_DIR required
36
+ AGENT_VERSION required — used to pin the right <botVersions> element
37
+
38
+ Outputs:
39
+ files (above)
40
+ stdout eval-friendly K=V lines
41
+ exit 0 always (no recoverable error condition; missing XML → empty planner)
42
+ """
43
+ import json
44
+ import os
45
+ import pathlib
46
+ import shlex
47
+ import sys
48
+ import xml.etree.ElementTree as ET
49
+
50
+
51
+ NS = {"sf": "http://soap.sforce.com/2006/04/metadata"}
52
+
53
+
54
+ def _t(el, p):
55
+ if el is None:
56
+ return None
57
+ x = el.find(p, NS)
58
+ return x.text if x is not None else None
59
+
60
+
61
+ def classify_generation(planner_type: str) -> str:
62
+ if not planner_type:
63
+ return "unknown"
64
+ if planner_type.startswith("AiCopilot__"):
65
+ return "classic"
66
+ if planner_type.startswith("Atlas__"):
67
+ return "nga"
68
+ return "unknown"
69
+
70
+
71
+ def extract_planner_name(work_dir: pathlib.Path, target_ver: str) -> str:
72
+ bots_dir = work_dir / "sf_meta" / "wave1_bot" / "unpackaged" / "bots"
73
+ if not bots_dir.exists():
74
+ return ""
75
+ for bot_file in bots_dir.glob("*.bot"):
76
+ try:
77
+ root = ET.parse(bot_file).getroot()
78
+ except ET.ParseError:
79
+ continue
80
+ for bv in root.findall("sf:botVersions", NS):
81
+ full = _t(bv, "sf:fullName") or _t(bv, "sf:developerName")
82
+ if target_ver and full != target_ver:
83
+ continue
84
+ for cdp in bv.findall("sf:conversationDefinitionPlanners", NS):
85
+ n = (_t(cdp, "sf:genAiPlannerName")
86
+ or _t(cdp, "sf:plannerName")
87
+ or _t(cdp, "sf:fullName"))
88
+ if n:
89
+ return n
90
+ return ""
91
+
92
+
93
+ def extract_bundle(work_dir: pathlib.Path, planner_name: str) -> dict:
94
+ bundle = {
95
+ "plannerType": None,
96
+ "plannerName": planner_name or None,
97
+ "generation": "unknown",
98
+ "description": None,
99
+ "masterLabel": None,
100
+ "topics": [],
101
+ "plannerActions": [],
102
+ }
103
+
104
+ planner_root = work_dir / "sf_meta" / "wave1_bundle" / "unpackaged" / "genAiPlannerBundles"
105
+ if not planner_root.exists():
106
+ return bundle
107
+
108
+ for bundle_dir in planner_root.iterdir():
109
+ if not bundle_dir.is_dir():
110
+ continue
111
+ bundle_xml = list(bundle_dir.glob("*.genAiPlannerBundle"))
112
+ if not bundle_xml:
113
+ continue
114
+ try:
115
+ root = ET.parse(bundle_xml[0]).getroot()
116
+ except ET.ParseError as e:
117
+ sys.stderr.write(f"parse_bundle.py: XML parse error on {bundle_xml[0]}: {e}\n")
118
+ continue
119
+
120
+ bundle["plannerType"] = _t(root, "sf:plannerType")
121
+ bundle["generation"] = classify_generation(bundle["plannerType"])
122
+ bundle["description"] = _t(root, "sf:description")
123
+ bundle["masterLabel"] = _t(root, "sf:masterLabel")
124
+
125
+ for lt in root.findall("sf:localTopics", NS):
126
+ tname = _t(lt, "sf:developerName") or _t(lt, "sf:fullName")
127
+ if not tname:
128
+ continue
129
+ topic = {
130
+ "name": tname,
131
+ "localDeveloperName": _t(lt, "sf:localDeveloperName"),
132
+ "masterLabel": _t(lt, "sf:masterLabel"),
133
+ "description": _t(lt, "sf:description"),
134
+ "canEscalate": (_t(lt, "sf:canEscalate") or "false").lower() == "true",
135
+ "pluginType": _t(lt, "sf:pluginType"),
136
+ "actions": [],
137
+ }
138
+ for la in lt.findall("sf:localActions", NS):
139
+ aname = _t(la, "sf:developerName") or _t(la, "sf:fullName")
140
+ if not aname:
141
+ continue
142
+ topic["actions"].append({
143
+ "name": aname,
144
+ "localDeveloperName": _t(la, "sf:localDeveloperName"),
145
+ "masterLabel": _t(la, "sf:masterLabel"),
146
+ "description": _t(la, "sf:description"),
147
+ "invocationTarget": _t(la, "sf:invocationTarget"),
148
+ "invocationTargetType": (_t(la, "sf:invocationTargetType") or "").strip(),
149
+ "source": _t(la, "sf:source"),
150
+ })
151
+ bundle["topics"].append(topic)
152
+
153
+ for pa in root.findall("sf:plannerActions", NS):
154
+ aname = _t(pa, "sf:developerName") or _t(pa, "sf:fullName")
155
+ if not aname:
156
+ continue
157
+ bundle["plannerActions"].append({
158
+ "name": aname,
159
+ "localDeveloperName": _t(pa, "sf:localDeveloperName"),
160
+ "masterLabel": _t(pa, "sf:masterLabel"),
161
+ "description": _t(pa, "sf:description"),
162
+ "invocationTarget": _t(pa, "sf:invocationTarget"),
163
+ "invocationTargetType": (_t(pa, "sf:invocationTargetType") or "").strip(),
164
+ "source": _t(pa, "sf:source"),
165
+ })
166
+ break # first bundle dir is enough
167
+ return bundle
168
+
169
+
170
+ def atomic_write(path: pathlib.Path, content: str) -> None:
171
+ tmp = path.with_suffix(path.suffix + ".tmp")
172
+ tmp.write_text(content)
173
+ os.replace(tmp, path)
174
+
175
+
176
+ def main() -> int:
177
+ try:
178
+ work_dir = pathlib.Path(os.environ["WORK_DIR"])
179
+ agent_version = os.environ["AGENT_VERSION"]
180
+ except KeyError as e:
181
+ sys.stderr.write(f"parse_bundle.py: missing env {e}\n")
182
+ return 1
183
+
184
+ # Step 1: planner name
185
+ planner_name = extract_planner_name(work_dir, agent_version)
186
+
187
+ # Step 2: bundle (only if planner resolved)
188
+ bundle = extract_bundle(work_dir, planner_name) if planner_name else {
189
+ "plannerType": None, "plannerName": None, "generation": "unknown",
190
+ "description": None, "masterLabel": None, "topics": [], "plannerActions": [],
191
+ }
192
+
193
+ atomic_write(work_dir / "_bundle_parsed.json", json.dumps(bundle, indent=2))
194
+ atomic_write(work_dir / "_agent_generation.txt", bundle["generation"] + "\n")
195
+
196
+ # Log lines (stderr would be lost via eval; use stderr for logs not shell-consumed)
197
+ total_actions = (
198
+ sum(len(t["actions"]) for t in bundle["topics"]) + len(bundle["plannerActions"])
199
+ )
200
+ sys.stderr.write(
201
+ f"[parse_bundle] plannerName={planner_name!r} "
202
+ f"plannerType={bundle['plannerType']!r} generation={bundle['generation']}\n"
203
+ f"[parse_bundle] topics={len(bundle['topics'])} "
204
+ f"topic-scope-actions={sum(len(t['actions']) for t in bundle['topics'])} "
205
+ f"bundle-scope-actions={len(bundle['plannerActions'])} total={total_actions}\n"
206
+ )
207
+
208
+ # Eval-friendly stdout
209
+ sys.stdout.write(f"PLANNER_NAME={shlex.quote(planner_name)}\n")
210
+ sys.stdout.write(f"AGENT_GENERATION={shlex.quote(bundle['generation'])}\n")
211
+ return 0
212
+
213
+
214
+ if __name__ == "__main__":
215
+ sys.exit(main())