The weknora HTTP client used a hardcoded 120s total-duration timeout, which
kills any smart-reasoning agent stream that legitimately runs longer (22 tool
rounds measured in prod) and the failure branch then overwrote the already
streamed card with the error text. Pass 0 and keep Go's default (no timeout).
The DingTalk binding can point at the quick-answer agent, which publishes the
whole answer as one answer run plus tool_call/tool_result steps. The narration
boundary was rejected for that shape (start=0), so the text-only heuristic ran
and dropped the answer lead-in together with its image.
- answer_observation: a single answer run means there is no narration to cut.
- outboundtext: rewrite LaTeX formulas into plain Unicode text, because
DingTalk cards render no math typesetting (r = sqrt(X^2 + Y^2) -> r = √(X² + Y²)).
- dingtalk handler: normalize formulas on both the partial and final card paths.
DINGTALK_CARD_WIDE_TABLE_GROUP=off keeps over-wide answer tables as tables on the final frame (still replaces <br> inside cells) so the PC wide-screen card can lay them out itself.
- outboundimage: re-encode large PNG/JPEG screenshots as downscaled JPEG (1600px long edge, q82, transparency flattened onto white) before upload; undecodable, small, GIF/WebP payloads are published untouched
- outboundimage: StableHashPublisher skips the upload when the content-addressed object already exists (ObjectStater); OSS store implements it via IsObjectExist
- cmd/dobotai: DOBOTAI_OUTBOUND_IMAGE_REWRITE_TIMEOUT default 60s -> 180s; DOBOTAI_OUTBOUND_IMAGE_COMPRESS (on by default, off restores raw bytes)
- outboundimage: fetch and publish up to 4 images in parallel, dedupe in document order, log per-image outcome plus a rewrite summary
- dingtalk handler: OutboundRewriteTimeout applies to the image rewrite stage only, falling back to finalDeliveryTimeout
- cmd/dobotai: DOBOTAI_OUTBOUND_IMAGE_REWRITE_TIMEOUT (default 60s, invalid values fall back)
AI card bodies render only DingTalk-hosted media, so published image URLs are
rewritten into media ids inside card content (streaming frames never block,
final frame waits briefly), while the markdown fallback keeps external URLs.