@salsita-ai/sdk 0.50.0-develop.bc08a38ffe → 0.50.0-develop.bd84173265

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 (348) hide show
  1. package/README.md +14 -13
  2. package/dist/application-spec/caching/content-diff.js +1 -1
  3. package/dist/application-spec/core/application-file.d.ts +0 -2
  4. package/dist/application-spec/core/application-file.js +1 -1
  5. package/dist/application-spec/errors/diagnostic-codes.d.ts +4 -0
  6. package/dist/application-spec/errors/diagnostic-codes.js +1 -1
  7. package/dist/application-spec/errors/diagnostic-messages.d.ts +4 -0
  8. package/dist/application-spec/errors/diagnostic-messages.js +1 -1
  9. package/dist/application-spec/generate-application/code/domain-runtime-files.js +1 -1
  10. package/dist/application-spec/generate-application/code/generate-application-code.d.ts +3 -2
  11. package/dist/application-spec/generate-application/code/generate-application-code.js +1 -1
  12. package/dist/application-spec/generate-application/code/project-scaffolding.d.ts +11 -8
  13. package/dist/application-spec/generate-application/code/project-scaffolding.js +2 -2
  14. package/dist/application-spec/generate-application/code/standalone-app-files.d.ts +2 -2
  15. package/dist/application-spec/generate-application/code/standalone-app-files.js +1 -1
  16. package/dist/application-spec/generate-application/code/templates/configurator-config.js +6 -4
  17. package/dist/application-spec/generate-application/code/templates/eslint-config.d.ts +5 -0
  18. package/dist/application-spec/generate-application/code/templates/eslint-config.js +4 -5
  19. package/dist/application-spec/generate-application/code/templates/frontend-config.js +3 -5
  20. package/dist/application-spec/generate-application/code/templates/gitignore.js +0 -3
  21. package/dist/application-spec/generate-application/code/templates/globals.js +3 -4
  22. package/dist/application-spec/generate-application/code/templates/index.d.ts +1 -1
  23. package/dist/application-spec/generate-application/code/templates/index.js +1 -1
  24. package/dist/application-spec/generate-application/code/templates/lingui-rc.d.ts +5 -0
  25. package/dist/application-spec/generate-application/code/templates/lingui-rc.js +4 -4
  26. package/dist/application-spec/generate-application/code/templates/package-json.js +1 -1
  27. package/dist/application-spec/generate-application/code/templates/prettier-config.d.ts +5 -0
  28. package/dist/application-spec/generate-application/code/templates/prettier-config.js +4 -5
  29. package/dist/application-spec/generate-application/code/templates/root-tsconfig.d.ts +6 -0
  30. package/dist/application-spec/generate-application/code/templates/root-tsconfig.js +2 -0
  31. package/dist/application-spec/generate-application/code/templates/skills/phoenix-cli-skill.js +1 -1
  32. package/dist/application-spec/generate-application/code/templates/skills/phoenix-review-skill.js +1 -1
  33. package/dist/application-spec/generate-application/code/templates/skills/sdk-content.d.ts +13 -7
  34. package/dist/application-spec/generate-application/code/templates/skills/sdk-content.js +2 -2
  35. package/dist/application-spec/generate-application/code/templates/tsconfig.d.ts +5 -0
  36. package/dist/application-spec/generate-application/code/templates/tsconfig.js +1 -1
  37. package/dist/application-spec/generate-application/code/templates/webhook-index.d.ts +6 -1
  38. package/dist/application-spec/generate-application/code/templates/webhook-index.js +10 -1
  39. package/dist/application-spec/generate-application/code/templates/webhooks-config.js +2 -3
  40. package/dist/application-spec/generate-application/index.d.ts +2 -0
  41. package/dist/application-spec/generate-application/index.js +1 -1
  42. package/dist/application-spec/generate-application/runtime/admin-runtime/admin-model-runtime.d.ts +4 -3
  43. package/dist/application-spec/generate-application/runtime/admin-runtime/admin-runtime.d.ts +7 -3
  44. package/dist/application-spec/generate-application/runtime/admin-runtime/admin-runtime.js +1 -1
  45. package/dist/application-spec/generate-application/runtime/admin-runtime/states-runtime.d.ts +2 -2
  46. package/dist/application-spec/generate-application/runtime/application-runtime.d.ts +13 -5
  47. package/dist/application-spec/generate-application/runtime/application-runtime.js +1 -1
  48. package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-model-runtime.d.ts +4 -3
  49. package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-runtime.d.ts +6 -2
  50. package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-runtime.js +1 -1
  51. package/dist/application-spec/generate-application/runtime/configurator-runtime/states-runtime.d.ts +2 -2
  52. package/dist/application-spec/generate-application/runtime/factory-data/factory-data-runtime.d.ts +43 -0
  53. package/dist/application-spec/generate-application/runtime/factory-data/factory-data-runtime.js +1 -0
  54. package/dist/application-spec/generate-application/runtime/factory-data/index.d.ts +3 -0
  55. package/dist/application-spec/generate-application/runtime/factory-data/index.js +1 -0
  56. package/dist/application-spec/generate-application/runtime/factory-data/recipe-defaults.d.ts +13 -0
  57. package/dist/application-spec/generate-application/runtime/factory-data/recipe-defaults.js +1 -0
  58. package/dist/application-spec/generate-application/runtime/factory-data/static-violations.d.ts +16 -0
  59. package/dist/application-spec/generate-application/runtime/factory-data/static-violations.js +1 -0
  60. package/dist/application-spec/generate-application/runtime/migrations/index.d.ts +1 -0
  61. package/dist/application-spec/generate-application/runtime/migrations/index.js +1 -0
  62. package/dist/application-spec/generate-application/runtime/migrations/migration-runtime.d.ts +53 -0
  63. package/dist/application-spec/generate-application/runtime/migrations/migration-runtime.js +1 -0
  64. package/dist/application-spec/generate-application/runtime/sections/assistant-runtime.d.ts +2 -2
  65. package/dist/application-spec/generate-application/runtime/sections/data-runtime.d.ts +4 -4
  66. package/dist/application-spec/generate-application/runtime/sections/expression-runtime.d.ts +3 -2
  67. package/dist/application-spec/generate-application/runtime/sections/theme-runtime.d.ts +2 -2
  68. package/dist/application-spec/generate-application/runtime/sections/transformers-runtime.d.ts +3 -3
  69. package/dist/application-spec/generate-application/runtime-spec/decode-runtime-spec.d.ts +9 -0
  70. package/dist/application-spec/generate-application/runtime-spec/decode-runtime-spec.js +1 -0
  71. package/dist/application-spec/generate-application/runtime-spec/encode-runtime-spec.d.ts +8 -0
  72. package/dist/application-spec/generate-application/runtime-spec/encode-runtime-spec.js +1 -0
  73. package/dist/application-spec/generate-application/runtime-spec/encoded-runtime-spec.d.ts +27 -0
  74. package/dist/application-spec/generate-application/runtime-spec/encoded-runtime-spec.js +1 -0
  75. package/dist/application-spec/generate-application/runtime-spec/index.d.ts +4 -0
  76. package/dist/application-spec/generate-application/runtime-spec/index.js +1 -0
  77. package/dist/application-spec/generate-application/runtime-spec/runtime-spec.d.ts +68 -0
  78. package/dist/application-spec/generate-application/runtime-spec/runtime-spec.js +1 -0
  79. package/dist/application-spec/parse-application-files/categorize/categorize-files.d.ts +34 -0
  80. package/dist/application-spec/parse-application-files/categorize/categorize-files.js +1 -1
  81. package/dist/application-spec/parse-application-files/categorize/earlier-generated-editor-configs.d.ts +16 -0
  82. package/dist/application-spec/parse-application-files/categorize/earlier-generated-editor-configs.js +9 -0
  83. package/dist/application-spec/parse-application-files/categorize/earlier-generated-tsconfig.d.ts +9 -0
  84. package/dist/application-spec/parse-application-files/categorize/earlier-generated-tsconfig.js +1 -0
  85. package/dist/application-spec/parse-application-files/raw-spec/parse-yaml-spec-file.js +1 -1
  86. package/dist/application-spec/parse-application-files/spec/application/admin-spec/admin-spec.js +1 -1
  87. package/dist/application-spec/parse-application-files/spec/application/configurator-spec/configurator-spec.js +1 -1
  88. package/dist/application-spec/parse-application-files/spec/common/index.d.ts +1 -0
  89. package/dist/application-spec/parse-application-files/spec/common/index.js +1 -1
  90. package/dist/application-spec/parse-application-files/spec/common/value-type/format-value-type.d.ts +3 -0
  91. package/dist/application-spec/parse-application-files/spec/common/value-type/format-value-type.js +1 -0
  92. package/dist/application-spec/parse-application-files/spec/common/value-type/index.d.ts +5 -0
  93. package/dist/application-spec/parse-application-files/spec/common/value-type/index.js +1 -0
  94. package/dist/application-spec/parse-application-files/spec/common/value-type/intersect-value-types.d.ts +6 -0
  95. package/dist/application-spec/parse-application-files/spec/common/value-type/intersect-value-types.js +1 -0
  96. package/dist/application-spec/parse-application-files/spec/common/value-type/is-assignable-value-type.d.ts +8 -0
  97. package/dist/application-spec/parse-application-files/spec/common/value-type/is-assignable-value-type.js +1 -0
  98. package/dist/application-spec/parse-application-files/spec/common/value-type/value-type-at.d.ts +10 -0
  99. package/dist/application-spec/parse-application-files/spec/common/value-type/value-type-at.js +1 -0
  100. package/dist/application-spec/parse-application-files/spec/common/value-type/value-type.d.ts +98 -0
  101. package/dist/application-spec/parse-application-files/spec/common/value-type/value-type.js +1 -0
  102. package/dist/application-spec/parse-application-files/spec/components/bindings/component-path.d.ts +13 -0
  103. package/dist/application-spec/parse-application-files/spec/components/bindings/component-path.js +1 -0
  104. package/dist/application-spec/parse-application-files/spec/components/bindings/index.d.ts +2 -0
  105. package/dist/application-spec/parse-application-files/spec/components/bindings/index.js +1 -1
  106. package/dist/application-spec/parse-application-files/spec/components/bindings/read-binding-type.d.ts +24 -0
  107. package/dist/application-spec/parse-application-files/spec/components/bindings/read-binding-type.js +1 -0
  108. package/dist/application-spec/parse-application-files/spec/components/component-state-type.d.ts +8 -0
  109. package/dist/application-spec/parse-application-files/spec/components/component-state-type.js +1 -0
  110. package/dist/application-spec/parse-application-files/spec/components/filter-criterion-types.d.ts +13 -0
  111. package/dist/application-spec/parse-application-files/spec/components/filter-criterion-types.js +1 -0
  112. package/dist/application-spec/parse-application-files/spec/components/static-entity-id.d.ts +14 -0
  113. package/dist/application-spec/parse-application-files/spec/components/static-entity-id.js +1 -0
  114. package/dist/application-spec/parse-application-files/spec/components/user-component-entry.d.ts +6 -0
  115. package/dist/application-spec/parse-application-files/spec/components/user-component-entry.js +1 -1
  116. package/dist/application-spec/parse-application-files/spec/components/user-components.d.ts +7 -4
  117. package/dist/application-spec/parse-application-files/spec/components/user-components.js +1 -1
  118. package/dist/application-spec/parse-application-files/spec/expressions/expression-read-types.d.ts +19 -0
  119. package/dist/application-spec/parse-application-files/spec/expressions/expression-read-types.js +1 -0
  120. package/dist/application-spec/parse-application-files/spec/expressions/expression-read.d.ts +13 -0
  121. package/dist/application-spec/parse-application-files/spec/expressions/expression-read.js +1 -0
  122. package/dist/application-spec/parse-application-files/spec/expressions/expressions.d.ts +6 -2
  123. package/dist/application-spec/parse-application-files/spec/expressions/expressions.js +1 -1
  124. package/dist/application-spec/parse-application-files/spec/invariants/invariants.d.ts +2 -2
  125. package/dist/application-spec/parse-application-files/spec/invariants/invariants.js +1 -1
  126. package/dist/application-spec/parse-application-files/spec/model/index.d.ts +1 -0
  127. package/dist/application-spec/parse-application-files/spec/model/index.js +1 -1
  128. package/dist/application-spec/parse-application-files/spec/model/model-type-resolution.d.ts +10 -0
  129. package/dist/application-spec/parse-application-files/spec/model/model-type-resolution.js +1 -0
  130. package/dist/client/phoenix-api.d.ts +367 -0
  131. package/dist/configurator/application-runtime/extensions/systems/assistant-system/assistant-system.d.ts +36 -1
  132. package/dist/configurator/application-runtime/extensions/systems/assistant-system/assistant-system.js +1 -1
  133. package/dist/configurator/application-runtime/extensions/systems/assistant-system/graphql-tools.d.ts +7 -1
  134. package/dist/configurator/application-runtime/extensions/systems/assistant-system/graphql-tools.js +1 -1
  135. package/dist/configurator/application-runtime/extensions/systems/graphql-system/graphql-system.d.ts +6 -0
  136. package/dist/configurator/application-runtime/extensions/systems/graphql-system/graphql-system.js +1 -1
  137. package/dist/configurator/common/configurator-interface.d.ts +16 -1
  138. package/dist/configurator/common/configurator-interface.js +1 -1
  139. package/dist/configurator/common/index.d.ts +2 -0
  140. package/dist/configurator/common/index.js +1 -1
  141. package/dist/configurator/common/use-finalize-action.d.ts +31 -0
  142. package/dist/configurator/common/use-finalize-action.js +1 -0
  143. package/dist/configurator/common/use-reset-camera.d.ts +6 -0
  144. package/dist/configurator/common/use-reset-camera.js +1 -0
  145. package/dist/configurator/pages/DefaultConfiguratorLayout.d.ts +3 -2
  146. package/dist/configurator/pages/LoadedConfiguratorDetailPage.js +1 -1
  147. package/dist/configurator/pages/configurator-layout-name.d.ts +2 -0
  148. package/dist/configurator/pages/configurator-layout-name.js +1 -0
  149. package/dist/configurator/pages/default-configurator-elements.d.ts +8 -0
  150. package/dist/configurator/pages/default-configurator-elements.js +1 -0
  151. package/dist/configurator/pages/default-elements/built-in-entity-element.d.ts +10 -0
  152. package/dist/configurator/pages/default-elements/built-in-entity-element.js +1 -0
  153. package/dist/configurator/pages/default-elements/built-in-layout-element.d.ts +10 -0
  154. package/dist/configurator/pages/default-elements/built-in-layout-element.js +1 -0
  155. package/dist/configurator/pages/default-elements/domain-control-elements.d.ts +6 -0
  156. package/dist/configurator/pages/default-elements/domain-control-elements.js +1 -0
  157. package/dist/configurator/pages/default-elements/index.d.ts +4 -0
  158. package/dist/configurator/pages/default-elements/index.js +1 -0
  159. package/dist/configurator/pages/default-elements/recipe-panel-elements.d.ts +3 -0
  160. package/dist/configurator/pages/default-elements/recipe-panel-elements.js +1 -0
  161. package/dist/configurator/pages/default-elements/sidebar-footer-elements.d.ts +7 -0
  162. package/dist/configurator/pages/default-elements/sidebar-footer-elements.js +1 -0
  163. package/dist/configurator/pages/default-elements/toolbar-elements.d.ts +7 -0
  164. package/dist/configurator/pages/default-elements/toolbar-elements.js +1 -0
  165. package/dist/configurator/pages/index.d.ts +1 -0
  166. package/dist/configurator/pages/index.js +1 -1
  167. package/dist/configurator/ui/assistant/AssistantChips.d.ts +8 -2
  168. package/dist/configurator/ui/assistant/AssistantChips.js +1 -1
  169. package/dist/configurator/ui/assistant/AssistantMarkdown.d.ts +7 -2
  170. package/dist/configurator/ui/assistant/AssistantMarkdown.js +1 -1
  171. package/dist/configurator/ui/assistant/AssistantPanel.js +1 -1
  172. package/dist/configurator/ui/assistant/AssistantThread.js +1 -1
  173. package/dist/configurator/ui/assistant/entity-link/AssistantEntityLink.d.ts +1 -1
  174. package/dist/configurator/ui/assistant/entity-link/AssistantEntityLink.js +1 -1
  175. package/dist/configurator/ui/assistant/entity-link/entity-link-state.d.ts +1 -1
  176. package/dist/configurator/ui/assistant/entity-link/index.d.ts +0 -1
  177. package/dist/configurator/ui/assistant/entity-link/index.js +1 -1
  178. package/dist/configurator/ui/assistant/form/AssistantForm.d.ts +19 -0
  179. package/dist/configurator/ui/assistant/form/AssistantForm.js +1 -0
  180. package/dist/configurator/ui/assistant/form/built-in-form-registry.d.ts +10 -0
  181. package/dist/configurator/ui/assistant/form/built-in-form-registry.js +1 -0
  182. package/dist/configurator/ui/assistant/form/compose-answer.d.ts +11 -0
  183. package/dist/configurator/ui/assistant/form/compose-answer.js +1 -0
  184. package/dist/configurator/ui/assistant/form/describe-build-errors.d.ts +6 -0
  185. package/dist/configurator/ui/assistant/form/describe-build-errors.js +1 -0
  186. package/dist/configurator/ui/assistant/form/form-element-definition.d.ts +14 -0
  187. package/dist/configurator/ui/assistant/form/form-element-definition.js +1 -0
  188. package/dist/configurator/ui/assistant/form/form-model.d.ts +38 -0
  189. package/dist/configurator/ui/assistant/form/form-model.js +1 -0
  190. package/dist/configurator/ui/assistant/form/form-registry.d.ts +31 -0
  191. package/dist/configurator/ui/assistant/form/form-registry.js +8 -0
  192. package/dist/configurator/ui/assistant/form/form-state.d.ts +4 -0
  193. package/dist/configurator/ui/assistant/form/form-state.js +1 -0
  194. package/dist/configurator/ui/assistant/form/index.d.ts +2 -0
  195. package/dist/configurator/ui/assistant/form/index.js +1 -0
  196. package/dist/configurator/ui/assistant/form/parse-form-block.d.ts +9 -0
  197. package/dist/configurator/ui/assistant/form/parse-form-block.js +1 -0
  198. package/dist/configurator/ui/assistant/form/read-form-attributes.d.ts +13 -0
  199. package/dist/configurator/ui/assistant/form/read-form-attributes.js +1 -0
  200. package/dist/configurator/ui/assistant/form-elements/FormGroup.d.ts +3 -0
  201. package/dist/configurator/ui/assistant/form-elements/FormGroup.js +1 -0
  202. package/dist/configurator/ui/assistant/form-elements/FormOptions.d.ts +3 -0
  203. package/dist/configurator/ui/assistant/form-elements/FormOptions.js +1 -0
  204. package/dist/configurator/ui/assistant/form-elements/FormReply.d.ts +3 -0
  205. package/dist/configurator/ui/assistant/form-elements/FormReply.js +1 -0
  206. package/dist/configurator/ui/assistant/form-elements/FormText.d.ts +3 -0
  207. package/dist/configurator/ui/assistant/form-elements/FormText.js +1 -0
  208. package/dist/configurator/ui/assistant/form-elements/form-element-props.d.ts +34 -0
  209. package/dist/configurator/ui/assistant/form-elements/form-element-props.js +1 -0
  210. package/dist/configurator/ui/assistant/form-elements/index.d.ts +5 -0
  211. package/dist/configurator/ui/assistant/form-elements/index.js +1 -0
  212. package/dist/configurator/ui/assistant/reference-link/AssistantReferenceLink.d.ts +16 -0
  213. package/dist/configurator/ui/assistant/reference-link/AssistantReferenceLink.js +1 -0
  214. package/dist/configurator/ui/assistant/reference-link/assistant-link-target.d.ts +34 -0
  215. package/dist/configurator/ui/assistant/reference-link/assistant-link-target.js +1 -0
  216. package/dist/configurator/ui/assistant/reference-link/assistant-reference-details.d.ts +25 -0
  217. package/dist/configurator/ui/assistant/reference-link/assistant-reference-details.js +1 -0
  218. package/dist/configurator/ui/assistant/reference-link/index.d.ts +3 -0
  219. package/dist/configurator/ui/assistant/reference-link/index.js +1 -0
  220. package/dist/configurator/ui/assistant/reference-link/reference-styles.d.ts +12 -0
  221. package/dist/configurator/ui/assistant/reference-link/reference-styles.js +1 -0
  222. package/dist/configurator/ui/assistant/reference-link/use-assistant-reference-details.d.ts +8 -0
  223. package/dist/configurator/ui/assistant/reference-link/use-assistant-reference-details.js +1 -0
  224. package/dist/configurator/ui/assistant/streamed-markdown.d.ts +2 -0
  225. package/dist/configurator/ui/assistant/streamed-markdown.js +2 -2
  226. package/dist/configurator/ui/assistant/thread-items.d.ts +8 -1
  227. package/dist/configurator/ui/assistant/thread-items.js +1 -1
  228. package/dist/docs/controls/select-child-entity/cardselect.mdx +1 -0
  229. package/dist/docs/fabs/basic.mdx +2 -2
  230. package/dist/docs/index.json +1 -1
  231. package/dist/docs/layouts/custom-layout.mdx +1466 -196
  232. package/dist/docs/phoenix/components.mdx +6 -0
  233. package/dist/docs/phoenix/configurator-interface.mdx +66 -13
  234. package/dist/docs/phoenix/deployments.mdx +2 -6
  235. package/dist/docs/phoenix/domain-model.mdx +2 -0
  236. package/dist/docs/phoenix/finalization.mdx +1 -1
  237. package/dist/docs/phoenix/getting-started.mdx +2 -1
  238. package/dist/docs/phoenix/layout-slots.mdx +4 -2
  239. package/dist/docs/phoenix/localization.mdx +8 -6
  240. package/dist/docs/phoenix/migration-guide.mdx +21 -8
  241. package/dist/docs/phoenix/phoenix-cli.mdx +46 -10
  242. package/dist/docs/phoenix/project-structure.mdx +31 -12
  243. package/dist/docs/phoenix/sdk-builder-workflow.mdx +2 -2
  244. package/dist/docs/phoenix/webhooks.mdx +21 -4
  245. package/dist/domain/application/application-config.d.ts +3 -1
  246. package/dist/domain/application/assistant/assistant-form-elements.d.ts +28 -0
  247. package/dist/domain/application/assistant/assistant-form-elements.js +1 -0
  248. package/dist/domain/application/assistant/generate-assistant-prompt.js +1 -1
  249. package/dist/domain/application/assistant/index.d.ts +2 -0
  250. package/dist/domain/application/assistant/index.js +1 -1
  251. package/dist/domain/application/assistant-recipe-groups.d.ts +3 -1
  252. package/dist/domain/application/configurator-builder.d.ts +4 -1
  253. package/dist/domain/application/configurator-builder.js +1 -1
  254. package/dist/domain/core/schema/extended-schema-validator.js +1 -1
  255. package/dist/domain/domain-context/index.d.ts +1 -1
  256. package/dist/domain/domain-context/undo-system.d.ts +28 -1
  257. package/dist/domain/domain-context/undo-system.js +1 -1
  258. package/dist/domain/domain-runtime/spec/initialize.js +1 -1
  259. package/dist/domain/domain-runtime/spec/selectors.js +1 -1
  260. package/dist/domain/domain-runtime/spec/types.d.ts +2 -0
  261. package/dist/domain/system-components/child-entity-selection.js +1 -1
  262. package/dist/domain/system-components/common/scene-entity-control-schema.d.ts +3 -0
  263. package/dist/domain/system-components/common/scene-entity-control-schema.js +1 -1
  264. package/dist/globals/index.d.ts +2 -0
  265. package/dist/i18n/locales/cs/messages.js +1 -1
  266. package/dist/i18n/locales/da/messages.js +1 -1
  267. package/dist/i18n/locales/de/messages.js +1 -1
  268. package/dist/i18n/locales/de-AT/messages.js +1 -1
  269. package/dist/i18n/locales/en/messages.js +1 -1
  270. package/dist/i18n/locales/en-AU/messages.js +1 -1
  271. package/dist/i18n/locales/en-GB/messages.js +1 -1
  272. package/dist/i18n/locales/es/messages.js +1 -1
  273. package/dist/i18n/locales/fr/messages.js +1 -1
  274. package/dist/i18n/locales/hu/messages.js +1 -1
  275. package/dist/i18n/locales/it/messages.js +1 -1
  276. package/dist/i18n/locales/nl/messages.js +1 -1
  277. package/dist/i18n/locales/pl/messages.js +1 -1
  278. package/dist/i18n/locales/pt/messages.js +1 -1
  279. package/dist/i18n/locales/ro/messages.js +1 -1
  280. package/dist/i18n/locales/sk/messages.js +1 -1
  281. package/dist/i18n/locales/tr/messages.js +1 -1
  282. package/dist/legacy/domain-cli/utils/cache.d.ts +1 -1
  283. package/dist/legacy/domain-cli/utils/cache.js +1 -1
  284. package/dist/legacy/domain-spec/__generated/domain-schema.d.ts +79 -80
  285. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/claude-md.d.ts +1 -1
  286. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/cursor-rules.d.ts +1 -1
  287. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/shared-sdk-content.d.ts +1 -1
  288. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/shared-sdk-content.js +7 -2
  289. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/frontend-admin.js +18 -16
  290. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/frontend-configurator.js +14 -12
  291. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/frontend-embedded-admin.js +13 -11
  292. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/frontend-embedded-configurator.js +13 -11
  293. package/dist/phoenix/application-spec/application-spec-builder.js +1 -1
  294. package/dist/phoenix/application-spec/generate-application-spec-story.js +2 -2
  295. package/dist/phoenix/application-spec/project-files.js +1 -1
  296. package/dist/phoenix/bin.d.ts +2 -0
  297. package/dist/phoenix/bin.js +2 -0
  298. package/dist/phoenix/check-configs/built-in-eslint-config.d.ts +9 -0
  299. package/dist/phoenix/check-configs/built-in-eslint-config.js +1 -0
  300. package/dist/phoenix/check-configs/eslint-config.d.ts +10 -0
  301. package/dist/phoenix/check-configs/eslint-config.js +1 -0
  302. package/dist/phoenix/check-configs/index.d.ts +8 -0
  303. package/dist/phoenix/check-configs/index.js +1 -0
  304. package/dist/phoenix/check-configs/typescript-project.d.ts +5 -0
  305. package/dist/phoenix/check-configs/typescript-project.js +1 -0
  306. package/dist/phoenix/cli.d.ts +0 -1
  307. package/dist/phoenix/cli.js +1 -2
  308. package/dist/phoenix/commands/check.js +1 -1
  309. package/dist/phoenix/commands/deps/deps.d.ts +52 -0
  310. package/dist/phoenix/commands/deps/deps.js +3 -0
  311. package/dist/phoenix/commands/deps/index.d.ts +1 -0
  312. package/dist/phoenix/commands/deps/index.js +1 -0
  313. package/dist/phoenix/commands/deps/sdk-manifest.d.ts +12 -0
  314. package/dist/phoenix/commands/deps/sdk-manifest.js +1 -0
  315. package/dist/phoenix/commands/dev.js +5 -5
  316. package/dist/phoenix/commands/fix.js +1 -1
  317. package/dist/phoenix/commands/index.d.ts +1 -0
  318. package/dist/phoenix/commands/index.js +1 -1
  319. package/dist/phoenix/commands/prettier.js +1 -1
  320. package/dist/phoenix/services/application-spec-project-watcher.d.ts +2 -0
  321. package/dist/phoenix/services/application-spec-project-watcher.js +3 -3
  322. package/dist/phoenix/services/lingui.d.ts +8 -0
  323. package/dist/phoenix/services/lingui.js +1 -1
  324. package/dist/phoenix/services/swc.js +1 -1
  325. package/dist/phoenix/services/vite-config.js +1 -1
  326. package/dist/phoenix/utils/index.d.ts +2 -1
  327. package/dist/phoenix/utils/index.js +1 -1
  328. package/dist/phoenix/utils/node-version/index.d.ts +1 -0
  329. package/dist/phoenix/utils/node-version/index.js +1 -0
  330. package/dist/phoenix/utils/node-version/supported-node-version.d.ts +12 -0
  331. package/dist/phoenix/utils/node-version/supported-node-version.js +4 -0
  332. package/dist/phoenix/utils/run-command.d.ts +11 -0
  333. package/dist/phoenix/utils/run-command.js +1 -1
  334. package/dist/phoenix/utils/sdk-tool/index.d.ts +1 -0
  335. package/dist/phoenix/utils/sdk-tool/index.js +1 -0
  336. package/dist/phoenix/utils/sdk-tool/resolve-sdk-tool-bin.d.ts +15 -0
  337. package/dist/phoenix/utils/sdk-tool/resolve-sdk-tool-bin.js +1 -0
  338. package/dist/react-sdk/domain-context/index.d.ts +1 -1
  339. package/dist/react-sdk/domain-context/index.js +1 -1
  340. package/dist/react-sdk/domain-context/system-hooks/navigation-hooks.d.ts +5 -0
  341. package/dist/react-sdk/domain-context/system-hooks/navigation-hooks.js +1 -1
  342. package/dist/ui-sdk/theme/types.d.ts +1 -1
  343. package/package.json +46 -35
  344. package/schema/domain-spec.json +86 -8
  345. package/dist/application-spec/generate-application/code/templates/webhook-implementation.d.ts +0 -1
  346. package/dist/application-spec/generate-application/code/templates/webhook-implementation.js +0 -7
  347. package/dist/configurator/ui/assistant/entity-link/entity-link-target.d.ts +0 -5
  348. package/dist/configurator/ui/assistant/entity-link/entity-link-target.js +0 -1
