@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
|
@@ -5,7 +5,7 @@ import { chatEffectIdentity } from "/assets/effect-chat-runtime.js";
|
|
|
5
5
|
const owners = new WeakSet(), safe = fn => { try { return fn(); } catch { return null; } };
|
|
6
6
|
const LIMIT = 128 * 1024;
|
|
7
7
|
export function createEffectTrialController({ window: host, current, allowed, onStart, onChange = () => {} }) {
|
|
8
|
-
let dead = false, active = null, physical = null, previous = null, broken = false, clockBusy = false;
|
|
8
|
+
let dead = false, active = null, physical = null, previous = null, broken = false, clockBusy = false, endedReason = null, endedOffer = null;
|
|
9
9
|
const cleanup = [], releases = [], identity = safe(() => chatEffectIdentity(host));
|
|
10
10
|
const tell = () => { if (!dead) safe(onChange); };
|
|
11
11
|
function clock() {
|
|
@@ -26,11 +26,16 @@ export function createEffectTrialController({ window: host, current, allowed, on
|
|
|
26
26
|
}
|
|
27
27
|
function end(op, reason = "stopped") {
|
|
28
28
|
if (!op || op.dead) return false;
|
|
29
|
-
op.dead = true; if (active === op) active = null;
|
|
29
|
+
op.dead = true; if (active === op) active = null;
|
|
30
|
+
endedReason = typeof reason === "string" && /^[a-z][a-z0-9_]{0,79}$/.test(reason) ? reason : "trial_failed";
|
|
31
|
+
endedOffer = op.offer.offer;
|
|
32
|
+
safe(() => op.resolve?.(false));
|
|
30
33
|
safe(() => host.clearTimeout(op.timer)); safe(() => op.controller.abort());
|
|
31
34
|
if (op.reply && !op.stopQueued) { op.stopQueued = true; cleanup.push(op); }
|
|
32
35
|
// Physical paint is removed before callbacks, cleanup I/O or another explicit click.
|
|
33
|
-
safe(() => op.dispose?.()); op.dispose = null;
|
|
36
|
+
safe(() => op.dispose?.()); op.dispose = null;
|
|
37
|
+
if (!["stopped", "replaced"].includes(endedReason)) safe(() => host.console?.warn("[AgEnD effects] Try stopped:", endedReason));
|
|
38
|
+
tell(); drain(); return true;
|
|
34
39
|
}
|
|
35
40
|
function arm(op) {
|
|
36
41
|
safe(() => host.clearTimeout(op.timer));
|
|
@@ -67,7 +72,7 @@ export function createEffectTrialController({ window: host, current, allowed, on
|
|
|
67
72
|
if (dead) return; dead = true; end(active); for (const off of releases.splice(0)) safe(off); tell();
|
|
68
73
|
}
|
|
69
74
|
const api = { ok: false, start: async () => false, stop: () => end(active), sync() { const op = active; if (op && !eligible(op)) end(op, "trial_ended"); },
|
|
70
|
-
snapshot: () => Object.freeze({ busy: !!physical || cleanup.length > 0, phase: active ? active.reply ? "running" : "starting" : "idle" }), dispose };
|
|
75
|
+
snapshot: () => Object.freeze({ busy: !!physical || cleanup.length > 0, phase: active ? active.reply ? "running" : "starting" : "idle", reason: active ? null : endedReason, offer: active ? active.offer.offer : endedOffer }), dispose };
|
|
71
76
|
if (!identity || owners.has(host) || typeof current !== "function" || typeof allowed !== "function" || typeof onStart !== "function"
|
|
72
77
|
|| typeof host.AgendAuth?.trialSession !== "function" || typeof host.AgendAuth?.onSessionEnd !== "function") return Object.freeze(api);
|
|
73
78
|
owners.add(host);
|
|
@@ -75,7 +80,7 @@ export function createEffectTrialController({ window: host, current, allowed, on
|
|
|
75
80
|
const off = host.AgendAuth.onSessionEnd(dispose);
|
|
76
81
|
if (dead) { safe(off); return Object.freeze(api); }
|
|
77
82
|
releases.push(off);
|
|
78
|
-
for (const [target, type, fn] of [[host, "blur", () => end(active)], [host, "pagehide", dispose], [host.document, "visibilitychange", () => { if (host.document.visibilityState !== "visible") end(active); }]]) {
|
|
83
|
+
for (const [target, type, fn] of [[host, "blur", () => end(active, "trial_window_blur")], [host, "pagehide", dispose], [host.document, "visibilitychange", () => { if (host.document.visibilityState !== "visible") end(active, "hidden"); }]]) {
|
|
79
84
|
target.addEventListener(type, fn); releases.push(() => target.removeEventListener(type, fn));
|
|
80
85
|
}
|
|
81
86
|
} catch { dispose(); return Object.freeze(api); }
|
|
@@ -86,7 +91,7 @@ export function createEffectTrialController({ window: host, current, allowed, on
|
|
|
86
91
|
const offer = safe(() => effectTrialMessage(message)), instance = safe(() => message.instance), began = clock();
|
|
87
92
|
if (!offer || began === null || began + 10000 > Number.MAX_SAFE_INTEGER || safe(() => host.Date.now() < offer.expiresAt) !== true) return false;
|
|
88
93
|
const op = { instance, offer, began, until: began + 10000, controller: new host.AbortController(), timer: null, reply: null, dead: false, stopQueued: false, dispose: null };
|
|
89
|
-
active = op; const token = {}; physical = token;
|
|
94
|
+
endedReason = null; endedOffer = null; active = op; const token = {}; physical = token;
|
|
90
95
|
const cancelled = new Promise(resolve => { op.resolve = resolve; });
|
|
91
96
|
const work = Promise.resolve().then(async () => {
|
|
92
97
|
if (!eligible(op)) return false;
|
|
@@ -105,12 +110,12 @@ export function createEffectTrialController({ window: host, current, allowed, on
|
|
|
105
110
|
op.until = began + reply.remainingMs;
|
|
106
111
|
if (op.until > Number.MAX_SAFE_INTEGER || !eligible(op)) return false;
|
|
107
112
|
arm(op);
|
|
108
|
-
const handle = Object.freeze({ reply, startedAt: began, instance, current: () => eligible(op), stop: () => end(op), });
|
|
113
|
+
const handle = Object.freeze({ reply, startedAt: began, instance, current: () => eligible(op), stop: (reason = "stopped") => end(op, reason), });
|
|
109
114
|
const disposer = onStart(handle);
|
|
110
115
|
if (typeof disposer !== "function") return false;
|
|
111
116
|
if (!eligible(op)) { safe(disposer); return false; }
|
|
112
117
|
op.dispose = disposer; tell(); return eligible(op);
|
|
113
|
-
}).catch(() => false).then(ok => { if (!ok) end(op); return ok; }).finally(() => { if (physical === token) physical = null; tell(); drain(); });
|
|
118
|
+
}).catch(() => false).then(ok => { if (!ok) end(op, "trial_start_failed"); return ok; }).finally(() => { if (physical === token) physical = null; tell(); drain(); });
|
|
114
119
|
// The logical caller may stop immediately, while the physical request/cancel still owns the lane.
|
|
115
120
|
tell();
|
|
116
121
|
return Promise.race([work, cancelled]);
|
|
@@ -1,31 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const FORBIDDEN = /(?!\u200d)[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u;
|
|
4
|
-
const VISIBLE = /[^\p{M}\p{C}\p{Z}\u115f\u1160\u3164\uffa0\u2800]/u;
|
|
5
|
-
let graphemes = null;
|
|
6
|
-
export function checkEffectTrialOffer(value) {
|
|
7
|
-
try {
|
|
8
|
-
if (!value || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) return null;
|
|
9
|
-
const keys = Reflect.ownKeys(value);
|
|
10
|
-
if (keys.length !== KEYS.length || keys.some(k => typeof k !== "string" || !KEYS.includes(k))) return null;
|
|
11
|
-
const x = Object.create(null);
|
|
12
|
-
for (const key of KEYS) {
|
|
13
|
-
const d = Object.getOwnPropertyDescriptor(value, key);
|
|
14
|
-
if (!d || !("value" in d) || !d.enumerable) return null;
|
|
15
|
-
x[key] = d.value;
|
|
16
|
-
}
|
|
17
|
-
if (x.v !== 1 || typeof x.offer !== "string" || !ID.test(x.offer) || typeof x.id !== "string" || !ID.test(x.id)
|
|
18
|
-
|| typeof x.title !== "string" || x.title.length > 400 || x.title.normalize("NFC") !== x.title || x.title.trim() !== x.title
|
|
19
|
-
|| FORBIDDEN.test(x.title) || !VISIBLE.test(x.title) || !Number.isSafeInteger(x.expiresAt) || x.expiresAt < 0) return null;
|
|
20
|
-
graphemes ??= new Intl.Segmenter(undefined, { granularity: "grapheme" });
|
|
21
|
-
let count = 0; for (const _part of graphemes.segment(x.title)) if (++count > 40) return null;
|
|
22
|
-
if (count < 1) return null;
|
|
23
|
-
return Object.freeze({ v: 1, offer: x.offer, id: x.id, title: x.title, expiresAt: x.expiresAt });
|
|
24
|
-
} catch { return null; }
|
|
25
|
-
}
|
|
26
|
-
/** Role and sender are host fields, never inferred from a message's text. Start must separately authorize. */
|
|
27
|
-
export function effectTrialMessage(message) {
|
|
28
|
-
if (!message || message.role !== "status" || message.sender !== "agend" || typeof message.instance !== "string"
|
|
29
|
-
|| message.instance.length < 1 || message.instance.length > 128) return null;
|
|
30
|
-
return checkEffectTrialOffer(message.effectTrial);
|
|
31
|
-
}
|
|
1
|
+
// On-only Canvas Worker display validation; ordinary chat boot imports no parser.
|
|
2
|
+
export { checkEffectTrialOffer, effectTrialMessage } from "/assets/effect-display-metadata.js";
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
// #1918: the org canvas's layout (fleet-canvas.js draws it; fleet-traffic.js routes lines through its empty lanes).
|
|
2
2
|
// Fixed slots, no layout engine: the same structure always gives the same picture.
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Sizes in canvas units. NW×NH a member card, LW×LH a General card; FOLDED a folded (or empty) team's height. GAP and
|
|
6
|
+
* PAD (#2182): the gutters between cards and a box's padding are the traffic lines' channels inside a box — wide
|
|
7
|
+
* enough that the router (fleet-route-scene.js) keeps a few lines apart in each; a phone's narrow packing keeps the
|
|
8
|
+
* tighter GAP_NARROW and PAD_NARROW, so General and the first team still open at a readable size. A layout says which
|
|
9
|
+
* it used (L.gap, L.pad).
|
|
10
|
+
*/
|
|
11
|
+
export const OC = { NW: 184, NH: 56, GAP: 28, PAD: 32, GAP_NARROW: 18, PAD_NARROW: 24, HEAD: 34, TEAM_GAP: 72, ROW_GAP: 96, ROW_MAX: 1400, ROW_MAX_NARROW: 460, LW: 232, LH: 68, TOP_Y: 20, BUS: 44, FOLDED: 64, TRUNK: -30 };
|
|
6
12
|
const colsFor = (n, narrow) => (n <= 1 ? 1 : n <= 4 || narrow ? 2 : 3);
|
|
13
|
+
/** A search's needle, and whether a node matches it (its name or nickname): the canvas's Find, the Office view's too. */
|
|
14
|
+
export const needle = (q) => String(q || "").trim().toLowerCase();
|
|
15
|
+
export const hits = (node, q) => !!q && (node.name.toLowerCase().includes(q) || (!!node.i && typeof node.i.display_name === "string" && node.i.display_name.toLowerCase().includes(q)));
|
|
7
16
|
/** The key a team folds by (per device): its name; the instances in no team have one of their own no team name can be. */
|
|
8
17
|
export const REST_KEY = "\u0000rest";
|
|
9
18
|
|
|
@@ -13,7 +22,7 @@ export const REST_KEY = "\u0000rest";
|
|
|
13
22
|
* size of the whole. `narrow`: a phone's packing.
|
|
14
23
|
*/
|
|
15
24
|
export function canvasLayout(view, folded = new Set(), { narrow = false, label = (s, n) => `${n} ${s}` } = {}) {
|
|
16
|
-
const { NW, NH, GAP, PAD
|
|
25
|
+
const { NW, NH, HEAD } = OC, GAP = narrow ? OC.GAP_NARROW : OC.GAP, PAD = narrow ? OC.PAD_NARROW : OC.PAD;
|
|
17
26
|
const groups = [...view.teams.map((tm) => ({ key: tm.name, name: tm.name, loose: false, nodes: tm.nodes, counts: tm.counts })),
|
|
18
27
|
...(view.rest.nodes.length ? [{ key: REST_KEY, name: null, loose: true, nodes: view.rest.nodes, counts: view.rest.counts }] : [])];
|
|
19
28
|
const rows = [];
|
|
@@ -49,7 +58,7 @@ export function canvasLayout(view, folded = new Set(), { narrow = false, label =
|
|
|
49
58
|
const width = Math.max(rowsW, topW);
|
|
50
59
|
const tops = view.top.map((node, i) => ({ node, key: `\u0000top/${node.name}`, x: width / 2 - topW / 2 + i * (OC.LW + GAP), y: OC.TOP_Y, w: OC.LW, h: OC.LH }));
|
|
51
60
|
const height = boxes.length ? y - OC.ROW_GAP : tops.length ? OC.TOP_Y + OC.LH : 0;
|
|
52
|
-
return { tops, boxes, width, height, tree: treeLines(tops, boxes) };
|
|
61
|
+
return { tops, boxes, width, height, tree: treeLines(tops, boxes), gap: GAP, pad: PAD };
|
|
53
62
|
}
|
|
54
63
|
|
|
55
64
|
/** A folded team's summary line height, and a label's width estimate (canvas units: wide for CJK, narrow otherwise). */
|
package/dist/ui/fleet-canvas.js
CHANGED
|
@@ -8,13 +8,16 @@
|
|
|
8
8
|
// a team or searching never moves another one. Tree lines: a stem from General, a bus over each row, a trunk at the
|
|
9
9
|
// left joining the rows, one drop per team — never a line per member (the box says who is in it). A phone packs
|
|
10
10
|
// narrower (one team a row, at most two columns), so General and the first team open readable.
|
|
11
|
-
// - Per device (localStorage; blocked storage: this page only): Canvas
|
|
12
|
-
// itself is not kept: it opens on General and the first row
|
|
13
|
-
// panel allows (no larger than life), on a phone no smaller
|
|
11
|
+
// - Per device (localStorage; blocked storage: this page only): Canvas, List or Office (fleet-office.js: the same fleet
|
|
12
|
+
// as a pixel office), and which teams are folded. The view itself is not kept: it opens on General and the first row
|
|
13
|
+
// (#1918's user decision 2) — on a desktop as wide as the panel allows (no larger than life), on a phone no smaller
|
|
14
|
+
// than readable. 0 / Fit shows the whole fleet.
|
|
14
15
|
// - Presentation only, like the list: a card opens that instance's chat; nothing is edited here (#1689 is how teams
|
|
15
16
|
// change). The live state is the app store's (fleet-org.js buildOrgView), so the canvas moves with the stream.
|
|
16
17
|
// - Live traffic (fleet-traffic.js): the messages between instances, drawn between the team boxes and the cards (never
|
|
17
18
|
// hidden under a box, never across a name). Live on or off per device; the list says it in words ("Sending: …").
|
|
19
|
+
// #2182: routed around the cards and through the boxes' doors by libavoid in a worker (fleet-route-scene.js), each
|
|
20
|
+
// line from card to card; the lanes are the fallback.
|
|
18
21
|
import { html, useEffect, useLayoutEffect, useMemo, useRef, useState } from "/assets/app-html.js";
|
|
19
22
|
import { appStore } from "/assets/app-store.js";
|
|
20
23
|
import { t, register } from "/assets/app-i18n.js";
|
|
@@ -22,30 +25,35 @@ import { chatPath } from "/assets/app-route.js";
|
|
|
22
25
|
import { navigate } from "/assets/app-nav.js";
|
|
23
26
|
import { Empty, Skeleton } from "/assets/ui-states.js";
|
|
24
27
|
import { Icon } from "/assets/ui-icons.js";
|
|
25
|
-
import { avatarOf,
|
|
28
|
+
import { avatarOf, firstCharacter, namesOf } from "/assets/instance-nav.js";
|
|
26
29
|
import { identityClasses, identityOf, paintIdentity, useIdentityColors } from "/assets/identity-color.js";
|
|
27
|
-
import { buildOrgView, OrgChart, OrgSummary } from "./fleet-org.js";
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
+
import { buildOrgView, nodeText, OrgChart, OrgSummary } from "./fleet-org.js";
|
|
31
|
+
import { Office } from "./fleet-office.js";
|
|
32
|
+
import { OC, REST_KEY, SUM_LINE, canvasLayout, hits, needle, openingRegion, summaryRows } from "./fleet-canvas-layout.js";
|
|
33
|
+
import { createTrafficStore, FAR_K, HEAD, POLL_MS, sendingBy, trafficEdges } from "./fleet-traffic.js";
|
|
34
|
+
import { routeScene } from "./fleet-route-scene.js";
|
|
35
|
+
import { createRouteClient } from "./fleet-route.js";
|
|
30
36
|
|
|
31
37
|
register("orgc", {
|
|
32
38
|
en: {
|
|
33
|
-
view: "View", canvas: "Canvas", list: "List", find: "Find an instance", findShort: "Find", found: "{0} found", foundOne: "1 found", noMatch: "No match",
|
|
39
|
+
view: "View", canvas: "Canvas", list: "List", office: "Office", find: "Find an instance", findShort: "Find", found: "{0} found", foundOne: "1 found", noMatch: "No match",
|
|
34
40
|
zoomIn: "Zoom in", zoomOut: "Zoom out", fit: "Fit to screen",
|
|
35
41
|
label: "Org chart canvas. Tab or the arrow keys move between instances, Enter opens a chat, + and − zoom, 0 fits the fleet.",
|
|
36
42
|
expand: "Expand", collapse: "Collapse", members: "{0} members", member: "1 member", inFolded: "{0} found · expand", noMembers: "No members",
|
|
37
43
|
openChat: "Open chat", minimap: "Overview: click to move there",
|
|
38
44
|
live: "Live", liveOn: "Hide live traffic", liveOff: "Show live traffic", lgTask: "delegate_task", lgSend: "send_to_instance",
|
|
39
45
|
lgReport: "report_result", lgBroadcast: "broadcast", lgQueued: "queued", lgFading: "delivered", lgTeam: "between teams", legend: "Key",
|
|
46
|
+
lgWork: "in progress (until its report)", lgReturn: "done (report back)", lgStale: "no report yet",
|
|
40
47
|
},
|
|
41
48
|
"zh-TW": {
|
|
42
|
-
view: "檢視", canvas: "畫布", list: "清單", find: "尋找 instance", findShort: "尋找", found: "找到 {0} 個", foundOne: "找到 1 個", noMatch: "沒有符合的",
|
|
49
|
+
view: "檢視", canvas: "畫布", list: "清單", office: "辦公室", find: "尋找 instance", findShort: "尋找", found: "找到 {0} 個", foundOne: "找到 1 個", noMatch: "沒有符合的",
|
|
43
50
|
zoomIn: "放大", zoomOut: "縮小", fit: "符合畫面",
|
|
44
51
|
label: "組織圖畫布。用 Tab 或方向鍵在 instance 之間移動,Enter 開啟聊天,+ 和 − 縮放,0 顯示整個 fleet。",
|
|
45
52
|
expand: "展開", collapse: "收合", members: "{0} 名成員", member: "1 名成員", inFolded: "找到 {0} 個 · 展開", noMembers: "沒有成員",
|
|
46
53
|
openChat: "開啟聊天", minimap: "總覽:點一下移到那裡",
|
|
47
54
|
live: "即時", liveOn: "隱藏即時往來", liveOff: "顯示即時往來", lgTask: "delegate_task", lgSend: "send_to_instance",
|
|
48
55
|
lgReport: "report_result", lgBroadcast: "broadcast", lgQueued: "排隊中", lgFading: "已送達", lgTeam: "team 之間", legend: "圖例",
|
|
56
|
+
lgWork: "進行中(直到回報)", lgReturn: "完成(回報送回)", lgStale: "尚未回報",
|
|
49
57
|
},
|
|
50
58
|
});
|
|
51
59
|
const tc = (k, ...v) => t(`orgc.${k}`, ...v);
|
|
@@ -84,7 +92,8 @@ export function zoomAt(v, f, cx, cy) {
|
|
|
84
92
|
// ── Per device ──
|
|
85
93
|
|
|
86
94
|
const MODE_KEY = "agend_org_mode", FOLD_KEY = "agend_org_folded", LIVE_KEY = "agend_org_live", KEY_KEY = "agend_org_key";
|
|
87
|
-
|
|
95
|
+
const MODES = ["canvas", "list", "office"];
|
|
96
|
+
function readMode() { try { const m = localStorage.getItem(MODE_KEY); return MODES.includes(m) ? m : "canvas"; } catch { return "canvas"; } }
|
|
88
97
|
function readLive() { try { return localStorage.getItem(LIVE_KEY) !== "0"; } catch { return true; } }
|
|
89
98
|
function readFolded() {
|
|
90
99
|
try { const a = JSON.parse(localStorage.getItem(FOLD_KEY) || "[]"); return new Set(Array.isArray(a) ? a.filter((x) => typeof x === "string").slice(0, 500) : []); } catch { return new Set(); }
|
|
@@ -112,8 +121,6 @@ export function clipText(s, n) {
|
|
|
112
121
|
return `${out}…`;
|
|
113
122
|
}
|
|
114
123
|
const clip = clipText;
|
|
115
|
-
const needle = (q) => String(q || "").trim().toLowerCase();
|
|
116
|
-
const hits = (node, q) => !!q && (node.name.toLowerCase().includes(q) || (!!node.i && typeof node.i.display_name === "string" && node.i.display_name.toLowerCase().includes(q)));
|
|
117
124
|
|
|
118
125
|
function Face({ it, name, cx, cy, r }) {
|
|
119
126
|
const a = it ? avatarOf(it) : { kind: "initial", text: firstCharacter(name) };
|
|
@@ -130,10 +137,8 @@ function Face({ it, name, cx, cy, r }) {
|
|
|
130
137
|
|
|
131
138
|
function Card({ c, lead, cls, onOpen }) {
|
|
132
139
|
const n = c.node, it = n.i;
|
|
133
|
-
const
|
|
140
|
+
const { primary, sub, full } = nodeText(n);
|
|
134
141
|
const id = it ? identityOf(it) : null;
|
|
135
|
-
const sub = it ? `${STATE_LABEL(n.state)} · ${backendLabel(it.backend)}` : STATE_LABEL(n.state);
|
|
136
|
-
const full = `${names.primary}${names.secondary ? ` (${names.secondary})` : ""} — ${sub}`;
|
|
137
142
|
const cy = c.h / 2;
|
|
138
143
|
return html`<g class=${`oc-node st-${n.state}${lead ? " lead" : ""}${cls ? ` ${cls}` : ""} ${identityClasses(id)}`} ref=${(el) => paintIdentity(el, id)}
|
|
139
144
|
transform=${`translate(${c.x} ${c.y})`} data-name=${n.name} data-key=${c.key} tabindex="0" role=${it ? "link" : "img"}
|
|
@@ -143,19 +148,36 @@ function Card({ c, lead, cls, onOpen }) {
|
|
|
143
148
|
<rect class="oc-idbar" x="0" y="8" width="4" height=${c.h - 16} rx="2" />
|
|
144
149
|
<${Face} it=${it} name=${n.name} cx=${26} cy=${cy} r=${16} />
|
|
145
150
|
<circle class=${`oc-dot st-${n.state}`} cx=${38} cy=${cy + 12} r=${5} />
|
|
146
|
-
<text class="oc-name" x=${50} y=${cy - 4}>${clip(
|
|
151
|
+
<text class="oc-name" x=${50} y=${cy - 4}>${clip(primary, lead ? 20 : 15)}</text>
|
|
147
152
|
<text class="oc-sub" x=${50} y=${cy + 13}><tspan class=${`oc-st st-${n.state}`}>${clip(sub, lead ? 27 : 20)}</tspan></text>
|
|
148
153
|
</g>`;
|
|
149
154
|
}
|
|
150
155
|
|
|
151
|
-
function
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
+
function teamName(b) { return b.name === null ? t("org.unteamed") : b.name; }
|
|
157
|
+
const foundIn = (b, q) => (q ? b.nodes.filter((n) => hits(n, q)).length : 0);
|
|
158
|
+
|
|
159
|
+
/** A team's box: its frame, header band and (folded) summary — under the traffic lines. */
|
|
160
|
+
function TeamBox({ b, q }) {
|
|
161
|
+
const found = foundIn(b, q);
|
|
156
162
|
return html`<g class=${`oc-team${b.loose ? " loose" : ""}${q && !found ? " dim" : ""}`} data-team=${b.key}>
|
|
157
163
|
<rect class=${`oc-box${b.folded && found ? " match" : ""}`} x=${b.x} y=${b.y} width=${b.w} height=${b.h} rx="12" />
|
|
158
164
|
<rect class="oc-head" x=${b.x + 1} y=${b.y + 1} width=${b.w - 2} height=${OC.HEAD - 2} rx="11" />
|
|
165
|
+
${!b.nodes.length ? html`<text class="oc-team-sum" x=${b.x + 14} y=${b.y + OC.HEAD + 18}>${tc("noMembers")}</text>` : null}
|
|
166
|
+
${b.folded ? b.summary.flatMap((row, i) => row.map((it) => html`<g key=${it.s}>
|
|
167
|
+
<circle class=${`oc-dot st-${it.s}`} cx=${b.x + it.dx + 5} cy=${b.y + OC.HEAD + 14 + i * SUM_LINE} r="5" />
|
|
168
|
+
<text class="oc-team-sum" x=${b.x + it.dx + 14} y=${b.y + OC.HEAD + 18 + i * SUM_LINE}>${it.label}</text></g>`)) : null}
|
|
169
|
+
</g>`;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* A team's header: the fold control, its name and count — above the traffic lines (#1918 review: a line leaving the box
|
|
174
|
+
* through its header ran over the count), so it stays readable and clickable.
|
|
175
|
+
*/
|
|
176
|
+
function TeamHead({ b, q, onFold }) {
|
|
177
|
+
const name = teamName(b), found = foundIn(b, q);
|
|
178
|
+
const count = b.nodes.length === 1 ? tc("member") : tc("members", b.nodes.length);
|
|
179
|
+
const toggle = (e) => { if (e.type === "click" || e.key === "Enter" || e.key === " ") { e.preventDefault(); e.stopPropagation(); onFold(b.key); } };
|
|
180
|
+
return html`<g class=${`oc-team-head${q && !found ? " dim" : ""}`} data-team=${b.key}>
|
|
159
181
|
<g class=${`oc-toggle${b.nodes.length ? "" : " empty"}`} tabindex=${b.nodes.length ? "0" : undefined} role=${b.nodes.length ? "button" : undefined}
|
|
160
182
|
aria-expanded=${b.nodes.length ? String(!b.folded) : undefined} aria-label=${`${name}, ${count}.${b.nodes.length ? ` ${b.folded ? tc("expand") : tc("collapse")}.` : ""}`}
|
|
161
183
|
onClick=${b.nodes.length ? toggle : undefined} onKeyDown=${b.nodes.length ? toggle : undefined}>
|
|
@@ -164,40 +186,61 @@ function TeamBox({ b, q, onFold }) {
|
|
|
164
186
|
<text class="oc-team-name" x=${b.x + (b.nodes.length ? 28 : 14)} y=${b.y + 22}>${clip(name, Math.max(8, Math.floor((b.w - 90) / 7.5)))}</text>
|
|
165
187
|
<text class="oc-team-meta" x=${b.x + b.w - 12} y=${b.y + 22} text-anchor="end">${b.folded && found ? tc("inFolded", found) : String(b.nodes.length)}</text>
|
|
166
188
|
</g>
|
|
167
|
-
${!b.nodes.length ? html`<text class="oc-team-sum" x=${b.x + 14} y=${b.y + OC.HEAD + 18}>${tc("noMembers")}</text>` : null}
|
|
168
|
-
${b.folded ? b.summary.flatMap((row, i) => row.map((it) => html`<g key=${it.s}>
|
|
169
|
-
<circle class=${`oc-dot st-${it.s}`} cx=${b.x + it.dx + 5} cy=${b.y + OC.HEAD + 14 + i * SUM_LINE} r="5" />
|
|
170
|
-
<text class="oc-team-sum" x=${b.x + it.dx + 14} y=${b.y + OC.HEAD + 18 + i * SUM_LINE}>${it.label}</text></g>`)) : null}
|
|
171
189
|
</g>`;
|
|
172
190
|
}
|
|
173
191
|
|
|
192
|
+
/** What a card (or an Office desk) opens: that instance's chat. */
|
|
193
|
+
const openChat = (name) => navigate(chatPath(name));
|
|
194
|
+
|
|
174
195
|
/** Every card, in the order Tab walks them (General, then each team's members in reading order). */
|
|
175
196
|
const cardsOf = (L) => [...L.tops, ...L.boxes.flatMap((b) => b.cells)];
|
|
176
197
|
|
|
177
198
|
const reducedMotion = () => typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
178
199
|
|
|
179
|
-
/**
|
|
200
|
+
/**
|
|
201
|
+
* The traffic lines: dotted while queued, a dash and a pulse while delivering, fading once delivered; a delegation's
|
|
202
|
+
* slow moving dash while its work is in progress, one pulse back when its report comes, a faint dash when none came;
|
|
203
|
+
* ×N on shared lines.
|
|
204
|
+
*/
|
|
205
|
+
const MARKER = (e) => (e.phase === "fading" || e.phase === "stale" ? "fading" : e.hue);
|
|
180
206
|
function TrafficLayer({ edges, q }) {
|
|
181
207
|
const still = reducedMotion();
|
|
182
208
|
return html`<g class="oc-flows" aria-hidden="true">${edges.map((e) => {
|
|
183
209
|
const dim = q && !e.names.some((n) => n.toLowerCase().includes(q));
|
|
184
|
-
return html`<g key=${e.key} class=${`oc-fl${dim ? " dim" : ""}`}>
|
|
210
|
+
return html`<g key=${e.key} class=${`oc-fl${dim ? " dim" : ""}`} data-routed=${e.routed ? "1" : undefined}>
|
|
185
211
|
<path class="oc-flow-halo" d=${e.d} />
|
|
186
|
-
<path class=${`oc-flow h-${e.hue} ph-${e.phase}`} d=${e.d}
|
|
212
|
+
<path class=${`oc-flow h-${e.hue} ph-${e.phase}`} d=${e.d} stroke-width=${e.w} marker-start=${`url(#oc-src-${MARKER(e)})`}
|
|
213
|
+
marker-end=${e.head ? `url(#oc-ah-${MARKER(e)})` : undefined} />
|
|
187
214
|
${e.phase === "live" && !still ? html`<circle class=${`oc-pulse h-${e.hue}`} r="4"><animateMotion dur=${`${Math.max(1.6, e.pts.length * 0.3)}s`} repeatCount="indefinite" path=${e.d} /></circle>` : null}
|
|
215
|
+
${e.phase === "return" && !still ? html`<circle class=${`oc-pulse h-${e.hue}`} r="5"><animateMotion dur="1.6s" repeatCount="1" fill="freeze" path=${e.d} /></circle>` : null}
|
|
188
216
|
${e.badge ? html`<g class="oc-badge" transform=${`translate(${e.badge.x - 14} ${e.badge.y - 10})`}><rect width="28" height="20" rx="10" /><text x="14" y="14" text-anchor="middle">${`×${e.n}`}</text></g>` : null}
|
|
189
217
|
</g>`;
|
|
190
218
|
})}</g>`;
|
|
191
219
|
}
|
|
192
220
|
const ARROWS = ["task", "send", "report", "broadcast", "team", "fading"];
|
|
221
|
+
/**
|
|
222
|
+
* The head (#2329), in a 10-unit box that is HEAD.LEN stroke widths each way: a slim swept triangle HEAD.WIDE across,
|
|
223
|
+
* its tip at x 10; the path ends HEAD.BACK stroke widths before the tip (refX), so the line's stroke ends inside it.
|
|
224
|
+
*/
|
|
225
|
+
const HEAD_HALF = (5 * HEAD.WIDE) / HEAD.LEN;
|
|
226
|
+
const HEAD_D = `M0 ${5 - HEAD_HALF} L10 5 L0 ${5 + HEAD_HALF} L2.5 5 z`;
|
|
227
|
+
const HEAD_REF_X = 10 - (10 * HEAD.BACK) / HEAD.LEN;
|
|
193
228
|
|
|
194
|
-
/**
|
|
229
|
+
/**
|
|
230
|
+
* The key to the lines (#2052): a **Key** toggle in the toolbar; open, its rows are a strip between the toolbar and the
|
|
231
|
+
* canvas — never over the canvas, so it covers no card (it used to sit in the canvas's bottom-left corner, over the
|
|
232
|
+
* team there at the opening view). Folded until the person opens it; kept per device.
|
|
233
|
+
*/
|
|
234
|
+
function readKeyOpen() { try { return localStorage.getItem(KEY_KEY) === "1"; } catch { return false; } }
|
|
235
|
+
function KeyToggle({ open, onToggle }) {
|
|
236
|
+
return html`<button type="button" class=${`btn btn-sm oc-key${open ? " on" : ""}`} aria-expanded=${open ? "true" : "false"} aria-controls="oc-legend"
|
|
237
|
+
onClick=${onToggle}>${tc("legend")}</button>`;
|
|
238
|
+
}
|
|
195
239
|
function Legend() {
|
|
196
|
-
const [open] = useState(() => { try { return localStorage.getItem(KEY_KEY) === "1"; } catch { return false; } });
|
|
197
240
|
const row = (cls, k) => html`<span class="oc-lg"><i class=${`oc-sw ${cls}`} aria-hidden="true"></i>${tc(k)}</span>`;
|
|
198
|
-
return html`<
|
|
241
|
+
return html`<div id="oc-legend" class="oc-legend" role="region" aria-label=${tc("legend")}>
|
|
199
242
|
<div class="oc-lg-rows">${row("h-task", "lgTask")}${row("h-send", "lgSend")}${row("h-report", "lgReport")}${row("h-broadcast", "lgBroadcast")}
|
|
200
|
-
${row("ph-queued", "lgQueued")}${row("ph-fading", "lgFading")}</div></
|
|
243
|
+
${row("ph-queued", "lgQueued")}${row("ph-fading", "lgFading")}${row("h-task ph-work", "lgWork")}${row("h-report ph-return", "lgReturn")}${row("ph-stale", "lgStale")}</div></div>`;
|
|
201
244
|
}
|
|
202
245
|
|
|
203
246
|
/**
|
|
@@ -212,11 +255,13 @@ function useTraffic(lease, on) {
|
|
|
212
255
|
if (!on || !lease) return undefined;
|
|
213
256
|
const bump = () => setRev((n) => n + 1);
|
|
214
257
|
const read = async () => {
|
|
258
|
+
// What the stream had said when this was asked for: a stream event after it makes the answer possibly older.
|
|
259
|
+
const since = store.streamRev();
|
|
215
260
|
try {
|
|
216
261
|
const r = await lease.fetch("/ui/traffic", { method: "GET", headers: { "Content-Type": "application/json" } });
|
|
217
262
|
if (!lease.current() || !r.ok) return;
|
|
218
263
|
const d = await r.json();
|
|
219
|
-
if (lease.current() && store.load(d)) bump();
|
|
264
|
+
if (lease.current() && store.load(d, undefined, since)) bump();
|
|
220
265
|
} catch { /* the next poll, or the stream, brings it */ }
|
|
221
266
|
};
|
|
222
267
|
void read();
|
|
@@ -226,6 +271,7 @@ function useTraffic(lease, on) {
|
|
|
226
271
|
const offs = [];
|
|
227
272
|
if (sub) {
|
|
228
273
|
offs.push(lease.hold(sub("traffic", (item) => { if (store.apply(item)) bump(); })));
|
|
274
|
+
offs.push(lease.hold(sub("delegation", (d) => { if (store.delegation(d)) bump(); })));
|
|
229
275
|
offs.push(lease.hold(sub("connection", (c) => { if (c === "live") void read(); })));
|
|
230
276
|
}
|
|
231
277
|
const hs = [
|
|
@@ -237,6 +283,32 @@ function useTraffic(lease, on) {
|
|
|
237
283
|
return useMemo(() => (on ? store.items() : []), [rev, on]);
|
|
238
284
|
}
|
|
239
285
|
|
|
286
|
+
/**
|
|
287
|
+
* #2182: the traffic lines, routed around the canvas by libavoid in a worker (fleet-route.js) once it answers; until
|
|
288
|
+
* then, and zoomed out (one line per team pair), along the lanes (fleet-traffic.js route()). An answer is kept while the
|
|
289
|
+
* layout it was routed on is the one drawn: a line it has not seen yet takes its lane until the next answer.
|
|
290
|
+
*/
|
|
291
|
+
let routeClient = null;
|
|
292
|
+
function useTrafficRoutes(traffic, L, far) {
|
|
293
|
+
const lanes = useMemo(() => (traffic ? trafficEdges(traffic, L, { far }) : []), [traffic, L, far]);
|
|
294
|
+
const scene = useMemo(() => (far || !lanes.length ? null : routeScene(L, lanes)), [lanes, L, far]);
|
|
295
|
+
const [answer, setAnswer] = useState(null); // { shapes, map }
|
|
296
|
+
// The layout as the router sees it: a status frame re-making the same layout keeps the answer (and asks nothing).
|
|
297
|
+
const shapes = scene ? JSON.stringify(scene.shapes) : null;
|
|
298
|
+
const ask = scene && scene.conns.length ? JSON.stringify(scene) : null;
|
|
299
|
+
useEffect(() => {
|
|
300
|
+
if (!ask) return undefined;
|
|
301
|
+
routeClient ??= createRouteClient();
|
|
302
|
+
if (!routeClient.available) return undefined;
|
|
303
|
+
let live = true;
|
|
304
|
+
routeClient.route(JSON.parse(ask)).then((map) => { if (live && map) setAnswer({ shapes, map }); });
|
|
305
|
+
return () => { live = false; };
|
|
306
|
+
}, [ask]);
|
|
307
|
+
useEffect(() => () => { routeClient?.close(); routeClient = null; }, []);
|
|
308
|
+
return useMemo(() => (answer && answer.shapes === shapes && traffic ? trafficEdges(traffic, L, { far, routed: answer.map }) : lanes),
|
|
309
|
+
[lanes, answer, shapes, L, far, traffic]);
|
|
310
|
+
}
|
|
311
|
+
|
|
240
312
|
/** The canvas body: `view` buildOrgView's answer; `folded` the folded teams' keys; `q` the search needle; `traffic` the live items (null: Live is off). */
|
|
241
313
|
function Canvas({ view, folded, onFold, q, jump, traffic }) {
|
|
242
314
|
const [narrow] = useState(() => typeof matchMedia === "function" && matchMedia("(max-width: 640px)").matches);
|
|
@@ -276,7 +348,7 @@ function Canvas({ view, folded, onFold, q, jump, traffic }) {
|
|
|
276
348
|
vp.current = narrow ? fitView(openingRegion(L), size(), { margin: 12, minK: 0.75 }) : fitView(whole(), size(), { widthOnly: true, maxK: 1, minK: 0.6 });
|
|
277
349
|
setFar(vp.current.k < FAR_K);
|
|
278
350
|
}, []);
|
|
279
|
-
const edges =
|
|
351
|
+
const edges = useTrafficRoutes(traffic, L, far);
|
|
280
352
|
// Preact owns the markup, not the transform: put it back after every render.
|
|
281
353
|
useLayoutEffect(apply);
|
|
282
354
|
// A search's Enter: the first match, unfolded (by the panel) and then brought into view — once. It waits for the
|
|
@@ -291,7 +363,7 @@ function Canvas({ view, folded, onFold, q, jump, traffic }) {
|
|
|
291
363
|
if (!L.boxes.some((b) => b.folded && b.nodes.some((n) => n.name === j.name))) pendingJump.current = null; // gone: nothing to wait for
|
|
292
364
|
});
|
|
293
365
|
|
|
294
|
-
const open =
|
|
366
|
+
const open = openChat;
|
|
295
367
|
// The click that ends a drag or a pinch opens nothing and folds nothing.
|
|
296
368
|
const onClickCapture = (e) => { if (drag.current.swallow) { e.preventDefault(); e.stopPropagation(); } };
|
|
297
369
|
const onWheel = (e) => {
|
|
@@ -377,21 +449,21 @@ function Canvas({ view, folded, onFold, q, jump, traffic }) {
|
|
|
377
449
|
<svg ref=${svgRef} class="oc-svg" role="application" tabindex="0" aria-label=${tc("label")} onWheel=${onWheel} onPointerDown=${onPointerDown}
|
|
378
450
|
onPointerMove=${onPointerMove} onPointerUp=${onPointerUp} onPointerCancel=${onPointerUp} onKeyDown=${onKeyDown} onFocusIn=${onFocusIn} onClickCapture=${onClickCapture}>
|
|
379
451
|
<defs><clipPath id="oc-clip-av" clipPathUnits="objectBoundingBox"><circle cx="0.5" cy="0.5" r="0.5" /></clipPath>
|
|
380
|
-
${ARROWS.map((a) => html`<marker key=${a} id=${`oc-ah-${a}`} viewBox="0 0 10 10" refX
|
|
381
|
-
<path d
|
|
382
|
-
${ARROWS.map((a) => html`<marker key=${`s-${a}`} id=${`oc-src-${a}`} viewBox="0 0 10 10" refX="5" refY="5" markerWidth
|
|
383
|
-
<circle cx="5" cy="5" r="
|
|
452
|
+
${ARROWS.map((a) => html`<marker key=${a} id=${`oc-ah-${a}`} viewBox="0 0 10 10" refX=${HEAD_REF_X} refY="5" markerWidth=${HEAD.LEN} markerHeight=${HEAD.LEN} orient="auto">
|
|
453
|
+
<path d=${HEAD_D} class=${`oc-ah h-${a}`} /></marker>`)}
|
|
454
|
+
${ARROWS.map((a) => html`<marker key=${`s-${a}`} id=${`oc-src-${a}`} viewBox="0 0 10 10" refX="5" refY="5" markerWidth=${HEAD.DOT} markerHeight=${HEAD.DOT}>
|
|
455
|
+
<circle cx="5" cy="5" r="5" class=${`oc-ah h-${a}`} /></marker>`)}</defs>
|
|
384
456
|
<g ref=${worldRef} class="oc-world">
|
|
385
457
|
<g class="oc-tree">${L.tree.map((d, i) => html`<path key=${i} d=${d} />`)}</g>
|
|
386
|
-
<g class="oc-teams">${L.boxes.map((b) => html`<${TeamBox} key=${b.key} b=${b} q=${q}
|
|
458
|
+
<g class="oc-teams">${L.boxes.map((b) => html`<${TeamBox} key=${b.key} b=${b} q=${q} />`)}</g>
|
|
387
459
|
<${TrafficLayer} edges=${edges} q=${q} />
|
|
460
|
+
<g class="oc-heads">${L.boxes.map((b) => html`<${TeamHead} key=${b.key} b=${b} q=${q} onFold=${onFold} />`)}</g>
|
|
388
461
|
<g class="oc-cards">
|
|
389
462
|
${L.tops.map((c) => html`<${Card} key=${c.key} c=${c} lead=${true} cls=${q ? (hits(c.node, q) ? "match" : "dim") : ""} onOpen=${open} />`)}
|
|
390
463
|
${L.boxes.flatMap((b) => b.cells.map((c) => html`<${Card} key=${c.key} c=${c} lead=${false} cls=${q ? (hits(c.node, q) ? "match" : "dim") : ""} onOpen=${open} />`))}
|
|
391
464
|
</g>
|
|
392
465
|
</g>
|
|
393
466
|
</svg>
|
|
394
|
-
${traffic ? html`<${Legend} />` : null}
|
|
395
467
|
<div class="oc-zoom" role="group" aria-label=${tc("view")}>
|
|
396
468
|
<button type="button" class="icon-btn" aria-label=${tc("zoomIn")} title=${tc("zoomIn")} onClick=${() => zoomBy(1.25)}><${Icon} name="plus" size=${16} /></button>
|
|
397
469
|
<button type="button" class="icon-btn" aria-label=${tc("zoomOut")} title=${tc("zoomOut")} onClick=${() => zoomBy(0.8)}><span aria-hidden="true">−</span></button>
|
|
@@ -469,21 +541,26 @@ export function OrgCanvas({ org, app, lease }) {
|
|
|
469
541
|
if (holder && folded.has(holder[0])) onFold(holder[0]);
|
|
470
542
|
setJump({ name: first.name, at: Date.now() });
|
|
471
543
|
};
|
|
544
|
+
const [keyOpen, setKeyOpen] = useState(readKeyOpen);
|
|
545
|
+
const toggleKey = () => setKeyOpen((v) => { save(KEY_KEY, v ? "0" : "1"); return !v; });
|
|
472
546
|
const modeBtn = (m) => html`<button type="button" class=${`btn btn-sm${mode === m ? " btn-primary" : ""}`} aria-pressed=${mode === m ? "true" : "false"}
|
|
473
547
|
onClick=${() => setMode(m)}>${tc(m)}</button>`;
|
|
474
548
|
return html`<div class=${`org oc oc-${mode}`}>
|
|
475
549
|
<div class="list-head org-head oc-bar">
|
|
476
550
|
<span>${view.total === 1 ? t("org.instance") : t("org.instances", view.total)}</span><${OrgSummary} counts=${view.counts} />
|
|
477
551
|
<div class="oc-tools">
|
|
478
|
-
${mode
|
|
552
|
+
${mode !== "list" ? html`<label class="s-search oc-find"><${Icon} name="search" size=${14} /><span class="sr-only">${tc("find")}</span>
|
|
479
553
|
<input type="search" value=${query} placeholder=${tc("findShort")} autocomplete="off" onInput=${(e) => setQuery(e.target.value)} onKeyDown=${onFind} />
|
|
480
554
|
${q ? html`<span class="oc-found" role="status">${found ? (found === 1 ? tc("foundOne") : tc("found", found)) : tc("noMatch")}</span>` : null}</label>` : null}
|
|
555
|
+
${mode !== "list" && live ? html`<${KeyToggle} open=${keyOpen} onToggle=${toggleKey} />` : null}
|
|
481
556
|
<button type="button" class=${`btn btn-sm oc-live${live ? " on" : ""}`} aria-pressed=${live ? "true" : "false"} title=${live ? tc("liveOn") : tc("liveOff")}
|
|
482
557
|
onClick=${() => setLive((v) => !v)}><span class="oc-live-dot" aria-hidden="true"></span>${tc("live")}</button>
|
|
483
|
-
<div class="seg-inline" role="group" aria-label=${tc("view")}>${modeBtn("canvas")}${modeBtn("list")}</div>
|
|
558
|
+
<div class="seg-inline" role="group" aria-label=${tc("view")}>${modeBtn("canvas")}${modeBtn("list")}${modeBtn("office")}</div>
|
|
484
559
|
</div>
|
|
485
560
|
</div>
|
|
561
|
+
${mode !== "list" && live && keyOpen ? html`<${Legend} />` : null}
|
|
486
562
|
${mode === "list" ? html`<${OrgChart} org=${org} app=${app} bare=${true} sending=${sending} />`
|
|
563
|
+
: mode === "office" ? html`<${Office} view=${view} traffic=${live ? traffic : null} q=${q} lease=${lease} onOpen=${openChat} />`
|
|
487
564
|
: html`<${Canvas} view=${view} folded=${folded} onFold=${onFold} q=${q} jump=${jump} traffic=${live ? traffic : null} />`}
|
|
488
565
|
</div>`;
|
|
489
566
|
}
|