@aglyn/plugins-ai 1.0.0-beta.285 → 1.0.0-beta.287

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 (210) hide show
  1. package/package.json +17 -17
  2. package/src/lib/assets/site-styles/nonprofit.webp +0 -0
  3. package/src/lib/assets/site-styles/professional.webp +0 -0
  4. package/src/lib/assets/site-styles/store.webp +0 -0
  5. package/src/lib/assets/site-styles/trades.webp +0 -0
  6. package/src/lib/components/ai-theme-proposal-card.component.js +12 -3
  7. package/src/lib/components/ai-theme-proposal-card.component.js.map +1 -1
  8. package/src/lib/declarations.js +5 -2
  9. package/src/lib/declarations.js.map +1 -1
  10. package/src/lib/declarations.server.js +12 -0
  11. package/src/lib/declarations.server.js.map +1 -1
  12. package/src/lib/jobs/ai-build-capabilities.d.ts +3 -1
  13. package/src/lib/jobs/ai-build-capabilities.js +27 -2
  14. package/src/lib/jobs/ai-build-capabilities.js.map +1 -1
  15. package/src/lib/jobs/ai-image-reads.d.ts +59 -0
  16. package/src/lib/jobs/ai-image-reads.js +138 -0
  17. package/src/lib/jobs/ai-image-reads.js.map +1 -0
  18. package/src/lib/jobs/ai-job-build-step.d.ts +29 -0
  19. package/src/lib/jobs/ai-job-build-step.js +83 -12
  20. package/src/lib/jobs/ai-job-build-step.js.map +1 -1
  21. package/src/lib/jobs/ai-job-duplicate-step.d.ts +2 -1
  22. package/src/lib/jobs/ai-job-duplicate-step.js +6 -6
  23. package/src/lib/jobs/ai-job-duplicate-step.js.map +1 -1
  24. package/src/lib/jobs/ai-job-import-step.d.ts +4 -2
  25. package/src/lib/jobs/ai-job-import-step.js +15 -11
  26. package/src/lib/jobs/ai-job-import-step.js.map +1 -1
  27. package/src/lib/jobs/ai-job-insight-step.d.ts +10 -0
  28. package/src/lib/jobs/ai-job-insight-step.js +23 -5
  29. package/src/lib/jobs/ai-job-insight-step.js.map +1 -1
  30. package/src/lib/jobs/ai-job-layout-language.js +2 -1
  31. package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
  32. package/src/lib/jobs/ai-job-media-step.d.ts +2 -1
  33. package/src/lib/jobs/ai-job-media-step.js +6 -8
  34. package/src/lib/jobs/ai-job-media-step.js.map +1 -1
  35. package/src/lib/jobs/ai-job-navigation-step.d.ts +2 -1
  36. package/src/lib/jobs/ai-job-navigation-step.js +7 -9
  37. package/src/lib/jobs/ai-job-navigation-step.js.map +1 -1
  38. package/src/lib/jobs/ai-job-page-language.js +7 -1
  39. package/src/lib/jobs/ai-job-page-language.js.map +1 -1
  40. package/src/lib/jobs/ai-job-page-sections.js +16 -3
  41. package/src/lib/jobs/ai-job-page-sections.js.map +1 -1
  42. package/src/lib/jobs/ai-job-page-step.js +9 -1
  43. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  44. package/src/lib/jobs/ai-job-plan-step.d.ts +30 -8
  45. package/src/lib/jobs/ai-job-plan-step.js +78 -13
  46. package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
  47. package/src/lib/jobs/ai-job-privacy-step.d.ts +4 -2
  48. package/src/lib/jobs/ai-job-privacy-step.js +14 -15
  49. package/src/lib/jobs/ai-job-privacy-step.js.map +1 -1
  50. package/src/lib/jobs/ai-job-products-step.js +5 -3
  51. package/src/lib/jobs/ai-job-products-step.js.map +1 -1
  52. package/src/lib/jobs/ai-job-settings-step.d.ts +2 -1
  53. package/src/lib/jobs/ai-job-settings-step.js +7 -8
  54. package/src/lib/jobs/ai-job-settings-step.js.map +1 -1
  55. package/src/lib/jobs/ai-job-site-content.d.ts +34 -1
  56. package/src/lib/jobs/ai-job-site-content.js +67 -8
  57. package/src/lib/jobs/ai-job-site-content.js.map +1 -1
  58. package/src/lib/jobs/ai-job-site-datasets.d.ts +53 -3
  59. package/src/lib/jobs/ai-job-site-datasets.js +298 -30
  60. package/src/lib/jobs/ai-job-site-datasets.js.map +1 -1
  61. package/src/lib/jobs/ai-job-site-step.js +6 -3
  62. package/src/lib/jobs/ai-job-site-step.js.map +1 -1
  63. package/src/lib/jobs/ai-job-site-store-pages.js +3 -3
  64. package/src/lib/jobs/ai-job-site-store-pages.js.map +1 -1
  65. package/src/lib/jobs/ai-job-tracking-step.d.ts +2 -1
  66. package/src/lib/jobs/ai-job-tracking-step.js +7 -8
  67. package/src/lib/jobs/ai-job-tracking-step.js.map +1 -1
  68. package/src/lib/jobs/ai-jobs-beat.d.ts +11 -7
  69. package/src/lib/jobs/ai-jobs-beat.js +18 -8
  70. package/src/lib/jobs/ai-jobs-beat.js.map +1 -1
  71. package/src/lib/jobs/ai-jobs-notify.d.ts +66 -1
  72. package/src/lib/jobs/ai-jobs-notify.js +136 -3
  73. package/src/lib/jobs/ai-jobs-notify.js.map +1 -1
  74. package/src/lib/jobs/ai-layout-stock-photos.d.ts +59 -4
  75. package/src/lib/jobs/ai-layout-stock-photos.js +897 -81
  76. package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
  77. package/src/lib/jobs/ai-product-image.d.ts +14 -0
  78. package/src/lib/jobs/ai-product-image.js +73 -21
  79. package/src/lib/jobs/ai-product-image.js.map +1 -1
  80. package/src/lib/jobs/ai-theme-brand-inputs.d.ts +9 -1
  81. package/src/lib/jobs/ai-theme-brand-inputs.js +28 -2
  82. package/src/lib/jobs/ai-theme-brand-inputs.js.map +1 -1
  83. package/src/lib/jobs/fixtures/ai-site-agl4065-datasets.d.ts +175 -0
  84. package/src/lib/jobs/fixtures/ai-site-agl4065-datasets.js +601 -0
  85. package/src/lib/jobs/fixtures/ai-site-agl4065-datasets.js.map +1 -0
  86. package/src/lib/jobs/fixtures/ai-site-agl4065-pages.d.ts +46 -0
  87. package/src/lib/jobs/fixtures/ai-site-agl4065-pages.js +2862 -0
  88. package/src/lib/jobs/fixtures/ai-site-agl4065-pages.js.map +1 -0
  89. package/src/lib/jobs/fixtures/ai-site-agl4065-plans.d.ts +74 -0
  90. package/src/lib/jobs/fixtures/ai-site-agl4065-plans.js +888 -0
  91. package/src/lib/jobs/fixtures/ai-site-agl4065-plans.js.map +1 -0
  92. package/src/lib/jobs/fixtures/ai-stock-photo-agl4065-judge.d.ts +29 -0
  93. package/src/lib/jobs/fixtures/ai-stock-photo-agl4065-judge.js +81 -0
  94. package/src/lib/jobs/fixtures/ai-stock-photo-agl4065-judge.js.map +1 -0
  95. package/src/lib/jobs/fixtures/ai-stock-photo-agl4065-recordings.d.ts +87 -0
  96. package/src/lib/jobs/fixtures/ai-stock-photo-agl4065-recordings.js +225 -0
  97. package/src/lib/jobs/fixtures/ai-stock-photo-agl4065-recordings.js.map +1 -0
  98. package/src/lib/layout-language/ai-layout-compiler.d.ts +11 -0
  99. package/src/lib/layout-language/ai-layout-compiler.js +194 -18
  100. package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
  101. package/src/lib/layout-language/ai-layout-copy.d.ts +37 -0
  102. package/src/lib/layout-language/ai-layout-copy.js +383 -3
  103. package/src/lib/layout-language/ai-layout-copy.js.map +1 -1
  104. package/src/lib/layout-language/ai-layout-design.d.ts +19 -0
  105. package/src/lib/layout-language/ai-layout-design.js +31 -11
  106. package/src/lib/layout-language/ai-layout-design.js.map +1 -1
  107. package/src/lib/layout-language/ai-layout-listings.d.ts +7 -1
  108. package/src/lib/layout-language/ai-layout-listings.js +9 -1
  109. package/src/lib/layout-language/ai-layout-listings.js.map +1 -1
  110. package/src/lib/layout-language/ai-layout-pictures.d.ts +30 -0
  111. package/src/lib/layout-language/ai-layout-pictures.js +131 -3
  112. package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
  113. package/src/lib/layout-language/ai-layout-storefront.d.ts +18 -4
  114. package/src/lib/layout-language/ai-layout-storefront.js +100 -20
  115. package/src/lib/layout-language/ai-layout-storefront.js.map +1 -1
  116. package/src/lib/model/ai-build-job.d.ts +7 -0
  117. package/src/lib/model/ai-build-job.js +36 -7
  118. package/src/lib/model/ai-build-job.js.map +1 -1
  119. package/src/lib/model/ai-build-plan.d.ts +28 -4
  120. package/src/lib/model/ai-build-plan.js +49 -9
  121. package/src/lib/model/ai-build-plan.js.map +1 -1
  122. package/src/lib/model/ai-build-progress.js +3 -1
  123. package/src/lib/model/ai-build-progress.js.map +1 -1
  124. package/src/lib/model/ai-job-notice.d.ts +8 -0
  125. package/src/lib/model/ai-job-notice.js +33 -0
  126. package/src/lib/model/ai-job-notice.js.map +1 -1
  127. package/src/lib/model/ai-job-plan-lines.d.ts +2 -1
  128. package/src/lib/model/ai-job-plan-lines.js +6 -1
  129. package/src/lib/model/ai-job-plan-lines.js.map +1 -1
  130. package/src/lib/model/ai-jobs.types.d.ts +8 -0
  131. package/src/lib/model/ai-jobs.types.js.map +1 -1
  132. package/src/lib/model/ai-permissions.d.ts +13 -0
  133. package/src/lib/model/ai-permissions.js +29 -1
  134. package/src/lib/model/ai-permissions.js.map +1 -1
  135. package/src/lib/model/ai-products.d.ts +18 -0
  136. package/src/lib/model/ai-products.js +32 -0
  137. package/src/lib/model/ai-products.js.map +1 -1
  138. package/src/lib/model/ai-site-inspiration.d.ts +3 -2
  139. package/src/lib/model/ai-site-inspiration.js +3 -2
  140. package/src/lib/model/ai-site-inspiration.js.map +1 -1
  141. package/src/lib/plugin.js +4 -13
  142. package/src/lib/plugin.js.map +1 -1
  143. package/src/lib/providers/anthropic.js +9 -2
  144. package/src/lib/providers/anthropic.js.map +1 -1
  145. package/src/lib/providers/catalog.js +14 -5
  146. package/src/lib/providers/catalog.js.map +1 -1
  147. package/src/lib/providers/contract.d.ts +24 -1
  148. package/src/lib/providers/contract.js.map +1 -1
  149. package/src/lib/providers/routing.js +5 -2
  150. package/src/lib/providers/routing.js.map +1 -1
  151. package/src/lib/runtime/ai-dataset-generation.d.ts +99 -1
  152. package/src/lib/runtime/ai-dataset-generation.js +251 -3
  153. package/src/lib/runtime/ai-dataset-generation.js.map +1 -1
  154. package/src/lib/runtime/ai-dev-replay.d.ts +1 -0
  155. package/src/lib/runtime/ai-dev-replay.js +4 -2
  156. package/src/lib/runtime/ai-dev-replay.js.map +1 -1
  157. package/src/lib/runtime/ai-doctrine-validators.d.ts +47 -3
  158. package/src/lib/runtime/ai-doctrine-validators.js +343 -27
  159. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
  160. package/src/lib/runtime/ai-doctrine.js +8 -2
  161. package/src/lib/runtime/ai-doctrine.js.map +1 -1
  162. package/src/lib/runtime/ai-icon-library.d.ts +27 -1
  163. package/src/lib/runtime/ai-icon-library.js +30 -3
  164. package/src/lib/runtime/ai-icon-library.js.map +1 -1
  165. package/src/lib/runtime/ai-products-generation.d.ts +11 -1
  166. package/src/lib/runtime/ai-products-generation.js +51 -4
  167. package/src/lib/runtime/ai-products-generation.js.map +1 -1
  168. package/src/lib/runtime/assist-answer-cache.d.ts +2 -0
  169. package/src/lib/runtime/assist-answer-cache.js +5 -2
  170. package/src/lib/runtime/assist-answer-cache.js.map +1 -1
  171. package/src/lib/server/ai-allotments.js +7 -2
  172. package/src/lib/server/ai-allotments.js.map +1 -1
  173. package/src/lib/server/ai-experiment-versions.js +5 -5
  174. package/src/lib/server/ai-experiment-versions.js.map +1 -1
  175. package/src/lib/server/ai-host-permissions-roster.d.ts +25 -0
  176. package/src/lib/server/ai-host-permissions-roster.js +33 -0
  177. package/src/lib/server/ai-host-permissions-roster.js.map +1 -0
  178. package/src/lib/server/ai-host-permissions.js +8 -6
  179. package/src/lib/server/ai-host-permissions.js.map +1 -1
  180. package/src/lib/server/ai-image-reads-route.d.ts +17 -0
  181. package/src/lib/server/ai-image-reads-route.js +106 -0
  182. package/src/lib/server/ai-image-reads-route.js.map +1 -0
  183. package/src/lib/server/ai-seo-apply.js +5 -5
  184. package/src/lib/server/ai-seo-apply.js.map +1 -1
  185. package/src/lib/server/ai-site-import-route.js +7 -4
  186. package/src/lib/server/ai-site-import-route.js.map +1 -1
  187. package/src/lib/server/assist-build.js +1 -0
  188. package/src/lib/server/assist-build.js.map +1 -1
  189. package/src/lib/server/assist-chat.d.ts +11 -7
  190. package/src/lib/server/assist-chat.js +185 -48
  191. package/src/lib/server/assist-chat.js.map +1 -1
  192. package/src/lib/server/assist-docs-query.d.ts +51 -0
  193. package/src/lib/server/assist-docs-query.js +57 -0
  194. package/src/lib/server/assist-docs-query.js.map +1 -0
  195. package/src/lib/server/assist-jobs-context.d.ts +102 -0
  196. package/src/lib/server/assist-jobs-context.js +227 -0
  197. package/src/lib/server/assist-jobs-context.js.map +1 -0
  198. package/src/lib/server/assist-view-context.d.ts +8 -4
  199. package/src/lib/server/assist-view-context.js +12 -7
  200. package/src/lib/server/assist-view-context.js.map +1 -1
  201. package/src/lib/server.js +12 -0
  202. package/src/lib/server.js.map +1 -1
  203. package/src/lib/tools/ai-dataset-tool.d.ts +11 -1
  204. package/src/lib/tools/ai-dataset-tool.js +24 -7
  205. package/src/lib/tools/ai-dataset-tool.js.map +1 -1
  206. package/src/lib/tools/ai-duplicate-resource-tool.js +5 -6
  207. package/src/lib/tools/ai-duplicate-resource-tool.js.map +1 -1
  208. package/src/lib/components/ai-collaborator-permissions-column.component.d.ts +0 -32
  209. package/src/lib/components/ai-collaborator-permissions-column.component.js +0 -132
  210. package/src/lib/components/ai-collaborator-permissions-column.component.js.map +0 -1
