@aglyn/plugins-ai 1.0.0-beta.238 → 1.0.0-beta.240
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.
- package/package.json +17 -17
- package/src/lib/components/ai-job-links.js +8 -0
- package/src/lib/components/ai-job-links.js.map +1 -1
- package/src/lib/components/ai-job-requests.d.ts +5 -0
- package/src/lib/components/ai-job-requests.js +4 -2
- package/src/lib/components/ai-job-requests.js.map +1 -1
- package/src/lib/components/ai-jobs-store.d.ts +12 -0
- package/src/lib/components/ai-jobs-store.js +15 -0
- package/src/lib/components/ai-jobs-store.js.map +1 -1
- package/src/lib/components/ai-usage-meter-refresh.d.ts +35 -0
- package/src/lib/components/ai-usage-meter-refresh.js +63 -0
- package/src/lib/components/ai-usage-meter-refresh.js.map +1 -0
- package/src/lib/components/assist-panel.component.js +17 -1
- package/src/lib/components/assist-panel.component.js.map +1 -1
- package/src/lib/components/use-ai-usage-meter.d.ts +2 -0
- package/src/lib/components/use-ai-usage-meter.js +8 -3
- package/src/lib/components/use-ai-usage-meter.js.map +1 -1
- package/src/lib/jobs/ai-build-unit-outcome.d.ts +3 -1
- package/src/lib/jobs/ai-build-unit-outcome.js +19 -3
- package/src/lib/jobs/ai-build-unit-outcome.js.map +1 -1
- package/src/lib/jobs/ai-job-build-step.js +29 -2
- package/src/lib/jobs/ai-job-build-step.js.map +1 -1
- package/src/lib/jobs/ai-job-draft-ids.js +7 -2
- package/src/lib/jobs/ai-job-draft-ids.js.map +1 -1
- package/src/lib/jobs/ai-job-form-dataset.d.ts +100 -0
- package/src/lib/jobs/ai-job-form-dataset.js +161 -0
- package/src/lib/jobs/ai-job-form-dataset.js.map +1 -0
- package/src/lib/jobs/ai-job-form-step.d.ts +15 -3
- package/src/lib/jobs/ai-job-form-step.js +37 -9
- package/src/lib/jobs/ai-job-form-step.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-language.js +7 -2
- package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
- package/src/lib/jobs/ai-job-page-language.d.ts +9 -0
- package/src/lib/jobs/ai-job-page-language.js +44 -4
- package/src/lib/jobs/ai-job-page-language.js.map +1 -1
- package/src/lib/jobs/ai-job-page-sections.js +13 -2
- package/src/lib/jobs/ai-job-page-sections.js.map +1 -1
- package/src/lib/jobs/ai-job-page-step.js +32 -2
- package/src/lib/jobs/ai-job-page-step.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-step.d.ts +18 -0
- package/src/lib/jobs/ai-job-plan-step.js +41 -4
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-datasets.d.ts +183 -0
- package/src/lib/jobs/ai-job-site-datasets.js +530 -0
- package/src/lib/jobs/ai-job-site-datasets.js.map +1 -0
- package/src/lib/jobs/ai-job-site-step.d.ts +15 -8
- package/src/lib/jobs/ai-job-site-step.js +148 -29
- package/src/lib/jobs/ai-job-site-step.js.map +1 -1
- package/src/lib/jobs/fixtures/ai-dataset-site-plan-recordings.d.ts +30 -0
- package/src/lib/jobs/fixtures/ai-dataset-site-plan-recordings.js +637 -0
- package/src/lib/jobs/fixtures/ai-dataset-site-plan-recordings.js.map +1 -0
- package/src/lib/layout-language/ai-layout-compiler.d.ts +10 -0
- package/src/lib/layout-language/ai-layout-compiler.js +93 -1
- package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
- package/src/lib/layout-language/ai-layout-gaps.js +17 -1
- package/src/lib/layout-language/ai-layout-gaps.js.map +1 -1
- package/src/lib/layout-language/ai-layout-listings.d.ts +32 -3
- package/src/lib/layout-language/ai-layout-listings.js +62 -9
- package/src/lib/layout-language/ai-layout-listings.js.map +1 -1
- package/src/lib/layout-language/ai-layout-pictures.js +12 -4
- package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
- package/src/lib/model/ai-build-job.d.ts +2 -0
- package/src/lib/model/ai-build-job.js +16 -1
- package/src/lib/model/ai-build-job.js.map +1 -1
- package/src/lib/model/ai-build-plan.d.ts +23 -3
- package/src/lib/model/ai-build-plan.js +47 -6
- package/src/lib/model/ai-build-plan.js.map +1 -1
- package/src/lib/model/ai-plan-capabilities.d.ts +7 -0
- package/src/lib/model/ai-plan-capabilities.js.map +1 -1
- package/src/lib/model/ai-site-job.d.ts +19 -2
- package/src/lib/model/ai-site-job.js +21 -6
- package/src/lib/model/ai-site-job.js.map +1 -1
- package/src/lib/runtime/ai-dataset-generation.d.ts +77 -0
- package/src/lib/runtime/ai-dataset-generation.js +127 -0
- package/src/lib/runtime/ai-dataset-generation.js.map +1 -0
- package/src/lib/runtime/ai-doctrine-validators.d.ts +84 -0
- package/src/lib/runtime/ai-doctrine-validators.js +307 -1
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-doctrine.js +10 -4
- package/src/lib/runtime/ai-doctrine.js.map +1 -1
- package/src/lib/runtime/ai-node-tree.d.ts +2 -0
- package/src/lib/runtime/ai-node-tree.js +16 -0
- package/src/lib/runtime/ai-node-tree.js.map +1 -1
- package/src/lib/tools/ai-dataset-tool.d.ts +68 -0
- package/src/lib/tools/ai-dataset-tool.js +231 -0
- package/src/lib/tools/ai-dataset-tool.js.map +1 -0
- package/src/lib/usage/free-ai-credits-left.js +26 -2
- package/src/lib/usage/free-ai-credits-left.js.map +1 -1
|
@@ -24,6 +24,7 @@ import { readAiDraftNodes } from './ai-job-drafts';
|
|
|
24
24
|
import { aiPublishGuidedSite } from './ai-site-publish';
|
|
25
25
|
import { aiPublishSitePosts, aiSiteContentRefusal } from './ai-job-site-content';
|
|
26
26
|
import { dropPluginSiteCache } from '@aglyn/aglyn/plugin-manager/plugin-site-cache';
|
|
27
|
+
import { aiSiteDatasetRefusal } from './ai-job-site-datasets';
|
|
27
28
|
import { type AiJobStepContext, type AiJobStepOutcome, type AiJobStepRunner } from './ai-job-text-step';
|
|
28
29
|
import { aiJobStepRunnerFor } from './ai-jobs';
|
|
29
30
|
/**
|
|
@@ -81,11 +82,12 @@ import { aiJobStepRunnerFor } from './ai-jobs';
|
|
|
81
82
|
*/
|
|
82
83
|
/**
|
|
83
84
|
* What a scaffold's units are, in the order it builds them; a component is a
|
|
84
|
-
* page job's.
|
|
85
|
-
*
|
|
86
|
-
*
|
|
85
|
+
* page job's. The site's datasets (AGL-3616) are built after the layout and
|
|
86
|
+
* before the form, which may write its submissions to one; a blog's first
|
|
87
|
+
* posts and a store's first products (AGL-3676) after the form; all of them
|
|
88
|
+
* before the pages, which are told what they are.
|
|
87
89
|
*/
|
|
88
|
-
export type AiSiteUnitKind = 'theme' | 'layout' | 'form' | 'component' | 'posts' | 'products' | 'page' | 'email';
|
|
90
|
+
export type AiSiteUnitKind = 'theme' | 'layout' | 'form' | 'component' | 'dataset' | 'posts' | 'products' | 'page' | 'email';
|
|
89
91
|
export interface AiSiteUnit {
|
|
90
92
|
kind: AiSiteUnitKind;
|
|
91
93
|
/** The job kind whose registered runner builds it. */
|
|
@@ -124,9 +126,11 @@ export declare const AI_SITE_MAX_PASSES: number;
|
|
|
124
126
|
/**
|
|
125
127
|
* The units a plan implies, in build order: the palette first, because a
|
|
126
128
|
* member reads it while the pages are still building; then the layout every
|
|
127
|
-
* page renders inside and the form they place
|
|
128
|
-
*
|
|
129
|
-
*
|
|
129
|
+
* page renders inside, the site's datasets, and the form they place —
|
|
130
|
+
* because a page binds the layout and the form by id, and a form binds the
|
|
131
|
+
* dataset it writes to (AGL-3616), so each needs what it binds to exist;
|
|
132
|
+
* then the pages; then the welcome email, which is about the site rather
|
|
133
|
+
* than part of it.
|
|
130
134
|
*/
|
|
131
135
|
export declare function aiSiteJobUnits(plan: Pick<AiJobPlan, 'create' | 'screens'>, options?: {
|
|
132
136
|
welcomeEmail?: boolean;
|
|
@@ -155,7 +159,7 @@ export interface AiSiteBuiltRef {
|
|
|
155
159
|
id: string;
|
|
156
160
|
label: string;
|
|
157
161
|
/** Only what becomes a record a page can name; a palette change is not one. */
|
|
158
|
-
kind: 'layout' | 'form' | 'component';
|
|
162
|
+
kind: 'layout' | 'form' | 'component' | 'dataset';
|
|
159
163
|
}
|
|
160
164
|
/**
|
|
161
165
|
* What the scaffold has already created, as the plan's `new:<name>`
|
|
@@ -287,6 +291,9 @@ export interface AiJobSiteStepDeps {
|
|
|
287
291
|
products?: AiJobStepRunner;
|
|
288
292
|
/** Whether a part may be built for this member, before its first pass. */
|
|
289
293
|
contentRefusal?: typeof aiSiteContentRefusal;
|
|
294
|
+
/** A dataset's pass and whether one may be made here (AGL-3616); specs hand in fakes. */
|
|
295
|
+
dataset?: AiJobStepRunner;
|
|
296
|
+
datasetRefusal?: typeof aiSiteDatasetRefusal;
|
|
290
297
|
/** The posts' publish once the pages are live, and the cache drop after it. */
|
|
291
298
|
publishPosts?: typeof aiPublishSitePosts;
|
|
292
299
|
dropCache?: typeof dropPluginSiteCache;
|
|
@@ -37,7 +37,9 @@ import { AI_LAYOUT_FORM_PAGE_INPUT, AI_LAYOUT_LANGUAGE_INPUT, aiLayoutFormPageOf
|
|
|
37
37
|
import { aiJobPublishesSite, aiPublishGuidedSite } from "./ai-site-publish.js";
|
|
38
38
|
import { AI_SITE_CONTENT_INPUT, AI_SITE_POST_BUDGET, AI_SITE_POSTS, AI_SITE_POSTS_LABEL, AI_SITE_PRODUCTS_LABEL, AI_SITE_PRODUCTS_PRICE_NOTE, aiPublishSitePosts, aiSiteContentBriefLines, aiSiteContentPart, aiSiteContentRefusal, aiSiteListings, aiSiteProductsBriefLine, createAiSiteProductsRunner, runAiSitePostsUnit } from "./ai-job-site-content.js";
|
|
39
39
|
import { dropPluginSiteCache } from "@aglyn/aglyn/plugin-manager/plugin-site-cache";
|
|
40
|
+
import { AI_SITE_DATASET_BUDGET, AI_SITE_DATASET_INPUT, AI_SITE_DATASETS_MAX, aiSiteDatasetBriefLines, aiSiteDatasetInputOf, aiSiteDatasetListings, aiSiteDatasetRefusal, aiSitePlanDatasets, aiSiteRecordTemplateOf, runAiSiteDatasetUnit } from "./ai-job-site-datasets.js";
|
|
40
41
|
import { AI_SITE_LOOK_BUDGET, aiRunSiteLook } from "./ai-job-site-look.js";
|
|
42
|
+
import { AI_FORM_DATASET_MADE_INPUT } from "./ai-job-form-dataset.js";
|
|
41
43
|
import { aiConfirmedPlan, aiUnspentOutcome } from "./ai-job-generation.js";
|
|
42
44
|
import { AI_JOB_BRIEF_MAX_CHARS } from "./ai-job-text-step.js";
|
|
43
45
|
import { AI_JOB_PAGE_STEP_MINIMUM_MS } from "./ai-job-page-budget.js";
|
|
@@ -77,6 +79,12 @@ import { aiJobStepRunMinimumMs, aiJobStepRunnerFor, registerAiJobStep, registerA
|
|
|
77
79
|
products: {
|
|
78
80
|
jobKind: 'products',
|
|
79
81
|
resource: 'product'
|
|
82
|
+
},
|
|
83
|
+
// The scaffold's own runner designs it (`ai-job-site-datasets.ts`), and the
|
|
84
|
+
// data plugin's writer keeps it: a draft of another plugin's (AGL-3616).
|
|
85
|
+
dataset: {
|
|
86
|
+
jobKind: 'text',
|
|
87
|
+
resource: 'draft'
|
|
80
88
|
}
|
|
81
89
|
};
|
|
82
90
|
/** The unit kind a creation is built as, where a unit builds it. */ const CREATION_UNIT_KINDS = {
|
|
@@ -123,13 +131,15 @@ export const AI_SITE_NO_PLAN_COPY = 'This site job has no confirmed plan to buil
|
|
|
123
131
|
* (one a pass, the largest part) and a welcome email — with nothing to
|
|
124
132
|
* spare, so a runner that never finishes is still bounded while a real site
|
|
125
133
|
* is not.
|
|
126
|
-
*/ export const AI_SITE_MAX_PASSES = AI_SITE_PAGES.max * (AI_SITE_MAX_SECTIONS + 1) + CREATION_UNITS.length + AI_SITE_POSTS + 1;
|
|
134
|
+
*/ export const AI_SITE_MAX_PASSES = AI_SITE_PAGES.max * (AI_SITE_MAX_SECTIONS + 1) + CREATION_UNITS.length + AI_SITE_DATASETS_MAX + AI_SITE_POSTS + 1;
|
|
127
135
|
/**
|
|
128
136
|
* The units a plan implies, in build order: the palette first, because a
|
|
129
137
|
* member reads it while the pages are still building; then the layout every
|
|
130
|
-
* page renders inside and the form they place
|
|
131
|
-
*
|
|
132
|
-
*
|
|
138
|
+
* page renders inside, the site's datasets, and the form they place —
|
|
139
|
+
* because a page binds the layout and the form by id, and a form binds the
|
|
140
|
+
* dataset it writes to (AGL-3616), so each needs what it binds to exist;
|
|
141
|
+
* then the pages; then the welcome email, which is about the site rather
|
|
142
|
+
* than part of it.
|
|
133
143
|
*/ export function aiSiteJobUnits(plan, options = {}) {
|
|
134
144
|
// The site's look is designed first, on every scaffold (AGL-3660): the
|
|
135
145
|
// header, the footer and every page render in it from their first draft.
|
|
@@ -144,6 +154,19 @@ export const AI_SITE_NO_PLAN_COPY = 'This site job has no confirmed plan to buil
|
|
|
144
154
|
];
|
|
145
155
|
for (const { unit, create } of CREATION_UNITS){
|
|
146
156
|
if (unit === 'theme') continue;
|
|
157
|
+
// The site's datasets (AGL-3616), before anything that lists them and
|
|
158
|
+
// before the form, which may write its submissions to one of them.
|
|
159
|
+
if (unit === 'form') {
|
|
160
|
+
aiSitePlanDatasets(plan).forEach((creation, index)=>{
|
|
161
|
+
units.push(_extends({
|
|
162
|
+
kind: 'dataset'
|
|
163
|
+
}, UNIT_KINDS.dataset, {
|
|
164
|
+
slot: `d${index}`,
|
|
165
|
+
creation,
|
|
166
|
+
label: creation.name
|
|
167
|
+
}));
|
|
168
|
+
});
|
|
169
|
+
}
|
|
147
170
|
const creation = plan.create.find((entry)=>entry.kind === create);
|
|
148
171
|
if (!creation) continue;
|
|
149
172
|
units.push(_extends({
|
|
@@ -254,8 +277,8 @@ export const AI_SITE_NO_PLAN_COPY = 'This site job has no confirmed plan to buil
|
|
|
254
277
|
const row = rows == null ? void 0 : rows.shift();
|
|
255
278
|
if (!row || !unit.creation) continue;
|
|
256
279
|
// A theme change is a proposal with no record to reference; a layout, a
|
|
257
|
-
// form and a
|
|
258
|
-
if (unit.creation.kind !== 'layout' && unit.creation.kind !== 'form' && unit.creation.kind !== 'component') {
|
|
280
|
+
// form, a component and a dataset (AGL-3616) become ids a page can name.
|
|
281
|
+
if (unit.creation.kind !== 'layout' && unit.creation.kind !== 'form' && unit.creation.kind !== 'component' && unit.creation.kind !== 'dataset') {
|
|
259
282
|
continue;
|
|
260
283
|
}
|
|
261
284
|
built.set(unit.creation.name.toLowerCase(), {
|
|
@@ -359,6 +382,7 @@ export const AI_SITE_NO_PLAN_COPY = 'This site job has no confirmed plan to buil
|
|
|
359
382
|
* for leaving it out.
|
|
360
383
|
*/ export function aiSiteUnitJob(job, unit, built) {
|
|
361
384
|
var _plan_labels;
|
|
385
|
+
var _unitPlan_create_, _unit_creation;
|
|
362
386
|
const plan = job.plan;
|
|
363
387
|
const labels = _extends({}, (_plan_labels = plan.labels) != null ? _plan_labels : {});
|
|
364
388
|
for (const entry of built.values())labels[entry.id] = entry.label;
|
|
@@ -380,12 +404,14 @@ export const AI_SITE_NO_PLAN_COPY = 'This site job has no confirmed plan to buil
|
|
|
380
404
|
unitPlan.create = [
|
|
381
405
|
_extends({}, unit.creation, {
|
|
382
406
|
duplicateOf: aiSiteResolvedRef(unit.creation.duplicateOf, built)
|
|
383
|
-
}
|
|
407
|
+
}, unit.creation.writesTo ? {
|
|
408
|
+
writesTo: aiSiteResolvedRef(unit.creation.writesTo, built)
|
|
409
|
+
} : {})
|
|
384
410
|
];
|
|
385
411
|
brief.push(`Build the ${unit.creation.kind} “${unit.creation.name}”: ${unit.creation.why}`);
|
|
386
412
|
}
|
|
387
413
|
if (unit.screen) {
|
|
388
|
-
var _aiSiteResolvedRef, _aiSiteResolvedRef1
|
|
414
|
+
var _aiSiteResolvedRef, _aiSiteResolvedRef1;
|
|
389
415
|
const screen = unit.screen;
|
|
390
416
|
// Everything the scaffold has already built is a record the site has, so
|
|
391
417
|
// the page is planned against it the way a page job is planned against
|
|
@@ -419,8 +445,12 @@ export const AI_SITE_NO_PLAN_COPY = 'This site job has no confirmed plan to buil
|
|
|
419
445
|
})
|
|
420
446
|
];
|
|
421
447
|
brief.push(`Build the page “${screen.title}” of this site, at ${screen.slug}.`);
|
|
422
|
-
// What the blog's posts or the store's products are, once built (AGL-3676)
|
|
423
|
-
|
|
448
|
+
// What the blog's posts or the store's products are, once built (AGL-3676),
|
|
449
|
+
// and what the site's datasets hold (AGL-3616).
|
|
450
|
+
if (job.kind === 'site') {
|
|
451
|
+
var _job_outputs, _job_outputs1;
|
|
452
|
+
brief.push(...aiSiteContentBriefLines((_job_outputs = job.outputs) != null ? _job_outputs : []), ...aiSiteDatasetBriefLines((_job_outputs1 = job.outputs) != null ? _job_outputs1 : []));
|
|
453
|
+
}
|
|
424
454
|
}
|
|
425
455
|
if (unit.kind === 'products') brief.push(aiSiteProductsBriefLine());
|
|
426
456
|
if (unit.kind === 'email') {
|
|
@@ -434,15 +464,15 @@ export const AI_SITE_NO_PLAN_COPY = 'This site job has no confirmed plan to buil
|
|
|
434
464
|
// A page is told the pages built before it, whose photos it does not place
|
|
435
465
|
// again (AGL-3660): the maker's portrait in About is never a vase in Work.
|
|
436
466
|
if (unit.screen) {
|
|
437
|
-
var
|
|
438
|
-
const pages = ((
|
|
467
|
+
var _job_outputs2;
|
|
468
|
+
const pages = ((_job_outputs2 = job.outputs) != null ? _job_outputs2 : []).filter((output)=>output.resource === 'screen' && output.hostId === job.hostId && output.id).map((output)=>output.id);
|
|
439
469
|
if (pages.length) unitInputs[AI_STOCK_PHOTO_PAGES_INPUT] = pages;
|
|
440
470
|
}
|
|
441
471
|
// The layout is built before the pages, so it is told them (AGL-3596): their
|
|
442
472
|
// ids are minted on the plan, and the platform writes the header's links.
|
|
443
473
|
// A page is told them too, so its buttons may go to a page built after it.
|
|
444
474
|
if (job.kind === 'site' && (unit.kind === 'layout' || unit.kind === 'page')) {
|
|
445
|
-
var
|
|
475
|
+
var _job_outputs3, _job_outputs4;
|
|
446
476
|
var _aiSiteKindOfInputs, _aiSiteKindOfInputs1;
|
|
447
477
|
// A guided start links every page the person asked for (AGL-3660), and
|
|
448
478
|
// the blog its first posts are written into, by its path, second after
|
|
@@ -481,7 +511,7 @@ export const AI_SITE_NO_PLAN_COPY = 'This site job has no confirmed plan to buil
|
|
|
481
511
|
// The store's catalog and the blog, listed by the sections that show them,
|
|
482
512
|
// and the cart in a selling site's header (AGL-3676).
|
|
483
513
|
const listings = aiSiteListings({
|
|
484
|
-
outputs: (
|
|
514
|
+
outputs: (_job_outputs3 = job.outputs) != null ? _job_outputs3 : [],
|
|
485
515
|
screens: merged.screens,
|
|
486
516
|
sells: aiSiteSellsProducts(job),
|
|
487
517
|
// A store lists its catalog on its Shop page even when its first
|
|
@@ -490,15 +520,28 @@ export const AI_SITE_NO_PLAN_COPY = 'This site job has no confirmed plan to buil
|
|
|
490
520
|
// A music site places an empty player for the artist's own tracks (AGL-3716).
|
|
491
521
|
music: ((_aiSiteKindOfInputs1 = aiSiteKindOfInputs(job.inputs)) == null ? void 0 : _aiSiteKindOfInputs1.id) === 'music'
|
|
492
522
|
});
|
|
523
|
+
// The site's datasets, each repeated in the sections that name it (AGL-3616).
|
|
524
|
+
const delivered = new Map([
|
|
525
|
+
...built.entries()
|
|
526
|
+
].filter(([, entry])=>entry.kind === 'dataset').map(([name, entry])=>[
|
|
527
|
+
name,
|
|
528
|
+
entry.id
|
|
529
|
+
]));
|
|
530
|
+
listings.push(...aiSiteDatasetListings({
|
|
531
|
+
outputs: (_job_outputs4 = job.outputs) != null ? _job_outputs4 : [],
|
|
532
|
+
datasets: aiSitePlanDatasets(plan),
|
|
533
|
+
screens: merged.screens,
|
|
534
|
+
delivered
|
|
535
|
+
}));
|
|
493
536
|
if (listings.length) unitInputs[AI_LAYOUT_LISTINGS_INPUT] = listings;
|
|
494
537
|
}
|
|
495
538
|
// A site's pages and its layout are designed in the layout language and
|
|
496
539
|
// compiled (AGL-3660), and a page is told which page places the site's form.
|
|
497
540
|
if (unit.kind === 'layout' || unit.kind === 'page') {
|
|
498
|
-
var
|
|
541
|
+
var _job_outputs5;
|
|
499
542
|
var _look_proposal;
|
|
500
543
|
// The look designed first (AGL-3660): its header arrangement and band rhythm.
|
|
501
|
-
const look = ((
|
|
544
|
+
const look = ((_job_outputs5 = job.outputs) != null ? _job_outputs5 : []).find((output)=>output.resource === 'theme' && output.id === 'look');
|
|
502
545
|
const style = look == null ? void 0 : (_look_proposal = look.proposal) == null ? void 0 : _look_proposal['style'];
|
|
503
546
|
if (style) unitInputs['siteStyle'] = {
|
|
504
547
|
headerAlign: style['headerAlign'],
|
|
@@ -510,11 +553,11 @@ export const AI_SITE_NO_PLAN_COPY = 'This site job has no confirmed plan to buil
|
|
|
510
553
|
if (formPage) unitInputs[AI_LAYOUT_FORM_PAGE_INPUT] = formPage;
|
|
511
554
|
}
|
|
512
555
|
if (unit.kind === 'posts') {
|
|
513
|
-
var
|
|
556
|
+
var _job_outputs6, _inputs_businessName;
|
|
514
557
|
// The posts already written (one a pass), the addresses the site's own
|
|
515
558
|
// pages answer at, and the byline the person gave (AGL-3676).
|
|
516
559
|
const posts = {
|
|
517
|
-
written: ((
|
|
560
|
+
written: ((_job_outputs6 = job.outputs) != null ? _job_outputs6 : []).filter((output)=>output.resource === 'entry').map((output)=>({
|
|
518
561
|
id: output.id,
|
|
519
562
|
title: output.label
|
|
520
563
|
})),
|
|
@@ -526,6 +569,14 @@ export const AI_SITE_NO_PLAN_COPY = 'This site job has no confirmed plan to buil
|
|
|
526
569
|
unitInputs[AI_SITE_CONTENT_INPUT] = posts;
|
|
527
570
|
}
|
|
528
571
|
if (unit.kind === 'products') unitInputs['target'] = 'catalog';
|
|
572
|
+
// Where the plan lists a dataset, which its design reads, and the form
|
|
573
|
+
// that writes to it (AGL-3616).
|
|
574
|
+
if (unit.kind === 'dataset' && unit.creation) {
|
|
575
|
+
unitInputs[AI_SITE_DATASET_INPUT] = aiSiteDatasetInputOf(unit.creation, plan.screens, plan.create);
|
|
576
|
+
}
|
|
577
|
+
// A form's dataset this start made, which the form may bind (AGL-3616).
|
|
578
|
+
const writesTo = unit.kind === 'form' ? (_unitPlan_create_ = unitPlan.create[0]) == null ? void 0 : _unitPlan_create_.writesTo : null;
|
|
579
|
+
if (writesTo && isAiPlanNewRef((_unit_creation = unit.creation) == null ? void 0 : _unit_creation.writesTo)) unitInputs[AI_FORM_DATASET_MADE_INPUT] = writesTo;
|
|
529
580
|
return _extends({}, job, {
|
|
530
581
|
$id: aiSiteUnitJobId(job, unit),
|
|
531
582
|
kind: unit.jobKind,
|
|
@@ -729,16 +780,31 @@ export const aiSiteJobAdmission = createAiSiteJobAdmission();
|
|
|
729
780
|
* Try again read, so a site is settled item by item exactly as a build is.
|
|
730
781
|
*/ export function aiSiteLedgerUnits(units) {
|
|
731
782
|
const creations = units.filter((unit)=>unit.kind === 'layout' || unit.kind === 'form').map((unit)=>unit.slot);
|
|
783
|
+
const datasets = units.filter((unit)=>unit.kind === 'dataset' && unit.creation);
|
|
784
|
+
/** The dataset a form writes to (AGL-3616): built before it, and it without the binding if it fails. */ const writtenTo = (creation)=>datasets.filter((unit)=>{
|
|
785
|
+
var _ref;
|
|
786
|
+
var _unit_creation;
|
|
787
|
+
return !!(creation == null ? void 0 : creation.writesTo) && creation.writesTo.trim().toLowerCase() === `new:${(_ref = (_unit_creation = unit.creation) == null ? void 0 : _unit_creation.name) != null ? _ref : ''}`.trim().toLowerCase();
|
|
788
|
+
}).map((unit)=>unit.slot);
|
|
789
|
+
/** The datasets a page lists or is the record template of (AGL-3616): built before it, and it without them if they fail. */ const listed = (screen)=>datasets.filter((unit)=>{
|
|
790
|
+
var _ref, _ref1;
|
|
791
|
+
var _unit_creation, _screen_record;
|
|
792
|
+
const named = `new:${(_ref = (_unit_creation = unit.creation) == null ? void 0 : _unit_creation.name) != null ? _ref : ''}`.trim().toLowerCase();
|
|
793
|
+
return (screen == null ? void 0 : (_screen_record = screen.record) == null ? void 0 : _screen_record.dataset.trim().toLowerCase()) === named || ((_ref1 = screen == null ? void 0 : screen.sections) != null ? _ref1 : []).some((section)=>section.uses.some((ref)=>ref.trim().toLowerCase() === named));
|
|
794
|
+
}).map((unit)=>unit.slot);
|
|
732
795
|
return units.map((unit)=>_extends({
|
|
733
796
|
slot: unit.slot,
|
|
734
|
-
op: unit.kind === 'theme' || unit.kind === 'posts' || unit.kind === 'products' ? unit.kind : unit.jobKind,
|
|
797
|
+
op: unit.kind === 'theme' || unit.kind === 'posts' || unit.kind === 'products' || unit.kind === 'dataset' ? unit.kind : unit.jobKind,
|
|
735
798
|
label: unit.label
|
|
736
799
|
}, unit.creation ? {
|
|
737
800
|
creation: unit.creation
|
|
738
801
|
} : {}, unit.screen ? {
|
|
739
802
|
screen: unit.screen
|
|
740
803
|
} : {}, {
|
|
741
|
-
deps: unit.kind === 'page' ?
|
|
804
|
+
deps: unit.kind === 'page' ? [
|
|
805
|
+
...creations,
|
|
806
|
+
...listed(unit.screen)
|
|
807
|
+
] : unit.kind === 'form' ? writtenTo(unit.creation) : []
|
|
742
808
|
}));
|
|
743
809
|
}
|
|
744
810
|
/**
|
|
@@ -770,20 +836,21 @@ export const aiSiteJobAdmission = createAiSiteJobAdmission();
|
|
|
770
836
|
return aiSiteJobUnits(plan, {
|
|
771
837
|
welcomeEmail: aiSiteWelcomeEmail(inputs, freeTaste),
|
|
772
838
|
content: aiSiteContentPart(job.inputs, freeTaste)
|
|
773
|
-
}).filter((unit)=>unit.kind === 'theme' || unit.kind === 'posts' || runnerFor(unit.jobKind));
|
|
839
|
+
}).filter((unit)=>unit.kind === 'theme' || unit.kind === 'posts' || unit.kind === 'dataset' || runnerFor(unit.jobKind));
|
|
774
840
|
}
|
|
775
841
|
export function createAiJobSiteStep(deps = {}) {
|
|
776
|
-
var _deps_runnerFor, _deps_readNodes, _deps_publish, _deps_look, _deps_contentRefusal, _deps_publishPosts, _deps_dropCache;
|
|
842
|
+
var _deps_runnerFor, _deps_readNodes, _deps_publish, _deps_look, _deps_contentRefusal, _deps_datasetRefusal, _deps_publishPosts, _deps_dropCache;
|
|
777
843
|
const runnerFor = (_deps_runnerFor = deps.runnerFor) != null ? _deps_runnerFor : aiJobStepRunnerFor;
|
|
778
844
|
const readNodes = (_deps_readNodes = deps.readNodes) != null ? _deps_readNodes : readAiDraftNodes;
|
|
779
845
|
const publish = (_deps_publish = deps.publish) != null ? _deps_publish : aiPublishGuidedSite;
|
|
780
846
|
const look = (_deps_look = deps.look) != null ? _deps_look : aiRunSiteLook;
|
|
781
847
|
const contentRefusal = (_deps_contentRefusal = deps.contentRefusal) != null ? _deps_contentRefusal : aiSiteContentRefusal;
|
|
848
|
+
const datasetRefusal = (_deps_datasetRefusal = deps.datasetRefusal) != null ? _deps_datasetRefusal : aiSiteDatasetRefusal;
|
|
782
849
|
const publishPosts = (_deps_publishPosts = deps.publishPosts) != null ? _deps_publishPosts : aiPublishSitePosts;
|
|
783
850
|
const dropCache = (_deps_dropCache = deps.dropCache) != null ? _deps_dropCache : dropPluginSiteCache;
|
|
784
851
|
return async (context)=>{
|
|
785
|
-
var _ref, _job_outputs, _deps_posts, _deps_products, _job_outputs1;
|
|
786
|
-
var _job_items, _rows_get;
|
|
852
|
+
var _ref, _job_outputs, _deps_posts, _deps_products, _deps_dataset, _job_outputs1;
|
|
853
|
+
var _job_items, _rows_get, _rows_get1;
|
|
787
854
|
const { job } = context;
|
|
788
855
|
// The scaffold asks no model of its own. What it names where it spends
|
|
789
856
|
// nothing is the model its plan ran on, which is the one exchange this
|
|
@@ -875,11 +942,20 @@ export function createAiJobSiteStep(deps = {}) {
|
|
|
875
942
|
error
|
|
876
943
|
}));
|
|
877
944
|
};
|
|
878
|
-
/**
|
|
945
|
+
/**
|
|
946
|
+
* The pages built so far, as the job reported them. A dataset's record
|
|
947
|
+
* template is not among them (AGL-3616): it renders once per record only
|
|
948
|
+
* once the member saves its binding, so it is never published at its own
|
|
949
|
+
* address, where its `{{item.*}}` would show.
|
|
950
|
+
*/ const templates = new Set(units.filter((unit)=>{
|
|
951
|
+
var _unit_screen;
|
|
952
|
+
return unit.kind === 'page' && ((_unit_screen = unit.screen) == null ? void 0 : _unit_screen.record);
|
|
953
|
+
}).map((unit)=>unit.slot));
|
|
954
|
+
const builtPages = (extra = [])=>{
|
|
879
955
|
var _job_outputs;
|
|
880
956
|
const ids = new Set(units.filter((unit)=>{
|
|
881
957
|
var _rows_get;
|
|
882
|
-
return unit.kind === 'page' && aiBuildItemDelivered((_rows_get = rows.get(unit.slot)) != null ? _rows_get : {
|
|
958
|
+
return unit.kind === 'page' && !templates.has(unit.slot) && aiBuildItemDelivered((_rows_get = rows.get(unit.slot)) != null ? _rows_get : {
|
|
883
959
|
status: 'pending'
|
|
884
960
|
});
|
|
885
961
|
}).flatMap((unit)=>{
|
|
@@ -898,7 +974,7 @@ export function createAiJobSiteStep(deps = {}) {
|
|
|
898
974
|
const catalog = unit.kind === 'products' ? runnerFor('products') : undefined;
|
|
899
975
|
const runner = unit.kind === 'theme' ? (lookContext)=>look(lookContext, lookContext.job) : unit.kind === 'posts' ? (_deps_posts = deps.posts) != null ? _deps_posts : runAiSitePostsUnit : unit.kind === 'products' ? (_deps_products = deps.products) != null ? _deps_products : catalog ? createAiSiteProductsRunner({
|
|
900
976
|
catalog
|
|
901
|
-
}) : undefined : runnerFor(unit.jobKind);
|
|
977
|
+
}) : undefined : unit.kind === 'dataset' ? (_deps_dataset = deps.dataset) != null ? _deps_dataset : runAiSiteDatasetUnit : runnerFor(unit.jobKind);
|
|
902
978
|
if (!runner) return _extends({}, aiUnspentOutcome(model), init);
|
|
903
979
|
const othersOpen = ledgerUnits.some((one)=>{
|
|
904
980
|
var _rows_get;
|
|
@@ -957,6 +1033,48 @@ export function createAiJobSiteStep(deps = {}) {
|
|
|
957
1033
|
note: `Not built: ${refusal}`
|
|
958
1034
|
}));
|
|
959
1035
|
}
|
|
1036
|
+
// A dataset asks the same before its first pass (AGL-3616): the data
|
|
1037
|
+
// plugin runs here, and its writer admits this member now.
|
|
1038
|
+
if (unit.kind === 'dataset' && ((_rows_get1 = rows.get(unit.slot)) == null ? void 0 : _rows_get1.status) !== 'running') {
|
|
1039
|
+
const refusal = await datasetRefusal(_extends({}, context, {
|
|
1040
|
+
job
|
|
1041
|
+
})).catch((error)=>{
|
|
1042
|
+
console.error('ai site dataset admission failed', {
|
|
1043
|
+
orgId: job.orgId,
|
|
1044
|
+
jobId: job.$id,
|
|
1045
|
+
slot: unit.slot,
|
|
1046
|
+
error
|
|
1047
|
+
});
|
|
1048
|
+
return AI_SITE_UNIT_EMPTY_COPY;
|
|
1049
|
+
});
|
|
1050
|
+
if (refusal) return closing(settle({
|
|
1051
|
+
slot: unit.slot,
|
|
1052
|
+
status: 'skipped',
|
|
1053
|
+
note: `Not built: ${refusal}`
|
|
1054
|
+
}));
|
|
1055
|
+
}
|
|
1056
|
+
// A record template whose dataset was not made has nothing to show
|
|
1057
|
+
// (AGL-3616): it is not built, and the pages that list the dataset are
|
|
1058
|
+
// built without it.
|
|
1059
|
+
const templateOf = unit.kind === 'page' && unit.screen ? aiSiteRecordTemplateOf(unit.screen) : null;
|
|
1060
|
+
if (templateOf) {
|
|
1061
|
+
const dataset = units.find((one)=>{
|
|
1062
|
+
var _one_creation;
|
|
1063
|
+
return one.kind === 'dataset' && ((_one_creation = one.creation) == null ? void 0 : _one_creation.name.trim().toLowerCase()) === templateOf.toLowerCase();
|
|
1064
|
+
});
|
|
1065
|
+
const row = dataset ? rows.get(dataset.slot) : undefined;
|
|
1066
|
+
if (!row || !aiBuildItemDelivered(row) || !row.outputs.length) {
|
|
1067
|
+
return closing(settle(_extends({
|
|
1068
|
+
slot: unit.slot,
|
|
1069
|
+
status: 'skipped',
|
|
1070
|
+
note: `Not built: the dataset “${templateOf}” it shows a page of each record of could not be created.`
|
|
1071
|
+
}, dataset ? {
|
|
1072
|
+
degradedBy: [
|
|
1073
|
+
dataset.slot
|
|
1074
|
+
]
|
|
1075
|
+
} : {})));
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
960
1078
|
// A page whose layout or form failed is built without it, and says so.
|
|
961
1079
|
const degradation = aiBuildDegradation(next, {
|
|
962
1080
|
units: ledgerUnits,
|
|
@@ -1042,7 +1160,7 @@ export function createAiJobSiteStep(deps = {}) {
|
|
|
1042
1160
|
rows.set(unit.slot, _extends({}, rows.get(unit.slot), {
|
|
1043
1161
|
status: degraded ? 'degraded' : 'succeeded'
|
|
1044
1162
|
}));
|
|
1045
|
-
return finish(done, builtPages(unit.kind === 'page' ? outcome.outputs.filter((output)=>output.resource === 'screen') : []));
|
|
1163
|
+
return finish(done, builtPages(unit.kind === 'page' && !templates.has(unit.slot) ? outcome.outputs.filter((output)=>output.resource === 'screen') : []));
|
|
1046
1164
|
};
|
|
1047
1165
|
}
|
|
1048
1166
|
export const runAiJobSiteStep = createAiJobSiteStep();
|
|
@@ -1065,7 +1183,7 @@ export const runAiJobSiteStep = createAiJobSiteStep();
|
|
|
1065
1183
|
const units = aiSiteJobUnits(plan, {
|
|
1066
1184
|
welcomeEmail: inputs.welcomeEmail,
|
|
1067
1185
|
content: aiSiteContentPart(job.inputs, false)
|
|
1068
|
-
}).filter((unit)=>(unit.kind === 'theme' || unit.kind === 'posts' || aiJobStepRunnerFor(unit.jobKind)) && (!owed.size || owed.has(unit.slot)));
|
|
1186
|
+
}).filter((unit)=>(unit.kind === 'theme' || unit.kind === 'posts' || unit.kind === 'dataset' || aiJobStepRunnerFor(unit.jobKind)) && (!owed.size || owed.has(unit.slot)));
|
|
1069
1187
|
const outputs = (_job_outputs = job.outputs) != null ? _job_outputs : [];
|
|
1070
1188
|
const ledger = ((_job_items1 = job.items) == null ? void 0 : _job_items1.length) ? job.items : aiSiteInitialLedger(units, outputs);
|
|
1071
1189
|
const next = aiBuildNextUnit(aiSiteLedgerUnits(units), ledger);
|
|
@@ -1073,6 +1191,7 @@ export const runAiJobSiteStep = createAiJobSiteStep();
|
|
|
1073
1191
|
if (!unit) return AI_JOB_PAGE_STEP_MINIMUM_MS;
|
|
1074
1192
|
if (unit.kind === 'theme') return AI_SITE_LOOK_BUDGET.minimumMs;
|
|
1075
1193
|
if (unit.kind === 'posts') return AI_SITE_POST_BUDGET.minimumMs;
|
|
1194
|
+
if (unit.kind === 'dataset') return AI_SITE_DATASET_BUDGET.minimumMs;
|
|
1076
1195
|
return aiJobStepRunMinimumMs(aiSiteUnitJob(job, unit, aiBuildBuiltRefs(aiSiteLedgerUnits(units), ledger, outputs)));
|
|
1077
1196
|
}
|
|
1078
1197
|
/**
|