@songsid/agend 2.2.1 → 2.2.6
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/dist/agent-cli-instructions.md +5 -2
- package/dist/agent-cli.js +284 -2
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.d.ts +2 -0
- package/dist/agent-endpoint.js +29 -0
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-file-read.d.ts +38 -0
- package/dist/agent-file-read.js +317 -0
- package/dist/agent-file-read.js.map +1 -0
- package/dist/agent-whats-new.d.ts +11 -0
- package/dist/agent-whats-new.js +34 -2
- package/dist/agent-whats-new.js.map +1 -1
- package/dist/atomic-write.js +9 -1
- package/dist/atomic-write.js.map +1 -1
- package/dist/auth-api.d.ts +30 -1
- package/dist/auth-api.js +61 -12
- package/dist/auth-api.js.map +1 -1
- package/dist/authority/authority-state.d.ts +38 -0
- package/dist/authority/authority-state.js +114 -0
- package/dist/authority/authority-state.js.map +1 -0
- package/dist/authority/session-authorizations.d.ts +43 -0
- package/dist/authority/session-authorizations.js +102 -0
- package/dist/authority/session-authorizations.js.map +1 -0
- package/dist/authority/web-authority.d.ts +120 -0
- package/dist/authority/web-authority.js +157 -0
- package/dist/authority/web-authority.js.map +1 -0
- package/dist/backend/antigravity.js +3 -3
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-code.d.ts +2 -2
- package/dist/backend/claude-code.js +10 -5
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/launch-effort.js +1 -1
- package/dist/backend/launch-effort.js.map +1 -1
- package/dist/backend/muse.js +10 -2
- package/dist/backend/muse.js.map +1 -1
- package/dist/backend/types.d.ts +14 -0
- package/dist/backend/types.js +25 -0
- package/dist/backend/types.js.map +1 -1
- package/dist/backend-availability.d.ts +120 -0
- package/dist/backend-availability.js +396 -0
- package/dist/backend-availability.js.map +1 -0
- package/dist/backend-command.d.ts +21 -3
- package/dist/backend-command.js +23 -4
- package/dist/backend-command.js.map +1 -1
- package/dist/bundled-skills.d.ts +14 -0
- package/dist/bundled-skills.js +29 -0
- package/dist/bundled-skills.js.map +1 -0
- package/dist/cache-analysis.d.ts +47 -1
- package/dist/cache-analysis.js +68 -8
- package/dist/cache-analysis.js.map +1 -1
- package/dist/cache-ledger.d.ts +16 -3
- package/dist/cache-ledger.js +33 -13
- package/dist/cache-ledger.js.map +1 -1
- package/dist/cache-report-tool.d.ts +17 -0
- package/dist/cache-report-tool.js +40 -0
- package/dist/cache-report-tool.js.map +1 -0
- package/dist/cache-service.d.ts +70 -3
- package/dist/cache-service.js +178 -17
- package/dist/cache-service.js.map +1 -1
- package/dist/channel/adapters/discord-client-retirement.d.ts +5 -0
- package/dist/channel/adapters/discord-client-retirement.js +57 -0
- package/dist/channel/adapters/discord-client-retirement.js.map +1 -0
- package/dist/channel/adapters/discord.d.ts +11 -0
- package/dist/channel/adapters/discord.js +66 -6
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +8 -1
- package/dist/channel/adapters/telegram.js +74 -4
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/mcp-tools.js +48 -2
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/types.d.ts +21 -0
- package/dist/classic-channel-manager.d.ts +10 -5
- package/dist/classic-channel-manager.js +12 -9
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli.js +142 -110
- package/dist/cli.js.map +1 -1
- package/dist/config-validator.js +119 -4
- package/dist/config-validator.js.map +1 -1
- package/dist/daemon.d.ts +8 -0
- package/dist/daemon.js +298 -22
- package/dist/daemon.js.map +1 -1
- package/dist/decision-list.d.ts +25 -0
- package/dist/decision-list.js +30 -0
- package/dist/decision-list.js.map +1 -0
- package/dist/delivery-outbox.d.ts +10 -0
- package/dist/delivery-outbox.js +12 -1
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/fleet-context.d.ts +15 -0
- package/dist/fleet-manager.d.ts +514 -12
- package/dist/fleet-manager.js +1885 -163
- package/dist/fleet-manager.js.map +1 -1
- package/dist/fleet-process-handlers.d.ts +18 -0
- package/dist/fleet-process-handlers.js +69 -0
- package/dist/fleet-process-handlers.js.map +1 -0
- package/dist/fleet-traffic.d.ts +74 -0
- package/dist/fleet-traffic.js +196 -0
- package/dist/fleet-traffic.js.map +1 -0
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +20 -5
- package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +6 -1
- package/dist/general-knowledge/skills/multi-channel/SKILL.md +3 -2
- package/dist/general-knowledge/skills/persona-emoji/SKILL.md +1 -1
- package/dist/general-knowledge/skills/web-appearance/SKILL.md +492 -0
- package/dist/general-knowledge/skills/web-dashboard/SKILL.md +482 -0
- package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +1 -1
- package/dist/human-delivery-receipts.d.ts +24 -1
- package/dist/human-delivery-receipts.js +64 -11
- package/dist/human-delivery-receipts.js.map +1 -1
- package/dist/instance-avatar.js +3 -0
- package/dist/instance-avatar.js.map +1 -1
- package/dist/instance-config-impact.js +6 -1
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +2 -0
- package/dist/instance-lifecycle.js +20 -10
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instance-names.d.ts +4 -0
- package/dist/instance-names.js +12 -0
- package/dist/instance-names.js.map +1 -0
- package/dist/instructions.d.ts +12 -1
- package/dist/instructions.js +13 -2
- package/dist/instructions.js.map +1 -1
- package/dist/locale.js +118 -10
- package/dist/locale.js.map +1 -1
- package/dist/login-controller.js +35 -2
- package/dist/login-controller.js.map +1 -1
- package/dist/ls-attach-resolve.d.ts +95 -0
- package/dist/ls-attach-resolve.js +174 -0
- package/dist/ls-attach-resolve.js.map +1 -0
- package/dist/memory-hogs.d.ts +27 -0
- package/dist/memory-hogs.js +124 -0
- package/dist/memory-hogs.js.map +1 -0
- package/dist/needs-you-hub.d.ts +4 -0
- package/dist/needs-you-hub.js +31 -6
- package/dist/needs-you-hub.js.map +1 -1
- package/dist/needs-you.d.ts +1 -13
- package/dist/needs-you.js +3 -37
- package/dist/needs-you.js.map +1 -1
- package/dist/outbound-handlers.d.ts +15 -0
- package/dist/outbound-handlers.js +152 -11
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +228 -4
- package/dist/outbound-schemas.js +147 -1
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/public-web-gateway.js +21 -1
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/public-web-link.d.ts +9 -0
- package/dist/public-web-link.js +8 -0
- package/dist/public-web-link.js.map +1 -1
- package/dist/quickstart-api.d.ts +10 -1
- package/dist/quickstart-api.js +12 -4
- package/dist/quickstart-api.js.map +1 -1
- package/dist/reply-buttons-controller.d.ts +4 -0
- package/dist/reply-buttons-controller.js +2 -2
- package/dist/reply-buttons-controller.js.map +1 -1
- package/dist/repo-worktree-guard.d.ts +36 -0
- package/dist/repo-worktree-guard.js +143 -0
- package/dist/repo-worktree-guard.js.map +1 -0
- package/dist/restart-progress.d.ts +65 -1
- package/dist/restart-progress.js +236 -10
- package/dist/restart-progress.js.map +1 -1
- package/dist/rollout-index.d.ts +5 -0
- package/dist/rollout-index.js +26 -5
- package/dist/rollout-index.js.map +1 -1
- package/dist/scheduler/scheduler.d.ts +70 -1
- package/dist/scheduler/scheduler.js +256 -17
- package/dist/scheduler/scheduler.js.map +1 -1
- package/dist/service-installer.d.ts +2 -1
- package/dist/service-installer.js +18 -3
- package/dist/service-installer.js.map +1 -1
- package/dist/settings-api.d.ts +23 -0
- package/dist/settings-api.js +233 -2
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-change.js +112 -0
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-effect.js +32 -2
- package/dist/settings-effect.js.map +1 -1
- package/dist/settings-http-confirmation.js +5 -0
- package/dist/settings-http-confirmation.js.map +1 -1
- package/dist/tmux-manager.d.ts +5 -0
- package/dist/tmux-manager.js +16 -0
- package/dist/tmux-manager.js.map +1 -1
- package/dist/tool-permissions.d.ts +4 -6
- package/dist/tool-permissions.js +100 -2
- package/dist/tool-permissions.js.map +1 -1
- package/dist/topic-commands.d.ts +17 -7
- package/dist/topic-commands.js +39 -21
- package/dist/topic-commands.js.map +1 -1
- package/dist/topic-link.d.ts +128 -0
- package/dist/topic-link.js +269 -0
- package/dist/topic-link.js.map +1 -0
- package/dist/tunnel/cloudflared.js +37 -2
- package/dist/tunnel/cloudflared.js.map +1 -1
- package/dist/tunnel/types.d.ts +3 -1
- package/dist/tunnel/types.js.map +1 -1
- package/dist/types.d.ts +61 -1
- package/dist/ui/app-effects.js +245 -0
- package/dist/ui/chat-ambient.js +307 -0
- package/dist/ui/chat-effect-posters.js +42 -0
- package/dist/ui/chat-effects.js +160 -0
- package/dist/ui/chat-live-replies.js +58 -0
- package/dist/ui/chat-render.js +25 -7
- package/dist/ui/chat-store.js +41 -13
- package/dist/ui/chat-strings.js +86 -2
- package/dist/ui/chat-thread.js +204 -37
- package/dist/ui/chat-tour.js +1 -1
- package/dist/ui/effect-trial-controller.js +124 -0
- package/dist/ui/effect-trial-offer.js +31 -0
- package/dist/ui/effect-trial-panel.js +40 -0
- package/dist/ui/fleet-cache.js +23 -1
- package/dist/ui/fleet-canvas-layout.js +111 -0
- package/dist/ui/fleet-canvas.js +525 -0
- package/dist/ui/fleet-org.js +27 -12
- package/dist/ui/fleet-traffic.js +343 -0
- package/dist/ui/fleet-usage.js +401 -0
- package/dist/ui/image-lightbox.js +1 -1
- package/dist/ui/panel-chat.js +252 -58
- package/dist/ui/panel-details.js +20 -6
- package/dist/ui/panel-fleet.js +45 -19
- package/dist/ui/panel-log.js +6 -6
- package/dist/ui/panel-needs.js +3 -3
- package/dist/ui/panel-settings.js +58 -13
- package/dist/ui/preview-panel.js +25 -9
- package/dist/ui/preview.js +3 -2
- package/dist/ui/settings-appearance.js +349 -0
- package/dist/ui/settings-catalog.js +92 -0
- package/dist/ui/settings-dialogs.js +40 -12
- package/dist/ui/settings-effects.js +202 -0
- package/dist/ui/settings-guests.js +117 -0
- package/dist/ui/settings-learn.js +25 -0
- package/dist/ui/settings-model.js +15 -6
- package/dist/ui/settings-mods.js +271 -0
- package/dist/ui/settings-owner-effects.js +80 -0
- package/dist/ui/settings-strings.js +335 -10
- package/dist/ui/settings-web-authority.js +91 -0
- package/dist/ui/shared/agend-auth.js +28 -4
- package/dist/ui/shared/agent-widget.js +248 -0
- package/dist/ui/shared/app-i18n.js +6 -2
- package/dist/ui/shared/app-prefs.js +34 -13
- package/dist/ui/shared/app-route.js +42 -2
- package/dist/ui/shared/app-session.js +3 -1
- package/dist/ui/shared/app-shell.js +119 -41
- package/dist/ui/shared/app-store.js +28 -1
- package/dist/ui/shared/app-stream.js +14 -7
- package/dist/ui/shared/app-themes.js +206 -0
- package/dist/ui/shared/app.css +566 -5
- package/dist/ui/shared/app.js +23 -10
- package/dist/ui/shared/card-strings.js +32 -0
- package/dist/ui/shared/effect-app-runtime.js +297 -0
- package/dist/ui/shared/effect-baseline.js +64 -0
- package/dist/ui/shared/effect-chat-runtime.js +167 -0
- package/dist/ui/shared/effect-cursor.js +125 -0
- package/dist/ui/shared/effect-frame.js +146 -0
- package/dist/ui/shared/effect-geometry.js +137 -0
- package/dist/ui/shared/effect-host-style.js +10 -0
- package/dist/ui/shared/effect-owner-regions.js +74 -0
- package/dist/ui/shared/effect-owner-source.js +122 -0
- package/dist/ui/shared/effect-policy.js +151 -0
- package/dist/ui/shared/effect-poster-reader.js +98 -0
- package/dist/ui/shared/effect-posters.js +117 -0
- package/dist/ui/shared/effect-profiler.js +184 -0
- package/dist/ui/shared/effect-profiles.js +65 -0
- package/dist/ui/shared/effect-registry.js +543 -0
- package/dist/ui/shared/effect-runtime-loader.js +234 -0
- package/dist/ui/shared/effect-safety.js +153 -0
- package/dist/ui/shared/effect-stock-snapshot.js +43 -0
- package/dist/ui/shared/effect-stock-trust.js +217 -0
- package/dist/ui/shared/effect-trial-shadow.js +62 -0
- package/dist/ui/shared/effect-trial-source.js +103 -0
- package/dist/ui/shared/effect-trial-stage.js +170 -0
- package/dist/ui/shared/effect-trial.css +40 -0
- package/dist/ui/shared/fx-motion.js +67 -0
- package/dist/ui/shared/header-tools.js +1 -1
- package/dist/ui/shared/identity-card.js +273 -0
- package/dist/ui/shared/identity-color.js +261 -0
- package/dist/ui/shared/instance-nav.js +215 -41
- package/dist/ui/shared/owner-css.js +250 -0
- package/dist/ui/shared/owner-effect-prefs.js +117 -0
- package/dist/ui/shared/panel-view.js +103 -10
- package/dist/ui/shared/signin.js +2 -0
- package/dist/ui/shared/tokens.css +9 -3
- package/dist/ui/shared/ui-dialog.js +1 -1
- package/dist/ui/shared/ui-icons.js +3 -0
- package/dist/ui/shared/ui-menu.js +1 -1
- package/dist/ui/shared/ui-toast.js +1 -1
- package/dist/ui/shared/usage-dialog.js +22 -2
- package/dist/ui/shared/view-strings.js +98 -2
- package/dist/ui/shared/web-authorize.js +151 -0
- package/dist/ui/signin.html +1 -0
- package/dist/ui/web-terminal/terminal.css +4 -4
- package/dist/usage/providers.d.ts +28 -0
- package/dist/usage/providers.js +126 -36
- package/dist/usage/providers.js.map +1 -1
- package/dist/usage-report.d.ts +158 -0
- package/dist/usage-report.js +226 -0
- package/dist/usage-report.js.map +1 -0
- package/dist/usage-rollup.d.ts +51 -0
- package/dist/usage-rollup.js +168 -0
- package/dist/usage-rollup.js.map +1 -0
- package/dist/view-api.d.ts +68 -0
- package/dist/view-api.js +249 -8
- package/dist/view-api.js.map +1 -1
- package/dist/web-ambient.d.ts +72 -0
- package/dist/web-ambient.js +161 -0
- package/dist/web-ambient.js.map +1 -0
- package/dist/web-api.d.ts +117 -7
- package/dist/web-api.js +1283 -70
- package/dist/web-api.js.map +1 -1
- package/dist/web-appearance-limits.d.ts +82 -0
- package/dist/web-appearance-limits.js +83 -0
- package/dist/web-appearance-limits.js.map +1 -0
- package/dist/web-appearance-policy.d.ts +64 -0
- package/dist/web-appearance-policy.js +87 -0
- package/dist/web-appearance-policy.js.map +1 -0
- package/dist/web-appearance-tools.d.ts +53 -0
- package/dist/web-appearance-tools.js +124 -0
- package/dist/web-appearance-tools.js.map +1 -0
- package/dist/web-appearance-view.d.ts +124 -0
- package/dist/web-appearance-view.js +278 -0
- package/dist/web-appearance-view.js.map +1 -0
- package/dist/web-appearance.d.ts +93 -0
- package/dist/web-appearance.js +373 -0
- package/dist/web-appearance.js.map +1 -0
- package/dist/web-asset-parts.d.ts +93 -0
- package/dist/web-asset-parts.js +133 -0
- package/dist/web-asset-parts.js.map +1 -0
- package/dist/web-auth.js +20 -2
- package/dist/web-auth.js.map +1 -1
- package/dist/web-card.d.ts +110 -0
- package/dist/web-card.js +266 -0
- package/dist/web-card.js.map +1 -0
- package/dist/web-channel-echo.d.ts +7 -1
- package/dist/web-channel-echo.js +6 -2
- package/dist/web-channel-echo.js.map +1 -1
- package/dist/web-chat-history.d.ts +63 -0
- package/dist/web-chat-history.js +109 -6
- package/dist/web-chat-history.js.map +1 -1
- package/dist/web-commands.d.ts +1 -0
- package/dist/web-effect-bootstrap.d.ts +12 -0
- package/dist/web-effect-bootstrap.js +49 -0
- package/dist/web-effect-bootstrap.js.map +1 -0
- package/dist/web-effect-bundle.d.ts +28 -0
- package/dist/web-effect-bundle.js +171 -0
- package/dist/web-effect-bundle.js.map +1 -0
- package/dist/web-effect-canonical.d.ts +8 -0
- package/dist/web-effect-canonical.js +27 -0
- package/dist/web-effect-canonical.js.map +1 -0
- package/dist/web-effect-library.d.ts +114 -0
- package/dist/web-effect-library.js +530 -0
- package/dist/web-effect-library.js.map +1 -0
- package/dist/web-effect-playback.d.ts +30 -0
- package/dist/web-effect-playback.js +71 -0
- package/dist/web-effect-playback.js.map +1 -0
- package/dist/web-effect-poster.d.ts +8 -0
- package/dist/web-effect-poster.js +52 -0
- package/dist/web-effect-poster.js.map +1 -0
- package/dist/web-effect-profiles.d.ts +118 -0
- package/dist/web-effect-profiles.js +180 -0
- package/dist/web-effect-profiles.js.map +1 -0
- package/dist/web-effect-service.d.ts +93 -0
- package/dist/web-effect-service.js +335 -0
- package/dist/web-effect-service.js.map +1 -0
- package/dist/web-effect-tools.d.ts +48 -0
- package/dist/web-effect-tools.js +129 -0
- package/dist/web-effect-tools.js.map +1 -0
- package/dist/web-effect-trials.d.ts +86 -0
- package/dist/web-effect-trials.js +204 -0
- package/dist/web-effect-trials.js.map +1 -0
- package/dist/web-effect-upload.d.ts +27 -0
- package/dist/web-effect-upload.js +185 -0
- package/dist/web-effect-upload.js.map +1 -0
- package/dist/web-effect-worker.d.ts +8 -0
- package/dist/web-effect-worker.js +170 -0
- package/dist/web-effect-worker.js.map +1 -0
- package/dist/web-effect.d.ts +103 -0
- package/dist/web-effect.js +153 -0
- package/dist/web-effect.js.map +1 -0
- package/dist/web-guest-access.d.ts +125 -0
- package/dist/web-guest-access.js +234 -0
- package/dist/web-guest-access.js.map +1 -0
- package/dist/web-guest-rooms.d.ts +82 -0
- package/dist/web-guest-rooms.js +135 -0
- package/dist/web-guest-rooms.js.map +1 -0
- package/dist/web-identity-color.d.ts +87 -0
- package/dist/web-identity-color.js +209 -0
- package/dist/web-identity-color.js.map +1 -0
- package/dist/web-identity-palette.d.ts +113 -0
- package/dist/web-identity-palette.js +84 -0
- package/dist/web-identity-palette.js.map +1 -0
- package/dist/web-image-meta.d.ts +38 -0
- package/dist/web-image-meta.js +262 -0
- package/dist/web-image-meta.js.map +1 -0
- package/dist/web-login.d.ts +47 -0
- package/dist/web-login.js +115 -0
- package/dist/web-login.js.map +1 -1
- package/dist/web-mod-agent.d.ts +50 -0
- package/dist/web-mod-agent.js +207 -0
- package/dist/web-mod-agent.js.map +1 -0
- package/dist/web-mod-bundle.d.ts +157 -0
- package/dist/web-mod-bundle.js +529 -0
- package/dist/web-mod-bundle.js.map +1 -0
- package/dist/web-mod-export.d.ts +68 -0
- package/dist/web-mod-export.js +100 -0
- package/dist/web-mod-export.js.map +1 -0
- package/dist/web-mod-store.d.ts +289 -0
- package/dist/web-mod-store.js +638 -0
- package/dist/web-mod-store.js.map +1 -0
- package/dist/web-org.d.ts +3 -3
- package/dist/web-org.js +11 -17
- package/dist/web-org.js.map +1 -1
- package/dist/web-owner-css-store.d.ts +222 -0
- package/dist/web-owner-css-store.js +440 -0
- package/dist/web-owner-css-store.js.map +1 -0
- package/dist/web-owner-css.d.ts +58 -0
- package/dist/web-owner-css.js +552 -0
- package/dist/web-owner-css.js.map +1 -0
- package/dist/web-prefs.d.ts +62 -0
- package/dist/web-prefs.js +232 -36
- package/dist/web-prefs.js.map +1 -1
- package/dist/web-preview.d.ts +15 -3
- package/dist/web-preview.js +28 -9
- package/dist/web-preview.js.map +1 -1
- package/dist/web-returning-device.d.ts +41 -0
- package/dist/web-returning-device.js +57 -5
- package/dist/web-returning-device.js.map +1 -1
- package/dist/web-session-authorization.d.ts +132 -0
- package/dist/web-session-authorization.js +193 -0
- package/dist/web-session-authorization.js.map +1 -0
- package/dist/web-session.d.ts +70 -10
- package/dist/web-session.js +137 -22
- package/dist/web-session.js.map +1 -1
- package/dist/web-settings-patch.d.ts +67 -2
- package/dist/web-settings-patch.js +196 -1
- package/dist/web-settings-patch.js.map +1 -1
- package/dist/web-settings-tools.d.ts +89 -0
- package/dist/web-settings-tools.js +273 -0
- package/dist/web-settings-tools.js.map +1 -0
- package/dist/web-shell-routes.d.ts +2 -2
- package/dist/web-shell-routes.js +2 -2
- package/dist/web-shell-routes.js.map +1 -1
- package/dist/web-terminal-http.js +15 -2
- package/dist/web-terminal-http.js.map +1 -1
- package/dist/web-theme-store.d.ts +257 -0
- package/dist/web-theme-store.js +627 -0
- package/dist/web-theme-store.js.map +1 -0
- package/dist/web-theme.d.ts +123 -0
- package/dist/web-theme.js +416 -0
- package/dist/web-theme.js.map +1 -0
- package/dist/web-upload.d.ts +13 -0
- package/dist/web-upload.js +39 -3
- package/dist/web-upload.js.map +1 -1
- package/dist/web-widget.d.ts +72 -0
- package/dist/web-widget.js +245 -0
- package/dist/web-widget.js.map +1 -0
- package/dist/workflow-templates/default.md +1 -1
- package/package.json +1 -1
- package/templates/systemd.service.ejs +8 -0
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
/** #1629 B2: one host-owned Canvas Worker pool. Product adapters are deliberately separate. */
|
|
2
|
+
import { allocateEffectFrames, effectEvent, effectPlaybackReason } from "./effect-policy.js";
|
|
3
|
+
import { createOpaqueEffectFrame } from "./effect-frame.js";
|
|
4
|
+
import { createEffectGeometry, hostEffectRect } from "./effect-geometry.js";
|
|
5
|
+
import { effectStockSnapshot, effectStockAllows, effectStockRefusal } from "./effect-stock-snapshot.js";
|
|
6
|
+
import { effectTrialStage, effectTrialStageIdentity, watchEffectTrialStage } from "./effect-trial-stage.js";
|
|
7
|
+
import { EffectBudget } from "./effect-profiler.js";
|
|
8
|
+
|
|
9
|
+
const registries = new WeakMap();
|
|
10
|
+
const plain = o => !!o && (Object.getPrototypeOf(o) === Object.prototype || Object.getPrototypeOf(o) === null);
|
|
11
|
+
const finite = v => typeof v === "number" && Number.isFinite(v);
|
|
12
|
+
const FLAGS = ["safe", "publicLink", "reducedMotion", "hidden", "enabled", "show", "transportReady", "constrained", "modal"];
|
|
13
|
+
const TYPES = ["state", "reply", "theme"];
|
|
14
|
+
function unsafeSnapshotDescriptor(d) {
|
|
15
|
+
if (!plain(d) || !plain(d.params ?? {})) return null;
|
|
16
|
+
const params = Object.create(null), keys = Object.keys(d.params ?? {}).sort();
|
|
17
|
+
if (keys.length > 16) return null;
|
|
18
|
+
for (const k of keys) {
|
|
19
|
+
const v = d.params[k];
|
|
20
|
+
if (!/^[a-z][a-z0-9_]{0,31}$/.test(k) || !(typeof v === "boolean" || finite(v) || typeof v === "string" && v.length <= 128)) return null;
|
|
21
|
+
params[k] = v;
|
|
22
|
+
}
|
|
23
|
+
const trialIdentity = d.trialStage == null ? null : effectTrialStageIdentity(d.trialStage);
|
|
24
|
+
if (d.trialStage != null && (!trialIdentity || d.region !== "chat" || trialIdentity.key !== d.key || trialIdentity.id !== d.id || trialIdentity.instance !== d.instance || trialIdentity.generation !== d.generation)) return null;
|
|
25
|
+
const out = { trialStage: d.trialStage ?? null, generation: trialIdentity?.generation ?? null, key: d.key, id: d.id, region: d.region, layer: d.layer, by: !trialIdentity && d.by === "human" ? "human" : "agent", order: d.order,
|
|
26
|
+
paused: d.paused, visible: d.visible, instance: d.region === "chat" ? d.instance : null, params, element: d.element };
|
|
27
|
+
const identity = [out.id, out.region, out.layer, out.by, out.instance, params];
|
|
28
|
+
if (trialIdentity) identity.push([trialIdentity.serial, trialIdentity.generation]);
|
|
29
|
+
out.identity = JSON.stringify(identity);
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function snapshotDescriptor(d) { try { return unsafeSnapshotDescriptor(d); } catch { return null; } }
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* `load` is an authenticated, bounded host loader, never a Worker callback. It returns {id,code,params,assets,wants}.
|
|
37
|
+
* Safety is mandatory and synchronous: allowed(id,device), begin({key,id,device}), finish(token,reason), pause(record), resume(id,device). Pause persists a soft latch and history; human resume never clears sticky off.
|
|
38
|
+
* stockSnapshot({frameRoot}) supplies current closed stock paint evidence synchronously; it must not reenter a mutation API.
|
|
39
|
+
* Unknown receipts, roots, trust coverage or gates mount nothing. No storage, network, content or product imports here.
|
|
40
|
+
*/
|
|
41
|
+
export function createEffectRegistry({ window: host, origin, boot, load, safety, stockSnapshot, onChange = () => {}, onProfile = () => {}, onMount = () => {}, onRetire = () => {}, clock = () => host.performance.now() } = {}) {
|
|
42
|
+
try { if (!host?.document || !host.document.body || registries.has(host) || typeof load !== "function" || typeof stockSnapshot !== "function" || typeof onChange !== "function" || typeof onProfile !== "function" || typeof onMount !== "function" || typeof onRetire !== "function" || typeof clock !== "function" || !safety || ["allowed", "begin", "finish", "pause", "resume"].some(k => typeof safety[k] !== "function") || ["requestAnimationFrame", "cancelAnimationFrame", "setTimeout", "clearTimeout", "MutationObserver", "ResizeObserver", "AbortController"].some(k => typeof host[k] !== "function")) return { ok: false, reason: "registry_unsupported" }; } catch { return { ok: false, reason: "registry_unsupported" }; }
|
|
43
|
+
let dead = false, blocked = null, revision = 0, last = null, lastView = null, frameSerial = 0, context = null, descriptors = [], raf = null, timer = null;
|
|
44
|
+
const slots = new Map(), loads = new Set(), paused = new Map(), offs = [], observed = new Set(), failures = new Map(), results = new Map();
|
|
45
|
+
let readingStock = false, stockFailure = "stock_evidence_invalid", warned = null;
|
|
46
|
+
let root, geometry, observer, resize, longTasks = null, longTasksSupported = false;
|
|
47
|
+
const time = () => {
|
|
48
|
+
let n; try { n = clock(); } catch { return null; }
|
|
49
|
+
if (!finite(n) || n < 0 || last !== null && n < last) return null;
|
|
50
|
+
last = n; return n;
|
|
51
|
+
};
|
|
52
|
+
const nativeClock = () => { const n = time(); if (n === null) throw Error("clock unavailable"); return n; };
|
|
53
|
+
const device = () => context?.constrained === true ? "constrained" : "standard";
|
|
54
|
+
const dpr = device => Math.min(device === "constrained" ? 1.5 : 3, Math.max(0.5, host.devicePixelRatio || 1));
|
|
55
|
+
// The provider is synchronous and observational. Reentrant mutation revokes this pool, rather than
|
|
56
|
+
// allowing an old admission to act on newer descriptors or scheduling unbounded callback retries.
|
|
57
|
+
const readingStages = new Set();
|
|
58
|
+
// A local receipt may synchronously invalidate and notify its owner. Fence its result by revision;
|
|
59
|
+
// recursion on the same receipt is unknown, while an independently issued replacement may proceed.
|
|
60
|
+
const localStage = (d, proof) => {
|
|
61
|
+
if (!d?.trialStage || dead || blocked || readingStages.has(d.trialStage)) return null;
|
|
62
|
+
const before = revision; let stage = null; readingStages.add(d.trialStage);
|
|
63
|
+
try { stage = effectTrialStage(d.trialStage, d, proof); } catch { /* unknown is never permission */ }
|
|
64
|
+
finally { readingStages.delete(d.trialStage); }
|
|
65
|
+
return !dead && !blocked && revision === before && stage?.root === d.element ? stage : null;
|
|
66
|
+
};
|
|
67
|
+
const permits = (d, proof) => eligible(d) && (d.trialStage ? !!localStage(d, proof) : effectStockAllows(proof, d));
|
|
68
|
+
const coverage = (d = null) => {
|
|
69
|
+
if (dead || blocked || readingStock) return null;
|
|
70
|
+
const before = revision; let proof = null; readingStock = true;
|
|
71
|
+
let failure = "stock_provider_failed";
|
|
72
|
+
try { const raw = stockSnapshot(Object.freeze({ frameRoot: root })); proof = effectStockSnapshot(raw); failure = proof ? null : effectStockRefusal(raw); }
|
|
73
|
+
catch { /* unavailable stays denied, with a local diagnostic */ }
|
|
74
|
+
finally { readingStock = false; }
|
|
75
|
+
if (dead || blocked || before !== revision) return null;
|
|
76
|
+
stockFailure = failure;
|
|
77
|
+
if (failure !== warned) { warned = failure; if (failure) { try { host.console?.warn("[AgEnD effects] Playback blocked:", failure); } catch { /* display only */ } } }
|
|
78
|
+
if (dead || blocked || before !== revision) return null;
|
|
79
|
+
return d === null || permits(d, proof) ? proof : null;
|
|
80
|
+
};
|
|
81
|
+
const position = (d, proof) => d.trialStage ? localStage(d, proof)?.rect ?? null : hostEffectRect(d.element);
|
|
82
|
+
const syncGeometry = (s, proof) => {
|
|
83
|
+
const before = revision, rect = position(s.d, proof);
|
|
84
|
+
if (!rect || !current(s) || before !== revision) return null;
|
|
85
|
+
const ok = s.d.trialStage ? s.geometry.sync(proof) : s.geometry.sync(rect, proof);
|
|
86
|
+
return ok && current(s) && before === revision ? rect : null;
|
|
87
|
+
};
|
|
88
|
+
const hideGeometry = () => { geometry?.hide(); for (const s of slots.values()) if (s.d.trialStage) s.geometry?.hide(); };
|
|
89
|
+
function reentrantStock() {
|
|
90
|
+
if (!readingStock) return false;
|
|
91
|
+
if (blocked) return true;
|
|
92
|
+
revision++; blocked = "stock_reentrant"; hideGeometry(); stopAll(blocked); tell(); return true;
|
|
93
|
+
}
|
|
94
|
+
const current = s => !dead && !blocked && slots.get(s.d.key) === s && s.live;
|
|
95
|
+
const tell = () => { if (dead) return; const state = view(), stamp = JSON.stringify(state); if (stamp === lastView) return; lastView = stamp; try { onChange(state); } catch { /* a display callback cannot admit code */ } };
|
|
96
|
+
const receipt = (fn, ...args) => { try { return Reflect.apply(fn, safety, args); } catch { return null; } };
|
|
97
|
+
// #2055: the history's own read names a denial; any other answer stays unknown (and denied).
|
|
98
|
+
const SAFETY_REASON = Object.freeze({ __proto__: null, off: "safety_off", paused: "paused", interrupted: "interrupted" });
|
|
99
|
+
// Display only: the sticky history state per descriptor, which outranks a waiting reason (a queue, a dialog, typing)
|
|
100
|
+
// because it is what Resume must answer. Admission, caps, latches and safety policy never read it.
|
|
101
|
+
const named = new Map();
|
|
102
|
+
// The read can re-enter (an update from a callback): only a pass still current, for the same device, may write.
|
|
103
|
+
const nameSafety = (d, dev = device()) => {
|
|
104
|
+
const proposed = revision;
|
|
105
|
+
const reason = d.trialStage ? null : SAFETY_REASON[receipt(safety.status, d.id, dev)?.state];
|
|
106
|
+
if (dead || proposed !== revision || dev !== device()) return false;
|
|
107
|
+
if (reason) named.set(d.key, { identity: signature(d), reason }); else named.delete(d.key);
|
|
108
|
+
return true;
|
|
109
|
+
};
|
|
110
|
+
// Display only: the closed global gate a row is waiting on, when the host knows it (else the caller's unknown).
|
|
111
|
+
const gateReason = () => effectPlaybackReason(context);
|
|
112
|
+
const clearMarker = (s, why) => {
|
|
113
|
+
if (!s.token) return true;
|
|
114
|
+
const token = s.token; s.token = null;
|
|
115
|
+
if (receipt(safety.finish, token, why) === true) return true;
|
|
116
|
+
blocked = "safety_unknown"; return false;
|
|
117
|
+
};
|
|
118
|
+
function retire(s, why, count = false) {
|
|
119
|
+
if (!s.live) return;
|
|
120
|
+
s.live = false;
|
|
121
|
+
if (slots.get(s.d.key) === s) slots.delete(s.d.key);
|
|
122
|
+
if (s.request) { s.request.controller.abort(); if (s.request.timer !== null) host.clearTimeout(s.request.timer); }
|
|
123
|
+
// A closed/unknown viewer gate revokes paint, not the effect identity. Fresh known gates
|
|
124
|
+
// may admit it again; resource failures and actual safety pauses retain their latches.
|
|
125
|
+
if (!["disposed", "superseded", "hidden", "human_resume", "geometry_changed", "gates_unknown"].includes(why)) failures.set(s.d.key, { identity: signature(s.d), reason: why });
|
|
126
|
+
s.stageOff?.(); s.stageOff = null;
|
|
127
|
+
s.frame?.remove(why); s.geometry?.remove();
|
|
128
|
+
if (s.loadOff) s.loadOff();
|
|
129
|
+
if (count) {
|
|
130
|
+
paused.set(s.d.key, signature(s.d));
|
|
131
|
+
if (receipt(safety.pause, { id: s.d.id, device: s.device, reason: why, metrics: s.budget?.snapshot().metrics ?? null }) !== true) blocked = "safety_unknown";
|
|
132
|
+
}
|
|
133
|
+
if (count || why === "safety_revoked") nameSafety(s.d, s.device); // #2055: the third pause, or another tab's, says off now
|
|
134
|
+
clearMarker(s, why);
|
|
135
|
+
if (s.owner) { try { onRetire(s.owner, why); } catch { /* an observation cannot prevent physical cleanup */ } }
|
|
136
|
+
if (blocked) for (const other of [...slots.values()]) retire(other, blocked);
|
|
137
|
+
}
|
|
138
|
+
function stopAll(why) {
|
|
139
|
+
const proposed = revision, wasDead = dead;
|
|
140
|
+
for (const s of [...slots.values()]) {
|
|
141
|
+
retire(s, why);
|
|
142
|
+
if (revision !== proposed || dead !== wasDead) return false;
|
|
143
|
+
}
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
function gatesKnown() { return context && FLAGS.every(k => typeof context[k] === "boolean") && (context.openInstance === null || typeof context.openInstance === "string" && context.openInstance.length >= 1 && context.openInstance.length <= 128); }
|
|
147
|
+
function eligible(d = null) {
|
|
148
|
+
return gatesKnown() && !context.safe && !context.reducedMotion && context.enabled && context.show && context.transportReady
|
|
149
|
+
&& (!d || !context.publicLink || d.region === "chat" && !d.trialStage);
|
|
150
|
+
}
|
|
151
|
+
const globalAllowed = (d = null) => eligible(d) && host.document.visibilityState === "visible";
|
|
152
|
+
const signature = d => d.identity;
|
|
153
|
+
// A frame stopped because its gates closed is recorded as gates_unknown; when the host knows which gate, say it.
|
|
154
|
+
const shown = why => (why === "gates_unknown" && !eligible() && gateReason()) || why;
|
|
155
|
+
function view() {
|
|
156
|
+
return descriptors.map(d => {
|
|
157
|
+
const r = results.get(d.key) ?? { verdict: "off", reason: blocked ?? (eligible() ? stockFailure : gateReason()) ?? "runtime_unavailable", queuePos: null }, s = slots.get(d.key);
|
|
158
|
+
// #2055 one display precedence: a global latch, then the sticky safety history, then this page's own pause/failure.
|
|
159
|
+
const n = named.get(d.key), sticky = n && n.identity === signature(d) ? n.reason : null;
|
|
160
|
+
return { key: d.key, id: d.id, ...r, ...(sticky && r.verdict === "queued" ? { verdict: "off", queuePos: null } : {}), phase: s?.frame ? s.ready ? "running" : "starting" : s ? "loading" : null,
|
|
161
|
+
quality: s?.budget?.snapshot().quality ?? null, reason: blocked ?? sticky ?? ((paused.get(d.key) === signature(d)) ? "paused" : failures.get(d.key)?.identity === signature(d) ? shown(failures.get(d.key).reason) : s && context?.hidden ? "hidden" : r.reason) };
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
function schedule() {
|
|
165
|
+
if (dead || blocked || !slots.size) return;
|
|
166
|
+
if (raf === null && host.document.visibilityState === "visible" && context?.hidden === false) raf = host.requestAnimationFrame(tick);
|
|
167
|
+
if (timer === null) {
|
|
168
|
+
const waits = [...slots.values()].filter(s => s.hiddenSince !== null).map(s => Math.max(1, 10000 - (last - s.hiddenSince)));
|
|
169
|
+
timer = host.setTimeout(heartbeat, Math.min(1000, ...waits));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const invalidate = () => {
|
|
173
|
+
if (dead || reentrantStock()) return;
|
|
174
|
+
hideGeometry(); for (const s of slots.values()) s.pointer = null;
|
|
175
|
+
if (time() === null) { blocked = "clock_unavailable"; stopAll(blocked); tell(); return; }
|
|
176
|
+
reconcile();
|
|
177
|
+
};
|
|
178
|
+
function observe() {
|
|
179
|
+
const nodes = host.document.querySelectorAll("[data-trust]");
|
|
180
|
+
if (nodes.length > 4096) throw Error("trust coverage unavailable");
|
|
181
|
+
const wanted = new Set([host.document.documentElement, ...nodes]);
|
|
182
|
+
for (const d of descriptors) if (d.element?.ownerDocument === host.document && d.element.isConnected === true) wanted.add(d.element);
|
|
183
|
+
for (const n of observed) if (!wanted.has(n)) { resize.unobserve(n); observed.delete(n); }
|
|
184
|
+
for (const n of wanted) if (!observed.has(n)) { resize.observe(n); observed.add(n); }
|
|
185
|
+
|
|
186
|
+
}
|
|
187
|
+
function reconcile() {
|
|
188
|
+
if (dead || reentrantStock()) return;
|
|
189
|
+
const proposal = revision;
|
|
190
|
+
if (time() === null) blocked = "clock_unavailable";
|
|
191
|
+
const hidden = context?.hidden === true || host.document.visibilityState !== "visible";
|
|
192
|
+
// #2188: nothing to place, nothing to prove — the stock walk (thousands of computed styles) is not run for an empty
|
|
193
|
+
// list; a frame still held is retired as superseded, exactly as an allocation of nothing would.
|
|
194
|
+
if (!blocked && descriptors.length === 0) {
|
|
195
|
+
for (const s of [...slots.values()]) { retire(s, "superseded"); if (dead || proposal !== revision) return; }
|
|
196
|
+
results.clear(); tell(); return;
|
|
197
|
+
}
|
|
198
|
+
const stock = eligible() ? coverage() : null;
|
|
199
|
+
if (dead || proposal !== revision) return;
|
|
200
|
+
if (blocked || !eligible() || !stock) {
|
|
201
|
+
if (!stopAll(blocked ?? "gates_unknown")) return;
|
|
202
|
+
results.clear();
|
|
203
|
+
if (!blocked) for (const d of descriptors) if (!nameSafety(d) || dead || proposal !== revision) return;
|
|
204
|
+
tell(); return;
|
|
205
|
+
}
|
|
206
|
+
// Hidden frames already owned may survive for <=10 s, but no new frame or load is admitted while hidden.
|
|
207
|
+
const ctx = { ...context, hidden: false };
|
|
208
|
+
const ds = [];
|
|
209
|
+
for (const d of descriptors) {
|
|
210
|
+
if (dead || proposal !== revision) return;
|
|
211
|
+
const allowed = permits(d, stock);
|
|
212
|
+
if (dead || proposal !== revision) return;
|
|
213
|
+
ds.push({ ...d, paused: !allowed || d.paused === true || paused.get(d.key) === signature(d) || failures.get(d.key)?.identity === signature(d) });
|
|
214
|
+
}
|
|
215
|
+
for (const d of descriptors) if (!nameSafety(d) || dead || proposal !== revision) return;
|
|
216
|
+
const allocation = allocateEffectFrames(ds, ctx); results.clear();
|
|
217
|
+
for (const r of allocation) {
|
|
218
|
+
const d = descriptors.find(d => d.key === r.key);
|
|
219
|
+
if (r.reason === "paused" && d && d.paused !== true && paused.get(d.key) !== signature(d) && failures.get(d.key)?.identity !== signature(d)) {
|
|
220
|
+
const allowed = permits(d, stock);
|
|
221
|
+
if (dead || proposal !== revision) return;
|
|
222
|
+
if (!allowed) r.reason = d.trialStage ? "trial_ended" : stock.front ? "owner_css" : "stock_overlay";
|
|
223
|
+
}
|
|
224
|
+
results.set(r.key, r);
|
|
225
|
+
}
|
|
226
|
+
if (dead || proposal !== revision) return;
|
|
227
|
+
const chosen = new Set(allocation.filter(r => r.verdict === "active").map(r => r.key));
|
|
228
|
+
for (const s of [...slots.values()]) {
|
|
229
|
+
const d = descriptors.find(x => x.key === s.d.key);
|
|
230
|
+
if (!chosen.has(s.d.key) || !d || signature(d) !== signature(s.d) || d.element !== s.d.element || s.device !== device()) retire(s, "superseded");
|
|
231
|
+
if (dead || proposal !== revision) return;
|
|
232
|
+
}
|
|
233
|
+
if (chosen.size === 0) { tell(); return; }
|
|
234
|
+
if (hidden) {
|
|
235
|
+
hideGeometry();
|
|
236
|
+
for (const s of [...slots.values()]) {
|
|
237
|
+
if (!s.frame) retire(s, "hidden");
|
|
238
|
+
else { if (s.hiddenSince === null) { s.hiddenSince = last; s.healthySince = null; } if (s.budget.gates({ hidden: true, reducedMotion: false, saveData: false, show: true }).remove) retire(s, "hidden"); }
|
|
239
|
+
if (dead || proposal !== revision) return;
|
|
240
|
+
}
|
|
241
|
+
schedule(); tell(); return;
|
|
242
|
+
}
|
|
243
|
+
if (!globalAllowed()) { stopAll("gates_unknown"); tell(); return; }
|
|
244
|
+
for (const s of [...slots.values()]) {
|
|
245
|
+
if (s.frame && s.hiddenSince !== null) { s.hiddenSince = null; s.healthySince = last; if (s.budget.gates({ hidden: false, reducedMotion: false, saveData: false, show: true }).remove) retire(s, "hidden"); }
|
|
246
|
+
if (dead || proposal !== revision) return;
|
|
247
|
+
}
|
|
248
|
+
try { observe(); } catch {
|
|
249
|
+
if (dead || proposal !== revision || !stopAll("trust_geometry_unknown")) return;
|
|
250
|
+
for (const d of descriptors) results.set(d.key, { verdict: "off", reason: "trust_geometry_unknown", queuePos: null });
|
|
251
|
+
tell(); return;
|
|
252
|
+
}
|
|
253
|
+
const max = context.constrained ? 1 : 3;
|
|
254
|
+
for (const d of descriptors) {
|
|
255
|
+
if (!chosen.has(d.key) || slots.has(d.key)) continue;
|
|
256
|
+
if (slots.size >= max || loads.size >= max) break;
|
|
257
|
+
const permitted = receipt(safety.allowed, d.id, device());
|
|
258
|
+
if (proposal !== revision) return;
|
|
259
|
+
if (permitted !== true) {
|
|
260
|
+
// #2055: say which denial it is. Only the safety history's own read names it; anything else stays unknown (still denied).
|
|
261
|
+
const st = receipt(safety.status, d.id, device());
|
|
262
|
+
if (proposal !== revision) return;
|
|
263
|
+
const why = SAFETY_REASON[st?.state] ?? "safety_unknown";
|
|
264
|
+
results.set(d.key, { verdict: "off", reason: why, queuePos: null }); continue;
|
|
265
|
+
}
|
|
266
|
+
if (slots.has(d.key) || slots.size >= max || loads.size >= max || !globalAllowed(d) || context.hidden || !coverage(d) || proposal !== revision || !descriptors.some(x => x.key === d.key && signature(x) === signature(d) && x.element === d.element)) break;
|
|
267
|
+
const rect = position(d, coverage(d));
|
|
268
|
+
if (dead || proposal !== revision) return;
|
|
269
|
+
if (!rect || d.element.ownerDocument !== host.document) { results.set(d.key, { verdict: "off", reason: "geometry_unknown", queuePos: null }); continue; }
|
|
270
|
+
const s = { d, device: device(), owner: null, live: true, stageOff: null, ready: false, readyAt: null, frame: null, geometry: null, budget: null, token: null, request: null, loadOff: null, rect: null, pointer: null, lastPointer: null, hiddenSince: null, healthySince: null };
|
|
271
|
+
slots.set(d.key, s);
|
|
272
|
+
if (d.trialStage) {
|
|
273
|
+
s.stageOff = watchEffectTrialStage(d.trialStage, () => {
|
|
274
|
+
if (!current(s)) return;
|
|
275
|
+
const before = revision; retire(s, "trial_ended");
|
|
276
|
+
if (!dead && before === revision) { reconcile(); tell(); }
|
|
277
|
+
});
|
|
278
|
+
if (!s.stageOff || !current(s)) { retire(s, "trial_ended"); continue; }
|
|
279
|
+
}
|
|
280
|
+
const request = { controller: new host.AbortController(), slot: s, timer: null, began: time() }; s.request = request; loads.add(request);
|
|
281
|
+
const withinDeadline = () => {
|
|
282
|
+
const n = time();
|
|
283
|
+
if (n === null || request.began === null || n - request.began >= 10000) { retire(s, n === null || request.began === null ? "clock_unavailable" : "resource_timeout"); return false; }
|
|
284
|
+
return true;
|
|
285
|
+
};
|
|
286
|
+
const acceptCompletion = () => {
|
|
287
|
+
if (!current(s)) { clearMarker(s, "superseded"); return false; }
|
|
288
|
+
if (!withinDeadline()) return false;
|
|
289
|
+
if (request.controller.signal.aborted || !globalAllowed(d) || context.hidden || !coverage(d)) {
|
|
290
|
+
if (current(s)) retire(s, "admission_revoked"); else clearMarker(s, "superseded");
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
return withinDeadline();
|
|
294
|
+
};
|
|
295
|
+
const deadline = () => {
|
|
296
|
+
if (!current(s)) return;
|
|
297
|
+
const n = time();
|
|
298
|
+
if (n === null || n - request.began >= 10000) { retire(s, n === null ? "clock_unavailable" : "resource_timeout"); tell(); return; }
|
|
299
|
+
request.timer = host.setTimeout(deadline, Math.max(1, 10000 - (n - request.began)));
|
|
300
|
+
};
|
|
301
|
+
request.timer = host.setTimeout(deadline, 10000);
|
|
302
|
+
// Keep a physical read reservation until its promise settles, including after abort/revocation.
|
|
303
|
+
Promise.resolve().then(() => {
|
|
304
|
+
if (!current(s) || request.controller.signal.aborted) return null;
|
|
305
|
+
return load({ key: d.key, id: d.id, params: { ...d.params } }, request.controller.signal);
|
|
306
|
+
}).then(resource => {
|
|
307
|
+
if (!acceptCompletion()) return;
|
|
308
|
+
if (!plain(resource) || resource.id !== d.id || !plain(resource.params) || Object.keys(d.params).some(k => resource.params[k] !== d.params[k])) { retire(s, "resource_unknown"); return; }
|
|
309
|
+
let fresh = position(d, coverage(d));
|
|
310
|
+
if (!fresh || receipt(safety.allowed, d.id, s.device) !== true) { retire(s, "safety_unknown"); return; }
|
|
311
|
+
if (!acceptCompletion()) return;
|
|
312
|
+
const token = receipt(safety.begin, { key: d.key, id: d.id, device: s.device });
|
|
313
|
+
if (typeof token !== "string" || token.length < 1 || token.length > 128) { retire(s, "safety_unknown"); return; }
|
|
314
|
+
s.token = token;
|
|
315
|
+
if (!acceptCompletion()) return;
|
|
316
|
+
// Obtain local geometry BEFORE the factory appends its temporarily unknown iframe. bind() is
|
|
317
|
+
// the very next local-stage operation and registers that frame before checking its topology.
|
|
318
|
+
const local = d.trialStage ? localStage(d, coverage(d)) : null;
|
|
319
|
+
if (d.trialStage && !local || !current(s)) { if (current(s)) retire(s, "admission_revoked"); return; }
|
|
320
|
+
if (local) fresh = local.rect;
|
|
321
|
+
s.rect = fresh;
|
|
322
|
+
s.budget = new EffectBudget({ device: s.device, clock: nativeClock, longTasksSupported });
|
|
323
|
+
const frame = createOpaqueEffectFrame({ window: host, root: local?.root ?? root, origin, boot, clock: nativeClock,
|
|
324
|
+
render: { code: resource.code, params: resource.params, assets: resource.assets, wants: resource.wants, instance: d.instance, width: fresh.width, height: fresh.height, dpr: dpr(s.device) },
|
|
325
|
+
onReady() { if (!current(s)) return; if (!globalAllowed(d) || context.hidden || !coverage(d)) { retire(s, "hidden"); tell(); return; } const n = time(); if (n === null) { blocked = "clock_unavailable"; stopAll(blocked); tell(); return; } s.ready = true; s.readyAt = n; s.healthySince = n; publishEnv(s); schedule(); tell(); },
|
|
326
|
+
onRemove(why) { if (current(s)) { retire(s, why); tell(); } },
|
|
327
|
+
});
|
|
328
|
+
s.frame = frame;
|
|
329
|
+
if (!current(s) || !frame.ok || frame.state().removed) { frame.remove?.("stale_mount"); retire(s, "mount_failed"); return; }
|
|
330
|
+
frame.element.id = `agend-effect-${boot}-${++frameSerial}`;
|
|
331
|
+
s.geometry = local ? local.bind(frame.element, { layer: d.layer }, coverage()) : geometry.bind(frame.element, { layer: d.layer, by: d.by });
|
|
332
|
+
if (!s.geometry.ok) { retire(s, "geometry_unknown"); return; }
|
|
333
|
+
const loaded = () => { if (current(s)) s.budget.loaded(); };
|
|
334
|
+
frame.element.addEventListener("load", loaded); s.loadOff = () => frame.element.removeEventListener("load", loaded);
|
|
335
|
+
const paint = coverage(d);
|
|
336
|
+
if (!current(s) || !paint || !syncGeometry(s, paint)) { retire(s, "geometry_unknown"); return; }
|
|
337
|
+
// One non-serializable host receipt per actual admitted frame. Never append it to a Worker event.
|
|
338
|
+
const owner = Object.freeze({ key: d.key, id: d.id, device: s.device, current: () => current(s) && s.owner === owner });
|
|
339
|
+
s.owner = owner;
|
|
340
|
+
try { onMount(owner); } catch { /* diagnostics/display failure cannot authorize or mutate a mount */ }
|
|
341
|
+
schedule();
|
|
342
|
+
}).catch(() => { if (current(s)) retire(s, "resource_unavailable"); }).finally(() => {
|
|
343
|
+
if (request.timer !== null) host.clearTimeout(request.timer);
|
|
344
|
+
loads.delete(request); if (s.request === request) s.request = null;
|
|
345
|
+
if (!dead) reconcile(); else if (loads.size === 0 && registries.get(host) === api) registries.delete(host);
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
schedule(); tell();
|
|
349
|
+
}
|
|
350
|
+
function publishEnv(s, proof = coverage(s.d)) {
|
|
351
|
+
if (!s.ready || !current(s) || context.hidden || !globalAllowed(s.d) || !permits(s.d, proof)) return;
|
|
352
|
+
const e = effectEvent("env", { width: s.rect.width, height: s.rect.height, dpr: dpr(s.device), quality: s.budget.snapshot().quality }, null, time());
|
|
353
|
+
if (e) s.frame.send(e);
|
|
354
|
+
}
|
|
355
|
+
function tick() {
|
|
356
|
+
raf = null;
|
|
357
|
+
if (dead) return;
|
|
358
|
+
const paint = coverage();
|
|
359
|
+
if (!globalAllowed() || context.hidden || !paint) { invalidate(); return; }
|
|
360
|
+
const proposal = revision; let policyChanged = false;
|
|
361
|
+
for (const s of [...slots.values()]) {
|
|
362
|
+
if (dead || proposal !== revision) return;
|
|
363
|
+
if (!s.frame) continue;
|
|
364
|
+
if (!permits(s.d, paint)) { retire(s, "superseded"); policyChanged = true; continue; }
|
|
365
|
+
if (dead || proposal !== revision) return;
|
|
366
|
+
const rect = syncGeometry(s, paint);
|
|
367
|
+
if (!current(s)) continue;
|
|
368
|
+
if (!rect) { retire(s, "geometry_unknown"); continue; }
|
|
369
|
+
// The host owns the CSS viewport. A bounded env signal lets Worker code redraw its own bitmap if desired.
|
|
370
|
+
const changed = rect.width !== s.rect.width || rect.height !== s.rect.height; s.rect = rect;
|
|
371
|
+
if (changed) publishEnv(s, paint);
|
|
372
|
+
if (s.ready) s.budget.frame();
|
|
373
|
+
if (s.pointer) {
|
|
374
|
+
const packet = s.pointer;
|
|
375
|
+
const n = time(), b = s.budget.snapshot();
|
|
376
|
+
if (n === null || n - packet.at > 100 || !permits(s.d, paint) || !pointerGate(paint) || !current(s) || !b.forward) {
|
|
377
|
+
if (s.pointer === packet) s.pointer = null;
|
|
378
|
+
} else if (s.lastPointer === null || n - s.lastPointer >= 1000 / b.pointerHz) {
|
|
379
|
+
if (s.pointer === packet) s.pointer = null;
|
|
380
|
+
const event = effectEvent("pointer", packet.fields, s.d.instance, packet.at);
|
|
381
|
+
if (event && s.frame.send(event)) s.lastPointer = n;
|
|
382
|
+
}
|
|
383
|
+
// Keep the latest fresh sample until the next eligible frame. An early rAF must
|
|
384
|
+
// not consume a click just because the preceding move used this rate interval.
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
if (dead || proposal !== revision) return;
|
|
388
|
+
if (policyChanged) reconcile(); else schedule();
|
|
389
|
+
}
|
|
390
|
+
function heartbeat() {
|
|
391
|
+
timer = null;
|
|
392
|
+
if (dead) return;
|
|
393
|
+
if (time() === null) { blocked = "clock_unavailable"; stopAll(blocked); tell(); return; }
|
|
394
|
+
const proposal = revision, activeBeforeSafety = slots.size;
|
|
395
|
+
if (!checkSafety()) { tell(); return; }
|
|
396
|
+
if (slots.size !== activeBeforeSafety) reconcile();
|
|
397
|
+
if (dead || proposal !== revision) return;
|
|
398
|
+
if (!globalAllowed() || context.hidden || !coverage()) { invalidate(); return; }
|
|
399
|
+
const budgetPauses = new Set();
|
|
400
|
+
for (const s of [...slots.values()]) {
|
|
401
|
+
if (dead || proposal !== revision) return;
|
|
402
|
+
if (!current(s) || !s.frame || !s.ready) continue;
|
|
403
|
+
if (s.d.trialStage && !coverage(s.d)) { if (dead || proposal !== revision) return; if (current(s)) retire(s, "trial_ended"); continue; }
|
|
404
|
+
if (dead || proposal !== revision) return;
|
|
405
|
+
const r = s.budget.gates({ hidden: false, reducedMotion: context.reducedMotion, saveData: context.saveData, show: context.show });
|
|
406
|
+
const state = r.remove ? r : s.readyAt !== null && last - s.readyAt >= 3000 ? s.budget.poll() : r;
|
|
407
|
+
try { onProfile({ key: s.d.key, id: s.d.id, device: s.device, ...state }, s.owner); } catch { /* metrics never authorize a mount */ }
|
|
408
|
+
if (dead || proposal !== revision) return;
|
|
409
|
+
if (!current(s)) continue;
|
|
410
|
+
if (s.d.trialStage && !coverage(s.d)) { if (dead || proposal !== revision) return; if (current(s)) retire(s, "trial_ended"); continue; }
|
|
411
|
+
if (dead || proposal !== revision) return;
|
|
412
|
+
if (state.remove) { const key = s.d.id + ":" + s.device; const count = state.reason === "host_budget" && !budgetPauses.has(key); if (count) budgetPauses.add(key); retire(s, state.reason, count); continue; }
|
|
413
|
+
if (state.badWindows > 0) s.healthySince = null; else if (s.healthySince === null) s.healthySince = last;
|
|
414
|
+
if (s.token && s.healthySince !== null && last - s.healthySince >= 5000 && state.badWindows === 0 && state.metrics !== null && !clearMarker(s, "healthy")) { stopAll("safety_unknown"); break; }
|
|
415
|
+
publishEnv(s);
|
|
416
|
+
}
|
|
417
|
+
if (dead || proposal !== revision) return;
|
|
418
|
+
schedule(); tell();
|
|
419
|
+
}
|
|
420
|
+
function checkSafety() {
|
|
421
|
+
if (dead || blocked) return false;
|
|
422
|
+
const proposed = revision;
|
|
423
|
+
for (const s of [...slots.values()]) {
|
|
424
|
+
if (!current(s)) continue;
|
|
425
|
+
const allowed = receipt(safety.allowed, s.d.id, s.device);
|
|
426
|
+
if (dead || proposed !== revision) return false;
|
|
427
|
+
if (current(s) && allowed !== true) retire(s, "safety_revoked");
|
|
428
|
+
if (dead || blocked || proposed !== revision) return false;
|
|
429
|
+
}
|
|
430
|
+
return !dead && !blocked;
|
|
431
|
+
}
|
|
432
|
+
function revalidateSafety() {
|
|
433
|
+
if (dead || reentrantStock()) return view();
|
|
434
|
+
if (checkSafety()) reconcile(); else tell();
|
|
435
|
+
return view();
|
|
436
|
+
}
|
|
437
|
+
function pointerGate(proof = coverage()) {
|
|
438
|
+
if (!globalAllowed() || context.hidden || context.modal || !proof || proof.front !== true) return false;
|
|
439
|
+
try {
|
|
440
|
+
const focused = host.document.activeElement;
|
|
441
|
+
// Native clicks on ordinary stock content focus its tabindex=-1 main ancestor.
|
|
442
|
+
// Recognize only that unique host root; unknown/editor focus remains a refusal.
|
|
443
|
+
const mains = focused?.tagName === "MAIN" ? host.document.querySelectorAll("#app > .shell > main#main.main[tabindex='-1']") : [];
|
|
444
|
+
const stockMain = focused?.isConnected === true && focused.ownerDocument === host.document && mains.length === 1 && mains[0] === focused;
|
|
445
|
+
return host.document.designMode !== "on" && !!focused && (["BODY", "BUTTON", "A"].includes(focused.tagName) || stockMain) && focused.isContentEditable === false && typeof focused.matches === "function" && !focused.matches("input,textarea,select,[contenteditable]:not([contenteditable='false'])");
|
|
446
|
+
} catch { return false; }
|
|
447
|
+
}
|
|
448
|
+
function pointer(event) {
|
|
449
|
+
// #2188: no frame to forward to — no gate to read (each read walks the page's computed styles, per pointer event).
|
|
450
|
+
if (dead || blocked || slots.size === 0 || !pointerGate() || event.isTrusted !== true) return;
|
|
451
|
+
const kinds = { pointermove: "move", pointerdown: "down", pointerup: "up", click: "click", wheel: "wheel" }, kind = kinds[event.type];
|
|
452
|
+
if (!kind || !finite(event.clientX) || !finite(event.clientY) || Math.abs(event.clientX) > 1e7 || Math.abs(event.clientY) > 1e7 || !Number.isInteger(event.buttons) || event.buttons < 0 || event.buttons > 31) return;
|
|
453
|
+
try { const target = host.document.elementFromPoint(event.clientX, event.clientY); if (!target || typeof target.closest !== "function" || target.closest("[data-trust]")) return; } catch { return; }
|
|
454
|
+
const at = time(); if (at === null) { blocked = "clock_unavailable"; stopAll(blocked); tell(); return; }
|
|
455
|
+
for (const s of slots.values()) {
|
|
456
|
+
if (!s.ready || !s.frame || !s.budget.snapshot().forward || !coverage(s.d) || !current(s)) continue;
|
|
457
|
+
const r = hostEffectRect(s.d.element); if (!r) continue;
|
|
458
|
+
const fields = { kind, x: event.clientX - r.x, y: event.clientY - r.y, buttons: event.buttons };
|
|
459
|
+
if (fields.x < 0 || fields.y < 0 || fields.x > r.width || fields.y > r.height) continue;
|
|
460
|
+
if (kind === "wheel") { fields.dx = event.deltaX; fields.dy = event.deltaY; }
|
|
461
|
+
if (effectEvent("pointer", fields, s.d.instance, at)) {
|
|
462
|
+
// One slot, with discrete input ahead of motion. A later move must not erase
|
|
463
|
+
// a waiting click; down/up/click may still coalesce to the latest discrete event.
|
|
464
|
+
if (kind !== "move" || !s.pointer || s.pointer.fields.kind === "move" || at - s.pointer.at > 100) s.pointer = { fields, at };
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
schedule();
|
|
468
|
+
}
|
|
469
|
+
try {
|
|
470
|
+
if (time() === null) throw Error("clock unavailable");
|
|
471
|
+
root = host.document.createElement("div"); root.className = "agend-effect-layer"; host.document.body.append(root);
|
|
472
|
+
geometry = createEffectGeometry({ window: host }); if (!geometry.ok) throw Error("geometry unsupported");
|
|
473
|
+
observer = new host.MutationObserver(invalidate); observer.observe(host.document.documentElement, { childList: true, subtree: true, attributes: true, characterData: true });
|
|
474
|
+
resize = new host.ResizeObserver(invalidate);
|
|
475
|
+
for (const type of ["scroll", "resize", "orientationchange", "focusin", "focusout"]) { host.addEventListener(type, invalidate, true); offs.push(() => host.removeEventListener(type, invalidate, true)); }
|
|
476
|
+
for (const type of ["pointermove", "pointerdown", "pointerup", "click", "wheel"]) { host.addEventListener(type, pointer, { passive: true }); offs.push(() => host.removeEventListener(type, pointer)); }
|
|
477
|
+
host.addEventListener("storage", revalidateSafety); offs.push(() => host.removeEventListener("storage", revalidateSafety));
|
|
478
|
+
const visibility = () => { revalidateSafety(); invalidate(); };
|
|
479
|
+
host.document.addEventListener("visibilitychange", visibility); offs.push(() => host.document.removeEventListener("visibilitychange", visibility));
|
|
480
|
+
if (typeof host.PerformanceObserver === "function" && host.PerformanceObserver.supportedEntryTypes?.includes("longtask")) {
|
|
481
|
+
try {
|
|
482
|
+
longTasks = new host.PerformanceObserver(list => {
|
|
483
|
+
for (const entry of list.getEntries()) for (const s of slots.values()) if (s.ready && s.budget) {
|
|
484
|
+
// No URL, container name, content or private Worker timing is read. Missing attribution stays unknown.
|
|
485
|
+
const attributed = Array.isArray(entry.attribution) && entry.attribution.some(a => a.containerId === s.frame.element.id && typeof a.containerId === "string" && a.containerId.length > 0);
|
|
486
|
+
s.budget.longTask(entry.startTime, entry.duration, attributed);
|
|
487
|
+
}
|
|
488
|
+
}); longTasks.observe({ type: "longtask", buffered: false }); longTasksSupported = true;
|
|
489
|
+
} catch { longTasks?.disconnect(); longTasks = null; }
|
|
490
|
+
}
|
|
491
|
+
} catch {
|
|
492
|
+
dead = true;
|
|
493
|
+
for (const release of [() => observer?.disconnect(), () => resize?.disconnect(), () => longTasks?.disconnect(), ...offs, () => geometry?.dispose(), () => root?.remove()]) { try { release(); } catch { /* continue releasing other host resources */ } }
|
|
494
|
+
return { ok: false, reason: "registry_unsupported" };
|
|
495
|
+
}
|
|
496
|
+
const api = { ok: true,
|
|
497
|
+
update(ds, ctx) {
|
|
498
|
+
if (dead || reentrantStock()) return view();
|
|
499
|
+
hideGeometry();
|
|
500
|
+
revision++;
|
|
501
|
+
if (!Array.isArray(ds) || ds.length > 128 || !plain(ctx)) { descriptors = []; context = null; results.clear(); stopAll("gates_unknown"); return []; }
|
|
502
|
+
descriptors = ds.map(snapshotDescriptor).filter(Boolean);
|
|
503
|
+
for (const [key, identity] of paused) if (!descriptors.some(d => d.key === key && signature(d) === identity)) paused.delete(key);
|
|
504
|
+
for (const [key, f] of failures) if (!descriptors.some(d => d.key === key && signature(d) === f.identity)) failures.delete(key);
|
|
505
|
+
context = Object.fromEntries([...FLAGS, "openInstance"].map(k => [k, ctx[k]]));
|
|
506
|
+
reconcile(); return view();
|
|
507
|
+
},
|
|
508
|
+
snapshot: view,
|
|
509
|
+
/** Host storage/foreground observation only, never called from a frame message. */
|
|
510
|
+
revalidateSafety,
|
|
511
|
+
/** Called only by the host's explicit human Resume UI. A descriptor update never clears this latch. */
|
|
512
|
+
resume(key) {
|
|
513
|
+
if (dead || reentrantStock() || blocked || typeof key !== "string") return false;
|
|
514
|
+
const proposed = revision, d = descriptors.find(d => d.key === key); if (!d || d.trialStage && !coverage(d) || revision !== proposed || receipt(safety.resume, d.id, device()) !== true || revision !== proposed) return false;
|
|
515
|
+
revision++;
|
|
516
|
+
if (!stopAll("human_resume")) return false;
|
|
517
|
+
if (blocked) return false; paused.delete(key); failures.delete(key); reconcile(); return true;
|
|
518
|
+
},
|
|
519
|
+
/** Host-only content-free signal API. Raw pointer publishing is refused; native pointer metadata is coalesced here. */
|
|
520
|
+
publish(type, fields, instance = null) {
|
|
521
|
+
// #2188: no frame to send to — nothing to prove (the stock walk ran twice on every page change).
|
|
522
|
+
if (dead || blocked || slots.size === 0 || !globalAllowed() || context.hidden || !coverage() || !TYPES.includes(type)) return 0;
|
|
523
|
+
const ts = time(); if (ts === null) { blocked = "clock_unavailable"; stopAll(blocked); tell(); return 0; }
|
|
524
|
+
let sent = 0; const proposal = revision;
|
|
525
|
+
for (const s of [...slots.values()]) {
|
|
526
|
+
if (dead || proposal !== revision) return sent;
|
|
527
|
+
if (!s.ready || !s.frame || !s.budget.snapshot().forward || !coverage(s.d) || !current(s)) continue;
|
|
528
|
+
if (["state", "reply", "mention"].includes(type) && (s.d.instance !== null ? instance !== s.d.instance : instance !== context.openInstance)) continue;
|
|
529
|
+
const e = effectEvent(type, fields, s.d.instance, ts); if (e && s.frame.send(e)) sent++;
|
|
530
|
+
}
|
|
531
|
+
return sent;
|
|
532
|
+
},
|
|
533
|
+
dispose() {
|
|
534
|
+
if (dead) return; dead = true; revision++; stopAll("disposed");
|
|
535
|
+
if (raf !== null) host.cancelAnimationFrame(raf); if (timer !== null) host.clearTimeout(timer);
|
|
536
|
+
observer.disconnect(); resize.disconnect(); longTasks?.disconnect(); for (const off of offs) off();
|
|
537
|
+
geometry.dispose(); root.remove(); observed.clear(); if (loads.size === 0 && registries.get(host) === api) registries.delete(host);
|
|
538
|
+
},
|
|
539
|
+
};
|
|
540
|
+
// Read-only host geometry seam; no selector guessing among poster and live roots.
|
|
541
|
+
Object.defineProperty(api, "frameRoot", { get: () => dead ? null : root });
|
|
542
|
+
registries.set(host, api); return api;
|
|
543
|
+
}
|