dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
DSH 多人联机剧情房间:AI 主持、共享故事线,支持 Galgame / 海龟汤 / 剧本杀,可导入剧情包、子代理与地图。 Multiplayer story-party plugin for DeepSeek Harness — shared AI-driven rooms for galgame, turtle soup and mystery, with story packs, sub-agents and maps.
作者:B站:喵诺澪染 · 代码许可:MIT · 内置立绘:CC BY-NC-SA 4.0(非商业) · 开源免费,禁止倒卖
如果你是付费购买的,请立即申请退款并举报卖家——本项目从未授权任何人售卖。
联机 Galgame:房间 API + 房间独立 LLM 会话 + 广播 + 可直接打开的网页房间。 阶段 1(服务端)与阶段 2(房间页)已完成;阶段 3(与 galgame 舞台结合)未开始。 v0.2.0 起支持:剧本杀(角色本 + 私聊 + 阶段机)、海龟汤私有汤底、主代理自动点名子代理、舞台场景同步与选项投票、AI 画我猜(单人)。
房间服务(本插件自己的端口,默认 7302)
├─ 房间生命周期:建房 / 凭邀请令牌加入 / 职位 / 踢人 / 关闭
├─ 共享消息流:用户与 AI 的消息同一条 seq,SSE 广播 + ?since= 增量拉取
├─ 私聊:剧本杀里玩家 ↔ GM 的私密消息,第三方与 SSE 都收不到
├─ 发言调度:玩家/GM 发言防抖合并成一轮,AI 自己判断接不接话(<silent>)
├─ 角色本:每个角色一份 secret,只下发给扮演者与 GM
├─ 阶段机:阅读 → 自我介绍 → 搜证 → 讨论 → 投票 → 复盘
├─ 房间页:/room/<房号>?t=<邀请令牌>,浏览器直接进
└─ 房间独立上下文:每个房间一份 system + 消息历史,sessionId = galgame-room:<房号>
剧本杀角色本(玩家只能看到自己那份):

GM 视角:能看全部角色本、指派角色:

私聊只发给 GM,第三方看不到:

海龟汤汤底只有 GM 能打开:

个人本:章节条 + AI 建议选项,输入框仍然可用:

制作页的个人本设置:章节目标、关键选项、结局条件:

舞台:背景、立绘、字幕;两个浏览器不刷新同步:


内置「鲸鱼娘」:头像和舞台立绘都来自包内非商业素材(CC BY-NC-SA 4.0):

个人资料页:统一换头像和昵称:

AI 画我猜(单人):AI 用几何图形画,你来猜:

方式一:GitHub(推荐,不用注册 npm)
DSH 桌面版:设置 → 插件 → 添加插件,填仓库地址:
https://github.com/miaonuo-lingran/dsh-story-party
或到仓库 Releases 下载 dsh-story-party-*.tgz,在「添加插件」里选本地文件安装。
方式二:npm(可选,发布后可用)
dsh plugin --profile desktop add dsh-story-party
方式三:本地目录(开发用)
path/to/dsh-story-party
assets/characters/deepseek/portraits/neutral.webp
是第三方衍生素材,不是 MIT;仅限非商业使用,必须保留完整署名链,衍生同许可。
详见 NOTICE 与 LICENSE-ARTWORK。maid-atelier 皮肤立绘)→ @lanxing/dsh-galgame(本插件直接取用)
→ 本插件。assets/characters/ 并移除 src/room-server.js 里的 BUILTIN_CARDS,代码仍可正常使用。package.json 的 author、LICENSE、README<meta name="author"> 与页脚 / 房间水印X-Plugin-Author、/api/health 的 authorpack.json 的 generator / brand 字段src/room-server.js 房间核心(零 DSH 依赖,standalone 与插件共用同一份)
src/draw.js AI 画我猜游戏核心(出题 / 判分 / 兜底题库)
src/zip.js 零依赖 zip 读取(stored / deflate,带上限与路径校验)
src/index.js Host 插件:接 ctx.llm + resolveDshHome + cosplay 角色库
src/standalone.js 不启动 DSH 的直跑入口(mock 模型,用于 curl 自检)
public/room.html 房间页(阶段 2)
public/room.css 房间页样式(开房页 / 房间页 / 制作页 / 画我猜共用)
public/room.js 房间页逻辑(SSE + fetch)
public/host.html 开房页(创建 / 加入 + 人设卡 + 剧情包)
public/host.js 开房页逻辑
public/make.html 剧情包制作页
public/make.js 制作页逻辑 + 浏览器端零依赖 zip 打包
public/profile.html 个人资料页(头像 / 昵称)
public/profile.js 个人资料页逻辑(本机 localStorage)
public/draw.html AI 画我猜页面(单人)
public/draw.js 画我猜页面逻辑(SVG 渲染 + 猜词)
client/client.js DSH 浏览器半侧:「联机模式」标签页(iframe 嵌房间页)
assets/icon.svg 插件图标(插件管理里显示)
assets/characters/ 内置「鲸鱼娘」立绘(CC BY-NC-SA 4.0,非 MIT;见 NOTICE)
LICENSE 代码 MIT 许可
LICENSE-ARTWORK 内置立绘的 CC BY-NC-SA 4.0 许可全文
NOTICE 立绘署名链与使用限制
scripts/acceptance.ps1 一键验收脚本
scripts/smoke-events.mjs 无浏览器的页面契约冒烟测试
scripts/card-test.mjs cosplay 人设卡集成测试
scripts/pack-test.mjs 剧情包导入 / 建房 / zip-slip 测试
scripts/mystery-test.mjs 剧本杀:角色本 / 私聊 / 阶段机 / 真相不泄露
scripts/solo-test.mjs 个人本:solo 字段 / 主角 / 章节 / 选项剥离
scripts/save-test.mjs 个人本:存档 / 读档 / 回退 / 长期记忆
scripts/scene-test.mjs 舞台:素材路由 / scene 同步 / AI <scene> / 选项投票
scripts/draw-test.mjs AI 画我猜:出题 / 猜词 / 计分 / 兜底题库
scripts/soup-test.mjs 海龟汤私有汤底:导入 / GM 接口 / 揭晓提示词
scripts/check-els.mjs 前端 els 引用检查
scripts/install-dsh.ps1 装进 profile 的脚本(复制式,备份 package.json)
cordis.patch.yml 插件挂载声明 + 默认配置
mock 模型只在「提问 / 叫旁白 / GM 推进」时接话,其余输出 <silent>,用来验证选择性发言。
cd dsh-story-party
$env:GALGAME_ROOM_PORT = '7302'
node src/standalone.js
另开一个窗口跑完整体验:
Invoke-Expression (Get-Content -Raw -Encoding UTF8 'dsh-story-party\scripts\acceptance.ps1')
也可以用
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\acceptance.ps1。 脚本会把curl.exe的响应先写到文件、再按 UTF-8 读回来解析——Windows PowerShell 5.1 在中文系统上默认用 GBK 解码子进程输出,直接curl | ConvertFrom-Json会把中文 JSON 拆成乱码并报':' or '}' expected。
脚本会依次演示:建房 → 玩家加入 → 观众加入 → 带问句的发言(AI 接话)→ 观众发言(不进上下文) → 闲聊(AI 沉默)→ 拉历史 → GM 推进(强制开口)→ 增量拉取 → 成员列表 → SSE 实时广播。
房主先开房:浏览器打开 http://<本机局域网 IP>:7302/。首屏是三个选项:
.zip),不展示邀请链接和参与者,别人 join 会被拒(403)。建房后会自动以 GM 身份进入房间页;把「复制邀请链接」得到的地址发给朋友即可。
http://<这台电脑的局域网 IP>:7302/room/<房号>?t=<邀请令牌>
localStorage,刷新不用重进;127.0.0.1;开房页会列出本机全部局域网地址。两个窗口测:同一浏览器开两个窗口,一个用邀请链接以「玩家」进,另一个开无痕窗口 以「观众」进,互相发一句,就能同时看到对方和旁白的消息。
无浏览器冒烟测试(验证页面依赖的接口与 SSE 字段):
node scripts/smoke-events.mjs
开房页的「人设卡」下拉会自动列出 cosplay 插件里的角色库,以及一个内置的「鲸鱼娘」。 选中后:
description / personality / system_prompt / rules / behavior / mes_example 进 system promptscenario 作为房间的世界观与开场设定(自己填了则以自己填的为准)first_mes 作为开场白,建房后直接出现在消息流里数据来源:$DSH_HOME/profiles/<profile>/cordis.patch.yml 里 cosplay-core 的
config.roles,用 js-yaml 读取(跟随 profile 的依赖),结果缓存 15 秒——
在 cosplay 里改完卡,稍等十几秒再建房就是新的。
注意:读取角色库是宿主侧代码,装/改完要**重载插件(开关关→开)**才生效, 只刷新页面不够。
无浏览器验证(注入一张假卡,验证建房、开场白、system prompt):
node scripts/card-test.mjs
发布者把「世界观 + 人物卡 + 背景素材」打成一个 zip,别人导入就能直接开房,类似 MC 整合包。
story-pack.zip
├─ pack.json
├─ scenario.md
├─ characters/1.json
└─ assets/...(可选)
pack.json:
{
"format": "dsh-galgame-pack",
"formatVersion": 1,
"name": "老式公寓的夏天",
"version": "1.0.0",
"author": "xxx",
"description": "一句话简介",
"mode": "roleplay",
"scenario": "scenario.md",
"truth": "汤底 / 完整真相(只有 GM 与 AI 能看到)",
"solo": {
"mode": "guided",
"protagonist": "player",
"premise": "你和学妹在旧公寓同居的第三个月。",
"chapters": [
{
"id": "ch1",
"title": "雨夜",
"goal": "让小柚放下戒心",
"choices": ["追问她为什么搬来", "先转移话题"]
}
],
"endings": [{ "id": "good", "title": "雨停了", "condition": "好感度达到 5,且聊过她的过去" }]
},
"characters": ["characters/1.json"],
"assets": ["assets/bg.png"]
}
人物卡兼容酒馆 v2 字段:name / emoji / description / personality / scenario / first_mes / mes_example / system_prompt / rules / behavior。
另外支持:
secret:角色本 / 秘密,只发给扮演该角色的玩家与 GM;不会出现在公开消息、房间公开信息或剧情包详情里playerBrief:玩家须知,领取角色后可见playedBy:ai / human / either;剧本杀里人类角色由玩家领取,AI 角色进子代理名册likes / favoritePlaces / relations:喜爱、常去地点、人物关系solo:个人本设置,全部字段可选;mode 是 free / guided / scripted,
protagonist 写人物 id(建议该人物标 playedBy: human 或 either),
chapters[].choices 是作者写的关键选项(软建议,不锁自由输入)建房时:包里的 scenario 当世界观,选中人物的卡当人设,first_mes 当开场白。
truth 只存在房主主机的房间 JSON 与系统提示词里;列表 / 详情 / 房间公开接口只返回 hasTruth。
浏览器打开 http://<本机>:7302/make:填包名、世界观、人物卡,可选几张背景图,
然后「下载 .zip」或「装进本机」。打包在浏览器端完成(stored zip、零依赖);
装进本机后回开房页,在「角色」下拉里就能选。
制作页会按包类型只显示需要的字段:
开房页「剧情包」一栏选 .zip → 点「导入 .zip」,之后「角色」下拉会出现
「剧情包 · xxx(n 人)」分组。
../ 与绝对路径(zip-slip);$DSH_HOME/galgame-room/packs/<id>/assets/,阶段 3 舞台用。avatar;
导入后 AI 消息的头像用它,房主建房时就能看到。手写包也可以让 avatar 填 assets/xxx.pngpack.json 的 mode,建房后按类型给系统提示词追加规则(海龟汤只答是/不是/无关,剧本杀按阶段推进)pos);打包进 map.locations(带 parent)/ map.routes,房间系统提示带【地图】路径gender;拼提示词时会写成「扮演『小柚』(女)」,模型不会把性别写反recommendedPlayers {min,max},开房页分组标题会显示(如「建议 2-4 人」);勾「单人本」直接写成 {1,1}ai / human / either;人类扮演可填「玩家须知」(playerBrief),入包保存/make 里的可视化编辑——拖动人物摆位置,从人物右侧「+」拉线到另一个人物,在弹出框里写关系(可勾「双向」);打包时按出边 / 双向边写进人物卡 relations,房间的【人物关系】段落会喂给模型开房页的「自我游玩」就是个人本入口:单人房间,只有你和 AI,不生成邀请链接,别人进不来。
solo.protagonist,该角色由你扮演,AI 当旁白并扮演其他角色;
没写就是第一人称「你」<choices>...</choices> 包起来;服务端会把标记从正文剥掉,
存进 room.story.choices,房间页渲染成选项 chipsmode 为 free / guided / scripted 时引导强度不同story:章节进度、当前选项、主角;SSE 增加 story 事件当前进度:选项、章节、主角、结局提示、自动/手动存档、回退一步、长期记忆已经通了;
独立的 /play 视觉小说页、结局收集、多存档导出还在后续版本。
存档面板(自动存档每回合更新,手动最多 5 个):

