@aglyn/plugins-ai 1.0.0-beta.236 → 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 (164) hide show
  1. package/package.json +17 -17
  2. package/src/lib/components/ai-credits-prompt.component.d.ts +44 -0
  3. package/src/lib/components/ai-credits-prompt.component.js +117 -0
  4. package/src/lib/components/ai-credits-prompt.component.js.map +1 -0
  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.d.ts +5 -4
  9. package/src/lib/components/ai-job-plan.component.js +48 -12
  10. package/src/lib/components/ai-job-plan.component.js.map +1 -1
  11. package/src/lib/components/ai-job-requests.d.ts +10 -0
  12. package/src/lib/components/ai-job-requests.js +12 -4
  13. package/src/lib/components/ai-job-requests.js.map +1 -1
  14. package/src/lib/components/ai-jobs-list-page.component.js +141 -72
  15. package/src/lib/components/ai-jobs-list-page.component.js.map +1 -1
  16. package/src/lib/components/ai-site-build-page.component.js +48 -9
  17. package/src/lib/components/ai-site-build-page.component.js.map +1 -1
  18. package/src/lib/components/ai-site-start-card.component.js +68 -22
  19. package/src/lib/components/ai-site-start-card.component.js.map +1 -1
  20. package/src/lib/components/ai-usage-strip.component.d.ts +19 -2
  21. package/src/lib/components/ai-usage-strip.component.js +40 -9
  22. package/src/lib/components/ai-usage-strip.component.js.map +1 -1
  23. package/src/lib/components/assist-build-card.component.d.ts +3 -1
  24. package/src/lib/components/assist-build-card.component.js +58 -7
  25. package/src/lib/components/assist-build-card.component.js.map +1 -1
  26. package/src/lib/components/assist-jobs-drawer.component.js +66 -22
  27. package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
  28. package/src/lib/components/assist-panel.component.js +89 -52
  29. package/src/lib/components/assist-panel.component.js.map +1 -1
  30. package/src/lib/jobs/ai-job-admission.d.ts +22 -2
  31. package/src/lib/jobs/ai-job-admission.js.map +1 -1
  32. package/src/lib/jobs/ai-job-build-step.d.ts +24 -11
  33. package/src/lib/jobs/ai-job-build-step.js +54 -35
  34. package/src/lib/jobs/ai-job-build-step.js.map +1 -1
  35. package/src/lib/jobs/ai-job-cancel.d.ts +71 -0
  36. package/src/lib/jobs/ai-job-cancel.js +102 -0
  37. package/src/lib/jobs/ai-job-cancel.js.map +1 -0
  38. package/src/lib/jobs/ai-job-component-step.js +4 -1
  39. package/src/lib/jobs/ai-job-component-step.js.map +1 -1
  40. package/src/lib/jobs/ai-job-drafts.js +2 -0
  41. package/src/lib/jobs/ai-job-drafts.js.map +1 -1
  42. package/src/lib/jobs/ai-job-form-step.js +4 -1
  43. package/src/lib/jobs/ai-job-form-step.js.map +1 -1
  44. package/src/lib/jobs/ai-job-layout-language.d.ts +2 -0
  45. package/src/lib/jobs/ai-job-layout-language.js +13 -1
  46. package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
  47. package/src/lib/jobs/ai-job-layout-step.js +6 -1
  48. package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
  49. package/src/lib/jobs/ai-job-page-language.js +12 -0
  50. package/src/lib/jobs/ai-job-page-language.js.map +1 -1
  51. package/src/lib/jobs/ai-job-page-step.d.ts +13 -0
  52. package/src/lib/jobs/ai-job-page-step.js +46 -4
  53. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  54. package/src/lib/jobs/ai-job-plan-step.d.ts +42 -0
  55. package/src/lib/jobs/ai-job-plan-step.js +118 -18
  56. package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
  57. package/src/lib/jobs/ai-job-site-content.d.ts +49 -3
  58. package/src/lib/jobs/ai-job-site-content.js +196 -37
  59. package/src/lib/jobs/ai-job-site-content.js.map +1 -1
  60. package/src/lib/jobs/ai-job-site-step.js +49 -16
  61. package/src/lib/jobs/ai-job-site-step.js.map +1 -1
  62. package/src/lib/jobs/ai-job-template-step.js +4 -1
  63. package/src/lib/jobs/ai-job-template-step.js.map +1 -1
  64. package/src/lib/jobs/ai-job-text-step.d.ts +8 -0
  65. package/src/lib/jobs/ai-job-text-step.js.map +1 -1
  66. package/src/lib/jobs/ai-jobs.d.ts +55 -13
  67. package/src/lib/jobs/ai-jobs.js +213 -41
  68. package/src/lib/jobs/ai-jobs.js.map +1 -1
  69. package/src/lib/jobs/ai-layout-stock-photos.d.ts +194 -34
  70. package/src/lib/jobs/ai-layout-stock-photos.js +861 -146
  71. package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
  72. package/src/lib/jobs/fixtures/ai-ceramics-portfolio-site-plan.d.ts +30 -0
  73. package/src/lib/jobs/fixtures/ai-ceramics-portfolio-site-plan.js +220 -0
  74. package/src/lib/jobs/fixtures/ai-ceramics-portfolio-site-plan.js.map +1 -0
  75. package/src/lib/jobs/fixtures/ai-stock-photo-pixabay-recordings.d.ts +27 -0
  76. package/src/lib/jobs/fixtures/ai-stock-photo-pixabay-recordings.js +151 -0
  77. package/src/lib/jobs/fixtures/ai-stock-photo-pixabay-recordings.js.map +1 -0
  78. package/src/lib/layout-language/ai-layout-compiler.d.ts +33 -0
  79. package/src/lib/layout-language/ai-layout-compiler.js +381 -18
  80. package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
  81. package/src/lib/layout-language/ai-layout-design.d.ts +6 -3
  82. package/src/lib/layout-language/ai-layout-design.js +5 -3
  83. package/src/lib/layout-language/ai-layout-design.js.map +1 -1
  84. package/src/lib/layout-language/ai-layout-frame.d.ts +12 -0
  85. package/src/lib/layout-language/ai-layout-frame.js +58 -3
  86. package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
  87. package/src/lib/layout-language/ai-layout-gaps.js +3 -1
  88. package/src/lib/layout-language/ai-layout-gaps.js.map +1 -1
  89. package/src/lib/layout-language/ai-layout-language.js +1 -1
  90. package/src/lib/layout-language/ai-layout-language.js.map +1 -1
  91. package/src/lib/layout-language/ai-layout-listings.d.ts +49 -1
  92. package/src/lib/layout-language/ai-layout-listings.js +117 -47
  93. package/src/lib/layout-language/ai-layout-listings.js.map +1 -1
  94. package/src/lib/layout-language/ai-layout-pictures.d.ts +10 -1
  95. package/src/lib/layout-language/ai-layout-pictures.js +5 -2
  96. package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
  97. package/src/lib/layout-language/ai-layout-storefront.d.ts +82 -0
  98. package/src/lib/layout-language/ai-layout-storefront.js +223 -0
  99. package/src/lib/layout-language/ai-layout-storefront.js.map +1 -0
  100. package/src/lib/model/ai-build-job.d.ts +39 -0
  101. package/src/lib/model/ai-build-job.js +100 -1
  102. package/src/lib/model/ai-build-job.js.map +1 -1
  103. package/src/lib/model/ai-build-progress.d.ts +8 -0
  104. package/src/lib/model/ai-build-progress.js +35 -0
  105. package/src/lib/model/ai-build-progress.js.map +1 -1
  106. package/src/lib/model/ai-credit-estimate.d.ts +249 -0
  107. package/src/lib/model/ai-credit-estimate.js +278 -0
  108. package/src/lib/model/ai-credit-estimate.js.map +1 -0
  109. package/src/lib/model/ai-job-cancel-copy.d.ts +44 -0
  110. package/src/lib/model/ai-job-cancel-copy.js +53 -0
  111. package/src/lib/model/ai-job-cancel-copy.js.map +1 -0
  112. package/src/lib/model/ai-job-failure-copy.d.ts +4 -1
  113. package/src/lib/model/ai-job-failure-copy.js +8 -3
  114. package/src/lib/model/ai-job-failure-copy.js.map +1 -1
  115. package/src/lib/model/ai-jobs.types.d.ts +35 -0
  116. package/src/lib/model/ai-jobs.types.js.map +1 -1
  117. package/src/lib/model/ai-site-build-progress.js +7 -4
  118. package/src/lib/model/ai-site-build-progress.js.map +1 -1
  119. package/src/lib/model/ai-site-job.d.ts +76 -22
  120. package/src/lib/model/ai-site-job.js +125 -23
  121. package/src/lib/model/ai-site-job.js.map +1 -1
  122. package/src/lib/model/ai-site-kinds.d.ts +4 -1
  123. package/src/lib/model/ai-site-kinds.js +35 -7
  124. package/src/lib/model/ai-site-kinds.js.map +1 -1
  125. package/src/lib/runtime/ai-doctrine-validators.d.ts +37 -1
  126. package/src/lib/runtime/ai-doctrine-validators.js +161 -7
  127. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
  128. package/src/lib/runtime/ai-doctrine.js +4 -3
  129. package/src/lib/runtime/ai-doctrine.js.map +1 -1
  130. package/src/lib/runtime/ai-node-tree.d.ts +11 -0
  131. package/src/lib/runtime/ai-node-tree.js +26 -0
  132. package/src/lib/runtime/ai-node-tree.js.map +1 -1
  133. package/src/lib/runtime/ai-palette.generated.js +592 -14
  134. package/src/lib/runtime/ai-palette.generated.js.map +1 -1
  135. package/src/lib/server/ai-jobs-cancel.d.ts +13 -5
  136. package/src/lib/server/ai-jobs-cancel.js +27 -9
  137. package/src/lib/server/ai-jobs-cancel.js.map +1 -1
  138. package/src/lib/server/ai-jobs-gate.d.ts +12 -2
  139. package/src/lib/server/ai-jobs-gate.js +20 -9
  140. package/src/lib/server/ai-jobs-gate.js.map +1 -1
  141. package/src/lib/server/ai-jobs-resume.js +93 -35
  142. package/src/lib/server/ai-jobs-resume.js.map +1 -1
  143. package/src/lib/server/ai-jobs-route.js +45 -4
  144. package/src/lib/server/ai-jobs-route.js.map +1 -1
  145. package/src/lib/server/assist-chat.js +4 -1
  146. package/src/lib/server/assist-chat.js.map +1 -1
  147. package/src/lib/server/assist-edit.js +3 -1
  148. package/src/lib/server/assist-edit.js.map +1 -1
  149. package/src/lib/server/assist-music.d.ts +36 -0
  150. package/src/lib/server/assist-music.js +36 -0
  151. package/src/lib/server/assist-music.js.map +1 -0
  152. package/src/lib/server.js +6 -0
  153. package/src/lib/server.js.map +1 -1
  154. package/src/lib/usage/ai-usage-meter.d.ts +2 -1
  155. package/src/lib/usage/ai-usage-meter.js +17 -1
  156. package/src/lib/usage/ai-usage-meter.js.map +1 -1
  157. package/src/lib/usage/ai-usage-wire.d.ts +6 -0
  158. package/src/lib/usage/ai-usage-wire.js.map +1 -1
  159. package/src/lib/usage/assist-usage.d.ts +7 -0
  160. package/src/lib/usage/assist-usage.js +14 -4
  161. package/src/lib/usage/assist-usage.js.map +1 -1
  162. package/src/lib/usage/free-ai-credits-left.d.ts +7 -0
  163. package/src/lib/usage/free-ai-credits-left.js +4 -2
  164. package/src/lib/usage/free-ai-credits-left.js.map +1 -1
