@salsita-ai/sdk 0.50.0-develop.ecda3c6152 → 0.50.0-develop.eeaf6c4605

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 (415) hide show
  1. package/README.md +4 -2
  2. package/dist/application-spec/caching/index.d.ts +6 -1
  3. package/dist/application-spec/caching/index.js +1 -1
  4. package/dist/application-spec/generate-application/code/domain-runtime-files.d.ts +0 -19
  5. package/dist/application-spec/generate-application/code/domain-runtime-files.js +1 -1
  6. package/dist/application-spec/generate-application/code/templates/gitignore.js +2 -1
  7. package/dist/application-spec/generate-application/code/templates/index.d.ts +1 -1
  8. package/dist/application-spec/generate-application/code/templates/index.js +1 -1
  9. package/dist/application-spec/generate-application/code/templates/lingui-rc.js +5 -4
  10. package/dist/application-spec/generate-application/code/templates/skills/core/cli.d.ts +2 -0
  11. package/dist/application-spec/generate-application/code/templates/skills/core/cli.js +1 -0
  12. package/dist/application-spec/generate-application/code/templates/skills/core/index.d.ts +3 -0
  13. package/dist/application-spec/generate-application/code/templates/skills/core/index.js +1 -0
  14. package/dist/application-spec/generate-application/code/templates/skills/core/sdk.d.ts +2 -0
  15. package/dist/application-spec/generate-application/code/templates/skills/core/sdk.js +150 -0
  16. package/dist/application-spec/generate-application/code/templates/skills/core/workflow.d.ts +2 -0
  17. package/dist/application-spec/generate-application/code/templates/skills/core/workflow.js +40 -0
  18. package/dist/application-spec/generate-application/code/templates/skills/features/custom-layout.d.ts +2 -0
  19. package/dist/application-spec/generate-application/code/templates/skills/features/custom-layout.js +1 -0
  20. package/dist/application-spec/generate-application/code/templates/skills/features/features.d.ts +3 -0
  21. package/dist/application-spec/generate-application/code/templates/skills/features/features.js +1 -0
  22. package/dist/application-spec/generate-application/code/templates/skills/features/index.d.ts +1 -0
  23. package/dist/application-spec/generate-application/code/templates/skills/features/index.js +1 -0
  24. package/dist/application-spec/generate-application/code/templates/skills/features/inspection.d.ts +2 -0
  25. package/dist/application-spec/generate-application/code/templates/skills/features/inspection.js +1 -0
  26. package/dist/application-spec/generate-application/code/templates/skills/features/variants.d.ts +2 -0
  27. package/dist/application-spec/generate-application/code/templates/skills/features/variants.js +1 -0
  28. package/dist/application-spec/generate-application/code/templates/skills/features/webhooks.d.ts +2 -0
  29. package/dist/application-spec/generate-application/code/templates/skills/features/webhooks.js +1 -0
  30. package/dist/application-spec/generate-application/code/templates/skills/guide.d.ts +54 -0
  31. package/dist/application-spec/generate-application/code/templates/skills/guide.js +18 -0
  32. package/dist/application-spec/generate-application/code/templates/skills/phoenix-skill-bundle.d.ts +2 -2
  33. package/dist/application-spec/generate-application/code/templates/skills/phoenix-skill-bundle.js +12 -5
  34. package/dist/application-spec/generate-application/code/templates/skills/processes/asset-conversion.d.ts +2 -0
  35. package/dist/application-spec/generate-application/code/templates/skills/processes/asset-conversion.js +23 -0
  36. package/dist/application-spec/generate-application/code/templates/skills/processes/feedback/evaluate.d.ts +2 -0
  37. package/dist/application-spec/generate-application/code/templates/skills/processes/feedback/evaluate.js +39 -0
  38. package/dist/application-spec/generate-application/code/templates/skills/processes/feedback/feedback.d.ts +3 -0
  39. package/dist/application-spec/generate-application/code/templates/skills/processes/feedback/feedback.js +1 -0
  40. package/dist/application-spec/generate-application/code/templates/skills/processes/feedback/index.d.ts +1 -0
  41. package/dist/application-spec/generate-application/code/templates/skills/processes/feedback/index.js +1 -0
  42. package/dist/application-spec/generate-application/code/templates/skills/processes/feedback/report.d.ts +2 -0
  43. package/dist/application-spec/generate-application/code/templates/skills/processes/feedback/report.js +7 -0
  44. package/dist/application-spec/generate-application/code/templates/skills/processes/feedback/send.d.ts +2 -0
  45. package/dist/application-spec/generate-application/code/templates/skills/processes/feedback/send.js +2 -0
  46. package/dist/application-spec/generate-application/code/templates/skills/processes/finalization.d.ts +2 -0
  47. package/dist/application-spec/generate-application/code/templates/skills/processes/finalization.js +2 -0
  48. package/dist/application-spec/generate-application/code/templates/skills/processes/first-draft/build.d.ts +2 -0
  49. package/dist/application-spec/generate-application/code/templates/skills/processes/first-draft/build.js +23 -0
  50. package/dist/application-spec/generate-application/code/templates/skills/processes/first-draft/direction.d.ts +2 -0
  51. package/dist/application-spec/generate-application/code/templates/skills/processes/first-draft/direction.js +26 -0
  52. package/dist/application-spec/generate-application/code/templates/skills/processes/first-draft/first-draft.d.ts +3 -0
  53. package/dist/application-spec/generate-application/code/templates/skills/processes/first-draft/first-draft.js +3 -0
  54. package/dist/application-spec/generate-application/code/templates/skills/processes/first-draft/handoff.d.ts +2 -0
  55. package/dist/application-spec/generate-application/code/templates/skills/processes/first-draft/handoff.js +7 -0
  56. package/dist/application-spec/generate-application/code/templates/skills/processes/first-draft/index.d.ts +1 -0
  57. package/dist/application-spec/generate-application/code/templates/skills/processes/first-draft/index.js +1 -0
  58. package/dist/application-spec/generate-application/code/templates/skills/processes/index.d.ts +9 -0
  59. package/dist/application-spec/generate-application/code/templates/skills/processes/index.js +1 -0
  60. package/dist/application-spec/generate-application/code/templates/skills/processes/model-migration.d.ts +2 -0
  61. package/dist/application-spec/generate-application/code/templates/skills/processes/model-migration.js +1 -0
  62. package/dist/application-spec/generate-application/code/templates/skills/{phoenix-skill.d.ts → processes/operations.d.ts} +2 -1
  63. package/dist/application-spec/generate-application/code/templates/skills/processes/operations.js +2 -0
  64. package/dist/application-spec/generate-application/code/templates/skills/processes/planning.d.ts +2 -0
  65. package/dist/application-spec/generate-application/code/templates/skills/processes/planning.js +5 -0
  66. package/dist/application-spec/generate-application/code/templates/skills/processes/review/appearance.d.ts +2 -0
  67. package/dist/application-spec/generate-application/code/templates/skills/processes/review/appearance.js +46 -0
  68. package/dist/application-spec/generate-application/code/templates/skills/processes/review/code.d.ts +2 -0
  69. package/dist/application-spec/generate-application/code/templates/skills/processes/review/code.js +2 -0
  70. package/dist/application-spec/generate-application/code/templates/skills/processes/review/hand-over.d.ts +2 -0
  71. package/dist/application-spec/generate-application/code/templates/skills/processes/review/hand-over.js +6 -0
  72. package/dist/application-spec/generate-application/code/templates/skills/processes/review/index.d.ts +1 -0
  73. package/dist/application-spec/generate-application/code/templates/skills/processes/review/index.js +1 -0
  74. package/dist/application-spec/generate-application/code/templates/skills/processes/review/review.d.ts +3 -0
  75. package/dist/application-spec/generate-application/code/templates/skills/processes/review/review.js +1 -0
  76. package/dist/application-spec/generate-application/code/templates/skills/processes/review/visual-inspection.d.ts +2 -0
  77. package/dist/application-spec/generate-application/code/templates/skills/processes/review/visual-inspection.js +13 -0
  78. package/dist/application-spec/generate-application/code/templates/skills/processes/specification/branding.d.ts +2 -0
  79. package/dist/application-spec/generate-application/code/templates/skills/processes/specification/branding.js +20 -0
  80. package/dist/application-spec/generate-application/code/templates/skills/processes/specification/catalog.d.ts +2 -0
  81. package/dist/application-spec/generate-application/code/templates/skills/processes/specification/catalog.js +1 -0
  82. package/dist/application-spec/generate-application/code/templates/skills/processes/specification/index.d.ts +1 -0
  83. package/dist/application-spec/generate-application/code/templates/skills/processes/specification/index.js +1 -0
  84. package/dist/application-spec/generate-application/code/templates/skills/processes/specification/product-definition.d.ts +2 -0
  85. package/dist/application-spec/generate-application/code/templates/skills/processes/specification/product-definition.js +22 -0
  86. package/dist/application-spec/generate-application/code/templates/skills/processes/specification/specification.d.ts +3 -0
  87. package/dist/application-spec/generate-application/code/templates/skills/processes/specification/specification.js +1 -0
  88. package/dist/application-spec/generate-application/code/templates/skills/processes/specification/ux-guidelines.d.ts +2 -0
  89. package/dist/application-spec/generate-application/code/templates/skills/processes/specification/ux-guidelines.js +25 -0
  90. package/dist/application-spec/generate-application/code/templates/skills/sdk-content.d.ts +63 -249
  91. package/dist/application-spec/generate-application/code/templates/skills/sdk-content.js +3 -58
  92. package/dist/application-spec/generate-application/code/templates/spec-code/collect-spec-code.d.ts +1 -1
  93. package/dist/application-spec/generate-application/code/templates/spec-code/collect-spec-code.js +1 -1
  94. package/dist/application-spec/generate-application/code/templates/tsconfig.js +2 -1
  95. package/dist/application-spec/generate-application/index.d.ts +1 -8
  96. package/dist/application-spec/generate-application/index.js +1 -1
  97. package/dist/client/authorized-client.d.ts +1 -1
  98. package/dist/client/contract.d.ts +4 -3
  99. package/dist/configurator/application-runtime/extensions/systems/assistant-system/assistant-system.d.ts +28 -18
  100. package/dist/configurator/application-runtime/extensions/systems/assistant-system/assistant-system.js +1 -1
  101. package/dist/configurator/application-runtime/extensions/systems/graphql-system/graphql-system.d.ts +8 -2
  102. package/dist/configurator/application-runtime/extensions/systems/graphql-system/graphql-system.js +1 -1
  103. package/dist/configurator/application-runtime/extensions/systems/index.d.ts +1 -1
  104. package/dist/configurator/application-runtime/extensions/systems/index.js +1 -1
  105. package/dist/configurator/ui/assistant/AssistantChips.d.ts +10 -0
  106. package/dist/configurator/ui/assistant/AssistantChips.js +1 -1
  107. package/dist/configurator/ui/assistant/AssistantComposer.js +2 -2
  108. package/dist/configurator/ui/assistant/AssistantMarkdown.js +1 -1
  109. package/dist/configurator/ui/assistant/AssistantThread.d.ts +4 -3
  110. package/dist/configurator/ui/assistant/AssistantThread.js +1 -1
  111. package/dist/configurator/ui/assistant/alert/AssistantAlert.d.ts +4 -1
  112. package/dist/configurator/ui/assistant/alert/AssistantAlert.js +1 -1
  113. package/dist/configurator/ui/assistant/entity-link/AssistantEntityLink.js +1 -1
  114. package/dist/configurator/ui/assistant/form/AssistantForm.js +1 -1
  115. package/dist/configurator/ui/assistant/form/registry/built-in-form-elements.d.ts +26 -0
  116. package/dist/configurator/ui/assistant/form-elements/FormNumber.js +1 -1
  117. package/dist/configurator/ui/assistant/popover/AssistantPopover.d.ts +24 -0
  118. package/dist/configurator/ui/assistant/popover/AssistantPopover.js +1 -0
  119. package/dist/configurator/ui/assistant/popover/index.d.ts +1 -0
  120. package/dist/configurator/ui/assistant/popover/index.js +1 -0
  121. package/dist/configurator/ui/assistant/reference-link/AssistantReferenceLink.js +1 -1
  122. package/dist/configurator/ui/assistant/reference-link/reference-styles.js +1 -1
  123. package/dist/configurator/ui/assistant/streamed-markdown.d.ts +11 -0
  124. package/dist/configurator/ui/assistant/streamed-markdown.js +2 -2
  125. package/dist/configurator/ui/assistant/tool-chip.js +1 -1
  126. package/dist/configurator/ui/assistant/use-load-older-on-top.d.ts +22 -0
  127. package/dist/configurator/ui/assistant/use-load-older-on-top.js +1 -0
  128. package/dist/configurator/ui/configurator-layout/universal/Layout.js +1 -1
  129. package/dist/docs/index.json +1 -1
  130. package/dist/docs/phoenix/getting-started.mdx +0 -2
  131. package/dist/docs/phoenix/migration-guide.mdx +7 -8
  132. package/dist/docs/phoenix/phoenix-cli.mdx +21 -12
  133. package/dist/docs/phoenix/project-structure.mdx +30 -35
  134. package/dist/docs/phoenix/sdk-builder-workflow.mdx +3 -9
  135. package/dist/domain/application/GetApplicationWrapperHandler.d.ts +1 -1
  136. package/dist/domain/application/GetThemeHandler.d.ts +1 -1
  137. package/dist/domain/application/GetWebComponentOptions.d.ts +1 -1
  138. package/dist/domain/application/application-config.d.ts +1 -3
  139. package/dist/domain/application/assistant/assistant-fields.d.ts +1 -1
  140. package/dist/domain/application/assistant/assistant-value-type.d.ts +1 -1
  141. package/dist/domain/application/assistant/build-assistant-lenses.d.ts +1 -2
  142. package/dist/domain/application/assistant/build-assistant-manifest.d.ts +1 -2
  143. package/dist/domain/application/assistant/generate-assistant-prompt.d.ts +1 -2
  144. package/dist/domain/application/assistant/generate-assistant-prompt.js +1 -1
  145. package/dist/domain/application/assistant/index.d.ts +0 -4
  146. package/dist/domain/application/assistant/index.js +1 -1
  147. package/dist/domain/application/assistant/session-setup/AssistantSetupHandler.d.ts +1 -1
  148. package/dist/domain/application/assistant/session-setup/apply-assistant-setup.d.ts +1 -1
  149. package/dist/domain/application/assistant/session-setup/assistant-setup-manifest.d.ts +1 -1
  150. package/dist/domain/application/assistant/session-setup/create-session-assistant.d.ts +1 -2
  151. package/dist/domain/application/assistant-field-options.d.ts +1 -1
  152. package/dist/domain/application/assistant-mutations.d.ts +1 -1
  153. package/dist/domain/application/assistant-recipe-groups.d.ts +1 -1
  154. package/dist/domain/application/configurator-builder.d.ts +1 -2
  155. package/dist/domain/application/create-initial-published-data.d.ts +2 -1
  156. package/dist/domain/application/published-data/DataRowValidatorHandler.d.ts +1 -1
  157. package/dist/domain/application/published-data/FilterPublishedChunksHandler.d.ts +1 -1
  158. package/dist/domain/application/published-data/MapPublishedChunkedDataHandler.d.ts +1 -1
  159. package/dist/domain/application/published-data/MapPublishedRevisionDataHandler.d.ts +1 -1
  160. package/dist/domain/application/published-data/SheetValidatorHandler.d.ts +1 -1
  161. package/dist/domain/domain-builder/domain-builder.d.ts +1 -1
  162. package/dist/domain/domain-builder/domain-builder.js +1 -1
  163. package/dist/domain/domain-runtime/domain-runtime.d.ts +24 -24
  164. package/dist/domain/domain-runtime/index.d.ts +0 -1
  165. package/dist/domain/domain-runtime/index.js +1 -1
  166. package/dist/domain/domain-runtime/spec/create-violation-expressions.d.ts +1 -1
  167. package/dist/domain/domain-runtime/spec/create-violation-expressions.js +1 -1
  168. package/dist/domain/domain-runtime/spec/index.d.ts +1 -1
  169. package/dist/domain/domain-runtime/spec/index.js +1 -1
  170. package/dist/domain/domain-runtime/spec/initialize.js +1 -1
  171. package/dist/domain/domain-runtime/spec/{module-checks/resolve-imported-transformers.d.ts → resolve-imported-transformers.d.ts} +3 -3
  172. package/dist/domain/domain-runtime/spec/resolve-imported-transformers.js +1 -0
  173. package/dist/domain/domain-runtime/spec/selectors.d.ts +5 -5
  174. package/dist/domain/domain-runtime/spec/types.d.ts +2 -2
  175. package/dist/domain/index.d.ts +13 -1
  176. package/dist/domain/index.js +1 -1
  177. package/dist/domain/mocks/create-test-application-config.d.ts +1 -1
  178. package/dist/domain/spec/index.d.ts +3 -8
  179. package/dist/domain/spec/index.js +1 -1
  180. package/dist/domain/{domain-runtime/spec/module-checks → spec/modules}/element-registration.d.ts +1 -1
  181. package/dist/domain/{domain-runtime/spec/module-checks → spec/modules}/find-assistant-form-element-errors.d.ts +1 -1
  182. package/dist/domain/spec/modules/find-assistant-form-element-errors.js +1 -0
  183. package/dist/domain/{domain-runtime/spec/module-checks → spec/modules}/index.d.ts +2 -3
  184. package/dist/domain/spec/modules/index.js +1 -0
  185. package/dist/domain/{domain-runtime/spec/module-checks → spec/modules}/merge-expression-modules.d.ts +2 -2
  186. package/dist/domain/spec/modules/merge-expression-modules.js +1 -0
  187. package/dist/domain/{domain-runtime/spec/module-checks → spec/modules}/project-modules.d.ts +1 -1
  188. package/dist/domain/spec/modules/project-modules.js +1 -0
  189. package/dist/domain/{domain-runtime/spec/module-checks → spec/modules}/resolve-action-modules.d.ts +1 -1
  190. package/dist/domain/{domain-runtime/spec/module-checks → spec/modules}/resolve-component-optic-modules.d.ts +1 -1
  191. package/dist/domain/{domain-runtime/spec/module-checks → spec/modules}/resolve-expression-modules.d.ts +1 -1
  192. package/dist/domain/{domain-runtime/spec/module-checks → spec/modules}/resolve-invariant-modules.d.ts +1 -1
  193. package/dist/domain/spec/phx/index.d.ts +1 -0
  194. package/dist/domain/spec/phx/index.js +1 -0
  195. package/dist/{application-spec/generate-application/implementations → domain/spec/phx}/phx-application-types.d.ts +1 -1
  196. package/dist/domain/spec/phx/phx-application-types.js +1 -0
  197. package/dist/domain/spec/phx/phx-domain.js +1 -0
  198. package/dist/{application-spec/generate-application/implementations → domain/spec/phx}/phx-model.d.ts +2 -2
  199. package/dist/domain/spec/phx/phx-model.js +1 -0
  200. package/dist/{application-spec/generate-application/implementations → domain/spec/phx}/phx.d.ts +1 -2
  201. package/dist/{application-spec/generate-application → domain/spec}/runtime/admin-runtime/admin-runtime.d.ts +7 -6
  202. package/dist/domain/spec/runtime/admin-runtime/admin-runtime.js +1 -0
  203. package/dist/{application-spec/generate-application → domain/spec}/runtime/admin-runtime/admin-spec-runtime.d.ts +2 -2
  204. package/dist/domain/spec/runtime/admin-runtime/admin-spec-runtime.js +1 -0
  205. package/dist/domain/spec/runtime/admin-runtime/index.d.ts +2 -0
  206. package/dist/domain/spec/runtime/admin-runtime/index.js +1 -0
  207. package/dist/{application-spec/generate-application → domain/spec}/runtime/admin-runtime/states-runtime.d.ts +1 -1
  208. package/dist/{application-spec/generate-application → domain/spec}/runtime/application-runtime.d.ts +8 -6
  209. package/dist/domain/spec/runtime/application-runtime.js +1 -0
  210. package/dist/{application-spec/generate-application → domain/spec}/runtime/application-spec-slice.d.ts +3 -1
  211. package/dist/domain/spec/runtime/application-spec-slice.js +1 -0
  212. package/dist/{application-spec/generate-application → domain/spec}/runtime/configurator-runtime/configurator-runtime.d.ts +8 -10
  213. package/dist/domain/spec/runtime/configurator-runtime/configurator-runtime.js +1 -0
  214. package/dist/{application-spec/generate-application → domain/spec}/runtime/configurator-runtime/configurator-spec-runtime.d.ts +2 -2
  215. package/dist/domain/spec/runtime/configurator-runtime/configurator-spec-runtime.js +1 -0
  216. package/dist/domain/spec/runtime/configurator-runtime/index.d.ts +2 -0
  217. package/dist/domain/spec/runtime/configurator-runtime/index.js +1 -0
  218. package/dist/{application-spec/generate-application → domain/spec}/runtime/configurator-runtime/states-runtime.d.ts +1 -1
  219. package/dist/{application-spec/generate-application → domain/spec}/runtime/create-application.d.ts +3 -2
  220. package/dist/domain/spec/runtime/create-application.js +1 -0
  221. package/dist/{application-spec/generate-application/runtime/sections → domain/spec/runtime/expressions}/expression-runtime.d.ts +5 -2
  222. package/dist/domain/spec/runtime/expressions/expression-runtime.js +1 -0
  223. package/dist/{application-spec/generate-application/runtime/sections → domain/spec/runtime/expressions}/generate-memo-eval-plan-runtime.d.ts +2 -1
  224. package/dist/domain/spec/runtime/expressions/generate-memo-eval-plan-runtime.js +1 -0
  225. package/dist/domain/spec/runtime/expressions/index.d.ts +3 -0
  226. package/dist/domain/spec/runtime/expressions/index.js +1 -0
  227. package/dist/{application-spec/generate-application/runtime/sections → domain/spec/runtime/expressions}/reflection-constants-runtime.d.ts +2 -1
  228. package/dist/{application-spec/generate-application → domain/spec}/runtime/factory-data/factory-data-runtime.d.ts +4 -2
  229. package/dist/{application-spec/generate-application → domain/spec}/runtime/factory-data/recipe-defaults.d.ts +1 -1
  230. package/dist/domain/spec/runtime/factory-data/recipe-defaults.js +1 -0
  231. package/dist/{application-spec/generate-application → domain/spec}/runtime/factory-data/static-violations.d.ts +2 -1
  232. package/dist/domain/spec/runtime/factory-data/static-violations.js +1 -0
  233. package/dist/{application-spec/generate-application → domain/spec}/runtime/generate-runtime-instance.d.ts +1 -1
  234. package/dist/domain/spec/runtime/generate-runtime-instance.js +1 -0
  235. package/dist/domain/spec/runtime/index.d.ts +13 -0
  236. package/dist/domain/spec/runtime/index.js +1 -0
  237. package/dist/{application-spec/generate-application → domain/spec}/runtime/migrations/migration-runtime.d.ts +2 -2
  238. package/dist/domain/spec/runtime/migrations/migration-runtime.js +1 -0
  239. package/dist/{application-spec/generate-application/runtime/admin-runtime → domain/spec/runtime/model}/admin-model-runtime.d.ts +4 -2
  240. package/dist/domain/spec/runtime/model/admin-model-runtime.js +1 -0
  241. package/dist/{application-spec/generate-application/runtime/configurator-runtime → domain/spec/runtime/model}/configurator-model-runtime.d.ts +4 -2
  242. package/dist/domain/spec/runtime/model/configurator-model-runtime.js +1 -0
  243. package/dist/domain/spec/runtime/model/index.d.ts +2 -0
  244. package/dist/domain/spec/runtime/model/index.js +1 -0
  245. package/dist/{application-spec/generate-application/runtime/sections → domain/spec/runtime/optics}/build-sdk-optic.d.ts +3 -4
  246. package/dist/domain/spec/runtime/optics/build-sdk-optic.js +1 -0
  247. package/dist/domain/spec/runtime/optics/build-user-bound-optic.d.ts +7 -0
  248. package/dist/domain/spec/runtime/optics/build-user-bound-optic.js +1 -0
  249. package/dist/domain/spec/runtime/optics/built-component-optic.d.ts +11 -0
  250. package/dist/{application-spec/generate-application/runtime/sections → domain/spec/runtime/optics}/component-optic.d.ts +4 -13
  251. package/dist/domain/spec/runtime/optics/index.d.ts +2 -0
  252. package/dist/domain/spec/runtime/optics/index.js +1 -0
  253. package/dist/{application-spec/caching → domain/spec/runtime}/runtime-reference-store.d.ts +1 -5
  254. package/dist/domain/spec/runtime/runtime-reference-store.js +1 -0
  255. package/dist/{application-spec/generate-application → domain/spec}/runtime/sections/actions-runtime.d.ts +3 -2
  256. package/dist/{application-spec/generate-application → domain/spec}/runtime/sections/assistant-runtime.d.ts +2 -2
  257. package/dist/{application-spec/generate-application → domain/spec}/runtime/sections/data-runtime.d.ts +1 -1
  258. package/dist/domain/spec/runtime/sections/index.d.ts +6 -0
  259. package/dist/domain/spec/runtime/sections/index.js +1 -0
  260. package/dist/{application-spec/generate-application → domain/spec}/runtime/sections/preset-runtime.d.ts +3 -2
  261. package/dist/{application-spec/generate-application → domain/spec}/runtime/sections/theme-runtime.d.ts +1 -1
  262. package/dist/{application-spec/generate-application → domain/spec}/runtime/sections/transformers-runtime.d.ts +2 -2
  263. package/dist/{application-spec/generate-application → domain/spec}/runtime/spec-code/resolve-spec-code.d.ts +1 -1
  264. package/dist/{application-spec/generate-application → domain/spec}/runtime/spec-runtime.d.ts +3 -3
  265. package/dist/domain/spec/runtime/spec-runtime.js +1 -0
  266. package/dist/domain/spec/runtime-spec/index.d.ts +4 -0
  267. package/dist/domain/spec/runtime-spec/index.js +1 -0
  268. package/dist/{application-spec/generate-application → domain/spec}/runtime-spec/runtime-spec.d.ts +7 -1
  269. package/dist/{application-spec/generate-application → domain/spec}/runtime-spec/spec-code-id.d.ts +1 -1
  270. package/dist/domain/spec/sections/assistant/assistant-resolved-manifest.js +1 -0
  271. package/dist/domain/spec/sections/assistant/index.d.ts +4 -0
  272. package/dist/domain/spec/sections/assistant/index.js +1 -0
  273. package/dist/domain/spec/sections/index.d.ts +1 -0
  274. package/dist/domain/spec/sections/index.js +1 -1
  275. package/dist/i18n/locales/cs/messages.js +1 -1
  276. package/dist/i18n/locales/da/messages.js +1 -1
  277. package/dist/i18n/locales/de/messages.js +1 -1
  278. package/dist/i18n/locales/de-AT/messages.js +1 -1
  279. package/dist/i18n/locales/en/messages.js +1 -1
  280. package/dist/i18n/locales/en-AU/messages.js +1 -1
  281. package/dist/i18n/locales/en-GB/messages.js +1 -1
  282. package/dist/i18n/locales/es/messages.js +1 -1
  283. package/dist/i18n/locales/fr/messages.js +1 -1
  284. package/dist/i18n/locales/hu/messages.js +1 -1
  285. package/dist/i18n/locales/it/messages.js +1 -1
  286. package/dist/i18n/locales/nl/messages.js +1 -1
  287. package/dist/i18n/locales/pl/messages.js +1 -1
  288. package/dist/i18n/locales/pt/messages.js +1 -1
  289. package/dist/i18n/locales/ro/messages.js +1 -1
  290. package/dist/i18n/locales/sk/messages.js +1 -1
  291. package/dist/i18n/locales/tr/messages.js +1 -1
  292. package/dist/phoenix/application-spec/application-spec-builder.js +1 -1
  293. package/dist/phoenix/application-spec/generate-application-spec-project.js +2 -2
  294. package/dist/phoenix/application-spec/index.d.ts +1 -0
  295. package/dist/phoenix/application-spec/index.js +1 -1
  296. package/dist/phoenix/application-spec/project-files.d.ts +8 -2
  297. package/dist/phoenix/application-spec/project-files.js +1 -1
  298. package/dist/phoenix/commands/clean.js +1 -1
  299. package/dist/phoenix/commands/deploy.js +1 -1
  300. package/dist/phoenix/services/source-archive.d.ts +2 -0
  301. package/dist/phoenix/services/source-archive.js +1 -1
  302. package/dist/phoenix/services/swc.d.ts +5 -4
  303. package/dist/phoenix/services/swc.js +2 -2
  304. package/dist/ui-sdk/components/numerical-input/InputField.d.ts +2 -0
  305. package/dist/ui-sdk/components/numerical-input/InputField.js +1 -1
  306. package/dist/ui-sdk/components/numerical-input/NumericalInput.d.ts +2 -2
  307. package/dist/ui-sdk/components/numerical-input/Slider.d.ts +3 -1
  308. package/dist/ui-sdk/components/numerical-input/Slider.js +1 -1
  309. package/package.json +3 -3
  310. package/dist/application-spec/caching/runtime-reference-store.js +0 -1
  311. package/dist/application-spec/generate-application/code/templates/skills/phoenix-cli-skill.d.ts +0 -1
  312. package/dist/application-spec/generate-application/code/templates/skills/phoenix-cli-skill.js +0 -1
  313. package/dist/application-spec/generate-application/code/templates/skills/phoenix-create-configurator-skill.d.ts +0 -3
  314. package/dist/application-spec/generate-application/code/templates/skills/phoenix-create-configurator-skill.js +0 -166
  315. package/dist/application-spec/generate-application/code/templates/skills/phoenix-feedback-skill.d.ts +0 -1
  316. package/dist/application-spec/generate-application/code/templates/skills/phoenix-feedback-skill.js +0 -54
  317. package/dist/application-spec/generate-application/code/templates/skills/phoenix-review-skill.d.ts +0 -1
  318. package/dist/application-spec/generate-application/code/templates/skills/phoenix-review-skill.js +0 -115
  319. package/dist/application-spec/generate-application/code/templates/skills/phoenix-skill.js +0 -1
  320. package/dist/application-spec/generate-application/code/templates/skills/phoenix-variants-skill.d.ts +0 -1
  321. package/dist/application-spec/generate-application/code/templates/skills/phoenix-variants-skill.js +0 -6
  322. package/dist/application-spec/generate-application/implementations/phx-application-types.js +0 -1
  323. package/dist/application-spec/generate-application/implementations/phx-domain.js +0 -1
  324. package/dist/application-spec/generate-application/implementations/phx-model.js +0 -1
  325. package/dist/application-spec/generate-application/runtime/admin-runtime/admin-model-runtime.js +0 -1
  326. package/dist/application-spec/generate-application/runtime/admin-runtime/admin-runtime.js +0 -1
  327. package/dist/application-spec/generate-application/runtime/admin-runtime/admin-spec-runtime.js +0 -1
  328. package/dist/application-spec/generate-application/runtime/application-runtime.js +0 -1
  329. package/dist/application-spec/generate-application/runtime/application-spec-slice.js +0 -1
  330. package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-model-runtime.js +0 -1
  331. package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-runtime.js +0 -1
  332. package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-spec-runtime.js +0 -1
  333. package/dist/application-spec/generate-application/runtime/create-application.js +0 -1
  334. package/dist/application-spec/generate-application/runtime/factory-data/recipe-defaults.js +0 -1
  335. package/dist/application-spec/generate-application/runtime/factory-data/static-violations.js +0 -1
  336. package/dist/application-spec/generate-application/runtime/generate-runtime-instance.js +0 -1
  337. package/dist/application-spec/generate-application/runtime/index.d.ts +0 -8
  338. package/dist/application-spec/generate-application/runtime/index.js +0 -1
  339. package/dist/application-spec/generate-application/runtime/migrations/migration-runtime.js +0 -1
  340. package/dist/application-spec/generate-application/runtime/sections/build-sdk-optic.js +0 -1
  341. package/dist/application-spec/generate-application/runtime/sections/build-user-bound-optic.d.ts +0 -8
  342. package/dist/application-spec/generate-application/runtime/sections/build-user-bound-optic.js +0 -1
  343. package/dist/application-spec/generate-application/runtime/sections/expression-runtime.js +0 -1
  344. package/dist/application-spec/generate-application/runtime/sections/generate-memo-eval-plan-runtime.js +0 -1
  345. package/dist/application-spec/generate-application/runtime/sections/index.d.ts +0 -10
  346. package/dist/application-spec/generate-application/runtime/sections/index.js +0 -1
  347. package/dist/application-spec/generate-application/runtime/spec-runtime.js +0 -1
  348. package/dist/application-spec/generate-application/runtime-spec/index.d.ts +0 -5
  349. package/dist/application-spec/generate-application/runtime-spec/index.js +0 -1
  350. package/dist/configurator/application-runtime/extensions/systems/assistant-system/browser-details.d.ts +0 -17
  351. package/dist/configurator/application-runtime/extensions/systems/assistant-system/browser-details.js +0 -1
  352. package/dist/domain/domain-runtime/spec/module-checks/find-assistant-form-element-errors.js +0 -1
  353. package/dist/domain/domain-runtime/spec/module-checks/index.js +0 -1
  354. package/dist/domain/domain-runtime/spec/module-checks/merge-expression-modules.js +0 -1
  355. package/dist/domain/domain-runtime/spec/module-checks/project-modules.js +0 -1
  356. package/dist/domain/domain-runtime/spec/module-checks/resolve-imported-transformers.js +0 -1
  357. /package/dist/domain/{domain-runtime → spec}/errors/implementation-error-collector.d.ts +0 -0
  358. /package/dist/domain/{domain-runtime → spec}/errors/implementation-error-collector.js +0 -0
  359. /package/dist/domain/{domain-runtime → spec}/errors/implementation-error.d.ts +0 -0
  360. /package/dist/domain/{domain-runtime → spec}/errors/implementation-error.js +0 -0
  361. /package/dist/domain/{domain-runtime → spec}/errors/implementation-errors.d.ts +0 -0
  362. /package/dist/domain/{domain-runtime → spec}/errors/implementation-errors.js +0 -0
  363. /package/dist/domain/{domain-runtime → spec}/errors/index.d.ts +0 -0
  364. /package/dist/domain/{domain-runtime → spec}/errors/index.js +0 -0
  365. /package/dist/domain/{domain-runtime → spec}/errors/to-implementation-errors.d.ts +0 -0
  366. /package/dist/domain/{domain-runtime → spec}/errors/to-implementation-errors.js +0 -0
  367. /package/dist/domain/{domain-runtime/spec/module-checks → spec/modules}/element-registration.js +0 -0
  368. /package/dist/domain/{domain-runtime/spec/module-checks → spec/modules}/handler-registration.d.ts +0 -0
  369. /package/dist/domain/{domain-runtime/spec/module-checks → spec/modules}/handler-registration.js +0 -0
  370. /package/dist/domain/{domain-runtime/spec/module-checks → spec/modules}/resolve-action-modules.js +0 -0
  371. /package/dist/domain/{domain-runtime/spec/module-checks → spec/modules}/resolve-component-optic-modules.js +0 -0
  372. /package/dist/domain/{domain-runtime/spec/module-checks → spec/modules}/resolve-expression-modules.js +0 -0
  373. /package/dist/domain/{domain-runtime/spec/module-checks → spec/modules}/resolve-invariant-modules.js +0 -0
  374. /package/dist/{application-spec/generate-application/implementations → domain/spec/phx}/phx-domain.d.ts +0 -0
  375. /package/dist/{application-spec/generate-application/implementations → domain/spec/phx}/phx.js +0 -0
  376. /package/dist/{application-spec/generate-application → domain/spec}/runtime/admin-runtime/states-runtime.js +0 -0
  377. /package/dist/{application-spec/generate-application → domain/spec}/runtime/configurator-runtime/states-runtime.js +0 -0
  378. /package/dist/{application-spec/generate-application/runtime/sections → domain/spec/runtime/expressions}/reflection-constants-runtime.js +0 -0
  379. /package/dist/{application-spec/generate-application → domain/spec}/runtime/factory-data/factory-data-runtime.js +0 -0
  380. /package/dist/{application-spec/generate-application → domain/spec}/runtime/factory-data/index.d.ts +0 -0
  381. /package/dist/{application-spec/generate-application → domain/spec}/runtime/factory-data/index.js +0 -0
  382. /package/dist/{application-spec/generate-application → domain/spec}/runtime/migrations/index.d.ts +0 -0
  383. /package/dist/{application-spec/generate-application → domain/spec}/runtime/migrations/index.js +0 -0
  384. /package/dist/{application-spec/generate-application/runtime/spec-code/spec-code-module.js → domain/spec/runtime/optics/built-component-optic.js} +0 -0
  385. /package/dist/{application-spec/generate-application/runtime/sections → domain/spec/runtime/optics}/component-optic.js +0 -0
  386. /package/dist/{application-spec/generate-application → domain/spec}/runtime/sections/actions-runtime.js +0 -0
  387. /package/dist/{application-spec/generate-application → domain/spec}/runtime/sections/assistant-runtime.js +0 -0
  388. /package/dist/{application-spec/generate-application → domain/spec}/runtime/sections/data-runtime.js +0 -0
  389. /package/dist/{application-spec/generate-application → domain/spec}/runtime/sections/preset-runtime.js +0 -0
  390. /package/dist/{application-spec/generate-application → domain/spec}/runtime/sections/theme-runtime.js +0 -0
  391. /package/dist/{application-spec/generate-application → domain/spec}/runtime/sections/transformers-runtime.js +0 -0
  392. /package/dist/{application-spec/generate-application → domain/spec}/runtime/spec-code/index.d.ts +0 -0
  393. /package/dist/{application-spec/generate-application → domain/spec}/runtime/spec-code/index.js +0 -0
  394. /package/dist/{application-spec/generate-application → domain/spec}/runtime/spec-code/resolve-spec-code.js +0 -0
  395. /package/dist/{application-spec/generate-application → domain/spec}/runtime/spec-code/spec-code-module.d.ts +0 -0
  396. /package/dist/domain/{application/assistant/assistant-resolved-manifest.js → spec/runtime/spec-code/spec-code-module.js} +0 -0
  397. /package/dist/{application-spec/generate-application → domain/spec}/runtime-spec/decode-runtime-spec.d.ts +0 -0
  398. /package/dist/{application-spec/generate-application → domain/spec}/runtime-spec/decode-runtime-spec.js +0 -0
  399. /package/dist/{application-spec/generate-application → domain/spec}/runtime-spec/encode-runtime-spec.d.ts +0 -0
  400. /package/dist/{application-spec/generate-application → domain/spec}/runtime-spec/encode-runtime-spec.js +0 -0
  401. /package/dist/{application-spec/generate-application → domain/spec}/runtime-spec/encoded-runtime-spec.d.ts +0 -0
  402. /package/dist/{application-spec/generate-application → domain/spec}/runtime-spec/encoded-runtime-spec.js +0 -0
  403. /package/dist/{application-spec/generate-application → domain/spec}/runtime-spec/runtime-spec.js +0 -0
  404. /package/dist/{application-spec/generate-application → domain/spec}/runtime-spec/spec-code-id.js +0 -0
  405. /package/dist/domain/{application → spec/sections}/assistant/assistant-manifest.d.ts +0 -0
  406. /package/dist/domain/{application → spec/sections}/assistant/assistant-manifest.js +0 -0
  407. /package/dist/domain/{application → spec/sections}/assistant/assistant-resolved-manifest.d.ts +0 -0
  408. /package/dist/domain/{application → spec/sections}/assistant/form/assistant-form-element-name.d.ts +0 -0
  409. /package/dist/domain/{application → spec/sections}/assistant/form/assistant-form-element-name.js +0 -0
  410. /package/dist/domain/{application → spec/sections}/assistant/form/assistant-form-elements.d.ts +0 -0
  411. /package/dist/domain/{application → spec/sections}/assistant/form/assistant-form-elements.js +0 -0
  412. /package/dist/domain/{application → spec/sections}/assistant/form/assistant-resource-path.d.ts +0 -0
  413. /package/dist/domain/{application → spec/sections}/assistant/form/assistant-resource-path.js +0 -0
  414. /package/dist/domain/{application → spec/sections}/assistant/form/index.d.ts +0 -0
  415. /package/dist/domain/{application → spec/sections}/assistant/form/index.js +0 -0