@@ -55,6 +55,38 @@ export interface paths {
55
55
  readonly patch?: never
56
56
  readonly trace?: never
57
57
  }
58
+ readonly '/auth/callback': {
59
+ readonly parameters: {
60
+ readonly query?: never
61
+ readonly header?: never
62
+ readonly path?: never
63
+ readonly cookie?: never
64
+ }
65
+ readonly get: operations['completeBrowserLogin']
66
+ readonly put?: never
67
+ readonly post?: never
68
+ readonly delete?: never
69
+ readonly options?: never
70
+ readonly head?: never
71
+ readonly patch?: never
72
+ readonly trace?: never
73
+ }
74
+ readonly '/auth/config': {
75
+ readonly parameters: {
76
+ readonly query?: never
77
+ readonly header?: never
78
+ readonly path?: never
79
+ readonly cookie?: never
80
+ }
81
+ readonly get: operations['getBrowserAuthConfig']
82
+ readonly put?: never
83
+ readonly post?: never
84
+ readonly delete?: never
85
+ readonly options?: never
86
+ readonly head?: never
87
+ readonly patch?: never
88
+ readonly trace?: never
89
+ }
58
90
  readonly '/auth/identity': {
59
91
  readonly parameters: {
60
92
  readonly query?: never
@@ -72,6 +104,39 @@ export interface paths {
72
104
  readonly patch?: never
73
105
  readonly trace?: never
74
106
  }
107
+ readonly '/auth/login': {
108
+ readonly parameters: {
109
+ readonly query?: never
110
+ readonly header?: never
111
+ readonly path?: never
112
+ readonly cookie?: never
113
+ }
114
+ readonly get: operations['startBrowserLogin']
115
+ readonly put?: never
116
+ readonly post?: never
117
+ readonly delete?: never
118
+ readonly options?: never
119
+ readonly head?: never
120
+ readonly patch?: never
121
+ readonly trace?: never
122
+ }
123
+ readonly '/auth/logout': {
124
+ readonly parameters: {
125
+ readonly query?: never
126
+ readonly header?: never
127
+ readonly path?: never
128
+ readonly cookie?: never
129
+ }
130
+ readonly get?: never
131
+ readonly put?: never
132
+ /** @description Destroy the local session and return the fixed Cognito hosted logout URL. Requires the exact shared Studio Origin. */
133
+ readonly post: operations['endBrowserSession']
134
+ readonly delete?: never
135
+ readonly options?: never
136
+ readonly head?: never
137
+ readonly patch?: never
138
+ readonly trace?: never
139
+ }
75
140
  readonly '/auth/me': {
76
141
  readonly parameters: {
77
142
  readonly query?: never
@@ -89,6 +154,23 @@ export interface paths {
89
154
  readonly patch?: never
90
155
  readonly trace?: never
91
156
  }
157
+ readonly '/auth/session': {
158
+ readonly parameters: {
159
+ readonly query?: never
160
+ readonly header?: never
161
+ readonly path?: never
162
+ readonly cookie?: never
163
+ }
164
+ /** @description Read the opaque browser session and current account status/memberships. Requires the exact shared Studio Origin. */
165
+ readonly get: operations['getBrowserSession']
166
+ readonly put?: never
167
+ readonly post?: never
168
+ readonly delete?: never
169
+ readonly options?: never
170
+ readonly head?: never
171
+ readonly patch?: never
172
+ readonly trace?: never
173
+ }
92
174
  readonly '/auth/token': {
93
175
  readonly parameters: {
94
176
  readonly query?: never
@@ -1620,6 +1702,114 @@ export interface operations {
1620
1702
  }
1621
1703
  }
1622
1704
  }
1705
+ readonly completeBrowserLogin: {
1706
+ readonly parameters: {
1707
+ readonly query: {
1708
+ readonly code: string
1709
+ readonly state: string
1710
+ }
1711
+ readonly header?: never
1712
+ readonly path?: never
1713
+ readonly cookie?: never
1714
+ }
1715
+ readonly requestBody?: never
1716
+ readonly responses: {
1717
+ /** @description Redirect to the configured sign-in or Studio destination. */
1718
+ readonly 302: {
1719
+ headers: {
1720
+ readonly [name: string]: unknown
1721
+ }
1722
+ content: {
1723
+ readonly 'application/json': Record<string, unknown>
1724
+ }
1725
+ }
1726
+ /** @description Bad Request! */
1727
+ readonly 400: {
1728
+ headers: {
1729
+ readonly [name: string]: unknown
1730
+ }
1731
+ content: {
1732
+ readonly 'application/json': components['schemas']['BadRequestError']
1733
+ }
1734
+ }
1735
+ /** @description Unauthorized! */
1736
+ readonly 401: {
1737
+ headers: {
1738
+ readonly [name: string]: unknown
1739
+ }
1740
+ content: {
1741
+ readonly 'application/json': components['schemas']['UnauthorizedError']
1742
+ }
1743
+ }
1744
+ /** @description Forbidden! */
1745
+ readonly 403: {
1746
+ headers: {
1747
+ readonly [name: string]: unknown
1748
+ }
1749
+ content: {
1750
+ readonly 'application/json': components['schemas']['ForbiddenError']
1751
+ }
1752
+ }
1753
+ /** @description Not Found! */
1754
+ readonly 404: {
1755
+ headers: {
1756
+ readonly [name: string]: unknown
1757
+ }
1758
+ content: {
1759
+ readonly 'application/json': components['schemas']['NotFoundError']
1760
+ }
1761
+ }
1762
+ /** @description Service Unavailable! */
1763
+ readonly 503: {
1764
+ headers: {
1765
+ readonly [name: string]: unknown
1766
+ }
1767
+ content: {
1768
+ readonly 'application/json': components['schemas']['ServiceUnavailableError']
1769
+ }
1770
+ }
1771
+ /** @description An unexpected error occurred! */
1772
+ readonly default: {
1773
+ headers: {
1774
+ readonly [name: string]: unknown
1775
+ }
1776
+ content: {
1777
+ readonly 'application/json': components['schemas']['DefaultResponse']
1778
+ }
1779
+ }
1780
+ }
1781
+ }
1782
+ readonly getBrowserAuthConfig: {
1783
+ readonly parameters: {
1784
+ readonly query?: never
1785
+ readonly header?: never
1786
+ readonly path?: never
1787
+ readonly cookie?: never
1788
+ }
1789
+ readonly requestBody?: never
1790
+ readonly responses: {
1791
+ /** @description Shared Studio origin when browser sign-in is configured; null otherwise. */
1792
+ readonly 200: {
1793
+ headers: {
1794
+ readonly [name: string]: unknown
1795
+ }
1796
+ content: {
1797
+ readonly 'application/json': {
1798
+ readonly studioOrigin: string | null
1799
+ }
1800
+ }
1801
+ }
1802
+ /** @description An unexpected error occurred! */
1803
+ readonly default: {
1804
+ headers: {
1805
+ readonly [name: string]: unknown
1806
+ }
1807
+ content: {
1808
+ readonly 'application/json': components['schemas']['DefaultResponse']
1809
+ }
1810
+ }
1811
+ }
1812
+ }
1623
1813
  readonly resolveIdentity: {
1624
1814
  readonly parameters: {
1625
1815
  readonly query?: never
@@ -1699,6 +1889,112 @@ export interface operations {
1699
1889
  }
1700
1890
  }
1701
1891
  }
1892
+ readonly startBrowserLogin: {
1893
+ readonly parameters: {
1894
+ readonly query?: never
1895
+ readonly header?: never
1896
+ readonly path?: never
1897
+ readonly cookie?: never
1898
+ }
1899
+ readonly requestBody?: never
1900
+ readonly responses: {
1901
+ /** @description Redirect to the configured sign-in or Studio destination. */
1902
+ readonly 302: {
1903
+ headers: {
1904
+ readonly [name: string]: unknown
1905
+ }
1906
+ content: {
1907
+ readonly 'application/json': Record<string, unknown>
1908
+ }
1909
+ }
1910
+ /** @description Bad Request! */
1911
+ readonly 400: {
1912
+ headers: {
1913
+ readonly [name: string]: unknown
1914
+ }
1915
+ content: {
1916
+ readonly 'application/json': components['schemas']['BadRequestError']
1917
+ }
1918
+ }
1919
+ /** @description Not Found! */
1920
+ readonly 404: {
1921
+ headers: {
1922
+ readonly [name: string]: unknown
1923
+ }
1924
+ content: {
1925
+ readonly 'application/json': components['schemas']['NotFoundError']
1926
+ }
1927
+ }
1928
+ /** @description An unexpected error occurred! */
1929
+ readonly default: {
1930
+ headers: {
1931
+ readonly [name: string]: unknown
1932
+ }
1933
+ content: {
1934
+ readonly 'application/json': components['schemas']['DefaultResponse']
1935
+ }
1936
+ }
1937
+ }
1938
+ }
1939
+ readonly endBrowserSession: {
1940
+ readonly parameters: {
1941
+ readonly query?: never
1942
+ readonly header?: never
1943
+ readonly path?: never
1944
+ readonly cookie?: never
1945
+ }
1946
+ readonly requestBody?: never
1947
+ readonly responses: {
1948
+ /** @description Navigate to this URL to finish hosted logout. */
1949
+ readonly 200: {
1950
+ headers: {
1951
+ readonly [name: string]: unknown
1952
+ }
1953
+ content: {
1954
+ readonly 'application/json': {
1955
+ /** Format: uri */
1956
+ readonly logoutUrl: string
1957
+ }
1958
+ }
1959
+ }
1960
+ /** @description Bad Request! */
1961
+ readonly 400: {
1962
+ headers: {
1963
+ readonly [name: string]: unknown
1964
+ }
1965
+ content: {
1966
+ readonly 'application/json': components['schemas']['BadRequestError']
1967
+ }
1968
+ }
1969
+ /** @description Forbidden! */
1970
+ readonly 403: {
1971
+ headers: {
1972
+ readonly [name: string]: unknown
1973
+ }
1974
+ content: {
1975
+ readonly 'application/json': components['schemas']['ForbiddenError']
1976
+ }
1977
+ }
1978
+ /** @description Not Found! */
1979
+ readonly 404: {
1980
+ headers: {
1981
+ readonly [name: string]: unknown
1982
+ }
1983
+ content: {
1984
+ readonly 'application/json': components['schemas']['NotFoundError']
1985
+ }
1986
+ }
1987
+ /** @description An unexpected error occurred! */
1988
+ readonly default: {
1989
+ headers: {
1990
+ readonly [name: string]: unknown
1991
+ }
1992
+ content: {
1993
+ readonly 'application/json': components['schemas']['DefaultResponse']
1994
+ }
1995
+ }
1996
+ }
1997
+ }
1702
1998
  readonly getApiSession: {
1703
1999
  readonly parameters: {
1704
2000
  readonly query?: never
@@ -1748,6 +2044,77 @@ export interface operations {
1748
2044
  }
1749
2045
  }
1750
2046
  }
2047
+ readonly getBrowserSession: {
2048
+ readonly parameters: {
2049
+ readonly query?: never
2050
+ readonly header?: never
2051
+ readonly path?: never
2052
+ readonly cookie?: never
2053
+ }
2054
+ readonly requestBody?: never
2055
+ readonly responses: {
2056
+ /** @description Current account and fixed session expiry, in Unix milliseconds. */
2057
+ readonly 200: {
2058
+ headers: {
2059
+ readonly [name: string]: unknown
2060
+ }
2061
+ content: {
2062
+ readonly 'application/json': {
2063
+ readonly expiresAt: number
2064
+ /** Format: uuid */
2065
+ readonly userId: string
2066
+ readonly workspaces: readonly {
2067
+ /** Format: uuid */
2068
+ readonly customerId: string
2069
+ readonly name: string
2070
+ /** @enum {string} */
2071
+ readonly role: 'user' | 'admin' | 'superadmin'
2072
+ readonly slug: string
2073
+ readonly tags: readonly string[]
2074
+ /** @enum {string} */
2075
+ readonly type: 'standard' | 'sdk_builder'
2076
+ }[]
2077
+ }
2078
+ }
2079
+ }
2080
+ /** @description Unauthorized! */
2081
+ readonly 401: {
2082
+ headers: {
2083
+ readonly [name: string]: unknown
2084
+ }
2085
+ content: {
2086
+ readonly 'application/json': components['schemas']['UnauthorizedError']
2087
+ }
2088
+ }
2089
+ /** @description Forbidden! */
2090
+ readonly 403: {
2091
+ headers: {
2092
+ readonly [name: string]: unknown
2093
+ }
2094
+ content: {
2095
+ readonly 'application/json': components['schemas']['ForbiddenError']
2096
+ }
2097
+ }
2098
+ /** @description Not Found! */
2099
+ readonly 404: {
2100
+ headers: {
2101
+ readonly [name: string]: unknown
2102
+ }
2103
+ content: {
2104
+ readonly 'application/json': components['schemas']['NotFoundError']
2105
+ }
2106
+ }
2107
+ /** @description An unexpected error occurred! */
2108
+ readonly default: {
2109
+ headers: {
2110
+ readonly [name: string]: unknown
2111
+ }
2112
+ content: {
2113
+ readonly 'application/json': components['schemas']['DefaultResponse']
2114
+ }
2115
+ }
2116
+ }
2117
+ }
1751
2118
  readonly exchangeAuthCode: {
1752
2119
  readonly parameters: {
1753
2120
  readonly query?: never
@@ -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 { DomainContextSelectors, DomainServicesSelectors, InitializableSystem, SessionAssistantSetup, SpecSelectors } from '#package/domain';
5
+ import type { AssistantManifest, DomainContextSelectors, DomainServicesSelectors, InitializableSystem, SessionAssistantSetup, SpecSelectors } 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;
@@ -127,11 +127,31 @@ export declare class AssistantSystem implements InitializableSystem {
127
127
  private readonly _recorder;
128
128
  /** The recorder's subscription to the committed emissions of the store; made by the first `initialize()`. */
129
129
  private _recording;
130
+ /**
131
+ * The tool call of every `apply` by the state it committed or held, for as long as the state
132
+ * lives: an undone state that the undo history dropped is forgotten with it.
133
+ *
134
+ * Accepted: a commit the project's `registerIsUndoable` keeps out of the history never becomes a
135
+ * step, so the row of its `apply` never offers Undo.
136
+ */
137
+ private readonly _applyToolCallIds;
138
+ private readonly _undoTipToolCallId;
130
139
  constructor(_context: AssistantSystemContext);
131
140
  /** The conversation. It never completes, and holds the empty chat whenever no chat is active. */
132
141
  readonly chat$: ObservableWithLastValue<AssistantChatSnapshot>;
133
142
  /** The state of the built-in panel. It never completes. */
134
143
  readonly panel$: ObservableWithLastValue<AssistantPanelSnapshot>;
144
+ /**
145
+ * The `apply` tool call whose committed state is the step of the undo history the configuration is
146
+ * at; nothing when that step is not a change of the assistant. It never completes.
147
+ */
148
+ readonly undoTipToolCallId$: ObservableWithLastValue<string | undefined>;
149
+ /**
150
+ * The manifest the initialized session runs, narrowed by the project's setup handler: what the
151
+ * agent can read, so the panel reads recipes and options the way the agent does. `null` while the
152
+ * assistant is off for the session or its setup failed.
153
+ */
154
+ getSessionManifest: () => AssistantManifest | null;
135
155
  /**
136
156
  * A new configuration load: the chat of the previous one is deactivated and both observables go
137
157
  * back to their empty values. An activation that is still held outlives it and gets the chat of
@@ -227,6 +247,15 @@ export declare class AssistantSystem implements InitializableSystem {
227
247
  * server is therefore gone from the thread and has to be written again.
228
248
  */
229
249
  reloadThread: () => void;
250
+ /**
251
+ * Undoes the changes of the given `apply` tool calls, one undo step at a time, while the step the
252
+ * configuration is at is one of them. A change the user made in between stops it, so it is never
253
+ * taken back; the non-undoable commits made on top of an undone change go with it, as with the
254
+ * toolbar's undo.
255
+ *
256
+ * Accepted: like the toolbar's undo, it does not check the session mode; only `apply` requires `owner`.
257
+ */
258
+ undoToolCalls: (toolCallIds: ReadonlySet<string>) => void;
230
259
  setOpen: (open: boolean) => void;
231
260
  setInputFocused: (isInputFocused: boolean) => void;
232
261
  /**
@@ -237,6 +266,12 @@ export declare class AssistantSystem implements InitializableSystem {
237
266
  private _findRefusedMessageIndex;
238
267
  private _sendOn;
239
268
  private _resume;
269
+ /**
270
+ * The `apply` call whose committed state is the step the configuration is at. Nothing at the bottom
271
+ * of the history, where nothing can be undone: that step was not made by a change it could take back.
272
+ */
273
+ private _findTipToolCallId;
274
+ private _refreshUndoTip;
240
275
  private _committedState;
241
276
  private _patchPanel;
242
277
  /**
@@ -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{AssistantRequestError as r}from"#package/client";import{createBrowserDetailsClientTool as n}from"./browser-details.js";import{ChangeRecorder as h}from"./change-recorder.js";import{createApplyClientTool as o,createQueryClientTool as l}from"./graphql-tools.js";let c=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}),d=Object.freeze({open:!1,hasUnreadReply:!1,isInputFocused:!1}),u=Object.freeze({}),_=Object.freeze({results:Object.freeze([]),committed:!1,sideEffects:Object.freeze([]),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."}),g=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(c);_panel=new i(d);_activation=null;_current=null;_finishing=new Set;_olderThreadId=null;_resuming=null;_refused=null;_firstAttempt=null;_chain={};_loadingThreadId=null;_recorder;_recording=null;constructor(e){this._context=e;let{configuratorExtensionSelectors:t,domainContextSelectors:i,domainServicesSelectors:s,getAssistantSetup:a}=e;this._recorder=new h({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??u,resolveLocalizable:e=>s.getResolveLocalizable()(e)});let r={getGraphQLSystem:()=>t.getGraphQLSystem(),getStoreSystem:()=>i.getStoreSystem(),getActiveMode:()=>i.getActiveMode(),clearChanges:()=>this._recorder.clear(this._committedState())};this._tools=[n(),l(r),o(r)]}chat$=this._chat;panel$=this._panel;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(d),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=>{if(!this._chat.value.isContinuable&&!await this.resume())return;let t=this._current;if(!t)return;let i={changes:this._recorder.take(this._committedState())};this._firstAttempt=t;try{await this._sendOn(t,e,i);let s=this._findRefusedMessageIndex(t);if(-1===s)return;this._refused={chat:t,index:s}}finally{this._firstAttempt===t&&(this._firstAttempt=null)}if(!await this.resume())return;let s=this._current;s&&await this._sendOn(s,e,i)};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};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()};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};_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({...c,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 r&&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 r?t.status:void 0}),this._context.domainServicesSelectors.getLogger().error("The assistant thread could not be resumed",{},t),!1}};_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)},h=e=>{if(!i.active)return;let t={...this._chat.value,...e};a(t,this._chat.value)||this._chat.next(t)},o=async(e,t)=>{let s=await fetch(e,t).finally(()=>h({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")),h({failedStatus:s.ok?void 0:s.status,...null!=a&&{isContinuable:"false"!==a,hasEarlierThread:null!==this._olderThreadId}}),s},l=async()=>({headers:await n().headers(),fetchClient:o}),c=t(()=>n().url,l),d=t(()=>`${n().url}/runs`,l),u=this._tools.map(e=>({...e,execute:(t,s)=>{if(!i.active)return _;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)}})),f=new e({threadId:`assistant:${s}`,connection:{...c,joinRun:d.joinRun},persistence:!0,history:{pageSize:50},tools:u,onMessagesChange:e=>h({messages:e}),onLoadingChange:e=>{let t=i.active&&this._chat.value.isLoading;h({isLoading:e}),!e&&g(f)&&(i.active?t&&!this._panel.value.open&&this._patchPanel({hasUnreadReply:!0}):v())},onErrorChange:e=>{i.active&&e!==this._chat.value.error&&(!e||-1===this._findRefusedMessageIndex(p))&&(h({error:e}),e&&this._context.domainServicesSelectors.getLogger().error("The assistant request failed",{status:this._chat.value.failedStatus},e))}}),m=!1,v=()=>{m||(m=!0,this._finishing.delete(p),f.dispose())},p={client:f,configurationId:s,generation:i,authorizedClient:r,getConnection:n,dispose:v};this._current=p,f.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!==c&&this._chat.next(c),e};_endChat=()=>{let e=this._retireChat();if(e){if(!e.client.getIsLoading()&&g(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 i}from"rxjs";import{skip as s}from"rxjs/operators";import{isShallowEqual as a}from"@salsita-ai/common/utils";import{AssistantRequestError as r}from"#package/client";import{createBrowserDetailsClientTool as n}from"./browser-details.js";import{ChangeRecorder as o}from"./change-recorder.js";import{createApplyClientTool as l,createQueryClientTool as h}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([]),hasEarlierThread:!1,isLoadingEarlierThread:!1}),c=Object.freeze({open:!1,hasUnreadReply:!1,isInputFocused:!1}),u=Object.freeze({}),_=Object.freeze({results:Object.freeze([]),committed:!1,sideEffects:Object.freeze([]),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."}),g=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(d);_panel=new i(c);_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);constructor(e){this._context=e;let{configuratorExtensionSelectors:t,domainContextSelectors:i,domainServicesSelectors:s,getAssistantSetup:a}=e;this._recorder=new o({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??u,resolveLocalizable:e=>s.getResolveLocalizable()(e)});let r={getGraphQLSystem:()=>t.getGraphQLSystem(),getStoreSystem:()=>i.getStoreSystem(),getActiveMode:()=>i.getActiveMode(),clearChanges:()=>this._recorder.clear(this._committedState()),rememberCommit:(e,t)=>{this._applyToolCallIds.set(t,e),this._refreshUndoTip()}};this._tools=[n(),h(r),l(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(c),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=>{if(!this._chat.value.isContinuable&&!await this.resume())return;let t=this._current;if(!t)return;let i={changes:this._recorder.take(this._committedState())};this._firstAttempt=t;try{await this._sendOn(t,e,i);let s=this._findRefusedMessageIndex(t);if(-1===s)return;this._refused={chat:t,index:s}}finally{this._firstAttempt===t&&(this._firstAttempt=null)}if(!await this.resume())return;let s=this._current;s&&await this._sendOn(s,e,i)};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};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};_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({...d,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 r&&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 r?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}),d=t(()=>n().url,h),c=t(()=>`${n().url}/runs`,h),u=this._tools.map(e=>({...e,execute:(t,s)=>{if(!i.active)return _;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)}})),f=new e({threadId:`assistant:${s}`,connection:{...d,joinRun:c.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&&g(f)&&(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))}}),m=!1,p=()=>{m||(m=!0,this._finishing.delete(v),f.dispose())},v={client:f,configurationId:s,generation:i,authorizedClient:r,getConnection:n,dispose:p};this._current=v,f.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!==d&&this._chat.next(d),e};_endChat=()=>{let e=this._retireChat();if(e){if(!e.client.getIsLoading()&&g(e.client))return void e.dispose();this._finishing.add(e)}}}
@@ -20,6 +20,11 @@ export interface AssistantToolDependencies {
20
20
  readonly getActiveMode: () => DomainMode;
21
21
  /** Forgets the changes recorded for the next change record, so it never lists what the agent itself changed. */
22
22
  readonly clearChanges: () => void;
23
+ /**
24
+ * Remembers the state an `apply` call committed or held for the user's approval, so the panel can
25
+ * tell while that state is the step of the undo history the configuration is at.
26
+ */
27
+ readonly rememberCommit: (toolCallId: string, state: DomainState<DomainEntity<string>>) => void;
23
28
  }
24
29
  /**
25
30
  * Browser implementation of the assistant's `query` tool: prepares the operations from the
@@ -93,7 +98,8 @@ export declare const createQueryClientTool: (dependencies: AssistantToolDependen
93
98
  * `GraphQLSystem.execute`, which commits their changes as one undo step, and returns its result,
94
99
  * including why nothing was committed when a commit was held or lost to a conflict. A commit clears
95
100
  * the recorded changes; a held one does not, so it shows in the next change record once the user
96
- * approves it. Only an owner
101
+ * approves it. The state it committed or held is remembered under the id of the call, so the chip
102
+ * row of the call can undo it. Only an owner
97
103
  * session may change the configuration; the check lives here and not in the `GraphQLSystem`, whose
98
104
  * other caller, the editor panel, has its own rules.
99
105
  */
@@ -1 +1 @@
1
- import{AssistantGraphQLToolInput as e,applyTool as t,queryTool as o}from"@salsita-ai/contracts/assistant";let a=e=>({results:[],committed:!1,message:e,sideEffects:[]}),i=e=>JSON.parse(JSON.stringify(e)),s=t=>{let o=e.safeParse(t);if(!o.success){let e=o.error.issues.map(e=>`${e.path.join(".")}: ${e.message}`).join("; ");return{ok:!1,refusal:a(`Nothing was run, because the tool input is not a list of operations (${e}). Send { "operations": [{ "query": "<one GraphQL operation>" }] } with at least one item.`)}}return{ok:!0,operations:o.data.operations.map(({query:e,variables:t,operationName:o})=>({document:e,variables:t??void 0,operationName:o??void 0}))}};export const createQueryClientTool=e=>o.client(async t=>{let o=s(t);if(!o.ok)return o.refusal;let n=e.getStoreSystem();if(!n.isInitialized)return a("Nothing was run, because the configuration is not loaded yet, so there is no state to query. Call the tool again once the configurator has finished loading.");let r=e.getGraphQLSystem(),l=await r.prepare(n.stateSlices.committed.value.state,o.operations);return i({results:l.map(({result:e})=>e),committed:!1,sideEffects:r.readSideEffects(l)})});export const createApplyClientTool=e=>t.client(async t=>{if("owner"!==e.getActiveMode())return a("Nothing was run, because changes cannot be applied in this session: the user may view this configuration but not change it. The query tool still works here, including mutations, to show what a change would do without keeping it.");let o=s(t);if(!o.ok)return o.refusal;let n=await e.getGraphQLSystem().execute(o.operations);return n.committed&&e.clearChanges(),i(n)});
1
+ import{AssistantGraphQLToolInput as e,applyTool as t,queryTool as o}from"@salsita-ai/contracts/assistant";let a=e=>({results:[],committed:!1,message:e,sideEffects:[]}),i=({preparedState:e,...t})=>JSON.parse(JSON.stringify(t)),s=t=>{let o=e.safeParse(t);if(!o.success){let e=o.error.issues.map(e=>`${e.path.join(".")}: ${e.message}`).join("; ");return{ok:!1,refusal:a(`Nothing was run, because the tool input is not a list of operations (${e}). Send { "operations": [{ "query": "<one GraphQL operation>" }] } with at least one item.`)}}return{ok:!0,operations:o.data.operations.map(({query:e,variables:t,operationName:o})=>({document:e,variables:t??void 0,operationName:o??void 0}))}};export const createQueryClientTool=e=>o.client(async t=>{let o=s(t);if(!o.ok)return o.refusal;let r=e.getStoreSystem();if(!r.isInitialized)return a("Nothing was run, because the configuration is not loaded yet, so there is no state to query. Call the tool again once the configurator has finished loading.");let n=e.getGraphQLSystem(),l=await n.prepare(r.stateSlices.committed.value.state,o.operations);return i({results:l.map(({result:e})=>e),committed:!1,sideEffects:n.readSideEffects(l)})});export const createApplyClientTool=e=>t.client(async(t,o)=>{if("owner"!==e.getActiveMode())return a("Nothing was run, because changes cannot be applied in this session: the user may view this configuration but not change it. The query tool still works here, including mutations, to show what a change would do without keeping it.");let r=s(t);if(!r.ok)return r.refusal;let n=await e.getGraphQLSystem().execute(r.operations),l=o?.toolCallId;return void 0!==l&&void 0!==n.preparedState&&e.rememberCommit(l,n.preparedState),n.committed&&e.clearChanges(),i(n)});
@@ -39,6 +39,12 @@ export interface GraphQLExecution {
39
39
  readonly message?: string;
40
40
  /** What the configurator did, or would do, beyond what the operations asked for, in applied order. */
41
41
  readonly sideEffects: readonly string[];
42
+ /**
43
+ * The state the operations prepared, when it was committed or held for the user's approval; a
44
+ * held state is the one committed if the user approves. A caller can recognize its own change in
45
+ * the undo history by it. It stays in the browser: nothing that leaves it may carry the state.
46
+ */
47
+ readonly preparedState?: AnyDomainState;
42
48
  }
43
49
  /**
44
50
  * Resolves a localizable value, or each item of a list of them, to a string in the current locale.
@@ -1 +1 @@
1
- import{GraphQLError as e,NoSchemaIntrospectionCustomRule as t,defaultFieldResolver as i,execute as o,getNamedType as n,parse as r,specifiedRules as a,validate as s,validateSchema as l}from"graphql";import{assertExistence as c,createSelector as d,isMessageDescriptor as h,isMultilingualString as u}from"@salsita-ai/common/utils";import{DomainEntityIdSchema as m,createAssistantExecutionSchema as f,findAssistantMutation as p}from"#package/domain";import{createEntityMeta as g}from"./entity-meta.js";import{injectAssistantLenses as y}from"./inject-assistant-lenses.js";import{readSideEffects as v}from"./side-effects.js";let S={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.")]},_={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.")]},x=new RegExp(m.pattern),w=[...a,t],E=e=>"object"==typeof e&&null!==e&&"type"in e&&"string"==typeof e.type&&"id"in e&&"string"==typeof e.id,$=(e,t)=>"object"==typeof e&&null!==e?Reflect.get(e,t):void 0,b=e=>e instanceof Error?e.message:String(e),T=e=>/[.!?]$/.test(e)?e:`${e}.`,C=e=>"object"==typeof e&&null!==e&&Object.getPrototypeOf(e)===Object.prototype,R=(e,t)=>{let i=C(e)?e._raw:void 0;if(E(i))return i;if(!Array.isArray(e)&&!C(e))return e;if(t.has(e))throw Error("The value contains itself.");let o=new Set([...t,e]);return Array.isArray(e)?e.map(e=>R(e,o)):Object.fromEntries(Object.entries(e).map(([e,t])=>[e,R(t,o)]))};export const localize=(e,t)=>Array.isArray(e)?e.map(e=>localize(e,t)):"string"==typeof e||h(e)||u(e)?t(e):e;let j=t=>new e(`The configurator cannot handle this request: ${T(t)} This is a fault in the configurator, not in your request. Tell the user this is not available.`),A=e=>(e.errors?.length??0)>0,M=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=d([d.leaf(e=>e)],e=>{try{let t=f(e),i=l(t);return i.length>0?j(i.map(e=>e.message).join(" ")):t}catch(e){return j(b(e))}});_selectLenses=d([d.leaf(e=>e)],e=>r(e));_selectFieldResolver=d([d.leaf(e=>e)],t=>(o,r,a,s)=>{if(s.parentType===s.schema.getQueryType())return i(o,r,a,s);if(s.parentType===s.schema.getMutationType())return this._resolveMutation(s.fieldName,String(s.path.key),r,a);if(!E(o))return i(o,r,a,s);if("meta"===s.fieldName){let e;return g({entity:o,state:("object"==typeof(e=$(o,"_state"))&&null!==e&&"entities"in e&&"rootEntityId"in e?e:void 0)??a.state},{manifest:a.manifest,recipes:this._recipeContext(),prepareStateEmission:(e,t,i)=>this._context.domainContextSelectors.getStoreSystem().prepareStateEmission(e,t,i),find$Entity:(e,t)=>this._find$Entity(e,t),validateEntity:e=>this._context.domainContextSelectors.getDomain().validateEntity(e)})}let{source:l,localized:c}=t[s.parentType.name]?.[s.fieldName]??{source:s.fieldName},d=((t,i)=>{try{return $(t,i)}catch(o){throw new e(`Expression "${i}" failed on ${E(t)?t.id:"an entity"}: ${T(b(o))} This is a fault in the configurator, not in your request. Tell the user this is not available.`,{originalError:o instanceof Error?o:void 0})}})(o,l);return c?localize(d,this._context.domainServicesSelectors.getResolveLocalizable()):l.startsWith("$")&&"JSON"===n(s.returnType).name?((t,i,o)=>{try{return R(o,new Set)}catch(o){throw new e(`Expression "${i}" returned a value that is not plain serializable data on ${E(t)?t.id:"an entity"}: ${T(b(o))} This is a fault in the configurator, not in your request. Tell the user this is not available.`,{originalError:o instanceof Error?o:void 0})}})(o,l,d):d});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;_recipeContext=()=>({componentReader:this._context.domainContextSelectors.getComponentReader(),recipeCooker:this._context.domainContextSelectors.getRecipeCookerSystem(),resolveLocalizable:this._context.domainServicesSelectors.getResolveLocalizable()});_rootValue={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 o=i.rootEntityId;let n=t.filter(e=>!x.test(e));if(n.length>0)throw new e(`${n.map(e=>`"${e}"`).join(", ")} ${1===n.length?"is not an entity id":"are not entity ids"}. Entity ids have the form "<Type>-<number>", e.g. "${o}". Use ids as returned by the "id" field.`);return t.map(e=>x.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=>E(e)?e.type:void 0;initialize=()=>{};_resolveMutation=(t,i,o,n)=>{if(void 0!==n.failedMutationField)throw new e(`Not run: the earlier field "${n.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,o,n)}catch(e){throw n.failedMutationField=i,e}};_runMutation=(t,i,o)=>{let n=p(t,o.manifest);if(!n)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=o.state,a=n.implementation(i,r,{manifest:o.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");if(!i.validity.valid)throw new e(`The changes of "${t}" were not applied, because the resulting configuration is invalid: ${(e=>{if("uncaught"===e.severity)return`validating it threw: ${T(b(e.error))}`;let t=[...new Set(e.entityViolations.filter(({violation:t})=>t.severity===e.severity).map(({entityId:e})=>e))];return`it has ${e.severity} violations on ${t.join(", ")}.`})(i.validity)} Change the request so the configuration stays valid.`);o.emissions.push(i),o.state=i.state}return a.readResult({previousState:r,state:o.state})};_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:S};let o=this._selectSchema(t.sdl);return o instanceof e?{ready:!1,result:{errors:[o]}}:{ready:!0,assistant:t,schema:o,lenses:t.lenses?.definitions?this._selectLenses(t.lenses.definitions):void 0,fieldResolver:this._selectFieldResolver(t.fields)}};_run=(t,i,n,a)=>{let l;try{l=r(t)}catch(t){return{errors:[t instanceof e?t:new e(b(t))]}}let c=s(n.schema,l,w);return c.length>0?{errors:c}:o({schema:n.schema,document:l,rootValue:this._rootValue,contextValue:a,variableValues:i.variables,operationName:i.operationName,fieldResolver:n.fieldResolver,typeResolver:this._resolveType})};prepare=async(t,i)=>{let o,n=this._setup();if(!n.ready)return i.map(()=>({result:n.result,emissions:[]}));let r={manifest:n.assistant,state:t,emissions:[],failedMutationField:void 0},a=[];for(let[t,s]of i.entries())if(void 0===o){let i=r.emissions.length;r.failedMutationField=void 0;let l=n.lenses?y(s.document,n.lenses):s.document,c=l instanceof e?{errors:[l]}:await this._run(l,s,n,r);a.push({result:c,emissions:r.emissions.slice(i)}),A(c)&&(o=t)}else a.push({result:M(o),emissions:[]});return a};readSideEffects=e=>{let t=this._context.domainServicesSelectors.getResolveLocalizable();return e.flatMap(({emissions:e})=>e.flatMap(e=>v(e.updates,t)))};_prepareAndCommit=async e=>{let t,i,o,n=this._context.domainContextSelectors.getStoreSystem(),r=await this.prepare(n.stateSlices.committed.value.state,e),a=r.map(({result:e})=>e),s=this.readSideEffects(r),l=r.flatMap(e=>e.emissions);return a.some(A)||0===l.length?{results:a,sideEffects:s,outcome:"none"}:{results:a,sideEffects:s,outcome:n.commitPrepared((t=c(l[0]),i=c(l[l.length-1]),o=l.some(e=>void 0!==e.transformationLog),{kind:"committed",previousState:t.previousState,state:i.state,updates:l.flatMap(e=>e.updates),validity:i.validity,transformationLog:o?l.flatMap(e=>e.transformationLog??[]):void 0}))}};execute=async e=>{if(!this._context.domainContextSelectors.getStoreSystem().isInitialized)return{results:e.map(()=>_),committed:!1,sideEffects:[]};let t=await this._prepareAndCommit(e),{results:i,sideEffects:o,outcome:n}="conflict"===t.outcome?await this._prepareAndCommit(e):t;return"committed"===n?{results:i,committed:!0,sideEffects:o}:"held"===n?{results:i,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}:"conflict"===n?{results:i,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}:{results:i,committed:!1,sideEffects:o}}}
1
+ import{GraphQLError as e,NoSchemaIntrospectionCustomRule as t,defaultFieldResolver as i,execute as o,getNamedType as n,parse as r,specifiedRules as a,validate as s,validateSchema as l}from"graphql";import{assertExistence as c,createSelector as d,isMessageDescriptor as h,isMultilingualString as u}from"@salsita-ai/common/utils";import{DomainEntityIdSchema as m,createAssistantExecutionSchema as f,findAssistantMutation as p}from"#package/domain";import{createEntityMeta as g}from"./entity-meta.js";import{injectAssistantLenses as y}from"./inject-assistant-lenses.js";import{readSideEffects as v}from"./side-effects.js";let S={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.")]},_={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.")]},x=new RegExp(m.pattern),w=[...a,t],E=e=>"object"==typeof e&&null!==e&&"type"in e&&"string"==typeof e.type&&"id"in e&&"string"==typeof e.id,$=(e,t)=>"object"==typeof e&&null!==e?Reflect.get(e,t):void 0,b=e=>e instanceof Error?e.message:String(e),T=e=>/[.!?]$/.test(e)?e:`${e}.`,C=e=>"object"==typeof e&&null!==e&&Object.getPrototypeOf(e)===Object.prototype,R=(e,t)=>{let i=C(e)?e._raw:void 0;if(E(i))return i;if(!Array.isArray(e)&&!C(e))return e;if(t.has(e))throw Error("The value contains itself.");let o=new Set([...t,e]);return Array.isArray(e)?e.map(e=>R(e,o)):Object.fromEntries(Object.entries(e).map(([e,t])=>[e,R(t,o)]))};export const localize=(e,t)=>Array.isArray(e)?e.map(e=>localize(e,t)):"string"==typeof e||h(e)||u(e)?t(e):e;let j=t=>new e(`The configurator cannot handle this request: ${T(t)} This is a fault in the configurator, not in your request. Tell the user this is not available.`),A=e=>(e.errors?.length??0)>0,M=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=d([d.leaf(e=>e)],e=>{try{let t=f(e),i=l(t);return i.length>0?j(i.map(e=>e.message).join(" ")):t}catch(e){return j(b(e))}});_selectLenses=d([d.leaf(e=>e)],e=>r(e));_selectFieldResolver=d([d.leaf(e=>e)],t=>(o,r,a,s)=>{if(s.parentType===s.schema.getQueryType())return i(o,r,a,s);if(s.parentType===s.schema.getMutationType())return this._resolveMutation(s.fieldName,String(s.path.key),r,a);if(!E(o))return i(o,r,a,s);if("meta"===s.fieldName){let e;return g({entity:o,state:("object"==typeof(e=$(o,"_state"))&&null!==e&&"entities"in e&&"rootEntityId"in e?e:void 0)??a.state},{manifest:a.manifest,recipes:this._recipeContext(),prepareStateEmission:(e,t,i)=>this._context.domainContextSelectors.getStoreSystem().prepareStateEmission(e,t,i),find$Entity:(e,t)=>this._find$Entity(e,t),validateEntity:e=>this._context.domainContextSelectors.getDomain().validateEntity(e)})}let{source:l,localized:c}=t[s.parentType.name]?.[s.fieldName]??{source:s.fieldName},d=((t,i)=>{try{return $(t,i)}catch(o){throw new e(`Expression "${i}" failed on ${E(t)?t.id:"an entity"}: ${T(b(o))} This is a fault in the configurator, not in your request. Tell the user this is not available.`,{originalError:o instanceof Error?o:void 0})}})(o,l);return c?localize(d,this._context.domainServicesSelectors.getResolveLocalizable()):l.startsWith("$")&&"JSON"===n(s.returnType).name?((t,i,o)=>{try{return R(o,new Set)}catch(o){throw new e(`Expression "${i}" returned a value that is not plain serializable data on ${E(t)?t.id:"an entity"}: ${T(b(o))} This is a fault in the configurator, not in your request. Tell the user this is not available.`,{originalError:o instanceof Error?o:void 0})}})(o,l,d):d});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;_recipeContext=()=>({componentReader:this._context.domainContextSelectors.getComponentReader(),recipeCooker:this._context.domainContextSelectors.getRecipeCookerSystem(),resolveLocalizable:this._context.domainServicesSelectors.getResolveLocalizable()});_rootValue={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 o=i.rootEntityId;let n=t.filter(e=>!x.test(e));if(n.length>0)throw new e(`${n.map(e=>`"${e}"`).join(", ")} ${1===n.length?"is not an entity id":"are not entity ids"}. Entity ids have the form "<Type>-<number>", e.g. "${o}". Use ids as returned by the "id" field.`);return t.map(e=>x.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=>E(e)?e.type:void 0;initialize=()=>{};_resolveMutation=(t,i,o,n)=>{if(void 0!==n.failedMutationField)throw new e(`Not run: the earlier field "${n.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,o,n)}catch(e){throw n.failedMutationField=i,e}};_runMutation=(t,i,o)=>{let n=p(t,o.manifest);if(!n)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=o.state,a=n.implementation(i,r,{manifest:o.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");if(!i.validity.valid)throw new e(`The changes of "${t}" were not applied, because the resulting configuration is invalid: ${(e=>{if("uncaught"===e.severity)return`validating it threw: ${T(b(e.error))}`;let t=[...new Set(e.entityViolations.filter(({violation:t})=>t.severity===e.severity).map(({entityId:e})=>e))];return`it has ${e.severity} violations on ${t.join(", ")}.`})(i.validity)} Change the request so the configuration stays valid.`);o.emissions.push(i),o.state=i.state}return a.readResult({previousState:r,state:o.state})};_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:S};let o=this._selectSchema(t.sdl);return o instanceof e?{ready:!1,result:{errors:[o]}}:{ready:!0,assistant:t,schema:o,lenses:t.lenses?.definitions?this._selectLenses(t.lenses.definitions):void 0,fieldResolver:this._selectFieldResolver(t.fields)}};_run=(t,i,n,a)=>{let l;try{l=r(t)}catch(t){return{errors:[t instanceof e?t:new e(b(t))]}}let c=s(n.schema,l,w);return c.length>0?{errors:c}:o({schema:n.schema,document:l,rootValue:this._rootValue,contextValue:a,variableValues:i.variables,operationName:i.operationName,fieldResolver:n.fieldResolver,typeResolver:this._resolveType})};prepare=async(t,i)=>{let o,n=this._setup();if(!n.ready)return i.map(()=>({result:n.result,emissions:[]}));let r={manifest:n.assistant,state:t,emissions:[],failedMutationField:void 0},a=[];for(let[t,s]of i.entries())if(void 0===o){let i=r.emissions.length;r.failedMutationField=void 0;let l=n.lenses?y(s.document,n.lenses):s.document,c=l instanceof e?{errors:[l]}:await this._run(l,s,n,r);a.push({result:c,emissions:r.emissions.slice(i)}),A(c)&&(o=t)}else a.push({result:M(o),emissions:[]});return a};readSideEffects=e=>{let t=this._context.domainServicesSelectors.getResolveLocalizable();return e.flatMap(({emissions:e})=>e.flatMap(e=>v(e.updates,t)))};_prepareAndCommit=async e=>{let t,i,o,n=this._context.domainContextSelectors.getStoreSystem(),r=await this.prepare(n.stateSlices.committed.value.state,e),a=r.map(({result:e})=>e),s=this.readSideEffects(r),l=r.flatMap(e=>e.emissions);if(a.some(A)||0===l.length)return{results:a,sideEffects:s,outcome:"none"};let d=(t=c(l[0]),i=c(l[l.length-1]),o=l.some(e=>void 0!==e.transformationLog),{kind:"committed",previousState:t.previousState,state:i.state,updates:l.flatMap(e=>e.updates),validity:i.validity,transformationLog:o?l.flatMap(e=>e.transformationLog??[]):void 0});return{results:a,sideEffects:s,outcome:n.commitPrepared(d),preparedState:d.state}};execute=async e=>{if(!this._context.domainContextSelectors.getStoreSystem().isInitialized)return{results:e.map(()=>_),committed:!1,sideEffects:[]};let t=await this._prepareAndCommit(e),{results:i,sideEffects:o,outcome:n,preparedState:r}="conflict"===t.outcome?await this._prepareAndCommit(e):t;return"committed"===n?{results:i,committed:!0,sideEffects:o,preparedState:r}:"held"===n?{results:i,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,preparedState:r}:"conflict"===n?{results:i,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}:{results:i,committed:!1,sideEffects:o}}}