@@ -16,6 +16,7 @@
16
16
  */
17
17
  import { type PluginMediaIngest } from '@aglyn/aglyn/plugin-manager/plugin-media-ingest';
18
18
  import { type StockPhoto, type StockPhotoOrientation, type StockPhotoProvider, type StockPhotoSearchRequest } from '@aglyn/aglyn/plugin-manager/stock-photo-provider';
19
+ import type { NodesMap } from '@aglyn/aglyn/types/nodes';
19
20
  import { type AiLayoutPictureSlot, type AiLayoutPictureSource } from '../layout-language/ai-layout-pictures';
20
21
  /**
21
22
  * STOCK PHOTOS FOR A LANGUAGE PAGE'S PICTURE SLOTS (AGL-3660).
@@ -26,64 +27,223 @@ import { type AiLayoutPictureSlot, type AiLayoutPictureSource } from '../layout-
26
27
  * server door (`core.media-ingest`), and builds no source at all when either
27
28
  * is missing, so a deployment without a key behaves exactly as before.
28
29
  *
29
- * For each slot, in document order:
30
+ * What the live starts of 2026-10-10 taught (Juniper Clay Works, a ceramic
31
+ * artist's portfolio, and Willow Wick Candles, a candle store), each photo
32
+ * traced through the library's cached answers:
30
33
  *
31
- * 1. **Search.** Plain words: the kind of business (the head of the site's
32
- * business type, "yoga studio" from "a family-owned yoga studio in
33
- * Austin") for the hero; the picture's own subject (the content words of
34
- * the alt text the model wrote, else its section's name) with the business
35
- * for the rest, and an about picture asks for people. The orientation and
36
- * a minimum size come from the slot's frame. The provider caches every
37
- * search for a day and keeps its own rate limit.
38
- * 2. **Pick.** Among the first hits not already on the page, by the job's
39
- * seed and the slot, so two sites built from the same words rarely open
40
- * with the same photo while one job always picks the same.
41
- * 3. **Keep.** A photo the site's library already holds (by its source key)
42
- * is reused; otherwise its bytes are downloaded from the library and
43
- * stored in the site's own media library as the member who started the
44
- * job, credited to its photographer. The page names the site's asset,
45
- * never the library's address.
34
+ * - The site's words were read as "portfolio" and "online" — the kind of
35
+ * SITE, not the craft — so every search said "serving bowl portfolio" and
36
+ * the hero asked for "portfolio": a wallet, fashion models, and a blank
37
+ * paper mockup that read as an empty panel beside the brushes.
38
+ * - A hit naming the object anywhere won: a robin tagged "food bowl" filled
39
+ * "Speckled serving bowl", a lilac branch tagged "bud, vase" filled "Tall
40
+ * bud vase", letterpress type tagged "set" filled "Nesting bowl set" (its
41
+ * head noun was read as "set"), and an antique tea set tagged "brown
42
+ * candle" filled "Candle Gift Set".
43
+ * - The page's 20 seconds ran out after four photos (each copy took ~5s, one
44
+ * after another), and the slots left took the starter photos: the laptop
45
+ * desk with pink roses under "Candle Wick Trimmer" and a work card, and the
46
+ * windowsill plants under another.
46
47
  *
47
- * A slot that finds nothing, any error, a refusal from the library (its
48
- * storage band, say) or the time running out leaves the slot to a starter
49
- * photo. Nothing here throws, and none of it is an AI model call: photos cost
50
- * no AI credits.
48
+ * So, for each slot:
49
+ *
50
+ * 1. **The site's terms** ({@link aiStockSiteTerms}): the business is the
51
+ * first clause of its type that says more than what kind of site it is
52
+ * ("ceramic artist" from "a portfolio for a ceramic artist who makes
53
+ * stoneware bowls"), its craft one word ("ceramic"), and its DOMAIN the
54
+ * words a photo of its world names: the craft, the business type's own
55
+ * nouns ("stoneware", "soy") and, for common crafts, their kin ("pottery",
56
+ * "clay", "wax"). Its broad searches ask for the world itself ("handmade
57
+ * ceramics", "pottery").
58
+ * 2. **Search.** A picture of a thing asks for its subject — the noun phrase
59
+ * of the caption, filler dropped — qualified by the craft where it does
60
+ * not already name the domain ("ceramic serving bowl"), then the craft and
61
+ * the object alone ("ceramic bowl"), then the broad searches. A hero asks
62
+ * for the business, then broad; an about picture for the business's
63
+ * people, then broad. The orientation and a minimum size come from the
64
+ * slot's frame.
65
+ * 3. **Accept, or reject.** A hit tagged as a mockup, a blank or a template
66
+ * never fills anything. A picture of a thing takes only a hit naming its
67
+ * OBJECT (the head noun, past "set", "gift", "kit": "bowl" in "nesting
68
+ * bowl set", "candle" in "candle gift set") AND either the site's domain
69
+ * or the subject's own two-word phrase ("bud vase"). A broad, hero or
70
+ * about search takes only a hit naming the domain. The accepted are
71
+ * ranked: the object in the hit's first tags (what the photo is OF) over
72
+ * a mention in its last, the subject's other words, the domain. Among
73
+ * equals the job's seed picks, so two sites differ and one job repeats.
74
+ * 4. **Never twice.** A photo is placed once per job: not twice on a page,
75
+ * and not on a page when another page (or another pass, in this process)
76
+ * of the same job already placed it. The caller hands in what the job's
77
+ * other pages hold (`avoid`); a pass repeated over its own page keeps its
78
+ * own.
79
+ * 5. **Keep, all at once.** The choosing is done first, slot by slot; the
80
+ * copies then run side by side, a few at a time, so a page of eight
81
+ * pictures takes about as long as two. A photo the site's library already
82
+ * holds (by its source key) is reused; otherwise its bytes are copied
83
+ * into the site's own library as the member who started the job, credited
84
+ * to its photographer. A copy that fails tries the slot's next accepted
85
+ * hit.
86
+ *
87
+ * A slot nothing acceptable answered — the library down, refusing, or out
88
+ * of time — is left `null` for the starter photos. A named object is never
89
+ * given one while the library answers anything of the site's world: the
90
+ * broad searches come first. Nothing here throws, and none of it is an AI
91
+ * model call: photos cost no AI credits.
51
92
  */
