@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
@@ -17,11 +17,11 @@ 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_PUBLISH_INPUT, aiArticle, aiBuildCreditRange, aiBuildDegradation, aiBuildInitialLedger, aiBuildItemDelivered, aiBuildItemOpen, aiBuildNextUnit, aiBuildOrder, aiBuildPlacedItemLines, aiBuildPlanShapeRefusal, aiBuildSmaller, aiBuildUnits } from "../model/ai-build-job.js";
20
+ import { AI_BUILD_LIMITS, AI_BUILD_MADE_INPUT, AI_BUILD_PUBLISH_INPUT, aiArticle, aiBuildCreditRange, aiBuildDegradation, aiBuildInitialLedger, aiBuildItemDelivered, aiBuildItemOpen, aiBuildNextUnit, aiBuildOrder, aiBuildItemOutputNote, aiBuildPlacedItemLines, aiBuildPlanMissingInput, aiBuildPlanShapeRefusal, aiBuildSmaller, aiBuildUnits } from "../model/ai-build-job.js";
21
21
  import { isAiPlanNewRef } from "../model/ai-build-plan.js";
22
22
  import { 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
- import { aiFreeCreditsNoneLeftText } from "../model/ai-site-job.js";
24
+ import { aiFreeCreditsNoneLeftText, aiSiteWords } from "../model/ai-site-job.js";
25
25
  import { readFreeAiCreditsLeft } from "../usage/free-ai-credits-left.js";
26
26
  import { aiModelForStep } from "../providers/routing.js";
27
27
  import { AI_BUILD_UNIT_EMPTY_COPY, aiBuildBuiltRefs, aiUnitErrorRetryable, aiUnitFailure, aiUnitSpend } from "./ai-build-unit-outcome.js";
@@ -36,6 +36,7 @@ import { aiSitePageWritten, aiSiteResolvedRef } from "./ai-job-site-step.js";
36
36
  import { AI_LAYOUT_SITE_PAGES_INPUT, aiLayoutSitePagesOfPlan } from "./ai-job-layout-site-pages.js";
37
37
  import { AI_LAYOUT_FORM_PAGE_INPUT, AI_LAYOUT_LANGUAGE_INPUT, aiLayoutFormPageOfPlan } from "./ai-job-page-language.js";
38
38
  import { aiDatasetListingsOf } from "./ai-job-site-datasets.js";
39
+ import { AI_SITE_EVENT_OP, aiEventsListings } from "./ai-job-site-events.js";
39
40
  import { AI_FORM_DATASET_MADE_INPUT } from "./ai-job-form-dataset.js";
40
41
  import { AI_LAYOUT_LISTINGS_INPUT } from "../layout-language/ai-layout-listings.js";
41
42
  import { AI_BUILD_STORE_OP, AI_BUILD_STORE_PAGES_PRESENT_NOTE, aiBuildStoreLayoutLinks, aiBuildStoreLayoutOf, aiBuildStorePagesOf, aiBuildStorePagesStillMissing } from "../model/ai-build-store-pages.js";
@@ -43,7 +44,7 @@ import { writeAiStoreLinksLayoutDraft } from "./ai-job-store-links-layout.js";
43
44
  import { AI_SITE_STORE_LINKS_INPUT, AI_SITE_STORE_PAGES_NOTE, aiStoreFrameLinks, aiStorePagesToWrite } from "../model/ai-site-store-pages.js";
44
45
  import { AI_SITE_STORE_PAGES_INPUT, aiSiteStorePageId, aiSiteStorePagesRefusal, runAiSiteStorePagesUnit } from "./ai-job-site-store-pages.js";
45
46
  import { AI_JOB_BRIEF_MAX_CHARS } from "./ai-job-text-step.js";
46
- import { aiJobPublishesBuild, aiPublishGuidedSite } from "./ai-site-publish.js";
47
+ import { aiJobPublishesBuild, aiMergeSitePublish, aiPublishGuidedSite } from "./ai-site-publish.js";
47
48
  import { AI_PLANNED_JOB_KINDS, aiJobStepRunMinimumMs, aiJobStepRunnerFor, registerAiJobStep, registerAiJobStepPasses } from "./ai-jobs.js";
48
49
  /**
49
50
  * The build step (AGL-3616): the generation step of a `build` job, run once
@@ -97,6 +98,7 @@ import { AI_PLANNED_JOB_KINDS, aiJobStepRunMinimumMs, aiJobStepRunnerFor, regist
97
98
  const runnerKind = (_ops_get = ops.get(unit.op)) == null ? void 0 : _ops_get.runnerKind;
98
99
  return runnerKind ? runnerKind : null;
99
100
  }
101
+ /** What the job drawer says under an item another plugin's writer made (`model/ai-build-job.ts`). */ export { aiBuildItemOutputNote };
100
102
  /** The id a unit's job, and so its draft, is named by. */ export function aiBuildUnitJobId(job, unit) {
101
103
  var _ref, _ref1, _ref2;
102
104
  var _unit_creation, _unit_screen, _unit_item;
@@ -167,10 +169,14 @@ import { AI_PLANNED_JOB_KINDS, aiJobStepRunMinimumMs, aiJobStepRunnerFor, regist
167
169
  })
168
170
  ];
