@songsid/agend 2.3.0-beta.8 → 2.3.0
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/README.md +16 -8
- package/README.zh-TW.md +16 -8
- package/dist/adapter-world.js.map +1 -1
- package/dist/agend-home.d.ts +5 -0
- package/dist/agend-home.js +7 -0
- package/dist/agend-home.js.map +1 -0
- package/dist/agent-cli-instructions.md +9 -2
- package/dist/agent-cli.js +44 -0
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.d.ts +9 -0
- package/dist/agent-endpoint.js +23 -0
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-file-read.js +1 -1
- package/dist/agent-file-read.js.map +1 -1
- package/dist/agent-whats-new.d.ts +16 -0
- package/dist/agent-whats-new.js +54 -11
- package/dist/agent-whats-new.js.map +1 -1
- package/dist/apply-job.js.map +1 -1
- package/dist/atomic-write.js.map +1 -1
- package/dist/auth-api.d.ts +12 -0
- package/dist/auth-api.js +77 -22
- package/dist/auth-api.js.map +1 -1
- package/dist/authority/authority-state.d.ts +4 -0
- package/dist/authority/authority-state.js +17 -8
- package/dist/authority/authority-state.js.map +1 -1
- package/dist/authority/session-authorizations.js.map +1 -1
- package/dist/authority/web-authority.d.ts +16 -8
- package/dist/authority/web-authority.js +19 -5
- package/dist/authority/web-authority.js.map +1 -1
- package/dist/backend/antigravity.d.ts +2 -2
- package/dist/backend/antigravity.js +2 -1
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-code.js +13 -4
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/codex-metadata.d.ts +8 -0
- package/dist/backend/codex-metadata.js +74 -17
- package/dist/backend/codex-metadata.js.map +1 -1
- package/dist/backend/codex-package.d.ts +30 -0
- package/dist/backend/codex-package.js +133 -0
- package/dist/backend/codex-package.js.map +1 -0
- package/dist/backend/codex-session-lookup.js.map +1 -1
- package/dist/backend/codex.d.ts +2 -0
- package/dist/backend/codex.js +25 -5
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/credential-profile.d.ts +2 -0
- package/dist/backend/credential-profile.js +2 -0
- package/dist/backend/credential-profile.js.map +1 -1
- package/dist/backend/effort-metadata.js.map +1 -1
- package/dist/backend/grok.js +58 -3
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro-engine-ledger.js.map +1 -1
- package/dist/backend/kiro-kas-store.js.map +1 -1
- package/dist/backend/kiro-v2-store.js.map +1 -1
- package/dist/backend/kiro-v3-identity.js.map +1 -1
- package/dist/backend/kiro.d.ts +9 -1
- package/dist/backend/kiro.js +102 -1
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/launch-effort.js.map +1 -1
- package/dist/backend/mock.js.map +1 -1
- package/dist/backend/muse.js.map +1 -1
- package/dist/backend/opencode-permission.js +1 -1
- package/dist/backend/opencode-permission.js.map +1 -1
- package/dist/backend/opencode.js +2 -1
- package/dist/backend/opencode.js.map +1 -1
- package/dist/backend/session-signals.js.map +1 -1
- package/dist/backend-availability.js.map +1 -1
- package/dist/backend-command.d.ts +2 -0
- package/dist/backend-command.js +3 -1
- package/dist/backend-command.js.map +1 -1
- package/dist/backend-outage.js.map +1 -1
- package/dist/binary-probe.js +1 -1
- package/dist/binary-probe.js.map +1 -1
- package/dist/bug-report-cli.d.ts +30 -0
- package/dist/bug-report-cli.js +139 -0
- package/dist/bug-report-cli.js.map +1 -0
- package/dist/bug-report.d.ts +47 -0
- package/dist/bug-report.js +137 -0
- package/dist/bug-report.js.map +1 -0
- package/dist/bundled-skills.d.ts +18 -0
- package/dist/bundled-skills.js +38 -0
- package/dist/bundled-skills.js.map +1 -0
- package/dist/cache-service.js +1 -1
- 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 +4 -0
- package/dist/channel/adapters/discord.js +57 -12
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +6 -0
- package/dist/channel/adapters/telegram.js +54 -14
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/mcp-server.js +21 -4
- package/dist/channel/mcp-server.js.map +1 -1
- package/dist/channel/mcp-tools.d.ts +3 -1
- package/dist/channel/mcp-tools.js +43 -6
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/message-queue.js.map +1 -1
- package/dist/channel/sticker-download.js.map +1 -1
- package/dist/channel/tool-router.js.map +1 -1
- package/dist/child-process.d.ts +21 -0
- package/dist/child-process.js +54 -0
- package/dist/child-process.js.map +1 -0
- package/dist/classic-channel-manager.js +3 -2
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli-entry.js.map +1 -1
- package/dist/cli-flags.js.map +1 -1
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +443 -311
- package/dist/cli.js.map +1 -1
- package/dist/command-table.d.ts +1 -1
- package/dist/command-table.js +1 -1
- package/dist/command-table.js.map +1 -1
- package/dist/compact-watch.js.map +1 -1
- package/dist/completion-install.js.map +1 -1
- package/dist/completion.js.map +1 -1
- package/dist/config-validator.d.ts +6 -0
- package/dist/config-validator.js +81 -8
- package/dist/config-validator.js.map +1 -1
- package/dist/config.d.ts +15 -3
- package/dist/config.js +41 -10
- package/dist/config.js.map +1 -1
- package/dist/connection-secrets.js.map +1 -1
- package/dist/context-guardian.js.map +1 -1
- package/dist/coredump-filter.js.map +1 -1
- package/dist/cpu-profile.js.map +1 -1
- package/dist/cross-instance-envelope.js.map +1 -1
- package/dist/cross-instance-notice.d.ts +7 -0
- package/dist/cross-instance-notice.js +10 -0
- package/dist/cross-instance-notice.js.map +1 -1
- package/dist/daemon.d.ts +39 -1
- package/dist/daemon.js +234 -15
- package/dist/daemon.js.map +1 -1
- package/dist/daily-summary.js.map +1 -1
- package/dist/darwin-memory.js +1 -1
- package/dist/darwin-memory.js.map +1 -1
- package/dist/dashboard-live.d.ts +8 -0
- package/dist/dashboard-live.js +35 -0
- package/dist/dashboard-live.js.map +1 -0
- package/dist/dashboard-permissions.d.ts +69 -0
- package/dist/dashboard-permissions.js +138 -0
- package/dist/dashboard-permissions.js.map +1 -0
- 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-consumed-watch.js.map +1 -1
- package/dist/delivery-outbox.js +5 -0
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/delivery-outbox.test.js.map +1 -1
- package/dist/delivery-reconciliation.test.js.map +1 -1
- package/dist/diagnostic-redaction.d.ts +10 -0
- package/dist/diagnostic-redaction.js +167 -0
- package/dist/diagnostic-redaction.js.map +1 -0
- package/dist/doctor.d.ts +8 -0
- package/dist/doctor.js +52 -0
- package/dist/doctor.js.map +1 -1
- package/dist/e2e-isolation.js.map +1 -1
- package/dist/event-log.js.map +1 -1
- package/dist/export-import.js +7 -5
- package/dist/export-import.js.map +1 -1
- package/dist/fleet-control-audit.js.map +1 -1
- package/dist/fleet-label.js.map +1 -1
- package/dist/fleet-level-config.d.ts +1 -1
- package/dist/fleet-level-config.js +2 -0
- package/dist/fleet-level-config.js.map +1 -1
- package/dist/fleet-lock.js +3 -2
- package/dist/fleet-lock.js.map +1 -1
- package/dist/fleet-manager.d.ts +258 -15
- package/dist/fleet-manager.js +1605 -304
- package/dist/fleet-manager.js.map +1 -1
- package/dist/fleet-process-handlers.d.ts +18 -0
- package/dist/fleet-process-handlers.js +70 -0
- package/dist/fleet-process-handlers.js.map +1 -0
- package/dist/fleet-startup.d.ts +14 -0
- package/dist/fleet-startup.js +30 -0
- package/dist/fleet-startup.js.map +1 -0
- package/dist/fleet-traffic.d.ts +36 -0
- package/dist/fleet-traffic.js +100 -0
- package/dist/fleet-traffic.js.map +1 -1
- package/dist/forged-envelope-scan.d.ts +0 -20
- package/dist/forged-envelope-scan.js +3 -2
- package/dist/forged-envelope-scan.js.map +1 -1
- package/dist/full-restart.d.ts +5 -5
- package/dist/full-restart.js +5 -5
- package/dist/full-restart.js.map +1 -1
- package/dist/general-knowledge/skills/bug-report/SKILL.md +31 -0
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +52 -11
- package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +5 -1
- package/dist/general-knowledge/skills/fleet-config/SKILL.md +3 -1
- package/dist/general-knowledge/skills/fleet-restart/SKILL.md +8 -9
- package/dist/general-knowledge/skills/multi-channel/SKILL.md +1 -1
- package/dist/general-knowledge/skills/persona-emoji/SKILL.md +1 -1
- package/dist/general-knowledge/skills/scheduling/SKILL.md +4 -0
- package/dist/general-knowledge/skills/web-appearance/SKILL.canvas-worker-off.md +321 -0
- package/dist/general-knowledge/skills/web-appearance/SKILL.md +28 -4
- package/dist/general-knowledge/skills/web-dashboard/SKILL.canvas-worker-off.md +553 -0
- package/dist/general-knowledge/skills/web-dashboard/SKILL.md +170 -35
- package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +1 -1
- package/dist/general-knowledge/steering/core-rules.md +1 -1
- package/dist/host-memory.js.map +1 -1
- package/dist/idle-gate-log.d.ts +19 -0
- package/dist/idle-gate-log.js +15 -0
- package/dist/idle-gate-log.js.map +1 -0
- package/dist/instance-config-impact.js +25 -4
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +10 -1
- package/dist/instance-lifecycle.js +86 -25
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instructions.d.ts +12 -6
- package/dist/instructions.js +19 -10
- package/dist/instructions.js.map +1 -1
- package/dist/kiro-compact-pane.js.map +1 -1
- package/dist/kiro-db-reader.js.map +1 -1
- package/dist/kiro-engine-status.js.map +1 -1
- package/dist/kiro-log-gate.js.map +1 -1
- package/dist/kiro-transcript-lane.js.map +1 -1
- package/dist/locale.js +428 -20
- package/dist/locale.js.map +1 -1
- package/dist/log-service.js.map +1 -1
- package/dist/log-steps.d.ts +1 -0
- package/dist/log-steps.js +15 -0
- package/dist/log-steps.js.map +1 -1
- package/dist/logger.js +3 -2
- package/dist/logger.js.map +1 -1
- package/dist/login-controller.d.ts +45 -0
- package/dist/login-controller.js +101 -5
- package/dist/login-controller.js.map +1 -1
- package/dist/login-flows.js +1 -1
- package/dist/login-manager.js.map +1 -1
- package/dist/login-shell.js +3 -1
- package/dist/login-shell.js.map +1 -1
- package/dist/ls-attach-resolve.d.ts +96 -0
- package/dist/ls-attach-resolve.js +180 -0
- package/dist/ls-attach-resolve.js.map +1 -0
- package/dist/ls-rows.d.ts +12 -0
- package/dist/ls-rows.js +83 -4
- package/dist/ls-rows.js.map +1 -1
- package/dist/memory-pressure.js.map +1 -1
- package/dist/muse-usage-relay.js.map +1 -1
- package/dist/needs-you-hub.d.ts +98 -1
- package/dist/needs-you-hub.js +313 -44
- package/dist/needs-you-hub.js.map +1 -1
- package/dist/needs-you-live.d.ts +5 -2
- package/dist/needs-you-live.js +6 -3
- package/dist/needs-you-live.js.map +1 -1
- package/dist/needs-you.d.ts +68 -3
- package/dist/needs-you.js +38 -4
- package/dist/needs-you.js.map +1 -1
- package/dist/network-family.js.map +1 -1
- package/dist/operator-control-paths.js +3 -4
- package/dist/operator-control-paths.js.map +1 -1
- package/dist/outbound-handlers.d.ts +3 -0
- package/dist/outbound-handlers.js +76 -19
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +112 -64
- package/dist/outbound-schemas.js +39 -12
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/outbox-open-error.js.map +1 -1
- package/dist/pane-context-cache.js.map +1 -1
- package/dist/paths.js.map +1 -1
- package/dist/private-dir.js.map +1 -1
- package/dist/probe-worker-pool.js.map +1 -1
- package/dist/profile-control.js.map +1 -1
- package/dist/prompt-file-ref.js.map +1 -1
- package/dist/provider-probe.js.map +1 -1
- package/dist/provider-secret-registry.d.ts +5 -3
- package/dist/provider-secret-registry.js +8 -2
- package/dist/provider-secret-registry.js.map +1 -1
- package/dist/public-link-auto-open.d.ts +32 -0
- package/dist/public-link-auto-open.js +86 -0
- package/dist/public-link-auto-open.js.map +1 -0
- package/dist/public-link-owner.d.ts +10 -0
- package/dist/public-link-owner.js +36 -0
- package/dist/public-link-owner.js.map +1 -0
- package/dist/public-link-progress.d.ts +12 -1
- package/dist/public-link-progress.js +5 -10
- package/dist/public-link-progress.js.map +1 -1
- package/dist/public-preview.js.map +1 -1
- package/dist/public-tunnel-config.d.ts +11 -0
- package/dist/public-tunnel-config.js +68 -0
- package/dist/public-tunnel-config.js.map +1 -0
- package/dist/public-web-gateway.d.ts +2 -0
- package/dist/public-web-gateway.js +19 -6
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/public-web-link.d.ts +48 -3
- package/dist/public-web-link.js +177 -51
- package/dist/public-web-link.js.map +1 -1
- package/dist/quickstart-api.d.ts +9 -0
- package/dist/quickstart-api.js +82 -0
- package/dist/quickstart-api.js.map +1 -1
- package/dist/quickstart.d.ts +5 -0
- package/dist/quickstart.js +40 -25
- package/dist/quickstart.js.map +1 -1
- package/dist/reply-buttons-controller.js.map +1 -1
- package/dist/reply-dedup.js.map +1 -1
- package/dist/resource-report.js +1 -1
- package/dist/resource-report.js.map +1 -1
- package/dist/restart-guard.js.map +1 -1
- package/dist/restart-progress.d.ts +80 -1
- package/dist/restart-progress.js +306 -21
- package/dist/restart-progress.js.map +1 -1
- package/dist/rollout-index.js.map +1 -1
- package/dist/runtime-cpu-profile.js.map +1 -1
- package/dist/scheduler/db.d.ts +40 -13
- package/dist/scheduler/db.js +123 -89
- package/dist/scheduler/db.js.map +1 -1
- package/dist/scheduler/scheduler.js.map +1 -1
- package/dist/scheduler/task-board-text.d.ts +26 -0
- package/dist/scheduler/task-board-text.js +140 -0
- package/dist/scheduler/task-board-text.js.map +1 -0
- package/dist/scheduler/task-board.d.ts +730 -0
- package/dist/scheduler/task-board.js +2179 -0
- package/dist/scheduler/task-board.js.map +1 -0
- package/dist/scheduler/types.d.ts +6 -1
- package/dist/sd-notify.js +2 -1
- package/dist/sd-notify.js.map +1 -1
- package/dist/search/search-docs.d.ts +58 -0
- package/dist/search/search-docs.js +63 -0
- package/dist/search/search-docs.js.map +1 -0
- package/dist/search/search-index.d.ts +141 -0
- package/dist/search/search-index.js +440 -0
- package/dist/search/search-index.js.map +1 -0
- package/dist/search/search-store.d.ts +122 -0
- package/dist/search/search-store.js +236 -0
- package/dist/search/search-store.js.map +1 -0
- package/dist/search/search-worker.d.ts +1 -0
- package/dist/search/search-worker.js +163 -0
- package/dist/search/search-worker.js.map +1 -0
- package/dist/secret-file.js.map +1 -1
- package/dist/secret-store.d.ts +2 -0
- package/dist/secret-store.js +21 -0
- package/dist/secret-store.js.map +1 -1
- package/dist/service-installer.d.ts +75 -0
- package/dist/service-installer.js +206 -0
- package/dist/service-installer.js.map +1 -1
- package/dist/service-owner.d.ts +44 -0
- package/dist/service-owner.js +48 -0
- package/dist/service-owner.js.map +1 -0
- package/dist/service-plan.d.ts +39 -2
- package/dist/service-plan.js +188 -6
- package/dist/service-plan.js.map +1 -1
- package/dist/session-oom.d.ts +21 -0
- package/dist/session-oom.js +139 -0
- package/dist/session-oom.js.map +1 -0
- package/dist/settings-api.d.ts +13 -0
- package/dist/settings-api.js +73 -12
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-baseline.js.map +1 -1
- package/dist/settings-change.d.ts +5 -0
- package/dist/settings-change.js +167 -6
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-confirmation.d.ts +9 -1
- package/dist/settings-confirmation.js +18 -8
- package/dist/settings-confirmation.js.map +1 -1
- package/dist/settings-control.js +2 -1
- package/dist/settings-control.js.map +1 -1
- package/dist/settings-effect.js +29 -4
- package/dist/settings-effect.js.map +1 -1
- package/dist/settings-http-confirmation.d.ts +13 -0
- package/dist/settings-http-confirmation.js +15 -3
- package/dist/settings-http-confirmation.js.map +1 -1
- package/dist/settings-instance-patch.js +13 -1
- package/dist/settings-instance-patch.js.map +1 -1
- package/dist/settings-request-capability.d.ts +4 -1
- package/dist/settings-request-capability.js +11 -3
- package/dist/settings-request-capability.js.map +1 -1
- package/dist/settings-transaction.js.map +1 -1
- package/dist/setup-auth.d.ts +1 -0
- package/dist/setup-auth.js +2 -1
- package/dist/setup-auth.js.map +1 -1
- package/dist/setup-form.d.ts +1 -1
- package/dist/setup-form.js +23 -7
- package/dist/setup-form.js.map +1 -1
- package/dist/setup-host.d.ts +6 -1
- package/dist/setup-host.js +15 -4
- package/dist/setup-host.js.map +1 -1
- package/dist/setup-wizard.js +6 -3
- package/dist/setup-wizard.js.map +1 -1
- package/dist/spawn-gate.d.ts +5 -0
- package/dist/spawn-gate.js +28 -8
- package/dist/spawn-gate.js.map +1 -1
- package/dist/start-attempt.d.ts +1 -0
- package/dist/start-attempt.js +18 -0
- package/dist/start-attempt.js.map +1 -0
- package/dist/start-failure-notice.d.ts +4 -0
- package/dist/start-failure-notice.js +20 -0
- package/dist/start-failure-notice.js.map +1 -0
- package/dist/start-failure.d.ts +147 -0
- package/dist/start-failure.js +281 -0
- package/dist/start-failure.js.map +1 -0
- package/dist/startup-memory-deadline.d.ts +23 -0
- package/dist/startup-memory-deadline.js +55 -0
- package/dist/startup-memory-deadline.js.map +1 -0
- package/dist/statusline-watcher.js.map +1 -1
- package/dist/storm-window.js.map +1 -1
- package/dist/systemd-peer-bus.js.map +1 -1
- package/dist/target-queue-worker.js.map +1 -1
- package/dist/task-board-summary.d.ts +101 -0
- package/dist/task-board-summary.js +177 -0
- package/dist/task-board-summary.js.map +1 -0
- package/dist/task-board-tool.d.ts +25 -0
- package/dist/task-board-tool.js +155 -0
- package/dist/task-board-tool.js.map +1 -0
- package/dist/task-board-waker.d.ts +51 -0
- package/dist/task-board-waker.js +141 -0
- package/dist/task-board-waker.js.map +1 -0
- package/dist/tips.js.map +1 -1
- package/dist/tmux-control.js +1 -1
- package/dist/tmux-control.js.map +1 -1
- package/dist/tmux-exec-helper.d.ts +104 -0
- package/dist/tmux-exec-helper.js +412 -0
- package/dist/tmux-exec-helper.js.map +1 -0
- package/dist/tmux-manager.d.ts +1 -0
- package/dist/tmux-manager.js +29 -13
- package/dist/tmux-manager.js.map +1 -1
- package/dist/tmux-read.js +2 -2
- package/dist/tmux-read.js.map +1 -1
- package/dist/tool-permissions.js +9 -42
- package/dist/tool-permissions.js.map +1 -1
- package/dist/tool-progress.js.map +1 -1
- package/dist/topic-archiver.js.map +1 -1
- package/dist/topic-commands.d.ts +13 -0
- package/dist/topic-commands.js +56 -33
- package/dist/topic-commands.js.map +1 -1
- package/dist/topic-link.js.map +1 -1
- package/dist/transcript-delta-reader.js.map +1 -1
- package/dist/transcript-jsonl.js.map +1 -1
- package/dist/transcript-monitor.js +5 -0
- package/dist/transcript-monitor.js.map +1 -1
- package/dist/transcript-sources.d.ts +2 -0
- package/dist/transcript-sources.js +4 -0
- package/dist/transcript-sources.js.map +1 -1
- package/dist/tunnel/cloudflared-install.js +3 -1
- package/dist/tunnel/cloudflared-install.js.map +1 -1
- package/dist/tunnel/cloudflared.d.ts +7 -16
- package/dist/tunnel/cloudflared.js +100 -13
- package/dist/tunnel/cloudflared.js.map +1 -1
- package/dist/tunnel/lease.js +3 -2
- package/dist/tunnel/lease.js.map +1 -1
- package/dist/tunnel/manager.js.map +1 -1
- package/dist/tunnel/named-diagnostics.d.ts +13 -0
- package/dist/tunnel/named-diagnostics.js +52 -0
- package/dist/tunnel/named-diagnostics.js.map +1 -0
- package/dist/tunnel/public-fetch.js.map +1 -1
- package/dist/tunnel/purpose-lane.js.map +1 -1
- package/dist/tunnel/types.d.ts +4 -1
- package/dist/tunnel/types.js.map +1 -1
- package/dist/types.d.ts +55 -2
- package/dist/ui/app-effects.js +27 -5
- package/dist/ui/app.html +2 -0
- package/dist/ui/backend-signin.js +297 -0
- package/dist/ui/chat-effects.js +15 -7
- package/dist/ui/chat-msg-actions.js +176 -0
- package/dist/ui/chat-render.js +67 -20
- package/dist/ui/chat-store.js +218 -48
- package/dist/ui/chat-strings.js +42 -10
- package/dist/ui/chat-thread.js +249 -23
- package/dist/ui/effect-trial-controller.js +13 -8
- package/dist/ui/effect-trial-offer.js +2 -31
- package/dist/ui/effects-waker.js +2 -0
- package/dist/ui/fleet-canvas-layout.js +13 -4
- package/dist/ui/fleet-canvas.js +120 -43
- package/dist/ui/fleet-office-editor.js +149 -0
- package/dist/ui/fleet-office-model.js +358 -0
- package/dist/ui/fleet-office-pack.js +199 -0
- package/dist/ui/fleet-office-skin.js +474 -0
- package/dist/ui/fleet-office-store.js +49 -0
- package/dist/ui/fleet-office-zones.js +177 -0
- package/dist/ui/fleet-office.js +434 -0
- package/dist/ui/fleet-org.js +21 -8
- package/dist/ui/fleet-route-scene.js +272 -0
- package/dist/ui/fleet-route-worker.js +21 -0
- package/dist/ui/fleet-route.js +88 -0
- package/dist/ui/fleet-task-card.js +436 -0
- package/dist/ui/fleet-task-common.js +482 -0
- package/dist/ui/fleet-task-work.js +107 -0
- package/dist/ui/fleet-tasks.js +569 -0
- package/dist/ui/fleet-traffic.js +227 -45
- package/dist/ui/fleet-usage.js +36 -2
- package/dist/ui/guest-refused.html +41 -0
- package/dist/ui/icons/icon-192.png +0 -0
- package/dist/ui/icons/icon-512.png +0 -0
- package/dist/ui/image-lightbox.js +45 -1
- package/dist/ui/image-zoom.js +242 -0
- package/dist/ui/panel-chat.js +282 -89
- package/dist/ui/panel-details.js +2 -0
- package/dist/ui/panel-fleet.js +32 -71
- package/dist/ui/panel-needs.js +23 -6
- package/dist/ui/panel-settings.js +158 -32
- package/dist/ui/preview-panel.js +2 -1
- package/dist/ui/search-dialog.js +350 -0
- package/dist/ui/settings-appearance.js +170 -10
- package/dist/ui/settings-apply.js +3 -3
- package/dist/ui/settings-confirm.js +7 -2
- package/dist/ui/settings-dialogs.js +46 -21
- package/dist/ui/settings-discord.js +6 -2
- package/dist/ui/settings-guests.js +2 -1
- package/dist/ui/settings-learn.js +1 -0
- package/dist/ui/settings-model.js +51 -18
- package/dist/ui/settings-mods.js +8 -3
- package/dist/ui/settings-owner-effects.js +6 -4
- package/dist/ui/settings-strings.js +180 -6
- package/dist/ui/settings-token.js +3 -1
- package/dist/ui/settings-web-authority.js +13 -5
- package/dist/ui/settings-wizard.js +13 -7
- package/dist/ui/shared/agend-auth.js +3 -1
- package/dist/ui/shared/app-i18n.js +12 -5
- package/dist/ui/shared/app-needs.js +2 -2
- package/dist/ui/shared/app-prefs.js +15 -0
- package/dist/ui/shared/app-route.js +18 -0
- package/dist/ui/shared/app-shell.js +172 -28
- package/dist/ui/shared/app-store.js +3 -2
- package/dist/ui/shared/app-stream.js +7 -2
- package/dist/ui/shared/app-themes.js +116 -1
- package/dist/ui/shared/app.css +681 -54
- package/dist/ui/shared/app.js +9 -1
- package/dist/ui/shared/card-strings.js +4 -0
- package/dist/ui/shared/effect-app-runtime.js +7 -5
- package/dist/ui/shared/effect-chat-runtime.js +2 -7
- package/dist/ui/shared/effect-cursor.js +3 -2
- package/dist/ui/shared/effect-display-metadata.js +39 -0
- package/dist/ui/shared/effect-owner-source.js +8 -1
- package/dist/ui/shared/effect-policy.js +2 -2
- package/dist/ui/shared/effect-registry.js +30 -11
- package/dist/ui/shared/effect-runtime-loader.js +3 -1
- package/dist/ui/shared/effect-stock-snapshot.js +9 -0
- package/dist/ui/shared/effect-stock-trust.js +40 -9
- package/dist/ui/shared/effect-trial-source.js +1 -1
- package/dist/ui/shared/effect-trial-stage.js +27 -21
- package/dist/ui/shared/effect-trial.css +1 -1
- package/dist/ui/shared/feature-flags.js +127 -0
- package/dist/ui/shared/guest-refused.js +35 -0
- package/dist/ui/shared/header-tools.js +2 -2
- package/dist/ui/shared/identity-card.js +26 -8
- package/dist/ui/shared/identity-color.js +17 -10
- package/dist/ui/shared/instance-nav.js +183 -28
- package/dist/ui/shared/owner-css.js +30 -1
- package/dist/ui/shared/panel-view.js +14 -29
- package/dist/ui/shared/text-undo.js +210 -0
- package/dist/ui/shared/tokens.css +13 -3
- package/dist/ui/shared/ui-dialog.js +5 -4
- package/dist/ui/shared/ui-icons.js +4 -0
- package/dist/ui/shared/ui-menu.js +20 -7
- package/dist/ui/shared/ui-toast.js +16 -3
- package/dist/ui/shared/usage-dialog.js +206 -16
- package/dist/ui/shared/view-strings.js +68 -4
- package/dist/ui/shared/web-authorize.js +50 -1
- package/dist/ui/signin.html +2 -0
- package/dist/ui/web-terminal/terminal.css +4 -4
- package/dist/ui/web-terminal/terminal.html +10 -10
- package/dist/ui/web-terminal/terminal.js +58 -12
- package/dist/update-check.js.map +1 -1
- package/dist/update-dispatch.js +1 -1
- package/dist/update-dispatch.js.map +1 -1
- package/dist/update-install.js.map +1 -1
- package/dist/update-launch.d.ts +10 -1
- package/dist/update-launch.js +39 -14
- package/dist/update-launch.js.map +1 -1
- package/dist/update-marker.js.map +1 -1
- package/dist/update-preflight.js +1 -1
- package/dist/update-preflight.js.map +1 -1
- package/dist/update-progress.d.ts +3 -1
- package/dist/update-progress.js +3 -1
- package/dist/update-progress.js.map +1 -1
- package/dist/usage/format-rich.js +6 -3
- package/dist/usage/format-rich.js.map +1 -1
- package/dist/usage/i18n-keys.d.ts +1 -1
- package/dist/usage/i18n-keys.js +2 -1
- package/dist/usage/i18n-keys.js.map +1 -1
- package/dist/usage/i18n.d.ts +13 -1
- package/dist/usage/i18n.js +29 -0
- package/dist/usage/i18n.js.map +1 -1
- package/dist/usage/providers.d.ts +89 -2
- package/dist/usage/providers.js +247 -41
- package/dist/usage/providers.js.map +1 -1
- package/dist/usage/statusline-usage.js.map +1 -1
- package/dist/usage/usage-api.d.ts +5 -1
- package/dist/usage/usage-api.js +185 -58
- package/dist/usage/usage-api.js.map +1 -1
- package/dist/usage-report.js.map +1 -1
- package/dist/usage-rollup.js +1 -1
- package/dist/usage-rollup.js.map +1 -1
- package/dist/user-systemd.d.ts +24 -0
- package/dist/user-systemd.js +75 -0
- package/dist/user-systemd.js.map +1 -0
- package/dist/view-api.d.ts +7 -0
- package/dist/view-api.js +16 -4
- package/dist/view-api.js.map +1 -1
- package/dist/wake-coordinator.js.map +1 -1
- package/dist/web-ambient.js +9 -2
- package/dist/web-ambient.js.map +1 -1
- package/dist/web-api.d.ts +58 -10
- package/dist/web-api.js +1104 -71
- package/dist/web-api.js.map +1 -1
- package/dist/web-app-icon-worker.d.ts +1 -0
- package/dist/web-app-icon-worker.js +16 -0
- package/dist/web-app-icon-worker.js.map +1 -0
- package/dist/web-app-icon.d.ts +109 -0
- package/dist/web-app-icon.js +257 -0
- package/dist/web-app-icon.js.map +1 -0
- package/dist/web-appearance-policy.js.map +1 -1
- package/dist/web-appearance-tools.d.ts +1 -0
- package/dist/web-appearance-tools.js +7 -3
- package/dist/web-appearance-tools.js.map +1 -1
- package/dist/web-appearance-view.js.map +1 -1
- package/dist/web-appearance.d.ts +4 -10
- package/dist/web-appearance.js +7 -4
- package/dist/web-appearance.js.map +1 -1
- package/dist/web-auth.d.ts +8 -4
- package/dist/web-auth.js +33 -21
- package/dist/web-auth.js.map +1 -1
- package/dist/web-backend-login.d.ts +130 -0
- package/dist/web-backend-login.js +225 -0
- package/dist/web-backend-login.js.map +1 -0
- package/dist/web-card.js.map +1 -1
- package/dist/web-channel-echo.js.map +1 -1
- package/dist/web-chat-history.d.ts +118 -8
- package/dist/web-chat-history.js +220 -25
- package/dist/web-chat-history.js.map +1 -1
- package/dist/web-commands.d.ts +5 -1
- package/dist/web-commands.js +1 -1
- package/dist/web-commands.js.map +1 -1
- package/dist/web-cookie-names.d.ts +5 -0
- package/dist/web-cookie-names.js +12 -0
- package/dist/web-cookie-names.js.map +1 -0
- package/dist/web-effect-bundle.d.ts +2 -2
- package/dist/web-effect-library.js.map +1 -1
- package/dist/web-effect-playback.js.map +1 -1
- package/dist/web-effect-profiles.d.ts +16 -16
- package/dist/web-effect-profiles.js +3 -2
- package/dist/web-effect-profiles.js.map +1 -1
- package/dist/web-effect-service.js.map +1 -1
- package/dist/web-effect-tools.js.map +1 -1
- package/dist/web-effect-trials.js.map +1 -1
- package/dist/web-effect-upload.js.map +1 -1
- package/dist/web-effect.d.ts +6 -6
- package/dist/web-effect.js.map +1 -1
- package/dist/web-experimental-http.d.ts +2 -0
- package/dist/web-experimental-http.js +12 -0
- package/dist/web-experimental-http.js.map +1 -0
- package/dist/web-experimental.d.ts +11 -0
- package/dist/web-experimental.js +49 -0
- package/dist/web-experimental.js.map +1 -0
- package/dist/web-guest-access.d.ts +4 -2
- package/dist/web-guest-access.js +22 -10
- package/dist/web-guest-access.js.map +1 -1
- package/dist/web-guest-rooms.js.map +1 -1
- package/dist/web-host-guard.d.ts +11 -0
- package/dist/web-host-guard.js +11 -0
- package/dist/web-host-guard.js.map +1 -1
- package/dist/web-icons.d.ts +33 -1
- package/dist/web-icons.js +83 -11
- package/dist/web-icons.js.map +1 -1
- package/dist/web-identity-color.js.map +1 -1
- package/dist/web-image-meta.d.ts +13 -0
- package/dist/web-image-meta.js +62 -0
- package/dist/web-image-meta.js.map +1 -1
- package/dist/web-images.js.map +1 -1
- package/dist/web-libavoid.d.ts +14 -0
- package/dist/web-libavoid.js +46 -0
- package/dist/web-libavoid.js.map +1 -0
- package/dist/web-login.js.map +1 -1
- package/dist/web-mentions.js.map +1 -1
- package/dist/web-mod-agent.js.map +1 -1
- package/dist/web-mod-store.d.ts +2 -0
- package/dist/web-mod-store.js +10 -0
- package/dist/web-mod-store.js.map +1 -1
- package/dist/web-office-store.d.ts +104 -0
- package/dist/web-office-store.js +236 -0
- package/dist/web-office-store.js.map +1 -0
- package/dist/web-owner-css-store.d.ts +44 -1
- package/dist/web-owner-css-store.js +70 -9
- package/dist/web-owner-css-store.js.map +1 -1
- package/dist/web-owner-css.js.map +1 -1
- package/dist/web-png.d.ts +33 -0
- package/dist/web-png.js +329 -0
- package/dist/web-png.js.map +1 -0
- package/dist/web-prefs.d.ts +6 -0
- package/dist/web-prefs.js +29 -3
- package/dist/web-prefs.js.map +1 -1
- package/dist/web-preview.d.ts +2 -0
- package/dist/web-preview.js +2 -0
- package/dist/web-preview.js.map +1 -1
- package/dist/web-profile.js.map +1 -1
- package/dist/web-reactions.d.ts +35 -0
- package/dist/web-reactions.js +47 -0
- package/dist/web-reactions.js.map +1 -0
- package/dist/web-request-context.d.ts +5 -0
- package/dist/web-request-context.js.map +1 -1
- package/dist/web-returning-device.d.ts +4 -2
- package/dist/web-returning-device.js +13 -6
- package/dist/web-returning-device.js.map +1 -1
- package/dist/web-schedules.js.map +1 -1
- package/dist/web-send-dedupe.d.ts +36 -0
- package/dist/web-send-dedupe.js +69 -0
- package/dist/web-send-dedupe.js.map +1 -0
- package/dist/web-session-authorization.js.map +1 -1
- package/dist/web-session.js +1 -1
- package/dist/web-session.js.map +1 -1
- package/dist/web-settings-patch.d.ts +3 -1
- package/dist/web-settings-patch.js +11 -5
- package/dist/web-settings-patch.js.map +1 -1
- package/dist/web-settings-tools.d.ts +6 -0
- package/dist/web-settings-tools.js +52 -17
- package/dist/web-settings-tools.js.map +1 -1
- package/dist/web-terminal-http.js +15 -2
- package/dist/web-terminal-http.js.map +1 -1
- package/dist/web-terminal.js +1 -1
- package/dist/web-terminal.js.map +1 -1
- package/dist/web-theme-store.d.ts +2 -2
- package/dist/web-theme-store.js +6 -3
- package/dist/web-theme-store.js.map +1 -1
- package/dist/web-theme.d.ts +29 -0
- package/dist/web-theme.js +89 -1
- package/dist/web-theme.js.map +1 -1
- package/dist/web-upload.d.ts +18 -1
- package/dist/web-upload.js +45 -7
- package/dist/web-upload.js.map +1 -1
- package/dist/web-widget.js.map +1 -1
- package/dist/webhook-emitter.js.map +1 -1
- package/dist/windows-shortcuts.d.ts +78 -0
- package/dist/windows-shortcuts.js +203 -0
- package/dist/windows-shortcuts.js.map +1 -0
- package/dist/workflow-templates/default.md +4 -1
- package/dist/ws-server.js.map +1 -1
- package/dist/yaml-shared-nodes.d.ts +25 -0
- package/dist/yaml-shared-nodes.js +185 -0
- package/dist/yaml-shared-nodes.js.map +1 -0
- package/launcher/agend-install.cjs +828 -0
- package/launcher/install-admission.cjs +4 -39
- package/launcher/postinstall.cjs +14 -12
- package/launcher/private-home.cjs +43 -0
- package/package.json +16 -13
- package/scripts/preinstall-guard.cjs +2 -5
- package/templates/windows-shortcuts.ps1 +181 -0
- package/launcher/old-updater-note.cjs +0 -48
package/dist/ui/panel-chat.js
CHANGED
|
@@ -7,11 +7,11 @@
|
|
|
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
9
|
import { html, useCallback, useEffect, useLayoutEffect, useRef, useState } from "/assets/app-html.js";
|
|
10
|
-
import { t } from "/assets/app-i18n.js";
|
|
11
|
-
import { appStore, guestPage, useStore } from "/assets/app-store.js";
|
|
12
|
-
import {
|
|
10
|
+
import { lang, t } from "/assets/app-i18n.js";
|
|
11
|
+
import { appStore, createStore, guestPage, useStore } from "/assets/app-store.js";
|
|
12
|
+
import { ComposerAuth } from "/assets/web-authorize.js";
|
|
13
13
|
import { useLease } from "/assets/app-ctx.js";
|
|
14
|
-
import { modelText, namesOf, namesStore } from "/assets/instance-nav.js";
|
|
14
|
+
import { modelText, namesOf, namesStore, navStore as instanceNavStore } from "/assets/instance-nav.js";
|
|
15
15
|
import { PanelHeader, onPanelKey, setTitle, statusClass, statusLabel, openDrawer, requestNewInstance } from "/assets/app-shell.js";
|
|
16
16
|
import { detailsPath, textLinkSegments } from "/assets/app-route.js";
|
|
17
17
|
import { InstanceSwitch } from "/assets/instance-switch.js";
|
|
@@ -21,33 +21,53 @@ import { Menu } from "/assets/ui-menu.js";
|
|
|
21
21
|
import { Dialog } from "/assets/ui-dialog.js";
|
|
22
22
|
import { Empty, Skeleton } from "/assets/ui-states.js";
|
|
23
23
|
import { Icon } from "/assets/ui-icons.js";
|
|
24
|
+
import { recordEdit } from "/assets/text-undo.js";
|
|
24
25
|
import { toast } from "/assets/ui-toast.js";
|
|
25
26
|
import { confirmDialog } from "/assets/ui-confirm.js";
|
|
26
27
|
import { savePref } from "/assets/app-prefs.js";
|
|
27
28
|
import { applyTheme, clearAmbient, resolvedMode, themeFor, themeImageUrl, themeMenuItems, themesStore } from "/assets/app-themes.js";
|
|
28
29
|
import { colorMenuItem } from "/assets/identity-color.js";
|
|
29
|
-
import { IdentityCard, useCard } from "/assets/identity-card.js";
|
|
30
|
+
import { brokenPictures, cardFoldable, IdentityCard, useCard } from "/assets/identity-card.js";
|
|
30
31
|
import { AgentWidget, instanceBinds, widgetFor } from "/assets/agent-widget.js";
|
|
31
32
|
|
|
32
|
-
// #1629 r4 §1: the identity card
|
|
33
|
+
// #1629 r4 §1: the identity card under the chat's header — hidden by default; shown or not is this device's choice.
|
|
34
|
+
// #2217 (the user, 2026-10-19): no row of its own; its picture and bio can be folded away (the banner stays) — this
|
|
35
|
+
// device's choice too, kept the same way. The user (2026-10-20): no control on the card — one card button in the header
|
|
36
|
+
// (a guest's and the public link's header too: they have no ⋯ menu), pressed-looking while the card is shown, opens a
|
|
37
|
+
// small menu of two checkboxes: Show card, and Show picture and bio (disabled while the card is hidden, or when it cannot
|
|
38
|
+
// fold: no banner, or nothing on its row).
|
|
33
39
|
const CHAT_CARD_KEY = "agend_chat_card";
|
|
34
|
-
const
|
|
40
|
+
const CHAT_CARD_ROW_KEY = "agend_chat_card_row";
|
|
41
|
+
const readKey = (k, v) => { try { return localStorage.getItem(k) === v; } catch { return false; } };
|
|
42
|
+
const writeKey = (k, v) => { try { if (v) localStorage.setItem(k, v); else localStorage.removeItem(k); } catch { /* this page only */ } };
|
|
43
|
+
/** Shared by the header's Show card and the card itself, so the two never disagree. */
|
|
44
|
+
export const chatCardPrefs = createStore({ open: readKey(CHAT_CARD_KEY, "open"), rowHidden: readKey(CHAT_CARD_ROW_KEY, "hidden") });
|
|
45
|
+
export const setChatCardOpen = (open) => { writeKey(CHAT_CARD_KEY, open ? "open" : null); chatCardPrefs.set((s) => ({ ...s, open })); };
|
|
46
|
+
export const setChatCardRowHidden = (rowHidden) => { writeKey(CHAT_CARD_ROW_KEY, rowHidden ? "hidden" : null); chatCardPrefs.set((s) => ({ ...s, rowHidden })); };
|
|
35
47
|
function ChatCard({ name, card }) {
|
|
36
|
-
const
|
|
37
|
-
if (!card) return null;
|
|
38
|
-
|
|
39
|
-
|
|
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}
|
|
48
|
+
const prefs = useStore(chatCardPrefs);
|
|
49
|
+
if (!card || !prefs.open) return null;
|
|
50
|
+
return html`<div data-trust="card" class="chat-card open">
|
|
51
|
+
<${IdentityCard} name=${name} card=${card} compact=${true} rowHidden=${prefs.rowHidden} />
|
|
45
52
|
</div>`;
|
|
46
53
|
}
|
|
54
|
+
/** The header's card menu: ☑ Show card, ☑ Show picture and bio. */
|
|
55
|
+
function CardMenu({ card }) {
|
|
56
|
+
const prefs = useStore(chatCardPrefs);
|
|
57
|
+
useStore(brokenPictures); // a banner that failed to load: the card cannot fold, the item greys out
|
|
58
|
+
if (!card) return null;
|
|
59
|
+
const items = [
|
|
60
|
+
{ key: "card", checkbox: true, checked: prefs.open, label: t("card.show"), onSelect: () => setChatCardOpen(!prefs.open) },
|
|
61
|
+
{ key: "row", checkbox: true, checked: !prefs.rowHidden && cardFoldable(card), disabled: !prefs.open || !cardFoldable(card), label: t("card.showRow"),
|
|
62
|
+
onSelect: () => setChatCardRowHidden(!prefs.rowHidden) },
|
|
63
|
+
];
|
|
64
|
+
return html`<${Menu} items=${items} label=${t("card.menu")} icon="idcard" cls="chat-card-menu" active=${prefs.open} />`;
|
|
65
|
+
}
|
|
47
66
|
import "./chat-strings.js";
|
|
48
|
-
import { confirmedWrite } from "./settings-confirm.js";
|
|
67
|
+
import { confirmedWrite, selfConfirmed } from "./settings-confirm.js";
|
|
49
68
|
import { createChatStore } from "./chat-store.js";
|
|
50
69
|
import { createThread, msgKey } from "./chat-thread.js";
|
|
70
|
+
import { installMessageActions } from "./chat-msg-actions.js";
|
|
51
71
|
import { createEmojiIndex } from "./chat-emojis.js";
|
|
52
72
|
import { pollPublicPreview } from "./preview-status.js";
|
|
53
73
|
import { createMentionIndex } from "./chat-mentions.js";
|
|
@@ -55,11 +75,14 @@ import { PreviewPanel, claimPanel, openPanel, panelClaims, panelStore, panelVers
|
|
|
55
75
|
import { needsArgument, paletteFor, parseCommandLine } from "./chat-commands.js";
|
|
56
76
|
import { installTour, refreshTourSpot } from "./chat-tour.js";
|
|
57
77
|
import { LightboxHost, openLightbox } from "./image-lightbox.js";
|
|
58
|
-
import {
|
|
59
|
-
|
|
78
|
+
import { canvasWorkerMenuAvailable, experimentalComponent, useCanvasWorker } from "/assets/feature-flags.js";
|
|
79
|
+
const ChatEffectPosters = experimentalComponent(() => import("./chat-effect-posters.js"), m => m.ChatEffectPosters);
|
|
80
|
+
const ChatEffects = experimentalComponent(() => import("./chat-effects.js"), m => m.ChatEffects);
|
|
60
81
|
import { setFollowsReducedMotion } from "/assets/fx-motion.js";
|
|
61
82
|
import { AmbientMotionNote, ChatAmbient, ambientMenuItems } from "./chat-ambient.js";
|
|
62
|
-
import {
|
|
83
|
+
import { startEffectsWaker, getAppEffects, wakeEffects, effectsLoaded, onEffectsAwake, chatHasEffects } from "/assets/feature-flags.js";
|
|
84
|
+
/** The composer's textarea (#2342: text put back into it is a step Ctrl+Z goes back from). */
|
|
85
|
+
const composerField = () => (typeof document !== "undefined" ? document.getElementById("msgIn") : null);
|
|
63
86
|
|
|
64
87
|
const R = () => globalThis.AgendChatRender;
|
|
65
88
|
const P = () => globalThis.AgendPreview;
|
|
@@ -99,7 +122,9 @@ export async function setPreviewOptIn(on, commit = (apply) => apply()) {
|
|
|
99
122
|
export function boot({ stream, boot: bootData, deps = {} }) {
|
|
100
123
|
if (store) return store;
|
|
101
124
|
store = createChatStore({
|
|
102
|
-
fetch: (...a) => fetch(...a), toast, announce, t, setTimeout: (fn, ms) => setTimeout(fn, ms), confirm: confirmDialog,
|
|
125
|
+
fetch: (...a) => fetch(...a), toast, announce, t, setTimeout: (fn, ms) => setTimeout(fn, ms), confirm: confirmDialog,
|
|
126
|
+
XMLHttpRequest: typeof XMLHttpRequest === "function" ? XMLHttpRequest : undefined, // an upload's progress (chat-store.js)
|
|
127
|
+
...deps,
|
|
103
128
|
});
|
|
104
129
|
emojiIndex = createEmojiIndex((url) => (deps.fetch || fetch)(url, { credentials: "same-origin" }));
|
|
105
130
|
mentionIndex = createMentionIndex((url) => (deps.fetch || fetch)(url, { credentials: "same-origin" }));
|
|
@@ -119,8 +144,9 @@ export function boot({ stream, boot: bootData, deps = {} }) {
|
|
|
119
144
|
}
|
|
120
145
|
// #1604: the preview opt-in and Tour live in Settings → This device now (and on each preview card's menu).
|
|
121
146
|
installTour();
|
|
122
|
-
// #2118: viewing current in-scope Chat effects needs no management or personal-slot authority.
|
|
123
|
-
|
|
147
|
+
// #2118: viewing current in-scope Chat effects needs no management or personal-slot authority. #2193: the runtime
|
|
148
|
+
// itself loads only when there is something to play (effects-waker.js).
|
|
149
|
+
startEffectsWaker({ store });
|
|
124
150
|
return store;
|
|
125
151
|
}
|
|
126
152
|
|
|
@@ -163,6 +189,10 @@ function useChatTick(name, kinds) {
|
|
|
163
189
|
|
|
164
190
|
/** #1722: the chat's title — the name that leads, the other on hover. */
|
|
165
191
|
const headerName = ({ primary, secondary }) => (secondary ? html`<span title=${secondary}>${primary}</span>` : primary);
|
|
192
|
+
/** #2478: who the composer writes to — the display name, else the instance's name (a long id made the box two lines). */
|
|
193
|
+
const composerLabel = (inst, name) => (inst && typeof inst.display_name === "string" && inst.display_name.trim()) || name;
|
|
194
|
+
/** #2478: a touch screen (a coarse pointer) — Return is a new line there and only the Send button sends. Asked each time. */
|
|
195
|
+
const touchScreen = () => typeof matchMedia === "function" && matchMedia("(pointer: coarse)").matches;
|
|
166
196
|
|
|
167
197
|
export function ChatPanel({ route, navKey }) {
|
|
168
198
|
const lease = useLease(navKey);
|
|
@@ -238,7 +268,12 @@ function ChatView({ name, inst, lease, navKey, exec, awaiting }) {
|
|
|
238
268
|
}, [themeKey]);
|
|
239
269
|
useEffect(() => { wrapListeners.add(setWrap); return () => wrapListeners.delete(setWrap); }, []);
|
|
240
270
|
// First visit to this instance's chat on this page: its history (a navigation — it counts as use). Back again: nothing.
|
|
241
|
-
|
|
271
|
+
// #2188: left before it answered (passing through on the way to another chat) — the read is aborted.
|
|
272
|
+
useEffect(() => {
|
|
273
|
+
const ac = typeof AbortController === "function" ? new AbortController() : null;
|
|
274
|
+
store.openHistory(name, lease, ac?.signal);
|
|
275
|
+
return () => ac?.abort();
|
|
276
|
+
}, [name]);
|
|
242
277
|
useEffect(() => { try { localStorage.setItem("agend_last_instance", name); } catch { /* none */ } }, [name]);
|
|
243
278
|
// Files dragged over the chat show where they go; a drop attaches them (counted, so moving over messages does not flicker).
|
|
244
279
|
useEffect(() => {
|
|
@@ -271,6 +306,9 @@ function ChatView({ name, inst, lease, navKey, exec, awaiting }) {
|
|
|
271
306
|
else if (r && r.held) toast(r.message);
|
|
272
307
|
else toast(t(verb === "start" ? "chat.started" : verb === "stop" ? "chat.stoppedInst" : "chat.restarted", name));
|
|
273
308
|
};
|
|
309
|
+
// #2193: this chat's Canvas Worker placements (its status row's effect_chat_v): none, no effects code runs for it.
|
|
310
|
+
const cwEnabled = useCanvasWorker();
|
|
311
|
+
const fxHere = cwEnabled && chatHasEffects(name);
|
|
274
312
|
const items = [
|
|
275
313
|
// #1523 N2: Details is a page now (the Fleet side of this instance), not a dialog.
|
|
276
314
|
{ key: "details", label: t("chat.details"), icon: "info", onSelect: () => navigate(detailsPath(name)) },
|
|
@@ -283,7 +321,7 @@ function ChatView({ name, inst, lease, navKey, exec, awaiting }) {
|
|
|
283
321
|
...themeMenuItems(name),
|
|
284
322
|
// #2117: its ambient — why it is not showing here (with the way to change that), and a person's Clear.
|
|
285
323
|
...ambientMenuItems(name, { publicLink: document.body.dataset.publicLink === "1", clear: clearAmbient }),
|
|
286
|
-
|
|
324
|
+
cwEnabled && canvasWorkerMenuAvailable(window) ? { key: "effects", label: t("cwControls.title"), onSelect: () => setDialog("effects") } : null,
|
|
287
325
|
{ key: "delete", label: t("chat.delete"), icon: "trash", danger: true, onSelect: () => setDialog("delete") },
|
|
288
326
|
];
|
|
289
327
|
const cls = statusClass(inst, exec, awaiting);
|
|
@@ -296,7 +334,7 @@ function ChatView({ name, inst, lease, navKey, exec, awaiting }) {
|
|
|
296
334
|
${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}
|
|
297
335
|
${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}`;
|
|
298
336
|
return html`<div class=${`panel p-chat${wrap ? " wrap-code" : ""}`} ref=${view}>
|
|
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)} />`}
|
|
337
|
+
<${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)} active=${fxHere} />`}>${fxHere ? html`<${ChatEffectPosters} name=${name} lease=${lease} element=${effectSurface} />` : null}<${CardMenu} card=${card} /><${HeaderTools} navKey=${navKey} />${guest ? null : html`<${Menu} items=${items} label=${t("app.more")} />`}</${PanelHeader}>
|
|
300
338
|
<${ChatCard} key=${name} name=${name} card=${card} />
|
|
301
339
|
<${AgentWidget} slot="chat_header" widget=${widgetFor(name, "chat_header")} binds=${instanceBinds(inst, exec, awaiting)} />
|
|
302
340
|
<div class="chat-split" ref=${split}>
|
|
@@ -317,66 +355,192 @@ function ChatView({ name, inst, lease, navKey, exec, awaiting }) {
|
|
|
317
355
|
</div>`;
|
|
318
356
|
}
|
|
319
357
|
|
|
320
|
-
/**
|
|
358
|
+
/**
|
|
359
|
+
* #2053: the last THREAD_KEEP chats' threads are kept when their view leaves (the chat view is keyed by instance, so
|
|
360
|
+
* each switch built the thread again: a revisit was no faster than a first visit). A kept thread is its list element
|
|
361
|
+
* and its renderer, and nothing more: it leaves as a chat always did (previews stop), with no subscription or timer
|
|
362
|
+
* left; shown again, one render draws only what changed meanwhile, where the reader was. A new language, another
|
|
363
|
+
* document, or more than the budget lets one go.
|
|
364
|
+
*
|
|
365
|
+
* #2184: the budget (raised for people who switch among ~10 favourites): up to THREAD_KEEP threads on a wide screen and
|
|
366
|
+
* THREAD_KEEP_NARROW on a narrow one (a phone), and THREAD_KEEP_NODES drawn messages in all, so memory stays bounded
|
|
367
|
+
* however long the chats are. Over it, the least recently shown goes first — one that is not a favourite before a
|
|
368
|
+
* favourite; the chat on screen never goes.
|
|
369
|
+
*/
|
|
370
|
+
export const THREAD_KEEP = 12;
|
|
371
|
+
export const THREAD_KEEP_NARROW = 6;
|
|
372
|
+
export const THREAD_KEEP_NODES = 2400;
|
|
373
|
+
/**
|
|
374
|
+
* #2188: a chat shown for less than this, on the way to another (clicking down the sidebar), is not kept: it is let go
|
|
375
|
+
* as it leaves, so passing through chats never evicts the ones in use. One that was already kept stays kept.
|
|
376
|
+
*/
|
|
377
|
+
export const THREAD_PASS_MS = 1000;
|
|
378
|
+
const monotonic = () => (typeof performance === "object" && typeof performance.now === "function" ? performance.now() : Date.now());
|
|
379
|
+
let now = monotonic;
|
|
380
|
+
/** Tests only: the clock THREAD_PASS_MS is measured on (null: the page's monotonic clock). */
|
|
381
|
+
export function setThreadClock(fn) { now = typeof fn === "function" ? fn : monotonic; }
|
|
382
|
+
/**
|
|
383
|
+
* The kept threads to let go, in order. `kept`: [name, drawn messages], least recently shown first; `current`: the
|
|
384
|
+
* one on screen (never let go).
|
|
385
|
+
*/
|
|
386
|
+
export function threadsToLetGo(kept, current, { keep, maxNodes, favorites }) {
|
|
387
|
+
let count = kept.length, nodes = kept.reduce((n, [, d]) => n + d, 0);
|
|
388
|
+
const out = [];
|
|
389
|
+
const order = [...kept.filter(([n]) => n !== current && !favorites.has(n)), ...kept.filter(([n]) => n !== current && favorites.has(n))];
|
|
390
|
+
for (const [n, d] of order) {
|
|
391
|
+
if (count <= keep && nodes <= maxNodes) break;
|
|
392
|
+
out.push(n); count--; nodes -= d;
|
|
393
|
+
}
|
|
394
|
+
return out;
|
|
395
|
+
}
|
|
396
|
+
const narrowScreen = () => typeof matchMedia === "function" && matchMedia("(max-width: 899px)").matches;
|
|
397
|
+
/** Let go what the budget does not hold (after `current` was shown, or drew more). */
|
|
398
|
+
function trimKept(current) {
|
|
399
|
+
const kept = [...keptThreads].map(([n, e]) => [n, e.thread.nodes.size]);
|
|
400
|
+
const favorites = new Set(instanceNavStore.get().favorites);
|
|
401
|
+
for (const n of threadsToLetGo(kept, current, { keep: narrowScreen() ? THREAD_KEEP_NARROW : THREAD_KEEP, maxNodes: THREAD_KEEP_NODES, favorites })) {
|
|
402
|
+
letGo(keptThreads.get(n), true); keptThreads.delete(n);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
const keptThreads = new Map(); // name → { thread, list, sink, lang }
|
|
406
|
+
/** Tests only: let every kept thread go. */
|
|
407
|
+
export function forgetKeptThreads() { for (const e of keptThreads.values()) letGo(e, true); keptThreads.clear(); }
|
|
408
|
+
function letGo(e, own) { e.thread.dispose(own); e.list.remove(); }
|
|
409
|
+
|
|
410
|
+
/** A chat's thread: its own list element and renderer, and a sink for the view that shows it. */
|
|
411
|
+
function threadEntry(name, doc) {
|
|
412
|
+
const list = doc.createElement("div");
|
|
413
|
+
list.className = "thread";
|
|
414
|
+
list.setAttribute("role", "log");
|
|
415
|
+
list.setAttribute("aria-live", "off");
|
|
416
|
+
list.setAttribute("aria-label", t("chat.conversationWith", name));
|
|
417
|
+
const e = { list, sink: null, lang: lang(), thread: null };
|
|
418
|
+
const thread = createThread(list, doc.createElement("div"), {
|
|
419
|
+
t, tf: t, isUser: (x) => store.isUser(x, name), onJump: (j) => e.sink?.setJump(j), onEmpty: (v) => e.sink?.setEmpty(v),
|
|
420
|
+
setPreviewOptIn, copyText, download: downloadHtml, toggleWrap,
|
|
421
|
+
// #2193: an offer shown while the effects runtime sleeps wakes it; until it answers, the offer is being checked.
|
|
422
|
+
effectTrialStatus: x => { const fx = getAppEffects(); if (fx) return fx.trialStatus(x); if (!effectsLoaded()) { void wakeEffects(); return "checking"; } return "localAdmin"; },
|
|
423
|
+
effectTrialFailure: x => getAppEffects()?.trialFailure(x),
|
|
424
|
+
fixEffectTrial: (x, reason) => {
|
|
425
|
+
if (reason === "reducedMotion") setFollowsReducedMotion(false);
|
|
426
|
+
else if (reason === "busy") getAppEffects()?.stopTrial();
|
|
427
|
+
else if (reason === "transport") location.reload();
|
|
428
|
+
else if (reason === "localAdmin") location.href = "/signin?next=" + encodeURIComponent(location.pathname + location.search);
|
|
429
|
+
else navigate("/settings/appearance");
|
|
430
|
+
},
|
|
431
|
+
canTryEffect: x => getAppEffects()?.canTry(x) === true,
|
|
432
|
+
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")); }); },
|
|
433
|
+
clickReplyButton: (id, index) => store.clickReplyButton(name, id, index), // #1266
|
|
434
|
+
retryOutgoing: (clientId) => store.retryOutgoing(name, clientId), // a failed send's Retry and Delete
|
|
435
|
+
deleteOutgoing: (clientId) => store.deleteOutgoing(name, clientId),
|
|
436
|
+
putBackOutgoing: (clientId) => { recordEdit(composerField()); store.putBackOutgoing(name, clientId); }, // undoable, as typing
|
|
437
|
+
// #2272: reply to a message (the bar above the composer), and show the one a reply quotes.
|
|
438
|
+
startReply: (x) => { store.startReply(name, x); doc.getElementById("msgIn")?.focus(); },
|
|
439
|
+
findQuoted: (key) => store.findQuoted(name, key),
|
|
440
|
+
notice: (text) => toast(text, false),
|
|
441
|
+
replyButtonBusy: (id) => store.state.rbBusy.has(id),
|
|
442
|
+
pollMine: (id) => store.state.pollMine[id], // #1823: this device's own vote
|
|
443
|
+
serverNow: () => Date.now() + store.state.clockSkew, // #1823: the deadline is the server's
|
|
444
|
+
panel: { shown: shownKey, open: (spec, o) => openPanel(spec, o), version: panelVersion, claim: claimPanel, claims: panelClaims }, // #1481, #1704
|
|
445
|
+
openImage: openLightbox, // an image, full size, in the page
|
|
446
|
+
emojis: (id) => !!emojiIndex && emojiIndex.known(id), // #1630: the fleet's server emoji
|
|
447
|
+
mentions: (kind, id) => (mentionIndex ? mentionIndex.name(kind, id) : null), // #1682: mention names
|
|
448
|
+
});
|
|
449
|
+
e.thread = thread;
|
|
450
|
+
return e;
|
|
451
|
+
}
|
|
452
|
+
/** While a thread is shown: what it follows. Returns what lets it all go. */
|
|
453
|
+
function follow(name, thread) {
|
|
454
|
+
// #1630: the server-emoji list is read once a message shows a tag; when it arrives, those messages are drawn again.
|
|
455
|
+
// #1682: the same for mention names — asked for the ids the messages carry; when names arrive, drawn again.
|
|
456
|
+
const wantEmojis = (msgs) => { if (emojiIndex && emojiIndex.wants(msgs)) emojiIndex.ensure(); if (mentionIndex) mentionIndex.ensure(msgs); };
|
|
457
|
+
const offs = [];
|
|
458
|
+
if (emojiIndex) offs.push(emojiIndex.subscribe(() => thread.render(store.threadRows(name))));
|
|
459
|
+
if (mentionIndex) offs.push(mentionIndex.subscribe(() => thread.render(store.threadRows(name))));
|
|
460
|
+
wantEmojis(store.state.msgs[name]);
|
|
461
|
+
offs.push(store.subscribe((instance, kind) => {
|
|
462
|
+
if (instance !== name) return;
|
|
463
|
+
if (kind === "msgs") { thread.render(store.threadRows(name)); wantEmojis(store.state.msgs[name]); }
|
|
464
|
+
else if (kind === "progress") thread.progress(); // an upload moved: its bar, in place
|
|
465
|
+
else if (kind === "sent") thread.jumpLatest();
|
|
466
|
+
}));
|
|
467
|
+
offs.push(P() ? P().onChange(() => thread.refreshCards()) : () => {});
|
|
468
|
+
// #2193: the runtime may start later (an offer shown wakes it): its trial updates are followed from then.
|
|
469
|
+
let trialOff = null, trialOwner = null;
|
|
470
|
+
const watchTrial = () => {
|
|
471
|
+
const next = getAppEffects();
|
|
472
|
+
if (next === trialOwner) return;
|
|
473
|
+
trialOff?.(); trialOff = null; trialOwner = next;
|
|
474
|
+
trialOff = next?.subscribeTrial(() => thread.render(store.threadRows(name))) ?? null;
|
|
475
|
+
};
|
|
476
|
+
watchTrial();
|
|
477
|
+
offs.push(onEffectsAwake(() => { watchTrial(); thread.render(store.threadRows(name)); }));
|
|
478
|
+
offs.push(() => { trialOff?.(); trialOff = null; trialOwner = null; });
|
|
479
|
+
offs.push(panelStore.subscribe(() => thread.refreshCards())); // a card shows whether the panel has its block
|
|
480
|
+
return () => { for (const off of offs) off(); };
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/** The thread's view: Preact owns the scroller and the jump pill; the kept list (chat-thread.js) is put inside it. */
|
|
321
484
|
function Thread({ name, th }) {
|
|
322
|
-
const scroller = useRef(null),
|
|
485
|
+
const scroller = useRef(null), host = useRef(null);
|
|
323
486
|
const [jump, setJump] = useState({ show: false, unseen: 0 });
|
|
324
487
|
const [empty, setEmpty] = useState(false);
|
|
325
488
|
useLayoutEffect(() => {
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
replyButtonBusy: (id) => store.state.rbBusy.has(id),
|
|
342
|
-
pollMine: (id) => store.state.pollMine[id], // #1823: this device's own vote
|
|
343
|
-
serverNow: () => Date.now() + store.state.clockSkew, // #1823: the deadline is the server's
|
|
344
|
-
panel: { shown: shownKey, open: (spec, o) => openPanel(spec, o), version: panelVersion, claim: claimPanel, claims: panelClaims }, // #1481, #1704
|
|
345
|
-
openImage: openLightbox, // an image, full size, in the page
|
|
346
|
-
emojis: (id) => !!emojiIndex && emojiIndex.known(id), // #1630: the fleet's server emoji
|
|
347
|
-
mentions: (kind, id) => (mentionIndex ? mentionIndex.name(kind, id) : null), // #1682: mention names
|
|
348
|
-
});
|
|
489
|
+
const doc = host.current.ownerDocument;
|
|
490
|
+
let e = keptThreads.get(name);
|
|
491
|
+
// Kept only while it can be shown as it is: the same language, and this page's own document.
|
|
492
|
+
if (e && (e.lang !== lang() || e.list.ownerDocument !== doc)) { letGo(e, true); keptThreads.delete(name); e = undefined; }
|
|
493
|
+
const kept = !!e;
|
|
494
|
+
if (e) keptThreads.delete(name);
|
|
495
|
+
else e = threadEntry(name, doc);
|
|
496
|
+
keptThreads.set(name, e); // the most recent last
|
|
497
|
+
// A thread already kept is trimmed against at once; a new one first has to stay (see THREAD_PASS_MS).
|
|
498
|
+
if (kept) trimKept(name);
|
|
499
|
+
const shownAt = now();
|
|
500
|
+
const thread = e.thread, sc = scroller.current, ls = e.list;
|
|
501
|
+
e.sink = { setJump, setEmpty };
|
|
502
|
+
host.current.append(ls);
|
|
503
|
+
thread.attach(sc);
|
|
349
504
|
th.current = thread;
|
|
350
|
-
//
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
const
|
|
354
|
-
const offMentions = mentionIndex ? mentionIndex.subscribe(() => thread.render(store.state.msgs[name] || [])) : () => {};
|
|
355
|
-
thread.render(store.state.msgs[name] || [], { restore: store.state.scrollMemo[name] ?? null });
|
|
356
|
-
wantEmojis(store.state.msgs[name]);
|
|
357
|
-
const off = store.subscribe((instance, kind) => {
|
|
358
|
-
if (instance !== name) return;
|
|
359
|
-
if (kind === "msgs") { thread.render(store.state.msgs[name] || []); wantEmojis(store.state.msgs[name]); }
|
|
360
|
-
else if (kind === "sent") thread.jumpLatest();
|
|
361
|
-
});
|
|
362
|
-
const offPv = P() ? P().onChange(() => thread.refreshCards()) : () => {};
|
|
363
|
-
const offTrials = getAppEffects()?.subscribeTrial(() => thread.render(store.state.msgs[name] || [])) ?? (() => {});
|
|
364
|
-
const offPanel = panelStore.subscribe(() => thread.refreshCards()); // a card shows whether the panel has its block
|
|
505
|
+
// 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.
|
|
506
|
+
thread.render(store.threadRows(name), { restore: store.state.scrollMemo[name] ?? null });
|
|
507
|
+
if (kept) thread.refreshCards();
|
|
508
|
+
const unfollow = follow(name, thread);
|
|
365
509
|
const onScroll = () => { store.state.scrollMemo[name] = thread.onScroll(); };
|
|
366
|
-
const sc = scroller.current, ls = list.current;
|
|
367
510
|
sc.addEventListener("scroll", onScroll, { passive: true });
|
|
368
511
|
ls.addEventListener("click", thread.onClick);
|
|
512
|
+
// #2272: the message menu, swipe left / long-press on a phone, R on a focused message.
|
|
513
|
+
const offActions = installMessageActions(ls, {
|
|
514
|
+
t, messageOf: thread.messageOf, rove: thread.rove, reply: (x) => { store.startReply(name, x); document.getElementById("msgIn")?.focus(); },
|
|
515
|
+
copyText, notice: (text, ok = true) => toast(text, ok),
|
|
516
|
+
linkOf: (x) => `${location.origin}/ui/chat/${encodeURIComponent(name)}#m=${msgKey(x)}`,
|
|
517
|
+
});
|
|
518
|
+
// A copied message link (#m=<boot>-<id>): show that message, flashed.
|
|
519
|
+
const linked = /^#m=([0-9a-f]{1,32}-\d{1,15})$/.exec(location.hash);
|
|
520
|
+
if (linked) void thread.jumpTo(linked[1]);
|
|
521
|
+
// #2293: search opening a message of this chat while it is shown — the address's #m= changes, the route does not.
|
|
522
|
+
// Only this chat's address: during a jump to another chat this one is still mounted for a moment.
|
|
523
|
+
const onHash = () => {
|
|
524
|
+
const m = /^#m=([0-9a-f]{1,32}-\d{1,15})$/.exec(location.hash);
|
|
525
|
+
if (m && location.pathname === `/ui/chat/${encodeURIComponent(name)}`) void thread.jumpTo(m[1]);
|
|
526
|
+
};
|
|
527
|
+
window.addEventListener("hashchange", onHash);
|
|
369
528
|
return () => {
|
|
370
|
-
|
|
371
|
-
|
|
529
|
+
window.removeEventListener("hashchange", onHash);
|
|
530
|
+
unfollow();
|
|
531
|
+
offActions();
|
|
372
532
|
sc.removeEventListener("scroll", onScroll);
|
|
373
533
|
ls.removeEventListener("click", thread.onClick);
|
|
374
|
-
|
|
534
|
+
e.sink = null;
|
|
375
535
|
th.current = null;
|
|
536
|
+
// Passed through (new, and shown under THREAD_PASS_MS): let go. Otherwise kept for a later visit, within the budget.
|
|
537
|
+
if (keptThreads.get(name) === e && !kept && now() - shownAt < THREAD_PASS_MS) { keptThreads.delete(name); letGo(e, false); }
|
|
538
|
+
else if (keptThreads.get(name) === e) { thread.park(); ls.remove(); trimKept(null); } // kept for a later visit: the chat left
|
|
539
|
+
else letGo(e, false); // let go meanwhile (a new language)
|
|
376
540
|
};
|
|
377
541
|
}, [name]);
|
|
378
542
|
return html`<div class="scroller" ref=${scroller}>
|
|
379
|
-
<div class="thread" ref=${
|
|
543
|
+
<div class="thread-host" ref=${host}></div>
|
|
380
544
|
${empty ? html`<${Empty} icon="chat" title=${t("chat.noMessages")} />` : null}
|
|
381
545
|
<div class="jump-dock">${jump.show ? html`<button data-trust="thread-control" type="button" class="jump-latest" onClick=${() => th.current && th.current.jumpLatest()}>
|
|
382
546
|
<${Icon} name="down" size=${16} />${jump.unseen > 0 ? t("chat.newBelow", jump.unseen) : t("chat.jumpLatest")}</button>` : null}</div>
|
|
@@ -392,15 +556,20 @@ function Dock({ name, inst, lease, exec, awaiting, workingLabel }) {
|
|
|
392
556
|
<${WorkBar} name=${name} lease=${lease} exec=${exec} awaiting=${awaiting} workingLabel=${workingLabel} />
|
|
393
557
|
<${CommandCard} name=${name} lease=${lease} />
|
|
394
558
|
<${QuickActions} name=${name} inst=${inst} lease=${lease} />
|
|
395
|
-
${s.
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
<p class="hint" title=${t(guestPage() ? "chat.guestMore" : "chat.composerMore")}>${t("chat.composerHint")}</p>
|
|
400
|
-
${guestPage() ? html`<p class="guest-note">${t("chat.guestNote")}</p>` : html`<${AuthorizeChip} />`}
|
|
559
|
+
${s.waking[name] ? html`<p class="send-waking" role="status">${t("chat.waking", name)}</p>` : null}
|
|
560
|
+
<${Composer} name=${name} label=${composerLabel(inst, name)} lease=${lease} busy=${R().isBusy(exec)} />
|
|
561
|
+
<div class="composer-row">${guestPage() ? html`<span class="guest-note" title=${t("chat.guestNote")}>${t("chat.guestNote")}</span>` : html`<${ComposerAuth} />`}<span
|
|
562
|
+
class="hint" title=${t(guestPage() ? "chat.guestMore" : "chat.composerMore")}>${t(touchScreen() ? "chat.composerHintTouch" : "chat.composerHint")}</span></div>
|
|
401
563
|
</div></div>`;
|
|
402
564
|
}
|
|
403
565
|
|
|
566
|
+
/** #2233: the public link's page — the dashboard's Sign in is refused there, so it is never offered (#2262 review). */
|
|
567
|
+
const publicLinkPage = () => typeof document !== "undefined" && !!document.body && document.body.dataset.publicLink === "1";
|
|
568
|
+
/** #2233: a backend's "not signed in" choice offers Sign in (the module behind the session gate, loaded when asked). */
|
|
569
|
+
function openBackendSignIn(backend) {
|
|
570
|
+
import("./backend-signin.js").then((m) => m.openSignIn({ backend }), () => toast(t("app.loadFailed"), false));
|
|
571
|
+
}
|
|
572
|
+
|
|
404
573
|
/** #1269: what the last chat command answered — its text, why it was refused, or a list to choose from. */
|
|
405
574
|
function CommandCard({ name, lease }) {
|
|
406
575
|
const c = store.state.commands[name];
|
|
@@ -419,6 +588,8 @@ function CommandCard({ name, lease }) {
|
|
|
419
588
|
${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"
|
|
420
589
|
class=${`btn btn-sm${o.id === c.choices.current ? " current" : ""}`} aria-current=${o.id === c.choices.current ? "true" : undefined}
|
|
421
590
|
disabled=${!!o.disabled} title=${o.disabled || undefined} onClick=${() => { if (!o.disabled) run(o.id); }}>${o.label}</button>`)}</div>` : null}
|
|
591
|
+
${c.choices && c.choices.options.some((o) => o.signIn) && !publicLinkPage() ? html`<div class="cmd-choices" role="group" aria-label=${t("chat.cmdSignIn")}>${c.choices.options.filter((o) => o.signIn).map((o) => html`<button
|
|
592
|
+
key=${`signin:${o.signIn}`} type="button" class="btn btn-sm btn-primary" onClick=${() => openBackendSignIn(o.signIn)}>${t("chat.cmdSignInTo", o.signIn)}</button>`)}</div>` : null}
|
|
422
593
|
</div>`;
|
|
423
594
|
}
|
|
424
595
|
|
|
@@ -465,7 +636,13 @@ function WorkBar({ name, lease, exec, awaiting, workingLabel }) {
|
|
|
465
636
|
: html`<span class="elapsed" title=${t("chat.elapsedTitle")} aria-hidden="true">${since == null ? "" : R().formatElapsed(performance.now() - since)}</span>`}</div>`;
|
|
466
637
|
}
|
|
467
638
|
|
|
468
|
-
|
|
639
|
+
/** #2272: the reply bar's quote — the first ~80 characters, or what it had instead of text. */
|
|
640
|
+
function replySnippet(r) {
|
|
641
|
+
const text = r.text ? (r.text.length > 80 ? `${r.text.slice(0, 79).trimEnd()}…` : r.text) : "";
|
|
642
|
+
return text || (r.media === "photo" ? t("chat.replyPhoto") : r.media === "document" ? t("chat.replyFile") : "");
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
function Composer({ name, label = name, lease, busy }) {
|
|
469
646
|
const s = store.state;
|
|
470
647
|
const input = useRef(null), fileIn = useRef(null);
|
|
471
648
|
const [, tick] = useState(0);
|
|
@@ -473,14 +650,20 @@ function Composer({ name, lease, busy }) {
|
|
|
473
650
|
const [closedFor, setClosedFor] = useState(null); // the draft the palette was closed on (Esc); it opens again on change
|
|
474
651
|
const value = s.drafts[name] || "";
|
|
475
652
|
const files = s.pendingFiles[name] || [];
|
|
653
|
+
const reply = s.replies[name]; // #2272: the message this one will reply to
|
|
476
654
|
const content = !!value.trim() || files.length > 0;
|
|
477
655
|
// A file waiting: what goes is a message with its file, never a command (no palette, no command line). A guest never
|
|
478
656
|
// runs one (#1920: the server refuses its slash text), so it has no palette either.
|
|
479
657
|
const guest = guestPage();
|
|
480
658
|
const palette = guest || files.length || closedFor === value ? null : paletteFor(value);
|
|
481
659
|
const pick = palette && palette.length ? palette[Math.min(sel, palette.length - 1)] : null;
|
|
482
|
-
// Grow with the text, up to a limit: set through the CSSOM, never a style attribute (#1300).
|
|
483
|
-
|
|
660
|
+
// Grow with the text, up to a limit: set through the CSSOM, never a style attribute (#1300). Empty, it is one line
|
|
661
|
+
// (#2478 — a long name's placeholder made the box two lines tall).
|
|
662
|
+
useLayoutEffect(() => {
|
|
663
|
+
const el = input.current; if (!el) return;
|
|
664
|
+
el.style.height = "auto";
|
|
665
|
+
if (value) el.style.height = `${Math.min(el.scrollHeight, 240)}px`;
|
|
666
|
+
}, [value]);
|
|
484
667
|
useEffect(() => { if (input.current) input.current.focus(); }, [name]);
|
|
485
668
|
useEffect(() => { refreshTourSpot(); });
|
|
486
669
|
const setValue = (v) => { store.setDraft(name, v); setSel(0); tick(n => n + 1); };
|
|
@@ -491,7 +674,8 @@ function Composer({ name, lease, busy }) {
|
|
|
491
674
|
setValue("");
|
|
492
675
|
store.runCommand(name, cmd.command, cmd.args, { alive: () => lease.current() });
|
|
493
676
|
};
|
|
494
|
-
|
|
677
|
+
// #2342: a completion is a step Ctrl+Z goes back from (to what was typed); a command that runs consumes the line.
|
|
678
|
+
const complete = (c) => { recordEdit(input.current); setValue(`/${c.name}${c.arg ? " " : ""}`); };
|
|
495
679
|
const submit = () => {
|
|
496
680
|
if (pick) {
|
|
497
681
|
if (value === `/${pick.name}` && !needsArgument(pick.name)) runLine({ command: pick.name, args: "" });
|
|
@@ -501,7 +685,7 @@ function Composer({ name, lease, busy }) {
|
|
|
501
685
|
// #1920: a guest's "/…" would be refused as a command — said here, the draft kept to edit.
|
|
502
686
|
if (guest && /^\s*\//.test(value)) { toast(t("chat.guestNoCommands"), false); return; }
|
|
503
687
|
const cmd = files.length ? null : parseCommandLine(value);
|
|
504
|
-
if (cmd && needsArgument(cmd.command) && !cmd.args) { setValue(`/${cmd.command} `); return; }
|
|
688
|
+
if (cmd && needsArgument(cmd.command) && !cmd.args) { recordEdit(input.current); setValue(`/${cmd.command} `); return; }
|
|
505
689
|
if (cmd) { runLine(cmd); return; }
|
|
506
690
|
store.send(name);
|
|
507
691
|
};
|
|
@@ -513,7 +697,8 @@ function Composer({ name, lease, busy }) {
|
|
|
513
697
|
}
|
|
514
698
|
if (pick && e.key === "Tab" && !e.shiftKey) { e.preventDefault(); complete(pick); return; }
|
|
515
699
|
if (palette && e.key === "Escape" && !e.isComposing) { e.preventDefault(); setClosedFor(value); return; }
|
|
516
|
-
if (
|
|
700
|
+
if (reply && e.key === "Escape" && !e.isComposing) { e.preventDefault(); store.clearReply(name); return; } // #2272
|
|
701
|
+
if (R().composerKey(e, { touch: touchScreen() }) === "send") { e.preventDefault(); submit(); }
|
|
517
702
|
};
|
|
518
703
|
const onInput = (e) => { setValue(e.target.value); };
|
|
519
704
|
// Files in a paste are attached; a very long text paste goes as a text file — only once it is really attached.
|
|
@@ -531,17 +716,25 @@ function Composer({ name, lease, busy }) {
|
|
|
531
716
|
<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>`)
|
|
532
717
|
: html`<li class="cmd-none" role="option" aria-selected="false">${t("chat.cmdNotCommand")}</li>`}
|
|
533
718
|
</ul>` : null}
|
|
719
|
+
${reply ? html`<div class="reply-bar" data-trust="composer" role="status">
|
|
720
|
+
<span class="reply-mark" aria-hidden="true"><svg class="icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 14 4 9l5-5"/><path d="M4 9h10.5a5.5 5.5 0 0 1 0 11H11"/></svg></span><span class="reply-label">${t("chat.replyingTo", reply.sender)}</span>
|
|
721
|
+
<span class="reply-text">${replySnippet(reply)}</span>
|
|
722
|
+
<button type="button" class="icon-btn reply-cancel" title=${t("chat.replyCancel")} aria-label=${t("chat.replyCancel")} onClick=${() => { store.clearReply(name); input.current?.focus(); }}><${Icon} name="close" size=${14} /></button>
|
|
723
|
+
</div>` : null}
|
|
534
724
|
${files.length ? html`<div class="pending-files">${files.map((f, i) => html`<${FileChip} key=${`${f.name}-${i}`} f=${f} i=${i} name=${name} />`)}</div>` : null}
|
|
535
725
|
<div class="composer">
|
|
536
726
|
<button id="attachBtn" type="button" class="icon-btn" title=${t("chat.attachTitle")} aria-label=${t("chat.attachTitle")} onClick=${() => fileIn.current && fileIn.current.click()}><${Icon} name="attach" /></button>
|
|
537
727
|
<input ref=${fileIn} type="file" multiple hidden
|
|
538
728
|
onChange=${(e) => { store.addFiles(name, e.target.files); e.target.value = ""; }} />
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
729
|
+
${/* #2478: the placeholder is drawn beside the box, one line ending in "…" — a textarea's own placeholder is clipped,
|
|
730
|
+
never ellipsized, and a long name wrapped it to two lines. The box keeps the words as its accessible name. */ ""}
|
|
731
|
+
<span class="composer-field"><textarea id="msgIn" ref=${input} rows="1" value=${value} aria-label=${t("chat.composerPlaceholder", label)}
|
|
732
|
+
enterkeyhint=${touchScreen() ? "enter" : undefined} autocomplete="off" aria-controls=${palette ? "cmdPalette" : undefined} aria-expanded=${palette ? "true" : "false"}
|
|
733
|
+
aria-activedescendant=${pick ? optId(pick) : undefined} onInput=${onInput} onKeyDown=${onKeyDown} onPaste=${onPaste}></textarea>${value ? null
|
|
734
|
+
: html`<span class="composer-ph" aria-hidden="true">${t("chat.composerPlaceholder", label)}</span>`}</span>
|
|
542
735
|
<button id="stopBtn" type="button" class="btn btn-stop" hidden=${!busy} title=${t("chat.stopReplyTitle")}
|
|
543
736
|
disabled=${!!s.cancelling[name]} onClick=${() => store.cancelReply(name)}><${Icon} name="stop" size=${14} /><span class="stop-label">${t("chat.stopReply")}</span></button>
|
|
544
|
-
<button id="sendBtn" type="button" class="btn btn-primary btn-send" hidden=${busy && !content} disabled=${!content
|
|
737
|
+
<button id="sendBtn" type="button" class="btn btn-primary btn-send" hidden=${busy && !content} disabled=${!content}
|
|
545
738
|
onMouseDown=${(e) => e.preventDefault()}
|
|
546
739
|
aria-label=${t("chat.send")} title=${t("chat.send")} onClick=${submit}><${Icon} name="send" size=${16} /><span class="send-label">${t("chat.send")}</span></button>
|
|
547
740
|
</div></div>`;
|
|
@@ -559,7 +752,7 @@ function FileChip({ f, i, name }) {
|
|
|
559
752
|
return html`<span class="file-chip">
|
|
560
753
|
${isImage ? html`<img ref=${img} alt="" />` : html`<span class="ic"><${Icon} name="file" size=${16} /></span>`}
|
|
561
754
|
<span class="nm">${f.name}</span><span class="sz">${R().formatSize(f.size)}</span>
|
|
562
|
-
${store.isPasted(f) ? html`<button type="button" class="as-text" onClick=${() => store.fileBackAsText(name, i)}>${t("chat.asText")}</button>` : null}
|
|
755
|
+
${store.isPasted(f) ? html`<button type="button" class="as-text" onClick=${() => { recordEdit(composerField()); store.fileBackAsText(name, i); }}>${t("chat.asText")}</button>` : null}
|
|
563
756
|
<button type="button" class="chip-x" title=${t("chat.removeFile")} aria-label=${`${t("chat.removeFile")} ${f.name}`} onClick=${() => store.removeFile(name, i)}><${Icon} name="close" size=${14} /></button></span>`;
|
|
564
757
|
}
|
|
565
758
|
|
|
@@ -582,7 +775,7 @@ function DeleteDialog({ name, onClose }) {
|
|
|
582
775
|
// navigates anything (the person may be anywhere by then).
|
|
583
776
|
try {
|
|
584
777
|
const res = await confirmedWrite(`/ui/instances/${encodeURIComponent(name)}/delete`, { method: "POST", body: { confirm: typed }, label: t("chat.deleteTitle", name),
|
|
585
|
-
onPending: () => { handedOver = true; toast(t("app.pendingSent")); if (lease.current()) { setBusy(false); onClose(); } } });
|
|
778
|
+
onPending: (_id, view) => { handedOver = true; toast(t(selfConfirmed(view) ? "app.pendingSelfSent" : "app.pendingSent")); if (lease.current()) { setBusy(false); onClose(); } } });
|
|
586
779
|
r = res.ok ? res.body || {} : { error: (res.body && res.body.error) || `HTTP ${res.status}` };
|
|
587
780
|
} catch (err) { r = { error: err && err.message ? err.message : t("chat.disconnected") }; }
|
|
588
781
|
if (r && r.error) { toast(r.error, false); if (!handedOver && lease.current()) setBusy(false); return; }
|
package/dist/ui/panel-details.js
CHANGED
|
@@ -25,6 +25,7 @@ import { Empty, ErrorState, Skeleton } from "/assets/ui-states.js";
|
|
|
25
25
|
import { toast } from "/assets/ui-toast.js";
|
|
26
26
|
import "./chat-strings.js";
|
|
27
27
|
import { api } from "./settings-confirm.js";
|
|
28
|
+
import { InstanceBoardWork } from "./fleet-task-work.js";
|
|
28
29
|
import { requestAgentSettings } from "./settings-request.js";
|
|
29
30
|
|
|
30
31
|
export function DetailsPanel({ route, navKey }) {
|
|
@@ -150,6 +151,7 @@ function DetailsView({ name, inst, navKey, exec, awaiting }) {
|
|
|
150
151
|
${row(t("chat.dContext"), html`<span class="pct">${ctx != null ? `${Math.round(ctx)}%` : "--"}</span>${ctx != null ? bar(ctx, ctx > 80 ? "warn" : "") : null}`)}
|
|
151
152
|
${row(t("chat.dRate5"), html`<span class="pct">${Math.round(rl5)}%</span>${bar(rl5, rl5 > 90 ? "error" : rl5 > 70 ? "warn" : "")}`)}
|
|
152
153
|
${row(t("chat.dRate7"), html`<span class="pct">${Math.round(rl7)}%</span>${bar(rl7, rl7 > 90 ? "error" : rl7 > 70 ? "warn" : "")}`)}</section>
|
|
154
|
+
<${InstanceBoardWork} name=${name} onOpen=${(id) => navigate(`/ui/fleet?card=${encodeURIComponent(id)}`)} />
|
|
153
155
|
<section class="card"><h3>${t("chat.dActivity")}</h3>${d.recent_activity?.length ? d.recent_activity.map((a, i) => html`<div key=${i} class="activity">
|
|
154
156
|
<span class="mono muted">${a.timestamp ? new Date(`${a.timestamp.replace(" ", "T")}Z`).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }) : ""}</span>
|
|
155
157
|
<span class="ev">${a.event}</span> ${a.summary || ""}</div>`) : html`<p class="note">${t("chat.dNoActivity")}</p>`}</section>`;
|