@@ -17,12 +17,13 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
17
17
  */ import { aiJobCancelAsked } from "./ai-job-cancel.js";
18
18
  import { resolveEffectivePlan } from "@aglyn/aglyn/app-utils/plan-entitlements";
19
19
  import { resolveOrgIdForHost } from "@aglyn/tenant-data-admin/server/organizations";
20
- import { AI_BUILD_LIMITS, AI_BUILD_MADE_INPUT, AI_BUILD_PUBLISH_INPUT, aiArticle, aiBuildCreditRange, aiBuildDegradation, aiBuildInitialLedger, aiBuildItemArgRefs, aiBuildItemDelivered, aiBuildItemOpen, aiBuildNextUnit, aiBuildOrder, aiBuildItemOutputNote, aiBuildPlacedItemLines, AI_BUILD_NEEDS_INPUT_CODE, aiBuildPlanMissingInput, aiBuildPlanShapeRefusal, aiBuildRefName, aiBuildSmaller, aiBuildUnits } from "../model/ai-build-job.js";
20
+ import { AI_BUILD_LIMITS, AI_BUILD_MADE_INPUT, AI_BUILD_PUBLISH_INPUT, AI_BUILD_THEME_OP, aiArticle, aiBuildCreationNoun, aiBuildCreditRange, aiBuildDegradation, aiBuildInitialLedger, aiBuildItemArgRefs, aiBuildItemDelivered, aiBuildItemOpen, aiBuildNextUnit, aiBuildOrder, aiBuildItemOutputNote, aiBuildPlacedItemLines, AI_BUILD_NEEDS_INPUT_CODE, aiBuildPlanMissingInput, aiBuildPlanShapeRefusal, aiBuildRefName, aiBuildSmaller, aiBuildUnits } from "../model/ai-build-job.js";
21
21
  import { isAiPlanNewRef } from "../model/ai-build-plan.js";