169
171
  brief.push(`Build the page “${screen.title}”, at ${screen.slug}.`);
172
+ // A build's events are listed by the platform (AGL-3755), never written by the page.
170
173
  brief.push(...aiBuildPlacedItemLines(unit, {
171
174
  units: context.units,
172
175
  ledger: context.ledger,
173
- ops: context.ops
176
+ ops: context.ops,
177
+ placedByCode: [
178
+ AI_SITE_EVENT_OP
179
+ ]
174
180
  }));
175
181
  }
176
182
  const item = unit.item;
@@ -197,6 +203,33 @@ import { AI_PLANNED_JOB_KINDS, aiJobStepRunMinimumMs, aiJobStepRunnerFor, regist
197
203
  originJobId: aiOriginJobId(job)
198
204
  });
199
205
  delete inputs[AI_BUILD_PUBLISH_INPUT];
206
+ // An item is told the pages and layouts this build made before it, which
207
+ // its arguments may link as `new:<name>` (a menu item, AGL-3728).
208
+ if (item) {
209
+ const rows = new Map(context.ledger.map((row)=>[
210
+ row.slot,
211
+ row
212
+ ]));
213
+ const made = {
214
+ pages: context.units.flatMap((one)=>{
215
+ var _one_screen;
216
+ const row = rows.get(one.slot);
217
+ return ((_one_screen = one.screen) == null ? void 0 : _one_screen.id) && row && aiBuildItemDelivered(row) ? [
218
+ {
219
+ title: one.screen.title,
220
+ id: one.screen.id
221
+ }
222
+ ] : [];
223
+ }),
224
+ layouts: [
225
+ ...built.entries()
226
+ ].filter(([, entry])=>entry.kind === 'layout').map(([name, entry])=>({
227
+ name,
228
+ id: entry.id
229
+ }))
230
+ };
231
+ if (made.pages.length || made.layouts.length) inputs[AI_BUILD_MADE_INPUT] = made;
232
+ }
200
233
  // A dataset this build made for its form, which the form may bind (AGL-3616).
201
234
  const madeFor = ((_unit_creation = unit.creation) == null ? void 0 : _unit_creation.kind) === 'form' && isAiPlanNewRef(unit.creation.writesTo) ? (_unitPlan_create_ = unitPlan.create[0]) == null ? void 0 : _unitPlan_create_.writesTo : null;
202
235
  if (madeFor) inputs[AI_FORM_DATASET_MADE_INPUT] = madeFor;
@@ -208,7 +241,9 @@ import { AI_PLANNED_JOB_KINDS, aiJobStepRunMinimumMs, aiJobStepRunnerFor, regist
208
241
  if (pages.length) inputs[AI_LAYOUT_SITE_PAGES_INPUT] = pages;
209
242
  const formPage = aiLayoutFormPageOfPlan(plan);
210
243
  if (formPage) inputs[AI_LAYOUT_FORM_PAGE_INPUT] = formPage;
211
- // The datasets this build made, repeated in the sections that name them (AGL-3616).
244
+ // The datasets this build made, repeated in the sections that name them (AGL-3616),
245
+ // and the site's own the plan reuses (AGL-3747): the page reads their fields,
246
+ // and the record pages the site already serves for them, off its inventory.
212
247
  const datasets = [
213
248
  ...built.entries()
214
249
  ].filter(([, entry])=>entry.kind === 'dataset').map(([name, entry])=>{
@@ -222,7 +257,41 @@ import { AI_PLANNED_JOB_KINDS, aiJobStepRunMinimumMs, aiJobStepRunnerFor, regist
222
257
  })) == null ? void 0 : _context_units_find.label) != null ? _ref : entry.label
223
258
  };
224
259
  });
260
+ for (const entry of plan.reuse){
261
+ var _ref2;
262
+ var _plan_labels1;
263
+ if (entry.kind !== 'dataset' || datasets.some((one)=>one.id === entry.id)) continue;
264
+ datasets.push({
265
+ id: entry.id,
266
+ name: (_ref2 = (_plan_labels1 = plan.labels) == null ? void 0 : _plan_labels1[entry.id]) != null ? _ref2 : entry.id
267
+ });
268
+ }
225
269
  const listings = aiDatasetListingsOf(datasets, plan.screens);
