@aglyn/plugins-ai 1.0.0-beta.230 → 1.0.0-beta.232

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 (305) hide show
  1. package/package.json +17 -17
  2. package/src/lib/activity/ai-activity-actions.js +8 -4
  3. package/src/lib/activity/ai-activity-actions.js.map +1 -1
  4. package/src/lib/components/ai-assist-provider-on-host.component.d.ts +66 -0
  5. package/src/lib/components/ai-assist-provider-on-host.component.js +78 -0
  6. package/src/lib/components/ai-assist-provider-on-host.component.js.map +1 -0
  7. package/src/lib/components/ai-assist-provider.component.js +9 -10
  8. package/src/lib/components/ai-assist-provider.component.js.map +1 -1
  9. package/src/lib/components/ai-job-follow.component.js +1 -0
  10. package/src/lib/components/ai-job-follow.component.js.map +1 -1
  11. package/src/lib/components/ai-job-links.js +13 -0
  12. package/src/lib/components/ai-job-links.js.map +1 -1
  13. package/src/lib/components/ai-job-plan.component.js +3 -1
  14. package/src/lib/components/ai-job-plan.component.js.map +1 -1
  15. package/src/lib/components/ai-jobs-list-page.component.js +1 -0
  16. package/src/lib/components/ai-jobs-list-page.component.js.map +1 -1
  17. package/src/lib/components/ai-media-create.component.d.ts +20 -7
  18. package/src/lib/components/ai-media-create.component.js +107 -55
  19. package/src/lib/components/ai-media-create.component.js.map +1 -1
  20. package/src/lib/components/ai-permissions-on-host.component.d.ts +3 -46
  21. package/src/lib/components/ai-permissions-on-host.component.js +5 -53
  22. package/src/lib/components/ai-permissions-on-host.component.js.map +1 -1
  23. package/src/lib/components/ai-seo-fields-card.component.js +1 -0
  24. package/src/lib/components/ai-seo-fields-card.component.js.map +1 -1
  25. package/src/lib/components/ai-site-build-page.component.js +20 -8
  26. package/src/lib/components/ai-site-build-page.component.js.map +1 -1
  27. package/src/lib/components/ai-site-memory-card.component.d.ts +32 -0
  28. package/src/lib/components/ai-site-memory-card.component.js +187 -0
  29. package/src/lib/components/ai-site-memory-card.component.js.map +1 -0
  30. package/src/lib/components/ai-site-start-card.component.js +80 -77
  31. package/src/lib/components/ai-site-start-card.component.js.map +1 -1
  32. package/src/lib/components/ai-theme-proposal-card.component.js +4 -0
  33. package/src/lib/components/ai-theme-proposal-card.component.js.map +1 -1
  34. package/src/lib/components/ai-usage-strip.component.js +1 -0
  35. package/src/lib/components/ai-usage-strip.component.js.map +1 -1
  36. package/src/lib/components/assist-panel.component.d.ts +10 -0
  37. package/src/lib/components/assist-panel.component.js +119 -9
  38. package/src/lib/components/assist-panel.component.js.map +1 -1
  39. package/src/lib/components/assist-signals-page.component.js +2 -0
  40. package/src/lib/components/assist-signals-page.component.js.map +1 -1
  41. package/src/lib/components/billing-ai-allotments.component.js +3 -0
  42. package/src/lib/components/billing-ai-allotments.component.js.map +1 -1
  43. package/src/lib/components/billing-ai-top-users.component.js +1 -0
  44. package/src/lib/components/billing-ai-top-users.component.js.map +1 -1
  45. package/src/lib/components/billing-assist-overage-card.component.js +2 -0
  46. package/src/lib/components/billing-assist-overage-card.component.js.map +1 -1
  47. package/src/lib/components/member-ai-usage-card.component.js +10 -0
  48. package/src/lib/components/member-ai-usage-card.component.js.map +1 -1
  49. package/src/lib/components/staff-org-ai-card.component.js +1 -0
  50. package/src/lib/components/staff-org-ai-card.component.js.map +1 -1
  51. package/src/lib/components/staff-org-ai-conversations.component.d.ts +23 -0
  52. package/src/lib/components/staff-org-ai-conversations.component.js +346 -0
  53. package/src/lib/components/staff-org-ai-conversations.component.js.map +1 -0
  54. package/src/lib/jobs/ai-build-capabilities.d.ts +13 -1
  55. package/src/lib/jobs/ai-build-capabilities.js +101 -7
  56. package/src/lib/jobs/ai-build-capabilities.js.map +1 -1
  57. package/src/lib/jobs/ai-build-unit-outcome.js +4 -2
  58. package/src/lib/jobs/ai-build-unit-outcome.js.map +1 -1
  59. package/src/lib/jobs/ai-business-profile-prefill.d.ts +29 -0
  60. package/src/lib/jobs/ai-business-profile-prefill.js +85 -0
  61. package/src/lib/jobs/ai-business-profile-prefill.js.map +1 -0
  62. package/src/lib/jobs/ai-job-auto-confirm.d.ts +8 -0
  63. package/src/lib/jobs/ai-job-auto-confirm.js +30 -6
  64. package/src/lib/jobs/ai-job-auto-confirm.js.map +1 -1
  65. package/src/lib/jobs/ai-job-build-step.js +14 -1
  66. package/src/lib/jobs/ai-job-build-step.js.map +1 -1
  67. package/src/lib/jobs/ai-job-edit-step.d.ts +225 -0
  68. package/src/lib/jobs/ai-job-edit-step.js +631 -0
  69. package/src/lib/jobs/ai-job-edit-step.js.map +1 -0
  70. package/src/lib/jobs/ai-job-generation.d.ts +8 -0
  71. package/src/lib/jobs/ai-job-generation.js +13 -2
  72. package/src/lib/jobs/ai-job-generation.js.map +1 -1
  73. package/src/lib/jobs/ai-job-insight-step.js +29 -5
  74. package/src/lib/jobs/ai-job-insight-step.js.map +1 -1
  75. package/src/lib/jobs/ai-job-layout-language.d.ts +78 -0
  76. package/src/lib/jobs/ai-job-layout-language.js +200 -0
  77. package/src/lib/jobs/ai-job-layout-language.js.map +1 -0
  78. package/src/lib/jobs/ai-job-layout-site-pages.d.ts +13 -2
  79. package/src/lib/jobs/ai-job-layout-site-pages.js +18 -2
  80. package/src/lib/jobs/ai-job-layout-site-pages.js.map +1 -1
  81. package/src/lib/jobs/ai-job-layout-step.d.ts +5 -0
  82. package/src/lib/jobs/ai-job-layout-step.js +107 -6
  83. package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
  84. package/src/lib/jobs/ai-job-logic-step.d.ts +20 -0
  85. package/src/lib/jobs/ai-job-logic-step.js +87 -6
  86. package/src/lib/jobs/ai-job-logic-step.js.map +1 -1
  87. package/src/lib/jobs/ai-job-page-language.d.ts +194 -0
  88. package/src/lib/jobs/ai-job-page-language.js +418 -0
  89. package/src/lib/jobs/ai-job-page-language.js.map +1 -0
  90. package/src/lib/jobs/ai-job-page-sections.d.ts +37 -1
  91. package/src/lib/jobs/ai-job-page-sections.js +93 -11
  92. package/src/lib/jobs/ai-job-page-sections.js.map +1 -1
  93. package/src/lib/jobs/ai-job-page-step.d.ts +4 -4
  94. package/src/lib/jobs/ai-job-page-step.js +115 -14
  95. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  96. package/src/lib/jobs/ai-job-plan-step.d.ts +20 -6
  97. package/src/lib/jobs/ai-job-plan-step.js +62 -22
  98. package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
  99. package/src/lib/jobs/ai-job-site-content.d.ts +163 -0
  100. package/src/lib/jobs/ai-job-site-content.js +443 -0
  101. package/src/lib/jobs/ai-job-site-content.js.map +1 -0
  102. package/src/lib/jobs/ai-job-site-look.d.ts +112 -0
  103. package/src/lib/jobs/ai-job-site-look.js +322 -0
  104. package/src/lib/jobs/ai-job-site-look.js.map +1 -0
  105. package/src/lib/jobs/ai-job-site-step.d.ts +30 -5
  106. package/src/lib/jobs/ai-job-site-step.js +183 -27
  107. package/src/lib/jobs/ai-job-site-step.js.map +1 -1
  108. package/src/lib/jobs/ai-job-workflow-step.js +2 -2
  109. package/src/lib/jobs/ai-job-workflow-step.js.map +1 -1
  110. package/src/lib/jobs/ai-jobs-notify.d.ts +6 -1
  111. package/src/lib/jobs/ai-jobs-notify.js +15 -3
  112. package/src/lib/jobs/ai-jobs-notify.js.map +1 -1
  113. package/src/lib/jobs/ai-jobs.d.ts +1 -1
  114. package/src/lib/jobs/ai-jobs.js +17 -8
  115. package/src/lib/jobs/ai-jobs.js.map +1 -1
  116. package/src/lib/jobs/ai-layout-full-height.d.ts +40 -0
  117. package/src/lib/jobs/ai-layout-full-height.js +82 -0
  118. package/src/lib/jobs/ai-layout-full-height.js.map +1 -0
  119. package/src/lib/jobs/ai-layout-site-facts.d.ts +54 -0
  120. package/src/lib/jobs/ai-layout-site-facts.js +153 -0
  121. package/src/lib/jobs/ai-layout-site-facts.js.map +1 -0
  122. package/src/lib/layout-language/ai-layout-compiler.d.ts +154 -0
  123. package/src/lib/layout-language/ai-layout-compiler.js +1235 -0
  124. package/src/lib/layout-language/ai-layout-compiler.js.map +1 -0
  125. package/src/lib/layout-language/ai-layout-copy.d.ts +73 -0
  126. package/src/lib/layout-language/ai-layout-copy.js +137 -0
  127. package/src/lib/layout-language/ai-layout-copy.js.map +1 -0
  128. package/src/lib/layout-language/ai-layout-frame.d.ts +52 -0
  129. package/src/lib/layout-language/ai-layout-frame.js +458 -0
  130. package/src/lib/layout-language/ai-layout-frame.js.map +1 -0
  131. package/src/lib/layout-language/ai-layout-gaps.d.ts +63 -0
  132. package/src/lib/layout-language/ai-layout-gaps.js +345 -0
  133. package/src/lib/layout-language/ai-layout-gaps.js.map +1 -0
  134. package/src/lib/layout-language/ai-layout-language.d.ts +168 -0
  135. package/src/lib/layout-language/ai-layout-language.js +529 -0
  136. package/src/lib/layout-language/ai-layout-language.js.map +1 -0
  137. package/src/lib/layout-language/ai-layout-links.d.ts +80 -0
  138. package/src/lib/layout-language/ai-layout-links.js +109 -0
  139. package/src/lib/layout-language/ai-layout-links.js.map +1 -0
  140. package/src/lib/layout-language/ai-layout-pictures.d.ts +144 -0
  141. package/src/lib/layout-language/ai-layout-pictures.js +214 -0
  142. package/src/lib/layout-language/ai-layout-pictures.js.map +1 -0
  143. package/src/lib/layout-language/ai-layout-store.d.ts +41 -0
  144. package/src/lib/layout-language/ai-layout-store.js +75 -0
  145. package/src/lib/layout-language/ai-layout-store.js.map +1 -0
  146. package/src/lib/layout-language/ai-layout-tree.d.ts +59 -0
  147. package/src/lib/layout-language/ai-layout-tree.js +84 -0
  148. package/src/lib/layout-language/ai-layout-tree.js.map +1 -0
  149. package/src/lib/lazy-widget.d.ts +45 -0
  150. package/src/lib/lazy-widget.js +53 -0
  151. package/src/lib/lazy-widget.js.map +1 -0
  152. package/src/lib/model/ai-build-job.js +2 -1
  153. package/src/lib/model/ai-build-job.js.map +1 -1
  154. package/src/lib/model/ai-build-progress.d.ts +20 -3
  155. package/src/lib/model/ai-build-progress.js +52 -7
  156. package/src/lib/model/ai-build-progress.js.map +1 -1
  157. package/src/lib/model/ai-edit-job.d.ts +109 -0
  158. package/src/lib/model/ai-edit-job.js +157 -0
  159. package/src/lib/model/ai-edit-job.js.map +1 -0
  160. package/src/lib/model/ai-host-publish-context.d.ts +51 -0
  161. package/src/lib/model/ai-host-publish-context.js +104 -0
  162. package/src/lib/model/ai-host-publish-context.js.map +1 -0
  163. package/src/lib/model/ai-job-activity.d.ts +22 -0
  164. package/src/lib/model/ai-job-activity.js +23 -1
  165. package/src/lib/model/ai-job-activity.js.map +1 -1
  166. package/src/lib/model/ai-job-failure-copy.d.ts +38 -1
  167. package/src/lib/model/ai-job-failure-copy.js +56 -1
  168. package/src/lib/model/ai-job-failure-copy.js.map +1 -1
  169. package/src/lib/model/ai-job-notice.d.ts +3 -1
  170. package/src/lib/model/ai-job-notice.js +31 -9
  171. package/src/lib/model/ai-job-notice.js.map +1 -1
  172. package/src/lib/model/ai-jobs.types.d.ts +22 -1
  173. package/src/lib/model/ai-jobs.types.js.map +1 -1
  174. package/src/lib/model/ai-logic-job.d.ts +18 -1
  175. package/src/lib/model/ai-logic-job.js +24 -3
  176. package/src/lib/model/ai-logic-job.js.map +1 -1
  177. package/src/lib/model/ai-media-credits.d.ts +8 -4
  178. package/src/lib/model/ai-media-credits.js +11 -4
  179. package/src/lib/model/ai-media-credits.js.map +1 -1
  180. package/src/lib/model/ai-media-kinds.d.ts +68 -0
  181. package/src/lib/model/ai-media-kinds.js +98 -0
  182. package/src/lib/model/ai-media-kinds.js.map +1 -0
  183. package/src/lib/model/ai-site-build-progress.d.ts +9 -1
  184. package/src/lib/model/ai-site-build-progress.js +54 -14
  185. package/src/lib/model/ai-site-build-progress.js.map +1 -1
  186. package/src/lib/model/ai-site-context.d.ts +111 -0
  187. package/src/lib/model/ai-site-context.js +222 -0
  188. package/src/lib/model/ai-site-context.js.map +1 -0
  189. package/src/lib/model/ai-site-job.d.ts +18 -2
  190. package/src/lib/model/ai-site-job.js +21 -5
  191. package/src/lib/model/ai-site-job.js.map +1 -1
  192. package/src/lib/model/ai-site-kinds.d.ts +164 -0
  193. package/src/lib/model/ai-site-kinds.js +1942 -0
  194. package/src/lib/model/ai-site-kinds.js.map +1 -0
  195. package/src/lib/model/ai-site-look.d.ts +150 -0
  196. package/src/lib/model/ai-site-look.js +1236 -0
  197. package/src/lib/model/ai-site-look.js.map +1 -0
  198. package/src/lib/model/ai-site-memory.d.ts +80 -0
  199. package/src/lib/model/ai-site-memory.js +171 -0
  200. package/src/lib/model/ai-site-memory.js.map +1 -0
  201. package/src/lib/model/ai-site-start-seo.d.ts +1 -1
  202. package/src/lib/model/ai-site-start.d.ts +15 -3
  203. package/src/lib/model/ai-site-start.js +21 -4
  204. package/src/lib/model/ai-site-start.js.map +1 -1
  205. package/src/lib/model/assist-follow-up.d.ts +92 -0
  206. package/src/lib/model/assist-follow-up.js +128 -0
  207. package/src/lib/model/assist-follow-up.js.map +1 -0
  208. package/src/lib/plugin-config.js +2 -0
  209. package/src/lib/plugin-config.js.map +1 -1
  210. package/src/lib/plugin.js +99 -48
  211. package/src/lib/plugin.js.map +1 -1
  212. package/src/lib/providers/anthropic.d.ts +9 -1
  213. package/src/lib/providers/anthropic.js +143 -9
  214. package/src/lib/providers/anthropic.js.map +1 -1
  215. package/src/lib/providers/catalog.d.ts +38 -8
  216. package/src/lib/providers/catalog.js +106 -14
  217. package/src/lib/providers/catalog.js.map +1 -1
  218. package/src/lib/providers/contract.d.ts +29 -0
  219. package/src/lib/providers/contract.js.map +1 -1
  220. package/src/lib/providers/image-contract.d.ts +22 -1
  221. package/src/lib/providers/image-contract.js +40 -1
  222. package/src/lib/providers/image-contract.js.map +1 -1
  223. package/src/lib/providers/image-endpoints.d.ts +24 -0
  224. package/src/lib/providers/image-endpoints.js +28 -0
  225. package/src/lib/providers/image-endpoints.js.map +1 -0
  226. package/src/lib/providers/model-choice.js +23 -2
  227. package/src/lib/providers/model-choice.js.map +1 -1
  228. package/src/lib/providers/routing.js +18 -0
  229. package/src/lib/providers/routing.js.map +1 -1
  230. package/src/lib/providers/vertex-image-endpoint.d.ts +48 -0
  231. package/src/lib/providers/vertex-image-endpoint.js +80 -0
  232. package/src/lib/providers/vertex-image-endpoint.js.map +1 -0
  233. package/src/lib/providers/vertex-image.d.ts +13 -27
  234. package/src/lib/providers/vertex-image.js +15 -42
  235. package/src/lib/providers/vertex-image.js.map +1 -1
  236. package/src/lib/runtime/ai-blog-post-generation.d.ts +62 -0
  237. package/src/lib/runtime/ai-blog-post-generation.js +89 -0
  238. package/src/lib/runtime/ai-blog-post-generation.js.map +1 -0
  239. package/src/lib/runtime/ai-dev-env.d.ts +53 -0
  240. package/src/lib/runtime/ai-dev-env.js +72 -0
  241. package/src/lib/runtime/ai-dev-env.js.map +1 -0
  242. package/src/lib/runtime/ai-dev-replay.d.ts +116 -0
  243. package/src/lib/runtime/ai-dev-replay.js +313 -0
  244. package/src/lib/runtime/ai-dev-replay.js.map +1 -0
  245. package/src/lib/runtime/ai-doctrine-validators.d.ts +82 -0
  246. package/src/lib/runtime/ai-doctrine-validators.js +436 -4
  247. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
  248. package/src/lib/runtime/ai-doctrine.js +16 -3
  249. package/src/lib/runtime/ai-doctrine.js.map +1 -1
  250. package/src/lib/runtime/ai-eval-live.js +4 -0
  251. package/src/lib/runtime/ai-eval-live.js.map +1 -1
  252. package/src/lib/runtime/ai-eval.d.ts +13 -1
  253. package/src/lib/runtime/ai-eval.js +84 -1
  254. package/src/lib/runtime/ai-eval.js.map +1 -1
  255. package/src/lib/runtime/ai-icon-library.d.ts +257 -0
  256. package/src/lib/runtime/ai-icon-library.js +254 -0
  257. package/src/lib/runtime/ai-icon-library.js.map +1 -0
  258. package/src/lib/runtime/ai-live-batch.d.ts +45 -0
  259. package/src/lib/runtime/ai-live-batch.js +89 -0
  260. package/src/lib/runtime/ai-live-batch.js.map +1 -0
  261. package/src/lib/runtime/ai-node-tree.d.ts +9 -0
  262. package/src/lib/runtime/ai-node-tree.js +30 -4
  263. package/src/lib/runtime/ai-node-tree.js.map +1 -1
  264. package/src/lib/runtime/ai-palette.d.ts +6 -0
  265. package/src/lib/runtime/ai-palette.generated.js +70 -0
  266. package/src/lib/runtime/ai-palette.generated.js.map +1 -1
  267. package/src/lib/runtime/ai-palette.js.map +1 -1
  268. package/src/lib/runtime/ai-runtime.js +46 -2
  269. package/src/lib/runtime/ai-runtime.js.map +1 -1
  270. package/src/lib/runtime/site-context.d.ts +58 -0
  271. package/src/lib/runtime/site-context.js +127 -0
  272. package/src/lib/runtime/site-context.js.map +1 -0
  273. package/src/lib/server/ai-admin-conversations.d.ts +22 -0
  274. package/src/lib/server/ai-admin-conversations.js +197 -0
  275. package/src/lib/server/ai-admin-conversations.js.map +1 -0
  276. package/src/lib/server/ai-media-image.d.ts +5 -5
  277. package/src/lib/server/ai-media-image.js +25 -11
  278. package/src/lib/server/ai-media-image.js.map +1 -1
  279. package/src/lib/server/ai-media-raster-prompt.d.ts +34 -0
  280. package/src/lib/server/ai-media-raster-prompt.js +53 -0
  281. package/src/lib/server/ai-media-raster-prompt.js.map +1 -0
  282. package/src/lib/server/assist-chat.d.ts +11 -0
  283. package/src/lib/server/assist-chat.js +57 -18
  284. package/src/lib/server/assist-chat.js.map +1 -1
  285. package/src/lib/server/assist-edit-applied.js +16 -3
  286. package/src/lib/server/assist-edit-applied.js.map +1 -1
  287. package/src/lib/server/assist-view-context.d.ts +19 -1
  288. package/src/lib/server/assist-view-context.js +38 -1
  289. package/src/lib/server/assist-view-context.js.map +1 -1
  290. package/src/lib/server.js +10 -0
  291. package/src/lib/server.js.map +1 -1
  292. package/src/lib/subprocessors.js +17 -1
  293. package/src/lib/subprocessors.js.map +1 -1
  294. package/src/lib/tools/ai-blog-post-tool.d.ts +60 -0
  295. package/src/lib/tools/ai-blog-post-tool.js +175 -0
  296. package/src/lib/tools/ai-blog-post-tool.js.map +1 -0
  297. package/src/lib/tools/ai-workflow-tool.d.ts +6 -2
  298. package/src/lib/tools/ai-workflow-tool.js +16 -14
  299. package/src/lib/tools/ai-workflow-tool.js.map +1 -1
  300. package/src/lib/usage/assist-usage.d.ts +3 -0
  301. package/src/lib/usage/assist-usage.js +4 -2
  302. package/src/lib/usage/assist-usage.js.map +1 -1
  303. package/src/lib/usage/staff-org-ai-conversations.d.ts +103 -0
  304. package/src/lib/usage/staff-org-ai-conversations.js +152 -0
  305. package/src/lib/usage/staff-org-ai-conversations.js.map +1 -0
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ /**
17
+ * The style wording each image-provider kind adds to a description
18
+ * (AGL-3602). The person's description comes first, so it decides what is
19
+ * in the picture; the wording after it decides how the picture is made — a
20
+ * photograph's lens, light and composition, an art style's medium and
21
+ * strokes, a design asset's layout.
22
+ *
23
+ * It is fixed text of ours and carries nothing of the workspace: what reaches
24
+ * the image provider is still the description and the shape, as the
25
+ * published subprocessor row says.
26
+ *
27
+ * `photo` adds nothing: its description is sent exactly as written, as it
28
+ * was before the other kinds existed.
29
+ */ export const AI_MEDIA_RASTER_STYLE_WORDING = {
30
+ photo: '',
31
+ natural: 'Style: a natural, candid photograph. Realistic colors and textures, soft available light, shot on a full-frame camera with a 35mm lens at a wide aperture for a shallow depth of field, an unposed, true-to-life composition.',
32
+ product: 'Style: a professional studio product photograph. The product is the hero, centered on a clean seamless backdrop, lit with soft diffused key and fill lights and a gentle contact shadow, tack-sharp focus on every detail, shot with a 100mm macro lens, commercial catalog quality. No other objects unless the description names them.',
33
+ lifestyle: 'Style: an editorial lifestyle photograph with people using or enjoying the subject in a real setting. Natural expressions and relaxed poses, warm natural light, 50mm lens, shallow depth of field, authentic rather than staged. The people are fictional and must not resemble any real or famous person.',
34
+ architecture: 'Style: an architectural photograph. Straight vertical lines and balanced two-point perspective, a 24mm tilt-shift lens, natural daylight with soft shadows, a clean uncluttered composition, true-to-life materials and textures.',
35
+ food: 'Style: a food photograph. Fresh, appetizing and carefully plated, soft directional window light from the side, shallow depth of field with an 85mm lens, rich true colors, a few tasteful props on a textured surface.',
36
+ aerial: 'Style: an aerial or wide landscape photograph, taken from a drone high above or as a sweeping vista. Wide-angle lens, golden-hour light, deep focus from the foreground to the horizon, vivid but natural colors.',
37
+ 'render-3d': 'Style: a polished 3D render. Smooth stylized shapes, soft global illumination with ambient occlusion, subtle reflections, a clean studio background, high detail.',
38
+ watercolor: 'Style: a watercolor painting. Soft transparent washes of pigment, visible cold-press paper texture, gentle bleeding edges, loose expressive brushwork, light and airy.',
39
+ 'oil-painting': 'Style: an oil painting on canvas. Rich layered color, visible impasto brushstrokes, painterly light and shadow, a classical, balanced composition.',
40
+ 'flat-art': 'Style: flat vector-style artwork. Clean geometric shapes, solid color fills with no gradients or texture, crisp edges, a limited harmonious palette, a modern editorial illustration look.',
41
+ 'line-drawing': 'Style: a line drawing. Clean, confident ink lines on a plain white background, minimal or no shading, elegant and uncluttered.',
42
+ cartoon: 'Style: a cartoon or anime-style illustration. Bold outlines, expressive original characters, vibrant cel-shaded colors, playful and friendly. Never a character from an existing film, show, comic or game.',
43
+ background: 'Style: a background texture or backdrop for a website. Subtle and low in contrast, evenly balanced across the whole frame with no focal subject, no text or lettering, so words can sit on top of it.',
44
+ banner: 'Style: a wide website banner or hero image. A strong focal subject placed to one side with generous, calm negative space on the other for a headline, no text or lettering in the image, a polished commercial look.',
45
+ social: 'Style: a social media post graphic. A bold, eye-catching composition with one clear focal point centered with balanced margins, vibrant colors, and no text or lettering unless the description asks for it.',
46
+ mockup: 'Style: a realistic product mockup. The described design is shown on a device screen or on packaging, photographed in a clean studio or lifestyle setting with accurate perspective, soft lighting and natural reflections.'
47
+ };
48
+ /** The prompt one picture is asked for: the description, then the kind's style wording. */ export function aiMediaRasterPrompt(description, style) {
49
+ const wording = AI_MEDIA_RASTER_STYLE_WORDING[style];
50
+ return wording ? `${description}\n\n${wording}` : description;
51
+ }
52
+
53
+ //# sourceMappingURL=ai-media-raster-prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/server/ai-media-raster-prompt.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 type { AiRasterStyle } from '../providers/image-contract'\n\n/**\n * The style wording each image-provider kind adds to a description\n * (AGL-3602). The person's description comes first, so it decides what is\n * in the picture; the wording after it decides how the picture is made — a\n * photograph's lens, light and composition, an art style's medium and\n * strokes, a design asset's layout.\n *\n * It is fixed text of ours and carries nothing of the workspace: what reaches\n * the image provider is still the description and the shape, as the\n * published subprocessor row says.\n *\n * `photo` adds nothing: its description is sent exactly as written, as it\n * was before the other kinds existed.\n */\nexport const AI_MEDIA_RASTER_STYLE_WORDING: Readonly<Record<AiRasterStyle, string>> = {\n photo: '',\n natural:\n 'Style: a natural, candid photograph. Realistic colors and textures, soft available light, shot on a full-frame camera with a 35mm lens at a wide aperture for a shallow depth of field, an unposed, true-to-life composition.',\n product:\n 'Style: a professional studio product photograph. The product is the hero, centered on a clean seamless backdrop, lit with soft diffused key and fill lights and a gentle contact shadow, tack-sharp focus on every detail, shot with a 100mm macro lens, commercial catalog quality. No other objects unless the description names them.',\n lifestyle:\n 'Style: an editorial lifestyle photograph with people using or enjoying the subject in a real setting. Natural expressions and relaxed poses, warm natural light, 50mm lens, shallow depth of field, authentic rather than staged. The people are fictional and must not resemble any real or famous person.',\n architecture:\n 'Style: an architectural photograph. Straight vertical lines and balanced two-point perspective, a 24mm tilt-shift lens, natural daylight with soft shadows, a clean uncluttered composition, true-to-life materials and textures.',\n food:\n 'Style: a food photograph. Fresh, appetizing and carefully plated, soft directional window light from the side, shallow depth of field with an 85mm lens, rich true colors, a few tasteful props on a textured surface.',\n aerial:\n 'Style: an aerial or wide landscape photograph, taken from a drone high above or as a sweeping vista. Wide-angle lens, golden-hour light, deep focus from the foreground to the horizon, vivid but natural colors.',\n 'render-3d':\n 'Style: a polished 3D render. Smooth stylized shapes, soft global illumination with ambient occlusion, subtle reflections, a clean studio background, high detail.',\n watercolor:\n 'Style: a watercolor painting. Soft transparent washes of pigment, visible cold-press paper texture, gentle bleeding edges, loose expressive brushwork, light and airy.',\n 'oil-painting':\n 'Style: an oil painting on canvas. Rich layered color, visible impasto brushstrokes, painterly light and shadow, a classical, balanced composition.',\n 'flat-art':\n 'Style: flat vector-style artwork. Clean geometric shapes, solid color fills with no gradients or texture, crisp edges, a limited harmonious palette, a modern editorial illustration look.',\n 'line-drawing':\n 'Style: a line drawing. Clean, confident ink lines on a plain white background, minimal or no shading, elegant and uncluttered.',\n cartoon:\n 'Style: a cartoon or anime-style illustration. Bold outlines, expressive original characters, vibrant cel-shaded colors, playful and friendly. Never a character from an existing film, show, comic or game.',\n background:\n 'Style: a background texture or backdrop for a website. Subtle and low in contrast, evenly balanced across the whole frame with no focal subject, no text or lettering, so words can sit on top of it.',\n banner:\n 'Style: a wide website banner or hero image. A strong focal subject placed to one side with generous, calm negative space on the other for a headline, no text or lettering in the image, a polished commercial look.',\n social:\n 'Style: a social media post graphic. A bold, eye-catching composition with one clear focal point centered with balanced margins, vibrant colors, and no text or lettering unless the description asks for it.',\n mockup:\n 'Style: a realistic product mockup. The described design is shown on a device screen or on packaging, photographed in a clean studio or lifestyle setting with accurate perspective, soft lighting and natural reflections.',\n}\n\n/** The prompt one picture is asked for: the description, then the kind's style wording. */\nexport function aiMediaRasterPrompt(description: string, style: AiRasterStyle): string {\n const wording = AI_MEDIA_RASTER_STYLE_WORDING[style]\n return wording ? `${description}\\n\\n${wording}` : description\n}\n"],"names":["AI_MEDIA_RASTER_STYLE_WORDING","photo","natural","product","lifestyle","architecture","food","aerial","watercolor","cartoon","background","banner","social","mockup","aiMediaRasterPrompt","description","style","wording"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAID;;;;;;;;;;;;;CAaC,GACD,OAAO,MAAMA,gCAAyE;IACpFC,OAAO;IACPC,SACE;IACFC,SACE;IACFC,WACE;IACFC,cACE;IACFC,MACE;IACFC,QACE;IACF,aACE;IACFC,YACE;IACF,gBACE;IACF,YACE;IACF,gBACE;IACFC,SACE;IACFC,YACE;IACFC,QACE;IACFC,QACE;IACFC,QACE;AACJ,EAAC;AAED,yFAAyF,GACzF,OAAO,SAASC,oBAAoBC,WAAmB,EAAEC,KAAoB;IAC3E,MAAMC,UAAUjB,6BAA6B,CAACgB,MAAM;IACpD,OAAOC,UAAU,GAAGF,YAAY,IAAI,EAAEE,SAAS,GAAGF;AACpD"}
@@ -14,6 +14,7 @@
14
14
  * See the License for the specific language governing permissions and
