@songsid/agend 2.2.1 → 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 +8 -0
- package/dist/daemon.js +298 -22
- package/dist/daemon.js.map +1 -1
- package/dist/decision-list.d.ts +25 -0
- package/dist/decision-list.js +30 -0
- package/dist/decision-list.js.map +1 -0
- package/dist/delivery-outbox.d.ts +10 -0
- package/dist/delivery-outbox.js +12 -1
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/fleet-context.d.ts +15 -0
- package/dist/fleet-manager.d.ts +514 -12
- package/dist/fleet-manager.js +1885 -163
- package/dist/fleet-manager.js.map +1 -1
- package/dist/fleet-process-handlers.d.ts +18 -0
- package/dist/fleet-process-handlers.js +69 -0
- package/dist/fleet-process-handlers.js.map +1 -0
- package/dist/fleet-traffic.d.ts +74 -0
- package/dist/fleet-traffic.js +196 -0
- package/dist/fleet-traffic.js.map +1 -0
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +20 -5
- package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +6 -1
- package/dist/general-knowledge/skills/multi-channel/SKILL.md +3 -2
- package/dist/general-knowledge/skills/persona-emoji/SKILL.md +1 -1
- package/dist/general-knowledge/skills/web-appearance/SKILL.md +492 -0
- package/dist/general-knowledge/skills/web-dashboard/SKILL.md +482 -0
- package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +1 -1
- package/dist/human-delivery-receipts.d.ts +24 -1
- package/dist/human-delivery-receipts.js +64 -11
- package/dist/human-delivery-receipts.js.map +1 -1
- package/dist/instance-avatar.js +3 -0
- package/dist/instance-avatar.js.map +1 -1
- package/dist/instance-config-impact.js +6 -1
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +2 -0
- package/dist/instance-lifecycle.js +20 -10
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instance-names.d.ts +4 -0
- package/dist/instance-names.js +12 -0
- package/dist/instance-names.js.map +1 -0
- package/dist/instructions.d.ts +12 -1
- package/dist/instructions.js +13 -2
- package/dist/instructions.js.map +1 -1
- package/dist/locale.js +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
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, navStore as instanceNavStore } 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,14 +199,51 @@ 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
|
+
// #2188: left before it answered (passing through on the way to another chat) — the read is aborted.
|
|
242
|
+
useEffect(() => {
|
|
243
|
+
const ac = typeof AbortController === "function" ? new AbortController() : null;
|
|
244
|
+
store.openHistory(name, lease, ac?.signal);
|
|
245
|
+
return () => ac?.abort();
|
|
246
|
+
}, [name]);
|
|
182
247
|
useEffect(() => { try { localStorage.setItem("agend_last_instance", name); } catch { /* none */ } }, [name]);
|
|
183
248
|
// Files dragged over the chat show where they go; a drop attaches them (counted, so moving over messages does not flicker).
|
|
184
249
|
useEffect(() => {
|
|
@@ -217,97 +282,219 @@ function ChatView({ name, inst, lease, navKey, exec, awaiting }) {
|
|
|
217
282
|
running ? null : { key: "start", label: t("chat.start"), icon: "play", onSelect: () => action("start") },
|
|
218
283
|
running ? { key: "restart", label: t("chat.restart"), icon: "restart", onSelect: () => action("restart") } : null,
|
|
219
284
|
running ? { key: "stop", label: t("chat.stopInstance"), icon: "stop", onSelect: () => action("stop") } : null,
|
|
285
|
+
// #1958: its identity colour and where it shows (the public link too, as profile edits).
|
|
286
|
+
colorMenuItem(name, inst),
|
|
287
|
+
// #1629: a person's control over this agent's theme — not over the public link (it only views themes).
|
|
288
|
+
...themeMenuItems(name),
|
|
289
|
+
// #2117: its ambient — why it is not showing here (with the way to change that), and a person's Clear.
|
|
290
|
+
...ambientMenuItems(name, { publicLink: document.body.dataset.publicLink === "1", clear: clearAmbient }),
|
|
291
|
+
chatEffectsMenuAvailable() ? { key: "effects", label: t("chatFx.title"), onSelect: () => setDialog("effects") } : null,
|
|
220
292
|
{ key: "delete", label: t("chat.delete"), icon: "trash", danger: true, onSelect: () => setDialog("delete") },
|
|
221
293
|
];
|
|
222
294
|
const cls = statusClass(inst, exec, awaiting);
|
|
295
|
+
// #1920 phase 3: a guest has this chat only — no Details, View or Log to switch to, no lifecycle, colour, theme,
|
|
296
|
+
// effect management or delete (a guest's status frame carries no model or effort either, so those chips do not show).
|
|
297
|
+
const guest = guestPage();
|
|
223
298
|
// #1269 quick actions: the model and effort it runs, each a way to /model or /effort (the same pick list).
|
|
224
299
|
const pick = (command) => store.runCommand(name, command, "", { alive: () => lease.current() });
|
|
225
300
|
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
|
|
301
|
+
${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
302
|
${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
303
|
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}
|
|
304
|
+
<${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}>
|
|
305
|
+
<${ChatCard} key=${name} name=${name} card=${card} />
|
|
306
|
+
<${AgentWidget} slot="chat_header" widget=${widgetFor(name, "chat_header")} binds=${instanceBinds(inst, exec, awaiting)} />
|
|
230
307
|
<div class="chat-split" ref=${split}>
|
|
231
|
-
<div class
|
|
308
|
+
<div ref=${effectSurface} class=${`chat-main${theme && theme.background ? " has-th-bg" : ""}`}>
|
|
309
|
+
${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}
|
|
310
|
+
<${ChatAmbient} name=${name} surface=${effectSurface} part="layer" />
|
|
311
|
+
<${AmbientMotionNote} name=${name} canvasPlaying=${canvasPlayback?.name === name && canvasPlayback.playing} />
|
|
232
312
|
<${Thread} name=${name} th=${thread} />
|
|
233
|
-
<${Dock} name=${name} inst=${inst} lease=${lease} exec=${exec} awaiting=${awaiting} />
|
|
313
|
+
<${Dock} name=${name} inst=${inst} lease=${lease} exec=${exec} awaiting=${awaiting} workingLabel=${theme ? theme.workingLabel : undefined} />
|
|
314
|
+
<${ChatAmbient} name=${name} surface=${effectSurface} part="front" />
|
|
234
315
|
</div>
|
|
235
316
|
<${PreviewPanel} name=${name} split=${split} msgs=${() => store.state.msgs[name] || []} subscribe=${(fn) => store.subscribe(fn)}
|
|
236
317
|
keyOf=${msgKey} reveal=${(k) => thread.current && thread.current.reveal(k)} download=${downloadHtml} allow=${(commit) => setPreviewOptIn(true, commit)} />
|
|
237
318
|
</div>
|
|
238
319
|
<${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>
|
|
320
|
+
<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
321
|
${dialog === "delete" ? html`<${DeleteDialog} name=${name} onClose=${() => setDialog(null)} />` : null}
|
|
241
322
|
</div>`;
|
|
242
323
|
}
|
|
243
324
|
|
|
244
|
-
/**
|
|
325
|
+
/**
|
|
326
|
+
* #2053: the last THREAD_KEEP chats' threads are kept when their view leaves (the chat view is keyed by instance, so
|
|
327
|
+
* each switch built the thread again: a revisit was no faster than a first visit). A kept thread is its list element
|
|
328
|
+
* and its renderer, and nothing more: it leaves as a chat always did (previews stop), with no subscription or timer
|
|
329
|
+
* left; shown again, one render draws only what changed meanwhile, where the reader was. A new language, another
|
|
330
|
+
* document, or more than the budget lets one go.
|
|
331
|
+
*
|
|
332
|
+
* #2184: the budget (raised for people who switch among ~10 favourites): up to THREAD_KEEP threads on a wide screen and
|
|
333
|
+
* THREAD_KEEP_NARROW on a narrow one (a phone), and THREAD_KEEP_NODES drawn messages in all, so memory stays bounded
|
|
334
|
+
* however long the chats are. Over it, the least recently shown goes first — one that is not a favourite before a
|
|
335
|
+
* favourite; the chat on screen never goes.
|
|
336
|
+
*/
|
|
337
|
+
export const THREAD_KEEP = 12;
|
|
338
|
+
export const THREAD_KEEP_NARROW = 6;
|
|
339
|
+
export const THREAD_KEEP_NODES = 2400;
|
|
340
|
+
/**
|
|
341
|
+
* #2188: a chat shown for less than this, on the way to another (clicking down the sidebar), is not kept: it is let go
|
|
342
|
+
* as it leaves, so passing through chats never evicts the ones in use. One that was already kept stays kept.
|
|
343
|
+
*/
|
|
344
|
+
export const THREAD_PASS_MS = 1000;
|
|
345
|
+
const monotonic = () => (typeof performance === "object" && typeof performance.now === "function" ? performance.now() : Date.now());
|
|
346
|
+
let now = monotonic;
|
|
347
|
+
/** Tests only: the clock THREAD_PASS_MS is measured on (null: the page's monotonic clock). */
|
|
348
|
+
export function setThreadClock(fn) { now = typeof fn === "function" ? fn : monotonic; }
|
|
349
|
+
/**
|
|
350
|
+
* The kept threads to let go, in order. `kept`: [name, drawn messages], least recently shown first; `current`: the
|
|
351
|
+
* one on screen (never let go).
|
|
352
|
+
*/
|
|
353
|
+
export function threadsToLetGo(kept, current, { keep, maxNodes, favorites }) {
|
|
354
|
+
let count = kept.length, nodes = kept.reduce((n, [, d]) => n + d, 0);
|
|
355
|
+
const out = [];
|
|
356
|
+
const order = [...kept.filter(([n]) => n !== current && !favorites.has(n)), ...kept.filter(([n]) => n !== current && favorites.has(n))];
|
|
357
|
+
for (const [n, d] of order) {
|
|
358
|
+
if (count <= keep && nodes <= maxNodes) break;
|
|
359
|
+
out.push(n); count--; nodes -= d;
|
|
360
|
+
}
|
|
361
|
+
return out;
|
|
362
|
+
}
|
|
363
|
+
const narrowScreen = () => typeof matchMedia === "function" && matchMedia("(max-width: 899px)").matches;
|
|
364
|
+
/** Let go what the budget does not hold (after `current` was shown, or drew more). */
|
|
365
|
+
function trimKept(current) {
|
|
366
|
+
const kept = [...keptThreads].map(([n, e]) => [n, e.thread.nodes.size]);
|
|
367
|
+
const favorites = new Set(instanceNavStore.get().favorites);
|
|
368
|
+
for (const n of threadsToLetGo(kept, current, { keep: narrowScreen() ? THREAD_KEEP_NARROW : THREAD_KEEP, maxNodes: THREAD_KEEP_NODES, favorites })) {
|
|
369
|
+
letGo(keptThreads.get(n), true); keptThreads.delete(n);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
const keptThreads = new Map(); // name → { thread, list, sink, lang }
|
|
373
|
+
/** Tests only: let every kept thread go. */
|
|
374
|
+
export function forgetKeptThreads() { for (const e of keptThreads.values()) letGo(e, true); keptThreads.clear(); }
|
|
375
|
+
function letGo(e, own) { e.thread.dispose(own); e.list.remove(); }
|
|
376
|
+
|
|
377
|
+
/** A chat's thread: its own list element and renderer, and a sink for the view that shows it. */
|
|
378
|
+
function threadEntry(name, doc) {
|
|
379
|
+
const list = doc.createElement("div");
|
|
380
|
+
list.className = "thread";
|
|
381
|
+
list.setAttribute("role", "log");
|
|
382
|
+
list.setAttribute("aria-live", "off");
|
|
383
|
+
list.setAttribute("aria-label", t("chat.conversationWith", name));
|
|
384
|
+
const e = { list, sink: null, lang: lang(), thread: null };
|
|
385
|
+
const thread = createThread(list, doc.createElement("div"), {
|
|
386
|
+
t, tf: t, isUser: (x) => store.isUser(x, name), onJump: (j) => e.sink?.setJump(j), onEmpty: (v) => e.sink?.setEmpty(v),
|
|
387
|
+
setPreviewOptIn, copyText, download: downloadHtml, toggleWrap,
|
|
388
|
+
effectTrialStatus: x => getAppEffects()?.trialStatus(x) ?? "localAdmin",
|
|
389
|
+
effectTrialFailure: x => getAppEffects()?.trialFailure(x),
|
|
390
|
+
fixEffectTrial: (x, reason) => {
|
|
391
|
+
if (reason === "reducedMotion") setFollowsReducedMotion(false);
|
|
392
|
+
else if (reason === "busy") getAppEffects()?.stopTrial();
|
|
393
|
+
else if (reason === "transport") location.reload();
|
|
394
|
+
else if (reason === "localAdmin") location.href = "/signin?next=" + encodeURIComponent(location.pathname + location.search);
|
|
395
|
+
else navigate("/settings/appearance");
|
|
396
|
+
},
|
|
397
|
+
canTryEffect: x => getAppEffects()?.canTry(x) === true,
|
|
398
|
+
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")); }); },
|
|
399
|
+
clickReplyButton: (id, index) => store.clickReplyButton(name, id, index), // #1266
|
|
400
|
+
replyButtonBusy: (id) => store.state.rbBusy.has(id),
|
|
401
|
+
pollMine: (id) => store.state.pollMine[id], // #1823: this device's own vote
|
|
402
|
+
serverNow: () => Date.now() + store.state.clockSkew, // #1823: the deadline is the server's
|
|
403
|
+
panel: { shown: shownKey, open: (spec, o) => openPanel(spec, o), version: panelVersion, claim: claimPanel, claims: panelClaims }, // #1481, #1704
|
|
404
|
+
openImage: openLightbox, // an image, full size, in the page
|
|
405
|
+
emojis: (id) => !!emojiIndex && emojiIndex.known(id), // #1630: the fleet's server emoji
|
|
406
|
+
mentions: (kind, id) => (mentionIndex ? mentionIndex.name(kind, id) : null), // #1682: mention names
|
|
407
|
+
});
|
|
408
|
+
e.thread = thread;
|
|
409
|
+
return e;
|
|
410
|
+
}
|
|
411
|
+
/** While a thread is shown: what it follows. Returns what lets it all go. */
|
|
412
|
+
function follow(name, thread) {
|
|
413
|
+
// #1630: the server-emoji list is read once a message shows a tag; when it arrives, those messages are drawn again.
|
|
414
|
+
// #1682: the same for mention names — asked for the ids the messages carry; when names arrive, drawn again.
|
|
415
|
+
const wantEmojis = (msgs) => { if (emojiIndex && emojiIndex.wants(msgs)) emojiIndex.ensure(); if (mentionIndex) mentionIndex.ensure(msgs); };
|
|
416
|
+
const offs = [];
|
|
417
|
+
if (emojiIndex) offs.push(emojiIndex.subscribe(() => thread.render(store.state.msgs[name] || [])));
|
|
418
|
+
if (mentionIndex) offs.push(mentionIndex.subscribe(() => thread.render(store.state.msgs[name] || [])));
|
|
419
|
+
wantEmojis(store.state.msgs[name]);
|
|
420
|
+
offs.push(store.subscribe((instance, kind) => {
|
|
421
|
+
if (instance !== name) return;
|
|
422
|
+
if (kind === "msgs") { thread.render(store.state.msgs[name] || []); wantEmojis(store.state.msgs[name]); }
|
|
423
|
+
else if (kind === "sent") thread.jumpLatest();
|
|
424
|
+
}));
|
|
425
|
+
offs.push(P() ? P().onChange(() => thread.refreshCards()) : () => {});
|
|
426
|
+
offs.push(getAppEffects()?.subscribeTrial(() => thread.render(store.state.msgs[name] || [])) ?? (() => {}));
|
|
427
|
+
offs.push(panelStore.subscribe(() => thread.refreshCards())); // a card shows whether the panel has its block
|
|
428
|
+
return () => { for (const off of offs) off(); };
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/** The thread's view: Preact owns the scroller and the jump pill; the kept list (chat-thread.js) is put inside it. */
|
|
245
432
|
function Thread({ name, th }) {
|
|
246
|
-
const scroller = useRef(null),
|
|
433
|
+
const scroller = useRef(null), host = useRef(null);
|
|
247
434
|
const [jump, setJump] = useState({ show: false, unseen: 0 });
|
|
248
435
|
const [empty, setEmpty] = useState(false);
|
|
249
436
|
useLayoutEffect(() => {
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
437
|
+
const doc = host.current.ownerDocument;
|
|
438
|
+
let e = keptThreads.get(name);
|
|
439
|
+
// Kept only while it can be shown as it is: the same language, and this page's own document.
|
|
440
|
+
if (e && (e.lang !== lang() || e.list.ownerDocument !== doc)) { letGo(e, true); keptThreads.delete(name); e = undefined; }
|
|
441
|
+
const kept = !!e;
|
|
442
|
+
if (e) keptThreads.delete(name);
|
|
443
|
+
else e = threadEntry(name, doc);
|
|
444
|
+
keptThreads.set(name, e); // the most recent last
|
|
445
|
+
// A thread already kept is trimmed against at once; a new one first has to stay (see THREAD_PASS_MS).
|
|
446
|
+
if (kept) trimKept(name);
|
|
447
|
+
const shownAt = now();
|
|
448
|
+
const thread = e.thread, sc = scroller.current, ls = e.list;
|
|
449
|
+
e.sink = { setJump, setEmpty };
|
|
450
|
+
host.current.append(ls);
|
|
451
|
+
thread.attach(sc);
|
|
262
452
|
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] || [])) : () => {};
|
|
453
|
+
// 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
454
|
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
|
|
455
|
+
if (kept) thread.refreshCards();
|
|
456
|
+
const unfollow = follow(name, thread);
|
|
277
457
|
const onScroll = () => { store.state.scrollMemo[name] = thread.onScroll(); };
|
|
278
|
-
const sc = scroller.current, ls = list.current;
|
|
279
458
|
sc.addEventListener("scroll", onScroll, { passive: true });
|
|
280
459
|
ls.addEventListener("click", thread.onClick);
|
|
281
460
|
return () => {
|
|
282
|
-
|
|
461
|
+
unfollow();
|
|
283
462
|
sc.removeEventListener("scroll", onScroll);
|
|
284
463
|
ls.removeEventListener("click", thread.onClick);
|
|
285
|
-
|
|
464
|
+
e.sink = null;
|
|
286
465
|
th.current = null;
|
|
466
|
+
// Passed through (new, and shown under THREAD_PASS_MS): let go. Otherwise kept for a later visit, within the budget.
|
|
467
|
+
if (keptThreads.get(name) === e && !kept && now() - shownAt < THREAD_PASS_MS) { keptThreads.delete(name); letGo(e, false); }
|
|
468
|
+
else if (keptThreads.get(name) === e) { thread.park(); ls.remove(); trimKept(null); } // kept for a later visit: the chat left
|
|
469
|
+
else letGo(e, false); // let go meanwhile (a new language)
|
|
287
470
|
};
|
|
288
471
|
}, [name]);
|
|
289
472
|
return html`<div class="scroller" ref=${scroller}>
|
|
290
|
-
<div class="thread" ref=${
|
|
473
|
+
<div class="thread-host" ref=${host}></div>
|
|
291
474
|
${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}
|
|
475
|
+
<div class="jump-dock">${jump.show ? html`<button data-trust="thread-control" type="button" class="jump-latest" onClick=${() => th.current && th.current.jumpLatest()}>
|
|
476
|
+
<${Icon} name="down" size=${16} />${jump.unseen > 0 ? t("chat.newBelow", jump.unseen) : t("chat.jumpLatest")}</button>` : null}</div>
|
|
294
477
|
</div>`;
|
|
295
478
|
}
|
|
296
479
|
|
|
297
480
|
/** Everything under the thread: prompts, the working line, a failed send, files waiting, and the composer. */
|
|
298
|
-
function Dock({ name, inst, lease, exec, awaiting }) {
|
|
481
|
+
function Dock({ name, inst, lease, exec, awaiting, workingLabel }) {
|
|
299
482
|
useChatTick(name, ["state"]);
|
|
300
483
|
const s = store.state;
|
|
301
|
-
return html`<div class="dock"><div class="dock-col">
|
|
484
|
+
return html`<div data-trust="composer" class="dock"><div class="dock-col">
|
|
302
485
|
<${Prompts} name=${name} />
|
|
303
|
-
<${WorkBar} name=${name} lease=${lease} exec=${exec} awaiting=${awaiting} />
|
|
486
|
+
<${WorkBar} name=${name} lease=${lease} exec=${exec} awaiting=${awaiting} workingLabel=${workingLabel} />
|
|
304
487
|
<${CommandCard} name=${name} lease=${lease} />
|
|
305
488
|
<${QuickActions} name=${name} inst=${inst} lease=${lease} />
|
|
306
489
|
${s.failedSends[name] ? html`<div class="failed-send" role="alert"><span>${t("chat.notSent")}</span><span class="txt">${s.failedSends[name]}</span>
|
|
307
490
|
<button type="button" class="btn btn-primary btn-sm" onClick=${() => store.putBack(name)}>${t("chat.putBack")}</button>
|
|
308
491
|
<button type="button" class="btn btn-sm" onClick=${() => store.discardFailed(name)}>${t("chat.discard")}</button></div>` : null}
|
|
492
|
+
${s.waking[name] ? html`<p class="send-waking" role="status">${t("chat.waking", name)}</p>` : null}
|
|
493
|
+
${s.sendFailures[name] ? html`<div class="failed-send send-failure" role="alert"><span>${s.sendFailures[name].error}</span>
|
|
494
|
+
<button type="button" class="btn btn-sm" disabled=${!store.canRetrySend(name)} onClick=${() => store.retrySend(name)}>${t("chat.retrySend")}</button></div>` : null}
|
|
309
495
|
<${Composer} name=${name} lease=${lease} busy=${R().isBusy(exec)} />
|
|
310
|
-
<p class="hint" title=${t("chat.composerMore")}>${t("chat.composerHint")}</p>
|
|
496
|
+
<p class="hint" title=${t(guestPage() ? "chat.guestMore" : "chat.composerMore")}>${t("chat.composerHint")}</p>
|
|
497
|
+
${guestPage() ? html`<p class="guest-note">${t("chat.guestNote")}</p>` : html`<${AuthorizeChip} />`}
|
|
311
498
|
</div></div>`;
|
|
312
499
|
}
|
|
313
500
|
|
|
@@ -327,7 +514,8 @@ function CommandCard({ name, lease }) {
|
|
|
327
514
|
: c.compact === "lost" ? t("chat.compactLost") : c.compact === "not_compacted" ? t("chat.compactNotCompacted") : t("chat.compactUnknown")}</p>` : null}
|
|
328
515
|
${c.choices && c.choices.prompt ? html`<pre class="cmd-text">${c.choices.prompt}</pre>` : null}
|
|
329
516
|
${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}
|
|
517
|
+
class=${`btn btn-sm${o.id === c.choices.current ? " current" : ""}`} aria-current=${o.id === c.choices.current ? "true" : undefined}
|
|
518
|
+
disabled=${!!o.disabled} title=${o.disabled || undefined} onClick=${() => { if (!o.disabled) run(o.id); }}>${o.label}</button>`)}</div>` : null}
|
|
331
519
|
</div>`;
|
|
332
520
|
}
|
|
333
521
|
|
|
@@ -347,14 +535,14 @@ function QuickActions({ name, inst, lease }) {
|
|
|
347
535
|
function Prompts({ name }) {
|
|
348
536
|
const list = store.promptsFor(name);
|
|
349
537
|
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>
|
|
538
|
+
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}>
|
|
539
|
+
<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
540
|
${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
541
|
${p.busy ? html`<span class="wait">${t("chat.promptAnswering")}</span>` : null}</div>`}</div>`)}</div>`;
|
|
354
542
|
}
|
|
355
543
|
|
|
356
544
|
/** "<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 }) {
|
|
545
|
+
function WorkBar({ name, lease, exec, awaiting, workingLabel }) {
|
|
358
546
|
const s = store.state;
|
|
359
547
|
const busy = R().isBusy(exec) ? exec : "";
|
|
360
548
|
const kind = awaiting != null ? "awaiting" : s.stopping[name] && busy ? "stopping" : busy;
|
|
@@ -365,7 +553,9 @@ function WorkBar({ name, lease, exec, awaiting }) {
|
|
|
365
553
|
return () => lease.clear(h);
|
|
366
554
|
}, [kind, lease]);
|
|
367
555
|
if (!kind) return null;
|
|
368
|
-
|
|
556
|
+
// #1629: the agent's own working label (its theme), shown as text — only for "working", never for the other states.
|
|
557
|
+
const label = kind === "working" && workingLabel ? workingLabel
|
|
558
|
+
: t(kind === "stuck" ? "chat.stuck" : kind === "stopping" ? "chat.stopping" : kind === "awaiting" ? "chat.awaiting" : "chat.working", name);
|
|
369
559
|
const since = s.workingSince[name];
|
|
370
560
|
return html`<div class=${`work-bar ${kind}`}><span class="pulse" aria-hidden="true"></span><span class="lbl">${label}</span>
|
|
371
561
|
${kind === "awaiting" ? html`<span class="note" title=${t("chat.approxNote")}>${awaiting || t("chat.approxNote")}</span>`
|
|
@@ -381,8 +571,10 @@ function Composer({ name, lease, busy }) {
|
|
|
381
571
|
const value = s.drafts[name] || "";
|
|
382
572
|
const files = s.pendingFiles[name] || [];
|
|
383
573
|
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
|
-
|
|
574
|
+
// A file waiting: what goes is a message with its file, never a command (no palette, no command line). A guest never
|
|
575
|
+
// runs one (#1920: the server refuses its slash text), so it has no palette either.
|
|
576
|
+
const guest = guestPage();
|
|
577
|
+
const palette = guest || files.length || closedFor === value ? null : paletteFor(value);
|
|
386
578
|
const pick = palette && palette.length ? palette[Math.min(sel, palette.length - 1)] : null;
|
|
387
579
|
// Grow with the text, up to a limit: set through the CSSOM, never a style attribute (#1300).
|
|
388
580
|
useLayoutEffect(() => { const el = input.current; if (!el) return; el.style.height = "auto"; el.style.height = `${Math.min(el.scrollHeight, 240)}px`; }, [value]);
|
|
@@ -403,6 +595,8 @@ function Composer({ name, lease, busy }) {
|
|
|
403
595
|
else complete(pick);
|
|
404
596
|
return;
|
|
405
597
|
}
|
|
598
|
+
// #1920: a guest's "/…" would be refused as a command — said here, the draft kept to edit.
|
|
599
|
+
if (guest && /^\s*\//.test(value)) { toast(t("chat.guestNoCommands"), false); return; }
|
|
406
600
|
const cmd = files.length ? null : parseCommandLine(value);
|
|
407
601
|
if (cmd && needsArgument(cmd.command) && !cmd.args) { setValue(`/${cmd.command} `); return; }
|
|
408
602
|
if (cmd) { runLine(cmd); return; }
|
|
@@ -428,7 +622,7 @@ function Composer({ name, lease, busy }) {
|
|
|
428
622
|
};
|
|
429
623
|
const optId = (c) => `cmd-${c.name}`;
|
|
430
624
|
return html`<div class="composer-box">
|
|
431
|
-
${palette ? html`<ul class="cmd-palette" id="cmdPalette" role="listbox" aria-label=${t("chat.cmdCommands")}>
|
|
625
|
+
${palette ? html`<ul data-trust="palette" class="cmd-palette" id="cmdPalette" role="listbox" aria-label=${t("chat.cmdCommands")}>
|
|
432
626
|
${palette.length ? palette.map((c) => html`<li key=${c.name} id=${optId(c)} role="option" aria-selected=${c === pick ? "true" : "false"}
|
|
433
627
|
class=${c === pick ? "on" : ""} onMouseDown=${(e) => { e.preventDefault(); complete(c); }}>
|
|
434
628
|
<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
|
}
|