270
+ // The events this build wrote, in the sections that name them (AGL-3755).
271
+ const eventUnits = context.units.filter((one)=>{
272
+ var _one_item;
273
+ return ((_one_item = one.item) == null ? void 0 : _one_item.op) === AI_SITE_EVENT_OP;
274
+ });
275
+ const ledgerRows = new Map(context.ledger.map((row)=>[
276
+ row.slot,
277
+ row
278
+ ]));
279
+ listings.push(...aiEventsListings({
280
+ written: eventUnits.filter((one)=>{
281
+ const row = ledgerRows.get(one.slot);
282
+ return Boolean(row && aiBuildItemDelivered(row) && row.outputs.length);
283
+ }).map((one)=>{
284
+ var _ref;
285
+ var _one_item;
286
+ return (_ref = (_one_item = one.item) == null ? void 0 : _one_item.name) != null ? _ref : one.label;
287
+ }),
288
+ planned: eventUnits.map((one)=>{
289
+ var _ref;
290
+ var _one_item;
291
+ return (_ref = (_one_item = one.item) == null ? void 0 : _one_item.name) != null ? _ref : one.label;
292
+ }),
293
+ screens: plan.screens
294
+ }));
226
295
  if (listings.length) inputs[AI_LAYOUT_LISTINGS_INPUT] = listings;
227
296
  }
228
297
  // A build that makes the site a store links its account and policies from
