Files
claude-code-haha/docs/im/qq.md
T
程序员阿江(Relakkes) 814c02a786 feat(im): add scan-to-create Feishu bots plus WeCom, QQ and Slack adapters
Connecting Feishu meant creating a bot by hand on the open platform and
pasting an App ID and App Secret back. Feishu also exposes an RFC 8628
device-authorization flow, so the desktop can now render a QR code, and
confirming it in the app creates the bot and stores its credentials
directly. `adapters/feishu/registration.ts` implements that protocol
rather than importing `registerApp` from `@larksuiteoapi/node-sdk@1.73`:
the repository pins 1.60 for the chat client, and the SDK runs the whole
poll inside one un-cancellable promise where the desktop needs the
stateless begin/poll pair the DingTalk registration already uses. The
scan is create-only, so it can never rewrite the configuration of a bot
the user already runs, and it pre-fills exactly the scopes, events and
callbacks this adapter calls. International tenants finish on Lark's
domain, which is now persisted and honoured by the client.

WeCom, QQ and Slack join the same session model. WeCom and QQ bind by
scanning; Slack has no scan flow, so it uses an app manifest that
pre-fills the scopes and Socket Mode. All three run over long
connections, so no public callback URL is needed, and all three accept
private chats only — pairing authorizes one person, and answering in a
group would extend that authorization to everyone else in the room.

They are built on a new `adapters/common/chat-runtime.ts` instead of a
fourth copy of the loop the five existing adapters each carry. A platform
supplies a `ChatPort` — how to say something, how to open a streaming
reply, optionally how to send an image — and the runtime owns pairing,
command routing, session restore, permission bookkeeping and the
translation of the server's stream. The existing five are deliberately
left on their own copies; migrating them is a separate change with its
own regression surface.

Attachments are downloaded through a deferred loader that runs after the
pairing gate and inside the per-chat queue. Resolving them eagerly would
let an unpaired stranger make the adapter fetch bytes and write them
under ~/.claude/im-downloads — on Slack with the bot token attached —
and would let a slow attachment overtake a text message sent after it.

The sidecar launcher's per-adapter branches become one table. It is
declared above the mode dispatch on purpose: `runAdapters` is hoisted and
runs at module top level, so a table declared below it is still in its
temporal dead zone when the adapters mode reads it — which type checks,
lints and unit tests all miss, and only the compiled binary reveals.

Verified with the checks `check:impact` selects: adapters, server,
desktop, electron, policy, chat-contract, agent-flow, docs, native
(sidecar compile, packaging and an adapters-mode smoke against the real
binary) and coverage. The scan flows themselves are not verified against
live platforms — that needs real WeCom, QQ and Slack accounts and would
create real bots.

Claude-Session: https://claude.ai/code/session_01CCGoP316AK7wdQG3Ms6Uwq
2026-09-05 23:46:50 +08:00

90 lines
4.8 KiB
Markdown