52
93
  /** Wall clock the whole page's photos may take, inside the step's own signal. */
53
- export declare const AI_LAYOUT_STOCK_PHOTOS_BUDGET_MS = 20000;
54
- /** Searches one page may ask, cached ones included. */
55
- export declare const AI_LAYOUT_STOCK_SEARCHES_PER_PAGE = 8;
94
+ export declare const AI_LAYOUT_STOCK_PHOTOS_BUDGET_MS = 30000;
95
+ /** Searches one page may send to the provider; a repeated query is answered from the page's own memory. */
96
+ export declare const AI_LAYOUT_STOCK_SEARCHES_PER_PAGE = 18;
56
97
  /** The hits a pick is made among. */
57
- export declare const AI_LAYOUT_STOCK_PICK_WINDOW = 8;
98
+ export declare const AI_LAYOUT_STOCK_PICK_WINDOW = 40;
58
99
  /** The largest photo copied: inside one direct upload. */
59
100
  export declare const AI_LAYOUT_STOCK_MAX_BYTES: number;
101
+ /**
102
+ * The unit job input naming the screen drafts the job's other pages were
103
+ * written to, whose photos a page does not place again (AGL-3660).
104
+ */
105
+ export declare const AI_STOCK_PHOTO_PAGES_INPUT = "stockPhotoPages";
106
+ /**
107
+ * A word's singular, for matching only: "bowls" and "bowl", "vases" and
108
+ * "vase", "berries" and "berry", "dishes" and "dish" meet. Both sides of a
109
+ * comparison are reduced the same way, so an odd stem still matches itself.
110
+ */
111
+ export declare function aiStockStem(word: string): string;
60
112
  /**
61
113
  * The kind of business in a few words: the first clause of the business
62
- * type, before a place or an audience, its last three content words (the
63
- * head of an English noun phrase is at its end).
114
+ * type that says more than what kind of site it is, before a place, an
115
+ * audience or what it makes, filler dropped, its last three words (the head
116
+ * of an English noun phrase is at its end). "ceramic artist" from "a
117
+ * portfolio for a ceramic artist who makes stoneware bowls"; "candle shop"
118
+ * from "a small-batch candle shop selling hand-poured soy candles online".
64
119
  */
