@salsita-ai/sdk 0.50.0-develop.aff4f8dd6d → 0.50.0-develop.b9eb39baf0

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 (405) hide show
  1. package/dist/application-spec/generate-application/code/common/index.d.ts +1 -0
  2. package/dist/application-spec/generate-application/code/common/index.js +1 -1
  3. package/dist/application-spec/generate-application/code/common/project-module-list.d.ts +8 -0
  4. package/dist/application-spec/generate-application/code/common/project-module-list.js +3 -0
  5. package/dist/application-spec/generate-application/code/domain-runtime-files.js +1 -1
  6. package/dist/application-spec/generate-application/code/templates/admin-domain-code.d.ts +1 -2
  7. package/dist/application-spec/generate-application/code/templates/admin-domain-code.js +6 -14
  8. package/dist/application-spec/generate-application/code/templates/admin-frontend-code.d.ts +1 -2
  9. package/dist/application-spec/generate-application/code/templates/admin-frontend-code.js +4 -4
  10. package/dist/application-spec/generate-application/code/templates/configurator-domain-code.d.ts +1 -2
  11. package/dist/application-spec/generate-application/code/templates/configurator-domain-code.js +7 -16
  12. package/dist/application-spec/generate-application/code/templates/configurator-frontend-code.d.ts +1 -2
  13. package/dist/application-spec/generate-application/code/templates/configurator-frontend-code.js +7 -9
  14. package/dist/application-spec/generate-application/code/templates/domain-spec/generate-assistant.d.ts +2 -2
  15. package/dist/application-spec/generate-application/code/templates/domain-spec/generate-assistant.js +1 -1
  16. package/dist/application-spec/generate-application/code/templates/domain-spec.js +4 -4
  17. package/dist/application-spec/generate-application/code/templates/domain.js +3 -3
  18. package/dist/application-spec/generate-application/code/templates/skills/phoenix-review-skill.js +1 -1
  19. package/dist/application-spec/generate-application/code/templates/skills/sdk-content.d.ts +2 -1
  20. package/dist/application-spec/generate-application/code/templates/skills/sdk-content.js +1 -2
  21. package/dist/application-spec/generate-application/code/templates/webhook-builders.js +8 -4
  22. package/dist/application-spec/generate-application/runtime/sections/assistant-runtime.d.ts +4 -3
  23. package/dist/application-spec/generate-application/runtime/sections/assistant-runtime.js +1 -1
  24. package/dist/application-spec/parse-application-files/spec/sections/assistant/assistant-field-type.d.ts +3 -8
  25. package/dist/application-spec/parse-application-files/spec/sections/assistant/assistant-field-type.js +1 -1
  26. package/dist/application-spec/parse-application-files/spec/sections/assistant/assistant-schema.d.ts +9 -43
  27. package/dist/application-spec/parse-application-files/spec/sections/assistant/assistant-schema.js +1 -1
  28. package/dist/application-spec/parse-application-files/spec/sections/assistant/assistant-server-settings.d.ts +2 -2
  29. package/dist/application-spec/parse-application-files/spec/sections/assistant/assistant.d.ts +5 -21
  30. package/dist/client/phoenix-api.d.ts +58 -30
  31. package/dist/docs/complex-use-cases/filtered-controls-with-fix-dialog.mdx +84 -98
  32. package/dist/docs/complex-use-cases/navigation-reset-selection.mdx +18 -12
  33. package/dist/docs/index.json +1 -1
  34. package/dist/docs/layouts/custom-price.mdx +14 -16
  35. package/dist/docs/layouts/sidebar/tabs.mdx +24 -21
  36. package/dist/docs/other-features/domain-actions.mdx +1 -1
  37. package/dist/docs/other-features/side-effects.mdx +42 -34
  38. package/dist/docs/other-features/transformers.mdx +1 -1
  39. package/dist/docs/phoenix/admin.mdx +9 -24
  40. package/dist/docs/phoenix/localization.mdx +3 -22
  41. package/dist/docs/phoenix/project-structure.mdx +6 -0
  42. package/dist/docs/recipes-and-delete/recipe-hierarchy-selection.mdx +15 -13
  43. package/dist/docs/relations/hierarchy.mdx +13 -2
  44. package/dist/domain/actions/action-factory.d.ts +4 -4
  45. package/dist/domain/admin-domain/__generated/enhanced-model.d.ts +1 -1
  46. package/dist/domain/admin-domain/__generated/model/versions/v1.d.ts +1 -1
  47. package/dist/domain/admin-domain/__generated/model/versions/v2.d.ts +1 -1
  48. package/dist/domain/admin-domain/__generated/model/versions/v3.d.ts +1 -1
  49. package/dist/domain/admin-domain/__generated/model/versions/v4.d.ts +1 -1
  50. package/dist/domain/admin-domain/__generated/model/versions/v5.d.ts +1 -1
  51. package/dist/domain/admin-domain/__generated/model/versions/v6.d.ts +2 -2
  52. package/dist/domain/admin-domain/__generated/model/versions/v6.js +1 -1
  53. package/dist/domain/admin-domain/implementation/common-admin-expressions.d.ts +1 -3
  54. package/dist/domain/admin-domain/implementation/common-admin-migrations.d.ts +1 -1
  55. package/dist/domain/admin-domain/index.d.ts +1 -1
  56. package/dist/domain/application/admin-page-factories.d.ts +1 -1
  57. package/dist/domain/application/application-config.d.ts +25 -75
  58. package/dist/domain/application/assistant/assistant-manifest.d.ts +61 -0
  59. package/dist/domain/application/assistant/assistant-resolved-manifest.d.ts +95 -0
  60. package/dist/domain/application/assistant/assistant-value-type.d.ts +9 -0
  61. package/dist/domain/application/assistant/assistant-value-type.js +1 -0
  62. package/dist/domain/application/assistant/build-assistant-manifest.d.ts +4 -0
  63. package/dist/domain/application/assistant/build-assistant-manifest.js +1 -0
  64. package/dist/{phoenix/application-spec → domain/application/assistant}/generate-assistant-prompt.d.ts +3 -3
  65. package/dist/{phoenix/application-spec → domain/application/assistant}/generate-assistant-prompt.js +1 -1
  66. package/dist/domain/application/assistant/index.d.ts +4 -0
  67. package/dist/domain/application/assistant/index.js +1 -0
  68. package/dist/domain/application/assistant-field-options.d.ts +2 -3
  69. package/dist/domain/application/assistant-mutations.d.ts +2 -4
  70. package/dist/domain/application/assistant-mutations.js +1 -1
  71. package/dist/domain/application/assistant-recipe-groups.d.ts +2 -4
  72. package/dist/domain/application/configurator-builder.d.ts +33 -18
  73. package/dist/domain/application/configurator-builder.js +1 -1
  74. package/dist/domain/application/element-registration.d.ts +5 -0
  75. package/dist/domain/application/element-registration.js +1 -1
  76. package/dist/domain/application/handler-registration.d.ts +5 -0
  77. package/dist/domain/application/handler-registration.js +1 -1
  78. package/dist/domain/application/index.d.ts +5 -4
  79. package/dist/domain/application/index.js +1 -1
  80. package/dist/domain/application/published-data/create-finalize-admin-domain.d.ts +1 -2
  81. package/dist/domain/application/published-data/map-published-chunked-data.d.ts +1 -1
  82. package/dist/domain/application/published-data/map-published-data.d.ts +1 -2
  83. package/dist/domain/application/resolve-imported-transformers.d.ts +12 -2
  84. package/dist/domain/application/resolve-imported-transformers.js +1 -1
  85. package/dist/domain/components/component-reader-types.d.ts +1 -2
  86. package/dist/domain/components/debug-state-component.d.ts +1 -1
  87. package/dist/domain/components/debug-state-component.js +1 -1
  88. package/dist/domain/components/domain-component-optic.d.ts +4 -5
  89. package/dist/domain/components/domain-component-optic.js +2 -2
  90. package/dist/domain/components/drag-state-component.d.ts +1 -1
  91. package/dist/domain/components/drag-state-component.js +1 -1
  92. package/dist/domain/components/export-state-component.d.ts +1 -1
  93. package/dist/domain/components/export-state-component.js +1 -1
  94. package/dist/domain/components/fullscreen-state-component.d.ts +1 -1
  95. package/dist/domain/components/fullscreen-state-component.js +1 -1
  96. package/dist/domain/components/group-components-by-entity-id-and-name.d.ts +1 -2
  97. package/dist/domain/components/group-components-by-entity-id-and-name.js +1 -1
  98. package/dist/domain/components/hover-state-component.d.ts +1 -1
  99. package/dist/domain/components/hover-state-component.js +1 -1
  100. package/dist/domain/components/legacy-filter.d.ts +1 -2
  101. package/dist/domain/components/navigation-state-component.d.ts +1 -1
  102. package/dist/domain/components/navigation-state-component.js +1 -1
  103. package/dist/domain/components/selection-state-component.d.ts +1 -1
  104. package/dist/domain/components/selection-state-component.js +1 -1
  105. package/dist/domain/components/system-component-builder.d.ts +1 -2
  106. package/dist/domain/components/system-component-builder.js +1 -1
  107. package/dist/domain/components/system-component-filter.d.ts +1 -3
  108. package/dist/domain/components/system-virtual-entity.js +1 -1
  109. package/dist/domain/components/tool-state-component.d.ts +1 -1
  110. package/dist/domain/components/tool-state-component.js +1 -1
  111. package/dist/domain/components/updates.d.ts +1 -2
  112. package/dist/domain/components/view-state-component.d.ts +1 -1
  113. package/dist/domain/components/view-state-component.js +1 -1
  114. package/dist/domain/components/viewport-state-component.d.ts +1 -1
  115. package/dist/domain/components/viewport-state-component.js +1 -1
  116. package/dist/domain/core/action.d.ts +2 -2
  117. package/dist/domain/core/decoder/create-decoder.d.ts +6 -0
  118. package/dist/domain/core/decoder/create-decoder.js +1 -0
  119. package/dist/domain/core/decoder/decoder.d.ts +6 -0
  120. package/dist/domain/core/decoder/decoder.js +1 -0
  121. package/dist/domain/core/decoder/index.d.ts +2 -0
  122. package/dist/domain/core/decoder/index.js +1 -0
  123. package/dist/domain/core/domain-factory.d.ts +1 -2
  124. package/dist/domain/core/domain-factory.js +1 -1
  125. package/dist/domain/core/domain.d.ts +1 -2
  126. package/dist/domain/core/domain.js +1 -1
  127. package/dist/domain/core/expression.d.ts +1 -2
  128. package/dist/domain/core/index.d.ts +8 -17
  129. package/dist/domain/core/index.js +1 -1
  130. package/dist/domain/core/migrations.d.ts +1 -2
  131. package/dist/domain/core/{component.d.ts → model/component.d.ts} +1 -1
  132. package/dist/domain/core/model/index.d.ts +6 -0
  133. package/dist/domain/core/model/index.js +1 -0
  134. package/dist/domain/core/{reflection.d.ts → model/reflection.d.ts} +1 -1
  135. package/dist/domain/core/model/reflection.js +1 -0
  136. package/dist/domain/core/schema/enhanced-json-schema.js +1 -0
  137. package/dist/domain/core/schema/extended-schema-validator.js +1 -0
  138. package/dist/domain/core/schema/index.d.ts +3 -0
  139. package/dist/domain/core/schema/index.js +1 -0
  140. package/dist/domain/core/schema/schema-validator.js +1 -0
  141. package/dist/domain/core/state.d.ts +1 -2
  142. package/dist/domain/domain-builder.d.ts +11 -8
  143. package/dist/domain/domain-builder.js +1 -1
  144. package/dist/domain/domain-context/action-system/action-system.d.ts +1 -3
  145. package/dist/domain/domain-context/action-system/action-system.js +1 -1
  146. package/dist/domain/domain-context/create-transformer.d.ts +1 -1
  147. package/dist/domain/domain-context/domain-context-systems.d.ts +1 -3
  148. package/dist/domain/domain-context/navigation-system/navigation-system.d.ts +1 -2
  149. package/dist/domain/domain-context/navigation-system/navigation-updates.d.ts +1 -1
  150. package/dist/domain/domain-context/navigation-system/selection-transformers.d.ts +1 -1
  151. package/dist/domain/domain-context/navigation-system/selection-transformers.js +1 -1
  152. package/dist/domain/domain-context/recipe-system/recipes.d.ts +1 -3
  153. package/dist/domain/domain-context/recipe-system/recipes.js +1 -1
  154. package/dist/domain/domain-context/relation-transformers/cascade-deletes.d.ts +1 -1
  155. package/dist/domain/domain-context/relation-transformers/cascade-deletes.js +1 -1
  156. package/dist/domain/domain-context/relation-transformers/cascade-ref-pruning.d.ts +1 -1
  157. package/dist/domain/domain-context/relation-transformers/create-entity-refs.d.ts +1 -1
  158. package/dist/domain/domain-context/relation-transformers/replace-refs.d.ts +1 -1
  159. package/dist/domain/domain-context/store-system/apply-updates.d.ts +1 -2
  160. package/dist/domain/domain-context/store-system/apply-updates.js +1 -1
  161. package/dist/domain/domain-context/store-system/next-domain-entity-id.d.ts +1 -2
  162. package/dist/domain/domain-context/store-system/next-domain-entity-id.js +1 -1
  163. package/dist/domain/domain-context/store-system/reconcile-projected-entities.d.ts +1 -1
  164. package/dist/domain/domain-context/store-system/store-system.d.ts +1 -3
  165. package/dist/domain/domain-context/store-system/store-system.js +1 -1
  166. package/dist/domain/domain-context/store-system/system-state.d.ts +1 -3
  167. package/dist/domain/domain-context/transformers/actions-builder.d.ts +1 -1
  168. package/dist/domain/domain-context/transformers/actions-builder.js +1 -1
  169. package/dist/domain/domain-context/transformers/auto-snap-transformer.d.ts +1 -2
  170. package/dist/domain/domain-context/transformers/chain-builder.d.ts +2 -2
  171. package/dist/domain/domain-context/transformers/context.d.ts +1 -2
  172. package/dist/domain/domain-context/transformers/entity-builder.d.ts +1 -1
  173. package/dist/domain/domain-context/transformers/entity-builder.js +1 -1
  174. package/dist/domain/domain-context/transformers/then-builder.d.ts +1 -1
  175. package/dist/domain/domain-context/transformers/then-builder.js +1 -1
  176. package/dist/domain/domain-context/transformers/when-builder.d.ts +1 -2
  177. package/dist/domain/domain-context/transformers/when-builder.js +1 -1
  178. package/dist/domain/domain-context/undo-system.d.ts +1 -1
  179. package/dist/domain/domain-runtime/domain-context/component-reader.d.ts +1 -3
  180. package/dist/domain/domain-runtime/domain-context/component-reader.js +1 -1
  181. package/dist/domain/domain-runtime/domain-context/selectors.d.ts +1 -2
  182. package/dist/domain/domain-runtime/domain-context/selectors.js +1 -1
  183. package/dist/domain/domain-runtime/domain-runtime.d.ts +4 -4
  184. package/dist/domain/domain-runtime/spec/initialize.js +1 -1
  185. package/dist/domain/domain-runtime/spec/selectors.d.ts +2 -2
  186. package/dist/domain/domain-runtime/spec/selectors.js +1 -1
  187. package/dist/domain/domain-runtime/spec/types.d.ts +3 -3
  188. package/dist/domain/expressions/constant-expressions.d.ts +1 -3
  189. package/dist/domain/expressions/custom-expression.d.ts +1 -4
  190. package/dist/domain/expressions/memoize-expression.d.ts +1 -2
  191. package/dist/domain/expressions/prepare-domain-expressions.d.ts +1 -1
  192. package/dist/domain/index.d.ts +3 -2
  193. package/dist/domain/index.js +1 -1
  194. package/dist/domain/invariants/builtin-invariant.d.ts +1 -2
  195. package/dist/domain/invariants/custom-invariants.d.ts +1 -2
  196. package/dist/domain/invariants/invariants.d.ts +10 -4
  197. package/dist/domain/invariants/invariants.js +1 -1
  198. package/dist/domain/invariants/violation.d.ts +1 -1
  199. package/dist/domain/mocks/create-mock-domain-runtime.d.ts +3 -3
  200. package/dist/domain/mocks/create-mock-domain-runtime.js +1 -1
  201. package/dist/domain/project-modules/index.d.ts +1 -0
  202. package/dist/domain/project-modules/index.js +1 -0
  203. package/dist/domain/project-modules/project-modules.d.ts +41 -0
  204. package/dist/domain/project-modules/project-modules.js +1 -0
  205. package/dist/domain/projections/projected-entities-projections.d.ts +1 -2
  206. package/dist/domain/projections/snap-matching.d.ts +1 -2
  207. package/dist/domain/projections/snap-utils.d.ts +1 -2
  208. package/dist/domain/relations/all-of-type-relation.d.ts +1 -4
  209. package/dist/domain/relations/all-of-type-relation.js +1 -1
  210. package/dist/domain/relations/component-factories.d.ts +1 -2
  211. package/dist/domain/relations/composed-of.d.ts +1 -1
  212. package/dist/domain/relations/composed-of.js +1 -1
  213. package/dist/domain/relations/direct-relation.d.ts +1 -3
  214. package/dist/domain/relations/indirect-relation.d.ts +1 -4
  215. package/dist/domain/relations/indirect-relation.js +1 -1
  216. package/dist/domain/relations/reference-component.d.ts +1 -2
  217. package/dist/domain/relations/reference-component.js +1 -1
  218. package/dist/domain/relations/reference-field.d.ts +1 -1
  219. package/dist/domain/relations/relation-factory.d.ts +1 -3
  220. package/dist/domain/relations/relation-implementation.d.ts +1 -4
  221. package/dist/domain/system-components/admin-sidebar.d.ts +1 -1
  222. package/dist/domain/system-components/admin-sidebar.js +1 -1
  223. package/dist/domain/system-components/angle-indicator.d.ts +1 -1
  224. package/dist/domain/system-components/angle-indicator.js +1 -1
  225. package/dist/domain/system-components/application-config.d.ts +1 -1
  226. package/dist/domain/system-components/application-config.js +1 -1
  227. package/dist/domain/system-components/attribute-selection.js +1 -1
  228. package/dist/domain/system-components/autorotate-camera-component.d.ts +1 -1
  229. package/dist/domain/system-components/basic-sidebar-footer.d.ts +1 -1
  230. package/dist/domain/system-components/basic-sidebar-footer.js +1 -1
  231. package/dist/domain/system-components/bounding-box-component.d.ts +1 -1
  232. package/dist/domain/system-components/bounding-sphere-component.d.ts +1 -1
  233. package/dist/domain/system-components/camera-based-hidden-entity-object.js +1 -1
  234. package/dist/domain/system-components/camera-based-hidden-entity.js +1 -1
  235. package/dist/domain/system-components/canvas-config.d.ts +1 -1
  236. package/dist/domain/system-components/canvas-config.js +1 -1
  237. package/dist/domain/system-components/canvas-padding.d.ts +1 -1
  238. package/dist/domain/system-components/canvas-padding.js +1 -1
  239. package/dist/domain/system-components/canvas-preset-environment.d.ts +1 -1
  240. package/dist/domain/system-components/canvas-preset-environment.js +1 -1
  241. package/dist/domain/system-components/child-entity-selection.d.ts +1 -1
  242. package/dist/domain/system-components/client-side-image.js +1 -1
  243. package/dist/domain/system-components/collision-box-geometry.d.ts +1 -1
  244. package/dist/domain/system-components/collision-geometries.d.ts +1 -1
  245. package/dist/domain/system-components/collision-geometry.d.ts +1 -1
  246. package/dist/domain/system-components/collision-point-geometry.d.ts +1 -1
  247. package/dist/domain/system-components/common/dimension-indicator-schema.d.ts +1 -1
  248. package/dist/domain/system-components/common/dimension-indicator-schema.js +1 -1
  249. package/dist/domain/system-components/constraint.d.ts +1 -1
  250. package/dist/domain/system-components/create-blueprint.d.ts +1 -1
  251. package/dist/domain/system-components/custom-header.d.ts +1 -1
  252. package/dist/domain/system-components/custom-header.js +1 -1
  253. package/dist/domain/system-components/custom-scene-entity.d.ts +1 -1
  254. package/dist/domain/system-components/custom-scene-entity.js +1 -1
  255. package/dist/domain/system-components/custom-sidebar-footer.d.ts +1 -1
  256. package/dist/domain/system-components/custom-sidebar-footer.js +1 -1
  257. package/dist/domain/system-components/dimension-indicator.d.ts +1 -1
  258. package/dist/domain/system-components/dimension-indicator.js +1 -1
  259. package/dist/domain/system-components/distance-dimension-select.d.ts +1 -1
  260. package/dist/domain/system-components/distance-dimension-select.js +1 -1
  261. package/dist/domain/system-components/distance-dimension.d.ts +1 -1
  262. package/dist/domain/system-components/distance-dimension.js +1 -1
  263. package/dist/domain/system-components/drag-handle.d.ts +1 -1
  264. package/dist/domain/system-components/drag-handle.js +1 -1
  265. package/dist/domain/system-components/editable-angle-indicator.d.ts +1 -1
  266. package/dist/domain/system-components/editable-angle-indicator.js +1 -1
  267. package/dist/domain/system-components/editable-distance-dimension-indicator.d.ts +1 -1
  268. package/dist/domain/system-components/editable-distance-dimension-indicator.js +1 -1
  269. package/dist/domain/system-components/editable-offset-indicator.d.ts +1 -1
  270. package/dist/domain/system-components/editable-offset-indicator.js +1 -1
  271. package/dist/domain/system-components/editable-size-indicator.d.ts +1 -1
  272. package/dist/domain/system-components/editable-size-indicator.js +1 -1
  273. package/dist/domain/system-components/exit-tool-mode-fab.d.ts +1 -1
  274. package/dist/domain/system-components/exit-tool-mode-fab.js +1 -1
  275. package/dist/domain/system-components/finalize-action.d.ts +1 -1
  276. package/dist/domain/system-components/finalize-action.js +1 -1
  277. package/dist/domain/system-components/fixed-header.d.ts +1 -1
  278. package/dist/domain/system-components/fixed-header.js +1 -1
  279. package/dist/domain/system-components/floating-header.d.ts +1 -1
  280. package/dist/domain/system-components/floating-header.js +1 -1
  281. package/dist/domain/system-components/generic-dimension.d.ts +1 -1
  282. package/dist/domain/system-components/generic-dimension.js +1 -1
  283. package/dist/domain/system-components/hidden-header.d.ts +1 -1
  284. package/dist/domain/system-components/hidden-header.js +1 -1
  285. package/dist/domain/system-components/hidden-sidebar-footer.d.ts +1 -1
  286. package/dist/domain/system-components/hidden-sidebar-footer.js +1 -1
  287. package/dist/domain/system-components/horizontal-tabs.d.ts +1 -1
  288. package/dist/domain/system-components/horizontal-tabs.js +1 -1
  289. package/dist/domain/system-components/hotspot-drag-handle.d.ts +1 -1
  290. package/dist/domain/system-components/hotspot-drag-handle.js +1 -1
  291. package/dist/domain/system-components/list-selector-dimension-indicator.d.ts +1 -1
  292. package/dist/domain/system-components/list-selector-dimension-indicator.js +1 -1
  293. package/dist/domain/system-components/material-swatch.js +1 -1
  294. package/dist/domain/system-components/offset-anchors.d.ts +1 -1
  295. package/dist/domain/system-components/offset-anchors.js +1 -1
  296. package/dist/domain/system-components/offset-indicator.d.ts +1 -2
  297. package/dist/domain/system-components/offset-indicator.js +1 -1
  298. package/dist/domain/system-components/offset.d.ts +1 -1
  299. package/dist/domain/system-components/offset.js +1 -1
  300. package/dist/domain/system-components/other-action.d.ts +1 -1
  301. package/dist/domain/system-components/other-action.js +1 -1
  302. package/dist/domain/system-components/pivot-point.d.ts +1 -1
  303. package/dist/domain/system-components/pivot-point.js +1 -1
  304. package/dist/domain/system-components/price.js +1 -1
  305. package/dist/domain/system-components/projected-entities.d.ts +1 -1
  306. package/dist/domain/system-components/projected-entities.js +1 -1
  307. package/dist/domain/system-components/property-page.d.ts +1 -1
  308. package/dist/domain/system-components/property-page.js +1 -1
  309. package/dist/domain/system-components/read-sidebar-footer.d.ts +1 -1
  310. package/dist/domain/system-components/read-sidebar-footer.js +1 -1
  311. package/dist/domain/system-components/save-template-thumbnail.js +1 -1
  312. package/dist/domain/system-components/scene-entity-add-fab.js +1 -1
  313. package/dist/domain/system-components/scene-entity-delete-fab.js +1 -1
  314. package/dist/domain/system-components/scene-entity-local-material-override.js +1 -1
  315. package/dist/domain/system-components/scene-entity-material-override.js +1 -1
  316. package/dist/domain/system-components/scene-entity-navigation-hotspot.js +1 -1
  317. package/dist/domain/system-components/scene-entity-object-local-material-override.js +1 -1
  318. package/dist/domain/system-components/scene-entity-object-material-override.js +1 -1
  319. package/dist/domain/system-components/scene-entity-object-remote-material-override.js +1 -1
  320. package/dist/domain/system-components/scene-entity-object-transimissive-material-override.js +1 -1
  321. package/dist/domain/system-components/scene-entity-remote-material-override.js +1 -1
  322. package/dist/domain/system-components/scene-entity-select-hotspot.js +1 -1
  323. package/dist/domain/system-components/scene-entity-transimissive-material-override.js +1 -1
  324. package/dist/domain/system-components/sidebar-tabs.d.ts +1 -1
  325. package/dist/domain/system-components/sidebar-tabs.js +1 -1
  326. package/dist/domain/system-components/simple-summary.js +1 -1
  327. package/dist/domain/system-components/size.d.ts +1 -1
  328. package/dist/domain/system-components/size.js +1 -1
  329. package/dist/domain/system-components/sketching-draw.d.ts +1 -1
  330. package/dist/domain/system-components/sketching-draw.js +1 -1
  331. package/dist/domain/system-components/sketching-edit.d.ts +1 -1
  332. package/dist/domain/system-components/sketching-edit.js +1 -1
  333. package/dist/domain/system-components/sketching-line.d.ts +1 -1
  334. package/dist/domain/system-components/sketching-line.js +1 -1
  335. package/dist/domain/system-components/sketching-rectangle.d.ts +1 -1
  336. package/dist/domain/system-components/sketching-rectangle.js +1 -1
  337. package/dist/domain/system-components/sketching.d.ts +1 -1
  338. package/dist/domain/system-components/sketching.js +1 -1
  339. package/dist/domain/system-components/snap-axis.d.ts +1 -1
  340. package/dist/domain/system-components/snap-axis.js +1 -1
  341. package/dist/domain/system-components/snap-edge.d.ts +1 -1
  342. package/dist/domain/system-components/snap-edge.js +1 -1
  343. package/dist/domain/system-components/snap-plane.d.ts +1 -1
  344. package/dist/domain/system-components/snap-plane.js +1 -1
  345. package/dist/domain/system-components/snap-point.d.ts +1 -1
  346. package/dist/domain/system-components/snap-point.js +1 -1
  347. package/dist/domain/system-components/summary-component.js +1 -1
  348. package/dist/domain/system-components/tool-menu-fab.d.ts +1 -1
  349. package/dist/domain/system-components/tool-menu-fab.js +1 -1
  350. package/dist/domain/system-components/toolbar.d.ts +1 -1
  351. package/dist/domain/system-components/toolbar.js +1 -1
  352. package/dist/domain/system-components/universal-sidebar-footer.d.ts +1 -1
  353. package/dist/domain/system-components/universal-sidebar-footer.js +1 -1
  354. package/dist/domain/utils/eval-cache.d.ts +1 -2
  355. package/dist/domain/utils/memo-eval.d.ts +1 -3
  356. package/dist/editor/domain-editors/use-implementation-files.d.ts +7 -6
  357. package/dist/editor/domain-editors/use-implementation-files.js +1 -1
  358. package/dist/legacy/domain-cli/gen/configurator-builder.js +21 -8
  359. package/dist/legacy/domain-cli/utils/cache.d.ts +1 -1
  360. package/dist/legacy/domain-cli/utils/cache.js +1 -1
  361. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/frontend-admin.js +18 -19
  362. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/frontend-configurator.js +15 -16
  363. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/frontend-embedded-admin.js +22 -23
  364. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/frontend-embedded-configurator.js +15 -16
  365. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/generator-shared.d.ts +7 -2
  366. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/generator-shared.js +8 -12
  367. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/index.d.ts +1 -1
  368. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/index.js +1 -1
  369. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/webhook-builders.js +7 -7
  370. package/dist/phoenix/application-spec/resolve-deployment-data.d.ts +4 -3
  371. package/dist/phoenix/application-spec/resolve-deployment-data.js +2 -2
  372. package/dist/phoenix/commands/prepare-deployment-command.js +2 -2
  373. package/dist/phoenix/commands/prepare-local-environment-command.js +1 -1
  374. package/dist/phoenix/scripts/build-admin.js +1 -1
  375. package/dist/phoenix/services/prepare-development-environment.js +1 -1
  376. package/dist/phoenix/services/variant-file-session.js +1 -1
  377. package/dist/react-sdk/application-runtime/hooks/use-domain-application-props.d.ts +5 -2
  378. package/dist/react-sdk/application-runtime/hooks/use-spec.d.ts +1 -1
  379. package/dist/react-sdk/application-runtime/mocks/create-mock-application-runtime.d.ts +1 -1
  380. package/dist/react-sdk/application-runtime/mocks/create-mock-application-runtime.js +1 -1
  381. package/dist/react-sdk/application-runtime/runtime/create-application-runtime.d.ts +4 -4
  382. package/dist/webhook/builders/common.d.ts +3 -0
  383. package/dist/webhook/builders/webhook-builder.d.ts +1 -1
  384. package/dist/webhook/builders/webhook-builder.js +1 -1
  385. package/package.json +3 -3
  386. package/dist/domain/core/json-schema.js +0 -1
  387. package/dist/domain/core/reflection.js +0 -1
  388. /package/dist/domain/{core/enhanced-json-schema.js → application/assistant/assistant-manifest.js} +0 -0
  389. /package/dist/domain/{core/schema-validator.js → application/assistant/assistant-resolved-manifest.js} +0 -0
  390. /package/dist/domain/core/{alias.d.ts → model/alias.d.ts} +0 -0
  391. /package/dist/domain/core/{alias.js → model/alias.js} +0 -0
  392. /package/dist/domain/core/{common-definitions.d.ts → model/common-definitions.d.ts} +0 -0
  393. /package/dist/domain/core/{common-definitions.js → model/common-definitions.js} +0 -0
  394. /package/dist/domain/core/{component.js → model/component.js} +0 -0
  395. /package/dist/domain/core/{model.d.ts → model/model.d.ts} +0 -0
  396. /package/dist/domain/core/{model.js → model/model.js} +0 -0
  397. /package/dist/domain/core/{preset.d.ts → model/preset.d.ts} +0 -0
  398. /package/dist/domain/core/{preset.js → model/preset.js} +0 -0
  399. /package/dist/domain/core/{schema-validator-ajv.d.ts → schema/create-ajv-schema-validator.d.ts} +0 -0
  400. /package/dist/domain/core/{schema-validator-ajv.js → schema/create-ajv-schema-validator.js} +0 -0
  401. /package/dist/domain/core/{schema-validator-csp.d.ts → schema/create-csp-schema-validator.d.ts} +0 -0
  402. /package/dist/domain/core/{schema-validator-csp.js → schema/create-csp-schema-validator.js} +0 -0
  403. /package/dist/domain/core/{enhanced-json-schema.d.ts → schema/enhanced-json-schema.d.ts} +0 -0
  404. /package/dist/domain/core/{json-schema.d.ts → schema/extended-schema-validator.d.ts} +0 -0
  405. /package/dist/domain/core/{schema-validator.d.ts → schema/schema-validator.d.ts} +0 -0