@@ -368,7 +437,10 @@ import { AI_PLANNED_JOB_KINDS, aiJobStepRunMinimumMs, aiJobStepRunnerFor, regist
368
437
  /** The store's links a build drafted into the site's layout (AGL-3676), as its publish puts them live; `null` where it drafted none. */ export function aiBuildStoreLinksToPublish(outputs) {
369
438
  var _ref;
370
439
  var _draft_proposal, _draft_proposal1;
371
- const draft = outputs.find((output)=>{
440
+ // The newest: a retried store drafts its links again after the first attempt's (AGL-3739).
441
+ const draft = [
442
+ ...outputs
443
+ ].reverse().find((output)=>{
372
444
  var _output_proposal;
373
445
  return output.resource === 'layout' && ((_output_proposal = output.proposal) == null ? void 0 : _output_proposal['storeLinks']) === 'draft' && output.versionId;
374
446
  });
@@ -437,9 +509,17 @@ export function createAiJobBuildStep(deps = {}) {
437
509
  status: 'pending'
438
510
  });
439
511
  });
440
- /** The build's last pass puts its pages live, where it was asked and confirmed. */ const finish = async (outcome, extraPages = [], extraOutputs = [])=>{
441
- var _job_outputs, _job_outputs1;
442
- if (!aiJobPublishesBuild(job) || job.sitePublish || !job.hostId) return outcome;
512
+ /**
513
+ * The build's last pass puts its pages live, where it was asked and
514
+ * confirmed. Once it has, Try again's last pass puts only the pages the
515
+ * retry built live (AGL-3739, AGL-3730's fix for a site start),
516
+ * merged into the record of the first.
517
+ */ const finish = async (outcome, extraPages = [], extraOutputs = [])=>{
518
+ var _job_sitePublish, _ref, _job_outputs, _job_outputs1;
519
+ if (!aiJobPublishesBuild(job) || !job.hostId) return outcome;
520
+ const previous = (_job_sitePublish = job.sitePublish) != null ? _job_sitePublish : null;
521
+ const retry = Boolean(previous == null ? void 0 : previous.published.length);
522
+ const already = new Set(((_ref = previous == null ? void 0 : previous.published) != null ? _ref : []).map((page)=>page.id));
443
523
  // A record template renders once per record only once its binding is
444
524
  // saved, so it is never published at its own address (AGL-3616).
445
525
  // A store's own pages (AGL-3676) go live with the pages the build planned.
@@ -453,24 +533,30 @@ export function createAiJobBuildStep(deps = {}) {
453
533
  var _rows_get;
454
534
  return (_ref = (_rows_get = rows.get(one.slot)) == null ? void 0 : _rows_get.outputs) != null ? _ref : [];
455
535
  }));
456
- const pages = [
536
+ const built = [
457
537
  ...((_job_outputs = job.outputs) != null ? _job_outputs : []).filter((output)=>output.resource === 'screen' && pageIds.has(output.id)),
458
538
  ...extraPages
459
539
  ];
540
+ const pages = built.filter((page)=>!already.has(page.id));
460
541
  if (!pages.length) return outcome;
461
542
  // A canceled build never puts anything live (AGL-3616): its pages stay drafts.
462
543
  if (await aiJobCancelAsked(firestore, job, context.signal)) return outcome;
463
544
  // The store pages a layout this build made links and that were not written come out of it.
464
545
  const storePages = aiBuildStorePagesOf(plan);
465
- const live = new Set(pages.map((page)=>{
546
+ const live = new Set(built.map((page)=>{
466
547
  var _page_proposal;
467
548
  return (_page_proposal = page.proposal) == null ? void 0 : _page_proposal['storePage'];
468
549
  }).filter(Boolean));
469
550
  const unwrittenHrefs = storePages ? aiStorePagesToWrite(storePages.pages).filter((page)=>!live.has(page.key)).map((page)=>page.href) : [];
470
- const storeLinks = aiBuildStoreLinksToPublish([
551
+ // A retry puts the store's links live only with store pages it built:
552
+ // the first publish's links draft is live already, and a person may have edited it since.
553
+ const storeLinks = !retry || pages.some((page)=>{
554
+ var _page_proposal;
555
+ return (_page_proposal = page.proposal) == null ? void 0 : _page_proposal['storePage'];
556
+ }) ? aiBuildStoreLinksToPublish([
471
557
  ...(_job_outputs1 = job.outputs) != null ? _job_outputs1 : [],
472
558
  ...extraOutputs
473
- ]);
559
+ ]) : null;
474
560
  const sitePublish = await publish(firestore, _extends({
475
561
  job,
476
562
  outputs: pages,
@@ -479,6 +565,8 @@ export function createAiJobBuildStep(deps = {}) {
479
565
  unwrittenHrefs
480
566
  } : {}, storeLinks ? {
481
567
  storeLinks
568
+ } : {}, retry ? {
569
+ retry: true
482
570
  } : {})).catch((error)=>{
483
571
  console.error('ai build publish threw', {
484
572
  orgId: job.orgId,
@@ -487,9 +575,10 @@ export function createAiJobBuildStep(deps = {}) {
487
575
  });
488
576
  return null;
489
577
  });
490
- return sitePublish ? _extends({}, outcome, {
491
- sitePublish
492
- }) : outcome;
578
+ if (!sitePublish) return outcome;
579
+ return _extends({}, outcome, {
580
+ sitePublish: previous ? aiMergeSitePublish(previous, sitePublish) : sitePublish
581
+ });
493
582
  };
494
583
  if (!unit) return finish(_extends({}, aiUnspentOutcome(model), init));
495
584
  const settle = (item, spent = aiUnspentOutcome(model))=>_extends({}, spent, init, {
@@ -705,6 +794,11 @@ export function createAiJobBuildStep(deps = {}) {
705
794
  uid: job.createdBy,
706
795
  org,
707
796
  now: context.now,
797
+ // Drafts of one build share what must not repeat (a cover photo) and read its business (AGL-3755).
798
+ act: {
799
+ id: aiOriginJobId(job),
800
+ business: aiSiteWords(job.inputs).about || job.brief || ''
801
+ },
708
802
  id,
709
803
  name: item.name,
710
804
  content
@@ -723,7 +817,8 @@ export function createAiJobBuildStep(deps = {}) {
723
817
  hostId: job.hostId,
724
818
  label: written.name,
725
819
  draftResource: capability.draftResource,
726
- note: `A draft, in ${capability.where}.`
820
+ // A resource with no draft state is live once written (AGL-3745, AGL-3746).
821
+ note: aiBuildItemOutputNote(capability, written)
727
822
  };
728
823
  return settle(_extends({
729
824
  slot: unit.slot,
@@ -874,7 +969,12 @@ export const runAiJobBuildStep = createAiJobBuildStep();
874
969
  campaign: 'campaign',
875
970
  workflow: 'workflow',
876
971
  function: 'logic',
877
- edit: 'edit'
972
+ edit: 'edit',
973
+ navigation: 'navigation',
974
+ duplicate: 'duplicate',
975
+ settings: 'settings',
976
+ media: 'media',
977
+ tracking: 'tracking'
878
978
  };
879
979
  /**
880
980
  * What a Free build's credits say before it runs (AGL-3722), on its measured
@@ -956,6 +1056,12 @@ export const runAiJobBuildStep = createAiJobBuildStep();
956
1056
  status: 400,
957
1057
  error: shape
958
1058
  };
1059
+ // Something only the person can give (AGL-3751): asked, never built without.
1060
+ const missing = aiBuildPlanMissingInput(plan, ops);
1061
+ if (missing) return {
1062
+ status: 400,
1063
+ error: missing
1064
+ };
959
1065
  if (freeTaste) {
960
1066
  var _ref;
961
1067
  const refusal = await aiBuildFreeCreditsRefusal({