@aglyn/plugins-ai 1.0.0-beta.244 → 1.0.0-beta.247

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 (173) hide show
  1. package/package.json +17 -17
  2. package/src/lib/activity/ai-activity-actions.js +7 -1
  3. package/src/lib/activity/ai-activity-actions.js.map +1 -1
  4. package/src/lib/components/ai-job-links.js +21 -0
  5. package/src/lib/components/ai-job-links.js.map +1 -1
  6. package/src/lib/components/ai-product-zones.d.ts +3 -1
  7. package/src/lib/components/ai-product-zones.js.map +1 -1
  8. package/src/lib/components/ai-products-hub-card.component.js +1 -1
  9. package/src/lib/components/ai-products-hub-card.component.js.map +1 -1
  10. package/src/lib/components/ai-products-proposals.component.js +17 -9
  11. package/src/lib/components/ai-products-proposals.component.js.map +1 -1
  12. package/src/lib/components/ai-site-start-card.component.d.ts +1 -1
  13. package/src/lib/components/ai-site-start-card.component.js +98 -23
  14. package/src/lib/components/ai-site-start-card.component.js.map +1 -1
  15. package/src/lib/components/ai-upsell-dialog.component.js +1 -1
  16. package/src/lib/components/ai-upsell-dialog.component.js.map +1 -1
  17. package/src/lib/declarations.server.js +12 -0
  18. package/src/lib/declarations.server.js.map +1 -1
  19. package/src/lib/jobs/ai-build-capabilities.js +216 -2
  20. package/src/lib/jobs/ai-build-capabilities.js.map +1 -1
  21. package/src/lib/jobs/ai-job-build-step.d.ts +3 -1
  22. package/src/lib/jobs/ai-job-build-step.js +124 -18
  23. package/src/lib/jobs/ai-job-build-step.js.map +1 -1
  24. package/src/lib/jobs/ai-job-duplicate-step.d.ts +123 -0
  25. package/src/lib/jobs/ai-job-duplicate-step.js +269 -0
  26. package/src/lib/jobs/ai-job-duplicate-step.js.map +1 -0
  27. package/src/lib/jobs/ai-job-form-dataset.d.ts +8 -5
  28. package/src/lib/jobs/ai-job-form-dataset.js +28 -10
  29. package/src/lib/jobs/ai-job-form-dataset.js.map +1 -1
  30. package/src/lib/jobs/ai-job-form-step.d.ts +20 -4
  31. package/src/lib/jobs/ai-job-form-step.js +98 -28
  32. package/src/lib/jobs/ai-job-form-step.js.map +1 -1
  33. package/src/lib/jobs/ai-job-layout-language.d.ts +6 -2
  34. package/src/lib/jobs/ai-job-layout-language.js +29 -5
  35. package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
  36. package/src/lib/jobs/ai-job-layout-step.js +4 -1
  37. package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
  38. package/src/lib/jobs/ai-job-media-step.d.ts +239 -0
  39. package/src/lib/jobs/ai-job-media-step.js +610 -0
  40. package/src/lib/jobs/ai-job-media-step.js.map +1 -0
  41. package/src/lib/jobs/ai-job-navigation-step.d.ts +157 -0
  42. package/src/lib/jobs/ai-job-navigation-step.js +439 -0
  43. package/src/lib/jobs/ai-job-navigation-step.js.map +1 -0
  44. package/src/lib/jobs/ai-job-page-language.d.ts +4 -1
  45. package/src/lib/jobs/ai-job-page-language.js +30 -5
  46. package/src/lib/jobs/ai-job-page-language.js.map +1 -1
  47. package/src/lib/jobs/ai-job-page-sections.js +5 -4
  48. package/src/lib/jobs/ai-job-page-sections.js.map +1 -1
  49. package/src/lib/jobs/ai-job-page-step.js +3 -2
  50. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  51. package/src/lib/jobs/ai-job-plan-step.d.ts +14 -3
  52. package/src/lib/jobs/ai-job-plan-step.js +87 -20
  53. package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
  54. package/src/lib/jobs/ai-job-products-step.d.ts +2 -2
  55. package/src/lib/jobs/ai-job-products-step.js +2 -2
  56. package/src/lib/jobs/ai-job-products-step.js.map +1 -1
  57. package/src/lib/jobs/ai-job-settings-step.d.ts +268 -0
  58. package/src/lib/jobs/ai-job-settings-step.js +690 -0
  59. package/src/lib/jobs/ai-job-settings-step.js.map +1 -0
  60. package/src/lib/jobs/ai-job-site-content.d.ts +22 -8
  61. package/src/lib/jobs/ai-job-site-content.js +33 -15
  62. package/src/lib/jobs/ai-job-site-content.js.map +1 -1
  63. package/src/lib/jobs/ai-job-site-datasets.d.ts +3 -1
  64. package/src/lib/jobs/ai-job-site-datasets.js +13 -5
  65. package/src/lib/jobs/ai-job-site-datasets.js.map +1 -1
  66. package/src/lib/jobs/ai-job-site-events.d.ts +148 -0
  67. package/src/lib/jobs/ai-job-site-events.js +313 -0
  68. package/src/lib/jobs/ai-job-site-events.js.map +1 -0
  69. package/src/lib/jobs/ai-job-site-step.d.ts +12 -4
  70. package/src/lib/jobs/ai-job-site-step.js +132 -26
  71. package/src/lib/jobs/ai-job-site-step.js.map +1 -1
  72. package/src/lib/jobs/ai-job-tracking-step.d.ts +184 -0
  73. package/src/lib/jobs/ai-job-tracking-step.js +501 -0
  74. package/src/lib/jobs/ai-job-tracking-step.js.map +1 -0
  75. package/src/lib/jobs/ai-layout-stock-photos.d.ts +21 -0
  76. package/src/lib/jobs/ai-layout-stock-photos.js +41 -4
  77. package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
  78. package/src/lib/jobs/ai-site-publish.d.ts +62 -4
  79. package/src/lib/jobs/ai-site-publish.js +202 -56
  80. package/src/lib/jobs/ai-site-publish.js.map +1 -1
  81. package/src/lib/jobs/ai-stock-photo-picker.d.ts +24 -0
  82. package/src/lib/jobs/ai-stock-photo-picker.js +108 -0
  83. package/src/lib/jobs/ai-stock-photo-picker.js.map +1 -0
  84. package/src/lib/jobs/fixtures/ai-jazz-events-build-plan-recording.d.ts +37 -0
  85. package/src/lib/jobs/fixtures/ai-jazz-events-build-plan-recording.js +47 -0
  86. package/src/lib/jobs/fixtures/ai-jazz-events-build-plan-recording.js.map +1 -0
  87. package/src/lib/jobs/fixtures/ai-stock-photo-agl3760-recordings.d.ts +21 -0
  88. package/src/lib/jobs/fixtures/ai-stock-photo-agl3760-recordings.js +128 -0
  89. package/src/lib/jobs/fixtures/ai-stock-photo-agl3760-recordings.js.map +1 -0
  90. package/src/lib/layout-language/ai-layout-compiler.d.ts +16 -7
  91. package/src/lib/layout-language/ai-layout-compiler.js +62 -42
  92. package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
  93. package/src/lib/layout-language/ai-layout-frame-hollows.d.ts +41 -0
  94. package/src/lib/layout-language/ai-layout-frame-hollows.js +330 -0
  95. package/src/lib/layout-language/ai-layout-frame-hollows.js.map +1 -0
  96. package/src/lib/layout-language/ai-layout-frame.d.ts +24 -5
  97. package/src/lib/layout-language/ai-layout-frame.js +93 -20
  98. package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
  99. package/src/lib/layout-language/ai-layout-gaps.js +3 -1
  100. package/src/lib/layout-language/ai-layout-gaps.js.map +1 -1
  101. package/src/lib/layout-language/ai-layout-labels.d.ts +70 -0
  102. package/src/lib/layout-language/ai-layout-labels.js +162 -0
  103. package/src/lib/layout-language/ai-layout-labels.js.map +1 -0
  104. package/src/lib/layout-language/ai-layout-links.js +5 -2
  105. package/src/lib/layout-language/ai-layout-links.js.map +1 -1
  106. package/src/lib/layout-language/ai-layout-listings.d.ts +49 -1
  107. package/src/lib/layout-language/ai-layout-listings.js +66 -5
  108. package/src/lib/layout-language/ai-layout-listings.js.map +1 -1
  109. package/src/lib/layout-language/ai-layout-tree.d.ts +2 -0
  110. package/src/lib/layout-language/ai-layout-tree.js +17 -0
  111. package/src/lib/layout-language/ai-layout-tree.js.map +1 -1
  112. package/src/lib/model/ai-build-event-page.d.ts +70 -0
  113. package/src/lib/model/ai-build-event-page.js +145 -0
  114. package/src/lib/model/ai-build-event-page.js.map +1 -0
  115. package/src/lib/model/ai-build-job.d.ts +44 -0
  116. package/src/lib/model/ai-build-job.js +141 -13
  117. package/src/lib/model/ai-build-job.js.map +1 -1
  118. package/src/lib/model/ai-build-plan.d.ts +39 -3
  119. package/src/lib/model/ai-build-plan.js +59 -5
  120. package/src/lib/model/ai-build-plan.js.map +1 -1
  121. package/src/lib/model/ai-credit-estimate.d.ts +52 -0
  122. package/src/lib/model/ai-credit-estimate.js +51 -0
  123. package/src/lib/model/ai-credit-estimate.js.map +1 -1
  124. package/src/lib/model/ai-job-activity.js +6 -1
  125. package/src/lib/model/ai-job-activity.js.map +1 -1
  126. package/src/lib/model/ai-jobs.types.d.ts +18 -2
  127. package/src/lib/model/ai-jobs.types.js +6 -1
  128. package/src/lib/model/ai-jobs.types.js.map +1 -1
  129. package/src/lib/model/ai-layout-menus.d.ts +104 -0
  130. package/src/lib/model/ai-layout-menus.js +518 -0
  131. package/src/lib/model/ai-layout-menus.js.map +1 -0
  132. package/src/lib/model/ai-plan-capabilities.d.ts +8 -0
  133. package/src/lib/model/ai-plan-capabilities.js.map +1 -1
  134. package/src/lib/model/ai-products.d.ts +31 -1
  135. package/src/lib/model/ai-products.js +34 -1
  136. package/src/lib/model/ai-products.js.map +1 -1
  137. package/src/lib/model/ai-site-inventory.d.ts +17 -0
  138. package/src/lib/model/ai-site-inventory.js +5 -0
  139. package/src/lib/model/ai-site-inventory.js.map +1 -1
  140. package/src/lib/model/ai-site-job.d.ts +12 -2
  141. package/src/lib/model/ai-site-job.js +39 -12
  142. package/src/lib/model/ai-site-job.js.map +1 -1
  143. package/src/lib/model/ai-site-store-pages.js +1 -1
  144. package/src/lib/model/ai-site-store-pages.js.map +1 -1
  145. package/src/lib/runtime/ai-doctrine-validators.d.ts +78 -3
  146. package/src/lib/runtime/ai-doctrine-validators.js +219 -31
  147. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
  148. package/src/lib/runtime/ai-doctrine.d.ts +6 -1
  149. package/src/lib/runtime/ai-doctrine.js +16 -7
  150. package/src/lib/runtime/ai-doctrine.js.map +1 -1
  151. package/src/lib/runtime/ai-eval-live.d.ts +1 -1
  152. package/src/lib/runtime/ai-eval-live.js +1 -1
  153. package/src/lib/runtime/ai-eval-live.js.map +1 -1
  154. package/src/lib/runtime/ai-palette.d.ts +3 -1
  155. package/src/lib/runtime/ai-palette.generated.js +499 -11
  156. package/src/lib/runtime/ai-palette.generated.js.map +1 -1
  157. package/src/lib/runtime/ai-palette.js +5 -3
  158. package/src/lib/runtime/ai-palette.js.map +1 -1
  159. package/src/lib/runtime/ai-products-generation.d.ts +4 -2
  160. package/src/lib/runtime/ai-products-generation.js +12 -6
  161. package/src/lib/runtime/ai-products-generation.js.map +1 -1
  162. package/src/lib/runtime/ai-template-examples.js +8 -2
  163. package/src/lib/runtime/ai-template-examples.js.map +1 -1
  164. package/src/lib/runtime/site-inventory.d.ts +12 -0
  165. package/src/lib/runtime/site-inventory.js +29 -1
  166. package/src/lib/runtime/site-inventory.js.map +1 -1
  167. package/src/lib/server.js +20 -0
  168. package/src/lib/server.js.map +1 -1
  169. package/src/lib/testing/stand-in-dataset-index.js +37 -3
  170. package/src/lib/testing/stand-in-dataset-index.js.map +1 -1
  171. package/src/lib/tools/ai-products-tool.d.ts +3 -1
  172. package/src/lib/tools/ai-products-tool.js +15 -5
  173. package/src/lib/tools/ai-products-tool.js.map +1 -1
