@songsid/agend 2.2.1 → 2.3.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-cli-instructions.md +5 -2
- package/dist/agent-cli.js +284 -2
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.d.ts +2 -0
- package/dist/agent-endpoint.js +29 -0
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-file-read.d.ts +38 -0
- package/dist/agent-file-read.js +317 -0
- package/dist/agent-file-read.js.map +1 -0
- package/dist/agent-whats-new.d.ts +11 -0
- package/dist/agent-whats-new.js +29 -2
- package/dist/agent-whats-new.js.map +1 -1
- package/dist/atomic-write.js +9 -1
- package/dist/atomic-write.js.map +1 -1
- package/dist/auth-api.d.ts +30 -1
- package/dist/auth-api.js +61 -12
- package/dist/auth-api.js.map +1 -1
- package/dist/authority/authority-state.d.ts +38 -0
- package/dist/authority/authority-state.js +114 -0
- package/dist/authority/authority-state.js.map +1 -0
- package/dist/authority/session-authorizations.d.ts +43 -0
- package/dist/authority/session-authorizations.js +102 -0
- package/dist/authority/session-authorizations.js.map +1 -0
- package/dist/authority/web-authority.d.ts +120 -0
- package/dist/authority/web-authority.js +157 -0
- package/dist/authority/web-authority.js.map +1 -0
- package/dist/backend/antigravity.js +3 -3
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-code.d.ts +2 -2
- package/dist/backend/claude-code.js +10 -5
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/launch-effort.js +1 -1
- package/dist/backend/launch-effort.js.map +1 -1
- package/dist/backend/muse.js +10 -2
- package/dist/backend/muse.js.map +1 -1
- package/dist/backend/types.d.ts +14 -0
- package/dist/backend/types.js +25 -0
- package/dist/backend/types.js.map +1 -1
- package/dist/backend-availability.d.ts +120 -0
- package/dist/backend-availability.js +396 -0
- package/dist/backend-availability.js.map +1 -0
- package/dist/backend-command.d.ts +21 -3
- package/dist/backend-command.js +23 -4
- package/dist/backend-command.js.map +1 -1
- package/dist/bundled-skills.d.ts +14 -0
- package/dist/bundled-skills.js +29 -0
- package/dist/bundled-skills.js.map +1 -0
- package/dist/cache-analysis.d.ts +47 -1
- package/dist/cache-analysis.js +68 -8
- package/dist/cache-analysis.js.map +1 -1
- package/dist/cache-ledger.d.ts +16 -3
- package/dist/cache-ledger.js +33 -13
- package/dist/cache-ledger.js.map +1 -1
- package/dist/cache-report-tool.d.ts +17 -0
- package/dist/cache-report-tool.js +40 -0
- package/dist/cache-report-tool.js.map +1 -0
- package/dist/cache-service.d.ts +70 -3
- package/dist/cache-service.js +178 -17
- package/dist/cache-service.js.map +1 -1
- package/dist/channel/adapters/discord.d.ts +9 -0
- package/dist/channel/adapters/discord.js +52 -2
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +8 -1
- package/dist/channel/adapters/telegram.js +74 -4
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/mcp-tools.js +48 -2
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/types.d.ts +21 -0
- package/dist/classic-channel-manager.d.ts +10 -5
- package/dist/classic-channel-manager.js +12 -9
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli.js +130 -31
- package/dist/cli.js.map +1 -1
- package/dist/config-validator.js +119 -4
- package/dist/config-validator.js.map +1 -1
- package/dist/daemon.d.ts +5 -0
- package/dist/daemon.js +273 -22
- package/dist/daemon.js.map +1 -1
- package/dist/decision-list.d.ts +25 -0
- package/dist/decision-list.js +30 -0
- package/dist/decision-list.js.map +1 -0
- package/dist/delivery-outbox.d.ts +10 -0
- package/dist/delivery-outbox.js +12 -1
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/fleet-context.d.ts +15 -0
- package/dist/fleet-manager.d.ts +506 -11
- package/dist/fleet-manager.js +1784 -130
- package/dist/fleet-manager.js.map +1 -1
- package/dist/fleet-traffic.d.ts +74 -0
- package/dist/fleet-traffic.js +196 -0
- package/dist/fleet-traffic.js.map +1 -0
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +20 -5
- package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +6 -1
- package/dist/general-knowledge/skills/multi-channel/SKILL.md +3 -2
- package/dist/general-knowledge/skills/persona-emoji/SKILL.md +1 -1
- package/dist/general-knowledge/skills/web-appearance/SKILL.md +492 -0
- package/dist/general-knowledge/skills/web-dashboard/SKILL.md +476 -0
- package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +1 -1
- package/dist/human-delivery-receipts.d.ts +24 -1
- package/dist/human-delivery-receipts.js +64 -11
- package/dist/human-delivery-receipts.js.map +1 -1
- package/dist/instance-avatar.js +3 -0
- package/dist/instance-avatar.js.map +1 -1
- package/dist/instance-config-impact.js +6 -1
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.js +9 -4
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instance-names.d.ts +4 -0
- package/dist/instance-names.js +12 -0
- package/dist/instance-names.js.map +1 -0
- package/dist/instructions.d.ts +12 -1
- package/dist/instructions.js +13 -2
- package/dist/instructions.js.map +1 -1
- package/dist/locale.js +100 -8
- package/dist/locale.js.map +1 -1
- package/dist/ls-attach-resolve.d.ts +95 -0
- package/dist/ls-attach-resolve.js +174 -0
- package/dist/ls-attach-resolve.js.map +1 -0
- package/dist/memory-hogs.d.ts +27 -0
- package/dist/memory-hogs.js +124 -0
- package/dist/memory-hogs.js.map +1 -0
- package/dist/needs-you-hub.d.ts +4 -0
- package/dist/needs-you-hub.js +31 -6
- package/dist/needs-you-hub.js.map +1 -1
- package/dist/needs-you.d.ts +1 -13
- package/dist/needs-you.js +3 -37
- package/dist/needs-you.js.map +1 -1
- package/dist/outbound-handlers.d.ts +15 -0
- package/dist/outbound-handlers.js +152 -11
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +228 -4
- package/dist/outbound-schemas.js +147 -1
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/public-web-gateway.js +21 -1
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/public-web-link.d.ts +9 -0
- package/dist/public-web-link.js +8 -0
- package/dist/public-web-link.js.map +1 -1
- package/dist/quickstart-api.d.ts +10 -1
- package/dist/quickstart-api.js +12 -4
- package/dist/quickstart-api.js.map +1 -1
- package/dist/reply-buttons-controller.d.ts +4 -0
- package/dist/reply-buttons-controller.js +2 -2
- package/dist/reply-buttons-controller.js.map +1 -1
- package/dist/repo-worktree-guard.d.ts +36 -0
- package/dist/repo-worktree-guard.js +143 -0
- package/dist/repo-worktree-guard.js.map +1 -0
- package/dist/restart-progress.d.ts +65 -1
- package/dist/restart-progress.js +236 -10
- package/dist/restart-progress.js.map +1 -1
- package/dist/rollout-index.d.ts +5 -0
- package/dist/rollout-index.js +26 -5
- package/dist/rollout-index.js.map +1 -1
- package/dist/scheduler/scheduler.d.ts +70 -1
- package/dist/scheduler/scheduler.js +256 -17
- package/dist/scheduler/scheduler.js.map +1 -1
- package/dist/service-installer.d.ts +2 -1
- package/dist/service-installer.js +18 -3
- package/dist/service-installer.js.map +1 -1
- package/dist/settings-api.d.ts +19 -0
- package/dist/settings-api.js +210 -2
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-change.js +112 -0
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-effect.js +32 -2
- package/dist/settings-effect.js.map +1 -1
- package/dist/settings-http-confirmation.js +5 -0
- package/dist/settings-http-confirmation.js.map +1 -1
- package/dist/tmux-manager.d.ts +5 -0
- package/dist/tmux-manager.js +16 -0
- package/dist/tmux-manager.js.map +1 -1
- package/dist/tool-permissions.d.ts +4 -6
- package/dist/tool-permissions.js +100 -2
- package/dist/tool-permissions.js.map +1 -1
- package/dist/topic-commands.d.ts +17 -7
- package/dist/topic-commands.js +39 -21
- package/dist/topic-commands.js.map +1 -1
- package/dist/topic-link.d.ts +128 -0
- package/dist/topic-link.js +269 -0
- package/dist/topic-link.js.map +1 -0
- package/dist/types.d.ts +61 -1
- package/dist/ui/app-effects.js +233 -0
- package/dist/ui/chat-ambient.js +307 -0
- package/dist/ui/chat-effect-posters.js +42 -0
- package/dist/ui/chat-effects.js +160 -0
- package/dist/ui/chat-live-replies.js +58 -0
- package/dist/ui/chat-render.js +9 -6
- package/dist/ui/chat-store.js +9 -3
- package/dist/ui/chat-strings.js +70 -2
- package/dist/ui/chat-thread.js +191 -37
- package/dist/ui/chat-tour.js +1 -1
- package/dist/ui/effect-trial-controller.js +124 -0
- package/dist/ui/effect-trial-offer.js +31 -0
- package/dist/ui/effect-trial-panel.js +40 -0
- package/dist/ui/fleet-cache.js +23 -1
- package/dist/ui/fleet-canvas-layout.js +111 -0
- package/dist/ui/fleet-canvas.js +525 -0
- package/dist/ui/fleet-org.js +27 -12
- package/dist/ui/fleet-traffic.js +343 -0
- package/dist/ui/fleet-usage.js +401 -0
- package/dist/ui/image-lightbox.js +1 -1
- package/dist/ui/panel-chat.js +203 -57
- package/dist/ui/panel-details.js +20 -6
- package/dist/ui/panel-fleet.js +43 -18
- package/dist/ui/panel-log.js +6 -6
- package/dist/ui/panel-needs.js +3 -3
- package/dist/ui/panel-settings.js +34 -13
- package/dist/ui/preview-panel.js +25 -9
- package/dist/ui/preview.js +3 -2
- package/dist/ui/settings-appearance.js +349 -0
- package/dist/ui/settings-catalog.js +92 -0
- package/dist/ui/settings-dialogs.js +40 -12
- package/dist/ui/settings-effects.js +202 -0
- package/dist/ui/settings-guests.js +117 -0
- package/dist/ui/settings-learn.js +25 -0
- package/dist/ui/settings-model.js +15 -6
- package/dist/ui/settings-mods.js +271 -0
- package/dist/ui/settings-owner-effects.js +80 -0
- package/dist/ui/settings-strings.js +333 -10
- package/dist/ui/settings-web-authority.js +91 -0
- package/dist/ui/shared/agend-auth.js +28 -4
- package/dist/ui/shared/agent-widget.js +248 -0
- package/dist/ui/shared/app-i18n.js +6 -2
- package/dist/ui/shared/app-prefs.js +34 -13
- package/dist/ui/shared/app-route.js +24 -2
- package/dist/ui/shared/app-session.js +3 -1
- package/dist/ui/shared/app-shell.js +102 -23
- package/dist/ui/shared/app-store.js +28 -1
- package/dist/ui/shared/app-stream.js +14 -7
- package/dist/ui/shared/app-themes.js +206 -0
- package/dist/ui/shared/app.css +565 -4
- package/dist/ui/shared/app.js +23 -10
- package/dist/ui/shared/card-strings.js +32 -0
- package/dist/ui/shared/effect-app-runtime.js +297 -0
- package/dist/ui/shared/effect-baseline.js +64 -0
- package/dist/ui/shared/effect-chat-runtime.js +167 -0
- package/dist/ui/shared/effect-cursor.js +125 -0
- package/dist/ui/shared/effect-frame.js +146 -0
- package/dist/ui/shared/effect-geometry.js +137 -0
- package/dist/ui/shared/effect-host-style.js +10 -0
- package/dist/ui/shared/effect-owner-regions.js +74 -0
- package/dist/ui/shared/effect-owner-source.js +115 -0
- package/dist/ui/shared/effect-policy.js +151 -0
- package/dist/ui/shared/effect-poster-reader.js +98 -0
- package/dist/ui/shared/effect-posters.js +117 -0
- package/dist/ui/shared/effect-profiler.js +184 -0
- package/dist/ui/shared/effect-profiles.js +65 -0
- package/dist/ui/shared/effect-registry.js +535 -0
- package/dist/ui/shared/effect-runtime-loader.js +234 -0
- package/dist/ui/shared/effect-safety.js +153 -0
- package/dist/ui/shared/effect-stock-snapshot.js +43 -0
- package/dist/ui/shared/effect-stock-trust.js +217 -0
- package/dist/ui/shared/effect-trial-shadow.js +62 -0
- package/dist/ui/shared/effect-trial-source.js +103 -0
- package/dist/ui/shared/effect-trial-stage.js +170 -0
- package/dist/ui/shared/effect-trial.css +40 -0
- package/dist/ui/shared/fx-motion.js +67 -0
- package/dist/ui/shared/header-tools.js +1 -1
- package/dist/ui/shared/identity-card.js +273 -0
- package/dist/ui/shared/identity-color.js +261 -0
- package/dist/ui/shared/instance-nav.js +215 -41
- package/dist/ui/shared/owner-css.js +221 -0
- package/dist/ui/shared/owner-effect-prefs.js +117 -0
- package/dist/ui/shared/panel-view.js +103 -10
- package/dist/ui/shared/signin.js +2 -0
- package/dist/ui/shared/tokens.css +9 -3
- package/dist/ui/shared/ui-dialog.js +1 -1
- package/dist/ui/shared/ui-icons.js +3 -0
- package/dist/ui/shared/ui-menu.js +1 -1
- package/dist/ui/shared/ui-toast.js +1 -1
- package/dist/ui/shared/usage-dialog.js +22 -2
- package/dist/ui/shared/view-strings.js +98 -2
- package/dist/ui/shared/web-authorize.js +151 -0
- package/dist/ui/signin.html +1 -0
- package/dist/ui/web-terminal/terminal.css +4 -4
- package/dist/usage/providers.d.ts +28 -0
- package/dist/usage/providers.js +126 -36
- package/dist/usage/providers.js.map +1 -1
- package/dist/usage-report.d.ts +158 -0
- package/dist/usage-report.js +226 -0
- package/dist/usage-report.js.map +1 -0
- package/dist/usage-rollup.d.ts +51 -0
- package/dist/usage-rollup.js +168 -0
- package/dist/usage-rollup.js.map +1 -0
- package/dist/view-api.d.ts +68 -0
- package/dist/view-api.js +249 -8
- package/dist/view-api.js.map +1 -1
- package/dist/web-ambient.d.ts +72 -0
- package/dist/web-ambient.js +161 -0
- package/dist/web-ambient.js.map +1 -0
- package/dist/web-api.d.ts +111 -5
- package/dist/web-api.js +1235 -58
- package/dist/web-api.js.map +1 -1
- package/dist/web-appearance-limits.d.ts +82 -0
- package/dist/web-appearance-limits.js +83 -0
- package/dist/web-appearance-limits.js.map +1 -0
- package/dist/web-appearance-policy.d.ts +64 -0
- package/dist/web-appearance-policy.js +87 -0
- package/dist/web-appearance-policy.js.map +1 -0
- package/dist/web-appearance-tools.d.ts +53 -0
- package/dist/web-appearance-tools.js +124 -0
- package/dist/web-appearance-tools.js.map +1 -0
- package/dist/web-appearance-view.d.ts +124 -0
- package/dist/web-appearance-view.js +278 -0
- package/dist/web-appearance-view.js.map +1 -0
- package/dist/web-appearance.d.ts +93 -0
- package/dist/web-appearance.js +373 -0
- package/dist/web-appearance.js.map +1 -0
- package/dist/web-asset-parts.d.ts +93 -0
- package/dist/web-asset-parts.js +133 -0
- package/dist/web-asset-parts.js.map +1 -0
- package/dist/web-auth.js +20 -2
- package/dist/web-auth.js.map +1 -1
- package/dist/web-card.d.ts +110 -0
- package/dist/web-card.js +266 -0
- package/dist/web-card.js.map +1 -0
- package/dist/web-channel-echo.d.ts +7 -1
- package/dist/web-channel-echo.js +6 -2
- package/dist/web-channel-echo.js.map +1 -1
- package/dist/web-chat-history.d.ts +59 -0
- package/dist/web-chat-history.js +102 -4
- package/dist/web-chat-history.js.map +1 -1
- package/dist/web-commands.d.ts +1 -0
- package/dist/web-effect-bootstrap.d.ts +12 -0
- package/dist/web-effect-bootstrap.js +49 -0
- package/dist/web-effect-bootstrap.js.map +1 -0
- package/dist/web-effect-bundle.d.ts +28 -0
- package/dist/web-effect-bundle.js +171 -0
- package/dist/web-effect-bundle.js.map +1 -0
- package/dist/web-effect-canonical.d.ts +8 -0
- package/dist/web-effect-canonical.js +27 -0
- package/dist/web-effect-canonical.js.map +1 -0
- package/dist/web-effect-library.d.ts +114 -0
- package/dist/web-effect-library.js +530 -0
- package/dist/web-effect-library.js.map +1 -0
- package/dist/web-effect-playback.d.ts +30 -0
- package/dist/web-effect-playback.js +71 -0
- package/dist/web-effect-playback.js.map +1 -0
- package/dist/web-effect-poster.d.ts +8 -0
- package/dist/web-effect-poster.js +52 -0
- package/dist/web-effect-poster.js.map +1 -0
- package/dist/web-effect-profiles.d.ts +118 -0
- package/dist/web-effect-profiles.js +180 -0
- package/dist/web-effect-profiles.js.map +1 -0
- package/dist/web-effect-service.d.ts +93 -0
- package/dist/web-effect-service.js +335 -0
- package/dist/web-effect-service.js.map +1 -0
- package/dist/web-effect-tools.d.ts +48 -0
- package/dist/web-effect-tools.js +129 -0
- package/dist/web-effect-tools.js.map +1 -0
- package/dist/web-effect-trials.d.ts +86 -0
- package/dist/web-effect-trials.js +204 -0
- package/dist/web-effect-trials.js.map +1 -0
- package/dist/web-effect-upload.d.ts +27 -0
- package/dist/web-effect-upload.js +185 -0
- package/dist/web-effect-upload.js.map +1 -0
- package/dist/web-effect-worker.d.ts +8 -0
- package/dist/web-effect-worker.js +170 -0
- package/dist/web-effect-worker.js.map +1 -0
- package/dist/web-effect.d.ts +103 -0
- package/dist/web-effect.js +153 -0
- package/dist/web-effect.js.map +1 -0
- package/dist/web-guest-access.d.ts +125 -0
- package/dist/web-guest-access.js +234 -0
- package/dist/web-guest-access.js.map +1 -0
- package/dist/web-guest-rooms.d.ts +82 -0
- package/dist/web-guest-rooms.js +135 -0
- package/dist/web-guest-rooms.js.map +1 -0
- package/dist/web-identity-color.d.ts +87 -0
- package/dist/web-identity-color.js +209 -0
- package/dist/web-identity-color.js.map +1 -0
- package/dist/web-identity-palette.d.ts +113 -0
- package/dist/web-identity-palette.js +84 -0
- package/dist/web-identity-palette.js.map +1 -0
- package/dist/web-image-meta.d.ts +25 -0
- package/dist/web-image-meta.js +200 -0
- package/dist/web-image-meta.js.map +1 -0
- package/dist/web-login.d.ts +47 -0
- package/dist/web-login.js +115 -0
- package/dist/web-login.js.map +1 -1
- package/dist/web-mod-agent.d.ts +50 -0
- package/dist/web-mod-agent.js +207 -0
- package/dist/web-mod-agent.js.map +1 -0
- package/dist/web-mod-bundle.d.ts +157 -0
- package/dist/web-mod-bundle.js +529 -0
- package/dist/web-mod-bundle.js.map +1 -0
- package/dist/web-mod-export.d.ts +68 -0
- package/dist/web-mod-export.js +100 -0
- package/dist/web-mod-export.js.map +1 -0
- package/dist/web-mod-store.d.ts +289 -0
- package/dist/web-mod-store.js +638 -0
- package/dist/web-mod-store.js.map +1 -0
- package/dist/web-org.d.ts +3 -3
- package/dist/web-org.js +11 -17
- package/dist/web-org.js.map +1 -1
- package/dist/web-owner-css-store.d.ts +180 -0
- package/dist/web-owner-css-store.js +384 -0
- package/dist/web-owner-css-store.js.map +1 -0
- package/dist/web-owner-css.d.ts +58 -0
- package/dist/web-owner-css.js +552 -0
- package/dist/web-owner-css.js.map +1 -0
- package/dist/web-prefs.d.ts +62 -0
- package/dist/web-prefs.js +232 -36
- package/dist/web-prefs.js.map +1 -1
- package/dist/web-preview.d.ts +15 -3
- package/dist/web-preview.js +28 -9
- package/dist/web-preview.js.map +1 -1
- package/dist/web-returning-device.d.ts +41 -0
- package/dist/web-returning-device.js +57 -5
- package/dist/web-returning-device.js.map +1 -1
- package/dist/web-session-authorization.d.ts +132 -0
- package/dist/web-session-authorization.js +193 -0
- package/dist/web-session-authorization.js.map +1 -0
- package/dist/web-session.d.ts +70 -10
- package/dist/web-session.js +137 -22
- package/dist/web-session.js.map +1 -1
- package/dist/web-settings-patch.d.ts +67 -2
- package/dist/web-settings-patch.js +196 -1
- package/dist/web-settings-patch.js.map +1 -1
- package/dist/web-settings-tools.d.ts +89 -0
- package/dist/web-settings-tools.js +270 -0
- package/dist/web-settings-tools.js.map +1 -0
- package/dist/web-shell-routes.d.ts +2 -2
- package/dist/web-shell-routes.js +2 -2
- package/dist/web-shell-routes.js.map +1 -1
- package/dist/web-theme-store.d.ts +257 -0
- package/dist/web-theme-store.js +627 -0
- package/dist/web-theme-store.js.map +1 -0
- package/dist/web-theme.d.ts +123 -0
- package/dist/web-theme.js +416 -0
- package/dist/web-theme.js.map +1 -0
- package/dist/web-widget.d.ts +72 -0
- package/dist/web-widget.js +245 -0
- package/dist/web-widget.js.map +1 -0
- package/dist/workflow-templates/default.md +1 -1
- package/package.json +1 -1
- package/templates/systemd.service.ejs +8 -0
package/dist/ui/panel-chat.js
CHANGED
|
@@ -6,16 +6,17 @@
|
|
|
6
6
|
// right, the agent's at full width, and one rounded composer pinned below with attach, Stop reply and Send inside it.
|
|
7
7
|
// The instance's own actions (details, start, stop, restart, delete) are in the header's ⋯ menu, and only the ones
|
|
8
8
|
// that apply to its state are offered (#1408 rough edges 4 and 7).
|
|
9
|
-
import { html, useEffect, useLayoutEffect, useRef, useState } from "/assets/app-html.js";
|
|
10
|
-
import { t } from "/assets/app-i18n.js";
|
|
11
|
-
import { appStore, useStore } from "/assets/app-store.js";
|
|
9
|
+
import { html, useCallback, useEffect, useLayoutEffect, useRef, useState } from "/assets/app-html.js";
|
|
10
|
+
import { lang, t } from "/assets/app-i18n.js";
|
|
11
|
+
import { appStore, guestPage, useStore } from "/assets/app-store.js";
|
|
12
|
+
import { AuthorizeChip } from "/assets/web-authorize.js";
|
|
12
13
|
import { useLease } from "/assets/app-ctx.js";
|
|
13
|
-
import { namesOf, namesStore } from "/assets/instance-nav.js";
|
|
14
|
+
import { modelText, namesOf, namesStore } from "/assets/instance-nav.js";
|
|
14
15
|
import { PanelHeader, onPanelKey, setTitle, statusClass, statusLabel, openDrawer, requestNewInstance } from "/assets/app-shell.js";
|
|
15
|
-
import { detailsPath } from "/assets/app-route.js";
|
|
16
|
+
import { detailsPath, textLinkSegments } from "/assets/app-route.js";
|
|
16
17
|
import { InstanceSwitch } from "/assets/instance-switch.js";
|
|
17
18
|
import { HeaderTools } from "/assets/header-tools.js";
|
|
18
|
-
import { navigate } from "/assets/app-nav.js";
|
|
19
|
+
import { navigate, navStore } from "/assets/app-nav.js";
|
|
19
20
|
import { Menu } from "/assets/ui-menu.js";
|
|
20
21
|
import { Dialog } from "/assets/ui-dialog.js";
|
|
21
22
|
import { Empty, Skeleton } from "/assets/ui-states.js";
|
|
@@ -23,6 +24,26 @@ import { Icon } from "/assets/ui-icons.js";
|
|
|
23
24
|
import { toast } from "/assets/ui-toast.js";
|
|
24
25
|
import { confirmDialog } from "/assets/ui-confirm.js";
|
|
25
26
|
import { savePref } from "/assets/app-prefs.js";
|
|
27
|
+
import { applyTheme, clearAmbient, resolvedMode, themeFor, themeImageUrl, themeMenuItems, themesStore } from "/assets/app-themes.js";
|
|
28
|
+
import { colorMenuItem } from "/assets/identity-color.js";
|
|
29
|
+
import { IdentityCard, useCard } from "/assets/identity-card.js";
|
|
30
|
+
import { AgentWidget, instanceBinds, widgetFor } from "/assets/agent-widget.js";
|
|
31
|
+
|
|
32
|
+
// #1629 r4 §1: the identity card folded into the chat's header — folded by default; open or not is this device's choice.
|
|
33
|
+
const CHAT_CARD_KEY = "agend_chat_card";
|
|
34
|
+
const chatCardOpen = () => { try { return localStorage.getItem(CHAT_CARD_KEY) === "open"; } catch { return false; } };
|
|
35
|
+
function ChatCard({ name, card }) {
|
|
36
|
+
const [open, setOpen] = useState(chatCardOpen);
|
|
37
|
+
if (!card) return null;
|
|
38
|
+
const toggle = () => { const next = !open; setOpen(next); try { if (next) localStorage.setItem(CHAT_CARD_KEY, "open"); else localStorage.removeItem(CHAT_CARD_KEY); } catch { /* this page only */ } };
|
|
39
|
+
return html`<div data-trust="card" class=${`chat-card${open ? " open" : ""}`}>
|
|
40
|
+
<button type="button" class="chat-card-toggle" aria-expanded=${open ? "true" : "false"} onClick=${toggle}>
|
|
41
|
+
<${Icon} name="chevron" size=${14} cls=${open ? "caret" : "caret flipped"} /><span>${t(open ? "card.hide" : "card.show")}</span>
|
|
42
|
+
${!open && card.tagline ? html`<span class="chat-card-peek">${card.tagline.text}</span>` : null}
|
|
43
|
+
</button>
|
|
44
|
+
${open ? html`<${IdentityCard} name=${name} card=${card} compact=${true} />` : null}
|
|
45
|
+
</div>`;
|
|
46
|
+
}
|
|
26
47
|
import "./chat-strings.js";
|
|
27
48
|
import { confirmedWrite } from "./settings-confirm.js";
|
|
28
49
|
import { createChatStore } from "./chat-store.js";
|
|
@@ -34,6 +55,11 @@ import { PreviewPanel, claimPanel, openPanel, panelClaims, panelStore, panelVers
|
|
|
34
55
|
import { needsArgument, paletteFor, parseCommandLine } from "./chat-commands.js";
|
|
35
56
|
import { installTour, refreshTourSpot } from "./chat-tour.js";
|
|
36
57
|
import { LightboxHost, openLightbox } from "./image-lightbox.js";
|
|
58
|
+
import { ChatEffectPosters } from "/ui/js/chat-effect-posters.js";
|
|
59
|
+
import { ChatEffects, chatEffectsMenuAvailable } from "./chat-effects.js";
|
|
60
|
+
import { setFollowsReducedMotion } from "/assets/fx-motion.js";
|
|
61
|
+
import { AmbientMotionNote, ChatAmbient, ambientMenuItems } from "./chat-ambient.js";
|
|
62
|
+
import { startAppEffects, getAppEffects } from "./app-effects.js";
|
|
37
63
|
|
|
38
64
|
const R = () => globalThis.AgendChatRender;
|
|
39
65
|
const P = () => globalThis.AgendPreview;
|
|
@@ -93,6 +119,8 @@ export function boot({ stream, boot: bootData, deps = {} }) {
|
|
|
93
119
|
}
|
|
94
120
|
// #1604: the preview opt-in and Tour live in Settings → This device now (and on each preview card's menu).
|
|
95
121
|
installTour();
|
|
122
|
+
// #2118: viewing current in-scope Chat effects needs no management or personal-slot authority.
|
|
123
|
+
startAppEffects({ store });
|
|
96
124
|
return store;
|
|
97
125
|
}
|
|
98
126
|
|
|
@@ -171,11 +199,43 @@ function NotFound({ name }) {
|
|
|
171
199
|
action=${html`<button type="button" class="btn only-narrow" onClick=${openDrawer}>${t("chat.backToList")}</button>`} /></div></div>`;
|
|
172
200
|
}
|
|
173
201
|
|
|
202
|
+
/**
|
|
203
|
+
* #1629: the mode the page is drawn in, followed live (the chosen theme, or the system's for "system"), so an agent's
|
|
204
|
+
* light and dark palettes swap with it.
|
|
205
|
+
*/
|
|
206
|
+
function useResolvedMode(lease) {
|
|
207
|
+
const [mode, setMode] = useState(resolvedMode);
|
|
208
|
+
useEffect(() => {
|
|
209
|
+
const T = globalThis.AgendTheme;
|
|
210
|
+
const update = () => setMode(resolvedMode());
|
|
211
|
+
const off = T && typeof T.onChange === "function" ? T.onChange(update) : null;
|
|
212
|
+
let mq = null;
|
|
213
|
+
try { mq = globalThis.matchMedia ? globalThis.matchMedia("(prefers-color-scheme: light)") : null; } catch { mq = null; }
|
|
214
|
+
if (mq && typeof mq.addEventListener === "function") lease.on(mq, "change", update);
|
|
215
|
+
return () => { if (typeof off === "function") off(); };
|
|
216
|
+
}, [lease]);
|
|
217
|
+
return mode;
|
|
218
|
+
}
|
|
219
|
+
|
|
174
220
|
function ChatView({ name, inst, lease, navKey, exec, awaiting }) {
|
|
175
221
|
const names = useStore(namesStore); // #1722: which name leads (the title)
|
|
222
|
+
// #1629: this agent's theme, on this surface only; redrawn when the themes, the viewer's switch or the mode move.
|
|
223
|
+
useStore(themesStore);
|
|
224
|
+
const mode = useResolvedMode(lease);
|
|
225
|
+
const theme = themeFor(name);
|
|
226
|
+
const themeKey = JSON.stringify(theme);
|
|
227
|
+
const card = useCard(name, inst.card_v);
|
|
176
228
|
const [dialog, setDialog] = useState(null); // "delete" | null
|
|
229
|
+
const [canvasPlayback, setCanvasPlayback] = useState(null);
|
|
230
|
+
const publishCanvasPlayback = useCallback(value => setCanvasPlayback(previous =>
|
|
231
|
+
!previous && !value.playing || previous?.name === value.name && previous.playing === value.playing ? previous : value), []);
|
|
177
232
|
const [wrap, setWrap] = useState(codeWrap);
|
|
178
|
-
const view = useRef(null), split = useRef(null), thread = useRef(null);
|
|
233
|
+
const view = useRef(null), split = useRef(null), thread = useRef(null), bg = useRef(null), effectSurface = useRef(null);
|
|
234
|
+
useLayoutEffect(() => { applyTheme(view.current, theme, mode); }, [themeKey, mode]);
|
|
235
|
+
useLayoutEffect(() => {
|
|
236
|
+
const img = bg.current;
|
|
237
|
+
if (img && img.style && theme && theme.background) img.style.setProperty("--th-bg-opacity", String(theme.background.opacity));
|
|
238
|
+
}, [themeKey]);
|
|
179
239
|
useEffect(() => { wrapListeners.add(setWrap); return () => wrapListeners.delete(setWrap); }, []);
|
|
180
240
|
// First visit to this instance's chat on this page: its history (a navigation — it counts as use). Back again: nothing.
|
|
181
241
|
useEffect(() => { store.openHistory(name, lease); }, [name]);
|
|
@@ -217,97 +277,176 @@ function ChatView({ name, inst, lease, navKey, exec, awaiting }) {
|
|
|
217
277
|
running ? null : { key: "start", label: t("chat.start"), icon: "play", onSelect: () => action("start") },
|
|
218
278
|
running ? { key: "restart", label: t("chat.restart"), icon: "restart", onSelect: () => action("restart") } : null,
|
|
219
279
|
running ? { key: "stop", label: t("chat.stopInstance"), icon: "stop", onSelect: () => action("stop") } : null,
|
|
280
|
+
// #1958: its identity colour and where it shows (the public link too, as profile edits).
|
|
281
|
+
colorMenuItem(name, inst),
|
|
282
|
+
// #1629: a person's control over this agent's theme — not over the public link (it only views themes).
|
|
283
|
+
...themeMenuItems(name),
|
|
284
|
+
// #2117: its ambient — why it is not showing here (with the way to change that), and a person's Clear.
|
|
285
|
+
...ambientMenuItems(name, { publicLink: document.body.dataset.publicLink === "1", clear: clearAmbient }),
|
|
286
|
+
chatEffectsMenuAvailable() ? { key: "effects", label: t("chatFx.title"), onSelect: () => setDialog("effects") } : null,
|
|
220
287
|
{ key: "delete", label: t("chat.delete"), icon: "trash", danger: true, onSelect: () => setDialog("delete") },
|
|
221
288
|
];
|
|
222
289
|
const cls = statusClass(inst, exec, awaiting);
|
|
290
|
+
// #1920 phase 3: a guest has this chat only — no Details, View or Log to switch to, no lifecycle, colour, theme,
|
|
291
|
+
// effect management or delete (a guest's status frame carries no model or effort either, so those chips do not show).
|
|
292
|
+
const guest = guestPage();
|
|
223
293
|
// #1269 quick actions: the model and effort it runs, each a way to /model or /effort (the same pick list).
|
|
224
294
|
const pick = (command) => store.runCommand(name, command, "", { alive: () => lease.current() });
|
|
225
295
|
const sub = html`<span class="status"><span class=${`dot ${cls}`} aria-hidden="true"></span>${statusLabel(inst, exec, awaiting)}</span>
|
|
226
|
-
${inst.model ? html`<button type="button" class="hd-chip" title=${t("chat.chipModel", inst
|
|
296
|
+
${inst.model ? html`<button type="button" class="hd-chip" title=${t("chat.chipModel", modelText(inst))} aria-label=${t("chat.chipModel", modelText(inst))} onClick=${() => pick("model")}>${modelText(inst)}</button>` : null}
|
|
227
297
|
${inst.effort ? html`<button type="button" class="hd-chip" title=${t("chat.chipEffort", inst.effort)} aria-label=${t("chat.chipEffort", inst.effort)} onClick=${() => pick("effort")}>${inst.effort}</button>` : null}`;
|
|
228
298
|
return html`<div class=${`panel p-chat${wrap ? " wrap-code" : ""}`} ref=${view}>
|
|
229
|
-
<${PanelHeader} title=${headerName(namesOf(inst || { name }, names.primary))} sub=${sub} nav=${html`<${InstanceSwitch} name=${name} current="chat" />`}><${HeaderTools} navKey=${navKey}
|
|
299
|
+
<${PanelHeader} title=${headerName(namesOf(inst || { name }, names.primary))} sub=${sub} nav=${guest ? null : html`<${InstanceSwitch} name=${name} current="chat" />`} notice=${html`<${ChatEffects} name=${name} lease=${lease} element=${effectSurface} store=${store} open=${dialog === "effects"} onPlayback=${publishCanvasPlayback} onClose=${() => setDialog(null)} />`}><${ChatEffectPosters} name=${name} lease=${lease} element=${effectSurface} /><${HeaderTools} navKey=${navKey} />${guest ? null : html`<${Menu} items=${items} label=${t("app.more")} />`}</${PanelHeader}>
|
|
300
|
+
<${ChatCard} key=${name} name=${name} card=${card} />
|
|
301
|
+
<${AgentWidget} slot="chat_header" widget=${widgetFor(name, "chat_header")} binds=${instanceBinds(inst, exec, awaiting)} />
|
|
230
302
|
<div class="chat-split" ref=${split}>
|
|
231
|
-
<div class
|
|
303
|
+
<div ref=${effectSurface} class=${`chat-main${theme && theme.background ? " has-th-bg" : ""}`}>
|
|
304
|
+
${theme && theme.background ? html`<img ref=${bg} class=${`th-bg th-bg-${theme.background.fit}`} src=${themeImageUrl(name, theme.background.image)} alt="" aria-hidden="true" decoding="async" />` : null}
|
|
305
|
+
<${ChatAmbient} name=${name} surface=${effectSurface} part="layer" />
|
|
306
|
+
<${AmbientMotionNote} name=${name} canvasPlaying=${canvasPlayback?.name === name && canvasPlayback.playing} />
|
|
232
307
|
<${Thread} name=${name} th=${thread} />
|
|
233
|
-
<${Dock} name=${name} inst=${inst} lease=${lease} exec=${exec} awaiting=${awaiting} />
|
|
308
|
+
<${Dock} name=${name} inst=${inst} lease=${lease} exec=${exec} awaiting=${awaiting} workingLabel=${theme ? theme.workingLabel : undefined} />
|
|
309
|
+
<${ChatAmbient} name=${name} surface=${effectSurface} part="front" />
|
|
234
310
|
</div>
|
|
235
311
|
<${PreviewPanel} name=${name} split=${split} msgs=${() => store.state.msgs[name] || []} subscribe=${(fn) => store.subscribe(fn)}
|
|
236
312
|
keyOf=${msgKey} reveal=${(k) => thread.current && thread.current.reveal(k)} download=${downloadHtml} allow=${(commit) => setPreviewOptIn(true, commit)} />
|
|
237
313
|
</div>
|
|
238
314
|
<${LightboxHost} />
|
|
239
|
-
<div class="drop-overlay" aria-hidden="true"><div class="drop-card"><${Icon} name="attach" size=${32} /><span>${t("chat.dropHere")}</span></div></div>
|
|
315
|
+
<div data-trust="drop" class="drop-overlay" aria-hidden="true"><div class="drop-card"><${Icon} name="attach" size=${32} /><span>${t("chat.dropHere")}</span></div></div>
|
|
240
316
|
${dialog === "delete" ? html`<${DeleteDialog} name=${name} onClose=${() => setDialog(null)} />` : null}
|
|
241
317
|
</div>`;
|
|
242
318
|
}
|
|
243
319
|
|
|
244
|
-
/**
|
|
320
|
+
/**
|
|
321
|
+
* #2053: the last THREAD_KEEP chats' threads are kept when their view leaves (the chat view is keyed by instance, so
|
|
322
|
+
* each switch built the thread again: a revisit was no faster than a first visit). A kept thread is its list element
|
|
323
|
+
* and its renderer, and nothing more: it leaves as a chat always did (previews stop), with no subscription or timer
|
|
324
|
+
* left; shown again, one render draws only what changed meanwhile, where the reader was. A new language, another
|
|
325
|
+
* document, or more than THREAD_KEEP lets one go.
|
|
326
|
+
*/
|
|
327
|
+
export const THREAD_KEEP = 4;
|
|
328
|
+
const keptThreads = new Map(); // name → { thread, list, sink, lang }
|
|
329
|
+
/** Tests only: let every kept thread go. */
|
|
330
|
+
export function forgetKeptThreads() { for (const e of keptThreads.values()) letGo(e, true); keptThreads.clear(); }
|
|
331
|
+
function letGo(e, own) { e.thread.dispose(own); e.list.remove(); }
|
|
332
|
+
|
|
333
|
+
/** A chat's thread: its own list element and renderer, and a sink for the view that shows it. */
|
|
334
|
+
function threadEntry(name, doc) {
|
|
335
|
+
const list = doc.createElement("div");
|
|
336
|
+
list.className = "thread";
|
|
337
|
+
list.setAttribute("role", "log");
|
|
338
|
+
list.setAttribute("aria-live", "off");
|
|
339
|
+
list.setAttribute("aria-label", t("chat.conversationWith", name));
|
|
340
|
+
const e = { list, sink: null, lang: lang(), thread: null };
|
|
341
|
+
const thread = createThread(list, doc.createElement("div"), {
|
|
342
|
+
t, tf: t, isUser: (x) => store.isUser(x, name), onJump: (j) => e.sink?.setJump(j), onEmpty: (v) => e.sink?.setEmpty(v),
|
|
343
|
+
setPreviewOptIn, copyText, download: downloadHtml, toggleWrap,
|
|
344
|
+
effectTrialStatus: x => getAppEffects()?.trialStatus(x) ?? "localAdmin",
|
|
345
|
+
effectTrialFailure: x => getAppEffects()?.trialFailure(x),
|
|
346
|
+
fixEffectTrial: (x, reason) => {
|
|
347
|
+
if (reason === "reducedMotion") setFollowsReducedMotion(false);
|
|
348
|
+
else if (reason === "busy") getAppEffects()?.stopTrial();
|
|
349
|
+
else if (reason === "transport") location.reload();
|
|
350
|
+
else if (reason === "localAdmin") location.href = "/signin?next=" + encodeURIComponent(location.pathname + location.search);
|
|
351
|
+
else navigate("/settings/appearance");
|
|
352
|
+
},
|
|
353
|
+
canTryEffect: x => getAppEffects()?.canTry(x) === true,
|
|
354
|
+
startEffectTrial: x => { const seq = navStore.get().seq; void getAppEffects()?.startTrial(x).then(ok => { if (!ok && e.sink && navStore.get().seq === seq && document.hasFocus?.() === true && document.visibilityState === "visible") toast(t("chat.effectTrialUnavailable")); }); },
|
|
355
|
+
clickReplyButton: (id, index) => store.clickReplyButton(name, id, index), // #1266
|
|
356
|
+
replyButtonBusy: (id) => store.state.rbBusy.has(id),
|
|
357
|
+
pollMine: (id) => store.state.pollMine[id], // #1823: this device's own vote
|
|
358
|
+
serverNow: () => Date.now() + store.state.clockSkew, // #1823: the deadline is the server's
|
|
359
|
+
panel: { shown: shownKey, open: (spec, o) => openPanel(spec, o), version: panelVersion, claim: claimPanel, claims: panelClaims }, // #1481, #1704
|
|
360
|
+
openImage: openLightbox, // an image, full size, in the page
|
|
361
|
+
emojis: (id) => !!emojiIndex && emojiIndex.known(id), // #1630: the fleet's server emoji
|
|
362
|
+
mentions: (kind, id) => (mentionIndex ? mentionIndex.name(kind, id) : null), // #1682: mention names
|
|
363
|
+
});
|
|
364
|
+
e.thread = thread;
|
|
365
|
+
return e;
|
|
366
|
+
}
|
|
367
|
+
/** While a thread is shown: what it follows. Returns what lets it all go. */
|
|
368
|
+
function follow(name, thread) {
|
|
369
|
+
// #1630: the server-emoji list is read once a message shows a tag; when it arrives, those messages are drawn again.
|
|
370
|
+
// #1682: the same for mention names — asked for the ids the messages carry; when names arrive, drawn again.
|
|
371
|
+
const wantEmojis = (msgs) => { if (emojiIndex && emojiIndex.wants(msgs)) emojiIndex.ensure(); if (mentionIndex) mentionIndex.ensure(msgs); };
|
|
372
|
+
const offs = [];
|
|
373
|
+
if (emojiIndex) offs.push(emojiIndex.subscribe(() => thread.render(store.state.msgs[name] || [])));
|
|
374
|
+
if (mentionIndex) offs.push(mentionIndex.subscribe(() => thread.render(store.state.msgs[name] || [])));
|
|
375
|
+
wantEmojis(store.state.msgs[name]);
|
|
376
|
+
offs.push(store.subscribe((instance, kind) => {
|
|
377
|
+
if (instance !== name) return;
|
|
378
|
+
if (kind === "msgs") { thread.render(store.state.msgs[name] || []); wantEmojis(store.state.msgs[name]); }
|
|
379
|
+
else if (kind === "sent") thread.jumpLatest();
|
|
380
|
+
}));
|
|
381
|
+
offs.push(P() ? P().onChange(() => thread.refreshCards()) : () => {});
|
|
382
|
+
offs.push(getAppEffects()?.subscribeTrial(() => thread.render(store.state.msgs[name] || [])) ?? (() => {}));
|
|
383
|
+
offs.push(panelStore.subscribe(() => thread.refreshCards())); // a card shows whether the panel has its block
|
|
384
|
+
return () => { for (const off of offs) off(); };
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/** The thread's view: Preact owns the scroller and the jump pill; the kept list (chat-thread.js) is put inside it. */
|
|
245
388
|
function Thread({ name, th }) {
|
|
246
|
-
const scroller = useRef(null),
|
|
389
|
+
const scroller = useRef(null), host = useRef(null);
|
|
247
390
|
const [jump, setJump] = useState({ show: false, unseen: 0 });
|
|
248
391
|
const [empty, setEmpty] = useState(false);
|
|
249
392
|
useLayoutEffect(() => {
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
}
|
|
393
|
+
const doc = host.current.ownerDocument;
|
|
394
|
+
let e = keptThreads.get(name);
|
|
395
|
+
// Kept only while it can be shown as it is: the same language, and this page's own document.
|
|
396
|
+
if (e && (e.lang !== lang() || e.list.ownerDocument !== doc)) { letGo(e, true); keptThreads.delete(name); e = undefined; }
|
|
397
|
+
const kept = !!e;
|
|
398
|
+
if (e) keptThreads.delete(name);
|
|
399
|
+
else e = threadEntry(name, doc);
|
|
400
|
+
keptThreads.set(name, e); // the most recent last
|
|
401
|
+
for (const [k, old] of keptThreads) {
|
|
402
|
+
if (keptThreads.size <= THREAD_KEEP) break;
|
|
403
|
+
if (k !== name) { letGo(old, true); keptThreads.delete(k); }
|
|
404
|
+
}
|
|
405
|
+
const thread = e.thread, sc = scroller.current, ls = e.list;
|
|
406
|
+
e.sink = { setJump, setEmpty };
|
|
407
|
+
host.current.append(ls);
|
|
408
|
+
thread.attach(sc);
|
|
262
409
|
th.current = thread;
|
|
263
|
-
//
|
|
264
|
-
// #1682: the same for mention names — asked for the ids the messages carry; when names arrive, drawn again.
|
|
265
|
-
const wantEmojis = (msgs) => { if (emojiIndex && emojiIndex.wants(msgs)) emojiIndex.ensure(); if (mentionIndex) mentionIndex.ensure(msgs); };
|
|
266
|
-
const offEmojis = emojiIndex ? emojiIndex.subscribe(() => thread.render(store.state.msgs[name] || [])) : () => {};
|
|
267
|
-
const offMentions = mentionIndex ? mentionIndex.subscribe(() => thread.render(store.state.msgs[name] || [])) : () => {};
|
|
410
|
+
// Up to date, at the reader's place (the bottom unless they had scrolled up); a kept one's cards say what they can do.
|
|
268
411
|
thread.render(store.state.msgs[name] || [], { restore: store.state.scrollMemo[name] ?? null });
|
|
269
|
-
|
|
270
|
-
const
|
|
271
|
-
if (instance !== name) return;
|
|
272
|
-
if (kind === "msgs") { thread.render(store.state.msgs[name] || []); wantEmojis(store.state.msgs[name]); }
|
|
273
|
-
else if (kind === "sent") thread.jumpLatest();
|
|
274
|
-
});
|
|
275
|
-
const offPv = P() ? P().onChange(() => thread.refreshCards()) : () => {};
|
|
276
|
-
const offPanel = panelStore.subscribe(() => thread.refreshCards()); // a card shows whether the panel has its block
|
|
412
|
+
if (kept) thread.refreshCards();
|
|
413
|
+
const unfollow = follow(name, thread);
|
|
277
414
|
const onScroll = () => { store.state.scrollMemo[name] = thread.onScroll(); };
|
|
278
|
-
const sc = scroller.current, ls = list.current;
|
|
279
415
|
sc.addEventListener("scroll", onScroll, { passive: true });
|
|
280
416
|
ls.addEventListener("click", thread.onClick);
|
|
281
417
|
return () => {
|
|
282
|
-
|
|
418
|
+
unfollow();
|
|
283
419
|
sc.removeEventListener("scroll", onScroll);
|
|
284
420
|
ls.removeEventListener("click", thread.onClick);
|
|
285
|
-
|
|
421
|
+
e.sink = null;
|
|
286
422
|
th.current = null;
|
|
423
|
+
if (keptThreads.get(name) === e) { thread.park(); ls.remove(); } // kept for a later visit: the chat left
|
|
424
|
+
else letGo(e, false); // let go meanwhile (a new language)
|
|
287
425
|
};
|
|
288
426
|
}, [name]);
|
|
289
427
|
return html`<div class="scroller" ref=${scroller}>
|
|
290
|
-
<div class="thread" ref=${
|
|
428
|
+
<div class="thread-host" ref=${host}></div>
|
|
291
429
|
${empty ? html`<${Empty} icon="chat" title=${t("chat.noMessages")} />` : null}
|
|
292
|
-
|
|
293
|
-
<${Icon} name="down" size=${16} />${jump.unseen > 0 ? t("chat.newBelow", jump.unseen) : t("chat.jumpLatest")}</button>` : null}
|
|
430
|
+
<div class="jump-dock">${jump.show ? html`<button data-trust="thread-control" type="button" class="jump-latest" onClick=${() => th.current && th.current.jumpLatest()}>
|
|
431
|
+
<${Icon} name="down" size=${16} />${jump.unseen > 0 ? t("chat.newBelow", jump.unseen) : t("chat.jumpLatest")}</button>` : null}</div>
|
|
294
432
|
</div>`;
|
|
295
433
|
}
|
|
296
434
|
|
|
297
435
|
/** Everything under the thread: prompts, the working line, a failed send, files waiting, and the composer. */
|
|
298
|
-
function Dock({ name, inst, lease, exec, awaiting }) {
|
|
436
|
+
function Dock({ name, inst, lease, exec, awaiting, workingLabel }) {
|
|
299
437
|
useChatTick(name, ["state"]);
|
|
300
438
|
const s = store.state;
|
|
301
|
-
return html`<div class="dock"><div class="dock-col">
|
|
439
|
+
return html`<div data-trust="composer" class="dock"><div class="dock-col">
|
|
302
440
|
<${Prompts} name=${name} />
|
|
303
|
-
<${WorkBar} name=${name} lease=${lease} exec=${exec} awaiting=${awaiting} />
|
|
441
|
+
<${WorkBar} name=${name} lease=${lease} exec=${exec} awaiting=${awaiting} workingLabel=${workingLabel} />
|
|
304
442
|
<${CommandCard} name=${name} lease=${lease} />
|
|
305
443
|
<${QuickActions} name=${name} inst=${inst} lease=${lease} />
|
|
306
444
|
${s.failedSends[name] ? html`<div class="failed-send" role="alert"><span>${t("chat.notSent")}</span><span class="txt">${s.failedSends[name]}</span>
|
|
307
445
|
<button type="button" class="btn btn-primary btn-sm" onClick=${() => store.putBack(name)}>${t("chat.putBack")}</button>
|
|
308
446
|
<button type="button" class="btn btn-sm" onClick=${() => store.discardFailed(name)}>${t("chat.discard")}</button></div>` : null}
|
|
309
447
|
<${Composer} name=${name} lease=${lease} busy=${R().isBusy(exec)} />
|
|
310
|
-
<p class="hint" title=${t("chat.composerMore")}>${t("chat.composerHint")}</p>
|
|
448
|
+
<p class="hint" title=${t(guestPage() ? "chat.guestMore" : "chat.composerMore")}>${t("chat.composerHint")}</p>
|
|
449
|
+
${guestPage() ? html`<p class="guest-note">${t("chat.guestNote")}</p>` : html`<${AuthorizeChip} />`}
|
|
311
450
|
</div></div>`;
|
|
312
451
|
}
|
|
313
452
|
|
|
@@ -327,7 +466,8 @@ function CommandCard({ name, lease }) {
|
|
|
327
466
|
: c.compact === "lost" ? t("chat.compactLost") : c.compact === "not_compacted" ? t("chat.compactNotCompacted") : t("chat.compactUnknown")}</p>` : null}
|
|
328
467
|
${c.choices && c.choices.prompt ? html`<pre class="cmd-text">${c.choices.prompt}</pre>` : null}
|
|
329
468
|
${c.choices ? html`<div class="cmd-choices" role="group" aria-label=${t("chat.cmdChoose")}>${c.choices.options.map((o) => html`<button key=${o.id} type="button"
|
|
330
|
-
class=${`btn btn-sm${o.id === c.choices.current ? " current" : ""}`} aria-current=${o.id === c.choices.current ? "true" : undefined}
|
|
469
|
+
class=${`btn btn-sm${o.id === c.choices.current ? " current" : ""}`} aria-current=${o.id === c.choices.current ? "true" : undefined}
|
|
470
|
+
disabled=${!!o.disabled} title=${o.disabled || undefined} onClick=${() => { if (!o.disabled) run(o.id); }}>${o.label}</button>`)}</div>` : null}
|
|
331
471
|
</div>`;
|
|
332
472
|
}
|
|
333
473
|
|
|
@@ -347,14 +487,14 @@ function QuickActions({ name, inst, lease }) {
|
|
|
347
487
|
function Prompts({ name }) {
|
|
348
488
|
const list = store.promptsFor(name);
|
|
349
489
|
if (!list.length) return null;
|
|
350
|
-
return html`<div class="prompts" aria-live="polite">${list.map(p => html`<div key=${p.nonce} class=${`prompt${p.resolved ? " done" : ""}`} role="group" aria-label=${p.text}>
|
|
351
|
-
<div class="txt">${p.resolved ? (p.outcome || t("chat.promptGone")) : p.text}</div>
|
|
490
|
+
return html`<div data-trust="permission" class="prompts" aria-live="polite">${list.map(p => html`<div key=${p.nonce} class=${`prompt${p.resolved ? " done" : ""}`} role="group" aria-label=${p.text}>
|
|
491
|
+
<div class="txt">${p.resolved ? (p.outcome || t("chat.promptGone")) : textLinkSegments(p.text, p.links).map(sg => sg.href ? html`<a data-trust="link" class="st-link" href=${sg.href}>${sg.text}</a>` : sg.text)}</div>
|
|
352
492
|
${p.resolved ? null : html`<div class="acts">${p.actions.map(a => html`<button key=${a.id} type="button" class="btn" disabled=${!!p.busy} onClick=${() => store.answerPrompt(p, a.id)}>${a.label}</button>`)}
|
|
353
493
|
${p.busy ? html`<span class="wait">${t("chat.promptAnswering")}</span>` : null}</div>`}</div>`)}</div>`;
|
|
354
494
|
}
|
|
355
495
|
|
|
356
496
|
/** "<name> is working… 0:42", "looks stuck", "Stopping…", or what it waits on at its terminal. Text only. */
|
|
357
|
-
function WorkBar({ name, lease, exec, awaiting }) {
|
|
497
|
+
function WorkBar({ name, lease, exec, awaiting, workingLabel }) {
|
|
358
498
|
const s = store.state;
|
|
359
499
|
const busy = R().isBusy(exec) ? exec : "";
|
|
360
500
|
const kind = awaiting != null ? "awaiting" : s.stopping[name] && busy ? "stopping" : busy;
|
|
@@ -365,7 +505,9 @@ function WorkBar({ name, lease, exec, awaiting }) {
|
|
|
365
505
|
return () => lease.clear(h);
|
|
366
506
|
}, [kind, lease]);
|
|
367
507
|
if (!kind) return null;
|
|
368
|
-
|
|
508
|
+
// #1629: the agent's own working label (its theme), shown as text — only for "working", never for the other states.
|
|
509
|
+
const label = kind === "working" && workingLabel ? workingLabel
|
|
510
|
+
: t(kind === "stuck" ? "chat.stuck" : kind === "stopping" ? "chat.stopping" : kind === "awaiting" ? "chat.awaiting" : "chat.working", name);
|
|
369
511
|
const since = s.workingSince[name];
|
|
370
512
|
return html`<div class=${`work-bar ${kind}`}><span class="pulse" aria-hidden="true"></span><span class="lbl">${label}</span>
|
|
371
513
|
${kind === "awaiting" ? html`<span class="note" title=${t("chat.approxNote")}>${awaiting || t("chat.approxNote")}</span>`
|
|
@@ -381,8 +523,10 @@ function Composer({ name, lease, busy }) {
|
|
|
381
523
|
const value = s.drafts[name] || "";
|
|
382
524
|
const files = s.pendingFiles[name] || [];
|
|
383
525
|
const content = !!value.trim() || files.length > 0;
|
|
384
|
-
// A file waiting: what goes is a message with its file, never a command (no palette, no command line).
|
|
385
|
-
|
|
526
|
+
// A file waiting: what goes is a message with its file, never a command (no palette, no command line). A guest never
|
|
527
|
+
// runs one (#1920: the server refuses its slash text), so it has no palette either.
|
|
528
|
+
const guest = guestPage();
|
|
529
|
+
const palette = guest || files.length || closedFor === value ? null : paletteFor(value);
|
|
386
530
|
const pick = palette && palette.length ? palette[Math.min(sel, palette.length - 1)] : null;
|
|
387
531
|
// Grow with the text, up to a limit: set through the CSSOM, never a style attribute (#1300).
|
|
388
532
|
useLayoutEffect(() => { const el = input.current; if (!el) return; el.style.height = "auto"; el.style.height = `${Math.min(el.scrollHeight, 240)}px`; }, [value]);
|
|
@@ -403,6 +547,8 @@ function Composer({ name, lease, busy }) {
|
|
|
403
547
|
else complete(pick);
|
|
404
548
|
return;
|
|
405
549
|
}
|
|
550
|
+
// #1920: a guest's "/…" would be refused as a command — said here, the draft kept to edit.
|
|
551
|
+
if (guest && /^\s*\//.test(value)) { toast(t("chat.guestNoCommands"), false); return; }
|
|
406
552
|
const cmd = files.length ? null : parseCommandLine(value);
|
|
407
553
|
if (cmd && needsArgument(cmd.command) && !cmd.args) { setValue(`/${cmd.command} `); return; }
|
|
408
554
|
if (cmd) { runLine(cmd); return; }
|
|
@@ -428,7 +574,7 @@ function Composer({ name, lease, busy }) {
|
|
|
428
574
|
};
|
|
429
575
|
const optId = (c) => `cmd-${c.name}`;
|
|
430
576
|
return html`<div class="composer-box">
|
|
431
|
-
${palette ? html`<ul class="cmd-palette" id="cmdPalette" role="listbox" aria-label=${t("chat.cmdCommands")}>
|
|
577
|
+
${palette ? html`<ul data-trust="palette" class="cmd-palette" id="cmdPalette" role="listbox" aria-label=${t("chat.cmdCommands")}>
|
|
432
578
|
${palette.length ? palette.map((c) => html`<li key=${c.name} id=${optId(c)} role="option" aria-selected=${c === pick ? "true" : "false"}
|
|
433
579
|
class=${c === pick ? "on" : ""} onMouseDown=${(e) => { e.preventDefault(); complete(c); }}>
|
|
434
580
|
<span class="cmd-name mono">/${c.name}${c.arg ? html` <span class="cmd-arg">${c.arg}</span>` : null}</span><span class="cmd-desc">${t(`chat.cmd_${c.name}`)}</span></li>`)
|
package/dist/ui/panel-details.js
CHANGED
|
@@ -14,8 +14,13 @@ import { PanelHeader, setTitle, statusClass, statusLabel, openDrawer } from "/as
|
|
|
14
14
|
import { navigate } from "/assets/app-nav.js";
|
|
15
15
|
import { settingsPath } from "/assets/app-route.js";
|
|
16
16
|
import { InstanceSwitch } from "/assets/instance-switch.js";
|
|
17
|
+
import { modelText } from "/assets/instance-nav.js";
|
|
17
18
|
import { HeaderTools } from "/assets/header-tools.js";
|
|
18
19
|
import { Menu } from "/assets/ui-menu.js";
|
|
20
|
+
import { themeMenuItems, themesStore } from "/assets/app-themes.js";
|
|
21
|
+
import { colorMenuItem } from "/assets/identity-color.js";
|
|
22
|
+
import { IdentityCard, useCard } from "/assets/identity-card.js";
|
|
23
|
+
import { AgentWidget, instanceBinds, widgetFor } from "/assets/agent-widget.js";
|
|
19
24
|
import { Empty, ErrorState, Skeleton } from "/assets/ui-states.js";
|
|
20
25
|
import { toast } from "/assets/ui-toast.js";
|
|
21
26
|
import "./chat-strings.js";
|
|
@@ -27,10 +32,10 @@ export function DetailsPanel({ route, navKey }) {
|
|
|
27
32
|
const name = route.instance;
|
|
28
33
|
const inst = app.instances.find((i) => i.name === name) || null;
|
|
29
34
|
useEffect(() => { setTitle(`${name} · ${t("app.details")}`); }, [name, navKey]);
|
|
30
|
-
if (!app.ready) return html`<div class="panel p-details"><${PanelHeader} title=${name} /><div class="panel-body"><${Skeleton} lines=${6} /></div></div>`;
|
|
35
|
+
if (!app.ready) return html`<div data-effect-panel="details" class="panel p-details"><${PanelHeader} title=${name} /><div data-trust="panel-content" class="panel-body"><${Skeleton} lines=${6} /></div></div>`;
|
|
31
36
|
if (!inst) {
|
|
32
|
-
return html`<div class="panel p-details"><${PanelHeader} title=${name} />
|
|
33
|
-
<div class="panel-body center"><${Empty} icon="alert" title=${t("chat.notFound", name)} hint=${t("chat.notFoundHint")}
|
|
37
|
+
return html`<div data-effect-panel="details" class="panel p-details"><${PanelHeader} title=${name} />
|
|
38
|
+
<div data-trust="panel-content" class="panel-body center"><${Empty} icon="alert" title=${t("chat.notFound", name)} hint=${t("chat.notFoundHint")}
|
|
34
39
|
action=${html`<button type="button" class="btn only-narrow" onClick=${openDrawer}>${t("chat.backToList")}</button>`} /></div></div>`;
|
|
35
40
|
}
|
|
36
41
|
return html`<${DetailsView} key=${name} name=${name} inst=${inst} navKey=${navKey} exec=${app.exec[name]}
|
|
@@ -38,7 +43,10 @@ export function DetailsPanel({ route, navKey }) {
|
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
function DetailsView({ name, inst, navKey, exec, awaiting }) {
|
|
46
|
+
useStore(themesStore); // #1629: Lock / Unlock follows the themes as read
|
|
41
47
|
const lease = useLease(`details:${name}`);
|
|
48
|
+
// #1629 r4 §1: the identity card at the top, read when the status frame's card_v moves.
|
|
49
|
+
const card = useCard(name, inst.card_v);
|
|
42
50
|
const [d, setD] = useState(null);
|
|
43
51
|
const [failed, setFailed] = useState(false);
|
|
44
52
|
const [busy, setBusy] = useState("");
|
|
@@ -92,6 +100,8 @@ function DetailsView({ name, inst, navKey, exec, awaiting }) {
|
|
|
92
100
|
{ key: "edit", label: t("chat.dEditInSettings"), icon: "settings", onSelect: editInSettings },
|
|
93
101
|
st === "running" ? { key: "pause", label: t("chat.dPause"), icon: "pause", disabled: !!busy, onSelect: () => pauseWake("pause") } : null,
|
|
94
102
|
st === "paused" ? { key: "wake", label: t("chat.dWake"), icon: "play", disabled: !!busy, onSelect: () => pauseWake("wake") } : null,
|
|
103
|
+
colorMenuItem(name, inst), // #1958
|
|
104
|
+
...themeMenuItems(name), // #1629
|
|
95
105
|
] : [
|
|
96
106
|
{ key: "edit", label: t("chat.dEditInSettings"), icon: "settings", onSelect: editInSettings },
|
|
97
107
|
st === "running" ? null : st === "paused" ? null : { key: "start", label: t("chat.start"), icon: "play", disabled: !!busy, onSelect: () => lifecycle("start") },
|
|
@@ -99,6 +109,9 @@ function DetailsView({ name, inst, navKey, exec, awaiting }) {
|
|
|
99
109
|
st === "running" ? { key: "stop", label: t("chat.stopInstance"), icon: "stop", disabled: !!busy, onSelect: () => lifecycle("stop") } : null,
|
|
100
110
|
st === "running" ? { key: "pause", label: t("chat.dPause"), icon: "pause", disabled: !!busy, onSelect: () => pauseWake("pause") } : null,
|
|
101
111
|
st === "paused" ? { key: "wake", label: t("chat.dWake"), icon: "play", disabled: !!busy, onSelect: () => pauseWake("wake") } : null,
|
|
112
|
+
colorMenuItem(name, inst), // #1958: its identity colour (the public link too)
|
|
113
|
+
// #1629: a person's Lock and Reset of this agent's own web theme (not over the public link).
|
|
114
|
+
...themeMenuItems(name),
|
|
102
115
|
];
|
|
103
116
|
|
|
104
117
|
const cls = statusClass(inst, exec, awaiting);
|
|
@@ -131,7 +144,7 @@ function DetailsView({ name, inst, navKey, exec, awaiting }) {
|
|
|
131
144
|
<button type="button" class="btn btn-sm d-edit-settings" onClick=${editInSettings}>${t("chat.dEditInSettings")}</button></div></section>
|
|
132
145
|
<section class="card"><h3>${t("chat.dRuntime")}</h3>
|
|
133
146
|
${row(t("chat.dBackend"), d.backend || "--")}
|
|
134
|
-
${row(t("chat.dModel"), `${d.model || sl.model?.display_name || "--"}${d.model_source === "live" ? "" : src(d.model_source)}`)}
|
|
147
|
+
${row(t("chat.dModel"), `${(d.model && modelText(d)) || sl.model?.display_name || "--"}${d.model_source === "live" ? "" : src(d.model_source)}`)}
|
|
135
148
|
${d.effort ? row(t("chat.dEffort"), `${d.effort}${src(d.effort_source)}`) : null}
|
|
136
149
|
${row(t("chat.dCost"), `$${cost.toFixed(2)} ${t("chat.dCostNote")}`)}
|
|
137
150
|
${row(t("chat.dContext"), html`<span class="pct">${ctx != null ? `${Math.round(ctx)}%` : "--"}</span>${ctx != null ? bar(ctx, ctx > 80 ? "warn" : "") : null}`)}
|
|
@@ -141,8 +154,9 @@ function DetailsView({ name, inst, navKey, exec, awaiting }) {
|
|
|
141
154
|
<span class="mono muted">${a.timestamp ? new Date(`${a.timestamp.replace(" ", "T")}Z`).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }) : ""}</span>
|
|
142
155
|
<span class="ev">${a.event}</span> ${a.summary || ""}</div>`) : html`<p class="note">${t("chat.dNoActivity")}</p>`}</section>`;
|
|
143
156
|
}
|
|
144
|
-
return html`<div class="panel p-details">
|
|
157
|
+
return html`<div data-effect-panel="details" class="panel p-details">
|
|
145
158
|
<${PanelHeader} title=${name} sub=${sub} nav=${html`<${InstanceSwitch} name=${name} current="details" />`}><${HeaderTools} navKey=${navKey} /><${Menu} items=${items} label=${t("app.more")} /></${PanelHeader}>
|
|
146
|
-
<div class="panel-body"><div class="col" ref=${body}>${busy ? html`<p class="note" role="status">${t("chat.dWorking")}</p>` : null}
|
|
159
|
+
<div data-trust="panel-content" class="panel-body"><div class="col" ref=${body}>${busy ? html`<p class="note" role="status">${t("chat.dWorking")}</p>` : null}<${IdentityCard} name=${name} card=${card} />
|
|
160
|
+
<${AgentWidget} slot="details" widget=${widgetFor(name, "details")} binds=${instanceBinds(inst, exec, awaiting)} />${content}</div></div>
|
|
147
161
|
</div>`;
|
|
148
162
|
}
|