@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/chat-render.js
CHANGED
|
@@ -53,11 +53,14 @@
|
|
|
53
53
|
|
|
54
54
|
// #1630: a Discord server emoji, `<:name:id>` / `<a:name:id>` — escaped by now — drawn as its picture. Only an id the
|
|
55
55
|
// page knows (the fleet's servers: /ui/emojis) and only from the dashboard's own route; the src is built from the
|
|
56
|
-
// matched digits, the name (word characters only) goes into alt/title.
|
|
56
|
+
// matched digits, the name (word characters only) goes into alt/title. Any other — an id the page does not know, or
|
|
57
|
+
// before the list has come — reads `:name:` (never the raw markup); so does a picture that does not load
|
|
58
|
+
// (chat-thread.js swaps it: an <img> sized to an emoji showed an empty box, the user's "tofu").
|
|
57
59
|
var EMOJI_RE = /<(a?):([A-Za-z0-9_]{2,32}):(\d{15,25})>/g;
|
|
58
60
|
function emojiImg(id, name) {
|
|
59
61
|
return '<img class="emoji" src="/ui/img/emoji/' + id + '" alt=":' + name + ':" title=":' + name + ':" decoding="async">';
|
|
60
62
|
}
|
|
63
|
+
function emojiText(name) { return '<span class="emoji-text" title=":' + name + ':">:' + name + ':</span>'; }
|
|
61
64
|
|
|
62
65
|
// #1682: Discord mentions — `<@id>` / `<@!id>` (a user), `<@&id>` (a role), `<#id>` (a channel) — escaped by now (the
|
|
63
66
|
// role's & too), drawn as a pill: the name the page knows (store.mentions(kind, id), inserted escaped), else @user /
|
|
@@ -82,7 +85,7 @@
|
|
|
82
85
|
// path held its whole column wide.
|
|
83
86
|
s = s.replace(/`([^`\n]+)`/g, function (_m, code) { return stash(store, "<code>" + (store.inCell ? code.replace(/\//g, "/<wbr>") : code) + "</code>"); });
|
|
84
87
|
var known = store.emojis;
|
|
85
|
-
|
|
88
|
+
s = s.replace(EMOJI_RE, function (_m, _a, name, id) { return stash(store, known && known(id) ? emojiImg(id, name) : emojiText(name)); });
|
|
86
89
|
var names = store.mentions;
|
|
87
90
|
s = s.replace(MENTION_RE, function (_m, sigil, id) {
|
|
88
91
|
var kind = MENTION_KIND[sigil];
|
|
@@ -429,6 +432,44 @@
|
|
|
429
432
|
return msgs;
|
|
430
433
|
}
|
|
431
434
|
|
|
435
|
+
/**
|
|
436
|
+
* #2305: the list after a reactions update for the row `boot`/`id` (the instance's reactions — its minimal reply): the
|
|
437
|
+
* same list when nothing changed, else a copy. At most 8 distinct short strings are taken; the server sent them.
|
|
438
|
+
*/
|
|
439
|
+
function applyReactions(list, boot, id, reactions) {
|
|
440
|
+
var msgs = list || [];
|
|
441
|
+
if (!Array.isArray(reactions)) return msgs;
|
|
442
|
+
var clean = [];
|
|
443
|
+
for (var j = 0; j < reactions.length && clean.length < 8; j++) {
|
|
444
|
+
var e = reactions[j];
|
|
445
|
+
if (typeof e === "string" && e.length > 0 && e.length <= 16 && clean.indexOf(e) < 0) clean.push(e);
|
|
446
|
+
}
|
|
447
|
+
for (var i = msgs.length - 1; i >= 0; i--) {
|
|
448
|
+
if (!msgs[i] || msgs[i].boot !== boot || msgs[i].id !== id) continue;
|
|
449
|
+
var had = msgs[i].reactions || [];
|
|
450
|
+
var same = had.length === clean.length;
|
|
451
|
+
for (var k = 0; same && k < had.length; k++) if (had[k] !== clean[k]) same = false;
|
|
452
|
+
if (same) return msgs;
|
|
453
|
+
var out = msgs.slice();
|
|
454
|
+
out[i] = Object.assign({}, msgs[i], { reactions: clean });
|
|
455
|
+
return out;
|
|
456
|
+
}
|
|
457
|
+
return msgs;
|
|
458
|
+
}
|
|
459
|
+
/** #2305: an emoji drawn as one — a heart, ☃, ✍ and the like have a text form unless U+FE0F follows. */
|
|
460
|
+
function emojiForm(e) { return /\p{Emoji_Presentation}/u.test(e) ? e : e + "\uFE0F"; }
|
|
461
|
+
/** #2305: a message's reactions under its bubble, labelled for a screen reader (`label`: who reacted); "" when none. */
|
|
462
|
+
function reactionsHtml(reactions, label) {
|
|
463
|
+
if (!Array.isArray(reactions) || !reactions.length) return "";
|
|
464
|
+
var items = "";
|
|
465
|
+
for (var i = 0; i < reactions.length; i++) {
|
|
466
|
+
if (typeof reactions[i] !== "string") continue;
|
|
467
|
+
items += '<span class="reaction" role="img" aria-label="' + escapeHtml(reactions[i]) + '">' + escapeHtml(emojiForm(reactions[i])) + "</span>";
|
|
468
|
+
}
|
|
469
|
+
var l = escapeHtml(label || "");
|
|
470
|
+
return items ? '<div class="msg-reactions" role="group" aria-label="' + l + '" title="' + l + '">' + items + "</div>" : "";
|
|
471
|
+
}
|
|
472
|
+
|
|
432
473
|
var TICK_GLYPH = { queued: "◷", processing: "✓", delivered: "✓✓", failed: "!", cancelled: "⊘" };
|
|
433
474
|
/** The ticks for one state, labelled for a screen reader as well as a pointer; "" when there is none. */
|
|
434
475
|
function deliveryHtml(state, labels) {
|
|
@@ -468,27 +509,17 @@
|
|
|
468
509
|
/** Whether the chat shows "working" and its Stop button for an instance in this execution state. */
|
|
469
510
|
function isBusy(state) { return state === "working" || state === "stuck"; }
|
|
470
511
|
|
|
471
|
-
/**
|
|
472
|
-
|
|
512
|
+
/**
|
|
513
|
+
* What a key in the composer does: Enter sends, Shift+Enter is a new line, nothing happens mid-IME-composition.
|
|
514
|
+
* #2478 (the user's request): on a touch screen (a coarse pointer) Return is a new line — the Send button sends.
|
|
515
|
+
*/
|
|
516
|
+
function composerKey(ev, opts) {
|
|
473
517
|
if (!ev || ev.key !== "Enter" || ev.isComposing || ev.keyCode === 229) return "none";
|
|
518
|
+
if (opts && opts.touch) return "newline";
|
|
474
519
|
if (ev.shiftKey || ev.altKey || ev.ctrlKey || ev.metaKey) return "newline";
|
|
475
520
|
return "send";
|
|
476
521
|
}
|
|
477
522
|
|
|
478
|
-
/**
|
|
479
|
-
* A send that failed: where does its text go? Back into the composer only if that composer is the same
|
|
480
|
-
* target's, still on screen and empty; otherwise it is kept aside for that target (never put into another
|
|
481
|
-
* target's composer, never over a draft someone is typing) and offered back when that chat is open.
|
|
482
|
-
*/
|
|
483
|
-
function settleFailedSend(target, current, composerPresent, composerValue) {
|
|
484
|
-
return target === current && composerPresent && !composerValue ? "restore" : "keep";
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
/** "Put back" for a kept message: in front of whatever is being typed now, never replacing it. */
|
|
488
|
-
function putBack(failedText, draft) {
|
|
489
|
-
return draft ? failedText + "\n" + draft : failedText;
|
|
490
|
-
}
|
|
491
|
-
|
|
492
523
|
/** The defaults of the upload limits the server enforces (web-upload.ts UPLOAD_LIMITS), for a page that was given none. */
|
|
493
524
|
var FILE_LIMITS = { maxFileBytes: 50 * 1024 * 1024, maxFiles: 5, maxTotalBytes: 100 * 1024 * 1024 };
|
|
494
525
|
/**
|
|
@@ -577,6 +608,21 @@
|
|
|
577
608
|
* With { htmlCards: true } (a server-marked agent reply, as for renderMarkdown) each .html/.htm file also gets an
|
|
578
609
|
* empty card placeholder <div class="html-card" data-att="<id>"> after the list — the id is 32 hex, nothing else.
|
|
579
610
|
*/
|
|
611
|
+
// The box a photo is drawn in (app.css: .msg .att-img img, max 260 × 220): its own size, scaled down to fit.
|
|
612
|
+
var PHOTO_MAX_W = 260, PHOTO_MAX_H = 220;
|
|
613
|
+
/**
|
|
614
|
+
* #2184: a photo's drawn size as width/height attributes, from the size the server read from its headers: the box is there
|
|
615
|
+
* before the picture loads, so the text around it never moves when it does (a chat opened cold jittered, as each
|
|
616
|
+
* photo grew from nothing). Nothing when the size is not known (drawn as before).
|
|
617
|
+
*/
|
|
618
|
+
function photoBox(a) {
|
|
619
|
+
var w = a.width, h = a.height;
|
|
620
|
+
var ok = function (v) { return typeof v === "number" && v >= 1 && v <= 65535 && Math.floor(v) === v; };
|
|
621
|
+
if (!ok(w) || !ok(h)) return "";
|
|
622
|
+
var k = Math.min(1, PHOTO_MAX_W / w, PHOTO_MAX_H / h);
|
|
623
|
+
return ' width="' + Math.max(1, Math.round(w * k)) + '" height="' + Math.max(1, Math.round(h * k)) + '"';
|
|
624
|
+
}
|
|
625
|
+
|
|
580
626
|
function attachmentsHtml(attachments, opts) {
|
|
581
627
|
if (!Array.isArray(attachments)) return "";
|
|
582
628
|
var cards = !!(opts && opts.htmlCards);
|
|
@@ -599,7 +645,7 @@
|
|
|
599
645
|
else if (kind) after.push('<div class="text-card" data-att="' + a.id + '" data-type="' + kind + '"></div>');
|
|
600
646
|
var name = escapeHtml(a.name || "file");
|
|
601
647
|
if (a.kind === "photo") {
|
|
602
|
-
out.push('<a class="att-img" href="' + url + '" target="_blank" rel="noopener noreferrer"><img src="' + url + '" alt="' + name + '" loading="lazy"></a>');
|
|
648
|
+
out.push('<a class="att-img" href="' + url + '" target="_blank" rel="noopener noreferrer"><img src="' + url + '" alt="' + name + '"' + photoBox(a) + ' loading="lazy"></a>');
|
|
603
649
|
} else {
|
|
604
650
|
out.push('<a class="att-file" href="' + url + '" download="' + name + '">📎 ' + name + ' <span class="att-size">' + escapeHtml(formatSize(a.size)) + "</span></a>");
|
|
605
651
|
}
|
|
@@ -610,9 +656,10 @@
|
|
|
610
656
|
return {
|
|
611
657
|
renderMarkdown: renderMarkdown, escapeHtml: escapeHtml, mergeMessages: mergeMessages, applyReplyButtons: applyReplyButtons, composerKey: composerKey,
|
|
612
658
|
pollRemaining: pollRemaining,
|
|
613
|
-
|
|
659
|
+
|
|
614
660
|
FILE_LIMITS: FILE_LIMITS, fileLimits: fileLimits, fileRejection: fileRejection, formatSize: formatSize, checkFiles: checkFiles, attachmentsHtml: attachmentsHtml, isHtmlAttachment: isHtmlAttachment,
|
|
615
661
|
nextDeliveryState: nextDeliveryState, applyDelivery: applyDelivery, deliveryHtml: deliveryHtml, isBusy: isBusy,
|
|
662
|
+
applyReactions: applyReactions, reactionsHtml: reactionsHtml,
|
|
616
663
|
isNearBottom: isNearBottom, CODE_FOLD_LINES: CODE_FOLD_LINES, lineCount: lineCount,
|
|
617
664
|
LONG_PASTE_CHARS: LONG_PASTE_CHARS, isLongPaste: isLongPaste, formatElapsed: formatElapsed,
|
|
618
665
|
htmlFences: htmlFences, attachmentPreviewType: attachmentPreviewType, highlight: highlight,
|
package/dist/ui/chat-store.js
CHANGED
|
@@ -42,7 +42,7 @@ const COMPACT_PAGE_LIMIT_MS = 11 * 60_000;
|
|
|
42
42
|
/** Build a store. `deps` (fetch, toast, announce, t, now) are injected so tests can drive every path. */
|
|
43
43
|
export function createChatStore(deps) {
|
|
44
44
|
const s = {
|
|
45
|
-
msgs: {}, drafts: {},
|
|
45
|
+
msgs: {}, drafts: {}, replies: {}, pendingFiles: {}, sending: {}, outgoing: {}, instanceStatus: {}, waking: {},
|
|
46
46
|
prompts: {}, workingSince: {}, stopping: {}, cancelling: {}, scrollMemo: {}, historyRead: new Set(), rbBusy: new Set(),
|
|
47
47
|
pollMine: readPollMine(),
|
|
48
48
|
// #1823 (#1828 review): the server's clock minus this device's. A poll's deadline is the server's; a page whose clock
|
|
@@ -61,9 +61,10 @@ export function createChatStore(deps) {
|
|
|
61
61
|
|
|
62
62
|
/** Tell subscribers what changed: `kind` "msgs" (the thread redraws) or "state" (everything else). */
|
|
63
63
|
function changed(instance, kind = "state") { for (const fn of [...subs]) fn(instance, kind); }
|
|
64
|
-
async function api(method, path, body) {
|
|
64
|
+
async function api(method, path, body, signal) {
|
|
65
65
|
const o = { method, headers: { "Content-Type": "application/json" } };
|
|
66
66
|
if (body) o.body = JSON.stringify(body);
|
|
67
|
+
if (signal) o.signal = signal;
|
|
67
68
|
const r = await deps.fetch(path, o);
|
|
68
69
|
return r.json();
|
|
69
70
|
}
|
|
@@ -82,6 +83,7 @@ export function createChatStore(deps) {
|
|
|
82
83
|
function applyStatus(d) {
|
|
83
84
|
if (!d || !Array.isArray(d.instances)) return;
|
|
84
85
|
for (const i of d.instances) {
|
|
86
|
+
s.instanceStatus[i.name] = i.status;
|
|
85
87
|
noteExec(i.name, (i.execution_state !== undefined ? i.execution_state : i.state) ?? null);
|
|
86
88
|
const waits = i.state === "awaiting_input" ? (typeof i.interaction_summary === "string" ? i.interaction_summary : "") : null;
|
|
87
89
|
if (i.name === s.current && waits != null && s.awaiting[i.name] == null) deps.announce(tf("chat.awaiting", i.name));
|
|
@@ -106,6 +108,8 @@ export function createChatStore(deps) {
|
|
|
106
108
|
liveReplies.message(m, extra);
|
|
107
109
|
const before = s.msgs[m.instance];
|
|
108
110
|
s.msgs[m.instance] = R().mergeMessages(before, [m], 500);
|
|
111
|
+
// The live copy of a message this page sent carries its clientId: its pending bubble goes in this same redraw.
|
|
112
|
+
if (settleOutgoing(m.instance, m.role === "user" ? m.clientId : undefined) && s.msgs[m.instance] === before) changed(m.instance, "msgs");
|
|
109
113
|
if (m.instance === s.current && s.msgs[m.instance] !== before && m.role !== "status" && !isUser(m, m.instance) && (s.msgs[m.instance] || []).length > (before || []).length) deps.announce(tf("chat.a11yReplied", m.sender));
|
|
110
114
|
if (s.msgs[m.instance] !== before) changed(m.instance, "msgs");
|
|
111
115
|
}
|
|
@@ -127,6 +131,13 @@ export function createChatStore(deps) {
|
|
|
127
131
|
s.msgs[u.instance] = R().applyReplyButtons(before, u.buttons);
|
|
128
132
|
if (s.msgs[u.instance] !== before) changed(u.instance, "msgs");
|
|
129
133
|
}
|
|
134
|
+
/** #2305: the instance reacted to a message — its bubble shows it. */
|
|
135
|
+
function applyReactions(u) {
|
|
136
|
+
if (!u || typeof u.instance !== "string" || typeof u.boot !== "string" || typeof u.id !== "number") return;
|
|
137
|
+
const before = s.msgs[u.instance];
|
|
138
|
+
s.msgs[u.instance] = R().applyReactions(before, u.boot, u.id, u.reactions);
|
|
139
|
+
if (s.msgs[u.instance] !== before) changed(u.instance, "msgs");
|
|
140
|
+
}
|
|
130
141
|
/**
|
|
131
142
|
* #1266: click one of a reply's buttons (the first click anywhere answers for everyone). On a poll (#1823) it is this
|
|
132
143
|
* session's vote: the answer is its ballot, which only this page marks.
|
|
@@ -142,16 +153,22 @@ export function createChatStore(deps) {
|
|
|
142
153
|
if (!r || !r.answered) deps.toast(r && r.error ? r.error : t("chat.disconnected"), false);
|
|
143
154
|
}
|
|
144
155
|
|
|
145
|
-
/**
|
|
146
|
-
|
|
147
|
-
|
|
156
|
+
/**
|
|
157
|
+
* Read an instance's history once per page (the first time a person opens its chat). #2188: `signal` — the chat was
|
|
158
|
+
* left before the answer came (clicking down the sidebar): the read is aborted, nothing is merged, and the next visit
|
|
159
|
+
* reads again.
|
|
160
|
+
*/
|
|
161
|
+
async function openHistory(name, lease, signal) {
|
|
162
|
+
if (s.historyRead.has(name) || signal?.aborted) return false;
|
|
148
163
|
s.historyRead.add(name);
|
|
149
164
|
try {
|
|
150
|
-
const r = await api("GET", `/ui/history?instance=${encodeURIComponent(name)}&limit=200
|
|
165
|
+
const r = await api("GET", `/ui/history?instance=${encodeURIComponent(name)}&limit=200`, undefined, signal);
|
|
166
|
+
if (signal?.aborted) { s.historyRead.delete(name); return false; }
|
|
151
167
|
if (!r || !Array.isArray(r.messages)) { s.historyRead.delete(name); return true; }
|
|
152
168
|
// Kept even when the person has moved on: the store is page-lived, and the answer belongs to `name`.
|
|
153
169
|
for (const m of r.messages) liveReplies.message(m);
|
|
154
170
|
s.msgs[name] = R().mergeMessages(s.msgs[name], r.messages, 500);
|
|
171
|
+
settleOutgoing(name);
|
|
155
172
|
changed(name, "msgs");
|
|
156
173
|
} catch { s.historyRead.delete(name); /* the live stream still works; the next visit tries again */ }
|
|
157
174
|
void lease;
|
|
@@ -228,51 +245,186 @@ export function createChatStore(deps) {
|
|
|
228
245
|
}
|
|
229
246
|
const promptsFor = (instance) => Object.values(s.prompts).filter(p => p.instance === instance);
|
|
230
247
|
|
|
231
|
-
// ── Sending
|
|
232
|
-
//
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
248
|
+
// ── Sending (Discord-like, the user's request): a message shows at once as its own bubble, dimmed while it goes; its
|
|
249
|
+
// files show their upload progress. The server's copy replaces it when it arrives — matched by the page's clientId
|
|
250
|
+
// (on the live copy) or the messageId the send answered with — so it is never shown twice. A send that fails stays,
|
|
251
|
+
// marked, with Retry and Delete: nothing is lost, and nothing is put back into the composer behind the person's back.
|
|
252
|
+
// Sends of one chat go out in order, one at a time; a later one waits behind an earlier one still going.
|
|
253
|
+
let outSeq = 0;
|
|
254
|
+
const objectUrl = (f) => { try { return globalThis.URL && typeof URL.createObjectURL === "function" && /^image\/(png|jpeg|gif|webp)$/.test(f.type || "") ? URL.createObjectURL(f) : null; } catch { return null; } };
|
|
255
|
+
const freeUrl = (u) => { try { if (u) URL.revokeObjectURL(u); } catch { /* gone */ } };
|
|
256
|
+
const newClientId = () => {
|
|
257
|
+
const bytes = new Uint8Array(12);
|
|
258
|
+
try { globalThis.crypto.getRandomValues(bytes); } catch { for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256); }
|
|
259
|
+
return "c" + [...bytes].map((x) => x.toString(16).padStart(2, "0")).join("");
|
|
260
|
+
};
|
|
261
|
+
/** Pending bubbles the server's copy now stands for go (their previews freed). Returns whether any went. */
|
|
262
|
+
function settleOutgoing(name, clientId) {
|
|
263
|
+
const list = s.outgoing[name];
|
|
264
|
+
if (!list || !list.length) return false;
|
|
265
|
+
const ids = new Set((s.msgs[name] || []).map((m) => m.messageId).filter(Boolean)), clients = new Set(clientId ? [clientId] : []);
|
|
266
|
+
const kept = list.filter((e) => !((e.messageId && ids.has(e.messageId)) || clients.has(e.clientId)));
|
|
267
|
+
if (kept.length === list.length) return false;
|
|
268
|
+
for (const e of list) if (!kept.includes(e)) for (const f of e.files) freeUrl(f.url);
|
|
269
|
+
s.outgoing[name] = kept;
|
|
270
|
+
return true;
|
|
271
|
+
}
|
|
272
|
+
/** The thread as drawn: the server's messages, then this page's pending ones. */
|
|
273
|
+
function threadRows(name) {
|
|
274
|
+
const out = s.outgoing[name];
|
|
275
|
+
return out && out.length ? (s.msgs[name] || []).concat(out) : (s.msgs[name] || []);
|
|
276
|
+
}
|
|
277
|
+
/** Upload one file, its progress told as it goes (XHR: fetch cannot report an upload's progress). */
|
|
278
|
+
async function uploadFile(target, file, onProgress) {
|
|
279
|
+
const url = `/ui/upload?instance=${encodeURIComponent(target)}`;
|
|
280
|
+
const X = deps.XMLHttpRequest;
|
|
281
|
+
if (!X) { // no XHR given (a test): the whole file at once
|
|
282
|
+
const r = await deps.fetch(url, { method: "POST", headers: { "Content-Type": file.type || "application/octet-stream", "X-Agend-Filename": encodeURIComponent(file.name || "file") }, body: file });
|
|
283
|
+
let body = {};
|
|
284
|
+
try { body = await r.json(); } catch { /* not JSON */ }
|
|
285
|
+
if (!r.ok || !body || typeof body.id !== "string") throw new Error(body && body.error ? `${file.name}: ${body.error}` : `${file.name}: upload failed (${r.status})`);
|
|
286
|
+
onProgress?.(file.size || 0, file.size || 0);
|
|
287
|
+
return body;
|
|
288
|
+
}
|
|
289
|
+
// The CSRF header the page's fetch adds (agend-auth.js), added here too; a 401 ends the session as fetch's would.
|
|
290
|
+
const csrf = globalThis.AgendAuth && typeof globalThis.AgendAuth.csrf === "function" ? await globalThis.AgendAuth.csrf().catch(() => null) : null;
|
|
291
|
+
return new Promise((resolve, reject) => {
|
|
292
|
+
const xhr = new X();
|
|
293
|
+
xhr.open("POST", url);
|
|
294
|
+
xhr.setRequestHeader("Content-Type", file.type || "application/octet-stream");
|
|
295
|
+
xhr.setRequestHeader("X-Agend-Filename", encodeURIComponent(file.name || "file"));
|
|
296
|
+
if (csrf) xhr.setRequestHeader("X-Agend-CSRF", csrf);
|
|
297
|
+
if (xhr.upload && onProgress) xhr.upload.onprogress = (ev) => { if (ev.lengthComputable) onProgress(ev.loaded, ev.total); };
|
|
298
|
+
xhr.onload = () => {
|
|
299
|
+
let body = {};
|
|
300
|
+
try { body = JSON.parse(xhr.responseText || "{}"); } catch { /* not JSON */ }
|
|
301
|
+
if (xhr.status === 401) globalThis.AgendAuth?.unauthorized?.();
|
|
302
|
+
if (xhr.status >= 200 && xhr.status < 300 && body && typeof body.id === "string") resolve(body);
|
|
303
|
+
else reject(new Error(body && body.error ? `${file.name}: ${body.error}` : `${file.name}: upload failed (${xhr.status})`));
|
|
304
|
+
};
|
|
305
|
+
xhr.onerror = () => reject(new Error(`${file.name}: ${t("chat.uploadNoConnection")}`));
|
|
306
|
+
xhr.onabort = () => reject(new Error(`${file.name}: ${t("chat.uploadNoConnection")}`));
|
|
307
|
+
xhr.send(file);
|
|
238
308
|
});
|
|
239
|
-
let body = {};
|
|
240
|
-
try { body = await r.json(); } catch { /* not JSON */ }
|
|
241
|
-
if (!r.ok || !body || typeof body.id !== "string") throw new Error(body && body.error ? `${file.name}: ${body.error}` : `${file.name}: upload failed (${r.status})`);
|
|
242
|
-
return body;
|
|
243
309
|
}
|
|
244
|
-
|
|
310
|
+
/** Send what the composer holds: its bubble at once, then out in this chat's order. */
|
|
311
|
+
function send(target) {
|
|
245
312
|
const txt = (s.drafts[target] || "").trim();
|
|
246
313
|
const files = (s.pendingFiles[target] || []).slice();
|
|
247
|
-
if ((!txt && !files.length) || !target
|
|
248
|
-
s.
|
|
314
|
+
if ((!txt && !files.length) || !target) return;
|
|
315
|
+
const quote = s.replies[target];
|
|
316
|
+
const e = {
|
|
317
|
+
// "You" until the server's copy (with the person's name) replaces it: no request is made for a name.
|
|
318
|
+
boot: "out", id: ++outSeq, instance: target, role: "user", sender: t("chat.you"), text: txt,
|
|
319
|
+
ts: new Date().toISOString(), clientId: newClientId(), replyTo: quote ? { boot: quote.boot, id: quote.id, sender: quote.sender, text: quote.text, media: quote.media } : undefined,
|
|
320
|
+
quote, outgoing: { state: "queued" },
|
|
321
|
+
files: files.map((f) => ({ file: f, name: f.name || "file", size: f.size || 0, type: f.type || "", url: objectUrl(f), loaded: 0, total: f.size || 0, state: "waiting", id: null })),
|
|
322
|
+
};
|
|
323
|
+
(s.outgoing[target] = s.outgoing[target] || []).push(e);
|
|
249
324
|
s.drafts[target] = "";
|
|
250
|
-
s.pendingFiles[target] = [];
|
|
325
|
+
s.pendingFiles[target] = [];
|
|
326
|
+
if (quote) delete s.replies[target];
|
|
327
|
+
changed(target, "msgs");
|
|
251
328
|
changed(target);
|
|
252
329
|
changed(target, "sent"); // your own message: the thread goes to the bottom
|
|
330
|
+
return pump(target);
|
|
331
|
+
}
|
|
332
|
+
/** Take this chat's waiting sends, one after another. */
|
|
333
|
+
async function pump(target) {
|
|
334
|
+
if (s.sending[target]) return;
|
|
335
|
+
s.sending[target] = true;
|
|
336
|
+
try {
|
|
337
|
+
for (let e = nextQueued(target); e; e = nextQueued(target)) await deliver(target, e);
|
|
338
|
+
} finally { s.sending[target] = false; delete s.waking[target]; changed(target); }
|
|
339
|
+
}
|
|
340
|
+
const nextQueued = (target) => (s.outgoing[target] || []).find((x) => x.outgoing.state === "queued");
|
|
341
|
+
/** One send: its files (each with its own progress), then the message. */
|
|
342
|
+
async function deliver(target, e) {
|
|
343
|
+
e.outgoing = { state: "sending" };
|
|
344
|
+
s.waking[target] = s.instanceStatus[target] === "paused";
|
|
345
|
+
changed(target, "msgs"); changed(target);
|
|
253
346
|
let r;
|
|
254
347
|
try {
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
348
|
+
for (const f of e.files) {
|
|
349
|
+
if (f.id) continue; // uploaded by an earlier try
|
|
350
|
+
f.state = "uploading"; f.loaded = 0; changed(target, "progress");
|
|
351
|
+
let last = 0;
|
|
352
|
+
const body = await uploadFile(target, f.file, (loaded, total) => {
|
|
353
|
+
f.loaded = loaded; f.total = total || f.total;
|
|
354
|
+
const at = deps.now ? deps.now() : Date.now();
|
|
355
|
+
if (at - last > 60 || loaded >= f.total) { last = at; changed(target, "progress"); }
|
|
356
|
+
});
|
|
357
|
+
f.id = body.id; f.state = "done"; f.loaded = f.total; changed(target, "progress");
|
|
358
|
+
}
|
|
359
|
+
const body = { instance: target, message: e.text, clientId: e.clientId };
|
|
360
|
+
const ids = e.files.map((f) => f.id);
|
|
361
|
+
if (ids.length) body.attachments = ids;
|
|
362
|
+
if (e.quote) body.replyTo = { boot: e.quote.boot, id: e.quote.id };
|
|
363
|
+
r = await api("POST", "/ui/send", body);
|
|
364
|
+
} catch (err) {
|
|
365
|
+
const f = e.files.find((x) => x.state === "uploading");
|
|
366
|
+
if (f) f.state = "failed";
|
|
367
|
+
// The browser's own words for a request that never reached the server (Chrome, Firefox, Safari): the page's.
|
|
368
|
+
const offline = err && err.name === "TypeError" && /failed to fetch|networkerror|load failed/i.test(err.message || "");
|
|
369
|
+
r = { error: offline ? t("chat.sendNoConnection") : err && err.message ? err.message : t("chat.disconnected") };
|
|
267
370
|
}
|
|
268
|
-
|
|
269
|
-
|
|
371
|
+
if (!(s.outgoing[target] || []).includes(e)) return; // deleted meanwhile
|
|
372
|
+
if (r && !r.error && r.sent !== false) {
|
|
373
|
+
e.outgoing = { state: "sent" };
|
|
374
|
+
if (typeof r.messageId === "string") e.messageId = r.messageId;
|
|
375
|
+
settleOutgoing(target);
|
|
376
|
+
changed(target, "msgs"); changed(target);
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
// Files the server no longer holds (they are released when a delivery fails) are uploaded again on Retry.
|
|
380
|
+
if (r && typeof r.error === "string" && /files? (are|is) not available|no such file|already sent/i.test(r.error)) for (const f of e.files) { f.id = null; f.state = "waiting"; }
|
|
381
|
+
// #2272: the quoted message is gone: Retry sends it without the quote.
|
|
382
|
+
if (r && r.reason === "reply_gone") { e.quote = undefined; e.replyTo = undefined; }
|
|
383
|
+
const why = r && r.reason;
|
|
384
|
+
const key = typeof why === "string" ? `chat.sendFailure_${why}` : "";
|
|
385
|
+
const localized = key ? t(key) : "";
|
|
386
|
+
e.outgoing = { state: "failed", error: localized && localized !== key ? localized : (r && r.error ? r.error : t("chat.disconnected")) };
|
|
387
|
+
changed(target, "msgs"); changed(target);
|
|
388
|
+
deps.toast(e.outgoing.error, false);
|
|
389
|
+
}
|
|
390
|
+
/** A failed send, sent again (the same bubble; files already uploaded are not uploaded again). */
|
|
391
|
+
function retryOutgoing(target, clientId) {
|
|
392
|
+
const e = (s.outgoing[target] || []).find((x) => x.clientId === clientId);
|
|
393
|
+
if (!e || e.outgoing.state !== "failed") return;
|
|
394
|
+
e.outgoing = { state: "queued" };
|
|
395
|
+
for (const f of e.files) if (f.state === "failed") f.state = "waiting";
|
|
396
|
+
changed(target, "msgs");
|
|
397
|
+
return pump(target);
|
|
398
|
+
}
|
|
399
|
+
/** A failed send, let go (its previews freed). */
|
|
400
|
+
function deleteOutgoing(target, clientId) {
|
|
401
|
+
const list = s.outgoing[target] || [];
|
|
402
|
+
const e = list.find((x) => x.clientId === clientId);
|
|
403
|
+
if (!e || e.outgoing.state !== "failed") return;
|
|
404
|
+
for (const f of e.files) freeUrl(f.url);
|
|
405
|
+
s.outgoing[target] = list.filter((x) => x !== e);
|
|
406
|
+
changed(target, "msgs"); changed(target);
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* A failed send, back in the composer to change it: its text before what is typed there now, its files (within the
|
|
410
|
+
* limits) and its reply, if none is started; the bubble goes. The page records the composer's undo step first.
|
|
411
|
+
*/
|
|
412
|
+
function putBackOutgoing(target, clientId) {
|
|
413
|
+
const list = s.outgoing[target] || [];
|
|
414
|
+
const e = list.find((x) => x.clientId === clientId);
|
|
415
|
+
if (!e || e.outgoing.state !== "failed") return;
|
|
416
|
+
const draft = s.drafts[target] || "";
|
|
417
|
+
s.drafts[target] = e.text ? (draft ? e.text + "\n" + draft : e.text) : draft;
|
|
418
|
+
for (const f of e.files) freeUrl(f.url);
|
|
419
|
+
s.outgoing[target] = list.filter((x) => x !== e);
|
|
420
|
+
if (e.quote && !s.replies[target]) s.replies[target] = e.quote;
|
|
421
|
+
changed(target, "msgs");
|
|
422
|
+
if (e.files.length) addFiles(target, e.files.map((f) => f.file)); else changed(target);
|
|
270
423
|
}
|
|
271
424
|
function addFiles(target, list) {
|
|
272
425
|
if (!target) return;
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
s.pendingFiles[target] = res.kept.slice(inFlight.length);
|
|
426
|
+
const res = R().checkFiles(s.pendingFiles[target] || [], [...(list || [])]);
|
|
427
|
+
s.pendingFiles[target] = res.kept;
|
|
276
428
|
for (const x of res.rejected) { const why = R().fileRejection(x.reason); deps.toast(`${x.name}: ${t(why.key, ...why.values)}`, false); }
|
|
277
429
|
changed(target);
|
|
278
430
|
}
|
|
@@ -282,7 +434,7 @@ export function createChatStore(deps) {
|
|
|
282
434
|
if (!target) return false;
|
|
283
435
|
const stamp = new Date().toISOString().slice(0, 19).replace(/[-:T]/g, "");
|
|
284
436
|
const f = new File([text], `pasted-${stamp}.txt`, { type: "text/plain" });
|
|
285
|
-
const taken =
|
|
437
|
+
const taken = s.pendingFiles[target] || [];
|
|
286
438
|
if (R().checkFiles(taken, [f]).rejected.length) { deps.toast(t("chat.pasteKeptAsText")); return false; }
|
|
287
439
|
pastedTexts.set(f, text);
|
|
288
440
|
addFiles(target, [f]);
|
|
@@ -299,16 +451,32 @@ export function createChatStore(deps) {
|
|
|
299
451
|
changed(target);
|
|
300
452
|
}
|
|
301
453
|
const isPasted = (f) => pastedTexts.has(f);
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
454
|
+
/** Typing stays local. */
|
|
455
|
+
function setDraft(target, value) { s.drafts[target] = value; }
|
|
456
|
+
/**
|
|
457
|
+
* #2272: reply to a message of this chat — what the bar above the composer shows (its sender and first words); only
|
|
458
|
+
* its row is sent. One at a time per chat: a new one replaces it.
|
|
459
|
+
*/
|
|
460
|
+
function startReply(target, m) {
|
|
461
|
+
if (!target || !m || typeof m.boot !== "string" || typeof m.id !== "number") return;
|
|
462
|
+
s.replies[target] = { boot: m.boot, id: m.id, sender: String(m.sender || ""), text: String(m.click?.label ?? m.text ?? "").replace(/\s+/g, " ").trim().slice(0, 160),
|
|
463
|
+
media: (m.attachments || []).length ? ((m.attachments || []).some(a => a.kind === "photo") ? "photo" : "document") : undefined };
|
|
307
464
|
changed(target);
|
|
308
465
|
}
|
|
309
|
-
function
|
|
310
|
-
/**
|
|
311
|
-
|
|
466
|
+
function clearReply(target) { if (s.replies[target]) { delete s.replies[target]; changed(target); } }
|
|
467
|
+
/**
|
|
468
|
+
* #2272: the quoted message, drawn for a jump: in what this chat holds, or after reading the longest history the
|
|
469
|
+
* server keeps for it (the newest 500). false: no longer kept.
|
|
470
|
+
*/
|
|
471
|
+
async function findQuoted(name, key) {
|
|
472
|
+
const has = () => (s.msgs[name] || []).some(m => `${m.boot}-${m.id}` === key);
|
|
473
|
+
if (has()) return true;
|
|
474
|
+
try {
|
|
475
|
+
const r = await api("GET", `/ui/history?instance=${encodeURIComponent(name)}&limit=500`);
|
|
476
|
+
if (r && Array.isArray(r.messages)) { s.msgs[name] = R().mergeMessages(s.msgs[name], r.messages, 500); settleOutgoing(name); changed(name, "msgs"); }
|
|
477
|
+
} catch { /* the jump says it is not there */ }
|
|
478
|
+
return has();
|
|
479
|
+
}
|
|
312
480
|
|
|
313
481
|
// ── Stop the reply under way (the composer's Stop, or Esc). Set before the request goes, so a held Esc or a second
|
|
314
482
|
// click sends nothing more (#1317); "Stopping…" until the agent goes idle, or a minute passes.
|
|
@@ -391,6 +559,7 @@ export function createChatStore(deps) {
|
|
|
391
559
|
stream.on("prompts", applyPrompts);
|
|
392
560
|
stream.on("prompt_resolved", resolvePrompt);
|
|
393
561
|
stream.on("reply_buttons", applyReplyButtons);
|
|
562
|
+
stream.on("reactions", applyReactions); // #2305
|
|
394
563
|
stream.on("clock", noteServerClock); // #1823
|
|
395
564
|
}
|
|
396
565
|
|
|
@@ -402,7 +571,8 @@ export function createChatStore(deps) {
|
|
|
402
571
|
attach, applyStatus, applyActivity, ingest, applyDeliveries, openHistory,
|
|
403
572
|
onPrompt, applyPrompts, resolvePrompt, answerPrompt, answerByNonce, holdPrompt, releasePrompt, promptsFor,
|
|
404
573
|
applyReplyButtons, clickReplyButton,
|
|
405
|
-
uploadFile, send, addFiles, removeFile, attachPastedText, fileBackAsText, isPasted,
|
|
574
|
+
uploadFile, send, retryOutgoing, deleteOutgoing, putBackOutgoing, threadRows, addFiles, removeFile, attachPastedText, fileBackAsText, isPasted, setDraft,
|
|
575
|
+
startReply, clearReply, findQuoted,
|
|
406
576
|
cancelReply, isUser, runCommand, dismissCommand, commandFree,
|
|
407
577
|
};
|
|
408
578
|
}
|