@songsid/agend 2.2.1 → 2.3.0-beta.10
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 +29 -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.d.ts +9 -0
- package/dist/channel/adapters/discord.js +52 -2
- 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 +130 -31
- 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 +5 -0
- package/dist/daemon.js +273 -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 +506 -11
- package/dist/fleet-manager.js +1784 -130
- package/dist/fleet-manager.js.map +1 -1
- 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 +476 -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.js +9 -4
- 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 +100 -8
- package/dist/locale.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 +19 -0
- package/dist/settings-api.js +210 -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/types.d.ts +61 -1
- package/dist/ui/app-effects.js +233 -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 +9 -6
- package/dist/ui/chat-store.js +9 -3
- package/dist/ui/chat-strings.js +70 -2
- package/dist/ui/chat-thread.js +191 -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 +203 -57
- package/dist/ui/panel-details.js +20 -6
- package/dist/ui/panel-fleet.js +43 -18
- package/dist/ui/panel-log.js +6 -6
- package/dist/ui/panel-needs.js +3 -3
- package/dist/ui/panel-settings.js +34 -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 +333 -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 +24 -2
- package/dist/ui/shared/app-session.js +3 -1
- package/dist/ui/shared/app-shell.js +102 -23
- 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 +565 -4
- 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 +115 -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 +535 -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 +221 -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 +111 -5
- package/dist/web-api.js +1235 -58
- 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 +59 -0
- package/dist/web-chat-history.js +102 -4
- 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 +25 -0
- package/dist/web-image-meta.js +200 -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 +180 -0
- package/dist/web-owner-css-store.js +384 -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 +270 -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-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-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,170 @@
|
|
|
1
|
+
/** #1629: trusted bootstrap sources; uploaded JS runs only in a dedicated Worker, never a DOM realm. */
|
|
2
|
+
export const EFFECT_MAX_BYTES = 1024 * 1024;
|
|
3
|
+
export const EFFECT_MAX_PIXELS = 8 * 1024 * 1024;
|
|
4
|
+
// Shared by the trusted document and Worker. Closed signals only; no content-bearing fields are read.
|
|
5
|
+
export const EFFECT_SIGNAL_CHECK = String.raw `
|
|
6
|
+
function signal(d, instance) {
|
|
7
|
+
if (!d || Object.getPrototypeOf(d) !== Object.prototype || d.v !== 1 || !Number.isFinite(d.ts) || d.ts < 0) return false;
|
|
8
|
+
var keys = {state:['state'],reply:[],mention:[],theme:['mode'],env:['width','height','dpr','quality'],pointer:['kind','x','y','buttons']};
|
|
9
|
+
if (!Object.prototype.hasOwnProperty.call(keys,d.type)) return false;
|
|
10
|
+
var exact = ['v','type','ts'].concat(keys[d.type]);
|
|
11
|
+
if (['state','reply','mention'].indexOf(d.type) >= 0 && Object.prototype.hasOwnProperty.call(d,'instance')) {
|
|
12
|
+
if (typeof instance !== 'string' || d.instance !== instance) return false;
|
|
13
|
+
exact.push('instance');
|
|
14
|
+
}
|
|
15
|
+
if (d.type === 'pointer') for (var key of ['dx','dy']) if (Object.prototype.hasOwnProperty.call(d,key)) {
|
|
16
|
+
if (!Number.isFinite(d[key]) || Math.abs(d[key]) > 10000) return false;
|
|
17
|
+
exact.push(key);
|
|
18
|
+
}
|
|
19
|
+
if (Object.keys(d).sort().join(',') !== exact.sort().join(',')) return false;
|
|
20
|
+
switch (d.type) {
|
|
21
|
+
case 'state': return ['idle','working','needs_you','stopped'].indexOf(d.state) >= 0;
|
|
22
|
+
case 'reply': case 'mention': return true;
|
|
23
|
+
case 'theme': return ['light','dark'].indexOf(d.mode) >= 0;
|
|
24
|
+
case 'env': return Number.isInteger(d.width) && d.width >= 1 && d.width <= 4096 && Number.isInteger(d.height) && d.height >= 1 && d.height <= 4096 && d.width*d.height <= 8388608 && Number.isFinite(d.dpr) && d.dpr >= 0.5 && d.dpr <= 3 && ['normal','low'].indexOf(d.quality) >= 0;
|
|
25
|
+
case 'pointer': return ['move','down','up','click','wheel'].indexOf(d.kind) >= 0 && Number.isFinite(d.x) && d.x >= 0 && d.x <= 4096 && Number.isFinite(d.y) && d.y >= 0 && d.y <= 4096 && Number.isInteger(d.buttons) && d.buttons >= 0 && d.buttons <= 31;
|
|
26
|
+
}
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
/** The private port never reaches user callbacks, including through poisoned native getters/schedulers. */
|
|
31
|
+
export function effectWorkerSource() {
|
|
32
|
+
return `"use strict";
|
|
33
|
+
(function () {
|
|
34
|
+
${EFFECT_SIGNAL_CHECK}
|
|
35
|
+
var defer = self.setTimeout.bind(self), load = self.importScripts.bind(self), end = self.close.bind(self), now = performance.now.bind(performance);
|
|
36
|
+
var read = Function.prototype.call.bind(Object.getOwnPropertyDescriptor(MessageEvent.prototype,'data').get);
|
|
37
|
+
var raf = typeof self.requestAnimationFrame === 'function' ? self.requestAnimationFrame.bind(self) : null;
|
|
38
|
+
var initialized = false;
|
|
39
|
+
function init(event) {
|
|
40
|
+
if (initialized) return;
|
|
41
|
+
var d = read(event);
|
|
42
|
+
if (!d || !d.port || !d.canvas || typeof d.codeUrl !== 'string') return;
|
|
43
|
+
initialized = true;
|
|
44
|
+
self.removeEventListener('message',init);
|
|
45
|
+
var port = d.port, post = port.postMessage.bind(port), callbacks = Object.create(null), ready = false;
|
|
46
|
+
var assets = Object.create(null);
|
|
47
|
+
d.assets.forEach(function (asset) { assets[asset.name] = asset.bitmap; });
|
|
48
|
+
var api = Object.freeze({
|
|
49
|
+
canvas: d.canvas,
|
|
50
|
+
params: Object.freeze(d.params),
|
|
51
|
+
asset: function (name) { return Object.prototype.hasOwnProperty.call(assets,name) ? assets[name] : undefined; },
|
|
52
|
+
on: function (kind,fn) {
|
|
53
|
+
if (['state','reply','mention','theme','env','pointer'].indexOf(kind) < 0 || typeof fn !== 'function') return;
|
|
54
|
+
if (!callbacks[kind]) callbacks[kind] = [];
|
|
55
|
+
if (callbacks[kind].length < 32) callbacks[kind].push(fn);
|
|
56
|
+
},
|
|
57
|
+
frame: function (fn) {
|
|
58
|
+
if (typeof fn !== 'function') return;
|
|
59
|
+
if (raf) { try { return raf(fn); } catch (_) {} }
|
|
60
|
+
return defer(function () { fn(now()); },16);
|
|
61
|
+
},
|
|
62
|
+
ready: function () { if (!ready) { ready = true; post({type:'ready'}); } }
|
|
63
|
+
});
|
|
64
|
+
Object.defineProperty(self,'agend',{value:api,writable:false,configurable:false});
|
|
65
|
+
// Defence in depth against nested workers; termination and host budgets remain required.
|
|
66
|
+
['Worker','SharedWorker','importScripts','RTCPeerConnection','webkitRTCPeerConnection'].forEach(function (key) {
|
|
67
|
+
try { Object.defineProperty(self,key,{value:undefined,writable:false,configurable:false}); } catch (_) {}
|
|
68
|
+
});
|
|
69
|
+
port.addEventListener('message',function (event) {
|
|
70
|
+
var payload = read(event);
|
|
71
|
+
if (!signal(payload,d.instance)) return;
|
|
72
|
+
defer(function () {
|
|
73
|
+
var listeners = (callbacks[payload.type] || []).slice();
|
|
74
|
+
listeners.forEach(function (fn) { try { fn(payload); } catch (_) {} });
|
|
75
|
+
},0);
|
|
76
|
+
});
|
|
77
|
+
port.start();
|
|
78
|
+
// Separate script/global: never concatenate user code into a trusted lexical scope.
|
|
79
|
+
defer(function () { try { load(d.codeUrl); } catch (_) { end(); } },0);
|
|
80
|
+
}
|
|
81
|
+
self.addEventListener('message',init);
|
|
82
|
+
})();`;
|
|
83
|
+
}
|
|
84
|
+
function literal(value) {
|
|
85
|
+
return JSON.stringify(value).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
86
|
+
}
|
|
87
|
+
/** No HTML input exists. The document realm contains only this shim and its single canvas. */
|
|
88
|
+
export function buildCanvasEffectShim(bootId, origins, sameListener = false) {
|
|
89
|
+
const source = String.raw `(function () {
|
|
90
|
+
"use strict";
|
|
91
|
+
${EFFECT_SIGNAL_CHECK}
|
|
92
|
+
var BOOT=${literal(bootId)}, ORIGINS=${sameListener ? "[new URL(window.location.href).origin]" : literal([...origins])}, MAX=${EFFECT_MAX_BYTES}, PIXELS=${EFFECT_MAX_PIXELS};
|
|
93
|
+
var WORKER=${literal(effectWorkerSource())};
|
|
94
|
+
var done=false, active=true, worker=null, host=null, link=null, urls=[], bitmaps=[], deadline=null, expires=null;
|
|
95
|
+
var defer=window.setTimeout.bind(window), cancel=window.clearTimeout.bind(window), now=performance.now.bind(performance);
|
|
96
|
+
var read=Function.prototype.call.bind(Object.getOwnPropertyDescriptor(MessageEvent.prototype,'data').get);
|
|
97
|
+
function plain(d) { return !!d && Object.getPrototypeOf(d) === Object.prototype; }
|
|
98
|
+
function bytes(s) { try { return new TextEncoder().encode(s).length; } catch (_) { return Infinity; } }
|
|
99
|
+
function stop() {
|
|
100
|
+
if (!active) return;
|
|
101
|
+
active=false;
|
|
102
|
+
if (deadline !== null) cancel(deadline);
|
|
103
|
+
if (worker) worker.terminate();
|
|
104
|
+
if (host) host.close();
|
|
105
|
+
if (link) link.close();
|
|
106
|
+
urls.forEach(function (url) { URL.revokeObjectURL(url); });
|
|
107
|
+
bitmaps.forEach(function (bitmap) { try { bitmap.close(); } catch (_) {} });
|
|
108
|
+
}
|
|
109
|
+
window.addEventListener('pagehide',stop,{once:true});
|
|
110
|
+
async function render(event) {
|
|
111
|
+
if (done || !active || event.source !== window.parent || event.origin === 'null' || ORIGINS.indexOf(event.origin) < 0) return;
|
|
112
|
+
var d=read(event);
|
|
113
|
+
if (!plain(d) || Object.keys(d).sort().join(',') !== 'assets,ch,code,dpr,height,instance,params,type,v,width' || d.v !== 1 || d.type !== 'render') return;
|
|
114
|
+
if (typeof d.ch !== 'string' || !/^[0-9a-f]{16,64}$/.test(d.ch) || typeof d.code !== 'string' || bytes(d.code) > MAX) return;
|
|
115
|
+
if (d.instance !== null && (typeof d.instance !== 'string' || d.instance.length < 1 || d.instance.length > 128)) return;
|
|
116
|
+
if (!signal({v:1,type:'env',ts:0,width:d.width,height:d.height,dpr:d.dpr,quality:'normal'},d.instance)) return;
|
|
117
|
+
if (!plain(d.params) || Object.keys(d.params).length > 16 || !Array.isArray(d.assets) || d.assets.length > 16) return;
|
|
118
|
+
var names=new Set();
|
|
119
|
+
if (!Object.keys(d.params).every(function (key) {
|
|
120
|
+
var value=d.params[key];
|
|
121
|
+
return /^[a-z][a-z0-9_]{0,31}$/.test(key) && (typeof value === 'boolean' || typeof value === 'number' && Number.isFinite(value) || typeof value === 'string' && value.length <= 128);
|
|
122
|
+
})) return;
|
|
123
|
+
var size=bytes(d.code)+bytes(JSON.stringify(d.params));
|
|
124
|
+
if (Object.keys(d.assets).length !== d.assets.length) return;
|
|
125
|
+
if (!d.assets.every(function (asset) {
|
|
126
|
+
if (!plain(asset) || Object.keys(asset).sort().join(',') !== 'bytes,mime,name' || typeof asset.name !== 'string' || !/^assets\/[a-z0-9][a-z0-9_-]{0,63}\.(png|jpe?g|webp|gif)$/.test(asset.name) || names.has(asset.name)) return false;
|
|
127
|
+
if (['image/png','image/jpeg','image/webp','image/gif'].indexOf(asset.mime) < 0 || !(asset.bytes instanceof Uint8Array)) return false;
|
|
128
|
+
names.add(asset.name);size+=asset.bytes.byteLength;return true;
|
|
129
|
+
}) || size > MAX) return;
|
|
130
|
+
if (!event.ports || event.ports.length !== 1) return;
|
|
131
|
+
var port=event.ports[0];
|
|
132
|
+
if (!port || typeof port.postMessage !== 'function' || typeof port.addEventListener !== 'function' || typeof port.start !== 'function' || typeof port.close !== 'function') return;
|
|
133
|
+
done=true;host=port;window.removeEventListener('message',render);
|
|
134
|
+
expires=now()+10000;deadline=defer(stop,10000);
|
|
135
|
+
try {
|
|
136
|
+
if (typeof Worker !== 'function' || typeof OffscreenCanvas !== 'function' || typeof createImageBitmap !== 'function' || typeof HTMLCanvasElement.prototype.transferControlToOffscreen !== 'function') { stop();return; }
|
|
137
|
+
var assets=[], pixels=0;
|
|
138
|
+
for (var asset of d.assets) {
|
|
139
|
+
var bitmap=await createImageBitmap(new Blob([asset.bytes],{type:asset.mime}));
|
|
140
|
+
if (!active || now() >= expires) { bitmap.close();stop();return; }
|
|
141
|
+
bitmaps.push(bitmap);
|
|
142
|
+
if (bitmap.width < 1 || bitmap.height < 1 || bitmap.width > 4096 || bitmap.height > 4096 || bitmap.width*bitmap.height > PIXELS) { stop();return; }
|
|
143
|
+
pixels+=bitmap.width*bitmap.height;if(pixels > PIXELS) { stop();return; }
|
|
144
|
+
assets.push({name:asset.name,bitmap:bitmap});
|
|
145
|
+
}
|
|
146
|
+
if (!active || now() >= expires) { stop();return; }
|
|
147
|
+
var canvas=document.querySelector('canvas');canvas.width=d.width;canvas.height=d.height;
|
|
148
|
+
var offscreen=canvas.transferControlToOffscreen();
|
|
149
|
+
var codeUrl=URL.createObjectURL(new Blob([d.code],{type:'text/javascript'}));urls.push(codeUrl);
|
|
150
|
+
var workerUrl=URL.createObjectURL(new Blob([WORKER],{type:'text/javascript'}));urls.push(workerUrl);
|
|
151
|
+
worker=new Worker(workerUrl);var channel=new MessageChannel();link=channel.port1;
|
|
152
|
+
var ready=false, post=port.postMessage.bind(port);
|
|
153
|
+
// No diagnostic, cost, pong, command or error message is forwarded to the host.
|
|
154
|
+
link.addEventListener('message',function (event) {
|
|
155
|
+
var value=read(event);
|
|
156
|
+
if (active && !ready && now() >= expires) { stop();return; }
|
|
157
|
+
if (!active || ready || !plain(value) || Object.keys(value).join(',') !== 'type' || value.type !== 'ready') return;
|
|
158
|
+
ready=true;cancel(deadline);deadline=null;post({type:'ready'});
|
|
159
|
+
});link.start();
|
|
160
|
+
worker.addEventListener('error',stop);worker.addEventListener('messageerror',stop);
|
|
161
|
+
port.addEventListener('message',function (event) { var payload=read(event);if (active && signal(payload,d.instance)) link.postMessage(payload); });port.start();
|
|
162
|
+
worker.postMessage({port:channel.port2,canvas:offscreen,assets:assets,params:d.params,instance:d.instance,codeUrl:codeUrl},[channel.port2,offscreen].concat(bitmaps));
|
|
163
|
+
} catch (_) { stop(); }
|
|
164
|
+
}
|
|
165
|
+
window.addEventListener('message',render);
|
|
166
|
+
window.parent.postMessage({v:1,type:'ready',ch:null,boot:BOOT},'*');
|
|
167
|
+
})();`;
|
|
168
|
+
return `<!doctype html><html><head><meta charset="utf-8"><title>Effect</title><style>html,body{margin:0;width:100%;height:100%;overflow:hidden}canvas{display:block;width:100%;height:100%}</style></head><body><canvas></canvas><script>${source}</script></body></html>`;
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=web-effect-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-effect-worker.js","sourceRoot":"","sources":["../src/web-effect-worker.ts"],"names":[],"mappings":"AAAA,wGAAwG;AACxG,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,GAAG,IAAI,CAAC;AAC5C,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAEjD,sGAAsG;AACtG,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;CAwB5C,CAAC;AAEF,2GAA2G;AAC3G,MAAM,UAAU,kBAAkB;IAChC,OAAO;;IAEL,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAgDjB,CAAC;AACP,CAAC;AAED,SAAS,OAAO,CAAC,KAAc;IAC7B,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AACpH,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,qBAAqB,CAAC,MAAc,EAAE,OAA0B,EAAE,YAAY,GAAG,KAAK;IACpG,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAA;;IAEvB,mBAAmB;aACV,OAAO,CAAC,MAAM,CAAC,aAAa,YAAY,CAAC,CAAC,CAAC,wCAAwC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,SAAS,gBAAgB,YAAY,iBAAiB;eAC/J,OAAO,CAAC,kBAAkB,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA0EtC,CAAC;IACL,OAAO,oOAAoO,MAAM,yBAAyB,CAAC;AAC7Q,CAAC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/** CW1 effect manifests are metadata, never placement authority. Widgets are host-rendered elsewhere. */
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
export declare const WEB_EFFECT_ID: RegExp;
|
|
4
|
+
export declare const WEB_EFFECT_REGIONS: readonly ["chat", "sidebar", "header", "page", "box"];
|
|
5
|
+
export declare const WEB_EFFECT_WANTS: readonly ["pointer", "state", "reply", "mention", "theme"];
|
|
6
|
+
declare const manifest: z.ZodObject<{
|
|
7
|
+
v: z.ZodLiteral<1>;
|
|
8
|
+
kind: z.ZodDefault<z.ZodLiteral<"effect">>;
|
|
9
|
+
runtime: z.ZodLiteral<"canvas-worker-v1">;
|
|
10
|
+
worker: z.ZodLiteral<"worker.js">;
|
|
11
|
+
name: z.ZodString;
|
|
12
|
+
title: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
13
|
+
description: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
|
|
14
|
+
poster: z.ZodOptional<z.ZodLiteral<"poster.png">>;
|
|
15
|
+
regions: z.ZodArray<z.ZodEnum<{
|
|
16
|
+
chat: "chat";
|
|
17
|
+
sidebar: "sidebar";
|
|
18
|
+
header: "header";
|
|
19
|
+
page: "page";
|
|
20
|
+
box: "box";
|
|
21
|
+
}>>;
|
|
22
|
+
layer: z.ZodEnum<{
|
|
23
|
+
behind: "behind";
|
|
24
|
+
front: "front";
|
|
25
|
+
}>;
|
|
26
|
+
box: z.ZodOptional<z.ZodObject<{
|
|
27
|
+
anchor: z.ZodEnum<{
|
|
28
|
+
"top-left": "top-left";
|
|
29
|
+
"top-right": "top-right";
|
|
30
|
+
"bottom-left": "bottom-left";
|
|
31
|
+
"bottom-right": "bottom-right";
|
|
32
|
+
center: "center";
|
|
33
|
+
}>;
|
|
34
|
+
width: z.ZodNumber;
|
|
35
|
+
height: z.ZodNumber;
|
|
36
|
+
offset: z.ZodNumber;
|
|
37
|
+
}, z.core.$strict>>;
|
|
38
|
+
cursor: z.ZodOptional<z.ZodObject<{
|
|
39
|
+
hotspot: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
|
|
40
|
+
}, z.core.$strict>>;
|
|
41
|
+
wants: z.ZodArray<z.ZodEnum<{
|
|
42
|
+
mention: "mention";
|
|
43
|
+
state: "state";
|
|
44
|
+
theme: "theme";
|
|
45
|
+
pointer: "pointer";
|
|
46
|
+
reply: "reply";
|
|
47
|
+
}>>;
|
|
48
|
+
params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
49
|
+
type: z.ZodLiteral<"number">;
|
|
50
|
+
min: z.ZodNumber;
|
|
51
|
+
max: z.ZodNumber;
|
|
52
|
+
step: z.ZodOptional<z.ZodNumber>;
|
|
53
|
+
default: z.ZodNumber;
|
|
54
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
55
|
+
type: z.ZodLiteral<"int">;
|
|
56
|
+
min: z.ZodNumber;
|
|
57
|
+
max: z.ZodNumber;
|
|
58
|
+
default: z.ZodNumber;
|
|
59
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
60
|
+
type: z.ZodLiteral<"bool">;
|
|
61
|
+
default: z.ZodBoolean;
|
|
62
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
63
|
+
type: z.ZodLiteral<"enum">;
|
|
64
|
+
values: z.ZodArray<z.ZodString>;
|
|
65
|
+
default: z.ZodString;
|
|
66
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
67
|
+
type: z.ZodLiteral<"color">;
|
|
68
|
+
default: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
69
|
+
}, z.core.$strict>], "type">>>;
|
|
70
|
+
}, z.core.$strict>;
|
|
71
|
+
export type WebEffectManifest = z.infer<typeof manifest>;
|
|
72
|
+
export type EffectParamValue = string | number | boolean;
|
|
73
|
+
export declare function parseWebEffectManifest(value: unknown): {
|
|
74
|
+
ok: true;
|
|
75
|
+
manifest: WebEffectManifest;
|
|
76
|
+
} | {
|
|
77
|
+
ok: false;
|
|
78
|
+
error: "invalid_manifest";
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* #2017: whether an effect can be placed in a chat — its manifest's regions include `chat` (else it is saved but never
|
|
82
|
+
* plays there). Only a NEW chat placement is checked (agent tool, person's route, a mod's theme.effects); an older one
|
|
83
|
+
* stays as it is (filtered at run time) and can be removed. A non-chat effect stays a valid upload and personal choice.
|
|
84
|
+
*/
|
|
85
|
+
export declare function chatCompatible(manifest: {
|
|
86
|
+
regions?: readonly string[];
|
|
87
|
+
}): boolean;
|
|
88
|
+
/** #2017: the same test on an effect's files (its effect.json), for a mod export: an unreadable manifest is not chat. */
|
|
89
|
+
export declare function filesPlayInChat(files: ReadonlyMap<string, Uint8Array>): boolean;
|
|
90
|
+
export declare const EFFECT_REGION: Readonly<{
|
|
91
|
+
error: "effect_region";
|
|
92
|
+
message: string;
|
|
93
|
+
}>;
|
|
94
|
+
/** Defaults and overrides are resolved together before a placement or mod commit can write. */
|
|
95
|
+
export declare function resolveEffectParams(input: WebEffectManifest, overrides?: unknown): {
|
|
96
|
+
ok: true;
|
|
97
|
+
values: Record<string, EffectParamValue>;
|
|
98
|
+
overrides: Record<string, EffectParamValue>;
|
|
99
|
+
} | {
|
|
100
|
+
ok: false;
|
|
101
|
+
error: "invalid_params";
|
|
102
|
+
};
|
|
103
|
+
export {};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/** CW1 effect manifests are metadata, never placement authority. Widgets are host-rendered elsewhere. */
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { canonicalText } from "./web-theme.js";
|
|
4
|
+
export const WEB_EFFECT_ID = /^[0-9a-f]{32}$/;
|
|
5
|
+
export const WEB_EFFECT_REGIONS = ["chat", "sidebar", "header", "page", "box"];
|
|
6
|
+
export const WEB_EFFECT_WANTS = ["pointer", "state", "reply", "mention", "theme"];
|
|
7
|
+
const slug = z.string().regex(/^[a-z0-9][a-z0-9-]{0,31}$/);
|
|
8
|
+
function text(max, min) {
|
|
9
|
+
return z.string().max(max * 10).transform((value, ctx) => {
|
|
10
|
+
const result = min === 0 && value === "" ? "" : canonicalText(value, Math.max(1, min), max);
|
|
11
|
+
if (result === null) {
|
|
12
|
+
ctx.addIssue({ code: "custom", message: "Invalid display text" });
|
|
13
|
+
return z.NEVER;
|
|
14
|
+
}
|
|
15
|
+
return result;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
const finite = z.number().finite().min(-1e9).max(1e9);
|
|
19
|
+
const numeric = z.strictObject({ type: z.literal("number"), min: finite, max: finite, step: z.number().finite().positive().max(2e9).optional(), default: finite });
|
|
20
|
+
const integer = z.strictObject({ type: z.literal("int"), min: finite.int(), max: finite.int(), default: finite.int() });
|
|
21
|
+
const param = z.discriminatedUnion("type", [
|
|
22
|
+
numeric, integer, z.strictObject({ type: z.literal("bool"), default: z.boolean() }),
|
|
23
|
+
z.strictObject({ type: z.literal("enum"), values: z.array(slug).min(1).max(16), default: slug }),
|
|
24
|
+
z.strictObject({ type: z.literal("color"), default: z.string().regex(/^#[0-9a-fA-F]{6}$/).transform(value => value.toLowerCase()) }),
|
|
25
|
+
]).refine(d => {
|
|
26
|
+
if (d.type === "enum")
|
|
27
|
+
return new Set(d.values).size === d.values.length && d.values.includes(d.default);
|
|
28
|
+
if (d.type === "number" || d.type === "int")
|
|
29
|
+
return d.min <= d.max && d.default >= d.min && d.default <= d.max && (d.type !== "number" || d.step === undefined || aligned(d.default, d.min, d.step));
|
|
30
|
+
return true;
|
|
31
|
+
});
|
|
32
|
+
function aligned(value, min, step) {
|
|
33
|
+
const distance = (value - min) / step;
|
|
34
|
+
return Number.isFinite(distance) && Math.abs(distance - Math.round(distance)) <= 1e-8;
|
|
35
|
+
}
|
|
36
|
+
const manifest = z.strictObject({
|
|
37
|
+
v: z.literal(1), kind: z.literal("effect").default("effect"), runtime: z.literal("canvas-worker-v1"), worker: z.literal("worker.js"),
|
|
38
|
+
name: slug, title: text(40, 1), description: text(200, 0).optional(), poster: z.literal("poster.png").optional(),
|
|
39
|
+
regions: z.array(z.enum(WEB_EFFECT_REGIONS)).min(1).max(5).refine(v => new Set(v).size === v.length),
|
|
40
|
+
layer: z.enum(["behind", "front"]),
|
|
41
|
+
box: z.strictObject({ anchor: z.enum(["top-left", "top-right", "bottom-left", "bottom-right", "center"]), width: z.number().int().min(32).max(480), height: z.number().int().min(32).max(480), offset: z.number().int().min(0).max(64) }).optional(),
|
|
42
|
+
cursor: z.strictObject({ hotspot: z.tuple([z.number().int().min(0).max(63), z.number().int().min(0).max(63)]) }).optional(),
|
|
43
|
+
wants: z.array(z.enum(WEB_EFFECT_WANTS)).max(5).refine(v => new Set(v).size === v.length),
|
|
44
|
+
params: z.record(z.string().regex(/^[a-z][a-z0-9_]{0,31}$/), param).refine(v => Object.keys(v).length <= 16).optional(),
|
|
45
|
+
});
|
|
46
|
+
/** Bounded data only. Do not invoke getters or interpret unreadable values as an absent field. */
|
|
47
|
+
function plainData(value) {
|
|
48
|
+
const pending = [{ value, depth: 0 }];
|
|
49
|
+
let nodes = 0;
|
|
50
|
+
while (pending.length) {
|
|
51
|
+
const { value, depth } = pending.pop();
|
|
52
|
+
if (++nodes > 1024 || depth > 8)
|
|
53
|
+
return false;
|
|
54
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
55
|
+
continue;
|
|
56
|
+
if (typeof value === "number") {
|
|
57
|
+
if (!Number.isFinite(value))
|
|
58
|
+
return false;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (typeof value !== "object")
|
|
62
|
+
return false;
|
|
63
|
+
const array = Array.isArray(value), proto = Object.getPrototypeOf(value);
|
|
64
|
+
if (array ? proto !== Array.prototype : proto !== Object.prototype && proto !== null)
|
|
65
|
+
return false;
|
|
66
|
+
const keys = Reflect.ownKeys(value);
|
|
67
|
+
if (keys.length > 33 || array && value.length > 32)
|
|
68
|
+
return false;
|
|
69
|
+
for (const key of keys) {
|
|
70
|
+
if (typeof key !== "string")
|
|
71
|
+
return false;
|
|
72
|
+
if (array && key === "length")
|
|
73
|
+
continue;
|
|
74
|
+
const field = Object.getOwnPropertyDescriptor(value, key);
|
|
75
|
+
if (!("value" in field))
|
|
76
|
+
return false;
|
|
77
|
+
pending.push({ value: field.value, depth: depth + 1 });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
export function parseWebEffectManifest(value) {
|
|
83
|
+
try {
|
|
84
|
+
if (!plainData(value))
|
|
85
|
+
return { ok: false, error: "invalid_manifest" };
|
|
86
|
+
const result = manifest.safeParse(value);
|
|
87
|
+
return result.success ? { ok: true, manifest: result.data } : { ok: false, error: "invalid_manifest" };
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return { ok: false, error: "invalid_manifest" };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* #2017: whether an effect can be placed in a chat — its manifest's regions include `chat` (else it is saved but never
|
|
95
|
+
* plays there). Only a NEW chat placement is checked (agent tool, person's route, a mod's theme.effects); an older one
|
|
96
|
+
* stays as it is (filtered at run time) and can be removed. A non-chat effect stays a valid upload and personal choice.
|
|
97
|
+
*/
|
|
98
|
+
export function chatCompatible(manifest) {
|
|
99
|
+
return Array.isArray(manifest.regions) && manifest.regions.includes("chat");
|
|
100
|
+
}
|
|
101
|
+
/** #2017: the same test on an effect's files (its effect.json), for a mod export: an unreadable manifest is not chat. */
|
|
102
|
+
export function filesPlayInChat(files) {
|
|
103
|
+
const raw = files.get("effect.json");
|
|
104
|
+
if (!raw)
|
|
105
|
+
return false;
|
|
106
|
+
try {
|
|
107
|
+
return chatCompatible(JSON.parse(Buffer.from(raw).toString("utf8")));
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
export const EFFECT_REGION = Object.freeze({ error: "effect_region", message: "This effect's regions do not include chat." });
|
|
114
|
+
/** Defaults and overrides are resolved together before a placement or mod commit can write. */
|
|
115
|
+
export function resolveEffectParams(input, overrides = {}) {
|
|
116
|
+
try {
|
|
117
|
+
if (!plainData(overrides) || !overrides || Array.isArray(overrides) || typeof overrides !== "object")
|
|
118
|
+
return { ok: false, error: "invalid_params" };
|
|
119
|
+
const schema = input.params ?? {};
|
|
120
|
+
for (const key of Object.keys(overrides))
|
|
121
|
+
if (!Object.hasOwn(schema, key))
|
|
122
|
+
return { ok: false, error: "invalid_params" };
|
|
123
|
+
const values = Object.create(null), changed = Object.create(null);
|
|
124
|
+
for (const [name, d] of Object.entries(schema)) {
|
|
125
|
+
let value = Object.hasOwn(overrides, name) ? overrides[name] : d.default;
|
|
126
|
+
if (d.type === "number" || d.type === "int") {
|
|
127
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < d.min || value > d.max || d.type === "int" && !Number.isSafeInteger(value) || d.type === "number" && d.step !== undefined && !aligned(value, d.min, d.step))
|
|
128
|
+
return { ok: false, error: "invalid_params" };
|
|
129
|
+
}
|
|
130
|
+
else if (d.type === "bool") {
|
|
131
|
+
if (typeof value !== "boolean")
|
|
132
|
+
return { ok: false, error: "invalid_params" };
|
|
133
|
+
}
|
|
134
|
+
else if (d.type === "enum") {
|
|
135
|
+
if (typeof value !== "string" || !d.values.includes(value))
|
|
136
|
+
return { ok: false, error: "invalid_params" };
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
if (typeof value !== "string" || !/^#[0-9a-fA-F]{6}$/.test(value))
|
|
140
|
+
return { ok: false, error: "invalid_params" };
|
|
141
|
+
value = value.toLowerCase();
|
|
142
|
+
}
|
|
143
|
+
values[name] = value;
|
|
144
|
+
if (value !== d.default)
|
|
145
|
+
changed[name] = value;
|
|
146
|
+
}
|
|
147
|
+
return { ok: true, values, overrides: changed };
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return { ok: false, error: "invalid_params" };
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=web-effect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-effect.js","sourceRoot":"","sources":["../src/web-effect.ts"],"names":[],"mappings":"AAAA,yGAAyG;AACzG,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,MAAM,CAAC,MAAM,aAAa,GAAG,gBAAgB,CAAC;AAC9C,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAU,CAAC;AACxF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAU,CAAC;AAC3F,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;AAC3D,SAAS,IAAI,CAAC,GAAW,EAAE,GAAW;IACpC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACvD,MAAM,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;QAC5F,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC,CAAC;YAClE,OAAO,CAAC,CAAC,KAAK,CAAC;QACjB,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC;AACD,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACtD,MAAM,OAAO,GAAG,CAAC,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;AACnK,MAAM,OAAO,GAAG,CAAC,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACxH,MAAM,KAAK,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IACzC,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;IACnF,CAAC,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAChG,CAAC,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;CACrI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;IACZ,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;QACnB,OAAO,IAAI,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACpF,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,KAAK;QACzC,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1J,OAAO,IAAI,CAAC;AACd,CAAC,CAAC,CAAC;AACH,SAAS,OAAO,CAAC,KAAa,EAAE,GAAW,EAAE,IAAY;IACvD,MAAM,QAAQ,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC;IACtC,OAAO,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,IAAI,CAAC;AACxF,CAAC;AACD,MAAM,QAAQ,GAAG,CAAC,CAAC,YAAY,CAAC;IAC9B,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;IACpI,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,QAAQ,EAAE;IAChH,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,MAAM,CAAC;IACpG,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAClC,GAAG,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;IACpP,MAAM,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC3H,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,MAAM,CAAC;IACzF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,wBAAwB,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE;CACxH,CAAC,CAAC;AAGH,kGAAkG;AAClG,SAAS,SAAS,CAAC,KAAc;IAC/B,MAAM,OAAO,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IACtC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,OAAO,OAAO,CAAC,MAAM,EAAE,CAAC;QACtB,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,GAAG,EAAG,CAAC;QACxC,IAAI,EAAE,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC;YAC7B,OAAO,KAAK,CAAC;QACf,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS;YAC3E,SAAS;QACX,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACzB,OAAO,KAAK,CAAC;YACf,SAAS;QACX,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,QAAQ;YAC3B,OAAO,KAAK,CAAC;QACf,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QACzE,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,SAAS,IAAI,KAAK,KAAK,IAAI;YAClF,OAAO,KAAK,CAAC;QACf,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE;YAChD,OAAO,KAAK,CAAC;QACf,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,OAAO,GAAG,KAAK,QAAQ;gBACzB,OAAO,KAAK,CAAC;YACf,IAAI,KAAK,IAAI,GAAG,KAAK,QAAQ;gBAC3B,SAAS;YACX,MAAM,KAAK,GAAG,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,GAAG,CAAE,CAAC;YAC3D,IAAI,CAAC,CAAC,OAAO,IAAI,KAAK,CAAC;gBACrB,OAAO,KAAK,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AACD,MAAM,UAAU,sBAAsB,CAAC,KAAc;IAOnD,IAAI,CAAC;QACH,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;YACnB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC;QAClD,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACzC,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC;IACzG,CAAC;IACD,MAAM,CAAC;QACL,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAClD,CAAC;AACH,CAAC;AACD;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,QAAyC;IACtE,OAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC9E,CAAC;AACD,yHAAyH;AACzH,MAAM,UAAU,eAAe,CAAC,KAAsC;IACpE,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACrC,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IACvB,IAAI,CAAC;QAAC,OAAO,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAoC,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,KAAK,CAAC;IAAC,CAAC;AAC1I,CAAC;AACD,MAAM,CAAC,MAAM,aAAa,GAA0D,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,4CAA4C,EAAE,CAAC,CAAC;AAErL,+FAA+F;AAC/F,MAAM,UAAU,mBAAmB,CAAC,KAAwB,EAAE,YAAqB,EAAE;IAQnF,IAAI,CAAC;QACH,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,OAAO,SAAS,KAAK,QAAQ;YAClG,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAChD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC;QAClC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;YACtC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;gBAC7B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAClD,MAAM,MAAM,GAAqC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,GAAqC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACtI,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/C,IAAI,KAAK,GAAY,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,CAAE,SAAqC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAC/G,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBAC5C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,KAAK,KAAK,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC;oBAC7N,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;YAClD,CAAC;iBACI,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC3B,IAAI,OAAO,KAAK,KAAK,SAAS;oBAC5B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;YAClD,CAAC;iBACI,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;oBACxD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;YAClD,CAAC;iBACI,CAAC;gBACJ,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC;oBAC/D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;gBAChD,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;YAC9B,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,GAAG,KAAyB,CAAC;YACzC,IAAI,KAAK,KAAK,CAAC,CAAC,OAAO;gBACrB,OAAO,CAAC,IAAI,CAAC,GAAG,KAAyB,CAAC;QAC9C,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;IAClD,CAAC;IACD,MAAM,CAAC;QACL,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAChD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { WebChatButtons, WebChatHistory, WebChatMessage, WebDeliveryState } from "./web-chat-history.js";
|
|
2
|
+
export type GuestRouteState = "on" | "later";
|
|
3
|
+
export interface GuestRoute {
|
|
4
|
+
readonly methods: readonly string[];
|
|
5
|
+
readonly pattern: RegExp;
|
|
6
|
+
/** Where the instance is: a path group (decoded), a query parameter, or nothing (static, not per instance). */
|
|
7
|
+
readonly instance: {
|
|
8
|
+
readonly group: number;
|
|
9
|
+
} | {
|
|
10
|
+
readonly query: string;
|
|
11
|
+
} | null;
|
|
12
|
+
readonly state: GuestRouteState;
|
|
13
|
+
/** Why it is open, or which phase opens it and what it waits for. */
|
|
14
|
+
readonly note: string;
|
|
15
|
+
}
|
|
16
|
+
/** The design's table (#1920 §4). Everything else is 403 for a guest. */
|
|
17
|
+
export declare const GUEST_ROUTES: readonly GuestRoute[];
|
|
18
|
+
export type GuestRouteDecision = {
|
|
19
|
+
readonly kind: "allow";
|
|
20
|
+
readonly route: GuestRoute;
|
|
21
|
+
} | {
|
|
22
|
+
readonly kind: "deny";
|
|
23
|
+
readonly status: 403 | 404;
|
|
24
|
+
readonly error: "guest_forbidden" | "not found";
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* A guest's request: allowed (an `on` route, its instance in `scope`), 404 (an `on` per-instance route whose instance is
|
|
28
|
+
* not in scope, or is not a name at all), or 403 (anything else).
|
|
29
|
+
*/
|
|
30
|
+
export declare function guestRouteDecision(method: string, url: URL, scope: ReadonlySet<string>): GuestRouteDecision;
|
|
31
|
+
/** The same Discord or Telegram account (both sessions name one), for a guest's "my own sessions". */
|
|
32
|
+
export declare function sameAccount(a: {
|
|
33
|
+
readonly adapterId: string;
|
|
34
|
+
readonly userId: string;
|
|
35
|
+
} | undefined, b: {
|
|
36
|
+
readonly adapterId: string;
|
|
37
|
+
readonly userId: string;
|
|
38
|
+
} | undefined): boolean;
|
|
39
|
+
type Owner = {
|
|
40
|
+
readonly adapterId: string;
|
|
41
|
+
readonly userId: string;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* A guest request: whose, and its scope — asked anew each time (a long-lived stream follows a narrowed scope). `current`
|
|
45
|
+
* is the exact session that admitted it, still current (not revoked, expired or rotated away) — never "some cookie on the
|
|
46
|
+
* request still authenticates": another device's session must not keep a revoked one's stream alive (#2049 review).
|
|
47
|
+
*/
|
|
48
|
+
export interface GuestRequest {
|
|
49
|
+
readonly owner: Owner;
|
|
50
|
+
scope(): ReadonlySet<string>;
|
|
51
|
+
current(): boolean;
|
|
52
|
+
/** #1920 §5.2: an instance whose every message is this guest's to see — its own Telegram private room. */
|
|
53
|
+
ownRoom?(instance: string): boolean;
|
|
54
|
+
/** #1920 §5.2: the kept messages, to show a tick or a reply's buttons only on a message the guest may see. */
|
|
55
|
+
history?(): WebChatHistory | null;
|
|
56
|
+
/** #1920 §5.1: guests may chat (web.guests.chat, default true); false: read-only. Absent: read-only. */
|
|
57
|
+
chat?(): boolean;
|
|
58
|
+
/** #1920 §3.2: its stream connected — its rooms' membership is read again, in the background. */
|
|
59
|
+
streamOpened?(): void;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* #1920 §5.1 (step 2b): why a guest may not write to `instance` now, or null (not a guest, or allowed): out of scope is
|
|
63
|
+
* "not found" (another instance's name is never confirmed); read-only when the host says so.
|
|
64
|
+
*/
|
|
65
|
+
export declare function guestChatRefusal(guest: GuestRequest | undefined, instance: unknown): {
|
|
66
|
+
status: 403 | 404;
|
|
67
|
+
error: string;
|
|
68
|
+
} | null;
|
|
69
|
+
/** A guest never sends a command: text that starts (after spaces) with "/" is the platform's admin or command syntax. */
|
|
70
|
+
export declare const guestCommandText: (text: string) => boolean;
|
|
71
|
+
/**
|
|
72
|
+
* #1920 §4 (step 2b): the preferences a guest reads — the host's look and the guest's own; never one that names an
|
|
73
|
+
* instance (the sidebar's order, favourites, a card's size, the sidebar widget, names, the filter).
|
|
74
|
+
*/
|
|
75
|
+
export declare const GUEST_PREF_KEYS: ReadonlySet<string>;
|
|
76
|
+
export declare function guestPrefs<T extends {
|
|
77
|
+
values: Record<string, unknown>;
|
|
78
|
+
}>(view: T): T;
|
|
79
|
+
/** Set by the one entry that admits a guest (FleetManager's gate); read by the handlers that answer per recipient. */
|
|
80
|
+
export declare function bindGuestRequest(req: object, guest: GuestRequest): void;
|
|
81
|
+
export declare function guestRequestOf(req: object): GuestRequest | undefined;
|
|
82
|
+
export declare function guestStatus(status: unknown, scope: ReadonlySet<string>): {
|
|
83
|
+
instances: Array<Record<string, unknown>>;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Whether a guest sees one kept message: an in-scope instance's message that reached its channel (what the channel's
|
|
87
|
+
* members already saw), the guest's own, or anything in its own private room. Never someone else's web-only exchange,
|
|
88
|
+
* a cross-instance notice, a fleet status line, or a row kept from before these were recorded (they have no mark).
|
|
89
|
+
*/
|
|
90
|
+
export declare function guestSeesMessage(m: WebChatMessage, guest: GuestRequest, scope: ReadonlySet<string>): boolean;
|
|
91
|
+
/**
|
|
92
|
+
* A message as a guest gets it: without whose account wrote it (`mine` says it was the guest), and without another
|
|
93
|
+
* person's message id and ticks; never an effect Try (effects stay admin-only).
|
|
94
|
+
*/
|
|
95
|
+
export declare function guestMessage(m: WebChatMessage, guest: GuestRequest): Record<string, unknown>;
|
|
96
|
+
/**
|
|
97
|
+
* One stream event as a guest gets it, or undefined (not sent). Default deny:
|
|
98
|
+
* - the status (projected) and an in-scope instance's activity;
|
|
99
|
+
* - a chat message it may see (§5.2), a tick on one of its own messages, the buttons of a reply it may see;
|
|
100
|
+
* - never: the live reply receipt (effects), prompts (their nonces answer them), Needs you, the Log's ticks, traffic or
|
|
101
|
+
* apply progress.
|
|
102
|
+
* Without `guest` (no context) only the status and activity pass.
|
|
103
|
+
*/
|
|
104
|
+
export declare function guestFrameData(event: string, data: unknown, scope: ReadonlySet<string>, guest?: GuestRequest): unknown;
|
|
105
|
+
/** The ticks a guest is caught up with: its own messages' only. */
|
|
106
|
+
export declare function guestDeliveries(history: WebChatHistory, guest: GuestRequest, scope: ReadonlySet<string>): Array<{
|
|
107
|
+
instance: string;
|
|
108
|
+
messageId: string;
|
|
109
|
+
delivery: WebDeliveryState;
|
|
110
|
+
}>;
|
|
111
|
+
/** The ended (or open-poll) buttons a guest is caught up with: on replies it may see. */
|
|
112
|
+
export declare function guestButtonStates(history: WebChatHistory, guest: GuestRequest, scope: ReadonlySet<string>): Array<{
|
|
113
|
+
instance: string;
|
|
114
|
+
buttons: WebChatButtons;
|
|
115
|
+
}>;
|
|
116
|
+
/** A guest's replay (a reconnecting stream, a poll): what it may see of `rows`. */
|
|
117
|
+
export declare function guestMessages(rows: readonly WebChatMessage[], guest: GuestRequest, scope: ReadonlySet<string>): Array<Record<string, unknown>>;
|
|
118
|
+
/** /ui/history for a guest: the newest `limit` messages of one instance that it may see. */
|
|
119
|
+
export declare function guestHistory(history: WebChatHistory, instance: string, limit: number, guest: GuestRequest, scope: ReadonlySet<string>): Array<Record<string, unknown>>;
|
|
120
|
+
/**
|
|
121
|
+
* /ui/poll's answer for a guest: the projected status, and the chat it may see (the same rule as its stream) — with the
|
|
122
|
+
* cursor every poll hands out. Never prompts or Needs you.
|
|
123
|
+
*/
|
|
124
|
+
export declare function guestPollBody(status: unknown, scope: ReadonlySet<string>, now: number, guest?: GuestRequest, after?: string | null, replay?: (after: string | null) => readonly WebChatMessage[]): Record<string, unknown>;
|
|
125
|
+
export {};
|