22
- import { AI_SITE_MAX_SECTIONS } from "../model/ai-site-job.js";
22
+ import { AI_SITE_INPUT_MAX_CHARS, AI_SITE_MAX_SECTIONS } from "../model/ai-site-job.js";
23
23
  import { AI_CREDITS_CONFIRM_CODE, aiCreditsPromptFor, aiCreditsPromptText } from "../model/ai-credit-estimate.js";
24
24
  import { aiFreeCreditsNoneLeftText, aiSiteWords } from "../model/ai-site-job.js";
25
25
  import { readFreeAiCreditsLeft } from "../usage/free-ai-credits-left.js";
26
+ import { readAiSiteContext } from "../runtime/site-context.js";
26
27
  import { aiModelForStep } from "../providers/routing.js";
27
28
  import { AI_BUILD_UNIT_EMPTY_COPY, aiBuildBuiltRefs, aiUnitErrorRetryable, aiUnitFailure, aiUnitSpend } from "./ai-build-unit-outcome.js";
28
29
  import { aiBuildOps } from "./ai-build-capabilities.js";
@@ -88,7 +89,9 @@ import { AI_PLANNED_JOB_KINDS, aiJobStepRunMinimumMs, aiJobStepRunnerFor, regist
88
89
  layout: 'layout',
89
90
  form: 'form',
90
91
  component: 'component',
91
- email: 'email'
92
+ email: 'email',
93
+ // The theme operation's unit, where the plan named it as its creation (AGL-4077).
94
+ 'theme-change': 'theme'
92
95
  };