15
15
  * limitations under the License.
16
16
  */
17
+ import { type AssistBuildDraft } from '../model/assist-follow-up';
17
18
  /**
18
19
  * Aglyn Assist chat proxy (AGL-1860, phase 1 — capability levels 1–2).
19
20
  *
@@ -108,6 +109,11 @@
108
109
  * 4. request facts workspace, plan, host, path
109
110
  * 5. docs retrieval follows the question
110
111
  *
112
+ * On the edit and build rungs a SITE block (AGL-3661) follows the stable
113
+ * blocks: the business profile, status and remembered preferences of the
114
+ * site being changed, cached per site as the span's last breakpoint, or
115
+ * volatile when the stable blocks already hold the runtime's four.
116
+ *
111
117
  * Caching is a prefix match, so breakpoint 2 covers blocks 1+2 together. The
112
118
  * split between 2 and 3 is the whole design and it is easy to get wrong:
113
119
  * folding the workspace name and plan into block 2 reads more natural and
@@ -173,6 +179,11 @@ interface AssistRequestBody {
173
179
  * to what may enter a prompt, and below the rung it is never parsed at all.
174
180
  */
175
181
  canvas: unknown;
182
+ /**
183
+ * The drafts a build in this thread made, by ref and label (AGL-3616):
184
+ * what a follow-up may offer to open. Held to `parseAssistBuildDrafts`.
185
+ */
186
+ drafts: AssistBuildDraft[];
176
187
  }