长期记忆(AI 提议更新,也可以手动改):

story、舞台和摘要;
「回退一步」就是回到 AI 开口之前room.story.memory 分四类——事实、人物关系、好感、物品。
AI 在回复末尾可以输出:<memory>{"facts":["小柚住在隔壁"],"relations":{"小柚":"开始信任你"},"affection":{"小柚":1},"items":["旧钥匙"]}</memory>
服务端会剥掉标记、合并进记忆(事实/物品去重,好感限制在 -100..100),再从系统提示词喂给下一轮。 也可以在房间右上角「记忆」里手动编辑。
相关接口:
| 方法 | 路径 | 鉴权 | 说明 |
|---|---|---|---|
| GET / POST | /api/rooms/:id/saves | 成员 | 存档列表 / 新建手动存档({name}) |
| POST | /api/rooms/:id/saves/:saveId/load | 成员 | 读档(saveId=auto 读自动存档) |
| DELETE | /api/rooms/:id/saves/:saveId | 成员 | 删除手动存档 |
| POST | /api/rooms/:id/rewind | 成员 | 回退一步(回到自动存档) |
| GET / PATCH | /api/rooms/:id/memory | 成员 | 读取 / 覆盖长期记忆 |
SSE 增加 restore(读档/回退后整份重渲染)与 saves 事件。
房间页顶部可以显示一块 galgame 舞台:
scene.background:背景图,只能来自剧情包 assets/scene.sprites:立绘列表,{ characterId, pos: left|center|right, emotion }scene.bgm:BGM,只能来自剧情包 assets/ 里的音频scene.caption:舞台字幕两种改法:
scene,
所有客户端不刷新就跟过去<scene>{"background":"assets/bg.png","sprites":[{"characterId":"yuzu","pos":"left","emotion":"smile"}],"bgm":"assets/rain.mp3","caption":"雨夜。"}</scene>
服务端会剥掉标记、校验素材与角色,再广播给所有人。素材路由:
GET /pack-assets/<packId>/<filename>
只提供 png/jpeg/webp/gif 与 mp3/ogg/wav/m4a/aac,拒绝 ../、绝对路径和 svg。
选项投票:
相关接口:
| 方法 | 路径 | 鉴权 | 说明 |
|---|---|---|---|
| GET / POST | /api/rooms/:id/scene | 邀请或成员 / GM | 读取 / 设置舞台 |
| POST | /api/rooms/:id/choice | 成员 / GM | 选项投票:start / cast / cancel |
| GET | /pack-assets/:packId/:file | 无 | 剧情包素材(图片 / 音频) |
BGM 受浏览器自动播放限制,第一次需要玩家点一下「BGM 播放」。
开房页的「🎨 AI 画我猜(单人)」或直接打开 /draw:
图形协议(只允许这些,避免文字泄题和 SVG 注入):
{
"answer": "雨伞",
"aliases": ["伞"],
"hint": "下雨天会用到",
"shapes": [
{ "type": "polygon", "points": [[50,12],[16,46],[84,46]], "fill": "#e05a5a" },
{ "type": "line", "x1": 50, "y1": 46, "x2": 50, "y2": 88, "stroke": "#6b4f2a", "strokeWidth": 3 }
]
}
允许 circle / ellipse / rect / line / polyline / polygon,坐标 0–100;text / image / path
一律丢弃。答案只在猜对或跳过后才下发。
相关接口:
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /api/draw/sessions | 新建一局({rounds},默认 5) |
| GET | /api/draw/sessions/:id | 当前状态(不含未揭晓答案) |
| POST | /api/draw/sessions/:id/next | 下一题 |
| POST | /api/draw/sessions/:id/guess | 猜词({text}) |
| POST | /api/draw/sessions/:id/skip | 跳过并揭晓 |
| POST | /api/draw/sessions/:id/hint | 提示字数 / 首字 |
会话存在内存里,重启房间服务会清空;它是单人小游戏,不做跨设备同步。
建房时可以设一个密码,进房的人必须输对才能进:
hasPassword,不返回任何哈希PATCH /api/rooms/:id {"password":"新密码"},传空串 = 取消密码开房页顶部「个人资料」进入 /profile:
join 一起提交;房主那边能看到注意:换浏览器 / 清站点数据 = 个人资料丢失;它不是账号,也不做跨设备同步。
uid(u_ + 10 位十六进制),进房时生成identities.json 记这层绑定开房页的「记录 AI 思维链」勾选框,由房主控制:
reasoning=off,思维链留在房间 JSON 的 debug 字段(最近 20 条)GET/POST /api/settings {"saveReasoning": true} 控制,选择存 settings.json剧情包里除主角外的 AI 角色会自动进房间名册(room.agents),每个角色一个子代理:
POST /api/rooms/:id/speaklocation 和接下来的打算 plan:子代理输出一行 JSON(line / location / plan),主代理在名册里能看到「她在哪、打算去哪」,用来决定该唤起谁剧情包里的 AI 角色除了 GM 手动「让她接话」,主代理也可以自己点名:
<speak 角色名>/speak 仍然可用剧情包 mode = "mystery" 时,建房会自动进入剧本杀模式:
secret 只下发给扮演者与 GM;玩家领取角色后点右上角「角色本」查看。
一个成员同时只能持有一个角色;GM 可以在「角色本」弹窗里指派 / 释放,观众不能领取。truth(完整真相)拼进系统提示词,但公开接口仍然不返回它。相关接口:
| 方法 | 路径 | 鉴权 | 说明 |
|---|---|---|---|
| GET | /api/rooms/:id/roles | 成员 | 角色名单 + 自己的角色本(GM 看全部) |
| POST | /api/rooms/:id/roles | 成员 / GM | claim 领取 / assign 指派 / release 释放 |
| POST | /api/rooms/:id/phase | GM | next 下一阶段 / set 指定阶段(narrate:false 不触发 AI) |
| GET | /api/rooms/:id/truth | GM | 读取汤底 / 真相正文 |
| POST | /api/rooms/:id/messages | 成员 | 带 to: <成员id> 时发私聊 |
制作页的「汤底 / 真相」一栏会写进 pack.json 的 truth(也可以放 truth.md):
hasTruth,玩家读不到正文;开房页的「长局自动摘要」默认开启:每攒够 max(20, 读取条数) 条未摘要的消息,就让模型压成一段 300 字以内的摘要,存在房间的 summary 字段里。之后发给模型的是「摘要 + 最近 N 条」,比每次重发全量便宜,也不会丢早期剧情。房主可以关掉它。
房间数据一直在房主机器上($DSH_HOME/galgame-room/rooms/),DSH 重启也不丢;
AI 的上下文会从最近 contextMessages 条消息重建。
开房页「继续上次没玩完的局」会列出本机开过的房间:
public/dialog.js),不再弹 Electron 原生 confirm玩家那边不用做任何事:本地副本先显示,再和房主对齐。
「联机模式」标签页默认显示本机房间(自己开房)。要进别人的房间:
?v=本机版本),加入前会先请求对方
GET /api/version,版本必须与本机一致;不一致直接提示,不会跳转标签页顶部只保留:本机插件版本 + 「回本机」(加入房间不再重复做一份)。
?sid= 会把当前 DSH 会话 id 记进房间
(room.sessionId,宿主侧可见)localStorage,最近 200 条消息 + 会话 id + seq)版本门禁两种力度:
cordis.patch.yml 里 strictVersion: true,进房必须携带
clientVersion 且与房主一致,浏览器直连会被拒(409)这个比对只挡「版本不一致导致的接口差异」,不是安全边界。
127.0.0.1:7302:
https://xxx.sakurafrp.com 域名,自动 HTTPSfrp-boy.com:56804 这种「域名:端口」,没有 https$DSH_HOME/galgame-room/publicUrl.json,
立即生效,不用重载插件);也可以写在插件配置 publicUrl 里地址稳定性:隧道「停止→启动」通常保留原端口;删除再新建会重新分配(TCP 的 自动端口会变)。地址变了就回到开房页改「公网地址」,旧邀请链接随之作废、重新复制一份。
鉴权统一走 Authorization: Bearer <令牌> 或 ?t=<令牌>:
| 方法 | 路径 | 鉴权 | 说明 |
|---|---|---|---|
| GET | / | 无 | 开房页(创建 / 加入 两种模式) |
| GET | /api/health | 无 | 存活检查 |
| GET | /api/version | 无 | 插件版本 + 协议版本 + 是否强制版本校验 |
| GET / POST | /api/settings | 无 | 房主侧调试开关(saveReasoning) |
| POST | /api/public-url | 无 | 运行时改公网地址(存 publicUrl.json) |
| GET | /api/network | 无 | 本机局域网地址(开房页展示用) |
| GET | /api/cards | 无 | cosplay 角色库(开房页人设卡下拉) |
| GET | /api/packs | 无 | 已导入的剧情包列表 |
| POST | /api/packs | 无 | 上传剧情包(body = zip 原始字节) |
| GET | /api/packs/:id | 无 | 剧情包详情(不含 truth / secret / playerBrief) |
| DELETE | /api/packs/:id | 无 | 删除剧情包 |
| GET | /make | 无 | 剧情包制作页 |
| POST | /api/port | 无 | 开放 / 切换本机端口({port},失败保持原端口) |
| GET | /room/:id | 无 | 房间页(页面内再要邀请令牌) |
| GET | /room-assets/room.css | room.js | host.js | 无 | 页面样式与脚本 |
| POST | /api/rooms | 无 | 建房,返回房号 / 邀请令牌 / GM 令牌 |
| GET | /api/rooms | 无 | 房间列表(不含令牌与消息) |
| GET | /api/rooms/:id | 邀请或成员 | 房间公开信息 |
| PATCH | /api/rooms/:id | GM | 改标题 / 世界观设定 |
| DELETE | /api/rooms/:id | GM | 关闭房间 |
| POST | /api/rooms/:id/join | 邀请 | 加入(role = player / spectator) |
| GET | /api/rooms/:id/members | 邀请或成员 | 成员列表 |
| PATCH | /api/rooms/:id/members/:mid | GM | 改职位(player / spectator) |
| DELETE | /api/rooms/:id/members/:mid | GM | 踢人 |
| POST | /api/rooms/:id/messages | 成员 | 发言;带 to: <成员id> = 私聊(观众只进消息流、不进 AI 上下文) |
| GET | /api/rooms/:id/messages?since=0 | 邀请或成员 | 增量拉取历史(私聊按身份过滤) |
| POST | /api/rooms/:id/advance | GM | 强制 AI 推进一轮 |
| POST | /api/rooms/:id/speak | GM | 点名子代理接话({agentId}) |
| GET | /api/rooms/:id/roles | 成员 | 角色名单 + 自己的角色本(GM 看全部) |
| POST | /api/rooms/:id/roles | 成员/GM | claim / assign / release |
| POST | /api/rooms/:id/phase | GM | 剧本杀阶段机:next / set |
| GET | /api/rooms/:id/truth | GM | 汤底 / 真相正文 |
| GET / POST | /api/rooms/:id/scene | 邀请或成员 / GM | 读取 / 设置舞台(背景、立绘、BGM、字幕) |
| POST | /api/rooms/:id/choice | 成员 / GM | 选项投票:start / cast / cancel |
| GET / POST | /api/rooms/:id/saves | 成员 | 个人本存档列表 / 新建存档 |
| POST | /api/rooms/:id/saves/:saveId/load | 成员 | 个人本读档 |
| DELETE | /api/rooms/:id/saves/:saveId | 成员 | 删除手动存档 |
| POST | /api/rooms/:id/rewind | 成员 | 个人本回退一步 |
| GET / PATCH | /api/rooms/:id/memory | 成员 | 个人本长期记忆 |
| POST | /api/draw/sessions | 无 | 新建一局 AI 画我猜 |
| GET | /api/draw/sessions/:id | 无 | 画我猜当前状态(不含未揭晓答案) |
| POST | /api/draw/sessions/:id/next | 无 | 下一题 |
| POST | /api/draw/sessions/:id/guess | 无 | 猜词 |
| POST | /api/draw/sessions/:id/skip | 无 | 跳过并揭晓 |
| POST | /api/draw/sessions/:id/hint | 无 | 提示字数 / 首字 |
| GET | /pack-assets/:packId/:file | 无 | 剧情包图片 / 音频素材 |
| POST | /api/rooms/:id/avatar | 成员 | 上传自己的头像(内联图片 data URL) |
| POST | /api/rooms/:id/vote | 成员/GM | 投票:start / cast / cancel(全员同意才通过) |
| POST | /api/rooms/:id/purge | GM 或本机 | 永久删除房间(关闭只是打标记) |
| POST | /api/rooms/:id/leave | 成员 | 主动离开 |
| GET | /api/rooms/:id/events?since=0 | 邀请或成员 | SSE:snapshot / message / members / ai / system / vote / room / phase / roles / story / scene / choice / restore / saves |
$base = 'http://127.0.0.1:7302'
# 1. 建房(房主即 GM)
curl.exe -s -X POST "$base/api/rooms" -H 'content-type: application/json' -d '{"title":"天台上的黄昏","gmName":"澪"}'
# → 201 { room, inviteToken, gm:{memberId,token}, joinPath }
# 2. 玩家加入(把上一步的 inviteToken 填进来)
curl.exe -s -X POST "$base/api/rooms/<房号>/join" -H 'content-type: application/json' -d '{"name":"小满","inviteToken":"<邀请令牌>"}'
# → 200 { memberId, token, role, room }
# 3. 发言(用第 2 步拿到的 token)
curl.exe -s -X POST "$base/api/rooms/<房号>/messages" -H "authorization: Bearer <成员令牌>" -H 'content-type: application/json' -d '{"text":"门后面好像有脚步声,要不要进去看看?"}'
# → 202 { message, seq };约 debounceMs 后 AI 会自己判断接不接话
# 4. 拉历史(新客户端进房)
curl.exe -s "$base/api/rooms/<房号>/messages?since=0&t=<邀请令牌>"
# 5. GM 推进(强制 AI 开口)
curl.exe -s -X POST "$base/api/rooms/<房号>/advance" -H "authorization: Bearer <GM令牌>"
# 6. 实时广播(另开一个窗口,边发边看)
curl.exe -N "$base/api/rooms/<房号>/events?t=<邀请令牌>"
debounceMs(默认 1200ms)内的发言合并成一轮,避免一句一回;<silent>,剧情需要推进才回应」;<silent>(或空)→ 不产生消息,但这批发言标记为已读,不会反复重发;/advance → 跳过防抖、强制要求「立即推进剧情」。浏览器半侧(client/client.js)在会话视图里注册了第四个标签:
conversation.view,id: galgame-room,order: 30 → 排在「对话 / 轨迹 / galgame 模式」最右边/api/galgame-room/config 返回的端口决定注意:
curl http://127.0.0.1:7302/api/health 确认。# 会先备份 profile/package.json,再复制插件并登记到 bundles
powershell -NoProfile -ExecutionPolicy Bypass -File 'dsh-story-party\scripts\install-dsh.ps1'
然后重启 DeepSeek Harness。启动日志里应出现:
[galgame-room] 房间服务已监听 0.0.0.0:7302,入口 POST /api/rooms
首次监听如果弹出 Windows 防火墙,请勾选「专用网络」允许,朋友才能连进来。
局域网地址形如 http://192.168.x.x:7302。
cd dsh-story-party
$env:npm_config_cache = 'dsh-story-party\.npm-cache' # 可选:避免写系统 npm 缓存
npm pack --pack-destination .
产物:.\dsh-story-party-0.2.0.tgz,共 54 个文件
(src/、public/、assets/、scripts/、cordis.patch.yml、README.md、package.json)。
包内已声明:
dsh.bundle.patch = ./cordis.patch.yml(插件管理器据此识别为可挂载的 bundle)engines.dsh = ">=0.2.1-rc.2 <0.3.0"(版本兼容以它为准,不再比 peer 范