@@ -31,6 +31,7 @@ export const generateApplicationSpecTsconfig=()=>`{
31
31
 
32
32
  "paths": {}
33
33
  },
34
- "include": ["../src", ".", "../prettier.config.js", "../eslint.config.js", "./globals.d.ts"]
34
+ "include": ["../src", ".", "../prettier.config.js", "../eslint.config.js", "./globals.d.ts"],
35
+ "exclude": ["workspace", "node_modules", "bower_components", "jspm_packages"]
35
36
  }
36
37
  `;
@@ -1,9 +1,2 @@
1
- export * from './runtime/sections/index.js';
2
- export * from './runtime/application-runtime.js';
3
- export { applicationSpecSlice, type ApplicationSpecSliceModules } from './runtime/application-spec-slice.js';
4
- export { type ApplicationModules, createApplication } from './runtime/create-application.js';
5
- export * from './runtime/factory-data/index.js';
6
- export * from './runtime/migrations/index.js';
7
- export { isConfiguratorModelSchemaCompatible } from './runtime/configurator-runtime/configurator-model-runtime.js';
1
+ export { ActionsRuntime, type ApplicationModules, ApplicationRuntime, type ApplicationRuntimeResult, type ApplicationSpecSliceModules, AssistantRuntime, type ComponentOptic, ComponentOptics, DataRuntime, type ExpressionImplementations, ExpressionRuntime, FactoryDataRuntime, type InvariantImplementations, type MigrationModules, MigrationRuntime, type MissingExpression, PresetRuntime, type RecipeDefaults, type StaticViolations, ThemeRuntime, TransformersRuntime, applicationSpecSlice, createApplication, evaluateReflectionConstants, evaluateStaticMemoEvalPlan, findReflectionConstants, generateMemoEvalPlanRuntime, generateRuntimeInstance, isConfiguratorModelSchemaCompatible, } from '#package/domain';
8
2
  export * from './code/index.js';
9
- export { generateRuntimeInstance } from './runtime/generate-runtime-instance.js';
@@ -1 +1 @@
1
- export*from"./runtime/sections/index.js";export*from"./runtime/application-runtime.js";export{applicationSpecSlice}from"./runtime/application-spec-slice.js";export{createApplication}from"./runtime/create-application.js";export*from"./runtime/factory-data/index.js";export*from"./runtime/migrations/index.js";export{isConfiguratorModelSchemaCompatible}from"./runtime/configurator-runtime/configurator-model-runtime.js";export*from"./code/index.js";export{generateRuntimeInstance}from"./runtime/generate-runtime-instance.js";
1
+ export{ActionsRuntime,ApplicationRuntime,AssistantRuntime,ComponentOptics,DataRuntime,ExpressionRuntime,FactoryDataRuntime,MigrationRuntime,PresetRuntime,ThemeRuntime,TransformersRuntime,applicationSpecSlice,createApplication,evaluateReflectionConstants,evaluateStaticMemoEvalPlan,findReflectionConstants,generateMemoEvalPlanRuntime,generateRuntimeInstance,isConfiguratorModelSchemaCompatible}from"#package/domain";export*from"./code/index.js";
@@ -27,7 +27,7 @@ export declare class AuthorizedClient<FINALIZE_DATA extends Record<string, unkno
27
27
  getTextToSpeech: (configurationId: string, content: string) => Promise<Blob>;
28
28
  getAssistantChatConnection: (configurationId: string) => AssistantChatConnection;
29
29
  compactAssistantThread: (configurationId: string) => Promise<AssistantThreadCompaction>;
30
- getAssistantEarlierThread: (configurationId: string, threadId: string, limit: number) => Promise<AssistantEarlierThread>;
30
+ getAssistantEarlierThread: (configurationId: string, threadId: string, limit?: number) => Promise<AssistantEarlierThread>;
31
31
  uploadAssistantImage: (configurationId: string, image: Blob) => Promise<AssistantImageUpload>;
32
32
  getAssistantImage: (configurationId: string, imageId: string) => Promise<Blob>;
33
33
  sendMessage: (configurationId: string, content: string, context?: Record<string, string>) => Promise<ReadableStream<ChatStreamChunk>>;
@@ -96,10 +96,11 @@ export interface AuthorizedPhoenixApiClient<FINALIZE_DATA extends Record<string,
96
96
  */
97
97
  compactAssistantThread: (configurationId: string) => Promise<AssistantThreadCompaction>;
98
98
  /**
99
- * Reads a closed assistant thread of the configuration that a later thread continues, at most
100
- * `limit` of its newest messages. Rejects with an {@link AssistantRequestError} when the server refuses.
99
+ * Reads a closed assistant thread of the configuration that a later thread continues: at most
100
+ * `limit` of its newest messages, or all of them without a limit. Rejects with an
101
+ * {@link AssistantRequestError} when the server refuses.
101
102
  */
102
- getAssistantEarlierThread: (configurationId: string, threadId: string, limit: number) => Promise<AssistantEarlierThread>;
103
+ getAssistantEarlierThread: (configurationId: string, threadId: string, limit?: number) => Promise<AssistantEarlierThread>;
103
104
  /**
104
105
  * Stores an image in the assistant thread of the configuration, creating the thread when there is
105
106
  * none yet: a screenshot the assistant took while a reply runs there, or an image the user attaches
@@ -2,7 +2,7 @@ import type { AnyClientTool } from '@tanstack/ai';
2
2
  import { type UIMessage } from '@tanstack/ai-client';
3
3
  import { type ObservableWithLastValue } from '@salsita-ai/common/utils';
4
4
  import { type AuthorizedPhoenixApiClient } from '#package/client';
5
- import type { AssistantManifest, DomainContextSelectors, DomainServicesSelectors, InitializableSystem, SessionAssistantSetup, SpecSelectors } from '#package/domain';
5
+ import type { AssistantManifest, DomainContextSelectors, DomainServicesSelectors, InitializableSystem, SessionAssistantSetup } from '#package/domain';
6
6
  import type { ConfiguratorExtensionSelectors } from '../../selectors.js';
7
7
  /** A tool of the assistant that the model calls and the browser runs, as the chat client accepts it. */
8
8
  export type AssistantClientTool = AnyClientTool;