177
188
  /**
178
189
  * The turns past the verbatim window, as one labelled digest (AGL-2937).
@@ -32,8 +32,9 @@ import { composeDocsLinksAnswer, deflectToDocs, questionStandsAlone, sectionLabe
32
32
  import { ASSIST_EDIT_TOOL_NAME, assistEditDocumentOf } from "../model/assist-edit.js";
33
33
  import { ASSIST_EDIT_MAX_OUTPUT_TOKENS, assistEditTool, editCanvasBlock, editSelectionBlock, parseAssistEditContext, resolveAssistEdit } from "./assist-edit.js";
34
34
  import { ASSIST_BUILD_TOOL_NAME } from "../model/assist-build.js";
35
+ import { assistBuildDraftsBlock, parseAssistBuildDrafts } from "../model/assist-follow-up.js";
35
36
  import { assistBuildBlock, assistBuildIntents, assistBuildIntentsBlock, assistBuildTool, resolveAssistBuild } from "./assist-build.js";
36
- import { describeView, extractAssistAction, finalAssistText, resolveAssistProposal, safeOrgFacts, sanitiseId, sanitiseRoute, viewFactsBlock, viewScreenBlock, visibleAssistText } from "./assist-view-context.js";
37
+ import { describeView, extractAssistAction, finalAssistText, resolveAssistProposal, safeOrgFacts, sanitiseId, sanitiseRoute, viewFactsBlock, viewScreenBlock, visibleAssistText, withAssistOpenDraftAction } from "./assist-view-context.js";
37
38
  import { invalidIdTokenResponse } from "@aglyn/tenant-data-admin/server/id-token-refusal";
38
39
  // By its own entry point rather than the barrel (AGL-2903), for the reason
39
40
  // `isRefusedIdToken` is: this route's spec replaces the barrel with a
@@ -42,7 +43,9 @@ import { invalidIdTokenResponse } from "@aglyn/tenant-data-admin/server/id-token
42
43
  // failing loudly. Nothing replaces the entry point, so the spec exercises
43
44
  // the real request shape, the real SSE parser and the real error boundary.
44
45
  import { AI_ROUTING_TABLE, aiModelForStep } from "../providers/routing.js";
45
- import { AI_ACCEPTABLE_USE_BLOCK, AiUpstreamError, aiProviderReady, runAiRequest } from "../runtime/ai-runtime.js";
46
+ import { aiSiteContextSystemBlock } from "../model/ai-site-context.js";
47
+ import { readAiSiteContext } from "../runtime/site-context.js";
48
+ import { AI_ACCEPTABLE_USE_BLOCK, AI_MAX_CACHE_BREAKPOINTS, AiUpstreamError, aiProviderReady, runAiRequest } from "../runtime/ai-runtime.js";
46
49
  // The Free taste's request-level rungs (AGL-2925), by their own entry
47
50
  // point for the same reason the runtime is.
48
51
  import { checkAiClientIpRateLimit, freeAccountAgeRefusal } from "../runtime/ai-abuse-guards.js";
@@ -140,6 +143,11 @@ import { checkAiClientIpRateLimit, freeAccountAgeRefusal } from "../runtime/ai-a
140
143
  * 4. request facts workspace, plan, host, path
141
144
  * 5. docs retrieval follows the question
142
145
  *
146
+ * On the edit and build rungs a SITE block (AGL-3661) follows the stable
147
+ * blocks: the business profile, status and remembered preferences of the
148
+ * site being changed, cached per site as the span's last breakpoint, or
149
+ * volatile when the stable blocks already hold the runtime's four.
150
+ *
143
151
  * Caching is a prefix match, so breakpoint 2 covers blocks 1+2 together. The
144
152
  * split between 2 and 3 is the whole design and it is easy to get wrong:
145
153
  * folding the workspace name and plan into block 2 reads more natural and
@@ -419,7 +427,8 @@ ${AI_ACCEPTABLE_USE_BLOCK}`;
419
427
  history,
420
428
  context,
421
429
  model: model && model !== AI_MODEL_AUTO ? model : null,
422
- canvas: (_body_canvas = body.canvas) != null ? _body_canvas : null
430
+ canvas: (_body_canvas = body.canvas) != null ? _body_canvas : null,
431
+ drafts: parseAssistBuildDrafts(body.drafts)
423
432
  };
424
433
  }
425
434
  /**
@@ -763,7 +772,7 @@ async function handler(request) {
763
772
  });
764
773
  }
765
774
  try {
766
- var _resolved_org, _org_slug, _ref, _ref1, _ref2, _ref3;
775
+ var _resolved_org, _org_slug, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
767
776
  var _body_context, _body_context1, _body_context2, _body_context3, _quota_allotment, _quota_allotment1;
768
777
  const app = firebaseAdmin.app();
769
778
  const decoded = await app.auth().verifyIdToken(idToken);
@@ -903,10 +912,11 @@ async function handler(request) {
903
912
  // an instruction and not a question about "this" element — is answered
904
913
  // from the docs there. `questionStandsAlone` is the deflector's own test
905
914
  // for a question that needs nothing around it, and the open canvas is
906
- // exactly what an edit request leans on.
907
- const deflection = (editRung || buildRung) && !questionStandsAlone(body.question) ? null : deflectToDocs(body.question, scored, body.history.length > 0);
915
+ // exactly what an edit request leans on. So is a follow-up on a draft
916
+ // this thread's build made (AGL-3616): "make the about page shorter".
917
+ const deflection = (editRung || buildRung || body.drafts.length) && !questionStandsAlone(body.question) ? null : deflectToDocs(body.question, scored, body.history.length > 0);
908
918
  if (deflection == null ? void 0 : deflection.answered) {
909
- var _ref4;
919
+ var _ref6;
910
920
  var _body_context4, _body_context5;
911
921
  // Costs no provider tokens, so it takes NO reservation: a docs answer
912
922
  // must not spend one of a free workspace's ten messages a day. The
@@ -920,7 +930,7 @@ async function handler(request) {
920
930
  answer: deflection.answer,
921
931
  docs,
922
932
  docsPaths: deflection.quoted.map((section)=>section.path + section.anchor),
923
- route: (_ref4 = (_body_context4 = body.context) == null ? void 0 : _body_context4.route) != null ? _ref4 : '',
933
+ route: (_ref6 = (_body_context4 = body.context) == null ? void 0 : _body_context4.route) != null ? _ref6 : '',
924
934
  hostId: ((_body_context5 = body.context) == null ? void 0 : _body_context5.hostId) || null,
925
935
  tier: entitled ? 'entitled' : 'free',
926
936
  rate
@@ -952,7 +962,7 @@ async function handler(request) {
952
962
  // panel does not print this string; it has its own plain-English line for
953
963
  // a 501, because the person reading it is not the person who sets the var.
954
964
  if (!aiProviderReady()) {
955
- var _ref5;
965
+ var _ref7;
956
966
  var _body_context6, _body_context7;
957
967
  const closest = composeDocsLinksAnswer(scored.map(({ section })=>section));
958
968
  if (!closest) {
@@ -973,7 +983,7 @@ async function handler(request) {
973
983
  answer: closest,
974
984
  docs,
975
985
  docsPaths,
976
- route: (_ref5 = (_body_context6 = body.context) == null ? void 0 : _body_context6.route) != null ? _ref5 : '',
986
+ route: (_ref7 = (_body_context6 = body.context) == null ? void 0 : _body_context6.route) != null ? _ref7 : '',
977
987
  hostId: ((_body_context7 = body.context) == null ? void 0 : _body_context7.hostId) || null,
978
988
  tier: entitled ? 'entitled' : 'free',
979
989
  rate,
@@ -1006,8 +1016,9 @@ async function handler(request) {
1006
1016
  // cache: the pick is a request for that model's answer, and a cached one
1007
1017
  // was written by whichever model Auto chose. Nor does a turn on the edit
1008
1018
  // rung (AGL-2906): that answer is composed against the canvas the request
1009
- // described, which the key cannot describe either.
1010
- const cacheKey = body.history.length || body.model || editRung || buildRung ? '' : assistAnswerCacheKey({
1019
+ // described, which the key cannot describe either. Nor does a turn that
1020
+ // listed a build's drafts (AGL-3616): its answer may open one of them.
1021
+ const cacheKey = body.history.length || body.model || editRung || buildRung || body.drafts.length ? '' : assistAnswerCacheKey({
1011
1022
  question: body.question,
1012
1023
  tier: entitled ? 'entitled' : 'free',
1013
1024
  route: (_ref = (_body_context2 = body.context) == null ? void 0 : _body_context2.route) != null ? _ref : '',
@@ -1016,7 +1027,7 @@ async function handler(request) {
1016
1027
  });
1017
1028
  const cached = cacheKey ? await readAssistAnswerCache(firestore, body.orgId, cacheKey) : null;
1018
1029
  if (cached) {
1019
- var _cached_docs, _ref6;
1030
+ var _cached_docs, _ref8;
1020
1031
  var _body_context8, _body_context9;
1021
1032
  // Spent nothing, so it takes no reservation — the same rule the docs
1022
1033
  // path follows, for the same reason.
@@ -1028,7 +1039,7 @@ async function handler(request) {
1028
1039
  answer: cached.answer,
1029
1040
  docs: (_cached_docs = cached.docs) != null ? _cached_docs : [],
1030
1041
  docsPaths,
1031
- route: (_ref6 = (_body_context8 = body.context) == null ? void 0 : _body_context8.route) != null ? _ref6 : '',
1042
+ route: (_ref8 = (_body_context8 = body.context) == null ? void 0 : _body_context8.route) != null ? _ref8 : '',
1032
1043
  hostId: ((_body_context9 = body.context) == null ? void 0 : _body_context9.hostId) || null,
1033
1044
  tier: entitled ? 'entitled' : 'free',
1034
1045
  rate,
@@ -1072,7 +1083,7 @@ async function handler(request) {
1072
1083
  // month counts it beside the org counter the reservation moved.
1073
1084
  recordUserAiRefusal(firestore, body.orgId, decoded.uid, quota);
1074
1085
  if (!quota.allowed) {
1075
- var _ref7;
1086
+ var _ref9;
1076
1087
  // Five refusals, not two. The spend ceiling (AGL-2264) is armed by
1077
1088
  // default at $40, and it must not borrow the message cap's words:
1078
1089
  // "reached its limit for the month" invites the user to count their
@@ -1124,10 +1135,10 @@ async function handler(request) {
1124
1135
  }
1125
1136
  const ownControl = assistOwnControlRefusalText(org, refusedBy);
1126
1137
  return Response.json({
1127
- error: (_ref7 = ownControl != null ? ownControl : // The Free taste's own precautions (AGL-2925): a clock or an
1138
+ error: (_ref9 = ownControl != null ? ownControl : // The Free taste's own precautions (AGL-2925): a clock or an
1128
1139
  // upgrade, in one sentence, from the same helper the other
1129
1140
  // doors read.
1130
- assistFreeTasteRefusalText(refusedBy)) != null ? _ref7 : refusedBy === 'budget' || refusedBy === 'band' ? quota.budgetUsd === null ? 'This workspace reached its assistant spending limit for the month' : 'This workspace used its assistant credits for the month' : entitled ? 'This workspace reached its assistant limit for the month' : `Free workspaces get ${quota.limit} assistant messages a day — upgrade to Pro for more`,
1141
+ assistFreeTasteRefusalText(refusedBy)) != null ? _ref9 : refusedBy === 'budget' || refusedBy === 'band' ? quota.budgetUsd === null ? 'This workspace reached its assistant spending limit for the month' : 'This workspace used its assistant credits for the month' : entitled ? 'This workspace reached its assistant limit for the month' : `Free workspaces get ${quota.limit} assistant messages a day — upgrade to Pro for more`,
1131
1142
  reason: 'quota',
1132
1143
  // CREDITS, never the reservation itself: it carries `costUsd`,
1133
1144
  // `costLimitUsd` and `budgetUsd`, all three of which are our
@@ -1156,6 +1167,24 @@ async function handler(request) {
1156
1167
  const guide = entitled && body.context ? buildViewBlock(body.context, org, {
1157
1168
  edit: Boolean(editRung)
1158
1169
  }) : null;
1170
+ // A follow-up on a draft this thread's build made (AGL-3616): offered on
1171
+ // a site, where the navigation has a destination, and nowhere else.
1172
+ const drafts = (guide == null ? void 0 : guide.scope.hostId) ? body.drafts : [];
1173
+ const draftsBlock = assistBuildDraftsBlock(drafts);
1174
+ const proposalView = guide ? withAssistOpenDraftAction(guide.view, drafts) : null;
1175
+ // The site's business profile, status and memory (AGL-3661), for a turn
1176
+ // that may change the site: the edit and build rungs, whose host was
1177
+ // checked for `ai.generate` above. Free and paid read the same block. A
1178
+ // site breakpoint when the stable blocks leave one, volatile otherwise.
1179
+ const siteHostId = (_ref4 = (_ref5 = buildRung == null ? void 0 : buildRung.hostId) != null ? _ref5 : editRung == null ? void 0 : editRung.target.hostId) != null ? _ref4 : null;
1180
+ const siteContext = siteHostId ? await readAiSiteContext(firestore, {
1181
+ orgId: body.orgId,
1182
+ hostId: siteHostId
1183
+ }) : null;
1184
+ const stableBreakpoints = 1 + ((guide == null ? void 0 : guide.screen) ? 1 : 0) + (editRung ? 1 : 0) + (buildRung ? 1 : 0);
1185
+ const siteBlock = aiSiteContextSystemBlock(siteContext, {
1186
+ cache: stableBreakpoints < AI_MAX_CACHE_BREAKPOINTS
1187
+ });
1159
1188
  const messages = [
1160
1189
  ...body.history.map((turn)=>({
1161
1190
  role: turn.role,
@@ -1201,6 +1230,9 @@ async function handler(request) {
1201
1230
  cacheBreakpoint: true
1202
1231
  }
1203
1232
  ] : [],
1233
+ // The site's own block closes the cached span (AGL-3661): every block
1234
+ // above is shared by every workspace, this one is cached per site.
1235
+ ...siteBlock,
1204
1236
  // Per-org, and therefore AFTER every breakpoint — see
1205
1237
  // `assistBrandBlock`. Unconditional: a free workspace assembles no
1206
1238
  // view block, and it must still be told what the product is called.
@@ -1214,6 +1246,13 @@ async function handler(request) {
1214
1246
  volatile: true
1215
1247
  }
1216
1248
  ] : [],
1249
+ // The drafts a follow-up may open: the person's own labels, so volatile.
1250
+ ...draftsBlock ? [
1251
+ {
1252
+ text: draftsBlock,
1253
+ volatile: true
1254
+ }
1255
+ ] : [],
1217
1256
  // The canvas the author has open — their own content, so volatile.
1218
1257
  ...editRung ? [
1219
1258
  {
@@ -1362,7 +1401,7 @@ async function handler(request) {
1362
1401
  // registry rather than taken from the completion. A dropped
1363
1402
  // proposal costs the user a button; an honoured bad one costs
1364
1403
  // them trust.
1365
- const proposal = guide ? resolveAssistProposal(extractAssistAction(raw), guide.view, guide.scope) : null;
1404
+ const proposal = guide ? resolveAssistProposal(extractAssistAction(raw), proposalView, guide.scope, drafts) : null;
1366
1405
  // The edit proposal, if the model called the tool — held to the
1367
1406
  // canvas the request described and to the palette validators. Still
1368
1407
  // nothing is written: a proposal is data for a card the author