65
120
  export declare function aiStockBusinessWords(businessType: string): string;
66
- /** A picture's subject in a few words: its alt text's first content words, else its section's name. */
121
+ /**
122
+ * The business's craft in one word: the last of its words that is not the
123
+ * place it is done in nor the person doing it, singular — "ceramic" from
124
+ * "ceramics studio" or "ceramic artist", "yoga" from "yoga studio". Empty
125
+ * when the business is only a place ("a shop").
126
+ */
127
+ export declare function aiStockCraftWords(business: string): string;
128
+ /** What a site's photos are searched and judged by (AGL-3660). */
129
+ export interface AiStockSiteTerms {
130
+ /** The kind of business, in a few words: "ceramic artist". */
131
+ business: string;
132
+ /** Its craft, one singular word: "ceramic". */
133
+ craft: string;
134
+ /**
135
+ * The stems a photo of the site's world names: the business's own words,
136
+ * what the things it makes are made of, and the craft's kin. Empty for a
137
+ * site whose words name no world (a type left blank), and then no hit is
138
+ * held to it.
139
+ */
140
+ domain: string[];
141
+ /** The searches for the site's world itself, broadest last. */
142
+ broad: string[];
143
+ }
144
+ /** The site's terms, read from its business type. */
145
+ export declare function aiStockSiteTerms(businessType: string): AiStockSiteTerms;
146
+ /**
147
+ * A picture's subject in a few words (AGL-3660): the noun phrase its alt
148
+ * text opens with — its first clause holding more than filler, cut where a
149
+ * preposition starts the setting, filler dropped, its last three words (the
150
+ * head noun is the last) — else its section's name.
151
+ */
67
152
  export declare function aiStockSubjectWords(alt: string, sectionName: string): string;