93
96
  /** The job kind a unit is built by, where an AI runner builds it. */ export function aiBuildUnitJobKind(unit, ops) {
94
97
  var _CREATION_JOB_KINDS_unit_creation_kind;
@@ -114,6 +117,41 @@ import { AI_PLANNED_JOB_KINDS, aiJobStepRunMinimumMs, aiJobStepRunnerFor, regist
114
117
  Array.isArray(value) ? value.filter((entry)=>!links(entry)) : value
115
118
  ]));
116
119
  }
120
+ /**
121
+ * What a build's theme change says under its proposal (AGL-4077): the theme
122
+ * runner proposes and never saves, so the owner applies it, or not, where
123
+ * every theme change is made.
124
+ */ export const AI_BUILD_THEME_PROPOSAL_NOTE = 'A proposal, in Setup → Theme. Nothing on the site changes until you apply it there and save.';
125
+ /** Text held to what a site start's own answer holds, cut at a word. */ function clipWords(value) {
126
+ const text = (value != null ? value : '').replace(/\s+/g, ' ').trim();
127
+ if (text.length <= AI_SITE_INPUT_MAX_CHARS) return text;
128
+ const cut = text.slice(0, AI_SITE_INPUT_MAX_CHARS + 1);
129
+ const space = cut.lastIndexOf(' ');
130
+ return (space > 0 ? cut.slice(0, space) : cut.slice(0, AI_SITE_INPUT_MAX_CHARS)).replace(/[\s,;:.–—-]+$/, '');
131
+ }
132
+ /**
133
+ * The site's business profile as those inputs (AGL-4077): what the business
134
+ * does, else the schema.org type its settings name, as words; its name; who
135
+ * it is for. Only what the profile says; nothing for a site with none.
136
+ */ export function aiBuildBusinessWords(profile) {
137
+ var _profile_whatYouDo, _profile_name, _profile_audience;
138
+ if (!profile) return {};
139
+ const type = profile.businessType ? profile.businessType.replace(/([a-z])([A-Z])/g, '$1 $2').toLowerCase() : '';
140
+ const words = {
141
+ businessType: clipWords((_profile_whatYouDo = profile.whatYouDo) == null ? void 0 : _profile_whatYouDo.value) || clipWords(type),
142
+ businessName: clipWords((_profile_name = profile.name) == null ? void 0 : _profile_name.value),
143
+ audience: clipWords((_profile_audience = profile.audience) == null ? void 0 : _profile_audience.value)
144
+ };
145
+ return Object.fromEntries(Object.entries(words).filter(([, value])=>value));
146
+ }
147
+ /**
148
+ * The business words a page is handed (AGL-4077): only where the build itself
149
+ * names no business, and only what the build does not say already.
150
+ */ function aiBuildBusinessInputs(inputs, business) {
151
+ if (!business || aiSiteWords(inputs).about) return {};
152
+ const given = (key)=>typeof (inputs == null ? void 0 : inputs[key]) === 'string' && inputs[key].trim() !== '';
153
+ return Object.fromEntries(Object.entries(business).filter(([key])=>!given(key)));
154
+ }
117
155
  /** The id a unit's job, and so its draft, is named by. */ export function aiBuildUnitJobId(job, unit) {
118
156
  var _ref, _ref1, _ref2;
119
157
  var _unit_creation, _unit_screen, _unit_item;
@@ -154,7 +192,8 @@ import { AI_PLANNED_JOB_KINDS, aiJobStepRunMinimumMs, aiJobStepRunnerFor, regist
154
192
  writesTo: aiSiteResolvedRef(unit.creation.writesTo, built)
155
193
  } : {})
