@aglyn/plugins-ai 1.0.0-beta.293 → 1.0.0-beta.296
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-job-links.d.ts +15 -2
- package/src/lib/components/ai-job-links.js +24 -3
- package/src/lib/components/ai-job-links.js.map +1 -1
- package/src/lib/components/ai-job-requests.d.ts +9 -0
- package/src/lib/components/ai-job-requests.js +34 -0
- package/src/lib/components/ai-job-requests.js.map +1 -1
- package/src/lib/components/ai-site-build-page.component.js +28 -2
- package/src/lib/components/ai-site-build-page.component.js.map +1 -1
- package/src/lib/components/assist-jobs-drawer.component.d.ts +7 -1
- package/src/lib/components/assist-jobs-drawer.component.js +20 -6
- package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
- package/src/lib/components/assist-page-change-card.component.d.ts +44 -0
- package/src/lib/components/assist-page-change-card.component.js +166 -0
- package/src/lib/components/assist-page-change-card.component.js.map +1 -0
- package/src/lib/components/assist-panel.component.d.ts +105 -1
- package/src/lib/components/assist-panel.component.js +224 -29
- package/src/lib/components/assist-panel.component.js.map +1 -1
- package/src/lib/jobs/ai-job-edit-step.d.ts +62 -16
- package/src/lib/jobs/ai-job-edit-step.js +172 -61
- package/src/lib/jobs/ai-job-edit-step.js.map +1 -1
- package/src/lib/jobs/ai-job-navigation-step.js +4 -2
- package/src/lib/jobs/ai-job-navigation-step.js.map +1 -1
- package/src/lib/model/ai-edit-job.d.ts +33 -16
- package/src/lib/model/ai-edit-job.js +50 -34
- package/src/lib/model/ai-edit-job.js.map +1 -1
- package/src/lib/model/ai-job-activity.d.ts +6 -11
- package/src/lib/model/ai-job-activity.js +8 -15
- package/src/lib/model/ai-job-activity.js.map +1 -1
- package/src/lib/model/ai-jobs.types.d.ts +6 -0
- package/src/lib/model/ai-jobs.types.js.map +1 -1
- package/src/lib/model/ai-site-inventory.d.ts +6 -0
- package/src/lib/model/ai-site-inventory.js.map +1 -1
- package/src/lib/model/assist-edit.d.ts +18 -1
- package/src/lib/model/assist-edit.js +7 -0
- package/src/lib/model/assist-edit.js.map +1 -1
- package/src/lib/model/assist-page-change.d.ts +86 -0
- package/src/lib/model/assist-page-change.js +86 -0
- package/src/lib/model/assist-page-change.js.map +1 -0
- package/src/lib/runtime/ai-eval.js +3 -1
- package/src/lib/runtime/ai-eval.js.map +1 -1
- package/src/lib/runtime/ai-node-tree.d.ts +5 -0
- package/src/lib/runtime/ai-node-tree.js +18 -3
- package/src/lib/runtime/ai-node-tree.js.map +1 -1
- package/src/lib/runtime/site-inventory.d.ts +8 -1
- package/src/lib/runtime/site-inventory.js +18 -0
- package/src/lib/runtime/site-inventory.js.map +1 -1
- package/src/lib/server/assist-build.js +2 -0
- package/src/lib/server/assist-build.js.map +1 -1
- package/src/lib/server/assist-chat.js +51 -2
- package/src/lib/server/assist-chat.js.map +1 -1
- package/src/lib/server/assist-edit.d.ts +54 -2
- package/src/lib/server/assist-edit.js +219 -30
- package/src/lib/server/assist-edit.js.map +1 -1
- package/src/lib/server/assist-page-change.d.ts +62 -0
- package/src/lib/server/assist-page-change.js +140 -0
- package/src/lib/server/assist-page-change.js.map +1 -0
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.296",
|
|
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.296",
|
|
29
|
+
"@aglyn/shared-data-enums": "1.0.0-beta.296",
|
|
30
|
+
"@aglyn/shared-data-mdi": "1.0.0-beta.296",
|
|
31
|
+
"@aglyn/shared-data-types": "1.0.0-beta.296",
|
|
32
|
+
"@aglyn/shared-ui-email-campaigns": "1.0.0-beta.296",
|
|
33
|
+
"@aglyn/shared-ui-jsx": "1.0.0-beta.296",
|
|
34
|
+
"@aglyn/shared-ui-snackstack": "1.0.0-beta.296",
|
|
35
|
+
"@aglyn/shared-ui-theme": "1.0.0-beta.296",
|
|
36
|
+
"@aglyn/shared-util-email": "1.0.0-beta.296",
|
|
37
|
+
"@aglyn/shared-util-errors": "1.0.0-beta.296",
|
|
38
|
+
"@aglyn/shared-util-http": "1.0.0-beta.296",
|
|
39
|
+
"@aglyn/shared-util-timestamp": "1.0.0-beta.296",
|
|
40
|
+
"@aglyn/shared-util-tools": "1.0.0-beta.296",
|
|
41
|
+
"@aglyn/tenant-data-admin": "1.0.0-beta.296",
|
|
42
|
+
"@aglyn/tenant-feature-instance": "1.0.0-beta.296",
|
|
43
|
+
"@aglyn/tenant-runtime": "1.0.0-beta.296",
|
|
44
44
|
"@swc/helpers": "0.5.23"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
@@ -34,13 +34,26 @@ export { AI_SITE_BUILD_HREF };
|
|
|
34
34
|
export declare function aiSiteBuildHref(orgSlug: string | null | undefined, hostSubdomain: string | null | undefined, jobId: string): string | null;
|
|
35
35
|
/**
|
|
36
36
|
* A finished site's two ways in (AGL-3594): its first page's draft, opened in
|
|
37
|
-
* the console's preview of that version
|
|
38
|
-
*
|
|
37
|
+
* the console's preview of that version — the page as a visitor will see it,
|
|
38
|
+
* never its details — and the Pages list every draft waits in. Either is
|
|
39
|
+
* `null` where the job reported nothing to open.
|
|
39
40
|
*/
|
|
40
41
|
export declare function aiSiteBuildDoneLinks(job: Pick<AiJobSummary, 'outputs'>, orgSlug: string): {
|
|
41
42
|
view: string | null;
|
|
42
43
|
pages: string | null;
|
|
43
44
|
};
|
|
45
|
+
/**
|
|
46
|
+
* The two ways to look at the one page a job changed (AGL-3616): its new
|
|
47
|
+
* version in the preview, where it can be published, and in the Besigner.
|
|
48
|
+
* A change saved into the page's draft (AGL-4116) has no preview of its own
|
|
49
|
+
* — a version's preview shows the version, not its draft — so only the
|
|
50
|
+
* Besigner, where Open draft shows it. `null` where the job wrote no page
|
|
51
|
+
* version, or more than one page — those wait in Pages.
|
|
52
|
+
*/
|
|
53
|
+
export declare function aiJobReviewLinks(job: Pick<AiJobSummary, 'outputs'>, orgSlug: string): {
|
|
54
|
+
preview: string | null;
|
|
55
|
+
besigner: string;
|
|
56
|
+
} | null;
|
|
44
57
|
/**
|
|
45
58
|
* Where a person gets more AI credits (AGL-3660): the workspace's Billing
|
|
46
59
|
* page at its plans, where an upgrade and the AI add-on are both sold — the
|
|
@@ -176,10 +176,14 @@ export { AI_SITE_BUILD_HREF };
|
|
|
176
176
|
if (!orgSlug || !hostSubdomain || !jobId) return null;
|
|
177
177
|
return `/${orgSlug}/hosts/${hostSubdomain}${AI_SITE_BUILD_HREF}/${encodeURIComponent(jobId)}`;
|
|
178
178
|
}
|
|
179
|
+
/** A page version's own address under a site, for the console route named by `leaf`. */ function screenVersionHref(orgSlug, output, leaf) {
|
|
180
|
+
return `/${orgSlug}/hosts/${String(output.hostSubdomain)}/screens/${output.id}/versions/${output.versionId}/${leaf}`;
|
|
181
|
+
}
|
|
179
182
|
/**
|
|
180
183
|
* A finished site's two ways in (AGL-3594): its first page's draft, opened in
|
|
181
|
-
* the console's preview of that version
|
|
182
|
-
*
|
|
184
|
+
* the console's preview of that version — the page as a visitor will see it,
|
|
185
|
+
* never its details — and the Pages list every draft waits in. Either is
|
|
186
|
+
* `null` where the job reported nothing to open.
|
|
183
187
|
*/ export function aiSiteBuildDoneLinks(job, orgSlug) {
|
|
184
188
|
const screens = job.outputs.filter((output)=>output.resource === 'screen' && output.hostSubdomain);
|
|
185
189
|
const first = screens[0];
|
|
@@ -189,13 +193,30 @@ export { AI_SITE_BUILD_HREF };
|
|
|
189
193
|
};
|
|
190
194
|
const host = String(first.hostSubdomain);
|
|
191
195
|
return {
|
|
192
|
-
|
|
196
|
+
// A change in a page's draft is not in its version's preview (AGL-4116).
|
|
197
|
+
view: first.versionId && !first.inDraft ? screenVersionHref(orgSlug, first, 'preview') : null,
|
|
193
198
|
pages: buildRoute(Route.HOST_SCREENS, {
|
|
194
199
|
orgSlug,
|
|
195
200
|
host
|
|
196
201
|
})
|
|
197
202
|
};
|
|
198
203
|
}
|
|
204
|
+
/**
|
|
205
|
+
* The two ways to look at the one page a job changed (AGL-3616): its new
|
|
206
|
+
* version in the preview, where it can be published, and in the Besigner.
|
|
207
|
+
* A change saved into the page's draft (AGL-4116) has no preview of its own
|
|
208
|
+
* — a version's preview shows the version, not its draft — so only the
|
|
209
|
+
* Besigner, where Open draft shows it. `null` where the job wrote no page
|
|
210
|
+
* version, or more than one page — those wait in Pages.
|
|
211
|
+
*/ export function aiJobReviewLinks(job, orgSlug) {
|
|
212
|
+
if (!orgSlug) return null;
|
|
213
|
+
const pages = job.outputs.filter((output)=>output.resource === 'screen' && output.hostSubdomain && output.versionId);
|
|
214
|
+
if (new Set(pages.map((page)=>page.id)).size !== 1) return null;
|
|
215
|
+
return {
|
|
216
|
+
preview: pages[0].inDraft ? null : screenVersionHref(orgSlug, pages[0], 'preview'),
|
|
217
|
+
besigner: screenVersionHref(orgSlug, pages[0], 'besigner')
|
|
218
|
+
};
|
|
219
|
+
}
|
|
199
220
|
/**
|
|
200
221
|
* Where a person gets more AI credits (AGL-3660): the workspace's Billing
|
|
201
222
|
* page at its plans, where an upgrade and the AI add-on are both sold — the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-job-links.ts"],"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 */\nimport { buildRoute, Route } from '@aglyn/aglyn/app-utils/console-routes'\nimport {\n pluginRecordHref,\n pluginRecordListHref,\n} from '@aglyn/aglyn/plugin-manager/plugin-record-routes'\nimport { AI_JOB_BESIGNER_SEGMENT as BESIGNER_SEGMENT, AI_SITE_BUILD_HREF } from '../model/ai-job-notice'\nimport type { AiJobOutput, AiJobSummary } from '../model/ai-jobs.types'\nimport { AI_STORE_FINISH_STEPS, type AiStoreFinishStep } from '../model/ai-site-store-pages'\nimport { AI_BUILD_STORE_LINKS_DRAFT_STEP, AI_BUILD_STORE_LINKS_MISSING_STEP } from '../model/ai-build-store-pages'\n\n// Where a job's work opens in the console (AGL-2904), shared by the AI jobs\n// drawer and every dialog that follows the job it started (AGL-3593).\n\n/**\n * Where \"open draft\" goes, or `null` when the output has no page of its\n * own — a `text` output carries its copy on the job and is shown inline.\n * A versioned resource opens in the besigner on the version the job wrote;\n * one the console lists without a detail page opens its list; a `theme`\n * proposal opens the site's Theme section, where it is put in the editor.\n *\n * A console URL names a site by its SUBDOMAIN: the `[host]` segment resolves\n * through the member's host projection by subdomain, never by document id.\n * So an output that carries no `hostSubdomain` gets no link rather than one\n * that opens no site.\n */\nexport function aiJobOutputHref(output: AiJobOutput, orgSlug: string): string | null {\n const host = output.hostSubdomain\n if (!orgSlug || !host) return null\n const segment = BESIGNER_SEGMENT[output.resource]\n if (segment) {\n const base = `/${orgSlug}/hosts/${host}/${segment}/${output.id}`\n return output.versionId ? `${base}/versions/${output.versionId}/besigner` : base\n }\n if (output.resource === 'product') {\n // The catalog a drafted product lands in: the commerce plugin's address\n // for it (AGL-3080), or no link where commerce is not loaded.\n return pluginRecordListHref('product', { orgSlug, host })\n }\n if (output.resource === 'workflow') {\n // A drafted automation is an action (AGL-2919), listed switched off on\n // the workflows plugin's list of actions, or no link where it is not loaded.\n return pluginRecordListHref('action', { orgSlug, host })\n }\n if (output.resource === 'entry') {\n // A post a guided start wrote (AGL-3676) opens in its blog's list in Content.\n const collectionSlug = output.proposal?.['collectionSlug']\n return typeof collectionSlug === 'string' && collectionSlug\n ? buildRoute(Route.HOST_CONTENT_COLLECTION, { orgSlug, host, collectionSlug })\n : buildRoute(Route.HOST_CONTENT, { orgSlug, host })\n }\n if (output.resource === 'theme') {\n return buildRoute(Route.HOST_SETUP_THEME, { orgSlug, host })\n }\n if (output.resource === 'media') {\n // Files a build organized (AGL-3752) open in the site's media library.\n return buildRoute(Route.HOST_MEDIA, { orgSlug, host })\n }\n if (output.resource === 'settings') {\n // Settings a build saved (AGL-3748) open where most of them are edited.\n return buildRoute(Route.HOST_SETUP_SEO, { orgSlug, host })\n }\n if (output.resource === 'tracking') {\n // Tags a build saved (AGL-3751) open on the card that edits them.\n return buildRoute(Route.HOST_SETUP_TRACKING, { orgSlug, host })\n }\n if (output.resource === 'privacy') {\n // Who can see the site (AGL-4033), each change on the card that makes it.\n if (output.id === 'maintenance') return buildRoute(Route.HOST_ADMIN_ERROR_PAGES, { orgSlug, host })\n if (output.id === 'search') return buildRoute(Route.HOST_SETUP_SEO, { orgSlug, host })\n return buildRoute(Route.HOST_SCREENS, { orgSlug, host })\n }\n if (output.resource === 'draft' && output.draftResource) {\n // A draft another plugin wrote — a dataset a site start or a build made\n // (AGL-3616) — opens where its owner lists it, or nowhere it is not loaded.\n return pluginRecordListHref(output.draftResource, { orgSlug, host })\n }\n if (output.resource === 'form') {\n // A new form has no version for the besigner to open: its own page — the\n // forms plugin's address for it — mints the first one, and holds the\n // routing and consent it declares.\n return pluginRecordHref('form', { orgSlug, host }, output.id)\n }\n if (output.resource === 'campaign') {\n // A campaign's page is the marketing plugin's, under the site: its\n // address for the campaign (AGL-3080), or no link where it is not loaded.\n return pluginRecordHref('campaign', { orgSlug, host }, output.id)\n }\n return null\n}\n\n/**\n * The ONE action a finished job's row, its notification and the dialog that\n * started it lead with (AGL-3593): what the job built. Several pages from one\n * job — a site's — open the site's Pages list, where they wait as drafts; one\n * output with a page of its own opens that page; anything else has no single\n * place to go, and the row's own links stand. `null` until the job is done.\n */\nexport function aiJobPrimaryLink(\n job: Pick<AiJobSummary, 'status' | 'outputs'>,\n orgSlug: string,\n): { href: string; label: string } | null {\n if (job.status !== 'done' || !orgSlug) return null\n const screens = job.outputs.filter(\n (output) => output.resource === 'screen' && output.hostSubdomain,\n )\n if (screens.length > 1) {\n return {\n href: buildRoute(Route.HOST_SCREENS, { orgSlug, host: String(screens[0].hostSubdomain) }),\n label: 'Open your draft pages',\n }\n }\n for (const output of job.outputs) {\n const href = aiJobOutputHref(output, orgSlug)\n if (href) {\n return {\n href,\n label: output.resource === 'screen' ? 'Open the draft page' : `Open ${output.label}`,\n }\n }\n }\n return null\n}\n\nexport { AI_SITE_BUILD_HREF }\n\n/**\n * The \"Building your site\" page for one site job (AGL-3594): linkable, so the\n * guided start lands on it, a reload keeps it and a notification opens it.\n * `null` without the org slug or the site's subdomain a console URL needs.\n */\nexport function aiSiteBuildHref(\n orgSlug: string | null | undefined,\n hostSubdomain: string | null | undefined,\n jobId: string,\n): string | null {\n if (!orgSlug || !hostSubdomain || !jobId) return null\n return `/${orgSlug}/hosts/${hostSubdomain}${AI_SITE_BUILD_HREF}/${encodeURIComponent(jobId)}`\n}\n\n/**\n * A finished site's two ways in (AGL-3594): its first page's draft, opened in\n * the console's preview of that version, and the Pages list every draft waits\n * in. Either is `null` where the job reported nothing to open.\n */\nexport function aiSiteBuildDoneLinks(\n job: Pick<AiJobSummary, 'outputs'>,\n orgSlug: string,\n): { view: string | null; pages: string | null } {\n const screens = job.outputs.filter((output) => output.resource === 'screen' && output.hostSubdomain)\n const first = screens[0]\n if (!first || !orgSlug) return { view: null, pages: null }\n const host = String(first.hostSubdomain)\n return {\n view: first.versionId\n ? `/${orgSlug}/hosts/${host}/screens/${first.id}/versions/${first.versionId}/view`\n : null,\n pages: buildRoute(Route.HOST_SCREENS, { orgSlug, host }),\n }\n}\n\n/**\n * Where a person gets more AI credits (AGL-3660): the workspace's Billing\n * page at its plans, where an upgrade and the AI add-on are both sold — the\n * door the AI credits meter's own upgrade link opens.\n */\nexport function aiCreditsBillingHref(orgSlug: string): string {\n return `${buildRoute(Route.MANAGE_BILLING, { orgSlug })}#plans`\n}\n\n/** One thing left to finish an AI-built store, with where it is done. */\nexport interface AiStoreFinishLink extends AiStoreFinishStep {\n /** The console page it is done on; `null` where the owner of that page is not loaded. */\n href: string | null\n}\n\n/**\n * What is left to finish a store a site start built (AGL-3676), or `null`\n * where the start built no store's own pages: its account, cart and policy\n * pages are written, so payments, products, shipping and tax, and the\n * policies' brackets are all that remain. Each links the exact console page:\n * the store's settings and its catalog, as the commerce plugin publishes\n * them, and the site's Pages.\n */\nexport function aiStoreFinishLinks(\n job: Pick<AiJobSummary, 'kind' | 'status' | 'items' | 'outputs'> & Partial<Pick<AiJobSummary, 'sitePublish'>>,\n orgSlug: string,\n): AiStoreFinishLink[] | null {\n // A site start's store, or an Assist build that made the site a store (AGL-3676).\n if ((job.kind !== 'site' && job.kind !== 'build') || job.status !== 'done' || !orgSlug) return null\n const row = (job.items ?? []).find((one) => one.slot === 'store')\n if (!row || (row.status !== 'succeeded' && row.status !== 'degraded')) return null\n const host = job.outputs.find((output) => output.resource === 'screen' && output.hostSubdomain)?.hostSubdomain\n if (!host) return null\n const context = { orgSlug, host: String(host) }\n // A build's products are drafts with no price unless asked, and it may\n // have written none of the policies (the site had them): its list says so.\n const build = job.kind === 'build'\n const mine = job.outputs.filter((output) => row.outputs.includes(output.id))\n const written = new Set(mine.map((output) => output.proposal?.['storePage']))\n const policies = !build || ['shipping', 'privacy', 'terms'].some((key) => written.has(key))\n const steps: AiStoreFinishLink[] = AI_STORE_FINISH_STEPS.filter((step) => step.id !== 'policies' || policies).map((step) => ({\n ...step,\n ...(build && step.id === 'products' ? { text: AI_BUILD_STORE_PRODUCTS_TEXT } : {}),\n href:\n step.opens === 'pages'\n ? buildRoute(Route.HOST_SCREENS, context)\n : step.opens === 'layouts' || step.opens === 'layout'\n ? buildRoute(Route.HOST_LAYOUTS, context)\n : step.record\n ? pluginRecordHref(step.opens, context, step.record)\n : pluginRecordListHref(step.opens, context),\n }))\n if (!build) return steps\n // The site's own header and footer (AGL-3676): links it had no list for are\n // the owner's to add; links drafted into it wait for its publish.\n if (mine.some((output) => output.proposal?.['storeLinks'] === 'missing')) {\n steps.push({ ...AI_BUILD_STORE_LINKS_MISSING_STEP, href: buildRoute(Route.HOST_LAYOUTS, context) })\n }\n const draft = mine.find((output) => output.resource === 'layout' && output.proposal?.['storeLinks'] === 'draft')\n const live = draft && job.sitePublish?.published.length\n if (draft && !live) steps.push({ ...AI_BUILD_STORE_LINKS_DRAFT_STEP, href: aiJobOutputHref(draft, orgSlug) })\n return steps\n}\n\n/**\n * The site an AI-built store is on — the one {@link aiStoreFinishLinks}\n * links — so \"Finish your store\" can read whether its workspace already takes\n * payments (AGL-3982). `null` where no output names a site.\n */\nexport function aiStoreFinishHostId(job: Pick<AiJobSummary, 'outputs'>): string | null {\n return job.outputs.find((output) => output.resource === 'screen' && output.hostSubdomain)?.hostId ?? null\n}\n\n/** What a build's \"Review your products\" step says: its products are drafts, priced only where the request said. */\nexport const AI_BUILD_STORE_PRODUCTS_TEXT =\n 'Your new products are drafts. Set their prices, photos and stock, then make them active so they show in your store.'\n"],"names":["buildRoute","Route","pluginRecordHref","pluginRecordListHref","AI_JOB_BESIGNER_SEGMENT","BESIGNER_SEGMENT","AI_SITE_BUILD_HREF","AI_STORE_FINISH_STEPS","AI_BUILD_STORE_LINKS_DRAFT_STEP","AI_BUILD_STORE_LINKS_MISSING_STEP","aiJobOutputHref","output","orgSlug","host","hostSubdomain","segment","resource","base","id","versionId","collectionSlug","proposal","HOST_CONTENT_COLLECTION","HOST_CONTENT","HOST_SETUP_THEME","HOST_MEDIA","HOST_SETUP_SEO","HOST_SETUP_TRACKING","HOST_ADMIN_ERROR_PAGES","HOST_SCREENS","draftResource","aiJobPrimaryLink","job","status","screens","outputs","filter","length","href","String","label","aiSiteBuildHref","jobId","encodeURIComponent","aiSiteBuildDoneLinks","first","view","pages","aiCreditsBillingHref","MANAGE_BILLING","aiStoreFinishLinks","kind","row","items","find","one","slot","context","build","mine","includes","written","Set","map","policies","some","key","has","steps","step","text","AI_BUILD_STORE_PRODUCTS_TEXT","opens","HOST_LAYOUTS","record","push","draft","live","sitePublish","published","aiStoreFinishHostId","hostId"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-job-links.ts"],"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 */\nimport { buildRoute, Route } from '@aglyn/aglyn/app-utils/console-routes'\nimport {\n pluginRecordHref,\n pluginRecordListHref,\n} from '@aglyn/aglyn/plugin-manager/plugin-record-routes'\nimport { AI_JOB_BESIGNER_SEGMENT as BESIGNER_SEGMENT, AI_SITE_BUILD_HREF } from '../model/ai-job-notice'\nimport type { AiJobOutput, AiJobSummary } from '../model/ai-jobs.types'\nimport { AI_STORE_FINISH_STEPS, type AiStoreFinishStep } from '../model/ai-site-store-pages'\nimport { AI_BUILD_STORE_LINKS_DRAFT_STEP, AI_BUILD_STORE_LINKS_MISSING_STEP } from '../model/ai-build-store-pages'\n\n// Where a job's work opens in the console (AGL-2904), shared by the AI jobs\n// drawer and every dialog that follows the job it started (AGL-3593).\n\n/**\n * Where \"open draft\" goes, or `null` when the output has no page of its\n * own — a `text` output carries its copy on the job and is shown inline.\n * A versioned resource opens in the besigner on the version the job wrote;\n * one the console lists without a detail page opens its list; a `theme`\n * proposal opens the site's Theme section, where it is put in the editor.\n *\n * A console URL names a site by its SUBDOMAIN: the `[host]` segment resolves\n * through the member's host projection by subdomain, never by document id.\n * So an output that carries no `hostSubdomain` gets no link rather than one\n * that opens no site.\n */\nexport function aiJobOutputHref(output: AiJobOutput, orgSlug: string): string | null {\n const host = output.hostSubdomain\n if (!orgSlug || !host) return null\n const segment = BESIGNER_SEGMENT[output.resource]\n if (segment) {\n const base = `/${orgSlug}/hosts/${host}/${segment}/${output.id}`\n return output.versionId ? `${base}/versions/${output.versionId}/besigner` : base\n }\n if (output.resource === 'product') {\n // The catalog a drafted product lands in: the commerce plugin's address\n // for it (AGL-3080), or no link where commerce is not loaded.\n return pluginRecordListHref('product', { orgSlug, host })\n }\n if (output.resource === 'workflow') {\n // A drafted automation is an action (AGL-2919), listed switched off on\n // the workflows plugin's list of actions, or no link where it is not loaded.\n return pluginRecordListHref('action', { orgSlug, host })\n }\n if (output.resource === 'entry') {\n // A post a guided start wrote (AGL-3676) opens in its blog's list in Content.\n const collectionSlug = output.proposal?.['collectionSlug']\n return typeof collectionSlug === 'string' && collectionSlug\n ? buildRoute(Route.HOST_CONTENT_COLLECTION, { orgSlug, host, collectionSlug })\n : buildRoute(Route.HOST_CONTENT, { orgSlug, host })\n }\n if (output.resource === 'theme') {\n return buildRoute(Route.HOST_SETUP_THEME, { orgSlug, host })\n }\n if (output.resource === 'media') {\n // Files a build organized (AGL-3752) open in the site's media library.\n return buildRoute(Route.HOST_MEDIA, { orgSlug, host })\n }\n if (output.resource === 'settings') {\n // Settings a build saved (AGL-3748) open where most of them are edited.\n return buildRoute(Route.HOST_SETUP_SEO, { orgSlug, host })\n }\n if (output.resource === 'tracking') {\n // Tags a build saved (AGL-3751) open on the card that edits them.\n return buildRoute(Route.HOST_SETUP_TRACKING, { orgSlug, host })\n }\n if (output.resource === 'privacy') {\n // Who can see the site (AGL-4033), each change on the card that makes it.\n if (output.id === 'maintenance') return buildRoute(Route.HOST_ADMIN_ERROR_PAGES, { orgSlug, host })\n if (output.id === 'search') return buildRoute(Route.HOST_SETUP_SEO, { orgSlug, host })\n return buildRoute(Route.HOST_SCREENS, { orgSlug, host })\n }\n if (output.resource === 'draft' && output.draftResource) {\n // A draft another plugin wrote — a dataset a site start or a build made\n // (AGL-3616) — opens where its owner lists it, or nowhere it is not loaded.\n return pluginRecordListHref(output.draftResource, { orgSlug, host })\n }\n if (output.resource === 'form') {\n // A new form has no version for the besigner to open: its own page — the\n // forms plugin's address for it — mints the first one, and holds the\n // routing and consent it declares.\n return pluginRecordHref('form', { orgSlug, host }, output.id)\n }\n if (output.resource === 'campaign') {\n // A campaign's page is the marketing plugin's, under the site: its\n // address for the campaign (AGL-3080), or no link where it is not loaded.\n return pluginRecordHref('campaign', { orgSlug, host }, output.id)\n }\n return null\n}\n\n/**\n * The ONE action a finished job's row, its notification and the dialog that\n * started it lead with (AGL-3593): what the job built. Several pages from one\n * job — a site's — open the site's Pages list, where they wait as drafts; one\n * output with a page of its own opens that page; anything else has no single\n * place to go, and the row's own links stand. `null` until the job is done.\n */\nexport function aiJobPrimaryLink(\n job: Pick<AiJobSummary, 'status' | 'outputs'>,\n orgSlug: string,\n): { href: string; label: string } | null {\n if (job.status !== 'done' || !orgSlug) return null\n const screens = job.outputs.filter(\n (output) => output.resource === 'screen' && output.hostSubdomain,\n )\n if (screens.length > 1) {\n return {\n href: buildRoute(Route.HOST_SCREENS, { orgSlug, host: String(screens[0].hostSubdomain) }),\n label: 'Open your draft pages',\n }\n }\n for (const output of job.outputs) {\n const href = aiJobOutputHref(output, orgSlug)\n if (href) {\n return {\n href,\n label: output.resource === 'screen' ? 'Open the draft page' : `Open ${output.label}`,\n }\n }\n }\n return null\n}\n\nexport { AI_SITE_BUILD_HREF }\n\n/**\n * The \"Building your site\" page for one site job (AGL-3594): linkable, so the\n * guided start lands on it, a reload keeps it and a notification opens it.\n * `null` without the org slug or the site's subdomain a console URL needs.\n */\nexport function aiSiteBuildHref(\n orgSlug: string | null | undefined,\n hostSubdomain: string | null | undefined,\n jobId: string,\n): string | null {\n if (!orgSlug || !hostSubdomain || !jobId) return null\n return `/${orgSlug}/hosts/${hostSubdomain}${AI_SITE_BUILD_HREF}/${encodeURIComponent(jobId)}`\n}\n\n/** A page version's own address under a site, for the console route named by `leaf`. */\nfunction screenVersionHref(orgSlug: string, output: AiJobOutput, leaf: 'preview' | 'besigner'): string {\n return `/${orgSlug}/hosts/${String(output.hostSubdomain)}/screens/${output.id}/versions/${output.versionId}/${leaf}`\n}\n\n/**\n * A finished site's two ways in (AGL-3594): its first page's draft, opened in\n * the console's preview of that version — the page as a visitor will see it,\n * never its details — and the Pages list every draft waits in. Either is\n * `null` where the job reported nothing to open.\n */\nexport function aiSiteBuildDoneLinks(\n job: Pick<AiJobSummary, 'outputs'>,\n orgSlug: string,\n): { view: string | null; pages: string | null } {\n const screens = job.outputs.filter((output) => output.resource === 'screen' && output.hostSubdomain)\n const first = screens[0]\n if (!first || !orgSlug) return { view: null, pages: null }\n const host = String(first.hostSubdomain)\n return {\n // A change in a page's draft is not in its version's preview (AGL-4116).\n view: first.versionId && !first.inDraft ? screenVersionHref(orgSlug, first, 'preview') : null,\n pages: buildRoute(Route.HOST_SCREENS, { orgSlug, host }),\n }\n}\n\n/**\n * The two ways to look at the one page a job changed (AGL-3616): its new\n * version in the preview, where it can be published, and in the Besigner.\n * A change saved into the page's draft (AGL-4116) has no preview of its own\n * — a version's preview shows the version, not its draft — so only the\n * Besigner, where Open draft shows it. `null` where the job wrote no page\n * version, or more than one page — those wait in Pages.\n */\nexport function aiJobReviewLinks(\n job: Pick<AiJobSummary, 'outputs'>,\n orgSlug: string,\n): { preview: string | null; besigner: string } | null {\n if (!orgSlug) return null\n const pages = job.outputs.filter((output) => output.resource === 'screen' && output.hostSubdomain && output.versionId)\n if (new Set(pages.map((page) => page.id)).size !== 1) return null\n return {\n preview: pages[0].inDraft ? null : screenVersionHref(orgSlug, pages[0], 'preview'),\n besigner: screenVersionHref(orgSlug, pages[0], 'besigner'),\n }\n}\n\n/**\n * Where a person gets more AI credits (AGL-3660): the workspace's Billing\n * page at its plans, where an upgrade and the AI add-on are both sold — the\n * door the AI credits meter's own upgrade link opens.\n */\nexport function aiCreditsBillingHref(orgSlug: string): string {\n return `${buildRoute(Route.MANAGE_BILLING, { orgSlug })}#plans`\n}\n\n/** One thing left to finish an AI-built store, with where it is done. */\nexport interface AiStoreFinishLink extends AiStoreFinishStep {\n /** The console page it is done on; `null` where the owner of that page is not loaded. */\n href: string | null\n}\n\n/**\n * What is left to finish a store a site start built (AGL-3676), or `null`\n * where the start built no store's own pages: its account, cart and policy\n * pages are written, so payments, products, shipping and tax, and the\n * policies' brackets are all that remain. Each links the exact console page:\n * the store's settings and its catalog, as the commerce plugin publishes\n * them, and the site's Pages.\n */\nexport function aiStoreFinishLinks(\n job: Pick<AiJobSummary, 'kind' | 'status' | 'items' | 'outputs'> & Partial<Pick<AiJobSummary, 'sitePublish'>>,\n orgSlug: string,\n): AiStoreFinishLink[] | null {\n // A site start's store, or an Assist build that made the site a store (AGL-3676).\n if ((job.kind !== 'site' && job.kind !== 'build') || job.status !== 'done' || !orgSlug) return null\n const row = (job.items ?? []).find((one) => one.slot === 'store')\n if (!row || (row.status !== 'succeeded' && row.status !== 'degraded')) return null\n const host = job.outputs.find((output) => output.resource === 'screen' && output.hostSubdomain)?.hostSubdomain\n if (!host) return null\n const context = { orgSlug, host: String(host) }\n // A build's products are drafts with no price unless asked, and it may\n // have written none of the policies (the site had them): its list says so.\n const build = job.kind === 'build'\n const mine = job.outputs.filter((output) => row.outputs.includes(output.id))\n const written = new Set(mine.map((output) => output.proposal?.['storePage']))\n const policies = !build || ['shipping', 'privacy', 'terms'].some((key) => written.has(key))\n const steps: AiStoreFinishLink[] = AI_STORE_FINISH_STEPS.filter((step) => step.id !== 'policies' || policies).map((step) => ({\n ...step,\n ...(build && step.id === 'products' ? { text: AI_BUILD_STORE_PRODUCTS_TEXT } : {}),\n href:\n step.opens === 'pages'\n ? buildRoute(Route.HOST_SCREENS, context)\n : step.opens === 'layouts' || step.opens === 'layout'\n ? buildRoute(Route.HOST_LAYOUTS, context)\n : step.record\n ? pluginRecordHref(step.opens, context, step.record)\n : pluginRecordListHref(step.opens, context),\n }))\n if (!build) return steps\n // The site's own header and footer (AGL-3676): links it had no list for are\n // the owner's to add; links drafted into it wait for its publish.\n if (mine.some((output) => output.proposal?.['storeLinks'] === 'missing')) {\n steps.push({ ...AI_BUILD_STORE_LINKS_MISSING_STEP, href: buildRoute(Route.HOST_LAYOUTS, context) })\n }\n const draft = mine.find((output) => output.resource === 'layout' && output.proposal?.['storeLinks'] === 'draft')\n const live = draft && job.sitePublish?.published.length\n if (draft && !live) steps.push({ ...AI_BUILD_STORE_LINKS_DRAFT_STEP, href: aiJobOutputHref(draft, orgSlug) })\n return steps\n}\n\n/**\n * The site an AI-built store is on — the one {@link aiStoreFinishLinks}\n * links — so \"Finish your store\" can read whether its workspace already takes\n * payments (AGL-3982). `null` where no output names a site.\n */\nexport function aiStoreFinishHostId(job: Pick<AiJobSummary, 'outputs'>): string | null {\n return job.outputs.find((output) => output.resource === 'screen' && output.hostSubdomain)?.hostId ?? null\n}\n\n/** What a build's \"Review your products\" step says: its products are drafts, priced only where the request said. */\nexport const AI_BUILD_STORE_PRODUCTS_TEXT =\n 'Your new products are drafts. Set their prices, photos and stock, then make them active so they show in your store.'\n"],"names":["buildRoute","Route","pluginRecordHref","pluginRecordListHref","AI_JOB_BESIGNER_SEGMENT","BESIGNER_SEGMENT","AI_SITE_BUILD_HREF","AI_STORE_FINISH_STEPS","AI_BUILD_STORE_LINKS_DRAFT_STEP","AI_BUILD_STORE_LINKS_MISSING_STEP","aiJobOutputHref","output","orgSlug","host","hostSubdomain","segment","resource","base","id","versionId","collectionSlug","proposal","HOST_CONTENT_COLLECTION","HOST_CONTENT","HOST_SETUP_THEME","HOST_MEDIA","HOST_SETUP_SEO","HOST_SETUP_TRACKING","HOST_ADMIN_ERROR_PAGES","HOST_SCREENS","draftResource","aiJobPrimaryLink","job","status","screens","outputs","filter","length","href","String","label","aiSiteBuildHref","jobId","encodeURIComponent","screenVersionHref","leaf","aiSiteBuildDoneLinks","first","view","pages","inDraft","aiJobReviewLinks","Set","map","page","size","preview","besigner","aiCreditsBillingHref","MANAGE_BILLING","aiStoreFinishLinks","kind","row","items","find","one","slot","context","build","mine","includes","written","policies","some","key","has","steps","step","text","AI_BUILD_STORE_PRODUCTS_TEXT","opens","HOST_LAYOUTS","record","push","draft","live","sitePublish","published","aiStoreFinishHostId","hostId"],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { type MaybeTokenSource } from '@aglyn/shared-util-http/authorized-token'
|
|
|
2
2
|
import { type AiCreditsPrompt } from '../model/ai-credit-estimate';
|
|
3
3
|
import type { AiJobSummary } from '../model/ai-jobs.types';
|
|
4
4
|
import { type AssistBuildProposal } from '../model/assist-build';
|
|
5
|
+
import { type AssistPageChangeProposal } from '../model/assist-page-change';
|
|
5
6
|
/**
|
|
6
7
|
* The two decisions a person makes about a job — confirm its plan (or try a
|
|
7
8
|
* refused step again), and cancel it — as ONE request each, whichever
|
|
@@ -57,5 +58,13 @@ export declare function resumeAiJobRequest(user: MaybeTokenSource, orgId: string
|
|
|
57
58
|
* card; nothing is built until the person confirms it.
|
|
58
59
|
*/
|
|
59
60
|
export declare function startAssistBuildRequest(user: MaybeTokenSource, orgId: string, proposal: AssistBuildProposal): Promise<AiJobDecision>;
|
|
61
|
+
/**
|
|
62
|
+
* Starts the change to a page a chat turn asked for (AGL-4116): one `edit`
|
|
63
|
+
* job on that page, through the door every job is created by, which checks
|
|
64
|
+
* the page and the plan again. There is no plan to confirm: what comes back
|
|
65
|
+
* is the job making the draft, or the reason it could not start.
|
|
66
|
+
* `versionId` continues the draft an earlier change in the conversation made.
|
|
67
|
+
*/
|
|
68
|
+
export declare function startAssistPageChangeRequest(user: MaybeTokenSource, orgId: string, proposal: AssistPageChangeProposal, versionId: string | null): Promise<AiJobDecision>;
|
|
60
69
|
/** Cancels a job that has not settled. */
|
|
61
70
|
export declare function cancelAiJobRequest(user: MaybeTokenSource, orgId: string, jobId: string): Promise<AiJobDecision>;
|
|
@@ -18,6 +18,7 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
|
18
18
|
import { authorizedFetch } from "@aglyn/shared-util-http/authorized-token";
|
|
19
19
|
import { AI_CREDITS_CONFIRM_CODE } from "../model/ai-credit-estimate.js";
|
|
20
20
|
import { assistBuildJobRequest } from "../model/assist-build.js";
|
|
21
|
+
import { assistPageChangeJobRequest } from "../model/assist-page-change.js";
|
|
21
22
|
import { publishAiJob } from "./ai-jobs-store.js";
|
|
22
23
|
/**
|
|
23
24
|
* Confirms a plan, or tries again a step whose answer broke a building rule
|
|
@@ -98,6 +99,39 @@ import { publishAiJob } from "./ai-jobs-store.js";
|
|
|
98
99
|
};
|
|
99
100
|
}
|
|
100
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Starts the change to a page a chat turn asked for (AGL-4116): one `edit`
|
|
104
|
+
* job on that page, through the door every job is created by, which checks
|
|
105
|
+
* the page and the plan again. There is no plan to confirm: what comes back
|
|
106
|
+
* is the job making the draft, or the reason it could not start.
|
|
107
|
+
* `versionId` continues the draft an earlier change in the conversation made.
|
|
108
|
+
*/ export async function startAssistPageChangeRequest(user, orgId, proposal, versionId) {
|
|
109
|
+
const failed = 'The change could not be started — try asking again.';
|
|
110
|
+
try {
|
|
111
|
+
var _ref, _ref1;
|
|
112
|
+
const response = await authorizedFetch(user, '/api/ai/jobs', {
|
|
113
|
+
method: 'POST',
|
|
114
|
+
headers: {
|
|
115
|
+
'Content-Type': 'application/json'
|
|
116
|
+
},
|
|
117
|
+
body: JSON.stringify(assistPageChangeJobRequest(orgId, proposal, versionId))
|
|
118
|
+
});
|
|
119
|
+
const payload = await response.json().catch(()=>null);
|
|
120
|
+
const next = (_ref = payload == null ? void 0 : payload.job) != null ? _ref : null;
|
|
121
|
+
if (response.ok && next) publishAiJob(next);
|
|
122
|
+
return _extends({
|
|
123
|
+
job: response.ok ? next : null,
|
|
124
|
+
error: response.ok && next ? null : String((_ref1 = payload == null ? void 0 : payload.error) != null ? _ref1 : failed)
|
|
125
|
+
}, (payload == null ? void 0 : payload.meter) ? {
|
|
126
|
+
meter: payload.meter
|
|
127
|
+
} : {});
|
|
128
|
+
} catch (unused) {
|
|
129
|
+
return {
|
|
130
|
+
job: null,
|
|
131
|
+
error: failed
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
}
|
|
101
135
|
/** Cancels a job that has not settled. */ export async function cancelAiJobRequest(user, orgId, jobId) {
|
|
102
136
|
try {
|
|
103
137
|
var _ref, _ref1;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-job-requests.ts"],"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 { authorizedFetch, type MaybeTokenSource } from '@aglyn/shared-util-http/authorized-token'\nimport { AI_CREDITS_CONFIRM_CODE, type AiCreditsPrompt } from '../model/ai-credit-estimate'\nimport type { AiJobSummary } from '../model/ai-jobs.types'\nimport { assistBuildJobRequest, type AssistBuildProposal } from '../model/assist-build'\nimport { publishAiJob } from './ai-jobs-store'\n\n/**\n * The two decisions a person makes about a job — confirm its plan (or try a\n * refused step again), and cancel it — as ONE request each, whichever\n * surface they press it on (AGL-3593). The AI jobs drawer and the dialog that\n * started the job both call these, so confirming in the dialog is the same\n * door, the same body and the same answer as confirming in the drawer.\n *\n * Each hands the job it gets back to every counting surface, so the top-bar\n * indicator stops saying \"plan ready\" the moment the plan is confirmed.\n */\n\n/** A door's answer: the job as it now stands, and the refusal when there is one. */\nexport interface AiJobDecision {\n job: AiJobSummary | null\n error: string | null\n /**\n * A Free job past what is left (AGL-3722): the door's 409 asks for the\n * person's go-ahead with these figures and choices instead of starting it.\n */\n credits?: AiCreditsPrompt | null\n /**\n * The usage strip's envelope the job door answered with, when it ran a step\n * inline (AGL-3722): what the plan just spent, so the strip moves with it.\n */\n meter?: unknown\n /** Why each answer a `needs_input` job asked for cannot be used, by field (AGL-3978). */\n fieldErrors?: Record<string, string> | null\n}\n\n/**\n * What a resume asks beyond confirming (AGL-3616): a build's plan confirmed\n * with its publish box ticked, or a finished build's failed items tried again.\n */\nexport interface AiJobResumeOptions {\n publish?: boolean\n retry?: 'failed-items'\n /** \"Build what fits\" (AGL-3722): a Free job past what is left, started on the person's go-ahead. */\n creditsConfirmed?: boolean\n /** \"Build the home page first\" (AGL-3722): the plan narrowed to its home page and what it needs. */\n reduce?: 'first-page'\n /** The answers a job waiting in `needs_input` asks for (AGL-3978), by `aiJobInputKey`. */\n input?: Record<string, string>\n /** \"Start every remaining wave\" (AGL-4084): an import starts its next wave and every one after it. */\n startAll?: boolean\n}\n\n/**\n * Confirms a plan, or tries again a step whose answer broke a building rule\n * (AGL-2935). The door runs the next step inline and answers with the job.\n */\nexport async function resumeAiJobRequest(\n user: MaybeTokenSource,\n orgId: string,\n job: Pick<AiJobSummary, 'id' | 'hostId'>,\n options: AiJobResumeOptions = {},\n): Promise<AiJobDecision> {\n try {\n const response = await authorizedFetch(\n user,\n `/api/ai/jobs/${encodeURIComponent(job.id)}/resume`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n orgId,\n hostId: job.hostId,\n ...(options.publish ? { publish: true } : {}),\n ...(options.retry ? { retry: options.retry } : {}),\n ...(options.creditsConfirmed ? { creditsConfirmed: true } : {}),\n ...(options.reduce ? { reduce: options.reduce } : {}),\n ...(options.input ? { input: options.input } : {}),\n ...(options.startAll ? { startAll: true } : {}),\n }),\n },\n )\n const payload = await response.json().catch(() => null)\n const next = (payload?.job as AiJobSummary | undefined) ?? null\n publishAiJob(next)\n const credits =\n response.status === 409 && payload?.code === AI_CREDITS_CONFIRM_CODE\n ? ((payload?.credits as AiCreditsPrompt | undefined) ?? null)\n : null\n return {\n job: next,\n error: response.ok\n ? null\n : String(payload?.error ?? 'The job could not be resumed — try again.'),\n ...(credits ? { credits } : {}),\n ...(payload?.fieldErrors ? { fieldErrors: payload.fieldErrors as Record<string, string> } : {}),\n }\n } catch {\n return { job: null, error: 'The job could not be resumed — try again.' }\n }\n}\n\n/**\n * Starts the build a chat turn proposed (AGL-3616): one `build` job on the\n * proposal's site, through the same door every job is created by, which\n * climbs its own gates and plans inline. What comes back stops at its plan\n * card; nothing is built until the person confirms it.\n */\nexport async function startAssistBuildRequest(\n user: MaybeTokenSource,\n orgId: string,\n proposal: AssistBuildProposal,\n): Promise<AiJobDecision> {\n const failed = 'The build could not be planned — try asking again.'\n try {\n const response = await authorizedFetch(user, '/api/ai/jobs', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(assistBuildJobRequest(orgId, proposal)),\n })\n const payload = await response.json().catch(() => null)\n const next = (payload?.job as AiJobSummary | undefined) ?? null\n if (response.ok && next) publishAiJob(next)\n return {\n job: response.ok ? next : null,\n error: response.ok && next ? null : String(payload?.error ?? failed),\n ...(payload?.meter ? { meter: payload.meter } : {}),\n }\n } catch {\n return { job: null, error: failed }\n }\n}\n\n/** Cancels a job that has not settled. */\nexport async function cancelAiJobRequest(\n user: MaybeTokenSource,\n orgId: string,\n jobId: string,\n): Promise<AiJobDecision> {\n try {\n const response = await authorizedFetch(\n user,\n `/api/ai/jobs/${encodeURIComponent(jobId)}/cancel`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ orgId }),\n },\n )\n const payload = await response.json().catch(() => null)\n const next = (payload?.job as AiJobSummary | undefined) ?? null\n publishAiJob(next)\n return {\n job: next,\n error: response.ok\n ? null\n : String(payload?.error ?? 'The job could not be canceled — try again.'),\n }\n } catch {\n return { job: null, error: 'The job could not be canceled — try again.' }\n }\n}\n"],"names":["authorizedFetch","AI_CREDITS_CONFIRM_CODE","assistBuildJobRequest","publishAiJob","resumeAiJobRequest","user","orgId","job","options","response","encodeURIComponent","id","method","headers","body","JSON","stringify","hostId","publish","retry","creditsConfirmed","reduce","input","startAll","payload","json","catch","next","credits","status","code","error","ok","String","fieldErrors","startAssistBuildRequest","proposal","failed","meter","cancelAiJobRequest","jobId"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-job-requests.ts"],"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 { authorizedFetch, type MaybeTokenSource } from '@aglyn/shared-util-http/authorized-token'\nimport { AI_CREDITS_CONFIRM_CODE, type AiCreditsPrompt } from '../model/ai-credit-estimate'\nimport type { AiJobSummary } from '../model/ai-jobs.types'\nimport { assistBuildJobRequest, type AssistBuildProposal } from '../model/assist-build'\nimport { assistPageChangeJobRequest, type AssistPageChangeProposal } from '../model/assist-page-change'\nimport { publishAiJob } from './ai-jobs-store'\n\n/**\n * The two decisions a person makes about a job — confirm its plan (or try a\n * refused step again), and cancel it — as ONE request each, whichever\n * surface they press it on (AGL-3593). The AI jobs drawer and the dialog that\n * started the job both call these, so confirming in the dialog is the same\n * door, the same body and the same answer as confirming in the drawer.\n *\n * Each hands the job it gets back to every counting surface, so the top-bar\n * indicator stops saying \"plan ready\" the moment the plan is confirmed.\n */\n\n/** A door's answer: the job as it now stands, and the refusal when there is one. */\nexport interface AiJobDecision {\n job: AiJobSummary | null\n error: string | null\n /**\n * A Free job past what is left (AGL-3722): the door's 409 asks for the\n * person's go-ahead with these figures and choices instead of starting it.\n */\n credits?: AiCreditsPrompt | null\n /**\n * The usage strip's envelope the job door answered with, when it ran a step\n * inline (AGL-3722): what the plan just spent, so the strip moves with it.\n */\n meter?: unknown\n /** Why each answer a `needs_input` job asked for cannot be used, by field (AGL-3978). */\n fieldErrors?: Record<string, string> | null\n}\n\n/**\n * What a resume asks beyond confirming (AGL-3616): a build's plan confirmed\n * with its publish box ticked, or a finished build's failed items tried again.\n */\nexport interface AiJobResumeOptions {\n publish?: boolean\n retry?: 'failed-items'\n /** \"Build what fits\" (AGL-3722): a Free job past what is left, started on the person's go-ahead. */\n creditsConfirmed?: boolean\n /** \"Build the home page first\" (AGL-3722): the plan narrowed to its home page and what it needs. */\n reduce?: 'first-page'\n /** The answers a job waiting in `needs_input` asks for (AGL-3978), by `aiJobInputKey`. */\n input?: Record<string, string>\n /** \"Start every remaining wave\" (AGL-4084): an import starts its next wave and every one after it. */\n startAll?: boolean\n}\n\n/**\n * Confirms a plan, or tries again a step whose answer broke a building rule\n * (AGL-2935). The door runs the next step inline and answers with the job.\n */\nexport async function resumeAiJobRequest(\n user: MaybeTokenSource,\n orgId: string,\n job: Pick<AiJobSummary, 'id' | 'hostId'>,\n options: AiJobResumeOptions = {},\n): Promise<AiJobDecision> {\n try {\n const response = await authorizedFetch(\n user,\n `/api/ai/jobs/${encodeURIComponent(job.id)}/resume`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n orgId,\n hostId: job.hostId,\n ...(options.publish ? { publish: true } : {}),\n ...(options.retry ? { retry: options.retry } : {}),\n ...(options.creditsConfirmed ? { creditsConfirmed: true } : {}),\n ...(options.reduce ? { reduce: options.reduce } : {}),\n ...(options.input ? { input: options.input } : {}),\n ...(options.startAll ? { startAll: true } : {}),\n }),\n },\n )\n const payload = await response.json().catch(() => null)\n const next = (payload?.job as AiJobSummary | undefined) ?? null\n publishAiJob(next)\n const credits =\n response.status === 409 && payload?.code === AI_CREDITS_CONFIRM_CODE\n ? ((payload?.credits as AiCreditsPrompt | undefined) ?? null)\n : null\n return {\n job: next,\n error: response.ok\n ? null\n : String(payload?.error ?? 'The job could not be resumed — try again.'),\n ...(credits ? { credits } : {}),\n ...(payload?.fieldErrors ? { fieldErrors: payload.fieldErrors as Record<string, string> } : {}),\n }\n } catch {\n return { job: null, error: 'The job could not be resumed — try again.' }\n }\n}\n\n/**\n * Starts the build a chat turn proposed (AGL-3616): one `build` job on the\n * proposal's site, through the same door every job is created by, which\n * climbs its own gates and plans inline. What comes back stops at its plan\n * card; nothing is built until the person confirms it.\n */\nexport async function startAssistBuildRequest(\n user: MaybeTokenSource,\n orgId: string,\n proposal: AssistBuildProposal,\n): Promise<AiJobDecision> {\n const failed = 'The build could not be planned — try asking again.'\n try {\n const response = await authorizedFetch(user, '/api/ai/jobs', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(assistBuildJobRequest(orgId, proposal)),\n })\n const payload = await response.json().catch(() => null)\n const next = (payload?.job as AiJobSummary | undefined) ?? null\n if (response.ok && next) publishAiJob(next)\n return {\n job: response.ok ? next : null,\n error: response.ok && next ? null : String(payload?.error ?? failed),\n ...(payload?.meter ? { meter: payload.meter } : {}),\n }\n } catch {\n return { job: null, error: failed }\n }\n}\n\n/**\n * Starts the change to a page a chat turn asked for (AGL-4116): one `edit`\n * job on that page, through the door every job is created by, which checks\n * the page and the plan again. There is no plan to confirm: what comes back\n * is the job making the draft, or the reason it could not start.\n * `versionId` continues the draft an earlier change in the conversation made.\n */\nexport async function startAssistPageChangeRequest(\n user: MaybeTokenSource,\n orgId: string,\n proposal: AssistPageChangeProposal,\n versionId: string | null,\n): Promise<AiJobDecision> {\n const failed = 'The change could not be started — try asking again.'\n try {\n const response = await authorizedFetch(user, '/api/ai/jobs', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(assistPageChangeJobRequest(orgId, proposal, versionId)),\n })\n const payload = await response.json().catch(() => null)\n const next = (payload?.job as AiJobSummary | undefined) ?? null\n if (response.ok && next) publishAiJob(next)\n return {\n job: response.ok ? next : null,\n error: response.ok && next ? null : String(payload?.error ?? failed),\n ...(payload?.meter ? { meter: payload.meter } : {}),\n }\n } catch {\n return { job: null, error: failed }\n }\n}\n\n/** Cancels a job that has not settled. */\nexport async function cancelAiJobRequest(\n user: MaybeTokenSource,\n orgId: string,\n jobId: string,\n): Promise<AiJobDecision> {\n try {\n const response = await authorizedFetch(\n user,\n `/api/ai/jobs/${encodeURIComponent(jobId)}/cancel`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ orgId }),\n },\n )\n const payload = await response.json().catch(() => null)\n const next = (payload?.job as AiJobSummary | undefined) ?? null\n publishAiJob(next)\n return {\n job: next,\n error: response.ok\n ? null\n : String(payload?.error ?? 'The job could not be canceled — try again.'),\n }\n } catch {\n return { job: null, error: 'The job could not be canceled — try again.' }\n }\n}\n"],"names":["authorizedFetch","AI_CREDITS_CONFIRM_CODE","assistBuildJobRequest","assistPageChangeJobRequest","publishAiJob","resumeAiJobRequest","user","orgId","job","options","response","encodeURIComponent","id","method","headers","body","JSON","stringify","hostId","publish","retry","creditsConfirmed","reduce","input","startAll","payload","json","catch","next","credits","status","code","error","ok","String","fieldErrors","startAssistBuildRequest","proposal","failed","meter","startAssistPageChangeRequest","versionId","cancelAiJobRequest","jobId"],"mappings":"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"}
|
|
@@ -31,7 +31,7 @@ import { aiSiteStartAnswersFromInputs } from "../model/ai-site-start.js";
|
|
|
31
31
|
import { AiSiteStartCard } from "./ai-site-start-card.component.js";
|
|
32
32
|
import { AI_JOB_TERMINAL_STATUSES } from "../model/ai-jobs.types.js";
|
|
33
33
|
import { followAiJobEvents } from "./ai-job-events.js";
|
|
34
|
-
import { aiCreditsBillingHref, aiSiteBuildDoneLinks, aiStoreFinishHostId, aiStoreFinishLinks } from "./ai-job-links.js";
|
|
34
|
+
import { aiCreditsBillingHref, aiJobReviewLinks, aiSiteBuildDoneLinks, aiStoreFinishHostId, aiStoreFinishLinks } from "./ai-job-links.js";
|
|
35
35
|
import { AiStoreFinishCard } from "./ai-store-finish-card.component.js";
|
|
36
36
|
import { AiJobPlan } from "./ai-job-plan.component.js";
|
|
37
37
|
import { aiBuildCanRetry, aiBuildRetryCreditRange } from "../model/ai-build-progress.js";
|
|
@@ -417,6 +417,9 @@ export function AiSiteBuildPage({ hostId, segments, basePath }) {
|
|
|
417
417
|
};
|
|
418
418
|
const sitePublish = ready.kind === 'site' && phase === 'done' ? (_ready_sitePublish = ready.sitePublish) != null ? _ready_sitePublish : null : null;
|
|
419
419
|
const liveUrl = sitePublish && sitePublish.published.length > 0 ? sitePublish.liveUrl : null;
|
|
420
|
+
// A job that changed one page (AGL-3616) leads with that page's new version,
|
|
421
|
+
// to look at and publish, rather than the site.
|
|
422
|
+
const review = phase === 'done' && ready.kind !== 'site' && !liveUrl ? aiJobReviewLinks(ready, orgSlug) : null;
|
|
420
423
|
// A store start's last steps (AGL-3676): only payments, products, shipping and tax, and the policies.
|
|
421
424
|
const storeFinish = phase === 'done' ? aiStoreFinishLinks(ready, orgSlug) : null;
|
|
422
425
|
// Paused by the meter (AGL-3660): out of credits or at a cap, carried on by Resume.
|
|
@@ -637,7 +640,30 @@ export function AiSiteBuildPage({ hostId, segments, basePath }) {
|
|
|
637
640
|
creditsConfirmed: true
|
|
638
641
|
})
|
|
639
642
|
}),
|
|
640
|
-
|
|
643
|
+
review ? /*#__PURE__*/ _jsxs(Stack, {
|
|
644
|
+
direction: {
|
|
645
|
+
xs: 'column',
|
|
646
|
+
sm: 'row'
|
|
647
|
+
},
|
|
648
|
+
spacing: 2,
|
|
649
|
+
children: [
|
|
650
|
+
review.preview ? /*#__PURE__*/ _jsx(Button, _extends({
|
|
651
|
+
variant: "contained",
|
|
652
|
+
size: "large",
|
|
653
|
+
component: AppLink,
|
|
654
|
+
href: review.preview
|
|
655
|
+
}, newTabLinkProps, {
|
|
656
|
+
children: 'Preview'
|
|
657
|
+
})) : null,
|
|
658
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
659
|
+
variant: review.preview ? 'outlined' : 'contained',
|
|
660
|
+
size: "large",
|
|
661
|
+
component: AppLink,
|
|
662
|
+
href: review.besigner,
|
|
663
|
+
children: 'Open in Besigner'
|
|
664
|
+
})
|
|
665
|
+
]
|
|
666
|
+
}) : phase === 'done' && !liveNotice && /*#__PURE__*/ _jsxs(Stack, {
|
|
641
667
|
direction: {
|
|
642
668
|
xs: 'column',
|
|
643
669
|
sm: 'row'
|