@@ -16,7 +16,7 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
16
16
  * limitations under the License.
17
17
  */ import { aiSiteKindOfInputs } from "../model/ai-site-kinds.js";
18
18
  import { createHash } from "node:crypto";
19
- import { AI_BUILD_PLAN_TOOL, aiBuildPlanToolFor, isAiPlanNewRef } from "../model/ai-build-plan.js";
19
+ import { AI_BUILD_PLAN_TOOL, aiBuildPlanToolFor, aiPlanSlugKey, isAiPlanNewRef } from "../model/ai-build-plan.js";
20
20
  import { AI_BUILD_PRODUCT_OP, aiBuildStorePagesFor } from "../model/ai-build-store-pages.js";
21
21
  import { readFreeAiCreditsLeft } from "../usage/free-ai-credits-left.js";
22
22
  import { AI_TEMPLATE_SUBJECT_DEFINITIONS, aiTemplateShownTokens } from "../model/ai-template-subjects.js";
@@ -24,7 +24,7 @@ import { AI_JOB_CREATE_KINDS, AI_JOB_CREATE_NOUNS } from "../model/ai-job-creati
24
24
  import { AI_PAGE_CREATE_KINDS, aiPagePlanShapeRefusal } from "../model/ai-page-job.js";
25
25
  import { AI_PLAN_COMPILED_REPEATS_SENTENCE, AI_PLAN_NO_FORM_SENTENCE, aiPlanCanPlaceForm, aiPlanCapabilitiesForJob, aiPlanCapabilityLines } from "../model/ai-plan-capabilities.js";
