@aglyn/plugins-ai 1.0.0-beta.237 → 1.0.0-beta.238

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 (128) hide show
  1. package/package.json +17 -17
  2. package/src/lib/components/ai-credits-prompt.component.d.ts +11 -4
  3. package/src/lib/components/ai-credits-prompt.component.js +84 -34
  4. package/src/lib/components/ai-credits-prompt.component.js.map +1 -1
  5. package/src/lib/components/ai-job-cancel.component.d.ts +38 -0
  6. package/src/lib/components/ai-job-cancel.component.js +156 -0
  7. package/src/lib/components/ai-job-cancel.component.js.map +1 -0
  8. package/src/lib/components/ai-job-plan.component.js +12 -1
  9. package/src/lib/components/ai-job-plan.component.js.map +1 -1
  10. package/src/lib/components/ai-jobs-list-page.component.js +141 -72
  11. package/src/lib/components/ai-jobs-list-page.component.js.map +1 -1
  12. package/src/lib/components/ai-site-build-page.component.js +22 -2
  13. package/src/lib/components/ai-site-build-page.component.js.map +1 -1
  14. package/src/lib/components/ai-usage-strip.component.d.ts +19 -2
  15. package/src/lib/components/ai-usage-strip.component.js +40 -9
  16. package/src/lib/components/ai-usage-strip.component.js.map +1 -1
  17. package/src/lib/components/assist-jobs-drawer.component.js +12 -16
  18. package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
  19. package/src/lib/components/assist-panel.component.js +87 -51
  20. package/src/lib/components/assist-panel.component.js.map +1 -1
  21. package/src/lib/jobs/ai-job-build-step.js +4 -1
  22. package/src/lib/jobs/ai-job-build-step.js.map +1 -1
  23. package/src/lib/jobs/ai-job-cancel.d.ts +71 -0
  24. package/src/lib/jobs/ai-job-cancel.js +102 -0
  25. package/src/lib/jobs/ai-job-cancel.js.map +1 -0
  26. package/src/lib/jobs/ai-job-component-step.js +4 -1
  27. package/src/lib/jobs/ai-job-component-step.js.map +1 -1
  28. package/src/lib/jobs/ai-job-drafts.js +2 -0
  29. package/src/lib/jobs/ai-job-drafts.js.map +1 -1
  30. package/src/lib/jobs/ai-job-form-step.js +4 -1
  31. package/src/lib/jobs/ai-job-form-step.js.map +1 -1
  32. package/src/lib/jobs/ai-job-layout-language.d.ts +2 -0
  33. package/src/lib/jobs/ai-job-layout-language.js +13 -1
  34. package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
  35. package/src/lib/jobs/ai-job-layout-step.js +6 -1
  36. package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
  37. package/src/lib/jobs/ai-job-page-language.js +8 -0
  38. package/src/lib/jobs/ai-job-page-language.js.map +1 -1
  39. package/src/lib/jobs/ai-job-page-step.js +12 -1
  40. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  41. package/src/lib/jobs/ai-job-plan-step.d.ts +20 -1
  42. package/src/lib/jobs/ai-job-plan-step.js +49 -9
  43. package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
  44. package/src/lib/jobs/ai-job-site-content.d.ts +15 -0
  45. package/src/lib/jobs/ai-job-site-content.js +66 -7
  46. package/src/lib/jobs/ai-job-site-content.js.map +1 -1
  47. package/src/lib/jobs/ai-job-site-step.js +4 -1
  48. package/src/lib/jobs/ai-job-site-step.js.map +1 -1
  49. package/src/lib/jobs/ai-job-template-step.js +4 -1
  50. package/src/lib/jobs/ai-job-template-step.js.map +1 -1
  51. package/src/lib/jobs/ai-jobs.d.ts +37 -12
  52. package/src/lib/jobs/ai-jobs.js +184 -28
  53. package/src/lib/jobs/ai-jobs.js.map +1 -1
  54. package/src/lib/jobs/ai-layout-stock-photos.d.ts +143 -70
  55. package/src/lib/jobs/ai-layout-stock-photos.js +649 -176
  56. package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
  57. package/src/lib/jobs/fixtures/ai-ceramics-portfolio-site-plan.d.ts +30 -0
  58. package/src/lib/jobs/fixtures/ai-ceramics-portfolio-site-plan.js +220 -0
  59. package/src/lib/jobs/fixtures/ai-ceramics-portfolio-site-plan.js.map +1 -0
  60. package/src/lib/jobs/fixtures/ai-stock-photo-pixabay-recordings.d.ts +27 -0
  61. package/src/lib/jobs/fixtures/ai-stock-photo-pixabay-recordings.js +151 -0
  62. package/src/lib/jobs/fixtures/ai-stock-photo-pixabay-recordings.js.map +1 -0
  63. package/src/lib/layout-language/ai-layout-compiler.d.ts +6 -0
  64. package/src/lib/layout-language/ai-layout-compiler.js +304 -8
  65. package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
  66. package/src/lib/layout-language/ai-layout-design.d.ts +6 -3
  67. package/src/lib/layout-language/ai-layout-design.js +5 -3
  68. package/src/lib/layout-language/ai-layout-design.js.map +1 -1
  69. package/src/lib/layout-language/ai-layout-frame.d.ts +12 -0
  70. package/src/lib/layout-language/ai-layout-frame.js +58 -3
  71. package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
  72. package/src/lib/layout-language/ai-layout-listings.d.ts +13 -1
  73. package/src/lib/layout-language/ai-layout-listings.js +61 -46
  74. package/src/lib/layout-language/ai-layout-listings.js.map +1 -1
  75. package/src/lib/layout-language/ai-layout-pictures.d.ts +8 -0
  76. package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
  77. package/src/lib/layout-language/ai-layout-storefront.d.ts +82 -0
  78. package/src/lib/layout-language/ai-layout-storefront.js +223 -0
  79. package/src/lib/layout-language/ai-layout-storefront.js.map +1 -0
  80. package/src/lib/model/ai-build-job.d.ts +9 -1
  81. package/src/lib/model/ai-build-job.js +19 -5
  82. package/src/lib/model/ai-build-job.js.map +1 -1
  83. package/src/lib/model/ai-build-progress.d.ts +2 -2
  84. package/src/lib/model/ai-build-progress.js +6 -4
  85. package/src/lib/model/ai-build-progress.js.map +1 -1
  86. package/src/lib/model/ai-credit-estimate.d.ts +69 -2
  87. package/src/lib/model/ai-credit-estimate.js +91 -3
  88. package/src/lib/model/ai-credit-estimate.js.map +1 -1
  89. package/src/lib/model/ai-job-cancel-copy.d.ts +44 -0
  90. package/src/lib/model/ai-job-cancel-copy.js +53 -0
  91. package/src/lib/model/ai-job-cancel-copy.js.map +1 -0
  92. package/src/lib/model/ai-job-failure-copy.d.ts +4 -1
  93. package/src/lib/model/ai-job-failure-copy.js +8 -3
  94. package/src/lib/model/ai-job-failure-copy.js.map +1 -1
  95. package/src/lib/model/ai-jobs.types.d.ts +20 -0
  96. package/src/lib/model/ai-jobs.types.js.map +1 -1
  97. package/src/lib/model/ai-site-build-progress.js +7 -4
  98. package/src/lib/model/ai-site-build-progress.js.map +1 -1
  99. package/src/lib/model/ai-site-job.d.ts +19 -2
  100. package/src/lib/model/ai-site-job.js +29 -8
  101. package/src/lib/model/ai-site-job.js.map +1 -1
  102. package/src/lib/model/ai-site-kinds.d.ts +4 -1
  103. package/src/lib/model/ai-site-kinds.js +34 -6
  104. package/src/lib/model/ai-site-kinds.js.map +1 -1
  105. package/src/lib/runtime/ai-doctrine-validators.d.ts +37 -1
  106. package/src/lib/runtime/ai-doctrine-validators.js +151 -6
  107. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
  108. package/src/lib/runtime/ai-doctrine.js +4 -3
  109. package/src/lib/runtime/ai-doctrine.js.map +1 -1
  110. package/src/lib/runtime/ai-palette.generated.js +53 -7
  111. package/src/lib/runtime/ai-palette.generated.js.map +1 -1
  112. package/src/lib/server/ai-jobs-cancel.d.ts +13 -5
  113. package/src/lib/server/ai-jobs-cancel.js +27 -9
  114. package/src/lib/server/ai-jobs-cancel.js.map +1 -1
  115. package/src/lib/server/ai-jobs-gate.d.ts +12 -2
  116. package/src/lib/server/ai-jobs-gate.js +20 -9
  117. package/src/lib/server/ai-jobs-gate.js.map +1 -1
  118. package/src/lib/usage/ai-usage-meter.d.ts +2 -1
  119. package/src/lib/usage/ai-usage-meter.js +17 -1
  120. package/src/lib/usage/ai-usage-meter.js.map +1 -1
  121. package/src/lib/usage/ai-usage-wire.d.ts +6 -0
  122. package/src/lib/usage/ai-usage-wire.js.map +1 -1
  123. package/src/lib/usage/assist-usage.d.ts +7 -0
  124. package/src/lib/usage/assist-usage.js +14 -4
  125. package/src/lib/usage/assist-usage.js.map +1 -1
  126. package/src/lib/usage/free-ai-credits-left.d.ts +7 -0
  127. package/src/lib/usage/free-ai-credits-left.js +4 -2
  128. package/src/lib/usage/free-ai-credits-left.js.map +1 -1
@@ -16,7 +16,7 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
16
16
  * limitations under the License.
17
17
  */ import { pluginAiCapabilityArgsProblems } from "@aglyn/aglyn/plugin-manager/plugin-ai-capabilities";
18
18
  import { AI_PLAN_NEW_REF_PREFIX, isAiPlanNewRef } from "./ai-build-plan.js";
19
- import { AI_SITE_HOME_FIRST_LABEL, AI_SITE_MAX_SECTIONS, AI_SITE_PASS_CREDITS, aiCreationMeasuredCredits, aiJobPlanCreditEstimate, aiJobPlanCreditRange, aiScreenCreditRange, aiSitePlanIsHome } from "./ai-site-job.js";
19
+ import { AI_SITE_HOME_FIRST_LABEL, AI_SITE_MAX_SECTIONS, AI_SITE_PASS_CREDITS, aiCreationMeasuredCredits, aiJobPlanCreditEstimate, aiJobPlanCreditRange, aiSitePlanIsHome, aiStandaloneScreenCreditRange } from "./ai-site-job.js";
20
20
  import { AI_CREDIT_RANGE_ZERO, AI_MEASURED_PASS_CREDITS, aiCreditRangeAdd, aiCreditRangeOf, aiCreditRangeOrdered } from "./ai-credit-estimate.js";
21
21
  /**
22
22
  * What a `build` job is (AGL-3616): one request — "a few pages, a contact
@@ -40,6 +40,17 @@ import { AI_CREDIT_RANGE_ZERO, AI_MEASURED_PASS_CREDITS, aiCreditRangeAdd, aiCre
40
40
  pages: 8,
41
41
  /** A Free workspace's pages. */ freePages: 2
42
42
  };