156
194
  ];
157
- brief.push(`Build the ${unit.creation.kind} “${unit.creation.name}”: ${unit.creation.why}`);
195
+ const what = unit.creation.kind === 'theme-change' ? aiBuildCreationNoun(unit.creation.kind) : unit.creation.kind;
196
+ brief.push(`Build the ${what} “${unit.creation.name}”: ${unit.creation.why}`);
158
197
  }
159
198
  if (unit.screen) {
160
199
  var _aiSiteResolvedRef, _aiSiteResolvedRef1;
@@ -214,10 +253,12 @@ import { AI_PLANNED_JOB_KINDS, aiJobStepRunMinimumMs, aiJobStepRunnerFor, regist
214
253
  ] : [];
215
254
  }
216
255
  brief.push(...(_context_briefLines = context.briefLines) != null ? _context_briefLines : []);
217
- const inputs = _extends({}, job.inputs, aiBuildItemArgsWithout((_ref = item == null ? void 0 : item.args) != null ? _ref : {}, context.dropped), {
256
+ const inputs = _extends({}, job.inputs, unit.screen ? aiBuildBusinessInputs(job.inputs, context.business) : {}, aiBuildItemArgsWithout((_ref = item == null ? void 0 : item.args) != null ? _ref : {}, context.dropped), {
218
257
  originJobId: aiOriginJobId(job)
219
258
  });
220
259
  delete inputs[AI_BUILD_PUBLISH_INPUT];
260
+ // A theme change is a change to the theme the site has (AGL-4077), never a new one.
261
+ if (context.kind === 'theme') inputs['mode'] = 'modify';
221
262
  // What a build adds to a site moves the way the site's own pages do
222
263
  // (AGL-3949): its look's motion style, drawn with the site's seed.
223
264
  if (context.siteMotion && (context.kind === 'page' || context.kind === 'layout' || context.kind === 'template')) {
@@ -324,7 +365,8 @@ import { AI_PLANNED_JOB_KINDS, aiJobStepRunMinimumMs, aiJobStepRunnerFor, regist
324
365
  steps: [],
325
366
  outputs: [],
326
367
  items: null,
327
- plan: item && !AI_PLANNED_JOB_KINDS.includes(context.kind) ? null : unitPlan,
368
+ // Only a planned kind builds from a plan: an item's other runners, and the theme runner, take none.
369
+ plan: AI_PLANNED_JOB_KINDS.includes(context.kind) ? unitPlan : null,
328
370
  inputs,
329
371
  brief: brief.join('\n').slice(0, AI_JOB_BRIEF_MAX_CHARS)
330
372
  });
@@ -481,7 +523,7 @@ import { AI_PLANNED_JOB_KINDS, aiJobStepRunMinimumMs, aiJobStepRunnerFor, regist
481
523
  return (_data = (await firestore.collection('hosts').doc(hostId).get()).data()) != null ? _data : null;
482
524
  }
483
525
  export function createAiJobBuildStep(deps = {}) {
484
- var _deps_runnerFor, _deps_writerFor, _deps_opsFor, _deps_admissionFor, _deps_pluginAdmission, _deps_readNodes, _deps_publish, _deps_storePages, _deps_storePagesRefusal, _deps_readSitePages, _deps_writeStoreLinks;
526
+ var _deps_runnerFor, _deps_writerFor, _deps_opsFor, _deps_admissionFor, _deps_pluginAdmission, _deps_readNodes, _deps_publish, _deps_storePages, _deps_storePagesRefusal, _deps_readSitePages, _deps_writeStoreLinks, _deps_readSiteContext;
485
527
  const runnerFor = (_deps_runnerFor = deps.runnerFor) != null ? _deps_runnerFor : aiJobStepRunnerFor;
486
528
  const writerFor = (_deps_writerFor = deps.writerFor) != null ? _deps_writerFor : aiPluginDraftWriter;
487
529
  const opsFor = (_deps_opsFor = deps.opsFor) != null ? _deps_opsFor : (context)=>aiBuildOps(context);
@@ -493,6 +535,7 @@ export function createAiJobBuildStep(deps = {}) {
493
535
  const storePagesRefusal = (_deps_storePagesRefusal = deps.storePagesRefusal) != null ? _deps_storePagesRefusal : aiSiteStorePagesRefusal;
494
536
  const readSitePages = (_deps_readSitePages = deps.readSitePages) != null ? _deps_readSitePages : readAiStoreSitePages;
495
537
  const writeStoreLinks = (_deps_writeStoreLinks = deps.writeStoreLinks) != null ? _deps_writeStoreLinks : writeAiStoreLinksLayoutDraft;
538
+ const readSiteContext = (_deps_readSiteContext = deps.readSiteContext) != null ? _deps_readSiteContext : readAiSiteContext;
496
539
  return async (context)=>{
497
540
  var _ref, _context_org, _aiBuildOrder, _job_hostId, _job_hostId1, _ref1;
498
541
  var _job_items, _rows_get;
@@ -744,6 +787,23 @@ export function createAiJobBuildStep(deps = {}) {
744
787
  });
745
788
  const degraded = degradation.degradedBy.length > 0;
746
789
  const note = degradation.notes.length ? degradation.notes.join(' ') : null;
790
+ // What the business is, for a page or another plugin's draft, read from
791
+ // the site's profile where the build names none (AGL-4077): a build from
792
+ // the chat carries no businessType, so its pages searched photos with
793
+ // nothing of the business to go on. Fail-soft: unread, the unit is built
794
+ // as it was.
795
+ const business = job.hostId && !aiSiteWords(job.inputs).about && (unit.screen || capability.draftResource) ? await readSiteContext(firestore, {
796
+ orgId: job.orgId,
797
+ hostId: job.hostId,
798
+ host
799
+ }).then((read)=>aiBuildBusinessWords(read == null ? void 0 : read.profile)).catch((error)=>{
800
+ console.warn('ai build business profile unread', {
801
+ orgId: job.orgId,
802
+ jobId: job.$id,
803
+ error
804
+ });
805
+ return null;
806
+ }) : null;
747
807
  // Another plugin's resource: its writer, with the content its capability derives.
748
808
  if (capability.draftResource) {
749
809
  var _ref2;
@@ -817,7 +877,7 @@ export function createAiJobBuildStep(deps = {}) {
817
877
  // Drafts of one build share what must not repeat (a cover photo) and read its business (AGL-3755).
818
878
  act: {
819
879
  id: aiOriginJobId(job),
820
- business: aiSiteWords(job.inputs).about || job.brief || ''
880
+ business: aiSiteWords(job.inputs).about || (business == null ? void 0 : business.businessType) || job.brief || ''
821
881
  },
822
882
  id,
823
883
  name: item.name,
@@ -870,7 +930,8 @@ export function createAiJobBuildStep(deps = {}) {
870
930
  ops,
871
931
  briefLines: degradation.briefLines,
872
932
  dropped: degradation.dropped,
873
- siteMotion: aiLayoutSiteMotionOf(host == null ? void 0 : host['siteStyle'])
933
+ siteMotion: aiLayoutSiteMotionOf(host == null ? void 0 : host['siteStyle']),
934
+ business
874
935
  });
875
936
  // An item's kind is asked its own admission first (a campaign's plan,
876
937
  // a template's subject), once, before its first pass.
@@ -922,7 +983,13 @@ export function createAiJobBuildStep(deps = {}) {
922
983
  message: AI_BUILD_UNIT_EMPTY_COPY
923
984
  }));
924
985
  }
925
- const spent = aiUnitSpend(outcome);
986
+ // A theme change's proposal says where it is applied (AGL-4077).
987
+ const theme = kind === 'theme';
988
+ const spent = theme ? _extends({}, aiUnitSpend(outcome), {
989
+ outputs: outcome.outputs.map((output)=>output.resource === 'theme' ? _extends({}, output, {
990
+ note: AI_BUILD_THEME_PROPOSAL_NOTE
991
+ }) : output)
992
+ }) : aiUnitSpend(outcome);
926
993
  const ids = outcome.outputs.map((output)=>output.id);
927
994
  const stopped = aiUnitFailure(unit.slot, outcome);
928
995
  if (stopped) return settle(stopped, spent);
@@ -950,7 +1017,10 @@ export function createAiJobBuildStep(deps = {}) {
950
1017
  slot: unit.slot,
951
1018
  status: degraded ? 'degraded' : 'succeeded',
952
1019
  outputs: ids,
953
- note
1020
+ note: theme ? [
1021
+ note,
1022
+ AI_BUILD_THEME_PROPOSAL_NOTE
1023
+ ].filter(Boolean).join(' ') : note
954
1024
  }, degraded ? {
955
1025
  degradedBy: degradation.degradedBy
956
1026
  } : {}), spent);
@@ -998,7 +1068,8 @@ export const runAiJobBuildStep = createAiJobBuildStep();
998
1068
  settings: 'settings',
999
1069
  media: 'media',
1000
1070
  tracking: 'tracking',
1001
- privacy: 'privacy'
1071
+ privacy: 'privacy',
1072
+ [AI_BUILD_THEME_OP]: 'theme'
1002
1073
  };
1003
1074
  /**
1004
1075
  * What a Free build's credits say before it runs (AGL-3722), on its measured