---
title: QQ 接入
nav_title: QQ
description: 在设置页扫码授权 QQ 机器人,在 QQ 私聊里驱动桌面端,回复走 QQ 的流式消息。
order: 7
---
# QQ 接入
适合个人用户:在桌面端点一下扫码,用手机 QQ 扫一扫完成授权,AppID 和 AppSecret 直接写进本机配置,不用去 QQ 开放平台手动创建应用。消息走官方 WebSocket 网关,本机不需要公网地址。
限制:只处理私聊(C2C),不处理群聊和频道;权限审批是文本命令。
## 扫码授权机器人
1. 打开「设置」→「IM 接入」,切到「QQ」Tab。
2. 点「扫码绑定」,页面上会出现一张二维码。
3. 用手机 QQ 扫码,按提示确认授权。
4. 授权成功后,AppID 和 AppSecret 会自动写入 `~/.claude/adapters.json`,适配器随即重启。
二维码过期时会自动换一张,页面上的图片会跟着刷新。绑定成功后按钮变成「重新扫码」,旁边多一个「解除机器人绑定」。
这一步只是让桌面端拿到机器人凭据,**不等于**放行所有人——谁能用还得看下一步的配对。
## 配对
回到页面顶部的「配对管理」,点「生成配对码」,拿到一枚 6 位码。这一步立即生效,不需要再点保存。
在 QQ 里私聊刚授权的机器人,把这枚码发过去。看到配对成功提示就可以开始对话。
配对码 60 分钟内有效、只能用一次,重新生成后旧码立刻作废。同一个用户 5 分钟内连续输错 5 次会被限流。
「允许的用户」可以留空。留空时只有完成配对的人能用。要直接放行已知账号,就填 QQ 用户 `openid`,多个用逗号分隔,填完点「保存」。QQ 的 `openid` 是每个机器人独立的一串标识,不是 QQ 号。
## 支持的命令
- `/help` 或 `帮助` — 列出当前可用命令
- `/status` 或 `状态` — 当前项目、模型、运行状态
- `/projects` 或 `项目列表` — 列出最近项目并切换
- `/new` 或 `新会话` — 开一条新会话,可带项目编号、名称或绝对路径
- `/clear` 或 `清空` — 清空上下文,保留项目绑定
- `/stop` 或 `停止` — 停止本轮生成
- 权限审批:回复 `1` 允许一次、`2` 永久允许、`3` 拒绝,也可以用 `/allow <id>`、`/always <id>`、`/deny <id>`
## 消息表现
回复用 QQ 的流式消息(`stream_messages`):同一条消息随生成过程刷新,结束时定稿。这个接口只对私聊开放;万一某轮拿不到可用的回复锚点,会自动退回成普通分片消息,不会丢内容。
思考和执行工具期间会发输入状态提示。收到的图片、文件会下载到 `~/.claude/im-downloads/qq/` 并作为附件送进 Agent;语音消息用 QQ 自带的转写文本,不下载音频。Agent 输出里引用的本地图片(限当前会话工作目录内)会上传成图片消息单独发出。
## Agent 能力与边界
QQ 不是一套独立的问答模型。普通消息进入的是当前项目的同一条 Claude Code Agent 会话,因此会延续多轮上下文,并能使用该会话已经加载的文件、终端、Git、Skills 和 MCP 工具。
这意味着配对成功的账号获得的是当前项目里的完整 Agent 能力,权限确认只是操作闸门,不是操作系统沙箱。不要把机器人交给不可信的人,也不要在聊天里安装未经本机审核的 Skill、Plugin 或 MCP。
Adapter 只接受已配对或在允许列表中的私聊账号;项目列表和名称匹配都限制在「允许访问的项目目录」内。
## 本地开发启动
发布版桌面端会自动把 adapter 作为 sidecar 拉起。只有从源码运行或单独调试时才需要手动启动:
```bash
cd adapters
bun install
bun run qq
```
可选的环境变量覆盖:
```bash
export QQ_APP_ID="xxx"
export QQ_APP_SECRET="xxx"
export ADAPTER_SERVER_URL="ws://127.0.0.1:3456"
```
## 常见问题
**二维码一直转不出来**:扫码走的是 QQ 开放平台的接口,确认本机网络能访问;20 秒拿不到二维码会报超时,点一下重试。
**扫码成功但机器人不回消息**:确认桌面端还开着,并且「QQ」Tab 里显示了 AppID。凭据是扫码那一刻写进配置的,之后适配器会自动重启一次。
**发消息提示未授权**:检查是否已生成配对码、码是否还在 60 分钟有效期内、发的是不是当前这一枚。
**群里 @ 机器人没反应**:这是预期行为,当前只处理私聊。配对授权的是个人身份,在群里放行会把这份授权扩散给群里所有人。
## 源码入口
`adapters/qq/index.ts`(运行时)、`adapters/qq/qr-auth.ts`(扫码授权)、`adapters/qq/extract-payload.ts`(入站消息解析),以及 `adapters/common/chat-runtime.ts` 这套跨平台会话循环。