Add a self-deployment guide for the new `wechatcom_kf` channel under
`docs/channels/wecom-kf.mdx` in zh / en / ja, mirroring the existing
`wecom.mdx` structure. Wire each language version into the sidebar in
`docs/docs.json`.
Walks through: creating the WeCom custom app, retrieving Corp ID /
Secret (push-to-phone) / Token / EncodingAESKey, configuring `config.json`,
saving the callback URL + Enterprise Trusted IPs, binding the WeCom
Customer Service account, and distributing the access link / QR code.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Clarify Secret retrieval (must tap "查看" on admin's phone, not copy)
- Update WeCom customer-service binding section to point to the
"接入链接" UI (copy link / generate QR code)
- Drop developer-only asides (wechatcomapp_secret / port collision
notes, internal sections about cursor persistence, channel runtime
differences, multi-kf-account support)
- Stop exposing `wechatcom_kf_cursor_dir` as a user config; cursor file
is now fixed under `tmp/`, which is an internal implementation detail.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Switch from the local `WechatComAppClient` (whose `fetch_access_token`
may return the raw response dict and whose background refresh loop
re-fetches every 60s) to the stock `wechatpy.enterprise.WeChatClient`.
- Use `client.access_token` (string property) when building sync_msg /
send_msg URLs; the previous `client.fetch_access_token()` call could
interpolate a dict into the URL and yield errcode 40014.
- Always skip historical messages on first start; drop the
`wechatcom_kf_skip_history_on_first_start` config — there is no real
case for replaying up to 14 days of history.
- Change default callback port from 9899 to 9888.
Co-authored-by: Cursor <cursoragent@cursor.com>
Introduce a new channel that integrates with WeCom Customer Service
(微信客服), separate from the existing self-built WeCom app channel.
- Register channel type `wechatcom_kf` in factory, app loader and const
- Add config keys for token / secret / aes_key / port / cursor dir and
the first-start history-skip switch; also expose corresponding env vars
- Implement channel, message and cursor store under channel/wechatcom_kf/
Co-authored-by: Cursor <cursoragent@cursor.com>
Search tool now supports 4 backends with unified output (bocha,
qianfan, zhipu, linkai) and a routing layer:
- strategy 'auto' (default): pick first configured in canonical order
bocha > qianfan > zhipu > linkai
- strategy 'fixed': pin a specific provider
- agent may pass `provider` to override per-call (only exposed when
≥2 providers configured + auto strategy)
- Clear NOT_SUPPORT_REPLYTYPE on weixin, wecom_bot, dingtalk so TTS replies
are actually synthesized for these channels.
- Wire desire_rtype=VOICE in weixin and wecom_bot _compose_context so the
always_reply_voice / voice_reply_voice toggles take effect.
- DingTalk: send native sampleAudio (mediaId + duration). The media API
only accepts ogg/amr, so convert TTS mp3/wav to amr on the fly.
- WeCom Bot: send native voice msgtype via ws (respond + active push),
converting TTS audio to amr before upload.
- Weixin (ilink): no outbound voice item, deliver TTS as a file attachment.
- chat_channel: when a TEXT reply is converted to VOICE, stash original
text in context["voice_reply_text"] and send a text bubble before the
voice reply. Skipped for feishu_streamed and wechatcom_app, which
already render text alongside the voice.
Add embedding_provider config knob with native support for
openai / dashscope / doubao / zhipu / linkai, plus an in-chat
/memory status and /memory rebuild-index workflow for switching
vendors safely.
When reloading a conversation, failed tool calls incorrectly showed checkmark instead of X because the is_error field was lost in the history rendering pipeline. Propagate is_error from DB extraction through to the frontend rendering to match the live SSE behavior.
Browser sessions now reuse a Chromium user profile across runs by default
(`~/.cow/browser_profile`), so users only log in to a site once.
Three launch modes are selectable via `tools.browser` in config.json:
- persistent (default): Playwright Chromium with a persistent user_data_dir
- cdp: attach to an externally launched real Chrome via `cdp_endpoint`
(full fingerprints, ideal for sites with strict bot detection)
- fresh: clean context every run, set `persistent: false`
Also:
- Self-heal when the user closes the browser window mid-session: detect
closed page/context/browser via close listeners and exception scanning,
then transparently relaunch on the next request.
- Graceful CDP shutdown: disconnect only, never kill the user's Chrome.
- Friendly errors when the CDP endpoint is unreachable or the persistent
profile is locked, so the LLM can guide the user instead of looping.
- Fix tool config being silently overwritten by workspace config in
AgentInitializer; per-tool user settings (e.g. browser.cdp_endpoint)
are now merged instead of replaced.
- Update zh / en / ja docs with the new login-persistence section,
including the Chrome 137+ requirement to pair --remote-debugging-port
with a dedicated --user-data-dir.