@aglyn/plugins-ai 1.0.0-beta.291 → 1.0.0-beta.293
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-site-import-job.component.js +5 -4
- package/src/lib/components/ai-site-import-job.component.js.map +1 -1
- package/src/lib/components/ai-site-import-start.component.js +3 -3
- package/src/lib/components/ai-site-import-start.component.js.map +1 -1
- package/src/lib/components/ai-site-start-card.component.d.ts +1 -1
- package/src/lib/components/ai-site-start-card.component.js +129 -29
- package/src/lib/components/ai-site-start-card.component.js.map +1 -1
- package/src/lib/components/ai-site-start-steps.component.d.ts +15 -3
- package/src/lib/components/ai-site-start-steps.component.js +42 -25
- package/src/lib/components/ai-site-start-steps.component.js.map +1 -1
- package/src/lib/components/ai-site-style-previews.d.ts +17 -0
- package/src/lib/components/ai-site-style-previews.js +26 -95
- package/src/lib/components/ai-site-style-previews.js.map +1 -1
- package/src/lib/declarations.server.js +22 -0
- package/src/lib/declarations.server.js.map +1 -1
- package/src/lib/jobs/ai-job-import-step.d.ts +21 -2
- package/src/lib/jobs/ai-job-import-step.js +179 -49
- package/src/lib/jobs/ai-job-import-step.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-language.d.ts +27 -3
- package/src/lib/jobs/ai-job-layout-language.js +156 -113
- package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-step.js +56 -17
- package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
- package/src/lib/jobs/ai-job-page-language.d.ts +25 -15
- package/src/lib/jobs/ai-job-page-language.js +120 -66
- package/src/lib/jobs/ai-job-page-language.js.map +1 -1
- package/src/lib/jobs/ai-job-page-step.js +27 -7
- package/src/lib/jobs/ai-job-page-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-datasets.d.ts +12 -4
- package/src/lib/jobs/ai-job-site-datasets.js +36 -16
- package/src/lib/jobs/ai-job-site-datasets.js.map +1 -1
- package/src/lib/jobs/ai-jobs.js +6 -2
- package/src/lib/jobs/ai-jobs.js.map +1 -1
- package/src/lib/jobs/ai-layout-stock-photos.d.ts +50 -1
- package/src/lib/jobs/ai-layout-stock-photos.js +586 -35
- package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
- package/src/lib/jobs/ai-site-import-compile.d.ts +147 -0
- package/src/lib/jobs/ai-site-import-compile.js +1143 -0
- package/src/lib/jobs/ai-site-import-compile.js.map +1 -0
- package/src/lib/jobs/ai-site-import-document.d.ts +9 -36
- package/src/lib/jobs/ai-site-import-document.js +23 -489
- package/src/lib/jobs/ai-site-import-document.js.map +1 -1
- package/src/lib/jobs/ai-site-import-look.d.ts +54 -7
- package/src/lib/jobs/ai-site-import-look.js +163 -52
- package/src/lib/jobs/ai-site-import-look.js.map +1 -1
- package/src/lib/jobs/ai-site-import-publish.d.ts +7 -1
- package/src/lib/jobs/ai-site-import-publish.js +19 -5
- package/src/lib/jobs/ai-site-import-publish.js.map +1 -1
- package/src/lib/jobs/ai-site-late-photos.js +4 -2
- package/src/lib/jobs/ai-site-late-photos.js.map +1 -1
- package/src/lib/jobs/ai-site-publish.d.ts +10 -1
- package/src/lib/jobs/ai-site-publish.js +8 -3
- package/src/lib/jobs/ai-site-publish.js.map +1 -1
- package/src/lib/jobs/fixtures/ai-stock-photo-agl4092-1029-recordings.d.ts +23 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl4092-1029-recordings.js +677 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl4092-1029-recordings.js.map +1 -0
- package/src/lib/layout-language/ai-layout-compiler.d.ts +26 -0
- package/src/lib/layout-language/ai-layout-compiler.js +677 -33
- package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
- package/src/lib/layout-language/ai-layout-frame-hollows.js +5 -1
- package/src/lib/layout-language/ai-layout-frame-hollows.js.map +1 -1
- package/src/lib/layout-language/ai-layout-frame-source.d.ts +196 -0
- package/src/lib/layout-language/ai-layout-frame-source.js +726 -0
- package/src/lib/layout-language/ai-layout-frame-source.js.map +1 -0
- package/src/lib/layout-language/ai-layout-frame.d.ts +22 -0
- package/src/lib/layout-language/ai-layout-frame.js +121 -29
- package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
- package/src/lib/layout-language/ai-layout-language.d.ts +103 -37
- package/src/lib/layout-language/ai-layout-language.js +85 -120
- package/src/lib/layout-language/ai-layout-language.js.map +1 -1
- package/src/lib/model/ai-credit-estimate.d.ts +11 -7
- package/src/lib/model/ai-credit-estimate.js +11 -7
- package/src/lib/model/ai-credit-estimate.js.map +1 -1
- package/src/lib/model/ai-site-import.d.ts +307 -13
- package/src/lib/model/ai-site-import.js +227 -19
- package/src/lib/model/ai-site-import.js.map +1 -1
- package/src/lib/model/ai-site-look.d.ts +65 -1
- package/src/lib/model/ai-site-look.js +141 -23
- package/src/lib/model/ai-site-look.js.map +1 -1
- package/src/lib/model/ai-site-photos.d.ts +2 -0
- package/src/lib/model/ai-site-photos.js.map +1 -1
- package/src/lib/model/ai-site-start-steps.d.ts +4 -3
- package/src/lib/model/ai-site-start-steps.js +11 -3
- package/src/lib/model/ai-site-start-steps.js.map +1 -1
- package/src/lib/model/ai-site-start.d.ts +23 -2
- package/src/lib/model/ai-site-start.js +25 -3
- package/src/lib/model/ai-site-start.js.map +1 -1
- package/src/lib/providers/routing.d.ts +11 -0
- package/src/lib/providers/routing.js +23 -0
- package/src/lib/providers/routing.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.d.ts +4 -2
- package/src/lib/runtime/ai-doctrine-validators.js +7 -2
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-icon-library.d.ts +4 -0
- package/src/lib/runtime/ai-icon-library.js +4 -0
- package/src/lib/runtime/ai-icon-library.js.map +1 -1
- package/src/lib/runtime/ai-node-tree.js +5 -1
- package/src/lib/runtime/ai-node-tree.js.map +1 -1
- package/src/lib/runtime/ai-palette.d.ts +2 -0
- package/src/lib/runtime/ai-palette.generated.js +19 -3
- package/src/lib/runtime/ai-palette.generated.js.map +1 -1
- package/src/lib/runtime/ai-palette.js +2 -1
- package/src/lib/runtime/ai-palette.js.map +1 -1
- package/src/lib/site-import/fixtures/site-layout-recordings.d.ts +50 -0
- package/src/lib/site-import/fixtures/site-layout-recordings.js +86 -0
- package/src/lib/site-import/fixtures/site-layout-recordings.js.map +1 -0
- package/src/lib/site-import/site-import-crawl.d.ts +18 -1
- package/src/lib/site-import/site-import-crawl.js +70 -10
- package/src/lib/site-import/site-import-crawl.js.map +1 -1
- package/src/lib/site-import/site-import-css.d.ts +110 -0
- package/src/lib/site-import/site-import-css.js +826 -0
- package/src/lib/site-import/site-import-css.js.map +1 -0
- package/src/lib/site-import/site-import-html.d.ts +116 -1
- package/src/lib/site-import/site-import-html.js +538 -46
- package/src/lib/site-import/site-import-html.js.map +1 -1
- package/src/lib/site-import/site-import-layout.d.ts +79 -0
- package/src/lib/site-import/site-import-layout.js +1608 -0
- package/src/lib/site-import/site-import-layout.js.map +1 -0
- package/src/lib/site-import/site-import-nav.d.ts +40 -0
- package/src/lib/site-import/site-import-nav.js +437 -0
- package/src/lib/site-import/site-import-nav.js.map +1 -0
- package/src/lib/site-import/site-import-page.d.ts +8 -1
- package/src/lib/site-import/site-import-page.js +24 -2
- package/src/lib/site-import/site-import-page.js.map +1 -1
- package/src/lib/assets/site-styles/beauty.webp +0 -0
- package/src/lib/assets/site-styles/blog.webp +0 -0
- package/src/lib/assets/site-styles/business.webp +0 -0
- package/src/lib/assets/site-styles/coming-soon.webp +0 -0
- package/src/lib/assets/site-styles/education.webp +0 -0
- package/src/lib/assets/site-styles/events.webp +0 -0
- package/src/lib/assets/site-styles/fitness.webp +0 -0
- package/src/lib/assets/site-styles/landing.webp +0 -0
- package/src/lib/assets/site-styles/music.webp +0 -0
- package/src/lib/assets/site-styles/nonprofit.webp +0 -0
- package/src/lib/assets/site-styles/personal.webp +0 -0
- package/src/lib/assets/site-styles/photography.webp +0 -0
- package/src/lib/assets/site-styles/portfolio.webp +0 -0
- package/src/lib/assets/site-styles/professional.webp +0 -0
- package/src/lib/assets/site-styles/realestate.webp +0 -0
- package/src/lib/assets/site-styles/restaurant.webp +0 -0
- package/src/lib/assets/site-styles/store.webp +0 -0
- package/src/lib/assets/site-styles/studio.webp +0 -0
- package/src/lib/assets/site-styles/trades.webp +0 -0
- package/src/lib/assets/site-styles/wellness.webp +0 -0
- package/src/lib/assets/site-styles/yoga.webp +0 -0
- package/src/lib/site-import/site-import-review.d.ts +0 -40
- package/src/lib/site-import/site-import-review.js +0 -149
- package/src/lib/site-import/site-import-review.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/jobs/ai-job-import-step.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 * THE `import` JOB: BRING MY SITE, IN REVIEWED WAVES (AGL-3976).\n *\n * One step, many passes, each one unit of work (`aiSiteImportNextWork`):\n *\n * 1. READ the proved site (no model): the crawler reads it as AglynBot,\n * main pages first, up to the plan's page count; the inventory is cut\n * into waves (`model/ai-site-import.ts`), every page gets a ledger row,\n * and Trust & Safety gets its row. The job then WAITS (`needs_review`,\n * reason `wave`): nothing is brought in until the person starts wave 1.\n * 2. START A WAVE (no model), on the person's say-so: the proof is still\n * current, the day's limit has room, the plan still has room; the\n * wave's pages are read again, fresh, and a page that became a sign-in\n * page, went away or is now off limits to AglynBot is left out.\n * 3. THE LOOK, in the first wave (no model, AGL-4084): the theme drawn\n * from the owner's own home page, its logo into the library, the site's\n * listing from the home page's own words (`ai-site-import-look.ts`).\n * 4. THE HEADER AND FOOTER, in the first wave: the layout step's own pass,\n * with the source's brand as its header draws it, its own header and\n * footer words as the footer's facts, and the site's menu order.\n * 5. EACH PAGE: its photos into the media library (no model, deduped by\n * source key), then the page step's own passes, NEVER REWRITTEN\n * (AGL-4084, `ai-site-import-document.ts`): a collection's page or a\n * long page is copied as it is, every word in order, with no model; a\n * main page is arranged, the model placing the source's numbered lines\n * and code writing every word as the source has it.\n * 6. CLOSE THE WAVE: its pages go live in the site's preview (AGL-4084,\n * `ai-site-import-publish.ts`), where only its team sees them, and the\n * job waits again until the person starts the next wave, or, where the\n * person chose \"Start every remaining wave\", starts it. The last wave\n * ends the job.\n *\n * Every page is an item of the job's ledger, so a page that fails on our\n * side gives back its own spend (the machine's `refundBuildCredits`) and the\n * wave goes on. Nothing is ever public by this job: a wave lands only in a\n * site that is in preview, and a site that is not keeps its pages as drafts.\n *=========================================*/\n\nimport { resolveEffectivePlan } from '@aglyn/aglyn/app-utils/plan-entitlements'\nimport { createResourceUid } from '@aglyn/aglyn/app-utils/create-resource-uid'\nimport { pluginMediaIngest, type PluginMediaIngest } from '@aglyn/aglyn/plugin-manager/plugin-media-ingest'\nimport {\n listDomainOwnershipClaims,\n normalizeOwnershipDomain,\n} from '@aglyn/tenant-data-admin/server/domain-ownership'\nimport { getOrgForUser, memberHasOrgPermission } from '@aglyn/tenant-data-admin/server/organizations'\nimport { consumeRateLimit } from '@aglyn/tenant-data-admin/server/rate-limit-store'\nimport { isServerReleaseFlagOnForOrg } from '@aglyn/tenant-data-admin/server/release-flags'\nimport type { AiBuildPlanCreate, AiBuildPlanScreen } from '../model/ai-build-plan'\nimport type { AiJob, AiJobItemLedger, AiJobPlan, AiJobReview } from '../model/ai-jobs.types'\nimport {\n AI_SITE_IMPORT_DOMAIN_INPUT,\n AI_SITE_IMPORT_FRAME_SLOT,\n AI_SITE_IMPORT_LABEL_MAX_CHARS,\n AI_SITE_IMPORT_LEFT_OUT_COPY,\n AI_SITE_IMPORT_MAX_PAGES,\n AI_SITE_IMPORT_MIN_WORDS,\n AI_SITE_IMPORT_WAVE_PAGES,\n aiSiteImportInventory,\n aiSiteImportItemOpen,\n aiSiteImportLedger,\n aiSiteImportNextWork,\n aiSiteImportPageBuild,\n aiSiteImportPageSettled,\n aiSiteImportPagesRead,\n aiSiteImportPhotosIn,\n aiSiteImportReadStops,\n aiSiteImportReadVerdict,\n aiSiteImportReadVerdictMessage,\n aiSiteImportReadVerdictReason,\n aiSiteImportWaveClosed,\n aiSiteImportWaveMessage,\n aiSiteImportWaveStarted,\n type AiSiteImportBuild,\n type AiSiteImportHome,\n type AiSiteImportLeftOutReason,\n type AiSiteImportPage,\n type AiSiteImportPageRead,\n type AiSiteImportState,\n type AiSiteImportWave,\n} from '../model/ai-site-import'\nimport { aiModelForStep } from '../providers/routing'\nimport { SITE_IMPORT_RELEASE_FLAG } from '../site-import/site-import-flag'\nimport { crawlSiteForImport, type SiteImportCrawlSeams, type SiteImportInventory } from '../site-import/site-import-crawl'\nimport { bringInSiteImportPhotos, type SiteImportPhotosDeps } from '../site-import/site-import-images'\nimport {\n siteImportHeaderBrand,\n siteImportLabel,\n siteImportLeftOutReason,\n siteImportListedPage,\n siteImportPageRead,\n siteImportPageWords,\n siteImportSiteFacts,\n siteImportSiteName,\n} from '../site-import/site-import-page'\nimport { aiSiteKindFor } from '../model/ai-site-kinds'\nimport { AI_LAYOUT_SITE_BRAND_INPUT, AI_LAYOUT_SITE_FACTS_INPUT } from './ai-job-layout-language'\nimport { AI_LAYOUT_IMPORTED_SECTIONS_INPUT, aiSiteImportDocLines, type AiSiteImportDocument } from './ai-site-import-document'\nimport { aiRunSiteImportLook, type AiSiteImportLookDeps } from './ai-site-import-look'\nimport { aiPublishImportedWave } from './ai-site-import-publish'\nimport { fileSiteImportReview } from '../site-import/site-import-review'\nimport { aiUnitErrorRetryable, aiUnitFailure, aiUnitSpend } from './ai-build-unit-outcome'\nimport { registerAiJobAdmission, type AiJobAdmission } from './ai-job-admission'\nimport { AI_JOB_STEP_OVERHEAD_MS } from './ai-job-budget'\nimport { readAiDraftNodes, readAiScreenRoom } from './ai-job-drafts'\nimport { aiUnspentOutcome } from './ai-job-generation'\nimport { AI_LAYOUT_PAGE_PHOTOS_INPUT } from './ai-layout-owner-photos'\nimport { AI_LAYOUT_SITE_PAGES_INPUT, AI_LAYOUT_SITE_PAGES_MAX, type AiLayoutSitePage } from './ai-job-layout-site-pages'\nimport { AI_JOB_PAGE_STEP_MINIMUM_MS } from './ai-job-page-budget'\nimport { AI_LAYOUT_IMPORTED_PAGE_INPUT, AI_LAYOUT_LANGUAGE_INPUT } from './ai-job-page-language'\nimport { aiSitePageWritten } from './ai-job-site-step'\nimport { AI_STOCK_PHOTO_PAGES_INPUT } from './ai-layout-stock-photos'\nimport { AI_JOB_BRIEF_MAX_CHARS, type AiJobItemOutcome, type AiJobStepContext, type AiJobStepOutcome, type AiJobStepRunner } from './ai-job-text-step'\nimport {\n aiApplyJobItemRecord,\n aiJobStepRunMinimumMs,\n aiJobStepRunnerFor,\n registerAiJobStep,\n registerAiJobStepPasses,\n} from './ai-jobs'\n\n/** Waves (the read included) one workspace may start in a day. */\nexport const SITE_IMPORT_WAVES_PER_ORG_PER_DAY = 12\n\nconst DAY_MS = 24 * 60 * 60 * 1000\n\n/** The rate-limit key a workspace's imports share. */\nexport function siteImportRateKey(orgId: string): string {\n return `ai-import:${orgId}`\n}\n\n/** The crawl's clock when the import reads the whole site. */\nexport const AI_SITE_IMPORT_READ_MS = 150_000\n\n/** The crawl's clock when a wave reads its own pages again. */\nexport const AI_SITE_IMPORT_WAVE_READ_MS = 90_000\n\n/** The clock for one page's photos: each is fetched and stored through the library's door. */\nexport const AI_SITE_IMPORT_PHOTOS_MS = 90_000\n\n/** What the step's own reads and writes around a pass take: the claims, the room, the row. */\nconst OWN_READS_MS = 10_000\n\n/** The least time each pass that asks no model needs. */\nexport const AI_SITE_IMPORT_PASS_MINIMUM_MS = {\n read: AI_SITE_IMPORT_READ_MS + OWN_READS_MS + AI_JOB_STEP_OVERHEAD_MS,\n wave: AI_SITE_IMPORT_WAVE_READ_MS + OWN_READS_MS + AI_JOB_STEP_OVERHEAD_MS,\n photos: AI_SITE_IMPORT_PHOTOS_MS + OWN_READS_MS + AI_JOB_STEP_OVERHEAD_MS,\n} as const\n\n/**\n * The passes one import may take: a read, then for every page its photos,\n * its answer and its listing, every wave's start and the header and footer,\n * with room for re-asks.\n */\nexport const AI_SITE_IMPORT_MAX_PASSES = AI_SITE_IMPORT_MAX_PAGES * 4 + 60\n\n/** Customer-safe sentences. */\nexport const AI_SITE_IMPORT_COPY = {\n noSite: 'Open the site to bring your website into.',\n badDomain: 'This website’s address cannot be brought in.',\n ownership: (domain: string) =>\n `Verify that you own ${domain} before bringing it in. A proof is good for 30 days; verify again, then start this wave again.`,\n limit: `This workspace has started as many site waves as it can today (${SITE_IMPORT_WAVES_PER_ORG_PER_DAY}). Start this wave again tomorrow.`,\n robots: (domain: string) =>\n `The robots.txt file of ${domain} could not be read just now, so nothing was read. Try again in a few minutes.`,\n nothing: (domain: string) => `No page of ${domain} could be read. Check that the site is up, then try again.`,\n blocked: (domain: string) =>\n `The bot protection or firewall of ${domain} turned AglynBot away, so no page could be read. Allow AglynBot in your site’s bot or firewall settings, then read the site again.`,\n unavailable: 'Bringing a site in is not available on this workspace right now.',\n frameUnavailable: 'The header and footer could not be built here; your pages use the site’s own layout.',\n pageUnavailable: 'Pages cannot be built here right now.',\n pageNotWritten: 'This page could not be written from its old page. Its spend is given back.',\n plan: 'Bringing an existing site in is included on every paid plan.',\n /** Names \"Bring a site in\" (`ai.import`, AGL-4047), never a role. */\n role: 'Your role does not include \"Bring a site in\" — ask an organization admin',\n} as const\n\n/*------------------------------------------\n * Seams\n *-----------------------------------------*/\n\nexport interface AiSiteImportOwnership {\n current: boolean\n method: string | null\n provenAt: number | null\n detail: string | null\n}\n\nexport interface AiSiteImportStepDeps {\n crawl?: typeof crawlSiteForImport\n crawlSeams?: SiteImportCrawlSeams\n runnerFor?: typeof aiJobStepRunnerFor\n ownership?: (orgId: string, domain: string) => Promise<AiSiteImportOwnership | null>\n rateLimit?: (key: string, options: { limit: number; windowMs: number }) => Promise<{ allowed: boolean }>\n releaseFlagOn?: (orgId: string) => Promise<boolean>\n ingest?: () => PluginMediaIngest | null\n fetchImage?: SiteImportPhotosDeps['fetch']\n readRoom?: typeof readAiScreenRoom\n readSiteName?: (firestore: FirebaseFirestore.Firestore, hostId: string) => Promise<string>\n fileReview?: typeof fileSiteImportReview\n pageWritten?: typeof aiSitePageWritten\n mintId?: () => string\n clock?: () => number\n /** The first wave's look pass (AGL-4084), and what it reads and writes through. */\n look?: typeof aiRunSiteImportLook\n lookDeps?: AiSiteImportLookDeps\n /** A closed wave's pages into the site's preview (AGL-4084). */\n publishWave?: typeof aiPublishImportedWave\n /** The words a page that came in shows, read off its draft (AGL-4084). */\n draftWords?: (firestore: FirebaseFirestore.Firestore, hostId: string, draftId: string) => Promise<number | null>\n}\n\nasync function readOwnership(orgId: string, domain: string): Promise<AiSiteImportOwnership | null> {\n const claims = await listDomainOwnershipClaims(orgId)\n const claim = claims.find((entry) => entry.domain === domain)\n if (!claim) return null\n return { current: claim.current, method: claim.provenMethod, provenAt: claim.provenAt, detail: claim.provenDetail }\n}\n\nasync function readSiteName(firestore: FirebaseFirestore.Firestore, hostId: string): Promise<string> {\n const host = await firestore.collection('hosts').doc(hostId).get()\n const name = host.get('displayName')\n return typeof name === 'string' ? name.trim() : ''\n}\n\n/** The proved domain an import job is for, or `null`. */\nexport function aiSiteImportDomainOf(job: Pick<AiJob, 'inputs'>): string | null {\n return normalizeOwnershipDomain(String(job.inputs?.[AI_SITE_IMPORT_DOMAIN_INPUT] ?? '')).domain\n}\n\n/*------------------------------------------\n * The jobs a unit is handed to\n *-----------------------------------------*/\n\nconst pathOf = (slug: string) => (slug === '/' ? '/' : `/${slug}`)\n\n/** A plan as a delegated unit reads it: confirmed, with what it builds and nothing else. */\nfunction unitPlan(job: AiJob, input: { create?: AiBuildPlanCreate[]; screens?: AiBuildPlanScreen[] }): AiJobPlan {\n return {\n reuse: [],\n create: input.create ?? [],\n screens: input.screens ?? [],\n labels: {},\n status: 'confirmed',\n proposedAt: job.createdAt,\n confirmedAt: job.createdAt,\n confirmedBy: job.createdBy,\n }\n}\n\nconst delivered = (items: readonly AiJobItemLedger[], slot: string) =>\n items.some((row) => row.slot === slot && (row.status === 'succeeded' || row.status === 'degraded'))\n\n/**\n * The pages the header and a page may link: the ones of this wave and those\n * before it that are in or still coming, home first, at most the header's\n * seven. A page of a later wave is not linked: it may never be brought in.\n */\nexport function aiSiteImportLinkedPages(\n state: AiSiteImportState,\n items: readonly AiJobItemLedger[],\n wave: number,\n): AiLayoutSitePage[] {\n const rows = new Map(items.map((row) => [row.slot, row]))\n const pages = state.pages\n .filter((page) => page.wave <= wave && !page.refused)\n .filter((page) => {\n const row = rows.get(page.slot)\n return !row || row.status === 'pending' || row.status === 'running' || row.status === 'succeeded' || row.status === 'degraded'\n })\n .map((page) => ({ id: page.draftId, label: page.title, slug: pathOf(page.slug) }))\n return [...pages.filter((page) => page.slug === '/'), ...pages.filter((page) => page.slug !== '/')].slice(0, AI_LAYOUT_SITE_PAGES_MAX)\n}\n\n/**\n * How a page is built (AGL-4084): a collection's page, or a long page, is\n * copied as it is; a main page is arranged. The home page is always\n * arranged, however long: it is the site's front door, never a document.\n */\nexport function aiSiteImportBuildOf(page: Pick<AiSiteImportPage, 'group' | 'words' | 'slug'>): AiSiteImportBuild {\n return page.group === 'main' && page.slug === '/' ? 'arranged' : aiSiteImportPageBuild(page)\n}\n\n/**\n * The name the header and footer carry (AGL-4084): the site's own name where\n * it is the name the person gave Create site but for its case or its\n * punctuation, else the person's.\n */\nexport function aiSiteImportBrandName(given: string, own: string): string {\n const key = (text: string) => text.toLowerCase().replace(/[^\\p{L}\\p{N}]+/gu, '')\n return own && key(own) && key(own) === key(given) ? own : given\n}\n\n/** The design inputs every unit of an import is drawn with: the kind of site its own words say, and its look (AGL-4084). */\nfunction aiSiteImportDesignInputs(state: AiSiteImportState): Record<string, unknown> {\n const home = state.home\n const kind = home ? aiSiteKindFor(`${home.siteName} ${home.description}`) : null\n const look = state.look\n return {\n ...(kind ? { siteKind: kind.id } : {}),\n ...(look && look.seed !== null\n ? {\n siteStyle: {\n seed: look.seed,\n ...(look.style?.headerAlign ? { headerAlign: look.style.headerAlign } : {}),\n ...(look.style?.rhythm ? { rhythm: look.style.rhythm } : {}),\n ...(look.style?.motion ? { motion: look.style.motion } : {}),\n },\n }\n : {}),\n }\n}\n\n/** The header and footer's job: a layout of the site's brand, linking the wave's pages, in the layout language. */\nexport function aiSiteImportFrameJob(job: AiJob, state: AiSiteImportState, wave: AiSiteImportWave, items: readonly AiJobItemLedger[]): AiJob {\n const draftId = state.frame?.draftId ?? `${job.$id}-${AI_SITE_IMPORT_FRAME_SLOT}`\n const creation: AiBuildPlanCreate = {\n kind: 'layout',\n name: 'Header and footer',\n why: `The header and footer every page brought in from ${state.domain} renders inside.`,\n duplicateOf: null,\n fields: ['header', 'nav', 'main', 'footer'],\n id: draftId,\n }\n const home = state.home ?? null\n const logo = state.look?.logo ?? null\n // The brand as the source's header draws it; with no logo in the library, its name.\n const brand = home ? { ...(logo && home.brand.kind !== 'name-only' ? { logo: { src: logo.src } } : {}), name: !logo || home.brand.kind !== 'logo-only' } : null\n return {\n ...job,\n $id: draftId,\n kind: 'layout',\n steps: [],\n outputs: [],\n items: null,\n siteImport: null,\n plan: unitPlan(job, { create: [creation] }),\n inputs: {\n originJobId: job.$id,\n businessName: aiSiteImportBrandName(state.siteName, home?.siteName ?? ''),\n [AI_LAYOUT_LANGUAGE_INPUT]: true,\n [AI_LAYOUT_SITE_PAGES_INPUT]: aiSiteImportLinkedPages(state, items, wave.index),\n ...aiSiteImportDesignInputs(state),\n ...(brand ? { [AI_LAYOUT_SITE_BRAND_INPUT]: brand } : {}),\n // The source's own header and footer words, fenced where the prompt shows them (AGL-4084).\n ...(home ? { [AI_LAYOUT_SITE_FACTS_INPUT]: { url: home.url, description: home.description, lines: home.facts.lines } } : {}),\n },\n // Never words a footer could print as the site's own (AGL-4084): the prompt shows the source's.\n brief: `The header and footer of the site “${state.siteName}”.`.slice(0, AI_JOB_BRIEF_MAX_CHARS),\n }\n}\n\n/** The page brought in, as its page job carries it: its lines, its photos, and the pages its links may go to (AGL-4084). */\nexport function aiSiteImportDocumentFor(state: AiSiteImportState, page: AiSiteImportPage): AiSiteImportDocument | null {\n const blocks = page.read?.blocks\n if (!blocks?.length) return null\n return {\n build: page.build ?? aiSiteImportBuildOf(page),\n title: page.title,\n url: page.url,\n blocks,\n photos: page.photos?.assets ?? [],\n // Home's own links are words: a link home says home, which the source's words may not.\n links: state.pages.filter((entry) => entry.slug !== '/' && !entry.refused).map((entry) => ({ path: entry.path.replace(/\\/+$/, '') || '/', id: entry.draftId })),\n origins: [`https://${state.domain}`, `https://www.${state.domain.replace(/^www\\./, '')}`],\n }\n}\n\n/** One page's job: a page job's plan of one screen, its sections the old page's own, its words carried as they are. */\nexport function aiSiteImportPageJob(\n job: AiJob,\n state: AiSiteImportState,\n page: AiSiteImportPage,\n items: readonly AiJobItemLedger[],\n): AiJob {\n const doc = aiSiteImportDocumentFor(state, page)\n // The page's sections are the source's own (AGL-4084): its opening, then one at each second-level heading.\n const names = doc ? aiSiteImportDocLines(doc.blocks, doc.title).sections.map((section) => section.name) : page.read?.sections ?? []\n const sections = (names.length ? names : ['Introduction']).map((name) => ({\n name: name.slice(0, AI_SITE_IMPORT_LABEL_MAX_CHARS),\n uses: [],\n items: 0,\n }))\n const screen: AiBuildPlanScreen = {\n title: page.title,\n slug: pathOf(page.slug),\n // Inside the header and footer this import built, once it is in.\n layout: state.frame && delivered(items, AI_SITE_IMPORT_FRAME_SLOT) ? state.frame.draftId : null,\n template: null,\n duplicateOf: null,\n nav: false,\n seoTitle: page.title,\n seoDescription: '',\n sections,\n record: null,\n id: page.draftId,\n }\n // The other pages already in, whose stock photos this page does not repeat.\n const others = state.pages.filter((entry) => entry.slot !== page.slot && delivered(items, entry.slot)).map((entry) => entry.draftId)\n return {\n ...job,\n $id: page.draftId,\n kind: 'page',\n steps: [],\n outputs: [],\n items: null,\n siteImport: null,\n plan: unitPlan(job, { screens: [screen] }),\n inputs: {\n originJobId: job.$id,\n businessName: aiSiteImportBrandName(state.siteName, state.home?.siteName ?? ''),\n [AI_LAYOUT_LANGUAGE_INPUT]: true,\n [AI_LAYOUT_SITE_PAGES_INPUT]: aiSiteImportLinkedPages(state, items, page.wave),\n ...aiSiteImportDesignInputs(state),\n // Every word as the source has it (AGL-4084); a read from before it was kept is the text the old page step had.\n ...(doc\n ? { [AI_LAYOUT_IMPORTED_SECTIONS_INPUT]: doc }\n : { [AI_LAYOUT_IMPORTED_PAGE_INPUT]: { url: page.url, text: page.read?.text ?? '' } }),\n [AI_LAYOUT_PAGE_PHOTOS_INPUT]: page.photos?.assets ?? [],\n ...(others.length ? { [AI_STOCK_PHOTO_PAGES_INPUT]: others } : {}),\n },\n brief: `Bring in the page “${page.title}” of ${state.domain} as a page of “${state.siteName}”.`.slice(0, AI_JOB_BRIEF_MAX_CHARS),\n }\n}\n\n/** What the home page says of the site as a whole (AGL-4084), kept for the look, the header and footer and the listing. */\nexport function aiSiteImportHomeOf(crawled: Pick<SiteImportInventory, 'pages'>): AiSiteImportHome | null {\n const page = crawled.pages.find((entry) => entry.foundBy === 'home') ?? crawled.pages.find((entry) => (entry.path.replace(/\\/+$/, '') || '/') === '/')\n if (!page) return null\n const brand = siteImportHeaderBrand(page)\n const facts = siteImportSiteFacts(page)\n const lines: string[] = []\n let chars = 0\n for (const block of [...facts.header, ...facts.footer]) {\n if (block.kind === 'image' || (block.kind === 'link' && block.inline)) continue\n const text = block.text.replace(/\\s+/g, ' ').trim()\n const line = block.kind === 'link' && /^(?:mailto|tel):/i.test(block.href) ? text : block.kind === 'link' && facts.social.includes(block.href) ? `${text}: ${block.href}` : text\n if (!line || lines.includes(line) || chars + line.length > 3_000 || lines.length >= 60) continue\n lines.push(line)\n chars += line.length\n }\n // And what the site states of itself in its structured data, as written: its address, phone and email.\n const organization = facts.organization\n for (const line of [organization?.address, organization?.telephone, organization?.email]) {\n const text = (line ?? '').replace(/\\s+/g, ' ').trim()\n if (text && !lines.some((entry) => entry.includes(text))) lines.push(text)\n }\n return {\n url: page.url,\n title: siteImportLabel(page.title ?? '', 160),\n description: siteImportLabel(page.description ?? '', 320),\n ogImage: page.ogImage ?? null,\n siteName: siteImportSiteName(page),\n brand: {\n kind: brand.kind,\n text: brand.text,\n logo: brand.logo ? { url: brand.logo.url, alt: brand.logo.alt, type: brand.logo.type } : null,\n },\n facts: {\n lines,\n emails: facts.emails,\n phones: facts.phones,\n social: facts.social,\n address: facts.organization?.address ?? '',\n },\n }\n}\n\n/** The least time the import's next pass needs: a read's, a photo pass's, or the time of the step its unit is handed to. */\nexport function aiSiteImportRunMinimumMs(job: AiJob, runnerFor: typeof aiJobStepRunnerFor = aiJobStepRunnerFor): number {\n const state = job.siteImport ?? null\n const items = job.items ?? []\n const work = aiSiteImportNextWork(state, items)\n switch (work.kind) {\n case 'inventory':\n return AI_SITE_IMPORT_PASS_MINIMUM_MS.read\n case 'start-wave':\n case 'read':\n return AI_SITE_IMPORT_PASS_MINIMUM_MS.wave\n case 'images':\n return AI_SITE_IMPORT_PASS_MINIMUM_MS.photos\n case 'frame':\n return runnerFor('layout') && state ? aiJobStepRunMinimumMs(aiSiteImportFrameJob(job, state, work.wave, items)) : 0\n case 'page':\n return runnerFor('page') && state ? aiJobStepRunMinimumMs(aiSiteImportPageJob(job, state, work.page, items)) : 0\n default:\n return 0\n }\n}\n\n/*------------------------------------------\n * The step\n *-----------------------------------------*/\n\nconst waveReview = (message: string): AiJobReview => ({ reason: 'wave', message, findings: [] })\n\n/** The rows a wave's read left out, settled as not brought in, with the reason. */\nfunction withLeftOutRows(\n items: readonly AiJobItemLedger[],\n reads: ReadonlyMap<string, AiSiteImportPageRead | AiSiteImportLeftOutReason>,\n): AiJobItemLedger[] {\n return items.map((row) => {\n const read = reads.get(row.slot)\n return typeof read === 'string' && (row.status === 'pending' || row.status === 'running')\n ? { ...row, status: 'skipped', note: AI_SITE_IMPORT_LEFT_OUT_COPY[read] }\n : row\n })\n}\n\n/**\n * The state with how each page is built (AGL-4084): from its main region's\n * words as the inventory listed them, and again from a wave's fresh read,\n * which is what the page is built from.\n */\nexport function aiSiteImportWithBuilds(state: AiSiteImportState, mainWords?: ReadonlyMap<string, number>): AiSiteImportState {\n return {\n ...state,\n pages: state.pages.map((page) => {\n const words = page.read?.words ?? mainWords?.get(page.url) ?? page.words\n const build = aiSiteImportBuildOf({ ...page, words })\n return page.build === build ? page : { ...page, build }\n }),\n }\n}\n\n/** The words a stored page shows (AGL-4084): its text, its list lines and its buttons. */\nexport function aiSiteImportShownWords(nodes: Readonly<Record<string, unknown>>): number {\n let words = 0\n for (const node of Object.values(nodes)) {\n const props = (node as { props?: Record<string, unknown> } | null)?.props ?? {}\n for (const key of ['children', 'primary', 'secondary']) {\n const value = props[key]\n if (typeof value === 'string') words += (value.match(/[\\p{L}\\p{N}]+/gu) ?? []).length\n }\n }\n return words\n}\n\nasync function readDraftWords(firestore: FirebaseFirestore.Firestore, hostId: string, draftId: string): Promise<number | null> {\n const stored = await readAiDraftNodes(firestore, { kind: 'screen', hostId, id: draftId })\n return stored ? aiSiteImportShownWords(stored.nodes as unknown as Record<string, unknown>) : null\n}\n\n/**\n * The review a wave that went live in the site's preview parks on (AGL-4084):\n * where its pages are now, who sees them, and the next wave's start.\n */\nexport function aiSiteImportPreviewMessage(state: AiSiteImportState, wave: Pick<AiSiteImportWave, 'label'>, published: number): string {\n const pages = `${published.toLocaleString('en-US')} ${published === 1 ? 'page is' : 'pages are'}`\n const lead = `${wave.label} is in your site’s preview: ${pages} on your site, where only you and your team can see ${published === 1 ? 'it' : 'them'}.`\n const next = state.waves.find((entry) => entry.status === 'waiting')\n return next ? `${lead} Start ${next.label} when you are ready.` : lead\n}\n\n/** Whether every row of the wave is settled, its header and footer included. */\nfunction waveSettled(state: AiSiteImportState, wave: AiSiteImportWave, items: readonly AiJobItemLedger[]): boolean {\n if (wave.frame && state.frame && aiSiteImportItemOpen(items, AI_SITE_IMPORT_FRAME_SLOT)) return false\n return wave.slots.every((slot) => !aiSiteImportItemOpen(items, slot))\n}\n\nexport function createAiJobImportStep(deps: AiSiteImportStepDeps = {}): AiJobStepRunner {\n const crawl = deps.crawl ?? crawlSiteForImport\n const runnerFor = deps.runnerFor ?? aiJobStepRunnerFor\n const ownershipOf = deps.ownership ?? readOwnership\n const rateLimit = deps.rateLimit ?? consumeRateLimit\n const flagOn = deps.releaseFlagOn ?? ((orgId: string) => isServerReleaseFlagOnForOrg(SITE_IMPORT_RELEASE_FLAG, orgId))\n const ingestOf = deps.ingest ?? pluginMediaIngest\n const readRoom = deps.readRoom ?? readAiScreenRoom\n const siteNameOf = deps.readSiteName ?? readSiteName\n const fileReview = deps.fileReview ?? fileSiteImportReview\n const pageWritten = deps.pageWritten ?? aiSitePageWritten\n const mintId = deps.mintId ?? createResourceUid\n const clock = deps.clock ?? Date.now\n const runLook = deps.look ?? aiRunSiteImportLook\n const publishWave = deps.publishWave ?? aiPublishImportedWave\n const draftWordsOf = deps.draftWords ?? readDraftWords\n\n return async (context: AiJobStepContext): Promise<AiJobStepOutcome> => {\n const { job, firestore, now, signal } = context\n const model = aiModelForStep('job.page')\n const unspent = (rest: Partial<AiJobStepOutcome> = {}): AiJobStepOutcome => ({ ...aiUnspentOutcome(model), ...rest })\n const hostId = job.hostId\n if (!hostId) return unspent({ failure: AI_SITE_IMPORT_COPY.noSite })\n const domain = aiSiteImportDomainOf(job)\n if (!domain) return unspent({ failure: AI_SITE_IMPORT_COPY.badDomain })\n const state = job.siteImport ?? null\n const items = job.items ?? []\n const work = aiSiteImportNextWork(state, items)\n const nowIso = now.toISOString()\n const review = (event: 'read' | 'wave-started' | 'wave-finished', next: AiSiteImportState, ledger: readonly AiJobItemLedger[], wave?: number) =>\n fileReview(firestore, { orgId: job.orgId, hostId, jobId: job.$id, state: next, items: ledger, event, nowMs: now.getTime(), ...(wave !== undefined ? { wave } : {}) })\n\n /** Closes the wave when this pass settled its last row: the review, or the job's end after the last wave. */\n const closing = async (\n next: AiSiteImportState,\n ledger: readonly AiJobItemLedger[],\n wave: AiSiteImportWave,\n outcome: AiJobStepOutcome,\n ): Promise<AiJobStepOutcome> => {\n if (!waveSettled(next, wave, ledger)) return { ...outcome, siteImport: next, continue: true }\n const closed = aiSiteImportWaveClosed(next, wave.index, nowIso)\n // The wave's pages go live in the site's preview, where only its team sees them (AGL-4084).\n let sitePublish = null as Awaited<ReturnType<typeof publishWave>>\n try {\n sitePublish = await publishWave(firestore, {\n job,\n state: closed,\n wave,\n items: ledger,\n outputs: [...(job.outputs ?? []), ...(outcome.outputs ?? [])],\n now,\n })\n } catch (error) {\n // A publish that failed leaves the pages drafts; the wave is still in.\n console.error('ai site import: a wave could not be published into the preview', { orgId: job.orgId, jobId: job.$id, wave: wave.index, error })\n }\n const published = sitePublish ? { sitePublish } : {}\n await review('wave-finished', closed, ledger, wave.index)\n const waiting = closed.waves.find((entry) => entry.index === wave.index)?.status === 'review'\n if (waiting) {\n const message = sitePublish?.published.length ? aiSiteImportPreviewMessage(closed, wave, sitePublish.published.length) : aiSiteImportWaveMessage(closed, ledger)\n return { ...outcome, ...published, siteImport: closed, review: waveReview(message) }\n }\n // \"Start every remaining wave\" (AGL-4083): the next wave starts with no review between them.\n const more = closed.autoContinue === true && closed.waves.some((entry) => entry.status === 'waiting')\n return { ...outcome, ...published, siteImport: closed, ...(more ? { continue: true } : {}) }\n }\n\n /** The proof, the flag and the day's limit, asked before anything is read. */\n const gate = async (counted = true): Promise<{ ownership: AiSiteImportOwnership } | AiJobStepOutcome> => {\n if (!(await flagOn(job.orgId))) return unspent({ review: waveReview(AI_SITE_IMPORT_COPY.unavailable) })\n const ownership = await ownershipOf(job.orgId, domain)\n if (!ownership?.current) {\n return unspent({ review: { reason: 'ownership', message: AI_SITE_IMPORT_COPY.ownership(domain), findings: [] } })\n }\n if (counted) {\n const window = await rateLimit(siteImportRateKey(job.orgId), { limit: SITE_IMPORT_WAVES_PER_ORG_PER_DAY, windowMs: DAY_MS })\n if (!window.allowed) return unspent({ review: { reason: 'limit', message: AI_SITE_IMPORT_COPY.limit, findings: [] } })\n }\n return { ownership }\n }\n\n // ── 1. Read the site ──\n if (work.kind === 'inventory') {\n const passed = await gate()\n if (!('ownership' in passed)) return passed\n const room = await readRoom(firestore, { hostId, org: (context.org ?? null) as never })\n const left = room.limit === null ? AI_SITE_IMPORT_MAX_PAGES : Math.max(0, room.limit - room.used)\n const crawled = await crawl(\n {\n domain,\n // A wave's worth past the room, so what the plan leaves out is said.\n maxPages: Math.min(AI_SITE_IMPORT_MAX_PAGES, left + AI_SITE_IMPORT_WAVE_PAGES),\n timeBudgetMs: AI_SITE_IMPORT_READ_MS,\n shallowFirst: true,\n ...(signal ? { signal } : {}),\n },\n deps.crawlSeams,\n )\n if (crawled.refused) return unspent({ failure: AI_SITE_IMPORT_COPY.badDomain })\n if (crawled.stoppedBy === 'robots-unreachable') return unspent({ review: waveReview(AI_SITE_IMPORT_COPY.robots(domain)) })\n const skipped = crawled.skipped.map((entry) => ({ url: entry.url, reason: siteImportLeftOutReason(entry.reason, entry.status) }))\n // Home first (AGL-4083): a site read without its home page plans nothing, quotes nothing and spends nothing.\n const verdict = aiSiteImportReadVerdict(crawled)\n const inventory = aiSiteImportInventory({\n domain,\n siteName: await siteNameOf(firestore, hostId),\n ownership: { method: passed.ownership.method, provenAt: passed.ownership.provenAt, detail: passed.ownership.detail },\n readAt: nowIso,\n pages: crawled.pages.map(siteImportListedPage),\n menu: siteImportMenu(crawled),\n skipped,\n skippedOverflow: crawled.skippedOverflow,\n stoppedBy: crawled.stoppedBy,\n pageLimit: room.limit,\n existingPages: room.used,\n verdict,\n mintId,\n })\n if (aiSiteImportReadStops(inventory.verdict)) {\n // Check again is the read again: the job waits, with why and what to do, and no ledger.\n return unspent({\n items: [],\n siteImport: inventory,\n review: {\n reason: aiSiteImportReadVerdictReason(inventory.verdict) ?? 'unreadable',\n message: aiSiteImportReadVerdictMessage(inventory.verdict, domain) ?? AI_SITE_IMPORT_COPY.nothing(domain),\n findings: [],\n },\n })\n }\n // How each page is built, from its main region's own words (AGL-4084), and what the home page says of the site.\n const mainWords = new Map(\n crawled.pages.map((page) => [page.url, siteImportPageWords({ title: '', blocks: page.blocks.filter((block) => block.region === 'main') })]),\n )\n const planned = { ...aiSiteImportWithBuilds(inventory, mainWords), home: aiSiteImportHomeOf(crawled) }\n const ledger = aiSiteImportLedger(planned)\n const reviewId = await review('read', planned, ledger)\n const next = { ...planned, reviewId }\n return unspent({ items: ledger, siteImport: next, review: waveReview(aiSiteImportWaveMessage(next, ledger)) })\n }\n\n if (!state) return unspent({ failure: AI_SITE_IMPORT_COPY.badDomain })\n if (work.kind === 'done') return unspent()\n\n // ── 2. Start a wave ──\n if (work.kind === 'start-wave') {\n // A wave \"Start every remaining wave\" started after the one the person did is that same start.\n const counted = !(state.autoContinue && typeof state.autoContinueFrom === 'number' && work.wave.index > state.autoContinueFrom)\n const passed = await gate(counted)\n if (!('ownership' in passed)) return passed\n const wave = work.wave\n const pages = wave.slots\n .map((slot) => state.pages.find((page) => page.slot === slot))\n .filter((page): page is AiSiteImportPage => !!page)\n const reads = new Map<string, AiSiteImportPageRead | AiSiteImportLeftOutReason>()\n // Never past the plan: the room is read again, since pages may have been added since the site was read.\n const room = await readRoom(firestore, { hostId, org: (context.org ?? null) as never })\n let left = room.limit === null ? Number.POSITIVE_INFINITY : Math.max(0, room.limit - room.used)\n const toRead: AiSiteImportPage[] = []\n for (const page of pages) {\n if (left > 0) {\n toRead.push(page)\n left -= 1\n } else {\n reads.set(page.slot, 'plan-limit')\n }\n }\n if (toRead.length) {\n const crawled = await crawl(\n {\n domain,\n maxPages: toRead.length,\n only: toRead.map((page) => page.url),\n timeBudgetMs: AI_SITE_IMPORT_WAVE_READ_MS,\n ...(signal ? { signal } : {}),\n },\n deps.crawlSeams,\n )\n if (crawled.stoppedBy === 'robots-unreachable') return unspent({ review: waveReview(AI_SITE_IMPORT_COPY.robots(domain)) })\n // A read the clock cut short leaves its other pages for the next pass, never \"unreadable\".\n for (const [slot, read] of siteImportWaveReads(toRead, crawled, nowIso, { cutShort: crawled.stoppedBy === 'time' })) {\n reads.set(slot, read)\n }\n }\n let ledger = withLeftOutRows(items, reads)\n // A wave none of whose pages could be read builds no header for them.\n const anyRead = [...reads.values()].some((read) => typeof read !== 'string')\n if (wave.frame && !anyRead && reads.size === pages.length) {\n ledger = ledger.map((row) =>\n row.slot === AI_SITE_IMPORT_FRAME_SLOT && (row.status === 'pending' || row.status === 'running')\n ? { ...row, status: 'skipped', note: 'Not built: no page of this wave could be read.' }\n : row,\n )\n }\n const started = aiSiteImportWithBuilds(aiSiteImportWaveStarted(state, wave.index, nowIso, reads))\n await review('wave-started', started, ledger, wave.index)\n const running = started.waves.find((entry) => entry.index === wave.index) as AiSiteImportWave\n return closing(started, ledger, running, unspent({ items: ledger }))\n }\n\n const wave = work.wave\n\n // ── 2b. The rest of a wave's read, where the clock cut it short ──\n if (work.kind === 'read') {\n const crawled = await crawl(\n {\n domain,\n maxPages: work.pages.length,\n only: work.pages.map((page) => page.url),\n timeBudgetMs: AI_SITE_IMPORT_WAVE_READ_MS,\n ...(signal ? { signal } : {}),\n },\n deps.crawlSeams,\n )\n if (crawled.stoppedBy === 'robots-unreachable') return unspent({ review: waveReview(AI_SITE_IMPORT_COPY.robots(domain)) })\n const reads = siteImportWaveReads(work.pages, crawled, nowIso, { cutShort: crawled.stoppedBy === 'time' })\n const ledger = withLeftOutRows(items, reads)\n return closing(aiSiteImportWithBuilds(aiSiteImportPagesRead(state, reads)), ledger, wave, unspent({ items: ledger }))\n }\n\n // ── 3. The look, before anything of the first wave is built (AGL-4084): no model ──\n const firstWave = state.waves[0]?.index === wave.index\n if (firstWave && !state.look && state.home && (work.kind === 'frame' || work.kind === 'images' || work.kind === 'page')) {\n const look = await runLook(\n {\n firestore,\n hostId,\n orgId: job.orgId,\n uid: job.createdBy,\n jobId: job.$id,\n domain,\n home: state.home,\n at: nowIso,\n ...(signal ? { signal } : {}),\n },\n {\n ingest: ingestOf(),\n ...(deps.crawlSeams?.fetch ? { fetch: deps.crawlSeams.fetch } : {}),\n ...(deps.crawlSeams?.headersFor ? { headersFor: deps.crawlSeams.headersFor } : {}),\n ...deps.lookDeps,\n },\n )\n return unspent({ siteImport: { ...state, look }, continue: true })\n }\n\n // ── 4. The header and footer ──\n if (work.kind === 'frame') {\n const runner = runnerFor('layout')\n if (!runner) {\n const item: AiJobItemOutcome = { slot: AI_SITE_IMPORT_FRAME_SLOT, status: 'skipped', note: AI_SITE_IMPORT_COPY.frameUnavailable }\n return closing(state, aiApplyJobItemRecord(items, item, 0, now), wave, unspent({ item }))\n }\n const derived = aiSiteImportFrameJob(job, state, wave, items)\n return runUnit(AI_SITE_IMPORT_FRAME_SLOT, runner, derived, state, null)\n }\n\n // ── 4a. A page's photos ──\n if (work.kind === 'images') {\n const photos = signal?.aborted\n ? { brought: 0, reused: 0, skipped: work.page.read?.images.length ?? 0, assets: [] }\n : await bringInSiteImportPhotos(\n {\n hostId,\n uid: job.createdBy,\n domain,\n images: work.page.read?.images ?? [],\n deadlineAt: clock() + AI_SITE_IMPORT_PHOTOS_MS,\n ...(signal ? { signal } : {}),\n },\n { ingest: ingestOf(), ...(deps.fetchImage ? { fetch: deps.fetchImage } : {}) },\n )\n return unspent({\n item: { slot: work.page.slot, status: 'running' },\n siteImport: aiSiteImportPhotosIn(state, work.page.slot, photos),\n continue: true,\n })\n }\n\n // ── 4b. The page ──\n if (work.kind === 'page') {\n const runner = runnerFor('page')\n if (!runner) {\n const item: AiJobItemOutcome = {\n slot: work.page.slot,\n status: 'failed',\n failure: { ours: true, reason: 'unavailable', message: AI_SITE_IMPORT_COPY.pageUnavailable },\n }\n return closing(state, aiApplyJobItemRecord(items, item, 0, now), wave, unspent({ item }))\n }\n return runUnit(work.page.slot, runner, aiSiteImportPageJob(job, state, work.page, items), state, work.page)\n }\n\n // ── 5. Close the wave ──\n return closing(state, items, wave, unspent())\n\n /** One delegated pass: the unit's spend is the pass's, what it came to is its row. */\n async function runUnit(\n slot: string,\n runner: AiJobStepRunner,\n derived: AiJob,\n current: AiSiteImportState,\n page: AiSiteImportPage | null,\n ): Promise<AiJobStepOutcome> {\n let outcome: AiJobStepOutcome\n try {\n outcome = await runner({ ...context, job: derived })\n } catch (error) {\n // A provider that will answer later, a budget that ended, a cancel: the machine's.\n if (aiUnitErrorRetryable(error) || (signal?.aborted ?? false)) throw error\n console.error('ai site import unit threw', { orgId: job.orgId, jobId: job.$id, slot, error })\n const item: AiJobItemOutcome = {\n slot,\n status: 'failed',\n failure: { ours: true, reason: 'provider', message: AI_SITE_IMPORT_COPY.pageNotWritten },\n }\n return closing(current, aiApplyJobItemRecord(items, item, 0, now), wave, unspent({ item }))\n }\n const spent = aiUnitSpend(outcome)\n const stopped = aiUnitFailure(slot, outcome)\n if (stopped?.status === 'running') return { ...spent, outputs: [], item: stopped, siteImport: current, continue: true }\n let item: AiJobItemOutcome\n if (stopped) {\n item = stopped\n } else if (page && derived.plan) {\n // A page counts as in only when its sections are in it (AGL-3596).\n const screen = derived.plan.screens[0]\n const written = await pageWritten(firestore, {\n hostId: hostId as string,\n unitJobId: derived.$id,\n screen,\n draftId: page.draftId,\n layoutLanguage: true,\n })\n item = written\n ? { slot, status: 'succeeded', outputs: spent.outputs.map((output) => output.id) }\n : { slot, status: 'failed', failure: { ours: true, reason: 'step-failure', message: AI_SITE_IMPORT_COPY.pageNotWritten } }\n } else {\n item = { slot, status: 'succeeded', outputs: spent.outputs.map((output) => output.id) }\n }\n // What came through, for the row that says it beside what the old page had (AGL-4084).\n let withBrought = current\n if (page && item.status === 'succeeded') {\n const words = await draftWordsOf(firestore, hostId as string, page.draftId).catch(() => null)\n if (words !== null) withBrought = { ...current, pages: current.pages.map((entry) => (entry.slot === slot ? { ...entry, brought: { words } } : entry)) }\n }\n const settledState = page ? aiSiteImportPageSettled(withBrought, slot) : withBrought\n return closing(\n settledState,\n aiApplyJobItemRecord(items, item, 0, now),\n wave,\n { ...spent, outputs: item.status === 'succeeded' ? spent.outputs : [], item },\n )\n }\n }\n}\n\n/** The home page's menu, as same-site paths in its order. */\nexport function siteImportMenu(crawled: Pick<SiteImportInventory, 'pages' | 'origins'>): string[] {\n const home = crawled.pages.find((page) => page.foundBy === 'home') ?? crawled.pages[0]\n const paths: string[] = []\n for (const link of home?.navLinks ?? []) {\n try {\n const url = new URL(link.url)\n if (!crawled.origins.includes(url.origin)) continue\n const path = url.pathname.replace(/\\/+$/, '') || '/'\n if (!paths.includes(path)) paths.push(path)\n } catch {\n // A menu entry that is not an address names no page.\n }\n }\n return paths\n}\n\n/**\n * What a wave's read came to for each page: the page read again, or why it\n * is left out now. Matched by address; a page the site sent to another of its\n * own addresses is matched in the order the wave asked for it.\n */\nexport function siteImportWaveReads(\n asked: readonly AiSiteImportPage[],\n crawled: Pick<SiteImportInventory, 'pages' | 'skipped'>,\n at: string,\n options: {\n /** The read's clock ran out: a page it did not reach is left for the next pass, not left out. */\n cutShort?: boolean\n } = {},\n): Map<string, AiSiteImportPageRead | AiSiteImportLeftOutReason> {\n const reads = new Map<string, AiSiteImportPageRead | AiSiteImportLeftOutReason>()\n const pathKey = (url: string) => {\n try {\n const parsed = new URL(url)\n return `${parsed.pathname.replace(/\\/+$/, '') || '/'}${parsed.search}`\n } catch {\n return url\n }\n }\n const pages = new Map(crawled.pages.map((page) => [pathKey(page.url), page]))\n const skipped = new Map(crawled.skipped.map((entry) => [pathKey(entry.url), entry]))\n const unmatched = [...crawled.pages]\n const take = (page: (typeof crawled.pages)[number]) => {\n const index = unmatched.indexOf(page)\n if (index !== -1) unmatched.splice(index, 1)\n }\n const pending: AiSiteImportPage[] = []\n for (const page of asked) {\n const found = pages.get(pathKey(page.url))\n if (found) {\n take(found)\n reads.set(page.slot, siteImportReadOrEmpty(found, at))\n continue\n }\n const left = skipped.get(pathKey(page.url))\n if (left) {\n reads.set(page.slot, siteImportLeftOutReason(left.reason, left.status))\n continue\n }\n pending.push(page)\n }\n for (const page of pending) {\n const found = unmatched.shift()\n if (found) reads.set(page.slot, siteImportReadOrEmpty(found, at))\n else if (!options.cutShort) reads.set(page.slot, 'unreadable')\n }\n return reads\n}\n\nfunction siteImportReadOrEmpty(page: SiteImportInventory['pages'][number], at: string): AiSiteImportPageRead | 'empty' {\n if (siteImportPageWords(page) < AI_SITE_IMPORT_MIN_WORDS && !page.images.length) return 'empty'\n return siteImportPageRead(page, at)\n}\n\n/**\n * \"Start every remaining wave\" (AGL-4083, wired by AGL-4084), as the resume\n * door writes it onto an import waiting to start its next wave: every\n * remaining wave starts after the one before it closes, with no review\n * between them, and the person's one start is the one the day's limit\n * counts. `null` when the job is not an import waiting for a wave.\n */\nexport function aiSiteImportStartAllUpdate(\n job: Pick<AiJob, 'kind' | 'status' | 'review' | 'siteImport'>,\n): { 'siteImport.autoContinue': true; 'siteImport.autoContinueFrom': number } | null {\n if (job.kind !== 'import' || job.status !== 'needs_review' || job.review?.reason !== 'wave') return null\n const next = job.siteImport?.waves.find((wave) => wave.status === 'waiting')\n if (!next) return null\n return { 'siteImport.autoContinue': true, 'siteImport.autoContinueFrom': next.index }\n}\n\n/*------------------------------------------\n * Admission, and registration\n *-----------------------------------------*/\n\nexport interface AiSiteImportAdmissionDeps {\n releaseFlagOn?: (orgId: string) => Promise<boolean>\n ownership?: (orgId: string, domain: string) => Promise<AiSiteImportOwnership | null>\n /** \"Bring a site in\" (`ai.import`, AGL-4047) for this member; specs hand in a double. */\n holdsSiteImport?: (uid: string, orgId: string) => Promise<boolean>\n}\n\n/**\n * What an import asks before it exists and before each wave (AGL-3976): the\n * release flag, a site to bring it into, a paid plan, the owner or an admin,\n * and a CURRENT proof that the workspace owns the domain. Nothing is spent on\n * a refusal, and the day's limit is the step's to count, once a wave runs.\n */\nexport function createAiSiteImportAdmission(deps: AiSiteImportAdmissionDeps = {}): AiJobAdmission {\n const flagOn = deps.releaseFlagOn ?? ((orgId: string) => isServerReleaseFlagOnForOrg(SITE_IMPORT_RELEASE_FLAG, orgId))\n const ownershipOf = deps.ownership ?? readOwnership\n const holdsSiteImport =\n deps.holdsSiteImport ??\n (async (uid: string, orgId: string) => {\n const member = (await getOrgForUser(uid, orgId))?.member ?? null\n return Boolean(member) && (await memberHasOrgPermission(orgId, member, 'ai.import'))\n })\n return async (context) => {\n if (!(await flagOn(context.orgId))) return { status: 404, error: 'Not found' }\n if (!context.hostId && !context.siteToCome) return { status: 400, error: AI_SITE_IMPORT_COPY.noSite }\n if (resolveEffectivePlan(context.org as never) === 'free') return { status: 403, error: AI_SITE_IMPORT_COPY.plan }\n // \"Bring a site in\" (`ai.import`, AGL-4047), whose default is the owner\n // and admin this asked for.\n if (!context.uid || !(await holdsSiteImport(context.uid, context.orgId))) {\n return { status: 403, error: AI_SITE_IMPORT_COPY.role }\n }\n const { domain, error } = normalizeOwnershipDomain(String(context.inputs[AI_SITE_IMPORT_DOMAIN_INPUT] ?? ''))\n if (!domain) return { status: 400, error: error ?? AI_SITE_IMPORT_COPY.badDomain }\n const ownership = await ownershipOf(context.orgId, domain)\n if (!ownership?.current) return { status: 403, error: AI_SITE_IMPORT_COPY.ownership(domain) }\n return null\n }\n}\n\n/**\n * The import kind's registrations (AGL-3976), by a call from `server.ts`,\n * never by an import: its runner with each pass's least time, its pass bound\n * and its admission.\n */\nexport function registerAiSiteImportJob(deps: AiSiteImportStepDeps = {}): void {\n const runnerFor = deps.runnerFor ?? aiJobStepRunnerFor\n registerAiJobStep('import', createAiJobImportStep(deps), {\n minimumMs: AI_JOB_PAGE_STEP_MINIMUM_MS,\n minimumMsFor: (job) => aiSiteImportRunMinimumMs(job, runnerFor),\n })\n registerAiJobStepPasses('import', AI_SITE_IMPORT_MAX_PASSES)\n registerAiJobAdmission('import', createAiSiteImportAdmission())\n}\n"],"names":["resolveEffectivePlan","createResourceUid","pluginMediaIngest","listDomainOwnershipClaims","normalizeOwnershipDomain","getOrgForUser","memberHasOrgPermission","consumeRateLimit","isServerReleaseFlagOnForOrg","AI_SITE_IMPORT_DOMAIN_INPUT","AI_SITE_IMPORT_FRAME_SLOT","AI_SITE_IMPORT_LABEL_MAX_CHARS","AI_SITE_IMPORT_LEFT_OUT_COPY","AI_SITE_IMPORT_MAX_PAGES","AI_SITE_IMPORT_MIN_WORDS","AI_SITE_IMPORT_WAVE_PAGES","aiSiteImportInventory","aiSiteImportItemOpen","aiSiteImportLedger","aiSiteImportNextWork","aiSiteImportPageBuild","aiSiteImportPageSettled","aiSiteImportPagesRead","aiSiteImportPhotosIn","aiSiteImportReadStops","aiSiteImportReadVerdict","aiSiteImportReadVerdictMessage","aiSiteImportReadVerdictReason","aiSiteImportWaveClosed","aiSiteImportWaveMessage","aiSiteImportWaveStarted","aiModelForStep","SITE_IMPORT_RELEASE_FLAG","crawlSiteForImport","bringInSiteImportPhotos","siteImportHeaderBrand","siteImportLabel","siteImportLeftOutReason","siteImportListedPage","siteImportPageRead","siteImportPageWords","siteImportSiteFacts","siteImportSiteName","aiSiteKindFor","AI_LAYOUT_SITE_BRAND_INPUT","AI_LAYOUT_SITE_FACTS_INPUT","AI_LAYOUT_IMPORTED_SECTIONS_INPUT","aiSiteImportDocLines","aiRunSiteImportLook","aiPublishImportedWave","fileSiteImportReview","aiUnitErrorRetryable","aiUnitFailure","aiUnitSpend","registerAiJobAdmission","AI_JOB_STEP_OVERHEAD_MS","readAiDraftNodes","readAiScreenRoom","aiUnspentOutcome","AI_LAYOUT_PAGE_PHOTOS_INPUT","AI_LAYOUT_SITE_PAGES_INPUT","AI_LAYOUT_SITE_PAGES_MAX","AI_JOB_PAGE_STEP_MINIMUM_MS","AI_LAYOUT_IMPORTED_PAGE_INPUT","AI_LAYOUT_LANGUAGE_INPUT","aiSitePageWritten","AI_STOCK_PHOTO_PAGES_INPUT","AI_JOB_BRIEF_MAX_CHARS","aiApplyJobItemRecord","aiJobStepRunMinimumMs","aiJobStepRunnerFor","registerAiJobStep","registerAiJobStepPasses","SITE_IMPORT_WAVES_PER_ORG_PER_DAY","DAY_MS","siteImportRateKey","orgId","AI_SITE_IMPORT_READ_MS","AI_SITE_IMPORT_WAVE_READ_MS","AI_SITE_IMPORT_PHOTOS_MS","OWN_READS_MS","AI_SITE_IMPORT_PASS_MINIMUM_MS","read","wave","photos","AI_SITE_IMPORT_MAX_PASSES","AI_SITE_IMPORT_COPY","noSite","badDomain","ownership","domain","limit","robots","nothing","blocked","unavailable","frameUnavailable","pageUnavailable","pageNotWritten","plan","role","readOwnership","claims","claim","find","entry","current","method","provenMethod","provenAt","detail","provenDetail","readSiteName","firestore","hostId","host","collection","doc","get","name","trim","aiSiteImportDomainOf","job","String","inputs","pathOf","slug","unitPlan","input","reuse","create","screens","labels","status","proposedAt","createdAt","confirmedAt","confirmedBy","createdBy","delivered","items","slot","some","row","aiSiteImportLinkedPages","state","rows","Map","map","pages","filter","page","refused","id","draftId","label","title","slice","aiSiteImportBuildOf","group","aiSiteImportBrandName","given","own","key","text","toLowerCase","replace","aiSiteImportDesignInputs","look","home","kind","siteName","description","siteKind","seed","siteStyle","style","headerAlign","rhythm","motion","aiSiteImportFrameJob","frame","$id","creation","why","duplicateOf","fields","logo","brand","src","steps","outputs","siteImport","originJobId","businessName","index","url","lines","facts","brief","aiSiteImportDocumentFor","blocks","length","build","assets","links","path","origins","aiSiteImportPageJob","names","sections","section","uses","screen","layout","template","nav","seoTitle","seoDescription","record","others","aiSiteImportHomeOf","crawled","foundBy","chars","block","header","footer","inline","line","test","href","social","includes","push","organization","address","telephone","email","ogImage","alt","type","emails","phones","aiSiteImportRunMinimumMs","runnerFor","work","waveReview","message","reason","findings","withLeftOutRows","reads","note","aiSiteImportWithBuilds","mainWords","words","aiSiteImportShownWords","nodes","node","Object","values","props","value","match","readDraftWords","stored","aiSiteImportPreviewMessage","published","toLocaleString","lead","next","waves","waveSettled","slots","every","createAiJobImportStep","deps","crawl","ownershipOf","rateLimit","flagOn","releaseFlagOn","ingestOf","ingest","readRoom","siteNameOf","fileReview","pageWritten","mintId","clock","Date","now","runLook","publishWave","draftWordsOf","draftWords","context","signal","model","unspent","rest","failure","nowIso","toISOString","review","event","ledger","jobId","nowMs","getTime","undefined","closing","outcome","closed","continue","sitePublish","error","console","waiting","more","autoContinue","gate","counted","window","windowMs","allowed","passed","room","org","left","Math","max","used","maxPages","min","timeBudgetMs","shallowFirst","crawlSeams","stoppedBy","skipped","verdict","inventory","readAt","menu","siteImportMenu","skippedOverflow","pageLimit","existingPages","region","planned","reviewId","autoContinueFrom","Number","POSITIVE_INFINITY","toRead","set","only","siteImportWaveReads","cutShort","anyRead","size","started","running","firstWave","uid","at","fetch","headersFor","lookDeps","runner","item","derived","runUnit","aborted","brought","reused","images","deadlineAt","fetchImage","ours","spent","stopped","written","unitJobId","layoutLanguage","output","withBrought","catch","settledState","paths","link","navLinks","URL","origin","pathname","asked","options","pathKey","parsed","search","unmatched","take","indexOf","splice","pending","found","siteImportReadOrEmpty","shift","aiSiteImportStartAllUpdate","createAiSiteImportAdmission","holdsSiteImport","member","Boolean","siteToCome","registerAiSiteImportJob","minimumMs","minimumMsFor"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/jobs/ai-job-import-step.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 * THE `import` JOB: BRING MY SITE, IN REVIEWED WAVES (AGL-3976).\n *\n * One step, many passes, each one unit of work (`aiSiteImportNextWork`):\n *\n * 1. READ the proved site (no model): the crawler reads it as AglynBot,\n * main pages first, up to the plan's page count; the inventory is cut\n * into waves (`model/ai-site-import.ts`) and every page gets a ledger\n * row. The job then WAITS (`needs_review`,\n * reason `wave`): nothing is brought in until the person starts wave 1.\n * 2. START A WAVE (no model), on the person's say-so: the proof is still\n * current, the day's limit has room, the plan still has room; the\n * wave's pages are read again, fresh, and a page that became a sign-in\n * page, went away or is now off limits to AglynBot is left out.\n * 3. THE LOOK, in the first wave (no model, AGL-4084): the theme drawn\n * from the owner's own home page, its logo into the library, the site's\n * listing from the home page's own words (`ai-site-import-look.ts`).\n * 4. THE HEADER AND FOOTER, in the first wave: the source's own menu, its\n * menus, its buttons and its footer as its home page builds them\n * (AGL-4108, `aiSiteImportFrameSource`), drawn by the layout step with\n * no model; for a source whose menu could not be read, the layout\n * step's own pass, with the source's brand as its header draws it, its\n * own header and footer words as the footer's facts, and the site's\n * menu order.\n * 5. EACH PAGE: its photos into the media library (no model, deduped by\n * source key), then the page step's own passes, NEVER REWRITTEN\n * (AGL-4084, `ai-site-import-document.ts`): a collection's page or a\n * long page is copied as it is, every word in order, with no model; a\n * main page is arranged, the model placing the source's numbered lines\n * and code writing every word as the source has it.\n * 6. CLOSE THE WAVE: its pages go live in the site's preview (AGL-4084,\n * `ai-site-import-publish.ts`), where only its team sees them, and the\n * job waits again until the person starts the next wave, or, where the\n * person chose \"Start every remaining wave\", starts it. The last wave\n * ends the job.\n *\n * Every page is an item of the job's ledger, so a page that fails on our\n * side gives back its own spend (the machine's `refundBuildCredits`) and the\n * wave goes on. Nothing is ever public by this job: a wave lands only in a\n * site that is in preview, and a site that is not keeps its pages as drafts.\n *=========================================*/\n\nimport { resolveEffectivePlan } from '@aglyn/aglyn/app-utils/plan-entitlements'\nimport { createResourceUid } from '@aglyn/aglyn/app-utils/create-resource-uid'\nimport { pluginMediaIngest, type PluginMediaIngest } from '@aglyn/aglyn/plugin-manager/plugin-media-ingest'\nimport {\n listDomainOwnershipClaims,\n normalizeOwnershipDomain,\n} from '@aglyn/tenant-data-admin/server/domain-ownership'\nimport { getOrgForUser, memberHasOrgPermission } from '@aglyn/tenant-data-admin/server/organizations'\nimport { consumeRateLimit } from '@aglyn/tenant-data-admin/server/rate-limit-store'\nimport { isServerReleaseFlagOnForOrg } from '@aglyn/tenant-data-admin/server/release-flags'\nimport type { AiBuildPlanCreate, AiBuildPlanScreen } from '../model/ai-build-plan'\nimport type { AiJob, AiJobItemLedger, AiJobPlan, AiJobReview } from '../model/ai-jobs.types'\nimport {\n AI_SITE_IMPORT_DOMAIN_INPUT,\n AI_SITE_IMPORT_FRAME_SLOT,\n AI_SITE_IMPORT_LABEL_MAX_CHARS,\n AI_SITE_IMPORT_LEFT_OUT_COPY,\n AI_SITE_IMPORT_MAX_PAGES,\n AI_SITE_IMPORT_MIN_WORDS,\n AI_SITE_IMPORT_WAVE_PAGES,\n aiSiteImportFrameIsRead,\n aiSiteImportInventory,\n aiSiteImportItemOpen,\n aiSiteImportLedger,\n aiSiteImportNextWork,\n aiSiteImportPageBuild,\n aiSiteImportPageSettled,\n aiSiteImportPagesRead,\n aiSiteImportPhotosIn,\n aiSiteImportReadStops,\n aiSiteImportReadVerdict,\n aiSiteImportReadVerdictMessage,\n aiSiteImportReadVerdictReason,\n aiSiteImportWaveClosed,\n aiSiteImportWaveMessage,\n aiSiteImportWaveStarted,\n type AiSiteImportBuild,\n type AiSiteImportHome,\n type AiSiteImportLeftOutReason,\n type AiSiteImportPage,\n type AiSiteImportPageRead,\n type AiSiteImportState,\n type AiSiteImportWave,\n} from '../model/ai-site-import'\nimport { aiModelForStep } from '../providers/routing'\nimport { SITE_IMPORT_RELEASE_FLAG } from '../site-import/site-import-flag'\nimport { crawlSiteForImport, siteImportOrigins, type SiteImportCrawlSeams, type SiteImportInventory } from '../site-import/site-import-crawl'\nimport { bringInSiteImportPhotos, type SiteImportPhotosDeps } from '../site-import/site-import-images'\nimport {\n siteImportHeaderBrand,\n siteImportLabel,\n siteImportLeftOutReason,\n siteImportListedPage,\n siteImportPageRead,\n siteImportPageWords,\n siteImportSiteFacts,\n siteImportSiteName,\n} from '../site-import/site-import-page'\nimport { aiSiteKindFor } from '../model/ai-site-kinds'\nimport { AI_LAYOUT_SITE_BRAND_INPUT, AI_LAYOUT_SITE_FACTS_INPUT, AI_LAYOUT_SITE_FRAME_INPUT } from './ai-job-layout-language'\nimport { aiLayoutTelHref, type AiLayoutFrameSource, type AiLayoutFrameSourceGround, type AiLayoutFrameSourceTo } from '../layout-language/ai-layout-frame-source'\nimport { aiHexOklch } from '../model/ai-site-look'\nimport { AI_LAYOUT_IMPORTED_SECTIONS_INPUT, type AiSiteImportDocument } from './ai-site-import-document'\nimport { aiSiteImportSectionNames } from './ai-site-import-compile'\nimport { aiRunSiteImportLook, type AiSiteImportLookDeps } from './ai-site-import-look'\nimport { aiPublishImportedWave } from './ai-site-import-publish'\nimport { aiUnitErrorRetryable, aiUnitFailure, aiUnitSpend } from './ai-build-unit-outcome'\nimport { registerAiJobAdmission, type AiJobAdmission } from './ai-job-admission'\nimport { AI_JOB_STEP_OVERHEAD_MS } from './ai-job-budget'\nimport { readAiDraftNodes, readAiScreenRoom } from './ai-job-drafts'\nimport { aiUnspentOutcome } from './ai-job-generation'\nimport { AI_LAYOUT_PAGE_PHOTOS_INPUT } from './ai-layout-owner-photos'\nimport { AI_LAYOUT_SITE_PAGES_INPUT, AI_LAYOUT_SITE_PAGES_MAX, type AiLayoutSitePage } from './ai-job-layout-site-pages'\nimport { AI_JOB_PAGE_STEP_MINIMUM_MS } from './ai-job-page-budget'\nimport { AI_LAYOUT_IMPORTED_PAGE_INPUT, AI_LAYOUT_LANGUAGE_INPUT } from './ai-job-page-language'\nimport { aiSitePageWritten } from './ai-job-site-step'\nimport { AI_STOCK_PHOTO_PAGES_INPUT } from './ai-layout-stock-photos'\nimport { AI_JOB_BRIEF_MAX_CHARS, type AiJobItemOutcome, type AiJobStepContext, type AiJobStepOutcome, type AiJobStepRunner } from './ai-job-text-step'\nimport {\n aiApplyJobItemRecord,\n aiJobStepRunMinimumMs,\n aiJobStepRunnerFor,\n registerAiJobStep,\n registerAiJobStepPasses,\n} from './ai-jobs'\n\n/** Waves (the read included) one workspace may start in a day. */\nexport const SITE_IMPORT_WAVES_PER_ORG_PER_DAY = 12\n\nconst DAY_MS = 24 * 60 * 60 * 1000\n\n/** The rate-limit key a workspace's imports share. */\nexport function siteImportRateKey(orgId: string): string {\n return `ai-import:${orgId}`\n}\n\n/** The crawl's clock when the import reads the whole site. */\nexport const AI_SITE_IMPORT_READ_MS = 150_000\n\n/** The crawl's clock when a wave reads its own pages again. */\nexport const AI_SITE_IMPORT_WAVE_READ_MS = 90_000\n\n/** The clock for one page's photos: each is fetched and stored through the library's door. */\nexport const AI_SITE_IMPORT_PHOTOS_MS = 90_000\n\n/** What the step's own reads and writes around a pass take: the claims, the room, the row. */\nconst OWN_READS_MS = 10_000\n\n/** The least time each pass that asks no model needs. */\nexport const AI_SITE_IMPORT_PASS_MINIMUM_MS = {\n read: AI_SITE_IMPORT_READ_MS + OWN_READS_MS + AI_JOB_STEP_OVERHEAD_MS,\n wave: AI_SITE_IMPORT_WAVE_READ_MS + OWN_READS_MS + AI_JOB_STEP_OVERHEAD_MS,\n photos: AI_SITE_IMPORT_PHOTOS_MS + OWN_READS_MS + AI_JOB_STEP_OVERHEAD_MS,\n} as const\n\n/**\n * The passes one import may take: a read, then for every page its photos,\n * its answer and its listing, every wave's start and the header and footer,\n * with room for re-asks.\n */\nexport const AI_SITE_IMPORT_MAX_PASSES = AI_SITE_IMPORT_MAX_PAGES * 4 + 60\n\n/** Customer-safe sentences. */\nexport const AI_SITE_IMPORT_COPY = {\n noSite: 'Open the site to bring your website into.',\n badDomain: 'This website’s address cannot be brought in.',\n ownership: (domain: string) =>\n `Verify that you own ${domain} before bringing it in. A proof is good for 30 days; verify again, then start this wave again.`,\n limit: `This workspace has started as many site waves as it can today (${SITE_IMPORT_WAVES_PER_ORG_PER_DAY}). Start this wave again tomorrow.`,\n robots: (domain: string) =>\n `The robots.txt file of ${domain} could not be read just now, so nothing was read. Try again in a few minutes.`,\n nothing: (domain: string) => `No page of ${domain} could be read. Check that the site is up, then try again.`,\n blocked: (domain: string) =>\n `The bot protection or firewall of ${domain} turned AglynBot away, so no page could be read. Allow AglynBot in your site’s bot or firewall settings, then read the site again.`,\n unavailable: 'Bringing a site in is not available on this workspace right now.',\n frameUnavailable: 'The header and footer could not be built here; your pages use the site’s own layout.',\n pageUnavailable: 'Pages cannot be built here right now.',\n pageNotWritten: 'This page could not be written from its old page. Its spend is given back.',\n plan: 'Bringing an existing site in is included on every paid plan.',\n /** Names \"Bring a site in\" (`ai.import`, AGL-4047), never a role. */\n role: 'Your role does not include \"Bring a site in\" — ask an organization admin',\n} as const\n\n/*------------------------------------------\n * Seams\n *-----------------------------------------*/\n\nexport interface AiSiteImportOwnership {\n current: boolean\n method: string | null\n provenAt: number | null\n detail: string | null\n}\n\nexport interface AiSiteImportStepDeps {\n crawl?: typeof crawlSiteForImport\n crawlSeams?: SiteImportCrawlSeams\n runnerFor?: typeof aiJobStepRunnerFor\n ownership?: (orgId: string, domain: string) => Promise<AiSiteImportOwnership | null>\n rateLimit?: (key: string, options: { limit: number; windowMs: number }) => Promise<{ allowed: boolean }>\n releaseFlagOn?: (orgId: string) => Promise<boolean>\n ingest?: () => PluginMediaIngest | null\n fetchImage?: SiteImportPhotosDeps['fetch']\n readRoom?: typeof readAiScreenRoom\n readSiteName?: (firestore: FirebaseFirestore.Firestore, hostId: string) => Promise<string>\n pageWritten?: typeof aiSitePageWritten\n mintId?: () => string\n clock?: () => number\n /** The first wave's look pass (AGL-4084), and what it reads and writes through. */\n look?: typeof aiRunSiteImportLook\n lookDeps?: AiSiteImportLookDeps\n /** A closed wave's pages into the site's preview (AGL-4084). */\n publishWave?: typeof aiPublishImportedWave\n /** The words a page that came in shows, read off its draft (AGL-4084). */\n draftWords?: (firestore: FirebaseFirestore.Firestore, hostId: string, draftId: string) => Promise<number | null>\n}\n\nasync function readOwnership(orgId: string, domain: string): Promise<AiSiteImportOwnership | null> {\n const claims = await listDomainOwnershipClaims(orgId)\n const claim = claims.find((entry) => entry.domain === domain)\n if (!claim) return null\n return { current: claim.current, method: claim.provenMethod, provenAt: claim.provenAt, detail: claim.provenDetail }\n}\n\nasync function readSiteName(firestore: FirebaseFirestore.Firestore, hostId: string): Promise<string> {\n const host = await firestore.collection('hosts').doc(hostId).get()\n const name = host.get('displayName')\n return typeof name === 'string' ? name.trim() : ''\n}\n\n/** The proved domain an import job is for, or `null`. */\nexport function aiSiteImportDomainOf(job: Pick<AiJob, 'inputs'>): string | null {\n return normalizeOwnershipDomain(String(job.inputs?.[AI_SITE_IMPORT_DOMAIN_INPUT] ?? '')).domain\n}\n\n/*------------------------------------------\n * The jobs a unit is handed to\n *-----------------------------------------*/\n\nconst pathOf = (slug: string) => (slug === '/' ? '/' : `/${slug}`)\n\n/** A plan as a delegated unit reads it: confirmed, with what it builds and nothing else. */\nfunction unitPlan(job: AiJob, input: { create?: AiBuildPlanCreate[]; screens?: AiBuildPlanScreen[] }): AiJobPlan {\n return {\n reuse: [],\n create: input.create ?? [],\n screens: input.screens ?? [],\n labels: {},\n status: 'confirmed',\n proposedAt: job.createdAt,\n confirmedAt: job.createdAt,\n confirmedBy: job.createdBy,\n }\n}\n\nconst delivered = (items: readonly AiJobItemLedger[], slot: string) =>\n items.some((row) => row.slot === slot && (row.status === 'succeeded' || row.status === 'degraded'))\n\n/**\n * The pages the header and a page may link: the ones of this wave and those\n * before it that are in or still coming, home first, at most the header's\n * seven. A page of a later wave is not linked: it may never be brought in.\n */\nexport function aiSiteImportLinkedPages(\n state: AiSiteImportState,\n items: readonly AiJobItemLedger[],\n wave: number,\n): AiLayoutSitePage[] {\n const rows = new Map(items.map((row) => [row.slot, row]))\n const pages = state.pages\n .filter((page) => page.wave <= wave && !page.refused)\n .filter((page) => {\n const row = rows.get(page.slot)\n return !row || row.status === 'pending' || row.status === 'running' || row.status === 'succeeded' || row.status === 'degraded'\n })\n .map((page) => ({ id: page.draftId, label: page.title, slug: pathOf(page.slug) }))\n return [...pages.filter((page) => page.slug === '/'), ...pages.filter((page) => page.slug !== '/')].slice(0, AI_LAYOUT_SITE_PAGES_MAX)\n}\n\n/**\n * How a page is built (AGL-4084): a collection's page, or a long page, is\n * copied as it is; a main page is arranged. The home page is always\n * arranged, however long: it is the site's front door, never a document.\n */\nexport function aiSiteImportBuildOf(page: Pick<AiSiteImportPage, 'group' | 'words' | 'slug'>): AiSiteImportBuild {\n return page.group === 'main' && page.slug === '/' ? 'arranged' : aiSiteImportPageBuild(page)\n}\n\n/**\n * The name the header and footer carry (AGL-4084): the site's own name where\n * it is the name the person gave Create site but for its case or its\n * punctuation, else the person's.\n */\nexport function aiSiteImportBrandName(given: string, own: string): string {\n const key = (text: string) => text.toLowerCase().replace(/[^\\p{L}\\p{N}]+/gu, '')\n return own && key(own) && key(own) === key(given) ? own : given\n}\n\n/** The design inputs every unit of an import is drawn with: the kind of site its own words say, and its look (AGL-4084). */\nfunction aiSiteImportDesignInputs(state: AiSiteImportState): Record<string, unknown> {\n const home = state.home\n const kind = home ? aiSiteKindFor(`${home.siteName} ${home.description}`) : null\n const look = state.look\n return {\n ...(kind ? { siteKind: kind.id } : {}),\n ...(look && look.seed !== null\n ? {\n siteStyle: {\n seed: look.seed,\n ...(look.style?.headerAlign ? { headerAlign: look.style.headerAlign } : {}),\n ...(look.style?.rhythm ? { rhythm: look.style.rhythm } : {}),\n ...(look.style?.motion ? { motion: look.style.motion } : {}),\n },\n }\n : {}),\n }\n}\n\n/**\n * Where a link of the source's header or footer goes on the new site\n * (AGL-4108): a page the import brings in by its id, once its wave is the\n * header's or before it; a page of a later wave by its address on the new\n * site, which the page takes when its wave lands, since a link by id to a\n * page not yet live is taken out when a wave goes live; and anywhere else by\n * the source's own address, so a button that leaves the source leaves the\n * new site too. `null` for an address no link may carry.\n */\nexport function aiSiteImportFrameLinkTo(state: Pick<AiSiteImportState, 'domain' | 'pages'>, wave: number): (href: string | null | undefined) => AiLayoutFrameSourceTo | null {\n const origins = new Set(siteImportOrigins(state.domain))\n const key = (path: string) => path.replace(/\\/+$/, '') || '/'\n const pages = new Map(state.pages.filter((page) => !page.refused).map((page) => [key(page.path), page]))\n return (href) => {\n const raw = String(href ?? '').trim()\n if (!raw) return null\n if (/^tel:/i.test(raw)) return aiLayoutTelHref(raw.slice(4))\n if (/^mailto:/i.test(raw)) return /^mailto:[^\\s@<>?#\"]+@[^\\s@<>?#\"]+\\.[^\\s@<>?#\".]{2,}$/i.test(raw) ? raw : null\n let url: URL\n try {\n url = new URL(raw)\n } catch {\n return null\n }\n if (url.protocol !== 'https:' && url.protocol !== 'http:') return null\n if (origins.has(`https://${url.host}`)) {\n const page = pages.get(key(decodeURIComponent(url.pathname)))\n if (page) return page.slug === '/' || page.wave <= wave ? `page:${page.draftId}` : `/${page.slug}`\n }\n // Anywhere else stays where the source sends it, over https.\n url.protocol = 'https:'\n return url.toString()\n }\n}\n\n/** The ground a source's header bar sits on (AGL-4108): dark, the brand's color, the page's own, or paper. */\nexport function aiSiteImportHeaderGround(background: string | null, look: AiSiteImportHome['look']): AiLayoutFrameSourceGround {\n const hex = /^#[0-9a-f]{6}$/i.test(background ?? '') ? (background as string) : null\n if (!hex) return 'paper'\n const own = aiHexOklch(hex)\n if (own.L < 0.4) return 'dark'\n const near = (other: string | null | undefined, within: number) => {\n if (!other || !/^#[0-9a-f]{6}$/i.test(other)) return false\n const them = aiHexOklch(other)\n const a = own.C * Math.cos((own.h * Math.PI) / 180) - them.C * Math.cos((them.h * Math.PI) / 180)\n const b = own.C * Math.sin((own.h * Math.PI) / 180) - them.C * Math.sin((them.h * Math.PI) / 180)\n return Math.hypot(own.L - them.L, a, b) <= within\n }\n if (near(look?.buttonFill, 0.05)) return 'brand'\n // The page's own ground, unless that ground is white, which paper is.\n if (near(look?.background, 0.02) && own.L < 0.99) return 'page'\n return 'paper'\n}\n\n/**\n * The site's header and footer as the source builds them (AGL-4108): its\n * menu with its menus and their entries, its buttons with their own\n * addresses and how they are drawn, and its footer, every link resolved\n * (`aiSiteImportFrameLinkTo`). Every label is the source's, as written.\n * `null` where the reader found no menu on the home page.\n */\nexport function aiSiteImportFrameSource(state: AiSiteImportState, wave: Pick<AiSiteImportWave, 'index'>): AiLayoutFrameSource | null {\n const home = state.home\n const nav = home?.nav\n if (!home || !nav || !aiSiteImportFrameIsRead(state)) return null\n const to = aiSiteImportFrameLinkTo(state, wave.index)\n const link = (label: string, href: string | null | undefined) => {\n const target = to(href)\n return label && target ? { label, to: target } : null\n }\n const present = <T,>(value: T | null): value is T => value !== null\n const footer = home.footer ?? null\n return {\n nav: nav.items\n .map((group) => ({\n label: group.label,\n to: to(group.href),\n items: group.items\n .map((entry) => {\n const target = link(entry.label, entry.href)\n if (!target) return null\n return {\n ...target,\n ...(entry.text ? { text: entry.text } : {}),\n // The icon element draws on a 24-unit square: an icon drawn on another is left out.\n ...(entry.iconPath && (entry.viewBox ?? '0 0 24 24') === '0 0 24 24' ? { iconPath: entry.iconPath } : {}),\n ...(entry.column ? { column: entry.column } : {}),\n }\n })\n .filter(present),\n }))\n .filter((group) => group.items.length || group.to),\n ctas: nav.ctas.map((cta) => {\n const target = link(cta.label, cta.href)\n return target ? { ...target, style: cta.style } : null\n }).filter(present),\n header: aiSiteImportHeaderGround(nav.background, home.look ?? null),\n footer: footer\n ? {\n columns: footer.columns\n .map((column) => ({ heading: column.heading, links: column.links.map((entry) => link(entry.label, entry.href)).filter(present) }))\n .filter((column) => column.links.length),\n links: footer.links.map((entry) => link(entry.label, entry.href)).filter(present),\n text: footer.text,\n social: footer.social.map((entry) => (/^https:\\/\\//i.test(entry.href) ? { label: entry.label, to: entry.href, network: entry.network } : null)).filter(present),\n address: footer.address,\n phone: footer.phone,\n email: footer.email,\n // The © line as the source writes it; where it writes none, the source's own name.\n copyright: footer.copyright ?? (home.siteName ? `© ${home.siteName}` : null),\n }\n : null,\n }\n}\n\n/** The header and footer's job: a layout of the site's brand, linking the wave's pages, in the layout language. */\nexport function aiSiteImportFrameJob(job: AiJob, state: AiSiteImportState, wave: AiSiteImportWave, items: readonly AiJobItemLedger[]): AiJob {\n const draftId = state.frame?.draftId ?? `${job.$id}-${AI_SITE_IMPORT_FRAME_SLOT}`\n const creation: AiBuildPlanCreate = {\n kind: 'layout',\n name: 'Header and footer',\n why: `The header and footer every page brought in from ${state.domain} renders inside.`,\n duplicateOf: null,\n fields: ['header', 'nav', 'main', 'footer'],\n id: draftId,\n }\n const home = state.home ?? null\n const logo = state.look?.logo ?? null\n // The brand as the source's header draws it; with no logo in the library, its name.\n // The logo is named as the source names it, never by the host's name (AGL-4108).\n const withLogo = !!logo && !!home && home.brand.kind !== 'name-only'\n const alt = home ? (home.brand.logo?.alt || home.siteName || home.brand.text).replace(/\\s+/g, ' ').trim().slice(0, 120) : ''\n const aspect = logo?.width && logo.height ? Math.round((logo.width / logo.height) * 1000) / 1000 : null\n const brand = home\n ? {\n ...(withLogo ? { logo: { src: (logo as NonNullable<typeof logo>).src }, ...(alt ? { alt } : {}), ...(aspect ? { aspect } : {}) } : {}),\n name: !logo || home.brand.kind !== 'logo-only',\n }\n : null\n // The source's own menu, buttons and footer, drawn with no model (AGL-4108).\n const source = aiSiteImportFrameSource(state, wave)\n return {\n ...job,\n $id: draftId,\n kind: 'layout',\n steps: [],\n outputs: [],\n items: null,\n siteImport: null,\n plan: unitPlan(job, { create: [creation] }),\n inputs: {\n originJobId: job.$id,\n businessName: aiSiteImportBrandName(state.siteName, home?.siteName ?? ''),\n [AI_LAYOUT_LANGUAGE_INPUT]: true,\n [AI_LAYOUT_SITE_PAGES_INPUT]: aiSiteImportLinkedPages(state, items, wave.index),\n ...aiSiteImportDesignInputs(state),\n ...(brand ? { [AI_LAYOUT_SITE_BRAND_INPUT]: brand } : {}),\n ...(source ? { [AI_LAYOUT_SITE_FRAME_INPUT]: source } : {}),\n // The source's own header and footer words, fenced where the prompt shows them (AGL-4084).\n ...(home ? { [AI_LAYOUT_SITE_FACTS_INPUT]: { url: home.url, description: home.description, lines: home.facts.lines } } : {}),\n },\n // Never words a footer could print as the site's own (AGL-4084): the prompt shows the source's.\n brief: `The header and footer of the site “${state.siteName}”.`.slice(0, AI_JOB_BRIEF_MAX_CHARS),\n }\n}\n\n/** The page brought in, as its page job carries it: its lines, its photos, and the pages its links may go to (AGL-4084). */\nexport function aiSiteImportDocumentFor(state: AiSiteImportState, page: AiSiteImportPage): AiSiteImportDocument | null {\n const blocks = page.read?.blocks\n if (!blocks?.length) return null\n return {\n build: page.build ?? aiSiteImportBuildOf(page),\n title: page.title,\n url: page.url,\n blocks,\n photos: page.photos?.assets ?? [],\n // Every page the import plans, in any wave (AGL-4107): a link to one still\n // to come shows its words until it is live. Home's own links are words: a\n // link home says home, which the source's words may not.\n links: state.pages.filter((entry) => entry.slug !== '/' && !entry.refused).map((entry) => ({ path: entry.path.replace(/\\/+$/, '') || '/', id: entry.draftId })),\n origins: [`https://${state.domain}`, `https://www.${state.domain.replace(/^www\\./, '')}`],\n // How the source lays it out (AGL-4106), which the site compiler builds it from (AGL-4107).\n ...(page.read?.layout ? { layout: page.read.layout } : {}),\n }\n}\n\n/** One page's job: a page job's plan of one screen, its sections the old page's own, its words carried as they are. */\nexport function aiSiteImportPageJob(\n job: AiJob,\n state: AiSiteImportState,\n page: AiSiteImportPage,\n items: readonly AiJobItemLedger[],\n): AiJob {\n const doc = aiSiteImportDocumentFor(state, page)\n // The page's sections are the source's own (AGL-4107): as its layout names\n // them, else its opening and one at each second-level heading.\n const names = doc ? aiSiteImportSectionNames(doc) : page.read?.sections ?? []\n const sections = (names.length ? names : ['Introduction']).map((name) => ({\n name: name.slice(0, AI_SITE_IMPORT_LABEL_MAX_CHARS),\n uses: [],\n items: 0,\n }))\n const screen: AiBuildPlanScreen = {\n title: page.title,\n slug: pathOf(page.slug),\n // Inside the header and footer this import built, once it is in.\n layout: state.frame && delivered(items, AI_SITE_IMPORT_FRAME_SLOT) ? state.frame.draftId : null,\n template: null,\n duplicateOf: null,\n nav: false,\n // The source's own title and description, word for word (AGL-4107).\n seoTitle: page.read?.meta?.title || page.title,\n seoDescription: page.read?.meta?.description ?? '',\n sections,\n record: null,\n id: page.draftId,\n }\n // The other pages already in, whose stock photos this page does not repeat.\n const others = state.pages.filter((entry) => entry.slot !== page.slot && delivered(items, entry.slot)).map((entry) => entry.draftId)\n return {\n ...job,\n $id: page.draftId,\n kind: 'page',\n steps: [],\n outputs: [],\n items: null,\n siteImport: null,\n plan: unitPlan(job, { screens: [screen] }),\n inputs: {\n originJobId: job.$id,\n businessName: aiSiteImportBrandName(state.siteName, state.home?.siteName ?? ''),\n [AI_LAYOUT_LANGUAGE_INPUT]: true,\n [AI_LAYOUT_SITE_PAGES_INPUT]: aiSiteImportLinkedPages(state, items, page.wave),\n ...aiSiteImportDesignInputs(state),\n // Every word as the source has it (AGL-4084); a read from before it was kept is the text the old page step had.\n ...(doc\n ? { [AI_LAYOUT_IMPORTED_SECTIONS_INPUT]: doc }\n : { [AI_LAYOUT_IMPORTED_PAGE_INPUT]: { url: page.url, text: page.read?.text ?? '' } }),\n [AI_LAYOUT_PAGE_PHOTOS_INPUT]: page.photos?.assets ?? [],\n ...(others.length ? { [AI_STOCK_PHOTO_PAGES_INPUT]: others } : {}),\n },\n brief: `Bring in the page “${page.title}” of ${state.domain} as a page of “${state.siteName}”.`.slice(0, AI_JOB_BRIEF_MAX_CHARS),\n }\n}\n\n/** What the home page says of the site as a whole (AGL-4084), kept for the look, the header and footer and the listing. */\nexport function aiSiteImportHomeOf(crawled: Pick<SiteImportInventory, 'pages'>): AiSiteImportHome | null {\n const page = crawled.pages.find((entry) => entry.foundBy === 'home') ?? crawled.pages.find((entry) => (entry.path.replace(/\\/+$/, '') || '/') === '/')\n if (!page) return null\n const brand = siteImportHeaderBrand(page)\n const facts = siteImportSiteFacts(page)\n const lines: string[] = []\n let chars = 0\n for (const block of [...facts.header, ...facts.footer]) {\n if (block.kind === 'image' || (block.kind === 'link' && block.inline)) continue\n const text = block.text.replace(/\\s+/g, ' ').trim()\n const line = block.kind === 'link' && /^(?:mailto|tel):/i.test(block.href) ? text : block.kind === 'link' && facts.social.includes(block.href) ? `${text}: ${block.href}` : text\n if (!line || lines.includes(line) || chars + line.length > 3_000 || lines.length >= 60) continue\n lines.push(line)\n chars += line.length\n }\n // And what the site states of itself in its structured data, as written: its address, phone and email.\n const organization = facts.organization\n for (const line of [organization?.address, organization?.telephone, organization?.email]) {\n const text = (line ?? '').replace(/\\s+/g, ' ').trim()\n if (text && !lines.some((entry) => entry.includes(text))) lines.push(text)\n }\n return {\n url: page.url,\n title: siteImportLabel(page.title ?? '', 160),\n description: siteImportLabel(page.description ?? '', 320),\n ogImage: page.ogImage ?? null,\n siteName: siteImportSiteName(page),\n brand: {\n kind: brand.kind,\n text: brand.text,\n logo: brand.logo ? { url: brand.logo.url, alt: brand.logo.alt, type: brand.logo.type } : null,\n },\n facts: {\n lines,\n emails: facts.emails,\n phones: facts.phones,\n social: facts.social,\n address: facts.organization?.address ?? '',\n },\n // The source's menu, footer and look as its home page builds them (AGL-4108).\n ...(page.nav ? { nav: page.nav } : {}),\n ...(page.footer ? { footer: page.footer } : {}),\n ...(page.look ? { look: page.look } : {}),\n }\n}\n\n/** The least time the import's next pass needs: a read's, a photo pass's, or the time of the step its unit is handed to. */\nexport function aiSiteImportRunMinimumMs(job: AiJob, runnerFor: typeof aiJobStepRunnerFor = aiJobStepRunnerFor): number {\n const state = job.siteImport ?? null\n const items = job.items ?? []\n const work = aiSiteImportNextWork(state, items)\n switch (work.kind) {\n case 'inventory':\n return AI_SITE_IMPORT_PASS_MINIMUM_MS.read\n case 'start-wave':\n case 'read':\n return AI_SITE_IMPORT_PASS_MINIMUM_MS.wave\n case 'images':\n return AI_SITE_IMPORT_PASS_MINIMUM_MS.photos\n case 'frame':\n return runnerFor('layout') && state ? aiJobStepRunMinimumMs(aiSiteImportFrameJob(job, state, work.wave, items)) : 0\n case 'page':\n return runnerFor('page') && state ? aiJobStepRunMinimumMs(aiSiteImportPageJob(job, state, work.page, items)) : 0\n default:\n return 0\n }\n}\n\n/*------------------------------------------\n * The step\n *-----------------------------------------*/\n\nconst waveReview = (message: string): AiJobReview => ({ reason: 'wave', message, findings: [] })\n\n/** The rows a wave's read left out, settled as not brought in, with the reason. */\nfunction withLeftOutRows(\n items: readonly AiJobItemLedger[],\n reads: ReadonlyMap<string, AiSiteImportPageRead | AiSiteImportLeftOutReason>,\n): AiJobItemLedger[] {\n return items.map((row) => {\n const read = reads.get(row.slot)\n return typeof read === 'string' && (row.status === 'pending' || row.status === 'running')\n ? { ...row, status: 'skipped', note: AI_SITE_IMPORT_LEFT_OUT_COPY[read] }\n : row\n })\n}\n\n/**\n * The state with how each page is built (AGL-4084): from its main region's\n * words as the inventory listed them, and again from a wave's fresh read,\n * which is what the page is built from.\n */\nexport function aiSiteImportWithBuilds(state: AiSiteImportState, mainWords?: ReadonlyMap<string, number>): AiSiteImportState {\n return {\n ...state,\n pages: state.pages.map((page) => {\n const words = page.read?.words ?? mainWords?.get(page.url) ?? page.words\n const build = aiSiteImportBuildOf({ ...page, words })\n return page.build === build ? page : { ...page, build }\n }),\n }\n}\n\n/** The words a stored page shows (AGL-4084): its text, its list lines and its buttons. */\nexport function aiSiteImportShownWords(nodes: Readonly<Record<string, unknown>>): number {\n let words = 0\n for (const node of Object.values(nodes)) {\n const props = (node as { props?: Record<string, unknown> } | null)?.props ?? {}\n for (const key of ['children', 'primary', 'secondary']) {\n const value = props[key]\n if (typeof value === 'string') words += (value.match(/[\\p{L}\\p{N}]+/gu) ?? []).length\n }\n }\n return words\n}\n\nasync function readDraftWords(firestore: FirebaseFirestore.Firestore, hostId: string, draftId: string): Promise<number | null> {\n const stored = await readAiDraftNodes(firestore, { kind: 'screen', hostId, id: draftId })\n return stored ? aiSiteImportShownWords(stored.nodes as unknown as Record<string, unknown>) : null\n}\n\n/**\n * The review a wave that went live in the site's preview parks on (AGL-4084):\n * where its pages are now, who sees them, and the next wave's start.\n */\nexport function aiSiteImportPreviewMessage(state: AiSiteImportState, wave: Pick<AiSiteImportWave, 'label'>, published: number): string {\n const pages = `${published.toLocaleString('en-US')} ${published === 1 ? 'page is' : 'pages are'}`\n const lead = `${wave.label} is in your site’s preview: ${pages} on your site, where only you and your team can see ${published === 1 ? 'it' : 'them'}.`\n const next = state.waves.find((entry) => entry.status === 'waiting')\n return next ? `${lead} Start ${next.label} when you are ready.` : lead\n}\n\n/** Whether every row of the wave is settled, its header and footer included. */\nfunction waveSettled(state: AiSiteImportState, wave: AiSiteImportWave, items: readonly AiJobItemLedger[]): boolean {\n if (wave.frame && state.frame && aiSiteImportItemOpen(items, AI_SITE_IMPORT_FRAME_SLOT)) return false\n return wave.slots.every((slot) => !aiSiteImportItemOpen(items, slot))\n}\n\nexport function createAiJobImportStep(deps: AiSiteImportStepDeps = {}): AiJobStepRunner {\n const crawl = deps.crawl ?? crawlSiteForImport\n const runnerFor = deps.runnerFor ?? aiJobStepRunnerFor\n const ownershipOf = deps.ownership ?? readOwnership\n const rateLimit = deps.rateLimit ?? consumeRateLimit\n const flagOn = deps.releaseFlagOn ?? ((orgId: string) => isServerReleaseFlagOnForOrg(SITE_IMPORT_RELEASE_FLAG, orgId))\n const ingestOf = deps.ingest ?? pluginMediaIngest\n const readRoom = deps.readRoom ?? readAiScreenRoom\n const siteNameOf = deps.readSiteName ?? readSiteName\n const pageWritten = deps.pageWritten ?? aiSitePageWritten\n const mintId = deps.mintId ?? createResourceUid\n const clock = deps.clock ?? Date.now\n const runLook = deps.look ?? aiRunSiteImportLook\n const publishWave = deps.publishWave ?? aiPublishImportedWave\n const draftWordsOf = deps.draftWords ?? readDraftWords\n\n return async (context: AiJobStepContext): Promise<AiJobStepOutcome> => {\n const { job, firestore, now, signal } = context\n const model = aiModelForStep('job.page')\n const unspent = (rest: Partial<AiJobStepOutcome> = {}): AiJobStepOutcome => ({ ...aiUnspentOutcome(model), ...rest })\n const hostId = job.hostId\n if (!hostId) return unspent({ failure: AI_SITE_IMPORT_COPY.noSite })\n const domain = aiSiteImportDomainOf(job)\n if (!domain) return unspent({ failure: AI_SITE_IMPORT_COPY.badDomain })\n const state = job.siteImport ?? null\n const items = job.items ?? []\n const work = aiSiteImportNextWork(state, items)\n const nowIso = now.toISOString()\n\n /** Closes the wave when this pass settled its last row: the review, or the job's end after the last wave. */\n const closing = async (\n next: AiSiteImportState,\n ledger: readonly AiJobItemLedger[],\n wave: AiSiteImportWave,\n outcome: AiJobStepOutcome,\n ): Promise<AiJobStepOutcome> => {\n if (!waveSettled(next, wave, ledger)) return { ...outcome, siteImport: next, continue: true }\n const closed = aiSiteImportWaveClosed(next, wave.index, nowIso)\n // The wave's pages go live in the site's preview, where only its team sees them (AGL-4084).\n let sitePublish = null as Awaited<ReturnType<typeof publishWave>>\n try {\n sitePublish = await publishWave(firestore, {\n job,\n state: closed,\n wave,\n items: ledger,\n outputs: [...(job.outputs ?? []), ...(outcome.outputs ?? [])],\n now,\n })\n } catch (error) {\n // A publish that failed leaves the pages drafts; the wave is still in.\n console.error('ai site import: a wave could not be published into the preview', { orgId: job.orgId, jobId: job.$id, wave: wave.index, error })\n }\n const published = sitePublish ? { sitePublish } : {}\n const waiting = closed.waves.find((entry) => entry.index === wave.index)?.status === 'review'\n if (waiting) {\n const message = sitePublish?.published.length ? aiSiteImportPreviewMessage(closed, wave, sitePublish.published.length) : aiSiteImportWaveMessage(closed, ledger)\n return { ...outcome, ...published, siteImport: closed, review: waveReview(message) }\n }\n // \"Start every remaining wave\" (AGL-4083): the next wave starts with no review between them.\n const more = closed.autoContinue === true && closed.waves.some((entry) => entry.status === 'waiting')\n return { ...outcome, ...published, siteImport: closed, ...(more ? { continue: true } : {}) }\n }\n\n /** The proof, the flag and the day's limit, asked before anything is read. */\n const gate = async (counted = true): Promise<{ ownership: AiSiteImportOwnership } | AiJobStepOutcome> => {\n if (!(await flagOn(job.orgId))) return unspent({ review: waveReview(AI_SITE_IMPORT_COPY.unavailable) })\n const ownership = await ownershipOf(job.orgId, domain)\n if (!ownership?.current) {\n return unspent({ review: { reason: 'ownership', message: AI_SITE_IMPORT_COPY.ownership(domain), findings: [] } })\n }\n if (counted) {\n const window = await rateLimit(siteImportRateKey(job.orgId), { limit: SITE_IMPORT_WAVES_PER_ORG_PER_DAY, windowMs: DAY_MS })\n if (!window.allowed) return unspent({ review: { reason: 'limit', message: AI_SITE_IMPORT_COPY.limit, findings: [] } })\n }\n return { ownership }\n }\n\n // ── 1. Read the site ──\n if (work.kind === 'inventory') {\n const passed = await gate()\n if (!('ownership' in passed)) return passed\n const room = await readRoom(firestore, { hostId, org: (context.org ?? null) as never })\n const left = room.limit === null ? AI_SITE_IMPORT_MAX_PAGES : Math.max(0, room.limit - room.used)\n const crawled = await crawl(\n {\n domain,\n // A wave's worth past the room, so what the plan leaves out is said.\n maxPages: Math.min(AI_SITE_IMPORT_MAX_PAGES, left + AI_SITE_IMPORT_WAVE_PAGES),\n timeBudgetMs: AI_SITE_IMPORT_READ_MS,\n shallowFirst: true,\n ...(signal ? { signal } : {}),\n },\n deps.crawlSeams,\n )\n if (crawled.refused) return unspent({ failure: AI_SITE_IMPORT_COPY.badDomain })\n if (crawled.stoppedBy === 'robots-unreachable') return unspent({ review: waveReview(AI_SITE_IMPORT_COPY.robots(domain)) })\n const skipped = crawled.skipped.map((entry) => ({ url: entry.url, reason: siteImportLeftOutReason(entry.reason, entry.status) }))\n // Home first (AGL-4083): a site read without its home page plans nothing, quotes nothing and spends nothing.\n const verdict = aiSiteImportReadVerdict(crawled)\n const inventory = aiSiteImportInventory({\n domain,\n siteName: await siteNameOf(firestore, hostId),\n ownership: { method: passed.ownership.method, provenAt: passed.ownership.provenAt, detail: passed.ownership.detail },\n readAt: nowIso,\n pages: crawled.pages.map(siteImportListedPage),\n menu: siteImportMenu(crawled),\n skipped,\n skippedOverflow: crawled.skippedOverflow,\n stoppedBy: crawled.stoppedBy,\n pageLimit: room.limit,\n existingPages: room.used,\n verdict,\n mintId,\n })\n if (aiSiteImportReadStops(inventory.verdict)) {\n // Check again is the read again: the job waits, with why and what to do, and no ledger.\n return unspent({\n items: [],\n siteImport: inventory,\n review: {\n reason: aiSiteImportReadVerdictReason(inventory.verdict) ?? 'unreadable',\n message: aiSiteImportReadVerdictMessage(inventory.verdict, domain) ?? AI_SITE_IMPORT_COPY.nothing(domain),\n findings: [],\n },\n })\n }\n // How each page is built, from its main region's own words (AGL-4084), and what the home page says of the site.\n const mainWords = new Map(\n crawled.pages.map((page) => [page.url, siteImportPageWords({ title: '', blocks: page.blocks.filter((block) => block.region === 'main') })]),\n )\n const planned = { ...aiSiteImportWithBuilds(inventory, mainWords), home: aiSiteImportHomeOf(crawled) }\n const ledger = aiSiteImportLedger(planned)\n return unspent({ items: ledger, siteImport: planned, review: waveReview(aiSiteImportWaveMessage(planned, ledger)) })\n }\n\n if (!state) return unspent({ failure: AI_SITE_IMPORT_COPY.badDomain })\n if (work.kind === 'done') return unspent()\n\n // ── 2. Start a wave ──\n if (work.kind === 'start-wave') {\n // A wave \"Start every remaining wave\" started after the one the person did is that same start.\n const counted = !(state.autoContinue && typeof state.autoContinueFrom === 'number' && work.wave.index > state.autoContinueFrom)\n const passed = await gate(counted)\n if (!('ownership' in passed)) return passed\n const wave = work.wave\n const pages = wave.slots\n .map((slot) => state.pages.find((page) => page.slot === slot))\n .filter((page): page is AiSiteImportPage => !!page)\n const reads = new Map<string, AiSiteImportPageRead | AiSiteImportLeftOutReason>()\n // Never past the plan: the room is read again, since pages may have been added since the site was read.\n const room = await readRoom(firestore, { hostId, org: (context.org ?? null) as never })\n let left = room.limit === null ? Number.POSITIVE_INFINITY : Math.max(0, room.limit - room.used)\n const toRead: AiSiteImportPage[] = []\n for (const page of pages) {\n if (left > 0) {\n toRead.push(page)\n left -= 1\n } else {\n reads.set(page.slot, 'plan-limit')\n }\n }\n if (toRead.length) {\n const crawled = await crawl(\n {\n domain,\n maxPages: toRead.length,\n only: toRead.map((page) => page.url),\n timeBudgetMs: AI_SITE_IMPORT_WAVE_READ_MS,\n ...(signal ? { signal } : {}),\n },\n deps.crawlSeams,\n )\n if (crawled.stoppedBy === 'robots-unreachable') return unspent({ review: waveReview(AI_SITE_IMPORT_COPY.robots(domain)) })\n // A read the clock cut short leaves its other pages for the next pass, never \"unreadable\".\n for (const [slot, read] of siteImportWaveReads(toRead, crawled, nowIso, { cutShort: crawled.stoppedBy === 'time' })) {\n reads.set(slot, read)\n }\n }\n let ledger = withLeftOutRows(items, reads)\n // A wave none of whose pages could be read builds no header for them.\n const anyRead = [...reads.values()].some((read) => typeof read !== 'string')\n if (wave.frame && !anyRead && reads.size === pages.length) {\n ledger = ledger.map((row) =>\n row.slot === AI_SITE_IMPORT_FRAME_SLOT && (row.status === 'pending' || row.status === 'running')\n ? { ...row, status: 'skipped', note: 'Not built: no page of this wave could be read.' }\n : row,\n )\n }\n const started = aiSiteImportWithBuilds(aiSiteImportWaveStarted(state, wave.index, nowIso, reads))\n const running = started.waves.find((entry) => entry.index === wave.index) as AiSiteImportWave\n return closing(started, ledger, running, unspent({ items: ledger }))\n }\n\n const wave = work.wave\n\n // ── 2b. The rest of a wave's read, where the clock cut it short ──\n if (work.kind === 'read') {\n const crawled = await crawl(\n {\n domain,\n maxPages: work.pages.length,\n only: work.pages.map((page) => page.url),\n timeBudgetMs: AI_SITE_IMPORT_WAVE_READ_MS,\n ...(signal ? { signal } : {}),\n },\n deps.crawlSeams,\n )\n if (crawled.stoppedBy === 'robots-unreachable') return unspent({ review: waveReview(AI_SITE_IMPORT_COPY.robots(domain)) })\n const reads = siteImportWaveReads(work.pages, crawled, nowIso, { cutShort: crawled.stoppedBy === 'time' })\n const ledger = withLeftOutRows(items, reads)\n return closing(aiSiteImportWithBuilds(aiSiteImportPagesRead(state, reads)), ledger, wave, unspent({ items: ledger }))\n }\n\n // ── 3. The look, before anything of the first wave is built (AGL-4084): no model ──\n const firstWave = state.waves[0]?.index === wave.index\n if (firstWave && !state.look && state.home && (work.kind === 'frame' || work.kind === 'images' || work.kind === 'page')) {\n const look = await runLook(\n {\n firestore,\n hostId,\n orgId: job.orgId,\n uid: job.createdBy,\n jobId: job.$id,\n domain,\n home: state.home,\n at: nowIso,\n ...(signal ? { signal } : {}),\n },\n {\n ingest: ingestOf(),\n ...(deps.crawlSeams?.fetch ? { fetch: deps.crawlSeams.fetch } : {}),\n ...(deps.crawlSeams?.headersFor ? { headersFor: deps.crawlSeams.headersFor } : {}),\n ...deps.lookDeps,\n },\n )\n return unspent({ siteImport: { ...state, look }, continue: true })\n }\n\n // ── 4. The header and footer ──\n if (work.kind === 'frame') {\n const runner = runnerFor('layout')\n if (!runner) {\n const item: AiJobItemOutcome = { slot: AI_SITE_IMPORT_FRAME_SLOT, status: 'skipped', note: AI_SITE_IMPORT_COPY.frameUnavailable }\n return closing(state, aiApplyJobItemRecord(items, item, 0, now), wave, unspent({ item }))\n }\n const derived = aiSiteImportFrameJob(job, state, wave, items)\n return runUnit(AI_SITE_IMPORT_FRAME_SLOT, runner, derived, state, null)\n }\n\n // ── 4a. A page's photos ──\n if (work.kind === 'images') {\n const photos = signal?.aborted\n ? { brought: 0, reused: 0, skipped: work.page.read?.images.length ?? 0, assets: [] }\n : await bringInSiteImportPhotos(\n {\n hostId,\n uid: job.createdBy,\n domain,\n images: work.page.read?.images ?? [],\n deadlineAt: clock() + AI_SITE_IMPORT_PHOTOS_MS,\n ...(signal ? { signal } : {}),\n },\n { ingest: ingestOf(), ...(deps.fetchImage ? { fetch: deps.fetchImage } : {}) },\n )\n return unspent({\n item: { slot: work.page.slot, status: 'running' },\n siteImport: aiSiteImportPhotosIn(state, work.page.slot, photos),\n continue: true,\n })\n }\n\n // ── 4b. The page ──\n if (work.kind === 'page') {\n const runner = runnerFor('page')\n if (!runner) {\n const item: AiJobItemOutcome = {\n slot: work.page.slot,\n status: 'failed',\n failure: { ours: true, reason: 'unavailable', message: AI_SITE_IMPORT_COPY.pageUnavailable },\n }\n return closing(state, aiApplyJobItemRecord(items, item, 0, now), wave, unspent({ item }))\n }\n return runUnit(work.page.slot, runner, aiSiteImportPageJob(job, state, work.page, items), state, work.page)\n }\n\n // ── 5. Close the wave ──\n return closing(state, items, wave, unspent())\n\n /** One delegated pass: the unit's spend is the pass's, what it came to is its row. */\n async function runUnit(\n slot: string,\n runner: AiJobStepRunner,\n derived: AiJob,\n current: AiSiteImportState,\n page: AiSiteImportPage | null,\n ): Promise<AiJobStepOutcome> {\n let outcome: AiJobStepOutcome\n try {\n outcome = await runner({ ...context, job: derived })\n } catch (error) {\n // A provider that will answer later, a budget that ended, a cancel: the machine's.\n if (aiUnitErrorRetryable(error) || (signal?.aborted ?? false)) throw error\n console.error('ai site import unit threw', { orgId: job.orgId, jobId: job.$id, slot, error })\n const item: AiJobItemOutcome = {\n slot,\n status: 'failed',\n failure: { ours: true, reason: 'provider', message: AI_SITE_IMPORT_COPY.pageNotWritten },\n }\n return closing(current, aiApplyJobItemRecord(items, item, 0, now), wave, unspent({ item }))\n }\n const spent = aiUnitSpend(outcome)\n const stopped = aiUnitFailure(slot, outcome)\n if (stopped?.status === 'running') return { ...spent, outputs: [], item: stopped, siteImport: current, continue: true }\n let item: AiJobItemOutcome\n if (stopped) {\n item = stopped\n } else if (page && derived.plan) {\n // A page counts as in only when its sections are in it (AGL-3596).\n const screen = derived.plan.screens[0]\n const written = await pageWritten(firestore, {\n hostId: hostId as string,\n unitJobId: derived.$id,\n screen,\n draftId: page.draftId,\n layoutLanguage: true,\n })\n item = written\n ? { slot, status: 'succeeded', outputs: spent.outputs.map((output) => output.id) }\n : { slot, status: 'failed', failure: { ours: true, reason: 'step-failure', message: AI_SITE_IMPORT_COPY.pageNotWritten } }\n } else {\n item = { slot, status: 'succeeded', outputs: spent.outputs.map((output) => output.id) }\n }\n // What came through, for the row that says it beside what the old page had (AGL-4084).\n let withBrought = current\n if (page && item.status === 'succeeded') {\n const words = await draftWordsOf(firestore, hostId as string, page.draftId).catch(() => null)\n if (words !== null) withBrought = { ...current, pages: current.pages.map((entry) => (entry.slot === slot ? { ...entry, brought: { words } } : entry)) }\n }\n const settledState = page ? aiSiteImportPageSettled(withBrought, slot) : withBrought\n return closing(\n settledState,\n aiApplyJobItemRecord(items, item, 0, now),\n wave,\n { ...spent, outputs: item.status === 'succeeded' ? spent.outputs : [], item },\n )\n }\n }\n}\n\n/** The home page's menu, as same-site paths in its order. */\nexport function siteImportMenu(crawled: Pick<SiteImportInventory, 'pages' | 'origins'>): string[] {\n const home = crawled.pages.find((page) => page.foundBy === 'home') ?? crawled.pages[0]\n const paths: string[] = []\n for (const link of home?.navLinks ?? []) {\n try {\n const url = new URL(link.url)\n if (!crawled.origins.includes(url.origin)) continue\n const path = url.pathname.replace(/\\/+$/, '') || '/'\n if (!paths.includes(path)) paths.push(path)\n } catch {\n // A menu entry that is not an address names no page.\n }\n }\n return paths\n}\n\n/**\n * What a wave's read came to for each page: the page read again, or why it\n * is left out now. Matched by address; a page the site sent to another of its\n * own addresses is matched in the order the wave asked for it.\n */\nexport function siteImportWaveReads(\n asked: readonly AiSiteImportPage[],\n crawled: Pick<SiteImportInventory, 'pages' | 'skipped'>,\n at: string,\n options: {\n /** The read's clock ran out: a page it did not reach is left for the next pass, not left out. */\n cutShort?: boolean\n } = {},\n): Map<string, AiSiteImportPageRead | AiSiteImportLeftOutReason> {\n const reads = new Map<string, AiSiteImportPageRead | AiSiteImportLeftOutReason>()\n const pathKey = (url: string) => {\n try {\n const parsed = new URL(url)\n return `${parsed.pathname.replace(/\\/+$/, '') || '/'}${parsed.search}`\n } catch {\n return url\n }\n }\n const pages = new Map(crawled.pages.map((page) => [pathKey(page.url), page]))\n const skipped = new Map(crawled.skipped.map((entry) => [pathKey(entry.url), entry]))\n const unmatched = [...crawled.pages]\n const take = (page: (typeof crawled.pages)[number]) => {\n const index = unmatched.indexOf(page)\n if (index !== -1) unmatched.splice(index, 1)\n }\n const pending: AiSiteImportPage[] = []\n for (const page of asked) {\n const found = pages.get(pathKey(page.url))\n if (found) {\n take(found)\n reads.set(page.slot, siteImportReadOrEmpty(found, at))\n continue\n }\n const left = skipped.get(pathKey(page.url))\n if (left) {\n reads.set(page.slot, siteImportLeftOutReason(left.reason, left.status))\n continue\n }\n pending.push(page)\n }\n for (const page of pending) {\n const found = unmatched.shift()\n if (found) reads.set(page.slot, siteImportReadOrEmpty(found, at))\n else if (!options.cutShort) reads.set(page.slot, 'unreadable')\n }\n return reads\n}\n\nfunction siteImportReadOrEmpty(page: SiteImportInventory['pages'][number], at: string): AiSiteImportPageRead | 'empty' {\n if (siteImportPageWords(page) < AI_SITE_IMPORT_MIN_WORDS && !page.images.length) return 'empty'\n return siteImportPageRead(page, at)\n}\n\n/**\n * \"Start every remaining wave\" (AGL-4083, wired by AGL-4084), as the resume\n * door writes it onto an import waiting to start its next wave: every\n * remaining wave starts after the one before it closes, with no review\n * between them, and the person's one start is the one the day's limit\n * counts. `null` when the job is not an import waiting for a wave.\n */\nexport function aiSiteImportStartAllUpdate(\n job: Pick<AiJob, 'kind' | 'status' | 'review' | 'siteImport'>,\n): { 'siteImport.autoContinue': true; 'siteImport.autoContinueFrom': number } | null {\n if (job.kind !== 'import' || job.status !== 'needs_review' || job.review?.reason !== 'wave') return null\n const next = job.siteImport?.waves.find((wave) => wave.status === 'waiting')\n if (!next) return null\n return { 'siteImport.autoContinue': true, 'siteImport.autoContinueFrom': next.index }\n}\n\n/*------------------------------------------\n * Admission, and registration\n *-----------------------------------------*/\n\nexport interface AiSiteImportAdmissionDeps {\n releaseFlagOn?: (orgId: string) => Promise<boolean>\n ownership?: (orgId: string, domain: string) => Promise<AiSiteImportOwnership | null>\n /** \"Bring a site in\" (`ai.import`, AGL-4047) for this member; specs hand in a double. */\n holdsSiteImport?: (uid: string, orgId: string) => Promise<boolean>\n}\n\n/**\n * What an import asks before it exists and before each wave (AGL-3976): the\n * release flag, a site to bring it into, a paid plan, the owner or an admin,\n * and a CURRENT proof that the workspace owns the domain. Nothing is spent on\n * a refusal, and the day's limit is the step's to count, once a wave runs.\n */\nexport function createAiSiteImportAdmission(deps: AiSiteImportAdmissionDeps = {}): AiJobAdmission {\n const flagOn = deps.releaseFlagOn ?? ((orgId: string) => isServerReleaseFlagOnForOrg(SITE_IMPORT_RELEASE_FLAG, orgId))\n const ownershipOf = deps.ownership ?? readOwnership\n const holdsSiteImport =\n deps.holdsSiteImport ??\n (async (uid: string, orgId: string) => {\n const member = (await getOrgForUser(uid, orgId))?.member ?? null\n return Boolean(member) && (await memberHasOrgPermission(orgId, member, 'ai.import'))\n })\n return async (context) => {\n if (!(await flagOn(context.orgId))) return { status: 404, error: 'Not found' }\n if (!context.hostId && !context.siteToCome) return { status: 400, error: AI_SITE_IMPORT_COPY.noSite }\n if (resolveEffectivePlan(context.org as never) === 'free') return { status: 403, error: AI_SITE_IMPORT_COPY.plan }\n // \"Bring a site in\" (`ai.import`, AGL-4047), whose default is the owner\n // and admin this asked for.\n if (!context.uid || !(await holdsSiteImport(context.uid, context.orgId))) {\n return { status: 403, error: AI_SITE_IMPORT_COPY.role }\n }\n const { domain, error } = normalizeOwnershipDomain(String(context.inputs[AI_SITE_IMPORT_DOMAIN_INPUT] ?? ''))\n if (!domain) return { status: 400, error: error ?? AI_SITE_IMPORT_COPY.badDomain }\n const ownership = await ownershipOf(context.orgId, domain)\n if (!ownership?.current) return { status: 403, error: AI_SITE_IMPORT_COPY.ownership(domain) }\n return null\n }\n}\n\n/**\n * The import kind's registrations (AGL-3976), by a call from `server.ts`,\n * never by an import: its runner with each pass's least time, its pass bound\n * and its admission.\n */\nexport function registerAiSiteImportJob(deps: AiSiteImportStepDeps = {}): void {\n const runnerFor = deps.runnerFor ?? aiJobStepRunnerFor\n registerAiJobStep('import', createAiJobImportStep(deps), {\n minimumMs: AI_JOB_PAGE_STEP_MINIMUM_MS,\n minimumMsFor: (job) => aiSiteImportRunMinimumMs(job, runnerFor),\n })\n registerAiJobStepPasses('import', AI_SITE_IMPORT_MAX_PASSES)\n registerAiJobAdmission('import', createAiSiteImportAdmission())\n}\n"],"names":["resolveEffectivePlan","createResourceUid","pluginMediaIngest","listDomainOwnershipClaims","normalizeOwnershipDomain","getOrgForUser","memberHasOrgPermission","consumeRateLimit","isServerReleaseFlagOnForOrg","AI_SITE_IMPORT_DOMAIN_INPUT","AI_SITE_IMPORT_FRAME_SLOT","AI_SITE_IMPORT_LABEL_MAX_CHARS","AI_SITE_IMPORT_LEFT_OUT_COPY","AI_SITE_IMPORT_MAX_PAGES","AI_SITE_IMPORT_MIN_WORDS","AI_SITE_IMPORT_WAVE_PAGES","aiSiteImportFrameIsRead","aiSiteImportInventory","aiSiteImportItemOpen","aiSiteImportLedger","aiSiteImportNextWork","aiSiteImportPageBuild","aiSiteImportPageSettled","aiSiteImportPagesRead","aiSiteImportPhotosIn","aiSiteImportReadStops","aiSiteImportReadVerdict","aiSiteImportReadVerdictMessage","aiSiteImportReadVerdictReason","aiSiteImportWaveClosed","aiSiteImportWaveMessage","aiSiteImportWaveStarted","aiModelForStep","SITE_IMPORT_RELEASE_FLAG","crawlSiteForImport","siteImportOrigins","bringInSiteImportPhotos","siteImportHeaderBrand","siteImportLabel","siteImportLeftOutReason","siteImportListedPage","siteImportPageRead","siteImportPageWords","siteImportSiteFacts","siteImportSiteName","aiSiteKindFor","AI_LAYOUT_SITE_BRAND_INPUT","AI_LAYOUT_SITE_FACTS_INPUT","AI_LAYOUT_SITE_FRAME_INPUT","aiLayoutTelHref","aiHexOklch","AI_LAYOUT_IMPORTED_SECTIONS_INPUT","aiSiteImportSectionNames","aiRunSiteImportLook","aiPublishImportedWave","aiUnitErrorRetryable","aiUnitFailure","aiUnitSpend","registerAiJobAdmission","AI_JOB_STEP_OVERHEAD_MS","readAiDraftNodes","readAiScreenRoom","aiUnspentOutcome","AI_LAYOUT_PAGE_PHOTOS_INPUT","AI_LAYOUT_SITE_PAGES_INPUT","AI_LAYOUT_SITE_PAGES_MAX","AI_JOB_PAGE_STEP_MINIMUM_MS","AI_LAYOUT_IMPORTED_PAGE_INPUT","AI_LAYOUT_LANGUAGE_INPUT","aiSitePageWritten","AI_STOCK_PHOTO_PAGES_INPUT","AI_JOB_BRIEF_MAX_CHARS","aiApplyJobItemRecord","aiJobStepRunMinimumMs","aiJobStepRunnerFor","registerAiJobStep","registerAiJobStepPasses","SITE_IMPORT_WAVES_PER_ORG_PER_DAY","DAY_MS","siteImportRateKey","orgId","AI_SITE_IMPORT_READ_MS","AI_SITE_IMPORT_WAVE_READ_MS","AI_SITE_IMPORT_PHOTOS_MS","OWN_READS_MS","AI_SITE_IMPORT_PASS_MINIMUM_MS","read","wave","photos","AI_SITE_IMPORT_MAX_PASSES","AI_SITE_IMPORT_COPY","noSite","badDomain","ownership","domain","limit","robots","nothing","blocked","unavailable","frameUnavailable","pageUnavailable","pageNotWritten","plan","role","readOwnership","claims","claim","find","entry","current","method","provenMethod","provenAt","detail","provenDetail","readSiteName","firestore","hostId","host","collection","doc","get","name","trim","aiSiteImportDomainOf","job","String","inputs","pathOf","slug","unitPlan","input","reuse","create","screens","labels","status","proposedAt","createdAt","confirmedAt","confirmedBy","createdBy","delivered","items","slot","some","row","aiSiteImportLinkedPages","state","rows","Map","map","pages","filter","page","refused","id","draftId","label","title","slice","aiSiteImportBuildOf","group","aiSiteImportBrandName","given","own","key","text","toLowerCase","replace","aiSiteImportDesignInputs","look","home","kind","siteName","description","siteKind","seed","siteStyle","style","headerAlign","rhythm","motion","aiSiteImportFrameLinkTo","origins","Set","path","href","raw","test","url","URL","protocol","has","decodeURIComponent","pathname","toString","aiSiteImportHeaderGround","background","hex","L","near","other","within","them","a","C","Math","cos","h","PI","b","sin","hypot","buttonFill","aiSiteImportFrameSource","footer","nav","to","index","link","target","present","value","iconPath","viewBox","column","length","ctas","cta","header","columns","heading","links","social","network","address","phone","email","copyright","aiSiteImportFrameJob","frame","$id","creation","why","duplicateOf","fields","logo","withLogo","brand","alt","aspect","width","height","round","src","source","steps","outputs","siteImport","originJobId","businessName","lines","facts","brief","aiSiteImportDocumentFor","blocks","build","assets","layout","aiSiteImportPageJob","names","sections","uses","screen","template","seoTitle","meta","seoDescription","record","others","aiSiteImportHomeOf","crawled","foundBy","chars","block","inline","line","includes","push","organization","telephone","ogImage","type","emails","phones","aiSiteImportRunMinimumMs","runnerFor","work","waveReview","message","reason","findings","withLeftOutRows","reads","note","aiSiteImportWithBuilds","mainWords","words","aiSiteImportShownWords","nodes","node","Object","values","props","match","readDraftWords","stored","aiSiteImportPreviewMessage","published","toLocaleString","lead","next","waves","waveSettled","slots","every","createAiJobImportStep","deps","crawl","ownershipOf","rateLimit","flagOn","releaseFlagOn","ingestOf","ingest","readRoom","siteNameOf","pageWritten","mintId","clock","Date","now","runLook","publishWave","draftWordsOf","draftWords","context","signal","model","unspent","rest","failure","nowIso","toISOString","closing","ledger","outcome","closed","continue","sitePublish","error","console","jobId","waiting","review","more","autoContinue","gate","counted","window","windowMs","allowed","passed","room","org","left","max","used","maxPages","min","timeBudgetMs","shallowFirst","crawlSeams","stoppedBy","skipped","verdict","inventory","readAt","menu","siteImportMenu","skippedOverflow","pageLimit","existingPages","region","planned","autoContinueFrom","Number","POSITIVE_INFINITY","toRead","set","only","siteImportWaveReads","cutShort","anyRead","size","started","running","firstWave","uid","at","fetch","headersFor","lookDeps","runner","item","derived","runUnit","aborted","brought","reused","images","deadlineAt","fetchImage","ours","spent","stopped","written","unitJobId","layoutLanguage","output","withBrought","catch","settledState","paths","navLinks","origin","asked","options","pathKey","parsed","search","unmatched","take","indexOf","splice","pending","found","siteImportReadOrEmpty","shift","aiSiteImportStartAllUpdate","createAiSiteImportAdmission","holdsSiteImport","member","Boolean","siteToCome","registerAiSiteImportJob","minimumMs","minimumMsFor"],"mappings":"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"}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
import type { NodesMap } from '@aglyn/aglyn/types/nodes';
|
|
18
18
|
import { type AiLayoutDesign } from '../layout-language/ai-layout-design';
|
|
19
19
|
import { type AiLayoutFrameBrand } from '../layout-language/ai-layout-frame';
|
|
20
|
+
import { type AiLayoutFrameSource } from '../layout-language/ai-layout-frame-source';
|
|
20
21
|
import type { AiLayoutPage, AiLayoutTargets } from '../layout-language/ai-layout-links';
|
|
21
22
|
import type { AiJob, AiJobPlan } from '../model/ai-jobs.types';
|
|
22
23
|
import { type AiSiteInventory } from '../model/ai-site-inventory';
|
|
@@ -54,6 +55,16 @@ export declare const AI_JOB_LAYOUT_LANGUAGE_INSTRUCTIONS: readonly AiSystemBlock
|
|
|
54
55
|
*/
|
|
55
56
|
export declare const AI_LAYOUT_SITE_BRAND_INPUT = "siteBrand";
|
|
56
57
|
export declare const AI_LAYOUT_SITE_FACTS_INPUT = "siteFacts";
|
|
58
|
+
/**
|
|
59
|
+
* The unit input a site brought in gives its header and footer where the
|
|
60
|
+
* reader found the source's menu (AGL-4108): its menu, its buttons and its
|
|
61
|
+
* footer, every link resolved to a page of the site or the source's own
|
|
62
|
+
* address (`AiLayoutFrameSource`). With it the frame is drawn by code and no
|
|
63
|
+
* model is asked; read defensively, `null` on every other job.
|
|
64
|
+
*/
|
|
65
|
+
export declare const AI_LAYOUT_SITE_FRAME_INPUT = "siteFrame";
|
|
66
|
+
/** A job's source frame (AGL-4108), held to what a link and a label may carry; `null` where it has none. */
|
|
67
|
+
export declare function aiLayoutSiteFrameOf(inputs: Readonly<Record<string, unknown>> | null | undefined): AiLayoutFrameSource | null;
|
|
57
68
|
/** The most characters of a site's own header and footer words a frame is shown. */
|
|
58
69
|
export declare const AI_LAYOUT_SITE_FACTS_MAX_CHARS = 4000;
|
|
59
70
|
export interface AiLayoutSiteFacts {
|
|
@@ -101,8 +112,8 @@ export interface AiLayoutFrameBuilt {
|
|
|
101
112
|
/** What the last answer's gaps took out of the frame (`ai-layout-gaps.ts`). */
|
|
102
113
|
dropped: string[];
|
|
103
114
|
}
|
|
104
|
-
/**
|
|
105
|
-
export
|
|
115
|
+
/** What a frame is built with: the site, its pages and links, its look, and the layout door's own checks. */
|
|
116
|
+
export interface AiLayoutFrameInput {
|
|
106
117
|
/** The header arrangement the site's look chose (AGL-3660); the answer's otherwise. */
|
|
107
118
|
headerAlign?: 'start' | 'center';
|
|
108
119
|
siteName: string;
|
|
@@ -118,6 +129,19 @@ export declare function aiLayoutFrameCheck(input: {
|
|
|
118
129
|
language?: string;
|
|
119
130
|
/** The header's brand as a site brought in draws it (AGL-4084). */
|
|
120
131
|
brand?: AiLayoutFrameBrand | null;
|
|
121
|
-
|
|
132
|
+
/** A site brought in's own header and footer (AGL-4108), drawn in place of the design's. */
|
|
133
|
+
source?: AiLayoutFrameSource | null;
|
|
134
|
+
}
|
|
135
|
+
/** The check a frame answer is held to: read, compiled, stored and checked as a layout, with the layout door's own checks. */
|
|
136
|
+
export declare function aiLayoutFrameCheck(input: AiLayoutFrameInput): AiGenerationCheck<AiLayoutFrameBuilt>;
|
|
137
|
+
/**
|
|
138
|
+
* A site brought in's header and footer as its source builds them
|
|
139
|
+
* (AGL-4108), with no model: compiled, stored and checked as a layout, held
|
|
140
|
+
* to every check an answer is. `value` is `null` with the violations where it
|
|
141
|
+
* does not pass, and the frame is then designed by the model instead.
|
|
142
|
+
*/
|
|
143
|
+
export declare function aiLayoutSourceFrameBuild(input: AiLayoutFrameInput & {
|
|
144
|
+
source: AiLayoutFrameSource;
|
|
145
|
+
}): ReturnType<AiGenerationCheck<AiLayoutFrameBuilt>>;
|
|
122
146
|
/** What a frame's links resolve against: the site's pages and its form, as a page's do. */
|
|
123
147
|
export declare function aiLayoutFrameTargets(job: Pick<AiJob, 'brief' | 'inputs'>, inventory: AiSiteInventory | null): AiLayoutTargets;
|