@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/fleet-traffic.js
CHANGED
|
@@ -3,8 +3,14 @@
|
|
|
3
3
|
// stream, every POLL_MS while the page is shown — the user's decision 1). Ids are opaque; there is never any text.
|
|
4
4
|
//
|
|
5
5
|
// - The store keeps each message's latest state: queued (a dotted line), delivering (a dash and a pulse), delivered
|
|
6
|
-
// (the line stays FADE_MS while it fades, then goes
|
|
7
|
-
// failed or
|
|
6
|
+
// or consumed (the line stays FADE_MS while it fades, then goes — long enough to see: an MCP send is delivered and
|
|
7
|
+
// read almost at once); failed, uncertain or cancelled ends it at once (a failed or uncertain delivery is Needs you's
|
|
8
|
+
// to show, #1386). A finished message never comes back.
|
|
9
|
+
// - And the work (the server's Delegations, stream event `delegation`, the snapshot's `delegations`): a task's
|
|
10
|
+
// delegator → worker line stays, "in progress" (a moving dash), until its report comes back; then a short return
|
|
11
|
+
// pulse worker → delegator (RETURN_MS), and it goes. One that waits past DELEGATION_TTL_MS fades as "no report yet".
|
|
12
|
+
// - Every line ends on something drawn: a card, or a folded team's box (a name not on the canvas draws nothing), and
|
|
13
|
+
// runs through lanes that touch the boxes it joins — two cards in one box are joined inside it.
|
|
8
14
|
// - Edges are routed metro-style through the lanes the layout keeps empty (beside the columns and between card rows
|
|
9
15
|
// inside a box; the bus above each row of teams; the trunk at the left), so a line never crosses a card.
|
|
10
16
|
// - Near: one edge per (from, to, kind, phase), ×N when several share it. Far (zoomed out): one edge per team pair.
|
|
@@ -12,14 +18,20 @@
|
|
|
12
18
|
// recipients, or far, it is one edge per recipient team, ×N (the user's decision 3). At most MAX_EDGES are drawn.
|
|
13
19
|
import { OC } from "./fleet-canvas-layout.js";
|
|
14
20
|
|
|
15
|
-
export const FADE_MS =
|
|
21
|
+
export const FADE_MS = 12000;
|
|
22
|
+
export const RETURN_MS = 2400;
|
|
23
|
+
/** As the server's (src/fleet-traffic.ts): how long a delegation waits for its report. */
|
|
24
|
+
export const DELEGATION_TTL_MS = 4 * 3_600_000;
|
|
16
25
|
export const POLL_MS = 5000;
|
|
17
26
|
export const MAX_EDGES = 60;
|
|
18
27
|
export const BUNDLE_AT = 8;
|
|
19
28
|
export const FAR_K = 0.55;
|
|
20
|
-
const MAX_ITEMS = 400, MAX_DONE = 2000;
|
|
29
|
+
const MAX_ITEMS = 400, MAX_DONE = 2000, MAX_WORK = 200;
|
|
30
|
+
const DSTATES = new Set(["open", "done", "expired", "cancelled"]);
|
|
21
31
|
const LIVE = new Set(["queued", "delivering"]);
|
|
22
|
-
const ENDS = new Set(["
|
|
32
|
+
const ENDS = new Set(["failed", "uncertain", "cancelled"]);
|
|
33
|
+
/** Delivered, or read: the line fades out (FADE_MS). */
|
|
34
|
+
const SETTLED = new Set(["delivered", "consumed"]);
|
|
23
35
|
const KINDS = new Set(["task", "report", "query", "update", "send", "broadcast"]);
|
|
24
36
|
const mono = () => (typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now());
|
|
25
37
|
|
|
@@ -28,55 +40,118 @@ export function itemOk(x) {
|
|
|
28
40
|
if (!x || typeof x !== "object") return null;
|
|
29
41
|
const { id, from, to, kind, state, op } = x;
|
|
30
42
|
if (typeof id !== "string" || !/^[0-9a-f]{16}$/.test(id) || typeof from !== "string" || !from || typeof to !== "string" || !to) return null;
|
|
31
|
-
if (!KINDS.has(kind) || !(LIVE.has(state) || state
|
|
43
|
+
if (!KINDS.has(kind) || !(LIVE.has(state) || SETTLED.has(state) || ENDS.has(state))) return null;
|
|
32
44
|
return { id, from, to, kind, state, ...(typeof op === "string" && /^[0-9a-f]{16}$/.test(op) ? { op } : {}) };
|
|
33
45
|
}
|
|
34
46
|
|
|
47
|
+
/** A delegation as the server sends it, checked; null for anything else. */
|
|
48
|
+
export function delegationOk(x) {
|
|
49
|
+
if (!x || typeof x !== "object") return null;
|
|
50
|
+
const { id, from, to, state, age_ms } = x;
|
|
51
|
+
if (typeof id !== "string" || !/^[0-9a-f]{16}$/.test(id) || typeof from !== "string" || !from || typeof to !== "string" || !to || from === to) return null;
|
|
52
|
+
if (!DSTATES.has(state) || typeof age_ms !== "number" || !Number.isFinite(age_ms) || age_ms < 0) return null;
|
|
53
|
+
return { id, from, to, state, age: age_ms };
|
|
54
|
+
}
|
|
55
|
+
|
|
35
56
|
/**
|
|
36
|
-
* The page's traffic: `apply(item, nowMs)` one stream item, `
|
|
37
|
-
*
|
|
57
|
+
* The page's traffic: `apply(item, nowMs)` one stream item, `delegation(d, nowMs)` one delegation event,
|
|
58
|
+
* `load(snapshot, nowMs, since)` a snapshot, `sweep(nowMs)` drops faded lines; each returns whether anything shown
|
|
59
|
+
* changed. `items()` what to draw: { …item, fading }. `streamRev()` counts the stream's events: a snapshot asked for
|
|
60
|
+
* before the latest one (`since` older than it) may be older than what the stream already said, so it adds only what
|
|
61
|
+
* is new and ends or rewinds nothing (#2135 review).
|
|
62
|
+
* Ended work is remembered (bounded): a late snapshot never draws a delegation that is done, expired or taken back.
|
|
38
63
|
*/
|
|
39
64
|
export function createTrafficStore() {
|
|
40
65
|
const items = new Map(); // id → { item, fadeAt }
|
|
41
|
-
const
|
|
66
|
+
const work = new Map(); // delegation id → { d, phase: "work" | "return" | "stale", until }
|
|
67
|
+
const done = new Set(); // message ids that ended: a late item for one is ignored
|
|
68
|
+
const ended = new Set(); // delegation ids that ended: never drawn in progress again
|
|
69
|
+
let rev = 0;
|
|
42
70
|
const finish = (id) => {
|
|
43
71
|
items.delete(id);
|
|
44
72
|
done.add(id);
|
|
45
73
|
if (done.size > MAX_DONE) done.delete(done.values().next().value);
|
|
46
74
|
};
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
75
|
+
const end = (id) => {
|
|
76
|
+
ended.add(id);
|
|
77
|
+
if (ended.size > MAX_DONE) ended.delete(ended.values().next().value);
|
|
78
|
+
};
|
|
79
|
+
const applyItem = (raw, now) => {
|
|
80
|
+
const it = itemOk(raw);
|
|
81
|
+
if (!it || done.has(it.id)) return false;
|
|
82
|
+
const prev = items.get(it.id);
|
|
83
|
+
if (ENDS.has(it.state)) { const had = !!prev; finish(it.id); return had; }
|
|
84
|
+
if (prev && prev.fadeAt !== null) return false; // fading: never goes back, nor starts again
|
|
85
|
+
if (prev && prev.item.state === it.state) return false;
|
|
86
|
+
if (it.state === "consumed" && !prev) { finish(it.id); return false; } // read before this page drew it
|
|
87
|
+
items.delete(it.id);
|
|
88
|
+
// A message keeps what it was (from, to, kind) through its states; only the state moves.
|
|
89
|
+
items.set(it.id, { item: prev ? { ...prev.item, state: it.state } : it, fadeAt: SETTLED.has(it.state) ? now + FADE_MS : null });
|
|
90
|
+
while (items.size > MAX_ITEMS) items.delete(items.keys().next().value);
|
|
91
|
+
return true;
|
|
92
|
+
};
|
|
93
|
+
const applyDelegation = (raw, now) => {
|
|
94
|
+
const d = delegationOk(raw);
|
|
95
|
+
if (!d || ended.has(d.id)) return false;
|
|
96
|
+
const prev = work.get(d.id);
|
|
97
|
+
if (d.state === "open") {
|
|
98
|
+
if (prev) return false;
|
|
99
|
+
work.set(d.id, { d, phase: "work", until: now + Math.max(0, DELEGATION_TTL_MS - d.age) });
|
|
100
|
+
while (work.size > MAX_WORK) { const oldest = work.keys().next().value; work.delete(oldest); end(oldest); }
|
|
58
101
|
return true;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
|
|
102
|
+
}
|
|
103
|
+
end(d.id);
|
|
104
|
+
if (d.state === "cancelled") return work.delete(d.id);
|
|
105
|
+
if (d.state === "done") { work.set(d.id, { d, phase: "return", until: now + RETURN_MS }); return true; }
|
|
106
|
+
if (!prev || prev.phase !== "work") return false; // expired: only one this page shows
|
|
107
|
+
work.set(d.id, { d, phase: "stale", until: now + FADE_MS });
|
|
108
|
+
return true;
|
|
109
|
+
};
|
|
110
|
+
const store = {
|
|
111
|
+
apply(raw, now = mono()) { rev++; return applyItem(raw, now); },
|
|
112
|
+
delegation(raw, now = mono()) { rev++; return applyDelegation(raw, now); },
|
|
113
|
+
streamRev: () => rev,
|
|
114
|
+
/**
|
|
115
|
+
* A snapshot is the truth for what is in flight: anything live it no longer lists has ended (missed while away) —
|
|
116
|
+
* unless the stream has spoken since it was asked for (`since`): then it may be older than what is drawn, and only
|
|
117
|
+
* what is new to this page is taken from it.
|
|
118
|
+
*/
|
|
119
|
+
load(snap, now = mono(), since = rev) {
|
|
120
|
+
const fresh = since === rev;
|
|
62
121
|
const list = snap && Array.isArray(snap.items) ? snap.items.map(itemOk).filter(Boolean) : [];
|
|
63
122
|
const listed = new Set(list.map((i) => i.id));
|
|
64
123
|
let changed = false;
|
|
65
|
-
for (const [id, e] of items) if (!listed.has(id) && LIVE.has(e.item.state)) { finish(id); changed = true; }
|
|
66
|
-
// Delivered, for a line drawn here: it fades now (with no stream, the snapshot is the only news of it). Any
|
|
67
|
-
// finished message is not drawn (it finished up to two minutes ago), and an ended one goes.
|
|
124
|
+
if (fresh) for (const [id, e] of items) if (!listed.has(id) && LIVE.has(e.item.state)) { finish(id); changed = true; }
|
|
125
|
+
// Delivered or read, for a line drawn here: it fades now (with no stream, the snapshot is the only news of it). Any
|
|
126
|
+
// other finished message is not drawn (it finished up to two minutes ago), and an ended one goes.
|
|
68
127
|
for (const it of list) {
|
|
69
|
-
if (
|
|
70
|
-
|
|
128
|
+
if (!fresh && items.has(it.id)) continue; // the stream knows it better
|
|
129
|
+
if (LIVE.has(it.state) || (SETTLED.has(it.state) && items.has(it.id))) changed = applyItem(it, now) || changed;
|
|
130
|
+
else if (fresh) { const had = items.has(it.id); finish(it.id); changed = changed || had; }
|
|
71
131
|
}
|
|
132
|
+
// The open delegations: the snapshot's list is the truth (one it no longer lists ended while this page was away).
|
|
133
|
+
const open = snap && Array.isArray(snap.delegations) ? snap.delegations.filter((d) => delegationOk(d)?.state === "open") : [];
|
|
134
|
+
const ids = new Set(open.map((d) => d.id));
|
|
135
|
+
if (fresh) for (const [id, e] of work) if (e.phase === "work" && !ids.has(id)) { work.delete(id); end(id); changed = true; }
|
|
136
|
+
for (const d of open) changed = applyDelegation(d, now) || changed;
|
|
72
137
|
return changed;
|
|
73
138
|
},
|
|
74
139
|
sweep(now = mono()) {
|
|
75
140
|
let changed = false;
|
|
76
141
|
for (const [id, e] of items) if (e.fadeAt !== null && now >= e.fadeAt) { finish(id); changed = true; }
|
|
142
|
+
for (const [id, e] of work) {
|
|
143
|
+
if (now < e.until) continue;
|
|
144
|
+
if (e.phase === "work") { end(id); work.set(id, { ...e, phase: "stale", until: now + FADE_MS }); } // its wait ran out here
|
|
145
|
+
else work.delete(id);
|
|
146
|
+
changed = true;
|
|
147
|
+
}
|
|
77
148
|
return changed;
|
|
78
149
|
},
|
|
79
|
-
|
|
150
|
+
/** What to draw: the messages, then the work (a done one is its return, worker → delegator). */
|
|
151
|
+
items: () => [...[...items.values()].map((e) => ({ ...e.item, fading: e.fadeAt !== null })),
|
|
152
|
+
...[...work.values()].map(({ d, phase }) => phase === "return"
|
|
153
|
+
? { id: `r${d.id}`, from: d.to, to: d.from, kind: "report", state: "delivering", phase, fading: false }
|
|
154
|
+
: { id: `w${d.id}`, from: d.from, to: d.to, kind: "task", state: "delivering", phase, fading: false })],
|
|
80
155
|
fadingCount: () => [...items.values()].filter((e) => e.fadeAt !== null).length,
|
|
81
156
|
};
|
|
82
157
|
return store;
|
|
@@ -103,6 +178,18 @@ function endOf(L, name) {
|
|
|
103
178
|
|
|
104
179
|
// ── Routing: lanes the layout keeps empty ──
|
|
105
180
|
|
|
181
|
+
/**
|
|
182
|
+
* A side lane's offset from the middle of the box's padding: at least 6 px from the box's border and from its cards.
|
|
183
|
+
* Negative: toward the border, on either side (#2329) — the first lines (o < 0) leave the cards a long last run for a head.
|
|
184
|
+
*/
|
|
185
|
+
const laneOffset = (o, PAD = OC.PAD) => Math.max(-PAD / 2 + 6, Math.min(PAD / 2 - 6, o * 0.5));
|
|
186
|
+
const leftLaneOf = (b, io, PAD) => b.x + PAD / 2 + io;
|
|
187
|
+
const rightLaneOf = (b, io, PAD) => b.x + b.w - PAD / 2 - io;
|
|
188
|
+
/** Where a line meets a card's side, from the side's middle (#2329): its full offset, a head's width from its neighbours. */
|
|
189
|
+
const sideOffset = (o) => Math.max(-OC.NH / 2 + 7, Math.min(OC.NH / 2 - 7, o));
|
|
190
|
+
/** The layout's own box padding and gutter (a phone's are narrower). */
|
|
191
|
+
const spacing = (L) => ({ PAD: L.pad ?? OC.PAD, GAP: L.gap ?? OC.GAP });
|
|
192
|
+
|
|
106
193
|
const firstBusOf = (L) => Math.min(...L.boxes.map((b) => b.busY));
|
|
107
194
|
/** From an end up to its row's bus lane: the points, and the lane's y. `o` spreads lines sharing a lane. */
|
|
108
195
|
function outward(L, end, o) {
|
|
@@ -116,17 +203,17 @@ function outward(L, end, o) {
|
|
|
116
203
|
const x = b.x + b.w / 2 + o * 1.5;
|
|
117
204
|
return { pts: [{ x, y: b.y }, { x, y: b.busY + o }], bus: b.busY + o };
|
|
118
205
|
}
|
|
119
|
-
const {
|
|
206
|
+
const { NW, NH } = OC, { PAD, GAP } = spacing(L);
|
|
120
207
|
const card = end.c, col = end.i % b.cols, rowI = Math.floor(end.i / b.cols), lines = Math.ceil(b.cells.length / b.cols);
|
|
121
|
-
const io =
|
|
122
|
-
const leftLane = b
|
|
208
|
+
const io = laneOffset(o, PAD);
|
|
209
|
+
const leftLane = leftLaneOf(b, io, PAD), rightLane = rightLaneOf(b, io, PAD);
|
|
123
210
|
let pts;
|
|
124
211
|
if (col === 0 || col === b.cols - 1) {
|
|
125
|
-
const left = col === 0, lane = left ? leftLane : rightLane, cy = card.y + NH / 2 +
|
|
212
|
+
const left = col === 0, lane = left ? leftLane : rightLane, cy = card.y + NH / 2 + sideOffset(o);
|
|
126
213
|
pts = [{ x: left ? card.x : card.x + NW, y: cy }, { x: lane, y: cy }, { x: lane, y: b.y }];
|
|
127
214
|
} else {
|
|
128
215
|
// A middle column: down into the gutter below its row, across to the nearer side lane.
|
|
129
|
-
const gy = card.y + NH + (rowI === lines - 1 ? PAD : GAP) / 2
|
|
216
|
+
const gy = card.y + NH + (rowI === lines - 1 ? PAD : GAP) / 2 - io / 2, cx = card.x + NW / 2 + o;
|
|
130
217
|
const lane = cx - b.x < b.w / 2 ? leftLane : rightLane;
|
|
131
218
|
pts = [{ x: cx, y: card.y + NH }, { x: cx, y: gy }, { x: lane, y: gy }, { x: lane, y: b.y }];
|
|
132
219
|
}
|
|
@@ -134,8 +221,43 @@ function outward(L, end, o) {
|
|
|
134
221
|
pts.push({ x: top.x, y: b.busY + o });
|
|
135
222
|
return { pts, bus: b.busY + o };
|
|
136
223
|
}
|
|
137
|
-
/**
|
|
224
|
+
/**
|
|
225
|
+
* Inside a box, from a card to one of its side lanes (x `lane`): straight out when the card is in that lane's column,
|
|
226
|
+
* else down into the gutter under its row (no card is there) and across. The last point is on the lane.
|
|
227
|
+
*/
|
|
228
|
+
function toLane(L, end, lane, o) {
|
|
229
|
+
const { NW, NH } = OC, { PAD, GAP } = spacing(L);
|
|
230
|
+
const b = end.b, card = end.c, col = end.i % b.cols, rowI = Math.floor(end.i / b.cols), lines = Math.ceil(b.cells.length / b.cols);
|
|
231
|
+
const io = laneOffset(o, PAD);
|
|
232
|
+
const left = lane < b.x + b.w / 2;
|
|
233
|
+
if ((left && col === 0) || (!left && col === b.cols - 1)) {
|
|
234
|
+
const cy = card.y + NH / 2 + sideOffset(o);
|
|
235
|
+
return [{ x: left ? card.x : card.x + NW, y: cy }, { x: lane, y: cy }];
|
|
236
|
+
}
|
|
237
|
+
const gy = card.y + NH + (rowI === lines - 1 ? PAD : GAP) / 2 - io / 2, cx = card.x + NW / 2 + o;
|
|
238
|
+
return [{ x: cx, y: card.y + NH }, { x: cx, y: gy }, { x: lane, y: gy }];
|
|
239
|
+
}
|
|
240
|
+
/** Two cards in one open box: joined inside it, through the side lane nearer to them both (never out to the bus). */
|
|
241
|
+
function inBox(L, a, z, o) {
|
|
242
|
+
const b = a.b, { PAD } = spacing(L);
|
|
243
|
+
const io = laneOffset(o, PAD);
|
|
244
|
+
const mid = ((a.i % b.cols) + (z.i % b.cols)) / 2;
|
|
245
|
+
const lane = mid <= (b.cols - 1) / 2 ? leftLaneOf(b, io, PAD) : rightLaneOf(b, io, PAD);
|
|
246
|
+
return [...toLane(L, a, lane, o), ...toLane(L, z, lane, o).reverse()];
|
|
247
|
+
}
|
|
248
|
+
/** Two of General's cards: under them, through the gap above the first row (or the canvas's empty space below). */
|
|
249
|
+
function betweenTops(a, z, o) {
|
|
250
|
+
const y = a.c.y + a.c.h + 30 + o * 0.6;
|
|
251
|
+
const ax = a.c.x + a.c.w / 2 + o, zx = z.c.x + z.c.w / 2 + o;
|
|
252
|
+
return [{ x: ax, y: a.c.y + a.c.h }, { x: ax, y }, { x: zx, y }, { x: zx, y: z.c.y + z.c.h }];
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* The points of a line from one end to the other: up to the bus, along it (and the trunk, between rows), down — or,
|
|
256
|
+
* for two cards in one box, inside the box; for two of General's cards, just under them.
|
|
257
|
+
*/
|
|
138
258
|
export function route(L, a, z, o) {
|
|
259
|
+
if (a.kind === "cell" && z.kind === "cell" && a.b === z.b) return inBox(L, a, z, o);
|
|
260
|
+
if (a.kind === "top" && z.kind === "top") return betweenTops(a, z, o);
|
|
139
261
|
const p = outward(L, a, o), q = outward(L, z, o);
|
|
140
262
|
const back = [...q.pts].reverse();
|
|
141
263
|
if (Math.abs(p.bus - q.bus) < 1) return [...p.pts, ...back];
|
|
@@ -165,19 +287,63 @@ export function badgeAt(pts) {
|
|
|
165
287
|
return best;
|
|
166
288
|
}
|
|
167
289
|
|
|
290
|
+
// ── Arrowheads (#2329) ──
|
|
291
|
+
|
|
292
|
+
/** A line's stroke width (px) by its kind and phase: the work's and its report's are heavier, a team pair's the most. */
|
|
293
|
+
export const strokeOf = (hue, phase) => (phase === "work" || phase === "return" ? 3 : hue === "team" ? 3.5 : 2.5);
|
|
294
|
+
/**
|
|
295
|
+
* The arrowhead and the ends. In stroke widths (the markers' units, fleet-canvas.js): a head LEN long and WIDE across,
|
|
296
|
+
* the line's own stroke ending BACK inside it (its round cap under the head, never out past the tip); the source dot
|
|
297
|
+
* DOT across. In px: the tip GAP short of the card, the dot's centre START off its card; a head only on a last straight
|
|
298
|
+
* run that holds it and ROOM of line before it — else the line ends GAP short with none (its dot and pulse show the way).
|
|
299
|
+
*/
|
|
300
|
+
export const HEAD = { LEN: 2.8, WIDE: 2.3, BACK: 1.4, DOT: 2, GAP: 3.5, START: 5, ROOM: 1 };
|
|
301
|
+
/** Whether a line of stroke `w` px whose last straight run is `run` px long gets a head. */
|
|
302
|
+
export const headFits = (run, w) => run >= HEAD.GAP + HEAD.LEN * w + HEAD.ROOM;
|
|
303
|
+
/** An orthogonal polyline without repeated points or points in the middle of a straight run. */
|
|
304
|
+
function corners(pts) {
|
|
305
|
+
const q = pts.filter((pt, i) => !i || pt.x !== pts[i - 1].x || pt.y !== pts[i - 1].y).map((pt) => ({ x: pt.x, y: pt.y }));
|
|
306
|
+
return q.filter((pt, i) => i === 0 || i === q.length - 1 || !((q[i - 1].x === pt.x && pt.x === q[i + 1].x) || (q[i - 1].y === pt.y && pt.y === q[i + 1].y)));
|
|
307
|
+
}
|
|
308
|
+
/** Route `pts` as drawn: its start moved `a` px along its first run, its end `b` px back along its last (each keeps 1 px). */
|
|
309
|
+
export function trimEnds(pts, a, b) {
|
|
310
|
+
const q = corners(pts);
|
|
311
|
+
if (q.length < 2) return q;
|
|
312
|
+
const pull = (i, j, by) => {
|
|
313
|
+
const l = Math.hypot(q[j].x - q[i].x, q[j].y - q[i].y), t = Math.max(0, Math.min(by, l - 1)) / l;
|
|
314
|
+
q[i] = { x: q[i].x + (q[j].x - q[i].x) * t, y: q[i].y + (q[j].y - q[i].y) * t };
|
|
315
|
+
};
|
|
316
|
+
pull(0, 1, a);
|
|
317
|
+
pull(q.length - 1, q.length - 2, b);
|
|
318
|
+
return q;
|
|
319
|
+
}
|
|
320
|
+
/** The length of a route's last straight run. */
|
|
321
|
+
export function lastRun(pts) {
|
|
322
|
+
const q = corners(pts);
|
|
323
|
+
return q.length < 2 ? 0 : Math.hypot(q[q.length - 1].x - q[q.length - 2].x, q[q.length - 1].y - q[q.length - 2].y);
|
|
324
|
+
}
|
|
325
|
+
|
|
168
326
|
// ── Edges ──
|
|
169
327
|
|
|
170
328
|
/** The colour family of a kind: task, report, broadcast, and the rest (send, query, update). */
|
|
171
329
|
export const hue = (kind) => (kind === "task" || kind === "report" || kind === "broadcast" ? kind : "send");
|
|
172
|
-
|
|
173
|
-
const
|
|
330
|
+
// A message: queued, live, fading. The work: in progress (work), its report coming back (return), or no report (stale).
|
|
331
|
+
const phaseOf = (it) => it.phase || (it.fading ? "fading" : it.state === "queued" ? "queued" : "live");
|
|
332
|
+
const RANK = { live: 0, return: 0, work: 1, queued: 2, fading: 3, stale: 3 };
|
|
333
|
+
const settled = (phase) => (phase === "fading" || phase === "stale" ? "fading" : phase);
|
|
174
334
|
|
|
175
335
|
/**
|
|
176
336
|
* The lines to draw from the store's items on layout `L`. `far`: zoomed out (one line per team pair). Each edge:
|
|
177
|
-
* { key, hue, phase, n, from, to, d, pts, badge } — `from`/`to` the instance (or team) names it
|
|
337
|
+
* { key, hue, phase, n, from, to, d, pts, w, head, badge, a, z, routed } — `from`/`to` the instance (or team) names it
|
|
338
|
+
* joins, for search; `pts` its route, end to end (on the cards); `d` the path drawn, its ends trimmed off the cards for
|
|
339
|
+
* the dot and the head (#2329); `w` its stroke width; `head` whether it has a head (headFits);
|
|
340
|
+
* `a`/`z` its two ends (fleet-route-scene.js routes the ones on cards). `routed` (#2182): the router's points by
|
|
341
|
+
* line key (fleet-route.js); a line it has none for keeps its lane route — or, while a new answer is on its way, the
|
|
342
|
+
* points the same two ends and kind had in the last one (a line changing phase keeps its place).
|
|
178
343
|
*/
|
|
179
|
-
export function trafficEdges(items, L, { far = false, max = MAX_EDGES } = {}) {
|
|
344
|
+
export function trafficEdges(items, L, { far = false, max = MAX_EDGES, routed = null } = {}) {
|
|
180
345
|
if (!L.boxes.length && L.tops.length < 2) return [];
|
|
346
|
+
// A top's way out is the first row's bus: with no box there is none, so only top ↔ top lines (betweenTops) are drawn.
|
|
181
347
|
const groups = new Map();
|
|
182
348
|
const add = (key, g) => { const cur = groups.get(key); if (cur) { cur.n += g.n; cur.names.push(...g.names); } else groups.set(key, g); };
|
|
183
349
|
const teamKey = (name) => { const t = teamOf(L, name); return t === null ? "\u0000general" : t ? t.key : undefined; };
|
|
@@ -195,7 +361,9 @@ export function trafficEdges(items, L, { far = false, max = MAX_EDGES } = {}) {
|
|
|
195
361
|
const k = far ? "team" : "broadcast";
|
|
196
362
|
const a = far ? teamEnd(it.from) : endOf(L, it.from), z = teamEnd(it.to);
|
|
197
363
|
if (!a || !z) continue;
|
|
198
|
-
|
|
364
|
+
// Queued and live messages share a line far away (as before); the work keeps its own.
|
|
365
|
+
const ph = settled(phase), lane = ph === "queued" ? "live" : ph;
|
|
366
|
+
add(`${k}|${a.key}>${z.key}|${lane}`, { a, z, hue: k === "team" ? "team" : "broadcast", phase: ph, n: 1, names });
|
|
199
367
|
continue;
|
|
200
368
|
}
|
|
201
369
|
const a = endOf(L, it.from), z = endOf(L, it.to);
|
|
@@ -203,10 +371,23 @@ export function trafficEdges(items, L, { far = false, max = MAX_EDGES } = {}) {
|
|
|
203
371
|
add(`${a.key}>${z.key}|${hue(it.kind)}|${phase}`, { a, z, hue: hue(it.kind), phase, n: 1, names });
|
|
204
372
|
}
|
|
205
373
|
const list = [...groups.entries()].sort((x, y) => RANK[x[1].phase] - RANK[y[1].phase]).slice(0, max);
|
|
374
|
+
const lent = new Set();
|
|
375
|
+
const routedBy = (key) => {
|
|
376
|
+
if (!routed || far) return null;
|
|
377
|
+
const exact = routed.get(key);
|
|
378
|
+
if (exact) return exact;
|
|
379
|
+
const kin = key.slice(0, key.lastIndexOf("|") + 1);
|
|
380
|
+
for (const [k, pts] of routed) if (k.startsWith(kin) && !groups.has(k) && !lent.has(k)) { lent.add(k); return pts; }
|
|
381
|
+
return null;
|
|
382
|
+
};
|
|
206
383
|
return list.map(([key, g], i) => {
|
|
207
384
|
const o = ((i % 7) - 3) * 7; // neighbours 7 px apart (within the ±22 px bus lane)
|
|
208
|
-
const
|
|
209
|
-
|
|
385
|
+
const viaRouter = routedBy(key);
|
|
386
|
+
const pts = viaRouter ?? route(L, g.a, g.z, o);
|
|
387
|
+
const w = strokeOf(g.hue, g.phase), head = headFits(lastRun(pts), w);
|
|
388
|
+
const d = pathOf(trimEnds(pts, HEAD.START, HEAD.GAP + (head ? HEAD.BACK * w : 0)));
|
|
389
|
+
return { key, hue: g.hue, phase: g.phase, n: g.n, names: [...new Set(g.names)], d, pts, w, head, badge: g.n > 1 ? badgeAt(pts) : null,
|
|
390
|
+
a: g.a, z: g.z, routed: !!viaRouter };
|
|
210
391
|
});
|
|
211
392
|
}
|
|
212
393
|
|
|
@@ -214,10 +395,11 @@ export function trafficEdges(items, L, { far = false, max = MAX_EDGES } = {}) {
|
|
|
214
395
|
export function sendingBy(items) {
|
|
215
396
|
const out = new Map();
|
|
216
397
|
for (const it of items) {
|
|
217
|
-
if (it.fading) continue;
|
|
398
|
+
if (it.fading || it.phase === "stale" || it.phase === "return") continue;
|
|
218
399
|
const l = out.get(it.from) || [];
|
|
219
|
-
const
|
|
220
|
-
|
|
400
|
+
const working = it.phase === "work";
|
|
401
|
+
const key = `${it.kind}>${it.to}>${working ? "work" : it.state}`;
|
|
402
|
+
if (!l.some((x) => x.key === key)) l.push({ key, kind: it.kind, to: it.to, queued: it.state === "queued", working });
|
|
221
403
|
out.set(it.from, l);
|
|
222
404
|
}
|
|
223
405
|
return out;
|
package/dist/ui/fleet-usage.js
CHANGED
|
@@ -183,6 +183,38 @@ export function zonesChanged(report) {
|
|
|
183
183
|
return zones.length > 1 || (zones.length === 1 && zones[0] !== report.zone) ? zones : null;
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
+
/** Estimated pixel width of one character in the 9 px `.us-axis` label. */
|
|
187
|
+
const LABEL_CHAR_W = 5.5;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* The 0-based indices of dates that should receive an x-axis label.
|
|
191
|
+
* Keeps the first (0) and last (n-1) when they are far enough apart not to
|
|
192
|
+
* overlap. When first and last are too close (n-1 < step), only the last
|
|
193
|
+
* (most recent) is shown — overlap-free takes precedence over keeping both
|
|
194
|
+
* ends. Intermediate labels are thinned so that no two consecutive shown
|
|
195
|
+
* labels are closer than `labelWidthPx` pixels apart.
|
|
196
|
+
*
|
|
197
|
+
* @param {number} n Number of data points (dates).
|
|
198
|
+
* @param {number} slotPx Pixels per slot (bar + gap).
|
|
199
|
+
* @param {number} labelWidthPx Estimated rendered width of one label.
|
|
200
|
+
* @returns {Set<number>}
|
|
201
|
+
*/
|
|
202
|
+
export function thinXLabels(n, slotPx, labelWidthPx) {
|
|
203
|
+
if (n <= 0) return new Set();
|
|
204
|
+
if (n === 1) return new Set([0]);
|
|
205
|
+
// Minimum slot steps between label centres (+ 2 px breathing room).
|
|
206
|
+
const step = Math.max(1, Math.ceil((labelWidthPx + 2) / slotPx));
|
|
207
|
+
// If first and last are too close to both be shown without overlap, keep
|
|
208
|
+
// only the last (most recent). The caller's "always first+last" contract
|
|
209
|
+
// is relaxed here: overlap-free takes precedence.
|
|
210
|
+
if (n - 1 < step) return new Set([n - 1]);
|
|
211
|
+
const idx = [0];
|
|
212
|
+
// Add intermediates that are at least `step` slots away from n-1.
|
|
213
|
+
for (let i = step; i < n - step; i += step) idx.push(i);
|
|
214
|
+
idx.push(n - 1); // always include last
|
|
215
|
+
return new Set(idx);
|
|
216
|
+
}
|
|
217
|
+
|
|
186
218
|
/** The trend's series: the top `TOP` agents by the measure over the range, then "others"; one value per date. */
|
|
187
219
|
export function trendSeries(report, dates) {
|
|
188
220
|
const priced = report.totals && report.totals.amount !== null && report.totals.amount > 0;
|
|
@@ -230,6 +262,8 @@ function Trend({ report, dates }) {
|
|
|
230
262
|
const max = Math.max(...sums, 0) || 1;
|
|
231
263
|
const what = s.priced ? tu("amount") : tu("trendTokens"), others = s.names.length > TOP;
|
|
232
264
|
const label = others ? tu("trendLabel", what, TOP, dates[0], dates[dates.length - 1]) : tu("trendLabelAll", what, s.names.length, dates[0], dates[dates.length - 1]);
|
|
265
|
+
// Thin x-axis labels: "MM-DD" (5 chars) × LABEL_CHAR_W ≈ 27.5 px at 9 px sans-serif.
|
|
266
|
+
const shownLabels = thinXLabels(dates.length, slot, 5 * LABEL_CHAR_W);
|
|
233
267
|
return html`<section class="us-trend card" aria-labelledby="us-trend-h">
|
|
234
268
|
<h3 id="us-trend-h">${tu("trend")} <span class="note">· ${s.priced ? tu("amount") : tu("trendTokens")}</span></h3>
|
|
235
269
|
<p class="note us-scale">${tu("scale", fmtMeasure(s.priced, max))}</p>
|
|
@@ -243,7 +277,7 @@ function Trend({ report, dates }) {
|
|
|
243
277
|
const h = v[i] > 0 ? Math.max(1, ((base - top) * v[i]) / max) : 0;
|
|
244
278
|
y -= h;
|
|
245
279
|
return h ? html`<rect key=${k} class=${`us-s${k}`} x=${left + i * slot + 2} y=${y} width=${slot - 4} height=${h}><title>${`${date} · ${s.names[k]}: ${fmtMeasure(s.priced, v[i])}`}</title></rect>` : null;
|
|
246
|
-
})}${(
|
|
280
|
+
})}${shownLabels.has(i) ? html`<text class="us-axis us-xlabel" x=${left + i * slot + slot / 2} y=${H - 6} text-anchor="middle">${date.slice(5)}</text>` : null}</g>`;
|
|
247
281
|
})}
|
|
248
282
|
</svg></div>
|
|
249
283
|
<${EarlierHint} wide=${wide} />
|
|
@@ -287,7 +321,7 @@ function Row({ r, group, max, measure }) {
|
|
|
287
321
|
const meta = [r.backends.join(", "), r.models.join(", "), r.profiles.join(", ")].filter(Boolean).join(" · ");
|
|
288
322
|
return html`<tr class="us-row">
|
|
289
323
|
<th scope="row" class="us-name"><span class="mono">${keyText(group, r.key)}</span>
|
|
290
|
-
<svg class="us-bar"
|
|
324
|
+
<svg class="us-bar" aria-hidden="true"><rect class="us-bar-bg" width="100%" height="6" rx="3" /><rect class="us-bar-fg" width=${`${Math.round(share * 100)}%`} height="6" rx="3" /></svg>
|
|
291
325
|
${group !== "instance" || meta ? html`<span class="us-meta">${meta}</span>` : null}
|
|
292
326
|
${r.flags.length ? html`<span class="us-flags">${r.flags.map((f) => html`<span key=${f} class="ch-tag">${flagText(f, r)}</span>`)}</span>` : null}</th>
|
|
293
327
|
<td data-label=${tu("amount")} class=${`num${r.amount === null ? " muted" : ""}`}>${amountText(r)}</td>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<meta name="referrer" content="no-referrer">
|
|
7
|
+
<meta name="robots" content="noindex">
|
|
8
|
+
<title>AgEnD</title>
|
|
9
|
+
<!--app-icon-->
|
|
10
|
+
<link rel="icon" href="/favicon.ico" sizes="16x16 32x32 64x64">
|
|
11
|
+
<link rel="icon" href="/favicon.svg" type="image/svg+xml" sizes="any">
|
|
12
|
+
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180">
|
|
13
|
+
<!--/app-icon-->
|
|
14
|
+
<script src="/assets/theme.js"></script>
|
|
15
|
+
<link rel="stylesheet" href="/assets/tokens.css">
|
|
16
|
+
<style>
|
|
17
|
+
/* What a guest's browser gets for a page it cannot open (#2399 smoke: it was the gate's bare JSON). The sign-in
|
|
18
|
+
page's look: the app's tokens, light and dark (theme.js before paint). */
|
|
19
|
+
* { box-sizing: border-box; }
|
|
20
|
+
body { margin: 0; min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 16px;
|
|
21
|
+
background: var(--bg); color: var(--text); font: var(--fw-regular) var(--fs-md)/var(--lh-md) var(--font-ui); -webkit-font-smoothing: antialiased; }
|
|
22
|
+
main { width: 100%; max-width: 380px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); padding: 28px 24px; }
|
|
23
|
+
.brand { margin: 0 0 18px; font-size: var(--fs-lg); font-weight: var(--fw-bold); }
|
|
24
|
+
h1 { margin: 0 0 6px; font-size: var(--fs-xl); font-weight: var(--fw-semibold); }
|
|
25
|
+
p { margin: 0 0 18px; color: var(--text-2); }
|
|
26
|
+
a.go { display: block; width: 100%; padding: 12px; text-align: center; text-decoration: none; font: var(--fw-semibold) var(--fs-md) var(--font-ui);
|
|
27
|
+
color: var(--on-accent); background: var(--accent-fill); border-radius: var(--r-full); }
|
|
28
|
+
a.go:hover { opacity: .88; }
|
|
29
|
+
a.go:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-dim); }
|
|
30
|
+
</style>
|
|
31
|
+
</head>
|
|
32
|
+
<body>
|
|
33
|
+
<main id="refused" data-why="__WHY__">
|
|
34
|
+
<div class="brand">AgEnD</div>
|
|
35
|
+
<h1 id="title">This page is not open to guests</h1>
|
|
36
|
+
<p id="lead">This page is for the fleet's members. As a guest you can use the chats shared with you.</p>
|
|
37
|
+
<a id="go" class="go" href="/ui">Open your chats</a>
|
|
38
|
+
</main>
|
|
39
|
+
<script src="/assets/guest-refused.js"></script>
|
|
40
|
+
</body>
|
|
41
|
+
</html>
|
|
Binary file
|
|
Binary file
|
|
@@ -5,10 +5,14 @@
|
|
|
5
5
|
//
|
|
6
6
|
// The native <dialog> opened with showModal(): the browser traps focus and makes the rest inert. No style attribute
|
|
7
7
|
// (#1300): classes only. Only a file URL the chat itself rendered (/ui/file/<32 hex>) is ever shown.
|
|
8
|
+
//
|
|
9
|
+
// #2333: zoom and pan (image-zoom.js). The toolbar has −, the level (it toggles fit ↔ 100%), + and Fit width; the keys
|
|
10
|
+
// + / − / 0 (fit) / 1 (100%) / W (fit width). Each image opens fitted; stepping to another fits it again.
|
|
8
11
|
import { html, useEffect, useLayoutEffect, useRef, useState } from "/assets/app-html.js";
|
|
9
12
|
import { t } from "/assets/app-i18n.js";
|
|
10
13
|
import { createStore, useStore } from "/assets/app-store.js";
|
|
11
14
|
import { Icon } from "/assets/ui-icons.js";
|
|
15
|
+
import { createZoom, STEP } from "./image-zoom.js";
|
|
12
16
|
|
|
13
17
|
const FILE_URL = /^\/ui\/file\/[0-9a-f]{32}$/;
|
|
14
18
|
/** What is shown: { items: [{ src, name }], index, opener } or null. One per page; the chat that shows it owns it. */
|
|
@@ -54,6 +58,10 @@ function ImageLightbox({ items, index, opener, onClose }) {
|
|
|
54
58
|
const [at, setAt] = useState(index);
|
|
55
59
|
const ref = useRef(null);
|
|
56
60
|
const close = useRef(null);
|
|
61
|
+
const stage = useRef(null);
|
|
62
|
+
const img = useRef(null);
|
|
63
|
+
const zoom = useRef(null);
|
|
64
|
+
const [level, setLevel] = useState(null); // { scale, fit, mode } once the picture has loaded
|
|
57
65
|
const item = items[at] || items[0];
|
|
58
66
|
const many = items.length > 1;
|
|
59
67
|
const step = (d) => setAt((n) => (n + d + items.length) % items.length);
|
|
@@ -69,6 +77,25 @@ function ImageLightbox({ items, index, opener, onClose }) {
|
|
|
69
77
|
if (opener && typeof opener.focus === "function" && document.contains?.(opener)) opener.focus();
|
|
70
78
|
};
|
|
71
79
|
}, []);
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
if (!stage.current || !img.current) return undefined;
|
|
82
|
+
const z = createZoom({ stage: stage.current, img: img.current, onChange: setLevel });
|
|
83
|
+
zoom.current = z;
|
|
84
|
+
return () => { z.destroy(); zoom.current = null; };
|
|
85
|
+
}, []);
|
|
86
|
+
// Another image: hidden until it has loaded and been fitted (its load resets the zoom). A layout effect — in the same
|
|
87
|
+
// commit that set the new src, before any load can arrive: a picture already in the cache (every thumbnail above it
|
|
88
|
+
// has loaded) fires its load before a passive effect would run, and such an effect then hid it for good with the
|
|
89
|
+
// level at "…" (the report on beta.24: Next "flashes once, then the next image is not visible"). A picture that is
|
|
90
|
+
// already complete here (the same file again: no load comes) is fitted at once.
|
|
91
|
+
const first = useRef(true);
|
|
92
|
+
useLayoutEffect(() => {
|
|
93
|
+
if (first.current) { first.current = false; return; }
|
|
94
|
+
const el = img.current;
|
|
95
|
+
if (el) el.classList.remove("lb-ready");
|
|
96
|
+
setLevel(null);
|
|
97
|
+
if (el && el.complete && el.naturalWidth > 0 && zoom.current) zoom.current.reset();
|
|
98
|
+
}, [at]);
|
|
72
99
|
useEffect(() => {
|
|
73
100
|
const d = ref.current;
|
|
74
101
|
if (!d) return undefined;
|
|
@@ -80,6 +107,12 @@ function ImageLightbox({ items, index, opener, onClose }) {
|
|
|
80
107
|
// The dark area (the dialog itself, or the stage around the image) closes it; the image and the controls do not.
|
|
81
108
|
const onClick = (e) => { if (e.target === d || (e.target && e.target.classList && e.target.classList.contains("lb-stage"))) onClose(); };
|
|
82
109
|
const onKey = (e) => {
|
|
110
|
+
const z = zoom.current;
|
|
111
|
+
if (z && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
112
|
+
const act = { "+": () => z.zoomBy(STEP), "=": () => z.zoomBy(STEP), "-": () => z.zoomBy(1 / STEP), "_": () => z.zoomBy(1 / STEP),
|
|
113
|
+
"0": () => z.fit(), "1": () => z.actual(), w: () => z.fitWidth(), W: () => z.fitWidth() }[e.key];
|
|
114
|
+
if (act) { e.preventDefault(); act(); return; }
|
|
115
|
+
}
|
|
83
116
|
if (!many) return;
|
|
84
117
|
if (e.key === "ArrowRight") { e.preventDefault(); step(1); } else if (e.key === "ArrowLeft") { e.preventDefault(); step(-1); }
|
|
85
118
|
};
|
|
@@ -90,14 +123,25 @@ function ImageLightbox({ items, index, opener, onClose }) {
|
|
|
90
123
|
return () => { d.removeEventListener("cancel", onCancel); d.removeEventListener("close", onNativeClose); d.removeEventListener("click", onClick); d.removeEventListener("keydown", onKey); };
|
|
91
124
|
}, [onClose, many, items.length]);
|
|
92
125
|
const label = item.name ? t("chat.lbLabel", item.name) : t("chat.lbLabelNoName");
|
|
126
|
+
const pct = level ? Math.round(level.scale * 100) : null;
|
|
93
127
|
return html`<dialog data-trust="lightbox" ref=${ref} class="lb" role="dialog" aria-modal="true" aria-label=${label}>
|
|
94
128
|
<div class="lb-bar">
|
|
95
129
|
<span class="lb-name" title=${item.name}>${item.name}</span>
|
|
96
130
|
${many ? html`<span class="lb-count">${t("chat.lbCount", at + 1, items.length)}</span>` : null}
|
|
131
|
+
<span class="lb-zoom" role="group">
|
|
132
|
+
<button type="button" class="icon-btn lb-zoom-out" disabled=${!level} aria-label=${t("chat.lbZoomOut")} title=${t("chat.lbZoomOut")}
|
|
133
|
+
onClick=${() => zoom.current && zoom.current.zoomBy(1 / STEP)}><${Icon} name="minus" /></button>
|
|
134
|
+
<button type="button" class="btn btn-sm lb-level" disabled=${!level} aria-label=${t("chat.lbZoomLevel", pct ?? "")} title=${t("chat.lbZoomLevel", pct ?? "")}
|
|
135
|
+
onClick=${() => zoom.current && zoom.current.toggle()}>${pct === null ? "…" : `${pct}%`}</button>
|
|
136
|
+
<button type="button" class="icon-btn lb-zoom-in" disabled=${!level} aria-label=${t("chat.lbZoomIn")} title=${t("chat.lbZoomIn")}
|
|
137
|
+
onClick=${() => zoom.current && zoom.current.zoomBy(STEP)}><${Icon} name="plus" /></button>
|
|
138
|
+
<button type="button" class=${`icon-btn lb-fit-width${level && level.mode === "width" ? " on" : ""}`} disabled=${!level} aria-pressed=${level && level.mode === "width" ? "true" : "false"}
|
|
139
|
+
aria-label=${t("chat.lbFitWidth")} title=${t("chat.lbFitWidth")} onClick=${() => zoom.current && zoom.current.fitWidth()}><${Icon} name="fitwidth" /></button>
|
|
140
|
+
</span>
|
|
97
141
|
<a class="btn btn-sm lb-orig" href=${item.src} target="_blank" rel="noopener noreferrer"><${Icon} name="external" size=${14} /><span class="lbl">${t("chat.lbOpenOriginal")}</span></a>
|
|
98
142
|
<button type="button" class="icon-btn lb-close" ref=${close} aria-label=${t("chat.lbClose")} title=${t("chat.lbClose")} onClick=${onClose}><${Icon} name="close" /></button>
|
|
99
143
|
</div>
|
|
100
|
-
<div class="lb-stage"><img class="lb-img" src=${item.src} alt=${item.name} /></div>
|
|
144
|
+
<div class="lb-stage" ref=${stage}><img class="lb-img" ref=${img} src=${item.src} alt=${item.name} draggable=${false} /></div>
|
|
101
145
|
${many ? html`<button type="button" class="icon-btn lb-nav lb-prev" aria-label=${t("chat.lbPrev")} title=${t("chat.lbPrev")} onClick=${() => step(-1)}><${Icon} name="back" /></button>
|
|
102
146
|
<button type="button" class="icon-btn lb-nav lb-next" aria-label=${t("chat.lbNext")} title=${t("chat.lbNext")} onClick=${() => step(1)}><${Icon} name="forward" /></button>` : null}
|
|
103
147
|
</dialog>`;
|