@songsid/agend 2.3.0-beta.9 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -8
- package/README.zh-TW.md +16 -8
- package/dist/adapter-world.js.map +1 -1
- package/dist/agend-home.d.ts +5 -0
- package/dist/agend-home.js +7 -0
- package/dist/agend-home.js.map +1 -0
- package/dist/agent-cli-instructions.md +7 -1
- package/dist/agent-cli.js +41 -0
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.d.ts +9 -0
- package/dist/agent-endpoint.js +23 -0
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-file-read.js +1 -1
- package/dist/agent-file-read.js.map +1 -1
- package/dist/agent-whats-new.d.ts +16 -0
- package/dist/agent-whats-new.js +53 -12
- package/dist/agent-whats-new.js.map +1 -1
- package/dist/apply-job.js.map +1 -1
- package/dist/atomic-write.js.map +1 -1
- package/dist/auth-api.d.ts +12 -0
- package/dist/auth-api.js +77 -22
- package/dist/auth-api.js.map +1 -1
- package/dist/authority/authority-state.d.ts +4 -0
- package/dist/authority/authority-state.js +17 -8
- package/dist/authority/authority-state.js.map +1 -1
- package/dist/authority/session-authorizations.js.map +1 -1
- package/dist/authority/web-authority.d.ts +16 -8
- package/dist/authority/web-authority.js +19 -5
- package/dist/authority/web-authority.js.map +1 -1
- package/dist/backend/antigravity.d.ts +2 -2
- package/dist/backend/antigravity.js +2 -1
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-code.js +13 -4
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/codex-metadata.d.ts +8 -0
- package/dist/backend/codex-metadata.js +74 -17
- package/dist/backend/codex-metadata.js.map +1 -1
- package/dist/backend/codex-package.d.ts +30 -0
- package/dist/backend/codex-package.js +133 -0
- package/dist/backend/codex-package.js.map +1 -0
- package/dist/backend/codex-session-lookup.js.map +1 -1
- package/dist/backend/codex.d.ts +2 -0
- package/dist/backend/codex.js +25 -5
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/credential-profile.d.ts +2 -0
- package/dist/backend/credential-profile.js +2 -0
- package/dist/backend/credential-profile.js.map +1 -1
- package/dist/backend/effort-metadata.js.map +1 -1
- package/dist/backend/grok.js +58 -3
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro-engine-ledger.js.map +1 -1
- package/dist/backend/kiro-kas-store.js.map +1 -1
- package/dist/backend/kiro-v2-store.js.map +1 -1
- package/dist/backend/kiro-v3-identity.js.map +1 -1
- package/dist/backend/kiro.d.ts +9 -1
- package/dist/backend/kiro.js +102 -1
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/launch-effort.js.map +1 -1
- package/dist/backend/mock.js.map +1 -1
- package/dist/backend/muse.js.map +1 -1
- package/dist/backend/opencode-permission.js +1 -1
- package/dist/backend/opencode-permission.js.map +1 -1
- package/dist/backend/opencode.js +2 -1
- package/dist/backend/opencode.js.map +1 -1
- package/dist/backend/session-signals.js.map +1 -1
- package/dist/backend-availability.js.map +1 -1
- package/dist/backend-command.d.ts +2 -0
- package/dist/backend-command.js +3 -1
- package/dist/backend-command.js.map +1 -1
- package/dist/backend-outage.js.map +1 -1
- package/dist/binary-probe.js +1 -1
- package/dist/binary-probe.js.map +1 -1
- package/dist/bug-report-cli.d.ts +30 -0
- package/dist/bug-report-cli.js +139 -0
- package/dist/bug-report-cli.js.map +1 -0
- package/dist/bug-report.d.ts +47 -0
- package/dist/bug-report.js +137 -0
- package/dist/bug-report.js.map +1 -0
- package/dist/bundled-skills.d.ts +18 -0
- package/dist/bundled-skills.js +38 -0
- package/dist/bundled-skills.js.map +1 -0
- package/dist/cache-service.js +1 -1
- package/dist/cache-service.js.map +1 -1
- package/dist/channel/adapters/discord-client-retirement.d.ts +5 -0
- package/dist/channel/adapters/discord-client-retirement.js +57 -0
- package/dist/channel/adapters/discord-client-retirement.js.map +1 -0
- package/dist/channel/adapters/discord.d.ts +4 -0
- package/dist/channel/adapters/discord.js +57 -12
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +6 -0
- package/dist/channel/adapters/telegram.js +54 -14
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/mcp-server.js +21 -4
- package/dist/channel/mcp-server.js.map +1 -1
- package/dist/channel/mcp-tools.d.ts +3 -1
- package/dist/channel/mcp-tools.js +41 -4
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/message-queue.js.map +1 -1
- package/dist/channel/sticker-download.js.map +1 -1
- package/dist/channel/tool-router.js.map +1 -1
- package/dist/child-process.d.ts +21 -0
- package/dist/child-process.js +54 -0
- package/dist/child-process.js.map +1 -0
- package/dist/classic-channel-manager.js +3 -2
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli-entry.js.map +1 -1
- package/dist/cli-flags.js.map +1 -1
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +443 -311
- package/dist/cli.js.map +1 -1
- package/dist/command-table.d.ts +1 -1
- package/dist/command-table.js +1 -1
- package/dist/command-table.js.map +1 -1
- package/dist/compact-watch.js.map +1 -1
- package/dist/completion-install.js.map +1 -1
- package/dist/completion.js.map +1 -1
- package/dist/config-validator.d.ts +6 -0
- package/dist/config-validator.js +81 -8
- package/dist/config-validator.js.map +1 -1
- package/dist/config.d.ts +15 -3
- package/dist/config.js +41 -10
- package/dist/config.js.map +1 -1
- package/dist/connection-secrets.js.map +1 -1
- package/dist/context-guardian.js.map +1 -1
- package/dist/coredump-filter.js.map +1 -1
- package/dist/cpu-profile.js.map +1 -1
- package/dist/cross-instance-envelope.js.map +1 -1
- package/dist/cross-instance-notice.d.ts +7 -0
- package/dist/cross-instance-notice.js +10 -0
- package/dist/cross-instance-notice.js.map +1 -1
- package/dist/daemon.d.ts +39 -1
- package/dist/daemon.js +234 -15
- package/dist/daemon.js.map +1 -1
- package/dist/daily-summary.js.map +1 -1
- package/dist/darwin-memory.js +1 -1
- package/dist/darwin-memory.js.map +1 -1
- package/dist/dashboard-live.d.ts +8 -0
- package/dist/dashboard-live.js +35 -0
- package/dist/dashboard-live.js.map +1 -0
- package/dist/dashboard-permissions.d.ts +69 -0
- package/dist/dashboard-permissions.js +138 -0
- package/dist/dashboard-permissions.js.map +1 -0
- package/dist/decision-list.js.map +1 -1
- package/dist/delivery-consumed-watch.js.map +1 -1
- package/dist/delivery-outbox.js +5 -0
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/delivery-outbox.test.js.map +1 -1
- package/dist/delivery-reconciliation.test.js.map +1 -1
- package/dist/diagnostic-redaction.d.ts +10 -0
- package/dist/diagnostic-redaction.js +167 -0
- package/dist/diagnostic-redaction.js.map +1 -0
- package/dist/doctor.d.ts +8 -0
- package/dist/doctor.js +52 -0
- package/dist/doctor.js.map +1 -1
- package/dist/e2e-isolation.js.map +1 -1
- package/dist/event-log.js.map +1 -1
- package/dist/export-import.js +7 -5
- package/dist/export-import.js.map +1 -1
- package/dist/fleet-control-audit.js.map +1 -1
- package/dist/fleet-label.js.map +1 -1
- package/dist/fleet-level-config.d.ts +1 -1
- package/dist/fleet-level-config.js +2 -0
- package/dist/fleet-level-config.js.map +1 -1
- package/dist/fleet-lock.js +3 -2
- package/dist/fleet-lock.js.map +1 -1
- package/dist/fleet-manager.d.ts +249 -13
- package/dist/fleet-manager.js +1561 -292
- package/dist/fleet-manager.js.map +1 -1
- package/dist/fleet-process-handlers.d.ts +18 -0
- package/dist/fleet-process-handlers.js +70 -0
- package/dist/fleet-process-handlers.js.map +1 -0
- package/dist/fleet-startup.d.ts +14 -0
- package/dist/fleet-startup.js +30 -0
- package/dist/fleet-startup.js.map +1 -0
- package/dist/fleet-traffic.js.map +1 -1
- package/dist/forged-envelope-scan.d.ts +0 -20
- package/dist/forged-envelope-scan.js +3 -2
- package/dist/forged-envelope-scan.js.map +1 -1
- package/dist/full-restart.d.ts +5 -5
- package/dist/full-restart.js +5 -5
- package/dist/full-restart.js.map +1 -1
- package/dist/general-knowledge/skills/bug-report/SKILL.md +31 -0
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +52 -11
- package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +5 -1
- package/dist/general-knowledge/skills/fleet-config/SKILL.md +3 -1
- package/dist/general-knowledge/skills/fleet-restart/SKILL.md +8 -9
- package/dist/general-knowledge/skills/multi-channel/SKILL.md +1 -1
- package/dist/general-knowledge/skills/persona-emoji/SKILL.md +1 -1
- package/dist/general-knowledge/skills/scheduling/SKILL.md +4 -0
- package/dist/general-knowledge/skills/web-appearance/SKILL.canvas-worker-off.md +321 -0
- package/dist/general-knowledge/skills/web-appearance/SKILL.md +24 -4
- package/dist/general-knowledge/skills/web-dashboard/SKILL.canvas-worker-off.md +553 -0
- package/dist/general-knowledge/skills/web-dashboard/SKILL.md +154 -31
- package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +1 -1
- package/dist/general-knowledge/steering/core-rules.md +1 -1
- package/dist/host-memory.js.map +1 -1
- package/dist/idle-gate-log.d.ts +19 -0
- package/dist/idle-gate-log.js +15 -0
- package/dist/idle-gate-log.js.map +1 -0
- package/dist/instance-config-impact.js +25 -4
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +10 -1
- package/dist/instance-lifecycle.js +86 -25
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instructions.d.ts +12 -6
- package/dist/instructions.js +19 -10
- package/dist/instructions.js.map +1 -1
- package/dist/kiro-compact-pane.js.map +1 -1
- package/dist/kiro-db-reader.js.map +1 -1
- package/dist/kiro-engine-status.js.map +1 -1
- package/dist/kiro-log-gate.js.map +1 -1
- package/dist/kiro-transcript-lane.js.map +1 -1
- package/dist/locale.js +428 -20
- package/dist/locale.js.map +1 -1
- package/dist/log-service.js.map +1 -1
- package/dist/log-steps.d.ts +1 -0
- package/dist/log-steps.js +15 -0
- package/dist/log-steps.js.map +1 -1
- package/dist/logger.js +3 -2
- package/dist/logger.js.map +1 -1
- package/dist/login-controller.d.ts +45 -0
- package/dist/login-controller.js +101 -5
- package/dist/login-controller.js.map +1 -1
- package/dist/login-flows.js +1 -1
- package/dist/login-manager.js.map +1 -1
- package/dist/login-shell.js +3 -1
- package/dist/login-shell.js.map +1 -1
- package/dist/ls-attach-resolve.d.ts +96 -0
- package/dist/ls-attach-resolve.js +180 -0
- package/dist/ls-attach-resolve.js.map +1 -0
- package/dist/ls-rows.d.ts +12 -0
- package/dist/ls-rows.js +83 -4
- package/dist/ls-rows.js.map +1 -1
- package/dist/memory-pressure.js.map +1 -1
- package/dist/muse-usage-relay.js.map +1 -1
- package/dist/needs-you-hub.d.ts +98 -1
- package/dist/needs-you-hub.js +313 -44
- package/dist/needs-you-hub.js.map +1 -1
- package/dist/needs-you-live.d.ts +5 -2
- package/dist/needs-you-live.js +6 -3
- package/dist/needs-you-live.js.map +1 -1
- package/dist/needs-you.d.ts +68 -3
- package/dist/needs-you.js +38 -4
- package/dist/needs-you.js.map +1 -1
- package/dist/network-family.js.map +1 -1
- package/dist/operator-control-paths.js +3 -4
- package/dist/operator-control-paths.js.map +1 -1
- package/dist/outbound-handlers.d.ts +3 -0
- package/dist/outbound-handlers.js +76 -19
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +106 -60
- package/dist/outbound-schemas.js +33 -10
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/outbox-open-error.js.map +1 -1
- package/dist/pane-context-cache.js.map +1 -1
- package/dist/paths.js.map +1 -1
- package/dist/private-dir.js.map +1 -1
- package/dist/probe-worker-pool.js.map +1 -1
- package/dist/profile-control.js.map +1 -1
- package/dist/prompt-file-ref.js.map +1 -1
- package/dist/provider-probe.js.map +1 -1
- package/dist/provider-secret-registry.d.ts +5 -3
- package/dist/provider-secret-registry.js +8 -2
- package/dist/provider-secret-registry.js.map +1 -1
- package/dist/public-link-auto-open.d.ts +32 -0
- package/dist/public-link-auto-open.js +86 -0
- package/dist/public-link-auto-open.js.map +1 -0
- package/dist/public-link-owner.d.ts +10 -0
- package/dist/public-link-owner.js +36 -0
- package/dist/public-link-owner.js.map +1 -0
- package/dist/public-link-progress.d.ts +12 -1
- package/dist/public-link-progress.js +5 -10
- package/dist/public-link-progress.js.map +1 -1
- package/dist/public-preview.js.map +1 -1
- package/dist/public-tunnel-config.d.ts +11 -0
- package/dist/public-tunnel-config.js +68 -0
- package/dist/public-tunnel-config.js.map +1 -0
- package/dist/public-web-gateway.d.ts +2 -0
- package/dist/public-web-gateway.js +19 -6
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/public-web-link.d.ts +48 -3
- package/dist/public-web-link.js +177 -51
- package/dist/public-web-link.js.map +1 -1
- package/dist/quickstart-api.d.ts +9 -0
- package/dist/quickstart-api.js +82 -0
- package/dist/quickstart-api.js.map +1 -1
- package/dist/quickstart.d.ts +5 -0
- package/dist/quickstart.js +40 -25
- package/dist/quickstart.js.map +1 -1
- package/dist/reply-buttons-controller.js.map +1 -1
- package/dist/reply-dedup.js.map +1 -1
- package/dist/resource-report.js +1 -1
- package/dist/resource-report.js.map +1 -1
- package/dist/restart-guard.js.map +1 -1
- package/dist/restart-progress.d.ts +80 -1
- package/dist/restart-progress.js +306 -21
- package/dist/restart-progress.js.map +1 -1
- package/dist/rollout-index.js.map +1 -1
- package/dist/runtime-cpu-profile.js.map +1 -1
- package/dist/scheduler/db.d.ts +40 -13
- package/dist/scheduler/db.js +123 -89
- package/dist/scheduler/db.js.map +1 -1
- package/dist/scheduler/scheduler.js.map +1 -1
- package/dist/scheduler/task-board-text.d.ts +26 -0
- package/dist/scheduler/task-board-text.js +140 -0
- package/dist/scheduler/task-board-text.js.map +1 -0
- package/dist/scheduler/task-board.d.ts +730 -0
- package/dist/scheduler/task-board.js +2179 -0
- package/dist/scheduler/task-board.js.map +1 -0
- package/dist/scheduler/types.d.ts +6 -1
- package/dist/sd-notify.js +2 -1
- package/dist/sd-notify.js.map +1 -1
- package/dist/search/search-docs.d.ts +58 -0
- package/dist/search/search-docs.js +63 -0
- package/dist/search/search-docs.js.map +1 -0
- package/dist/search/search-index.d.ts +141 -0
- package/dist/search/search-index.js +440 -0
- package/dist/search/search-index.js.map +1 -0
- package/dist/search/search-store.d.ts +122 -0
- package/dist/search/search-store.js +236 -0
- package/dist/search/search-store.js.map +1 -0
- package/dist/search/search-worker.d.ts +1 -0
- package/dist/search/search-worker.js +163 -0
- package/dist/search/search-worker.js.map +1 -0
- package/dist/secret-file.js.map +1 -1
- package/dist/secret-store.d.ts +2 -0
- package/dist/secret-store.js +21 -0
- package/dist/secret-store.js.map +1 -1
- package/dist/service-installer.d.ts +75 -0
- package/dist/service-installer.js +206 -0
- package/dist/service-installer.js.map +1 -1
- package/dist/service-owner.d.ts +44 -0
- package/dist/service-owner.js +48 -0
- package/dist/service-owner.js.map +1 -0
- package/dist/service-plan.d.ts +39 -2
- package/dist/service-plan.js +188 -6
- package/dist/service-plan.js.map +1 -1
- package/dist/session-oom.d.ts +21 -0
- package/dist/session-oom.js +139 -0
- package/dist/session-oom.js.map +1 -0
- package/dist/settings-api.d.ts +13 -0
- package/dist/settings-api.js +73 -12
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-baseline.js.map +1 -1
- package/dist/settings-change.d.ts +5 -0
- package/dist/settings-change.js +167 -6
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-confirmation.d.ts +9 -1
- package/dist/settings-confirmation.js +18 -8
- package/dist/settings-confirmation.js.map +1 -1
- package/dist/settings-control.js +2 -1
- package/dist/settings-control.js.map +1 -1
- package/dist/settings-effect.js +29 -4
- package/dist/settings-effect.js.map +1 -1
- package/dist/settings-http-confirmation.d.ts +13 -0
- package/dist/settings-http-confirmation.js +15 -3
- package/dist/settings-http-confirmation.js.map +1 -1
- package/dist/settings-instance-patch.js +13 -1
- package/dist/settings-instance-patch.js.map +1 -1
- package/dist/settings-request-capability.d.ts +4 -1
- package/dist/settings-request-capability.js +11 -3
- package/dist/settings-request-capability.js.map +1 -1
- package/dist/settings-transaction.js.map +1 -1
- package/dist/setup-auth.d.ts +1 -0
- package/dist/setup-auth.js +2 -1
- package/dist/setup-auth.js.map +1 -1
- package/dist/setup-form.d.ts +1 -1
- package/dist/setup-form.js +23 -7
- package/dist/setup-form.js.map +1 -1
- package/dist/setup-host.d.ts +6 -1
- package/dist/setup-host.js +15 -4
- package/dist/setup-host.js.map +1 -1
- package/dist/setup-wizard.js +6 -3
- package/dist/setup-wizard.js.map +1 -1
- package/dist/spawn-gate.d.ts +5 -0
- package/dist/spawn-gate.js +28 -8
- package/dist/spawn-gate.js.map +1 -1
- package/dist/start-attempt.d.ts +1 -0
- package/dist/start-attempt.js +18 -0
- package/dist/start-attempt.js.map +1 -0
- package/dist/start-failure-notice.d.ts +4 -0
- package/dist/start-failure-notice.js +20 -0
- package/dist/start-failure-notice.js.map +1 -0
- package/dist/start-failure.d.ts +147 -0
- package/dist/start-failure.js +281 -0
- package/dist/start-failure.js.map +1 -0
- package/dist/startup-memory-deadline.d.ts +23 -0
- package/dist/startup-memory-deadline.js +55 -0
- package/dist/startup-memory-deadline.js.map +1 -0
- package/dist/statusline-watcher.js.map +1 -1
- package/dist/storm-window.js.map +1 -1
- package/dist/systemd-peer-bus.js.map +1 -1
- package/dist/target-queue-worker.js.map +1 -1
- package/dist/task-board-summary.d.ts +101 -0
- package/dist/task-board-summary.js +177 -0
- package/dist/task-board-summary.js.map +1 -0
- package/dist/task-board-tool.d.ts +25 -0
- package/dist/task-board-tool.js +155 -0
- package/dist/task-board-tool.js.map +1 -0
- package/dist/task-board-waker.d.ts +51 -0
- package/dist/task-board-waker.js +141 -0
- package/dist/task-board-waker.js.map +1 -0
- package/dist/tips.js.map +1 -1
- package/dist/tmux-control.js +1 -1
- package/dist/tmux-control.js.map +1 -1
- package/dist/tmux-exec-helper.d.ts +104 -0
- package/dist/tmux-exec-helper.js +412 -0
- package/dist/tmux-exec-helper.js.map +1 -0
- package/dist/tmux-manager.d.ts +1 -0
- package/dist/tmux-manager.js +29 -13
- package/dist/tmux-manager.js.map +1 -1
- package/dist/tmux-read.js +2 -2
- package/dist/tmux-read.js.map +1 -1
- package/dist/tool-permissions.js.map +1 -1
- package/dist/tool-progress.js.map +1 -1
- package/dist/topic-archiver.js.map +1 -1
- package/dist/topic-commands.d.ts +13 -0
- package/dist/topic-commands.js +56 -33
- package/dist/topic-commands.js.map +1 -1
- package/dist/topic-link.js.map +1 -1
- package/dist/transcript-delta-reader.js.map +1 -1
- package/dist/transcript-jsonl.js.map +1 -1
- package/dist/transcript-monitor.js +5 -0
- package/dist/transcript-monitor.js.map +1 -1
- package/dist/transcript-sources.d.ts +2 -0
- package/dist/transcript-sources.js +4 -0
- package/dist/transcript-sources.js.map +1 -1
- package/dist/tunnel/cloudflared-install.js +3 -1
- package/dist/tunnel/cloudflared-install.js.map +1 -1
- package/dist/tunnel/cloudflared.d.ts +7 -16
- package/dist/tunnel/cloudflared.js +100 -13
- package/dist/tunnel/cloudflared.js.map +1 -1
- package/dist/tunnel/lease.js +3 -2
- package/dist/tunnel/lease.js.map +1 -1
- package/dist/tunnel/manager.js.map +1 -1
- package/dist/tunnel/named-diagnostics.d.ts +13 -0
- package/dist/tunnel/named-diagnostics.js +52 -0
- package/dist/tunnel/named-diagnostics.js.map +1 -0
- package/dist/tunnel/public-fetch.js.map +1 -1
- package/dist/tunnel/purpose-lane.js.map +1 -1
- package/dist/tunnel/types.d.ts +4 -1
- package/dist/tunnel/types.js.map +1 -1
- package/dist/types.d.ts +55 -2
- package/dist/ui/app-effects.js +23 -5
- package/dist/ui/app.html +2 -0
- package/dist/ui/backend-signin.js +297 -0
- package/dist/ui/chat-effects.js +10 -3
- package/dist/ui/chat-msg-actions.js +176 -0
- package/dist/ui/chat-render.js +62 -18
- package/dist/ui/chat-store.js +218 -48
- package/dist/ui/chat-strings.js +40 -8
- package/dist/ui/chat-thread.js +119 -10
- package/dist/ui/effect-trial-offer.js +2 -31
- package/dist/ui/effects-waker.js +2 -0
- package/dist/ui/fleet-canvas-layout.js +13 -4
- package/dist/ui/fleet-canvas.js +69 -28
- package/dist/ui/fleet-office-editor.js +149 -0
- package/dist/ui/fleet-office-model.js +358 -0
- package/dist/ui/fleet-office-pack.js +199 -0
- package/dist/ui/fleet-office-skin.js +474 -0
- package/dist/ui/fleet-office-store.js +49 -0
- package/dist/ui/fleet-office-zones.js +177 -0
- package/dist/ui/fleet-office.js +434 -0
- package/dist/ui/fleet-org.js +18 -5
- package/dist/ui/fleet-route-scene.js +272 -0
- package/dist/ui/fleet-route-worker.js +21 -0
- package/dist/ui/fleet-route.js +88 -0
- package/dist/ui/fleet-task-card.js +436 -0
- package/dist/ui/fleet-task-common.js +482 -0
- package/dist/ui/fleet-task-work.js +107 -0
- package/dist/ui/fleet-tasks.js +569 -0
- package/dist/ui/fleet-traffic.js +81 -18
- package/dist/ui/fleet-usage.js +36 -2
- package/dist/ui/guest-refused.html +41 -0
- package/dist/ui/icons/icon-192.png +0 -0
- package/dist/ui/icons/icon-512.png +0 -0
- package/dist/ui/image-lightbox.js +45 -1
- package/dist/ui/image-zoom.js +242 -0
- package/dist/ui/panel-chat.js +200 -56
- package/dist/ui/panel-details.js +2 -0
- package/dist/ui/panel-fleet.js +32 -71
- package/dist/ui/panel-needs.js +23 -6
- package/dist/ui/panel-settings.js +158 -32
- package/dist/ui/preview-panel.js +2 -1
- package/dist/ui/search-dialog.js +350 -0
- package/dist/ui/settings-appearance.js +170 -10
- package/dist/ui/settings-apply.js +3 -3
- package/dist/ui/settings-confirm.js +7 -2
- package/dist/ui/settings-dialogs.js +46 -21
- package/dist/ui/settings-discord.js +6 -2
- package/dist/ui/settings-guests.js +2 -1
- package/dist/ui/settings-learn.js +1 -0
- package/dist/ui/settings-model.js +51 -18
- package/dist/ui/settings-mods.js +8 -3
- package/dist/ui/settings-owner-effects.js +6 -4
- package/dist/ui/settings-strings.js +180 -6
- package/dist/ui/settings-token.js +3 -1
- package/dist/ui/settings-web-authority.js +13 -5
- package/dist/ui/settings-wizard.js +13 -7
- package/dist/ui/shared/agend-auth.js +2 -0
- package/dist/ui/shared/app-i18n.js +12 -5
- package/dist/ui/shared/app-needs.js +2 -2
- package/dist/ui/shared/app-prefs.js +15 -0
- package/dist/ui/shared/app-route.js +18 -0
- package/dist/ui/shared/app-shell.js +172 -28
- package/dist/ui/shared/app-store.js +3 -2
- package/dist/ui/shared/app-stream.js +5 -1
- package/dist/ui/shared/app-themes.js +116 -1
- package/dist/ui/shared/app.css +662 -48
- package/dist/ui/shared/app.js +9 -1
- package/dist/ui/shared/card-strings.js +4 -0
- package/dist/ui/shared/effect-app-runtime.js +7 -5
- package/dist/ui/shared/effect-chat-runtime.js +2 -7
- package/dist/ui/shared/effect-cursor.js +3 -2
- package/dist/ui/shared/effect-display-metadata.js +39 -0
- package/dist/ui/shared/effect-owner-source.js +8 -1
- package/dist/ui/shared/effect-registry.js +14 -4
- package/dist/ui/shared/effect-runtime-loader.js +3 -1
- package/dist/ui/shared/effect-stock-trust.js +5 -5
- package/dist/ui/shared/feature-flags.js +127 -0
- package/dist/ui/shared/guest-refused.js +35 -0
- package/dist/ui/shared/header-tools.js +2 -2
- package/dist/ui/shared/identity-card.js +26 -8
- package/dist/ui/shared/identity-color.js +17 -10
- package/dist/ui/shared/instance-nav.js +183 -28
- package/dist/ui/shared/owner-css.js +30 -1
- package/dist/ui/shared/panel-view.js +14 -29
- package/dist/ui/shared/text-undo.js +210 -0
- package/dist/ui/shared/tokens.css +4 -0
- package/dist/ui/shared/ui-dialog.js +5 -4
- package/dist/ui/shared/ui-icons.js +4 -0
- package/dist/ui/shared/ui-menu.js +20 -7
- package/dist/ui/shared/ui-toast.js +16 -3
- package/dist/ui/shared/usage-dialog.js +206 -16
- package/dist/ui/shared/view-strings.js +68 -4
- package/dist/ui/shared/web-authorize.js +50 -1
- package/dist/ui/signin.html +2 -0
- package/dist/ui/web-terminal/terminal.html +10 -10
- package/dist/ui/web-terminal/terminal.js +58 -12
- package/dist/update-check.js.map +1 -1
- package/dist/update-dispatch.js +1 -1
- package/dist/update-dispatch.js.map +1 -1
- package/dist/update-install.js.map +1 -1
- package/dist/update-launch.d.ts +10 -1
- package/dist/update-launch.js +39 -14
- package/dist/update-launch.js.map +1 -1
- package/dist/update-marker.js.map +1 -1
- package/dist/update-preflight.js +1 -1
- package/dist/update-preflight.js.map +1 -1
- package/dist/update-progress.d.ts +3 -1
- package/dist/update-progress.js +3 -1
- package/dist/update-progress.js.map +1 -1
- package/dist/usage/format-rich.js +6 -3
- package/dist/usage/format-rich.js.map +1 -1
- package/dist/usage/i18n-keys.d.ts +1 -1
- package/dist/usage/i18n-keys.js +2 -1
- package/dist/usage/i18n-keys.js.map +1 -1
- package/dist/usage/i18n.d.ts +13 -1
- package/dist/usage/i18n.js +29 -0
- package/dist/usage/i18n.js.map +1 -1
- package/dist/usage/providers.d.ts +89 -2
- package/dist/usage/providers.js +247 -41
- package/dist/usage/providers.js.map +1 -1
- package/dist/usage/statusline-usage.js.map +1 -1
- package/dist/usage/usage-api.d.ts +5 -1
- package/dist/usage/usage-api.js +185 -58
- package/dist/usage/usage-api.js.map +1 -1
- package/dist/usage-report.js.map +1 -1
- package/dist/usage-rollup.js +1 -1
- package/dist/usage-rollup.js.map +1 -1
- package/dist/user-systemd.d.ts +24 -0
- package/dist/user-systemd.js +75 -0
- package/dist/user-systemd.js.map +1 -0
- package/dist/view-api.d.ts +7 -0
- package/dist/view-api.js +16 -4
- package/dist/view-api.js.map +1 -1
- package/dist/wake-coordinator.js.map +1 -1
- package/dist/web-ambient.js.map +1 -1
- package/dist/web-api.d.ts +57 -10
- package/dist/web-api.js +1103 -70
- package/dist/web-api.js.map +1 -1
- package/dist/web-app-icon-worker.d.ts +1 -0
- package/dist/web-app-icon-worker.js +16 -0
- package/dist/web-app-icon-worker.js.map +1 -0
- package/dist/web-app-icon.d.ts +109 -0
- package/dist/web-app-icon.js +257 -0
- package/dist/web-app-icon.js.map +1 -0
- package/dist/web-appearance-policy.js.map +1 -1
- package/dist/web-appearance-tools.d.ts +1 -0
- package/dist/web-appearance-tools.js +7 -3
- package/dist/web-appearance-tools.js.map +1 -1
- package/dist/web-appearance-view.js.map +1 -1
- package/dist/web-appearance.d.ts +4 -10
- package/dist/web-appearance.js +7 -4
- package/dist/web-appearance.js.map +1 -1
- package/dist/web-auth.d.ts +8 -4
- package/dist/web-auth.js +33 -21
- package/dist/web-auth.js.map +1 -1
- package/dist/web-backend-login.d.ts +130 -0
- package/dist/web-backend-login.js +225 -0
- package/dist/web-backend-login.js.map +1 -0
- package/dist/web-card.js.map +1 -1
- package/dist/web-channel-echo.js.map +1 -1
- package/dist/web-chat-history.d.ts +118 -8
- package/dist/web-chat-history.js +220 -25
- package/dist/web-chat-history.js.map +1 -1
- package/dist/web-commands.d.ts +5 -1
- package/dist/web-commands.js +1 -1
- package/dist/web-commands.js.map +1 -1
- package/dist/web-cookie-names.d.ts +5 -0
- package/dist/web-cookie-names.js +12 -0
- package/dist/web-cookie-names.js.map +1 -0
- package/dist/web-effect-bundle.d.ts +2 -2
- package/dist/web-effect-library.js.map +1 -1
- package/dist/web-effect-playback.js.map +1 -1
- package/dist/web-effect-profiles.d.ts +16 -16
- package/dist/web-effect-profiles.js +3 -2
- package/dist/web-effect-profiles.js.map +1 -1
- package/dist/web-effect-service.js.map +1 -1
- package/dist/web-effect-tools.js.map +1 -1
- package/dist/web-effect-trials.js.map +1 -1
- package/dist/web-effect-upload.js.map +1 -1
- package/dist/web-effect.d.ts +6 -6
- package/dist/web-effect.js.map +1 -1
- package/dist/web-experimental-http.d.ts +2 -0
- package/dist/web-experimental-http.js +12 -0
- package/dist/web-experimental-http.js.map +1 -0
- package/dist/web-experimental.d.ts +11 -0
- package/dist/web-experimental.js +49 -0
- package/dist/web-experimental.js.map +1 -0
- package/dist/web-guest-access.d.ts +4 -2
- package/dist/web-guest-access.js +22 -10
- package/dist/web-guest-access.js.map +1 -1
- package/dist/web-guest-rooms.js.map +1 -1
- package/dist/web-host-guard.d.ts +11 -0
- package/dist/web-host-guard.js +11 -0
- package/dist/web-host-guard.js.map +1 -1
- package/dist/web-icons.d.ts +33 -1
- package/dist/web-icons.js +83 -11
- package/dist/web-icons.js.map +1 -1
- package/dist/web-identity-color.js.map +1 -1
- package/dist/web-image-meta.d.ts +13 -0
- package/dist/web-image-meta.js +62 -0
- package/dist/web-image-meta.js.map +1 -1
- package/dist/web-images.js.map +1 -1
- package/dist/web-libavoid.d.ts +14 -0
- package/dist/web-libavoid.js +46 -0
- package/dist/web-libavoid.js.map +1 -0
- package/dist/web-login.js.map +1 -1
- package/dist/web-mentions.js.map +1 -1
- package/dist/web-mod-agent.js.map +1 -1
- package/dist/web-mod-store.d.ts +2 -0
- package/dist/web-mod-store.js +10 -0
- package/dist/web-mod-store.js.map +1 -1
- package/dist/web-office-store.d.ts +104 -0
- package/dist/web-office-store.js +236 -0
- package/dist/web-office-store.js.map +1 -0
- package/dist/web-owner-css-store.d.ts +44 -1
- package/dist/web-owner-css-store.js +70 -9
- package/dist/web-owner-css-store.js.map +1 -1
- package/dist/web-owner-css.js.map +1 -1
- package/dist/web-png.d.ts +33 -0
- package/dist/web-png.js +329 -0
- package/dist/web-png.js.map +1 -0
- package/dist/web-prefs.d.ts +6 -0
- package/dist/web-prefs.js +29 -3
- package/dist/web-prefs.js.map +1 -1
- package/dist/web-preview.d.ts +2 -0
- package/dist/web-preview.js +2 -0
- package/dist/web-preview.js.map +1 -1
- package/dist/web-profile.js.map +1 -1
- package/dist/web-reactions.d.ts +35 -0
- package/dist/web-reactions.js +47 -0
- package/dist/web-reactions.js.map +1 -0
- package/dist/web-request-context.d.ts +5 -0
- package/dist/web-request-context.js.map +1 -1
- package/dist/web-returning-device.d.ts +4 -2
- package/dist/web-returning-device.js +13 -6
- package/dist/web-returning-device.js.map +1 -1
- package/dist/web-schedules.js.map +1 -1
- package/dist/web-send-dedupe.d.ts +36 -0
- package/dist/web-send-dedupe.js +69 -0
- package/dist/web-send-dedupe.js.map +1 -0
- package/dist/web-session-authorization.js.map +1 -1
- package/dist/web-session.js +1 -1
- package/dist/web-session.js.map +1 -1
- package/dist/web-settings-patch.d.ts +3 -1
- package/dist/web-settings-patch.js +11 -5
- package/dist/web-settings-patch.js.map +1 -1
- package/dist/web-settings-tools.d.ts +6 -0
- package/dist/web-settings-tools.js +52 -17
- package/dist/web-settings-tools.js.map +1 -1
- package/dist/web-terminal-http.js +15 -2
- package/dist/web-terminal-http.js.map +1 -1
- package/dist/web-terminal.js +1 -1
- package/dist/web-terminal.js.map +1 -1
- package/dist/web-theme-store.d.ts +2 -2
- package/dist/web-theme-store.js +6 -3
- package/dist/web-theme-store.js.map +1 -1
- package/dist/web-theme.d.ts +29 -0
- package/dist/web-theme.js +89 -1
- package/dist/web-theme.js.map +1 -1
- package/dist/web-upload.d.ts +18 -1
- package/dist/web-upload.js +45 -7
- package/dist/web-upload.js.map +1 -1
- package/dist/web-widget.js.map +1 -1
- package/dist/webhook-emitter.js.map +1 -1
- package/dist/windows-shortcuts.d.ts +78 -0
- package/dist/windows-shortcuts.js +203 -0
- package/dist/windows-shortcuts.js.map +1 -0
- package/dist/workflow-templates/default.md +3 -0
- package/dist/ws-server.js.map +1 -1
- package/dist/yaml-shared-nodes.d.ts +25 -0
- package/dist/yaml-shared-nodes.js +185 -0
- package/dist/yaml-shared-nodes.js.map +1 -0
- package/launcher/agend-install.cjs +828 -0
- package/launcher/install-admission.cjs +4 -39
- package/launcher/postinstall.cjs +14 -12
- package/launcher/private-home.cjs +43 -0
- package/package.json +16 -13
- package/scripts/preinstall-guard.cjs +2 -5
- package/templates/windows-shortcuts.ps1 +181 -0
- package/launcher/old-updater-note.cjs +0 -48
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
// The task board's shared pieces (Fleet › Tasks): its words, the numbers a project shows, the requests, asking for a
|
|
2
|
+
// reason, moving a card, and the small marks (status pill, progress bar, who). fleet-tasks.js draws the board and
|
|
3
|
+
// fleet-task-card.js one card; both use these. No style attribute anywhere (the CSP): bars are SVG rects.
|
|
4
|
+
import { html, useEffect, useState } from "/assets/app-html.js";
|
|
5
|
+
import { t, register, lang } from "/assets/app-i18n.js";
|
|
6
|
+
import { appStore, createStore, useStore } from "/assets/app-store.js";
|
|
7
|
+
import { identityOf, paintIdentity, useIdentityColors } from "/assets/identity-color.js";
|
|
8
|
+
import { Dialog } from "/assets/ui-dialog.js";
|
|
9
|
+
import { toast } from "/assets/ui-toast.js";
|
|
10
|
+
|
|
11
|
+
register("tasks", {
|
|
12
|
+
en: {
|
|
13
|
+
open: "To do", claimed: "In progress", blocked: "Blocked", review: "Waiting for you", done: "Done", cancelled: "Cancelled",
|
|
14
|
+
main: "Main task", sub: "Sub task", urgent: "Urgent", high: "High", normal: "Normal", low: "Low",
|
|
15
|
+
sizeS: "Small", sizeM: "Medium", sizeL: "Large", sizeNone: "Not sized",
|
|
16
|
+
projects: "Projects", noProject: "No project", noProjectDesc: "Tasks the fleet opened outside any project",
|
|
17
|
+
newProject: "New project", newMain: "Main task", archived: "Archived", archive: "Archive", restore: "Restore",
|
|
18
|
+
rename: "Edit project", projectName: "Name", projectDesc: "Description",
|
|
19
|
+
projectLead: "Lead instance", projectLeadNone: "None — General", projectLeadHint: "Cards of this project that wait for you (to confirm, or blocked) get their buttons in the lead's channel, unless an instance handed them out (then in its channel).", projectLeadGone: "{0} (no longer in the fleet)", projectLeadChip: "lead: {0}", create: "Create", save: "Save", cancel: "Cancel",
|
|
20
|
+
projectCreated: "Project created", projectSaved: "Project saved",
|
|
21
|
+
noProjects: "No projects yet", noProjectsHint: "A project groups related work — create one, then open main tasks in it.",
|
|
22
|
+
mainCount: "{0} main tasks", mainOne: "1 main task", waiting: "{0} waiting for you", blockedN: "{0} blocked", lastActivity: "Last change {0}",
|
|
23
|
+
percentTitle: "Done: finished sub tasks out of all of them; a main task without sub tasks counts once you confirm it",
|
|
24
|
+
allProjects: "All projects", back: "Projects",
|
|
25
|
+
everyone: "Everyone", nobody: "Unassigned", filterLabel: "Filter by assignee",
|
|
26
|
+
recent: "Last 7 days", all: "All", toggleDone: "Show the last 7 days / everything",
|
|
27
|
+
emptyBoard: "No main tasks here yet", emptyFiltered: "No main tasks match the filter",
|
|
28
|
+
emptyBoardHint: "A main task is an outcome you want. Assign it to an instance: it does a small one directly and splits a big one into sub tasks.",
|
|
29
|
+
subProgress: "Sub tasks {0}/{1}", showSubs: "Show sub tasks", hideSubs: "Hide sub tasks", olderSubs: "{0} more finished earlier",
|
|
30
|
+
acceptance: "Acceptance", definition: "Definition of done", waitsFor: "Waits for {0}", comments: "Comments", agentReplied: "An instance replied",
|
|
31
|
+
needsReview: "Needs review", needsReviewTitle: "Stops at review for your confirmation", urgentTag: "Urgent", highTag: "High",
|
|
32
|
+
waitingTitle: "Waiting for you", waitingEmpty: "Nothing is waiting for you.", confirm: "Confirm", sendBack: "Send back", answer: "Answer",
|
|
33
|
+
confirmed: "{0} confirmed", sentBack: "{0} sent back", answered: "Answered {0}",
|
|
34
|
+
sendBackTitle: "Send back {0}", sendBackLabel: "What needs to change (the assignee reads this)",
|
|
35
|
+
blockTitle: "{0} is blocked", blockLabel: "Blocked on: who has to answer what?", block: "Mark blocked",
|
|
36
|
+
answerTitle: "Answer {0}", answerLabel: "{0} asks: {1}", answerConfirm: "Answer and resume",
|
|
37
|
+
cancelTitle: "Cancel {0}", cancelLabel: "Reason (optional)", cancelConfirm: "Cancel this card",
|
|
38
|
+
derivedMove: "A main task with sub tasks follows them: open it to see its sub tasks, or confirm or send it back when it waits for you",
|
|
39
|
+
createMain: "New main task", createSub: "New sub task", title: "Title", titleHint: "Start with a verb, e.g. Build the leaderboard",
|
|
40
|
+
goal: "Goal", goalHint: "Why, and what done looks like", scope: "Scope", scopeHint: "In: … / Out: …",
|
|
41
|
+
definitionHint: "One per line: conditions anyone can check", acceptanceHint: "One per line",
|
|
42
|
+
context: "Context", contextHint: "Paths, related cards, decisions already made (pointers only)",
|
|
43
|
+
assignee: "Assignee", assigneeHint: "Which instance", project: "Project", size: "Size", priority: "Priority",
|
|
44
|
+
reviewBox: "Stop at review for my confirmation", created: "Opened {0}", titleRequired: "A title is required",
|
|
45
|
+
search: "Search cards", searchHint: "Search titles, fields, checklists and comments", searchEmpty: "No cards match", inField: "in {0}",
|
|
46
|
+
fieldgoal: "goal", fieldscope: "scope", fieldcontext: "context", fieldstate: "state", fieldresult: "result", fieldblockedReason: "blocked reason",
|
|
47
|
+
fieldacceptance: "acceptance", fieldlog: "log", fieldcomment: "comment",
|
|
48
|
+
loadFailed: "The board could not be read", justNow: "just now",
|
|
49
|
+
fieldtitle: "the title", fieldreason: "the reason", fieldprojectName: "the project's name", fieldprojectDescription: "the description",
|
|
50
|
+
readOnly: "The public link shows the board read-only. To change it, open the dashboard on the machine running AgEnD.",
|
|
51
|
+
tileHint: "Enter opens it · Alt+↑/↓ moves it in its column · Alt+←/→ to the next status",
|
|
52
|
+
conflictAgain: "{0} changed meanwhile (it is now {1}). Your text is kept — send it again?", sendAgain: "Send again", conflictLabel: "What you wrote",
|
|
53
|
+
nowDoing: "Working on", nowBlocked: "Blocked", nowNext: "Next", ownerTip: "Main task owner: {0}", moreCards: "+{0}",
|
|
54
|
+
wrapTag: "To fill in", wrapLine: "Not wrapped up yet: {0}", gapUnchecked: "{0} checklist items unchecked", gapUncheckedOne: "1 checklist item unchecked",
|
|
55
|
+
gapNoResult: "no result", confirmGapTitle: "Confirm {0}?", confirmAnyway: "Confirm anyway",
|
|
56
|
+
askedFirst: "{0} handed it out and has been asked; you can answer it here too",
|
|
57
|
+
confirmGapLabel: "{0}. You can send it back to have it filled in — or confirm anyway, with a note if you like",
|
|
58
|
+
"err.too_long": "{0} is too long: {1} characters, at most {2}", "err.state_lines": "State is at most {0} lines (it has {1})",
|
|
59
|
+
"err.acceptance_empty": "An acceptance item cannot be empty", "err.acceptance_max": "At most {0} acceptance items",
|
|
60
|
+
"err.acceptance_no_item": "There is no acceptance item {0} (there are {1})", "err.project_not_found": "There is no project “{0}”",
|
|
61
|
+
"err.project_name_empty": "A project needs a name", "err.project_name_digits": "A project's name cannot be only digits", "err.lead_not_instance": "The lead must be one of the fleet's instances",
|
|
62
|
+
"err.project_name_taken": "There is already a project named “{0}”", "err.project_archived": "Project “{0}” is archived: it takes no new main tasks",
|
|
63
|
+
"err.card_not_found": "There is no card {0}", "err.title_empty": "A card needs a title", "err.scope_main_only": "Scope is for main tasks only",
|
|
64
|
+
"err.blocked_reason_not_blocked": "Only a blocked card has a blocked reason", "err.block_reason": "Blocking needs a reason: who has to answer what",
|
|
65
|
+
"err.sub_project": "A sub task follows its main task's project: move the main task", "err.already": "{0} is already {1}",
|
|
66
|
+
"err.main_cancelled": "Main task {0} is cancelled: restore it first", "err.sendback_reason": "Sending work back needs a reason",
|
|
67
|
+
"err.cannot_block": "{0} is {1}: it cannot be blocked",
|
|
68
|
+
"err.derived_move": "{0} has sub tasks and follows them: confirm it, send it back, block it or cancel it",
|
|
69
|
+
"err.unfinished_subs": "{0} still has unfinished sub tasks: {1}", "err.parent_is_sub": "{0} is a sub task: sub tasks are not split further",
|
|
70
|
+
"err.parent_cancelled": "{0} is cancelled: it takes no new sub tasks", "err.dep_self": "A card cannot depend on itself",
|
|
71
|
+
"err.dep_own_main": "A sub task cannot depend on its own main task {0}", "err.dep_own_sub": "A main task cannot depend on its own sub task {0}",
|
|
72
|
+
"err.dep_cycle": "These dependencies would wait on each other forever: {0}", "err.conflict": "{0} was changed meanwhile (last by {1})",
|
|
73
|
+
"err.signed_in_only": "The task board takes changes from a signed-in dashboard", "err.unavailable": "The task board is not available right now", "err.not_over_public_link": "The public link can only read the board",
|
|
74
|
+
"note.review_waiting": "{0} “{1}”: every sub task is done — it waits for your confirmation",
|
|
75
|
+
"note.back_to": "{0} has unfinished sub tasks again: it is back to {1}", "note.deps_done": "{0}'s dependencies are all done: it can start",
|
|
76
|
+
"note.deps_unmet": "Note: {0} not done yet",
|
|
77
|
+
// #2246 step 3: who works on what (fleet-task-work.js)
|
|
78
|
+
instances: "Instances", instancesTip: "The fleet's instances and what each works on", instancesHead: "{0} instance(s) · {1} working",
|
|
79
|
+
workSentBack: "Sent back", workDoing: "In progress", workBlocked: "Blocked", workReview: "Waiting for you", workMain: "Owns",
|
|
80
|
+
workReady: "Can start", workWaiting: "Waiting on", workSubs: "sub tasks {0}/{1}", workClaimable: "nobody's: can be taken",
|
|
81
|
+
workWaitsFor: "waits for {0}", workNone: "Nothing on the board", workNewComments: "Comments it has not read yet",
|
|
82
|
+
workOutside: "Not in the fleet", workFailed: "Could not read who works on what: {0}", workJoin: ", ",
|
|
83
|
+
detailsBoard: "Task board",
|
|
84
|
+
},
|
|
85
|
+
"zh-TW": {
|
|
86
|
+
open: "待辦", claimed: "進行中", blocked: "卡住", review: "待確認", done: "完成", cancelled: "取消",
|
|
87
|
+
main: "主任務", sub: "子任務", urgent: "緊急", high: "高", normal: "一般", low: "低",
|
|
88
|
+
sizeS: "小", sizeM: "中", sizeL: "大", sizeNone: "未定",
|
|
89
|
+
projects: "專案", noProject: "未分類", noProjectDesc: "fleet 在專案以外開的 task",
|
|
90
|
+
newProject: "新增專案", newMain: "主任務", archived: "已封存", archive: "封存", restore: "恢復",
|
|
91
|
+
rename: "編輯專案", projectName: "名稱", projectDesc: "說明",
|
|
92
|
+
projectLead: "負責的 instance", projectLeadNone: "無(General)", projectLeadHint: "這個專案裡等你處理的卡片(待確認或卡住)會在負責 instance 的頻道顯示按鈕;若卡片是某個 instance 派出的,則顯示在派出者的頻道。", projectLeadGone: "{0}(已不在 fleet 中)", projectLeadChip: "負責:{0}", create: "建立", save: "儲存", cancel: "取消",
|
|
93
|
+
projectCreated: "專案已建立", projectSaved: "專案已儲存",
|
|
94
|
+
noProjects: "還沒有專案", noProjectsHint: "專案是一組相關的工作:先建立專案,再在裡面開主任務。",
|
|
95
|
+
mainCount: "{0} 個主任務", mainOne: "1 個主任務", waiting: "等你確認 {0}", blockedN: "卡住 {0}", lastActivity: "最後動態 {0}",
|
|
96
|
+
percentTitle: "完成度:已完成的子任務佔全部的比例;沒有子任務的主任務算一份,你確認後才算完成",
|
|
97
|
+
allProjects: "所有專案", back: "專案",
|
|
98
|
+
everyone: "全部負責人", nobody: "沒人負責", filterLabel: "依負責人篩選",
|
|
99
|
+
recent: "近 7 天", all: "全部", toggleDone: "切換:只看近 7 天/全部",
|
|
100
|
+
emptyBoard: "這個專案還沒有主任務", emptyFiltered: "沒有符合篩選的主任務",
|
|
101
|
+
emptyBoardHint: "主任務是你要的成果,可大可小。指派給 instance,它會自己決定直接做,或先拆成子任務。",
|
|
102
|
+
subProgress: "子任務 {0}/{1}", showSubs: "展開子任務", hideSubs: "收起子任務", olderSubs: "另有 {0} 張比較早完成",
|
|
103
|
+
acceptance: "驗收條件", definition: "完成定義", waitsFor: "等 {0} 完成", comments: "留言", agentReplied: "instance 有新回覆",
|
|
104
|
+
needsReview: "需確認", needsReviewTitle: "做完要停在待確認,等你確認", urgentTag: "緊急", highTag: "優先",
|
|
105
|
+
waitingTitle: "待你處理", waitingEmpty: "沒有等你處理的事。", confirm: "確認", sendBack: "退回", answer: "回覆",
|
|
106
|
+
confirmed: "已確認 {0}", sentBack: "已退回 {0}", answered: "已回覆 {0}",
|
|
107
|
+
sendBackTitle: "退回 {0}", sendBackLabel: "要改什麼(負責人會看到)",
|
|
108
|
+
blockTitle: "{0} 卡住了", blockLabel: "卡住原因:需要誰回答什麼?", block: "標記卡住",
|
|
109
|
+
answerTitle: "回覆 {0}", answerLabel: "{0} 問:{1}", answerConfirm: "回覆並改回進行中",
|
|
110
|
+
cancelTitle: "取消 {0}", cancelLabel: "原因(可以不填)", cancelConfirm: "取消這張卡",
|
|
111
|
+
derivedMove: "有子任務的主任務會跟著子任務自動變化:打開卡片看子任務;待確認時可以確認或退回",
|
|
112
|
+
createMain: "開主任務", createSub: "開子任務", title: "標題", titleHint: "動詞開頭,例如:做排行榜",
|
|
113
|
+
goal: "目標", goalHint: "為什麼做、做完是什麼樣子", scope: "範圍", scopeHint: "做:…/不做:…",
|
|
114
|
+
definitionHint: "一行一項:能客觀判斷是否達成的條件", acceptanceHint: "一行一項",
|
|
115
|
+
context: "背景", contextHint: "檔案路徑、相關卡號、已經做的決定(只放指引)",
|
|
116
|
+
assignee: "負責人", assigneeHint: "交給哪個 instance", project: "專案", size: "大小", priority: "優先度",
|
|
117
|
+
reviewBox: "做完要停在待確認,等我確認", created: "已開 {0}", titleRequired: "標題必填",
|
|
118
|
+
search: "搜尋卡片", searchHint: "搜尋標題、各欄位、驗收條件和留言", searchEmpty: "沒有符合的卡片", inField: "在{0}",
|
|
119
|
+
fieldgoal: "目標", fieldscope: "範圍", fieldcontext: "背景", fieldstate: "目前狀態", fieldresult: "產出", fieldblockedReason: "卡住原因",
|
|
120
|
+
fieldacceptance: "驗收條件", fieldlog: "進度紀錄", fieldcomment: "留言",
|
|
121
|
+
loadFailed: "看板讀不到", justNow: "剛剛",
|
|
122
|
+
fieldtitle: "標題", fieldreason: "原因", fieldprojectName: "專案名稱", fieldprojectDescription: "專案說明",
|
|
123
|
+
readOnly: "公開連結上的任務板只能看。要修改,請在執行 AgEnD 的那台機器上開啟儀表板。",
|
|
124
|
+
tileHint: "Enter 打開 · Alt+↑/↓ 在欄內移動 · Alt+←/→ 移到前一個/下一個狀態",
|
|
125
|
+
conflictAgain: "{0} 在這之間被改過(現在是{1})。你寫的內容還在,要再送一次嗎?", sendAgain: "再送一次", conflictLabel: "你寫的內容",
|
|
126
|
+
nowDoing: "執行中", nowBlocked: "卡住", nowNext: "下一步", ownerTip: "主任務負責人:{0}", moreCards: "+{0}",
|
|
127
|
+
wrapTag: "待補齊", wrapLine: "負責人還沒補齊:{0}", gapUnchecked: "還有 {0} 項沒勾", gapUncheckedOne: "還有 1 項沒勾",
|
|
128
|
+
gapNoResult: "沒有產出總結", confirmGapTitle: "確認 {0}?", confirmAnyway: "還是確認",
|
|
129
|
+
askedFirst: "已先通知派工者 {0};你也可以直接在這裡回覆",
|
|
130
|
+
confirmGapLabel: "{0}。可以先退回請負責人補齊;還是要確認的話,可以留一句確認意見",
|
|
131
|
+
"err.too_long": "{0}太長:{1} 字,上限 {2} 字", "err.state_lines": "目前狀態最多 {0} 行(現在 {1} 行)",
|
|
132
|
+
"err.acceptance_empty": "驗收條件不能是空的", "err.acceptance_max": "驗收條件最多 {0} 項",
|
|
133
|
+
"err.acceptance_no_item": "驗收條件沒有第 {0} 項(共 {1} 項)", "err.project_not_found": "找不到專案「{0}」",
|
|
134
|
+
"err.project_name_empty": "專案名稱不能是空的", "err.project_name_digits": "專案名稱不能只有數字", "err.lead_not_instance": "負責人必須是 fleet 裡的 instance",
|
|
135
|
+
"err.project_name_taken": "已經有專案叫「{0}」", "err.project_archived": "專案「{0}」已封存,不能再開主任務",
|
|
136
|
+
"err.card_not_found": "找不到 {0}", "err.title_empty": "標題不能是空的", "err.scope_main_only": "範圍只用在主任務",
|
|
137
|
+
"err.blocked_reason_not_blocked": "只有卡住的卡才有卡住原因", "err.block_reason": "卡住要寫原因:需要誰回答什麼",
|
|
138
|
+
"err.sub_project": "子任務跟著主任務的專案:要移就移主任務", "err.already": "{0} 已經是{1}",
|
|
139
|
+
"err.main_cancelled": "主任務 {0} 已取消:要繼續做請先恢復主任務", "err.sendback_reason": "退回要寫退回意見",
|
|
140
|
+
"err.cannot_block": "{0} 現在是{1},不能標卡住",
|
|
141
|
+
"err.derived_move": "{0} 有子任務,狀態會跟著子任務變化:可以確認、退回、標卡住或取消",
|
|
142
|
+
"err.unfinished_subs": "{0} 還有子任務沒完成:{1}", "err.parent_is_sub": "{0} 是子任務:子任務不能再往下拆",
|
|
143
|
+
"err.parent_cancelled": "{0} 已取消:不能在底下開子任務", "err.dep_self": "卡片不能相依自己",
|
|
144
|
+
"err.dep_own_main": "子任務不能相依自己的主任務 {0}", "err.dep_own_sub": "主任務不能相依自己的子任務 {0}",
|
|
145
|
+
"err.dep_cycle": "相依會形成循環,大家會互相等待:{0}", "err.conflict": "{0} 已經被改過(最後由 {1} 修改)",
|
|
146
|
+
"err.signed_in_only": "看板只接受已登入網頁的修改", "err.unavailable": "看板目前無法使用", "err.not_over_public_link": "公開連結只能看看板,不能修改",
|
|
147
|
+
"note.review_waiting": "{0}「{1}」的子任務都完成了,等你確認",
|
|
148
|
+
"note.back_to": "{0} 又有沒完成的子任務,已回到{1}", "note.deps_done": "{0} 的相依都完成了,可以開始",
|
|
149
|
+
"note.deps_unmet": "提醒:{0} 還沒完成",
|
|
150
|
+
// #2246 step 3:誰在做什麼(fleet-task-work.js)
|
|
151
|
+
instances: "Instance", instancesTip: "fleet 有哪些 instance、各在做什麼", instancesHead: "{0} 個 · 工作中 {1}",
|
|
152
|
+
workSentBack: "被退回", workDoing: "進行中", workBlocked: "卡住", workReview: "待確認", workMain: "負責",
|
|
153
|
+
workReady: "可以開始", workWaiting: "等前置", workSubs: "子任務 {0}/{1}", workClaimable: "沒人負責,可領",
|
|
154
|
+
workWaitsFor: "等 {0}", workNone: "看板上沒有它的卡", workNewComments: "有它還沒看過的留言",
|
|
155
|
+
workOutside: "不在 fleet 裡", workFailed: "讀不到工作清單:{0}", workJoin: "、",
|
|
156
|
+
detailsBoard: "任務看板",
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
export const COLUMNS = ["open", "claimed", "blocked", "review", "done"];
|
|
161
|
+
export const NO_PROJECT = "none";
|
|
162
|
+
const WEEK = 7 * 86_400_000;
|
|
163
|
+
export const UNASSIGNED = "\u0000none";
|
|
164
|
+
|
|
165
|
+
// ── Pure helpers (tests import these) ─────────────────────────
|
|
166
|
+
|
|
167
|
+
export const emptyProgress = () => ({ total: 0, open: 0, claimed: 0, blocked: 0, review: 0, done: 0 });
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* A main task's work units: its sub tasks, or one unit when it has none. A confirmed main task counts all its units
|
|
171
|
+
* as done; one without sub tasks counts as done only once confirmed.
|
|
172
|
+
*/
|
|
173
|
+
export function addUnits(units, main) {
|
|
174
|
+
if (main.status === "cancelled") return;
|
|
175
|
+
const p = main.progress;
|
|
176
|
+
if (main.status === "done") {
|
|
177
|
+
const n = (p && p.total) || 1;
|
|
178
|
+
units.total += n;
|
|
179
|
+
units.done += n;
|
|
180
|
+
} else if (p && p.total) {
|
|
181
|
+
for (const k of ["total", "open", "claimed", "blocked", "review", "done"]) units[k] += p[k];
|
|
182
|
+
} else {
|
|
183
|
+
units.total++;
|
|
184
|
+
units[main.status]++;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export const percentDone = (units) => (units.total ? Math.round((units.done / units.total) * 100) : 0);
|
|
189
|
+
|
|
190
|
+
/** The key a card's project is filed under: its id, or NO_PROJECT. */
|
|
191
|
+
export const projectKey = (card) => (card.projectId === null || card.projectId === undefined ? NO_PROJECT : card.projectId);
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* One project's numbers for its card on Home and its header, from the cards at hand (`key`: a project id or
|
|
195
|
+
* NO_PROJECT). The board's read carries the server's (over every card, finished ones too); this is the fallback.
|
|
196
|
+
*/
|
|
197
|
+
export function projectStats(key, cards) {
|
|
198
|
+
const units = emptyProgress();
|
|
199
|
+
let mains = 0, waiting = 0, blocked = 0, lastActivity = null;
|
|
200
|
+
for (const c of cards) {
|
|
201
|
+
if (projectKey(c) !== key) continue;
|
|
202
|
+
if (!lastActivity || c.updatedAt > lastActivity) lastActivity = c.updatedAt;
|
|
203
|
+
if (c.status === "cancelled") continue;
|
|
204
|
+
if (c.status === "review") waiting++;
|
|
205
|
+
if (c.status === "blocked") blocked++;
|
|
206
|
+
if (c.kind !== "main") continue;
|
|
207
|
+
mains++;
|
|
208
|
+
addUnits(units, c);
|
|
209
|
+
}
|
|
210
|
+
return { mains, units, percent: percentDone(units), waiting, blocked, lastActivity };
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** A main task with sub tasks follows them; by hand it is only confirmed, sent back, blocked or cancelled. */
|
|
214
|
+
export const followsSubs = (card) => card.kind === "main" && !!card.progress && card.progress.total > 0;
|
|
215
|
+
|
|
216
|
+
/** Done within the last week (the Done column's default). */
|
|
217
|
+
export const recentlyDone = (card, now = Date.now()) => !!card.doneAt && now - Date.parse(card.doneAt) < WEEK;
|
|
218
|
+
|
|
219
|
+
/** Where a dropped card lands in `column` (the cards there now, in order): its neighbours by card number. */
|
|
220
|
+
export function dropNeighbours(column, draggedId, index) {
|
|
221
|
+
const others = column.filter((c) => c.id !== draggedId);
|
|
222
|
+
return { after: index > 0 ? others[index - 1]?.id ?? null : null, before: others[index]?.id ?? null };
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** A progress bar's segments, in percent of its width: done, review, in progress, blocked (to do is the track). */
|
|
226
|
+
export function barSegments(progress) {
|
|
227
|
+
const total = progress && progress.total ? progress.total : 0;
|
|
228
|
+
if (!total) return [];
|
|
229
|
+
let x = 0;
|
|
230
|
+
const out = [];
|
|
231
|
+
for (const k of ["done", "review", "claimed", "blocked"]) {
|
|
232
|
+
const w = (progress[k] / total) * 100;
|
|
233
|
+
if (w > 0) out.push({ k, x, w });
|
|
234
|
+
x += w;
|
|
235
|
+
}
|
|
236
|
+
return out;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** "3 min ago" in the dashboard's language. */
|
|
240
|
+
export function relTime(iso, now = Date.now()) {
|
|
241
|
+
const ms = now - Date.parse(iso);
|
|
242
|
+
if (!Number.isFinite(ms)) return "";
|
|
243
|
+
if (ms < 45_000) return t("tasks.justNow");
|
|
244
|
+
const rtf = new Intl.RelativeTimeFormat(lang() === "zh-TW" ? "zh-TW" : "en", { numeric: "auto" });
|
|
245
|
+
const steps = [[60, "second"], [60, "minute"], [24, "hour"], [7, "day"], [4.35, "week"], [12, "month"], [Infinity, "year"]];
|
|
246
|
+
let v = ms / 1000;
|
|
247
|
+
for (const [n, unit] of steps) {
|
|
248
|
+
if (Math.abs(v) < n) return rtf.format(-Math.round(v), unit);
|
|
249
|
+
v /= n;
|
|
250
|
+
}
|
|
251
|
+
return "";
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// ── Requests ──────────────────────────────────────────────
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* What a finished card still lacks for your confirmation, in words ("" when nothing): unchecked checklist items, no
|
|
258
|
+
* result. A main task goes to review by itself when its last sub task is done — often a reviewer's — before its owner
|
|
259
|
+
* wrapped it up (scheduler/task-board.ts wrapUpGap).
|
|
260
|
+
*/
|
|
261
|
+
export function wrapUpText(card) {
|
|
262
|
+
const unchecked = (card.acceptance || []).filter((a) => !a.done).length;
|
|
263
|
+
const parts = [];
|
|
264
|
+
if (unchecked) parts.push(unchecked === 1 ? t("tasks.gapUncheckedOne") : t("tasks.gapUnchecked", unchecked));
|
|
265
|
+
if (!String(card.result || "").trim()) parts.push(t("tasks.gapNoResult"));
|
|
266
|
+
return parts.join(lang() === "zh-TW" ? "、" : ", ");
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Who works on a main task right now: its sub tasks in progress, else the blocked ones, else those that can start
|
|
271
|
+
* (dependencies done). Null when there are none, or when the main task waits for you or is finished. Its owner is not
|
|
272
|
+
* always the one at work: a review step belongs to the reviewer.
|
|
273
|
+
*/
|
|
274
|
+
export function currentWork(main, subs) {
|
|
275
|
+
if (["review", "done", "cancelled"].includes(main.status)) return null;
|
|
276
|
+
const live = subs.filter((s) => s.status !== "cancelled");
|
|
277
|
+
for (const [status, label, tone] of [["claimed", "tasks.nowDoing", "claimed"], ["blocked", "tasks.nowBlocked", "blocked"]]) {
|
|
278
|
+
const cards = live.filter((s) => s.status === status);
|
|
279
|
+
if (cards.length) return { label, tone, cards };
|
|
280
|
+
}
|
|
281
|
+
const ready = live.filter((s) => s.status === "open" && !(s.unmetDeps || []).length);
|
|
282
|
+
return ready.length ? { label: "tasks.nowNext", tone: "open", cards: ready } : null;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/** The instances behind some cards, each once ("" for a card nobody has taken). */
|
|
286
|
+
export const workersOf = (cards) => [...new Set(cards.map((c) => c.assignee || ""))];
|
|
287
|
+
|
|
288
|
+
/** A board request: the answer's JSON, or a thrown Error carrying the HTTP status and the board's code. */
|
|
289
|
+
export async function boardCall(method, path, body) {
|
|
290
|
+
const o = { method, headers: { "Content-Type": "application/json" } };
|
|
291
|
+
if (body !== undefined) o.body = JSON.stringify(body);
|
|
292
|
+
const r = await fetch(path, o);
|
|
293
|
+
let d = {};
|
|
294
|
+
try { d = await r.json(); } catch { /* an empty answer */ }
|
|
295
|
+
if (!r.ok) {
|
|
296
|
+
const err = new Error(d.error || `HTTP ${r.status}`);
|
|
297
|
+
err.status = r.status;
|
|
298
|
+
err.code = d.code;
|
|
299
|
+
err.key = d.key;
|
|
300
|
+
err.args = Array.isArray(d.args) ? d.args : [];
|
|
301
|
+
throw err;
|
|
302
|
+
}
|
|
303
|
+
return d;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/** Statuses and field names among a refusal's or a note's values, in the page's words. */
|
|
307
|
+
function word(key, arg, i) {
|
|
308
|
+
if (typeof arg !== "string") return arg;
|
|
309
|
+
if ((key === "too_long") && i === 0) { const w = t(`tasks.field${arg}`); return w === `tasks.field${arg}` ? arg : w; }
|
|
310
|
+
if (["open", "claimed", "blocked", "review", "done", "cancelled"].includes(arg) && ["already", "cannot_block", "back_to"].includes(key)) return t(`tasks.${arg}`);
|
|
311
|
+
return arg;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** A refusal in the page's language when the board named it (tasks.err.<key>), else the board's own sentence. */
|
|
315
|
+
export function errorText(err) {
|
|
316
|
+
if (err && err.key) {
|
|
317
|
+
const key = `tasks.err.${err.key}`;
|
|
318
|
+
const said = t(key, ...(err.args || []).map((a, i) => word(err.key, a, i)));
|
|
319
|
+
if (said !== key) return said;
|
|
320
|
+
}
|
|
321
|
+
return err && err.message ? err.message : String(err);
|
|
322
|
+
}
|
|
323
|
+
const enc = encodeURIComponent;
|
|
324
|
+
export const boardApi = {
|
|
325
|
+
board: (allDone = false) => boardCall("GET", `/ui/tasks/board${allDone ? "?done=all" : ""}`),
|
|
326
|
+
card: (id) => boardCall("GET", `/ui/tasks/cards/${enc(id)}`),
|
|
327
|
+
create: (spec) => boardCall("POST", "/ui/tasks/cards", spec),
|
|
328
|
+
update: (id, patch) => boardCall("POST", `/ui/tasks/cards/${enc(id)}`, patch),
|
|
329
|
+
move: (id, to, input = {}) => boardCall("POST", `/ui/tasks/cards/${enc(id)}/move`, { to, ...input }),
|
|
330
|
+
reorder: (id, after, before) => boardCall("POST", `/ui/tasks/cards/${enc(id)}/reorder`, { after, before }),
|
|
331
|
+
search: (q) => boardCall("GET", `/ui/tasks/search?q=${enc(q)}`),
|
|
332
|
+
/** #2246 step 3: each instance's work (its `task mine`), or one instance's. */
|
|
333
|
+
work: (instance) => boardCall("GET", `/ui/tasks/work${instance ? `?instance=${enc(instance)}` : ""}`),
|
|
334
|
+
createProject: (name, description, leadInstance) => boardCall("POST", "/ui/tasks/projects", { name, description, ...(leadInstance ? { leadInstance } : {}) }),
|
|
335
|
+
updateProject: (id, patch) => boardCall("POST", `/ui/tasks/projects/${id}`, patch),
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
/** The notes a write brings that a person wants to hear, in the page's language (the rest are for agents). */
|
|
339
|
+
const PERSON_NOTES = new Set(["review_waiting", "back_to", "deps_done", "deps_unmet"]);
|
|
340
|
+
export function notesForPeople(notes) {
|
|
341
|
+
return (notes || []).filter((n) => n && typeof n === "object" && PERSON_NOTES.has(n.key))
|
|
342
|
+
.map((n) => t(`tasks.note.${n.key}`, ...(n.args || []).map((a, i) => word(n.key, a, i))));
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/** Over the temporary public link the board is read-only (its writes are refused there). */
|
|
346
|
+
export const onPublicLink = () => typeof document !== "undefined" && !!document.body && document.body.dataset.publicLink === "1";
|
|
347
|
+
|
|
348
|
+
// ── Asking for a line of text (a reason, an answer) ──────────
|
|
349
|
+
|
|
350
|
+
let askStore = null;
|
|
351
|
+
let askSeq = 0;
|
|
352
|
+
/** Made on first use, so loading this module runs nothing but its words (tests read them that way). */
|
|
353
|
+
const asks = () => askStore || (askStore = createStore({ queue: [] }));
|
|
354
|
+
|
|
355
|
+
/** Ask for text in the app's dialog. Resolves the trimmed text, or null when the person backs out. */
|
|
356
|
+
export function askText({ title, label, confirmLabel, required = false, danger = false, initial = "" }) {
|
|
357
|
+
return new Promise((resolve) => {
|
|
358
|
+
asks().set((s) => ({ queue: [...s.queue, { id: ++askSeq, title, label, confirmLabel: confirmLabel || t("tasks.save"), required, danger, initial, resolve }] }));
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
function answerAsk(id, value) {
|
|
362
|
+
const item = asks().get().queue.find((q) => q.id === id);
|
|
363
|
+
if (!item) return;
|
|
364
|
+
asks().set((s) => ({ queue: s.queue.filter((q) => q.id !== id) }));
|
|
365
|
+
item.resolve(value);
|
|
366
|
+
}
|
|
367
|
+
/** Rendered once by the board: the oldest question. */
|
|
368
|
+
export function AskHost() {
|
|
369
|
+
const { queue } = useStore(asks());
|
|
370
|
+
const q = queue[0];
|
|
371
|
+
const [text, setText] = useState("");
|
|
372
|
+
useEffect(() => { setText(q ? q.initial : ""); }, [q && q.id]);
|
|
373
|
+
if (!q) return null;
|
|
374
|
+
const ok = !q.required || text.trim() !== "";
|
|
375
|
+
const submit = () => { if (ok) answerAsk(q.id, text.trim()); };
|
|
376
|
+
return html`<${Dialog} key=${q.id} title=${q.title} onClose=${() => answerAsk(q.id, null)}
|
|
377
|
+
actions=${html`<button type="button" class="btn" onClick=${() => answerAsk(q.id, null)}>${t("tasks.cancel")}</button>
|
|
378
|
+
<button type="button" class=${`btn ${q.danger ? "btn-danger" : "btn-primary"}`} disabled=${!ok} onClick=${submit}>${q.confirmLabel}</button>`}>
|
|
379
|
+
<form class="form" onSubmit=${(e) => { e.preventDefault(); submit(); }}>
|
|
380
|
+
<label class="field"><span>${q.label}</span>
|
|
381
|
+
<textarea rows="3" value=${text} onInput=${(e) => setText(e.target.value)}
|
|
382
|
+
onKeyDown=${(e) => { if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) { e.preventDefault(); submit(); } }}></textarea></label>
|
|
383
|
+
</form></${Dialog}>`;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Moving a card: the text a move needs (why it is blocked, why it is sent back), then the request with the version the
|
|
388
|
+
* person saw. When an agent changed the card in between (409), typed text is not lost: the card is read again and the
|
|
389
|
+
* person is asked once more, the text in place, before it is sent to the card as it now is.
|
|
390
|
+
* Resolves the board's answer, or null (backed out or refused; the refusal is toasted).
|
|
391
|
+
*/
|
|
392
|
+
export async function moveCard(card, to, extra = {}) {
|
|
393
|
+
const { again: _again, ...given } = extra;
|
|
394
|
+
const input = { ...given };
|
|
395
|
+
if (to === "blocked" && !input.reason) {
|
|
396
|
+
const r = await askText({ title: t("tasks.blockTitle", card.id), label: t("tasks.blockLabel"), required: true, confirmLabel: t("tasks.block") });
|
|
397
|
+
if (r === null) return null;
|
|
398
|
+
input.reason = r;
|
|
399
|
+
}
|
|
400
|
+
if (card.status === "review" && (to === "claimed" || to === "open") && !input.reason) {
|
|
401
|
+
const r = await askText({ title: t("tasks.sendBackTitle", card.id), label: t("tasks.sendBackLabel"), required: true, confirmLabel: t("tasks.sendBack") });
|
|
402
|
+
if (r === null) return null;
|
|
403
|
+
input.reason = r;
|
|
404
|
+
}
|
|
405
|
+
// Confirming work that is not wrapped up (checklist unticked, no result) asks first; a note there is the approval's.
|
|
406
|
+
const gap = card.status === "review" && to === "done" && input.reason === undefined ? wrapUpText(card) : "";
|
|
407
|
+
if (gap) {
|
|
408
|
+
const r = await askText({ title: t("tasks.confirmGapTitle", card.id), label: t("tasks.confirmGapLabel", gap), confirmLabel: t("tasks.confirmAnyway") });
|
|
409
|
+
if (r === null) return null;
|
|
410
|
+
if (r) input.reason = r;
|
|
411
|
+
}
|
|
412
|
+
if (to === "cancelled" && input.reason === undefined) {
|
|
413
|
+
const r = await askText({ title: t("tasks.cancelTitle", card.id), label: t("tasks.cancelLabel"), confirmLabel: t("tasks.cancelConfirm"), danger: true });
|
|
414
|
+
if (r === null) return null;
|
|
415
|
+
if (r) input.reason = r;
|
|
416
|
+
}
|
|
417
|
+
input.version = card.version;
|
|
418
|
+
try {
|
|
419
|
+
const r = await boardApi.move(card.id, to, input);
|
|
420
|
+
for (const n of notesForPeople(r.notes)) toast(n);
|
|
421
|
+
return r;
|
|
422
|
+
} catch (err) {
|
|
423
|
+
// Someone changed the card meanwhile: what was typed is not lost — read the card again and offer to send it there.
|
|
424
|
+
if (err.status === 409 && (input.reason || input.comment) && !extra.again) {
|
|
425
|
+
try {
|
|
426
|
+
const { card: fresh } = await boardApi.card(card.id);
|
|
427
|
+
const typed = input.reason || input.comment;
|
|
428
|
+
const again = await askText({ title: t("tasks.conflictAgain", card.id, t(`tasks.${fresh.status}`)), label: t("tasks.conflictLabel"), initial: typed, required: true, confirmLabel: t("tasks.sendAgain") });
|
|
429
|
+
if (again === null) return null;
|
|
430
|
+
return moveCard(fresh, to, { ...extra, ...(input.reason ? { reason: again } : { comment: again }), again: true });
|
|
431
|
+
} catch (e) { toast(errorText(e), false); return null; }
|
|
432
|
+
}
|
|
433
|
+
toast(errorText(err), false);
|
|
434
|
+
return null;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/** Answering a blocked card: the answer as a comment, and the card back in progress. */
|
|
439
|
+
export async function answerBlocked(card) {
|
|
440
|
+
const text = await askText({ title: t("tasks.answerTitle", card.id), label: t("tasks.answerLabel", card.assignee || "—", card.blockedReason), required: true, confirmLabel: t("tasks.answerConfirm") });
|
|
441
|
+
if (!text) return null;
|
|
442
|
+
return moveCard(card, "claimed", { comment: text });
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// ── Small pieces ──────────────────────────────────────────
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* #2299: the bar is the percentage beside it — only done work fills it, so 0 % never looks full (a project whose only
|
|
449
|
+
* card was blocked drew a full red bar). What waits for the person or is blocked is said by the card's chips.
|
|
450
|
+
*/
|
|
451
|
+
export function ProgressBar({ progress, wide = false }) {
|
|
452
|
+
return html`<svg class=${`tb-bar${wide ? " wide" : ""}`} viewBox="0 0 100 6" preserveAspectRatio="none" aria-hidden="true" focusable="false">
|
|
453
|
+
<rect class="tb-bar-track" width="100" height="6" />
|
|
454
|
+
${barSegments(progress).filter((s) => s.k === "done").map((s) => html`<rect key=${s.k} class=${`tb-seg st-${s.k}`} x=${s.x} width=${s.w} height="6" />`)}</svg>`;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export function StatusPill({ status }) {
|
|
458
|
+
return html`<span class=${`tb-pill st-${status}`}>${t(`tasks.${status}`)}</span>`;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Who a card is with, as taskhall shows it: a round initial, then the name. An instance's initial takes its identity
|
|
463
|
+
* colour (#1958, the sidebar's), painted through the CSSOM; a person's, or anyone not in the fleet, stays grey.
|
|
464
|
+
*/
|
|
465
|
+
export function Who({ name, title, empty = "—" }) {
|
|
466
|
+
const { instances } = useStore(appStore);
|
|
467
|
+
useIdentityColors();
|
|
468
|
+
if (!name) return html`<span class="tb-person none"><span class="tb-who">${empty}</span></span>`;
|
|
469
|
+
const it = (instances || []).find((i) => i.name === name);
|
|
470
|
+
const id = it ? identityOf(it) : null;
|
|
471
|
+
return html`<span class="tb-person" title=${title || name}>
|
|
472
|
+
<span class="tb-av idc" aria-hidden="true" ref=${(el) => paintIdentity(el, id)}>${initialOf(name)}</span><span class="tb-who">${name}</span></span>`;
|
|
473
|
+
}
|
|
474
|
+
const initialOf = (name) => (Array.from(name.trim())[0] || "?").toLocaleUpperCase();
|
|
475
|
+
|
|
476
|
+
/** A per-device preference (localStorage may be unavailable: then nothing is remembered). */
|
|
477
|
+
export function readStored(key, fallback) {
|
|
478
|
+
try { const v = localStorage.getItem(key); return v === null ? fallback : v; } catch { return fallback; }
|
|
479
|
+
}
|
|
480
|
+
export function writeStored(key, value) {
|
|
481
|
+
try { if (value === null) localStorage.removeItem(key); else localStorage.setItem(key, value); } catch { /* private mode */ }
|
|
482
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// #2246 step 3: who works on what on the task board — each instance's cards as its `task mine` reads them (GET
|
|
2
|
+
// /ui/tasks/work, the server's myWork): the board's Instance list, a drawer by team as taskhall's, and the block on an
|
|
3
|
+
// instance's Details page. A card opens on the board. No style attribute anywhere (the CSP).
|
|
4
|
+
import { html, useEffect, useState } from "/assets/app-html.js";
|
|
5
|
+
import { t } from "/assets/app-i18n.js";
|
|
6
|
+
import { appStore, useStore } from "/assets/app-store.js";
|
|
7
|
+
import { Dialog } from "/assets/ui-dialog.js";
|
|
8
|
+
import { Icon } from "/assets/ui-icons.js";
|
|
9
|
+
import { Skeleton } from "/assets/ui-states.js";
|
|
10
|
+
import { GroupMark, InstanceAvatar, dotLabel, dotState, groupKind, groupLabel, groupOf, namesOf, namesStore } from "/assets/instance-nav.js";
|
|
11
|
+
import { Who, boardApi, errorText } from "./fleet-task-common.js";
|
|
12
|
+
|
|
13
|
+
const LABEL = { back: "tasks.workSentBack", doing: "tasks.workDoing", blocked: "tasks.workBlocked", review: "tasks.workReview", main: "tasks.workMain", ready: "tasks.workReady", waiting: "tasks.workWaiting" };
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* An instance's work as lines, in taskhall's order: what it works on, is blocked on, waits on the person for, the main
|
|
17
|
+
* tasks it coordinates, what it can start, what waits for other cards. A card sent back to it says so instead.
|
|
18
|
+
*/
|
|
19
|
+
export function workLines(w) {
|
|
20
|
+
const back = new Set(w.sentBack || []), unread = new Set(w.newComments || []);
|
|
21
|
+
const line = (kind, card, note = "") => ({ kind: kind !== "main" && back.has(card.id) ? "back" : kind, card, note, unread: unread.has(card.id) });
|
|
22
|
+
return [
|
|
23
|
+
...(w.doing || []).map((c) => line("doing", c)),
|
|
24
|
+
...(w.blocked || []).map((c) => line("blocked", c)),
|
|
25
|
+
...(w.review || []).map((c) => line("review", c)),
|
|
26
|
+
...(w.mains || []).map((c) => line("main", c, c.progress && c.progress.total ? t("tasks.workSubs", c.progress.done, c.progress.total) : "")),
|
|
27
|
+
...(w.ready || []).map((c) => line("ready", c, c.assignee ? "" : t("tasks.workClaimable"))),
|
|
28
|
+
...(w.waiting || []).map((c) => line("waiting", c, t("tasks.workWaitsFor", (c.unmetDeps || []).join(t("tasks.workJoin"))))),
|
|
29
|
+
];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function WorkLines({ lines, onOpen }) {
|
|
33
|
+
if (!lines.length) return html`<p class="muted tw-none">${t("tasks.workNone")}</p>`;
|
|
34
|
+
return html`<ul class="tw-lines">${lines.map((l) => html`<li key=${`${l.kind}:${l.card.id}`}>
|
|
35
|
+
<button type="button" class="tw-line" title=${`${l.card.id} ${l.card.title}`} onClick=${() => onOpen(l.card.id)}>
|
|
36
|
+
<span class=${`tw-kind k-${l.kind}`}>${t(LABEL[l.kind])}</span><span class="tb-code">${l.card.id}</span><span class="tw-title">${l.card.title}</span>
|
|
37
|
+
${l.note ? html`<span class="muted tw-note">${l.note}</span>` : null}
|
|
38
|
+
${l.unread ? html`<span class="tw-unread" title=${t("tasks.workNewComments")} aria-label=${t("tasks.workNewComments")}><${Icon} name="chat" size=${13} /></span>` : null}
|
|
39
|
+
</button></li>`)}</ul>`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const OUTSIDE = "\u0000outside";
|
|
43
|
+
/** Groups as the sidebar orders them: teams, then tags, then the rest; names nobody in the fleet has last. */
|
|
44
|
+
const groupRank = (g) => (g === OUTSIDE ? 3 : groupKind(g) === "team" ? 0 : groupKind(g) === "tag" ? 1 : 2);
|
|
45
|
+
|
|
46
|
+
/** The board's Instance list: every instance by team, working ones first, each with its cards. Read again on each board change. */
|
|
47
|
+
export function InstancesDrawer({ tick, onClose, onOpen }) {
|
|
48
|
+
const { instances, exec, awaiting } = useStore(appStore);
|
|
49
|
+
useStore(namesStore); // the sidebar's Names choice: display name or instance name first
|
|
50
|
+
const [work, setWork] = useState(null);
|
|
51
|
+
const [error, setError] = useState("");
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
let live = true;
|
|
54
|
+
boardApi.work().then((d) => { if (live) { setWork(d.instances || []); setError(""); } }, (e) => { if (live) setError(errorText(e)); });
|
|
55
|
+
return () => { live = false; };
|
|
56
|
+
}, [tick]);
|
|
57
|
+
const byName = new Map((instances || []).map((i) => [i.name, i]));
|
|
58
|
+
const rows = (work || []).map((w) => {
|
|
59
|
+
const it = byName.get(w.name);
|
|
60
|
+
return { w, it, state: it ? dotState(it, exec[w.name], awaiting[w.name]) : null, lines: workLines(w) };
|
|
61
|
+
});
|
|
62
|
+
// Working first, then those with cards, then the running ones; by name.
|
|
63
|
+
const rank = (r) => (r.state === "working" ? 0 : r.lines.length ? 1 : r.it && r.it.status === "running" ? 2 : 3);
|
|
64
|
+
rows.sort((a, b) => rank(a) - rank(b) || a.w.name.localeCompare(b.w.name));
|
|
65
|
+
const groups = new Map();
|
|
66
|
+
for (const r of rows) {
|
|
67
|
+
const g = r.it ? groupOf(r.it) : OUTSIDE;
|
|
68
|
+
if (!groups.has(g)) groups.set(g, []);
|
|
69
|
+
groups.get(g).push(r);
|
|
70
|
+
}
|
|
71
|
+
const ordered = [...groups].sort(([a], [b]) => groupRank(a) - groupRank(b));
|
|
72
|
+
const working = rows.filter((r) => r.state === "working").length;
|
|
73
|
+
return html`<${Dialog} title=${t("tasks.instances")} onClose=${onClose} wide drawer>
|
|
74
|
+
<div class="tw">
|
|
75
|
+
${work ? html`<p class="muted tw-head">${t("tasks.instancesHead", rows.length, working)}</p>` : null}
|
|
76
|
+
${error ? html`<p class="tw-error" role="alert">${t("tasks.workFailed", error)}</p>` : null}
|
|
77
|
+
${!work && !error ? html`<${Skeleton} lines=${4} />` : null}
|
|
78
|
+
${ordered.map(([g, list]) => html`<section key=${g} class="tw-group">
|
|
79
|
+
<h3 class="tw-group-head">${g === OUTSIDE ? t("tasks.workOutside") : html`<${GroupMark} group=${g} />${groupLabel(g)}`}<span class="tb-count">${list.length}</span></h3>
|
|
80
|
+
${list.map((r) => html`<div key=${r.w.name} class="tw-inst">
|
|
81
|
+
<div class="tw-inst-head">
|
|
82
|
+
${r.it ? html`<${InstanceAvatar} it=${r.it} state=${r.state} />` : html`<${Who} name=${r.w.name} />`}
|
|
83
|
+
${r.it ? (() => { const n = namesOf(r.it); return html`<span class="tw-name" title=${r.w.name}>${n.primary}</span>${n.secondary ? html`<span class="muted tw-alt">${n.secondary}</span>` : null}`; })() : null}
|
|
84
|
+
${r.state ? html`<span class="muted tw-state">${dotLabel(r.state)}</span>` : null}
|
|
85
|
+
</div>
|
|
86
|
+
${r.it && r.it.description ? html`<p class="muted tw-desc">${r.it.description}</p>` : null}
|
|
87
|
+
<${WorkLines} lines=${r.lines} onOpen=${onOpen} />
|
|
88
|
+
</div>`)}
|
|
89
|
+
</section>`)}
|
|
90
|
+
</div>
|
|
91
|
+
</${Dialog}>`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** An instance's Details page: its cards, read once when the page opens (the page reads nothing recurring, #1374). */
|
|
95
|
+
export function InstanceBoardWork({ name, onOpen }) {
|
|
96
|
+
const [work, setWork] = useState(null);
|
|
97
|
+
const [error, setError] = useState("");
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
let live = true;
|
|
100
|
+
setWork(null); setError("");
|
|
101
|
+
boardApi.work(name).then((d) => { if (live) setWork((d.instances || [])[0] || { name }); }, (e) => { if (live) setError(errorText(e)); });
|
|
102
|
+
return () => { live = false; };
|
|
103
|
+
}, [name]);
|
|
104
|
+
return html`<section class="card d-board"><h3>${t("tasks.detailsBoard")}</h3>
|
|
105
|
+
${error ? html`<p class="note">${t("tasks.workFailed", error)}</p>` : !work ? html`<${Skeleton} lines=${2} />` : html`<${WorkLines} lines=${workLines(work)} onOpen=${onOpen} />`}
|
|
106
|
+
</section>`;
|
|
107
|
+
}
|