@aglyn/plugins-ai 1.0.0-beta.268 → 1.0.0-beta.270

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 (60) hide show
  1. package/package.json +17 -17
  2. package/src/lib/components/ai-credits-card.component.d.ts +4 -3
  3. package/src/lib/components/ai-credits-card.component.js +25 -8
  4. package/src/lib/components/ai-credits-card.component.js.map +1 -1
  5. package/src/lib/components/ai-job-links.d.ts +6 -0
  6. package/src/lib/components/ai-job-links.js +9 -0
  7. package/src/lib/components/ai-job-links.js.map +1 -1
  8. package/src/lib/components/ai-products-hub-card.component.d.ts +6 -0
  9. package/src/lib/components/ai-products-hub-card.component.js +21 -6
  10. package/src/lib/components/ai-products-hub-card.component.js.map +1 -1
  11. package/src/lib/components/ai-site-build-page.component.js +3 -2
  12. package/src/lib/components/ai-site-build-page.component.js.map +1 -1
  13. package/src/lib/components/ai-store-finish-card.component.d.ts +14 -3
  14. package/src/lib/components/ai-store-finish-card.component.js +67 -9
  15. package/src/lib/components/ai-store-finish-card.component.js.map +1 -1
  16. package/src/lib/components/assist-build-card.component.js +3 -2
  17. package/src/lib/components/assist-build-card.component.js.map +1 -1
  18. package/src/lib/jobs/ai-job-build-step.d.ts +3 -0
  19. package/src/lib/jobs/ai-job-build-step.js +8 -2
  20. package/src/lib/jobs/ai-job-build-step.js.map +1 -1
  21. package/src/lib/jobs/ai-job-form-step.d.ts +9 -0
  22. package/src/lib/jobs/ai-job-form-step.js +21 -2
  23. package/src/lib/jobs/ai-job-form-step.js.map +1 -1
  24. package/src/lib/jobs/ai-job-page-language.d.ts +26 -9
  25. package/src/lib/jobs/ai-job-page-language.js +46 -3
  26. package/src/lib/jobs/ai-job-page-language.js.map +1 -1
  27. package/src/lib/jobs/ai-job-page-step.js +4 -2
  28. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  29. package/src/lib/jobs/ai-job-site-look.d.ts +2 -1
  30. package/src/lib/jobs/ai-job-site-look.js +6 -2
  31. package/src/lib/jobs/ai-job-site-look.js.map +1 -1
  32. package/src/lib/jobs/ai-job-site-step.js +11 -6
  33. package/src/lib/jobs/ai-job-site-step.js.map +1 -1
  34. package/src/lib/jobs/ai-layout-owner-photos.d.ts +57 -0
  35. package/src/lib/jobs/ai-layout-owner-photos.js +110 -0
  36. package/src/lib/jobs/ai-layout-owner-photos.js.map +1 -0
  37. package/src/lib/jobs/ai-layout-stock-photos.d.ts +51 -10
  38. package/src/lib/jobs/ai-layout-stock-photos.js +812 -121
  39. package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
  40. package/src/lib/jobs/fixtures/ai-stock-photo-agl3942-recordings.d.ts +29 -0
  41. package/src/lib/jobs/fixtures/ai-stock-photo-agl3942-recordings.js +291 -0
  42. package/src/lib/jobs/fixtures/ai-stock-photo-agl3942-recordings.js.map +1 -0
  43. package/src/lib/jobs/fixtures/ai-stock-photo-brightvale-recordings.d.ts +4 -0
  44. package/src/lib/jobs/fixtures/ai-stock-photo-brightvale-recordings.js +87 -1
  45. package/src/lib/jobs/fixtures/ai-stock-photo-brightvale-recordings.js.map +1 -1
  46. package/src/lib/jobs/fixtures/ai-stock-photo-mexicano-recordings.d.ts +31 -0
  47. package/src/lib/jobs/fixtures/ai-stock-photo-mexicano-recordings.js +325 -0
  48. package/src/lib/jobs/fixtures/ai-stock-photo-mexicano-recordings.js.map +1 -0
  49. package/src/lib/layout-language/ai-layout-motion.d.ts +60 -7
  50. package/src/lib/layout-language/ai-layout-motion.js +231 -4
  51. package/src/lib/layout-language/ai-layout-motion.js.map +1 -1
  52. package/src/lib/layout-language/ai-layout-pictures.d.ts +8 -0
  53. package/src/lib/layout-language/ai-layout-pictures.js +68 -4
  54. package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
  55. package/src/lib/model/ai-site-look.d.ts +10 -1
  56. package/src/lib/model/ai-site-look.js +14 -3
  57. package/src/lib/model/ai-site-look.js.map +1 -1
  58. package/src/lib/native-nav.d.ts +26 -0
  59. package/src/lib/native-nav.js +58 -0
  60. package/src/lib/native-nav.js.map +1 -0
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import type { PluginMediaAsset } from '@aglyn/aglyn/plugin-manager/plugin-media-ingest';
18
+ import type { AiLayoutPicturePhoto, AiLayoutPictureSlot, AiLayoutPictureSource } from '../layout-language/ai-layout-pictures';
19
+ import { aiLayoutStockPhotoSource, type AiLayoutStockPhotoDeps, type AiLayoutStockPhotoSourceInput } from './ai-layout-stock-photos';
20
+ /**
21
+ * THE BUSINESS'S OWN PHOTOS COME FIRST (AGL-3957).
22
+ *
23
+ * A site built for an owner at a booth or on a doorstep has, by the time its
24
+ * pages are drawn, the photos they sent from their phone through a site
25
+ * photo link: their van, their shop, their work. A photo of the owner's own
26
+ * work beats any stock photo, so a page's picture slots are filled from
27
+ * those first, and only the slots left over are searched for in the stock
28
+ * library, the way they were before.
29
+ *
30
+ * Which photo goes where is decided by shape and size, not by subject: an
31
+ * owner's photo says nothing a search could read. The hero takes the widest
32
+ * photo among the largest; the about picture takes the next largest; the
33
+ * gallery takes the rest, newest first, each photo once on the page and once
34
+ * across the job (`avoid`). A product's photo, a person's portrait and a
35
+ * record's cover are of one named thing, which a photo of the business in
36
+ * general is not, so those slots go to the stock search untouched.
37
+ */
38
+ export interface AiLayoutOwnerPhotoDeps extends AiLayoutStockPhotoDeps {
39
+ /** The stock source the leftover slots go to; the real one otherwise. Specs hand in a fake. */
40
+ stock?: typeof aiLayoutStockPhotoSource;
41
+ /** The most owner photos read for one page. */
42
+ limit?: number;
43
+ }
44
+ /** A slot an owner's photo may fill: one of the business in general, not of one named thing. */
45
+ export declare function aiOwnerPhotoFits(slot: AiLayoutPictureSlot): boolean;
46
+ /**
47
+ * Assigns the owner's photos to the slots, in the order above. Pure, so a
48
+ * spec can hold the choice itself: `null` for a slot left to the stock
49
+ * search, in slot order.
50
+ */
51
+ export declare function aiAssignOwnerPhotos(slots: readonly AiLayoutPictureSlot[], photos: readonly PluginMediaAsset[], avoid?: ReadonlySet<string>): Array<AiLayoutPicturePhoto | null>;
52
+ /**
53
+ * The source for one page: the owner's photos for the slots they fit, the
54
+ * stock library for the rest. `null` only when neither can answer — no
55
+ * media door and no stock library — which leaves every slot to the starters.
56
+ */
57
+ export declare function aiLayoutSitePhotoSource(input: AiLayoutStockPhotoSourceInput, deps?: AiLayoutOwnerPhotoDeps): AiLayoutPictureSource | null;
@@ -0,0 +1,110 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { _ as _extends } from "@swc/helpers/_/_extends";
17
+ import { pluginMediaIngest } from "@aglyn/aglyn/plugin-manager/plugin-media-ingest";
18
+ import { aiLayoutStockPhotoSource } from "./ai-layout-stock-photos.js";
19
+ const OWNER_PHOTOS_LIMIT = 60;
20
+ /** A slot an owner's photo may fill: one of the business in general, not of one named thing. */ export function aiOwnerPhotoFits(slot) {
21
+ return !slot.product && !slot.people && !slot.record;
22
+ }
23
+ /** Fill order: the hero first, so the biggest photo is the first one seen; then about; then the gallery in document order. */ const ROLE_RANK = {
24
+ hero: 0,
25
+ about: 1,
26
+ gallery: 2
27
+ };
28
+ function area(photo) {
29
+ var _photo_width, _photo_height;
30
+ return ((_photo_width = photo.width) != null ? _photo_width : 0) * ((_photo_height = photo.height) != null ? _photo_height : 0);
31
+ }
32
+ /**
33
+ * Assigns the owner's photos to the slots, in the order above. Pure, so a
34
+ * spec can hold the choice itself: `null` for a slot left to the stock
35
+ * search, in slot order.
36
+ */ export function aiAssignOwnerPhotos(slots, photos, avoid = new Set()) {
37
+ const pool = photos.filter((photo)=>{
38
+ var _photo_width, _photo_height;
39
+ return photo.src && ((_photo_width = photo.width) != null ? _photo_width : 0) > 0 && ((_photo_height = photo.height) != null ? _photo_height : 0) > 0 && !avoid.has(photo.src);
40
+ }).sort((a, b)=>area(b) - area(a));
41
+ const answers = slots.map(()=>null);
42
+ const used = new Set();
43
+ const order = slots.map((slot, index)=>({
44
+ slot,
45
+ index
46
+ })).filter(({ slot })=>aiOwnerPhotoFits(slot)).sort((a, b)=>ROLE_RANK[a.slot.role] - ROLE_RANK[b.slot.role] || a.index - b.index);
47
+ for (const { slot, index } of order){
48
+ const free = pool.filter((photo)=>!used.has(photo.src));
49
+ if (!free.length) break;
50
+ // The hero wants the widest of the three largest; a portrait phone photo
51
+ // in a wide frame is the one mismatch a visitor sees first.
52
+ const pick = slot.role === 'hero' ? [
53
+ ...free.slice(0, 3)
54
+ ].sort((a, b)=>{
55
+ var _b_width, _b_height, _a_width, _a_height;
56
+ return ((_b_width = b.width) != null ? _b_width : 0) / ((_b_height = b.height) != null ? _b_height : 1) - ((_a_width = a.width) != null ? _a_width : 0) / ((_a_height = a.height) != null ? _a_height : 1);
57
+ })[0] : free[0];
58
+ if (!pick) break;
59
+ used.add(pick.src);
60
+ answers[index] = _extends({
61
+ src: pick.src,
62
+ width: pick.width,
63
+ height: pick.height
64
+ }, pick.alt ? {
65
+ alt: pick.alt
66
+ } : {});
67
+ }
68
+ return answers;
69
+ }
70
+ /**
71
+ * The source for one page: the owner's photos for the slots they fit, the
72
+ * stock library for the rest. `null` only when neither can answer — no
73
+ * media door and no stock library — which leaves every slot to the starters.
74
+ */ export function aiLayoutSitePhotoSource(input, deps = {}) {
75
+ var _deps_stock, _deps_ingest;
76
+ var _ingest_listOwnerPhotos;
77
+ const stock = ((_deps_stock = deps.stock) != null ? _deps_stock : aiLayoutStockPhotoSource)(input, deps);
78
+ const ingest = ((_deps_ingest = deps.ingest) != null ? _deps_ingest : pluginMediaIngest)();
79
+ const list = ingest == null ? void 0 : (_ingest_listOwnerPhotos = ingest.listOwnerPhotos) == null ? void 0 : _ingest_listOwnerPhotos.bind(ingest);
80
+ if (!list || !input.hostId) return stock;
81
+ return async (slots)=>{
82
+ var _input_avoid;
83
+ let photos = [];
84
+ try {
85
+ var _deps_limit;
86
+ photos = await list({
87
+ hostId: input.hostId,
88
+ limit: (_deps_limit = deps.limit) != null ? _deps_limit : OWNER_PHOTOS_LIMIT
89
+ });
90
+ } catch (error) {
91
+ console.warn('ai layout pictures: the owner photos could not be read; stock photos fill the page', {
92
+ error
93
+ });
94
+ }
95
+ const answers = aiAssignOwnerPhotos(slots, photos, new Set((_input_avoid = input.avoid) != null ? _input_avoid : []));
96
+ if (!stock) return answers;
97
+ const open = slots.filter((_slot, index)=>!answers[index]);
98
+ if (!open.length) return answers;
99
+ // The stock source sees only the slots the owner's photos left, so its
100
+ // own no-repeat rules and search budget are spent on those alone.
101
+ const found = await stock(open);
102
+ let next = 0;
103
+ return answers.map((answer)=>{
104
+ var _ref;
105
+ return (_ref = answer != null ? answer : found[next++]) != null ? _ref : null;
106
+ });
107
+ };
108
+ }
109
+
110
+ //# sourceMappingURL=ai-layout-owner-photos.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/jobs/ai-layout-owner-photos.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 type { PluginMediaAsset } from '@aglyn/aglyn/plugin-manager/plugin-media-ingest'\nimport { pluginMediaIngest } from '@aglyn/aglyn/plugin-manager/plugin-media-ingest'\nimport type {\n AiLayoutPicturePhoto,\n AiLayoutPictureSlot,\n AiLayoutPictureSource,\n} from '../layout-language/ai-layout-pictures'\nimport {\n aiLayoutStockPhotoSource,\n type AiLayoutStockPhotoDeps,\n type AiLayoutStockPhotoSourceInput,\n} from './ai-layout-stock-photos'\n\n/**\n * THE BUSINESS'S OWN PHOTOS COME FIRST (AGL-3957).\n *\n * A site built for an owner at a booth or on a doorstep has, by the time its\n * pages are drawn, the photos they sent from their phone through a site\n * photo link: their van, their shop, their work. A photo of the owner's own\n * work beats any stock photo, so a page's picture slots are filled from\n * those first, and only the slots left over are searched for in the stock\n * library, the way they were before.\n *\n * Which photo goes where is decided by shape and size, not by subject: an\n * owner's photo says nothing a search could read. The hero takes the widest\n * photo among the largest; the about picture takes the next largest; the\n * gallery takes the rest, newest first, each photo once on the page and once\n * across the job (`avoid`). A product's photo, a person's portrait and a\n * record's cover are of one named thing, which a photo of the business in\n * general is not, so those slots go to the stock search untouched.\n */\n\nexport interface AiLayoutOwnerPhotoDeps extends AiLayoutStockPhotoDeps {\n /** The stock source the leftover slots go to; the real one otherwise. Specs hand in a fake. */\n stock?: typeof aiLayoutStockPhotoSource\n /** The most owner photos read for one page. */\n limit?: number\n}\n\nconst OWNER_PHOTOS_LIMIT = 60\n\n/** A slot an owner's photo may fill: one of the business in general, not of one named thing. */\nexport function aiOwnerPhotoFits(slot: AiLayoutPictureSlot): boolean {\n return !slot.product && !slot.people && !slot.record\n}\n\n/** Fill order: the hero first, so the biggest photo is the first one seen; then about; then the gallery in document order. */\nconst ROLE_RANK = { hero: 0, about: 1, gallery: 2 } as const\n\nfunction area(photo: PluginMediaAsset): number {\n return (photo.width ?? 0) * (photo.height ?? 0)\n}\n\n/**\n * Assigns the owner's photos to the slots, in the order above. Pure, so a\n * spec can hold the choice itself: `null` for a slot left to the stock\n * search, in slot order.\n */\nexport function aiAssignOwnerPhotos(\n slots: readonly AiLayoutPictureSlot[],\n photos: readonly PluginMediaAsset[],\n avoid: ReadonlySet<string> = new Set(),\n): Array<AiLayoutPicturePhoto | null> {\n const pool = photos\n .filter((photo) => photo.src && (photo.width ?? 0) > 0 && (photo.height ?? 0) > 0 && !avoid.has(photo.src))\n .sort((a, b) => area(b) - area(a))\n const answers: Array<AiLayoutPicturePhoto | null> = slots.map(() => null)\n const used = new Set<string>()\n const order = slots\n .map((slot, index) => ({ slot, index }))\n .filter(({ slot }) => aiOwnerPhotoFits(slot))\n .sort((a, b) => ROLE_RANK[a.slot.role] - ROLE_RANK[b.slot.role] || a.index - b.index)\n for (const { slot, index } of order) {\n const free = pool.filter((photo) => !used.has(photo.src))\n if (!free.length) break\n // The hero wants the widest of the three largest; a portrait phone photo\n // in a wide frame is the one mismatch a visitor sees first.\n const pick =\n slot.role === 'hero'\n ? [...free.slice(0, 3)].sort(\n (a, b) => (b.width ?? 0) / (b.height ?? 1) - (a.width ?? 0) / (a.height ?? 1),\n )[0]\n : free[0]\n if (!pick) break\n used.add(pick.src)\n answers[index] = {\n src: pick.src,\n width: pick.width as number,\n height: pick.height as number,\n ...(pick.alt ? { alt: pick.alt } : {}),\n }\n }\n return answers\n}\n\n/**\n * The source for one page: the owner's photos for the slots they fit, the\n * stock library for the rest. `null` only when neither can answer — no\n * media door and no stock library — which leaves every slot to the starters.\n */\nexport function aiLayoutSitePhotoSource(\n input: AiLayoutStockPhotoSourceInput,\n deps: AiLayoutOwnerPhotoDeps = {},\n): AiLayoutPictureSource | null {\n const stock = (deps.stock ?? aiLayoutStockPhotoSource)(input, deps)\n const ingest = (deps.ingest ?? pluginMediaIngest)()\n const list = ingest?.listOwnerPhotos?.bind(ingest)\n if (!list || !input.hostId) return stock\n return async (slots) => {\n let photos: PluginMediaAsset[] = []\n try {\n photos = await list({ hostId: input.hostId, limit: deps.limit ?? OWNER_PHOTOS_LIMIT })\n } catch (error) {\n console.warn('ai layout pictures: the owner photos could not be read; stock photos fill the page', { error })\n }\n const answers = aiAssignOwnerPhotos(slots, photos, new Set(input.avoid ?? []))\n if (!stock) return answers\n const open = slots.filter((_slot, index) => !answers[index])\n if (!open.length) return answers\n // The stock source sees only the slots the owner's photos left, so its\n // own no-repeat rules and search budget are spent on those alone.\n const found = await stock(open)\n let next = 0\n return answers.map((answer) => answer ?? found[next++] ?? null)\n }\n}\n"],"names":["pluginMediaIngest","aiLayoutStockPhotoSource","OWNER_PHOTOS_LIMIT","aiOwnerPhotoFits","slot","product","people","record","ROLE_RANK","hero","about","gallery","area","photo","width","height","aiAssignOwnerPhotos","slots","photos","avoid","Set","pool","filter","src","has","sort","a","b","answers","map","used","order","index","role","free","length","pick","slice","add","alt","aiLayoutSitePhotoSource","input","deps","ingest","stock","list","listOwnerPhotos","bind","hostId","limit","error","console","warn","open","_slot","found","next","answer"],"mappings":"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"}
@@ -243,6 +243,12 @@ export interface AiStockSiteTerms {
243
243
  setting?: string;
244
244
  /** The craft's maker and tools as stems, which a record of its work never leads with ({@link CRAFT_KIN}, AGL-3856). */
245
245
  maker?: string[];
246
+ /**
247
+ * What a craft whose pictures are people at a moment shows wherever a page
248
+ * would show its maker ({@link aiStockWorkScenes}, AGL-3942): the scenes
249
+ * its site's own words name, set where the site is.
250
+ */
251
+ work?: AiStockScene[];
246
252
  }
