@songsid/agend 2.2.0-alpha.9 → 2.2.0-beta.10
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 +1 -1
- package/README.zh-TW.md +1 -1
- package/dist/agent-cli-instructions.md +16 -9
- package/dist/agent-cli.js +15 -7
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.js +21 -9
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-whats-new.d.ts +47 -0
- package/dist/agent-whats-new.js +147 -0
- package/dist/agent-whats-new.js.map +1 -0
- package/dist/auth-api.d.ts +2 -2
- package/dist/auth-api.js +4 -2
- package/dist/auth-api.js.map +1 -1
- package/dist/backend/antigravity.d.ts +3 -0
- package/dist/backend/antigravity.js +9 -0
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-carry.d.ts +22 -0
- package/dist/backend/claude-carry.js +170 -0
- package/dist/backend/claude-carry.js.map +1 -0
- package/dist/backend/claude-code.d.ts +65 -2
- package/dist/backend/claude-code.js +226 -33
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/codex-metadata.d.ts +33 -0
- package/dist/backend/codex-metadata.js +122 -18
- package/dist/backend/codex-metadata.js.map +1 -1
- package/dist/backend/codex.d.ts +3 -0
- package/dist/backend/codex.js +17 -1
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/credential-profile.d.ts +40 -3
- package/dist/backend/credential-profile.js +113 -5
- package/dist/backend/credential-profile.js.map +1 -1
- package/dist/backend/effort-metadata.d.ts +1 -1
- package/dist/backend/effort-metadata.js +3 -2
- package/dist/backend/effort-metadata.js.map +1 -1
- package/dist/backend/grok.d.ts +4 -0
- package/dist/backend/grok.js +14 -0
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro-engine-ledger.d.ts +5 -0
- package/dist/backend/kiro-engine-ledger.js +20 -0
- package/dist/backend/kiro-engine-ledger.js.map +1 -1
- package/dist/backend/kiro-identity.d.ts +6 -0
- package/dist/backend/kiro-identity.js +19 -5
- package/dist/backend/kiro-identity.js.map +1 -1
- package/dist/backend/kiro.d.ts +39 -3
- package/dist/backend/kiro.js +143 -19
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/launch-effort.d.ts +33 -0
- package/dist/backend/launch-effort.js +123 -0
- package/dist/backend/launch-effort.js.map +1 -0
- package/dist/backend/muse.d.ts +84 -0
- package/dist/backend/muse.js +449 -53
- package/dist/backend/muse.js.map +1 -1
- package/dist/backend/types.d.ts +33 -4
- package/dist/backend/types.js +2 -1
- package/dist/backend/types.js.map +1 -1
- package/dist/backend-command.d.ts +91 -0
- package/dist/backend-command.js +122 -0
- package/dist/backend-command.js.map +1 -0
- package/dist/background-work-ended.d.ts +18 -0
- package/dist/background-work-ended.js +30 -0
- package/dist/background-work-ended.js.map +1 -0
- package/dist/cache-service.d.ts +2 -0
- package/dist/cache-service.js +2 -1
- package/dist/cache-service.js.map +1 -1
- package/dist/channel/adapters/discord.d.ts +26 -1
- package/dist/channel/adapters/discord.js +98 -3
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +26 -2
- package/dist/channel/adapters/telegram.js +123 -19
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/mcp-server.js +9 -1
- package/dist/channel/mcp-server.js.map +1 -1
- package/dist/channel/mcp-tools.d.ts +11 -0
- package/dist/channel/mcp-tools.js +24 -13
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/message-edit-errors.d.ts +5 -0
- package/dist/channel/message-edit-errors.js +24 -0
- package/dist/channel/message-edit-errors.js.map +1 -0
- package/dist/channel/telegram-markdown.d.ts +6 -0
- package/dist/channel/telegram-markdown.js +104 -0
- package/dist/channel/telegram-markdown.js.map +1 -0
- package/dist/channel/tool-router.js +9 -3
- package/dist/channel/tool-router.js.map +1 -1
- package/dist/channel/types.d.ts +41 -3
- package/dist/cli.js +133 -28
- package/dist/cli.js.map +1 -1
- package/dist/command-table.d.ts +2 -2
- package/dist/command-table.js +6 -3
- package/dist/command-table.js.map +1 -1
- package/dist/config-validator.js +59 -0
- package/dist/config-validator.js.map +1 -1
- package/dist/cross-instance-envelope.d.ts +15 -2
- package/dist/cross-instance-envelope.js +29 -5
- package/dist/cross-instance-envelope.js.map +1 -1
- package/dist/daemon.d.ts +156 -1
- package/dist/daemon.js +764 -89
- package/dist/daemon.js.map +1 -1
- package/dist/delivery-outbox.d.ts +62 -7
- package/dist/delivery-outbox.js +309 -22
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/delivery-reconciliation.d.ts +18 -1
- package/dist/delivery-reconciliation.js +67 -2
- package/dist/delivery-reconciliation.js.map +1 -1
- package/dist/fleet-context.d.ts +10 -1
- package/dist/fleet-manager.d.ts +352 -10
- package/dist/fleet-manager.js +1925 -175
- package/dist/fleet-manager.js.map +1 -1
- package/dist/general-knowledge/skills/backend-providers/SKILL.md +1 -1
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +92 -21
- package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +27 -3
- package/dist/general-knowledge/skills/delegation-playbook/SKILL.md +8 -8
- package/dist/general-knowledge/skills/fleet-config/SKILL.md +5 -5
- package/dist/general-knowledge/skills/fleet-health/SKILL.md +4 -4
- package/dist/general-knowledge/skills/fleet-restart/SKILL.md +13 -13
- package/dist/general-knowledge/skills/instance-lifecycle/SKILL.md +3 -2
- package/dist/general-knowledge/skills/kiro-engine-migration/SKILL.md +6 -0
- package/dist/general-knowledge/skills/model-discovery/SKILL.md +9 -9
- package/dist/general-knowledge/skills/multi-channel/SKILL.md +8 -2
- package/dist/general-knowledge/skills/scheduling/SKILL.md +5 -3
- package/dist/general-knowledge/skills/session-management/SKILL.md +6 -5
- package/dist/general-knowledge/skills/tui-effort/SKILL.md +2 -2
- package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +8 -3
- package/dist/general-knowledge/steering/core-rules.md +8 -7
- package/dist/host-memory.d.ts +10 -0
- package/dist/host-memory.js +33 -1
- package/dist/host-memory.js.map +1 -1
- package/dist/human-delivery-receipts.d.ts +83 -0
- package/dist/human-delivery-receipts.js +194 -0
- package/dist/human-delivery-receipts.js.map +1 -0
- package/dist/instance-avatar.d.ts +36 -0
- package/dist/instance-avatar.js +57 -0
- package/dist/instance-avatar.js.map +1 -0
- package/dist/instance-config-impact.js +6 -0
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +29 -6
- package/dist/instance-lifecycle.js +79 -28
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instructions.d.ts +3 -1
- package/dist/instructions.js +11 -8
- package/dist/instructions.js.map +1 -1
- package/dist/kiro-log-gate.d.ts +42 -0
- package/dist/kiro-log-gate.js +39 -0
- package/dist/kiro-log-gate.js.map +1 -0
- package/dist/locale.js +204 -44
- package/dist/locale.js.map +1 -1
- package/dist/log-service.d.ts +99 -0
- package/dist/log-service.js +243 -0
- package/dist/log-service.js.map +1 -0
- package/dist/log-steps.d.ts +169 -0
- package/dist/log-steps.js +858 -0
- package/dist/log-steps.js.map +1 -0
- package/dist/login-controller.d.ts +20 -3
- package/dist/login-controller.js +71 -19
- package/dist/login-controller.js.map +1 -1
- package/dist/login-flows.d.ts +5 -2
- package/dist/login-flows.js +5 -4
- package/dist/login-flows.js.map +1 -1
- package/dist/memory-pressure.d.ts +13 -1
- package/dist/memory-pressure.js +50 -10
- package/dist/memory-pressure.js.map +1 -1
- package/dist/needs-you-hub.js +2 -0
- package/dist/needs-you-hub.js.map +1 -1
- package/dist/needs-you-live.d.ts +6 -0
- package/dist/needs-you-live.js +23 -3
- package/dist/needs-you-live.js.map +1 -1
- package/dist/next-steps.js +1 -1
- package/dist/next-steps.js.map +1 -1
- package/dist/outbound-handlers.d.ts +100 -0
- package/dist/outbound-handlers.js +263 -96
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +26 -15
- package/dist/outbound-schemas.js +24 -7
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/public-link-progress.d.ts +1 -1
- package/dist/public-link-progress.js +8 -2
- package/dist/public-link-progress.js.map +1 -1
- package/dist/public-preview.d.ts +101 -0
- package/dist/public-preview.js +236 -0
- package/dist/public-preview.js.map +1 -0
- package/dist/public-web-gateway.js +11 -4
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/public-web-link.d.ts +24 -1
- package/dist/public-web-link.js +63 -9
- package/dist/public-web-link.js.map +1 -1
- package/dist/reply-buttons-controller.d.ts +3 -0
- package/dist/reply-buttons-controller.js +3 -2
- package/dist/reply-buttons-controller.js.map +1 -1
- package/dist/restart-guard.d.ts +6 -3
- package/dist/restart-guard.js +6 -3
- package/dist/restart-guard.js.map +1 -1
- package/dist/restart-progress.d.ts +33 -0
- package/dist/restart-progress.js +30 -0
- package/dist/restart-progress.js.map +1 -1
- package/dist/service-activation.d.ts +15 -7
- package/dist/service-activation.js +46 -29
- package/dist/service-activation.js.map +1 -1
- package/dist/service-installer.d.ts +31 -0
- package/dist/service-installer.js +41 -2
- package/dist/service-installer.js.map +1 -1
- package/dist/settings-api.js +85 -25
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-change.js +72 -1
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-effect.js +28 -4
- package/dist/settings-effect.js.map +1 -1
- package/dist/settings-http-confirmation.js +7 -0
- package/dist/settings-http-confirmation.js.map +1 -1
- package/dist/setup-form.d.ts +1 -1
- package/dist/setup-form.js +1 -1
- package/dist/spawn-gate.js +5 -1
- package/dist/spawn-gate.js.map +1 -1
- package/dist/spawn-hold-reply.d.ts +12 -0
- package/dist/spawn-hold-reply.js +39 -0
- package/dist/spawn-hold-reply.js.map +1 -0
- package/dist/status-emojis.d.ts +10 -3
- package/dist/status-emojis.js +11 -2
- package/dist/status-emojis.js.map +1 -1
- package/dist/systemd-peer-bus.d.ts +95 -0
- package/dist/systemd-peer-bus.js +430 -0
- package/dist/systemd-peer-bus.js.map +1 -0
- package/dist/systemd-runtime.d.ts +27 -1
- package/dist/systemd-runtime.js +69 -7
- package/dist/systemd-runtime.js.map +1 -1
- package/dist/tips.js +4 -4
- package/dist/tips.js.map +1 -1
- package/dist/tool-progress.js +3 -2
- package/dist/tool-progress.js.map +1 -1
- package/dist/topic-commands.d.ts +42 -2
- package/dist/topic-commands.js +92 -7
- package/dist/topic-commands.js.map +1 -1
- package/dist/transcript-delta-reader.d.ts +3 -3
- package/dist/transcript-delta-reader.js +8 -8
- package/dist/transcript-delta-reader.js.map +1 -1
- package/dist/transcript-jsonl.d.ts +80 -3
- package/dist/transcript-jsonl.js +147 -10
- package/dist/transcript-jsonl.js.map +1 -1
- package/dist/transcript-monitor.d.ts +19 -0
- package/dist/transcript-monitor.js +87 -15
- package/dist/transcript-monitor.js.map +1 -1
- package/dist/transcript-sources.d.ts +78 -0
- package/dist/transcript-sources.js +375 -64
- package/dist/transcript-sources.js.map +1 -1
- package/dist/transcript-turns.d.ts +15 -2
- package/dist/transcript-turns.js +15 -2
- package/dist/transcript-turns.js.map +1 -1
- package/dist/tunnel/cloudflared.d.ts +7 -15
- package/dist/tunnel/cloudflared.js +36 -1
- package/dist/tunnel/cloudflared.js.map +1 -1
- package/dist/tunnel/purpose-lane.d.ts +5 -1
- package/dist/tunnel/purpose-lane.js +14 -7
- package/dist/tunnel/purpose-lane.js.map +1 -1
- package/dist/tunnel/types.d.ts +5 -1
- package/dist/tunnel/types.js.map +1 -1
- package/dist/turn-resume.d.ts +2 -0
- package/dist/turn-resume.js +1 -1
- package/dist/turn-resume.js.map +1 -1
- package/dist/types.d.ts +25 -0
- package/dist/ui/chat-commands.js +1 -0
- package/dist/ui/chat-emojis.js +33 -0
- package/dist/ui/chat-mentions.js +63 -0
- package/dist/ui/chat-render.js +42 -2
- package/dist/ui/chat-store.js +2 -2
- package/dist/ui/chat-strings.js +38 -20
- package/dist/ui/chat-thread.js +69 -12
- package/dist/ui/chat-time.js +80 -0
- package/dist/ui/panel-chat.js +39 -10
- package/dist/ui/panel-details.js +2 -0
- package/dist/ui/panel-fleet.js +199 -57
- package/dist/ui/panel-log.js +428 -0
- package/dist/ui/panel-needs.js +6 -2
- package/dist/ui/panel-settings.js +137 -32
- package/dist/ui/preview-panel.js +55 -15
- package/dist/ui/preview-status.js +28 -0
- package/dist/ui/preview.js +44 -3
- package/dist/ui/settings-dialogs.js +7 -2
- package/dist/ui/settings-model.js +2 -1
- package/dist/ui/settings-strings.js +46 -4
- package/dist/ui/settings-token.js +1 -1
- package/dist/ui/shared/app-i18n.js +43 -17
- package/dist/ui/shared/app-prefs.js +250 -0
- package/dist/ui/shared/app-route.js +7 -2
- package/dist/ui/shared/app-shell.js +165 -8
- package/dist/ui/shared/app-store.js +5 -1
- package/dist/ui/shared/app-stream.js +23 -5
- package/dist/ui/shared/app.css +159 -23
- package/dist/ui/shared/app.js +11 -1
- package/dist/ui/shared/fonts/README.md +1 -1
- package/dist/ui/shared/header-tools.js +55 -5
- package/dist/ui/shared/instance-nav.js +241 -45
- package/dist/ui/shared/instance-switch.js +4 -4
- package/dist/ui/shared/panel-view.js +6 -0
- package/dist/ui/shared/signin.js +7 -7
- package/dist/ui/shared/theme.js +39 -7
- package/dist/ui/shared/tokens.css +10 -1
- package/dist/ui/shared/ui-icons.js +1 -0
- package/dist/ui/shared/usage-dialog.js +23 -5
- package/dist/ui/shared/view-strings.js +32 -4
- package/dist/ui/signin.html +1 -1
- package/dist/unrecognised-prompt.d.ts +23 -0
- package/dist/unrecognised-prompt.js +74 -0
- package/dist/unrecognised-prompt.js.map +1 -0
- package/dist/update-install.d.ts +28 -2
- package/dist/update-install.js +22 -4
- package/dist/update-install.js.map +1 -1
- package/dist/update-marker.d.ts +51 -0
- package/dist/update-marker.js +61 -0
- package/dist/update-marker.js.map +1 -1
- package/dist/update-preflight.d.ts +100 -0
- package/dist/update-preflight.js +264 -0
- package/dist/update-preflight.js.map +1 -0
- package/dist/updater-caller.d.ts +31 -0
- package/dist/updater-caller.js +109 -0
- package/dist/updater-caller.js.map +1 -0
- package/dist/usage/i18n-keys.d.ts +1 -1
- package/dist/usage/i18n-keys.js +1 -1
- package/dist/usage/i18n-keys.js.map +1 -1
- package/dist/usage/providers.d.ts +34 -5
- package/dist/usage/providers.js +160 -27
- package/dist/usage/providers.js.map +1 -1
- package/dist/usage/statusline-usage.d.ts +6 -2
- package/dist/usage/statusline-usage.js +10 -4
- package/dist/usage/statusline-usage.js.map +1 -1
- package/dist/view-api.d.ts +1 -1
- package/dist/view-api.js +38 -8
- package/dist/view-api.js.map +1 -1
- package/dist/wake-coordinator.d.ts +11 -0
- package/dist/wake-coordinator.js +38 -4
- package/dist/wake-coordinator.js.map +1 -1
- package/dist/web-api.d.ts +49 -2
- package/dist/web-api.js +421 -31
- package/dist/web-api.js.map +1 -1
- package/dist/web-auth.d.ts +2 -2
- package/dist/web-auth.js +9 -4
- package/dist/web-auth.js.map +1 -1
- package/dist/web-commands.d.ts +27 -4
- package/dist/web-commands.js +19 -4
- package/dist/web-commands.js.map +1 -1
- package/dist/web-host-guard.d.ts +3 -11
- package/dist/web-host-guard.js +3 -12
- package/dist/web-host-guard.js.map +1 -1
- package/dist/web-images.d.ts +47 -0
- package/dist/web-images.js +169 -0
- package/dist/web-images.js.map +1 -0
- package/dist/web-mentions.d.ts +44 -0
- package/dist/web-mentions.js +75 -0
- package/dist/web-mentions.js.map +1 -0
- package/dist/web-prefs.d.ts +63 -0
- package/dist/web-prefs.js +265 -0
- package/dist/web-prefs.js.map +1 -0
- package/dist/web-preview.d.ts +14 -1
- package/dist/web-preview.js +35 -13
- package/dist/web-preview.js.map +1 -1
- package/dist/web-reply-files.d.ts +45 -0
- package/dist/web-reply-files.js +223 -0
- package/dist/web-reply-files.js.map +1 -0
- package/dist/web-schedules.d.ts +12 -0
- package/dist/web-schedules.js +34 -0
- package/dist/web-schedules.js.map +1 -0
- package/dist/web-server-drain.d.ts +10 -0
- package/dist/web-server-drain.js +50 -0
- package/dist/web-server-drain.js.map +1 -0
- package/dist/web-session.d.ts +36 -1
- package/dist/web-session.js +53 -6
- package/dist/web-session.js.map +1 -1
- package/dist/web-settings-patch.d.ts +23 -0
- package/dist/web-settings-patch.js +77 -0
- package/dist/web-settings-patch.js.map +1 -0
- package/dist/web-shell-routes.d.ts +5 -1
- package/dist/web-shell-routes.js +10 -1
- package/dist/web-shell-routes.js.map +1 -1
- package/dist/web-upload.d.ts +17 -4
- package/dist/web-upload.js +64 -13
- package/dist/web-upload.js.map +1 -1
- package/dist/workflow-templates/default.md +1 -1
- package/package.json +1 -1
- package/templates/launchd.plist.ejs +3 -1
- package/templates/systemd.service.ejs +2 -1
|
@@ -8,10 +8,12 @@ import { ConfirmHost } from "./ui-confirm.js";
|
|
|
8
8
|
import { t, lang, setLang, onLang } from "./app-i18n.js";
|
|
9
9
|
import { appStore, createStore, useStore } from "./app-store.js";
|
|
10
10
|
import { navStore } from "./app-nav.js";
|
|
11
|
-
import { chatPath, viewPath, settingsPath, routeKey, NEEDS_PATH, detailsPath } from "./app-route.js";
|
|
11
|
+
import { chatPath, viewPath, settingsPath, routeKey, NEEDS_PATH, detailsPath, fleetPath } from "./app-route.js";
|
|
12
12
|
import { SessionMenu } from "./app-session.js";
|
|
13
|
+
import { savePref } from "./app-prefs.js";
|
|
13
14
|
import { ErrorState, Skeleton } from "./ui-states.js";
|
|
14
|
-
import { InstanceNav, RosterNav } from "./instance-nav.js";
|
|
15
|
+
import { InstanceNav, RosterNav, namesStore, setNamesPrimary } from "./instance-nav.js";
|
|
16
|
+
import { UsageRail, usageRailStore } from "./header-tools.js";
|
|
15
17
|
|
|
16
18
|
/** Shell state shared with panels: the phone drawer, the collapsed sidebar, extensions a panel module adds. */
|
|
17
19
|
export const shellStore = createStore({ drawer: false, collapsed: readCollapsed(), keyboard: false, dialog: null, side: null });
|
|
@@ -41,6 +43,144 @@ export function closeDialog() { shellStore.set({ dialog: null }); }
|
|
|
41
43
|
function readCollapsed() { try { return localStorage.getItem("agend_sidebar") === "hidden"; } catch { return false; } }
|
|
42
44
|
const narrow = () => typeof matchMedia === "function" && matchMedia("(max-width: 899px)").matches;
|
|
43
45
|
|
|
46
|
+
// ── #1722: the sidebar's width — this device's (the #1665 split: a width depends on the screen), through the CSSOM ──
|
|
47
|
+
export const SIDEBAR_W = { min: 200, max: 480, def: 260, step: 16, mainMin: 480 };
|
|
48
|
+
const SIDEBAR_W_KEY = "agend_sidebar_w";
|
|
49
|
+
const win = () => (typeof window !== "undefined" ? window : null);
|
|
50
|
+
const viewportWidth = () => { const w = win(); return w && typeof w.innerWidth === "number" && w.innerWidth > 0 ? w.innerWidth : 1366; };
|
|
51
|
+
/** The width the sidebar may have on a viewport `vw` px wide: within [min, max], and leaving the main pane mainMin. */
|
|
52
|
+
export function clampSidebarWidth(w, vw) {
|
|
53
|
+
const max = Math.max(SIDEBAR_W.min, Math.min(SIDEBAR_W.max, vw - SIDEBAR_W.mainMin));
|
|
54
|
+
return Math.round(Math.min(max, Math.max(SIDEBAR_W.min, w)));
|
|
55
|
+
}
|
|
56
|
+
function storedSidebarWidth() { try { const v = Number(localStorage.getItem(SIDEBAR_W_KEY)); return Number.isFinite(v) && v > 0 ? v : null; } catch { return null; } }
|
|
57
|
+
/** { width: px | null } — null: the default width (tokens.css). */
|
|
58
|
+
export const sidebarWidthStore = createStore({ width: null });
|
|
59
|
+
/** Set the width (clamped to this viewport); `save`: this device keeps it. null: back to the default, nothing kept. */
|
|
60
|
+
/**
|
|
61
|
+
* The room the main pane has beside the sidebar: the window, less the usage rail when it is on screen (#1673 — shown
|
|
62
|
+
* open, ≥ 1200 px; its CSS width when the layout gives none). #1722 review: the sidebar never leaves main under 480.
|
|
63
|
+
*/
|
|
64
|
+
function mainBudget() {
|
|
65
|
+
const vw = viewportWidth();
|
|
66
|
+
if (vw < 1200 || typeof document === "undefined") return vw;
|
|
67
|
+
const rail = document.querySelector(".u-rail");
|
|
68
|
+
if (!rail) return vw;
|
|
69
|
+
const w = Math.round(rail.getBoundingClientRect ? rail.getBoundingClientRect().width : 0) || RAIL_W;
|
|
70
|
+
return vw - w;
|
|
71
|
+
}
|
|
72
|
+
const RAIL_W = 320;
|
|
73
|
+
/** Show a width (clamped to the room there is now) — this page only; null: the default width. Nothing is kept. */
|
|
74
|
+
function showSidebarWidth(w) {
|
|
75
|
+
const root = document.documentElement;
|
|
76
|
+
if (w == null) { root.style.removeProperty("--sidebar-w"); sidebarWidthStore.set({ width: null }); return null; }
|
|
77
|
+
const v = clampSidebarWidth(w, mainBudget());
|
|
78
|
+
root.style.setProperty("--sidebar-w", `${v}px`); // CSSOM: the page's CSP allows no style attribute
|
|
79
|
+
sidebarWidthStore.set({ width: v });
|
|
80
|
+
return v;
|
|
81
|
+
}
|
|
82
|
+
/** Set the width (clamped to the room there is now); `save`: this device keeps it. null: back to the default, nothing kept. */
|
|
83
|
+
export function setSidebarWidth(w, save = false) {
|
|
84
|
+
if (w == null) {
|
|
85
|
+
try { localStorage.removeItem(SIDEBAR_W_KEY); } catch { /* this page only */ }
|
|
86
|
+
return showSidebarWidth(null);
|
|
87
|
+
}
|
|
88
|
+
const v = showSidebarWidth(w);
|
|
89
|
+
// Kept: the choice within the window, not the squeeze beside the rail — it comes back when the rail goes.
|
|
90
|
+
if (save) { try { localStorage.setItem(SIDEBAR_W_KEY, String(clampSidebarWidth(w, viewportWidth()))); } catch { /* this page only */ } }
|
|
91
|
+
return v;
|
|
92
|
+
}
|
|
93
|
+
/** A drag in progress (one at a time): its end(commit). Only it may set the width until it ends. */
|
|
94
|
+
let activeDrag = null;
|
|
95
|
+
/**
|
|
96
|
+
* This device's kept width, shown within the room there is now — again whenever that changes (the window, the usage
|
|
97
|
+
* rail, the page). A squeeze is shown, never kept: the device's choice comes back when there is room. On a phone (the
|
|
98
|
+
* drawer) none applies, and a drag in progress is cancelled.
|
|
99
|
+
*/
|
|
100
|
+
function applyKeptSidebarWidth() {
|
|
101
|
+
if (narrow()) {
|
|
102
|
+
if (activeDrag) activeDrag.end(false);
|
|
103
|
+
showSidebarWidth(null);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (activeDrag) return;
|
|
107
|
+
const w = storedSidebarWidth();
|
|
108
|
+
if (w != null) showSidebarWidth(w);
|
|
109
|
+
}
|
|
110
|
+
const afterPaint = (fn) => (typeof requestAnimationFrame === "function" ? requestAnimationFrame(() => fn()) : setTimeout(fn, 0));
|
|
111
|
+
/** The separator on the sidebar's right edge: drag, ← → (16 px), Home / End, Enter or a double-click resets. */
|
|
112
|
+
function SidebarResize() {
|
|
113
|
+
const { width } = useStore(sidebarWidthStore);
|
|
114
|
+
useStore(usageRailStore); // the rail's room is the separator's limit too
|
|
115
|
+
useLayoutEffect(() => {
|
|
116
|
+
applyKeptSidebarWidth();
|
|
117
|
+
// The room changes with the window, the rail (opened, closed) and the page (a page with no rail): shown again,
|
|
118
|
+
// once the page has drawn its change.
|
|
119
|
+
const again = () => afterPaint(applyKeptSidebarWidth);
|
|
120
|
+
const offRail = usageRailStore.subscribe(again);
|
|
121
|
+
const offNav = navStore.subscribe(again);
|
|
122
|
+
const w = win();
|
|
123
|
+
if (w && typeof w.addEventListener === "function") w.addEventListener("resize", applyKeptSidebarWidth);
|
|
124
|
+
return () => {
|
|
125
|
+
offRail(); offNav();
|
|
126
|
+
if (w && typeof w.removeEventListener === "function") w.removeEventListener("resize", applyKeptSidebarWidth);
|
|
127
|
+
if (activeDrag) activeDrag.end(false); // unmounted mid-drag: nothing kept, nothing left behind
|
|
128
|
+
};
|
|
129
|
+
}, []);
|
|
130
|
+
const now = width ?? SIDEBAR_W.def;
|
|
131
|
+
const onKey = (e) => {
|
|
132
|
+
const cur = sidebarWidthStore.get().width ?? SIDEBAR_W.def;
|
|
133
|
+
if (e.key === "ArrowRight") setSidebarWidth(cur + SIDEBAR_W.step, true);
|
|
134
|
+
else if (e.key === "ArrowLeft") setSidebarWidth(cur - SIDEBAR_W.step, true);
|
|
135
|
+
else if (e.key === "Home") setSidebarWidth(SIDEBAR_W.min, true);
|
|
136
|
+
else if (e.key === "End") setSidebarWidth(SIDEBAR_W.max, true);
|
|
137
|
+
else if (e.key === "Enter") setSidebarWidth(null);
|
|
138
|
+
else return;
|
|
139
|
+
e.preventDefault();
|
|
140
|
+
};
|
|
141
|
+
// One pointer owns a drag. Only its release keeps the width; a cancel, a lost capture, the drawer or an unmount
|
|
142
|
+
// puts back the width shown before it and keeps nothing — and no event of it can write after it ended. What is kept
|
|
143
|
+
// is where the pointer went (within the window), not what the room beside the rail let it show.
|
|
144
|
+
const onDown = (e) => {
|
|
145
|
+
if (e.button !== 0 || activeDrag || narrow()) return;
|
|
146
|
+
e.preventDefault();
|
|
147
|
+
const handle = e.currentTarget, pointerId = e.pointerId;
|
|
148
|
+
const before = sidebarWidthStore.get().width;
|
|
149
|
+
let chosen = null; // the pointer's own width this drag; null: it never moved
|
|
150
|
+
const left = handle.parentElement ? handle.parentElement.getBoundingClientRect().left : 0;
|
|
151
|
+
const mine = {};
|
|
152
|
+
const own = (ev) => activeDrag === mine && (ev.pointerId === undefined || ev.pointerId === pointerId);
|
|
153
|
+
const move = (ev) => { if (own(ev)) { chosen = ev.clientX - left; showSidebarWidth(chosen); } };
|
|
154
|
+
const up = (ev) => { if (own(ev)) mine.end(true); };
|
|
155
|
+
const cancel = (ev) => { if (own(ev)) mine.end(false); };
|
|
156
|
+
mine.end = (commit) => {
|
|
157
|
+
if (activeDrag !== mine) return;
|
|
158
|
+
activeDrag = null;
|
|
159
|
+
handle.removeEventListener("pointermove", move);
|
|
160
|
+
handle.removeEventListener("pointerup", up);
|
|
161
|
+
handle.removeEventListener("pointercancel", cancel);
|
|
162
|
+
handle.removeEventListener("lostpointercapture", cancel);
|
|
163
|
+
handle.classList.remove("dragging");
|
|
164
|
+
document.body.classList.remove("side-resizing");
|
|
165
|
+
try { handle.releasePointerCapture(pointerId); } catch { /* not held */ }
|
|
166
|
+
if (commit && chosen != null) setSidebarWidth(chosen, true);
|
|
167
|
+
else showSidebarWidth(before);
|
|
168
|
+
};
|
|
169
|
+
activeDrag = mine;
|
|
170
|
+
try { handle.setPointerCapture(pointerId); } catch { /* the move still works while over the handle */ }
|
|
171
|
+
handle.classList.add("dragging");
|
|
172
|
+
document.body.classList.add("side-resizing");
|
|
173
|
+
handle.addEventListener("pointermove", move);
|
|
174
|
+
handle.addEventListener("pointerup", up);
|
|
175
|
+
handle.addEventListener("pointercancel", cancel);
|
|
176
|
+
handle.addEventListener("lostpointercapture", cancel);
|
|
177
|
+
};
|
|
178
|
+
return html`<div class="side-resize" role="separator" aria-orientation="vertical" tabindex="0" aria-controls="sidebar"
|
|
179
|
+
aria-label=${t("app.resizeSidebar")} title=${t("app.resizeSidebarHint")} aria-valuemin=${String(SIDEBAR_W.min)}
|
|
180
|
+
aria-valuemax=${String(clampSidebarWidth(Infinity, mainBudget()))} aria-valuenow=${String(now)}
|
|
181
|
+
onKeyDown=${onKey} onPointerDown=${onDown} ondblclick=${() => setSidebarWidth(null)}></div>`;
|
|
182
|
+
}
|
|
183
|
+
|
|
44
184
|
export function openDrawer() { shellStore.set({ drawer: true }); }
|
|
45
185
|
export function closeDrawer() { if (shellStore.get().drawer) shellStore.set({ drawer: false }); }
|
|
46
186
|
export function toggleSidebar() {
|
|
@@ -104,7 +244,8 @@ export function signInHref() {
|
|
|
104
244
|
function Sidebar({ route, onNewInstance, viewOnly }) {
|
|
105
245
|
const app = useStore(appStore);
|
|
106
246
|
const shell = useStore(shellStore);
|
|
107
|
-
|
|
247
|
+
// #1675: the Fleet panel is "Fleet overview"'s (one current row); the "Fleet" row is current on an instance's Details.
|
|
248
|
+
const on = (panel) => !!route && (panel === "fleet" ? route.panel === "details" : route.panel === panel);
|
|
108
249
|
const openInstance = openInstanceOf(route);
|
|
109
250
|
// A count badge is hidden at 0; its number is also in the link's accessible name.
|
|
110
251
|
const navLink = (panel, href, icon, label, count = 0) => html`<a class=${`side-row${on(panel) ? " active" : ""}`} href=${href}
|
|
@@ -124,8 +265,14 @@ function Sidebar({ route, onNewInstance, viewOnly }) {
|
|
|
124
265
|
<a class="side-row" href=${signInHref()}><${Icon} name="user" /><span>${t("app.signIn")}</span></a>
|
|
125
266
|
<${PrefsPopover} />
|
|
126
267
|
</div>
|
|
268
|
+
<${SidebarResize} />
|
|
127
269
|
</aside>`;
|
|
128
270
|
}
|
|
271
|
+
// #1675: the whole fleet, on its Org chart (#1389), from anywhere — top left, so at the top of a phone's drawer too. The
|
|
272
|
+
// "Fleet" row under it goes to the open instance's Details (#1523 N2); this one is the Fleet panel, any of its tabs.
|
|
273
|
+
const onFleet = !!route && route.panel === "fleet";
|
|
274
|
+
const overview = html`<a class=${`side-row side-overview${onFleet ? " active" : ""}`} href=${fleetPath("org")}
|
|
275
|
+
aria-current=${onFleet ? "page" : undefined} onClick=${closeDrawer}><${Icon} name="org" /><span class="grow">${t("app.fleetOverview")}</span></a>`;
|
|
129
276
|
return html`<aside id="sidebar" class="sidebar" aria-label=${t("app.menu")}>
|
|
130
277
|
<div class="side-head">
|
|
131
278
|
<a class="brand" href="/ui" onClick=${closeDrawer}>${t("app.brand")}</a>
|
|
@@ -133,6 +280,7 @@ function Sidebar({ route, onNewInstance, viewOnly }) {
|
|
|
133
280
|
<button type="button" class="icon-btn" onClick=${onNewInstance} aria-label=${t("app.newInstance")} title=${t("app.newInstance")}><${Icon} name="plus" /></button>
|
|
134
281
|
</div>
|
|
135
282
|
<nav class="side-nav" aria-label=${t("app.menu")}>
|
|
283
|
+
${overview}
|
|
136
284
|
${navLink("needs", NEEDS_PATH, "inbox", t("app.needsNav"), needsCount)}
|
|
137
285
|
${navLink("fleet", openInstance ? detailsPath(openInstance) : "/ui/fleet", "fleet", t("app.fleet"))}
|
|
138
286
|
${navLink("view", "/view", "view", t("app.view"))}
|
|
@@ -143,6 +291,7 @@ function Sidebar({ route, onNewInstance, viewOnly }) {
|
|
|
143
291
|
${navLink("settings", settingsPath(), "settings", t("app.settings"))}
|
|
144
292
|
<${SessionMenu} />
|
|
145
293
|
</div>
|
|
294
|
+
<${SidebarResize} />
|
|
146
295
|
</aside>`;
|
|
147
296
|
}
|
|
148
297
|
|
|
@@ -158,13 +307,20 @@ function ViewOnlyNav({ route }) {
|
|
|
158
307
|
export function DevicePrefs({ labels = false } = {}) {
|
|
159
308
|
const [theme, setTheme] = useState(typeof AgendTheme !== "undefined" ? AgendTheme.get() : "system");
|
|
160
309
|
const [l, setL] = useState(lang());
|
|
310
|
+
const names = useStore(namesStore); // #1722
|
|
311
|
+
// #1665: what is in force, as it changes — another device's choice arriving while this is open is shown at once.
|
|
312
|
+
useEffect(() => (typeof AgendTheme !== "undefined" && typeof AgendTheme.onChange === "function" ? AgendTheme.onChange(setTheme) : undefined), []);
|
|
313
|
+
useEffect(() => onLang(setL), []);
|
|
161
314
|
return html`<div class=${`prefs${labels ? " labelled" : ""}`}>
|
|
162
315
|
<label class="pref"><${Icon} name="sun" size=${16} /><span class=${labels ? "pref-label" : "sr-only"}>${t("app.theme")}</span>
|
|
163
|
-
<select value=${theme} aria-label=${t("app.theme")} onChange=${(e) => { setTheme(e.target.value); if (typeof AgendTheme !== "undefined") AgendTheme.set(e.target.value); }}>
|
|
316
|
+
<select value=${theme} aria-label=${t("app.theme")} onChange=${(e) => { setTheme(e.target.value); if (typeof AgendTheme !== "undefined") AgendTheme.set(e.target.value); savePref("theme", e.target.value); }}>
|
|
164
317
|
<option value="system">${t("app.themeSystem")}</option><option value="light">${t("app.themeLight")}</option><option value="dark">${t("app.themeDark")}</option></select></label>
|
|
165
318
|
<label class="pref"><${Icon} name="globe" size=${16} /><span class=${labels ? "pref-label" : "sr-only"}>${t("app.language")}</span>
|
|
166
|
-
<select value=${l} aria-label=${t("app.language")} onChange=${(e) => { setL(e.target.value); setLang(e.target.value); }}>
|
|
319
|
+
<select value=${l} aria-label=${t("app.language")} onChange=${(e) => { setL(e.target.value); setLang(e.target.value); savePref("lang", e.target.value); }}>
|
|
167
320
|
<option value="en">English</option><option value="zh-TW">中文</option></select></label>
|
|
321
|
+
<label class="pref"><${Icon} name="user" size=${16} /><span class=${labels ? "pref-label" : "sr-only"}>${t("app.names")}</span>
|
|
322
|
+
<select value=${names.primary} aria-label=${t("app.names")} onChange=${(e) => setNamesPrimary(e.target.value)}>
|
|
323
|
+
<option value="nickname">${t("app.namesNickname")}</option><option value="instance">${t("app.namesInstance")}</option></select></label>
|
|
168
324
|
</div>`;
|
|
169
325
|
}
|
|
170
326
|
|
|
@@ -192,11 +348,11 @@ export function PanelHeader({ title, sub, children, headingRef, nav }) {
|
|
|
192
348
|
}
|
|
193
349
|
|
|
194
350
|
/**
|
|
195
|
-
* #1523 N2: the instance a page is about — Chat, View or Details of it — or null. With one open, Fleet goes to its
|
|
351
|
+
* #1523 N2: the instance a page is about — Chat, View, Log (#1218) or Details of it — or null. With one open, Fleet goes to its
|
|
196
352
|
* Details (the user's complaint: Fleet always landed on Tasks), and Chat and View keep it; with none, as before.
|
|
197
353
|
*/
|
|
198
354
|
export function openInstanceOf(route) {
|
|
199
|
-
return route && (route.panel === "chat" || route.panel === "view" || route.panel === "details") && route.instance ? route.instance : null;
|
|
355
|
+
return route && (route.panel === "chat" || route.panel === "view" || route.panel === "log" || route.panel === "details") && route.instance ? route.instance : null;
|
|
200
356
|
}
|
|
201
357
|
|
|
202
358
|
function BottomTabs({ route, viewOnly }) {
|
|
@@ -210,7 +366,7 @@ function BottomTabs({ route, viewOnly }) {
|
|
|
210
366
|
<${Icon} name=${icon} size=${20} /><span>${label}</span>${badge ? html`<span class="tab-badge" aria-label=${badgeLabel || t("app.needsYou")}>${badge}</span>` : null}</a>`;
|
|
211
367
|
let lastView = null;
|
|
212
368
|
try { lastView = localStorage.getItem("agend_last_view"); } catch { /* none */ }
|
|
213
|
-
const viewHref = route && (route.panel === "view" || route.panel === "details") && route.instance ? viewPath(route.instance) : viewPath(lastView);
|
|
369
|
+
const viewHref = route && (route.panel === "view" || route.panel === "log" || route.panel === "details") && route.instance ? viewPath(route.instance) : viewPath(lastView);
|
|
214
370
|
if (viewOnly) {
|
|
215
371
|
return html`<nav class="tabs" aria-label=${t("app.menu")}>
|
|
216
372
|
${tab(viewHref, "view", t("app.view"), route && route.panel === "view")}
|
|
@@ -351,6 +507,7 @@ export function Shell({ panels, onNewInstance, viewOnly = false }) {
|
|
|
351
507
|
${viewOnly ? null : html`<${OperationLine} route=${nav.route} />`}
|
|
352
508
|
<${Outlet} route=${nav.route} seq=${nav.seq} panels=${panels} />
|
|
353
509
|
</main>
|
|
510
|
+
<${UsageRail} route=${nav.route} />
|
|
354
511
|
<${BottomTabs} route=${nav.route} viewOnly=${viewOnly} />
|
|
355
512
|
${shell.dialog ? html`<${shell.dialog.Component} ...${shell.dialog.props} onClose=${closeDialog} />` : null}
|
|
356
513
|
${viewOnly || (nav.route && nav.route.panel === "settings") ? null : html`<${PendingChanges} />`}
|
|
@@ -36,7 +36,11 @@ export function applyStatus(d) {
|
|
|
36
36
|
if (i.state === "awaiting_input") awaiting[i.name] = typeof i.interaction_summary === "string" ? i.interaction_summary : "";
|
|
37
37
|
}
|
|
38
38
|
appStore.set({ ready: true, instances: d.instances, uptime: d.uptime ?? 0, exec, awaiting,
|
|
39
|
-
connections: typeof d.connections === "number" ? d.connections : null
|
|
39
|
+
connections: typeof d.connections === "number" ? d.connections : null,
|
|
40
|
+
// #1665: the host preferences' revision (app-prefs.js re-reads them when it moves).
|
|
41
|
+
prefsRev: typeof d.prefs_rev === "number" ? d.prefs_rev : null,
|
|
42
|
+
// #1685: host memory pressure slowing or holding new agents ("elevated" | "critical"), else null.
|
|
43
|
+
hostMemory: d.host_memory === "elevated" || d.host_memory === "critical" ? d.host_memory : null });
|
|
40
44
|
}
|
|
41
45
|
|
|
42
46
|
/** One "activity" event: an instance started or stopped working. */
|
|
@@ -29,14 +29,15 @@
|
|
|
29
29
|
// - a 401 is the session ending: nothing is retried (agend-auth.js says so).
|
|
30
30
|
// - suspend()/resume(): the page is leaving (pagehide) / came back from the back-forward cache.
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
// #1218: steps_tick — an instance's transcript moved while a Log watches it (SSE only: a poll page asks the Log itself).
|
|
33
|
+
const EVENTS = ["status", "message", "delivery", "deliveries", "prompt", "prompts", "prompt_resolved", "activity", "needs", "reply_buttons", "steps_tick"];
|
|
33
34
|
const MAX_HELD = 1000; // live events held during one catch-up read; more → read again afterwards
|
|
34
35
|
const RETRY_DELAYS = [1000, 2000, 4000]; // after the first failed catch-up read; then it waits for Retry
|
|
35
36
|
const POLL_LIMIT_MS = 10000; // a poll that has not answered by then counts as failed
|
|
36
37
|
const MAX_OVERFLOW_READS = 3; // reads again after dropped live events, within one catch-up
|
|
37
38
|
// #1580: the reconnect backoff — step n waits min(cap, base·2ⁿ), drawn from 50–100 % of that (jitter: tabs that lost
|
|
38
39
|
// the fleet together do not come back together).
|
|
39
|
-
export const RECONNECT = { baseMs: 1000, capMs: 30000 };
|
|
40
|
+
export const RECONNECT = { baseMs: 1000, capMs: 30000, shutdownMs: 10000 };
|
|
40
41
|
export function reconnectDelay(step, random = Math.random) {
|
|
41
42
|
const full = Math.min(RECONNECT.capMs, RECONNECT.baseMs * 2 ** Math.min(step, 20));
|
|
42
43
|
return Math.round(full * (0.5 + random() * 0.5));
|
|
@@ -49,6 +50,7 @@ export function createStream(opts) {
|
|
|
49
50
|
let sse = null, pollTimer = null, silentTimer = null, closed = false, started = false;
|
|
50
51
|
// #1580: the reconnect step waiting, how many failed in a row, a step waiting for the tab to be shown, a page that left.
|
|
51
52
|
let reconnectTimer = null, attempts = 0, waitingVisible = false, suspended = false, ended = false, retryAt = 0;
|
|
53
|
+
let shutdownUntil = 0; // monotonic; retained through pagehide/pageshow
|
|
52
54
|
const random = typeof env.random === "function" ? env.random : Math.random;
|
|
53
55
|
const doc = env.document || null;
|
|
54
56
|
const hidden = () => !!(doc && doc.hidden);
|
|
@@ -188,6 +190,18 @@ export function createStream(opts) {
|
|
|
188
190
|
const es = sse = new env.EventSource("/ui/events");
|
|
189
191
|
let spoke = false;
|
|
190
192
|
silentTimer = env.setTimeout(startPolling, 15000); // the server sends a status frame the moment a stream opens
|
|
193
|
+
es.addEventListener("shutdown", (e) => {
|
|
194
|
+
if (es !== sse || closed || suspended || ended) return;
|
|
195
|
+
let data;
|
|
196
|
+
try { data = JSON.parse(e.data); } catch { return; }
|
|
197
|
+
if (data?.retry_ms !== RECONNECT.shutdownMs) return;
|
|
198
|
+
shutdownUntil = now() + RECONNECT.shutdownMs + Math.round(random() * 5000);
|
|
199
|
+
cancelWork(); closeStream(); stopPolling();
|
|
200
|
+
env.clearTimeout(reconnectTimer); reconnectTimer = null; waitingVisible = false;
|
|
201
|
+
attempts = Math.max(attempts, 4);
|
|
202
|
+
setConnection("reconnecting");
|
|
203
|
+
scheduleStep(shutdownUntil - now());
|
|
204
|
+
});
|
|
191
205
|
for (const name of EVENTS) {
|
|
192
206
|
es.addEventListener(name, (e) => {
|
|
193
207
|
if (es !== sse) return; // a stream this page already let go of
|
|
@@ -216,15 +230,16 @@ export function createStream(opts) {
|
|
|
216
230
|
else setConnection("reconnecting");
|
|
217
231
|
scheduleStep();
|
|
218
232
|
}
|
|
219
|
-
function scheduleStep() {
|
|
233
|
+
function scheduleStep(delay) {
|
|
220
234
|
if (reconnectTimer || closed || suspended || ended) return;
|
|
221
|
-
const ms = reconnectDelay(attempts++, random);
|
|
235
|
+
const ms = Math.max(delay ?? reconnectDelay(attempts++, random), shutdownUntil - now());
|
|
222
236
|
retryAt = now() + ms;
|
|
223
237
|
emit("retry", { inMs: ms });
|
|
224
238
|
reconnectTimer = env.setTimeout(() => { reconnectTimer = null; step(); }, ms);
|
|
225
239
|
}
|
|
226
240
|
function step() {
|
|
227
241
|
if (closed || suspended || ended) return;
|
|
242
|
+
if (shutdownUntil > now()) { scheduleStep(shutdownUntil - now()); return; }
|
|
228
243
|
if (hidden()) { waitingVisible = true; return; } // not while nobody looks: the next step waits to be shown
|
|
229
244
|
if (opts.transport === "poll") { pollProbe(); return; }
|
|
230
245
|
openStream(true);
|
|
@@ -255,7 +270,7 @@ export function createStream(opts) {
|
|
|
255
270
|
* It opens no transport: still the one EventSource, and no polling loop.
|
|
256
271
|
*/
|
|
257
272
|
function catchUp() {
|
|
258
|
-
if (closed || ended) return Promise.resolve(false);
|
|
273
|
+
if (closed || ended || shutdownUntil > now()) return Promise.resolve(false);
|
|
259
274
|
if (catching) return catching;
|
|
260
275
|
env.clearTimeout(retryTimer); retryTimer = null;
|
|
261
276
|
setHydration("catching");
|
|
@@ -327,6 +342,9 @@ export function createStream(opts) {
|
|
|
327
342
|
if (closed || !suspended || ended) return;
|
|
328
343
|
suspended = false;
|
|
329
344
|
epoch++;
|
|
345
|
+
if (shutdownUntil > now()) {
|
|
346
|
+
setConnection("reconnecting"); scheduleStep(shutdownUntil - now()); return;
|
|
347
|
+
}
|
|
330
348
|
attempts = 0;
|
|
331
349
|
if (opts.transport === "poll") { startPolling(); return; }
|
|
332
350
|
openStream(true);
|