26
26
  import { aiSitePlanDatasetCapability } from "./ai-job-site-datasets.js";
27
- import { AI_FREE_SITE_WORST_CASE_CREDITS, AI_SITE_CREATE_KINDS, AI_SITE_FREE_PAGES, AI_SITE_PLAN_MAX_TOKENS, AI_SITE_HOME_BANDS, aiFreeSiteSectionsWithin, aiSiteFullPlanSentence, aiSiteHomeMinSections, aiSiteNameSentence, aiSitePlanIsHome, aiSitePlanShapeRefusal, aiSiteBlogStandInViolations, aiSiteThinHomeViolations, AI_SITE_GALLERY_SENTENCE, aiSiteEmptyGalleryViolations, AI_SITE_DATASETS_MAX } from "../model/ai-site-job.js";
27
+ import { AI_FREE_SITE_WORST_CASE_CREDITS, AI_SITE_CREATE_KINDS, AI_SITE_FREE_PAGES, AI_SITE_PLAN_MAX_TOKENS, AI_SITE_HOME_BANDS, aiFreeSiteSectionsWithin, aiSiteFullPlanSentence, aiSiteHomeMinSections, aiSiteNameSentence, aiSitePlanIsHome, aiSitePlanShapeRefusal, aiSiteBlogStandInViolations, aiSiteThinHomeViolations, AI_SITE_GALLERY_SENTENCE, aiSiteEmptyGalleryViolations, AI_SITE_DATASETS_MAX, AI_SITE_GALLERY_MIN_ITEMS } from "../model/ai-site-job.js";
28
28
  import { aiSiteContentPart } from "./ai-job-site-content.js";
