@aglyn/plugins-ai 1.0.0-beta.287 → 1.0.0-beta.288
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/jobs/ai-business-profile-prefill.js +6 -3
- package/src/lib/jobs/ai-business-profile-prefill.js.map +1 -1
- package/src/lib/jobs/ai-job-site-datasets.js +5 -3
- package/src/lib/jobs/ai-job-site-datasets.js.map +1 -1
- package/src/lib/jobs/ai-job-text-step.js +2 -1
- package/src/lib/jobs/ai-job-text-step.js.map +1 -1
- package/src/lib/jobs/ai-layout-stock-photos.d.ts +97 -4
- package/src/lib/jobs/ai-layout-stock-photos.js +635 -154
- package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
- package/src/lib/jobs/fixtures/ai-site-agl4092-datasets.d.ts +120 -0
- package/src/lib/jobs/fixtures/ai-site-agl4092-datasets.js +410 -0
- package/src/lib/jobs/fixtures/ai-site-agl4092-datasets.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl4092-recordings.d.ts +26 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl4092-recordings.js +714 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl4092-recordings.js.map +1 -0
- package/src/lib/layout-language/ai-layout-pictures.d.ts +9 -1
- package/src/lib/layout-language/ai-layout-pictures.js +14 -5
- package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
- package/src/lib/model/ai-plan-said-sections.d.ts +12 -3
- package/src/lib/model/ai-plan-said-sections.js +22 -5
- package/src/lib/model/ai-plan-said-sections.js.map +1 -1
- package/src/lib/model/ai-site-context.d.ts +6 -2
- package/src/lib/model/ai-site-context.js +8 -2
- package/src/lib/model/ai-site-context.js.map +1 -1
- package/src/lib/runtime/ai-dataset-generation.d.ts +26 -5
- package/src/lib/runtime/ai-dataset-generation.js +110 -9
- package/src/lib/runtime/ai-dataset-generation.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.js +2 -1
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-doctrine.d.ts +5 -4
- package/src/lib/runtime/ai-doctrine.js +2 -1
- package/src/lib/runtime/ai-doctrine.js.map +1 -1
- package/src/lib/server/assist-build.d.ts +15 -1
- package/src/lib/server/assist-build.js +29 -3
- package/src/lib/server/assist-build.js.map +1 -1
|
@@ -58,7 +58,8 @@ import { runAiOverlayCopy } from "./ai-job-overlay-copy.js";
|
|
|
58
58
|
* customer's brief and the org's inputs never enter it.
|
|
59
59
|
*/ export const AI_JOB_TEXT_SYSTEM = [
|
|
60
60
|
{
|
|
61
|
-
text: 'You write short, publishable copy for a website builder. You are ' + 'given a brief from the person who owns the site. Answer with the ' + 'copy only: no preamble, no headings unless the brief asks for them, ' + 'no closing remarks, no markdown fences. Keep to the length the brief ' + 'implies; when it implies none, write under 150 words. Write in the ' + 'language of the brief. Never invent facts, prices, names or claims ' +
|
|
61
|
+
text: 'You write short, publishable copy for a website builder. You are ' + 'given a brief from the person who owns the site. Answer with the ' + 'copy only: no preamble, no headings unless the brief asks for them, ' + 'no closing remarks, no markdown fences. Keep to the length the brief ' + 'implies; when it implies none, write under 150 words. Write in the ' + 'language of the brief. Never invent facts, prices, names or claims ' + // AGL-4092: never a bracketed placeholder, which a page shows as written.
|
|
62
|
+
'the brief did not give you; where a detail is missing, leave it out ' + 'and write the sentence without it.',
|
|
62
63
|
cacheBreakpoint: true
|
|
63
64
|
}
|
|
64
65
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/jobs/ai-job-text-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 { AglynOrgBilling } from '@aglyn/aglyn/foundation/definitions/org-billing.types'\nimport type {\n AiJob,\n AiJobOutput,\n AiJobPlan,\n AiJobReview,\n AiJobInputRequest,\n AiJobItemFailure,\n AiJobItemLedger,\n AiJobItemStatus,\n AiJobSitePublish,\n} from '../model/ai-jobs.types'\nimport { AI_STEP_TIERS, type AiStepKind } from '../providers/catalog'\nimport { AI_ROUTING_TABLE, aiModelForStep } from '../providers/routing'\nimport { aiDevEffortFor } from '../runtime/ai-dev-env'\nimport { runAiRequest, type AiEffort, type AiSystemBlock } from '../runtime/ai-runtime'\nimport type { AssistTokenUsage } from '../usage/assist-usage'\nimport type { AiSiteImportState } from '../model/ai-site-import'\nimport type { AiSitePhotos } from '../model/ai-site-photos'\nimport { aiJobStepBudget } from './ai-job-budget'\nimport { aiOverlayCopyRequested } from '../model/ai-overlay-copy'\nimport { runAiOverlayCopy } from './ai-job-overlay-copy'\n\n/**\n * The `text` step (AGL-2904): a brief in, a short piece of copy out.\n *\n * The one step kind this issue ships for real, so the state machine — the\n * lease, the reservation, the record, the beat — is exercised end to end by\n * something that spends tokens, rather than by a stub that could pass with\n * the meter unplugged. Every other kind refuses until its own issue lands.\n *\n * The balanced tier with adaptive thinking: a brief is open-ended in a way the copy\n * assistant's element mode is not, and the cost is one call per job. The\n * static system block is cached; the brief rides in the user turn, so no\n * per-org byte sits inside the cached prefix (AGL-2352, enforced by the\n * runtime before the request leaves).\n */\n\n/** The model the text step runs on: the routing table's answer for `job.text`. */\nexport function aiJobTextModel(): string {\n return aiModelForStep('job.text')\n}\n\n/** The text step's answer ceiling, from the routing table. */\nexport const AI_JOB_TEXT_MAX_TOKENS = AI_ROUTING_TABLE['job.text'].maxTokens\n\n/**\n * The text step's time (AGL-3035): ONE request — no re-ask, and no site\n * inventory to look anything up in — at the routing table's ceiling on the\n * tier `job.text` is served from, with the step's reads and writes. That fits\n * an inline door's budget, so a door runs a text job where it is asked for,\n * and the least time is the helper's worst case rather than a figure anyone\n * chose; a slower tier asks less so its worst case still fits.\n */\nexport const AI_JOB_TEXT_STEP_BUDGET = aiJobStepBudget({\n tier: AI_STEP_TIERS['job.text'],\n maxTokens: AI_JOB_TEXT_MAX_TOKENS,\n attempts: 1,\n lookups: 0,\n})\n\n/** The least time one text step needs before it starts. */\nexport const AI_JOB_TEXT_STEP_MINIMUM_MS = AI_JOB_TEXT_STEP_BUDGET.minimumMs\n\n/** How much of a brief is sent. Past this a brief is a document, not a brief. */\nexport const AI_JOB_BRIEF_MAX_CHARS = 4_000\n\n/**\n * What a step hands back to the machine. The machine meters `usage` at\n * `model`'s rates, records the step and appends the outputs; a step never\n * touches the job document or the meter itself.\n */\nexport interface AiJobStepOutcome {\n outputs: AiJobOutput[]\n /**\n * The step made progress and has more of the same work to do (AGL-2910):\n * a site audit works through its pages a batch at a time. The machine\n * records this pass — its spend and its outputs — and hands the SAME step\n * back to run again, so every pass is one reservation and one provider\n * exchange, and the job document says how far it got.\n */\n continue?: boolean\n usage: AssistTokenUsage\n estCostUsd: number\n model: string\n stopReason: string | null\n /**\n * The thinking effort the request asked for, recorded on the step\n * (AGL-2937); absent or `null` when the request named none.\n */\n effort?: AiEffort | null\n /** The model declined the brief (`stop_reason: 'refusal'`). Tokens were spent. */\n refused?: boolean\n /**\n * The model answered and nothing usable came of it — no structured answer\n * even after the step's own re-ask, say (AGL-2938). Tokens were spent, so\n * the machine meters the step before it fails the job with this sentence,\n * which is customer-safe and the only thing a customer reads.\n */\n failure?: string\n /** The plan the plan step proposed, which the machine keeps on the job (AGL-2935). */\n plan?: AiJobPlan\n /**\n * The step stopped for a person (AGL-2935). The machine records what it\n * spent and parks the job `needs_review`: a `plan` review completes the\n * step, so confirming runs the next one; a `doctrine` review hands the\n * step back, so trying again runs the same one.\n */\n review?: AiJobReview\n /**\n * With a `plan` review: the plan needs an answer only the person can give\n * first (AGL-3978) — a tracking change with no pixel ID. The machine keeps\n * the plan and its review and parks the job `needs_input` with these\n * fields instead of `needs_review`; the answer returns it to the review.\n */\n input?: AiJobInputRequest\n /**\n * The answer was refused by the platform's own checks, not the model's\n * (AGL-3594): the machine meters the step as any other and then gives the\n * job's credits back to the meters it was charged to (`refundJobCredits`),\n * a bounded number of times a day.\n */\n uncredited?: boolean\n /**\n * The `failure` is the workspace's own limit, not a fault of ours: the\n * month's Free AI credits are spent (a 429 from the kind's admission, asked\n * when the plan is kept). The machine fails the job and gives the step's\n * credits back exactly as for our failure, but announces it as NOT ours, so\n * no staff alert is raised for a customer reaching their allowance.\n */\n customerLimit?: boolean\n /**\n * What a guided site start put live on its last pass (AGL-3596), kept on\n * the job by the machine in the write that records the pass: a step never\n * writes the job document itself.\n */\n sitePublish?: AiJobSitePublish\n /**\n * A `build` pass's unit and what it came to (AGL-3616), which the machine\n * writes to the job's item ledger in the transaction that records the\n * pass's spend. An item's failure is never the step's: it is a row, and\n * the build goes on.\n */\n item?: AiJobItemOutcome\n /** A `build`'s ledger to start from, written by the machine in the same transaction (AGL-3616). */\n items?: AiJobItemLedger[]\n /**\n * An `import` job's waves after this pass (AGL-3976), kept on the job by\n * the machine in the write that records the pass: a step never writes the\n * job document itself.\n */\n siteImport?: AiSiteImportState\n /**\n * A `site` job's pictures left on a starter photo after this pass\n * (AGL-3988), whole: what its late photo pass fills before the site is\n * published. A page's or a dataset's pass reports its own; the site step\n * merges them and the machine keeps the result on the job.\n */\n sitePhotos?: AiSitePhotos\n}\n\n/** What one `build` pass came to for the unit it ran (AGL-3616). */\nexport interface AiJobItemOutcome {\n slot: string\n /** `running` while the unit asks for another pass of its own. */\n status: AiJobItemStatus\n failure?: AiJobItemFailure | null\n /** Customer-safe: what the person should know about the item. */\n note?: string | null\n degradedBy?: string[]\n /** The ids of the outputs this pass produced for the item. */\n outputs?: string[]\n}\n\nexport interface AiJobStepContext {\n job: AiJob\n stepIndex: number\n now: Date\n /** Aborts the provider call when the runner's budget ends. */\n signal?: AbortSignal\n /**\n * The Admin SDK handle the machine runs on, for a step that reads what it\n * builds from — a site's theme, say — or writes a draft. A step never\n * writes the job document, the meter or the lease through it.\n */\n firestore: FirebaseFirestore.Firestore\n /** The org document the machine read for the step's reservation. */\n org?: Partial<AglynOrgBilling> | null\n /**\n * The model a step of this kind runs on for THIS job (AGL-2942): the\n * creator's pick where the plan and the allotment allowlists allow it,\n * the routing table otherwise. Absent, a runner asks the table itself.\n */\n modelFor?: (kind: AiStepKind) => string | undefined\n}\n\nexport type AiJobStepRunner = (\n context: AiJobStepContext,\n) => Promise<AiJobStepOutcome>\n\n/**\n * The static block, byte-identical on every request so it caches. The\n * customer's brief and the org's inputs never enter it.\n */\nexport const AI_JOB_TEXT_SYSTEM: AiSystemBlock[] = [\n {\n text:\n 'You write short, publishable copy for a website builder. You are ' +\n 'given a brief from the person who owns the site. Answer with the ' +\n 'copy only: no preamble, no headings unless the brief asks for them, ' +\n 'no closing remarks, no markdown fences. Keep to the length the brief ' +\n 'implies; when it implies none, write under 150 words. Write in the ' +\n 'language of the brief. Never invent facts, prices, names or claims ' +\n 'the brief did not give you; where a detail is missing, leave a ' +\n 'clearly marked placeholder in square brackets.',\n cacheBreakpoint: true,\n },\n]\n\n/** The brief as the user turn, with the kind-specific inputs stated plainly. */\nexport function aiJobTextPrompt(job: Pick<AiJob, 'brief' | 'inputs'>): string {\n const brief = job.brief.slice(0, AI_JOB_BRIEF_MAX_CHARS)\n const tone = typeof job.inputs?.['tone'] === 'string' ? job.inputs['tone'] : ''\n const audience =\n typeof job.inputs?.['audience'] === 'string' ? job.inputs['audience'] : ''\n const lines = [`Brief: ${brief}`]\n if (tone) lines.push(`Tone: ${tone}`)\n if (audience) lines.push(`Audience: ${audience}`)\n return lines.join('\\n')\n}\n\nexport const runAiJobTextStep: AiJobStepRunner = async ({ job, signal, modelFor }) => {\n const model = modelFor?.('job.text') ?? aiJobTextModel()\n // Overlay copy (AGL-3603): the same one request, answered as fields.\n if (aiOverlayCopyRequested(job.inputs)) {\n return runAiOverlayCopy({\n job,\n model,\n maxTokens: AI_JOB_TEXT_STEP_BUDGET.maxTokens(model),\n ...(signal ? { signal } : {}),\n })\n }\n // A development run's effort A/B arm (AGL-3781), else the row's.\n const effort = aiDevEffortFor('job.text') ?? AI_ROUTING_TABLE['job.text'].effort\n const result = await runAiRequest({\n model,\n system: AI_JOB_TEXT_SYSTEM,\n messages: [{ role: 'user', content: aiJobTextPrompt(job) }],\n // The routing ceiling, lowered on a tier too slow to answer it inside the\n // least time the step registered.\n maxTokens: AI_JOB_TEXT_STEP_BUDGET.maxTokens(model),\n ...(AI_ROUTING_TABLE['job.text'].thinking ? { thinking: AI_ROUTING_TABLE['job.text'].thinking } : {}),\n ...(effort ? { effort } : {}),\n stream: false,\n ...(signal ? { signal } : {}),\n })\n if (result.kind === 'refusal') {\n return {\n outputs: [],\n usage: result.usage,\n estCostUsd: result.estCostUsd,\n model,\n stopReason: result.stopReason,\n refused: true,\n }\n }\n const text = result.text.trim()\n return {\n outputs: text\n ? [\n {\n resource: 'text',\n // A text output has no document of its own; the id names the\n // step within the job so a later step can address it.\n id: 'draft',\n hostId: job.hostId ?? null,\n label: 'Draft copy',\n text,\n },\n ]\n : [],\n usage: result.usage,\n estCostUsd: result.estCostUsd,\n model,\n stopReason: result.stopReason,\n }\n}\n"],"names":["AI_STEP_TIERS","AI_ROUTING_TABLE","aiModelForStep","aiDevEffortFor","runAiRequest","aiJobStepBudget","aiOverlayCopyRequested","runAiOverlayCopy","aiJobTextModel","AI_JOB_TEXT_MAX_TOKENS","maxTokens","AI_JOB_TEXT_STEP_BUDGET","tier","attempts","lookups","AI_JOB_TEXT_STEP_MINIMUM_MS","minimumMs","AI_JOB_BRIEF_MAX_CHARS","AI_JOB_TEXT_SYSTEM","text","cacheBreakpoint","aiJobTextPrompt","job","brief","slice","tone","inputs","audience","lines","push","join","runAiJobTextStep","signal","modelFor","model","effort","result","system","messages","role","content","thinking","stream","kind","outputs","usage","estCostUsd","stopReason","refused","trim","resource","id","hostId","label"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/jobs/ai-job-text-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 { AglynOrgBilling } from '@aglyn/aglyn/foundation/definitions/org-billing.types'\nimport type {\n AiJob,\n AiJobOutput,\n AiJobPlan,\n AiJobReview,\n AiJobInputRequest,\n AiJobItemFailure,\n AiJobItemLedger,\n AiJobItemStatus,\n AiJobSitePublish,\n} from '../model/ai-jobs.types'\nimport { AI_STEP_TIERS, type AiStepKind } from '../providers/catalog'\nimport { AI_ROUTING_TABLE, aiModelForStep } from '../providers/routing'\nimport { aiDevEffortFor } from '../runtime/ai-dev-env'\nimport { runAiRequest, type AiEffort, type AiSystemBlock } from '../runtime/ai-runtime'\nimport type { AssistTokenUsage } from '../usage/assist-usage'\nimport type { AiSiteImportState } from '../model/ai-site-import'\nimport type { AiSitePhotos } from '../model/ai-site-photos'\nimport { aiJobStepBudget } from './ai-job-budget'\nimport { aiOverlayCopyRequested } from '../model/ai-overlay-copy'\nimport { runAiOverlayCopy } from './ai-job-overlay-copy'\n\n/**\n * The `text` step (AGL-2904): a brief in, a short piece of copy out.\n *\n * The one step kind this issue ships for real, so the state machine — the\n * lease, the reservation, the record, the beat — is exercised end to end by\n * something that spends tokens, rather than by a stub that could pass with\n * the meter unplugged. Every other kind refuses until its own issue lands.\n *\n * The balanced tier with adaptive thinking: a brief is open-ended in a way the copy\n * assistant's element mode is not, and the cost is one call per job. The\n * static system block is cached; the brief rides in the user turn, so no\n * per-org byte sits inside the cached prefix (AGL-2352, enforced by the\n * runtime before the request leaves).\n */\n\n/** The model the text step runs on: the routing table's answer for `job.text`. */\nexport function aiJobTextModel(): string {\n return aiModelForStep('job.text')\n}\n\n/** The text step's answer ceiling, from the routing table. */\nexport const AI_JOB_TEXT_MAX_TOKENS = AI_ROUTING_TABLE['job.text'].maxTokens\n\n/**\n * The text step's time (AGL-3035): ONE request — no re-ask, and no site\n * inventory to look anything up in — at the routing table's ceiling on the\n * tier `job.text` is served from, with the step's reads and writes. That fits\n * an inline door's budget, so a door runs a text job where it is asked for,\n * and the least time is the helper's worst case rather than a figure anyone\n * chose; a slower tier asks less so its worst case still fits.\n */\nexport const AI_JOB_TEXT_STEP_BUDGET = aiJobStepBudget({\n tier: AI_STEP_TIERS['job.text'],\n maxTokens: AI_JOB_TEXT_MAX_TOKENS,\n attempts: 1,\n lookups: 0,\n})\n\n/** The least time one text step needs before it starts. */\nexport const AI_JOB_TEXT_STEP_MINIMUM_MS = AI_JOB_TEXT_STEP_BUDGET.minimumMs\n\n/** How much of a brief is sent. Past this a brief is a document, not a brief. */\nexport const AI_JOB_BRIEF_MAX_CHARS = 4_000\n\n/**\n * What a step hands back to the machine. The machine meters `usage` at\n * `model`'s rates, records the step and appends the outputs; a step never\n * touches the job document or the meter itself.\n */\nexport interface AiJobStepOutcome {\n outputs: AiJobOutput[]\n /**\n * The step made progress and has more of the same work to do (AGL-2910):\n * a site audit works through its pages a batch at a time. The machine\n * records this pass — its spend and its outputs — and hands the SAME step\n * back to run again, so every pass is one reservation and one provider\n * exchange, and the job document says how far it got.\n */\n continue?: boolean\n usage: AssistTokenUsage\n estCostUsd: number\n model: string\n stopReason: string | null\n /**\n * The thinking effort the request asked for, recorded on the step\n * (AGL-2937); absent or `null` when the request named none.\n */\n effort?: AiEffort | null\n /** The model declined the brief (`stop_reason: 'refusal'`). Tokens were spent. */\n refused?: boolean\n /**\n * The model answered and nothing usable came of it — no structured answer\n * even after the step's own re-ask, say (AGL-2938). Tokens were spent, so\n * the machine meters the step before it fails the job with this sentence,\n * which is customer-safe and the only thing a customer reads.\n */\n failure?: string\n /** The plan the plan step proposed, which the machine keeps on the job (AGL-2935). */\n plan?: AiJobPlan\n /**\n * The step stopped for a person (AGL-2935). The machine records what it\n * spent and parks the job `needs_review`: a `plan` review completes the\n * step, so confirming runs the next one; a `doctrine` review hands the\n * step back, so trying again runs the same one.\n */\n review?: AiJobReview\n /**\n * With a `plan` review: the plan needs an answer only the person can give\n * first (AGL-3978) — a tracking change with no pixel ID. The machine keeps\n * the plan and its review and parks the job `needs_input` with these\n * fields instead of `needs_review`; the answer returns it to the review.\n */\n input?: AiJobInputRequest\n /**\n * The answer was refused by the platform's own checks, not the model's\n * (AGL-3594): the machine meters the step as any other and then gives the\n * job's credits back to the meters it was charged to (`refundJobCredits`),\n * a bounded number of times a day.\n */\n uncredited?: boolean\n /**\n * The `failure` is the workspace's own limit, not a fault of ours: the\n * month's Free AI credits are spent (a 429 from the kind's admission, asked\n * when the plan is kept). The machine fails the job and gives the step's\n * credits back exactly as for our failure, but announces it as NOT ours, so\n * no staff alert is raised for a customer reaching their allowance.\n */\n customerLimit?: boolean\n /**\n * What a guided site start put live on its last pass (AGL-3596), kept on\n * the job by the machine in the write that records the pass: a step never\n * writes the job document itself.\n */\n sitePublish?: AiJobSitePublish\n /**\n * A `build` pass's unit and what it came to (AGL-3616), which the machine\n * writes to the job's item ledger in the transaction that records the\n * pass's spend. An item's failure is never the step's: it is a row, and\n * the build goes on.\n */\n item?: AiJobItemOutcome\n /** A `build`'s ledger to start from, written by the machine in the same transaction (AGL-3616). */\n items?: AiJobItemLedger[]\n /**\n * An `import` job's waves after this pass (AGL-3976), kept on the job by\n * the machine in the write that records the pass: a step never writes the\n * job document itself.\n */\n siteImport?: AiSiteImportState\n /**\n * A `site` job's pictures left on a starter photo after this pass\n * (AGL-3988), whole: what its late photo pass fills before the site is\n * published. A page's or a dataset's pass reports its own; the site step\n * merges them and the machine keeps the result on the job.\n */\n sitePhotos?: AiSitePhotos\n}\n\n/** What one `build` pass came to for the unit it ran (AGL-3616). */\nexport interface AiJobItemOutcome {\n slot: string\n /** `running` while the unit asks for another pass of its own. */\n status: AiJobItemStatus\n failure?: AiJobItemFailure | null\n /** Customer-safe: what the person should know about the item. */\n note?: string | null\n degradedBy?: string[]\n /** The ids of the outputs this pass produced for the item. */\n outputs?: string[]\n}\n\nexport interface AiJobStepContext {\n job: AiJob\n stepIndex: number\n now: Date\n /** Aborts the provider call when the runner's budget ends. */\n signal?: AbortSignal\n /**\n * The Admin SDK handle the machine runs on, for a step that reads what it\n * builds from — a site's theme, say — or writes a draft. A step never\n * writes the job document, the meter or the lease through it.\n */\n firestore: FirebaseFirestore.Firestore\n /** The org document the machine read for the step's reservation. */\n org?: Partial<AglynOrgBilling> | null\n /**\n * The model a step of this kind runs on for THIS job (AGL-2942): the\n * creator's pick where the plan and the allotment allowlists allow it,\n * the routing table otherwise. Absent, a runner asks the table itself.\n */\n modelFor?: (kind: AiStepKind) => string | undefined\n}\n\nexport type AiJobStepRunner = (\n context: AiJobStepContext,\n) => Promise<AiJobStepOutcome>\n\n/**\n * The static block, byte-identical on every request so it caches. The\n * customer's brief and the org's inputs never enter it.\n */\nexport const AI_JOB_TEXT_SYSTEM: AiSystemBlock[] = [\n {\n text:\n 'You write short, publishable copy for a website builder. You are ' +\n 'given a brief from the person who owns the site. Answer with the ' +\n 'copy only: no preamble, no headings unless the brief asks for them, ' +\n 'no closing remarks, no markdown fences. Keep to the length the brief ' +\n 'implies; when it implies none, write under 150 words. Write in the ' +\n 'language of the brief. Never invent facts, prices, names or claims ' +\n // AGL-4092: never a bracketed placeholder, which a page shows as written.\n 'the brief did not give you; where a detail is missing, leave it out ' +\n 'and write the sentence without it.',\n cacheBreakpoint: true,\n },\n]\n\n/** The brief as the user turn, with the kind-specific inputs stated plainly. */\nexport function aiJobTextPrompt(job: Pick<AiJob, 'brief' | 'inputs'>): string {\n const brief = job.brief.slice(0, AI_JOB_BRIEF_MAX_CHARS)\n const tone = typeof job.inputs?.['tone'] === 'string' ? job.inputs['tone'] : ''\n const audience =\n typeof job.inputs?.['audience'] === 'string' ? job.inputs['audience'] : ''\n const lines = [`Brief: ${brief}`]\n if (tone) lines.push(`Tone: ${tone}`)\n if (audience) lines.push(`Audience: ${audience}`)\n return lines.join('\\n')\n}\n\nexport const runAiJobTextStep: AiJobStepRunner = async ({ job, signal, modelFor }) => {\n const model = modelFor?.('job.text') ?? aiJobTextModel()\n // Overlay copy (AGL-3603): the same one request, answered as fields.\n if (aiOverlayCopyRequested(job.inputs)) {\n return runAiOverlayCopy({\n job,\n model,\n maxTokens: AI_JOB_TEXT_STEP_BUDGET.maxTokens(model),\n ...(signal ? { signal } : {}),\n })\n }\n // A development run's effort A/B arm (AGL-3781), else the row's.\n const effort = aiDevEffortFor('job.text') ?? AI_ROUTING_TABLE['job.text'].effort\n const result = await runAiRequest({\n model,\n system: AI_JOB_TEXT_SYSTEM,\n messages: [{ role: 'user', content: aiJobTextPrompt(job) }],\n // The routing ceiling, lowered on a tier too slow to answer it inside the\n // least time the step registered.\n maxTokens: AI_JOB_TEXT_STEP_BUDGET.maxTokens(model),\n ...(AI_ROUTING_TABLE['job.text'].thinking ? { thinking: AI_ROUTING_TABLE['job.text'].thinking } : {}),\n ...(effort ? { effort } : {}),\n stream: false,\n ...(signal ? { signal } : {}),\n })\n if (result.kind === 'refusal') {\n return {\n outputs: [],\n usage: result.usage,\n estCostUsd: result.estCostUsd,\n model,\n stopReason: result.stopReason,\n refused: true,\n }\n }\n const text = result.text.trim()\n return {\n outputs: text\n ? [\n {\n resource: 'text',\n // A text output has no document of its own; the id names the\n // step within the job so a later step can address it.\n id: 'draft',\n hostId: job.hostId ?? null,\n label: 'Draft copy',\n text,\n },\n ]\n : [],\n usage: result.usage,\n estCostUsd: result.estCostUsd,\n model,\n stopReason: result.stopReason,\n }\n}\n"],"names":["AI_STEP_TIERS","AI_ROUTING_TABLE","aiModelForStep","aiDevEffortFor","runAiRequest","aiJobStepBudget","aiOverlayCopyRequested","runAiOverlayCopy","aiJobTextModel","AI_JOB_TEXT_MAX_TOKENS","maxTokens","AI_JOB_TEXT_STEP_BUDGET","tier","attempts","lookups","AI_JOB_TEXT_STEP_MINIMUM_MS","minimumMs","AI_JOB_BRIEF_MAX_CHARS","AI_JOB_TEXT_SYSTEM","text","cacheBreakpoint","aiJobTextPrompt","job","brief","slice","tone","inputs","audience","lines","push","join","runAiJobTextStep","signal","modelFor","model","effort","result","system","messages","role","content","thinking","stream","kind","outputs","usage","estCostUsd","stopReason","refused","trim","resource","id","hostId","label"],"mappings":"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"}
|
|
@@ -152,6 +152,22 @@ import type { AiBuildPlan } from '../model/ai-build-plan';
|
|
|
152
152
|
* searched only with its world; a record's cover is searched in its world
|
|
153
153
|
* first; and a listed world widens only where the library knew nothing of
|
|
154
154
|
* it, never an outdoor or a trade world to an office.
|
|
155
|
+
* 11. **The thing, the place and the trade** (the 2026-10-28 live check,
|
|
156
|
+
* AGL-4092: a bare foot tagged "body part" for a parts shop's "Engine and
|
|
157
|
+
* air", a transmission chain for its "Brake Pad Set", a cat tagged "hungry"
|
|
158
|
+
* for a taco trailer's "Come hungry", a European alley for "Around town", a
|
|
159
|
+
* taco bowl salad for "Race day", and a man posing with a street bike tagged
|
|
160
|
+
* "susuki" in a motocross team's band of pictures). A picture of a thing is
|
|
161
|
+
* held to the business's own world, never any word of its type; a feeling,
|
|
162
|
+
* a time or a way of being somewhere is never a thing, and "around town" is
|
|
163
|
+
* the business's customers out there; a broad search's photo is OF the
|
|
164
|
+
* world among its first tags, never a "taco bowl"; an animal, a toy or a
|
|
165
|
+
* bare body part never leads a photo naming nothing of the world; a trade's
|
|
166
|
+
* things are held to the world it serves, never to "part"; a product takes
|
|
167
|
+
* a shoot no other product shows; a motocross business's world is
|
|
168
|
+
* off-road; and a maker is named one letter off ("susuki") and by its
|
|
169
|
+
* gear's and tires' names. Still by the tags: a mark only the pixels show
|
|
170
|
+
* is placed.
|
|
155
171
|
*
|
|
156
172
|
* A slot the library could not fill because it never answered — down, or
|
|
157
173
|
* out of time before its first answer — or because the site's library
|
|
@@ -259,6 +275,15 @@ export interface AiStockSiteTerms {
|
|
|
259
275
|
* pictures are qualified by in place of the craft.
|
|
260
276
|
*/
|
|
261
277
|
leadWord?: string;
|
|
278
|
+
/**
|
|
279
|
+
* What a trade's pictures of a thing must name, where the craft is the
|
|
280
|
+
* trade (AGL-4092): the names of the world it serves ("dirt bike",
|
|
281
|
+
* "motocross"), never its craft. A parts shop's "part" named a bare foot
|
|
282
|
+
* tagged "body part" and a transmission tagged "mechanical part".
|
|
283
|
+
*/
|
|
284
|
+
held?: string[];
|
|
285
|
+
/** What a picture of the business out where it is asks for ({@link CRAFT_KIN}, AGL-4092). */
|
|
286
|
+
out?: string[];
|
|
262
287
|
/** The searches for the site's world itself, broadest last. */
|
|
263
288
|
broad: string[];
|
|
264
289
|
/** The searches for its maker at work, for a story of the craft (AGL-3660); empty for a craft not listed. */
|
|
@@ -326,7 +351,9 @@ export declare function aiStockSubjectWords(alt: string, sectionName: string): s
|
|
|
326
351
|
* The thing a subject shows, one singular word: its last word that is not
|
|
327
352
|
* a set or a wrapper of it — "bowl" from "nesting bowl set", "candle" from
|
|
328
353
|
* "candle gift set", "vase" from "bud vase". Its last word when every word
|
|
329
|
-
* is one ("gift set").
|
|
354
|
+
* is one ("gift set"). A feeling, a time or a way of being somewhere is
|
|
355
|
+
* never one ({@link NON_THINGS}, AGL-4092): "Come hungry" and "Around town"
|
|
356
|
+
* show no thing, and "Race day" is of the race.
|
|
330
357
|
*/
|
|
331
358
|
export declare function aiStockObjectWord(subject: string): string;
|
|
332
359
|
/** The frame's orientation: a wide frame wants a landscape photo, a tall one a portrait. */
|
|
@@ -356,6 +383,25 @@ export interface AiStockSearch extends StockPhotoSearchRequest {
|
|
|
356
383
|
lead?: boolean;
|
|
357
384
|
/** Whether the hit's first tags must name the site's world, where the object need not lead (AGL-3660). */
|
|
358
385
|
leadWorld?: boolean;
|
|
386
|
+
/**
|
|
387
|
+
* Whether one of the hit's first tags must be OF the business's own world
|
|
388
|
+
* ({@link AiStockSiteTerms.lead}, AGL-4092): naming it, and ending in a word
|
|
389
|
+
* of it. "Taco bowl" is a bowl and "body part" a part: a taco trailer's
|
|
390
|
+
* "Race day" took a chicken salad tagged "taco bowl".
|
|
391
|
+
*/
|
|
392
|
+
leadOwn?: boolean;
|
|
393
|
+
/**
|
|
394
|
+
* Stems of things a picture is never OF unless its words or the brief name
|
|
395
|
+
* them, refused among a hit's first tags where those name nothing of the
|
|
396
|
+
* business's own world ({@link aiStockOddLeads}, AGL-4092): a cat, a bare foot.
|
|
397
|
+
*/
|
|
398
|
+
oddLeads?: readonly string[];
|
|
399
|
+
/**
|
|
400
|
+
* The world a trade serves, one of whose names every hit names, its kin or
|
|
401
|
+
* not ({@link AiStockSiteTerms.held}, AGL-4092): a dirt bike shop's "Brake
|
|
402
|
+
* Pad Set" is never a railway wagon's brake wheel tagged "brake".
|
|
403
|
+
*/
|
|
404
|
+
served?: readonly string[];
|
|
359
405
|
/**
|
|
360
406
|
* Whether the hit's FIRST tag must name the site's world (AGL-3760): what
|
|
361
407
|
* the photo is of, most of all. A hero is the site's opening picture; the
|
|
@@ -483,6 +529,10 @@ export interface AiStockProductFallback {
|
|
|
483
529
|
broad?: readonly string[];
|
|
484
530
|
/** The words a photo of the craft itself names ({@link AiStockSiteTerms.core}). */
|
|
485
531
|
core?: readonly string[];
|
|
532
|
+
/** The world a trade serves, which its products name in place of the craft ({@link AiStockSiteTerms.held}, AGL-4092). */
|
|
533
|
+
held?: readonly string[];
|
|
534
|
+
/** The word a trade's product is searched with in place of its craft ({@link AiStockSiteTerms.leadWord}, AGL-4092). */
|
|
535
|
+
leadWord?: string;
|
|
486
536
|
}
|
|
487
537
|
/**
|
|
488
538
|
* A product's searches (AGL-3676), most specific first: each of its subjects
|
|
@@ -537,7 +587,7 @@ export declare function aiStockProductSearches(slot: Pick<AiLayoutPictureSlot, '
|
|
|
537
587
|
* asks first for the role its words or its list's name (`sectionName`) say,
|
|
538
588
|
* in the site's world: "teacher classroom" for a "Math instructor" (AGL-3856).
|
|
539
589
|
*/
|
|
540
|
-
export declare function aiStockSearchesFor(slot: Pick<AiLayoutPictureSlot, 'role' | 'alt' | 'aspect' | 'people' | 'record' | 'product'>, terms: Pick<AiStockSiteTerms, 'business' | 'craft' | 'domain' | 'broad'> & Partial<Pick<AiStockSiteTerms, 'making' | 'core' | 'scenes' | 'setting' | 'maker' | 'work' | 'leadWord'>>, subject: string, part?: AiStockSlotPart, sectionName?: string): AiStockSearch[];
|
|
590
|
+
export declare function aiStockSearchesFor(slot: Pick<AiLayoutPictureSlot, 'role' | 'alt' | 'aspect' | 'people' | 'record' | 'product'>, terms: Pick<AiStockSiteTerms, 'business' | 'craft' | 'domain' | 'broad'> & Partial<Pick<AiStockSiteTerms, 'making' | 'core' | 'scenes' | 'setting' | 'maker' | 'work' | 'leadWord' | 'held' | 'out'>>, subject: string, part?: AiStockSlotPart, sectionName?: string): AiStockSearch[];
|
|
541
591
|
/**
|
|
542
592
|
* Whether a picture of a craft's site whose pictures are people at a moment
|
|
543
593
|
* shows that work wherever a page would show the maker (AGL-3942): an about
|
|
@@ -583,6 +633,12 @@ export interface AiStockJudgement {
|
|
|
583
633
|
lead?: boolean;
|
|
584
634
|
/** Whether the hit's first tags must name the site's world ({@link AiStockSearch.leadWorld}). */
|
|
585
635
|
leadWorld?: boolean;
|
|
636
|
+
/** Whether one of the hit's first tags must be OF the business's own world ({@link AiStockSearch.leadOwn}, AGL-4092). */
|
|
637
|
+
leadOwn?: boolean;
|
|
638
|
+
/** Stems no hit's first tags lead with while they name nothing of the business's own world ({@link AiStockSearch.oddLeads}, AGL-4092). */
|
|
639
|
+
oddLeads?: readonly string[];
|
|
640
|
+
/** The world a trade serves, which every hit names ({@link AiStockSearch.served}, AGL-4092). */
|
|
641
|
+
served?: readonly string[];
|
|
586
642
|
/** Whether the hit's first tag must name the site's world ({@link AiStockSearch.first}). */
|
|
587
643
|
first?: boolean;
|
|
588
644
|
/** The stems of the site's business type or brief, which let a sensitive topic in ({@link AiStockSiteTerms.named}). */
|
|
@@ -615,6 +671,17 @@ export interface AiStockJudgement {
|
|
|
615
671
|
/** Stems of the places the picture is not set in, which none of a hit's first tags may name ({@link AiStockSearch.away}). */
|
|
616
672
|
away?: readonly string[];
|
|
617
673
|
}
|
|
674
|
+
/**
|
|
675
|
+
* What a picture of a business's world is never OF unless its words name it
|
|
676
|
+
* (AGL-4092): an animal or a toy (as a portfolio's record never is,
|
|
677
|
+
* {@link RECORD_ODD_LEADS}), or a bare body part. Each group is let in whole
|
|
678
|
+
* by any of its words in `said` — the slot's words, its section's, the
|
|
679
|
+
* brief's — so a dog groomer's pictures show dogs and cats alike. As stems;
|
|
680
|
+
* the body's left out where `body` is false (a portrait's face).
|
|
681
|
+
*/
|
|
682
|
+
export declare function aiStockOddLeads(said: readonly string[], options?: {
|
|
683
|
+
body?: boolean;
|
|
684
|
+
}): string[];
|
|
618
685
|
/**
|
|
619
686
|
* Whether a hit carries a topic its site never named ({@link SENSITIVE_TOPICS}):
|
|
620
687
|
* a cross, a grave, a flag, a gun, a glass of wine, a child, a mannequin.
|
|
@@ -649,9 +716,13 @@ export declare function aiStockSameShoot(a: Pick<StockPhoto, 'id' | 'photographe
|
|
|
649
716
|
* A search's ranked hits with those of a shoot no slot shows yet first among
|
|
650
717
|
* the best (AGL-3856): a team's three cards are three people where the
|
|
651
718
|
* library has them, never one model three times while another fits as well.
|
|
652
|
-
* Every other order is kept.
|
|
719
|
+
* Every other order is kept. A product's are of a shoot no slot shows yet
|
|
720
|
+
* first among ALL its accepted hits (`whole`, AGL-4092): Berm & Bolt's two
|
|
721
|
+
* tires were one contributor's shoot, 32 uploads apart.
|
|
653
722
|
*/
|
|
654
|
-
export declare function aiStockFreshShootsFirst(ranked: readonly StockPhoto[], shown: readonly StockPhoto[], judgement: AiStockJudgement
|
|
723
|
+
export declare function aiStockFreshShootsFirst(ranked: readonly StockPhoto[], shown: readonly StockPhoto[], judgement: AiStockJudgement, options?: {
|
|
724
|
+
whole?: boolean;
|
|
725
|
+
}): StockPhoto[];
|
|
655
726
|
/** The pick among a search's hits: the first {@link aiStockRank} would try, or `null`. */
|
|
656
727
|
export declare function aiStockPick(photos: readonly StockPhoto[], used: ReadonlySet<string>, seed: string, judgement?: AiStockJudgement): StockPhoto | null;
|
|
657
728
|
/**
|
|
@@ -907,6 +978,28 @@ export declare function aiStockWorldIsOutdoorOrTrade(terms: Pick<AiStockSiteTerm
|
|
|
907
978
|
* name ("Hillside") never becomes a world.
|
|
908
979
|
*/
|
|
909
980
|
export declare function aiStockListedCraft(text: string): string;
|
|
981
|
+
/**
|
|
982
|
+
* How a search's hits are judged for a slot (AGL-3660), as the source judges
|
|
983
|
+
* them: by the search's own words, held to the world it was asked for — the
|
|
984
|
+
* site's own (`site`), or a wider one where the site's found nothing
|
|
985
|
+
* (`world`, AGL-3923). What lets a sensitive topic, an animal or a body part
|
|
986
|
+
* in is always the site's own words. On a site for adults alone no hit names
|
|
987
|
+
* a child; a portrait of one of the business's people names an adult, never
|
|
988
|
+
* leads with a child, and is preferred in its role (AGL-3856). Any other
|
|
989
|
+
* picture never leads with an animal, a toy or a bare body part its words
|
|
990
|
+
* and the brief do not name, unless its first tags name the business's own
|
|
991
|
+
* world too (AGL-4092): Pit Row Tacos' "Come hungry" took a cat. Pure.
|
|
992
|
+
*/
|
|
993
|
+
export declare function aiStockJudgementFor(slot: Pick<AiLayoutPictureSlot, 'role' | 'alt' | 'people' | 'product'>, request: AiStockSearch, subject: string, site: AiStockSiteTerms, sectionName?: string, world?: AiStockSiteTerms): AiStockJudgement;
|
|
994
|
+
/**
|
|
995
|
+
* The craft's own photos, the last thing a slot of a craft's site is filled
|
|
996
|
+
* from (AGL-3660): its broad searches, any hit naming the craft itself. Never
|
|
997
|
+
* a desk, a laptop or a living room for a soap shop. A picture that is not a
|
|
998
|
+
* hero nor a product takes only a photo OF the business's own world among its
|
|
999
|
+
* first tags (AGL-4092): a taco trailer's "Race day" took a chicken salad
|
|
1000
|
+
* tagged "taco bowl". Pure.
|
|
1001
|
+
*/
|
|
1002
|
+
export declare function aiStockCraftSearches(slot: Pick<AiLayoutPictureSlot, 'role' | 'aspect' | 'record' | 'people' | 'product'>, world: AiStockSiteTerms): AiStockSearch[];
|
|
910
1003
|
/**
|
|
911
1004
|
* The source for one page, or `null` when this deployment has no stock
|
|
912
1005
|
* photo library or no media door, which leaves every slot to the starters.
|