@songsid/agend 2.3.0-beta.2 → 2.3.0-beta.20
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 +7 -1
- package/README.zh-TW.md +7 -1
- package/dist/agent-cli-instructions.md +9 -2
- package/dist/agent-cli.js +63 -2
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.js +4 -0
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-file-read.d.ts +4 -1
- package/dist/agent-file-read.js +189 -16
- package/dist/agent-file-read.js.map +1 -1
- package/dist/agent-whats-new.d.ts +11 -0
- package/dist/agent-whats-new.js +29 -5
- package/dist/agent-whats-new.js.map +1 -1
- package/dist/auth-api.d.ts +30 -1
- package/dist/auth-api.js +45 -13
- package/dist/auth-api.js.map +1 -1
- package/dist/authority/authority-state.d.ts +38 -0
- package/dist/authority/authority-state.js +114 -0
- package/dist/authority/authority-state.js.map +1 -0
- package/dist/authority/session-authorizations.d.ts +43 -0
- package/dist/authority/session-authorizations.js +102 -0
- package/dist/authority/session-authorizations.js.map +1 -0
- package/dist/authority/web-authority.d.ts +120 -0
- package/dist/authority/web-authority.js +157 -0
- package/dist/authority/web-authority.js.map +1 -0
- package/dist/backend/claude-code.d.ts +2 -2
- package/dist/backend/claude-code.js +18 -8
- 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.js +15 -2
- 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/types.d.ts +6 -0
- package/dist/backend/types.js +15 -0
- package/dist/backend/types.js.map +1 -1
- package/dist/backend-availability.d.ts +120 -0
- package/dist/backend-availability.js +396 -0
- package/dist/backend-availability.js.map +1 -0
- package/dist/backend-command.d.ts +23 -3
- package/dist/backend-command.js +25 -4
- package/dist/backend-command.js.map +1 -1
- package/dist/bug-report-cli.d.ts +30 -0
- package/dist/bug-report-cli.js +138 -0
- package/dist/bug-report-cli.js.map +1 -0
- package/dist/bug-report.d.ts +47 -0
- package/dist/bug-report.js +136 -0
- package/dist/bug-report.js.map +1 -0
- package/dist/bundled-skills.d.ts +14 -0
- package/dist/bundled-skills.js +29 -0
- package/dist/bundled-skills.js.map +1 -0
- package/dist/cache-ledger.d.ts +16 -3
- package/dist/cache-ledger.js +33 -13
- package/dist/cache-ledger.js.map +1 -1
- package/dist/cache-service.d.ts +55 -3
- package/dist/cache-service.js +152 -16
- 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 +9 -0
- package/dist/channel/adapters/discord.js +49 -4
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/mcp-tools.js +22 -11
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/types.d.ts +6 -0
- package/dist/classic-channel-manager.d.ts +10 -5
- package/dist/classic-channel-manager.js +12 -9
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli.js +224 -111
- package/dist/cli.js.map +1 -1
- package/dist/config-validator.d.ts +6 -0
- package/dist/config-validator.js +129 -3
- package/dist/config-validator.js.map +1 -1
- package/dist/config.d.ts +13 -1
- package/dist/config.js +14 -5
- package/dist/config.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 +24 -1
- package/dist/daemon.js +151 -19
- package/dist/daemon.js.map +1 -1
- 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-outbox.d.ts +10 -0
- package/dist/delivery-outbox.js +17 -1
- package/dist/delivery-outbox.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/fleet-context.d.ts +10 -0
- package/dist/fleet-manager.d.ts +505 -15
- package/dist/fleet-manager.js +1870 -204
- package/dist/fleet-manager.js.map +1 -1
- package/dist/fleet-process-handlers.d.ts +18 -0
- package/dist/fleet-process-handlers.js +69 -0
- package/dist/fleet-process-handlers.js.map +1 -0
- package/dist/fleet-traffic.d.ts +74 -0
- package/dist/fleet-traffic.js +196 -0
- package/dist/fleet-traffic.js.map +1 -0
- package/dist/general-knowledge/skills/bug-report/SKILL.md +31 -0
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +17 -6
- package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +6 -1
- package/dist/general-knowledge/skills/fleet-config/SKILL.md +2 -0
- package/dist/general-knowledge/skills/multi-channel/SKILL.md +3 -2
- 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.md +190 -47
- package/dist/general-knowledge/skills/web-dashboard/SKILL.md +545 -0
- package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +1 -1
- package/dist/human-delivery-receipts.d.ts +24 -1
- package/dist/human-delivery-receipts.js +64 -11
- package/dist/human-delivery-receipts.js.map +1 -1
- package/dist/instance-config-impact.js +7 -1
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +10 -1
- package/dist/instance-lifecycle.js +79 -18
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instance-names.d.ts +4 -0
- package/dist/instance-names.js +12 -0
- package/dist/instance-names.js.map +1 -0
- package/dist/instructions.d.ts +12 -1
- package/dist/instructions.js +13 -2
- package/dist/instructions.js.map +1 -1
- package/dist/locale.js +173 -12
- package/dist/locale.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/login-controller.d.ts +45 -0
- package/dist/login-controller.js +101 -5
- package/dist/login-controller.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 +82 -3
- package/dist/ls-rows.js.map +1 -1
- package/dist/memory-hogs.d.ts +27 -0
- package/dist/memory-hogs.js +124 -0
- package/dist/memory-hogs.js.map +1 -0
- package/dist/needs-you.d.ts +10 -0
- package/dist/needs-you.js +2 -1
- package/dist/needs-you.js.map +1 -1
- package/dist/outbound-handlers.d.ts +11 -0
- package/dist/outbound-handlers.js +139 -11
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +200 -4
- package/dist/outbound-schemas.js +124 -11
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/public-web-gateway.js +17 -4
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/public-web-link.d.ts +9 -0
- package/dist/public-web-link.js +8 -0
- package/dist/public-web-link.js.map +1 -1
- package/dist/quickstart-api.d.ts +19 -1
- package/dist/quickstart-api.js +94 -4
- package/dist/quickstart-api.js.map +1 -1
- package/dist/reply-buttons-controller.d.ts +4 -0
- package/dist/reply-buttons-controller.js +2 -2
- package/dist/reply-buttons-controller.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.d.ts +5 -0
- package/dist/rollout-index.js +26 -5
- package/dist/rollout-index.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/task-board-text.d.ts +26 -0
- package/dist/scheduler/task-board-text.js +135 -0
- package/dist/scheduler/task-board-text.js.map +1 -0
- package/dist/scheduler/task-board.d.ts +650 -0
- package/dist/scheduler/task-board.js +1938 -0
- package/dist/scheduler/task-board.js.map +1 -0
- package/dist/scheduler/types.d.ts +6 -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/service-installer.js +12 -0
- package/dist/service-installer.js.map +1 -1
- package/dist/settings-api.d.ts +23 -0
- package/dist/settings-api.js +164 -3
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-change.js +104 -0
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-confirmation.d.ts +3 -1
- package/dist/settings-confirmation.js +2 -0
- package/dist/settings-confirmation.js.map +1 -1
- package/dist/settings-effect.js +34 -3
- package/dist/settings-effect.js.map +1 -1
- package/dist/settings-http-confirmation.d.ts +11 -0
- package/dist/settings-http-confirmation.js +10 -0
- package/dist/settings-http-confirmation.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/spawn-gate.d.ts +1 -0
- package/dist/spawn-gate.js +13 -3
- package/dist/spawn-gate.js.map +1 -1
- package/dist/task-board-tool.d.ts +25 -0
- package/dist/task-board-tool.js +154 -0
- package/dist/task-board-tool.js.map +1 -0
- package/dist/task-board-waker.d.ts +44 -0
- package/dist/task-board-waker.js +128 -0
- package/dist/task-board-waker.js.map +1 -0
- package/dist/tmux-exec-helper.d.ts +94 -0
- package/dist/tmux-exec-helper.js +407 -0
- package/dist/tmux-exec-helper.js.map +1 -0
- package/dist/tmux-manager.d.ts +5 -0
- package/dist/tmux-manager.js +42 -11
- package/dist/tmux-manager.js.map +1 -1
- package/dist/tool-permissions.d.ts +0 -7
- package/dist/tool-permissions.js +44 -5
- package/dist/tool-permissions.js.map +1 -1
- package/dist/topic-commands.d.ts +17 -1
- package/dist/topic-commands.js +45 -19
- package/dist/topic-commands.js.map +1 -1
- package/dist/tunnel/cloudflared.js +37 -2
- package/dist/tunnel/cloudflared.js.map +1 -1
- package/dist/tunnel/types.d.ts +3 -1
- package/dist/tunnel/types.js.map +1 -1
- package/dist/types.d.ts +63 -1
- package/dist/ui/app-effects.js +90 -32
- package/dist/ui/backend-signin.js +297 -0
- package/dist/ui/chat-ambient.js +307 -0
- package/dist/ui/chat-effect-posters.js +8 -8
- package/dist/ui/chat-effects.js +110 -15
- package/dist/ui/chat-msg-actions.js +176 -0
- package/dist/ui/chat-render.js +21 -3
- package/dist/ui/chat-store.js +64 -12
- package/dist/ui/chat-strings.js +85 -8
- package/dist/ui/chat-thread.js +204 -21
- package/dist/ui/effect-trial-controller.js +13 -8
- package/dist/ui/effect-trial-panel.js +19 -16
- package/dist/ui/effects-waker.js +70 -0
- package/dist/ui/fleet-canvas-layout.js +117 -0
- package/dist/ui/fleet-canvas.js +555 -0
- package/dist/ui/fleet-org.js +27 -12
- package/dist/ui/fleet-route-scene.js +207 -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 +448 -0
- package/dist/ui/fleet-tasks.js +535 -0
- package/dist/ui/fleet-traffic.js +359 -0
- package/dist/ui/fleet-usage.js +435 -0
- package/dist/ui/panel-chat.js +264 -66
- package/dist/ui/panel-details.js +2 -1
- package/dist/ui/panel-fleet.js +65 -83
- package/dist/ui/panel-needs.js +4 -2
- package/dist/ui/panel-settings.js +56 -11
- package/dist/ui/preview.js +3 -2
- package/dist/ui/search-dialog.js +349 -0
- package/dist/ui/settings-appearance.js +44 -19
- package/dist/ui/settings-apply.js +3 -3
- package/dist/ui/settings-catalog.js +92 -0
- package/dist/ui/settings-confirm.js +7 -2
- package/dist/ui/settings-dialogs.js +40 -12
- package/dist/ui/settings-effects.js +4 -3
- package/dist/ui/settings-guests.js +117 -0
- package/dist/ui/settings-learn.js +25 -0
- package/dist/ui/settings-model.js +15 -6
- package/dist/ui/settings-mods.js +23 -9
- package/dist/ui/settings-owner-effects.js +15 -13
- package/dist/ui/settings-strings.js +122 -42
- package/dist/ui/settings-web-authority.js +91 -0
- package/dist/ui/shared/agend-auth.js +1 -1
- package/dist/ui/shared/app-i18n.js +11 -2
- package/dist/ui/shared/app-prefs.js +17 -4
- package/dist/ui/shared/app-route.js +19 -1
- package/dist/ui/shared/app-session.js +2 -0
- package/dist/ui/shared/app-shell.js +174 -30
- package/dist/ui/shared/app-store.js +26 -1
- package/dist/ui/shared/app-stream.js +5 -1
- package/dist/ui/shared/app-themes.js +140 -7
- package/dist/ui/shared/app.css +704 -20
- package/dist/ui/shared/app.js +26 -15
- package/dist/ui/shared/card-strings.js +8 -0
- package/dist/ui/shared/effect-app-runtime.js +68 -19
- package/dist/ui/shared/effect-chat-runtime.js +16 -3
- package/dist/ui/shared/effect-frame.js +26 -7
- package/dist/ui/shared/effect-geometry.js +24 -9
- package/dist/ui/shared/effect-owner-source.js +8 -1
- package/dist/ui/shared/effect-policy.js +21 -7
- package/dist/ui/shared/effect-profiler.js +31 -9
- package/dist/ui/shared/effect-registry.js +97 -50
- package/dist/ui/shared/effect-stock-snapshot.js +9 -0
- package/dist/ui/shared/effect-stock-trust.js +62 -10
- package/dist/ui/shared/effect-trial-shadow.js +62 -0
- package/dist/ui/shared/effect-trial-source.js +1 -1
- package/dist/ui/shared/effect-trial-stage.js +54 -31
- package/dist/ui/shared/effect-trial.css +40 -0
- package/dist/ui/shared/fx-motion.js +67 -0
- package/dist/ui/shared/identity-card.js +100 -11
- package/dist/ui/shared/identity-color.js +14 -10
- package/dist/ui/shared/instance-nav.js +179 -23
- package/dist/ui/shared/owner-css.js +30 -1
- package/dist/ui/shared/panel-view.js +24 -4
- package/dist/ui/shared/tokens.css +9 -3
- package/dist/ui/shared/ui-icons.js +2 -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 +34 -3
- package/dist/ui/shared/view-strings.js +72 -0
- package/dist/ui/shared/web-authorize.js +198 -0
- package/dist/ui/web-terminal/terminal.css +4 -4
- package/dist/ui/web-terminal/terminal.html +1 -1
- package/dist/update-launch.d.ts +9 -0
- package/dist/update-launch.js +38 -12
- package/dist/update-launch.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 +81 -2
- package/dist/usage/providers.js +240 -38
- package/dist/usage/providers.js.map +1 -1
- package/dist/usage/usage-api.d.ts +5 -1
- package/dist/usage/usage-api.js +184 -58
- package/dist/usage/usage-api.js.map +1 -1
- package/dist/usage-report.d.ts +158 -0
- package/dist/usage-report.js +226 -0
- package/dist/usage-report.js.map +1 -0
- package/dist/usage-rollup.d.ts +51 -0
- package/dist/usage-rollup.js +168 -0
- package/dist/usage-rollup.js.map +1 -0
- 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 +39 -0
- package/dist/view-api.js +69 -6
- package/dist/view-api.js.map +1 -1
- package/dist/web-ambient.d.ts +72 -0
- package/dist/web-ambient.js +161 -0
- package/dist/web-ambient.js.map +1 -0
- package/dist/web-api.d.ts +98 -14
- package/dist/web-api.js +1027 -83
- package/dist/web-api.js.map +1 -1
- package/dist/web-appearance-policy.d.ts +4 -6
- package/dist/web-appearance-policy.js +5 -12
- package/dist/web-appearance-policy.js.map +1 -1
- package/dist/web-appearance-tools.d.ts +3 -0
- package/dist/web-appearance-tools.js +22 -3
- package/dist/web-appearance-tools.js.map +1 -1
- package/dist/web-appearance-view.d.ts +27 -2
- package/dist/web-appearance-view.js +129 -14
- package/dist/web-appearance-view.js.map +1 -1
- package/dist/web-appearance.d.ts +17 -3
- package/dist/web-appearance.js +85 -8
- package/dist/web-appearance.js.map +1 -1
- package/dist/web-asset-parts.d.ts +2 -2
- package/dist/web-asset-parts.js +3 -3
- package/dist/web-asset-parts.js.map +1 -1
- package/dist/web-auth.js +3 -1
- 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.d.ts +14 -0
- package/dist/web-card.js +40 -6
- package/dist/web-card.js.map +1 -1
- package/dist/web-channel-echo.d.ts +7 -1
- package/dist/web-channel-echo.js +6 -2
- package/dist/web-channel-echo.js.map +1 -1
- package/dist/web-chat-history.d.ts +83 -0
- package/dist/web-chat-history.js +137 -5
- package/dist/web-chat-history.js.map +1 -1
- package/dist/web-commands.d.ts +6 -1
- package/dist/web-commands.js +1 -1
- package/dist/web-commands.js.map +1 -1
- package/dist/web-effect-bootstrap.d.ts +12 -0
- package/dist/web-effect-bootstrap.js +49 -0
- package/dist/web-effect-bootstrap.js.map +1 -0
- package/dist/web-effect-bundle.js +46 -1
- package/dist/web-effect-bundle.js.map +1 -1
- package/dist/web-effect-playback.d.ts +30 -0
- package/dist/web-effect-playback.js +71 -0
- package/dist/web-effect-playback.js.map +1 -0
- package/dist/web-effect-profiles.d.ts +4 -4
- package/dist/web-effect-service.d.ts +11 -4
- package/dist/web-effect-service.js +25 -4
- package/dist/web-effect-service.js.map +1 -1
- package/dist/web-effect-tools.d.ts +1 -0
- package/dist/web-effect-tools.js +4 -4
- package/dist/web-effect-tools.js.map +1 -1
- package/dist/web-effect-trials.d.ts +2 -2
- package/dist/web-effect-trials.js +3 -3
- package/dist/web-effect-trials.js.map +1 -1
- package/dist/web-effect-upload.js +1 -1
- package/dist/web-effect-upload.js.map +1 -1
- package/dist/web-effect-worker.d.ts +1 -1
- package/dist/web-effect-worker.js +2 -2
- package/dist/web-effect-worker.js.map +1 -1
- package/dist/web-effect.d.ts +1 -1
- package/dist/web-guest-access.d.ts +126 -0
- package/dist/web-guest-access.js +238 -0
- package/dist/web-guest-access.js.map +1 -0
- package/dist/web-guest-rooms.d.ts +82 -0
- package/dist/web-guest-rooms.js +135 -0
- package/dist/web-guest-rooms.js.map +1 -0
- 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-identity-color.d.ts +1 -1
- package/dist/web-identity-color.js +2 -2
- package/dist/web-identity-color.js.map +1 -1
- package/dist/web-identity-palette.d.ts +1 -1
- package/dist/web-identity-palette.js +2 -2
- package/dist/web-identity-palette.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-libavoid.d.ts +14 -0
- package/dist/web-libavoid.js +46 -0
- package/dist/web-libavoid.js.map +1 -0
- package/dist/web-login.d.ts +47 -0
- package/dist/web-login.js +115 -0
- package/dist/web-login.js.map +1 -1
- package/dist/web-mod-agent.d.ts +1 -1
- package/dist/web-mod-agent.js +7 -5
- package/dist/web-mod-agent.js.map +1 -1
- package/dist/web-mod-bundle.d.ts +9 -1
- package/dist/web-mod-bundle.js +62 -3
- package/dist/web-mod-bundle.js.map +1 -1
- package/dist/web-mod-export.d.ts +9 -0
- package/dist/web-mod-export.js +21 -0
- package/dist/web-mod-export.js.map +1 -1
- package/dist/web-mod-store.d.ts +7 -1
- package/dist/web-mod-store.js +19 -6
- package/dist/web-mod-store.js.map +1 -1
- 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-prefs.d.ts +14 -0
- package/dist/web-prefs.js +37 -4
- package/dist/web-prefs.js.map +1 -1
- package/dist/web-preview.d.ts +6 -2
- package/dist/web-preview.js +4 -2
- package/dist/web-preview.js.map +1 -1
- package/dist/web-returning-device.d.ts +41 -0
- package/dist/web-returning-device.js +57 -5
- package/dist/web-returning-device.js.map +1 -1
- package/dist/web-session-authorization.d.ts +132 -0
- package/dist/web-session-authorization.js +193 -0
- package/dist/web-session-authorization.js.map +1 -0
- package/dist/web-session.d.ts +70 -10
- package/dist/web-session.js +137 -22
- package/dist/web-session.js.map +1 -1
- package/dist/web-settings-patch.d.ts +49 -2
- package/dist/web-settings-patch.js +145 -1
- package/dist/web-settings-patch.js.map +1 -1
- package/dist/web-settings-tools.d.ts +94 -0
- package/dist/web-settings-tools.js +301 -0
- package/dist/web-settings-tools.js.map +1 -0
- package/dist/web-shell-routes.d.ts +1 -1
- package/dist/web-shell-routes.js +1 -1
- package/dist/web-shell-routes.js.map +1 -1
- package/dist/web-terminal-http.js +15 -2
- package/dist/web-terminal-http.js.map +1 -1
- package/dist/web-theme-store.d.ts +39 -0
- package/dist/web-theme-store.js +122 -11
- package/dist/web-theme-store.js.map +1 -1
- package/dist/web-theme.d.ts +31 -0
- package/dist/web-theme.js +99 -2
- package/dist/web-theme.js.map +1 -1
- package/dist/web-upload.d.ts +13 -0
- package/dist/web-upload.js +39 -3
- package/dist/web-upload.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/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 +553 -0
- package/launcher/install-admission.cjs +4 -39
- package/launcher/postinstall.cjs +14 -12
- package/package.json +4 -2
- 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,176 @@
|
|
|
1
|
+
// #2272: a chat message's own actions, beyond the hover strip — the message menu (right-click, long-press on a phone),
|
|
2
|
+
// swipe left to reply (as in Telegram), and R on a focused message. One install per thread element.
|
|
3
|
+
//
|
|
4
|
+
// - Right-click on a message opens Reply / Copy text / Copy link. Shift+right-click, a right-click with text selected,
|
|
5
|
+
// or one on a link, an image or a field keeps the browser's own menu.
|
|
6
|
+
// - A long press (500 ms without moving) opens the same menu; the click and the browser menu it would also cause are
|
|
7
|
+
// swallowed.
|
|
8
|
+
// - Swipe left on a message: it follows the finger (up to 64 px); let go past 56 px and it is a reply. A mostly
|
|
9
|
+
// vertical move is scrolling, never a reply. A swipe right is the phone drawer's (app-swipe.js), on a message too: the
|
|
10
|
+
// two never fight.
|
|
11
|
+
// - R (no modifier) on a focused message replies; ↑/↓ move to the message before or after (one message is in the Tab
|
|
12
|
+
// order); Escape closes the menu.
|
|
13
|
+
|
|
14
|
+
const LONG_PRESS_MS = 500, MOVE_TOLERANCE = 10, SWIPE_REPLY_PX = 56, SWIPE_MAX_PX = 64;
|
|
15
|
+
|
|
16
|
+
/** The message element an event is on (a person's or an agent's message of this thread), or null. */
|
|
17
|
+
function messageEl(list, target) {
|
|
18
|
+
const el = target && target.closest ? target.closest(".msg[data-key]") : null;
|
|
19
|
+
return el && list.contains(el) ? el : null;
|
|
20
|
+
}
|
|
21
|
+
/** The browser's own menu stays for: Shift, selected text, a link, an image, a field, code. */
|
|
22
|
+
function keepsNativeMenu(e, doc) {
|
|
23
|
+
if (e.shiftKey) return true;
|
|
24
|
+
const sel = doc.getSelection ? doc.getSelection() : null;
|
|
25
|
+
if (sel && !sel.isCollapsed && String(sel).trim()) return true;
|
|
26
|
+
return !!(e.target && e.target.closest && e.target.closest("a[href], img, video, input, textarea, select, pre, code, [contenteditable='true']"));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Install the gestures on `list` (the thread element). `deps`:
|
|
31
|
+
* messageOf(key) → the row; reply(row); copyText(text) → Promise<boolean>; linkOf(row) → string; notice(text);
|
|
32
|
+
* canReply() → boolean (false: no Reply — a page that cannot send); t(key).
|
|
33
|
+
* Returns a function that removes everything (and closes an open menu).
|
|
34
|
+
*/
|
|
35
|
+
export function installMessageActions(list, deps) {
|
|
36
|
+
const doc = list.ownerDocument, win = doc.defaultView;
|
|
37
|
+
let menu = null, press = null, swipe = null, swallowClick = false;
|
|
38
|
+
|
|
39
|
+
function closeMenu() {
|
|
40
|
+
if (!menu) return;
|
|
41
|
+
menu.remove(); menu = null;
|
|
42
|
+
doc.removeEventListener("pointerdown", outside, true);
|
|
43
|
+
doc.removeEventListener("keydown", onMenuKey, true);
|
|
44
|
+
win?.removeEventListener("scroll", closeMenu, true);
|
|
45
|
+
win?.removeEventListener("blur", closeMenu);
|
|
46
|
+
}
|
|
47
|
+
function outside(e) { if (menu && !menu.contains(e.target)) closeMenu(); }
|
|
48
|
+
function onMenuKey(e) {
|
|
49
|
+
if (!menu) return;
|
|
50
|
+
if (e.key === "Escape") { e.preventDefault(); e.stopPropagation(); closeMenu(); return; }
|
|
51
|
+
if (e.key === "ArrowDown" || e.key === "ArrowUp") {
|
|
52
|
+
e.preventDefault();
|
|
53
|
+
const items = [...menu.querySelectorAll("button")], i = items.indexOf(doc.activeElement);
|
|
54
|
+
items[(i + (e.key === "ArrowDown" ? 1 : items.length - 1)) % items.length]?.focus();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** The message menu at (x, y), within the window; focus on its first item. */
|
|
58
|
+
function openMenu(row, x, y) {
|
|
59
|
+
closeMenu();
|
|
60
|
+
const items = [];
|
|
61
|
+
if (deps.canReply?.() !== false) items.push(["reply", deps.t("chat.reply"), () => deps.reply(row)]);
|
|
62
|
+
items.push(["copyText", deps.t("chat.copyText"), async () => { const ok = await deps.copyText(String(row.click?.label ?? row.text ?? "")); deps.notice(deps.t(ok ? "chat.copied" : "chat.copyFailed"), ok); }]);
|
|
63
|
+
items.push(["copyLink", deps.t("chat.copyLink"), async () => { const ok = await deps.copyText(deps.linkOf(row)); deps.notice(deps.t(ok ? "chat.copied" : "chat.copyFailed"), ok); }]);
|
|
64
|
+
menu = doc.createElement("div");
|
|
65
|
+
menu.className = "msg-menu";
|
|
66
|
+
menu.setAttribute("role", "menu");
|
|
67
|
+
menu.setAttribute("aria-label", deps.t("chat.msgMenu"));
|
|
68
|
+
menu.setAttribute("data-trust", "menu");
|
|
69
|
+
for (const [id, label, run] of items) {
|
|
70
|
+
const b = doc.createElement("button");
|
|
71
|
+
b.type = "button"; b.className = "menu-item"; b.setAttribute("role", "menuitem"); b.dataset.item = id; b.textContent = label;
|
|
72
|
+
b.addEventListener("click", () => { closeMenu(); void run(); });
|
|
73
|
+
menu.append(b);
|
|
74
|
+
}
|
|
75
|
+
doc.body.append(menu);
|
|
76
|
+
const w = win?.innerWidth ?? 1024, h = win?.innerHeight ?? 768, r = menu.getBoundingClientRect();
|
|
77
|
+
menu.style.left = `${Math.max(4, Math.min(x, w - r.width - 4))}px`;
|
|
78
|
+
menu.style.top = `${Math.max(4, Math.min(y, h - r.height - 4))}px`;
|
|
79
|
+
doc.addEventListener("pointerdown", outside, true);
|
|
80
|
+
doc.addEventListener("keydown", onMenuKey, true);
|
|
81
|
+
win?.addEventListener("scroll", closeMenu, true);
|
|
82
|
+
win?.addEventListener("blur", closeMenu);
|
|
83
|
+
menu.querySelector("button")?.focus();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function onContextMenu(e) {
|
|
87
|
+
if (swallowClick) { e.preventDefault(); return; } // the long press already opened ours
|
|
88
|
+
cancelPress(); // Android's long press fires this itself: one menu
|
|
89
|
+
const el = messageEl(list, e.target);
|
|
90
|
+
if (!el || keepsNativeMenu(e, doc)) return;
|
|
91
|
+
const row = deps.messageOf(el.dataset.key);
|
|
92
|
+
if (!row) return;
|
|
93
|
+
e.preventDefault();
|
|
94
|
+
openMenu(row, e.clientX, e.clientY);
|
|
95
|
+
}
|
|
96
|
+
function onKeyDown(e) {
|
|
97
|
+
// ↑/↓ on a focused message: the one before or after it (one message is in the Tab order: the thread's rove()).
|
|
98
|
+
if ((e.key === "ArrowUp" || e.key === "ArrowDown") && !e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey
|
|
99
|
+
&& e.target && e.target.matches && e.target.matches(".msg[data-key]") && list.contains(e.target)) {
|
|
100
|
+
const all = [...list.querySelectorAll(".msg[data-key]")], i = all.indexOf(e.target);
|
|
101
|
+
const to = all[i + (e.key === "ArrowDown" ? 1 : -1)];
|
|
102
|
+
if (to) { e.preventDefault(); deps.rove?.(to.dataset.key); to.focus(); to.scrollIntoView?.({ block: "nearest" }); }
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (e.key !== "r" && e.key !== "R") return;
|
|
106
|
+
if (e.ctrlKey || e.metaKey || e.altKey || deps.canReply?.() === false) return;
|
|
107
|
+
const el = e.target && e.target.matches && e.target.matches(".msg[data-key]") && list.contains(e.target) ? e.target : null;
|
|
108
|
+
const row = el ? deps.messageOf(el.dataset.key) : null;
|
|
109
|
+
if (!row) return;
|
|
110
|
+
e.preventDefault();
|
|
111
|
+
deps.reply(row);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function onTouchStart(e) {
|
|
115
|
+
if (e.touches.length !== 1) { cancelPress(); cancelSwipe(); return; }
|
|
116
|
+
const el = messageEl(list, e.target);
|
|
117
|
+
if (!el) return;
|
|
118
|
+
const t0 = e.touches[0];
|
|
119
|
+
const native = keepsNativeMenu({ target: e.target, shiftKey: false }, doc); // a link, an image, code: the browser's
|
|
120
|
+
press = native ? null : { el, x: t0.clientX, y: t0.clientY, timer: setTimeout(() => {
|
|
121
|
+
const row = deps.messageOf(el.dataset.key);
|
|
122
|
+
press = null; cancelSwipe();
|
|
123
|
+
if (!row) return;
|
|
124
|
+
swallowClick = true; setTimeout(() => { swallowClick = false; }, 700);
|
|
125
|
+
openMenu(row, t0.clientX, t0.clientY);
|
|
126
|
+
}, LONG_PRESS_MS) };
|
|
127
|
+
swipe = deps.canReply?.() === false || native ? null : { el, x: t0.clientX, y: t0.clientY, dx: 0, locked: null };
|
|
128
|
+
}
|
|
129
|
+
function onTouchMove(e) {
|
|
130
|
+
const p = e.touches[0];
|
|
131
|
+
if (press && (Math.abs(p.clientX - press.x) > MOVE_TOLERANCE || Math.abs(p.clientY - press.y) > MOVE_TOLERANCE)) cancelPress();
|
|
132
|
+
if (!swipe) return;
|
|
133
|
+
const dx = p.clientX - swipe.x, dy = p.clientY - swipe.y;
|
|
134
|
+
if (swipe.locked === null && (Math.abs(dx) > MOVE_TOLERANCE || Math.abs(dy) > MOVE_TOLERANCE)) swipe.locked = dx < 0 && Math.abs(dy) < -dx / 2 ? "x" : "no";
|
|
135
|
+
if (swipe.locked !== "x") return;
|
|
136
|
+
swipe.dx = Math.max(0, Math.min(-dx, SWIPE_MAX_PX)); // how far left, as a positive distance
|
|
137
|
+
swipe.el.style.transform = `translateX(${-swipe.dx}px)`;
|
|
138
|
+
swipe.el.classList.toggle("swipe-ready", swipe.dx >= SWIPE_REPLY_PX);
|
|
139
|
+
}
|
|
140
|
+
function onTouchEnd() {
|
|
141
|
+
cancelPress();
|
|
142
|
+
if (!swipe) return;
|
|
143
|
+
const { el, dx, locked } = swipe;
|
|
144
|
+
cancelSwipe();
|
|
145
|
+
if (locked === "x" && dx >= SWIPE_REPLY_PX) { const row = deps.messageOf(el.dataset.key); if (row) deps.reply(row); }
|
|
146
|
+
}
|
|
147
|
+
function cancelPress() { if (press) { clearTimeout(press.timer); press = null; } }
|
|
148
|
+
function cancelSwipe() {
|
|
149
|
+
if (!swipe) return;
|
|
150
|
+
swipe.el.style.transform = ""; swipe.el.classList.remove("swipe-ready");
|
|
151
|
+
swipe = null;
|
|
152
|
+
}
|
|
153
|
+
function onClickCapture(e) { if (swallowClick) { e.preventDefault(); e.stopPropagation(); } }
|
|
154
|
+
|
|
155
|
+
// A message focused by a click or a tap becomes the one Tab comes back to.
|
|
156
|
+
function onFocusIn(e) { const el = e.target && e.target.matches && e.target.matches(".msg[data-key]") ? e.target : null; if (el && list.contains(el)) deps.rove?.(el.dataset.key); }
|
|
157
|
+
list.addEventListener("focusin", onFocusIn);
|
|
158
|
+
list.addEventListener("contextmenu", onContextMenu);
|
|
159
|
+
list.addEventListener("keydown", onKeyDown);
|
|
160
|
+
list.addEventListener("touchstart", onTouchStart, { passive: true });
|
|
161
|
+
list.addEventListener("touchmove", onTouchMove, { passive: true });
|
|
162
|
+
list.addEventListener("touchend", onTouchEnd, { passive: true });
|
|
163
|
+
list.addEventListener("touchcancel", onTouchEnd, { passive: true });
|
|
164
|
+
list.addEventListener("click", onClickCapture, true);
|
|
165
|
+
return () => {
|
|
166
|
+
closeMenu(); cancelPress(); cancelSwipe();
|
|
167
|
+
list.removeEventListener("focusin", onFocusIn);
|
|
168
|
+
list.removeEventListener("contextmenu", onContextMenu);
|
|
169
|
+
list.removeEventListener("keydown", onKeyDown);
|
|
170
|
+
list.removeEventListener("touchstart", onTouchStart);
|
|
171
|
+
list.removeEventListener("touchmove", onTouchMove);
|
|
172
|
+
list.removeEventListener("touchend", onTouchEnd);
|
|
173
|
+
list.removeEventListener("touchcancel", onTouchEnd);
|
|
174
|
+
list.removeEventListener("click", onClickCapture, true);
|
|
175
|
+
};
|
|
176
|
+
}
|
package/dist/ui/chat-render.js
CHANGED
|
@@ -53,11 +53,14 @@
|
|
|
53
53
|
|
|
54
54
|
// #1630: a Discord server emoji, `<:name:id>` / `<a:name:id>` — escaped by now — drawn as its picture. Only an id the
|
|
55
55
|
// page knows (the fleet's servers: /ui/emojis) and only from the dashboard's own route; the src is built from the
|
|
56
|
-
// matched digits, the name (word characters only) goes into alt/title.
|
|
56
|
+
// matched digits, the name (word characters only) goes into alt/title. Any other — an id the page does not know, or
|
|
57
|
+
// before the list has come — reads `:name:` (never the raw markup); so does a picture that does not load
|
|
58
|
+
// (chat-thread.js swaps it: an <img> sized to an emoji showed an empty box, the user's "tofu").
|
|
57
59
|
var EMOJI_RE = /<(a?):([A-Za-z0-9_]{2,32}):(\d{15,25})>/g;
|
|
58
60
|
function emojiImg(id, name) {
|
|
59
61
|
return '<img class="emoji" src="/ui/img/emoji/' + id + '" alt=":' + name + ':" title=":' + name + ':" decoding="async">';
|
|
60
62
|
}
|
|
63
|
+
function emojiText(name) { return '<span class="emoji-text" title=":' + name + ':">:' + name + ':</span>'; }
|
|
61
64
|
|
|
62
65
|
// #1682: Discord mentions — `<@id>` / `<@!id>` (a user), `<@&id>` (a role), `<#id>` (a channel) — escaped by now (the
|
|
63
66
|
// role's & too), drawn as a pill: the name the page knows (store.mentions(kind, id), inserted escaped), else @user /
|
|
@@ -82,7 +85,7 @@
|
|
|
82
85
|
// path held its whole column wide.
|
|
83
86
|
s = s.replace(/`([^`\n]+)`/g, function (_m, code) { return stash(store, "<code>" + (store.inCell ? code.replace(/\//g, "/<wbr>") : code) + "</code>"); });
|
|
84
87
|
var known = store.emojis;
|
|
85
|
-
|
|
88
|
+
s = s.replace(EMOJI_RE, function (_m, _a, name, id) { return stash(store, known && known(id) ? emojiImg(id, name) : emojiText(name)); });
|
|
86
89
|
var names = store.mentions;
|
|
87
90
|
s = s.replace(MENTION_RE, function (_m, sigil, id) {
|
|
88
91
|
var kind = MENTION_KIND[sigil];
|
|
@@ -577,6 +580,21 @@
|
|
|
577
580
|
* With { htmlCards: true } (a server-marked agent reply, as for renderMarkdown) each .html/.htm file also gets an
|
|
578
581
|
* empty card placeholder <div class="html-card" data-att="<id>"> after the list — the id is 32 hex, nothing else.
|
|
579
582
|
*/
|
|
583
|
+
// The box a photo is drawn in (app.css: .msg .att-img img, max 260 × 220): its own size, scaled down to fit.
|
|
584
|
+
var PHOTO_MAX_W = 260, PHOTO_MAX_H = 220;
|
|
585
|
+
/**
|
|
586
|
+
* #2184: a photo's drawn size as width/height attributes, from the size the server read from its headers: the box is there
|
|
587
|
+
* before the picture loads, so the text around it never moves when it does (a chat opened cold jittered, as each
|
|
588
|
+
* photo grew from nothing). Nothing when the size is not known (drawn as before).
|
|
589
|
+
*/
|
|
590
|
+
function photoBox(a) {
|
|
591
|
+
var w = a.width, h = a.height;
|
|
592
|
+
var ok = function (v) { return typeof v === "number" && v >= 1 && v <= 65535 && Math.floor(v) === v; };
|
|
593
|
+
if (!ok(w) || !ok(h)) return "";
|
|
594
|
+
var k = Math.min(1, PHOTO_MAX_W / w, PHOTO_MAX_H / h);
|
|
595
|
+
return ' width="' + Math.max(1, Math.round(w * k)) + '" height="' + Math.max(1, Math.round(h * k)) + '"';
|
|
596
|
+
}
|
|
597
|
+
|
|
580
598
|
function attachmentsHtml(attachments, opts) {
|
|
581
599
|
if (!Array.isArray(attachments)) return "";
|
|
582
600
|
var cards = !!(opts && opts.htmlCards);
|
|
@@ -599,7 +617,7 @@
|
|
|
599
617
|
else if (kind) after.push('<div class="text-card" data-att="' + a.id + '" data-type="' + kind + '"></div>');
|
|
600
618
|
var name = escapeHtml(a.name || "file");
|
|
601
619
|
if (a.kind === "photo") {
|
|
602
|
-
out.push('<a class="att-img" href="' + url + '" target="_blank" rel="noopener noreferrer"><img src="' + url + '" alt="' + name + '" loading="lazy"></a>');
|
|
620
|
+
out.push('<a class="att-img" href="' + url + '" target="_blank" rel="noopener noreferrer"><img src="' + url + '" alt="' + name + '"' + photoBox(a) + ' loading="lazy"></a>');
|
|
603
621
|
} else {
|
|
604
622
|
out.push('<a class="att-file" href="' + url + '" download="' + name + '">📎 ' + name + ' <span class="att-size">' + escapeHtml(formatSize(a.size)) + "</span></a>");
|
|
605
623
|
}
|
package/dist/ui/chat-store.js
CHANGED
|
@@ -42,7 +42,7 @@ const COMPACT_PAGE_LIMIT_MS = 11 * 60_000;
|
|
|
42
42
|
/** Build a store. `deps` (fetch, toast, announce, t, now) are injected so tests can drive every path. */
|
|
43
43
|
export function createChatStore(deps) {
|
|
44
44
|
const s = {
|
|
45
|
-
msgs: {}, drafts: {}, failedSends: {}, pendingFiles: {}, sending: {}, inFlightFiles: {},
|
|
45
|
+
msgs: {}, drafts: {}, replies: {}, failedSends: {}, pendingFiles: {}, sending: {}, inFlightFiles: {}, sendFailures: {}, instanceStatus: {}, waking: {},
|
|
46
46
|
prompts: {}, workingSince: {}, stopping: {}, cancelling: {}, scrollMemo: {}, historyRead: new Set(), rbBusy: new Set(),
|
|
47
47
|
pollMine: readPollMine(),
|
|
48
48
|
// #1823 (#1828 review): the server's clock minus this device's. A poll's deadline is the server's; a page whose clock
|
|
@@ -61,9 +61,10 @@ export function createChatStore(deps) {
|
|
|
61
61
|
|
|
62
62
|
/** Tell subscribers what changed: `kind` "msgs" (the thread redraws) or "state" (everything else). */
|
|
63
63
|
function changed(instance, kind = "state") { for (const fn of [...subs]) fn(instance, kind); }
|
|
64
|
-
async function api(method, path, body) {
|
|
64
|
+
async function api(method, path, body, signal) {
|
|
65
65
|
const o = { method, headers: { "Content-Type": "application/json" } };
|
|
66
66
|
if (body) o.body = JSON.stringify(body);
|
|
67
|
+
if (signal) o.signal = signal;
|
|
67
68
|
const r = await deps.fetch(path, o);
|
|
68
69
|
return r.json();
|
|
69
70
|
}
|
|
@@ -82,6 +83,7 @@ export function createChatStore(deps) {
|
|
|
82
83
|
function applyStatus(d) {
|
|
83
84
|
if (!d || !Array.isArray(d.instances)) return;
|
|
84
85
|
for (const i of d.instances) {
|
|
86
|
+
s.instanceStatus[i.name] = i.status;
|
|
85
87
|
noteExec(i.name, (i.execution_state !== undefined ? i.execution_state : i.state) ?? null);
|
|
86
88
|
const waits = i.state === "awaiting_input" ? (typeof i.interaction_summary === "string" ? i.interaction_summary : "") : null;
|
|
87
89
|
if (i.name === s.current && waits != null && s.awaiting[i.name] == null) deps.announce(tf("chat.awaiting", i.name));
|
|
@@ -142,12 +144,17 @@ export function createChatStore(deps) {
|
|
|
142
144
|
if (!r || !r.answered) deps.toast(r && r.error ? r.error : t("chat.disconnected"), false);
|
|
143
145
|
}
|
|
144
146
|
|
|
145
|
-
/**
|
|
146
|
-
|
|
147
|
-
|
|
147
|
+
/**
|
|
148
|
+
* Read an instance's history once per page (the first time a person opens its chat). #2188: `signal` — the chat was
|
|
149
|
+
* left before the answer came (clicking down the sidebar): the read is aborted, nothing is merged, and the next visit
|
|
150
|
+
* reads again.
|
|
151
|
+
*/
|
|
152
|
+
async function openHistory(name, lease, signal) {
|
|
153
|
+
if (s.historyRead.has(name) || signal?.aborted) return false;
|
|
148
154
|
s.historyRead.add(name);
|
|
149
155
|
try {
|
|
150
|
-
const r = await api("GET", `/ui/history?instance=${encodeURIComponent(name)}&limit=200
|
|
156
|
+
const r = await api("GET", `/ui/history?instance=${encodeURIComponent(name)}&limit=200`, undefined, signal);
|
|
157
|
+
if (signal?.aborted) { s.historyRead.delete(name); return false; }
|
|
151
158
|
if (!r || !Array.isArray(r.messages)) { s.historyRead.delete(name); return true; }
|
|
152
159
|
// Kept even when the person has moved on: the store is page-lived, and the answer belongs to `name`.
|
|
153
160
|
for (const m of r.messages) liveReplies.message(m);
|
|
@@ -243,9 +250,12 @@ export function createChatStore(deps) {
|
|
|
243
250
|
}
|
|
244
251
|
async function send(target) {
|
|
245
252
|
const txt = (s.drafts[target] || "").trim();
|
|
253
|
+
const quote = s.replies[target]; // #2272: the message this one replies to (its row; the server reads the rest)
|
|
246
254
|
const files = (s.pendingFiles[target] || []).slice();
|
|
247
255
|
if ((!txt && !files.length) || !target || s.sending[target]) return;
|
|
248
256
|
s.sending[target] = true;
|
|
257
|
+
s.waking[target] = s.instanceStatus[target] === "paused";
|
|
258
|
+
delete s.sendFailures[target];
|
|
249
259
|
s.drafts[target] = "";
|
|
250
260
|
s.pendingFiles[target] = []; s.inFlightFiles[target] = files;
|
|
251
261
|
changed(target);
|
|
@@ -254,20 +264,37 @@ export function createChatStore(deps) {
|
|
|
254
264
|
try {
|
|
255
265
|
const ids = [];
|
|
256
266
|
for (const f of files) ids.push((await uploadFile(target, f)).id);
|
|
257
|
-
|
|
267
|
+
const body = ids.length ? { instance: target, message: txt, attachments: ids } : { instance: target, message: txt };
|
|
268
|
+
if (quote) body.replyTo = { boot: quote.boot, id: quote.id };
|
|
269
|
+
r = await api("POST", "/ui/send", body);
|
|
258
270
|
} catch (err) { r = { error: err && err.message ? err.message : t("chat.disconnected") }; }
|
|
259
271
|
s.sending[target] = false;
|
|
272
|
+
delete s.waking[target];
|
|
260
273
|
delete s.inFlightFiles[target];
|
|
261
|
-
if (r && !r.error) { changed(target); return; }
|
|
274
|
+
if (r && !r.error) { if (s.replies[target] === quote) delete s.replies[target]; changed(target); return; }
|
|
275
|
+
// #2272: the quoted message is gone: the reply goes, the text and files stay (sent again without it, or re-aimed).
|
|
276
|
+
if (r && r.reason === "reply_gone" && s.replies[target] === quote) delete s.replies[target];
|
|
262
277
|
if (files.length) s.pendingFiles[target] = R().checkFiles(files, s.pendingFiles[target] || []).kept;
|
|
263
278
|
if (txt) {
|
|
264
279
|
const shown = s.current === target;
|
|
265
280
|
if (R().settleFailedSend(target, s.current, shown, shown ? (s.drafts[target] || "") : "") === "restore") s.drafts[target] = txt;
|
|
266
281
|
else s.failedSends[target] = s.failedSends[target] ? `${s.failedSends[target]}\n${txt}` : txt;
|
|
267
282
|
}
|
|
283
|
+
const why = r && r.reason;
|
|
284
|
+
const key = typeof why === "string" ? `chat.sendFailure_${why}` : "";
|
|
285
|
+
const localized = key ? t(key) : "";
|
|
286
|
+
const error = localized && localized !== key ? localized : (r && r.error ? r.error : t("chat.disconnected"));
|
|
287
|
+
s.sendFailures[target] = { error, text: txt, files };
|
|
268
288
|
changed(target);
|
|
269
|
-
deps.toast(
|
|
289
|
+
deps.toast(error, false);
|
|
270
290
|
}
|
|
291
|
+
function canRetrySend(target) {
|
|
292
|
+
const failed = s.sendFailures[target], files = s.pendingFiles[target] || [];
|
|
293
|
+
return !!failed && !s.sending[target] && !s.failedSends[target]
|
|
294
|
+
&& (s.drafts[target] || "").trim() === failed.text
|
|
295
|
+
&& files.length === failed.files.length && files.every((f, i) => f === failed.files[i]);
|
|
296
|
+
}
|
|
297
|
+
function retrySend(target) { if (canRetrySend(target)) return send(target); }
|
|
271
298
|
function addFiles(target, list) {
|
|
272
299
|
if (!target) return;
|
|
273
300
|
const inFlight = s.inFlightFiles[target] || [];
|
|
@@ -307,8 +334,32 @@ export function createChatStore(deps) {
|
|
|
307
334
|
changed(target);
|
|
308
335
|
}
|
|
309
336
|
function discardFailed(target) { delete s.failedSends[target]; changed(target); }
|
|
310
|
-
/** Typing
|
|
311
|
-
function setDraft(target, value) { s.drafts[target] = value; }
|
|
337
|
+
/** Typing stays local, except a failed send's Retry button must follow edits too. */
|
|
338
|
+
function setDraft(target, value) { s.drafts[target] = value; if (s.sendFailures[target]) changed(target); }
|
|
339
|
+
/**
|
|
340
|
+
* #2272: reply to a message of this chat — what the bar above the composer shows (its sender and first words); only
|
|
341
|
+
* its row is sent. One at a time per chat: a new one replaces it.
|
|
342
|
+
*/
|
|
343
|
+
function startReply(target, m) {
|
|
344
|
+
if (!target || !m || typeof m.boot !== "string" || typeof m.id !== "number") return;
|
|
345
|
+
s.replies[target] = { boot: m.boot, id: m.id, sender: String(m.sender || ""), text: String(m.click?.label ?? m.text ?? "").replace(/\s+/g, " ").trim().slice(0, 160),
|
|
346
|
+
media: (m.attachments || []).length ? ((m.attachments || []).some(a => a.kind === "photo") ? "photo" : "document") : undefined };
|
|
347
|
+
changed(target);
|
|
348
|
+
}
|
|
349
|
+
function clearReply(target) { if (s.replies[target]) { delete s.replies[target]; changed(target); } }
|
|
350
|
+
/**
|
|
351
|
+
* #2272: the quoted message, drawn for a jump: in what this chat holds, or after reading the longest history the
|
|
352
|
+
* server keeps for it (the newest 500). false: no longer kept.
|
|
353
|
+
*/
|
|
354
|
+
async function findQuoted(name, key) {
|
|
355
|
+
const has = () => (s.msgs[name] || []).some(m => `${m.boot}-${m.id}` === key);
|
|
356
|
+
if (has()) return true;
|
|
357
|
+
try {
|
|
358
|
+
const r = await api("GET", `/ui/history?instance=${encodeURIComponent(name)}&limit=500`);
|
|
359
|
+
if (r && Array.isArray(r.messages)) { s.msgs[name] = R().mergeMessages(s.msgs[name], r.messages, 500); changed(name, "msgs"); }
|
|
360
|
+
} catch { /* the jump says it is not there */ }
|
|
361
|
+
return has();
|
|
362
|
+
}
|
|
312
363
|
|
|
313
364
|
// ── Stop the reply under way (the composer's Stop, or Esc). Set before the request goes, so a held Esc or a second
|
|
314
365
|
// click sends nothing more (#1317); "Stopping…" until the agent goes idle, or a minute passes.
|
|
@@ -402,7 +453,8 @@ export function createChatStore(deps) {
|
|
|
402
453
|
attach, applyStatus, applyActivity, ingest, applyDeliveries, openHistory,
|
|
403
454
|
onPrompt, applyPrompts, resolvePrompt, answerPrompt, answerByNonce, holdPrompt, releasePrompt, promptsFor,
|
|
404
455
|
applyReplyButtons, clickReplyButton,
|
|
405
|
-
uploadFile, send, addFiles, removeFile, attachPastedText, fileBackAsText, isPasted, putBack, discardFailed, setDraft,
|
|
456
|
+
uploadFile, send, canRetrySend, retrySend, addFiles, removeFile, attachPastedText, fileBackAsText, isPasted, putBack, discardFailed, setDraft,
|
|
457
|
+
startReply, clearReply, findQuoted,
|
|
406
458
|
cancelReply, isUser, runCommand, dismissCommand, commandFree,
|
|
407
459
|
};
|
|
408
460
|
}
|
package/dist/ui/chat-strings.js
CHANGED
|
@@ -3,14 +3,42 @@ import { register } from "/assets/app-i18n.js";
|
|
|
3
3
|
|
|
4
4
|
register("chat", {
|
|
5
5
|
en: {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
waking: "Waking {0}…", retrySend: "Retry send",
|
|
7
|
+
sendFailure_wake_capacity: "No slot is free to wake this instance. Retry when another instance is idle.",
|
|
8
|
+
sendFailure_wake_credentials: "The instance could not sign in. Check its account on the host, then retry.",
|
|
9
|
+
sendFailure_wake_timeout: "The instance did not become ready in time. Retry, or check its status on the host.",
|
|
10
|
+
sendFailure_instance_stopped: "This instance was stopped or removed. Start it on the host before retrying.",
|
|
11
|
+
sendFailure_delivery_unavailable: "The instance could not receive this message. Check its status on the host, then retry.",
|
|
12
|
+
sendFailure_delivery_changed: "The session or instance changed before this message was sent. Sign in again if needed, then retry.",
|
|
13
|
+
sendFailure_reply_gone: "The message you replied to is no longer in this chat. Your text is still here: send it without the reply, or reply to another message.",
|
|
14
|
+
reply: "Reply", replyingTo: "Replying to {0}", replyCancel: "Cancel the reply (Esc)", replyHidden: "an earlier message", replyPhoto: "[Photo]", replyFile: "[File]",
|
|
15
|
+
replyGone: "That message is no longer in this chat.", replyJump: "Show the message this replies to", copyText: "Copy text", copyLink: "Copy link", msgMenu: "Message",
|
|
16
|
+
|
|
17
|
+
effectTrialReason_checking: "Checking this session…",
|
|
18
|
+
effectTrialReason_localAdmin: "Sign in as an admin outside the public link to Try.",
|
|
19
|
+
effectTrialReason_chatChanged: "Open the chat that offered this trial.",
|
|
20
|
+
effectTrialReason_busy: "Stop the current trial before starting another.",
|
|
21
|
+
effectTrialReason_safe: "Turn off safe mode to Try.",
|
|
22
|
+
effectTrialReason_effectsOff: "Turn on effects to Try.",
|
|
23
|
+
effectTrialReason_reducedMotion: "Effects follow this device’s reduced-motion setting.",
|
|
24
|
+
effectTrialReason_saveData: "Your device requests reduced data use.",
|
|
25
|
+
effectTrialReason_transport: "The isolated effect player is unavailable. Reload this page.",
|
|
26
|
+
effectTrialReason_unsupported: "Canvas Worker playback is unavailable in this browser.",
|
|
27
|
+
effectTrialReason_inactive: "Return to this page to Try.",
|
|
28
|
+
effectTrialReason_dialog: "Close the other menu or dialog to Try.",
|
|
29
|
+
effectTrialReason_expired: "This trial offer has expired.",
|
|
30
|
+
effectTrialSignIn: "Sign in here",
|
|
31
|
+
effectTrialStopOther: "Stop current trial",
|
|
32
|
+
effectTrialSettings: "Open playback settings",
|
|
33
|
+
effectTrialPlayMotion: "Play effects anyway",
|
|
34
|
+
effectTrial: "Effect trial", effectTrialLocal: "A sample on this page. Nothing is applied or saved.",
|
|
35
|
+
effectTrialStopped: "Try stopped", effectTrialStart: "Try", effectTrialExpired: "This trial offer has expired.", effectTrialUnavailable: "This trial is no longer available.",
|
|
8
36
|
cmdConfirm: "Clear", cmdConfirmBackend: "Switch and restart", cmdRunning: "Running /{0}…", cmdNotCommand: "Not a command here — Enter sends it as a message.", cmdDismiss: "Dismiss", cmdCommands: "Commands",
|
|
9
37
|
compactRunning: "Compacting…", compactDone: "✅ Conversation compacted", compactUnknown: "This backend does not report when compaction ends.",
|
|
10
38
|
compactTimeout: "No sign that compaction finished within {0} minutes — check the agent's own chat.",
|
|
11
39
|
compactLost: "Can't follow this compaction: the command did not reach the agent, or the agent stopped or changed backend.",
|
|
12
40
|
compactNotCompacted: "kiro did not compact the conversation: it was too short, or the compaction was stopped.",
|
|
13
|
-
cmdChoose: "Choose", cmdCurrent: "current", chipCompact: "Compact", chipClear: "Clear…", chipContext: "Context {0}% used",
|
|
41
|
+
cmdChoose: "Choose", cmdCurrent: "current", cmdSignIn: "Sign in", cmdSignInTo: "Sign in to {0}", chipCompact: "Compact", chipClear: "Clear…", chipContext: "Context {0}% used",
|
|
14
42
|
chipModel: "Model: {0} — choose another", chipEffort: "Effort: {0} — choose another",
|
|
15
43
|
cmd_ctx: "Context use, model and effort", cmd_compact: "Compact the conversation", cmd_clear: "Clear the conversation (asks first)",
|
|
16
44
|
cmd_model: "Show or switch the model", cmd_backend: "Switch the CLI backend, then model and effort (restarts)", cmd_effort: "Show or set the reasoning effort", cmd_cancel: "Stop the current reply",
|
|
@@ -25,7 +53,8 @@ register("chat", {
|
|
|
25
53
|
a11yWorking: "{0} started working", a11yIdle: "{0} finished", a11yReplied: "{0} replied", conversationWith: "Conversation with {0}",
|
|
26
54
|
stopping: "Stopping {0}…", awaiting: "{0} is waiting for your input", approxNote: "Read from the terminal, so approximate", elapsedTitle: "Time since this page saw it start (approximate)",
|
|
27
55
|
dropHere: "Drop files to attach them", asText: "As text", pasteAttached: "A long paste ({0} characters) was attached as a text file", pasteKeptAsText: "No room for another attachment: the long paste stays as text",
|
|
28
|
-
send: "Send", composerPlaceholder: "Message {0}…", composerHint: "Enter to send · Shift+Enter for a new line", composerMore: "/ for commands · Esc stops the reply",
|
|
56
|
+
send: "Send", composerPlaceholder: "Message {0}…", composerHint: "Enter to send · Shift+Enter for a new line", composerMore: "/ for commands · Esc stops the reply", guestMore: "Esc stops the reply",
|
|
57
|
+
guestNote: "You're a guest: the agent sees your messages as a guest's (recognition only).", guestNoCommands: "Guests can't run commands — send it without the leading /.", attachTitle: "Attach files (any type — or paste / drop them)",
|
|
29
58
|
pvPreview: "Preview", pvStop: "Stop", pvDownload: "Download", pvMenu: "Preview options", pvHtml: "HTML",
|
|
30
59
|
pvAllowButton: "Allow previews", pvAllow: "Allow HTML previews — they may be able to send data out", pvDisallow: "Stop allowing HTML previews",
|
|
31
60
|
pvConfirm: "Allow HTML previews?\n\nThis applies on every device where you are signed in. A preview runs the agent's HTML in an isolated frame. It cannot use your login, but it may be able to send data out, and it can slow or freeze this tab. You still click Preview each time.",
|
|
@@ -71,6 +100,8 @@ register("chat", {
|
|
|
71
100
|
"pvFail_bad-address": "Cloudflare gave an address that could not be used",
|
|
72
101
|
pvFail_unknown: "an unexpected error",
|
|
73
102
|
pvServer_notOffered: "Previews are not available on this page.",
|
|
103
|
+
pvServer_listenFailed: "Previews are unavailable: the fleet could not open its preview port ({0}). Another program may be using it — set web.preview_port, then restart AgEnD.",
|
|
104
|
+
pvServer_notListening: "Previews are not available on this fleet right now.",
|
|
74
105
|
previews: "Allow HTML previews",
|
|
75
106
|
clicked: "Clicked:", clickShow: "Show the message these buttons were on",
|
|
76
107
|
copy: "Copy", copyMessage: "Copy this reply", copied: "Copied", copyFailed: "Copy failed", wrap: "Wrap", showAll: "Show all {0} lines", showMore: "Show more", showLess: "Show less", jumpLatest: "Latest", newBelow: "{0} new",
|
|
@@ -94,21 +125,57 @@ register("chat", {
|
|
|
94
125
|
dNoActivity: "No activity in the last hour.", dWorking: "Working…",
|
|
95
126
|
// #1629: a person's control over an agent's own web theme.
|
|
96
127
|
themeLock: "Lock theme", themeUnlock: "Unlock theme", themeReset: "Reset theme…", themeResetGo: "Reset",
|
|
128
|
+
pageColours: "Page colours", pageAgentOn: "The agent's choice (on)", pageAgentOff: "The agent's choice (off)", pageWhole: "On the whole page", pageChatOnly: "Only its chat",
|
|
97
129
|
themeResetConfirm: "Reset {0}'s theme to the default? Its colours, picture and working label go; a lock stays.",
|
|
98
130
|
themeResetDone: "{0}'s theme was reset.", themeLocked: "{0}'s theme is locked: the agent can't change it.", themeUnlocked: "{0}'s theme is unlocked.",
|
|
99
131
|
themeFailed: "The theme was not changed ({0}).",
|
|
100
132
|
widgetRemoveHeader: "Remove the chat header widget", widgetRemoveDetails: "Remove the Details widget", widgetRemoved: "{0}'s widget was removed.",
|
|
133
|
+
// #2117: an agent's ambient effect — why it is not showing here, and a person's Clear.
|
|
134
|
+
ambientBlocked_hidden: "Ambient effect hidden: agents' themes are off — turn them on",
|
|
135
|
+
ambientBlocked_safe: "Ambient effect hidden: safe mode (?safe=1) — leave safe mode",
|
|
136
|
+
ambientBlocked_reducedMotion: "Ambient effect hidden: this device follows reduced motion — play effects anyway",
|
|
137
|
+
ambientBlocked_unsupported: "Ambient effect hidden: this browser can't animate it",
|
|
138
|
+
ambientClearLoop: "Clear the ambient effect", ambientClearClick: "Clear the click effect", ambientCleared: "{0}'s ambient effect was cleared.",
|
|
139
|
+
ambientMotionNote: "Your system asks for reduced motion; effects are on.", ambientMotionNoteLink: "Turn off here", ambientMotionNoteClose: "Close",
|
|
101
140
|
configured: "(configured)", fleetDefault: "(fleet default)",
|
|
102
141
|
},
|
|
103
142
|
"zh-TW": {
|
|
104
|
-
|
|
105
|
-
|
|
143
|
+
waking: "正在喚醒 {0}…", retrySend: "重試傳送",
|
|
144
|
+
sendFailure_wake_capacity: "目前沒有空位可喚醒這個實例。請等其他實例閒置後重試。",
|
|
145
|
+
sendFailure_wake_credentials: "實例無法登入。請先在主機檢查它的帳號,再重試。",
|
|
146
|
+
sendFailure_wake_timeout: "實例未能及時就緒。請重試,或在主機檢查它的狀態。",
|
|
147
|
+
sendFailure_instance_stopped: "這個實例已停止或移除。請先在主機啟動它,再重試。",
|
|
148
|
+
sendFailure_delivery_unavailable: "實例目前無法接收這則訊息。請在主機檢查它的狀態,再重試。",
|
|
149
|
+
sendFailure_delivery_changed: "訊息送出前,登入或實例狀態已改變。必要時請重新登入,再重試。",
|
|
150
|
+
sendFailure_reply_gone: "你回覆的訊息已不在這個聊天裡。內容還在:可以不帶回覆直接送出,或改回覆其他訊息。",
|
|
151
|
+
reply: "回覆", replyingTo: "回覆 {0}", replyCancel: "取消回覆(Esc)", replyHidden: "之前的一則訊息", replyPhoto: "[圖片]", replyFile: "[檔案]",
|
|
152
|
+
replyGone: "那則訊息已不在這個聊天裡。", replyJump: "顯示被回覆的訊息", copyText: "複製文字", copyLink: "複製連結", msgMenu: "訊息",
|
|
153
|
+
|
|
154
|
+
effectTrialReason_checking: "正在確認工作階段…",
|
|
155
|
+
effectTrialReason_localAdmin: "請在公開連結以外的儀表板以管理員登入後試播。",
|
|
156
|
+
effectTrialReason_chatChanged: "請開啟發出試播邀請的聊天。",
|
|
157
|
+
effectTrialReason_busy: "請先停止目前的試播。",
|
|
158
|
+
effectTrialReason_safe: "請先關閉安全模式。",
|
|
159
|
+
effectTrialReason_effectsOff: "請先開啟效果。",
|
|
160
|
+
effectTrialReason_reducedMotion: "效果跟隨這台裝置的「減少動態效果」設定。",
|
|
161
|
+
effectTrialReason_saveData: "裝置目前要求節省數據。",
|
|
162
|
+
effectTrialReason_transport: "隔離效果播放器目前無法使用。請重新載入頁面。",
|
|
163
|
+
effectTrialReason_unsupported: "此瀏覽器無法播放 Canvas Worker 效果。",
|
|
164
|
+
effectTrialReason_inactive: "請回到本頁後試播。",
|
|
165
|
+
effectTrialReason_dialog: "請先關閉其他選單或對話框。",
|
|
166
|
+
effectTrialReason_expired: "試播邀請已過期。",
|
|
167
|
+
effectTrialSignIn: "在此登入",
|
|
168
|
+
effectTrialStopOther: "停止目前試播",
|
|
169
|
+
effectTrialSettings: "開啟播放設定",
|
|
170
|
+
effectTrialPlayMotion: "仍然播放效果",
|
|
171
|
+
effectTrial: "效果試播", effectTrialLocal: "僅在本頁試播,不會套用或儲存。",
|
|
172
|
+
effectTrialStopped: "試播已停止", effectTrialStart: "試播", effectTrialExpired: "試播邀請已過期。", effectTrialUnavailable: "此試播已無法使用。",
|
|
106
173
|
cmdConfirm: "清空", cmdConfirmBackend: "切換並重新啟動", cmdRunning: "執行 /{0} 中…", cmdNotCommand: "這裡沒有這個指令——按 Enter 會當成一般訊息送出。", cmdDismiss: "關閉", cmdCommands: "指令",
|
|
107
174
|
compactRunning: "壓縮中…", compactDone: "✅ 對話已壓縮", compactUnknown: "這個後端不會回報壓縮何時完成。",
|
|
108
175
|
compactTimeout: "{0} 分鐘內沒有看到壓縮完成的紀錄,請到代理自己的對話確認。",
|
|
109
176
|
compactLost: "無法再追蹤這次壓縮:指令沒有送到代理,或代理已停止、換了後端。",
|
|
110
177
|
compactNotCompacted: "kiro 沒有壓縮對話:對話太短,或壓縮被中止了。",
|
|
111
|
-
cmdChoose: "選擇", cmdCurrent: "目前", chipCompact: "壓縮", chipClear: "清空…", chipContext: "已用 {0}% 的 context",
|
|
178
|
+
cmdChoose: "選擇", cmdCurrent: "目前", cmdSignIn: "登入", cmdSignInTo: "登入 {0}", chipCompact: "壓縮", chipClear: "清空…", chipContext: "已用 {0}% 的 context",
|
|
112
179
|
chipModel: "模型:{0}——選擇其他", chipEffort: "推理強度:{0}——選擇其他",
|
|
113
180
|
cmd_ctx: "context 用量、模型與推理強度", cmd_compact: "壓縮對話", cmd_clear: "清空對話(會先確認)",
|
|
114
181
|
cmd_model: "查看或切換模型", cmd_backend: "切換 CLI backend,再選模型和推理強度(會重新啟動)", cmd_effort: "查看或設定推理強度", cmd_cancel: "停止目前的回覆",
|
|
@@ -123,7 +190,8 @@ register("chat", {
|
|
|
123
190
|
a11yWorking: "{0} 開始工作", a11yIdle: "{0} 已完成", a11yReplied: "{0} 已回覆", conversationWith: "與 {0} 的對話",
|
|
124
191
|
stopping: "正在中止 {0}…", awaiting: "{0} 正在等你回應", approxNote: "從終端畫面判讀,僅供參考", elapsedTitle: "從這個頁面看到它開始工作起算(約略)",
|
|
125
192
|
dropHere: "放開即可附加檔案", asText: "改為文字", pasteAttached: "貼上的長文字({0} 個字元)已改為文字檔附加", pasteKeptAsText: "附件已滿,貼上的長文字保留為一般文字",
|
|
126
|
-
send: "送出", composerPlaceholder: "傳訊息給 {0}…", composerHint: "Enter 送出 · Shift+Enter 換行", composerMore: "/ 叫出指令 · Esc 中止回覆",
|
|
193
|
+
send: "送出", composerPlaceholder: "傳訊息給 {0}…", composerHint: "Enter 送出 · Shift+Enter 換行", composerMore: "/ 叫出指令 · Esc 中止回覆", guestMore: "Esc 中止回覆",
|
|
194
|
+
guestNote: "你是訪客:agent 會把你的訊息視為訪客的訊息(僅供辨識)。", guestNoCommands: "訪客不能執行指令,請去掉開頭的 / 再送出。", attachTitle: "附加檔案(任何類型,也可以貼上或拖曳)",
|
|
127
195
|
pvPreview: "預覽", pvStop: "停止", pvDownload: "下載", pvMenu: "預覽選項", pvHtml: "HTML",
|
|
128
196
|
pvAllowButton: "允許預覽", pvAllow: "允許預覽 HTML(預覽可能把資料傳出去)", pvDisallow: "不再允許預覽 HTML",
|
|
129
197
|
pvConfirm: "要允許預覽 HTML 嗎?\n\n這會套用到你登入的每一台裝置。預覽會在隔離的框架裡執行 agent 的 HTML。它無法使用你的登入,但可能把資料傳出去,也可能讓這個分頁變慢或卡住。每次仍需要你按「預覽」。",
|
|
@@ -168,6 +236,8 @@ register("chat", {
|
|
|
168
236
|
"pvFail_bad-address": "Cloudflare 給出的網址無法使用",
|
|
169
237
|
pvFail_unknown: "發生了未預期的錯誤",
|
|
170
238
|
pvServer_notOffered: "這個頁面不提供預覽。",
|
|
239
|
+
pvServer_listenFailed: "無法預覽:fleet 無法開啟預覽用的連接埠({0})。可能有其他程式正在使用它——請設定 web.preview_port,然後重新啟動 AgEnD。",
|
|
240
|
+
pvServer_notListening: "這個 fleet 目前無法預覽。",
|
|
171
241
|
previews: "允許預覽 HTML",
|
|
172
242
|
clicked: "點選了:", clickShow: "顯示這些按鈕所在的訊息",
|
|
173
243
|
copy: "複製", copyMessage: "複製這則回覆", copied: "已複製", copyFailed: "複製失敗", wrap: "換行", showAll: "展開全部 {0} 行", showMore: "顯示更多", showLess: "收合", jumpLatest: "最新", newBelow: "{0} 則新訊息",
|
|
@@ -189,10 +259,17 @@ register("chat", {
|
|
|
189
259
|
dEditInSettings: "到設定編輯", dPause: "暫停", dWake: "喚醒", dPaused: "{0} 已暫停", dWoken: "{0} 正在喚醒", dActionFailed: "沒有成功,請再試一次。",
|
|
190
260
|
dNoActivity: "最近一小時沒有活動。", dWorking: "處理中…",
|
|
191
261
|
themeLock: "鎖定主題", themeUnlock: "解除主題鎖定", themeReset: "重設主題…", themeResetGo: "重設",
|
|
262
|
+
pageColours: "頁面配色", pageAgentOn: "依 agent 的設定(開)", pageAgentOff: "依 agent 的設定(關)", pageWhole: "整個頁面", pageChatOnly: "只在它的聊天",
|
|
192
263
|
themeResetConfirm: "要把 {0} 的主題重設為預設嗎?顏色、圖片和處理中文字都會移除;鎖定會保留。",
|
|
193
264
|
themeResetDone: "已重設 {0} 的主題。", themeLocked: "已鎖定 {0} 的主題:agent 無法變更。", themeUnlocked: "已解除 {0} 的主題鎖定。",
|
|
194
265
|
themeFailed: "主題沒有變更({0})。",
|
|
195
266
|
widgetRemoveHeader: "移除聊天標頭的小工具", widgetRemoveDetails: "移除詳細資料頁的小工具", widgetRemoved: "已移除 {0} 的小工具。",
|
|
267
|
+
ambientBlocked_hidden: "環境效果未顯示:已關閉 agent 的主題——開啟",
|
|
268
|
+
ambientBlocked_safe: "環境效果未顯示:安全模式(?safe=1)——離開安全模式",
|
|
269
|
+
ambientBlocked_reducedMotion: "環境效果未顯示:這台裝置跟隨「減少動態效果」——仍然播放",
|
|
270
|
+
ambientBlocked_unsupported: "環境效果未顯示:此瀏覽器無法播放",
|
|
271
|
+
ambientClearLoop: "清除環境效果", ambientClearClick: "清除點擊效果", ambientCleared: "已清除 {0} 的環境效果。",
|
|
272
|
+
ambientMotionNote: "你的系統要求減少動態效果;效果目前開著。", ambientMotionNoteLink: "在這裡關閉", ambientMotionNoteClose: "關閉",
|
|
196
273
|
configured: "(設定值)", fleetDefault: "(fleet 預設)",
|
|
197
274
|
},
|
|
198
275
|
});
|