@aglyn/plugins-ai 1.0.0-beta.229 → 1.0.0-beta.231

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 (340) hide show
  1. package/README.md +3 -3
  2. package/package.json +17 -17
  3. package/src/lib/activity/ai-activity-actions.js +7 -1
  4. package/src/lib/activity/ai-activity-actions.js.map +1 -1
  5. package/src/lib/components/ai-assist-provider-on-host.component.d.ts +66 -0
  6. package/src/lib/components/ai-assist-provider-on-host.component.js +78 -0
  7. package/src/lib/components/ai-assist-provider-on-host.component.js.map +1 -0
  8. package/src/lib/components/ai-assist-provider.component.js +9 -10
  9. package/src/lib/components/ai-assist-provider.component.js.map +1 -1
  10. package/src/lib/components/ai-automation-zones.d.ts +38 -0
  11. package/src/lib/components/ai-automation-zones.js +5 -1
  12. package/src/lib/components/ai-automation-zones.js.map +1 -1
  13. package/src/lib/components/ai-brief-dialog.component.d.ts +20 -2
  14. package/src/lib/components/ai-brief-dialog.component.js +87 -8
  15. package/src/lib/components/ai-brief-dialog.component.js.map +1 -1
  16. package/src/lib/components/ai-campaign-create.component.d.ts +54 -0
  17. package/src/lib/components/ai-campaign-create.component.js +270 -0
  18. package/src/lib/components/ai-campaign-create.component.js.map +1 -0
  19. package/src/lib/components/ai-describe-automation.component.d.ts +8 -3
  20. package/src/lib/components/ai-describe-automation.component.js +15 -6
  21. package/src/lib/components/ai-describe-automation.component.js.map +1 -1
  22. package/src/lib/components/ai-describe-button.component.d.ts +20 -8
  23. package/src/lib/components/ai-describe-button.component.js +19 -36
  24. package/src/lib/components/ai-describe-button.component.js.map +1 -1
  25. package/src/lib/components/ai-describe-email.component.d.ts +31 -0
  26. package/src/lib/components/ai-describe-email.component.js +22 -0
  27. package/src/lib/components/ai-describe-email.component.js.map +1 -0
  28. package/src/lib/components/ai-describe-org-automation.component.d.ts +36 -0
  29. package/src/lib/components/ai-describe-org-automation.component.js +238 -0
  30. package/src/lib/components/ai-describe-org-automation.component.js.map +1 -0
  31. package/src/lib/components/ai-experiment-cards.component.d.ts +9 -1
  32. package/src/lib/components/ai-experiment-cards.component.js +104 -18
  33. package/src/lib/components/ai-experiment-cards.component.js.map +1 -1
  34. package/src/lib/components/ai-explain-automation.component.js +1 -5
  35. package/src/lib/components/ai-explain-automation.component.js.map +1 -1
  36. package/src/lib/components/ai-funnel-zones.component.d.ts +61 -0
  37. package/src/lib/components/ai-funnel-zones.component.js +178 -0
  38. package/src/lib/components/ai-funnel-zones.component.js.map +1 -0
  39. package/src/lib/components/ai-insight-card.component.d.ts +42 -0
  40. package/src/lib/components/ai-insight-card.component.js +137 -0
  41. package/src/lib/components/ai-insight-card.component.js.map +1 -0
  42. package/src/lib/components/ai-insight-dialog.component.d.ts +6 -0
  43. package/src/lib/components/ai-insight-dialog.component.js +9 -3
  44. package/src/lib/components/ai-insight-dialog.component.js.map +1 -1
  45. package/src/lib/components/ai-job-plan.component.d.ts +7 -2
  46. package/src/lib/components/ai-job-plan.component.js +38 -6
  47. package/src/lib/components/ai-job-plan.component.js.map +1 -1
  48. package/src/lib/components/ai-job-requests.d.ts +17 -1
  49. package/src/lib/components/ai-job-requests.js +39 -3
  50. package/src/lib/components/ai-job-requests.js.map +1 -1
  51. package/src/lib/components/ai-logic-zones.d.ts +64 -0
  52. package/src/lib/components/ai-logic-zones.js +18 -0
  53. package/src/lib/components/ai-logic-zones.js.map +1 -0
  54. package/src/lib/components/ai-logic.component.d.ts +77 -0
  55. package/src/lib/components/ai-logic.component.js +553 -0
  56. package/src/lib/components/ai-logic.component.js.map +1 -0
  57. package/src/lib/components/ai-marketing-insight.component.d.ts +30 -0
  58. package/src/lib/components/ai-marketing-insight.component.js +80 -0
  59. package/src/lib/components/ai-marketing-insight.component.js.map +1 -0
  60. package/src/lib/components/ai-media-create.component.d.ts +55 -0
  61. package/src/lib/components/ai-media-create.component.js +433 -0
  62. package/src/lib/components/ai-media-create.component.js.map +1 -0
  63. package/src/lib/components/ai-overlay-cards.component.d.ts +83 -0
  64. package/src/lib/components/ai-overlay-cards.component.js +505 -0
  65. package/src/lib/components/ai-overlay-cards.component.js.map +1 -0
  66. package/src/lib/components/ai-permissions-on-host.component.d.ts +3 -46
  67. package/src/lib/components/ai-permissions-on-host.component.js +5 -53
  68. package/src/lib/components/ai-permissions-on-host.component.js.map +1 -1
  69. package/src/lib/components/ai-product-zones.d.ts +5 -0
  70. package/src/lib/components/ai-product-zones.js +1 -1
  71. package/src/lib/components/ai-product-zones.js.map +1 -1
  72. package/src/lib/components/ai-products-create-button.component.d.ts +42 -0
  73. package/src/lib/components/ai-products-create-button.component.js +67 -0
  74. package/src/lib/components/ai-products-create-button.component.js.map +1 -0
  75. package/src/lib/components/ai-products-hub-card.component.js +100 -81
  76. package/src/lib/components/ai-products-hub-card.component.js.map +1 -1
  77. package/src/lib/components/ai-revise-automation.component.d.ts +16 -0
  78. package/src/lib/components/ai-revise-automation.component.js +207 -0
  79. package/src/lib/components/ai-revise-automation.component.js.map +1 -0
  80. package/src/lib/components/ai-site-build-page.component.js +160 -24
  81. package/src/lib/components/ai-site-build-page.component.js.map +1 -1
  82. package/src/lib/components/ai-upsell-dialog.component.d.ts +53 -0
  83. package/src/lib/components/ai-upsell-dialog.component.js +177 -0
  84. package/src/lib/components/ai-upsell-dialog.component.js.map +1 -0
  85. package/src/lib/components/assist-build-card.component.d.ts +42 -0
  86. package/src/lib/components/assist-build-card.component.js +183 -0
  87. package/src/lib/components/assist-build-card.component.js.map +1 -0
  88. package/src/lib/components/assist-edit-canvas.d.ts +2 -0
  89. package/src/lib/components/assist-edit-canvas.js +56 -1
  90. package/src/lib/components/assist-edit-canvas.js.map +1 -1
  91. package/src/lib/components/assist-jobs-drawer.component.js +48 -3
  92. package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
  93. package/src/lib/components/assist-panel.component.js +51 -2
  94. package/src/lib/components/assist-panel.component.js.map +1 -1
  95. package/src/lib/components/use-ai-job-run.d.ts +3 -14
  96. package/src/lib/components/use-ai-job-run.js +0 -50
  97. package/src/lib/components/use-ai-job-run.js.map +1 -1
  98. package/src/lib/jobs/ai-build-capabilities.d.ts +58 -0
  99. package/src/lib/jobs/ai-build-capabilities.js +256 -0
  100. package/src/lib/jobs/ai-build-capabilities.js.map +1 -0
  101. package/src/lib/jobs/ai-build-unit-outcome.d.ts +52 -0
  102. package/src/lib/jobs/ai-build-unit-outcome.js +140 -0
  103. package/src/lib/jobs/ai-build-unit-outcome.js.map +1 -0
  104. package/src/lib/jobs/ai-job-auto-confirm.d.ts +8 -0
  105. package/src/lib/jobs/ai-job-auto-confirm.js +30 -6
  106. package/src/lib/jobs/ai-job-auto-confirm.js.map +1 -1
  107. package/src/lib/jobs/ai-job-build-step.d.ts +144 -0
  108. package/src/lib/jobs/ai-job-build-step.js +668 -0
  109. package/src/lib/jobs/ai-job-build-step.js.map +1 -0
  110. package/src/lib/jobs/ai-job-draft-ids.js +9 -1
  111. package/src/lib/jobs/ai-job-draft-ids.js.map +1 -1
  112. package/src/lib/jobs/ai-job-drafts.d.ts +14 -4
  113. package/src/lib/jobs/ai-job-drafts.js +25 -4
  114. package/src/lib/jobs/ai-job-drafts.js.map +1 -1
  115. package/src/lib/jobs/ai-job-generation.d.ts +8 -0
  116. package/src/lib/jobs/ai-job-generation.js +13 -2
  117. package/src/lib/jobs/ai-job-generation.js.map +1 -1
  118. package/src/lib/jobs/ai-job-insight-step.js +8 -1
  119. package/src/lib/jobs/ai-job-insight-step.js.map +1 -1
  120. package/src/lib/jobs/ai-job-layout-language.d.ts +73 -0
  121. package/src/lib/jobs/ai-job-layout-language.js +194 -0
  122. package/src/lib/jobs/ai-job-layout-language.js.map +1 -0
  123. package/src/lib/jobs/ai-job-layout-site-pages.d.ts +13 -2
  124. package/src/lib/jobs/ai-job-layout-site-pages.js +18 -2
  125. package/src/lib/jobs/ai-job-layout-site-pages.js.map +1 -1
  126. package/src/lib/jobs/ai-job-layout-step.d.ts +5 -0
  127. package/src/lib/jobs/ai-job-layout-step.js +105 -5
  128. package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
  129. package/src/lib/jobs/ai-job-logic-step.d.ts +107 -0
  130. package/src/lib/jobs/ai-job-logic-step.js +395 -0
  131. package/src/lib/jobs/ai-job-logic-step.js.map +1 -0
  132. package/src/lib/jobs/ai-job-overlay-copy.d.ts +70 -0
  133. package/src/lib/jobs/ai-job-overlay-copy.js +178 -0
  134. package/src/lib/jobs/ai-job-overlay-copy.js.map +1 -0
  135. package/src/lib/jobs/ai-job-page-language.d.ts +149 -0
  136. package/src/lib/jobs/ai-job-page-language.js +355 -0
  137. package/src/lib/jobs/ai-job-page-language.js.map +1 -0
  138. package/src/lib/jobs/ai-job-page-sections.d.ts +37 -1
  139. package/src/lib/jobs/ai-job-page-sections.js +93 -11
  140. package/src/lib/jobs/ai-job-page-sections.js.map +1 -1
  141. package/src/lib/jobs/ai-job-page-step.d.ts +4 -4
  142. package/src/lib/jobs/ai-job-page-step.js +111 -20
  143. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  144. package/src/lib/jobs/ai-job-plan-step.d.ts +27 -2
  145. package/src/lib/jobs/ai-job-plan-step.js +87 -13
  146. package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
  147. package/src/lib/jobs/ai-job-site-step.d.ts +19 -1
  148. package/src/lib/jobs/ai-job-site-step.js +220 -61
  149. package/src/lib/jobs/ai-job-site-step.js.map +1 -1
  150. package/src/lib/jobs/ai-job-text-step.d.ts +22 -1
  151. package/src/lib/jobs/ai-job-text-step.js +12 -0
  152. package/src/lib/jobs/ai-job-text-step.js.map +1 -1
  153. package/src/lib/jobs/ai-job-workflow-step.d.ts +54 -4
  154. package/src/lib/jobs/ai-job-workflow-step.js +320 -15
  155. package/src/lib/jobs/ai-job-workflow-step.js.map +1 -1
  156. package/src/lib/jobs/ai-jobs.d.ts +80 -2
  157. package/src/lib/jobs/ai-jobs.js +391 -18
  158. package/src/lib/jobs/ai-jobs.js.map +1 -1
  159. package/src/lib/jobs/ai-layout-full-height.d.ts +40 -0
  160. package/src/lib/jobs/ai-layout-full-height.js +82 -0
  161. package/src/lib/jobs/ai-layout-full-height.js.map +1 -0
  162. package/src/lib/jobs/ai-layout-site-facts.d.ts +54 -0
  163. package/src/lib/jobs/ai-layout-site-facts.js +153 -0
  164. package/src/lib/jobs/ai-layout-site-facts.js.map +1 -0
  165. package/src/lib/jobs/ai-logic-records.d.ts +40 -0
  166. package/src/lib/jobs/ai-logic-records.js +55 -0
  167. package/src/lib/jobs/ai-logic-records.js.map +1 -0
  168. package/src/lib/jobs/ai-site-publish.d.ts +7 -0
  169. package/src/lib/jobs/ai-site-publish.js +9 -0
  170. package/src/lib/jobs/ai-site-publish.js.map +1 -1
  171. package/src/lib/jobs/ai-workflow-records.d.ts +4 -0
  172. package/src/lib/jobs/ai-workflow-records.js +40 -1
  173. package/src/lib/jobs/ai-workflow-records.js.map +1 -1
  174. package/src/lib/layout-language/ai-layout-compiler.d.ts +145 -0
  175. package/src/lib/layout-language/ai-layout-compiler.js +1148 -0
  176. package/src/lib/layout-language/ai-layout-compiler.js.map +1 -0
  177. package/src/lib/layout-language/ai-layout-copy.d.ts +73 -0
  178. package/src/lib/layout-language/ai-layout-copy.js +137 -0
  179. package/src/lib/layout-language/ai-layout-copy.js.map +1 -0
  180. package/src/lib/layout-language/ai-layout-frame.d.ts +52 -0
  181. package/src/lib/layout-language/ai-layout-frame.js +457 -0
  182. package/src/lib/layout-language/ai-layout-frame.js.map +1 -0
  183. package/src/lib/layout-language/ai-layout-gaps.d.ts +63 -0
  184. package/src/lib/layout-language/ai-layout-gaps.js +345 -0
  185. package/src/lib/layout-language/ai-layout-gaps.js.map +1 -0
  186. package/src/lib/layout-language/ai-layout-language.d.ts +161 -0
  187. package/src/lib/layout-language/ai-layout-language.js +446 -0
  188. package/src/lib/layout-language/ai-layout-language.js.map +1 -0
  189. package/src/lib/layout-language/ai-layout-links.d.ts +80 -0
  190. package/src/lib/layout-language/ai-layout-links.js +109 -0
  191. package/src/lib/layout-language/ai-layout-links.js.map +1 -0
  192. package/src/lib/layout-language/ai-layout-store.d.ts +39 -0
  193. package/src/lib/layout-language/ai-layout-store.js +69 -0
  194. package/src/lib/layout-language/ai-layout-store.js.map +1 -0
  195. package/src/lib/layout-language/ai-layout-tree.d.ts +59 -0
  196. package/src/lib/layout-language/ai-layout-tree.js +84 -0
  197. package/src/lib/layout-language/ai-layout-tree.js.map +1 -0
  198. package/src/lib/lazy-widget.d.ts +45 -0
  199. package/src/lib/lazy-widget.js +53 -0
  200. package/src/lib/lazy-widget.js.map +1 -0
  201. package/src/lib/model/ai-automation-draft.d.ts +18 -0
  202. package/src/lib/model/ai-automation-draft.js +86 -0
  203. package/src/lib/model/ai-automation-draft.js.map +1 -1
  204. package/src/lib/model/ai-build-job.d.ts +201 -0
  205. package/src/lib/model/ai-build-job.js +472 -0
  206. package/src/lib/model/ai-build-job.js.map +1 -0
  207. package/src/lib/model/ai-build-plan.d.ts +61 -0
  208. package/src/lib/model/ai-build-plan.js +154 -9
  209. package/src/lib/model/ai-build-plan.js.map +1 -1
  210. package/src/lib/model/ai-build-progress.d.ts +73 -0
  211. package/src/lib/model/ai-build-progress.js +170 -0
  212. package/src/lib/model/ai-build-progress.js.map +1 -0
  213. package/src/lib/model/ai-host-publish-context.d.ts +51 -0
  214. package/src/lib/model/ai-host-publish-context.js +104 -0
  215. package/src/lib/model/ai-host-publish-context.js.map +1 -0
  216. package/src/lib/model/ai-insight.d.ts +20 -10
  217. package/src/lib/model/ai-insight.js +72 -9
  218. package/src/lib/model/ai-insight.js.map +1 -1
  219. package/src/lib/model/ai-job-activity.d.ts +22 -0
  220. package/src/lib/model/ai-job-activity.js +25 -2
  221. package/src/lib/model/ai-job-activity.js.map +1 -1
  222. package/src/lib/model/ai-job-failure-copy.d.ts +38 -1
  223. package/src/lib/model/ai-job-failure-copy.js +56 -1
  224. package/src/lib/model/ai-job-failure-copy.js.map +1 -1
  225. package/src/lib/model/ai-job-notice.d.ts +3 -1
  226. package/src/lib/model/ai-job-notice.js +31 -9
  227. package/src/lib/model/ai-job-notice.js.map +1 -1
  228. package/src/lib/model/ai-jobs.types.d.ts +99 -2
  229. package/src/lib/model/ai-jobs.types.js +3 -1
  230. package/src/lib/model/ai-jobs.types.js.map +1 -1
  231. package/src/lib/model/ai-logic-job.d.ts +108 -0
  232. package/src/lib/model/ai-logic-job.js +327 -0
  233. package/src/lib/model/ai-logic-job.js.map +1 -0
  234. package/src/lib/model/ai-media-credits.d.ts +52 -0
  235. package/src/lib/model/ai-media-credits.js +61 -0
  236. package/src/lib/model/ai-media-credits.js.map +1 -0
  237. package/src/lib/model/ai-overlay-copy.d.ts +114 -0
  238. package/src/lib/model/ai-overlay-copy.js +175 -0
  239. package/src/lib/model/ai-overlay-copy.js.map +1 -0
  240. package/src/lib/model/ai-site-build-progress.d.ts +25 -4
  241. package/src/lib/model/ai-site-build-progress.js +194 -11
  242. package/src/lib/model/ai-site-build-progress.js.map +1 -1
  243. package/src/lib/model/ai-site-job.d.ts +8 -0
  244. package/src/lib/model/ai-site-job.js +9 -0
  245. package/src/lib/model/ai-site-job.js.map +1 -1
  246. package/src/lib/model/ai-site-start-seo.d.ts +1 -1
  247. package/src/lib/model/ai-site-start.d.ts +5 -2
  248. package/src/lib/model/ai-site-start.js +5 -2
  249. package/src/lib/model/ai-site-start.js.map +1 -1
  250. package/src/lib/model/ai-svg.d.ts +69 -0
  251. package/src/lib/model/ai-svg.js +265 -0
  252. package/src/lib/model/ai-svg.js.map +1 -0
  253. package/src/lib/model/ai-usage-by-user.d.ts +3 -2
  254. package/src/lib/model/ai-usage-by-user.js.map +1 -1
  255. package/src/lib/model/ai-workflow-job.d.ts +92 -4
  256. package/src/lib/model/ai-workflow-job.js +124 -7
  257. package/src/lib/model/ai-workflow-job.js.map +1 -1
  258. package/src/lib/model/assist-build.d.ts +58 -0
  259. package/src/lib/model/assist-build.js +52 -0
  260. package/src/lib/model/assist-build.js.map +1 -0
  261. package/src/lib/model/assist-edit.d.ts +48 -3
  262. package/src/lib/model/assist-edit.js +48 -4
  263. package/src/lib/model/assist-edit.js.map +1 -1
  264. package/src/lib/plugin-config.js +2 -0
  265. package/src/lib/plugin-config.js.map +1 -1
  266. package/src/lib/plugin.js +308 -47
  267. package/src/lib/plugin.js.map +1 -1
  268. package/src/lib/providers/catalog.d.ts +82 -5
  269. package/src/lib/providers/catalog.js +83 -12
  270. package/src/lib/providers/catalog.js.map +1 -1
  271. package/src/lib/providers/image-contract.d.ts +116 -0
  272. package/src/lib/providers/image-contract.js +74 -0
  273. package/src/lib/providers/image-contract.js.map +1 -0
  274. package/src/lib/providers/model-choice.js +11 -0
  275. package/src/lib/providers/model-choice.js.map +1 -1
  276. package/src/lib/providers/routing.js +18 -0
  277. package/src/lib/providers/routing.js.map +1 -1
  278. package/src/lib/providers/vertex-image.d.ts +121 -0
  279. package/src/lib/providers/vertex-image.js +312 -0
  280. package/src/lib/providers/vertex-image.js.map +1 -0
  281. package/src/lib/runtime/ai-doctrine-validators.d.ts +101 -0
  282. package/src/lib/runtime/ai-doctrine-validators.js +525 -4
  283. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
  284. package/src/lib/runtime/ai-doctrine.js +21 -6
  285. package/src/lib/runtime/ai-doctrine.js.map +1 -1
  286. package/src/lib/runtime/ai-eval-live.js +4 -0
  287. package/src/lib/runtime/ai-eval-live.js.map +1 -1
  288. package/src/lib/runtime/ai-eval.d.ts +15 -1
  289. package/src/lib/runtime/ai-eval.js +52 -1
  290. package/src/lib/runtime/ai-eval.js.map +1 -1
  291. package/src/lib/runtime/ai-icon-library.d.ts +257 -0
  292. package/src/lib/runtime/ai-icon-library.js +254 -0
  293. package/src/lib/runtime/ai-icon-library.js.map +1 -0
  294. package/src/lib/runtime/ai-node-tree.d.ts +9 -0
  295. package/src/lib/runtime/ai-node-tree.js +30 -4
  296. package/src/lib/runtime/ai-node-tree.js.map +1 -1
  297. package/src/lib/runtime/ai-palette.d.ts +6 -0
  298. package/src/lib/runtime/ai-palette.generated.js +70 -0
  299. package/src/lib/runtime/ai-palette.generated.js.map +1 -1
  300. package/src/lib/runtime/ai-palette.js.map +1 -1
  301. package/src/lib/runtime/experiment-variant-copy.d.ts +34 -0
  302. package/src/lib/runtime/experiment-variant-copy.js +102 -0
  303. package/src/lib/runtime/experiment-variant-copy.js.map +1 -0
  304. package/src/lib/server/ai-experiment-versions.d.ts +51 -0
  305. package/src/lib/server/ai-experiment-versions.js +270 -0
  306. package/src/lib/server/ai-experiment-versions.js.map +1 -0
  307. package/src/lib/server/ai-jobs-resume.js +74 -4
  308. package/src/lib/server/ai-jobs-resume.js.map +1 -1
  309. package/src/lib/server/ai-media-image.d.ts +66 -0
  310. package/src/lib/server/ai-media-image.js +521 -0
  311. package/src/lib/server/ai-media-image.js.map +1 -0
  312. package/src/lib/server/ai-media-svg.d.ts +91 -0
  313. package/src/lib/server/ai-media-svg.js +186 -0
  314. package/src/lib/server/ai-media-svg.js.map +1 -0
  315. package/src/lib/server/assist-build.d.ts +54 -0
  316. package/src/lib/server/assist-build.js +121 -0
  317. package/src/lib/server/assist-build.js.map +1 -0
  318. package/src/lib/server/assist-chat.js +108 -12
  319. package/src/lib/server/assist-chat.js.map +1 -1
  320. package/src/lib/server/assist-edit.js +213 -3
  321. package/src/lib/server/assist-edit.js.map +1 -1
  322. package/src/lib/server/assist-view-context.js +242 -4
  323. package/src/lib/server/assist-view-context.js.map +1 -1
  324. package/src/lib/server.js +26 -0
  325. package/src/lib/server.js.map +1 -1
  326. package/src/lib/tools/ai-logic-tool.d.ts +27 -0
  327. package/src/lib/tools/ai-logic-tool.js +207 -0
  328. package/src/lib/tools/ai-logic-tool.js.map +1 -0
  329. package/src/lib/tools/ai-overlay-tool.d.ts +35 -0
  330. package/src/lib/tools/ai-overlay-tool.js +107 -0
  331. package/src/lib/tools/ai-overlay-tool.js.map +1 -0
  332. package/src/lib/tools/ai-workflow-tool.d.ts +17 -2
  333. package/src/lib/tools/ai-workflow-tool.js +47 -14
  334. package/src/lib/tools/ai-workflow-tool.js.map +1 -1
  335. package/src/lib/usage/assist-job-refund.d.ts +28 -1
  336. package/src/lib/usage/assist-job-refund.js +44 -9
  337. package/src/lib/usage/assist-job-refund.js.map +1 -1
  338. package/src/lib/usage/assist-usage.d.ts +5 -0
  339. package/src/lib/usage/assist-usage.js +2 -0
  340. package/src/lib/usage/assist-usage.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/assist-edit-canvas.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n screenSeoStageKey,\n type ScreenSeoTextField,\n} from '@aglyn/aglyn/app-utils/screen-seo-fields'\nimport {\n NODE_HIDE_IF_PROP,\n replaceSubtreeWithInstance,\n reusableComponentDefinitionFrom,\n} from '@aglyn/aglyn/app-utils/compose-reusable-components'\nimport { CANVAS_ROOT_ELEMENT_ID } from '@aglyn/aglyn/foundation/constants/canvas'\nimport type {\n ReusableComponentProp,\n ReusableComponentPropValue,\n} from '@aglyn/aglyn/foundation/definitions/platform.types'\nimport {\n stageEditorSessionFields,\n type EditorSession,\n} from '@aglyn/aglyn/plugin-manager/editor-sessions'\nimport {\n ASSIST_EDIT_CONTEXT_MAX_NODES,\n ASSIST_EDIT_CONTEXT_MAX_PROPS,\n ASSIST_EDIT_OUTLINE_TEXT_CHARS,\n ASSIST_EDIT_SELECTED_TEXT_CHARS,\n assistEditOpCounts,\n type AssistEditCanvasContext,\n type AssistEditCanvasNode,\n type AssistEditInsertOp,\n type AssistEditOp,\n type AssistEditProposal,\n type AssistEditComponentProp,\n type AssistEditSaveAsComponentOp,\n} from '../model/assist-edit'\n\n/**\n * The edit rung's client half (AGL-2906): what the panel tells the server\n * about the open canvas, and how a confirmed proposal lands on it.\n *\n * Applying goes through the canvas's own guarded mutators — the same ones\n * the besigner's panels and the marketing appliers use — inside ONE\n * `batch`, so the whole proposal is one undo step and a guard that refuses\n * part-way leaves nothing behind. Every change is an unsaved edit on the\n * version the editor has open; saving it stays the author's act, with the\n * editor's own control. A version the live site serves is never edited:\n * the check refuses it, and the card offers the editor's own new-version\n * flow instead.\n */\n\n/** A node as the canvas holds it — the fields this module reads. */\nexport interface AssistEditCanvasNodeLike {\n $id?: string\n componentId?: string\n parentId?: string | null\n nodes?: string[]\n name?: string\n props?: unknown\n sx?: unknown\n}\n\n/**\n * The slice of the besigner canvas the edit rung reads and drives. Every\n * member is one `CanvasManager` already has, so the panel hands over the\n * canvas itself and a spec hands over a real one.\n */\nexport interface AssistEditCanvas {\n getNode(id: string): AssistEditCanvasNodeLike | undefined\n batch<T>(mutate: () => T): T\n updateNodeProps(node: any, props: any): void\n updateNodeFields(node: any, patch: any): void\n reparentNode(node: any, parent: any, index?: number): unknown\n deleteNode(node: any): unknown\n addNodeFromNested(nested: any, parent: any, index?: number): unknown\n nodeAcceptsChildren(node: any): boolean\n /** The whole document, which a component save reads its definition out of. */\n toJSON(): { nodes: Record<string, unknown> }\n /** The document after a save: the promoted subtree swapped for an instance. */\n applyNodes(nodes: any): unknown\n}\n\nconst UNDESCRIBED_PROP = /^(html|sx|style|className|dangerouslySetInnerHTML|on[A-Z].*)$/\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/**\n * An observable's own keys as a plain object. A canvas node's `props` and\n * `sx` are observable proxies, and a spread of one is how a merge silently\n * copies nothing.\n */\nfunction plain(value: unknown): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n if (!value || typeof value !== 'object') return out\n for (const key in value as Record<string, unknown>) {\n out[key] = (value as Record<string, unknown>)[key]\n }\n return out\n}\n\nfunction describeProps(\n raw: unknown,\n textChars: number,\n): Record<string, string | number | boolean> | undefined {\n const props: Record<string, string | number | boolean> = {}\n let kept = 0\n for (const [name, value] of Object.entries(plain(raw))) {\n if (kept >= ASSIST_EDIT_CONTEXT_MAX_PROPS) break\n if (UNDESCRIBED_PROP.test(name)) continue\n if (typeof value === 'string') {\n if (!value.trim()) continue\n props[name] = value.slice(0, textChars)\n } else if (typeof value === 'number' && Number.isFinite(value)) {\n props[name] = value\n } else if (typeof value === 'boolean') {\n props[name] = value\n } else {\n continue\n }\n kept += 1\n }\n return kept ? props : undefined\n}\n\nfunction describeSx(raw: unknown): Record<string, unknown> | undefined {\n const sx: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(plain(raw))) {\n if (typeof value === 'string' || typeof value === 'number') sx[key] = value\n else if (isRecord(value)) sx[key] = plain(value)\n }\n return Object.keys(sx).length ? sx : undefined\n}\n\n/**\n * The selection's ancestors below the document root, top-level section first\n * and the selection last; null when its parents do not lead to the root,\n * which is not a chain the server can check.\n */\nfunction chainToRoot(\n canvas: Pick<AssistEditCanvas, 'getNode'>,\n selected: AssistEditCanvasNodeLike,\n): string[] | null {\n const chain: string[] = []\n const walked = new Set<string>()\n let current: AssistEditCanvasNodeLike | undefined = selected\n while (current?.$id && current.$id !== CANVAS_ROOT_ELEMENT_ID && !walked.has(current.$id)) {\n walked.add(current.$id)\n chain.unshift(current.$id)\n current = current.parentId ? canvas.getNode(current.parentId) : undefined\n }\n return current?.$id === CANVAS_ROOT_ELEMENT_ID ? chain : null\n}\n\n/** Elements one shape is taken over at most; a larger subtree is never called alike. */\nconst SHAPE_LIMIT = 200\n\n/**\n * How an element is built: its component and, in order, its children's —\n * what two cards of one row have in common whatever their text. Null past\n * `SHAPE_LIMIT` elements, or for a subtree that loops back on itself.\n */\nfunction shapeOf(canvas: Pick<AssistEditCanvas, 'getNode'>, rootId: string): string | null {\n let budget = SHAPE_LIMIT\n const walked = new Set<string>()\n const walk = (id: string): string | null => {\n const node = canvas.getNode(id)\n if (!node || walked.has(id) || --budget < 0) return null\n walked.add(id)\n const parts: string[] = []\n for (const child of node.nodes ?? []) {\n const part = walk(child)\n if (part === null) return null\n parts.push(part)\n }\n return `${String(node.componentId ?? '')}(${parts.join(',')})`\n }\n return walk(rootId)\n}\n\n/** Elements reachable from the document root through child lists, the root included. */\nfunction countElements(canvas: Pick<AssistEditCanvas, 'getNode'>): number {\n let count = 0\n const reached = new Set<string>([CANVAS_ROOT_ELEMENT_ID])\n const pending = [CANVAS_ROOT_ELEMENT_ID]\n while (pending.length) {\n const node = canvas.getNode(pending.pop() as string)\n if (!node) continue\n count += 1\n for (const child of node.nodes ?? []) {\n if (reached.has(child)) continue\n reached.add(child)\n pending.push(child)\n }\n }\n return count\n}\n\n/**\n * The canvas outline a question carries on the edit rung, in two tiers, until\n * the cap.\n *\n * Described in full, settings and all: the document root, the selection's\n * ancestors and the selection, the document's top-level sections, everything\n * inside the selection — what an edit to it changes — and its siblings.\n *\n * Described briefly, by place alone (`brief`): what surrounds that, so the\n * model knows it exists and asks for it rather than calling it missing —\n *\n * 1. what the selection's siblings hold, level by level (the icons beside a\n * selected link, in the card they share);\n * 2. the siblings of each ancestor below the top-level section, nearest\n * first (the other cards of the row, then what sits beside the row).\n *\n * An element built the same way as the selection, or as the ancestor it sits\n * beside, is marked `like` it and its contents are left out: one card\n * described, and every other card of the row says it holds the same.\n *\n * With nothing selected, it is the root, the top-level sections and one level\n * inside each: enough for a change to the page as a whole, and the prompt asks\n * for a selection before anything more specific.\n *\n * An element is only ever described after its parent, so every ancestor chain\n * the server checks is whole. `total` counts the document, and each element's\n * `childCount` stays its real one, so the server can tell the model what the\n * outline leaves out. The server holds this to its own limits before it quotes\n * a byte of it; null when the canvas has no document root loaded.\n */\nexport function describeAssistEditCanvas(\n canvas: Pick<AssistEditCanvas, 'getNode'>,\n selectedId: string | null,\n): AssistEditCanvasContext | null {\n const root = canvas.getNode(CANVAS_ROOT_ELEMENT_ID)\n if (!root) return null\n const order: string[] = []\n const seen = new Set<string>()\n const brief = new Set<string>()\n const like = new Map<string, string>()\n const full = (): boolean => order.length >= ASSIST_EDIT_CONTEXT_MAX_NODES\n const add = (id: string | undefined | null, briefly = false): void => {\n if (!id || seen.has(id) || full()) return\n if (!canvas.getNode(id)) return\n seen.add(id)\n order.push(id)\n if (briefly) brief.add(id)\n }\n const childrenOf = (id: string): string[] => canvas.getNode(id)?.nodes ?? []\n const shapes = new Map<string, string | null>()\n const shape = (id: string): string | null => {\n if (!shapes.has(id)) shapes.set(id, shapeOf(canvas, id))\n return shapes.get(id) ?? null\n }\n // Alike only when there are contents to leave out.\n const alike = (id: string, model: string): boolean =>\n childrenOf(id).length > 0 && shape(id) !== null && shape(id) === shape(model)\n\n add(CANVAS_ROOT_ELEMENT_ID)\n const selected =\n selectedId && selectedId !== CANVAS_ROOT_ELEMENT_ID ? canvas.getNode(selectedId) : undefined\n const chain = selected?.$id ? chainToRoot(canvas, selected) : null\n chain?.forEach((id) => add(id))\n if (selected?.$id && chain && seen.has(selected.$id)) {\n for (const id of root.nodes ?? []) add(id)\n const inside = new Set<string>([selected.$id])\n const queue = [...childrenOf(selected.$id)]\n while (queue.length && !full()) {\n const id = queue.shift() as string\n if (inside.has(id)) continue\n inside.add(id)\n add(id)\n queue.push(...childrenOf(id))\n }\n const siblings = selected.parentId\n ? childrenOf(selected.parentId).filter((id) => id !== selected.$id)\n : []\n const held: string[] = []\n for (const id of siblings) {\n add(id)\n // A sibling the cap left out takes its contents with it.\n if (!seen.has(id)) continue\n if (alike(id, selected.$id)) like.set(id, selected.$id)\n else held.push(...childrenOf(id))\n }\n const reached = new Set<string>([...inside, ...siblings, ...held])\n for (let level = held; level.length && !full(); ) {\n const deeper: string[] = []\n for (const id of level) {\n add(id, true)\n for (const child of childrenOf(id)) {\n if (reached.has(child)) continue\n reached.add(child)\n deeper.push(child)\n }\n }\n level = deeper\n }\n // Parent first; the top-level section's own siblings are the sections above.\n for (const ancestor of chain.slice(1, -1).reverse()) {\n const parentId = canvas.getNode(ancestor)?.parentId\n for (const id of parentId ? childrenOf(parentId) : []) {\n if (id === ancestor || seen.has(id)) continue\n add(id, true)\n if (seen.has(id) && alike(id, ancestor)) like.set(id, ancestor)\n }\n }\n } else {\n for (const id of root.nodes ?? []) add(id)\n for (const section of root.nodes ?? []) {\n for (const id of childrenOf(section)) add(id)\n }\n }\n\n const nodes: AssistEditCanvasNode[] = order.map((id) => {\n const node = canvas.getNode(id) as AssistEditCanvasNodeLike\n const isRoot = id === CANVAS_ROOT_ELEMENT_ID\n const parentId = isRoot ? null : (node.parentId ?? null)\n const parent = parentId ? canvas.getNode(parentId) : undefined\n const isSelected = id === selected?.$id\n const isBrief = brief.has(id)\n const props = isBrief\n ? undefined\n : describeProps(\n node.props,\n isSelected ? ASSIST_EDIT_SELECTED_TEXT_CHARS : ASSIST_EDIT_OUTLINE_TEXT_CHARS,\n )\n const sx = isSelected ? describeSx(node.sx) : undefined\n const model = like.get(id)\n return {\n id,\n componentId: String(node.componentId ?? ''),\n parentId,\n index: Math.max(0, parent?.nodes?.indexOf(id) ?? 0),\n childCount: node.nodes?.length ?? 0,\n ...(node.name ? { name: String(node.name) } : {}),\n ...(props ? { props } : {}),\n ...(sx ? { sx } : {}),\n ...(isBrief ? { brief: true } : {}),\n ...(model ? { like: model } : {}),\n }\n })\n return {\n selectedId: selected?.$id && seen.has(selected.$id) ? selected.$id : null,\n total: countElements(canvas),\n nodes,\n }\n}\n\n/** Why a proposal cannot land on the open editor as it stands. */\nexport type AssistEditRefusal =\n /** No editor is open. */\n | 'no-editor'\n /** The editor open is not the document the proposal was made for. */\n | 'other-document'\n /** The open version is the one the live site serves. */\n | 'live-version'\n /** An element the proposal names has gone or changed since. */\n | 'stale'\n /** The canvas's own guards refused part of the change. */\n | 'refused'\n\nexport type AssistEditCheck =\n | { ok: true }\n | { ok: false; reason: AssistEditRefusal; message: string }\n\nexport type AssistEditApplyResult =\n | {\n ok: true\n /** Applied ops, counted by kind for the activity row. */\n opCounts: Record<string, number>\n /** Editor fields staged, as the editor keys them. */\n staged: string[]\n }\n | { ok: false; reason: AssistEditRefusal; message: string }\n\n/** Ids of the subtree at `rootId`, the root included, through child lists only. */\nfunction subtreeIds(\n canvas: Pick<AssistEditCanvas, 'getNode'>,\n rootId: string,\n): Set<string> {\n const found = new Set<string>([rootId])\n const queue = [...(canvas.getNode(rootId)?.nodes ?? [])]\n while (queue.length) {\n const id = queue.shift() as string\n if (found.has(id) || !canvas.getNode(id)) continue\n found.add(id)\n queue.push(...(canvas.getNode(id)?.nodes ?? []))\n }\n return found\n}\n\nconst STALE: AssistEditCheck = {\n ok: false,\n reason: 'stale',\n message: 'The canvas has changed since this was proposed, so nothing was applied. Ask again.',\n}\n\n/**\n * Whether the proposal can land on the open editor as it stands — checked in\n * full before anything is touched, so a refusal never leaves half an edit.\n */\nexport function checkAssistEdit(\n canvas: Pick<AssistEditCanvas, 'getNode' | 'nodeAcceptsChildren'>,\n proposal: AssistEditProposal,\n session: EditorSession | undefined,\n): AssistEditCheck {\n if (!session) {\n return {\n ok: false,\n reason: 'no-editor',\n message: 'Open the editor this change was proposed for to apply it.',\n }\n }\n if (\n session.documentKind !== proposal.target.kind ||\n session.documentId !== proposal.target.documentId\n ) {\n return {\n ok: false,\n reason: 'other-document',\n message: 'This change was proposed for a different document than the one open.',\n }\n }\n if (session.isLiveVersion()) {\n return {\n ok: false,\n reason: 'live-version',\n message:\n 'This is the version your live site shows. Make a new version first, then apply the change there.',\n }\n }\n for (const op of proposal.ops) {\n switch (op.op) {\n case 'setSeo': {\n for (const field of Object.keys(op.fields) as ScreenSeoTextField[]) {\n if (typeof session.fields?.[screenSeoStageKey(field)] !== 'function') {\n return {\n ok: false,\n reason: 'other-document',\n message: 'This editor has no search fields to fill in.',\n }\n }\n }\n break\n }\n case 'insertSubtree': {\n const parent = canvas.getNode(op.parentId)\n if (!parent || parent.componentId !== op.parentComponentId) return STALE\n if (!canvas.nodeAcceptsChildren(parent)) return STALE\n break\n }\n case 'move': {\n const node = canvas.getNode(op.nodeId)\n const parent = canvas.getNode(op.parentId)\n if (!node || node.componentId !== op.componentId) return STALE\n if (!parent || parent.componentId !== op.parentComponentId) return STALE\n break\n }\n case 'saveAsComponent': {\n const node = canvas.getNode(op.nodeId)\n if (!node || node.componentId !== op.componentId) return STALE\n // The document itself is not a section of itself: promoting the root\n // would leave a document holding one instance of its own contents.\n if (op.nodeId === CANVAS_ROOT_ELEMENT_ID) return STALE\n const inside = subtreeIds(canvas, op.nodeId)\n for (const binding of op.bindings) {\n const bound = canvas.getNode(binding.nodeId)\n if (!bound || bound.componentId !== binding.componentId) return STALE\n // A closed world: a token outside the promoted subtree would bind a\n // property of the new component to an element it does not contain.\n if (!inside.has(binding.nodeId)) return STALE\n }\n break\n }\n default: {\n const node = canvas.getNode(op.nodeId)\n if (!node || node.componentId !== op.componentId) return STALE\n }\n }\n }\n return { ok: true }\n}\n\n/**\n * Styles merged one key at a time. A responsive patch over a plain value\n * keeps that value as the base breakpoint, so \"more padding on wide screens\"\n * does not quietly remove the padding everywhere else.\n */\nfunction mergeSx(\n current: Record<string, unknown>,\n patch: Record<string, unknown>,\n): Record<string, unknown> {\n const out = { ...current }\n for (const [key, value] of Object.entries(patch)) {\n const existing = out[key]\n if (isRecord(value) && isRecord(existing)) {\n out[key] = { ...plain(existing), ...value }\n } else if (isRecord(value) && (typeof existing === 'string' || typeof existing === 'number')) {\n out[key] = { xs: existing, ...value }\n } else {\n out[key] = value\n }\n }\n return out\n}\n\n/** A validated flat subtree as the nested shape `addNodeFromNested` takes. */\nfunction nestSubtree(op: AssistEditInsertOp): Record<string, unknown> {\n const visited = new Set<string>()\n const build = (id: string): Record<string, unknown> => {\n visited.add(id)\n const node = op.nodes[id]\n return {\n componentId: node.componentId,\n ...(node.pluginId ? { pluginId: node.pluginId } : {}),\n props: { ...node.props },\n ...(node.sx ? { sx: { ...node.sx } } : {}),\n ...(node.hidden ? { hidden: true } : {}),\n nodes: node.nodes\n .filter((child) => op.nodes[child] && !visited.has(child))\n .map((child) => build(child)),\n }\n }\n return build(op.rootId)\n}\n\nfunction live(canvas: AssistEditCanvas, id: string): AssistEditCanvasNodeLike {\n const node = canvas.getNode(id)\n if (!node) throw new Error(`element ${id} is no longer on the canvas`)\n return node\n}\n\nfunction applyOne(canvas: AssistEditCanvas, op: AssistEditOp): void {\n switch (op.op) {\n case 'updateProps': {\n const node = live(canvas, op.nodeId)\n // Spread the props the element has: `updateNodeProps` REPLACES the bag,\n // and a patch of one setting would otherwise strip every other one.\n const next: Record<string, unknown> = { ...plain(node.props), ...op.props }\n // Rich text renders `html` over `children`; proposed text replaces it.\n if ('children' in op.props) delete next['html']\n canvas.updateNodeProps(node, next)\n return\n }\n case 'updateSx': {\n const node = live(canvas, op.nodeId)\n canvas.updateNodeFields(node, { sx: mergeSx(plain(node.sx), op.sx) })\n return\n }\n case 'move':\n canvas.reparentNode(live(canvas, op.nodeId), live(canvas, op.parentId), op.index ?? NaN)\n return\n case 'remove':\n canvas.deleteNode(live(canvas, op.nodeId))\n return\n case 'rename':\n canvas.updateNodeFields(live(canvas, op.nodeId), { name: op.name })\n return\n case 'insertSubtree':\n canvas.addNodeFromNested(nestSubtree(op), live(canvas, op.parentId), op.index ?? NaN)\n return\n case 'setSeo':\n case 'saveAsComponent':\n // Both are applied outside the canvas batch: search fields are staged\n // into the editor's own form, and a component save mints a document\n // first and then swaps the subtree for an instance of it.\n return\n }\n}\n\n/* ------------------------------------------------------------------ *\n * Save the selection as a reusable component (AGL-2908)\n * ------------------------------------------------------------------ */\n\n/** What the apply needs from the console to create the component. */\nexport interface AssistEditComponentWriter {\n /**\n * Creates the component through `POST /api/hosts/resources`, where the\n * plan's entitlement and the route's field allow-list are enforced, and\n * answers its id. The plugin never writes Firestore from the browser.\n */\n createComponent(input: {\n name: string\n rootId: string\n nodes: Record<string, unknown>\n props: ReusableComponentProp[]\n }): Promise<string>\n}\n\n/**\n * The value a bound field holds on the live canvas right now, which becomes\n * the property's default.\n *\n * `hideIf` is the exception: the part is on the page, so the property that\n * hides it starts at no. Every other field answers with what the author can\n * see, which is what makes the instance render exactly what was there.\n */\nfunction currentValue(\n node: AssistEditCanvasNodeLike,\n field: string,\n): ReusableComponentPropValue | undefined {\n if (field === NODE_HIDE_IF_PROP) return false\n const value = plain(node.props)[field]\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return value\n }\n return undefined\n}\n\n/**\n * Whether a default the canvas gave is one the property's own control\n * offers. A Choice whose current value is not among its answers is a\n * selection that has changed since the proposal was made, and applying it\n * would declare a property no page could ever set back.\n */\nfunction defaultFitsProp(prop: AssistEditComponentProp, value: unknown): boolean {\n if (!prop.options?.length) return true\n return prop.options.some((option) => option.value === value)\n}\n\n/**\n * The definition the new component holds: the promoted subtree, with each\n * bound field replaced by its property's token.\n *\n * The defaults are read off the SAME fields a moment before they are\n * replaced, so the instance that takes the subtree's place renders what the\n * author was looking at. Returns null when a default no longer fits its\n * property, which is the stale case.\n */\nfunction componentDefinition(\n canvas: AssistEditCanvas,\n op: AssistEditSaveAsComponentOp,\n): { nodes: Record<string, unknown>; props: ReusableComponentProp[] } | null {\n const nodes = reusableComponentDefinitionFrom(\n canvas.toJSON().nodes as never,\n op.nodeId,\n ) as unknown as Record<string, Record<string, unknown>>\n const defaults = new Map<string, ReusableComponentPropValue | undefined>()\n for (const binding of op.bindings) {\n const live = canvas.getNode(binding.nodeId)\n const stored = nodes[binding.nodeId]\n if (!live || !stored) return null\n if (!defaults.has(binding.prop)) defaults.set(binding.prop, currentValue(live, binding.field))\n stored['props'] = { ...plain(stored['props']), [binding.field]: `{{prop.${binding.prop}}}` }\n }\n const props: ReusableComponentProp[] = []\n for (const declared of op.props) {\n const value = defaults.get(declared.name)\n if (!defaultFitsProp(declared, value)) return null\n props.push({ ...declared, ...(value === undefined ? {} : { defaultValue: value }) })\n }\n return { nodes, props }\n}\n\n/**\n * Lands a confirmed proposal on the open editor: the canvas ops as ONE batch\n * — one undo step, all or nothing — then any search fields staged into the\n * editor's own form. Nothing is saved.\n */\nexport function applyAssistEdit(\n canvas: AssistEditCanvas,\n proposal: AssistEditProposal,\n session: EditorSession | undefined,\n): AssistEditApplyResult {\n const check = checkAssistEdit(canvas, proposal, session)\n if (check.ok === false) return check\n const open = session as EditorSession\n const canvasOps = proposal.ops.filter((op) => op.op !== 'setSeo' && op.op !== 'saveAsComponent')\n if (canvasOps.length) {\n try {\n canvas.batch(() => {\n for (const op of canvasOps) applyOne(canvas, op)\n })\n } catch (error) {\n console.error('assist edit refused by the canvas', error)\n return {\n ok: false,\n reason: 'refused',\n message: 'The editor refused part of this change, so none of it was applied.',\n }\n }\n }\n const staged: string[] = []\n for (const op of proposal.ops) {\n if (op.op !== 'setSeo') continue\n const values: Record<string, string> = {}\n for (const [field, value] of Object.entries(op.fields)) {\n values[screenSeoStageKey(field as ScreenSeoTextField)] = String(value)\n }\n staged.push(...stageEditorSessionFields(open, values).staged)\n }\n return { ok: true, opCounts: assistEditOpCounts(proposal.ops), staged }\n}\n\n/**\n * Lands a proposal that saves the selection as a reusable component\n * (AGL-2908) — AGL-2866's recipe, in place, with no clipboard.\n *\n * The order is the manual action's order, and it matters:\n *\n * 1. the definition is read off the live subtree, each bound field replaced\n * by its token and its current value kept as that property's default;\n * 2. the component is created through the host resources route, where the\n * server enforces the plan's entitlement and its own allow-list — so a\n * refusal happens before the open document is touched at all;\n * 3. the subtree is swapped for an instance of what was just created, inside\n * ONE `batch` with the rest of the proposal's canvas ops: one undo step.\n *\n * The only document created is the component, exactly as Save as reusable\n * component creates one. The page change is an unsaved edit on the version\n * the editor has open, which the check has already refused to be a live one.\n * Nothing is published and nothing is saved.\n */\nexport async function applyAssistEditSavingComponent(\n canvas: AssistEditCanvas,\n proposal: AssistEditProposal,\n session: EditorSession | undefined,\n writer: AssistEditComponentWriter,\n): Promise<AssistEditApplyResult> {\n const save = proposal.ops.find(\n (op): op is AssistEditSaveAsComponentOp => op.op === 'saveAsComponent',\n )\n if (!save) return applyAssistEdit(canvas, proposal, session)\n const check = checkAssistEdit(canvas, proposal, session)\n if (check.ok === false) return check\n\n const definition = componentDefinition(canvas, save)\n if (!definition) return STALE as AssistEditApplyResult\n\n let componentId: string\n try {\n componentId = await writer.createComponent({\n name: save.name,\n rootId: save.nodeId,\n nodes: definition.nodes,\n props: definition.props,\n })\n } catch (error) {\n console.error('assist edit could not create the component', error)\n return {\n ok: false,\n reason: 'refused',\n message:\n error instanceof Error && error.message\n ? error.message\n : 'The component could not be saved, so nothing on this page was changed.',\n }\n }\n\n const canvasOps = proposal.ops.filter((op) => op.op !== 'setSeo' && op.op !== 'saveAsComponent')\n try {\n canvas.batch(() => {\n for (const op of canvasOps) applyOne(canvas, op)\n canvas.applyNodes(\n replaceSubtreeWithInstance(\n canvas.toJSON().nodes as never,\n save.nodeId,\n componentId,\n save.name,\n ),\n )\n })\n } catch (error) {\n console.error('assist edit refused by the canvas', error)\n return {\n ok: false,\n reason: 'refused',\n message:\n 'The component was saved, but the editor refused to swap this element for it. ' +\n 'Insert it from Your components instead.',\n }\n }\n return { ok: true, opCounts: assistEditOpCounts(proposal.ops), staged: [] }\n}\n"],"names":["screenSeoStageKey","NODE_HIDE_IF_PROP","replaceSubtreeWithInstance","reusableComponentDefinitionFrom","CANVAS_ROOT_ELEMENT_ID","stageEditorSessionFields","ASSIST_EDIT_CONTEXT_MAX_NODES","ASSIST_EDIT_CONTEXT_MAX_PROPS","ASSIST_EDIT_OUTLINE_TEXT_CHARS","ASSIST_EDIT_SELECTED_TEXT_CHARS","assistEditOpCounts","UNDESCRIBED_PROP","isRecord","value","Array","isArray","plain","out","key","describeProps","raw","textChars","props","kept","name","Object","entries","test","trim","slice","Number","isFinite","undefined","describeSx","sx","keys","length","chainToRoot","canvas","selected","chain","walked","Set","current","$id","has","add","unshift","parentId","getNode","SHAPE_LIMIT","shapeOf","rootId","budget","walk","id","node","parts","child","nodes","part","push","String","componentId","join","countElements","count","reached","pending","pop","describeAssistEditCanvas","selectedId","root","order","seen","brief","like","Map","full","briefly","childrenOf","shapes","shape","set","get","alike","model","forEach","inside","queue","shift","siblings","filter","held","level","deeper","ancestor","reverse","section","map","parent","isRoot","isSelected","isBrief","index","Math","max","indexOf","childCount","total","subtreeIds","found","STALE","ok","reason","message","checkAssistEdit","proposal","session","documentKind","target","kind","documentId","isLiveVersion","op","ops","field","fields","parentComponentId","nodeAcceptsChildren","nodeId","binding","bindings","bound","mergeSx","patch","existing","xs","nestSubtree","visited","build","pluginId","hidden","live","Error","applyOne","next","updateNodeProps","updateNodeFields","reparentNode","NaN","deleteNode","addNodeFromNested","currentValue","defaultFitsProp","prop","options","some","option","componentDefinition","toJSON","defaults","stored","declared","defaultValue","applyAssistEdit","check","open","canvasOps","batch","error","console","staged","values","opCounts","applyAssistEditSavingComponent","writer","save","find","definition","createComponent","applyNodes"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/assist-edit-canvas.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n screenSeoStageKey,\n type ScreenSeoTextField,\n} from '@aglyn/aglyn/app-utils/screen-seo-fields'\nimport {\n NODE_HIDE_IF_PROP,\n replaceSubtreeWithInstance,\n reusableComponentDefinitionFrom,\n} from '@aglyn/aglyn/app-utils/compose-reusable-components'\nimport { CANVAS_ROOT_ELEMENT_ID } from '@aglyn/aglyn/foundation/constants/canvas'\nimport {\n NODE_MAX_INTERACTIONS,\n upsertNodeInteraction,\n type NodeInteraction,\n} from '@aglyn/aglyn/app-utils/node-interactions'\nimport type {\n ReusableComponentProp,\n ReusableComponentPropValue,\n} from '@aglyn/aglyn/foundation/definitions/platform.types'\nimport {\n stageEditorSessionFields,\n type EditorSession,\n} from '@aglyn/aglyn/plugin-manager/editor-sessions'\nimport {\n ASSIST_EDIT_CONTEXT_MAX_NODES,\n ASSIST_EDIT_CONTEXT_MAX_PROPS,\n ASSIST_EDIT_OUTLINE_TEXT_CHARS,\n ASSIST_EDIT_SELECTED_TEXT_CHARS,\n assistEditOpCounts,\n type AssistEditCanvasContext,\n type AssistEditCanvasNode,\n type AssistEditInsertOp,\n type AssistEditInteractionSummary,\n type AssistEditOp,\n type AssistEditProposal,\n type AssistEditComponentProp,\n type AssistEditSaveAsComponentOp,\n} from '../model/assist-edit'\n\n/**\n * The edit rung's client half (AGL-2906): what the panel tells the server\n * about the open canvas, and how a confirmed proposal lands on it.\n *\n * Applying goes through the canvas's own guarded mutators — the same ones\n * the besigner's panels and the marketing appliers use — inside ONE\n * `batch`, so the whole proposal is one undo step and a guard that refuses\n * part-way leaves nothing behind. Every change is an unsaved edit on the\n * version the editor has open; saving it stays the author's act, with the\n * editor's own control. A version the live site serves is never edited:\n * the check refuses it, and the card offers the editor's own new-version\n * flow instead.\n */\n\n/** A node as the canvas holds it — the fields this module reads. */\nexport interface AssistEditCanvasNodeLike {\n $id?: string\n componentId?: string\n parentId?: string | null\n nodes?: string[]\n name?: string\n props?: unknown\n sx?: unknown\n /** The element's own interactions (AGL-3603), as the canvas holds them. */\n interactions?: unknown\n}\n\n/**\n * The slice of the besigner canvas the edit rung reads and drives. Every\n * member is one `CanvasManager` already has, so the panel hands over the\n * canvas itself and a spec hands over a real one.\n */\nexport interface AssistEditCanvas {\n getNode(id: string): AssistEditCanvasNodeLike | undefined\n batch<T>(mutate: () => T): T\n updateNodeProps(node: any, props: any): void\n updateNodeFields(node: any, patch: any): void\n reparentNode(node: any, parent: any, index?: number): unknown\n deleteNode(node: any): unknown\n addNodeFromNested(nested: any, parent: any, index?: number): unknown\n nodeAcceptsChildren(node: any): boolean\n /** The whole document, which a component save reads its definition out of. */\n toJSON(): { nodes: Record<string, unknown> }\n /** The document after a save: the promoted subtree swapped for an instance. */\n applyNodes(nodes: any): unknown\n}\n\nconst UNDESCRIBED_PROP = /^(html|sx|style|className|dangerouslySetInnerHTML|on[A-Z].*)$/\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/**\n * An observable's own keys as a plain object. A canvas node's `props` and\n * `sx` are observable proxies, and a spread of one is how a merge silently\n * copies nothing.\n */\nfunction plain(value: unknown): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n if (!value || typeof value !== 'object') return out\n for (const key in value as Record<string, unknown>) {\n out[key] = (value as Record<string, unknown>)[key]\n }\n return out\n}\n\nfunction describeProps(\n raw: unknown,\n textChars: number,\n): Record<string, string | number | boolean> | undefined {\n const props: Record<string, string | number | boolean> = {}\n let kept = 0\n for (const [name, value] of Object.entries(plain(raw))) {\n if (kept >= ASSIST_EDIT_CONTEXT_MAX_PROPS) break\n if (UNDESCRIBED_PROP.test(name)) continue\n if (typeof value === 'string') {\n if (!value.trim()) continue\n props[name] = value.slice(0, textChars)\n } else if (typeof value === 'number' && Number.isFinite(value)) {\n props[name] = value\n } else if (typeof value === 'boolean') {\n props[name] = value\n } else {\n continue\n }\n kept += 1\n }\n return kept ? props : undefined\n}\n\nfunction describeSx(raw: unknown): Record<string, unknown> | undefined {\n const sx: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(plain(raw))) {\n if (typeof value === 'string' || typeof value === 'number') sx[key] = value\n else if (isRecord(value)) sx[key] = plain(value)\n }\n return Object.keys(sx).length ? sx : undefined\n}\n\n/**\n * The selection's ancestors below the document root, top-level section first\n * and the selection last; null when its parents do not lead to the root,\n * which is not a chain the server can check.\n */\nfunction chainToRoot(\n canvas: Pick<AssistEditCanvas, 'getNode'>,\n selected: AssistEditCanvasNodeLike,\n): string[] | null {\n const chain: string[] = []\n const walked = new Set<string>()\n let current: AssistEditCanvasNodeLike | undefined = selected\n while (current?.$id && current.$id !== CANVAS_ROOT_ELEMENT_ID && !walked.has(current.$id)) {\n walked.add(current.$id)\n chain.unshift(current.$id)\n current = current.parentId ? canvas.getNode(current.parentId) : undefined\n }\n return current?.$id === CANVAS_ROOT_ELEMENT_ID ? chain : null\n}\n\n/** Elements one shape is taken over at most; a larger subtree is never called alike. */\nconst SHAPE_LIMIT = 200\n\n/**\n * How an element is built: its component and, in order, its children's —\n * what two cards of one row have in common whatever their text. Null past\n * `SHAPE_LIMIT` elements, or for a subtree that loops back on itself.\n */\nfunction shapeOf(canvas: Pick<AssistEditCanvas, 'getNode'>, rootId: string): string | null {\n let budget = SHAPE_LIMIT\n const walked = new Set<string>()\n const walk = (id: string): string | null => {\n const node = canvas.getNode(id)\n if (!node || walked.has(id) || --budget < 0) return null\n walked.add(id)\n const parts: string[] = []\n for (const child of node.nodes ?? []) {\n const part = walk(child)\n if (part === null) return null\n parts.push(part)\n }\n return `${String(node.componentId ?? '')}(${parts.join(',')})`\n }\n return walk(rootId)\n}\n\n/** Elements reachable from the document root through child lists, the root included. */\nfunction countElements(canvas: Pick<AssistEditCanvas, 'getNode'>): number {\n let count = 0\n const reached = new Set<string>([CANVAS_ROOT_ELEMENT_ID])\n const pending = [CANVAS_ROOT_ELEMENT_ID]\n while (pending.length) {\n const node = canvas.getNode(pending.pop() as string)\n if (!node) continue\n count += 1\n for (const child of node.nodes ?? []) {\n if (reached.has(child)) continue\n reached.add(child)\n pending.push(child)\n }\n }\n return count\n}\n\n/**\n * The canvas outline a question carries on the edit rung, in two tiers, until\n * the cap.\n *\n * Described in full, settings and all: the document root, the selection's\n * ancestors and the selection, the document's top-level sections, everything\n * inside the selection — what an edit to it changes — and its siblings.\n *\n * Described briefly, by place alone (`brief`): what surrounds that, so the\n * model knows it exists and asks for it rather than calling it missing —\n *\n * 1. what the selection's siblings hold, level by level (the icons beside a\n * selected link, in the card they share);\n * 2. the siblings of each ancestor below the top-level section, nearest\n * first (the other cards of the row, then what sits beside the row).\n *\n * An element built the same way as the selection, or as the ancestor it sits\n * beside, is marked `like` it and its contents are left out: one card\n * described, and every other card of the row says it holds the same.\n *\n * With nothing selected, it is the root, the top-level sections and one level\n * inside each: enough for a change to the page as a whole, and the prompt asks\n * for a selection before anything more specific.\n *\n * An element is only ever described after its parent, so every ancestor chain\n * the server checks is whole. `total` counts the document, and each element's\n * `childCount` stays its real one, so the server can tell the model what the\n * outline leaves out. The server holds this to its own limits before it quotes\n * a byte of it; null when the canvas has no document root loaded.\n */\nexport function describeAssistEditCanvas(\n canvas: Pick<AssistEditCanvas, 'getNode'>,\n selectedId: string | null,\n): AssistEditCanvasContext | null {\n const root = canvas.getNode(CANVAS_ROOT_ELEMENT_ID)\n if (!root) return null\n const order: string[] = []\n const seen = new Set<string>()\n const brief = new Set<string>()\n const like = new Map<string, string>()\n const full = (): boolean => order.length >= ASSIST_EDIT_CONTEXT_MAX_NODES\n const add = (id: string | undefined | null, briefly = false): void => {\n if (!id || seen.has(id) || full()) return\n if (!canvas.getNode(id)) return\n seen.add(id)\n order.push(id)\n if (briefly) brief.add(id)\n }\n const childrenOf = (id: string): string[] => canvas.getNode(id)?.nodes ?? []\n const shapes = new Map<string, string | null>()\n const shape = (id: string): string | null => {\n if (!shapes.has(id)) shapes.set(id, shapeOf(canvas, id))\n return shapes.get(id) ?? null\n }\n // Alike only when there are contents to leave out.\n const alike = (id: string, model: string): boolean =>\n childrenOf(id).length > 0 && shape(id) !== null && shape(id) === shape(model)\n\n add(CANVAS_ROOT_ELEMENT_ID)\n const selected =\n selectedId && selectedId !== CANVAS_ROOT_ELEMENT_ID ? canvas.getNode(selectedId) : undefined\n const chain = selected?.$id ? chainToRoot(canvas, selected) : null\n chain?.forEach((id) => add(id))\n if (selected?.$id && chain && seen.has(selected.$id)) {\n for (const id of root.nodes ?? []) add(id)\n const inside = new Set<string>([selected.$id])\n const queue = [...childrenOf(selected.$id)]\n while (queue.length && !full()) {\n const id = queue.shift() as string\n if (inside.has(id)) continue\n inside.add(id)\n add(id)\n queue.push(...childrenOf(id))\n }\n const siblings = selected.parentId\n ? childrenOf(selected.parentId).filter((id) => id !== selected.$id)\n : []\n const held: string[] = []\n for (const id of siblings) {\n add(id)\n // A sibling the cap left out takes its contents with it.\n if (!seen.has(id)) continue\n if (alike(id, selected.$id)) like.set(id, selected.$id)\n else held.push(...childrenOf(id))\n }\n const reached = new Set<string>([...inside, ...siblings, ...held])\n for (let level = held; level.length && !full(); ) {\n const deeper: string[] = []\n for (const id of level) {\n add(id, true)\n for (const child of childrenOf(id)) {\n if (reached.has(child)) continue\n reached.add(child)\n deeper.push(child)\n }\n }\n level = deeper\n }\n // Parent first; the top-level section's own siblings are the sections above.\n for (const ancestor of chain.slice(1, -1).reverse()) {\n const parentId = canvas.getNode(ancestor)?.parentId\n for (const id of parentId ? childrenOf(parentId) : []) {\n if (id === ancestor || seen.has(id)) continue\n add(id, true)\n if (seen.has(id) && alike(id, ancestor)) like.set(id, ancestor)\n }\n }\n } else {\n for (const id of root.nodes ?? []) add(id)\n for (const section of root.nodes ?? []) {\n for (const id of childrenOf(section)) add(id)\n }\n }\n\n const nodes: AssistEditCanvasNode[] = order.map((id) => {\n const node = canvas.getNode(id) as AssistEditCanvasNodeLike\n const isRoot = id === CANVAS_ROOT_ELEMENT_ID\n const parentId = isRoot ? null : (node.parentId ?? null)\n const parent = parentId ? canvas.getNode(parentId) : undefined\n const isSelected = id === selected?.$id\n const isBrief = brief.has(id)\n const props = isBrief\n ? undefined\n : describeProps(\n node.props,\n isSelected ? ASSIST_EDIT_SELECTED_TEXT_CHARS : ASSIST_EDIT_OUTLINE_TEXT_CHARS,\n )\n const sx = isSelected ? describeSx(node.sx) : undefined\n const model = like.get(id)\n return {\n id,\n componentId: String(node.componentId ?? ''),\n parentId,\n index: Math.max(0, parent?.nodes?.indexOf(id) ?? 0),\n childCount: node.nodes?.length ?? 0,\n ...(node.name ? { name: String(node.name) } : {}),\n ...(props ? { props } : {}),\n ...(sx ? { sx } : {}),\n ...(isBrief ? { brief: true } : {}),\n ...(model ? { like: model } : {}),\n ...(isSelected ? summarizeInteractions(node.interactions) : {}),\n }\n })\n return {\n selectedId: selected?.$id && seen.has(selected.$id) ? selected.$id : null,\n total: countElements(canvas),\n nodes,\n }\n}\n\n/**\n * The selected element's interactions as the outline carries them\n * (AGL-3603): name, event and the kinds of its steps — never a selector.\n */\nfunction summarizeInteractions(raw: unknown): { interactions?: AssistEditInteractionSummary[] } {\n if (!Array.isArray(raw) || !raw.length) return {}\n const interactions = raw\n .filter(isRecord)\n .slice(0, NODE_MAX_INTERACTIONS)\n .map((entry) => ({\n name: String(entry['name'] ?? ''),\n event: String(isRecord(entry['trigger']) ? (entry['trigger']['event'] ?? '') : ''),\n steps: (Array.isArray(entry['steps']) ? entry['steps'] : [])\n .filter(isRecord)\n .map((step) => String(step['type'] ?? '')),\n enabled: entry['enabled'] !== false,\n }))\n .filter((entry) => entry.event)\n return interactions.length ? { interactions } : {}\n}\n\n/** Why a proposal cannot land on the open editor as it stands. */\nexport type AssistEditRefusal =\n /** No editor is open. */\n | 'no-editor'\n /** The editor open is not the document the proposal was made for. */\n | 'other-document'\n /** The open version is the one the live site serves. */\n | 'live-version'\n /** An element the proposal names has gone or changed since. */\n | 'stale'\n /** The canvas's own guards refused part of the change. */\n | 'refused'\n\nexport type AssistEditCheck =\n | { ok: true }\n | { ok: false; reason: AssistEditRefusal; message: string }\n\nexport type AssistEditApplyResult =\n | {\n ok: true\n /** Applied ops, counted by kind for the activity row. */\n opCounts: Record<string, number>\n /** Editor fields staged, as the editor keys them. */\n staged: string[]\n }\n | { ok: false; reason: AssistEditRefusal; message: string }\n\n/** Ids of the subtree at `rootId`, the root included, through child lists only. */\nfunction subtreeIds(\n canvas: Pick<AssistEditCanvas, 'getNode'>,\n rootId: string,\n): Set<string> {\n const found = new Set<string>([rootId])\n const queue = [...(canvas.getNode(rootId)?.nodes ?? [])]\n while (queue.length) {\n const id = queue.shift() as string\n if (found.has(id) || !canvas.getNode(id)) continue\n found.add(id)\n queue.push(...(canvas.getNode(id)?.nodes ?? []))\n }\n return found\n}\n\nconst STALE: AssistEditCheck = {\n ok: false,\n reason: 'stale',\n message: 'The canvas has changed since this was proposed, so nothing was applied. Ask again.',\n}\n\n/**\n * Whether the proposal can land on the open editor as it stands — checked in\n * full before anything is touched, so a refusal never leaves half an edit.\n */\nexport function checkAssistEdit(\n canvas: Pick<AssistEditCanvas, 'getNode' | 'nodeAcceptsChildren'>,\n proposal: AssistEditProposal,\n session: EditorSession | undefined,\n): AssistEditCheck {\n if (!session) {\n return {\n ok: false,\n reason: 'no-editor',\n message: 'Open the editor this change was proposed for to apply it.',\n }\n }\n if (\n session.documentKind !== proposal.target.kind ||\n session.documentId !== proposal.target.documentId\n ) {\n return {\n ok: false,\n reason: 'other-document',\n message: 'This change was proposed for a different document than the one open.',\n }\n }\n if (session.isLiveVersion()) {\n return {\n ok: false,\n reason: 'live-version',\n message:\n 'This is the version your live site shows. Make a new version first, then apply the change there.',\n }\n }\n for (const op of proposal.ops) {\n switch (op.op) {\n case 'setSeo': {\n for (const field of Object.keys(op.fields) as ScreenSeoTextField[]) {\n if (typeof session.fields?.[screenSeoStageKey(field)] !== 'function') {\n return {\n ok: false,\n reason: 'other-document',\n message: 'This editor has no search fields to fill in.',\n }\n }\n }\n break\n }\n case 'insertSubtree': {\n const parent = canvas.getNode(op.parentId)\n if (!parent || parent.componentId !== op.parentComponentId) return STALE\n if (!canvas.nodeAcceptsChildren(parent)) return STALE\n break\n }\n case 'move': {\n const node = canvas.getNode(op.nodeId)\n const parent = canvas.getNode(op.parentId)\n if (!node || node.componentId !== op.componentId) return STALE\n if (!parent || parent.componentId !== op.parentComponentId) return STALE\n break\n }\n case 'saveAsComponent': {\n const node = canvas.getNode(op.nodeId)\n if (!node || node.componentId !== op.componentId) return STALE\n // The document itself is not a section of itself: promoting the root\n // would leave a document holding one instance of its own contents.\n if (op.nodeId === CANVAS_ROOT_ELEMENT_ID) return STALE\n const inside = subtreeIds(canvas, op.nodeId)\n for (const binding of op.bindings) {\n const bound = canvas.getNode(binding.nodeId)\n if (!bound || bound.componentId !== binding.componentId) return STALE\n // A closed world: a token outside the promoted subtree would bind a\n // property of the new component to an element it does not contain.\n if (!inside.has(binding.nodeId)) return STALE\n }\n break\n }\n case 'addInteraction': {\n const node = canvas.getNode(op.nodeId)\n if (!node || node.componentId !== op.componentId) return STALE\n if (Array.isArray(node.interactions) && node.interactions.length >= NODE_MAX_INTERACTIONS) {\n return {\n ok: false,\n reason: 'refused',\n message: `That element already does ${NODE_MAX_INTERACTIONS} things, the most one can. Remove one in Interactions first.`,\n }\n }\n // Every element a step acts on is still there, as it was.\n for (const target of op.targets) {\n const live = canvas.getNode(target.nodeId)\n if (!live || live.componentId !== target.componentId) return STALE\n }\n break\n }\n default: {\n const node = canvas.getNode(op.nodeId)\n if (!node || node.componentId !== op.componentId) return STALE\n }\n }\n }\n return { ok: true }\n}\n\n/**\n * Styles merged one key at a time. A responsive patch over a plain value\n * keeps that value as the base breakpoint, so \"more padding on wide screens\"\n * does not quietly remove the padding everywhere else.\n */\nfunction mergeSx(\n current: Record<string, unknown>,\n patch: Record<string, unknown>,\n): Record<string, unknown> {\n const out = { ...current }\n for (const [key, value] of Object.entries(patch)) {\n const existing = out[key]\n if (isRecord(value) && isRecord(existing)) {\n out[key] = { ...plain(existing), ...value }\n } else if (isRecord(value) && (typeof existing === 'string' || typeof existing === 'number')) {\n out[key] = { xs: existing, ...value }\n } else {\n out[key] = value\n }\n }\n return out\n}\n\n/** A validated flat subtree as the nested shape `addNodeFromNested` takes. */\nfunction nestSubtree(op: AssistEditInsertOp): Record<string, unknown> {\n const visited = new Set<string>()\n const build = (id: string): Record<string, unknown> => {\n visited.add(id)\n const node = op.nodes[id]\n return {\n componentId: node.componentId,\n ...(node.pluginId ? { pluginId: node.pluginId } : {}),\n props: { ...node.props },\n ...(node.sx ? { sx: { ...node.sx } } : {}),\n ...(node.hidden ? { hidden: true } : {}),\n nodes: node.nodes\n .filter((child) => op.nodes[child] && !visited.has(child))\n .map((child) => build(child)),\n }\n }\n return build(op.rootId)\n}\n\nfunction live(canvas: AssistEditCanvas, id: string): AssistEditCanvasNodeLike {\n const node = canvas.getNode(id)\n if (!node) throw new Error(`element ${id} is no longer on the canvas`)\n return node\n}\n\nfunction applyOne(canvas: AssistEditCanvas, op: AssistEditOp): void {\n switch (op.op) {\n case 'updateProps': {\n const node = live(canvas, op.nodeId)\n // Spread the props the element has: `updateNodeProps` REPLACES the bag,\n // and a patch of one setting would otherwise strip every other one.\n const next: Record<string, unknown> = { ...plain(node.props), ...op.props }\n // Rich text renders `html` over `children`; proposed text replaces it.\n if ('children' in op.props) delete next['html']\n canvas.updateNodeProps(node, next)\n return\n }\n case 'updateSx': {\n const node = live(canvas, op.nodeId)\n canvas.updateNodeFields(node, { sx: mergeSx(plain(node.sx), op.sx) })\n return\n }\n case 'move':\n canvas.reparentNode(live(canvas, op.nodeId), live(canvas, op.parentId), op.index ?? NaN)\n return\n case 'remove':\n canvas.deleteNode(live(canvas, op.nodeId))\n return\n case 'rename':\n canvas.updateNodeFields(live(canvas, op.nodeId), { name: op.name })\n return\n case 'addInteraction': {\n // Added beside what the element does already, never in place of it:\n // an id the element already uses is re-minted, so nothing is replaced.\n const node = live(canvas, op.nodeId)\n const current = (Array.isArray(node.interactions) ? node.interactions : []) as NodeInteraction[]\n let id = op.interaction.id\n while (current.some((entry) => entry.id === id)) id = `${op.interaction.id}${current.length}x`\n canvas.updateNodeFields(node, {\n interactions: upsertNodeInteraction(current, { ...op.interaction, id }),\n })\n return\n }\n case 'insertSubtree':\n canvas.addNodeFromNested(nestSubtree(op), live(canvas, op.parentId), op.index ?? NaN)\n return\n case 'setSeo':\n case 'saveAsComponent':\n // Both are applied outside the canvas batch: search fields are staged\n // into the editor's own form, and a component save mints a document\n // first and then swaps the subtree for an instance of it.\n return\n }\n}\n\n/* ------------------------------------------------------------------ *\n * Save the selection as a reusable component (AGL-2908)\n * ------------------------------------------------------------------ */\n\n/** What the apply needs from the console to create the component. */\nexport interface AssistEditComponentWriter {\n /**\n * Creates the component through `POST /api/hosts/resources`, where the\n * plan's entitlement and the route's field allow-list are enforced, and\n * answers its id. The plugin never writes Firestore from the browser.\n */\n createComponent(input: {\n name: string\n rootId: string\n nodes: Record<string, unknown>\n props: ReusableComponentProp[]\n }): Promise<string>\n}\n\n/**\n * The value a bound field holds on the live canvas right now, which becomes\n * the property's default.\n *\n * `hideIf` is the exception: the part is on the page, so the property that\n * hides it starts at no. Every other field answers with what the author can\n * see, which is what makes the instance render exactly what was there.\n */\nfunction currentValue(\n node: AssistEditCanvasNodeLike,\n field: string,\n): ReusableComponentPropValue | undefined {\n if (field === NODE_HIDE_IF_PROP) return false\n const value = plain(node.props)[field]\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return value\n }\n return undefined\n}\n\n/**\n * Whether a default the canvas gave is one the property's own control\n * offers. A Choice whose current value is not among its answers is a\n * selection that has changed since the proposal was made, and applying it\n * would declare a property no page could ever set back.\n */\nfunction defaultFitsProp(prop: AssistEditComponentProp, value: unknown): boolean {\n if (!prop.options?.length) return true\n return prop.options.some((option) => option.value === value)\n}\n\n/**\n * The definition the new component holds: the promoted subtree, with each\n * bound field replaced by its property's token.\n *\n * The defaults are read off the SAME fields a moment before they are\n * replaced, so the instance that takes the subtree's place renders what the\n * author was looking at. Returns null when a default no longer fits its\n * property, which is the stale case.\n */\nfunction componentDefinition(\n canvas: AssistEditCanvas,\n op: AssistEditSaveAsComponentOp,\n): { nodes: Record<string, unknown>; props: ReusableComponentProp[] } | null {\n const nodes = reusableComponentDefinitionFrom(\n canvas.toJSON().nodes as never,\n op.nodeId,\n ) as unknown as Record<string, Record<string, unknown>>\n const defaults = new Map<string, ReusableComponentPropValue | undefined>()\n for (const binding of op.bindings) {\n const live = canvas.getNode(binding.nodeId)\n const stored = nodes[binding.nodeId]\n if (!live || !stored) return null\n if (!defaults.has(binding.prop)) defaults.set(binding.prop, currentValue(live, binding.field))\n stored['props'] = { ...plain(stored['props']), [binding.field]: `{{prop.${binding.prop}}}` }\n }\n const props: ReusableComponentProp[] = []\n for (const declared of op.props) {\n const value = defaults.get(declared.name)\n if (!defaultFitsProp(declared, value)) return null\n props.push({ ...declared, ...(value === undefined ? {} : { defaultValue: value }) })\n }\n return { nodes, props }\n}\n\n/**\n * Lands a confirmed proposal on the open editor: the canvas ops as ONE batch\n * — one undo step, all or nothing — then any search fields staged into the\n * editor's own form. Nothing is saved.\n */\nexport function applyAssistEdit(\n canvas: AssistEditCanvas,\n proposal: AssistEditProposal,\n session: EditorSession | undefined,\n): AssistEditApplyResult {\n const check = checkAssistEdit(canvas, proposal, session)\n if (check.ok === false) return check\n const open = session as EditorSession\n const canvasOps = proposal.ops.filter((op) => op.op !== 'setSeo' && op.op !== 'saveAsComponent')\n if (canvasOps.length) {\n try {\n canvas.batch(() => {\n for (const op of canvasOps) applyOne(canvas, op)\n })\n } catch (error) {\n console.error('assist edit refused by the canvas', error)\n return {\n ok: false,\n reason: 'refused',\n message: 'The editor refused part of this change, so none of it was applied.',\n }\n }\n }\n const staged: string[] = []\n for (const op of proposal.ops) {\n if (op.op !== 'setSeo') continue\n const values: Record<string, string> = {}\n for (const [field, value] of Object.entries(op.fields)) {\n values[screenSeoStageKey(field as ScreenSeoTextField)] = String(value)\n }\n staged.push(...stageEditorSessionFields(open, values).staged)\n }\n return { ok: true, opCounts: assistEditOpCounts(proposal.ops), staged }\n}\n\n/**\n * Lands a proposal that saves the selection as a reusable component\n * (AGL-2908) — AGL-2866's recipe, in place, with no clipboard.\n *\n * The order is the manual action's order, and it matters:\n *\n * 1. the definition is read off the live subtree, each bound field replaced\n * by its token and its current value kept as that property's default;\n * 2. the component is created through the host resources route, where the\n * server enforces the plan's entitlement and its own allow-list — so a\n * refusal happens before the open document is touched at all;\n * 3. the subtree is swapped for an instance of what was just created, inside\n * ONE `batch` with the rest of the proposal's canvas ops: one undo step.\n *\n * The only document created is the component, exactly as Save as reusable\n * component creates one. The page change is an unsaved edit on the version\n * the editor has open, which the check has already refused to be a live one.\n * Nothing is published and nothing is saved.\n */\nexport async function applyAssistEditSavingComponent(\n canvas: AssistEditCanvas,\n proposal: AssistEditProposal,\n session: EditorSession | undefined,\n writer: AssistEditComponentWriter,\n): Promise<AssistEditApplyResult> {\n const save = proposal.ops.find(\n (op): op is AssistEditSaveAsComponentOp => op.op === 'saveAsComponent',\n )\n if (!save) return applyAssistEdit(canvas, proposal, session)\n const check = checkAssistEdit(canvas, proposal, session)\n if (check.ok === false) return check\n\n const definition = componentDefinition(canvas, save)\n if (!definition) return STALE as AssistEditApplyResult\n\n let componentId: string\n try {\n componentId = await writer.createComponent({\n name: save.name,\n rootId: save.nodeId,\n nodes: definition.nodes,\n props: definition.props,\n })\n } catch (error) {\n console.error('assist edit could not create the component', error)\n return {\n ok: false,\n reason: 'refused',\n message:\n error instanceof Error && error.message\n ? error.message\n : 'The component could not be saved, so nothing on this page was changed.',\n }\n }\n\n const canvasOps = proposal.ops.filter((op) => op.op !== 'setSeo' && op.op !== 'saveAsComponent')\n try {\n canvas.batch(() => {\n for (const op of canvasOps) applyOne(canvas, op)\n canvas.applyNodes(\n replaceSubtreeWithInstance(\n canvas.toJSON().nodes as never,\n save.nodeId,\n componentId,\n save.name,\n ),\n )\n })\n } catch (error) {\n console.error('assist edit refused by the canvas', error)\n return {\n ok: false,\n reason: 'refused',\n message:\n 'The component was saved, but the editor refused to swap this element for it. ' +\n 'Insert it from Your components instead.',\n }\n }\n return { ok: true, opCounts: assistEditOpCounts(proposal.ops), staged: [] }\n}\n"],"names":["screenSeoStageKey","NODE_HIDE_IF_PROP","replaceSubtreeWithInstance","reusableComponentDefinitionFrom","CANVAS_ROOT_ELEMENT_ID","NODE_MAX_INTERACTIONS","upsertNodeInteraction","stageEditorSessionFields","ASSIST_EDIT_CONTEXT_MAX_NODES","ASSIST_EDIT_CONTEXT_MAX_PROPS","ASSIST_EDIT_OUTLINE_TEXT_CHARS","ASSIST_EDIT_SELECTED_TEXT_CHARS","assistEditOpCounts","UNDESCRIBED_PROP","isRecord","value","Array","isArray","plain","out","key","describeProps","raw","textChars","props","kept","name","Object","entries","test","trim","slice","Number","isFinite","undefined","describeSx","sx","keys","length","chainToRoot","canvas","selected","chain","walked","Set","current","$id","has","add","unshift","parentId","getNode","SHAPE_LIMIT","shapeOf","rootId","budget","walk","id","node","parts","child","nodes","part","push","String","componentId","join","countElements","count","reached","pending","pop","describeAssistEditCanvas","selectedId","root","order","seen","brief","like","Map","full","briefly","childrenOf","shapes","shape","set","get","alike","model","forEach","inside","queue","shift","siblings","filter","held","level","deeper","ancestor","reverse","section","map","parent","isRoot","isSelected","isBrief","index","Math","max","indexOf","childCount","summarizeInteractions","interactions","total","entry","event","steps","step","enabled","subtreeIds","found","STALE","ok","reason","message","checkAssistEdit","proposal","session","documentKind","target","kind","documentId","isLiveVersion","op","ops","field","fields","parentComponentId","nodeAcceptsChildren","nodeId","binding","bindings","bound","targets","live","mergeSx","patch","existing","xs","nestSubtree","visited","build","pluginId","hidden","Error","applyOne","next","updateNodeProps","updateNodeFields","reparentNode","NaN","deleteNode","interaction","some","addNodeFromNested","currentValue","defaultFitsProp","prop","options","option","componentDefinition","toJSON","defaults","stored","declared","defaultValue","applyAssistEdit","check","open","canvasOps","batch","error","console","staged","values","opCounts","applyAssistEditSavingComponent","writer","save","find","definition","createComponent","applyNodes"],"mappings":"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"}
@@ -25,6 +25,7 @@ import { Box, Button, Chip, CircularProgress, Collapse, IconButton, Stack, Typog
25
25
  import { useCallback, useEffect, useRef, useState } from "react";
26
26
  import { AI_JOB_PHASE_LABELS, aiJobActivityCounts, aiJobPhase, aiJobsHeaderChips } from "../model/ai-job-activity.js";
27
27
  import { cancelAiJobRequest, resumeAiJobRequest } from "./ai-job-requests.js";
28
+ import { aiBuildCanRetry, aiBuildItemRows, aiSitePartialCopy } from "../model/ai-build-progress.js";
28
29
  import { publishAiJob } from "./ai-jobs-store.js";
29
30
  import { AiPageBriefDialog } from "./ai-page-brief-dialog.component.js";
30
31
  import { AiInsightDialog } from "./ai-insight-dialog.component.js";
@@ -77,6 +78,13 @@ export { aiJobOutputHref, aiJobPrimaryLink, readEventFrames };
77
78
  attention: 'warning',
78
79
  running: 'primary'
79
80
  };
81
+ /** What each item state reads as in a row (AGL-3616). */ const ITEM_STATE_LABELS = {
82
+ done: 'built',
83
+ active: 'building',
84
+ waiting: 'waiting',
85
+ failed: 'failed',
86
+ skipped: 'not built'
87
+ };
80
88
  /** How long a job AI jobs was opened on stays highlighted. */ const HIGHLIGHT_MS = 2500;
81
89
  /**
82
90
  * Where a guided start that ended unbuilt is tried again (AGL-3596): its
@@ -314,12 +322,12 @@ export function AssistJobsDrawer({ orgId, org, orgReady, orgSlug, user, visible,
314
322
  // Confirms a plan, or tries again a step whose answer broke a building
315
323
  // rule (AGL-2935). The door runs the next step inline and answers with the
316
324
  // job, so the row moves on without waiting for the stream.
317
- const resume = useCallback(async (job)=>{
325
+ const resume = useCallback(async (job, options)=>{
318
326
  if (!orgId) return;
319
327
  setResuming(job.id);
320
328
  setNotice(null);
321
329
  // The same door the dialog that started the job confirms through (AGL-3593).
322
- const { job: next, error } = await resumeAiJobRequest(user, orgId, job);
330
+ const { job: next, error } = await resumeAiJobRequest(user, orgId, job, options);
323
331
  if (next) patchJob(next);
324
332
  if (error) setNotice(error);
325
333
  setResuming(null);
@@ -429,6 +437,7 @@ export function AssistJobsDrawer({ orgId, org, orgReady, orgSlug, user, visible,
429
437
  role: "list",
430
438
  "aria-label": "AI jobs",
431
439
  children: jobs.map((job)=>{
440
+ var _job_items;
432
441
  const restartHref = (row)=>aiJobRestartHref(row, {
433
442
  orgSlug,
434
443
  hostId,
@@ -518,6 +527,42 @@ export function AssistJobsDrawer({ orgId, org, orgReady, orgSlug, user, visible,
518
527
  component: "div",
519
528
  children: aiJobRefundCopy(job)
520
529
  }),
530
+ aiSitePartialCopy(job) && /*#__PURE__*/ _jsx(Typography, {
531
+ variant: "caption",
532
+ color: "text.secondary",
533
+ component: "div",
534
+ children: aiSitePartialCopy(job)
535
+ }),
536
+ ((_job_items = job.items) == null ? void 0 : _job_items.length) ? /*#__PURE__*/ _jsx(Box, {
537
+ component: "ul",
538
+ "aria-label": "Items",
539
+ sx: {
540
+ m: 0,
541
+ mt: 0.5,
542
+ pl: 2
543
+ },
544
+ children: aiBuildItemRows(job).map((row)=>/*#__PURE__*/ _jsxs(Typography, {
545
+ component: "li",
546
+ variant: "caption",
547
+ "data-item-state": row.state,
548
+ children: [
549
+ `${row.label} — ${ITEM_STATE_LABELS[row.state]}`,
550
+ row.detail ? `. ${row.detail}` : ''
551
+ ]
552
+ }, row.slot))
553
+ }) : null,
554
+ aiBuildCanRetry(job) ? /*#__PURE__*/ _jsx(Button, {
555
+ size: "small",
556
+ variant: "contained",
557
+ disabled: resuming === job.id,
558
+ onClick: ()=>void resume(job, {
559
+ retry: 'failed-items'
560
+ }),
561
+ sx: {
562
+ mt: 0.5
563
+ },
564
+ children: 'Try again what failed'
565
+ }) : null,
521
566
  restartHref(job) ? /*#__PURE__*/ _jsx(Button, {
522
567
  size: "small",
523
568
  variant: "contained",
@@ -602,7 +647,7 @@ export function AssistJobsDrawer({ orgId, org, orgReady, orgSlug, user, visible,
602
647
  }),
603
648
  /*#__PURE__*/ _jsx(AiJobPlan, {
604
649
  job: job,
605
- onResume: (target)=>void resume(target),
650
+ onResume: (target, options)=>void resume(target, options),
606
651
  busy: resuming === job.id,
607
652
  staff: isStaff,
608
653
  user: user
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/assist-jobs-drawer.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { checkEntitlement } from '@aglyn/aglyn'\nimport { trackEvent } from '@aglyn/aglyn/app-utils/analytics-events'\nimport { formatBytes } from '@aglyn/aglyn/app-utils/measure-node-map'\nimport {\n AI_JOB_TERMINAL_STATUSES,\n type AiJobOutput,\n type AiJobSummary,\n} from '../model/ai-jobs.types'\nimport type { AglynOrgBilling } from '@aglyn/aglyn/foundation/definitions/org-billing.types'\nimport { mdiChevronDown, mdiChevronUp } from '@aglyn/shared-data-mdi'\nimport { AppLink, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport {\n Box,\n Button,\n Chip,\n CircularProgress,\n Collapse,\n IconButton,\n Stack,\n Typography,\n} from '@mui/material'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport {\n AI_JOB_PHASE_LABELS,\n aiJobActivityCounts,\n aiJobPhase,\n aiJobsHeaderChips,\n type AiJobActivityState,\n type AiJobPhase,\n} from '../model/ai-job-activity'\nimport type { AiInsightSurface } from '../model/ai-insight'\nimport { cancelAiJobRequest, resumeAiJobRequest } from './ai-job-requests'\nimport { publishAiJob, type AiJobsOpenRequest } from './ai-jobs-store'\nimport { AiPageBriefDialog } from './ai-page-brief-dialog.component'\nimport { AiInsightDialog } from './ai-insight-dialog.component'\nimport { AiJobPlan } from './ai-job-plan.component'\nimport { aiJobOutputHref, aiJobPrimaryLink, aiSiteBuildHref } from './ai-job-links'\nimport { aiJobRefundCopy } from '../model/ai-job-failure-copy'\nimport { readEventFrames } from './ai-job-events'\n\n// Where an output opens, and the stream reader, live beside the dialogs that\n// share them (AGL-3593); this module has always exported them.\nexport { aiJobOutputHref, aiJobPrimaryLink, readEventFrames }\n\n/**\n * The AI jobs drawer inside the Assist panel (AGL-2904): the workspace's\n * running and recent generation jobs, each step's progress, an \"open\n * draft\" link per output, and cancel.\n *\n * Reads through the routes, never Firestore directly, so the same\n * membership, flag and entitlement rungs answer every read; progress comes\n * from the events route's server-sent stream, re-opened when the server\n * says `reconnect`. Everything loads on EXPAND rather than on mount: the\n * panel opens on every console page, and a list nobody asked for is a read\n * on every page view.\n *\n * It opens EXPANDED while any of the workspace's jobs is moving or waiting\n * for the person (AGL-3593) — the shared list the top-bar indicator reads\n * says so — because a plan waiting behind a collapsed row is a site that\n * never gets built. An \"Open AI jobs\" anywhere in the console expands it,\n * scrolls to the job it names and highlights it for a moment.\n *\n * Hidden — not disabled — unless the flag shows it AND the plan carries\n * `aiGenerative`: a released-off feature does not exist, and a plan without\n * it is sold the add-on on the Billing page, not here.\n */\n\n/** Jobs the drawer lists; the route caps higher, the drawer is a glance. */\nconst LIST_LIMIT = 10\n\n/** How much of a brief a row shows. */\nconst BRIEF_PREVIEW_CHARS = 90\n\n/**\n * A row's chip says where the job stands in the words every AI surface uses\n * (AGL-3593): a plan waiting to be confirmed is \"Plan ready\", never \"Running\"\n * and never the machine's `needs_review`.\n */\nconst PHASE_COLOR: Record<AiJobPhase, 'default' | 'primary' | 'success' | 'error' | 'warning'> = {\n queued: 'default',\n planning: 'primary',\n 'plan-ready': 'warning',\n building: 'primary',\n attention: 'warning',\n done: 'success',\n failed: 'error',\n canceled: 'default',\n}\n\n/** The header's count chips, colored as the rows they count. */\nconst STATE_COLOR: Record<AiJobActivityState, 'primary' | 'warning'> = {\n 'needs-you': 'warning',\n attention: 'warning',\n running: 'primary',\n}\n\n/** How long a job AI jobs was opened on stays highlighted. */\nconst HIGHLIGHT_MS = 2_500\n\n/**\n * Where a guided start that ended unbuilt is tried again (AGL-3596): its\n * \"Building your site\" page, opened on its own answers (`?retry=1`). Only for\n * a job of the site the console is on, whose subdomain the address names;\n * `null` otherwise.\n */\nexport function aiJobRestartHref(\n job: Pick<AiJobSummary, 'id' | 'kind' | 'status' | 'hostId' | 'siteInputs'>,\n input: { orgSlug: string; hostId?: string | null; pathname: string },\n): string | null {\n if (job.kind !== 'site' || (job.status !== 'failed' && job.status !== 'canceled')) return null\n if (!job.siteInputs || !job.hostId || job.hostId !== input.hostId) return null\n const subdomain = /^\\/[^/]+\\/hosts\\/([^/?#]+)/.exec(input.pathname)?.[1] ?? null\n const href = aiSiteBuildHref(input.orgSlug, subdomain, job.id)\n return href ? `${href}?retry=1` : null\n}\n\n/** What a job cost the person: what it spent, less what we refunded. */\nfunction netCredits(job: Pick<AiJobSummary, 'creditsSpent' | 'refundedCredits'>): number {\n return Math.max(0, (job.creditsSpent ?? 0) - (job.refundedCredits ?? 0))\n}\n\n/**\n * The navigation entry a page job proposes for the page it built (AGL-2907),\n * or `null`. The job writes no menu: the member adds the entry once the page\n * is live.\n */\nexport function aiJobNavigationProposal(output: AiJobOutput): string | null {\n if (output.resource !== 'screen') return null\n const navigation = output.proposal?.['navigation']\n if (!navigation || typeof navigation !== 'object') return null\n const label = (navigation as Record<string, unknown>)['label']\n return typeof label === 'string' && label.trim() ? label.trim() : null\n}\n\n\nexport interface AssistJobsDrawerProps {\n /** The org the panel is scoped to — `undefined` where the page named none. */\n orgId: string | undefined\n org: Partial<AglynOrgBilling> | undefined\n orgReady: boolean\n orgSlug: string\n user: Parameters<typeof authorizedFetch>[0]\n /** The `release_ai_generative` verdict, staff bypass applied (the shell's). */\n visible: boolean\n /**\n * The viewer is staff (AGL-3078): a job that stopped for a broken rule shows\n * them where the refused answer broke it. Who may read a job is unchanged.\n */\n isStaff?: boolean\n /** The site the console page is on, when it is on one: a page is described for a site. */\n hostId?: string | null\n /**\n * The page's insight surface (AGL-2915) — a site's Analytics, Data or CRM\n * Reports page, or the workspace's Data page — with the site's subdomain;\n * `null` elsewhere, where no question about the figures is offered.\n */\n insight?: { surface: Exclude<AiInsightSurface, 'digest'>; host: string | null } | null\n /**\n * The workspace's jobs that are not yet settled, from the shared store the\n * top-bar indicator reads (AGL-3593). The header counts them, and the\n * drawer opens expanded while there is any. Absent, the drawer counts what\n * it loaded itself.\n */\n inFlight?: readonly AiJobSummary[]\n /**\n * The latest request to open AI jobs (AGL-3593): a new `seq` expands the\n * drawer, and a named job is scrolled to and highlighted.\n */\n focus?: AiJobsOpenRequest | null\n}\n\nexport function AssistJobsDrawer({\n orgId,\n org,\n orgReady,\n orgSlug,\n user,\n visible,\n isStaff = false,\n hostId,\n insight,\n inFlight,\n focus,\n}: AssistJobsDrawerProps): JSX.Element | null {\n const entitled = orgReady && checkEntitlement(org as never, 'aiGenerative')\n const [expanded, setExpanded] = useState(false)\n /**\n * The person opened or closed the list themselves: from then on the\n * expanded-by-default rule leaves their choice alone until the workspace\n * changes.\n */\n const toggledRef = useRef(false)\n /** The job AI jobs was opened on, highlighted for a moment once it is listed. */\n const [highlight, setHighlight] = useState<string | null>(null)\n const listRef = useRef<HTMLDivElement | null>(null)\n const [jobs, setJobs] = useState<AiJobSummary[]>([])\n const [loading, setLoading] = useState(false)\n const [notice, setNotice] = useState<string | null>(null)\n /** Whether the page brief dialog is open (AGL-2907). */\n const [describing, setDescribing] = useState(false)\n /**\n * The insight dialog (AGL-2915): `'ask'` for a new question, a job id for an\n * answer a job already wrote, `null` when closed.\n */\n const [insightOpen, setInsightOpen] = useState<string | null>(null)\n /** Job ids whose terminal event has been tracked, so a re-read does not count twice. */\n const trackedRef = useRef(new Set<string>())\n /** The job whose stream is open, so a re-render does not open a second. */\n const watchingRef = useRef<string | null>(null)\n\n const patchJob = useCallback((next: AiJobSummary) => {\n // Every counting surface moves with the row (AGL-3593).\n publishAiJob(next)\n setJobs((prior) => {\n const index = prior.findIndex((job) => job.id === next.id)\n if (index === -1) return [next, ...prior].slice(0, LIST_LIMIT)\n const copy = [...prior]\n copy[index] = next\n return copy\n })\n if (\n AI_JOB_TERMINAL_STATUSES.includes(next.status) &&\n !trackedRef.current.has(next.id)\n ) {\n trackedRef.current.add(next.id)\n if (next.status === 'done') {\n trackEvent('ai_job_completed', { kind: next.kind, credits: next.creditsSpent })\n } else if (next.status === 'failed') {\n trackEvent('ai_job_failed', { kind: next.kind })\n }\n }\n }, [])\n\n const load = useCallback(async () => {\n if (!orgId) return\n setLoading(true)\n setNotice(null)\n try {\n const response = await authorizedFetch(\n user,\n `/api/ai/jobs?orgId=${encodeURIComponent(orgId)}&limit=${LIST_LIMIT}`,\n )\n if (!response.ok) {\n const payload = await response.json().catch(() => null)\n setNotice(String(payload?.error ?? 'The AI jobs could not be loaded — try again.'))\n return\n }\n const payload = (await response.json()) as { jobs: AiJobSummary[] }\n // Every job that arrives already terminal is one the drawer did not\n // watch finish, so its outcome is not this session's to count.\n for (const job of payload.jobs) {\n if (AI_JOB_TERMINAL_STATUSES.includes(job.status)) trackedRef.current.add(job.id)\n // A job the indicator still counts that has settled since leaves it.\n publishAiJob(job)\n }\n setJobs(payload.jobs)\n } catch {\n setNotice('The AI jobs could not be loaded — try again.')\n } finally {\n setLoading(false)\n }\n }, [orgId, user])\n\n useEffect(() => {\n if (expanded) void load()\n }, [expanded, load])\n\n // Reset when the panel's org changes: a list from one workspace must not\n // show under another's key while the new one loads.\n useEffect(() => {\n setJobs([])\n setExpanded(false)\n toggledRef.current = false\n watchingRef.current = null\n }, [orgId])\n\n // Expanded by default while anything is moving or waiting (AGL-3593): a\n // plan waiting to be confirmed behind a collapsed row is a site that never\n // gets built. Otherwise collapsed, which reads nothing until asked.\n const anyInFlight = (inFlight?.length ?? 0) > 0\n useEffect(() => {\n if (anyInFlight && !toggledRef.current) setExpanded(true)\n }, [anyInFlight])\n\n // A request to open AI jobs (AGL-3593): expand, read the list again so a\n // job created a moment ago is in it, and highlight the job named.\n const focusSeq = focus?.seq ?? 0\n const focusJobId = focus?.jobId ?? null\n const expandedRef = useRef(expanded)\n expandedRef.current = expanded\n useEffect(() => {\n if (!focusSeq) return\n toggledRef.current = true\n setHighlight(focusJobId)\n // An open list does not re-run the expand effect's read, so it reads here.\n if (expandedRef.current) void load()\n else setExpanded(true)\n // Only a new request runs this; `load` and the job are read as they stand.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [focusSeq])\n\n // Scroll to the highlighted job once it is listed, then let it fade.\n const highlightListed = highlight !== null && jobs.some((job) => job.id === highlight)\n useEffect(() => {\n if (!highlight || !highlightListed) return undefined\n const row = Array.from(\n listRef.current?.querySelectorAll<HTMLElement>('[data-ai-job-id]') ?? [],\n ).find((element) => element.dataset['aiJobId'] === highlight)\n row?.scrollIntoView?.({ block: 'nearest', behavior: 'smooth' })\n const timer = setTimeout(() => setHighlight(null), HIGHLIGHT_MS)\n return () => clearTimeout(timer)\n }, [highlight, highlightListed])\n\n // Watch the most recent job that is still moving. One stream at a time:\n // the route re-reads a document every two seconds per open stream, and a\n // drawer with three running jobs does not need three of them.\n const watched = jobs.find((job) => !AI_JOB_TERMINAL_STATUSES.includes(job.status))\n const watchedId = watched?.id ?? null\n useEffect(() => {\n if (!expanded || !orgId || !watchedId || watchingRef.current === watchedId) return\n watchingRef.current = watchedId\n const controller = new AbortController()\n const watch = async () => {\n // The server closes a stream at its deadline with `reconnect`; the\n // loop here re-opens it until the job settles or the drawer unmounts.\n let again = true\n while (again && !controller.signal.aborted) {\n again = false\n try {\n const response = await authorizedFetch(\n user,\n `/api/ai/jobs/${encodeURIComponent(watchedId)}/events?orgId=${encodeURIComponent(orgId)}`,\n { signal: controller.signal },\n )\n if (!response.ok || !response.body) return\n await readEventFrames(response.body, (event) => {\n if (event['type'] === 'state') patchJob(event['job'] as AiJobSummary)\n else if (event['type'] === 'reconnect') again = true\n else if (event['type'] === 'gone') {\n setJobs((prior) => prior.filter((job) => job.id !== watchedId))\n }\n })\n } catch {\n // The stream ended without a terminal state — a network blip or\n // the drawer closing. The next expand reloads the list.\n return\n }\n }\n }\n void watch().finally(() => {\n if (watchingRef.current === watchedId) watchingRef.current = null\n })\n return () => {\n controller.abort()\n if (watchingRef.current === watchedId) watchingRef.current = null\n }\n }, [expanded, orgId, watchedId, user, patchJob])\n\n // The same door the dialog that started the job cancels through (AGL-3593).\n const cancel = useCallback(\n async (jobId: string) => {\n if (!orgId) return\n const { job, error } = await cancelAiJobRequest(user, orgId, jobId)\n if (error) {\n setNotice(error)\n return\n }\n if (job) patchJob(job)\n },\n [orgId, user, patchJob],\n )\n\n /** The job whose resume is in flight, so its button cannot send twice. */\n const [resuming, setResuming] = useState<string | null>(null)\n\n // Confirms a plan, or tries again a step whose answer broke a building\n // rule (AGL-2935). The door runs the next step inline and answers with the\n // job, so the row moves on without waiting for the stream.\n const resume = useCallback(\n async (job: AiJobSummary) => {\n if (!orgId) return\n setResuming(job.id)\n setNotice(null)\n // The same door the dialog that started the job confirms through (AGL-3593).\n const { job: next, error } = await resumeAiJobRequest(user, orgId, job)\n if (next) patchJob(next)\n if (error) setNotice(error)\n setResuming(null)\n },\n [orgId, user, patchJob],\n )\n\n if (!visible || !orgId || !entitled) return null\n\n // Counted by state, never as one \"running\" figure (AGL-3593): a plan waiting\n // to be confirmed needs the person, and a stopped job is not moving.\n const chips = aiJobsHeaderChips(aiJobActivityCounts(inFlight ?? jobs))\n\n return (\n <Box sx={{ mb: 2, borderBottom: 1, borderColor: 'divider', pb: 1 }}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography variant=\"subtitle2\" sx={{ flexGrow: 1 }}>\n AI jobs\n {chips.map((chip) => (\n <Chip\n key={chip.state}\n size=\"small\"\n color={STATE_COLOR[chip.state]}\n label={chip.label}\n sx={{ ml: 1 }}\n />\n ))}\n </Typography>\n {/* A question about the page's figures (AGL-2915). */}\n {insight && (\n <Button size=\"small\" onClick={() => setInsightOpen('ask')}>\n Ask about your numbers\n </Button>\n )}\n {/* A page from a brief (AGL-2907), on a site's own routes. */}\n {hostId && (\n <Button size=\"small\" onClick={() => setDescribing(true)}>\n Describe a page\n </Button>\n )}\n <IconButton\n size=\"small\"\n aria-label={expanded ? 'Hide AI jobs' : 'Show AI jobs'}\n aria-expanded={expanded}\n onClick={() => {\n toggledRef.current = true\n setExpanded((prior) => !prior)\n }}\n >\n <MdiIcon\n path={expanded ? mdiChevronUp.path : mdiChevronDown.path}\n sx={{ fontSize: 18 }}\n />\n </IconButton>\n </Stack>\n <Collapse in={expanded} unmountOnExit>\n {notice && (\n <Typography variant=\"caption\" color=\"error\" component=\"div\" sx={{ mt: 0.5 }}>\n {notice}\n </Typography>\n )}\n {loading && !jobs.length && (\n <CircularProgress size={16} sx={{ mt: 1 }} aria-label=\"Loading AI jobs\" />\n )}\n {!loading && !jobs.length && !notice && (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\" sx={{ mt: 0.5 }}>\n No AI jobs yet.\n </Typography>\n )}\n <Stack ref={listRef} spacing={1} sx={{ mt: 1 }} role=\"list\" aria-label=\"AI jobs\">\n {jobs.map((job) => {\n const restartHref = (row: AiJobSummary) =>\n aiJobRestartHref(row, {\n orgSlug,\n hostId,\n pathname: typeof window === 'undefined' ? '' : window.location.pathname,\n })\n const stepsDone = job.steps.filter((step) => step.status === 'done').length\n const current = job.steps.find((step) => step.status === 'running')\n const terminal = AI_JOB_TERMINAL_STATUSES.includes(job.status)\n const phase = aiJobPhase(job)\n const primary = aiJobPrimaryLink(job, orgSlug)\n const highlighted = highlight === job.id\n return (\n <Box\n key={job.id}\n role=\"listitem\"\n data-ai-job-id={job.id}\n aria-current={highlighted ? 'true' : undefined}\n sx={{\n borderRadius: 1,\n bgcolor: highlighted ? 'action.selected' : 'action.hover',\n outline: 2,\n outlineColor: highlighted ? 'primary.main' : 'transparent',\n transition: (theme) =>\n theme.transitions.create(['background-color', 'outline-color'], {\n duration: theme.transitions.duration.standard,\n }),\n px: 1.5,\n py: 1,\n }}\n >\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Chip size=\"small\" variant=\"outlined\" label={job.kind} />\n <Chip size=\"small\" color={PHASE_COLOR[phase]} label={AI_JOB_PHASE_LABELS[phase]} />\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ flexGrow: 1 }}>\n {stepsDone}/{job.steps.length} steps\n {current ? ` — ${current.name}` : ''}\n {/* Net of what a failure on our side gave back (AGL-3594). */}\n {netCredits(job) > 0 ? ` · ${netCredits(job)} credits` : ''}\n </Typography>\n {!terminal && (\n <Button size=\"small\" onClick={() => void cancel(job.id)}>\n Cancel\n </Button>\n )}\n </Stack>\n <Typography variant=\"body2\" sx={{ mt: 0.5, wordBreak: 'break-word' }}>\n {job.brief.length > BRIEF_PREVIEW_CHARS\n ? `${job.brief.slice(0, BRIEF_PREVIEW_CHARS)}…`\n : job.brief}\n </Typography>\n {job.error && (\n <Typography variant=\"caption\" color={job.status === 'failed' ? 'error' : 'warning.main'} component=\"div\">\n {job.error}\n </Typography>\n )}\n {/* What became of its credits, from the job's recorded give-back (AGL-3596). */}\n {aiJobRefundCopy(job) && (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\">\n {aiJobRefundCopy(job)}\n </Typography>\n )}\n {restartHref(job) ? (\n <Button size=\"small\" variant=\"contained\" component={AppLink} href={restartHref(job) as string} sx={{ mt: 0.5 }}>\n {'Try again'}\n </Button>\n ) : null}\n {/* What a finished job built, first (AGL-3593). */}\n {primary ? (\n <Button\n size=\"small\"\n variant=\"contained\"\n component={AppLink}\n href={primary.href}\n sx={{ mt: 0.5 }}\n >\n {primary.label}\n </Button>\n ) : null}\n {job.outputs.map((output, index) => {\n const href = aiJobOutputHref(output, orgSlug)\n const navigation = aiJobNavigationProposal(output)\n return (\n <Box key={`${output.resource}:${output.id}:${index}`} sx={{ mt: 0.5 }}>\n {output.resource === 'insight' ? (\n <Button size=\"small\" onClick={() => setInsightOpen(output.id)}>\n View answer\n </Button>\n ) : href ? (\n <AppLink componentVariant=\"naked\" href={href}>\n Open draft — {output.label}\n </AppLink>\n ) : output.text ? (\n <Typography\n variant=\"body2\"\n component=\"pre\"\n sx={{ whiteSpace: 'pre-wrap', fontFamily: 'inherit', m: 0 }}\n >\n {output.text}\n </Typography>\n ) : (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {output.label}\n </Typography>\n )}\n {output.load ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\">\n About {formatBytes(output.load.totalBytes)} on a first visit\n </Typography>\n ) : null}\n {output.note ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\">\n {output.note}\n </Typography>\n ) : null}\n {navigation ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\">\n Add “{navigation}” to your navigation once the page is live.\n </Typography>\n ) : null}\n </Box>\n )\n })}\n <AiJobPlan\n job={job}\n onResume={(target) => void resume(target)}\n busy={resuming === job.id}\n staff={isStaff}\n user={user}\n />\n </Box>\n )\n })}\n </Stack>\n </Collapse>\n {/*\n The brief dialog (AGL-2907). It starts a job and closes; the list\n below it is the only place the job is watched, so an open list reads\n the new job back as soon as the dialog hands it over.\n */}\n {insightOpen !== null && (\n <AiInsightDialog\n open\n onClose={() => {\n setInsightOpen(null)\n if (expanded) void load()\n }}\n orgId={orgId}\n orgSlug={orgSlug}\n hostId={insight?.host ? (hostId ?? null) : null}\n host={insight?.host ?? null}\n surface={insight?.surface ?? 'analytics'}\n user={user}\n uid={(user as { uid?: string } | null | undefined)?.uid ?? null}\n jobId={insightOpen === 'ask' ? null : insightOpen}\n />\n )}\n {hostId && (\n <AiPageBriefDialog\n open={describing}\n onClose={() => {\n setDescribing(false)\n if (expanded) void load()\n }}\n orgId={orgId}\n hostId={hostId}\n user={user}\n orgSlug={orgSlug}\n isStaff={isStaff}\n />\n )}\n </Box>\n )\n}\n\nexport default AssistJobsDrawer\n"],"names":["checkEntitlement","trackEvent","formatBytes","AI_JOB_TERMINAL_STATUSES","mdiChevronDown","mdiChevronUp","AppLink","MdiIcon","authorizedFetch","Box","Button","Chip","CircularProgress","Collapse","IconButton","Stack","Typography","useCallback","useEffect","useRef","useState","AI_JOB_PHASE_LABELS","aiJobActivityCounts","aiJobPhase","aiJobsHeaderChips","cancelAiJobRequest","resumeAiJobRequest","publishAiJob","AiPageBriefDialog","AiInsightDialog","AiJobPlan","aiJobOutputHref","aiJobPrimaryLink","aiSiteBuildHref","aiJobRefundCopy","readEventFrames","LIST_LIMIT","BRIEF_PREVIEW_CHARS","PHASE_COLOR","queued","planning","building","attention","done","failed","canceled","STATE_COLOR","running","HIGHLIGHT_MS","aiJobRestartHref","job","input","kind","status","siteInputs","hostId","subdomain","exec","pathname","href","orgSlug","id","netCredits","Math","max","creditsSpent","refundedCredits","aiJobNavigationProposal","output","resource","navigation","proposal","label","trim","AssistJobsDrawer","orgId","org","orgReady","user","visible","isStaff","insight","inFlight","focus","entitled","expanded","setExpanded","toggledRef","highlight","setHighlight","listRef","jobs","setJobs","loading","setLoading","notice","setNotice","describing","setDescribing","insightOpen","setInsightOpen","trackedRef","Set","watchingRef","patchJob","next","prior","index","findIndex","slice","copy","includes","current","has","add","credits","load","response","encodeURIComponent","ok","payload","json","catch","String","error","anyInFlight","length","focusSeq","seq","focusJobId","jobId","expandedRef","highlightListed","some","row","undefined","Array","from","querySelectorAll","find","element","dataset","scrollIntoView","block","behavior","timer","setTimeout","clearTimeout","watched","watchedId","controller","AbortController","watch","again","signal","aborted","body","event","filter","finally","abort","cancel","resuming","setResuming","resume","chips","sx","mb","borderBottom","borderColor","pb","direction","spacing","alignItems","variant","flexGrow","map","chip","size","color","state","ml","onClick","aria-label","aria-expanded","path","fontSize","in","unmountOnExit","component","mt","ref","role","restartHref","window","location","stepsDone","steps","step","terminal","phase","primary","highlighted","data-ai-job-id","aria-current","borderRadius","bgcolor","outline","outlineColor","transition","theme","transitions","create","duration","standard","px","py","name","wordBreak","brief","outputs","componentVariant","text","whiteSpace","fontFamily","m","totalBytes","note","onResume","target","busy","staff","open","onClose","host","surface","uid"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/assist-jobs-drawer.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { checkEntitlement } from '@aglyn/aglyn'\nimport { trackEvent } from '@aglyn/aglyn/app-utils/analytics-events'\nimport { formatBytes } from '@aglyn/aglyn/app-utils/measure-node-map'\nimport {\n AI_JOB_TERMINAL_STATUSES,\n type AiJobOutput,\n type AiJobSummary,\n} from '../model/ai-jobs.types'\nimport type { AglynOrgBilling } from '@aglyn/aglyn/foundation/definitions/org-billing.types'\nimport { mdiChevronDown, mdiChevronUp } from '@aglyn/shared-data-mdi'\nimport { AppLink, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport {\n Box,\n Button,\n Chip,\n CircularProgress,\n Collapse,\n IconButton,\n Stack,\n Typography,\n} from '@mui/material'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport {\n AI_JOB_PHASE_LABELS,\n aiJobActivityCounts,\n aiJobPhase,\n aiJobsHeaderChips,\n type AiJobActivityState,\n type AiJobPhase,\n} from '../model/ai-job-activity'\nimport type { AiInsightSurface } from '../model/ai-insight'\nimport { cancelAiJobRequest, resumeAiJobRequest, type AiJobResumeOptions } from './ai-job-requests'\nimport { aiBuildCanRetry, aiBuildItemRows, aiSitePartialCopy } from '../model/ai-build-progress'\nimport { publishAiJob, type AiJobsOpenRequest } from './ai-jobs-store'\nimport { AiPageBriefDialog } from './ai-page-brief-dialog.component'\nimport { AiInsightDialog } from './ai-insight-dialog.component'\nimport { AiJobPlan } from './ai-job-plan.component'\nimport { aiJobOutputHref, aiJobPrimaryLink, aiSiteBuildHref } from './ai-job-links'\nimport { aiJobRefundCopy } from '../model/ai-job-failure-copy'\nimport { readEventFrames } from './ai-job-events'\n\n// Where an output opens, and the stream reader, live beside the dialogs that\n// share them (AGL-3593); this module has always exported them.\nexport { aiJobOutputHref, aiJobPrimaryLink, readEventFrames }\n\n/**\n * The AI jobs drawer inside the Assist panel (AGL-2904): the workspace's\n * running and recent generation jobs, each step's progress, an \"open\n * draft\" link per output, and cancel.\n *\n * Reads through the routes, never Firestore directly, so the same\n * membership, flag and entitlement rungs answer every read; progress comes\n * from the events route's server-sent stream, re-opened when the server\n * says `reconnect`. Everything loads on EXPAND rather than on mount: the\n * panel opens on every console page, and a list nobody asked for is a read\n * on every page view.\n *\n * It opens EXPANDED while any of the workspace's jobs is moving or waiting\n * for the person (AGL-3593) — the shared list the top-bar indicator reads\n * says so — because a plan waiting behind a collapsed row is a site that\n * never gets built. An \"Open AI jobs\" anywhere in the console expands it,\n * scrolls to the job it names and highlights it for a moment.\n *\n * Hidden — not disabled — unless the flag shows it AND the plan carries\n * `aiGenerative`: a released-off feature does not exist, and a plan without\n * it is sold the add-on on the Billing page, not here.\n */\n\n/** Jobs the drawer lists; the route caps higher, the drawer is a glance. */\nconst LIST_LIMIT = 10\n\n/** How much of a brief a row shows. */\nconst BRIEF_PREVIEW_CHARS = 90\n\n/**\n * A row's chip says where the job stands in the words every AI surface uses\n * (AGL-3593): a plan waiting to be confirmed is \"Plan ready\", never \"Running\"\n * and never the machine's `needs_review`.\n */\nconst PHASE_COLOR: Record<AiJobPhase, 'default' | 'primary' | 'success' | 'error' | 'warning'> = {\n queued: 'default',\n planning: 'primary',\n 'plan-ready': 'warning',\n building: 'primary',\n attention: 'warning',\n done: 'success',\n failed: 'error',\n canceled: 'default',\n}\n\n/** The header's count chips, colored as the rows they count. */\nconst STATE_COLOR: Record<AiJobActivityState, 'primary' | 'warning'> = {\n 'needs-you': 'warning',\n attention: 'warning',\n running: 'primary',\n}\n\n/** What each item state reads as in a row (AGL-3616). */\nconst ITEM_STATE_LABELS = {\n done: 'built',\n active: 'building',\n waiting: 'waiting',\n failed: 'failed',\n skipped: 'not built',\n} as const\n\n/** How long a job AI jobs was opened on stays highlighted. */\nconst HIGHLIGHT_MS = 2_500\n\n/**\n * Where a guided start that ended unbuilt is tried again (AGL-3596): its\n * \"Building your site\" page, opened on its own answers (`?retry=1`). Only for\n * a job of the site the console is on, whose subdomain the address names;\n * `null` otherwise.\n */\nexport function aiJobRestartHref(\n job: Pick<AiJobSummary, 'id' | 'kind' | 'status' | 'hostId' | 'siteInputs'>,\n input: { orgSlug: string; hostId?: string | null; pathname: string },\n): string | null {\n if (job.kind !== 'site' || (job.status !== 'failed' && job.status !== 'canceled')) return null\n if (!job.siteInputs || !job.hostId || job.hostId !== input.hostId) return null\n const subdomain = /^\\/[^/]+\\/hosts\\/([^/?#]+)/.exec(input.pathname)?.[1] ?? null\n const href = aiSiteBuildHref(input.orgSlug, subdomain, job.id)\n return href ? `${href}?retry=1` : null\n}\n\n/** What a job cost the person: what it spent, less what we refunded. */\nfunction netCredits(job: Pick<AiJobSummary, 'creditsSpent' | 'refundedCredits'>): number {\n return Math.max(0, (job.creditsSpent ?? 0) - (job.refundedCredits ?? 0))\n}\n\n/**\n * The navigation entry a page job proposes for the page it built (AGL-2907),\n * or `null`. The job writes no menu: the member adds the entry once the page\n * is live.\n */\nexport function aiJobNavigationProposal(output: AiJobOutput): string | null {\n if (output.resource !== 'screen') return null\n const navigation = output.proposal?.['navigation']\n if (!navigation || typeof navigation !== 'object') return null\n const label = (navigation as Record<string, unknown>)['label']\n return typeof label === 'string' && label.trim() ? label.trim() : null\n}\n\n\nexport interface AssistJobsDrawerProps {\n /** The org the panel is scoped to — `undefined` where the page named none. */\n orgId: string | undefined\n org: Partial<AglynOrgBilling> | undefined\n orgReady: boolean\n orgSlug: string\n user: Parameters<typeof authorizedFetch>[0]\n /** The `release_ai_generative` verdict, staff bypass applied (the shell's). */\n visible: boolean\n /**\n * The viewer is staff (AGL-3078): a job that stopped for a broken rule shows\n * them where the refused answer broke it. Who may read a job is unchanged.\n */\n isStaff?: boolean\n /** The site the console page is on, when it is on one: a page is described for a site. */\n hostId?: string | null\n /**\n * The page's insight surface (AGL-2915) — a site's Analytics, Data or CRM\n * Reports page, or the workspace's Data page — with the site's subdomain;\n * `null` elsewhere, where no question about the figures is offered.\n */\n insight?: { surface: Exclude<AiInsightSurface, 'digest'>; host: string | null } | null\n /**\n * The workspace's jobs that are not yet settled, from the shared store the\n * top-bar indicator reads (AGL-3593). The header counts them, and the\n * drawer opens expanded while there is any. Absent, the drawer counts what\n * it loaded itself.\n */\n inFlight?: readonly AiJobSummary[]\n /**\n * The latest request to open AI jobs (AGL-3593): a new `seq` expands the\n * drawer, and a named job is scrolled to and highlighted.\n */\n focus?: AiJobsOpenRequest | null\n}\n\nexport function AssistJobsDrawer({\n orgId,\n org,\n orgReady,\n orgSlug,\n user,\n visible,\n isStaff = false,\n hostId,\n insight,\n inFlight,\n focus,\n}: AssistJobsDrawerProps): JSX.Element | null {\n const entitled = orgReady && checkEntitlement(org as never, 'aiGenerative')\n const [expanded, setExpanded] = useState(false)\n /**\n * The person opened or closed the list themselves: from then on the\n * expanded-by-default rule leaves their choice alone until the workspace\n * changes.\n */\n const toggledRef = useRef(false)\n /** The job AI jobs was opened on, highlighted for a moment once it is listed. */\n const [highlight, setHighlight] = useState<string | null>(null)\n const listRef = useRef<HTMLDivElement | null>(null)\n const [jobs, setJobs] = useState<AiJobSummary[]>([])\n const [loading, setLoading] = useState(false)\n const [notice, setNotice] = useState<string | null>(null)\n /** Whether the page brief dialog is open (AGL-2907). */\n const [describing, setDescribing] = useState(false)\n /**\n * The insight dialog (AGL-2915): `'ask'` for a new question, a job id for an\n * answer a job already wrote, `null` when closed.\n */\n const [insightOpen, setInsightOpen] = useState<string | null>(null)\n /** Job ids whose terminal event has been tracked, so a re-read does not count twice. */\n const trackedRef = useRef(new Set<string>())\n /** The job whose stream is open, so a re-render does not open a second. */\n const watchingRef = useRef<string | null>(null)\n\n const patchJob = useCallback((next: AiJobSummary) => {\n // Every counting surface moves with the row (AGL-3593).\n publishAiJob(next)\n setJobs((prior) => {\n const index = prior.findIndex((job) => job.id === next.id)\n if (index === -1) return [next, ...prior].slice(0, LIST_LIMIT)\n const copy = [...prior]\n copy[index] = next\n return copy\n })\n if (\n AI_JOB_TERMINAL_STATUSES.includes(next.status) &&\n !trackedRef.current.has(next.id)\n ) {\n trackedRef.current.add(next.id)\n if (next.status === 'done') {\n trackEvent('ai_job_completed', { kind: next.kind, credits: next.creditsSpent })\n } else if (next.status === 'failed') {\n trackEvent('ai_job_failed', { kind: next.kind })\n }\n }\n }, [])\n\n const load = useCallback(async () => {\n if (!orgId) return\n setLoading(true)\n setNotice(null)\n try {\n const response = await authorizedFetch(\n user,\n `/api/ai/jobs?orgId=${encodeURIComponent(orgId)}&limit=${LIST_LIMIT}`,\n )\n if (!response.ok) {\n const payload = await response.json().catch(() => null)\n setNotice(String(payload?.error ?? 'The AI jobs could not be loaded — try again.'))\n return\n }\n const payload = (await response.json()) as { jobs: AiJobSummary[] }\n // Every job that arrives already terminal is one the drawer did not\n // watch finish, so its outcome is not this session's to count.\n for (const job of payload.jobs) {\n if (AI_JOB_TERMINAL_STATUSES.includes(job.status)) trackedRef.current.add(job.id)\n // A job the indicator still counts that has settled since leaves it.\n publishAiJob(job)\n }\n setJobs(payload.jobs)\n } catch {\n setNotice('The AI jobs could not be loaded — try again.')\n } finally {\n setLoading(false)\n }\n }, [orgId, user])\n\n useEffect(() => {\n if (expanded) void load()\n }, [expanded, load])\n\n // Reset when the panel's org changes: a list from one workspace must not\n // show under another's key while the new one loads.\n useEffect(() => {\n setJobs([])\n setExpanded(false)\n toggledRef.current = false\n watchingRef.current = null\n }, [orgId])\n\n // Expanded by default while anything is moving or waiting (AGL-3593): a\n // plan waiting to be confirmed behind a collapsed row is a site that never\n // gets built. Otherwise collapsed, which reads nothing until asked.\n const anyInFlight = (inFlight?.length ?? 0) > 0\n useEffect(() => {\n if (anyInFlight && !toggledRef.current) setExpanded(true)\n }, [anyInFlight])\n\n // A request to open AI jobs (AGL-3593): expand, read the list again so a\n // job created a moment ago is in it, and highlight the job named.\n const focusSeq = focus?.seq ?? 0\n const focusJobId = focus?.jobId ?? null\n const expandedRef = useRef(expanded)\n expandedRef.current = expanded\n useEffect(() => {\n if (!focusSeq) return\n toggledRef.current = true\n setHighlight(focusJobId)\n // An open list does not re-run the expand effect's read, so it reads here.\n if (expandedRef.current) void load()\n else setExpanded(true)\n // Only a new request runs this; `load` and the job are read as they stand.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [focusSeq])\n\n // Scroll to the highlighted job once it is listed, then let it fade.\n const highlightListed = highlight !== null && jobs.some((job) => job.id === highlight)\n useEffect(() => {\n if (!highlight || !highlightListed) return undefined\n const row = Array.from(\n listRef.current?.querySelectorAll<HTMLElement>('[data-ai-job-id]') ?? [],\n ).find((element) => element.dataset['aiJobId'] === highlight)\n row?.scrollIntoView?.({ block: 'nearest', behavior: 'smooth' })\n const timer = setTimeout(() => setHighlight(null), HIGHLIGHT_MS)\n return () => clearTimeout(timer)\n }, [highlight, highlightListed])\n\n // Watch the most recent job that is still moving. One stream at a time:\n // the route re-reads a document every two seconds per open stream, and a\n // drawer with three running jobs does not need three of them.\n const watched = jobs.find((job) => !AI_JOB_TERMINAL_STATUSES.includes(job.status))\n const watchedId = watched?.id ?? null\n useEffect(() => {\n if (!expanded || !orgId || !watchedId || watchingRef.current === watchedId) return\n watchingRef.current = watchedId\n const controller = new AbortController()\n const watch = async () => {\n // The server closes a stream at its deadline with `reconnect`; the\n // loop here re-opens it until the job settles or the drawer unmounts.\n let again = true\n while (again && !controller.signal.aborted) {\n again = false\n try {\n const response = await authorizedFetch(\n user,\n `/api/ai/jobs/${encodeURIComponent(watchedId)}/events?orgId=${encodeURIComponent(orgId)}`,\n { signal: controller.signal },\n )\n if (!response.ok || !response.body) return\n await readEventFrames(response.body, (event) => {\n if (event['type'] === 'state') patchJob(event['job'] as AiJobSummary)\n else if (event['type'] === 'reconnect') again = true\n else if (event['type'] === 'gone') {\n setJobs((prior) => prior.filter((job) => job.id !== watchedId))\n }\n })\n } catch {\n // The stream ended without a terminal state — a network blip or\n // the drawer closing. The next expand reloads the list.\n return\n }\n }\n }\n void watch().finally(() => {\n if (watchingRef.current === watchedId) watchingRef.current = null\n })\n return () => {\n controller.abort()\n if (watchingRef.current === watchedId) watchingRef.current = null\n }\n }, [expanded, orgId, watchedId, user, patchJob])\n\n // The same door the dialog that started the job cancels through (AGL-3593).\n const cancel = useCallback(\n async (jobId: string) => {\n if (!orgId) return\n const { job, error } = await cancelAiJobRequest(user, orgId, jobId)\n if (error) {\n setNotice(error)\n return\n }\n if (job) patchJob(job)\n },\n [orgId, user, patchJob],\n )\n\n /** The job whose resume is in flight, so its button cannot send twice. */\n const [resuming, setResuming] = useState<string | null>(null)\n\n // Confirms a plan, or tries again a step whose answer broke a building\n // rule (AGL-2935). The door runs the next step inline and answers with the\n // job, so the row moves on without waiting for the stream.\n const resume = useCallback(\n async (job: AiJobSummary, options?: AiJobResumeOptions) => {\n if (!orgId) return\n setResuming(job.id)\n setNotice(null)\n // The same door the dialog that started the job confirms through (AGL-3593).\n const { job: next, error } = await resumeAiJobRequest(user, orgId, job, options)\n if (next) patchJob(next)\n if (error) setNotice(error)\n setResuming(null)\n },\n [orgId, user, patchJob],\n )\n\n if (!visible || !orgId || !entitled) return null\n\n // Counted by state, never as one \"running\" figure (AGL-3593): a plan waiting\n // to be confirmed needs the person, and a stopped job is not moving.\n const chips = aiJobsHeaderChips(aiJobActivityCounts(inFlight ?? jobs))\n\n return (\n <Box sx={{ mb: 2, borderBottom: 1, borderColor: 'divider', pb: 1 }}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography variant=\"subtitle2\" sx={{ flexGrow: 1 }}>\n AI jobs\n {chips.map((chip) => (\n <Chip\n key={chip.state}\n size=\"small\"\n color={STATE_COLOR[chip.state]}\n label={chip.label}\n sx={{ ml: 1 }}\n />\n ))}\n </Typography>\n {/* A question about the page's figures (AGL-2915). */}\n {insight && (\n <Button size=\"small\" onClick={() => setInsightOpen('ask')}>\n Ask about your numbers\n </Button>\n )}\n {/* A page from a brief (AGL-2907), on a site's own routes. */}\n {hostId && (\n <Button size=\"small\" onClick={() => setDescribing(true)}>\n Describe a page\n </Button>\n )}\n <IconButton\n size=\"small\"\n aria-label={expanded ? 'Hide AI jobs' : 'Show AI jobs'}\n aria-expanded={expanded}\n onClick={() => {\n toggledRef.current = true\n setExpanded((prior) => !prior)\n }}\n >\n <MdiIcon\n path={expanded ? mdiChevronUp.path : mdiChevronDown.path}\n sx={{ fontSize: 18 }}\n />\n </IconButton>\n </Stack>\n <Collapse in={expanded} unmountOnExit>\n {notice && (\n <Typography variant=\"caption\" color=\"error\" component=\"div\" sx={{ mt: 0.5 }}>\n {notice}\n </Typography>\n )}\n {loading && !jobs.length && (\n <CircularProgress size={16} sx={{ mt: 1 }} aria-label=\"Loading AI jobs\" />\n )}\n {!loading && !jobs.length && !notice && (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\" sx={{ mt: 0.5 }}>\n No AI jobs yet.\n </Typography>\n )}\n <Stack ref={listRef} spacing={1} sx={{ mt: 1 }} role=\"list\" aria-label=\"AI jobs\">\n {jobs.map((job) => {\n const restartHref = (row: AiJobSummary) =>\n aiJobRestartHref(row, {\n orgSlug,\n hostId,\n pathname: typeof window === 'undefined' ? '' : window.location.pathname,\n })\n const stepsDone = job.steps.filter((step) => step.status === 'done').length\n const current = job.steps.find((step) => step.status === 'running')\n const terminal = AI_JOB_TERMINAL_STATUSES.includes(job.status)\n const phase = aiJobPhase(job)\n const primary = aiJobPrimaryLink(job, orgSlug)\n const highlighted = highlight === job.id\n return (\n <Box\n key={job.id}\n role=\"listitem\"\n data-ai-job-id={job.id}\n aria-current={highlighted ? 'true' : undefined}\n sx={{\n borderRadius: 1,\n bgcolor: highlighted ? 'action.selected' : 'action.hover',\n outline: 2,\n outlineColor: highlighted ? 'primary.main' : 'transparent',\n transition: (theme) =>\n theme.transitions.create(['background-color', 'outline-color'], {\n duration: theme.transitions.duration.standard,\n }),\n px: 1.5,\n py: 1,\n }}\n >\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Chip size=\"small\" variant=\"outlined\" label={job.kind} />\n <Chip size=\"small\" color={PHASE_COLOR[phase]} label={AI_JOB_PHASE_LABELS[phase]} />\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ flexGrow: 1 }}>\n {stepsDone}/{job.steps.length} steps\n {current ? ` — ${current.name}` : ''}\n {/* Net of what a failure on our side gave back (AGL-3594). */}\n {netCredits(job) > 0 ? ` · ${netCredits(job)} credits` : ''}\n </Typography>\n {!terminal && (\n <Button size=\"small\" onClick={() => void cancel(job.id)}>\n Cancel\n </Button>\n )}\n </Stack>\n <Typography variant=\"body2\" sx={{ mt: 0.5, wordBreak: 'break-word' }}>\n {job.brief.length > BRIEF_PREVIEW_CHARS\n ? `${job.brief.slice(0, BRIEF_PREVIEW_CHARS)}…`\n : job.brief}\n </Typography>\n {job.error && (\n <Typography variant=\"caption\" color={job.status === 'failed' ? 'error' : 'warning.main'} component=\"div\">\n {job.error}\n </Typography>\n )}\n {/* What became of its credits, from the job's recorded give-back (AGL-3596). */}\n {aiJobRefundCopy(job) && (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\">\n {aiJobRefundCopy(job)}\n </Typography>\n )}\n {/* A site that built part of itself says what, and that the rest was on us (AGL-3616). */}\n {aiSitePartialCopy(job) && (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\">\n {aiSitePartialCopy(job)}\n </Typography>\n )}\n {/* A build, item by item: where each stands, and what became of its credits (AGL-3616). */}\n {job.items?.length ? (\n <Box component=\"ul\" aria-label=\"Items\" sx={{ m: 0, mt: 0.5, pl: 2 }}>\n {aiBuildItemRows(job).map((row) => (\n <Typography key={row.slot} component=\"li\" variant=\"caption\" data-item-state={row.state}>\n {`${row.label} — ${ITEM_STATE_LABELS[row.state]}`}\n {row.detail ? `. ${row.detail}` : ''}\n </Typography>\n ))}\n </Box>\n ) : null}\n {aiBuildCanRetry(job) ? (\n <Button\n size=\"small\"\n variant=\"contained\"\n disabled={resuming === job.id}\n onClick={() => void resume(job, { retry: 'failed-items' })}\n sx={{ mt: 0.5 }}\n >\n {'Try again what failed'}\n </Button>\n ) : null}\n {restartHref(job) ? (\n <Button size=\"small\" variant=\"contained\" component={AppLink} href={restartHref(job) as string} sx={{ mt: 0.5 }}>\n {'Try again'}\n </Button>\n ) : null}\n {/* What a finished job built, first (AGL-3593). */}\n {primary ? (\n <Button\n size=\"small\"\n variant=\"contained\"\n component={AppLink}\n href={primary.href}\n sx={{ mt: 0.5 }}\n >\n {primary.label}\n </Button>\n ) : null}\n {job.outputs.map((output, index) => {\n const href = aiJobOutputHref(output, orgSlug)\n const navigation = aiJobNavigationProposal(output)\n return (\n <Box key={`${output.resource}:${output.id}:${index}`} sx={{ mt: 0.5 }}>\n {output.resource === 'insight' ? (\n <Button size=\"small\" onClick={() => setInsightOpen(output.id)}>\n View answer\n </Button>\n ) : href ? (\n <AppLink componentVariant=\"naked\" href={href}>\n Open draft — {output.label}\n </AppLink>\n ) : output.text ? (\n <Typography\n variant=\"body2\"\n component=\"pre\"\n sx={{ whiteSpace: 'pre-wrap', fontFamily: 'inherit', m: 0 }}\n >\n {output.text}\n </Typography>\n ) : (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {output.label}\n </Typography>\n )}\n {output.load ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\">\n About {formatBytes(output.load.totalBytes)} on a first visit\n </Typography>\n ) : null}\n {output.note ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\">\n {output.note}\n </Typography>\n ) : null}\n {navigation ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\">\n Add “{navigation}” to your navigation once the page is live.\n </Typography>\n ) : null}\n </Box>\n )\n })}\n <AiJobPlan\n job={job}\n onResume={(target, options) => void resume(target, options)}\n busy={resuming === job.id}\n staff={isStaff}\n user={user}\n />\n </Box>\n )\n })}\n </Stack>\n </Collapse>\n {/*\n The brief dialog (AGL-2907). It starts a job and closes; the list\n below it is the only place the job is watched, so an open list reads\n the new job back as soon as the dialog hands it over.\n */}\n {insightOpen !== null && (\n <AiInsightDialog\n open\n onClose={() => {\n setInsightOpen(null)\n if (expanded) void load()\n }}\n orgId={orgId}\n orgSlug={orgSlug}\n hostId={insight?.host ? (hostId ?? null) : null}\n host={insight?.host ?? null}\n surface={insight?.surface ?? 'analytics'}\n user={user}\n uid={(user as { uid?: string } | null | undefined)?.uid ?? null}\n jobId={insightOpen === 'ask' ? null : insightOpen}\n />\n )}\n {hostId && (\n <AiPageBriefDialog\n open={describing}\n onClose={() => {\n setDescribing(false)\n if (expanded) void load()\n }}\n orgId={orgId}\n hostId={hostId}\n user={user}\n orgSlug={orgSlug}\n isStaff={isStaff}\n />\n )}\n </Box>\n )\n}\n\nexport default AssistJobsDrawer\n"],"names":["checkEntitlement","trackEvent","formatBytes","AI_JOB_TERMINAL_STATUSES","mdiChevronDown","mdiChevronUp","AppLink","MdiIcon","authorizedFetch","Box","Button","Chip","CircularProgress","Collapse","IconButton","Stack","Typography","useCallback","useEffect","useRef","useState","AI_JOB_PHASE_LABELS","aiJobActivityCounts","aiJobPhase","aiJobsHeaderChips","cancelAiJobRequest","resumeAiJobRequest","aiBuildCanRetry","aiBuildItemRows","aiSitePartialCopy","publishAiJob","AiPageBriefDialog","AiInsightDialog","AiJobPlan","aiJobOutputHref","aiJobPrimaryLink","aiSiteBuildHref","aiJobRefundCopy","readEventFrames","LIST_LIMIT","BRIEF_PREVIEW_CHARS","PHASE_COLOR","queued","planning","building","attention","done","failed","canceled","STATE_COLOR","running","ITEM_STATE_LABELS","active","waiting","skipped","HIGHLIGHT_MS","aiJobRestartHref","job","input","kind","status","siteInputs","hostId","subdomain","exec","pathname","href","orgSlug","id","netCredits","Math","max","creditsSpent","refundedCredits","aiJobNavigationProposal","output","resource","navigation","proposal","label","trim","AssistJobsDrawer","orgId","org","orgReady","user","visible","isStaff","insight","inFlight","focus","entitled","expanded","setExpanded","toggledRef","highlight","setHighlight","listRef","jobs","setJobs","loading","setLoading","notice","setNotice","describing","setDescribing","insightOpen","setInsightOpen","trackedRef","Set","watchingRef","patchJob","next","prior","index","findIndex","slice","copy","includes","current","has","add","credits","load","response","encodeURIComponent","ok","payload","json","catch","String","error","anyInFlight","length","focusSeq","seq","focusJobId","jobId","expandedRef","highlightListed","some","row","undefined","Array","from","querySelectorAll","find","element","dataset","scrollIntoView","block","behavior","timer","setTimeout","clearTimeout","watched","watchedId","controller","AbortController","watch","again","signal","aborted","body","event","filter","finally","abort","cancel","resuming","setResuming","resume","options","chips","sx","mb","borderBottom","borderColor","pb","direction","spacing","alignItems","variant","flexGrow","map","chip","size","color","state","ml","onClick","aria-label","aria-expanded","path","fontSize","in","unmountOnExit","component","mt","ref","role","restartHref","window","location","stepsDone","steps","step","terminal","phase","primary","highlighted","data-ai-job-id","aria-current","borderRadius","bgcolor","outline","outlineColor","transition","theme","transitions","create","duration","standard","px","py","name","wordBreak","brief","items","m","pl","data-item-state","detail","slot","disabled","retry","outputs","componentVariant","text","whiteSpace","fontFamily","totalBytes","note","onResume","target","busy","staff","open","onClose","host","surface","uid"],"mappings":"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"}