-
Notifications
You must be signed in to change notification settings - Fork 3.1k
fix(qqbot): restore per-group session isolation under thread scope #8241
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
0635538
f9cc1bc
7f1912b
f2daf02
a41cdad
2fd94e3
2d9c4f3
5bf5498
d4b99e6
f5ace0c
2189179
bdd4b86
cbd7faa
144b63f
216d201
ca7c546
f5c3317
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -50,30 +50,30 @@ Channels are configured under the `channels` key in `settings.json`. Each channe | |
|
|
||
| ### Options | ||
|
|
||
| | Option | Required | Description | | ||
| | ------------------------ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| | `type` | Yes | Channel type: `telegram`, `weixin`, `qq`, `dingtalk`, `wecom`, `feishu`, `github`, or a custom type from an extension (see [Plugins](./plugins)) | | ||
| | `token` | Telegram | Bot token. Supports `$ENV_VAR` syntax to read from environment variables. Not needed for WeChat, DingTalk, WeCom, or Feishu | | ||
| | `clientId` | DingTalk, Feishu | DingTalk AppKey or Feishu App ID. Supports `$ENV_VAR` syntax | | ||
| | `clientSecret` | DingTalk, Feishu | DingTalk AppSecret or Feishu App Secret. Supports `$ENV_VAR` syntax | | ||
| | `botId` | WeCom | WeCom intelligent robot Bot ID. Supports `$ENV_VAR` syntax. See [WeCom](./wecom) | | ||
| | `secret` | WeCom | WeCom intelligent robot Secret. Supports `$ENV_VAR` syntax. See [WeCom](./wecom) | | ||
| | `model` | No | Model to use for this channel (e.g., `qwen3.5-plus`). Overrides the default model. Useful for multimodal models that support image input | | ||
| | `senderPolicy` | No | Who can talk to the bot: `allowlist` (default), `open`, or `pairing` | | ||
| | `allowedUsers` | No | List of user IDs allowed to use the bot (used by `allowlist` and `pairing` policies) | | ||
| | `sessionScope` | No | How sessions are scoped: `user` (default), `thread`, or `single` | | ||
| | `cwd` | No | Working directory for the agent. Defaults to the current directory | | ||
| | `approvalMode` | No | Tool approval mode for channel sessions. Unattended webhook tasks require `yolo`; the setting applies to every session on the channel | | ||
| | `instructions` | No | Custom instructions prepended to the first message of each session | | ||
| | `webhooks` | No | Webhook sources and delivery targets for daemon-managed channels. See [Webhook-triggered tasks](#webhook-triggered-tasks) | | ||
| | `groupPolicy` | No | Group chat access: `disabled` (default), `allowlist`, or `open`. See [Group Chats](#group-chats) | | ||
| | `dmPolicy` | No | Private/DM access: `open` (default) or `disabled` (silently drop all DMs). Useful for group-only bots | | ||
| | `groupHistoryLimit` | No | Opt-in group history backfill. `0` or omitted disables it. A positive number persists that many authorized, unmentioned group messages for the next bot mention/reply. | | ||
| | `groups` | No | Per-group settings. Keys are group chat IDs or `"*"` for defaults. See [Group Chats](#group-chats) | | ||
| | `dispatchMode` | No | What happens when you send a message while the bot is busy: `steer` (default), `collect`, or `followup`. See [Dispatch Modes](#dispatch-modes) | | ||
| | `blockStreaming` | No | Progressive response delivery: `on` or `off` (default). See [Block Streaming](#block-streaming) | | ||
| | `blockStreamingChunk` | No | Chunk size bounds: `{ "minChars": 400, "maxChars": 1000 }`. See [Block Streaming](#block-streaming) | | ||
| | `blockStreamingCoalesce` | No | Idle flush: `{ "idleMs": 1500 }`. See [Block Streaming](#block-streaming) | | ||
| | Option | Required | Description | | ||
| | ------------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ||
| | `type` | Yes | Channel type: `telegram`, `weixin`, `qq`, `dingtalk`, `wecom`, `feishu`, `github`, or a custom type from an extension (see [Plugins](./plugins)) | | ||
| | `token` | Telegram | Bot token. Supports `$ENV_VAR` syntax to read from environment variables. Not needed for WeChat, DingTalk, WeCom, or Feishu | | ||
| | `clientId` | DingTalk, Feishu | DingTalk AppKey or Feishu App ID. Supports `$ENV_VAR` syntax | | ||
| | `clientSecret` | DingTalk, Feishu | DingTalk AppSecret or Feishu App Secret. Supports `$ENV_VAR` syntax | | ||
| | `botId` | WeCom | WeCom intelligent robot Bot ID. Supports `$ENV_VAR` syntax. See [WeCom](./wecom) | | ||
| | `secret` | WeCom | WeCom intelligent robot Secret. Supports `$ENV_VAR` syntax. See [WeCom](./wecom) | | ||
| | `model` | No | Model to use for this channel (e.g., `qwen3.5-plus`). Overrides the default model. Useful for multimodal models that support image input | | ||
| | `senderPolicy` | No | Who can talk to the bot: `allowlist` (default), `open`, or `pairing` | | ||
| | `allowedUsers` | No | List of user IDs allowed to use the bot (used by `allowlist` and `pairing` policies) | | ||
| | `sessionScope` | No | How sessions are scoped: `user` (default), `thread`, `chat_thread`, or `single`. Channel plugins may declare a different default (QQ defaults to `thread`; GitHub and GitLab default to `chat_thread`) | | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] This PR adds chat_thread to this row and to the daemon settings validation set, but leaves the cross-linked sibling doc plugins.md:53 stating sessionScope is " 中文说明本 PR 给这一行和守护进程设置校验集加了 chat_thread,却让相互链接的兄弟文档 plugins.md:53 仍写 sessionScope 为 " — qwen3.8-max via Qwen Code /review (v0.21.7) |
||
| | `cwd` | No | Working directory for the agent. Defaults to the current directory | | ||
| | `approvalMode` | No | Tool approval mode for channel sessions. Unattended webhook tasks require `yolo`; the setting applies to every session on the channel | | ||
| | `instructions` | No | Custom instructions prepended to the first message of each session | | ||
| | `webhooks` | No | Webhook sources and delivery targets for daemon-managed channels. See [Webhook-triggered tasks](#webhook-triggered-tasks) | | ||
| | `groupPolicy` | No | Group chat access: `disabled` (default), `allowlist`, or `open`. See [Group Chats](#group-chats) | | ||
| | `dmPolicy` | No | Private/DM access: `open` (default) or `disabled` (silently drop all DMs). Useful for group-only bots | | ||
| | `groupHistoryLimit` | No | Opt-in group history backfill. `0` or omitted disables it. A positive number persists that many authorized, unmentioned group messages for the next bot mention/reply. | | ||
| | `groups` | No | Per-group settings. Keys are group chat IDs or `"*"` for defaults. See [Group Chats](#group-chats) | | ||
| | `dispatchMode` | No | What happens when you send a message while the bot is busy: `steer` (default), `collect`, or `followup`. See [Dispatch Modes](#dispatch-modes) | | ||
| | `blockStreaming` | No | Progressive response delivery: `on` or `off` (default). See [Block Streaming](#block-streaming) | | ||
| | `blockStreamingChunk` | No | Chunk size bounds: `{ "minChars": 400, "maxChars": 1000 }`. See [Block Streaming](#block-streaming) | | ||
| | `blockStreamingCoalesce` | No | Idle flush: `{ "idleMs": 1500 }`. See [Block Streaming](#block-streaming) | | ||
|
|
||
| ### Sender Policy | ||
|
|
||
|
|
@@ -87,8 +87,9 @@ Controls who can interact with the bot: | |
|
|
||
| Controls how conversation sessions are managed: | ||
|
|
||
| - **`user`** (default) — One session per user. All messages from the same user share a conversation. | ||
| - **`user`** (default) — One session per user. All messages from the same user share a conversation. `user` is the global default, but a channel plugin can declare a different default for its type: the QQ channel defaults to `thread`, while the GitHub and GitLab channels default to `chat_thread`. | ||
| - **`thread`** — One session per thread/topic. Useful for group chats with threads. | ||
| - **`chat_thread`** — One session per chat and thread, shared across participants even outside a group (for example, an issue or PR discussion). | ||
| - **`single`** — One shared session for all users. Everyone shares the same conversation. | ||
|
|
||
| ### Channel Memory | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -60,7 +60,7 @@ export QQ_APP_SECRET=<your-app-secret> | |
| "appSecret": "$QQ_APP_SECRET", | ||
| "sandbox": false, | ||
| "senderPolicy": "open", | ||
| "sessionScope": "user", | ||
| "sessionScope": "thread", | ||
| "cwd": "/path/to/your/project", | ||
| "instructions": "你是一个通过 QQ Bot 对话的 AI 助手。回复控制在 2000 字符以内。", | ||
| "blockStreaming": "on", | ||
|
|
@@ -73,6 +73,8 @@ export QQ_APP_SECRET=<your-app-secret> | |
| } | ||
| ``` | ||
|
|
||
| > `sessionScope` defaults to `"thread"`. With `groupPolicy: "disabled"` this is a DM-only setup, where both `"thread"` and `"user"` behave identically — each direct message gets its own context. `"thread"` is shown here for consistency with the [Session Isolation](#session-isolation) section below. | ||
|
|
||
| ### QQ-Specific Options | ||
|
|
||
| | Option | Default | Description | | ||
|
|
@@ -106,6 +108,14 @@ To use the bot in QQ groups: | |
|
|
||
| QQ Bot API V2 only delivers group messages that @mention the bot — the bot does not see all group messages. By default, `requireMention` is `true` and should be left that way for QQ. | ||
|
|
||
| ### Session Isolation | ||
|
|
||
| The QQ channel defaults to `sessionScope: "thread"`: members of the same group share a single conversation context keyed by `<channel>:<group_openid>`, while different groups are isolated from each other. Each direct message gets its own context keyed by `<channel>:<user_openid>`. | ||
|
|
||
| A group thread session is a **shared session**: every member of the group reads and continues the same conversation history. Session-control commands (`/clear`, `/cancel`) and the `!` host-shell gate act on that shared session — in `"thread"` scope they affect the whole group, restricted to `allowedUsers` members when the list is non-empty. Permission-request answers are gated separately, by **chat + thread**: you can answer a pending permission request only for the same chat and thread you are in, and in a shared group session any member may do so — this gating is independent of `sessionScope`. If group members should not share history or control each other's turns, set `sessionScope: "user"` (each member gets a private session) or restrict membership via `senderPolicy` / `allowedUsers`. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] The new Session Isolation paragraph misstates two security-relevant gates. (1) The 中文说明新增的 Session Isolation 段落对两个安全相关门控的描述与实现不符。(1) — qwen3.8-max via Qwen Code /review (v0.21.7) |
||
|
|
||
| For full-message mode this default is already what you want — with `groupAllPolicy: "all"`, keeping `"thread"` gives you shared context within a group and isolation across groups. If you instead set `sessionScope: "user"`, full-message traffic is fragmented per sender (a separate session for every member), which is not suitable for group full-message scenarios. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] This paragraph steers users into full-message mode via 中文说明本段引导用户通过 — qwen3.8-max via Qwen Code /review (v0.21.7) |
||
|
|
||
| See [Group Chats](./overview#group-chats) for full details on group policies and mention gating. | ||
|
|
||
| ## Markdown Support | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Suggestion] This PR's rewritten sessionScope row tells readers "GitHub and GitLab default to chat_thread", but this adjacent type row still omits gitlab from the supported channel types — the page contradicts itself, newly introduced by this diff's sessionScope edit. — Failure scenario: gitlab is bundled and first-class (channel-registry.ts:27 registers @qwen-code/channel-gitlab; gitlab.md documents "type": "gitlab"). A user who learns GitLab exists from the sessionScope row reads this row and concludes GitLab needs an extension or is unsupported. Suggested fix: add
gitlabto the channel list (aftergithub).中文说明
本 PR 重写的 sessionScope 行告诉读者“GitHub 与 GitLab 默认 chat_thread”,但相邻的 type 行仍未把 gitlab 列入支持的渠道类型——页面自相矛盾,且是本 diff 的 sessionScope 修改新引入的。失败场景:gitlab 是内置一等渠道(channel-registry.ts:27 注册 @qwen-code/channel-gitlab;gitlab.md 文档写明 "type": "gitlab")。读者从 sessionScope 行得知 GitLab 存在,再看此行会误以为 GitLab 需要扩展或不被支持。修复建议:在渠道列表中加入
gitlab(放在github之后)。— qwen3.8-max via Qwen Code /review (v0.21.7)