feat: Discord id cache, resolve fallback, and instant tab-switch#150
Conversation
- Use gh CLI to get release body (avoids shell escaping issues) - Use jq for proper JSON construction - Skip .sig and latest.json files - Use HTTP/1.1 for large file upload stability
- Detect user timezone to determine if likely in China - CN users fetch release assets from GitLab (lay2dev/clawpal) - Other users fetch from GitHub as before - Falls back to secondary source if primary fails
feat(site): geo-aware download links
- Add canonical, Open Graph, Twitter Card meta tags - Add SoftwareApplication JSON-LD schema - Add robots.txt with AI crawler permissions - Add llms.txt for AI search engines - Add sitemap.xml - Improve meta description for better CTR
feat(seo): add SEO/GEO optimization for AI search visibility
Co-authored-by: dev01lay2 <dev01lay2@users.noreply.github.com>
list_recipes, manage_rescue_bot, get_rescue_bot_status, diagnose_primary_via_rescue, and repair_primary_via_rescue were defined in both mod.rs and their split-out files (recipe_cmds.rs, rescue.rs), causing E0428 duplicate definition errors during full compilation.
- Agents and model profiles now initialize from localStorage persisted cache on mount, showing data immediately without waiting for a fetch - Increase listAgents cache TTL from 6s/12s to 30s/60s to reduce redundant fetches during page navigation - Combined with the existing RuntimeSnapshot → listAgents cache seeding, this means Cook/Recipes dropdowns populate instantly in most scenarios
- Guild names show spinner when name equals ID and full data pending - Channel names show mono ID + spinner when unresolved, normal text once resolved - Agent dropdown initializes from persisted cache for instant population - Uses discordChannelsResolved from InstanceContext (set by App.tsx fast/full loading)
- Call refreshDiscordChannelsCacheFast() on ALL routes (channels/cook/recipes), not just cook/recipes — channels page needs the fast skeleton too - Fix stale persisted cache blocking fast data: only keep prev data if it has actually resolved names (channelName !== channelId), not just non-empty
…switch - Integrate DiscordIdCache into both remote and local slow paths to persist guild/channel id→name mappings across page reloads (discord-id-cache.json) - Fall back to one-by-one channel resolution when batch openclaw channels resolve fails (e.g. single 404 channel blocking all others) - Preserve previously-resolved channel names via channel_name_fallback_map when CLI resolution fails, preventing overwrite with raw IDs - Fix tab-switch showing wrong VPS channels by resolving remote persistenceScope synchronously during render (setState-during-render pattern) instead of in useEffect, eliminating the one-render lag - Change useChannelCache initialization from useEffect to useLayoutEffect so state maps are populated before browser paint - Add unit tests for DiscordIdCache, parse_resolve_name_map, channel name fallback, loadInitialSharedChannels, and tab-switch cache behavior Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
A rate-limited response proves the API key is valid and the endpoint is reachable — failing the test on 429 causes flaky CI when free-tier quotas are exhausted. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
dev01lay2
left a comment
There was a problem hiding this comment.
First review — PR #150
Status
- Merge conflicts — PR is in CONFLICTING state, needs rebase onto main
- CI — Only
mirrorran (fork PR limitation). Cannot verify build/test/lint status.
Architecture
Large but well-structured refactor: Discord channel caching with TTL gates, DiscordIdCache for id→name persistence, streaming session analysis via Tauri events, and hook extraction from monolithic components. The layered cache strategy (fast path → TTL gate → full refresh) is sound.
🔴 Blocking
BS 1: Merge conflicts must be resolved before meaningful CI can run.
BS 2: console.log debug statements left in production code
useChannelCache.ts has multiple console.log calls ([useChannelCache] slow path raw channels:, [useChannelCache] fast path raw channels:, etc.) that should be removed or gated behind a dev flag before merge.
BS 3: discovery.rs guild-level placeholder may cause UI confusion
When a guild has no explicit channel list, a placeholder entry is emitted with channel_id == guild_id. Downstream code that filters or routes by channel_id will treat this as a real channel. Consider using a sentinel value or a separate field to mark it as a placeholder.
🟡 Non-blocking suggestions
NBS 1: useChannelCache.ts — ref sync pattern
The channelNodesByInstanceRef is synced via an unguarded useEffect (no deps array). This works but is unconventional — a direct assignment (channelNodesByInstanceRef.current = channelNodesByInstance outside useEffect, like the version in PR #118's fix) is more idiomatic and avoids a render-phase delay.
NBS 2: sessions.rs code duplication
analyze_sessions_sync duplicates the classification/sorting logic that clawpal_core::sessions::classify_session and sort_sessions already provide. Consider reusing the core functions to reduce drift risk.
NBS 3: parse_json_output forward-scanning approach
The new forward-scanning JSON extractor is more robust than the old reverse-scan, good improvement. Minor: the loop will spin on pathological input with many unbalanced brackets — consider adding a max-iterations guard.
NBS 4: DISCORD_CACHE_TTL_SECS = 7 days is aggressive
Channel names rarely change, but guild restructuring (new channels, renamed channels) would be invisible for a week. Consider making this configurable or reducing to 24h.
NBS 5: shell_escape usage in remote session preview
stream_remote_session_preview builds awk commands with shell_escape — ensure this handles session IDs with special characters robustly (e.g. UUIDs are fine, but user-created session names might not be).
Summary
DiscordIdCacheinto both remote and local slow paths to persist guild/channel id→name mappings across page reloads (discord-id-cache.json)openclaw channels resolvefails (e.g. single 404 channel blocking all others)channel_name_fallback_mapwhen CLI resolution fails, preventing overwrite with raw IDspersistenceScopesynchronously during render instead of inuseEffectuseChannelCacheinitialization fromuseEffecttouseLayoutEffectfor zero-flash tab switchingTest plan
DiscordIdCacheTTL behavior, JSON roundtripparse_resolve_name_mapedge casesloadInitialSharedChannelstab-switch cache behavior🤖 Generated with Claude Code