@aglyn/plugins-ai 1.0.0-beta.257 → 1.0.0-beta.258
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/assist-panel.component.js +21 -8
- package/src/lib/components/assist-panel.component.js.map +1 -1
- package/src/lib/insights/ai-figure-readers.js +15 -8
- package/src/lib/insights/ai-figure-readers.js.map +1 -1
- package/src/lib/jobs/ai-job-build-step.d.ts +9 -0
- package/src/lib/jobs/ai-job-build-step.js +19 -3
- package/src/lib/jobs/ai-job-build-step.js.map +1 -1
- package/src/lib/jobs/ai-job-insight-step.js +1 -1
- package/src/lib/jobs/ai-job-insight-step.js.map +1 -1
- package/src/lib/jobs/ai-job-page-language.d.ts +19 -0
- package/src/lib/jobs/ai-job-page-language.js +24 -4
- package/src/lib/jobs/ai-job-page-language.js.map +1 -1
- package/src/lib/jobs/ai-job-page-sections.js +12 -1
- package/src/lib/jobs/ai-job-page-sections.js.map +1 -1
- package/src/lib/jobs/ai-job-page-step.d.ts +14 -0
- package/src/lib/jobs/ai-job-page-step.js +69 -20
- package/src/lib/jobs/ai-job-page-step.js.map +1 -1
- package/src/lib/jobs/ai-job-seo-step.js +3 -2
- package/src/lib/jobs/ai-job-seo-step.js.map +1 -1
- package/src/lib/jobs/ai-layout-stock-photos.d.ts +10 -5
- package/src/lib/jobs/ai-layout-stock-photos.js +89 -7
- package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
- package/src/lib/jobs/fixtures/ai-stock-photo-copper-kettle-recordings.d.ts +21 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-copper-kettle-recordings.js +126 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-copper-kettle-recordings.js.map +1 -0
- package/src/lib/layout-language/ai-layout-compiler.js +52 -52
- package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
- package/src/lib/layout-language/ai-layout-copy.d.ts +9 -5
- package/src/lib/layout-language/ai-layout-copy.js +22 -14
- package/src/lib/layout-language/ai-layout-copy.js.map +1 -1
- package/src/lib/layout-language/ai-layout-frame.js +4 -4
- package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
- package/src/lib/layout-language/ai-layout-pictures.d.ts +44 -15
- package/src/lib/layout-language/ai-layout-pictures.js +29 -8
- package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
- package/src/lib/model/ai-build-job.js +14 -0
- package/src/lib/model/ai-build-job.js.map +1 -1
- package/src/lib/model/ai-host-publish-context.d.ts +6 -0
- package/src/lib/model/ai-host-publish-context.js +15 -2
- package/src/lib/model/ai-host-publish-context.js.map +1 -1
- package/src/lib/model/assist-follow-up.d.ts +35 -0
- package/src/lib/model/assist-follow-up.js +44 -4
- package/src/lib/model/assist-follow-up.js.map +1 -1
- package/src/lib/providers/anthropic.js +17 -4
- package/src/lib/providers/anthropic.js.map +1 -1
- package/src/lib/providers/cache-write-hour.d.ts +37 -0
- package/src/lib/providers/cache-write-hour.js +46 -0
- package/src/lib/providers/cache-write-hour.js.map +1 -0
- package/src/lib/providers/contract.d.ts +16 -3
- package/src/lib/providers/contract.js.map +1 -1
- package/src/lib/providers/routing.d.ts +13 -0
- package/src/lib/providers/routing.js +27 -11
- package/src/lib/providers/routing.js.map +1 -1
- package/src/lib/runtime/ai-dev-env.d.ts +13 -3
- package/src/lib/runtime/ai-dev-env.js +17 -3
- package/src/lib/runtime/ai-dev-env.js.map +1 -1
- package/src/lib/runtime/ai-dev-replay.js +4 -2
- package/src/lib/runtime/ai-dev-replay.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.d.ts +41 -1
- package/src/lib/runtime/ai-doctrine-validators.js +263 -2
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-doctrine.js +7 -1
- package/src/lib/runtime/ai-doctrine.js.map +1 -1
- package/src/lib/runtime/ai-eval-live.js +1 -1
- package/src/lib/runtime/ai-eval-live.js.map +1 -1
- package/src/lib/runtime/ai-eval.d.ts +1 -1
- package/src/lib/runtime/ai-eval.js +18 -1
- package/src/lib/runtime/ai-eval.js.map +1 -1
- package/src/lib/runtime/ai-placeholder-tokens.d.ts +70 -0
- package/src/lib/runtime/ai-placeholder-tokens.js +169 -0
- package/src/lib/runtime/ai-placeholder-tokens.js.map +1 -0
- package/src/lib/runtime/ai-repeated-items.js +5 -2
- package/src/lib/runtime/ai-repeated-items.js.map +1 -1
- package/src/lib/runtime/ai-runtime.js +2 -3
- package/src/lib/runtime/ai-runtime.js.map +1 -1
- package/src/lib/server/assist-chat.js +8 -3
- package/src/lib/server/assist-chat.js.map +1 -1
- package/src/lib/server/assist-view-context.d.ts +5 -1
- package/src/lib/server/assist-view-context.js +8 -3
- package/src/lib/server/assist-view-context.js.map +1 -1
- package/src/lib/usage/assist-usage.d.ts +2 -0
- package/src/lib/usage/assist-usage.js +8 -3
- package/src/lib/usage/assist-usage.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/jobs/ai-job-build-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\nimport { aiJobCancelAsked } from './ai-job-cancel'\nimport type { AglynOrgBilling } from '@aglyn/aglyn/foundation/definitions/org-billing.types'\nimport type { PluginAiCapability } from '@aglyn/aglyn/plugin-manager/plugin-ai-capabilities'\nimport { resolveEffectivePlan } from '@aglyn/aglyn/app-utils/plan-entitlements'\nimport { resolveOrgIdForHost } from '@aglyn/tenant-data-admin/server/organizations'\nimport {\n AI_BUILD_LIMITS,\n AI_BUILD_MADE_INPUT,\n AI_BUILD_PUBLISH_INPUT,\n aiArticle,\n aiBuildCreditRange,\n aiBuildDegradation,\n aiBuildInitialLedger,\n aiBuildItemDelivered,\n aiBuildItemOpen,\n aiBuildNextUnit,\n aiBuildOrder,\n aiBuildItemOutputNote,\n aiBuildPlacedItemLines,\n aiBuildPlanMissingInput,\n aiBuildPlanShapeRefusal,\n aiBuildSmaller,\n aiBuildUnits,\n type AiBuildMade,\n type AiBuildOps,\n type AiBuildUnit,\n} from '../model/ai-build-job'\nimport { isAiPlanNewRef, type AiBuildPlanCreateKind } from '../model/ai-build-plan'\nimport type {\n AiJob,\n AiJobItemFailure,\n AiJobItemLedger,\n AiJobKind,\n AiJobOutput,\n AiJobPlan,\n} from '../model/ai-jobs.types'\nimport { AI_SITE_MAX_SECTIONS } from '../model/ai-site-job'\nimport {\n AI_CREDITS_CONFIRM_CODE,\n aiCreditsPromptFor,\n aiCreditsPromptText,\n type AiCreditRange,\n type AiCreditsPrompt,\n type AiCreditsSmaller,\n} from '../model/ai-credit-estimate'\nimport { aiFreeCreditsNoneLeftText, aiSiteWords } from '../model/ai-site-job'\nimport { readFreeAiCreditsLeft } from '../usage/free-ai-credits-left'\nimport { aiModelForStep } from '../providers/routing'\nimport {\n AI_BUILD_UNIT_EMPTY_COPY,\n aiBuildBuiltRefs,\n aiUnitErrorRetryable,\n aiUnitFailure,\n aiUnitSpend,\n} from './ai-build-unit-outcome'\nimport { aiBuildOps, type AiBuildOpsContext } from './ai-build-capabilities'\nimport {\n aiJobAdmissionRefusal,\n registerAiJobAdmission,\n type AiJobAdmission,\n type AiJobAdmissionContext,\n type AiJobAdmissionRefusal,\n} from './ai-job-admission'\nimport { aiOriginJobId } from './ai-job-draft-ids'\nimport { readAiDraftNodes } from './ai-job-drafts'\nimport { aiConfirmedPlan, aiUnspentOutcome } from './ai-job-generation'\nimport { AI_JOB_PAGE_STEP_MINIMUM_MS } from './ai-job-page-budget'\nimport {\n aiPluginDraftAdmissionRefusal,\n aiPluginDraftWriter,\n type AiPluginDraftWriterLookup,\n} from './ai-job-plugin-drafts'\nimport { aiSitePageWritten, aiSiteResolvedRef } from './ai-job-site-step'\nimport { AI_LAYOUT_SITE_PAGES_INPUT, aiLayoutSitePagesOfPlan } from './ai-job-layout-site-pages'\nimport { AI_LAYOUT_FORM_PAGE_INPUT, AI_LAYOUT_LANGUAGE_INPUT, aiJobUsesLayoutLanguage, aiLayoutFormPageOfPlan } from './ai-job-page-language'\nimport { aiDatasetListingsOf } from './ai-job-site-datasets'\nimport { AI_SITE_EVENT_OP, aiEventsListings } from './ai-job-site-events'\nimport { AI_FORM_DATASET_MADE_INPUT } from './ai-job-form-dataset'\nimport { AI_LAYOUT_LISTINGS_INPUT } from '../layout-language/ai-layout-listings'\nimport {\n AI_BUILD_STORE_OP,\n AI_BUILD_STORE_PAGES_PRESENT_NOTE,\n aiBuildStoreLayoutLinks,\n aiBuildStoreLayoutOf,\n aiBuildStorePagesOf,\n aiBuildStorePagesStillMissing,\n type AiBuildStoreLinksState,\n type AiStoreSitePage,\n} from '../model/ai-build-store-pages'\nimport type { AiStoreLayoutLinks } from '../model/ai-layout-store-links'\nimport { writeAiStoreLinksLayoutDraft } from './ai-job-store-links-layout'\nimport type { AiSitePublishStoreLinks } from './ai-site-publish'\nimport {\n AI_SITE_STORE_LINKS_INPUT,\n AI_SITE_STORE_PAGES_NOTE,\n aiStoreFrameLinks,\n aiStorePagesToWrite,\n} from '../model/ai-site-store-pages'\nimport {\n AI_SITE_STORE_PAGES_INPUT,\n aiSiteStorePageId,\n aiSiteStorePagesRefusal,\n runAiSiteStorePagesUnit,\n type AiSiteStorePagesInput,\n} from './ai-job-site-store-pages'\nimport {\n AI_JOB_BRIEF_MAX_CHARS,\n type AiJobItemOutcome,\n type AiJobStepOutcome,\n type AiJobStepRunner,\n} from './ai-job-text-step'\nimport { aiJobPublishesBuild, aiMergeSitePublish, aiPublishGuidedSite } from './ai-site-publish'\nimport {\n AI_PLANNED_JOB_KINDS,\n aiJobStepRunMinimumMs,\n aiJobStepRunnerFor,\n registerAiJobStep,\n registerAiJobStepPasses,\n} from './ai-jobs'\n\n/**\n * The build step (AGL-3616): the generation step of a `build` job, run once\n * the member confirmed the plan their request produced.\n *\n * Like the site scaffold it generalizes, it builds nothing itself and asks no\n * model of its own. Each pass takes the next unit in dependency order and\n * hands it to what builds that kind of thing — a page, layout, form,\n * component, email design or template to this plugin's own step, under a job\n * derived for the unit; another plugin's resource to that plugin's writer on\n * the resource-draft seam, with the content the owner's capability derives\n * from the item's arguments. One unit, one pass, one recorded spend.\n *\n * ── Settled item by item ────────────────────────────────────────────────\n *\n * Where a unit stands is read from the job's ITEM LEDGER, never from counting\n * outputs: the machine writes each pass's row in the transaction that\n * records its spend (`recordStep`). A unit that fails is a FAILED ROW, not a\n * failed job: the pass reports it, the machine gives back that item's spend\n * where the failure was ours, and the next pass builds the next unit. What\n * depended on it is built without it, or skipped where it cannot stand\n * without it (`aiBuildDegradation`). The machine ends the job when nothing is\n * left: `done` when anything was delivered, `failed` — its planning given\n * back too — when nothing was.\n *\n * ── Drafts, unless asked and confirmed ───────────────────────────────────\n *\n * Every unit writes the draft its own kind writes, which nothing publishes.\n * Only a build whose request asked to publish AND whose member ticked the\n * plan card's box puts its built pages live, once, on its last pass, through\n * the guided start's publish.\n */\n\n/** What a build answers with no confirmed plan to build. */\nexport const AI_BUILD_NO_PLAN_COPY = 'This build has no confirmed plan to build.'\n\n/** What a unit says when nothing on this site builds its operation any more. */\nexport const aiBuildUnavailableCopy = (noun: string): string =>\n `Not built: ${aiArticle(noun)} cannot be made on this site right now.`\n\n\n/** What a page that was reported built but holds none of its plan says. */\nexport const AI_BUILD_PAGE_NOT_WRITTEN_COPY = 'The page was not written from its plan.'\n\n\n/**\n * The most passes a build's step may take: every unit at a page's worst — its\n * sections and its listing — so a runner that never finishes is still\n * bounded while the largest plan is not. Try again starts the count over.\n */\nexport const AI_BUILD_MAX_PASSES = AI_BUILD_LIMITS.units * (AI_SITE_MAX_SECTIONS + 1) + 1\n\n/** The job kind a creation of the build is built by. */\nconst CREATION_JOB_KINDS: Partial<Record<AiBuildPlanCreateKind, AiJobKind>> = {\n layout: 'layout',\n form: 'form',\n component: 'component',\n email: 'email',\n}\n\n/** The job kind a unit is built by, where an AI runner builds it. */\nexport function aiBuildUnitJobKind(unit: AiBuildUnit, ops: AiBuildOps): AiJobKind | null {\n if (unit.screen) return 'page'\n if (unit.creation) return CREATION_JOB_KINDS[unit.creation.kind] ?? null\n const runnerKind = ops.get(unit.op)?.runnerKind\n return runnerKind ? (runnerKind as AiJobKind) : null\n}\n\n/** What the job drawer says under an item another plugin's writer made (`model/ai-build-job.ts`). */\nexport { aiBuildItemOutputNote }\n\n/** The id a unit's job, and so its draft, is named by. */\nexport function aiBuildUnitJobId(job: Pick<AiJob, '$id'>, unit: AiBuildUnit): string {\n return unit.creation?.id ?? unit.screen?.id ?? unit.item?.id ?? `${job.$id}-${unit.slot}`\n}\n\n/**\n * The job a unit is built under (generalizing `aiSiteUnitJob`): this job's\n * org, site, creator and model; the kind that builds the unit; a plan\n * narrowed to the unit, its `new:` references resolved to what was built and\n * the failed ones left out; and a brief that says what the unit is, what it\n * is built without, and which blocks its sections place.\n */\nexport function aiBuildUnitJob(\n job: AiJob,\n unit: AiBuildUnit,\n context: {\n kind: AiJobKind\n units: readonly AiBuildUnit[]\n ledger: readonly AiJobItemLedger[]\n ops: AiBuildOps\n briefLines?: readonly string[]\n },\n): AiJob {\n const plan = job.plan as AiJobPlan\n const built = aiBuildBuiltRefs(context.units, context.ledger, job.outputs ?? [])\n const labels = { ...(plan.labels ?? {}) }\n for (const entry of built.values()) labels[entry.id] = entry.label\n const brief = [job.brief.trim()]\n const unitPlan: AiJobPlan = { ...plan, labels, reuse: [...plan.reuse], create: [], screens: [] }\n delete unitPlan.items\n const placedByScreens = new Set(plan.screens.flatMap((screen) => screen.sections.flatMap((section) => section.uses)))\n if (unit.creation) {\n unitPlan.reuse = plan.reuse.filter((entry) => !placedByScreens.has(entry.id))\n unitPlan.create = [\n {\n ...unit.creation,\n duplicateOf: aiSiteResolvedRef(unit.creation.duplicateOf, built),\n // The dataset a form writes to, new or the site's own (AGL-3616); one\n // this build failed to make leaves the form as it always was.\n ...(unit.creation.writesTo ? { writesTo: aiSiteResolvedRef(unit.creation.writesTo, built) } : {}),\n },\n ]\n brief.push(`Build the ${unit.creation.kind} “${unit.creation.name}”: ${unit.creation.why}`)\n }\n if (unit.screen) {\n const screen = unit.screen\n for (const entry of built.values()) {\n unitPlan.reuse.push({ kind: entry.kind, id: entry.id, purpose: `the ${entry.kind} this request built` })\n }\n let builtLayout: string | null = null\n for (const entry of built.values()) if (entry.kind === 'layout') builtLayout = builtLayout ?? entry.id\n unitPlan.screens = [\n {\n ...screen,\n // A page whose layout failed renders inside the site's own: the page\n // step falls back to it when the plan names none.\n layout: aiSiteResolvedRef(screen.layout, built) ?? (isAiPlanNewRef(screen.layout) ? builtLayout : null),\n template: aiSiteResolvedRef(screen.template, built),\n duplicateOf: aiSiteResolvedRef(screen.duplicateOf, built),\n record: screen.record\n ? { ...screen.record, dataset: aiSiteResolvedRef(screen.record.dataset, built) ?? screen.record.dataset }\n : null,\n sections: screen.sections.map((section) => ({\n ...section,\n uses: section.uses\n .map((ref) => aiSiteResolvedRef(ref, built))\n .filter((ref): ref is string => !!ref),\n })),\n },\n ]\n brief.push(`Build the page “${screen.title}”, at ${screen.slug}.`)\n // A build's events are listed by the platform (AGL-3755), never written by the page.\n brief.push(\n ...aiBuildPlacedItemLines(unit, { units: context.units, ledger: context.ledger, ops: context.ops, placedByCode: [AI_SITE_EVENT_OP] }),\n )\n }\n const item = unit.item\n if (item) {\n const noun = context.ops.get(item.op)?.noun ?? item.op\n brief.push(`Build the ${noun} “${item.name}”${item.why ? `: ${item.why}` : '.'}`)\n // A planned kind's step builds the plan's first creation of its kind.\n unitPlan.create = AI_PLANNED_JOB_KINDS.includes(context.kind)\n ? [{ kind: context.kind as AiBuildPlanCreateKind, name: item.name, why: item.why, duplicateOf: null, fields: [], ...(item.id ? { id: item.id } : {}) }]\n : []\n }\n brief.push(...(context.briefLines ?? []))\n const inputs: Record<string, unknown> = {\n ...job.inputs,\n ...(item?.args ?? {}),\n originJobId: aiOriginJobId(job),\n }\n delete inputs[AI_BUILD_PUBLISH_INPUT]\n // An item is told the pages and layouts this build made before it, which\n // its arguments may link as `new:<name>` (a menu item, AGL-3728).\n if (item) {\n const rows = new Map(context.ledger.map((row) => [row.slot, row]))\n const made: AiBuildMade = {\n pages: context.units.flatMap((one) => {\n const row = rows.get(one.slot)\n return one.screen?.id && row && aiBuildItemDelivered(row) ? [{ title: one.screen.title, id: one.screen.id }] : []\n }),\n layouts: [...built.entries()].filter(([, entry]) => entry.kind === 'layout').map(([name, entry]) => ({ name, id: entry.id })),\n }\n if (made.pages.length || made.layouts.length) inputs[AI_BUILD_MADE_INPUT] = made\n }\n // A dataset this build made for its form, which the form may bind (AGL-3616).\n const madeFor = unit.creation?.kind === 'form' && isAiPlanNewRef(unit.creation.writesTo) ? unitPlan.create[0]?.writesTo : null\n if (madeFor) inputs[AI_FORM_DATASET_MADE_INPUT] = madeFor\n // A build's pages and layouts are designed in the layout language and\n // compiled (AGL-3660), told the pages the build plans and where its form is.\n if (context.kind === 'page' || context.kind === 'layout') {\n inputs[AI_LAYOUT_LANGUAGE_INPUT] = true\n const pages = aiLayoutSitePagesOfPlan(plan.screens)\n if (pages.length) inputs[AI_LAYOUT_SITE_PAGES_INPUT] = pages\n const formPage = aiLayoutFormPageOfPlan(plan)\n if (formPage) inputs[AI_LAYOUT_FORM_PAGE_INPUT] = formPage\n // The datasets this build made, repeated in the sections that name them (AGL-3616),\n // and the site's own the plan reuses (AGL-3747): the page reads their fields,\n // and the record pages the site already serves for them, off its inventory.\n const datasets = [...built.entries()]\n .filter(([, entry]) => entry.kind === 'dataset')\n .map(([name, entry]) => ({ id: entry.id, name: context.units.find((one) => one.item?.name.toLowerCase() === name)?.label ?? entry.label }))\n for (const entry of plan.reuse) {\n if (entry.kind !== 'dataset' || datasets.some((one) => one.id === entry.id)) continue\n datasets.push({ id: entry.id, name: plan.labels?.[entry.id] ?? entry.id })\n }\n const listings = aiDatasetListingsOf(datasets, plan.screens)\n // The events this build wrote, in the sections that name them (AGL-3755).\n const eventUnits = context.units.filter((one) => one.item?.op === AI_SITE_EVENT_OP)\n const ledgerRows = new Map(context.ledger.map((row) => [row.slot, row]))\n listings.push(\n ...aiEventsListings({\n written: eventUnits\n .filter((one) => {\n const row = ledgerRows.get(one.slot)\n return Boolean(row && aiBuildItemDelivered(row) && row.outputs.length)\n })\n .map((one) => one.item?.name ?? one.label),\n planned: eventUnits.map((one) => one.item?.name ?? one.label),\n screens: plan.screens,\n }),\n )\n if (listings.length) inputs[AI_LAYOUT_LISTINGS_INPUT] = listings\n }\n // A build that makes the site a store links its account and policies from\n // the layout it makes (AGL-3676), by path: they are written after it.\n const storePages = aiBuildStorePagesOf(plan)\n if (context.kind === 'layout' && storePages) inputs[AI_SITE_STORE_LINKS_INPUT] = aiStoreFrameLinks(storePages.pages)\n return {\n ...job,\n $id: aiBuildUnitJobId(job, unit),\n kind: context.kind,\n steps: [],\n outputs: [],\n items: null,\n plan: item && !AI_PLANNED_JOB_KINDS.includes(context.kind) ? null : unitPlan,\n inputs,\n brief: brief.join('\\n').slice(0, AI_JOB_BRIEF_MAX_CHARS),\n }\n}\n\n/** The unit's failure, for its row: ours or not, why, in customer-safe words. */\nfunction failed(\n slot: string,\n failure: AiJobItemFailure,\n extra: Partial<AiJobItemOutcome> = {},\n): AiJobItemOutcome {\n return { slot, status: 'failed', failure, ...extra }\n}\n\nexport interface AiJobBuildStepDeps {\n /** The runner registry; specs hand in fakes. */\n runnerFor?: typeof aiJobStepRunnerFor\n /** The draft writer registry; specs hand in fakes. */\n writerFor?: AiPluginDraftWriterLookup\n /** The operations this site may use; the registry and its gates otherwise. */\n opsFor?: (context: AiBuildOpsContext) => Promise<AiBuildOps>\n /** A runner kind's own admission, asked before its item runs; the registry's otherwise. */\n admissionFor?: typeof aiJobAdmissionRefusal\n /** Another plugin's admission for its writer; the seam's otherwise. */\n pluginAdmission?: typeof aiPluginDraftAdmissionRefusal\n /** The draft reader a built page is checked through. */\n readNodes?: typeof readAiDraftNodes\n /** The publish a build asked for and confirmed. */\n publish?: typeof aiPublishGuidedSite\n /** A store's own pages' pass and whether they may be added here (AGL-3676); specs hand in fakes. */\n storePages?: AiJobStepRunner\n storePagesRefusal?: typeof aiSiteStorePagesRefusal\n /** The site's pages as they are now, which a store's own pages are checked against before they are written. */\n readSitePages?: typeof readAiStoreSitePages\n /** The draft version of the site's layout a store's links are written into. */\n writeStoreLinks?: typeof writeAiStoreLinksLayoutDraft\n}\n\n/** The site's pages as a store's own pages are checked against them (AGL-3676): every page that is not deleted. */\nexport async function readAiStoreSitePages(firestore: FirebaseFirestore.Firestore, hostId: string): Promise<AiStoreSitePage[]> {\n const snapshot = await firestore\n .collection('hosts')\n .doc(hostId)\n .collection('screens')\n .select('displayName', 'slug', 'kind', 'deletedAt', 'layoutId')\n .get()\n return snapshot.docs.flatMap((doc) => {\n const kind = doc.get('kind')\n if (doc.get('deletedAt') || (kind && kind !== 'template')) return []\n const slug = String(doc.get('slug') ?? '')\n const layoutId = doc.get('layoutId')\n return slug\n ? [{ id: doc.id, slug, title: String(doc.get('displayName') ?? ''), template: kind === 'template', layoutId: typeof layoutId === 'string' && layoutId ? layoutId : null }]\n : []\n })\n}\n\n/**\n * What a build's store pages unit is told (AGL-3676): the pages its plan kept,\n * less any the site has gained since — never counting the pages this unit\n * wrote itself on an earlier pass, which it finds again by their ids — what\n * their words link, and the layout they render inside: the plan's Shop\n * page's, else the site's own (`aiBuildStoreLayoutOf`).\n */\nexport function aiBuildStorePagesInput(\n job: AiJob,\n context: { unitJobId: string; sitePages: readonly AiStoreSitePage[]; units: readonly AiBuildUnit[]; ledger: readonly AiJobItemLedger[] },\n): AiSiteStorePagesInput | null {\n const plan = job.plan as AiJobPlan\n const kept = aiBuildStorePagesOf(plan)\n if (!kept) return null\n const own = new Set(kept.pages.map((page) => aiSiteStorePageId(context.unitJobId, page.key)))\n const pages = aiBuildStorePagesStillMissing(\n kept.pages,\n context.sitePages.filter((page) => !page.id || !own.has(page.id)),\n )\n const built = aiBuildBuiltRefs(context.units, context.ledger, job.outputs ?? [])\n const shop = plan.screens.find((screen) => !screen.record && screen.slug.replace(/^\\/+/, '').split('/')[0].toLowerCase() === kept.facts.shopPath.slice(1))\n const layout = shop ? aiSiteResolvedRef(shop.layout, built) : null\n return {\n pages,\n facts: kept.facts,\n layoutId: aiBuildStoreLayoutOf(layout && !isAiPlanNewRef(layout) ? layout : null, context.sitePages),\n }\n}\n\n/**\n * Adds a store's links to the site's own layout (AGL-3676), as a draft\n * version, where the build made no layout of its own for its store pages: the\n * outputs that record it — the layout version written (`storeLinks: draft`),\n * and on the first page `storeLinks: missing` where the layout had no header\n * or footer list to add them to, or there is no layout at all.\n */\nexport async function aiBuildStoreLinksOutputs(\n firestore: FirebaseFirestore.Firestore,\n input: {\n job: AiJob\n unitJobId: string\n store: AiSiteStorePagesInput\n outputs: readonly AiJobOutput[]\n sitePages: readonly AiStoreSitePage[]\n builtLayouts: ReadonlySet<string>\n now: Date\n },\n write: typeof writeAiStoreLinksLayoutDraft = writeAiStoreLinksLayoutDraft,\n): Promise<AiJobOutput[]> {\n const outputs = input.outputs.map((output) => ({ ...output }))\n const layoutId = input.store.layoutId\n // A layout this build made was told the store's links as it was compiled.\n if (layoutId && input.builtLayouts.has(layoutId)) return outputs\n const written = new Set(outputs.map((output) => output.proposal?.['storePage']).filter((key): key is string => typeof key === 'string'))\n const links = aiBuildStoreLayoutLinks(input.store.pages, written)\n const missing = (): AiJobOutput[] => {\n const [first, ...rest] = outputs\n const state: AiBuildStoreLinksState = 'missing'\n return first ? [{ ...first, proposal: { ...(first.proposal ?? {}), storeLinks: state } }, ...rest] : outputs\n }\n if (!layoutId || !input.job.hostId) return missing()\n const hrefs = new Set([...links.header, ...(links.cart ? [links.cart] : []), ...links.footer].map((link) => link.href.slice(1)))\n const screenPaths: Record<string, string> = {}\n for (const page of input.sitePages) {\n const slug = page.slug.replace(/^\\/+/, '').split('/')[0].toLowerCase()\n if (page.id && hrefs.has(slug)) screenPaths[page.id] = slug\n }\n const draft = await write(firestore, {\n hostId: input.job.hostId,\n layoutId,\n versionId: `${input.unitJobId}-links`.slice(0, 64),\n links,\n screenPaths,\n uid: input.job.createdBy,\n aiJobId: aiOriginJobId(input.job),\n now: input.now,\n })\n if (draft.status === 'present') return outputs\n if (draft.status === 'gone') return missing()\n const versionId = draft.versionId\n const layout: AiJobOutput[] = versionId\n ? [\n {\n resource: 'layout',\n id: draft.layoutId,\n versionId,\n hostId: input.job.hostId,\n hostSubdomain: outputs.find((output) => output.hostSubdomain)?.hostSubdomain,\n label: draft.name,\n note: 'A new draft version with Account and policy links. Visitors see it once it is published.',\n proposal: { storeLinks: 'draft' satisfies AiBuildStoreLinksState, links, screenPaths },\n },\n ]\n : []\n return [...(draft.status === 'unrecognized' ? missing() : outputs), ...layout]\n}\n\n/** The store's links a build drafted into the site's layout (AGL-3676), as its publish puts them live; `null` where it drafted none. */\nexport function aiBuildStoreLinksToPublish(outputs: readonly AiJobOutput[]): AiSitePublishStoreLinks | null {\n // The newest: a retried store drafts its links again after the first attempt's (AGL-3739).\n const draft = [...outputs]\n .reverse()\n .find((output) => output.resource === 'layout' && output.proposal?.['storeLinks'] === 'draft' && output.versionId)\n if (!draft?.versionId) return null\n return {\n layoutId: draft.id,\n versionId: draft.versionId,\n links: draft.proposal?.['links'] as AiStoreLayoutLinks,\n screenPaths: (draft.proposal?.['screenPaths'] ?? {}) as Record<string, string>,\n }\n}\n\n/** Whether a build's workspace spends the Free taste. */\nexport function aiBuildFreeTaste(org: object | null | undefined): boolean {\n return Boolean(org) && resolveEffectivePlan(org as never) === 'free'\n}\n\n/** The site document a gate reads, or `null`. */\nasync function readHost(firestore: FirebaseFirestore.Firestore, hostId: string | null) {\n if (!hostId) return null\n return ((await firestore.collection('hosts').doc(hostId).get()).data() ?? null) as Record<string, unknown> | null\n}\n\nexport function createAiJobBuildStep(deps: AiJobBuildStepDeps = {}): AiJobStepRunner {\n const runnerFor = deps.runnerFor ?? aiJobStepRunnerFor\n const writerFor = deps.writerFor ?? aiPluginDraftWriter\n const opsFor = deps.opsFor ?? ((context) => aiBuildOps(context))\n const admissionFor = deps.admissionFor ?? aiJobAdmissionRefusal\n const pluginAdmission = deps.pluginAdmission ?? aiPluginDraftAdmissionRefusal\n const readNodes = deps.readNodes ?? readAiDraftNodes\n const publish = deps.publish ?? aiPublishGuidedSite\n const storePagesRunner = deps.storePages ?? runAiSiteStorePagesUnit\n const storePagesRefusal = deps.storePagesRefusal ?? aiSiteStorePagesRefusal\n const readSitePages = deps.readSitePages ?? readAiStoreSitePages\n const writeStoreLinks = deps.writeStoreLinks ?? writeAiStoreLinksLayoutDraft\n\n return async (context): Promise<AiJobStepOutcome> => {\n const { job, firestore } = context\n const model = context.modelFor?.('job.plan') ?? aiModelForStep('job.plan')\n const plan = aiConfirmedPlan(job)\n if (!plan) return { ...aiUnspentOutcome(model), failure: AI_BUILD_NO_PLAN_COPY }\n const org = (context.org ?? null) as Partial<AglynOrgBilling> | null\n const units = aiBuildUnits(plan)\n const ordered = aiBuildOrder(units) ?? units\n const starting = !job.items?.length\n const ledger = starting ? aiBuildInitialLedger(units) : (job.items as AiJobItemLedger[])\n const init = starting ? { items: ledger } : {}\n const unit = aiBuildNextUnit(ordered, ledger)\n const rows = new Map(ledger.map((row) => [row.slot, row]))\n const host = await readHost(firestore, job.hostId ?? null)\n const ops = await opsFor({\n orgId: job.orgId,\n hostId: job.hostId ?? null,\n org,\n host,\n freeTaste: aiBuildFreeTaste(org),\n })\n\n /** Whether units other than this one are still to build. */\n const othersOpen = (slot: string) =>\n ordered.some((one) => one.slot !== slot && aiBuildItemOpen(rows.get(one.slot) ?? { status: 'pending' }))\n\n /**\n * The build's last pass puts its pages live, where it was asked and\n * confirmed. Once it has, Try again's last pass puts only the pages the\n * retry built live (AGL-3739, AGL-3730's fix for a site start),\n * merged into the record of the first.\n */\n const finish = async (\n outcome: AiJobStepOutcome,\n extraPages: readonly AiJobOutput[] = [],\n extraOutputs: readonly AiJobOutput[] = [],\n ): Promise<AiJobStepOutcome> => {\n if (!aiJobPublishesBuild(job) || !job.hostId) return outcome\n const previous = job.sitePublish ?? null\n const retry = Boolean(previous?.published.length)\n const already = new Set((previous?.published ?? []).map((page) => page.id))\n // A record template renders once per record only once its binding is\n // saved, so it is never published at its own address (AGL-3616).\n // A store's own pages (AGL-3676) go live with the pages the build planned.\n const pageIds = new Set(\n units\n .filter(\n (one) =>\n ((one.screen && !one.screen.record) || one.op === AI_BUILD_STORE_OP) &&\n aiBuildItemDelivered(rows.get(one.slot) ?? { status: 'pending' }),\n )\n .flatMap((one) => rows.get(one.slot)?.outputs ?? []),\n )\n const built = [\n ...(job.outputs ?? []).filter((output) => output.resource === 'screen' && pageIds.has(output.id)),\n ...extraPages,\n ]\n const pages = built.filter((page) => !already.has(page.id))\n if (!pages.length) return outcome\n // A canceled build never puts anything live (AGL-3616): its pages stay drafts.\n if (await aiJobCancelAsked(firestore, job, context.signal)) return outcome\n // The store pages a layout this build made links and that were not written come out of it.\n const storePages = aiBuildStorePagesOf(plan)\n const live = new Set(built.map((page) => page.proposal?.['storePage']).filter(Boolean))\n const unwrittenHrefs = storePages\n ? aiStorePagesToWrite(storePages.pages).filter((page) => !live.has(page.key)).map((page) => page.href)\n : []\n // A retry puts the store's links live only with store pages it built:\n // the first publish's links draft is live already, and a person may have edited it since.\n const storeLinks =\n !retry || pages.some((page) => page.proposal?.['storePage'])\n ? aiBuildStoreLinksToPublish([...(job.outputs ?? []), ...extraOutputs])\n : null\n const sitePublish = await publish(firestore, {\n job,\n outputs: pages,\n now: context.now,\n ...(unwrittenHrefs.length ? { unwrittenHrefs } : {}),\n ...(storeLinks ? { storeLinks } : {}),\n ...(retry ? { retry: true } : {}),\n }).catch((error: unknown) => {\n console.error('ai build publish threw', { orgId: job.orgId, jobId: job.$id, error })\n return null\n })\n if (!sitePublish) return outcome\n return { ...outcome, sitePublish: previous ? aiMergeSitePublish(previous, sitePublish) : sitePublish }\n }\n\n if (!unit) return finish({ ...aiUnspentOutcome(model), ...init })\n\n const settle = (item: AiJobItemOutcome, spent: AiJobStepOutcome = aiUnspentOutcome(model)): AiJobStepOutcome => ({\n ...spent,\n ...init,\n item,\n ...(item.status === 'running' || othersOpen(unit.slot) ? { continue: true } : {}),\n })\n\n // What its dependencies came to.\n const degradation = aiBuildDegradation(unit, { units, ledger, ops })\n if (degradation.skip) {\n return settle({ slot: unit.slot, status: 'skipped', note: degradation.skip, degradedBy: degradation.degradedBy })\n }\n // A store's own pages (AGL-3676): written by code, behind the site start's gate.\n if (unit.op === AI_BUILD_STORE_OP) {\n if (!job.hostId) return settle({ slot: unit.slot, status: 'skipped', note: 'Not built: open the site first.' })\n if (rows.get(unit.slot)?.status !== 'running') {\n const refusal = await storePagesRefusal({ ...context, job }).catch((error: unknown) => {\n console.error('ai build store pages admission failed', { orgId: job.orgId, jobId: job.$id, error })\n return AI_BUILD_UNIT_EMPTY_COPY\n })\n if (refusal) return settle({ slot: unit.slot, status: 'skipped', note: `Not built: ${refusal}` })\n }\n const unitJobId = aiBuildUnitJobId(job, unit)\n const sitePages = await readSitePages(firestore, job.hostId)\n const input = aiBuildStorePagesInput(job, { unitJobId, sitePages, units, ledger })\n if (!input) return settle({ slot: unit.slot, status: 'skipped', note: aiBuildUnavailableCopy('store page') })\n if (!aiStorePagesToWrite(input.pages).length) {\n return settle({ slot: unit.slot, status: 'skipped', note: AI_BUILD_STORE_PAGES_PRESENT_NOTE })\n }\n const derived: AiJob = {\n ...job,\n $id: unitJobId,\n kind: 'text',\n steps: [],\n outputs: [],\n items: null,\n plan: null,\n inputs: { ...job.inputs, originJobId: aiOriginJobId(job), [AI_SITE_STORE_PAGES_INPUT]: input },\n }\n let outcome: AiJobStepOutcome\n try {\n outcome = await storePagesRunner({ ...context, job: derived })\n } catch (error) {\n if (aiUnitErrorRetryable(error)) throw error\n console.error('ai build store pages threw', { orgId: job.orgId, jobId: job.$id, error })\n return settle(failed(unit.slot, { ours: true, reason: 'step-failure', message: AI_BUILD_UNIT_EMPTY_COPY }))\n }\n const stopped = aiUnitFailure(unit.slot, outcome)\n if (stopped) return settle(stopped, aiUnitSpend(outcome))\n // The site's own header and footer link them (AGL-3676), in a draft\n // version of its layout; a layout this build made already does.\n const builtLayouts = new Set(\n [...aiBuildBuiltRefs(units, ledger, job.outputs ?? []).values()].filter((entry) => entry.kind === 'layout').map((entry) => entry.id),\n )\n const outputs = await aiBuildStoreLinksOutputs(\n firestore,\n { job, unitJobId, store: input, outputs: outcome.outputs, sitePages, builtLayouts, now: context.now },\n writeStoreLinks,\n ).catch((error: unknown) => {\n console.error('ai build store links not written', { orgId: job.orgId, jobId: job.$id, error })\n return outcome.outputs\n })\n const ids = outputs.map((output) => output.id)\n const done = settle({ slot: unit.slot, status: 'succeeded', outputs: ids, note: AI_SITE_STORE_PAGES_NOTE }, { ...aiUnitSpend(outcome), outputs })\n if (done.continue) return done\n rows.set(unit.slot, { ...(rows.get(unit.slot) as AiJobItemLedger), status: 'succeeded', outputs: ids })\n return finish(\n done,\n outputs.filter((output) => output.resource === 'screen'),\n outputs,\n )\n }\n\n const capability = ops.get(unit.op)\n const noun = capability?.noun ?? unit.op\n if (!capability) return settle({ slot: unit.slot, status: 'skipped', note: aiBuildUnavailableCopy(noun) })\n const degraded = degradation.degradedBy.length > 0\n const note = degradation.notes.length ? degradation.notes.join(' ') : null\n\n // Another plugin's resource: its writer, with the content its capability derives.\n if (capability.draftResource) {\n const item = unit.item\n const writer = writerFor(capability.draftResource)\n if (!item || !writer || !job.hostId) {\n return settle({ slot: unit.slot, status: 'skipped', note: aiBuildUnavailableCopy(noun) })\n }\n const admission: AiJobAdmissionContext = {\n firestore,\n orgId: job.orgId,\n hostId: job.hostId,\n inputs: {},\n org,\n uid: job.createdBy,\n }\n const refusal = await pluginAdmission(admission, {\n kind: 'build',\n drafts: [{ resource: capability.draftResource, label: capability.noun }],\n writerFor,\n })\n if (refusal) return settle({ slot: unit.slot, status: 'skipped', note: `Not built: ${refusal.error}` })\n const dependencies: Record<string, { op: string; id: string }> = {}\n for (const slot of unit.deps) {\n const dep = units.find((one) => one.slot === slot)\n const row = rows.get(slot)\n if (!dep || !row || !aiBuildItemDelivered(row) || !row.outputs.length) continue\n dependencies[`new:${dep.label}`] = { op: dep.op, id: row.outputs[0] }\n }\n const content = capability.draftContent?.({ name: item.name, args: item.args }, { hostId: job.hostId, dependencies }) ?? item.args\n const checked = writer.check(content, { hostId: job.hostId })\n if (checked.ok === false) {\n return settle(\n failed(unit.slot, { ours: true, reason: 'step-failure', message: checked.problems[0] ?? AI_BUILD_UNIT_EMPTY_COPY }),\n )\n }\n const id = aiBuildUnitJobId(job, unit)\n const written = await writer.write({\n orgId: job.orgId,\n hostId: job.hostId,\n uid: job.createdBy,\n org,\n now: context.now,\n // Drafts of one build share what must not repeat (a cover photo) and read its business (AGL-3755).\n act: { id: aiOriginJobId(job), business: aiSiteWords(job.inputs).about || job.brief || '' },\n id,\n name: item.name,\n content,\n })\n if (written.ok === false) {\n return settle(failed(unit.slot, { ours: false, reason: 'review', message: written.error }))\n }\n const output: AiJobOutput = {\n resource: 'draft',\n id: written.id,\n versionId: written.versionId,\n hostId: job.hostId,\n label: written.name,\n draftResource: capability.draftResource,\n // A resource with no draft state is live once written (AGL-3745, AGL-3746).\n note: aiBuildItemOutputNote(capability, written),\n }\n return settle(\n {\n slot: unit.slot,\n status: degraded ? 'degraded' : 'succeeded',\n outputs: [written.id],\n note,\n ...(degraded ? { degradedBy: degradation.degradedBy } : {}),\n },\n { ...aiUnspentOutcome(model), outputs: [output] },\n )\n }\n\n // This plugin's own runner, under a job derived for the unit.\n const kind = aiBuildUnitJobKind(unit, ops)\n const runner = kind ? runnerFor(kind) : null\n if (!kind || !runner) return settle({ slot: unit.slot, status: 'skipped', note: aiBuildUnavailableCopy(noun) })\n const derived = aiBuildUnitJob(job, unit, { kind, units, ledger, ops, briefLines: degradation.briefLines })\n // An item's kind is asked its own admission first (a campaign's plan,\n // a template's subject), once, before its first pass.\n if (unit.item && rows.get(unit.slot)?.status !== 'running') {\n const refusal = await admissionFor(kind, {\n firestore,\n orgId: job.orgId,\n hostId: job.hostId ?? null,\n inputs: derived.inputs,\n org,\n uid: job.createdBy,\n }).catch((error: unknown) => {\n console.error('ai build item admission failed', { orgId: job.orgId, jobId: job.$id, slot: unit.slot, error })\n return { status: 403 as const, error: AI_BUILD_UNIT_EMPTY_COPY }\n })\n if (refusal) return settle({ slot: unit.slot, status: 'skipped', note: `Not built: ${refusal.error}` })\n }\n\n let outcome: AiJobStepOutcome\n try {\n outcome = await runner({ ...context, job: derived })\n } catch (error) {\n // A provider that will answer later is the machine's to retry; anything\n // else is this item's failure, and the build goes on.\n if (aiUnitErrorRetryable(error)) throw error\n console.error('ai build unit threw', { orgId: job.orgId, jobId: job.$id, slot: unit.slot, error })\n return settle(failed(unit.slot, { ours: true, reason: 'provider', message: AI_BUILD_UNIT_EMPTY_COPY }))\n }\n const spent = aiUnitSpend(outcome)\n const ids = outcome.outputs.map((output) => output.id)\n const stopped = aiUnitFailure(unit.slot, outcome)\n if (stopped) return settle(stopped, spent)\n // A page counts as built only when its plan's sections are in it (AGL-3596).\n if (unit.screen && job.hostId) {\n const page = outcome.outputs.find((output) => output.resource === 'screen')\n const written =\n page !== undefined &&\n (await aiSitePageWritten(\n firestore,\n {\n hostId: job.hostId,\n unitJobId: derived.$id,\n screen: unit.screen,\n draftId: page.id,\n layoutLanguage: aiJobUsesLayoutLanguage(derived),\n },\n readNodes,\n ))\n if (!written) {\n return settle(\n failed(unit.slot, { ours: true, reason: 'step-failure', message: AI_BUILD_PAGE_NOT_WRITTEN_COPY }),\n { ...spent, outputs: outcome.outputs.filter((output) => output.resource !== 'screen') },\n )\n }\n }\n const done = settle(\n {\n slot: unit.slot,\n status: degraded ? 'degraded' : 'succeeded',\n outputs: ids,\n note,\n ...(degraded ? { degradedBy: degradation.degradedBy } : {}),\n },\n spent,\n )\n if (done.continue) return done\n // The last unit: what was built goes live where it was asked and confirmed.\n rows.set(unit.slot, { ...(rows.get(unit.slot) as AiJobItemLedger), status: degraded ? 'degraded' : 'succeeded', outputs: ids })\n return finish(done, unit.screen ? outcome.outputs.filter((output) => output.resource === 'screen') : [])\n }\n}\n\nexport const runAiJobBuildStep = createAiJobBuildStep()\n\n/**\n * The least time a build's next pass needs: what the step that builds its\n * next unit registers for the job derived for it; a page pass's when the\n * next unit is another plugin's draft, which asks no model.\n */\nexport function aiBuildJobRunMinimumMs(job: AiJob): number {\n const plan = aiConfirmedPlan(job)\n if (!plan) return AI_JOB_PAGE_STEP_MINIMUM_MS\n const units = aiBuildUnits(plan)\n const ordered = aiBuildOrder(units) ?? units\n const ledger = job.items?.length ? job.items : aiBuildInitialLedger(units)\n const unit = aiBuildNextUnit(ordered, ledger)\n if (!unit) return AI_JOB_PAGE_STEP_MINIMUM_MS\n const kind: AiJobKind | null = unit.screen\n ? 'page'\n : unit.creation\n ? (CREATION_JOB_KINDS[unit.creation.kind] ?? null)\n : (AI_BUILD_ITEM_RUNNER_KINDS[unit.op] ?? null)\n if (!kind) return AI_JOB_PAGE_STEP_MINIMUM_MS\n return aiJobStepRunMinimumMs(aiBuildUnitJob(job, unit, { kind, units, ledger, ops: new Map() }))\n}\n\n/** The runner kinds this plugin's own item operations use, for the time a pass needs without the registry. */\nconst AI_BUILD_ITEM_RUNNER_KINDS: Readonly<Record<string, AiJobKind>> = {\n template: 'template',\n campaign: 'campaign',\n workflow: 'workflow',\n function: 'logic',\n edit: 'edit',\n navigation: 'navigation',\n duplicate: 'duplicate',\n settings: 'settings',\n media: 'media',\n tracking: 'tracking',\n}\n\n/**\n * What a Free build's credits say before it runs (AGL-3722), on its measured\n * p90 rather than its ceiling: `null` when what is left this month covers the\n * p90 — or when nothing is known about what is left, since each pass's\n * reservation still decides — and `null` too for a build the person chose\n * to build as far as it goes (`confirmed`), whose prompt `onConfirmed` is\n * told so the door records it. Otherwise a 409 carrying the prompt: the\n * range, what is left, and the smaller first build. Nothing left at all is a\n * 429. Read off the same two walls the reservation refuses at\n * (`readFreeAiCreditsLeft`), net of give-backs.\n */\nexport async function aiBuildFreeCreditsRefusal(input: {\n firestore: FirebaseFirestore.Firestore\n orgId: string\n org: object | null\n range: AiCreditRange\n smaller?: AiCreditsSmaller | null\n confirmed?: boolean\n onConfirmed?: (prompt: AiCreditsPrompt) => void\n now: Date\n freeCreditsLeft?: typeof readFreeAiCreditsLeft\n}): Promise<AiJobAdmissionRefusal | null> {\n const read = input.freeCreditsLeft ?? readFreeAiCreditsLeft\n const credits = await read(input.firestore, { orgId: input.orgId, org: input.org, now: input.now })\n if (!credits) return null\n if (credits.left <= 0) return { status: 429, error: aiFreeCreditsNoneLeftText(credits.resetsOn) }\n const prompt = aiCreditsPromptFor(input.range, credits, input.smaller ?? null)\n if (!prompt) return null\n if (!input.confirmed) {\n return { status: 409, error: aiCreditsPromptText(prompt, 'build'), code: AI_CREDITS_CONFIRM_CODE, credits: prompt }\n }\n input.onConfirmed?.(prompt)\n return null\n}\n\nexport interface AiBuildAdmissionDeps {\n opsFor?: (context: AiBuildOpsContext) => Promise<AiBuildOps>\n freeCreditsLeft?: typeof readFreeAiCreditsLeft\n ownerOf?: typeof resolveOrgIdForHost\n now?: () => Date\n}\n\n/**\n * A build is admitted for a site of the job's own org where a page can be\n * built; and confirmed only for a plan it can build here — its shape, its\n * operations as this site has them, and on the Free taste a measured p90\n * the month's Free credits still cover — or the person's go-ahead to build\n * what fits (AGL-3722).\n */\nexport function createAiBuildJobAdmission(deps: AiBuildAdmissionDeps = {}): AiJobAdmission {\n const opsFor = deps.opsFor ?? ((context) => aiBuildOps(context))\n const ownerOf = deps.ownerOf ?? resolveOrgIdForHost\n return async (context) => {\n if (!context.hostId) return { status: 400, error: 'Open the site to build on before asking Assist to build' }\n const owner = await ownerOf(context.hostId)\n if (!owner || owner !== context.orgId) return { status: 404, error: 'Unknown site' }\n if (!aiJobStepRunnerFor('page')) return { status: 400, error: 'Building from a request is not available yet.' }\n const plan = context.plan\n if (!plan) return null\n const org = context.org as Partial<AglynOrgBilling> | null\n const freeTaste = aiBuildFreeTaste(org)\n const host = await readHost(context.firestore, context.hostId)\n const ops = await opsFor({ orgId: context.orgId, hostId: context.hostId, org, host, freeTaste })\n const shape = aiBuildPlanShapeRefusal(plan, { freeTaste, ops })\n if (shape) return { status: 400, error: shape }\n // Something only the person can give (AGL-3751): asked, never built without.\n const missing = aiBuildPlanMissingInput(plan, ops)\n if (missing) return { status: 400, error: missing }\n if (freeTaste) {\n const refusal = await aiBuildFreeCreditsRefusal({\n firestore: context.firestore,\n orgId: context.orgId,\n org,\n range: aiBuildCreditRange(plan, { ops }),\n smaller: aiBuildSmaller(plan, ops),\n confirmed: context.creditsConfirmed === true,\n onConfirmed: context.onCreditsConfirmed,\n now: deps.now?.() ?? new Date(),\n freeCreditsLeft: deps.freeCreditsLeft,\n })\n if (refusal) return refusal\n }\n return null\n }\n}\n\nexport const aiBuildJobAdmission = createAiBuildJobAdmission()\n\n/**\n * Registers the build with the least time a pass needs, the time its next\n * pass needs, the passes its largest plan may take, and its admission.\n */\nexport function registerAiBuildJob(): void {\n registerAiJobStep('build', runAiJobBuildStep, {\n minimumMs: AI_JOB_PAGE_STEP_MINIMUM_MS,\n minimumMsFor: aiBuildJobRunMinimumMs,\n })\n registerAiJobStepPasses('build', AI_BUILD_MAX_PASSES)\n registerAiJobAdmission('build', aiBuildJobAdmission)\n}\n"],"names":["aiJobCancelAsked","resolveEffectivePlan","resolveOrgIdForHost","AI_BUILD_LIMITS","AI_BUILD_MADE_INPUT","AI_BUILD_PUBLISH_INPUT","aiArticle","aiBuildCreditRange","aiBuildDegradation","aiBuildInitialLedger","aiBuildItemDelivered","aiBuildItemOpen","aiBuildNextUnit","aiBuildOrder","aiBuildItemOutputNote","aiBuildPlacedItemLines","aiBuildPlanMissingInput","aiBuildPlanShapeRefusal","aiBuildSmaller","aiBuildUnits","isAiPlanNewRef","AI_SITE_MAX_SECTIONS","AI_CREDITS_CONFIRM_CODE","aiCreditsPromptFor","aiCreditsPromptText","aiFreeCreditsNoneLeftText","aiSiteWords","readFreeAiCreditsLeft","aiModelForStep","AI_BUILD_UNIT_EMPTY_COPY","aiBuildBuiltRefs","aiUnitErrorRetryable","aiUnitFailure","aiUnitSpend","aiBuildOps","aiJobAdmissionRefusal","registerAiJobAdmission","aiOriginJobId","readAiDraftNodes","aiConfirmedPlan","aiUnspentOutcome","AI_JOB_PAGE_STEP_MINIMUM_MS","aiPluginDraftAdmissionRefusal","aiPluginDraftWriter","aiSitePageWritten","aiSiteResolvedRef","AI_LAYOUT_SITE_PAGES_INPUT","aiLayoutSitePagesOfPlan","AI_LAYOUT_FORM_PAGE_INPUT","AI_LAYOUT_LANGUAGE_INPUT","aiJobUsesLayoutLanguage","aiLayoutFormPageOfPlan","aiDatasetListingsOf","AI_SITE_EVENT_OP","aiEventsListings","AI_FORM_DATASET_MADE_INPUT","AI_LAYOUT_LISTINGS_INPUT","AI_BUILD_STORE_OP","AI_BUILD_STORE_PAGES_PRESENT_NOTE","aiBuildStoreLayoutLinks","aiBuildStoreLayoutOf","aiBuildStorePagesOf","aiBuildStorePagesStillMissing","writeAiStoreLinksLayoutDraft","AI_SITE_STORE_LINKS_INPUT","AI_SITE_STORE_PAGES_NOTE","aiStoreFrameLinks","aiStorePagesToWrite","AI_SITE_STORE_PAGES_INPUT","aiSiteStorePageId","aiSiteStorePagesRefusal","runAiSiteStorePagesUnit","AI_JOB_BRIEF_MAX_CHARS","aiJobPublishesBuild","aiMergeSitePublish","aiPublishGuidedSite","AI_PLANNED_JOB_KINDS","aiJobStepRunMinimumMs","aiJobStepRunnerFor","registerAiJobStep","registerAiJobStepPasses","AI_BUILD_NO_PLAN_COPY","aiBuildUnavailableCopy","noun","AI_BUILD_PAGE_NOT_WRITTEN_COPY","AI_BUILD_MAX_PASSES","units","CREATION_JOB_KINDS","layout","form","component","email","aiBuildUnitJobKind","unit","ops","screen","creation","kind","runnerKind","get","op","aiBuildUnitJobId","job","id","item","$id","slot","aiBuildUnitJob","context","plan","unitPlan","built","ledger","outputs","labels","entry","values","label","brief","trim","reuse","create","screens","items","placedByScreens","Set","flatMap","sections","section","uses","filter","has","duplicateOf","writesTo","push","name","why","purpose","builtLayout","template","record","dataset","map","ref","title","slug","placedByCode","includes","fields","briefLines","inputs","args","originJobId","rows","Map","row","made","pages","one","layouts","entries","length","madeFor","formPage","datasets","find","toLowerCase","some","listings","eventUnits","ledgerRows","written","Boolean","planned","storePages","steps","join","slice","failed","failure","extra","status","readAiStoreSitePages","firestore","hostId","snapshot","collection","doc","select","docs","String","layoutId","aiBuildStorePagesInput","kept","own","page","unitJobId","key","sitePages","shop","replace","split","facts","shopPath","aiBuildStoreLinksOutputs","input","write","output","store","builtLayouts","proposal","links","missing","first","rest","state","storeLinks","hrefs","header","cart","footer","link","href","screenPaths","draft","versionId","uid","createdBy","aiJobId","now","resource","hostSubdomain","note","aiBuildStoreLinksToPublish","reverse","aiBuildFreeTaste","org","readHost","data","createAiJobBuildStep","deps","runnerFor","writerFor","opsFor","admissionFor","pluginAdmission","readNodes","publish","storePagesRunner","storePagesRefusal","readSitePages","writeStoreLinks","model","modelFor","ordered","starting","init","host","orgId","freeTaste","othersOpen","finish","outcome","extraPages","extraOutputs","previous","sitePublish","retry","published","already","pageIds","signal","live","unwrittenHrefs","catch","error","console","jobId","settle","spent","continue","degradation","skip","degradedBy","refusal","derived","ours","reason","message","stopped","ids","done","set","capability","degraded","notes","draftResource","writer","admission","drafts","dependencies","dep","content","draftContent","checked","check","ok","problems","act","business","about","runner","undefined","draftId","layoutLanguage","runAiJobBuildStep","aiBuildJobRunMinimumMs","AI_BUILD_ITEM_RUNNER_KINDS","campaign","workflow","function","edit","navigation","duplicate","settings","media","tracking","aiBuildFreeCreditsRefusal","read","freeCreditsLeft","credits","left","resetsOn","prompt","range","smaller","confirmed","code","onConfirmed","createAiBuildJobAdmission","ownerOf","owner","shape","creditsConfirmed","onCreditsConfirmed","Date","aiBuildJobAdmission","registerAiBuildJob","minimumMs","minimumMsFor"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/jobs/ai-job-build-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\nimport { aiJobCancelAsked } from './ai-job-cancel'\nimport type { AglynOrgBilling } from '@aglyn/aglyn/foundation/definitions/org-billing.types'\nimport type { PluginAiCapability } from '@aglyn/aglyn/plugin-manager/plugin-ai-capabilities'\nimport { resolveEffectivePlan } from '@aglyn/aglyn/app-utils/plan-entitlements'\nimport { resolveOrgIdForHost } from '@aglyn/tenant-data-admin/server/organizations'\nimport {\n AI_BUILD_LIMITS,\n AI_BUILD_MADE_INPUT,\n AI_BUILD_PUBLISH_INPUT,\n aiArticle,\n aiBuildCreditRange,\n aiBuildDegradation,\n aiBuildInitialLedger,\n aiBuildItemArgRefs,\n aiBuildItemDelivered,\n aiBuildItemOpen,\n aiBuildNextUnit,\n aiBuildOrder,\n aiBuildItemOutputNote,\n aiBuildPlacedItemLines,\n aiBuildPlanMissingInput,\n aiBuildPlanShapeRefusal,\n aiBuildRefName,\n aiBuildSmaller,\n aiBuildUnits,\n type AiBuildMade,\n type AiBuildOps,\n type AiBuildUnit,\n} from '../model/ai-build-job'\nimport { isAiPlanNewRef, type AiBuildPlanCreateKind } from '../model/ai-build-plan'\nimport type {\n AiJob,\n AiJobItemFailure,\n AiJobItemLedger,\n AiJobKind,\n AiJobOutput,\n AiJobPlan,\n} from '../model/ai-jobs.types'\nimport { AI_SITE_MAX_SECTIONS } from '../model/ai-site-job'\nimport {\n AI_CREDITS_CONFIRM_CODE,\n aiCreditsPromptFor,\n aiCreditsPromptText,\n type AiCreditRange,\n type AiCreditsPrompt,\n type AiCreditsSmaller,\n} from '../model/ai-credit-estimate'\nimport { aiFreeCreditsNoneLeftText, aiSiteWords } from '../model/ai-site-job'\nimport { readFreeAiCreditsLeft } from '../usage/free-ai-credits-left'\nimport { aiModelForStep } from '../providers/routing'\nimport {\n AI_BUILD_UNIT_EMPTY_COPY,\n aiBuildBuiltRefs,\n aiUnitErrorRetryable,\n aiUnitFailure,\n aiUnitSpend,\n} from './ai-build-unit-outcome'\nimport { aiBuildOps, type AiBuildOpsContext } from './ai-build-capabilities'\nimport {\n aiJobAdmissionRefusal,\n registerAiJobAdmission,\n type AiJobAdmission,\n type AiJobAdmissionContext,\n type AiJobAdmissionRefusal,\n} from './ai-job-admission'\nimport { aiOriginJobId } from './ai-job-draft-ids'\nimport { readAiDraftNodes } from './ai-job-drafts'\nimport { aiConfirmedPlan, aiUnspentOutcome } from './ai-job-generation'\nimport { AI_JOB_PAGE_STEP_MINIMUM_MS } from './ai-job-page-budget'\nimport {\n aiPluginDraftAdmissionRefusal,\n aiPluginDraftWriter,\n type AiPluginDraftWriterLookup,\n} from './ai-job-plugin-drafts'\nimport { aiSitePageWritten, aiSiteResolvedRef } from './ai-job-site-step'\nimport { AI_LAYOUT_SITE_PAGES_INPUT, aiLayoutSitePagesOfPlan } from './ai-job-layout-site-pages'\nimport { AI_LAYOUT_FORM_PAGE_INPUT, AI_LAYOUT_LANGUAGE_INPUT, aiJobUsesLayoutLanguage, aiLayoutFormPageOfPlan } from './ai-job-page-language'\nimport { aiDatasetListingsOf } from './ai-job-site-datasets'\nimport { AI_SITE_EVENT_OP, aiEventsListings } from './ai-job-site-events'\nimport { AI_FORM_DATASET_MADE_INPUT } from './ai-job-form-dataset'\nimport { AI_LAYOUT_LISTINGS_INPUT } from '../layout-language/ai-layout-listings'\nimport {\n AI_BUILD_STORE_OP,\n AI_BUILD_STORE_PAGES_PRESENT_NOTE,\n aiBuildStoreLayoutLinks,\n aiBuildStoreLayoutOf,\n aiBuildStorePagesOf,\n aiBuildStorePagesStillMissing,\n type AiBuildStoreLinksState,\n type AiStoreSitePage,\n} from '../model/ai-build-store-pages'\nimport type { AiStoreLayoutLinks } from '../model/ai-layout-store-links'\nimport { writeAiStoreLinksLayoutDraft } from './ai-job-store-links-layout'\nimport type { AiSitePublishStoreLinks } from './ai-site-publish'\nimport {\n AI_SITE_STORE_LINKS_INPUT,\n AI_SITE_STORE_PAGES_NOTE,\n aiStoreFrameLinks,\n aiStorePagesToWrite,\n} from '../model/ai-site-store-pages'\nimport {\n AI_SITE_STORE_PAGES_INPUT,\n aiSiteStorePageId,\n aiSiteStorePagesRefusal,\n runAiSiteStorePagesUnit,\n type AiSiteStorePagesInput,\n} from './ai-job-site-store-pages'\nimport {\n AI_JOB_BRIEF_MAX_CHARS,\n type AiJobItemOutcome,\n type AiJobStepOutcome,\n type AiJobStepRunner,\n} from './ai-job-text-step'\nimport { aiJobPublishesBuild, aiMergeSitePublish, aiPublishGuidedSite } from './ai-site-publish'\nimport {\n AI_PLANNED_JOB_KINDS,\n aiJobStepRunMinimumMs,\n aiJobStepRunnerFor,\n registerAiJobStep,\n registerAiJobStepPasses,\n} from './ai-jobs'\n\n/**\n * The build step (AGL-3616): the generation step of a `build` job, run once\n * the member confirmed the plan their request produced.\n *\n * Like the site scaffold it generalizes, it builds nothing itself and asks no\n * model of its own. Each pass takes the next unit in dependency order and\n * hands it to what builds that kind of thing — a page, layout, form,\n * component, email design or template to this plugin's own step, under a job\n * derived for the unit; another plugin's resource to that plugin's writer on\n * the resource-draft seam, with the content the owner's capability derives\n * from the item's arguments. One unit, one pass, one recorded spend.\n *\n * ── Settled item by item ────────────────────────────────────────────────\n *\n * Where a unit stands is read from the job's ITEM LEDGER, never from counting\n * outputs: the machine writes each pass's row in the transaction that\n * records its spend (`recordStep`). A unit that fails is a FAILED ROW, not a\n * failed job: the pass reports it, the machine gives back that item's spend\n * where the failure was ours, and the next pass builds the next unit. What\n * depended on it is built without it, or skipped where it cannot stand\n * without it (`aiBuildDegradation`). The machine ends the job when nothing is\n * left: `done` when anything was delivered, `failed` — its planning given\n * back too — when nothing was.\n *\n * ── Drafts, unless asked and confirmed ───────────────────────────────────\n *\n * Every unit writes the draft its own kind writes, which nothing publishes.\n * Only a build whose request asked to publish AND whose member ticked the\n * plan card's box puts its built pages live, once, on its last pass, through\n * the guided start's publish.\n */\n\n/** What a build answers with no confirmed plan to build. */\nexport const AI_BUILD_NO_PLAN_COPY = 'This build has no confirmed plan to build.'\n\n/** What a unit says when nothing on this site builds its operation any more. */\nexport const aiBuildUnavailableCopy = (noun: string): string =>\n `Not built: ${aiArticle(noun)} cannot be made on this site right now.`\n\n\n/** What a page that was reported built but holds none of its plan says. */\nexport const AI_BUILD_PAGE_NOT_WRITTEN_COPY = 'The page was not written from its plan.'\n\n\n/**\n * The most passes a build's step may take: every unit at a page's worst — its\n * sections and its listing — so a runner that never finishes is still\n * bounded while the largest plan is not. Try again starts the count over.\n */\nexport const AI_BUILD_MAX_PASSES = AI_BUILD_LIMITS.units * (AI_SITE_MAX_SECTIONS + 1) + 1\n\n/** The job kind a creation of the build is built by. */\nconst CREATION_JOB_KINDS: Partial<Record<AiBuildPlanCreateKind, AiJobKind>> = {\n layout: 'layout',\n form: 'form',\n component: 'component',\n email: 'email',\n}\n\n/** The job kind a unit is built by, where an AI runner builds it. */\nexport function aiBuildUnitJobKind(unit: AiBuildUnit, ops: AiBuildOps): AiJobKind | null {\n if (unit.screen) return 'page'\n if (unit.creation) return CREATION_JOB_KINDS[unit.creation.kind] ?? null\n const runnerKind = ops.get(unit.op)?.runnerKind\n return runnerKind ? (runnerKind as AiJobKind) : null\n}\n\n/** What the job drawer says under an item another plugin's writer made (`model/ai-build-job.ts`). */\nexport { aiBuildItemOutputNote }\n\n/**\n * An item's arguments without the list entries that link what this build\n * could not make (AGL-3832): a menu's `About => new:About` once the page\n * About failed. The item is built with the rest, and its note names what it\n * is without, so its own report never shows a `new:` reference.\n */\nexport function aiBuildItemArgsWithout(\n args: Readonly<Record<string, unknown>>,\n dropped: ReadonlySet<string> | undefined,\n): Record<string, unknown> {\n if (!dropped?.size) return { ...args }\n const links = (entry: unknown) => aiBuildItemArgRefs({ entry }).some((ref) => dropped.has(aiBuildRefName(ref)))\n return Object.fromEntries(\n Object.entries(args).map(([key, value]) => [key, Array.isArray(value) ? value.filter((entry) => !links(entry)) : value]),\n )\n}\n\n/** The id a unit's job, and so its draft, is named by. */\nexport function aiBuildUnitJobId(job: Pick<AiJob, '$id'>, unit: AiBuildUnit): string {\n return unit.creation?.id ?? unit.screen?.id ?? unit.item?.id ?? `${job.$id}-${unit.slot}`\n}\n\n/**\n * The job a unit is built under (generalizing `aiSiteUnitJob`): this job's\n * org, site, creator and model; the kind that builds the unit; a plan\n * narrowed to the unit, its `new:` references resolved to what was built and\n * the failed ones left out; and a brief that says what the unit is, what it\n * is built without, and which blocks its sections place.\n */\nexport function aiBuildUnitJob(\n job: AiJob,\n unit: AiBuildUnit,\n context: {\n kind: AiJobKind\n units: readonly AiBuildUnit[]\n ledger: readonly AiJobItemLedger[]\n ops: AiBuildOps\n briefLines?: readonly string[]\n /** The `new:` names, lowercased, of what failed and the unit is built without (`aiBuildDegradation`). */\n dropped?: ReadonlySet<string>\n },\n): AiJob {\n const plan = job.plan as AiJobPlan\n const built = aiBuildBuiltRefs(context.units, context.ledger, job.outputs ?? [])\n const labels = { ...(plan.labels ?? {}) }\n for (const entry of built.values()) labels[entry.id] = entry.label\n const brief = [job.brief.trim()]\n const unitPlan: AiJobPlan = { ...plan, labels, reuse: [...plan.reuse], create: [], screens: [] }\n delete unitPlan.items\n const placedByScreens = new Set(plan.screens.flatMap((screen) => screen.sections.flatMap((section) => section.uses)))\n if (unit.creation) {\n unitPlan.reuse = plan.reuse.filter((entry) => !placedByScreens.has(entry.id))\n unitPlan.create = [\n {\n ...unit.creation,\n duplicateOf: aiSiteResolvedRef(unit.creation.duplicateOf, built),\n // The dataset a form writes to, new or the site's own (AGL-3616); one\n // this build failed to make leaves the form as it always was.\n ...(unit.creation.writesTo ? { writesTo: aiSiteResolvedRef(unit.creation.writesTo, built) } : {}),\n },\n ]\n brief.push(`Build the ${unit.creation.kind} “${unit.creation.name}”: ${unit.creation.why}`)\n }\n if (unit.screen) {\n const screen = unit.screen\n for (const entry of built.values()) {\n unitPlan.reuse.push({ kind: entry.kind, id: entry.id, purpose: `the ${entry.kind} this request built` })\n }\n let builtLayout: string | null = null\n for (const entry of built.values()) if (entry.kind === 'layout') builtLayout = builtLayout ?? entry.id\n unitPlan.screens = [\n {\n ...screen,\n // A page whose layout failed renders inside the site's own: the page\n // step falls back to it when the plan names none.\n layout: aiSiteResolvedRef(screen.layout, built) ?? (isAiPlanNewRef(screen.layout) ? builtLayout : null),\n template: aiSiteResolvedRef(screen.template, built),\n duplicateOf: aiSiteResolvedRef(screen.duplicateOf, built),\n record: screen.record\n ? { ...screen.record, dataset: aiSiteResolvedRef(screen.record.dataset, built) ?? screen.record.dataset }\n : null,\n sections: screen.sections.map((section) => ({\n ...section,\n uses: section.uses\n .map((ref) => aiSiteResolvedRef(ref, built))\n .filter((ref): ref is string => !!ref),\n })),\n },\n ]\n brief.push(`Build the page “${screen.title}”, at ${screen.slug}.`)\n // A build's events are listed by the platform (AGL-3755), never written by the page.\n brief.push(\n ...aiBuildPlacedItemLines(unit, { units: context.units, ledger: context.ledger, ops: context.ops, placedByCode: [AI_SITE_EVENT_OP] }),\n )\n }\n const item = unit.item\n if (item) {\n const noun = context.ops.get(item.op)?.noun ?? item.op\n brief.push(`Build the ${noun} “${item.name}”${item.why ? `: ${item.why}` : '.'}`)\n // A planned kind's step builds the plan's first creation of its kind.\n unitPlan.create = AI_PLANNED_JOB_KINDS.includes(context.kind)\n ? [{ kind: context.kind as AiBuildPlanCreateKind, name: item.name, why: item.why, duplicateOf: null, fields: [], ...(item.id ? { id: item.id } : {}) }]\n : []\n }\n brief.push(...(context.briefLines ?? []))\n const inputs: Record<string, unknown> = {\n ...job.inputs,\n ...aiBuildItemArgsWithout(item?.args ?? {}, context.dropped),\n originJobId: aiOriginJobId(job),\n }\n delete inputs[AI_BUILD_PUBLISH_INPUT]\n // An item is told the pages and layouts this build made before it, which\n // its arguments may link as `new:<name>` (a menu item, AGL-3728).\n if (item) {\n const rows = new Map(context.ledger.map((row) => [row.slot, row]))\n const made: AiBuildMade = {\n pages: context.units.flatMap((one) => {\n const row = rows.get(one.slot)\n return one.screen?.id && row && aiBuildItemDelivered(row) ? [{ title: one.screen.title, id: one.screen.id }] : []\n }),\n layouts: [...built.entries()].filter(([, entry]) => entry.kind === 'layout').map(([name, entry]) => ({ name, id: entry.id })),\n }\n if (made.pages.length || made.layouts.length) inputs[AI_BUILD_MADE_INPUT] = made\n }\n // A dataset this build made for its form, which the form may bind (AGL-3616).\n const madeFor = unit.creation?.kind === 'form' && isAiPlanNewRef(unit.creation.writesTo) ? unitPlan.create[0]?.writesTo : null\n if (madeFor) inputs[AI_FORM_DATASET_MADE_INPUT] = madeFor\n // A build's pages and layouts are designed in the layout language and\n // compiled (AGL-3660), told the pages the build plans and where its form is.\n if (context.kind === 'page' || context.kind === 'layout') {\n inputs[AI_LAYOUT_LANGUAGE_INPUT] = true\n const pages = aiLayoutSitePagesOfPlan(plan.screens)\n if (pages.length) inputs[AI_LAYOUT_SITE_PAGES_INPUT] = pages\n const formPage = aiLayoutFormPageOfPlan(plan)\n if (formPage) inputs[AI_LAYOUT_FORM_PAGE_INPUT] = formPage\n // The datasets this build made, repeated in the sections that name them (AGL-3616),\n // and the site's own the plan reuses (AGL-3747): the page reads their fields,\n // and the record pages the site already serves for them, off its inventory.\n const datasets = [...built.entries()]\n .filter(([, entry]) => entry.kind === 'dataset')\n .map(([name, entry]) => ({ id: entry.id, name: context.units.find((one) => one.item?.name.toLowerCase() === name)?.label ?? entry.label }))\n for (const entry of plan.reuse) {\n if (entry.kind !== 'dataset' || datasets.some((one) => one.id === entry.id)) continue\n datasets.push({ id: entry.id, name: plan.labels?.[entry.id] ?? entry.id })\n }\n const listings = aiDatasetListingsOf(datasets, plan.screens)\n // The events this build wrote, in the sections that name them (AGL-3755).\n const eventUnits = context.units.filter((one) => one.item?.op === AI_SITE_EVENT_OP)\n const ledgerRows = new Map(context.ledger.map((row) => [row.slot, row]))\n listings.push(\n ...aiEventsListings({\n written: eventUnits\n .filter((one) => {\n const row = ledgerRows.get(one.slot)\n return Boolean(row && aiBuildItemDelivered(row) && row.outputs.length)\n })\n .map((one) => one.item?.name ?? one.label),\n planned: eventUnits.map((one) => one.item?.name ?? one.label),\n screens: plan.screens,\n }),\n )\n if (listings.length) inputs[AI_LAYOUT_LISTINGS_INPUT] = listings\n }\n // A build that makes the site a store links its account and policies from\n // the layout it makes (AGL-3676), by path: they are written after it.\n const storePages = aiBuildStorePagesOf(plan)\n if (context.kind === 'layout' && storePages) inputs[AI_SITE_STORE_LINKS_INPUT] = aiStoreFrameLinks(storePages.pages)\n return {\n ...job,\n $id: aiBuildUnitJobId(job, unit),\n kind: context.kind,\n steps: [],\n outputs: [],\n items: null,\n plan: item && !AI_PLANNED_JOB_KINDS.includes(context.kind) ? null : unitPlan,\n inputs,\n brief: brief.join('\\n').slice(0, AI_JOB_BRIEF_MAX_CHARS),\n }\n}\n\n/** The unit's failure, for its row: ours or not, why, in customer-safe words. */\nfunction failed(\n slot: string,\n failure: AiJobItemFailure,\n extra: Partial<AiJobItemOutcome> = {},\n): AiJobItemOutcome {\n return { slot, status: 'failed', failure, ...extra }\n}\n\nexport interface AiJobBuildStepDeps {\n /** The runner registry; specs hand in fakes. */\n runnerFor?: typeof aiJobStepRunnerFor\n /** The draft writer registry; specs hand in fakes. */\n writerFor?: AiPluginDraftWriterLookup\n /** The operations this site may use; the registry and its gates otherwise. */\n opsFor?: (context: AiBuildOpsContext) => Promise<AiBuildOps>\n /** A runner kind's own admission, asked before its item runs; the registry's otherwise. */\n admissionFor?: typeof aiJobAdmissionRefusal\n /** Another plugin's admission for its writer; the seam's otherwise. */\n pluginAdmission?: typeof aiPluginDraftAdmissionRefusal\n /** The draft reader a built page is checked through. */\n readNodes?: typeof readAiDraftNodes\n /** The publish a build asked for and confirmed. */\n publish?: typeof aiPublishGuidedSite\n /** A store's own pages' pass and whether they may be added here (AGL-3676); specs hand in fakes. */\n storePages?: AiJobStepRunner\n storePagesRefusal?: typeof aiSiteStorePagesRefusal\n /** The site's pages as they are now, which a store's own pages are checked against before they are written. */\n readSitePages?: typeof readAiStoreSitePages\n /** The draft version of the site's layout a store's links are written into. */\n writeStoreLinks?: typeof writeAiStoreLinksLayoutDraft\n}\n\n/** The site's pages as a store's own pages are checked against them (AGL-3676): every page that is not deleted. */\nexport async function readAiStoreSitePages(firestore: FirebaseFirestore.Firestore, hostId: string): Promise<AiStoreSitePage[]> {\n const snapshot = await firestore\n .collection('hosts')\n .doc(hostId)\n .collection('screens')\n .select('displayName', 'slug', 'kind', 'deletedAt', 'layoutId')\n .get()\n return snapshot.docs.flatMap((doc) => {\n const kind = doc.get('kind')\n if (doc.get('deletedAt') || (kind && kind !== 'template')) return []\n const slug = String(doc.get('slug') ?? '')\n const layoutId = doc.get('layoutId')\n return slug\n ? [{ id: doc.id, slug, title: String(doc.get('displayName') ?? ''), template: kind === 'template', layoutId: typeof layoutId === 'string' && layoutId ? layoutId : null }]\n : []\n })\n}\n\n/**\n * What a build's store pages unit is told (AGL-3676): the pages its plan kept,\n * less any the site has gained since — never counting the pages this unit\n * wrote itself on an earlier pass, which it finds again by their ids — what\n * their words link, and the layout they render inside: the plan's Shop\n * page's, else the site's own (`aiBuildStoreLayoutOf`).\n */\nexport function aiBuildStorePagesInput(\n job: AiJob,\n context: { unitJobId: string; sitePages: readonly AiStoreSitePage[]; units: readonly AiBuildUnit[]; ledger: readonly AiJobItemLedger[] },\n): AiSiteStorePagesInput | null {\n const plan = job.plan as AiJobPlan\n const kept = aiBuildStorePagesOf(plan)\n if (!kept) return null\n const own = new Set(kept.pages.map((page) => aiSiteStorePageId(context.unitJobId, page.key)))\n const pages = aiBuildStorePagesStillMissing(\n kept.pages,\n context.sitePages.filter((page) => !page.id || !own.has(page.id)),\n )\n const built = aiBuildBuiltRefs(context.units, context.ledger, job.outputs ?? [])\n const shop = plan.screens.find((screen) => !screen.record && screen.slug.replace(/^\\/+/, '').split('/')[0].toLowerCase() === kept.facts.shopPath.slice(1))\n const layout = shop ? aiSiteResolvedRef(shop.layout, built) : null\n return {\n pages,\n facts: kept.facts,\n layoutId: aiBuildStoreLayoutOf(layout && !isAiPlanNewRef(layout) ? layout : null, context.sitePages),\n }\n}\n\n/**\n * Adds a store's links to the site's own layout (AGL-3676), as a draft\n * version, where the build made no layout of its own for its store pages: the\n * outputs that record it — the layout version written (`storeLinks: draft`),\n * and on the first page `storeLinks: missing` where the layout had no header\n * or footer list to add them to, or there is no layout at all.\n */\nexport async function aiBuildStoreLinksOutputs(\n firestore: FirebaseFirestore.Firestore,\n input: {\n job: AiJob\n unitJobId: string\n store: AiSiteStorePagesInput\n outputs: readonly AiJobOutput[]\n sitePages: readonly AiStoreSitePage[]\n builtLayouts: ReadonlySet<string>\n now: Date\n },\n write: typeof writeAiStoreLinksLayoutDraft = writeAiStoreLinksLayoutDraft,\n): Promise<AiJobOutput[]> {\n const outputs = input.outputs.map((output) => ({ ...output }))\n const layoutId = input.store.layoutId\n // A layout this build made was told the store's links as it was compiled.\n if (layoutId && input.builtLayouts.has(layoutId)) return outputs\n const written = new Set(outputs.map((output) => output.proposal?.['storePage']).filter((key): key is string => typeof key === 'string'))\n const links = aiBuildStoreLayoutLinks(input.store.pages, written)\n const missing = (): AiJobOutput[] => {\n const [first, ...rest] = outputs\n const state: AiBuildStoreLinksState = 'missing'\n return first ? [{ ...first, proposal: { ...(first.proposal ?? {}), storeLinks: state } }, ...rest] : outputs\n }\n if (!layoutId || !input.job.hostId) return missing()\n const hrefs = new Set([...links.header, ...(links.cart ? [links.cart] : []), ...links.footer].map((link) => link.href.slice(1)))\n const screenPaths: Record<string, string> = {}\n for (const page of input.sitePages) {\n const slug = page.slug.replace(/^\\/+/, '').split('/')[0].toLowerCase()\n if (page.id && hrefs.has(slug)) screenPaths[page.id] = slug\n }\n const draft = await write(firestore, {\n hostId: input.job.hostId,\n layoutId,\n versionId: `${input.unitJobId}-links`.slice(0, 64),\n links,\n screenPaths,\n uid: input.job.createdBy,\n aiJobId: aiOriginJobId(input.job),\n now: input.now,\n })\n if (draft.status === 'present') return outputs\n if (draft.status === 'gone') return missing()\n const versionId = draft.versionId\n const layout: AiJobOutput[] = versionId\n ? [\n {\n resource: 'layout',\n id: draft.layoutId,\n versionId,\n hostId: input.job.hostId,\n hostSubdomain: outputs.find((output) => output.hostSubdomain)?.hostSubdomain,\n label: draft.name,\n note: 'A new draft version with Account and policy links. Visitors see it once it is published.',\n proposal: { storeLinks: 'draft' satisfies AiBuildStoreLinksState, links, screenPaths },\n },\n ]\n : []\n return [...(draft.status === 'unrecognized' ? missing() : outputs), ...layout]\n}\n\n/** The store's links a build drafted into the site's layout (AGL-3676), as its publish puts them live; `null` where it drafted none. */\nexport function aiBuildStoreLinksToPublish(outputs: readonly AiJobOutput[]): AiSitePublishStoreLinks | null {\n // The newest: a retried store drafts its links again after the first attempt's (AGL-3739).\n const draft = [...outputs]\n .reverse()\n .find((output) => output.resource === 'layout' && output.proposal?.['storeLinks'] === 'draft' && output.versionId)\n if (!draft?.versionId) return null\n return {\n layoutId: draft.id,\n versionId: draft.versionId,\n links: draft.proposal?.['links'] as AiStoreLayoutLinks,\n screenPaths: (draft.proposal?.['screenPaths'] ?? {}) as Record<string, string>,\n }\n}\n\n/** Whether a build's workspace spends the Free taste. */\nexport function aiBuildFreeTaste(org: object | null | undefined): boolean {\n return Boolean(org) && resolveEffectivePlan(org as never) === 'free'\n}\n\n/** The site document a gate reads, or `null`. */\nasync function readHost(firestore: FirebaseFirestore.Firestore, hostId: string | null) {\n if (!hostId) return null\n return ((await firestore.collection('hosts').doc(hostId).get()).data() ?? null) as Record<string, unknown> | null\n}\n\nexport function createAiJobBuildStep(deps: AiJobBuildStepDeps = {}): AiJobStepRunner {\n const runnerFor = deps.runnerFor ?? aiJobStepRunnerFor\n const writerFor = deps.writerFor ?? aiPluginDraftWriter\n const opsFor = deps.opsFor ?? ((context) => aiBuildOps(context))\n const admissionFor = deps.admissionFor ?? aiJobAdmissionRefusal\n const pluginAdmission = deps.pluginAdmission ?? aiPluginDraftAdmissionRefusal\n const readNodes = deps.readNodes ?? readAiDraftNodes\n const publish = deps.publish ?? aiPublishGuidedSite\n const storePagesRunner = deps.storePages ?? runAiSiteStorePagesUnit\n const storePagesRefusal = deps.storePagesRefusal ?? aiSiteStorePagesRefusal\n const readSitePages = deps.readSitePages ?? readAiStoreSitePages\n const writeStoreLinks = deps.writeStoreLinks ?? writeAiStoreLinksLayoutDraft\n\n return async (context): Promise<AiJobStepOutcome> => {\n const { job, firestore } = context\n const model = context.modelFor?.('job.plan') ?? aiModelForStep('job.plan')\n const plan = aiConfirmedPlan(job)\n if (!plan) return { ...aiUnspentOutcome(model), failure: AI_BUILD_NO_PLAN_COPY }\n const org = (context.org ?? null) as Partial<AglynOrgBilling> | null\n const units = aiBuildUnits(plan)\n const ordered = aiBuildOrder(units) ?? units\n const starting = !job.items?.length\n const ledger = starting ? aiBuildInitialLedger(units) : (job.items as AiJobItemLedger[])\n const init = starting ? { items: ledger } : {}\n const unit = aiBuildNextUnit(ordered, ledger)\n const rows = new Map(ledger.map((row) => [row.slot, row]))\n const host = await readHost(firestore, job.hostId ?? null)\n const ops = await opsFor({\n orgId: job.orgId,\n hostId: job.hostId ?? null,\n org,\n host,\n freeTaste: aiBuildFreeTaste(org),\n })\n\n /** Whether units other than this one are still to build. */\n const othersOpen = (slot: string) =>\n ordered.some((one) => one.slot !== slot && aiBuildItemOpen(rows.get(one.slot) ?? { status: 'pending' }))\n\n /**\n * The build's last pass puts its pages live, where it was asked and\n * confirmed. Once it has, Try again's last pass puts only the pages the\n * retry built live (AGL-3739, AGL-3730's fix for a site start),\n * merged into the record of the first.\n */\n const finish = async (\n outcome: AiJobStepOutcome,\n extraPages: readonly AiJobOutput[] = [],\n extraOutputs: readonly AiJobOutput[] = [],\n ): Promise<AiJobStepOutcome> => {\n if (!aiJobPublishesBuild(job) || !job.hostId) return outcome\n const previous = job.sitePublish ?? null\n const retry = Boolean(previous?.published.length)\n const already = new Set((previous?.published ?? []).map((page) => page.id))\n // A record template renders once per record only once its binding is\n // saved, so it is never published at its own address (AGL-3616).\n // A store's own pages (AGL-3676) go live with the pages the build planned.\n const pageIds = new Set(\n units\n .filter(\n (one) =>\n ((one.screen && !one.screen.record) || one.op === AI_BUILD_STORE_OP) &&\n aiBuildItemDelivered(rows.get(one.slot) ?? { status: 'pending' }),\n )\n .flatMap((one) => rows.get(one.slot)?.outputs ?? []),\n )\n const built = [\n ...(job.outputs ?? []).filter((output) => output.resource === 'screen' && pageIds.has(output.id)),\n ...extraPages,\n ]\n const pages = built.filter((page) => !already.has(page.id))\n if (!pages.length) return outcome\n // A canceled build never puts anything live (AGL-3616): its pages stay drafts.\n if (await aiJobCancelAsked(firestore, job, context.signal)) return outcome\n // The store pages a layout this build made links and that were not written come out of it.\n const storePages = aiBuildStorePagesOf(plan)\n const live = new Set(built.map((page) => page.proposal?.['storePage']).filter(Boolean))\n const unwrittenHrefs = storePages\n ? aiStorePagesToWrite(storePages.pages).filter((page) => !live.has(page.key)).map((page) => page.href)\n : []\n // A retry puts the store's links live only with store pages it built:\n // the first publish's links draft is live already, and a person may have edited it since.\n const storeLinks =\n !retry || pages.some((page) => page.proposal?.['storePage'])\n ? aiBuildStoreLinksToPublish([...(job.outputs ?? []), ...extraOutputs])\n : null\n const sitePublish = await publish(firestore, {\n job,\n outputs: pages,\n now: context.now,\n ...(unwrittenHrefs.length ? { unwrittenHrefs } : {}),\n ...(storeLinks ? { storeLinks } : {}),\n ...(retry ? { retry: true } : {}),\n }).catch((error: unknown) => {\n console.error('ai build publish threw', { orgId: job.orgId, jobId: job.$id, error })\n return null\n })\n if (!sitePublish) return outcome\n return { ...outcome, sitePublish: previous ? aiMergeSitePublish(previous, sitePublish) : sitePublish }\n }\n\n if (!unit) return finish({ ...aiUnspentOutcome(model), ...init })\n\n const settle = (item: AiJobItemOutcome, spent: AiJobStepOutcome = aiUnspentOutcome(model)): AiJobStepOutcome => ({\n ...spent,\n ...init,\n item,\n ...(item.status === 'running' || othersOpen(unit.slot) ? { continue: true } : {}),\n })\n\n // What its dependencies came to.\n const degradation = aiBuildDegradation(unit, { units, ledger, ops })\n if (degradation.skip) {\n return settle({ slot: unit.slot, status: 'skipped', note: degradation.skip, degradedBy: degradation.degradedBy })\n }\n // A store's own pages (AGL-3676): written by code, behind the site start's gate.\n if (unit.op === AI_BUILD_STORE_OP) {\n if (!job.hostId) return settle({ slot: unit.slot, status: 'skipped', note: 'Not built: open the site first.' })\n if (rows.get(unit.slot)?.status !== 'running') {\n const refusal = await storePagesRefusal({ ...context, job }).catch((error: unknown) => {\n console.error('ai build store pages admission failed', { orgId: job.orgId, jobId: job.$id, error })\n return AI_BUILD_UNIT_EMPTY_COPY\n })\n if (refusal) return settle({ slot: unit.slot, status: 'skipped', note: `Not built: ${refusal}` })\n }\n const unitJobId = aiBuildUnitJobId(job, unit)\n const sitePages = await readSitePages(firestore, job.hostId)\n const input = aiBuildStorePagesInput(job, { unitJobId, sitePages, units, ledger })\n if (!input) return settle({ slot: unit.slot, status: 'skipped', note: aiBuildUnavailableCopy('store page') })\n if (!aiStorePagesToWrite(input.pages).length) {\n return settle({ slot: unit.slot, status: 'skipped', note: AI_BUILD_STORE_PAGES_PRESENT_NOTE })\n }\n const derived: AiJob = {\n ...job,\n $id: unitJobId,\n kind: 'text',\n steps: [],\n outputs: [],\n items: null,\n plan: null,\n inputs: { ...job.inputs, originJobId: aiOriginJobId(job), [AI_SITE_STORE_PAGES_INPUT]: input },\n }\n let outcome: AiJobStepOutcome\n try {\n outcome = await storePagesRunner({ ...context, job: derived })\n } catch (error) {\n if (aiUnitErrorRetryable(error)) throw error\n console.error('ai build store pages threw', { orgId: job.orgId, jobId: job.$id, error })\n return settle(failed(unit.slot, { ours: true, reason: 'step-failure', message: AI_BUILD_UNIT_EMPTY_COPY }))\n }\n const stopped = aiUnitFailure(unit.slot, outcome)\n if (stopped) return settle(stopped, aiUnitSpend(outcome))\n // The site's own header and footer link them (AGL-3676), in a draft\n // version of its layout; a layout this build made already does.\n const builtLayouts = new Set(\n [...aiBuildBuiltRefs(units, ledger, job.outputs ?? []).values()].filter((entry) => entry.kind === 'layout').map((entry) => entry.id),\n )\n const outputs = await aiBuildStoreLinksOutputs(\n firestore,\n { job, unitJobId, store: input, outputs: outcome.outputs, sitePages, builtLayouts, now: context.now },\n writeStoreLinks,\n ).catch((error: unknown) => {\n console.error('ai build store links not written', { orgId: job.orgId, jobId: job.$id, error })\n return outcome.outputs\n })\n const ids = outputs.map((output) => output.id)\n const done = settle({ slot: unit.slot, status: 'succeeded', outputs: ids, note: AI_SITE_STORE_PAGES_NOTE }, { ...aiUnitSpend(outcome), outputs })\n if (done.continue) return done\n rows.set(unit.slot, { ...(rows.get(unit.slot) as AiJobItemLedger), status: 'succeeded', outputs: ids })\n return finish(\n done,\n outputs.filter((output) => output.resource === 'screen'),\n outputs,\n )\n }\n\n const capability = ops.get(unit.op)\n const noun = capability?.noun ?? unit.op\n if (!capability) return settle({ slot: unit.slot, status: 'skipped', note: aiBuildUnavailableCopy(noun) })\n const degraded = degradation.degradedBy.length > 0\n const note = degradation.notes.length ? degradation.notes.join(' ') : null\n\n // Another plugin's resource: its writer, with the content its capability derives.\n if (capability.draftResource) {\n const item = unit.item\n const writer = writerFor(capability.draftResource)\n if (!item || !writer || !job.hostId) {\n return settle({ slot: unit.slot, status: 'skipped', note: aiBuildUnavailableCopy(noun) })\n }\n const admission: AiJobAdmissionContext = {\n firestore,\n orgId: job.orgId,\n hostId: job.hostId,\n inputs: {},\n org,\n uid: job.createdBy,\n }\n const refusal = await pluginAdmission(admission, {\n kind: 'build',\n drafts: [{ resource: capability.draftResource, label: capability.noun }],\n writerFor,\n })\n if (refusal) return settle({ slot: unit.slot, status: 'skipped', note: `Not built: ${refusal.error}` })\n const dependencies: Record<string, { op: string; id: string }> = {}\n for (const slot of unit.deps) {\n const dep = units.find((one) => one.slot === slot)\n const row = rows.get(slot)\n if (!dep || !row || !aiBuildItemDelivered(row) || !row.outputs.length) continue\n dependencies[`new:${dep.label}`] = { op: dep.op, id: row.outputs[0] }\n }\n const content = capability.draftContent?.({ name: item.name, args: item.args }, { hostId: job.hostId, dependencies }) ?? item.args\n const checked = writer.check(content, { hostId: job.hostId })\n if (checked.ok === false) {\n return settle(\n failed(unit.slot, { ours: true, reason: 'step-failure', message: checked.problems[0] ?? AI_BUILD_UNIT_EMPTY_COPY }),\n )\n }\n const id = aiBuildUnitJobId(job, unit)\n const written = await writer.write({\n orgId: job.orgId,\n hostId: job.hostId,\n uid: job.createdBy,\n org,\n now: context.now,\n // Drafts of one build share what must not repeat (a cover photo) and read its business (AGL-3755).\n act: { id: aiOriginJobId(job), business: aiSiteWords(job.inputs).about || job.brief || '' },\n id,\n name: item.name,\n content,\n })\n if (written.ok === false) {\n return settle(failed(unit.slot, { ours: false, reason: 'review', message: written.error }))\n }\n const output: AiJobOutput = {\n resource: 'draft',\n id: written.id,\n versionId: written.versionId,\n hostId: job.hostId,\n label: written.name,\n draftResource: capability.draftResource,\n // A resource with no draft state is live once written (AGL-3745, AGL-3746).\n note: aiBuildItemOutputNote(capability, written),\n }\n return settle(\n {\n slot: unit.slot,\n status: degraded ? 'degraded' : 'succeeded',\n outputs: [written.id],\n note,\n ...(degraded ? { degradedBy: degradation.degradedBy } : {}),\n },\n { ...aiUnspentOutcome(model), outputs: [output] },\n )\n }\n\n // This plugin's own runner, under a job derived for the unit.\n const kind = aiBuildUnitJobKind(unit, ops)\n const runner = kind ? runnerFor(kind) : null\n if (!kind || !runner) return settle({ slot: unit.slot, status: 'skipped', note: aiBuildUnavailableCopy(noun) })\n const derived = aiBuildUnitJob(job, unit, {\n kind,\n units,\n ledger,\n ops,\n briefLines: degradation.briefLines,\n dropped: degradation.dropped,\n })\n // An item's kind is asked its own admission first (a campaign's plan,\n // a template's subject), once, before its first pass.\n if (unit.item && rows.get(unit.slot)?.status !== 'running') {\n const refusal = await admissionFor(kind, {\n firestore,\n orgId: job.orgId,\n hostId: job.hostId ?? null,\n inputs: derived.inputs,\n org,\n uid: job.createdBy,\n }).catch((error: unknown) => {\n console.error('ai build item admission failed', { orgId: job.orgId, jobId: job.$id, slot: unit.slot, error })\n return { status: 403 as const, error: AI_BUILD_UNIT_EMPTY_COPY }\n })\n if (refusal) return settle({ slot: unit.slot, status: 'skipped', note: `Not built: ${refusal.error}` })\n }\n\n let outcome: AiJobStepOutcome\n try {\n outcome = await runner({ ...context, job: derived })\n } catch (error) {\n // A provider that will answer later is the machine's to retry; anything\n // else is this item's failure, and the build goes on.\n if (aiUnitErrorRetryable(error)) throw error\n console.error('ai build unit threw', { orgId: job.orgId, jobId: job.$id, slot: unit.slot, error })\n return settle(failed(unit.slot, { ours: true, reason: 'provider', message: AI_BUILD_UNIT_EMPTY_COPY }))\n }\n const spent = aiUnitSpend(outcome)\n const ids = outcome.outputs.map((output) => output.id)\n const stopped = aiUnitFailure(unit.slot, outcome)\n if (stopped) return settle(stopped, spent)\n // A page counts as built only when its plan's sections are in it (AGL-3596).\n if (unit.screen && job.hostId) {\n const page = outcome.outputs.find((output) => output.resource === 'screen')\n const written =\n page !== undefined &&\n (await aiSitePageWritten(\n firestore,\n {\n hostId: job.hostId,\n unitJobId: derived.$id,\n screen: unit.screen,\n draftId: page.id,\n layoutLanguage: aiJobUsesLayoutLanguage(derived),\n },\n readNodes,\n ))\n if (!written) {\n return settle(\n failed(unit.slot, { ours: true, reason: 'step-failure', message: AI_BUILD_PAGE_NOT_WRITTEN_COPY }),\n { ...spent, outputs: outcome.outputs.filter((output) => output.resource !== 'screen') },\n )\n }\n }\n const done = settle(\n {\n slot: unit.slot,\n status: degraded ? 'degraded' : 'succeeded',\n outputs: ids,\n note,\n ...(degraded ? { degradedBy: degradation.degradedBy } : {}),\n },\n spent,\n )\n if (done.continue) return done\n // The last unit: what was built goes live where it was asked and confirmed.\n rows.set(unit.slot, { ...(rows.get(unit.slot) as AiJobItemLedger), status: degraded ? 'degraded' : 'succeeded', outputs: ids })\n return finish(done, unit.screen ? outcome.outputs.filter((output) => output.resource === 'screen') : [])\n }\n}\n\nexport const runAiJobBuildStep = createAiJobBuildStep()\n\n/**\n * The least time a build's next pass needs: what the step that builds its\n * next unit registers for the job derived for it; a page pass's when the\n * next unit is another plugin's draft, which asks no model.\n */\nexport function aiBuildJobRunMinimumMs(job: AiJob): number {\n const plan = aiConfirmedPlan(job)\n if (!plan) return AI_JOB_PAGE_STEP_MINIMUM_MS\n const units = aiBuildUnits(plan)\n const ordered = aiBuildOrder(units) ?? units\n const ledger = job.items?.length ? job.items : aiBuildInitialLedger(units)\n const unit = aiBuildNextUnit(ordered, ledger)\n if (!unit) return AI_JOB_PAGE_STEP_MINIMUM_MS\n const kind: AiJobKind | null = unit.screen\n ? 'page'\n : unit.creation\n ? (CREATION_JOB_KINDS[unit.creation.kind] ?? null)\n : (AI_BUILD_ITEM_RUNNER_KINDS[unit.op] ?? null)\n if (!kind) return AI_JOB_PAGE_STEP_MINIMUM_MS\n return aiJobStepRunMinimumMs(aiBuildUnitJob(job, unit, { kind, units, ledger, ops: new Map() }))\n}\n\n/** The runner kinds this plugin's own item operations use, for the time a pass needs without the registry. */\nconst AI_BUILD_ITEM_RUNNER_KINDS: Readonly<Record<string, AiJobKind>> = {\n template: 'template',\n campaign: 'campaign',\n workflow: 'workflow',\n function: 'logic',\n edit: 'edit',\n navigation: 'navigation',\n duplicate: 'duplicate',\n settings: 'settings',\n media: 'media',\n tracking: 'tracking',\n}\n\n/**\n * What a Free build's credits say before it runs (AGL-3722), on its measured\n * p90 rather than its ceiling: `null` when what is left this month covers the\n * p90 — or when nothing is known about what is left, since each pass's\n * reservation still decides — and `null` too for a build the person chose\n * to build as far as it goes (`confirmed`), whose prompt `onConfirmed` is\n * told so the door records it. Otherwise a 409 carrying the prompt: the\n * range, what is left, and the smaller first build. Nothing left at all is a\n * 429. Read off the same two walls the reservation refuses at\n * (`readFreeAiCreditsLeft`), net of give-backs.\n */\nexport async function aiBuildFreeCreditsRefusal(input: {\n firestore: FirebaseFirestore.Firestore\n orgId: string\n org: object | null\n range: AiCreditRange\n smaller?: AiCreditsSmaller | null\n confirmed?: boolean\n onConfirmed?: (prompt: AiCreditsPrompt) => void\n now: Date\n freeCreditsLeft?: typeof readFreeAiCreditsLeft\n}): Promise<AiJobAdmissionRefusal | null> {\n const read = input.freeCreditsLeft ?? readFreeAiCreditsLeft\n const credits = await read(input.firestore, { orgId: input.orgId, org: input.org, now: input.now })\n if (!credits) return null\n if (credits.left <= 0) return { status: 429, error: aiFreeCreditsNoneLeftText(credits.resetsOn) }\n const prompt = aiCreditsPromptFor(input.range, credits, input.smaller ?? null)\n if (!prompt) return null\n if (!input.confirmed) {\n return { status: 409, error: aiCreditsPromptText(prompt, 'build'), code: AI_CREDITS_CONFIRM_CODE, credits: prompt }\n }\n input.onConfirmed?.(prompt)\n return null\n}\n\nexport interface AiBuildAdmissionDeps {\n opsFor?: (context: AiBuildOpsContext) => Promise<AiBuildOps>\n freeCreditsLeft?: typeof readFreeAiCreditsLeft\n ownerOf?: typeof resolveOrgIdForHost\n now?: () => Date\n}\n\n/**\n * A build is admitted for a site of the job's own org where a page can be\n * built; and confirmed only for a plan it can build here — its shape, its\n * operations as this site has them, and on the Free taste a measured p90\n * the month's Free credits still cover — or the person's go-ahead to build\n * what fits (AGL-3722).\n */\nexport function createAiBuildJobAdmission(deps: AiBuildAdmissionDeps = {}): AiJobAdmission {\n const opsFor = deps.opsFor ?? ((context) => aiBuildOps(context))\n const ownerOf = deps.ownerOf ?? resolveOrgIdForHost\n return async (context) => {\n if (!context.hostId) return { status: 400, error: 'Open the site to build on before asking Assist to build' }\n const owner = await ownerOf(context.hostId)\n if (!owner || owner !== context.orgId) return { status: 404, error: 'Unknown site' }\n if (!aiJobStepRunnerFor('page')) return { status: 400, error: 'Building from a request is not available yet.' }\n const plan = context.plan\n if (!plan) return null\n const org = context.org as Partial<AglynOrgBilling> | null\n const freeTaste = aiBuildFreeTaste(org)\n const host = await readHost(context.firestore, context.hostId)\n const ops = await opsFor({ orgId: context.orgId, hostId: context.hostId, org, host, freeTaste })\n const shape = aiBuildPlanShapeRefusal(plan, { freeTaste, ops })\n if (shape) return { status: 400, error: shape }\n // Something only the person can give (AGL-3751): asked, never built without.\n const missing = aiBuildPlanMissingInput(plan, ops)\n if (missing) return { status: 400, error: missing }\n if (freeTaste) {\n const refusal = await aiBuildFreeCreditsRefusal({\n firestore: context.firestore,\n orgId: context.orgId,\n org,\n range: aiBuildCreditRange(plan, { ops }),\n smaller: aiBuildSmaller(plan, ops),\n confirmed: context.creditsConfirmed === true,\n onConfirmed: context.onCreditsConfirmed,\n now: deps.now?.() ?? new Date(),\n freeCreditsLeft: deps.freeCreditsLeft,\n })\n if (refusal) return refusal\n }\n return null\n }\n}\n\nexport const aiBuildJobAdmission = createAiBuildJobAdmission()\n\n/**\n * Registers the build with the least time a pass needs, the time its next\n * pass needs, the passes its largest plan may take, and its admission.\n */\nexport function registerAiBuildJob(): void {\n registerAiJobStep('build', runAiJobBuildStep, {\n minimumMs: AI_JOB_PAGE_STEP_MINIMUM_MS,\n minimumMsFor: aiBuildJobRunMinimumMs,\n })\n registerAiJobStepPasses('build', AI_BUILD_MAX_PASSES)\n registerAiJobAdmission('build', aiBuildJobAdmission)\n}\n"],"names":["aiJobCancelAsked","resolveEffectivePlan","resolveOrgIdForHost","AI_BUILD_LIMITS","AI_BUILD_MADE_INPUT","AI_BUILD_PUBLISH_INPUT","aiArticle","aiBuildCreditRange","aiBuildDegradation","aiBuildInitialLedger","aiBuildItemArgRefs","aiBuildItemDelivered","aiBuildItemOpen","aiBuildNextUnit","aiBuildOrder","aiBuildItemOutputNote","aiBuildPlacedItemLines","aiBuildPlanMissingInput","aiBuildPlanShapeRefusal","aiBuildRefName","aiBuildSmaller","aiBuildUnits","isAiPlanNewRef","AI_SITE_MAX_SECTIONS","AI_CREDITS_CONFIRM_CODE","aiCreditsPromptFor","aiCreditsPromptText","aiFreeCreditsNoneLeftText","aiSiteWords","readFreeAiCreditsLeft","aiModelForStep","AI_BUILD_UNIT_EMPTY_COPY","aiBuildBuiltRefs","aiUnitErrorRetryable","aiUnitFailure","aiUnitSpend","aiBuildOps","aiJobAdmissionRefusal","registerAiJobAdmission","aiOriginJobId","readAiDraftNodes","aiConfirmedPlan","aiUnspentOutcome","AI_JOB_PAGE_STEP_MINIMUM_MS","aiPluginDraftAdmissionRefusal","aiPluginDraftWriter","aiSitePageWritten","aiSiteResolvedRef","AI_LAYOUT_SITE_PAGES_INPUT","aiLayoutSitePagesOfPlan","AI_LAYOUT_FORM_PAGE_INPUT","AI_LAYOUT_LANGUAGE_INPUT","aiJobUsesLayoutLanguage","aiLayoutFormPageOfPlan","aiDatasetListingsOf","AI_SITE_EVENT_OP","aiEventsListings","AI_FORM_DATASET_MADE_INPUT","AI_LAYOUT_LISTINGS_INPUT","AI_BUILD_STORE_OP","AI_BUILD_STORE_PAGES_PRESENT_NOTE","aiBuildStoreLayoutLinks","aiBuildStoreLayoutOf","aiBuildStorePagesOf","aiBuildStorePagesStillMissing","writeAiStoreLinksLayoutDraft","AI_SITE_STORE_LINKS_INPUT","AI_SITE_STORE_PAGES_NOTE","aiStoreFrameLinks","aiStorePagesToWrite","AI_SITE_STORE_PAGES_INPUT","aiSiteStorePageId","aiSiteStorePagesRefusal","runAiSiteStorePagesUnit","AI_JOB_BRIEF_MAX_CHARS","aiJobPublishesBuild","aiMergeSitePublish","aiPublishGuidedSite","AI_PLANNED_JOB_KINDS","aiJobStepRunMinimumMs","aiJobStepRunnerFor","registerAiJobStep","registerAiJobStepPasses","AI_BUILD_NO_PLAN_COPY","aiBuildUnavailableCopy","noun","AI_BUILD_PAGE_NOT_WRITTEN_COPY","AI_BUILD_MAX_PASSES","units","CREATION_JOB_KINDS","layout","form","component","email","aiBuildUnitJobKind","unit","ops","screen","creation","kind","runnerKind","get","op","aiBuildItemArgsWithout","args","dropped","size","links","entry","some","ref","has","Object","fromEntries","entries","map","key","value","Array","isArray","filter","aiBuildUnitJobId","job","id","item","$id","slot","aiBuildUnitJob","context","plan","unitPlan","built","ledger","outputs","labels","values","label","brief","trim","reuse","create","screens","items","placedByScreens","Set","flatMap","sections","section","uses","duplicateOf","writesTo","push","name","why","purpose","builtLayout","template","record","dataset","title","slug","placedByCode","includes","fields","briefLines","inputs","originJobId","rows","Map","row","made","pages","one","layouts","length","madeFor","formPage","datasets","find","toLowerCase","listings","eventUnits","ledgerRows","written","Boolean","planned","storePages","steps","join","slice","failed","failure","extra","status","readAiStoreSitePages","firestore","hostId","snapshot","collection","doc","select","docs","String","layoutId","aiBuildStorePagesInput","kept","own","page","unitJobId","sitePages","shop","replace","split","facts","shopPath","aiBuildStoreLinksOutputs","input","write","output","store","builtLayouts","proposal","missing","first","rest","state","storeLinks","hrefs","header","cart","footer","link","href","screenPaths","draft","versionId","uid","createdBy","aiJobId","now","resource","hostSubdomain","note","aiBuildStoreLinksToPublish","reverse","aiBuildFreeTaste","org","readHost","data","createAiJobBuildStep","deps","runnerFor","writerFor","opsFor","admissionFor","pluginAdmission","readNodes","publish","storePagesRunner","storePagesRefusal","readSitePages","writeStoreLinks","model","modelFor","ordered","starting","init","host","orgId","freeTaste","othersOpen","finish","outcome","extraPages","extraOutputs","previous","sitePublish","retry","published","already","pageIds","signal","live","unwrittenHrefs","catch","error","console","jobId","settle","spent","continue","degradation","skip","degradedBy","refusal","derived","ours","reason","message","stopped","ids","done","set","capability","degraded","notes","draftResource","writer","admission","drafts","dependencies","dep","content","draftContent","checked","check","ok","problems","act","business","about","runner","undefined","draftId","layoutLanguage","runAiJobBuildStep","aiBuildJobRunMinimumMs","AI_BUILD_ITEM_RUNNER_KINDS","campaign","workflow","function","edit","navigation","duplicate","settings","media","tracking","aiBuildFreeCreditsRefusal","read","freeCreditsLeft","credits","left","resetsOn","prompt","range","smaller","confirmed","code","onConfirmed","createAiBuildJobAdmission","ownerOf","owner","shape","creditsConfirmed","onCreditsConfirmed","Date","aiBuildJobAdmission","registerAiBuildJob","minimumMs","minimumMsFor"],"mappings":"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"}
|
|
@@ -49,7 +49,7 @@ export const AI_INSIGHT_UNREADABLE_COPY = 'The AI did not answer with insights.
|
|
|
49
49
|
'- Name nobody, and write no email address or phone number.',
|
|
50
50
|
'- Plain sentences: no markdown, no headings, no lists.',
|
|
51
51
|
'- When the tables cannot answer part of the question, say so in gap in one sentence with no numbers; otherwise gap is null.',
|
|
52
|
-
'- Whether the site is published,
|
|
52
|
+
'- Whether the site is published, its address and which pages are published come only from the Site status table. Page views and visitors never show whether a site or a page is live: never say or suggest a site is not live, not launched or not published because of its traffic, and never call the pages a views table lists the published ones.',
|
|
53
53
|
'- Write in the language of the question.'
|
|
54
54
|
].join('\n');
|
|
55
55
|
/** The system blocks both calls send: the rules and the platform's acceptable-use rules. */ export const AI_JOB_INSIGHT_SYSTEM = [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/jobs/ai-job-insight-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\nimport type { ResolvedPluginFigureReader } from '@aglyn/aglyn/plugin-manager/plugin-figures'\nimport {\n AI_INSIGHT_ASK_SURFACES,\n AI_INSIGHT_DIGEST_DAYS,\n AI_INSIGHT_DIGEST_READERS,\n AI_INSIGHT_QUESTION_MAX_CHARS,\n AI_INSIGHTS_COLLECTION,\n aiInsightDays,\n aiInsightOutput,\n aiInsightSurface,\n aiInsightSurfaceNeedsSite,\n type AiInsightRecord,\n type AiInsightSurface,\n type AiInsightTable,\n} from '../model/ai-insight'\nimport { aiHostPublishContext, aiSiteStatusTable } from '../model/ai-host-publish-context'\nimport { aiInstructionsWithSiteContext } from '../model/ai-site-context'\nimport { readAiSiteContext } from '../runtime/site-context'\nimport { AI_ROUTING_TABLE, aiModelForStep } from '../providers/routing'\nimport { aiDevEffortFor } from '../runtime/ai-dev-env'\nimport {\n AI_ACCEPTABLE_USE_BLOCK,\n runAiRequest,\n type AiMessage,\n type AiResult,\n type AiSystemBlock,\n type AiUsage,\n} from '../runtime/ai-runtime'\nimport { AI_GENERATION_MAX_ATTEMPTS } from '../runtime/ai-generation-bounds'\nimport { checkAiInsightAnswer, type AiInsightCheck } from '../runtime/ai-insight-check'\nimport {\n AI_INSIGHT_ANSWER_TOOL_NAME,\n AI_INSIGHT_READ_TOOL_NAME,\n aiInsightAnswerTool,\n aiInsightReadTool,\n parseAiInsightAnswer,\n parseAiInsightReads,\n type AiInsightReadRequest,\n} from '../tools/ai-insight-tool'\nimport { aiDatasetCatalog } from '../insights/ai-dataset-catalog'\nimport {\n aiInsightDatasetCatalog,\n aiInsightReaderCatalog,\n aiInsightReaderDays,\n aiInsightReaders,\n aiInsightTableText,\n readAiInsightTables,\n} from '../insights/ai-insight-readers'\nimport { assistExchangeExpiry } from '../usage/assist-usage'\nimport { registerAiJobAdmission, type AiJobAdmissionContext, type AiJobAdmissionRefusal } from './ai-job-admission'\nimport { AI_INSIGHT_READ_MAX_TOKENS, AI_JOB_INSIGHT_STEP_BUDGET, AI_JOB_INSIGHT_STEP_MINIMUM_MS } from './ai-job-insight-budget'\nimport type { AiJobStepContext, AiJobStepOutcome, AiJobStepRunner } from './ai-job-text-step'\nimport { registerAiJobStep } from './ai-jobs'\n\n/**\n * The `insight` step (AGL-2915): a question about a site's figures, answered\n * from tables code read, with every insight traced to the rows it cites.\n *\n * ## Two exchanges, and the model never writes a query\n *\n * 1. **The reads.** The model is shown the question and the readers this job\n * may read — each an id, what it answers, its windows and parameters — and\n * answers `read_figures` with a choice among them. It names nothing else: no\n * collection, no field path, no filter. A choice that names no reader this\n * job may read is dropped, and a job left with none reads the surface's\n * defaults. A weekly digest makes no read call: code reads the digest's\n * readers.\n * 2. **The answer.** Code reads the tables through the owners' readers, and the\n * model is shown them and answers `submit_insights`. The trace\n * (`runtime/ai-insight-check.ts`) keeps each insight whose every number is\n * in a row it cites and leaves out the rest. An answer that is not a call,\n * or whose every insight was left out, is asked for once more with the\n * reasons; what the second answer keeps is the answer.\n *\n * Both calls share one allowance of output, twice the routing ceiling, which\n * is what the step's least time is planned against.\n *\n * ## What reaches the model\n *\n * The question, the names and descriptions of the readers, the tables, the\n * site's publish state (published or not, its address, its pages' paths), and\n * for a datasets question the names of the datasets the member may see with\n * their fields' names and types. A table holds counts, sums and rates labeled\n * by a page path, a referring site, a form's, a service's, a product's or a\n * campaign's name, or the values of a dataset field with at most sixty\n * different values that at least three records share. No\n * record, visitor, contact, order, booking, submission or recipient is read\n * into a prompt, and every text cell is masked of email addresses and phone\n * numbers on its way into a table.\n *\n * ## What it writes\n *\n * The answer, at `orgs/{orgId}/aiInsights/{jobId}` under the job's own\n * expiry, and an output that names it and says how many insights it holds.\n * Nothing else: no draft, no setting, no message.\n */\n\ntype Firestore = FirebaseFirestore.Firestore\n\nexport const AI_INSIGHT_NO_SURFACE_COPY = 'This question does not say which page it was asked from.'\nexport const AI_INSIGHT_NO_SITE_COPY = 'Open the site whose numbers you are asking about.'\nexport const AI_INSIGHT_NO_READERS_COPY =\n 'There are no figures to answer from here yet: the features this page reports on are not on for this workspace.'\nexport const AI_INSIGHT_NO_TABLES_COPY = 'The figures could not be read. Try again in a moment.'\nexport const AI_INSIGHT_UNREADABLE_COPY = 'The AI did not answer with insights. Try asking in different words.'\n\n/** The digest's question: what a week's insights cover, in the order a person reads them. */\nexport const AI_INSIGHT_DIGEST_QUESTION =\n 'What changed on this site this week? Write the week’s insights: the change in traffic, the most viewed page, the form that turned the most views into submissions, a campaign that did better than the rest, and any day that stood out — only those the tables support.'\n\n/** The rules both calls are sent: static, byte-identical for every workspace. */\nexport const AI_INSIGHT_RULES = [\n 'You answer a workspace owner’s questions about their own figures: page views, orders, bookings, forms, campaigns, A/B tests and datasets. You never see a record, and you never write a query: code reads figures through fixed readers and gives you their tables.',\n '',\n `When you are given a question and a list of readers, call ${AI_INSIGHT_READ_TOOL_NAME} once with the readers whose tables answer it, most useful first, and the window each should cover. Choose only readers from the list, with their parameters' values taken from what the list and the question give you.`,\n '',\n `When you are given tables, call ${AI_INSIGHT_ANSWER_TOOL_NAME} once. Each table has a handle (t1, t2, …) and numbered rows. Rules for the insights:`,\n '- Say what matters most to the question first. Leave out what the tables do not support.',\n '- Every insight cites the table and the rows its figures come from.',\n '- Every number you write appears in a row you cite, as the table shows it or rounded. Never add, subtract, average or otherwise compute a figure yourself. The only other numbers you may write are the length of a table’s window, a date in it, and how many rows you cite.',\n '- Say a figure rose or fell only when a change you quote shows it.',\n '- Name nobody, and write no email address or phone number.',\n '- Plain sentences: no markdown, no headings, no lists.',\n '- When the tables cannot answer part of the question, say so in gap in one sentence with no numbers; otherwise gap is null.',\n '- Whether the site is published, and its address, come only from the Site status table. Page views and visitors never show whether a site is live: never say or suggest a site is not live, not launched or not published because of its traffic.',\n '- Write in the language of the question.',\n].join('\\n')\n\n/** The system blocks both calls send: the rules and the platform's acceptable-use rules. */\nexport const AI_JOB_INSIGHT_SYSTEM: AiSystemBlock[] = [\n { text: `${AI_INSIGHT_RULES}\\n\\n${AI_ACCEPTABLE_USE_BLOCK}`, cacheBreakpoint: true },\n]\n\nconst ZERO_USAGE: AiUsage = { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 }\n\nconst str = (value: unknown): string => (typeof value === 'string' ? value.trim() : '')\n\n/** What the step's calls have spent so far, in the outcome's shape. */\nclass InsightSpend {\n usage: AiUsage = { ...ZERO_USAGE }\n estCostUsd = 0\n stopReason: string | null = null\n\n constructor(readonly model: string) {}\n\n add(result: AiResult): void {\n this.usage = {\n inputTokens: this.usage.inputTokens + result.usage.inputTokens,\n outputTokens: this.usage.outputTokens + result.usage.outputTokens,\n cacheReadTokens: this.usage.cacheReadTokens + result.usage.cacheReadTokens,\n cacheWriteTokens: this.usage.cacheWriteTokens + result.usage.cacheWriteTokens,\n }\n this.estCostUsd = Math.round((this.estCostUsd + result.estCostUsd) * 1_000_000) / 1_000_000\n this.stopReason = result.stopReason\n }\n\n outcome(): Pick<AiJobStepOutcome, 'usage' | 'estCostUsd' | 'model' | 'stopReason' | 'effort'> {\n return { usage: this.usage, estCostUsd: this.estCostUsd, model: this.model, stopReason: this.stopReason, effort: null }\n }\n}\n\n/** The read call's user turn: the question, the window asked for, the readers and, for datasets, the datasets. */\nexport function aiInsightReadPrompt(input: {\n question: string\n days: number\n readers: readonly ResolvedPluginFigureReader[]\n datasets: string | null\n}): string {\n return [\n `Question: ${input.question}`,\n `The window picked on the page: ${input.days} days. Use it unless the question names another window a reader lists.`,\n 'Readers you may read here:',\n aiInsightReaderCatalog(input.readers),\n ...(input.datasets === null ? [] : ['', 'Datasets you may read, with their fields:', input.datasets]),\n ].join('\\n')\n}\n\n/** The answer call's user turn: the question and every table. */\nexport function aiInsightAnswerPrompt(question: string, tables: readonly AiInsightTable[]): string {\n return [`Question: ${question}`, '', 'Tables:', '', tables.map(aiInsightTableText).join('\\n\\n')].join('\\n')\n}\n\n/** What a re-ask tells the model: why nothing it wrote could be kept. */\nexport function aiInsightReaskMessage(check: AiInsightCheck | null): string {\n const reasons = check?.findings.length\n ? `None of those insights could be kept: ${[...new Set(check.findings)].slice(0, 8).join('; ')}.`\n : `That answer did not come through ${AI_INSIGHT_ANSWER_TOOL_NAME}.`\n return `${reasons} Answer again with ${AI_INSIGHT_ANSWER_TOOL_NAME}: cite the rows each insight's figures are in, and write every number as a row you cite shows it.`\n}\n\n/** The reads a surface falls back to when the model named none it may read: the digest's own readers. */\nfunction defaultReads(readers: readonly ResolvedPluginFigureReader[], days: number): AiInsightReadRequest[] {\n const ids = readers.map(({ reader }) => reader.id)\n const preferred = AI_INSIGHT_DIGEST_READERS.filter((id) => ids.includes(id))\n const chosen = preferred.length ? preferred : ids\n return chosen.map((id) => ({\n reader: id,\n days: aiInsightReaderDays(readers.find(({ reader }) => reader.id === id)?.reader.windows ?? [], days),\n params: {},\n }))\n}\n\nasync function readHost(\n firestore: Firestore,\n orgId: string,\n hostId: string | null,\n): Promise<{ host: Record<string, unknown> | null; ok: boolean }> {\n if (!hostId) return { host: null, ok: true }\n const snapshot = await firestore.collection('hosts').doc(hostId).get()\n const host = snapshot.exists ? ((snapshot.data() ?? {}) as Record<string, unknown>) : null\n return { host, ok: Boolean(host) && host?.['orgId'] === orgId }\n}\n\nexport const runAiJobInsightStep: AiJobStepRunner = async (context: AiJobStepContext) => {\n const { job, firestore, signal, now } = context\n const model = context.modelFor?.('job.insight') ?? aiModelForStep('job.insight')\n const spend = new InsightSpend(model)\n const stop = (failure: string): AiJobStepOutcome => ({ outputs: [], ...spend.outcome(), failure })\n\n const surface = aiInsightSurface(job.inputs)\n if (!surface) return stop(AI_INSIGHT_NO_SURFACE_COPY)\n const hostId = job.hostId ?? null\n if (aiInsightSurfaceNeedsSite(surface) && !hostId) return stop(AI_INSIGHT_NO_SITE_COPY)\n // The door checks the caller belongs to the org; that the site does is\n // checked here, before anything about it is read.\n const site = await readHost(firestore, job.orgId, hostId)\n if (!site.ok) return stop(AI_INSIGHT_NO_SITE_COPY)\n const readers = await aiInsightReaders({\n orgId: job.orgId,\n hostId,\n org: context.org ?? null,\n host: site.host,\n surface,\n })\n if (!readers.length) return stop(AI_INSIGHT_NO_READERS_COPY)\n\n const digest = surface === 'digest'\n const days = digest ? AI_INSIGHT_DIGEST_DAYS : aiInsightDays(job.inputs?.['days'])\n const question = digest ? AI_INSIGHT_DIGEST_QUESTION : job.brief.slice(0, AI_INSIGHT_QUESTION_MAX_CHARS)\n const maxTokens = AI_JOB_INSIGHT_STEP_BUDGET.maxTokens(model)\n const allowance = AI_GENERATION_MAX_ATTEMPTS * maxTokens\n const left = () => allowance - spend.usage.outputTokens\n // What the business is and what the owner's edits showed (AGL-3661), so an\n // answer reads the numbers for THIS business. No contact details: an\n // insight names nobody. No publish state either: that is the Site status\n // table's to say, and the rules send the model there.\n const siteContext = await readAiSiteContext(firestore, { orgId: job.orgId, hostId, host: site.host ?? null })\n const system = [\n ...aiInstructionsWithSiteContext(\n AI_JOB_INSIGHT_SYSTEM,\n siteContext ? { ...siteContext, publish: null, contact: false } : null,\n ),\n ]\n // A development run's effort A/B arm (AGL-3781), else the row's.\n const effort = aiDevEffortFor('job.insight') ?? AI_ROUTING_TABLE['job.insight'].effort\n const ask = (messages: AiMessage[], tool: 'read' | 'answer', ceiling: number) =>\n runAiRequest({\n model,\n system,\n messages,\n tools: [tool === 'read' ? aiInsightReadTool() : aiInsightAnswerTool()],\n maxTokens: Math.max(1, Math.min(ceiling, left())),\n ...(AI_ROUTING_TABLE['job.insight'].thinking ? { thinking: AI_ROUTING_TABLE['job.insight'].thinking } : {}),\n ...(effort ? { effort } : {}),\n stream: false,\n ...(signal ? { signal } : {}),\n })\n\n // 1. The reads.\n const base = { orgId: job.orgId, hostId, uid: digest ? null : job.createdBy, now }\n let requests: AiInsightReadRequest[]\n if (digest) {\n requests = defaultReads(readers, days)\n } else {\n const datasets =\n surface === 'datasets'\n ? aiInsightDatasetCatalog(await aiDatasetCatalog(firestore, { orgId: job.orgId, hostId, uid: job.createdBy }))\n : null\n const result = await ask(\n [{ role: 'user', content: aiInsightReadPrompt({ question, days, readers, datasets }) }],\n 'read',\n AI_INSIGHT_READ_MAX_TOKENS,\n )\n spend.add(result)\n if (result.kind === 'refusal') return { outputs: [], ...spend.outcome(), refused: true }\n requests = parseAiInsightReads(result.toolUse.find((use) => use.name === AI_INSIGHT_READ_TOOL_NAME)?.input)\n }\n const maxTables = digest ? AI_INSIGHT_DIGEST_READERS.length : undefined\n let read = await readAiInsightTables(readers, requests, base, maxTables)\n if (!read.tables.length && !digest) read = await readAiInsightTables(readers, defaultReads(readers, days), base)\n if (read.refusals.length) console.warn('ai insight reads refused', { jobId: job.$id, refusals: read.refusals })\n if (!read.tables.length) return stop(AI_INSIGHT_NO_TABLES_COPY)\n // A site's question is told whether the site is live, so traffic is never\n // read as launch status. Appended, so the readers' refs stay as they were.\n const tables =\n !digest && site.host\n ? [...read.tables, aiSiteStatusTable(aiHostPublishContext(site.host), `t${read.tables.length + 1}`)]\n : read.tables\n\n // 2. The answer, and at most one re-ask.\n let messages: AiMessage[] = [{ role: 'user', content: aiInsightAnswerPrompt(question, tables) }]\n let checked: AiInsightCheck | null = null\n for (let attempt = 0; attempt < AI_GENERATION_MAX_ATTEMPTS && left() > 0; attempt += 1) {\n const result = await ask(messages, 'answer', maxTokens)\n spend.add(result)\n if (result.kind === 'refusal') return { outputs: [], ...spend.outcome(), refused: true }\n const answer = parseAiInsightAnswer(result.toolUse.find((use) => use.name === AI_INSIGHT_ANSWER_TOOL_NAME)?.input)\n const check = answer ? checkAiInsightAnswer(answer, tables) : null\n if (check) checked = check\n if (check && (check.kept.length || !answer?.insights.length)) break\n messages = [\n ...messages,\n { role: 'assistant', content: `Answered with ${AI_INSIGHT_ANSWER_TOOL_NAME}.` },\n { role: 'user', content: aiInsightReaskMessage(check) },\n ]\n }\n if (!checked) return stop(AI_INSIGHT_UNREADABLE_COPY)\n\n const record: AiInsightRecord = {\n jobId: job.$id,\n orgId: job.orgId,\n hostId,\n surface,\n createdBy: job.createdBy,\n question: digest ? str(job.brief) || 'Weekly insights' : question,\n days,\n insights: checked.kept,\n gap: checked.gap,\n tables,\n left: checked.left.length,\n week: digest ? str(job.inputs?.['week']) || null : null,\n createdAtMs: now.getTime(),\n }\n if (checked.left.length) {\n console.info('ai insight left out untraced insights', { jobId: job.$id, findings: checked.findings })\n }\n // Keyed by the job, so a step run again replaces its own answer.\n await firestore\n .collection('orgs')\n .doc(job.orgId)\n .collection(AI_INSIGHTS_COLLECTION)\n .doc(job.$id)\n .set({ ...(JSON.parse(JSON.stringify(record)) as AiInsightRecord), expiresAt: job.expiresAt ?? assistExchangeExpiry(now) })\n return {\n outputs: [aiInsightOutput(job, record, str(site.host?.['subdomain']) || null)],\n ...spend.outcome(),\n }\n}\n\n/**\n * Whether a question may be asked here: a surface a person asks from, a site\n * of the job's own org where the surface needs one, and at least one reader\n * the workspace may read. A digest is made by the weekly sweep and never at a\n * door.\n */\nexport async function aiInsightAdmissionRefusal(\n context: AiJobAdmissionContext,\n): Promise<AiJobAdmissionRefusal | null> {\n const surface: AiInsightSurface | null = aiInsightSurface(context.inputs)\n if (!surface || !AI_INSIGHT_ASK_SURFACES.includes(surface)) {\n return { status: 400, error: 'Ask about your numbers from a site’s Analytics, Data or CRM Reports page.' }\n }\n if (aiInsightSurfaceNeedsSite(surface) && !context.hostId) {\n return { status: 400, error: AI_INSIGHT_NO_SITE_COPY }\n }\n const site = await readHost(context.firestore, context.orgId, context.hostId)\n if (!site.ok) return { status: 404, error: 'Unknown site' }\n const readers = await aiInsightReaders({\n orgId: context.orgId,\n hostId: context.hostId,\n org: context.org,\n host: site.host,\n surface,\n })\n return readers.length ? null : { status: 403, error: AI_INSIGHT_NO_READERS_COPY }\n}\n\n/**\n * The insight kind's registrations, called by the console surface\n * (`registerAiJobKinds` in `server.ts`), never made by importing this module\n * (AGL-3025).\n */\nexport function registerAiInsightJob(): void {\n registerAiJobStep('insight', runAiJobInsightStep, { minimumMs: AI_JOB_INSIGHT_STEP_MINIMUM_MS })\n registerAiJobAdmission('insight', aiInsightAdmissionRefusal)\n}\n"],"names":["AI_INSIGHT_ASK_SURFACES","AI_INSIGHT_DIGEST_DAYS","AI_INSIGHT_DIGEST_READERS","AI_INSIGHT_QUESTION_MAX_CHARS","AI_INSIGHTS_COLLECTION","aiInsightDays","aiInsightOutput","aiInsightSurface","aiInsightSurfaceNeedsSite","aiHostPublishContext","aiSiteStatusTable","aiInstructionsWithSiteContext","readAiSiteContext","AI_ROUTING_TABLE","aiModelForStep","aiDevEffortFor","AI_ACCEPTABLE_USE_BLOCK","runAiRequest","AI_GENERATION_MAX_ATTEMPTS","checkAiInsightAnswer","AI_INSIGHT_ANSWER_TOOL_NAME","AI_INSIGHT_READ_TOOL_NAME","aiInsightAnswerTool","aiInsightReadTool","parseAiInsightAnswer","parseAiInsightReads","aiDatasetCatalog","aiInsightDatasetCatalog","aiInsightReaderCatalog","aiInsightReaderDays","aiInsightReaders","aiInsightTableText","readAiInsightTables","assistExchangeExpiry","registerAiJobAdmission","AI_INSIGHT_READ_MAX_TOKENS","AI_JOB_INSIGHT_STEP_BUDGET","AI_JOB_INSIGHT_STEP_MINIMUM_MS","registerAiJobStep","AI_INSIGHT_NO_SURFACE_COPY","AI_INSIGHT_NO_SITE_COPY","AI_INSIGHT_NO_READERS_COPY","AI_INSIGHT_NO_TABLES_COPY","AI_INSIGHT_UNREADABLE_COPY","AI_INSIGHT_DIGEST_QUESTION","AI_INSIGHT_RULES","join","AI_JOB_INSIGHT_SYSTEM","text","cacheBreakpoint","ZERO_USAGE","inputTokens","outputTokens","cacheReadTokens","cacheWriteTokens","str","value","trim","InsightSpend","add","result","usage","estCostUsd","Math","round","stopReason","outcome","model","effort","aiInsightReadPrompt","input","question","days","readers","datasets","aiInsightAnswerPrompt","tables","map","aiInsightReaskMessage","check","reasons","findings","length","Set","slice","defaultReads","ids","reader","id","preferred","filter","includes","chosen","find","windows","params","readHost","firestore","orgId","hostId","snapshot","host","ok","collection","doc","get","exists","data","Boolean","runAiJobInsightStep","context","job","site","signal","now","modelFor","spend","stop","failure","outputs","surface","inputs","org","digest","brief","maxTokens","allowance","left","siteContext","system","publish","contact","ask","messages","tool","ceiling","tools","max","min","thinking","stream","base","uid","createdBy","requests","role","content","kind","refused","toolUse","use","name","maxTables","undefined","read","refusals","console","warn","jobId","$id","checked","attempt","answer","kept","insights","record","gap","week","createdAtMs","getTime","info","set","JSON","parse","stringify","expiresAt","aiInsightAdmissionRefusal","status","error","registerAiInsightJob","minimumMs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/jobs/ai-job-insight-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\nimport type { ResolvedPluginFigureReader } from '@aglyn/aglyn/plugin-manager/plugin-figures'\nimport {\n AI_INSIGHT_ASK_SURFACES,\n AI_INSIGHT_DIGEST_DAYS,\n AI_INSIGHT_DIGEST_READERS,\n AI_INSIGHT_QUESTION_MAX_CHARS,\n AI_INSIGHTS_COLLECTION,\n aiInsightDays,\n aiInsightOutput,\n aiInsightSurface,\n aiInsightSurfaceNeedsSite,\n type AiInsightRecord,\n type AiInsightSurface,\n type AiInsightTable,\n} from '../model/ai-insight'\nimport { aiHostPublishContext, aiSiteStatusTable } from '../model/ai-host-publish-context'\nimport { aiInstructionsWithSiteContext } from '../model/ai-site-context'\nimport { readAiSiteContext } from '../runtime/site-context'\nimport { AI_ROUTING_TABLE, aiModelForStep } from '../providers/routing'\nimport { aiDevEffortFor } from '../runtime/ai-dev-env'\nimport {\n AI_ACCEPTABLE_USE_BLOCK,\n runAiRequest,\n type AiMessage,\n type AiResult,\n type AiSystemBlock,\n type AiUsage,\n} from '../runtime/ai-runtime'\nimport { AI_GENERATION_MAX_ATTEMPTS } from '../runtime/ai-generation-bounds'\nimport { checkAiInsightAnswer, type AiInsightCheck } from '../runtime/ai-insight-check'\nimport {\n AI_INSIGHT_ANSWER_TOOL_NAME,\n AI_INSIGHT_READ_TOOL_NAME,\n aiInsightAnswerTool,\n aiInsightReadTool,\n parseAiInsightAnswer,\n parseAiInsightReads,\n type AiInsightReadRequest,\n} from '../tools/ai-insight-tool'\nimport { aiDatasetCatalog } from '../insights/ai-dataset-catalog'\nimport {\n aiInsightDatasetCatalog,\n aiInsightReaderCatalog,\n aiInsightReaderDays,\n aiInsightReaders,\n aiInsightTableText,\n readAiInsightTables,\n} from '../insights/ai-insight-readers'\nimport { assistExchangeExpiry } from '../usage/assist-usage'\nimport { registerAiJobAdmission, type AiJobAdmissionContext, type AiJobAdmissionRefusal } from './ai-job-admission'\nimport { AI_INSIGHT_READ_MAX_TOKENS, AI_JOB_INSIGHT_STEP_BUDGET, AI_JOB_INSIGHT_STEP_MINIMUM_MS } from './ai-job-insight-budget'\nimport type { AiJobStepContext, AiJobStepOutcome, AiJobStepRunner } from './ai-job-text-step'\nimport { registerAiJobStep } from './ai-jobs'\n\n/**\n * The `insight` step (AGL-2915): a question about a site's figures, answered\n * from tables code read, with every insight traced to the rows it cites.\n *\n * ## Two exchanges, and the model never writes a query\n *\n * 1. **The reads.** The model is shown the question and the readers this job\n * may read — each an id, what it answers, its windows and parameters — and\n * answers `read_figures` with a choice among them. It names nothing else: no\n * collection, no field path, no filter. A choice that names no reader this\n * job may read is dropped, and a job left with none reads the surface's\n * defaults. A weekly digest makes no read call: code reads the digest's\n * readers.\n * 2. **The answer.** Code reads the tables through the owners' readers, and the\n * model is shown them and answers `submit_insights`. The trace\n * (`runtime/ai-insight-check.ts`) keeps each insight whose every number is\n * in a row it cites and leaves out the rest. An answer that is not a call,\n * or whose every insight was left out, is asked for once more with the\n * reasons; what the second answer keeps is the answer.\n *\n * Both calls share one allowance of output, twice the routing ceiling, which\n * is what the step's least time is planned against.\n *\n * ## What reaches the model\n *\n * The question, the names and descriptions of the readers, the tables, the\n * site's publish state (published or not, its address, its pages' paths), and\n * for a datasets question the names of the datasets the member may see with\n * their fields' names and types. A table holds counts, sums and rates labeled\n * by a page path, a referring site, a form's, a service's, a product's or a\n * campaign's name, or the values of a dataset field with at most sixty\n * different values that at least three records share. No\n * record, visitor, contact, order, booking, submission or recipient is read\n * into a prompt, and every text cell is masked of email addresses and phone\n * numbers on its way into a table.\n *\n * ## What it writes\n *\n * The answer, at `orgs/{orgId}/aiInsights/{jobId}` under the job's own\n * expiry, and an output that names it and says how many insights it holds.\n * Nothing else: no draft, no setting, no message.\n */\n\ntype Firestore = FirebaseFirestore.Firestore\n\nexport const AI_INSIGHT_NO_SURFACE_COPY = 'This question does not say which page it was asked from.'\nexport const AI_INSIGHT_NO_SITE_COPY = 'Open the site whose numbers you are asking about.'\nexport const AI_INSIGHT_NO_READERS_COPY =\n 'There are no figures to answer from here yet: the features this page reports on are not on for this workspace.'\nexport const AI_INSIGHT_NO_TABLES_COPY = 'The figures could not be read. Try again in a moment.'\nexport const AI_INSIGHT_UNREADABLE_COPY = 'The AI did not answer with insights. Try asking in different words.'\n\n/** The digest's question: what a week's insights cover, in the order a person reads them. */\nexport const AI_INSIGHT_DIGEST_QUESTION =\n 'What changed on this site this week? Write the week’s insights: the change in traffic, the most viewed page, the form that turned the most views into submissions, a campaign that did better than the rest, and any day that stood out — only those the tables support.'\n\n/** The rules both calls are sent: static, byte-identical for every workspace. */\nexport const AI_INSIGHT_RULES = [\n 'You answer a workspace owner’s questions about their own figures: page views, orders, bookings, forms, campaigns, A/B tests and datasets. You never see a record, and you never write a query: code reads figures through fixed readers and gives you their tables.',\n '',\n `When you are given a question and a list of readers, call ${AI_INSIGHT_READ_TOOL_NAME} once with the readers whose tables answer it, most useful first, and the window each should cover. Choose only readers from the list, with their parameters' values taken from what the list and the question give you.`,\n '',\n `When you are given tables, call ${AI_INSIGHT_ANSWER_TOOL_NAME} once. Each table has a handle (t1, t2, …) and numbered rows. Rules for the insights:`,\n '- Say what matters most to the question first. Leave out what the tables do not support.',\n '- Every insight cites the table and the rows its figures come from.',\n '- Every number you write appears in a row you cite, as the table shows it or rounded. Never add, subtract, average or otherwise compute a figure yourself. The only other numbers you may write are the length of a table’s window, a date in it, and how many rows you cite.',\n '- Say a figure rose or fell only when a change you quote shows it.',\n '- Name nobody, and write no email address or phone number.',\n '- Plain sentences: no markdown, no headings, no lists.',\n '- When the tables cannot answer part of the question, say so in gap in one sentence with no numbers; otherwise gap is null.',\n '- Whether the site is published, its address and which pages are published come only from the Site status table. Page views and visitors never show whether a site or a page is live: never say or suggest a site is not live, not launched or not published because of its traffic, and never call the pages a views table lists the published ones.',\n '- Write in the language of the question.',\n].join('\\n')\n\n/** The system blocks both calls send: the rules and the platform's acceptable-use rules. */\nexport const AI_JOB_INSIGHT_SYSTEM: AiSystemBlock[] = [\n { text: `${AI_INSIGHT_RULES}\\n\\n${AI_ACCEPTABLE_USE_BLOCK}`, cacheBreakpoint: true },\n]\n\nconst ZERO_USAGE: AiUsage = { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 }\n\nconst str = (value: unknown): string => (typeof value === 'string' ? value.trim() : '')\n\n/** What the step's calls have spent so far, in the outcome's shape. */\nclass InsightSpend {\n usage: AiUsage = { ...ZERO_USAGE }\n estCostUsd = 0\n stopReason: string | null = null\n\n constructor(readonly model: string) {}\n\n add(result: AiResult): void {\n this.usage = {\n inputTokens: this.usage.inputTokens + result.usage.inputTokens,\n outputTokens: this.usage.outputTokens + result.usage.outputTokens,\n cacheReadTokens: this.usage.cacheReadTokens + result.usage.cacheReadTokens,\n cacheWriteTokens: this.usage.cacheWriteTokens + result.usage.cacheWriteTokens,\n }\n this.estCostUsd = Math.round((this.estCostUsd + result.estCostUsd) * 1_000_000) / 1_000_000\n this.stopReason = result.stopReason\n }\n\n outcome(): Pick<AiJobStepOutcome, 'usage' | 'estCostUsd' | 'model' | 'stopReason' | 'effort'> {\n return { usage: this.usage, estCostUsd: this.estCostUsd, model: this.model, stopReason: this.stopReason, effort: null }\n }\n}\n\n/** The read call's user turn: the question, the window asked for, the readers and, for datasets, the datasets. */\nexport function aiInsightReadPrompt(input: {\n question: string\n days: number\n readers: readonly ResolvedPluginFigureReader[]\n datasets: string | null\n}): string {\n return [\n `Question: ${input.question}`,\n `The window picked on the page: ${input.days} days. Use it unless the question names another window a reader lists.`,\n 'Readers you may read here:',\n aiInsightReaderCatalog(input.readers),\n ...(input.datasets === null ? [] : ['', 'Datasets you may read, with their fields:', input.datasets]),\n ].join('\\n')\n}\n\n/** The answer call's user turn: the question and every table. */\nexport function aiInsightAnswerPrompt(question: string, tables: readonly AiInsightTable[]): string {\n return [`Question: ${question}`, '', 'Tables:', '', tables.map(aiInsightTableText).join('\\n\\n')].join('\\n')\n}\n\n/** What a re-ask tells the model: why nothing it wrote could be kept. */\nexport function aiInsightReaskMessage(check: AiInsightCheck | null): string {\n const reasons = check?.findings.length\n ? `None of those insights could be kept: ${[...new Set(check.findings)].slice(0, 8).join('; ')}.`\n : `That answer did not come through ${AI_INSIGHT_ANSWER_TOOL_NAME}.`\n return `${reasons} Answer again with ${AI_INSIGHT_ANSWER_TOOL_NAME}: cite the rows each insight's figures are in, and write every number as a row you cite shows it.`\n}\n\n/** The reads a surface falls back to when the model named none it may read: the digest's own readers. */\nfunction defaultReads(readers: readonly ResolvedPluginFigureReader[], days: number): AiInsightReadRequest[] {\n const ids = readers.map(({ reader }) => reader.id)\n const preferred = AI_INSIGHT_DIGEST_READERS.filter((id) => ids.includes(id))\n const chosen = preferred.length ? preferred : ids\n return chosen.map((id) => ({\n reader: id,\n days: aiInsightReaderDays(readers.find(({ reader }) => reader.id === id)?.reader.windows ?? [], days),\n params: {},\n }))\n}\n\nasync function readHost(\n firestore: Firestore,\n orgId: string,\n hostId: string | null,\n): Promise<{ host: Record<string, unknown> | null; ok: boolean }> {\n if (!hostId) return { host: null, ok: true }\n const snapshot = await firestore.collection('hosts').doc(hostId).get()\n const host = snapshot.exists ? ((snapshot.data() ?? {}) as Record<string, unknown>) : null\n return { host, ok: Boolean(host) && host?.['orgId'] === orgId }\n}\n\nexport const runAiJobInsightStep: AiJobStepRunner = async (context: AiJobStepContext) => {\n const { job, firestore, signal, now } = context\n const model = context.modelFor?.('job.insight') ?? aiModelForStep('job.insight')\n const spend = new InsightSpend(model)\n const stop = (failure: string): AiJobStepOutcome => ({ outputs: [], ...spend.outcome(), failure })\n\n const surface = aiInsightSurface(job.inputs)\n if (!surface) return stop(AI_INSIGHT_NO_SURFACE_COPY)\n const hostId = job.hostId ?? null\n if (aiInsightSurfaceNeedsSite(surface) && !hostId) return stop(AI_INSIGHT_NO_SITE_COPY)\n // The door checks the caller belongs to the org; that the site does is\n // checked here, before anything about it is read.\n const site = await readHost(firestore, job.orgId, hostId)\n if (!site.ok) return stop(AI_INSIGHT_NO_SITE_COPY)\n const readers = await aiInsightReaders({\n orgId: job.orgId,\n hostId,\n org: context.org ?? null,\n host: site.host,\n surface,\n })\n if (!readers.length) return stop(AI_INSIGHT_NO_READERS_COPY)\n\n const digest = surface === 'digest'\n const days = digest ? AI_INSIGHT_DIGEST_DAYS : aiInsightDays(job.inputs?.['days'])\n const question = digest ? AI_INSIGHT_DIGEST_QUESTION : job.brief.slice(0, AI_INSIGHT_QUESTION_MAX_CHARS)\n const maxTokens = AI_JOB_INSIGHT_STEP_BUDGET.maxTokens(model)\n const allowance = AI_GENERATION_MAX_ATTEMPTS * maxTokens\n const left = () => allowance - spend.usage.outputTokens\n // What the business is and what the owner's edits showed (AGL-3661), so an\n // answer reads the numbers for THIS business. No contact details: an\n // insight names nobody. No publish state either: that is the Site status\n // table's to say, and the rules send the model there.\n const siteContext = await readAiSiteContext(firestore, { orgId: job.orgId, hostId, host: site.host ?? null })\n const system = [\n ...aiInstructionsWithSiteContext(\n AI_JOB_INSIGHT_SYSTEM,\n siteContext ? { ...siteContext, publish: null, contact: false } : null,\n ),\n ]\n // A development run's effort A/B arm (AGL-3781), else the row's.\n const effort = aiDevEffortFor('job.insight') ?? AI_ROUTING_TABLE['job.insight'].effort\n const ask = (messages: AiMessage[], tool: 'read' | 'answer', ceiling: number) =>\n runAiRequest({\n model,\n system,\n messages,\n tools: [tool === 'read' ? aiInsightReadTool() : aiInsightAnswerTool()],\n maxTokens: Math.max(1, Math.min(ceiling, left())),\n ...(AI_ROUTING_TABLE['job.insight'].thinking ? { thinking: AI_ROUTING_TABLE['job.insight'].thinking } : {}),\n ...(effort ? { effort } : {}),\n stream: false,\n ...(signal ? { signal } : {}),\n })\n\n // 1. The reads.\n const base = { orgId: job.orgId, hostId, uid: digest ? null : job.createdBy, now }\n let requests: AiInsightReadRequest[]\n if (digest) {\n requests = defaultReads(readers, days)\n } else {\n const datasets =\n surface === 'datasets'\n ? aiInsightDatasetCatalog(await aiDatasetCatalog(firestore, { orgId: job.orgId, hostId, uid: job.createdBy }))\n : null\n const result = await ask(\n [{ role: 'user', content: aiInsightReadPrompt({ question, days, readers, datasets }) }],\n 'read',\n AI_INSIGHT_READ_MAX_TOKENS,\n )\n spend.add(result)\n if (result.kind === 'refusal') return { outputs: [], ...spend.outcome(), refused: true }\n requests = parseAiInsightReads(result.toolUse.find((use) => use.name === AI_INSIGHT_READ_TOOL_NAME)?.input)\n }\n const maxTables = digest ? AI_INSIGHT_DIGEST_READERS.length : undefined\n let read = await readAiInsightTables(readers, requests, base, maxTables)\n if (!read.tables.length && !digest) read = await readAiInsightTables(readers, defaultReads(readers, days), base)\n if (read.refusals.length) console.warn('ai insight reads refused', { jobId: job.$id, refusals: read.refusals })\n if (!read.tables.length) return stop(AI_INSIGHT_NO_TABLES_COPY)\n // A site's question is told whether the site is live, so traffic is never\n // read as launch status. Appended, so the readers' refs stay as they were.\n const tables =\n !digest && site.host\n ? [...read.tables, aiSiteStatusTable(aiHostPublishContext(site.host), `t${read.tables.length + 1}`)]\n : read.tables\n\n // 2. The answer, and at most one re-ask.\n let messages: AiMessage[] = [{ role: 'user', content: aiInsightAnswerPrompt(question, tables) }]\n let checked: AiInsightCheck | null = null\n for (let attempt = 0; attempt < AI_GENERATION_MAX_ATTEMPTS && left() > 0; attempt += 1) {\n const result = await ask(messages, 'answer', maxTokens)\n spend.add(result)\n if (result.kind === 'refusal') return { outputs: [], ...spend.outcome(), refused: true }\n const answer = parseAiInsightAnswer(result.toolUse.find((use) => use.name === AI_INSIGHT_ANSWER_TOOL_NAME)?.input)\n const check = answer ? checkAiInsightAnswer(answer, tables) : null\n if (check) checked = check\n if (check && (check.kept.length || !answer?.insights.length)) break\n messages = [\n ...messages,\n { role: 'assistant', content: `Answered with ${AI_INSIGHT_ANSWER_TOOL_NAME}.` },\n { role: 'user', content: aiInsightReaskMessage(check) },\n ]\n }\n if (!checked) return stop(AI_INSIGHT_UNREADABLE_COPY)\n\n const record: AiInsightRecord = {\n jobId: job.$id,\n orgId: job.orgId,\n hostId,\n surface,\n createdBy: job.createdBy,\n question: digest ? str(job.brief) || 'Weekly insights' : question,\n days,\n insights: checked.kept,\n gap: checked.gap,\n tables,\n left: checked.left.length,\n week: digest ? str(job.inputs?.['week']) || null : null,\n createdAtMs: now.getTime(),\n }\n if (checked.left.length) {\n console.info('ai insight left out untraced insights', { jobId: job.$id, findings: checked.findings })\n }\n // Keyed by the job, so a step run again replaces its own answer.\n await firestore\n .collection('orgs')\n .doc(job.orgId)\n .collection(AI_INSIGHTS_COLLECTION)\n .doc(job.$id)\n .set({ ...(JSON.parse(JSON.stringify(record)) as AiInsightRecord), expiresAt: job.expiresAt ?? assistExchangeExpiry(now) })\n return {\n outputs: [aiInsightOutput(job, record, str(site.host?.['subdomain']) || null)],\n ...spend.outcome(),\n }\n}\n\n/**\n * Whether a question may be asked here: a surface a person asks from, a site\n * of the job's own org where the surface needs one, and at least one reader\n * the workspace may read. A digest is made by the weekly sweep and never at a\n * door.\n */\nexport async function aiInsightAdmissionRefusal(\n context: AiJobAdmissionContext,\n): Promise<AiJobAdmissionRefusal | null> {\n const surface: AiInsightSurface | null = aiInsightSurface(context.inputs)\n if (!surface || !AI_INSIGHT_ASK_SURFACES.includes(surface)) {\n return { status: 400, error: 'Ask about your numbers from a site’s Analytics, Data or CRM Reports page.' }\n }\n if (aiInsightSurfaceNeedsSite(surface) && !context.hostId) {\n return { status: 400, error: AI_INSIGHT_NO_SITE_COPY }\n }\n const site = await readHost(context.firestore, context.orgId, context.hostId)\n if (!site.ok) return { status: 404, error: 'Unknown site' }\n const readers = await aiInsightReaders({\n orgId: context.orgId,\n hostId: context.hostId,\n org: context.org,\n host: site.host,\n surface,\n })\n return readers.length ? null : { status: 403, error: AI_INSIGHT_NO_READERS_COPY }\n}\n\n/**\n * The insight kind's registrations, called by the console surface\n * (`registerAiJobKinds` in `server.ts`), never made by importing this module\n * (AGL-3025).\n */\nexport function registerAiInsightJob(): void {\n registerAiJobStep('insight', runAiJobInsightStep, { minimumMs: AI_JOB_INSIGHT_STEP_MINIMUM_MS })\n registerAiJobAdmission('insight', aiInsightAdmissionRefusal)\n}\n"],"names":["AI_INSIGHT_ASK_SURFACES","AI_INSIGHT_DIGEST_DAYS","AI_INSIGHT_DIGEST_READERS","AI_INSIGHT_QUESTION_MAX_CHARS","AI_INSIGHTS_COLLECTION","aiInsightDays","aiInsightOutput","aiInsightSurface","aiInsightSurfaceNeedsSite","aiHostPublishContext","aiSiteStatusTable","aiInstructionsWithSiteContext","readAiSiteContext","AI_ROUTING_TABLE","aiModelForStep","aiDevEffortFor","AI_ACCEPTABLE_USE_BLOCK","runAiRequest","AI_GENERATION_MAX_ATTEMPTS","checkAiInsightAnswer","AI_INSIGHT_ANSWER_TOOL_NAME","AI_INSIGHT_READ_TOOL_NAME","aiInsightAnswerTool","aiInsightReadTool","parseAiInsightAnswer","parseAiInsightReads","aiDatasetCatalog","aiInsightDatasetCatalog","aiInsightReaderCatalog","aiInsightReaderDays","aiInsightReaders","aiInsightTableText","readAiInsightTables","assistExchangeExpiry","registerAiJobAdmission","AI_INSIGHT_READ_MAX_TOKENS","AI_JOB_INSIGHT_STEP_BUDGET","AI_JOB_INSIGHT_STEP_MINIMUM_MS","registerAiJobStep","AI_INSIGHT_NO_SURFACE_COPY","AI_INSIGHT_NO_SITE_COPY","AI_INSIGHT_NO_READERS_COPY","AI_INSIGHT_NO_TABLES_COPY","AI_INSIGHT_UNREADABLE_COPY","AI_INSIGHT_DIGEST_QUESTION","AI_INSIGHT_RULES","join","AI_JOB_INSIGHT_SYSTEM","text","cacheBreakpoint","ZERO_USAGE","inputTokens","outputTokens","cacheReadTokens","cacheWriteTokens","str","value","trim","InsightSpend","add","result","usage","estCostUsd","Math","round","stopReason","outcome","model","effort","aiInsightReadPrompt","input","question","days","readers","datasets","aiInsightAnswerPrompt","tables","map","aiInsightReaskMessage","check","reasons","findings","length","Set","slice","defaultReads","ids","reader","id","preferred","filter","includes","chosen","find","windows","params","readHost","firestore","orgId","hostId","snapshot","host","ok","collection","doc","get","exists","data","Boolean","runAiJobInsightStep","context","job","site","signal","now","modelFor","spend","stop","failure","outputs","surface","inputs","org","digest","brief","maxTokens","allowance","left","siteContext","system","publish","contact","ask","messages","tool","ceiling","tools","max","min","thinking","stream","base","uid","createdBy","requests","role","content","kind","refused","toolUse","use","name","maxTables","undefined","read","refusals","console","warn","jobId","$id","checked","attempt","answer","kept","insights","record","gap","week","createdAtMs","getTime","info","set","JSON","parse","stringify","expiresAt","aiInsightAdmissionRefusal","status","error","registerAiInsightJob","minimumMs"],"mappings":"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"}
|