Changelog
This project follows the Keep a Changelog format.
[Unreleased]
[3.2.1] - 2026-09-18
Changed
- OpenClaw development SDK: Pin
2026.9.4with matching build metadata and update the recommended development environment to Node.js24.16.0. CI retains older hosts and Node.js22.22.3coverage; the plugin's minimum host and Node.js runtime requirements are unchanged.
[3.2.0] - 2026-09-16
Added
- Maintenance report preview: Added a manually triggered gh-aw maintenance summary with staged-only outputs and separate agent and threat-detection inference budgets; it does not automatically create issues, PRs, or releases.
Changed
- Inbound host orchestration: Use the shared public context builder and select routed or legacy public dispatch by runtime capability, while retaining the OpenClaw
2026.6.1minimum, account isolation and independent approval lane. Failed dispatches are never retried through another contract. - Package source priority: The repository, website, and ClawHub package are now ClawHub-first. npm and GitHub Packages generate npm-first READMEs from the same source package, removing the website-only transformation; publishing jobs reuse the exact tarballs created during validation.
Fixed
- Plugin icon metadata: Removed the top-level manifest
iconURL flagged by ClawHub validation against OpenClaw2026.9.4and bundled the existing brand artwork asassets/icon.pngin every registry package. Plugin/channel IDs and the minimum supported host remain unchanged; icon display follows the host's packaged-icon support. - Reply hooks: Modern inbound replies and host-managed direct text/media sends use one host hook owner, avoiding duplicate content changes and sent observations. Legacy inbound replies and independent debug sends retain local hooks; successful replies expose their existing client transport IDs.
- Login reload: Update only the channel timestamp in the host's current source config with an explicit automatic reload policy, avoiding stale runtime snapshots overwriting unrelated settings. Failed config writes leave saved login credentials intact.
- Block replies: Restored ordered delivery of completed text blocks between tool calls by default, with channel-level and per-account
blockStreaming: falseopt-outs for final-only replies.
[3.1.6] - 2026-08-22
Fixed
- Diagnostic privacy: normal logs now fully mask identifiers and tokens, opt-in DEBUG logs expose at most short redacted prefixes, and diagnostics no longer persist message text, URL queries, QR URLs, or raw filesystem paths.
[3.1.5] - 2026-08-16
Changed
- Node.js compatibility range: the published package now declares support for Node.js
>=22.22.3, including Node.js 24 and 26; CI adds compatibility coverage for the current Node.js 26 runtime.
Fixed
- OpenClaw beta config compatibility: the plugin entry and channel registration now share the host's JSON Schema boundary instead of the removed
openclaw/plugin-sdk/zodexport. The schema covers the documentedbotAgent, progress-message setting, and string or numeric route tags, allowing the plugin to load on newer hosts without shipping a second Zod copy.
[3.1.4] - 2026-08-12
Fixed
- Release version gaps: npmjs and GitHub Packages no longer require intermediate repository versions to be published. The workflows still check the exact target, require
latestto be lower than the release, recheck remote state before irreversible boundaries, and fail explicit non-404 lookup errors.
[3.1.3] - 2026-08-12
Fixed
- Release workflow reliability: npmjs, ClawHub, and GitHub Packages now publish in parallel from the validated release tag and complete from successful publish responses, avoiding a false failure when npm registry propagation lags; GitHub Release finalizes after all three package targets complete. ClawHub OIDC trusted publishing no longer overrides the package owner.
[3.1.2] - 2026-08-12
Changed
- Channel ID alias compatibility: On OpenClaw 2026.7.1 and later, declared
openclaw-wechatas a channel alias while keepingopenclaw-weixinas the sole canonical plugin/channel ID, config key, and state namespace.
[3.1.1] - 2026-08-11
Changed
- ClawHub release preparation: Added a constrained conversion from the canonical npm tarball to an
openclaw-wechatClawPack, credential-free PR dry-runs, and a GitHub OIDC trusted-publish workflow that can be manually triggered only from the matching release tag. The npm package and plugin/channel id remainopenclaw-weixin; a maintainer must still bootstrap the public listing and publisher binding on the next release.
Fixed
- Refuse to send when
contextTokenis missing (avoid silent-drop): the 5 send entry points (sendMessageWeixin,sendMessageItemWeixin,sendImageMessageWeixin,sendVideoMessageWeixin,sendFileMessageWeixin) now throw before calling the backend instead oflogger.warn-and-continue whencontextTokenis absent, so missing-token attempts cannot return a locally generated fake-successmessageId. These helpers redact recipient IDs in their own logs viaredactToken(see Tencent/openclaw-weixin#247).
[3.1.0] - 2026-08-10
Fixed
- OpenClaw SDK entry compatibility:
createTypingCallbacksnow imports fromopenclaw/plugin-sdk/channel-message, supporting both the minimum host that still exposes the legacy entry and modern hosts that removedchannel-runtime. CI builds and imports this boundary and runs an unmocked plugin-registration smoke against both real SDK profiles. - Context-token user ID case normalization (outbound ret=-3): account-scoped in-memory and persisted context-token keys now lowercase the user ID. Mixed-case IDs from getUpdates, lowercased OpenClaw session targets, and legacy persisted files therefore resolve the same token after restart (see Tencent/openclaw-weixin#243).
- Persist stable
--accountaliases on QR login (logical mapping): afterchannels login --account <alias>succeeds, credentials and state stay under the serverilink_bot_id(primary hash) and a 1:1alias → hashmap is stored for bindings / outbound resolution.listAccountIds/ monitors use only the primary;config.isEnabledreturns false for aliases so hoststart(alias)is rejected before a lifecycle task (no restart loop). The hostdefaultsentinel is never treated as an alias;alreadyConnectedonly records the mapping when unambiguous and is a no-op for existing primary-hash relogin; conflicting alias credentials are rejected without moving sync/context/allow-list state; the account index is written atomically and left intact if publish fails.
[3.0.2] - 2026-08-05
Changed
- Per-agent inbound media isolation: images, videos, files, and voice messages are now stored under
weixin/<agentId>/inboundfor the routed agent, preventing mixed media and cross-agent access in multi-agent deployments. Unresolved routes continue to use the legacy-compatibleinboundpath.
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).