@songsid/agend 2.3.0-beta.9 → 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 +7 -1
- package/dist/agent-cli.js +41 -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 +53 -12
- 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 +41 -4
- 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.js.map +1 -1
- 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 +249 -13
- package/dist/fleet-manager.js +1561 -292
- 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.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 +24 -4
- package/dist/general-knowledge/skills/web-dashboard/SKILL.canvas-worker-off.md +553 -0
- package/dist/general-knowledge/skills/web-dashboard/SKILL.md +154 -31
- 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 +106 -60
- package/dist/outbound-schemas.js +33 -10
- 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.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 +23 -5
- package/dist/ui/app.html +2 -0
- package/dist/ui/backend-signin.js +297 -0
- package/dist/ui/chat-effects.js +10 -3
- package/dist/ui/chat-msg-actions.js +176 -0
- package/dist/ui/chat-render.js +62 -18
- package/dist/ui/chat-store.js +218 -48
- package/dist/ui/chat-strings.js +40 -8
- package/dist/ui/chat-thread.js +119 -10
- 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 +69 -28
- 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 +18 -5
- 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 +81 -18
- 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 +200 -56
- 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 +2 -0
- 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 +5 -1
- package/dist/ui/shared/app-themes.js +116 -1
- package/dist/ui/shared/app.css +662 -48
- 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-registry.js +14 -4
- package/dist/ui/shared/effect-runtime-loader.js +3 -1
- package/dist/ui/shared/effect-stock-trust.js +5 -5
- 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 +4 -0
- 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.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.map +1 -1
- package/dist/web-api.d.ts +57 -10
- package/dist/web-api.js +1103 -70
- 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 +3 -0
- 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-thread.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// Unrelated updates (a new message, another message's tick) stop nothing (#1306 §6.2, #1408 §4).
|
|
9
9
|
import "./chat-render.js";
|
|
10
10
|
import "./preview.js";
|
|
11
|
-
import {
|
|
11
|
+
import { canvasWorkerEnabled, onCanvasWorkerChange, onCanvasMetadataChange, readCanvasTrialMessage } from "/assets/feature-flags.js";
|
|
12
12
|
import { loadHtmlAttachment } from "./html-attachment.js";
|
|
13
13
|
import { chatTime, chatTimeFull, onDayChange } from "./chat-time.js";
|
|
14
14
|
import { textLinkSegments } from "/assets/app-route.js";
|
|
@@ -28,6 +28,7 @@ const P = () => globalThis.AgendPreview;
|
|
|
28
28
|
/** #1672: a status line longer than this (lines, or characters) is folded until it is opened. */
|
|
29
29
|
export const STATUS_FOLD_LINES = 6;
|
|
30
30
|
export const STATUS_FOLD_CHARS = 600;
|
|
31
|
+
const REPLY = '<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" aria-hidden="true"><path d="M9 14 4 9l5-5"/><path d="M4 9h10.5a5.5 5.5 0 0 1 0 11H11"/></svg>';
|
|
31
32
|
const COPY = '<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" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>';
|
|
32
33
|
|
|
33
34
|
/** Escapes & " ' < >: safe for text and inside a quoted attribute. */
|
|
@@ -131,8 +132,9 @@ export function createThread(list, scroller, opts) {
|
|
|
131
132
|
// #1770: the label ("17:38", "Yesterday 17:38", "10/11 17:38") depends on today, so it is not part of the html a node
|
|
132
133
|
// is kept by: it is written into the node (timeLabels) — crossing midnight relabels in place and reloads no preview.
|
|
133
134
|
const time = x.ts ? `<span class="time" data-ts="${escAttr(x.ts)}" title="${escAttr(chatTimeFull(x.ts))}"></span>` : `<span class="time"></span>`;
|
|
134
|
-
|
|
135
|
-
|
|
135
|
+
if (x.outgoing) return outgoingHtml(x);
|
|
136
|
+
const trial = readCanvasTrialMessage(x);
|
|
137
|
+
if (trial) return canvasWorkerEnabled() ? trialHtml(trial, time, x) : "";
|
|
136
138
|
if (x.role === "status") return statusHtml(x, time);
|
|
137
139
|
const u = opts.isUser(x);
|
|
138
140
|
// renderMarkdown escapes the whole text before it adds any tag of its own (chat-render.js).
|
|
@@ -141,7 +143,64 @@ export function createThread(list, scroller, opts) {
|
|
|
141
143
|
const buttons = x.role === "agent" ? replyButtonsHtml(x.buttons) : "";
|
|
142
144
|
// A person's click on a reply button shows as the button's label, never the line the agent was given (its value).
|
|
143
145
|
const clicked = x.role === "user" && x.click && typeof x.click.label === "string";
|
|
144
|
-
|
|
146
|
+
// #2272: reply to it — a hover strip at its top right (phones: swipe left or long-press; R on a focused message).
|
|
147
|
+
const key = msgKey(x);
|
|
148
|
+
const act = opts.canReply?.() === false ? "" : `<div data-trust="thread-control" class="msg-actions"><button type="button" class="chip-btn icon-only" data-act="reply" data-arg="${escAttr(key)}" title="${escAttr(tr("chat.reply"))}" aria-label="${escAttr(tr("chat.reply"))}">${REPLY}</button></div>`;
|
|
149
|
+
return `<div class="msg ${u ? "user" : "agent"}" data-key="${escAttr(key)}" tabindex="-1">${act}<div class="meta"><span class="sender">${escAttr(x.sender)}</span>${time}${ticks}</div>${quoteHtml(x.replyTo)}<div class="body">${clicked ? clickHtml(x.click) : `<div class="md">${renderedMarkdown(x.text, x.role === "agent", opts.emojis, opts.mentions)}</div>`}${R().attachmentsHtml(x.attachments, { htmlCards: x.role === "agent", goneTitle: tr("chat.attGone"), goneLabel: tr("chat.attUnavailable"), inlinePreviews: !PUBLIC_LINK() })}${buttons}</div>${R().reactionsHtml(x.reactions, tr("chat.reactedBy", x.instance || ""))}${tools}</div>`;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* A message this page is sending (chat-store.js): its own bubble at once, dimmed with "Sending…" until the server
|
|
153
|
+
* takes it, then as sent until the server's copy replaces it; failed: marked, with Retry and Delete. Each file shows
|
|
154
|
+
* its upload — a picture as itself (a local preview), anything else by name — with its own bar, moved in place by
|
|
155
|
+
* progress() (the html does not hold the numbers, so a moving bar never redraws the bubble). No data-key: it is no
|
|
156
|
+
* message yet (nothing replies to it, links to it or copies it).
|
|
157
|
+
*/
|
|
158
|
+
function outgoingHtml(x) {
|
|
159
|
+
const st = x.outgoing.state, going = st === "queued" || st === "sending";
|
|
160
|
+
const files = (x.files || []).map((f, i) => {
|
|
161
|
+
const pic = f.url ? `<img class="out-pic" src="${escAttr(f.url)}" alt="${escAttr(f.name)}">` : `<span class="out-doc" aria-hidden="true"></span>`;
|
|
162
|
+
return `<div class="out-file" data-i="${escAttr(i)}">${pic}<div class="out-file-info"><span class="out-name">${escAttr(f.name)}</span>`
|
|
163
|
+
+ `<span class="out-bar" role="progressbar" aria-label="${escAttr(trf("chat.uploadingFile", f.name))}" aria-valuemin="0" aria-valuemax="100"><span class="out-fill"></span></span>`
|
|
164
|
+
+ `<span class="out-pct"></span></div></div>`;
|
|
165
|
+
}).join("");
|
|
166
|
+
const failed = st === "failed" ? `<div data-trust="thread-control" class="out-note lbar" role="alert"><span class="out-error">${escAttr(trf("chat.notSentBecause", x.outgoing.error || ""))}</span>`
|
|
167
|
+
+ `<span class="out-actions"><button type="button" class="btn btn-sm btn-primary" data-act="retryOut" data-arg="${escAttr(x.clientId)}">${escAttr(tr("chat.retrySend"))}</button>`
|
|
168
|
+
+ `<button type="button" class="btn btn-sm" data-act="putBackOut" data-arg="${escAttr(x.clientId)}">${escAttr(tr("chat.putBack"))}</button>`
|
|
169
|
+
+ `<button type="button" class="btn btn-sm" data-act="deleteOut" data-arg="${escAttr(x.clientId)}">${escAttr(tr("chat.deleteUnsent"))}</button></span></div>` : "";
|
|
170
|
+
const state = going ? `<span class="out-state" role="status"><span class="out-spin" aria-hidden="true"></span>${escAttr(tr("chat.sending"))}</span>` : "";
|
|
171
|
+
return `<div class="msg user out out-${st}" data-out="${escAttr(x.clientId)}"${going ? ' aria-busy="true"' : ""} tabindex="-1"><div class="meta"><span class="sender">${escAttr(x.sender)}</span>${state}</div>`
|
|
172
|
+
+ `${quoteHtml(x.replyTo)}<div class="body">${x.text ? `<div class="md">${renderedMarkdown(x.text, false, opts.emojis, opts.mentions)}</div>` : ""}`
|
|
173
|
+
+ `${files ? `<div class="out-files">${files}</div>` : ""}</div>${failed}</div>`;
|
|
174
|
+
}
|
|
175
|
+
/** The pending bubbles' upload bars and percentages, as their files stand now (in place: CSSOM, no redraw). */
|
|
176
|
+
function progress() {
|
|
177
|
+
for (const v of nodes.values()) {
|
|
178
|
+
const x = v.x;
|
|
179
|
+
if (!x || !x.outgoing || !x.files || !x.files.length) continue;
|
|
180
|
+
for (const el of v.node.querySelectorAll(".out-file[data-i]")) {
|
|
181
|
+
const f = x.files[Number(el.dataset.i)];
|
|
182
|
+
if (!f) continue;
|
|
183
|
+
const pct = f.state === "done" ? 100 : f.total > 0 ? Math.min(100, Math.floor((f.loaded / f.total) * 100)) : 0;
|
|
184
|
+
el.dataset.state = f.state;
|
|
185
|
+
const bar = el.querySelector(".out-bar"), fill = el.querySelector(".out-fill"), label = el.querySelector(".out-pct");
|
|
186
|
+
if (bar) bar.setAttribute("aria-valuenow", String(pct));
|
|
187
|
+
if (fill) fill.style.transform = `scaleX(${pct / 100})`;
|
|
188
|
+
if (label) { const text = f.state === "failed" ? tr("chat.uploadFailed") : f.state === "waiting" ? tr("chat.uploadWaiting") : `${pct}%`; if (label.textContent !== text) label.textContent = text; }
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* #2272: what a reply quotes, above its body — the quoted sender and first words (or that it had files), as the server
|
|
195
|
+
* read them when it was sent; a button that shows that message. A guest that may not see it gets only "an earlier
|
|
196
|
+
* message". Text only: everything is escaped.
|
|
197
|
+
*/
|
|
198
|
+
function quoteHtml(q) {
|
|
199
|
+
if (!q || typeof q !== "object" || typeof q.boot !== "string" || typeof q.id !== "number") return "";
|
|
200
|
+
const words = q.hidden ? tr("chat.replyHidden")
|
|
201
|
+
: (typeof q.text === "string" && q.text) || (q.media === "photo" ? tr("chat.replyPhoto") : q.media === "document" ? tr("chat.replyFile") : "");
|
|
202
|
+
const who = !q.hidden && typeof q.sender === "string" && q.sender ? `<span class="quote-sender">${escAttr(q.sender)}</span> ` : "";
|
|
203
|
+
return `<button type="button" data-trust="thread-control" class="msg-quote" data-act="jumpQuote" data-arg="${escAttr(`${q.boot}-${q.id}`)}" title="${escAttr(tr("chat.replyJump"))}"><span class="quote-mark">${REPLY}</span> ${who}<span class="quote-text">${escAttr(words)}</span></button>`;
|
|
145
204
|
}
|
|
146
205
|
/**
|
|
147
206
|
* A button click as a chip: 🔘 and the label (escaped: the label is the agent's text). With `of` (live, while its
|
|
@@ -170,7 +229,8 @@ export function createThread(list, scroller, opts) {
|
|
|
170
229
|
}
|
|
171
230
|
function armTrials() {
|
|
172
231
|
if (trialTimer !== null) clearTimeout(trialTimer); trialTimer = null;
|
|
173
|
-
|
|
232
|
+
if (!canvasWorkerEnabled()) return;
|
|
233
|
+
const now = trialNow(), next = msgs.map(x => readCanvasTrialMessage(x)).filter(x => x && x.expiresAt > now).reduce((n, x) => Math.min(n, x.expiresAt), Infinity);
|
|
174
234
|
if (Number.isFinite(next)) trialTimer = setTimeout(() => { trialTimer = null; render(msgs); }, Math.max(1, Math.min(2147483647, next - now)));
|
|
175
235
|
}
|
|
176
236
|
/**
|
|
@@ -526,7 +586,20 @@ export function createThread(list, scroller, opts) {
|
|
|
526
586
|
// newest bubble clipped behind it, and the next growth past 48 px put the pill over it.
|
|
527
587
|
const atBottom = () => R().isNearBottom(scroller.scrollTop, scroller.clientHeight, scroller.scrollHeight, 1);
|
|
528
588
|
function reportJump() { opts.onJump({ show: !nearBottom(), unseen }); }
|
|
529
|
-
function toBottom() { scroller.scrollTop = scroller.scrollHeight; pinned = true; mark(); }
|
|
589
|
+
function toBottom() { snap(); scroller.scrollTop = scroller.scrollHeight; pinned = true; mark(); }
|
|
590
|
+
/**
|
|
591
|
+
* #2184: a thread's height is rarely a whole number of pixels, and a pinned view's offset is: so each time older messages
|
|
592
|
+
* were drawn above, the whole view moved by the change in that fraction (0.6–0.7 px — the faint jitter of a chat
|
|
593
|
+
* opened cold). A sub-pixel margin above the list keeps the thread's height whole, so the bottom never moves.
|
|
594
|
+
*/
|
|
595
|
+
// #2188: one read (the list's box excludes its own margin, so nothing is reset first) and a write only on a change —
|
|
596
|
+
// a reset-then-measure laid a 200-message thread out twice on every pinned draw (2.3 s at 4× CPU on a kept chat).
|
|
597
|
+
let snapped = null;
|
|
598
|
+
function snap() {
|
|
599
|
+
const h = list.getBoundingClientRect().height, f = h - Math.floor(h);
|
|
600
|
+
const want = f > 0.001 && f < 0.999 ? (1 - f) + "px" : "0px";
|
|
601
|
+
if (want !== snapped) { snapped = want; list.style.setProperty("--thread-snap", want); }
|
|
602
|
+
}
|
|
530
603
|
// Sizes change without a scroll event (layout after the render, the dock under the thread): while pinned, the view
|
|
531
604
|
// stays flush with the bottom; a reader who scrolled up is never moved.
|
|
532
605
|
const resized = () => { if (pinned && !atBottom()) toBottom(); reportJump(); };
|
|
@@ -620,7 +693,11 @@ export function createThread(list, scroller, opts) {
|
|
|
620
693
|
}
|
|
621
694
|
/** Put the messages from startIndex() on in the list (nodes reused when unchanged). Returns how many are new. */
|
|
622
695
|
function draw(drawOpts) {
|
|
623
|
-
const shown = msgs.slice(startIndex())
|
|
696
|
+
const shown = msgs.slice(startIndex()).filter(message => {
|
|
697
|
+
// Volatile host offer records are hidden off and while their on-only parser is loading.
|
|
698
|
+
const hostOffer = message?.role === "status" && message.sender === "agend" && Object.hasOwn(message, "effectTrial") && message.effectTrial != null;
|
|
699
|
+
return !hostOffer || canvasWorkerEnabled() && readCanvasTrialMessage(message) !== undefined;
|
|
700
|
+
});
|
|
624
701
|
const keep = new Set(shown.map(msgKey));
|
|
625
702
|
for (const [k, v] of nodes) if (!keep.has(k)) { stopIn(v.node); v.node.remove(); nodes.delete(k); }
|
|
626
703
|
let prev = null, added = 0;
|
|
@@ -643,8 +720,21 @@ export function createThread(list, scroller, opts) {
|
|
|
643
720
|
}
|
|
644
721
|
armDay();
|
|
645
722
|
armPolls();
|
|
723
|
+
rove();
|
|
724
|
+
progress();
|
|
646
725
|
return added;
|
|
647
726
|
}
|
|
727
|
+
/**
|
|
728
|
+
* #2272 (review): one message in the thread is in the Tab order — the last one focused while it is still drawn, else
|
|
729
|
+
* the newest; ↑/↓ move between messages (chat-msg-actions.js). The rest are -1, so Tab passes the thread in one step.
|
|
730
|
+
*/
|
|
731
|
+
let roving = null;
|
|
732
|
+
function rove(key) {
|
|
733
|
+
if (key !== undefined) roving = key;
|
|
734
|
+
const at = (roving && nodes.has(roving) ? nodes.get(roving).node : null) || [...list.querySelectorAll(".msg[data-key]")].at(-1) || null;
|
|
735
|
+
for (const el of list.querySelectorAll('.msg[data-key][tabindex="0"]')) if (el !== at) el.setAttribute("tabindex", "-1");
|
|
736
|
+
if (at) at.setAttribute("tabindex", "0");
|
|
737
|
+
}
|
|
648
738
|
|
|
649
739
|
function onScroll() {
|
|
650
740
|
// #2158: the thread got shorter under a pinned view (text settling on a cold load, a card) and the browser clamped
|
|
@@ -723,13 +813,30 @@ export function createThread(list, scroller, opts) {
|
|
|
723
813
|
if (m && opts.clickReplyButton) opts.clickReplyButton(m[1], Number(m[2]));
|
|
724
814
|
} else if (act === "effectTrial") {
|
|
725
815
|
// Only the current host-produced keyed card and a real local click can request admission. No token is read from DOM.
|
|
726
|
-
const key = el.dataset.arg, row = msgs.find(x => msgKey(x) === key), owner = nodes.get(key), node = owner?.node, offer =
|
|
816
|
+
const key = el.dataset.arg, row = msgs.find(x => msgKey(x) === key), owner = nodes.get(key), node = owner?.node, offer = readCanvasTrialMessage(row);
|
|
727
817
|
if (PUBLIC_LINK() || e.defaultPrevented || e.isTrusted !== true || owner?.trialButton !== el || el.className !== "btn btn-sm effect-trial-start" || !node?.contains(el) || el.closest(".effect-trial-offer")?.getAttribute("data-trust") !== "thread-control"
|
|
728
818
|
|| !offer || trialNow() >= offer.expiresAt) return;
|
|
729
819
|
if (trialStatus(row) === "ready" && opts.canTryEffect?.(row) === true) opts.startEffectTrial?.(row);
|
|
730
820
|
else opts.fixEffectTrial?.(row, trialStatus(row));
|
|
731
821
|
} else if (act === "showButtons") { const x = msgs.find(y => y.buttons && y.buttons.id === el.dataset.arg); if (x) reveal(msgKey(x)); }
|
|
822
|
+
else if (act === "reply") { const x = msgs.find(y => msgKey(y) === el.dataset.arg); if (x) opts.startReply?.(x); }
|
|
823
|
+
else if (act === "jumpQuote") void jumpTo(el.dataset.arg);
|
|
824
|
+
else if (act === "retryOut") opts.retryOutgoing?.(el.dataset.arg); // a failed send, again
|
|
825
|
+
else if (act === "putBackOut") opts.putBackOutgoing?.(el.dataset.arg); // back in the composer, to change it
|
|
826
|
+
else if (act === "deleteOut") opts.deleteOutgoing?.(el.dataset.arg);
|
|
732
827
|
}
|
|
828
|
+
/**
|
|
829
|
+
* #2272: show the message a reply quotes, flashed — drawn now, or after the chat reads back the longest history the
|
|
830
|
+
* server keeps; otherwise it says it is no longer there.
|
|
831
|
+
*/
|
|
832
|
+
async function jumpTo(key) {
|
|
833
|
+
if (typeof key !== "string" || !key) return;
|
|
834
|
+
if (reveal(key)) return;
|
|
835
|
+
const found = opts.findQuoted ? await opts.findQuoted(key) : false;
|
|
836
|
+
if (!found || !reveal(key)) opts.notice?.(tr("chat.replyGone"));
|
|
837
|
+
}
|
|
838
|
+
/** #2272: a drawn message's row (for the message menu and gestures), or undefined. */
|
|
839
|
+
function messageOf(key) { return msgs.find(y => msgKey(y) === key); }
|
|
733
840
|
|
|
734
841
|
/** The thread goes (the chat left, or another instance opened): every preview in it stops first. */
|
|
735
842
|
/**
|
|
@@ -761,8 +868,10 @@ export function createThread(list, scroller, opts) {
|
|
|
761
868
|
if (ro) { ro.observe(list); ro.observe(sc); }
|
|
762
869
|
}
|
|
763
870
|
/** `own`: only this thread's previews stop (a thread let go while another chat is in view); else every one, as leaving. */
|
|
871
|
+
const redrawFeature = () => { if (!disposed && !parked) render(msgs); };
|
|
872
|
+
const featureOff = onCanvasWorkerChange(redrawFeature), metadataOff = onCanvasMetadataChange(redrawFeature);
|
|
764
873
|
function dispose(own = false) {
|
|
765
|
-
disposed = true;
|
|
874
|
+
disposed = true; featureOff(); metadataOff();
|
|
766
875
|
if (!parked) watchReader(scroller, false);
|
|
767
876
|
if (trialTimer !== null) clearTimeout(trialTimer); trialTimer = null;
|
|
768
877
|
if (ro) ro.disconnect();
|
|
@@ -772,5 +881,5 @@ export function createThread(list, scroller, opts) {
|
|
|
772
881
|
armPolls();
|
|
773
882
|
}
|
|
774
883
|
|
|
775
|
-
return { render, onScroll, onClick, jumpLatest, reveal, refreshCards, park, attach, dispose, nodes, get unseen() { return unseen; } };
|
|
884
|
+
return { render, progress, onScroll, onClick, jumpLatest, reveal, jumpTo, messageOf, rove, refreshCards, park, attach, dispose, nodes, get unseen() { return unseen; } };
|
|
776
885
|
}
|
|
@@ -1,31 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const FORBIDDEN = /(?!\u200d)[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u;
|
|
4
|
-
const VISIBLE = /[^\p{M}\p{C}\p{Z}\u115f\u1160\u3164\uffa0\u2800]/u;
|
|
5
|
-
let graphemes = null;
|
|
6
|
-
export function checkEffectTrialOffer(value) {
|
|
7
|
-
try {
|
|
8
|
-
if (!value || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) return null;
|
|
9
|
-
const keys = Reflect.ownKeys(value);
|
|
10
|
-
if (keys.length !== KEYS.length || keys.some(k => typeof k !== "string" || !KEYS.includes(k))) return null;
|
|
11
|
-
const x = Object.create(null);
|
|
12
|
-
for (const key of KEYS) {
|
|
13
|
-
const d = Object.getOwnPropertyDescriptor(value, key);
|
|
14
|
-
if (!d || !("value" in d) || !d.enumerable) return null;
|
|
15
|
-
x[key] = d.value;
|
|
16
|
-
}
|
|
17
|
-
if (x.v !== 1 || typeof x.offer !== "string" || !ID.test(x.offer) || typeof x.id !== "string" || !ID.test(x.id)
|
|
18
|
-
|| typeof x.title !== "string" || x.title.length > 400 || x.title.normalize("NFC") !== x.title || x.title.trim() !== x.title
|
|
19
|
-
|| FORBIDDEN.test(x.title) || !VISIBLE.test(x.title) || !Number.isSafeInteger(x.expiresAt) || x.expiresAt < 0) return null;
|
|
20
|
-
graphemes ??= new Intl.Segmenter(undefined, { granularity: "grapheme" });
|
|
21
|
-
let count = 0; for (const _part of graphemes.segment(x.title)) if (++count > 40) return null;
|
|
22
|
-
if (count < 1) return null;
|
|
23
|
-
return Object.freeze({ v: 1, offer: x.offer, id: x.id, title: x.title, expiresAt: x.expiresAt });
|
|
24
|
-
} catch { return null; }
|
|
25
|
-
}
|
|
26
|
-
/** Role and sender are host fields, never inferred from a message's text. Start must separately authorize. */
|
|
27
|
-
export function effectTrialMessage(message) {
|
|
28
|
-
if (!message || message.role !== "status" || message.sender !== "agend" || typeof message.instance !== "string"
|
|
29
|
-
|| message.instance.length < 1 || message.instance.length > 128) return null;
|
|
30
|
-
return checkEffectTrialOffer(message.effectTrial);
|
|
31
|
-
}
|
|
1
|
+
// On-only Canvas Worker display validation; ordinary chat boot imports no parser.
|
|
2
|
+
export { checkEffectTrialOffer, effectTrialMessage } from "/assets/effect-display-metadata.js";
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
// #1918: the org canvas's layout (fleet-canvas.js draws it; fleet-traffic.js routes lines through its empty lanes).
|
|
2
2
|
// Fixed slots, no layout engine: the same structure always gives the same picture.
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Sizes in canvas units. NW×NH a member card, LW×LH a General card; FOLDED a folded (or empty) team's height. GAP and
|
|
6
|
+
* PAD (#2182): the gutters between cards and a box's padding are the traffic lines' channels inside a box — wide
|
|
7
|
+
* enough that the router (fleet-route-scene.js) keeps a few lines apart in each; a phone's narrow packing keeps the
|
|
8
|
+
* tighter GAP_NARROW and PAD_NARROW, so General and the first team still open at a readable size. A layout says which
|
|
9
|
+
* it used (L.gap, L.pad).
|
|
10
|
+
*/
|
|
11
|
+
export const OC = { NW: 184, NH: 56, GAP: 28, PAD: 32, GAP_NARROW: 18, PAD_NARROW: 24, HEAD: 34, TEAM_GAP: 72, ROW_GAP: 96, ROW_MAX: 1400, ROW_MAX_NARROW: 460, LW: 232, LH: 68, TOP_Y: 20, BUS: 44, FOLDED: 64, TRUNK: -30 };
|
|
6
12
|
const colsFor = (n, narrow) => (n <= 1 ? 1 : n <= 4 || narrow ? 2 : 3);
|
|
13
|
+
/** A search's needle, and whether a node matches it (its name or nickname): the canvas's Find, the Office view's too. */
|
|
14
|
+
export const needle = (q) => String(q || "").trim().toLowerCase();
|
|
15
|
+
export const hits = (node, q) => !!q && (node.name.toLowerCase().includes(q) || (!!node.i && typeof node.i.display_name === "string" && node.i.display_name.toLowerCase().includes(q)));
|
|
7
16
|
/** The key a team folds by (per device): its name; the instances in no team have one of their own no team name can be. */
|
|
8
17
|
export const REST_KEY = "\u0000rest";
|
|
9
18
|
|
|
@@ -13,7 +22,7 @@ export const REST_KEY = "\u0000rest";
|
|
|
13
22
|
* size of the whole. `narrow`: a phone's packing.
|
|
14
23
|
*/
|
|
15
24
|
export function canvasLayout(view, folded = new Set(), { narrow = false, label = (s, n) => `${n} ${s}` } = {}) {
|
|
16
|
-
const { NW, NH, GAP, PAD
|
|
25
|
+
const { NW, NH, HEAD } = OC, GAP = narrow ? OC.GAP_NARROW : OC.GAP, PAD = narrow ? OC.PAD_NARROW : OC.PAD;
|
|
17
26
|
const groups = [...view.teams.map((tm) => ({ key: tm.name, name: tm.name, loose: false, nodes: tm.nodes, counts: tm.counts })),
|
|
18
27
|
...(view.rest.nodes.length ? [{ key: REST_KEY, name: null, loose: true, nodes: view.rest.nodes, counts: view.rest.counts }] : [])];
|
|
19
28
|
const rows = [];
|
|
@@ -49,7 +58,7 @@ export function canvasLayout(view, folded = new Set(), { narrow = false, label =
|
|
|
49
58
|
const width = Math.max(rowsW, topW);
|
|
50
59
|
const tops = view.top.map((node, i) => ({ node, key: `\u0000top/${node.name}`, x: width / 2 - topW / 2 + i * (OC.LW + GAP), y: OC.TOP_Y, w: OC.LW, h: OC.LH }));
|
|
51
60
|
const height = boxes.length ? y - OC.ROW_GAP : tops.length ? OC.TOP_Y + OC.LH : 0;
|
|
52
|
-
return { tops, boxes, width, height, tree: treeLines(tops, boxes) };
|
|
61
|
+
return { tops, boxes, width, height, tree: treeLines(tops, boxes), gap: GAP, pad: PAD };
|
|
53
62
|
}
|
|
54
63
|
|
|
55
64
|
/** A folded team's summary line height, and a label's width estimate (canvas units: wide for CJK, narrow otherwise). */
|
package/dist/ui/fleet-canvas.js
CHANGED
|
@@ -8,13 +8,16 @@
|
|
|
8
8
|
// a team or searching never moves another one. Tree lines: a stem from General, a bus over each row, a trunk at the
|
|
9
9
|
// left joining the rows, one drop per team — never a line per member (the box says who is in it). A phone packs
|
|
10
10
|
// narrower (one team a row, at most two columns), so General and the first team open readable.
|
|
11
|
-
// - Per device (localStorage; blocked storage: this page only): Canvas
|
|
12
|
-
// itself is not kept: it opens on General and the first row
|
|
13
|
-
// panel allows (no larger than life), on a phone no smaller
|
|
11
|
+
// - Per device (localStorage; blocked storage: this page only): Canvas, List or Office (fleet-office.js: the same fleet
|
|
12
|
+
// as a pixel office), and which teams are folded. The view itself is not kept: it opens on General and the first row
|
|
13
|
+
// (#1918's user decision 2) — on a desktop as wide as the panel allows (no larger than life), on a phone no smaller
|
|
14
|
+
// than readable. 0 / Fit shows the whole fleet.
|
|
14
15
|
// - Presentation only, like the list: a card opens that instance's chat; nothing is edited here (#1689 is how teams
|
|
15
16
|
// change). The live state is the app store's (fleet-org.js buildOrgView), so the canvas moves with the stream.
|
|
16
17
|
// - Live traffic (fleet-traffic.js): the messages between instances, drawn between the team boxes and the cards (never
|
|
17
18
|
// hidden under a box, never across a name). Live on or off per device; the list says it in words ("Sending: …").
|
|
19
|
+
// #2182: routed around the cards and through the boxes' doors by libavoid in a worker (fleet-route-scene.js), each
|
|
20
|
+
// line from card to card; the lanes are the fallback.
|
|
18
21
|
import { html, useEffect, useLayoutEffect, useMemo, useRef, useState } from "/assets/app-html.js";
|
|
19
22
|
import { appStore } from "/assets/app-store.js";
|
|
20
23
|
import { t, register } from "/assets/app-i18n.js";
|
|
@@ -22,15 +25,18 @@ import { chatPath } from "/assets/app-route.js";
|
|
|
22
25
|
import { navigate } from "/assets/app-nav.js";
|
|
23
26
|
import { Empty, Skeleton } from "/assets/ui-states.js";
|
|
24
27
|
import { Icon } from "/assets/ui-icons.js";
|
|
25
|
-
import { avatarOf,
|
|
28
|
+
import { avatarOf, firstCharacter, namesOf } from "/assets/instance-nav.js";
|
|
26
29
|
import { identityClasses, identityOf, paintIdentity, useIdentityColors } from "/assets/identity-color.js";
|
|
27
|
-
import { buildOrgView, OrgChart, OrgSummary } from "./fleet-org.js";
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
+
import { buildOrgView, nodeText, OrgChart, OrgSummary } from "./fleet-org.js";
|
|
31
|
+
import { Office } from "./fleet-office.js";
|
|
32
|
+
import { OC, REST_KEY, SUM_LINE, canvasLayout, hits, needle, openingRegion, summaryRows } from "./fleet-canvas-layout.js";
|
|
33
|
+
import { createTrafficStore, FAR_K, HEAD, POLL_MS, sendingBy, trafficEdges } from "./fleet-traffic.js";
|
|
34
|
+
import { routeScene } from "./fleet-route-scene.js";
|
|
35
|
+
import { createRouteClient } from "./fleet-route.js";
|
|
30
36
|
|
|
31
37
|
register("orgc", {
|
|
32
38
|
en: {
|
|
33
|
-
view: "View", canvas: "Canvas", list: "List", find: "Find an instance", findShort: "Find", found: "{0} found", foundOne: "1 found", noMatch: "No match",
|
|
39
|
+
view: "View", canvas: "Canvas", list: "List", office: "Office", find: "Find an instance", findShort: "Find", found: "{0} found", foundOne: "1 found", noMatch: "No match",
|
|
34
40
|
zoomIn: "Zoom in", zoomOut: "Zoom out", fit: "Fit to screen",
|
|
35
41
|
label: "Org chart canvas. Tab or the arrow keys move between instances, Enter opens a chat, + and − zoom, 0 fits the fleet.",
|
|
36
42
|
expand: "Expand", collapse: "Collapse", members: "{0} members", member: "1 member", inFolded: "{0} found · expand", noMembers: "No members",
|
|
@@ -40,7 +46,7 @@ register("orgc", {
|
|
|
40
46
|
lgWork: "in progress (until its report)", lgReturn: "done (report back)", lgStale: "no report yet",
|
|
41
47
|
},
|
|
42
48
|
"zh-TW": {
|
|
43
|
-
view: "檢視", canvas: "畫布", list: "清單", find: "尋找 instance", findShort: "尋找", found: "找到 {0} 個", foundOne: "找到 1 個", noMatch: "沒有符合的",
|
|
49
|
+
view: "檢視", canvas: "畫布", list: "清單", office: "辦公室", find: "尋找 instance", findShort: "尋找", found: "找到 {0} 個", foundOne: "找到 1 個", noMatch: "沒有符合的",
|
|
44
50
|
zoomIn: "放大", zoomOut: "縮小", fit: "符合畫面",
|
|
45
51
|
label: "組織圖畫布。用 Tab 或方向鍵在 instance 之間移動,Enter 開啟聊天,+ 和 − 縮放,0 顯示整個 fleet。",
|
|
46
52
|
expand: "展開", collapse: "收合", members: "{0} 名成員", member: "1 名成員", inFolded: "找到 {0} 個 · 展開", noMembers: "沒有成員",
|
|
@@ -86,7 +92,8 @@ export function zoomAt(v, f, cx, cy) {
|
|
|
86
92
|
// ── Per device ──
|
|
87
93
|
|
|
88
94
|
const MODE_KEY = "agend_org_mode", FOLD_KEY = "agend_org_folded", LIVE_KEY = "agend_org_live", KEY_KEY = "agend_org_key";
|
|
89
|
-
|
|
95
|
+
const MODES = ["canvas", "list", "office"];
|
|
96
|
+
function readMode() { try { const m = localStorage.getItem(MODE_KEY); return MODES.includes(m) ? m : "canvas"; } catch { return "canvas"; } }
|
|
90
97
|
function readLive() { try { return localStorage.getItem(LIVE_KEY) !== "0"; } catch { return true; } }
|
|
91
98
|
function readFolded() {
|
|
92
99
|
try { const a = JSON.parse(localStorage.getItem(FOLD_KEY) || "[]"); return new Set(Array.isArray(a) ? a.filter((x) => typeof x === "string").slice(0, 500) : []); } catch { return new Set(); }
|
|
@@ -114,8 +121,6 @@ export function clipText(s, n) {
|
|
|
114
121
|
return `${out}…`;
|
|
115
122
|
}
|
|
116
123
|
const clip = clipText;
|
|
117
|
-
const needle = (q) => String(q || "").trim().toLowerCase();
|
|
118
|
-
const hits = (node, q) => !!q && (node.name.toLowerCase().includes(q) || (!!node.i && typeof node.i.display_name === "string" && node.i.display_name.toLowerCase().includes(q)));
|
|
119
124
|
|
|
120
125
|
function Face({ it, name, cx, cy, r }) {
|
|
121
126
|
const a = it ? avatarOf(it) : { kind: "initial", text: firstCharacter(name) };
|
|
@@ -132,10 +137,8 @@ function Face({ it, name, cx, cy, r }) {
|
|
|
132
137
|
|
|
133
138
|
function Card({ c, lead, cls, onOpen }) {
|
|
134
139
|
const n = c.node, it = n.i;
|
|
135
|
-
const
|
|
140
|
+
const { primary, sub, full } = nodeText(n);
|
|
136
141
|
const id = it ? identityOf(it) : null;
|
|
137
|
-
const sub = it ? `${STATE_LABEL(n.state)} · ${backendLabel(it.backend)}` : STATE_LABEL(n.state);
|
|
138
|
-
const full = `${names.primary}${names.secondary ? ` (${names.secondary})` : ""} — ${sub}`;
|
|
139
142
|
const cy = c.h / 2;
|
|
140
143
|
return html`<g class=${`oc-node st-${n.state}${lead ? " lead" : ""}${cls ? ` ${cls}` : ""} ${identityClasses(id)}`} ref=${(el) => paintIdentity(el, id)}
|
|
141
144
|
transform=${`translate(${c.x} ${c.y})`} data-name=${n.name} data-key=${c.key} tabindex="0" role=${it ? "link" : "img"}
|
|
@@ -145,7 +148,7 @@ function Card({ c, lead, cls, onOpen }) {
|
|
|
145
148
|
<rect class="oc-idbar" x="0" y="8" width="4" height=${c.h - 16} rx="2" />
|
|
146
149
|
<${Face} it=${it} name=${n.name} cx=${26} cy=${cy} r=${16} />
|
|
147
150
|
<circle class=${`oc-dot st-${n.state}`} cx=${38} cy=${cy + 12} r=${5} />
|
|
148
|
-
<text class="oc-name" x=${50} y=${cy - 4}>${clip(
|
|
151
|
+
<text class="oc-name" x=${50} y=${cy - 4}>${clip(primary, lead ? 20 : 15)}</text>
|
|
149
152
|
<text class="oc-sub" x=${50} y=${cy + 13}><tspan class=${`oc-st st-${n.state}`}>${clip(sub, lead ? 27 : 20)}</tspan></text>
|
|
150
153
|
</g>`;
|
|
151
154
|
}
|
|
@@ -186,6 +189,9 @@ function TeamHead({ b, q, onFold }) {
|
|
|
186
189
|
</g>`;
|
|
187
190
|
}
|
|
188
191
|
|
|
192
|
+
/** What a card (or an Office desk) opens: that instance's chat. */
|
|
193
|
+
const openChat = (name) => navigate(chatPath(name));
|
|
194
|
+
|
|
189
195
|
/** Every card, in the order Tab walks them (General, then each team's members in reading order). */
|
|
190
196
|
const cardsOf = (L) => [...L.tops, ...L.boxes.flatMap((b) => b.cells)];
|
|
191
197
|
|
|
@@ -201,9 +207,10 @@ function TrafficLayer({ edges, q }) {
|
|
|
201
207
|
const still = reducedMotion();
|
|
202
208
|
return html`<g class="oc-flows" aria-hidden="true">${edges.map((e) => {
|
|
203
209
|
const dim = q && !e.names.some((n) => n.toLowerCase().includes(q));
|
|
204
|
-
return html`<g key=${e.key} class=${`oc-fl${dim ? " dim" : ""}`}>
|
|
210
|
+
return html`<g key=${e.key} class=${`oc-fl${dim ? " dim" : ""}`} data-routed=${e.routed ? "1" : undefined}>
|
|
205
211
|
<path class="oc-flow-halo" d=${e.d} />
|
|
206
|
-
<path class=${`oc-flow h-${e.hue} ph-${e.phase}`} d=${e.d}
|
|
212
|
+
<path class=${`oc-flow h-${e.hue} ph-${e.phase}`} d=${e.d} stroke-width=${e.w} marker-start=${`url(#oc-src-${MARKER(e)})`}
|
|
213
|
+
marker-end=${e.head ? `url(#oc-ah-${MARKER(e)})` : undefined} />
|
|
207
214
|
${e.phase === "live" && !still ? html`<circle class=${`oc-pulse h-${e.hue}`} r="4"><animateMotion dur=${`${Math.max(1.6, e.pts.length * 0.3)}s`} repeatCount="indefinite" path=${e.d} /></circle>` : null}
|
|
208
215
|
${e.phase === "return" && !still ? html`<circle class=${`oc-pulse h-${e.hue}`} r="5"><animateMotion dur="1.6s" repeatCount="1" fill="freeze" path=${e.d} /></circle>` : null}
|
|
209
216
|
${e.badge ? html`<g class="oc-badge" transform=${`translate(${e.badge.x - 14} ${e.badge.y - 10})`}><rect width="28" height="20" rx="10" /><text x="14" y="14" text-anchor="middle">${`×${e.n}`}</text></g>` : null}
|
|
@@ -211,6 +218,13 @@ function TrafficLayer({ edges, q }) {
|
|
|
211
218
|
})}</g>`;
|
|
212
219
|
}
|
|
213
220
|
const ARROWS = ["task", "send", "report", "broadcast", "team", "fading"];
|
|
221
|
+
/**
|
|
222
|
+
* The head (#2329), in a 10-unit box that is HEAD.LEN stroke widths each way: a slim swept triangle HEAD.WIDE across,
|
|
223
|
+
* its tip at x 10; the path ends HEAD.BACK stroke widths before the tip (refX), so the line's stroke ends inside it.
|
|
224
|
+
*/
|
|
225
|
+
const HEAD_HALF = (5 * HEAD.WIDE) / HEAD.LEN;
|
|
226
|
+
const HEAD_D = `M0 ${5 - HEAD_HALF} L10 5 L0 ${5 + HEAD_HALF} L2.5 5 z`;
|
|
227
|
+
const HEAD_REF_X = 10 - (10 * HEAD.BACK) / HEAD.LEN;
|
|
214
228
|
|
|
215
229
|
/**
|
|
216
230
|
* The key to the lines (#2052): a **Key** toggle in the toolbar; open, its rows are a strip between the toolbar and the
|
|
@@ -269,6 +283,32 @@ function useTraffic(lease, on) {
|
|
|
269
283
|
return useMemo(() => (on ? store.items() : []), [rev, on]);
|
|
270
284
|
}
|
|
271
285
|
|
|
286
|
+
/**
|
|
287
|
+
* #2182: the traffic lines, routed around the canvas by libavoid in a worker (fleet-route.js) once it answers; until
|
|
288
|
+
* then, and zoomed out (one line per team pair), along the lanes (fleet-traffic.js route()). An answer is kept while the
|
|
289
|
+
* layout it was routed on is the one drawn: a line it has not seen yet takes its lane until the next answer.
|
|
290
|
+
*/
|
|
291
|
+
let routeClient = null;
|
|
292
|
+
function useTrafficRoutes(traffic, L, far) {
|
|
293
|
+
const lanes = useMemo(() => (traffic ? trafficEdges(traffic, L, { far }) : []), [traffic, L, far]);
|
|
294
|
+
const scene = useMemo(() => (far || !lanes.length ? null : routeScene(L, lanes)), [lanes, L, far]);
|
|
295
|
+
const [answer, setAnswer] = useState(null); // { shapes, map }
|
|
296
|
+
// The layout as the router sees it: a status frame re-making the same layout keeps the answer (and asks nothing).
|
|
297
|
+
const shapes = scene ? JSON.stringify(scene.shapes) : null;
|
|
298
|
+
const ask = scene && scene.conns.length ? JSON.stringify(scene) : null;
|
|
299
|
+
useEffect(() => {
|
|
300
|
+
if (!ask) return undefined;
|
|
301
|
+
routeClient ??= createRouteClient();
|
|
302
|
+
if (!routeClient.available) return undefined;
|
|
303
|
+
let live = true;
|
|
304
|
+
routeClient.route(JSON.parse(ask)).then((map) => { if (live && map) setAnswer({ shapes, map }); });
|
|
305
|
+
return () => { live = false; };
|
|
306
|
+
}, [ask]);
|
|
307
|
+
useEffect(() => () => { routeClient?.close(); routeClient = null; }, []);
|
|
308
|
+
return useMemo(() => (answer && answer.shapes === shapes && traffic ? trafficEdges(traffic, L, { far, routed: answer.map }) : lanes),
|
|
309
|
+
[lanes, answer, shapes, L, far, traffic]);
|
|
310
|
+
}
|
|
311
|
+
|
|
272
312
|
/** The canvas body: `view` buildOrgView's answer; `folded` the folded teams' keys; `q` the search needle; `traffic` the live items (null: Live is off). */
|
|
273
313
|
function Canvas({ view, folded, onFold, q, jump, traffic }) {
|
|
274
314
|
const [narrow] = useState(() => typeof matchMedia === "function" && matchMedia("(max-width: 640px)").matches);
|
|
@@ -308,7 +348,7 @@ function Canvas({ view, folded, onFold, q, jump, traffic }) {
|
|
|
308
348
|
vp.current = narrow ? fitView(openingRegion(L), size(), { margin: 12, minK: 0.75 }) : fitView(whole(), size(), { widthOnly: true, maxK: 1, minK: 0.6 });
|
|
309
349
|
setFar(vp.current.k < FAR_K);
|
|
310
350
|
}, []);
|
|
311
|
-
const edges =
|
|
351
|
+
const edges = useTrafficRoutes(traffic, L, far);
|
|
312
352
|
// Preact owns the markup, not the transform: put it back after every render.
|
|
313
353
|
useLayoutEffect(apply);
|
|
314
354
|
// A search's Enter: the first match, unfolded (by the panel) and then brought into view — once. It waits for the
|
|
@@ -323,7 +363,7 @@ function Canvas({ view, folded, onFold, q, jump, traffic }) {
|
|
|
323
363
|
if (!L.boxes.some((b) => b.folded && b.nodes.some((n) => n.name === j.name))) pendingJump.current = null; // gone: nothing to wait for
|
|
324
364
|
});
|
|
325
365
|
|
|
326
|
-
const open =
|
|
366
|
+
const open = openChat;
|
|
327
367
|
// The click that ends a drag or a pinch opens nothing and folds nothing.
|
|
328
368
|
const onClickCapture = (e) => { if (drag.current.swallow) { e.preventDefault(); e.stopPropagation(); } };
|
|
329
369
|
const onWheel = (e) => {
|
|
@@ -409,10 +449,10 @@ function Canvas({ view, folded, onFold, q, jump, traffic }) {
|
|
|
409
449
|
<svg ref=${svgRef} class="oc-svg" role="application" tabindex="0" aria-label=${tc("label")} onWheel=${onWheel} onPointerDown=${onPointerDown}
|
|
410
450
|
onPointerMove=${onPointerMove} onPointerUp=${onPointerUp} onPointerCancel=${onPointerUp} onKeyDown=${onKeyDown} onFocusIn=${onFocusIn} onClickCapture=${onClickCapture}>
|
|
411
451
|
<defs><clipPath id="oc-clip-av" clipPathUnits="objectBoundingBox"><circle cx="0.5" cy="0.5" r="0.5" /></clipPath>
|
|
412
|
-
${ARROWS.map((a) => html`<marker key=${a} id=${`oc-ah-${a}`} viewBox="0 0 10 10" refX
|
|
413
|
-
<path d
|
|
414
|
-
${ARROWS.map((a) => html`<marker key=${`s-${a}`} id=${`oc-src-${a}`} viewBox="0 0 10 10" refX="5" refY="5" markerWidth
|
|
415
|
-
<circle cx="5" cy="5" r="
|
|
452
|
+
${ARROWS.map((a) => html`<marker key=${a} id=${`oc-ah-${a}`} viewBox="0 0 10 10" refX=${HEAD_REF_X} refY="5" markerWidth=${HEAD.LEN} markerHeight=${HEAD.LEN} orient="auto">
|
|
453
|
+
<path d=${HEAD_D} class=${`oc-ah h-${a}`} /></marker>`)}
|
|
454
|
+
${ARROWS.map((a) => html`<marker key=${`s-${a}`} id=${`oc-src-${a}`} viewBox="0 0 10 10" refX="5" refY="5" markerWidth=${HEAD.DOT} markerHeight=${HEAD.DOT}>
|
|
455
|
+
<circle cx="5" cy="5" r="5" class=${`oc-ah h-${a}`} /></marker>`)}</defs>
|
|
416
456
|
<g ref=${worldRef} class="oc-world">
|
|
417
457
|
<g class="oc-tree">${L.tree.map((d, i) => html`<path key=${i} d=${d} />`)}</g>
|
|
418
458
|
<g class="oc-teams">${L.boxes.map((b) => html`<${TeamBox} key=${b.key} b=${b} q=${q} />`)}</g>
|
|
@@ -509,17 +549,18 @@ export function OrgCanvas({ org, app, lease }) {
|
|
|
509
549
|
<div class="list-head org-head oc-bar">
|
|
510
550
|
<span>${view.total === 1 ? t("org.instance") : t("org.instances", view.total)}</span><${OrgSummary} counts=${view.counts} />
|
|
511
551
|
<div class="oc-tools">
|
|
512
|
-
${mode
|
|
552
|
+
${mode !== "list" ? html`<label class="s-search oc-find"><${Icon} name="search" size=${14} /><span class="sr-only">${tc("find")}</span>
|
|
513
553
|
<input type="search" value=${query} placeholder=${tc("findShort")} autocomplete="off" onInput=${(e) => setQuery(e.target.value)} onKeyDown=${onFind} />
|
|
514
554
|
${q ? html`<span class="oc-found" role="status">${found ? (found === 1 ? tc("foundOne") : tc("found", found)) : tc("noMatch")}</span>` : null}</label>` : null}
|
|
515
|
-
${mode
|
|
555
|
+
${mode !== "list" && live ? html`<${KeyToggle} open=${keyOpen} onToggle=${toggleKey} />` : null}
|
|
516
556
|
<button type="button" class=${`btn btn-sm oc-live${live ? " on" : ""}`} aria-pressed=${live ? "true" : "false"} title=${live ? tc("liveOn") : tc("liveOff")}
|
|
517
557
|
onClick=${() => setLive((v) => !v)}><span class="oc-live-dot" aria-hidden="true"></span>${tc("live")}</button>
|
|
518
|
-
<div class="seg-inline" role="group" aria-label=${tc("view")}>${modeBtn("canvas")}${modeBtn("list")}</div>
|
|
558
|
+
<div class="seg-inline" role="group" aria-label=${tc("view")}>${modeBtn("canvas")}${modeBtn("list")}${modeBtn("office")}</div>
|
|
519
559
|
</div>
|
|
520
560
|
</div>
|
|
521
|
-
${mode
|
|
561
|
+
${mode !== "list" && live && keyOpen ? html`<${Legend} />` : null}
|
|
522
562
|
${mode === "list" ? html`<${OrgChart} org=${org} app=${app} bare=${true} sending=${sending} />`
|
|
563
|
+
: mode === "office" ? html`<${Office} view=${view} traffic=${live ? traffic : null} q=${q} lease=${lease} onOpen=${openChat} />`
|
|
523
564
|
: html`<${Canvas} view=${view} folded=${folded} onFold=${onFold} q=${q} jump=${jump} traffic=${live ? traffic : null} />`}
|
|
524
565
|
</div>`;
|
|
525
566
|
}
|