@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-org.js
CHANGED
|
@@ -11,32 +11,32 @@ import { t, register } from "/assets/app-i18n.js";
|
|
|
11
11
|
import { chatPath } from "/assets/app-route.js";
|
|
12
12
|
import { Empty, Skeleton } from "/assets/ui-states.js";
|
|
13
13
|
import { Icon } from "/assets/ui-icons.js";
|
|
14
|
-
import { modelText } from "/assets/instance-nav.js";
|
|
14
|
+
import { backendLabel, modelText, namesOf } from "/assets/instance-nav.js";
|
|
15
15
|
|
|
16
16
|
register("org", {
|
|
17
17
|
en: {
|
|
18
|
-
title: "Org chart", general: "General", unteamed: "Not in a team", members: "{0} members", member: "1 member", instances: "{0} instances", instance: "1 instance",
|
|
18
|
+
starting: "Starting", queued: "Queued", title: "Org chart", general: "General", unteamed: "Not in a team", members: "{0} members", member: "1 member", instances: "{0} instances", instance: "1 instance",
|
|
19
19
|
needs: "Needs you", working: "Working", idle: "Idle", stuck: "Looks stuck", paused: "Paused", stopped: "Stopped", crashed: "Crashed",
|
|
20
20
|
missing: "Not in the fleet", thread_discord: "Discord thread", thread_telegram: "Telegram topic", openChat: "Open chat",
|
|
21
21
|
classic: "ClassicBot room", empty: "No instances yet", emptyHint: "Instances and teams show here once the fleet has them.",
|
|
22
22
|
noTeams: "No teams yet — define them in Fleet → Teams to group the chart.", newTab: "(opens in a new tab)",
|
|
23
|
-
sending: "Sending:", queuedNote: "(queued)",
|
|
23
|
+
sending: "Sending:", queuedNote: "(queued)", workingNote: "(in progress)",
|
|
24
24
|
},
|
|
25
25
|
"zh-TW": {
|
|
26
|
-
title: "組織圖", general: "General", unteamed: "未加入 team", members: "{0} 名成員", member: "1 名成員", instances: "{0} 個 instance", instance: "1 個 instance",
|
|
26
|
+
starting: "啟動中", queued: "等待啟動", title: "組織圖", general: "General", unteamed: "未加入 team", members: "{0} 名成員", member: "1 名成員", instances: "{0} 個 instance", instance: "1 個 instance",
|
|
27
27
|
needs: "等你回應", working: "工作中", idle: "閒置", stuck: "似乎卡住", paused: "已暫停", stopped: "已停止", crashed: "已當掉",
|
|
28
28
|
missing: "不在 fleet 中", thread_discord: "Discord 討論串", thread_telegram: "Telegram topic", openChat: "開啟聊天",
|
|
29
29
|
classic: "ClassicBot 頻道", empty: "還沒有 instance", emptyHint: "fleet 有 instance 和 team 後會顯示在這裡。",
|
|
30
30
|
noTeams: "還沒有 team——到 Fleet → Teams 定義後,組織圖會依 team 分組。", newTab: "(在新分頁開啟)",
|
|
31
|
-
sending: "傳送中:", queuedNote: "(排隊中)",
|
|
31
|
+
sending: "傳送中:", queuedNote: "(排隊中)", workingNote: "(進行中)",
|
|
32
32
|
},
|
|
33
33
|
});
|
|
34
34
|
const to = (k, ...v) => t(`org.${k}`, ...v);
|
|
35
35
|
const count = (one, many, n) => (n === 1 ? to(one) : to(many, n));
|
|
36
36
|
|
|
37
37
|
/** The states a node can show, most pressing first (a team's summary lists them in this order). */
|
|
38
|
-
export const ORG_STATES = ["needs", "crashed", "stuck", "working", "idle", "paused", "stopped", "missing"];
|
|
39
|
-
const DOT = { needs: "warn", crashed: "bad", stuck: "warn", working: "busy", idle: "ok", paused: "off", stopped: "off", missing: "off" };
|
|
38
|
+
export const ORG_STATES = ["needs", "crashed", "stuck", "starting", "queued", "working", "idle", "paused", "stopped", "missing"];
|
|
39
|
+
const DOT = { starting: "busy", queued: "off", needs: "warn", crashed: "bad", stuck: "warn", working: "busy", idle: "ok", paused: "off", stopped: "off", missing: "off" };
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* One instance's live state, from the app store: `i` its status entry (null: the fleet does not list it), `exec` the
|
|
@@ -46,6 +46,8 @@ const DOT = { needs: "warn", crashed: "bad", stuck: "warn", working: "busy", idl
|
|
|
46
46
|
export function orgState(i, exec, awaiting, needs) {
|
|
47
47
|
if (!i) return "missing";
|
|
48
48
|
if (awaiting != null || needs > 0) return "needs";
|
|
49
|
+
if (i.startup_phase === "queued") return "queued";
|
|
50
|
+
if (i.startup_phase === "starting") return "starting";
|
|
49
51
|
if (i.status === "crashed") return "crashed";
|
|
50
52
|
if (i.status === "paused") return "paused";
|
|
51
53
|
if (i.status !== "running") return "stopped";
|
|
@@ -54,6 +56,17 @@ export function orgState(i, exec, awaiting, needs) {
|
|
|
54
56
|
return "idle";
|
|
55
57
|
}
|
|
56
58
|
|
|
59
|
+
/**
|
|
60
|
+
* What a node's card says (fleet-canvas.js; the Office view's desk too, fleet-office.js): its names, its state and
|
|
61
|
+
* backend (`sub`), and all of it in one line (`full`, the card's title and label).
|
|
62
|
+
*/
|
|
63
|
+
export function nodeText(n) {
|
|
64
|
+
const it = n.i;
|
|
65
|
+
const names = it ? namesOf(it) : { primary: n.name, secondary: "" };
|
|
66
|
+
const sub = it ? `${to(n.state)} · ${backendLabel(it.backend)}` : to(n.state);
|
|
67
|
+
return { primary: names.primary, secondary: names.secondary, sub, full: `${names.primary}${names.secondary ? ` (${names.secondary})` : ""} — ${sub}` };
|
|
68
|
+
}
|
|
69
|
+
|
|
57
70
|
/**
|
|
58
71
|
* The chart: the structure from /ui/org, the nodes and their states from the app store. General on top; each team with
|
|
59
72
|
* its members in fleet.yaml's order (an instance in two teams shows in both: that is its place in each); then the
|
|
@@ -95,7 +108,7 @@ export function OrgSummary({ counts }) {
|
|
|
95
108
|
/** #1918: what an instance is sending now, in words — the canvas's live traffic for the list (and a screen reader). */
|
|
96
109
|
const KIND_WORD = { task: "delegate_task", report: "report_result", query: "request_information", update: "send_to_instance", send: "send_to_instance", broadcast: "broadcast" };
|
|
97
110
|
function Sending({ list }) {
|
|
98
|
-
return html`<p class="org-sending"><span class="muted">${to("sending")}</span> ${list.map((s, i) => html`<span key=${s.key} class=${`org-send k-${s.kind}`}>${i ? ", " : ""}${KIND_WORD[s.kind] || s.kind} → ${s.to}${s.queued ? ` ${to("queuedNote")}` : ""}</span>`)}</p>`;
|
|
111
|
+
return html`<p class="org-sending"><span class="muted">${to("sending")}</span> ${list.map((s, i) => html`<span key=${s.key} class=${`org-send k-${s.kind}`}>${i ? ", " : ""}${KIND_WORD[s.kind] || s.kind} → ${s.to}${s.working ? ` ${to("workingNote")}` : s.queued ? ` ${to("queuedNote")}` : ""}</span>`)}</p>`;
|
|
99
112
|
}
|
|
100
113
|
|
|
101
114
|
function Node({ n, sending }) {
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
// #2182: the org canvas's traffic lines routed around the canvas, not along fixed lanes. libavoid (Adaptagrams, through
|
|
2
|
+
// libavoid-js 0.4.5, LGPL-2.1-or-later, an npm dependency served unmodified from /ui/vendor/) routes each line between
|
|
3
|
+
// fixed obstacles; this module says what the obstacles are (pure: the worker, the page and the tests share it).
|
|
4
|
+
//
|
|
5
|
+
// - Obstacles: every card (General's and the members'), a folded team's box, each open box's header band (its name and
|
|
6
|
+
// count are drawn over the lines) and its border as wall pieces in front of its cards. The gaps between the pieces —
|
|
7
|
+
// the box's padding and the gutters between its rows and columns (L.pad, L.gap: wide enough for a few lines each)
|
|
8
|
+
// — are the only doors, so a line crosses a border at right angles, through a door, and never runs along it.
|
|
9
|
+
// - Ends: pins on each card's sides (several on the long sides, one on the short), facing out; a line ends on a card,
|
|
10
|
+
// never on a box. A card with more lines than pins gets more, so two lines never start at one point. A short side
|
|
11
|
+
// facing a neighbour across less than ROUTE.SIDE (a column gutter, a phone's box padding) has no pin (#2329): a line
|
|
12
|
+
// into it would turn in that narrow gap with no room left for its arrowhead. libavoid turns a line into its pin right
|
|
13
|
+
// at the card's buffer, which leaves a head no straight run: lengthen() moves that turn out where there is room.
|
|
14
|
+
// - Separation: libavoid nudges lines that share a run ROUTE.NUDGE apart; the same two ends and kind are one line (×N)
|
|
15
|
+
// before they get here (fleet-traffic.js).
|
|
16
|
+
// A route that comes back otherwise (not orthogonal, not ending on its two shapes) is not drawn: that line keeps the
|
|
17
|
+
// lane route (fleet-traffic.js route()).
|
|
18
|
+
import { OC } from "./fleet-canvas-layout.js";
|
|
19
|
+
|
|
20
|
+
/** Buffer around every obstacle, the distance nudging keeps between lines, the cost of a bend, pins on a long side. */
|
|
21
|
+
export const ROUTE = { BUF: 5, NUDGE: 8, SEG: 60, PINS: 4, MAX_PINS: 64, MAX_POINTS: 64, MAX_SHAPES: 600, MAX_CONNS: 120, SIDE: 30, RUN: 16 };
|
|
22
|
+
/** libavoid's ConnDirFlags: the way a line leaves a pin. */
|
|
23
|
+
const UP = 1, DOWN = 2, LEFT = 4, RIGHT = 8;
|
|
24
|
+
/** A shape's `sides`: which short sides have a pin (absent: both). */
|
|
25
|
+
const SIDE_L = 1, SIDE_R = 2;
|
|
26
|
+
const sidesOf = (sh) => sh.sides ?? SIDE_L | SIDE_R;
|
|
27
|
+
const pinsOn = (sh) => ROUTE.PINS * 2 + ((sidesOf(sh) & SIDE_L) ? 1 : 0) + ((sidesOf(sh) & SIDE_R) ? 1 : 0);
|
|
28
|
+
|
|
29
|
+
/** The shape a line's end is on: a card (General's or a member's) or a folded team's box. Null: not routed here. */
|
|
30
|
+
function endShape(end) {
|
|
31
|
+
if (!end) return null;
|
|
32
|
+
if (end.kind === "top" || end.kind === "cell") return { key: end.key, x: end.c.x, y: end.c.y, w: end.c.w, h: end.c.h };
|
|
33
|
+
if (end.kind === "box" && end.b.folded) return { key: end.key, x: end.b.x, y: end.b.y, w: end.b.w, h: end.b.h };
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The scene for layout `L` and the lines `lines` ([{ key, a, z }], a and z ends as fleet-traffic.js endOf gives them):
|
|
39
|
+
* { shapes: [{ x, y, w, h, pins, sides? }], conns: [{ key, a, z }], boxes: [{ x, y, w, h }] } — `pins` 0 none (an
|
|
40
|
+
* obstacle only), 1 the usual pins, more: that many on each long side (a busy card); `sides` the short sides with a pin
|
|
41
|
+
* (1 left, 2 right; absent: both); every pin takes one line; `a`/`z` index
|
|
42
|
+
* shapes; `boxes` the open teams' outlines (separate() keeps lines off them). A line whose end is not a card or a folded box is left out (it keeps its lane).
|
|
43
|
+
*/
|
|
44
|
+
export function routeScene(L, lines) {
|
|
45
|
+
const shapes = [], boxes = [], at = new Map();
|
|
46
|
+
const add = (s, pins) => { shapes.push({ x: s.x, y: s.y, w: s.w, h: s.h, pins }); return shapes.length - 1; };
|
|
47
|
+
for (const c of L.tops) at.set(c.key, add(c, 1));
|
|
48
|
+
const { NW, NH, HEAD } = OC, PAD = L.pad ?? OC.PAD, GAP = L.gap ?? OC.GAP;
|
|
49
|
+
for (const b of L.boxes) {
|
|
50
|
+
if (b.folded) { at.set(`box:${b.key}`, add(b, 1)); continue; }
|
|
51
|
+
if (!b.cells.length) { add(b, 0); continue; }
|
|
52
|
+
boxes.push({ x: b.x, y: b.y, w: b.w, h: b.h });
|
|
53
|
+
for (const c of b.cells) at.set(c.key, add(c, 1));
|
|
54
|
+
add({ x: b.x - 1, y: b.y - 1, w: b.w + 2, h: HEAD + 1 }, 0);
|
|
55
|
+
const lines = Math.ceil(b.cells.length / b.cols);
|
|
56
|
+
for (let col = 0; col < b.cols; col++) add({ x: b.x + PAD + col * (NW + GAP), y: b.y + b.h - 1, w: NW, h: 2 }, 0);
|
|
57
|
+
for (const x of [b.x - 1, b.x + b.w - 1]) for (let row = 0; row < lines; row++) add({ x, y: b.y + HEAD + PAD + row * (NH + GAP), w: 2, h: NH }, 0);
|
|
58
|
+
}
|
|
59
|
+
const conns = [], demand = new Map();
|
|
60
|
+
for (const ln of lines) {
|
|
61
|
+
const a = endShape(ln.a), z = endShape(ln.z);
|
|
62
|
+
if (!a || !z || !at.has(a.key) || !at.has(z.key) || a.key === z.key) continue;
|
|
63
|
+
const ia = at.get(a.key), iz = at.get(z.key);
|
|
64
|
+
conns.push({ key: ln.key, a: ia, z: iz });
|
|
65
|
+
for (const i of [ia, iz]) demand.set(i, (demand.get(i) || 0) + 1);
|
|
66
|
+
}
|
|
67
|
+
// A short side with a pin only where a line has room to turn into it with its head: ROUTE.SIDE to the nearest shape
|
|
68
|
+
// beside it (a neighbour card, a box's wall piece).
|
|
69
|
+
for (const sh of shapes) {
|
|
70
|
+
if (!sh.pins) continue;
|
|
71
|
+
let left = Infinity, right = Infinity;
|
|
72
|
+
for (const o of shapes) {
|
|
73
|
+
if (o === sh || o.y >= sh.y + sh.h || o.y + o.h <= sh.y) continue;
|
|
74
|
+
if (o.x + o.w <= sh.x) left = Math.min(left, sh.x - o.x - o.w);
|
|
75
|
+
if (o.x >= sh.x + sh.w) right = Math.min(right, o.x - sh.x - sh.w);
|
|
76
|
+
}
|
|
77
|
+
const sides = (left >= ROUTE.SIDE ? SIDE_L : 0) | (right >= ROUTE.SIDE ? SIDE_R : 0);
|
|
78
|
+
if (sides !== (SIDE_L | SIDE_R)) sh.sides = sides;
|
|
79
|
+
}
|
|
80
|
+
// A line each: a shape with more lines than pins gets more pins on its long sides (two lines never leave one point:
|
|
81
|
+
// libavoid cannot nudge apart runs that start at the same point).
|
|
82
|
+
for (const [i, n] of demand) if (n > pinsOn(shapes[i])) shapes[i].pins = Math.min(ROUTE.MAX_PINS, Math.ceil((n - (pinsOn(shapes[i]) - ROUTE.PINS * 2)) / 2));
|
|
83
|
+
return { shapes, conns, boxes };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** A scene from anywhere else (the worker's message): only numbers in range, only indexes it has. Null: refused. */
|
|
87
|
+
export function sceneOk(s) {
|
|
88
|
+
if (!s || !Array.isArray(s.shapes) || !Array.isArray(s.conns) || !Array.isArray(s.boxes) || s.shapes.length > ROUTE.MAX_SHAPES || s.conns.length > ROUTE.MAX_CONNS
|
|
89
|
+
|| s.boxes.length > ROUTE.MAX_SHAPES) return null;
|
|
90
|
+
const num = (v) => typeof v === "number" && Number.isFinite(v) && Math.abs(v) < 1e6;
|
|
91
|
+
for (const b of s.boxes) if (!b || ![b.x, b.y, b.w, b.h].every(num) || b.w <= 0 || b.h <= 0) return null;
|
|
92
|
+
for (const sh of s.shapes) if (!sh || ![sh.x, sh.y, sh.w, sh.h].every(num) || sh.w <= 0 || sh.h <= 0 || !Number.isInteger(sh.pins) || sh.pins < 0 || sh.pins > ROUTE.MAX_PINS
|
|
93
|
+
|| (sh.sides !== undefined && (!Number.isInteger(sh.sides) || sh.sides < 0 || sh.sides > (SIDE_L | SIDE_R)))) return null;
|
|
94
|
+
for (const c of s.conns) {
|
|
95
|
+
if (!c || typeof c.key !== "string" || c.key.length > 2048) return null;
|
|
96
|
+
for (const i of [c.a, c.z]) if (!Number.isInteger(i) || i < 0 || i >= s.shapes.length || !s.shapes[i].pins) return null;
|
|
97
|
+
}
|
|
98
|
+
return s;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const onEdge = (p, s) => (Math.abs(p.x - s.x) < 0.5 || Math.abs(p.x - s.x - s.w) < 0.5) && p.y >= s.y - 0.5 && p.y <= s.y + s.h + 0.5
|
|
102
|
+
|| (Math.abs(p.y - s.y) < 0.5 || Math.abs(p.y - s.y - s.h) < 0.5) && p.x >= s.x - 0.5 && p.x <= s.x + s.w + 0.5;
|
|
103
|
+
/**
|
|
104
|
+
* A route for connection `c` of `scene`, or null: at most MAX_POINTS finite points, every segment horizontal or
|
|
105
|
+
* vertical, starting on its first shape's edge and ending on its second's.
|
|
106
|
+
*/
|
|
107
|
+
export function routeOk(pts, scene, c) {
|
|
108
|
+
if (!Array.isArray(pts) || pts.length < 2 || pts.length > ROUTE.MAX_POINTS) return null;
|
|
109
|
+
for (const p of pts) if (!p || !Number.isFinite(p.x) || !Number.isFinite(p.y)) return null;
|
|
110
|
+
for (let i = 1; i < pts.length; i++) if (pts[i].x !== pts[i - 1].x && pts[i].y !== pts[i - 1].y) return null;
|
|
111
|
+
if (!onEdge(pts[0], scene.shapes[c.a]) || !onEdge(pts[pts.length - 1], scene.shapes[c.z])) return null;
|
|
112
|
+
return pts.map((p) => ({ x: p.x, y: p.y }));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** The worker's answer to a route request `m`: its scene checked (sceneOk) before libavoid sees any of it. */
|
|
116
|
+
export function answerRoute(A, m) {
|
|
117
|
+
const scene = sceneOk(m && m.scene);
|
|
118
|
+
return { type: "routes", id: m.id, routes: scene ? [...routeWith(A, scene)] : null };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** What separate() and lengthen() share, on `scene` and the routes' points `pts` (which they move in place). */
|
|
122
|
+
function mover(scene, pts) {
|
|
123
|
+
const B = ROUTE.BUF - 0.5, OVER = 8;
|
|
124
|
+
const segsOf = (r, p) => p.slice(1).map((q, i) => ({ r, i, h: p[i].y === q.y }));
|
|
125
|
+
const coord = (p, s) => (s.h ? p[s.i].y : p[s.i].x);
|
|
126
|
+
const span = (p, s) => (s.h ? [Math.min(p[s.i].x, p[s.i + 1].x), Math.max(p[s.i].x, p[s.i + 1].x)] : [Math.min(p[s.i].y, p[s.i + 1].y), Math.max(p[s.i].y, p[s.i + 1].y)]);
|
|
127
|
+
/**
|
|
128
|
+
* A segment from a to b clear of every shape's buffer (but `own`, the card a line's first or last run starts on at its
|
|
129
|
+
* pin), and not along a box's border (through a door, say).
|
|
130
|
+
*/
|
|
131
|
+
const clear = (a, b, own = -1) => {
|
|
132
|
+
const x0 = Math.min(a.x, b.x), x1 = Math.max(a.x, b.x), y0 = Math.min(a.y, b.y), y1 = Math.max(a.y, b.y), h = y0 === y1;
|
|
133
|
+
return scene.shapes.every((sh, k) => k === own || x1 <= sh.x - B || x0 >= sh.x + sh.w + B || y1 <= sh.y - B || y0 >= sh.y + sh.h + B)
|
|
134
|
+
&& (scene.boxes ?? []).every((bx) => (h ? [bx.y, bx.y + bx.h].every((v) => Math.abs(v - y0) >= SEPARATE + 1) || Math.min(x1, bx.x + bx.w) - Math.max(x0, bx.x) <= 12
|
|
135
|
+
: [bx.x, bx.x + bx.w].every((v) => Math.abs(v - x0) >= SEPARATE + 1) || Math.min(y1, bx.y + bx.h) - Math.max(y0, bx.y) <= 12));
|
|
136
|
+
};
|
|
137
|
+
const connOf = new Map(scene.conns.map((c) => [c.key, c]));
|
|
138
|
+
/** The segments of other lines (and this one's) parallel to segment s of line r, overlapping it, closer than SEPARATE. */
|
|
139
|
+
const near = (r, s, c, lo, hi) => {
|
|
140
|
+
const out = [];
|
|
141
|
+
pts.forEach((p, r2) => segsOf(r2, p).forEach((t) => {
|
|
142
|
+
if (t.h !== s.h || (r2 === r && t.i === s.i)) return;
|
|
143
|
+
const [l2, h2] = span(p, t);
|
|
144
|
+
if (Math.min(hi, h2) - Math.max(lo, l2) > OVER) out.push(coord(p, t));
|
|
145
|
+
}));
|
|
146
|
+
return out.filter((c2) => Math.abs(c2 - c) < SEPARATE - 1e-6); // libavoid's points carry float noise
|
|
147
|
+
};
|
|
148
|
+
return { segsOf, coord, span, clear, near, connOf };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* libavoid nudges lines that share a run apart, but not always: in a channel shared by many lines it packs them closer
|
|
153
|
+
* than ROUTE.NUDGE, and lines fanning out of one card can come back on the very same run. This pass moves the middle
|
|
154
|
+
* segments of such lines (never a line's first or last, which end on a pin) sideways to the nearest place at least
|
|
155
|
+
* SEPARATE from every parallel line along them — only where the moved segment and the two it joins stay clear of
|
|
156
|
+
* every shape's buffer and keep their direction. What cannot move stays as libavoid left it.
|
|
157
|
+
*/
|
|
158
|
+
export const SEPARATE = 6;
|
|
159
|
+
export function separate(routes, scene) {
|
|
160
|
+
const keys = [...routes.keys()];
|
|
161
|
+
const pts = keys.map((k) => routes.get(k).map((p) => ({ x: p.x, y: p.y })));
|
|
162
|
+
const { segsOf, coord, span, clear, near, connOf } = mover(scene, pts);
|
|
163
|
+
for (let pass = 0; pass < 8; pass++) {
|
|
164
|
+
let moved = false;
|
|
165
|
+
pts.forEach((p, r) => segsOf(r, p).forEach((s) => {
|
|
166
|
+
if (s.i === 0 || s.i + 1 >= p.length - 1) return; // a first or last segment ends on a pin
|
|
167
|
+
const c = coord(p, s), [lo, hi] = span(p, s);
|
|
168
|
+
const close = near(r, s, c, lo, hi);
|
|
169
|
+
if (!close.length) return;
|
|
170
|
+
// Try the nearest places SEPARATE from the lines it is close to, both ways.
|
|
171
|
+
const tries = [...new Set(close.flatMap((c2) => [1, 2, 3, 4, 5, 6].flatMap((m) => [c2 + m * SEPARATE, c2 - m * SEPARATE])))].sort((u, v) => Math.abs(u - c) - Math.abs(v - c));
|
|
172
|
+
for (const c2 of tries) {
|
|
173
|
+
const a = { ...p[s.i] }, b = { ...p[s.i + 1] };
|
|
174
|
+
if (s.h) { a.y = c2; b.y = c2; } else { a.x = c2; b.x = c2; }
|
|
175
|
+
const prev = p[s.i - 1], next = p[s.i + 2];
|
|
176
|
+
// The joining segments keep their direction (never shrink through zero).
|
|
177
|
+
const dir = (u, v) => Math.sign(s.h ? v.y - u.y : v.x - u.x);
|
|
178
|
+
if (dir(prev, a) !== dir(prev, p[s.i]) || dir(b, next) !== dir(p[s.i + 1], next) || dir(prev, a) === 0 || dir(b, next) === 0) continue;
|
|
179
|
+
const c0 = connOf.get(keys[r]);
|
|
180
|
+
if (!clear(a, b) || !clear(prev, a, s.i - 1 === 0 && c0 ? c0.a : -1) || !clear(b, next, s.i + 2 === p.length - 1 && c0 ? c0.z : -1)) continue;
|
|
181
|
+
const old = [p[s.i], p[s.i + 1]];
|
|
182
|
+
p[s.i] = a; p[s.i + 1] = b;
|
|
183
|
+
const ok = !near(r, s, c2, lo, hi).length && [s.i - 1, s.i + 1].every((j) => { const t = { r, i: j, h: !s.h }; const [l3, h3] = span(p, t); return !near(r, t, coord(p, t), l3, h3).length; });
|
|
184
|
+
if (ok) { moved = true; break; }
|
|
185
|
+
[p[s.i], p[s.i + 1]] = old;
|
|
186
|
+
}
|
|
187
|
+
}));
|
|
188
|
+
if (!moved) break;
|
|
189
|
+
}
|
|
190
|
+
return new Map(keys.map((k, i) => [k, pts[i]]));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* #2329: room for each line's arrowhead. libavoid turns a line into its last pin right at the card's buffer, so the
|
|
195
|
+
* last run (where the head goes) is a few px long. This pass moves the turn before it out from the card until the last
|
|
196
|
+
* run is ROUTE.RUN long (or up to 3 × SEPARATE more; where none fits, the longest that does): only where the moved segment and the two it joins stay clear of
|
|
197
|
+
* every shape's buffer, at least SEPARATE from every parallel line, and the run before the turn keeps its direction and
|
|
198
|
+
* 4 px. A line whose turn cannot move keeps its short run (fleet-traffic.js draws it with no head).
|
|
199
|
+
*/
|
|
200
|
+
export function lengthen(routes, scene) {
|
|
201
|
+
const keys = [...routes.keys()];
|
|
202
|
+
const pts = keys.map((k) => routes.get(k).map((p) => ({ x: p.x, y: p.y })));
|
|
203
|
+
const { coord, span, clear, near, connOf } = mover(scene, pts);
|
|
204
|
+
pts.forEach((p, r) => {
|
|
205
|
+
const n = p.length;
|
|
206
|
+
if (n < 4) return; // the turn's other end is the first pin
|
|
207
|
+
const z = p[n - 1], y = p[n - 2], x = p[n - 3], w = p[n - 4], h = y.y === z.y;
|
|
208
|
+
const at = (q) => (h ? q.x : q.y);
|
|
209
|
+
const u = Math.sign(at(y) - at(z)); // out from the card
|
|
210
|
+
if (!u || Math.abs(at(y) - at(z)) >= ROUTE.RUN) return;
|
|
211
|
+
const c0 = connOf.get(keys[r]);
|
|
212
|
+
const run = Math.abs(at(y) - at(z)), tries = [];
|
|
213
|
+
for (let t = ROUTE.RUN; t <= ROUTE.RUN + 3 * SEPARATE; t++) tries.push(t);
|
|
214
|
+
for (let t = ROUTE.RUN - 1; t > run; t--) tries.push(t); // short of RUN (a phone's gutter): the longest that fits
|
|
215
|
+
for (const t of tries) {
|
|
216
|
+
const c2 = at(z) + u * t;
|
|
217
|
+
const a = h ? { x: c2, y: x.y } : { x: x.x, y: c2 }, b = h ? { x: c2, y: y.y } : { x: y.x, y: c2 };
|
|
218
|
+
if (Math.sign(at(a) - at(w)) !== Math.sign(at(x) - at(w)) || Math.abs(at(a) - at(w)) < 4) continue;
|
|
219
|
+
if (!clear(a, b) || !clear(w, a, n - 4 === 0 && c0 ? c0.a : -1) || !clear(b, z, c0 ? c0.z : -1)) continue;
|
|
220
|
+
const old = [p[n - 3], p[n - 2]];
|
|
221
|
+
p[n - 3] = a; p[n - 2] = b;
|
|
222
|
+
const ok = [n - 4, n - 3, n - 2].every((i) => { const s = { r, i, h: i === n - 3 ? !h : h }; const [lo, hi] = span(p, s); return !near(r, s, coord(p, s), lo, hi).length; });
|
|
223
|
+
if (ok) return;
|
|
224
|
+
[p[n - 3], p[n - 2]] = old;
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
return new Map(keys.map((k, i) => [k, pts[i]]));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Route `scene` with libavoid instance `A` (libavoid-js 0.4.5's: its constants are numbers on `A`). A Map of
|
|
232
|
+
* connection key → points, for the routes that pass routeOk only.
|
|
233
|
+
*/
|
|
234
|
+
export function routeWith(A, scene) {
|
|
235
|
+
const r = new A.Router(A.OrthogonalRouting);
|
|
236
|
+
try {
|
|
237
|
+
r.setRoutingParameter(A.shapeBufferDistance, ROUTE.BUF);
|
|
238
|
+
r.setRoutingParameter(A.idealNudgingDistance, ROUTE.NUDGE);
|
|
239
|
+
r.setRoutingParameter(A.segmentPenalty, ROUTE.SEG);
|
|
240
|
+
r.setRoutingOption(A.nudgeOrthogonalSegmentsConnectedToShapes, true);
|
|
241
|
+
r.setRoutingOption(A.nudgeSharedPathsWithCommonEndPoint, true);
|
|
242
|
+
for (const [k, v] of Object.entries(ROUTE.EXTRA_OPT ?? {})) r.setRoutingOption(A[k], v);
|
|
243
|
+
for (const [k, v] of Object.entries(ROUTE.EXTRA_PARAM ?? {})) r.setRoutingParameter(A[k], v);
|
|
244
|
+
// The router owns its shapes, pins and connectors (A.destroy(r) frees them); the points, rectangles and ends it
|
|
245
|
+
// copies are freed here, or the wasm heap grows with every route.
|
|
246
|
+
const temp = (o) => { made.push(o); return o; }, made = [];
|
|
247
|
+
const refs = scene.shapes.map((s) => {
|
|
248
|
+
const ref = new A.ShapeRef(r, temp(new A.Rectangle(temp(new A.Point(s.x, s.y)), temp(new A.Point(s.x + s.w, s.y + s.h)))));
|
|
249
|
+
if (s.pins) {
|
|
250
|
+
const k = s.pins === 1 ? ROUTE.PINS : s.pins;
|
|
251
|
+
const pin = (x, y, dir) => new A.ShapeConnectionPin(ref, 1, x, y, true, 0, dir).setExclusive(true);
|
|
252
|
+
for (let i = 1; i <= k; i++) { pin(i / (k + 1), 0, UP); pin(i / (k + 1), 1, DOWN); }
|
|
253
|
+
if (sidesOf(s) & SIDE_L) pin(0, 0.5, LEFT);
|
|
254
|
+
if (sidesOf(s) & SIDE_R) pin(1, 0.5, RIGHT);
|
|
255
|
+
}
|
|
256
|
+
return ref;
|
|
257
|
+
});
|
|
258
|
+
const conns = scene.conns.map((c) => new A.ConnRef(r, temp(new A.ConnEnd(refs[c.a], 1)), temp(new A.ConnEnd(refs[c.z], 1))));
|
|
259
|
+
for (const o of made.splice(0)) A.destroy(o);
|
|
260
|
+
r.processTransaction();
|
|
261
|
+
const out = new Map();
|
|
262
|
+
scene.conns.forEach((c, i) => {
|
|
263
|
+
const line = conns[i].displayRoute(), pts = [];
|
|
264
|
+
for (let k = 0; k < line.size() && k <= ROUTE.MAX_POINTS; k++) { const p = line.get_ps(k); pts.push({ x: p.x, y: p.y }); }
|
|
265
|
+
const ok = routeOk(pts, scene, c);
|
|
266
|
+
if (ok) out.set(c.key, ok);
|
|
267
|
+
});
|
|
268
|
+
return ROUTE.SEPARATE === false ? out : lengthen(separate(out, scene), scene);
|
|
269
|
+
} finally {
|
|
270
|
+
A.destroy(r);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// #2182: the worker that routes the org canvas's traffic lines (fleet-route-scene.js says what to route). It is served
|
|
2
|
+
// with a policy of its own (web-host-guard.ts ROUTE_WORKER_CSP): WebAssembly may run here, as it may not on the page,
|
|
3
|
+
// and it may reach nothing — the page fetches libavoid.wasm and hands the bytes over; they are instantiated from a
|
|
4
|
+
// blob: URL. It receives numbers and answers numbers; the page checks both.
|
|
5
|
+
import { AvoidLib } from "/ui/vendor/libavoid-0.4.5/libavoid.js";
|
|
6
|
+
import { answerRoute } from "./fleet-route-scene.js";
|
|
7
|
+
|
|
8
|
+
let ready = null;
|
|
9
|
+
self.onmessage = (ev) => {
|
|
10
|
+
const m = ev.data;
|
|
11
|
+
if (!m || typeof m !== "object") return;
|
|
12
|
+
if (m.type === "init" && !ready && m.wasm instanceof ArrayBuffer) {
|
|
13
|
+
const url = URL.createObjectURL(new Blob([m.wasm], { type: "application/wasm" }));
|
|
14
|
+
ready = AvoidLib.load(url).then(() => AvoidLib.getInstance()).finally(() => URL.revokeObjectURL(url));
|
|
15
|
+
ready.then(() => self.postMessage({ type: "ready" }), () => self.postMessage({ type: "failed" }));
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (m.type === "route" && ready && Number.isInteger(m.id)) {
|
|
19
|
+
ready.then((A) => self.postMessage(answerRoute(A, m))).catch(() => self.postMessage({ type: "routes", id: m.id, routes: null }));
|
|
20
|
+
}
|
|
21
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// #2182: the page's side of the traffic router — one worker (fleet-route-worker.js), started the first time Live
|
|
2
|
+
// traffic is drawn, fed the libavoid.wasm bytes the page fetched. One scene at a time: a newer one replaces any still
|
|
3
|
+
// waiting (the older one's answer would be stale anyway). A worker that fails, or takes longer than TIMEOUT_MS, is
|
|
4
|
+
// ended; after FAIL_LIMIT failures in a row this page stops asking, and every line keeps its lane route (the caller's
|
|
5
|
+
// fallback for a null answer).
|
|
6
|
+
import { routeOk } from "./fleet-route-scene.js";
|
|
7
|
+
|
|
8
|
+
export const WORKER_URL = "/ui/js/fleet-route-worker.js";
|
|
9
|
+
export const WASM_URL = "/ui/vendor/libavoid-0.4.5/libavoid.wasm";
|
|
10
|
+
export const TIMEOUT_MS = 4000;
|
|
11
|
+
const FAIL_LIMIT = 2;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A client: route(scene) → a Promise of a Map (connection key → points, checked against the scene) or null (not
|
|
15
|
+
* routed: superseded, failed, unavailable). `deps` replaces Worker, fetch and the clock in tests.
|
|
16
|
+
*/
|
|
17
|
+
export function createRouteClient(deps = {}) {
|
|
18
|
+
const W = deps.Worker ?? (typeof Worker === "function" ? Worker : null);
|
|
19
|
+
const get = deps.fetch ?? ((...a) => fetch(...a));
|
|
20
|
+
const timers = deps.timers ?? { set: (f, ms) => setTimeout(f, ms), clear: (t) => clearTimeout(t) };
|
|
21
|
+
let worker = null, wasm = null, fails = 0, nextId = 1;
|
|
22
|
+
let busy = null, waiting = null; // { id, scene, resolve, timer }
|
|
23
|
+
const end = () => { try { worker?.terminate(); } catch { /* gone */ } worker = null; };
|
|
24
|
+
const fail = () => {
|
|
25
|
+
fails++;
|
|
26
|
+
end();
|
|
27
|
+
if (busy) { timers.clear(busy.timer); busy.resolve(null); busy = null; }
|
|
28
|
+
if (fails >= FAIL_LIMIT && waiting) { waiting.resolve(null); waiting = null; }
|
|
29
|
+
pump();
|
|
30
|
+
};
|
|
31
|
+
async function start(job) {
|
|
32
|
+
if (!wasm) {
|
|
33
|
+
const res = await get(WASM_URL, { credentials: "same-origin" });
|
|
34
|
+
if (!res.ok) throw new Error(`libavoid.wasm: ${res.status}`);
|
|
35
|
+
wasm = await res.arrayBuffer();
|
|
36
|
+
}
|
|
37
|
+
// #2194 review: closed, timed out or replaced while the .wasm was on its way — start nothing (a worker made now
|
|
38
|
+
// would be nobody's, and a later start would make another).
|
|
39
|
+
if (busy !== job || worker) return;
|
|
40
|
+
const w = new W(WORKER_URL, { type: "module" });
|
|
41
|
+
w.onmessage = (ev) => {
|
|
42
|
+
const m = ev.data;
|
|
43
|
+
if (!m || typeof m !== "object" || w !== worker) return;
|
|
44
|
+
if (m.type === "failed") { fail(); return; }
|
|
45
|
+
if (m.type !== "routes" || !busy || m.id !== busy.id) return;
|
|
46
|
+
const { scene, resolve, timer } = busy;
|
|
47
|
+
busy = null;
|
|
48
|
+
timers.clear(timer);
|
|
49
|
+
if (!Array.isArray(m.routes)) { fail(); resolve(null); return; }
|
|
50
|
+
fails = 0;
|
|
51
|
+
const out = new Map();
|
|
52
|
+
for (const pair of m.routes.slice(0, scene.conns.length)) {
|
|
53
|
+
if (!Array.isArray(pair) || typeof pair[0] !== "string") continue;
|
|
54
|
+
const c = scene.conns.find((x) => x.key === pair[0]);
|
|
55
|
+
const pts = c && routeOk(pair[1], scene, c);
|
|
56
|
+
if (pts) out.set(c.key, pts);
|
|
57
|
+
}
|
|
58
|
+
resolve(out);
|
|
59
|
+
pump();
|
|
60
|
+
};
|
|
61
|
+
w.onerror = (e) => { e?.preventDefault?.(); if (w === worker) fail(); };
|
|
62
|
+
worker = w;
|
|
63
|
+
w.postMessage({ type: "init", wasm: wasm.slice(0) });
|
|
64
|
+
}
|
|
65
|
+
function pump() {
|
|
66
|
+
if (busy || !waiting) return;
|
|
67
|
+
if (fails >= FAIL_LIMIT || !W) { waiting.resolve(null); waiting = null; return; }
|
|
68
|
+
busy = waiting; waiting = null;
|
|
69
|
+
const job = busy;
|
|
70
|
+
job.timer = timers.set(() => { if (busy === job) fail(); }, TIMEOUT_MS);
|
|
71
|
+
(worker ? Promise.resolve() : start(job)).then(() => {
|
|
72
|
+
if (busy === job) worker.postMessage({ type: "route", id: job.id, scene: job.scene });
|
|
73
|
+
}, () => { if (busy === job) fail(); });
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
route(scene) {
|
|
77
|
+
if (waiting) waiting.resolve(null);
|
|
78
|
+
return new Promise((resolve) => { waiting = { id: nextId++, scene, resolve, timer: null }; pump(); });
|
|
79
|
+
},
|
|
80
|
+
/** Off: the worker ended; what was waiting gets null. */
|
|
81
|
+
close() {
|
|
82
|
+
if (waiting) { waiting.resolve(null); waiting = null; }
|
|
83
|
+
if (busy) { timers.clear(busy.timer); busy.resolve(null); busy = null; }
|
|
84
|
+
end();
|
|
85
|
+
},
|
|
86
|
+
get available() { return !!W && fails < FAIL_LIMIT; },
|
|
87
|
+
};
|
|
88
|
+
}
|