@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
|
@@ -5,15 +5,18 @@ import { html, useEffect, useLayoutEffect, useRef, useState } from "./app-html.j
|
|
|
5
5
|
import { Icon } from "./ui-icons.js";
|
|
6
6
|
import { Toasts } from "./ui-toast.js";
|
|
7
7
|
import { ConfirmHost } from "./ui-confirm.js";
|
|
8
|
+
import { ColorDialogHost } from "./identity-color.js";
|
|
8
9
|
import { t, lang, setLang, onLang } from "./app-i18n.js";
|
|
9
|
-
import { appStore, createStore, useStore } from "./app-store.js";
|
|
10
|
+
import { appStore, createStore, guestBadge, guestPage, useStore } from "./app-store.js";
|
|
10
11
|
import { navStore } from "./app-nav.js";
|
|
11
|
-
import { chatPath, viewPath, settingsPath, routeKey, NEEDS_PATH,
|
|
12
|
+
import { chatPath, viewPath, settingsPath, routeKey, NEEDS_PATH, fleetEntryPath } from "./app-route.js";
|
|
12
13
|
import { SessionMenu } from "./app-session.js";
|
|
13
14
|
import { savePref } from "./app-prefs.js";
|
|
14
15
|
import { ErrorState, Skeleton } from "./ui-states.js";
|
|
15
16
|
import { InstanceNav, RosterNav, namesStore, setNamesPrimary } from "./instance-nav.js";
|
|
16
17
|
import { UsageRail, usageRailStore } from "./header-tools.js";
|
|
18
|
+
import { OwnerCssKeepBar } from "./owner-css.js";
|
|
19
|
+
import { AgentWidget, fleetBinds, sidebarWidget, sidebarWidgetStore } from "./agent-widget.js";
|
|
17
20
|
|
|
18
21
|
/** Shell state shared with panels: the phone drawer, the collapsed sidebar, extensions a panel module adds. */
|
|
19
22
|
export const shellStore = createStore({ drawer: false, collapsed: readCollapsed(), keyboard: false, dialog: null, side: null });
|
|
@@ -36,6 +39,25 @@ let newInstanceOpener = null;
|
|
|
36
39
|
export function setNewInstanceOpener(fn) { newInstanceOpener = fn; }
|
|
37
40
|
export function requestNewInstance() { if (newInstanceOpener) newInstanceOpener(); }
|
|
38
41
|
|
|
42
|
+
/**
|
|
43
|
+
* #2074: whether this page's session may make an agent — an admin's (/auth/session's tier); a guest's create is refused.
|
|
44
|
+
* Asked once per page; a session that ends takes the buttons away. A display hint only: the create route decides.
|
|
45
|
+
*/
|
|
46
|
+
export const canCreateStore = createStore({ value: false });
|
|
47
|
+
let canCreateOf = null; // the AgendAuth asked (one per page)
|
|
48
|
+
export function useCanCreate() {
|
|
49
|
+
const s = useStore(canCreateStore);
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
const auth = typeof window !== "undefined" ? window.AgendAuth : undefined;
|
|
52
|
+
if (!auth || typeof auth.canWrite !== "function" || canCreateOf === auth) return;
|
|
53
|
+
canCreateOf = auth;
|
|
54
|
+
canCreateStore.set({ value: false });
|
|
55
|
+
Promise.resolve(auth.canWrite()).then((v) => { if (canCreateOf === auth && !auth.sessionEnded?.()) canCreateStore.set({ value: v === true }); }, () => {});
|
|
56
|
+
auth.onSessionEnd?.(() => { if (canCreateOf === auth) canCreateStore.set({ value: false }); });
|
|
57
|
+
}, []);
|
|
58
|
+
return s.value;
|
|
59
|
+
}
|
|
60
|
+
|
|
39
61
|
/** An app-level dialog (New instance): rendered by the shell until closed, whatever panel is showing. */
|
|
40
62
|
export function showDialog(Component, props = {}) { shellStore.set({ dialog: { Component, props } }); }
|
|
41
63
|
export function closeDialog() { shellStore.set({ dialog: null }); }
|
|
@@ -175,7 +197,7 @@ function SidebarResize() {
|
|
|
175
197
|
handle.addEventListener("pointercancel", cancel);
|
|
176
198
|
handle.addEventListener("lostpointercapture", cancel);
|
|
177
199
|
};
|
|
178
|
-
return html`<div class="side-resize" role="separator" aria-orientation="vertical" tabindex="0" aria-controls="sidebar"
|
|
200
|
+
return html`<div data-trust="navigation" class="side-resize" role="separator" aria-orientation="vertical" tabindex="0" aria-controls="sidebar"
|
|
179
201
|
aria-label=${t("app.resizeSidebar")} title=${t("app.resizeSidebarHint")} aria-valuemin=${String(SIDEBAR_W.min)}
|
|
180
202
|
aria-valuemax=${String(clampSidebarWidth(Infinity, mainBudget()))} aria-valuenow=${String(now)}
|
|
181
203
|
onKeyDown=${onKey} onPointerDown=${onDown} ondblclick=${() => setSidebarWidth(null)}></div>`;
|
|
@@ -244,9 +266,8 @@ export function signInHref() {
|
|
|
244
266
|
function Sidebar({ route, onNewInstance, viewOnly }) {
|
|
245
267
|
const app = useStore(appStore);
|
|
246
268
|
const shell = useStore(shellStore);
|
|
247
|
-
|
|
248
|
-
const on = (panel) => !!route &&
|
|
249
|
-
const openInstance = openInstanceOf(route);
|
|
269
|
+
const canCreate = useCanCreate();
|
|
270
|
+
const on = (panel) => !!route && route.panel === panel;
|
|
250
271
|
// A count badge is hidden at 0; its number is also in the link's accessible name.
|
|
251
272
|
const navLink = (panel, href, icon, label, count = 0) => html`<a class=${`side-row${on(panel) ? " active" : ""}`} href=${href}
|
|
252
273
|
aria-current=${on(panel) ? "page" : undefined} aria-label=${count ? `${label} (${t("app.needsCount", count)})` : undefined} onClick=${closeDrawer}>
|
|
@@ -255,39 +276,55 @@ function Sidebar({ route, onNewInstance, viewOnly }) {
|
|
|
255
276
|
// View-only (an anonymous reader, #1408 §3): View and a way to sign in — nothing that needs a session is rendered.
|
|
256
277
|
if (viewOnly) {
|
|
257
278
|
return html`<aside id="sidebar" class="sidebar" aria-label=${t("app.menu")}>
|
|
258
|
-
<div class="side-head">
|
|
279
|
+
<div class="side-head" data-trust="navigation">
|
|
259
280
|
<a class="brand" href="/view" onClick=${closeDrawer}>${t("app.brand")}</a>
|
|
260
281
|
<button type="button" class="icon-btn side-collapse" onClick=${toggleSidebar} aria-label=${narrow() ? t("app.closeMenu") : t("app.collapse")} title=${narrow() ? t("app.closeMenu") : t("app.collapse")} aria-controls="sidebar"><${Icon} name="sidebar" /></button>
|
|
261
282
|
</div>
|
|
262
|
-
<nav class="side-nav" aria-label=${t("app.menu")}>${navLink("view", "/view", "view", t("app.view"))}</nav>
|
|
283
|
+
<nav data-trust="navigation" class="side-nav" aria-label=${t("app.menu")}>${navLink("view", "/view", "view", t("app.view"))}</nav>
|
|
263
284
|
${shell.side ? html`<${shell.side.Component} />` : html`<${ViewOnlyNav} route=${route} />`}
|
|
264
|
-
<div class="side-foot">
|
|
285
|
+
<div class="side-foot" data-trust="navigation">
|
|
265
286
|
<a class="side-row" href=${signInHref()}><${Icon} name="user" /><span>${t("app.signIn")}</span></a>
|
|
266
287
|
<${PrefsPopover} />
|
|
267
288
|
</div>
|
|
268
289
|
<${SidebarResize} />
|
|
269
290
|
</aside>`;
|
|
270
291
|
}
|
|
271
|
-
// #
|
|
272
|
-
//
|
|
292
|
+
// #1920 phase 3: a guest's sidebar — its own agents to pick from, who it is signed in as, and its session; no fleet,
|
|
293
|
+
// Needs you, View, Settings, new agent or widget (each is an admin's, and the server refuses a guest them anyway).
|
|
294
|
+
if (guestPage()) {
|
|
295
|
+
return html`<aside id="sidebar" class="sidebar" aria-label=${t("app.menu")}>
|
|
296
|
+
<div class="side-head" data-trust="navigation">
|
|
297
|
+
<a class="brand" href="/ui" onClick=${closeDrawer}>${t("app.brand")}</a>
|
|
298
|
+
<button type="button" class="icon-btn side-collapse" onClick=${toggleSidebar} aria-label=${narrow() ? t("app.closeMenu") : t("app.collapse")} title=${narrow() ? t("app.closeMenu") : t("app.collapse")} aria-controls="sidebar"><${Icon} name="sidebar" /></button>
|
|
299
|
+
</div>
|
|
300
|
+
<${InstanceNav} route=${route} items=${app.instances} loaded=${app.ready !== false} exec=${app.exec} awaiting=${app.awaiting} onPick=${closeDrawer} />
|
|
301
|
+
<div class="side-foot" data-trust="navigation">
|
|
302
|
+
<${GuestChip} />
|
|
303
|
+
<${SessionMenu} />
|
|
304
|
+
</div>
|
|
305
|
+
<${SidebarResize} />
|
|
306
|
+
</aside>`;
|
|
307
|
+
}
|
|
308
|
+
// #1675: the whole fleet, from anywhere — top left, so at the top of a phone's drawer too. #2183 (the user's call): the
|
|
309
|
+
// one Fleet entry ("Fleet" / "Fleet 概覽"), on the tab this device used last (the Org chart the first time); an agent's
|
|
310
|
+
// View, Log and Details are its header's tabs, so the sidebar has no "Fleet" (Details) or "View" row of its own.
|
|
273
311
|
const onFleet = !!route && route.panel === "fleet";
|
|
274
|
-
const overview = html`<a class=${`side-row side-overview${onFleet ? " active" : ""}`} href=${
|
|
312
|
+
const overview = html`<a class=${`side-row side-overview${onFleet ? " active" : ""}`} href=${fleetEntryPath(route)}
|
|
275
313
|
aria-current=${onFleet ? "page" : undefined} onClick=${closeDrawer}><${Icon} name="org" /><span class="grow">${t("app.fleetOverview")}</span></a>`;
|
|
276
314
|
return html`<aside id="sidebar" class="sidebar" aria-label=${t("app.menu")}>
|
|
277
|
-
<div class="side-head">
|
|
315
|
+
<div class="side-head" data-trust="navigation">
|
|
278
316
|
<a class="brand" href="/ui" onClick=${closeDrawer}>${t("app.brand")}</a>
|
|
279
317
|
<button type="button" class="icon-btn side-collapse" onClick=${toggleSidebar} aria-label=${narrow() ? t("app.closeMenu") : t("app.collapse")} title=${narrow() ? t("app.closeMenu") : t("app.collapse")} aria-controls="sidebar"><${Icon} name="sidebar" /></button>
|
|
280
|
-
<button type="button" class="icon-btn" onClick=${onNewInstance} aria-label=${t("app.newInstance")} title=${t("app.newInstance")}><${Icon} name="plus" /></button>
|
|
281
318
|
</div>
|
|
282
|
-
<nav class="side-nav" aria-label=${t("app.menu")}>
|
|
319
|
+
<nav data-trust="navigation" class="side-nav" aria-label=${t("app.menu")}>
|
|
283
320
|
${overview}
|
|
284
321
|
${navLink("needs", NEEDS_PATH, "inbox", t("app.needsNav"), needsCount)}
|
|
285
|
-
${
|
|
286
|
-
${navLink("view", "/view", "view", t("app.view"))}
|
|
322
|
+
${canCreate && onNewInstance ? html`<button type="button" class="side-row side-new" onClick=${onNewInstance}><${Icon} name="plus" /><span class="grow">${t("app.newAgent")}</span></button>` : null}
|
|
287
323
|
</nav>
|
|
288
324
|
${shell.side ? html`<${shell.side.Component} />` : html`<${InstanceNav} route=${route} items=${app.instances} loaded=${app.ready !== false}
|
|
289
325
|
exec=${app.exec} awaiting=${app.awaiting} onPick=${closeDrawer} />`}
|
|
290
|
-
|
|
326
|
+
<${SidebarWidget} app=${app} />
|
|
327
|
+
<div class="side-foot" data-trust="navigation">
|
|
291
328
|
${navLink("settings", settingsPath(), "settings", t("app.settings"))}
|
|
292
329
|
<${SessionMenu} />
|
|
293
330
|
</div>
|
|
@@ -295,6 +332,24 @@ function Sidebar({ route, onNewInstance, viewOnly }) {
|
|
|
295
332
|
</aside>`;
|
|
296
333
|
}
|
|
297
334
|
|
|
335
|
+
/** #1920 phase 3: "Guest · <name> (<platform>)" — who this guest's page is signed in as; what a guest sees, in its title. */
|
|
336
|
+
const PLATFORM_NAMES = { discord: "Discord", telegram: "Telegram" };
|
|
337
|
+
function GuestChip() {
|
|
338
|
+
const { name, platform } = guestBadge();
|
|
339
|
+
const where = PLATFORM_NAMES[platform] || platform;
|
|
340
|
+
const label = name ? (where ? t("app.guestAsOn", name, where) : t("app.guestAs", name)) : t("app.guestChip");
|
|
341
|
+
// Inside .side-foot (a marked, stock-trusted element): no trust marker of its own — effect-stock-trust's closed inventory
|
|
342
|
+
// refuses any element it does not know, which would hide a guest's static effect posters (#2101 review).
|
|
343
|
+
return html`<p class="guest-chip" title=${t("app.guestHint")}><${Icon} name="user" size=${14} /><span class="grow">${label}</span></p>`;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/** #1629 r4-4: the person's own sidebar widget (their synced preference), with the fleet's counts. */
|
|
347
|
+
function SidebarWidget({ app }) {
|
|
348
|
+
useStore(sidebarWidgetStore);
|
|
349
|
+
const widget = sidebarWidget();
|
|
350
|
+
return widget ? html`<div class="side-widget" data-trust="widget"><${AgentWidget} slot="sidebar" widget=${widget} binds=${fleetBinds(app.instances, app.exec, app.awaiting)} /></div>` : null;
|
|
351
|
+
}
|
|
352
|
+
|
|
298
353
|
/** The anonymous View reader's list: View's roster read (no status frames without a session), the same component. */
|
|
299
354
|
function ViewOnlyNav({ route }) {
|
|
300
355
|
return html`<${RosterNav} route=${route} viewOnly=${true} onPick=${closeDrawer} />`;
|
|
@@ -328,7 +383,7 @@ export function DevicePrefs({ labels = false } = {}) {
|
|
|
328
383
|
function PrefsPopover() {
|
|
329
384
|
return html`<details class="prefs-pop">
|
|
330
385
|
<summary class="icon-btn" aria-label=${t("app.devicePrefs")} title=${t("app.devicePrefs")}><${Icon} name="sun" /></summary>
|
|
331
|
-
<div class="pop" role="group" aria-label=${t("app.devicePrefs")}><${DevicePrefs} labels=${true} /></div>
|
|
386
|
+
<div data-trust="popover" class="pop" role="group" aria-label=${t("app.devicePrefs")}><${DevicePrefs} labels=${true} /></div>
|
|
332
387
|
</details>`;
|
|
333
388
|
}
|
|
334
389
|
|
|
@@ -336,20 +391,23 @@ function PrefsPopover() {
|
|
|
336
391
|
* The header every panel shows: ☰ (phone, or a collapsed sidebar), its title and status, then its actions. `nav`
|
|
337
392
|
* (#1523 N2): an instance page's view switch — beside the title on a wide screen, a row of tabs under it on a phone.
|
|
338
393
|
*/
|
|
339
|
-
export function PanelHeader({ title, sub, children, headingRef, nav }) {
|
|
394
|
+
export function PanelHeader({ title, sub, children, headingRef, nav, notice }) {
|
|
340
395
|
const shell = useStore(shellStore);
|
|
341
|
-
|
|
396
|
+
const canCreate = useCanCreate() && !!newInstanceOpener;
|
|
397
|
+
return html`<header data-trust="header" class=${`panel-head${shell.collapsed ? " collapsed" : ""}`}>
|
|
342
398
|
<button type="button" id="sbOpen" class="icon-btn sb-open" onClick=${() => (narrow() ? openDrawer() : toggleSidebar())}
|
|
343
399
|
aria-label=${narrow() ? t("app.openMenu") : t("app.expand")} title=${narrow() ? t("app.openMenu") : t("app.expand")} aria-controls="sidebar" aria-expanded=${shell.drawer ? "true" : "false"}><${Icon} name="menu" /></button>
|
|
400
|
+
${canCreate && shell.collapsed ? html`<button type="button" class="icon-btn sb-new" onClick=${requestNewInstance} aria-label=${t("app.newAgent")} title=${t("app.newAgent")}><${Icon} name="plus" /></button>` : null}
|
|
344
401
|
<div class="panel-title"><h1 ref=${headingRef} tabindex="-1">${title}</h1>${sub ? html`<div class="panel-sub">${sub}</div>` : null}</div>
|
|
345
402
|
${nav || null}
|
|
346
403
|
<div class="panel-actions">${children}</div>
|
|
404
|
+
${notice || null}
|
|
347
405
|
</header>`;
|
|
348
406
|
}
|
|
349
407
|
|
|
350
408
|
/**
|
|
351
|
-
* #1523 N2: the instance a page is about — Chat, View, Log (#1218) or Details of it — or null.
|
|
352
|
-
*
|
|
409
|
+
* #1523 N2: the instance a page is about — Chat, View, Log (#1218) or Details of it — or null. #2183: with one open, the
|
|
410
|
+
* phone's Chat tab is current and goes to its chat.
|
|
353
411
|
*/
|
|
354
412
|
export function openInstanceOf(route) {
|
|
355
413
|
return route && (route.panel === "chat" || route.panel === "view" || route.panel === "log" || route.panel === "details") && route.instance ? route.instance : null;
|
|
@@ -360,24 +418,28 @@ function BottomTabs({ route, viewOnly }) {
|
|
|
360
418
|
let last = null;
|
|
361
419
|
try { last = localStorage.getItem("agend_last_instance"); } catch { /* none */ }
|
|
362
420
|
const open = openInstanceOf(route);
|
|
363
|
-
|
|
421
|
+
// #2183: Chat stands for the open agent's pages (its View, Log and Details are the tabs under its header), so it goes to that agent's chat.
|
|
422
|
+
const chatHref = open ? chatPath(open) : last ? chatPath(last) : "/ui";
|
|
364
423
|
const anyAwaiting = Object.keys(app.awaiting).length;
|
|
365
424
|
const tab = (href, icon, label, active, badge, badgeLabel) => html`<a class=${`tab${active ? " active" : ""}`} href=${href} aria-current=${active ? "page" : undefined}>
|
|
366
425
|
<${Icon} name=${icon} size=${20} /><span>${label}</span>${badge ? html`<span class="tab-badge" aria-label=${badgeLabel || t("app.needsYou")}>${badge}</span>` : null}</a>`;
|
|
367
|
-
let lastView = null;
|
|
368
|
-
try { lastView = localStorage.getItem("agend_last_view"); } catch { /* none */ }
|
|
369
|
-
const viewHref = route && (route.panel === "view" || route.panel === "log" || route.panel === "details") && route.instance ? viewPath(route.instance) : viewPath(lastView);
|
|
370
426
|
if (viewOnly) {
|
|
371
|
-
|
|
427
|
+
let lastView = null;
|
|
428
|
+
try { lastView = localStorage.getItem("agend_last_view"); } catch { /* none */ }
|
|
429
|
+
const viewHref = route && route.panel === "view" && route.instance ? viewPath(route.instance) : viewPath(lastView);
|
|
430
|
+
return html`<nav data-trust="navigation" class="tabs" aria-label=${t("app.menu")}>
|
|
372
431
|
${tab(viewHref, "view", t("app.view"), route && route.panel === "view")}
|
|
373
432
|
${tab(signInHref(), "user", t("app.signIn"), false)}
|
|
374
433
|
</nav>`;
|
|
375
434
|
}
|
|
376
|
-
|
|
377
|
-
|
|
435
|
+
// #1920: a guest has only its chats (the drawer lists them): no tabs to switch between.
|
|
436
|
+
if (guestPage()) return null;
|
|
437
|
+
// #2183 (the user's call): four tabs — Chat (current on /ui and on any of an agent's pages), Needs you, Fleet (on its
|
|
438
|
+
// last tab), Settings.
|
|
439
|
+
return html`<nav data-trust="navigation" class="tabs" aria-label=${t("app.menu")}>
|
|
440
|
+
${tab(chatHref, "chat", t("app.chat"), !!open || (!!route && route.panel === "chat"), anyAwaiting)}
|
|
378
441
|
${tab(NEEDS_PATH, "inbox", t("app.needsTab"), route && route.panel === "needs", (app.needs || []).length, t("app.needsCount", (app.needs || []).length))}
|
|
379
|
-
${tab(
|
|
380
|
-
${tab(viewHref, "view", t("app.view"), route && route.panel === "view")}
|
|
442
|
+
${tab(fleetEntryPath(route), "fleet", t("app.fleet"), route && route.panel === "fleet")}
|
|
381
443
|
${tab(settingsPath(), "settings", t("app.settings"), route && route.panel === "settings")}
|
|
382
444
|
</nav>`;
|
|
383
445
|
}
|
|
@@ -386,7 +448,7 @@ function ConnectionLine() {
|
|
|
386
448
|
const { connection, hydration, retryHydration } = useStore(appStore);
|
|
387
449
|
// A late catch-up that is not done: the chat may be missing what was open before it loaded (#1425 review).
|
|
388
450
|
if (hydration === "retrying" || hydration === "failed") {
|
|
389
|
-
return html`<div class="conn" role="status">${hydration === "failed" ? t("app.hydrateFailed") : t("app.hydrating")}
|
|
451
|
+
return html`<div data-trust="status" class="conn" role="status">${hydration === "failed" ? t("app.hydrateFailed") : t("app.hydrating")}
|
|
390
452
|
${hydration === "failed" && retryHydration ? html` <button type="button" class="btn btn-sm" onClick=${() => retryHydration()}>${t("app.retry")}</button>` : null}</div>`;
|
|
391
453
|
}
|
|
392
454
|
if (connection === "reconnecting") return html`<${Reconnecting} />`;
|
|
@@ -400,7 +462,7 @@ function Reconnecting() {
|
|
|
400
462
|
const { retryAt } = useStore(appStore);
|
|
401
463
|
useTick(true);
|
|
402
464
|
const s = typeof retryAt === "number" ? Math.max(0, Math.ceil((retryAt - NOW()) / 1000)) : 0;
|
|
403
|
-
return html`<div class="conn reconnecting" role="status">${s > 0 ? t("app.connReconnectingIn", s) : t("app.connReconnecting")}</div>`;
|
|
465
|
+
return html`<div data-trust="status" class="conn reconnecting" role="status">${s > 0 ? t("app.connReconnectingIn", s) : t("app.connReconnecting")}</div>`;
|
|
404
466
|
}
|
|
405
467
|
|
|
406
468
|
const NOW = () => (typeof performance !== "undefined" ? performance.now() : Date.now());
|
|
@@ -424,8 +486,21 @@ export function PendingChanges({ inline = false } = {}) {
|
|
|
424
486
|
const { pendingChanges } = useStore(appStore);
|
|
425
487
|
const list = pendingChanges || [];
|
|
426
488
|
useTick(list.some(p => p.state === "pending"));
|
|
489
|
+
// #2168: inline (Settings' own column), a request that has just started waiting is brought into view — on a phone the
|
|
490
|
+
// person applied far down the list, and the card that says where to confirm it sat above the screen. Once per request.
|
|
491
|
+
const box = useRef(null), shown = useRef(new Set());
|
|
492
|
+
useEffect(() => {
|
|
493
|
+
if (!inline || !box.current) return;
|
|
494
|
+
for (const p of list) {
|
|
495
|
+
if (p.state !== "pending" || shown.current.has(p.id)) continue;
|
|
496
|
+
shown.current.add(p.id);
|
|
497
|
+
const card = box.current.querySelector(`[data-pending="${p.id}"]`);
|
|
498
|
+
const still = typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
499
|
+
if (card && typeof card.scrollIntoView === "function") card.scrollIntoView({ block: "nearest", behavior: still ? "auto" : "smooth" });
|
|
500
|
+
}
|
|
501
|
+
});
|
|
427
502
|
if (!list.length) return null;
|
|
428
|
-
return html`<div class=${`pending-stack${inline ? " inline" : ""}`} role="region" aria-label=${t("app.pendingTitle")}>${list.map(p => html`<section key=${p.id} class=${`pending-card ${p.state}`} role="status">
|
|
503
|
+
return html`<div data-trust="confirmation" ref=${box} class=${`pending-stack${inline ? " inline" : ""}`} role="region" aria-label=${t("app.pendingTitle")}>${list.map(p => html`<section key=${p.id} data-pending=${p.id} class=${`pending-card ${p.state}`} role="status">
|
|
429
504
|
<div class="pending-head"><${Icon} name=${p.state === "applied" ? "check" : p.state === "pending" || p.state === "applying" ? "clock" : "alert"} size=${16} />
|
|
430
505
|
<strong>${t(`app.pending_${p.state}`)}</strong>
|
|
431
506
|
${p.state === "pending" ? html`<span class="pending-left">${t("app.pendingLeft", mmss(p.deadline - NOW()))}</span>` : null}
|
|
@@ -450,7 +525,7 @@ function OperationLine({ route }) {
|
|
|
450
525
|
: op.phase === "posting" || op.phase === "watching" ? t("app.opApplying")
|
|
451
526
|
: op.phase === "failed" ? t("app.opFailed") : restart ? t("app.opRestart") : failedRows ? t("app.opPartial") : t("app.opDone");
|
|
452
527
|
const busy = op.phase === "writing" || op.phase === "posting" || op.phase === "watching";
|
|
453
|
-
return html`<div class=${`conn op-line${busy ? "" : op.phase === "failed" || restart || failedRows ? " bad" : " ok"}`} role="status">
|
|
528
|
+
return html`<div data-trust="status" class=${`conn op-line${busy ? "" : op.phase === "failed" || restart || failedRows ? " bad" : " ok"}`} role="status">
|
|
454
529
|
<span>${text}</span> <a class="btn btn-sm" href=${settingsPath()}>${t("app.openSettings")}</a></div>`;
|
|
455
530
|
}
|
|
456
531
|
|
|
@@ -497,21 +572,24 @@ export function Shell({ panels, onNewInstance, viewOnly = false }) {
|
|
|
497
572
|
vv.addEventListener("resize", onResize);
|
|
498
573
|
return () => vv.removeEventListener("resize", onResize);
|
|
499
574
|
}, []);
|
|
500
|
-
const
|
|
575
|
+
const guest = guestPage(); // #1920: a guest's page — no operations, usage, pending changes or owner CSS
|
|
576
|
+
const cls = ["shell", shell.collapsed ? "sb-collapsed" : "", shell.drawer ? "sb-open" : "", shell.keyboard ? "kb-open" : "", guest ? "guest" : ""].filter(Boolean).join(" ");
|
|
501
577
|
return html`<div class=${cls}>
|
|
502
|
-
<a class="skip" href="#main">${t("app.skip")}</a>
|
|
578
|
+
<a data-trust="navigation" class="skip" href="#main">${t("app.skip")}</a>
|
|
503
579
|
<${Sidebar} route=${nav.route} onNewInstance=${onNewInstance} viewOnly=${viewOnly} />
|
|
504
580
|
<div class="scrim" onClick=${closeDrawer} aria-hidden="true"></div>
|
|
505
581
|
<main id="main" class="main" tabindex="-1" inert=${shell.drawer && narrow() ? true : undefined}>
|
|
506
582
|
<${ConnectionLine} />
|
|
507
|
-
${viewOnly ? null : html`<${OperationLine} route=${nav.route} />`}
|
|
583
|
+
${viewOnly || guest ? null : html`<${OperationLine} route=${nav.route} />`}
|
|
508
584
|
<${Outlet} route=${nav.route} seq=${nav.seq} panels=${panels} />
|
|
509
585
|
</main>
|
|
510
|
-
|
|
586
|
+
${guest ? null : html`<${UsageRail} route=${nav.route} />`}
|
|
511
587
|
<${BottomTabs} route=${nav.route} viewOnly=${viewOnly} />
|
|
512
588
|
${shell.dialog ? html`<${shell.dialog.Component} ...${shell.dialog.props} onClose=${closeDialog} />` : null}
|
|
513
|
-
${viewOnly || (nav.route && nav.route.panel === "settings") ? null : html`<${PendingChanges} />`}
|
|
589
|
+
${viewOnly || guest || (nav.route && nav.route.panel === "settings") ? null : html`<${PendingChanges} />`}
|
|
514
590
|
<${ConfirmHost} />
|
|
591
|
+
<${ColorDialogHost} />
|
|
592
|
+
${viewOnly || guest ? null : html`<${OwnerCssKeepBar} />`}
|
|
515
593
|
<${Toasts} />
|
|
516
594
|
</div>`;
|
|
517
595
|
}
|
|
@@ -26,6 +26,20 @@ export function createStore(initial) {
|
|
|
26
26
|
export const appStore = createStore({ ready: false, instances: [], uptime: 0, exec: {}, awaiting: {}, connection: "connecting", needs: [], connections: null,
|
|
27
27
|
hydration: "none", retryHydration: null });
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* #1920 phase 3: this page is a guest's — the server says so on <body> (data-tier="guest"). A guest sees only its own
|
|
31
|
+
* agents' chats: no fleet, Needs you, View, Settings, filters, commands or new agent, and nothing it may not read is asked
|
|
32
|
+
* for (each would be refused). The server checks every request regardless; this only keeps the page to what works.
|
|
33
|
+
*/
|
|
34
|
+
export function guestPage() {
|
|
35
|
+
return typeof document !== "undefined" && !!document.body && document.body.dataset.tier === "guest";
|
|
36
|
+
}
|
|
37
|
+
/** Who a guest's page is signed in as: its web name and its platform (the server's, on <body>). */
|
|
38
|
+
export function guestBadge() {
|
|
39
|
+
const d = typeof document !== "undefined" && document.body ? document.body.dataset : {};
|
|
40
|
+
return { name: d.guestName || "", platform: d.guestPlatform || "" };
|
|
41
|
+
}
|
|
42
|
+
|
|
29
43
|
/** Fold one status frame (stream or poll) into the store. */
|
|
30
44
|
export function applyStatus(d) {
|
|
31
45
|
if (!d || !Array.isArray(d.instances)) return;
|
|
@@ -39,8 +53,21 @@ export function applyStatus(d) {
|
|
|
39
53
|
connections: typeof d.connections === "number" ? d.connections : null,
|
|
40
54
|
// #1665: the host preferences' revision (app-prefs.js re-reads them when it moves).
|
|
41
55
|
prefsRev: typeof d.prefs_rev === "number" ? d.prefs_rev : null,
|
|
56
|
+
// #1629: the agents' themes' revision (app-themes.js re-reads them when it moves).
|
|
57
|
+
themesRev: typeof d.themes_rev === "number" ? d.themes_rev : null,
|
|
42
58
|
// #1685: host memory pressure slowing or holding new agents ("elevated" | "critical"), else null.
|
|
43
|
-
hostMemory: d.host_memory === "elevated" || d.host_memory === "critical" ? d.host_memory : null
|
|
59
|
+
hostMemory: d.host_memory === "elevated" || d.host_memory === "critical" ? d.host_memory : null,
|
|
60
|
+
// #2015: while it lasts, the largest processes in the fleet and whose they are (at most 3; anything else dropped).
|
|
61
|
+
hostMemoryTop: hostMemoryTop(d.host_memory_top) });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** #2015: the status frame's host_memory_top, as the dashboard keeps it: well-formed entries only, at most 3. */
|
|
65
|
+
export function hostMemoryTop(raw) {
|
|
66
|
+
if (!Array.isArray(raw)) return [];
|
|
67
|
+
return raw.slice(0, 3).flatMap(p => p && typeof p.name === "string" && Number.isSafeInteger(p.pid) && Number.isSafeInteger(p.rssBytes) && p.rssBytes >= 0
|
|
68
|
+
&& ["fleet", "tmux", "instance", "other"].includes(p.owner)
|
|
69
|
+
? [{ name: p.name.slice(0, 64), pid: p.pid, rssBytes: p.rssBytes, owner: p.owner, ...(p.owner === "instance" && typeof p.instance === "string" ? { instance: p.instance.slice(0, 128) } : {}) }]
|
|
70
|
+
: []);
|
|
44
71
|
}
|
|
45
72
|
|
|
46
73
|
/** One "activity" event: an instance started or stopped working. */
|
|
@@ -30,7 +30,9 @@
|
|
|
30
30
|
// - suspend()/resume(): the page is leaving (pagehide) / came back from the back-forward cache.
|
|
31
31
|
|
|
32
32
|
// #1218: steps_tick — an instance's transcript moved while a Log watches it (SSE only: a poll page asks the Log itself).
|
|
33
|
-
|
|
33
|
+
// #1918: traffic — a message between instances moved; delegation — a task opened, or its report closed it (SSE only: the
|
|
34
|
+
// org canvas reads /ui/traffic when it has no stream).
|
|
35
|
+
const EVENTS = ["status", "message", "agent_reply_live", "delivery", "deliveries", "prompt", "prompts", "prompt_resolved", "activity", "needs", "reply_buttons", "steps_tick", "clock", "traffic", "delegation"];
|
|
34
36
|
const MAX_HELD = 1000; // live events held during one catch-up read; more → read again afterwards
|
|
35
37
|
const RETRY_DELAYS = [1000, 2000, 4000]; // after the first failed catch-up read; then it waits for Retry
|
|
36
38
|
const POLL_LIMIT_MS = 10000; // a poll that has not answered by then counts as failed
|
|
@@ -68,17 +70,20 @@ export function createStream(opts) {
|
|
|
68
70
|
const set = listeners.get(name);
|
|
69
71
|
if (set) for (const fn of [...set]) { try { fn(data, extra); } catch (e) { if (env.console) env.console.error(e); } }
|
|
70
72
|
}
|
|
73
|
+
function sseIngress() {
|
|
74
|
+
try { return Object.freeze({ source: "sse", receivedAt: now() }); } catch { return undefined; }
|
|
75
|
+
}
|
|
71
76
|
function setConnection(c) { if (state.connection !== c) { state.connection = c; emit("connection", c); } }
|
|
72
77
|
function setHydration(h) { if (state.hydration !== h) { state.hydration = h; emit("hydration", h); } }
|
|
73
78
|
|
|
74
79
|
/** A live event: delivered now, or held (in order) while a catch-up snapshot is on its way. */
|
|
75
|
-
function live(name, data, cursor) {
|
|
80
|
+
function live(name, data, cursor, extra) {
|
|
76
81
|
if (held) {
|
|
77
|
-
if (held.length < MAX_HELD) held.push([name, data, cursor]); else held.overflow = true;
|
|
82
|
+
if (held.length < MAX_HELD) held.push([name, data, cursor, extra]); else held.overflow = true;
|
|
78
83
|
return;
|
|
79
84
|
}
|
|
80
85
|
if (cursor) state.cursor = cursor;
|
|
81
|
-
emit(name, data);
|
|
86
|
+
emit(name, data, extra);
|
|
82
87
|
// A full set of open prompts arrives on every (re)connect: whatever a failed catch-up missed is current again.
|
|
83
88
|
if (name === "prompts" && (state.hydration === "failed" || state.hydration === "retrying") && !catching) setHydration("ok");
|
|
84
89
|
}
|
|
@@ -86,7 +91,7 @@ export function createStream(opts) {
|
|
|
86
91
|
const list = held;
|
|
87
92
|
held = null;
|
|
88
93
|
if (!list) return false;
|
|
89
|
-
for (const [name, data, cursor] of list) { if (cursor) state.cursor = cursor; emit(name, data); }
|
|
94
|
+
for (const [name, data, cursor, extra] of list) { if (cursor) state.cursor = cursor; emit(name, data, extra); }
|
|
90
95
|
return !!list.overflow;
|
|
91
96
|
}
|
|
92
97
|
|
|
@@ -116,7 +121,7 @@ export function createStream(opts) {
|
|
|
116
121
|
if (closed || mine !== pollSeq) return false;
|
|
117
122
|
if (typeof d.now === "number") emit("clock", { now: d.now }); // #1823: read just now, handed over at once
|
|
118
123
|
if (d.status) emit("status", d.status);
|
|
119
|
-
for (const m of d.messages || []) emit("message", m);
|
|
124
|
+
for (const m of d.messages || []) emit("message", m, { source: "poll" });
|
|
120
125
|
if (typeof d.cursor === "string") state.cursor = d.cursor;
|
|
121
126
|
if (Array.isArray(d.deliveries)) emit("deliveries", d.deliveries);
|
|
122
127
|
if (Array.isArray(d.prompts)) emit("prompts", d.prompts);
|
|
@@ -206,13 +211,15 @@ export function createStream(opts) {
|
|
|
206
211
|
for (const name of EVENTS) {
|
|
207
212
|
es.addEventListener(name, (e) => {
|
|
208
213
|
if (es !== sse) return; // a stream this page already let go of
|
|
214
|
+
// Snapshot before parsing or any synchronous connection/hydration observer can consume time.
|
|
215
|
+
const ingress = name === "message" || name === "agent_reply_live" ? sseIngress() : undefined;
|
|
209
216
|
let data;
|
|
210
217
|
try { data = JSON.parse(e.data); } catch { return; }
|
|
211
218
|
if (!spoke) { spoke = true; alive(); if (again) catchUp(); }
|
|
212
219
|
else alive();
|
|
213
220
|
// #1823: a clock reading is about now, not about order: it is never held behind a catch-up (it would be stale).
|
|
214
221
|
if (name === "clock") { emit(name, data); return; }
|
|
215
|
-
live(name, data, name === "message" ? e.lastEventId : null);
|
|
222
|
+
live(name, data, name === "message" ? e.lastEventId : null, ingress);
|
|
216
223
|
});
|
|
217
224
|
}
|
|
218
225
|
es.onerror = () => {
|