@aglyn/plugins-ai 1.0.0-beta.233 → 1.0.0-beta.235

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.
Files changed (199) hide show
  1. package/package.json +17 -17
  2. package/src/lib/activity/ai-activity-actions.d.ts +25 -0
  3. package/src/lib/activity/ai-activity-actions.js +85 -4
  4. package/src/lib/activity/ai-activity-actions.js.map +1 -1
  5. package/src/lib/components/ai-brief-dialog.component.js +46 -2
  6. package/src/lib/components/ai-brief-dialog.component.js.map +1 -1
  7. package/src/lib/components/ai-campaign-create.component.js +1 -1
  8. package/src/lib/components/ai-campaign-create.component.js.map +1 -1
  9. package/src/lib/components/ai-credits-card.component.js +3 -3
  10. package/src/lib/components/ai-credits-card.component.js.map +1 -1
  11. package/src/lib/components/ai-crm-email-draft.component.js +1 -1
  12. package/src/lib/components/ai-crm-email-draft.component.js.map +1 -1
  13. package/src/lib/components/ai-crm-import-mapping.component.js +1 -1
  14. package/src/lib/components/ai-crm-import-mapping.component.js.map +1 -1
  15. package/src/lib/components/ai-crm-record-card.component.js +1 -1
  16. package/src/lib/components/ai-crm-record-card.component.js.map +1 -1
  17. package/src/lib/components/ai-describe-automation.component.js +4 -2
  18. package/src/lib/components/ai-describe-automation.component.js.map +1 -1
  19. package/src/lib/components/ai-describe-org-automation.component.js +1 -1
  20. package/src/lib/components/ai-describe-org-automation.component.js.map +1 -1
  21. package/src/lib/components/ai-experiment-cards.component.js +2 -2
  22. package/src/lib/components/ai-experiment-cards.component.js.map +1 -1
  23. package/src/lib/components/ai-explain-automation.component.js +1 -1
  24. package/src/lib/components/ai-explain-automation.component.js.map +1 -1
  25. package/src/lib/components/ai-insight-card.component.js +3 -1
  26. package/src/lib/components/ai-insight-card.component.js.map +1 -1
  27. package/src/lib/components/ai-job-links.d.ts +6 -0
  28. package/src/lib/components/ai-job-links.js +9 -0
  29. package/src/lib/components/ai-job-links.js.map +1 -1
  30. package/src/lib/components/ai-jobs-list-page.component.d.ts +6 -1
  31. package/src/lib/components/ai-jobs-list-page.component.js +15 -2
  32. package/src/lib/components/ai-jobs-list-page.component.js.map +1 -1
  33. package/src/lib/components/ai-logic.component.js +5 -3
  34. package/src/lib/components/ai-logic.component.js.map +1 -1
  35. package/src/lib/components/ai-media-create.component.js +88 -16
  36. package/src/lib/components/ai-media-create.component.js.map +1 -1
  37. package/src/lib/components/ai-model-selector.component.js +8 -0
  38. package/src/lib/components/ai-model-selector.component.js.map +1 -1
  39. package/src/lib/components/ai-overlay-cards.component.js +2 -2
  40. package/src/lib/components/ai-overlay-cards.component.js.map +1 -1
  41. package/src/lib/components/ai-product-copy-card.component.js +2 -1
  42. package/src/lib/components/ai-product-copy-card.component.js.map +1 -1
  43. package/src/lib/components/ai-products-hub-card.component.js +2 -1
  44. package/src/lib/components/ai-products-hub-card.component.js.map +1 -1
  45. package/src/lib/components/ai-revise-automation.component.js +1 -1
  46. package/src/lib/components/ai-revise-automation.component.js.map +1 -1
  47. package/src/lib/components/ai-seo-fields-card.component.js +7 -3
  48. package/src/lib/components/ai-seo-fields-card.component.js.map +1 -1
  49. package/src/lib/components/ai-site-batch-card.component.js +7 -4
  50. package/src/lib/components/ai-site-batch-card.component.js.map +1 -1
  51. package/src/lib/components/ai-site-build-page.component.js +48 -6
  52. package/src/lib/components/ai-site-build-page.component.js.map +1 -1
  53. package/src/lib/components/ai-site-seo-start-card.component.js +7 -4
  54. package/src/lib/components/ai-site-seo-start-card.component.js.map +1 -1
  55. package/src/lib/components/ai-site-start-card.component.js +152 -36
  56. package/src/lib/components/ai-site-start-card.component.js.map +1 -1
  57. package/src/lib/components/ai-theme-proposal-card.component.js +1 -0
  58. package/src/lib/components/ai-theme-proposal-card.component.js.map +1 -1
  59. package/src/lib/components/ai-upsell-dialog.component.js +17 -3
  60. package/src/lib/components/ai-upsell-dialog.component.js.map +1 -1
  61. package/src/lib/components/ai-usage-strip.component.js +13 -2
  62. package/src/lib/components/ai-usage-strip.component.js.map +1 -1
  63. package/src/lib/components/assist-build-card.component.js +20 -3
  64. package/src/lib/components/assist-build-card.component.js.map +1 -1
  65. package/src/lib/components/assist-jobs-drawer.component.js +7 -1
  66. package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
  67. package/src/lib/components/billing-ai-allotments.component.js +2 -2
  68. package/src/lib/components/billing-ai-allotments.component.js.map +1 -1
  69. package/src/lib/components/billing-ai-top-users.component.js +1 -0
  70. package/src/lib/components/billing-ai-top-users.component.js.map +1 -1
  71. package/src/lib/components/billing-assist-overage-card.component.js +2 -2
  72. package/src/lib/components/billing-assist-overage-card.component.js.map +1 -1
  73. package/src/lib/components/host-ai-allotments.component.js +2 -2
  74. package/src/lib/components/host-ai-allotments.component.js.map +1 -1
  75. package/src/lib/components/member-ai-allotment-card.component.js +2 -2
  76. package/src/lib/components/member-ai-allotment-card.component.js.map +1 -1
  77. package/src/lib/components/staff-org-ai-card.component.js +1 -0
  78. package/src/lib/components/staff-org-ai-card.component.js.map +1 -1
  79. package/src/lib/components/staff-org-ai-conversations.component.d.ts +9 -3
  80. package/src/lib/components/staff-org-ai-conversations.component.js +174 -83
  81. package/src/lib/components/staff-org-ai-conversations.component.js.map +1 -1
  82. package/src/lib/components/staff-user-ai-usage-card.component.js +2 -1
  83. package/src/lib/components/staff-user-ai-usage-card.component.js.map +1 -1
  84. package/src/lib/jobs/ai-job-admission.d.ts +2 -1
  85. package/src/lib/jobs/ai-job-admission.js.map +1 -1
  86. package/src/lib/jobs/ai-job-email-step.d.ts +39 -0
  87. package/src/lib/jobs/ai-job-email-step.js +116 -5
  88. package/src/lib/jobs/ai-job-email-step.js.map +1 -1
  89. package/src/lib/jobs/ai-job-layout-language.d.ts +3 -0
  90. package/src/lib/jobs/ai-job-layout-language.js +6 -1
  91. package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
  92. package/src/lib/jobs/ai-job-layout-site-pages.d.ts +14 -0
  93. package/src/lib/jobs/ai-job-layout-site-pages.js +43 -11
  94. package/src/lib/jobs/ai-job-layout-site-pages.js.map +1 -1
  95. package/src/lib/jobs/ai-job-layout-step.js +3 -2
  96. package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
  97. package/src/lib/jobs/ai-job-page-language.d.ts +26 -1
  98. package/src/lib/jobs/ai-job-page-language.js +75 -13
  99. package/src/lib/jobs/ai-job-page-language.js.map +1 -1
  100. package/src/lib/jobs/ai-job-page-step.d.ts +3 -0
  101. package/src/lib/jobs/ai-job-page-step.js +32 -7
  102. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  103. package/src/lib/jobs/ai-job-plan-step.d.ts +34 -0
  104. package/src/lib/jobs/ai-job-plan-step.js +106 -14
  105. package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
  106. package/src/lib/jobs/ai-job-site-content.d.ts +81 -13
  107. package/src/lib/jobs/ai-job-site-content.js +210 -43
  108. package/src/lib/jobs/ai-job-site-content.js.map +1 -1
  109. package/src/lib/jobs/ai-job-site-step.d.ts +19 -0
  110. package/src/lib/jobs/ai-job-site-step.js +152 -51
  111. package/src/lib/jobs/ai-job-site-step.js.map +1 -1
  112. package/src/lib/jobs/ai-jobs.d.ts +8 -4
  113. package/src/lib/jobs/ai-jobs.js +19 -2
  114. package/src/lib/jobs/ai-jobs.js.map +1 -1
  115. package/src/lib/jobs/ai-layout-stock-photos.d.ts +98 -0
  116. package/src/lib/jobs/ai-layout-stock-photos.js +248 -0
  117. package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -0
  118. package/src/lib/jobs/ai-site-publish.d.ts +11 -0
  119. package/src/lib/jobs/ai-site-publish.js +31 -1
  120. package/src/lib/jobs/ai-site-publish.js.map +1 -1
  121. package/src/lib/jobs/fixtures/ai-juniper-portfolio-page-recording.d.ts +151 -0
  122. package/src/lib/jobs/fixtures/ai-juniper-portfolio-page-recording.js +183 -0
  123. package/src/lib/jobs/fixtures/ai-juniper-portfolio-page-recording.js.map +1 -0
  124. package/src/lib/jobs/fixtures/ai-slow-roads-site-plan-recording.d.ts +27 -0
  125. package/src/lib/jobs/fixtures/ai-slow-roads-site-plan-recording.js +192 -0
  126. package/src/lib/jobs/fixtures/ai-slow-roads-site-plan-recording.js.map +1 -0
  127. package/src/lib/jobs/fixtures/ai-yoga-site-plan-recording.d.ts +27 -0
  128. package/src/lib/jobs/fixtures/ai-yoga-site-plan-recording.js +222 -0
  129. package/src/lib/jobs/fixtures/ai-yoga-site-plan-recording.js.map +1 -0
  130. package/src/lib/layout-language/ai-layout-compiler.d.ts +37 -0
  131. package/src/lib/layout-language/ai-layout-compiler.js +1003 -19
  132. package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
  133. package/src/lib/layout-language/ai-layout-design.d.ts +114 -0
  134. package/src/lib/layout-language/ai-layout-design.js +209 -0
  135. package/src/lib/layout-language/ai-layout-design.js.map +1 -0
  136. package/src/lib/layout-language/ai-layout-frame.d.ts +12 -0
  137. package/src/lib/layout-language/ai-layout-frame.js +33 -8
  138. package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
  139. package/src/lib/layout-language/ai-layout-gaps.js +18 -2
  140. package/src/lib/layout-language/ai-layout-gaps.js.map +1 -1
  141. package/src/lib/layout-language/ai-layout-language.d.ts +2 -0
  142. package/src/lib/layout-language/ai-layout-language.js +15 -1
  143. package/src/lib/layout-language/ai-layout-language.js.map +1 -1
  144. package/src/lib/layout-language/ai-layout-links.d.ts +36 -0
  145. package/src/lib/layout-language/ai-layout-links.js +26 -2
  146. package/src/lib/layout-language/ai-layout-links.js.map +1 -1
  147. package/src/lib/layout-language/ai-layout-listings.d.ts +125 -0
  148. package/src/lib/layout-language/ai-layout-listings.js +187 -0
  149. package/src/lib/layout-language/ai-layout-listings.js.map +1 -0
  150. package/src/lib/layout-language/ai-layout-pictures.d.ts +11 -5
  151. package/src/lib/layout-language/ai-layout-pictures.js +80 -17
  152. package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
  153. package/src/lib/model/ai-job-notice.d.ts +9 -1
  154. package/src/lib/model/ai-job-notice.js +23 -0
  155. package/src/lib/model/ai-job-notice.js.map +1 -1
  156. package/src/lib/model/ai-plan-capabilities.d.ts +7 -0
  157. package/src/lib/model/ai-plan-capabilities.js.map +1 -1
  158. package/src/lib/model/ai-site-build-progress.d.ts +12 -2
  159. package/src/lib/model/ai-site-build-progress.js +104 -15
  160. package/src/lib/model/ai-site-build-progress.js.map +1 -1
  161. package/src/lib/model/ai-site-job.d.ts +236 -24
  162. package/src/lib/model/ai-site-job.js +269 -22
  163. package/src/lib/model/ai-site-job.js.map +1 -1
  164. package/src/lib/model/ai-site-kinds.d.ts +30 -8
  165. package/src/lib/model/ai-site-kinds.js +735 -116
  166. package/src/lib/model/ai-site-kinds.js.map +1 -1
  167. package/src/lib/model/ai-site-look.d.ts +21 -0
  168. package/src/lib/model/ai-site-look.js +63 -14
  169. package/src/lib/model/ai-site-look.js.map +1 -1
  170. package/src/lib/model/ai-site-start-seo.d.ts +30 -0
  171. package/src/lib/model/ai-site-start-seo.js +132 -11
  172. package/src/lib/model/ai-site-start-seo.js.map +1 -1
  173. package/src/lib/model/ai-site-start.d.ts +2 -2
  174. package/src/lib/model/ai-site-start.js +3 -3
  175. package/src/lib/model/ai-site-start.js.map +1 -1
  176. package/src/lib/plugin.js +15 -3
  177. package/src/lib/plugin.js.map +1 -1
  178. package/src/lib/runtime/ai-doctrine-validators.d.ts +32 -1
  179. package/src/lib/runtime/ai-doctrine-validators.js +227 -4
  180. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
  181. package/src/lib/runtime/ai-doctrine.js +5 -3
  182. package/src/lib/runtime/ai-doctrine.js.map +1 -1
  183. package/src/lib/runtime/ai-palette.generated.d.ts +2 -0
  184. package/src/lib/runtime/ai-palette.generated.js +31 -5
  185. package/src/lib/runtime/ai-palette.generated.js.map +1 -1
  186. package/src/lib/server/ai-admin-conversations.d.ts +9 -0
  187. package/src/lib/server/ai-admin-conversations.js +151 -9
  188. package/src/lib/server/ai-admin-conversations.js.map +1 -1
  189. package/src/lib/server/ai-jobs-resume.js.map +1 -1
  190. package/src/lib/server/ai-jobs-route.js +15 -3
  191. package/src/lib/server/ai-jobs-route.js.map +1 -1
  192. package/src/lib/server/assist-edit.js +5 -2
  193. package/src/lib/server/assist-edit.js.map +1 -1
  194. package/src/lib/usage/free-ai-credits-left.d.ts +54 -0
  195. package/src/lib/usage/free-ai-credits-left.js +62 -0
  196. package/src/lib/usage/free-ai-credits-left.js.map +1 -0
  197. package/src/lib/usage/staff-org-ai-conversations.d.ts +23 -0
  198. package/src/lib/usage/staff-org-ai-conversations.js +45 -0
  199. package/src/lib/usage/staff-org-ai-conversations.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-jobs-list-page.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'use client'\n\nimport { PLATFORM_BRAND_NAME } from '@aglyn/aglyn'\nimport type { ConsolePluginPageProps } from '@aglyn/aglyn/plugin-manager/feature-plugins'\nimport { aiJobRefundCopy } from '../model/ai-job-failure-copy'\nimport { AppLink } from '@aglyn/shared-ui-jsx'\nimport { authorizedFetch, type MaybeTokenSource } from '@aglyn/shared-util-http/authorized-token'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n Box,\n Button,\n Card,\n Chip,\n CircularProgress,\n Container,\n List,\n ListItemButton,\n Stack,\n Typography,\n} from '@mui/material'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { AI_JOB_PHASE_LABELS, aiJobKindNoun, aiJobPhase, type AiJobPhase } from '../model/ai-job-activity'\nimport type { AiJobSummary } from '../model/ai-jobs.types'\nimport { publishAiJob } from './ai-jobs-store'\nimport { useAiJobSite } from './ai-job-site'\n\n/**\n * A site's AI jobs (AGL-3596), at `/ai-jobs` under the site: every job that\n * worked on this site, newest first, each linking to its own page.\n *\n * Read through the jobs route, never Firestore, so the membership, flag and\n * plan rungs that answer every other jobs read answer this one. The site is\n * a query on the route (`hostId`), not a filter of the workspace's list.\n *\n * Every wait ends: the site's read and the list's each settle on content,\n * the empty state, or a sentence with Try again.\n */\n\n/** The most jobs the page lists; the newest, which is what a person comes for. */\nexport const AI_JOBS_PAGE_LIMIT = 50\n\n/** How long the list may take before the page says it could not be loaded. */\nexport const AI_JOBS_LIST_TIMEOUT_MS = 20_000\n\n/** How much of a brief a row shows. */\nconst BRIEF_PREVIEW_CHARS = 120\n\n/** A row's chip, colored as the AI jobs drawer colors it. */\nconst PHASE_COLOR: Record<AiJobPhase, 'default' | 'primary' | 'success' | 'error' | 'warning'> = {\n queued: 'default',\n planning: 'primary',\n 'plan-ready': 'warning',\n building: 'primary',\n attention: 'warning',\n done: 'success',\n failed: 'error',\n canceled: 'default',\n}\n\nconst WHEN = new Intl.DateTimeFormat('en-US', { dateStyle: 'medium', timeStyle: 'short' })\n\n/** What a job cost the person: what it spent, less what we refunded. */\nexport function aiJobNetCredits(job: Pick<AiJobSummary, 'creditsSpent' | 'refundedCredits'>): number {\n return Math.max(0, (job.creditsSpent ?? 0) - (job.refundedCredits ?? 0))\n}\n\n/** The kind as a row names it: `Site`, `Page`, `AI job`. */\nexport function aiJobKindLabel(kind: AiJobSummary['kind']): string {\n const noun = aiJobKindNoun(kind)\n return noun === 'AI job' ? noun : noun.charAt(0).toUpperCase() + noun.slice(1)\n}\n\ntype ListState =\n | { status: 'loading' }\n | { status: 'ready'; jobs: AiJobSummary[] }\n | { status: 'error'; message: string }\n\nconst LOAD_ERROR = 'This site’s AI jobs could not be loaded. Try again in a moment.'\n\nasync function readSiteJobs(\n user: MaybeTokenSource,\n orgId: string,\n hostId: string,\n signal: AbortSignal,\n): Promise<ListState> {\n try {\n const response = await authorizedFetch(\n user,\n `/api/ai/jobs?orgId=${encodeURIComponent(orgId)}&hostId=${encodeURIComponent(hostId)}&limit=${AI_JOBS_PAGE_LIMIT}`,\n { signal },\n )\n const payload = (await response.json().catch(() => null)) as { jobs?: AiJobSummary[]; error?: string } | null\n if (!response.ok) return { status: 'error', message: String(payload?.error ?? LOAD_ERROR) }\n const jobs = payload?.jobs ?? []\n // A job the top-bar indicator still counts that has settled since leaves it.\n for (const job of jobs) publishAiJob(job)\n return { status: 'ready', jobs }\n } catch {\n return { status: 'error', message: LOAD_ERROR }\n }\n}\n\nexport function AiJobsListPage({ hostId, basePath }: ConsolePluginPageProps) {\n const { data: user } = useUser()\n const userRef = useRef<MaybeTokenSource>(user)\n userRef.current = user\n const site = useAiJobSite(hostId)\n const orgId = site.status === 'ready' ? site.orgId : null\n const [list, setList] = useState<ListState>({ status: 'loading' })\n const [attempt, setAttempt] = useState(0)\n const uid = user?.uid ?? null\n\n useEffect(() => {\n if (!orgId || !hostId || !uid) return undefined\n const controller = new AbortController()\n let settled = false\n setList({ status: 'loading' })\n const timer = setTimeout(() => {\n if (settled) return\n settled = true\n controller.abort()\n setList({ status: 'error', message: LOAD_ERROR })\n }, AI_JOBS_LIST_TIMEOUT_MS)\n void readSiteJobs(userRef.current, orgId, hostId, controller.signal).then((next) => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n setList(next)\n })\n return () => {\n settled = true\n clearTimeout(timer)\n controller.abort()\n }\n }, [orgId, hostId, uid, attempt])\n\n const retry = useCallback(() => setAttempt((count) => count + 1), [])\n\n const siteName = site.status === 'ready' ? site.name : ''\n const state: ListState =\n site.status === 'error'\n ? { status: 'error', message: 'This site could not be read. Check your connection and reload the page.' }\n : list\n\n return (\n <Container maxWidth=\"md\" sx={{ py: { xs: 3, sm: 5 }, px: { xs: 2, sm: 3 } }}>\n <Stack spacing={3}>\n <Stack spacing={1}>\n {siteName ? (\n <Typography variant=\"overline\" color=\"text.secondary\">\n {siteName}\n </Typography>\n ) : null}\n <Typography variant=\"h4\" component=\"h1\">\n {'AI jobs'}\n </Typography>\n <Typography variant=\"body1\" color=\"text.secondary\">\n {`What ${PLATFORM_BRAND_NAME} AI has done and is doing on this site, newest first.`}\n </Typography>\n </Stack>\n {state.status === 'loading' ? (\n <Stack sx={{ alignItems: 'center', py: 4 }}>\n <CircularProgress aria-label=\"Loading AI jobs\" />\n </Stack>\n ) : state.status === 'error' ? (\n <Alert\n severity=\"warning\"\n action={\n site.status === 'error' ? undefined : (\n <Button color=\"inherit\" size=\"small\" onClick={retry}>\n {'Try again'}\n </Button>\n )\n }\n >\n {state.message}\n </Alert>\n ) : state.jobs.length === 0 ? (\n <Card variant=\"outlined\" sx={{ borderRadius: 2, p: { xs: 2, sm: 3 } }}>\n <Stack spacing={1}>\n <Typography variant=\"h6\" component=\"h2\">\n {'No AI jobs on this site yet'}\n </Typography>\n <Typography variant=\"body1\" color=\"text.secondary\">\n {`An AI job is ${PLATFORM_BRAND_NAME} AI building something for this site from a short ` +\n 'description you write: a page, a page template, a layout, a form or a reusable component. ' +\n 'Each one gets a page here that shows its progress and what it built.'}\n </Typography>\n <Typography variant=\"body1\" color=\"text.secondary\">\n {'To start one, choose Create with AI on this site’s Pages, Templates, Layouts, Forms or ' +\n 'Components page. A new site can also be built with AI when it is created.'}\n </Typography>\n </Stack>\n </Card>\n ) : (\n <Card variant=\"outlined\" sx={{ borderRadius: 2 }}>\n <List disablePadding aria-label=\"AI jobs\">\n {state.jobs.map((job, index) => {\n const phase = aiJobPhase(job)\n const credits = aiJobNetCredits(job)\n const refund = aiJobRefundCopy(job)\n const brief =\n job.brief.length > BRIEF_PREVIEW_CHARS ? `${job.brief.slice(0, BRIEF_PREVIEW_CHARS)}…` : job.brief\n const created = new Date(job.createdAt)\n return (\n <ListItemButton\n key={job.id}\n component={AppLink}\n href={`${basePath ?? ''}/${encodeURIComponent(job.id)}`}\n divider={index < state.jobs.length - 1}\n sx={{ display: 'block', py: 1.5 }}\n >\n <Stack direction=\"row\" spacing={1} useFlexGap sx={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 0.5 }}>\n <Chip size=\"small\" variant=\"outlined\" label={aiJobKindLabel(job.kind)} />\n <Chip size=\"small\" color={PHASE_COLOR[phase]} label={AI_JOB_PHASE_LABELS[phase]} />\n <Box sx={{ flexGrow: 1 }} />\n <Typography variant=\"caption\" color=\"text.secondary\">\n {credits > 0 ? `${credits.toLocaleString('en-US')} credits · ` : ''}\n {Number.isNaN(created.getTime()) ? null : (\n <time dateTime={job.createdAt}>{WHEN.format(created)}</time>\n )}\n </Typography>\n </Stack>\n <Typography variant=\"body2\" sx={{ mt: 0.75, wordBreak: 'break-word' }}>\n {brief}\n </Typography>\n {/* What became of its credits, from the job's recorded give-back (AGL-3596). */}\n {refund ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\" sx={{ mt: 0.5 }}>\n {refund}\n </Typography>\n ) : null}\n </ListItemButton>\n )\n })}\n </List>\n </Card>\n )}\n {state.status === 'ready' && state.jobs.length >= AI_JOBS_PAGE_LIMIT ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`Showing the ${AI_JOBS_PAGE_LIMIT} most recent jobs.`}\n </Typography>\n ) : null}\n </Stack>\n </Container>\n )\n}\n\nexport default AiJobsListPage\n"],"names":["PLATFORM_BRAND_NAME","aiJobRefundCopy","AppLink","authorizedFetch","useUser","Alert","Box","Button","Card","Chip","CircularProgress","Container","List","ListItemButton","Stack","Typography","useCallback","useEffect","useRef","useState","AI_JOB_PHASE_LABELS","aiJobKindNoun","aiJobPhase","publishAiJob","useAiJobSite","AI_JOBS_PAGE_LIMIT","AI_JOBS_LIST_TIMEOUT_MS","BRIEF_PREVIEW_CHARS","PHASE_COLOR","queued","planning","building","attention","done","failed","canceled","WHEN","Intl","DateTimeFormat","dateStyle","timeStyle","aiJobNetCredits","job","Math","max","creditsSpent","refundedCredits","aiJobKindLabel","kind","noun","charAt","toUpperCase","slice","LOAD_ERROR","readSiteJobs","user","orgId","hostId","signal","response","encodeURIComponent","payload","json","catch","ok","status","message","String","error","jobs","AiJobsListPage","basePath","data","userRef","current","site","list","setList","attempt","setAttempt","uid","undefined","controller","AbortController","settled","timer","setTimeout","abort","then","next","clearTimeout","retry","count","siteName","name","state","maxWidth","sx","py","xs","sm","px","spacing","variant","color","component","alignItems","aria-label","severity","action","size","onClick","length","borderRadius","p","disablePadding","map","index","phase","credits","refund","brief","created","Date","createdAt","href","id","divider","display","direction","useFlexGap","flexWrap","rowGap","label","flexGrow","toLocaleString","Number","isNaN","getTime","time","dateTime","format","mt","wordBreak"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-jobs-list-page.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'use client'\n\nimport { PLATFORM_BRAND_NAME } from '@aglyn/aglyn'\nimport type { ConsolePluginPageProps } from '@aglyn/aglyn/plugin-manager/feature-plugins'\nimport { aiJobRefundCopy } from '../model/ai-job-failure-copy'\nimport { AppLink } from '@aglyn/shared-ui-jsx'\nimport { authorizedFetch, type MaybeTokenSource } from '@aglyn/shared-util-http/authorized-token'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n Box,\n Button,\n Card,\n Chip,\n CircularProgress,\n Container,\n List,\n ListItemButton,\n Stack,\n Typography,\n} from '@mui/material'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { AI_JOB_PHASE_LABELS, aiJobKindNoun, aiJobPhase, type AiJobPhase } from '../model/ai-job-activity'\nimport { AI_JOB_KINDS, type AiJobSummary } from '../model/ai-jobs.types'\nimport { publishAiJob } from './ai-jobs-store'\nimport { useAiJobSite } from './ai-job-site'\n\n/**\n * A site's AI jobs (AGL-3596), at `/ai-jobs` under the site: every job that\n * worked on this site, newest first, each linking to its own page.\n *\n * Read through the jobs route, never Firestore, so the membership, flag and\n * plan rungs that answer every other jobs read answer this one. The site is\n * a query on the route (`hostId`), not a filter of the workspace's list.\n *\n * Every wait ends: the site's read and the list's each settle on content,\n * the empty state, or a sentence with Try again.\n */\n\n/** The most jobs the page lists; the newest, which is what a person comes for. */\nexport const AI_JOBS_PAGE_LIMIT = 50\n\n/** How long the list may take before the page says it could not be loaded. */\nexport const AI_JOBS_LIST_TIMEOUT_MS = 20_000\n\n/** How much of a brief a row shows. */\nconst BRIEF_PREVIEW_CHARS = 120\n\n/** A row's chip, colored as the AI jobs drawer colors it. */\nconst PHASE_COLOR: Record<AiJobPhase, 'default' | 'primary' | 'success' | 'error' | 'warning'> = {\n queued: 'default',\n planning: 'primary',\n 'plan-ready': 'warning',\n building: 'primary',\n attention: 'warning',\n done: 'success',\n failed: 'error',\n canceled: 'default',\n}\n\nconst WHEN = new Intl.DateTimeFormat('en-US', { dateStyle: 'medium', timeStyle: 'short' })\n\n/** What a job cost the person: what it spent, less what we refunded. */\nexport function aiJobNetCredits(job: Pick<AiJobSummary, 'creditsSpent' | 'refundedCredits'>): number {\n return Math.max(0, (job.creditsSpent ?? 0) - (job.refundedCredits ?? 0))\n}\n\n/** The kind as a row names it: `Site`, `Page`, `AI job`. */\nexport function aiJobKindLabel(kind: AiJobSummary['kind']): string {\n const noun = aiJobKindNoun(kind)\n return noun === 'AI job' ? noun : noun.charAt(0).toUpperCase() + noun.slice(1)\n}\n\n/**\n * Every kind a row can name, in the kinds registry's order: the labels the\n * rows' chips read, so the empty state never falls behind a new kind.\n */\nexport function aiJobKindLabels(): string[] {\n const labels = AI_JOB_KINDS.map(aiJobKindLabel).filter((label) => label !== 'AI job')\n return [...new Set(labels)]\n}\n\n/** `A, B and C`. */\nfunction listOf(items: readonly string[]): string {\n return items.length < 2 ? items.join('') : `${items.slice(0, -1).join(', ')} and ${items[items.length - 1]}`\n}\n\ntype ListState =\n | { status: 'loading' }\n | { status: 'ready'; jobs: AiJobSummary[] }\n | { status: 'error'; message: string }\n\nconst LOAD_ERROR = 'This site’s AI jobs could not be loaded. Try again in a moment.'\n\nasync function readSiteJobs(\n user: MaybeTokenSource,\n orgId: string,\n hostId: string,\n signal: AbortSignal,\n): Promise<ListState> {\n try {\n const response = await authorizedFetch(\n user,\n `/api/ai/jobs?orgId=${encodeURIComponent(orgId)}&hostId=${encodeURIComponent(hostId)}&limit=${AI_JOBS_PAGE_LIMIT}`,\n { signal },\n )\n const payload = (await response.json().catch(() => null)) as { jobs?: AiJobSummary[]; error?: string } | null\n if (!response.ok) return { status: 'error', message: String(payload?.error ?? LOAD_ERROR) }\n const jobs = payload?.jobs ?? []\n // A job the top-bar indicator still counts that has settled since leaves it.\n for (const job of jobs) publishAiJob(job)\n return { status: 'ready', jobs }\n } catch {\n return { status: 'error', message: LOAD_ERROR }\n }\n}\n\nexport function AiJobsListPage({ hostId, basePath }: ConsolePluginPageProps) {\n const { data: user } = useUser()\n const userRef = useRef<MaybeTokenSource>(user)\n userRef.current = user\n const site = useAiJobSite(hostId)\n const orgId = site.status === 'ready' ? site.orgId : null\n const [list, setList] = useState<ListState>({ status: 'loading' })\n const [attempt, setAttempt] = useState(0)\n const uid = user?.uid ?? null\n\n useEffect(() => {\n if (!orgId || !hostId || !uid) return undefined\n const controller = new AbortController()\n let settled = false\n setList({ status: 'loading' })\n const timer = setTimeout(() => {\n if (settled) return\n settled = true\n controller.abort()\n setList({ status: 'error', message: LOAD_ERROR })\n }, AI_JOBS_LIST_TIMEOUT_MS)\n void readSiteJobs(userRef.current, orgId, hostId, controller.signal).then((next) => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n setList(next)\n })\n return () => {\n settled = true\n clearTimeout(timer)\n controller.abort()\n }\n }, [orgId, hostId, uid, attempt])\n\n const retry = useCallback(() => setAttempt((count) => count + 1), [])\n\n const siteName = site.status === 'ready' ? site.name : ''\n const state: ListState =\n site.status === 'error'\n ? { status: 'error', message: 'This site could not be read. Check your connection and reload the page.' }\n : list\n\n return (\n <Container maxWidth=\"md\" sx={{ py: { xs: 3, sm: 5 }, px: { xs: 2, sm: 3 } }}>\n <Stack spacing={3}>\n <Stack spacing={1}>\n {siteName ? (\n <Typography variant=\"overline\" color=\"text.secondary\">\n {siteName}\n </Typography>\n ) : null}\n <Typography variant=\"h4\" component=\"h1\">\n {'AI jobs'}\n </Typography>\n <Typography variant=\"body1\" color=\"text.secondary\">\n {`What ${PLATFORM_BRAND_NAME} AI has done and is doing on this site, newest first.`}\n </Typography>\n </Stack>\n {state.status === 'loading' ? (\n <Stack sx={{ alignItems: 'center', py: 4 }}>\n <CircularProgress aria-label=\"Loading AI jobs\" />\n </Stack>\n ) : state.status === 'error' ? (\n <Alert\n severity=\"warning\"\n action={\n site.status === 'error' ? undefined : (\n <Button color=\"inherit\" size=\"small\" onClick={retry}>\n {'Try again'}\n </Button>\n )\n }\n >\n {state.message}\n </Alert>\n ) : state.jobs.length === 0 ? (\n <Card variant=\"outlined\" sx={{ borderRadius: 2, p: { xs: 2, sm: 3 } }}>\n <Stack spacing={1}>\n <Typography variant=\"h6\" component=\"h2\">\n {'No AI jobs on this site yet'}\n </Typography>\n <Typography variant=\"body1\" color=\"text.secondary\">\n {`An AI job is ${PLATFORM_BRAND_NAME} AI making something for this site from a short ` +\n `description you write. Each job is one of these kinds: ${listOf(aiJobKindLabels())}. ` +\n 'Each one gets a page here that shows its progress and what it made.'}\n </Typography>\n <Typography variant=\"body1\" color=\"text.secondary\">\n {'To start one, choose Create with AI on any list that offers it, such as this site’s ' +\n 'Pages or Forms. A new site can also be built with AI when it is created.'}\n </Typography>\n </Stack>\n </Card>\n ) : (\n <Card variant=\"outlined\" sx={{ borderRadius: 2 }}>\n <List disablePadding aria-label=\"AI jobs\">\n {state.jobs.map((job, index) => {\n const phase = aiJobPhase(job)\n const credits = aiJobNetCredits(job)\n const refund = aiJobRefundCopy(job)\n const brief =\n job.brief.length > BRIEF_PREVIEW_CHARS ? `${job.brief.slice(0, BRIEF_PREVIEW_CHARS)}…` : job.brief\n const created = new Date(job.createdAt)\n return (\n <ListItemButton\n key={job.id}\n component={AppLink}\n href={`${basePath ?? ''}/${encodeURIComponent(job.id)}`}\n divider={index < state.jobs.length - 1}\n sx={{ display: 'block', py: 1.5 }}\n >\n <Stack direction=\"row\" spacing={1} useFlexGap sx={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 0.5 }}>\n <Chip size=\"small\" variant=\"outlined\" label={aiJobKindLabel(job.kind)} />\n <Chip size=\"small\" color={PHASE_COLOR[phase]} label={AI_JOB_PHASE_LABELS[phase]} />\n <Box sx={{ flexGrow: 1 }} />\n <Typography variant=\"caption\" color=\"text.secondary\">\n {credits > 0 ? `${credits.toLocaleString('en-US')} credits · ` : ''}\n {Number.isNaN(created.getTime()) ? null : (\n <time dateTime={job.createdAt}>{WHEN.format(created)}</time>\n )}\n </Typography>\n </Stack>\n <Typography variant=\"body2\" sx={{ mt: 0.75, wordBreak: 'break-word' }}>\n {brief}\n </Typography>\n {/* What became of its credits, from the job's recorded give-back (AGL-3596). */}\n {refund ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\" sx={{ mt: 0.5 }}>\n {refund}\n </Typography>\n ) : null}\n </ListItemButton>\n )\n })}\n </List>\n </Card>\n )}\n {state.status === 'ready' && state.jobs.length >= AI_JOBS_PAGE_LIMIT ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`Showing the ${AI_JOBS_PAGE_LIMIT} most recent jobs.`}\n </Typography>\n ) : null}\n </Stack>\n </Container>\n )\n}\n\nexport default AiJobsListPage\n"],"names":["PLATFORM_BRAND_NAME","aiJobRefundCopy","AppLink","authorizedFetch","useUser","Alert","Box","Button","Card","Chip","CircularProgress","Container","List","ListItemButton","Stack","Typography","useCallback","useEffect","useRef","useState","AI_JOB_PHASE_LABELS","aiJobKindNoun","aiJobPhase","AI_JOB_KINDS","publishAiJob","useAiJobSite","AI_JOBS_PAGE_LIMIT","AI_JOBS_LIST_TIMEOUT_MS","BRIEF_PREVIEW_CHARS","PHASE_COLOR","queued","planning","building","attention","done","failed","canceled","WHEN","Intl","DateTimeFormat","dateStyle","timeStyle","aiJobNetCredits","job","Math","max","creditsSpent","refundedCredits","aiJobKindLabel","kind","noun","charAt","toUpperCase","slice","aiJobKindLabels","labels","map","filter","label","Set","listOf","items","length","join","LOAD_ERROR","readSiteJobs","user","orgId","hostId","signal","response","encodeURIComponent","payload","json","catch","ok","status","message","String","error","jobs","AiJobsListPage","basePath","data","userRef","current","site","list","setList","attempt","setAttempt","uid","undefined","controller","AbortController","settled","timer","setTimeout","abort","then","next","clearTimeout","retry","count","siteName","name","state","maxWidth","sx","py","xs","sm","px","spacing","variant","color","component","alignItems","aria-label","severity","action","size","onClick","borderRadius","p","disablePadding","index","phase","credits","refund","brief","created","Date","createdAt","href","id","divider","display","direction","useFlexGap","flexWrap","rowGap","flexGrow","toLocaleString","Number","isNaN","getTime","time","dateTime","format","mt","wordBreak"],"mappings":"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"}
@@ -121,7 +121,9 @@ function nameOf(proposal) {
121
121
  }
122
122
  /** "Create with AI" in the Functions or the Variables card's header. */ export function AiLogicCreateButton({ hostId, orgId, kind, propose, entitled, upgrade }) {
123
123
  const copy = AI_LOGIC_COPY;
124
- const help = pluginDocsHelp('aiLogic');
124
+ const help = pluginDocsHelp('aiLogic', {
125
+ anchor: kind === 'variable' ? '#variable' : '#function'
126
+ });
125
127
  const { data: user } = useUser();
126
128
  const run = useAiJobRun(user, copy.failed);
127
129
  const { reset } = run;
@@ -211,7 +213,7 @@ function nameOf(proposal) {
211
213
  href: help.href,
212
214
  target: "_blank",
213
215
  rel: "noopener",
214
- title: help.excerpt,
216
+ title: help.excerptText,
215
217
  children: 'How it works'
216
218
  })
217
219
  ]
@@ -347,7 +349,7 @@ function nameOf(proposal) {
347
349
  href: help.href,
348
350
  target: "_blank",
349
351
  rel: "noopener",
350
- title: help.excerpt,
352
+ title: help.excerptText,
351
353
  children: 'How it works'
352
354
  })