29
29
  import { aiLayoutIsShopPage, aiLayoutShopGridSection } from "../layout-language/ai-layout-listings.js";
30
30
  import { aiStorefrontPlanScreens } from "../layout-language/ai-layout-storefront.js";
@@ -43,6 +43,8 @@ import { readAiSiteContext } from "../runtime/site-context.js";
43
43
  import { aiInstructionsWithSiteContext } from "../model/ai-site-context.js";
44
44
  import { AI_BUILD_CREATE_KINDS, AI_BUILD_STRUCTURAL_OPS, aiBuildPageLimit, aiBuildPlanShapeRefusal } from "../model/ai-build-job.js";
45
45
  import { aiBuildOpLines, aiBuildOps } from "./ai-build-capabilities.js";
46
+ import { aiBuildUnlistedEventsCheck, aiSettleBuildEventPage } from "../model/ai-build-event-page.js";
47
+ import { aiSiteEventItemsCheck, aiSiteEventPlanLines, readAiSiteEventPlanning } from "./ai-job-site-events.js";
46
48
  import { aiJobAdmissionRefusal } from "./ai-job-admission.js";
47
49
  import { AI_CREDITS_CONFIRM_CODE } from "../model/ai-credit-estimate.js";
48
50
  import { readAiPlanCapabilities } from "./ai-job-drafts.js";
