@aglyn/plugins-ai 1.0.0-beta.229 → 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/README.md +3 -3
- package/package.json +17 -17
- package/src/lib/activity/ai-activity-actions.js +7 -1
- package/src/lib/activity/ai-activity-actions.js.map +1 -1
- 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-automation-zones.d.ts +38 -0
- package/src/lib/components/ai-automation-zones.js +5 -1
- package/src/lib/components/ai-automation-zones.js.map +1 -1
- package/src/lib/components/ai-brief-dialog.component.d.ts +20 -2
- package/src/lib/components/ai-brief-dialog.component.js +87 -8
- package/src/lib/components/ai-brief-dialog.component.js.map +1 -1
- package/src/lib/components/ai-campaign-create.component.d.ts +54 -0
- package/src/lib/components/ai-campaign-create.component.js +270 -0
- package/src/lib/components/ai-campaign-create.component.js.map +1 -0
- package/src/lib/components/ai-describe-automation.component.d.ts +8 -3
- package/src/lib/components/ai-describe-automation.component.js +15 -6
- package/src/lib/components/ai-describe-automation.component.js.map +1 -1
- package/src/lib/components/ai-describe-button.component.d.ts +20 -8
- package/src/lib/components/ai-describe-button.component.js +19 -36
- package/src/lib/components/ai-describe-button.component.js.map +1 -1
- package/src/lib/components/ai-describe-email.component.d.ts +31 -0
- package/src/lib/components/ai-describe-email.component.js +22 -0
- package/src/lib/components/ai-describe-email.component.js.map +1 -0
- package/src/lib/components/ai-describe-org-automation.component.d.ts +36 -0
- package/src/lib/components/ai-describe-org-automation.component.js +238 -0
- package/src/lib/components/ai-describe-org-automation.component.js.map +1 -0
- package/src/lib/components/ai-experiment-cards.component.d.ts +9 -1
- package/src/lib/components/ai-experiment-cards.component.js +104 -18
- package/src/lib/components/ai-experiment-cards.component.js.map +1 -1
- package/src/lib/components/ai-explain-automation.component.js +1 -5
- package/src/lib/components/ai-explain-automation.component.js.map +1 -1
- package/src/lib/components/ai-funnel-zones.component.d.ts +61 -0
- package/src/lib/components/ai-funnel-zones.component.js +178 -0
- package/src/lib/components/ai-funnel-zones.component.js.map +1 -0
- package/src/lib/components/ai-insight-card.component.d.ts +42 -0
- package/src/lib/components/ai-insight-card.component.js +137 -0
- package/src/lib/components/ai-insight-card.component.js.map +1 -0
- package/src/lib/components/ai-insight-dialog.component.d.ts +6 -0
- package/src/lib/components/ai-insight-dialog.component.js +9 -3
- package/src/lib/components/ai-insight-dialog.component.js.map +1 -1
- package/src/lib/components/ai-job-plan.component.d.ts +7 -2
- package/src/lib/components/ai-job-plan.component.js +38 -6
- package/src/lib/components/ai-job-plan.component.js.map +1 -1
- package/src/lib/components/ai-job-requests.d.ts +17 -1
- package/src/lib/components/ai-job-requests.js +39 -3
- package/src/lib/components/ai-job-requests.js.map +1 -1
- package/src/lib/components/ai-logic-zones.d.ts +64 -0
- package/src/lib/components/ai-logic-zones.js +18 -0
- package/src/lib/components/ai-logic-zones.js.map +1 -0
- package/src/lib/components/ai-logic.component.d.ts +77 -0
- package/src/lib/components/ai-logic.component.js +553 -0
- package/src/lib/components/ai-logic.component.js.map +1 -0
- package/src/lib/components/ai-marketing-insight.component.d.ts +30 -0
- package/src/lib/components/ai-marketing-insight.component.js +80 -0
- package/src/lib/components/ai-marketing-insight.component.js.map +1 -0
- package/src/lib/components/ai-media-create.component.d.ts +55 -0
- package/src/lib/components/ai-media-create.component.js +433 -0
- package/src/lib/components/ai-media-create.component.js.map +1 -0
- package/src/lib/components/ai-overlay-cards.component.d.ts +83 -0
- package/src/lib/components/ai-overlay-cards.component.js +505 -0
- package/src/lib/components/ai-overlay-cards.component.js.map +1 -0
- 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-product-zones.d.ts +5 -0
- package/src/lib/components/ai-product-zones.js +1 -1
- package/src/lib/components/ai-product-zones.js.map +1 -1
- package/src/lib/components/ai-products-create-button.component.d.ts +42 -0
- package/src/lib/components/ai-products-create-button.component.js +67 -0
- package/src/lib/components/ai-products-create-button.component.js.map +1 -0
- package/src/lib/components/ai-products-hub-card.component.js +100 -81
- package/src/lib/components/ai-products-hub-card.component.js.map +1 -1
- package/src/lib/components/ai-revise-automation.component.d.ts +16 -0
- package/src/lib/components/ai-revise-automation.component.js +207 -0
- package/src/lib/components/ai-revise-automation.component.js.map +1 -0
- package/src/lib/components/ai-site-build-page.component.js +160 -24
- package/src/lib/components/ai-site-build-page.component.js.map +1 -1
- package/src/lib/components/ai-upsell-dialog.component.d.ts +53 -0
- package/src/lib/components/ai-upsell-dialog.component.js +177 -0
- package/src/lib/components/ai-upsell-dialog.component.js.map +1 -0
- package/src/lib/components/assist-build-card.component.d.ts +42 -0
- package/src/lib/components/assist-build-card.component.js +183 -0
- package/src/lib/components/assist-build-card.component.js.map +1 -0
- package/src/lib/components/assist-edit-canvas.d.ts +2 -0
- package/src/lib/components/assist-edit-canvas.js +56 -1
- package/src/lib/components/assist-edit-canvas.js.map +1 -1
- package/src/lib/components/assist-jobs-drawer.component.js +48 -3
- package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
- package/src/lib/components/assist-panel.component.js +51 -2
- package/src/lib/components/assist-panel.component.js.map +1 -1
- package/src/lib/components/use-ai-job-run.d.ts +3 -14
- package/src/lib/components/use-ai-job-run.js +0 -50
- package/src/lib/components/use-ai-job-run.js.map +1 -1
- package/src/lib/jobs/ai-build-capabilities.d.ts +58 -0
- package/src/lib/jobs/ai-build-capabilities.js +256 -0
- package/src/lib/jobs/ai-build-capabilities.js.map +1 -0
- package/src/lib/jobs/ai-build-unit-outcome.d.ts +52 -0
- package/src/lib/jobs/ai-build-unit-outcome.js +140 -0
- package/src/lib/jobs/ai-build-unit-outcome.js.map +1 -0
- 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.d.ts +144 -0
- package/src/lib/jobs/ai-job-build-step.js +668 -0
- package/src/lib/jobs/ai-job-build-step.js.map +1 -0
- package/src/lib/jobs/ai-job-draft-ids.js +9 -1
- package/src/lib/jobs/ai-job-draft-ids.js.map +1 -1
- package/src/lib/jobs/ai-job-drafts.d.ts +14 -4
- package/src/lib/jobs/ai-job-drafts.js +25 -4
- package/src/lib/jobs/ai-job-drafts.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-logic-step.d.ts +107 -0
- package/src/lib/jobs/ai-job-logic-step.js +395 -0
- package/src/lib/jobs/ai-job-logic-step.js.map +1 -0
- package/src/lib/jobs/ai-job-overlay-copy.d.ts +70 -0
- package/src/lib/jobs/ai-job-overlay-copy.js +178 -0
- package/src/lib/jobs/ai-job-overlay-copy.js.map +1 -0
- 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 +111 -20
- package/src/lib/jobs/ai-job-page-step.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-step.d.ts +27 -2
- package/src/lib/jobs/ai-job-plan-step.js +87 -13
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-step.d.ts +19 -1
- package/src/lib/jobs/ai-job-site-step.js +220 -61
- package/src/lib/jobs/ai-job-site-step.js.map +1 -1
- package/src/lib/jobs/ai-job-text-step.d.ts +22 -1
- package/src/lib/jobs/ai-job-text-step.js +12 -0
- package/src/lib/jobs/ai-job-text-step.js.map +1 -1
- package/src/lib/jobs/ai-job-workflow-step.d.ts +54 -4
- package/src/lib/jobs/ai-job-workflow-step.js +320 -15
- package/src/lib/jobs/ai-job-workflow-step.js.map +1 -1
- package/src/lib/jobs/ai-jobs.d.ts +80 -2
- package/src/lib/jobs/ai-jobs.js +391 -18
- 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/jobs/ai-logic-records.d.ts +40 -0
- package/src/lib/jobs/ai-logic-records.js +55 -0
- package/src/lib/jobs/ai-logic-records.js.map +1 -0
- package/src/lib/jobs/ai-site-publish.d.ts +7 -0
- package/src/lib/jobs/ai-site-publish.js +9 -0
- package/src/lib/jobs/ai-site-publish.js.map +1 -1
- package/src/lib/jobs/ai-workflow-records.d.ts +4 -0
- package/src/lib/jobs/ai-workflow-records.js +40 -1
- package/src/lib/jobs/ai-workflow-records.js.map +1 -1
- 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-automation-draft.d.ts +18 -0
- package/src/lib/model/ai-automation-draft.js +86 -0
- package/src/lib/model/ai-automation-draft.js.map +1 -1
- package/src/lib/model/ai-build-job.d.ts +201 -0
- package/src/lib/model/ai-build-job.js +472 -0
- package/src/lib/model/ai-build-job.js.map +1 -0
- package/src/lib/model/ai-build-plan.d.ts +61 -0
- package/src/lib/model/ai-build-plan.js +154 -9
- package/src/lib/model/ai-build-plan.js.map +1 -1
- package/src/lib/model/ai-build-progress.d.ts +73 -0
- package/src/lib/model/ai-build-progress.js +170 -0
- package/src/lib/model/ai-build-progress.js.map +1 -0
- 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-insight.d.ts +20 -10
- package/src/lib/model/ai-insight.js +72 -9
- package/src/lib/model/ai-insight.js.map +1 -1
- package/src/lib/model/ai-job-activity.d.ts +22 -0
- package/src/lib/model/ai-job-activity.js +25 -2
- 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 +99 -2
- package/src/lib/model/ai-jobs.types.js +3 -1
- package/src/lib/model/ai-jobs.types.js.map +1 -1
- package/src/lib/model/ai-logic-job.d.ts +108 -0
- package/src/lib/model/ai-logic-job.js +327 -0
- package/src/lib/model/ai-logic-job.js.map +1 -0
- package/src/lib/model/ai-media-credits.d.ts +52 -0
- package/src/lib/model/ai-media-credits.js +61 -0
- package/src/lib/model/ai-media-credits.js.map +1 -0
- package/src/lib/model/ai-overlay-copy.d.ts +114 -0
- package/src/lib/model/ai-overlay-copy.js +175 -0
- package/src/lib/model/ai-overlay-copy.js.map +1 -0
- package/src/lib/model/ai-site-build-progress.d.ts +25 -4
- package/src/lib/model/ai-site-build-progress.js +194 -11
- 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/model/ai-svg.d.ts +69 -0
- package/src/lib/model/ai-svg.js +265 -0
- package/src/lib/model/ai-svg.js.map +1 -0
- package/src/lib/model/ai-usage-by-user.d.ts +3 -2
- package/src/lib/model/ai-usage-by-user.js.map +1 -1
- package/src/lib/model/ai-workflow-job.d.ts +92 -4
- package/src/lib/model/ai-workflow-job.js +124 -7
- package/src/lib/model/ai-workflow-job.js.map +1 -1
- package/src/lib/model/assist-build.d.ts +58 -0
- package/src/lib/model/assist-build.js +52 -0
- package/src/lib/model/assist-build.js.map +1 -0
- package/src/lib/model/assist-edit.d.ts +48 -3
- package/src/lib/model/assist-edit.js +48 -4
- package/src/lib/model/assist-edit.js.map +1 -1
- package/src/lib/plugin-config.js +2 -0
- package/src/lib/plugin-config.js.map +1 -1
- package/src/lib/plugin.js +308 -47
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/providers/catalog.d.ts +82 -5
- package/src/lib/providers/catalog.js +83 -12
- package/src/lib/providers/catalog.js.map +1 -1
- package/src/lib/providers/image-contract.d.ts +116 -0
- package/src/lib/providers/image-contract.js +74 -0
- package/src/lib/providers/image-contract.js.map +1 -0
- package/src/lib/providers/model-choice.js +11 -0
- package/src/lib/providers/model-choice.js.map +1 -1
- package/src/lib/providers/routing.js +18 -0
- package/src/lib/providers/routing.js.map +1 -1
- package/src/lib/providers/vertex-image.d.ts +121 -0
- package/src/lib/providers/vertex-image.js +312 -0
- package/src/lib/providers/vertex-image.js.map +1 -0
- package/src/lib/runtime/ai-doctrine-validators.d.ts +101 -0
- package/src/lib/runtime/ai-doctrine-validators.js +525 -4
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-doctrine.js +21 -6
- package/src/lib/runtime/ai-doctrine.js.map +1 -1
- package/src/lib/runtime/ai-eval-live.js +4 -0
- package/src/lib/runtime/ai-eval-live.js.map +1 -1
- package/src/lib/runtime/ai-eval.d.ts +15 -1
- package/src/lib/runtime/ai-eval.js +52 -1
- package/src/lib/runtime/ai-eval.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/runtime/experiment-variant-copy.d.ts +34 -0
- package/src/lib/runtime/experiment-variant-copy.js +102 -0
- package/src/lib/runtime/experiment-variant-copy.js.map +1 -0
- package/src/lib/server/ai-experiment-versions.d.ts +51 -0
- package/src/lib/server/ai-experiment-versions.js +270 -0
- package/src/lib/server/ai-experiment-versions.js.map +1 -0
- package/src/lib/server/ai-jobs-resume.js +74 -4
- package/src/lib/server/ai-jobs-resume.js.map +1 -1
- package/src/lib/server/ai-media-image.d.ts +66 -0
- package/src/lib/server/ai-media-image.js +521 -0
- package/src/lib/server/ai-media-image.js.map +1 -0
- package/src/lib/server/ai-media-svg.d.ts +91 -0
- package/src/lib/server/ai-media-svg.js +186 -0
- package/src/lib/server/ai-media-svg.js.map +1 -0
- package/src/lib/server/assist-build.d.ts +54 -0
- package/src/lib/server/assist-build.js +121 -0
- package/src/lib/server/assist-build.js.map +1 -0
- package/src/lib/server/assist-chat.js +108 -12
- package/src/lib/server/assist-chat.js.map +1 -1
- package/src/lib/server/assist-edit.js +213 -3
- package/src/lib/server/assist-edit.js.map +1 -1
- package/src/lib/server/assist-view-context.js +242 -4
- package/src/lib/server/assist-view-context.js.map +1 -1
- package/src/lib/server.js +26 -0
- package/src/lib/server.js.map +1 -1
- package/src/lib/tools/ai-logic-tool.d.ts +27 -0
- package/src/lib/tools/ai-logic-tool.js +207 -0
- package/src/lib/tools/ai-logic-tool.js.map +1 -0
- package/src/lib/tools/ai-overlay-tool.d.ts +35 -0
- package/src/lib/tools/ai-overlay-tool.js +107 -0
- package/src/lib/tools/ai-overlay-tool.js.map +1 -0
- package/src/lib/tools/ai-workflow-tool.d.ts +17 -2
- package/src/lib/tools/ai-workflow-tool.js +47 -14
- package/src/lib/tools/ai-workflow-tool.js.map +1 -1
- package/src/lib/usage/assist-job-refund.d.ts +28 -1
- package/src/lib/usage/assist-job-refund.js +44 -9
- package/src/lib/usage/assist-job-refund.js.map +1 -1
- package/src/lib/usage/assist-usage.d.ts +5 -0
- package/src/lib/usage/assist-usage.js +2 -0
- package/src/lib/usage/assist-usage.js.map +1 -1
package/src/lib/jobs/ai-jobs.js
CHANGED
|
@@ -27,7 +27,6 @@ import { AI_JOB_PLAN_STEP, AI_JOB_TERMINAL_STATUSES } from "../model/ai-jobs.typ
|
|
|
27
27
|
import { resolveEffectivePlan } from "@aglyn/aglyn/app-utils/plan-entitlements";
|
|
28
28
|
import { aiOverageReservationRefusal } from "../billing/ai-overage-gate.js";
|
|
29
29
|
import { aiAllotmentRefusalText } from "../model/ai-allotments.js";
|
|
30
|
-
import { aiJobPlanCreditEstimate } from "../model/ai-site-job.js";
|
|
31
30
|
import { AI_OFF_FOR_SITE_COPY, isAiOffForSite } from "../model/ai-site-switch.js";
|
|
32
31
|
import { resolveAiModelChoice } from "../providers/model-choice.js";
|
|
33
32
|
import { aiOutputTargetType } from "../activity/ai-activity-actions.js";
|
|
@@ -40,10 +39,11 @@ import { AI_JOB_TEXT_STEP_MINIMUM_MS, runAiJobTextStep } from "./ai-job-text-ste
|
|
|
40
39
|
import { AI_JOB_SEO_STEP_MINIMUM_MS } from "./ai-job-seo-budget.js";
|
|
41
40
|
import { AI_JOB_THEME_STEP_MINIMUM_MS } from "./ai-job-theme-budget.js";
|
|
42
41
|
import { assistExchangeExpiry, assistUsageDay, assistUsageMonth, recordAssistCost, releaseAssistMessage, reserveAssistMessage } from "../usage/assist-usage.js";
|
|
43
|
-
import { aiJobRefundCredits, refundJobCredits } from "../usage/assist-job-refund.js";
|
|
42
|
+
import { aiJobItemRefundKey, aiJobRefundCredits, refundJobCredits } from "../usage/assist-job-refund.js";
|
|
43
|
+
import { aiBuildSettlement, aiBuildUnits, aiBuildRetryLedger, aiBuildCreditEstimate, aiLedgerUnits, aiJobCreditEstimate } from "../model/ai-build-job.js";
|
|
44
44
|
import { freeAssistAccount } from "../usage/assist-free-taste.js";
|
|
45
45
|
import { aiJobAutoConfirms } from "./ai-job-auto-confirm.js";
|
|
46
|
-
import { AI_SITE_GUIDED_BUILD_FAILED_COPY } from "../model/ai-job-failure-copy.js";
|
|
46
|
+
import { AI_SITE_GUIDED_BUILD_FAILED_COPY, aiCustomerSafeCopy, aiCustomerSafeItem, aiCustomerSafeReview } from "../model/ai-job-failure-copy.js";
|
|
47
47
|
import { aiSiteStartInputsOf } from "../model/ai-site-start.js";
|
|
48
48
|
import { addAdminAudit } from "@aglyn/tenant-data-admin/server/admin-audit-write";
|
|
49
49
|
/**
|
|
@@ -153,7 +153,8 @@ export { AI_JOB_PLAN_STEP };
|
|
|
153
153
|
'layout',
|
|
154
154
|
'template',
|
|
155
155
|
'form',
|
|
156
|
-
'email'
|
|
156
|
+
'email',
|
|
157
|
+
'build'
|
|
157
158
|
];
|
|
158
159
|
const stepRunners = new Map();
|
|
159
160
|
const stepMinimums = new Map();
|
|
@@ -455,8 +456,8 @@ export async function getAiJob(firestore, orgId, jobId) {
|
|
|
455
456
|
return code === 9 || code === 'failed-precondition' || code === 'FAILED_PRECONDITION';
|
|
456
457
|
}
|
|
457
458
|
/** The wire form. `running` is the lease, read against `now`. */ export function aiJobSummary(job, now = new Date()) {
|
|
458
|
-
var _job_hostId, _job_steps, _job_outputs, _job_creditsReserved, _job_creditsSpent, _job_refundedCredits, _toIso, _toIso1, _job_error, _job_plan_labels, _job_plan_confirmedBy,
|
|
459
|
-
var _job_lease, _job_inputs;
|
|
459
|
+
var _job_hostId, _job_steps, _job_outputs, _job_creditsReserved, _job_creditsSpent, _job_refundedCredits, _toIso, _toIso1, _job_error, _job_plan_labels, _job_plan_confirmedBy, _job_applied_versions, _job_applied_staged;
|
|
460
|
+
var _job_lease, _job_inputs, _job_items, _job_inputs1;
|
|
460
461
|
const leaseUntil = toMillis((_job_lease = job.lease) == null ? void 0 : _job_lease.until);
|
|
461
462
|
return _extends({
|
|
462
463
|
id: job.$id,
|
|
@@ -474,7 +475,7 @@ export async function getAiJob(firestore, orgId, jobId) {
|
|
|
474
475
|
startedAt: toIso(step.startedAt),
|
|
475
476
|
endedAt: toIso(step.endedAt),
|
|
476
477
|
creditsSpent: (_step_creditsSpent = step.creditsSpent) != null ? _step_creditsSpent : 0,
|
|
477
|
-
error: (_step_error = step.error) != null ? _step_error : null
|
|
478
|
+
error: aiCustomerSafeCopy((_step_error = step.error) != null ? _step_error : null)
|
|
478
479
|
};
|
|
479
480
|
}),
|
|
480
481
|
outputs: (_job_outputs = job.outputs) != null ? _job_outputs : [],
|
|
@@ -484,7 +485,10 @@ export async function getAiJob(firestore, orgId, jobId) {
|
|
|
484
485
|
createdBy: job.createdBy,
|
|
485
486
|
createdAt: (_toIso = toIso(job.createdAt)) != null ? _toIso : new Date(0).toISOString(),
|
|
486
487
|
updatedAt: (_toIso1 = toIso(job.updatedAt)) != null ? _toIso1 : new Date(0).toISOString(),
|
|
487
|
-
|
|
488
|
+
// The doctrine's own words never reach a customer (AGL-3596).
|
|
489
|
+
error: aiCustomerSafeCopy((_job_error = job.error) != null ? _job_error : null, {
|
|
490
|
+
page: job.kind === 'page'
|
|
491
|
+
}),
|
|
488
492
|
running: job.status === 'running' && leaseUntil !== null && leaseUntil > now.getTime(),
|
|
489
493
|
plan: job.plan ? _extends({}, job.plan, {
|
|
490
494
|
labels: (_job_plan_labels = job.plan.labels) != null ? _job_plan_labels : {},
|
|
@@ -492,7 +496,9 @@ export async function getAiJob(firestore, orgId, jobId) {
|
|
|
492
496
|
confirmedAt: toIso(job.plan.confirmedAt),
|
|
493
497
|
confirmedBy: (_job_plan_confirmedBy = job.plan.confirmedBy) != null ? _job_plan_confirmedBy : null
|
|
494
498
|
}) : null,
|
|
495
|
-
review:
|
|
499
|
+
review: job.review ? aiCustomerSafeReview(job.review, {
|
|
500
|
+
page: job.kind === 'page'
|
|
501
|
+
}) : null,
|
|
496
502
|
applied: job.applied ? {
|
|
497
503
|
at: toIso(job.applied.at),
|
|
498
504
|
by: job.applied.by,
|
|
@@ -503,6 +509,14 @@ export async function getAiJob(firestore, orgId, jobId) {
|
|
|
503
509
|
sitePublish: job.sitePublish
|
|
504
510
|
} : {}, job.kind === 'site' ? {
|
|
505
511
|
siteInputs: aiSiteStartInputsOf(job.inputs)
|
|
512
|
+
} : {}, aiJobAutoConfirms(job) ? {
|
|
513
|
+
autoConfirm: true
|
|
514
|
+
} : {}, ((_job_items = job.items) == null ? void 0 : _job_items.length) ? {
|
|
515
|
+
items: job.items.map(aiCustomerSafeItem)
|
|
516
|
+
} : {}, job.orchestration ? {
|
|
517
|
+
orchestration: job.orchestration
|
|
518
|
+
} : {}, job.kind === 'build' && ((_job_inputs1 = job.inputs) == null ? void 0 : _job_inputs1['publish']) === true ? {
|
|
519
|
+
publishAsked: true
|
|
506
520
|
} : {});
|
|
507
521
|
}
|
|
508
522
|
function leaseIsLive(job, owner, nowMs) {
|
|
@@ -622,6 +636,40 @@ function nextStepIndex(job) {
|
|
|
622
636
|
});
|
|
623
637
|
});
|
|
624
638
|
}
|
|
639
|
+
/**
|
|
640
|
+
* A build's ledger with one pass applied (AGL-3616): the pass's credits on
|
|
641
|
+
* the item's row, its status, failure, note and outputs, and what was given
|
|
642
|
+
* back for it. Pure; the machine applies it inside `recordStep`.
|
|
643
|
+
*/ export function aiApplyJobItemRecord(ledger, record, credits, now) {
|
|
644
|
+
return ledger.map((row)=>{
|
|
645
|
+
var _row_creditsSpent, _row_attemptCredits, _row_creditsRefunded, _record_creditsRefunded, _row_outputs, _record_outputs;
|
|
646
|
+
var _record_degradedBy;
|
|
647
|
+
return row.slot !== record.slot ? row : _extends({}, row, {
|
|
648
|
+
status: record.status,
|
|
649
|
+
creditsSpent: ((_row_creditsSpent = row.creditsSpent) != null ? _row_creditsSpent : 0) + credits,
|
|
650
|
+
attemptCredits: ((_row_attemptCredits = row.attemptCredits) != null ? _row_attemptCredits : 0) + credits,
|
|
651
|
+
creditsRefunded: ((_row_creditsRefunded = row.creditsRefunded) != null ? _row_creditsRefunded : 0) + ((_record_creditsRefunded = record.creditsRefunded) != null ? _record_creditsRefunded : 0)
|
|
652
|
+
}, record.refundKey ? {
|
|
653
|
+
refundKey: record.refundKey
|
|
654
|
+
} : {}, record.failure !== undefined ? {
|
|
655
|
+
failure: record.failure
|
|
656
|
+
} : {}, record.note !== undefined ? {
|
|
657
|
+
note: record.note
|
|
658
|
+
} : {}, ((_record_degradedBy = record.degradedBy) == null ? void 0 : _record_degradedBy.length) ? {
|
|
659
|
+
degradedBy: record.degradedBy
|
|
660
|
+
} : {}, now && record.status !== 'running' && record.status !== 'pending' ? {
|
|
661
|
+
settledAt: now.toISOString()
|
|
662
|
+
} : {}, {
|
|
663
|
+
outputs: [
|
|
664
|
+
...(_row_outputs = row.outputs) != null ? _row_outputs : [],
|
|
665
|
+
...((_record_outputs = record.outputs) != null ? _record_outputs : []).filter((id)=>{
|
|
666
|
+
var _row_outputs;
|
|
667
|
+
return !((_row_outputs = row.outputs) != null ? _row_outputs : []).includes(id);
|
|
668
|
+
})
|
|
669
|
+
]
|
|
670
|
+
});
|
|
671
|
+
});
|
|
672
|
+
}
|
|
625
673
|
/**
|
|
626
674
|
* The runs whose stop reasons a step's record keeps (AGL-3042), newest last.
|
|
627
675
|
* A page job that builds a layout, a form and a component, then five sections
|
|
@@ -679,8 +727,8 @@ function nextStepIndex(job) {
|
|
|
679
727
|
*/ export async function recordStep(firestore, orgId, jobId, owner, stepIndex, input, now = new Date()) {
|
|
680
728
|
const ref = jobsCollection(firestore, orgId).doc(jobId);
|
|
681
729
|
const recorded = await firestore.runTransaction(async (tx)=>{
|
|
682
|
-
var _job_outputs, _input_outputs, _job_creditsSpent, _job_creditsReserved, _job_creditsReserved1;
|
|
683
|
-
var _job_lease;
|
|
730
|
+
var _ref, _input_items, _job_outputs, _input_outputs, _job_creditsSpent, _job_creditsReserved, _job_creditsReserved1, _job_refundedCredits;
|
|
731
|
+
var _job_lease, _input_item;
|
|
684
732
|
const job = jobFrom(await tx.get(ref));
|
|
685
733
|
if (!job) throw new Error(`ai job ${orgId}/${jobId} vanished`);
|
|
686
734
|
const steps = job.steps.map((step, index)=>{
|
|
@@ -698,6 +746,9 @@ function nextStepIndex(job) {
|
|
|
698
746
|
} : {}) : step;
|
|
699
747
|
});
|
|
700
748
|
const remaining = steps.filter((step)=>step.status === 'pending' || step.status === 'running').length;
|
|
749
|
+
// A build's item ledger moves with its spend, in this one write (AGL-3616).
|
|
750
|
+
const ledger = (_ref = (_input_items = input.items) != null ? _input_items : job.items) != null ? _ref : null;
|
|
751
|
+
const items = ledger && input.item ? aiApplyJobItemRecord(ledger, input.item, input.creditsSpent, now) : input.items ? ledger : null;
|
|
701
752
|
const settled = input.status !== 'pending';
|
|
702
753
|
const ownsLease = ((_job_lease = job.lease) == null ? void 0 : _job_lease.owner) === owner;
|
|
703
754
|
const parksForReview = Boolean(input.review) && !isAiJobTerminal(job.status);
|
|
@@ -720,6 +771,10 @@ function nextStepIndex(job) {
|
|
|
720
771
|
plan: input.plan
|
|
721
772
|
} : {}, input.sitePublish ? {
|
|
722
773
|
sitePublish: input.sitePublish
|
|
774
|
+
} : {}, items ? {
|
|
775
|
+
items
|
|
776
|
+
} : {}, ((_input_item = input.item) == null ? void 0 : _input_item.creditsRefunded) ? {
|
|
777
|
+
refundedCredits: ((_job_refundedCredits = job.refundedCredits) != null ? _job_refundedCredits : 0) + input.item.creditsRefunded
|
|
723
778
|
} : {}, parksForReview && input.review ? {
|
|
724
779
|
review: input.review,
|
|
725
780
|
error: input.review.reason === 'plan' ? null : input.review.message
|
|
@@ -903,7 +958,27 @@ async function transition(firestore, orgId, jobId, apply) {
|
|
|
903
958
|
* ended meanwhile — a person's cancel, which pays for what ran — is left as it
|
|
904
959
|
* ended and given nothing back.
|
|
905
960
|
*/ async function failOurFailure(firestore, orgId, jobId, message, detail, refund, now) {
|
|
961
|
+
var _current_items;
|
|
906
962
|
const current = await getAiJob(firestore, orgId, jobId);
|
|
963
|
+
// A build that got as far as its items settles item by item (AGL-3616):
|
|
964
|
+
// what it delivered stands, and what it did not is given back per item.
|
|
965
|
+
if (current && aiJobSettlesByItem(current.kind) && ((_current_items = current.items) == null ? void 0 : _current_items.length) && !isAiJobTerminal(current.status)) {
|
|
966
|
+
var _detail_stepIndex;
|
|
967
|
+
console.error('ai build stopped', {
|
|
968
|
+
orgId,
|
|
969
|
+
jobId,
|
|
970
|
+
stepIndex: (_detail_stepIndex = detail.stepIndex) != null ? _detail_stepIndex : null,
|
|
971
|
+
error: detail.error
|
|
972
|
+
});
|
|
973
|
+
return settleAiBuildJob(firestore, orgId, jobId, {
|
|
974
|
+
now,
|
|
975
|
+
free: refund.free,
|
|
976
|
+
stopped: {
|
|
977
|
+
message,
|
|
978
|
+
reason: refund.reason
|
|
979
|
+
}
|
|
980
|
+
});
|
|
981
|
+
}
|
|
907
982
|
if (current && !isAiJobTerminal(current.status)) {
|
|
908
983
|
await refundOurFailure(firestore, orgId, current, _extends({}, refund, {
|
|
909
984
|
now
|
|
@@ -911,6 +986,256 @@ async function transition(firestore, orgId, jobId, apply) {
|
|
|
911
986
|
}
|
|
912
987
|
return failAiJob(firestore, orgId, jobId, message, detail, now);
|
|
913
988
|
}
|
|
989
|
+
// ── A build's settlement (AGL-3616) ──────────────────────────────────────
|
|
990
|
+
/**
|
|
991
|
+
* The kinds settled item by item (AGL-3616): a build, and a site scaffold,
|
|
992
|
+
* which is the build's preset. Their step writes an item ledger; a failed
|
|
993
|
+
* item gives back its own spend and the rest goes on.
|
|
994
|
+
*/ export function aiJobSettlesByItem(kind) {
|
|
995
|
+
return kind === 'build' || kind === 'site';
|
|
996
|
+
}
|
|
997
|
+
/**
|
|
998
|
+
* Whether Try again may run a job's failed items: a finished build, done or
|
|
999
|
+
* failed; a site scaffold that delivered part of its site — one that built
|
|
1000
|
+
* nothing starts over from its own answers instead.
|
|
1001
|
+
*/ export function aiBuildRetryable(job) {
|
|
1002
|
+
if (job.kind === 'build') return job.status === 'done' || job.status === 'failed';
|
|
1003
|
+
return job.kind === 'site' && job.status === 'done';
|
|
1004
|
+
}
|
|
1005
|
+
/** What a build that delivered nothing says; its planning was given back too. */ export const AI_BUILD_NOTHING_BUILT_COPY = 'Nothing in this request could be built. Try again, or ask for less at once.';
|
|
1006
|
+
/** What an item the build never reached says when the build stopped early. */ export const AI_BUILD_NOT_REACHED_COPY = 'Not built: the build stopped before it reached this.';
|
|
1007
|
+
/**
|
|
1008
|
+
* Gives back one build item's spend, or its planning's (`slot: 'plan'`),
|
|
1009
|
+
* under the item key (job, slot, attempt), so a replayed pass gives back once
|
|
1010
|
+
* and a later attempt is a give-back of its own. The credits given back and
|
|
1011
|
+
* the key, or `null` when nothing was. Never throws.
|
|
1012
|
+
*/ async function refundBuildCredits(firestore, orgId, job, input) {
|
|
1013
|
+
const credits = Math.max(0, Math.floor(input.credits));
|
|
1014
|
+
if (credits <= 0) return null;
|
|
1015
|
+
try {
|
|
1016
|
+
var _data;
|
|
1017
|
+
const free = input.free !== undefined ? input.free : freeAssistAccount((_data = (await firestore.collection('orgs').doc(orgId).get()).data()) != null ? _data : {});
|
|
1018
|
+
const created = toMillis(job.createdAt);
|
|
1019
|
+
const jobDay = assistUsageDay(created === null ? input.now : new Date(created));
|
|
1020
|
+
const refund = await refundJobCredits(firestore, {
|
|
1021
|
+
orgId,
|
|
1022
|
+
free,
|
|
1023
|
+
jobId: job.$id,
|
|
1024
|
+
ordinal: 0,
|
|
1025
|
+
credits,
|
|
1026
|
+
month: assistUsageMonth(input.now),
|
|
1027
|
+
day: assistUsageDay(input.now),
|
|
1028
|
+
reason: input.reason,
|
|
1029
|
+
item: {
|
|
1030
|
+
slot: input.slot,
|
|
1031
|
+
attempt: input.attempt,
|
|
1032
|
+
jobDay
|
|
1033
|
+
}
|
|
1034
|
+
});
|
|
1035
|
+
// A key the month already holds was given back by an earlier run of this pass.
|
|
1036
|
+
if (refund.status !== 'returned' && refund.status !== 'duplicate') return null;
|
|
1037
|
+
return {
|
|
1038
|
+
credits,
|
|
1039
|
+
key: aiJobItemRefundKey({
|
|
1040
|
+
day: jobDay,
|
|
1041
|
+
jobId: job.$id,
|
|
1042
|
+
slot: input.slot,
|
|
1043
|
+
attempt: input.attempt
|
|
1044
|
+
})
|
|
1045
|
+
};
|
|
1046
|
+
} catch (error) {
|
|
1047
|
+
console.error('ai build refund failed', {
|
|
1048
|
+
orgId,
|
|
1049
|
+
jobId: job.$id,
|
|
1050
|
+
slot: input.slot,
|
|
1051
|
+
error
|
|
1052
|
+
});
|
|
1053
|
+
return null;
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
/** What the build's plan step spent: its orchestration. */ function aiBuildPlanCredits(job) {
|
|
1057
|
+
var _ref;
|
|
1058
|
+
var _job_steps_find;
|
|
1059
|
+
return (_ref = (_job_steps_find = job.steps.find((step)=>step.name === AI_JOB_PLAN_STEP)) == null ? void 0 : _job_steps_find.creditsSpent) != null ? _ref : 0;
|
|
1060
|
+
}
|
|
1061
|
+
/**
|
|
1062
|
+
* Ends a build (AGL-3616), once nothing is left to build or the machine
|
|
1063
|
+
* stopped it. A build that STOPPED — a provider failure, its attempts used up
|
|
1064
|
+
* — fails the item it was on and gives back that attempt's spend, and leaves
|
|
1065
|
+
* the items it never reached `skipped`. Then: anything delivered, and its
|
|
1066
|
+
* planning is charged and the job is `done`, failed items and all; nothing
|
|
1067
|
+
* delivered, and its planning is given back too and the job is `failed`.
|
|
1068
|
+
*/ export async function settleAiBuildJob(firestore, orgId, jobId, input) {
|
|
1069
|
+
var _job_items, _job_items1, _job_items2, _ref, _ref1;
|
|
1070
|
+
var _job_orchestration;
|
|
1071
|
+
const { now } = input;
|
|
1072
|
+
let job = await getAiJob(firestore, orgId, jobId);
|
|
1073
|
+
if (!job || isAiJobTerminal(job.status)) return job;
|
|
1074
|
+
const stopped = input.stopped;
|
|
1075
|
+
if (stopped && ((_job_items = job.items) != null ? _job_items : []).some((row)=>row.status === 'pending' || row.status === 'running')) {
|
|
1076
|
+
var _job_items3;
|
|
1077
|
+
const refunds = new Map();
|
|
1078
|
+
for (const row of (_job_items3 = job.items) != null ? _job_items3 : []){
|
|
1079
|
+
var _row_attemptCredits;
|
|
1080
|
+
if (row.status !== 'running') continue;
|
|
1081
|
+
const refund = await refundBuildCredits(firestore, orgId, job, {
|
|
1082
|
+
slot: row.slot,
|
|
1083
|
+
attempt: row.attempt,
|
|
1084
|
+
credits: (_row_attemptCredits = row.attemptCredits) != null ? _row_attemptCredits : 0,
|
|
1085
|
+
reason: stopped.reason,
|
|
1086
|
+
free: input.free,
|
|
1087
|
+
now
|
|
1088
|
+
});
|
|
1089
|
+
if (refund) refunds.set(row.slot, refund);
|
|
1090
|
+
}
|
|
1091
|
+
job = (await transition(firestore, orgId, jobId, (current)=>{
|
|
1092
|
+
var _current_items, _current_refundedCredits;
|
|
1093
|
+
if (isAiJobTerminal(current.status)) return null;
|
|
1094
|
+
let given = 0;
|
|
1095
|
+
const items = ((_current_items = current.items) != null ? _current_items : []).map((row)=>{
|
|
1096
|
+
if (row.status === 'running') {
|
|
1097
|
+
var _ref, _row_creditsRefunded, _ref1;
|
|
1098
|
+
const refund = refunds.get(row.slot);
|
|
1099
|
+
given += (_ref = refund == null ? void 0 : refund.credits) != null ? _ref : 0;
|
|
1100
|
+
return _extends({}, row, {
|
|
1101
|
+
status: 'failed',
|
|
1102
|
+
failure: {
|
|
1103
|
+
ours: true,
|
|
1104
|
+
reason: stopped.reason,
|
|
1105
|
+
message: stopped.message
|
|
1106
|
+
},
|
|
1107
|
+
creditsRefunded: ((_row_creditsRefunded = row.creditsRefunded) != null ? _row_creditsRefunded : 0) + ((_ref1 = refund == null ? void 0 : refund.credits) != null ? _ref1 : 0)
|
|
1108
|
+
}, refund ? {
|
|
1109
|
+
refundKey: refund.key
|
|
1110
|
+
} : {});
|
|
1111
|
+
}
|
|
1112
|
+
return row.status === 'pending' ? _extends({}, row, {
|
|
1113
|
+
status: 'skipped',
|
|
1114
|
+
note: AI_BUILD_NOT_REACHED_COPY
|
|
1115
|
+
}) : row;
|
|
1116
|
+
});
|
|
1117
|
+
return {
|
|
1118
|
+
items,
|
|
1119
|
+
refundedCredits: ((_current_refundedCredits = current.refundedCredits) != null ? _current_refundedCredits : 0) + given,
|
|
1120
|
+
updatedAt: now
|
|
1121
|
+
};
|
|
1122
|
+
})).job;
|
|
1123
|
+
}
|
|
1124
|
+
// A site is delivered when a page is (AGL-3616): a form alone is not a
|
|
1125
|
+
// site. A scaffold that owed no page (a deployment without the page kind)
|
|
1126
|
+
// is delivered by whatever it did build.
|
|
1127
|
+
const sitePages = job.kind === 'site' ? ((_job_items1 = job.items) != null ? _job_items1 : []).filter((row)=>row.op === 'page') : [];
|
|
1128
|
+
const delivered = sitePages.length ? sitePages.some((row)=>row.status === 'succeeded' || row.status === 'degraded') : aiBuildSettlement((_job_items2 = job.items) != null ? _job_items2 : []).delivered;
|
|
1129
|
+
const planCredits = aiBuildPlanCredits(job);
|
|
1130
|
+
if (delivered) {
|
|
1131
|
+
await transition(firestore, orgId, jobId, (current)=>isAiJobTerminal(current.status) ? null : {
|
|
1132
|
+
orchestration: {
|
|
1133
|
+
creditsSpent: planCredits,
|
|
1134
|
+
settled: 'charged'
|
|
1135
|
+
},
|
|
1136
|
+
updatedAt: now
|
|
1137
|
+
});
|
|
1138
|
+
return completeAiJob(firestore, orgId, jobId, now);
|
|
1139
|
+
}
|
|
1140
|
+
// A site that built no page gives back what its other parts cost too: it
|
|
1141
|
+
// was not built, and its Try again starts over from its answers.
|
|
1142
|
+
const parts = new Map();
|
|
1143
|
+
if (job.kind === 'site') {
|
|
1144
|
+
var _job_items4;
|
|
1145
|
+
for (const row of (_job_items4 = job.items) != null ? _job_items4 : []){
|
|
1146
|
+
var _row_creditsSpent, _row_creditsRefunded, _ref2;
|
|
1147
|
+
const owed = Math.max(0, ((_row_creditsSpent = row.creditsSpent) != null ? _row_creditsSpent : 0) - ((_row_creditsRefunded = row.creditsRefunded) != null ? _row_creditsRefunded : 0));
|
|
1148
|
+
if (owed <= 0 || row.status === 'failed') continue;
|
|
1149
|
+
const given = await refundBuildCredits(firestore, orgId, job, {
|
|
1150
|
+
slot: row.slot,
|
|
1151
|
+
attempt: row.attempt,
|
|
1152
|
+
credits: owed,
|
|
1153
|
+
reason: (_ref2 = stopped == null ? void 0 : stopped.reason) != null ? _ref2 : 'step-failure',
|
|
1154
|
+
free: input.free,
|
|
1155
|
+
now
|
|
1156
|
+
});
|
|
1157
|
+
if (given) parts.set(row.slot, given);
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
const refund = ((_job_orchestration = job.orchestration) == null ? void 0 : _job_orchestration.settled) === 'refunded' ? null : await refundBuildCredits(firestore, orgId, job, {
|
|
1161
|
+
slot: 'plan',
|
|
1162
|
+
attempt: 1,
|
|
1163
|
+
credits: planCredits,
|
|
1164
|
+
reason: (_ref = stopped == null ? void 0 : stopped.reason) != null ? _ref : 'step-failure',
|
|
1165
|
+
free: input.free,
|
|
1166
|
+
now
|
|
1167
|
+
});
|
|
1168
|
+
await transition(firestore, orgId, jobId, (current)=>{
|
|
1169
|
+
var _current_refundedCredits, _ref, _ref1, _current_items;
|
|
1170
|
+
var _current_orchestration;
|
|
1171
|
+
return isAiJobTerminal(current.status) ? null : _extends({
|
|
1172
|
+
orchestration: {
|
|
1173
|
+
creditsSpent: planCredits,
|
|
1174
|
+
settled: refund || ((_current_orchestration = current.orchestration) == null ? void 0 : _current_orchestration.settled) === 'refunded' ? 'refunded' : 'charged'
|
|
1175
|
+
}
|
|
1176
|
+
}, refund || parts.size ? {
|
|
1177
|
+
refundedCredits: ((_current_refundedCredits = current.refundedCredits) != null ? _current_refundedCredits : 0) + ((_ref = refund == null ? void 0 : refund.credits) != null ? _ref : 0) + [
|
|
1178
|
+
...parts.values()
|
|
1179
|
+
].reduce((total, part)=>total + part.credits, 0),
|
|
1180
|
+
refundReason: (_ref1 = stopped == null ? void 0 : stopped.reason) != null ? _ref1 : 'step-failure'
|
|
1181
|
+
} : {}, parts.size ? {
|
|
1182
|
+
items: ((_current_items = current.items) != null ? _current_items : []).map((row)=>{
|
|
1183
|
+
var _row_creditsRefunded;
|
|
1184
|
+
const part = parts.get(row.slot);
|
|
1185
|
+
return part ? _extends({}, row, {
|
|
1186
|
+
creditsRefunded: ((_row_creditsRefunded = row.creditsRefunded) != null ? _row_creditsRefunded : 0) + part.credits,
|
|
1187
|
+
refundKey: part.key
|
|
1188
|
+
}) : row;
|
|
1189
|
+
})
|
|
1190
|
+
} : {}, {
|
|
1191
|
+
updatedAt: now
|
|
1192
|
+
});
|
|
1193
|
+
});
|
|
1194
|
+
const nothing = job.kind === 'site' ? AI_SITE_GUIDED_BUILD_FAILED_COPY : AI_BUILD_NOTHING_BUILT_COPY;
|
|
1195
|
+
return failAiJob(firestore, orgId, jobId, (_ref1 = stopped == null ? void 0 : stopped.message) != null ? _ref1 : nothing, {
|
|
1196
|
+
error: 'build delivered nothing'
|
|
1197
|
+
}, now);
|
|
1198
|
+
}
|
|
1199
|
+
/**
|
|
1200
|
+
* Try again on a build (AGL-3616): its failed items back to pending on their
|
|
1201
|
+
* next attempt, with what they left unbuilt (`aiBuildRetryLedger`), and its
|
|
1202
|
+
* generation step queued again. Never re-runs an item that succeeded, never
|
|
1203
|
+
* re-asks the plan. Held at what the retried items are estimated to cost.
|
|
1204
|
+
* `changed: false` for a job that is not a finished build, or has nothing to
|
|
1205
|
+
* try again.
|
|
1206
|
+
*/ export async function retryAiBuildJob(firestore, orgId, jobId, now = new Date()) {
|
|
1207
|
+
let retried = [];
|
|
1208
|
+
const result = await transition(firestore, orgId, jobId, (current)=>{
|
|
1209
|
+
var _current_plan, _current_items;
|
|
1210
|
+
if (!aiBuildRetryable(current)) return null;
|
|
1211
|
+
const plan = ((_current_plan = current.plan) == null ? void 0 : _current_plan.status) === 'confirmed' ? current.plan : null;
|
|
1212
|
+
if (!plan || !((_current_items = current.items) == null ? void 0 : _current_items.length)) return null;
|
|
1213
|
+
const next = aiBuildRetryLedger(current.items, current.kind === 'site' ? aiLedgerUnits(current.items) : aiBuildUnits(plan));
|
|
1214
|
+
if (!next.ledger.some((row)=>row.status === 'pending')) return null;
|
|
1215
|
+
retried = next.retried;
|
|
1216
|
+
return {
|
|
1217
|
+
status: 'queued',
|
|
1218
|
+
items: next.ledger,
|
|
1219
|
+
steps: current.steps.map((step)=>step.name === AI_JOB_PLAN_STEP ? step : _extends({}, step, {
|
|
1220
|
+
status: 'pending',
|
|
1221
|
+
attempts: 0,
|
|
1222
|
+
passes: 0,
|
|
1223
|
+
endedAt: null,
|
|
1224
|
+
error: null
|
|
1225
|
+
})),
|
|
1226
|
+
review: null,
|
|
1227
|
+
error: null,
|
|
1228
|
+
lease: null,
|
|
1229
|
+
creditsReserved: Math.max(AI_JOB_STEP_RESERVE_CREDITS, current.kind === 'site' ? next.retried.length * AI_JOB_STEP_RESERVE_CREDITS : aiBuildCreditEstimate(plan, {
|
|
1230
|
+
slots: new Set(next.retried)
|
|
1231
|
+
})),
|
|
1232
|
+
updatedAt: now
|
|
1233
|
+
};
|
|
1234
|
+
});
|
|
1235
|
+
return _extends({}, result, {
|
|
1236
|
+
retried: result.changed ? retried : []
|
|
1237
|
+
});
|
|
1238
|
+
}
|
|
914
1239
|
/**
|
|
915
1240
|
* Resume a job that stopped for a person (AGL-2935): confirm its plan, or
|
|
916
1241
|
* try again the step whose answer broke a building rule. One transaction,
|
|
@@ -921,9 +1246,9 @@ async function transition(firestore, orgId, jobId, apply) {
|
|
|
921
1246
|
* it queues are held at the nominal figure again, which the park released —
|
|
922
1247
|
* and a confirmed plan is held at what the whole job is estimated to cost
|
|
923
1248
|
* (AGL-3031), creations included, where that is more.
|
|
924
|
-
*/ export async function resumeAiJob(firestore, orgId, jobId, actor, now = new Date()) {
|
|
1249
|
+
*/ export async function resumeAiJob(firestore, orgId, jobId, actor, now = new Date(), options = {}) {
|
|
925
1250
|
return transition(firestore, orgId, jobId, (current)=>{
|
|
926
|
-
var _current_review;
|
|
1251
|
+
var _current_review, _current_inputs;
|
|
927
1252
|
if (current.status !== 'needs_review') return null;
|
|
928
1253
|
const steps = current.steps.map((step)=>step.status === 'pending' ? _extends({}, step, {
|
|
929
1254
|
attempts: 0
|
|
@@ -938,13 +1263,18 @@ async function transition(firestore, orgId, jobId, apply) {
|
|
|
938
1263
|
confirmedBy: actor.uid
|
|
939
1264
|
})
|
|
940
1265
|
} : {};
|
|
1266
|
+
const publish = confirming && current.kind === 'build' && options.publishConfirmed && ((_current_inputs = current.inputs) == null ? void 0 : _current_inputs['publish']) === true ? {
|
|
1267
|
+
inputs: _extends({}, current.inputs, {
|
|
1268
|
+
publishConfirmed: true
|
|
1269
|
+
})
|
|
1270
|
+
} : {};
|
|
941
1271
|
return _extends({
|
|
942
1272
|
status: pending ? 'queued' : 'done',
|
|
943
1273
|
steps,
|
|
944
1274
|
review: null,
|
|
945
1275
|
error: null
|
|
946
|
-
}, confirmed, {
|
|
947
|
-
creditsReserved: pending ? Math.max(outstanding * AI_JOB_STEP_RESERVE_CREDITS, confirming ?
|
|
1276
|
+
}, confirmed, publish, {
|
|
1277
|
+
creditsReserved: pending ? Math.max(outstanding * AI_JOB_STEP_RESERVE_CREDITS, confirming ? aiJobCreditEstimate(current.kind, confirming) : 0) : 0,
|
|
948
1278
|
updatedAt: now
|
|
949
1279
|
});
|
|
950
1280
|
});
|
|
@@ -1048,7 +1378,7 @@ async function transition(firestore, orgId, jobId, apply) {
|
|
|
1048
1378
|
* round.
|
|
1049
1379
|
*/ export async function runAiJobStep(firestore, orgId, jobId, options) {
|
|
1050
1380
|
var _options_now, _step_attempts, _options_org, _data, _ref, _ref1, _outcome_effort, _step_passes, _options_actor;
|
|
1051
|
-
var _reservation_allotment, _reservation_allotment1, _outcome_review;
|
|
1381
|
+
var _reservation_allotment, _reservation_allotment1, _outcome_review, _itemRecord_failure, _recorded_job_items;
|
|
1052
1382
|
const now = (_options_now = options.now) != null ? _options_now : new Date();
|
|
1053
1383
|
// A reservation the caller took before the job existed is a message
|
|
1054
1384
|
// counted against the org; a step that fails before the provider is
|
|
@@ -1390,6 +1720,26 @@ async function transition(firestore, orgId, jobId, apply) {
|
|
|
1390
1720
|
// for a person never continues: the review is what it waits on. The pass
|
|
1391
1721
|
// cap is what stops a runner that never finishes: past it the pass is
|
|
1392
1722
|
// recorded as the step's last, and what it produced stands.
|
|
1723
|
+
// A build item that failed on our side gives back its own attempt's spend
|
|
1724
|
+
// before its row is written (AGL-3616), so the row records what was given.
|
|
1725
|
+
let itemRecord = aiJobSettlesByItem(job.kind) ? outcome.item : undefined;
|
|
1726
|
+
if ((itemRecord == null ? void 0 : itemRecord.status) === 'failed' && ((_itemRecord_failure = itemRecord.failure) == null ? void 0 : _itemRecord_failure.ours)) {
|
|
1727
|
+
var _ref2, _outcome_items, _ref3, _ref4, _reservation_free5;
|
|
1728
|
+
const slot = itemRecord.slot;
|
|
1729
|
+
const row = ((_ref2 = (_outcome_items = outcome.items) != null ? _outcome_items : job.items) != null ? _ref2 : []).find((one)=>one.slot === slot);
|
|
1730
|
+
const refund = await refundBuildCredits(firestore, orgId, job, {
|
|
1731
|
+
slot,
|
|
1732
|
+
attempt: (_ref3 = row == null ? void 0 : row.attempt) != null ? _ref3 : 1,
|
|
1733
|
+
credits: ((_ref4 = row == null ? void 0 : row.attemptCredits) != null ? _ref4 : 0) + credits,
|
|
1734
|
+
reason: itemRecord.failure.reason,
|
|
1735
|
+
free: (_reservation_free5 = reservation.free) != null ? _reservation_free5 : null,
|
|
1736
|
+
now
|
|
1737
|
+
});
|
|
1738
|
+
if (refund) itemRecord = _extends({}, itemRecord, {
|
|
1739
|
+
creditsRefunded: refund.credits,
|
|
1740
|
+
refundKey: refund.key
|
|
1741
|
+
});
|
|
1742
|
+
}
|
|
1393
1743
|
const review = outcome.review;
|
|
1394
1744
|
const continuing = !review && Boolean(outcome.continue) && ((_step_passes = step.passes) != null ? _step_passes : 0) + 1 < aiJobStepMaxPasses(job.kind);
|
|
1395
1745
|
if (!review && outcome.continue && !continuing) {
|
|
@@ -1415,6 +1765,10 @@ async function transition(firestore, orgId, jobId, apply) {
|
|
|
1415
1765
|
review
|
|
1416
1766
|
} : {}, outcome.sitePublish ? {
|
|
1417
1767
|
sitePublish: outcome.sitePublish
|
|
1768
|
+
} : {}, aiJobSettlesByItem(job.kind) && outcome.items ? {
|
|
1769
|
+
items: outcome.items
|
|
1770
|
+
} : {}, itemRecord ? {
|
|
1771
|
+
item: itemRecord
|
|
1418
1772
|
} : {}, review ? {
|
|
1419
1773
|
quiet: true
|
|
1420
1774
|
} : {}), now);
|
|
@@ -1473,7 +1827,7 @@ async function transition(firestore, orgId, jobId, apply) {
|
|
|
1473
1827
|
};
|
|
1474
1828
|
}
|
|
1475
1829
|
if (review && recorded.job.status === 'needs_review') {
|
|
1476
|
-
var
|
|
1830
|
+
var _reservation_free6;
|
|
1477
1831
|
// Nobody parked the job but its own step, so the row names no actor, as
|
|
1478
1832
|
// the meter's park does.
|
|
1479
1833
|
await logAiJobNeedsInput(orgId, {
|
|
@@ -1492,7 +1846,7 @@ async function transition(firestore, orgId, jobId, apply) {
|
|
|
1492
1846
|
const parked = ours ? await refundOurFailure(firestore, orgId, recorded.job, {
|
|
1493
1847
|
reason: ours,
|
|
1494
1848
|
stepCredits: credits,
|
|
1495
|
-
free: (
|
|
1849
|
+
free: (_reservation_free6 = reservation.free) != null ? _reservation_free6 : null,
|
|
1496
1850
|
now
|
|
1497
1851
|
}) : recorded.job;
|
|
1498
1852
|
if (recorded.parked) await announceAiJobTransition(parked, 'needs-review');
|
|
@@ -1507,6 +1861,25 @@ async function transition(firestore, orgId, jobId, apply) {
|
|
|
1507
1861
|
job: recorded.job
|
|
1508
1862
|
};
|
|
1509
1863
|
}
|
|
1864
|
+
// A build ends by its items (AGL-3616): done when anything was delivered.
|
|
1865
|
+
if (aiJobSettlesByItem(job.kind) && step.name !== AI_JOB_PLAN_STEP && ((_recorded_job_items = recorded.job.items) == null ? void 0 : _recorded_job_items.length)) {
|
|
1866
|
+
var _recorded_job_items1, _reservation_free7;
|
|
1867
|
+
// Items still open here are ones the pass cap cut off: the build stopped.
|
|
1868
|
+
const open = aiBuildSettlement((_recorded_job_items1 = recorded.job.items) != null ? _recorded_job_items1 : []).open;
|
|
1869
|
+
const settled = await settleAiBuildJob(firestore, orgId, jobId, _extends({
|
|
1870
|
+
now,
|
|
1871
|
+
free: (_reservation_free7 = reservation.free) != null ? _reservation_free7 : null
|
|
1872
|
+
}, open ? {
|
|
1873
|
+
stopped: {
|
|
1874
|
+
message: AI_UPSTREAM_FAILURE_COPY,
|
|
1875
|
+
reason: 'timeout'
|
|
1876
|
+
}
|
|
1877
|
+
} : {}));
|
|
1878
|
+
return {
|
|
1879
|
+
outcome: settled.status === 'failed' ? 'failed' : 'done',
|
|
1880
|
+
job: settled
|
|
1881
|
+
};
|
|
1882
|
+
}
|
|
1510
1883
|
return {
|
|
1511
1884
|
outcome: 'done',
|
|
1512
1885
|
job: await completeAiJob(firestore, orgId, jobId, now)
|