@aglyn/plugins-ai 1.0.0-beta.234 → 1.0.0-beta.236
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +17 -17
- package/src/lib/activity/ai-activity-actions.d.ts +25 -0
- package/src/lib/activity/ai-activity-actions.js +85 -4
- package/src/lib/activity/ai-activity-actions.js.map +1 -1
- package/src/lib/components/ai-brief-dialog.component.js +46 -2
- package/src/lib/components/ai-brief-dialog.component.js.map +1 -1
- package/src/lib/components/ai-campaign-create.component.js +1 -1
- package/src/lib/components/ai-campaign-create.component.js.map +1 -1
- package/src/lib/components/ai-credits-card.component.js +3 -3
- package/src/lib/components/ai-credits-card.component.js.map +1 -1
- package/src/lib/components/ai-crm-email-draft.component.js +1 -1
- package/src/lib/components/ai-crm-email-draft.component.js.map +1 -1
- package/src/lib/components/ai-crm-import-mapping.component.js +1 -1
- package/src/lib/components/ai-crm-import-mapping.component.js.map +1 -1
- package/src/lib/components/ai-crm-record-card.component.js +1 -1
- package/src/lib/components/ai-crm-record-card.component.js.map +1 -1
- package/src/lib/components/ai-describe-automation.component.js +4 -2
- package/src/lib/components/ai-describe-automation.component.js.map +1 -1
- package/src/lib/components/ai-describe-org-automation.component.js +1 -1
- package/src/lib/components/ai-describe-org-automation.component.js.map +1 -1
- package/src/lib/components/ai-experiment-cards.component.js +2 -2
- package/src/lib/components/ai-experiment-cards.component.js.map +1 -1
- package/src/lib/components/ai-explain-automation.component.js +1 -1
- package/src/lib/components/ai-explain-automation.component.js.map +1 -1
- package/src/lib/components/ai-insight-card.component.js +3 -1
- package/src/lib/components/ai-insight-card.component.js.map +1 -1
- package/src/lib/components/ai-jobs-list-page.component.d.ts +6 -1
- package/src/lib/components/ai-jobs-list-page.component.js +15 -2
- package/src/lib/components/ai-jobs-list-page.component.js.map +1 -1
- package/src/lib/components/ai-logic.component.js +5 -3
- package/src/lib/components/ai-logic.component.js.map +1 -1
- package/src/lib/components/ai-media-create.component.js +88 -16
- package/src/lib/components/ai-media-create.component.js.map +1 -1
- package/src/lib/components/ai-model-selector.component.js +8 -0
- package/src/lib/components/ai-model-selector.component.js.map +1 -1
- package/src/lib/components/ai-overlay-cards.component.js +2 -2
- package/src/lib/components/ai-overlay-cards.component.js.map +1 -1
- package/src/lib/components/ai-product-copy-card.component.js +2 -1
- package/src/lib/components/ai-product-copy-card.component.js.map +1 -1
- package/src/lib/components/ai-products-hub-card.component.js +2 -1
- package/src/lib/components/ai-products-hub-card.component.js.map +1 -1
- package/src/lib/components/ai-revise-automation.component.js +1 -1
- package/src/lib/components/ai-revise-automation.component.js.map +1 -1
- package/src/lib/components/ai-seo-fields-card.component.js +7 -3
- package/src/lib/components/ai-seo-fields-card.component.js.map +1 -1
- package/src/lib/components/ai-site-batch-card.component.js +7 -4
- package/src/lib/components/ai-site-batch-card.component.js.map +1 -1
- package/src/lib/components/ai-site-build-page.component.js +7 -3
- package/src/lib/components/ai-site-build-page.component.js.map +1 -1
- package/src/lib/components/ai-site-seo-start-card.component.js +7 -4
- package/src/lib/components/ai-site-seo-start-card.component.js.map +1 -1
- package/src/lib/components/ai-site-start-card.component.js +62 -29
- package/src/lib/components/ai-site-start-card.component.js.map +1 -1
- package/src/lib/components/ai-theme-proposal-card.component.js +1 -0
- package/src/lib/components/ai-theme-proposal-card.component.js.map +1 -1
- package/src/lib/components/ai-upsell-dialog.component.js +17 -3
- package/src/lib/components/ai-upsell-dialog.component.js.map +1 -1
- package/src/lib/components/ai-usage-strip.component.js +13 -2
- package/src/lib/components/ai-usage-strip.component.js.map +1 -1
- package/src/lib/components/assist-build-card.component.js +20 -3
- package/src/lib/components/assist-build-card.component.js.map +1 -1
- package/src/lib/components/assist-jobs-drawer.component.js +7 -1
- package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
- package/src/lib/components/billing-ai-allotments.component.js +2 -2
- package/src/lib/components/billing-ai-allotments.component.js.map +1 -1
- package/src/lib/components/billing-ai-top-users.component.js +1 -0
- package/src/lib/components/billing-ai-top-users.component.js.map +1 -1
- package/src/lib/components/billing-assist-overage-card.component.js +2 -2
- package/src/lib/components/billing-assist-overage-card.component.js.map +1 -1
- package/src/lib/components/host-ai-allotments.component.js +2 -2
- package/src/lib/components/host-ai-allotments.component.js.map +1 -1
- package/src/lib/components/member-ai-allotment-card.component.js +2 -2
- package/src/lib/components/member-ai-allotment-card.component.js.map +1 -1
- package/src/lib/components/staff-org-ai-card.component.js +1 -0
- package/src/lib/components/staff-org-ai-card.component.js.map +1 -1
- package/src/lib/components/staff-org-ai-conversations.component.d.ts +9 -3
- package/src/lib/components/staff-org-ai-conversations.component.js +174 -83
- package/src/lib/components/staff-org-ai-conversations.component.js.map +1 -1
- package/src/lib/components/staff-user-ai-usage-card.component.js +2 -1
- package/src/lib/components/staff-user-ai-usage-card.component.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-language.js +4 -1
- package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-site-pages.d.ts +12 -0
- package/src/lib/jobs/ai-job-layout-site-pages.js +20 -0
- package/src/lib/jobs/ai-job-layout-site-pages.js.map +1 -1
- package/src/lib/jobs/ai-job-page-language.d.ts +10 -1
- package/src/lib/jobs/ai-job-page-language.js +41 -8
- package/src/lib/jobs/ai-job-page-language.js.map +1 -1
- package/src/lib/jobs/ai-job-page-step.js +14 -3
- package/src/lib/jobs/ai-job-page-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-content.d.ts +75 -7
- package/src/lib/jobs/ai-job-site-content.js +205 -32
- package/src/lib/jobs/ai-job-site-content.js.map +1 -1
- package/src/lib/jobs/ai-job-site-step.d.ts +8 -0
- package/src/lib/jobs/ai-job-site-step.js +61 -12
- package/src/lib/jobs/ai-job-site-step.js.map +1 -1
- package/src/lib/layout-language/ai-layout-compiler.d.ts +8 -0
- package/src/lib/layout-language/ai-layout-compiler.js +308 -10
- package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
- package/src/lib/layout-language/ai-layout-design.d.ts +7 -0
- package/src/lib/layout-language/ai-layout-design.js +23 -11
- package/src/lib/layout-language/ai-layout-design.js.map +1 -1
- package/src/lib/layout-language/ai-layout-frame.d.ts +6 -0
- package/src/lib/layout-language/ai-layout-frame.js +12 -3
- package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
- package/src/lib/layout-language/ai-layout-gaps.js +18 -2
- package/src/lib/layout-language/ai-layout-gaps.js.map +1 -1
- package/src/lib/layout-language/ai-layout-links.d.ts +26 -1
- package/src/lib/layout-language/ai-layout-links.js +24 -4
- package/src/lib/layout-language/ai-layout-links.js.map +1 -1
- package/src/lib/layout-language/ai-layout-listings.d.ts +125 -0
- package/src/lib/layout-language/ai-layout-listings.js +187 -0
- package/src/lib/layout-language/ai-layout-listings.js.map +1 -0
- package/src/lib/model/ai-site-build-progress.js +27 -12
- package/src/lib/model/ai-site-build-progress.js.map +1 -1
- package/src/lib/model/ai-site-job.d.ts +33 -8
- package/src/lib/model/ai-site-job.js +38 -18
- package/src/lib/model/ai-site-job.js.map +1 -1
- package/src/lib/model/ai-site-kinds.d.ts +30 -8
- package/src/lib/model/ai-site-kinds.js +731 -117
- package/src/lib/model/ai-site-kinds.js.map +1 -1
- package/src/lib/model/ai-site-start-seo.d.ts +30 -0
- package/src/lib/model/ai-site-start-seo.js +132 -11
- package/src/lib/model/ai-site-start-seo.js.map +1 -1
- package/src/lib/model/ai-site-start.d.ts +2 -2
- package/src/lib/model/ai-site-start.js +3 -3
- package/src/lib/model/ai-site-start.js.map +1 -1
- package/src/lib/plugin.js +15 -3
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/runtime/ai-palette.generated.js +13 -3
- package/src/lib/runtime/ai-palette.generated.js.map +1 -1
- package/src/lib/server/ai-admin-conversations.d.ts +9 -0
- package/src/lib/server/ai-admin-conversations.js +151 -9
- package/src/lib/server/ai-admin-conversations.js.map +1 -1
- package/src/lib/usage/staff-org-ai-conversations.d.ts +23 -0
- package/src/lib/usage/staff-org-ai-conversations.js +45 -0
- 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-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 {
|
|
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__*/
|
|
113
|
-
|
|
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__*/
|
|
266
|
-
|
|
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__*/
|
|
316
|
-
|
|
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:
|
|
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__*/
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
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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"}
|
|
@@ -14,10 +14,17 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/ 'use client';
|
|
17
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
17
18
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
19
|
+
import { pluginDocsHelp } from "@aglyn/aglyn/app-utils/docs-help";
|
|
20
|
+
import { HelpTip } from "@aglyn/shared-ui-jsx";
|
|
18
21
|
import { Button, ListItemText, Menu, MenuItem } from "@mui/material";
|
|
19
22
|
import { useState } from "react";
|
|
20
23
|
const perRequest = (credits)=>`≈ ${credits.toLocaleString()} credit${credits === 1 ? '' : 's'} a request`;
|
|
24
|
+
/** The Model switch's own section of the allotments guide (AGL-3660). */ const AI_MODEL_HELP = pluginDocsHelp('aiAllotments', {
|
|
25
|
+
anchor: '#choosing-a-model',
|
|
26
|
+
excerpt: 'Auto picks a model for each request. Choosing one shows what a typical request costs on it; Free workspaces always run on Auto.'
|
|
27
|
+
});
|
|
21
28
|
/**
|
|
22
29
|
* THE MODEL SWITCH (AGL-2942): Auto, and the models the reader's plan, the
|
|
23
30
|
* workspace's restriction and their allotment allow — each with what a
|
|
@@ -58,6 +65,7 @@ const perRequest = (credits)=>`≈ ${credits.toLocaleString()} credit${credits =
|
|
|
58
65
|
},
|
|
59
66
|
children: `Model: ${choice.label}`
|
|
60
67
|
}),
|
|
68
|
+
/*#__PURE__*/ _jsx(HelpTip, _extends({}, AI_MODEL_HELP)),
|
|
61
69
|
/*#__PURE__*/ _jsxs(Menu, {
|
|
62
70
|
anchorEl: anchor,
|
|
63
71
|
open: Boolean(anchor),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-model-selector.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 { Button, ListItemText, Menu, MenuItem } from '@mui/material'\nimport { useState, type MouseEvent } from 'react'\nimport type { AiModelChoiceState } from './use-ai-model-choice'\n\nexport interface AiModelSelectorProps {\n choice: AiModelChoiceState\n disabled?: boolean\n}\n\nconst perRequest = (credits: number): string =>\n `≈ ${credits.toLocaleString()} credit${credits === 1 ? '' : 's'} a request`\n\n/**\n * THE MODEL SWITCH (AGL-2942): Auto, and the models the reader's plan, the\n * workspace's restriction and their allotment allow — each with what a\n * typical request costs on it and the multiple of Auto.\n *\n * Every label and id comes from the provider catalog through the options\n * route; this component names no model. The pick is remembered per person\n * per surface (`use-ai-model-choice.ts`), and the door the request goes to\n * decides again, so a stale pick runs on Auto rather than on a model the\n * reader may no longer have.\n */\nexport function AiModelSelector({ choice, disabled }: AiModelSelectorProps) {\n const [anchor, setAnchor] = useState<HTMLElement | null>(null)\n const open = (event: MouseEvent<HTMLElement>) => {\n setAnchor(event.currentTarget)\n choice.load()\n }\n const close = () => setAnchor(null)\n const pick = (option: { id: string; label: string } | null) => {\n choice.select(option)\n close()\n }\n const { options, status } = choice\n return (\n <>\n <Button\n size=\"small\"\n color=\"inherit\"\n onClick={open}\n disabled={disabled}\n aria-haspopup=\"menu\"\n aria-expanded={Boolean(anchor)}\n aria-label={`AI model: ${choice.label}`}\n sx={{ textTransform: 'none', minWidth: 0, px: 1, color: 'text.secondary' }}\n >\n {`Model: ${choice.label}`}\n </Button>\n <Menu anchorEl={anchor} open={Boolean(anchor)} onClose={close}>\n {status === 'loading' || status === 'idle' ? (\n <MenuItem disabled>{'Loading models…'}</MenuItem>\n ) : null}\n {status === 'refused' ? (\n <MenuItem disabled>{'Your role does not include AI assistance'}</MenuItem>\n ) : null}\n {status === 'error' ? (\n <MenuItem disabled>{'The models could not be loaded — try again'}</MenuItem>\n ) : null}\n {status === 'ready' && options?.auto ? (\n <MenuItem selected={choice.model === null} onClick={() => pick(null)}>\n <ListItemText\n primary={options.auto.label}\n secondary={`${perRequest(options.auto.creditsPerRequest)} · picked for each request`}\n />\n </MenuItem>\n ) : null}\n {status === 'ready' && options\n ? options.options.map((option) => (\n <MenuItem\n key={option.id}\n selected={choice.model === option.id}\n onClick={() => pick({ id: option.id, label: option.label })}\n >\n <ListItemText\n primary={option.label}\n secondary={`${perRequest(option.creditsPerRequest)} · ${option.multiplier}× Auto`}\n />\n </MenuItem>\n ))\n : null}\n {status === 'ready' && options && !options.options.length ? (\n <MenuItem disabled>{'This workspace runs on Auto'}</MenuItem>\n ) : null}\n </Menu>\n </>\n )\n}\nAiModelSelector.displayName = 'AiModelSelector'\n\nexport default AiModelSelector\n"],"names":["Button","ListItemText","Menu","MenuItem","useState","perRequest","credits","toLocaleString","AiModelSelector","choice","disabled","
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-model-selector.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 { pluginDocsHelp } from '@aglyn/aglyn/app-utils/docs-help'\nimport { HelpTip } from '@aglyn/shared-ui-jsx'\nimport { Button, ListItemText, Menu, MenuItem } from '@mui/material'\nimport { useState, type MouseEvent } from 'react'\nimport type { AiModelChoiceState } from './use-ai-model-choice'\n\nexport interface AiModelSelectorProps {\n choice: AiModelChoiceState\n disabled?: boolean\n}\n\nconst perRequest = (credits: number): string =>\n `≈ ${credits.toLocaleString()} credit${credits === 1 ? '' : 's'} a request`\n\n/** The Model switch's own section of the allotments guide (AGL-3660). */\nconst AI_MODEL_HELP = pluginDocsHelp('aiAllotments', {\n anchor: '#choosing-a-model',\n excerpt:\n 'Auto picks a model for each request. Choosing one shows what a typical request costs on it; Free workspaces always run on Auto.',\n})\n\n/**\n * THE MODEL SWITCH (AGL-2942): Auto, and the models the reader's plan, the\n * workspace's restriction and their allotment allow — each with what a\n * typical request costs on it and the multiple of Auto.\n *\n * Every label and id comes from the provider catalog through the options\n * route; this component names no model. The pick is remembered per person\n * per surface (`use-ai-model-choice.ts`), and the door the request goes to\n * decides again, so a stale pick runs on Auto rather than on a model the\n * reader may no longer have.\n */\nexport function AiModelSelector({ choice, disabled }: AiModelSelectorProps) {\n const [anchor, setAnchor] = useState<HTMLElement | null>(null)\n const open = (event: MouseEvent<HTMLElement>) => {\n setAnchor(event.currentTarget)\n choice.load()\n }\n const close = () => setAnchor(null)\n const pick = (option: { id: string; label: string } | null) => {\n choice.select(option)\n close()\n }\n const { options, status } = choice\n return (\n <>\n <Button\n size=\"small\"\n color=\"inherit\"\n onClick={open}\n disabled={disabled}\n aria-haspopup=\"menu\"\n aria-expanded={Boolean(anchor)}\n aria-label={`AI model: ${choice.label}`}\n sx={{ textTransform: 'none', minWidth: 0, px: 1, color: 'text.secondary' }}\n >\n {`Model: ${choice.label}`}\n </Button>\n <HelpTip {...AI_MODEL_HELP} />\n <Menu anchorEl={anchor} open={Boolean(anchor)} onClose={close}>\n {status === 'loading' || status === 'idle' ? (\n <MenuItem disabled>{'Loading models…'}</MenuItem>\n ) : null}\n {status === 'refused' ? (\n <MenuItem disabled>{'Your role does not include AI assistance'}</MenuItem>\n ) : null}\n {status === 'error' ? (\n <MenuItem disabled>{'The models could not be loaded — try again'}</MenuItem>\n ) : null}\n {status === 'ready' && options?.auto ? (\n <MenuItem selected={choice.model === null} onClick={() => pick(null)}>\n <ListItemText\n primary={options.auto.label}\n secondary={`${perRequest(options.auto.creditsPerRequest)} · picked for each request`}\n />\n </MenuItem>\n ) : null}\n {status === 'ready' && options\n ? options.options.map((option) => (\n <MenuItem\n key={option.id}\n selected={choice.model === option.id}\n onClick={() => pick({ id: option.id, label: option.label })}\n >\n <ListItemText\n primary={option.label}\n secondary={`${perRequest(option.creditsPerRequest)} · ${option.multiplier}× Auto`}\n />\n </MenuItem>\n ))\n : null}\n {status === 'ready' && options && !options.options.length ? (\n <MenuItem disabled>{'This workspace runs on Auto'}</MenuItem>\n ) : null}\n </Menu>\n </>\n )\n}\nAiModelSelector.displayName = 'AiModelSelector'\n\nexport default AiModelSelector\n"],"names":["pluginDocsHelp","HelpTip","Button","ListItemText","Menu","MenuItem","useState","perRequest","credits","toLocaleString","AI_MODEL_HELP","anchor","excerpt","AiModelSelector","choice","disabled","setAnchor","open","event","currentTarget","load","close","pick","option","select","options","status","size","color","onClick","aria-haspopup","aria-expanded","Boolean","aria-label","label","sx","textTransform","minWidth","px","anchorEl","onClose","auto","selected","model","primary","secondary","creditsPerRequest","map","id","multiplier","length","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAEA,SAASA,cAAc,QAAQ,mCAAkC;AACjE,SAASC,OAAO,QAAQ,uBAAsB;AAC9C,SAASC,MAAM,EAAEC,YAAY,EAAEC,IAAI,EAAEC,QAAQ,QAAQ,gBAAe;AACpE,SAASC,QAAQ,QAAyB,QAAO;AAQjD,MAAMC,aAAa,CAACC,UAClB,CAAC,EAAE,EAAEA,QAAQC,cAAc,GAAG,OAAO,EAAED,YAAY,IAAI,KAAK,IAAI,UAAU,CAAC;AAE7E,uEAAuE,GACvE,MAAME,gBAAgBV,eAAe,gBAAgB;IACnDW,QAAQ;IACRC,SACE;AACJ;AAEA;;;;;;;;;;CAUC,GACD,OAAO,SAASC,gBAAgB,EAAEC,MAAM,EAAEC,QAAQ,EAAwB;IACxE,MAAM,CAACJ,QAAQK,UAAU,GAAGV,SAA6B;IACzD,MAAMW,OAAO,CAACC;QACZF,UAAUE,MAAMC,aAAa;QAC7BL,OAAOM,IAAI;IACb;IACA,MAAMC,QAAQ,IAAML,UAAU;IAC9B,MAAMM,OAAO,CAACC;QACZT,OAAOU,MAAM,CAACD;QACdF;IACF;IACA,MAAM,EAAEI,OAAO,EAAEC,MAAM,EAAE,GAAGZ;IAC5B,qBACE;;0BACE,KAACZ;gBACCyB,MAAK;gBACLC,OAAM;gBACNC,SAASZ;gBACTF,UAAUA;gBACVe,iBAAc;gBACdC,iBAAeC,QAAQrB;gBACvBsB,cAAY,CAAC,UAAU,EAAEnB,OAAOoB,KAAK,EAAE;gBACvCC,IAAI;oBAAEC,eAAe;oBAAQC,UAAU;oBAAGC,IAAI;oBAAGV,OAAO;gBAAiB;0BAExE,CAAC,OAAO,EAAEd,OAAOoB,KAAK,EAAE;;0BAE3B,KAACjC,sBAAYS;0BACb,MAACN;gBAAKmC,UAAU5B;gBAAQM,MAAMe,QAAQrB;gBAAS6B,SAASnB;;oBACrDK,WAAW,aAAaA,WAAW,uBAClC,KAACrB;wBAASU,QAAQ;kCAAE;yBAClB;oBACHW,WAAW,0BACV,KAACrB;wBAASU,QAAQ;kCAAE;yBAClB;oBACHW,WAAW,wBACV,KAACrB;wBAASU,QAAQ;kCAAE;yBAClB;oBACHW,WAAW,YAAWD,2BAAAA,QAASgB,IAAI,kBAClC,KAACpC;wBAASqC,UAAU5B,OAAO6B,KAAK,KAAK;wBAAMd,SAAS,IAAMP,KAAK;kCAC7D,cAAA,KAACnB;4BACCyC,SAASnB,QAAQgB,IAAI,CAACP,KAAK;4BAC3BW,WAAW,GAAGtC,WAAWkB,QAAQgB,IAAI,CAACK,iBAAiB,EAAE,0BAA0B,CAAC;;yBAGtF;oBACHpB,WAAW,WAAWD,UACnBA,QAAQA,OAAO,CAACsB,GAAG,CAAC,CAACxB,uBACnB,KAAClB;4BAECqC,UAAU5B,OAAO6B,KAAK,KAAKpB,OAAOyB,EAAE;4BACpCnB,SAAS,IAAMP,KAAK;oCAAE0B,IAAIzB,OAAOyB,EAAE;oCAAEd,OAAOX,OAAOW,KAAK;gCAAC;sCAEzD,cAAA,KAAC/B;gCACCyC,SAASrB,OAAOW,KAAK;gCACrBW,WAAW,GAAGtC,WAAWgB,OAAOuB,iBAAiB,EAAE,GAAG,EAAEvB,OAAO0B,UAAU,CAAC,MAAM,CAAC;;2BAN9E1B,OAAOyB,EAAE,KAUlB;oBACHtB,WAAW,WAAWD,WAAW,CAACA,QAAQA,OAAO,CAACyB,MAAM,iBACvD,KAAC7C;wBAASU,QAAQ;kCAAE;yBAClB;;;;;AAIZ;AACAF,gBAAgBsC,WAAW,GAAG;AAE9B,eAAetC,gBAAe"}
|
|
@@ -226,7 +226,7 @@ const overlayHelp = (anchor, excerpt)=>pluginDocsHelp('aiMarketing', {
|
|
|
226
226
|
target: "_blank",
|
|
227
227
|
rel: "noopener",
|
|
228
228
|
variant: "caption",
|
|
229
|
-
title: help.
|
|
229
|
+
title: help.excerptText,
|
|
230
230
|
children: 'How it works'
|
|
231
231
|
})
|
|
232
232
|
]
|
|
@@ -438,7 +438,7 @@ AiOverlayEditorCard.displayName = 'AiOverlayEditorCard';
|
|
|
438
438
|
href: help.href,
|
|
439
439
|
target: "_blank",
|
|
440
440
|
rel: "noopener",
|
|
441
|
-
title: help.
|
|
441
|
+
title: help.excerptText,
|
|
442
442
|
children: 'How it works'
|
|
443
443
|
})
|
|
444
444
|
]
|