@@ -113,7 +115,7 @@ import { AI_JOBS_COLLECTION, registerAiJobPlanStep } from "./ai-jobs.js";
113
115
  * inputs and, where the job read them, what it may create on its site
114
116
  * (AGL-3030). Per workspace and per site, which is why they ride here and
115
117
  * never in a system block the platform's cache entry is keyed on.
116
- */ export function aiJobPlanPrompt(job, capabilities = null, inventory = null, ops = null) {
118
+ */ export function aiJobPlanPrompt(job, capabilities = null, inventory = null, ops = null, now = null) {
117
119
  var _job_inputs;
118
120
  const lines = [
119
121
  `Job kind: ${job.kind}`,
@@ -132,7 +134,7 @@ import { AI_JOBS_COLLECTION, registerAiJobPlanStep } from "./ai-jobs.js";
132
134
  }
133
135
  lines.push(...aiPlanTemplateTokenLines(job));
134
136
  lines.push(...aiPlanSiteLines(job, inventory, capabilities));
135
- lines.push(...aiPlanBuildLines(job, capabilities, ops));
137
+ lines.push(...aiPlanBuildLines(job, capabilities, ops, now));
136
138
  return lines.join('\n');
137
139
  }
138
140
  /**
@@ -140,7 +142,7 @@ import { AI_JOBS_COLLECTION, registerAiJobPlanStep } from "./ai-jobs.js";
140
142
  * creations and items, how many pages it may hold, and the item operations
141
143
  * this site has with their arguments. On the job's own turn, never a cached
142
144
  * system block, because the operations are per site.
143
- */ export function aiPlanBuildLines(job, capabilities, ops) {
145
+ */ export function aiPlanBuildLines(job, capabilities, ops, now = null) {
144
146
  if (job.kind !== 'build') return [];
145
147
  const pages = aiBuildPageLimit((capabilities == null ? void 0 : capabilities.freeTaste) === true);
146
148
  return [
@@ -151,9 +153,16 @@ import { AI_JOBS_COLLECTION, registerAiJobPlanStep } from "./ai-jobs.js";
151
153
  ...(capabilities == null ? void 0 : capabilities.repeatsCompiled) ? [
152
154
  AI_PLAN_COMPILED_REPEATS_SENTENCE
153
155
  ] : [],
154
- ...ops ? aiBuildOpLines(ops, AI_BUILD_STRUCTURAL_OPS) : []
156
+ ...ops ? aiBuildOpLines(ops, AI_BUILD_STRUCTURAL_OPS) : [],
157
+ // An item with a date (an event, AGL-3743) is dated after the build.
158
+ ...now ? [
159
+ aiPlanTodaySentence(now)
160
+ ] : []
155
161
  ];
156
162
  }
163
+ /** The build's date, so a dated item falls after it (AGL-3743). */ export function aiPlanTodaySentence(now) {
164
+ return `Today is ${now.toISOString().slice(0, 10)} (UTC). Anything an item dates, such as an event, falls after today.`;
165
+ }
157
166
  /**
158
167
  * What a SITE job's plan is told beside the inventory (AGL-3594): the pages
159
168
  * the site already has and that their addresses are taken, which one — the
@@ -350,7 +359,10 @@ import { AI_JOBS_COLLECTION, registerAiJobPlanStep } from "./ai-jobs.js";
350
359
  /**
351
360
  * A site plan's section that shows the work without its pieces (AGL-3660),
352
361
  * asked about on the FIRST answer only, like a thin home: the re-ask names
353
- * the section, and an answer that keeps it thin is kept.
362
+ * the section, and an answer that keeps it thin is kept. A site start's plan
363
+ * is given its fewest pieces in code first (`aiSettlePlanGalleries`,
364
+ * AGL-3754), so this is the backstop for a section that settle leaves: one
365
+ * item of a list split into sections.
354
366
  */ export function aiSiteEmptyGalleryCheck() {
355
367
  let answers = 0;
356
368
  return (plan)=>{
@@ -470,6 +482,27 @@ import { AI_JOBS_COLLECTION, registerAiJobPlanStep } from "./ai-jobs.js";
470
482
  ];
471
483
  };
472
484
  }
485
+ /** The layout a site's pages render in (AGL-3755): its home page's, else its only layout, else none. */ function aiSiteLayoutOf(inventory) {
486
+ var _ref;
487
+ var _inventory_layouts_;
488
+ const home = inventory == null ? void 0 : inventory.screens.find((screen)=>!screen.template && aiPlanSlugKey(screen.slug) === '/');
489
+ if (home == null ? void 0 : home.layoutId) return home.layoutId;
490
+ return (inventory == null ? void 0 : inventory.layouts.length) === 1 ? (_ref = (_inventory_layouts_ = inventory.layouts[0]) == null ? void 0 : _inventory_layouts_.id) != null ? _ref : null : null;
491
+ }
492
+ /**
493
+ * A site plan's violations with its events' (AGL-3755): its items are only
494
+ * the events it may plan. Every other kind's are as they are.
495
+ */ function aiSiteWithEventItemsCheck(violations, siteEvents, ops = null) {
496
+ // A build's events left on no page are re-asked once (AGL-3755).
497
+ const unlisted = ops ? aiBuildUnlistedEventsCheck(ops) : null;
498
+ const events = siteEvents === undefined ? null : aiSiteEventItemsCheck(siteEvents);
499
+ if (!unlisted && !events) return violations;
500
+ return (plan)=>[
501
+ ...violations(plan),
502
+ ...events ? events(plan) : [],
503
+ ...unlisted ? unlisted(plan) : []
504
+ ];
505
+ }
473
506
  /**
474
507
  * The inventory names of every id the plan references, so the proposal reads
475
508
  * "the Services layout" rather than an id — kept on the plan because the
@@ -695,8 +728,9 @@ export function createAiJobPlanStep(deps = {}) {
695
728
  const readOps = (_deps_readOps = deps.readOps) != null ? _deps_readOps : readAiBuildOps;
696
729
  const readContext = deps.readSiteContext === undefined ? readAiJobSiteContext : deps.readSiteContext;
697
730
  const readFreeCredits = deps.readFreeCredits === undefined ? readFreeAiCreditsLeft : deps.readFreeCredits;
731
+ const readSiteEvents = deps.readSiteEvents === undefined ? readAiSiteEventPlanning : deps.readSiteEvents;
698
732
  return async ({ job, now, signal, firestore, modelFor, org: orgDocument })=>{
699
- var _AI_JOB_PLAN_SCOPES_job_kind, _job_inputs, _ref;
733
+ var _AI_JOB_PLAN_SCOPES_job_kind, _ref, _job_inputs, _ref1;
700
734
  var _aiSiteKindOfInputs, _aiSiteKindOfInputs1;
701
735
  const org = orgDocument != null ? orgDocument : null;
702
736
  const [inventory, workspace, siteContext] = await Promise.all([
@@ -728,6 +762,21 @@ export function createAiJobPlanStep(deps = {}) {
728
762
  freeTaste
729
763
  }) : null;
730
764
  const site = job.kind === 'site';
765
+ // An event-led start's first events (AGL-3755), only where the build's
766
+ // gate admits the events plugin's operation here and its writer this member.
767
+ const siteEvents = site && readSiteEvents ? await readSiteEvents({
768
+ job,
769
+ org,
770
+ firestore,
771
+ now,
772
+ readOps: ()=>readOps({
773
+ job,
774
+ org,
775
+ firestore,
776
+ freeTaste
777
+ })
778
+ }) : null;
779
+ const itemOps = (_ref = ops != null ? ops : siteEvents == null ? void 0 : siteEvents.ops) != null ? _ref : null;
731
780
  // A kept plan waits for its confirmation; a Free build's card is told what
732
781
  // is left, so it says before Confirm whether the build fits (AGL-3722).
733
782
  // Net of what THIS plan just spent: the machine meters the step after it
@@ -758,7 +807,10 @@ export function createAiJobPlanStep(deps = {}) {
758
807
  // provider's fast tier (AGL-3594), unless the creator picked a model.
759
808
  const model = aiSitePlanModel(job, modelFor == null ? void 0 : modelFor('job.plan'), freeTaste);
760
809
  const route = AI_ROUTING_TABLE['job.plan'];
761
- const prompt = aiJobPlanPrompt(job, capabilities, inventory, ops);
810
+ const prompt = [
811
+ aiJobPlanPrompt(job, capabilities, inventory, ops, now),
812
+ ...siteEvents ? aiSiteEventPlanLines(siteEvents, now) : []
813
+ ].join('\n');
762
814
  /**
763
815
  * The confirm door's answer for this plan, asked before the plan is kept
764
816
  * (AGL-3030): the kind's own admission, handed the plan as the resume
@@ -812,10 +864,12 @@ export function createAiJobPlanStep(deps = {}) {
812
864
  const resolved = model != null ? model : aiModelForStep('job.plan');
813
865
  // A brief that asks for a video is offered the plan's list of players
814
866
  // (AGL-3433), and a job that may bind a dataset a record template on
815
- // each screen (AGL-3475).
867
+ // each screen (AGL-3475). A site's plan says the language its brief is
868
+ // written in, which its guided start sets the site's language from (AGL-3750).
816
869
  const tool = aiBuildPlanToolFor(job.brief, {
817
870
  records: Boolean(inventory == null ? void 0 : inventory.datasets.length) || (capabilities == null ? void 0 : capabilities.create.dataset.allowed) === true,
818
- items: job.kind === 'build'
871
+ items: job.kind === 'build' || Boolean(siteEvents),
872
+ language: site
819
873
  });
820
874
  const key = aiJobPlanKey({
821
875
  job,
@@ -831,9 +885,9 @@ export function createAiJobPlanStep(deps = {}) {
831
885
  now
832
886
  }) : null;
833
887
  if (reused) {
834
- var _ref1;
888
+ var _ref2;
835
889
  // The reused plan's draft ids name the other job's drafts; this job's are its own.
836
- const plan = aiPlanWithStorePages(job.kind, ops, inventory, aiPlanWithItemCredits(ops, aiPlanWithDraftIds(job.kind, _extends({}, reused.plan, {
890
+ const plan = aiPlanWithStorePages(job.kind, ops, inventory, aiPlanWithItemCredits(itemOps, aiPlanWithDraftIds(job.kind, _extends({}, reused.plan, {
837
891
  status: 'proposed',
838
892
  labels: aiPlanLabels(reused.plan, inventory),
839
893
  proposedAt: now,
@@ -843,7 +897,7 @@ export function createAiJobPlanStep(deps = {}) {
843
897
  reusedFrom: reused.jobId
844
898
  }))));
845
899
  const unspent = aiUnspentOutcome(resolved);
846
- return (_ref1 = await refusalOnKeep(plan, unspent)) != null ? _ref1 : _extends({}, unspent, {
900
+ return (_ref2 = await refusalOnKeep(plan, unspent)) != null ? _ref2 : _extends({}, unspent, {
847
901
  plan,
848
902
  review: await planReview()
849
903
  });
@@ -875,8 +929,19 @@ export function createAiJobPlanStep(deps = {}) {
875
929
  } : {}, signal ? {
876
930
  signal
877
931
  } : {}, {
878
- capabilities,
879
- extend: planViolations(scope, job.brief, freeTaste, ops, site ? aiSitePlanHomeRule(inventory, capabilities) : null, site && aiSiteContentPart((_job_inputs = job.inputs) != null ? _job_inputs : null, freeTaste) === 'posts', site, site && ((_aiSiteKindOfInputs = aiSiteKindOfInputs(job.inputs)) == null ? void 0 : _aiSiteKindOfInputs.id) === 'store')
932
+ capabilities
933
+ }, ops ? {
934
+ settle: (answered)=>{
935
+ var _ref;
936
+ return aiSettleBuildEventPage(answered, {
937
+ ops,
938
+ siteSlugs: ((_ref = inventory == null ? void 0 : inventory.screens) != null ? _ref : []).map((screen)=>screen.slug),
939
+ pageLimit: aiBuildPageLimit(freeTaste),
940
+ siteLayout: aiSiteLayoutOf(inventory)
941
+ });
942
+ }
943
+ } : {}, {
944
+ extend: aiSiteWithEventItemsCheck(planViolations(scope, job.brief, freeTaste, ops, site ? aiSitePlanHomeRule(inventory, capabilities) : null, site && aiSiteContentPart((_job_inputs = job.inputs) != null ? _job_inputs : null, freeTaste) === 'posts', site, site && ((_aiSiteKindOfInputs = aiSiteKindOfInputs(job.inputs)) == null ? void 0 : _aiSiteKindOfInputs.id) === 'store'), site ? siteEvents : undefined, ops)
880
945
  }));
881
946
  const spent = _extends({
882
947
  outputs: [],
@@ -924,7 +989,7 @@ export function createAiJobPlanStep(deps = {}) {
924
989
  paid: !freeTaste
925
990
  }) : result.value;
926
991
  // Each draft the plan decides is named as the plan is kept, before anything is built (AGL-3079).
927
- const plan = aiPlanWithStorePages(job.kind, ops, inventory, aiPlanWithItemCredits(ops, aiPlanWithDraftIds(job.kind, _extends({}, answered, {
992
+ const plan = aiPlanWithStorePages(job.kind, ops, inventory, aiPlanWithItemCredits(itemOps, aiPlanWithDraftIds(job.kind, _extends({}, answered, {
928
993
  status: 'proposed',
929
994
  labels: aiPlanLabels(answered, inventory),
930
995
  // A Date the Admin SDK stores as a timestamp, like every instant the machine writes.
@@ -933,7 +998,7 @@ export function createAiJobPlanStep(deps = {}) {
933
998
  confirmedBy: null,
934
999
  key
935
1000
  }))));
936
- return (_ref = await refusalOnKeep(plan, spent)) != null ? _ref : _extends({}, spent, {
1001
+ return (_ref1 = await refusalOnKeep(plan, spent)) != null ? _ref1 : _extends({}, spent, {
937
1002
  plan,
938
1003
  review: await planReview(result.estCostUsd)
939
1004
  });
@@ -973,11 +1038,13 @@ export function createAiJobPlanStep(deps = {}) {
973
1038
  reason: 'a site start draws its repeated items in their sections'
974
1039
  }
975
1040
  });
976
- // At most a start's few datasets, settled in code where a plan names more (AGL-3616).
1041
+ // At most a start's few datasets, settled in code where a plan names more
1042
+ // (AGL-3616); a section that shows the work with its fewest pieces (AGL-3754).
977
1043
  const site = _extends({}, capabilities, {
978
1044
  reusableComponents: false,
979
1045
  create,
980
- datasetsMax: AI_SITE_DATASETS_MAX
1046
+ datasetsMax: AI_SITE_DATASETS_MAX,
1047
+ galleryMinItems: AI_SITE_GALLERY_MIN_ITEMS
981
1048
  });
982
1049
  if (!capabilities.freeTaste) return site;
983
1050
  const asked = Number(((_job_inputs = job.inputs) != null ? _job_inputs : {})['pages']);