@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
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
// The POST climbs `aiGateLadder`, whose lockdown rung is the verdict.
|
|
18
18
|
import { randomUUID } from "crypto";
|
|
19
19
|
import { aiJobAdmissionRefusal, aiJobSiteRefusal } from "../jobs/ai-job-admission.js";
|
|
20
|
-
import { AI_JOB_INLINE_BUDGET_MS, aiJobNextStepMinimumMs, aiJobSummary, getAiJob, resumeAiJob, runAiJobStep, writeAiJobAudit } from "../jobs/ai-jobs.js";
|
|
20
|
+
import { AI_JOB_INLINE_BUDGET_MS, aiJobNextStepMinimumMs, aiJobSummary, getAiJob, aiBuildRetryable, resumeAiJob, retryAiBuildJob, runAiJobStep, writeAiJobAudit } from "../jobs/ai-jobs.js";
|
|
21
|
+
import { aiBuildFreeBalanceRefusal, aiBuildFreeTaste } from "../jobs/ai-job-build-step.js";
|
|
22
|
+
import { aiBuildCreditEstimate, aiBuildRetryLedger, aiBuildUnits, aiLedgerUnits } from "../model/ai-build-job.js";
|
|
21
23
|
import { aiGateLadder } from "../runtime/ai-gate.js";
|
|
22
24
|
import { releaseAssistMessage } from "../usage/assist-usage.js";
|
|
23
25
|
/**
|
|
@@ -83,6 +85,31 @@ export async function POST(request, context) {
|
|
|
83
85
|
status: 400
|
|
84
86
|
});
|
|
85
87
|
}
|
|
88
|
+
// Try again on a build (AGL-3616): its failed items and what they left
|
|
89
|
+
// unbuilt, never what succeeded, and never its plan again.
|
|
90
|
+
const retryFailedItems = (payload == null ? void 0 : payload['retry']) === 'failed-items';
|
|
91
|
+
if (retryFailedItems) {
|
|
92
|
+
const refusal = await aiBuildRetryRefusal(gate, existing).catch((error)=>{
|
|
93
|
+
console.error('ai build retry admission failed', {
|
|
94
|
+
orgId: gate.orgId,
|
|
95
|
+
jobId,
|
|
96
|
+
error
|
|
97
|
+
});
|
|
98
|
+
return {
|
|
99
|
+
status: 500,
|
|
100
|
+
error: 'The AI job could not be resumed'
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
if (refusal) {
|
|
104
|
+
await release();
|
|
105
|
+
return Response.json({
|
|
106
|
+
error: refusal.error,
|
|
107
|
+
job: aiJobSummary(existing, new Date())
|
|
108
|
+
}, {
|
|
109
|
+
status: refusal.status
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
86
113
|
// A confirmed plan runs the step that writes, and an allowance free when the
|
|
87
114
|
// job was created may be used by now (AGL-2909): the kind is asked again
|
|
88
115
|
// before anything runs, and a refusal leaves the job waiting for review.
|
|
@@ -129,9 +156,11 @@ export async function POST(request, context) {
|
|
|
129
156
|
}
|
|
130
157
|
}
|
|
131
158
|
const now = new Date();
|
|
132
|
-
const { job, changed } = await resumeAiJob(gate.firestore, gate.orgId, jobId, {
|
|
159
|
+
const { job, changed } = retryFailedItems ? await retryAiBuildJob(gate.firestore, gate.orgId, jobId, now) : await resumeAiJob(gate.firestore, gate.orgId, jobId, {
|
|
133
160
|
uid: gate.uid
|
|
134
|
-
}, now
|
|
161
|
+
}, now, {
|
|
162
|
+
publishConfirmed: (payload == null ? void 0 : payload['publish']) === true
|
|
163
|
+
});
|
|
135
164
|
if (!changed) {
|
|
136
165
|
await release();
|
|
137
166
|
return Response.json({
|
|
@@ -149,7 +178,7 @@ export async function POST(request, context) {
|
|
|
149
178
|
jobId,
|
|
150
179
|
after: {
|
|
151
180
|
status: job.status,
|
|
152
|
-
reason: (_ref1 = (_existing_review = existing.review) == null ? void 0 : _existing_review.reason) != null ? _ref1 : null,
|
|
181
|
+
reason: retryFailedItems ? 'retry-failed-items' : (_ref1 = (_existing_review = existing.review) == null ? void 0 : _existing_review.reason) != null ? _ref1 : null,
|
|
153
182
|
kind: existing.kind
|
|
154
183
|
}
|
|
155
184
|
});
|
|
@@ -203,6 +232,47 @@ export async function POST(request, context) {
|
|
|
203
232
|
status: 200
|
|
204
233
|
});
|
|
205
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* Why a build's Try again cannot run (AGL-3616), or `null`: it is not a
|
|
237
|
+
* finished build, the site switched AI off, or — on the Free taste — the
|
|
238
|
+
* month's Free credits do not cover what the retried items are estimated at.
|
|
239
|
+
*/ async function aiBuildRetryRefusal(gate, job) {
|
|
240
|
+
var _job_hostId;
|
|
241
|
+
var _job_plan, _job_items;
|
|
242
|
+
const plan = ((_job_plan = job.plan) == null ? void 0 : _job_plan.status) === 'confirmed' ? job.plan : null;
|
|
243
|
+
if (!aiBuildRetryable(job) || !plan || !((_job_items = job.items) == null ? void 0 : _job_items.length)) {
|
|
244
|
+
return {
|
|
245
|
+
status: 409,
|
|
246
|
+
error: 'Only a finished build can try its failed items again'
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
const site = await aiJobSiteRefusal({
|
|
250
|
+
firestore: gate.firestore,
|
|
251
|
+
org: gate.org,
|
|
252
|
+
hostId: (_job_hostId = job.hostId) != null ? _job_hostId : null
|
|
253
|
+
});
|
|
254
|
+
if (site) return site;
|
|
255
|
+
const { retried } = aiBuildRetryLedger(job.items, job.kind === 'site' ? aiLedgerUnits(job.items) : aiBuildUnits(plan));
|
|
256
|
+
if (!retried.length) return {
|
|
257
|
+
status: 409,
|
|
258
|
+
error: 'Nothing in this build is left to try again'
|
|
259
|
+
};
|
|
260
|
+
// A site's retried parts are its own pages and creations, held by the
|
|
261
|
+
// reservation each pass takes; a build's are estimated against the Free taste.
|
|
262
|
+
if (job.kind === 'site' || !aiBuildFreeTaste(gate.org)) return null;
|
|
263
|
+
const refusal = await aiBuildFreeBalanceRefusal({
|
|
264
|
+
firestore: gate.firestore,
|
|
265
|
+
org: gate.org,
|
|
266
|
+
estimate: aiBuildCreditEstimate(plan, {
|
|
267
|
+
slots: new Set(retried)
|
|
268
|
+
}),
|
|
269
|
+
now: new Date()
|
|
270
|
+
});
|
|
271
|
+
return refusal ? {
|
|
272
|
+
status: 403,
|
|
273
|
+
error: refusal
|
|
274
|
+
} : null;
|
|
275
|
+
}
|
|
206
276
|
export const dynamic = 'force-dynamic';
|
|
207
277
|
export const maxDuration = 60;
|
|
208
278
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/server/ai-jobs-resume.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\n// lockdown-423: via libs/plugins/ai/src/lib/runtime/ai-gate.ts\n// The POST climbs `aiGateLadder`, whose lockdown rung is the verdict.\n\nimport { randomUUID } from 'crypto'\nimport { aiJobAdmissionRefusal, aiJobSiteRefusal } from '../jobs/ai-job-admission'\nimport {\n AI_JOB_INLINE_BUDGET_MS,\n aiJobNextStepMinimumMs,\n aiJobSummary,\n getAiJob,\n resumeAiJob,\n runAiJobStep,\n writeAiJobAudit,\n} from '../jobs/ai-jobs'\nimport { aiGateLadder } from '../runtime/ai-gate'\nimport { releaseAssistMessage } from '../usage/assist-usage'\n\n/**\n * Resume a job that stopped for a person (AGL-2935): confirm its plan, or\n * try again the step whose answer broke a building rule on its re-ask.\n *\n * A door that SPENDS — the next step calls the provider — so it climbs the\n * whole ladder the create door climbs: `aiGenerative`,\n * `release_ai_generative`, the `ai-generate` switch, `ai.generate` on the\n * job's site, a per-uid window and a reservation. It then runs the next\n * step inline on that reservation, the way the create door runs the first,\n * and hands the reservation back whenever no step runs here.\n *\n * The body names the org and the job's site. A site that is not the job's\n * is refused, so a collaborator's permission on one site never confirms a\n * job on another. Audited per resume that changed something.\n */\n\nconst AI_JOBS_RESUME_RATE_LIMIT = { key: 'ai-jobs-resume', limit: 10, windowMs: 60_000 }\n\nexport async function POST(\n request: Request,\n context: { params: Promise<{ jobId: string }> },\n): Promise<Response> {\n let payload: Record<string, unknown> | null\n try {\n payload = (await request.json()) as Record<string, unknown>\n } catch {\n payload = null\n }\n const rawHost = payload?.['hostId']\n const hostId = typeof rawHost === 'string' && rawHost ? rawHost : null\n const gate = await aiGateLadder(\n { request, orgId: String(payload?.['orgId'] ?? ''), hostId },\n {\n feature: 'aiGenerative',\n releaseFlag: 'release_ai_generative',\n lockdownFeature: 'ai-generate',\n permission: 'ai.generate',\n rateLimit: AI_JOBS_RESUME_RATE_LIMIT,\n },\n )\n if (gate instanceof Response) return gate\n // No token is spent until a step runs, so every exit before one hands the\n // message back.\n const release = () =>\n releaseAssistMessage(gate.firestore, gate.orgId, gate.reservation).catch(() => undefined)\n\n const { jobId } = await context.params\n const existing = await getAiJob(gate.firestore, gate.orgId, jobId)\n if (!existing) {\n await release()\n return Response.json({ error: 'Unknown job' }, { status: 404 })\n }\n if ((existing.hostId ?? null) !== hostId) {\n await release()\n return Response.json({ error: 'That job belongs to another site' }, { status: 400 })\n }\n // A confirmed plan runs the step that writes, and an allowance free when the\n // job was created may be used by now (AGL-2909): the kind is asked again\n // before anything runs, and a refusal leaves the job waiting for review.\n if (existing.status === 'needs_review') {\n let refusal: Awaited<ReturnType<typeof aiJobAdmissionRefusal>>\n try {\n // A site that switched AI off first (AGL-3028), then the kind's own check.\n refusal =\n (await aiJobSiteRefusal({\n firestore: gate.firestore,\n org: gate.org,\n hostId: existing.hostId ?? null,\n })) ??\n (await aiJobAdmissionRefusal(existing.kind, {\n firestore: gate.firestore,\n orgId: gate.orgId,\n hostId: existing.hostId ?? null,\n inputs: existing.inputs ?? {},\n org: gate.org,\n // The plan being confirmed, for a kind that builds only some plans.\n plan: existing.plan ?? null,\n uid: gate.uid,\n }))\n } catch (error) {\n await release()\n console.error('ai job admission failed', { orgId: gate.orgId, jobId, error })\n return Response.json({ error: 'The AI job could not be resumed' }, { status: 500 })\n }\n if (refusal) {\n await release()\n return Response.json(\n { error: refusal.error, job: aiJobSummary(existing, new Date()) },\n { status: refusal.status },\n )\n }\n }\n const now = new Date()\n const { job, changed } = await resumeAiJob(\n gate.firestore,\n gate.orgId,\n jobId,\n { uid: gate.uid },\n now,\n )\n if (!changed) {\n await release()\n return Response.json(\n { error: 'This job is not waiting for review', job: aiJobSummary(job, now) },\n { status: 409 },\n )\n }\n await writeAiJobAudit(gate.firestore, {\n action: 'ai.job.resume',\n actorUid: gate.uid,\n actorEmail: gate.decoded.email ?? null,\n orgId: gate.orgId,\n jobId,\n after: {\n status: job.status,\n reason: existing.review?.reason ?? null,\n kind: existing.kind,\n },\n })\n if (job.status !== 'queued') {\n await release()\n return Response.json({ job: aiJobSummary(job, now) }, { status: 200 })\n }\n // A step that needs more time than this request has (AGL-2907) is left\n // queued for the beat, which starts it with a budget of its own: a provider\n // call this request's timeout cut off would be billed upstream and metered\n // nowhere.\n if (aiJobNextStepMinimumMs(job) > AI_JOB_INLINE_BUDGET_MS) {\n await release()\n return Response.json({ job: aiJobSummary(job, now) }, { status: 200 })\n }\n\n const run = await runAiJobStep(gate.firestore, gate.orgId, jobId, {\n owner: `route:${randomUUID()}`,\n now,\n reservation: gate.reservation,\n org: gate.org,\n signal: AbortSignal.timeout(AI_JOB_INLINE_BUDGET_MS),\n actor: { uid: gate.uid, email: gate.decoded.email ?? null },\n // The workspace's AI pause lets staff through, as the ladder above did.\n staff: gate.staff,\n })\n if (run.outcome === 'not-claimable') {\n // The beat claimed the step between the resume and this run; it runs\n // there, on a reservation of its own.\n await release()\n const latest = await getAiJob(gate.firestore, gate.orgId, jobId)\n return Response.json({ job: aiJobSummary(latest ?? job, now) }, { status: 200 })\n }\n return Response.json({ job: aiJobSummary(run.job) }, { status: 200 })\n}\n\nexport const dynamic = 'force-dynamic'\nexport const maxDuration = 60\n"],"names":["randomUUID","aiJobAdmissionRefusal","aiJobSiteRefusal","AI_JOB_INLINE_BUDGET_MS","aiJobNextStepMinimumMs","aiJobSummary","getAiJob","resumeAiJob","runAiJobStep","writeAiJobAudit","aiGateLadder","releaseAssistMessage","AI_JOBS_RESUME_RATE_LIMIT","key","limit","windowMs","POST","request","context","existing","gate","payload","json","rawHost","hostId","orgId","String","feature","releaseFlag","lockdownFeature","permission","rateLimit","Response","release","firestore","reservation","catch","undefined","jobId","params","error","status","refusal","org","kind","inputs","plan","uid","console","job","Date","now","changed","action","actorUid","actorEmail","decoded","email","after","reason","review","run","owner","signal","AbortSignal","timeout","actor","staff","outcome","latest","dynamic","maxDuration"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/server/ai-jobs-resume.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\n// lockdown-423: via libs/plugins/ai/src/lib/runtime/ai-gate.ts\n// The POST climbs `aiGateLadder`, whose lockdown rung is the verdict.\n\nimport { randomUUID } from 'crypto'\nimport { aiJobAdmissionRefusal, aiJobSiteRefusal } from '../jobs/ai-job-admission'\nimport {\n AI_JOB_INLINE_BUDGET_MS,\n aiJobNextStepMinimumMs,\n aiJobSummary,\n getAiJob,\n aiBuildRetryable,\n resumeAiJob,\n retryAiBuildJob,\n runAiJobStep,\n writeAiJobAudit,\n} from '../jobs/ai-jobs'\nimport type { AiJob } from '../model/ai-jobs.types'\nimport { aiBuildFreeBalanceRefusal, aiBuildFreeTaste } from '../jobs/ai-job-build-step'\nimport { aiBuildCreditEstimate, aiBuildRetryLedger, aiBuildUnits, aiLedgerUnits } from '../model/ai-build-job'\nimport { aiGateLadder } from '../runtime/ai-gate'\nimport { releaseAssistMessage } from '../usage/assist-usage'\n\n/**\n * Resume a job that stopped for a person (AGL-2935): confirm its plan, or\n * try again the step whose answer broke a building rule on its re-ask.\n *\n * A door that SPENDS — the next step calls the provider — so it climbs the\n * whole ladder the create door climbs: `aiGenerative`,\n * `release_ai_generative`, the `ai-generate` switch, `ai.generate` on the\n * job's site, a per-uid window and a reservation. It then runs the next\n * step inline on that reservation, the way the create door runs the first,\n * and hands the reservation back whenever no step runs here.\n *\n * The body names the org and the job's site. A site that is not the job's\n * is refused, so a collaborator's permission on one site never confirms a\n * job on another. Audited per resume that changed something.\n */\n\nconst AI_JOBS_RESUME_RATE_LIMIT = { key: 'ai-jobs-resume', limit: 10, windowMs: 60_000 }\n\nexport async function POST(\n request: Request,\n context: { params: Promise<{ jobId: string }> },\n): Promise<Response> {\n let payload: Record<string, unknown> | null\n try {\n payload = (await request.json()) as Record<string, unknown>\n } catch {\n payload = null\n }\n const rawHost = payload?.['hostId']\n const hostId = typeof rawHost === 'string' && rawHost ? rawHost : null\n const gate = await aiGateLadder(\n { request, orgId: String(payload?.['orgId'] ?? ''), hostId },\n {\n feature: 'aiGenerative',\n releaseFlag: 'release_ai_generative',\n lockdownFeature: 'ai-generate',\n permission: 'ai.generate',\n rateLimit: AI_JOBS_RESUME_RATE_LIMIT,\n },\n )\n if (gate instanceof Response) return gate\n // No token is spent until a step runs, so every exit before one hands the\n // message back.\n const release = () =>\n releaseAssistMessage(gate.firestore, gate.orgId, gate.reservation).catch(() => undefined)\n\n const { jobId } = await context.params\n const existing = await getAiJob(gate.firestore, gate.orgId, jobId)\n if (!existing) {\n await release()\n return Response.json({ error: 'Unknown job' }, { status: 404 })\n }\n if ((existing.hostId ?? null) !== hostId) {\n await release()\n return Response.json({ error: 'That job belongs to another site' }, { status: 400 })\n }\n // Try again on a build (AGL-3616): its failed items and what they left\n // unbuilt, never what succeeded, and never its plan again.\n const retryFailedItems = payload?.['retry'] === 'failed-items'\n if (retryFailedItems) {\n const refusal = await aiBuildRetryRefusal(gate, existing).catch((error: unknown) => {\n console.error('ai build retry admission failed', { orgId: gate.orgId, jobId, error })\n return { status: 500 as const, error: 'The AI job could not be resumed' }\n })\n if (refusal) {\n await release()\n return Response.json({ error: refusal.error, job: aiJobSummary(existing, new Date()) }, { status: refusal.status })\n }\n }\n // A confirmed plan runs the step that writes, and an allowance free when the\n // job was created may be used by now (AGL-2909): the kind is asked again\n // before anything runs, and a refusal leaves the job waiting for review.\n if (existing.status === 'needs_review') {\n let refusal: Awaited<ReturnType<typeof aiJobAdmissionRefusal>>\n try {\n // A site that switched AI off first (AGL-3028), then the kind's own check.\n refusal =\n (await aiJobSiteRefusal({\n firestore: gate.firestore,\n org: gate.org,\n hostId: existing.hostId ?? null,\n })) ??\n (await aiJobAdmissionRefusal(existing.kind, {\n firestore: gate.firestore,\n orgId: gate.orgId,\n hostId: existing.hostId ?? null,\n inputs: existing.inputs ?? {},\n org: gate.org,\n // The plan being confirmed, for a kind that builds only some plans.\n plan: existing.plan ?? null,\n uid: gate.uid,\n }))\n } catch (error) {\n await release()\n console.error('ai job admission failed', { orgId: gate.orgId, jobId, error })\n return Response.json({ error: 'The AI job could not be resumed' }, { status: 500 })\n }\n if (refusal) {\n await release()\n return Response.json(\n { error: refusal.error, job: aiJobSummary(existing, new Date()) },\n { status: refusal.status },\n )\n }\n }\n const now = new Date()\n const { job, changed } = retryFailedItems\n ? await retryAiBuildJob(gate.firestore, gate.orgId, jobId, now)\n : await resumeAiJob(gate.firestore, gate.orgId, jobId, { uid: gate.uid }, now, {\n publishConfirmed: payload?.['publish'] === true,\n })\n if (!changed) {\n await release()\n return Response.json(\n { error: 'This job is not waiting for review', job: aiJobSummary(job, now) },\n { status: 409 },\n )\n }\n await writeAiJobAudit(gate.firestore, {\n action: 'ai.job.resume',\n actorUid: gate.uid,\n actorEmail: gate.decoded.email ?? null,\n orgId: gate.orgId,\n jobId,\n after: {\n status: job.status,\n reason: retryFailedItems ? 'retry-failed-items' : (existing.review?.reason ?? null),\n kind: existing.kind,\n },\n })\n if (job.status !== 'queued') {\n await release()\n return Response.json({ job: aiJobSummary(job, now) }, { status: 200 })\n }\n // A step that needs more time than this request has (AGL-2907) is left\n // queued for the beat, which starts it with a budget of its own: a provider\n // call this request's timeout cut off would be billed upstream and metered\n // nowhere.\n if (aiJobNextStepMinimumMs(job) > AI_JOB_INLINE_BUDGET_MS) {\n await release()\n return Response.json({ job: aiJobSummary(job, now) }, { status: 200 })\n }\n\n const run = await runAiJobStep(gate.firestore, gate.orgId, jobId, {\n owner: `route:${randomUUID()}`,\n now,\n reservation: gate.reservation,\n org: gate.org,\n signal: AbortSignal.timeout(AI_JOB_INLINE_BUDGET_MS),\n actor: { uid: gate.uid, email: gate.decoded.email ?? null },\n // The workspace's AI pause lets staff through, as the ladder above did.\n staff: gate.staff,\n })\n if (run.outcome === 'not-claimable') {\n // The beat claimed the step between the resume and this run; it runs\n // there, on a reservation of its own.\n await release()\n const latest = await getAiJob(gate.firestore, gate.orgId, jobId)\n return Response.json({ job: aiJobSummary(latest ?? job, now) }, { status: 200 })\n }\n return Response.json({ job: aiJobSummary(run.job) }, { status: 200 })\n}\n\n/**\n * Why a build's Try again cannot run (AGL-3616), or `null`: it is not a\n * finished build, the site switched AI off, or — on the Free taste — the\n * month's Free credits do not cover what the retried items are estimated at.\n */\nasync function aiBuildRetryRefusal(\n gate: { firestore: FirebaseFirestore.Firestore; org: object | null },\n job: AiJob,\n): Promise<{ status: 400 | 403 | 404 | 409; error: string } | null> {\n const plan = job.plan?.status === 'confirmed' ? job.plan : null\n if (!aiBuildRetryable(job) || !plan || !job.items?.length) {\n return { status: 409, error: 'Only a finished build can try its failed items again' }\n }\n const site = await aiJobSiteRefusal({ firestore: gate.firestore, org: gate.org, hostId: job.hostId ?? null })\n if (site) return site\n const { retried } = aiBuildRetryLedger(job.items, job.kind === 'site' ? aiLedgerUnits(job.items) : aiBuildUnits(plan))\n if (!retried.length) return { status: 409, error: 'Nothing in this build is left to try again' }\n // A site's retried parts are its own pages and creations, held by the\n // reservation each pass takes; a build's are estimated against the Free taste.\n if (job.kind === 'site' || !aiBuildFreeTaste(gate.org)) return null\n const refusal = await aiBuildFreeBalanceRefusal({\n firestore: gate.firestore,\n org: gate.org,\n estimate: aiBuildCreditEstimate(plan, { slots: new Set(retried) }),\n now: new Date(),\n })\n return refusal ? { status: 403, error: refusal } : null\n}\n\nexport const dynamic = 'force-dynamic'\nexport const maxDuration = 60\n"],"names":["randomUUID","aiJobAdmissionRefusal","aiJobSiteRefusal","AI_JOB_INLINE_BUDGET_MS","aiJobNextStepMinimumMs","aiJobSummary","getAiJob","aiBuildRetryable","resumeAiJob","retryAiBuildJob","runAiJobStep","writeAiJobAudit","aiBuildFreeBalanceRefusal","aiBuildFreeTaste","aiBuildCreditEstimate","aiBuildRetryLedger","aiBuildUnits","aiLedgerUnits","aiGateLadder","releaseAssistMessage","AI_JOBS_RESUME_RATE_LIMIT","key","limit","windowMs","POST","request","context","existing","gate","payload","json","rawHost","hostId","orgId","String","feature","releaseFlag","lockdownFeature","permission","rateLimit","Response","release","firestore","reservation","catch","undefined","jobId","params","error","status","retryFailedItems","refusal","aiBuildRetryRefusal","console","job","Date","org","kind","inputs","plan","uid","now","changed","publishConfirmed","action","actorUid","actorEmail","decoded","email","after","reason","review","run","owner","signal","AbortSignal","timeout","actor","staff","outcome","latest","items","length","site","retried","estimate","slots","Set","dynamic","maxDuration"],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import { type AiImageMode, type AiSvgStyle } from '../providers/image-contract';
|
|
18
|
+
/** What a person reads when a picture failed on our side. */
|
|
19
|
+
export declare const AI_MEDIA_OURS_COPY = "This one's on us \u2014 you weren't charged. The picture didn't come out right; try again, or describe it a little differently.";
|
|
20
|
+
/** What the door answers on a deployment that makes no photos. */
|
|
21
|
+
export declare const AI_MEDIA_NO_PHOTOS_COPY = "Photos aren't available here yet. Choose Illustration to draw one instead.";
|
|
22
|
+
/** Every control character as a space, squeezed, trimmed and cut. */
|
|
23
|
+
export declare function cleanAiImagePrompt(value: unknown): string;
|
|
24
|
+
/**
|
|
25
|
+
* The alt text a picture is stored with: the sentence given, as a sentence,
|
|
26
|
+
* cut at a word inside the library's alt limit. A person edits it like any
|
|
27
|
+
* other.
|
|
28
|
+
*/
|
|
29
|
+
export declare function aiImageAltText(text: string): string;
|
|
30
|
+
/** A file name from the description's first words: `ai-a-red-barn-2.png`. */
|
|
31
|
+
export declare function aiImageFileName(prompt: string, index: number, mimeType: string): string;
|
|
32
|
+
/** What the library asked for, read and bounded. */
|
|
33
|
+
export interface AiMediaImageInput {
|
|
34
|
+
orgId: string;
|
|
35
|
+
library: 'host' | 'org';
|
|
36
|
+
/** The site whose library this is, or the site on screen for the org's. */
|
|
37
|
+
hostId: string | null;
|
|
38
|
+
folderId: string | null;
|
|
39
|
+
mode: AiImageMode;
|
|
40
|
+
prompt: string;
|
|
41
|
+
aspectRatio: string;
|
|
42
|
+
count: number;
|
|
43
|
+
/** An illustration's kind; unread for a photo. */
|
|
44
|
+
style: string;
|
|
45
|
+
/** An illustration's colors: the site theme's, or these. */
|
|
46
|
+
palette: {
|
|
47
|
+
source: 'theme';
|
|
48
|
+
} | {
|
|
49
|
+
source: 'custom';
|
|
50
|
+
colors: string[];
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export declare function parseAiMediaImageInput(body: Record<string, unknown> | null): AiMediaImageInput;
|
|
54
|
+
/** The record a generated picture keeps of how it was made. */
|
|
55
|
+
export interface AiMediaProvenance {
|
|
56
|
+
model: string;
|
|
57
|
+
prompt: string;
|
|
58
|
+
mode: AiImageMode;
|
|
59
|
+
/** An illustration's kind; absent on a photo. */
|
|
60
|
+
style?: AiSvgStyle;
|
|
61
|
+
aspectRatio: string;
|
|
62
|
+
/** The meter's signal id for the request that made it. */
|
|
63
|
+
signalId: string | null;
|
|
64
|
+
generatedBy: string;
|
|
65
|
+
}
|
|
66
|
+
export declare function POST(request: Request): Promise<Response>;
|