@@ -15,7 +15,6 @@ export interface AssistantSystemContext {
15
15
  readonly configuratorExtensionSelectors: ConfiguratorExtensionSelectors;
16
16
  readonly domainContextSelectors: DomainContextSelectors;
17
17
  readonly domainServicesSelectors: DomainServicesSelectors;
18
- readonly specSelectors: SpecSelectors;
19
18
  readonly getConfigurationId: () => string;
20
19
  readonly getAuthorizedClient: () => AuthorizedPhoenixApiClient<any, any, any>;
21
20
  /** The assistant the initialized session runs: its tools, its exposed fields and whether chat runs at all. */
@@ -51,10 +50,19 @@ export interface AssistantChatSnapshot {
51
50
  * the chat was open, and the ones loaded with {@link AssistantSystem.loadEarlierThread}.
52
51
  */
53
52
  readonly earlierThreads: ReadonlyArray<AssistantEarlierThreadSnapshot>;
54
- /** True when the server holds a thread older than the oldest painted one. */
55
- readonly hasEarlierThread: boolean;
56
- /** True while that older thread is being loaded. */
53
+ /**
54
+ * The closed thread that {@link AssistantSystem.loadEarlierThread} loads next; `null` when the
55
+ * painted threads start the conversation. Usually the thread before the oldest painted one, but
56
+ * the oldest painted one itself when it was closed while only its newest messages were painted:
57
+ * loading it then paints it whole.
58
+ */
59
+ readonly earlierThreadId: string | null;
60
+ /** True while that thread is being loaded. */
57
61
  readonly isLoadingEarlierThread: boolean;
62
+ /** True when the thread of the chat has older messages than the painted ones on the server; see {@link AssistantSystem.loadOlderMessages}. */
63
+ readonly hasOlderMessages: boolean;
64
+ /** True while those older messages are being loaded. */
65
+ readonly isLoadingOlderMessages: boolean;
58
66
  }
59
67
  /** What else the caller of {@link AssistantSystem.send} learns about the message. */
60
68
  export interface AssistantSendOptions {
@@ -88,9 +96,9 @@ export interface AssistantPanelSnapshot {
88
96
  readonly isInputFocused: boolean;
89
97
  }
90
98
  /**
91
- * Owns the conversational assistant of a configurator: its client tools (`getBrowserDetails`,
92
- * `query` and `apply`), the chat with the server, the state of the built-in panel, and the record
93
- * of what changed in the configuration since the agent last acted, which every user message carries.
99
+ * Owns the conversational assistant of a configurator: its client tools (`query` and `apply`), the
100
+ * chat with the server, the state of the built-in panel, and the record of what changed in the
101
+ * configuration since the agent last acted, which every user message carries.
94
102
  *
95
103
  * The server owns the thread, so the chat keeps nothing in browser storage: its client hydrates
96
104
  * from the server and rejoins a reply that is still streaming.
@@ -113,11 +121,6 @@ export declare class AssistantSystem implements InitializableSystem {
113
121
  * background. Each leaves the set when its reply ends or when a new chat takes its thread over.
114
122
  */
115
123
  private readonly _finishing;
116
- /**
117
- * The thread before the oldest painted one, as the server named it; nothing when the painted
118
- * threads start the conversation. `hasEarlierThread` of the chat says whether it is set.
119
- */
120
- private _olderThreadId;
121
124
  /** The resume that is running, so two sends that find the thread locked share one. */
122
125
  private _resuming;
123
126
  /**
@@ -137,8 +140,6 @@ export declare class AssistantSystem implements InitializableSystem {
137
140
  * thread continues the same chain; any other new chat starts another one.
138
141
  */
139
142
  private _chain;
140
- /** The earlier thread that is being loaded, so a second press loads nothing twice. */
141
- private _loadingThreadId;
142
143
  private readonly _recorder;
143
144
  /** The recorder's subscription to the committed emissions of the store; made by the first `initialize()`. */
144
145
  private _recording;
@@ -272,10 +273,19 @@ export declare class AssistantSystem implements InitializableSystem {
272
273
  */
273
274
  loadScreenshotUrl: (imageId: string) => Promise<string>;
274
275
  /**
275
- * Loads the thread before the oldest painted one and paints it above. Does nothing when there is
276
- * none or one is being loaded. A load that fails is logged and can be asked for again.
276
+ * Loads the closed thread named by `earlierThreadId` of the chat, whole, and paints it above the
277
+ * painted ones; when it is the oldest painted thread itself, closed while only its newest messages
278
+ * were painted, it replaces that partial copy. Does nothing when there is none, one is being
279
+ * loaded, or the chat's own thread still has older messages: the earlier threads come above them.
280
+ * A load that fails is logged and can be asked for again.
277
281
  */
278
282
  loadEarlierThread: () => Promise<void>;
283
+ /**
284
+ * Loads the page of messages before the oldest painted one of the chat's thread and paints it
285
+ * above. Does nothing when the thread has no older messages or a page is being loaded. A load that
286
+ * fails is logged and can be asked for again; one that ends after its chat did is dropped.
287
+ */
288
+ loadOlderMessages: () => Promise<void>;
279
289
  /**
280
290
  * Stops the reply on both sides. Closing the stream alone keeps the server run going, because a
281
291
  * closed connection is also how a reload looks and a reload must be able to rejoin the run.
@@ -322,7 +332,7 @@ export declare class AssistantSystem implements InitializableSystem {
322
332
  private _uploadSuccessorImages;
323
333
  private _reportUploadFailure;
324
334
  private _sendOn;
325
- private _resume;
335
+ private _compact;
326
336
  /**
327
337
  * The `apply` call whose committed state is the step the configuration is at. Nothing at the bottom
328
338
  * of the history, where nothing can be undone: that step was not made by a change it could take back.
@@ -1 +1 @@
1
- import{ChatClient as e,fetchServerSentEvents as t}from"@tanstack/ai-client";import{BehaviorSubject as i}from"rxjs";import{skip as s}from"rxjs/operators";import{isShallowEqual as a}from"@salsita-ai/common/utils";import{assistantImageReference as r}from"@salsita-ai/contracts/assistant";import{AssistantRequestError as n}from"#package/client";import{createBrowserDetailsClientTool as o}from"./browser-details.js";import{ChangeRecorder as l}from"./change-recorder.js";import{createApplyClientTool as h,createQueryClientTool as c,toToolResult as d}from"./graphql-tools.js";let u=Object.freeze({messages:Object.freeze([]),isLoading:!1,error:void 0,failedStatus:void 0,isContinuable:!0,isLoaded:!1,isResuming:!1,earlierThreads:Object.freeze([]),hasEarlierThread:!1,isLoadingEarlierThread:!1}),_=Object.freeze({open:!1,hasUnreadReply:!1,isInputFocused:!1}),g=Object.freeze({}),f=d({results:[],committed:!1,sideEffects:[],warnings:[],screenshots:new Map,message:"Nothing was run, because the user closed the configurator while this reply was being written. Do not call any more tools in this reply and end it now. The tools work again as soon as the user writes the next message."}),m=e=>{if(e.getError())return!0;let t=e.getMessages().at(-1)?.parts.at(-1);return t?.type!=="tool-call"&&t?.type!=="tool-result"};export class AssistantSystem{_context;_tools;_chat=new i(u);_panel=new i(_);_activation=null;_current=null;_finishing=new Set;_olderThreadId=null;_resuming=null;_refused=null;_firstAttempt=null;_chain={};_loadingThreadId=null;_recorder;_recording=null;_applyToolCallIds=new WeakMap;_undoTipToolCallId=new i(void 0);_screenshotUrls=new Map;constructor(e){this._context=e;let{configuratorExtensionSelectors:t,domainContextSelectors:i,domainServicesSelectors:s,getAssistantSetup:a}=e;this._recorder=new l({maxEntities:30},{readers:{selectedEntityId:e=>i.getNavigationSystem().getActiveSelectionState(e),navigationState:e=>i.getNavigationSystem().getActiveNavigationState(e),viewState:e=>i.getNavigationSystem().getActiveViewState(e),toolState:e=>i.getNavigationSystem().getActiveToolState(e)},getExposedFields:()=>a().manifest?.fields??g,resolveLocalizable:e=>s.getResolveLocalizable()(e)});let r={getGraphQLSystem:()=>t.getGraphQLSystem(),getStoreSystem:()=>i.getStoreSystem(),getActiveMode:()=>i.getActiveMode(),getIsViewMode:()=>i.getIsViewMode(),clearChanges:()=>this._recorder.clear(this._committedState()),rememberCommit:(e,t)=>{this._applyToolCallIds.set(t,e),this._refreshUndoTip()}};this._tools=[o(),c(r),h(r)],i.getUndoSystem().tip$.subscribe(this._refreshUndoTip)}chat$=this._chat;panel$=this._panel;undoTipToolCallId$=this._undoTipToolCallId;getSessionManifest=()=>this._context.getAssistantSetup().manifest;initialize=()=>{let{committed:e}=this._context.domainContextSelectors.getStoreSystem().stateSlices;this._recording??=e.pipe(s(1)).subscribe(this._recorder.record),this._recorder.reset(e.value.state),this._endChat(),this._patchPanel(_),this._releaseScreenshotUrls(),this._activation&&this._startClient()};activate=()=>{this._endChat();let e={};return this._activation=e,this._startClient(),()=>{this._activation===e&&(this._activation=null,this._endChat())}};send=async(e,t=[],{onSent:i,onUnsent:s}={})=>{if(!this._chat.value.isContinuable&&!await this.resume())return;let a=this._current;if(!a)return;let r={changes:this._recorder.take(this._committedState()),locale:this._context.domainServicesSelectors.getI18n().locale},n=()=>this._recorder.reset(this._committedState()),o=!1,l=(t,s)=>(o||(o=!0,i?.()),this._sendOn(t,this._messageContent(e,s),r));this._firstAttempt=a;try{let e=0===t.length?[]:await this._uploadImages(a,t);if(null===e||!a.generation.active)return void n();if("refused"!==e){await l(a,e);let t=this._findRefusedMessageIndex(a);if(-1===t)return;this._refused={chat:a,index:t}}}finally{this._firstAttempt===a&&(this._firstAttempt=null)}if(!await this.resume()){o||n();return}let h=this._current,c=h?await this._uploadSuccessorImages(h,t):null;if(!h||null===c||"refused"===c||!h.generation.active){h&&"refused"===c&&this._reportUploadFailure(h,this._chat.value.error),o&&s?.(),n();return}await l(h,c)};resume=async()=>{let e=this._current;if(!e)return!1;if(this._chat.value.isContinuable)return!0;if(this._resuming)return this._resuming;let t=this._resume(e).finally(()=>{this._resuming===t&&(this._resuming=null)});return this._resuming=t,t};loadScreenshotUrl=e=>{let t=this._screenshotUrls.get(e);if(t)return t;let i=this._current;if(!i)return Promise.reject(Error(`The screenshot ${e} cannot be read, because the assistant chat is not active. Open the assistant panel of the configuration first.`));let s=this._screenshotUrls,a=i.authorizedClient.getAssistantImage(i.configurationId,e).then(e=>URL.createObjectURL(e));return s.set(e,a),a.catch(()=>{s.get(e)===a&&s.delete(e)}),a};loadEarlierThread=async()=>{let e=this._current,t=this._olderThreadId;if(!e||null===t||this._loadingThreadId===t)return;let i=this._chain;this._loadingThreadId=t,this._chat.next({...this._chat.value,isLoadingEarlierThread:!0});try{let s=await e.authorizedClient.getAssistantEarlierThread(e.configurationId,t,50);if(this._chain!==i||this._olderThreadId!==t)return;this._olderThreadId=s.previousThreadId,this._chat.next({...this._chat.value,earlierThreads:[{threadId:t,messages:s.messages},...this._chat.value.earlierThreads],hasEarlierThread:null!==s.previousThreadId})}catch(e){this._context.domainServicesSelectors.getLogger().warn("Could not load the earlier assistant conversation",{error:e})}finally{this._chain===i&&this._loadingThreadId===t&&(this._loadingThreadId=null,this._chat.next({...this._chat.value,isLoadingEarlierThread:!1}))}};stop=async()=>{let e=this._current;if(!e)return;let t=e.client.getCurrentRunId();if(e.client.stop(),null!=t)try{let i=e.getConnection();await fetch(`${i.url}/runs/${encodeURIComponent(t)}/cancel`,{method:"POST",headers:await i.headers()})}catch(e){this._context.domainServicesSelectors.getLogger().warn("Could not cancel the assistant run on the server",{error:e})}};reloadThread=()=>{if(!this._activation)return;let e=this._retireChat();e?.client.stop(),e?.dispose(),this._recorder.reset(this._committedState()),this._startClient()};undoToolCalls=e=>{let t=this._context.domainContextSelectors.getUndoSystem(),i=()=>{let t=this._findTipToolCallId();return void 0!==t&&e.has(t)};for(;i();)t.undo()};setOpen=e=>{this._patchPanel(e?{open:e,hasUnreadReply:!1}:{open:e,isInputFocused:!1})};setInputFocused=e=>{this._patchPanel({isInputFocused:e})};_findRefusedMessageIndex=e=>{var t;let i,{failedStatus:s,isContinuable:a}=this._chat.value;return this._firstAttempt===e&&e.generation.active&&409===s&&!a?(i=(t=e.client.getMessages()).map(e=>e.role).lastIndexOf("user"),t.slice(i+1).every(e=>0===e.parts.length)?i:-1):-1};_messageContent=(e,t)=>0===t.length?e:[...e?[{type:"text",content:e}]:[],...t.map(e=>({type:"image",source:{type:"url",value:r(e)}}))];_uploadImages=async(e,t)=>{if(0===t.length)return[];e.generation.active&&this._chat.next({...this._chat.value,error:void 0,failedStatus:void 0});try{return(await Promise.all(t.map(t=>e.authorizedClient.uploadAssistantImage(e.configurationId,t)))).map(({imageId:e})=>e)}catch(i){let t=i instanceof Error?i:Error(String(i));if(t instanceof n&&t.threadNotContinuable)return e.generation.active&&this._chat.next({...this._chat.value,isContinuable:!1,error:t,failedStatus:t.status}),"refused";return this._reportUploadFailure(e,t),null}};_uploadSuccessorImages=async(e,t)=>{if(0===t.length)return[];this._chat.next({...this._chat.value,isResuming:!0});try{return await this._uploadImages(e,t)}finally{e.generation.active&&this._chat.next({...this._chat.value,isResuming:!1})}};_reportUploadFailure=(e,t)=>{e.generation.active&&this._chat.next({...this._chat.value,error:t,failedStatus:t instanceof n?t.status:void 0}),this._context.domainServicesSelectors.getLogger().error("The images of the assistant message could not be uploaded",{},t)};_sendOn=async(e,t,i)=>{let{client:s}=e;s.getIsLoading()||null===s.getResumeState()||s.stop();try{await s.sendMessage({content:t,metadata:i})}catch(i){let t=i instanceof Error?i:Error(String(i));e.generation.active&&this._chat.next({...this._chat.value,error:t}),this._context.domainServicesSelectors.getLogger().error("The assistant message could not be sent",{},t)}};_resume=async e=>{this._chat.next({...this._chat.value,isResuming:!0,error:void 0,failedStatus:void 0});try{let{previousThreadId:t}=await e.authorizedClient.compactAssistantThread(e.configurationId);if(!e.generation.active)return!1;let{messages:i,earlierThreads:s,hasEarlierThread:a}=this._chat.value,r=this._refused?.chat===e?i.slice(0,this._refused.index):i;return e.generation.active=!1,this._current=null,e.client.stop(),e.dispose(),this._chat.next({...u,earlierThreads:[...s,{threadId:t,messages:r}],hasEarlierThread:a,isLoadingEarlierThread:null!==this._loadingThreadId}),this._startClient(),!0}catch(i){let t=i instanceof Error?i:Error(String(i));if(t instanceof n&&409===t.status)return e.generation.active&&this.reloadThread(),!1;return e.generation.active&&this._chat.next({...this._chat.value,isResuming:!1,error:t,failedStatus:t instanceof n?t.status:void 0}),this._context.domainServicesSelectors.getLogger().error("The assistant thread could not be resumed",{},t),!1}};_findTipToolCallId=()=>{let e=this._context.domainContextSelectors.getUndoSystem(),t=e.tip$.value?.committedState;return void 0!==t&&e.canUndo()?this._applyToolCallIds.get(t):void 0};_refreshUndoTip=()=>{let e=this._findTipToolCallId();e!==this._undoTipToolCallId.value&&this._undoTipToolCallId.next(e)};_committedState=()=>this._context.domainContextSelectors.getStoreSystem().stateSlices.committed.value.state;_patchPanel=e=>{let t={...this._panel.value,...e};a(t,this._panel.value)||this._panel.next(t)};_takeOverThread=e=>{for(let t of this._finishing)t.configurationId===e&&(t.client.stop(),t.dispose())};_startClient=()=>{let i={active:!0},s=this._context.getConfigurationId();this._takeOverThread(s);let r=this._context.getAuthorizedClient(),n=()=>{if(i.active){let{manifest:e,error:t}=this._context.getAssistantSetup();if(t)throw t;if(!e)throw Error("The assistant is disabled for this session.")}return r.getAssistantChatConnection(s)},o=e=>{if(!i.active)return;let t={...this._chat.value,...e};a(t,this._chat.value)||this._chat.next(t)},l=async(e,t)=>{let s=await fetch(e,t).finally(()=>o({isLoaded:!0})),a=s.headers.get("x-assistant-thread-continuable");return null!=a&&s.ok&&i.active&&0===this._chat.value.earlierThreads.length&&(this._olderThreadId=s.headers.get("x-assistant-previous-thread")),o({failedStatus:s.ok?void 0:s.status,...null!=a&&{isContinuable:"false"!==a,hasEarlierThread:null!==this._olderThreadId}}),s},h=async()=>({headers:await n().headers(),fetchClient:l}),c=t(()=>n().url,h),d=t(()=>`${n().url}/runs`,h),u=this._tools.map(e=>({...e,execute:(t,s)=>{if(!i.active)return f;let{manifest:a,error:r}=this._context.getAssistantSetup();return r||!a?{error:r?.message??"The assistant is disabled for this session."}:e.execute?.(t,s)}})),_=new e({threadId:`assistant:${s}`,connection:{...c,joinRun:d.joinRun},persistence:!0,history:{pageSize:50},tools:u,onMessagesChange:e=>o({messages:e}),onLoadingChange:e=>{let t=i.active&&this._chat.value.isLoading;o({isLoading:e}),!e&&m(_)&&(i.active?t&&!this._panel.value.open&&this._patchPanel({hasUnreadReply:!0}):p())},onErrorChange:e=>{i.active&&e!==this._chat.value.error&&(!e||-1===this._findRefusedMessageIndex(v))&&(o({error:e}),e&&this._context.domainServicesSelectors.getLogger().error("The assistant request failed",{status:this._chat.value.failedStatus},e))}}),g=!1,p=()=>{g||(g=!0,this._finishing.delete(v),_.dispose())},v={client:_,configurationId:s,generation:i,authorizedClient:r,getConnection:n,dispose:p};this._current=v,_.attach()};_retireChat=()=>{let e=this._current;return this._current=null,e&&(e.generation.active=!1),this._chain={},this._olderThreadId=null,this._resuming=null,this._refused=null,this._loadingThreadId=null,this._chat.value!==u&&this._chat.next(u),e};_releaseScreenshotUrls=()=>{for(let e of this._screenshotUrls.values())e.then(URL.revokeObjectURL,()=>void 0);this._screenshotUrls=new Map};_endChat=()=>{let e=this._retireChat();if(e){if(!e.client.getIsLoading()&&m(e.client))return void e.dispose();this._finishing.add(e)}}}
1
+ import{ChatClient as e,fetchServerSentEvents as t}from"@tanstack/ai-client";import{BehaviorSubject as s}from"rxjs";import{skip as i}from"rxjs/operators";import{isShallowEqual as a}from"@salsita-ai/common/utils";import{assistantImageReference as r}from"@salsita-ai/contracts/assistant";import{AssistantRequestError as n}from"#package/client";import{ChangeRecorder as o}from"./change-recorder.js";import{createApplyClientTool as l,createQueryClientTool as h,toToolResult as c}from"./graphql-tools.js";let d=Object.freeze({messages:Object.freeze([]),isLoading:!1,error:void 0,failedStatus:void 0,isContinuable:!0,isLoaded:!1,isResuming:!1,earlierThreads:Object.freeze([]),earlierThreadId:null,isLoadingEarlierThread:!1,hasOlderMessages:!1,isLoadingOlderMessages:!1}),u=Object.freeze({open:!1,hasUnreadReply:!1,isInputFocused:!1}),_=Object.freeze({}),g=c({results:[],committed:!1,sideEffects:[],warnings:[],screenshots:new Map,message:"Nothing was run, because the user closed the configurator while this reply was being written. Do not call any more tools in this reply and end it now. The tools work again as soon as the user writes the next message."}),f=e=>{if(e.getError())return!0;let t=e.getMessages().at(-1)?.parts.at(-1);return t?.type!=="tool-call"&&t?.type!=="tool-result"},m=async e=>{try{let t=await e.clone().json(),s=t?.page;return s?.truncated===!0&&"string"==typeof s.cursor&&""!==s.cursor}catch{return!1}};export class AssistantSystem{_context;_tools;_chat=new s(d);_panel=new s(u);_activation=null;_current=null;_finishing=new Set;_resuming=null;_refused=null;_firstAttempt=null;_chain={};_recorder;_recording=null;_applyToolCallIds=new WeakMap;_undoTipToolCallId=new s(void 0);_screenshotUrls=new Map;constructor(e){this._context=e;let{configuratorExtensionSelectors:t,domainContextSelectors:s,domainServicesSelectors:i,getAssistantSetup:a}=e;this._recorder=new o({maxEntities:30},{readers:{selectedEntityId:e=>s.getNavigationSystem().getActiveSelectionState(e),navigationState:e=>s.getNavigationSystem().getActiveNavigationState(e),viewState:e=>s.getNavigationSystem().getActiveViewState(e),toolState:e=>s.getNavigationSystem().getActiveToolState(e)},getExposedFields:()=>a().manifest?.fields??_,resolveLocalizable:e=>i.getResolveLocalizable()(e)});let r={getGraphQLSystem:()=>t.getGraphQLSystem(),getStoreSystem:()=>s.getStoreSystem(),getActiveMode:()=>s.getActiveMode(),getIsViewMode:()=>s.getIsViewMode(),clearChanges:()=>this._recorder.clear(this._committedState()),rememberCommit:(e,t)=>{this._applyToolCallIds.set(t,e),this._refreshUndoTip()}};this._tools=[h(r),l(r)],s.getUndoSystem().tip$.subscribe(this._refreshUndoTip)}chat$=this._chat;panel$=this._panel;undoTipToolCallId$=this._undoTipToolCallId;getSessionManifest=()=>this._context.getAssistantSetup().manifest;initialize=()=>{let{committed:e}=this._context.domainContextSelectors.getStoreSystem().stateSlices;this._recording??=e.pipe(i(1)).subscribe(this._recorder.record),this._recorder.reset(e.value.state),this._endChat(),this._patchPanel(u),this._releaseScreenshotUrls(),this._activation&&this._startClient()};activate=()=>{this._endChat();let e={};return this._activation=e,this._startClient(),()=>{this._activation===e&&(this._activation=null,this._endChat())}};send=async(e,t=[],{onSent:s,onUnsent:i}={})=>{if(!this._chat.value.isContinuable&&!await this.resume())return;let a=this._current;if(!a)return;let r={changes:this._recorder.take(this._committedState()),locale:this._context.domainServicesSelectors.getI18n().locale},n=()=>this._recorder.reset(this._committedState()),o=!1,l=(t,i)=>(o||(o=!0,s?.()),this._sendOn(t,this._messageContent(e,i),r));this._firstAttempt=a;try{let e=0===t.length?[]:await this._uploadImages(a,t);if(null===e||!a.generation.active)return void n();if("refused"!==e){await l(a,e);let t=this._findRefusedMessageIndex(a);if(-1===t)return;this._refused={chat:a,index:t}}}finally{this._firstAttempt===a&&(this._firstAttempt=null)}if(!await this.resume()){o||n();return}let h=this._current,c=h?await this._uploadSuccessorImages(h,t):null;if(!h||null===c||"refused"===c||!h.generation.active){h&&"refused"===c&&this._reportUploadFailure(h,this._chat.value.error),o&&i?.(),n();return}await l(h,c)};resume=async()=>{let e=this._current;if(!e)return!1;if(this._chat.value.isContinuable)return!0;if(this._resuming)return this._resuming;let t=this._compact(e).finally(()=>{this._resuming===t&&(this._resuming=null)});return this._resuming=t,t};loadScreenshotUrl=e=>{let t=this._screenshotUrls.get(e);if(t)return t;let s=this._current;if(!s)return Promise.reject(Error(`The screenshot ${e} cannot be read, because the assistant chat is not active. Open the assistant panel of the configuration first.`));let i=this._screenshotUrls,a=s.authorizedClient.getAssistantImage(s.configurationId,e).then(e=>URL.createObjectURL(e));return i.set(e,a),a.catch(()=>{i.get(e)===a&&i.delete(e)}),a};loadEarlierThread=async()=>{let e=this._current,{earlierThreadId:t,isLoadingEarlierThread:s,hasOlderMessages:i}=this._chat.value;if(!e||null===t||s||i)return;let a=this._chain;this._chat.next({...this._chat.value,isLoadingEarlierThread:!0});try{let s=await e.authorizedClient.getAssistantEarlierThread(e.configurationId,t);if(this._chain!==a||this._chat.value.earlierThreadId!==t)return;let[i,...r]=this._chat.value.earlierThreads,n={threadId:t,messages:s.messages};this._chat.next({...this._chat.value,earlierThreads:i?.threadId===t?[n,...r]:[n,...this._chat.value.earlierThreads],earlierThreadId:s.previousThreadId})}catch(e){this._context.domainServicesSelectors.getLogger().warn("Could not load the earlier assistant conversation",{error:e})}finally{this._chain===a&&this._chat.next({...this._chat.value,isLoadingEarlierThread:!1})}};loadOlderMessages=async()=>{let e=this._current,{hasOlderMessages:t,isLoadingOlderMessages:s}=this._chat.value;if(e&&t&&!s){this._chat.next({...this._chat.value,isLoadingOlderMessages:!0});try{await e.client.loadOlderMessages()}catch(e){this._context.domainServicesSelectors.getLogger().warn("Could not load older assistant messages",{error:e})}finally{e===this._current&&this._chat.next({...this._chat.value,hasOlderMessages:e.client.getHasOlderMessages(),isLoadingOlderMessages:!1})}}};stop=async()=>{let e=this._current;if(!e)return;let t=e.client.getCurrentRunId();if(e.client.stop(),null!=t)try{let s=e.getConnection();await fetch(`${s.url}/runs/${encodeURIComponent(t)}/cancel`,{method:"POST",headers:await s.headers()})}catch(e){this._context.domainServicesSelectors.getLogger().warn("Could not cancel the assistant run on the server",{error:e})}};reloadThread=()=>{if(!this._activation)return;let e=this._retireChat();e?.client.stop(),e?.dispose(),this._recorder.reset(this._committedState()),this._startClient()};undoToolCalls=e=>{let t=this._context.domainContextSelectors.getUndoSystem(),s=()=>{let t=this._findTipToolCallId();return void 0!==t&&e.has(t)};for(;s();)t.undo()};setOpen=e=>{this._patchPanel(e?{open:e,hasUnreadReply:!1}:{open:e,isInputFocused:!1})};setInputFocused=e=>{this._patchPanel({isInputFocused:e})};_findRefusedMessageIndex=e=>{var t;let s,{failedStatus:i,isContinuable:a}=this._chat.value;return this._firstAttempt===e&&e.generation.active&&409===i&&!a?(s=(t=e.client.getMessages()).map(e=>e.role).lastIndexOf("user"),t.slice(s+1).every(e=>0===e.parts.length)?s:-1):-1};_messageContent=(e,t)=>0===t.length?e:[...e?[{type:"text",content:e}]:[],...t.map(e=>({type:"image",source:{type:"url",value:r(e)}}))];_uploadImages=async(e,t)=>{if(0===t.length)return[];e.generation.active&&this._chat.next({...this._chat.value,error:void 0,failedStatus:void 0});try{return(await Promise.all(t.map(t=>e.authorizedClient.uploadAssistantImage(e.configurationId,t)))).map(({imageId:e})=>e)}catch(s){let t=s instanceof Error?s:Error(String(s));if(t instanceof n&&t.threadNotContinuable)return e.generation.active&&this._chat.next({...this._chat.value,isContinuable:!1,error:t,failedStatus:t.status}),"refused";return this._reportUploadFailure(e,t),null}};_uploadSuccessorImages=async(e,t)=>{if(0===t.length)return[];this._chat.next({...this._chat.value,isResuming:!0});try{return await this._uploadImages(e,t)}finally{e.generation.active&&this._chat.next({...this._chat.value,isResuming:!1})}};_reportUploadFailure=(e,t)=>{e.generation.active&&this._chat.next({...this._chat.value,error:t,failedStatus:t instanceof n?t.status:void 0}),this._context.domainServicesSelectors.getLogger().error("The images of the assistant message could not be uploaded",{},t)};_sendOn=async(e,t,s)=>{let{client:i}=e;i.getIsLoading()||null===i.getResumeState()||i.stop();try{await i.sendMessage({content:t,metadata:s})}catch(s){let t=s instanceof Error?s:Error(String(s));e.generation.active&&this._chat.next({...this._chat.value,error:t}),this._context.domainServicesSelectors.getLogger().error("The assistant message could not be sent",{},t)}};_compact=async e=>{this._chat.next({...this._chat.value,isResuming:!0,error:void 0,failedStatus:void 0});try{let{previousThreadId:t}=await e.authorizedClient.compactAssistantThread(e.configurationId);if(!e.generation.active)return!1;let{messages:s,earlierThreads:i,earlierThreadId:a,isLoadingEarlierThread:r}=this._chat.value,n=this._refused?.chat===e?s.slice(0,this._refused.index):s,o=e.client.getHasOlderMessages()?t:a;return e.generation.active=!1,this._current=null,e.client.stop(),e.dispose(),this._chat.next({...d,earlierThreads:[...i,{threadId:t,messages:n}],earlierThreadId:o,isLoadingEarlierThread:r}),this._startClient(),!0}catch(s){let t=s instanceof Error?s:Error(String(s));if(t instanceof n&&409===t.status)return e.generation.active&&this.reloadThread(),!1;return e.generation.active&&this._chat.next({...this._chat.value,isResuming:!1,error:t,failedStatus:t instanceof n?t.status:void 0}),this._context.domainServicesSelectors.getLogger().error("The assistant thread could not be resumed",{},t),!1}};_findTipToolCallId=()=>{let e=this._context.domainContextSelectors.getUndoSystem(),t=e.tip$.value?.committedState;return void 0!==t&&e.canUndo()?this._applyToolCallIds.get(t):void 0};_refreshUndoTip=()=>{let e=this._findTipToolCallId();e!==this._undoTipToolCallId.value&&this._undoTipToolCallId.next(e)};_committedState=()=>this._context.domainContextSelectors.getStoreSystem().stateSlices.committed.value.state;_patchPanel=e=>{let t={...this._panel.value,...e};a(t,this._panel.value)||this._panel.next(t)};_takeOverThread=e=>{for(let t of this._finishing)t.configurationId===e&&(t.client.stop(),t.dispose())};_startClient=()=>{let s={active:!0},i=this._context.getConfigurationId();this._takeOverThread(i);let r=this._context.getAuthorizedClient(),n=()=>{if(s.active){let{manifest:e,error:t}=this._context.getAssistantSetup();if(t)throw t;if(!e)throw Error("The assistant is disabled for this session.")}return r.getAssistantChatConnection(i)},o=e=>{if(!s.active)return;let t={...this._chat.value,...e};a(t,this._chat.value)||this._chat.next(t)},l=async(e,t)=>{let s=await fetch(e,t).finally(()=>o({isLoaded:!0})),i=s.headers.get("x-assistant-thread-continuable"),a=null!=i&&s.ok&&0===this._chat.value.earlierThreads.length,r=a?s.headers.get("x-assistant-previous-thread"):null;return o({failedStatus:s.ok?void 0:s.status,...null!=i&&{isContinuable:"false"!==i},...a&&{earlierThreadId:r,...null!==r&&{hasOlderMessages:await m(s)}}}),s},h=async()=>({headers:await n().headers(),fetchClient:l}),c=t(()=>n().url,h),d=t(()=>`${n().url}/runs`,h),u=this._tools.map(e=>({...e,execute:(t,i)=>{if(!s.active)return g;let{manifest:a,error:r}=this._context.getAssistantSetup();return r||!a?{error:r?.message??"The assistant is disabled for this session."}:e.execute?.(t,i)}})),_=new e({threadId:`assistant:${i}`,connection:{...c,joinRun:d.joinRun},persistence:!0,history:{pageSize:50},tools:u,onMessagesChange:e=>o({messages:e,hasOlderMessages:_.getHasOlderMessages()}),onLoadingChange:e=>{let t=s.active&&this._chat.value.isLoading;o({isLoading:e}),!e&&f(_)&&(s.active?t&&!this._panel.value.open&&this._patchPanel({hasUnreadReply:!0}):v())},onErrorChange:e=>{s.active&&e!==this._chat.value.error&&(!e||-1===this._findRefusedMessageIndex(S))&&(o({error:e}),e&&this._context.domainServicesSelectors.getLogger().error("The assistant request failed",{status:this._chat.value.failedStatus},e))}}),p=!1,v=()=>{p||(p=!0,this._finishing.delete(S),_.dispose())},S={client:_,configurationId:i,generation:s,authorizedClient:r,getConnection:n,dispose:v};this._current=S,_.attach()};_retireChat=()=>{let e=this._current;return this._current=null,e&&(e.generation.active=!1),this._chain={},this._resuming=null,this._refused=null,this._chat.value!==d&&this._chat.next(d),e};_releaseScreenshotUrls=()=>{for(let e of this._screenshotUrls.values())e.then(URL.revokeObjectURL,()=>void 0);this._screenshotUrls=new Map};_endChat=()=>{let e=this._retireChat();if(e){if(!e.client.getIsLoading()&&f(e.client))return void e.dispose();this._finishing.add(e)}}}
@@ -1,6 +1,6 @@
1
1
  import { type ExecutionResult } from 'graphql';
2
2
  import { type Localizable } from '@salsita-ai/common/utils';
3
- import { type $DomainEntity, type AgentScreenshotComponent, type ComponentSnapshot, type DomainContextSelectors, type DomainEntity, type DomainServicesSelectors, type DomainState, type InitializationGeneration, type SessionAssistantSetup, type SpecSelectors, type StateUpdateEmission } from '#package/domain';
3
+ import { type $DomainEntity, type AgentScreenshotComponent, type ComponentSnapshot, type DomainContextSelectors, type DomainEntity, type DomainServicesSelectors, type DomainState, type InitializationGeneration, type SessionAssistantSetup, type StateUpdateEmission } from '#package/domain';
4
4
  import { type AssistantWarning } from './violations.js';
5
5
  /** One single-operation GraphQL document with its own variables, as executed by {@link GraphQLSystem}. */
6
6
  export interface GraphQLOperation {
@@ -31,7 +31,6 @@ export interface GraphQLSystemContext {
31
31
  readonly uploadScreenshot: (image: Blob) => Promise<{
32
32
  readonly imageId: string;
33
33
  }>;
34
- readonly specSelectors: SpecSelectors;
35
34
  readonly domainContextSelectors: DomainContextSelectors;
36
35
  readonly domainServicesSelectors: DomainServicesSelectors;
37
36
  }
@@ -82,6 +81,13 @@ export interface GraphQLExecution {
82
81
  * `null` and values that are not localizable pass through, so the schema's nullability decides.
83
82
  */
84
83
  export declare const localize: (value: unknown, resolveLocalizable: (message: Localizable) => string) => unknown;
84
+ /**
85
+ * The code of the error a screenshot that was not taken fails its own field with. Such an error is
86
+ * no failure of its operation: the screenshot is only a look at the configuration, so it neither
87
+ * stops the operations after it nor keeps `apply` from committing, and the assistant panel shows a
88
+ * query that failed only on it as done.
89
+ */
90
+ export declare const SCREENSHOT_NOT_TAKEN = "SCREENSHOT_NOT_TAKEN";
85
91
  /**
86
92
  * Executes GraphQL operations against the schema generated from the application spec `assistant`
87
93
  * manifest, resolving it against the committed domain state. Agent-independent: the assistant's
@@ -1 +1 @@
1
- import{GraphQLError as e,NoSchemaIntrospectionCustomRule as t,defaultFieldResolver as i,execute as n,getNamedType as o,parse as r,specifiedRules as a,validate as s,validateSchema as l}from"graphql";import{assertExistence as c,createSelector as h,isMessageDescriptor as d,isMultilingualString as u}from"@salsita-ai/common/utils";import{AGENT_SCREENSHOT_MAX_SIDE as m,DomainEntityIdSchema as f,agentScreenshotComponent as p,createAssistantExecutionSchema as g,findAssistantMutation as v}from"#package/domain";import{ExportBusyError as y}from"../export-system/export-busy-error.js";import{closeUnclosedBraces as S}from"./close-unclosed-braces.js";import{createEntityMeta as w}from"./entity-meta.js";import{injectAssistantLenses as _}from"./inject-assistant-lenses.js";import{readSideEffects as x}from"./side-effects.js";import{ViolationsError as $,readStateWarnings as b,readViolationEntries as E}from"./violations.js";let T={errors:[new e("The configurator does not provide this request. This is a fault in the configurator, not in your request. Tell the user this is not available.")]},C={errors:[new e("The configuration is not loaded yet, so there is no state to query. Run the query again once the configurator has finished loading.")]},M="Not taken: another configuration was loaded while this request ran. Query the current configuration before asking for screenshots again.",R=class ScreenshotTooLargeError extends Error{constructor(e,t){super(`The view is configured at ${e} \xd7 ${t} px, more than the ${m} \xd7 ${m} px a screenshot may have.`),this.name="ScreenshotTooLargeError"}},k=new RegExp(f.pattern),j=[...a,t],L=e=>"object"==typeof e&&null!==e&&"type"in e&&"string"==typeof e.type&&"id"in e&&"string"==typeof e.id,N=(e,t)=>"object"==typeof e&&null!==e?Reflect.get(e,t):void 0,A=e=>e instanceof Error?e.message:String(e),z=e=>/[.!?]$/.test(e)?e:`${e}.`,q=e=>"object"==typeof e&&null!==e&&Object.getPrototypeOf(e)===Object.prototype,O=(e,t)=>{let i=q(e)?e._raw:void 0;if(L(i))return i;if(!Array.isArray(e)&&!q(e))return e;if(t.has(e))throw Error("The value contains itself.");let n=new Set([...t,e]);return Array.isArray(e)?e.map(e=>O(e,n)):Object.fromEntries(Object.entries(e).map(([e,t])=>[e,O(t,n)]))};export const localize=(e,t)=>Array.isArray(e)?e.map(e=>localize(e,t)):"string"==typeof e||d(e)||u(e)?t(e):e;let F=t=>new e(`The configurator cannot handle this request: ${z(t)} This is a fault in the configurator, not in your request. Tell the user this is not available.`),I="SCREENSHOT_NOT_TAKEN",V=(t,i)=>new e(t,{originalError:i,extensions:{code:I}}),P=e=>(e.errors??[]).some(e=>e.extensions.code!==I),D=t=>({errors:[new e(`Not run: operation ${t+1} failed, so the operations after it were skipped and no change of the list takes effect. Fix the failing operation and send the whole list again.`)]});export class GraphQLSystem{_context;_selectSchema=h([h.leaf(e=>e)],e=>{try{let t=g(e),i=l(t);return i.length>0?F(i.map(e=>e.message).join(" ")):t}catch(e){return F(A(e))}});_selectLenses=h([h.leaf(e=>e)],e=>r(e));_selectFieldResolver=h([h.leaf(e=>e)],t=>(n,r,a,s)=>{if(s.parentType===s.schema.getQueryType())return i(n,r,a,s);if(s.parentType===s.schema.getMutationType())return this._resolveMutation(s.fieldName,String(s.path.key),r,a);if(!L(n))return i(n,r,a,s);if("meta"===s.fieldName){let e;return w({entity:n,state:("object"==typeof(e=N(n,"_state"))&&null!==e&&"entities"in e&&"rootEntityId"in e?e:void 0)??a.state},{manifest:a.manifest,recipes:this._recipeContext(),prepareStateEmission:(e,t,i)=>{let n=this._context.domainContextSelectors.getStoreSystem().prepareStateEmission(e,t,i);return a.validities.set(n.state,n.validity),n},find$Entity:(e,t)=>this._find$Entity(e,t),validateEntity:e=>this._context.domainContextSelectors.getDomain().validateEntity(e),takeScreenshot:(e,t)=>this._takeScreenshot(e,t,a),validateState:e=>this._validateCached(e,a)})}let{source:l,localized:c}=t[s.parentType.name]?.[s.fieldName]??{source:s.fieldName},h=((t,i)=>{try{return N(t,i)}catch(n){throw new e(`Expression "${i}" failed on ${L(t)?t.id:"an entity"}: ${z(A(n))} This is a fault in the configurator, not in your request. Tell the user this is not available.`,{originalError:n instanceof Error?n:void 0})}})(n,l);return c?localize(h,this._context.domainServicesSelectors.getResolveLocalizable()):l.startsWith("$")&&"JSON"===o(s.returnType).name?((t,i,n)=>{try{return O(n,new Set)}catch(n){throw new e(`Expression "${i}" returned a value that is not plain serializable data on ${L(t)?t.id:"an entity"}: ${z(A(n))} This is a fault in the configurator, not in your request. Tell the user this is not available.`,{originalError:n instanceof Error?n:void 0})}})(n,l,h):h});constructor(e){this._context=e}_get$Entity=(e,t)=>this._context.domainContextSelectors.getDomain().get$Entity(e,t);_find$Entity=(e,t)=>this._context.domainContextSelectors.getDomain().getEntity(e,t)?this._get$Entity(e,t):null;_validateState=e=>this._context.domainContextSelectors.getValidationProjections().validateState(e);_validateCached=(e,{validities:t})=>{let i=t.get(e);if(i)return i;let n=this._validateState(e);return t.set(e,n),n};_recipeContext=()=>({componentReader:this._context.domainContextSelectors.getComponentReader(),recipeCooker:this._context.domainContextSelectors.getRecipeCookerSystem(),resolveLocalizable:this._context.domainServicesSelectors.getResolveLocalizable()});_rootValue={warnings:(e,t)=>b(this._validateCached(t.state,t),void 0,this._context.domainServicesSelectors.getResolveLocalizable()),root:(e,{state:t})=>this._get$Entity(t.rootEntityId,t),entities:({ids:t},{state:i})=>{if(null==t)return i.entities.map(e=>this._get$Entity(e.id,i));var n=i.rootEntityId;let o=t.filter(e=>!k.test(e));if(o.length>0)throw new e(`${o.map(e=>`"${e}"`).join(", ")} ${1===o.length?"is not an entity id":"are not entity ids"}. Entity ids have the form "<Type>-<number>", e.g. "${n}". Use ids as returned by the "id" field.`);return t.map(e=>k.test(e)?this._find$Entity(e,i):null)},selectedEntity:(e,{state:t})=>this._find$Entity(this._context.domainContextSelectors.getNavigationSystem().getActiveSelectionState(t),t),navigation:(e,{state:t})=>{let i=this._context.domainContextSelectors.getNavigationSystem();return{navigationState:i.getActiveNavigationState(t),viewState:i.getActiveViewState(t),toolState:i.getActiveToolState(t)}}};_resolveType=e=>L(e)?e.type:void 0;_generation={active:!0};_renderScreenshot=async(e,t,i)=>{let n=this._context.domainContextSelectors.getComponentReader().readOneComponent({entityId:e,componentType:p,instanceName:t},i);if(!n)return null;let{width:o,height:r}=n.state;if(o>m||r>m)throw new R(o,r);let a=await this._context.renderScreenshot(n,i);return null===a?null:new Blob([a],{type:"JPEG"===n.state.fileFormat?"image/jpeg":"image/png"})};initialize=()=>{this._generation.active=!1,this._generation={active:!0}};_resolveMutation=(t,i,n,o)=>{if(void 0!==o.failedMutationField)throw new e(`Not run: the earlier field "${o.failedMutationField}" of this operation failed, so "${i}" was skipped and no change of the operation takes effect. Fix the failing field and send the operation again.`);try{return this._runMutation(t,n,o)}catch(e){throw o.failedMutationField=i,e}};_runMutation=(t,i,n)=>{let o=v(t,n.manifest);if(!o)throw new e(`The schema declares the mutation "${t}", but the configurator has no implementation for it. This is a fault in the configurator, not in your request. Tell the user this is not available.`);let r=n.state,a=o.implementation(i,r,{manifest:n.manifest,action:this._context.domainContextSelectors.getActionSystem().createContext(r),resolveLocalizable:this._context.domainServicesSelectors.getResolveLocalizable()});if(a.updates.length>0){let i=this._context.domainContextSelectors.getStoreSystem().prepareStateEmission(a.updates,r,"committed"),{validity:o}=i;if("uncaught"===o.severity)throw new e(`The changes of "${t}" were not applied, because the resulting configuration is invalid: validating it threw: ${z(A(o.error))} Change the request so the configuration stays valid.`,{originalError:o.error});if(!o.valid)throw new $(`The changes of "${t}" were not applied, because the resulting configuration has ${o.severity} violations.`,E(o,this._context.domainServicesSelectors.getResolveLocalizable()));n.emissions.push(i),n.validities.set(i.state,o),n.state=i.state}return a.readResult({previousState:r,state:n.state})};_takeScreenshot=({entity:t,state:i},n,o)=>{let r=o.manifest.screenshots?.[t.type]?.find(e=>e.view===n);if(!r)return Promise.reject(new e(`The schema declares the screenshot view "${n}" on ${t.type}, but the configurator has no view of that name. This is a fault in the configurator, not in your request. Tell the user this is not available.`));let a=o.lastScreenshot.then(async()=>{if(!o.generation.active)throw V(M);let e=await this._renderScreenshot(t.id,r.instanceName,i).catch(e=>{throw V(e instanceof y?"User made concurrent actions that prevented the screenshot from being taken, try again":e instanceof R?`The screenshot of ${t.id} from "${n}" cannot be taken: ${e.message} Tell the user the screenshot is not available.`:`The screenshot of ${t.id} from "${n}" could not be taken: ${z(A(e))} Try again; if it fails again, tell the user the screenshot is not available.`,e instanceof Error?e:void 0)});if(!o.generation.active)throw V(M);if(null===e)return null;let{imageId:a}=await this._context.uploadScreenshot(e).catch(e=>{throw V(`The screenshot of ${t.id} from "${n}" was taken but could not be stored: ${z(A(e))} Try again; if it fails again, tell the user the screenshot is not available.`,e instanceof Error?e:void 0)}),s=`${t.id}/${n}`,l=[...o.screenshots.values()].filter(e=>e.entityId===t.id&&e.view===n).length,c=0===l?s:`${s}#${l+1}`;return o.screenshots.set(c,{entityId:t.id,view:n,imageId:a}),{image:c}});return o.lastScreenshot=a.catch(()=>void 0),a};_setup=()=>{let{manifest:t,error:i}=this._context.getAssistantSetup();if(i)return{ready:!1,result:{errors:[new e(i.message,{originalError:i})]}};if(!t)return{ready:!1,result:T};let n=this._selectSchema(t.sdl);return n instanceof e?{ready:!1,result:{errors:[n]}}:{ready:!0,assistant:t,schema:n,lenses:t.lenses?.definitions?this._selectLenses(t.lenses.definitions):void 0,fieldResolver:this._selectFieldResolver(t.fields)}};_run=async(t,i,o,a)=>{var l;let c;try{c=r(t)}catch(t){return{errors:[t instanceof e?t:new e(A(t))]}}let h=s(o.schema,c,j);return h.length>0?{errors:h}:(l=await n({schema:o.schema,document:c,rootValue:this._rootValue,contextValue:a,variableValues:i.variables,operationName:i.operationName,fieldResolver:o.fieldResolver,typeResolver:this._resolveType}),l.errors?.some(e=>e.originalError instanceof $)?{...l,errors:l.errors.flatMap(t=>t.originalError instanceof $?t.originalError.entries.map(({type:i,entityId:n,message:o})=>new e(o??i,{nodes:t.nodes,source:t.source,positions:t.positions,path:t.path,extensions:{code:"VIOLATION",type:i,entityId:n}})):[t])}:l)};prepare=async(t,i,n=this._generation)=>{let o,r=this._setup();if(!r.ready)return i.map(()=>({result:r.result,emissions:[],screenshots:new Map}));let a={manifest:r.assistant,state:t,emissions:[],failedMutationField:void 0,screenshots:new Map,lastScreenshot:Promise.resolve(),generation:n,validities:new WeakMap},s=[];for(let[t,n]of i.entries())if(void 0===o){let i=a.emissions.length,l=a.screenshots.size;a.failedMutationField=void 0;let c=S(n.document),h=r.lenses?_(c,r.lenses):c,d=h instanceof e?{errors:[h]}:await this._run(h,n,r,a);await a.lastScreenshot,s.push({result:d,emissions:a.emissions.slice(i),screenshots:new Map([...a.screenshots].slice(l))}),P(d)&&(o=t)}else s.push({result:D(o),emissions:[],screenshots:new Map});return s};readSideEffects=e=>{let t=this._context.domainServicesSelectors.getResolveLocalizable();return e.flatMap(({emissions:e})=>e.flatMap(e=>x(e.updates,t)))};readScreenshots=e=>new Map(e.flatMap(({screenshots:e})=>[...e]));readWarnings=(e,t)=>{let i=t.flatMap(({emissions:e})=>e).at(-1);return void 0===i||t.some(({result:e})=>P(e))?[]:b(i.validity,this._validateState(e),this._context.domainServicesSelectors.getResolveLocalizable())};_prepareAndCommit=async(e,t)=>{let i,n,o,r=this._context.domainContextSelectors.getStoreSystem(),a=r.stateSlices.committed.value.state,s=await this.prepare(a,e,t),l=s.map(({result:e})=>e),h=this.readSideEffects(s),d=this.readScreenshots(s),u=s.flatMap(e=>e.emissions);if(!t.active)return{results:l,sideEffects:h,screenshots:d,warnings:[],outcome:"conflict"};if(l.some(P)||0===u.length)return{results:l,sideEffects:h,screenshots:d,warnings:[],outcome:"none"};let m=(i=c(u[0]),n=c(u[u.length-1]),o=u.some(e=>void 0!==e.transformationLog),{kind:"committed",previousState:i.previousState,state:n.state,updates:u.flatMap(e=>e.updates),validity:n.validity,transformationLog:o?u.flatMap(e=>e.transformationLog??[]):void 0});return{results:l,sideEffects:h,screenshots:d,warnings:this.readWarnings(a,s),outcome:r.commitPrepared(m),preparedState:m.state}};execute=async e=>{let t=this._generation;if(!this._context.domainContextSelectors.getStoreSystem().isInitialized)return{results:e.map(()=>C),committed:!1,sideEffects:[],warnings:[],screenshots:new Map};let i=await this._prepareAndCommit(e,t),{results:n,sideEffects:o,warnings:r,screenshots:a,outcome:s,preparedState:l}="conflict"===i.outcome&&t.active?await this._prepareAndCommit(e,t):i;return"committed"===s?{results:n,committed:!0,sideEffects:o,warnings:r,screenshots:a,preparedState:l}:"held"===s?{results:n,committed:!1,message:"The changes wait for the user's approval and are not applied yet. Do not send them again; the next `[changes]` block lists them once approved.",sideEffects:o,warnings:r,screenshots:a,preparedState:l}:"conflict"===s?{results:n,committed:!1,message:"The changes were not committed, because the configuration changed while they were being applied. The results describe a state that was discarded. Query the current configuration and send the operations again if they still make sense.",sideEffects:o,warnings:r,screenshots:a}:{results:n,committed:!1,sideEffects:o,warnings:r,screenshots:a}}}
1
+ import{GraphQLError as e,NoSchemaIntrospectionCustomRule as t,defaultFieldResolver as i,execute as n,getNamedType as o,parse as r,specifiedRules as s,validate as a,validateSchema as l}from"graphql";import{assertExistence as c,createSelector as h,isMessageDescriptor as d,isMultilingualString as u}from"@salsita-ai/common/utils";import{AGENT_SCREENSHOT_MAX_SIDE as m,DomainEntityIdSchema as f,agentScreenshotComponent as p,createAssistantExecutionSchema as g,findAssistantMutation as v}from"#package/domain";import{ExportBusyError as y}from"../export-system/export-busy-error.js";import{closeUnclosedBraces as S}from"./close-unclosed-braces.js";import{createEntityMeta as _}from"./entity-meta.js";import{injectAssistantLenses as w}from"./inject-assistant-lenses.js";import{readSideEffects as x}from"./side-effects.js";import{ViolationsError as E,readStateWarnings as T,readViolationEntries as $}from"./violations.js";let b={errors:[new e("The configurator does not provide this request. This is a fault in the configurator, not in your request. Tell the user this is not available.")]},C={errors:[new e("The configuration is not loaded yet, so there is no state to query. Run the query again once the configurator has finished loading.")]},N="Not taken: another configuration was loaded while this request ran. Query the current configuration before asking for screenshots again.",M=class ScreenshotTooLargeError extends Error{constructor(e,t){super(`The view is configured at ${e} \xd7 ${t} px, more than the ${m} \xd7 ${m} px a screenshot may have.`),this.name="ScreenshotTooLargeError"}},R=new RegExp(f.pattern),k=[...s,t],j=e=>"object"==typeof e&&null!==e&&"type"in e&&"string"==typeof e.type&&"id"in e&&"string"==typeof e.id,A=(e,t)=>"object"==typeof e&&null!==e?Reflect.get(e,t):void 0,L=e=>e instanceof Error?e.message:String(e),O=e=>/[.!?]$/.test(e)?e:`${e}.`,z=e=>"object"==typeof e&&null!==e&&Object.getPrototypeOf(e)===Object.prototype,q=(e,t)=>{let i=z(e)?e._raw:void 0;if(j(i))return i;if(!Array.isArray(e)&&!z(e))return e;if(t.has(e))throw Error("The value contains itself.");let n=new Set([...t,e]);return Array.isArray(e)?e.map(e=>q(e,n)):Object.fromEntries(Object.entries(e).map(([e,t])=>[e,q(t,n)]))};export const localize=(e,t)=>Array.isArray(e)?e.map(e=>localize(e,t)):"string"==typeof e||d(e)||u(e)?t(e):e;let F=t=>new e(`The configurator cannot handle this request: ${O(t)} This is a fault in the configurator, not in your request. Tell the user this is not available.`);export const SCREENSHOT_NOT_TAKEN="SCREENSHOT_NOT_TAKEN";let I=(t,i)=>new e(t,{originalError:i,extensions:{code:SCREENSHOT_NOT_TAKEN}}),V=e=>(e.errors??[]).some(e=>e.extensions.code!==SCREENSHOT_NOT_TAKEN),P=t=>({errors:[new e(`Not run: operation ${t+1} failed, so the operations after it were skipped and no change of the list takes effect. Fix the failing operation and send the whole list again.`)]});export class GraphQLSystem{_context;_selectSchema=h([h.leaf(e=>e)],e=>{try{let t=g(e),i=l(t);return i.length>0?F(i.map(e=>e.message).join(" ")):t}catch(e){return F(L(e))}});_selectLenses=h([h.leaf(e=>e)],e=>r(e));_selectFieldResolver=h([h.leaf(e=>e)],t=>(n,r,s,a)=>{if(a.parentType===a.schema.getQueryType())return i(n,r,s,a);if(a.parentType===a.schema.getMutationType())return this._resolveMutation(a.fieldName,String(a.path.key),r,s);if(!j(n))return i(n,r,s,a);if("meta"===a.fieldName){let e;return _({entity:n,state:("object"==typeof(e=A(n,"_state"))&&null!==e&&"entities"in e&&"rootEntityId"in e?e:void 0)??s.state},{manifest:s.manifest,recipes:this._recipeContext(),prepareStateEmission:(e,t,i)=>{let n=this._context.domainContextSelectors.getStoreSystem().prepareStateEmission(e,t,i);return s.validities.set(n.state,n.validity),n},find$Entity:(e,t)=>this._find$Entity(e,t),validateEntity:e=>this._context.domainContextSelectors.getDomain().validateEntity(e),takeScreenshot:(e,t)=>this._takeScreenshot(e,t,s),validateState:e=>this._validateCached(e,s)})}let{source:l,localized:c}=t[a.parentType.name]?.[a.fieldName]??{source:a.fieldName},h=((t,i)=>{try{return A(t,i)}catch(n){throw new e(`Expression "${i}" failed on ${j(t)?t.id:"an entity"}: ${O(L(n))} This is a fault in the configurator, not in your request. Tell the user this is not available.`,{originalError:n instanceof Error?n:void 0})}})(n,l);return c?localize(h,this._context.domainServicesSelectors.getResolveLocalizable()):l.startsWith("$")&&"JSON"===o(a.returnType).name?((t,i,n)=>{try{return q(n,new Set)}catch(n){throw new e(`Expression "${i}" returned a value that is not plain serializable data on ${j(t)?t.id:"an entity"}: ${O(L(n))} This is a fault in the configurator, not in your request. Tell the user this is not available.`,{originalError:n instanceof Error?n:void 0})}})(n,l,h):h});constructor(e){this._context=e}_get$Entity=(e,t)=>this._context.domainContextSelectors.getDomain().get$Entity(e,t);_find$Entity=(e,t)=>this._context.domainContextSelectors.getDomain().getEntity(e,t)?this._get$Entity(e,t):null;_validateState=e=>this._context.domainContextSelectors.getValidationProjections().validateState(e);_validateCached=(e,{validities:t})=>{let i=t.get(e);if(i)return i;let n=this._validateState(e);return t.set(e,n),n};_recipeContext=()=>({componentReader:this._context.domainContextSelectors.getComponentReader(),recipeCooker:this._context.domainContextSelectors.getRecipeCookerSystem(),resolveLocalizable:this._context.domainServicesSelectors.getResolveLocalizable()});_rootValue={warnings:(e,t)=>T(this._validateCached(t.state,t),void 0,this._context.domainServicesSelectors.getResolveLocalizable()),root:(e,{state:t})=>this._get$Entity(t.rootEntityId,t),entities:({ids:t},{state:i})=>{if(null==t)return i.entities.map(e=>this._get$Entity(e.id,i));var n=i.rootEntityId;let o=t.filter(e=>!R.test(e));if(o.length>0)throw new e(`${o.map(e=>`"${e}"`).join(", ")} ${1===o.length?"is not an entity id":"are not entity ids"}. Entity ids have the form "<Type>-<number>", e.g. "${n}". Use ids as returned by the "id" field.`);return t.map(e=>R.test(e)?this._find$Entity(e,i):null)},selectedEntity:(e,{state:t})=>this._find$Entity(this._context.domainContextSelectors.getNavigationSystem().getActiveSelectionState(t),t),navigation:(e,{state:t})=>{let i=this._context.domainContextSelectors.getNavigationSystem();return{navigationState:i.getActiveNavigationState(t),viewState:i.getActiveViewState(t),toolState:i.getActiveToolState(t)}}};_resolveType=e=>j(e)?e.type:void 0;_generation={active:!0};_renderScreenshot=async(e,t,i)=>{let n=this._context.domainContextSelectors.getComponentReader().readOneComponent({entityId:e,componentType:p,instanceName:t},i);if(!n)return null;let{width:o,height:r}=n.state;if(o>m||r>m)throw new M(o,r);let s=await this._context.renderScreenshot(n,i);return null===s?null:new Blob([s],{type:"JPEG"===n.state.fileFormat?"image/jpeg":"image/png"})};initialize=()=>{this._generation.active=!1,this._generation={active:!0}};_resolveMutation=(t,i,n,o)=>{if(void 0!==o.failedMutationField)throw new e(`Not run: the earlier field "${o.failedMutationField}" of this operation failed, so "${i}" was skipped and no change of the operation takes effect. Fix the failing field and send the operation again.`);try{return this._runMutation(t,n,o)}catch(e){throw o.failedMutationField=i,e}};_runMutation=(t,i,n)=>{let o=v(t,n.manifest);if(!o)throw new e(`The schema declares the mutation "${t}", but the configurator has no implementation for it. This is a fault in the configurator, not in your request. Tell the user this is not available.`);let r=n.state,s=o.implementation(i,r,{manifest:n.manifest,action:this._context.domainContextSelectors.getActionSystem().createContext(r),resolveLocalizable:this._context.domainServicesSelectors.getResolveLocalizable()});if(s.updates.length>0){let i=this._context.domainContextSelectors.getStoreSystem().prepareStateEmission(s.updates,r,"committed"),{validity:o}=i;if("uncaught"===o.severity)throw new e(`The changes of "${t}" were not applied, because the resulting configuration is invalid: validating it threw: ${O(L(o.error))} Change the request so the configuration stays valid.`,{originalError:o.error});if(!o.valid)throw new E(`The changes of "${t}" were not applied, because the resulting configuration has ${o.severity} violations.`,$(o,this._context.domainServicesSelectors.getResolveLocalizable()));n.emissions.push(i),n.validities.set(i.state,o),n.state=i.state}return s.readResult({previousState:r,state:n.state})};_takeScreenshot=({entity:t,state:i},n,o)=>{let r=o.manifest.screenshots?.[t.type]?.find(e=>e.view===n);if(!r)return Promise.reject(new e(`The schema declares the screenshot view "${n}" on ${t.type}, but the configurator has no view of that name. This is a fault in the configurator, not in your request. Tell the user this is not available.`));let s=o.lastScreenshot.then(async()=>{if(!o.generation.active)throw I(N);let e=await this._renderScreenshot(t.id,r.instanceName,i).catch(e=>{throw I(e instanceof y?"User made concurrent actions that prevented the screenshot from being taken, try again":e instanceof M?`The screenshot of ${t.id} from "${n}" cannot be taken: ${e.message} Tell the user the screenshot is not available.`:`The screenshot of ${t.id} from "${n}" could not be taken: ${O(L(e))} Try again; if it fails again, tell the user the screenshot is not available.`,e instanceof Error?e:void 0)});if(!o.generation.active)throw I(N);if(null===e)return null;let{imageId:s}=await this._context.uploadScreenshot(e).catch(e=>{throw I(`The screenshot of ${t.id} from "${n}" was taken but could not be stored: ${O(L(e))} Try again; if it fails again, tell the user the screenshot is not available.`,e instanceof Error?e:void 0)}),a=`${t.id}/${n}`,l=[...o.screenshots.values()].filter(e=>e.entityId===t.id&&e.view===n).length,c=0===l?a:`${a}#${l+1}`;return o.screenshots.set(c,{entityId:t.id,view:n,imageId:s}),{image:c}});return o.lastScreenshot=s.catch(()=>void 0),s};_setup=()=>{let{manifest:t,error:i}=this._context.getAssistantSetup();if(i)return{ready:!1,result:{errors:[new e(i.message,{originalError:i})]}};if(!t)return{ready:!1,result:b};let n=this._selectSchema(t.sdl);return n instanceof e?{ready:!1,result:{errors:[n]}}:{ready:!0,assistant:t,schema:n,lenses:t.lenses?.definitions?this._selectLenses(t.lenses.definitions):void 0,fieldResolver:this._selectFieldResolver(t.fields)}};_run=async(t,i,o,s)=>{var l;let c;try{c=r(t)}catch(t){return{errors:[t instanceof e?t:new e(L(t))]}}let h=a(o.schema,c,k);return h.length>0?{errors:h}:(l=await n({schema:o.schema,document:c,rootValue:this._rootValue,contextValue:s,variableValues:i.variables,operationName:i.operationName,fieldResolver:o.fieldResolver,typeResolver:this._resolveType}),l.errors?.some(e=>e.originalError instanceof E)?{...l,errors:l.errors.flatMap(t=>t.originalError instanceof E?t.originalError.entries.map(({type:i,entityId:n,message:o})=>new e(o??i,{nodes:t.nodes,source:t.source,positions:t.positions,path:t.path,extensions:{code:"VIOLATION",type:i,entityId:n}})):[t])}:l)};prepare=async(t,i,n=this._generation)=>{let o,r=this._setup();if(!r.ready)return i.map(()=>({result:r.result,emissions:[],screenshots:new Map}));let s={manifest:r.assistant,state:t,emissions:[],failedMutationField:void 0,screenshots:new Map,lastScreenshot:Promise.resolve(),generation:n,validities:new WeakMap},a=[];for(let[t,n]of i.entries())if(void 0===o){let i=s.emissions.length,l=s.screenshots.size;s.failedMutationField=void 0;let c=S(n.document),h=r.lenses?w(c,r.lenses):c,d=h instanceof e?{errors:[h]}:await this._run(h,n,r,s);await s.lastScreenshot,a.push({result:d,emissions:s.emissions.slice(i),screenshots:new Map([...s.screenshots].slice(l))}),V(d)&&(o=t)}else a.push({result:P(o),emissions:[],screenshots:new Map});return a};readSideEffects=e=>{let t=this._context.domainServicesSelectors.getResolveLocalizable();return e.flatMap(({emissions:e})=>e.flatMap(e=>x(e.updates,t)))};readScreenshots=e=>new Map(e.flatMap(({screenshots:e})=>[...e]));readWarnings=(e,t)=>{let i=t.flatMap(({emissions:e})=>e).at(-1);return void 0===i||t.some(({result:e})=>V(e))?[]:T(i.validity,this._validateState(e),this._context.domainServicesSelectors.getResolveLocalizable())};_prepareAndCommit=async(e,t)=>{let i,n,o,r=this._context.domainContextSelectors.getStoreSystem(),s=r.stateSlices.committed.value.state,a=await this.prepare(s,e,t),l=a.map(({result:e})=>e),h=this.readSideEffects(a),d=this.readScreenshots(a),u=a.flatMap(e=>e.emissions);if(!t.active)return{results:l,sideEffects:h,screenshots:d,warnings:[],outcome:"conflict"};if(l.some(V)||0===u.length)return{results:l,sideEffects:h,screenshots:d,warnings:[],outcome:"none"};let m=(i=c(u[0]),n=c(u[u.length-1]),o=u.some(e=>void 0!==e.transformationLog),{kind:"committed",previousState:i.previousState,state:n.state,updates:u.flatMap(e=>e.updates),validity:n.validity,transformationLog:o?u.flatMap(e=>e.transformationLog??[]):void 0});return{results:l,sideEffects:h,screenshots:d,warnings:this.readWarnings(s,a),outcome:r.commitPrepared(m),preparedState:m.state}};execute=async e=>{let t=this._generation;if(!this._context.domainContextSelectors.getStoreSystem().isInitialized)return{results:e.map(()=>C),committed:!1,sideEffects:[],warnings:[],screenshots:new Map};let i=await this._prepareAndCommit(e,t),{results:n,sideEffects:o,warnings:r,screenshots:s,outcome:a,preparedState:l}="conflict"===i.outcome&&t.active?await this._prepareAndCommit(e,t):i;return"committed"===a?{results:n,committed:!0,sideEffects:o,warnings:r,screenshots:s,preparedState:l}:"held"===a?{results:n,committed:!1,message:"The changes wait for the user's approval and are not applied yet. Do not send them again; the next `[changes]` block lists them once approved.",sideEffects:o,warnings:r,screenshots:s,preparedState:l}:"conflict"===a?{results:n,committed:!1,message:"The changes were not committed, because the configuration changed while they were being applied. The results describe a state that was discarded. Query the current configuration and send the operations again if they still make sense.",sideEffects:o,warnings:r,screenshots:s}:{results:n,committed:!1,sideEffects:o,warnings:r,screenshots:s}}}
@@ -6,7 +6,7 @@ export { createCameraControls } from './camera-control-system/create-camera-cont
6
6
  export { type AnyCanvasSystem, CanvasSystem, type EntityObjectFilter, type FlushToken } from './canvas-system.js';
7
7
  export { type AnyDragAndDropSystem, DragAndDropSystem, type DragAndDropSystemContext, type DraggableState, type DraggingState, type RotationDraggingState, } from './drag-and-drop-system/drag-and-drop-system.js';
8
8
  export { type AnyExportSystem, ExportSystem, type ExportSystemContext } from './export-system/export-system.js';
9
- export { type GraphQLExecution, type GraphQLScreenshot, type GraphQLOperation, GraphQLSystem, type GraphQLSystemContext, type PreparedOperation, } from './graphql-system/graphql-system.js';
9
+ export { type GraphQLExecution, type GraphQLScreenshot, type GraphQLOperation, GraphQLSystem, type GraphQLSystemContext, type PreparedOperation, SCREENSHOT_NOT_TAKEN, } from './graphql-system/graphql-system.js';
10
10
  export type * from './image-rendering-system/image-renderer.js';
11
11
  export { type AnyImageRenderingSystem, ImageRenderingSystem, type ImageRenderingSystemContext, } from './image-rendering-system/image-rendering-system.js';
12
12
  export { type AnyLayoutSystem, LayoutSystem, type LayoutSystemContext } from './layout-system/layout-system.js';
@@ -1 +1 @@
1
- export{AnimationSystem}from"./animation-system.js";export{AssistantSystem}from"./assistant-system/assistant-system.js";export{CameraControlSystem,CameraControlType}from"./camera-control-system/camera-control-system.js";export{CameraSystem}from"./camera-control-system/camera-system.js";export{createCameraControls}from"./camera-control-system/create-camera-controls.js";export{CanvasSystem}from"./canvas-system.js";export{DragAndDropSystem}from"./drag-and-drop-system/drag-and-drop-system.js";export{ExportSystem}from"./export-system/export-system.js";export{GraphQLSystem}from"./graphql-system/graphql-system.js";export{ImageRenderingSystem}from"./image-rendering-system/image-rendering-system.js";export{LayoutSystem}from"./layout-system/layout-system.js";export{toolbarHelpElementName}from"./layout-system/toolbar-help-element.js";export{SketchingSystem}from"./sketching-system/sketching-system.js";export{LineEndPointUpdateTag,LineLengthUpdateTag,LineLineConnectionUpdateTag,LineRectangleBottomLeftConnectionUpdateTag,LineRectangleBottomRightConnectionUpdateTag,LineRectangleTopLeftConnectionUpdateTag,LineRectangleTopRightConnectionUpdateTag,LineSketchingPointUpdateTag,LineStartPointUpdateTag,RectangleBottomLeftCornerUpdateTag,RectangleBottomRightCornerUpdateTag,RectangleDepthUpdateTag,RectangleSketchingPointUpdateTag,RectangleTopLeftCornerUpdateTag,RectangleTopRightCornerUpdateTag,RectangleWidthUpdateTag,SetInitialSketchingPointPositionTag,SketchingFixTransformationTag,isAnySketchingPointUpdate,isLineEndPointUpdate,isLineLengthUpdate,isLineLineConnectionUpdate,isLineRectangleBottomLeftConnectionUpdate,isLineRectangleBottomRightConnectionUpdate,isLineRectangleTopLeftConnectionUpdate,isLineRectangleTopRightConnectionUpdate,isLineSketchingPointUpdate,isLineStartPointUpdate,isRectangleBottomLeftCornerUpdate,isRectangleBottomRightCornerUpdate,isRectangleDepthUpdate,isRectangleSketchingPointUpdate,isRectangleTopLeftCornerUpdate,isRectangleTopRightCornerUpdate,isRectangleWidthUpdate,isSetInitialLinePositionUpdate,isSetInitialRectanglePositionUpdate,isSketchingFixTransformationUpdate}from"./sketching-system/sketching-updates.js";
1
+ export{AnimationSystem}from"./animation-system.js";export{AssistantSystem}from"./assistant-system/assistant-system.js";export{CameraControlSystem,CameraControlType}from"./camera-control-system/camera-control-system.js";export{CameraSystem}from"./camera-control-system/camera-system.js";export{createCameraControls}from"./camera-control-system/create-camera-controls.js";export{CanvasSystem}from"./canvas-system.js";export{DragAndDropSystem}from"./drag-and-drop-system/drag-and-drop-system.js";export{ExportSystem}from"./export-system/export-system.js";export{GraphQLSystem,SCREENSHOT_NOT_TAKEN}from"./graphql-system/graphql-system.js";export{ImageRenderingSystem}from"./image-rendering-system/image-rendering-system.js";export{LayoutSystem}from"./layout-system/layout-system.js";export{toolbarHelpElementName}from"./layout-system/toolbar-help-element.js";export{SketchingSystem}from"./sketching-system/sketching-system.js";export{LineEndPointUpdateTag,LineLengthUpdateTag,LineLineConnectionUpdateTag,LineRectangleBottomLeftConnectionUpdateTag,LineRectangleBottomRightConnectionUpdateTag,LineRectangleTopLeftConnectionUpdateTag,LineRectangleTopRightConnectionUpdateTag,LineSketchingPointUpdateTag,LineStartPointUpdateTag,RectangleBottomLeftCornerUpdateTag,RectangleBottomRightCornerUpdateTag,RectangleDepthUpdateTag,RectangleSketchingPointUpdateTag,RectangleTopLeftCornerUpdateTag,RectangleTopRightCornerUpdateTag,RectangleWidthUpdateTag,SetInitialSketchingPointPositionTag,SketchingFixTransformationTag,isAnySketchingPointUpdate,isLineEndPointUpdate,isLineLengthUpdate,isLineLineConnectionUpdate,isLineRectangleBottomLeftConnectionUpdate,isLineRectangleBottomRightConnectionUpdate,isLineRectangleTopLeftConnectionUpdate,isLineRectangleTopRightConnectionUpdate,isLineSketchingPointUpdate,isLineStartPointUpdate,isRectangleBottomLeftCornerUpdate,isRectangleBottomRightCornerUpdate,isRectangleDepthUpdate,isRectangleSketchingPointUpdate,isRectangleTopLeftCornerUpdate,isRectangleTopRightCornerUpdate,isRectangleWidthUpdate,isSetInitialLinePositionUpdate,isSetInitialRectanglePositionUpdate,isSketchingFixTransformationUpdate}from"./sketching-system/sketching-updates.js";
@@ -1,3 +1,4 @@
1
+ import { type ReactNode } from 'react';
1
2
  import type { AssistantToolItem } from './thread-items.js';
2
3
  export interface AssistantToolChipsProps {
3
4
  readonly tools: readonly AssistantToolItem[];
@@ -16,3 +17,12 @@ export interface AssistantToolChipsProps {
16
17
  * back, up to a change the user made in between.
17
18
  */
18
19
  export declare const AssistantToolChips: import("react").MemoExoticComponent<({ tools, isActive, canUndo, onUndo }: AssistantToolChipsProps) => import("react/jsx-runtime").JSX.Element>;
20
+ export interface AssistantActivityRowProps {
21
+ /** What the assistant is doing, said beside the turning icon. */
22
+ readonly label: ReactNode;
23
+ }
24
+ /**
25
+ * The assistant at work before it has a row of chips to show, such as while it thinks: the row's
26
+ * turning icon, in the place the icon of the first row of chips takes over.
27
+ */
28
+ export declare const AssistantActivityRow: ({ label }: AssistantActivityRowProps) => import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- import{jsx as e,jsxs as t,Fragment as n}from"react/jsx-runtime";import{ButtonBase as i,ClickAwayListener as o,Tooltip as s,styled as a}from"@mui/material";import{memo as r,useCallback as l,useMemo as d,useRef as c,useState as m}from"react";import{match as p}from"ts-pattern";import{useLocalizable as h}from"#package/react-sdk";import{PhxIcon as u}from"#package/ui-sdk";import{assistantReferenceStyles as f}from"./reference-link/index.js";import{ScreenshotThumbnails as g,readToolScreenshots as k}from"./screenshots/index.js";import{AssistantPanelName as x}from"./theme.js";let y={id:"sdk.assistant.tool.updateDesign.label",message:"Update design"},b={id:"sdk.assistant.tool.readDesign.label",message:"Read design"},w={id:"sdk.assistant.tool.mistake.hint",message:"The assistant made a mistake."},v={id:"sdk.assistant.tool.cancelled.hint",message:"Stopped before it finished."},C={id:"sdk.assistant.tool.noResult.hint",message:"The result of this step was lost. It may or may not have been done."},I={id:"sdk.assistant.tool.toolBudget.hint",message:"Not done: the assistant reached its limit of steps for one message."},S={id:"sdk.assistant.tool.undo.label",message:"Undo"},D={id:"sdk.assistant.tool.screenshots.label",message:"{count, plural, one {# screenshot} other {# screenshots}}"},j=a("div",{name:x,slot:"chips"})(({theme:{palette:e,spacing:t,typography:n}})=>({...n.caption,alignItems:"start",color:e.text.secondary,display:"grid",gap:t(.75),gridTemplateColumns:"min-content minmax(0, 1fr)"})),z=a("span",{name:x,slot:"activity"})(({theme:{typography:e}})=>({blockSize:`calc(${e.caption.lineHeight} * 1em)`,display:"grid",placeItems:"center"})),A=a(u,{name:x,slot:"activityIcon"})({fontSize:14,'[data-chips="active"] &':{animation:"phx-assistant-turn 2.4s linear infinite","@media (prefers-reduced-motion: reduce)":{animation:"none"}},"@keyframes phx-assistant-turn":{to:{rotate:"360deg"}}}),T=a("span",{name:x,slot:"chip"})(({theme:{palette:e,spacing:t}})=>({cursor:"default",display:"inline-flex",maxInlineSize:"100%",verticalAlign:"top",whiteSpace:"nowrap","&:not(:last-of-type)::after":{color:e.text.secondary,content:'"\xb7"',flexShrink:0,marginInline:t(.75)}})),E=a("span",{name:x,slot:"screenshotsLink"})(f),L=a(i,{name:x,slot:"undoButton"})(({theme:{palette:e,shape:t,spacing:n}})=>({alignItems:"center",animation:"phx-assistant-undo-in 150ms ease-out",borderRadius:t.borderRadius,color:e.primary.main,display:"inline-flex",font:"inherit",gap:n(.5),marginInlineStart:n(1),verticalAlign:"top","&:hover":{textDecoration:"underline"},"@media (prefers-reduced-motion: reduce)":{animation:"none"},"@keyframes phx-assistant-undo-in":{from:{opacity:0}}})),R=a("span",{name:x,slot:"chipLabel"})(({theme:{palette:e}})=>({minInlineSize:0,overflow:"hidden",textOverflow:"ellipsis",'[data-chip="failed"] > &':{textDecoration:"line-through",textDecorationColor:e.error.main}})),P=a("span",{name:x,slot:"violation"})({display:"block"}),B=a("span",{name:x,slot:"fullLabel"})({display:"block"}),O=r(({tool:i})=>{let{chip:o,input:a,result:r}=i,d=h(y),u=h(b),f=h(w),g=h(v),k=h(C),x=h(I),S=c(null),[D,j]=m(!1),z=p(o.label).with({kind:"text"},({text:e})=>e).with({kind:"updateDesign"},()=>d).with({kind:"readDesign"},()=>u).exhaustive(),A=l(()=>{console.info(`Assistant tool call "${z}"`,{input:a,result:r})},[a,z,r]),E=l(()=>{let e=S.current;j(null!=e&&e.scrollWidth>e.clientWidth)},[]),L=p(o).with({errorCode:"cancelled"},()=>g).with({errorCode:"no_result"},()=>k).with({errorCode:"tool_budget"},()=>x).when(({violations:e})=>e.length>0,({violations:t})=>t.map((t,n)=>e(P,{children:t},n))).with({state:"failed"},()=>f).otherwise(()=>""),O=D?t(n,{children:[e(B,{children:z}),L]}):L;return e(s,{title:O,placement:"top-start",children:e(T,{onClick:A,onPointerEnter:E,"data-chip":o.state,children:e(R,{ref:S,children:z})})})}),U=r(({screenshots:t})=>{let n=h({...D,values:{count:t.length}}),[i,a]=m(!1),r=l(()=>a(!0),[]),d=l(()=>a(!1),[]),p=c(null),u=l(e=>{p.current=e},[]),f=l(()=>{p.current?.update()},[]),k=l(e=>{("Enter"===e.key||" "===e.key)&&(e.preventDefault(),a(!0))},[]);return e(T,{"data-chip":"screenshots",children:e(o,{onClickAway:d,mouseEvent:!!i&&"onClick",touchEvent:!!i&&"onTouchEnd",children:e(s,{open:i,onOpen:r,onClose:d,title:e(g,{screenshots:t,onImageLoad:f}),placement:"top-start",describeChild:!0,disableTouchListener:!0,PopperProps:{popperRef:u},slotProps:{tooltip:{sx:{background:"none",maxInlineSize:"none",padding:0}}},children:e(E,{role:"button",tabIndex:0,"aria-expanded":i,onClick:r,onKeyDown:k,children:n})})})})}),W=({tool:i})=>{let o=d(()=>k(i.result),[i.result]);return t(n,{children:[e(O,{tool:i}),o.length>0&&e(U,{screenshots:o})]})};export const AssistantToolChips=r(({tools:n,isActive:i,canUndo:o,onUndo:s})=>{let a=h(S),r=l(()=>{s(new Set(n.map(({id:e})=>e)))},[s,n]);return t(j,{"data-chips":i?"active":"done","aria-busy":i,children:[e(z,{children:e(A,{name:"Gear"})}),t("div",{children:[n.map(t=>e(W,{tool:t},t.id)),o&&t(L,{onClick:r,children:[e(u,{name:"ArrowCounterClockwise",fontSize:"inherit"}),a]})]})]})});
1
+ import{jsx as e,jsxs as t,Fragment as i}from"react/jsx-runtime";import{ButtonBase as n,Tooltip as s,styled as a}from"@mui/material";import{memo as o,useCallback as r,useMemo as l,useRef as d,useState as c}from"react";import{match as m}from"ts-pattern";import{useLocalizable as h}from"#package/react-sdk";import{PhxIcon as p,hoverStyles as u}from"#package/ui-sdk";import{AssistantPopover as f}from"./popover/index.js";import{assistantReferenceStyles as g}from"./reference-link/index.js";import{ScreenshotThumbnails as k,readToolScreenshots as x}from"./screenshots/index.js";import{AssistantPanelName as y}from"./theme.js";let v={id:"sdk.assistant.tool.updateDesign.label",message:"Update design"},w={id:"sdk.assistant.tool.readDesign.label",message:"Read design"},b={id:"sdk.assistant.tool.mistake.hint",message:"The assistant made a mistake."},C={id:"sdk.assistant.tool.cancelled.hint",message:"Stopped before it finished."},I={id:"sdk.assistant.tool.noResult.hint",message:"The result of this step was lost. It may or may not have been done."},S={id:"sdk.assistant.tool.toolBudget.hint",message:"Not done: the assistant reached its limit of steps for one message."},A={id:"sdk.assistant.tool.undo.label",message:"Undo"},D={id:"sdk.assistant.tool.screenshots.label",message:"{count, plural, one {# screenshot} other {# screenshots}}"},j=a("div",{name:y,slot:"chips"})(({theme:{palette:e,spacing:t,typography:i}})=>({...i.caption,alignItems:"start",color:e.text.secondary,display:"grid",gap:t(.75),gridTemplateColumns:"min-content minmax(0, 1fr)"})),z=a("span",{name:y,slot:"activity"})(({theme:{typography:e}})=>({blockSize:`calc(${e.caption.lineHeight} * 1em)`,display:"grid",placeItems:"center"})),R=a(p,{name:y,slot:"activityIcon"})({fontSize:14,'[data-chips="active"] &':{animation:"phx-assistant-turn 2400ms linear infinite","@media (prefers-reduced-motion: reduce)":{animation:"none"}},"@keyframes phx-assistant-turn":{to:{rotate:"360deg"}}}),L=({isActive:t})=>{let i=l(()=>t?-(performance.now()%2400):0,[t]);return e(R,{name:"Gear",style:{animationDelay:`${i}ms`}})},T=a("span",{name:y,slot:"chip"})(({theme:{palette:e,spacing:t}})=>({cursor:"default",display:"inline-flex",maxInlineSize:"100%",verticalAlign:"top",whiteSpace:"nowrap","&:not(:last-of-type)::after":{color:e.text.secondary,content:'"\xb7"',flexShrink:0,marginInline:t(.75)}})),$=a("span",{name:y,slot:"screenshotsLink"})(g),B=a(n,{name:y,slot:"undoButton"})(({theme:{palette:e,shape:t,spacing:i}})=>({alignItems:"center",animation:"phx-assistant-undo-in 150ms ease-out",borderRadius:t.borderRadius,color:e.primary.main,display:"inline-flex",font:"inherit",gap:i(.5),marginInlineStart:i(1),verticalAlign:"top",...u({"&:hover":{textDecoration:"underline"}}),"@media (prefers-reduced-motion: reduce)":{animation:"none"},"@keyframes phx-assistant-undo-in":{from:{opacity:0}}})),U=a("span",{name:y,slot:"chipLabel"})(({theme:{palette:e}})=>({minInlineSize:0,overflow:"hidden",textOverflow:"ellipsis",'[data-chip="failed"] > &':{textDecoration:"line-through",textDecorationColor:e.error.main}})),W=a("span",{name:y,slot:"violation"})({display:"block"}),_=a("span",{name:y,slot:"fullLabel"})({display:"block"}),E=o(({tool:n})=>{let{chip:a,input:o,result:l}=n,p=h(v),u=h(w),f=h(b),g=h(C),k=h(I),x=h(S),y=d(null),[A,D]=c(!1),j=m(a.label).with({kind:"text"},({text:e})=>e).with({kind:"updateDesign"},()=>p).with({kind:"readDesign"},()=>u).exhaustive(),z=r(()=>{console.info(`Assistant tool call "${j}"`,{input:o,result:l})},[o,j,l]),R=r(()=>{let e=y.current;D(null!=e&&e.scrollWidth>e.clientWidth)},[]),L=m(a).with({errorCode:"cancelled"},()=>g).with({errorCode:"no_result"},()=>k).with({errorCode:"tool_budget"},()=>x).when(({violations:e})=>e.length>0,({violations:t})=>t.map((t,i)=>e(W,{children:t},i))).with({state:"failed"},()=>f).otherwise(()=>""),$=A?t(i,{children:[e(_,{children:j}),L]}):L;return e(s,{title:$,placement:"top-start",children:e(T,{onClick:z,onPointerEnter:R,"data-chip":a.state,children:e(U,{ref:y,children:j})})})}),F=o(({screenshots:t})=>{let i=h({...D,values:{count:t.length}});return e(T,{"data-chip":"screenshots",children:e(f,{title:i=>e(k,{screenshots:t,onImageLoad:i}),children:t=>e($,{...t,children:i})})})}),G=({tool:n})=>{let s=l(()=>x(n.result),[n.result]);return t(i,{children:[e(E,{tool:n}),s.length>0&&e(F,{screenshots:s})]})};export const AssistantToolChips=o(({tools:i,isActive:n,canUndo:s,onUndo:a})=>{let o=h(A),l=r(()=>{a(new Set(i.map(({id:e})=>e)))},[a,i]);return t(j,{"data-chips":n?"active":"done","aria-busy":n,children:[e(z,{children:e(L,{isActive:n})}),t("div",{children:[i.map(t=>e(G,{tool:t},t.id)),s&&t(B,{onClick:l,children:[e(p,{name:"ArrowCounterClockwise",fontSize:"inherit"}),o]})]})]})});export const AssistantActivityRow=({label:i})=>t(j,{"data-chips":"active","aria-busy":!0,children:[e(z,{children:e(L,{isActive:!0})}),e("div",{children:i})]});
@@ -1,2 +1,2 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import{Trans as a}from"@lingui/react";import{IconButton as r,InputBase as i,Tooltip as n,styled as o}from"@mui/material";import{useCallback as l,useEffect as s,useRef as d,useState as c}from"react";import{useEagerObservableSelector as m,useLocalizable as p}from"#package/react-sdk";import{PhxIcon as u,useResponsive as g}from"#package/ui-sdk";import{useConfigurator as h}from"../../application-runtime/index.js";import{prepareImage as b}from"./attachments/index.js";import{AssistantPanelName as f}from"./theme.js";let k={id:"sdk.assistant.composer.placeholder",message:"Ask or tell me what to change…"},v={id:"sdk.assistant.composer.send.label",message:"Send"},y={id:"sdk.assistant.composer.stop.label",message:"Stop"},x={id:"sdk.assistant.composer.attach.label",message:"Attach images"},R={id:"sdk.assistant.composer.attachment.remove",message:"Remove image"},S={id:"sdk.assistant.composer.attachment.unreadable",message:"Unsupported image format."},w={id:"sdk.assistant.composer.attachment.limit",message:"You can attach up to {max} images."},z=o("form",{name:f,slot:"composer"})(({theme:{palette:e,spacing:t}})=>({borderBlockStart:`1px solid ${e.divider}`,display:"grid",gap:t(.75),paddingBlock:t(1.25),paddingInline:`var(--phx-sidebar-padding, ${t(2)})`})),U=o("div",{name:f,slot:"inputFrame"})(({theme:{palette:e,spacing:t}})=>({alignItems:"end",border:`1px solid ${e.divider}`,borderRadius:12,columnGap:t(1),display:"grid",gridTemplateColumns:"auto minmax(0, 1fr) auto",padding:t(.5),'&:focus-within, &[data-dragging="true"]':{borderColor:e.primary.main}})),C=o("div",{name:f,slot:"attachments"})(({theme:{spacing:e}})=>({display:"flex",flexWrap:"wrap",gap:e(1),gridColumn:"1 / -1",paddingBlockStart:e(.75)})),j=o(r,{name:f,slot:"attachButton"})(({theme:{palette:e}})=>({background:"transparent",border:"none",borderRadius:8,boxShadow:"none",color:e.text.secondary,"&:hover":{background:e.action.hover,color:e.text.primary},"&.Mui-disabled":{background:"transparent",color:e.action.disabled}})),B=o("div",{name:f,slot:"attachment"})(({theme:{palette:e,shape:t}})=>({blockSize:56,border:`1px solid ${e.divider}`,borderRadius:t.borderRadius,inlineSize:56,overflow:"hidden",position:"relative"})),D=o("img")({blockSize:"100%",display:"block",inlineSize:"100%",objectFit:"cover"}),L=o(r,{name:f,slot:"removeAttachment"})(({theme:{palette:e}})=>({background:e.background.paper,insetBlockStart:2,insetInlineEnd:2,padding:2,position:"absolute","&:hover":{background:e.background.paper}})),T=o("div")({alignSelf:"stretch",display:"grid",minInlineSize:0}),$=o(i,{name:f,slot:"input"})(({theme:{spacing:e,typography:t}})=>({...t.body2,flex:1,paddingBlock:e(.75)})),I=o(r,{name:f,slot:"sendButton"})(({theme:{palette:e}})=>({background:e.primary.main,borderRadius:8,color:e.primary.contrastText,"&:hover":{background:e.primary.dark},"&.Mui-disabled":{background:e.action.disabledBackground,color:e.action.disabled}})),F=o(r,{name:f,slot:"stopButton"})(({theme:{palette:e}})=>({background:e.text.primary,borderRadius:8,color:e.background.paper,"&:hover":{background:e.text.secondary}})),O=o("span")({background:"currentColor",blockSize:10,borderRadius:2,inlineSize:10,margin:5}),P=o("div",{name:f,slot:"hint"})(({theme:{palette:e,typography:t}})=>({...t.caption,color:e.text.secondary})),A=o("div",{name:f,slot:"attachmentNotice"})(({theme:{palette:e,typography:t}})=>({...t.caption,color:e.error.main})),E=o("input")({display:"none"}),M=0,K=e=>{for(let{previewUrl:t}of e)URL.revokeObjectURL(t)};export const AssistantComposer=()=>{let{assistantSystem:r}=h(),[i,o]=c(""),[f,N]=c([]),[W,G]=c(0),[X,Y]=c(),[q,H]=c(!1),[J,Q]=c(!1),V=d(null),Z=d(null),_=d(0),ee=d(f),{isDesktop:et}=g();ee.current=f;let ea=p(k),er=p(v),ei=p(y),en=p(x),eo=p(R),el=p(S),es=p({...w,values:{max:4}}),ed=d(!0);s(()=>(ed.current=!0,()=>{ed.current=!1,K(ee.current)}),[]);let{isReplying:ec,isResuming:em}=m(r.chat$,e=>({isReplying:e.isLoading,isResuming:e.isResuming}),[]),ep=i.trim(),eu=em||q,eg=!ec&&!eu&&0===W&&(ep.length>0||f.length>0),eh=l(async e=>{if(0===e.length)return;let t=e.slice(0,Math.max(0,4-_.current));Y(t.length<e.length?"limit":void 0),0!==t.length&&(_.current+=t.length,G(e=>e+t.length),await Promise.all(t.map(async e=>{try{let t=await b(e);if(!ed.current)return;let a={id:`attachment-${++M}`,blob:t,previewUrl:URL.createObjectURL(t)};N(e=>[...e,a])}catch{_.current-=1,Y("unreadable")}finally{G(e=>e-1)}})))},[]),eb=l(e=>{URL.revokeObjectURL(e.previewUrl),_.current-=1,N(t=>t.filter(({id:t})=>t!==e.id)),Y(void 0)},[]),ef=l(async()=>{if(eg){et||V.current?.blur(),H(!0);try{await r.send(ep,f.map(({blob:e})=>e),{onSent:()=>{o(""),N(e=>e.filter(e=>!f.includes(e))),K(f),_.current-=f.length,Y(void 0),H(!1)},onUnsent:()=>{if(!ed.current)return;let e=f.slice(0,Math.max(0,4-_.current)),t=e.map(e=>({...e,previewUrl:URL.createObjectURL(e.blob)}));o(e=>e.trim()?`${e}
2
- ${i}`:i),N(e=>[...t,...e]),_.current+=t.length,Y(e.length<f.length?"limit":void 0)}})}finally{H(!1)}}},[r,f,eg,ep,i,et]),ek=l(e=>{e.preventDefault(),ef()},[ef]),ev=l(e=>{"Enter"!==e.key||e.shiftKey||e.nativeEvent.isComposing||(e.preventDefault(),ef())},[ef]),ey=l(()=>{r.stop()},[r]),ex=l(e=>{let t=[...e.target.files??[]];e.target.value="",eh(t)},[eh]),eR=l(e=>{let t=[...e.clipboardData.files].filter(e=>e.type.startsWith("image/"));0!==t.length&&(e.preventDefault(),eh(t))},[eh]);return t(z,{onSubmit:ek,onDragOver:l(e=>{e.dataTransfer.types.includes("Files")&&(e.preventDefault(),e.dataTransfer.dropEffect="copy",Q(!0))},[]),onDragLeave:l(e=>{e.relatedTarget instanceof Node&&e.currentTarget.contains(e.relatedTarget)||Q(!1)},[]),onDrop:l(e=>{0!==e.dataTransfer.files.length&&(e.preventDefault(),Q(!1),eh([...e.dataTransfer.files]))},[eh]),children:[t(U,{"data-dragging":J,children:[f.length>0&&e(C,{children:f.map(a=>t(B,{children:[e(D,{src:a.previewUrl,alt:""}),e(L,{size:"small","aria-label":eo,disabled:eu,onClick:()=>eb(a),children:e(u,{name:"X",sx:{fontSize:12}})})]},a.id))}),e(n,{title:en,placement:"top",children:e("span",{children:e(j,{size:"small","aria-label":en,disabled:eu,onClick:()=>Z.current?.click(),children:e(u,{name:"Paperclip",fontSize:"small"})})})}),e(E,{ref:Z,type:"file",accept:"image/*",multiple:!0,onChange:ex}),e(T,{children:e($,{multiline:!0,maxRows:6,placeholder:ea,value:i,readOnly:eu,inputRef:V,onChange:e=>o(e.target.value),onKeyDown:ev,onPaste:eR,onFocus:()=>r.setInputFocused(!0),onBlur:()=>r.setInputFocused(!1),inputProps:{"aria-label":ea}})}),ec?e(n,{title:ei,placement:"top",children:e(F,{size:"small","aria-label":ei,onClick:ey,children:e(O,{})})}):e(n,{title:er,placement:"top",children:e("span",{children:e(I,{type:"submit",size:"small","aria-label":er,disabled:!eg,children:e(u,{name:"PaperPlaneRightBold",fontSize:"small"})})})})]}),X?e(A,{role:"status",children:"limit"===X?es:el}):e(P,{children:e(a,{id:"sdk.assistant.composer.disclaimer",message:"AI can be wrong. Check the result."})})]})};
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import{Trans as a}from"@lingui/react";import{IconButton as r,InputBase as i,Tooltip as n,styled as o}from"@mui/material";import{useCallback as l,useEffect as s,useRef as d,useState as c}from"react";import{useEagerObservableSelector as m,useLocalizable as p}from"#package/react-sdk";import{PhxIcon as u,hoverStyles as g,useResponsive as h}from"#package/ui-sdk";import{useConfigurator as b}from"../../application-runtime/index.js";import{prepareImage as f}from"./attachments/index.js";import{AssistantPanelName as k}from"./theme.js";let v={id:"sdk.assistant.composer.placeholder",message:"Ask or tell me what to change…"},y={id:"sdk.assistant.composer.send.label",message:"Send"},x={id:"sdk.assistant.composer.stop.label",message:"Stop"},R={id:"sdk.assistant.composer.attach.label",message:"Attach images"},S={id:"sdk.assistant.composer.attachment.remove",message:"Remove image"},w={id:"sdk.assistant.composer.attachment.unreadable",message:"Unsupported image format."},z={id:"sdk.assistant.composer.attachment.limit",message:"You can attach up to {max} images."},U=o("form",{name:k,slot:"composer"})(({theme:{palette:e,spacing:t}})=>({borderBlockStart:`1px solid ${e.divider}`,display:"grid",gap:t(.75),paddingBlock:t(1.25),paddingInline:`var(--phx-sidebar-padding, ${t(2)})`})),C=o("div",{name:k,slot:"inputFrame"})(({theme:{palette:e,spacing:t}})=>({alignItems:"end",border:`1px solid ${e.divider}`,borderRadius:12,columnGap:t(1),display:"grid",gridTemplateColumns:"auto minmax(0, 1fr) auto",padding:t(.5),'&:focus-within, &[data-dragging="true"]':{borderColor:e.primary.main}})),j=o("div",{name:k,slot:"attachments"})(({theme:{spacing:e}})=>({display:"flex",flexWrap:"wrap",gap:e(1),gridColumn:"1 / -1",paddingBlockStart:e(.75)})),B=o(r,{name:k,slot:"attachButton"})(({theme:{palette:e}})=>({background:"transparent",border:"none",borderRadius:8,boxShadow:"none",color:e.text.secondary,"&:hover":{background:"transparent"},...g({"&:hover":{background:e.action.hover,color:e.text.primary}}),"&.Mui-disabled":{background:"transparent",color:e.action.disabled}})),D=o("div",{name:k,slot:"attachment"})(({theme:{palette:e,shape:t}})=>({blockSize:56,border:`1px solid ${e.divider}`,borderRadius:t.borderRadius,inlineSize:56,overflow:"hidden",position:"relative"})),L=o("img")({blockSize:"100%",display:"block",inlineSize:"100%",objectFit:"cover"}),T=o(r,{name:k,slot:"removeAttachment"})(({theme:{palette:e}})=>({background:e.background.paper,insetBlockStart:2,insetInlineEnd:2,padding:2,position:"absolute","&:hover":{background:e.background.paper}})),$=o("div")({alignSelf:"stretch",display:"grid",minInlineSize:0}),I=o(i,{name:k,slot:"input"})(({theme:{spacing:e,typography:t}})=>({...t.body2,flex:1,paddingBlock:e(.75)})),F=o(r,{name:k,slot:"sendButton"})(({theme:{palette:e}})=>({background:e.primary.main,borderRadius:8,color:e.primary.contrastText,"&:hover":{background:e.primary.main},...g({"&:hover":{background:e.primary.dark}}),"&.Mui-disabled":{background:e.action.disabledBackground,color:e.action.disabled}})),O=o(r,{name:k,slot:"stopButton"})(({theme:{palette:e}})=>({background:e.text.primary,borderRadius:8,color:e.background.paper,"&:hover":{background:e.text.primary},...g({"&:hover":{background:e.text.secondary}})})),P=o("span")({background:"currentColor",blockSize:10,borderRadius:2,inlineSize:10,margin:5}),A=o("div",{name:k,slot:"hint"})(({theme:{palette:e,typography:t}})=>({...t.caption,color:e.text.secondary})),E=o("div",{name:k,slot:"attachmentNotice"})(({theme:{palette:e,typography:t}})=>({...t.caption,color:e.error.main})),M=o("input")({display:"none"}),K=0,N=e=>{for(let{previewUrl:t}of e)URL.revokeObjectURL(t)};export const AssistantComposer=()=>{let{assistantSystem:r}=b(),[i,o]=c(""),[g,k]=c([]),[W,G]=c(0),[X,Y]=c(),[q,H]=c(!1),[J,Q]=c(!1),V=d(null),Z=d(null),_=d(0),ee=d(g),{isDesktop:et}=h();ee.current=g;let ea=p(v),er=p(y),ei=p(x),en=p(R),eo=p(S),el=p(w),es=p({...z,values:{max:4}}),ed=d(!0);s(()=>(ed.current=!0,()=>{ed.current=!1,N(ee.current)}),[]);let{isReplying:ec,isResuming:em}=m(r.chat$,e=>({isReplying:e.isLoading,isResuming:e.isResuming}),[]),ep=i.trim(),eu=em||q,eg=!ec&&!eu&&0===W&&(ep.length>0||g.length>0),eh=l(async e=>{if(0===e.length)return;let t=e.slice(0,Math.max(0,4-_.current));Y(t.length<e.length?"limit":void 0),0!==t.length&&(_.current+=t.length,G(e=>e+t.length),await Promise.all(t.map(async e=>{try{let t=await f(e);if(!ed.current)return;let a={id:`attachment-${++K}`,blob:t,previewUrl:URL.createObjectURL(t)};k(e=>[...e,a])}catch{_.current-=1,Y("unreadable")}finally{G(e=>e-1)}})))},[]),eb=l(e=>{URL.revokeObjectURL(e.previewUrl),_.current-=1,k(t=>t.filter(({id:t})=>t!==e.id)),Y(void 0)},[]),ef=l(async()=>{if(eg){et||V.current?.blur(),H(!0);try{await r.send(ep,g.map(({blob:e})=>e),{onSent:()=>{o(""),k(e=>e.filter(e=>!g.includes(e))),N(g),_.current-=g.length,Y(void 0),H(!1)},onUnsent:()=>{if(!ed.current)return;let e=g.slice(0,Math.max(0,4-_.current)),t=e.map(e=>({...e,previewUrl:URL.createObjectURL(e.blob)}));o(e=>e.trim()?`${e}
2
+ ${i}`:i),k(e=>[...t,...e]),_.current+=t.length,Y(e.length<g.length?"limit":void 0)}})}finally{H(!1)}}},[r,g,eg,ep,i,et]),ek=l(e=>{e.preventDefault(),ef()},[ef]),ev=l(e=>{"Enter"!==e.key||e.shiftKey||e.nativeEvent.isComposing||(e.preventDefault(),ef())},[ef]),ey=l(()=>{r.stop()},[r]),ex=l(e=>{let t=[...e.target.files??[]];e.target.value="",eh(t)},[eh]),eR=l(e=>{let t=[...e.clipboardData.files].filter(e=>e.type.startsWith("image/"));0!==t.length&&(e.preventDefault(),eh(t))},[eh]);return t(U,{onSubmit:ek,onDragOver:l(e=>{e.dataTransfer.types.includes("Files")&&(e.preventDefault(),e.dataTransfer.dropEffect="copy",Q(!0))},[]),onDragLeave:l(e=>{e.relatedTarget instanceof Node&&e.currentTarget.contains(e.relatedTarget)||Q(!1)},[]),onDrop:l(e=>{0!==e.dataTransfer.files.length&&(e.preventDefault(),Q(!1),eh([...e.dataTransfer.files]))},[eh]),children:[t(C,{"data-dragging":J,children:[g.length>0&&e(j,{children:g.map(a=>t(D,{children:[e(L,{src:a.previewUrl,alt:""}),e(T,{size:"small","aria-label":eo,disabled:eu,onClick:()=>eb(a),children:e(u,{name:"X",sx:{fontSize:12}})})]},a.id))}),e(n,{title:en,placement:"top",children:e("span",{children:e(B,{size:"small","aria-label":en,disabled:eu,onClick:()=>Z.current?.click(),children:e(u,{name:"Paperclip",fontSize:"small"})})})}),e(M,{ref:Z,type:"file",accept:"image/*",multiple:!0,onChange:ex}),e($,{children:e(I,{multiline:!0,maxRows:6,placeholder:ea,value:i,readOnly:eu,inputRef:V,onChange:e=>o(e.target.value),onKeyDown:ev,onPaste:eR,onFocus:()=>r.setInputFocused(!0),onBlur:()=>r.setInputFocused(!1),inputProps:{"aria-label":ea}})}),ec?e(n,{title:ei,placement:"top",children:e(O,{size:"small","aria-label":ei,onClick:ey,children:e(P,{})})}):e(n,{title:er,placement:"top",children:e("span",{children:e(F,{type:"submit",size:"small","aria-label":er,disabled:!eg,children:e(u,{name:"PaperPlaneRightBold",fontSize:"small"})})})})]}),X?e(E,{role:"status",children:"limit"===X?es:el}):e(A,{children:e(a,{id:"sdk.assistant.composer.disclaimer",message:"AI can be wrong. Check the result."})})]})};
@@ -1 +1 @@
1
- import{jsx as e,Fragment as r}from"react/jsx-runtime";import{styled as n}from"@mui/material";import{createContext as i,memo as o,useContext as t,useMemo as l}from"react";import a,{defaultUrlTransform as d}from"react-markdown";import m from"remark-gfm";import{AssistantAlert as s,isAlertKind as c,remarkAlerts as u}from"./alert/index.js";import{AssistantEntityLink as p}from"./entity-link/index.js";import{AssistantForm as h}from"./form/index.js";import{AssistantReferenceLink as f,isAssistantLinkHref as g,parseAssistantLinkTarget as k}from"./reference-link/index.js";import{AssistantImage as b}from"./resource-image/index.js";import{completeStreamedMarkdown as v,hasOpenFence as x}from"./streamed-markdown.js";import{AssistantPanelName as y}from"./theme.js";let j=n("div",{name:y,slot:"assistantMessage"})(({theme:{palette:e,shape:r,spacing:n,typography:i}})=>({overflowWrap:"anywhere","& > :first-child":{marginBlockStart:0},"& > :last-child":{marginBlockEnd:0},"p, ul, ol, pre, blockquote":{marginBlock:n(1)},"h1, h2, h3, h4, h5, h6":{...i.subtitle2,marginBlock:n(1.5,.5)},"ul, ol":{paddingInlineStart:n(2.5)},a:{color:e.primary.main},code:{background:e.action.hover,borderRadius:r.borderRadius/2,fontFamily:"ui-monospace, Menlo, monospace",fontSize:"0.9em",paddingInline:n(.5)},pre:{background:e.action.hover,borderRadius:r.borderRadius,overflowX:"auto",padding:n(1),code:{background:"none",padding:0}},blockquote:{borderInlineStart:`2px solid ${e.divider}`,color:e.text.secondary,marginInline:0,paddingInlineStart:n(1.5)},"th, td":{borderBlockEnd:`1px solid ${e.divider}`,padding:n(.5,1),textAlign:"start",verticalAlign:"top"}})),w=n("div")({overflowX:"auto",table:{borderCollapse:"collapse",inlineSize:"100%"}}),S=i({forms:"hidden",openFenceEnd:void 0,isStreaming:!1}),A=({source:r,end:n})=>{let{forms:i,openFenceEnd:o,isStreaming:l}=t(S);return"hidden"===i?null:null!=n&&n===o?l?e(h,{source:r,status:"writing"}):null:e(h,{source:r,status:"disabled"===i?"waiting":"ready"})},B={a:({node:n,children:i,href:o,...t})=>{if(null==o||!g(o))return e("a",{...t,href:o,target:"_blank",rel:"noopener noreferrer",children:i});let l=k(o);return null==l?e(r,{children:i}):"entity"===l.kind?e(p,{id:l.id,children:i}):e(f,{target:l,children:i})},blockquote:({node:r,children:n,...i})=>{let o=r?.properties.dataAlert;return c(o)?e(s,{kind:o,children:n}):e("blockquote",{...i,children:n})},img:({src:r,alt:n})=>e(b,{src:r,alt:n}),pre:({node:r,children:n,...i})=>{let o=(e=>{let[r]=e?.children??[];if(r?.type!=="element"||"code"!==r.tagName)return;let{className:n}=r.properties;if(Array.isArray(n)&&n.includes("language-form"))return r.children.map(e=>"text"===e.type?e.value:"").join("")})(r);return null==o?e("pre",{...i,children:n}):e(A,{source:o,end:r?.position?.end.offset})},table:({node:r,children:n,...i})=>e(w,{children:e("table",{...i,children:n})})},I=[m,u],q=e=>g(e)?e:d(e);export const AssistantMarkdown=o(({markdown:r,isStreaming:n,forms:i})=>{let o=n?v(r):r,t=x(r)?o.length:void 0,d=l(()=>({forms:i,openFenceEnd:t,isStreaming:n}),[i,t,n]);return e(j,{children:e(S.Provider,{value:d,children:e(a,{components:B,remarkPlugins:I,urlTransform:q,children:o})})})});
1
+ import{jsx as e,Fragment as r}from"react/jsx-runtime";import{styled as n}from"@mui/material";import{createContext as t,memo as i,useContext as o,useMemo as l}from"react";import a,{defaultUrlTransform as d}from"react-markdown";import s from"remark-gfm";import{AssistantAlert as m,isAlertKind as c,remarkAlerts as u}from"./alert/index.js";import{AssistantEntityLink as p}from"./entity-link/index.js";import{AssistantForm as f}from"./form/index.js";import{AssistantReferenceLink as h,isAssistantLinkHref as g,parseAssistantLinkTarget as k}from"./reference-link/index.js";import{AssistantImage as b}from"./resource-image/index.js";import{completeStreamedMarkdown as v,hasOpenFence as x,isCutOffFence as y}from"./streamed-markdown.js";import{AssistantPanelName as j}from"./theme.js";let w=n("div",{name:j,slot:"assistantMessage"})(({theme:{palette:e,shape:r,spacing:n,typography:t}})=>({overflowWrap:"anywhere","& > :first-child":{marginBlockStart:0},"& > :last-child":{marginBlockEnd:0},"p, ul, ol, pre, blockquote":{marginBlock:n(1)},"h1, h2, h3, h4, h5, h6":{...t.subtitle2,marginBlock:n(1.5,.5)},"ul, ol":{paddingInlineStart:n(2.5)},a:{color:e.primary.main},code:{background:e.action.hover,borderRadius:r.borderRadius/2,fontFamily:"ui-monospace, Menlo, monospace",fontSize:"0.9em",paddingInline:n(.5)},pre:{background:e.action.hover,borderRadius:r.borderRadius,overflowX:"auto",padding:n(1),code:{background:"none",padding:0}},blockquote:{borderInlineStart:`2px solid ${e.divider}`,color:e.text.secondary,marginInline:0,paddingInlineStart:n(1.5)},"th, td":{borderBlockEnd:`1px solid ${e.divider}`,padding:n(.5,1),textAlign:"start",verticalAlign:"top"}})),S=n("div")({overflowX:"auto",table:{borderCollapse:"collapse",inlineSize:"100%"}}),A=t({forms:"hidden",text:"",openFenceEnd:void 0,isStreaming:!1}),B=({source:r,start:n,end:t})=>{let{forms:i,text:l,openFenceEnd:a,isStreaming:d}=o(A);return"hidden"===i?null:d&&null!=t&&t===a?e(f,{source:r,status:"writing"}):!d&&null!=n&&null!=t&&y(l,{start:n,end:t})?null:e(f,{source:r,status:"disabled"===i?"waiting":"ready"})},I={a:({node:n,children:t,href:i,...o})=>{if(null==i||!g(i))return e("a",{...o,href:i,target:"_blank",rel:"noopener noreferrer",children:t});let l=k(i);return null==l?e(r,{children:t}):"entity"===l.kind?e(p,{id:l.id,children:t}):e(h,{target:l,children:t})},blockquote:({node:r,children:n,...t})=>{let i=r?.properties.dataAlert;return c(i)?e(m,{kind:i,children:n}):e("blockquote",{...t,children:n})},img:({src:r,alt:n})=>e(b,{src:r,alt:n}),pre:({node:r,children:n,...t})=>{let i=(e=>{let[r]=e?.children??[];if(r?.type!=="element"||"code"!==r.tagName)return;let{className:n}=r.properties;if(Array.isArray(n)&&n.includes("language-form"))return r.children.map(e=>"text"===e.type?e.value:"").join("")})(r);return null==i?e("pre",{...t,children:n}):e(B,{source:i,start:r?.position?.start.offset,end:r?.position?.end.offset})},table:({node:r,children:n,...t})=>e(S,{children:e("table",{...t,children:n})})},q=[s,u],R=e=>g(e)?e:d(e);export const AssistantMarkdown=i(({markdown:r,isStreaming:n,forms:t})=>{let i=n?v(r):r,o=n&&x(r)?i.length:void 0,d=l(()=>({forms:t,text:i,openFenceEnd:o,isStreaming:n}),[t,i,o,n]);return e(w,{children:e(A.Provider,{value:d,children:e(a,{components:I,remarkPlugins:q,urlTransform:R,children:i})})})});
@@ -3,8 +3,9 @@
3
3
  * has to say itself, which is a line while the thread loads, a greeting for an empty thread, a
4
4
  * "Thinking…" line and a failure with its way out. It follows a streaming reply until the user scrolls up.
5
5
  *
6
- * A conversation the assistant continued from a summary is painted whole: the threads that were
7
- * closed come first, each ended by a separator, and the ones still on the server are loaded one at a
8
- * time from a control above them.
6
+ * A conversation is painted whole as the user scrolls up: the thread shows its newest messages first
7
+ * and loads older pages when its top comes into view. A conversation the assistant continued from a
8
+ * summary has closed threads before it, each ended by a separator; once the current thread is painted
9
+ * whole, the ones still on the server are loaded one at a time from a control above them.
9
10
  */
10
11
  export declare const AssistantThread: () => import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- import{jsx as e,jsxs as a}from"react/jsx-runtime";import{Trans as i}from"@lingui/react";import{Button as t,styled as s}from"@mui/material";import{useCallback as r,useMemo as n}from"react";import{match as o}from"ts-pattern";import{useEagerObservableValue as l}from"#package/react-sdk";import{PhxIcon as d}from"#package/ui-sdk";import{useConfigurator as m}from"../../application-runtime/index.js";import{AssistantToolChips as c}from"./AssistantChips.js";import{AssistantMarkdown as h}from"./AssistantMarkdown.js";import{describeAssistantFailure as p}from"./assistant-failure.js";import{MessageImages as g}from"./attachments/index.js";import{EntityLinkSelectionProvider as u,useCreateEntityLinkSelection as f}from"./entity-link/index.js";import{AssistantPanelName as k}from"./theme.js";import{buildEarlierThreadItems as v,buildThreadView as b}from"./thread-items.js";import{useFollowStream as w}from"./use-follow-stream.js";let x=s("div",{name:k,slot:"thread"})({display:"grid",position:"relative"}),y=s("div",{name:k,slot:"messages"})(({theme:{spacing:e,typography:a}})=>({...a.body2,display:"flex",flexDirection:"column",gap:e(1.5),overflowY:"auto",overscrollBehavior:"contain",paddingBlock:e(2),paddingInline:`var(--phx-sidebar-padding, ${e(2)})`,"& > :first-child":{marginBlockStart:"auto"}})),T=s("div",{name:k,slot:"userMessage"})(({theme:{palette:e,spacing:a}})=>({alignSelf:"flex-end",background:`hsl(from ${e.primary.main} h s l / 12%)`,borderRadius:"14px 14px 4px 14px",display:"grid",gap:a(1),maxInlineSize:"85%",overflowWrap:"anywhere",paddingBlock:a(1),paddingInline:a(1.5),whiteSpace:"pre-wrap"})),j=s("div",{name:k,slot:"greeting"})({}),C=s("div",{name:k,slot:"status"})(({theme:{palette:e,typography:a}})=>({...a.caption,color:e.text.secondary})),I=s("div",{name:k,slot:"separator"})(({theme:{palette:e,spacing:a,typography:i}})=>({...i.caption,alignItems:"center",color:e.text.secondary,display:"flex",gap:a(1),"&::before, &::after":{borderBlockStart:`1px solid ${e.divider}`,content:'""',flex:1}})),S=s(t,{name:k,slot:"earlierButton"})({alignSelf:"center"}),B=s("div",{name:k,slot:"notice"})(({theme:{palette:e,shape:a,spacing:i}})=>({alignItems:"center",background:e.action.hover,borderRadius:a.borderRadius,display:"flex",flexWrap:"wrap",gap:i(1),justifyContent:"space-between",paddingBlock:i(1),paddingInline:i(1.5)})),E=s(t,{name:k,slot:"newReplyButton"})(({theme:{palette:e,spacing:a}})=>({background:e.text.primary,borderRadius:"calc(infinity * 1px)",color:e.background.paper,insetBlockEnd:a(1),insetInlineStart:"50%",position:"absolute",translate:"-50% 0","&:hover":{background:e.text.secondary}})),A=({item:t,isActive:s,undoableToolCallId:r,onUndo:n})=>o(t).with({kind:"user"},({text:i,imageIds:t})=>a(T,{children:[t.length>0&&e(g,{imageIds:t}),i]})).with({kind:"text"},({markdown:a,isStreaming:i,forms:t})=>e(h,{markdown:a,isStreaming:i,forms:t})).with({kind:"tools"},({tools:a})=>e(c,{tools:a,isActive:s,canUndo:a.some(({id:e})=>e===r),onUndo:n})).with({kind:"separator"},()=>e(I,{role:"separator",children:e(i,{id:"sdk.assistant.thread.earlierSummarized",message:"Earlier conversation summarized"})})).exhaustive();export const AssistantThread=()=>{let{assistantSystem:s}=m(),c=l(s.chat$),{messages:h,isLoading:g,isResuming:k,earlierThreads:T}=c,I=l(s.undoTipToolCallId$),R=g?void 0:I,{items:L,isThinking:z}=n(()=>b(h,g,k),[h,g,k]),$=n(()=>v(T),[T]),U=n(()=>L.filter(({kind:e})=>"user"===e).length,[L]),D=c.error?p(c.failedStatus):void 0,{scrollerRef:M,hasUnseenContent:W,handleScroll:q,scrollToEnd:H}=w(n(()=>({messages:h,isThinking:z,isResuming:k,failure:D?.kind}),[h,z,k,D?.kind]),U),N=f(),Y=r(e=>{e.target instanceof Element&&e.target.closest('a, button, input, label, select, textarea, [role="button"], [role="tooltip"]')||window.getSelection()?.isCollapsed!==!1&&N.release()},[N]),F=!c.isLoaded&&0===$.length&&!k&&!D;return a(x,{children:[e(u,{selection:N,children:a(y,{ref:M,onScroll:q,onClick:Y,role:"log","aria-live":"polite",children:[c.isLoaded&&0===L.length&&0===$.length&&!g&&!k&&!D&&e(j,{children:e(i,{id:"sdk.assistant.thread.greeting",message:"Hi. I can answer questions about this design and change it with you. Tell me what you need."})}),F&&e(C,{children:e(i,{id:"sdk.assistant.thread.loading",message:"Loading the conversation…"})}),c.isLoadingEarlierThread&&e(C,{children:e(i,{id:"sdk.assistant.thread.loadingEarlier",message:"Loading the earlier conversation…"})}),c.hasEarlierThread&&!c.isLoadingEarlierThread&&e(S,{size:"small",color:"inherit",onClick:s.loadEarlierThread,children:e(i,{id:"sdk.assistant.thread.showEarlier.label",message:"Show earlier conversation"})}),$.map(a=>e(A,{item:a,isActive:!1,undoableToolCallId:R,onUndo:s.undoToolCalls},a.id)),L.map(a=>e(A,{item:a,isActive:g&&a===L.at(-1),undoableToolCallId:R,onUndo:s.undoToolCalls},a.id)),k&&e(C,{children:e(i,{id:"sdk.assistant.thread.resuming",message:"Resuming the conversation…"})}),z&&e(C,{children:e(i,{id:"sdk.assistant.thread.thinking",message:"Thinking…"})}),D&&a(B,{role:"alert",children:[e("span",{children:o(D.kind).with("notAvailable",()=>e(i,{id:"sdk.assistant.failure.notAvailable",message:"The assistant is not available here."})).with("busy",()=>e(i,{id:"sdk.assistant.failure.busy",message:"The assistant is still working on an earlier message."})).with("unavailable",()=>e(i,{id:"sdk.assistant.failure.unavailable",message:"The assistant is unavailable right now."})).exhaustive()}),D.canRetry&&e(t,{size:"small",variant:"outlined",color:"inherit",onClick:s.reloadThread,children:e(i,{id:"sdk.assistant.failure.retry.label",message:"Try again"})})]})]})}),W&&e(E,{size:"small",onClick:H,endIcon:e(d,{name:"CaretDown"}),children:e(i,{id:"sdk.assistant.thread.newReply.label",message:"New reply"})})]})};
1
+ import{jsx as e,jsxs as a}from"react/jsx-runtime";import{Trans as i}from"@lingui/react";import{Button as s,styled as t}from"@mui/material";import{useCallback as r,useMemo as n,useRef as o}from"react";import{match as l}from"ts-pattern";import{useEagerObservableValue as d}from"#package/react-sdk";import{PhxIcon as m,hoverStyles as c}from"#package/ui-sdk";import{useConfigurator as h}from"../../application-runtime/index.js";import{AssistantActivityRow as g,AssistantToolChips as p}from"./AssistantChips.js";import{AssistantMarkdown as u}from"./AssistantMarkdown.js";import{describeAssistantFailure as k}from"./assistant-failure.js";import{MessageImages as f}from"./attachments/index.js";import{EntityLinkSelectionProvider as b,useCreateEntityLinkSelection as v}from"./entity-link/index.js";import{AssistantPanelName as x}from"./theme.js";import{buildEarlierThreadItems as w,buildThreadView as y}from"./thread-items.js";import{useFollowStream as T}from"./use-follow-stream.js";import{useLoadOlderOnTop as I}from"./use-load-older-on-top.js";let S=t("div",{name:x,slot:"thread"})({display:"grid",position:"relative"}),j=t("div",{name:x,slot:"messages"})(({theme:{spacing:e,typography:a}})=>({...a.body2,display:"flex",flexDirection:"column",gap:e(1.5),overflowY:"auto",overscrollBehavior:"contain",paddingBlock:e(2),paddingInline:`var(--phx-sidebar-padding, ${e(2)})`,position:"relative","& > :first-child":{marginBlockStart:"auto"}})),C=t("div",{name:x,slot:"userMessage"})(({theme:{palette:e,spacing:a}})=>({alignSelf:"flex-end",background:`hsl(from ${e.primary.main} h s l / 12%)`,borderRadius:"14px 14px 4px 14px",display:"grid",gap:a(1),maxInlineSize:"85%",overflowWrap:"anywhere",paddingBlock:a(1),paddingInline:a(1.5),whiteSpace:"pre-wrap"})),B=t("div",{name:x,slot:"greeting"})({}),R=t("div",{name:x,slot:"status"})(({theme:{palette:e,typography:a}})=>({...a.caption,color:e.text.secondary})),L=t("div",{name:x,slot:"separator"})(({theme:{palette:e,spacing:a,typography:i}})=>({...i.caption,alignItems:"center",color:e.text.secondary,display:"flex",gap:a(1),"&::before, &::after":{borderBlockStart:`1px solid ${e.divider}`,content:'""',flex:1}})),A=t(s,{name:x,slot:"earlierButton"})({alignSelf:"center"}),E=t("div")({blockSize:1,insetBlockStart:0,insetInline:0,position:"absolute"}),M=t(R)(({theme:{palette:e,shape:a,spacing:i}})=>({background:e.background.paper,borderRadius:a.borderRadius,insetBlockStart:i(1),insetInlineStart:"50%",paddingBlock:i(.5),paddingInline:i(1),position:"absolute",translate:"-50% 0"})),z=t("div",{name:x,slot:"notice"})(({theme:{palette:e,shape:a,spacing:i}})=>({alignItems:"center",background:e.action.hover,borderRadius:a.borderRadius,display:"flex",flexWrap:"wrap",gap:i(1),justifyContent:"space-between",paddingBlock:i(1),paddingInline:i(1.5)})),O=t(s,{name:x,slot:"newReplyButton"})(({theme:{palette:e,spacing:a}})=>({background:e.text.primary,borderRadius:"calc(infinity * 1px)",color:e.background.paper,insetBlockEnd:a(1),insetInlineStart:"50%",position:"absolute",translate:"-50% 0","&:hover":{background:e.text.primary},...c({"&:hover":{background:e.text.secondary}})})),$=({item:s,isActive:t,undoableToolCallId:r,onUndo:n})=>l(s).with({kind:"user"},({text:i,imageIds:s})=>a(C,{children:[s.length>0&&e(f,{imageIds:s}),i]})).with({kind:"text"},({markdown:a,isStreaming:i,forms:s})=>e(u,{markdown:a,isStreaming:i,forms:s})).with({kind:"tools"},({tools:a})=>e(p,{tools:a,isActive:t,canUndo:a.some(({id:e})=>e===r),onUndo:n})).with({kind:"separator"},()=>e(L,{role:"separator",children:e(i,{id:"sdk.assistant.thread.earlierSummarized",message:"Earlier conversation summarized"})})).exhaustive();export const AssistantThread=()=>{let{assistantSystem:t}=h(),c=d(t.chat$),{messages:p,isLoading:u,isResuming:f,earlierThreads:x}=c,C=d(t.undoTipToolCallId$),L=u?void 0:C,{items:U,isThinking:D}=n(()=>y(p,u,f),[p,u,f]),W=n(()=>w(x),[x]),q=n(()=>U.filter(({kind:e})=>"user"===e).at(-1)?.id,[U]),H=c.error?k(c.failedStatus):void 0,K=p.at(-1),{scrollerRef:N,hasUnseenContent:Y,handleScroll:F,scrollToEnd:G}=T(n(()=>({newestMessage:K,isThinking:D,isResuming:f,failure:H?.kind}),[K,D,f,H?.kind]),q),J=o(null);I(N,J,{enabled:c.hasOlderMessages&&!c.isLoadingOlderMessages,onReachTop:t.loadOlderMessages,firstItemKey:p[0]?.id});let P=null!==c.earlierThreadId&&!c.hasOlderMessages&&!c.isLoadingEarlierThread,Q=v(),V=r(e=>{e.target instanceof Element&&e.target.closest('a, button, input, label, select, textarea, [role="button"], [role="tooltip"]')||window.getSelection()?.isCollapsed!==!1&&Q.release()},[Q]),X=!c.isLoaded&&0===W.length&&!f&&!H;return a(S,{children:[e(b,{selection:Q,children:a(j,{ref:N,onScroll:F,onClick:V,role:"log","aria-live":"polite",children:[c.isLoaded&&0===U.length&&0===W.length&&!u&&!f&&!H&&e(B,{children:e(i,{id:"sdk.assistant.thread.greeting",message:"Hi. I can answer questions about this design and change it with you. Tell me what you need."})}),X&&e(R,{children:e(i,{id:"sdk.assistant.thread.loading",message:"Loading the conversation…"})}),c.isLoadingEarlierThread&&e(R,{children:e(i,{id:"sdk.assistant.thread.loadingEarlier",message:"Loading the earlier conversation…"})}),P&&e(A,{size:"small",color:"inherit",onClick:t.loadEarlierThread,children:e(i,{id:"sdk.assistant.thread.showEarlier.label",message:"Show earlier conversation"})}),W.map(a=>e($,{item:a,isActive:!1,undoableToolCallId:L,onUndo:t.undoToolCalls},a.id)),U.map(a=>e($,{item:a,isActive:u&&a===U.at(-1),undoableToolCallId:L,onUndo:t.undoToolCalls},a.id)),f&&e(R,{children:e(i,{id:"sdk.assistant.thread.resuming",message:"Resuming the conversation…"})}),D&&e(g,{label:e(i,{id:"sdk.assistant.thread.thinking",message:"Thinking…"})}),H&&a(z,{role:"alert",children:[e("span",{children:l(H.kind).with("notAvailable",()=>e(i,{id:"sdk.assistant.failure.notAvailable",message:"The assistant is not available here."})).with("busy",()=>e(i,{id:"sdk.assistant.failure.busy",message:"The assistant is still working on an earlier message."})).with("unavailable",()=>e(i,{id:"sdk.assistant.failure.unavailable",message:"The assistant is unavailable right now."})).exhaustive()}),H.canRetry&&e(s,{size:"small",variant:"outlined",color:"inherit",onClick:t.reloadThread,children:e(i,{id:"sdk.assistant.failure.retry.label",message:"Try again"})})]}),c.hasOlderMessages&&e(E,{ref:J,"aria-hidden":!0})]})}),c.isLoadingOlderMessages&&e(M,{role:"status",children:e(i,{id:"sdk.assistant.thread.loadingOlder",message:"Loading earlier messages…"})}),Y&&e(O,{size:"small",onClick:G,endIcon:e(m,{name:"CaretDown"}),children:e(i,{id:"sdk.assistant.thread.newReply.label",message:"New reply"})})]})};
@@ -4,5 +4,8 @@ export interface AssistantAlertProps {
4
4
  readonly kind: AlertKind;
5
5
  readonly children: ReactNode;
6
6
  }
7
- /** A GitHub alert in a reply: its content as Markdown, marked by the colour and icon of its kind. */
7
+ /**
8
+ * A GitHub alert in a reply: its content as Markdown, marked by the colour and icon of its kind,
9
+ * and starting with the word for its kind, which only assistive technology reads.
10
+ */
8
11
  export declare const AssistantAlert: import("react").MemoExoticComponent<({ kind, children }: AssistantAlertProps) => import("react/jsx-runtime").JSX.Element>;
@@ -1 +1 @@
1
- import{jsx as r,jsxs as i}from"react/jsx-runtime";import{alpha as o,styled as t}from"@mui/material";import{memo as n}from"react";import{PhxIcon as a}from"#package/ui-sdk";import{AssistantPanelName as e}from"../theme.js";let l={note:{color:"info",icon:"Info"},tip:{color:"success",icon:"Lightbulb"},important:{color:"primary",icon:"WarningCircle"},warning:{color:"warning",icon:"Warning"},caution:{color:"error",icon:"XCircle"}},c=t("div",{name:e,slot:"alert"})(({theme:{palette:r,shape:i,spacing:t,typography:n}})=>({borderInlineStart:"3px solid",borderRadius:i.borderRadius,display:"grid",gap:t(1),gridTemplateColumns:"min-content minmax(0, 1fr)",marginBlock:t(1),padding:t(1,1.5),...Object.fromEntries(Object.entries(l).map(([i,{color:t}])=>[`&[data-alert="${i}"]`,{background:o(r[t].main,.08),borderInlineStartColor:r[t].main,"& > :first-child":{color:r[t].main}}])),"& > :last-child > :first-child":{marginBlockStart:0},"& > :last-child > :last-child":{marginBlockEnd:0},"& > :first-child":{blockSize:`calc(${n.body2.lineHeight} * 1em)`,display:"grid",placeItems:"center"}}));export const AssistantAlert=n(({kind:o,children:t})=>i(c,{role:"note","data-alert":o,children:[r("span",{children:r(a,{name:l[o].icon})}),r("div",{children:t})]}));
1
+ import{jsx as a,jsxs as i}from"react/jsx-runtime";import{alpha as r,styled as t}from"@mui/material";import{visuallyHidden as e}from"@mui/utils";import{memo as l}from"react";import{useLocalizable as n}from"#package/react-sdk";import{PhxIcon as s}from"#package/ui-sdk";import{AssistantPanelName as o}from"../theme.js";let m={note:{color:"info",icon:"Info",label:{id:"sdk.assistant.alert.note.label",message:"Note"}},tip:{color:"success",icon:"Lightbulb",label:{id:"sdk.assistant.alert.tip.label",message:"Tip"}},important:{color:"primary",icon:"WarningCircle",label:{id:"sdk.assistant.alert.important.label",message:"Important"}},warning:{color:"warning",icon:"Warning",label:{id:"sdk.assistant.alert.warning.label",message:"Warning"}},caution:{color:"error",icon:"XCircle",label:{id:"sdk.assistant.alert.caution.label",message:"Caution"}}},c=t("div",{name:o,slot:"alert"})(({theme:{palette:a,shape:i,spacing:t,typography:e}})=>({borderInlineStart:"3px solid",borderRadius:i.borderRadius,display:"grid",gap:t(1),gridTemplateColumns:"min-content minmax(0, 1fr)",marginBlock:t(1),padding:t(1,1.5),...Object.fromEntries(Object.entries(m).map(([i,{color:t}])=>[`&[data-alert="${i}"]`,{background:r(a[t].main,.08),borderInlineStartColor:a[t].main,"& > :first-child":{color:a[t].main}}])),"& > :last-child > :first-child":{marginBlockStart:0},"& > :last-child > :last-child":{marginBlockEnd:0},"& > :first-child":{blockSize:`calc(${e.body2.lineHeight} * 1em)`,display:"grid",placeItems:"center"}}));export const AssistantAlert=l(({kind:r,children:t})=>{let{icon:l,label:o}=m[r],d=n(o);return i(c,{role:"note","data-alert":r,children:[i("span",{children:[a(s,{name:l}),a("span",{style:e,children:d})]}),a("div",{children:t})]})});
@@ -1 +1 @@
1
- import{jsx as e}from"react/jsx-runtime";import{styled as t}from"@mui/material";import{memo as n,useCallback as i,useEffect as r,useRef as o}from"react";import{sceneEntitySelectHotspotComponent as a,selectableComponent as l}from"#package/domain";import{FrontendAnalyticsFactory as s,useDomain as c,useFirstRenderedComponent as d,useHoveredDomainEntityId as m,useRenderedSelector as u,useSelectEntity as p,useSelectedDomainEntityId as k,useStoreSelector as y}from"#package/react-sdk";import{assistantReferenceStyles as f}from"../reference-link/index.js";import{AssistantPanelName as g}from"../theme.js";import{useEntityLinkSelection as h}from"./entity-link-selection.js";import{resolveEntityLinkState as v}from"./entity-link-state.js";let b=t("span",{name:g,slot:"entityLink"})(e=>({...f(e),'&[data-entity-link="plain"], &[data-entity-link="missing"]':{cursor:"auto","&:hover":{background:"none"}},'&[data-selected="true"]':{textDecorationStyle:"solid"}})),S={interactive:void 0,plain:"plain",missing:"muted"},j=({kind:t,isSelected:n,children:i})=>e(b,{"data-entity-link":t,"data-reference":S[t],"data-selected":n,children:i}),x=({id:t,isSelected:n,children:u})=>{let{navigationSystem:k}=c(),y=d({entityIds:[t],componentTypes:[l]}),f=d({entityIds:[t],componentTypes:[a]}),{kind:g,canHover:S}=v({isSelectable:null!=y,isHoverDisabled:y?.state.hoverable===!1,hasSelectHotspot:null!=f}),x=m()===t,E=p(s.AssistantEntityLinkClicked),T=h(),D=i(()=>{T?.remember(t),E(t)},[t,T,E]),H=o(!1),L=i(()=>{S&&(H.current=!0,k.debouncedToggleHover(t))},[S,t,k]),I=i(()=>{H.current&&(H.current=!1,k.debouncedToggleHover(null))},[k]),A=i(e=>{"touch"!==e.pointerType&&L()},[L]),C=i(e=>{e.currentTarget.matches(":focus-visible")&&L()},[L]),P=i(e=>{("Enter"===e.key||" "===e.key)&&(e.preventDefault(),D())},[D]);return(r(()=>I,[S,I,t]),"interactive"!==g)?e(j,{kind:g,isSelected:n,children:u}):e(b,{role:"button",tabIndex:0,"data-entity-link":g,"data-selected":n,"data-hovered":S&&x,"aria-current":n?"true":void 0,onClick:D,onKeyDown:P,onPointerEnter:A,onPointerLeave:I,onFocus:C,onBlur:I,children:u})};export const AssistantEntityLink=n(({id:t,children:n})=>{let{domain:i}=c(),r=y(e=>null!=i.getEntity(t,e.state),[i,t]),o=u(e=>null!=i.getEntity(t,e.state),[i,t]),a=k()===t;return r?o?e(x,{id:t,isSelected:a,children:n}):e(j,{kind:"plain",isSelected:a,children:n}):e(j,{kind:"missing",isSelected:!1,children:n})});
1
+ import{jsx as e}from"react/jsx-runtime";import{styled as t}from"@mui/material";import{memo as n,useCallback as r,useEffect as i,useRef as o}from"react";import{sceneEntitySelectHotspotComponent as a,selectableComponent as l}from"#package/domain";import{FrontendAnalyticsFactory as c,useDomain as s,useFirstRenderedComponent as d,useHoveredDomainEntityId as m,useRenderedSelector as u,useSelectEntity as p,useSelectedDomainEntityId as k,useStoreSelector as y}from"#package/react-sdk";import{hoverStyles as f}from"#package/ui-sdk";import{assistantReferenceStyles as g}from"../reference-link/index.js";import{AssistantPanelName as h}from"../theme.js";import{useEntityLinkSelection as v}from"./entity-link-selection.js";import{resolveEntityLinkState as b}from"./entity-link-state.js";let S=t("span",{name:h,slot:"entityLink"})(e=>({...g(e),'&[data-entity-link="plain"], &[data-entity-link="missing"]':{cursor:"auto",...f({"&:hover":{background:"none"}})},'&[data-selected="true"]':{textDecorationStyle:"solid"}})),j={interactive:void 0,plain:"plain",missing:"muted"},x=({kind:t,isSelected:n,children:r})=>e(S,{"data-entity-link":t,"data-reference":j[t],"data-selected":n,children:r}),E=({id:t,isSelected:n,children:u})=>{let{navigationSystem:k}=s(),y=d({entityIds:[t],componentTypes:[l]}),f=d({entityIds:[t],componentTypes:[a]}),{kind:g,canHover:h}=b({isSelectable:null!=y,isHoverDisabled:y?.state.hoverable===!1,hasSelectHotspot:null!=f}),j=m()===t,E=p(c.AssistantEntityLinkClicked),T=v(),D=r(()=>{T?.remember(t),E(t)},[t,T,E]),H=o(!1),L=o(!1),I=o(!1),A=r(()=>{I.current&&(I.current=!1,k.debouncedToggleHover(null))},[k]),C=r(()=>{h&&(H.current||L.current)?(I.current=!0,k.debouncedToggleHover(t)):A()},[h,A,t,k]),P=r(e=>{"touch"!==e.pointerType&&(L.current=!0,C())},[C]),w=r(()=>{L.current=!1,C()},[C]),B=r(e=>{e.currentTarget.matches(":focus-visible")&&(H.current=!0,C())},[C]),F=r(()=>{H.current=!1,C()},[C]),K=r(e=>{("Enter"===e.key||" "===e.key)&&(e.preventDefault(),D())},[D]);return(i(()=>A,[h,A,t]),"interactive"!==g)?e(x,{kind:g,isSelected:n,children:u}):e(S,{role:"button",tabIndex:0,"data-entity-link":g,"data-selected":n,"data-hovered":h&&j,"aria-current":n?"true":void 0,onClick:D,onKeyDown:K,onPointerEnter:P,onPointerLeave:w,onFocus:B,onBlur:F,children:u})};export const AssistantEntityLink=n(({id:t,children:n})=>{let{domain:r}=s(),i=y(e=>null!=r.getEntity(t,e.state),[r,t]),o=u(e=>null!=r.getEntity(t,e.state),[r,t]),a=k()===t;return i?o?e(E,{id:t,isSelected:a,children:n}):e(x,{kind:"plain",isSelected:a,children:n}):e(x,{kind:"missing",isSelected:!1,children:n})});