@aglyn/plugins-ai 1.0.0-beta.271 → 1.0.0-beta.273
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/activity/ai-activity-actions.d.ts +4 -3
- package/src/lib/activity/ai-activity-actions.js +3 -0
- package/src/lib/activity/ai-activity-actions.js.map +1 -1
- package/src/lib/components/ai-site-build-page.component.js +18 -0
- package/src/lib/components/ai-site-build-page.component.js.map +1 -1
- package/src/lib/components/ai-site-import-job.component.d.ts +41 -0
- package/src/lib/components/ai-site-import-job.component.js +707 -0
- package/src/lib/components/ai-site-import-job.component.js.map +1 -0
- package/src/lib/components/ai-site-import-start.component.d.ts +64 -0
- package/src/lib/components/ai-site-import-start.component.js +335 -0
- package/src/lib/components/ai-site-import-start.component.js.map +1 -0
- package/src/lib/components/ai-site-ownership-proof.component.d.ts +42 -0
- package/src/lib/components/ai-site-ownership-proof.component.js +353 -0
- package/src/lib/components/ai-site-ownership-proof.component.js.map +1 -0
- package/src/lib/components/ai-site-start-card.component.js +329 -252
- package/src/lib/components/ai-site-start-card.component.js.map +1 -1
- package/src/lib/jobs/ai-empty-site-sweep.d.ts +12 -1
- package/src/lib/jobs/ai-empty-site-sweep.js +15 -3
- package/src/lib/jobs/ai-empty-site-sweep.js.map +1 -1
- package/src/lib/jobs/ai-job-drafts.d.ts +14 -0
- package/src/lib/jobs/ai-job-drafts.js +24 -0
- package/src/lib/jobs/ai-job-drafts.js.map +1 -1
- package/src/lib/jobs/ai-job-import-step.d.ts +136 -0
- package/src/lib/jobs/ai-job-import-step.js +809 -0
- package/src/lib/jobs/ai-job-import-step.js.map +1 -0
- package/src/lib/jobs/ai-job-page-language.d.ts +39 -1
- package/src/lib/jobs/ai-job-page-language.js +62 -4
- package/src/lib/jobs/ai-job-page-language.js.map +1 -1
- package/src/lib/jobs/ai-job-page-step.d.ts +2 -2
- package/src/lib/jobs/ai-job-page-step.js +26 -4
- package/src/lib/jobs/ai-job-page-step.js.map +1 -1
- package/src/lib/jobs/ai-job-seo-step.js +8 -4
- package/src/lib/jobs/ai-job-seo-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-datasets.d.ts +39 -1
- package/src/lib/jobs/ai-job-site-datasets.js +111 -15
- package/src/lib/jobs/ai-job-site-datasets.js.map +1 -1
- package/src/lib/jobs/ai-job-site-step.d.ts +12 -3
- package/src/lib/jobs/ai-job-site-step.js +85 -11
- package/src/lib/jobs/ai-job-site-step.js.map +1 -1
- package/src/lib/jobs/ai-job-text-step.d.ts +15 -0
- package/src/lib/jobs/ai-job-text-step.js.map +1 -1
- package/src/lib/jobs/ai-jobs.d.ts +8 -0
- package/src/lib/jobs/ai-jobs.js +19 -3
- package/src/lib/jobs/ai-jobs.js.map +1 -1
- package/src/lib/jobs/ai-layout-owner-photos.d.ts +16 -1
- package/src/lib/jobs/ai-layout-owner-photos.js +49 -2
- package/src/lib/jobs/ai-layout-owner-photos.js.map +1 -1
- package/src/lib/jobs/ai-layout-stock-photos.d.ts +35 -0
- package/src/lib/jobs/ai-layout-stock-photos.js +114 -43
- package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
- package/src/lib/jobs/ai-site-late-photos.d.ts +143 -0
- package/src/lib/jobs/ai-site-late-photos.js +486 -0
- package/src/lib/jobs/ai-site-late-photos.js.map +1 -0
- package/src/lib/jobs/ai-site-publish.d.ts +18 -0
- package/src/lib/jobs/ai-site-publish.js +123 -5
- package/src/lib/jobs/ai-site-publish.js.map +1 -1
- package/src/lib/jobs/ai-theme-brand-inputs.d.ts +61 -3
- package/src/lib/jobs/ai-theme-brand-inputs.js +117 -27
- package/src/lib/jobs/ai-theme-brand-inputs.js.map +1 -1
- package/src/lib/jobs/fixtures/ai-site-late-photos-laurel-fork.d.ts +83 -0
- package/src/lib/jobs/fixtures/ai-site-late-photos-laurel-fork.js +1553 -0
- package/src/lib/jobs/fixtures/ai-site-late-photos-laurel-fork.js.map +1 -0
- package/src/lib/layout-language/ai-layout-pictures.d.ts +50 -13
- package/src/lib/layout-language/ai-layout-pictures.js +81 -19
- package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
- package/src/lib/model/ai-credit-estimate.d.ts +20 -0
- package/src/lib/model/ai-credit-estimate.js +13 -0
- package/src/lib/model/ai-credit-estimate.js.map +1 -1
- package/src/lib/model/ai-job-activity.d.ts +2 -2
- package/src/lib/model/ai-job-activity.js +6 -4
- package/src/lib/model/ai-job-activity.js.map +1 -1
- package/src/lib/model/ai-job-notice.js +18 -4
- package/src/lib/model/ai-job-notice.js.map +1 -1
- package/src/lib/model/ai-jobs.types.d.ts +39 -2
- package/src/lib/model/ai-jobs.types.js +2 -1
- package/src/lib/model/ai-jobs.types.js.map +1 -1
- package/src/lib/model/ai-site-import-view.d.ts +130 -0
- package/src/lib/model/ai-site-import-view.js +182 -0
- package/src/lib/model/ai-site-import-view.js.map +1 -0
- package/src/lib/model/ai-site-import.d.ts +302 -0
- package/src/lib/model/ai-site-import.js +526 -0
- package/src/lib/model/ai-site-import.js.map +1 -0
- package/src/lib/model/ai-site-photos.d.ts +119 -0
- package/src/lib/model/ai-site-photos.js +128 -0
- package/src/lib/model/ai-site-photos.js.map +1 -0
- package/src/lib/model/ai-site-start.d.ts +22 -9
- package/src/lib/model/ai-site-start.js +64 -23
- package/src/lib/model/ai-site-start.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.d.ts +3 -1
- package/src/lib/runtime/ai-doctrine-validators.js +3 -1
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/seo-fields.d.ts +29 -4
- package/src/lib/runtime/seo-fields.js +58 -11
- package/src/lib/runtime/seo-fields.js.map +1 -1
- package/src/lib/server/ai-jobs-route.js +11 -0
- package/src/lib/server/ai-jobs-route.js.map +1 -1
- package/src/lib/server/ai-site-import-route.d.ts +89 -0
- package/src/lib/server/ai-site-import-route.js +356 -0
- package/src/lib/server/ai-site-import-route.js.map +1 -0
- package/src/lib/server.js +14 -0
- package/src/lib/server.js.map +1 -1
- package/src/lib/site-import/fixtures/site-import-crawl-recordings.d.ts +45 -0
- package/src/lib/site-import/fixtures/site-import-crawl-recordings.js +313 -0
- package/src/lib/site-import/fixtures/site-import-crawl-recordings.js.map +1 -0
- package/src/lib/site-import/fixtures/site-import-wave-recordings.d.ts +50 -0
- package/src/lib/site-import/fixtures/site-import-wave-recordings.js +217 -0
- package/src/lib/site-import/fixtures/site-import-wave-recordings.js.map +1 -0
- package/src/lib/site-import/site-import-crawl.d.ts +163 -0
- package/src/lib/site-import/site-import-crawl.js +467 -0
- package/src/lib/site-import/site-import-crawl.js.map +1 -0
- package/src/lib/site-import/site-import-flag.d.ts +23 -0
- package/src/lib/site-import/site-import-flag.js +23 -0
- package/src/lib/site-import/site-import-flag.js.map +1 -0
- package/src/lib/site-import/site-import-html.d.ts +94 -0
- package/src/lib/site-import/site-import-html.js +462 -0
- package/src/lib/site-import/site-import-html.js.map +1 -0
- package/src/lib/site-import/site-import-images.d.ts +54 -0
- package/src/lib/site-import/site-import-images.js +204 -0
- package/src/lib/site-import/site-import-images.js.map +1 -0
- package/src/lib/site-import/site-import-page.d.ts +48 -0
- package/src/lib/site-import/site-import-page.js +150 -0
- package/src/lib/site-import/site-import-page.js.map +1 -0
- package/src/lib/site-import/site-import-review.d.ts +40 -0
- package/src/lib/site-import/site-import-review.js +149 -0
- package/src/lib/site-import/site-import-review.js.map +1 -0
- package/src/lib/site-import/site-import-robots.d.ts +52 -0
- package/src/lib/site-import/site-import-robots.js +126 -0
- package/src/lib/site-import/site-import-robots.js.map +1 -0
- package/src/lib/tools/ai-seo-tool.d.ts +25 -1
- package/src/lib/tools/ai-seo-tool.js +61 -0
- package/src/lib/tools/ai-seo-tool.js.map +1 -1
|
@@ -0,0 +1,130 @@
|
|
|
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 { AiJobSummary } from './ai-jobs.types';
|
|
18
|
+
import { type AiSiteImportLeftOutReason, type AiSiteImportState, type AiSiteImportWave } from './ai-site-import';
|
|
19
|
+
/** A domain ownership claim, as the ownership door answers it. */
|
|
20
|
+
export interface AiSiteImportClaim {
|
|
21
|
+
domain: string;
|
|
22
|
+
status: 'pending' | 'proven';
|
|
23
|
+
current: boolean;
|
|
24
|
+
provenMethod: 'dns' | 'meta' | 'email' | null;
|
|
25
|
+
provenAt: number | null;
|
|
26
|
+
provenDetail: string | null;
|
|
27
|
+
lastChecks: Partial<Record<'dns' | 'meta' | 'email', 'proven' | 'not-yet' | 'unreachable'>>;
|
|
28
|
+
dns: {
|
|
29
|
+
host: string;
|
|
30
|
+
type: 'TXT';
|
|
31
|
+
value: string;
|
|
32
|
+
};
|
|
33
|
+
meta: {
|
|
34
|
+
name: string;
|
|
35
|
+
content: string;
|
|
36
|
+
tag: string;
|
|
37
|
+
};
|
|
38
|
+
email: {
|
|
39
|
+
domain: string;
|
|
40
|
+
pendingAddress: string | null;
|
|
41
|
+
expiresAt: number | null;
|
|
42
|
+
attemptsLeft: number | null;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/** Whether "Bring my site" is offered here, and if not why. */
|
|
46
|
+
export type AiSiteImportAvailability = {
|
|
47
|
+
state: 'checking';
|
|
48
|
+
}
|
|
49
|
+
/** The release flag is off, or the doors cannot be reached: the card is not drawn. */
|
|
50
|
+
| {
|
|
51
|
+
state: 'hidden';
|
|
52
|
+
}
|
|
53
|
+
/** Something the workspace can change stands in the way: the card is drawn disabled, with the reason. */
|
|
54
|
+
| {
|
|
55
|
+
state: 'blocked';
|
|
56
|
+
reason: 'plan' | 'role';
|
|
57
|
+
message: string;
|
|
58
|
+
} | {
|
|
59
|
+
state: 'ready';
|
|
60
|
+
claims: AiSiteImportClaim[];
|
|
61
|
+
};
|
|
62
|
+
/** What the card says to a plan that does not include it. */
|
|
63
|
+
export declare const AI_SITE_IMPORT_PLAN_COPY = "Bring your current website in, every page and photo, on any paid plan. Upgrade to bring yours in.";
|
|
64
|
+
/** What the card says to a member who cannot. */
|
|
65
|
+
export declare const AI_SITE_IMPORT_ROLE_COPY = "Only the workspace owner or an admin can bring a site in.";
|
|
66
|
+
/**
|
|
67
|
+
* The jobs list's `siteImport` offer (AGL-3976), as the card's state: absent
|
|
68
|
+
* is the flag off, and the card is not drawn; `plan` and `role` are drawn
|
|
69
|
+
* disabled with the reason.
|
|
70
|
+
*/
|
|
71
|
+
export declare function aiSiteImportOfferOf(offer: unknown): AiSiteImportAvailability;
|
|
72
|
+
/** Where an import job's page is. */
|
|
73
|
+
export type AiSiteImportPhase =
|
|
74
|
+
/** The site is being read. */
|
|
75
|
+
'reading'
|
|
76
|
+
/** Read and planned; the first wave waits to be started. */
|
|
77
|
+
| 'ready'
|
|
78
|
+
/** A wave was started and has not begun yet. */
|
|
79
|
+
| 'starting' | 'running'
|
|
80
|
+
/** A wave is in; the next waits to be started. */
|
|
81
|
+
| 'review'
|
|
82
|
+
/** Held for something the person does: verify again, wait for tomorrow, read again. */
|
|
83
|
+
| 'held'
|
|
84
|
+
/** Out of AI credits or at a cap: the meter's pause, carried on by Resume. */
|
|
85
|
+
| 'paused' | 'done' | 'stopped';
|
|
86
|
+
export declare function aiSiteImportPhaseOf(job: Pick<AiJobSummary, 'status' | 'review' | 'siteImport'>): AiSiteImportPhase;
|
|
87
|
+
export type AiSiteImportRowState = 'waiting' | 'active' | 'done' | 'failed' | 'skipped';
|
|
88
|
+
export interface AiSiteImportRowView {
|
|
89
|
+
slot: string;
|
|
90
|
+
title: string;
|
|
91
|
+
/** Where it is on the old site. */
|
|
92
|
+
from: string;
|
|
93
|
+
/** Where it is on the new one. */
|
|
94
|
+
to: string;
|
|
95
|
+
state: AiSiteImportRowState;
|
|
96
|
+
/** Why it failed or was left out, or what the person should know. */
|
|
97
|
+
note: string | null;
|
|
98
|
+
/** "3 photos added, 1 already in your library". */
|
|
99
|
+
photos: string | null;
|
|
100
|
+
/** The draft the row wrote, by its output id. */
|
|
101
|
+
outputId: string | null;
|
|
102
|
+
}
|
|
103
|
+
/** "3 photos added", "2 photos added, 1 already in your library". */
|
|
104
|
+
export declare function aiSiteImportPhotosText(photos: {
|
|
105
|
+
brought: number;
|
|
106
|
+
reused: number;
|
|
107
|
+
} | null | undefined): string | null;
|
|
108
|
+
/** One wave's rows, the header and footer first where the wave builds them. */
|
|
109
|
+
export declare function aiSiteImportWaveRows(job: Pick<AiJobSummary, 'items' | 'siteImport' | 'status'>, wave: AiSiteImportWave): AiSiteImportRowView[];
|
|
110
|
+
/** "About 189 credits (up to 650)" for the wave, as it stands. */
|
|
111
|
+
export declare function aiSiteImportWaveQuote(job: Pick<AiJobSummary, 'items' | 'siteImport'>, wave: AiSiteImportWave): string;
|
|
112
|
+
/** What a wave cost, its pages' credits less what was given back. */
|
|
113
|
+
export declare function aiSiteImportWaveSpent(job: Pick<AiJobSummary, 'items'>, wave: AiSiteImportWave): number;
|
|
114
|
+
/** The read site in one sentence: "Found 21 pages on harbor-dental.com: Main pages (6) and Blog (14)." */
|
|
115
|
+
export declare function aiSiteImportFoundText(state: AiSiteImportState): string;
|
|
116
|
+
/** The plan's page count against the site: "Your plan includes 25 pages and this site has 0, so 20 are brought in." */
|
|
117
|
+
export declare function aiSiteImportPlanText(state: AiSiteImportState): string;
|
|
118
|
+
/** What was left out, by reason, most first. */
|
|
119
|
+
export declare function aiSiteImportLeftOutLines(state: AiSiteImportState): Array<{
|
|
120
|
+
reason: AiSiteImportLeftOutReason;
|
|
121
|
+
count: number;
|
|
122
|
+
text: string;
|
|
123
|
+
paths: string[];
|
|
124
|
+
}>;
|
|
125
|
+
/** The wave a page offers to start next, and its button's words. */
|
|
126
|
+
export declare function aiSiteImportStartAction(job: Pick<AiJobSummary, 'siteImport' | 'items'>): {
|
|
127
|
+
wave: AiSiteImportWave;
|
|
128
|
+
label: string;
|
|
129
|
+
quote: string;
|
|
130
|
+
} | null;
|
|
@@ -0,0 +1,182 @@
|
|
|
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
|
+
* BRING MY SITE, AS THE CONSOLE SHOWS IT (AGL-3976).
|
|
18
|
+
*
|
|
19
|
+
* Pure: what the "Create site" choice card says before anyone clicks, and
|
|
20
|
+
* what an import job's page shows in each of its states — the site read and
|
|
21
|
+
* its waves planned, a wave running, a wave in for review, a wave held for a
|
|
22
|
+
* proof or the day's limit, the import done. The components draw these; the
|
|
23
|
+
* specs hold them.
|
|
24
|
+
*=========================================*/ import { aiCreditRangeText } from "./ai-credit-estimate.js";
|
|
25
|
+
import { AI_SITE_IMPORT_FRAME_SLOT, AI_SITE_IMPORT_LEFT_OUT_COPY, AI_SITE_IMPORT_LEFT_OUT_REASONS, aiSiteImportNextWave, aiSiteImportPagesText, aiSiteImportReviewWave, aiSiteImportRunningWave, aiSiteImportWaveCreditRange } from "./ai-site-import.js";
|
|
26
|
+
/** What the card says to a plan that does not include it. */ export const AI_SITE_IMPORT_PLAN_COPY = 'Bring your current website in, every page and photo, on any paid plan. Upgrade to bring yours in.';
|
|
27
|
+
/** What the card says to a member who cannot. */ export const AI_SITE_IMPORT_ROLE_COPY = 'Only the workspace owner or an admin can bring a site in.';
|
|
28
|
+
/**
|
|
29
|
+
* The jobs list's `siteImport` offer (AGL-3976), as the card's state: absent
|
|
30
|
+
* is the flag off, and the card is not drawn; `plan` and `role` are drawn
|
|
31
|
+
* disabled with the reason.
|
|
32
|
+
*/ export function aiSiteImportOfferOf(offer) {
|
|
33
|
+
if (offer === 'ready') return {
|
|
34
|
+
state: 'ready',
|
|
35
|
+
claims: []
|
|
36
|
+
};
|
|
37
|
+
if (offer === 'plan') return {
|
|
38
|
+
state: 'blocked',
|
|
39
|
+
reason: 'plan',
|
|
40
|
+
message: AI_SITE_IMPORT_PLAN_COPY
|
|
41
|
+
};
|
|
42
|
+
if (offer === 'role') return {
|
|
43
|
+
state: 'blocked',
|
|
44
|
+
reason: 'role',
|
|
45
|
+
message: AI_SITE_IMPORT_ROLE_COPY
|
|
46
|
+
};
|
|
47
|
+
return {
|
|
48
|
+
state: 'hidden'
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export function aiSiteImportPhaseOf(job) {
|
|
52
|
+
var _job_siteImport;
|
|
53
|
+
const state = (_job_siteImport = job.siteImport) != null ? _job_siteImport : null;
|
|
54
|
+
if (job.status === 'done') return 'done';
|
|
55
|
+
if (job.status === 'failed' || job.status === 'canceled') return 'stopped';
|
|
56
|
+
if (job.status === 'needs_input') return 'paused';
|
|
57
|
+
if (job.status === 'needs_review') {
|
|
58
|
+
var _job_review;
|
|
59
|
+
if (((_job_review = job.review) == null ? void 0 : _job_review.reason) !== 'wave' || !state) return 'held';
|
|
60
|
+
return aiSiteImportReviewWave(state) ? 'review' : 'ready';
|
|
61
|
+
}
|
|
62
|
+
if (!state) return 'reading';
|
|
63
|
+
return aiSiteImportRunningWave(state) ? 'running' : 'starting';
|
|
64
|
+
}
|
|
65
|
+
function rowState(row, active) {
|
|
66
|
+
if (!row) return 'waiting';
|
|
67
|
+
if (row.status === 'succeeded' || row.status === 'degraded') return 'done';
|
|
68
|
+
if (row.status === 'failed') return 'failed';
|
|
69
|
+
if (row.status === 'skipped') return 'skipped';
|
|
70
|
+
return active ? 'active' : 'waiting';
|
|
71
|
+
}
|
|
72
|
+
/** "3 photos added", "2 photos added, 1 already in your library". */ export function aiSiteImportPhotosText(photos) {
|
|
73
|
+
if (!photos || photos.brought + photos.reused === 0) return null;
|
|
74
|
+
const added = photos.brought ? `${photos.brought} ${photos.brought === 1 ? 'photo' : 'photos'} added` : '';
|
|
75
|
+
const reused = photos.reused ? `${photos.reused} already in your media library` : '';
|
|
76
|
+
return [
|
|
77
|
+
added,
|
|
78
|
+
reused
|
|
79
|
+
].filter(Boolean).join(', ');
|
|
80
|
+
}
|
|
81
|
+
/** One wave's rows, the header and footer first where the wave builds them. */ export function aiSiteImportWaveRows(job, wave) {
|
|
82
|
+
var _job_items;
|
|
83
|
+
const state = job.siteImport;
|
|
84
|
+
const items = new Map(((_job_items = job.items) != null ? _job_items : []).map((row)=>[
|
|
85
|
+
row.slot,
|
|
86
|
+
row
|
|
87
|
+
]));
|
|
88
|
+
const running = wave.status === 'running' && (job.status === 'running' || job.status === 'queued');
|
|
89
|
+
let activeTaken = false;
|
|
90
|
+
const active = (row)=>{
|
|
91
|
+
if (!running || activeTaken || !row || row.status !== 'pending' && row.status !== 'running') return false;
|
|
92
|
+
activeTaken = true;
|
|
93
|
+
return true;
|
|
94
|
+
};
|
|
95
|
+
const rows = [];
|
|
96
|
+
if (wave.frame && state.frame) {
|
|
97
|
+
var _ref, _ref1, _ref2;
|
|
98
|
+
var _row_failure;
|
|
99
|
+
const row = items.get(AI_SITE_IMPORT_FRAME_SLOT);
|
|
100
|
+
rows.push({
|
|
101
|
+
slot: AI_SITE_IMPORT_FRAME_SLOT,
|
|
102
|
+
title: 'Header and footer',
|
|
103
|
+
from: `Your menu on ${state.domain}`,
|
|
104
|
+
to: 'Every page',
|
|
105
|
+
state: rowState(row, active(row)),
|
|
106
|
+
note: (_ref = (_ref1 = row == null ? void 0 : (_row_failure = row.failure) == null ? void 0 : _row_failure.message) != null ? _ref1 : row == null ? void 0 : row.note) != null ? _ref : null,
|
|
107
|
+
photos: null,
|
|
108
|
+
outputId: (_ref2 = row == null ? void 0 : row.outputs[0]) != null ? _ref2 : null
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
for (const slot of wave.slots){
|
|
112
|
+
var _ref3, _ref4, _ref5;
|
|
113
|
+
var _row_failure1;
|
|
114
|
+
const page = state.pages.find((entry)=>entry.slot === slot);
|
|
115
|
+
if (!page) continue;
|
|
116
|
+
const row = items.get(slot);
|
|
117
|
+
rows.push({
|
|
118
|
+
slot,
|
|
119
|
+
title: page.title,
|
|
120
|
+
from: page.path,
|
|
121
|
+
to: page.slug === '/' ? '/' : `/${page.slug}`,
|
|
122
|
+
state: rowState(row, active(row)),
|
|
123
|
+
note: (_ref3 = (_ref4 = row == null ? void 0 : (_row_failure1 = row.failure) == null ? void 0 : _row_failure1.message) != null ? _ref4 : row == null ? void 0 : row.note) != null ? _ref3 : page.refused ? AI_SITE_IMPORT_LEFT_OUT_COPY[page.refused] : null,
|
|
124
|
+
photos: aiSiteImportPhotosText(page.photos),
|
|
125
|
+
outputId: (_ref5 = row == null ? void 0 : row.outputs[0]) != null ? _ref5 : null
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
return rows;
|
|
129
|
+
}
|
|
130
|
+
/** "About 189 credits (up to 650)" for the wave, as it stands. */ export function aiSiteImportWaveQuote(job, wave) {
|
|
131
|
+
var _job_items;
|
|
132
|
+
return aiCreditRangeText(aiSiteImportWaveCreditRange(job.siteImport, wave, (_job_items = job.items) != null ? _job_items : null));
|
|
133
|
+
}
|
|
134
|
+
/** What a wave cost, its pages' credits less what was given back. */ export function aiSiteImportWaveSpent(job, wave) {
|
|
135
|
+
var _job_items;
|
|
136
|
+
const slots = new Set([
|
|
137
|
+
...wave.slots,
|
|
138
|
+
...wave.frame ? [
|
|
139
|
+
AI_SITE_IMPORT_FRAME_SLOT
|
|
140
|
+
] : []
|
|
141
|
+
]);
|
|
142
|
+
return ((_job_items = job.items) != null ? _job_items : []).filter((row)=>slots.has(row.slot)).reduce((total, row)=>{
|
|
143
|
+
var _row_creditsSpent, _row_creditsRefunded;
|
|
144
|
+
return total + Math.max(0, ((_row_creditsSpent = row.creditsSpent) != null ? _row_creditsSpent : 0) - ((_row_creditsRefunded = row.creditsRefunded) != null ? _row_creditsRefunded : 0));
|
|
145
|
+
}, 0);
|
|
146
|
+
}
|
|
147
|
+
/** The read site in one sentence: "Found 21 pages on harbor-dental.com: Main pages (6) and Blog (14)." */ export function aiSiteImportFoundText(state) {
|
|
148
|
+
const groups = state.groups.map((group)=>`${group.label} (${group.pages})`);
|
|
149
|
+
const listed = groups.length <= 1 ? groups.join('') : `${groups.slice(0, -1).join(', ')} and ${groups[groups.length - 1]}`;
|
|
150
|
+
const found = `Found ${aiSiteImportPagesText(state.found)} on ${state.domain}`;
|
|
151
|
+
return listed ? `${found}: ${listed}.` : `${found}.`;
|
|
152
|
+
}
|
|
153
|
+
/** The plan's page count against the site: "Your plan includes 25 pages and this site has 0, so 20 are brought in." */ export function aiSiteImportPlanText(state) {
|
|
154
|
+
const kept = state.pages.length;
|
|
155
|
+
const waves = state.waves.length;
|
|
156
|
+
const plan = state.pageLimit === null ? 'Your plan has no page limit' : `Your plan includes ${aiSiteImportPagesText(state.pageLimit)} and this site has ${state.existingPages}`;
|
|
157
|
+
return `${plan}, so ${aiSiteImportPagesText(kept)} ${kept === 1 ? 'is' : 'are'} brought in, in ${waves === 1 ? 'one wave' : `${waves} waves`}.`;
|
|
158
|
+
}
|
|
159
|
+
/** What was left out, by reason, most first. */ export function aiSiteImportLeftOutLines(state) {
|
|
160
|
+
return AI_SITE_IMPORT_LEFT_OUT_REASONS.map((reason)=>{
|
|
161
|
+
var _state_leftOutCount_reason;
|
|
162
|
+
return {
|
|
163
|
+
reason,
|
|
164
|
+
count: (_state_leftOutCount_reason = state.leftOutCount[reason]) != null ? _state_leftOutCount_reason : 0,
|
|
165
|
+
text: AI_SITE_IMPORT_LEFT_OUT_COPY[reason],
|
|
166
|
+
paths: state.leftOut.filter((entry)=>entry.reason === reason).map((entry)=>entry.path)
|
|
167
|
+
};
|
|
168
|
+
}).filter((line)=>line.count > 0).sort((a, b)=>b.count - a.count);
|
|
169
|
+
}
|
|
170
|
+
/** The wave a page offers to start next, and its button's words. */ export function aiSiteImportStartAction(job) {
|
|
171
|
+
var _job_siteImport;
|
|
172
|
+
const state = (_job_siteImport = job.siteImport) != null ? _job_siteImport : null;
|
|
173
|
+
const wave = aiSiteImportNextWave(state);
|
|
174
|
+
if (!state || !wave) return null;
|
|
175
|
+
return {
|
|
176
|
+
wave,
|
|
177
|
+
label: `Start ${wave.label}`,
|
|
178
|
+
quote: aiSiteImportWaveQuote(job, wave)
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
//# sourceMappingURL=ai-site-import-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/model/ai-site-import-view.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\n/*==========================================\n * BRING MY SITE, AS THE CONSOLE SHOWS IT (AGL-3976).\n *\n * Pure: what the \"Create site\" choice card says before anyone clicks, and\n * what an import job's page shows in each of its states — the site read and\n * its waves planned, a wave running, a wave in for review, a wave held for a\n * proof or the day's limit, the import done. The components draw these; the\n * specs hold them.\n *=========================================*/\n\nimport { aiCreditRangeText } from './ai-credit-estimate'\nimport type { AiJobItemLedger, AiJobSummary } from './ai-jobs.types'\nimport {\n AI_SITE_IMPORT_FRAME_SLOT,\n AI_SITE_IMPORT_LEFT_OUT_COPY,\n AI_SITE_IMPORT_LEFT_OUT_REASONS,\n aiSiteImportNextWave,\n aiSiteImportPagesText,\n aiSiteImportReviewWave,\n aiSiteImportRunningWave,\n aiSiteImportWaveCreditRange,\n type AiSiteImportLeftOutReason,\n type AiSiteImportState,\n type AiSiteImportWave,\n} from './ai-site-import'\n\n/** A domain ownership claim, as the ownership door answers it. */\nexport interface AiSiteImportClaim {\n domain: string\n status: 'pending' | 'proven'\n current: boolean\n provenMethod: 'dns' | 'meta' | 'email' | null\n provenAt: number | null\n provenDetail: string | null\n lastChecks: Partial<Record<'dns' | 'meta' | 'email', 'proven' | 'not-yet' | 'unreachable'>>\n dns: { host: string; type: 'TXT'; value: string }\n meta: { name: string; content: string; tag: string }\n email: { domain: string; pendingAddress: string | null; expiresAt: number | null; attemptsLeft: number | null }\n}\n\n/** Whether \"Bring my site\" is offered here, and if not why. */\nexport type AiSiteImportAvailability =\n | { state: 'checking' }\n /** The release flag is off, or the doors cannot be reached: the card is not drawn. */\n | { state: 'hidden' }\n /** Something the workspace can change stands in the way: the card is drawn disabled, with the reason. */\n | { state: 'blocked'; reason: 'plan' | 'role'; message: string }\n | { state: 'ready'; claims: AiSiteImportClaim[] }\n\n/** What the card says to a plan that does not include it. */\nexport const AI_SITE_IMPORT_PLAN_COPY =\n 'Bring your current website in, every page and photo, on any paid plan. Upgrade to bring yours in.'\n\n/** What the card says to a member who cannot. */\nexport const AI_SITE_IMPORT_ROLE_COPY = 'Only the workspace owner or an admin can bring a site in.'\n\n/**\n * The jobs list's `siteImport` offer (AGL-3976), as the card's state: absent\n * is the flag off, and the card is not drawn; `plan` and `role` are drawn\n * disabled with the reason.\n */\nexport function aiSiteImportOfferOf(offer: unknown): AiSiteImportAvailability {\n if (offer === 'ready') return { state: 'ready', claims: [] }\n if (offer === 'plan') return { state: 'blocked', reason: 'plan', message: AI_SITE_IMPORT_PLAN_COPY }\n if (offer === 'role') return { state: 'blocked', reason: 'role', message: AI_SITE_IMPORT_ROLE_COPY }\n return { state: 'hidden' }\n}\n\n/** Where an import job's page is. */\nexport type AiSiteImportPhase =\n /** The site is being read. */\n | 'reading'\n /** Read and planned; the first wave waits to be started. */\n | 'ready'\n /** A wave was started and has not begun yet. */\n | 'starting'\n | 'running'\n /** A wave is in; the next waits to be started. */\n | 'review'\n /** Held for something the person does: verify again, wait for tomorrow, read again. */\n | 'held'\n /** Out of AI credits or at a cap: the meter's pause, carried on by Resume. */\n | 'paused'\n | 'done'\n | 'stopped'\n\nexport function aiSiteImportPhaseOf(job: Pick<AiJobSummary, 'status' | 'review' | 'siteImport'>): AiSiteImportPhase {\n const state = job.siteImport ?? null\n if (job.status === 'done') return 'done'\n if (job.status === 'failed' || job.status === 'canceled') return 'stopped'\n if (job.status === 'needs_input') return 'paused'\n if (job.status === 'needs_review') {\n if (job.review?.reason !== 'wave' || !state) return 'held'\n return aiSiteImportReviewWave(state) ? 'review' : 'ready'\n }\n if (!state) return 'reading'\n return aiSiteImportRunningWave(state) ? 'running' : 'starting'\n}\n\nexport type AiSiteImportRowState = 'waiting' | 'active' | 'done' | 'failed' | 'skipped'\n\nexport interface AiSiteImportRowView {\n slot: string\n title: string\n /** Where it is on the old site. */\n from: string\n /** Where it is on the new one. */\n to: string\n state: AiSiteImportRowState\n /** Why it failed or was left out, or what the person should know. */\n note: string | null\n /** \"3 photos added, 1 already in your library\". */\n photos: string | null\n /** The draft the row wrote, by its output id. */\n outputId: string | null\n}\n\nfunction rowState(row: AiJobItemLedger | undefined, active: boolean): AiSiteImportRowState {\n if (!row) return 'waiting'\n if (row.status === 'succeeded' || row.status === 'degraded') return 'done'\n if (row.status === 'failed') return 'failed'\n if (row.status === 'skipped') return 'skipped'\n return active ? 'active' : 'waiting'\n}\n\n/** \"3 photos added\", \"2 photos added, 1 already in your library\". */\nexport function aiSiteImportPhotosText(photos: { brought: number; reused: number } | null | undefined): string | null {\n if (!photos || photos.brought + photos.reused === 0) return null\n const added = photos.brought ? `${photos.brought} ${photos.brought === 1 ? 'photo' : 'photos'} added` : ''\n const reused = photos.reused ? `${photos.reused} already in your media library` : ''\n return [added, reused].filter(Boolean).join(', ')\n}\n\n/** One wave's rows, the header and footer first where the wave builds them. */\nexport function aiSiteImportWaveRows(\n job: Pick<AiJobSummary, 'items' | 'siteImport' | 'status'>,\n wave: AiSiteImportWave,\n): AiSiteImportRowView[] {\n const state = job.siteImport as AiSiteImportState\n const items = new Map((job.items ?? []).map((row) => [row.slot, row]))\n const running = wave.status === 'running' && (job.status === 'running' || job.status === 'queued')\n let activeTaken = false\n const active = (row: AiJobItemLedger | undefined) => {\n if (!running || activeTaken || !row || (row.status !== 'pending' && row.status !== 'running')) return false\n activeTaken = true\n return true\n }\n const rows: AiSiteImportRowView[] = []\n if (wave.frame && state.frame) {\n const row = items.get(AI_SITE_IMPORT_FRAME_SLOT)\n rows.push({\n slot: AI_SITE_IMPORT_FRAME_SLOT,\n title: 'Header and footer',\n from: `Your menu on ${state.domain}`,\n to: 'Every page',\n state: rowState(row, active(row)),\n note: row?.failure?.message ?? row?.note ?? null,\n photos: null,\n outputId: row?.outputs[0] ?? null,\n })\n }\n for (const slot of wave.slots) {\n const page = state.pages.find((entry) => entry.slot === slot)\n if (!page) continue\n const row = items.get(slot)\n rows.push({\n slot,\n title: page.title,\n from: page.path,\n to: page.slug === '/' ? '/' : `/${page.slug}`,\n state: rowState(row, active(row)),\n note: row?.failure?.message ?? row?.note ?? (page.refused ? AI_SITE_IMPORT_LEFT_OUT_COPY[page.refused] : null),\n photos: aiSiteImportPhotosText(page.photos),\n outputId: row?.outputs[0] ?? null,\n })\n }\n return rows\n}\n\n/** \"About 189 credits (up to 650)\" for the wave, as it stands. */\nexport function aiSiteImportWaveQuote(job: Pick<AiJobSummary, 'items' | 'siteImport'>, wave: AiSiteImportWave): string {\n return aiCreditRangeText(aiSiteImportWaveCreditRange(job.siteImport as AiSiteImportState, wave, job.items ?? null))\n}\n\n/** What a wave cost, its pages' credits less what was given back. */\nexport function aiSiteImportWaveSpent(job: Pick<AiJobSummary, 'items'>, wave: AiSiteImportWave): number {\n const slots = new Set([...wave.slots, ...(wave.frame ? [AI_SITE_IMPORT_FRAME_SLOT] : [])])\n return (job.items ?? [])\n .filter((row) => slots.has(row.slot))\n .reduce((total, row) => total + Math.max(0, (row.creditsSpent ?? 0) - (row.creditsRefunded ?? 0)), 0)\n}\n\n/** The read site in one sentence: \"Found 21 pages on harbor-dental.com: Main pages (6) and Blog (14).\" */\nexport function aiSiteImportFoundText(state: AiSiteImportState): string {\n const groups = state.groups.map((group) => `${group.label} (${group.pages})`)\n const listed =\n groups.length <= 1 ? groups.join('') : `${groups.slice(0, -1).join(', ')} and ${groups[groups.length - 1]}`\n const found = `Found ${aiSiteImportPagesText(state.found)} on ${state.domain}`\n return listed ? `${found}: ${listed}.` : `${found}.`\n}\n\n/** The plan's page count against the site: \"Your plan includes 25 pages and this site has 0, so 20 are brought in.\" */\nexport function aiSiteImportPlanText(state: AiSiteImportState): string {\n const kept = state.pages.length\n const waves = state.waves.length\n const plan =\n state.pageLimit === null\n ? 'Your plan has no page limit'\n : `Your plan includes ${aiSiteImportPagesText(state.pageLimit)} and this site has ${state.existingPages}`\n return `${plan}, so ${aiSiteImportPagesText(kept)} ${kept === 1 ? 'is' : 'are'} brought in, in ${waves === 1 ? 'one wave' : `${waves} waves`}.`\n}\n\n/** What was left out, by reason, most first. */\nexport function aiSiteImportLeftOutLines(state: AiSiteImportState): Array<{ reason: AiSiteImportLeftOutReason; count: number; text: string; paths: string[] }> {\n return AI_SITE_IMPORT_LEFT_OUT_REASONS.map((reason) => ({\n reason,\n count: state.leftOutCount[reason] ?? 0,\n text: AI_SITE_IMPORT_LEFT_OUT_COPY[reason],\n paths: state.leftOut.filter((entry) => entry.reason === reason).map((entry) => entry.path),\n }))\n .filter((line) => line.count > 0)\n .sort((a, b) => b.count - a.count)\n}\n\n/** The wave a page offers to start next, and its button's words. */\nexport function aiSiteImportStartAction(\n job: Pick<AiJobSummary, 'siteImport' | 'items'>,\n): { wave: AiSiteImportWave; label: string; quote: string } | null {\n const state = job.siteImport ?? null\n const wave = aiSiteImportNextWave(state)\n if (!state || !wave) return null\n return { wave, label: `Start ${wave.label}`, quote: aiSiteImportWaveQuote(job, wave) }\n}\n"],"names":["aiCreditRangeText","AI_SITE_IMPORT_FRAME_SLOT","AI_SITE_IMPORT_LEFT_OUT_COPY","AI_SITE_IMPORT_LEFT_OUT_REASONS","aiSiteImportNextWave","aiSiteImportPagesText","aiSiteImportReviewWave","aiSiteImportRunningWave","aiSiteImportWaveCreditRange","AI_SITE_IMPORT_PLAN_COPY","AI_SITE_IMPORT_ROLE_COPY","aiSiteImportOfferOf","offer","state","claims","reason","message","aiSiteImportPhaseOf","job","siteImport","status","review","rowState","row","active","aiSiteImportPhotosText","photos","brought","reused","added","filter","Boolean","join","aiSiteImportWaveRows","wave","items","Map","map","slot","running","activeTaken","rows","frame","get","push","title","from","domain","to","note","failure","outputId","outputs","slots","page","pages","find","entry","path","slug","refused","aiSiteImportWaveQuote","aiSiteImportWaveSpent","Set","has","reduce","total","Math","max","creditsSpent","creditsRefunded","aiSiteImportFoundText","groups","group","label","listed","length","slice","found","aiSiteImportPlanText","kept","waves","plan","pageLimit","existingPages","aiSiteImportLeftOutLines","count","leftOutCount","text","paths","leftOut","line","sort","a","b","aiSiteImportStartAction","quote"],"mappings":"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"}
|
|
@@ -0,0 +1,302 @@
|
|
|
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 AiCreditRange } from './ai-credit-estimate';
|
|
18
|
+
import type { AiJobItemLedger } from './ai-jobs.types';
|
|
19
|
+
/** The job kind. */
|
|
20
|
+
export declare const AI_SITE_IMPORT_KIND: "import";
|
|
21
|
+
/** The input naming the proved domain the job brings in. */
|
|
22
|
+
export declare const AI_SITE_IMPORT_DOMAIN_INPUT = "domain";
|
|
23
|
+
/** The most pages one wave brings in. */
|
|
24
|
+
export declare const AI_SITE_IMPORT_WAVE_PAGES = 10;
|
|
25
|
+
/**
|
|
26
|
+
* The most pages one import reads, whatever the plan allows: an unlimited
|
|
27
|
+
* plan is still one crawl's worth, and the crawl's own time budget may stop
|
|
28
|
+
* sooner (the inventory then says so).
|
|
29
|
+
*/
|
|
30
|
+
export declare const AI_SITE_IMPORT_MAX_PAGES = 200;
|
|
31
|
+
/** The fewest pages under one address prefix that make it a collection. */
|
|
32
|
+
export declare const AI_SITE_IMPORT_COLLECTION_MIN = 3;
|
|
33
|
+
/** The most photos brought in from one page. */
|
|
34
|
+
export declare const AI_SITE_IMPORT_IMAGES_PER_PAGE = 8;
|
|
35
|
+
/** The most characters of one page's text a wave keeps for its model answer. */
|
|
36
|
+
export declare const AI_SITE_IMPORT_PAGE_TEXT_MAX_CHARS = 6000;
|
|
37
|
+
/** The most sections one imported page is planned with. */
|
|
38
|
+
export declare const AI_SITE_IMPORT_MAX_SECTIONS = 6;
|
|
39
|
+
/** The most characters a section's name, a page's title or a label keeps. */
|
|
40
|
+
export declare const AI_SITE_IMPORT_LABEL_MAX_CHARS = 60;
|
|
41
|
+
/** A page with fewer words than this and no photo has nothing to bring in. */
|
|
42
|
+
export declare const AI_SITE_IMPORT_MIN_WORDS = 5;
|
|
43
|
+
/** The item ledger slot of the site's header and footer. */
|
|
44
|
+
export declare const AI_SITE_IMPORT_FRAME_SLOT = "frame";
|
|
45
|
+
/** The ceiling one imported page reserves: its answer pass and its listing pass, at 50 each. */
|
|
46
|
+
export declare const AI_SITE_IMPORT_PAGE_CEILING_CREDITS = 100;
|
|
47
|
+
/** The ceiling the header and footer reserve: one answer at 50. */
|
|
48
|
+
export declare const AI_SITE_IMPORT_FRAME_CEILING_CREDITS = 50;
|
|
49
|
+
/** The most left-out pages listed by address; the rest are counted. */
|
|
50
|
+
export declare const AI_SITE_IMPORT_LEFT_OUT_LISTED = 60;
|
|
51
|
+
/** A page the crawl read, as the inventory keeps it: no text, only what plans it. */
|
|
52
|
+
export interface AiSiteImportListedPage {
|
|
53
|
+
url: string;
|
|
54
|
+
path: string;
|
|
55
|
+
title: string;
|
|
56
|
+
foundBy: 'home' | 'sitemap' | 'link';
|
|
57
|
+
words: number;
|
|
58
|
+
images: number;
|
|
59
|
+
}
|
|
60
|
+
export type AiSiteImportGroupKind = 'main' | 'collection';
|
|
61
|
+
export interface AiSiteImportGroup {
|
|
62
|
+
/** `main`, or `c:<prefix>` for a collection. */
|
|
63
|
+
id: string;
|
|
64
|
+
label: string;
|
|
65
|
+
kind: AiSiteImportGroupKind;
|
|
66
|
+
/** Pages of the group the crawl read, kept or not. */
|
|
67
|
+
pages: number;
|
|
68
|
+
}
|
|
69
|
+
/** Why a page the site has is not brought in. */
|
|
70
|
+
export type AiSiteImportLeftOutReason =
|
|
71
|
+
/** Past the site's room under its plan's page count. */
|
|
72
|
+
'plan-limit'
|
|
73
|
+
/** robots.txt keeps AglynBot off it. */
|
|
74
|
+
| 'robots'
|
|
75
|
+
/** A sign-in page: refused outright. */
|
|
76
|
+
| 'login-form'
|
|
77
|
+
/** No text and no photo: nothing to bring in. */
|
|
78
|
+
| 'empty'
|
|
79
|
+
/** It could not be read: an error, no answer, or not a web page. */
|
|
80
|
+
| 'unreadable'
|
|
81
|
+
/** Over the size one page may be. */
|
|
82
|
+
| 'too-large'
|
|
83
|
+
/** It sends visitors to another website. */
|
|
84
|
+
| 'off-site';
|
|
85
|
+
export declare const AI_SITE_IMPORT_LEFT_OUT_REASONS: readonly AiSiteImportLeftOutReason[];
|
|
86
|
+
export interface AiSiteImportLeftOut {
|
|
87
|
+
url: string;
|
|
88
|
+
path: string;
|
|
89
|
+
title: string;
|
|
90
|
+
reason: AiSiteImportLeftOutReason;
|
|
91
|
+
}
|
|
92
|
+
/** A photo brought into the site's media library, as a page places it. */
|
|
93
|
+
export interface AiSiteImportPhoto {
|
|
94
|
+
mediaId: string;
|
|
95
|
+
src: string;
|
|
96
|
+
width?: number;
|
|
97
|
+
height?: number;
|
|
98
|
+
alt?: string;
|
|
99
|
+
}
|
|
100
|
+
/** What a wave's read found on one page, for its model answer. Never on the wire. */
|
|
101
|
+
export interface AiSiteImportPageRead {
|
|
102
|
+
at: string;
|
|
103
|
+
title: string;
|
|
104
|
+
/** The page's text in order, cut to `AI_SITE_IMPORT_PAGE_TEXT_MAX_CHARS`; fenced only when a prompt reads it. */
|
|
105
|
+
text: string;
|
|
106
|
+
/** The page's sections, from its headings. */
|
|
107
|
+
sections: string[];
|
|
108
|
+
/** Its photos' addresses, at most `AI_SITE_IMPORT_IMAGES_PER_PAGE`. */
|
|
109
|
+
images: Array<{
|
|
110
|
+
url: string;
|
|
111
|
+
alt: string;
|
|
112
|
+
}>;
|
|
113
|
+
}
|
|
114
|
+
export interface AiSiteImportPage {
|
|
115
|
+
/** The item ledger slot: `p0`, `p1`, … */
|
|
116
|
+
slot: string;
|
|
117
|
+
url: string;
|
|
118
|
+
path: string;
|
|
119
|
+
title: string;
|
|
120
|
+
group: string;
|
|
121
|
+
wave: number;
|
|
122
|
+
/** The id the page's draft is written under, minted with the inventory. */
|
|
123
|
+
draftId: string;
|
|
124
|
+
/** The page's address on the new site. */
|
|
125
|
+
slug: string;
|
|
126
|
+
words: number;
|
|
127
|
+
images: number;
|
|
128
|
+
/** Filled by the wave's read; the text is cleared once the page is in. */
|
|
129
|
+
read?: AiSiteImportPageRead | null;
|
|
130
|
+
/** Set when the wave's read found the page cannot be brought in after all. */
|
|
131
|
+
refused?: AiSiteImportLeftOutReason | null;
|
|
132
|
+
/** Filled once the page's photos are in the library. */
|
|
133
|
+
photos?: {
|
|
134
|
+
brought: number;
|
|
135
|
+
/** Already in the library from an earlier page or import: the same file, never a second copy. */
|
|
136
|
+
reused: number;
|
|
137
|
+
skipped: number;
|
|
138
|
+
assets: AiSiteImportPhoto[];
|
|
139
|
+
} | null;
|
|
140
|
+
}
|
|
141
|
+
export type AiSiteImportWaveStatus = 'waiting' | 'running' | 'review' | 'done';
|
|
142
|
+
export interface AiSiteImportWave {
|
|
143
|
+
index: number;
|
|
144
|
+
label: string;
|
|
145
|
+
/** The group the wave brings in; the first wave's is `main`. */
|
|
146
|
+
group: string;
|
|
147
|
+
slots: string[];
|
|
148
|
+
/** Whether the wave builds the site's header and footer first. */
|
|
149
|
+
frame: boolean;
|
|
150
|
+
status: AiSiteImportWaveStatus;
|
|
151
|
+
startedAt: string | null;
|
|
152
|
+
finishedAt: string | null;
|
|
153
|
+
}
|
|
154
|
+
export interface AiSiteImportState {
|
|
155
|
+
domain: string;
|
|
156
|
+
/** The site's name, as Create site was given it: the header's name. */
|
|
157
|
+
siteName: string;
|
|
158
|
+
ownership: {
|
|
159
|
+
method: string | null;
|
|
160
|
+
provenAt: number | null;
|
|
161
|
+
detail: string | null;
|
|
162
|
+
};
|
|
163
|
+
readAt: string;
|
|
164
|
+
/** The plan's page count; `null` when it has none. */
|
|
165
|
+
pageLimit: number | null;
|
|
166
|
+
/** Pages the site already had when its import read the old site. */
|
|
167
|
+
existingPages: number;
|
|
168
|
+
/** Pages the crawl read. */
|
|
169
|
+
found: number;
|
|
170
|
+
/** Why the crawl stopped short of the whole site, or `null` when it did not. */
|
|
171
|
+
stoppedBy: string | null;
|
|
172
|
+
groups: AiSiteImportGroup[];
|
|
173
|
+
pages: AiSiteImportPage[];
|
|
174
|
+
waves: AiSiteImportWave[];
|
|
175
|
+
/** At most `AI_SITE_IMPORT_LEFT_OUT_LISTED`, by address. */
|
|
176
|
+
leftOut: AiSiteImportLeftOut[];
|
|
177
|
+
/** Every page left out, by reason, listed or not. */
|
|
178
|
+
leftOutCount: Partial<Record<AiSiteImportLeftOutReason, number>>;
|
|
179
|
+
/** The header and footer's draft id, built in the first wave; `null` when there are no main pages. */
|
|
180
|
+
frame: {
|
|
181
|
+
draftId: string;
|
|
182
|
+
} | null;
|
|
183
|
+
/** The Trust & Safety row this import is logged under. */
|
|
184
|
+
reviewId: string | null;
|
|
185
|
+
}
|
|
186
|
+
/** A collection's prefix for a page address: its first segment, a dated archive's `posts`; `null` for a top-level page. */
|
|
187
|
+
export declare function aiSiteImportPrefix(path: string): string | null;
|
|
188
|
+
/** "news-and-events" → "News and events". */
|
|
189
|
+
export declare function aiSiteImportPrefixLabel(prefix: string): string;
|
|
190
|
+
/**
|
|
191
|
+
* The inventory's groups, in the order they are brought in: the main pages,
|
|
192
|
+
* then each collection — one the home page's menu links first, in menu order,
|
|
193
|
+
* then the larger before the smaller.
|
|
194
|
+
*/
|
|
195
|
+
export declare function aiSiteImportGroups(pages: readonly AiSiteImportListedPage[], menu?: readonly string[]): {
|
|
196
|
+
groups: AiSiteImportGroup[];
|
|
197
|
+
groupOf: (page: AiSiteImportListedPage) => string;
|
|
198
|
+
};
|
|
199
|
+
/**
|
|
200
|
+
* The address a page takes on the new site: one segment, as every Aglyn page
|
|
201
|
+
* has, from the last segment of its old address; home is the root. Two pages
|
|
202
|
+
* that would take the same address are told apart by their collection, then
|
|
203
|
+
* by a number. The draft writer still makes it unique on the site itself.
|
|
204
|
+
*/
|
|
205
|
+
export declare function aiSiteImportSlug(path: string, taken: Set<string>): string;
|
|
206
|
+
export interface AiSiteImportInventoryInput {
|
|
207
|
+
domain: string;
|
|
208
|
+
siteName: string;
|
|
209
|
+
ownership: AiSiteImportState['ownership'];
|
|
210
|
+
readAt: string;
|
|
211
|
+
pages: readonly AiSiteImportListedPage[];
|
|
212
|
+
/** Addresses the home page's menu links, in its order. */
|
|
213
|
+
menu: readonly string[];
|
|
214
|
+
/** What the crawl could not read, by reason. */
|
|
215
|
+
skipped: ReadonlyArray<{
|
|
216
|
+
url: string;
|
|
217
|
+
reason: AiSiteImportLeftOutReason;
|
|
218
|
+
}>;
|
|
219
|
+
/** Skips the crawl only counted. */
|
|
220
|
+
skippedOverflow?: number;
|
|
221
|
+
stoppedBy: string | null;
|
|
222
|
+
/** The plan's page count; `null` for none. */
|
|
223
|
+
pageLimit: number | null;
|
|
224
|
+
existingPages: number;
|
|
225
|
+
/** Mints one draft id; the inventory names every page's draft before any is written. */
|
|
226
|
+
mintId: () => string;
|
|
227
|
+
reviewId?: string | null;
|
|
228
|
+
wavePages?: number;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* The site's inventory cut into waves, every page left out said with its
|
|
232
|
+
* reason. Pure: the step reads the site, this decides what comes in.
|
|
233
|
+
*/
|
|
234
|
+
export declare function aiSiteImportInventory(input: AiSiteImportInventoryInput): AiSiteImportState;
|
|
235
|
+
/** The item ledger an inventory starts: the header and footer, then every page, all pending. */
|
|
236
|
+
export declare function aiSiteImportLedger(state: AiSiteImportState): AiJobItemLedger[];
|
|
237
|
+
export type AiSiteImportWork = {
|
|
238
|
+
kind: 'inventory';
|
|
239
|
+
} | {
|
|
240
|
+
kind: 'start-wave';
|
|
241
|
+
wave: AiSiteImportWave;
|
|
242
|
+
}
|
|
243
|
+
/** Pages of the running wave its read did not reach before its clock ran out. */
|
|
244
|
+
| {
|
|
245
|
+
kind: 'read';
|
|
246
|
+
wave: AiSiteImportWave;
|
|
247
|
+
pages: AiSiteImportPage[];
|
|
248
|
+
} | {
|
|
249
|
+
kind: 'frame';
|
|
250
|
+
wave: AiSiteImportWave;
|
|
251
|
+
} | {
|
|
252
|
+
kind: 'images';
|
|
253
|
+
wave: AiSiteImportWave;
|
|
254
|
+
page: AiSiteImportPage;
|
|
255
|
+
} | {
|
|
256
|
+
kind: 'page';
|
|
257
|
+
wave: AiSiteImportWave;
|
|
258
|
+
page: AiSiteImportPage;
|
|
259
|
+
} | {
|
|
260
|
+
kind: 'close-wave';
|
|
261
|
+
wave: AiSiteImportWave;
|
|
262
|
+
} | {
|
|
263
|
+
kind: 'done';
|
|
264
|
+
};
|
|
265
|
+
/** Whether an item is still to be built. */
|
|
266
|
+
export declare function aiSiteImportItemOpen(items: readonly AiJobItemLedger[] | null | undefined, slot: string): boolean;
|
|
267
|
+
/** The wave running now, else `null`. */
|
|
268
|
+
export declare function aiSiteImportRunningWave(state: AiSiteImportState | null | undefined): AiSiteImportWave | null;
|
|
269
|
+
/** The next wave a person may start, else `null`. */
|
|
270
|
+
export declare function aiSiteImportNextWave(state: AiSiteImportState | null | undefined): AiSiteImportWave | null;
|
|
271
|
+
/** The wave a person is reviewing, else `null`. */
|
|
272
|
+
export declare function aiSiteImportReviewWave(state: AiSiteImportState | null | undefined): AiSiteImportWave | null;
|
|
273
|
+
/** What the next pass of the step does. */
|
|
274
|
+
export declare function aiSiteImportNextWork(state: AiSiteImportState | null | undefined, items: readonly AiJobItemLedger[] | null | undefined): AiSiteImportWork;
|
|
275
|
+
/** A wave started: running, with what its read found on each page. */
|
|
276
|
+
export declare function aiSiteImportWaveStarted(state: AiSiteImportState, index: number, at: string, reads: ReadonlyMap<string, AiSiteImportPageRead | AiSiteImportLeftOutReason>): AiSiteImportState;
|
|
277
|
+
/** More of a running wave's pages, read now. */
|
|
278
|
+
export declare function aiSiteImportPagesRead(state: AiSiteImportState, reads: ReadonlyMap<string, AiSiteImportPageRead | AiSiteImportLeftOutReason>): AiSiteImportState;
|
|
279
|
+
/** A page's photos are in the library. */
|
|
280
|
+
export declare function aiSiteImportPhotosIn(state: AiSiteImportState, slot: string, photos: NonNullable<AiSiteImportPage['photos']>): AiSiteImportState;
|
|
281
|
+
/** A page is in: its text is no longer kept. */
|
|
282
|
+
export declare function aiSiteImportPageSettled(state: AiSiteImportState, slot: string): AiSiteImportState;
|
|
283
|
+
/** A wave is in: waiting for its review, or done when no wave follows it. */
|
|
284
|
+
export declare function aiSiteImportWaveClosed(state: AiSiteImportState, index: number, at: string): AiSiteImportState;
|
|
285
|
+
/** The state as the console reads it: every page's read text left off. */
|
|
286
|
+
export declare function aiSiteImportWire(state: AiSiteImportState | null | undefined): AiSiteImportState | null;
|
|
287
|
+
/**
|
|
288
|
+
* What bringing in this many pages costs, quoted before it starts (AGL-3976):
|
|
289
|
+
* each page an AI page as measured, its ceiling its two passes, and the
|
|
290
|
+
* site's header and footer once when the wave builds them.
|
|
291
|
+
*/
|
|
292
|
+
export declare function aiSiteImportCreditRange(pages: number, options?: {
|
|
293
|
+
frame?: boolean;
|
|
294
|
+
}): AiCreditRange;
|
|
295
|
+
/** A wave's quote: the pages it has still to bring in, and its header and footer while they are owed. */
|
|
296
|
+
export declare function aiSiteImportWaveCreditRange(state: AiSiteImportState, wave: AiSiteImportWave, items?: readonly AiJobItemLedger[] | null): AiCreditRange;
|
|
297
|
+
/** Why a page is not brought in, as a person reads it. */
|
|
298
|
+
export declare const AI_SITE_IMPORT_LEFT_OUT_COPY: Readonly<Record<AiSiteImportLeftOutReason, string>>;
|
|
299
|
+
/** "3 pages" / "1 page". */
|
|
300
|
+
export declare function aiSiteImportPagesText(count: number): string;
|
|
301
|
+
/** The review a finished wave parks on, or the first wave's go-ahead once the site is read. */
|
|
302
|
+
export declare function aiSiteImportWaveMessage(state: AiSiteImportState, items: readonly AiJobItemLedger[] | null | undefined): string;
|