@aglyn/plugins-ai 1.0.0-beta.236 → 1.0.0-beta.238
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +17 -17
- package/src/lib/components/ai-credits-prompt.component.d.ts +44 -0
- package/src/lib/components/ai-credits-prompt.component.js +117 -0
- package/src/lib/components/ai-credits-prompt.component.js.map +1 -0
- package/src/lib/components/ai-job-cancel.component.d.ts +38 -0
- package/src/lib/components/ai-job-cancel.component.js +156 -0
- package/src/lib/components/ai-job-cancel.component.js.map +1 -0
- package/src/lib/components/ai-job-plan.component.d.ts +5 -4
- package/src/lib/components/ai-job-plan.component.js +48 -12
- package/src/lib/components/ai-job-plan.component.js.map +1 -1
- package/src/lib/components/ai-job-requests.d.ts +10 -0
- package/src/lib/components/ai-job-requests.js +12 -4
- package/src/lib/components/ai-job-requests.js.map +1 -1
- package/src/lib/components/ai-jobs-list-page.component.js +141 -72
- package/src/lib/components/ai-jobs-list-page.component.js.map +1 -1
- package/src/lib/components/ai-site-build-page.component.js +48 -9
- package/src/lib/components/ai-site-build-page.component.js.map +1 -1
- package/src/lib/components/ai-site-start-card.component.js +68 -22
- package/src/lib/components/ai-site-start-card.component.js.map +1 -1
- package/src/lib/components/ai-usage-strip.component.d.ts +19 -2
- package/src/lib/components/ai-usage-strip.component.js +40 -9
- package/src/lib/components/ai-usage-strip.component.js.map +1 -1
- package/src/lib/components/assist-build-card.component.d.ts +3 -1
- package/src/lib/components/assist-build-card.component.js +58 -7
- package/src/lib/components/assist-build-card.component.js.map +1 -1
- package/src/lib/components/assist-jobs-drawer.component.js +66 -22
- package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
- package/src/lib/components/assist-panel.component.js +89 -52
- package/src/lib/components/assist-panel.component.js.map +1 -1
- package/src/lib/jobs/ai-job-admission.d.ts +22 -2
- package/src/lib/jobs/ai-job-admission.js.map +1 -1
- package/src/lib/jobs/ai-job-build-step.d.ts +24 -11
- package/src/lib/jobs/ai-job-build-step.js +54 -35
- package/src/lib/jobs/ai-job-build-step.js.map +1 -1
- package/src/lib/jobs/ai-job-cancel.d.ts +71 -0
- package/src/lib/jobs/ai-job-cancel.js +102 -0
- package/src/lib/jobs/ai-job-cancel.js.map +1 -0
- package/src/lib/jobs/ai-job-component-step.js +4 -1
- package/src/lib/jobs/ai-job-component-step.js.map +1 -1
- package/src/lib/jobs/ai-job-drafts.js +2 -0
- package/src/lib/jobs/ai-job-drafts.js.map +1 -1
- package/src/lib/jobs/ai-job-form-step.js +4 -1
- package/src/lib/jobs/ai-job-form-step.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-language.d.ts +2 -0
- package/src/lib/jobs/ai-job-layout-language.js +13 -1
- package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-step.js +6 -1
- package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
- package/src/lib/jobs/ai-job-page-language.js +12 -0
- package/src/lib/jobs/ai-job-page-language.js.map +1 -1
- package/src/lib/jobs/ai-job-page-step.d.ts +13 -0
- package/src/lib/jobs/ai-job-page-step.js +46 -4
- package/src/lib/jobs/ai-job-page-step.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-step.d.ts +42 -0
- package/src/lib/jobs/ai-job-plan-step.js +118 -18
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-content.d.ts +49 -3
- package/src/lib/jobs/ai-job-site-content.js +196 -37
- package/src/lib/jobs/ai-job-site-content.js.map +1 -1
- package/src/lib/jobs/ai-job-site-step.js +49 -16
- package/src/lib/jobs/ai-job-site-step.js.map +1 -1
- package/src/lib/jobs/ai-job-template-step.js +4 -1
- package/src/lib/jobs/ai-job-template-step.js.map +1 -1
- package/src/lib/jobs/ai-job-text-step.d.ts +8 -0
- package/src/lib/jobs/ai-job-text-step.js.map +1 -1
- package/src/lib/jobs/ai-jobs.d.ts +55 -13
- package/src/lib/jobs/ai-jobs.js +213 -41
- package/src/lib/jobs/ai-jobs.js.map +1 -1
- package/src/lib/jobs/ai-layout-stock-photos.d.ts +194 -34
- package/src/lib/jobs/ai-layout-stock-photos.js +861 -146
- package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
- package/src/lib/jobs/fixtures/ai-ceramics-portfolio-site-plan.d.ts +30 -0
- package/src/lib/jobs/fixtures/ai-ceramics-portfolio-site-plan.js +220 -0
- package/src/lib/jobs/fixtures/ai-ceramics-portfolio-site-plan.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-pixabay-recordings.d.ts +27 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-pixabay-recordings.js +151 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-pixabay-recordings.js.map +1 -0
- package/src/lib/layout-language/ai-layout-compiler.d.ts +33 -0
- package/src/lib/layout-language/ai-layout-compiler.js +381 -18
- package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
- package/src/lib/layout-language/ai-layout-design.d.ts +6 -3
- package/src/lib/layout-language/ai-layout-design.js +5 -3
- package/src/lib/layout-language/ai-layout-design.js.map +1 -1
- package/src/lib/layout-language/ai-layout-frame.d.ts +12 -0
- package/src/lib/layout-language/ai-layout-frame.js +58 -3
- package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
- package/src/lib/layout-language/ai-layout-gaps.js +3 -1
- package/src/lib/layout-language/ai-layout-gaps.js.map +1 -1
- package/src/lib/layout-language/ai-layout-language.js +1 -1
- package/src/lib/layout-language/ai-layout-language.js.map +1 -1
- package/src/lib/layout-language/ai-layout-listings.d.ts +49 -1
- package/src/lib/layout-language/ai-layout-listings.js +117 -47
- package/src/lib/layout-language/ai-layout-listings.js.map +1 -1
- package/src/lib/layout-language/ai-layout-pictures.d.ts +10 -1
- package/src/lib/layout-language/ai-layout-pictures.js +5 -2
- package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
- package/src/lib/layout-language/ai-layout-storefront.d.ts +82 -0
- package/src/lib/layout-language/ai-layout-storefront.js +223 -0
- package/src/lib/layout-language/ai-layout-storefront.js.map +1 -0
- package/src/lib/model/ai-build-job.d.ts +39 -0
- package/src/lib/model/ai-build-job.js +100 -1
- package/src/lib/model/ai-build-job.js.map +1 -1
- package/src/lib/model/ai-build-progress.d.ts +8 -0
- package/src/lib/model/ai-build-progress.js +35 -0
- package/src/lib/model/ai-build-progress.js.map +1 -1
- package/src/lib/model/ai-credit-estimate.d.ts +249 -0
- package/src/lib/model/ai-credit-estimate.js +278 -0
- package/src/lib/model/ai-credit-estimate.js.map +1 -0
- package/src/lib/model/ai-job-cancel-copy.d.ts +44 -0
- package/src/lib/model/ai-job-cancel-copy.js +53 -0
- package/src/lib/model/ai-job-cancel-copy.js.map +1 -0
- package/src/lib/model/ai-job-failure-copy.d.ts +4 -1
- package/src/lib/model/ai-job-failure-copy.js +8 -3
- package/src/lib/model/ai-job-failure-copy.js.map +1 -1
- package/src/lib/model/ai-jobs.types.d.ts +35 -0
- package/src/lib/model/ai-jobs.types.js.map +1 -1
- package/src/lib/model/ai-site-build-progress.js +7 -4
- package/src/lib/model/ai-site-build-progress.js.map +1 -1
- package/src/lib/model/ai-site-job.d.ts +76 -22
- package/src/lib/model/ai-site-job.js +125 -23
- package/src/lib/model/ai-site-job.js.map +1 -1
- package/src/lib/model/ai-site-kinds.d.ts +4 -1
- package/src/lib/model/ai-site-kinds.js +35 -7
- package/src/lib/model/ai-site-kinds.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.d.ts +37 -1
- package/src/lib/runtime/ai-doctrine-validators.js +161 -7
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-doctrine.js +4 -3
- package/src/lib/runtime/ai-doctrine.js.map +1 -1
- package/src/lib/runtime/ai-node-tree.d.ts +11 -0
- package/src/lib/runtime/ai-node-tree.js +26 -0
- package/src/lib/runtime/ai-node-tree.js.map +1 -1
- package/src/lib/runtime/ai-palette.generated.js +592 -14
- package/src/lib/runtime/ai-palette.generated.js.map +1 -1
- package/src/lib/server/ai-jobs-cancel.d.ts +13 -5
- package/src/lib/server/ai-jobs-cancel.js +27 -9
- package/src/lib/server/ai-jobs-cancel.js.map +1 -1
- package/src/lib/server/ai-jobs-gate.d.ts +12 -2
- package/src/lib/server/ai-jobs-gate.js +20 -9
- package/src/lib/server/ai-jobs-gate.js.map +1 -1
- package/src/lib/server/ai-jobs-resume.js +93 -35
- package/src/lib/server/ai-jobs-resume.js.map +1 -1
- package/src/lib/server/ai-jobs-route.js +45 -4
- package/src/lib/server/ai-jobs-route.js.map +1 -1
- package/src/lib/server/assist-chat.js +4 -1
- package/src/lib/server/assist-chat.js.map +1 -1
- package/src/lib/server/assist-edit.js +3 -1
- package/src/lib/server/assist-edit.js.map +1 -1
- package/src/lib/server/assist-music.d.ts +36 -0
- package/src/lib/server/assist-music.js +36 -0
- package/src/lib/server/assist-music.js.map +1 -0
- package/src/lib/server.js +6 -0
- package/src/lib/server.js.map +1 -1
- package/src/lib/usage/ai-usage-meter.d.ts +2 -1
- package/src/lib/usage/ai-usage-meter.js +17 -1
- package/src/lib/usage/ai-usage-meter.js.map +1 -1
- package/src/lib/usage/ai-usage-wire.d.ts +6 -0
- package/src/lib/usage/ai-usage-wire.js.map +1 -1
- package/src/lib/usage/assist-usage.d.ts +7 -0
- package/src/lib/usage/assist-usage.js +14 -4
- package/src/lib/usage/assist-usage.js.map +1 -1
- package/src/lib/usage/free-ai-credits-left.d.ts +7 -0
- package/src/lib/usage/free-ai-credits-left.js +4 -2
- package/src/lib/usage/free-ai-credits-left.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aglyn/plugins-ai",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.238",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "https://aglyn.com",
|
|
6
6
|
"repository": {
|
|
@@ -25,22 +25,22 @@
|
|
|
25
25
|
"./package.json": "./package.json"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@aglyn/aglyn": "1.0.0-beta.
|
|
29
|
-
"@aglyn/shared-data-enums": "1.0.0-beta.
|
|
30
|
-
"@aglyn/shared-data-mdi": "1.0.0-beta.
|
|
31
|
-
"@aglyn/shared-data-types": "1.0.0-beta.
|
|
32
|
-
"@aglyn/shared-ui-email-campaigns": "1.0.0-beta.
|
|
33
|
-
"@aglyn/shared-ui-jsx": "1.0.0-beta.
|
|
34
|
-
"@aglyn/shared-ui-snackstack": "1.0.0-beta.
|
|
35
|
-
"@aglyn/shared-ui-theme": "1.0.0-beta.
|
|
36
|
-
"@aglyn/shared-util-email": "1.0.0-beta.
|
|
37
|
-
"@aglyn/shared-util-errors": "1.0.0-beta.
|
|
38
|
-
"@aglyn/shared-util-http": "1.0.0-beta.
|
|
39
|
-
"@aglyn/shared-util-timestamp": "1.0.0-beta.
|
|
40
|
-
"@aglyn/shared-util-tools": "1.0.0-beta.
|
|
41
|
-
"@aglyn/tenant-data-admin": "1.0.0-beta.
|
|
42
|
-
"@aglyn/tenant-feature-instance": "1.0.0-beta.
|
|
43
|
-
"@aglyn/tenant-runtime": "1.0.0-beta.
|
|
28
|
+
"@aglyn/aglyn": "1.0.0-beta.238",
|
|
29
|
+
"@aglyn/shared-data-enums": "1.0.0-beta.238",
|
|
30
|
+
"@aglyn/shared-data-mdi": "1.0.0-beta.238",
|
|
31
|
+
"@aglyn/shared-data-types": "1.0.0-beta.238",
|
|
32
|
+
"@aglyn/shared-ui-email-campaigns": "1.0.0-beta.238",
|
|
33
|
+
"@aglyn/shared-ui-jsx": "1.0.0-beta.238",
|
|
34
|
+
"@aglyn/shared-ui-snackstack": "1.0.0-beta.238",
|
|
35
|
+
"@aglyn/shared-ui-theme": "1.0.0-beta.238",
|
|
36
|
+
"@aglyn/shared-util-email": "1.0.0-beta.238",
|
|
37
|
+
"@aglyn/shared-util-errors": "1.0.0-beta.238",
|
|
38
|
+
"@aglyn/shared-util-http": "1.0.0-beta.238",
|
|
39
|
+
"@aglyn/shared-util-timestamp": "1.0.0-beta.238",
|
|
40
|
+
"@aglyn/shared-util-tools": "1.0.0-beta.238",
|
|
41
|
+
"@aglyn/tenant-data-admin": "1.0.0-beta.238",
|
|
42
|
+
"@aglyn/tenant-feature-instance": "1.0.0-beta.238",
|
|
43
|
+
"@aglyn/tenant-runtime": "1.0.0-beta.238",
|
|
44
44
|
"@swc/helpers": "0.5.23"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import { type AiCreditsPrompt } from '../model/ai-credit-estimate';
|
|
18
|
+
/**
|
|
19
|
+
* What a Free job past what is left asks before it starts (AGL-3722), on the
|
|
20
|
+
* Assist build plan card, in the guided start, on a build's page and in the
|
|
21
|
+
* jobs drawer alike: the plain sentence — about what it costs, what is left,
|
|
22
|
+
* that it builds what it can and pauses — and its ways on. Only "Build what
|
|
23
|
+
* fits" (or the smaller first build) starts anything; nothing is started by
|
|
24
|
+
* showing this.
|
|
25
|
+
*
|
|
26
|
+
* The ways on are one set of option buttons (Zach, 2026-10-10): the same
|
|
27
|
+
* shape and height, full width so a long label never wraps beside another,
|
|
28
|
+
* sentence case, a short label with its figure under it, and the recommended
|
|
29
|
+
* one drawn as the primary button. Theme tokens only, so it reads the same in
|
|
30
|
+
* the Assist panel's narrow column and in light or dark.
|
|
31
|
+
*/
|
|
32
|
+
export interface AiCreditsPromptProps {
|
|
33
|
+
prompt: AiCreditsPrompt;
|
|
34
|
+
noun: 'build' | 'site';
|
|
35
|
+
/** The workspace's path slug, for Upgrade; Upgrade is left out without it. */
|
|
36
|
+
orgSlug?: string | null;
|
|
37
|
+
busy?: boolean;
|
|
38
|
+
/** "Build what fits": start it, to pause where the credits run out. */
|
|
39
|
+
onBuildWhatFits: () => void;
|
|
40
|
+
/** The smaller first build; offered only when the prompt has one and this is given. */
|
|
41
|
+
onSmaller?: () => void;
|
|
42
|
+
}
|
|
43
|
+
export declare function AiCreditsPromptNotice({ prompt, noun, orgSlug, busy, onBuildWhatFits, onSmaller, }: AiCreditsPromptProps): JSX.Element;
|
|
44
|
+
export default AiCreditsPromptNotice;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ 'use client';
|
|
17
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
18
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
19
|
+
import { Box, Button, Stack, Typography } from "@mui/material";
|
|
20
|
+
import { useId } from "react";
|
|
21
|
+
import { aiCreditsChoices, aiCreditsPromptText } from "../model/ai-credit-estimate.js";
|
|
22
|
+
import { aiCreditsBillingHref } from "./ai-job-links.js";
|
|
23
|
+
function AiCreditsChoiceButton({ choice, busy, href, onClick }) {
|
|
24
|
+
const detailId = `${useId()}-detail`;
|
|
25
|
+
return /*#__PURE__*/ _jsxs(Button, _extends({
|
|
26
|
+
fullWidth: true,
|
|
27
|
+
size: "medium",
|
|
28
|
+
variant: choice.recommended ? 'contained' : 'outlined',
|
|
29
|
+
color: "primary",
|
|
30
|
+
disabled: busy && choice.key !== 'upgrade',
|
|
31
|
+
"aria-label": choice.label,
|
|
32
|
+
"aria-describedby": detailId,
|
|
33
|
+
"data-choice": choice.key
|
|
34
|
+
}, href ? {
|
|
35
|
+
href
|
|
36
|
+
} : {
|
|
37
|
+
onClick
|
|
38
|
+
}, {
|
|
39
|
+
sx: {
|
|
40
|
+
minHeight: 56,
|
|
41
|
+
px: 1.5,
|
|
42
|
+
py: 1,
|
|
43
|
+
display: 'flex',
|
|
44
|
+
flexDirection: 'column',
|
|
45
|
+
alignItems: 'flex-start',
|
|
46
|
+
justifyContent: 'center',
|
|
47
|
+
textAlign: 'left',
|
|
48
|
+
textTransform: 'none',
|
|
49
|
+
lineHeight: 1.3
|
|
50
|
+
},
|
|
51
|
+
children: [
|
|
52
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
53
|
+
component: "span",
|
|
54
|
+
variant: "body2",
|
|
55
|
+
sx: {
|
|
56
|
+
fontWeight: 600,
|
|
57
|
+
color: 'inherit'
|
|
58
|
+
},
|
|
59
|
+
children: choice.label
|
|
60
|
+
}),
|
|
61
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
62
|
+
id: detailId,
|
|
63
|
+
component: "span",
|
|
64
|
+
variant: "caption",
|
|
65
|
+
sx: {
|
|
66
|
+
color: 'inherit',
|
|
67
|
+
opacity: 0.8
|
|
68
|
+
},
|
|
69
|
+
children: choice.detail
|
|
70
|
+
})
|
|
71
|
+
]
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
export function AiCreditsPromptNotice({ prompt, noun, orgSlug, busy = false, onBuildWhatFits, onSmaller }) {
|
|
75
|
+
const choices = aiCreditsChoices(prompt, {
|
|
76
|
+
smaller: Boolean(onSmaller),
|
|
77
|
+
upgrade: Boolean(orgSlug)
|
|
78
|
+
});
|
|
79
|
+
return /*#__PURE__*/ _jsxs(Box, {
|
|
80
|
+
role: "alert",
|
|
81
|
+
"aria-label": "More than your credits left",
|
|
82
|
+
sx: {
|
|
83
|
+
mt: 1,
|
|
84
|
+
p: 1.5,
|
|
85
|
+
border: 1,
|
|
86
|
+
borderColor: 'warning.main',
|
|
87
|
+
borderRadius: 1,
|
|
88
|
+
bgcolor: 'background.paper'
|
|
89
|
+
},
|
|
90
|
+
children: [
|
|
91
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
92
|
+
variant: "body2",
|
|
93
|
+
sx: {
|
|
94
|
+
color: 'text.primary'
|
|
95
|
+
},
|
|
96
|
+
children: aiCreditsPromptText(prompt, noun)
|
|
97
|
+
}),
|
|
98
|
+
/*#__PURE__*/ _jsx(Stack, {
|
|
99
|
+
spacing: 1,
|
|
100
|
+
sx: {
|
|
101
|
+
mt: 1.5
|
|
102
|
+
},
|
|
103
|
+
children: choices.map((choice)=>/*#__PURE__*/ _jsx(AiCreditsChoiceButton, _extends({
|
|
104
|
+
choice: choice,
|
|
105
|
+
busy: busy
|
|
106
|
+
}, choice.key === 'upgrade' && orgSlug ? {
|
|
107
|
+
href: aiCreditsBillingHref(orgSlug)
|
|
108
|
+
} : {
|
|
109
|
+
onClick: choice.key === 'smaller' ? onSmaller : onBuildWhatFits
|
|
110
|
+
}), choice.key))
|
|
111
|
+
})
|
|
112
|
+
]
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
export default AiCreditsPromptNotice;
|
|
116
|
+
|
|
117
|
+
//# sourceMappingURL=ai-credits-prompt.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-credits-prompt.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\n'use client'\n\nimport { Box, Button, Stack, Typography } from '@mui/material'\nimport { useId } from 'react'\nimport {\n aiCreditsChoices,\n aiCreditsPromptText,\n type AiCreditsChoice,\n type AiCreditsPrompt,\n} from '../model/ai-credit-estimate'\nimport { aiCreditsBillingHref } from './ai-job-links'\n\n/**\n * What a Free job past what is left asks before it starts (AGL-3722), on the\n * Assist build plan card, in the guided start, on a build's page and in the\n * jobs drawer alike: the plain sentence — about what it costs, what is left,\n * that it builds what it can and pauses — and its ways on. Only \"Build what\n * fits\" (or the smaller first build) starts anything; nothing is started by\n * showing this.\n *\n * The ways on are one set of option buttons (Zach, 2026-10-10): the same\n * shape and height, full width so a long label never wraps beside another,\n * sentence case, a short label with its figure under it, and the recommended\n * one drawn as the primary button. Theme tokens only, so it reads the same in\n * the Assist panel's narrow column and in light or dark.\n */\nexport interface AiCreditsPromptProps {\n prompt: AiCreditsPrompt\n noun: 'build' | 'site'\n /** The workspace's path slug, for Upgrade; Upgrade is left out without it. */\n orgSlug?: string | null\n busy?: boolean\n /** \"Build what fits\": start it, to pause where the credits run out. */\n onBuildWhatFits: () => void\n /** The smaller first build; offered only when the prompt has one and this is given. */\n onSmaller?: () => void\n}\n\nfunction AiCreditsChoiceButton({\n choice,\n busy,\n href,\n onClick,\n}: {\n choice: AiCreditsChoice\n busy: boolean\n href?: string\n onClick?: () => void\n}): JSX.Element {\n const detailId = `${useId()}-detail`\n return (\n <Button\n fullWidth\n size=\"medium\"\n variant={choice.recommended ? 'contained' : 'outlined'}\n color=\"primary\"\n disabled={busy && choice.key !== 'upgrade'}\n aria-label={choice.label}\n aria-describedby={detailId}\n data-choice={choice.key}\n {...(href ? { href } : { onClick })}\n sx={{\n minHeight: 56,\n px: 1.5,\n py: 1,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'flex-start',\n justifyContent: 'center',\n textAlign: 'left',\n textTransform: 'none',\n lineHeight: 1.3,\n }}\n >\n <Typography component=\"span\" variant=\"body2\" sx={{ fontWeight: 600, color: 'inherit' }}>\n {choice.label}\n </Typography>\n <Typography id={detailId} component=\"span\" variant=\"caption\" sx={{ color: 'inherit', opacity: 0.8 }}>\n {choice.detail}\n </Typography>\n </Button>\n )\n}\n\nexport function AiCreditsPromptNotice({\n prompt,\n noun,\n orgSlug,\n busy = false,\n onBuildWhatFits,\n onSmaller,\n}: AiCreditsPromptProps): JSX.Element {\n const choices = aiCreditsChoices(prompt, { smaller: Boolean(onSmaller), upgrade: Boolean(orgSlug) })\n return (\n <Box\n role=\"alert\"\n aria-label=\"More than your credits left\"\n sx={{\n mt: 1,\n p: 1.5,\n border: 1,\n borderColor: 'warning.main',\n borderRadius: 1,\n bgcolor: 'background.paper',\n }}\n >\n <Typography variant=\"body2\" sx={{ color: 'text.primary' }}>\n {aiCreditsPromptText(prompt, noun)}\n </Typography>\n <Stack spacing={1} sx={{ mt: 1.5 }}>\n {choices.map((choice) => (\n <AiCreditsChoiceButton\n key={choice.key}\n choice={choice}\n busy={busy}\n {...(choice.key === 'upgrade' && orgSlug\n ? { href: aiCreditsBillingHref(orgSlug) }\n : { onClick: choice.key === 'smaller' ? onSmaller : onBuildWhatFits })}\n />\n ))}\n </Stack>\n </Box>\n )\n}\n\nexport default AiCreditsPromptNotice\n"],"names":["Box","Button","Stack","Typography","useId","aiCreditsChoices","aiCreditsPromptText","aiCreditsBillingHref","AiCreditsChoiceButton","choice","busy","href","onClick","detailId","fullWidth","size","variant","recommended","color","disabled","key","aria-label","label","aria-describedby","data-choice","sx","minHeight","px","py","display","flexDirection","alignItems","justifyContent","textAlign","textTransform","lineHeight","component","fontWeight","id","opacity","detail","AiCreditsPromptNotice","prompt","noun","orgSlug","onBuildWhatFits","onSmaller","choices","smaller","Boolean","upgrade","role","mt","p","border","borderColor","borderRadius","bgcolor","spacing","map"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;AAEA,SAASA,GAAG,EAAEC,MAAM,EAAEC,KAAK,EAAEC,UAAU,QAAQ,gBAAe;AAC9D,SAASC,KAAK,QAAQ,QAAO;AAC7B,SACEC,gBAAgB,EAChBC,mBAAmB,QAGd,iCAA6B;AACpC,SAASC,oBAAoB,QAAQ,oBAAgB;AA4BrD,SAASC,sBAAsB,EAC7BC,MAAM,EACNC,IAAI,EACJC,IAAI,EACJC,OAAO,EAMR;IACC,MAAMC,WAAW,GAAGT,QAAQ,OAAO,CAAC;IACpC,qBACE,MAACH;QACCa,SAAS;QACTC,MAAK;QACLC,SAASP,OAAOQ,WAAW,GAAG,cAAc;QAC5CC,OAAM;QACNC,UAAUT,QAAQD,OAAOW,GAAG,KAAK;QACjCC,cAAYZ,OAAOa,KAAK;QACxBC,oBAAkBV;QAClBW,eAAaf,OAAOW,GAAG;OAClBT,OAAO;QAAEA;IAAK,IAAI;QAAEC;IAAQ;QACjCa,IAAI;YACFC,WAAW;YACXC,IAAI;YACJC,IAAI;YACJC,SAAS;YACTC,eAAe;YACfC,YAAY;YACZC,gBAAgB;YAChBC,WAAW;YACXC,eAAe;YACfC,YAAY;QACd;;0BAEA,KAAChC;gBAAWiC,WAAU;gBAAOpB,SAAQ;gBAAQS,IAAI;oBAAEY,YAAY;oBAAKnB,OAAO;gBAAU;0BAClFT,OAAOa,KAAK;;0BAEf,KAACnB;gBAAWmC,IAAIzB;gBAAUuB,WAAU;gBAAOpB,SAAQ;gBAAUS,IAAI;oBAAEP,OAAO;oBAAWqB,SAAS;gBAAI;0BAC/F9B,OAAO+B,MAAM;;;;AAItB;AAEA,OAAO,SAASC,sBAAsB,EACpCC,MAAM,EACNC,IAAI,EACJC,OAAO,EACPlC,OAAO,KAAK,EACZmC,eAAe,EACfC,SAAS,EACY;IACrB,MAAMC,UAAU1C,iBAAiBqC,QAAQ;QAAEM,SAASC,QAAQH;QAAYI,SAASD,QAAQL;IAAS;IAClG,qBACE,MAAC5C;QACCmD,MAAK;QACL9B,cAAW;QACXI,IAAI;YACF2B,IAAI;YACJC,GAAG;YACHC,QAAQ;YACRC,aAAa;YACbC,cAAc;YACdC,SAAS;QACX;;0BAEA,KAACtD;gBAAWa,SAAQ;gBAAQS,IAAI;oBAAEP,OAAO;gBAAe;0BACrDZ,oBAAoBoC,QAAQC;;0BAE/B,KAACzC;gBAAMwD,SAAS;gBAAGjC,IAAI;oBAAE2B,IAAI;gBAAI;0BAC9BL,QAAQY,GAAG,CAAC,CAAClD,uBACZ,KAACD;wBAECC,QAAQA;wBACRC,MAAMA;uBACDD,OAAOW,GAAG,KAAK,aAAawB,UAC7B;wBAAEjC,MAAMJ,qBAAqBqC;oBAAS,IACtC;wBAAEhC,SAASH,OAAOW,GAAG,KAAK,YAAY0B,YAAYD;oBAAgB,IALjEpC,OAAOW,GAAG;;;;AAW3B;AAEA,eAAeqB,sBAAqB"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { MaybeTokenSource } from '@aglyn/shared-util-http/authorized-token';
|
|
2
|
+
import { type ButtonProps } from '@mui/material';
|
|
3
|
+
import { type ReactNode } from 'react';
|
|
4
|
+
import { type AiJobSummary } from '../model/ai-jobs.types';
|
|
5
|
+
/**
|
|
6
|
+
* Cancel an AI job, after saying what it does (AGL-3616). One confirm dialog
|
|
7
|
+
* and one request for every surface that offers Cancel — the job's page, a
|
|
8
|
+
* row of the site's AI jobs list, and the AI jobs list the top-bar chip
|
|
9
|
+
* opens — through the cancel door the Assist panel's list always used.
|
|
10
|
+
*
|
|
11
|
+
* `useAiJobCancel` owns the dialog: `ask(job)` opens it, Keep building
|
|
12
|
+
* closes it, and Cancel job posts the cancel and hands the job the door
|
|
13
|
+
* answered with to `onJob`, so the surface shows "Stopping…" or "Canceled"
|
|
14
|
+
* without waiting for its stream. A refusal stays in the dialog, in the
|
|
15
|
+
* door's own words.
|
|
16
|
+
*/
|
|
17
|
+
export declare function useAiJobCancel({ user, orgId, onJob, }: {
|
|
18
|
+
user: MaybeTokenSource;
|
|
19
|
+
orgId: string | null;
|
|
20
|
+
onJob?: (job: AiJobSummary) => void;
|
|
21
|
+
}): {
|
|
22
|
+
ask: (job: AiJobSummary) => void;
|
|
23
|
+
busyJobId: string | null;
|
|
24
|
+
dialog: ReactNode;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* The Cancel button: enabled while the job can still be stopped, and
|
|
28
|
+
* disabled with the reason as its tooltip once it is done, failed, canceled
|
|
29
|
+
* or already stopping.
|
|
30
|
+
*/
|
|
31
|
+
export declare function AiJobCancelButton({ job, user, orgId, onJob, size, variant, }: {
|
|
32
|
+
job: AiJobSummary;
|
|
33
|
+
user: MaybeTokenSource;
|
|
34
|
+
orgId: string | null;
|
|
35
|
+
onJob?: (job: AiJobSummary) => void;
|
|
36
|
+
size?: ButtonProps['size'];
|
|
37
|
+
variant?: ButtonProps['variant'];
|
|
38
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ 'use client';
|
|
17
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
18
|
+
import { Alert, Box, Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, Tooltip } from "@mui/material";
|
|
19
|
+
import { useCallback, useRef, useState } from "react";
|
|
20
|
+
import { AI_JOB_CANCEL_CONFIRM_COPY, AI_JOB_CANCEL_TITLE, aiJobCancelBlockedReason } from "../model/ai-job-cancel-copy.js";
|
|
21
|
+
import { AI_JOB_TERMINAL_STATUSES } from "../model/ai-jobs.types.js";
|
|
22
|
+
import { cancelAiJobRequest } from "./ai-job-requests.js";
|
|
23
|
+
/**
|
|
24
|
+
* Cancel an AI job, after saying what it does (AGL-3616). One confirm dialog
|
|
25
|
+
* and one request for every surface that offers Cancel — the job's page, a
|
|
26
|
+
* row of the site's AI jobs list, and the AI jobs list the top-bar chip
|
|
27
|
+
* opens — through the cancel door the Assist panel's list always used.
|
|
28
|
+
*
|
|
29
|
+
* `useAiJobCancel` owns the dialog: `ask(job)` opens it, Keep building
|
|
30
|
+
* closes it, and Cancel job posts the cancel and hands the job the door
|
|
31
|
+
* answered with to `onJob`, so the surface shows "Stopping…" or "Canceled"
|
|
32
|
+
* without waiting for its stream. A refusal stays in the dialog, in the
|
|
33
|
+
* door's own words.
|
|
34
|
+
*/ export function useAiJobCancel({ user, orgId, onJob }) {
|
|
35
|
+
var _ref;
|
|
36
|
+
const [target, setTarget] = useState(null);
|
|
37
|
+
const [busy, setBusy] = useState(false);
|
|
38
|
+
const [error, setError] = useState(null);
|
|
39
|
+
const onJobRef = useRef(onJob);
|
|
40
|
+
onJobRef.current = onJob;
|
|
41
|
+
const ask = useCallback((job)=>{
|
|
42
|
+
if (aiJobCancelBlockedReason(job)) return;
|
|
43
|
+
setError(null);
|
|
44
|
+
setTarget(job);
|
|
45
|
+
}, []);
|
|
46
|
+
const close = useCallback(()=>{
|
|
47
|
+
if (busy) return;
|
|
48
|
+
setTarget(null);
|
|
49
|
+
setError(null);
|
|
50
|
+
}, [
|
|
51
|
+
busy
|
|
52
|
+
]);
|
|
53
|
+
const confirm = useCallback(async ()=>{
|
|
54
|
+
if (!target || !orgId) return;
|
|
55
|
+
setBusy(true);
|
|
56
|
+
setError(null);
|
|
57
|
+
const { job, error: refused } = await cancelAiJobRequest(user, orgId, target.id);
|
|
58
|
+
setBusy(false);
|
|
59
|
+
if (job) onJobRef.current == null ? void 0 : onJobRef.current.call(onJobRef, job);
|
|
60
|
+
if (refused) {
|
|
61
|
+
setError(refused);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
setTarget(null);
|
|
65
|
+
}, [
|
|
66
|
+
target,
|
|
67
|
+
orgId,
|
|
68
|
+
user
|
|
69
|
+
]);
|
|
70
|
+
const dialog = /*#__PURE__*/ _jsxs(Dialog, {
|
|
71
|
+
open: target !== null,
|
|
72
|
+
onClose: close,
|
|
73
|
+
"aria-labelledby": "ai-job-cancel-title",
|
|
74
|
+
maxWidth: "xs",
|
|
75
|
+
fullWidth: true,
|
|
76
|
+
children: [
|
|
77
|
+
/*#__PURE__*/ _jsx(DialogTitle, {
|
|
78
|
+
id: "ai-job-cancel-title",
|
|
79
|
+
children: AI_JOB_CANCEL_TITLE
|
|
80
|
+
}),
|
|
81
|
+
/*#__PURE__*/ _jsxs(DialogContent, {
|
|
82
|
+
children: [
|
|
83
|
+
/*#__PURE__*/ _jsx(DialogContentText, {
|
|
84
|
+
children: AI_JOB_CANCEL_CONFIRM_COPY
|
|
85
|
+
}),
|
|
86
|
+
error ? /*#__PURE__*/ _jsx(Alert, {
|
|
87
|
+
severity: "warning",
|
|
88
|
+
sx: {
|
|
89
|
+
mt: 2
|
|
90
|
+
},
|
|
91
|
+
children: error
|
|
92
|
+
}) : null
|
|
93
|
+
]
|
|
94
|
+
}),
|
|
95
|
+
/*#__PURE__*/ _jsxs(DialogActions, {
|
|
96
|
+
children: [
|
|
97
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
98
|
+
onClick: close,
|
|
99
|
+
disabled: busy,
|
|
100
|
+
children: 'Keep building'
|
|
101
|
+
}),
|
|
102
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
103
|
+
color: "error",
|
|
104
|
+
variant: "contained",
|
|
105
|
+
onClick: ()=>void confirm(),
|
|
106
|
+
disabled: busy || !orgId,
|
|
107
|
+
children: busy ? 'Canceling…' : 'Cancel job'
|
|
108
|
+
})
|
|
109
|
+
]
|
|
110
|
+
})
|
|
111
|
+
]
|
|
112
|
+
});
|
|
113
|
+
return {
|
|
114
|
+
ask,
|
|
115
|
+
busyJobId: busy ? (_ref = target == null ? void 0 : target.id) != null ? _ref : null : null,
|
|
116
|
+
dialog
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* The Cancel button: enabled while the job can still be stopped, and
|
|
121
|
+
* disabled with the reason as its tooltip once it is done, failed, canceled
|
|
122
|
+
* or already stopping.
|
|
123
|
+
*/ export function AiJobCancelButton({ job, user, orgId, onJob, size = 'medium', variant = 'outlined' }) {
|
|
124
|
+
const { ask, busyJobId, dialog } = useAiJobCancel({
|
|
125
|
+
user,
|
|
126
|
+
orgId,
|
|
127
|
+
onJob
|
|
128
|
+
});
|
|
129
|
+
const blocked = aiJobCancelBlockedReason(job);
|
|
130
|
+
const stopping = Boolean(job.cancelRequested) && !AI_JOB_TERMINAL_STATUSES.includes(job.status);
|
|
131
|
+
const button = /*#__PURE__*/ _jsx(Button, {
|
|
132
|
+
size: size,
|
|
133
|
+
variant: variant,
|
|
134
|
+
color: "error",
|
|
135
|
+
disabled: Boolean(blocked) || busyJobId === job.id || !orgId,
|
|
136
|
+
onClick: ()=>ask(job),
|
|
137
|
+
children: stopping ? 'Stopping…' : 'Cancel'
|
|
138
|
+
});
|
|
139
|
+
return /*#__PURE__*/ _jsxs(_Fragment, {
|
|
140
|
+
children: [
|
|
141
|
+
blocked ? /*#__PURE__*/ _jsx(Tooltip, {
|
|
142
|
+
title: blocked,
|
|
143
|
+
children: /*#__PURE__*/ _jsx(Box, {
|
|
144
|
+
component: "span",
|
|
145
|
+
sx: {
|
|
146
|
+
display: 'inline-flex'
|
|
147
|
+
},
|
|
148
|
+
children: button
|
|
149
|
+
})
|
|
150
|
+
}) : button,
|
|
151
|
+
dialog
|
|
152
|
+
]
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
//# sourceMappingURL=ai-job-cancel.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-job-cancel.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 type { MaybeTokenSource } from '@aglyn/shared-util-http/authorized-token'\nimport {\n Alert,\n Box,\n Button,\n type ButtonProps,\n Dialog,\n DialogActions,\n DialogContent,\n DialogContentText,\n DialogTitle,\n Tooltip,\n} from '@mui/material'\nimport { type ReactNode, useCallback, useRef, useState } from 'react'\nimport {\n AI_JOB_CANCEL_CONFIRM_COPY,\n AI_JOB_CANCEL_TITLE,\n aiJobCancelBlockedReason,\n} from '../model/ai-job-cancel-copy'\nimport { AI_JOB_TERMINAL_STATUSES, type AiJobSummary } from '../model/ai-jobs.types'\nimport { cancelAiJobRequest } from './ai-job-requests'\n\n/**\n * Cancel an AI job, after saying what it does (AGL-3616). One confirm dialog\n * and one request for every surface that offers Cancel — the job's page, a\n * row of the site's AI jobs list, and the AI jobs list the top-bar chip\n * opens — through the cancel door the Assist panel's list always used.\n *\n * `useAiJobCancel` owns the dialog: `ask(job)` opens it, Keep building\n * closes it, and Cancel job posts the cancel and hands the job the door\n * answered with to `onJob`, so the surface shows \"Stopping…\" or \"Canceled\"\n * without waiting for its stream. A refusal stays in the dialog, in the\n * door's own words.\n */\nexport function useAiJobCancel({\n user,\n orgId,\n onJob,\n}: {\n user: MaybeTokenSource\n orgId: string | null\n onJob?: (job: AiJobSummary) => void\n}): { ask: (job: AiJobSummary) => void; busyJobId: string | null; dialog: ReactNode } {\n const [target, setTarget] = useState<AiJobSummary | null>(null)\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const onJobRef = useRef(onJob)\n onJobRef.current = onJob\n\n const ask = useCallback((job: AiJobSummary) => {\n if (aiJobCancelBlockedReason(job)) return\n setError(null)\n setTarget(job)\n }, [])\n const close = useCallback(() => {\n if (busy) return\n setTarget(null)\n setError(null)\n }, [busy])\n const confirm = useCallback(async () => {\n if (!target || !orgId) return\n setBusy(true)\n setError(null)\n const { job, error: refused } = await cancelAiJobRequest(user, orgId, target.id)\n setBusy(false)\n if (job) onJobRef.current?.(job)\n if (refused) {\n setError(refused)\n return\n }\n setTarget(null)\n }, [target, orgId, user])\n\n const dialog = (\n <Dialog open={target !== null} onClose={close} aria-labelledby=\"ai-job-cancel-title\" maxWidth=\"xs\" fullWidth>\n <DialogTitle id=\"ai-job-cancel-title\">{AI_JOB_CANCEL_TITLE}</DialogTitle>\n <DialogContent>\n <DialogContentText>{AI_JOB_CANCEL_CONFIRM_COPY}</DialogContentText>\n {error ? (\n <Alert severity=\"warning\" sx={{ mt: 2 }}>\n {error}\n </Alert>\n ) : null}\n </DialogContent>\n <DialogActions>\n <Button onClick={close} disabled={busy}>\n {'Keep building'}\n </Button>\n <Button color=\"error\" variant=\"contained\" onClick={() => void confirm()} disabled={busy || !orgId}>\n {busy ? 'Canceling…' : 'Cancel job'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n return { ask, busyJobId: busy ? (target?.id ?? null) : null, dialog }\n}\n\n/**\n * The Cancel button: enabled while the job can still be stopped, and\n * disabled with the reason as its tooltip once it is done, failed, canceled\n * or already stopping.\n */\nexport function AiJobCancelButton({\n job,\n user,\n orgId,\n onJob,\n size = 'medium',\n variant = 'outlined',\n}: {\n job: AiJobSummary\n user: MaybeTokenSource\n orgId: string | null\n onJob?: (job: AiJobSummary) => void\n size?: ButtonProps['size']\n variant?: ButtonProps['variant']\n}) {\n const { ask, busyJobId, dialog } = useAiJobCancel({ user, orgId, onJob })\n const blocked = aiJobCancelBlockedReason(job)\n const stopping = Boolean(job.cancelRequested) && !AI_JOB_TERMINAL_STATUSES.includes(job.status)\n const button = (\n <Button\n size={size}\n variant={variant}\n color=\"error\"\n disabled={Boolean(blocked) || busyJobId === job.id || !orgId}\n onClick={() => ask(job)}\n >\n {stopping ? 'Stopping…' : 'Cancel'}\n </Button>\n )\n return (\n <>\n {blocked ? (\n <Tooltip title={blocked}>\n {/* A disabled button fires no pointer events; the span carries the tooltip. */}\n <Box component=\"span\" sx={{ display: 'inline-flex' }}>\n {button}\n </Box>\n </Tooltip>\n ) : (\n button\n )}\n {dialog}\n </>\n )\n}\n"],"names":["Alert","Box","Button","Dialog","DialogActions","DialogContent","DialogContentText","DialogTitle","Tooltip","useCallback","useRef","useState","AI_JOB_CANCEL_CONFIRM_COPY","AI_JOB_CANCEL_TITLE","aiJobCancelBlockedReason","AI_JOB_TERMINAL_STATUSES","cancelAiJobRequest","useAiJobCancel","user","orgId","onJob","target","setTarget","busy","setBusy","error","setError","onJobRef","current","ask","job","close","confirm","refused","id","dialog","open","onClose","aria-labelledby","maxWidth","fullWidth","severity","sx","mt","onClick","disabled","color","variant","busyJobId","AiJobCancelButton","size","blocked","stopping","Boolean","cancelRequested","includes","status","button","title","component","display"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;AAGA,SACEA,KAAK,EACLC,GAAG,EACHC,MAAM,EAENC,MAAM,EACNC,aAAa,EACbC,aAAa,EACbC,iBAAiB,EACjBC,WAAW,EACXC,OAAO,QACF,gBAAe;AACtB,SAAyBC,WAAW,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAO;AACrE,SACEC,0BAA0B,EAC1BC,mBAAmB,EACnBC,wBAAwB,QACnB,iCAA6B;AACpC,SAASC,wBAAwB,QAA2B,4BAAwB;AACpF,SAASC,kBAAkB,QAAQ,uBAAmB;AAEtD;;;;;;;;;;;CAWC,GACD,OAAO,SAASC,eAAe,EAC7BC,IAAI,EACJC,KAAK,EACLC,KAAK,EAKN;;IACC,MAAM,CAACC,QAAQC,UAAU,GAAGX,SAA8B;IAC1D,MAAM,CAACY,MAAMC,QAAQ,GAAGb,SAAS;IACjC,MAAM,CAACc,OAAOC,SAAS,GAAGf,SAAwB;IAClD,MAAMgB,WAAWjB,OAAOU;IACxBO,SAASC,OAAO,GAAGR;IAEnB,MAAMS,MAAMpB,YAAY,CAACqB;QACvB,IAAIhB,yBAAyBgB,MAAM;QACnCJ,SAAS;QACTJ,UAAUQ;IACZ,GAAG,EAAE;IACL,MAAMC,QAAQtB,YAAY;QACxB,IAAIc,MAAM;QACVD,UAAU;QACVI,SAAS;IACX,GAAG;QAACH;KAAK;IACT,MAAMS,UAAUvB,YAAY;QAC1B,IAAI,CAACY,UAAU,CAACF,OAAO;QACvBK,QAAQ;QACRE,SAAS;QACT,MAAM,EAAEI,GAAG,EAAEL,OAAOQ,OAAO,EAAE,GAAG,MAAMjB,mBAAmBE,MAAMC,OAAOE,OAAOa,EAAE;QAC/EV,QAAQ;QACR,IAAIM,KAAKH,SAASC,OAAO,oBAAhBD,SAASC,OAAO,MAAhBD,UAAmBG;QAC5B,IAAIG,SAAS;YACXP,SAASO;YACT;QACF;QACAX,UAAU;IACZ,GAAG;QAACD;QAAQF;QAAOD;KAAK;IAExB,MAAMiB,uBACJ,MAAChC;QAAOiC,MAAMf,WAAW;QAAMgB,SAASN;QAAOO,mBAAgB;QAAsBC,UAAS;QAAKC,SAAS;;0BAC1G,KAACjC;gBAAY2B,IAAG;0BAAuBrB;;0BACvC,MAACR;;kCACC,KAACC;kCAAmBM;;oBACnBa,sBACC,KAACzB;wBAAMyC,UAAS;wBAAUC,IAAI;4BAAEC,IAAI;wBAAE;kCACnClB;yBAED;;;0BAEN,MAACrB;;kCACC,KAACF;wBAAO0C,SAASb;wBAAOc,UAAUtB;kCAC/B;;kCAEH,KAACrB;wBAAO4C,OAAM;wBAAQC,SAAQ;wBAAYH,SAAS,IAAM,KAAKZ;wBAAWa,UAAUtB,QAAQ,CAACJ;kCACzFI,OAAO,eAAe;;;;;;IAK/B,OAAO;QAAEM;QAAKmB,WAAWzB,eAAQF,0BAAAA,OAAQa,EAAE,mBAAI,OAAQ;QAAMC;IAAO;AACtE;AAEA;;;;CAIC,GACD,OAAO,SAASc,kBAAkB,EAChCnB,GAAG,EACHZ,IAAI,EACJC,KAAK,EACLC,KAAK,EACL8B,OAAO,QAAQ,EACfH,UAAU,UAAU,EAQrB;IACC,MAAM,EAAElB,GAAG,EAAEmB,SAAS,EAAEb,MAAM,EAAE,GAAGlB,eAAe;QAAEC;QAAMC;QAAOC;IAAM;IACvE,MAAM+B,UAAUrC,yBAAyBgB;IACzC,MAAMsB,WAAWC,QAAQvB,IAAIwB,eAAe,KAAK,CAACvC,yBAAyBwC,QAAQ,CAACzB,IAAI0B,MAAM;IAC9F,MAAMC,uBACJ,KAACvD;QACCgD,MAAMA;QACNH,SAASA;QACTD,OAAM;QACND,UAAUQ,QAAQF,YAAYH,cAAclB,IAAII,EAAE,IAAI,CAACf;QACvDyB,SAAS,IAAMf,IAAIC;kBAElBsB,WAAW,cAAc;;IAG9B,qBACE;;YACGD,wBACC,KAAC3C;gBAAQkD,OAAOP;0BAEd,cAAA,KAAClD;oBAAI0D,WAAU;oBAAOjB,IAAI;wBAAEkB,SAAS;oBAAc;8BAChDH;;iBAILA;YAEDtB;;;AAGP"}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import { type AiBuildPlanEmbed } from '../model/ai-build-plan';
|
|
18
18
|
import type { AiJobReview, AiJobSummary } from '../model/ai-jobs.types';
|
|
19
|
+
import type { AiJobResumeOptions } from './ai-job-requests';
|
|
19
20
|
import { AiSiteStarterFallback } from './ai-site-starter-fallback.component';
|
|
20
21
|
/**
|
|
21
22
|
* A job's plan and what it waits for (AGL-2935), inside the AI jobs drawer
|
|
@@ -31,9 +32,7 @@ export interface AiJobPlanProps {
|
|
|
31
32
|
* Confirms the plan, or tries the refused step again. A build whose request
|
|
32
33
|
* asked to publish confirms with `publish` when its box is ticked (AGL-3616).
|
|
33
34
|
*/
|
|
34
|
-
onResume: (job: AiJobSummary, options?:
|
|
35
|
-
publish?: boolean;
|
|
36
|
-
}) => void;
|
|
35
|
+
onResume: (job: AiJobSummary, options?: AiJobResumeOptions) => void;
|
|
37
36
|
/** A resume for this job is in flight. */
|
|
38
37
|
busy?: boolean;
|
|
39
38
|
/**
|
|
@@ -47,6 +46,8 @@ export interface AiJobPlanProps {
|
|
|
47
46
|
* that did not work out (AGL-3594); the action is drawn only when given.
|
|
48
47
|
*/
|
|
49
48
|
user?: Parameters<typeof AiSiteStarterFallback>[0]['user'];
|
|
49
|
+
/** The workspace's path slug, for the Upgrade a Free build past what is left offers (AGL-3722). */
|
|
50
|
+
orgSlug?: string | null;
|
|
50
51
|
}
|
|
51
52
|
/**
|
|
52
53
|
* Where a refused answer broke its rules, and the outline of those parts, as
|
|
@@ -62,5 +63,5 @@ export declare function aiJobReviewDetails(review: AiJobReview | null): string[]
|
|
|
62
63
|
* host's code loads when a visitor reaches it, whether or not they press play.
|
|
63
64
|
*/
|
|
64
65
|
export declare function aiPlanEmbedLine(embed: AiBuildPlanEmbed, named: (ref: string) => string): string;
|
|
65
|
-
export declare function AiJobPlan({ job, onResume, busy, staff, user, }: AiJobPlanProps): JSX.Element | null;
|
|
66
|
+
export declare function AiJobPlan({ job, onResume, busy, staff, user, orgSlug, }: AiJobPlanProps): JSX.Element | null;
|
|
66
67
|
export default AiJobPlan;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
3
|
/**
|
|
3
4
|
* @license
|
|
@@ -15,7 +16,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
15
16
|
* See the License for the specific language governing permissions and
|
|
16
17
|
* limitations under the License.
|
|
17
18
|
*/ import { AI_BUILD_PLAN_CREATION_NOUNS, AI_BUILD_PLAN_EMBED_HOST_NAMES, isAiPlanNewRef } from "../model/ai-build-plan.js";
|
|
18
|
-
import {
|
|
19
|
+
import { aiBuildFreePageCapNote, aiBuildSmaller, aiJobCreditRange } from "../model/ai-build-job.js";
|
|
20
|
+
import { aiCreditRangeText, aiCreditsPromptFor } from "../model/ai-credit-estimate.js";
|
|
21
|
+
import { aiFreeCreditsResetLabel } from "../model/ai-site-job.js";
|
|
22
|
+
import { AiCreditsPromptNotice } from "./ai-credits-prompt.component.js";
|
|
19
23
|
import { aiBuildOpNoun } from "../model/ai-build-progress.js";
|
|
20
24
|
import { aiJobConfirmingOwnPlan } from "../model/ai-job-activity.js";
|
|
21
25
|
import { aiSiteStarterFallbackOffered } from "../model/ai-job-failure-copy.js";
|
|
@@ -67,8 +71,8 @@ import { useState } from "react";
|
|
|
67
71
|
const link = embed.url ? ` playing ${embed.url}` : ', its link left for you to paste';
|
|
68
72
|
return `Embeds a ${host} player on ${where}${link}, as you asked (“${embed.asked}”). It loads ${host}’s own code when a visitor reaches it, whether or not they press play.`;
|
|
69
73
|
}
|
|
70
|
-
export function AiJobPlan({ job, onResume, busy = false, staff = false, user }) {
|
|
71
|
-
var _plan_items, _plan_embeds;
|
|
74
|
+
export function AiJobPlan({ job, onResume, busy = false, staff = false, user, orgSlug }) {
|
|
75
|
+
var _ref, _plan_items, _plan_embeds;
|
|
72
76
|
const [detailsOpen, setDetailsOpen] = useState(false);
|
|
73
77
|
// Unticked until the person ticks it: a build publishes only when its
|
|
74
78
|
// request asked AND they confirm it here (AGL-3616).
|
|
@@ -84,11 +88,20 @@ export function AiJobPlan({ job, onResume, busy = false, staff = false, user })
|
|
|
84
88
|
const waiting = job.status === 'needs_review' && review !== null && !aiJobConfirmingOwnPlan(job);
|
|
85
89
|
// The guard rail (AGL-2911): what the plan is estimated to cost is read
|
|
86
90
|
// before it is confirmed, not after it has been spent. An estimate, and
|
|
87
|
-
// said to be one
|
|
88
|
-
//
|
|
91
|
+
// said to be one: what it is likely to cost — what builds like it measured
|
|
92
|
+
// — and its ceiling, every pass at its reserve (AGL-3722). A page job
|
|
89
93
|
// counts the creations it builds before its page (AGL-3031).
|
|
90
|
-
const
|
|
94
|
+
const range = plan && waiting && review.reason === 'plan' ? aiJobCreditRange(job.kind, plan) : null;
|
|
95
|
+
// A Free build past what is left asks first (AGL-3722): build what fits,
|
|
96
|
+
// the home page first, or upgrade — never a refusal with no way on.
|
|
97
|
+
const freeCredits = (_ref = review == null ? void 0 : review.freeCredits) != null ? _ref : null;
|
|
98
|
+
const prompt = plan && range && job.kind === 'build' ? aiCreditsPromptFor(range, freeCredits, aiBuildSmaller(plan)) : null;
|
|
99
|
+
// A Free build at its page cap says so (AGL-3722): pages past it were left for a later request.
|
|
100
|
+
const pageCapNote = plan && waiting && review.reason === 'plan' && job.kind === 'build' ? aiBuildFreePageCapNote(plan, Boolean(freeCredits)) : null;
|
|
91
101
|
const offersPublish = job.kind === 'build' && job.publishAsked === true && waiting && review.reason === 'plan';
|
|
102
|
+
const publishing = offersPublish && publish ? {
|
|
103
|
+
publish: true
|
|
104
|
+
} : {};
|
|
92
105
|
return /*#__PURE__*/ _jsxs(Box, {
|
|
93
106
|
sx: {
|
|
94
107
|
mt: 1
|
|
@@ -206,14 +219,26 @@ export function AiJobPlan({ job, onResume, busy = false, staff = false, user })
|
|
|
206
219
|
})
|
|
207
220
|
]
|
|
208
221
|
}),
|
|
209
|
-
|
|
222
|
+
range && range.ceiling > 0 && /*#__PURE__*/ _jsxs(Typography, {
|
|
210
223
|
variant: "caption",
|
|
211
224
|
color: "text.secondary",
|
|
212
225
|
sx: {
|
|
213
226
|
display: 'block',
|
|
214
227
|
mt: 1
|
|
215
228
|
},
|
|
216
|
-
children:
|
|
229
|
+
children: [
|
|
230
|
+
`Estimated cost: ${aiCreditRangeText(range)}. What it costs is what its steps spend.`,
|
|
231
|
+
freeCredits && !prompt ? ` You have ${freeCredits.left.toLocaleString('en-US')} of your free AI credits left this month, until ${aiFreeCreditsResetLabel(freeCredits.resetsOn)}.` : ''
|
|
232
|
+
]
|
|
233
|
+
}),
|
|
234
|
+
pageCapNote && /*#__PURE__*/ _jsx(Typography, {
|
|
235
|
+
variant: "caption",
|
|
236
|
+
color: "text.secondary",
|
|
237
|
+
sx: {
|
|
238
|
+
display: 'block',
|
|
239
|
+
mt: 0.5
|
|
240
|
+
},
|
|
241
|
+
children: pageCapNote
|
|
217
242
|
}),
|
|
218
243
|
waiting && review.retryRefusal && review.reason !== 'plan' && /*#__PURE__*/ _jsx(Typography, {
|
|
219
244
|
variant: "caption",
|
|
@@ -239,15 +264,26 @@ export function AiJobPlan({ job, onResume, busy = false, staff = false, user })
|
|
|
239
264
|
children: 'Publish the new pages when they are built'
|
|
240
265
|
})
|
|
241
266
|
}),
|
|
242
|
-
waiting && /*#__PURE__*/ _jsx(
|
|
267
|
+
waiting && prompt && /*#__PURE__*/ _jsx(AiCreditsPromptNotice, {
|
|
268
|
+
prompt: prompt,
|
|
269
|
+
noun: "build",
|
|
270
|
+
orgSlug: orgSlug,
|
|
271
|
+
busy: busy,
|
|
272
|
+
onBuildWhatFits: ()=>onResume(job, _extends({}, publishing, {
|
|
273
|
+
creditsConfirmed: true
|
|
274
|
+
})),
|
|
275
|
+
onSmaller: ()=>onResume(job, _extends({}, publishing, {
|
|
276
|
+
creditsConfirmed: true,
|
|
277
|
+
reduce: 'first-page'
|
|
278
|
+
}))
|
|
279
|
+
}),
|
|
280
|
+
waiting && !prompt && /*#__PURE__*/ _jsx(Button, {
|
|
243
281
|
size: "small",
|
|
244
282
|
variant: "contained",
|
|
245
283
|
// Disabled with its reason above when the Free allowance left
|
|
246
284
|
// cannot pay for another try (AGL-3594).
|
|
247
285
|
disabled: busy || review.reason !== 'plan' && Boolean(review.retryRefusal),
|
|
248
|
-
onClick: ()=>onResume(job, offersPublish && publish ?
|
|
249
|
-
publish: true
|
|
250
|
-
} : undefined),
|
|
286
|
+
onClick: ()=>onResume(job, offersPublish && publish ? publishing : undefined),
|
|
251
287
|
sx: {
|
|
252
288
|
mt: 1
|
|
253
289
|
},
|