43
+ /**
44
+ * What a Free build's plan card says when it holds as many pages as a Free
45
+ * build makes (AGL-3722): the plan is told the cap and plans the first pages
46
+ * a request asks for, so a request for three — "About us, Custom cakes and
47
+ * Catering", 2026-10-10 — came back as two with nothing saying why. `null`
48
+ * when the plan holds fewer, or on a paid workspace.
49
+ */ export function aiBuildFreePageCapNote(plan, freeTaste) {
50
+ const cap = AI_BUILD_LIMITS.freePages;
51
+ if (!freeTaste || plan.screens.length < cap) return null;
52
+ return `A Free workspace’s build makes up to ${cap} pages at a time. If you asked for more, ask Assist for the rest once this build is done.`;
53
+ }
43
54
  /** What a build creates through its `create` list; everything else beyond pages is an item. */ export const AI_BUILD_CREATE_KINDS = [
44
55
  'layout',
45
56
  'form',
@@ -266,14 +277,17 @@ import { AI_CREDIT_RANGE_ZERO, AI_MEASURED_PASS_CREDITS, aiCreditRangeAdd, aiCre
266
277
  }
267
278
  /**
268
279
  * What one unit is likely to cost, its p90 and its ceiling (AGL-3722): a page
269
- * by its sections around the measured page, a creation at what its kind
280
+ * as a page written on its own measured (a fixed cost and one per section), a creation at what its kind
270
281
  * measured, an item at the measured pass times the passes its capability
271
282
  * estimates (none for a draft another plugin writes, which asks no model).
272
283
  * The ceiling is `aiBuildUnitCreditEstimate`, unchanged.
273
284
  */ export function aiBuildUnitCreditRange(unit, ops) {
274
285
  const ceiling = aiBuildUnitCreditEstimate(unit, ops);
275
- if (unit.screen) return aiScreenCreditRange(unit.screen.sections.length);
276
- if (unit.creation) return aiCreditRangeOf(aiCreationMeasuredCredits(unit.creation.kind), ceiling);
286
+ // A build writes each page on its own, never in a site start's warm run (AGL-3722).
287
+ if (unit.screen) return aiStandaloneScreenCreditRange(unit.screen.sections.length);
288
+ if (unit.creation) return aiCreditRangeOf(aiCreationMeasuredCredits(unit.creation.kind, {
289
+ standalone: true
290
+ }), ceiling);
277
291
  const passes = Math.ceil(ceiling / AI_SITE_PASS_CREDITS);
278
292
  return aiCreditRangeOf({
279
293
  median: passes * AI_MEASURED_PASS_CREDITS.median,
@@ -341,7 +355,7 @@ import { AI_CREDIT_RANGE_ZERO, AI_MEASURED_PASS_CREDITS, aiCreditRangeAdd, aiCre
341
355
  const smaller = aiBuildFirstPagePlan(plan);
342
356
  if (!smaller) return null;
343
357
  const screen = smaller.screens[0];
344
- const label = aiSitePlanIsHome(screen) ? AI_SITE_HOME_FIRST_LABEL : `Build the page “${screen.title}” first`;
358
+ const label = aiSitePlanIsHome(screen) ? AI_SITE_HOME_FIRST_LABEL : `Build the ${screen.title} page first`;
345
359
  return _extends({
346
360
  label
347
361
  }, aiBuildCreditRange(smaller, {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/model/ai-build-job.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 pluginAiCapabilityArgsProblems,\n type PluginAiCapability,\n} from '@aglyn/aglyn/plugin-manager/plugin-ai-capabilities'\nimport {\n AI_PLAN_NEW_REF_PREFIX,\n isAiPlanNewRef,\n type AiBuildItem,\n type AiBuildPlan,\n type AiBuildPlanCreate,\n type AiBuildPlanCreateKind,\n type AiBuildPlanScreen,\n} from './ai-build-plan'\nimport type { AiJobItemLedger, AiJobItemStatus } from './ai-jobs.types'\nimport {\n AI_SITE_HOME_FIRST_LABEL,\n AI_SITE_MAX_SECTIONS,\n AI_SITE_PASS_CREDITS,\n aiCreationMeasuredCredits,\n aiJobPlanCreditEstimate,\n aiJobPlanCreditRange,\n aiScreenCreditRange,\n aiSitePlanIsHome,\n} from './ai-site-job'\nimport {\n AI_CREDIT_RANGE_ZERO,\n AI_MEASURED_PASS_CREDITS,\n aiCreditRangeAdd,\n aiCreditRangeOf,\n aiCreditRangeOrdered,\n type AiCreditRange,\n type AiCreditsSmaller,\n} from './ai-credit-estimate'\n\n/**\n * What a `build` job is (AGL-3616): one request — \"a few pages, a contact\n * form and a way to book me\" — planned as creations, pages and items, built\n * one UNIT a pass in dependency order, and settled ITEM BY ITEM.\n *\n * A build is a generalized site scaffold. Every unit is handed to what\n * already builds that kind of thing — a page to the page step, a form to the\n * form step, another plugin's resource to that plugin's draft writer — so a\n * build cannot drift from what it builds. What is new is the settlement: one\n * failed unit does not end the job. It gives back its own spend, the units\n * that depended on it are built without it (or skipped, when they cannot\n * stand without it), and the job is `done` when anything was delivered.\n *\n * This module is the build's MODEL — its units, their order, how a failure\n * travels to what depends on it, what it is estimated to cost, and the\n * ledger arithmetic — and does no I/O, so the step, the machine, the doors\n * and the console read one vocabulary.\n */\n\n/** How much one build holds: what one proposal can describe and one person can read. */\nexport const AI_BUILD_LIMITS = {\n /** Creations, pages and items together. */\n units: 16,\n pages: 8,\n /** A Free workspace's pages. */\n freePages: 2,\n} as const\n\n/** What a build creates through its `create` list; everything else beyond pages is an item. */\nexport const AI_BUILD_CREATE_KINDS: readonly AiBuildPlanCreateKind[] = ['layout', 'form', 'component', 'email']\n\n/**\n * The operations a build plans through `create` and `screens` rather than\n * `items`: an item naming one is a plan that put it in the wrong list.\n */\nexport const AI_BUILD_STRUCTURAL_OPS: readonly string[] = ['page', ...AI_BUILD_CREATE_KINDS]\n\n/** The job input a build's Assist proposal sets when the brief asked to publish. */\nexport const AI_BUILD_PUBLISH_INPUT = 'publish'\n\n/** A unit of a build: a creation, a page, or an item. */\nexport interface AiBuildUnit {\n slot: string\n /** The capability operation that builds it. */\n op: string\n label: string\n creation?: AiBuildPlanCreate\n screen?: AiBuildPlanScreen\n item?: AiBuildItem\n /** The slots it is built after, in plan order. */\n deps: string[]\n}\n\n/** The operation a creation is built as. */\nfunction creationOp(creation: AiBuildPlanCreate): string {\n return creation.kind\n}\n\n/** A plan's `new:<name>` names, each to the slot that builds it. */\nfunction namedSlots(plan: AiBuildPlan): Map<string, string> {\n const slots = new Map<string, string>()\n plan.create.forEach((creation, index) => {\n if (AI_BUILD_CREATE_KINDS.includes(creation.kind)) slots.set(creation.name.toLowerCase(), `c${index}`)\n })\n for (const item of plan.items ?? []) slots.set(item.name.toLowerCase(), item.slot)\n return slots\n}\n\n/** The name a `new:<name>` reference gives, lowercased. */\nexport function aiBuildRefName(ref: string): string {\n return ref.slice(AI_PLAN_NEW_REF_PREFIX.length).trim().toLowerCase()\n}\n\n/** Every reference a page makes: its layout, template, starting page and what its sections place. */\nexport function aiBuildScreenRefs(screen: AiBuildPlanScreen): string[] {\n return [\n screen.layout,\n screen.template,\n screen.duplicateOf,\n ...screen.sections.flatMap((section) => section.uses),\n ].filter((ref): ref is string => typeof ref === 'string' && ref.length > 0)\n}\n\n/**\n * The units a plan implies, in plan order: creations, then items, then\n * pages — the order a member reads them in, and the one a page that places\n * a creation or an item is built after anyway. `aiBuildOrder` sorts them on\n * their dependencies.\n */\nexport function aiBuildUnits(plan: AiBuildPlan): AiBuildUnit[] {\n const slots = namedSlots(plan)\n const depsOf = (refs: readonly (string | null)[], self: string): string[] => {\n const deps: string[] = []\n for (const ref of refs) {\n if (!isAiPlanNewRef(ref)) continue\n const slot = slots.get(aiBuildRefName(ref))\n if (slot && slot !== self && !deps.includes(slot)) deps.push(slot)\n }\n return deps\n }\n const units: AiBuildUnit[] = []\n plan.create.forEach((creation, index) => {\n if (!AI_BUILD_CREATE_KINDS.includes(creation.kind)) return\n const slot = `c${index}`\n units.push({ slot, op: creationOp(creation), label: creation.name, creation, deps: depsOf([creation.duplicateOf], slot) })\n })\n for (const item of plan.items ?? []) {\n units.push({ slot: item.slot, op: item.op, label: item.name, item, deps: depsOf(item.dependsOn, item.slot) })\n }\n plan.screens.forEach((screen, index) => {\n const slot = `p${index}`\n units.push({ slot, op: 'page', label: screen.title, screen, deps: depsOf(aiBuildScreenRefs(screen), slot) })\n })\n return units\n}\n\n/**\n * The units in an order that builds every dependency before what depends on\n * it, plan order otherwise; `null` when the dependencies hold a cycle.\n */\nexport function aiBuildOrder(units: readonly AiBuildUnit[]): AiBuildUnit[] | null {\n const ordered: AiBuildUnit[] = []\n const placed = new Set<string>()\n const known = new Set(units.map((unit) => unit.slot))\n while (ordered.length < units.length) {\n const next = units.find(\n (unit) => !placed.has(unit.slot) && unit.deps.every((dep) => placed.has(dep) || !known.has(dep)),\n )\n if (!next) return null\n ordered.push(next)\n placed.add(next.slot)\n }\n return ordered\n}\n\n/**\n * What is wrong with a plan's references as a build reads them: a\n * `new:<name>` an item depends on that nothing in the plan makes, and a\n * cycle. Each is a sentence the plan's one re-ask carries.\n */\nexport function aiBuildGraphProblems(plan: AiBuildPlan): string[] {\n const problems: string[] = []\n const slots = namedSlots(plan)\n for (const item of plan.items ?? []) {\n for (const ref of item.dependsOn) {\n if (!isAiPlanNewRef(ref)) continue\n if (!slots.has(aiBuildRefName(ref))) {\n problems.push(`The item \"${item.name}\" depends on ${ref}, which the plan never makes. Declare it, or take it out of dependsOn.`)\n } else if (aiBuildRefName(ref) === item.name.toLowerCase()) {\n problems.push(`The item \"${item.name}\" depends on itself. Take it out of its own dependsOn.`)\n }\n }\n }\n if (!aiBuildOrder(aiBuildUnits(plan))) {\n problems.push('The plan’s dependencies go round in a circle, so nothing in the circle can be built first. Make one of them depend on nothing.')\n }\n return problems\n}\n\n/** The operations a build may plan, as the registry and the gates left them, by op. */\nexport type AiBuildOps = ReadonlyMap<string, PluginAiCapability>\n\n/** How many pages a build may hold on this workspace. */\nexport function aiBuildPageLimit(freeTaste: boolean | null | undefined): number {\n return freeTaste ? AI_BUILD_LIMITS.freePages : AI_BUILD_LIMITS.pages\n}\n\n/**\n * Why a build cannot build a plan of this shape, in a sentence a member\n * reads; `null` when it can. Held to the plan with the one re-ask (the plan\n * step's scope), and again by the doors before a confirmed plan runs.\n * `ops` is what may be planned on this site; absent, items are not judged\n * against the registry (a console reading a kept plan).\n */\nexport function aiBuildPlanShapeRefusal(\n plan: AiBuildPlan,\n options: { freeTaste?: boolean; ops?: AiBuildOps } = {},\n): string | null {\n const units = aiBuildUnits(plan)\n if (!units.length) return 'This plan builds nothing. Describe what to build again.'\n if (units.length > AI_BUILD_LIMITS.units) {\n return `This plan builds ${units.length} things, and one build holds ${AI_BUILD_LIMITS.units}. Ask for the rest in a second request.`\n }\n const pages = aiBuildPageLimit(options.freeTaste)\n if (plan.screens.length > pages) {\n return options.freeTaste\n ? `This plan builds ${plan.screens.length} pages, and a Free workspace's build makes at most ${pages}. Paid plans can build more.`\n : `This plan builds ${plan.screens.length} pages, and one build makes at most ${pages}.`\n }\n const slugs = new Set<string>()\n for (const screen of plan.screens) {\n if (!screen.sections.length) return `The page “${screen.title}” has no sections to build.`\n if (screen.sections.length > AI_SITE_MAX_SECTIONS) {\n return `The page “${screen.title}” has ${screen.sections.length} sections, and a built page holds ${AI_SITE_MAX_SECTIONS}.`\n }\n const slug = screen.slug.trim().toLowerCase()\n if (slugs.has(slug)) return `Two pages in this plan share the address ${screen.slug}.`\n slugs.add(slug)\n }\n for (const creation of plan.create) {\n if (!AI_BUILD_CREATE_KINDS.includes(creation.kind)) {\n return `A build does not create ${creation.kind === 'theme-change' ? 'theme changes' : `${creation.kind}s`} (“${creation.name}”). Take it out of create.`\n }\n }\n const graph = aiBuildGraphProblems(plan)\n if (graph.length) return graph[0]\n const ops = options.ops\n const counts = new Map<string, number>()\n for (const unit of units) counts.set(unit.op, (counts.get(unit.op) ?? 0) + 1)\n for (const item of plan.items ?? []) {\n if (AI_BUILD_STRUCTURAL_OPS.includes(item.op)) {\n return item.op === 'page'\n ? `“${item.name}” is a page: plan it in screens, not items.`\n : `“${item.name}” is ${item.op === 'email' ? 'an' : 'a'} ${item.op}: plan it in create, not items.`\n }\n if (!ops) continue\n const capability = ops.get(item.op)\n if (!capability) return `Nothing on this site can make “${item.name}” (${item.op}). Take it out of items.`\n if (options.freeTaste && !capability.freeAllowed) {\n return `A Free workspace cannot have ${aiArticle(capability.noun)} made (“${item.name}”). Take it out of items.`\n }\n const problems = pluginAiCapabilityArgsProblems(capability.argsSchema, item.args)\n if (problems.length) return `The arguments of “${item.name}” do not read: ${problems.join('; ')}.`\n }\n if (ops) {\n for (const [op, count] of counts) {\n const capability = ops.get(op)\n if (capability && count > capability.maxPerPlan) {\n return `This plan makes ${count} of “${capability.noun}”, and one build makes at most ${capability.maxPerPlan}.`\n }\n }\n }\n return null\n}\n\n/** \"a booking service\", \"an email design\". */\nexport function aiArticle(noun: string): string {\n return `${/^[aeiou]/i.test(noun) ? 'an' : 'a'} ${noun}`\n}\n\n/** The passes one unit is estimated at: a page's sections and its listing, one for a creation. */\nfunction unitPasses(unit: AiBuildUnit): number {\n if (unit.screen) return unit.screen.sections.length + 1\n return 1\n}\n\n/**\n * About what one unit costs, in credits: a page or a creation by the passes\n * it implies at the nominal credits a pass is held against, as a site's are;\n * an item by its capability's own estimate, recorded on the plan when it was\n * kept.\n */\nexport function aiBuildUnitCreditEstimate(unit: AiBuildUnit, ops?: AiBuildOps): number {\n if (unit.item) {\n if (typeof unit.item.credits === 'number') return unit.item.credits\n const capability = ops?.get(unit.item.op)\n if (capability) return Math.max(0, Math.floor(capability.estimateCredits(unit.item.args)))\n return AI_SITE_PASS_CREDITS\n }\n return unitPasses(unit) * AI_SITE_PASS_CREDITS\n}\n\n/**\n * About what a build costs, in credits: every unit's estimate, or only the\n * units named in `slots` — what Try again shows. The ceiling a member\n * confirms; the meter charges what actually runs.\n */\nexport function aiBuildCreditEstimate(\n plan: AiBuildPlan,\n options: { ops?: AiBuildOps; slots?: ReadonlySet<string> } = {},\n): number {\n return aiBuildUnits(plan)\n .filter((unit) => !options.slots || options.slots.has(unit.slot))\n .reduce((total, unit) => total + aiBuildUnitCreditEstimate(unit, options.ops), 0)\n}\n\n/**\n * About what a job of this kind costs to build from its plan: a build's\n * units, every other planned kind as `aiJobPlanCreditEstimate` counts it.\n */\nexport function aiJobCreditEstimate(kind: string, plan: AiBuildPlan): number {\n return kind === 'build' ? aiBuildCreditEstimate(plan) : aiJobPlanCreditEstimate(kind, plan)\n}\n\n/**\n * What one unit is likely to cost, its p90 and its ceiling (AGL-3722): a page\n * by its sections around the measured page, a creation at what its kind\n * measured, an item at the measured pass times the passes its capability\n * estimates (none for a draft another plugin writes, which asks no model).\n * The ceiling is `aiBuildUnitCreditEstimate`, unchanged.\n */\nexport function aiBuildUnitCreditRange(unit: AiBuildUnit, ops?: AiBuildOps): AiCreditRange {\n const ceiling = aiBuildUnitCreditEstimate(unit, ops)\n if (unit.screen) return aiScreenCreditRange(unit.screen.sections.length)\n if (unit.creation) return aiCreditRangeOf(aiCreationMeasuredCredits(unit.creation.kind), ceiling)\n const passes = Math.ceil(ceiling / AI_SITE_PASS_CREDITS)\n return aiCreditRangeOf(\n { median: passes * AI_MEASURED_PASS_CREDITS.median, p90: passes * AI_MEASURED_PASS_CREDITS.p90 },\n ceiling,\n )\n}\n\n/**\n * What a build is likely to cost, its p90 and its ceiling (AGL-3722): every\n * unit's range, or only the units named in `slots` — what Try again runs.\n * The plan card, Try again and the Free admission all read this; the meter\n * charges what actually runs.\n */\nexport function aiBuildCreditRange(\n plan: AiBuildPlan,\n options: { ops?: AiBuildOps; slots?: ReadonlySet<string> } = {},\n): AiCreditRange {\n return aiCreditRangeOrdered(\n aiBuildUnits(plan)\n .filter((unit) => !options.slots || options.slots.has(unit.slot))\n .reduce((total, unit) => aiCreditRangeAdd(total, aiBuildUnitCreditRange(unit, options.ops)), AI_CREDIT_RANGE_ZERO),\n )\n}\n\n/** `aiJobCreditEstimate` as a range (AGL-3722). */\nexport function aiJobCreditRange(kind: string, plan: AiBuildPlan): AiCreditRange {\n return kind === 'build' ? aiBuildCreditRange(plan) : aiJobPlanCreditRange(kind, plan)\n}\n\n/**\n * A smaller first build (AGL-3722): the plan's home page — its first page\n * where it has no home — and only what that page needs, transitively: the\n * layout it is drawn in, the form and anything else its sections place.\n * Every other page, and what only they needed, waits for a later request.\n * `null` when the plan has no page, or when the smaller plan is the whole one.\n */\nexport function aiBuildFirstPagePlan<T extends AiBuildPlan>(plan: T): T | null {\n if (!plan.screens.length) return null\n const index = Math.max(0, plan.screens.findIndex(aiSitePlanIsHome))\n const units = aiBuildUnits(plan)\n const bySlot = new Map(units.map((unit) => [unit.slot, unit]))\n const keep = new Set<string>()\n const queue = [`p${index}`]\n while (queue.length) {\n const slot = queue.shift() as string\n if (keep.has(slot)) continue\n keep.add(slot)\n for (const dep of bySlot.get(slot)?.deps ?? []) queue.push(dep)\n }\n if (keep.size === units.length) return null\n const screen = plan.screens[index]\n const create = plan.create.filter((creation, at) => !AI_BUILD_CREATE_KINDS.includes(creation.kind) || keep.has(`c${at}`))\n const items = (plan.items ?? []).filter((item) => keep.has(item.slot))\n const kept = new Set([screen.slug, ...create.map((entry) => `${AI_PLAN_NEW_REF_PREFIX}${entry.name}`)])\n return {\n ...plan,\n create,\n screens: [screen],\n ...(plan.items ? { items } : {}),\n ...(plan.embeds ? { embeds: plan.embeds.filter((embed) => kept.has(embed.where)) } : {}),\n }\n}\n\n/** The smaller first build a build that does not fit is offered (AGL-3722), with its range; `null` when there is none. */\nexport function aiBuildSmaller(plan: AiBuildPlan, ops?: AiBuildOps): AiCreditsSmaller | null {\n const smaller = aiBuildFirstPagePlan(plan)\n if (!smaller) return null\n const screen = smaller.screens[0]\n const label = aiSitePlanIsHome(screen) ? AI_SITE_HOME_FIRST_LABEL : `Build the page “${screen.title}” first`\n return { label, ...aiBuildCreditRange(smaller, { ops }) }\n}\n\n/** A fresh ledger: one pending row per unit, first attempt. */\nexport function aiBuildInitialLedger(units: readonly AiBuildUnit[]): AiJobItemLedger[] {\n return units.map((unit) => ({\n slot: unit.slot,\n op: unit.op,\n label: unit.label,\n status: 'pending',\n attempt: 1,\n creditsSpent: 0,\n attemptCredits: 0,\n creditsRefunded: 0,\n failure: null,\n outputs: [],\n }))\n}\n\nconst OPEN: readonly AiJobItemStatus[] = ['pending', 'running']\n\n/** Whether an item is still to be built. */\nexport function aiBuildItemOpen(row: Pick<AiJobItemLedger, 'status'>): boolean {\n return OPEN.includes(row.status)\n}\n\n/** Whether an item delivered: built as planned, or built without something that failed. */\nexport function aiBuildItemDelivered(row: Pick<AiJobItemLedger, 'status'>): boolean {\n return row.status === 'succeeded' || row.status === 'degraded'\n}\n\n/**\n * The next unit to build: the first in build order whose row is still open.\n * Its dependencies come before it, so by then each is settled one way or the\n * other. `null` when nothing is left.\n */\nexport function aiBuildNextUnit(\n ordered: readonly AiBuildUnit[],\n ledger: readonly AiJobItemLedger[],\n): AiBuildUnit | null {\n const rows = new Map(ledger.map((row) => [row.slot, row]))\n return ordered.find((unit) => {\n const row = rows.get(unit.slot)\n return !row || aiBuildItemOpen(row)\n }) ?? null\n}\n\n/** How a unit is built given what its dependencies came to. */\nexport interface AiBuildDegradation {\n /** The unit is not built at all, with the sentence why; nothing is spent. */\n skip: string | null\n /** The failed dependencies that change how it is built. */\n degradedBy: string[]\n /** What the person reads about the change; one per failed dependency. */\n notes: string[]\n /** `new:<name>` references (lowercased names) to leave out. */\n dropped: Set<string>\n /** Brief lines for the unit's own job: what to leave out, and what to place. */\n briefLines: string[]\n}\n\n/**\n * How a unit is built when some of what it depends on failed (AGL-3616).\n *\n * A PAGE is always built: a failed layout falls back to the site's own, a\n * failed form or component is left out of its section, and a failed item a\n * section places (a booking service) takes its block out of the page — each\n * with a note. Any OTHER unit whose dependency failed is skipped when that\n * dependency's capability says `omit` (a campaign whose email design failed\n * has nothing to send), and built without it when it says `fallback`.\n */\nexport function aiBuildDegradation(\n unit: AiBuildUnit,\n context: {\n units: readonly AiBuildUnit[]\n ledger: readonly AiJobItemLedger[]\n ops?: AiBuildOps\n },\n): AiBuildDegradation {\n const rows = new Map(context.ledger.map((row) => [row.slot, row]))\n const bySlot = new Map(context.units.map((one) => [one.slot, one]))\n const result: AiBuildDegradation = { skip: null, degradedBy: [], notes: [], dropped: new Set(), briefLines: [] }\n for (const slot of unit.deps) {\n const dep = bySlot.get(slot)\n const row = rows.get(slot)\n if (!dep || !row || aiBuildItemDelivered(row)) continue\n const noun = dep.creation\n ? aiBuildCreationNoun(dep.creation.kind)\n : (context.ops?.get(dep.op)?.noun ?? dep.op)\n const capability = dep.item ? context.ops?.get(dep.op) : undefined\n const degrade = dep.item?.degrade ?? capability?.degrade ?? (dep.creation?.kind === 'layout' ? 'fallback' : 'omit')\n if (!unit.screen && degrade === 'omit') {\n result.skip = `Not built: the ${noun} “${dep.label}” it needs could not be created.`\n result.degradedBy.push(slot)\n return result\n }\n result.degradedBy.push(slot)\n result.dropped.add(dep.label.toLowerCase())\n if (dep.creation?.kind === 'layout') {\n result.notes.push(`Built inside the site’s own layout: the layout “${dep.label}” could not be created.`)\n continue\n }\n if (unit.screen) {\n const section = unit.screen.sections.find((one) =>\n one.uses.some((ref) => isAiPlanNewRef(ref) && aiBuildRefName(ref) === dep.label.toLowerCase()),\n )\n const blocks = capability?.pageBlocks?.length ? ` the ${capability.pageBlocks.join(' or ')} block` : ''\n result.notes.push(\n `Built without${blocks || ` the ${noun}`}: the ${noun} “${dep.label}” could not be created.`,\n )\n result.briefLines.push(\n `${section ? `Build the “${section.name}” section` : 'Build the page'} without the ${noun} “${dep.label}”${blocks ? ` and without${blocks}` : ''}: it could not be created.`,\n )\n } else {\n result.notes.push(`Built without the ${noun} “${dep.label}”: it could not be created.`)\n }\n }\n return result\n}\n\n/** What each creation is called in a note. */\nexport function aiBuildCreationNoun(kind: AiBuildPlanCreateKind): string {\n return kind === 'email' ? 'email design' : kind === 'theme-change' ? 'theme change' : kind\n}\n\n/**\n * The brief lines a page is told about the items its sections place and\n * that were built: the block to put there, in the owner's words.\n */\nexport function aiBuildPlacedItemLines(\n unit: AiBuildUnit,\n context: { units: readonly AiBuildUnit[]; ledger: readonly AiJobItemLedger[]; ops?: AiBuildOps },\n): string[] {\n if (!unit.screen) return []\n const rows = new Map(context.ledger.map((row) => [row.slot, row]))\n const lines: string[] = []\n for (const section of unit.screen.sections) {\n for (const ref of section.uses) {\n if (!isAiPlanNewRef(ref)) continue\n const dep = context.units.find((one) => one.item && one.item.name.toLowerCase() === aiBuildRefName(ref))\n if (!dep?.item) continue\n const row = rows.get(dep.slot)\n if (!row || !aiBuildItemDelivered(row)) continue\n const capability = context.ops?.get(dep.op)\n const blocks = capability?.pageBlocks ?? []\n if (!blocks.length) continue\n lines.push(\n `In the “${section.name}” section, place the ${blocks.join(' or ')} block for the ${capability?.noun ?? dep.op} “${dep.label}”.`,\n )\n }\n }\n return lines\n}\n\n/** What a build came to: whether anything was delivered, and whether anything is left. */\nexport function aiBuildSettlement(ledger: readonly AiJobItemLedger[]): {\n delivered: boolean\n open: boolean\n failed: number\n} {\n return {\n delivered: ledger.some(aiBuildItemDelivered),\n open: ledger.some(aiBuildItemOpen),\n failed: ledger.filter((row) => row.status === 'failed').length,\n }\n}\n\n/**\n * The ledger Try again runs (AGL-3616): every failed item back to `pending`\n * on its next attempt, with the items left unbuilt because of it — skipped,\n * or degraded with no draft — and every item the build never reached. An\n * item that succeeded is never run again, and a degraded page that has its\n * draft keeps it, with a note that the page needs an edit. `retried` names\n * the slots that will run, which is what the estimate is shown for.\n */\nexport function aiBuildRetryLedger(\n ledger: readonly AiJobItemLedger[],\n units: readonly AiBuildUnit[],\n): { ledger: AiJobItemLedger[]; retried: string[] } {\n const failed = new Set(ledger.filter((row) => row.status === 'failed').map((row) => row.slot))\n const dependents = new Map<string, string[]>()\n for (const unit of units) {\n for (const dep of unit.deps) dependents.set(dep, [...(dependents.get(dep) ?? []), unit.slot])\n }\n // Everything downstream of a failed item, transitively.\n const downstream = new Set<string>()\n const queue = [...failed]\n while (queue.length) {\n const slot = queue.shift() as string\n for (const next of dependents.get(slot) ?? []) {\n if (downstream.has(next)) continue\n downstream.add(next)\n queue.push(next)\n }\n }\n const retried: string[] = []\n const next = ledger.map((row): AiJobItemLedger => {\n const again =\n row.status === 'failed' ||\n (row.status === 'skipped' && (downstream.has(row.slot) || !(row.degradedBy ?? []).length)) ||\n (row.status === 'degraded' && downstream.has(row.slot) && !row.outputs.length)\n if (again) {\n retried.push(row.slot)\n return {\n ...row,\n status: 'pending',\n attempt: row.attempt + 1,\n attemptCredits: 0,\n failure: null,\n note: null,\n degradedBy: [],\n settledAt: null,\n }\n }\n if (row.status === 'degraded' && downstream.has(row.slot) && row.outputs.length) {\n return {\n ...row,\n note: `${row.note ? `${row.note} ` : ''}It keeps its draft: once the rest is built, edit this page to add what it is missing.`,\n }\n }\n return row\n })\n return { ledger: next, retried }\n}\n\n/**\n * Units read back off a ledger alone (AGL-3616), for a job whose units are\n * not a build plan's — a site scaffold's: each row as its unit, and every\n * page built after the layouts and forms the ledger holds.\n */\nexport function aiLedgerUnits(ledger: readonly AiJobItemLedger[]): AiBuildUnit[] {\n const creations = ledger.filter((row) => row.op === 'layout' || row.op === 'form').map((row) => row.slot)\n return ledger.map((row) => ({\n slot: row.slot,\n op: row.op,\n label: row.label,\n deps: row.op === 'page' ? creations : [],\n }))\n}\n"],"names":["pluginAiCapabilityArgsProblems","AI_PLAN_NEW_REF_PREFIX","isAiPlanNewRef","AI_SITE_HOME_FIRST_LABEL","AI_SITE_MAX_SECTIONS","AI_SITE_PASS_CREDITS","aiCreationMeasuredCredits","aiJobPlanCreditEstimate","aiJobPlanCreditRange","aiScreenCreditRange","aiSitePlanIsHome","AI_CREDIT_RANGE_ZERO","AI_MEASURED_PASS_CREDITS","aiCreditRangeAdd","aiCreditRangeOf","aiCreditRangeOrdered","AI_BUILD_LIMITS","units","pages","freePages","AI_BUILD_CREATE_KINDS","AI_BUILD_STRUCTURAL_OPS","AI_BUILD_PUBLISH_INPUT","creationOp","creation","kind","namedSlots","plan","slots","Map","create","forEach","index","includes","set","name","toLowerCase","item","items","slot","aiBuildRefName","ref","slice","length","trim","aiBuildScreenRefs","screen","layout","template","duplicateOf","sections","flatMap","section","uses","filter","aiBuildUnits","depsOf","refs","self","deps","get","push","op","label","dependsOn","screens","title","aiBuildOrder","ordered","placed","Set","known","map","unit","next","find","has","every","dep","add","aiBuildGraphProblems","problems","aiBuildPageLimit","freeTaste","aiBuildPlanShapeRefusal","options","counts","slugs","slug","graph","ops","capability","freeAllowed","aiArticle","noun","argsSchema","args","join","count","maxPerPlan","test","unitPasses","aiBuildUnitCreditEstimate","credits","Math","max","floor","estimateCredits","aiBuildCreditEstimate","reduce","total","aiJobCreditEstimate","aiBuildUnitCreditRange","ceiling","passes","ceil","median","p90","aiBuildCreditRange","aiJobCreditRange","aiBuildFirstPagePlan","findIndex","bySlot","keep","queue","shift","size","at","kept","entry","embeds","embed","where","aiBuildSmaller","smaller","aiBuildInitialLedger","status","attempt","creditsSpent","attemptCredits","creditsRefunded","failure","outputs","OPEN","aiBuildItemOpen","row","aiBuildItemDelivered","aiBuildNextUnit","ledger","rows","aiBuildDegradation","context","one","result","skip","degradedBy","notes","dropped","briefLines","aiBuildCreationNoun","undefined","degrade","some","blocks","pageBlocks","aiBuildPlacedItemLines","lines","aiBuildSettlement","delivered","open","failed","aiBuildRetryLedger","dependents","downstream","retried","again","note","settledAt","aiLedgerUnits","creations"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/model/ai-build-job.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 pluginAiCapabilityArgsProblems,\n type PluginAiCapability,\n} from '@aglyn/aglyn/plugin-manager/plugin-ai-capabilities'\nimport {\n AI_PLAN_NEW_REF_PREFIX,\n isAiPlanNewRef,\n type AiBuildItem,\n type AiBuildPlan,\n type AiBuildPlanCreate,\n type AiBuildPlanCreateKind,\n type AiBuildPlanScreen,\n} from './ai-build-plan'\nimport type { AiJobItemLedger, AiJobItemStatus } from './ai-jobs.types'\nimport {\n AI_SITE_HOME_FIRST_LABEL,\n AI_SITE_MAX_SECTIONS,\n AI_SITE_PASS_CREDITS,\n aiCreationMeasuredCredits,\n aiJobPlanCreditEstimate,\n aiJobPlanCreditRange,\n aiSitePlanIsHome,\n aiStandaloneScreenCreditRange,\n} from './ai-site-job'\nimport {\n AI_CREDIT_RANGE_ZERO,\n AI_MEASURED_PASS_CREDITS,\n aiCreditRangeAdd,\n aiCreditRangeOf,\n aiCreditRangeOrdered,\n type AiCreditRange,\n type AiCreditsSmaller,\n} from './ai-credit-estimate'\n\n/**\n * What a `build` job is (AGL-3616): one request — \"a few pages, a contact\n * form and a way to book me\" — planned as creations, pages and items, built\n * one UNIT a pass in dependency order, and settled ITEM BY ITEM.\n *\n * A build is a generalized site scaffold. Every unit is handed to what\n * already builds that kind of thing — a page to the page step, a form to the\n * form step, another plugin's resource to that plugin's draft writer — so a\n * build cannot drift from what it builds. What is new is the settlement: one\n * failed unit does not end the job. It gives back its own spend, the units\n * that depended on it are built without it (or skipped, when they cannot\n * stand without it), and the job is `done` when anything was delivered.\n *\n * This module is the build's MODEL — its units, their order, how a failure\n * travels to what depends on it, what it is estimated to cost, and the\n * ledger arithmetic — and does no I/O, so the step, the machine, the doors\n * and the console read one vocabulary.\n */\n\n/** How much one build holds: what one proposal can describe and one person can read. */\nexport const AI_BUILD_LIMITS = {\n /** Creations, pages and items together. */\n units: 16,\n pages: 8,\n /** A Free workspace's pages. */\n freePages: 2,\n} as const\n\n/**\n * What a Free build's plan card says when it holds as many pages as a Free\n * build makes (AGL-3722): the plan is told the cap and plans the first pages\n * a request asks for, so a request for three — \"About us, Custom cakes and\n * Catering\", 2026-10-10 — came back as two with nothing saying why. `null`\n * when the plan holds fewer, or on a paid workspace.\n */\nexport function aiBuildFreePageCapNote(plan: Pick<AiBuildPlan, 'screens'>, freeTaste: boolean): string | null {\n const cap = AI_BUILD_LIMITS.freePages\n if (!freeTaste || plan.screens.length < cap) return null\n return `A Free workspace’s build makes up to ${cap} pages at a time. If you asked for more, ask Assist for the rest once this build is done.`\n}\n\n/** What a build creates through its `create` list; everything else beyond pages is an item. */\nexport const AI_BUILD_CREATE_KINDS: readonly AiBuildPlanCreateKind[] = ['layout', 'form', 'component', 'email']\n\n/**\n * The operations a build plans through `create` and `screens` rather than\n * `items`: an item naming one is a plan that put it in the wrong list.\n */\nexport const AI_BUILD_STRUCTURAL_OPS: readonly string[] = ['page', ...AI_BUILD_CREATE_KINDS]\n\n/** The job input a build's Assist proposal sets when the brief asked to publish. */\nexport const AI_BUILD_PUBLISH_INPUT = 'publish'\n\n/** A unit of a build: a creation, a page, or an item. */\nexport interface AiBuildUnit {\n slot: string\n /** The capability operation that builds it. */\n op: string\n label: string\n creation?: AiBuildPlanCreate\n screen?: AiBuildPlanScreen\n item?: AiBuildItem\n /** The slots it is built after, in plan order. */\n deps: string[]\n}\n\n/** The operation a creation is built as. */\nfunction creationOp(creation: AiBuildPlanCreate): string {\n return creation.kind\n}\n\n/** A plan's `new:<name>` names, each to the slot that builds it. */\nfunction namedSlots(plan: AiBuildPlan): Map<string, string> {\n const slots = new Map<string, string>()\n plan.create.forEach((creation, index) => {\n if (AI_BUILD_CREATE_KINDS.includes(creation.kind)) slots.set(creation.name.toLowerCase(), `c${index}`)\n })\n for (const item of plan.items ?? []) slots.set(item.name.toLowerCase(), item.slot)\n return slots\n}\n\n/** The name a `new:<name>` reference gives, lowercased. */\nexport function aiBuildRefName(ref: string): string {\n return ref.slice(AI_PLAN_NEW_REF_PREFIX.length).trim().toLowerCase()\n}\n\n/** Every reference a page makes: its layout, template, starting page and what its sections place. */\nexport function aiBuildScreenRefs(screen: AiBuildPlanScreen): string[] {\n return [\n screen.layout,\n screen.template,\n screen.duplicateOf,\n ...screen.sections.flatMap((section) => section.uses),\n ].filter((ref): ref is string => typeof ref === 'string' && ref.length > 0)\n}\n\n/**\n * The units a plan implies, in plan order: creations, then items, then\n * pages — the order a member reads them in, and the one a page that places\n * a creation or an item is built after anyway. `aiBuildOrder` sorts them on\n * their dependencies.\n */\nexport function aiBuildUnits(plan: AiBuildPlan): AiBuildUnit[] {\n const slots = namedSlots(plan)\n const depsOf = (refs: readonly (string | null)[], self: string): string[] => {\n const deps: string[] = []\n for (const ref of refs) {\n if (!isAiPlanNewRef(ref)) continue\n const slot = slots.get(aiBuildRefName(ref))\n if (slot && slot !== self && !deps.includes(slot)) deps.push(slot)\n }\n return deps\n }\n const units: AiBuildUnit[] = []\n plan.create.forEach((creation, index) => {\n if (!AI_BUILD_CREATE_KINDS.includes(creation.kind)) return\n const slot = `c${index}`\n units.push({ slot, op: creationOp(creation), label: creation.name, creation, deps: depsOf([creation.duplicateOf], slot) })\n })\n for (const item of plan.items ?? []) {\n units.push({ slot: item.slot, op: item.op, label: item.name, item, deps: depsOf(item.dependsOn, item.slot) })\n }\n plan.screens.forEach((screen, index) => {\n const slot = `p${index}`\n units.push({ slot, op: 'page', label: screen.title, screen, deps: depsOf(aiBuildScreenRefs(screen), slot) })\n })\n return units\n}\n\n/**\n * The units in an order that builds every dependency before what depends on\n * it, plan order otherwise; `null` when the dependencies hold a cycle.\n */\nexport function aiBuildOrder(units: readonly AiBuildUnit[]): AiBuildUnit[] | null {\n const ordered: AiBuildUnit[] = []\n const placed = new Set<string>()\n const known = new Set(units.map((unit) => unit.slot))\n while (ordered.length < units.length) {\n const next = units.find(\n (unit) => !placed.has(unit.slot) && unit.deps.every((dep) => placed.has(dep) || !known.has(dep)),\n )\n if (!next) return null\n ordered.push(next)\n placed.add(next.slot)\n }\n return ordered\n}\n\n/**\n * What is wrong with a plan's references as a build reads them: a\n * `new:<name>` an item depends on that nothing in the plan makes, and a\n * cycle. Each is a sentence the plan's one re-ask carries.\n */\nexport function aiBuildGraphProblems(plan: AiBuildPlan): string[] {\n const problems: string[] = []\n const slots = namedSlots(plan)\n for (const item of plan.items ?? []) {\n for (const ref of item.dependsOn) {\n if (!isAiPlanNewRef(ref)) continue\n if (!slots.has(aiBuildRefName(ref))) {\n problems.push(`The item \"${item.name}\" depends on ${ref}, which the plan never makes. Declare it, or take it out of dependsOn.`)\n } else if (aiBuildRefName(ref) === item.name.toLowerCase()) {\n problems.push(`The item \"${item.name}\" depends on itself. Take it out of its own dependsOn.`)\n }\n }\n }\n if (!aiBuildOrder(aiBuildUnits(plan))) {\n problems.push('The plan’s dependencies go round in a circle, so nothing in the circle can be built first. Make one of them depend on nothing.')\n }\n return problems\n}\n\n/** The operations a build may plan, as the registry and the gates left them, by op. */\nexport type AiBuildOps = ReadonlyMap<string, PluginAiCapability>\n\n/** How many pages a build may hold on this workspace. */\nexport function aiBuildPageLimit(freeTaste: boolean | null | undefined): number {\n return freeTaste ? AI_BUILD_LIMITS.freePages : AI_BUILD_LIMITS.pages\n}\n\n/**\n * Why a build cannot build a plan of this shape, in a sentence a member\n * reads; `null` when it can. Held to the plan with the one re-ask (the plan\n * step's scope), and again by the doors before a confirmed plan runs.\n * `ops` is what may be planned on this site; absent, items are not judged\n * against the registry (a console reading a kept plan).\n */\nexport function aiBuildPlanShapeRefusal(\n plan: AiBuildPlan,\n options: { freeTaste?: boolean; ops?: AiBuildOps } = {},\n): string | null {\n const units = aiBuildUnits(plan)\n if (!units.length) return 'This plan builds nothing. Describe what to build again.'\n if (units.length > AI_BUILD_LIMITS.units) {\n return `This plan builds ${units.length} things, and one build holds ${AI_BUILD_LIMITS.units}. Ask for the rest in a second request.`\n }\n const pages = aiBuildPageLimit(options.freeTaste)\n if (plan.screens.length > pages) {\n return options.freeTaste\n ? `This plan builds ${plan.screens.length} pages, and a Free workspace's build makes at most ${pages}. Paid plans can build more.`\n : `This plan builds ${plan.screens.length} pages, and one build makes at most ${pages}.`\n }\n const slugs = new Set<string>()\n for (const screen of plan.screens) {\n if (!screen.sections.length) return `The page “${screen.title}” has no sections to build.`\n if (screen.sections.length > AI_SITE_MAX_SECTIONS) {\n return `The page “${screen.title}” has ${screen.sections.length} sections, and a built page holds ${AI_SITE_MAX_SECTIONS}.`\n }\n const slug = screen.slug.trim().toLowerCase()\n if (slugs.has(slug)) return `Two pages in this plan share the address ${screen.slug}.`\n slugs.add(slug)\n }\n for (const creation of plan.create) {\n if (!AI_BUILD_CREATE_KINDS.includes(creation.kind)) {\n return `A build does not create ${creation.kind === 'theme-change' ? 'theme changes' : `${creation.kind}s`} (“${creation.name}”). Take it out of create.`\n }\n }\n const graph = aiBuildGraphProblems(plan)\n if (graph.length) return graph[0]\n const ops = options.ops\n const counts = new Map<string, number>()\n for (const unit of units) counts.set(unit.op, (counts.get(unit.op) ?? 0) + 1)\n for (const item of plan.items ?? []) {\n if (AI_BUILD_STRUCTURAL_OPS.includes(item.op)) {\n return item.op === 'page'\n ? `“${item.name}” is a page: plan it in screens, not items.`\n : `“${item.name}” is ${item.op === 'email' ? 'an' : 'a'} ${item.op}: plan it in create, not items.`\n }\n if (!ops) continue\n const capability = ops.get(item.op)\n if (!capability) return `Nothing on this site can make “${item.name}” (${item.op}). Take it out of items.`\n if (options.freeTaste && !capability.freeAllowed) {\n return `A Free workspace cannot have ${aiArticle(capability.noun)} made (“${item.name}”). Take it out of items.`\n }\n const problems = pluginAiCapabilityArgsProblems(capability.argsSchema, item.args)\n if (problems.length) return `The arguments of “${item.name}” do not read: ${problems.join('; ')}.`\n }\n if (ops) {\n for (const [op, count] of counts) {\n const capability = ops.get(op)\n if (capability && count > capability.maxPerPlan) {\n return `This plan makes ${count} of “${capability.noun}”, and one build makes at most ${capability.maxPerPlan}.`\n }\n }\n }\n return null\n}\n\n/** \"a booking service\", \"an email design\". */\nexport function aiArticle(noun: string): string {\n return `${/^[aeiou]/i.test(noun) ? 'an' : 'a'} ${noun}`\n}\n\n/** The passes one unit is estimated at: a page's sections and its listing, one for a creation. */\nfunction unitPasses(unit: AiBuildUnit): number {\n if (unit.screen) return unit.screen.sections.length + 1\n return 1\n}\n\n/**\n * About what one unit costs, in credits: a page or a creation by the passes\n * it implies at the nominal credits a pass is held against, as a site's are;\n * an item by its capability's own estimate, recorded on the plan when it was\n * kept.\n */\nexport function aiBuildUnitCreditEstimate(unit: AiBuildUnit, ops?: AiBuildOps): number {\n if (unit.item) {\n if (typeof unit.item.credits === 'number') return unit.item.credits\n const capability = ops?.get(unit.item.op)\n if (capability) return Math.max(0, Math.floor(capability.estimateCredits(unit.item.args)))\n return AI_SITE_PASS_CREDITS\n }\n return unitPasses(unit) * AI_SITE_PASS_CREDITS\n}\n\n/**\n * About what a build costs, in credits: every unit's estimate, or only the\n * units named in `slots` — what Try again shows. The ceiling a member\n * confirms; the meter charges what actually runs.\n */\nexport function aiBuildCreditEstimate(\n plan: AiBuildPlan,\n options: { ops?: AiBuildOps; slots?: ReadonlySet<string> } = {},\n): number {\n return aiBuildUnits(plan)\n .filter((unit) => !options.slots || options.slots.has(unit.slot))\n .reduce((total, unit) => total + aiBuildUnitCreditEstimate(unit, options.ops), 0)\n}\n\n/**\n * About what a job of this kind costs to build from its plan: a build's\n * units, every other planned kind as `aiJobPlanCreditEstimate` counts it.\n */\nexport function aiJobCreditEstimate(kind: string, plan: AiBuildPlan): number {\n return kind === 'build' ? aiBuildCreditEstimate(plan) : aiJobPlanCreditEstimate(kind, plan)\n}\n\n/**\n * What one unit is likely to cost, its p90 and its ceiling (AGL-3722): a page\n * as a page written on its own measured (a fixed cost and one per section), a creation at what its kind\n * measured, an item at the measured pass times the passes its capability\n * estimates (none for a draft another plugin writes, which asks no model).\n * The ceiling is `aiBuildUnitCreditEstimate`, unchanged.\n */\nexport function aiBuildUnitCreditRange(unit: AiBuildUnit, ops?: AiBuildOps): AiCreditRange {\n const ceiling = aiBuildUnitCreditEstimate(unit, ops)\n // A build writes each page on its own, never in a site start's warm run (AGL-3722).\n if (unit.screen) return aiStandaloneScreenCreditRange(unit.screen.sections.length)\n if (unit.creation) return aiCreditRangeOf(aiCreationMeasuredCredits(unit.creation.kind, { standalone: true }), ceiling)\n const passes = Math.ceil(ceiling / AI_SITE_PASS_CREDITS)\n return aiCreditRangeOf(\n { median: passes * AI_MEASURED_PASS_CREDITS.median, p90: passes * AI_MEASURED_PASS_CREDITS.p90 },\n ceiling,\n )\n}\n\n/**\n * What a build is likely to cost, its p90 and its ceiling (AGL-3722): every\n * unit's range, or only the units named in `slots` — what Try again runs.\n * The plan card, Try again and the Free admission all read this; the meter\n * charges what actually runs.\n */\nexport function aiBuildCreditRange(\n plan: AiBuildPlan,\n options: { ops?: AiBuildOps; slots?: ReadonlySet<string> } = {},\n): AiCreditRange {\n return aiCreditRangeOrdered(\n aiBuildUnits(plan)\n .filter((unit) => !options.slots || options.slots.has(unit.slot))\n .reduce((total, unit) => aiCreditRangeAdd(total, aiBuildUnitCreditRange(unit, options.ops)), AI_CREDIT_RANGE_ZERO),\n )\n}\n\n/** `aiJobCreditEstimate` as a range (AGL-3722). */\nexport function aiJobCreditRange(kind: string, plan: AiBuildPlan): AiCreditRange {\n return kind === 'build' ? aiBuildCreditRange(plan) : aiJobPlanCreditRange(kind, plan)\n}\n\n/**\n * A smaller first build (AGL-3722): the plan's home page — its first page\n * where it has no home — and only what that page needs, transitively: the\n * layout it is drawn in, the form and anything else its sections place.\n * Every other page, and what only they needed, waits for a later request.\n * `null` when the plan has no page, or when the smaller plan is the whole one.\n */\nexport function aiBuildFirstPagePlan<T extends AiBuildPlan>(plan: T): T | null {\n if (!plan.screens.length) return null\n const index = Math.max(0, plan.screens.findIndex(aiSitePlanIsHome))\n const units = aiBuildUnits(plan)\n const bySlot = new Map(units.map((unit) => [unit.slot, unit]))\n const keep = new Set<string>()\n const queue = [`p${index}`]\n while (queue.length) {\n const slot = queue.shift() as string\n if (keep.has(slot)) continue\n keep.add(slot)\n for (const dep of bySlot.get(slot)?.deps ?? []) queue.push(dep)\n }\n if (keep.size === units.length) return null\n const screen = plan.screens[index]\n const create = plan.create.filter((creation, at) => !AI_BUILD_CREATE_KINDS.includes(creation.kind) || keep.has(`c${at}`))\n const items = (plan.items ?? []).filter((item) => keep.has(item.slot))\n const kept = new Set([screen.slug, ...create.map((entry) => `${AI_PLAN_NEW_REF_PREFIX}${entry.name}`)])\n return {\n ...plan,\n create,\n screens: [screen],\n ...(plan.items ? { items } : {}),\n ...(plan.embeds ? { embeds: plan.embeds.filter((embed) => kept.has(embed.where)) } : {}),\n }\n}\n\n/** The smaller first build a build that does not fit is offered (AGL-3722), with its range; `null` when there is none. */\nexport function aiBuildSmaller(plan: AiBuildPlan, ops?: AiBuildOps): AiCreditsSmaller | null {\n const smaller = aiBuildFirstPagePlan(plan)\n if (!smaller) return null\n const screen = smaller.screens[0]\n const label = aiSitePlanIsHome(screen) ? AI_SITE_HOME_FIRST_LABEL : `Build the ${screen.title} page first`\n return { label, ...aiBuildCreditRange(smaller, { ops }) }\n}\n\n/** A fresh ledger: one pending row per unit, first attempt. */\nexport function aiBuildInitialLedger(units: readonly AiBuildUnit[]): AiJobItemLedger[] {\n return units.map((unit) => ({\n slot: unit.slot,\n op: unit.op,\n label: unit.label,\n status: 'pending',\n attempt: 1,\n creditsSpent: 0,\n attemptCredits: 0,\n creditsRefunded: 0,\n failure: null,\n outputs: [],\n }))\n}\n\nconst OPEN: readonly AiJobItemStatus[] = ['pending', 'running']\n\n/** Whether an item is still to be built. */\nexport function aiBuildItemOpen(row: Pick<AiJobItemLedger, 'status'>): boolean {\n return OPEN.includes(row.status)\n}\n\n/** Whether an item delivered: built as planned, or built without something that failed. */\nexport function aiBuildItemDelivered(row: Pick<AiJobItemLedger, 'status'>): boolean {\n return row.status === 'succeeded' || row.status === 'degraded'\n}\n\n/**\n * The next unit to build: the first in build order whose row is still open.\n * Its dependencies come before it, so by then each is settled one way or the\n * other. `null` when nothing is left.\n */\nexport function aiBuildNextUnit(\n ordered: readonly AiBuildUnit[],\n ledger: readonly AiJobItemLedger[],\n): AiBuildUnit | null {\n const rows = new Map(ledger.map((row) => [row.slot, row]))\n return ordered.find((unit) => {\n const row = rows.get(unit.slot)\n return !row || aiBuildItemOpen(row)\n }) ?? null\n}\n\n/** How a unit is built given what its dependencies came to. */\nexport interface AiBuildDegradation {\n /** The unit is not built at all, with the sentence why; nothing is spent. */\n skip: string | null\n /** The failed dependencies that change how it is built. */\n degradedBy: string[]\n /** What the person reads about the change; one per failed dependency. */\n notes: string[]\n /** `new:<name>` references (lowercased names) to leave out. */\n dropped: Set<string>\n /** Brief lines for the unit's own job: what to leave out, and what to place. */\n briefLines: string[]\n}\n\n/**\n * How a unit is built when some of what it depends on failed (AGL-3616).\n *\n * A PAGE is always built: a failed layout falls back to the site's own, a\n * failed form or component is left out of its section, and a failed item a\n * section places (a booking service) takes its block out of the page — each\n * with a note. Any OTHER unit whose dependency failed is skipped when that\n * dependency's capability says `omit` (a campaign whose email design failed\n * has nothing to send), and built without it when it says `fallback`.\n */\nexport function aiBuildDegradation(\n unit: AiBuildUnit,\n context: {\n units: readonly AiBuildUnit[]\n ledger: readonly AiJobItemLedger[]\n ops?: AiBuildOps\n },\n): AiBuildDegradation {\n const rows = new Map(context.ledger.map((row) => [row.slot, row]))\n const bySlot = new Map(context.units.map((one) => [one.slot, one]))\n const result: AiBuildDegradation = { skip: null, degradedBy: [], notes: [], dropped: new Set(), briefLines: [] }\n for (const slot of unit.deps) {\n const dep = bySlot.get(slot)\n const row = rows.get(slot)\n if (!dep || !row || aiBuildItemDelivered(row)) continue\n const noun = dep.creation\n ? aiBuildCreationNoun(dep.creation.kind)\n : (context.ops?.get(dep.op)?.noun ?? dep.op)\n const capability = dep.item ? context.ops?.get(dep.op) : undefined\n const degrade = dep.item?.degrade ?? capability?.degrade ?? (dep.creation?.kind === 'layout' ? 'fallback' : 'omit')\n if (!unit.screen && degrade === 'omit') {\n result.skip = `Not built: the ${noun} “${dep.label}” it needs could not be created.`\n result.degradedBy.push(slot)\n return result\n }\n result.degradedBy.push(slot)\n result.dropped.add(dep.label.toLowerCase())\n if (dep.creation?.kind === 'layout') {\n result.notes.push(`Built inside the site’s own layout: the layout “${dep.label}” could not be created.`)\n continue\n }\n if (unit.screen) {\n const section = unit.screen.sections.find((one) =>\n one.uses.some((ref) => isAiPlanNewRef(ref) && aiBuildRefName(ref) === dep.label.toLowerCase()),\n )\n const blocks = capability?.pageBlocks?.length ? ` the ${capability.pageBlocks.join(' or ')} block` : ''\n result.notes.push(\n `Built without${blocks || ` the ${noun}`}: the ${noun} “${dep.label}” could not be created.`,\n )\n result.briefLines.push(\n `${section ? `Build the “${section.name}” section` : 'Build the page'} without the ${noun} “${dep.label}”${blocks ? ` and without${blocks}` : ''}: it could not be created.`,\n )\n } else {\n result.notes.push(`Built without the ${noun} “${dep.label}”: it could not be created.`)\n }\n }\n return result\n}\n\n/** What each creation is called in a note. */\nexport function aiBuildCreationNoun(kind: AiBuildPlanCreateKind): string {\n return kind === 'email' ? 'email design' : kind === 'theme-change' ? 'theme change' : kind\n}\n\n/**\n * The brief lines a page is told about the items its sections place and\n * that were built: the block to put there, in the owner's words.\n */\nexport function aiBuildPlacedItemLines(\n unit: AiBuildUnit,\n context: { units: readonly AiBuildUnit[]; ledger: readonly AiJobItemLedger[]; ops?: AiBuildOps },\n): string[] {\n if (!unit.screen) return []\n const rows = new Map(context.ledger.map((row) => [row.slot, row]))\n const lines: string[] = []\n for (const section of unit.screen.sections) {\n for (const ref of section.uses) {\n if (!isAiPlanNewRef(ref)) continue\n const dep = context.units.find((one) => one.item && one.item.name.toLowerCase() === aiBuildRefName(ref))\n if (!dep?.item) continue\n const row = rows.get(dep.slot)\n if (!row || !aiBuildItemDelivered(row)) continue\n const capability = context.ops?.get(dep.op)\n const blocks = capability?.pageBlocks ?? []\n if (!blocks.length) continue\n lines.push(\n `In the “${section.name}” section, place the ${blocks.join(' or ')} block for the ${capability?.noun ?? dep.op} “${dep.label}”.`,\n )\n }\n }\n return lines\n}\n\n/** What a build came to: whether anything was delivered, and whether anything is left. */\nexport function aiBuildSettlement(ledger: readonly AiJobItemLedger[]): {\n delivered: boolean\n open: boolean\n failed: number\n} {\n return {\n delivered: ledger.some(aiBuildItemDelivered),\n open: ledger.some(aiBuildItemOpen),\n failed: ledger.filter((row) => row.status === 'failed').length,\n }\n}\n\n/**\n * The ledger Try again runs (AGL-3616): every failed item back to `pending`\n * on its next attempt, with the items left unbuilt because of it — skipped,\n * or degraded with no draft — and every item the build never reached. An\n * item that succeeded is never run again, and a degraded page that has its\n * draft keeps it, with a note that the page needs an edit. `retried` names\n * the slots that will run, which is what the estimate is shown for.\n */\nexport function aiBuildRetryLedger(\n ledger: readonly AiJobItemLedger[],\n units: readonly AiBuildUnit[],\n): { ledger: AiJobItemLedger[]; retried: string[] } {\n const failed = new Set(ledger.filter((row) => row.status === 'failed').map((row) => row.slot))\n const dependents = new Map<string, string[]>()\n for (const unit of units) {\n for (const dep of unit.deps) dependents.set(dep, [...(dependents.get(dep) ?? []), unit.slot])\n }\n // Everything downstream of a failed item, transitively.\n const downstream = new Set<string>()\n const queue = [...failed]\n while (queue.length) {\n const slot = queue.shift() as string\n for (const next of dependents.get(slot) ?? []) {\n if (downstream.has(next)) continue\n downstream.add(next)\n queue.push(next)\n }\n }\n const retried: string[] = []\n const next = ledger.map((row): AiJobItemLedger => {\n const again =\n row.status === 'failed' ||\n (row.status === 'skipped' && (downstream.has(row.slot) || !(row.degradedBy ?? []).length)) ||\n (row.status === 'degraded' && downstream.has(row.slot) && !row.outputs.length)\n if (again) {\n retried.push(row.slot)\n return {\n ...row,\n status: 'pending',\n attempt: row.attempt + 1,\n attemptCredits: 0,\n failure: null,\n note: null,\n degradedBy: [],\n settledAt: null,\n }\n }\n if (row.status === 'degraded' && downstream.has(row.slot) && row.outputs.length) {\n return {\n ...row,\n note: `${row.note ? `${row.note} ` : ''}It keeps its draft: once the rest is built, edit this page to add what it is missing.`,\n }\n }\n return row\n })\n return { ledger: next, retried }\n}\n\n/**\n * Units read back off a ledger alone (AGL-3616), for a job whose units are\n * not a build plan's — a site scaffold's: each row as its unit, and every\n * page built after the layouts and forms the ledger holds.\n */\nexport function aiLedgerUnits(ledger: readonly AiJobItemLedger[]): AiBuildUnit[] {\n const creations = ledger.filter((row) => row.op === 'layout' || row.op === 'form').map((row) => row.slot)\n return ledger.map((row) => ({\n slot: row.slot,\n op: row.op,\n label: row.label,\n deps: row.op === 'page' ? creations : [],\n }))\n}\n"],"names":["pluginAiCapabilityArgsProblems","AI_PLAN_NEW_REF_PREFIX","isAiPlanNewRef","AI_SITE_HOME_FIRST_LABEL","AI_SITE_MAX_SECTIONS","AI_SITE_PASS_CREDITS","aiCreationMeasuredCredits","aiJobPlanCreditEstimate","aiJobPlanCreditRange","aiSitePlanIsHome","aiStandaloneScreenCreditRange","AI_CREDIT_RANGE_ZERO","AI_MEASURED_PASS_CREDITS","aiCreditRangeAdd","aiCreditRangeOf","aiCreditRangeOrdered","AI_BUILD_LIMITS","units","pages","freePages","aiBuildFreePageCapNote","plan","freeTaste","cap","screens","length","AI_BUILD_CREATE_KINDS","AI_BUILD_STRUCTURAL_OPS","AI_BUILD_PUBLISH_INPUT","creationOp","creation","kind","namedSlots","slots","Map","create","forEach","index","includes","set","name","toLowerCase","item","items","slot","aiBuildRefName","ref","slice","trim","aiBuildScreenRefs","screen","layout","template","duplicateOf","sections","flatMap","section","uses","filter","aiBuildUnits","depsOf","refs","self","deps","get","push","op","label","dependsOn","title","aiBuildOrder","ordered","placed","Set","known","map","unit","next","find","has","every","dep","add","aiBuildGraphProblems","problems","aiBuildPageLimit","aiBuildPlanShapeRefusal","options","counts","slugs","slug","graph","ops","capability","freeAllowed","aiArticle","noun","argsSchema","args","join","count","maxPerPlan","test","unitPasses","aiBuildUnitCreditEstimate","credits","Math","max","floor","estimateCredits","aiBuildCreditEstimate","reduce","total","aiJobCreditEstimate","aiBuildUnitCreditRange","ceiling","standalone","passes","ceil","median","p90","aiBuildCreditRange","aiJobCreditRange","aiBuildFirstPagePlan","findIndex","bySlot","keep","queue","shift","size","at","kept","entry","embeds","embed","where","aiBuildSmaller","smaller","aiBuildInitialLedger","status","attempt","creditsSpent","attemptCredits","creditsRefunded","failure","outputs","OPEN","aiBuildItemOpen","row","aiBuildItemDelivered","aiBuildNextUnit","ledger","rows","aiBuildDegradation","context","one","result","skip","degradedBy","notes","dropped","briefLines","aiBuildCreationNoun","undefined","degrade","some","blocks","pageBlocks","aiBuildPlacedItemLines","lines","aiBuildSettlement","delivered","open","failed","aiBuildRetryLedger","dependents","downstream","retried","again","note","settledAt","aiLedgerUnits","creations"],"mappings":"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"}
@@ -69,8 +69,8 @@ export declare function aiBuildCanRetry(job: Pick<AiJobSummary, 'kind' | 'status
69
69
  /**
70
70
  * What Try again is likely to cost (AGL-3722), quoted beside its button: a
71
71
  * build's retried items by `aiBuildCreditRange`; a site's retried rows each
72
- * at what its kind measured — a page at the nominal sections — held at the
73
- * reserve a row is retried at. `null` when nothing would run.
72
+ * at what its kind measured — a page at the nominal sections, written on its
73
+ * own as a retry is — held at the reserve a row is retried at. `null` when nothing would run.
74
74
  */
75
75
  export declare function aiBuildRetryCreditRange(job: Pick<AiJobSummary, 'kind' | 'items' | 'plan'>): AiCreditRange | null;
76
76
  /**
@@ -18,7 +18,7 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
18
18
  import { AI_JOB_PLAN_STEP } from "./ai-jobs.types.js";
19
19
  import { aiBuildCreditRange, aiBuildRetryLedger, aiBuildUnits, aiLedgerUnits } from "./ai-build-job.js";
20
20
  import { AI_CREDIT_RANGE_ZERO, aiCreditRangeAdd, aiCreditRangeOf, aiCreditRangeOrdered } from "./ai-credit-estimate.js";
21
- import { AI_SITE_NOMINAL_SECTIONS, AI_SITE_PASS_CREDITS, aiCreationMeasuredCredits, aiScreenCreditRange } from "./ai-site-job.js";
21
+ import { AI_SITE_NOMINAL_SECTIONS, AI_SITE_PASS_CREDITS, aiCreationMeasuredCredits, aiStandaloneScreenCreditRange } from "./ai-site-job.js";
22
22
  const OP_NOUNS = {
23
23
  page: 'Page',
24
24
  layout: 'Layout',
@@ -149,8 +149,8 @@ const STATES = {
149
149
  /**
150
150
  * What Try again is likely to cost (AGL-3722), quoted beside its button: a
151
151
  * build's retried items by `aiBuildCreditRange`; a site's retried rows each
152
- * at what its kind measured — a page at the nominal sections — held at the
153
- * reserve a row is retried at. `null` when nothing would run.
152
+ * at what its kind measured — a page at the nominal sections, written on its
153
+ * own as a retry is — held at the reserve a row is retried at. `null` when nothing would run.
154
154
  */ export function aiBuildRetryCreditRange(job) {
155
155
  var _job_items;
156
156
  const items = (_job_items = job.items) != null ? _job_items : [];
@@ -172,7 +172,9 @@ const STATES = {
172
172
  return aiCreditRangeOrdered(retried.reduce((total, slot)=>{
173
173
  var _ops_get;
174
174
  const op = (_ops_get = ops.get(slot)) != null ? _ops_get : '';
175
- const row = op === 'page' ? aiScreenCreditRange(AI_SITE_NOMINAL_SECTIONS) : aiCreditRangeOf(aiCreationMeasuredCredits(op), AI_SITE_PASS_CREDITS);
175
+ const row = op === 'page' ? aiStandaloneScreenCreditRange(AI_SITE_NOMINAL_SECTIONS) : aiCreditRangeOf(aiCreationMeasuredCredits(op, {
176
+ standalone: true
177
+ }), AI_SITE_PASS_CREDITS);
176
178
  return aiCreditRangeAdd(total, row);
177
179
  }, AI_CREDIT_RANGE_ZERO));
178
180
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/model/ai-build-progress.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 { aiCustomerSafeItem } from './ai-job-failure-copy'\nimport { AI_JOB_PLAN_STEP, type AiJobItemLedger, type AiJobSummary } from './ai-jobs.types'\nimport { aiBuildCreditRange, aiBuildRetryLedger, aiBuildUnits, aiLedgerUnits } from './ai-build-job'\nimport {\n AI_CREDIT_RANGE_ZERO,\n aiCreditRangeAdd,\n aiCreditRangeOf,\n aiCreditRangeOrdered,\n type AiCreditRange,\n} from './ai-credit-estimate'\nimport {\n AI_SITE_NOMINAL_SECTIONS,\n AI_SITE_PASS_CREDITS,\n aiCreationMeasuredCredits,\n aiScreenCreditRange,\n} from './ai-site-job'\n\n/**\n * What a `build` job shows of each item (AGL-3616), wherever it is shown —\n * the AI jobs drawer, the job's own page, the chat card: the item, where it\n * stands, what it cost, and what became of its credits when it failed.\n *\n * Pure: no React, no request.\n */\n\n/** Where one item stands, as a row's icon reads it. */\nexport type AiBuildItemRowState = 'done' | 'active' | 'waiting' | 'failed' | 'skipped'\n\nexport interface AiBuildItemRow {\n slot: string\n /** \"Page: About\", \"Form: Contact\". */\n label: string\n state: AiBuildItemRowState\n /** What the person should know: the failure, the note, what was given back. */\n detail: string | null\n /** When the active item started, for the elapsed time beside it; absent on every other row. */\n startedAt?: string | null\n}\n\nconst OP_NOUNS: Readonly<Record<string, string>> = {\n page: 'Page',\n layout: 'Layout',\n form: 'Form',\n component: 'Component',\n email: 'Email design',\n template: 'Page template',\n campaign: 'Email campaign',\n workflow: 'Automation',\n // A guided start's first posts and products (AGL-3676).\n posts: 'Blog',\n products: 'Store',\n}\n\n/** What an operation is called at the start of a row: its own noun, or the op spelled as words. */\nexport function aiBuildOpNoun(op: string): string {\n const known = OP_NOUNS[op]\n if (known) return known\n const words = op.replace(/[-_]+/g, ' ').trim()\n return words ? `${words[0].toUpperCase()}${words.slice(1)}` : 'Item'\n}\n\n/**\n * What became of a failed item's credits (AGL-3616), in the words every\n * surface uses for a failure on our side: \"This one’s on us — you weren’t\n * charged.\" A failure that was not ours — the model declining, a site at its\n * allowance — says what it used, which was charged. `null` for an item that\n * did not fail.\n */\nexport function aiBuildItemRefundCopy(\n row: Pick<AiJobItemLedger, 'status' | 'failure' | 'creditsRefunded' | 'creditsSpent'>,\n): string | null {\n if (row.status !== 'failed') return null\n if (row.failure?.ours) {\n const refunded = Math.max(0, Math.floor(row.creditsRefunded ?? 0))\n if (refunded > 0) {\n return `This one’s on us — you weren’t charged. The ${refunded} ${refunded === 1 ? 'credit' : 'credits'} it used ${refunded === 1 ? 'is' : 'are'} back in your AI credits.`\n }\n return 'This one’s on us — you weren’t charged.'\n }\n const spent = Math.max(0, Math.floor(row.creditsSpent ?? 0))\n return spent > 0 ? `It used ${spent} ${spent === 1 ? 'credit' : 'credits'}.` : null\n}\n\nconst STATES: Readonly<Record<AiJobItemLedger['status'], AiBuildItemRowState>> = {\n pending: 'waiting',\n running: 'active',\n succeeded: 'done',\n degraded: 'done',\n failed: 'failed',\n skipped: 'skipped',\n}\n\n/**\n * The item the build is on (AGL-3596): the one its ledger marks running, else\n * — while the job moves — the first still pending, which is the one its runner\n * builds next. The runner settles an item in the write that records its pass,\n * so the item it is writing reads `pending` until it is done; read as such,\n * every row waited and the build looked stalled. `null` when the job is not\n * moving or nothing is left.\n */\nexport function aiBuildActiveSlot(\n job: Pick<AiJobSummary, 'items'> & Partial<Pick<AiJobSummary, 'status'>>,\n): string | null {\n const items = job.items ?? []\n const running = items.find((row) => row.status === 'running')\n if (running) return running.slot\n if (job.status !== 'queued' && job.status !== 'running') return null\n return items.find((row) => row.status === 'pending')?.slot ?? null\n}\n\n/**\n * When the active item started: when the last item before it settled, which\n * the ledger records, else when the build step started — the first item's\n * start, and the best a ledger written before settling was recorded has.\n */\nexport function aiBuildActiveStartedAt(\n job: Pick<AiJobSummary, 'items'> & Partial<Pick<AiJobSummary, 'steps'>>,\n): string | null {\n let latest: { at: number; iso: string } | null = null\n for (const row of job.items ?? []) {\n const at = row.settledAt ? Date.parse(row.settledAt) : NaN\n if (Number.isFinite(at) && (!latest || at > latest.at)) latest = { at, iso: row.settledAt as string }\n }\n if (latest) return latest.iso\n const step = (job.steps ?? []).find((one) => one.name !== AI_JOB_PLAN_STEP && one.startedAt)\n return step?.startedAt ?? null\n}\n\n/** One row an item, in the order the build planned them; the item it is on is the active one. */\nexport function aiBuildItemRows(\n job: Pick<AiJobSummary, 'items'> & Partial<Pick<AiJobSummary, 'status' | 'steps'>>,\n): AiBuildItemRow[] {\n const active = aiBuildActiveSlot(job)\n return (job.items ?? []).map((ledger) => {\n // A building rule's own words never reach a customer (AGL-3596).\n const row = aiCustomerSafeItem(ledger)\n const parts: string[] = []\n if (row.status === 'failed' && row.failure?.message) parts.push(row.failure.message)\n if (row.note) parts.push(row.note)\n const refund = aiBuildItemRefundCopy(row)\n if (refund) parts.push(refund)\n return {\n slot: row.slot,\n label: `${aiBuildOpNoun(row.op)}: ${row.label}`,\n state: row.slot === active ? 'active' : (STATES[row.status] ?? 'waiting'),\n detail: parts.length ? parts.join(' ') : null,\n ...(row.slot === active ? { startedAt: aiBuildActiveStartedAt(job) } : {}),\n }\n })\n}\n\n/** How a build came out, in one line: \"4 of 5 built; 1 failed.\" `null` while it runs. */\nexport function aiBuildOutcomeLine(job: Pick<AiJobSummary, 'items' | 'status'>): string | null {\n const items = job.items ?? []\n if (!items.length || (job.status !== 'done' && job.status !== 'failed')) return null\n const built = items.filter((row) => row.status === 'succeeded' || row.status === 'degraded').length\n const failed = items.filter((row) => row.status === 'failed').length\n const skipped = items.filter((row) => row.status === 'skipped').length\n const tail = [failed ? `${failed} failed` : '', skipped ? `${skipped} not built` : ''].filter(Boolean)\n return `${built} of ${items.length} built${tail.length ? `; ${tail.join(', ')}` : ''}.`\n}\n\n/** Whether a finished build — or a site that built part of itself — has failed items to try again. */\nexport function aiBuildCanRetry(job: Pick<AiJobSummary, 'kind' | 'status' | 'items'>): boolean {\n // A site that built nothing starts over from its own answers instead.\n const finished = job.kind === 'build' ? job.status === 'done' || job.status === 'failed' : job.kind === 'site' && job.status === 'done'\n return (\n finished &&\n (job.items ?? []).some((row) => row.status === 'failed' || (row.status === 'skipped' && !row.degradedBy?.length))\n )\n}\n\n/**\n * What Try again is likely to cost (AGL-3722), quoted beside its button: a\n * build's retried items by `aiBuildCreditRange`; a site's retried rows each\n * at what its kind measured — a page at the nominal sections — held at the\n * reserve a row is retried at. `null` when nothing would run.\n */\nexport function aiBuildRetryCreditRange(\n job: Pick<AiJobSummary, 'kind' | 'items' | 'plan'>,\n): AiCreditRange | null {\n const items = job.items ?? []\n if (!items.length) return null\n if (job.kind === 'build') {\n if (!job.plan) return null\n const plan = job.plan as unknown as Parameters<typeof aiBuildUnits>[0]\n const { retried } = aiBuildRetryLedger(items, aiBuildUnits(plan))\n return retried.length ? aiBuildCreditRange(plan, { slots: new Set(retried) }) : null\n }\n const { retried } = aiBuildRetryLedger(items, aiLedgerUnits(items))\n if (!retried.length) return null\n const ops = new Map(items.map((row) => [row.slot, row.op]))\n return aiCreditRangeOrdered(\n retried.reduce((total, slot) => {\n const op = ops.get(slot) ?? ''\n const row =\n op === 'page'\n ? aiScreenCreditRange(AI_SITE_NOMINAL_SECTIONS)\n : aiCreditRangeOf(aiCreationMeasuredCredits(op), AI_SITE_PASS_CREDITS)\n return aiCreditRangeAdd(total, row)\n }, AI_CREDIT_RANGE_ZERO),\n )\n}\n\n/**\n * What a guided start that built part of its site says (AGL-3616), in the\n * words every surface uses: \"Built 1 of 2 pages. Home couldn’t be built —\n * that one’s on us…\". `null` when every page was built, or none was.\n */\nexport function aiSitePartialCopy(job: Pick<AiJobSummary, 'items' | 'status'>): string | null {\n const pages = (job.items ?? []).filter((row) => row.op === 'page')\n const built = pages.filter((row) => row.status === 'succeeded' || row.status === 'degraded')\n const unbuilt = (job.items ?? []).filter((row) => row.status === 'failed' || row.status === 'skipped')\n if (job.status !== 'done' || !unbuilt.length || !built.length) return null\n const names = unbuilt.map((row) => (row.op === 'page' ? row.label : `The ${aiBuildOpNoun(row.op).toLowerCase()} “${row.label}”`))\n const list = names.length === 1 ? names[0] : `${names.slice(0, -1).join(', ')} and ${names[names.length - 1]}`\n const refunded = unbuilt.reduce((total, row) => total + Math.max(0, Math.floor(row.creditsRefunded ?? 0)), 0)\n const back = refunded > 0 ? ` The ${refunded} ${refunded === 1 ? 'credit' : 'credits'} it used ${refunded === 1 ? 'is' : 'are'} back in your AI credits.` : ''\n // Only a failure on our side says so; a part the AI declined or an allowance\n // stopped was charged for what it used, and the row says that.\n const ours = unbuilt.every((row) => row.status === 'skipped' || row.failure?.ours === true)\n const why = ours ? ` — that one’s on us, you weren’t charged for ${unbuilt.length === 1 ? 'it' : 'them'}.` : '.'\n return `Built ${built.length} of ${pages.length} ${pages.length === 1 ? 'page' : 'pages'}. ${list} couldn’t be built${why}${back} Try again builds only what failed.`\n}\n"],"names":["aiCustomerSafeItem","AI_JOB_PLAN_STEP","aiBuildCreditRange","aiBuildRetryLedger","aiBuildUnits","aiLedgerUnits","AI_CREDIT_RANGE_ZERO","aiCreditRangeAdd","aiCreditRangeOf","aiCreditRangeOrdered","AI_SITE_NOMINAL_SECTIONS","AI_SITE_PASS_CREDITS","aiCreationMeasuredCredits","aiScreenCreditRange","OP_NOUNS","page","layout","form","component","email","template","campaign","workflow","posts","products","aiBuildOpNoun","op","known","words","replace","trim","toUpperCase","slice","aiBuildItemRefundCopy","row","status","failure","ours","refunded","Math","max","floor","creditsRefunded","spent","creditsSpent","STATES","pending","running","succeeded","degraded","failed","skipped","aiBuildActiveSlot","job","items","find","slot","aiBuildActiveStartedAt","latest","at","settledAt","Date","parse","NaN","Number","isFinite","iso","step","steps","one","name","startedAt","aiBuildItemRows","active","map","ledger","parts","message","push","note","refund","label","state","detail","length","join","aiBuildOutcomeLine","built","filter","tail","Boolean","aiBuildCanRetry","finished","kind","some","degradedBy","aiBuildRetryCreditRange","plan","retried","slots","Set","ops","Map","reduce","total","get","aiSitePartialCopy","pages","unbuilt","names","toLowerCase","list","back","every","why"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/model/ai-build-progress.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 { aiCustomerSafeItem } from './ai-job-failure-copy'\nimport { AI_JOB_PLAN_STEP, type AiJobItemLedger, type AiJobSummary } from './ai-jobs.types'\nimport { aiBuildCreditRange, aiBuildRetryLedger, aiBuildUnits, aiLedgerUnits } from './ai-build-job'\nimport {\n AI_CREDIT_RANGE_ZERO,\n aiCreditRangeAdd,\n aiCreditRangeOf,\n aiCreditRangeOrdered,\n type AiCreditRange,\n} from './ai-credit-estimate'\nimport {\n AI_SITE_NOMINAL_SECTIONS,\n AI_SITE_PASS_CREDITS,\n aiCreationMeasuredCredits,\n aiStandaloneScreenCreditRange,\n} from './ai-site-job'\n\n/**\n * What a `build` job shows of each item (AGL-3616), wherever it is shown —\n * the AI jobs drawer, the job's own page, the chat card: the item, where it\n * stands, what it cost, and what became of its credits when it failed.\n *\n * Pure: no React, no request.\n */\n\n/** Where one item stands, as a row's icon reads it. */\nexport type AiBuildItemRowState = 'done' | 'active' | 'waiting' | 'failed' | 'skipped'\n\nexport interface AiBuildItemRow {\n slot: string\n /** \"Page: About\", \"Form: Contact\". */\n label: string\n state: AiBuildItemRowState\n /** What the person should know: the failure, the note, what was given back. */\n detail: string | null\n /** When the active item started, for the elapsed time beside it; absent on every other row. */\n startedAt?: string | null\n}\n\nconst OP_NOUNS: Readonly<Record<string, string>> = {\n page: 'Page',\n layout: 'Layout',\n form: 'Form',\n component: 'Component',\n email: 'Email design',\n template: 'Page template',\n campaign: 'Email campaign',\n workflow: 'Automation',\n // A guided start's first posts and products (AGL-3676).\n posts: 'Blog',\n products: 'Store',\n}\n\n/** What an operation is called at the start of a row: its own noun, or the op spelled as words. */\nexport function aiBuildOpNoun(op: string): string {\n const known = OP_NOUNS[op]\n if (known) return known\n const words = op.replace(/[-_]+/g, ' ').trim()\n return words ? `${words[0].toUpperCase()}${words.slice(1)}` : 'Item'\n}\n\n/**\n * What became of a failed item's credits (AGL-3616), in the words every\n * surface uses for a failure on our side: \"This one’s on us — you weren’t\n * charged.\" A failure that was not ours — the model declining, a site at its\n * allowance — says what it used, which was charged. `null` for an item that\n * did not fail.\n */\nexport function aiBuildItemRefundCopy(\n row: Pick<AiJobItemLedger, 'status' | 'failure' | 'creditsRefunded' | 'creditsSpent'>,\n): string | null {\n if (row.status !== 'failed') return null\n if (row.failure?.ours) {\n const refunded = Math.max(0, Math.floor(row.creditsRefunded ?? 0))\n if (refunded > 0) {\n return `This one’s on us — you weren’t charged. The ${refunded} ${refunded === 1 ? 'credit' : 'credits'} it used ${refunded === 1 ? 'is' : 'are'} back in your AI credits.`\n }\n return 'This one’s on us — you weren’t charged.'\n }\n const spent = Math.max(0, Math.floor(row.creditsSpent ?? 0))\n return spent > 0 ? `It used ${spent} ${spent === 1 ? 'credit' : 'credits'}.` : null\n}\n\nconst STATES: Readonly<Record<AiJobItemLedger['status'], AiBuildItemRowState>> = {\n pending: 'waiting',\n running: 'active',\n succeeded: 'done',\n degraded: 'done',\n failed: 'failed',\n skipped: 'skipped',\n}\n\n/**\n * The item the build is on (AGL-3596): the one its ledger marks running, else\n * — while the job moves — the first still pending, which is the one its runner\n * builds next. The runner settles an item in the write that records its pass,\n * so the item it is writing reads `pending` until it is done; read as such,\n * every row waited and the build looked stalled. `null` when the job is not\n * moving or nothing is left.\n */\nexport function aiBuildActiveSlot(\n job: Pick<AiJobSummary, 'items'> & Partial<Pick<AiJobSummary, 'status'>>,\n): string | null {\n const items = job.items ?? []\n const running = items.find((row) => row.status === 'running')\n if (running) return running.slot\n if (job.status !== 'queued' && job.status !== 'running') return null\n return items.find((row) => row.status === 'pending')?.slot ?? null\n}\n\n/**\n * When the active item started: when the last item before it settled, which\n * the ledger records, else when the build step started — the first item's\n * start, and the best a ledger written before settling was recorded has.\n */\nexport function aiBuildActiveStartedAt(\n job: Pick<AiJobSummary, 'items'> & Partial<Pick<AiJobSummary, 'steps'>>,\n): string | null {\n let latest: { at: number; iso: string } | null = null\n for (const row of job.items ?? []) {\n const at = row.settledAt ? Date.parse(row.settledAt) : NaN\n if (Number.isFinite(at) && (!latest || at > latest.at)) latest = { at, iso: row.settledAt as string }\n }\n if (latest) return latest.iso\n const step = (job.steps ?? []).find((one) => one.name !== AI_JOB_PLAN_STEP && one.startedAt)\n return step?.startedAt ?? null\n}\n\n/** One row an item, in the order the build planned them; the item it is on is the active one. */\nexport function aiBuildItemRows(\n job: Pick<AiJobSummary, 'items'> & Partial<Pick<AiJobSummary, 'status' | 'steps'>>,\n): AiBuildItemRow[] {\n const active = aiBuildActiveSlot(job)\n return (job.items ?? []).map((ledger) => {\n // A building rule's own words never reach a customer (AGL-3596).\n const row = aiCustomerSafeItem(ledger)\n const parts: string[] = []\n if (row.status === 'failed' && row.failure?.message) parts.push(row.failure.message)\n if (row.note) parts.push(row.note)\n const refund = aiBuildItemRefundCopy(row)\n if (refund) parts.push(refund)\n return {\n slot: row.slot,\n label: `${aiBuildOpNoun(row.op)}: ${row.label}`,\n state: row.slot === active ? 'active' : (STATES[row.status] ?? 'waiting'),\n detail: parts.length ? parts.join(' ') : null,\n ...(row.slot === active ? { startedAt: aiBuildActiveStartedAt(job) } : {}),\n }\n })\n}\n\n/** How a build came out, in one line: \"4 of 5 built; 1 failed.\" `null` while it runs. */\nexport function aiBuildOutcomeLine(job: Pick<AiJobSummary, 'items' | 'status'>): string | null {\n const items = job.items ?? []\n if (!items.length || (job.status !== 'done' && job.status !== 'failed')) return null\n const built = items.filter((row) => row.status === 'succeeded' || row.status === 'degraded').length\n const failed = items.filter((row) => row.status === 'failed').length\n const skipped = items.filter((row) => row.status === 'skipped').length\n const tail = [failed ? `${failed} failed` : '', skipped ? `${skipped} not built` : ''].filter(Boolean)\n return `${built} of ${items.length} built${tail.length ? `; ${tail.join(', ')}` : ''}.`\n}\n\n/** Whether a finished build — or a site that built part of itself — has failed items to try again. */\nexport function aiBuildCanRetry(job: Pick<AiJobSummary, 'kind' | 'status' | 'items'>): boolean {\n // A site that built nothing starts over from its own answers instead.\n const finished = job.kind === 'build' ? job.status === 'done' || job.status === 'failed' : job.kind === 'site' && job.status === 'done'\n return (\n finished &&\n (job.items ?? []).some((row) => row.status === 'failed' || (row.status === 'skipped' && !row.degradedBy?.length))\n )\n}\n\n/**\n * What Try again is likely to cost (AGL-3722), quoted beside its button: a\n * build's retried items by `aiBuildCreditRange`; a site's retried rows each\n * at what its kind measured — a page at the nominal sections, written on its\n * own as a retry is — held at the reserve a row is retried at. `null` when nothing would run.\n */\nexport function aiBuildRetryCreditRange(\n job: Pick<AiJobSummary, 'kind' | 'items' | 'plan'>,\n): AiCreditRange | null {\n const items = job.items ?? []\n if (!items.length) return null\n if (job.kind === 'build') {\n if (!job.plan) return null\n const plan = job.plan as unknown as Parameters<typeof aiBuildUnits>[0]\n const { retried } = aiBuildRetryLedger(items, aiBuildUnits(plan))\n return retried.length ? aiBuildCreditRange(plan, { slots: new Set(retried) }) : null\n }\n const { retried } = aiBuildRetryLedger(items, aiLedgerUnits(items))\n if (!retried.length) return null\n const ops = new Map(items.map((row) => [row.slot, row.op]))\n return aiCreditRangeOrdered(\n retried.reduce((total, slot) => {\n const op = ops.get(slot) ?? ''\n const row =\n op === 'page'\n ? aiStandaloneScreenCreditRange(AI_SITE_NOMINAL_SECTIONS)\n : aiCreditRangeOf(aiCreationMeasuredCredits(op, { standalone: true }), AI_SITE_PASS_CREDITS)\n return aiCreditRangeAdd(total, row)\n }, AI_CREDIT_RANGE_ZERO),\n )\n}\n\n/**\n * What a guided start that built part of its site says (AGL-3616), in the\n * words every surface uses: \"Built 1 of 2 pages. Home couldn’t be built —\n * that one’s on us…\". `null` when every page was built, or none was.\n */\nexport function aiSitePartialCopy(job: Pick<AiJobSummary, 'items' | 'status'>): string | null {\n const pages = (job.items ?? []).filter((row) => row.op === 'page')\n const built = pages.filter((row) => row.status === 'succeeded' || row.status === 'degraded')\n const unbuilt = (job.items ?? []).filter((row) => row.status === 'failed' || row.status === 'skipped')\n if (job.status !== 'done' || !unbuilt.length || !built.length) return null\n const names = unbuilt.map((row) => (row.op === 'page' ? row.label : `The ${aiBuildOpNoun(row.op).toLowerCase()} “${row.label}”`))\n const list = names.length === 1 ? names[0] : `${names.slice(0, -1).join(', ')} and ${names[names.length - 1]}`\n const refunded = unbuilt.reduce((total, row) => total + Math.max(0, Math.floor(row.creditsRefunded ?? 0)), 0)\n const back = refunded > 0 ? ` The ${refunded} ${refunded === 1 ? 'credit' : 'credits'} it used ${refunded === 1 ? 'is' : 'are'} back in your AI credits.` : ''\n // Only a failure on our side says so; a part the AI declined or an allowance\n // stopped was charged for what it used, and the row says that.\n const ours = unbuilt.every((row) => row.status === 'skipped' || row.failure?.ours === true)\n const why = ours ? ` — that one’s on us, you weren’t charged for ${unbuilt.length === 1 ? 'it' : 'them'}.` : '.'\n return `Built ${built.length} of ${pages.length} ${pages.length === 1 ? 'page' : 'pages'}. ${list} couldn’t be built${why}${back} Try again builds only what failed.`\n}\n"],"names":["aiCustomerSafeItem","AI_JOB_PLAN_STEP","aiBuildCreditRange","aiBuildRetryLedger","aiBuildUnits","aiLedgerUnits","AI_CREDIT_RANGE_ZERO","aiCreditRangeAdd","aiCreditRangeOf","aiCreditRangeOrdered","AI_SITE_NOMINAL_SECTIONS","AI_SITE_PASS_CREDITS","aiCreationMeasuredCredits","aiStandaloneScreenCreditRange","OP_NOUNS","page","layout","form","component","email","template","campaign","workflow","posts","products","aiBuildOpNoun","op","known","words","replace","trim","toUpperCase","slice","aiBuildItemRefundCopy","row","status","failure","ours","refunded","Math","max","floor","creditsRefunded","spent","creditsSpent","STATES","pending","running","succeeded","degraded","failed","skipped","aiBuildActiveSlot","job","items","find","slot","aiBuildActiveStartedAt","latest","at","settledAt","Date","parse","NaN","Number","isFinite","iso","step","steps","one","name","startedAt","aiBuildItemRows","active","map","ledger","parts","message","push","note","refund","label","state","detail","length","join","aiBuildOutcomeLine","built","filter","tail","Boolean","aiBuildCanRetry","finished","kind","some","degradedBy","aiBuildRetryCreditRange","plan","retried","slots","Set","ops","Map","reduce","total","get","standalone","aiSitePartialCopy","pages","unbuilt","names","toLowerCase","list","back","every","why"],"mappings":"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"}
@@ -97,11 +97,56 @@ export declare const AI_MEASURED_PAGE_SECTIONS = 5;
97
97
  * section, 8 at the p90.
98
98
  */
99
99
  export declare function aiMeasuredPageCredits(sections: number): AiMeasuredCredits;
100
+ /**
101
+ * What a page costs when it is written ON ITS OWN — a page an Assist build or
102
+ * a page job writes, rather than one of a site start's pages (AGL-3722).
103
+ *
104
+ * The table's page item is a site start's: its pages are written one after
105
+ * another inside one job, the later ones reading the prompt the first one
106
+ * paid to write, so a 2-section second page measured 19–28. A page written on
107
+ * its own pays that prompt itself and reads the site it lands on, and costs
108
+ * what a site start's FIRST page costs: a 5-section home page measured 39–78
109
+ * (median 40, p90 78), standalone page jobs' writing step 82–105 for a
110
+ * 2-section page, and the Assist build pages of 2026-10-09 22–89 each. Quoting
111
+ * a build's pages at the site start's scaled median told a Free workspace
112
+ * "about 48 credits" for two 4-section pages (AGL-3722, 2026-10-10).
113
+ *
114
+ * So it is priced as a fixed cost — the prompt, the site, the listing — and a
115
+ * cost per section: a 4-section page about 40 (p90 78), a 5-section 46 (p90 90).
116
+ */
117
+ export declare const AI_MEASURED_STANDALONE_PAGE: {
118
+ readonly fixed: {
119
+ readonly median: 16;
120
+ readonly p90: 30;
121
+ };
122
+ readonly perSection: {
123
+ readonly median: 6;
124
+ readonly p90: 12;
125
+ };
126
+ };
127
+ /** What a page of this many sections written on its own is likely to cost. */
128
+ export declare function aiMeasuredStandalonePageCredits(sections: number): AiMeasuredCredits;
129
+ /**
130
+ * What a creation costs when it is written ON ITS OWN (AGL-3722), where it
131
+ * measured apart from a site start's: an Assist build's layout came to 24–28
132
+ * (2026-10-09/10), against a site start's 23/24 written in its warm prompt.
133
+ * A form measured the same either way (25–30 on its own, 29/31 in a site
134
+ * start), so it keeps the table's figure.
135
+ */
136
+ export declare const AI_MEASURED_STANDALONE_CREATION_CREDITS: {
137
+ readonly layout: {
138
+ readonly median: 26;
139
+ readonly p90: 30;
140
+ };
141
+ };
100
142
  /**
101
143
  * What one pass of a kind with no measurement of its own is likely to cost
102
144
  * (a component, an email design, a template, an item another runner
103
- * builds): a form's, the measured single-answer creation closest to them.
104
- * A declared stand-in, replaced the day those kinds are measured.
145
+ * builds), written on its own: a component job's writing step measured
146
+ * 52–65, a form job's 37, a layout job's 63, and the Assist build of
147
+ * 2026-10-09 a welcome email at 46 and a products step at 60. Until
148
+ * 2026-10-10 this was a site start's form (29/31), which is written inside a
149
+ * site job's warm prompt and is the cheapest single answer there is.
105
150
  */
106
151
  export declare const AI_MEASURED_PASS_CREDITS: AiMeasuredCredits;
107
152
  /** A job's cost as it is quoted: likely, nine times in ten, and at its worst. */
@@ -158,6 +203,28 @@ export declare const AI_CREDITS_CONFIRM_CODE = "credits-confirm";
158
203
  export declare const AI_CREDITS_BUILD_WHAT_FITS = "Build what fits";
159
204
  /** The smaller first build's button: "Build the home page first (about 64 credits)". */
160
205
  export declare function aiCreditsSmallerText(smaller: Pick<AiCreditsSmaller, 'label' | 'likely'>): string;
206
+ /** Which way on a prompt offers, in the order it offers them. */
207
+ export type AiCreditsChoiceKey = 'fits' | 'smaller' | 'upgrade';
208
+ /** One way on, as its option button reads it: a short label and the figure under it (AGL-3722). */
209
+ export interface AiCreditsChoice {
210
+ key: AiCreditsChoiceKey;
211
+ label: string;
212
+ detail: string;
213
+ /** The one choice drawn as the primary button. */
214
+ recommended: boolean;
215
+ }
216
+ /**
217
+ * The prompt's ways on, as its three option buttons read them (Zach,
218
+ * 2026-10-10: "more appealing and consistent"): build what fits, the smaller
219
+ * first build when there is one, and Upgrade when it can be offered — each a
220
+ * short sentence-case label with its figure under it. The smaller build is
221
+ * the recommended one when its p90 fits what is left, since it then finishes;
222
+ * otherwise building what fits is.
223
+ */
224
+ export declare function aiCreditsChoices(prompt: Pick<AiCreditsPrompt, 'left' | 'smaller'>, offers: {
225
+ smaller: boolean;
226
+ upgrade: boolean;
227
+ }): AiCreditsChoice[];
161
228
  /**
162
229
  * The plain sentence (Zach, 2026-10-09): "This build is about N credits (up
163
230
  * to M). You have L left, so it will build as much as it can and pause when