@@ -1 +1 @@
1
- import{GraphQLBoolean as e,GraphQLID as t,GraphQLInputObjectType as n,GraphQLInterfaceType as i,GraphQLList as r,GraphQLNonNull as o,GraphQLObjectType as s,GraphQLSchema as a,GraphQLString as p,getNullableType as d,isInputType as l,isNonNullType as c,printSchema as h,validateSchema as f}from"graphql";import{isArray as u}from"@salsita-ai/common/utils";import{DiagnosticCode as y,diagnosticMessages as m}from"../../../../errors/index.js";import{ASSISTANT_HINTS as g}from"../../../raw-spec/index.js";import{createSchemaRefResolver as S,isNullableSchema as T,phxDefinitionRefName as w}from"../../common/index.js";import{GraphQLJSON as N,assistantFieldType as A}from"./assistant-field-type.js";let E="AnyDomainEntity",I="RootEntity",_="RecipeGroup",O="Recipe",v="DryRun",b="DryRunError",$="FieldOption",R={section:"childRecipes",component:"childEntityRecipes",mutation:"addChild"},j={section:"replaceRecipes",component:"replaceEntityRecipes",mutation:"replaceEntity"},M=new Set(["id","type","meta"]),D=new Set(["Query","Mutation","Navigation",_,O,v,b,$,"JSON","String","Int","Float","Boolean","ID"]),C=(e,t)=>{if(!t||0===t.length)return e;let n=`One of: ${t.map(e=>`"${e}"`).join(", ")}.`;return e?/[.!?]$/.test(e)?`${e} ${n}`:`${e}. ${n}`:n},U=new Set(["id","type"]),P="The raw stored value: a string, a message descriptor or a multilingual object.",k=(e,t)=>Object.entries(e).find(([e])=>e===t)?.[1],L=(e,t,{model:n,components:i})=>{let r=new Set([e,...[...n.aliases].filter(([,t])=>t.includes(e)).map(([e])=>e)]);return i.filter(({componentName:e,typeOrAlias:n})=>e===t&&r.has(n)).map(({instanceName:e})=>String(e))},W=(...e)=>g.filter(t=>e.some(e=>e?.includes(t))),F=(e,t,n,i)=>{let{model:r}=n,o=new Map,s=new Map;for(let[a,{groups:p,hints:d}]of Object.entries(e)){let e=r.entityTypes.find(e=>e===a),l=e?[e]:[...r.aliases].find(([e])=>e===a)?.[1];if(!l){i.at(a).error(y.ASSISTANT_UNKNOWN_TYPE,m.ASSISTANT_UNKNOWN_TYPE(t.section,a));continue}for(let[e,r]of(l.forEach(e=>s.set(e,W(s.get(e),d))),Object.entries(p))){let s=i.at(a,"groups",e),p=`${a}.groups.${e}`,d={groupId:r?.as??e,instanceName:e,...r?.description===void 0?{}:{description:r.description},dryRuns:r?.allowDryRuns??!0};for(let i of l){let r=L(i,t.component,n),l=o.get(i)??[],c=l.find(e=>e.group.groupId===d.groupId);r.includes(e)?c?s.error(y.ASSISTANT_DUPLICATE_RECIPE_GROUP,m.ASSISTANT_DUPLICATE_RECIPE_GROUP(t,i,d.groupId,[c.entry,p])):o.set(i,[...l,{group:d,entry:p,entryCtx:s}]):s.error(y.ASSISTANT_UNKNOWN_RECIPE_GROUP,m.ASSISTANT_UNKNOWN_RECIPE_GROUP(t,a,e,i,r))}}}let a=r.entityTypes.flatMap(e=>{let t=o.get(e);return t?[{entityType:e,groups:t}]:[]});return{groups:Object.fromEntries(a.map(({entityType:e,groups:t})=>[e,t.map(({group:e})=>e)])),hints:s,metaEntries:new Map(a.flatMap(({entityType:e,groups:[t]})=>t?[[e,t.entryCtx]]:[]))}},K=e=>`${e}Meta`,G={sameForAllInstances:e=>`All ${e} instances have the same recipe groups and recipes.`,constantDuringSession:()=>"They do not change during the session."},Y={sameForAllInstances:e=>`All ${e} instances have the same options.`,constantDuringSession:()=>"The options do not change during the session."},V=(e,t,n)=>e.map(e=>` ${t[e](n)}`).join(""),x=({section:e},{groups:t,hints:n},{entityType:i,purpose:s,recipeGroup:a})=>{let p=t.filter(({dryRuns:e})=>!e).map(({groupId:e})=>e);return 0===t.length?{}:{[e]:{type:new o(new r(new o(a))),description:`The recipe groups for ${s} this ${i}: ${t.map(({groupId:e})=>e).join(", ")}. A group is listed only while the configurator offers it on the entity.${p.length>0?` Recipes of these groups cannot be dry-run: ${p.join(", ")}.`:""}${V(n,G,i)}`}}},q=({entityType:e,childRecipes:t,replaceRecipes:n,optionsEdges:i},{recipeGroup:a,fieldOption:p})=>new s({name:K(e),fields:Object.assign(x(R,t,{entityType:e,purpose:"adding children to",recipeGroup:a}),x(j,n,{entityType:e,purpose:"replacing",recipeGroup:a}),...i.map(({options:{edgeName:t,field:n,validate:i,dryRuns:s},hints:a})=>({[t]:{type:new r(new o(p)),description:`The values "${n}" of this ${e} can take, as the configurator offers them in the current state of the entity. Null when the configurator does not offer a choice on this entity. ${i?`modify${e} rejects a "${n}" value that is not in the list.`:`modify${e} does not check "${n}" against the list.`}${s?"":" Its options cannot be dry-run."}${V(a,Y,e)}`}})))}),B=e=>Object.entries(e).map(([e,t])=>`${e} (${t.map(({groupId:e})=>e).join(", ")})`),z=e=>`${e.charAt(0).toUpperCase()+e.slice(1)}Result`,H=e=>{let t=(({anyOf:e,oneOf:t})=>[...e??[],...t??[]].filter(e=>"null"!==e.type))(e);return e.$ref||1!==t.length?e:t[0]},Q=(e,t)=>{let{type:n,enumValues:i,localized:r,description:s}=A(e,t),a=d(n),p=r||!l(a)?N:a;return{type:c(n)?new o(p):p,description:r?`${C(s,i)??""} ${P}`.trim():C(s,i)}},X=(e,t)=>{let n=(e=>{let t=H(e),n=t?.type==="array"&&t.items&&!u(t.items)?H(t.items):void 0,i=n??t;if(i?.$ref!==void 0&&"$DomainEntity"===w(i.$ref))return{target:i.references??E,list:void 0!==n}})(e);if(n)return{kind:"edge",...n,nullable:T(e,t),description:e.description};let{type:i,enumValues:r,localized:s,description:a}=A(e,t);return s?{kind:"value",type:c(i)?new o(N):N,description:`${a??""} ${P}`.trim()}:{kind:"value",type:i,description:C(a,r)}},J=(e,t)=>{let{type:n,enumValues:i,localized:r,description:o}=A(e,t);return{type:{kind:"value",type:n},localized:!0===r,description:o,enumValues:i}},Z=(e,t,n,i,r)=>{let o=t.startsWith("$")?((e,t,n,i)=>{let r=((e,t,{expressions:n,entityTypes:i})=>{let r=i.find(t=>t===e);for(let i of void 0===r?[e]:n.entityExpressions.get(r)?.shapeGroups??[]){let e=[...n.expressions.get(i)?.values()??[]].find(e=>e.name===t);if(e?.declaredSchema)return{implementation:e.implementation,declaredSchema:e.declaredSchema}}})(e.name,t,n);if(!r)return void i.error(y.ASSISTANT_UNKNOWN_FIELD,m.ASSISTANT_UNKNOWN_FIELD("entities",e.name,t));let{implementation:o}=r;if("violations"===o.kind)return void i.error(y.ASSISTANT_UNSUPPORTED_EXPRESSION,m.ASSISTANT_UNSUPPORTED_EXPRESSION(e.name,t));if("relation"===o.kind){let[{target:e,cardinality:t}]=o.params;return{type:{kind:"edge",target:e,cardinality:t},localized:!1,description:void 0}}return J(r.declaredSchema,n.resolveRef)})(e,t,i,r):((e,t,{resolveRef:n},i)=>{let r=Object.entries(e.shape.properties).find(([e])=>e===t)?.[1];return r?J(r,n):void i.error(y.ASSISTANT_UNKNOWN_FIELD,m.ASSISTANT_UNKNOWN_FIELD("entities",e.name,t))})(e,t,i,r);if(!o)return;let s=n?.as??(t.startsWith("$")?`_${t.slice(1)}`:t);return M.has(s)?void r.error(y.ASSISTANT_RESERVED_FIELD_NAME,m.ASSISTANT_RESERVED_FIELD_NAME(e.name,t,s)):{name:s,source:t,type:o.type,localized:o.localized,description:C(n?.description??o.description,o.enumValues),describedByManifest:n?.description!==void 0,enumValues:o.enumValues,valueDescription:n?.description??o.description}},ee=(e,t,n,i,r)=>{let o=new Map,s=new Set(n);for(let i of[...t.flat(),...n]){let t=o.get(i.name);t?t.source!==i.source?r.error(y.ASSISTANT_FIELD_NAME_CONFLICT,m.ASSISTANT_FIELD_NAME_CONFLICT(e,i.name,[t.source,i.source])):s.has(i)&&i.describedByManifest&&o.set(i.name,{...t,description:i.description,describedByManifest:!0,valueDescription:i.valueDescription}):o.set(i.name,i)}return[...o.values()].map(e=>{let t=e.enumValues&&i(e.source);return t?{...e,enumValues:t,description:C(e.valueDescription,t)}:e})},et=({target:e,cardinality:t},n)=>{let i=n(e);switch(t){case"1-1":return new o(i);case"0-1":return i;case"0-N":case"1-N":return new o(new r(new o(i)))}},en=(e,n,i)=>{let r={id:{type:new o(t),description:i?`Unique id of the entity, e.g. "${i}-1".`:void 0},type:{type:new o(p),description:i?`Entity type name, e.g. "${i}".`:void 0}};for(let t of e)r[t.name]={type:"edge"===t.type.kind?et(t.type,n):t.type.type,description:t.description};return r},ei=e=>Object.fromEntries(e.map(({name:e,source:t,localized:n})=>[e,n?{source:t,localized:!0}:{source:t}]));export const createAssistantSchema=(c,{model:u,states:g,phxDefinitions:T,expressions:w,components:M,actions:G},Y)=>{let V,x,H,J=Y.errors.length,et=Y.at("entities"),er=S(u.commonTypes,T),eo=u.rootEntityTypes[0]??u.entityTypes[0];for(let e of u.resolvedShapes.keys())D.has(e)&&Y.error(y.ASSISTANT_RESERVED_TYPE_NAME,m.ASSISTANT_RESERVED_TYPE_NAME(e,[...D]));let es=((e,t,n)=>{let i=new Map;for(let r of e){let e=[];for(let[i,o]of Object.entries(r.entries)){let s=Z(r,i,o,t,n.at(r.name,i));s&&e.push(s)}i.set(r.name,e)}return i})(((e,t,n)=>{let i=[];for(let[n,r]of t.resolvedShapes){let t=e[n];t&&i.push({name:n,shape:r,entries:t})}let r=new Set(t.resolvedShapes.keys());for(let t of Object.keys(e))r.has(t)||n.at(t).error(y.ASSISTANT_UNKNOWN_TYPE,m.ASSISTANT_UNKNOWN_TYPE("entities",t));return i})(c.entities??{},u,et),{resolveRef:er,expressions:w,entityTypes:u.entityTypes},et),ea=ee(E,[],es.get(E)??[],()=>void 0,Y),ep=new Map,ed=F(c.childRecipes??{},R,{model:u,components:M},Y.at(R.section)),el=F(c.replaceRecipes??{},j,{model:u,components:M},Y.at(j.section)),ec=ed.groups,eh=el.groups,ef=new Map,eu=e=>{let[t,...n]=[...u.aliases].find(([t])=>t===e)?.[1]??[];return(t&&0===n.length?ep.get(t):void 0)??eg.get(e)??em},ey=e=>ep.get(e)??eu(e),em=new i({name:E,description:"Every domain entity.",fields:()=>en(ea,ey,eo)}),eg=new Map([[E,em]]),eS=new Map([[E,ea]]);for(let e of u.aliases.keys()){if(e===E)continue;let t=ee(e,[ea],es.get(e)??[],()=>void 0,Y);eS.set(e,t),eg.set(e,new i({name:e,interfaces:[em],fields:()=>en(t,ey)}))}let eT={};for(let e of u.entityTypes){let t=[E,...[...u.aliases].filter(([t,n])=>t!==E&&n.includes(e)).map(([e])=>e)],n=[...u.resolvedShapes].find(([t])=>t===e)?.[1],i=ee(e,t.map(e=>eS.get(e)??[]),es.get(e)??[],e=>{let t=Object.entries(n?.properties??{}).find(([t])=>t===e)?.[1];return t&&A(t,er).enumValues},Y);eT[e]=ei(i),ep.set(e,new s({name:e,interfaces:t.flatMap(e=>eg.get(e)??[]),fields:()=>{let t=ef.get(e);return{...en(i,ey),...t?{meta:{type:new o(t),description:"What the configurator offers on this entity besides its fields."}}:{}}}}))}let ew=((e,t,n)=>{let i=new Set;for(let r of Object.keys(e)){let e=t.entityTypes.find(e=>e===r),o=e?[e]:[...t.aliases].find(([e])=>e===r)?.[1];o?o.forEach(e=>i.add(e)):n.at(r).error(y.ASSISTANT_UNKNOWN_TYPE,m.ASSISTANT_UNKNOWN_TYPE("deletable",r))}return t.entityTypes.filter(e=>i.has(e))})(c.deletable??{},u,Y.at("deletable")),eN=((e,t,n)=>{let{model:i}=t,r=((e,t,n)=>{let i=new Map;for(let[r,o]of Object.entries(e)){let e=t.entityTypes.find(e=>e===r),s=e?[e]:[...t.aliases].find(([e])=>e===r)?.[1],a=[...t.resolvedShapes].find(([e])=>e===r)?.[1];if(!s||!a){n.at(r).error(y.ASSISTANT_UNKNOWN_TYPE,m.ASSISTANT_UNKNOWN_TYPE("writable",r));continue}for(let e of Object.keys(o)){let t=n.at(r,e);e.startsWith("$")||U.has(e)?t.error(y.ASSISTANT_NOT_WRITABLE,m.ASSISTANT_NOT_WRITABLE(r,e)):k(a.properties,e)?s.forEach(t=>{let n=i.get(t)??new Map;i.set(t,n.has(e)?n:n.set(e,r))}):t.error(y.ASSISTANT_UNKNOWN_FIELD,m.ASSISTANT_UNKNOWN_FIELD("writable",r,e))}}return i})(e,i,n);return i.entityTypes.flatMap(e=>{let o=[...i.resolvedShapes].find(([t])=>t===e)?.[1],s=[...r.get(e)??[]].flatMap(([i,r])=>{let s=o&&k(o.properties,i);return(s&&((e,{property:t,writableKey:n},i,{resolveRef:r,exposed:o,sources:s},a)=>{let p=Object.entries(k(s,e)??{}),c=o.get(e)?.find(({source:e})=>e===t)?.name??p.find(([,{source:e}])=>e===t)?.[0],h=void 0===c?p.find(([e])=>e===t)?.[1]:void 0;if(h)return void a.at(n,t).error(y.ASSISTANT_FIELD_NAME_CONFLICT,m.ASSISTANT_FIELD_NAME_CONFLICT(e,t,[h.source,t],`${n}.${t}`));let{type:f,enumValues:u,localized:g,description:S}=A(i,r),T=d(f),w=c??t,E=void 0===c?C(S,u):void 0;return g?{name:w,property:t,type:N,description:E?`${E} ${P}`:P}:{name:w,property:t,type:l(T)?T:N,description:E}})(e,{property:i,writableKey:r},s,t,n))??[]});return s.length>0?[{entityType:e,fields:s}]:[]})})(c.writable??{},{model:u,resolveRef:er,exposed:es,sources:eT},Y.at("writable")),eA=((e,t,n,i)=>{let{model:r}=n,o=new Map;for(let[s,a]of Object.entries(e)){let e=r.entityTypes.find(e=>e===s),p=e?[e]:[...r.aliases].find(([e])=>e===s)?.[1]??[];for(let[e,r]of Object.entries(a)){let a=r?.options;if(!a)continue;let d=i.at(s,e,"options"),l=`${s}.${e}`;for(let i of p){let r=t.find(e=>e.entityType===i)?.fields.find(t=>t.property===e);if(!r)continue;let s=a.as??`${r.name}Options`,p=L(i,a.componentType,n),c=o.get(i)??[],h=c.find(e=>e.options.edgeName===s||e.options.field===r.name);if(p.includes(a.instanceName))if(s===R.section||s===j.section)d.error(y.ASSISTANT_RESERVED_OPTIONS_EDGE_NAME,m.ASSISTANT_RESERVED_OPTIONS_EDGE_NAME(l,s,r.name));else if(h)d.error(y.ASSISTANT_DUPLICATE_OPTIONS_EDGE,m.ASSISTANT_DUPLICATE_OPTIONS_EDGE(i,h.options.edgeName===s?{edgeName:s}:{field:r.name},[h.entry,l]));else{let e={field:r.name,edgeName:s,componentType:a.componentType,instanceName:a.instanceName,validate:a.validate??!0,dryRuns:a.allowDryRuns??!0};o.set(i,[...c,{options:e,hints:W(a.hints),entry:l,entryCtx:d}])}else d.error(y.ASSISTANT_UNKNOWN_OPTIONS_COMPONENT,m.ASSISTANT_UNKNOWN_OPTIONS_COMPONENT(l,a,i,p))}}}return o})(c.writable??{},eN,{model:u,components:M},Y.at("writable"));var eE,eI,e_,eO=[ed.metaEntries,el.metaEntries,new Map([...eA].flatMap(([e,[t]])=>t?[[e,t.entryCtx]]:[]))];for(let e of u.entityTypes){let t=eO.flatMap(t=>t.get(e)??[])[0],n=K(e);t&&[...u.resolvedShapes.keys()].some(e=>e===n)&&t.error(y.ASSISTANT_META_TYPE_NAME_CONFLICT,m.ASSISTANT_META_TYPE_NAME_CONFLICT(e,n))}let ev=(eE=()=>eu(eg.has(I)?I:E),eI=()=>eu(E),V=new s({name:b,description:"One reason a change cannot be made right now.",fields:{type:{type:new o(p),description:'Kind of the problem, or "uncaught".'},entityId:{type:t,description:"The entity the problem is on, when it is on one."},message:{type:p,description:"The problem as the configurator words it for the user."}}}),new s({name:v,description:"What using a recipe or writing an option would do, tried out on the configuration the query reads. Nothing is changed.",fields:()=>({ok:{type:new o(e),description:"Whether the change would succeed on the configuration the query reads."},root:{type:eE(),description:"The root entity of the configuration as it would be after the change; null when ok is false. Everything selected under it reads that configuration."},changedEntities:{type:new o(new r(new o(eI()))),description:"Every entity the change would add or modify, read from that configuration; empty when ok is false. An entity whose id the configuration does not have yet would be added, and its id may differ in the real mutation. An entity that is written to is listed even when it gets the values it already has."},deletedEntityIds:{type:new o(new r(new o(t))),description:"The ids of the entities the change would remove; empty when ok is false."},sideEffects:{type:new o(new r(new o(p))),description:"What the configurator would do beyond the change itself, such as parts it would add or replace, in its own words; empty when ok is false."},errors:{type:new o(new r(new o(V))),description:"Why the change cannot be made; empty when ok is true."}})})),eb={recipeGroup:(e_=[...Object.keys(ec).length>0?[R.mutation]:[],...Object.keys(eh).length>0?[j.mutation]:[]],x=e_.join(" or "),H=new s({name:O,description:"One recipe of a recipe group: something that can be added to the entity, or something the entity can be replaced with, depending on the edge the group is listed under.",fields:{key:{type:new o(p),description:`Identifies the recipe within its group; pass it to ${x} as recipeKey. Keys can change with the configuration and with the language, so read them from the listing rather than remembering them.`},name:{type:new o(p),description:"Name shown to the user."},description:{type:p},imageUrl:{type:p,description:"Thumbnail shown to the user."},dryRun:{type:ev,description:"Tries the recipe out. Each selected dry-run costs a full recalculation, so select it only on the recipes you are deciding between. Null for a group whose recipes cannot be dry-run."}}}),new s({name:_,description:"A group of recipes of an entity, as the configurator offers them to the user.",fields:{groupId:{type:new o(p),description:`Identifies the group on its entity; pass it to ${x} as recipeGroupId.`},name:{type:new o(p),description:"Name shown to the user."},description:{type:p},recipes:{type:new o(new r(new o(H)))}}})),fieldOption:new s({name:$,description:"One choice of a field, as the configurator offers it to the user.",fields:{value:{type:new o(N),description:"The value to write to the field."},name:{type:p,description:"Name shown to the user."},description:{type:p},imageUrl:{type:p,description:"Image shown to the user."},color:{type:p,description:'Color shown to the user, as "#rrggbb".'},dryRun:{type:ev,description:"Tries writing the value to the field. Each selected dry-run costs a full recalculation, so select it only on the options you are deciding between. Null for a field whose options cannot be dry-run."}}})};for(let e of u.entityTypes){let t=k(ec,e)??[],n=k(eh,e)??[],i=eA.get(e)??[];(t.length>0||n.length>0||i.length>0)&&ef.set(e,q({entityType:e,childRecipes:{groups:t,hints:ed.hints.get(e)??[]},replaceRecipes:{groups:n,hints:el.hints.get(e)??[]},optionsEdges:i},eb))}let e$=Object.fromEntries(u.entityTypes.flatMap(e=>{let t=eA.get(e);return t?[[e,t.map(({options:e})=>e)]]:[]})),eR=((e,{actions:t,resolveRef:n,builtInMutations:i,typeNames:r},o)=>{let s=[],a=[...t.values()].map(e=>String(e.name));for(let[p,d]of Object.entries(e)){let e=o.at(p),l=[...t.values()].find(e=>e.name===p);if(!l){e.error(y.ASSISTANT_UNKNOWN_ACTION,m.ASSISTANT_UNKNOWN_ACTION(p,a));continue}let c=d?.as??p,h=s.find(e=>e.fieldName===c),f=z(c);if(i.has(c)||h){e.error(y.ASSISTANT_MUTATION_NAME_CONFLICT,m.ASSISTANT_MUTATION_NAME_CONFLICT(p,c,h?`"assistant.actions.${h.actionName}" already exposes`:"the built-in mutation of that name already takes"));continue}if(r.has(f)||s.some(e=>z(e.fieldName)===f)){e.error(y.ASSISTANT_ACTION_RESULT_TYPE_CONFLICT,m.ASSISTANT_ACTION_RESULT_TYPE_CONFLICT(p,c,f));continue}s.push({fieldName:c,actionName:p,description:d?.description??l.description,args:Object.fromEntries(Object.entries(l.params).map(([e,{schema:t}])=>[e,Q(t,n)])),result:Object.fromEntries(Object.entries(l.result).map(([e,t])=>[e,X(t,n)]))})}return s})(c.actions??{},{actions:G,resolveRef:er,builtInMutations:new Set(["deleteEntity",R.mutation,j.mutation,...eN.map(({entityType:e})=>`modify${e}`)]),typeNames:new Set([...D,...u.resolvedShapes.keys(),...ef.keys()])},Y.at("actions"));if(Y.errors.length>J)return;let ej=((e,t)=>{let n;try{let t=e();if(n=f(t).map(e=>e.message),0===n.length)return h(t)}catch(e){n=[e instanceof Error?e.message:String(e)]}t.error(y.ASSISTANT_INVALID_SCHEMA,m.ASSISTANT_INVALID_SCHEMA(n))})(()=>{var e,i;let d;return new a({query:(e=eu(eg.has(I)?I:E),i=eu(E),d=(e=>{let t={};for(let[n,i,r]of[["navigationState","Active navigation state.",e.navigationStates],["viewState","Active view state.",e.viewStates],["toolState","Active tool state.",e.toolStates]])r.length>1&&(t[n]={type:new o(p),description:C(i,r)});if(0!==Object.keys(t).length)return new s({name:"Navigation",description:"The active UI states of the configurator.",fields:t})})(g),new s({name:"Query",fields:{root:{type:new o(e),description:"The root entity of the configuration."},entities:{type:new o(new r(i)),args:{ids:{type:new r(new o(t))}},description:`Every entity of the configuration, or, when ids are given, those entities in the same order with null for an unknown id. Ids have the form "<Type>-<number>"${eo?`, e.g. "${eo}-1"`:""}; any other id is an error.`},selectedEntity:{type:new o(i),description:"The selected entity, or the root entity when nothing is selected."},...d?{navigation:{type:new o(d)}}:{}}})),mutation:(({deletableTypes:e,writableTypes:i,childRecipes:a,replaceRecipes:d,actionFields:l,objectTypes:c,anyDomainEntity:h,targetOutputType:f})=>{let u,y;if(0!==e.length||0!==i.length||0!==Object.keys(a).length||0!==Object.keys(d).length||0!==l.length)return new s({name:"Mutation",fields:Object.assign(0===e.length?{}:{deleteEntity:{type:new o(new r(new o(t))),args:{id:{type:new o(t)}},description:`Deletes the entity with the given id, together with the entities composed into it, and returns the ids of every entity the deletion removed, the given one first. Deletable entity types: ${e.join(", ")}. Nothing can be read from removed entities afterwards, so query what you need from them before deleting.`}},0===(u=B(a)).length?{}:{addChild:{type:new o(new r(new o(h))),args:{parentId:{type:new o(t)},recipeGroupId:{type:new o(p)},recipeKey:{type:new o(p)}},description:`Adds a child to the entity with the id parentId by one recipe of one of its recipe groups. Entity types with recipe groups: ${u.join("; ")}. Read the groupId and the recipe key from "meta { childRecipes }" of the parent. Returns every entity the change added, the recipe's own first and then whatever the configurator added in response, such as a part the new child needs; the list is empty when the configurator removed them again.`}},0===(y=B(d)).length?{}:{replaceEntity:{type:new o(new r(new o(h))),args:{entityId:{type:new o(t)},recipeGroupId:{type:new o(p)},recipeKey:{type:new o(p)}},description:`Replaces the entity with the id entityId by one recipe of one of its replace recipe groups. Entity types with replace recipe groups: ${y.join("; ")}. Read the groupId and the recipe key from "meta { replaceRecipes }" of the entity. The replacement is a new entity with a new id: the id passed in no longer exists afterwards, and the replacement has the field values of its recipe, not those of the entity it replaces. Returns every entity the change added, the replacement first and then whatever the configurator added in response, such as a part the replacement needs; the list is empty when the configurator removed them again.`}},...i.flatMap(e=>{let i=c.get(e.entityType);return i?[(({entityType:e,fields:i},r)=>{let s=Object.fromEntries(i.map(({name:e,type:t,description:n})=>[e,{type:t,description:n}]));return{[`modify${e}`]:{type:r,args:{id:{type:new o(t)},delta:{type:new o(new n({name:`${e}Delta`,fields:s}))}},description:`Changes writable fields of the one ${e} with the given id: ${i.map(({name:e})=>e).join(", ")}. The delta sets only the fields it names and needs at least one; values are in stored units, as the field descriptions say. Returns the entity as it is after the change, including what the configurator adjusted in response, or null when the change caused the entity to be removed.`}}})(e,i)]:[]}),Object.fromEntries(l.map(e=>[e.fieldName,{type:new o(new s({name:z(e.fieldName),description:`What ${e.fieldName} returns, read from the configuration after the change.`,fields:()=>Object.fromEntries(Object.entries(e.result).map(([e,t])=>[e,{type:"edge"===t.kind?(({target:e,list:t,nullable:n},i)=>{let s=t?new r(new o(i(e))):i(e);return n?s:new o(s)})(t,f):t.type,description:t.description}]))})),args:e.args,description:e.description}])))})})({deletableTypes:ew,writableTypes:eN,childRecipes:ec,replaceRecipes:eh,actionFields:eR,objectTypes:ep,anyDomainEntity:eu(E),targetOutputType:ey}),types:[...eg.values(),...ep.values()]})},Y);return void 0===ej?void 0:{sdl:ej,fields:eT,deletableTypes:ew,writableFields:Object.fromEntries(eN.map(({entityType:e,fields:t})=>[e,Object.fromEntries(t.map(({name:e,property:t})=>[e,t]))])),childRecipes:ec,replaceRecipes:eh,fieldOptions:e$,actions:Object.fromEntries(eR.map(({fieldName:e,actionName:t})=>[e,t]))}};
1
+ import{isArray as e}from"@salsita-ai/common/utils";import{buildAssistantManifest as t}from"#package/domain";import{DiagnosticCode as r,diagnosticMessages as i}from"../../../../errors/index.js";import{ASSISTANT_HINTS as n}from"../../../raw-spec/index.js";import{createSchemaRefResolver as s,isNullableSchema as o,phxDefinitionRefName as a}from"../../common/index.js";import{resolveAssistantFieldType as l}from"./assistant-field-type.js";let p="AnyDomainEntity",S={section:"childRecipes",component:"childEntityRecipes",mutation:"addChild"},N={section:"replaceRecipes",component:"replaceEntityRecipes",mutation:"replaceEntity"},T=new Set(["id","type","meta"]),d=new Set(["Query","Mutation","Navigation","RecipeGroup","Recipe","DryRun","DryRunError","FieldOption","JSON","String","Int","Float","Boolean","ID"]),c=(e,t)=>{if(!t||0===t.length)return e;let r=`One of: ${t.map(e=>`"${e}"`).join(", ")}.`;return e?/[.!?]$/.test(e)?`${e} ${r}`:`${e}. ${r}`:r},f=new Set(["id","type"]),m="The raw stored value: a string, a message descriptor or a multilingual object.",A=(e,t)=>Object.entries(e).find(([e])=>e===t)?.[1],u=(e,t,{model:r,components:i})=>{let n=new Set([e,...[...r.aliases].filter(([,t])=>t.includes(e)).map(([e])=>e)]);return i.filter(({componentName:e,typeOrAlias:r})=>e===t&&n.has(r)).map(({instanceName:e})=>String(e))},_=(...e)=>n.filter(t=>e.some(e=>e?.includes(t))),E=(e,t,n,s)=>{let{model:o}=n,a=new Map,l=new Map;for(let[p,{groups:S,hints:N}]of Object.entries(e)){let e=o.entityTypes.find(e=>e===p),T=e?[e]:[...o.aliases].find(([e])=>e===p)?.[1];if(!T){s.at(p).error(r.ASSISTANT_UNKNOWN_TYPE,i.ASSISTANT_UNKNOWN_TYPE(t.section,p));continue}for(let[e,o]of(T.forEach(e=>l.set(e,_(l.get(e),N))),Object.entries(S))){let l=s.at(p,"groups",e),S=`${p}.groups.${e}`,N={groupId:o?.as??e,instanceName:e,...o?.description===void 0?{}:{description:o.description},dryRuns:o?.allowDryRuns??!0};for(let s of T){let o=u(s,t.component,n),T=a.get(s)??[],d=T.find(e=>e.group.groupId===N.groupId);o.includes(e)?d?l.error(r.ASSISTANT_DUPLICATE_RECIPE_GROUP,i.ASSISTANT_DUPLICATE_RECIPE_GROUP(t,s,N.groupId,[d.entry,S])):a.set(s,[...T,{group:N,entry:S,entryCtx:l}]):l.error(r.ASSISTANT_UNKNOWN_RECIPE_GROUP,i.ASSISTANT_UNKNOWN_RECIPE_GROUP(t,p,e,s,o))}}}let p=o.entityTypes.flatMap(e=>{let t=a.get(e);return t?[{entityType:e,groups:t}]:[]});return{groups:Object.fromEntries(p.map(({entityType:e,groups:t})=>[e,t.map(({group:e})=>e)])),hints:l,metaEntries:new Map(p.flatMap(({entityType:e,groups:[t]})=>t?[[e,t.entryCtx]]:[]))}},I=e=>`${e}Meta`,O=e=>`${e.charAt(0).toUpperCase()+e.slice(1)}Result`,y=e=>{let t=(({anyOf:e,oneOf:t})=>[...e??[],...t??[]].filter(e=>"null"!==e.type))(e);return e.$ref||1!==t.length?e:t[0]},h=(e,t)=>{let{type:r,enumValues:i,localized:n,description:s}=l(e,t),o={...r,nonNull:!1},a=n?`${c(s,i)??""} ${m}`.trim():c(s,i);return{type:{...n?{kind:"scalar",name:"JSON",nonNull:!1}:o,nonNull:r.nonNull},...void 0===a?{}:{description:a}}},g=(t,r)=>{let i=(t=>{let r=y(t),i=r?.type==="array"&&r.items&&!e(r.items)?y(r.items):void 0,n=i??r;if(n?.$ref!==void 0&&"$DomainEntity"===a(n.$ref))return{target:n.references??p,list:void 0!==i}})(t);if(i)return{kind:"edge",...i,nullable:o(t,r),...void 0===t.description?{}:{description:t.description}};let{type:n,enumValues:s,localized:S,description:N}=l(t,r),T=c(N,s);return S?{kind:"value",type:{kind:"scalar",name:"JSON",nonNull:n.nonNull},description:`${N??""} ${m}`.trim()}:{kind:"value",type:n,...void 0===T?{}:{description:T}}},v=(e,t)=>{let{type:r,enumValues:i,localized:n,description:s}=l(e,t);return{type:{kind:"value",type:r},localized:!0===n,description:s,enumValues:i}},R=(e,t,n,s,o)=>{let a=t.startsWith("$")?((e,t,n,s)=>{let o=((e,t,{expressions:r,entityTypes:i})=>{let n=i.find(t=>t===e);for(let i of void 0===n?[e]:r.entityExpressions.get(n)?.shapeGroups??[]){let e=[...r.expressions.get(i)?.values()??[]].find(e=>e.name===t);if(e?.declaredSchema)return{implementation:e.implementation,declaredSchema:e.declaredSchema}}})(e.name,t,n);if(!o)return void s.error(r.ASSISTANT_UNKNOWN_FIELD,i.ASSISTANT_UNKNOWN_FIELD("entities",e.name,t));let{implementation:a}=o;if("violations"===a.kind)return void s.error(r.ASSISTANT_UNSUPPORTED_EXPRESSION,i.ASSISTANT_UNSUPPORTED_EXPRESSION(e.name,t));if("relation"===a.kind){let[{target:e,cardinality:t}]=a.params;return{type:{kind:"edge",target:e,cardinality:t},localized:!1,description:void 0}}return v(o.declaredSchema,n.resolveRef)})(e,t,s,o):((e,t,{resolveRef:n},s)=>{let o=Object.entries(e.shape.properties).find(([e])=>e===t)?.[1];return o?v(o,n):void s.error(r.ASSISTANT_UNKNOWN_FIELD,i.ASSISTANT_UNKNOWN_FIELD("entities",e.name,t))})(e,t,s,o);if(!a)return;let l=n?.as??(t.startsWith("$")?`_${t.slice(1)}`:t);return T.has(l)?void o.error(r.ASSISTANT_RESERVED_FIELD_NAME,i.ASSISTANT_RESERVED_FIELD_NAME(e.name,t,l)):{name:l,source:t,type:a.type,localized:a.localized,description:c(n?.description??a.description,a.enumValues),describedByManifest:n?.description!==void 0,enumValues:a.enumValues,valueDescription:n?.description??a.description}},M=(e,t,n,s,o)=>{let a=new Map,l=new Set(n);for(let s of[...t.flat(),...n]){let t=a.get(s.name);t?t.source!==s.source?o.error(r.ASSISTANT_FIELD_NAME_CONFLICT,i.ASSISTANT_FIELD_NAME_CONFLICT(e,s.name,[t.source,s.source])):l.has(s)&&s.describedByManifest&&a.set(s.name,{...t,description:s.description,describedByManifest:!0,valueDescription:s.valueDescription}):a.set(s.name,s)}return[...a.values()].map(e=>{let t=e.enumValues&&s(e.source);return t?{...e,enumValues:t,description:c(e.valueDescription,t)}:e})};export const resolveAssistantManifest=(e,{model:t,states:n,phxDefinitions:o,expressions:a,components:T,actions:y},v)=>{let b=v.errors.length,D=v.at("entities"),C=s(t.commonTypes,o);for(let e of t.resolvedShapes.keys())d.has(e)&&v.error(r.ASSISTANT_RESERVED_TYPE_NAME,i.ASSISTANT_RESERVED_TYPE_NAME(e,[...d]));let P=((e,t,r)=>{let i=new Map;for(let n of e){let e=[];for(let[i,s]of Object.entries(n.entries)){let o=R(n,i,s,t,r.at(n.name,i));o&&e.push(o)}i.set(n.name,e)}return i})(((e,t,n)=>{let s=[];for(let[r,i]of t.resolvedShapes){let t=e[r];t&&s.push({name:r,shape:i,entries:t})}let o=new Set(t.resolvedShapes.keys());for(let t of Object.keys(e))o.has(t)||n.at(t).error(r.ASSISTANT_UNKNOWN_TYPE,i.ASSISTANT_UNKNOWN_TYPE("entities",t));return s})(e.entities??{},t,D),{resolveRef:C,expressions:a,entityTypes:t.entityTypes},D),U=M(p,[],P.get(p)??[],()=>void 0,v),j=new Map([[p,U]]);for(let e of t.aliases.keys())e!==p&&j.set(e,M(e,[U],P.get(e)??[],()=>void 0,v));for(let e of t.entityTypes){let r=[p,...[...t.aliases].filter(([t,r])=>t!==p&&r.includes(e)).map(([e])=>e)],i=[...t.resolvedShapes].find(([t])=>t===e)?.[1];j.set(e,M(e,r.map(e=>j.get(e)??[]),P.get(e)??[],e=>{let t=Object.entries(i?.properties??{}).find(([t])=>t===e)?.[1];return t&&l(t,C).enumValues},v))}let L=Object.fromEntries(t.entityTypes.map(e=>[e,Object.fromEntries((j.get(e)??[]).map(({name:e,source:t,localized:r})=>[e,r?{source:t,localized:!0}:{source:t}]))])),$=E(e.childRecipes??{},S,{model:t,components:T},v.at("childRecipes")),w=E(e.replaceRecipes??{},N,{model:t,components:T},v.at("replaceRecipes")),W=((e,t,n)=>{let s=new Set;for(let o of Object.keys(e)){let e=t.entityTypes.find(e=>e===o),a=e?[e]:[...t.aliases].find(([e])=>e===o)?.[1];a?a.forEach(e=>s.add(e)):n.at(o).error(r.ASSISTANT_UNKNOWN_TYPE,i.ASSISTANT_UNKNOWN_TYPE("deletable",o))}return t.entityTypes.filter(e=>s.has(e))})(e.deletable??{},t,v.at("deletable")),F=((e,t,n)=>{let{model:s}=t,o=((e,t,n)=>{let s=new Map;for(let[o,a]of Object.entries(e)){let e=t.entityTypes.find(e=>e===o),l=e?[e]:[...t.aliases].find(([e])=>e===o)?.[1],p=[...t.resolvedShapes].find(([e])=>e===o)?.[1];if(!l||!p){n.at(o).error(r.ASSISTANT_UNKNOWN_TYPE,i.ASSISTANT_UNKNOWN_TYPE("writable",o));continue}for(let e of Object.keys(a)){let t=n.at(o,e);e.startsWith("$")||f.has(e)?t.error(r.ASSISTANT_NOT_WRITABLE,i.ASSISTANT_NOT_WRITABLE(o,e)):A(p.properties,e)?l.forEach(t=>{let r=s.get(t)??new Map;s.set(t,r.has(e)?r:r.set(e,o))}):t.error(r.ASSISTANT_UNKNOWN_FIELD,i.ASSISTANT_UNKNOWN_FIELD("writable",o,e))}}return s})(e,s,n);return s.entityTypes.flatMap(e=>{let a=[...s.resolvedShapes].find(([t])=>t===e)?.[1],p=[...o.get(e)??[]].flatMap(([s,o])=>{let p=a&&A(a.properties,s);return(p&&((e,{property:t,writableKey:n},s,{resolveRef:o,exposed:a,sources:p},S)=>{let N=Object.entries(A(p,e)??{}),T=a.get(e)?.find(({source:e})=>e===t)?.name??N.find(([,{source:e}])=>e===t)?.[0],d=void 0===T?N.find(([e])=>e===t)?.[1]:void 0;if(d)return void S.at(n,t).error(r.ASSISTANT_FIELD_NAME_CONFLICT,i.ASSISTANT_FIELD_NAME_CONFLICT(e,t,[d.source,t],`${n}.${t}`));let{type:f,enumValues:u,localized:_,description:E}=l(s,o),I={...f,nonNull:!1},O=T??t,y=void 0===T?c(E,u):void 0;return _?{name:O,property:t,type:{kind:"scalar",name:"JSON",nonNull:!1},description:y?`${y} ${m}`:m}:{name:O,property:t,type:I,...void 0===y?{}:{description:y}}})(e,{property:s,writableKey:o},p,t,n))??[]});return p.length>0?[{entityType:e,fields:p}]:[]})})(e.writable??{},{model:t,resolveRef:C,exposed:P,sources:L},v.at("writable")),k=((e,t,n,s)=>{let{model:o}=n,a=new Map;for(let[l,p]of Object.entries(e)){let e=o.entityTypes.find(e=>e===l),T=e?[e]:[...o.aliases].find(([e])=>e===l)?.[1]??[];for(let[e,o]of Object.entries(p)){let p=o?.options;if(!p)continue;let d=s.at(l,e,"options"),c=`${l}.${e}`;for(let s of T){let o=t.find(e=>e.entityType===s)?.fields.find(t=>t.property===e);if(!o)continue;let l=p.as??`${o.name}Options`,T=u(s,p.componentType,n),f=a.get(s)??[],m=f.find(e=>e.options.edgeName===l||e.options.field===o.name);if(T.includes(p.instanceName))if(l===S.section||l===N.section)d.error(r.ASSISTANT_RESERVED_OPTIONS_EDGE_NAME,i.ASSISTANT_RESERVED_OPTIONS_EDGE_NAME(c,l,o.name));else if(m)d.error(r.ASSISTANT_DUPLICATE_OPTIONS_EDGE,i.ASSISTANT_DUPLICATE_OPTIONS_EDGE(s,m.options.edgeName===l?{edgeName:l}:{field:o.name},[m.entry,c]));else{let e={field:o.name,edgeName:l,componentType:p.componentType,instanceName:p.instanceName,validate:p.validate??!0,dryRuns:p.allowDryRuns??!0};a.set(s,[...f,{options:e,hints:_(p.hints),entry:c,entryCtx:d}])}else d.error(r.ASSISTANT_UNKNOWN_OPTIONS_COMPONENT,i.ASSISTANT_UNKNOWN_OPTIONS_COMPONENT(c,p,s,T))}}}return a})(e.writable??{},F,{model:t,components:T},v.at("writable"));var K=[$.metaEntries,w.metaEntries,new Map([...k].flatMap(([e,[t]])=>t?[[e,t.entryCtx]]:[]))];for(let e of t.entityTypes){let n=K.flatMap(t=>t.get(e)??[])[0],s=I(e);n&&[...t.resolvedShapes.keys()].some(e=>e===s)&&n.error(r.ASSISTANT_META_TYPE_NAME_CONFLICT,i.ASSISTANT_META_TYPE_NAME_CONFLICT(e,s))}let Y=t.entityTypes.filter(e=>($.groups[e]?.length??0)>0||(w.groups[e]?.length??0)>0||(k.get(e)?.length??0)>0).map(I),V=((e,{actions:t,resolveRef:n,builtInMutations:s,typeNames:o},a)=>{let l=[],p=[...t.values()].map(e=>String(e.name));for(let[S,N]of Object.entries(e)){let e=a.at(S),T=[...t.values()].find(e=>e.name===S);if(!T){e.error(r.ASSISTANT_UNKNOWN_ACTION,i.ASSISTANT_UNKNOWN_ACTION(S,p));continue}let d=N?.as??S,c=l.find(e=>e.fieldName===d),f=O(d);if(s.has(d)||c){e.error(r.ASSISTANT_MUTATION_NAME_CONFLICT,i.ASSISTANT_MUTATION_NAME_CONFLICT(S,d,c?`"assistant.actions.${c.actionName}" already exposes`:"the built-in mutation of that name already takes"));continue}if(o.has(f)||l.some(e=>O(e.fieldName)===f)){e.error(r.ASSISTANT_ACTION_RESULT_TYPE_CONFLICT,i.ASSISTANT_ACTION_RESULT_TYPE_CONFLICT(S,d,f));continue}let m=N?.description??T.description;l.push({fieldName:d,actionName:S,...void 0===m?{}:{description:m},args:Object.fromEntries(Object.entries(T.params).map(([e,{schema:t}])=>[e,h(t,n)])),result:Object.fromEntries(Object.entries(T.result).map(([e,t])=>[e,g(t,n)]))})}return l})(e.actions??{},{actions:y,resolveRef:C,builtInMutations:new Set(["deleteEntity",S.mutation,N.mutation,...F.map(({entityType:e})=>`modify${e}`)]),typeNames:new Set([...d,...t.resolvedShapes.keys(),...Y])},v.at("actions"));if(!(v.errors.length>b))return{entityTypes:t.entityTypes,aliases:Object.fromEntries(t.aliases),exampleType:t.rootEntityTypes[0]??t.entityTypes[0],states:{navigationStates:n.navigationStates,viewStates:n.viewStates,toolStates:n.toolStates},deletableTypes:W,writableTypes:F,actionFields:V,childRecipes:Object.fromEntries(Object.entries($.groups).map(([e,t])=>[e,{groups:t,hints:$.hints.get(e)??[]}])),replaceRecipes:Object.fromEntries(Object.entries(w.groups).map(([e,t])=>[e,{groups:t,hints:w.hints.get(e)??[]}])),optionsEdges:Object.fromEntries([...k].map(([e,t])=>[e,t.map(({options:e,hints:t})=>({options:e,hints:t}))])),fields:Object.fromEntries([...j].map(([e,t])=>[e,t.map(e=>({name:e.name,source:e.source,localized:e.localized,type:e.type,...void 0===e.description?{}:{description:e.description}}))]))}};export const createAssistantSchema=(e,n,s)=>{let o=resolveAssistantManifest(e,n,s);if(o)try{return{...t(o),resolved:o}}catch(e){s.error(r.ASSISTANT_INVALID_SCHEMA,i.ASSISTANT_INVALID_SCHEMA([e instanceof Error?e.message:String(e)]));return}};
@@ -4,8 +4,8 @@ import type { MergedAssistant } from '../../../merge/index.js';
4
4
  /**
5
5
  * The part of the assistant manifest only the server reads: the integrator's instructions for the
6
6
  * assistant and the AI settings it runs with. It is kept beside `AssistantSpec`, never inside it,
7
- * because `AssistantSpec` is serialized into the application bundle and into hot reload, and these
8
- * must not reach the browser of a customer. Deployment registration uploads them. `null` when the
7
+ * because its resolved manifest is serialized into the application bundle and into hot reload, and these
8
+ * must not reach the browser of a customer. The generated webhook bundle carries them for server-side setup resolution. `null` when the
9
9
  * application declares no `assistant` section.
10
10
  */