153
+ /**
154
+ * The thing a subject shows, one singular word: its last word that is not
155
+ * a set or a wrapper of it — "bowl" from "nesting bowl set", "candle" from
156
+ * "candle gift set", "vase" from "bud vase". Its last word when every word
157
+ * is one ("gift set").
158
+ */
159
+ export declare function aiStockObjectWord(subject: string): string;
68
160
  /** The frame's orientation: a wide frame wants a landscape photo, a tall one a portrait. */
69
161
  export declare function aiStockOrientation(aspect: number): StockPhotoOrientation;
162
+ /**
163
+ * One search a slot tries. A `broad` one asks for the site's world and
164
+ * takes any hit of it; any other picture of a thing takes only a hit naming
165
+ * the thing.
166
+ */
167
+ export interface AiStockSearch extends StockPhotoSearchRequest {
168
+ broad?: boolean;
169
+ /** The words its hits are scored by, where they are not the slot's own subject (a product's searches, AGL-3676). */
170
+ subject?: string;
171
+ /** A word every hit must name: a product's photo names the shop's category (AGL-3676). */
172
+ requires?: string;
173
+ }
174
+ /**
175
+ * A product's searches (AGL-3676), most specific first: each of its subjects
176
+ * — its name's noun phrase, then its photo's — with the shop's category
177
+ * where the phrase does not already say it ("candle gift box"), then the
178
+ * category alone, a plain photo of what the shop sells. Every one must find a
179
+ * hit naming the category, so no product is ever filled with a lifestyle shot
180
+ * of something else: the beta.237 Willow Wick start put a laptop and roses
181
+ * under "Candle Wick Trimmer" and an antique tea set under "Candle Gift Set".
182
+ */
183
+ export declare function aiStockProductSearches(slot: Pick<AiLayoutPictureSlot, 'aspect' | 'product'>, craft: string): AiStockSearch[];
70
184
  /** The searches a slot tries, in order, most specific first, each distinct. */
