The Peak Error Hours widget displayed identical error rates for all hours
because the legacy algorithm distributed errors proportionally across
session time spans. This produced misleading data (e.g., every hour
showing 9.89%) instead of highlighting actual error-heavy periods.
Changes:
- Add SessionHourlyMessageCounts type with quarterIndex field (0-95)
representing UTC-based 15-minute buckets for timezone-accurate
hour conversion — covers all global UTC offsets (±15/30/45 min)
- Collect per-quarter-hour message/error counts in loadSessionCostSummary
using getUTCHours()/getUTCMinutes() with UTC day keys (formatUtcDayKey)
- Prefer precise quarterly data in buildPeakErrorHours for both local
and UTC views, falling back to proportional allocation for sessions
without quarterly data
- Fix DST bug: replace single getTimezoneOffset() with
new Date(Date.UTC(...)).getHours() for DST-aware local hour mapping
- Extract accumulateMessageCounts helper to deduplicate daily/hourly
message count aggregation logic
- Guard hourlyMessageCounts with .length check before including in
summary (consistent with dailyLatency/dailyModelUsage pattern)
Fix Telegram portrait video distortion by probing video dimensions through the shared media helper and passing width/height to sendVideo.
Validation:
- Targeted Telegram/media tests passed locally.
- Plugin SDK API baseline check passed locally.
- Formatter and git diff whitespace checks passed locally.
CI note: current boundary drift observed on prior run came from existing src/plugin-sdk/discord.ts and src/plugin-sdk/telegram-account.ts, not this PR diff.
Fixes#73621.
Preserve queued Control UI chat messages across in-UI session switches by saving the active queue per session before reset and restoring it when switching back. Route the overview session selector through the shared switchChatSession helper so it follows the same queue lifecycle.
Validation:
- OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test ui/src/ui/app-render.helpers.node.test.ts
- pnpm tsgo:test:ui
- pnpm exec oxfmt --check --threads=1 ui/src/ui/app-render.helpers.node.test.ts ui/src/ui/app-render.helpers.ts ui/src/ui/app-render.ts ui/src/ui/app-view-state.ts ui/src/ui/app.ts
Fix startup and per-turn provider registry hot paths by keeping primary-model startup discovery on metadata-only provider entries and by keeping capability provider fallback loads scoped to manifest-derived owners, including explicit empty scopes when no bundled owner exists.
Evidence:
- Reproduces the reported code paths from #73729, #73835, and #73793: startup prewarm was able to enter provider/model discovery that loaded plugin runtime, and capability lookups could bypass active registry reuse or broaden fallback registry loads.
- Fix threads providerDiscoveryEntriesOnly through models-config planning into plugin discovery.
- Fix reuses active non-memory/non-speech capability providers even with explicit plugins.entries.
- Fix keeps fallback registry loads scoped with onlyPluginIds, including [] for no-owner media capability checks.
- Local targeted tests passed for gateway startup, models config, provider discovery, capability providers, and web provider runtimes.
- Testbox pnpm check:changed passed.
- Testbox pnpm build passed.
- GitHub CI required checks passed on e5e6fe1d52.
Fixes#73729.
Fixes#73835.
Fixes#73793.
Supersedes #73794.