@aglyn/plugins-ai 1.0.0-beta.236 → 1.0.0-beta.238
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +17 -17
- package/src/lib/components/ai-credits-prompt.component.d.ts +44 -0
- package/src/lib/components/ai-credits-prompt.component.js +117 -0
- package/src/lib/components/ai-credits-prompt.component.js.map +1 -0
- package/src/lib/components/ai-job-cancel.component.d.ts +38 -0
- package/src/lib/components/ai-job-cancel.component.js +156 -0
- package/src/lib/components/ai-job-cancel.component.js.map +1 -0
- package/src/lib/components/ai-job-plan.component.d.ts +5 -4
- package/src/lib/components/ai-job-plan.component.js +48 -12
- package/src/lib/components/ai-job-plan.component.js.map +1 -1
- package/src/lib/components/ai-job-requests.d.ts +10 -0
- package/src/lib/components/ai-job-requests.js +12 -4
- package/src/lib/components/ai-job-requests.js.map +1 -1
- package/src/lib/components/ai-jobs-list-page.component.js +141 -72
- package/src/lib/components/ai-jobs-list-page.component.js.map +1 -1
- package/src/lib/components/ai-site-build-page.component.js +48 -9
- package/src/lib/components/ai-site-build-page.component.js.map +1 -1
- package/src/lib/components/ai-site-start-card.component.js +68 -22
- package/src/lib/components/ai-site-start-card.component.js.map +1 -1
- package/src/lib/components/ai-usage-strip.component.d.ts +19 -2
- package/src/lib/components/ai-usage-strip.component.js +40 -9
- package/src/lib/components/ai-usage-strip.component.js.map +1 -1
- package/src/lib/components/assist-build-card.component.d.ts +3 -1
- package/src/lib/components/assist-build-card.component.js +58 -7
- package/src/lib/components/assist-build-card.component.js.map +1 -1
- package/src/lib/components/assist-jobs-drawer.component.js +66 -22
- package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
- package/src/lib/components/assist-panel.component.js +89 -52
- package/src/lib/components/assist-panel.component.js.map +1 -1
- package/src/lib/jobs/ai-job-admission.d.ts +22 -2
- package/src/lib/jobs/ai-job-admission.js.map +1 -1
- package/src/lib/jobs/ai-job-build-step.d.ts +24 -11
- package/src/lib/jobs/ai-job-build-step.js +54 -35
- package/src/lib/jobs/ai-job-build-step.js.map +1 -1
- package/src/lib/jobs/ai-job-cancel.d.ts +71 -0
- package/src/lib/jobs/ai-job-cancel.js +102 -0
- package/src/lib/jobs/ai-job-cancel.js.map +1 -0
- package/src/lib/jobs/ai-job-component-step.js +4 -1
- package/src/lib/jobs/ai-job-component-step.js.map +1 -1
- package/src/lib/jobs/ai-job-drafts.js +2 -0
- package/src/lib/jobs/ai-job-drafts.js.map +1 -1
- package/src/lib/jobs/ai-job-form-step.js +4 -1
- package/src/lib/jobs/ai-job-form-step.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-language.d.ts +2 -0
- package/src/lib/jobs/ai-job-layout-language.js +13 -1
- package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-step.js +6 -1
- package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
- package/src/lib/jobs/ai-job-page-language.js +12 -0
- package/src/lib/jobs/ai-job-page-language.js.map +1 -1
- package/src/lib/jobs/ai-job-page-step.d.ts +13 -0
- package/src/lib/jobs/ai-job-page-step.js +46 -4
- package/src/lib/jobs/ai-job-page-step.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-step.d.ts +42 -0
- package/src/lib/jobs/ai-job-plan-step.js +118 -18
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-content.d.ts +49 -3
- package/src/lib/jobs/ai-job-site-content.js +196 -37
- package/src/lib/jobs/ai-job-site-content.js.map +1 -1
- package/src/lib/jobs/ai-job-site-step.js +49 -16
- package/src/lib/jobs/ai-job-site-step.js.map +1 -1
- package/src/lib/jobs/ai-job-template-step.js +4 -1
- package/src/lib/jobs/ai-job-template-step.js.map +1 -1
- package/src/lib/jobs/ai-job-text-step.d.ts +8 -0
- package/src/lib/jobs/ai-job-text-step.js.map +1 -1
- package/src/lib/jobs/ai-jobs.d.ts +55 -13
- package/src/lib/jobs/ai-jobs.js +213 -41
- package/src/lib/jobs/ai-jobs.js.map +1 -1
- package/src/lib/jobs/ai-layout-stock-photos.d.ts +194 -34
- package/src/lib/jobs/ai-layout-stock-photos.js +861 -146
- package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
- package/src/lib/jobs/fixtures/ai-ceramics-portfolio-site-plan.d.ts +30 -0
- package/src/lib/jobs/fixtures/ai-ceramics-portfolio-site-plan.js +220 -0
- package/src/lib/jobs/fixtures/ai-ceramics-portfolio-site-plan.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-pixabay-recordings.d.ts +27 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-pixabay-recordings.js +151 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-pixabay-recordings.js.map +1 -0
- package/src/lib/layout-language/ai-layout-compiler.d.ts +33 -0
- package/src/lib/layout-language/ai-layout-compiler.js +381 -18
- package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
- package/src/lib/layout-language/ai-layout-design.d.ts +6 -3
- package/src/lib/layout-language/ai-layout-design.js +5 -3
- package/src/lib/layout-language/ai-layout-design.js.map +1 -1
- package/src/lib/layout-language/ai-layout-frame.d.ts +12 -0
- package/src/lib/layout-language/ai-layout-frame.js +58 -3
- package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
- package/src/lib/layout-language/ai-layout-gaps.js +3 -1
- package/src/lib/layout-language/ai-layout-gaps.js.map +1 -1
- package/src/lib/layout-language/ai-layout-language.js +1 -1
- package/src/lib/layout-language/ai-layout-language.js.map +1 -1
- package/src/lib/layout-language/ai-layout-listings.d.ts +49 -1
- package/src/lib/layout-language/ai-layout-listings.js +117 -47
- package/src/lib/layout-language/ai-layout-listings.js.map +1 -1
- package/src/lib/layout-language/ai-layout-pictures.d.ts +10 -1
- package/src/lib/layout-language/ai-layout-pictures.js +5 -2
- package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
- package/src/lib/layout-language/ai-layout-storefront.d.ts +82 -0
- package/src/lib/layout-language/ai-layout-storefront.js +223 -0
- package/src/lib/layout-language/ai-layout-storefront.js.map +1 -0
- package/src/lib/model/ai-build-job.d.ts +39 -0
- package/src/lib/model/ai-build-job.js +100 -1
- package/src/lib/model/ai-build-job.js.map +1 -1
- package/src/lib/model/ai-build-progress.d.ts +8 -0
- package/src/lib/model/ai-build-progress.js +35 -0
- package/src/lib/model/ai-build-progress.js.map +1 -1
- package/src/lib/model/ai-credit-estimate.d.ts +249 -0
- package/src/lib/model/ai-credit-estimate.js +278 -0
- package/src/lib/model/ai-credit-estimate.js.map +1 -0
- package/src/lib/model/ai-job-cancel-copy.d.ts +44 -0
- package/src/lib/model/ai-job-cancel-copy.js +53 -0
- package/src/lib/model/ai-job-cancel-copy.js.map +1 -0
- package/src/lib/model/ai-job-failure-copy.d.ts +4 -1
- package/src/lib/model/ai-job-failure-copy.js +8 -3
- package/src/lib/model/ai-job-failure-copy.js.map +1 -1
- package/src/lib/model/ai-jobs.types.d.ts +35 -0
- package/src/lib/model/ai-jobs.types.js.map +1 -1
- package/src/lib/model/ai-site-build-progress.js +7 -4
- package/src/lib/model/ai-site-build-progress.js.map +1 -1
- package/src/lib/model/ai-site-job.d.ts +76 -22
- package/src/lib/model/ai-site-job.js +125 -23
- package/src/lib/model/ai-site-job.js.map +1 -1
- package/src/lib/model/ai-site-kinds.d.ts +4 -1
- package/src/lib/model/ai-site-kinds.js +35 -7
- package/src/lib/model/ai-site-kinds.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.d.ts +37 -1
- package/src/lib/runtime/ai-doctrine-validators.js +161 -7
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-doctrine.js +4 -3
- package/src/lib/runtime/ai-doctrine.js.map +1 -1
- package/src/lib/runtime/ai-node-tree.d.ts +11 -0
- package/src/lib/runtime/ai-node-tree.js +26 -0
- package/src/lib/runtime/ai-node-tree.js.map +1 -1
- package/src/lib/runtime/ai-palette.generated.js +592 -14
- package/src/lib/runtime/ai-palette.generated.js.map +1 -1
- package/src/lib/server/ai-jobs-cancel.d.ts +13 -5
- package/src/lib/server/ai-jobs-cancel.js +27 -9
- package/src/lib/server/ai-jobs-cancel.js.map +1 -1
- package/src/lib/server/ai-jobs-gate.d.ts +12 -2
- package/src/lib/server/ai-jobs-gate.js +20 -9
- package/src/lib/server/ai-jobs-gate.js.map +1 -1
- package/src/lib/server/ai-jobs-resume.js +93 -35
- package/src/lib/server/ai-jobs-resume.js.map +1 -1
- package/src/lib/server/ai-jobs-route.js +45 -4
- package/src/lib/server/ai-jobs-route.js.map +1 -1
- package/src/lib/server/assist-chat.js +4 -1
- package/src/lib/server/assist-chat.js.map +1 -1
- package/src/lib/server/assist-edit.js +3 -1
- package/src/lib/server/assist-edit.js.map +1 -1
- package/src/lib/server/assist-music.d.ts +36 -0
- package/src/lib/server/assist-music.js +36 -0
- package/src/lib/server/assist-music.js.map +1 -0
- package/src/lib/server.js +6 -0
- package/src/lib/server.js.map +1 -1
- package/src/lib/usage/ai-usage-meter.d.ts +2 -1
- package/src/lib/usage/ai-usage-meter.js +17 -1
- package/src/lib/usage/ai-usage-meter.js.map +1 -1
- package/src/lib/usage/ai-usage-wire.d.ts +6 -0
- package/src/lib/usage/ai-usage-wire.js.map +1 -1
- package/src/lib/usage/assist-usage.d.ts +7 -0
- package/src/lib/usage/assist-usage.js +14 -4
- package/src/lib/usage/assist-usage.js.map +1 -1
- package/src/lib/usage/free-ai-credits-left.d.ts +7 -0
- package/src/lib/usage/free-ai-credits-left.js +4 -2
- package/src/lib/usage/free-ai-credits-left.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/model/ai-site-build-progress.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { aiJobConfirmingOwnPlan, aiJobKindNoun } from './ai-job-activity'\nimport { aiJobRefundCopy } from './ai-job-failure-copy'\nimport { aiBuildItemRows, aiBuildOpNoun, aiBuildOutcomeLine, aiSitePartialCopy } from './ai-build-progress'\nimport { AI_JOB_PAUSED_NEXT_COPY, aiJobPausedTitle } from './ai-job-notice'\nimport type { AiJobSummary } from './ai-jobs.types'\n\n/**\n * What the \"Building your site\" page shows of a site job (AGL-3594): one row\n * a stage — planning the pages, then each page — with its state, the state\n * the whole job is in, and the job's one price.\n *\n * Read off the job summary every surface already follows: the plan step's\n * status, the plan's pages, and the pages the build has reported as outputs.\n * A scaffold builds its units in plan order and reports each page when it is\n * written, so the pages written so far are the first pages of the plan.\n *\n * Pure: no React, no request. The page and its spec read the same rows.\n */\n\n/**\n * `paused` (AGL-3660): the row a job the meter paused stopped at — not\n * running, not failed, and carried on from by Resume.\n */\nexport type AiSiteBuildRowState = 'done' | 'active' | 'waiting' | 'failed' | 'skipped' | 'paused'\n\nexport interface AiSiteBuildRow {\n id: string\n label: string\n state: AiSiteBuildRowState\n /** What the person should know about this row (AGL-3616): a build item's failure, note or refund. */\n detail?: string | null\n /** What the row is doing while it is the active one, in a sentence. */\n hint?: string | null\n /** A page's planned sections, in order, so the person sees what is being written. */\n sections?: string[]\n /** The credits this row's work used, once it has finished; absent while it runs. */\n credits?: number\n /** When this row's work started, for the elapsed time beside the active row. */\n startedAt?: string | null\n}\n\n/** Where the whole job stands, as the page's header and actions read it. */\nexport type AiSiteBuildPhase = 'working' | 'done' | 'stopped' | 'failed' | 'canceled'\n\nexport function aiSiteBuildPhase(\n job: Pick<AiJobSummary, 'status'> & Partial<Pick<AiJobSummary, 'review' | 'autoConfirm' | 'updatedAt'>>,\n): AiSiteBuildPhase {\n // A guided start's plan parked for the instant its confirmation takes is\n // the build going on (AGL-3596), never a stop.\n if (aiJobConfirmingOwnPlan(job)) return 'working'\n switch (job.status) {\n case 'done':\n return 'done'\n case 'failed':\n return 'failed'\n case 'canceled':\n return 'canceled'\n case 'needs_review':\n case 'needs_input':\n return 'stopped'\n default:\n return 'working'\n }\n}\n\n/** The creations a scaffold builds before its pages, in its build order, and what each row says. */\nconst CREATION_ROWS: ReadonlyArray<{ kind: string; resource: string; label: (name: string) => string }> = [\n { kind: 'theme-change', resource: 'theme', label: () => AI_SITE_LOOK_ROW_LABEL },\n { kind: 'layout', resource: 'layout', label: (name) => `Building the header and footer: ${name}` },\n { kind: 'form', resource: 'form', label: (name) => `Building the form: ${name}` },\n]\n\n/**\n * One row a stage: planning, then each creation the plan builds before its\n * pages — the colors, the layout, the form — then each page (AGL-3596). A\n * scaffold builds them in that order and reports each as an output when it\n * is written, so the first row without its output is where the build is, and\n * where a failure stopped it: a layout that broke is the layout's row, never\n * the first page's.\n */\nexport function aiSiteBuildRows(\n job: Pick<AiJobSummary, 'status' | 'steps' | 'plan' | 'outputs' | 'review'> &\n Partial<Pick<AiJobSummary, 'items' | 'kind' | 'siteInputs' | 'sitePublish'>>,\n): AiSiteBuildRow[] {\n const rows = aiSiteBuildRowsOf(job)\n return job.status === 'needs_input' ? aiPausedRows(rows) : rows\n}\n\n/**\n * A job the meter paused (AGL-3660) shows no spinner: the row it stopped at —\n * one still marked running, else the first not yet built — reads `paused`,\n * with no running clock and no \"building now\" hint, and every row after it\n * keeps waiting.\n */\nfunction aiPausedRows(rows: AiSiteBuildRow[]): AiSiteBuildRow[] {\n const at = rows.findIndex((row) => row.state === 'active' || row.state === 'paused')\n const index = at >= 0 ? at : rows.findIndex((row) => row.state === 'waiting')\n return rows.map((row, position) => {\n if (row.state === 'active' && position !== index) return { ...row, state: 'waiting', hint: null, startedAt: null }\n if (position !== index) return row\n return { ...row, state: 'paused', hint: null, startedAt: null }\n })\n}\n\nfunction aiSiteBuildRowsOf(\n job: Pick<AiJobSummary, 'status' | 'steps' | 'plan' | 'outputs' | 'review'> &\n Partial<Pick<AiJobSummary, 'items' | 'kind' | 'siteInputs' | 'sitePublish'>>,\n): AiSiteBuildRow[] {\n const phase = aiSiteBuildPhase(job)\n // A build is read off its item ledger (AGL-3616): one row an item, each with\n // its own state and what became of its credits.\n if (job.items?.length) {\n const site = job.kind !== 'build'\n const pages = (job.items ?? []).filter((row) => row.op === 'page')\n // The plan keeps the credits it used once the items take over the page.\n const planStep = job.steps.find((step) => step.name === 'plan')\n return [\n {\n id: 'plan',\n label: site ? 'Planning your pages' : 'Planning what to build',\n state: 'done',\n ...(planStep ? { credits: Math.max(0, Math.floor(planStep.creditsSpent ?? 0)) } : {}),\n },\n ...aiBuildItemRows(job).map((row, index) => {\n const ledger = (job.items ?? [])[index]\n // A site keeps the scaffold's own words for each stage (AGL-3596).\n const label =\n !site || !ledger\n ? row.label\n : ledger.op === 'theme'\n ? AI_SITE_LOOK_ROW_LABEL\n : ledger.op === 'layout'\n ? `Building the header and footer: ${ledger.label}`\n : ledger.op === 'form'\n ? `Building the form: ${ledger.label}`\n : ledger.op === 'page'\n ? `Writing page ${pages.indexOf(ledger) + 1} of ${pages.length}: ${ledger.label}`\n : ledger.op === 'email'\n ? 'Writing your welcome email'\n : row.label\n const screen = ledger?.op === 'page' ? aiPlanScreenFor(job.plan, ledger.label, pages.indexOf(ledger)) : null\n const finished = row.state === 'done' || row.state === 'failed'\n const net = ledger ? Math.max(0, Math.floor((ledger.creditsSpent ?? 0) - (ledger.creditsRefunded ?? 0))) : 0\n return {\n id: row.slot,\n label,\n state: row.state,\n // A part that failed while the rest is still being built says the\n // build goes on (AGL-3596): read alone, it looked like the site had.\n detail:\n row.state === 'failed' && phase === 'working'\n ? [row.detail, site ? 'The rest of your site keeps building.' : 'The rest keeps building.'].filter(Boolean).join(' ')\n : row.detail,\n ...(row.state === 'active'\n ? {\n startedAt: row.startedAt ?? null,\n hint:\n ledger?.op === 'page'\n ? AI_SITE_PAGE_HINT\n : site && ledger?.op === 'theme'\n ? AI_SITE_LOOK_HINT\n : AI_SITE_ITEM_HINT,\n }\n : {}),\n ...(screen?.sections.length ? { sections: screen.sections.map((section) => section.name) } : {}),\n ...(finished && ledger ? { credits: net } : {}),\n }\n }),\n ...aiSitePublishRow(job, phase),\n ]\n }\n const planStep = job.steps.find((step) => step.name === 'plan')\n const planDone = planStep?.status === 'done' || Boolean(job.plan)\n const stopped = phase === 'failed' || phase === 'stopped'\n const paused = job.status === 'needs_input'\n const planState: AiSiteBuildRowState = planDone\n ? 'done'\n : paused\n ? 'paused'\n : stopped\n ? 'failed'\n : phase === 'working'\n ? 'active'\n : 'waiting'\n const rows: AiSiteBuildRow[] = [\n {\n id: 'plan',\n label: 'Planning your pages',\n state: planState,\n startedAt: planStep?.startedAt ?? null,\n hint: planState === 'active' ? AI_SITE_PLAN_HINT : null,\n ...(planDone && planStep ? { credits: Math.max(0, Math.floor(planStep.creditsSpent ?? 0)) } : {}),\n },\n ]\n // Before there is a plan, the stages a guided start always goes through\n // are named from its answers, so the page shows the whole way from the\n // start rather than one row.\n if (!job.plan && job.kind !== 'build') {\n const pagesAsked = typeof job.siteInputs?.['pages'] === 'number' ? Math.round(job.siteInputs['pages'] as number) : 0\n if (job.siteInputs) {\n // The look is designed first, before the header and footer (AGL-3660).\n rows.push({ id: 'look', label: AI_SITE_LOOK_ROW_LABEL, state: 'waiting' })\n rows.push({ id: 'layout', label: 'Building the header and footer', state: 'waiting' })\n // A guided start that says where its contact form's submissions go\n // plans that form, built after the layout and before the pages (AGL-3596).\n const submissions = job.siteInputs['submissions']\n if (submissions === 'inbox' || submissions === 'lead') {\n rows.push({ id: 'form', label: 'Building your contact form', state: 'waiting' })\n }\n rows.push({\n id: 'pages',\n label: pagesAsked > 1 ? `Writing your ${pagesAsked} pages` : 'Writing your pages',\n state: 'waiting',\n })\n rows.push(...aiSitePublishRow(job, phase))\n }\n return rows\n }\n const built = new Map<string, number>()\n for (const output of job.outputs) built.set(output.resource, (built.get(output.resource) ?? 0) + 1)\n const take = (resource: string): boolean => {\n const left = built.get(resource) ?? 0\n if (left <= 0) return false\n built.set(resource, left - 1)\n return true\n }\n const stages: Array<{ id: string; label: string; resource: string; sections?: string[]; hint?: string }> = []\n // A scaffold designs its look first on every start (AGL-3660), and writes\n // its item ledger only with that first pass's outcome — so while the look\n // is being designed, the job is read here, without a ledger, and the look\n // is the stage it is on: a moving site job that has built nothing yet. A\n // job read without its ledger that has built something and no look is one\n // from before the look had a unit of its own, and has the stage only where\n // it built one.\n const moving = (phase === 'working' || paused) && job.outputs.length === 0\n for (const row of CREATION_ROWS) {\n const creation = job.plan?.create.find((entry) => entry.kind === row.kind)\n const look = row.resource === 'theme'\n if (\n creation ||\n (look && job.kind !== 'build' && moving) ||\n (look && job.outputs.some((output) => output.resource === 'theme'))\n ) {\n stages.push({\n id: look ? 'look' : row.resource,\n label: row.label(creation?.name ?? ''),\n resource: row.resource,\n ...(look ? { hint: AI_SITE_LOOK_HINT } : {}),\n })\n }\n }\n const pages = job.plan?.screens ?? []\n pages.forEach((page, index) => {\n stages.push({\n id: `page-${index}`,\n label: `Writing page ${index + 1} of ${pages.length}: ${page.title}`,\n resource: 'screen',\n sections: page.sections.map((section) => section.name),\n })\n })\n // The build step's start: when the first stage after the plan began.\n const buildStartedAt = job.steps.find((step) => step.name !== 'plan' && step.startedAt)?.startedAt ?? null\n let reached = false\n for (const stage of stages) {\n const done = phase === 'done' || take(stage.resource)\n const current = !done && !reached && planDone\n if (current) reached = true\n const state: AiSiteBuildRowState = done\n ? 'done'\n : current && paused\n ? 'paused'\n : current && stopped\n ? 'failed'\n : current && phase === 'working'\n ? 'active'\n : 'waiting'\n rows.push({\n id: stage.id,\n label: stage.label,\n state,\n ...(state === 'active' && stage.hint ? { hint: stage.hint, startedAt: buildStartedAt } : {}),\n ...(stage.sections?.length ? { sections: stage.sections } : {}),\n })\n }\n rows.push(...aiSitePublishRow(job, phase))\n return rows\n}\n\n/** The row the site's look is designed on (AGL-3660). */\nexport const AI_SITE_LOOK_ROW_LABEL = 'Designing your look'\n\n/** What the look's row says while it runs. */\nexport const AI_SITE_LOOK_HINT =\n 'Choosing a base theme, colors, fonts and the style of your buttons, cards and forms for your kind of site. This takes a few seconds.'\n\n/** What the planning row says while it runs. */\nexport const AI_SITE_PLAN_HINT =\n 'Reading your answers and choosing your pages, what each one says, and the forms and layout they need. This usually takes under a minute.'\n\n/** What the page being written says while it is the active row (AGL-3596). */\nexport const AI_SITE_PAGE_HINT =\n 'Writing this page’s sections from your plan. It is done once every section is in.'\n\n/** What any other part being built says while it is the active row. */\nexport const AI_SITE_ITEM_HINT = 'Building this now. The next step starts when it is done.'\n\n/** The plan's page an item builds: by its title, else by its place among the pages. */\nfunction aiPlanScreenFor(\n plan: AiJobSummary['plan'],\n title: string,\n index: number,\n): NonNullable<AiJobSummary['plan']>['screens'][number] | null {\n const screens = plan?.screens ?? []\n return screens.find((screen) => screen.title === title) ?? (index >= 0 ? (screens[index] ?? null) : null)\n}\n\n/**\n * A guided start ends by putting its pages live (AGL-3596): the last row, so\n * the person sees that step coming and when it is done. Only a site job\n * publishes on its own; a build publishes when asked, and says so in its plan.\n */\nfunction aiSitePublishRow(\n job: Pick<AiJobSummary, 'status'> & Partial<Pick<AiJobSummary, 'kind' | 'sitePublish'>>,\n phase: AiSiteBuildPhase,\n): AiSiteBuildRow[] {\n if (job.kind !== 'site') return []\n const published = (job.sitePublish?.published.length ?? 0) > 0\n return [\n {\n id: 'publish',\n label: 'Publishing your site',\n // A job that stopped or failed publishes nothing, so the row is passed over.\n state: phase === 'done' ? (published ? 'done' : 'skipped') : phase === 'working' ? 'waiting' : 'skipped',\n },\n ]\n}\n\n/**\n * How far the job is, from 0 to 1, by its rows: a finished row counts whole\n * and the active one half. `null` before there is more than one row to count.\n */\nexport function aiSiteBuildFraction(rows: readonly AiSiteBuildRow[]): number | null {\n if (rows.length < 2) return null\n const counted = rows.reduce(\n (sum, row) => sum + (row.state === 'active' ? 0.5 : row.state === 'waiting' || row.state === 'paused' ? 0 : 1),\n 0,\n )\n return Math.min(1, counted / rows.length)\n}\n\n/**\n * The job's one price (AGL-3594), never a plan's on its own: what it has used\n * so far while it works, what it used once done, and, on a failure we gave\n * back, that nothing was charged.\n */\nexport function aiSiteBuildCreditsLine(\n job: Pick<AiJobSummary, 'status' | 'creditsSpent' | 'refundedCredits'> & Partial<Pick<AiJobSummary, 'kind'>>,\n): string | null {\n const spent = Math.max(0, job.creditsSpent ?? 0)\n const refunded = Math.max(0, job.refundedCredits ?? 0)\n const net = Math.max(0, spent - refunded)\n const phase = aiSiteBuildPhase(job)\n // What the job made, by its kind; a job that names none is a site's.\n const subject = !job.kind || job.kind === 'site' ? 'This site' : aiJobKindNoun(job.kind) === 'AI job' ? 'This AI job' : `This ${aiJobKindNoun(job.kind)}`\n // A failure on our side says so in the words every surface uses (AGL-3596),\n // from the job's recorded give-back.\n const refund = phase === 'working' || phase === 'done' ? null : aiJobRefundCopy(job)\n if (refund && refunded > 0) return refund\n if (phase === 'done') return `${subject} used ${net} credits.`\n if (phase === 'working') return `Credits used so far: ${net}`\n if (refund) return `${subject} used ${net} credits. ${refund}`\n return net > 0 ? `${subject} used ${net} credits.` : null\n}\n\n/** The heading and the sentence under it, for one job's page in its current phase. */\nexport interface AiJobPageCopy {\n heading: string\n lede: string\n}\n\n/**\n * What one job's page says at the top (AGL-3594, AGL-3596). A site job reads\n * as \"Building your site\"; any other kind names what it makes — \"Building\n * your page\" — or, for a kind with no noun, the job itself.\n *\n * A guided site start publishes its pages when it finishes, and says so\n * (`sitePublish`): with a page live the heading is \"Your site is live\". A\n * done site job without that record — an older job, or one that was not a\n * guided start — built drafts, and says that instead.\n */\nexport function aiJobPageCopy(\n job: Pick<AiJobSummary, 'kind' | 'status' | 'review' | 'error'> &\n Partial<Pick<AiJobSummary, 'sitePublish' | 'items' | 'outputs'>>,\n brand: string,\n): AiJobPageCopy {\n const phase = aiSiteBuildPhase(job)\n // Paused by the meter (AGL-3660): why, what is already built, and that it\n // carries on — never \"was not built\", which read as a dead end.\n if (job.status === 'needs_input') {\n return {\n heading: aiJobPausedTitle(job.kind),\n lede: [job.error, aiJobBuiltSoFar(job), AI_JOB_PAUSED_NEXT_COPY].filter(Boolean).join(' '),\n }\n }\n // A build is what the person asked for, item by item (AGL-3616).\n if (job.kind === 'build') return aiBuildPageCopy(job, brand)\n const noun = job.kind === 'site' ? 'site' : aiJobKindNoun(job.kind)\n const generic = noun === 'AI job'\n // `products` is the one plural noun.\n const isAre = noun.endsWith('s') ? 'are' : 'is'\n const why = job.review?.message ?? job.error ?? null\n if (phase === 'working') {\n return {\n heading: generic ? 'Your AI job is running' : `Building your ${noun}`,\n lede:\n job.kind === 'site'\n ? `${brand} AI is planning your pages and writing each one. You can leave this page; it keeps going.`\n : `${brand} AI is working on it. You can leave this page; it keeps going.`,\n }\n }\n if (phase === 'done') {\n const published = job.sitePublish?.published.length ?? 0\n // Part of the site was built (AGL-3616): what was, what was not, and its credits.\n const partial = job.kind === 'site' ? aiSitePartialCopy({ items: job.items, status: job.status }) : null\n if (job.kind === 'site' && published > 0) {\n return {\n heading: 'Your site is live',\n lede: [\n partial,\n job.sitePublish?.drafts.length\n ? 'Your pages are published, except the ones listed below, which stayed drafts.'\n : 'Your pages are published, and anyone can visit your site now.',\n ]\n .filter(Boolean)\n .join(' '),\n }\n }\n if (partial) return { heading: 'Your site is ready', lede: `${partial} Your new pages are drafts. Publish them when you’re happy.` }\n if (job.kind === 'site' && job.sitePublish) {\n return {\n heading: 'Your site is ready',\n lede: 'None of your new pages could be published, so they are drafts. The reasons are below.',\n }\n }\n return {\n heading: generic ? 'Your AI job finished' : `Your ${noun} ${isAre} ready`,\n lede:\n job.kind === 'site'\n ? 'Your new pages are drafts. Publish them when you’re happy.'\n : 'Everything it built is an unpublished draft until you publish it.',\n }\n }\n if (phase === 'canceled') {\n return { heading: generic ? 'Your AI job was canceled' : `Your ${noun} was not built`, lede: 'The job was canceled.' }\n }\n return {\n heading: generic ? 'Your AI job stopped' : `Your ${noun} ${noun.endsWith('s') ? 'were' : 'was'} not built`,\n lede: why ?? (generic ? 'Something went wrong running this job.' : `Something went wrong building your ${noun}.`),\n }\n}\n\nconst joinWords = (names: string[]): string =>\n names.length <= 1 ? (names[0] ?? '') : `${names.slice(0, -1).join(', ')} and ${names[names.length - 1]}`\n\n/**\n * What a job has already built, in a sentence (AGL-3660): its look, the header\n * and footer, its form, its pages — from the item ledger where it has one,\n * else from what it has reported as outputs. `null` when it has built nothing.\n */\nexport function aiJobBuiltSoFar(\n job: Pick<AiJobSummary, 'kind'> & Partial<Pick<AiJobSummary, 'items' | 'outputs'>>,\n): string | null {\n const built = (job.items ?? []).filter((row) => row.status === 'succeeded' || row.status === 'degraded')\n const names: string[] = []\n if (job.items?.length) {\n for (const row of built) {\n if (row.op === 'theme') names.push('your look')\n else if (row.op === 'layout') names.push('the header and footer')\n else if (row.op === 'form') names.push(`the form “${row.label}”`)\n else if (row.op === 'page') names.push(`the page “${row.label}”`)\n else if (row.op === 'email') names.push('your welcome email')\n else names.push(`${aiBuildOpNoun(row.op).toLowerCase()} “${row.label}”`)\n }\n } else {\n const outputs = job.outputs ?? []\n const count = (resource: string) => outputs.filter((output) => output.resource === resource).length\n if (count('theme')) names.push('your look')\n if (count('layout')) names.push('the header and footer')\n if (count('form')) names.push(count('form') === 1 ? 'the form' : `${count('form')} forms`)\n const pages = count('screen')\n if (pages) names.push(pages === 1 ? '1 page' : `${pages} pages`)\n }\n return names.length ? `Built so far: ${joinWords(names)}.` : null\n}\n\n/** A build's page heading and sentence (AGL-3616). */\nfunction aiBuildPageCopy(\n job: Pick<AiJobSummary, 'status' | 'review' | 'error'> & Partial<Pick<AiJobSummary, 'items' | 'sitePublish'>>,\n brand: string,\n): AiJobPageCopy {\n const phase = aiSiteBuildPhase(job)\n const outcome = aiBuildOutcomeLine({ items: job.items ?? [], status: job.status })\n if (phase === 'working') {\n return {\n heading: 'Building what you asked for',\n lede: `${brand} AI is building each part in turn. You can leave this page; it keeps going.`,\n }\n }\n if (phase === 'stopped') {\n return {\n heading: job.review?.reason === 'plan' ? 'Your plan is ready' : 'Your build needs you',\n lede: job.review?.message ?? job.error ?? 'It waits for your decision.',\n }\n }\n if (phase === 'done') {\n const failed = (job.items ?? []).some((row) => row.status === 'failed' || row.status === 'skipped')\n const live = job.sitePublish?.published.length ?? 0\n return {\n heading: failed ? 'Most of it is ready' : 'Everything you asked for is ready',\n lede: [\n outcome,\n live ? 'Your new pages are published.' : 'Everything it built is an unpublished draft until you publish it.',\n failed ? 'Try again builds only what failed.' : '',\n ]\n .filter(Boolean)\n .join(' '),\n }\n }\n if (phase === 'canceled') return { heading: 'Your build was canceled', lede: 'The job was canceled.' }\n return {\n heading: 'Nothing could be built',\n lede: [job.error ?? 'Something went wrong building what you asked for.', outcome].filter(Boolean).join(' '),\n }\n}\n"],"names":["aiJobConfirmingOwnPlan","aiJobKindNoun","aiJobRefundCopy","aiBuildItemRows","aiBuildOpNoun","aiBuildOutcomeLine","aiSitePartialCopy","AI_JOB_PAUSED_NEXT_COPY","aiJobPausedTitle","aiSiteBuildPhase","job","status","CREATION_ROWS","kind","resource","label","AI_SITE_LOOK_ROW_LABEL","name","aiSiteBuildRows","rows","aiSiteBuildRowsOf","aiPausedRows","at","findIndex","row","state","index","map","position","hint","startedAt","planStep","built","phase","items","length","site","pages","filter","op","steps","find","step","id","credits","Math","max","floor","creditsSpent","ledger","indexOf","screen","aiPlanScreenFor","plan","finished","net","creditsRefunded","slot","detail","Boolean","join","AI_SITE_PAGE_HINT","AI_SITE_LOOK_HINT","AI_SITE_ITEM_HINT","sections","section","aiSitePublishRow","planDone","stopped","paused","planState","AI_SITE_PLAN_HINT","pagesAsked","siteInputs","round","push","submissions","Map","output","outputs","set","get","take","left","stages","moving","creation","create","entry","look","some","screens","forEach","page","title","buildStartedAt","reached","stage","done","current","published","sitePublish","aiSiteBuildFraction","counted","reduce","sum","min","aiSiteBuildCreditsLine","spent","refunded","refundedCredits","subject","refund","aiJobPageCopy","brand","heading","lede","error","aiJobBuiltSoFar","aiBuildPageCopy","noun","generic","isAre","endsWith","why","review","message","partial","drafts","joinWords","names","slice","toLowerCase","count","outcome","reason","failed","live"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/model/ai-site-build-progress.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AI_JOB_CANCELED_LEDE, aiJobCanceledCreditsCopy } from './ai-job-cancel-copy'\nimport { aiJobConfirmingOwnPlan, aiJobKindNoun } from './ai-job-activity'\nimport { aiJobRefundCopy } from './ai-job-failure-copy'\nimport { aiBuildItemRows, aiBuildOpNoun, aiBuildOutcomeLine, aiSitePartialCopy } from './ai-build-progress'\nimport { AI_JOB_PAUSED_NEXT_COPY, aiJobPausedTitle } from './ai-job-notice'\nimport type { AiJobSummary } from './ai-jobs.types'\n\n/**\n * What the \"Building your site\" page shows of a site job (AGL-3594): one row\n * a stage — planning the pages, then each page — with its state, the state\n * the whole job is in, and the job's one price.\n *\n * Read off the job summary every surface already follows: the plan step's\n * status, the plan's pages, and the pages the build has reported as outputs.\n * A scaffold builds its units in plan order and reports each page when it is\n * written, so the pages written so far are the first pages of the plan.\n *\n * Pure: no React, no request. The page and its spec read the same rows.\n */\n\n/**\n * `paused` (AGL-3660): the row a job the meter paused stopped at — not\n * running, not failed, and carried on from by Resume.\n */\nexport type AiSiteBuildRowState = 'done' | 'active' | 'waiting' | 'failed' | 'skipped' | 'paused'\n\nexport interface AiSiteBuildRow {\n id: string\n label: string\n state: AiSiteBuildRowState\n /** What the person should know about this row (AGL-3616): a build item's failure, note or refund. */\n detail?: string | null\n /** What the row is doing while it is the active one, in a sentence. */\n hint?: string | null\n /** A page's planned sections, in order, so the person sees what is being written. */\n sections?: string[]\n /** The credits this row's work used, once it has finished; absent while it runs. */\n credits?: number\n /** When this row's work started, for the elapsed time beside the active row. */\n startedAt?: string | null\n}\n\n/** Where the whole job stands, as the page's header and actions read it. */\nexport type AiSiteBuildPhase = 'working' | 'done' | 'stopped' | 'failed' | 'canceled'\n\nexport function aiSiteBuildPhase(\n job: Pick<AiJobSummary, 'status'> & Partial<Pick<AiJobSummary, 'review' | 'autoConfirm' | 'updatedAt'>>,\n): AiSiteBuildPhase {\n // A guided start's plan parked for the instant its confirmation takes is\n // the build going on (AGL-3596), never a stop.\n if (aiJobConfirmingOwnPlan(job)) return 'working'\n switch (job.status) {\n case 'done':\n return 'done'\n case 'failed':\n return 'failed'\n case 'canceled':\n return 'canceled'\n case 'needs_review':\n case 'needs_input':\n return 'stopped'\n default:\n return 'working'\n }\n}\n\n/** The creations a scaffold builds before its pages, in its build order, and what each row says. */\nconst CREATION_ROWS: ReadonlyArray<{ kind: string; resource: string; label: (name: string) => string }> = [\n { kind: 'theme-change', resource: 'theme', label: () => AI_SITE_LOOK_ROW_LABEL },\n { kind: 'layout', resource: 'layout', label: (name) => `Building the header and footer: ${name}` },\n { kind: 'form', resource: 'form', label: (name) => `Building the form: ${name}` },\n]\n\n/**\n * One row a stage: planning, then each creation the plan builds before its\n * pages — the colors, the layout, the form — then each page (AGL-3596). A\n * scaffold builds them in that order and reports each as an output when it\n * is written, so the first row without its output is where the build is, and\n * where a failure stopped it: a layout that broke is the layout's row, never\n * the first page's.\n */\nexport function aiSiteBuildRows(\n job: Pick<AiJobSummary, 'status' | 'steps' | 'plan' | 'outputs' | 'review'> &\n Partial<Pick<AiJobSummary, 'items' | 'kind' | 'siteInputs' | 'sitePublish'>>,\n): AiSiteBuildRow[] {\n const rows = aiSiteBuildRowsOf(job)\n return job.status === 'needs_input' ? aiPausedRows(rows) : rows\n}\n\n/**\n * A job the meter paused (AGL-3660) shows no spinner: the row it stopped at —\n * one still marked running, else the first not yet built — reads `paused`,\n * with no running clock and no \"building now\" hint, and every row after it\n * keeps waiting.\n */\nfunction aiPausedRows(rows: AiSiteBuildRow[]): AiSiteBuildRow[] {\n const at = rows.findIndex((row) => row.state === 'active' || row.state === 'paused')\n const index = at >= 0 ? at : rows.findIndex((row) => row.state === 'waiting')\n return rows.map((row, position) => {\n if (row.state === 'active' && position !== index) return { ...row, state: 'waiting', hint: null, startedAt: null }\n if (position !== index) return row\n return { ...row, state: 'paused', hint: null, startedAt: null }\n })\n}\n\nfunction aiSiteBuildRowsOf(\n job: Pick<AiJobSummary, 'status' | 'steps' | 'plan' | 'outputs' | 'review'> &\n Partial<Pick<AiJobSummary, 'items' | 'kind' | 'siteInputs' | 'sitePublish'>>,\n): AiSiteBuildRow[] {\n const phase = aiSiteBuildPhase(job)\n // A build is read off its item ledger (AGL-3616): one row an item, each with\n // its own state and what became of its credits.\n if (job.items?.length) {\n const site = job.kind !== 'build'\n const pages = (job.items ?? []).filter((row) => row.op === 'page')\n // The plan keeps the credits it used once the items take over the page.\n const planStep = job.steps.find((step) => step.name === 'plan')\n return [\n {\n id: 'plan',\n label: site ? 'Planning your pages' : 'Planning what to build',\n state: 'done',\n ...(planStep ? { credits: Math.max(0, Math.floor(planStep.creditsSpent ?? 0)) } : {}),\n },\n ...aiBuildItemRows(job).map((row, index) => {\n const ledger = (job.items ?? [])[index]\n // A site keeps the scaffold's own words for each stage (AGL-3596).\n const label =\n !site || !ledger\n ? row.label\n : ledger.op === 'theme'\n ? AI_SITE_LOOK_ROW_LABEL\n : ledger.op === 'layout'\n ? `Building the header and footer: ${ledger.label}`\n : ledger.op === 'form'\n ? `Building the form: ${ledger.label}`\n : ledger.op === 'page'\n ? `Writing page ${pages.indexOf(ledger) + 1} of ${pages.length}: ${ledger.label}`\n : ledger.op === 'email'\n ? 'Writing your welcome email'\n : row.label\n const screen = ledger?.op === 'page' ? aiPlanScreenFor(job.plan, ledger.label, pages.indexOf(ledger)) : null\n const finished = row.state === 'done' || row.state === 'failed'\n const net = ledger ? Math.max(0, Math.floor((ledger.creditsSpent ?? 0) - (ledger.creditsRefunded ?? 0))) : 0\n return {\n id: row.slot,\n label,\n state: row.state,\n // A part that failed while the rest is still being built says the\n // build goes on (AGL-3596): read alone, it looked like the site had.\n detail:\n row.state === 'failed' && phase === 'working'\n ? [row.detail, site ? 'The rest of your site keeps building.' : 'The rest keeps building.'].filter(Boolean).join(' ')\n : row.detail,\n ...(row.state === 'active'\n ? {\n startedAt: row.startedAt ?? null,\n hint:\n ledger?.op === 'page'\n ? AI_SITE_PAGE_HINT\n : site && ledger?.op === 'theme'\n ? AI_SITE_LOOK_HINT\n : AI_SITE_ITEM_HINT,\n }\n : {}),\n ...(screen?.sections.length ? { sections: screen.sections.map((section) => section.name) } : {}),\n ...(finished && ledger ? { credits: net } : {}),\n }\n }),\n ...aiSitePublishRow(job, phase),\n ]\n }\n const planStep = job.steps.find((step) => step.name === 'plan')\n const planDone = planStep?.status === 'done' || Boolean(job.plan)\n const stopped = phase === 'failed' || phase === 'stopped'\n const paused = job.status === 'needs_input'\n const planState: AiSiteBuildRowState = planDone\n ? 'done'\n : paused\n ? 'paused'\n : stopped\n ? 'failed'\n : phase === 'working'\n ? 'active'\n : 'waiting'\n const rows: AiSiteBuildRow[] = [\n {\n id: 'plan',\n label: 'Planning your pages',\n state: planState,\n startedAt: planStep?.startedAt ?? null,\n hint: planState === 'active' ? AI_SITE_PLAN_HINT : null,\n ...(planDone && planStep ? { credits: Math.max(0, Math.floor(planStep.creditsSpent ?? 0)) } : {}),\n },\n ]\n // Before there is a plan, the stages a guided start always goes through\n // are named from its answers, so the page shows the whole way from the\n // start rather than one row.\n if (!job.plan && job.kind !== 'build') {\n const pagesAsked = typeof job.siteInputs?.['pages'] === 'number' ? Math.round(job.siteInputs['pages'] as number) : 0\n if (job.siteInputs) {\n // The look is designed first, before the header and footer (AGL-3660).\n rows.push({ id: 'look', label: AI_SITE_LOOK_ROW_LABEL, state: 'waiting' })\n rows.push({ id: 'layout', label: 'Building the header and footer', state: 'waiting' })\n // A guided start that says where its contact form's submissions go\n // plans that form, built after the layout and before the pages (AGL-3596).\n const submissions = job.siteInputs['submissions']\n if (submissions === 'inbox' || submissions === 'lead') {\n rows.push({ id: 'form', label: 'Building your contact form', state: 'waiting' })\n }\n rows.push({\n id: 'pages',\n label: pagesAsked > 1 ? `Writing your ${pagesAsked} pages` : 'Writing your pages',\n state: 'waiting',\n })\n rows.push(...aiSitePublishRow(job, phase))\n }\n return rows\n }\n const built = new Map<string, number>()\n for (const output of job.outputs) built.set(output.resource, (built.get(output.resource) ?? 0) + 1)\n const take = (resource: string): boolean => {\n const left = built.get(resource) ?? 0\n if (left <= 0) return false\n built.set(resource, left - 1)\n return true\n }\n const stages: Array<{ id: string; label: string; resource: string; sections?: string[]; hint?: string }> = []\n // A scaffold designs its look first on every start (AGL-3660), and writes\n // its item ledger only with that first pass's outcome — so while the look\n // is being designed, the job is read here, without a ledger, and the look\n // is the stage it is on: a moving site job that has built nothing yet. A\n // job read without its ledger that has built something and no look is one\n // from before the look had a unit of its own, and has the stage only where\n // it built one.\n const moving = (phase === 'working' || paused) && job.outputs.length === 0\n for (const row of CREATION_ROWS) {\n const creation = job.plan?.create.find((entry) => entry.kind === row.kind)\n const look = row.resource === 'theme'\n if (\n creation ||\n (look && job.kind !== 'build' && moving) ||\n (look && job.outputs.some((output) => output.resource === 'theme'))\n ) {\n stages.push({\n id: look ? 'look' : row.resource,\n label: row.label(creation?.name ?? ''),\n resource: row.resource,\n ...(look ? { hint: AI_SITE_LOOK_HINT } : {}),\n })\n }\n }\n const pages = job.plan?.screens ?? []\n pages.forEach((page, index) => {\n stages.push({\n id: `page-${index}`,\n label: `Writing page ${index + 1} of ${pages.length}: ${page.title}`,\n resource: 'screen',\n sections: page.sections.map((section) => section.name),\n })\n })\n // The build step's start: when the first stage after the plan began.\n const buildStartedAt = job.steps.find((step) => step.name !== 'plan' && step.startedAt)?.startedAt ?? null\n let reached = false\n for (const stage of stages) {\n const done = phase === 'done' || take(stage.resource)\n const current = !done && !reached && planDone\n if (current) reached = true\n const state: AiSiteBuildRowState = done\n ? 'done'\n : current && paused\n ? 'paused'\n : current && stopped\n ? 'failed'\n : current && phase === 'working'\n ? 'active'\n : 'waiting'\n rows.push({\n id: stage.id,\n label: stage.label,\n state,\n ...(state === 'active' && stage.hint ? { hint: stage.hint, startedAt: buildStartedAt } : {}),\n ...(stage.sections?.length ? { sections: stage.sections } : {}),\n })\n }\n rows.push(...aiSitePublishRow(job, phase))\n return rows\n}\n\n/** The row the site's look is designed on (AGL-3660). */\nexport const AI_SITE_LOOK_ROW_LABEL = 'Designing your look'\n\n/** What the look's row says while it runs. */\nexport const AI_SITE_LOOK_HINT =\n 'Choosing a base theme, colors, fonts and the style of your buttons, cards and forms for your kind of site. This takes a few seconds.'\n\n/** What the planning row says while it runs. */\nexport const AI_SITE_PLAN_HINT =\n 'Reading your answers and choosing your pages, what each one says, and the forms and layout they need. This usually takes under a minute.'\n\n/** What the page being written says while it is the active row (AGL-3596). */\nexport const AI_SITE_PAGE_HINT =\n 'Writing this page’s sections from your plan. It is done once every section is in.'\n\n/** What any other part being built says while it is the active row. */\nexport const AI_SITE_ITEM_HINT = 'Building this now. The next step starts when it is done.'\n\n/** The plan's page an item builds: by its title, else by its place among the pages. */\nfunction aiPlanScreenFor(\n plan: AiJobSummary['plan'],\n title: string,\n index: number,\n): NonNullable<AiJobSummary['plan']>['screens'][number] | null {\n const screens = plan?.screens ?? []\n return screens.find((screen) => screen.title === title) ?? (index >= 0 ? (screens[index] ?? null) : null)\n}\n\n/**\n * A guided start ends by putting its pages live (AGL-3596): the last row, so\n * the person sees that step coming and when it is done. Only a site job\n * publishes on its own; a build publishes when asked, and says so in its plan.\n */\nfunction aiSitePublishRow(\n job: Pick<AiJobSummary, 'status'> & Partial<Pick<AiJobSummary, 'kind' | 'sitePublish'>>,\n phase: AiSiteBuildPhase,\n): AiSiteBuildRow[] {\n if (job.kind !== 'site') return []\n const published = (job.sitePublish?.published.length ?? 0) > 0\n return [\n {\n id: 'publish',\n label: 'Publishing your site',\n // A job that stopped or failed publishes nothing, so the row is passed over.\n state: phase === 'done' ? (published ? 'done' : 'skipped') : phase === 'working' ? 'waiting' : 'skipped',\n },\n ]\n}\n\n/**\n * How far the job is, from 0 to 1, by its rows: a finished row counts whole\n * and the active one half. `null` before there is more than one row to count.\n */\nexport function aiSiteBuildFraction(rows: readonly AiSiteBuildRow[]): number | null {\n if (rows.length < 2) return null\n const counted = rows.reduce(\n (sum, row) => sum + (row.state === 'active' ? 0.5 : row.state === 'waiting' || row.state === 'paused' ? 0 : 1),\n 0,\n )\n return Math.min(1, counted / rows.length)\n}\n\n/**\n * The job's one price (AGL-3594), never a plan's on its own: what it has used\n * so far while it works, what it used once done, and, on a failure we gave\n * back, that nothing was charged.\n */\nexport function aiSiteBuildCreditsLine(\n job: Pick<AiJobSummary, 'status' | 'creditsSpent' | 'refundedCredits'> & Partial<Pick<AiJobSummary, 'kind'>>,\n): string | null {\n const spent = Math.max(0, job.creditsSpent ?? 0)\n const refunded = Math.max(0, job.refundedCredits ?? 0)\n const net = Math.max(0, spent - refunded)\n const phase = aiSiteBuildPhase(job)\n // What the job made, by its kind; a job that names none is a site's.\n const subject = !job.kind || job.kind === 'site' ? 'This site' : aiJobKindNoun(job.kind) === 'AI job' ? 'This AI job' : `This ${aiJobKindNoun(job.kind)}`\n // A failure on our side says so in the words every surface uses (AGL-3596),\n // from the job's recorded give-back.\n const refund = phase === 'working' || phase === 'done' ? null : aiJobRefundCopy(job)\n if (refund && refunded > 0) return refund\n // A person's cancel keeps what ran charged, and says how much (AGL-3616).\n if (phase === 'canceled') return aiJobCanceledCreditsCopy(job)\n if (phase === 'done') return `${subject} used ${net} credits.`\n if (phase === 'working') return `Credits used so far: ${net}`\n if (refund) return `${subject} used ${net} credits. ${refund}`\n return net > 0 ? `${subject} used ${net} credits.` : null\n}\n\n/** The heading and the sentence under it, for one job's page in its current phase. */\nexport interface AiJobPageCopy {\n heading: string\n lede: string\n}\n\n/**\n * What one job's page says at the top (AGL-3594, AGL-3596). A site job reads\n * as \"Building your site\"; any other kind names what it makes — \"Building\n * your page\" — or, for a kind with no noun, the job itself.\n *\n * A guided site start publishes its pages when it finishes, and says so\n * (`sitePublish`): with a page live the heading is \"Your site is live\". A\n * done site job without that record — an older job, or one that was not a\n * guided start — built drafts, and says that instead.\n */\nexport function aiJobPageCopy(\n job: Pick<AiJobSummary, 'kind' | 'status' | 'review' | 'error'> &\n Partial<Pick<AiJobSummary, 'sitePublish' | 'items' | 'outputs'>>,\n brand: string,\n): AiJobPageCopy {\n const phase = aiSiteBuildPhase(job)\n // Paused by the meter (AGL-3660): why, what is already built, and that it\n // carries on — never \"was not built\", which read as a dead end.\n if (job.status === 'needs_input') {\n return {\n heading: aiJobPausedTitle(job.kind),\n lede: [job.error, aiJobBuiltSoFar(job), AI_JOB_PAUSED_NEXT_COPY].filter(Boolean).join(' '),\n }\n }\n // A build is what the person asked for, item by item (AGL-3616).\n if (job.kind === 'build') return aiBuildPageCopy(job, brand)\n const noun = job.kind === 'site' ? 'site' : aiJobKindNoun(job.kind)\n const generic = noun === 'AI job'\n // `products` is the one plural noun.\n const isAre = noun.endsWith('s') ? 'are' : 'is'\n const why = job.review?.message ?? job.error ?? null\n if (phase === 'working') {\n return {\n heading: generic ? 'Your AI job is running' : `Building your ${noun}`,\n lede:\n job.kind === 'site'\n ? `${brand} AI is planning your pages and writing each one. You can leave this page; it keeps going.`\n : `${brand} AI is working on it. You can leave this page; it keeps going.`,\n }\n }\n if (phase === 'done') {\n const published = job.sitePublish?.published.length ?? 0\n // Part of the site was built (AGL-3616): what was, what was not, and its credits.\n const partial = job.kind === 'site' ? aiSitePartialCopy({ items: job.items, status: job.status }) : null\n if (job.kind === 'site' && published > 0) {\n return {\n heading: 'Your site is live',\n lede: [\n partial,\n job.sitePublish?.drafts.length\n ? 'Your pages are published, except the ones listed below, which stayed drafts.'\n : 'Your pages are published, and anyone can visit your site now.',\n ]\n .filter(Boolean)\n .join(' '),\n }\n }\n if (partial) return { heading: 'Your site is ready', lede: `${partial} Your new pages are drafts. Publish them when you’re happy.` }\n if (job.kind === 'site' && job.sitePublish) {\n return {\n heading: 'Your site is ready',\n lede: 'None of your new pages could be published, so they are drafts. The reasons are below.',\n }\n }\n return {\n heading: generic ? 'Your AI job finished' : `Your ${noun} ${isAre} ready`,\n lede:\n job.kind === 'site'\n ? 'Your new pages are drafts. Publish them when you’re happy.'\n : 'Everything it built is an unpublished draft until you publish it.',\n }\n }\n if (phase === 'canceled') {\n return { heading: generic ? 'Your AI job was canceled' : `You canceled your ${noun}`, lede: AI_JOB_CANCELED_LEDE }\n }\n return {\n heading: generic ? 'Your AI job stopped' : `Your ${noun} ${noun.endsWith('s') ? 'were' : 'was'} not built`,\n lede: why ?? (generic ? 'Something went wrong running this job.' : `Something went wrong building your ${noun}.`),\n }\n}\n\nconst joinWords = (names: string[]): string =>\n names.length <= 1 ? (names[0] ?? '') : `${names.slice(0, -1).join(', ')} and ${names[names.length - 1]}`\n\n/**\n * What a job has already built, in a sentence (AGL-3660): its look, the header\n * and footer, its form, its pages — from the item ledger where it has one,\n * else from what it has reported as outputs. `null` when it has built nothing.\n */\nexport function aiJobBuiltSoFar(\n job: Pick<AiJobSummary, 'kind'> & Partial<Pick<AiJobSummary, 'items' | 'outputs'>>,\n): string | null {\n const built = (job.items ?? []).filter((row) => row.status === 'succeeded' || row.status === 'degraded')\n const names: string[] = []\n if (job.items?.length) {\n for (const row of built) {\n if (row.op === 'theme') names.push('your look')\n else if (row.op === 'layout') names.push('the header and footer')\n else if (row.op === 'form') names.push(`the form “${row.label}”`)\n else if (row.op === 'page') names.push(`the page “${row.label}”`)\n else if (row.op === 'email') names.push('your welcome email')\n else names.push(`${aiBuildOpNoun(row.op).toLowerCase()} “${row.label}”`)\n }\n } else {\n const outputs = job.outputs ?? []\n const count = (resource: string) => outputs.filter((output) => output.resource === resource).length\n if (count('theme')) names.push('your look')\n if (count('layout')) names.push('the header and footer')\n if (count('form')) names.push(count('form') === 1 ? 'the form' : `${count('form')} forms`)\n const pages = count('screen')\n if (pages) names.push(pages === 1 ? '1 page' : `${pages} pages`)\n }\n return names.length ? `Built so far: ${joinWords(names)}.` : null\n}\n\n/** A build's page heading and sentence (AGL-3616). */\nfunction aiBuildPageCopy(\n job: Pick<AiJobSummary, 'status' | 'review' | 'error'> & Partial<Pick<AiJobSummary, 'items' | 'sitePublish'>>,\n brand: string,\n): AiJobPageCopy {\n const phase = aiSiteBuildPhase(job)\n const outcome = aiBuildOutcomeLine({ items: job.items ?? [], status: job.status })\n if (phase === 'working') {\n return {\n heading: 'Building what you asked for',\n lede: `${brand} AI is building each part in turn. You can leave this page; it keeps going.`,\n }\n }\n if (phase === 'stopped') {\n return {\n heading: job.review?.reason === 'plan' ? 'Your plan is ready' : 'Your build needs you',\n lede: job.review?.message ?? job.error ?? 'It waits for your decision.',\n }\n }\n if (phase === 'done') {\n const failed = (job.items ?? []).some((row) => row.status === 'failed' || row.status === 'skipped')\n const live = job.sitePublish?.published.length ?? 0\n return {\n heading: failed ? 'Most of it is ready' : 'Everything you asked for is ready',\n lede: [\n outcome,\n live ? 'Your new pages are published.' : 'Everything it built is an unpublished draft until you publish it.',\n failed ? 'Try again builds only what failed.' : '',\n ]\n .filter(Boolean)\n .join(' '),\n }\n }\n if (phase === 'canceled') return { heading: 'Your build was canceled', lede: AI_JOB_CANCELED_LEDE }\n return {\n heading: 'Nothing could be built',\n lede: [job.error ?? 'Something went wrong building what you asked for.', outcome].filter(Boolean).join(' '),\n }\n}\n"],"names":["AI_JOB_CANCELED_LEDE","aiJobCanceledCreditsCopy","aiJobConfirmingOwnPlan","aiJobKindNoun","aiJobRefundCopy","aiBuildItemRows","aiBuildOpNoun","aiBuildOutcomeLine","aiSitePartialCopy","AI_JOB_PAUSED_NEXT_COPY","aiJobPausedTitle","aiSiteBuildPhase","job","status","CREATION_ROWS","kind","resource","label","AI_SITE_LOOK_ROW_LABEL","name","aiSiteBuildRows","rows","aiSiteBuildRowsOf","aiPausedRows","at","findIndex","row","state","index","map","position","hint","startedAt","planStep","built","phase","items","length","site","pages","filter","op","steps","find","step","id","credits","Math","max","floor","creditsSpent","ledger","indexOf","screen","aiPlanScreenFor","plan","finished","net","creditsRefunded","slot","detail","Boolean","join","AI_SITE_PAGE_HINT","AI_SITE_LOOK_HINT","AI_SITE_ITEM_HINT","sections","section","aiSitePublishRow","planDone","stopped","paused","planState","AI_SITE_PLAN_HINT","pagesAsked","siteInputs","round","push","submissions","Map","output","outputs","set","get","take","left","stages","moving","creation","create","entry","look","some","screens","forEach","page","title","buildStartedAt","reached","stage","done","current","published","sitePublish","aiSiteBuildFraction","counted","reduce","sum","min","aiSiteBuildCreditsLine","spent","refunded","refundedCredits","subject","refund","aiJobPageCopy","brand","heading","lede","error","aiJobBuiltSoFar","aiBuildPageCopy","noun","generic","isAre","endsWith","why","review","message","partial","drafts","joinWords","names","slice","toLowerCase","count","outcome","reason","failed","live"],"mappings":"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"}
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
import { type AiBuildPlan, type AiBuildPlanCreateKind } from './ai-build-plan';
|
|
18
|
+
import { type AiCreditRange, type AiCreditsPrompt, type AiMeasuredCredits } from './ai-credit-estimate';
|
|
18
19
|
/**
|
|
19
20
|
* What a site scaffold is (AGL-2911): the inputs a `site` job is admitted
|
|
20
21
|
* with, the plans a scaffold can build, and what one is estimated to cost
|
|
@@ -147,14 +148,17 @@ export declare function aiFreeSiteWorstCaseCredits(creations: AiFreeSiteCreation
|
|
|
147
148
|
export declare function aiFreeSiteSectionsWithin(creations: AiFreeSiteCreations, taste: number, credits?: Readonly<AiFreeSiteWorstCase>): number;
|
|
148
149
|
/**
|
|
149
150
|
* What a Free site start of this many pages can cost at its worst, in
|
|
150
|
-
* credits (AGL-3660)
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
151
|
+
* credits (AGL-3660): `aiFreeSiteWorstCaseCredits` for an empty site — the
|
|
152
|
+
* plan, its look, the layout and form a guided start builds, each page's
|
|
153
|
+
* answer and listing, the sections its plan is held to
|
|
154
|
+
* (`aiFreeSiteSectionsWithin` at the month's whole taste, which is what the
|
|
155
|
+
* plan step allows) and the room for one retried page.
|
|
156
|
+
*
|
|
157
|
+
* The CEILING a start is quoted with ("up to 282"), no longer the figure it
|
|
158
|
+
* is admitted on (AGL-3722): that is the measured p90
|
|
159
|
+
* (`aiFreeSiteCreditRange`), and a start past what is left is asked to be
|
|
160
|
+
* confirmed and pauses with Resume when its credits run out, instead of
|
|
161
|
+
* being held back from starting at all.
|
|
158
162
|
*/
|
|
159
163
|
export declare function aiFreeSiteCreditEstimate(pages: number, credits?: Readonly<AiFreeSiteWorstCase>): number;
|
|
160
164
|
/**
|
|
@@ -174,21 +178,30 @@ export declare function aiFreeCreditsResetOn(now: Date): string;
|
|
|
174
178
|
/** A reset day as a person reads it: "November 1". */
|
|
175
179
|
export declare function aiFreeCreditsResetLabel(resetsOn: string): string;
|
|
176
180
|
/**
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
* is the
|
|
181
|
+
* What a Free site start of this many pages is likely to cost, its p90 and
|
|
182
|
+
* its ceiling (AGL-3722), before a plan names its sections: the plan, the
|
|
183
|
+
* look, the layout and form a guided start builds, and each page at the
|
|
184
|
+
* nominal section count, at what each MEASURED in production
|
|
185
|
+
* (`AI_MEASURED_UNIT_CREDITS`); the ceiling is the whole worst case the wall
|
|
186
|
+
* is proven with (`aiFreeSiteCreditEstimate`). Two pages: about 137
|
|
187
|
+
* (p90 213, up to 282).
|
|
182
188
|
*/
|
|
183
|
-
export declare function
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
189
|
+
export declare function aiFreeSiteCreditRange(pages: number): AiCreditRange;
|
|
190
|
+
/** The smaller first build a site start offers: its home page alone. */
|
|
191
|
+
export declare const AI_SITE_HOME_FIRST_LABEL = "Build the home page first";
|
|
192
|
+
/**
|
|
193
|
+
* What a Free site start says before it starts when what is left does not
|
|
194
|
+
* cover its p90 (AGL-3722), or `null` when it fits — or when nothing is known
|
|
195
|
+
* about what is left, since the reservation still decides each pass. Not a
|
|
196
|
+
* refusal: the person may build what fits (the job pauses with Resume when
|
|
197
|
+
* the credits run out), build the home page first, or upgrade.
|
|
198
|
+
*/
|
|
199
|
+
export declare function aiFreeSitePrompt(credits: Pick<AiFreeCreditsLeft, 'left' | 'resetsOn'> | null | undefined, pages: number): AiCreditsPrompt | null;
|
|
200
|
+
/**
|
|
201
|
+
* Why a Free start is refused outright (AGL-3722): nothing at all is left,
|
|
202
|
+
* so there is nothing for "build what fits" to build.
|
|
203
|
+
*/
|
|
204
|
+
export declare function aiFreeCreditsNoneLeftText(resetsOn: string): string;
|
|
192
205
|
/**
|
|
193
206
|
* The most sections one scaffolded page may hold. The plan model allows more
|
|
194
207
|
* for a page job, which builds one page; a scaffold builds eight, and each
|
|
@@ -535,6 +548,8 @@ export interface AiPlanPassOptions {
|
|
|
535
548
|
welcomeEmail?: boolean;
|
|
536
549
|
/** The creation kinds the job builds itself; a scaffold's when absent. */
|
|
537
550
|
creates?: readonly AiBuildPlanCreateKind[];
|
|
551
|
+
/** Each page and creation written on its own (`aiStandaloneScreenCreditRange`), not as a site start’s (AGL-3722). */
|
|
552
|
+
standalonePages?: boolean;
|
|
538
553
|
}
|
|
539
554
|
/**
|
|
540
555
|
* The passes a plan implies: one per section of every screen, one more per
|
|
@@ -566,3 +581,42 @@ export declare function aiJobPlanCreditEstimate(kind: string, plan: AiBuildPlan)
|
|
|
566
581
|
export declare function aiSiteCreditEstimate(pages: number, options?: {
|
|
567
582
|
welcomeEmail?: boolean;
|
|
568
583
|
}): number;
|
|
584
|
+
/**
|
|
585
|
+
* The measured cost of one creation a plan builds (AGL-3722): a layout's or
|
|
586
|
+
* a form's as measured, a theme's as the site start's look measured, and
|
|
587
|
+
* any other kind at the stand-in a single-answer creation is priced at.
|
|
588
|
+
* `standalone` for one written on its own — a build's, a page job's — rather
|
|
589
|
+
* than inside a site start's warm run.
|
|
590
|
+
*/
|
|
591
|
+
export declare function aiCreationMeasuredCredits(kind: string, options?: {
|
|
592
|
+
standalone?: boolean;
|
|
593
|
+
}): AiMeasuredCredits;
|
|
594
|
+
/** A planned page's range: its sections scaled around the measured page, its ceiling one pass a section and one for its listing. */
|
|
595
|
+
export declare function aiScreenCreditRange(sections: number): AiCreditRange;
|
|
596
|
+
/**
|
|
597
|
+
* A page written on its own — an Assist build's, a page job's — as a range
|
|
598
|
+
* (AGL-3722): a fixed cost and one per section as such pages measured
|
|
599
|
+
* (`AI_MEASURED_STANDALONE_PAGE`), never a site start's later, cheaper
|
|
600
|
+
* pages; the ceiling as `aiScreenCreditRange`'s.
|
|
601
|
+
*/
|
|
602
|
+
export declare function aiStandaloneScreenCreditRange(sections: number): AiCreditRange;
|
|
603
|
+
/**
|
|
604
|
+
* What a plan is likely to cost, its p90 and its ceiling (AGL-3722): the
|
|
605
|
+
* same units `aiPlanCreditEstimate` counts, each at what it measured; the
|
|
606
|
+
* ceiling IS `aiPlanCreditEstimate`.
|
|
607
|
+
*/
|
|
608
|
+
export declare function aiPlanCreditRange(plan: AiBuildPlan, options?: AiPlanPassOptions): AiCreditRange;
|
|
609
|
+
/**
|
|
610
|
+
* `aiJobPlanCreditEstimate` as a range (AGL-3722): the same kinds, each at
|
|
611
|
+
* what it measured. Only a site start writes its pages in one warm run; every
|
|
612
|
+
* other kind's page is written on its own.
|
|
613
|
+
*/
|
|
614
|
+
export declare function aiJobPlanCreditRange(kind: string, plan: AiBuildPlan): AiCreditRange;
|
|
615
|
+
/**
|
|
616
|
+
* A paid site start's range before its plan (AGL-3722): the plan, its look,
|
|
617
|
+
* layout and form, and each page at the nominal sections, as measured; the
|
|
618
|
+
* ceiling is `aiSiteCreditEstimate`.
|
|
619
|
+
*/
|
|
620
|
+
export declare function aiSiteCreditRange(pages: number, options?: {
|
|
621
|
+
welcomeEmail?: boolean;
|
|
622
|
+
}): AiCreditRange;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
1
2
|
/**
|
|
2
3
|
* @license
|
|
3
4
|
* Copyright 2026 Aglyn LLC
|
|
@@ -18,6 +19,7 @@ import { AI_BUILD_PLAN_CREATION_NOUNS, aiPlanUndeclaredRefs } from "./ai-build-p
|
|
|
18
19
|
import { AI_JOB_CREATE_KINDS } from "./ai-job-creations.js";
|
|
19
20
|
import { AI_PAGE_CREATE_KINDS } from "./ai-page-job.js";
|
|
20
21
|
import { FREE_AI_TASTE_CREDITS_PER_MONTH } from "../plan-entitlements.js";
|
|
22
|
+
import { AI_CREDIT_RANGE_ZERO, AI_MEASURED_PASS_CREDITS, AI_MEASURED_STANDALONE_CREATION_CREDITS, AI_MEASURED_UNIT_CREDITS, aiCreditRangeAdd, aiCreditRangeOf, aiCreditRangeOrdered, aiCreditsPromptFor, aiMeasuredPageCredits, aiMeasuredStandalonePageCredits } from "./ai-credit-estimate.js";
|
|
21
23
|
/**
|
|
22
24
|
* What a site scaffold is (AGL-2911): the inputs a `site` job is admitted
|
|
23
25
|
* with, the plans a scaffold can build, and what one is estimated to cost
|
|
@@ -118,14 +120,17 @@ import { FREE_AI_TASTE_CREDITS_PER_MONTH } from "../plan-entitlements.js";
|
|
|
118
120
|
}
|
|
119
121
|
/**
|
|
120
122
|
* What a Free site start of this many pages can cost at its worst, in
|
|
121
|
-
* credits (AGL-3660)
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
123
|
+
* credits (AGL-3660): `aiFreeSiteWorstCaseCredits` for an empty site — the
|
|
124
|
+
* plan, its look, the layout and form a guided start builds, each page's
|
|
125
|
+
* answer and listing, the sections its plan is held to
|
|
126
|
+
* (`aiFreeSiteSectionsWithin` at the month's whole taste, which is what the
|
|
127
|
+
* plan step allows) and the room for one retried page.
|
|
128
|
+
*
|
|
129
|
+
* The CEILING a start is quoted with ("up to 282"), no longer the figure it
|
|
130
|
+
* is admitted on (AGL-3722): that is the measured p90
|
|
131
|
+
* (`aiFreeSiteCreditRange`), and a start past what is left is asked to be
|
|
132
|
+
* confirmed and pauses with Resume when its credits run out, instead of
|
|
133
|
+
* being held back from starting at all.
|
|
129
134
|
*/ export function aiFreeSiteCreditEstimate(pages, credits = AI_FREE_SITE_WORST_CASE_CREDITS) {
|
|
130
135
|
const creations = {
|
|
131
136
|
layouts: 1,
|
|
@@ -148,23 +153,47 @@ import { FREE_AI_TASTE_CREDITS_PER_MONTH } from "../plan-entitlements.js";
|
|
|
148
153
|
}) : 'the first of next month';
|
|
149
154
|
}
|
|
150
155
|
/**
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
* is the
|
|
156
|
-
|
|
156
|
+
* What a Free site start of this many pages is likely to cost, its p90 and
|
|
157
|
+
* its ceiling (AGL-3722), before a plan names its sections: the plan, the
|
|
158
|
+
* look, the layout and form a guided start builds, and each page at the
|
|
159
|
+
* nominal section count, at what each MEASURED in production
|
|
160
|
+
* (`AI_MEASURED_UNIT_CREDITS`); the ceiling is the whole worst case the wall
|
|
161
|
+
* is proven with (`aiFreeSiteCreditEstimate`). Two pages: about 137
|
|
162
|
+
* (p90 213, up to 282).
|
|
163
|
+
*/ export function aiFreeSiteCreditRange(pages) {
|
|
164
|
+
const count = Math.max(1, Math.floor(pages));
|
|
165
|
+
return aiCreditRangeOrdered(_extends({}, aiSiteStartMeasured(count), {
|
|
166
|
+
ceiling: aiFreeSiteCreditEstimate(count)
|
|
167
|
+
}));
|
|
168
|
+
}
|
|
169
|
+
/** A site start's measured likely and p90 before its plan: plan, look, layout, form and its pages at the nominal sections. */ function aiSiteStartMeasured(pages) {
|
|
170
|
+
const { plan, theme, layout, form } = AI_MEASURED_UNIT_CREDITS;
|
|
171
|
+
const page = aiMeasuredPageCredits(AI_SITE_NOMINAL_SECTIONS);
|
|
172
|
+
return {
|
|
173
|
+
likely: plan.median + theme.median + layout.median + form.median + pages * page.median,
|
|
174
|
+
p90: plan.p90 + theme.p90 + layout.p90 + form.p90 + pages * page.p90
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
/** The smaller first build a site start offers: its home page alone. */ export const AI_SITE_HOME_FIRST_LABEL = 'Build the home page first';
|
|
178
|
+
/**
|
|
179
|
+
* What a Free site start says before it starts when what is left does not
|
|
180
|
+
* cover its p90 (AGL-3722), or `null` when it fits — or when nothing is known
|
|
181
|
+
* about what is left, since the reservation still decides each pass. Not a
|
|
182
|
+
* refusal: the person may build what fits (the job pauses with Resume when
|
|
183
|
+
* the credits run out), build the home page first, or upgrade.
|
|
184
|
+
*/ export function aiFreeSitePrompt(credits, pages) {
|
|
157
185
|
if (!credits || !Number.isFinite(credits.left)) return null;
|
|
158
|
-
const
|
|
159
|
-
const
|
|
160
|
-
return
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
} : null;
|
|
186
|
+
const count = Math.max(1, Math.floor(pages));
|
|
187
|
+
const home = aiFreeSiteCreditRange(1);
|
|
188
|
+
return aiCreditsPromptFor(aiFreeSiteCreditRange(count), credits, count > 1 ? _extends({
|
|
189
|
+
label: AI_SITE_HOME_FIRST_LABEL
|
|
190
|
+
}, home) : null);
|
|
164
191
|
}
|
|
165
|
-
/**
|
|
166
|
-
|
|
167
|
-
|
|
192
|
+
/**
|
|
193
|
+
* Why a Free start is refused outright (AGL-3722): nothing at all is left,
|
|
194
|
+
* so there is nothing for "build what fits" to build.
|
|
195
|
+
*/ export function aiFreeCreditsNoneLeftText(resetsOn) {
|
|
196
|
+
return `You have no free AI credits left this month. They are shared by all your Free workspaces and ` + `renew on ${aiFreeCreditsResetLabel(resetsOn)}. Upgrade this workspace to build with AI now.`;
|
|
168
197
|
}
|
|
169
198
|
/**
|
|
170
199
|
* The most sections one scaffolded page may hold. The plan model allows more
|
|
@@ -658,5 +687,78 @@ const ID_CHARS = /^[A-Za-z0-9_-]{1,64}$/;
|
|
|
658
687
|
const passes = 1 + screens * (AI_SITE_NOMINAL_SECTIONS + 1) + 2 + (options.welcomeEmail ? 1 : 0);
|
|
659
688
|
return passes * AI_SITE_PASS_CREDITS;
|
|
660
689
|
}
|
|
690
|
+
/**
|
|
691
|
+
* The measured cost of one creation a plan builds (AGL-3722): a layout's or
|
|
692
|
+
* a form's as measured, a theme's as the site start's look measured, and
|
|
693
|
+
* any other kind at the stand-in a single-answer creation is priced at.
|
|
694
|
+
* `standalone` for one written on its own — a build's, a page job's — rather
|
|
695
|
+
* than inside a site start's warm run.
|
|
696
|
+
*/ export function aiCreationMeasuredCredits(kind, options = {}) {
|
|
697
|
+
if (kind === 'layout') {
|
|
698
|
+
return options.standalone ? AI_MEASURED_STANDALONE_CREATION_CREDITS.layout : AI_MEASURED_UNIT_CREDITS.layout;
|
|
699
|
+
}
|
|
700
|
+
if (kind === 'form') return AI_MEASURED_UNIT_CREDITS.form;
|
|
701
|
+
if (kind === 'theme' || kind === 'theme-change') return AI_MEASURED_UNIT_CREDITS.theme;
|
|
702
|
+
return AI_MEASURED_PASS_CREDITS;
|
|
703
|
+
}
|
|
704
|
+
/** A planned page's range: its sections scaled around the measured page, its ceiling one pass a section and one for its listing. */ export function aiScreenCreditRange(sections) {
|
|
705
|
+
return aiCreditRangeOf(aiMeasuredPageCredits(sections), (Math.max(0, sections) + 1) * AI_SITE_PASS_CREDITS);
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* A page written on its own — an Assist build's, a page job's — as a range
|
|
709
|
+
* (AGL-3722): a fixed cost and one per section as such pages measured
|
|
710
|
+
* (`AI_MEASURED_STANDALONE_PAGE`), never a site start's later, cheaper
|
|
711
|
+
* pages; the ceiling as `aiScreenCreditRange`'s.
|
|
712
|
+
*/ export function aiStandaloneScreenCreditRange(sections) {
|
|
713
|
+
return aiCreditRangeOf(aiMeasuredStandalonePageCredits(sections), (Math.max(0, sections) + 1) * AI_SITE_PASS_CREDITS);
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* What a plan is likely to cost, its p90 and its ceiling (AGL-3722): the
|
|
717
|
+
* same units `aiPlanCreditEstimate` counts, each at what it measured; the
|
|
718
|
+
* ceiling IS `aiPlanCreditEstimate`.
|
|
719
|
+
*/ export function aiPlanCreditRange(plan, options = {}) {
|
|
720
|
+
var _options_creates;
|
|
721
|
+
const creates = (_options_creates = options.creates) != null ? _options_creates : AI_SITE_CREATE_KINDS;
|
|
722
|
+
let range = AI_CREDIT_RANGE_ZERO;
|
|
723
|
+
const screenRange = options.standalonePages ? aiStandaloneScreenCreditRange : aiScreenCreditRange;
|
|
724
|
+
for (const screen of plan.screens)range = aiCreditRangeAdd(range, screenRange(screen.sections.length));
|
|
725
|
+
for (const entry of plan.create){
|
|
726
|
+
if (!creates.includes(entry.kind)) continue;
|
|
727
|
+
range = aiCreditRangeAdd(range, aiCreditRangeOf(aiCreationMeasuredCredits(entry.kind, {
|
|
728
|
+
standalone: options.standalonePages
|
|
729
|
+
}), AI_SITE_PASS_CREDITS));
|
|
730
|
+
}
|
|
731
|
+
if (options.welcomeEmail) range = aiCreditRangeAdd(range, aiCreditRangeOf(AI_MEASURED_PASS_CREDITS, AI_SITE_PASS_CREDITS));
|
|
732
|
+
return aiCreditRangeOrdered(range);
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* `aiJobPlanCreditEstimate` as a range (AGL-3722): the same kinds, each at
|
|
736
|
+
* what it measured. Only a site start writes its pages in one warm run; every
|
|
737
|
+
* other kind's page is written on its own.
|
|
738
|
+
*/ export function aiJobPlanCreditRange(kind, plan) {
|
|
739
|
+
const creates = kind === 'page' ? AI_PAGE_CREATE_KINDS : AI_JOB_CREATE_KINDS[kind];
|
|
740
|
+
return aiPlanCreditRange(plan, _extends({}, creates ? {
|
|
741
|
+
creates
|
|
742
|
+
} : {}, {
|
|
743
|
+
standalonePages: kind !== 'site'
|
|
744
|
+
}));
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* A paid site start's range before its plan (AGL-3722): the plan, its look,
|
|
748
|
+
* layout and form, and each page at the nominal sections, as measured; the
|
|
749
|
+
* ceiling is `aiSiteCreditEstimate`.
|
|
750
|
+
*/ export function aiSiteCreditRange(pages, options = {}) {
|
|
751
|
+
const count = Math.max(0, Math.floor(pages));
|
|
752
|
+
const measured = aiSiteStartMeasured(count);
|
|
753
|
+
const email = options.welcomeEmail ? AI_MEASURED_PASS_CREDITS : {
|
|
754
|
+
median: 0,
|
|
755
|
+
p90: 0
|
|
756
|
+
};
|
|
757
|
+
return aiCreditRangeOrdered({
|
|
758
|
+
likely: measured.likely + email.median,
|
|
759
|
+
p90: measured.p90 + email.p90,
|
|
760
|
+
ceiling: aiSiteCreditEstimate(count, options)
|
|
761
|
+
});
|
|
762
|
+
}
|
|
661
763
|
|
|
662
764
|
//# sourceMappingURL=ai-site-job.js.map
|