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

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 (248) 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-automation-zones.d.ts +38 -0
  6. package/src/lib/components/ai-automation-zones.js +5 -1
  7. package/src/lib/components/ai-automation-zones.js.map +1 -1
  8. package/src/lib/components/ai-brief-dialog.component.d.ts +20 -2
  9. package/src/lib/components/ai-brief-dialog.component.js +87 -8
  10. package/src/lib/components/ai-brief-dialog.component.js.map +1 -1
  11. package/src/lib/components/ai-campaign-create.component.d.ts +54 -0
  12. package/src/lib/components/ai-campaign-create.component.js +270 -0
  13. package/src/lib/components/ai-campaign-create.component.js.map +1 -0
  14. package/src/lib/components/ai-describe-automation.component.d.ts +8 -3
  15. package/src/lib/components/ai-describe-automation.component.js +15 -6
  16. package/src/lib/components/ai-describe-automation.component.js.map +1 -1
  17. package/src/lib/components/ai-describe-button.component.d.ts +20 -8
  18. package/src/lib/components/ai-describe-button.component.js +19 -36
  19. package/src/lib/components/ai-describe-button.component.js.map +1 -1
  20. package/src/lib/components/ai-describe-email.component.d.ts +31 -0
  21. package/src/lib/components/ai-describe-email.component.js +22 -0
  22. package/src/lib/components/ai-describe-email.component.js.map +1 -0
  23. package/src/lib/components/ai-describe-org-automation.component.d.ts +36 -0
  24. package/src/lib/components/ai-describe-org-automation.component.js +238 -0
  25. package/src/lib/components/ai-describe-org-automation.component.js.map +1 -0
  26. package/src/lib/components/ai-experiment-cards.component.d.ts +9 -1
  27. package/src/lib/components/ai-experiment-cards.component.js +104 -18
  28. package/src/lib/components/ai-experiment-cards.component.js.map +1 -1
  29. package/src/lib/components/ai-explain-automation.component.js +1 -5
  30. package/src/lib/components/ai-explain-automation.component.js.map +1 -1
  31. package/src/lib/components/ai-funnel-zones.component.d.ts +61 -0
  32. package/src/lib/components/ai-funnel-zones.component.js +178 -0
  33. package/src/lib/components/ai-funnel-zones.component.js.map +1 -0
  34. package/src/lib/components/ai-insight-card.component.d.ts +42 -0
  35. package/src/lib/components/ai-insight-card.component.js +137 -0
  36. package/src/lib/components/ai-insight-card.component.js.map +1 -0
  37. package/src/lib/components/ai-insight-dialog.component.d.ts +6 -0
  38. package/src/lib/components/ai-insight-dialog.component.js +9 -3
  39. package/src/lib/components/ai-insight-dialog.component.js.map +1 -1
  40. package/src/lib/components/ai-job-plan.component.d.ts +7 -2
  41. package/src/lib/components/ai-job-plan.component.js +35 -5
  42. package/src/lib/components/ai-job-plan.component.js.map +1 -1
  43. package/src/lib/components/ai-job-requests.d.ts +17 -1
  44. package/src/lib/components/ai-job-requests.js +39 -3
  45. package/src/lib/components/ai-job-requests.js.map +1 -1
  46. package/src/lib/components/ai-logic-zones.d.ts +64 -0
  47. package/src/lib/components/ai-logic-zones.js +18 -0
  48. package/src/lib/components/ai-logic-zones.js.map +1 -0
  49. package/src/lib/components/ai-logic.component.d.ts +77 -0
  50. package/src/lib/components/ai-logic.component.js +553 -0
  51. package/src/lib/components/ai-logic.component.js.map +1 -0
  52. package/src/lib/components/ai-marketing-insight.component.d.ts +30 -0
  53. package/src/lib/components/ai-marketing-insight.component.js +80 -0
  54. package/src/lib/components/ai-marketing-insight.component.js.map +1 -0
  55. package/src/lib/components/ai-media-create.component.d.ts +55 -0
  56. package/src/lib/components/ai-media-create.component.js +433 -0
  57. package/src/lib/components/ai-media-create.component.js.map +1 -0
  58. package/src/lib/components/ai-overlay-cards.component.d.ts +83 -0
  59. package/src/lib/components/ai-overlay-cards.component.js +505 -0
  60. package/src/lib/components/ai-overlay-cards.component.js.map +1 -0
  61. package/src/lib/components/ai-product-zones.d.ts +5 -0
  62. package/src/lib/components/ai-product-zones.js +1 -1
  63. package/src/lib/components/ai-product-zones.js.map +1 -1
  64. package/src/lib/components/ai-products-create-button.component.d.ts +42 -0
  65. package/src/lib/components/ai-products-create-button.component.js +67 -0
  66. package/src/lib/components/ai-products-create-button.component.js.map +1 -0
  67. package/src/lib/components/ai-products-hub-card.component.js +100 -81
  68. package/src/lib/components/ai-products-hub-card.component.js.map +1 -1
  69. package/src/lib/components/ai-revise-automation.component.d.ts +16 -0
  70. package/src/lib/components/ai-revise-automation.component.js +207 -0
  71. package/src/lib/components/ai-revise-automation.component.js.map +1 -0
  72. package/src/lib/components/ai-site-build-page.component.js +140 -16
  73. package/src/lib/components/ai-site-build-page.component.js.map +1 -1
  74. package/src/lib/components/ai-upsell-dialog.component.d.ts +53 -0
  75. package/src/lib/components/ai-upsell-dialog.component.js +177 -0
  76. package/src/lib/components/ai-upsell-dialog.component.js.map +1 -0
  77. package/src/lib/components/assist-build-card.component.d.ts +42 -0
  78. package/src/lib/components/assist-build-card.component.js +183 -0
  79. package/src/lib/components/assist-build-card.component.js.map +1 -0
  80. package/src/lib/components/assist-edit-canvas.d.ts +2 -0
  81. package/src/lib/components/assist-edit-canvas.js +56 -1
  82. package/src/lib/components/assist-edit-canvas.js.map +1 -1
  83. package/src/lib/components/assist-jobs-drawer.component.js +48 -3
  84. package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
  85. package/src/lib/components/assist-panel.component.js +51 -2
  86. package/src/lib/components/assist-panel.component.js.map +1 -1
  87. package/src/lib/components/use-ai-job-run.d.ts +3 -14
  88. package/src/lib/components/use-ai-job-run.js +0 -50
  89. package/src/lib/components/use-ai-job-run.js.map +1 -1
  90. package/src/lib/jobs/ai-build-capabilities.d.ts +58 -0
  91. package/src/lib/jobs/ai-build-capabilities.js +256 -0
  92. package/src/lib/jobs/ai-build-capabilities.js.map +1 -0
  93. package/src/lib/jobs/ai-build-unit-outcome.d.ts +52 -0
  94. package/src/lib/jobs/ai-build-unit-outcome.js +138 -0
  95. package/src/lib/jobs/ai-build-unit-outcome.js.map +1 -0
  96. package/src/lib/jobs/ai-job-build-step.d.ts +144 -0
  97. package/src/lib/jobs/ai-job-build-step.js +657 -0
  98. package/src/lib/jobs/ai-job-build-step.js.map +1 -0
  99. package/src/lib/jobs/ai-job-draft-ids.js +9 -1
  100. package/src/lib/jobs/ai-job-draft-ids.js.map +1 -1
  101. package/src/lib/jobs/ai-job-drafts.d.ts +14 -4
  102. package/src/lib/jobs/ai-job-drafts.js +25 -4
  103. package/src/lib/jobs/ai-job-drafts.js.map +1 -1
  104. package/src/lib/jobs/ai-job-logic-step.d.ts +107 -0
  105. package/src/lib/jobs/ai-job-logic-step.js +395 -0
  106. package/src/lib/jobs/ai-job-logic-step.js.map +1 -0
  107. package/src/lib/jobs/ai-job-overlay-copy.d.ts +70 -0
  108. package/src/lib/jobs/ai-job-overlay-copy.js +178 -0
  109. package/src/lib/jobs/ai-job-overlay-copy.js.map +1 -0
  110. package/src/lib/jobs/ai-job-page-step.js +6 -6
  111. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  112. package/src/lib/jobs/ai-job-plan-step.d.ts +26 -1
  113. package/src/lib/jobs/ai-job-plan-step.js +79 -11
  114. package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
  115. package/src/lib/jobs/ai-job-site-step.d.ts +15 -1
  116. package/src/lib/jobs/ai-job-site-step.js +200 -58
  117. package/src/lib/jobs/ai-job-site-step.js.map +1 -1
  118. package/src/lib/jobs/ai-job-text-step.d.ts +22 -1
  119. package/src/lib/jobs/ai-job-text-step.js +12 -0
  120. package/src/lib/jobs/ai-job-text-step.js.map +1 -1
  121. package/src/lib/jobs/ai-job-workflow-step.d.ts +54 -4
  122. package/src/lib/jobs/ai-job-workflow-step.js +318 -13
  123. package/src/lib/jobs/ai-job-workflow-step.js.map +1 -1
  124. package/src/lib/jobs/ai-jobs.d.ts +80 -2
  125. package/src/lib/jobs/ai-jobs.js +377 -13
  126. package/src/lib/jobs/ai-jobs.js.map +1 -1
  127. package/src/lib/jobs/ai-logic-records.d.ts +40 -0
  128. package/src/lib/jobs/ai-logic-records.js +55 -0
  129. package/src/lib/jobs/ai-logic-records.js.map +1 -0
  130. package/src/lib/jobs/ai-site-publish.d.ts +7 -0
  131. package/src/lib/jobs/ai-site-publish.js +9 -0
  132. package/src/lib/jobs/ai-site-publish.js.map +1 -1
  133. package/src/lib/jobs/ai-workflow-records.d.ts +4 -0
  134. package/src/lib/jobs/ai-workflow-records.js +40 -1
  135. package/src/lib/jobs/ai-workflow-records.js.map +1 -1
  136. package/src/lib/model/ai-automation-draft.d.ts +18 -0
  137. package/src/lib/model/ai-automation-draft.js +86 -0
  138. package/src/lib/model/ai-automation-draft.js.map +1 -1
  139. package/src/lib/model/ai-build-job.d.ts +201 -0
  140. package/src/lib/model/ai-build-job.js +471 -0
  141. package/src/lib/model/ai-build-job.js.map +1 -0
  142. package/src/lib/model/ai-build-plan.d.ts +61 -0
  143. package/src/lib/model/ai-build-plan.js +154 -9
  144. package/src/lib/model/ai-build-plan.js.map +1 -1
  145. package/src/lib/model/ai-build-progress.d.ts +56 -0
  146. package/src/lib/model/ai-build-progress.js +128 -0
  147. package/src/lib/model/ai-build-progress.js.map +1 -0
  148. package/src/lib/model/ai-insight.d.ts +20 -10
  149. package/src/lib/model/ai-insight.js +72 -9
  150. package/src/lib/model/ai-insight.js.map +1 -1
  151. package/src/lib/model/ai-job-activity.js +3 -1
  152. package/src/lib/model/ai-job-activity.js.map +1 -1
  153. package/src/lib/model/ai-jobs.types.d.ts +80 -2
  154. package/src/lib/model/ai-jobs.types.js +3 -1
  155. package/src/lib/model/ai-jobs.types.js.map +1 -1
  156. package/src/lib/model/ai-logic-job.d.ts +108 -0
  157. package/src/lib/model/ai-logic-job.js +327 -0
  158. package/src/lib/model/ai-logic-job.js.map +1 -0
  159. package/src/lib/model/ai-media-credits.d.ts +52 -0
  160. package/src/lib/model/ai-media-credits.js +61 -0
  161. package/src/lib/model/ai-media-credits.js.map +1 -0
  162. package/src/lib/model/ai-overlay-copy.d.ts +114 -0
  163. package/src/lib/model/ai-overlay-copy.js +175 -0
  164. package/src/lib/model/ai-overlay-copy.js.map +1 -0
  165. package/src/lib/model/ai-site-build-progress.d.ts +20 -3
  166. package/src/lib/model/ai-site-build-progress.js +170 -10
  167. package/src/lib/model/ai-site-build-progress.js.map +1 -1
  168. package/src/lib/model/ai-svg.d.ts +69 -0
  169. package/src/lib/model/ai-svg.js +265 -0
  170. package/src/lib/model/ai-svg.js.map +1 -0
  171. package/src/lib/model/ai-usage-by-user.d.ts +3 -2
  172. package/src/lib/model/ai-usage-by-user.js.map +1 -1
  173. package/src/lib/model/ai-workflow-job.d.ts +92 -4
  174. package/src/lib/model/ai-workflow-job.js +124 -7
  175. package/src/lib/model/ai-workflow-job.js.map +1 -1
  176. package/src/lib/model/assist-build.d.ts +58 -0
  177. package/src/lib/model/assist-build.js +52 -0
  178. package/src/lib/model/assist-build.js.map +1 -0
  179. package/src/lib/model/assist-edit.d.ts +48 -3
  180. package/src/lib/model/assist-edit.js +48 -4
  181. package/src/lib/model/assist-edit.js.map +1 -1
  182. package/src/lib/plugin-config.js +2 -0
  183. package/src/lib/plugin-config.js.map +1 -1
  184. package/src/lib/plugin.js +240 -11
  185. package/src/lib/plugin.js.map +1 -1
  186. package/src/lib/providers/catalog.d.ts +81 -4
  187. package/src/lib/providers/catalog.js +80 -9
  188. package/src/lib/providers/catalog.js.map +1 -1
  189. package/src/lib/providers/image-contract.d.ts +116 -0
  190. package/src/lib/providers/image-contract.js +74 -0
  191. package/src/lib/providers/image-contract.js.map +1 -0
  192. package/src/lib/providers/model-choice.js +11 -0
  193. package/src/lib/providers/model-choice.js.map +1 -1
  194. package/src/lib/providers/routing.js +18 -0
  195. package/src/lib/providers/routing.js.map +1 -1
  196. package/src/lib/providers/vertex-image.d.ts +121 -0
  197. package/src/lib/providers/vertex-image.js +312 -0
  198. package/src/lib/providers/vertex-image.js.map +1 -0
  199. package/src/lib/runtime/ai-doctrine-validators.d.ts +19 -0
  200. package/src/lib/runtime/ai-doctrine-validators.js +89 -0
  201. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
  202. package/src/lib/runtime/ai-doctrine.js +11 -5
  203. package/src/lib/runtime/ai-doctrine.js.map +1 -1
  204. package/src/lib/runtime/ai-eval-live.js +4 -0
  205. package/src/lib/runtime/ai-eval-live.js.map +1 -1
  206. package/src/lib/runtime/ai-eval.d.ts +15 -1
  207. package/src/lib/runtime/ai-eval.js +52 -1
  208. package/src/lib/runtime/ai-eval.js.map +1 -1
  209. package/src/lib/runtime/experiment-variant-copy.d.ts +34 -0
  210. package/src/lib/runtime/experiment-variant-copy.js +102 -0
  211. package/src/lib/runtime/experiment-variant-copy.js.map +1 -0
  212. package/src/lib/server/ai-experiment-versions.d.ts +51 -0
  213. package/src/lib/server/ai-experiment-versions.js +270 -0
  214. package/src/lib/server/ai-experiment-versions.js.map +1 -0
  215. package/src/lib/server/ai-jobs-resume.js +74 -4
  216. package/src/lib/server/ai-jobs-resume.js.map +1 -1
  217. package/src/lib/server/ai-media-image.d.ts +66 -0
  218. package/src/lib/server/ai-media-image.js +521 -0
  219. package/src/lib/server/ai-media-image.js.map +1 -0
  220. package/src/lib/server/ai-media-svg.d.ts +91 -0
  221. package/src/lib/server/ai-media-svg.js +186 -0
  222. package/src/lib/server/ai-media-svg.js.map +1 -0
  223. package/src/lib/server/assist-build.d.ts +54 -0
  224. package/src/lib/server/assist-build.js +121 -0
  225. package/src/lib/server/assist-build.js.map +1 -0
  226. package/src/lib/server/assist-chat.js +108 -12
  227. package/src/lib/server/assist-chat.js.map +1 -1
  228. package/src/lib/server/assist-edit.js +213 -3
  229. package/src/lib/server/assist-edit.js.map +1 -1
  230. package/src/lib/server/assist-view-context.js +242 -4
  231. package/src/lib/server/assist-view-context.js.map +1 -1
  232. package/src/lib/server.js +26 -0
  233. package/src/lib/server.js.map +1 -1
  234. package/src/lib/tools/ai-logic-tool.d.ts +27 -0
  235. package/src/lib/tools/ai-logic-tool.js +207 -0
  236. package/src/lib/tools/ai-logic-tool.js.map +1 -0
  237. package/src/lib/tools/ai-overlay-tool.d.ts +35 -0
  238. package/src/lib/tools/ai-overlay-tool.js +107 -0
  239. package/src/lib/tools/ai-overlay-tool.js.map +1 -0
  240. package/src/lib/tools/ai-workflow-tool.d.ts +11 -0
  241. package/src/lib/tools/ai-workflow-tool.js +31 -0
  242. package/src/lib/tools/ai-workflow-tool.js.map +1 -1
  243. package/src/lib/usage/assist-job-refund.d.ts +28 -1
  244. package/src/lib/usage/assist-job-refund.js +44 -9
  245. package/src/lib/usage/assist-job-refund.js.map +1 -1
  246. package/src/lib/usage/assist-usage.d.ts +5 -0
  247. package/src/lib/usage/assist-usage.js +2 -0
  248. package/src/lib/usage/assist-usage.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/model/ai-automation-draft.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 describeInteractionPlaceholder,\n draftPlaceholder,\n type InteractionPlaceholder,\n interactionPlaceholders,\n} from '@aglyn/aglyn/app-utils/draft-placeholders'\nimport type { InteractionCondition, InteractionStepGuard } from '@aglyn/aglyn/app-utils/site-interactions'\nimport type { AiAutomation, AiAutomationStep } from './ai-automation-format'\nimport type {\n AiAutomationAnswer,\n AiAutomationAnswerStep,\n AiAutomationCondition,\n} from '../tools/ai-workflow-tool'\n\n/**\n * An answer made into the automation the workflows plugin stores (AGL-2919).\n *\n * The answer names each record in WORDS. Here, in code and after the answer,\n * each is looked up among the site's own records: a list, a campaign, a\n * workflow, a webhook, a dataset, a form or a deal stage the words name\n * without doubt becomes that record's id; words that name none, or name more\n * than one, become a placeholder — the words in square brackets where the\n * record belongs — for the person to pick in the Actions editor. Nothing is\n * guessed, and the model never saw the records it was matched against beyond\n * what the site inventory already sends.\n */\n\n/** One record a description may name. */\nexport interface AiAutomationNamedRecord {\n id: string\n name: string\n}\n\n/** A form, with the fields its submissions carry. */\nexport interface AiAutomationForm extends AiAutomationNamedRecord {\n fields: string[]\n}\n\n/** The site's records an automation's words are looked up among. */\nexport interface AiAutomationRecords {\n forms: AiAutomationForm[]\n datasets: AiAutomationNamedRecord[]\n lists: AiAutomationNamedRecord[]\n campaigns: AiAutomationNamedRecord[]\n workflows: AiAutomationNamedRecord[]\n webhooks: AiAutomationNamedRecord[]\n /** Every stage of every pipeline the site may see. */\n stages: AiAutomationNamedRecord[]\n}\n\nexport function emptyAiAutomationRecords(): AiAutomationRecords {\n return { forms: [], datasets: [], lists: [], campaigns: [], workflows: [], webhooks: [], stages: [] }\n}\n\n/** Words that say nothing about which record is meant. */\nconst FILLER = new Set(['the', 'a', 'an', 'our', 'my', 'your', 'this', 'that', 'new', 'called', 'named'])\n\nfunction tokens(value: string, noun: string): string[] {\n const nouns = new Set([noun, `${noun}s`])\n return value\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}]+/gu, ' ')\n .split(' ')\n .filter(Boolean)\n .filter((word) => !FILLER.has(word) && !nouns.has(word))\n .map((word) => (word.length > 3 && word.endsWith('s') && !word.endsWith('ss') ? word.slice(0, -1) : word))\n}\n\n/**\n * The one record `words` name, or `null`: its id written whole; else the one\n * record whose name is the same words; else the one record whose name holds\n * every word, or whose every word the words hold. Two records that fit\n * equally well name neither — a placeholder is better than a coin toss.\n */\nexport function aiMatchNamedRecord<T extends AiAutomationNamedRecord>(\n words: string,\n records: readonly T[],\n noun: string,\n): T | null {\n const wanted = words.trim()\n if (!wanted) return null\n const byId = records.filter((record) => record.id === wanted)\n if (byId.length === 1) return byId[0]\n const asked = tokens(wanted, noun)\n if (!asked.length) return null\n const same = (record: T) => {\n const name = tokens(record.name, noun)\n return name.length === asked.length && asked.every((word) => name.includes(word))\n }\n const exact = records.filter(same)\n if (exact.length) return exact.length === 1 ? exact[0] : null\n const within = records.filter((record) => {\n const name = tokens(record.name, noun)\n if (!name.length) return false\n const [small, large] = name.length <= asked.length ? [name, asked] : [asked, name]\n return small.every((word) => large.includes(word))\n })\n return within.length === 1 ? within[0] : null\n}\n\n/** A form by its id or its name, for a condition that names one. */\nfunction formOf(value: string, forms: readonly AiAutomationForm[]): AiAutomationForm | null {\n return aiMatchNamedRecord(value, forms, 'form')\n}\n\nfunction conditionOf(\n condition: AiAutomationCondition,\n records: AiAutomationRecords,\n): InteractionCondition {\n const { field, op, value } = condition\n if (op === 'notEmpty' || value === null) return { field, op }\n if (field === 'formId') {\n const form = formOf(value, records.forms)\n return { field, op, value: form ? form.id : draftPlaceholder(value) }\n }\n if (field === 'formName') {\n const form = formOf(value, records.forms)\n return { field, op, value: form ? form.name : draftPlaceholder(value) }\n }\n if (field === 'stageId' || field === 'previousStageId') {\n const stage = aiMatchNamedRecord(value, records.stages, 'stage')\n return { field, op, value: stage ? stage.id : draftPlaceholder(value) }\n }\n return { field, op, value }\n}\n\nfunction guardOf(\n when: AiAutomationCondition | null,\n records: AiAutomationRecords,\n): { when?: InteractionStepGuard } {\n return when ? { when: { conditions: [conditionOf(when, records)] } } : {}\n}\n\n/** A named record as a step stores it: the id and the name, or a placeholder name and no id. */\nfunction referenceOf(\n words: string | null,\n records: readonly AiAutomationNamedRecord[],\n noun: string,\n): { id: string | null; name: string } {\n const record = aiMatchNamedRecord(words ?? '', records, noun)\n return record ? { id: record.id, name: record.name } : { id: null, name: draftPlaceholder(words ?? '') }\n}\n\nfunction stepOf(step: AiAutomationAnswerStep, records: AiAutomationRecords): AiAutomationStep {\n const guard = guardOf(step.when, records)\n switch (step.type) {\n case 'sendEmail':\n return {\n type: 'sendEmail',\n subject: step.subject ?? '',\n body: step.body ?? '',\n ...(step.toField ? { toField: step.toField } : {}),\n ...guard,\n }\n case 'notifyAdmins':\n return { type: 'notifyAdmins', title: step.title ?? '', ...guard }\n case 'enrollList': {\n const { id, name } = referenceOf(step.list, records.lists, 'list')\n return { type: 'enrollList', ...(id ? { listId: id } : {}), listName: name, ...guard }\n }\n case 'assignCampaign': {\n const { id, name } = referenceOf(step.campaign, records.campaigns, 'campaign')\n return { type: 'assignCampaign', ...(id ? { campaignId: id } : {}), campaignName: name, ...guard }\n }\n case 'runWorkflow': {\n const { id, name } = referenceOf(step.workflow, records.workflows, 'workflow')\n return { type: 'runWorkflow', ...(id ? { workflowId: id } : {}), workflowName: name, ...guard }\n }\n case 'webhookPost': {\n const { id, name } = referenceOf(step.webhook, records.webhooks, 'webhook')\n return { type: 'webhookPost', ...(id ? { webhookId: id } : {}), webhookName: name, ...guard }\n }\n case 'datasetAppend':\n case 'updateDataset': {\n const { id, name } = referenceOf(step.dataset, records.datasets, 'dataset')\n return { type: step.type, ...(id ? { datasetId: id } : {}), datasetName: name, ...guard }\n }\n case 'siteAlert':\n return { type: 'siteAlert', message: step.message ?? '', severity: step.severity ?? 'info', ...guard }\n case 'wait':\n return { type: 'wait', delayMinutes: step.minutes ?? 0, ...guard }\n case 'waitForEvent':\n return {\n type: 'waitForEvent',\n eventName: step.event ?? '',\n timeoutMinutes: step.minutes ?? 0,\n ...guard,\n }\n case 'exitFlow':\n return { type: 'exitFlow', ...guard }\n case 'setContactStage':\n return { type: 'setContactStage', lifecycleStage: step.stage ?? 'lead', ...guard }\n case 'addContactTag':\n return { type: 'addContactTag', tag: step.tag ?? '', ...guard }\n case 'assignContactOwner':\n return step.owner === 'round robin'\n ? { type: 'assignContactOwner', roundRobin: true, ...guard }\n : { type: 'assignContactOwner', ownerEmail: step.owner ?? '', ...guard }\n case 'createCrmTask':\n return {\n type: 'createCrmTask',\n title: step.title ?? '',\n kind: step.taskKind ?? 'todo',\n // The runner stores the org's label for the meaning (AGL-3538).\n ...(step.priority ? { priority: step.priority } : {}),\n dueInDays: step.dueInDays ?? 0,\n ...guard,\n }\n case 'logCrmActivity':\n return {\n type: 'logCrmActivity',\n kind: step.activityKind ?? 'note',\n body: step.body ?? '',\n ...(step.direction ? { direction: step.direction } : {}),\n ...guard,\n }\n }\n}\n\n/** The name an automation is drafted under when the answer gave none. */\nexport const AI_AUTOMATION_DEFAULT_NAME = 'New automation'\n\nexport interface AiAutomationDraft {\n /** The automation as the workflows plugin stores it: OFF. */\n action: AiAutomation\n /** What a person still has to supply before switching it on. */\n placeholders: InteractionPlaceholder[]\n}\n\n/** An answer as the automation to store, with every record it names looked up. */\nexport function aiAutomationDraft(\n answer: AiAutomationAnswer,\n records: AiAutomationRecords,\n): AiAutomationDraft {\n const conditions = answer.trigger.conditions.map((condition) => conditionOf(condition, records))\n const action: AiAutomation = {\n name: answer.name || AI_AUTOMATION_DEFAULT_NAME,\n trigger: {\n event: answer.trigger.event,\n ...(conditions.length ? { conditions, combinator: answer.trigger.combinator } : {}),\n },\n steps: answer.steps.map((step) => stepOf(step, records)),\n enabled: false,\n }\n return { action, placeholders: interactionPlaceholders(action) }\n}\n\n/**\n * What a drafted automation's output tells a person: that it is off, what to\n * fill in before switching it on, and what the answer said needs deciding.\n */\nexport function aiAutomationDraftNote(draft: AiAutomationDraft, notes: readonly string[]): string {\n const parts = ['It is off until you switch it on.']\n if (draft.placeholders.length) {\n parts.push(\n `Fill in ${draft.placeholders.length === 1 ? 'its placeholder' : `its ${draft.placeholders.length} placeholders`} first — ${draft.placeholders\n .map(describeInteractionPlaceholder)\n .join('; ')}.`,\n )\n } else {\n parts.push('Review its steps in the Actions editor, then switch it on from the list.')\n }\n parts.push(...notes)\n return parts.join(' ')\n}\n"],"names":["describeInteractionPlaceholder","draftPlaceholder","interactionPlaceholders","emptyAiAutomationRecords","forms","datasets","lists","campaigns","workflows","webhooks","stages","FILLER","Set","tokens","value","noun","nouns","toLowerCase","replace","split","filter","Boolean","word","has","map","length","endsWith","slice","aiMatchNamedRecord","words","records","wanted","trim","byId","record","id","asked","same","name","every","includes","exact","within","small","large","formOf","conditionOf","condition","field","op","form","stage","guardOf","when","conditions","referenceOf","stepOf","step","guard","type","subject","body","toField","title","list","listId","listName","campaign","campaignId","campaignName","workflow","workflowId","workflowName","webhook","webhookId","webhookName","dataset","datasetId","datasetName","message","severity","delayMinutes","minutes","eventName","event","timeoutMinutes","lifecycleStage","tag","owner","roundRobin","ownerEmail","kind","taskKind","priority","dueInDays","activityKind","direction","AI_AUTOMATION_DEFAULT_NAME","aiAutomationDraft","answer","trigger","action","combinator","steps","enabled","placeholders","aiAutomationDraftNote","draft","notes","parts","push","join"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/model/ai-automation-draft.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 describeInteractionPlaceholder,\n draftPlaceholder,\n type InteractionPlaceholder,\n interactionPlaceholders,\n} from '@aglyn/aglyn/app-utils/draft-placeholders'\nimport type { InteractionCondition, InteractionStepGuard } from '@aglyn/aglyn/app-utils/site-interactions'\nimport type { AiAutomation, AiAutomationStep } from './ai-automation-format'\nimport type {\n AiAutomationAnswer,\n AiAutomationAnswerStep,\n AiAutomationCondition,\n} from '../tools/ai-workflow-tool'\n\n/**\n * An answer made into the automation the workflows plugin stores (AGL-2919).\n *\n * The answer names each record in WORDS. Here, in code and after the answer,\n * each is looked up among the site's own records: a list, a campaign, a\n * workflow, a webhook, a dataset, a form or a deal stage the words name\n * without doubt becomes that record's id; words that name none, or name more\n * than one, become a placeholder — the words in square brackets where the\n * record belongs — for the person to pick in the Actions editor. Nothing is\n * guessed, and the model never saw the records it was matched against beyond\n * what the site inventory already sends.\n */\n\n/** One record a description may name. */\nexport interface AiAutomationNamedRecord {\n id: string\n name: string\n}\n\n/** A form, with the fields its submissions carry. */\nexport interface AiAutomationForm extends AiAutomationNamedRecord {\n fields: string[]\n}\n\n/** The site's records an automation's words are looked up among. */\nexport interface AiAutomationRecords {\n forms: AiAutomationForm[]\n datasets: AiAutomationNamedRecord[]\n lists: AiAutomationNamedRecord[]\n campaigns: AiAutomationNamedRecord[]\n workflows: AiAutomationNamedRecord[]\n webhooks: AiAutomationNamedRecord[]\n /** Every stage of every pipeline the site may see. */\n stages: AiAutomationNamedRecord[]\n}\n\nexport function emptyAiAutomationRecords(): AiAutomationRecords {\n return { forms: [], datasets: [], lists: [], campaigns: [], workflows: [], webhooks: [], stages: [] }\n}\n\n/** Words that say nothing about which record is meant. */\nconst FILLER = new Set(['the', 'a', 'an', 'our', 'my', 'your', 'this', 'that', 'new', 'called', 'named'])\n\nfunction tokens(value: string, noun: string): string[] {\n const nouns = new Set([noun, `${noun}s`])\n return value\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}]+/gu, ' ')\n .split(' ')\n .filter(Boolean)\n .filter((word) => !FILLER.has(word) && !nouns.has(word))\n .map((word) => (word.length > 3 && word.endsWith('s') && !word.endsWith('ss') ? word.slice(0, -1) : word))\n}\n\n/**\n * The one record `words` name, or `null`: its id written whole; else the one\n * record whose name is the same words; else the one record whose name holds\n * every word, or whose every word the words hold. Two records that fit\n * equally well name neither — a placeholder is better than a coin toss.\n */\nexport function aiMatchNamedRecord<T extends AiAutomationNamedRecord>(\n words: string,\n records: readonly T[],\n noun: string,\n): T | null {\n const wanted = words.trim()\n if (!wanted) return null\n const byId = records.filter((record) => record.id === wanted)\n if (byId.length === 1) return byId[0]\n const asked = tokens(wanted, noun)\n if (!asked.length) return null\n const same = (record: T) => {\n const name = tokens(record.name, noun)\n return name.length === asked.length && asked.every((word) => name.includes(word))\n }\n const exact = records.filter(same)\n if (exact.length) return exact.length === 1 ? exact[0] : null\n const within = records.filter((record) => {\n const name = tokens(record.name, noun)\n if (!name.length) return false\n const [small, large] = name.length <= asked.length ? [name, asked] : [asked, name]\n return small.every((word) => large.includes(word))\n })\n return within.length === 1 ? within[0] : null\n}\n\n/** A form by its id or its name, for a condition that names one. */\nfunction formOf(value: string, forms: readonly AiAutomationForm[]): AiAutomationForm | null {\n return aiMatchNamedRecord(value, forms, 'form')\n}\n\nfunction conditionOf(\n condition: AiAutomationCondition,\n records: AiAutomationRecords,\n): InteractionCondition {\n const { field, op, value } = condition\n if (op === 'notEmpty' || value === null) return { field, op }\n if (field === 'formId') {\n const form = formOf(value, records.forms)\n return { field, op, value: form ? form.id : draftPlaceholder(value) }\n }\n if (field === 'formName') {\n const form = formOf(value, records.forms)\n return { field, op, value: form ? form.name : draftPlaceholder(value) }\n }\n if (field === 'stageId' || field === 'previousStageId') {\n const stage = aiMatchNamedRecord(value, records.stages, 'stage')\n return { field, op, value: stage ? stage.id : draftPlaceholder(value) }\n }\n return { field, op, value }\n}\n\nfunction guardOf(\n when: AiAutomationCondition | null,\n records: AiAutomationRecords,\n): { when?: InteractionStepGuard } {\n return when ? { when: { conditions: [conditionOf(when, records)] } } : {}\n}\n\n/** A named record as a step stores it: the id and the name, or a placeholder name and no id. */\nfunction referenceOf(\n words: string | null,\n records: readonly AiAutomationNamedRecord[],\n noun: string,\n): { id: string | null; name: string } {\n const record = aiMatchNamedRecord(words ?? '', records, noun)\n return record ? { id: record.id, name: record.name } : { id: null, name: draftPlaceholder(words ?? '') }\n}\n\nfunction stepOf(step: AiAutomationAnswerStep, records: AiAutomationRecords): AiAutomationStep {\n const guard = guardOf(step.when, records)\n switch (step.type) {\n case 'sendEmail':\n return {\n type: 'sendEmail',\n subject: step.subject ?? '',\n body: step.body ?? '',\n ...(step.toField ? { toField: step.toField } : {}),\n ...guard,\n }\n case 'notifyAdmins':\n return { type: 'notifyAdmins', title: step.title ?? '', ...guard }\n case 'enrollList': {\n const { id, name } = referenceOf(step.list, records.lists, 'list')\n return { type: 'enrollList', ...(id ? { listId: id } : {}), listName: name, ...guard }\n }\n case 'assignCampaign': {\n const { id, name } = referenceOf(step.campaign, records.campaigns, 'campaign')\n return { type: 'assignCampaign', ...(id ? { campaignId: id } : {}), campaignName: name, ...guard }\n }\n case 'runWorkflow': {\n const { id, name } = referenceOf(step.workflow, records.workflows, 'workflow')\n return { type: 'runWorkflow', ...(id ? { workflowId: id } : {}), workflowName: name, ...guard }\n }\n case 'webhookPost': {\n const { id, name } = referenceOf(step.webhook, records.webhooks, 'webhook')\n return { type: 'webhookPost', ...(id ? { webhookId: id } : {}), webhookName: name, ...guard }\n }\n case 'datasetAppend':\n case 'updateDataset': {\n const { id, name } = referenceOf(step.dataset, records.datasets, 'dataset')\n return { type: step.type, ...(id ? { datasetId: id } : {}), datasetName: name, ...guard }\n }\n case 'siteAlert':\n return { type: 'siteAlert', message: step.message ?? '', severity: step.severity ?? 'info', ...guard }\n case 'wait':\n return { type: 'wait', delayMinutes: step.minutes ?? 0, ...guard }\n case 'waitForEvent':\n return {\n type: 'waitForEvent',\n eventName: step.event ?? '',\n timeoutMinutes: step.minutes ?? 0,\n ...guard,\n }\n case 'exitFlow':\n return { type: 'exitFlow', ...guard }\n case 'setContactStage':\n return { type: 'setContactStage', lifecycleStage: step.stage ?? 'lead', ...guard }\n case 'addContactTag':\n return { type: 'addContactTag', tag: step.tag ?? '', ...guard }\n case 'assignContactOwner':\n return step.owner === 'round robin'\n ? { type: 'assignContactOwner', roundRobin: true, ...guard }\n : { type: 'assignContactOwner', ownerEmail: step.owner ?? '', ...guard }\n case 'createCrmTask':\n return {\n type: 'createCrmTask',\n title: step.title ?? '',\n kind: step.taskKind ?? 'todo',\n // The runner stores the org's label for the meaning (AGL-3538).\n ...(step.priority ? { priority: step.priority } : {}),\n dueInDays: step.dueInDays ?? 0,\n ...guard,\n }\n case 'logCrmActivity':\n return {\n type: 'logCrmActivity',\n kind: step.activityKind ?? 'note',\n body: step.body ?? '',\n ...(step.direction ? { direction: step.direction } : {}),\n ...guard,\n }\n }\n}\n\n/** The name an automation is drafted under when the answer gave none. */\nexport const AI_AUTOMATION_DEFAULT_NAME = 'New automation'\n\nexport interface AiAutomationDraft {\n /** The automation as the workflows plugin stores it: OFF. */\n action: AiAutomation\n /** What a person still has to supply before switching it on. */\n placeholders: InteractionPlaceholder[]\n}\n\n/** An answer as the automation to store, with every record it names looked up. */\nexport function aiAutomationDraft(\n answer: AiAutomationAnswer,\n records: AiAutomationRecords,\n): AiAutomationDraft {\n const conditions = answer.trigger.conditions.map((condition) => conditionOf(condition, records))\n const action: AiAutomation = {\n name: answer.name || AI_AUTOMATION_DEFAULT_NAME,\n trigger: {\n event: answer.trigger.event,\n ...(conditions.length ? { conditions, combinator: answer.trigger.combinator } : {}),\n },\n steps: answer.steps.map((step) => stepOf(step, records)),\n enabled: false,\n }\n return { action, placeholders: interactionPlaceholders(action) }\n}\n\n/**\n * What a drafted automation's output tells a person: that it is off, what to\n * fill in before switching it on, and what the answer said needs deciding.\n */\nexport function aiAutomationDraftNote(draft: AiAutomationDraft, notes: readonly string[]): string {\n const parts = ['It is off until you switch it on.']\n if (draft.placeholders.length) {\n parts.push(\n `Fill in ${draft.placeholders.length === 1 ? 'its placeholder' : `its ${draft.placeholders.length} placeholders`} first — ${draft.placeholders\n .map(describeInteractionPlaceholder)\n .join('; ')}.`,\n )\n } else {\n parts.push('Review its steps in the Actions editor, then switch it on from the list.')\n }\n parts.push(...notes)\n return parts.join(' ')\n}\n\n/** A step as compared across a revision: its stored fields, in a fixed key order. */\nfunction stepSignature(step: AiAutomationStep): string {\n const record = step as unknown as Record<string, unknown>\n return JSON.stringify(Object.keys(record).sort().map((key) => [key, record[key]]))\n}\n\n/** The longest run of `after` that `before` holds in order, as a pair of kept flags. */\nfunction keptSteps(before: readonly string[], after: readonly string[]): [boolean[], boolean[]] {\n const table = Array.from({ length: before.length + 1 }, () => new Array<number>(after.length + 1).fill(0))\n for (let i = before.length - 1; i >= 0; i -= 1) {\n for (let j = after.length - 1; j >= 0; j -= 1) {\n table[i][j] = before[i] === after[j] ? table[i + 1][j + 1] + 1 : Math.max(table[i + 1][j], table[i][j + 1])\n }\n }\n const keptBefore = before.map(() => false)\n const keptAfter = after.map(() => false)\n let i = 0\n let j = 0\n while (i < before.length && j < after.length) {\n if (before[i] === after[j]) {\n keptBefore[i] = true\n keptAfter[j] = true\n i += 1\n j += 1\n } else if (table[i + 1][j] >= table[i][j + 1]) i += 1\n else j += 1\n }\n return [keptBefore, keptAfter]\n}\n\n/**\n * What a revised draft changed from the saved action it was drawn from\n * (AGL-3603), worked out in code from the two stored shapes — never the\n * model's own account of what it did. A step whose kind is both removed and\n * added — edited, or moved — is reported as changed.\n */\nexport function aiAutomationRevisionChanges(\n before: Pick<AiAutomation, 'trigger' | 'steps'>,\n after: Pick<AiAutomation, 'trigger' | 'steps'>,\n label: (type: string) => string,\n): string[] {\n const changes: string[] = []\n if (before.trigger?.event !== after.trigger?.event) changes.push('It starts on a different event.')\n else {\n const conditions = (trigger: AiAutomation['trigger'] | undefined) =>\n JSON.stringify({ conditions: trigger?.conditions ?? [], combinator: trigger?.conditions?.length ? trigger.combinator ?? 'and' : null })\n if (conditions(before.trigger) !== conditions(after.trigger)) changes.push('Its conditions changed.')\n }\n const beforeSteps = before.steps ?? []\n const afterSteps = after.steps ?? []\n const [keptBefore, keptAfter] = keptSteps(beforeSteps.map(stepSignature), afterSteps.map(stepSignature))\n const removed = beforeSteps.filter((_, index) => !keptBefore[index]).map((step) => label(step.type))\n const added = afterSteps.filter((_, index) => !keptAfter[index]).map((step) => label(step.type))\n const changed = [...new Set(removed.filter((name) => added.includes(name)))]\n const only = (names: string[]) => [...new Set(names.filter((name) => !changed.includes(name)))]\n if (changed.length) changes.push(`Changed: ${changed.join(', ')}.`)\n if (only(added).length) changes.push(`Added: ${only(added).join(', ')}.`)\n if (only(removed).length) changes.push(`Removed: ${only(removed).join(', ')}.`)\n return changes\n}\n\n/**\n * What a revised draft's output tells a person: which saved action it was\n * drawn from, what changed, that the saved one is untouched, and the draft's\n * own note.\n */\nexport function aiAutomationRevisionNote(\n input: { fromName: string; changes: readonly string[]; draft: AiAutomationDraft; notes: readonly string[] },\n): string {\n const changes = input.changes.length ? input.changes : ['Nothing changed from the saved action.']\n return [\n `A changed copy of “${input.fromName}”, which is left as it is.`,\n ...changes,\n aiAutomationDraftNote(input.draft, input.notes),\n 'Switch the old one off when you switch this one on.',\n ].join(' ')\n}\n"],"names":["describeInteractionPlaceholder","draftPlaceholder","interactionPlaceholders","emptyAiAutomationRecords","forms","datasets","lists","campaigns","workflows","webhooks","stages","FILLER","Set","tokens","value","noun","nouns","toLowerCase","replace","split","filter","Boolean","word","has","map","length","endsWith","slice","aiMatchNamedRecord","words","records","wanted","trim","byId","record","id","asked","same","name","every","includes","exact","within","small","large","formOf","conditionOf","condition","field","op","form","stage","guardOf","when","conditions","referenceOf","stepOf","step","guard","type","subject","body","toField","title","list","listId","listName","campaign","campaignId","campaignName","workflow","workflowId","workflowName","webhook","webhookId","webhookName","dataset","datasetId","datasetName","message","severity","delayMinutes","minutes","eventName","event","timeoutMinutes","lifecycleStage","tag","owner","roundRobin","ownerEmail","kind","taskKind","priority","dueInDays","activityKind","direction","AI_AUTOMATION_DEFAULT_NAME","aiAutomationDraft","answer","trigger","action","combinator","steps","enabled","placeholders","aiAutomationDraftNote","draft","notes","parts","push","join","stepSignature","JSON","stringify","Object","keys","sort","key","keptSteps","before","after","table","Array","from","fill","i","j","Math","max","keptBefore","keptAfter","aiAutomationRevisionChanges","label","changes","beforeSteps","afterSteps","removed","_","index","added","changed","only","names","aiAutomationRevisionNote","input","fromName"],"mappings":"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"}
@@ -0,0 +1,201 @@
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
+ import { type PluginAiCapability } from '@aglyn/aglyn/plugin-manager/plugin-ai-capabilities';
18
+ import { type AiBuildItem, type AiBuildPlan, type AiBuildPlanCreate, type AiBuildPlanCreateKind, type AiBuildPlanScreen } from './ai-build-plan';
19
+ import type { AiJobItemLedger } from './ai-jobs.types';
20
+ /**
21
+ * What a `build` job is (AGL-3616): one request — "a few pages, a contact
22
+ * form and a way to book me" — planned as creations, pages and items, built
23
+ * one UNIT a pass in dependency order, and settled ITEM BY ITEM.
24
+ *
25
+ * A build is a generalized site scaffold. Every unit is handed to what
26
+ * already builds that kind of thing — a page to the page step, a form to the
27
+ * form step, another plugin's resource to that plugin's draft writer — so a
28
+ * build cannot drift from what it builds. What is new is the settlement: one
29
+ * failed unit does not end the job. It gives back its own spend, the units
30
+ * that depended on it are built without it (or skipped, when they cannot
31
+ * stand without it), and the job is `done` when anything was delivered.
32
+ *
33
+ * This module is the build's MODEL — its units, their order, how a failure
34
+ * travels to what depends on it, what it is estimated to cost, and the
35
+ * ledger arithmetic — and does no I/O, so the step, the machine, the doors
36
+ * and the console read one vocabulary.
37
+ */
38
+ /** How much one build holds: what one proposal can describe and one person can read. */
39
+ export declare const AI_BUILD_LIMITS: {
40
+ /** Creations, pages and items together. */
41
+ readonly units: 16;
42
+ readonly pages: 8;
43
+ /** A Free workspace's pages. */
44
+ readonly freePages: 2;
45
+ };
46
+ /** What a build creates through its `create` list; everything else beyond pages is an item. */
47
+ export declare const AI_BUILD_CREATE_KINDS: readonly AiBuildPlanCreateKind[];
48
+ /**
49
+ * The operations a build plans through `create` and `screens` rather than
50
+ * `items`: an item naming one is a plan that put it in the wrong list.
51
+ */
52
+ export declare const AI_BUILD_STRUCTURAL_OPS: readonly string[];
53
+ /** The job input a build's Assist proposal sets when the brief asked to publish. */
54
+ export declare const AI_BUILD_PUBLISH_INPUT = "publish";
55
+ /** A unit of a build: a creation, a page, or an item. */
56
+ export interface AiBuildUnit {
57
+ slot: string;
58
+ /** The capability operation that builds it. */
59
+ op: string;
60
+ label: string;
61
+ creation?: AiBuildPlanCreate;
62
+ screen?: AiBuildPlanScreen;
63
+ item?: AiBuildItem;
64
+ /** The slots it is built after, in plan order. */
65
+ deps: string[];
66
+ }
67
+ /** The name a `new:<name>` reference gives, lowercased. */
68
+ export declare function aiBuildRefName(ref: string): string;
69
+ /** Every reference a page makes: its layout, template, starting page and what its sections place. */
70
+ export declare function aiBuildScreenRefs(screen: AiBuildPlanScreen): string[];
71
+ /**
72
+ * The units a plan implies, in plan order: creations, then items, then
73
+ * pages — the order a member reads them in, and the one a page that places
74
+ * a creation or an item is built after anyway. `aiBuildOrder` sorts them on
75
+ * their dependencies.
76
+ */
77
+ export declare function aiBuildUnits(plan: AiBuildPlan): AiBuildUnit[];
78
+ /**
79
+ * The units in an order that builds every dependency before what depends on
80
+ * it, plan order otherwise; `null` when the dependencies hold a cycle.
81
+ */
82
+ export declare function aiBuildOrder(units: readonly AiBuildUnit[]): AiBuildUnit[] | null;
83
+ /**
84
+ * What is wrong with a plan's references as a build reads them: a
85
+ * `new:<name>` an item depends on that nothing in the plan makes, and a
86
+ * cycle. Each is a sentence the plan's one re-ask carries.
87
+ */
88
+ export declare function aiBuildGraphProblems(plan: AiBuildPlan): string[];
89
+ /** The operations a build may plan, as the registry and the gates left them, by op. */
90
+ export type AiBuildOps = ReadonlyMap<string, PluginAiCapability>;
91
+ /** How many pages a build may hold on this workspace. */
92
+ export declare function aiBuildPageLimit(freeTaste: boolean | null | undefined): number;
93
+ /**
94
+ * Why a build cannot build a plan of this shape, in a sentence a member
95
+ * reads; `null` when it can. Held to the plan with the one re-ask (the plan
96
+ * step's scope), and again by the doors before a confirmed plan runs.
97
+ * `ops` is what may be planned on this site; absent, items are not judged
98
+ * against the registry (a console reading a kept plan).
99
+ */
100
+ export declare function aiBuildPlanShapeRefusal(plan: AiBuildPlan, options?: {
101
+ freeTaste?: boolean;
102
+ ops?: AiBuildOps;
103
+ }): string | null;
104
+ /** "a booking service", "an email design". */
105
+ export declare function aiArticle(noun: string): string;
106
+ /**
107
+ * About what one unit costs, in credits: a page or a creation by the passes
108
+ * it implies at the nominal credits a pass is held against, as a site's are;
109
+ * an item by its capability's own estimate, recorded on the plan when it was
110
+ * kept.
111
+ */
112
+ export declare function aiBuildUnitCreditEstimate(unit: AiBuildUnit, ops?: AiBuildOps): number;
113
+ /**
114
+ * About what a build costs, in credits: every unit's estimate, or only the
115
+ * units named in `slots` — what Try again shows. The ceiling a member
116
+ * confirms; the meter charges what actually runs.
117
+ */
118
+ export declare function aiBuildCreditEstimate(plan: AiBuildPlan, options?: {
119
+ ops?: AiBuildOps;
120
+ slots?: ReadonlySet<string>;
121
+ }): number;
122
+ /**
123
+ * About what a job of this kind costs to build from its plan: a build's
124
+ * units, every other planned kind as `aiJobPlanCreditEstimate` counts it.
125
+ */
126
+ export declare function aiJobCreditEstimate(kind: string, plan: AiBuildPlan): number;
127
+ /** A fresh ledger: one pending row per unit, first attempt. */
128
+ export declare function aiBuildInitialLedger(units: readonly AiBuildUnit[]): AiJobItemLedger[];
129
+ /** Whether an item is still to be built. */
130
+ export declare function aiBuildItemOpen(row: Pick<AiJobItemLedger, 'status'>): boolean;
131
+ /** Whether an item delivered: built as planned, or built without something that failed. */
132
+ export declare function aiBuildItemDelivered(row: Pick<AiJobItemLedger, 'status'>): boolean;
133
+ /**
134
+ * The next unit to build: the first in build order whose row is still open.
135
+ * Its dependencies come before it, so by then each is settled one way or the
136
+ * other. `null` when nothing is left.
137
+ */
138
+ export declare function aiBuildNextUnit(ordered: readonly AiBuildUnit[], ledger: readonly AiJobItemLedger[]): AiBuildUnit | null;
139
+ /** How a unit is built given what its dependencies came to. */
140
+ export interface AiBuildDegradation {
141
+ /** The unit is not built at all, with the sentence why; nothing is spent. */
142
+ skip: string | null;
143
+ /** The failed dependencies that change how it is built. */
144
+ degradedBy: string[];
145
+ /** What the person reads about the change; one per failed dependency. */
146
+ notes: string[];
147
+ /** `new:<name>` references (lowercased names) to leave out. */
148
+ dropped: Set<string>;
149
+ /** Brief lines for the unit's own job: what to leave out, and what to place. */
150
+ briefLines: string[];
151
+ }
152
+ /**
153
+ * How a unit is built when some of what it depends on failed (AGL-3616).
154
+ *
155
+ * A PAGE is always built: a failed layout falls back to the site's own, a
156
+ * failed form or component is left out of its section, and a failed item a
157
+ * section places (a booking service) takes its block out of the page — each
158
+ * with a note. Any OTHER unit whose dependency failed is skipped when that
159
+ * dependency's capability says `omit` (a campaign whose email design failed
160
+ * has nothing to send), and built without it when it says `fallback`.
161
+ */
162
+ export declare function aiBuildDegradation(unit: AiBuildUnit, context: {
163
+ units: readonly AiBuildUnit[];
164
+ ledger: readonly AiJobItemLedger[];
165
+ ops?: AiBuildOps;
166
+ }): AiBuildDegradation;
167
+ /** What each creation is called in a note. */
168
+ export declare function aiBuildCreationNoun(kind: AiBuildPlanCreateKind): string;
169
+ /**
170
+ * The brief lines a page is told about the items its sections place and
171
+ * that were built: the block to put there, in the owner's words.
172
+ */
173
+ export declare function aiBuildPlacedItemLines(unit: AiBuildUnit, context: {
174
+ units: readonly AiBuildUnit[];
175
+ ledger: readonly AiJobItemLedger[];
176
+ ops?: AiBuildOps;
177
+ }): string[];
178
+ /** What a build came to: whether anything was delivered, and whether anything is left. */
179
+ export declare function aiBuildSettlement(ledger: readonly AiJobItemLedger[]): {
180
+ delivered: boolean;
181
+ open: boolean;
182
+ failed: number;
183
+ };
184
+ /**
185
+ * The ledger Try again runs (AGL-3616): every failed item back to `pending`
186
+ * on its next attempt, with the items left unbuilt because of it — skipped,
187
+ * or degraded with no draft — and every item the build never reached. An
188
+ * item that succeeded is never run again, and a degraded page that has its
189
+ * draft keeps it, with a note that the page needs an edit. `retried` names
190
+ * the slots that will run, which is what the estimate is shown for.
191
+ */
192
+ export declare function aiBuildRetryLedger(ledger: readonly AiJobItemLedger[], units: readonly AiBuildUnit[]): {
193
+ ledger: AiJobItemLedger[];
194
+ retried: string[];
195
+ };
196
+ /**
197
+ * Units read back off a ledger alone (AGL-3616), for a job whose units are
198
+ * not a build plan's — a site scaffold's: each row as its unit, and every
199
+ * page built after the layouts and forms the ledger holds.
200
+ */
201
+ export declare function aiLedgerUnits(ledger: readonly AiJobItemLedger[]): AiBuildUnit[];