@aglyn/plugins-ai 1.0.0-beta.260 → 1.0.0-beta.262
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +17 -17
- package/src/lib/components/ai-brief-dialog.component.d.ts +21 -58
- package/src/lib/components/ai-brief-dialog.component.js +8 -132
- package/src/lib/components/ai-brief-dialog.component.js.map +1 -1
- package/src/lib/components/ai-job-follow.component.js +2 -35
- package/src/lib/components/ai-job-follow.component.js.map +1 -1
- package/src/lib/components/ai-job-plan.component.d.ts +2 -8
- package/src/lib/components/ai-job-plan.component.js +13 -74
- package/src/lib/components/ai-job-plan.component.js.map +1 -1
- package/src/lib/components/ai-site-start-card.component.js +43 -34
- package/src/lib/components/ai-site-start-card.component.js.map +1 -1
- package/src/lib/components/ai-template-collection-field.component.d.ts +2 -12
- package/src/lib/components/ai-template-collection-field.component.js +13 -10
- package/src/lib/components/ai-template-collection-field.component.js.map +1 -1
- package/src/lib/components/ai-upsell-dialog.component.d.ts +3 -25
- package/src/lib/components/ai-upsell-dialog.component.js +9 -66
- package/src/lib/components/ai-upsell-dialog.component.js.map +1 -1
- package/src/lib/components/use-ai-job-run.d.ts +3 -8
- package/src/lib/components/use-ai-job-run.js +4 -15
- package/src/lib/components/use-ai-job-run.js.map +1 -1
- package/src/lib/insights/ai-figure-readers.js +15 -5
- package/src/lib/insights/ai-figure-readers.js.map +1 -1
- package/src/lib/insights/ai-figure-summaries.d.ts +27 -0
- package/src/lib/insights/ai-figure-summaries.js +79 -0
- package/src/lib/insights/ai-figure-summaries.js.map +1 -0
- package/src/lib/insights/ai-insight-readers.d.ts +2 -1
- package/src/lib/insights/ai-insight-readers.js +11 -26
- package/src/lib/insights/ai-insight-readers.js.map +1 -1
- package/src/lib/jobs/ai-job-admission.d.ts +6 -0
- package/src/lib/jobs/ai-job-admission.js.map +1 -1
- package/src/lib/jobs/ai-job-site-step.js +10 -6
- package/src/lib/jobs/ai-job-site-step.js.map +1 -1
- package/src/lib/jobs/ai-layout-stock-photos.d.ts +43 -11
- package/src/lib/jobs/ai-layout-stock-photos.js +329 -32
- package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
- package/src/lib/jobs/ai-stock-photo-picker.js +13 -7
- package/src/lib/jobs/ai-stock-photo-picker.js.map +1 -1
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3856-recordings.d.ts +35 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3856-recordings.js +404 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3856-recordings.js.map +1 -0
- package/src/lib/layout-language/ai-layout-motion.d.ts +9 -3
- package/src/lib/layout-language/ai-layout-motion.js +9 -3
- package/src/lib/layout-language/ai-layout-motion.js.map +1 -1
- package/src/lib/layout-language/ai-layout-pictures.d.ts +10 -1
- package/src/lib/layout-language/ai-layout-pictures.js +12 -6
- package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
- package/src/lib/model/ai-brief-copy.d.ts +85 -0
- package/src/lib/model/ai-brief-copy.js +152 -0
- package/src/lib/model/ai-brief-copy.js.map +1 -0
- package/src/lib/model/ai-create-view.d.ts +200 -0
- package/src/lib/model/ai-create-view.js +263 -0
- package/src/lib/model/ai-create-view.js.map +1 -0
- package/src/lib/model/ai-insight.d.ts +1 -1
- package/src/lib/model/ai-insight.js +4 -39
- package/src/lib/model/ai-insight.js.map +1 -1
- package/src/lib/model/ai-job-activity.d.ts +24 -0
- package/src/lib/model/ai-job-activity.js +52 -1
- package/src/lib/model/ai-job-activity.js.map +1 -1
- package/src/lib/model/ai-job-plan-lines.d.ts +46 -0
- package/src/lib/model/ai-job-plan-lines.js +70 -0
- package/src/lib/model/ai-job-plan-lines.js.map +1 -0
- package/src/lib/model/ai-template-collections.d.ts +28 -0
- package/src/lib/model/ai-template-collections.js +28 -0
- package/src/lib/model/ai-template-collections.js.map +1 -0
- package/src/lib/model/ai-upsell-copy.d.ts +41 -0
- package/src/lib/model/ai-upsell-copy.js +85 -0
- package/src/lib/model/ai-upsell-copy.js.map +1 -0
- package/src/lib/runtime/ai-doctrine-validators.d.ts +40 -0
- package/src/lib/runtime/ai-doctrine-validators.js +148 -3
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-doctrine.js +6 -2
- package/src/lib/runtime/ai-doctrine.js.map +1 -1
- package/src/lib/runtime/ai-eval-memory-firestore.js +2 -0
- package/src/lib/runtime/ai-eval-memory-firestore.js.map +1 -1
- package/src/lib/server/ai-create-route.d.ts +32 -0
- package/src/lib/server/ai-create-route.js +295 -0
- package/src/lib/server/ai-create-route.js.map +1 -0
- package/src/lib/server/ai-jobs-route.js +19 -0
- package/src/lib/server/ai-jobs-route.js.map +1 -1
- package/src/lib/server.js +14 -0
- package/src/lib/server.js.map +1 -1
|
@@ -15,13 +15,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
15
15
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
16
|
* See the License for the specific language governing permissions and
|
|
17
17
|
* limitations under the License.
|
|
18
|
-
*/ import {
|
|
18
|
+
*/ import { aiJobPlanHeading, aiJobPlanLines, aiPlanEmbedLine } from "../model/ai-job-plan-lines.js";
|
|
19
19
|
import { aiBuildFreePageCapNote, aiBuildSmaller, aiJobCreditRange } from "../model/ai-build-job.js";
|
|
20
20
|
import { aiCreditRangeText, aiCreditsPromptFor } from "../model/ai-credit-estimate.js";
|
|
21
21
|
import { aiFreeCreditsResetLabel } from "../model/ai-site-job.js";
|
|
22
22
|
import { AiCreditsPromptNotice } from "./ai-credits-prompt.component.js";
|
|
23
|
-
import { aiBuildOpNoun } from "../model/ai-build-progress.js";
|
|
24
|
-
import { aiBuildStorePagesAdded } from "../model/ai-build-store-pages.js";
|
|
25
23
|
import { AI_PAGE_BUILDING_JOB_KINDS, AI_SITE_BUILD_IN_FLIGHT_COPY, aiJobConfirmingOwnPlan, aiSiteBuildInFlight } from "../model/ai-job-activity.js";
|
|
26
24
|
import { aiSiteStarterFallbackOffered } from "../model/ai-job-failure-copy.js";
|
|
27
25
|
import { useAiJobsInFlightKnown } from "./ai-jobs-store.js";
|
|
@@ -62,19 +60,11 @@ import { useState } from "react";
|
|
|
62
60
|
}
|
|
63
61
|
return lines;
|
|
64
62
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
* platform's sentence, never the model's: the player is framed lazily, so its
|
|
69
|
-
* host's code loads when a visitor reaches it, whether or not they press play.
|
|
70
|
-
*/ export function aiPlanEmbedLine(embed, named) {
|
|
71
|
-
const host = AI_BUILD_PLAN_EMBED_HOST_NAMES[embed.host];
|
|
72
|
-
const where = isAiPlanNewRef(embed.where) ? `the component ${named(embed.where)}` : embed.where;
|
|
73
|
-
const link = embed.url ? ` playing ${embed.url}` : ', its link left for you to paste';
|
|
74
|
-
return `Embeds a ${host} player on ${where}${link}, as you asked (“${embed.asked}”). It loads ${host}’s own code when a visitor reaches it, whether or not they press play.`;
|
|
75
|
-
}
|
|
63
|
+
// A plan's lines are the model's, which the native apps' follow view sends
|
|
64
|
+
// too (AGL-3854); re-exported for this card's existing readers.
|
|
65
|
+
export { aiPlanEmbedLine };
|
|
76
66
|
export function AiJobPlan({ job, onResume, busy = false, staff = false, user, orgSlug }) {
|
|
77
|
-
var _ref
|
|
67
|
+
var _ref;
|
|
78
68
|
var _job_review;
|
|
79
69
|
const [detailsOpen, setDetailsOpen] = useState(false);
|
|
80
70
|
// Unticked until the person ticks it: a build publishes only when its
|
|
@@ -92,10 +82,6 @@ export function AiJobPlan({ job, onResume, busy = false, staff = false, user, or
|
|
|
92
82
|
const { plan, review } = job;
|
|
93
83
|
if (!plan && !review) return null;
|
|
94
84
|
const details = staff ? aiJobReviewDetails(review) : [];
|
|
95
|
-
/** A reference as a person reads it: the record's name, or what the plan creates. */ const named = (ref)=>{
|
|
96
|
-
var _ref;
|
|
97
|
-
return !ref ? '' : isAiPlanNewRef(ref) ? ref.slice('new:'.length) : (_ref = plan == null ? void 0 : plan.labels[ref]) != null ? _ref : ref;
|
|
98
|
-
};
|
|
99
85
|
// A plan the machine is confirming itself is not one to confirm (AGL-3596).
|
|
100
86
|
const waiting = job.status === 'needs_review' && review !== null && !aiJobConfirmingOwnPlan(job);
|
|
101
87
|
// The guard rail (AGL-2911): what the plan is estimated to cost is read
|
|
@@ -127,63 +113,16 @@ export function AiJobPlan({ job, onResume, busy = false, staff = false, user, or
|
|
|
127
113
|
/*#__PURE__*/ _jsx(Typography, {
|
|
128
114
|
variant: "caption",
|
|
129
115
|
color: "text.secondary",
|
|
130
|
-
children: plan
|
|
116
|
+
children: aiJobPlanHeading(plan)
|
|
131
117
|
}),
|
|
132
|
-
plan.
|
|
133
|
-
variant: "body2",
|
|
134
|
-
role: "listitem",
|
|
135
|
-
children: [
|
|
136
|
-
"Reuses the ",
|
|
137
|
-
entry.kind === 'screen' ? 'page' : entry.kind,
|
|
138
|
-
" ",
|
|
139
|
-
named(entry.id),
|
|
140
|
-
" — ",
|
|
141
|
-
entry.purpose
|
|
142
|
-
]
|
|
143
|
-
}, `reuse-${index}`)),
|
|
144
|
-
plan.create.map((entry, index)=>/*#__PURE__*/ _jsxs(Typography, {
|
|
145
|
-
variant: "body2",
|
|
146
|
-
role: "listitem",
|
|
147
|
-
children: [
|
|
148
|
-
"Creates the ",
|
|
149
|
-
AI_BUILD_PLAN_CREATION_NOUNS[entry.kind].noun,
|
|
150
|
-
" ",
|
|
151
|
-
entry.name,
|
|
152
|
-
entry.duplicateOf ? `, from a copy of ${named(entry.duplicateOf)}` : '',
|
|
153
|
-
' ',
|
|
154
|
-
"— ",
|
|
155
|
-
entry.why
|
|
156
|
-
]
|
|
157
|
-
}, `create-${index}`)),
|
|
158
|
-
plan.screens.map((screen, index)=>/*#__PURE__*/ _jsxs(Typography, {
|
|
159
|
-
variant: "body2",
|
|
160
|
-
role: "listitem",
|
|
161
|
-
children: [
|
|
162
|
-
screen.record ? `Builds the record template ${screen.title}, a page per record of ${named(screen.record.dataset)} at /${screen.record.base}/…` : `Builds the page ${screen.title} at ${screen.slug}`,
|
|
163
|
-
screen.duplicateOf ? `, from a copy of ${named(screen.duplicateOf)}` : '',
|
|
164
|
-
screen.layout ? ` in ${named(screen.layout)}` : '',
|
|
165
|
-
screen.sections.length ? `: ${screen.sections.map((section)=>section.name).join(', ')}` : ''
|
|
166
|
-
]
|
|
167
|
-
}, `screen-${index}`)),
|
|
168
|
-
((_plan_items = plan.items) != null ? _plan_items : []).map((item)=>/*#__PURE__*/ _jsxs(Typography, {
|
|
169
|
-
variant: "body2",
|
|
170
|
-
role: "listitem",
|
|
171
|
-
children: [
|
|
172
|
-
`Makes the ${aiBuildOpNoun(item.op).toLowerCase()} ${item.name}`,
|
|
173
|
-
item.why ? ` — ${item.why}` : ''
|
|
174
|
-
]
|
|
175
|
-
}, `item-${item.slot}`)),
|
|
176
|
-
((_plan_embeds = plan.embeds) != null ? _plan_embeds : []).map((embed, index)=>/*#__PURE__*/ _jsx(Typography, {
|
|
177
|
-
variant: "body2",
|
|
178
|
-
role: "listitem",
|
|
179
|
-
children: aiPlanEmbedLine(embed, named)
|
|
180
|
-
}, `embed-${index}`)),
|
|
181
|
-
aiBuildStorePagesAdded(plan).map((page)=>/*#__PURE__*/ _jsx(Typography, {
|
|
118
|
+
aiJobPlanLines(plan).map((line)=>/*#__PURE__*/ _jsx(Typography, _extends({
|
|
182
119
|
variant: "body2",
|
|
183
|
-
role: "listitem"
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
},
|
|
120
|
+
role: "listitem"
|
|
121
|
+
}, line.platformAdded ? {
|
|
122
|
+
'data-platform-added': 'true'
|
|
123
|
+
} : {}, {
|
|
124
|
+
children: line.text
|
|
125
|
+
}), line.key))
|
|
187
126
|
]
|
|
188
127
|
}),
|
|
189
128
|
staff && (review == null ? void 0 : review.detail) && /*#__PURE__*/ _jsx(Typography, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-job-plan.component.tsx"],"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 {\n AI_BUILD_PLAN_CREATION_NOUNS,\n AI_BUILD_PLAN_EMBED_HOST_NAMES,\n isAiPlanNewRef,\n type AiBuildPlanEmbed,\n} from '../model/ai-build-plan'\nimport type { AiJobReview, AiJobSummary } from '../model/ai-jobs.types'\nimport { aiBuildFreePageCapNote, aiBuildSmaller, aiJobCreditRange } from '../model/ai-build-job'\nimport { aiCreditRangeText, aiCreditsPromptFor } from '../model/ai-credit-estimate'\nimport { aiFreeCreditsResetLabel } from '../model/ai-site-job'\nimport { AiCreditsPromptNotice } from './ai-credits-prompt.component'\nimport type { AiJobResumeOptions } from './ai-job-requests'\nimport { aiBuildOpNoun } from '../model/ai-build-progress'\nimport { aiBuildStorePagesAdded } from '../model/ai-build-store-pages'\nimport {\n AI_PAGE_BUILDING_JOB_KINDS,\n AI_SITE_BUILD_IN_FLIGHT_COPY,\n aiJobConfirmingOwnPlan,\n aiSiteBuildInFlight,\n} from '../model/ai-job-activity'\nimport { aiSiteStarterFallbackOffered } from '../model/ai-job-failure-copy'\nimport { useAiJobsInFlightKnown } from './ai-jobs-store'\nimport { AiSiteStarterFallback } from './ai-site-starter-fallback.component'\nimport { Alert, Box, Button, Checkbox, Collapse, FormControlLabel, Stack, Typography } from '@mui/material'\nimport { useState } from 'react'\n\n/**\n * A job's plan and what it waits for (AGL-2935), inside the AI jobs drawer\n * and the dialog that started the job (AGL-3593): what the job reuses from\n * the site, what it creates and why, the screens it builds — and, while the\n * job waits for a person, the one button that confirms the plan or tries a\n * refused step again. Both send the same request (`resumeAiJobRequest`);\n * this renders.\n */\nexport interface AiJobPlanProps {\n job: AiJobSummary\n /**\n * Confirms the plan, or tries the refused step again. A build whose request\n * asked to publish confirms with `publish` when its box is ticked (AGL-3616).\n */\n onResume: (job: AiJobSummary, options?: AiJobResumeOptions) => void\n /** A resume for this job is in flight. */\n busy?: boolean\n /**\n * The viewer is staff (AGL-3078), who can open where a refused answer broke\n * its rules and the outline of those parts, to tell a shape the rules should\n * allow from an answer that ignored its re-ask. A member reads the findings.\n */\n staff?: boolean\n /**\n * The signed-in user, for \"Use the starter site instead\" on a guided start\n * that did not work out (AGL-3594); the action is drawn only when given.\n */\n user?: Parameters<typeof AiSiteStarterFallback>[0]['user']\n /** The workspace's path slug, for the Upgrade a Free build past what is left offers (AGL-3722). */\n orgSlug?: string | null\n}\n\n/**\n * Where a refused answer broke its rules, and the outline of those parts, as\n * lines staff read (AGL-3078): each finding with the nodes or plan entries it\n * names, then each outlined node indented by its depth, with its element, a\n * Grid's layout as written, and the names of what it sets and holds.\n */\nexport function aiJobReviewDetails(review: AiJobReview | null): string[] {\n if (review?.reason !== 'doctrine') return []\n const lines = review.findings.flatMap((finding) => {\n const where = finding.nodeIds?.length\n ? `nodes ${finding.nodeIds.join(', ')}`\n : finding.paths?.length\n ? `at ${finding.paths.join(', ')}`\n : null\n return where ? [`${finding.rule === null ? '' : `Rule ${finding.rule} `}${finding.code}: ${where}`] : []\n })\n for (const node of review.outline ?? []) {\n lines.push(\n [\n `${' '.repeat(node.depth)}${node.id} ${node.componentId}`,\n ...Object.entries(node.grid ?? {}).map(([name, value]) => `${name}=${JSON.stringify(value)}`),\n ...(node.props.length ? [`props ${node.props.join(', ')}`] : []),\n ...(node.sx?.length ? [`sx ${node.sx.join(', ')}`] : []),\n ...(node.children.length ? [`holds ${node.children.join(', ')}`] : []),\n ].join(' · '),\n )\n }\n return lines\n}\n\n/**\n * A third-party player the plan lists, with what it costs the page, read\n * before the member confirms it (rule 16, AGL-3433). The cost is the\n * platform's sentence, never the model's: the player is framed lazily, so its\n * host's code loads when a visitor reaches it, whether or not they press play.\n */\nexport function aiPlanEmbedLine(\n embed: AiBuildPlanEmbed,\n named: (ref: string) => string,\n): string {\n const host = AI_BUILD_PLAN_EMBED_HOST_NAMES[embed.host]\n const where = isAiPlanNewRef(embed.where) ? `the component ${named(embed.where)}` : embed.where\n const link = embed.url ? ` playing ${embed.url}` : ', its link left for you to paste'\n return `Embeds a ${host} player on ${where}${link}, as you asked (“${embed.asked}”). It loads ${host}’s own code when a visitor reaches it, whether or not they press play.`\n}\n\nexport function AiJobPlan({\n job,\n onResume,\n busy = false,\n staff = false,\n user,\n orgSlug,\n}: AiJobPlanProps): JSX.Element | null {\n const [detailsOpen, setDetailsOpen] = useState(false)\n // Unticked until the person ticks it: a build publishes only when its\n // request asked AND they confirm it here (AGL-3616).\n const [publish, setPublish] = useState(false)\n // Confirming builds pages while another job is building on this site\n // (AGL-3765), from the list the indicator and the panel already hold: said\n // beside Confirm, which still confirms.\n const confirmsPages =\n job.status === 'needs_review' &&\n job.review?.reason === 'plan' &&\n !aiJobConfirmingOwnPlan(job) &&\n AI_PAGE_BUILDING_JOB_KINDS.includes(job.kind)\n const inFlight = useAiJobsInFlightKnown(user, job.orgId, confirmsPages)\n const building = confirmsPages ? aiSiteBuildInFlight(inFlight, { hostId: job.hostId, exceptJobId: job.id }) : null\n const { plan, review } = job\n if (!plan && !review) return null\n const details = staff ? aiJobReviewDetails(review) : []\n /** A reference as a person reads it: the record's name, or what the plan creates. */\n const named = (ref: string | null): string =>\n !ref\n ? ''\n : isAiPlanNewRef(ref)\n ? ref.slice('new:'.length)\n : (plan?.labels[ref] ?? ref)\n // A plan the machine is confirming itself is not one to confirm (AGL-3596).\n const waiting = job.status === 'needs_review' && review !== null && !aiJobConfirmingOwnPlan(job)\n // The guard rail (AGL-2911): what the plan is estimated to cost is read\n // before it is confirmed, not after it has been spent. An estimate, and\n // said to be one: what it is likely to cost — what builds like it measured\n // — and its ceiling, every pass at its reserve (AGL-3722). A page job\n // counts the creations it builds before its page (AGL-3031).\n const range = plan && waiting && review.reason === 'plan' ? aiJobCreditRange(job.kind, plan) : null\n // A Free build past what is left asks first (AGL-3722): build what fits,\n // the home page first, or upgrade — never a refusal with no way on.\n const freeCredits = review?.freeCredits ?? null\n const prompt =\n plan && range && job.kind === 'build' ? aiCreditsPromptFor(range, freeCredits, aiBuildSmaller(plan)) : null\n // A Free build at its page cap says so (AGL-3722): pages past it were left for a later request.\n const pageCapNote =\n plan && waiting && review.reason === 'plan' && job.kind === 'build'\n ? aiBuildFreePageCapNote(plan, Boolean(freeCredits))\n : null\n const offersPublish = job.kind === 'build' && job.publishAsked === true && waiting && review.reason === 'plan'\n const publishing = offersPublish && publish ? { publish: true } : {}\n return (\n <Box sx={{ mt: 1 }}>\n {plan && (\n <Stack spacing={0.5} role=\"list\" aria-label=\"Plan\">\n <Typography variant=\"caption\" color=\"text.secondary\">\n {plan.status === 'confirmed' ? 'Confirmed plan' : 'Proposed plan'}\n </Typography>\n {plan.reuse.map((entry, index) => (\n <Typography key={`reuse-${index}`} variant=\"body2\" role=\"listitem\">\n Reuses the {entry.kind === 'screen' ? 'page' : entry.kind} {named(entry.id)} — {entry.purpose}\n </Typography>\n ))}\n {plan.create.map((entry, index) => (\n <Typography key={`create-${index}`} variant=\"body2\" role=\"listitem\">\n Creates the {AI_BUILD_PLAN_CREATION_NOUNS[entry.kind].noun} {entry.name}\n {entry.duplicateOf\n ? `, from a copy of ${named(entry.duplicateOf)}`\n : ''}{' '}\n — {entry.why}\n </Typography>\n ))}\n {plan.screens.map((screen, index) => (\n <Typography key={`screen-${index}`} variant=\"body2\" role=\"listitem\">\n {screen.record\n ? `Builds the record template ${screen.title}, a page per record of ${named(screen.record.dataset)} at /${screen.record.base}/…`\n : `Builds the page ${screen.title} at ${screen.slug}`}\n {screen.duplicateOf\n ? `, from a copy of ${named(screen.duplicateOf)}`\n : ''}\n {screen.layout ? ` in ${named(screen.layout)}` : ''}\n {screen.sections.length\n ? `: ${screen.sections.map((section) => section.name).join(', ')}`\n : ''}\n </Typography>\n ))}\n {(plan.items ?? []).map((item) => (\n <Typography key={`item-${item.slot}`} variant=\"body2\" role=\"listitem\">\n {`Makes the ${aiBuildOpNoun(item.op).toLowerCase()} ${item.name}`}\n {item.why ? ` — ${item.why}` : ''}\n </Typography>\n ))}\n {(plan.embeds ?? []).map((embed, index) => (\n <Typography key={`embed-${index}`} variant=\"body2\" role=\"listitem\">\n {aiPlanEmbedLine(embed, named)}\n </Typography>\n ))}\n {/* A store's own pages (AGL-3676): added by the platform, written by code, no credits. */}\n {aiBuildStorePagesAdded(plan).map((page) => (\n <Typography key={`store-${page.key}`} variant=\"body2\" role=\"listitem\" data-platform-added=\"true\">\n {`Adds the page ${page.title} at ${page.href} — added for your store automatically, uses no AI credits`}\n </Typography>\n ))}\n </Stack>\n )}\n {/*\n A review written for the member (AGL-3594) carries the checks' own\n sentence as `detail`: its findings are then staff reading too, and the\n member reads the job's one sentence alone.\n */}\n {staff && review?.detail && (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\" sx={{ mt: 0.5 }}>\n {review.detail}\n </Typography>\n )}\n {review?.reason === 'doctrine' && review.findings.length > 0 && (staff || !review.detail) && (\n <Box\n component=\"ul\"\n sx={{ my: 0.5, pl: 2.5 }}\n aria-label=\"Building rules broken\"\n >\n {review.findings.map((finding, index) => (\n <Typography\n key={`finding-${index}`}\n component=\"li\"\n variant=\"caption\"\n >\n {finding.message}\n </Typography>\n ))}\n </Box>\n )}\n {details.length > 0 && (\n <Box sx={{ mt: 0.5 }}>\n <Button\n size=\"small\"\n aria-expanded={detailsOpen}\n onClick={() => setDetailsOpen((prior) => !prior)}\n >\n {detailsOpen ? 'Hide what was refused' : 'Show what was refused'}\n </Button>\n <Collapse in={detailsOpen} unmountOnExit>\n <Typography\n variant=\"caption\"\n component=\"pre\"\n aria-label=\"What was refused\"\n sx={{ m: 0, fontFamily: 'monospace', whiteSpace: 'pre', overflowX: 'auto' }}\n >\n {details.join('\\n')}\n </Typography>\n </Collapse>\n </Box>\n )}\n {range && range.ceiling > 0 && (\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ display: 'block', mt: 1 }}\n >\n {`Estimated cost: ${aiCreditRangeText(range)}. What it costs is what its steps spend.`}\n {freeCredits && !prompt\n ? ` You have ${freeCredits.left.toLocaleString('en-US')} of your free AI credits left this month, until ${aiFreeCreditsResetLabel(freeCredits.resetsOn)}.`\n : ''}\n </Typography>\n )}\n {pageCapNote && (\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ display: 'block', mt: 0.5 }}>\n {pageCapNote}\n </Typography>\n )}\n {waiting && review.retryRefusal && review.reason !== 'plan' && (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\" sx={{ mt: 1 }}>\n {review.retryRefusal}\n </Typography>\n )}\n {offersPublish && (\n <FormControlLabel\n sx={{ display: 'flex', mt: 1 }}\n control={<Checkbox size=\"small\" checked={publish} onChange={(event) => setPublish(event.target.checked)} />}\n label={<Typography variant=\"body2\">{'Publish the new pages when they are built'}</Typography>}\n />\n )}\n {waiting && prompt && (\n <AiCreditsPromptNotice\n prompt={prompt}\n noun=\"build\"\n orgSlug={orgSlug}\n busy={busy}\n onBuildWhatFits={() => onResume(job, { ...publishing, creditsConfirmed: true })}\n onSmaller={() => onResume(job, { ...publishing, creditsConfirmed: true, reduce: 'first-page' })}\n />\n )}\n {building && (\n <Alert severity=\"info\" sx={{ mt: 1 }}>\n {AI_SITE_BUILD_IN_FLIGHT_COPY}\n </Alert>\n )}\n {waiting && !prompt && (\n <Button\n size=\"small\"\n variant=\"contained\"\n // Disabled with its reason above when the Free allowance left\n // cannot pay for another try (AGL-3594).\n disabled={busy || (review.reason !== 'plan' && Boolean(review.retryRefusal))}\n onClick={() => onResume(job, offersPublish && publish ? publishing : undefined)}\n sx={{ mt: 1 }}\n >\n {review.reason === 'plan' ? 'Confirm plan' : 'Try again'}\n </Button>\n )}\n {/* A guided start that did not work out can take the starter instead (AGL-3594). */}\n {waiting && user && aiSiteStarterFallbackOffered(job) && <AiSiteStarterFallback job={job} user={user} />}\n </Box>\n )\n}\n\nexport default AiJobPlan\n"],"names":["AI_BUILD_PLAN_CREATION_NOUNS","AI_BUILD_PLAN_EMBED_HOST_NAMES","isAiPlanNewRef","aiBuildFreePageCapNote","aiBuildSmaller","aiJobCreditRange","aiCreditRangeText","aiCreditsPromptFor","aiFreeCreditsResetLabel","AiCreditsPromptNotice","aiBuildOpNoun","aiBuildStorePagesAdded","AI_PAGE_BUILDING_JOB_KINDS","AI_SITE_BUILD_IN_FLIGHT_COPY","aiJobConfirmingOwnPlan","aiSiteBuildInFlight","aiSiteStarterFallbackOffered","useAiJobsInFlightKnown","AiSiteStarterFallback","Alert","Box","Button","Checkbox","Collapse","FormControlLabel","Stack","Typography","useState","aiJobReviewDetails","review","reason","lines","findings","flatMap","finding","where","nodeIds","length","join","paths","rule","code","node","outline","push","repeat","depth","id","componentId","Object","entries","grid","map","name","value","JSON","stringify","props","sx","children","aiPlanEmbedLine","embed","named","host","link","url","asked","AiJobPlan","job","onResume","busy","staff","user","orgSlug","plan","detailsOpen","setDetailsOpen","publish","setPublish","confirmsPages","status","includes","kind","inFlight","orgId","building","hostId","exceptJobId","details","ref","slice","labels","waiting","range","freeCredits","prompt","pageCapNote","Boolean","offersPublish","publishAsked","publishing","mt","spacing","role","aria-label","variant","color","reuse","entry","index","purpose","create","noun","duplicateOf","why","screens","screen","record","title","dataset","base","slug","layout","sections","section","items","item","op","toLowerCase","slot","embeds","page","data-platform-added","href","key","detail","component","my","pl","message","size","aria-expanded","onClick","prior","in","unmountOnExit","m","fontFamily","whiteSpace","overflowX","ceiling","display","left","toLocaleString","resetsOn","retryRefusal","control","checked","onChange","event","target","label","onBuildWhatFits","creditsConfirmed","onSmaller","reduce","severity","disabled","undefined"],"mappings":";;AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,4BAA4B,EAC5BC,8BAA8B,EAC9BC,cAAc,QAET,4BAAwB;AAE/B,SAASC,sBAAsB,EAAEC,cAAc,EAAEC,gBAAgB,QAAQ,2BAAuB;AAChG,SAASC,iBAAiB,EAAEC,kBAAkB,QAAQ,iCAA6B;AACnF,SAASC,uBAAuB,QAAQ,0BAAsB;AAC9D,SAASC,qBAAqB,QAAQ,mCAA+B;AAErE,SAASC,aAAa,QAAQ,gCAA4B;AAC1D,SAASC,sBAAsB,QAAQ,mCAA+B;AACtE,SACEC,0BAA0B,EAC1BC,4BAA4B,EAC5BC,sBAAsB,EACtBC,mBAAmB,QACd,8BAA0B;AACjC,SAASC,4BAA4B,QAAQ,kCAA8B;AAC3E,SAASC,sBAAsB,QAAQ,qBAAiB;AACxD,SAASC,qBAAqB,QAAQ,0CAAsC;AAC5E,SAASC,KAAK,EAAEC,GAAG,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,QAAQ,EAAEC,gBAAgB,EAAEC,KAAK,EAAEC,UAAU,QAAQ,gBAAe;AAC3G,SAASC,QAAQ,QAAQ,QAAO;AAkChC;;;;;CAKC,GACD,OAAO,SAASC,mBAAmBC,MAA0B;QAUxCA;IATnB,IAAIA,CAAAA,0BAAAA,OAAQC,MAAM,MAAK,YAAY,OAAO,EAAE;IAC5C,MAAMC,QAAQF,OAAOG,QAAQ,CAACC,OAAO,CAAC,CAACC;YACvBA,kBAEVA;QAFJ,MAAMC,QAAQD,EAAAA,mBAAAA,QAAQE,OAAO,qBAAfF,iBAAiBG,MAAM,IACjC,CAAC,MAAM,EAAEH,QAAQE,OAAO,CAACE,IAAI,CAAC,OAAO,GACrCJ,EAAAA,iBAAAA,QAAQK,KAAK,qBAAbL,eAAeG,MAAM,IACnB,CAAC,GAAG,EAAEH,QAAQK,KAAK,CAACD,IAAI,CAAC,OAAO,GAChC;QACN,OAAOH,QAAQ;YAAC,GAAGD,QAAQM,IAAI,KAAK,OAAO,KAAK,CAAC,KAAK,EAAEN,QAAQM,IAAI,CAAC,CAAC,CAAC,GAAGN,QAAQO,IAAI,CAAC,EAAE,EAAEN,OAAO;SAAC,GAAG,EAAE;IAC1G;IACA,KAAK,MAAMO,SAAQb,kBAAAA,OAAOc,OAAO,YAAdd,kBAAkB,EAAE,CAAE;YAIjBa;YAEdA;QALRX,MAAMa,IAAI,CACR;YACE,GAAG,KAAKC,MAAM,CAACH,KAAKI,KAAK,IAAIJ,KAAKK,EAAE,CAAC,CAAC,EAAEL,KAAKM,WAAW,EAAE;eACvDC,OAAOC,OAAO,EAACR,aAAAA,KAAKS,IAAI,YAATT,aAAa,CAAC,GAAGU,GAAG,CAAC,CAAC,CAACC,MAAMC,MAAM,GAAK,GAAGD,KAAK,CAAC,EAAEE,KAAKC,SAAS,CAACF,QAAQ;eACxFZ,KAAKe,KAAK,CAACpB,MAAM,GAAG;gBAAC,CAAC,MAAM,EAAEK,KAAKe,KAAK,CAACnB,IAAI,CAAC,OAAO;aAAC,GAAG,EAAE;eAC3DI,EAAAA,WAAAA,KAAKgB,EAAE,qBAAPhB,SAASL,MAAM,IAAG;gBAAC,CAAC,GAAG,EAAEK,KAAKgB,EAAE,CAACpB,IAAI,CAAC,OAAO;aAAC,GAAG,EAAE;eACnDI,KAAKiB,QAAQ,CAACtB,MAAM,GAAG;gBAAC,CAAC,MAAM,EAAEK,KAAKiB,QAAQ,CAACrB,IAAI,CAAC,OAAO;aAAC,GAAG,EAAE;SACtE,CAACA,IAAI,CAAC;IAEX;IACA,OAAOP;AACT;AAEA;;;;;CAKC,GACD,OAAO,SAAS6B,gBACdC,KAAuB,EACvBC,KAA8B;IAE9B,MAAMC,OAAO9D,8BAA8B,CAAC4D,MAAME,IAAI,CAAC;IACvD,MAAM5B,QAAQjC,eAAe2D,MAAM1B,KAAK,IAAI,CAAC,cAAc,EAAE2B,MAAMD,MAAM1B,KAAK,GAAG,GAAG0B,MAAM1B,KAAK;IAC/F,MAAM6B,OAAOH,MAAMI,GAAG,GAAG,CAAC,SAAS,EAAEJ,MAAMI,GAAG,EAAE,GAAG;IACnD,OAAO,CAAC,SAAS,EAAEF,KAAK,WAAW,EAAE5B,QAAQ6B,KAAK,iBAAiB,EAAEH,MAAMK,KAAK,CAAC,aAAa,EAAEH,KAAK,sEAAsE,CAAC;AAC9K;AAEA,OAAO,SAASI,UAAU,EACxBC,GAAG,EACHC,QAAQ,EACRC,OAAO,KAAK,EACZC,QAAQ,KAAK,EACbC,IAAI,EACJC,OAAO,EACQ;cAgFLC,aAMAA;QA5ERN;IATF,MAAM,CAACO,aAAaC,eAAe,GAAGjD,SAAS;IAC/C,sEAAsE;IACtE,qDAAqD;IACrD,MAAM,CAACkD,SAASC,WAAW,GAAGnD,SAAS;IACvC,qEAAqE;IACrE,2EAA2E;IAC3E,wCAAwC;IACxC,MAAMoD,gBACJX,IAAIY,MAAM,KAAK,kBACfZ,EAAAA,cAAAA,IAAIvC,MAAM,qBAAVuC,YAAYtC,MAAM,MAAK,UACvB,CAAChB,uBAAuBsD,QACxBxD,2BAA2BqE,QAAQ,CAACb,IAAIc,IAAI;IAC9C,MAAMC,WAAWlE,uBAAuBuD,MAAMJ,IAAIgB,KAAK,EAAEL;IACzD,MAAMM,WAAWN,gBAAgBhE,oBAAoBoE,UAAU;QAAEG,QAAQlB,IAAIkB,MAAM;QAAEC,aAAanB,IAAIrB,EAAE;IAAC,KAAK;IAC9G,MAAM,EAAE2B,IAAI,EAAE7C,MAAM,EAAE,GAAGuC;IACzB,IAAI,CAACM,QAAQ,CAAC7C,QAAQ,OAAO;IAC7B,MAAM2D,UAAUjB,QAAQ3C,mBAAmBC,UAAU,EAAE;IACvD,mFAAmF,GACnF,MAAMiC,QAAQ,CAAC2B;;eACb,CAACA,MACG,KACAvF,eAAeuF,OACbA,IAAIC,KAAK,CAAC,OAAOrD,MAAM,YACtBqC,wBAAAA,KAAMiB,MAAM,CAACF,IAAI,mBAAIA;;IAC9B,4EAA4E;IAC5E,MAAMG,UAAUxB,IAAIY,MAAM,KAAK,kBAAkBnD,WAAW,QAAQ,CAACf,uBAAuBsD;IAC5F,wEAAwE;IACxE,wEAAwE;IACxE,2EAA2E;IAC3E,sEAAsE;IACtE,6DAA6D;IAC7D,MAAMyB,QAAQnB,QAAQkB,WAAW/D,OAAOC,MAAM,KAAK,SAASzB,iBAAiB+D,IAAIc,IAAI,EAAER,QAAQ;IAC/F,yEAAyE;IACzE,oEAAoE;IACpE,MAAMoB,sBAAcjE,0BAAAA,OAAQiE,WAAW,mBAAI;IAC3C,MAAMC,SACJrB,QAAQmB,SAASzB,IAAIc,IAAI,KAAK,UAAU3E,mBAAmBsF,OAAOC,aAAa1F,eAAesE,SAAS;IACzG,gGAAgG;IAChG,MAAMsB,cACJtB,QAAQkB,WAAW/D,OAAOC,MAAM,KAAK,UAAUsC,IAAIc,IAAI,KAAK,UACxD/E,uBAAuBuE,MAAMuB,QAAQH,gBACrC;IACN,MAAMI,gBAAgB9B,IAAIc,IAAI,KAAK,WAAWd,IAAI+B,YAAY,KAAK,QAAQP,WAAW/D,OAAOC,MAAM,KAAK;IACxG,MAAMsE,aAAaF,iBAAiBrB,UAAU;QAAEA,SAAS;IAAK,IAAI,CAAC;IACnE,qBACE,MAACzD;QAAIsC,IAAI;YAAE2C,IAAI;QAAE;;YACd3B,sBACC,MAACjD;gBAAM6E,SAAS;gBAAKC,MAAK;gBAAOC,cAAW;;kCAC1C,KAAC9E;wBAAW+E,SAAQ;wBAAUC,OAAM;kCACjChC,KAAKM,MAAM,KAAK,cAAc,mBAAmB;;oBAEnDN,KAAKiC,KAAK,CAACvD,GAAG,CAAC,CAACwD,OAAOC,sBACtB,MAACnF;4BAAkC+E,SAAQ;4BAAQF,MAAK;;gCAAW;gCACrDK,MAAM1B,IAAI,KAAK,WAAW,SAAS0B,MAAM1B,IAAI;gCAAC;gCAAEpB,MAAM8C,MAAM7D,EAAE;gCAAE;gCAAI6D,MAAME,OAAO;;2BAD9E,CAAC,MAAM,EAAED,OAAO;oBAIlCnC,KAAKqC,MAAM,CAAC3D,GAAG,CAAC,CAACwD,OAAOC,sBACvB,MAACnF;4BAAmC+E,SAAQ;4BAAQF,MAAK;;gCAAW;gCACrDvG,4BAA4B,CAAC4G,MAAM1B,IAAI,CAAC,CAAC8B,IAAI;gCAAC;gCAAEJ,MAAMvD,IAAI;gCACtEuD,MAAMK,WAAW,GACd,CAAC,iBAAiB,EAAEnD,MAAM8C,MAAMK,WAAW,GAAG,GAC9C;gCAAI;gCAAI;gCACTL,MAAMM,GAAG;;2BALG,CAAC,OAAO,EAAEL,OAAO;oBAQnCnC,KAAKyC,OAAO,CAAC/D,GAAG,CAAC,CAACgE,QAAQP,sBACzB,MAACnF;4BAAmC+E,SAAQ;4BAAQF,MAAK;;gCACtDa,OAAOC,MAAM,GACV,CAAC,2BAA2B,EAAED,OAAOE,KAAK,CAAC,uBAAuB,EAAExD,MAAMsD,OAAOC,MAAM,CAACE,OAAO,EAAE,KAAK,EAAEH,OAAOC,MAAM,CAACG,IAAI,CAAC,EAAE,CAAC,GAC9H,CAAC,gBAAgB,EAAEJ,OAAOE,KAAK,CAAC,IAAI,EAAEF,OAAOK,IAAI,EAAE;gCACtDL,OAAOH,WAAW,GACf,CAAC,iBAAiB,EAAEnD,MAAMsD,OAAOH,WAAW,GAAG,GAC/C;gCACHG,OAAOM,MAAM,GAAG,CAAC,IAAI,EAAE5D,MAAMsD,OAAOM,MAAM,GAAG,GAAG;gCAChDN,OAAOO,QAAQ,CAACtF,MAAM,GACnB,CAAC,EAAE,EAAE+E,OAAOO,QAAQ,CAACvE,GAAG,CAAC,CAACwE,UAAYA,QAAQvE,IAAI,EAAEf,IAAI,CAAC,OAAO,GAChE;;2BAVW,CAAC,OAAO,EAAEuE,OAAO;oBAanC,EAACnC,cAAAA,KAAKmD,KAAK,YAAVnD,cAAc,EAAE,EAAEtB,GAAG,CAAC,CAAC0E,qBACvB,MAACpG;4BAAqC+E,SAAQ;4BAAQF,MAAK;;gCACxD,CAAC,UAAU,EAAE7F,cAAcoH,KAAKC,EAAE,EAAEC,WAAW,GAAG,CAAC,EAAEF,KAAKzE,IAAI,EAAE;gCAChEyE,KAAKZ,GAAG,GAAG,CAAC,GAAG,EAAEY,KAAKZ,GAAG,EAAE,GAAG;;2BAFhB,CAAC,KAAK,EAAEY,KAAKG,IAAI,EAAE;oBAKrC,EAACvD,eAAAA,KAAKwD,MAAM,YAAXxD,eAAe,EAAE,EAAEtB,GAAG,CAAC,CAACS,OAAOgD,sBAC/B,KAACnF;4BAAkC+E,SAAQ;4BAAQF,MAAK;sCACrD3C,gBAAgBC,OAAOC;2BADT,CAAC,MAAM,EAAE+C,OAAO;oBAKlClG,uBAAuB+D,MAAMtB,GAAG,CAAC,CAAC+E,qBACjC,KAACzG;4BAAqC+E,SAAQ;4BAAQF,MAAK;4BAAW6B,uBAAoB;sCACvF,CAAC,cAAc,EAAED,KAAKb,KAAK,CAAC,IAAI,EAAEa,KAAKE,IAAI,CAAC,yDAAyD,CAAC;2BADxF,CAAC,MAAM,EAAEF,KAAKG,GAAG,EAAE;;;YAWzC/D,UAAS1C,0BAAAA,OAAQ0G,MAAM,mBACtB,KAAC7G;gBAAW+E,SAAQ;gBAAUC,OAAM;gBAAiB8B,WAAU;gBAAM9E,IAAI;oBAAE2C,IAAI;gBAAI;0BAChFxE,OAAO0G,MAAM;;YAGjB1G,CAAAA,0BAAAA,OAAQC,MAAM,MAAK,cAAcD,OAAOG,QAAQ,CAACK,MAAM,GAAG,KAAMkC,CAAAA,SAAS,CAAC1C,OAAO0G,MAAM,AAAD,mBACrF,KAACnH;gBACCoH,WAAU;gBACV9E,IAAI;oBAAE+E,IAAI;oBAAKC,IAAI;gBAAI;gBACvBlC,cAAW;0BAEV3E,OAAOG,QAAQ,CAACoB,GAAG,CAAC,CAAClB,SAAS2E,sBAC7B,KAACnF;wBAEC8G,WAAU;wBACV/B,SAAQ;kCAEPvE,QAAQyG,OAAO;uBAJX,CAAC,QAAQ,EAAE9B,OAAO;;YAS9BrB,QAAQnD,MAAM,GAAG,mBAChB,MAACjB;gBAAIsC,IAAI;oBAAE2C,IAAI;gBAAI;;kCACjB,KAAChF;wBACCuH,MAAK;wBACLC,iBAAelE;wBACfmE,SAAS,IAAMlE,eAAe,CAACmE,QAAU,CAACA;kCAEzCpE,cAAc,0BAA0B;;kCAE3C,KAACpD;wBAASyH,IAAIrE;wBAAasE,aAAa;kCACtC,cAAA,KAACvH;4BACC+E,SAAQ;4BACR+B,WAAU;4BACVhC,cAAW;4BACX9C,IAAI;gCAAEwF,GAAG;gCAAGC,YAAY;gCAAaC,YAAY;gCAAOC,WAAW;4BAAO;sCAEzE7D,QAAQlD,IAAI,CAAC;;;;;YAKrBuD,SAASA,MAAMyD,OAAO,GAAG,mBACxB,MAAC5H;gBACC+E,SAAQ;gBACRC,OAAM;gBACNhD,IAAI;oBAAE6F,SAAS;oBAASlD,IAAI;gBAAE;;oBAE7B,CAAC,gBAAgB,EAAE/F,kBAAkBuF,OAAO,wCAAwC,CAAC;oBACrFC,eAAe,CAACC,SACb,CAAC,UAAU,EAAED,YAAY0D,IAAI,CAACC,cAAc,CAAC,SAAS,gDAAgD,EAAEjJ,wBAAwBsF,YAAY4D,QAAQ,EAAE,CAAC,CAAC,GACxJ;;;YAGP1D,6BACC,KAACtE;gBAAW+E,SAAQ;gBAAUC,OAAM;gBAAiBhD,IAAI;oBAAE6F,SAAS;oBAASlD,IAAI;gBAAI;0BAClFL;;YAGJJ,WAAW/D,OAAO8H,YAAY,IAAI9H,OAAOC,MAAM,KAAK,wBACnD,KAACJ;gBAAW+E,SAAQ;gBAAUC,OAAM;gBAAiB8B,WAAU;gBAAM9E,IAAI;oBAAE2C,IAAI;gBAAE;0BAC9ExE,OAAO8H,YAAY;;YAGvBzD,+BACC,KAAC1E;gBACCkC,IAAI;oBAAE6F,SAAS;oBAAQlD,IAAI;gBAAE;gBAC7BuD,uBAAS,KAACtI;oBAASsH,MAAK;oBAAQiB,SAAShF;oBAASiF,UAAU,CAACC,QAAUjF,WAAWiF,MAAMC,MAAM,CAACH,OAAO;;gBACtGI,qBAAO,KAACvI;oBAAW+E,SAAQ;8BAAS;;;YAGvCb,WAAWG,wBACV,KAACtF;gBACCsF,QAAQA;gBACRiB,MAAK;gBACLvC,SAASA;gBACTH,MAAMA;gBACN4F,iBAAiB,IAAM7F,SAASD,KAAK,aAAKgC;wBAAY+D,kBAAkB;;gBACxEC,WAAW,IAAM/F,SAASD,KAAK,aAAKgC;wBAAY+D,kBAAkB;wBAAME,QAAQ;;;YAGnFhF,0BACC,KAAClE;gBAAMmJ,UAAS;gBAAO5G,IAAI;oBAAE2C,IAAI;gBAAE;0BAChCxF;;YAGJ+E,WAAW,CAACG,wBACX,KAAC1E;gBACCuH,MAAK;gBACLnC,SAAQ;gBACR,8DAA8D;gBAC9D,yCAAyC;gBACzC8D,UAAUjG,QAASzC,OAAOC,MAAM,KAAK,UAAUmE,QAAQpE,OAAO8H,YAAY;gBAC1Eb,SAAS,IAAMzE,SAASD,KAAK8B,iBAAiBrB,UAAUuB,aAAaoE;gBACrE9G,IAAI;oBAAE2C,IAAI;gBAAE;0BAEXxE,OAAOC,MAAM,KAAK,SAAS,iBAAiB;;YAIhD8D,WAAWpB,QAAQxD,6BAA6BoD,sBAAQ,KAAClD;gBAAsBkD,KAAKA;gBAAKI,MAAMA;;;;AAGtG;AAEA,eAAeL,UAAS"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-job-plan.component.tsx"],"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 { aiJobPlanHeading, aiJobPlanLines, aiPlanEmbedLine } from '../model/ai-job-plan-lines'\nimport type { AiJobReview, AiJobSummary } from '../model/ai-jobs.types'\nimport { aiBuildFreePageCapNote, aiBuildSmaller, aiJobCreditRange } from '../model/ai-build-job'\nimport { aiCreditRangeText, aiCreditsPromptFor } from '../model/ai-credit-estimate'\nimport { aiFreeCreditsResetLabel } from '../model/ai-site-job'\nimport { AiCreditsPromptNotice } from './ai-credits-prompt.component'\nimport type { AiJobResumeOptions } from './ai-job-requests'\nimport {\n AI_PAGE_BUILDING_JOB_KINDS,\n AI_SITE_BUILD_IN_FLIGHT_COPY,\n aiJobConfirmingOwnPlan,\n aiSiteBuildInFlight,\n} from '../model/ai-job-activity'\nimport { aiSiteStarterFallbackOffered } from '../model/ai-job-failure-copy'\nimport { useAiJobsInFlightKnown } from './ai-jobs-store'\nimport { AiSiteStarterFallback } from './ai-site-starter-fallback.component'\nimport { Alert, Box, Button, Checkbox, Collapse, FormControlLabel, Stack, Typography } from '@mui/material'\nimport { useState } from 'react'\n\n/**\n * A job's plan and what it waits for (AGL-2935), inside the AI jobs drawer\n * and the dialog that started the job (AGL-3593): what the job reuses from\n * the site, what it creates and why, the screens it builds — and, while the\n * job waits for a person, the one button that confirms the plan or tries a\n * refused step again. Both send the same request (`resumeAiJobRequest`);\n * this renders.\n */\nexport interface AiJobPlanProps {\n job: AiJobSummary\n /**\n * Confirms the plan, or tries the refused step again. A build whose request\n * asked to publish confirms with `publish` when its box is ticked (AGL-3616).\n */\n onResume: (job: AiJobSummary, options?: AiJobResumeOptions) => void\n /** A resume for this job is in flight. */\n busy?: boolean\n /**\n * The viewer is staff (AGL-3078), who can open where a refused answer broke\n * its rules and the outline of those parts, to tell a shape the rules should\n * allow from an answer that ignored its re-ask. A member reads the findings.\n */\n staff?: boolean\n /**\n * The signed-in user, for \"Use the starter site instead\" on a guided start\n * that did not work out (AGL-3594); the action is drawn only when given.\n */\n user?: Parameters<typeof AiSiteStarterFallback>[0]['user']\n /** The workspace's path slug, for the Upgrade a Free build past what is left offers (AGL-3722). */\n orgSlug?: string | null\n}\n\n/**\n * Where a refused answer broke its rules, and the outline of those parts, as\n * lines staff read (AGL-3078): each finding with the nodes or plan entries it\n * names, then each outlined node indented by its depth, with its element, a\n * Grid's layout as written, and the names of what it sets and holds.\n */\nexport function aiJobReviewDetails(review: AiJobReview | null): string[] {\n if (review?.reason !== 'doctrine') return []\n const lines = review.findings.flatMap((finding) => {\n const where = finding.nodeIds?.length\n ? `nodes ${finding.nodeIds.join(', ')}`\n : finding.paths?.length\n ? `at ${finding.paths.join(', ')}`\n : null\n return where ? [`${finding.rule === null ? '' : `Rule ${finding.rule} `}${finding.code}: ${where}`] : []\n })\n for (const node of review.outline ?? []) {\n lines.push(\n [\n `${' '.repeat(node.depth)}${node.id} ${node.componentId}`,\n ...Object.entries(node.grid ?? {}).map(([name, value]) => `${name}=${JSON.stringify(value)}`),\n ...(node.props.length ? [`props ${node.props.join(', ')}`] : []),\n ...(node.sx?.length ? [`sx ${node.sx.join(', ')}`] : []),\n ...(node.children.length ? [`holds ${node.children.join(', ')}`] : []),\n ].join(' · '),\n )\n }\n return lines\n}\n\n// A plan's lines are the model's, which the native apps' follow view sends\n// too (AGL-3854); re-exported for this card's existing readers.\nexport { aiPlanEmbedLine }\n\nexport function AiJobPlan({\n job,\n onResume,\n busy = false,\n staff = false,\n user,\n orgSlug,\n}: AiJobPlanProps): JSX.Element | null {\n const [detailsOpen, setDetailsOpen] = useState(false)\n // Unticked until the person ticks it: a build publishes only when its\n // request asked AND they confirm it here (AGL-3616).\n const [publish, setPublish] = useState(false)\n // Confirming builds pages while another job is building on this site\n // (AGL-3765), from the list the indicator and the panel already hold: said\n // beside Confirm, which still confirms.\n const confirmsPages =\n job.status === 'needs_review' &&\n job.review?.reason === 'plan' &&\n !aiJobConfirmingOwnPlan(job) &&\n AI_PAGE_BUILDING_JOB_KINDS.includes(job.kind)\n const inFlight = useAiJobsInFlightKnown(user, job.orgId, confirmsPages)\n const building = confirmsPages ? aiSiteBuildInFlight(inFlight, { hostId: job.hostId, exceptJobId: job.id }) : null\n const { plan, review } = job\n if (!plan && !review) return null\n const details = staff ? aiJobReviewDetails(review) : []\n // A plan the machine is confirming itself is not one to confirm (AGL-3596).\n const waiting = job.status === 'needs_review' && review !== null && !aiJobConfirmingOwnPlan(job)\n // The guard rail (AGL-2911): what the plan is estimated to cost is read\n // before it is confirmed, not after it has been spent. An estimate, and\n // said to be one: what it is likely to cost — what builds like it measured\n // — and its ceiling, every pass at its reserve (AGL-3722). A page job\n // counts the creations it builds before its page (AGL-3031).\n const range = plan && waiting && review.reason === 'plan' ? aiJobCreditRange(job.kind, plan) : null\n // A Free build past what is left asks first (AGL-3722): build what fits,\n // the home page first, or upgrade — never a refusal with no way on.\n const freeCredits = review?.freeCredits ?? null\n const prompt =\n plan && range && job.kind === 'build' ? aiCreditsPromptFor(range, freeCredits, aiBuildSmaller(plan)) : null\n // A Free build at its page cap says so (AGL-3722): pages past it were left for a later request.\n const pageCapNote =\n plan && waiting && review.reason === 'plan' && job.kind === 'build'\n ? aiBuildFreePageCapNote(plan, Boolean(freeCredits))\n : null\n const offersPublish = job.kind === 'build' && job.publishAsked === true && waiting && review.reason === 'plan'\n const publishing = offersPublish && publish ? { publish: true } : {}\n return (\n <Box sx={{ mt: 1 }}>\n {plan && (\n <Stack spacing={0.5} role=\"list\" aria-label=\"Plan\">\n <Typography variant=\"caption\" color=\"text.secondary\">\n {aiJobPlanHeading(plan)}\n </Typography>\n {aiJobPlanLines(plan).map((line) => (\n <Typography\n key={line.key}\n variant=\"body2\"\n role=\"listitem\"\n {...(line.platformAdded ? { 'data-platform-added': 'true' } : {})}\n >\n {line.text}\n </Typography>\n ))}\n </Stack>\n )}\n {/*\n A review written for the member (AGL-3594) carries the checks' own\n sentence as `detail`: its findings are then staff reading too, and the\n member reads the job's one sentence alone.\n */}\n {staff && review?.detail && (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\" sx={{ mt: 0.5 }}>\n {review.detail}\n </Typography>\n )}\n {review?.reason === 'doctrine' && review.findings.length > 0 && (staff || !review.detail) && (\n <Box\n component=\"ul\"\n sx={{ my: 0.5, pl: 2.5 }}\n aria-label=\"Building rules broken\"\n >\n {review.findings.map((finding, index) => (\n <Typography\n key={`finding-${index}`}\n component=\"li\"\n variant=\"caption\"\n >\n {finding.message}\n </Typography>\n ))}\n </Box>\n )}\n {details.length > 0 && (\n <Box sx={{ mt: 0.5 }}>\n <Button\n size=\"small\"\n aria-expanded={detailsOpen}\n onClick={() => setDetailsOpen((prior) => !prior)}\n >\n {detailsOpen ? 'Hide what was refused' : 'Show what was refused'}\n </Button>\n <Collapse in={detailsOpen} unmountOnExit>\n <Typography\n variant=\"caption\"\n component=\"pre\"\n aria-label=\"What was refused\"\n sx={{ m: 0, fontFamily: 'monospace', whiteSpace: 'pre', overflowX: 'auto' }}\n >\n {details.join('\\n')}\n </Typography>\n </Collapse>\n </Box>\n )}\n {range && range.ceiling > 0 && (\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ display: 'block', mt: 1 }}\n >\n {`Estimated cost: ${aiCreditRangeText(range)}. What it costs is what its steps spend.`}\n {freeCredits && !prompt\n ? ` You have ${freeCredits.left.toLocaleString('en-US')} of your free AI credits left this month, until ${aiFreeCreditsResetLabel(freeCredits.resetsOn)}.`\n : ''}\n </Typography>\n )}\n {pageCapNote && (\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ display: 'block', mt: 0.5 }}>\n {pageCapNote}\n </Typography>\n )}\n {waiting && review.retryRefusal && review.reason !== 'plan' && (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\" sx={{ mt: 1 }}>\n {review.retryRefusal}\n </Typography>\n )}\n {offersPublish && (\n <FormControlLabel\n sx={{ display: 'flex', mt: 1 }}\n control={<Checkbox size=\"small\" checked={publish} onChange={(event) => setPublish(event.target.checked)} />}\n label={<Typography variant=\"body2\">{'Publish the new pages when they are built'}</Typography>}\n />\n )}\n {waiting && prompt && (\n <AiCreditsPromptNotice\n prompt={prompt}\n noun=\"build\"\n orgSlug={orgSlug}\n busy={busy}\n onBuildWhatFits={() => onResume(job, { ...publishing, creditsConfirmed: true })}\n onSmaller={() => onResume(job, { ...publishing, creditsConfirmed: true, reduce: 'first-page' })}\n />\n )}\n {building && (\n <Alert severity=\"info\" sx={{ mt: 1 }}>\n {AI_SITE_BUILD_IN_FLIGHT_COPY}\n </Alert>\n )}\n {waiting && !prompt && (\n <Button\n size=\"small\"\n variant=\"contained\"\n // Disabled with its reason above when the Free allowance left\n // cannot pay for another try (AGL-3594).\n disabled={busy || (review.reason !== 'plan' && Boolean(review.retryRefusal))}\n onClick={() => onResume(job, offersPublish && publish ? publishing : undefined)}\n sx={{ mt: 1 }}\n >\n {review.reason === 'plan' ? 'Confirm plan' : 'Try again'}\n </Button>\n )}\n {/* A guided start that did not work out can take the starter instead (AGL-3594). */}\n {waiting && user && aiSiteStarterFallbackOffered(job) && <AiSiteStarterFallback job={job} user={user} />}\n </Box>\n )\n}\n\nexport default AiJobPlan\n"],"names":["aiJobPlanHeading","aiJobPlanLines","aiPlanEmbedLine","aiBuildFreePageCapNote","aiBuildSmaller","aiJobCreditRange","aiCreditRangeText","aiCreditsPromptFor","aiFreeCreditsResetLabel","AiCreditsPromptNotice","AI_PAGE_BUILDING_JOB_KINDS","AI_SITE_BUILD_IN_FLIGHT_COPY","aiJobConfirmingOwnPlan","aiSiteBuildInFlight","aiSiteStarterFallbackOffered","useAiJobsInFlightKnown","AiSiteStarterFallback","Alert","Box","Button","Checkbox","Collapse","FormControlLabel","Stack","Typography","useState","aiJobReviewDetails","review","reason","lines","findings","flatMap","finding","where","nodeIds","length","join","paths","rule","code","node","outline","push","repeat","depth","id","componentId","Object","entries","grid","map","name","value","JSON","stringify","props","sx","children","AiJobPlan","job","onResume","busy","staff","user","orgSlug","detailsOpen","setDetailsOpen","publish","setPublish","confirmsPages","status","includes","kind","inFlight","orgId","building","hostId","exceptJobId","plan","details","waiting","range","freeCredits","prompt","pageCapNote","Boolean","offersPublish","publishAsked","publishing","mt","spacing","role","aria-label","variant","color","line","platformAdded","text","key","detail","component","my","pl","index","message","size","aria-expanded","onClick","prior","in","unmountOnExit","m","fontFamily","whiteSpace","overflowX","ceiling","display","left","toLocaleString","resetsOn","retryRefusal","control","checked","onChange","event","target","label","noun","onBuildWhatFits","creditsConfirmed","onSmaller","reduce","severity","disabled","undefined"],"mappings":"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"}
|
|
@@ -355,15 +355,54 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
355
355
|
setServerPrompt(null);
|
|
356
356
|
try {
|
|
357
357
|
var _ref;
|
|
358
|
+
const requestJob = (siteId, check)=>authorizedFetch(userRef.current, '/api/ai/jobs', {
|
|
359
|
+
method: 'POST',
|
|
360
|
+
headers: {
|
|
361
|
+
'Content-Type': 'application/json'
|
|
362
|
+
},
|
|
363
|
+
body: JSON.stringify(_extends({
|
|
364
|
+
orgId,
|
|
365
|
+
hostId: siteId,
|
|
366
|
+
kind: 'site',
|
|
367
|
+
brief: aiSiteStartBrief(asked),
|
|
368
|
+
// The guided start confirms its own plan (AGL-3594): the build
|
|
369
|
+
// follows the plan with no approval to make.
|
|
370
|
+
inputs: _extends({}, aiSiteStartInputs(asked), {
|
|
371
|
+
[AI_JOB_AUTO_CONFIRM_INPUT]: true
|
|
372
|
+
})
|
|
373
|
+
}, pickedModel ? {
|
|
374
|
+
model: pickedModel
|
|
375
|
+
} : {}, options.creditsConfirmed ? {
|
|
376
|
+
creditsConfirmed: true
|
|
377
|
+
} : {}, check ? {
|
|
378
|
+
check: true
|
|
379
|
+
} : {}))
|
|
380
|
+
});
|
|
381
|
+
// A refusal said in the dialog, or the Free go-ahead it asks for.
|
|
382
|
+
const refused = async (response)=>{
|
|
383
|
+
var _ref;
|
|
384
|
+
const payload = await response.json().catch(()=>null);
|
|
385
|
+
if (response.ok) return payload != null ? payload : {};
|
|
386
|
+
if (response.status === 409 && (payload == null ? void 0 : payload.code) === AI_CREDITS_CONFIRM_CODE && (payload == null ? void 0 : payload.credits)) {
|
|
387
|
+
setServerPrompt(payload.credits);
|
|
388
|
+
return null;
|
|
389
|
+
}
|
|
390
|
+
const locked = parseLockdownRefusal(response.status, payload);
|
|
391
|
+
setNotice(locked ? lockdownRefusalText(locked) : String((_ref = payload == null ? void 0 : payload.error) != null ? _ref : 'The site could not be started. Try again.'));
|
|
392
|
+
return null;
|
|
393
|
+
};
|
|
358
394
|
// The site, created now when it does not exist yet (AGL-3761): this is
|
|
359
|
-
// the moment the person asked for it.
|
|
360
|
-
//
|
|
395
|
+
// the moment the person asked for it. The start is checked first
|
|
396
|
+
// (AGL-3859), so one the jobs route would refuse, or would ask the Free
|
|
397
|
+
// go-ahead for, is answered before any site exists. A refusal about the
|
|
398
|
+
// name or address goes back to step 1, where they are typed.
|
|
361
399
|
let site = {
|
|
362
400
|
hostId,
|
|
363
401
|
host,
|
|
364
402
|
orgSlug
|
|
365
403
|
};
|
|
366
404
|
if (!hostId && pendingSite) {
|
|
405
|
+
if (!pendingSite.created && !await refused(await requestJob(null, true))) return;
|
|
367
406
|
const made = await pendingSite.create();
|
|
368
407
|
if ('error' in made) {
|
|
369
408
|
setNotice(made.error);
|
|
@@ -377,38 +416,8 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
377
416
|
};
|
|
378
417
|
}
|
|
379
418
|
if (!site.hostId) return;
|
|
380
|
-
const
|
|
381
|
-
|
|
382
|
-
headers: {
|
|
383
|
-
'Content-Type': 'application/json'
|
|
384
|
-
},
|
|
385
|
-
body: JSON.stringify(_extends({
|
|
386
|
-
orgId,
|
|
387
|
-
hostId: site.hostId,
|
|
388
|
-
kind: 'site',
|
|
389
|
-
brief: aiSiteStartBrief(asked),
|
|
390
|
-
// The guided start confirms its own plan (AGL-3594): the build
|
|
391
|
-
// follows the plan with no approval to make.
|
|
392
|
-
inputs: _extends({}, aiSiteStartInputs(asked), {
|
|
393
|
-
[AI_JOB_AUTO_CONFIRM_INPUT]: true
|
|
394
|
-
})
|
|
395
|
-
}, pickedModel ? {
|
|
396
|
-
model: pickedModel
|
|
397
|
-
} : {}, options.creditsConfirmed ? {
|
|
398
|
-
creditsConfirmed: true
|
|
399
|
-
} : {}))
|
|
400
|
-
});
|
|
401
|
-
const payload = await response.json().catch(()=>null);
|
|
402
|
-
if (!response.ok) {
|
|
403
|
-
var _ref1;
|
|
404
|
-
if (response.status === 409 && (payload == null ? void 0 : payload.code) === AI_CREDITS_CONFIRM_CODE && (payload == null ? void 0 : payload.credits)) {
|
|
405
|
-
setServerPrompt(payload.credits);
|
|
406
|
-
return;
|
|
407
|
-
}
|
|
408
|
-
const locked = parseLockdownRefusal(response.status, payload);
|
|
409
|
-
setNotice(locked ? lockdownRefusalText(locked) : String((_ref1 = payload == null ? void 0 : payload.error) != null ? _ref1 : 'The site could not be started. Try again.'));
|
|
410
|
-
return;
|
|
411
|
-
}
|
|
419
|
+
const payload = await refused(await requestJob(site.hostId, false));
|
|
420
|
+
if (!payload) return;
|
|
412
421
|
const created = (_ref = payload == null ? void 0 : payload.job) != null ? _ref : null;
|
|
413
422
|
if (!created) {
|
|
414
423
|
setNotice('The site could not be started. Try again.');
|