Large raw_output snapshots from tool_call_update notifications caused
O(N²) traffic through the event pipeline, multi-GB transient allocations
and WKWebView crashes. The fix turns cumulative snapshots into bounded
incremental deltas and removes redundant payload copies.
- Add ToolCallOutputCache keyed by tool_call_id with a 8KB tail
fingerprint and total length. Detects cumulative extensions by
matching the cached tail at the expected offset in the incoming
snapshot, so it works even when the full output grows into the MB
range. Emits suffix deltas with raw_output_append=true; falls back
to a truncated replacement when content diverges.
- Cap any single emitted raw_output chunk at 64KB (MAX_SINGLE_EMIT_BYTES)
with a UTF-8 char-boundary-safe tail and ANSI-sequence-safe trimming.
Apply the same cap to emit_terminal_output_update.
- Bound the cache at 256 entries with FIFO eviction, and clear entries
when the tool call reaches completed / failed / cancelled / error.
- Seed the cache via a dedicated seed() method on SessionUpdate::ToolCall
so the initial event never emits an accidental append.
- Share emit payloads as Arc<serde_json::Value> across broadcast
receivers and skip the Tauri-side clone: serialize once and hand the
same Arc to both the webview emit and the WebSocket broadcaster.
- Add 14 unit tests covering boundary cases: identity, prefix extension
past the cached tail, divergence, oversized deltas, multibyte UTF-8
truncation, final-status cleanup, FIFO eviction, seed semantics, and
ANSI-safe trimming.
- Replace hardcoded "Claude Code" in agent_responding with each session's actual AgentType label; store agent_type on ActiveSession and populate it in both task-start and resume paths
- Remove silent ClaudeCode fallback in resolve_agent_type; /task now prompts the user to pick an agent when none is selected and the folder has no default
- Move session command strings out of session_commands.rs into i18n.rs with full 10-language coverage (en/zh-CN/zh-TW/ja/ko/es/de/fr/pt/ar)
- Fix French accent and wrap Latin agent name with Arabic bidi isolates (FSI/PDI) for consistent rendering across Telegram/Lark/WeiXin clients
- Release the bridge lock before the get_lang DB lookup in the content_delta flush path to avoid cross-session contention
- Log unknown agent_type fallback in conversation_service::parse_agent_type for observability
- Generate QR code server-side when iLink API returns SPA page URL
(added qrcode + image crates for PNG generation)
- Strip bot_token from frontend response (new WeixinQrcodeStatusPublic type)
- Add request timeouts and shared HTTP client for QR code endpoints
- Fix TOCTOU race on reply_context double-lock (single lock scope)
- Extract do_send() helper to deduplicate sendmessage logic; resend now
checks ret field for context expiry instead of HTTP status only
- Cap pending_messages buffer at 50 to prevent unbounded memory growth
- Generate stable X-WECHAT-UIN per backend instance instead of per request
- Extract ILINK_CHANNEL_VERSION constant (was hardcoded in 4 places)
- Add 5-minute client-side QR expiry timeout in frontend dialog
- Track consecutive polling errors and show warning after 3 failures
- Stabilise onAuthSuccess/onClose callback refs to prevent polling restarts
- Replace dead i18n key weixinOpenQrcode with weixinPollError
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Filter messages by message_type=1 to skip bot echo and prevent loops
- Add voice message support (type=3) with voice-to-text extraction
- Check resend results and re-buffer failed messages to prevent loss
- Handle session expiry (ret=-14) with 30s pause in polling loop
- Use exponential backoff (5s–30s) for network errors instead of fixed 5s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Display specific file paths, commands, and patterns in tool call messages
instead of generic titles (e.g. ">> Read: src/main.rs")
- Show tool call details only on completion to ensure raw_input availability
- Enrich permission request messages with tool details from rawInput
- Localize stop_reason in turn_complete messages for all 10 languages
- Fix UTF-8 byte-slice panic in format_completion for multi-byte content
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>