Changelog
This project follows the Keep a Changelog format.
[Unreleased]
Added
- Added a multilingual documentation site generated from the repository Markdown and published with GitHub Pages: VitePress provides English and Chinese navigation, local search, dark mode, and a mobile layout, every page is served as HTML and as raw Markdown, and
llms.txtplusllms-full.txtlet language models index the latest documentation.
Fixed
- Inbound getUpdates duplicate delivery: ordinary and approval admission lanes claim a stable dedupe key (
message_id→client_id→seq→ body fingerprint) via OpenClawcreateClaimableDedupe(account-scopedresolveFilePathunderopenclaw-weixin/replay-dedupe/, compatible with the minimum host2026.6.1) before processing, then commit a 24h tombstone so at-least-once iLink long-poll replays (~1s) and longer redeliveries after stuck long turns do not run the AI pipeline twice — including across process restart. Failures and abort release the claim for retry. In-flight replays release the admission lane immediately, observe the owner out of band, and re-enqueue only if the owner releases — so a distinct follow-up message is not blocked. Claim ownership wraps every step after admission. Fallback keys prefer itemmsg_iddigests and never key by sender alone. Duplicate logs record only a non-sensitive identity kind. The window is a replay-dedupe / tombstone window, not a content dedupe that swallows intentional re-sends with a newmessage_id. StableMessageSiduses the same key when transport ids are present. Port of Tencent/openclaw-weixin#240; tracks NewFuture/openclaw-weixin#36.
[3.0.1] - 2026-08-02
Changed
- Bound npm publishing to the protected
npm-publishenvironment, requiring a repository administrator's approval after automated validation and granting OIDC publish permission only to the approved job. - Made the same workflow mirror each npmjs release to GitHub Packages as
@newfuture/openclaw-weixin, then create a GitHub Release from the bilingual changelogs; retries skip existing package versions and reconcile missing destinations; publication remains blocked, including when the registry is empty, until the preceding repository release reaches GitHub Packages. - Expanded the minimum supported OpenClaw host to
2026.6.1, retained2026.7.1as the normal development baseline, and added a full minimum-host CI build and test.
[3.0.0] - 2026-07-31
Added
- Exec approval prompts now expose separate copy-friendly
/approvecode blocks: forwarded prompts append each allowed short-ID action, while direct prompts split each command underOther optionsinto its own block.
Changed
- Set the community package and plugin version to
3.0.0for the first release after consolidating on the singleopenclaw-weixinidentity. - Standardized the repository, npm package, plugin, and channel name on
openclaw-weixin, and simplified releases to publish one package. - Standardized the MIT license text and packaged an informational
NOTICEpreserving Tencent's upstream attribution and the community modification notice. - Added a release metadata gate and idempotent release reconciliation after successful
mainCI, with immutable transition-commit tagging and ordered npm publication. - Made Chinese the primary README and moved the English version to
README_EN.md, while retainingREADME.zh_CN.mdas a compatibility link. - Raised the minimum supported OpenClaw host to
2026.7.1and aligned the runtime guard, package metadata, development environment, and CI Node.js floors with that release. - Unified plugin installation and in-place Tencent-package replacement around one
--forcecommand, with separate account setup, reload verification, and agent guidance; moved detailed usage and protocol reference into the packageddocs/directory.
Security
- Overrode vulnerable transitive development dependencies with patched versions and added a moderate-or-higher dependency audit gate to CI and npm releases.
[2.4.6] - 2026-07-23
Changed
- Prepared the first community-maintained npm distribution as the unscoped
openclaw-weixinpackage, derived from Tencent's@tencent-weixin/openclaw-weixin. - Preserved the internal
openclaw-weixinplugin/channel id, configuration keys, and state paths for in-place migration. - Added community repository metadata, package-content checks, and an npm Trusted Publishing workflow.
- Aligned the runtime compatibility guard and documentation with OpenClaw
>=2026.5.12and Node.js>=22.
[2.4.5] - 2026-06-22
Added
classifyFetchError— network error classification: NewclassifyFetchErrorutility insrc/api/api.tsclassifies fetch-level errors intodns/tcp/tls/timeout/unknown.apiGetFetchandapiPostFetchnow log structured error details (type, description, code) on failure, making network troubleshooting significantly easier. Includes full test coverage for ENOTFOUND, ECONNREFUSED, ETIMEDOUT, SSL/TLS, AbortError, and more.sendMessageresponse validation:sendMessagenow parses the server response (SendMessageRespwithret/errmsg) and throws on non-zeroret, preventing silent delivery failures.
Changed
SESSION_EXPIRED_ERRCODE→STALE_TOKEN_ERRCODE: Renamed insrc/api/session-guard.tsto more accurately describe the token-stale condition (the error code -14 indicates a stale/expired token, not a session expiry). All references inmonitor.tsand tests updated.- Error logging improvements:
getUpdateserrors inmonitor.tsnow includeclassifyFetchErrorclassification (type, description, code).- Removed duplicate
errLoglines inmonitor.ts; onlyaLog.errorremains. - CDN upload failure logs (
cdn-upload.ts) now include redacted URL and error cause. downloadRemoteImageToTemp(upload.ts) now logs detailed fetch network errors with cause.- API GET/POST fetch failures (
api.ts) now log redacted URL, timeout, and error classification.
- Minimum host version bumped:
peerDependencies.openclawandinstall.minHostVersionraised from>=2026.3.22to>=2026.5.12.
Added (Dev/Engineering)
outbound-hooks.test.ts: New test file coveringapplyWeixinMessageSendingHook(no hooks, content modification, cancellation, error recovery) andemitWeixinMessageSent(no hooks, success, failure with fire-and-forget) scenarios.
Fixed
pairing.test.tsmock path:vi.mocktarget corrected from"openclaw/plugin-sdk"to"openclaw/plugin-sdk/infra-runtime".api.test.tssendMessage mock response: Success test case mock now returns"{}"instead of"", matching the updatedsendMessagelogic that parses the response body.
[2.4.4] - 2026-05-22
Added
- Tool-call progress messages:
WeixinReplyProgressSendersendsTOOL_CALL_START/TOOL_CALL_RESULTprogress messages when the model executes tools. Configurable via thereplyProgressMessageschannel option (default:true). - Abort signal support for in-flight requests:
apiPostFetch/getUpdatesnow accept an externalAbortSignal. When the gateway stops or hot-reloads a channel, the in-flight long-poll is cancelled immediately instead of waiting for the server-side timeout.
[2.4.3] - 2026-05-08
Fixed
iLink-App-Id/iLink-App-ClientVersionheaders were empty /0in production.readPackageJsonresolvedpackage.jsonvia a fixed../../fromimport.meta.url, but the TypeScript build (withindex.tsplussrc/**/*.tsintsconfig.include) emitsdist/src/api/api.js(extrasrc/segment), so the resolved path landed on the non-existentdist/package.jsonand the catch returned{}. Replaced with a walk-up that searches for the plugin's ownpackage.json(validated bynamecontainingopenclaw-weixinor by the presence ofilink_appid), tolerating both dev (src/api/) and built (dist/src/api/) layouts. Adds tests insrc/api/api.test.tscovering the compiled layout, dev layout, nestednode_modules/<dep>/package.jsonshadowing, missing manifest, and malformed manifest.openclaw channels loginexited non-zero when the bot was already bound to this OpenClaw, which caused automated installers (e.g.openclaw-weixin-installer) to report a misleading "首次连接未完成" message and continue past a successful state. The QR poller now returnsalreadyConnected: truefor the server'sbinded_redirectstatus, andauth.logininchannel.tstreats it as a successful no-op (no save, no throw) so the CLI exits cleanly.
[2.4.2] - 2026-05-07
Fixed
- Node 24 / undici compatibility —
TypeError: fetch failedon every request. Drop the manually-setContent-Lengthheader frombuildHeaders. The bundled undici in Node 24 rejects pre-setContent-LengthwithUND_ERR_INVALID_ARG: invalid content-length header, breaking all CGI calls. Lettingfetchcompute it from the request body restores network calls on Node 24. - OpenClaw ≥ 2026.5.x — Weixin runtime initialization timeout restart loop. Replace the module-scope
pluginRuntimeglobal (and removesrc/runtime.tsalong with it) with thectx.channelRuntimeinjected by the gateway per call. The previous global was set during plugin registration, but newer hosts inject a per-call runtime surface, so the global was missing/stale at startup and the channel kept timing out and restarting.
Removed
- Dead scripts and shims:
scripts/test-full-upload.ts/scripts/test-upload-url.tsdebug scripts and the unused legacyindex.tsre-exports. No behavior change for consumers.
[2.4.1] - 2026-05-04
Added
- Ship compiled runtime in the npm tarball:
dist/is added tofilesandpackage.json#openclaw.runtimeExtensionsis set to["./dist/index.js"]. The host loads the prebuilt JS entry directly instead of relying on source-only TypeScript at install time, which avoids therequires compiled runtime output for TypeScript entry index.tserror on stricter host versions. openclaw.plugin.jsonchannel config: DeclarechannelsandchannelConfigsinopenclaw.plugin.jsonso newer hosts (≥ 2026.4.x) can render the channel selection UI without falling back topackage.json#openclaw.
[2.3.1] - 2026-04-28
Added
bot_agentrequest field: Outgoing CGI requests now carry an upstream-app-suppliedbot_agent(UA-stylename/version (comment)grammar, multi-product allowed). Configurable per upstream app via channel config and sanitized bysanitizeBotAgentinsrc/api/api.ts; falls back toOpenClawwhen missing or invalid.local_token_liston QR fetch:fetchQRCodenow posts the most recent localbot_tokens (up to 10), enabling the server to recognize already-bound bots and reply withbinded_redirectinstead of issuing a duplicate session.- Pair-code login flow: Support entering a pair-code (
verify_code) when the QR scan triggers a server-side challenge;waitForWeixinLoginhandlesneed_verifycode/verify_code_blockedstates with a stdin prompt and bounded retries. binded_redirecthandling: New status branch in QR polling that prints✅ 已连接过此 OpenClaw,无需重复连接。and returns gracefully when the scanned bot is already bound to this OpenClaw.- Connection status notify (start/stop): Emit
notifyStartfromgateway.startAccount(after the provider is announced) andnotifyStopfrom a newgateway.stopAccounthook, so the upstream Weixin server can reconcile per-account online state.
Changed
- QR login UX: Reword the QR/scan prompts and remove the client-side timeout from
fetchQRCode/startWeixinLoginWithQr— only server / stack limits now bound the long-poll.
[2.1.10] - 2026-04-24
Added
- Connection status notify (start/stop) — initial introduction:
notifyStarton account startup andnotifyStopon shutdown via the newgateway.stopAccounthook. (Carried into the 2.3.x line as well.)
[2.1.9] - 2026-04-20
Added
- Outbound hook support: Add
message_sending(pre-send interception/modification) andmessage_sent(post-send notification) hook integration for all outbound paths —sendText,sendMedia, and the inbound-replydeliverinprocess-message. Hook logic is extracted into a sharedsrc/messaging/outbound-hooks.tsmodule.
Changed
- Cleanup: Remove unused
mediaUrlparameter fromsendWeixinOutboundsignature.
[2.1.8] - 2026-04-07
Changed
- Markdown filter:
StreamingMarkdownFilternow preserves more Markdown constructs in outbound text.
[2.1.7] - 2026-04-07
Fixed
- Plugin registration re-entrance: Lazy-import
monitorWeixinProviderinsidestartAccountinchannel.tsto avoid pulling in the monitor → process-message → command-auth chain at plugin registration time, which could re-enter the plugin/provider registry before the account starts. - Initialization side effect: Lazy-import
resolveSenderCommandAuthorizationWithRuntime/resolveDirectDmAuthorizationOutcomeinprocess-message.tsto preventensureContextWindowCacheLoadedfrom being triggered during module initialization, which causedloadOpenClawPluginsre-entrance.
Changed
- Tool-call outbound path:
sendWeixinOutboundnow appliesStreamingMarkdownFilterto the outbound text, consistent with the model-output path inprocess-message.
[2.1.4] - 2026-04-03
Changed
- QR login: Remove client-side timeout for
get_bot_qrcode; the request is no longer aborted on a fixed deadline (server / stack limits still apply).
[2.1.3] - 2026-04-02
Added
StreamingMarkdownFilter(src/messaging/markdown-filter.ts): outbound text no longer runs through whole-stringmarkdownToPlainTextstripping; a streaming character filter replaces it, so Markdown goes from effectively unsupported to partially supported.
Changed
- Outbound text path:
process-messageusesStreamingMarkdownFilter(feed/flush) per deliver chunk instead ofmarkdownToPlainText.
Removed
markdownToPlainTextfromsrc/messaging/send.ts(and its tests fromsend.test.ts); coverage moves tomarkdown-filter.test.ts.
[2.1.2] - 2026-04-02
Changed
- Config reload after login: On each successful Weixin login, bump
channels.openclaw-weixin.channelConfigUpdatedAt(ISO 8601) inopenclaw.jsonso the gateway reloads config from disk, instead of writing an emptyaccounts: {}placeholder. - QR login: Increase client timeout for
get_bot_qrcodefrom 5s to 10s. - Docs: Uninstall instructions now use
openclaw plugins uninstall @tencent-weixin/openclaw-weixin(aligned with the plugins CLI). - Logging:
debug-checklog line no longer includesstateDir/OPENCLAW_STATE_DIR.
Removed
openclaw-weixinCLI subcommands (src/weixin-cli.tsand registration inindex.ts). Use the hostopenclaw plugins uninstall …flow instead.
Fixed
- Resolves the dangerous code pattern warning when installing the plugin on OpenClaw 2026.3.31+ (host plugin install / static checks).