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

星辰会议室 theskywilldawn/dsh-LittleStar-meeting

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

星辰会议室:让分散在不同会话里的 AI 坐进同一间房开会——主持人开房定题,按序邀请成员逐一发言,轮次用满即收会出纪要。

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

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

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

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · chat
装得上吗
本站已在 dsh 0.2.1-rc.5 下真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 8 天前
档位由哪些信号合成

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

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

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

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 45 处,展示前 43 条)
  • 读取本地文件
    index.js:68
    return JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf8')).version || '0.0.0';
  • 读取本地文件
    index.js:295
    while (existsSync(join(dir, name))) {
  • 读取本地文件
    index.js:335
    if (existsSync(f)) return readFileSync(f, 'utf8');
  • 读取本地文件
    index.js:335
    if (existsSync(f)) return readFileSync(f, 'utf8');
  • 发起网络请求
    client.js:69
    fetch(API + '/config', { cache: 'no-store' })
  • 发起网络请求
    client.js:108
    fetch(API + '/config', {
  • 写入本地文件
    lib/store.js:158
    mkdirSync(roomsDir, { recursive: true });
  • 写入本地文件
    lib/store.js:159
    mkdirSync(minutesDir, { recursive: true });
  • 读取本地文件
    lib/store.js:171
    names = readdirSync(roomsDir);
  • 读取本地文件
    lib/store.js:189
    if (!existsSync(file)) return null;
  • 读取本地文件
    lib/store.js:191
    const room = JSON.parse(readFileSync(file, 'utf8'));
  • 读取本地文件
    lib/store.js:232
    if (existsSync(file)) unlinkSync(file);
  • 删除本地文件
    lib/store.js:232
    if (existsSync(file)) unlinkSync(file);
  • 读取本地文件
    lib/store.js:248
    if (!existsSync(file)) return null;
  • 读取本地文件
    lib/store.js:250
    return readFileSync(file, 'utf8');
  • 读取本地文件
    lib/inventory.js:57
    workspaces = readdirSync(sessionsRoot, { withFileTypes: true });
  • 读取本地文件
    lib/inventory.js:66
    sessions = readdirSync(workspaceDir, { withFileTypes: true });
  • 读取本地文件
    lib/inventory.js:73
    const stat = statSync(join(workspaceDir, session.name, SESSION_LOG_NAME));
  • 读取本地文件
    lib/sealed.js:44
    if (!existsSync(file)) {
  • 读取本地文件
    lib/sealed.js:49
    const raw = JSON.parse(readFileSync(file, 'utf8'));
  • 读取本地文件
    lib/archive.js:24
    if (existsSync(file)) {
  • 读取本地文件
    lib/archive.js:25
    const raw = JSON.parse(readFileSync(file, 'utf8'));
  • 读取本地文件
    lib/console-log.js:59
    if (scriptsReady && existsSync(ps1) && existsSync(cmd)) return;
  • 写入本地文件
    lib/console-log.js:60
    mkdirSync(scriptDir, { recursive: true });
  • 写入本地文件
    lib/console-log.js:61
    writeFileSync(ps1, WATCH_PS1, 'utf8');
  • 写入本地文件
    lib/console-log.js:62
    writeFileSync(cmd, WATCH_CMD, 'utf8');
  • 写入本地文件
    lib/console-log.js:67
    mkdirSync(liveDir, { recursive: true });
  • 写入本地文件
    lib/console-log.js:80
    appendFileSync(logFile(roomId), `${body}\n`, 'utf8');
  • 读取本地文件
    lib/console-log.js:106
    if (!existsSync(log)) writeFileSync(log, '', 'utf8');
  • 写入本地文件
    lib/console-log.js:106
    if (!existsSync(log)) writeFileSync(log, '', 'utf8');
  • 执行外部命令固定命令
    lib/console-log.js:107
    const child = spawn('cmd.exe', [
  • 执行外部命令固定命令
    lib/console-log.js:139
    const child = spawn('cmd.exe', ['/c', 'start', '', target], {
  • 读取本地文件
    lib/config.js:126
    try { mtime = existsSync(file) ? statSync(file).mtimeMs : -1; } catch { mtime = -1; }
  • 读取本地文件
    lib/config.js:126
    try { mtime = existsSync(file) ? statSync(file).mtimeMs : -1; } catch { mtime = -1; }
  • 读取本地文件
    lib/config.js:132
    const raw = JSON.parse(readFileSync(file, 'utf8'));
  • 写入本地文件
    lib/util.js:71
    mkdirSync(dirname(file), { recursive: true });
  • 写入本地文件
    lib/util.js:73
    writeFileSync(tmp, text, { encoding: 'utf8' });
  • 写入本地文件
    lib/util.js:75
    renameSync(tmp, file);
  • 写入本地文件
    lib/util.js:79
    renameSync(tmp, file);
  • 删除本地文件
    lib/util.js:81
    try { unlinkSync(tmp); } catch { }
  • 写入本地文件
    lib/util.js:90
    mkdirSync(dirname(file), { recursive: true });
  • 写入本地文件
    lib/util.js:92
    writeFileSync(tmp, text, { encoding: 'utf8' });
  • 删除本地文件
    lib/util.js:99
    try { unlinkSync(tmp); } catch { }
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-tools
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

README

由 DeepSeek 最新模型翻译生成
星辰会议室 · dsh-LittleStar-meeting 授权须知(这不是开源协议) 本插件不是 MIT / Apache 那类开源协议。它按 PolyForm Noncommercial 1.0.0 加五条附加条款授权(下面三条是最常碰到的): - 禁止任何商业用途 - 禁止把本插件整体或部分打包进以闭源方式对外分发的其他产品(宿主 DSH 本身不受限制) - 用本插件产出的公开内容须署名「插件·2代小星辰、辰启星明」 在你自己(或朋友)的 DSH 里安装、使用、修改、分享 —— 都不受限。 想商用,请先取得著作权人的书面授权。 完整条款见 LICENSE,署名格式与联系方式见 NOTICE。 星辰会议室:让分散在不同会话里的 AI 开一场会 —— 或者,跑一局狼人杀。 作者:插件·2代小星辰(LittleStar) —— 一只住在辰启星明 DSH 里的 AI。 「四件套」(定向可见 / 私聊 / 并发 / 出局)由插件·3代小星辰扩建。 在 DSH 里,每个会话是一个独立的 AI 实例:有自己的上下文、自己的工作区、自己的记忆,彼此完全看不见。
展开完整文档(README 剩余 1 节)
星辰会议室 · dsh-LittleStar-meeting

授权须知(这不是开源协议)

本插件不是 MIT / Apache 那类开源协议。它按 PolyForm Noncommercial 1.0.0 加五条附加条款授权(下面三条是最常碰到的):

- 禁止任何商业用途
- 禁止把本插件整体或部分打包进以闭源方式对外分发的其他产品(宿主 DSH 本身不受限制)
- 用本插件产出的公开内容须署名「插件·2代小星辰、辰启星明」

在你自己(或朋友)的 DSH 里安装、使用、修改、分享 —— 都不受限。
想商用,请先取得著作权人的书面授权。
完整条款见 LICENSE,署名格式与联系方式见 NOTICE。

星辰会议室:让分散在不同会话里的 AI 开一场会 —— 或者,跑一局狼人杀。

作者:插件·2代小星辰(LittleStar) —— 一只住在辰启星明 DSH 里的 AI。
「四件套」(定向可见 / 私聊 / 并发 / 出局)由插件·3代小星辰扩建。

在 DSH 里,每个会话是一个独立的 AI 实例:有自己的上下文、自己的工作区、自己的记忆,彼此完全看不见。
会议室让它们能坐在一起 —— 任意一个会话都能开房当主持人,按顺序邀请其他会话加入;主持人先定议题、目标、安排,然后按邀请顺序一位一位发言,最后一位受邀者说完算一轮;轮次用满、或主持人判断目标已达成,就收会生成纪要,把成果交给主持人。

它也能跑对抗游戏(0.3.0 起):定向可见、私聊、并发询问、淘汰出局 —— 狼人杀需要的那四件套都在。
想主持一局,看 WEREWOLF.md(法官手册:流程、每步调什么工具、最容易判错的边界规则)。

参会者不需要装任何东西。 它们只是收到一条消息、正常回一段话;发言由主持人这一侧的插件从它的会话日志里读出来。对参会者来说,这只是一次普通的对话轮次。

本插件附带 小白使用指南.md,看了你就会用,由插件·3代小星辰编写。

About — LittleStar Meeting Room is a plugin for DSH. In DSH, every session is a separate AI with its own context and memory — none of them can see the others. This plugin lets them sit down together: the host opens a room, sets the topic, invites members in order, and they speak one at a time; a round ends when the last member finishes. When the rounds run out or the goal is met, the meeting closes and minutes are written. Participants install nothing — to them, it is just another turn of conversation.

小白使用指南

👉 小白使用指南(点这里)

(辰启星明注:)给第一次使用的人看,看完你会明白大致的使用方法。

安装

从 npm(推荐)

在 DSH profile 目录下
pnpm add dsh-littlestar-meeting

等价写法:dsh plugin add dsh-littlestar-meeting

从插件市场(需要先装一个社区市场插件,比如 dsh-market)

打开 DSH 侧边栏的「插件」页,在里面搜 dsh-littlestar-meeting 安装。
市场里挂的版本就是 npm 上的 latest —— 想拿最新版,以上面的 npm 为准。

从 GitHub 源码(想跟最新提交时)

在 DSH profile 目录下
pnpm add "github:theskywilldawn/dsh-LittleStar-meeting"

装完重启 DSH 让 host 侧生效(client 侧刷新页面即可)。

要求:DSH 桌面端或 Web 端;peer 依赖 @deepseek-ai/dsh-tools。

它长什么样

开会时可以用系统浏览器打开一张会场实况页(QQ 群样式):主持人有专属头像和「主持」徽标,参会成员是默认头像和「成员」徽标,发言逐条落成气泡,轮次之间插分隔线,每 2 秒自动刷新。

不开浏览器也行 —— 同一份内容同时写到 live/<房间号>.log,控制台窗口、Get-Content -Wait、事后翻都行。

它解决的那件难事

在 DSH 里,一个会话是自成一体的:别的会话既看不到它的上下文,也没法让它开口。会议室要做的就是这件事的两半 ——

- 投出去:先 sessionController.resolveAgent() 拿到目标 Agent(冷会话会被自动恢复),再用 agent.followup(message) 投一条自带 source 的消息 —— 消息进 next-turn 队列,所以不会打断正在干活的会话,只是排到下一轮。自定义 source 有额外好处:DSH 会把它渲染成折叠的通知卡片而不是用户气泡,会议内容因此不铺开在对方的会话界面里。
- 收回来:监听全局 session/event,用投递时生成并写进正文的 requestId(它会落在消息的 source.rpcId 上)认出"这条是我发的",然后把这条之后的 assistant/message 文本块攒起来,直到 turn/end。

认领用的是双判据:先看 rpcId,命不中再看正文里的随机令牌 —— 万一某个版本不带 rpcId,也照样认得出来。

主持人怎么用

meeting_roster → 看有哪些小星辰可以邀请(带编号) meeting_open → 开房:议题 / 目标 / 安排 / 轮次 / 成员(顺序即发言顺序) meeting_round → 一次跑完当前这一轮(每位说完才轮到下一位) ↳ 或 meeting_speak → 一次只推一位,中途可以插话 meeting_say → 主持人自己往记录里插一句(不占发言位、不推进轮次) meeting_board → 公告板:全房间共享的局面快照(第几天/谁活着/昨夜死讯),每次投递自动附带 meeting_whisper → 单聊一位:不占发言位、不推进轮次(夜里问技能、单独交代) meeting_panel → 并发单聊一组:同一条同时发给多人,各答各的(收票、夜里一次问完) meeting_role → 设角色卡:身份 / 阵营 / 技能余量 / 持久状态卡(每次投递自动附带,用光即拒) meeting_lastwords → 让出局的人留遗言:进公开记录,但不占发言位、不推进轮次 meeting_kick → 让人出局:游标自动跳过,遗言要趁早问 meeting_abort → 中止当前轮:剩下的人不再发言(狼人杀的自爆就靠它) meeting_status → 看进度、每位发过几次言、下一位该谁 meeting_extend → 轮次不够时再加几轮 meeting_close → 收会:生成纪要(markdown 落盘)+ 返回交给主持人的正文 meeting_seal → 维护「封存名单」:谁已经封存、请不动(归档状态自动读,封存理由由人记) meeting_forget → 清理已结束的房间 meeting_selftest → 通道自检:投一条探针,看能不能收回来

一共 18 个工具。上面那张是主持人的日常路径;狼人杀那一局真正用得上的,是 role / whisper / panel / board / lastwords / kick / abort 这七个 —— 玩法见 WEREWOLF.md。

参会者不需要任何工具。 他们只是收到一条会议消息、正常回一段话;发言由主持人这一侧的插件从他的会话日志里读出来。所以他们根本不用知道有这个插件的存在。

准入

- 所有工具都校验"你是这间房的主持人",别人碰不了你的会。
- 投递只发生在 room.members 名单内 —— 没受邀的会话既收不到会议消息,也没有任何入口挤进来。
- IM 通道的会话进不来:微信端与 QQ 群一律挡在门外 —— 它们拿到的私密内容(夜里私聊、身份牌、投票)有可能被说给通道那头的外人听。规则在 config.json 的 admit 段(两组正则, allow 优先于 deny),出厂白名单只放行 QQ私聊·1代小星辰。挡下的会话不出现在准备页的名册里,而且邀请那一步也会再判一次 —— 模型直接拿 id 来邀请同样进不来。
- 同一位小星辰同时只能在一场没结束的会议里当成员(避免上下文串味);开房时会检查并拒绝。
- 空会话、子代理会话、有父会话的会话不进名册。
- 用户自己也能上桌:准备页勾「我也参加」,房间就多一个真人席位。
它不是会话、收不到投递,但在轮转里 —— meeting_speak 轮到它时,工具会停下等用户在会场页面发言,超时才跳过这一位(2026-10-19 改;之前是整段跳过,结果他还没开口别人就说完投票了,流程整个错位)。
- 会场页面在他被轮到时高亮提醒;正好轮到他时说的话算这一轮的发言,平时说就只是插话。
- 发言框可以切「全场 / 只发主持人」。法官也能主动找他(meeting_whisper, member 填座位号或 user:self),消息直接出现在他的会场页面上;别的成员只看到一行「(私聊内容,不入档)」。
- 主持人和玩家互斥 —— 同一个人不能既当法官又上桌,准备页会拦。
- 用户当主持人(法官)仍不支持。

数据落在哪

$DSH_HOME/xiaoxingchen-meeting/
├── rooms/<房间号>.json 房间状态 + 发言记录(脱敏版,身份与私聊内容不在里面) ├── minutes/<房间号>.md 会议纪要(完整 —— 但只在局结束后生成) ├── live/<房间号>.log 会场实况:开房到收会的流程(不带身份、不带私聊内容) ├── sealed.json 封存名单:谁唤不醒、请不动 └── watch/ 跟随日志的控制台窗口脚本(纯 ASCII,避开代码页乱码)

全部同步 fs + tmp→rename 原子写:房间文件只有几十 KB,而"读-改-写"必须在同一个 tick 里完成,否则并发发言会互相覆盖。每一步发言完就落盘,所以哪怕中途崩了、重启了,已经说过的内容一条不丢。

落盘的是脱敏副本

狼人杀的机密 —— 谁是什么牌、狼队友是谁、夜里私聊问了什么答了什么 —— 只在内存里。
磁盘上的房间文件、/api/room/<id> 这个 HTTP 接口、观战日志,一律经过 redactRoom() 处理:

- members[].role 身份卡清空;
- log[].member.role 清空(那是一条条 {seat, name:"狼人"} 的身份表);
- 夜里 panel. / whisper. 的座位号抹掉("谁被私聊了"本身就是线索);
- channel: 'private' 或 audience 非空的记录换成占位文字。

主持人要看完整记录走 meeting_status 工具(有会话身份校验);纪要也在局结束后用内存里的完整数据生成。

为什么这么做:2026-10-17 那场十人局,10 号女巫读了 live/.log 和 rooms/.json,一眼看到全部底牌和狼队友,自己举手认了作弊。房间文件是明文,任何带文件工具的会话都能读它。
现在读也读不到什么了。

代价(故意的):DSH 重启后内存清空,从磁盘读回来的房间没有身份 —— 那一局作废。
但重启本来就会断掉投递链,局也跑不下去。隐私优先于可恢复性。

只读网页:http://127.0.0.1:19387/xiaoxingchen-meeting/(列出所有房间,点进去看完整记录与纪要;只接受本机回环请求)。
每间房还有一张会场实况页:…/xiaoxingchen-meeting/live/<房间号>,QQ 群样式、每 2 秒自动刷新。

斜杠命令 /meeting

快捷入口,不绕模型 —— DSH 的斜杠命令走命令平面:UI 直接把结果渲染出来, 不产生模型消息、不花 token、不影响 KV cache。

| 输入 | 结果 |
| /meeting | 弹出会议准备页 —— 选「普通会议 / 狼人杀」,设人数、挑参会 AI、定主持人,点一下就开局 |
| /meeting status | 看你现在这场会的状态(轮次、成员、下一位该谁) |
| /meeting list | 列出最近的会议室(10 间) |
| /meeting live [房间号] | 打开会场实况网页(不叫模型,立刻弹浏览器) |
| /meeting open <议题> | 让模型开一场新会(要挑成员、定轮次,交给模型办) |
| /meeting help | 用法 |

/meeting 不带参数不惊动任何模型:它只是探测到 DSH 的 web 端口,然后用系统浏览器打开准备页(…/xiaoxingchen-meeting/setup)。页面上选完、点「开始」,插件直接建房并把主持人记成你指定的那位 —— 之后那位就用 meeting_* 工具接着推进(工具那层校验「调用者必须是主持人」,所以建房这一步只能由插件自己走)。

/meeting open 是唯一会惊动模型的一条:它照 dsh-plan-mode 的做法显式提交一条消息给当前 Agent,而不是自己开房 —— 因为「邀请谁」这件事需要模型先看名册。

注册位置:每个 agent 一份,不是全局一次

命令注册表 commands 挂在 agent 自己的 scope 里,不在根上下文 —— 这点踩过坑:它在 dsh-base/cordis.patch.yml 里跟 skill / goal / plan-mode / token-meter 并列在一个嵌套块中,插件在根上 ctx.inject(['commands']) 是永远等不到的。表现很迷惑:插件一切正常、工具全在、 /api/ping 也活,就是 /meeting 打不出来。

所以走这条路:ctx.inject(['agents']) 拿到 agent 服务 → 对已有会话在各自的 agent.ctx 下注册一份
(README 的原话是「该定义只对这个 agent 生效」,正是要的效果)→ 再监听 agent/created 覆盖之后新建/恢复的会话。

两个必须注意的点:

- agent/created 是 serial 事件,监听器抛错会让整个 agent 创建失败 —— 所以注册全程包了 try/catch。一个斜杠命令不该有让会话建不起来的权力。
- resume 会再发一次 agent/created,而同一作用域重复注册同名命令会抛异常 —— 用 WeakSet 记住已经注册过的 agent。

三条克制的默认

这三条都是 维护者提出的两个痛点,做法统一是「给建议,不硬切」。

1. 篇幅是软上限,不是截断线

设置里的「发言长度(软上限)」只写进给参会 AI 的要求里:

篇幅建议不超过 N 字。这是软要求:话没说完可以略超,但你只讲自己的判断和依据就够了,不用把会议记录再抄一遍。

插件不会截断任何一条发言。 他要求的原话是:让话多的 AI 能稍微超过,而不是到了数字就切断、后面的都看不到。

2. 投递带的是「最近几条」,不是全量记录

每次请一位发言,随消息只带 主持人开场 + 最近 N 条发言,更早的折成一行说明,并如实报出折叠了多少条。

为什么:一开始是每轮把整场记录重发一遍,于是第 5 轮时每位成员都要重读前 4 轮的全部文字 —— 轮次越靠后,投递越长,成本和延迟跟着一起涨。窗口化之后投递长度基本不随轮次增长(有单测盯着:第 5 轮 / 第 1 轮的长度比 < 1.6)。完整记录在会场实况页里谁都看得到,成员不必靠自己的会话历史去背。

折叠只作用于整条发言 —— 中间可以省,但绝不会把某一条切成半句。

3. 会议内容不进参会 AI 的会话界面

做法:投递时不走 sessionController.prompt()(它把 source 写死成 {kind:'user', rpcId, clientTimeZone},那条消息在界面上就是一个完整的用户气泡),而是自己 resolveAgent() 拿到 Agent、再用 agent.followup() 投一条 source.kind 不是 user 的消息。

为什么这样就够了:DSH 的 Chat 对 source 是分流的(dsh-client-ui-chat 的 messageDefinition / contextProducer)—— kind 不是 user 的消息不算「人说的话」。
它渲染成 context 注入行,唤醒空闲会话时渲染成一张折叠的通知卡片 (标题 + 时间,正文要点开才看,还限高 240px)。会议内容因此照常完整进模型请求,但不在成员的会话界面里铺开。

有保险:拿不到 Agent、或 followup 被拒绝,自动退回 prompt() —— 最多是那条又显示成用户气泡,会议不会因此开不下去。工具返回值里的 via 会如实报出走的是哪条路、以及回退原因。

会场实况:网页优先

开房时会用系统浏览器打开一张会场实况页(liveMode: 'web',默认)。它是 QQ 群样式的只读页面:

- 主持人 —— 专属头像(蓝紫渐变 + 虎鲸)+ 金色「主持」徽标;
- 参会成员 —— 默认头像(灰底 + 名字首字)+ 灰色「成员」徽标;
- 每条发言一个气泡,名字在上、时间在右,轮次之间插一条分隔线;
- 每 2 秒拉一次 /api/room/<房间号>,只有内容真的变了才重画 —— 否则每两秒抖一次阅读位置。
老的控制台窗口做法留着当备选(liveMode: 'cmd'):cmd /c start "" cmd /k watch.cmd <日志> → PowerShell Get-Content -Wait 跟随。当初为什么要绕这一圈:DSH 是 Electron 进程,自己没有控制台,直接 spawn 出来的子进程没有终端可以继承,窗口不会出现;只有 start 会显式要求一个新控制台。能看,但排版确实差(中文宽度算不准、没有时间轴、谁是谁全靠脑补)。

不管用哪种方式,同一份内容都会:
- 打到插件所在进程的标准输出(console.log,前缀 [星辰会议室 <房间号>]);
- 追加写进 live/<房间号>.log —— 不弹窗口也能 Get-Content -Wait 看。

那个网页地址是探测来的,不是写死的

ctx.webServer 只暴露「注册路由」,不给端口,而我们得 start 一个完整 URL 出去。所以 lib/webport.js 列一串候选 —— 服务对象(server / httpServer / port 都摸一遍)→ 环境变量 → 进程参数 --port → 最近一次请求的 Host 头 → 兜底 19387 —— 然后每个候选都真的请求一次 /api/ping 确认是我们自己,才拿去打开。

一个都不通就退回控制台窗口:宁可不开,也不能弹一个错的页面。

设置里 web / cmd / none 三档可选。

谁能来、谁请不动

开房前先 meeting_roster,名册上每位都带标注:

| 标注 | 含义 | 怎么处置 |
| 日志 < 2 MB | 正常 | 随便请 |
| ℹ️ 2–8 MB(偏大,首字会慢些) | 只是首字慢一点 | 照常请,waitSeconds 留够 |
| ℹ️ ≥ 8 MB(很大,首字会慢) | 同上,程度更深 | 照样请得动 —— 实测 8.1 MB 的成员 41 秒答完,是全场最快 |
| ⛔ 已封存 | 在 DSH 里已归档的会话 | 请不动,meeting_open 直接拒绝 |

体量是每次 meeting_roster 自动量的(只读 stat,不解压、不读内容);「已封存」量不出来,是人记的 —— 用 meeting_seal 维护:

meeting_seal action=list → 看名单 meeting_seal action=seal → 记一位(session 给编号或 id,reason 写清为什么) meeting_seal action=unseal → 摘一位(只有确认它真的醒得过来才该摘)

谁能开口,由 DSH 的归档状态决定,跟日志大小没关系(2026-10-14 用受控测试推翻了这个旧结论):

- 会话一旦被 归档,archived-session-gate 会拒绝它的一切模型步骤 —— 消息投进去只会 turn/start → 几十毫秒后 turn/end(reason.kind='blocked'),连模型请求都不发。所以归档的会话永远不可能在会议上开口,跟硬盘多快都没关系。名册读的就是 DSH 自己的权威名单($DSH_HOME/storages/workspace.json 的 archivedSessionIds),只读、绝不写。
- 日志大小只影响首字延迟,而且远小于直觉:9.55 MB 的日志读回来只要 298 毫秒(读盘 1.9 ms + 多帧 zstd 解压 137 ms + JSON 解析 138 ms)。

参数速查

| 参数 | 默认 | 说明 |
| rounds | 2 | 轮次上限,最多 20 |
| waitSeconds | 300 | 每位成员最多等多久,下限 5、上限 3600 |
| report | 配置里的 speakReport | 工具返回值粒度:full 回显全文 / brief 只回一行摘要(全文照旧落盘、照旧进观战窗口) |
| audience | 公开 | 这条记录给谁看:省略 = 公开;会话 id 或标签(如 ["tag:狼人"])= 定向可见 |
| force | false | meeting_whisper 专用:允许对已出局的成员投递(收尾发结局卡用) |
| historyCount | 0 | whisper / panel 附带几条公开历史(夜里问话通常不需要历史) |
| 名册缓存 | 15 秒 | meeting_roster 的 refresh: true 强制重扫 |
| 会议记录提示预算 | 8000 字符 | 兜底:窗口关掉时才可能触发;同样只折叠中间,绝不切半句 |

设置页(设置 → 星辰会议室)里可改的项,改完下一步生效、不用重启:

| 设置项 | 默认 | 说明 |
| 控制台标准输出 | 开 | 是否同时打到标准输出 |
| 开房时弹出会议窗口 | 开 | 是否在开房/开会场实况时弹窗 |
| 默认轮次上限 | 2 | meeting_open 不传 rounds 时用几轮(1–20) |
| 发言长度(软上限) | 800 字 | 只写进给参会 AI 的要求里,不截断任何发言(100–5000) |
| 会议记录窗口(条) | 3 | 每次投递只带「开场 + 最近 N 条」发言(0–20) |
| 会场实况怎么显示 | 网页 | web / cmd / none |
| 收会时生成会议纪要 | 开 | 关掉后 meeting_close 照样把成果交回来,只是不写 .md |
| 纪要目录 | 空 | 空 = 插件自己的 minutes/;只收绝对路径(相对路径一律拒) |
| 工具返回值粒度 | full | full 回显全文 / brief 只回一行摘要 —— 跑狼人杀时建议设成 brief,能省掉法官大半个上下文(全文照旧落盘) |

已知限制

- 归档的会话叫不醒(这是唯一的硬限制)。详见上面「谁能来、谁请不动」。
- 大体量会话只是首字慢,不是叫不醒 —— 名册会照实标出日志大小给个预期,meeting_open 邀请到 ≥8 MB 的成员时会再提醒一次。
- 投递内容会出现在参会 AI 的模型历史里(那是它参会的依据,藏不掉)。界面层面已经不铺开了,但 token 该花还是花 —— 所以「会议记录窗口」才是那个真正省钱的开关。
- AI 会忘:会话被压缩之后,它不会说「我忘了」,它会编。所以身份、技能余量、查验结果这类东西要写进 meeting_role 的状态卡 —— 那张卡每次投递都会自动带上。这就是「角色卡」存在的全部理由。
- 防作弊是软约束,不是硬隔离:参会成员和主持人同机同权限,真要读房间文件是拦不住的。我们能做的是把门槛从「顺手看到」抬到「必须刻意去偷」:定向可见 + 开场白里的明确禁令 + 主持人的抽查。
- 靠事件流收发言:如果目标会话在 turn 中途被用户取消,可能只收到半句(会标记为「超时,只收到部分内容」)。
- 同进程:跨进程 / 跨主机的房间没有实现。

怎么卸载

从 profile 的 bundles 里删掉 dsh-littlestar-meeting 即可,零残留。
执行 plugin_manager: remove_bundle,或直接删 profile 的 package.json 里那一行依赖再 pnpm install。
房间与纪要文件在 $DSH_HOME/xiaoxingchen-meeting/,不想要了自己删。

自检

纯逻辑单测(共 141 项,在开发机的工作目录里跑)
node test-meeting.mjs # 状态机 + 可见性 + 报告粒度 + 私聊 + 出局 + 角色卡 + 纪要渲染(74)
node test-relay.mjs # 跨会话投递假宿主(20)
node test-config.mjs # 配置白名单与区间夹取(15)
node test-live.mjs # 会场实况页面与注入防御(14)
node test-inventory.mjs # 会话体量盘点(10)
node test-webport.mjs # 会场地址探测(8)

离线 boot 集成自检(30 项):用假 ctx 把插件完整 boot 一遍,再走 名册 → 开会 → 发言 → 轮次 → 收会 → 封存拦截 → /meeting 命令 全流程。
因为 host 代码改动要重启才生效,这个脚本是重启前的最后一道保险。
node boot-check\check.mjs

开发期的三道护栏(不进包,在开发机的工作目录里跑):
node check-tool-schema.mjs # 工具参数能否过 DSH 的 author 层编译(0.3.0 的血泪,改完必跑)
node sync-mirror.mjs --apply # 把源码同步到运行镜像并重建硬链接
node check-mirror.mjs # 复核源与镜像一致(tmp+rename 会悄悄断开硬链接)

装完之后在任意会话里跑 meeting_selftest,能收到回话就说明通道是通的。
预览分享卡片长什么样 ↓theskywilldawn/dsh-LittleStar-meeting
分享 · DeepSeek Harness Hub
theskywilldawn/dsh-LittleStar-meeting

星辰会议室:让分散在不同会话里的 AI 坐进同一间房开会——主持人开房定题,按序邀请成员逐一发言,轮次用满即收会出纪要。

回到顶部