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

鲸鲸世界 chenkezhen480/dsh-world

DeepSeek Harnessv0.6.6
chenkezhen4802 天前有提交已提供中文文档扫描:含敏感能力

给鲸鲸一个完整的世界

63.6/100
综合分
227
GitHub 星标
870
npm 周下载
—/5
用户评分

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

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dsh-world
npm 源 · dsh-world 的发布者账号已校验与本仓库一致

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · market
装得上吗
实装验证未通过(unknown),装前请到仓库确认最近更新与 issue
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 2 天前
档位由哪些信号合成

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

验证判据与等级说明 →
⚠︎ 实装验证未通过(unknown · 2026/10/25) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-world @ 0.6.6
✓Node 引擎要求 >=22.16.0 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/11/1 18:22:04

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

可执行外部命令读写/删除本地文件写入剪贴板(不计风险)读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 95 处,展示前 95 条)
  • 发起网络请求
    lib/index.js:317
    homeApply.request(); } });
  • 发起网络请求
    lib/index.js:381
    applyHome: () => !power.running() || !life ? '请先启动世界生活线' : homeApply.request(),
  • 读取本地文件
    lib/index.js:384
    worldPrompt: existsSync(worldPromptFile) ? { text: readFileSync(worldPromptFile, 'utf8'), custom: true } : { text: readFileSync(DEFAULT_TEMPLATE_FILE,
  • 读取本地文件
    lib/index.js:384
    worldPrompt: existsSync(worldPromptFile) ? { text: readFileSync(worldPromptFile, 'utf8'), custom: true } : { text: readFileSync(DEFAULT_TEMPLATE_FILE,
  • 删除本地文件
    lib/index.js:450
    rmSync(worldPromptFile, { force: true }); },
  • 发起网络请求
    client/index.js:23
    function getFrom(base, path) { return fetch(base + path, { cache: 'no-store' }).then(settle) }
  • 发起网络请求
    client/index.js:25
    return fetch(base + path, { method: 'POST', cache: 'no-store', headers: { 'content-type': 'application/json', 'x-dsh-world': '1' }, body: JSON.stringi
  • 写入剪贴板
    client/index.js:493
    navigator.clipboard.writeText(text).then(function () { setMsg('命令已复制') }, function () { setMsg('复制失败,自己选上面那行') })
  • 读取本地文件
    lib/ecosystem/bridge/bridge.js:95
    if (JSON.parse(readFileSync(deps.file, 'utf8')).token === token)
  • 删除本地文件
    lib/ecosystem/bridge/bridge.js:96
    rmSync(deps.file, { force: true });
  • 读取本地文件
    lib/compactionSwap.js:14
    if (!existsSync(file))
  • 读取本地文件
    lib/compactionSwap.js:16
    const text = readFileSync(file, 'utf8');
  • 写入本地文件
    lib/compactionSwap.js:24
    copyFileSync(file, backup);
  • 写入本地文件
    lib/compactionSwap.js:26
    writeFileSync(temporary, text.replace(stock, "$1'dsh-world/compaction'$3"), 'utf8');
  • 写入本地文件
    lib/compactionSwap.js:27
    renameSync(temporary, file);
  • 删除本地文件
    lib/compactionSwap.js:30
    rmSync(temporary, { force: true });
  • 写入本地文件
    lib/life/lifeStore.js:15
    writeFileSync(fd, text);
  • 删除本地文件
    lib/life/lifeStore.js:34
    rmSync(temporary, { force: true });
  • 写入本地文件
    lib/life/lifeStore.js:44
    writeFileSync(fd, `${torn ? '\n' : ''}${JSON.stringify(value)}\n`);
  • 读取本地文件
    lib/life/lifeStore.js:53
    if (!existsSync(file))
  • 读取本地文件
    lib/life/lifeStore.js:55
    return readFileSync(file, 'utf8').split('\n').filter(Boolean).flatMap(line => { try {
  • 写入本地文件
    lib/life/lifeStore.js:68
    mkdirSync(lifeDir, { recursive: true });
  • 写入本地文件
    lib/life/lifeStore.js:69
    mkdirSync(activityDir, { recursive: true });
  • 读取本地文件
    lib/life/lifeStore.js:72
    if (!existsSync(stateFile))
  • 读取本地文件
    lib/life/lifeStore.js:75
    return JSON.parse(readFileSync(stateFile, 'utf8'));
  • 写入本地文件
    lib/life/lifeStore.js:90
    mkdirSync(activityDir, { recursive: true });
  • 读取本地文件
    lib/life/lifeStore.js:103
    activityDays: () => existsSync(activityDir) ? readdirSync(activityDir).filter(name => dayFile.test(name)).map(name => name.slice(0, 10)).sort().revers
  • 读取本地文件
    lib/life/lifeStore.js:103
    activityDays: () => existsSync(activityDir) ? readdirSync(activityDir).filter(name => dayFile.test(name)).map(name => name.slice(0, 10)).sort().revers
  • 读取本地文件
    lib/life/runtime.js:281
    const existing = (dir) => { const file = join(options.worldDir, dir, `${review.day}.jsonl`); return existsSync(file) ? file : undefined; };
  • 读取本地文件
    lib/ecosystem/shared/outlets.js:31
    raw = readFileSync(file, 'utf8');
  • 读取本地文件
    lib/persona.js:10
    if (existsSync(file))
  • 读取本地文件
    lib/persona.js:11
    sections = parseSections(readFileSync(file, 'utf8'), PERSONA_LAYERS);
  • 删除本地文件
    lib/persona.js:22
    rmSync(file, { force: true });
  • 读取本地文件
    lib/ecosystem/qq/panel.js:29
    if (!existsSync(runtime))
  • 读取本地文件
    lib/ecosystem/qq/panel.js:33
    parsed = JSON.parse(readFileSync(runtime, 'utf8'));
  • 读取本地文件
    lib/ecosystem/qq/panel.js:54
    if (dir && existsSync(join(dir, 'config', 'runtime.json')))
  • 读取本地文件
    lib/ecosystem/qq/panel.js:64
    if (existsSync(file))
  • 读取本地文件
    lib/ecosystem/qq/panel.js:65
    stored = JSON.parse(readFileSync(file, 'utf8'));
  • 写入本地文件
    lib/store.js:12
    mkdirSync(directory, { recursive: true, mode: 0o700 });
  • 读取本地文件
    lib/store.js:50
    const fd = openSync(file, existsSync(file) ? 'r+' : 'wx+', 0o600);
  • 读取本地文件
    lib/worldPrompt.js:14
    if (file && existsSync(file)) {
  • 读取本地文件
    lib/worldPrompt.js:16
    return { text: readFileSync(file, 'utf8').trim() };
  • 读取本地文件
    lib/worldPrompt.js:19
    return { text: readFileSync(DEFAULT_TEMPLATE_FILE, 'utf8'), error: `世界提示词模板 ${file} 读不了,先用默认模板:${error instanceof Error ? error.message : String(error
  • 读取本地文件
    lib/worldPrompt.js:22
    return { text: readFileSync(DEFAULT_TEMPLATE_FILE, 'utf8') };
  • 读取本地文件
    lib/worldSwitch.js:18
    const stored = existsSync(file) ? JSON.parse(readFileSync(file, 'utf8')) : undefined;
  • 读取本地文件
    lib/worldSwitch.js:18
    const stored = existsSync(file) ? JSON.parse(readFileSync(file, 'utf8')) : undefined;
  • 读取本地文件
    lib/worldSwitch.js:20
    running: stored ? stored.running === true : existsSync(join(worldDir, 'life.json')),
  • 读取本地文件
    lib/worldSwitch.js:80
    wechatEnabled: () => settings.wechatEnabled ?? existsSync(join(worldDir, 'wechat-outbox.sqlite')),
  • 读取本地文件
    lib/worldSwitch.js:84
    const wechat = next.wechat ?? wechatEnabled ?? existsSync(join(worldDir, 'wechat-outbox.sqlite')), qq = next.qq ?? qqEnabled === true;
  • 读取本地文件
    lib/ecosystem/wechat/index.js:199
    if (JSON.parse(readFileSync(deps.file, 'utf8')).token === token)
  • 删除本地文件
    lib/ecosystem/wechat/index.js:200
    rmSync(deps.file, { force: true });
  • 执行外部命令固定命令
    lib/ecosystem/wechat/supervisor.js:29
    spawn('taskkill', ['/PID', String(target.pid), '/T', '/F'], { stdio: 'ignore', windowsHide: true });
  • 读取本地文件
    lib/ecosystem/wechat/supervisor.js:42
    if (!existsSync(path))
  • 读取本地文件
    lib/ecosystem/wechat/supervisor.js:47
    if (existsSync(deps.logFile) && statSync(deps.logFile).size > MAX_LOG_BYTES)
  • 读取本地文件
    lib/ecosystem/wechat/supervisor.js:47
    if (existsSync(deps.logFile) && statSync(deps.logFile).size > MAX_LOG_BYTES)
  • 写入本地文件
    lib/ecosystem/wechat/supervisor.js:48
    truncateSync(deps.logFile, 0);
  • 读取本地文件
    lib/archiveSelection.js:5
    const byPath = (roomDir) => (workspace) => workspace.path === (existsSync(roomDir) ? realpathSync.native(roomDir) : roomDir);
  • 读取本地文件
    lib/workspacePermissions.js:7
    if (source !== 'startup' || header.isSeeded || header.parentSession || header.origin === 'subagent' || (header.delegationDepth ?? 0) > 0 || !header.cw
  • 写入本地文件
    lib/life/photos.js:26
    mkdirSync(directory, { recursive: true });
  • 读取本地文件
    lib/life/photos.js:54
    if (existsSync(legacy)) {
  • 读取本地文件
    lib/life/photos.js:55
    const old = JSON.parse(readFileSync(legacy, 'utf8'));
  • 读取本地文件
    lib/life/photos.js:62
    if (lstatSync(file).isSymbolicLink() || dirname(realpathSync(file)) !== realpathSync(directory) || lstatSync(file).size > MAX_BYTES)
  • 读取本地文件
    lib/life/photos.js:64
    insert(row.id, row.savedAt, { ref: row.attachment, data: readFileSync(file) }, row.description, row.tags);
  • 读取本地文件
    lib/ecosystem/qq-native/sdkInstall.js:13
    const range = JSON.parse(readFileSync(new URL('../../../package.json', import.meta.url), 'utf8')).peerDependencies[SDK];
  • 读取本地文件
    lib/ecosystem/qq-native/sdkInstall.js:41
    return { path, bytes: await readFile(path) };
  • 删除本地文件
    lib/ecosystem/qq-native/sdkInstall.js:60
    await rm(file.path, { force: true });
  • 读取本地文件
    lib/life/diary.js:5
    const dates = () => existsSync(diaryDir) ? readdirSync(diaryDir).filter(name => /^\d{4}-\d{2}-\d{2}\.md$/.test(name)).map(name => name.slice(0, 10)).s
  • 读取本地文件
    lib/life/diary.js:5
    const dates = () => existsSync(diaryDir) ? readdirSync(diaryDir).filter(name => /^\d{4}-\d{2}-\d{2}\.md$/.test(name)).map(name => name.slice(0, 10)).s
  • 读取本地文件
    lib/life/diary.js:7
    const read = (date) => { const file = join(diaryDir, `${date}.md`); return datePattern.test(date) && existsSync(file) ? readFileSync(file, 'utf8') : u
  • 读取本地文件
    lib/life/diary.js:7
    const read = (date) => { const file = join(diaryDir, `${date}.md`); return datePattern.test(date) && existsSync(file) ? readFileSync(file, 'utf8') : u
  • 读取本地文件
    lib/self.js:14
    text = existsSync(selfFile) ? readFileSync(selfFile, 'utf8').trim() : '';
  • 读取本地文件
    lib/self.js:14
    text = existsSync(selfFile) ? readFileSync(selfFile, 'utf8').trim() : '';
  • 读取本地文件
    lib/self.js:28
    if (!existsSync(selfFile))
  • 写入本地文件
    lib/self.js:32
    mkdirSync(dir, { recursive: true });
  • 写入本地文件
    lib/self.js:34
    copyFileSync(selfFile, copy);
  • 写入本地文件
    lib/life/home.js:38
    mkdirSync(deps.roomDir, { recursive: true });
  • 读取本地文件
    lib/life/messages.js:32
    const shipped = parseSections(readFileSync(DEFAULT_ALARM_FILE, 'utf8'));
  • 读取本地文件
    lib/life/messages.js:35
    if (file && existsSync(file)) {
  • 读取本地文件
    lib/life/messages.js:37
    own = parseSections(readFileSync(file, 'utf8'));
  • 读取本地文件
    lib/ecosystem/wechat/images.js:19
    const root = await realpath(incomingDir);
  • 读取本地文件
    lib/ecosystem/wechat/images.js:21
    const directory = await realpath(join(root, key));
  • 读取本地文件
    lib/ecosystem/wechat/images.js:27
    const path = await realpath(join(directory, file));
  • 读取本地文件
    lib/ecosystem/wechat/stickerLibrary.js:57
    text = await readFile(indexFile, 'utf8');
  • 写入本地文件
    lib/ecosystem/wechat/stickerLibrary.js:72
    await mkdir(dir, { recursive: true });
  • 写入本地文件
    lib/ecosystem/wechat/stickerLibrary.js:74
    await writeFile(temporary, JSON.stringify({ version: 1, stickers }, null, 2), 'utf8');
  • 写入本地文件
    lib/ecosystem/wechat/stickerLibrary.js:75
    await rename(temporary, indexFile);
  • 写入本地文件
    lib/ecosystem/wechat/stickerLibrary.js:106
    await mkdir(filesDir, { recursive: true });
  • 写入本地文件
    lib/ecosystem/wechat/stickerLibrary.js:107
    await writeFile(join(filesDir, sticker.file), data);
  • 删除本地文件
    lib/ecosystem/wechat/stickerLibrary.js:112
    await rm(join(filesDir, sticker.file), { force: true });
  • 删除本地文件
    lib/ecosystem/wechat/stickerLibrary.js:128
    await rm(join(filesDir, sticker.file), { force: true });
  • 读取本地文件
    lib/ecosystem/wechat/stickerLibrary.js:146
    const catalog = JSON.parse(await readFile(join(legacyDir, 'catalog.json'), 'utf8'));
  • 读取本地文件
    lib/ecosystem/wechat/stickerLibrary.js:155
    const data = await readFile(join(legacyDir, 'assets', entry.file));
  • 读取本地文件
    lib/ecosystem/wechat/stickerTools.js:41
    const { sticker, existing } = await library.add(await readFile(file), { tags, ...(name === undefined ? {} : { name }) }, { expectedMd5: staged.md5 });
  • 删除本地文件
    lib/ecosystem/wechat/stickerTools.js:45
    await rm(file, { force: true });
  • 读取密钥环境变量
    lib/qq-line.js:20
    const token = process.env.DSH_QQ_BRIDGE_TOKEN ?? '';
扫描于 2026/11/2(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包

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

依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-agent-loop@deepseek-ai/dsh-compaction-basic@deepseek-ai/dsh-session-persistence-jsonl@deepseek-ai/dsh-session-projection@deepseek-ai/dsh-system-prompt@deepseek-ai/dsh-token-meter@deepseek-ai/dsh-tools@deepseek-ai/dsh-plugin-manager@deepseek-ai/dsh-atomic-write@deepseek-ai/cordis@deepseek-ai/dsh-agent@deepseek-ai/dsh-attachment
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
v0.6.62026-10-30
本版调整压缩触发与默认值、让每日回顾后的压缩更稳,把微信和 QQ 改为默认关闭,并把注意事项整理进 NOTES.md。 · 压缩触发改为按窗口约 75%:去掉原来的 90% 比例和固定 65,536 的预留,窗口取模型声明的 contextWindow,模型没声明时用新增的 defaultContextWindow(默认 1M,顶层与 modelPolicies 均可设置),首次用到默认值时记一条日志。 · 每日回顾后自动压缩默认开启,控制台新增开关;只有关闭时才写入设置。 · 新增 replaceCompaction(默认开):插件在某个 profile 首次启动时换用只留对话的压缩,原版配置留 .bak 备份。 · 人设:装上插件后替换 DSH 自带的身份行,已有的人设不覆盖;控制台提示文字同步更新。 · 守卫拦截会话时写日志,写明原因、会话和仍在其上的记忆块位置与类型,不记录任何文本。 · 微信和 QQ 默认关闭;已经在用微信的世界(存在 wechat-outbox.sqlite)升级后保持开启,控制台开关会明确保存。 · 新增 NOTES.md 统一收纳全部注意事项,README 指向它,并说明已拓展微信与 QQ 模块、QQ 仍需外部 SnowLuma 及 @snowluma/sdk。 · 宿主已验证兼容清单加入 0.2.1-rc.5:宿主包类型检查零错误,测试全过,桌面应用包与 rc.3 对比,我们依赖的宿主包除版本号外无变化;版本范围不变。
v0.6.52026-10-30
本版修复记忆块刷新后埋在长历史中间、attach 与每步退役写出坏日志和微信发送前快照超时卡进人工核对三个问题,减少微信群上下文的 token 开销,新增按需看群图片和插件自带的表情库,并让每日回顾后自动压缩、装上插件默认换用只留对话的压缩。 · 下载与安装 npm:0.6.5 已发布到 npm,dsh-world@latest 即本版。 已有 world 升级:正常退出 DSH,下载本页 Assets 中的 dsh-world-0.6.5.tgz(与 npm 上发布的安装包为同一文件),用 scripts/update-world.mjs 指定原 profile、该安装包和 DSH 自带 pnpm 更新;脚本会先完整备份,失败恢复旧 profile。命令见仓库 已有 world 升级。 首次安装:在正在使用的 DSH profile 目录,用 DSH 自带的 pnpm 从 npm 安装: Set-Location "/profiles/" node "" add dsh-world@latest --ignore-scripts --registry= 之后仍需将 dsh-world 加入 profile 的 bundles 并配置插件,见仓库 安装说明。 升级沿用原 profile、worldId 和世界目录,保留她的人设、世界提示词、房间文件和日记。使用微信适配器时同步更新并重启适配器,保留账号配置、游标、发送队列和回执。 · 升级后默认行为有两处变化 · 每日回顾后自动压缩默认开:控制台概览的「回顾后自动压缩」可以关。每晚会多一次摘要调用。 · 首次启动默认把 profile 的压缩换成只留对话的压缩:会先备份 cordis.patch.yml,重启 DSH 后生效,整个 profile 都会受影响(写代码等工作区的会话压缩时也会去掉工具调用过程)。不想换,在 dsh-world 的配置里写 replaceCompaction: false。 · 主要变化 · 修复记忆块刷新后模型“看不见”的问题(#21):旧块原地替换会让新块一直留在历史中间,长会话里被淹没;现在退役旧块,由正常的追加路径把新块放在末尾。回放用户提供的真实日志验证:刷新后只有一个非空记忆块,位于请求末尾。 · 修复退役记忆块写出无法重载的日志(#22):宿主只在 turn 和 step 都打开时接受空的 system/message,而 attach 发生在两轮之间、pre-step 发生在 step/start 之前。现在 attach 不再写事件,退役改在 agent/request 钩子里写,仍早于请求组装。新增带磁盘重载的回归测试。已经写坏的旧日志不会被自动修复。 · 微信发送前读不到稳定快照时自动重试(#23):只在一个回复的第一条、真正发送之前超时才识别为“确定未发送”,撤销本次尝试写下的状态并由家重新派发,最多 3 次,之后回到原来的“需要人工核对”。发送之后的确认阶段和第 2 条起的超时保持原有保守处理。 · 微信群上下文省 token:默认条数由 8 改为 5(控制台仍可调 1–20,没设置过的用户升级后生效);上下文渲染把渠道、账号和会话信息只写一次,每条只留发言人来源,同样输入约少 45%。QQ 共用同一渲染。 · 新增 wechat_image:wechat_history 里的群图片先显示为未读取,想看哪张用该条的 id 调用;适配器只在已配置群聊按本机缓存读取这一张,作为下一条消息附给她,不推进游标也不清未读。 · 新增插件自带的表情库(世界目录 stickers/),不再依赖 DeepSeek-meme 插件和 stickerDir:sticker_search(按名称、标签查,每次只返回几条,不回传图片)、sticker_save(私聊或群里别人发来的表情包,按消息 ID 取原始动图并核对 md5,同图去重)、sticker_edit、sticker_remove。每张只有名称和标签,没有分组。发送仍用 wechat_send,表情不在库里时排队就被拒绝。旧库用 scripts/import-stickers.mjs 导入一次,QQ 仍用自己的收藏表情。 · 文档说明微信里 @昵称 只是普通文字,不会真的 @ 到人:原生发送没有 @ 列表,靠操作窗口输入会抢焦点,所以不做。 · 每日回顾后自动压缩:她在晚上 23:00 的回顾里会改写「我是谁」,而系统提示只在压缩之后才重新读取,新版要等到下一次压缩才生效。现在回顾那一轮递给她、家空闲后,自动执行一次「应用并压缩家会话」,让新版随压缩一起生效(压缩本来就要重建缓存,不多破坏一次),压缩后最近的聊天作为记忆块重新放回她眼前。默认开,控制台概览的「回顾
v0.6.42026-10-29
本版恢复相册,新增家会话提示词应用入口和 QQ SDK 按需安装,并修复微信独立发送被待核对记录阻塞的问题。从本版起,dsh-world 发布到 npm。 · 下载与安装 首次安装:在正在使用的 DSH profile 目录,用 DSH 自带的 pnpm 从 npm 安装: Set-Location "/profiles/" node "" add dsh-world@latest --ignore-scripts --registry= 之后仍需将 dsh-world 加入 profile 的 bundles 并配置插件,见仓库 安装说明。 已有 world 升级:正常退出 DSH,下载本页 Assets 中的 dsh-world-0.6.4.tgz(与 npm 上发布的安装包为同一文件),用 scripts/update-world.mjs 指定原 profile、该安装包和 DSH 自带 pnpm 更新;脚本会先完整备份,失败恢复旧 profile。命令见 已有 world 升级。GitHub 自动生成的 Source code 是源码,不是预编译安装包。 升级沿用原 profile、worldId 和世界目录,保留她的人设、世界提示词、房间文件和日记。使用微信适配器时同步更新并重启适配器,保留账号配置、游标、发送队列和回执。已有世界升级后,QQ 需要在控制台「概览 → 接入」重新拨开。 · 主要变化 · 恢复家会话的相册工具和控制台独立相册页:收藏本轮图片、分页查看和移除,图片与索引使用同一事务;旧相册导入时保留原文件,不自动将图片放入后续上下文。 · 微信群聊动静随现有闹钟送入家会话:普通群消息只累计持久化的未读数和最后发言信息,不唤醒、不注入正文;成功读取最新页后清零,自己的发言不计未读,过期或离线数据不展示。概况在自定义闹钟模板渲染后追加,不改写个人文件,不规定是否发言。 · QQ 的 SnowLuma SDK 改为可选 peer,首次手动开启 QQ 时缺少依赖就复用宿主包管理器按需安装,完成后提示重启;不使用 QQ 时不安装,失败不重新开启 QQ。移除 postinstall、SDK 文件修补脚本及更新器修补步骤,不自动升级 Node,核心 Node 要求不变。 · 人设和世界提示词页面新增「应用并压缩家会话」:等待家空闲后执行一次,维护期间刷新已保存配置后再放行排队消息;显示进度与失败原因,停止世界取消任务,无可压缩内容时仍刷新配置。 · 记忆块刷新失败时,将具体原因显示在世界面板健康状态中,成功重试后清除;保留原有错误传播,不自动追加可能重复的记忆块。 · 世界控制台新增微信独立页面并恢复 QQ 独立页面入口,概览保留接入开关,详细状态和设置移到各自页面;顶部标签可随可用宽度换行。 · 修复微信入站 pending 冻结独立发送队列(#20):待核对记录继续阻止入站重放,独立发送任务按各自 ID 和回执运行,结果不明的原任务只补报回执、不重发。 · 微信回执、任务领取、状态和群读取结果请求遇到 HTTP 502/503/504 或连接错误时有限退避重试,错误保留响应正文;生成回复的请求保持只发送一次,每次重试重新读取宿主地址和令牌。 · 补充适配器核对与升级运行数据保留说明。 上一个 GitHub Release 是 0.5.7;其间 0.6.0 至 0.6.3 的变化(世界收进工作区、QQ 默认关闭等)见 更新日志。 · 验证与已知范围 · 在 Windows 微信 4.1.15.56 私聊中完成两条真实文字发送验证;任务领取及回执 503 使用本机故障注入,确认没有重复发送。完整 DSH 联动尚未验证。 · QQ SDK 不再随插件安装,首次在控制台手动开启 QQ 时按需安装,完成后需重启 DSH。 · npm 安装包打包于本版文档更新之前,包内 README / INSTALL 仍是旧的安装写法;以仓库中的最新说明为准。 · 完整性校验 同时提供 dsh-world-0.6.4.tgz.sha256。安装包 SHA256: 995c0d6916341b4f9f42389d16496b8863f36585a0a331673d426c6465fc4d6f
数据来自仓库的 GitHub Release,可能与插件实际版本不一致。

README

由 DeepSeek 最新模型翻译生成
dsh-world 给 DSH 里的陪伴角色一个会记得、会生活的世界。 装上以后,她会记得你们在每个窗口里说过的话;有一个自己的家,自己决定接下来做什么、做到几点,想你了会主动来找你;每天晚上回想这一天,写日记,也改写一份关于自己的自述。开关和人设都在 DSH 设置里的「世界控制台」,由你掌握。 插件只用 DSH 原本开放的扩展接口,不改宿主的一行代码。 已拓展到微信和 QQ:除了 DSH 里的窗口,她也能在 微信 和 QQ 里收发消息,私聊和群聊都可以,和家共用同一份记忆、同一个她。 - 微信模块自带 Windows 适配器和原生发送,不依赖 dsh-plugin-weixin 等其他微信插件;只适配指定的微信构建,需要按适配器说明准备 Python 环境,有账号风险,见 注意事项·微信。 - QQ 模块仍然需要外部的 SnowLuma:插件自己连 OneBot,但登录 QQ、提供 OneBot 服务的是需要你另行安装的 SnowLuma,另外还要它的 SDK @snowluma/sdk(首次手动开启 QQ 时按需安装)。微信和 QQ 默认都是关的,要用先在控制台拨开;不用 QQ 时不需要装这些。见 注意事项·QQ。 当前版本 0.6.5。完整变更和升级说明见 更新日志。
展开完整文档(README 剩余 1 节)
dsh-world

给 DSH 里的陪伴角色一个会记得、会生活的世界。

装上以后,她会记得你们在每个窗口里说过的话;有一个自己的家,自己决定接下来做什么、做到几点,想你了会主动来找你;每天晚上回想这一天,写日记,也改写一份关于自己的自述。开关和人设都在 DSH 设置里的「世界控制台」,由你掌握。

插件只用 DSH 原本开放的扩展接口,不改宿主的一行代码。

已拓展到微信和 QQ:除了 DSH 里的窗口,她也能在 微信 和 QQ 里收发消息,私聊和群聊都可以,和家共用同一份记忆、同一个她。

- 微信模块自带 Windows 适配器和原生发送,不依赖 dsh-plugin-weixin 等其他微信插件;只适配指定的微信构建,需要按适配器说明准备 Python 环境,有账号风险,见 注意事项·微信。
- QQ 模块仍然需要外部的 SnowLuma:插件自己连 OneBot,但登录 QQ、提供 OneBot 服务的是需要你另行安装的 SnowLuma,另外还要它的 SDK @snowluma/sdk(首次手动开启 QQ 时按需安装)。微信和 QQ 默认都是关的,要用先在控制台拨开;不用 QQ 时不需要装这些。见 注意事项·QQ。

当前版本 0.6.5。完整变更和升级说明见 更新日志。

她能做到什么

记得:像人一样记

- 近期记忆:你们最近数轮的对话原文,每次开始对话和每次压缩之后都放在她眼前,谁、什么时候、说了什么,一字不差。轮数在控制台里填,默认 200。
- 日记:人生里重要的事,她自己写进日记,一天一篇。这是她的长期记忆。
- 我是谁:她写给自己的一份自述,随着她变化而改写。每晚回顾前,插件会留一份当时的版本,改过的都找得回来。
- 范围内的原文留着:按天归档用户和助手的正文。近期记忆以外的事,她可以自己去翻。

日记和自述都由她自己动笔,插件从不替她写。

为什么不用向量库或记忆系统? 一个人的生活,量没有那么大。在这个量级上,把原文留在眼前、需要时按原话去找,比切碎了再拼回来更准,也少一道会出错的环节。可参考:

- Chan et al., 2024. Don't Do RAG: When Cache-Augmented Generation is All You Need for Knowledge Tasks. arXiv:2412.15605
- Sen et al., 2026. Is Grep All You Need? How Agent Harnesses Reshape Agentic Search. arXiv:2605.15184

生活:她自己的日子

- 家:她有一个自己的会话「<名字>的家」,和一个房间(工作目录),在里面过自己的日子。
- 自己定节奏:她说好接下来做什么、做到几点,到点了再决定继续还是换一件。什么都不定,就休息到第二天早上。
- 主动找你:想你的时候,她可以把一句话送到你面前(Windows 系统通知,或你接上的桌宠等程序)。
- 每日回顾:每天晚上 23:00,她回想当天的聊天和做过的事,写日记,更新「我是谁」。
- 每天额度:可以给家里每天的花费设个上限,超过了会提醒她一次,由她自己决定收尾。
- 大事先问:删改房间外的文件、装软件、花钱、以你的名义对外发消息等,约定好先问你。

世界控制台:开关在你手里

DSH 设置里的「世界控制台」:

- 开始 / 停止:按下开始,她才住进来;按下停止,记忆、人设和生活线一起安静下来,家还在,等你回来。
- 人设:分层写她是谁:名字、她是谁、性格、说话方式、愿景、补充,旁边实时预览她读到的样子。写了以后,它取代 DSH 自带的那句默认身份(“You are an AI agent powered by DeepSeek Harness.”);你已经在 DSH 里设过的系统人设(宿主设置里的人设,或当前预设自带的人设)不会被替换,原样保留,这里写的排在它后面;预设如果已经自己改写了那句默认身份,也按它写的保留,不会被盖掉。全部留空时什么都不改,沿用 DSH 的默认身份和你已有的人设,控制台不自动回填。DSH 里其余的系统提示(计划、工具和文件引用等说明)不动。
- 世界提示词:你想对她说的话,以及她的世界的说明。
- 相册:家会话可用 keep_photo 收藏本轮最新消息中的图片(含本轮已读取的微信图片和引用图),list_photos 分页查看说明,forget_photo 移除收藏。控制台顶部「相册」页查看照片,点开才加载图片;照片不会自动加入之后每轮上下文。旧相册首次打开时导入,原文件保留。
- 应用并压缩家会话:人设和世界提示词页面里的热加载入口,操作方法见注意事项。
- 工作区权限:选择世界工作区新建会话的默认权限,选项沿用宿主提供的权限预设,默认完全权限。保存后对新会话生效;已有会话及其手动权限不会被重新覆盖。
- 概览与记录:她此刻在做什么、下个闹钟、近期记忆有多少轮、今天花了多少;还有活动记录、日记和压缩记录。
- 接入开关:配置里启用了微信(wechat: true)或 QQ(qqNative.enabled: true)后,概览里有一张「接入」卡片,状态记在 world.json。微信开着才注册工具并拉起适配器(配了 wechatAdapter 时),关掉就撤掉;QQ 开着才加载通道,关掉就断开连接。微信和 QQ 都默认关,已经在用微信的世界升级后保持开着。首次手动开启 QQ 时,缺少 SnowLuma SDK 就按需安装,完成后提示重启 DSH;SDK 已就绪时直接切换,无需重启。
- 微信 / QQ 页面:顶部各有一个独立入口,详细状态和设置不再挤在概览里。微信页查看连接、待发送与待核对数量,重启适配器并调整读取条数和图片缓冲;QQ 页管理 OneBot、白名单、静默和 SnowLuma。通道关闭或世界停止时,页面提示未开启。
- 归档范围:默认 workspace,归档家所在工作区的普通会话,包含独立微信群会话;home 仅当前家会话。保存范围后提示重启,重启前沿用原范围。启动时分页回扫所选范围内的会话日志,按消息实际时间重选最近配置轮数,下次请求前替换旧记忆块;没有时间过期。旧归档保留,范围外记录不再注入。旧配置 world 迁为 workspace。
- 注入范围:世界记忆、世界提示词、世界线工具和微信/QQ 通道仅进入世界工作区内匹配预设的普通会话,其他工作区即使用相同预设也不会收到。归档选为 home 时,同工作区的其他会话仍可读取家记忆。
对世界工作区以外的会话,只有两项有影响:控制台人设和只留对话的压缩。详情见 注意事项。

注意事项

容易踩的地方都集中写在 注意事项,按主题分类。第一次装或升级之前,建议先看 默认就会发生的事。

- 安装与升级:默认换用只留对话的压缩。
- 人设与提示词:改了以后要手动应用;控制台人设和 DSH 自带系统提示词怎么共存。
- 压缩与记忆:什么时候自动压缩、每日回顾后自动压缩。
- 世界范围与会话:对世界工作区以外的影响,以及「会话已离开世界工作区」怎么排查。
- 微信:支持的版本、账号风险、图片和表情包、@、退出重开。
- QQ:SnowLuma SDK、群里默认只接被叫到的、看门狗。

只留下你们之间的话的压缩

对话太长需要压缩时,dsh-world 自带的压缩方式会去掉工具调用的过程,把你们之间的交流整理成一段摘要。她记住的是你,不是那些命令。装上插件后它默认就会换上,见 注意事项。

桌宠和其他程序

dsh-world 开放了一个本地的「桥」:桌宠之类的程序可以把你说的话送进她的家,也可以接收她的回复和主动找你的话。协议见文末。

微信作为独立模块接入同一个家,使用她的独立账号收发指定私聊或群聊。她可用 wechat_chats 查询已配置目标,用 wechat_history 主动分页查看群消息,无需等别人 @,历史里的图片用 wechat_image 按消息 ID 一张张看;读完以同一个 chatId 调用 wechat_send 自主联系对方或回复消息,文字、图片和表情共用同一发送队列;wechat_delivery 查询确认结果。普通最终回答不会自动转发到微信。Windows 适配器和配置步骤见 微信模块。B 站尚未接入。

群聊动静:适配器在线时,已配置群里未 @ 她的消息只更新未读数、最后发言人和时间,不唤醒模型,也不把正文加入上下文。她原有的闹钟响起时,会附上一行群聊概况,包括未读消息或安静了多久;是否去看、是否发言,由她自己决定。成功读取群的最新一页后清零未读,自己的发言不计入未读;计数保存在适配器状态中,重启保留。插件不会改写你的 alarm.md、world-prompt.md 或「我是谁」。

微信的支持版本、账号风险、图片与表情包、表情库、@、退出重开等注意事项,见 注意事项·微信;首次接入与升级见 注意事项·安装与升级。

QQ 走插件自己那条原生通道:插件直接连 SnowLuma 提供的 OneBot WebSocket,自己收、自己发(代码在 src/ecosystem/qq-native/),中间没有第二个进程,也不需要别的 QQ 实现。SnowLuma 负责登录 QQ 并对外提供 OneBot 的 HTTP/WS 服务;它按自己的 EULA 不许被自动化脚本部署,装法与参数怎么拿见 INSTALL.md。这条通道的配置都在 profile 的 cordis.patch.yml 里(见下文「设置」),控制台上改过的设置存在世界目录的 qq-native.json。

外部生态接入代码统一放在 src/ecosystem/:wechat/ 包含微信宿主模块、Windows 收发适配器和原生桥;qq-native/ 是插件自己连 OneBot 的那条 QQ 通道(qq/ 里是与它配套的控制台接口和 SnowLuma 控制台那扇门);shared/ 保存通用身份协议、群会话路由与消息出口;bridge/ 为桌宠等本地程序提供通用桥。后续平台在同一目录下独立扩展,核心记忆、人设和生活线保持独立。

微信原生发送引擎单独适用非商业许可,详见该模块的许可说明。

QQ

QQ 走插件自己那条原生通道:直接连 SnowLuma 开出来的 OneBot WebSocket,收文本、发文本,中途没有别的进程。代码在 src/ecosystem/qq-native/。

QQ 的 SDK 依赖、群里默认只接被叫到的、看门狗,以及 QQ 的记忆和接入开关,见 注意事项·QQ。

在 profile 的 cordis.patch.yml 里打开 qqNative(enabled: true 只是允许它存在)、填上 WS 地址与 token,再到控制台「概览 → 接入」把 QQ 拨开,切到顶部「QQ」页查看:连着哪个地址、收过几个会话、发过几条、挡下几条、排队待发几条、会自己回还是只看不回,一眼看到。页面里能直接拨「会自己回话 / 只看不回」,设「静默到某个时间点」(只收不回,到点自己醒),改私聊和群的白名单(留空就是谁都不收,改完不用重启),也能打开 SnowLuma 控制台、手动拉起 SnowLuma。这些改动记在世界目录的 qq-native.json,盖在配置之上。没配 qqNative.enabled 时,QQ 页提示通道未开启。

参数不对不会崩,只会连不上:卡上会把原因写在 lastError 里(比如 WS 错误: Unexpected server response: 401,说明填的是 HTTP 那份 token,该换成 WebSocket 那份)。QQ 页在通道启用、世界已经开始时展示详细状态,其他时候提示未开启。

她怎么说话:同一会话 batchQuietMs(默认 10 秒)内连着来的几句攒成一条再问她(最多等 30 秒),群里每句前面带着是谁说的。她的回答按空行分成几条发,中间停一下;回话里写 [[img:路径]]、[[face:id]]、[[at:QQ号]] 会变成图片、QQ 表情和 @,[[sticker:开心]] 按备注挑一个收藏表情单发(也可以写第几个),[[qzone:正文]] 发一条所有人可见的 QQ 空间说说。发不出去的消息先排队,每 3 秒重试,最多留 5 分钟。她在家里自己开的那一轮(闹钟、世界线)说完的话,也会推一份给主人(ownerQQ,空着取 allowPrivate 的第一个);有人说话的轮次是在回那个人,不另推。
卡上那个「打开 SnowLuma 控制台」按钮,会读取 snowlumaHome 下 config/runtime.json 里的地址与端口,带着一次性登录票据打开系统浏览器。第一次要先填一次 SnowLuma 的面板密码,之后记在世界目录的 panel.json 里(权限 600),不用再输。

安装

需要 DSH 桌面版,世界控制台和生活线都依赖它。

最省事的办法:把这个仓库地址交给她,让她照 INSTALL.md 自己装。那份说明是写给模型看的——每一步都有命令、判定和失败对照表,连同 QQ 怎么接进来、哪两个动作必须人来做,一路写到底。

自己装:dsh-world 已发布到 npm。在你的 DSH profile 目录用 DSH 自带的 pnpm 安装:

node <DSH 自带 pnpm 的入口文件> add dsh-world@latest --ignore-scripts --registry=https://registry.npmjs.org/

装好后按 安装说明 在 profile 里登记 bundle,重启 DSH,打开设置里的「世界控制台」,按需填写人设,按「开始」。

想用仓库源码时,执行 npm ci、npm pack,再用同一个 pnpm 把生成的 dsh-world-*.tgz 装进 profile;也可从 CI 对应运行的 Artifacts 下载检查通过的编译安装包,Windows 和 Linux 分别提供产物。不要用 link: 指向项目目录,否则会加载项目自己的一份 Cordis。本机复现检查的命令见 贡献协议。

已有 world 更新:正常退出 DSH 后,用 scripts/update-world.mjs 指定原 profile、.tgz 和 DSH 自带 pnpm;.tgz 可直接从 npm 下载,例如 <https://registry.npmjs.org/dsh-world/-/dsh-world-0.6.4.tgz>。脚本先备份完整 profile、世界及会话,再更新并校验;失败恢复旧 profile,保留她已有文件。安装成品无需 Git、npm 或 TypeScript,完整命令与恢复说明见 已有 world 升级。

只留对话的压缩:装好 dsh-world 后第一次启动,默认会把 profile 的压缩换成 dsh-world/compaction(先备份,重启 DSH 后生效),整个 profile 的会话压缩都会受影响。怎么关、怎么手动启用,见 注意事项·安装与升级。

设置

大多数东西在世界控制台里改。其余的写在 profile 的 cordis.patch.yml 里,按 id 覆盖插件那一行,只写想改的项:

- id: dsh-world
name: dsh-world
config:
companionName: 小鱼 # 她的名字(控制台人设里写了名字时以人设为准),默认 TA partnerName: 伙伴 # 她对你的称呼,默认 伙伴 worldId: default # 世界名;换一个就是另一个世界、另一份记忆 agentPreset: standard # 她所在的预设 timeZone: Asia/Seoul # 默认系统时区 life: true # 生活线,默认开启 replaceCompaction: true # 首次启动把 profile 的压缩换成 dsh-world 的只留对话压缩;false = 不动 archiveScope: workspace # workspace:家的工作区;home:仅当前家会话 fallbackWakeTime: '09:00' # 没定闹钟时,早上几点叫醒她 diaryDir: C:/path/to/日记 # 日记目录,默认在世界目录里 toast: true # 主动找你时发 Windows 系统通知 toastAppId: com.deepseek.dsh # 通知身份,默认在开始菜单里找 DSH 桌面版(com.deepseek.dsh 或 electron.app.DeepSeek Harness) bridge: false # 打开本地的桥 wechat: false # 打开独立微信接口,需另行启动 Windows 适配器
outlets: [] # 接收她的话的本地程序,见文末
allowedHosts: [] # 通过反向代理从局域网访问控制台时,放行的域名或 IP
qqNative: # 插件自己连 OneBot(原生通道);不写这一块就是不接 QQ enabled: false # 打开通道:连上、控制台里出 QQ 卡 wsUrl: ws://127.0.0.1:3003 # OneBot 的 WS 服务地址(不是 HTTP 那个) accessToken: '' # OneBot WS 服务端自己的 token,与 HTTP 那份不是一码事
allowPrivate: [] # 谁能私聊她;留空 = 谁都不理
ownerQQ: '' # 她自己开口的话推给谁;空着取 allowPrivate 的第一个
allowGroups: [] # 群白名单
autoReply: true # false = 只看不回 contextMessages: 6 # 每轮带上最近的几条 batchQuietMs: 10000 # 同一会话这几毫秒内的话攒成一条问她;0 = 一条一问 groupTrigger: mention # mention:@ 她/引用她/命中关键词才接;all:每句都接
groupKeywords: [] # groupTrigger: mention 时算「在叫她」的词
mutedUntil: '' # 静默到这个时间(ISO):只收不回,到点自己醒 bindHomeSession: owner # owner:主人私聊用家会话、群各自独立;all:都用;none:各建一个 snowlumaHome: '' # SnowLuma 安装目录:控制台那扇门、看门狗和「拉起 SnowLuma」都靠它 supervise: true # 看门狗:端口不通就把 SnowLuma 拉起来

压缩的配置写在压缩那一行的 config 里(profile 的 cordis.patch.yml 中 name: 'dsh-world/compaction' 那一条),不是上面 dsh-world 这一行:

- id: compaction-basic
name: 'dsh-world/compaction'
config:
thresholdRatio: 0.75 # 用量超过上下文窗口的这个比例就压缩,默认 0.75 defaultContextWindow: 1048576 # 适配器没声明窗口的模型按这个估算,默认 1M auto: true # false = 只手动压缩(「应用并压缩家会话」仍可用) maxTokens: 65536 # 压缩时摘要回复的长度上限 headroomTokens: 65536 # 不再影响触发点;只在没写 maxTokens 时当作摘要回复的长度 maxOverflowRetries: 1 # 请求被模型以“超出窗口”拒绝后,压缩重试的次数
modelPolicies: [] # 按 provider/model 单独写上面的项,例如给一个窗口只有 128k 的自建模型写 defaultContextWindow

触发点怎么算、窗口值从哪来,见 注意事项。

改她的措辞:世界提示词可以直接在控制台里改。闹钟响时、提前停下时、每日回顾时她收到的话,在世界目录里放一份 alarm.md 就能按段覆盖,段落名和可用的占位符见 templates/alarm.md。插件写给她的话一律用第一人称「我」,读起来是她自己的念头。

时间:建议把预设里 time-context 条目的 refreshIntervalMs 设为 0,让她每一步都知道现在几点。

她的东西放在哪

都在 <DSH_HOME>/worlds/<worldId>/ 下(DSH_HOME 默认是用户目录下的 .dsh):

| 位置 | 是什么 |
| conversations/ | 按天归档的聊天原文(给人看的导出,正本在 archive.sqlite) |
| room/ | 她的房间;room/我是谁.md 是她的自述 |
| diary/ | 她的日记(可用 diaryDir 换位置) |
| persona.md、world-prompt.md、alarm.md | 你写给她的人设、世界提示词和闹钟措辞 |
| world.json | 世界是否在运行、每天额度、近期记忆轮数和选定归档范围 |
| activity/ | 她在家里用过的工具,只记录,不进记忆 |
| photos/album.sqlite | 收藏的图片、说明与标签;首次导入旧相册后仍保留原文件 |
| wechat.json | 本机微信模块的地址、令牌和协议版本,不应公开 |
| wechat-outbox.sqlite | 微信工具安排的发送队列和确认状态 |
| qq-native.json | 控制台上 QQ 卡改过的设置(会不会自己回话、静默到几点、白名单、阳台端口),盖在 profile 默认之上 |
| panel.json | SnowLuma 控制台那扇门的登录票据,权限 600,不应公开 |

备份时整个目录一起备份即可,最好先停止 DSH。

桥与推送协议

给桌宠等本地程序用。

把话送进她的家(bridge: true):插件启动时写出 <世界目录>/bridge.json,内容是 { origin, token, name, ... }。向 POST {origin}/dsh-world/bridge/say 发 { "text": "..." },请求头带 x-dsh-world-token: <token>,会立即返回 202。这句话会作为你本人说的话进入她的家和记忆。

接收她的话(outlets):每个目标写一个 name,地址用 url(其中 {origin} 会被替换),或者用 urlFile + path(端口会变的程序用这个);再用 kinds 选择要接收哪些:reply 是桥上那句话的回复,busy 表示她正忙,reach 是她主动找你。插件会向目标 POST:

{ "text": "她的话(纯文本)", "kind": "reply", "name": "她的名字", "images": ["http://…"], "image": "表情名" }

目标回复 2xx 就算送到。送不到的会显示在控制台的「健康」里。

参与贡献

PR 统一提到 dev 分支,main 由维护者从 dev 并入后发布,详见 贡献协议。新增 QQ、B 站等生态模块前,请阅读 贡献协议:平台代码放在 src/ecosystem/<channel>/,复用统一身份、会话和归档能力;涉及内核的修改必须说明原因、影响、兼容性与验证结果。几条硬性要求:一个 PR 只做一件事;平台 SDK 只能是可选依赖,模块默认关闭,新依赖要先开 Issue;她的主动性来自她自己的安排,插件不往对话里推提醒,改动生活线核心或给她新增工具之前先开 Issue 讨论。

许可

MIT
预览分享卡片长什么样 ↓chenkezhen480/dsh-world
分享 · DeepSeek Harness Hub
chenkezhen480/dsh-world

给鲸鲸一个完整的世界

回到顶部