@aglyn/plugins-ai 1.0.0-beta.230 → 1.0.0-beta.231
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-assist-provider-on-host.component.d.ts +66 -0
- package/src/lib/components/ai-assist-provider-on-host.component.js +78 -0
- package/src/lib/components/ai-assist-provider-on-host.component.js.map +1 -0
- package/src/lib/components/ai-assist-provider.component.js +9 -10
- package/src/lib/components/ai-assist-provider.component.js.map +1 -1
- package/src/lib/components/ai-job-plan.component.js +3 -1
- package/src/lib/components/ai-job-plan.component.js.map +1 -1
- package/src/lib/components/ai-permissions-on-host.component.d.ts +3 -46
- package/src/lib/components/ai-permissions-on-host.component.js +5 -53
- package/src/lib/components/ai-permissions-on-host.component.js.map +1 -1
- package/src/lib/components/ai-site-build-page.component.js +20 -8
- package/src/lib/components/ai-site-build-page.component.js.map +1 -1
- package/src/lib/jobs/ai-build-unit-outcome.js +4 -2
- package/src/lib/jobs/ai-build-unit-outcome.js.map +1 -1
- package/src/lib/jobs/ai-job-auto-confirm.d.ts +8 -0
- package/src/lib/jobs/ai-job-auto-confirm.js +30 -6
- package/src/lib/jobs/ai-job-auto-confirm.js.map +1 -1
- package/src/lib/jobs/ai-job-build-step.js +11 -0
- package/src/lib/jobs/ai-job-build-step.js.map +1 -1
- package/src/lib/jobs/ai-job-generation.d.ts +8 -0
- package/src/lib/jobs/ai-job-generation.js +13 -2
- package/src/lib/jobs/ai-job-generation.js.map +1 -1
- package/src/lib/jobs/ai-job-insight-step.js +8 -1
- package/src/lib/jobs/ai-job-insight-step.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-language.d.ts +73 -0
- package/src/lib/jobs/ai-job-layout-language.js +194 -0
- package/src/lib/jobs/ai-job-layout-language.js.map +1 -0
- package/src/lib/jobs/ai-job-layout-site-pages.d.ts +13 -2
- package/src/lib/jobs/ai-job-layout-site-pages.js +18 -2
- package/src/lib/jobs/ai-job-layout-site-pages.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-step.d.ts +5 -0
- package/src/lib/jobs/ai-job-layout-step.js +105 -5
- package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
- package/src/lib/jobs/ai-job-page-language.d.ts +149 -0
- package/src/lib/jobs/ai-job-page-language.js +355 -0
- package/src/lib/jobs/ai-job-page-language.js.map +1 -0
- package/src/lib/jobs/ai-job-page-sections.d.ts +37 -1
- package/src/lib/jobs/ai-job-page-sections.js +93 -11
- package/src/lib/jobs/ai-job-page-sections.js.map +1 -1
- package/src/lib/jobs/ai-job-page-step.d.ts +4 -4
- package/src/lib/jobs/ai-job-page-step.js +105 -14
- package/src/lib/jobs/ai-job-page-step.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-step.d.ts +1 -1
- package/src/lib/jobs/ai-job-plan-step.js +8 -2
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-step.d.ts +4 -0
- package/src/lib/jobs/ai-job-site-step.js +20 -3
- package/src/lib/jobs/ai-job-site-step.js.map +1 -1
- package/src/lib/jobs/ai-job-workflow-step.js +2 -2
- package/src/lib/jobs/ai-job-workflow-step.js.map +1 -1
- package/src/lib/jobs/ai-jobs.d.ts +1 -1
- package/src/lib/jobs/ai-jobs.js +17 -8
- package/src/lib/jobs/ai-jobs.js.map +1 -1
- package/src/lib/jobs/ai-layout-full-height.d.ts +40 -0
- package/src/lib/jobs/ai-layout-full-height.js +82 -0
- package/src/lib/jobs/ai-layout-full-height.js.map +1 -0
- package/src/lib/jobs/ai-layout-site-facts.d.ts +54 -0
- package/src/lib/jobs/ai-layout-site-facts.js +153 -0
- package/src/lib/jobs/ai-layout-site-facts.js.map +1 -0
- package/src/lib/layout-language/ai-layout-compiler.d.ts +145 -0
- package/src/lib/layout-language/ai-layout-compiler.js +1148 -0
- package/src/lib/layout-language/ai-layout-compiler.js.map +1 -0
- package/src/lib/layout-language/ai-layout-copy.d.ts +73 -0
- package/src/lib/layout-language/ai-layout-copy.js +137 -0
- package/src/lib/layout-language/ai-layout-copy.js.map +1 -0
- package/src/lib/layout-language/ai-layout-frame.d.ts +52 -0
- package/src/lib/layout-language/ai-layout-frame.js +457 -0
- package/src/lib/layout-language/ai-layout-frame.js.map +1 -0
- package/src/lib/layout-language/ai-layout-gaps.d.ts +63 -0
- package/src/lib/layout-language/ai-layout-gaps.js +345 -0
- package/src/lib/layout-language/ai-layout-gaps.js.map +1 -0
- package/src/lib/layout-language/ai-layout-language.d.ts +161 -0
- package/src/lib/layout-language/ai-layout-language.js +446 -0
- package/src/lib/layout-language/ai-layout-language.js.map +1 -0
- package/src/lib/layout-language/ai-layout-links.d.ts +80 -0
- package/src/lib/layout-language/ai-layout-links.js +109 -0
- package/src/lib/layout-language/ai-layout-links.js.map +1 -0
- package/src/lib/layout-language/ai-layout-store.d.ts +39 -0
- package/src/lib/layout-language/ai-layout-store.js +69 -0
- package/src/lib/layout-language/ai-layout-store.js.map +1 -0
- package/src/lib/layout-language/ai-layout-tree.d.ts +59 -0
- package/src/lib/layout-language/ai-layout-tree.js +84 -0
- package/src/lib/layout-language/ai-layout-tree.js.map +1 -0
- package/src/lib/lazy-widget.d.ts +45 -0
- package/src/lib/lazy-widget.js +53 -0
- package/src/lib/lazy-widget.js.map +1 -0
- package/src/lib/model/ai-build-job.js +2 -1
- package/src/lib/model/ai-build-job.js.map +1 -1
- package/src/lib/model/ai-build-progress.d.ts +20 -3
- package/src/lib/model/ai-build-progress.js +48 -6
- package/src/lib/model/ai-build-progress.js.map +1 -1
- package/src/lib/model/ai-host-publish-context.d.ts +51 -0
- package/src/lib/model/ai-host-publish-context.js +104 -0
- package/src/lib/model/ai-host-publish-context.js.map +1 -0
- package/src/lib/model/ai-job-activity.d.ts +22 -0
- package/src/lib/model/ai-job-activity.js +22 -1
- package/src/lib/model/ai-job-activity.js.map +1 -1
- package/src/lib/model/ai-job-failure-copy.d.ts +38 -1
- package/src/lib/model/ai-job-failure-copy.js +56 -1
- package/src/lib/model/ai-job-failure-copy.js.map +1 -1
- package/src/lib/model/ai-job-notice.d.ts +3 -1
- package/src/lib/model/ai-job-notice.js +31 -9
- package/src/lib/model/ai-job-notice.js.map +1 -1
- package/src/lib/model/ai-jobs.types.d.ts +19 -0
- package/src/lib/model/ai-jobs.types.js.map +1 -1
- package/src/lib/model/ai-site-build-progress.d.ts +5 -1
- package/src/lib/model/ai-site-build-progress.js +27 -4
- package/src/lib/model/ai-site-build-progress.js.map +1 -1
- package/src/lib/model/ai-site-job.d.ts +8 -0
- package/src/lib/model/ai-site-job.js +9 -0
- package/src/lib/model/ai-site-job.js.map +1 -1
- package/src/lib/model/ai-site-start-seo.d.ts +1 -1
- package/src/lib/model/ai-site-start.d.ts +5 -2
- package/src/lib/model/ai-site-start.js +5 -2
- package/src/lib/model/ai-site-start.js.map +1 -1
- package/src/lib/plugin.js +79 -47
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/providers/catalog.d.ts +1 -1
- package/src/lib/providers/catalog.js +3 -3
- package/src/lib/providers/catalog.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.d.ts +82 -0
- package/src/lib/runtime/ai-doctrine-validators.js +436 -4
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-doctrine.js +12 -3
- package/src/lib/runtime/ai-doctrine.js.map +1 -1
- package/src/lib/runtime/ai-icon-library.d.ts +257 -0
- package/src/lib/runtime/ai-icon-library.js +254 -0
- package/src/lib/runtime/ai-icon-library.js.map +1 -0
- package/src/lib/runtime/ai-node-tree.d.ts +9 -0
- package/src/lib/runtime/ai-node-tree.js +30 -4
- package/src/lib/runtime/ai-node-tree.js.map +1 -1
- package/src/lib/runtime/ai-palette.d.ts +6 -0
- package/src/lib/runtime/ai-palette.generated.js +70 -0
- package/src/lib/runtime/ai-palette.generated.js.map +1 -1
- package/src/lib/runtime/ai-palette.js.map +1 -1
- package/src/lib/tools/ai-workflow-tool.d.ts +6 -2
- package/src/lib/tools/ai-workflow-tool.js +16 -14
- package/src/lib/tools/ai-workflow-tool.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.231",
|
|
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.231",
|
|
29
|
+
"@aglyn/shared-data-enums": "1.0.0-beta.231",
|
|
30
|
+
"@aglyn/shared-data-mdi": "1.0.0-beta.231",
|
|
31
|
+
"@aglyn/shared-data-types": "1.0.0-beta.231",
|
|
32
|
+
"@aglyn/shared-ui-email-campaigns": "1.0.0-beta.231",
|
|
33
|
+
"@aglyn/shared-ui-jsx": "1.0.0-beta.231",
|
|
34
|
+
"@aglyn/shared-ui-snackstack": "1.0.0-beta.231",
|
|
35
|
+
"@aglyn/shared-ui-theme": "1.0.0-beta.231",
|
|
36
|
+
"@aglyn/shared-util-email": "1.0.0-beta.231",
|
|
37
|
+
"@aglyn/shared-util-errors": "1.0.0-beta.231",
|
|
38
|
+
"@aglyn/shared-util-http": "1.0.0-beta.231",
|
|
39
|
+
"@aglyn/shared-util-timestamp": "1.0.0-beta.231",
|
|
40
|
+
"@aglyn/shared-util-tools": "1.0.0-beta.231",
|
|
41
|
+
"@aglyn/tenant-data-admin": "1.0.0-beta.231",
|
|
42
|
+
"@aglyn/tenant-feature-instance": "1.0.0-beta.231",
|
|
43
|
+
"@aglyn/tenant-runtime": "1.0.0-beta.231",
|
|
44
44
|
"@swc/helpers": "0.5.23"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
@@ -0,0 +1,66 @@
|
|
|
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 ComponentProps } from 'react';
|
|
18
|
+
import { AiAssistProvider } from './ai-assist-provider.component';
|
|
19
|
+
/**
|
|
20
|
+
* What the console shell hands a provider and the assistant dock (AGL-2984):
|
|
21
|
+
* the reader's verdict for every catalog key a plugin declared, on the site
|
|
22
|
+
* in view, with `loaded` false until every read behind it has answered.
|
|
23
|
+
*/
|
|
24
|
+
export interface ShellPermissionsOnHost {
|
|
25
|
+
loaded: boolean;
|
|
26
|
+
granted: Readonly<Record<string, boolean>>;
|
|
27
|
+
}
|
|
28
|
+
/** The AI half of that answer, in the shape the AI surfaces hold on. */
|
|
29
|
+
export interface AiPermissionsAnswer {
|
|
30
|
+
loaded: boolean;
|
|
31
|
+
use: boolean;
|
|
32
|
+
generate: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The shell's answer read for the two AI keys. `undefined` while the shell
|
|
36
|
+
* has handed nothing, which the provider reads as pending; one object per
|
|
37
|
+
* verdict, so the callbacks keyed on it are not rebuilt on every render.
|
|
38
|
+
*/
|
|
39
|
+
export declare function useAiPermissionsOnHost(answer: ShellPermissionsOnHost | undefined): AiPermissionsAnswer | undefined;
|
|
40
|
+
type ProviderProps = Omit<ComponentProps<typeof AiAssistProvider>, 'aiPermissions'> & {
|
|
41
|
+
permissionsOnHost?: ShellPermissionsOnHost;
|
|
42
|
+
/**
|
|
43
|
+
* The plugins that run on the site in view, as the shell resolved them
|
|
44
|
+
* (AGL-3028). Absent where the shell hands none, which reads as no site
|
|
45
|
+
* narrowing at all.
|
|
46
|
+
*/
|
|
47
|
+
enabledPluginIds?: readonly string[];
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* The besigner copy assistant's provider, holding on the shell's permission
|
|
51
|
+
* answer.
|
|
52
|
+
*
|
|
53
|
+
* On a site with AI switched off (AGL-3028) it stays MOUNTED — it wraps every
|
|
54
|
+
* console page, and a provider that came and went per site would remount the
|
|
55
|
+
* whole tree beneath it — and opens nothing: a settled refusal publishes no
|
|
56
|
+
* callback, so no control can reach its dialogs.
|
|
57
|
+
*
|
|
58
|
+
* The one component the plugin registers eagerly (AGL-3649): a provider wraps
|
|
59
|
+
* the page, so one that loaded late would remount everything beneath it. It
|
|
60
|
+
* is in its own module so that loading it loads nothing of the dock's.
|
|
61
|
+
*/
|
|
62
|
+
export declare function AiAssistProviderOnHost(props: ProviderProps): import("react").JSX.Element;
|
|
63
|
+
export declare namespace AiAssistProviderOnHost {
|
|
64
|
+
var displayName: string;
|
|
65
|
+
}
|
|
66
|
+
export {};
|
|
@@ -0,0 +1,78 @@
|
|
|
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 { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
|
|
19
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
20
|
+
import { useMemo } from "react";
|
|
21
|
+
import { AI_PLUGIN_ID } from "../constants.js";
|
|
22
|
+
import { aiPermissionsOf } from "../model/ai-permissions.js";
|
|
23
|
+
import { AiAssistProvider } from "./ai-assist-provider.component.js";
|
|
24
|
+
/**
|
|
25
|
+
* The shell's answer read for the two AI keys. `undefined` while the shell
|
|
26
|
+
* has handed nothing, which the provider reads as pending; one object per
|
|
27
|
+
* verdict, so the callbacks keyed on it are not rebuilt on every render.
|
|
28
|
+
*/ export function useAiPermissionsOnHost(answer) {
|
|
29
|
+
const present = answer !== undefined;
|
|
30
|
+
const loaded = (answer == null ? void 0 : answer.loaded) === true;
|
|
31
|
+
const verdict = aiPermissionsOf(loaded ? answer == null ? void 0 : answer.granted : null);
|
|
32
|
+
const use = verdict['ai.use'];
|
|
33
|
+
const generate = verdict['ai.generate'];
|
|
34
|
+
return useMemo(()=>present ? {
|
|
35
|
+
loaded,
|
|
36
|
+
use,
|
|
37
|
+
generate
|
|
38
|
+
} : undefined, [
|
|
39
|
+
present,
|
|
40
|
+
loaded,
|
|
41
|
+
use,
|
|
42
|
+
generate
|
|
43
|
+
]);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Every AI door closed, as a settled answer: what the provider holds on a site
|
|
47
|
+
* that switched AI off. One object, so the callbacks keyed on it are stable.
|
|
48
|
+
*/ const OFF_FOR_SITE = {
|
|
49
|
+
loaded: true,
|
|
50
|
+
use: false,
|
|
51
|
+
generate: false
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* The besigner copy assistant's provider, holding on the shell's permission
|
|
55
|
+
* answer.
|
|
56
|
+
*
|
|
57
|
+
* On a site with AI switched off (AGL-3028) it stays MOUNTED — it wraps every
|
|
58
|
+
* console page, and a provider that came and went per site would remount the
|
|
59
|
+
* whole tree beneath it — and opens nothing: a settled refusal publishes no
|
|
60
|
+
* callback, so no control can reach its dialogs.
|
|
61
|
+
*
|
|
62
|
+
* The one component the plugin registers eagerly (AGL-3649): a provider wraps
|
|
63
|
+
* the page, so one that loaded late would remount everything beneath it. It
|
|
64
|
+
* is in its own module so that loading it loads nothing of the dock's.
|
|
65
|
+
*/ export function AiAssistProviderOnHost(props) {
|
|
66
|
+
const { permissionsOnHost, enabledPluginIds } = props, rest = _object_without_properties_loose(props, [
|
|
67
|
+
"permissionsOnHost",
|
|
68
|
+
"enabledPluginIds"
|
|
69
|
+
]);
|
|
70
|
+
const aiPermissions = useAiPermissionsOnHost(permissionsOnHost);
|
|
71
|
+
const offForSite = Boolean(enabledPluginIds) && !(enabledPluginIds == null ? void 0 : enabledPluginIds.includes(AI_PLUGIN_ID));
|
|
72
|
+
return /*#__PURE__*/ _jsx(AiAssistProvider, _extends({}, rest, {
|
|
73
|
+
aiPermissions: offForSite ? OFF_FOR_SITE : aiPermissions
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
AiAssistProviderOnHost.displayName = 'AiAssistProviderOnHost';
|
|
77
|
+
|
|
78
|
+
//# sourceMappingURL=ai-assist-provider-on-host.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-assist-provider-on-host.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 { useMemo, type ComponentProps } from 'react'\nimport { AI_PLUGIN_ID } from '../constants'\nimport { aiPermissionsOf } from '../model/ai-permissions'\nimport { AiAssistProvider } from './ai-assist-provider.component'\n\n/**\n * What the console shell hands a provider and the assistant dock (AGL-2984):\n * the reader's verdict for every catalog key a plugin declared, on the site\n * in view, with `loaded` false until every read behind it has answered.\n */\nexport interface ShellPermissionsOnHost {\n loaded: boolean\n granted: Readonly<Record<string, boolean>>\n}\n\n/** The AI half of that answer, in the shape the AI surfaces hold on. */\nexport interface AiPermissionsAnswer {\n loaded: boolean\n use: boolean\n generate: boolean\n}\n\n/**\n * The shell's answer read for the two AI keys. `undefined` while the shell\n * has handed nothing, which the provider reads as pending; one object per\n * verdict, so the callbacks keyed on it are not rebuilt on every render.\n */\nexport function useAiPermissionsOnHost(\n answer: ShellPermissionsOnHost | undefined,\n): AiPermissionsAnswer | undefined {\n const present = answer !== undefined\n const loaded = answer?.loaded === true\n const verdict = aiPermissionsOf(loaded ? answer?.granted : null)\n const use = verdict['ai.use']\n const generate = verdict['ai.generate']\n return useMemo(\n () => (present ? { loaded, use, generate } : undefined),\n [present, loaded, use, generate],\n )\n}\n\ntype ProviderProps = Omit<\n ComponentProps<typeof AiAssistProvider>,\n 'aiPermissions'\n> & {\n permissionsOnHost?: ShellPermissionsOnHost\n /**\n * The plugins that run on the site in view, as the shell resolved them\n * (AGL-3028). Absent where the shell hands none, which reads as no site\n * narrowing at all.\n */\n enabledPluginIds?: readonly string[]\n}\n\n/**\n * Every AI door closed, as a settled answer: what the provider holds on a site\n * that switched AI off. One object, so the callbacks keyed on it are stable.\n */\nconst OFF_FOR_SITE: AiPermissionsAnswer = {\n loaded: true,\n use: false,\n generate: false,\n}\n\n/**\n * The besigner copy assistant's provider, holding on the shell's permission\n * answer.\n *\n * On a site with AI switched off (AGL-3028) it stays MOUNTED — it wraps every\n * console page, and a provider that came and went per site would remount the\n * whole tree beneath it — and opens nothing: a settled refusal publishes no\n * callback, so no control can reach its dialogs.\n *\n * The one component the plugin registers eagerly (AGL-3649): a provider wraps\n * the page, so one that loaded late would remount everything beneath it. It\n * is in its own module so that loading it loads nothing of the dock's.\n */\nexport function AiAssistProviderOnHost(props: ProviderProps) {\n const { permissionsOnHost, enabledPluginIds, ...rest } = props\n const aiPermissions = useAiPermissionsOnHost(permissionsOnHost)\n const offForSite =\n Boolean(enabledPluginIds) && !enabledPluginIds?.includes(AI_PLUGIN_ID)\n return (\n <AiAssistProvider\n {...rest}\n aiPermissions={offForSite ? OFF_FOR_SITE : aiPermissions}\n />\n )\n}\nAiAssistProviderOnHost.displayName = 'AiAssistProviderOnHost'\n"],"names":["useMemo","AI_PLUGIN_ID","aiPermissionsOf","AiAssistProvider","useAiPermissionsOnHost","answer","present","undefined","loaded","verdict","granted","use","generate","OFF_FOR_SITE","AiAssistProviderOnHost","props","permissionsOnHost","enabledPluginIds","rest","aiPermissions","offForSite","Boolean","includes","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;AAEA,SAASA,OAAO,QAA6B,QAAO;AACpD,SAASC,YAAY,QAAQ,kBAAc;AAC3C,SAASC,eAAe,QAAQ,6BAAyB;AACzD,SAASC,gBAAgB,QAAQ,oCAAgC;AAmBjE;;;;CAIC,GACD,OAAO,SAASC,uBACdC,MAA0C;IAE1C,MAAMC,UAAUD,WAAWE;IAC3B,MAAMC,SAASH,CAAAA,0BAAAA,OAAQG,MAAM,MAAK;IAClC,MAAMC,UAAUP,gBAAgBM,SAASH,0BAAAA,OAAQK,OAAO,GAAG;IAC3D,MAAMC,MAAMF,OAAO,CAAC,SAAS;IAC7B,MAAMG,WAAWH,OAAO,CAAC,cAAc;IACvC,OAAOT,QACL,IAAOM,UAAU;YAAEE;YAAQG;YAAKC;QAAS,IAAIL,WAC7C;QAACD;QAASE;QAAQG;QAAKC;KAAS;AAEpC;AAeA;;;CAGC,GACD,MAAMC,eAAoC;IACxCL,QAAQ;IACRG,KAAK;IACLC,UAAU;AACZ;AAEA;;;;;;;;;;;;CAYC,GACD,OAAO,SAASE,uBAAuBC,KAAoB;IACzD,MAAM,EAAEC,iBAAiB,EAAEC,gBAAgB,EAAW,GAAGF,OAATG,wCAASH;;;;IACzD,MAAMI,gBAAgBf,uBAAuBY;IAC7C,MAAMI,aACJC,QAAQJ,qBAAqB,EAACA,oCAAAA,iBAAkBK,QAAQ,CAACrB;IAC3D,qBACE,KAACE,+BACKe;QACJC,eAAeC,aAAaP,eAAeM;;AAGjD;AACAL,uBAAuBS,WAAW,GAAG"}
|
|
@@ -16,8 +16,7 @@
|
|
|
16
16
|
*/ 'use client';
|
|
17
17
|
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
18
18
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
19
|
-
import
|
|
20
|
-
import { checkEntitlement, lockdownRefusalText, parseLockdownRefusal } from "@aglyn/aglyn";
|
|
19
|
+
import { canvas, checkEntitlement, components, FEATURE_FLAG, FieldComponentType, lockdownRefusalText, NodeType, parseLockdownRefusal } from "@aglyn/aglyn";
|
|
21
20
|
import { portableDefinitionToNested } from "@aglyn/aglyn/app-utils/node-definition-sanitizer";
|
|
22
21
|
import { AiAssistActionsContext } from "./ai-assist-actions-context.js";
|
|
23
22
|
import { assistNotOnPlanText } from "../usage/assist-credits.js";
|
|
@@ -79,8 +78,8 @@ const AI_GENERATE_REFUSED = 'Your role does not include AI generation — ask an
|
|
|
79
78
|
var _ref, _ref1;
|
|
80
79
|
var _schema_flags;
|
|
81
80
|
const schema = node == null ? void 0 : node.componentSchema;
|
|
82
|
-
const textEditable = (((_ref = schema == null ? void 0 : (_schema_flags = schema.flags) == null ? void 0 : _schema_flags.textEditable) != null ? _ref :
|
|
83
|
-
const attributes = ((_ref1 = schema == null ? void 0 : schema.attributes) != null ? _ref1 : []).filter((field)=>field.component ===
|
|
81
|
+
const textEditable = (((_ref = schema == null ? void 0 : (_schema_flags = schema.flags) == null ? void 0 : _schema_flags.textEditable) != null ? _ref : FEATURE_FLAG.DISABLED) & FEATURE_FLAG.ENABLED) !== 0;
|
|
82
|
+
const attributes = ((_ref1 = schema == null ? void 0 : schema.attributes) != null ? _ref1 : []).filter((field)=>field.component === FieldComponentType.TEXT_FIELD || field.component === FieldComponentType.TEXTAREA).map((field)=>{
|
|
84
83
|
var _field_label;
|
|
85
84
|
return {
|
|
86
85
|
prop: String(field.name),
|
|
@@ -143,7 +142,7 @@ const AI_GENERATE_REFUSED = 'Your role does not include AI generation — ask an
|
|
|
143
142
|
setBusy(true);
|
|
144
143
|
try {
|
|
145
144
|
var _current_props;
|
|
146
|
-
const current =
|
|
145
|
+
const current = canvas.toJSON().nodes[node.$id];
|
|
147
146
|
const text = typeof (current == null ? void 0 : (_current_props = current.props) == null ? void 0 : _current_props[effectiveTarget]) === 'string' ? current.props[effectiveTarget] : '';
|
|
148
147
|
const response = await authorizedFetch(user, '/api/ai/assist', {
|
|
149
148
|
method: 'POST',
|
|
@@ -185,7 +184,7 @@ const AI_GENERATE_REFUSED = 'Your role does not include AI generation — ask an
|
|
|
185
184
|
allowDuplicate: true
|
|
186
185
|
});
|
|
187
186
|
}
|
|
188
|
-
|
|
187
|
+
canvas.updateNodeProps(node, _extends({}, current == null ? void 0 : current.props, {
|
|
189
188
|
[effectiveTarget]: payload.text
|
|
190
189
|
}, effectiveTarget === 'children' ? {
|
|
191
190
|
html: undefined
|
|
@@ -305,17 +304,17 @@ const AI_GENERATE_REFUSED = 'Your role does not include AI generation — ask an
|
|
|
305
304
|
// and the subtree lands at the end of the canvas root.
|
|
306
305
|
const stamped = function stamp(node) {
|
|
307
306
|
var _node_nodes;
|
|
308
|
-
const schema =
|
|
307
|
+
const schema = components.getSchema(node.componentId);
|
|
309
308
|
return _extends({}, node, (schema == null ? void 0 : schema.pluginId) ? {
|
|
310
309
|
pluginId: schema.pluginId
|
|
311
310
|
} : {}, {
|
|
312
311
|
nodes: ((_node_nodes = node.nodes) != null ? _node_nodes : []).map(stamp)
|
|
313
312
|
});
|
|
314
313
|
}(nested);
|
|
315
|
-
|
|
316
|
-
type:
|
|
314
|
+
canvas.addNodeFromPreset({
|
|
315
|
+
type: NodeType.PRESET,
|
|
317
316
|
data: stamped
|
|
318
|
-
},
|
|
317
|
+
}, canvas.rootNode);
|
|
319
318
|
setSectionOpen(false);
|
|
320
319
|
enqueueSnackbar('Section added — undo removes it', {
|
|
321
320
|
variant: 'success',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-assist-provider.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 * as Aglyn from '@aglyn/aglyn'\nimport {\n checkEntitlement,\n lockdownRefusalText,\n parseLockdownRefusal,\n} from '@aglyn/aglyn'\nimport { portableDefinitionToNested } from '@aglyn/aglyn/app-utils/node-definition-sanitizer'\nimport { AiAssistActionsContext } from './ai-assist-actions-context'\nimport { assistNotOnPlanText } from '../usage/assist-credits'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport {\n Button,\n CircularProgress,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n MenuItem,\n TextField,\n Typography,\n} from '@mui/material'\nimport { useCallback, useMemo, useState } from 'react'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { AiModelSelector } from './ai-model-selector.component'\nimport { AiUsageStrip } from './ai-usage-strip.component'\nimport { useAiModelChoice } from './use-ai-model-choice'\nimport { usePublishAiUsageMeter } from './use-ai-usage-meter'\n\n\nexport interface AiAssistProviderProps {\n /** Org billing doc for the entitlement gate (mounted by the shell). */\n org?: unknown\n /**\n * True once `org` is a trustworthy answer (AGL-1380). The shell mounts\n * this provider above the whole console route tree, so it cannot hold its\n * render until the billing doc settles the way the plugin-page route does\n * — and an undefined `org` is not \"unknown\" to `checkEntitlement`, it is\n * the free tier. Without this flag the gates below told a Pro org that AI\n * assist is not on its plan for as long as the read was in flight.\n */\n orgReady?: boolean\n /**\n * The org every assist call is metered against (AGL-2073). The route no\n * longer resolves it from the signed-in user — a user with one paid org was\n * getting assist on all of their free ones, and their spend was landing on\n * whichever org the server happened to resolve.\n */\n orgId?: string\n /**\n * The site the canvas belongs to (AGL-2927), sent with every assist call\n * so the door can decide a site collaborator's permission on THAT site.\n * Null off a host route, where there is no canvas to assist on.\n */\n hostId?: string | null\n /**\n * The reader's AI verdict, resolved by the shell (AGL-2927). The gates\n * below HOLD until `loaded` — a door opened on a pending answer would\n * spend the workspace's credits on a permission nobody has confirmed —\n * and a refused key removes its callback from the context, so the\n * designer draws no control for it. Omitted, the answer is pending.\n */\n aiPermissions?: { loaded: boolean; use: boolean; generate: boolean }\n children?: JSX.Children\n}\n\nconst PERMISSIONS_PENDING = 'Checking your permissions — try again in a moment'\nconst AI_USE_REFUSED =\n 'Your role does not include AI assistance — ask an organization admin'\nconst AI_GENERATE_REFUSED =\n 'Your role does not include AI generation — ask an organization admin'\n\n/**\n * Console-side AI copy assist (AGL-89): provides the designer's \"Rewrite\n * with AI\" callback, hosts the instruction dialog, and calls the assist API\n * (which 501-degrades when no AI provider is configured). The commit\n * spreads the node's current props — `updateNodeProps` REPLACES the props\n * object — and clears any stale rich-text `html` so the new text renders.\n */\nexport function AiAssistProvider(props: AiAssistProviderProps) {\n const org = props.org\n const orgReady = props.orgReady\n const orgId = props.orgId\n const hostId = props.hostId ?? null\n const aiPermissions = props.aiPermissions\n const { children } = props\n const { enqueueSnackbar } = useSnackbar()\n const { data: user } = useUser()\n const [node, setNode] = useState<Aglyn.NodeSchema<any> | null>(null)\n const [instruction, setInstruction] = useState('')\n // Rewrite target (AGL-130): 'children' for text-editable elements, or\n // any text attribute the element's schema declares (alt text, labels…).\n const [targetProp, setTargetProp] = useState('children')\n const [busy, setBusy] = useState(false)\n // Generate section (AGL-169).\n const [sectionOpen, setSectionOpen] = useState(false)\n const [sectionPrompt, setSectionPrompt] = useState('')\n // The model switch and the usage strip in both dialogs (AGL-2942). Each\n // dialog remembers its own pick; one envelope store serves both strips\n // and the assistant panel's.\n const copyModel = useAiModelChoice({ orgId, hostId, surface: 'copy', kind: 'copy.element' })\n const sectionModel = useAiModelChoice({\n orgId,\n hostId,\n surface: 'section',\n kind: 'copy.section',\n })\n const publishMeter = usePublishAiUsageMeter(orgId)\n\n const textTargets = useMemo(() => {\n const schema = node?.componentSchema\n const textEditable =\n ((schema?.flags?.textEditable ?? Aglyn.FEATURE_FLAG.DISABLED) &\n Aglyn.FEATURE_FLAG.ENABLED) !==\n 0\n const attributes = (schema?.attributes ?? [])\n .filter(\n (field: any) =>\n field.component === Aglyn.FieldComponentType.TEXT_FIELD ||\n field.component === Aglyn.FieldComponentType.TEXTAREA,\n )\n .map((field: any) => ({\n prop: String(field.name),\n label: String(field.label ?? field.name),\n }))\n return textEditable\n ? [{ prop: 'children', label: 'Element text' }, ...attributes]\n : attributes\n }, [node])\n\n const handleRewrite = useCallback(\n (target: Aglyn.NodeSchema<any>) => {\n // The permission first (AGL-2927): it is a fact about the reader, and\n // pending asserts nothing here either. The refusal is unreachable\n // through the designer — a refused key publishes no callback — and\n // stands for any other caller of the context.\n if (!aiPermissions?.loaded) {\n return void enqueueSnackbar(PERMISSIONS_PENDING, {\n variant: 'info',\n persist: false,\n })\n }\n if (!aiPermissions.use) {\n return void enqueueSnackbar(AI_USE_REFUSED, {\n variant: 'warning',\n persist: false,\n })\n }\n // AGL-1380: pending asserts nothing. See `orgReady` on the props.\n if (!orgReady) {\n return void enqueueSnackbar(\n 'Checking your plan — try again in a moment',\n { variant: 'info', persist: false },\n )\n }\n if (!checkEntitlement(org as never, 'aiAssist')) {\n return void enqueueSnackbar(assistNotOnPlanText(), {\n variant: 'warning',\n persist: false,\n })\n }\n setInstruction('')\n setTargetProp('children')\n setNode(target)\n },\n [org, orgReady, aiPermissions, enqueueSnackbar],\n )\n\n // Keep the target valid for the selected element.\n const effectiveTarget = textTargets.some((item) => item.prop === targetProp)\n ? targetProp\n : (textTargets[0]?.prop ?? 'children')\n\n const handleConfirm = useCallback(async () => {\n if (!node || !instruction.trim() || busy) return\n setBusy(true)\n try {\n const current = (Aglyn.canvas.toJSON().nodes as Record<string, any>)[\n node.$id\n ]\n const text =\n typeof current?.props?.[effectiveTarget] === 'string'\n ? (current.props[effectiveTarget] as string)\n : ''\n const response = await authorizedFetch(user, '/api/ai/assist', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n orgId,\n hostId,\n text,\n instruction: instruction.trim(),\n ...(copyModel.model ? { model: copyModel.model } : {}),\n }),\n })\n const payload = await response.json()\n publishMeter(payload?.meter)\n // An ai-assist feature lockdown (AGL-1510/1532) reads as a pause, not\n // as \"AI request failed\" — a provider incident or a cost runaway is\n // something WE turned off, and saying so keeps the user's content out\n // of the story.\n const locked = parseLockdownRefusal(response.status, payload)\n if (locked) {\n return void enqueueSnackbar(lockdownRefusalText(locked), {\n variant: 'warning',\n persist: true,\n })\n }\n if (response.status === 501) {\n return void enqueueSnackbar(\n 'AI assist is not configured on this deployment',\n { variant: 'info', persist: false },\n )\n }\n if (!response.ok || !payload?.text) {\n return void enqueueSnackbar(payload?.error ?? 'AI request failed', {\n variant: 'error',\n allowDuplicate: true,\n })\n }\n Aglyn.canvas.updateNodeProps(node, {\n ...current?.props,\n [effectiveTarget]: payload.text,\n // Rich-text elements render `html` over `children`; drop it so the\n // rewrite is what shows (the user can re-format inline afterwards).\n ...(effectiveTarget === 'children' ? { html: undefined } : {}),\n })\n setNode(null)\n enqueueSnackbar('Text rewritten — undo restores the original', {\n variant: 'success',\n persist: false,\n })\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', {\n variant: 'error',\n allowDuplicate: true,\n })\n } finally {\n setBusy(false)\n }\n }, [\n node,\n instruction,\n busy,\n user,\n effectiveTarget,\n orgId,\n hostId,\n copyModel.model,\n publishMeter,\n enqueueSnackbar,\n ])\n\n const handleGenerateSection = useCallback(() => {\n // The permission first (AGL-2927) — a section is a generation, so this\n // door sells under `ai.generate`; see `handleRewrite`.\n if (!aiPermissions?.loaded) {\n return void enqueueSnackbar(PERMISSIONS_PENDING, {\n variant: 'info',\n persist: false,\n })\n }\n if (!aiPermissions.generate) {\n return void enqueueSnackbar(AI_GENERATE_REFUSED, {\n variant: 'warning',\n persist: false,\n })\n }\n // AGL-1380: same gate as `handleRewrite`.\n if (!orgReady) {\n return void enqueueSnackbar('Checking your plan — try again in a moment', {\n variant: 'info',\n persist: false,\n })\n }\n if (!checkEntitlement(org as never, 'aiAssist')) {\n return void enqueueSnackbar(assistNotOnPlanText(), {\n variant: 'warning',\n persist: false,\n })\n }\n setSectionPrompt('')\n setSectionOpen(true)\n }, [org, orgReady, aiPermissions, enqueueSnackbar])\n\n const handleSectionConfirm = useCallback(async () => {\n if (!sectionPrompt.trim() || busy) return\n setBusy(true)\n try {\n const response = await authorizedFetch(user, '/api/ai/assist', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n orgId,\n hostId,\n mode: 'section',\n instruction: sectionPrompt.trim(),\n ...(sectionModel.model ? { model: sectionModel.model } : {}),\n }),\n })\n const payload = await response.json()\n publishMeter(payload?.meter)\n // Same pause notice on the section-generation door (AGL-1532).\n const locked = parseLockdownRefusal(response.status, payload)\n if (locked) {\n return void enqueueSnackbar(lockdownRefusalText(locked), {\n variant: 'warning',\n persist: true,\n })\n }\n if (response.status === 501) {\n return void enqueueSnackbar(\n 'AI assist is not configured on this deployment',\n { variant: 'info', persist: false },\n )\n }\n if (!response.ok || !payload?.section?.rootId) {\n return void enqueueSnackbar(payload?.error ?? 'AI request failed', {\n variant: 'error',\n allowDuplicate: true,\n })\n }\n const nested = portableDefinitionToNested(\n payload.section.rootId,\n payload.section.nodes,\n )\n if (!nested) {\n return void enqueueSnackbar('AI returned an empty section', {\n variant: 'error',\n allowDuplicate: true,\n })\n }\n // Graft through the preset path: ids regenerate, history is saved,\n // and the subtree lands at the end of the canvas root.\n const stamped = (function stamp(node: any): any {\n const schema = Aglyn.components.getSchema(node.componentId)\n return {\n ...node,\n ...(schema?.pluginId ? { pluginId: schema.pluginId } : {}),\n nodes: (node.nodes ?? []).map(stamp),\n }\n })(nested)\n Aglyn.canvas.addNodeFromPreset(\n { type: Aglyn.NodeType.PRESET, data: stamped } as any,\n Aglyn.canvas.rootNode as any,\n )\n setSectionOpen(false)\n enqueueSnackbar('Section added — undo removes it', {\n variant: 'success',\n persist: false,\n })\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', {\n variant: 'error',\n allowDuplicate: true,\n })\n } finally {\n setBusy(false)\n }\n }, [\n sectionPrompt,\n busy,\n user,\n orgId,\n hostId,\n sectionModel.model,\n publishMeter,\n enqueueSnackbar,\n ])\n\n // A REFUSED key publishes no callback (AGL-2927): the besigner controls\n // render only when the callback exists, so the refusal removes\n // the button rather than dimming it. A PENDING answer keeps both\n // callbacks, and each holds with a notice when pressed — a control that\n // vanishes and reappears while the read lands is worse than one that is\n // briefly inert (the `useHostRole` argument, applied here).\n const refusedUse = aiPermissions?.loaded === true && !aiPermissions.use\n const refusedGenerate =\n aiPermissions?.loaded === true && !aiPermissions.generate\n const contextValue = useMemo(\n () => ({\n ...(refusedUse ? {} : { onRewrite: handleRewrite }),\n ...(refusedGenerate ? {} : { onGenerateSection: handleGenerateSection }),\n }),\n [handleRewrite, handleGenerateSection, refusedUse, refusedGenerate],\n )\n\n return (\n <AiAssistActionsContext.Provider value={contextValue}>\n {children}\n <Dialog\n open={Boolean(node)}\n onClose={() => (busy ? null : setNode(null))}\n maxWidth=\"xs\"\n fullWidth\n >\n <DialogTitle>{'Rewrite with AI'}</DialogTitle>\n <DialogContent\n sx={{ display: 'flex', flexDirection: 'column', gap: 2, pt: 1 }}\n >\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Describe how the text should change — tone, length, message.'}\n </Typography>\n {textTargets.length > 1 ? (\n <TextField\n select\n label=\"Field\"\n value={effectiveTarget}\n onChange={(event) => setTargetProp(event.target.value)}\n size=\"small\"\n disabled={busy}\n >\n {textTargets.map((item) => (\n <MenuItem key={item.prop} value={item.prop}>\n {item.label}\n </MenuItem>\n ))}\n </TextField>\n ) : null}\n <TextField\n label=\"Instruction\"\n placeholder=\"e.g. Make it punchier and half as long\"\n value={instruction}\n onChange={(event) => setInstruction(event.target.value)}\n size=\"small\"\n autoFocus\n multiline\n minRows={2}\n disabled={busy}\n onKeyDown={(event) => {\n if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n handleConfirm()\n }\n }}\n />\n <AiModelSelector choice={copyModel} disabled={busy} />\n <AiUsageStrip orgId={orgId} />\n </DialogContent>\n <DialogActions>\n <Button disabled={busy} onClick={() => setNode(null)}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n disabled={!instruction.trim() || busy}\n startIcon={busy ? <CircularProgress size={16} /> : undefined}\n onClick={handleConfirm}\n >\n {busy ? 'Rewriting…' : 'Rewrite'}\n </Button>\n </DialogActions>\n </Dialog>\n <Dialog\n open={sectionOpen}\n onClose={() => (busy ? null : setSectionOpen(false))}\n maxWidth=\"xs\"\n fullWidth\n >\n <DialogTitle>{'Generate a section with AI'}</DialogTitle>\n <DialogContent\n sx={{ display: 'flex', flexDirection: 'column', gap: 2, pt: 1 }}\n >\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Describe the section — e.g. \"hero with headline, subtext, ' +\n 'and a call-to-action button\" or \"three-column feature grid\".'}\n </Typography>\n <TextField\n label=\"Section\"\n value={sectionPrompt}\n onChange={(event) => setSectionPrompt(event.target.value)}\n size=\"small\"\n autoFocus\n multiline\n minRows={2}\n disabled={busy}\n onKeyDown={(event) => {\n if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n handleSectionConfirm()\n }\n }}\n />\n <AiModelSelector choice={sectionModel} disabled={busy} />\n <AiUsageStrip orgId={orgId} />\n </DialogContent>\n <DialogActions>\n <Button disabled={busy} onClick={() => setSectionOpen(false)}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n disabled={!sectionPrompt.trim() || busy}\n startIcon={busy ? <CircularProgress size={16} /> : undefined}\n onClick={handleSectionConfirm}\n >\n {busy ? 'Generating…' : 'Generate'}\n </Button>\n </DialogActions>\n </Dialog>\n </AiAssistActionsContext.Provider>\n )\n}\nAiAssistProvider.displayName = 'AiAssistProvider'\n\nexport default AiAssistProvider\n"],"names":["Aglyn","checkEntitlement","lockdownRefusalText","parseLockdownRefusal","portableDefinitionToNested","AiAssistActionsContext","assistNotOnPlanText","useSnackbar","Button","CircularProgress","Dialog","DialogActions","DialogContent","DialogTitle","MenuItem","TextField","Typography","useCallback","useMemo","useState","useUser","authorizedFetch","AiModelSelector","AiUsageStrip","useAiModelChoice","usePublishAiUsageMeter","PERMISSIONS_PENDING","AI_USE_REFUSED","AI_GENERATE_REFUSED","AiAssistProvider","props","textTargets","org","orgReady","orgId","hostId","aiPermissions","children","enqueueSnackbar","data","user","node","setNode","instruction","setInstruction","targetProp","setTargetProp","busy","setBusy","sectionOpen","setSectionOpen","sectionPrompt","setSectionPrompt","copyModel","surface","kind","sectionModel","publishMeter","schema","componentSchema","textEditable","flags","FEATURE_FLAG","DISABLED","ENABLED","attributes","filter","field","component","FieldComponentType","TEXT_FIELD","TEXTAREA","map","prop","String","name","label","handleRewrite","target","loaded","variant","persist","use","effectiveTarget","some","item","handleConfirm","trim","current","canvas","toJSON","nodes","$id","text","response","method","headers","body","JSON","stringify","model","payload","json","meter","locked","status","ok","error","allowDuplicate","updateNodeProps","html","undefined","console","handleGenerateSection","generate","handleSectionConfirm","mode","section","rootId","nested","stamped","stamp","components","getSchema","componentId","pluginId","addNodeFromPreset","type","NodeType","PRESET","rootNode","refusedUse","refusedGenerate","contextValue","onRewrite","onGenerateSection","Provider","value","open","Boolean","onClose","maxWidth","fullWidth","sx","display","flexDirection","gap","pt","color","length","select","onChange","event","size","disabled","placeholder","autoFocus","multiline","minRows","onKeyDown","key","metaKey","ctrlKey","preventDefault","choice","onClick","startIcon","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAEA,YAAYA,WAAW,eAAc;AACrC,SACEC,gBAAgB,EAChBC,mBAAmB,EACnBC,oBAAoB,QACf,eAAc;AACrB,SAASC,0BAA0B,QAAQ,mDAAkD;AAC7F,SAASC,sBAAsB,QAAQ,iCAA6B;AACpE,SAASC,mBAAmB,QAAQ,6BAAyB;AAC7D,SAASC,WAAW,QAAQ,8BAA6B;AACzD,SACEC,MAAM,EACNC,gBAAgB,EAChBC,MAAM,EACNC,aAAa,EACbC,aAAa,EACbC,WAAW,EACXC,QAAQ,EACRC,SAAS,EACTC,UAAU,QACL,gBAAe;AACtB,SAASC,WAAW,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,QAAO;AACtD,SAASC,OAAO,QAAQ,iCAAgC;AACxD,SAASC,eAAe,QAAQ,2CAA0C;AAC1E,SAASC,eAAe,QAAQ,mCAA+B;AAC/D,SAASC,YAAY,QAAQ,gCAA4B;AACzD,SAASC,gBAAgB,QAAQ,2BAAuB;AACxD,SAASC,sBAAsB,QAAQ,0BAAsB;AAuC7D,MAAMC,sBAAsB;AAC5B,MAAMC,iBACJ;AACF,MAAMC,sBACJ;AAEF;;;;;;CAMC,GACD,OAAO,SAASC,iBAAiBC,KAA4B;QAI5CA;QAwFVC;IA3FL,MAAMC,MAAMF,MAAME,GAAG;IACrB,MAAMC,WAAWH,MAAMG,QAAQ;IAC/B,MAAMC,QAAQJ,MAAMI,KAAK;IACzB,MAAMC,UAASL,gBAAAA,MAAMK,MAAM,YAAZL,gBAAgB;IAC/B,MAAMM,gBAAgBN,MAAMM,aAAa;IACzC,MAAM,EAAEC,QAAQ,EAAE,GAAGP;IACrB,MAAM,EAAEQ,eAAe,EAAE,GAAG/B;IAC5B,MAAM,EAAEgC,MAAMC,IAAI,EAAE,GAAGpB;IACvB,MAAM,CAACqB,MAAMC,QAAQ,GAAGvB,SAAuC;IAC/D,MAAM,CAACwB,aAAaC,eAAe,GAAGzB,SAAS;IAC/C,sEAAsE;IACtE,wEAAwE;IACxE,MAAM,CAAC0B,YAAYC,cAAc,GAAG3B,SAAS;IAC7C,MAAM,CAAC4B,MAAMC,QAAQ,GAAG7B,SAAS;IACjC,8BAA8B;IAC9B,MAAM,CAAC8B,aAAaC,eAAe,GAAG/B,SAAS;IAC/C,MAAM,CAACgC,eAAeC,iBAAiB,GAAGjC,SAAS;IACnD,wEAAwE;IACxE,uEAAuE;IACvE,6BAA6B;IAC7B,MAAMkC,YAAY7B,iBAAiB;QAAEU;QAAOC;QAAQmB,SAAS;QAAQC,MAAM;IAAe;IAC1F,MAAMC,eAAehC,iBAAiB;QACpCU;QACAC;QACAmB,SAAS;QACTC,MAAM;IACR;IACA,MAAME,eAAehC,uBAAuBS;IAE5C,MAAMH,cAAcb,QAAQ;;YAGtBwC;QAFJ,MAAMA,SAASjB,wBAAAA,KAAMkB,eAAe;QACpC,MAAMC,eACJ,AAAC,CAAA,SAACF,2BAAAA,gBAAAA,OAAQG,KAAK,qBAAbH,cAAeE,YAAY,mBAAI5D,MAAM8D,YAAY,CAACC,QAAQ,IAC1D/D,MAAM8D,YAAY,CAACE,OAAO,AAAD,MAC3B;QACF,MAAMC,aAAa,UAACP,0BAAAA,OAAQO,UAAU,oBAAI,EAAE,EACzCC,MAAM,CACL,CAACC,QACCA,MAAMC,SAAS,KAAKpE,MAAMqE,kBAAkB,CAACC,UAAU,IACvDH,MAAMC,SAAS,KAAKpE,MAAMqE,kBAAkB,CAACE,QAAQ,EAExDC,GAAG,CAAC,CAACL;gBAEUA;mBAFM;gBACpBM,MAAMC,OAAOP,MAAMQ,IAAI;gBACvBC,OAAOF,QAAOP,eAAAA,MAAMS,KAAK,YAAXT,eAAeA,MAAMQ,IAAI;YACzC;;QACF,OAAOf,eACH;YAAC;gBAAEa,MAAM;gBAAYG,OAAO;YAAe;eAAMX;SAAW,GAC5DA;IACN,GAAG;QAACxB;KAAK;IAET,MAAMoC,gBAAgB5D,YACpB,CAAC6D;QACC,sEAAsE;QACtE,kEAAkE;QAClE,mEAAmE;QACnE,8CAA8C;QAC9C,IAAI,EAAC1C,iCAAAA,cAAe2C,MAAM,GAAE;YAC1B,OAAO,KAAKzC,gBAAgBZ,qBAAqB;gBAC/CsD,SAAS;gBACTC,SAAS;YACX;QACF;QACA,IAAI,CAAC7C,cAAc8C,GAAG,EAAE;YACtB,OAAO,KAAK5C,gBAAgBX,gBAAgB;gBAC1CqD,SAAS;gBACTC,SAAS;YACX;QACF;QACA,kEAAkE;QAClE,IAAI,CAAChD,UAAU;YACb,OAAO,KAAKK,gBACV,8CACA;gBAAE0C,SAAS;gBAAQC,SAAS;YAAM;QAEtC;QACA,IAAI,CAAChF,iBAAiB+B,KAAc,aAAa;YAC/C,OAAO,KAAKM,gBAAgBhC,uBAAuB;gBACjD0E,SAAS;gBACTC,SAAS;YACX;QACF;QACArC,eAAe;QACfE,cAAc;QACdJ,QAAQoC;IACV,GACA;QAAC9C;QAAKC;QAAUG;QAAeE;KAAgB;IAGjD,kDAAkD;IAClD,MAAM6C,kBAAkBpD,YAAYqD,IAAI,CAAC,CAACC,OAASA,KAAKZ,IAAI,KAAK5B,cAC7DA,sBACCd,gBAAAA,WAAW,CAAC,EAAE,qBAAdA,cAAgB0C,IAAI,mBAAI;IAE7B,MAAMa,gBAAgBrE,YAAY;QAChC,IAAI,CAACwB,QAAQ,CAACE,YAAY4C,IAAI,MAAMxC,MAAM;QAC1CC,QAAQ;QACR,IAAI;gBAKOwC;YAJT,MAAMA,UAAU,AAACxF,MAAMyF,MAAM,CAACC,MAAM,GAAGC,KAAK,AAAwB,CAClElD,KAAKmD,GAAG,CACT;YACD,MAAMC,OACJ,QAAOL,4BAAAA,iBAAAA,QAAS1D,KAAK,qBAAd0D,cAAgB,CAACL,gBAAgB,MAAK,WACxCK,QAAQ1D,KAAK,CAACqD,gBAAgB,GAC/B;YACN,MAAMW,WAAW,MAAMzE,gBAAgBmB,MAAM,kBAAkB;gBAC7DuD,QAAQ;gBACRC,SAAS;oBAAE,gBAAgB;gBAAmB;gBAC9CC,MAAMC,KAAKC,SAAS,CAAC;oBACnBjE;oBACAC;oBACA0D;oBACAlD,aAAaA,YAAY4C,IAAI;mBACzBlC,UAAU+C,KAAK,GAAG;oBAAEA,OAAO/C,UAAU+C,KAAK;gBAAC,IAAI,CAAC;YAExD;YACA,MAAMC,UAAU,MAAMP,SAASQ,IAAI;YACnC7C,aAAa4C,2BAAAA,QAASE,KAAK;YAC3B,sEAAsE;YACtE,oEAAoE;YACpE,sEAAsE;YACtE,gBAAgB;YAChB,MAAMC,SAASrG,qBAAqB2F,SAASW,MAAM,EAAEJ;YACrD,IAAIG,QAAQ;gBACV,OAAO,KAAKlE,gBAAgBpC,oBAAoBsG,SAAS;oBACvDxB,SAAS;oBACTC,SAAS;gBACX;YACF;YACA,IAAIa,SAASW,MAAM,KAAK,KAAK;gBAC3B,OAAO,KAAKnE,gBACV,kDACA;oBAAE0C,SAAS;oBAAQC,SAAS;gBAAM;YAEtC;YACA,IAAI,CAACa,SAASY,EAAE,IAAI,EAACL,2BAAAA,QAASR,IAAI,GAAE;;gBAClC,OAAO,KAAKvD,wBAAgB+D,2BAAAA,QAASM,KAAK,mBAAI,qBAAqB;oBACjE3B,SAAS;oBACT4B,gBAAgB;gBAClB;YACF;YACA5G,MAAMyF,MAAM,CAACoB,eAAe,CAACpE,MAAM,aAC9B+C,2BAAAA,QAAS1D,KAAK;gBACjB,CAACqD,gBAAgB,EAAEkB,QAAQR,IAAI;eAG3BV,oBAAoB,aAAa;gBAAE2B,MAAMC;YAAU,IAAI,CAAC;YAE9DrE,QAAQ;YACRJ,gBAAgB,+CAA+C;gBAC7D0C,SAAS;gBACTC,SAAS;YACX;QACF,EAAE,OAAO0B,OAAO;YACdK,QAAQL,KAAK,CAACA;YACdrE,gBAAgB,yBAAyB;gBACvC0C,SAAS;gBACT4B,gBAAgB;YAClB;QACF,SAAU;YACR5D,QAAQ;QACV;IACF,GAAG;QACDP;QACAE;QACAI;QACAP;QACA2C;QACAjD;QACAC;QACAkB,UAAU+C,KAAK;QACf3C;QACAnB;KACD;IAED,MAAM2E,wBAAwBhG,YAAY;QACxC,uEAAuE;QACvE,uDAAuD;QACvD,IAAI,EAACmB,iCAAAA,cAAe2C,MAAM,GAAE;YAC1B,OAAO,KAAKzC,gBAAgBZ,qBAAqB;gBAC/CsD,SAAS;gBACTC,SAAS;YACX;QACF;QACA,IAAI,CAAC7C,cAAc8E,QAAQ,EAAE;YAC3B,OAAO,KAAK5E,gBAAgBV,qBAAqB;gBAC/CoD,SAAS;gBACTC,SAAS;YACX;QACF;QACA,0CAA0C;QAC1C,IAAI,CAAChD,UAAU;YACb,OAAO,KAAKK,gBAAgB,8CAA8C;gBACxE0C,SAAS;gBACTC,SAAS;YACX;QACF;QACA,IAAI,CAAChF,iBAAiB+B,KAAc,aAAa;YAC/C,OAAO,KAAKM,gBAAgBhC,uBAAuB;gBACjD0E,SAAS;gBACTC,SAAS;YACX;QACF;QACA7B,iBAAiB;QACjBF,eAAe;IACjB,GAAG;QAAClB;QAAKC;QAAUG;QAAeE;KAAgB;IAElD,MAAM6E,uBAAuBlG,YAAY;QACvC,IAAI,CAACkC,cAAcoC,IAAI,MAAMxC,MAAM;QACnCC,QAAQ;QACR,IAAI;gBA4BmBqD;YA3BrB,MAAMP,WAAW,MAAMzE,gBAAgBmB,MAAM,kBAAkB;gBAC7DuD,QAAQ;gBACRC,SAAS;oBAAE,gBAAgB;gBAAmB;gBAC9CC,MAAMC,KAAKC,SAAS,CAAC;oBACnBjE;oBACAC;oBACAiF,MAAM;oBACNzE,aAAaQ,cAAcoC,IAAI;mBAC3B/B,aAAa4C,KAAK,GAAG;oBAAEA,OAAO5C,aAAa4C,KAAK;gBAAC,IAAI,CAAC;YAE9D;YACA,MAAMC,UAAU,MAAMP,SAASQ,IAAI;YACnC7C,aAAa4C,2BAAAA,QAASE,KAAK;YAC3B,+DAA+D;YAC/D,MAAMC,SAASrG,qBAAqB2F,SAASW,MAAM,EAAEJ;YACrD,IAAIG,QAAQ;gBACV,OAAO,KAAKlE,gBAAgBpC,oBAAoBsG,SAAS;oBACvDxB,SAAS;oBACTC,SAAS;gBACX;YACF;YACA,IAAIa,SAASW,MAAM,KAAK,KAAK;gBAC3B,OAAO,KAAKnE,gBACV,kDACA;oBAAE0C,SAAS;oBAAQC,SAAS;gBAAM;YAEtC;YACA,IAAI,CAACa,SAASY,EAAE,IAAI,EAACL,4BAAAA,mBAAAA,QAASgB,OAAO,qBAAhBhB,iBAAkBiB,MAAM,GAAE;;gBAC7C,OAAO,KAAKhF,wBAAgB+D,2BAAAA,QAASM,KAAK,mBAAI,qBAAqB;oBACjE3B,SAAS;oBACT4B,gBAAgB;gBAClB;YACF;YACA,MAAMW,SAASnH,2BACbiG,QAAQgB,OAAO,CAACC,MAAM,EACtBjB,QAAQgB,OAAO,CAAC1B,KAAK;YAEvB,IAAI,CAAC4B,QAAQ;gBACX,OAAO,KAAKjF,gBAAgB,gCAAgC;oBAC1D0C,SAAS;oBACT4B,gBAAgB;gBAClB;YACF;YACA,mEAAmE;YACnE,uDAAuD;YACvD,MAAMY,UAAU,AAAC,SAASC,MAAMhF,IAAS;oBAK7BA;gBAJV,MAAMiB,SAAS1D,MAAM0H,UAAU,CAACC,SAAS,CAAClF,KAAKmF,WAAW;gBAC1D,OAAO,aACFnF,MACCiB,CAAAA,0BAAAA,OAAQmE,QAAQ,IAAG;oBAAEA,UAAUnE,OAAOmE,QAAQ;gBAAC,IAAI,CAAC;oBACxDlC,OAAO,EAAClD,cAAAA,KAAKkD,KAAK,YAAVlD,cAAc,EAAE,EAAE+B,GAAG,CAACiD;;YAElC,EAAGF;YACHvH,MAAMyF,MAAM,CAACqC,iBAAiB,CAC5B;gBAAEC,MAAM/H,MAAMgI,QAAQ,CAACC,MAAM;gBAAE1F,MAAMiF;YAAQ,GAC7CxH,MAAMyF,MAAM,CAACyC,QAAQ;YAEvBhF,eAAe;YACfZ,gBAAgB,mCAAmC;gBACjD0C,SAAS;gBACTC,SAAS;YACX;QACF,EAAE,OAAO0B,OAAO;YACdK,QAAQL,KAAK,CAACA;YACdrE,gBAAgB,yBAAyB;gBACvC0C,SAAS;gBACT4B,gBAAgB;YAClB;QACF,SAAU;YACR5D,QAAQ;QACV;IACF,GAAG;QACDG;QACAJ;QACAP;QACAN;QACAC;QACAqB,aAAa4C,KAAK;QAClB3C;QACAnB;KACD;IAED,wEAAwE;IACxE,+DAA+D;IAC/D,iEAAiE;IACjE,wEAAwE;IACxE,wEAAwE;IACxE,4DAA4D;IAC5D,MAAM6F,aAAa/F,CAAAA,iCAAAA,cAAe2C,MAAM,MAAK,QAAQ,CAAC3C,cAAc8C,GAAG;IACvE,MAAMkD,kBACJhG,CAAAA,iCAAAA,cAAe2C,MAAM,MAAK,QAAQ,CAAC3C,cAAc8E,QAAQ;IAC3D,MAAMmB,eAAenH,QACnB,IAAO,aACDiH,aAAa,CAAC,IAAI;YAAEG,WAAWzD;QAAc,GAC7CuD,kBAAkB,CAAC,IAAI;YAAEG,mBAAmBtB;QAAsB,IAExE;QAACpC;QAAeoC;QAAuBkB;QAAYC;KAAgB;IAGrE,qBACE,MAAC/H,uBAAuBmI,QAAQ;QAACC,OAAOJ;;YACrChG;0BACD,MAAC3B;gBACCgI,MAAMC,QAAQlG;gBACdmG,SAAS,IAAO7F,OAAO,OAAOL,QAAQ;gBACtCmG,UAAS;gBACTC,SAAS;;kCAET,KAACjI;kCAAa;;kCACd,MAACD;wBACCmI,IAAI;4BAAEC,SAAS;4BAAQC,eAAe;4BAAUC,KAAK;4BAAGC,IAAI;wBAAE;;0CAE9D,KAACnI;gCAAWgE,SAAQ;gCAAQoE,OAAM;0CAC/B;;4BAEFrH,YAAYsH,MAAM,GAAG,kBACpB,KAACtI;gCACCuI,MAAM;gCACN1E,OAAM;gCACN6D,OAAOtD;gCACPoE,UAAU,CAACC,QAAU1G,cAAc0G,MAAM1E,MAAM,CAAC2D,KAAK;gCACrDgB,MAAK;gCACLC,UAAU3G;0CAEThB,YAAYyC,GAAG,CAAC,CAACa,qBAChB,KAACvE;wCAAyB2H,OAAOpD,KAAKZ,IAAI;kDACvCY,KAAKT,KAAK;uCADES,KAAKZ,IAAI;iCAK1B;0CACJ,KAAC1D;gCACC6D,OAAM;gCACN+E,aAAY;gCACZlB,OAAO9F;gCACP4G,UAAU,CAACC,QAAU5G,eAAe4G,MAAM1E,MAAM,CAAC2D,KAAK;gCACtDgB,MAAK;gCACLG,SAAS;gCACTC,SAAS;gCACTC,SAAS;gCACTJ,UAAU3G;gCACVgH,WAAW,CAACP;oCACV,IAAIA,MAAMQ,GAAG,KAAK,WAAYR,CAAAA,MAAMS,OAAO,IAAIT,MAAMU,OAAO,AAAD,GAAI;wCAC7DV,MAAMW,cAAc;wCACpB7E;oCACF;gCACF;;0CAEF,KAAChE;gCAAgB8I,QAAQ/G;gCAAWqG,UAAU3G;;0CAC9C,KAACxB;gCAAaW,OAAOA;;;;kCAEvB,MAACvB;;0CACC,KAACH;gCAAOkJ,UAAU3G;gCAAMsH,SAAS,IAAM3H,QAAQ;0CAC5C;;0CAEH,KAAClC;gCACCwE,SAAQ;gCACRoE,OAAM;gCACNM,UAAU,CAAC/G,YAAY4C,IAAI,MAAMxC;gCACjCuH,WAAWvH,qBAAO,KAACtC;oCAAiBgJ,MAAM;qCAAS1C;gCACnDsD,SAAS/E;0CAERvC,OAAO,eAAe;;;;;;0BAI7B,MAACrC;gBACCgI,MAAMzF;gBACN2F,SAAS,IAAO7F,OAAO,OAAOG,eAAe;gBAC7C2F,UAAS;gBACTC,SAAS;;kCAET,KAACjI;kCAAa;;kCACd,MAACD;wBACCmI,IAAI;4BAAEC,SAAS;4BAAQC,eAAe;4BAAUC,KAAK;4BAAGC,IAAI;wBAAE;;0CAE9D,KAACnI;gCAAWgE,SAAQ;gCAAQoE,OAAM;0CAC/B,+DACC;;0CAEJ,KAACrI;gCACC6D,OAAM;gCACN6D,OAAOtF;gCACPoG,UAAU,CAACC,QAAUpG,iBAAiBoG,MAAM1E,MAAM,CAAC2D,KAAK;gCACxDgB,MAAK;gCACLG,SAAS;gCACTC,SAAS;gCACTC,SAAS;gCACTJ,UAAU3G;gCACVgH,WAAW,CAACP;oCACV,IAAIA,MAAMQ,GAAG,KAAK,WAAYR,CAAAA,MAAMS,OAAO,IAAIT,MAAMU,OAAO,AAAD,GAAI;wCAC7DV,MAAMW,cAAc;wCACpBhD;oCACF;gCACF;;0CAEF,KAAC7F;gCAAgB8I,QAAQ5G;gCAAckG,UAAU3G;;0CACjD,KAACxB;gCAAaW,OAAOA;;;;kCAEvB,MAACvB;;0CACC,KAACH;gCAAOkJ,UAAU3G;gCAAMsH,SAAS,IAAMnH,eAAe;0CACnD;;0CAEH,KAAC1C;gCACCwE,SAAQ;gCACRoE,OAAM;gCACNM,UAAU,CAACvG,cAAcoC,IAAI,MAAMxC;gCACnCuH,WAAWvH,qBAAO,KAACtC;oCAAiBgJ,MAAM;qCAAS1C;gCACnDsD,SAASlD;0CAERpE,OAAO,gBAAgB;;;;;;;;AAMpC;AACAlB,iBAAiB0I,WAAW,GAAG;AAE/B,eAAe1I,iBAAgB"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-assist-provider.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 {\n canvas,\n checkEntitlement,\n components,\n FEATURE_FLAG,\n FieldComponentType,\n lockdownRefusalText,\n NodeType,\n parseLockdownRefusal,\n type NodeSchema,\n} from '@aglyn/aglyn'\nimport { portableDefinitionToNested } from '@aglyn/aglyn/app-utils/node-definition-sanitizer'\nimport { AiAssistActionsContext } from './ai-assist-actions-context'\nimport { assistNotOnPlanText } from '../usage/assist-credits'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport {\n Button,\n CircularProgress,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n MenuItem,\n TextField,\n Typography,\n} from '@mui/material'\nimport { useCallback, useMemo, useState } from 'react'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { AiModelSelector } from './ai-model-selector.component'\nimport { AiUsageStrip } from './ai-usage-strip.component'\nimport { useAiModelChoice } from './use-ai-model-choice'\nimport { usePublishAiUsageMeter } from './use-ai-usage-meter'\n\n\nexport interface AiAssistProviderProps {\n /** Org billing doc for the entitlement gate (mounted by the shell). */\n org?: unknown\n /**\n * True once `org` is a trustworthy answer (AGL-1380). The shell mounts\n * this provider above the whole console route tree, so it cannot hold its\n * render until the billing doc settles the way the plugin-page route does\n * — and an undefined `org` is not \"unknown\" to `checkEntitlement`, it is\n * the free tier. Without this flag the gates below told a Pro org that AI\n * assist is not on its plan for as long as the read was in flight.\n */\n orgReady?: boolean\n /**\n * The org every assist call is metered against (AGL-2073). The route no\n * longer resolves it from the signed-in user — a user with one paid org was\n * getting assist on all of their free ones, and their spend was landing on\n * whichever org the server happened to resolve.\n */\n orgId?: string\n /**\n * The site the canvas belongs to (AGL-2927), sent with every assist call\n * so the door can decide a site collaborator's permission on THAT site.\n * Null off a host route, where there is no canvas to assist on.\n */\n hostId?: string | null\n /**\n * The reader's AI verdict, resolved by the shell (AGL-2927). The gates\n * below HOLD until `loaded` — a door opened on a pending answer would\n * spend the workspace's credits on a permission nobody has confirmed —\n * and a refused key removes its callback from the context, so the\n * designer draws no control for it. Omitted, the answer is pending.\n */\n aiPermissions?: { loaded: boolean; use: boolean; generate: boolean }\n children?: JSX.Children\n}\n\nconst PERMISSIONS_PENDING = 'Checking your permissions — try again in a moment'\nconst AI_USE_REFUSED =\n 'Your role does not include AI assistance — ask an organization admin'\nconst AI_GENERATE_REFUSED =\n 'Your role does not include AI generation — ask an organization admin'\n\n/**\n * Console-side AI copy assist (AGL-89): provides the designer's \"Rewrite\n * with AI\" callback, hosts the instruction dialog, and calls the assist API\n * (which 501-degrades when no AI provider is configured). The commit\n * spreads the node's current props — `updateNodeProps` REPLACES the props\n * object — and clears any stale rich-text `html` so the new text renders.\n */\nexport function AiAssistProvider(props: AiAssistProviderProps) {\n const org = props.org\n const orgReady = props.orgReady\n const orgId = props.orgId\n const hostId = props.hostId ?? null\n const aiPermissions = props.aiPermissions\n const { children } = props\n const { enqueueSnackbar } = useSnackbar()\n const { data: user } = useUser()\n const [node, setNode] = useState<NodeSchema<any> | null>(null)\n const [instruction, setInstruction] = useState('')\n // Rewrite target (AGL-130): 'children' for text-editable elements, or\n // any text attribute the element's schema declares (alt text, labels…).\n const [targetProp, setTargetProp] = useState('children')\n const [busy, setBusy] = useState(false)\n // Generate section (AGL-169).\n const [sectionOpen, setSectionOpen] = useState(false)\n const [sectionPrompt, setSectionPrompt] = useState('')\n // The model switch and the usage strip in both dialogs (AGL-2942). Each\n // dialog remembers its own pick; one envelope store serves both strips\n // and the assistant panel's.\n const copyModel = useAiModelChoice({ orgId, hostId, surface: 'copy', kind: 'copy.element' })\n const sectionModel = useAiModelChoice({\n orgId,\n hostId,\n surface: 'section',\n kind: 'copy.section',\n })\n const publishMeter = usePublishAiUsageMeter(orgId)\n\n const textTargets = useMemo(() => {\n const schema = node?.componentSchema\n const textEditable =\n ((schema?.flags?.textEditable ?? FEATURE_FLAG.DISABLED) &\n FEATURE_FLAG.ENABLED) !==\n 0\n const attributes = (schema?.attributes ?? [])\n .filter(\n (field: any) =>\n field.component === FieldComponentType.TEXT_FIELD ||\n field.component === FieldComponentType.TEXTAREA,\n )\n .map((field: any) => ({\n prop: String(field.name),\n label: String(field.label ?? field.name),\n }))\n return textEditable\n ? [{ prop: 'children', label: 'Element text' }, ...attributes]\n : attributes\n }, [node])\n\n const handleRewrite = useCallback(\n (target: NodeSchema<any>) => {\n // The permission first (AGL-2927): it is a fact about the reader, and\n // pending asserts nothing here either. The refusal is unreachable\n // through the designer — a refused key publishes no callback — and\n // stands for any other caller of the context.\n if (!aiPermissions?.loaded) {\n return void enqueueSnackbar(PERMISSIONS_PENDING, {\n variant: 'info',\n persist: false,\n })\n }\n if (!aiPermissions.use) {\n return void enqueueSnackbar(AI_USE_REFUSED, {\n variant: 'warning',\n persist: false,\n })\n }\n // AGL-1380: pending asserts nothing. See `orgReady` on the props.\n if (!orgReady) {\n return void enqueueSnackbar(\n 'Checking your plan — try again in a moment',\n { variant: 'info', persist: false },\n )\n }\n if (!checkEntitlement(org as never, 'aiAssist')) {\n return void enqueueSnackbar(assistNotOnPlanText(), {\n variant: 'warning',\n persist: false,\n })\n }\n setInstruction('')\n setTargetProp('children')\n setNode(target)\n },\n [org, orgReady, aiPermissions, enqueueSnackbar],\n )\n\n // Keep the target valid for the selected element.\n const effectiveTarget = textTargets.some((item) => item.prop === targetProp)\n ? targetProp\n : (textTargets[0]?.prop ?? 'children')\n\n const handleConfirm = useCallback(async () => {\n if (!node || !instruction.trim() || busy) return\n setBusy(true)\n try {\n const current = (canvas.toJSON().nodes as Record<string, any>)[\n node.$id\n ]\n const text =\n typeof current?.props?.[effectiveTarget] === 'string'\n ? (current.props[effectiveTarget] as string)\n : ''\n const response = await authorizedFetch(user, '/api/ai/assist', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n orgId,\n hostId,\n text,\n instruction: instruction.trim(),\n ...(copyModel.model ? { model: copyModel.model } : {}),\n }),\n })\n const payload = await response.json()\n publishMeter(payload?.meter)\n // An ai-assist feature lockdown (AGL-1510/1532) reads as a pause, not\n // as \"AI request failed\" — a provider incident or a cost runaway is\n // something WE turned off, and saying so keeps the user's content out\n // of the story.\n const locked = parseLockdownRefusal(response.status, payload)\n if (locked) {\n return void enqueueSnackbar(lockdownRefusalText(locked), {\n variant: 'warning',\n persist: true,\n })\n }\n if (response.status === 501) {\n return void enqueueSnackbar(\n 'AI assist is not configured on this deployment',\n { variant: 'info', persist: false },\n )\n }\n if (!response.ok || !payload?.text) {\n return void enqueueSnackbar(payload?.error ?? 'AI request failed', {\n variant: 'error',\n allowDuplicate: true,\n })\n }\n canvas.updateNodeProps(node, {\n ...current?.props,\n [effectiveTarget]: payload.text,\n // Rich-text elements render `html` over `children`; drop it so the\n // rewrite is what shows (the user can re-format inline afterwards).\n ...(effectiveTarget === 'children' ? { html: undefined } : {}),\n })\n setNode(null)\n enqueueSnackbar('Text rewritten — undo restores the original', {\n variant: 'success',\n persist: false,\n })\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', {\n variant: 'error',\n allowDuplicate: true,\n })\n } finally {\n setBusy(false)\n }\n }, [\n node,\n instruction,\n busy,\n user,\n effectiveTarget,\n orgId,\n hostId,\n copyModel.model,\n publishMeter,\n enqueueSnackbar,\n ])\n\n const handleGenerateSection = useCallback(() => {\n // The permission first (AGL-2927) — a section is a generation, so this\n // door sells under `ai.generate`; see `handleRewrite`.\n if (!aiPermissions?.loaded) {\n return void enqueueSnackbar(PERMISSIONS_PENDING, {\n variant: 'info',\n persist: false,\n })\n }\n if (!aiPermissions.generate) {\n return void enqueueSnackbar(AI_GENERATE_REFUSED, {\n variant: 'warning',\n persist: false,\n })\n }\n // AGL-1380: same gate as `handleRewrite`.\n if (!orgReady) {\n return void enqueueSnackbar('Checking your plan — try again in a moment', {\n variant: 'info',\n persist: false,\n })\n }\n if (!checkEntitlement(org as never, 'aiAssist')) {\n return void enqueueSnackbar(assistNotOnPlanText(), {\n variant: 'warning',\n persist: false,\n })\n }\n setSectionPrompt('')\n setSectionOpen(true)\n }, [org, orgReady, aiPermissions, enqueueSnackbar])\n\n const handleSectionConfirm = useCallback(async () => {\n if (!sectionPrompt.trim() || busy) return\n setBusy(true)\n try {\n const response = await authorizedFetch(user, '/api/ai/assist', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n orgId,\n hostId,\n mode: 'section',\n instruction: sectionPrompt.trim(),\n ...(sectionModel.model ? { model: sectionModel.model } : {}),\n }),\n })\n const payload = await response.json()\n publishMeter(payload?.meter)\n // Same pause notice on the section-generation door (AGL-1532).\n const locked = parseLockdownRefusal(response.status, payload)\n if (locked) {\n return void enqueueSnackbar(lockdownRefusalText(locked), {\n variant: 'warning',\n persist: true,\n })\n }\n if (response.status === 501) {\n return void enqueueSnackbar(\n 'AI assist is not configured on this deployment',\n { variant: 'info', persist: false },\n )\n }\n if (!response.ok || !payload?.section?.rootId) {\n return void enqueueSnackbar(payload?.error ?? 'AI request failed', {\n variant: 'error',\n allowDuplicate: true,\n })\n }\n const nested = portableDefinitionToNested(\n payload.section.rootId,\n payload.section.nodes,\n )\n if (!nested) {\n return void enqueueSnackbar('AI returned an empty section', {\n variant: 'error',\n allowDuplicate: true,\n })\n }\n // Graft through the preset path: ids regenerate, history is saved,\n // and the subtree lands at the end of the canvas root.\n const stamped = (function stamp(node: any): any {\n const schema = components.getSchema(node.componentId)\n return {\n ...node,\n ...(schema?.pluginId ? { pluginId: schema.pluginId } : {}),\n nodes: (node.nodes ?? []).map(stamp),\n }\n })(nested)\n canvas.addNodeFromPreset(\n { type: NodeType.PRESET, data: stamped } as any,\n canvas.rootNode as any,\n )\n setSectionOpen(false)\n enqueueSnackbar('Section added — undo removes it', {\n variant: 'success',\n persist: false,\n })\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', {\n variant: 'error',\n allowDuplicate: true,\n })\n } finally {\n setBusy(false)\n }\n }, [\n sectionPrompt,\n busy,\n user,\n orgId,\n hostId,\n sectionModel.model,\n publishMeter,\n enqueueSnackbar,\n ])\n\n // A REFUSED key publishes no callback (AGL-2927): the besigner controls\n // render only when the callback exists, so the refusal removes\n // the button rather than dimming it. A PENDING answer keeps both\n // callbacks, and each holds with a notice when pressed — a control that\n // vanishes and reappears while the read lands is worse than one that is\n // briefly inert (the `useHostRole` argument, applied here).\n const refusedUse = aiPermissions?.loaded === true && !aiPermissions.use\n const refusedGenerate =\n aiPermissions?.loaded === true && !aiPermissions.generate\n const contextValue = useMemo(\n () => ({\n ...(refusedUse ? {} : { onRewrite: handleRewrite }),\n ...(refusedGenerate ? {} : { onGenerateSection: handleGenerateSection }),\n }),\n [handleRewrite, handleGenerateSection, refusedUse, refusedGenerate],\n )\n\n return (\n <AiAssistActionsContext.Provider value={contextValue}>\n {children}\n <Dialog\n open={Boolean(node)}\n onClose={() => (busy ? null : setNode(null))}\n maxWidth=\"xs\"\n fullWidth\n >\n <DialogTitle>{'Rewrite with AI'}</DialogTitle>\n <DialogContent\n sx={{ display: 'flex', flexDirection: 'column', gap: 2, pt: 1 }}\n >\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Describe how the text should change — tone, length, message.'}\n </Typography>\n {textTargets.length > 1 ? (\n <TextField\n select\n label=\"Field\"\n value={effectiveTarget}\n onChange={(event) => setTargetProp(event.target.value)}\n size=\"small\"\n disabled={busy}\n >\n {textTargets.map((item) => (\n <MenuItem key={item.prop} value={item.prop}>\n {item.label}\n </MenuItem>\n ))}\n </TextField>\n ) : null}\n <TextField\n label=\"Instruction\"\n placeholder=\"e.g. Make it punchier and half as long\"\n value={instruction}\n onChange={(event) => setInstruction(event.target.value)}\n size=\"small\"\n autoFocus\n multiline\n minRows={2}\n disabled={busy}\n onKeyDown={(event) => {\n if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n handleConfirm()\n }\n }}\n />\n <AiModelSelector choice={copyModel} disabled={busy} />\n <AiUsageStrip orgId={orgId} />\n </DialogContent>\n <DialogActions>\n <Button disabled={busy} onClick={() => setNode(null)}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n disabled={!instruction.trim() || busy}\n startIcon={busy ? <CircularProgress size={16} /> : undefined}\n onClick={handleConfirm}\n >\n {busy ? 'Rewriting…' : 'Rewrite'}\n </Button>\n </DialogActions>\n </Dialog>\n <Dialog\n open={sectionOpen}\n onClose={() => (busy ? null : setSectionOpen(false))}\n maxWidth=\"xs\"\n fullWidth\n >\n <DialogTitle>{'Generate a section with AI'}</DialogTitle>\n <DialogContent\n sx={{ display: 'flex', flexDirection: 'column', gap: 2, pt: 1 }}\n >\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Describe the section — e.g. \"hero with headline, subtext, ' +\n 'and a call-to-action button\" or \"three-column feature grid\".'}\n </Typography>\n <TextField\n label=\"Section\"\n value={sectionPrompt}\n onChange={(event) => setSectionPrompt(event.target.value)}\n size=\"small\"\n autoFocus\n multiline\n minRows={2}\n disabled={busy}\n onKeyDown={(event) => {\n if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n handleSectionConfirm()\n }\n }}\n />\n <AiModelSelector choice={sectionModel} disabled={busy} />\n <AiUsageStrip orgId={orgId} />\n </DialogContent>\n <DialogActions>\n <Button disabled={busy} onClick={() => setSectionOpen(false)}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n disabled={!sectionPrompt.trim() || busy}\n startIcon={busy ? <CircularProgress size={16} /> : undefined}\n onClick={handleSectionConfirm}\n >\n {busy ? 'Generating…' : 'Generate'}\n </Button>\n </DialogActions>\n </Dialog>\n </AiAssistActionsContext.Provider>\n )\n}\nAiAssistProvider.displayName = 'AiAssistProvider'\n\nexport default AiAssistProvider\n"],"names":["canvas","checkEntitlement","components","FEATURE_FLAG","FieldComponentType","lockdownRefusalText","NodeType","parseLockdownRefusal","portableDefinitionToNested","AiAssistActionsContext","assistNotOnPlanText","useSnackbar","Button","CircularProgress","Dialog","DialogActions","DialogContent","DialogTitle","MenuItem","TextField","Typography","useCallback","useMemo","useState","useUser","authorizedFetch","AiModelSelector","AiUsageStrip","useAiModelChoice","usePublishAiUsageMeter","PERMISSIONS_PENDING","AI_USE_REFUSED","AI_GENERATE_REFUSED","AiAssistProvider","props","textTargets","org","orgReady","orgId","hostId","aiPermissions","children","enqueueSnackbar","data","user","node","setNode","instruction","setInstruction","targetProp","setTargetProp","busy","setBusy","sectionOpen","setSectionOpen","sectionPrompt","setSectionPrompt","copyModel","surface","kind","sectionModel","publishMeter","schema","componentSchema","textEditable","flags","DISABLED","ENABLED","attributes","filter","field","component","TEXT_FIELD","TEXTAREA","map","prop","String","name","label","handleRewrite","target","loaded","variant","persist","use","effectiveTarget","some","item","handleConfirm","trim","current","toJSON","nodes","$id","text","response","method","headers","body","JSON","stringify","model","payload","json","meter","locked","status","ok","error","allowDuplicate","updateNodeProps","html","undefined","console","handleGenerateSection","generate","handleSectionConfirm","mode","section","rootId","nested","stamped","stamp","getSchema","componentId","pluginId","addNodeFromPreset","type","PRESET","rootNode","refusedUse","refusedGenerate","contextValue","onRewrite","onGenerateSection","Provider","value","open","Boolean","onClose","maxWidth","fullWidth","sx","display","flexDirection","gap","pt","color","length","select","onChange","event","size","disabled","placeholder","autoFocus","multiline","minRows","onKeyDown","key","metaKey","ctrlKey","preventDefault","choice","onClick","startIcon","displayName"],"mappings":"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"}
|
|
@@ -17,6 +17,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
17
17
|
*/ import { AI_BUILD_PLAN_CREATION_NOUNS, AI_BUILD_PLAN_EMBED_HOST_NAMES, isAiPlanNewRef } from "../model/ai-build-plan.js";
|
|
18
18
|
import { aiJobCreditEstimate } from "../model/ai-build-job.js";
|
|
19
19
|
import { aiBuildOpNoun } from "../model/ai-build-progress.js";
|
|
20
|
+
import { aiJobConfirmingOwnPlan } from "../model/ai-job-activity.js";
|
|
20
21
|
import { aiSiteStarterFallbackOffered } from "../model/ai-job-failure-copy.js";
|
|
21
22
|
import { AiSiteStarterFallback } from "./ai-site-starter-fallback.component.js";
|
|
22
23
|
import { Box, Button, Checkbox, Collapse, FormControlLabel, Stack, Typography } from "@mui/material";
|
|
@@ -79,7 +80,8 @@ export function AiJobPlan({ job, onResume, busy = false, staff = false, user })
|
|
|
79
80
|
var _ref;
|
|
80
81
|
return !ref ? '' : isAiPlanNewRef(ref) ? ref.slice('new:'.length) : (_ref = plan == null ? void 0 : plan.labels[ref]) != null ? _ref : ref;
|
|
81
82
|
};
|
|
82
|
-
|
|
83
|
+
// A plan the machine is confirming itself is not one to confirm (AGL-3596).
|
|
84
|
+
const waiting = job.status === 'needs_review' && review !== null && !aiJobConfirmingOwnPlan(job);
|
|
83
85
|
// The guard rail (AGL-2911): what the plan is estimated to cost is read
|
|
84
86
|
// before it is confirmed, not after it has been spent. An estimate, and
|
|
85
87
|
// said to be one — the plan's own passes at the nominal credits a step
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-job-plan.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AI_BUILD_PLAN_CREATION_NOUNS,\n AI_BUILD_PLAN_EMBED_HOST_NAMES,\n isAiPlanNewRef,\n type AiBuildPlanEmbed,\n} from '../model/ai-build-plan'\nimport type { AiJobReview, AiJobSummary } from '../model/ai-jobs.types'\nimport { aiJobCreditEstimate } from '../model/ai-build-job'\nimport { aiBuildOpNoun } from '../model/ai-build-progress'\nimport { aiSiteStarterFallbackOffered } from '../model/ai-job-failure-copy'\nimport { AiSiteStarterFallback } from './ai-site-starter-fallback.component'\nimport { Box, Button, Checkbox, Collapse, FormControlLabel, Stack, Typography } from '@mui/material'\nimport { useState } from 'react'\n\n/**\n * A job's plan and what it waits for (AGL-2935), inside the AI jobs drawer\n * and the dialog that started the job (AGL-3593): what the job reuses from\n * the site, what it creates and why, the screens it builds — and, while the\n * job waits for a person, the one button that confirms the plan or tries a\n * refused step again. Both send the same request (`resumeAiJobRequest`);\n * this renders.\n */\nexport interface AiJobPlanProps {\n job: AiJobSummary\n /**\n * Confirms the plan, or tries the refused step again. A build whose request\n * asked to publish confirms with `publish` when its box is ticked (AGL-3616).\n */\n onResume: (job: AiJobSummary, options?: { publish?: boolean }) => void\n /** A resume for this job is in flight. */\n busy?: boolean\n /**\n * The viewer is staff (AGL-3078), who can open where a refused answer broke\n * its rules and the outline of those parts, to tell a shape the rules should\n * allow from an answer that ignored its re-ask. A member reads the findings.\n */\n staff?: boolean\n /**\n * The signed-in user, for \"Use the starter site instead\" on a guided start\n * that did not work out (AGL-3594); the action is drawn only when given.\n */\n user?: Parameters<typeof AiSiteStarterFallback>[0]['user']\n}\n\n/**\n * Where a refused answer broke its rules, and the outline of those parts, as\n * lines staff read (AGL-3078): each finding with the nodes or plan entries it\n * names, then each outlined node indented by its depth, with its element, a\n * Grid's layout as written, and the names of what it sets and holds.\n */\nexport function aiJobReviewDetails(review: AiJobReview | null): string[] {\n if (review?.reason !== 'doctrine') return []\n const lines = review.findings.flatMap((finding) => {\n const where = finding.nodeIds?.length\n ? `nodes ${finding.nodeIds.join(', ')}`\n : finding.paths?.length\n ? `at ${finding.paths.join(', ')}`\n : null\n return where ? [`${finding.rule === null ? '' : `Rule ${finding.rule} `}${finding.code}: ${where}`] : []\n })\n for (const node of review.outline ?? []) {\n lines.push(\n [\n `${' '.repeat(node.depth)}${node.id} ${node.componentId}`,\n ...Object.entries(node.grid ?? {}).map(([name, value]) => `${name}=${JSON.stringify(value)}`),\n ...(node.props.length ? [`props ${node.props.join(', ')}`] : []),\n ...(node.sx?.length ? [`sx ${node.sx.join(', ')}`] : []),\n ...(node.children.length ? [`holds ${node.children.join(', ')}`] : []),\n ].join(' · '),\n )\n }\n return lines\n}\n\n/**\n * A third-party player the plan lists, with what it costs the page, read\n * before the member confirms it (rule 16, AGL-3433). The cost is the\n * platform's sentence, never the model's: the player is framed lazily, so its\n * host's code loads when a visitor reaches it, whether or not they press play.\n */\nexport function aiPlanEmbedLine(\n embed: AiBuildPlanEmbed,\n named: (ref: string) => string,\n): string {\n const host = AI_BUILD_PLAN_EMBED_HOST_NAMES[embed.host]\n const where = isAiPlanNewRef(embed.where) ? `the component ${named(embed.where)}` : embed.where\n const link = embed.url ? ` playing ${embed.url}` : ', its link left for you to paste'\n return `Embeds a ${host} player on ${where}${link}, as you asked (“${embed.asked}”). It loads ${host}’s own code when a visitor reaches it, whether or not they press play.`\n}\n\nexport function AiJobPlan({\n job,\n onResume,\n busy = false,\n staff = false,\n user,\n}: AiJobPlanProps): JSX.Element | null {\n const [detailsOpen, setDetailsOpen] = useState(false)\n // Unticked until the person ticks it: a build publishes only when its\n // request asked AND they confirm it here (AGL-3616).\n const [publish, setPublish] = useState(false)\n const { plan, review } = job\n if (!plan && !review) return null\n const details = staff ? aiJobReviewDetails(review) : []\n /** A reference as a person reads it: the record's name, or what the plan creates. */\n const named = (ref: string | null): string =>\n !ref\n ? ''\n : isAiPlanNewRef(ref)\n ? ref.slice('new:'.length)\n : (plan?.labels[ref] ?? ref)\n const waiting = job.status === 'needs_review' && review !== null\n // The guard rail (AGL-2911): what the plan is estimated to cost is read\n // before it is confirmed, not after it has been spent. An estimate, and\n // said to be one — the plan's own passes at the nominal credits a step\n // holds, where what a step really costs is its model's tokens. A page job\n // counts the creations it builds before its page (AGL-3031).\n const estimate =\n plan && waiting && review.reason === 'plan' ? aiJobCreditEstimate(job.kind, plan) : 0\n const offersPublish = job.kind === 'build' && job.publishAsked === true && waiting && review.reason === 'plan'\n return (\n <Box sx={{ mt: 1 }}>\n {plan && (\n <Stack spacing={0.5} role=\"list\" aria-label=\"Plan\">\n <Typography variant=\"caption\" color=\"text.secondary\">\n {plan.status === 'confirmed' ? 'Confirmed plan' : 'Proposed plan'}\n </Typography>\n {plan.reuse.map((entry, index) => (\n <Typography key={`reuse-${index}`} variant=\"body2\" role=\"listitem\">\n Reuses the {entry.kind === 'screen' ? 'page' : entry.kind} {named(entry.id)} — {entry.purpose}\n </Typography>\n ))}\n {plan.create.map((entry, index) => (\n <Typography key={`create-${index}`} variant=\"body2\" role=\"listitem\">\n Creates the {AI_BUILD_PLAN_CREATION_NOUNS[entry.kind].noun} {entry.name}\n {entry.duplicateOf\n ? `, from a copy of ${named(entry.duplicateOf)}`\n : ''}{' '}\n — {entry.why}\n </Typography>\n ))}\n {plan.screens.map((screen, index) => (\n <Typography key={`screen-${index}`} variant=\"body2\" role=\"listitem\">\n {screen.record\n ? `Builds the record template ${screen.title}, a page per record of ${named(screen.record.dataset)} at /${screen.record.base}/…`\n : `Builds the page ${screen.title} at ${screen.slug}`}\n {screen.duplicateOf\n ? `, from a copy of ${named(screen.duplicateOf)}`\n : ''}\n {screen.layout ? ` in ${named(screen.layout)}` : ''}\n {screen.sections.length\n ? `: ${screen.sections.map((section) => section.name).join(', ')}`\n : ''}\n </Typography>\n ))}\n {(plan.items ?? []).map((item) => (\n <Typography key={`item-${item.slot}`} variant=\"body2\" role=\"listitem\">\n {`Makes the ${aiBuildOpNoun(item.op).toLowerCase()} ${item.name}`}\n {item.why ? ` — ${item.why}` : ''}\n </Typography>\n ))}\n {(plan.embeds ?? []).map((embed, index) => (\n <Typography key={`embed-${index}`} variant=\"body2\" role=\"listitem\">\n {aiPlanEmbedLine(embed, named)}\n </Typography>\n ))}\n </Stack>\n )}\n {/*\n A review written for the member (AGL-3594) carries the checks' own\n sentence as `detail`: its findings are then staff reading too, and the\n member reads the job's one sentence alone.\n */}\n {staff && review?.detail && (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\" sx={{ mt: 0.5 }}>\n {review.detail}\n </Typography>\n )}\n {review?.reason === 'doctrine' && review.findings.length > 0 && (staff || !review.detail) && (\n <Box\n component=\"ul\"\n sx={{ my: 0.5, pl: 2.5 }}\n aria-label=\"Building rules broken\"\n >\n {review.findings.map((finding, index) => (\n <Typography\n key={`finding-${index}`}\n component=\"li\"\n variant=\"caption\"\n >\n {finding.message}\n </Typography>\n ))}\n </Box>\n )}\n {details.length > 0 && (\n <Box sx={{ mt: 0.5 }}>\n <Button\n size=\"small\"\n aria-expanded={detailsOpen}\n onClick={() => setDetailsOpen((prior) => !prior)}\n >\n {detailsOpen ? 'Hide what was refused' : 'Show what was refused'}\n </Button>\n <Collapse in={detailsOpen} unmountOnExit>\n <Typography\n variant=\"caption\"\n component=\"pre\"\n aria-label=\"What was refused\"\n sx={{ m: 0, fontFamily: 'monospace', whiteSpace: 'pre', overflowX: 'auto' }}\n >\n {details.join('\\n')}\n </Typography>\n </Collapse>\n </Box>\n )}\n {estimate > 0 && (\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ display: 'block', mt: 1 }}\n >\n {`Estimated cost: about ${estimate.toLocaleString('en-US')} credits. What it costs is what its steps spend.`}\n </Typography>\n )}\n {waiting && review.retryRefusal && review.reason !== 'plan' && (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\" sx={{ mt: 1 }}>\n {review.retryRefusal}\n </Typography>\n )}\n {offersPublish && (\n <FormControlLabel\n sx={{ display: 'flex', mt: 1 }}\n control={<Checkbox size=\"small\" checked={publish} onChange={(event) => setPublish(event.target.checked)} />}\n label={<Typography variant=\"body2\">{'Publish the new pages when they are built'}</Typography>}\n />\n )}\n {waiting && (\n <Button\n size=\"small\"\n variant=\"contained\"\n // Disabled with its reason above when the Free allowance left\n // cannot pay for another try (AGL-3594).\n disabled={busy || (review.reason !== 'plan' && Boolean(review.retryRefusal))}\n onClick={() => onResume(job, offersPublish && publish ? { publish: true } : undefined)}\n sx={{ mt: 1 }}\n >\n {review.reason === 'plan' ? 'Confirm plan' : 'Try again'}\n </Button>\n )}\n {/* A guided start that did not work out can take the starter instead (AGL-3594). */}\n {waiting && user && aiSiteStarterFallbackOffered(job) && <AiSiteStarterFallback job={job} user={user} />}\n </Box>\n )\n}\n\nexport default AiJobPlan\n"],"names":["AI_BUILD_PLAN_CREATION_NOUNS","AI_BUILD_PLAN_EMBED_HOST_NAMES","isAiPlanNewRef","aiJobCreditEstimate","aiBuildOpNoun","aiSiteStarterFallbackOffered","AiSiteStarterFallback","Box","Button","Checkbox","Collapse","FormControlLabel","Stack","Typography","useState","aiJobReviewDetails","review","reason","lines","findings","flatMap","finding","where","nodeIds","length","join","paths","rule","code","node","outline","push","repeat","depth","id","componentId","Object","entries","grid","map","name","value","JSON","stringify","props","sx","children","aiPlanEmbedLine","embed","named","host","link","url","asked","AiJobPlan","job","onResume","busy","staff","user","plan","detailsOpen","setDetailsOpen","publish","setPublish","details","ref","slice","labels","waiting","status","estimate","kind","offersPublish","publishAsked","mt","spacing","role","aria-label","variant","color","reuse","entry","index","purpose","create","noun","duplicateOf","why","screens","screen","record","title","dataset","base","slug","layout","sections","section","items","item","op","toLowerCase","slot","embeds","detail","component","my","pl","message","size","aria-expanded","onClick","prior","in","unmountOnExit","m","fontFamily","whiteSpace","overflowX","display","toLocaleString","retryRefusal","control","checked","onChange","event","target","label","disabled","Boolean","undefined"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-job-plan.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AI_BUILD_PLAN_CREATION_NOUNS,\n AI_BUILD_PLAN_EMBED_HOST_NAMES,\n isAiPlanNewRef,\n type AiBuildPlanEmbed,\n} from '../model/ai-build-plan'\nimport type { AiJobReview, AiJobSummary } from '../model/ai-jobs.types'\nimport { aiJobCreditEstimate } from '../model/ai-build-job'\nimport { aiBuildOpNoun } from '../model/ai-build-progress'\nimport { aiJobConfirmingOwnPlan } from '../model/ai-job-activity'\nimport { aiSiteStarterFallbackOffered } from '../model/ai-job-failure-copy'\nimport { AiSiteStarterFallback } from './ai-site-starter-fallback.component'\nimport { Box, Button, Checkbox, Collapse, FormControlLabel, Stack, Typography } from '@mui/material'\nimport { useState } from 'react'\n\n/**\n * A job's plan and what it waits for (AGL-2935), inside the AI jobs drawer\n * and the dialog that started the job (AGL-3593): what the job reuses from\n * the site, what it creates and why, the screens it builds — and, while the\n * job waits for a person, the one button that confirms the plan or tries a\n * refused step again. Both send the same request (`resumeAiJobRequest`);\n * this renders.\n */\nexport interface AiJobPlanProps {\n job: AiJobSummary\n /**\n * Confirms the plan, or tries the refused step again. A build whose request\n * asked to publish confirms with `publish` when its box is ticked (AGL-3616).\n */\n onResume: (job: AiJobSummary, options?: { publish?: boolean }) => void\n /** A resume for this job is in flight. */\n busy?: boolean\n /**\n * The viewer is staff (AGL-3078), who can open where a refused answer broke\n * its rules and the outline of those parts, to tell a shape the rules should\n * allow from an answer that ignored its re-ask. A member reads the findings.\n */\n staff?: boolean\n /**\n * The signed-in user, for \"Use the starter site instead\" on a guided start\n * that did not work out (AGL-3594); the action is drawn only when given.\n */\n user?: Parameters<typeof AiSiteStarterFallback>[0]['user']\n}\n\n/**\n * Where a refused answer broke its rules, and the outline of those parts, as\n * lines staff read (AGL-3078): each finding with the nodes or plan entries it\n * names, then each outlined node indented by its depth, with its element, a\n * Grid's layout as written, and the names of what it sets and holds.\n */\nexport function aiJobReviewDetails(review: AiJobReview | null): string[] {\n if (review?.reason !== 'doctrine') return []\n const lines = review.findings.flatMap((finding) => {\n const where = finding.nodeIds?.length\n ? `nodes ${finding.nodeIds.join(', ')}`\n : finding.paths?.length\n ? `at ${finding.paths.join(', ')}`\n : null\n return where ? [`${finding.rule === null ? '' : `Rule ${finding.rule} `}${finding.code}: ${where}`] : []\n })\n for (const node of review.outline ?? []) {\n lines.push(\n [\n `${' '.repeat(node.depth)}${node.id} ${node.componentId}`,\n ...Object.entries(node.grid ?? {}).map(([name, value]) => `${name}=${JSON.stringify(value)}`),\n ...(node.props.length ? [`props ${node.props.join(', ')}`] : []),\n ...(node.sx?.length ? [`sx ${node.sx.join(', ')}`] : []),\n ...(node.children.length ? [`holds ${node.children.join(', ')}`] : []),\n ].join(' · '),\n )\n }\n return lines\n}\n\n/**\n * A third-party player the plan lists, with what it costs the page, read\n * before the member confirms it (rule 16, AGL-3433). The cost is the\n * platform's sentence, never the model's: the player is framed lazily, so its\n * host's code loads when a visitor reaches it, whether or not they press play.\n */\nexport function aiPlanEmbedLine(\n embed: AiBuildPlanEmbed,\n named: (ref: string) => string,\n): string {\n const host = AI_BUILD_PLAN_EMBED_HOST_NAMES[embed.host]\n const where = isAiPlanNewRef(embed.where) ? `the component ${named(embed.where)}` : embed.where\n const link = embed.url ? ` playing ${embed.url}` : ', its link left for you to paste'\n return `Embeds a ${host} player on ${where}${link}, as you asked (“${embed.asked}”). It loads ${host}’s own code when a visitor reaches it, whether or not they press play.`\n}\n\nexport function AiJobPlan({\n job,\n onResume,\n busy = false,\n staff = false,\n user,\n}: AiJobPlanProps): JSX.Element | null {\n const [detailsOpen, setDetailsOpen] = useState(false)\n // Unticked until the person ticks it: a build publishes only when its\n // request asked AND they confirm it here (AGL-3616).\n const [publish, setPublish] = useState(false)\n const { plan, review } = job\n if (!plan && !review) return null\n const details = staff ? aiJobReviewDetails(review) : []\n /** A reference as a person reads it: the record's name, or what the plan creates. */\n const named = (ref: string | null): string =>\n !ref\n ? ''\n : isAiPlanNewRef(ref)\n ? ref.slice('new:'.length)\n : (plan?.labels[ref] ?? ref)\n // A plan the machine is confirming itself is not one to confirm (AGL-3596).\n const waiting = job.status === 'needs_review' && review !== null && !aiJobConfirmingOwnPlan(job)\n // The guard rail (AGL-2911): what the plan is estimated to cost is read\n // before it is confirmed, not after it has been spent. An estimate, and\n // said to be one — the plan's own passes at the nominal credits a step\n // holds, where what a step really costs is its model's tokens. A page job\n // counts the creations it builds before its page (AGL-3031).\n const estimate =\n plan && waiting && review.reason === 'plan' ? aiJobCreditEstimate(job.kind, plan) : 0\n const offersPublish = job.kind === 'build' && job.publishAsked === true && waiting && review.reason === 'plan'\n return (\n <Box sx={{ mt: 1 }}>\n {plan && (\n <Stack spacing={0.5} role=\"list\" aria-label=\"Plan\">\n <Typography variant=\"caption\" color=\"text.secondary\">\n {plan.status === 'confirmed' ? 'Confirmed plan' : 'Proposed plan'}\n </Typography>\n {plan.reuse.map((entry, index) => (\n <Typography key={`reuse-${index}`} variant=\"body2\" role=\"listitem\">\n Reuses the {entry.kind === 'screen' ? 'page' : entry.kind} {named(entry.id)} — {entry.purpose}\n </Typography>\n ))}\n {plan.create.map((entry, index) => (\n <Typography key={`create-${index}`} variant=\"body2\" role=\"listitem\">\n Creates the {AI_BUILD_PLAN_CREATION_NOUNS[entry.kind].noun} {entry.name}\n {entry.duplicateOf\n ? `, from a copy of ${named(entry.duplicateOf)}`\n : ''}{' '}\n — {entry.why}\n </Typography>\n ))}\n {plan.screens.map((screen, index) => (\n <Typography key={`screen-${index}`} variant=\"body2\" role=\"listitem\">\n {screen.record\n ? `Builds the record template ${screen.title}, a page per record of ${named(screen.record.dataset)} at /${screen.record.base}/…`\n : `Builds the page ${screen.title} at ${screen.slug}`}\n {screen.duplicateOf\n ? `, from a copy of ${named(screen.duplicateOf)}`\n : ''}\n {screen.layout ? ` in ${named(screen.layout)}` : ''}\n {screen.sections.length\n ? `: ${screen.sections.map((section) => section.name).join(', ')}`\n : ''}\n </Typography>\n ))}\n {(plan.items ?? []).map((item) => (\n <Typography key={`item-${item.slot}`} variant=\"body2\" role=\"listitem\">\n {`Makes the ${aiBuildOpNoun(item.op).toLowerCase()} ${item.name}`}\n {item.why ? ` — ${item.why}` : ''}\n </Typography>\n ))}\n {(plan.embeds ?? []).map((embed, index) => (\n <Typography key={`embed-${index}`} variant=\"body2\" role=\"listitem\">\n {aiPlanEmbedLine(embed, named)}\n </Typography>\n ))}\n </Stack>\n )}\n {/*\n A review written for the member (AGL-3594) carries the checks' own\n sentence as `detail`: its findings are then staff reading too, and the\n member reads the job's one sentence alone.\n */}\n {staff && review?.detail && (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\" sx={{ mt: 0.5 }}>\n {review.detail}\n </Typography>\n )}\n {review?.reason === 'doctrine' && review.findings.length > 0 && (staff || !review.detail) && (\n <Box\n component=\"ul\"\n sx={{ my: 0.5, pl: 2.5 }}\n aria-label=\"Building rules broken\"\n >\n {review.findings.map((finding, index) => (\n <Typography\n key={`finding-${index}`}\n component=\"li\"\n variant=\"caption\"\n >\n {finding.message}\n </Typography>\n ))}\n </Box>\n )}\n {details.length > 0 && (\n <Box sx={{ mt: 0.5 }}>\n <Button\n size=\"small\"\n aria-expanded={detailsOpen}\n onClick={() => setDetailsOpen((prior) => !prior)}\n >\n {detailsOpen ? 'Hide what was refused' : 'Show what was refused'}\n </Button>\n <Collapse in={detailsOpen} unmountOnExit>\n <Typography\n variant=\"caption\"\n component=\"pre\"\n aria-label=\"What was refused\"\n sx={{ m: 0, fontFamily: 'monospace', whiteSpace: 'pre', overflowX: 'auto' }}\n >\n {details.join('\\n')}\n </Typography>\n </Collapse>\n </Box>\n )}\n {estimate > 0 && (\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ display: 'block', mt: 1 }}\n >\n {`Estimated cost: about ${estimate.toLocaleString('en-US')} credits. What it costs is what its steps spend.`}\n </Typography>\n )}\n {waiting && review.retryRefusal && review.reason !== 'plan' && (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\" sx={{ mt: 1 }}>\n {review.retryRefusal}\n </Typography>\n )}\n {offersPublish && (\n <FormControlLabel\n sx={{ display: 'flex', mt: 1 }}\n control={<Checkbox size=\"small\" checked={publish} onChange={(event) => setPublish(event.target.checked)} />}\n label={<Typography variant=\"body2\">{'Publish the new pages when they are built'}</Typography>}\n />\n )}\n {waiting && (\n <Button\n size=\"small\"\n variant=\"contained\"\n // Disabled with its reason above when the Free allowance left\n // cannot pay for another try (AGL-3594).\n disabled={busy || (review.reason !== 'plan' && Boolean(review.retryRefusal))}\n onClick={() => onResume(job, offersPublish && publish ? { publish: true } : undefined)}\n sx={{ mt: 1 }}\n >\n {review.reason === 'plan' ? 'Confirm plan' : 'Try again'}\n </Button>\n )}\n {/* A guided start that did not work out can take the starter instead (AGL-3594). */}\n {waiting && user && aiSiteStarterFallbackOffered(job) && <AiSiteStarterFallback job={job} user={user} />}\n </Box>\n )\n}\n\nexport default AiJobPlan\n"],"names":["AI_BUILD_PLAN_CREATION_NOUNS","AI_BUILD_PLAN_EMBED_HOST_NAMES","isAiPlanNewRef","aiJobCreditEstimate","aiBuildOpNoun","aiJobConfirmingOwnPlan","aiSiteStarterFallbackOffered","AiSiteStarterFallback","Box","Button","Checkbox","Collapse","FormControlLabel","Stack","Typography","useState","aiJobReviewDetails","review","reason","lines","findings","flatMap","finding","where","nodeIds","length","join","paths","rule","code","node","outline","push","repeat","depth","id","componentId","Object","entries","grid","map","name","value","JSON","stringify","props","sx","children","aiPlanEmbedLine","embed","named","host","link","url","asked","AiJobPlan","job","onResume","busy","staff","user","plan","detailsOpen","setDetailsOpen","publish","setPublish","details","ref","slice","labels","waiting","status","estimate","kind","offersPublish","publishAsked","mt","spacing","role","aria-label","variant","color","reuse","entry","index","purpose","create","noun","duplicateOf","why","screens","screen","record","title","dataset","base","slug","layout","sections","section","items","item","op","toLowerCase","slot","embeds","detail","component","my","pl","message","size","aria-expanded","onClick","prior","in","unmountOnExit","m","fontFamily","whiteSpace","overflowX","display","toLocaleString","retryRefusal","control","checked","onChange","event","target","label","disabled","Boolean","undefined"],"mappings":"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"}
|
|
@@ -1,50 +1,8 @@
|
|
|
1
1
|
import type { ConsoleDockZoneProps } from '@aglyn/aglyn';
|
|
2
|
-
import {
|
|
3
|
-
import { AiAssistProvider } from './ai-assist-provider.component';
|
|
2
|
+
import type { ComponentProps } from 'react';
|
|
4
3
|
import { AssistPanelComponent } from './assist-panel.component';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* the reader's verdict for every catalog key a plugin declared, on the site
|
|
8
|
-
* in view, with `loaded` false until every read behind it has answered.
|
|
9
|
-
*/
|
|
10
|
-
export interface ShellPermissionsOnHost {
|
|
11
|
-
loaded: boolean;
|
|
12
|
-
granted: Readonly<Record<string, boolean>>;
|
|
13
|
-
}
|
|
14
|
-
/** The AI half of that answer, in the shape the AI surfaces hold on. */
|
|
15
|
-
export interface AiPermissionsAnswer {
|
|
16
|
-
loaded: boolean;
|
|
17
|
-
use: boolean;
|
|
18
|
-
generate: boolean;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* The shell's answer read for the two AI keys. `undefined` while the shell
|
|
22
|
-
* has handed nothing, which the provider reads as pending; one object per
|
|
23
|
-
* verdict, so the callbacks keyed on it are not rebuilt on every render.
|
|
24
|
-
*/
|
|
25
|
-
export declare function useAiPermissionsOnHost(answer: ShellPermissionsOnHost | undefined): AiPermissionsAnswer | undefined;
|
|
26
|
-
type ProviderProps = Omit<ComponentProps<typeof AiAssistProvider>, 'aiPermissions'> & {
|
|
27
|
-
permissionsOnHost?: ShellPermissionsOnHost;
|
|
28
|
-
/**
|
|
29
|
-
* The plugins that run on the site in view, as the shell resolved them
|
|
30
|
-
* (AGL-3028). Absent where the shell hands none, which reads as no site
|
|
31
|
-
* narrowing at all.
|
|
32
|
-
*/
|
|
33
|
-
enabledPluginIds?: readonly string[];
|
|
34
|
-
};
|
|
35
|
-
/**
|
|
36
|
-
* The besigner copy assistant's provider, holding on the shell's permission
|
|
37
|
-
* answer.
|
|
38
|
-
*
|
|
39
|
-
* On a site with AI switched off (AGL-3028) it stays MOUNTED — it wraps every
|
|
40
|
-
* console page, and a provider that came and went per site would remount the
|
|
41
|
-
* whole tree beneath it — and opens nothing: a settled refusal publishes no
|
|
42
|
-
* callback, so no control can reach its dialogs.
|
|
43
|
-
*/
|
|
44
|
-
export declare function AiAssistProviderOnHost(props: ProviderProps): import("react").JSX.Element;
|
|
45
|
-
export declare namespace AiAssistProviderOnHost {
|
|
46
|
-
var displayName: string;
|
|
47
|
-
}
|
|
4
|
+
import { type ShellPermissionsOnHost } from './ai-assist-provider-on-host.component';
|
|
5
|
+
export { AiAssistProviderOnHost, useAiPermissionsOnHost, type AiPermissionsAnswer, type ShellPermissionsOnHost, } from './ai-assist-provider-on-host.component';
|
|
48
6
|
type PanelProps = Omit<ComponentProps<typeof AssistPanelComponent>, 'aiPermissions' | 'assistVisible' | 'assistStaffPreview' | 'generativeVisible'> & {
|
|
49
7
|
permissionsOnHost?: ShellPermissionsOnHost;
|
|
50
8
|
/**
|
|
@@ -62,4 +20,3 @@ export declare function AssistPanelOnHost(props: PanelProps): import("react").JS
|
|
|
62
20
|
export declare namespace AssistPanelOnHost {
|
|
63
21
|
var displayName: string;
|
|
64
22
|
}
|
|
65
|
-
export {};
|