71
- export declare function aiStockSearchesFor(slot: Pick<AiLayoutPictureSlot, 'role' | 'alt' | 'aspect'>, words: {
72
- business: string;
73
- subject: string;
74
- }): StockPhotoSearchRequest[];
75
- /** The pick among a search's hits: not on the page yet, among the first few, by the seed. */
76
- export declare function aiStockPick(photos: readonly StockPhoto[], used: ReadonlySet<string>, seed: string): StockPhoto | null;
185
+ export declare function aiStockSearchesFor(slot: Pick<AiLayoutPictureSlot, 'role' | 'alt' | 'aspect'>, terms: Pick<AiStockSiteTerms, 'business' | 'craft' | 'domain' | 'broad'>, subject: string): AiStockSearch[];
186
+ /** What a hit is judged by. */
187
+ export interface AiStockJudgement {
188
+ /** The words the picture is of; empty for a picture of the site's world. */
189
+ subject?: string;
190
+ /** The site's domain stems ({@link AiStockSiteTerms.domain}). */
191
+ domain?: readonly string[];
192
+ /**
193
+ * Whether a hit must name the subject's object. A broad search, a hero
194
+ * and an about picture need only name the domain.
195
+ */
196
+ strict?: boolean;
197
+ /** A word every hit must name: a product's photo names the shop's category (AGL-3676). */
198
+ requires?: string;
199
+ }
200
+ /**
201
+ * How well a hit shows what a slot needs (AGL-3660), or 0 when it must not
202
+ * fill it: a mockup or a blank never; a picture of a thing only when the hit
203
+ * names its object AND either the site's world or the subject's own
204
+ * two-word phrase ("bud vase", "wick trimmer"); anything else only when it
205
+ * names the site's world (when the site names one). Among the accepted, the
206
+ * object among the hit's first tags counts 4 (a mention among its last, 2),
207
+ * the subject's two-word phrase 3, each of its other words 1, and the
208
+ * site's world 1, plus a quarter when it is among the first tags.
209
+ */
210
+ export declare function aiStockRelevance(photo: Pick<StockPhoto, 'tags' | 'alt' | 'pageUrl'>, judgement: AiStockJudgement): number;
211
+ /**
212
+ * A search's acceptable hits in the order they are tried (AGL-3660): those
213
+ * not placed yet, among the first few the library returned, those it must
214
+ * not take dropped ({@link aiStockRelevance}), best first; the seed turns
215
+ * the hits that score alike, so two jobs differ and one job repeats itself.
216
+ */
217
+ export declare function aiStockRank(photos: readonly StockPhoto[], used: ReadonlySet<string>, seed: string, judgement?: AiStockJudgement): StockPhoto[];
218
+ /** The pick among a search's hits: the first {@link aiStockRank} would try, or `null`. */
219
+ export declare function aiStockPick(photos: readonly StockPhoto[], used: ReadonlySet<string>, seed: string, judgement?: AiStockJudgement): StockPhoto | null;
220
+ /**
221
+ * The library photos a stored page already shows: every `image` whose
222
+ * source is the site's media reference. Starter photos are the platform's,
223
+ * not the job's, and are not listed.
224
+ */
225
+ export declare function aiStockPlacedSrcs(nodes: NodesMap | null | undefined): string[];
226
+ /** Forgets every job's placed photos; for specs. */
227
+ export declare function aiStockForgetJobPhotos(): void;
77
228
  export interface AiLayoutStockPhotoSourceInput {
78
229
  hostId: string;
79
230
  /** The member the photos are stored as: the job's creator. */
80
231
  uid: string;
81
- /** The job's seed, as the starter photos turn by. */
232
+ /** The job's seed, as the starter photos turn by; also the scope a photo is placed under. */
82
233
  seed: string;
83
234
  /** The site's business type, else the job's brief. */
84
235
  business: string;
85
236
  /** The page's section names, by plan index. */
86
237
  sectionNames: readonly string[];
238
+ /**
239
+ * The job the member started (`aiOriginJobId`), so a photo is placed once
240
+ * across its pages. Absent, only the page itself is kept free of repeats.
241
+ */
242
+ jobId?: string;
243
+ /** Asset srcs or source keys the job's other pages already show. */
244
+ avoid?: readonly string[];
245
+ /** The most searches this source sends; a page's own bound where absent. A store's products search more (AGL-3676). */
246
+ searches?: number;
87
247
  signal?: AbortSignal;
88
248
  }
89
249
  export interface AiLayoutStockPhotoDeps {