🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

群聊人格机器人 icewindwillow/DSH-bot

DeepSeek Harness
icewindwillow4 天前有提交已提供中文文档扫描:含敏感能力

让 QQ 机器人在不同群有不同性格,按需记住群友的话

30.5/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/11/2 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add icewindwillow/DSH-bot
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么
dsh 原生插件 · platform
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 4 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 156 处,展示前 100 条)
  • 读取本地文件
    bot-config-panel/credentials.mjs:33
    try { return lstatSync(path); }
  • 写入本地文件
    bot-config-panel/credentials.mjs:49
    mkdirSync(dir, { recursive: true, mode: 0o700 });
  • 写入本地文件
    bot-config-panel/credentials.mjs:158
    writeFileSync(fd, content, 'utf8');
  • 写入本地文件
    bot-config-panel/credentials.mjs:163
    renameSync(temp, path);
  • 删除本地文件
    bot-config-panel/credentials.mjs:168
    if (created) unlinkSync(temp);
  • 读取本地文件
    bot-config-panel/image-generation.mjs:98
    try { return lstatSync(path); }
  • 写入本地文件
    bot-config-panel/image-generation.mjs:111
    mkdirSync(dir, { recursive: true, mode: 0o700 });
  • 写入本地文件
    bot-config-panel/image-generation.mjs:170
    writeFileSync(fd, `${JSON.stringify(settings, null, 2)}\n`, 'utf8');
  • 写入本地文件
    bot-config-panel/image-generation.mjs:175
    renameSync(temp, path);
  • 删除本地文件
    bot-config-panel/image-generation.mjs:184
    unlinkSync(temp);
  • 读取本地文件
    bot-config-panel/server.mjs:38
    const PATCH = existsSync(OVERLAY) ? OVERLAY : join(PROFILE_DIR, 'cordis.patch.yml');
  • 读取本地文件
    bot-config-panel/server.mjs:105
    const pkg = JSON.parse(readFileSync(join(PROFILE_DIR, 'package.json'), 'utf8'));
  • 读取本地文件
    bot-config-panel/server.mjs:118
    if (!existsSync(catalogPath)) return undefined;
  • 读取本地文件
    bot-config-panel/server.mjs:120
    try { catalog = JSON.parse(readFileSync(catalogPath, 'utf8')); }
  • 读取本地文件
    bot-config-panel/server.mjs:133
    const settings = JSON.parse(readFileSync(join(OUR_FREE_DIR, 'settings.json'), 'utf8'));
  • 读取本地文件
    bot-config-panel/server.mjs:156
    return existsSync(file) ? readFileSync(file, 'utf8') : '';
  • 写入本地文件
    bot-config-panel/server.mjs:168
    if (exists) copyFileSync(file, backup);
  • 写入本地文件
    bot-config-panel/server.mjs:170
    writeFileSync(tmp, text, { encoding: 'utf8', mode });
  • 写入本地文件
    bot-config-panel/server.mjs:171
    chmodSync(tmp, mode);
  • 写入本地文件
    bot-config-panel/server.mjs:172
    renameSync(tmp, file);
  • 写入本地文件
    bot-config-panel/server.mjs:379
    writeFileSync(tmp, text, { encoding: 'utf8', mode: 0o600, flag: 'wx' });
  • 执行外部命令固定命令
    bot-config-panel/server.mjs:380
    execFileSync('python3', ['-c', 'import sys,yaml;yaml.safe_load(open(sys.argv[1],encoding="utf-8").read())', tmp],
  • 删除本地文件
    bot-config-panel/server.mjs:391
    try { unlinkSync(tmp); } catch { }
  • 删除本地文件
    bot-config-panel/server.mjs:645
    if (Date.now() - statSync(lock).mtimeMs > 8000) unlinkSync(lock);
  • 删除本地文件
    bot-config-panel/server.mjs:658
    try { unlinkSync(lock); } catch { }
  • 删除本地文件
    bot-config-panel/server.mjs:685
    if (Date.now() - statSync(lock).mtimeMs > 8000) unlinkSync(lock);
  • 写入本地文件
    bot-config-panel/server.mjs:698
    writeFileSync(tmp, `${JSON.stringify(state, null, 2)}\n`);
  • 删除本地文件
    bot-config-panel/server.mjs:705
    try { unlinkSync(lock); } catch { }
  • 执行外部命令固定命令
    bot-config-panel/server.mjs:748
    const out = execFileSync('pgrep', ['-fl', `profile ${PROFILE_NAME}`], { encoding: 'utf8' });
  • 执行外部命令固定命令
    bot-config-panel/server.mjs:767
    const which = execFileSync('which', ['dsh'], { encoding: 'utf8' }).trim();
  • 执行外部命令固定命令
    bot-config-panel/server.mjs:823
    execFileSync('launchctl', ['kickstart', '-k', `gui/${process.getuid()}/${label}`], { encoding: 'utf8', timeout: 15000 });
  • 发起网络请求
    bot-config-panel/server.mjs:833
    const res = await fetch(`${CONTROL_URL}${path}`, {
  • 删除本地文件
    bot-config-panel/server.mjs:1349
    unlinkSync(filePath);
  • 写入本地文件
    patch-qqbot.mjs:786
    writeFileSync(tmp, bytes, { mode, flag: 'wx' });
  • 写入本地文件
    patch-qqbot.mjs:787
    chmodSync(tmp, mode);
  • 写入本地文件
    patch-qqbot.mjs:788
    renameSync(tmp, file);
  • 读取本地文件
    patch-qqbot.mjs:790
    if (existsSync(tmp)) unlinkSync(tmp);
  • 删除本地文件
    patch-qqbot.mjs:790
    if (existsSync(tmp)) unlinkSync(tmp);
  • 写入本地文件
    patch-qqbot.mjs:853
    writeFileSync(temp, source, { flag: 'wx', mode: 0o600 });
  • 执行外部命令来自配置/变量
    patch-qqbot.mjs:854
    const result = spawnSync(process.execPath, ['--check', temp], {
  • 读取本地文件
    patch-qqbot.mjs:861
    if (existsSync(temp)) unlinkSync(temp);
  • 删除本地文件
    patch-qqbot.mjs:861
    if (existsSync(temp)) unlinkSync(temp);
  • 删除本地文件
    patch-qqbot.mjs:862
    rmdirSync(tempDir);
  • 读取本地文件
    patch-qqbot.mjs:871
    if (!statSync(file).isFile()) throw new Error('target is not a regular file');
  • 读取本地文件
    patch-qqbot.mjs:874
    const before = readFileSync(file);
  • 读取本地文件
    patch-qqbot.mjs:875
    entry = { file, before, source: before.toString('utf8'), mode: statSync(file).mode & 0o777, patches: [] };
  • 读取本地文件
    patch-qqbot.mjs:878
    let snippet = readFileSync(join(SNIPPETS, patch.snippet), 'utf8').replace(/ $/, '');
  • 写入本地文件
    patch-qqbot.mjs:915
    writeFileSync(fd, JSON.stringify({ pid: process.pid, at: new Date().toISOString() }));
  • 删除本地文件
    patch-qqbot.mjs:917
    if (fd !== undefined) { closeSync(fd); unlinkSync(LOCK); }
  • 删除本地文件
    patch-qqbot.mjs:921
    finally { closeSync(fd); unlinkSync(LOCK); }
  • 写入本地文件
    patch-qqbot.mjs:930
    mkdirSync(dir, { recursive: true, mode: 0o700 });
  • 读取密钥环境变量
    qqbot-patches/auto-compact-helper.js:10
    const threshold = Number(process.env.QQBOT_AUTO_COMPACT_TOKENS ?? 60000);
  • 读取密钥环境变量
    qqbot-patches/auto-sticker-helper.js:32
    let key = process.env.XIANGXIN_API_KEY ?? '';
  • 请求外部主机api.xiangxinai.cn
    qqbot-patches/auto-sticker-helper.js:72
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 发起网络请求
    qqbot-patches/auto-sticker-helper.js:72
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 读取密钥环境变量
    qqbot-patches/bot-control-helper.js:17
    const token = String(process.env.QQBOT_CONTROL_TOKEN ?? '');
  • 读取密钥环境变量
    qqbot-patches/event-helper.js:168
    let key = process.env.XIANGXIN_API_KEY ?? '';
  • 请求外部主机api.xiangxinai.cn
    qqbot-patches/event-helper.js:211
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 发起网络请求
    qqbot-patches/event-helper.js:211
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 读取密钥环境变量
    qqbot-patches/hook-judge-helper.js:13
    let key = process.env.XIANGXIN_API_KEY ?? '';
  • 请求外部主机api.xiangxinai.cn
    qqbot-patches/hook-judge-helper.js:48
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 发起网络请求
    qqbot-patches/hook-judge-helper.js:48
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 发起网络请求
    qqbot-patches/image-generation-helper.js:221
    const response = await fetch(url, { method: 'GET', redirect: 'error', signal, headers: { accept: 'image/*' } });
  • 发起网络请求
    qqbot-patches/image-generation-helper.js:393
    const response = await fetch(endpoint, {
  • 发起网络请求
    qqbot-patches/image-generation-helper.js:570
    const response = await fetch(endpoint, {
  • 读取密钥环境变量
    qqbot-patches/media-archive-helper.js:279
    if (String(process.env.XIANGXIN_API_KEY ?? '').trim() !== '')
  • 读取密钥环境变量
    qqbot-patches/media-archive-helper.js:280
    return String(process.env.XIANGXIN_API_KEY).trim();
  • 请求外部主机api.xiangxinai.cn
    qqbot-patches/media-archive-helper.js:297
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 发起网络请求
    qqbot-patches/media-archive-helper.js:297
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 读取密钥环境变量
    qqbot-patches/memory-gate-helper.js:54
    let key = process.env.XIANGXIN_API_KEY ?? '';
  • 请求外部主机api.xiangxinai.cn
    qqbot-patches/memory-gate-helper.js:112
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 发起网络请求
    qqbot-patches/memory-gate-helper.js:112
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 读取密钥环境变量
    qqbot-patches/memory-summary-helper.js:10
    let key = process.env.XIANGXIN_API_KEY ?? '';
  • 请求外部主机api.xiangxinai.cn
    qqbot-patches/memory-summary-helper.js:38
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 发起网络请求
    qqbot-patches/memory-summary-helper.js:38
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 发起网络请求
    qqbot-patches/model-aware-fetch-helper.js:44
    const result = await ds(route).fetch({ url }, signal);
  • 发起网络请求
    qqbot-patches/model-aware-fetch-helper.js:96
    async fetch(request, signal) {
  • 发起网络请求
    qqbot-patches/model-aware-fetch-helper.js:101
    return ds(route).fetch({ url: validateUrl(request?.url) }, signal);
  • 发起网络请求
    qqbot-patches/model-aware-search-helper.js:22
    const response = await deps.fetch(`${base}/responses`, {
  • 发起网络请求
    qqbot-patches/model-aware-search-helper.js:159
    fetch: (...args) => fetch(...args),
  • 读取密钥环境变量
    qqbot-patches/model-failover-helper.js:20
    const BACKUP_MAX_TOKENS = Math.max(256, Number(process.env.QQBOT_FALLBACK_MAX_TOKENS ?? 8192));
  • 读取密钥环境变量
    qqbot-patches/person-feedback-tool-helper.js:38
    let key = process.env.XIANGXIN_API_KEY ?? '';
  • 请求外部主机api.xiangxinai.cn
    qqbot-patches/person-feedback-tool-helper.js:97
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 发起网络请求
    qqbot-patches/person-feedback-tool-helper.js:97
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 发起网络请求
    qqbot-patches/person-feedback-tool-helper.js:236
    const res = await fetch(url, {
  • 读取密钥环境变量
    qqbot-patches/reply-gate-helper.js:10
    let key = process.env.XIANGXIN_API_KEY ?? '';
  • 请求外部主机api.xiangxinai.cn
    qqbot-patches/reply-gate-helper.js:43
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 发起网络请求
    qqbot-patches/reply-gate-helper.js:43
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 读取密钥环境变量
    qqbot-patches/social-judge-helper.js:25
    let apiKey = process.env.OPENCODE_GO_API_KEY ?? '';
  • 请求外部主机opencode.ai
    qqbot-patches/social-judge-helper.js:50
    const res = await fetch('https://opencode.ai/zen/go/v1/chat/completions', {
  • 发起网络请求
    qqbot-patches/social-judge-helper.js:50
    const res = await fetch('https://opencode.ai/zen/go/v1/chat/completions', {
  • 读取密钥环境变量
    qqbot-patches/social-judge-helper.js:78
    let apiKey = process.env.XIANGXIN_API_KEY ?? '';
  • 请求外部主机api.xiangxinai.cn
    qqbot-patches/social-judge-helper.js:111
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 发起网络请求
    qqbot-patches/social-judge-helper.js:111
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 读取密钥环境变量
    qqbot-patches/stale-draft.js:12
    let key = process.env.XIANGXIN_API_KEY ?? '';
  • 请求外部主机api.xiangxinai.cn
    qqbot-patches/stale-draft.js:62
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 发起网络请求
    qqbot-patches/stale-draft.js:62
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 读取密钥环境变量
    qqbot-patches/subject-judge-helper.js:11
    let key = process.env.XIANGXIN_API_KEY ?? '';
  • 请求外部主机api.xiangxinai.cn
    qqbot-patches/subject-judge-helper.js:34
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
  • 发起网络请求
    qqbot-patches/subject-judge-helper.js:34
    const res = await fetch('https://api.xiangxinai.cn/v1/systemone', {
扫描于 2026/11/4(0 天前) · 范围 全包扫描 · 来源 GitHub 仓库
涉及外部主机:api.xiangxinai.cn、opencode.ai

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
展开完整介绍(122 字)↓

基于 DeepSeek Harness 的 QQ 群聊机器人增强体系:群人格、选择性记忆、低打扰、可视化密钥配置、可选免费模型渠道,以及按角色/好感度授权的多供应商生图(OpenAI / 硅基流动 / Cloudflare)。macOS 优先。

README

由 DeepSeek 最新模型翻译生成
DSH-bot 原创鲸鱼主题横幅,非产品截图 DSH-bot · 让 QQ 机器人更像一位群友 不是换一句系统提示词,而是让机器人知道:这是哪个群、谁在说话、什么值得记住、什么时候最好别插嘴。 DSH-bot 是一套 QQ 机器人增强体系,基于 DeepSeek Harness(DSH)与上游 @tencent-connect/dsh-qqbot。上游负责机器人宿主、QQ 接入和基础会话;本仓库提供群聊增强补丁、可视化控制台、示例配置与部署工具,不是从零原创的 QQ 宿主,也不包含模型服务。 它有什么不一样? | 你想要的体验 | 这里的做法 | | 同一个机器人,在不同群有不同性格 | 按群组织人格模块;针对当前说话人启用话题、风格与角色技能,不必把所有设定塞进每一轮对话 | | 记得住事情,但不是每句话都记 | 记忆门控筛选有价值的信息;可选语义检索,用模糊描述找回旧事 | | 对话不总像第一次见面 | 关系状态、心情和事件线索参与回应;这些是可检查的程序状态,不是机器人真的有情感 | | 能接梗,也能安静待着 | 唤醒词、对话窗口、按群唤醒指数和静默回应共同控制打扰程度 | | 群友发过的图,不必反复翻聊天记录 | 媒体归档、搜图、收藏和发回当前会话;启用前请先获得成员理解与同意 |
展开完整文档(README 剩余 1 节)
DSH-bot 原创鲸鱼主题横幅,非产品截图

DSH-bot · 让 QQ 机器人更像一位群友

不是换一句系统提示词,而是让机器人知道:这是哪个群、谁在说话、什么值得记住、什么时候最好别插嘴。

DSH-bot 是一套 QQ 机器人增强体系,基于 DeepSeek Harness(DSH)与上游 @tencent-connect/dsh-qqbot。上游负责机器人宿主、QQ 接入和基础会话;本仓库提供群聊增强补丁、可视化控制台、示例配置与部署工具,不是从零原创的 QQ 宿主,也不包含模型服务。

它有什么不一样?

| 你想要的体验 | 这里的做法 |
| 同一个机器人,在不同群有不同性格 | 按群组织人格模块;针对当前说话人启用话题、风格与角色技能,不必把所有设定塞进每一轮对话 |
| 记得住事情,但不是每句话都记 | 记忆门控筛选有价值的信息;可选语义检索,用模糊描述找回旧事 |
| 对话不总像第一次见面 | 关系状态、心情和事件线索参与回应;这些是可检查的程序状态,不是机器人真的有情感 |
| 能接梗,也能安静待着 | 唤醒词、对话窗口、按群唤醒指数和静默回应共同控制打扰程度 |
| 群友发过的图,不必反复翻聊天记录 | 媒体归档、搜图、收藏和发回当前会话;启用前请先获得成员理解与同意 |
| 只有名单里的人能画图 | 可选单张生图与 QQ 回传(OpenAI 付费 / 硅基流动 Kolors 免费 / Cloudflare flux 免费额度);默认关闭,只发本次新 prompt,不附群历史,不自动重试 |
| 每条消息都送主模型,很贵 | 先用便宜的判断模型做门控与分类,主模型只处理真正值得回的消息,大幅节省 Token |
| 配置不想手改一大堆 JSON | 本机网页管理 API Key、模型、人格、成员模块、唤醒指数与图库 |
| 切模型,联网行为也跟着切 | 搜索/读取按实际请求路由选择后端;读不到就明确说读不到,不把搜索摘要伪装成文章原文 |

这些能力有配置和隐私边界,不是每项都默认开启。日记与向量检索默认关闭;群 scope 也不是严格的数据安全隔离。 特别是人物卡存在跨群汇总路径,上游记忆库默认可能由多个 profile 共享。见隐私说明。

API Key:打开面板,填上就好

核心流程很简单:终端初始化一次,此后在面板填 Key、选模型、调人格。

运行 npm run panel,打开终端打印的 http://127.0.0.1:7791,在凭据区域配置:

- 象信 API Key(判断模型,强烈建议先配);
- OpenAI / DeepSeek 聊天 API Key;
- QQ 机器人的 QQBOT_APPID、QQBOT_SECRET;
- 可选的 OPENCODE_GO_API_KEY(部分辅助功能的后备路由)。

不需要为了填 Key 先学 YAML。 面板不回显已保存的密码;留空表示保留,删除要显式操作,保存后需重启机器人。继承的非空环境变量优先于面板值。

密钥存放在所选 profile 的 .bot-secrets.json,使用 0600 权限,是本地明文,不是加密保险箱。同一操作系统账号、备份软件及具有相应权限的进程仍可能读取。通过 npm run bot 启动,才会由本项目启动器加载它。详见配置指南。

为什么建议配一个「判断模型」?

群聊里大部分消息并不需要主模型逐条读完:要不要回、值不值得记、是不是在骂人,都是高频的小判断。本项目先交给一个便宜的判断模型(system-1),只把真正值得处理的消息送进主模型,Token 消耗会明显下降。

- 象信(推荐):结构化判断,一次请求返回多个是非/评分,最省。在面板填 XIANGXIN_API_KEY 即可;内置的回复门控、记忆门控、事件与主语判断都走它。
- Jev 这类免费模型:Our Free Model 提供 jev-1.13-free 等免费聊天模型,适合承担便宜的辅助生成(日报、人物卡、事件摘要),也可以直接当主聊天模型。把对应的 QQBOT__PROVIDER / QQBOT__MODEL 指向可用路由即可。

不配判断模型也能跑:判断失败时门控会自动放行(宁可多说),但每条消息都更容易送进主模型,更贵也更吵。判断模型本身也可能按次计费或受额度限制,详见配置指南。

免费模型,也能纳入同一套选择器

本项目对接 Our Free Model / our-free-model,对应第三方插件 dsh-our-free-model。安装到同一 profile 后,可以在控制台选择其模型或插件提供的降级链;插件源码不内置、不复制到本仓库。

免费渠道可以不填 OpenAI Key,但 QQ 的 AppID/Secret 仍然需要,搜索、读取和辅助功能也有各自凭据要求。它适合先体验,但受上游网络、地区、额度和条款影响:不承诺永久免费、无限额度或持续可用。部分渠道可能记录提示词,敏感信息不要发送;官方付费 API 及辅助模型调用仍各自计费。

本项目的跨服务商兜底默认关闭,不会在免费渠道故障后默认改送付费后端。只有管理员显式 QQBOT_MODEL_FAILOVER=on 并审阅后备模型、路由 Key、上下文外发及费用后才启用;Our Free Model 自己的 combo 另由该插件管理。

官方 README 明确警告:不要安装 npm 上同名的非官方包。我们核对了官方 v2.7.3 Release 的发布制品,按免费模型接入指南安装,而不是猜一条 npm install。

也能画图:三家可选,权限说了算

可选工具 generate_image 生成单张图片并回传当前 QQ 群聊或 C2C。默认关闭,与聊天 provider 独立——可以 DeepSeek 聊天、别家生图。

| 模型 | 服务商 | 费用 | 特点 |
| gpt-image-2 等 | OpenAI | 按官方计费 | 质量最好,中文原生 |
| Kwai-Kolors/Kolors | 硅基流动 | 当前免费(需实名认证) | 中文友好,带「AI 生成」水印 |
| @cf/black-forest-labs/flux-1-schnell | Cloudflare Workers AI | 每日免费额度(1024² / 4 步约 170 张) | 只认英文,发送前自动补全并翻译 |

谁能画:主人、image-gen 这个独立技能(qqbot-role-skills.json,面板「角色模块」里对应的勾选框)的受众、或好感度达到门槛(缺省 60)的成员。有权限的人直接说人话就行——「画只戴墨镜的柯基在冲浪」——不用打 /生图;没权限的人说什么都不会产生请求。生图权限是一个独立技能,不会因为某人有别的角色技能就顺带获得。

边界:一次请求一张、同一时刻一张在途、不自动重试、只发本次 prompt、不附群历史或参考图;Cloudflare 的英文改写失败时退回原文并在回执里注明。没有冷却和每小时次数上限——能发图的人由权限名单控制。

Key 不会进仓库:面板把 Key 写进所选 profile 的 .bot-secrets.json(0600),运行时也会直接读 ~/.dsh/.credentials.yaml;仓库里只有 examples/.env.example 的空占位,没有任何真实密钥。详见生图指南与边界。

先跑起来

需要已安装、可执行的 DSH,以及腾讯 QQ 开放平台的机器人应用和所需权限。本项目不替你申请机器人账号,也不会绕过平台审核。

1. 克隆与安装

git clone https://github.com/icewindwillow/DSH-bot.git
cd DSH-bot
npm install
若尚未安装 DSH:此固定版本已核对官方 npm 发布信息
npm install -g @deepseek-ai/dsh@0.2.1-rc.3

已有 DSH 桌面端或其它官方发行版时,不必盲目再装一份;可按部署指南选择明确的运行时路径。推荐使用 Node 24 LTS;本机 macOS 已在 Node 24.22.2 与 25.8.1 跑通离线回归。

2. 建一个新的测试 profile

脚本默认名仍为 qqbot。以下示例特意使用独立的 qqbot-demo,避免碰到旧机器人:

export QQBOT_PROFILE_NAME=qqbot-demo
先确认目标全新/空白!下面命令会替换目标 profile,不是合并。
dsh --profile "$QQBOT_PROFILE_NAME" --from-default-profile web
dsh plugin --profile "$QQBOT_PROFILE_NAME" add @tencent-connect/dsh-qqbot@0.5.2
dsh plugin --profile "$QQBOT_PROFILE_NAME" add @tr1v3r/dsh-ltm@0.3.4

已有同名 profile 就换个新名字,不要运行替换命令。 创建命令可能随后启动宿主;生成配置后先用 Ctrl+C 停止,再安装插件,后续统一用 npm run bot 启动,避免重复实例。若已通过其它官方方式创建独立 profile,跳过 --from-default-profile web。完整步骤见部署指南。

目录默认按 DSH_HOME/profiles/QQBOT_PROFILE_NAME 组成,未设 DSH_HOME 时为 ~/.dsh。启动器要求显式 QQBOT_PROFILE_DIR 也匹配该位置;要换数据根请改 DSH_HOME,不要单独随意指向另一个目录。

3. 预览初始化,检查,再应用

npm run init # 仅预览,不写入
npm run init -- --apply # 只补缺失 JSON 与独立 overlay
npm run doctor
npm run patch:plan # 先看补丁是否适用于当前上游版本
npm run patch
npm run patch:check

初始化不会安装 DSH/插件,也不修改现有 profile 的包清单或原始 patch;它仅补缺失的虚构资料模板和 dsh-bot.patch.yml。启动时用 --patch 叠加该 overlay;面板优先编辑它,避免直接改旧配置。

补丁改的是目标 profile 中上游插件的安装产物,不是 DSH 内核。安装版本变化导致锚点不匹配时应停止,不要强行替换。启动器会再检查补丁、获取本地锁与控制 token,并在 profile 的私有 workspace 运行;不会拿 Git 源码目录当机器人工作区。

4. 用网页配置,启动机器人

npm run panel
在浏览器打开 http://127.0.0.1:7791,填写凭据、模型和群配置另开一个终端,使用相同的 QQBOT_PROFILE_NAME / QQBOT_PROFILE_DIR:
npm run bot

先在获同意的测试群里用 @机器人 验证一轮普通聊天,再逐步开启其它能力。面板不是机器人进程;关掉面板也不等于停止机器人。

常用命令

| 命令 | 用途 |
| npm run init / npm run init -- --apply | 初始化预览 / 仅写缺失 profile 模板 |
| npm run doctor | 检查本机环境、profile 与依赖,不代表真实 QQ/API 验收 |
| npm run panel | 启动仅本机可访问的可视化控制台,默认端口 7791 |
| npm run bot | 加载本地凭据并启动所选 profile 的 DSH |
| npm run patch:plan / npm run patch | 补丁预检 / 部署与备份 |
| npm run patch:check / npm run patch:revert | 检查补丁 / 从部署备份恢复原件 |
| npm test / npm run security:check | 回归测试 / 仓库敏感数据检查 |

面板重启功能默认关闭;仅可显式配置 macOS launchd,不会在失败时偷偷启动第二个实例。Linux/Windows 的进程管理不在当前承诺范围。

兼容性与已知边界

- 已观察的组合:DSH 0.2.1-rc.3、QQ 插件 0.5.2、LTM 0.3.4、Our Free Model 2.7.3。这是版本基线,不保证兼容任意未来版本。
- 推荐 Node 24 LTS。本机 macOS 的 Node 24.22.2 / 25.8.1 各通过 88/88;首轮远端 CI 的 Node 24/25 × Ubuntu/macOS 四组全部通过。这仍不等于真实 QQ/API 或 Linux 守护部署验收。
- 本地 macOS Node 24.22.2 与 25.8.1 离线回归均 88/88 通过;干净上游包的补丁部署、检查、幂等与原件回滚已验证。范围与未验项见验证记录,这不等于真实 QQ/API 验收。
- 模型调用、搜索与辅助判定可能产生费用;选免费聊天模型不代表整套增强零费用。
- 补丁采用全量预检、原件备份、逐文件提交和失败回滚;不是跨文件单一原子事务,也不保证断电时自动恢复。
- 不附带生产群资料、聊天历史、密钥、日志或图片;示例与测试只能使用虚构数据。
- 生图为独立可选能力,默认关闭。 看图、图库和已有图发送不等于生图;生图需明确请求、独立费用与权限,见专用指南。

文档导航

架构与能力边界 · 配置 · 部署 · 免费模型 · 生图 · 隐私 · 开发 · 故障排查

Git 协作流程 · 参与贡献 · 安全报告 · 第三方说明

接下来

- 保持 Node 24/25 CI 矩阵持续通过,补齐更多环境的实机验证;
- 持续减少对上游安装产物锚点的依赖,完善补丁升级检查;
- 改进权限、隐私选择和新手引导;
- 完善生图授权和费用提示,补齐管理员授权下的真实 QQ 图片回传验收。

授权与致谢

感谢 DSH、@tencent-connect/dsh-qqbot、LTM 及 Our Free Model 等上游项目。本仓库不是这些项目或腾讯、OpenAI、DeepSeek 等服务商的官方产品;名称与商标归各权利人。

本项目原创部分采用 MIT 许可证。第三方组件、模型与服务不因本项目采用 MIT 就被重新授权,始终受各自许可与条款约束,详见第三方说明。
预览分享卡片长什么样 ↓icewindwillow/DSH-bot
分享 · DeepSeek Harness Hub
icewindwillow/DSH-bot

让 QQ 机器人在不同群有不同性格,按需记住群友的话

这是你的仓库?认领条目

回到顶部