@songsid/agend 2.2.0 → 2.2.5
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 +10 -0
- package/dist/daemon.js +327 -31
- 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 +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 +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/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-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,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #1920 phase 1: what a guest web session may reach — default deny. A guest is a non-admin signed in as their own
|
|
3
|
+
* Discord or Telegram account; its scope (the instances it may see) is derived on every request (phase 2) and never
|
|
4
|
+
* stored. This module is the table and the decision; FleetManager applies it at the one entry every web request passes
|
|
5
|
+
* (the local listener and the public link's gateway), before any handler.
|
|
6
|
+
*
|
|
7
|
+
* - A route not on GUEST_ROUTES: 403 `guest_forbidden` — a new route is closed to guests until someone classifies it.
|
|
8
|
+
* - A route on it that names an instance out of scope: 404 (another instance's name is never confirmed).
|
|
9
|
+
* - An entry is `on` only once what it serves is safe for a guest. `later` entries are the design's (#1920 §4) and say
|
|
10
|
+
* which phase opens them; until then they answer 403 like any other route.
|
|
11
|
+
* - Phase 1b: a guest's request carries its guest context (bindGuestRequest) for the handlers that answer per recipient —
|
|
12
|
+
* the stream, the poll, a file — and their projections are here, default deny like the table.
|
|
13
|
+
*
|
|
14
|
+
* The `/auth/*` self routes (who am I, my devices, sign out) are not here: they are public by path and answer each
|
|
15
|
+
* caller about their own account only (auth-api.ts).
|
|
16
|
+
*/
|
|
17
|
+
import { shellRoute } from "./web-shell-routes.js";
|
|
18
|
+
const READS = ["GET", "HEAD"];
|
|
19
|
+
const NAME = "([^/]+)";
|
|
20
|
+
/** The design's table (#1920 §4). Everything else is 403 for a guest. */
|
|
21
|
+
export const GUEST_ROUTES = [
|
|
22
|
+
// The app shell and its code: static (the shell boots in guest mode in phase 3).
|
|
23
|
+
{ methods: READS, pattern: /^\/ui$/, instance: null, state: "on", note: "the app shell (static)" },
|
|
24
|
+
{ methods: READS, pattern: new RegExp(`^/ui/chat/${NAME}$`), instance: { group: 1 }, state: "on", note: "the app shell for one chat (static; out of scope: 404)" },
|
|
25
|
+
{ methods: ["GET"], pattern: /^\/ui\/js\/[a-z0-9_-]+\.js$/, instance: null, state: "on", note: "the panels' code (static)" },
|
|
26
|
+
// What a member of the channel already sees of the instance: its profile, avatar, identity card and theme pictures.
|
|
27
|
+
{ methods: READS, pattern: new RegExp(`^/api/(?:profile|avatar)/${NAME}$`), instance: { group: 1 }, state: "on", note: "the instance's profile and avatar" },
|
|
28
|
+
{ methods: READS, pattern: new RegExp(`^/api/card/${NAME}(?:/(?:portrait|banner))?$`), instance: { group: 1 }, state: "on", note: "the instance's identity card" },
|
|
29
|
+
{ methods: ["GET"], pattern: new RegExp(`^/ui/img/(?:avatar|bot)/${NAME}$`), instance: { group: 1 }, state: "on", note: "the instance's face in the sidebar" },
|
|
30
|
+
{ methods: ["GET"], pattern: new RegExp(`^/ui/img/theme/${NAME}/[0-9a-f]{32}$`), instance: { group: 1 }, state: "on", note: "the instance's theme pictures" },
|
|
31
|
+
{ methods: ["GET"], pattern: /^\/ui\/effect-posters$/, instance: { query: "instance" }, state: "on", note: "the instance's static effect posters (the list)" },
|
|
32
|
+
{ methods: ["GET"], pattern: /^\/ui\/effects\/placements$/, instance: { query: "instance" }, state: "on", note: "current in-scope Chat effect metadata only, with a session epoch" },
|
|
33
|
+
{ methods: ["GET"], pattern: /^\/ui\/effects\/resource\/[0-9a-f]{32}$/, instance: { query: "instance" }, state: "on", note: "a current in-scope Chat effect resource, never library or personal-slot reads" },
|
|
34
|
+
// Opened by phase 1b: the stream and the poll filtered per recipient; a file bound to its instance.
|
|
35
|
+
// The stream and the poll, projected per recipient (guestFrameData / guestPollBody); a file, bound to its stored
|
|
36
|
+
// instance by the handler (404 out of scope: an id from another instance is useless).
|
|
37
|
+
{ methods: ["GET"], pattern: /^\/ui\/events$/, instance: null, state: "on", note: "the stream, projected for this guest (guestFrameData)" },
|
|
38
|
+
{ methods: ["GET"], pattern: /^\/ui\/poll$/, instance: null, state: "on", note: "the poll, projected for this guest (guestPollBody)" },
|
|
39
|
+
{ methods: ["GET"], pattern: /^\/ui\/file\/[^/]+$/, instance: null, state: "on", note: "a file, served only when its stored instance is in scope (the handler checks)" },
|
|
40
|
+
{ methods: ["GET"], pattern: /^\/ui\/effect-posters\/[0-9a-f]{32}\.png$/, instance: { query: "instance" }, state: "on", note: "a placed effect's static poster, bound to its instance by the query" },
|
|
41
|
+
// Opened by phase 2: what needs the guest's own identity, authority and the history rule.
|
|
42
|
+
{ methods: ["GET"], pattern: /^\/ui\/history$/, instance: { query: "instance" }, state: "on", note: "an in-scope instance's history, as its channel showed it (guestHistory, #1920 §5.2)" },
|
|
43
|
+
// Phase 2 (step 2b): chat as on the platform — authority none, never a command (guestChatRefusal, in the handlers).
|
|
44
|
+
{ methods: ["POST"], pattern: /^\/ui\/send$/, instance: null, state: "on", note: "a message to an in-scope instance (the handler checks the body's instance and web.guests.chat); never a command" },
|
|
45
|
+
{ methods: ["POST"], pattern: /^\/ui\/upload$/, instance: { query: "instance" }, state: "on", note: "a file for an in-scope instance's message (web.guests.chat)" },
|
|
46
|
+
{ methods: ["POST"], pattern: /^\/ui\/reply-button$/, instance: null, state: "on", note: "a click on a reply the guest may see (the handler checks; web.guests.chat)" },
|
|
47
|
+
{ methods: ["POST"], pattern: new RegExp(`^/ui/cancel/${NAME}$`), instance: { group: 1 }, state: "on", note: "Cancel, as the platform's button lets anyone allowed there (web.guests.chat)" },
|
|
48
|
+
{ methods: ["GET"], pattern: /^\/ui\/prefs$/, instance: null, state: "on", note: "the host's look (theme, language, shown settings) and the guest's own — nothing that names an instance (guestPrefs)" },
|
|
49
|
+
{ methods: ["POST"], pattern: /^\/ui\/prefs$/, instance: null, state: "later", note: "phase 3: what a guest may keep of its own" },
|
|
50
|
+
{ methods: ["GET", "POST"], pattern: /^\/ui\/profile$/, instance: null, state: "on", note: "the guest's own web name (its account's, never anyone else's)" },
|
|
51
|
+
];
|
|
52
|
+
/** An instance name from a path segment, or null when it is not one (the shell's own rule). */
|
|
53
|
+
function segmentName(path) {
|
|
54
|
+
const m = shellRoute("GET", `/ui/chat/${path}`);
|
|
55
|
+
return m && m.kind === "shell" && m.route.panel === "chat" ? m.route.instance : null;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* A guest's request: allowed (an `on` route, its instance in `scope`), 404 (an `on` per-instance route whose instance is
|
|
59
|
+
* not in scope, or is not a name at all), or 403 (anything else).
|
|
60
|
+
*/
|
|
61
|
+
export function guestRouteDecision(method, url, scope) {
|
|
62
|
+
const m = (method || "GET").toUpperCase();
|
|
63
|
+
for (const route of GUEST_ROUTES) {
|
|
64
|
+
if (!route.methods.includes(m))
|
|
65
|
+
continue;
|
|
66
|
+
const match = route.pattern.exec(url.pathname);
|
|
67
|
+
if (!match)
|
|
68
|
+
continue;
|
|
69
|
+
if (route.state !== "on")
|
|
70
|
+
break;
|
|
71
|
+
if (route.instance === null)
|
|
72
|
+
return { kind: "allow", route };
|
|
73
|
+
const name = "group" in route.instance ? segmentName(match[route.instance.group]) : url.searchParams.get(route.instance.query);
|
|
74
|
+
if (name && scope.has(name))
|
|
75
|
+
return { kind: "allow", route };
|
|
76
|
+
return { kind: "deny", status: 404, error: "not found" };
|
|
77
|
+
}
|
|
78
|
+
return { kind: "deny", status: 403, error: "guest_forbidden" };
|
|
79
|
+
}
|
|
80
|
+
/** The same Discord or Telegram account (both sessions name one), for a guest's "my own sessions". */
|
|
81
|
+
export function sameAccount(a, b) {
|
|
82
|
+
return !!a && !!b && a.adapterId === b.adapterId && a.userId === b.userId;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* #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
|
|
86
|
+
* "not found" (another instance's name is never confirmed); read-only when the host says so.
|
|
87
|
+
*/
|
|
88
|
+
export function guestChatRefusal(guest, instance) {
|
|
89
|
+
if (!guest)
|
|
90
|
+
return null;
|
|
91
|
+
if (typeof instance !== "string" || !guest.scope().has(instance))
|
|
92
|
+
return { status: 404, error: "not found" };
|
|
93
|
+
if (guest.chat?.() !== true)
|
|
94
|
+
return { status: 403, error: "guest_read_only" };
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
/** A guest never sends a command: text that starts (after spaces) with "/" is the platform's admin or command syntax. */
|
|
98
|
+
export const guestCommandText = (text) => /^\s*\//.test(text);
|
|
99
|
+
/**
|
|
100
|
+
* #1920 §4 (step 2b): the preferences a guest reads — the host's look and the guest's own; never one that names an
|
|
101
|
+
* instance (the sidebar's order, favourites, a card's size, the sidebar widget, names, the filter).
|
|
102
|
+
*/
|
|
103
|
+
export const GUEST_PREF_KEYS = new Set(["theme", "lang", "fx.show", "card.size", "color.show", "color.off", "fx.sidebar", "fx.header", "fx.page", "fx.box", "fx.cursor"]);
|
|
104
|
+
export function guestPrefs(view) {
|
|
105
|
+
const values = {};
|
|
106
|
+
for (const [k, v] of Object.entries(view.values))
|
|
107
|
+
if (GUEST_PREF_KEYS.has(k))
|
|
108
|
+
values[k] = v;
|
|
109
|
+
return { ...view, values };
|
|
110
|
+
}
|
|
111
|
+
const guestRequests = new WeakMap();
|
|
112
|
+
/** Set by the one entry that admits a guest (FleetManager's gate); read by the handlers that answer per recipient. */
|
|
113
|
+
export function bindGuestRequest(req, guest) { guestRequests.set(req, guest); }
|
|
114
|
+
export function guestRequestOf(req) { return guestRequests.get(req); }
|
|
115
|
+
/**
|
|
116
|
+
* What a guest's status frame keeps of each in-scope instance: who it is and how it looks, its state — not its model,
|
|
117
|
+
* backend, effort, cost, context, description, tags or what it is waiting for (a prompt's text). And nothing of the
|
|
118
|
+
* fleet: no public link, connections, uptime, host memory, revisions.
|
|
119
|
+
*/
|
|
120
|
+
const STATUS_FIELDS = ["name", "display_name", "avatar", "accent", "theme_avatar", "theme_accent", "card_v", "effect_chat_v", "color", "color_show", "status", "state", "execution_state"];
|
|
121
|
+
export function guestStatus(status, scope) {
|
|
122
|
+
const list = status && typeof status === "object" && Array.isArray(status.instances) ? status.instances : [];
|
|
123
|
+
const instances = [];
|
|
124
|
+
for (const raw of list) {
|
|
125
|
+
if (!raw || typeof raw !== "object")
|
|
126
|
+
continue;
|
|
127
|
+
const i = raw;
|
|
128
|
+
if (typeof i.name !== "string" || !scope.has(i.name))
|
|
129
|
+
continue;
|
|
130
|
+
const out = {};
|
|
131
|
+
for (const k of STATUS_FIELDS)
|
|
132
|
+
if (Object.prototype.hasOwnProperty.call(i, k) && i[k] !== undefined)
|
|
133
|
+
out[k] = i[k];
|
|
134
|
+
instances.push(out);
|
|
135
|
+
}
|
|
136
|
+
return { instances };
|
|
137
|
+
}
|
|
138
|
+
// ── Phase 2: the chat, as the channel showed it (#1920 §5.2) ──
|
|
139
|
+
const accountOf = (o) => `${o.adapterId}:${o.userId}`;
|
|
140
|
+
/**
|
|
141
|
+
* Whether a guest sees one kept message: an in-scope instance's message that reached its channel (what the channel's
|
|
142
|
+
* members already saw), the guest's own, or anything in its own private room. Never someone else's web-only exchange,
|
|
143
|
+
* a cross-instance notice, a fleet status line, or a row kept from before these were recorded (they have no mark).
|
|
144
|
+
*/
|
|
145
|
+
export function guestSeesMessage(m, guest, scope) {
|
|
146
|
+
if (!scope.has(m.instance))
|
|
147
|
+
return false;
|
|
148
|
+
return m.channel === true || m.from === accountOf(guest.owner) || guest.ownRoom?.(m.instance) === true;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* A message as a guest gets it: without whose account wrote it (`mine` says it was the guest), and without another
|
|
152
|
+
* person's message id and ticks; never an effect Try (effects stay admin-only).
|
|
153
|
+
*/
|
|
154
|
+
export function guestMessage(m, guest) {
|
|
155
|
+
const { from, channel: _channel, messageId, delivery, effectTrial: _trial, seenSeq: _seen, ...rest } = m;
|
|
156
|
+
void _channel;
|
|
157
|
+
void _trial;
|
|
158
|
+
void _seen;
|
|
159
|
+
const mine = from === accountOf(guest.owner);
|
|
160
|
+
// #2085 review: a click's `text` is what the agent was given — the button's value too, which the platform never
|
|
161
|
+
// shows. A guest gets the label, as the channel showed it.
|
|
162
|
+
const click = rest.click ? { text: rest.click.label } : {};
|
|
163
|
+
return { ...rest, ...click, ...(mine ? { mine: true } : {}), ...(mine && messageId ? { messageId } : {}), ...(mine && delivery ? { delivery } : {}) };
|
|
164
|
+
}
|
|
165
|
+
const visibleList = (rows, guest, scope) => rows.filter((m) => !m.effectTrial && guestSeesMessage(m, guest, scope)).map((m) => guestMessage(m, guest));
|
|
166
|
+
/**
|
|
167
|
+
* One stream event as a guest gets it, or undefined (not sent). Default deny:
|
|
168
|
+
* - the status (projected) and an in-scope instance's activity;
|
|
169
|
+
* - a chat message it may see (§5.2), a tick on one of its own messages, the buttons of a reply it may see;
|
|
170
|
+
* - never: the live reply receipt (effects), prompts (their nonces answer them), Needs you, the Log's ticks, traffic or
|
|
171
|
+
* apply progress.
|
|
172
|
+
* Without `guest` (no context) only the status and activity pass.
|
|
173
|
+
*/
|
|
174
|
+
export function guestFrameData(event, data, scope, guest) {
|
|
175
|
+
if (event === "status")
|
|
176
|
+
return guestStatus(data, scope);
|
|
177
|
+
const d = data && typeof data === "object" ? data : {};
|
|
178
|
+
if (event === "activity")
|
|
179
|
+
return typeof d.instance === "string" && scope.has(d.instance) ? { instance: d.instance, state: d.state ?? null } : undefined;
|
|
180
|
+
if (!guest)
|
|
181
|
+
return undefined;
|
|
182
|
+
if (event === "message") {
|
|
183
|
+
const m = data;
|
|
184
|
+
return typeof m?.instance === "string" && guestSeesMessage(m, guest, scope) ? guestMessage(m, guest) : undefined;
|
|
185
|
+
}
|
|
186
|
+
const history = guest.history?.();
|
|
187
|
+
if (!history || typeof d.instance !== "string" || !scope.has(d.instance))
|
|
188
|
+
return undefined;
|
|
189
|
+
if (event === "delivery") {
|
|
190
|
+
const own = typeof d.messageId === "string" ? history.findByMessageId(d.instance, d.messageId) : undefined;
|
|
191
|
+
return own && own.from === accountOf(guest.owner) ? { instance: d.instance, messageId: d.messageId, delivery: d.delivery } : undefined;
|
|
192
|
+
}
|
|
193
|
+
if (event === "reply_buttons") {
|
|
194
|
+
const id = d.buttons && typeof d.buttons === "object" ? d.buttons.id : undefined;
|
|
195
|
+
const row = typeof id === "string" ? history.findByButtons(d.instance, id) : undefined;
|
|
196
|
+
return row && guestSeesMessage(row, guest, scope) ? { instance: d.instance, buttons: d.buttons } : undefined;
|
|
197
|
+
}
|
|
198
|
+
return undefined;
|
|
199
|
+
}
|
|
200
|
+
/** The ticks a guest is caught up with: its own messages' only. */
|
|
201
|
+
export function guestDeliveries(history, guest, scope) {
|
|
202
|
+
return history.deliveries().filter((t) => scope.has(t.instance) && history.findByMessageId(t.instance, t.messageId)?.from === accountOf(guest.owner));
|
|
203
|
+
}
|
|
204
|
+
/** The ended (or open-poll) buttons a guest is caught up with: on replies it may see. */
|
|
205
|
+
export function guestButtonStates(history, guest, scope) {
|
|
206
|
+
return history.buttonStates().filter((b) => { const row = history.findByButtons(b.instance, b.buttons.id); return !!row && guestSeesMessage(row, guest, scope); });
|
|
207
|
+
}
|
|
208
|
+
/** A guest's replay (a reconnecting stream, a poll): what it may see of `rows`. */
|
|
209
|
+
export function guestMessages(rows, guest, scope) {
|
|
210
|
+
return visibleList(rows, guest, scope);
|
|
211
|
+
}
|
|
212
|
+
/** /ui/history for a guest: the newest `limit` messages of one instance that it may see. */
|
|
213
|
+
export function guestHistory(history, instance, limit, guest, scope) {
|
|
214
|
+
return visibleList(history.list(instance), guest, scope).slice(-limit);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* /ui/poll's answer for a guest: the projected status, and the chat it may see (the same rule as its stream) — with the
|
|
218
|
+
* cursor every poll hands out. Never prompts or Needs you.
|
|
219
|
+
*/
|
|
220
|
+
export function guestPollBody(status, scope, now, guest, after, replay) {
|
|
221
|
+
const history = guest?.history?.() ?? null;
|
|
222
|
+
if (!guest || !history || !replay)
|
|
223
|
+
return { status: guestStatus(status, scope), messages: [], deliveries: [], reply_buttons: [], prompts: [], needs: [], cursor: null, now };
|
|
224
|
+
return {
|
|
225
|
+
status: guestStatus(status, scope),
|
|
226
|
+
messages: guestMessages(replay(after ?? null), guest, scope),
|
|
227
|
+
deliveries: guestDeliveries(history, guest, scope),
|
|
228
|
+
reply_buttons: guestButtonStates(history, guest, scope),
|
|
229
|
+
prompts: [], needs: [],
|
|
230
|
+
cursor: history.pollCursor(),
|
|
231
|
+
now,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=web-guest-access.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-guest-access.js","sourceRoot":"","sources":["../src/web-guest-access.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #1920 §3.2: a guest's ClassicBot group or guild rooms — in scope only while its membership is verified.
|
|
3
|
+
*
|
|
4
|
+
* The answers are read in the background (at sign-in, every ten minutes, and when the guest's stream connects) and
|
|
5
|
+
* kept in memory; a request only reads them, never the platform. A room is shown only on a "member" answer at most
|
|
6
|
+
* 15 minutes old; an unknown, failed or stale answer hides it (fail closed).
|
|
7
|
+
*
|
|
8
|
+
* Revocation needs more than "hidden": a scope that becomes empty ends the session, and an answer not read yet (a
|
|
9
|
+
* restart, a room just created) must not end it. A key with no answer is pending for at most the stale window from
|
|
10
|
+
* when it was first wanted; after that, and after a "not a member" answer, it is settled.
|
|
11
|
+
*/
|
|
12
|
+
import type { ClassicChannel } from "./classic-channel-manager.js";
|
|
13
|
+
export interface GuestOwner {
|
|
14
|
+
readonly adapterId: string;
|
|
15
|
+
readonly userId: string;
|
|
16
|
+
}
|
|
17
|
+
/** A ClassicBot room a guest may be a member of: a Telegram group or a Discord channel, on the guest's connection. */
|
|
18
|
+
export interface GuestRoom {
|
|
19
|
+
readonly instance: string;
|
|
20
|
+
readonly adapterId: string;
|
|
21
|
+
readonly channelId: string;
|
|
22
|
+
readonly kind: "telegram" | "discord";
|
|
23
|
+
}
|
|
24
|
+
/** The adapter's read: true a member, false not (a definite answer); a rejection or anything else is no answer. */
|
|
25
|
+
export type RoomMemberRead = (room: GuestRoom, userId: string) => Promise<boolean> | undefined;
|
|
26
|
+
export declare const GUEST_ROOM_RECHECK_MS: number;
|
|
27
|
+
export declare const GUEST_ROOM_STALE_MS: number;
|
|
28
|
+
export declare const GUEST_ROOM_FORCE_FLOOR_MS = 60000;
|
|
29
|
+
/** A read a request started (a pending guest polling or retrying): at most one per key in this long, whatever the volume. */
|
|
30
|
+
export declare const GUEST_ROOM_TRIGGER_FLOOR_MS = 30000;
|
|
31
|
+
/** Failed reads back off — a minute, then 2, 4, 8 … — up to ten minutes (a bot without the permission, or removed). */
|
|
32
|
+
export declare const GUEST_ROOM_RETRY_MS = 60000;
|
|
33
|
+
export declare const GUEST_ROOM_RETRY_MAX_MS: number;
|
|
34
|
+
/** Consecutive failures after which a key's failure is persistent: said once (onPersistentFailure), not every attempt. */
|
|
35
|
+
export declare const GUEST_ROOM_PERSISTENT_FAILURES = 3;
|
|
36
|
+
/** The background tick runs this often and reads only what is due. */
|
|
37
|
+
export declare const GUEST_ROOM_TICK_MS = 60000;
|
|
38
|
+
/**
|
|
39
|
+
* The group rooms on this guest's own connection. A Telegram private room (a positive id) is not here: it is the
|
|
40
|
+
* account's own room or someone else's, never a membership question.
|
|
41
|
+
*/
|
|
42
|
+
export declare function guestGroupRooms(rooms: readonly ClassicChannel[], owner: GuestOwner): GuestRoom[];
|
|
43
|
+
/** Who reads: the background pass (what is due), a request of a pending guest (rate-limited), a stream connecting. */
|
|
44
|
+
export type GuestRoomReadMode = "scheduled" | "triggered" | "force";
|
|
45
|
+
export declare class GuestRoomMembership {
|
|
46
|
+
private readonly opts;
|
|
47
|
+
private readonly entries;
|
|
48
|
+
private readonly reads;
|
|
49
|
+
constructor(opts: {
|
|
50
|
+
now: () => number;
|
|
51
|
+
read: RoomMemberRead;
|
|
52
|
+
deadlineMs?: number;
|
|
53
|
+
staleMs?: number;
|
|
54
|
+
recheckMs?: number;
|
|
55
|
+
/** A key's reads keep failing (said once, until an answer); and when it answers again after that. */
|
|
56
|
+
onPersistentFailure?: (room: GuestRoom, failures: number) => void;
|
|
57
|
+
onRecovered?: (room: GuestRoom) => void;
|
|
58
|
+
});
|
|
59
|
+
private key;
|
|
60
|
+
private get staleMs();
|
|
61
|
+
/** Shown: a "member" answer no older than the stale window. */
|
|
62
|
+
verified(room: GuestRoom, userId: string): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Not settled yet: no definite answer, and first wanted less than the stale window ago (or never — a key nobody
|
|
65
|
+
* asked about yet is pending, and starts its window here). A pending room keeps an emptied scope from ending the
|
|
66
|
+
* session; it never shows the room.
|
|
67
|
+
*/
|
|
68
|
+
pending(room: GuestRoom, userId: string): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Read this guest's rooms, one at a time; never rejects. One read per key at a time.
|
|
71
|
+
* - "scheduled": what is due (never asked; ten minutes after an answer; a failure's backoff).
|
|
72
|
+
* - "triggered" (a pending guest's request): the same, and never within 30 s of the key's last read, so a guest that
|
|
73
|
+
* polls or retries is not platform traffic.
|
|
74
|
+
* - "force" (its stream connected): a minute after the key's last read — but a failing key keeps its backoff.
|
|
75
|
+
*/
|
|
76
|
+
refresh(owner: GuestOwner, rooms: readonly GuestRoom[], opts?: {
|
|
77
|
+
mode?: GuestRoomReadMode;
|
|
78
|
+
}): Promise<void>;
|
|
79
|
+
private ask;
|
|
80
|
+
private readBounded;
|
|
81
|
+
private put;
|
|
82
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { inferClassicChannelType } from "./classic-channel-manager.js";
|
|
2
|
+
export const GUEST_ROOM_RECHECK_MS = 10 * 60_000;
|
|
3
|
+
export const GUEST_ROOM_STALE_MS = 15 * 60_000;
|
|
4
|
+
export const GUEST_ROOM_FORCE_FLOOR_MS = 60_000;
|
|
5
|
+
/** A read a request started (a pending guest polling or retrying): at most one per key in this long, whatever the volume. */
|
|
6
|
+
export const GUEST_ROOM_TRIGGER_FLOOR_MS = 30_000;
|
|
7
|
+
/** Failed reads back off — a minute, then 2, 4, 8 … — up to ten minutes (a bot without the permission, or removed). */
|
|
8
|
+
export const GUEST_ROOM_RETRY_MS = 60_000;
|
|
9
|
+
export const GUEST_ROOM_RETRY_MAX_MS = 10 * 60_000;
|
|
10
|
+
/** Consecutive failures after which a key's failure is persistent: said once (onPersistentFailure), not every attempt. */
|
|
11
|
+
export const GUEST_ROOM_PERSISTENT_FAILURES = 3;
|
|
12
|
+
/** The background tick runs this often and reads only what is due. */
|
|
13
|
+
export const GUEST_ROOM_TICK_MS = 60_000;
|
|
14
|
+
const READ_DEADLINE_MS = 5_000;
|
|
15
|
+
/** The guest caps (4 per account, 64 in all) bound the owners; this bounds a fleet with very many rooms. */
|
|
16
|
+
const MAX_ENTRIES = 8192;
|
|
17
|
+
/**
|
|
18
|
+
* The group rooms on this guest's own connection. A Telegram private room (a positive id) is not here: it is the
|
|
19
|
+
* account's own room or someone else's, never a membership question.
|
|
20
|
+
*/
|
|
21
|
+
export function guestGroupRooms(rooms, owner) {
|
|
22
|
+
const out = [];
|
|
23
|
+
for (const room of rooms) {
|
|
24
|
+
if (room.adapterId !== owner.adapterId)
|
|
25
|
+
continue;
|
|
26
|
+
const kind = inferClassicChannelType(room.channelId);
|
|
27
|
+
if (kind === "telegram" && room.channelId.trim().startsWith("-"))
|
|
28
|
+
out.push({ instance: room.instanceName, adapterId: room.adapterId, channelId: room.channelId, kind });
|
|
29
|
+
else if (kind === "discord")
|
|
30
|
+
out.push({ instance: room.instanceName, adapterId: room.adapterId, channelId: room.channelId, kind });
|
|
31
|
+
}
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
export class GuestRoomMembership {
|
|
35
|
+
opts;
|
|
36
|
+
entries = new Map();
|
|
37
|
+
reads = new Map();
|
|
38
|
+
constructor(opts) {
|
|
39
|
+
this.opts = opts;
|
|
40
|
+
}
|
|
41
|
+
key(room, userId) { return `${room.adapterId}\u0000${room.channelId}\u0000${userId}`; }
|
|
42
|
+
get staleMs() { return this.opts.staleMs ?? GUEST_ROOM_STALE_MS; }
|
|
43
|
+
/** Shown: a "member" answer no older than the stale window. */
|
|
44
|
+
verified(room, userId) {
|
|
45
|
+
const e = this.entries.get(this.key(room, userId));
|
|
46
|
+
return !!e && e.member === true && this.opts.now() - e.at <= this.staleMs;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Not settled yet: no definite answer, and first wanted less than the stale window ago (or never — a key nobody
|
|
50
|
+
* asked about yet is pending, and starts its window here). A pending room keeps an emptied scope from ending the
|
|
51
|
+
* session; it never shows the room.
|
|
52
|
+
*/
|
|
53
|
+
pending(room, userId) {
|
|
54
|
+
const k = this.key(room, userId), now = this.opts.now();
|
|
55
|
+
let e = this.entries.get(k);
|
|
56
|
+
if (!e) {
|
|
57
|
+
e = { member: null, at: now, asked: Number.NEGATIVE_INFINITY, due: Number.NEGATIVE_INFINITY, failures: 0, reported: false };
|
|
58
|
+
this.put(k, e);
|
|
59
|
+
}
|
|
60
|
+
return e.member === null && now - e.at < this.staleMs;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Read this guest's rooms, one at a time; never rejects. One read per key at a time.
|
|
64
|
+
* - "scheduled": what is due (never asked; ten minutes after an answer; a failure's backoff).
|
|
65
|
+
* - "triggered" (a pending guest's request): the same, and never within 30 s of the key's last read, so a guest that
|
|
66
|
+
* polls or retries is not platform traffic.
|
|
67
|
+
* - "force" (its stream connected): a minute after the key's last read — but a failing key keeps its backoff.
|
|
68
|
+
*/
|
|
69
|
+
async refresh(owner, rooms, opts = {}) {
|
|
70
|
+
const mode = opts.mode ?? "scheduled";
|
|
71
|
+
for (const room of rooms) {
|
|
72
|
+
const k = this.key(room, owner.userId), now = this.opts.now();
|
|
73
|
+
const e = this.entries.get(k);
|
|
74
|
+
// A read in flight is never repeated: a scheduled refresh waits for it; the others skip it (asked just now).
|
|
75
|
+
if (e) {
|
|
76
|
+
const sinceAsked = now - e.asked;
|
|
77
|
+
if (mode === "force" ? sinceAsked < GUEST_ROOM_FORCE_FLOOR_MS || (e.failures > 0 && now < e.due)
|
|
78
|
+
: now < e.due || (mode === "triggered" && sinceAsked < GUEST_ROOM_TRIGGER_FLOOR_MS))
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
await (this.reads.get(k) ?? this.ask(k, room, owner.userId));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
ask(k, room, userId) {
|
|
85
|
+
const started = this.opts.now();
|
|
86
|
+
const existing = this.entries.get(k);
|
|
87
|
+
const recheck = this.opts.recheckMs ?? GUEST_ROOM_RECHECK_MS;
|
|
88
|
+
const fresh = { member: null, at: started, asked: started, due: started, failures: 0, reported: false };
|
|
89
|
+
this.put(k, existing ? { ...existing, asked: started } : fresh);
|
|
90
|
+
const read = this.readBounded(room, userId).then((member) => {
|
|
91
|
+
const e = this.entries.get(k) ?? fresh;
|
|
92
|
+
const now = this.opts.now();
|
|
93
|
+
if (member === undefined) {
|
|
94
|
+
// A failure leaves the last answer to age (and hide the room when stale), and backs off: 1, 2, 4 … 10 min.
|
|
95
|
+
const failures = e.failures + 1;
|
|
96
|
+
const reported = failures >= GUEST_ROOM_PERSISTENT_FAILURES; // an answer resets both
|
|
97
|
+
this.put(k, { ...e, failures, reported, due: now + Math.min(GUEST_ROOM_RETRY_MAX_MS, GUEST_ROOM_RETRY_MS * 2 ** (failures - 1)) });
|
|
98
|
+
if (reported && !e.reported)
|
|
99
|
+
this.opts.onPersistentFailure?.(room, failures);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
this.put(k, { member, at: now, asked: e.asked, due: now + recheck, failures: 0, reported: false });
|
|
103
|
+
if (e.reported)
|
|
104
|
+
this.opts.onRecovered?.(room);
|
|
105
|
+
}).finally(() => this.reads.delete(k));
|
|
106
|
+
this.reads.set(k, read);
|
|
107
|
+
return read;
|
|
108
|
+
}
|
|
109
|
+
readBounded(room, userId) {
|
|
110
|
+
return new Promise((resolve) => {
|
|
111
|
+
const timer = setTimeout(() => resolve(undefined), this.opts.deadlineMs ?? READ_DEADLINE_MS);
|
|
112
|
+
timer.unref?.();
|
|
113
|
+
let asked;
|
|
114
|
+
try {
|
|
115
|
+
asked = this.opts.read(room, userId);
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
asked = undefined;
|
|
119
|
+
}
|
|
120
|
+
if (!asked) {
|
|
121
|
+
clearTimeout(timer);
|
|
122
|
+
resolve(undefined);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
asked.then((m) => { clearTimeout(timer); resolve(m === true ? true : m === false ? false : undefined); }, () => { clearTimeout(timer); resolve(undefined); });
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
put(k, e) {
|
|
129
|
+
this.entries.delete(k); // re-insert: the map's order is its age, for the bound below
|
|
130
|
+
this.entries.set(k, e);
|
|
131
|
+
while (this.entries.size > MAX_ENTRIES)
|
|
132
|
+
this.entries.delete(this.entries.keys().next().value);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=web-guest-rooms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-guest-rooms.js","sourceRoot":"","sources":["../src/web-guest-rooms.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type Database from "better-sqlite3";
|
|
2
|
+
import { type ThemeMode } from "./web-theme.js";
|
|
3
|
+
import { type IdentityColor, type Placement } from "./web-identity-palette.js";
|
|
4
|
+
export { AUTO_PALETTE, autoIdentityColor, canonicalIdentityColor, canonicalPlacements, DEFAULT_PLACEMENTS, IDENTITY_PALETTE, identityColorValue, PLACEMENTS, type AutoId, type IdentityColor, type Placement, type PresetId } from "./web-identity-palette.js";
|
|
5
|
+
/** The sidebar's own background (src/ui/shared/tokens.css --bg-sidebar), where names are drawn as well as the page's. */
|
|
6
|
+
export declare const SIDEBAR_BG: Record<ThemeMode, string>;
|
|
7
|
+
export type IdentityColorSource = "person" | "agent" | "role" | "auto";
|
|
8
|
+
export type PlacementSource = "person" | "agent" | "host";
|
|
9
|
+
/**
|
|
10
|
+
* The shade of `hex` that name text uses on a page in `mode`: the colour itself if it reads at 4.5:1 against the
|
|
11
|
+
* page's and the sidebar's backgrounds, else the nearest step toward black (light page) or white (dark page) that does.
|
|
12
|
+
*/
|
|
13
|
+
export declare function readableShade(hex: string, mode: ThemeMode): string;
|
|
14
|
+
/** The tiers one instance has, as the status frame carries them (`auto` always). */
|
|
15
|
+
export interface IdentityColorTiers {
|
|
16
|
+
person?: IdentityColor;
|
|
17
|
+
agent?: string;
|
|
18
|
+
role?: string;
|
|
19
|
+
auto: IdentityColor;
|
|
20
|
+
}
|
|
21
|
+
/** The placement tiers one instance has (the host's default is the viewer's prefs, not the instance's). */
|
|
22
|
+
export interface PlacementTiers {
|
|
23
|
+
person?: Placement[];
|
|
24
|
+
agent?: Placement[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The colour in force and where it comes from. `showThemes`: whether the viewer shows agents' themes (fx.show, not
|
|
28
|
+
* safe mode) — when not, the agent's tier is skipped, as the rest of the agent's theme is.
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolveIdentityColor(t: IdentityColorTiers, opts: {
|
|
31
|
+
showThemes: boolean;
|
|
32
|
+
}): {
|
|
33
|
+
color: IdentityColor;
|
|
34
|
+
source: IdentityColorSource;
|
|
35
|
+
};
|
|
36
|
+
/** Where the colour shows: a person's choice, else the agent's (themes shown), else the host's default, else all three (DEFAULT_PLACEMENTS). */
|
|
37
|
+
export declare function resolvePlacements(t: PlacementTiers, opts: {
|
|
38
|
+
showThemes: boolean;
|
|
39
|
+
hostDefault?: unknown;
|
|
40
|
+
}): {
|
|
41
|
+
show: Placement[];
|
|
42
|
+
source: PlacementSource;
|
|
43
|
+
};
|
|
44
|
+
/** A person's choice for one instance: a colour, the places it shows, or both (null: not chosen — the next tier). */
|
|
45
|
+
export interface PersonIdentity {
|
|
46
|
+
color: IdentityColor | null;
|
|
47
|
+
show: Placement[] | null;
|
|
48
|
+
}
|
|
49
|
+
export type ColorWrite = {
|
|
50
|
+
ok: true;
|
|
51
|
+
} | {
|
|
52
|
+
ok: false;
|
|
53
|
+
status: 400 | 503;
|
|
54
|
+
error: string;
|
|
55
|
+
detail?: string;
|
|
56
|
+
};
|
|
57
|
+
/** The people's choices, one row per instance. */
|
|
58
|
+
export declare class IdentityColorStore {
|
|
59
|
+
private readonly openDb;
|
|
60
|
+
private readonly now;
|
|
61
|
+
constructor(openDb: () => Database.Database, now?: () => number);
|
|
62
|
+
get(name: string): PersonIdentity;
|
|
63
|
+
/** Every choice, for a status read: only when profiles.db exists and has the table — a read creates nothing. */
|
|
64
|
+
static all(dataDir: string, openDb: () => Database.Database): Map<string, PersonIdentity>;
|
|
65
|
+
/**
|
|
66
|
+
* A person's choice, field by field: only the fields given change; `null` (or "" for the colour) clears one — the next
|
|
67
|
+
* tier shows again. Both checked before anything is written. A row with nothing left is removed.
|
|
68
|
+
*/
|
|
69
|
+
set(name: string, patch: {
|
|
70
|
+
color?: unknown;
|
|
71
|
+
show?: unknown;
|
|
72
|
+
}): ColorWrite;
|
|
73
|
+
/** The patch, checked: `undefined` for a field not given, `null` to clear it. Writes nothing. */
|
|
74
|
+
check(patch: {
|
|
75
|
+
color?: unknown;
|
|
76
|
+
show?: unknown;
|
|
77
|
+
}): {
|
|
78
|
+
ok: true;
|
|
79
|
+
color?: IdentityColor | null;
|
|
80
|
+
show?: Placement[] | null;
|
|
81
|
+
} | {
|
|
82
|
+
ok: false;
|
|
83
|
+
status: 400;
|
|
84
|
+
error: string;
|
|
85
|
+
detail: string;
|
|
86
|
+
};
|
|
87
|
+
}
|