353
355
  ]
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-logic.component.tsx"],"sourcesContent":["'use client'\n\n/**\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 { ConsoleWidgetEntitlementProps } from '@aglyn/aglyn/plugin-manager/feature-plugins'\nimport { pluginDocsHelp } from '@aglyn/aglyn/app-utils/docs-help'\nimport { mdiCreation } from '@aglyn/shared-data-mdi'\nimport { MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n Box,\n Button,\n CircularProgress,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n Link,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport { useEffect, useState } from 'react'\nimport { AI_LOGIC_RESOURCE, readAiLogicProposal, type AiLogicProposal } from '../model/ai-logic-job'\nimport type { AiJobSummary } from '../model/ai-jobs.types'\nimport { openAiJobs } from './ai-jobs-store'\nimport type {\n ConsoleHostLogicZoneProps,\n ConsoleLogicFunctionEditorZoneProps,\n ConsoleLogicReferenceIssueZoneProps,\n} from './ai-logic-zones'\nimport { aiJobProblem, useAiJobRun, type AiJobRun } from './use-ai-job-run'\nimport { AiUpsellButton } from './ai-upsell-dialog.component'\n\n/**\n * Logic by AI (AGL-3603), in the zones the logic plugin hosts on its\n * Functions & Variables page:\n *\n * - \"Create with AI\" in the Functions and the Variables card headers\n * (`hostLogic`): a description becomes a `logic` job whose proposal opens\n * in that card's editor, unsaved.\n * - \"Explain it\", \"Change with AI\" and \"Fix with AI\" in a saved function's\n * editor (`logicFunctionEditor`).\n * - \"Fix with AI\" on a broken reference an ACTION holds\n * (`logicReferenceIssue`): a changed copy of the action, drafted switched\n * off by the workflow job's `revise` mode.\n *\n * Nothing here saves: a proposal is put in the editor only when the person\n * asks, and the editor's Save is the write.\n */\n\nconst BRIEF_MAX_CHARS = 4_000\n\nexport const AI_LOGIC_COPY = {\n create: 'Create with AI',\n title: { function: 'Describe a function', variable: 'Describe a variable' },\n label: { function: 'What should it work out?', variable: 'What should it hold?' },\n placeholder: {\n function: 'A shipping quote: free over our free-shipping amount, otherwise the flat rate plus 2 per kilo',\n variable: 'Our plan prices: starter 19, pro 49, business 99',\n },\n next: {\n function:\n 'The function is written only from the expressions the editor runs and your site’s variables, checked, and run once. It opens in the editor for you to test and save.',\n variable: 'The variable opens in the editor for you to check and save.',\n },\n submit: { function: 'Write the function', variable: 'Write the variable' },\n running: 'Writing it. This usually takes under a minute.',\n ready: 'Ready',\n open: 'Open in the editor',\n notOpened: 'It could not be opened in the editor. Check the card for why, then try again.',\n failed: 'Nothing could be written from this description. Try again.',\n explain: 'Explain it',\n explaining: 'Reading the function.',\n again: 'Explain it again',\n explainFailed: 'The function could not be explained. Try again.',\n explainBrief: (name: string) => `Explain what ${name} works out, and anything in it worth checking.`,\n changeLabel: 'What should change?',\n changePlaceholder: 'Add a 10% discount when the order is over 200',\n change: 'Change with AI',\n fix: 'Fix with AI',\n fixBrief: (name: string) =>\n `Fix whatever in ${name} would stop it working — a name the site does not have, a condition that can never hold, a value it returns that nothing sets. Change nothing else.`,\n changeIntro:\n 'Describe a change, or let AI fix what would stop it working. The changed function replaces what this editor holds only when you open it, and is saved only when you save.',\n replace: 'Put it in the editor',\n referenceFix: 'Fix with AI',\n referenceTitle: 'Fix this reference',\n referenceRunning: 'Drafting a changed copy of the automation. This can take a few minutes.',\n referenceDone:\n 'A changed copy is drafted, switched off, beside the automation. Review it on the Automation page, then switch it on in place of the old one.',\n referenceFailed: 'The automation could not be changed. Try again.',\n referenceBrief: (issue: { refType: string; missing: string }) =>\n `A step names the ${issue.refType} “${issue.missing}”, which the site no longer has. Point that step at the site’s ${issue.refType} the name means, or leave it for me to pick. Change nothing else.`,\n} as const\n\n/** The proposal a finished logic job wrote, or `null`. */\nfunction proposalOf(job: AiJobSummary | null): { proposal: AiLogicProposal; note: string | null } | null {\n if (job?.status !== 'done') return null\n const output = job.outputs.find((one) => one.resource === AI_LOGIC_RESOURCE)\n const proposal = readAiLogicProposal(output?.proposal)\n return proposal ? { proposal, note: output?.note ?? null } : null\n}\n\nfunction nameOf(proposal: AiLogicProposal): string {\n return proposal.kind === 'function' ? proposal.definition.name : proposal.variable.name\n}\n\n/** Progress and what went wrong, shared by every control here. */\nfunction RunState({ run, running, failed, done }: { run: AiJobRun; running: string; failed: string; done: boolean }) {\n const problem = aiJobProblem(run.job, failed) ?? (run.job?.status === 'done' && !done ? failed : null)\n return (\n <>\n {run.running && run.job ? (\n <Alert\n severity=\"info\"\n icon={<CircularProgress size={18} aria-label=\"Working\" />}\n action={\n <Button color=\"inherit\" size=\"small\" variant=\"outlined\" onClick={() => run.job && openAiJobs({ jobId: run.job.id })}>\n {'Open AI jobs'}\n </Button>\n }\n >\n {running}\n </Alert>\n ) : null}\n {problem ? <Alert severity={run.job?.status === 'failed' ? 'error' : 'warning'}>{problem}</Alert> : null}\n {run.notice ? <Alert severity=\"warning\">{run.notice}</Alert> : null}\n </>\n )\n}\n\n/** \"Create with AI\" in the Functions or the Variables card's header. */\nexport function AiLogicCreateButton({\n hostId,\n orgId,\n kind,\n propose,\n entitled,\n upgrade,\n}: ConsoleHostLogicZoneProps & ConsoleWidgetEntitlementProps) {\n const copy = AI_LOGIC_COPY\n const help = pluginDocsHelp('aiLogic')\n const { data: user } = useUser()\n const run = useAiJobRun(user, copy.failed)\n const { reset } = run\n const [open, setOpen] = useState(false)\n const [brief, setBrief] = useState('')\n const [notOpened, setNotOpened] = useState(false)\n\n useEffect(() => {\n reset()\n setNotOpened(false)\n }, [open, reset])\n\n // Drawn from the shell's gates alone (AGL-3601); a plan without the add-on\n // gets the add-on's dialog, and nothing asks a server until it is used.\n if (entitled === false) return upgrade ? <AiUpsellButton kind=\"logic\" upgrade={upgrade} /> : null\n const ready = proposalOf(run.job)\n const asking = !run.job || Boolean(run.notice)\n const close = () => setOpen(false)\n\n const start = async () => {\n const trimmed = brief.trim()\n if (!orgId || !trimmed) return\n if (await run.start({ orgId, hostId, kind: 'logic', brief: trimmed, inputs: { mode: kind } })) setBrief('')\n }\n const apply = () => {\n if (!ready) return\n if (propose(ready.proposal)) close()\n else setNotOpened(true)\n }\n\n return (\n <>\n <Button size=\"small\" variant=\"outlined\" startIcon={<MdiIcon path={mdiCreation.path} />} onClick={() => setOpen(true)}>\n {copy.create}\n </Button>\n <Dialog open={open} onClose={run.starting ? undefined : close} fullWidth maxWidth=\"sm\">\n <DialogTitle>{copy.title[kind]}</DialogTitle>\n <DialogContent>\n <Stack spacing={2} sx={{ pt: 1 }}>\n {asking ? (\n <>\n <TextField\n label={copy.label[kind]}\n placeholder={copy.placeholder[kind]}\n multiline\n minRows={3}\n value={brief}\n onChange={(event) => setBrief(event.target.value.slice(0, BRIEF_MAX_CHARS))}\n disabled={run.starting}\n autoFocus\n />\n <Typography variant=\"body2\" color=\"text.secondary\">\n {copy.next[kind]}{' '}\n <Link href={help.href} target=\"_blank\" rel=\"noopener\" title={help.excerpt}>\n {'How it works'}\n </Link>\n </Typography>\n </>\n ) : null}\n {ready ? (\n <Alert severity=\"success\">\n <Typography variant=\"body2\" sx={{ fontWeight: 600 }}>{`${copy.ready}: ${nameOf(ready.proposal)}`}</Typography>\n {ready.note ? <Typography variant=\"body2\">{ready.note}</Typography> : null}\n </Alert>\n ) : null}\n <RunState run={run} running={copy.running} failed={copy.failed} done={Boolean(ready)} />\n {notOpened ? <Alert severity=\"warning\">{copy.notOpened}</Alert> : null}\n </Stack>\n </DialogContent>\n <DialogActions>\n <Button onClick={close} disabled={run.starting}>\n {asking ? 'Cancel' : 'Close'}\n </Button>\n {asking ? (\n <Button variant=\"contained\" onClick={() => void start()} disabled={run.starting || !orgId || !brief.trim()}>\n {copy.submit[kind]}\n </Button>\n ) : ready ? (\n <Button variant=\"contained\" onClick={apply}>\n {copy.open}\n </Button>\n ) : null}\n </DialogActions>\n </Dialog>\n </>\n )\n}\n\n/** \"Explain it\", \"Change with AI\" and \"Fix with AI\" in a saved function's editor. */\nexport function AiLogicFunctionTools({ hostId, orgId, target, propose }: ConsoleLogicFunctionEditorZoneProps) {\n const copy = AI_LOGIC_COPY\n const help = pluginDocsHelp('aiLogic', { anchor: '#change' })\n const { data: user } = useUser()\n const explain = useAiJobRun(user, copy.explainFailed)\n const change = useAiJobRun(user, copy.failed)\n const [brief, setBrief] = useState('')\n const [notOpened, setNotOpened] = useState(false)\n\n const explanation =\n explain.job?.status === 'done' ? explain.job.outputs.find((one) => one.resource === 'text')?.text ?? null : null\n const ready = proposalOf(change.job)\n const busy = change.starting || change.running\n\n const ask = () => {\n if (!orgId) return\n void explain.start({\n orgId,\n hostId,\n kind: 'logic',\n brief: copy.explainBrief(target.name),\n inputs: { mode: 'explain', functionId: target.id },\n })\n }\n const revise = async (text: string) => {\n const trimmed = text.trim()\n if (!orgId || !trimmed) return\n setNotOpened(false)\n if (\n await change.start({ orgId, hostId, kind: 'logic', brief: trimmed, inputs: { mode: 'function', functionId: target.id } })\n ) {\n setBrief('')\n }\n }\n\n return (\n <Box sx={{ border: 1, borderColor: 'divider', borderRadius: 1, p: 1.5 }} aria-label=\"This function with AI\">\n <Stack spacing={1}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography variant=\"body2\" color=\"text.secondary\" sx={{ flexGrow: 1 }}>\n {copy.changeIntro}{' '}\n <Link href={help.href} target=\"_blank\" rel=\"noopener\" title={help.excerpt}>\n {'How it works'}\n </Link>\n </Typography>\n <Button size=\"small\" variant=\"outlined\" disabled={explain.starting || explain.running || !orgId} onClick={ask}>\n {explanation ? copy.again : copy.explain}\n </Button>\n </Stack>\n {explanation ? (\n <Typography variant=\"body2\" component=\"div\" sx={{ whiteSpace: 'pre-line', wordBreak: 'break-word' }}>\n {explanation}\n </Typography>\n ) : null}\n <RunState run={explain} running={copy.explaining} failed={copy.explainFailed} done={Boolean(explanation)} />\n <TextField\n size=\"small\"\n label={copy.changeLabel}\n placeholder={copy.changePlaceholder}\n value={brief}\n multiline\n maxRows={4}\n onChange={(event) => setBrief(event.target.value.slice(0, BRIEF_MAX_CHARS))}\n disabled={busy}\n />\n <Stack direction=\"row\" spacing={1}>\n <Button\n size=\"small\"\n variant=\"outlined\"\n startIcon={<MdiIcon path={mdiCreation.path} />}\n disabled={busy || !orgId || !brief.trim()}\n onClick={() => void revise(brief)}\n >\n {copy.change}\n </Button>\n <Button\n size=\"small\"\n variant=\"text\"\n startIcon={<MdiIcon path={mdiCreation.path} />}\n disabled={busy || !orgId}\n onClick={() => void revise(copy.fixBrief(target.name))}\n >\n {copy.fix}\n </Button>\n </Stack>\n {ready ? (\n <Alert\n severity=\"success\"\n action={\n <Button\n color=\"inherit\"\n size=\"small\"\n variant=\"outlined\"\n onClick={() => {\n if (!propose(ready.proposal)) setNotOpened(true)\n }}\n >\n {copy.replace}\n </Button>\n }\n >\n <Typography variant=\"body2\" sx={{ fontWeight: 600 }}>{`${copy.ready}: ${nameOf(ready.proposal)}`}</Typography>\n {ready.note ? <Typography variant=\"body2\">{ready.note}</Typography> : null}\n </Alert>\n ) : null}\n <RunState run={change} running={copy.running} failed={copy.failed} done={Boolean(ready)} />\n {notOpened ? <Alert severity=\"warning\">{copy.notOpened}</Alert> : null}\n </Stack>\n </Box>\n )\n}\n\n/**\n * \"Fix with AI\" on a broken reference an automation holds: a changed copy of\n * the action, drafted switched off by the workflow job's `revise` mode. A\n * workflow's, a variable's and a page's references are not offered.\n */\nexport function AiLogicFixReference({ hostId, orgId, issue }: ConsoleLogicReferenceIssueZoneProps) {\n const copy = AI_LOGIC_COPY\n const { data: user } = useUser()\n const run = useAiJobRun(user, copy.referenceFailed)\n const [open, setOpen] = useState(false)\n\n if (issue.source !== 'action') return null\n const drafted = run.job?.status === 'done' ? run.job.outputs.find((one) => one.resource === 'workflow') : undefined\n\n const ask = () => {\n setOpen(true)\n if (run.job || !orgId) return\n void run.start({\n orgId,\n hostId,\n kind: 'workflow',\n brief: copy.referenceBrief(issue),\n inputs: { mode: 'revise', targetType: 'action', targetId: issue.sourceId },\n })\n }\n const close = () => {\n setOpen(false)\n if (run.notice) run.reset()\n }\n\n return (\n <>\n <Button size=\"small\" variant=\"text\" sx={{ px: 0.5, minWidth: 0 }} startIcon={<MdiIcon path={mdiCreation.path} />} onClick={ask}>\n {copy.referenceFix}\n </Button>\n <Dialog open={open} onClose={close} fullWidth maxWidth=\"sm\">\n <DialogTitle>{copy.referenceTitle}</DialogTitle>\n <DialogContent>\n <Stack spacing={1.5} sx={{ pt: 1 }}>\n {drafted ? (\n <Alert severity=\"success\">\n <Typography variant=\"body2\" sx={{ fontWeight: 600 }}>{drafted.label}</Typography>\n <Typography variant=\"body2\">{drafted.note || copy.referenceDone}</Typography>\n </Alert>\n ) : null}\n <RunState run={run} running={copy.referenceRunning} failed={copy.referenceFailed} done={Boolean(drafted)} />\n </Stack>\n </DialogContent>\n <DialogActions>\n <Button onClick={close}>{'Close'}</Button>\n </DialogActions>\n </Dialog>\n </>\n )\n}\n"],"names":["pluginDocsHelp","mdiCreation","MdiIcon","useUser","Alert","Box","Button","CircularProgress","Dialog","DialogActions","DialogContent","DialogTitle","Link","Stack","TextField","Typography","useEffect","useState","AI_LOGIC_RESOURCE","readAiLogicProposal","openAiJobs","aiJobProblem","useAiJobRun","AiUpsellButton","BRIEF_MAX_CHARS","AI_LOGIC_COPY","create","title","function","variable","label","placeholder","next","submit","running","ready","open","notOpened","failed","explain","explaining","again","explainFailed","explainBrief","name","changeLabel","changePlaceholder","change","fix","fixBrief","changeIntro","replace","referenceFix","referenceTitle","referenceRunning","referenceDone","referenceFailed","referenceBrief","issue","refType","missing","proposalOf","job","status","output","outputs","find","one","resource","proposal","note","nameOf","kind","definition","RunState","run","done","problem","severity","icon","size","aria-label","action","color","variant","onClick","jobId","id","notice","AiLogicCreateButton","hostId","orgId","propose","entitled","upgrade","copy","help","data","user","reset","setOpen","brief","setBrief","setNotOpened","asking","Boolean","close","start","trimmed","trim","inputs","mode","apply","startIcon","path","onClose","starting","undefined","fullWidth","maxWidth","spacing","sx","pt","multiline","minRows","value","onChange","event","target","slice","disabled","autoFocus","href","rel","excerpt","fontWeight","AiLogicFunctionTools","anchor","explanation","text","busy","ask","functionId","revise","border","borderColor","borderRadius","p","direction","alignItems","flexGrow","component","whiteSpace","wordBreak","maxRows","AiLogicFixReference","source","drafted","targetType","targetId","sourceId","px","minWidth"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-logic.component.tsx"],"sourcesContent":["'use client'\n\n/**\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 { ConsoleWidgetEntitlementProps } from '@aglyn/aglyn/plugin-manager/feature-plugins'\nimport { pluginDocsHelp } from '@aglyn/aglyn/app-utils/docs-help'\nimport { mdiCreation } from '@aglyn/shared-data-mdi'\nimport { MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n Box,\n Button,\n CircularProgress,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n Link,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport { useEffect, useState } from 'react'\nimport { AI_LOGIC_RESOURCE, readAiLogicProposal, type AiLogicProposal } from '../model/ai-logic-job'\nimport type { AiJobSummary } from '../model/ai-jobs.types'\nimport { openAiJobs } from './ai-jobs-store'\nimport type {\n ConsoleHostLogicZoneProps,\n ConsoleLogicFunctionEditorZoneProps,\n ConsoleLogicReferenceIssueZoneProps,\n} from './ai-logic-zones'\nimport { aiJobProblem, useAiJobRun, type AiJobRun } from './use-ai-job-run'\nimport { AiUpsellButton } from './ai-upsell-dialog.component'\n\n/**\n * Logic by AI (AGL-3603), in the zones the logic plugin hosts on its\n * Functions & Variables page:\n *\n * - \"Create with AI\" in the Functions and the Variables card headers\n * (`hostLogic`): a description becomes a `logic` job whose proposal opens\n * in that card's editor, unsaved.\n * - \"Explain it\", \"Change with AI\" and \"Fix with AI\" in a saved function's\n * editor (`logicFunctionEditor`).\n * - \"Fix with AI\" on a broken reference an ACTION holds\n * (`logicReferenceIssue`): a changed copy of the action, drafted switched\n * off by the workflow job's `revise` mode.\n *\n * Nothing here saves: a proposal is put in the editor only when the person\n * asks, and the editor's Save is the write.\n */\n\nconst BRIEF_MAX_CHARS = 4_000\n\nexport const AI_LOGIC_COPY = {\n create: 'Create with AI',\n title: { function: 'Describe a function', variable: 'Describe a variable' },\n label: { function: 'What should it work out?', variable: 'What should it hold?' },\n placeholder: {\n function: 'A shipping quote: free over our free-shipping amount, otherwise the flat rate plus 2 per kilo',\n variable: 'Our plan prices: starter 19, pro 49, business 99',\n },\n next: {\n function:\n 'The function is written only from the expressions the editor runs and your site’s variables, checked, and run once. It opens in the editor for you to test and save.',\n variable: 'The variable opens in the editor for you to check and save.',\n },\n submit: { function: 'Write the function', variable: 'Write the variable' },\n running: 'Writing it. This usually takes under a minute.',\n ready: 'Ready',\n open: 'Open in the editor',\n notOpened: 'It could not be opened in the editor. Check the card for why, then try again.',\n failed: 'Nothing could be written from this description. Try again.',\n explain: 'Explain it',\n explaining: 'Reading the function.',\n again: 'Explain it again',\n explainFailed: 'The function could not be explained. Try again.',\n explainBrief: (name: string) => `Explain what ${name} works out, and anything in it worth checking.`,\n changeLabel: 'What should change?',\n changePlaceholder: 'Add a 10% discount when the order is over 200',\n change: 'Change with AI',\n fix: 'Fix with AI',\n fixBrief: (name: string) =>\n `Fix whatever in ${name} would stop it working — a name the site does not have, a condition that can never hold, a value it returns that nothing sets. Change nothing else.`,\n changeIntro:\n 'Describe a change, or let AI fix what would stop it working. The changed function replaces what this editor holds only when you open it, and is saved only when you save.',\n replace: 'Put it in the editor',\n referenceFix: 'Fix with AI',\n referenceTitle: 'Fix this reference',\n referenceRunning: 'Drafting a changed copy of the automation. This can take a few minutes.',\n referenceDone:\n 'A changed copy is drafted, switched off, beside the automation. Review it on the Automation page, then switch it on in place of the old one.',\n referenceFailed: 'The automation could not be changed. Try again.',\n referenceBrief: (issue: { refType: string; missing: string }) =>\n `A step names the ${issue.refType} “${issue.missing}”, which the site no longer has. Point that step at the site’s ${issue.refType} the name means, or leave it for me to pick. Change nothing else.`,\n} as const\n\n/** The proposal a finished logic job wrote, or `null`. */\nfunction proposalOf(job: AiJobSummary | null): { proposal: AiLogicProposal; note: string | null } | null {\n if (job?.status !== 'done') return null\n const output = job.outputs.find((one) => one.resource === AI_LOGIC_RESOURCE)\n const proposal = readAiLogicProposal(output?.proposal)\n return proposal ? { proposal, note: output?.note ?? null } : null\n}\n\nfunction nameOf(proposal: AiLogicProposal): string {\n return proposal.kind === 'function' ? proposal.definition.name : proposal.variable.name\n}\n\n/** Progress and what went wrong, shared by every control here. */\nfunction RunState({ run, running, failed, done }: { run: AiJobRun; running: string; failed: string; done: boolean }) {\n const problem = aiJobProblem(run.job, failed) ?? (run.job?.status === 'done' && !done ? failed : null)\n return (\n <>\n {run.running && run.job ? (\n <Alert\n severity=\"info\"\n icon={<CircularProgress size={18} aria-label=\"Working\" />}\n action={\n <Button color=\"inherit\" size=\"small\" variant=\"outlined\" onClick={() => run.job && openAiJobs({ jobId: run.job.id })}>\n {'Open AI jobs'}\n </Button>\n }\n >\n {running}\n </Alert>\n ) : null}\n {problem ? <Alert severity={run.job?.status === 'failed' ? 'error' : 'warning'}>{problem}</Alert> : null}\n {run.notice ? <Alert severity=\"warning\">{run.notice}</Alert> : null}\n </>\n )\n}\n\n/** \"Create with AI\" in the Functions or the Variables card's header. */\nexport function AiLogicCreateButton({\n hostId,\n orgId,\n kind,\n propose,\n entitled,\n upgrade,\n}: ConsoleHostLogicZoneProps & ConsoleWidgetEntitlementProps) {\n const copy = AI_LOGIC_COPY\n const help = pluginDocsHelp('aiLogic', {\n anchor: kind === 'variable' ? '#variable' : '#function',\n })\n const { data: user } = useUser()\n const run = useAiJobRun(user, copy.failed)\n const { reset } = run\n const [open, setOpen] = useState(false)\n const [brief, setBrief] = useState('')\n const [notOpened, setNotOpened] = useState(false)\n\n useEffect(() => {\n reset()\n setNotOpened(false)\n }, [open, reset])\n\n // Drawn from the shell's gates alone (AGL-3601); a plan without the add-on\n // gets the add-on's dialog, and nothing asks a server until it is used.\n if (entitled === false) return upgrade ? <AiUpsellButton kind=\"logic\" upgrade={upgrade} /> : null\n const ready = proposalOf(run.job)\n const asking = !run.job || Boolean(run.notice)\n const close = () => setOpen(false)\n\n const start = async () => {\n const trimmed = brief.trim()\n if (!orgId || !trimmed) return\n if (await run.start({ orgId, hostId, kind: 'logic', brief: trimmed, inputs: { mode: kind } })) setBrief('')\n }\n const apply = () => {\n if (!ready) return\n if (propose(ready.proposal)) close()\n else setNotOpened(true)\n }\n\n return (\n <>\n <Button size=\"small\" variant=\"outlined\" startIcon={<MdiIcon path={mdiCreation.path} />} onClick={() => setOpen(true)}>\n {copy.create}\n </Button>\n <Dialog open={open} onClose={run.starting ? undefined : close} fullWidth maxWidth=\"sm\">\n <DialogTitle>{copy.title[kind]}</DialogTitle>\n <DialogContent>\n <Stack spacing={2} sx={{ pt: 1 }}>\n {asking ? (\n <>\n <TextField\n label={copy.label[kind]}\n placeholder={copy.placeholder[kind]}\n multiline\n minRows={3}\n value={brief}\n onChange={(event) => setBrief(event.target.value.slice(0, BRIEF_MAX_CHARS))}\n disabled={run.starting}\n autoFocus\n />\n <Typography variant=\"body2\" color=\"text.secondary\">\n {copy.next[kind]}{' '}\n <Link href={help.href} target=\"_blank\" rel=\"noopener\" title={help.excerptText}>\n {'How it works'}\n </Link>\n </Typography>\n </>\n ) : null}\n {ready ? (\n <Alert severity=\"success\">\n <Typography variant=\"body2\" sx={{ fontWeight: 600 }}>{`${copy.ready}: ${nameOf(ready.proposal)}`}</Typography>\n {ready.note ? <Typography variant=\"body2\">{ready.note}</Typography> : null}\n </Alert>\n ) : null}\n <RunState run={run} running={copy.running} failed={copy.failed} done={Boolean(ready)} />\n {notOpened ? <Alert severity=\"warning\">{copy.notOpened}</Alert> : null}\n </Stack>\n </DialogContent>\n <DialogActions>\n <Button onClick={close} disabled={run.starting}>\n {asking ? 'Cancel' : 'Close'}\n </Button>\n {asking ? (\n <Button variant=\"contained\" onClick={() => void start()} disabled={run.starting || !orgId || !brief.trim()}>\n {copy.submit[kind]}\n </Button>\n ) : ready ? (\n <Button variant=\"contained\" onClick={apply}>\n {copy.open}\n </Button>\n ) : null}\n </DialogActions>\n </Dialog>\n </>\n )\n}\n\n/** \"Explain it\", \"Change with AI\" and \"Fix with AI\" in a saved function's editor. */\nexport function AiLogicFunctionTools({ hostId, orgId, target, propose }: ConsoleLogicFunctionEditorZoneProps) {\n const copy = AI_LOGIC_COPY\n const help = pluginDocsHelp('aiLogic', { anchor: '#change' })\n const { data: user } = useUser()\n const explain = useAiJobRun(user, copy.explainFailed)\n const change = useAiJobRun(user, copy.failed)\n const [brief, setBrief] = useState('')\n const [notOpened, setNotOpened] = useState(false)\n\n const explanation =\n explain.job?.status === 'done' ? explain.job.outputs.find((one) => one.resource === 'text')?.text ?? null : null\n const ready = proposalOf(change.job)\n const busy = change.starting || change.running\n\n const ask = () => {\n if (!orgId) return\n void explain.start({\n orgId,\n hostId,\n kind: 'logic',\n brief: copy.explainBrief(target.name),\n inputs: { mode: 'explain', functionId: target.id },\n })\n }\n const revise = async (text: string) => {\n const trimmed = text.trim()\n if (!orgId || !trimmed) return\n setNotOpened(false)\n if (\n await change.start({ orgId, hostId, kind: 'logic', brief: trimmed, inputs: { mode: 'function', functionId: target.id } })\n ) {\n setBrief('')\n }\n }\n\n return (\n <Box sx={{ border: 1, borderColor: 'divider', borderRadius: 1, p: 1.5 }} aria-label=\"This function with AI\">\n <Stack spacing={1}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography variant=\"body2\" color=\"text.secondary\" sx={{ flexGrow: 1 }}>\n {copy.changeIntro}{' '}\n <Link href={help.href} target=\"_blank\" rel=\"noopener\" title={help.excerptText}>\n {'How it works'}\n </Link>\n </Typography>\n <Button size=\"small\" variant=\"outlined\" disabled={explain.starting || explain.running || !orgId} onClick={ask}>\n {explanation ? copy.again : copy.explain}\n </Button>\n </Stack>\n {explanation ? (\n <Typography variant=\"body2\" component=\"div\" sx={{ whiteSpace: 'pre-line', wordBreak: 'break-word' }}>\n {explanation}\n </Typography>\n ) : null}\n <RunState run={explain} running={copy.explaining} failed={copy.explainFailed} done={Boolean(explanation)} />\n <TextField\n size=\"small\"\n label={copy.changeLabel}\n placeholder={copy.changePlaceholder}\n value={brief}\n multiline\n maxRows={4}\n onChange={(event) => setBrief(event.target.value.slice(0, BRIEF_MAX_CHARS))}\n disabled={busy}\n />\n <Stack direction=\"row\" spacing={1}>\n <Button\n size=\"small\"\n variant=\"outlined\"\n startIcon={<MdiIcon path={mdiCreation.path} />}\n disabled={busy || !orgId || !brief.trim()}\n onClick={() => void revise(brief)}\n >\n {copy.change}\n </Button>\n <Button\n size=\"small\"\n variant=\"text\"\n startIcon={<MdiIcon path={mdiCreation.path} />}\n disabled={busy || !orgId}\n onClick={() => void revise(copy.fixBrief(target.name))}\n >\n {copy.fix}\n </Button>\n </Stack>\n {ready ? (\n <Alert\n severity=\"success\"\n action={\n <Button\n color=\"inherit\"\n size=\"small\"\n variant=\"outlined\"\n onClick={() => {\n if (!propose(ready.proposal)) setNotOpened(true)\n }}\n >\n {copy.replace}\n </Button>\n }\n >\n <Typography variant=\"body2\" sx={{ fontWeight: 600 }}>{`${copy.ready}: ${nameOf(ready.proposal)}`}</Typography>\n {ready.note ? <Typography variant=\"body2\">{ready.note}</Typography> : null}\n </Alert>\n ) : null}\n <RunState run={change} running={copy.running} failed={copy.failed} done={Boolean(ready)} />\n {notOpened ? <Alert severity=\"warning\">{copy.notOpened}</Alert> : null}\n </Stack>\n </Box>\n )\n}\n\n/**\n * \"Fix with AI\" on a broken reference an automation holds: a changed copy of\n * the action, drafted switched off by the workflow job's `revise` mode. A\n * workflow's, a variable's and a page's references are not offered.\n */\nexport function AiLogicFixReference({ hostId, orgId, issue }: ConsoleLogicReferenceIssueZoneProps) {\n const copy = AI_LOGIC_COPY\n const { data: user } = useUser()\n const run = useAiJobRun(user, copy.referenceFailed)\n const [open, setOpen] = useState(false)\n\n if (issue.source !== 'action') return null\n const drafted = run.job?.status === 'done' ? run.job.outputs.find((one) => one.resource === 'workflow') : undefined\n\n const ask = () => {\n setOpen(true)\n if (run.job || !orgId) return\n void run.start({\n orgId,\n hostId,\n kind: 'workflow',\n brief: copy.referenceBrief(issue),\n inputs: { mode: 'revise', targetType: 'action', targetId: issue.sourceId },\n })\n }\n const close = () => {\n setOpen(false)\n if (run.notice) run.reset()\n }\n\n return (\n <>\n <Button size=\"small\" variant=\"text\" sx={{ px: 0.5, minWidth: 0 }} startIcon={<MdiIcon path={mdiCreation.path} />} onClick={ask}>\n {copy.referenceFix}\n </Button>\n <Dialog open={open} onClose={close} fullWidth maxWidth=\"sm\">\n <DialogTitle>{copy.referenceTitle}</DialogTitle>\n <DialogContent>\n <Stack spacing={1.5} sx={{ pt: 1 }}>\n {drafted ? (\n <Alert severity=\"success\">\n <Typography variant=\"body2\" sx={{ fontWeight: 600 }}>{drafted.label}</Typography>\n <Typography variant=\"body2\">{drafted.note || copy.referenceDone}</Typography>\n </Alert>\n ) : null}\n <RunState run={run} running={copy.referenceRunning} failed={copy.referenceFailed} done={Boolean(drafted)} />\n </Stack>\n </DialogContent>\n <DialogActions>\n <Button onClick={close}>{'Close'}</Button>\n </DialogActions>\n </Dialog>\n </>\n )\n}\n"],"names":["pluginDocsHelp","mdiCreation","MdiIcon","useUser","Alert","Box","Button","CircularProgress","Dialog","DialogActions","DialogContent","DialogTitle","Link","Stack","TextField","Typography","useEffect","useState","AI_LOGIC_RESOURCE","readAiLogicProposal","openAiJobs","aiJobProblem","useAiJobRun","AiUpsellButton","BRIEF_MAX_CHARS","AI_LOGIC_COPY","create","title","function","variable","label","placeholder","next","submit","running","ready","open","notOpened","failed","explain","explaining","again","explainFailed","explainBrief","name","changeLabel","changePlaceholder","change","fix","fixBrief","changeIntro","replace","referenceFix","referenceTitle","referenceRunning","referenceDone","referenceFailed","referenceBrief","issue","refType","missing","proposalOf","job","status","output","outputs","find","one","resource","proposal","note","nameOf","kind","definition","RunState","run","done","problem","severity","icon","size","aria-label","action","color","variant","onClick","jobId","id","notice","AiLogicCreateButton","hostId","orgId","propose","entitled","upgrade","copy","help","anchor","data","user","reset","setOpen","brief","setBrief","setNotOpened","asking","Boolean","close","start","trimmed","trim","inputs","mode","apply","startIcon","path","onClose","starting","undefined","fullWidth","maxWidth","spacing","sx","pt","multiline","minRows","value","onChange","event","target","slice","disabled","autoFocus","href","rel","excerptText","fontWeight","AiLogicFunctionTools","explanation","text","busy","ask","functionId","revise","border","borderColor","borderRadius","p","direction","alignItems","flexGrow","component","whiteSpace","wordBreak","maxRows","AiLogicFixReference","source","drafted","targetType","targetId","sourceId","px","minWidth"],"mappings":"AAAA;;AAoBA,SAASA,cAAc,QAAQ,mCAAkC;AACjE,SAASC,WAAW,QAAQ,yBAAwB;AACpD,SAASC,OAAO,QAAQ,uBAAsB;AAC9C,SAASC,OAAO,QAAQ,iCAAgC;AACxD,SACEC,KAAK,EACLC,GAAG,EACHC,MAAM,EACNC,gBAAgB,EAChBC,MAAM,EACNC,aAAa,EACbC,aAAa,EACbC,WAAW,EACXC,IAAI,EACJC,KAAK,EACLC,SAAS,EACTC,UAAU,QACL,gBAAe;AACtB,SAASC,SAAS,EAAEC,QAAQ,QAAQ,QAAO;AAC3C,SAASC,iBAAiB,EAAEC,mBAAmB,QAA8B,2BAAuB;AAEpG,SAASC,UAAU,QAAQ,qBAAiB;AAM5C,SAASC,YAAY,EAAEC,WAAW,QAAuB,sBAAkB;AAC3E,SAASC,cAAc,QAAQ,kCAA8B;AAE7D;;;;;;;;;;;;;;;CAeC,GAED,MAAMC,kBAAkB;AAExB,OAAO,MAAMC,gBAAgB;IAC3BC,QAAQ;IACRC,OAAO;QAAEC,UAAU;QAAuBC,UAAU;IAAsB;IAC1EC,OAAO;QAAEF,UAAU;QAA4BC,UAAU;IAAuB;IAChFE,aAAa;QACXH,UAAU;QACVC,UAAU;IACZ;IACAG,MAAM;QACJJ,UACE;QACFC,UAAU;IACZ;IACAI,QAAQ;QAAEL,UAAU;QAAsBC,UAAU;IAAqB;IACzEK,SAAS;IACTC,OAAO;IACPC,MAAM;IACNC,WAAW;IACXC,QAAQ;IACRC,SAAS;IACTC,YAAY;IACZC,OAAO;IACPC,eAAe;IACfC,cAAc,CAACC,OAAiB,CAAC,aAAa,EAAEA,KAAK,8CAA8C,CAAC;IACpGC,aAAa;IACbC,mBAAmB;IACnBC,QAAQ;IACRC,KAAK;IACLC,UAAU,CAACL,OACT,CAAC,gBAAgB,EAAEA,KAAK,mJAAmJ,CAAC;IAC9KM,aACE;IACFC,SAAS;IACTC,cAAc;IACdC,gBAAgB;IAChBC,kBAAkB;IAClBC,eACE;IACFC,iBAAiB;IACjBC,gBAAgB,CAACC,QACf,CAAC,iBAAiB,EAAEA,MAAMC,OAAO,CAAC,EAAE,EAAED,MAAME,OAAO,CAAC,+DAA+D,EAAEF,MAAMC,OAAO,CAAC,iEAAiE,CAAC;AACzM,EAAU;AAEV,wDAAwD,GACxD,SAASE,WAAWC,GAAwB;;IAC1C,IAAIA,CAAAA,uBAAAA,IAAKC,MAAM,MAAK,QAAQ,OAAO;IACnC,MAAMC,SAASF,IAAIG,OAAO,CAACC,IAAI,CAAC,CAACC,MAAQA,IAAIC,QAAQ,KAAKlD;IAC1D,MAAMmD,WAAWlD,oBAAoB6C,0BAAAA,OAAQK,QAAQ;IACrD,OAAOA,WAAW;QAAEA;QAAUC,IAAI,UAAEN,0BAAAA,OAAQM,IAAI,mBAAI;IAAK,IAAI;AAC/D;AAEA,SAASC,OAAOF,QAAyB;IACvC,OAAOA,SAASG,IAAI,KAAK,aAAaH,SAASI,UAAU,CAAC7B,IAAI,GAAGyB,SAASxC,QAAQ,CAACe,IAAI;AACzF;AAEA,gEAAgE,GAChE,SAAS8B,SAAS,EAAEC,GAAG,EAAEzC,OAAO,EAAEI,MAAM,EAAEsC,IAAI,EAAqE;QACjGvD;QAAkCsD,UAgBlBA;IAhBhC,MAAME,WAAUxD,gBAAAA,aAAasD,IAAIb,GAAG,EAAExB,mBAAtBjB,gBAAkCsD,EAAAA,WAAAA,IAAIb,GAAG,qBAAPa,SAASZ,MAAM,MAAK,UAAU,CAACa,OAAOtC,SAAS;IACjG,qBACE;;YACGqC,IAAIzC,OAAO,IAAIyC,IAAIb,GAAG,iBACrB,KAAC1D;gBACC0E,UAAS;gBACTC,oBAAM,KAACxE;oBAAiByE,MAAM;oBAAIC,cAAW;;gBAC7CC,sBACE,KAAC5E;oBAAO6E,OAAM;oBAAUH,MAAK;oBAAQI,SAAQ;oBAAWC,SAAS,IAAMV,IAAIb,GAAG,IAAI1C,WAAW;4BAAEkE,OAAOX,IAAIb,GAAG,CAACyB,EAAE;wBAAC;8BAC9G;;0BAIJrD;iBAED;YACH2C,wBAAU,KAACzE;gBAAM0E,UAAUH,EAAAA,YAAAA,IAAIb,GAAG,qBAAPa,UAASZ,MAAM,MAAK,WAAW,UAAU;0BAAYc;iBAAmB;YACnGF,IAAIa,MAAM,iBAAG,KAACpF;gBAAM0E,UAAS;0BAAWH,IAAIa,MAAM;iBAAY;;;AAGrE;AAEA,sEAAsE,GACtE,OAAO,SAASC,oBAAoB,EAClCC,MAAM,EACNC,KAAK,EACLnB,IAAI,EACJoB,OAAO,EACPC,QAAQ,EACRC,OAAO,EACmD;IAC1D,MAAMC,OAAOtE;IACb,MAAMuE,OAAOhG,eAAe,WAAW;QACrCiG,QAAQzB,SAAS,aAAa,cAAc;IAC9C;IACA,MAAM,EAAE0B,MAAMC,IAAI,EAAE,GAAGhG;IACvB,MAAMwE,MAAMrD,YAAY6E,MAAMJ,KAAKzD,MAAM;IACzC,MAAM,EAAE8D,KAAK,EAAE,GAAGzB;IAClB,MAAM,CAACvC,MAAMiE,QAAQ,GAAGpF,SAAS;IACjC,MAAM,CAACqF,OAAOC,SAAS,GAAGtF,SAAS;IACnC,MAAM,CAACoB,WAAWmE,aAAa,GAAGvF,SAAS;IAE3CD,UAAU;QACRoF;QACAI,aAAa;IACf,GAAG;QAACpE;QAAMgE;KAAM;IAEhB,2EAA2E;IAC3E,wEAAwE;IACxE,IAAIP,aAAa,OAAO,OAAOC,wBAAU,KAACvE;QAAeiD,MAAK;QAAQsB,SAASA;SAAc;IAC7F,MAAM3D,QAAQ0B,WAAWc,IAAIb,GAAG;IAChC,MAAM2C,SAAS,CAAC9B,IAAIb,GAAG,IAAI4C,QAAQ/B,IAAIa,MAAM;IAC7C,MAAMmB,QAAQ,IAAMN,QAAQ;IAE5B,MAAMO,QAAQ;QACZ,MAAMC,UAAUP,MAAMQ,IAAI;QAC1B,IAAI,CAACnB,SAAS,CAACkB,SAAS;QACxB,IAAI,MAAMlC,IAAIiC,KAAK,CAAC;YAAEjB;YAAOD;YAAQlB,MAAM;YAAS8B,OAAOO;YAASE,QAAQ;gBAAEC,MAAMxC;YAAK;QAAE,IAAI+B,SAAS;IAC1G;IACA,MAAMU,QAAQ;QACZ,IAAI,CAAC9E,OAAO;QACZ,IAAIyD,QAAQzD,MAAMkC,QAAQ,GAAGsC;aACxBH,aAAa;IACpB;IAEA,qBACE;;0BACE,KAAClG;gBAAO0E,MAAK;gBAAQI,SAAQ;gBAAW8B,yBAAW,KAAChH;oBAAQiH,MAAMlH,YAAYkH,IAAI;;gBAAM9B,SAAS,IAAMgB,QAAQ;0BAC5GN,KAAKrE,MAAM;;0BAEd,MAAClB;gBAAO4B,MAAMA;gBAAMgF,SAASzC,IAAI0C,QAAQ,GAAGC,YAAYX;gBAAOY,SAAS;gBAACC,UAAS;;kCAChF,KAAC7G;kCAAaoF,KAAKpE,KAAK,CAAC6C,KAAK;;kCAC9B,KAAC9D;kCACC,cAAA,MAACG;4BAAM4G,SAAS;4BAAGC,IAAI;gCAAEC,IAAI;4BAAE;;gCAC5BlB,uBACC;;sDACE,KAAC3F;4CACCgB,OAAOiE,KAAKjE,KAAK,CAAC0C,KAAK;4CACvBzC,aAAagE,KAAKhE,WAAW,CAACyC,KAAK;4CACnCoD,SAAS;4CACTC,SAAS;4CACTC,OAAOxB;4CACPyB,UAAU,CAACC,QAAUzB,SAASyB,MAAMC,MAAM,CAACH,KAAK,CAACI,KAAK,CAAC,GAAG1G;4CAC1D2G,UAAUxD,IAAI0C,QAAQ;4CACtBe,SAAS;;sDAEX,MAACrH;4CAAWqE,SAAQ;4CAAQD,OAAM;;gDAC/BY,KAAK/D,IAAI,CAACwC,KAAK;gDAAE;8DAClB,KAAC5D;oDAAKyH,MAAMrC,KAAKqC,IAAI;oDAAEJ,QAAO;oDAASK,KAAI;oDAAW3G,OAAOqE,KAAKuC,WAAW;8DAC1E;;;;;qCAIL;gCACHpG,sBACC,MAAC/B;oCAAM0E,UAAS;;sDACd,KAAC/D;4CAAWqE,SAAQ;4CAAQsC,IAAI;gDAAEc,YAAY;4CAAI;sDAAI,GAAGzC,KAAK5D,KAAK,CAAC,EAAE,EAAEoC,OAAOpC,MAAMkC,QAAQ,GAAG;;wCAC/FlC,MAAMmC,IAAI,iBAAG,KAACvD;4CAAWqE,SAAQ;sDAASjD,MAAMmC,IAAI;6CAAiB;;qCAEtE;8CACJ,KAACI;oCAASC,KAAKA;oCAAKzC,SAAS6D,KAAK7D,OAAO;oCAAEI,QAAQyD,KAAKzD,MAAM;oCAAEsC,MAAM8B,QAAQvE;;gCAC7EE,0BAAY,KAACjC;oCAAM0E,UAAS;8CAAWiB,KAAK1D,SAAS;qCAAY;;;;kCAGtE,MAAC5B;;0CACC,KAACH;gCAAO+E,SAASsB;gCAAOwB,UAAUxD,IAAI0C,QAAQ;0CAC3CZ,SAAS,WAAW;;4BAEtBA,uBACC,KAACnG;gCAAO8E,SAAQ;gCAAYC,SAAS,IAAM,KAAKuB;gCAASuB,UAAUxD,IAAI0C,QAAQ,IAAI,CAAC1B,SAAS,CAACW,MAAMQ,IAAI;0CACrGf,KAAK9D,MAAM,CAACuC,KAAK;iCAElBrC,sBACF,KAAC7B;gCAAO8E,SAAQ;gCAAYC,SAAS4B;0CAClClB,KAAK3D,IAAI;iCAEV;;;;;;;AAKd;AAEA,mFAAmF,GACnF,OAAO,SAASqG,qBAAqB,EAAE/C,MAAM,EAAEC,KAAK,EAAEsC,MAAM,EAAErC,OAAO,EAAuC;;QAUxGrD,cAAiCA;IATnC,MAAMwD,OAAOtE;IACb,MAAMuE,OAAOhG,eAAe,WAAW;QAAEiG,QAAQ;IAAU;IAC3D,MAAM,EAAEC,MAAMC,IAAI,EAAE,GAAGhG;IACvB,MAAMoC,UAAUjB,YAAY6E,MAAMJ,KAAKrD,aAAa;IACpD,MAAMK,SAASzB,YAAY6E,MAAMJ,KAAKzD,MAAM;IAC5C,MAAM,CAACgE,OAAOC,SAAS,GAAGtF,SAAS;IACnC,MAAM,CAACoB,WAAWmE,aAAa,GAAGvF,SAAS;IAE3C,MAAMyH,cACJnG,EAAAA,eAAAA,QAAQuB,GAAG,qBAAXvB,aAAawB,MAAM,MAAK,kBAASxB,4BAAAA,QAAQuB,GAAG,CAACG,OAAO,CAACC,IAAI,CAAC,CAACC,MAAQA,IAAIC,QAAQ,KAAK,4BAAnD7B,0BAA4DoG,IAAI,mBAAI,OAAO;IAC9G,MAAMxG,QAAQ0B,WAAWd,OAAOe,GAAG;IACnC,MAAM8E,OAAO7F,OAAOsE,QAAQ,IAAItE,OAAOb,OAAO;IAE9C,MAAM2G,MAAM;QACV,IAAI,CAAClD,OAAO;QACZ,KAAKpD,QAAQqE,KAAK,CAAC;YACjBjB;YACAD;YACAlB,MAAM;YACN8B,OAAOP,KAAKpD,YAAY,CAACsF,OAAOrF,IAAI;YACpCmE,QAAQ;gBAAEC,MAAM;gBAAW8B,YAAYb,OAAO1C,EAAE;YAAC;QACnD;IACF;IACA,MAAMwD,SAAS,OAAOJ;QACpB,MAAM9B,UAAU8B,KAAK7B,IAAI;QACzB,IAAI,CAACnB,SAAS,CAACkB,SAAS;QACxBL,aAAa;QACb,IACE,MAAMzD,OAAO6D,KAAK,CAAC;YAAEjB;YAAOD;YAAQlB,MAAM;YAAS8B,OAAOO;YAASE,QAAQ;gBAAEC,MAAM;gBAAY8B,YAAYb,OAAO1C,EAAE;YAAC;QAAE,IACvH;YACAgB,SAAS;QACX;IACF;IAEA,qBACE,KAAClG;QAAIqH,IAAI;YAAEsB,QAAQ;YAAGC,aAAa;YAAWC,cAAc;YAAGC,GAAG;QAAI;QAAGlE,cAAW;kBAClF,cAAA,MAACpE;YAAM4G,SAAS;;8BACd,MAAC5G;oBAAMuI,WAAU;oBAAM3B,SAAS;oBAAGC,IAAI;wBAAE2B,YAAY;oBAAS;;sCAC5D,MAACtI;4BAAWqE,SAAQ;4BAAQD,OAAM;4BAAiBuC,IAAI;gCAAE4B,UAAU;4BAAE;;gCAClEvD,KAAK7C,WAAW;gCAAE;8CACnB,KAACtC;oCAAKyH,MAAMrC,KAAKqC,IAAI;oCAAEJ,QAAO;oCAASK,KAAI;oCAAW3G,OAAOqE,KAAKuC,WAAW;8CAC1E;;;;sCAGL,KAACjI;4BAAO0E,MAAK;4BAAQI,SAAQ;4BAAW+C,UAAU5F,QAAQ8E,QAAQ,IAAI9E,QAAQL,OAAO,IAAI,CAACyD;4BAAON,SAASwD;sCACvGH,cAAc3C,KAAKtD,KAAK,GAAGsD,KAAKxD,OAAO;;;;gBAG3CmG,4BACC,KAAC3H;oBAAWqE,SAAQ;oBAAQmE,WAAU;oBAAM7B,IAAI;wBAAE8B,YAAY;wBAAYC,WAAW;oBAAa;8BAC/Ff;qBAED;8BACJ,KAAChE;oBAASC,KAAKpC;oBAASL,SAAS6D,KAAKvD,UAAU;oBAAEF,QAAQyD,KAAKrD,aAAa;oBAAEkC,MAAM8B,QAAQgC;;8BAC5F,KAAC5H;oBACCkE,MAAK;oBACLlD,OAAOiE,KAAKlD,WAAW;oBACvBd,aAAagE,KAAKjD,iBAAiB;oBACnCgF,OAAOxB;oBACPsB,SAAS;oBACT8B,SAAS;oBACT3B,UAAU,CAACC,QAAUzB,SAASyB,MAAMC,MAAM,CAACH,KAAK,CAACI,KAAK,CAAC,GAAG1G;oBAC1D2G,UAAUS;;8BAEZ,MAAC/H;oBAAMuI,WAAU;oBAAM3B,SAAS;;sCAC9B,KAACnH;4BACC0E,MAAK;4BACLI,SAAQ;4BACR8B,yBAAW,KAAChH;gCAAQiH,MAAMlH,YAAYkH,IAAI;;4BAC1CgB,UAAUS,QAAQ,CAACjD,SAAS,CAACW,MAAMQ,IAAI;4BACvCzB,SAAS,IAAM,KAAK0D,OAAOzC;sCAE1BP,KAAKhD,MAAM;;sCAEd,KAACzC;4BACC0E,MAAK;4BACLI,SAAQ;4BACR8B,yBAAW,KAAChH;gCAAQiH,MAAMlH,YAAYkH,IAAI;;4BAC1CgB,UAAUS,QAAQ,CAACjD;4BACnBN,SAAS,IAAM,KAAK0D,OAAOhD,KAAK9C,QAAQ,CAACgF,OAAOrF,IAAI;sCAEnDmD,KAAK/C,GAAG;;;;gBAGZb,sBACC,MAAC/B;oBACC0E,UAAS;oBACTI,sBACE,KAAC5E;wBACC6E,OAAM;wBACNH,MAAK;wBACLI,SAAQ;wBACRC,SAAS;4BACP,IAAI,CAACO,QAAQzD,MAAMkC,QAAQ,GAAGmC,aAAa;wBAC7C;kCAECT,KAAK5C,OAAO;;;sCAIjB,KAACpC;4BAAWqE,SAAQ;4BAAQsC,IAAI;gCAAEc,YAAY;4BAAI;sCAAI,GAAGzC,KAAK5D,KAAK,CAAC,EAAE,EAAEoC,OAAOpC,MAAMkC,QAAQ,GAAG;;wBAC/FlC,MAAMmC,IAAI,iBAAG,KAACvD;4BAAWqE,SAAQ;sCAASjD,MAAMmC,IAAI;6BAAiB;;qBAEtE;8BACJ,KAACI;oBAASC,KAAK5B;oBAAQb,SAAS6D,KAAK7D,OAAO;oBAAEI,QAAQyD,KAAKzD,MAAM;oBAAEsC,MAAM8B,QAAQvE;;gBAChFE,0BAAY,KAACjC;oBAAM0E,UAAS;8BAAWiB,KAAK1D,SAAS;qBAAY;;;;AAI1E;AAEA;;;;CAIC,GACD,OAAO,SAASsH,oBAAoB,EAAEjE,MAAM,EAAEC,KAAK,EAAEjC,KAAK,EAAuC;QAO/EiB;IANhB,MAAMoB,OAAOtE;IACb,MAAM,EAAEyE,MAAMC,IAAI,EAAE,GAAGhG;IACvB,MAAMwE,MAAMrD,YAAY6E,MAAMJ,KAAKvC,eAAe;IAClD,MAAM,CAACpB,MAAMiE,QAAQ,GAAGpF,SAAS;IAEjC,IAAIyC,MAAMkG,MAAM,KAAK,UAAU,OAAO;IACtC,MAAMC,UAAUlF,EAAAA,WAAAA,IAAIb,GAAG,qBAAPa,SAASZ,MAAM,MAAK,SAASY,IAAIb,GAAG,CAACG,OAAO,CAACC,IAAI,CAAC,CAACC,MAAQA,IAAIC,QAAQ,KAAK,cAAckD;IAE1G,MAAMuB,MAAM;QACVxC,QAAQ;QACR,IAAI1B,IAAIb,GAAG,IAAI,CAAC6B,OAAO;QACvB,KAAKhB,IAAIiC,KAAK,CAAC;YACbjB;YACAD;YACAlB,MAAM;YACN8B,OAAOP,KAAKtC,cAAc,CAACC;YAC3BqD,QAAQ;gBAAEC,MAAM;gBAAU8C,YAAY;gBAAUC,UAAUrG,MAAMsG,QAAQ;YAAC;QAC3E;IACF;IACA,MAAMrD,QAAQ;QACZN,QAAQ;QACR,IAAI1B,IAAIa,MAAM,EAAEb,IAAIyB,KAAK;IAC3B;IAEA,qBACE;;0BACE,KAAC9F;gBAAO0E,MAAK;gBAAQI,SAAQ;gBAAOsC,IAAI;oBAAEuC,IAAI;oBAAKC,UAAU;gBAAE;gBAAGhD,yBAAW,KAAChH;oBAAQiH,MAAMlH,YAAYkH,IAAI;;gBAAM9B,SAASwD;0BACxH9C,KAAK3C,YAAY;;0BAEpB,MAAC5C;gBAAO4B,MAAMA;gBAAMgF,SAAST;gBAAOY,SAAS;gBAACC,UAAS;;kCACrD,KAAC7G;kCAAaoF,KAAK1C,cAAc;;kCACjC,KAAC3C;kCACC,cAAA,MAACG;4BAAM4G,SAAS;4BAAKC,IAAI;gCAAEC,IAAI;4BAAE;;gCAC9BkC,wBACC,MAACzJ;oCAAM0E,UAAS;;sDACd,KAAC/D;4CAAWqE,SAAQ;4CAAQsC,IAAI;gDAAEc,YAAY;4CAAI;sDAAIqB,QAAQ/H,KAAK;;sDACnE,KAACf;4CAAWqE,SAAQ;sDAASyE,QAAQvF,IAAI,IAAIyB,KAAKxC,aAAa;;;qCAE/D;8CACJ,KAACmB;oCAASC,KAAKA;oCAAKzC,SAAS6D,KAAKzC,gBAAgB;oCAAEhB,QAAQyD,KAAKvC,eAAe;oCAAEoB,MAAM8B,QAAQmD;;;;;kCAGpG,KAACpJ;kCACC,cAAA,KAACH;4BAAO+E,SAASsB;sCAAQ;;;;;;;AAKnC"}
@@ -17,7 +17,8 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
17
17
  * limitations under the License.
18
18
  */ import { lockdownRefusalText, parseLockdownRefusal, resolveEffectivePlan } from "@aglyn/aglyn";
19
19
  import { mdiCreation } from "@aglyn/shared-data-mdi";
20
- import { MdiIcon } from "@aglyn/shared-ui-jsx";
20
+ import { pluginDocsHelp } from "@aglyn/aglyn/app-utils/docs-help";
21
+ import { HelpTip, MdiIcon } from "@aglyn/shared-ui-jsx";
21
22
  import { authorizedFetch } from "@aglyn/shared-util-http/authorized-token";
22
23
  import { useFirestore, useFirestoreDoc, useUser } from "@aglyn/tenant-feature-instance";
23
24
  import { Alert, Button, Dialog, DialogActions, DialogContent, DialogTitle, FormControlLabel, IconButton, LinearProgress, ListItemText, ListSubheader, MenuItem, Radio, RadioGroup, Stack, TextField, ToggleButton, ToggleButtonGroup, Typography } from "@mui/material";
@@ -67,6 +68,31 @@ import { AI_IMAGE_ASPECT_RATIOS, AI_IMAGE_MAX_COUNT, AI_IMAGE_PROMPT_MAX_CHARS,
67
68
  ...kinds.filter((kind)=>kind.group === group).map(item)
68
69
  ]);
69
70
  }
71
+ /**
72
+ * The window's own help (AGL-3660): each control links the section of the
73
+ * guide about it, not the guide's top.
74
+ */ const AI_MEDIA_HELP = {
75
+ dialog: pluginDocsHelp('aiImages', {
76
+ anchor: '#make-a-picture',
77
+ excerpt: 'Choose a kind, describe the picture, pick a shape and how many. The pictures land in the folder you have open, with alt text you can edit.'
78
+ }),
79
+ locked: pluginDocsHelp('aiImages', {
80
+ anchor: '#who-can-use-it',
81
+ excerpt: 'Creating pictures needs AI on your plan and the Generate with AI permission. A Free workspace creates them from its monthly credits.'
82
+ }),
83
+ shape: pluginDocsHelp('aiImages', {
84
+ anchor: '#shapes-and-how-many',
85
+ excerpt: 'Five shapes, from Square 1:1 to Tall 9:16, and one to four pictures per request. Each picture is charged on its own.'
86
+ }),
87
+ credits: pluginDocsHelp('aiImages', {
88
+ anchor: '#credits',
89
+ excerpt: 'The estimate is per picture times how many. You are charged only for pictures that reach your library; a declined or failed picture costs nothing.'
90
+ }),
91
+ declined: pluginDocsHelp('aiImages', {
92
+ anchor: '#declined-pictures',
93
+ excerpt: 'Google’s safety filters may decline real people, celebrities, brands and unsafe content. A declined picture is not charged.'
94
+ })
95
+ };
70
96
  /**
71
97
  * The size the door will make a picture at for this workspace (AGL-3602):
72
98
  * 512 px on the Free plan, 1K on a paid one. The door decides from the plan
@@ -109,8 +135,16 @@ export function AiMediaCreateButton(props) {
109
135
  fullWidth: true,
110
136
  maxWidth: "xs",
111
137
  children: [
112
- /*#__PURE__*/ _jsx(DialogTitle, {
113
- children: 'Create images with AI'
138
+ /*#__PURE__*/ _jsxs(DialogTitle, {
139
+ sx: {
140
+ display: 'flex',
141
+ alignItems: 'center',
142
+ gap: 0.5
143
+ },
144
+ children: [
145
+ 'Create images with AI',
146
+ /*#__PURE__*/ _jsx(HelpTip, _extends({}, AI_MEDIA_HELP.locked))
147
+ ]
114
148
  }),
115
149
  /*#__PURE__*/ _jsx(DialogContent, {
116
150
  children: /*#__PURE__*/ _jsx(Typography, {
@@ -262,8 +296,16 @@ export function AiMediaCreateDialog({ open, onClose, orgId, hostId, library, fol
262
296
  fullWidth: true,
263
297
  maxWidth: "sm",
264
298
  children: [
265
- /*#__PURE__*/ _jsx(DialogTitle, {
266
- children: 'Create images with AI'
299
+ /*#__PURE__*/ _jsxs(DialogTitle, {
300
+ sx: {
301
+ display: 'flex',
302
+ alignItems: 'center',
303
+ gap: 0.5
304
+ },
305
+ children: [
306
+ 'Create images with AI',
307
+ /*#__PURE__*/ _jsx(HelpTip, _extends({}, AI_MEDIA_HELP.dialog))
308
+ ]
267
309
  }),
268
310
  /*#__PURE__*/ _jsx(DialogContent, {
269
311
  children: /*#__PURE__*/ _jsxs(Stack, {
@@ -312,18 +354,38 @@ export function AiMediaCreateDialog({ open, onClose, orgId, hostId, library, fol
312
354
  disabled: busy,
313
355
  helperText: kind.colors === 'describe' ? `${AI_MEDIA_DESCRIBE_COLORS_NOTE} The description becomes each picture's alt text, which you can edit.` : "The description becomes each picture's alt text, which you can edit."
314
356
  }),
315
- mode === 'photo' ? /*#__PURE__*/ _jsx(Typography, {
316
- variant: "body2",
317
- color: "text.secondary",
318
- children: AI_MEDIA_RASTER_SAFETY_NOTE
319
- }) : null,
320
- /*#__PURE__*/ _jsxs(Stack, {
357
+ mode === 'photo' ? /*#__PURE__*/ _jsxs(Stack, {
358
+ direction: "row",
321
359
  spacing: 0.5,
360
+ sx: {
361
+ alignItems: 'center'
362
+ },
322
363
  children: [
323
364
  /*#__PURE__*/ _jsx(Typography, {
324
365
  variant: "body2",
325
366
  color: "text.secondary",
326
- children: 'Shape'
367
+ children: AI_MEDIA_RASTER_SAFETY_NOTE
368
+ }),
369
+ /*#__PURE__*/ _jsx(HelpTip, _extends({}, AI_MEDIA_HELP.declined))
370
+ ]
371
+ }) : null,
372
+ /*#__PURE__*/ _jsxs(Stack, {
373
+ spacing: 0.5,
374
+ children: [
375
+ /*#__PURE__*/ _jsxs(Stack, {
376
+ direction: "row",
377
+ spacing: 0.5,
378
+ sx: {
379
+ alignItems: 'center'
380
+ },
381
+ children: [
382
+ /*#__PURE__*/ _jsx(Typography, {
383
+ variant: "body2",
384
+ color: "text.secondary",
385
+ children: 'Shape'
386
+ }),
387
+ /*#__PURE__*/ _jsx(HelpTip, _extends({}, AI_MEDIA_HELP.shape))
388
+ ]
327
389
  }),
328
390
  /*#__PURE__*/ _jsx(ToggleButtonGroup, {
329
391
  size: "small",
@@ -439,10 +501,20 @@ export function AiMediaCreateDialog({ open, onClose, orgId, hostId, library, fol
439
501
  children: value
440
502
  }, value))
441
503
  }),
442
- /*#__PURE__*/ _jsx(Typography, {
443
- variant: "body2",
444
- color: "text.secondary",
445
- children: aiMediaCreditEstimate(mode, count, imageSize)
504
+ /*#__PURE__*/ _jsxs(Stack, {
505
+ direction: "row",
506
+ spacing: 0.5,
507
+ sx: {
508
+ alignItems: 'center'
509
+ },
510
+ children: [
511
+ /*#__PURE__*/ _jsx(Typography, {
512
+ variant: "body2",
513
+ color: "text.secondary",
514
+ children: aiMediaCreditEstimate(mode, count, imageSize)
515
+ }),
516
+ /*#__PURE__*/ _jsx(HelpTip, _extends({}, AI_MEDIA_HELP.credits))
517
+ ]
446
518
  }),
447
519
  busy ? /*#__PURE__*/ _jsxs(Stack, {
448
520
  spacing: 1,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-media-create.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 { lockdownRefusalText, parseLockdownRefusal, resolveEffectivePlan } from '@aglyn/aglyn'\nimport type { ConsoleMediaLibraryZoneProps } from '@aglyn/aglyn/plugin-manager/feature-plugins'\nimport { mdiCreation } from '@aglyn/shared-data-mdi'\nimport { MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { useFirestore, useFirestoreDoc, useUser } from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n FormControlLabel,\n IconButton,\n LinearProgress,\n ListItemText,\n ListSubheader,\n MenuItem,\n Radio,\n RadioGroup,\n Stack,\n TextField,\n ToggleButton,\n ToggleButtonGroup,\n Typography,\n} from '@mui/material'\nimport { doc } from 'firebase/firestore'\nimport { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from 'react'\nimport { aiMediaCreditsPerPicture } from '../model/ai-media-credits'\nimport {\n AI_MEDIA_KIND_GROUP_LABELS,\n AI_MEDIA_KIND_GROUPS,\n aiMediaKind,\n aiMediaKindsOffered,\n type AiMediaKind,\n type AiMediaKindId,\n} from '../model/ai-media-kinds'\nimport {\n AI_IMAGE_ASPECT_RATIOS,\n AI_IMAGE_MAX_COUNT,\n AI_IMAGE_PROMPT_MAX_CHARS,\n aiImageSizeForPlan,\n AI_SVG_MAX_COLORS,\n aiImagePhotosOffered,\n type AiImageAspectRatio,\n type AiImageMode,\n type AiImageSize,\n} from '../providers/image-contract'\n\n/**\n * \"Create with AI\" in Media (AGL-3602): pictures from a description, added to\n * the library that is open, through the `mediaLibrary` zone beside Upload\n * media and in the library's empty state.\n *\n * It draws from the shell's gates alone — the plan, the member's\n * `ai.generate`, the plugin being on for the workspace and the site — and asks\n * no server anything until someone creates a picture: the door decides then,\n * and the dialog says what it decided. One Kind menu, in sections: Vector\n * kinds (an SVG the text AI draws, wherever text AI runs) and, where the\n * deployment makes them, Photo, Art and Design kinds from the image provider.\n */\n\n/** Where the shell sends a reader to buy what the plan lacks (AGL-3601). */\nexport interface AiMediaUpgrade {\n billingHref: string\n canManageBilling: boolean\n}\n\nexport interface AiMediaCreateButtonProps extends ConsoleMediaLibraryZoneProps {\n /**\n * `false` when the shell mounted this as its own upsell: the plan lacks AI\n * generation and an add-on would grant it. Absent means entitled.\n */\n entitled?: boolean\n upgrade?: AiMediaUpgrade\n}\n\n/** The words each shape is offered in. */\nconst ASPECT_LABELS: Record<AiImageAspectRatio, string> = {\n '1:1': 'Square',\n '4:3': 'Landscape',\n '3:4': 'Portrait',\n '16:9': 'Wide',\n '9:16': 'Tall',\n}\n\n/**\n * What a picture from the image provider may be declined for, as the code\n * and the provider decide it: Google's filters, and its policies on real\n * people and brands. A declined picture is never charged.\n */\nexport const AI_MEDIA_RASTER_SAFETY_NOTE =\n 'Pictures of real, identifiable people, celebrities or brands may be declined by the image service. A declined picture is not charged.'\n\n/** The line under the description for a kind whose colors are described rather than picked. */\nexport const AI_MEDIA_DESCRIBE_COLORS_NOTE =\n 'To steer the colors, name them in the description, such as navy and coral.'\n\n/** The menu's items: each section's heading, then its kinds with what one costs. */\nfunction kindMenuItems(kinds: readonly AiMediaKind[], size: AiImageSize): ReactNode[] {\n const groups = AI_MEDIA_KIND_GROUPS.filter((group) => kinds.some((kind) => kind.group === group))\n const item = (kind: AiMediaKind) => (\n <MenuItem key={kind.id} value={kind.id} sx={{ gap: 2 }}>\n <ListItemText primary={kind.label} />\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`about ${aiMediaCreditsPerPicture(kind.mode, undefined, size).toLocaleString()} credits`}\n </Typography>\n </MenuItem>\n )\n // One section needs no heading: a deployment without the image provider\n // lists the vector kinds alone, as it always has.\n if (groups.length < 2) return kinds.map(item)\n return groups.flatMap((group) => [\n <ListSubheader key={`group:${group}`}>{AI_MEDIA_KIND_GROUP_LABELS[group]}</ListSubheader>,\n ...kinds.filter((kind) => kind.group === group).map(item),\n ])\n}\n\n/**\n * The size the door will make a picture at for this workspace (AGL-3602):\n * 512 px on the Free plan, 1K on a paid one. The door decides from the plan\n * itself; this reads the same plan so the estimate matches, and reads 1K —\n * the dearer estimate — until the workspace has arrived.\n */\nexport function useAiMediaImageSize(orgId: string): AiImageSize {\n const firestore = useFirestore()\n const { data: org, status } = useFirestoreDoc<Record<string, unknown>>(\n () => doc(firestore, 'orgs', orgId),\n [firestore, orgId],\n )\n return aiImageSizeForPlan(status === 'success' && resolveEffectivePlan(org as never) === 'free')\n}\n\n/** The sentence the estimate reads as, before anything is spent. */\nexport function aiMediaCreditEstimate(\n mode: AiImageMode,\n count: number,\n size: AiImageSize = '1K',\n): string {\n const each = aiMediaCreditsPerPicture(mode, undefined, size)\n const pictures = count === 1 ? '1 picture' : `${count} pictures`\n return (\n `${pictures} uses about ${(count * each).toLocaleString()} AI credits ` +\n `(about ${each.toLocaleString()} each). A picture that is held back or does not come out is not charged.`\n )\n}\n\nexport function AiMediaCreateButton(props: AiMediaCreateButtonProps) {\n const { orgId, entitled, upgrade } = props\n const [open, setOpen] = useState(false)\n if (!orgId) return null\n const button = (\n <Button\n size=\"small\"\n variant=\"outlined\"\n startIcon={<MdiIcon path={mdiCreation.path} />}\n onClick={() => setOpen(true)}\n >\n {'Create with AI'}\n </Button>\n )\n if (entitled === false) {\n if (!upgrade) return null\n return (\n <>\n {button}\n <Dialog open={open} onClose={() => setOpen(false)} fullWidth maxWidth=\"xs\">\n <DialogTitle>{'Create images with AI'}</DialogTitle>\n <DialogContent>\n <Typography>\n {upgrade.canManageBilling\n ? 'Creating pictures and illustrations comes with the AI add-on.'\n : 'Creating pictures and illustrations comes with the AI add-on. Ask an owner or admin of this workspace to add it.'}\n </Typography>\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setOpen(false)}>{'Close'}</Button>\n {upgrade.canManageBilling ? (\n <Button variant=\"contained\" href={upgrade.billingHref}>\n {'See the AI add-on'}\n </Button>\n ) : null}\n </DialogActions>\n </Dialog>\n </>\n )\n }\n return (\n <>\n {button}\n <AiMediaCreateDialog {...props} orgId={orgId} open={open} onClose={() => setOpen(false)} />\n </>\n )\n}\n\nexport interface AiMediaCreateDialogProps\n extends Pick<ConsoleMediaLibraryZoneProps, 'hostId' | 'library' | 'folderId' | 'onCreated'> {\n open: boolean\n onClose: () => void\n orgId: string\n}\n\nexport function AiMediaCreateDialog({\n open,\n onClose,\n orgId,\n hostId,\n library,\n folderId,\n onCreated,\n}: AiMediaCreateDialogProps) {\n const { data: user } = useUser()\n const userRef = useRef(user)\n userRef.current = user\n const photos = aiImagePhotosOffered()\n const imageSize = useAiMediaImageSize(orgId)\n const kinds = useMemo(() => aiMediaKindsOffered(photos), [photos])\n const [kindId, setKindId] = useState<AiMediaKindId>(photos ? 'photo' : 'illustration')\n const kind = kinds.find((entry) => entry.id === kindId) ?? kinds[0]\n const mode = kind.mode\n // The site theme's colors need a site; the organization's library names none.\n const [paletteSource, setPaletteSource] = useState<'theme' | 'custom'>(hostId ? 'theme' : 'custom')\n const [colors, setColors] = useState<string[]>(['#1a73e8', '#fbbc04'])\n const [prompt, setPrompt] = useState('')\n const [aspectRatio, setAspectRatio] = useState<AiImageAspectRatio>(kind.aspectRatio)\n const [count, setCount] = useState(1)\n const [busy, setBusy] = useState(false)\n const [notice, setNotice] = useState<{ severity: 'error' | 'warning'; text: string } | null>(null)\n\n useEffect(() => {\n if (open) setNotice(null)\n }, [open])\n\n /** A new kind brings its own shape; the person may still change it. */\n const chooseKind = (next: AiMediaKindId) => {\n setKindId(next)\n const chosen = aiMediaKind(next)\n if (chosen) setAspectRatio(chosen.aspectRatio)\n }\n\n const create = useCallback(async () => {\n const description = prompt.trim()\n if (!description) return\n setBusy(true)\n setNotice(null)\n try {\n const response = await authorizedFetch(userRef.current, '/api/ai/media/images', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n orgId,\n library,\n hostId,\n folderId,\n mode,\n prompt: description,\n aspectRatio,\n count,\n style: kind.id,\n ...(kind.colors === 'palette'\n ? {\n palette:\n paletteSource === 'theme' ? { source: 'theme' } : { source: 'custom', colors },\n }\n : {}),\n }),\n })\n const payload = await response.json().catch(() => null)\n if (!response.ok) {\n const locked = parseLockdownRefusal(response.status, payload)\n setNotice({\n severity: 'error',\n text: locked\n ? lockdownRefusalText(locked)\n : String(payload?.error ?? 'The pictures could not be made — try again.'),\n })\n return\n }\n const ids: string[] = Array.isArray(payload?.mediaIds) ? payload.mediaIds : []\n onCreated(ids)\n const missing = Number(payload?.filtered ?? 0) + Number(payload?.failed ?? 0)\n if (missing > 0) {\n setNotice({\n severity: 'warning',\n text:\n `Added ${ids.length} of ${count} to the library. ` +\n (payload?.warning\n ? String(payload.warning)\n : 'The rest were held back and were not charged.'),\n })\n return\n }\n setPrompt('')\n onClose()\n } catch {\n setNotice({ severity: 'error', text: 'The pictures could not be made — try again.' })\n } finally {\n setBusy(false)\n }\n }, [prompt, orgId, library, hostId, folderId, mode, aspectRatio, count, kind, paletteSource, colors, onCreated, onClose])\n\n return (\n <Dialog open={open} onClose={busy ? undefined : onClose} fullWidth maxWidth=\"sm\">\n <DialogTitle>{'Create images with AI'}</DialogTitle>\n <DialogContent>\n <Stack spacing={2} sx={{ pt: 1 }}>\n <TextField\n select\n size=\"small\"\n label=\"Kind\"\n value={kind.id}\n onChange={(event) => chooseKind(event.target.value as AiMediaKindId)}\n disabled={busy}\n fullWidth\n helperText={kind.hint}\n slotProps={{\n select: {\n renderValue: (value) => aiMediaKind(String(value))?.label ?? String(value),\n MenuProps: { slotProps: { paper: { sx: { maxHeight: 420 } } } },\n },\n }}\n >\n {kindMenuItems(kinds, imageSize)}\n </TextField>\n <TextField\n label={mode === 'photo' ? 'Describe the picture' : 'Describe what to draw'}\n placeholder={kind.placeholder}\n value={prompt}\n onChange={(event) => setPrompt(event.target.value.slice(0, AI_IMAGE_PROMPT_MAX_CHARS))}\n multiline\n minRows={3}\n autoFocus\n disabled={busy}\n helperText={\n kind.colors === 'describe'\n ? `${AI_MEDIA_DESCRIBE_COLORS_NOTE} The description becomes each picture's alt text, which you can edit.`\n : \"The description becomes each picture's alt text, which you can edit.\"\n }\n />\n {mode === 'photo' ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {AI_MEDIA_RASTER_SAFETY_NOTE}\n </Typography>\n ) : null}\n <Stack spacing={0.5}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Shape'}\n </Typography>\n <ToggleButtonGroup\n size=\"small\"\n exclusive\n value={aspectRatio}\n onChange={(_event, next) => {\n if (next) setAspectRatio(next)\n }}\n aria-label=\"Shape\"\n disabled={busy}\n sx={{ flexWrap: 'wrap' }}\n >\n {AI_IMAGE_ASPECT_RATIOS.map((ratio) => (\n <ToggleButton key={ratio} value={ratio} aria-label={`${ASPECT_LABELS[ratio]} ${ratio}`}>\n {`${ASPECT_LABELS[ratio]} ${ratio}`}\n </ToggleButton>\n ))}\n </ToggleButtonGroup>\n </Stack>\n {kind.colors === 'palette' ? (\n <Stack spacing={1}>\n <RadioGroup\n value={paletteSource}\n onChange={(event) => setPaletteSource(event.target.value as 'theme' | 'custom')}\n aria-label=\"Colors\"\n >\n <FormControlLabel\n value=\"theme\"\n control={<Radio size=\"small\" />}\n label=\"Use my site's theme colors\"\n disabled={busy || !hostId}\n />\n <FormControlLabel\n value=\"custom\"\n control={<Radio size=\"small\" />}\n label=\"Choose colors\"\n disabled={busy}\n />\n </RadioGroup>\n {paletteSource === 'custom' ? (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center', flexWrap: 'wrap' }}>\n {colors.map((color, index) => (\n <Stack key={index} direction=\"row\" sx={{ alignItems: 'center' }}>\n <TextField\n type=\"color\"\n size=\"small\"\n value={color}\n onChange={(event) =>\n setColors((current) =>\n current.map((value, at) => (at === index ? event.target.value : value)),\n )\n }\n disabled={busy}\n slotProps={{ htmlInput: { 'aria-label': `Color ${index + 1}` } }}\n sx={{ width: 64 }}\n />\n {colors.length > 1 ? (\n <IconButton\n size=\"small\"\n aria-label={`Remove color ${index + 1}`}\n onClick={() => setColors((current) => current.filter((_value, at) => at !== index))}\n disabled={busy}\n >\n {'×'}\n </IconButton>\n ) : null}\n </Stack>\n ))}\n {colors.length < AI_SVG_MAX_COLORS ? (\n <Button size=\"small\" onClick={() => setColors((current) => [...current, '#333333'])} disabled={busy}>\n {'Add a color'}\n </Button>\n ) : null}\n </Stack>\n ) : null}\n </Stack>\n ) : null}\n <TextField\n select\n size=\"small\"\n label=\"How many\"\n value={count}\n onChange={(event) => setCount(Number(event.target.value))}\n disabled={busy}\n sx={{ maxWidth: 160 }}\n >\n {Array.from({ length: AI_IMAGE_MAX_COUNT }, (_unused, index) => index + 1).map((value) => (\n <MenuItem key={value} value={value}>\n {value}\n </MenuItem>\n ))}\n </TextField>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {aiMediaCreditEstimate(mode, count, imageSize)}\n </Typography>\n {busy ? (\n <Stack spacing={1}>\n <LinearProgress />\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Making your pictures and adding them to the library…'}\n </Typography>\n </Stack>\n ) : null}\n {notice ? <Alert severity={notice.severity}>{notice.text}</Alert> : null}\n </Stack>\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose} disabled={busy}>\n {'Close'}\n </Button>\n <Button variant=\"contained\" onClick={() => void create()} disabled={busy || !prompt.trim()}>\n {busy ? 'Creating…' : 'Create'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\n\nexport default AiMediaCreateButton\n"],"names":["lockdownRefusalText","parseLockdownRefusal","resolveEffectivePlan","mdiCreation","MdiIcon","authorizedFetch","useFirestore","useFirestoreDoc","useUser","Alert","Button","Dialog","DialogActions","DialogContent","DialogTitle","FormControlLabel","IconButton","LinearProgress","ListItemText","ListSubheader","MenuItem","Radio","RadioGroup","Stack","TextField","ToggleButton","ToggleButtonGroup","Typography","doc","useCallback","useEffect","useMemo","useRef","useState","aiMediaCreditsPerPicture","AI_MEDIA_KIND_GROUP_LABELS","AI_MEDIA_KIND_GROUPS","aiMediaKind","aiMediaKindsOffered","AI_IMAGE_ASPECT_RATIOS","AI_IMAGE_MAX_COUNT","AI_IMAGE_PROMPT_MAX_CHARS","aiImageSizeForPlan","AI_SVG_MAX_COLORS","aiImagePhotosOffered","ASPECT_LABELS","AI_MEDIA_RASTER_SAFETY_NOTE","AI_MEDIA_DESCRIBE_COLORS_NOTE","kindMenuItems","kinds","size","groups","filter","group","some","kind","item","value","id","sx","gap","primary","label","variant","color","mode","undefined","toLocaleString","length","map","flatMap","useAiMediaImageSize","orgId","firestore","data","org","status","aiMediaCreditEstimate","count","each","pictures","AiMediaCreateButton","props","entitled","upgrade","open","setOpen","button","startIcon","path","onClick","onClose","fullWidth","maxWidth","canManageBilling","href","billingHref","AiMediaCreateDialog","hostId","library","folderId","onCreated","user","userRef","current","photos","imageSize","kindId","setKindId","find","entry","paletteSource","setPaletteSource","colors","setColors","prompt","setPrompt","aspectRatio","setAspectRatio","setCount","busy","setBusy","notice","setNotice","chooseKind","next","chosen","create","description","trim","response","method","headers","body","JSON","stringify","style","palette","source","payload","json","catch","ok","locked","severity","text","String","error","ids","Array","isArray","mediaIds","missing","Number","filtered","failed","warning","spacing","pt","select","onChange","event","target","disabled","helperText","hint","slotProps","renderValue","MenuProps","paper","maxHeight","placeholder","slice","multiline","minRows","autoFocus","exclusive","_event","aria-label","flexWrap","ratio","control","direction","alignItems","index","type","at","htmlInput","width","_value","from","_unused"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-media-create.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 { lockdownRefusalText, parseLockdownRefusal, resolveEffectivePlan } from '@aglyn/aglyn'\nimport type { ConsoleMediaLibraryZoneProps } from '@aglyn/aglyn/plugin-manager/feature-plugins'\nimport { mdiCreation } from '@aglyn/shared-data-mdi'\nimport { pluginDocsHelp } from '@aglyn/aglyn/app-utils/docs-help'\nimport { HelpTip, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { useFirestore, useFirestoreDoc, useUser } from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n FormControlLabel,\n IconButton,\n LinearProgress,\n ListItemText,\n ListSubheader,\n MenuItem,\n Radio,\n RadioGroup,\n Stack,\n TextField,\n ToggleButton,\n ToggleButtonGroup,\n Typography,\n} from '@mui/material'\nimport { doc } from 'firebase/firestore'\nimport { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from 'react'\nimport { aiMediaCreditsPerPicture } from '../model/ai-media-credits'\nimport {\n AI_MEDIA_KIND_GROUP_LABELS,\n AI_MEDIA_KIND_GROUPS,\n aiMediaKind,\n aiMediaKindsOffered,\n type AiMediaKind,\n type AiMediaKindId,\n} from '../model/ai-media-kinds'\nimport {\n AI_IMAGE_ASPECT_RATIOS,\n AI_IMAGE_MAX_COUNT,\n AI_IMAGE_PROMPT_MAX_CHARS,\n aiImageSizeForPlan,\n AI_SVG_MAX_COLORS,\n aiImagePhotosOffered,\n type AiImageAspectRatio,\n type AiImageMode,\n type AiImageSize,\n} from '../providers/image-contract'\n\n/**\n * \"Create with AI\" in Media (AGL-3602): pictures from a description, added to\n * the library that is open, through the `mediaLibrary` zone beside Upload\n * media and in the library's empty state.\n *\n * It draws from the shell's gates alone — the plan, the member's\n * `ai.generate`, the plugin being on for the workspace and the site — and asks\n * no server anything until someone creates a picture: the door decides then,\n * and the dialog says what it decided. One Kind menu, in sections: Vector\n * kinds (an SVG the text AI draws, wherever text AI runs) and, where the\n * deployment makes them, Photo, Art and Design kinds from the image provider.\n */\n\n/** Where the shell sends a reader to buy what the plan lacks (AGL-3601). */\nexport interface AiMediaUpgrade {\n billingHref: string\n canManageBilling: boolean\n}\n\nexport interface AiMediaCreateButtonProps extends ConsoleMediaLibraryZoneProps {\n /**\n * `false` when the shell mounted this as its own upsell: the plan lacks AI\n * generation and an add-on would grant it. Absent means entitled.\n */\n entitled?: boolean\n upgrade?: AiMediaUpgrade\n}\n\n/** The words each shape is offered in. */\nconst ASPECT_LABELS: Record<AiImageAspectRatio, string> = {\n '1:1': 'Square',\n '4:3': 'Landscape',\n '3:4': 'Portrait',\n '16:9': 'Wide',\n '9:16': 'Tall',\n}\n\n/**\n * What a picture from the image provider may be declined for, as the code\n * and the provider decide it: Google's filters, and its policies on real\n * people and brands. A declined picture is never charged.\n */\nexport const AI_MEDIA_RASTER_SAFETY_NOTE =\n 'Pictures of real, identifiable people, celebrities or brands may be declined by the image service. A declined picture is not charged.'\n\n/** The line under the description for a kind whose colors are described rather than picked. */\nexport const AI_MEDIA_DESCRIBE_COLORS_NOTE =\n 'To steer the colors, name them in the description, such as navy and coral.'\n\n/** The menu's items: each section's heading, then its kinds with what one costs. */\nfunction kindMenuItems(kinds: readonly AiMediaKind[], size: AiImageSize): ReactNode[] {\n const groups = AI_MEDIA_KIND_GROUPS.filter((group) => kinds.some((kind) => kind.group === group))\n const item = (kind: AiMediaKind) => (\n <MenuItem key={kind.id} value={kind.id} sx={{ gap: 2 }}>\n <ListItemText primary={kind.label} />\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`about ${aiMediaCreditsPerPicture(kind.mode, undefined, size).toLocaleString()} credits`}\n </Typography>\n </MenuItem>\n )\n // One section needs no heading: a deployment without the image provider\n // lists the vector kinds alone, as it always has.\n if (groups.length < 2) return kinds.map(item)\n return groups.flatMap((group) => [\n <ListSubheader key={`group:${group}`}>{AI_MEDIA_KIND_GROUP_LABELS[group]}</ListSubheader>,\n ...kinds.filter((kind) => kind.group === group).map(item),\n ])\n}\n\n/**\n * The window's own help (AGL-3660): each control links the section of the\n * guide about it, not the guide's top.\n */\nconst AI_MEDIA_HELP = {\n dialog: pluginDocsHelp('aiImages', {\n anchor: '#make-a-picture',\n excerpt:\n 'Choose a kind, describe the picture, pick a shape and how many. The pictures land in the folder you have open, with alt text you can edit.',\n }),\n locked: pluginDocsHelp('aiImages', {\n anchor: '#who-can-use-it',\n excerpt:\n 'Creating pictures needs AI on your plan and the Generate with AI permission. A Free workspace creates them from its monthly credits.',\n }),\n shape: pluginDocsHelp('aiImages', {\n anchor: '#shapes-and-how-many',\n excerpt:\n 'Five shapes, from Square 1:1 to Tall 9:16, and one to four pictures per request. Each picture is charged on its own.',\n }),\n credits: pluginDocsHelp('aiImages', {\n anchor: '#credits',\n excerpt:\n 'The estimate is per picture times how many. You are charged only for pictures that reach your library; a declined or failed picture costs nothing.',\n }),\n declined: pluginDocsHelp('aiImages', {\n anchor: '#declined-pictures',\n excerpt:\n 'Google’s safety filters may decline real people, celebrities, brands and unsafe content. A declined picture is not charged.',\n }),\n}\n\n/**\n * The size the door will make a picture at for this workspace (AGL-3602):\n * 512 px on the Free plan, 1K on a paid one. The door decides from the plan\n * itself; this reads the same plan so the estimate matches, and reads 1K —\n * the dearer estimate — until the workspace has arrived.\n */\nexport function useAiMediaImageSize(orgId: string): AiImageSize {\n const firestore = useFirestore()\n const { data: org, status } = useFirestoreDoc<Record<string, unknown>>(\n () => doc(firestore, 'orgs', orgId),\n [firestore, orgId],\n )\n return aiImageSizeForPlan(status === 'success' && resolveEffectivePlan(org as never) === 'free')\n}\n\n/** The sentence the estimate reads as, before anything is spent. */\nexport function aiMediaCreditEstimate(\n mode: AiImageMode,\n count: number,\n size: AiImageSize = '1K',\n): string {\n const each = aiMediaCreditsPerPicture(mode, undefined, size)\n const pictures = count === 1 ? '1 picture' : `${count} pictures`\n return (\n `${pictures} uses about ${(count * each).toLocaleString()} AI credits ` +\n `(about ${each.toLocaleString()} each). A picture that is held back or does not come out is not charged.`\n )\n}\n\nexport function AiMediaCreateButton(props: AiMediaCreateButtonProps) {\n const { orgId, entitled, upgrade } = props\n const [open, setOpen] = useState(false)\n if (!orgId) return null\n const button = (\n <Button\n size=\"small\"\n variant=\"outlined\"\n startIcon={<MdiIcon path={mdiCreation.path} />}\n onClick={() => setOpen(true)}\n >\n {'Create with AI'}\n </Button>\n )\n if (entitled === false) {\n if (!upgrade) return null\n return (\n <>\n {button}\n <Dialog open={open} onClose={() => setOpen(false)} fullWidth maxWidth=\"xs\">\n <DialogTitle sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>\n {'Create images with AI'}\n <HelpTip {...AI_MEDIA_HELP.locked} />\n </DialogTitle>\n <DialogContent>\n <Typography>\n {upgrade.canManageBilling\n ? 'Creating pictures and illustrations comes with the AI add-on.'\n : 'Creating pictures and illustrations comes with the AI add-on. Ask an owner or admin of this workspace to add it.'}\n </Typography>\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setOpen(false)}>{'Close'}</Button>\n {upgrade.canManageBilling ? (\n <Button variant=\"contained\" href={upgrade.billingHref}>\n {'See the AI add-on'}\n </Button>\n ) : null}\n </DialogActions>\n </Dialog>\n </>\n )\n }\n return (\n <>\n {button}\n <AiMediaCreateDialog {...props} orgId={orgId} open={open} onClose={() => setOpen(false)} />\n </>\n )\n}\n\nexport interface AiMediaCreateDialogProps\n extends Pick<ConsoleMediaLibraryZoneProps, 'hostId' | 'library' | 'folderId' | 'onCreated'> {\n open: boolean\n onClose: () => void\n orgId: string\n}\n\nexport function AiMediaCreateDialog({\n open,\n onClose,\n orgId,\n hostId,\n library,\n folderId,\n onCreated,\n}: AiMediaCreateDialogProps) {\n const { data: user } = useUser()\n const userRef = useRef(user)\n userRef.current = user\n const photos = aiImagePhotosOffered()\n const imageSize = useAiMediaImageSize(orgId)\n const kinds = useMemo(() => aiMediaKindsOffered(photos), [photos])\n const [kindId, setKindId] = useState<AiMediaKindId>(photos ? 'photo' : 'illustration')\n const kind = kinds.find((entry) => entry.id === kindId) ?? kinds[0]\n const mode = kind.mode\n // The site theme's colors need a site; the organization's library names none.\n const [paletteSource, setPaletteSource] = useState<'theme' | 'custom'>(hostId ? 'theme' : 'custom')\n const [colors, setColors] = useState<string[]>(['#1a73e8', '#fbbc04'])\n const [prompt, setPrompt] = useState('')\n const [aspectRatio, setAspectRatio] = useState<AiImageAspectRatio>(kind.aspectRatio)\n const [count, setCount] = useState(1)\n const [busy, setBusy] = useState(false)\n const [notice, setNotice] = useState<{ severity: 'error' | 'warning'; text: string } | null>(null)\n\n useEffect(() => {\n if (open) setNotice(null)\n }, [open])\n\n /** A new kind brings its own shape; the person may still change it. */\n const chooseKind = (next: AiMediaKindId) => {\n setKindId(next)\n const chosen = aiMediaKind(next)\n if (chosen) setAspectRatio(chosen.aspectRatio)\n }\n\n const create = useCallback(async () => {\n const description = prompt.trim()\n if (!description) return\n setBusy(true)\n setNotice(null)\n try {\n const response = await authorizedFetch(userRef.current, '/api/ai/media/images', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n orgId,\n library,\n hostId,\n folderId,\n mode,\n prompt: description,\n aspectRatio,\n count,\n style: kind.id,\n ...(kind.colors === 'palette'\n ? {\n palette:\n paletteSource === 'theme' ? { source: 'theme' } : { source: 'custom', colors },\n }\n : {}),\n }),\n })\n const payload = await response.json().catch(() => null)\n if (!response.ok) {\n const locked = parseLockdownRefusal(response.status, payload)\n setNotice({\n severity: 'error',\n text: locked\n ? lockdownRefusalText(locked)\n : String(payload?.error ?? 'The pictures could not be made — try again.'),\n })\n return\n }\n const ids: string[] = Array.isArray(payload?.mediaIds) ? payload.mediaIds : []\n onCreated(ids)\n const missing = Number(payload?.filtered ?? 0) + Number(payload?.failed ?? 0)\n if (missing > 0) {\n setNotice({\n severity: 'warning',\n text:\n `Added ${ids.length} of ${count} to the library. ` +\n (payload?.warning\n ? String(payload.warning)\n : 'The rest were held back and were not charged.'),\n })\n return\n }\n setPrompt('')\n onClose()\n } catch {\n setNotice({ severity: 'error', text: 'The pictures could not be made — try again.' })\n } finally {\n setBusy(false)\n }\n }, [prompt, orgId, library, hostId, folderId, mode, aspectRatio, count, kind, paletteSource, colors, onCreated, onClose])\n\n return (\n <Dialog open={open} onClose={busy ? undefined : onClose} fullWidth maxWidth=\"sm\">\n <DialogTitle sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>\n {'Create images with AI'}\n <HelpTip {...AI_MEDIA_HELP.dialog} />\n </DialogTitle>\n <DialogContent>\n <Stack spacing={2} sx={{ pt: 1 }}>\n <TextField\n select\n size=\"small\"\n label=\"Kind\"\n value={kind.id}\n onChange={(event) => chooseKind(event.target.value as AiMediaKindId)}\n disabled={busy}\n fullWidth\n helperText={kind.hint}\n slotProps={{\n select: {\n renderValue: (value) => aiMediaKind(String(value))?.label ?? String(value),\n MenuProps: { slotProps: { paper: { sx: { maxHeight: 420 } } } },\n },\n }}\n >\n {kindMenuItems(kinds, imageSize)}\n </TextField>\n <TextField\n label={mode === 'photo' ? 'Describe the picture' : 'Describe what to draw'}\n placeholder={kind.placeholder}\n value={prompt}\n onChange={(event) => setPrompt(event.target.value.slice(0, AI_IMAGE_PROMPT_MAX_CHARS))}\n multiline\n minRows={3}\n autoFocus\n disabled={busy}\n helperText={\n kind.colors === 'describe'\n ? `${AI_MEDIA_DESCRIBE_COLORS_NOTE} The description becomes each picture's alt text, which you can edit.`\n : \"The description becomes each picture's alt text, which you can edit.\"\n }\n />\n {mode === 'photo' ? (\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {AI_MEDIA_RASTER_SAFETY_NOTE}\n </Typography>\n <HelpTip {...AI_MEDIA_HELP.declined} />\n </Stack>\n ) : null}\n <Stack spacing={0.5}>\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Shape'}\n </Typography>\n <HelpTip {...AI_MEDIA_HELP.shape} />\n </Stack>\n <ToggleButtonGroup\n size=\"small\"\n exclusive\n value={aspectRatio}\n onChange={(_event, next) => {\n if (next) setAspectRatio(next)\n }}\n aria-label=\"Shape\"\n disabled={busy}\n sx={{ flexWrap: 'wrap' }}\n >\n {AI_IMAGE_ASPECT_RATIOS.map((ratio) => (\n <ToggleButton key={ratio} value={ratio} aria-label={`${ASPECT_LABELS[ratio]} ${ratio}`}>\n {`${ASPECT_LABELS[ratio]} ${ratio}`}\n </ToggleButton>\n ))}\n </ToggleButtonGroup>\n </Stack>\n {kind.colors === 'palette' ? (\n <Stack spacing={1}>\n <RadioGroup\n value={paletteSource}\n onChange={(event) => setPaletteSource(event.target.value as 'theme' | 'custom')}\n aria-label=\"Colors\"\n >\n <FormControlLabel\n value=\"theme\"\n control={<Radio size=\"small\" />}\n label=\"Use my site's theme colors\"\n disabled={busy || !hostId}\n />\n <FormControlLabel\n value=\"custom\"\n control={<Radio size=\"small\" />}\n label=\"Choose colors\"\n disabled={busy}\n />\n </RadioGroup>\n {paletteSource === 'custom' ? (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center', flexWrap: 'wrap' }}>\n {colors.map((color, index) => (\n <Stack key={index} direction=\"row\" sx={{ alignItems: 'center' }}>\n <TextField\n type=\"color\"\n size=\"small\"\n value={color}\n onChange={(event) =>\n setColors((current) =>\n current.map((value, at) => (at === index ? event.target.value : value)),\n )\n }\n disabled={busy}\n slotProps={{ htmlInput: { 'aria-label': `Color ${index + 1}` } }}\n sx={{ width: 64 }}\n />\n {colors.length > 1 ? (\n <IconButton\n size=\"small\"\n aria-label={`Remove color ${index + 1}`}\n onClick={() => setColors((current) => current.filter((_value, at) => at !== index))}\n disabled={busy}\n >\n {'×'}\n </IconButton>\n ) : null}\n </Stack>\n ))}\n {colors.length < AI_SVG_MAX_COLORS ? (\n <Button size=\"small\" onClick={() => setColors((current) => [...current, '#333333'])} disabled={busy}>\n {'Add a color'}\n </Button>\n ) : null}\n </Stack>\n ) : null}\n </Stack>\n ) : null}\n <TextField\n select\n size=\"small\"\n label=\"How many\"\n value={count}\n onChange={(event) => setCount(Number(event.target.value))}\n disabled={busy}\n sx={{ maxWidth: 160 }}\n >\n {Array.from({ length: AI_IMAGE_MAX_COUNT }, (_unused, index) => index + 1).map((value) => (\n <MenuItem key={value} value={value}>\n {value}\n </MenuItem>\n ))}\n </TextField>\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {aiMediaCreditEstimate(mode, count, imageSize)}\n </Typography>\n <HelpTip {...AI_MEDIA_HELP.credits} />\n </Stack>\n {busy ? (\n <Stack spacing={1}>\n <LinearProgress />\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Making your pictures and adding them to the library…'}\n </Typography>\n </Stack>\n ) : null}\n {notice ? <Alert severity={notice.severity}>{notice.text}</Alert> : null}\n </Stack>\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose} disabled={busy}>\n {'Close'}\n </Button>\n <Button variant=\"contained\" onClick={() => void create()} disabled={busy || !prompt.trim()}>\n {busy ? 'Creating…' : 'Create'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\n\nexport default AiMediaCreateButton\n"],"names":["lockdownRefusalText","parseLockdownRefusal","resolveEffectivePlan","mdiCreation","pluginDocsHelp","HelpTip","MdiIcon","authorizedFetch","useFirestore","useFirestoreDoc","useUser","Alert","Button","Dialog","DialogActions","DialogContent","DialogTitle","FormControlLabel","IconButton","LinearProgress","ListItemText","ListSubheader","MenuItem","Radio","RadioGroup","Stack","TextField","ToggleButton","ToggleButtonGroup","Typography","doc","useCallback","useEffect","useMemo","useRef","useState","aiMediaCreditsPerPicture","AI_MEDIA_KIND_GROUP_LABELS","AI_MEDIA_KIND_GROUPS","aiMediaKind","aiMediaKindsOffered","AI_IMAGE_ASPECT_RATIOS","AI_IMAGE_MAX_COUNT","AI_IMAGE_PROMPT_MAX_CHARS","aiImageSizeForPlan","AI_SVG_MAX_COLORS","aiImagePhotosOffered","ASPECT_LABELS","AI_MEDIA_RASTER_SAFETY_NOTE","AI_MEDIA_DESCRIBE_COLORS_NOTE","kindMenuItems","kinds","size","groups","filter","group","some","kind","item","value","id","sx","gap","primary","label","variant","color","mode","undefined","toLocaleString","length","map","flatMap","AI_MEDIA_HELP","dialog","anchor","excerpt","locked","shape","credits","declined","useAiMediaImageSize","orgId","firestore","data","org","status","aiMediaCreditEstimate","count","each","pictures","AiMediaCreateButton","props","entitled","upgrade","open","setOpen","button","startIcon","path","onClick","onClose","fullWidth","maxWidth","display","alignItems","canManageBilling","href","billingHref","AiMediaCreateDialog","hostId","library","folderId","onCreated","user","userRef","current","photos","imageSize","kindId","setKindId","find","entry","paletteSource","setPaletteSource","colors","setColors","prompt","setPrompt","aspectRatio","setAspectRatio","setCount","busy","setBusy","notice","setNotice","chooseKind","next","chosen","create","description","trim","response","method","headers","body","JSON","stringify","style","palette","source","payload","json","catch","ok","severity","text","String","error","ids","Array","isArray","mediaIds","missing","Number","filtered","failed","warning","spacing","pt","select","onChange","event","target","disabled","helperText","hint","slotProps","renderValue","MenuProps","paper","maxHeight","placeholder","slice","multiline","minRows","autoFocus","direction","exclusive","_event","aria-label","flexWrap","ratio","control","index","type","at","htmlInput","width","_value","from","_unused"],"mappings":"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"}