11
11
  export type AssistantServerSettings = Branded<'AssistantServerSettings', {
@@ -1,27 +1,11 @@
1
1
  import { Branded } from '@salsita-ai/common/utils';
2
2
  import type { ParseContext } from '../../../../core/index.js';
3
3
  import type { MergedAssistant } from '../../../merge/index.js';
4
- import type { EntityTypeName } from '../../model/index.js';
5
- import { type AssistantActions, type AssistantFieldOptionsByType, type AssistantFieldSources, type AssistantRecipeGroups, type AssistantSchemaInput, type AssistantWritableFields } from './assistant-schema.js';
4
+ import { type AssistantSchema, type AssistantSchemaInput } from './assistant-schema.js';
6
5
  /**
7
- * The experimental assistant manifest with its GraphQL SDL, prepared once at parse time so the
8
- * `.phoenix` codegen, the in-browser hot-reload runtime and deployment registration all carry the
9
- * exact same schema text. `fields` maps exposed GraphQL fields back to the stored fields and
10
- * expressions the runtime resolvers read; `deletableTypes` lists the entity types `deleteEntity`
11
- * may delete; `writableFields` maps the delta fields of each `modify<Type>` mutation to the stored
12
- * properties they write; `childRecipes` and `replaceRecipes` list the recipe groups each entity type exposes; `fieldOptions` lists
13
- * the options edges of each entity type's writable fields; `actions` maps each custom `Mutation`
14
- * field to the declared action it runs. `null` when the application declares no `assistant`
15
- * section or it is invalid.
6
+ * The validated built assistant schema and its JSON-only resolved input. Parsing constructs the
7
+ * schema to retain diagnostics; code generation and hot reload carry `resolved`, while deployment
8
+ * registration consumes the built SDL and resolver metadata. Null without a valid assistant section.
16
9
  */
17
- export type AssistantSpec = Branded<'AssistantSpec', {
18
- readonly sdl: string;
19
- readonly fields: AssistantFieldSources;
20
- readonly deletableTypes: readonly EntityTypeName[];
21
- readonly writableFields: AssistantWritableFields;
22
- readonly childRecipes: AssistantRecipeGroups;
23
- readonly replaceRecipes: AssistantRecipeGroups;
24
- readonly fieldOptions: AssistantFieldOptionsByType;
25
- readonly actions: AssistantActions;
26
- }> | null;
10
+ export type AssistantSpec = Branded<'AssistantSpec', AssistantSchema> | null;
27
11
  export declare const AssistantSpec: (merged: MergedAssistant, input: AssistantSchemaInput, ctx: ParseContext) => AssistantSpec;
@@ -201,10 +201,10 @@ export interface paths {
201
201
  readonly path?: never
202
202
  readonly cookie?: never
203
203
  }
204
- /** @description Load the caller's latest assistant thread on the configuration with its active run, newest window first. The `x-assistant-thread-continuable` response header is `false` when the thread belongs to another deployment or is closed; a chat request then answers 409. */
204
+ /** @description Load the caller's latest assistant thread on the configuration with its active run, newest window first. The `x-assistant-thread-continuable` response header is `false` when the thread has a different setup or is closed; a chat request then answers 409. */
205
205
  readonly get: operations['getAssistantThread']
206
206
  readonly put?: never
207
- /** @description Run the experimental assistant on the caller's thread of the configuration, or replay the run when the request carries `Last-Event-ID`. Answers 409 when the thread cannot be continued from this deployment or another run is still answering, and 503 while the server shuts down; sent again, the message reaches another instance. Answers 403 unless the customer has the AI Assistant feature flag on. */
207
+ /** @description Run the experimental assistant on the caller's thread of the configuration, or replay the run when the request carries `Last-Event-ID`. Answers 409 when the thread cannot be continued with this setup or another run is still answering, and 503 while the server shuts down; sent again, the message reaches another instance. Answers 403 unless the customer has the AI Assistant feature flag on. */
208
208
  readonly post: operations['assistantChat']
209
209
  readonly delete?: never
210
210
  readonly options?: never
@@ -993,6 +993,12 @@ export interface paths {
993
993
  export type webhooks = Record<string, never>
994
994
  export interface components {
995
995
  schemas: {
996
+ /** @description The deployment webhook failed or returned invalid assistant setup. */
997
+ readonly BadGatewayError: {
998
+ readonly message: string
999
+ /** @enum {number} */
1000
+ readonly statusCode: 502
1001
+ }
996
1002
  /** @description Bad Request: The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). */
997
1003
  readonly BadRequestError: {
998
1004
  /** @example Expected integer, received string! */
@@ -2443,6 +2449,15 @@ export interface operations {
2443
2449
  readonly 'application/json': components['schemas']['NotFoundError']
2444
2450
  }
2445
2451
  }
2452
+ /** @description Bad Gateway! */
2453
+ readonly 502: {
2454
+ headers: {
2455
+ readonly [name: string]: unknown
2456
+ }
2457
+ content: {
2458
+ readonly 'application/json': components['schemas']['BadGatewayError']
2459
+ }
2460
+ }
2446
2461
  /** @description An unexpected error occurred! */
2447
2462
  readonly default: {
2448
2463
  headers: {
@@ -2527,6 +2542,15 @@ export interface operations {
2527
2542
  readonly 'application/json': components['schemas']['ConflictError']
2528
2543
  }
2529
2544
  }
2545
+ /** @description Bad Gateway! */
2546
+ readonly 502: {
2547
+ headers: {
2548
+ readonly [name: string]: unknown
2549
+ }
2550
+ content: {
2551
+ readonly 'application/json': components['schemas']['BadGatewayError']
2552
+ }
2553
+ }
2530
2554
  /** @description Service Unavailable! */
2531
2555
  readonly 503: {
2532
2556
  headers: {
@@ -5370,20 +5394,22 @@ export interface operations {
5370
5394
  readonly adminConfigurationSchema?: components['schemas']['ConfigurationSchema']
5371
5395
  /** @description Semantic version (x.y.z) of the deployed application. */
5372
5396
  readonly applicationVersion?: string
5373
- /** @description What the deployment registers for its experimental assistant: the GraphQL SDL of the application spec, the prompt the SDK generates for its version, the instructions of the integrator and the AI settings. A deployment prepared without it has no assistant. */
5374
- readonly assistant?: {
5375
- readonly ai: {
5376
- /** @enum {string} */
5377
- readonly model: 'frontier' | 'advanced' | 'balanced' | 'fast'
5378
- /** @enum {string} */
5379
- readonly provider: 'openai'
5380
- /** @enum {string} */
5381
- readonly reasoning: 'low' | 'medium' | 'high'
5382
- }
5383
- readonly instructions?: string
5384
- readonly prompt: string
5385
- readonly sdl: string
5386
- }
5397
+ /** @description Whether the deployment webhook provides assistant setup. Omitted or legacy object registrations disable the assistant; prepare with a current SDK to enable it. */
5398
+ readonly assistant?:
5399
+ | boolean
5400
+ | {
5401
+ readonly ai: {
5402
+ /** @enum {string} */
5403
+ readonly model: 'frontier' | 'advanced' | 'balanced' | 'fast'
5404
+ /** @enum {string} */
5405
+ readonly provider: 'openai'
5406
+ /** @enum {string} */
5407
+ readonly reasoning: 'low' | 'medium' | 'high'
5408
+ }
5409
+ readonly instructions?: string
5410
+ readonly prompt: string
5411
+ readonly sdl: string
5412
+ }
5387
5413
  /** @description Configuration of the chat functionality. */
5388
5414
  readonly chat?: components['schemas']['ChatConfiguration']
5389
5415
  readonly configurationSchema: components['schemas']['ConfigurationSchema']
@@ -5590,20 +5616,22 @@ export interface operations {
5590
5616
  readonly adminConfigurationSchema?: components['schemas']['ConfigurationSchema']
5591
5617
  /** @description Semantic version (x.y.z) of the deployed application. */
5592
5618
  readonly applicationVersion?: string
5593
- /** @description What the deployment registers for its experimental assistant: the GraphQL SDL of the application spec, the prompt the SDK generates for its version, the instructions of the integrator and the AI settings. A deployment prepared without it has no assistant. */
5594
- readonly assistant?: {
5595
- readonly ai: {
5596
- /** @enum {string} */
5597
- readonly model: 'frontier' | 'advanced' | 'balanced' | 'fast'
5598
- /** @enum {string} */
5599
- readonly provider: 'openai'
5600
- /** @enum {string} */
5601
- readonly reasoning: 'low' | 'medium' | 'high'
5602
- }
5603
- readonly instructions?: string
5604
- readonly prompt: string
5605
- readonly sdl: string
5606
- }
5619
+ /** @description Whether the deployment webhook provides assistant setup. Omitted or legacy object registrations disable the assistant; prepare with a current SDK to enable it. */
5620
+ readonly assistant?:
5621
+ | boolean
5622
+ | {
5623
+ readonly ai: {
5624
+ /** @enum {string} */
5625
+ readonly model: 'frontier' | 'advanced' | 'balanced' | 'fast'
5626
+ /** @enum {string} */
5627
+ readonly provider: 'openai'
5628
+ /** @enum {string} */
5629
+ readonly reasoning: 'low' | 'medium' | 'high'
5630
+ }
5631
+ readonly instructions?: string
5632
+ readonly prompt: string
5633
+ readonly sdl: string
5634
+ }
5607
5635
  /** @description Configuration of the chat functionality. */
5608
5636
  readonly chat?: components['schemas']['ChatConfiguration']
5609
5637
  readonly configurationSchema: components['schemas']['ConfigurationSchema']
@@ -104,106 +104,92 @@ All inputs include countersinkNotAvailable, as that is fixable by auto fix dialo
104
104
  And corresponding transformers
105
105
 
106
106
  ```typescript
107
- configuratorBuilder
108
- .withTransformers(() => [
109
- {
110
- priority: 3,
111
- transformer: (updates, currentState) => {
112
- if (updates.length > 1) {
113
- return updates
114
- }
115
-
116
- const materialUpdate = updates.find(
117
- (u): u is ComponentModification<MaterialSwatchComponent> =>
118
- u.kind === 'modifyComponent' && u.updateTag === 'selectSwatch-material'
119
- )
120
-
121
- if (!materialUpdate) {
122
- return updates
123
- }
124
-
125
- const plate = currentState.domainState.entities.find(Plate.is)!
126
- const newMaterial = materialUpdate.writableState.selectedSwatchKey
127
-
128
- const isAvailable = availableMaterials.some(
129
- state =>
130
- state.material === newMaterial && state.finish === plate.finish && state.thickness === plate.thickness
131
- )
132
-
133
- if (isAvailable) {
134
- return updates
135
- }
136
-
137
- const similarMaterial = availableMaterials.find(m => m.material === newMaterial)
138
-
139
- if (!similarMaterial) {
140
- return updates
141
- }
142
-
143
- const fixUpdate = updateFactory.DomainEntityModification({
144
- entityId: plate.id,
145
- stateDelta: {
146
- material: similarMaterial.material,
147
- finish: similarMaterial.finish,
148
- thickness: similarMaterial.thickness,
149
- },
150
- updateTag: 'fix.material',
151
- })
152
-
153
- return [fixUpdate]
107
+ // src/transformers/fix-finish.ts
108
+ import { availableMaterials } from '../_shared/available-materials.js'
109
+
110
+ export default phx.frontend.transformerBuilder.when
111
+ .entity(['Plate'])
112
+ .modified({ atFields: ['finish'] })
113
+ .then.overrideMatchingUpdate(({ update, getOld$Entity }) => {
114
+ const plate = getOld$Entity()
115
+ const newFinish = update.stateDelta.finish
116
+
117
+ const isAvailable = availableMaterials.some(
118
+ state => state.material === plate.material && state.finish === newFinish && state.thickness === plate.thickness
119
+ )
120
+
121
+ if (isAvailable) {
122
+ return [update]
123
+ }
124
+
125
+ const similarMaterial = availableMaterials.find(m => m.finish === newFinish && m.material === plate.material)
126
+
127
+ if (!similarMaterial) {
128
+ return [update]
129
+ }
130
+
131
+ const fixUpdate = phx.frontend.updates.DomainEntityModification({
132
+ entityId: plate.id,
133
+ stateDelta: {
134
+ material: similarMaterial.material,
135
+ finish: similarMaterial.finish,
136
+ thickness: similarMaterial.thickness,
154
137
  },
155
- },
156
- {
157
- priority: 3.1,
158
- transformer: (updates, currentState) => {
159
- if (updates.length > 1) {
160
- return updates
161
- }
162
-
163
- const materialUpdate = updates.find(
164
- (u): u is ComponentModification<AttributeSelectionComponent> =>
165
- u.kind === 'modifyComponent' &&
166
- u.updateTag === 'AttributeSelect.update' &&
167
- (u.componentInstance.instanceName as string) === 'finish'
168
- )
169
-
170
- if (!materialUpdate) {
171
- return updates
172
- }
173
-
174
- const plate = currentState.domainState.entities.find(Plate.is)!
175
- const newFinish = materialUpdate.writableState.value
176
-
177
- const isAvailable = availableMaterials.some(
178
- state =>
179
- state.material === plate.material && state.finish === newFinish && state.thickness === plate.thickness
180
- )
181
-
182
- if (isAvailable) {
183
- return updates
184
- }
185
-
186
- const similarMaterial = availableMaterials.find(m => m.finish === newFinish && m.material === plate.material)
187
-
188
- if (!similarMaterial) {
189
- return updates
190
- }
191
-
192
- const fixUpdate = updateFactory.DomainEntityModification({
193
- entityId: plate.id,
194
- stateDelta: {
195
- material: similarMaterial.material,
196
- finish: similarMaterial.finish,
197
- thickness: similarMaterial.thickness,
198
- },
199
- updateTag: 'fix.brushed',
200
- })
201
-
202
- return [fixUpdate]
138
+ updateTag: 'fix.brushed',
139
+ })
140
+
141
+ return [fixUpdate]
142
+ })
143
+ .build('fix-finish')
144
+ ```
145
+
146
+ ```typescript
147
+ // src/transformers/fix-material.ts
148
+ import { availableMaterials } from '../_shared/available-materials.js'
149
+
150
+ export default phx.frontend.transformerBuilder.when
151
+ .entity(['Plate'])
152
+ .modified({ atFields: ['material'] })
153
+ .then.overrideMatchingUpdate(({ update, getOld$Entity }) => {
154
+ const plate = getOld$Entity()
155
+ const newMaterial = update.stateDelta.material
156
+
157
+ const isAvailable = availableMaterials.some(
158
+ state => state.material === newMaterial && state.finish === plate.finish && state.thickness === plate.thickness
159
+ )
160
+
161
+ if (isAvailable) {
162
+ return [update]
163
+ }
164
+
165
+ const similarMaterial = availableMaterials.find(m => m.material === newMaterial)
166
+
167
+ if (!similarMaterial) {
168
+ return [update]
169
+ }
170
+
171
+ const fixUpdate = phx.frontend.updates.DomainEntityModification({
172
+ entityId: plate.id,
173
+ stateDelta: {
174
+ material: similarMaterial.material,
175
+ finish: similarMaterial.finish,
176
+ thickness: similarMaterial.thickness,
203
177
  },
204
- },
205
- ])
206
- .buildConfig()
178
+ updateTag: 'fix.material',
179
+ })
180
+
181
+ return [fixUpdate]
182
+ })
183
+ .build('fix-material')
184
+ ```
185
+
186
+ Each file in `src/transformers/` default-exports one transformer and is picked up by its location. The `transformers` section of the spec turns it on by name. For a transformer made with `build(name)` that is the name passed to `build(...)`, which must match the file name with case and dashes ignored (`fix-finish.ts` and `fixFinish` match). For a plain-function export it is the file name:
187
+
188
+ ```yaml
189
+ # spec/application.yaml
190
+ transformers:
191
+ - name: fix-finish
192
+ - name: fix-material
207
193
  ```
208
194
 
209
195
  And FilteredControls
@@ -18,7 +18,7 @@ The `createResetSelectionOnNavigationTransformer` automatically deselects entiti
18
18
 
19
19
  ## Guide
20
20
 
21
- The `createResetSelectionOnNavigationTransformer` is added through the `.withTransformers()` method. It automatically injects a deselect update when navigating to specified states.
21
+ The `createResetSelectionOnNavigationTransformer` is added as a file in `src/transformers/`. It automatically injects a deselect update when navigating to specified states.
22
22
 
23
23
  ### Step 1: Import the transformer
24
24
 
@@ -28,19 +28,25 @@ Import the transformer function from the domain package:
28
28
  import { createResetSelectionOnNavigationTransformer } from '@salsita-ai/sdk/domain'
29
29
  ```
30
30
 
31
- ### Step 2: Add the transformer to your config
31
+ ### Step 2: Add the transformer to your project
32
32
 
33
- Use the `.withTransformers()` method on the builder:
33
+ Create the transformer in a file under `src/transformers/`:
34
34
 
35
35
  ```typescript
36
- const config = configuratorBuilder
37
- .withTransformers(ctx => [
38
- {
39
- priority: 32,
40
- transformer: createResetSelectionOnNavigationTransformer([ApplicationTypes.NavigationState.SecondStep], ctx),
41
- },
42
- ])
43
- .buildConfig()
36
+ // src/transformers/reset-selection.ts
37
+ import { createResetSelectionOnNavigationTransformer } from '@salsita-ai/sdk/domain'
38
+
39
+ export default phx.frontend.createTransformer(ctx =>
40
+ createResetSelectionOnNavigationTransformer([phx.applicationTypes.NavigationState.SecondStep], ctx)
41
+ )
42
+ ```
43
+
44
+ Each file in `src/transformers/` default-exports one transformer and is picked up by its location. The `transformers` section of the spec turns it on by name. For a transformer made with `build(name)` that is the name passed to `build(...)`, which must match the file name with case and dashes ignored (`fix-finish.ts` and `fixFinish` match). For a plain-function export it is the file name:
45
+
46
+ ```yaml
47
+ # spec/application.yaml
48
+ transformers:
49
+ - name: reset-selection
44
50
  ```
45
51
 
46
52
  The transformer takes two arguments:
@@ -97,7 +103,7 @@ When the transformer triggers, any selected entity is deselected automatically.
97
103
  *
98
104
  * @param navigationStates - Array of navigation state names that trigger deselection
99
105
  * @param ctx - Domain context providing access to the navigation system
100
- * @returns Update transformer that can be registered in withTransformers
106
+ * @returns Update transformer to return from a transformer file in src/transformers/
101
107
  *
102
108
  * @example
103
109
  * // Deselect when entering the summary step
@@ -1,5 +1,5 @@
1
1
  {
2
- "generatedAt": "2026-10-12T14:52:47.166Z",
2
+ "generatedAt": "2026-10-13T05:23:14.254Z",
3
3
  "categories": [
4
4
  {
5
5
  "name": "Phoenix",
@@ -78,24 +78,22 @@ Your custom component has full access to the Material-UI theme and SDK utilities
78
78
 
79
79
  ### Step 3: Attach the component to your entity
80
80
 
81
- Use the configurator builder to attach your custom price component to the root entity:
81
+ Attach your custom price component to the root entity in a file under `src/components/`. The generated code picks the
82
+ file up by its location and registers its default export:
82
83
 
83
84
  ```typescript
84
- const config = configuratorBuilder
85
- .withComponentOptics([
86
- attachComponent
87
- .withEntity('Scene')
88
- .withComponent(customPriceFooterComponent, 'default')
89
- .attach(
90
- memoEval(
91
- (s) => [s.$price],
92
- (price) => ({
93
- node: <AppPrice price={price} />,
94
- })
95
- )
96
- ),
97
- ])
98
- .buildConfig()
85
+ // src/components/custom-price.tsx
86
+ export default phx.domain.attachComponent
87
+ .withEntity('Scene')
88
+ .withComponent(customPriceFooterComponent, 'default')
89
+ .attach(
90
+ memoEval(
91
+ (s) => [s.$price],
92
+ (price) => ({
93
+ node: <AppPrice price={price} />,
94
+ })
95
+ )
96
+ )
99
97
  ```
100
98
 
101
99
  The `memoEval` function takes two arguments:
@@ -179,27 +179,30 @@ When a selected entity has no `sidebarTabs`, its property pages replace the root
179
179
  You can use transformers to automatically navigate to specific tabs when entities are selected or deselected:
180
180
 
181
181
  ```typescript
182
- const config = configuratorBuilder
183
- .withTransformers(ctx => {
184
- return [
185
- // Navigate to BuckyBall's first tab when selected
186
- phx.frontend.transformerBuilder.when
187
- .entity(['BuckyBall'])
188
- .selected()
189
- .then.navigateTo('BuckyBallTab1')
190
- .build('Navigate to BuckyBallTab1')
191
- .register(ctx),
192
-
193
- // Return to global tab1 when BuckyBall is deselected
194
- phx.frontend.transformerBuilder.when
195
- .entity(['BuckyBall'])
196
- .deselected()
197
- .then.navigateTo('tab1')
198
- .build('Navigate to Tab1')
199
- .register(ctx),
200
- ]
201
- })
202
- .buildConfig()
182
+ // src/transformers/bucky-ball-tab.ts
183
+ export default phx.frontend.transformerBuilder.when
184
+ .entity(['BuckyBall'])
185
+ .selected()
186
+ .then.navigateTo('BuckyBallTab1')
187
+ .build('buckyBallTab')
188
+ ```
189
+
190
+ ```typescript
191
+ // src/transformers/tab.ts
192
+ export default phx.frontend.transformerBuilder.when
193
+ .entity(['BuckyBall'])
194
+ .deselected()
195
+ .then.navigateTo('tab1')
196
+ .build('tab')
197
+ ```
198
+
199
+ Each file in `src/transformers/` default-exports one transformer and is picked up by its location. The `transformers` section of the spec turns it on by name. For a transformer made with `build(name)` that is the name passed to `build(...)`, which must match the file name with case and dashes ignored (`fix-finish.ts` and `fixFinish` match). For a plain-function export it is the file name:
200
+
201
+ ```yaml
202
+ # spec/application.yaml
203
+ transformers:
204
+ - name: buckyBallTab
205
+ - name: tab
203
206
  ```
204
207
 
205
208
  This creates smooth navigation flows where selecting specific entities automatically switches to their relevant tabs, and deselecting returns to a default tab state.
@@ -83,7 +83,7 @@ export default phx.domain.implementActions({
83
83
  })
84
84
  ```
85
85
 
86
- Throw to reject a call: the message reaches the user through the control's hint and the assistant through the failed mutation, so say what went wrong and what to send instead. An action declared without an implementation, or an implementation of a name the spec does not declare, is a type error. A declared action without an implementation also stops the domain from initializing, and under `phoenix dev` the editor reports it as a `MISSING_ACTION_IMPLEMENTATIONS` diagnostic and does not apply the change; an implementation of an undeclared name is logged.
86
+ Throw to reject a call: the message reaches the user through the control's hint and the assistant through the failed mutation, so say what went wrong and what to send instead. An implementation of a name the spec does not declare is a type error. A declared action without an implementation is not: it stops the domain from initializing, and under `phoenix dev` the editor reports it as a `MISSING_ACTION_IMPLEMENTATIONS` diagnostic and does not apply the change; an implementation of an undeclared name is logged.
87
87
 
88
88
  ## Run it from the UI
89
89