247
253
  /** The site's terms, read from its business type. */
248
254
  export declare function aiStockSiteTerms(businessType: string): AiStockSiteTerms;
@@ -308,6 +314,8 @@ export interface AiStockSearch extends StockPhotoSearchRequest {
308
314
  refuseLead?: readonly string[];
309
315
  /** Whether its hits are held to no world of the site's: a portfolio's record is of its subject, never of the craft (AGL-3856). */
310
316
  worldless?: boolean;
317
+ /** Stems of the places its hits are not set in, which none of their first tags name: a Blue Ridge couple's beach ({@link aiStockSettingAway}, AGL-3942). */
318
+ away?: readonly string[];
311
319
  /** Whether it fills a product: no room, no scene, no fragrance bottle ({@link PRODUCT_SCENES}, AGL-3660). */
312
320
  product?: boolean;
313
321
  /** Words its hits never carry unless the slot or the brief names them ({@link AiStockSiteTerms.shun}). */
@@ -355,6 +363,8 @@ export declare function aiStockRoleRefusals(role: Pick<AiStockPeopleRole, 'refus
355
363
  * anywhere on it, whatever else its words name ("school").
356
364
  */
357
365
  export declare function aiStockAdultsOnly(texts: ReadonlyArray<string | undefined>): boolean;
366
+ /** The stems of the places a setting is not ({@link SCENE_SETTINGS}); none for no setting. */
367
+ export declare function aiStockSettingAway(setting: string): string[];
358
368
  /** What a picture of a moment shows ({@link aiStockScene}). */
359
369
  export interface AiStockScene {
360
370
  /** The searches that ask for it, the people and their setting first. */
@@ -369,6 +379,8 @@ export interface AiStockScene {
369
379
  shun: string[];
370
380
  /** The stems of its words, which let in what they name: a family's children. */
371
381
  named: string[];
382
+ /** Stems of the places it is not set in, which none of a photo's first tags name ({@link aiStockSettingAway}, AGL-3942). */
383
+ away: string[];
372
384
  }
373
385
  /**
374
386
  * The scene a picture's words name (AGL-3856): the people at a moment, and
@@ -377,7 +389,7 @@ export interface AiStockScene {
377
389
  * family in autumn — read from every word, never only the first clause.
378
390
  * `null` where it names no people.
379
391
  */
380
- export declare function aiStockScene(text: string): AiStockScene | null;
392
+ export declare function aiStockScene(text: string, siteSetting?: string): AiStockScene | null;
381
393
  /** Where a text's words set a picture ({@link SCENE_SETTINGS}): "mountains" of "Couples planning mountain weddings"; empty for none. */
382
394
  export declare function aiStockSetting(text: string): string;
383
395
  /**
@@ -391,6 +403,17 @@ export declare function aiStockSetting(text: string): string;
391
403
  * neither names people at a moment nor a portrait.
392
404
  */
393
405
  export declare function aiStockRecordScene(name: string, category?: string, siteSetting?: string): AiStockScene | null;
406
+ /**
407
+ * The work a craft whose pictures are people at a moment shows (AGL-3942):
408
+ * the scenes its site's own words name, in the order they name them, each
409
+ * set where the site is — a wedding photographer "for couples planning
410
+ * mountain weddings, and families" shows a wedding couple in the mountains
411
+ * and a family in the mountains. A family session still never shows a
412
+ * bride, whatever else the site names. Empty where its words name no people.
413
+ */
414
+ export declare function aiStockWorkScenes(text: string, setting?: string): AiStockScene[];
415
+ /** Whether a setting is a place a photo shows on its own, a landscape searched by its name: "mountains", never "autumn". */
416
+ export declare function aiStockSettingIsLandscape(setting: string): boolean;
394
417
  /** What a product falls back to once its own searches find nothing ({@link aiStockProductSearches}). */
395
418
  export interface AiStockProductFallback {
396
419
  /** The site's broad searches ({@link AiStockSiteTerms.broad}): "handmade soap". */
@@ -451,7 +474,15 @@ export declare function aiStockProductSearches(slot: Pick<AiLayoutPictureSlot, '
451
474
  * asks first for the role its words or its list's name (`sectionName`) say,
452
475
  * in the site's world: "teacher classroom" for a "Math instructor" (AGL-3856).
453
476
  */
454
- export declare function aiStockSearchesFor(slot: Pick<AiLayoutPictureSlot, 'role' | 'alt' | 'aspect' | 'people' | 'record' | 'product'>, terms: Pick<AiStockSiteTerms, 'business' | 'craft' | 'domain' | 'broad'> & Partial<Pick<AiStockSiteTerms, 'making' | 'core' | 'scenes' | 'setting' | 'maker'>>, subject: string, part?: AiStockSlotPart, sectionName?: string): AiStockSearch[];
477
+ export declare function aiStockSearchesFor(slot: Pick<AiLayoutPictureSlot, 'role' | 'alt' | 'aspect' | 'people' | 'record' | 'product'>, terms: Pick<AiStockSiteTerms, 'business' | 'craft' | 'domain' | 'broad'> & Partial<Pick<AiStockSiteTerms, 'making' | 'core' | 'scenes' | 'setting' | 'maker' | 'work'>>, subject: string, part?: AiStockSlotPart, sectionName?: string): AiStockSearch[];
478
+ /**
479
+ * Whether a picture of a craft's site whose pictures are people at a moment
480
+ * shows that work wherever a page would show the maker (AGL-3942): an about
481
+ * picture, a story of the craft, an intro's cover. Not a record (which shows
482
+ * its own moment, {@link aiStockShowsTheWork}), a portrait of the business's
483
+ * people, nor a product; and only where the site's words name the work.
484
+ */
485
+ export declare function aiStockShowsItsWork(slot: Pick<AiLayoutPictureSlot, 'record' | 'people' | 'product'>, terms: Partial<Pick<AiStockSiteTerms, 'scenes' | 'work'>>): boolean;
455
486
  /**
456
487
  * Whether a slot is a portfolio's record of a craft whose work is people at a
457
488
  * moment (AGL-3856): a photographer's "Mountain Elopements" shows an
@@ -512,6 +543,8 @@ export interface AiStockJudgement {
512
543
  roleScene?: readonly string[];
513
544
  /** Stems of something else being done, which none of a hit's first tags may name ({@link AiStockPeopleRole.refuse}). */
514
545
  roleRefuse?: readonly string[];
546
+ /** Stems of the places the picture is not set in, which none of a hit's first tags may name ({@link AiStockSearch.away}). */
547
+ away?: readonly string[];
515
548
  }
516
549
  /**
517
550
  * Whether a hit carries a topic its site never named ({@link SENSITIVE_TOPICS}):
@@ -718,6 +751,8 @@ export declare function aiStockIsAbbreviation(businessType: string): boolean;
718
751
  export declare function aiStockNamedKind(text: string): string;
719
752
  /** What a kind of site's pictures are searched and judged by ({@link KIND_SUBJECTS}); `null` for a kind not listed. */
720
753
  export declare function aiStockKindTerms(kind: string): AiStockSiteTerms | null;
754
+ /** A kind of site's common photos as a world to search and judge by ({@link KIND_GENERIC}); `null` for a kind with no set. */
755
+ export declare function aiStockKindGenericTerms(kind: string): AiStockSiteTerms | null;
721
756
  /**
722
757
  * Whether a site's world is only its own words (AGL-3923): no craft this
723
758
  * module lists and no kind of site named it, so its broad searches are its
@@ -727,20 +762,26 @@ export declare function aiStockKindTerms(kind: string): AiStockSiteTerms | null;
727
762
  export declare function aiStockWorldIsUnlisted(terms: Pick<AiStockSiteTerms, 'business' | 'craft' | 'broad'>): boolean;
728
763
  /**
729
764
  * What a picture is searched by once nothing narrower found it a photo
730
- * (AGL-3923), widest last: the kind of site the person picked, the kind its
731
- * starter is the shape of, and the starter's own common photos
732
- * ({@link STARTER_GENERIC}). Only a site whose world is its own words alone
733
- * ({@link aiStockWorldIsUnlisted}) widens: a craft this module lists, or a
734
- * world read from the kind of site, keeps its slots to that world, and a slot
735
- * nothing in it fits keeps no photo rather than an office (AGL-3831). A rung
736
- * that would search what an earlier one did is left out.
765
+ * (AGL-3923), widest last.
766
+ *
767
+ * - A site whose world is its own words alone ({@link aiStockWorldIsUnlisted})
768
+ * widens to the kind of site the person picked, the kind its starter is the
769
+ * shape of, and last the kind's own common photos ({@link KIND_GENERIC}),
770
+ * else its starter's.
771
+ * - Any other site widens only to its kind's own common photos, and only
772
+ * where its world agrees with that kind ({@link worldOfKind}): a portfolio
773
+ * read from its kind takes art supplies before no photo at all, and a
774
+ * barbecue caterer whose kind says nothing of food never takes an office
775
+ * (AGL-3831). A kind with no set keeps a slot nothing fits without a photo.
776
+ *
777
+ * A rung that would search what an earlier one did is left out.
737
778
  *
738
779
  * The beta.265 Kasvora Marketing Solutions start (job BK3r4I8bF1) typed its
739
780
  * business as "Freelencing site offer services": its world was the one word
740
781
  * "freelencing", which no library tags, so its cover hero searched it, found
741
782
  * nothing, and shipped a flat dark band with no photo.
742
783
  */
743
- export declare function aiStockWiderTerms(terms: Pick<AiStockSiteTerms, 'business' | 'craft' | 'broad'>, kind: string): Array<{
784
+ export declare function aiStockWiderTerms(terms: Pick<AiStockSiteTerms, 'business' | 'craft' | 'broad' | 'domain'>, kind: string): Array<{
744
785
  rung: 'kind' | 'starter' | 'generic';
745
786
  terms: AiStockSiteTerms;
746
787
  }>;