Skip to content

fix: populate SenderId on inbound MsgContext for multi-user routing#88

Open
yarnovo wants to merge 1 commit intoTencent:mainfrom
yarnovo:fix/multi-user-sender-id
Open

fix: populate SenderId on inbound MsgContext for multi-user routing#88
yarnovo wants to merge 1 commit intoTencent:mainfrom
yarnovo:fix/multi-user-sender-id

Conversation

@yarnovo
Copy link
Copy Markdown

@yarnovo yarnovo commented Apr 26, 2026

Summary

Set SenderId on the WeixinMsgContext returned by weixinMessageToMsgContext so OpenClaw core can route per-sender peer state correctly when this plugin is used alongside multi-user-aware memory plugins (e.g. openclaw-honcho).

Why

OpenClaw core's buildInboundUserContextPrefix reads ctx.SenderId to populate the sender_id field of the inbound Conversation info (untrusted metadata) block prepended to user messages. Memory plugins parse that block to attribute messages to a specific sender's peer.

Currently weixinMessageToMsgContext only sets From: from_user_id and leaves SenderId undefined. The resulting metadata block omits sender_id, so downstream plugins (e.g. honcho's extractSenderId) cannot identify the sender and collapse all senders into a single peer. Multi-user isolation breaks for any deployment that exposes this plugin to more than one wxid.

For comparison, the equivalent inbound builders in @wecom/wecom-openclaw-plugin (monitor.js line setting SenderId: body.from.userid) and @larksuite/openclaw-lark (dispatch-builders.js line setting SenderId: opts.senderId) already populate this field. This change brings weixin in line.

Changes

  • Add optional SenderId?: string to the WeixinMsgContext type with a doc comment explaining the contract with OpenClaw core. Optional rather than required to preserve backward compatibility for any external code that constructs this type directly.
  • Set SenderId: from_user_id alongside From in weixinMessageToMsgContext.
  • Add two test cases:
    • SenderId is populated from from_user_id for a normal message.
    • SenderId falls back to empty string when from_user_id is missing (matches the existing From / To behavior).

Test plan

  • npm run typecheck passes.
  • npm test — 337 of 338 tests pass; the single pre-existing failure in src/auth/pairing.test.ts > registerUserInFrameworkStore > uses withFileLock for concurrency safety reproduces on a clean checkout of upstream/main and is unrelated to this change.
  • npx vitest run src/messaging/inbound.test.ts — all 26 inbound tests pass, including the two new SenderId cases.

Diff

 src/messaging/inbound.test.ts | 10 ++++++++++
 src/messaging/inbound.ts      |  8 ++++++++
 2 files changed, 18 insertions(+)

OpenClaw core's `buildInboundUserContextPrefix` reads `ctx.SenderId` to populate
the `sender_id` field of the inbound `Conversation info (untrusted metadata)`
block. Memory plugins like `openclaw-honcho` parse that block to route per-sender
peer state.

Currently `weixinMessageToMsgContext` only sets `From: from_user_id` and leaves
`SenderId` undefined, so the metadata block omits `sender_id`. Downstream
plugins that depend on it (honcho `extractSenderId`, etc.) collapse all senders
into a single peer, breaking multi-user isolation.

This change:

- Adds optional `SenderId?: string` to `WeixinMsgContext` with a doc comment
  explaining the contract with OpenClaw core.
- Sets `SenderId: from_user_id` alongside `From` in `weixinMessageToMsgContext`.
- Adds two test cases: one that asserts `SenderId` matches `from_user_id` for
  a normal message, and one that verifies the empty-string fallback when
  `from_user_id` is missing.

For comparison, both `@wecom/wecom-openclaw-plugin` and
`@larksuite/openclaw-lark` already populate `SenderId` on inbound; this brings
weixin in line.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant