@songsid/agend 2.3.0-beta.8 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -8
- package/README.zh-TW.md +16 -8
- package/dist/adapter-world.js.map +1 -1
- package/dist/agend-home.d.ts +5 -0
- package/dist/agend-home.js +7 -0
- package/dist/agend-home.js.map +1 -0
- package/dist/agent-cli-instructions.md +9 -2
- package/dist/agent-cli.js +44 -0
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.d.ts +9 -0
- package/dist/agent-endpoint.js +23 -0
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-file-read.js +1 -1
- package/dist/agent-file-read.js.map +1 -1
- package/dist/agent-whats-new.d.ts +16 -0
- package/dist/agent-whats-new.js +54 -11
- package/dist/agent-whats-new.js.map +1 -1
- package/dist/apply-job.js.map +1 -1
- package/dist/atomic-write.js.map +1 -1
- package/dist/auth-api.d.ts +12 -0
- package/dist/auth-api.js +77 -22
- package/dist/auth-api.js.map +1 -1
- package/dist/authority/authority-state.d.ts +4 -0
- package/dist/authority/authority-state.js +17 -8
- package/dist/authority/authority-state.js.map +1 -1
- package/dist/authority/session-authorizations.js.map +1 -1
- package/dist/authority/web-authority.d.ts +16 -8
- package/dist/authority/web-authority.js +19 -5
- package/dist/authority/web-authority.js.map +1 -1
- package/dist/backend/antigravity.d.ts +2 -2
- package/dist/backend/antigravity.js +2 -1
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-code.js +13 -4
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/codex-metadata.d.ts +8 -0
- package/dist/backend/codex-metadata.js +74 -17
- package/dist/backend/codex-metadata.js.map +1 -1
- package/dist/backend/codex-package.d.ts +30 -0
- package/dist/backend/codex-package.js +133 -0
- package/dist/backend/codex-package.js.map +1 -0
- package/dist/backend/codex-session-lookup.js.map +1 -1
- package/dist/backend/codex.d.ts +2 -0
- package/dist/backend/codex.js +25 -5
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/credential-profile.d.ts +2 -0
- package/dist/backend/credential-profile.js +2 -0
- package/dist/backend/credential-profile.js.map +1 -1
- package/dist/backend/effort-metadata.js.map +1 -1
- package/dist/backend/grok.js +58 -3
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro-engine-ledger.js.map +1 -1
- package/dist/backend/kiro-kas-store.js.map +1 -1
- package/dist/backend/kiro-v2-store.js.map +1 -1
- package/dist/backend/kiro-v3-identity.js.map +1 -1
- package/dist/backend/kiro.d.ts +9 -1
- package/dist/backend/kiro.js +102 -1
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/launch-effort.js.map +1 -1
- package/dist/backend/mock.js.map +1 -1
- package/dist/backend/muse.js.map +1 -1
- package/dist/backend/opencode-permission.js +1 -1
- package/dist/backend/opencode-permission.js.map +1 -1
- package/dist/backend/opencode.js +2 -1
- package/dist/backend/opencode.js.map +1 -1
- package/dist/backend/session-signals.js.map +1 -1
- package/dist/backend-availability.js.map +1 -1
- package/dist/backend-command.d.ts +2 -0
- package/dist/backend-command.js +3 -1
- package/dist/backend-command.js.map +1 -1
- package/dist/backend-outage.js.map +1 -1
- package/dist/binary-probe.js +1 -1
- package/dist/binary-probe.js.map +1 -1
- package/dist/bug-report-cli.d.ts +30 -0
- package/dist/bug-report-cli.js +139 -0
- package/dist/bug-report-cli.js.map +1 -0
- package/dist/bug-report.d.ts +47 -0
- package/dist/bug-report.js +137 -0
- package/dist/bug-report.js.map +1 -0
- package/dist/bundled-skills.d.ts +18 -0
- package/dist/bundled-skills.js +38 -0
- package/dist/bundled-skills.js.map +1 -0
- package/dist/cache-service.js +1 -1
- package/dist/cache-service.js.map +1 -1
- package/dist/channel/adapters/discord-client-retirement.d.ts +5 -0
- package/dist/channel/adapters/discord-client-retirement.js +57 -0
- package/dist/channel/adapters/discord-client-retirement.js.map +1 -0
- package/dist/channel/adapters/discord.d.ts +4 -0
- package/dist/channel/adapters/discord.js +57 -12
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +6 -0
- package/dist/channel/adapters/telegram.js +54 -14
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/mcp-server.js +21 -4
- package/dist/channel/mcp-server.js.map +1 -1
- package/dist/channel/mcp-tools.d.ts +3 -1
- package/dist/channel/mcp-tools.js +43 -6
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/message-queue.js.map +1 -1
- package/dist/channel/sticker-download.js.map +1 -1
- package/dist/channel/tool-router.js.map +1 -1
- package/dist/child-process.d.ts +21 -0
- package/dist/child-process.js +54 -0
- package/dist/child-process.js.map +1 -0
- package/dist/classic-channel-manager.js +3 -2
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli-entry.js.map +1 -1
- package/dist/cli-flags.js.map +1 -1
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +443 -311
- package/dist/cli.js.map +1 -1
- package/dist/command-table.d.ts +1 -1
- package/dist/command-table.js +1 -1
- package/dist/command-table.js.map +1 -1
- package/dist/compact-watch.js.map +1 -1
- package/dist/completion-install.js.map +1 -1
- package/dist/completion.js.map +1 -1
- package/dist/config-validator.d.ts +6 -0
- package/dist/config-validator.js +81 -8
- package/dist/config-validator.js.map +1 -1
- package/dist/config.d.ts +15 -3
- package/dist/config.js +41 -10
- package/dist/config.js.map +1 -1
- package/dist/connection-secrets.js.map +1 -1
- package/dist/context-guardian.js.map +1 -1
- package/dist/coredump-filter.js.map +1 -1
- package/dist/cpu-profile.js.map +1 -1
- package/dist/cross-instance-envelope.js.map +1 -1
- package/dist/cross-instance-notice.d.ts +7 -0
- package/dist/cross-instance-notice.js +10 -0
- package/dist/cross-instance-notice.js.map +1 -1
- package/dist/daemon.d.ts +39 -1
- package/dist/daemon.js +234 -15
- package/dist/daemon.js.map +1 -1
- package/dist/daily-summary.js.map +1 -1
- package/dist/darwin-memory.js +1 -1
- package/dist/darwin-memory.js.map +1 -1
- package/dist/dashboard-live.d.ts +8 -0
- package/dist/dashboard-live.js +35 -0
- package/dist/dashboard-live.js.map +1 -0
- package/dist/dashboard-permissions.d.ts +69 -0
- package/dist/dashboard-permissions.js +138 -0
- package/dist/dashboard-permissions.js.map +1 -0
- package/dist/decision-list.d.ts +25 -0
- package/dist/decision-list.js +30 -0
- package/dist/decision-list.js.map +1 -0
- package/dist/delivery-consumed-watch.js.map +1 -1
- package/dist/delivery-outbox.js +5 -0
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/delivery-outbox.test.js.map +1 -1
- package/dist/delivery-reconciliation.test.js.map +1 -1
- package/dist/diagnostic-redaction.d.ts +10 -0
- package/dist/diagnostic-redaction.js +167 -0
- package/dist/diagnostic-redaction.js.map +1 -0
- package/dist/doctor.d.ts +8 -0
- package/dist/doctor.js +52 -0
- package/dist/doctor.js.map +1 -1
- package/dist/e2e-isolation.js.map +1 -1
- package/dist/event-log.js.map +1 -1
- package/dist/export-import.js +7 -5
- package/dist/export-import.js.map +1 -1
- package/dist/fleet-control-audit.js.map +1 -1
- package/dist/fleet-label.js.map +1 -1
- package/dist/fleet-level-config.d.ts +1 -1
- package/dist/fleet-level-config.js +2 -0
- package/dist/fleet-level-config.js.map +1 -1
- package/dist/fleet-lock.js +3 -2
- package/dist/fleet-lock.js.map +1 -1
- package/dist/fleet-manager.d.ts +258 -15
- package/dist/fleet-manager.js +1605 -304
- package/dist/fleet-manager.js.map +1 -1
- package/dist/fleet-process-handlers.d.ts +18 -0
- package/dist/fleet-process-handlers.js +70 -0
- package/dist/fleet-process-handlers.js.map +1 -0
- package/dist/fleet-startup.d.ts +14 -0
- package/dist/fleet-startup.js +30 -0
- package/dist/fleet-startup.js.map +1 -0
- package/dist/fleet-traffic.d.ts +36 -0
- package/dist/fleet-traffic.js +100 -0
- package/dist/fleet-traffic.js.map +1 -1
- package/dist/forged-envelope-scan.d.ts +0 -20
- package/dist/forged-envelope-scan.js +3 -2
- package/dist/forged-envelope-scan.js.map +1 -1
- package/dist/full-restart.d.ts +5 -5
- package/dist/full-restart.js +5 -5
- package/dist/full-restart.js.map +1 -1
- package/dist/general-knowledge/skills/bug-report/SKILL.md +31 -0
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +52 -11
- package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +5 -1
- package/dist/general-knowledge/skills/fleet-config/SKILL.md +3 -1
- package/dist/general-knowledge/skills/fleet-restart/SKILL.md +8 -9
- package/dist/general-knowledge/skills/multi-channel/SKILL.md +1 -1
- package/dist/general-knowledge/skills/persona-emoji/SKILL.md +1 -1
- package/dist/general-knowledge/skills/scheduling/SKILL.md +4 -0
- package/dist/general-knowledge/skills/web-appearance/SKILL.canvas-worker-off.md +321 -0
- package/dist/general-knowledge/skills/web-appearance/SKILL.md +28 -4
- package/dist/general-knowledge/skills/web-dashboard/SKILL.canvas-worker-off.md +553 -0
- package/dist/general-knowledge/skills/web-dashboard/SKILL.md +170 -35
- package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +1 -1
- package/dist/general-knowledge/steering/core-rules.md +1 -1
- package/dist/host-memory.js.map +1 -1
- package/dist/idle-gate-log.d.ts +19 -0
- package/dist/idle-gate-log.js +15 -0
- package/dist/idle-gate-log.js.map +1 -0
- package/dist/instance-config-impact.js +25 -4
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +10 -1
- package/dist/instance-lifecycle.js +86 -25
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instructions.d.ts +12 -6
- package/dist/instructions.js +19 -10
- package/dist/instructions.js.map +1 -1
- package/dist/kiro-compact-pane.js.map +1 -1
- package/dist/kiro-db-reader.js.map +1 -1
- package/dist/kiro-engine-status.js.map +1 -1
- package/dist/kiro-log-gate.js.map +1 -1
- package/dist/kiro-transcript-lane.js.map +1 -1
- package/dist/locale.js +428 -20
- package/dist/locale.js.map +1 -1
- package/dist/log-service.js.map +1 -1
- package/dist/log-steps.d.ts +1 -0
- package/dist/log-steps.js +15 -0
- package/dist/log-steps.js.map +1 -1
- package/dist/logger.js +3 -2
- package/dist/logger.js.map +1 -1
- package/dist/login-controller.d.ts +45 -0
- package/dist/login-controller.js +101 -5
- package/dist/login-controller.js.map +1 -1
- package/dist/login-flows.js +1 -1
- package/dist/login-manager.js.map +1 -1
- package/dist/login-shell.js +3 -1
- package/dist/login-shell.js.map +1 -1
- package/dist/ls-attach-resolve.d.ts +96 -0
- package/dist/ls-attach-resolve.js +180 -0
- package/dist/ls-attach-resolve.js.map +1 -0
- package/dist/ls-rows.d.ts +12 -0
- package/dist/ls-rows.js +83 -4
- package/dist/ls-rows.js.map +1 -1
- package/dist/memory-pressure.js.map +1 -1
- package/dist/muse-usage-relay.js.map +1 -1
- package/dist/needs-you-hub.d.ts +98 -1
- package/dist/needs-you-hub.js +313 -44
- package/dist/needs-you-hub.js.map +1 -1
- package/dist/needs-you-live.d.ts +5 -2
- package/dist/needs-you-live.js +6 -3
- package/dist/needs-you-live.js.map +1 -1
- package/dist/needs-you.d.ts +68 -3
- package/dist/needs-you.js +38 -4
- package/dist/needs-you.js.map +1 -1
- package/dist/network-family.js.map +1 -1
- package/dist/operator-control-paths.js +3 -4
- package/dist/operator-control-paths.js.map +1 -1
- package/dist/outbound-handlers.d.ts +3 -0
- package/dist/outbound-handlers.js +76 -19
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +112 -64
- package/dist/outbound-schemas.js +39 -12
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/outbox-open-error.js.map +1 -1
- package/dist/pane-context-cache.js.map +1 -1
- package/dist/paths.js.map +1 -1
- package/dist/private-dir.js.map +1 -1
- package/dist/probe-worker-pool.js.map +1 -1
- package/dist/profile-control.js.map +1 -1
- package/dist/prompt-file-ref.js.map +1 -1
- package/dist/provider-probe.js.map +1 -1
- package/dist/provider-secret-registry.d.ts +5 -3
- package/dist/provider-secret-registry.js +8 -2
- package/dist/provider-secret-registry.js.map +1 -1
- package/dist/public-link-auto-open.d.ts +32 -0
- package/dist/public-link-auto-open.js +86 -0
- package/dist/public-link-auto-open.js.map +1 -0
- package/dist/public-link-owner.d.ts +10 -0
- package/dist/public-link-owner.js +36 -0
- package/dist/public-link-owner.js.map +1 -0
- package/dist/public-link-progress.d.ts +12 -1
- package/dist/public-link-progress.js +5 -10
- package/dist/public-link-progress.js.map +1 -1
- package/dist/public-preview.js.map +1 -1
- package/dist/public-tunnel-config.d.ts +11 -0
- package/dist/public-tunnel-config.js +68 -0
- package/dist/public-tunnel-config.js.map +1 -0
- package/dist/public-web-gateway.d.ts +2 -0
- package/dist/public-web-gateway.js +19 -6
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/public-web-link.d.ts +48 -3
- package/dist/public-web-link.js +177 -51
- package/dist/public-web-link.js.map +1 -1
- package/dist/quickstart-api.d.ts +9 -0
- package/dist/quickstart-api.js +82 -0
- package/dist/quickstart-api.js.map +1 -1
- package/dist/quickstart.d.ts +5 -0
- package/dist/quickstart.js +40 -25
- package/dist/quickstart.js.map +1 -1
- package/dist/reply-buttons-controller.js.map +1 -1
- package/dist/reply-dedup.js.map +1 -1
- package/dist/resource-report.js +1 -1
- package/dist/resource-report.js.map +1 -1
- package/dist/restart-guard.js.map +1 -1
- package/dist/restart-progress.d.ts +80 -1
- package/dist/restart-progress.js +306 -21
- package/dist/restart-progress.js.map +1 -1
- package/dist/rollout-index.js.map +1 -1
- package/dist/runtime-cpu-profile.js.map +1 -1
- package/dist/scheduler/db.d.ts +40 -13
- package/dist/scheduler/db.js +123 -89
- package/dist/scheduler/db.js.map +1 -1
- package/dist/scheduler/scheduler.js.map +1 -1
- package/dist/scheduler/task-board-text.d.ts +26 -0
- package/dist/scheduler/task-board-text.js +140 -0
- package/dist/scheduler/task-board-text.js.map +1 -0
- package/dist/scheduler/task-board.d.ts +730 -0
- package/dist/scheduler/task-board.js +2179 -0
- package/dist/scheduler/task-board.js.map +1 -0
- package/dist/scheduler/types.d.ts +6 -1
- package/dist/sd-notify.js +2 -1
- package/dist/sd-notify.js.map +1 -1
- package/dist/search/search-docs.d.ts +58 -0
- package/dist/search/search-docs.js +63 -0
- package/dist/search/search-docs.js.map +1 -0
- package/dist/search/search-index.d.ts +141 -0
- package/dist/search/search-index.js +440 -0
- package/dist/search/search-index.js.map +1 -0
- package/dist/search/search-store.d.ts +122 -0
- package/dist/search/search-store.js +236 -0
- package/dist/search/search-store.js.map +1 -0
- package/dist/search/search-worker.d.ts +1 -0
- package/dist/search/search-worker.js +163 -0
- package/dist/search/search-worker.js.map +1 -0
- package/dist/secret-file.js.map +1 -1
- package/dist/secret-store.d.ts +2 -0
- package/dist/secret-store.js +21 -0
- package/dist/secret-store.js.map +1 -1
- package/dist/service-installer.d.ts +75 -0
- package/dist/service-installer.js +206 -0
- package/dist/service-installer.js.map +1 -1
- package/dist/service-owner.d.ts +44 -0
- package/dist/service-owner.js +48 -0
- package/dist/service-owner.js.map +1 -0
- package/dist/service-plan.d.ts +39 -2
- package/dist/service-plan.js +188 -6
- package/dist/service-plan.js.map +1 -1
- package/dist/session-oom.d.ts +21 -0
- package/dist/session-oom.js +139 -0
- package/dist/session-oom.js.map +1 -0
- package/dist/settings-api.d.ts +13 -0
- package/dist/settings-api.js +73 -12
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-baseline.js.map +1 -1
- package/dist/settings-change.d.ts +5 -0
- package/dist/settings-change.js +167 -6
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-confirmation.d.ts +9 -1
- package/dist/settings-confirmation.js +18 -8
- package/dist/settings-confirmation.js.map +1 -1
- package/dist/settings-control.js +2 -1
- package/dist/settings-control.js.map +1 -1
- package/dist/settings-effect.js +29 -4
- package/dist/settings-effect.js.map +1 -1
- package/dist/settings-http-confirmation.d.ts +13 -0
- package/dist/settings-http-confirmation.js +15 -3
- package/dist/settings-http-confirmation.js.map +1 -1
- package/dist/settings-instance-patch.js +13 -1
- package/dist/settings-instance-patch.js.map +1 -1
- package/dist/settings-request-capability.d.ts +4 -1
- package/dist/settings-request-capability.js +11 -3
- package/dist/settings-request-capability.js.map +1 -1
- package/dist/settings-transaction.js.map +1 -1
- package/dist/setup-auth.d.ts +1 -0
- package/dist/setup-auth.js +2 -1
- package/dist/setup-auth.js.map +1 -1
- package/dist/setup-form.d.ts +1 -1
- package/dist/setup-form.js +23 -7
- package/dist/setup-form.js.map +1 -1
- package/dist/setup-host.d.ts +6 -1
- package/dist/setup-host.js +15 -4
- package/dist/setup-host.js.map +1 -1
- package/dist/setup-wizard.js +6 -3
- package/dist/setup-wizard.js.map +1 -1
- package/dist/spawn-gate.d.ts +5 -0
- package/dist/spawn-gate.js +28 -8
- package/dist/spawn-gate.js.map +1 -1
- package/dist/start-attempt.d.ts +1 -0
- package/dist/start-attempt.js +18 -0
- package/dist/start-attempt.js.map +1 -0
- package/dist/start-failure-notice.d.ts +4 -0
- package/dist/start-failure-notice.js +20 -0
- package/dist/start-failure-notice.js.map +1 -0
- package/dist/start-failure.d.ts +147 -0
- package/dist/start-failure.js +281 -0
- package/dist/start-failure.js.map +1 -0
- package/dist/startup-memory-deadline.d.ts +23 -0
- package/dist/startup-memory-deadline.js +55 -0
- package/dist/startup-memory-deadline.js.map +1 -0
- package/dist/statusline-watcher.js.map +1 -1
- package/dist/storm-window.js.map +1 -1
- package/dist/systemd-peer-bus.js.map +1 -1
- package/dist/target-queue-worker.js.map +1 -1
- package/dist/task-board-summary.d.ts +101 -0
- package/dist/task-board-summary.js +177 -0
- package/dist/task-board-summary.js.map +1 -0
- package/dist/task-board-tool.d.ts +25 -0
- package/dist/task-board-tool.js +155 -0
- package/dist/task-board-tool.js.map +1 -0
- package/dist/task-board-waker.d.ts +51 -0
- package/dist/task-board-waker.js +141 -0
- package/dist/task-board-waker.js.map +1 -0
- package/dist/tips.js.map +1 -1
- package/dist/tmux-control.js +1 -1
- package/dist/tmux-control.js.map +1 -1
- package/dist/tmux-exec-helper.d.ts +104 -0
- package/dist/tmux-exec-helper.js +412 -0
- package/dist/tmux-exec-helper.js.map +1 -0
- package/dist/tmux-manager.d.ts +1 -0
- package/dist/tmux-manager.js +29 -13
- package/dist/tmux-manager.js.map +1 -1
- package/dist/tmux-read.js +2 -2
- package/dist/tmux-read.js.map +1 -1
- package/dist/tool-permissions.js +9 -42
- package/dist/tool-permissions.js.map +1 -1
- package/dist/tool-progress.js.map +1 -1
- package/dist/topic-archiver.js.map +1 -1
- package/dist/topic-commands.d.ts +13 -0
- package/dist/topic-commands.js +56 -33
- package/dist/topic-commands.js.map +1 -1
- package/dist/topic-link.js.map +1 -1
- package/dist/transcript-delta-reader.js.map +1 -1
- package/dist/transcript-jsonl.js.map +1 -1
- package/dist/transcript-monitor.js +5 -0
- package/dist/transcript-monitor.js.map +1 -1
- package/dist/transcript-sources.d.ts +2 -0
- package/dist/transcript-sources.js +4 -0
- package/dist/transcript-sources.js.map +1 -1
- package/dist/tunnel/cloudflared-install.js +3 -1
- package/dist/tunnel/cloudflared-install.js.map +1 -1
- package/dist/tunnel/cloudflared.d.ts +7 -16
- package/dist/tunnel/cloudflared.js +100 -13
- package/dist/tunnel/cloudflared.js.map +1 -1
- package/dist/tunnel/lease.js +3 -2
- package/dist/tunnel/lease.js.map +1 -1
- package/dist/tunnel/manager.js.map +1 -1
- package/dist/tunnel/named-diagnostics.d.ts +13 -0
- package/dist/tunnel/named-diagnostics.js +52 -0
- package/dist/tunnel/named-diagnostics.js.map +1 -0
- package/dist/tunnel/public-fetch.js.map +1 -1
- package/dist/tunnel/purpose-lane.js.map +1 -1
- package/dist/tunnel/types.d.ts +4 -1
- package/dist/tunnel/types.js.map +1 -1
- package/dist/types.d.ts +55 -2
- package/dist/ui/app-effects.js +27 -5
- package/dist/ui/app.html +2 -0
- package/dist/ui/backend-signin.js +297 -0
- package/dist/ui/chat-effects.js +15 -7
- package/dist/ui/chat-msg-actions.js +176 -0
- package/dist/ui/chat-render.js +67 -20
- package/dist/ui/chat-store.js +218 -48
- package/dist/ui/chat-strings.js +42 -10
- package/dist/ui/chat-thread.js +249 -23
- package/dist/ui/effect-trial-controller.js +13 -8
- package/dist/ui/effect-trial-offer.js +2 -31
- package/dist/ui/effects-waker.js +2 -0
- package/dist/ui/fleet-canvas-layout.js +13 -4
- package/dist/ui/fleet-canvas.js +120 -43
- package/dist/ui/fleet-office-editor.js +149 -0
- package/dist/ui/fleet-office-model.js +358 -0
- package/dist/ui/fleet-office-pack.js +199 -0
- package/dist/ui/fleet-office-skin.js +474 -0
- package/dist/ui/fleet-office-store.js +49 -0
- package/dist/ui/fleet-office-zones.js +177 -0
- package/dist/ui/fleet-office.js +434 -0
- package/dist/ui/fleet-org.js +21 -8
- package/dist/ui/fleet-route-scene.js +272 -0
- package/dist/ui/fleet-route-worker.js +21 -0
- package/dist/ui/fleet-route.js +88 -0
- package/dist/ui/fleet-task-card.js +436 -0
- package/dist/ui/fleet-task-common.js +482 -0
- package/dist/ui/fleet-task-work.js +107 -0
- package/dist/ui/fleet-tasks.js +569 -0
- package/dist/ui/fleet-traffic.js +227 -45
- package/dist/ui/fleet-usage.js +36 -2
- package/dist/ui/guest-refused.html +41 -0
- package/dist/ui/icons/icon-192.png +0 -0
- package/dist/ui/icons/icon-512.png +0 -0
- package/dist/ui/image-lightbox.js +45 -1
- package/dist/ui/image-zoom.js +242 -0
- package/dist/ui/panel-chat.js +282 -89
- package/dist/ui/panel-details.js +2 -0
- package/dist/ui/panel-fleet.js +32 -71
- package/dist/ui/panel-needs.js +23 -6
- package/dist/ui/panel-settings.js +158 -32
- package/dist/ui/preview-panel.js +2 -1
- package/dist/ui/search-dialog.js +350 -0
- package/dist/ui/settings-appearance.js +170 -10
- package/dist/ui/settings-apply.js +3 -3
- package/dist/ui/settings-confirm.js +7 -2
- package/dist/ui/settings-dialogs.js +46 -21
- package/dist/ui/settings-discord.js +6 -2
- package/dist/ui/settings-guests.js +2 -1
- package/dist/ui/settings-learn.js +1 -0
- package/dist/ui/settings-model.js +51 -18
- package/dist/ui/settings-mods.js +8 -3
- package/dist/ui/settings-owner-effects.js +6 -4
- package/dist/ui/settings-strings.js +180 -6
- package/dist/ui/settings-token.js +3 -1
- package/dist/ui/settings-web-authority.js +13 -5
- package/dist/ui/settings-wizard.js +13 -7
- package/dist/ui/shared/agend-auth.js +3 -1
- package/dist/ui/shared/app-i18n.js +12 -5
- package/dist/ui/shared/app-needs.js +2 -2
- package/dist/ui/shared/app-prefs.js +15 -0
- package/dist/ui/shared/app-route.js +18 -0
- package/dist/ui/shared/app-shell.js +172 -28
- package/dist/ui/shared/app-store.js +3 -2
- package/dist/ui/shared/app-stream.js +7 -2
- package/dist/ui/shared/app-themes.js +116 -1
- package/dist/ui/shared/app.css +681 -54
- package/dist/ui/shared/app.js +9 -1
- package/dist/ui/shared/card-strings.js +4 -0
- package/dist/ui/shared/effect-app-runtime.js +7 -5
- package/dist/ui/shared/effect-chat-runtime.js +2 -7
- package/dist/ui/shared/effect-cursor.js +3 -2
- package/dist/ui/shared/effect-display-metadata.js +39 -0
- package/dist/ui/shared/effect-owner-source.js +8 -1
- package/dist/ui/shared/effect-policy.js +2 -2
- package/dist/ui/shared/effect-registry.js +30 -11
- package/dist/ui/shared/effect-runtime-loader.js +3 -1
- package/dist/ui/shared/effect-stock-snapshot.js +9 -0
- package/dist/ui/shared/effect-stock-trust.js +40 -9
- package/dist/ui/shared/effect-trial-source.js +1 -1
- package/dist/ui/shared/effect-trial-stage.js +27 -21
- package/dist/ui/shared/effect-trial.css +1 -1
- package/dist/ui/shared/feature-flags.js +127 -0
- package/dist/ui/shared/guest-refused.js +35 -0
- package/dist/ui/shared/header-tools.js +2 -2
- package/dist/ui/shared/identity-card.js +26 -8
- package/dist/ui/shared/identity-color.js +17 -10
- package/dist/ui/shared/instance-nav.js +183 -28
- package/dist/ui/shared/owner-css.js +30 -1
- package/dist/ui/shared/panel-view.js +14 -29
- package/dist/ui/shared/text-undo.js +210 -0
- package/dist/ui/shared/tokens.css +13 -3
- package/dist/ui/shared/ui-dialog.js +5 -4
- package/dist/ui/shared/ui-icons.js +4 -0
- package/dist/ui/shared/ui-menu.js +20 -7
- package/dist/ui/shared/ui-toast.js +16 -3
- package/dist/ui/shared/usage-dialog.js +206 -16
- package/dist/ui/shared/view-strings.js +68 -4
- package/dist/ui/shared/web-authorize.js +50 -1
- package/dist/ui/signin.html +2 -0
- package/dist/ui/web-terminal/terminal.css +4 -4
- package/dist/ui/web-terminal/terminal.html +10 -10
- package/dist/ui/web-terminal/terminal.js +58 -12
- package/dist/update-check.js.map +1 -1
- package/dist/update-dispatch.js +1 -1
- package/dist/update-dispatch.js.map +1 -1
- package/dist/update-install.js.map +1 -1
- package/dist/update-launch.d.ts +10 -1
- package/dist/update-launch.js +39 -14
- package/dist/update-launch.js.map +1 -1
- package/dist/update-marker.js.map +1 -1
- package/dist/update-preflight.js +1 -1
- package/dist/update-preflight.js.map +1 -1
- package/dist/update-progress.d.ts +3 -1
- package/dist/update-progress.js +3 -1
- package/dist/update-progress.js.map +1 -1
- package/dist/usage/format-rich.js +6 -3
- package/dist/usage/format-rich.js.map +1 -1
- package/dist/usage/i18n-keys.d.ts +1 -1
- package/dist/usage/i18n-keys.js +2 -1
- package/dist/usage/i18n-keys.js.map +1 -1
- package/dist/usage/i18n.d.ts +13 -1
- package/dist/usage/i18n.js +29 -0
- package/dist/usage/i18n.js.map +1 -1
- package/dist/usage/providers.d.ts +89 -2
- package/dist/usage/providers.js +247 -41
- package/dist/usage/providers.js.map +1 -1
- package/dist/usage/statusline-usage.js.map +1 -1
- package/dist/usage/usage-api.d.ts +5 -1
- package/dist/usage/usage-api.js +185 -58
- package/dist/usage/usage-api.js.map +1 -1
- package/dist/usage-report.js.map +1 -1
- package/dist/usage-rollup.js +1 -1
- package/dist/usage-rollup.js.map +1 -1
- package/dist/user-systemd.d.ts +24 -0
- package/dist/user-systemd.js +75 -0
- package/dist/user-systemd.js.map +1 -0
- package/dist/view-api.d.ts +7 -0
- package/dist/view-api.js +16 -4
- package/dist/view-api.js.map +1 -1
- package/dist/wake-coordinator.js.map +1 -1
- package/dist/web-ambient.js +9 -2
- package/dist/web-ambient.js.map +1 -1
- package/dist/web-api.d.ts +58 -10
- package/dist/web-api.js +1104 -71
- package/dist/web-api.js.map +1 -1
- package/dist/web-app-icon-worker.d.ts +1 -0
- package/dist/web-app-icon-worker.js +16 -0
- package/dist/web-app-icon-worker.js.map +1 -0
- package/dist/web-app-icon.d.ts +109 -0
- package/dist/web-app-icon.js +257 -0
- package/dist/web-app-icon.js.map +1 -0
- package/dist/web-appearance-policy.js.map +1 -1
- package/dist/web-appearance-tools.d.ts +1 -0
- package/dist/web-appearance-tools.js +7 -3
- package/dist/web-appearance-tools.js.map +1 -1
- package/dist/web-appearance-view.js.map +1 -1
- package/dist/web-appearance.d.ts +4 -10
- package/dist/web-appearance.js +7 -4
- package/dist/web-appearance.js.map +1 -1
- package/dist/web-auth.d.ts +8 -4
- package/dist/web-auth.js +33 -21
- package/dist/web-auth.js.map +1 -1
- package/dist/web-backend-login.d.ts +130 -0
- package/dist/web-backend-login.js +225 -0
- package/dist/web-backend-login.js.map +1 -0
- package/dist/web-card.js.map +1 -1
- package/dist/web-channel-echo.js.map +1 -1
- package/dist/web-chat-history.d.ts +118 -8
- package/dist/web-chat-history.js +220 -25
- package/dist/web-chat-history.js.map +1 -1
- package/dist/web-commands.d.ts +5 -1
- package/dist/web-commands.js +1 -1
- package/dist/web-commands.js.map +1 -1
- package/dist/web-cookie-names.d.ts +5 -0
- package/dist/web-cookie-names.js +12 -0
- package/dist/web-cookie-names.js.map +1 -0
- package/dist/web-effect-bundle.d.ts +2 -2
- package/dist/web-effect-library.js.map +1 -1
- package/dist/web-effect-playback.js.map +1 -1
- package/dist/web-effect-profiles.d.ts +16 -16
- package/dist/web-effect-profiles.js +3 -2
- package/dist/web-effect-profiles.js.map +1 -1
- package/dist/web-effect-service.js.map +1 -1
- package/dist/web-effect-tools.js.map +1 -1
- package/dist/web-effect-trials.js.map +1 -1
- package/dist/web-effect-upload.js.map +1 -1
- package/dist/web-effect.d.ts +6 -6
- package/dist/web-effect.js.map +1 -1
- package/dist/web-experimental-http.d.ts +2 -0
- package/dist/web-experimental-http.js +12 -0
- package/dist/web-experimental-http.js.map +1 -0
- package/dist/web-experimental.d.ts +11 -0
- package/dist/web-experimental.js +49 -0
- package/dist/web-experimental.js.map +1 -0
- package/dist/web-guest-access.d.ts +4 -2
- package/dist/web-guest-access.js +22 -10
- package/dist/web-guest-access.js.map +1 -1
- package/dist/web-guest-rooms.js.map +1 -1
- package/dist/web-host-guard.d.ts +11 -0
- package/dist/web-host-guard.js +11 -0
- package/dist/web-host-guard.js.map +1 -1
- package/dist/web-icons.d.ts +33 -1
- package/dist/web-icons.js +83 -11
- package/dist/web-icons.js.map +1 -1
- package/dist/web-identity-color.js.map +1 -1
- package/dist/web-image-meta.d.ts +13 -0
- package/dist/web-image-meta.js +62 -0
- package/dist/web-image-meta.js.map +1 -1
- package/dist/web-images.js.map +1 -1
- package/dist/web-libavoid.d.ts +14 -0
- package/dist/web-libavoid.js +46 -0
- package/dist/web-libavoid.js.map +1 -0
- package/dist/web-login.js.map +1 -1
- package/dist/web-mentions.js.map +1 -1
- package/dist/web-mod-agent.js.map +1 -1
- package/dist/web-mod-store.d.ts +2 -0
- package/dist/web-mod-store.js +10 -0
- package/dist/web-mod-store.js.map +1 -1
- package/dist/web-office-store.d.ts +104 -0
- package/dist/web-office-store.js +236 -0
- package/dist/web-office-store.js.map +1 -0
- package/dist/web-owner-css-store.d.ts +44 -1
- package/dist/web-owner-css-store.js +70 -9
- package/dist/web-owner-css-store.js.map +1 -1
- package/dist/web-owner-css.js.map +1 -1
- package/dist/web-png.d.ts +33 -0
- package/dist/web-png.js +329 -0
- package/dist/web-png.js.map +1 -0
- package/dist/web-prefs.d.ts +6 -0
- package/dist/web-prefs.js +29 -3
- package/dist/web-prefs.js.map +1 -1
- package/dist/web-preview.d.ts +2 -0
- package/dist/web-preview.js +2 -0
- package/dist/web-preview.js.map +1 -1
- package/dist/web-profile.js.map +1 -1
- package/dist/web-reactions.d.ts +35 -0
- package/dist/web-reactions.js +47 -0
- package/dist/web-reactions.js.map +1 -0
- package/dist/web-request-context.d.ts +5 -0
- package/dist/web-request-context.js.map +1 -1
- package/dist/web-returning-device.d.ts +4 -2
- package/dist/web-returning-device.js +13 -6
- package/dist/web-returning-device.js.map +1 -1
- package/dist/web-schedules.js.map +1 -1
- package/dist/web-send-dedupe.d.ts +36 -0
- package/dist/web-send-dedupe.js +69 -0
- package/dist/web-send-dedupe.js.map +1 -0
- package/dist/web-session-authorization.js.map +1 -1
- package/dist/web-session.js +1 -1
- package/dist/web-session.js.map +1 -1
- package/dist/web-settings-patch.d.ts +3 -1
- package/dist/web-settings-patch.js +11 -5
- package/dist/web-settings-patch.js.map +1 -1
- package/dist/web-settings-tools.d.ts +6 -0
- package/dist/web-settings-tools.js +52 -17
- package/dist/web-settings-tools.js.map +1 -1
- package/dist/web-terminal-http.js +15 -2
- package/dist/web-terminal-http.js.map +1 -1
- package/dist/web-terminal.js +1 -1
- package/dist/web-terminal.js.map +1 -1
- package/dist/web-theme-store.d.ts +2 -2
- package/dist/web-theme-store.js +6 -3
- package/dist/web-theme-store.js.map +1 -1
- package/dist/web-theme.d.ts +29 -0
- package/dist/web-theme.js +89 -1
- package/dist/web-theme.js.map +1 -1
- package/dist/web-upload.d.ts +18 -1
- package/dist/web-upload.js +45 -7
- package/dist/web-upload.js.map +1 -1
- package/dist/web-widget.js.map +1 -1
- package/dist/webhook-emitter.js.map +1 -1
- package/dist/windows-shortcuts.d.ts +78 -0
- package/dist/windows-shortcuts.js +203 -0
- package/dist/windows-shortcuts.js.map +1 -0
- package/dist/workflow-templates/default.md +4 -1
- package/dist/ws-server.js.map +1 -1
- package/dist/yaml-shared-nodes.d.ts +25 -0
- package/dist/yaml-shared-nodes.js +185 -0
- package/dist/yaml-shared-nodes.js.map +1 -0
- package/launcher/agend-install.cjs +828 -0
- package/launcher/install-admission.cjs +4 -39
- package/launcher/postinstall.cjs +14 -12
- package/launcher/private-home.cjs +43 -0
- package/package.json +16 -13
- package/scripts/preinstall-guard.cjs +2 -5
- package/templates/windows-shortcuts.ps1 +181 -0
- package/launcher/old-updater-note.cjs +0 -48
package/dist/needs-you-hub.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { ChannelAdapter } from "./channel/types.js";
|
|
2
|
-
import { type DeliveryInput, type InstanceInput, type NeedsYouItem, type PromptInput, type WorldPlace } from "./needs-you.js";
|
|
2
|
+
import { type DeliveryInput, type InstanceInput, type NeedsYouItem, type PromptInput, type TaskInput, type WorldPlace } from "./needs-you.js";
|
|
3
3
|
import { type LiveTarget } from "./needs-you-live.js";
|
|
4
4
|
export declare const NEEDS_ACK_PREFIX = "needs-ack:";
|
|
5
|
+
/** A Send back or Answer prompt waits this long for its reply (monotonic). */
|
|
6
|
+
export declare const TASK_REPLY_TTL_MS: number;
|
|
7
|
+
/** Send back / Answer prompts open at once, being sent or waiting for their reply, over every card and person (#2306 review). */
|
|
8
|
+
export declare const TASK_REPLY_MAX = 32;
|
|
5
9
|
/** awaiting_input pings (DM, browser) only once it has lasted this long; the list itself is never delayed (§6.3). */
|
|
6
10
|
export declare const AWAITING_PING_MIN_MS = 5000;
|
|
7
11
|
/** An Acknowledge button's capability lapses this long after it was minted, whether or not a renewal replaced it. */
|
|
@@ -27,6 +31,15 @@ export interface NeedsYouHubContext {
|
|
|
27
31
|
worlds(): NeedsYouWorld[];
|
|
28
32
|
/** Where a world's fleet notices go (its General), or null. */
|
|
29
33
|
noticeTarget(world: string): LiveTarget | null;
|
|
34
|
+
/** #2352: an instance's own channel (its topic in its world's group, or its ClassicBot room), or null. */
|
|
35
|
+
laneTarget?(instance: string): LiveTarget | null;
|
|
36
|
+
/**
|
|
37
|
+
* #2355 review: where a card's buttons belong NOW, read from the board (not from the last render): `{ lane }` (no lane:
|
|
38
|
+
* General), or null when the card no longer waits for the person (the board answers a move by its version).
|
|
39
|
+
*/
|
|
40
|
+
taskRoute?(code: string): {
|
|
41
|
+
lane?: string;
|
|
42
|
+
} | null;
|
|
30
43
|
/** An instance's own thread/topic id, for its link. */
|
|
31
44
|
instanceTopic(instance: string): string | undefined;
|
|
32
45
|
isFleetAdmin(userId: string, world: string): boolean;
|
|
@@ -34,6 +47,16 @@ export interface NeedsYouHubContext {
|
|
|
34
47
|
emitSse(event: string, data: unknown): void;
|
|
35
48
|
/** outbox.acknowledge: true when this call acknowledged it; throws on a write error. */
|
|
36
49
|
acknowledge(deliveryId: string, by: string): boolean;
|
|
50
|
+
/** Task board cards waiting for the person (#2246 step 3); none when the board is not open. */
|
|
51
|
+
tasks?(): TaskInput[];
|
|
52
|
+
/**
|
|
53
|
+
* The person's move on a card from the chat: confirm it, send it back with `text` (the reason), or answer its blocked
|
|
54
|
+
* question with `text`. Checked against the version the button showed; the answer is said to the clicker.
|
|
55
|
+
*/
|
|
56
|
+
taskAction?(action: TaskAction): {
|
|
57
|
+
ok: boolean;
|
|
58
|
+
message: string;
|
|
59
|
+
};
|
|
37
60
|
settings(): {
|
|
38
61
|
liveMessage: boolean;
|
|
39
62
|
dm: boolean;
|
|
@@ -42,16 +65,44 @@ export interface NeedsYouHubContext {
|
|
|
42
65
|
t(key: string, ...args: Array<string | number>): string;
|
|
43
66
|
log(level: "info" | "warn" | "debug", message: string, extra?: Record<string, unknown>): void;
|
|
44
67
|
}
|
|
68
|
+
export type TaskVerb = "confirm" | "back" | "answer";
|
|
69
|
+
export interface TaskAction {
|
|
70
|
+
verb: TaskVerb;
|
|
71
|
+
code: string;
|
|
72
|
+
version: number;
|
|
73
|
+
/** The reason (back) or the answer (answer). */
|
|
74
|
+
text?: string;
|
|
75
|
+
/** The person, as the platform names them. */
|
|
76
|
+
by: {
|
|
77
|
+
platform: string;
|
|
78
|
+
userId: string;
|
|
79
|
+
username?: string;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/** A reply to a message, as the inbound handler sees it (InboundMessage's fields). */
|
|
83
|
+
export interface ReplyMessage {
|
|
84
|
+
adapterId: string;
|
|
85
|
+
chatId: string;
|
|
86
|
+
threadId?: string;
|
|
87
|
+
replyTo?: string;
|
|
88
|
+
messageId: string;
|
|
89
|
+
userId: string;
|
|
90
|
+
username?: string;
|
|
91
|
+
text: string;
|
|
92
|
+
}
|
|
45
93
|
export interface AckCallback {
|
|
46
94
|
callbackData: string;
|
|
47
95
|
chatId: string;
|
|
48
96
|
threadId?: string;
|
|
49
97
|
messageId: string;
|
|
50
98
|
userId?: string;
|
|
99
|
+
username?: string;
|
|
51
100
|
ack?(notice?: string): void;
|
|
52
101
|
}
|
|
53
102
|
/** What the web receives: the items without their chat coordinates. */
|
|
54
103
|
export type WebNeedsItem = Omit<NeedsYouItem, "promptAt">;
|
|
104
|
+
/** #2352: a live message's key — its world (General, as before #2352) or `<world>#lane:<instance>` (a lane's channel). */
|
|
105
|
+
export declare function liveKey(world: string, lane: string | null): string;
|
|
55
106
|
export declare class NeedsYouHub {
|
|
56
107
|
private readonly ctx;
|
|
57
108
|
private items;
|
|
@@ -62,6 +113,16 @@ export declare class NeedsYouHub {
|
|
|
62
113
|
* moved place gets a new renderer, and the old one can no longer publish. */
|
|
63
114
|
private readonly live;
|
|
64
115
|
private readonly acks;
|
|
116
|
+
/** Send back / Answer prompts waiting for the clicker's reply, by `${world}|${chatId}|${messageId}`. */
|
|
117
|
+
/** Pending replies by where their prompt is (`<chatId>|<messageId>`), whichever bot receives the reply. */
|
|
118
|
+
private readonly replies;
|
|
119
|
+
/** Prompts on their way: reserved before the send, released when it is posted or fails (#2306 review). */
|
|
120
|
+
private readonly asking;
|
|
121
|
+
/**
|
|
122
|
+
* #2341 review r2: replies already taken, by `<chatId>|<messageId>`, until the prompt's TTL — so another bot's copy of
|
|
123
|
+
* the same message (a shared group) is dropped by the inbound handler, not handed to an agent as input.
|
|
124
|
+
*/
|
|
125
|
+
private readonly taken;
|
|
65
126
|
private readonly dmSeen;
|
|
66
127
|
private readonly dmLastAt;
|
|
67
128
|
/** Per world: the ids waiting to be DMed, and the one timer that will send them. */
|
|
@@ -84,7 +145,12 @@ export declare class NeedsYouHub {
|
|
|
84
145
|
private pointerPath;
|
|
85
146
|
private readPointers;
|
|
86
147
|
private writePointer;
|
|
148
|
+
/** A line's words: why it waits — and for a card, which card and what it asks or lacks (the chat shows no detail). */
|
|
87
149
|
private lineTitle;
|
|
150
|
+
/** #2352: a lane can carry a list here: its instance is this world's now, and has a channel of its own. */
|
|
151
|
+
private laneUsable;
|
|
152
|
+
/** Where a list (General, or a lane's) is posted now, or null. */
|
|
153
|
+
private listTarget;
|
|
88
154
|
private makeLive;
|
|
89
155
|
private mintAcks;
|
|
90
156
|
private revokeAcks;
|
|
@@ -94,6 +160,37 @@ export declare class NeedsYouHub {
|
|
|
94
160
|
* never edited from here — that would strip the current keyboard of the same message.
|
|
95
161
|
*/
|
|
96
162
|
handleCallback(data: AckCallback, adapterId: string): boolean;
|
|
163
|
+
/**
|
|
164
|
+
* #2352: a card still routes to this lane (or, for no lane, to General) — asked of the board now (#2355 review: a
|
|
165
|
+
* project's lead can change with the card's version unchanged, and the last render may not have seen it yet). One
|
|
166
|
+
* that no longer waits for the person is left to the board, which answers by its version.
|
|
167
|
+
*/
|
|
168
|
+
private stillInLane;
|
|
169
|
+
/** #2355 review: a list's place (its lane's channel, or General) is still where this button or prompt is. */
|
|
170
|
+
private placeStill;
|
|
171
|
+
/** A prompt for this reservation still waits for its reply. */
|
|
172
|
+
private pendingFor;
|
|
173
|
+
/** Prompts still waiting for their reply (lapsed ones go). */
|
|
174
|
+
private livePending;
|
|
175
|
+
/**
|
|
176
|
+
* The card's instance is still this world's, the world still the same connection in the same place, and its notice
|
|
177
|
+
* place still where the prompt is: else a reply there is not this world's to take (#2306 review — an instance that
|
|
178
|
+
* moved to another world, a replaced connection, a new notice room).
|
|
179
|
+
*/
|
|
180
|
+
private stillHere;
|
|
181
|
+
/** Post the prompt for a Send back's reason or an answer, and wait for the clicker's reply to it. */
|
|
182
|
+
private askForReply;
|
|
183
|
+
/**
|
|
184
|
+
* An inbound message that replies to one of our Send back / Answer prompts, by the admin who clicked: its text is
|
|
185
|
+
* the reason or the answer, and the message goes no further (true). Anything else — another message, another
|
|
186
|
+
* person, a lapsed prompt — is not ours (false) and flows on as usual.
|
|
187
|
+
*/
|
|
188
|
+
handleReply(msg: ReplyMessage): boolean;
|
|
189
|
+
/**
|
|
190
|
+
* #2341 review r2: this message (another bot's copy of it) was already taken as a prompt's answer. The inbound handler
|
|
191
|
+
* asks it first and drops the copy: it is neither a second answer nor an agent's input.
|
|
192
|
+
*/
|
|
193
|
+
wasTakenReply(chatId: string, messageId: string | undefined): boolean;
|
|
97
194
|
/** The web's Acknowledge: any item (the web is global, §5.0). `principal` is "web:<session handle>" or "cli". */
|
|
98
195
|
webAcknowledge(itemId: string, principal: string): {
|
|
99
196
|
status: 200 | 400 | 404 | 409 | 500;
|
package/dist/needs-you-hub.js
CHANGED
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
* #1386: the fleet side of "Needs you". One derivation (needs-you.ts), recomputed on change, rendered to:
|
|
3
3
|
* - each world's live message in its General and, optionally, its admins' DMs — only that world's items (§5.0, §5);
|
|
4
4
|
* - the web, globally: SSE `needs` and a `needs` field on /ui/poll (§6).
|
|
5
|
-
* Plus Acknowledge for delivery items, from a world's live message (its admins, its items) or from the web (any)
|
|
5
|
+
* Plus Acknowledge for delivery items, from a world's live message (its admins, its items) or from the web (any); and
|
|
6
|
+
* for task board cards (#2246 step 3), Confirm, Send back and Answer from the live message — the two that need words
|
|
7
|
+
* ask for them as a reply to a prompt the bot posts, which only the admin who clicked may answer.
|
|
8
|
+
*
|
|
9
|
+
* #2352: a card with a lane (the instance that handed it out, else its project's lead) is listed in that instance's own
|
|
10
|
+
* channel instead — one live message per lane, the same renderer, its buttons and prompts bound to that message and
|
|
11
|
+
* place. A world's General keeps everything else.
|
|
6
12
|
*
|
|
7
13
|
* The Acknowledge capabilities live in this hub's own registry, not in the fleet's prompt map: the map's walkers
|
|
8
14
|
* (per-instance clear, shutdown retire, prompt expiry) edit the message an entry points at, and the live message must
|
|
@@ -14,11 +20,15 @@ import { readFileSync } from "node:fs";
|
|
|
14
20
|
import { join } from "node:path";
|
|
15
21
|
import { writeFileAtomic } from "./backend/kiro-engine-ledger.js";
|
|
16
22
|
import { isMessageEditLoss } from "./channel/message-edit-errors.js";
|
|
17
|
-
import { deriveNeedsYou, itemsForWorld, renderLiveMessage, renderSignature, messageLink, instanceLink, } from "./needs-you.js";
|
|
23
|
+
import { deriveNeedsYou, itemsForWorld, itemsForLane, lanesOf, renderLiveMessage, renderSignature, messageLink, instanceLink, } from "./needs-you.js";
|
|
18
24
|
import { GroupMembership, topicUrl } from "./topic-link.js";
|
|
19
|
-
import { NeedsYouLiveMessage, canonicalTarget } from "./needs-you-live.js";
|
|
25
|
+
import { NeedsYouLiveMessage, canonicalTarget, samePlace } from "./needs-you-live.js";
|
|
20
26
|
export const NEEDS_ACK_PREFIX = "needs-ack:";
|
|
21
|
-
const ACK_RE = /^needs-ack:([0-9a-f]{32}):ack$/;
|
|
27
|
+
const ACK_RE = /^needs-ack:([0-9a-f]{32}):(ack|confirm|back|answer)$/;
|
|
28
|
+
/** A Send back or Answer prompt waits this long for its reply (monotonic). */
|
|
29
|
+
export const TASK_REPLY_TTL_MS = 10 * 60_000;
|
|
30
|
+
/** Send back / Answer prompts open at once, being sent or waiting for their reply, over every card and person (#2306 review). */
|
|
31
|
+
export const TASK_REPLY_MAX = 32;
|
|
22
32
|
const BACKSTOP_MS = 10_000;
|
|
23
33
|
const ATTENTION_WINDOW_MS = 24 * 60 * 60_000;
|
|
24
34
|
/** awaiting_input pings (DM, browser) only once it has lasted this long; the list itself is never delayed (§6.3). */
|
|
@@ -30,6 +40,11 @@ export const ACK_TTL_MS = 15 * 60_000;
|
|
|
30
40
|
function placeKey(place) {
|
|
31
41
|
return `${place.type}|${place.groupId ?? ""}`;
|
|
32
42
|
}
|
|
43
|
+
/** #2352: a live message's key — its world (General, as before #2352) or `<world>#lane:<instance>` (a lane's channel). */
|
|
44
|
+
export function liveKey(world, lane) {
|
|
45
|
+
return lane ? `${world}#lane:${lane}` : world;
|
|
46
|
+
}
|
|
47
|
+
const LANE_SEP = "#lane:";
|
|
33
48
|
export class NeedsYouHub {
|
|
34
49
|
ctx;
|
|
35
50
|
items = [];
|
|
@@ -40,6 +55,16 @@ export class NeedsYouHub {
|
|
|
40
55
|
* moved place gets a new renderer, and the old one can no longer publish. */
|
|
41
56
|
live = new Map();
|
|
42
57
|
acks = new Map();
|
|
58
|
+
/** Send back / Answer prompts waiting for the clicker's reply, by `${world}|${chatId}|${messageId}`. */
|
|
59
|
+
/** Pending replies by where their prompt is (`<chatId>|<messageId>`), whichever bot receives the reply. */
|
|
60
|
+
replies = new Map();
|
|
61
|
+
/** Prompts on their way: reserved before the send, released when it is posted or fails (#2306 review). */
|
|
62
|
+
asking = new Set();
|
|
63
|
+
/**
|
|
64
|
+
* #2341 review r2: replies already taken, by `<chatId>|<messageId>`, until the prompt's TTL — so another bot's copy of
|
|
65
|
+
* the same message (a shared group) is dropped by the inbound handler, not handed to an agent as input.
|
|
66
|
+
*/
|
|
67
|
+
taken = new Map();
|
|
43
68
|
dmSeen = new Map();
|
|
44
69
|
dmLastAt = new Map();
|
|
45
70
|
/** Per world: the ids waiting to be DMed, and the one timer that will send them. */
|
|
@@ -75,6 +100,9 @@ export class NeedsYouHub {
|
|
|
75
100
|
if (this.stopped)
|
|
76
101
|
return;
|
|
77
102
|
const now = this.ctx.now();
|
|
103
|
+
for (const [key, r] of this.replies)
|
|
104
|
+
if (this.ctx.mono() >= r.deadline)
|
|
105
|
+
this.replies.delete(key);
|
|
78
106
|
let deliveries = [];
|
|
79
107
|
try {
|
|
80
108
|
deliveries = this.ctx.deliveries(new Date(now - ATTENTION_WINDOW_MS).toISOString());
|
|
@@ -82,7 +110,14 @@ export class NeedsYouHub {
|
|
|
82
110
|
catch (err) {
|
|
83
111
|
this.ctx.log("warn", "Needs you: could not read the delivery outbox", { err: String(err?.message ?? err) });
|
|
84
112
|
}
|
|
85
|
-
|
|
113
|
+
let tasks = [];
|
|
114
|
+
try {
|
|
115
|
+
tasks = this.ctx.tasks?.() ?? [];
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
this.ctx.log("warn", "Needs you: could not read the task board", { err: String(err?.message ?? err) });
|
|
119
|
+
}
|
|
120
|
+
this.items = deriveNeedsYou({ prompts: this.ctx.prompts(), instances: this.ctx.instances(), deliveries, tasks, ownerOf: i => this.ctx.ownerOf(i) });
|
|
86
121
|
const webSig = renderSignature(this.items, now);
|
|
87
122
|
if (webSig !== this.webSignature) {
|
|
88
123
|
this.webSignature = webSig;
|
|
@@ -91,20 +126,30 @@ export class NeedsYouHub {
|
|
|
91
126
|
const settings = this.ctx.settings();
|
|
92
127
|
const worlds = this.ctx.worlds();
|
|
93
128
|
const worldIds = new Set(worlds.map(w => w.id));
|
|
94
|
-
for (const [
|
|
95
|
-
const current = worlds.find(w => w.id ===
|
|
129
|
+
for (const [key, pinned] of this.live) {
|
|
130
|
+
const current = worlds.find(w => w.id === pinned.world);
|
|
96
131
|
if (!settings.liveMessage || !current) {
|
|
97
|
-
this.live.delete(
|
|
98
|
-
this.worldSignature.delete(
|
|
132
|
+
this.live.delete(key);
|
|
133
|
+
this.worldSignature.delete(key);
|
|
134
|
+
this.worldSeen.delete(key);
|
|
99
135
|
void pinned.renderer.disable();
|
|
100
136
|
}
|
|
101
137
|
else if (current.adapter !== pinned.adapter || placeKey(current.place) !== pinned.placeKey) {
|
|
102
138
|
// Another adapter (or place) under the same id: the old renderer stops without touching anything — its adapter
|
|
103
139
|
// may be gone — and a new one picks up from the persisted pointer.
|
|
104
|
-
this.live.delete(
|
|
105
|
-
this.worldSignature.delete(
|
|
140
|
+
this.live.delete(key);
|
|
141
|
+
this.worldSignature.delete(key);
|
|
142
|
+
this.worldSeen.delete(key);
|
|
106
143
|
pinned.renderer.abandon();
|
|
107
144
|
}
|
|
145
|
+
else if (pinned.lane !== null && !this.laneUsable(pinned.lane, pinned.world)) {
|
|
146
|
+
// #2352: the lane is gone from this world (its instance removed or moved, its channel gone): its message says
|
|
147
|
+
// so, without buttons, and is forgotten. A lane that is merely empty stays, saying nothing waits.
|
|
148
|
+
this.live.delete(key);
|
|
149
|
+
this.worldSignature.delete(key);
|
|
150
|
+
this.worldSeen.delete(key);
|
|
151
|
+
void pinned.renderer.disable(this.ctx.t("needs.live_moved"));
|
|
152
|
+
}
|
|
108
153
|
}
|
|
109
154
|
if (!settings.dm)
|
|
110
155
|
for (const id of [...this.dmPending.keys()])
|
|
@@ -114,25 +159,39 @@ export class NeedsYouHub {
|
|
|
114
159
|
this.cancelDms(id);
|
|
115
160
|
const seeding = !this.seeded;
|
|
116
161
|
this.seeded = true;
|
|
162
|
+
const saved = settings.liveMessage ? Object.keys(this.readPointers()) : [];
|
|
117
163
|
for (const world of worlds) {
|
|
118
164
|
const mine = itemsForWorld(this.items, world.id);
|
|
119
|
-
if (seeding)
|
|
120
|
-
this.worldSeen.set(world.id, new Set(mine.map(i => i.id)));
|
|
165
|
+
if (seeding)
|
|
121
166
|
this.dmSeen.set(world.id, new Set(mine.map(i => i.id)));
|
|
122
|
-
}
|
|
123
|
-
const seen = this.worldSeen.get(world.id) ?? new Set();
|
|
124
|
-
const fresh = mine.filter(i => !seen.has(i.id));
|
|
125
|
-
this.worldSeen.set(world.id, new Set(mine.map(i => i.id)));
|
|
126
167
|
if (settings.liveMessage) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
168
|
+
// General, every lane with cards now, and every lane whose message is still out there (from before a restart,
|
|
169
|
+
// or emptied since): those render too, so a stale list never keeps its old lines.
|
|
170
|
+
const lanes = new Set(lanesOf(this.items, world.id));
|
|
171
|
+
for (const k of saved)
|
|
172
|
+
if (k.startsWith(world.id + LANE_SEP))
|
|
173
|
+
lanes.add(k.slice(world.id.length + LANE_SEP.length));
|
|
174
|
+
for (const [, pinned] of this.live)
|
|
175
|
+
if (pinned.world === world.id && pinned.lane !== null)
|
|
176
|
+
lanes.add(pinned.lane);
|
|
177
|
+
for (const lane of [null, ...[...lanes].filter(l => this.laneUsable(l, world.id))]) {
|
|
178
|
+
const key = liveKey(world.id, lane);
|
|
179
|
+
const listed = itemsForLane(this.items, world.id, lane);
|
|
180
|
+
if (seeding)
|
|
181
|
+
this.worldSeen.set(key, new Set(listed.map(i => i.id)));
|
|
182
|
+
const seen = this.worldSeen.get(key) ?? new Set();
|
|
183
|
+
const fresh = listed.filter(i => !seen.has(i.id));
|
|
184
|
+
this.worldSeen.set(key, new Set(listed.map(i => i.id)));
|
|
185
|
+
let pinned = this.live.get(key);
|
|
186
|
+
if (!pinned) {
|
|
187
|
+
pinned = { renderer: this.makeLive(world, lane), adapter: world.adapter, placeKey: placeKey(world.place), world: world.id, lane };
|
|
188
|
+
this.live.set(key, pinned);
|
|
189
|
+
}
|
|
190
|
+
const sig = renderSignature(listed, now);
|
|
191
|
+
if (sig !== this.worldSignature.get(key)) {
|
|
192
|
+
this.worldSignature.set(key, sig);
|
|
193
|
+
pinned.renderer.changed(fresh.length > 0);
|
|
194
|
+
}
|
|
136
195
|
}
|
|
137
196
|
}
|
|
138
197
|
if (settings.dm)
|
|
@@ -172,27 +231,42 @@ export class NeedsYouHub {
|
|
|
172
231
|
this.ctx.log("warn", "Needs you: could not save where the live message is", { world, err: String(err?.message ?? err) });
|
|
173
232
|
}
|
|
174
233
|
}
|
|
175
|
-
|
|
176
|
-
|
|
234
|
+
/** A line's words: why it waits — and for a card, which card and what it asks or lacks (the chat shows no detail). */
|
|
235
|
+
lineTitle(item) {
|
|
236
|
+
const reason = this.ctx.t(`needs.reason.${item.reason}`);
|
|
237
|
+
return item.type === "task" && item.detail ? `${reason}: ${item.detail}` : reason;
|
|
238
|
+
}
|
|
239
|
+
/** #2352: a lane can carry a list here: its instance is this world's now, and has a channel of its own. */
|
|
240
|
+
laneUsable(lane, world) {
|
|
241
|
+
return this.ctx.ownerOf(lane) === world && !!this.ctx.laneTarget?.(lane);
|
|
242
|
+
}
|
|
243
|
+
/** Where a list (General, or a lane's) is posted now, or null. */
|
|
244
|
+
listTarget(world, lane) {
|
|
245
|
+
if (!lane)
|
|
246
|
+
return this.ctx.noticeTarget(world);
|
|
247
|
+
return this.laneUsable(lane, world) ? this.ctx.laneTarget(lane) : null;
|
|
248
|
+
}
|
|
249
|
+
makeLive(world, lane) {
|
|
177
250
|
const ctx = this.ctx;
|
|
178
|
-
const
|
|
251
|
+
const key = liveKey(world.id, lane);
|
|
252
|
+
const owner = Symbol(key);
|
|
179
253
|
return new NeedsYouLiveMessage({
|
|
180
|
-
world:
|
|
254
|
+
world: key,
|
|
181
255
|
now: () => ctx.mono(),
|
|
182
256
|
setTimer: (fn, ms) => ctx.setTimer(fn, ms),
|
|
183
257
|
clearTimer: h => ctx.clearTimer(h),
|
|
184
|
-
target: () => { const t =
|
|
258
|
+
target: () => { const t = this.listTarget(world.id, lane); return t ? canonicalTarget(t) : null; },
|
|
185
259
|
enabled: () => ctx.settings().liveMessage,
|
|
186
260
|
stopping: () => ctx.stopping() || this.stopped,
|
|
187
261
|
// The same world means the same adapter object and place it was built for, not just the same id.
|
|
188
262
|
worldExists: () => ctx.worlds().some(w => w.id === world.id && w.adapter === world.adapter && placeKey(w.place) === placeKey(world.place)),
|
|
189
263
|
content: () => {
|
|
190
|
-
const mine =
|
|
264
|
+
const mine = itemsForLane(this.items, world.id, lane);
|
|
191
265
|
const lines = mine.map(item => ({
|
|
192
266
|
item, title: this.lineTitle(item),
|
|
193
267
|
link: item.promptAt ? messageLink(world.place, item.promptAt) : instanceLink(world.place, ctx.instanceTopic(item.instance)),
|
|
194
268
|
}));
|
|
195
|
-
const rendered = renderLiveMessage(lines, ctx.now(), (k, ...a) => ctx.t(k, ...a));
|
|
269
|
+
const rendered = renderLiveMessage(lines, ctx.now(), (k, ...a) => ctx.t(k, ...a), lane ? "needs.live_header_lane" : "needs.live_header");
|
|
196
270
|
return { empty: mine.length === 0, ...rendered };
|
|
197
271
|
},
|
|
198
272
|
post: async (target, text, choices) => {
|
|
@@ -206,25 +280,36 @@ export class NeedsYouHub {
|
|
|
206
280
|
},
|
|
207
281
|
isEditLoss: isMessageEditLoss,
|
|
208
282
|
remove: async (pointer) => { await world.adapter.deleteMessage?.(pointer.chatId, pointer.messageId, pointer.threadId); },
|
|
209
|
-
loadPointer: () => this.readPointers()[
|
|
210
|
-
savePointer: pointer => this.writePointer(
|
|
211
|
-
mintAcks: (generation, place, items) => this.mintAcks(world.id, owner, generation, place, items),
|
|
283
|
+
loadPointer: () => this.readPointers()[key] ?? null,
|
|
284
|
+
savePointer: pointer => this.writePointer(key, pointer),
|
|
285
|
+
mintAcks: (generation, place, items) => this.mintAcks(world.id, owner, generation, place, items, lane),
|
|
212
286
|
revokeAcks: () => this.revokeAcks(owner),
|
|
213
287
|
log: (message, extra) => ctx.log("info", `Needs you: ${message}`, extra),
|
|
214
288
|
text: { stopped: ctx.t("needs.live_stopped"), off: ctx.t("needs.live_off") },
|
|
215
289
|
});
|
|
216
290
|
}
|
|
217
|
-
mintAcks(world, owner, generation, place, items) {
|
|
291
|
+
mintAcks(world, owner, generation, place, items, lane = null) {
|
|
218
292
|
const minted = [];
|
|
219
|
-
const
|
|
293
|
+
const mint = (item, verb, label) => {
|
|
220
294
|
const nonce = randomBytes(16).toString("hex");
|
|
221
295
|
const entry = {
|
|
222
296
|
world, owner, generation, deadline: this.ctx.mono() + ACK_TTL_MS, chatId: place.chatId, ...(place.threadId !== undefined ? { threadId: place.threadId } : {}),
|
|
223
|
-
...(place.messageId ? { messageId: place.messageId } : {}),
|
|
297
|
+
...(place.messageId ? { messageId: place.messageId } : {}), verb, instance: item.instance, ...(lane ? { lane } : {}),
|
|
298
|
+
...(item.deliveryId ? { deliveryId: item.deliveryId } : {}), ...(item.card ? { card: { ...item.card } } : {}),
|
|
224
299
|
};
|
|
225
300
|
this.acks.set(nonce, entry);
|
|
226
301
|
minted.push(entry);
|
|
227
|
-
return { id: `${NEEDS_ACK_PREFIX}${nonce}
|
|
302
|
+
return { id: `${NEEDS_ACK_PREFIX}${nonce}:${verb}`, label };
|
|
303
|
+
};
|
|
304
|
+
const choices = items.flatMap(item => {
|
|
305
|
+
if (item.deliveryId)
|
|
306
|
+
return [mint(item, "ack", this.ctx.t("needs.ack_button", item.instance))];
|
|
307
|
+
if (item.type !== "task" || !item.card)
|
|
308
|
+
return [];
|
|
309
|
+
const code = item.card.code;
|
|
310
|
+
return item.reason === "task_review"
|
|
311
|
+
? [mint(item, "confirm", this.ctx.t("needs.task_confirm_button", code)), mint(item, "back", this.ctx.t("needs.task_back_button", code))]
|
|
312
|
+
: [mint(item, "answer", this.ctx.t("needs.task_answer_button", code))];
|
|
228
313
|
});
|
|
229
314
|
return { choices, bind: pointer => { for (const e of minted)
|
|
230
315
|
e.messageId = pointer.messageId; } };
|
|
@@ -244,7 +329,8 @@ export class NeedsYouHub {
|
|
|
244
329
|
if (!data.callbackData.startsWith(NEEDS_ACK_PREFIX))
|
|
245
330
|
return false;
|
|
246
331
|
const m = ACK_RE.exec(data.callbackData);
|
|
247
|
-
const
|
|
332
|
+
const found = m ? this.acks.get(m[1]) : undefined;
|
|
333
|
+
const entry = found && found.verb === m[2] ? found : undefined;
|
|
248
334
|
if (entry && this.ctx.mono() >= entry.deadline)
|
|
249
335
|
this.acks.delete(m[1]);
|
|
250
336
|
// Unknown, revoked, lapsed — or not yet bound to the message its post returned: no authority yet.
|
|
@@ -263,13 +349,193 @@ export class NeedsYouHub {
|
|
|
263
349
|
data.ack?.(this.ctx.t("buttons.admin_only"));
|
|
264
350
|
return true;
|
|
265
351
|
}
|
|
266
|
-
// §5.0: the item must still belong to this world.
|
|
267
|
-
if (this.ctx.ownerOf(entry.instance) !== adapterId) {
|
|
352
|
+
// §5.0: the item must still belong to this world — for a laned card, its lane's world (#2352).
|
|
353
|
+
if (this.ctx.ownerOf(entry.lane ?? entry.instance) !== adapterId) {
|
|
268
354
|
data.ack?.(this.ctx.t("needs.ack_not_this_world"));
|
|
269
355
|
return true;
|
|
270
356
|
}
|
|
357
|
+
// #2352: and a card must still wait where this button showed it (its lead or dispatcher changed: elsewhere now).
|
|
358
|
+
// #2355 review: read now — the card's route (a lead changed) and the list's place (a lane's topic moved or went).
|
|
359
|
+
if (entry.card && (!this.stillInLane(entry.card.code, entry.lane) || !this.placeStill(adapterId, entry.lane, entry.chatId, entry.threadId))) {
|
|
360
|
+
data.ack?.(this.ctx.t("needs.task_moved"));
|
|
361
|
+
return true;
|
|
362
|
+
}
|
|
271
363
|
const platform = this.ctx.worlds().find(w => w.id === adapterId)?.place.type ?? "chat";
|
|
272
|
-
|
|
364
|
+
if (entry.verb === "ack") {
|
|
365
|
+
data.ack?.(this.ctx.t(`needs.ack_${this.acknowledge(entry.deliveryId, `${platform}:${data.userId}`)}`));
|
|
366
|
+
return true;
|
|
367
|
+
}
|
|
368
|
+
const card = entry.card;
|
|
369
|
+
const by = { platform, userId: data.userId, ...(data.username ? { username: data.username } : {}) };
|
|
370
|
+
if (entry.verb === "confirm") {
|
|
371
|
+
const outcome = this.ctx.taskAction?.({ verb: "confirm", code: card.code, version: card.version, by }) ?? { ok: false, message: this.ctx.t("needs.task_board_closed") };
|
|
372
|
+
data.ack?.(outcome.message);
|
|
373
|
+
this.poke();
|
|
374
|
+
return true;
|
|
375
|
+
}
|
|
376
|
+
// Send back and Answer take words: a prompt the clicker answers by replying to it (handleReply). One prompt per
|
|
377
|
+
// world, card, person and verb at a time, reserved before the send (#2306 review): a second press while one is on
|
|
378
|
+
// its way or still waits is told so, and the prompts open over everything are capped.
|
|
379
|
+
const askKey = `${adapterId}|${card.code}|${data.userId}|${entry.verb}`;
|
|
380
|
+
if (this.asking.has(askKey) || this.pendingFor(askKey)) {
|
|
381
|
+
data.ack?.(this.ctx.t("needs.task_reply_already", card.code));
|
|
382
|
+
return true;
|
|
383
|
+
}
|
|
384
|
+
if (this.asking.size + this.livePending() >= TASK_REPLY_MAX) {
|
|
385
|
+
data.ack?.(this.ctx.t("needs.task_reply_busy"));
|
|
386
|
+
return true;
|
|
387
|
+
}
|
|
388
|
+
this.asking.add(askKey);
|
|
389
|
+
data.ack?.(this.ctx.t("needs.task_reply_asked"));
|
|
390
|
+
void this.askForReply(entry, entry.verb, by, askKey);
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* #2352: a card still routes to this lane (or, for no lane, to General) — asked of the board now (#2355 review: a
|
|
395
|
+
* project's lead can change with the card's version unchanged, and the last render may not have seen it yet). One
|
|
396
|
+
* that no longer waits for the person is left to the board, which answers by its version.
|
|
397
|
+
*/
|
|
398
|
+
stillInLane(code, lane) {
|
|
399
|
+
if (this.ctx.taskRoute) {
|
|
400
|
+
const route = this.ctx.taskRoute(code);
|
|
401
|
+
return route === null || (route.lane ?? undefined) === lane;
|
|
402
|
+
}
|
|
403
|
+
const now = this.items.find(i => i.type === "task" && i.card?.code === code);
|
|
404
|
+
return !now || (now.lane ?? undefined) === lane;
|
|
405
|
+
}
|
|
406
|
+
/** #2355 review: a list's place (its lane's channel, or General) is still where this button or prompt is. */
|
|
407
|
+
placeStill(world, lane, chatId, threadId) {
|
|
408
|
+
const target = this.listTarget(world, lane);
|
|
409
|
+
return !!target && samePlace(target, { chatId, ...(threadId !== undefined ? { threadId } : {}) });
|
|
410
|
+
}
|
|
411
|
+
/** A prompt for this reservation still waits for its reply. */
|
|
412
|
+
pendingFor(askKey) {
|
|
413
|
+
const now = this.ctx.mono();
|
|
414
|
+
for (const r of this.replies.values())
|
|
415
|
+
if (r.askKey === askKey && now < r.deadline)
|
|
416
|
+
return true;
|
|
417
|
+
return false;
|
|
418
|
+
}
|
|
419
|
+
/** Prompts still waiting for their reply (lapsed ones go). */
|
|
420
|
+
livePending() {
|
|
421
|
+
const now = this.ctx.mono();
|
|
422
|
+
for (const [key, r] of this.replies)
|
|
423
|
+
if (now >= r.deadline)
|
|
424
|
+
this.replies.delete(key);
|
|
425
|
+
return this.replies.size;
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* The card's instance is still this world's, the world still the same connection in the same place, and its notice
|
|
429
|
+
* place still where the prompt is: else a reply there is not this world's to take (#2306 review — an instance that
|
|
430
|
+
* moved to another world, a replaced connection, a new notice room).
|
|
431
|
+
*/
|
|
432
|
+
stillHere(p) {
|
|
433
|
+
if (this.ctx.ownerOf(p.lane ?? p.instance) !== p.world)
|
|
434
|
+
return false;
|
|
435
|
+
const now = this.ctx.worlds().find(w => w.id === p.world);
|
|
436
|
+
if (!now || now.adapter !== p.adapter || placeKey(now.place) !== p.placeKey)
|
|
437
|
+
return false;
|
|
438
|
+
// #2352: the card still waits in this lane, and the lane's (or General's) place is still where the prompt is.
|
|
439
|
+
if (p.code !== undefined && !this.stillInLane(p.code, p.lane))
|
|
440
|
+
return false;
|
|
441
|
+
return this.placeStill(p.world, p.lane, p.chatId, p.threadId);
|
|
442
|
+
}
|
|
443
|
+
/** Post the prompt for a Send back's reason or an answer, and wait for the clicker's reply to it. */
|
|
444
|
+
async askForReply(entry, verb, by, askKey) {
|
|
445
|
+
const card = entry.card;
|
|
446
|
+
try {
|
|
447
|
+
const world = this.ctx.worlds().find(w => w.id === entry.world);
|
|
448
|
+
if (!world || this.stopped)
|
|
449
|
+
return;
|
|
450
|
+
const target = { world: entry.world, instance: entry.instance, ...(entry.lane ? { lane: entry.lane } : {}), code: card.code,
|
|
451
|
+
adapter: world.adapter, placeKey: placeKey(world.place), chatId: entry.chatId, ...(entry.threadId !== undefined ? { threadId: entry.threadId } : {}) };
|
|
452
|
+
// #2355 review: and again before the prompt goes out — the card's route and the place as they are now.
|
|
453
|
+
if (!this.stillHere(target))
|
|
454
|
+
return;
|
|
455
|
+
const who = by.username ? ` (@${by.username})` : "";
|
|
456
|
+
const text = this.ctx.t(verb === "back" ? "needs.task_back_prompt" : "needs.task_answer_prompt", card.code, who, Math.round(TASK_REPLY_TTL_MS / 60_000));
|
|
457
|
+
const sent = await world.adapter.sendText(entry.chatId, text, entry.threadId !== undefined ? { threadId: entry.threadId } : undefined);
|
|
458
|
+
// While it was on its way the fleet may have stopped, or the card's instance, the connection or the room moved.
|
|
459
|
+
if (this.stopped || !this.stillHere(target))
|
|
460
|
+
return;
|
|
461
|
+
const pending = {
|
|
462
|
+
...target, askKey, messageId: sent.messageId,
|
|
463
|
+
userId: by.userId, ...(by.username ? { username: by.username } : {}), verb, code: card.code, version: card.version,
|
|
464
|
+
deadline: this.ctx.mono() + TASK_REPLY_TTL_MS,
|
|
465
|
+
};
|
|
466
|
+
this.replies.set(`${entry.chatId}|${sent.messageId}`, pending);
|
|
467
|
+
}
|
|
468
|
+
catch (err) {
|
|
469
|
+
this.ctx.log("warn", "Needs you: could not ask for a reply", { code: card.code, err: String(err?.message ?? err) });
|
|
470
|
+
}
|
|
471
|
+
finally {
|
|
472
|
+
this.asking.delete(askKey);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* An inbound message that replies to one of our Send back / Answer prompts, by the admin who clicked: its text is
|
|
477
|
+
* the reason or the answer, and the message goes no further (true). Anything else — another message, another
|
|
478
|
+
* person, a lapsed prompt — is not ours (false) and flows on as usual.
|
|
479
|
+
*/
|
|
480
|
+
handleReply(msg) {
|
|
481
|
+
if (!msg.replyTo)
|
|
482
|
+
return false;
|
|
483
|
+
// #2306 review: found by where the prompt is, whichever bot received the reply (in a shared Discord guild a
|
|
484
|
+
// sibling bot's copy may come first), and judged by the prompt's world — its admins, its instance, its connection
|
|
485
|
+
// and room as they are now — so the answer is taken once, and only with that world's authority.
|
|
486
|
+
const key = `${msg.chatId}|${msg.replyTo}`;
|
|
487
|
+
const pending = this.replies.get(key);
|
|
488
|
+
if (!pending)
|
|
489
|
+
return false;
|
|
490
|
+
if (this.ctx.mono() >= pending.deadline) {
|
|
491
|
+
this.replies.delete(key);
|
|
492
|
+
return false;
|
|
493
|
+
}
|
|
494
|
+
if (msg.userId !== pending.userId || (pending.threadId !== undefined && msg.threadId !== undefined && msg.threadId !== pending.threadId))
|
|
495
|
+
return false;
|
|
496
|
+
if (!this.ctx.isFleetAdmin(msg.userId, pending.world))
|
|
497
|
+
return false;
|
|
498
|
+
if (!this.stillHere(pending)) {
|
|
499
|
+
this.replies.delete(key);
|
|
500
|
+
return false;
|
|
501
|
+
}
|
|
502
|
+
this.replies.delete(key);
|
|
503
|
+
if (msg.messageId) {
|
|
504
|
+
this.taken.set(`${msg.chatId}|${msg.messageId}`, this.ctx.mono() + TASK_REPLY_TTL_MS);
|
|
505
|
+
for (const [k, until] of this.taken)
|
|
506
|
+
if (this.taken.size > 256 || this.ctx.mono() >= until)
|
|
507
|
+
this.taken.delete(k);
|
|
508
|
+
else
|
|
509
|
+
break;
|
|
510
|
+
}
|
|
511
|
+
const text = msg.text.trim();
|
|
512
|
+
const world = this.ctx.worlds().find(w => w.id === pending.world);
|
|
513
|
+
const platform = world?.place.type ?? "chat";
|
|
514
|
+
const outcome = text
|
|
515
|
+
? this.ctx.taskAction?.({ verb: pending.verb, code: pending.code, version: pending.version, text,
|
|
516
|
+
by: { platform, userId: msg.userId, ...(msg.username ? { username: msg.username } : {}) } }) ?? { ok: false, message: this.ctx.t("needs.task_board_closed") }
|
|
517
|
+
: { ok: false, message: this.ctx.t("needs.task_reply_empty", pending.code) };
|
|
518
|
+
this.poke();
|
|
519
|
+
if (world) {
|
|
520
|
+
void world.adapter.sendText(msg.chatId, outcome.message, { ...(msg.threadId !== undefined ? { threadId: msg.threadId } : {}), replyTo: msg.messageId })
|
|
521
|
+
.catch(err => this.ctx.log("warn", "Needs you: could not answer a reply", { code: pending.code, err: String(err?.message ?? err) }));
|
|
522
|
+
}
|
|
523
|
+
return true;
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* #2341 review r2: this message (another bot's copy of it) was already taken as a prompt's answer. The inbound handler
|
|
527
|
+
* asks it first and drops the copy: it is neither a second answer nor an agent's input.
|
|
528
|
+
*/
|
|
529
|
+
wasTakenReply(chatId, messageId) {
|
|
530
|
+
if (!messageId)
|
|
531
|
+
return false;
|
|
532
|
+
const until = this.taken.get(`${chatId}|${messageId}`);
|
|
533
|
+
if (until === undefined)
|
|
534
|
+
return false;
|
|
535
|
+
if (this.ctx.mono() >= until) {
|
|
536
|
+
this.taken.delete(`${chatId}|${messageId}`);
|
|
537
|
+
return false;
|
|
538
|
+
}
|
|
273
539
|
return true;
|
|
274
540
|
}
|
|
275
541
|
/** The web's Acknowledge: any item (the web is global, §5.0). `principal` is "web:<session handle>" or "cli". */
|
|
@@ -392,6 +658,9 @@ export class NeedsYouHub {
|
|
|
392
658
|
this.cancelDms(id);
|
|
393
659
|
await Promise.all([...this.live.values()].map(p => p.renderer.retire()));
|
|
394
660
|
this.acks.clear();
|
|
661
|
+
this.replies.clear();
|
|
662
|
+
this.asking.clear();
|
|
663
|
+
this.taken.clear();
|
|
395
664
|
}
|
|
396
665
|
}
|
|
397
666
|
//# sourceMappingURL=needs-you-hub.js.map
|