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

项目群聊 duxingxiake3/dsh-project-room

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

让多个代理在同一项目群里分工协作并真实执行任务

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

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

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

状态速览

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

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

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

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

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 37 处,展示前 37 条)
  • 发起网络请求
    client.js:1584
    const response = await fetch(ROUTE, {
  • 读取本地文件
    src/host/index.js:724
    const manifest = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'package.json'), 'utf8'));
  • 读取本地文件
    src/host/adapter/host-adapter.js:1195
    const parsed = JSON.parse(readFileSync(resolved, 'utf8'));
  • 读取本地文件
    src/host/adapter/host-adapter.js:1223
    const parsed = JSON.parse(readFileSync(manifest, 'utf8'));
  • 读取本地文件
    src/host/research/research-service.js:1262
    const workspaceReal = existsSync(workspace) ? realpathSync(workspace) : workspace;
  • 读取本地文件
    src/host/research/research-service.js:1264
    const realProtected = existsSync(protectedRoot) ? realpathSync(protectedRoot) : protectedRoot;
  • 读取本地文件
    src/host/research/research-service.js:1277
    const realProtected = existsSync(protectedRoot) ? realpathSync(protectedRoot) : protectedRoot;
  • 读取本地文件
    src/host/research/research-service.js:1295
    const real = existsSync(absolute) ? realpathSync(absolute) : absolute;
  • 读取本地文件
    src/host/storage/store.js:885
    if (existsSync(this.lockFile)) {
  • 读取本地文件
    src/host/storage/store.js:886
    const raw = readFileSync(this.lockFile, 'utf8');
  • 写入本地文件
    src/host/storage/store.js:909
    writeFileSync(this.lockFile, `${process.pid}|${isoTimestamp()}`, 'utf8');
  • 读取本地文件
    src/host/storage/store.js:915
    if (!existsSync(this.lockFile)) return;
  • 读取本地文件
    src/host/storage/store.js:916
    const [pidText] = readFileSync(this.lockFile, 'utf8').split('|');
  • 删除本地文件
    src/host/storage/store.js:917
    if (Number(pidText) === process.pid) rmSync(this.lockFile, { force: true });
  • 写入本地文件
    src/host/storage/store.js:940
    copyFileSync(this.file, backup);
  • 读取本地文件
    src/host/storage/paths.js:44
    if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
  • 写入本地文件
    src/host/storage/paths.js:44
    if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
  • 写入本地文件
    src/host/diagnostics.js:62
    appendFileSync(tracePath(), line, 'utf8');
  • 读取本地文件
    src/host/diagnostics.js:127
    const previous = existsSync(target) ? JSON.parse(readFileSync(target, 'utf8')) : null;
  • 读取本地文件
    src/host/diagnostics.js:127
    const previous = existsSync(target) ? JSON.parse(readFileSync(target, 'utf8')) : null;
  • 写入本地文件
    src/host/diagnostics.js:144
    writeFileSync(
  • 读取本地文件
    src/host/diagnostics.js:188
    if (!existsSync(target)) return;
  • 读取本地文件
    src/host/diagnostics.js:189
    const size = readFileSync(target).length;
  • 写入本地文件
    src/host/diagnostics.js:192
    mkdirSync(dataRoot(), { recursive: true });
  • 写入本地文件
    src/host/diagnostics.js:193
    renameSync(target, `${target}.1`);
  • 读取本地文件
    src/host/workspace/artifact-service.js:211
    if (!existsSync(target)) {
  • 读取本地文件
    src/host/workspace/artifact-service.js:216
    const stat = statSync(target);
  • 读取本地文件
    src/host/workspace/artifact-service.js:220
    const hash = createHash('sha256').update(readFileSync(target)).digest('hex');
  • 写入本地文件
    src/host/workspace/coordinator.js:101
    mkdirSync(resolve(this.worktreeRoot), { recursive: true });
  • 读取本地文件
    src/host/workspace/coordinator.js:102
    if (!existsSync(path)) {
  • 读取本地文件
    src/host/workspace/coordinator.js:340
    if (path && existsSync(path)) rmSync(path, { recursive: true, force: true });
  • 删除本地文件递归
    src/host/workspace/coordinator.js:340
    if (path && existsSync(path)) rmSync(path, { recursive: true, force: true });
  • 读取本地文件
    src/host/security/safe-path.js:64
    while (!existsSync(cursor)) {
  • 执行外部命令来自配置/变量
    src/host/process.js:58
    const piped = spawnSync(file, args, {
  • 执行外部命令来自配置/变量
    src/host/process.js:82
    const redirected = spawnSync(file, args, {
  • 读取本地文件
    src/host/process.js:89
    stdout: readFileSync(outFile, 'utf8'),
  • 删除本地文件递归
    src/host/process.js:107
    rmSync(scratch, { recursive: true, force: true });
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

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

项目群 / Project Room — 给 DeepSeek Harness 用的持久项目群聊。

README

由 DeepSeek 最新模型翻译生成
Project Room(项目群聊) 一个项目 = 一个持续存在的群聊。用户、主代理、前端、后端、测试、运维在同一条群消息时间线上沟通,同时各自拥有真实独立的 Harness 会话、自己的工作上下文和真实的执行能力。 这不是套壳聊天界面:群里的每条投递都落到真实会话,任务状态只由真实执行与证据驱动,模型按成员独立路由。 - English: README.md 1. 安装与启用 插件是零运行时依赖的纯 ESM 包:宿主半边只 import Node 内置模块,浏览器半边是一段自注册的 classic script,因此不需要构建工具链,也不需要在 profile 里额外安装任何包。 先克隆本仓库(git clone https://github.com/duxingxiake3/dsh-project-room.git),再在 Harness 的插件管理里安装克隆出的目录 <REPO>;之后 profile 会得到一条 link: 依赖和一条 loader 行: - insert: - id: project-room name: 'dsh-project-room' 注意写法:- insert: 才会创建 loader 行(行 id 与包名是两件事)。写成 - id: project-room 不会加载任何东西——这一点是在隔离 profile 里实测出来的。
展开完整文档(README 剩余 1 节)
Project Room(项目群聊)

一个项目 = 一个持续存在的群聊。用户、主代理、前端、后端、测试、运维在同一条群消息时间线上沟通,同时各自拥有真实独立的 Harness 会话、自己的工作上下文和真实的执行能力。

这不是套壳聊天界面:群里的每条投递都落到真实会话,任务状态只由真实执行与证据驱动,模型按成员独立路由。

- English: README.md

1. 安装与启用

插件是零运行时依赖的纯 ESM 包:宿主半边只 import Node 内置模块,浏览器半边是一段自注册的 classic script,因此不需要构建工具链,也不需要在 profile 里额外安装任何包。

先克隆本仓库(git clone https://github.com/duxingxiake3/dsh-project-room.git),再在 Harness 的插件管理里安装克隆出的目录 <REPO>;之后 profile 会得到一条 link: 依赖和一条 loader 行:

- insert:
- id: project-room
name: 'dsh-project-room'

注意写法:- insert: 才会创建 loader 行(行 id 与包名是两件事)。写成 - id: project-room 不会加载任何东西——这一点是在隔离 profile 里实测出来的。

启用成功后会写出两份可复核的记录:

| 文件 | 内容 |
| <DSH_HOME>/storages/project-room/boot-report.json | 解析到的核心版本、解析来源文件路径(coreResolvedFrom)、已注册工具名、当前上下文可用的工具名、能力标志、每次激活的历史 |
| <DSH_HOME>/storages/project-room/boot-trace.jsonl | 逐阶段的激活轨迹(一行一个 JSON)。进程若在启动中死掉,最后一行就是它走到哪一步 |

boot-report.json 里的版本取自运行进程自己的解析结果,不是读某个路径猜的;同时安装多套运行时,也能看出实际执行的是哪一套。

停用与卸载

- 停用:插件管理里关闭 project-room。
- 卸载:插件管理里移除 dsh-project-room。删除插件不删除项目历史——群、消息、任务、决定、成果都留在该目录的 rooms.sqlite 里,重装即可继续。
- 彻底清理是单独操作:关掉插件后删除上述目录。
- 插件不会销毁借用的用户会话(见第 6 节)。

2. 建群

左侧栏「项目群」图标 → 新建项目群。

| 字段 | 说明 |
| 群名称 | 任意,例如「验证码登录功能」 |
| 工作区目录 | 成员真实执行任务的工作目录(成员会话的 cwd)。可留空后补 |
| 整体目标 | 交给主代理的目标。提交后主代理会拆分工作、安排成员并推进 |
| 初始成员 | 勾选主代理 / 前端 / 后端 / 测试 / 运维 / 设计 / 文档;也可只建主代理,之后再按需补齐 |
| 每位成员的模型 | 每位成员单独选模型,或留空走角色/项目默认。选项来自宿主真实已接入的提供方与模型 ID |

建群在一个事务里写完群、成员与 room.created 事件,然后才创建成员会话。中断不会留下半个团队;成员身份先落盘,恢复时是核对而不是重建一个人。

3. 每位成员独立选模型

四层配置,优先级从低到高:

| 层级 | 位置 | 说明 |
| 项目默认 | 群设置 → 模型 | 没有单独配置的成员使用 |
| 角色默认 | 群设置 → 模型 → 角色默认 | 按 frontend/backend/tester/devops 预设 |
| 成员专属 | 成员详情 → 模型 | 指定到具体 memberId,优先级最高 |
| 允许池自动选型 | 群设置 → 选型模式 | 用户启用后,主代理在允许池内选型并公开理由;不覆盖被锁定的成员 |

默认 fixed:由用户固定每位成员,不会偷偷换成别的模型。

切换语义(安全边界):在成员详情选好模型点「应用模型」后,当前正在进行的请求沿用旧路由,下一次请求使用新模型;成员身份、头像、昵称、@ 名称与任务归属全部不变,也不重建会话、不重复工具副作用。每次切换记录配置版本与原因,旧结果保留旧来源。

「实际路由」一行显示的是真实请求时观测到的提供方/模型,而不是配置里写了什么——只有真正跑过一次才会出现。

模型标识必须写成宿主已接入的 提供方/模型ID。口头品牌名(「用 GLM 吧」)不会被当作模型 ID;目录读取失败或凭据失效的提供方显示为不可用并给出原因,而不是从列表里消失。

4. 三种 @,以及怎么把整体任务交出去

4.1 三种合法输入方式

| 方式 | 操作 | 行为 |
| 头像右键「@ 他」 | 右键(触屏长按 / 键盘 Enter)任意头像 | 把该成员插入输入框,不自动发送,原草稿保留。对自己显示「@ 自己」,只作留注记,不触发模型 |
| 输入 @ 选人 | 输入框输入 @ 或全角 @ | 弹出本群成员列表;按显示名/handle/角色/别名筛选;↑↓ 移动、Enter/Tab 选人、Esc 关闭。第一项是「所有人」,并显示会触达几位 AI 成员 |
| 直接输入 @名字 | 例如 @后端,接口字段怎么变了? | 服务器用确定性规则解析成与芯片相同的 memberId 列表,不要求重新打开选人框 |

解析规则(shared/mention-resolver.js,前后端是同一份代码,由 scripts/build-client.mjs 内联进浏览器半边):

1. 先屏蔽正文结构——代码块、行内代码、> 引用行、链接目标、邮箱地址、URL——这些位置里的 @ 不唤醒任何人。
2. @ 前必须是文本开始、空白或允许的标点边界;dev@example.com 与 @scope/pkg 不触发。
3. 先按唯一 handle 精确匹配(ASCII 大小写不敏感),再按唯一别名、唯一显示名(NFC 规范化)精确匹配。不做 LLM 猜人。
4. 同一成员被不同形式点名只生成一份投递;芯片 + 文本重复点名也只投一次。
5. 名称含空格时用 @「前端 小林」;@前端 小林 只按「前端」这个完整别名解析。
6. @前端你先看看 这种没有名字边界的写法不猜测拆分,界面提示「请在名字后加空格或标点(例如 @前端)」。
7. 重名、无法识别、成员已退出(旧别名 tombstone)都在发送前提示,可以选人或按普通文本发送——不会静默改投主代理。
8. @所有人 / @all 展开为发送时的活跃成员快照;@用户 只通知人类成员,不产生模型调用。

中文输入法处于 composition 阶段时 Enter 不会被抢走;Enter 发送、Shift+Enter 换行。

4.2 提交整体任务

建群时填「整体目标」,或直接在群里对主代理说一句整体目标(未点名时默认由主代理接收)。主代理随后:

1. 检查现状与约束;
2. 通过群工具落盘结构化计划(工作项、依赖、验收条件、假设);
3. 校验提交(依赖无环、每项有验收条件、负责人存在);
4. 依赖满足的任务才进入 ready 并派发,未满足的保持可见的等待状态;
5. 持续协调、组织验收。

「先规划」模式下计划只落盘、不派发,等用户启动。

4.3 用户直接改需求

@前端 把这个入口改成手机验证码。 这类明确指令走完整链路:保存原话 → 绑定目标任务 → 写成新的需求决定 revision(人类要求直接采纳)→ 标出确定性影响的任务并置 needsSync → 通知相关成员 → 要求每人回报同步状态。旧版本的通过结果不能直接沿用,必须按新版本重验。

@前端 为什么这样设计? 是提问,不会自动变成改代码的任务。

5. 群里能看到什么

- 面板:顶部是项目标题、状态、项目切换以及任务/成员入口。宽屏显示「项目群 / 时间线 / 任务与模型」三栏;空间不足时自动收起左右栏,入口变成抽屉,不会把聊天挤成一条缝。右上角的 Aa 提供标准 / 大 / 特大三档字号,选择保存在本机。
- 时间线:按天分隔;自己的消息在右侧气泡里,成员消息在左侧。代码围栏显示为代码块,行内代码、加粗与已投递的点名都有明确样式;悬停消息可以回复,或在输入框里 @ 对方。
- 输入区:毛玻璃输入卡片;@ 弹层支持键盘选择,引用条、接收人芯片与「将触达几位 AI 成员」的提示都在发送前可见。
- 成员栏:头像菜单提供 @ 他、查看成员、查看/切换模型、查看当前任务、暂停与退出;状态点与模型来源(成员固定/角色默认/项目默认/允许池)在行内可见。
- 任务与模型:同一栏分「任务 / 模型」两个标签。任务页有验收进度、任务卡(状态、版本、负责人、验收条件、依赖等待、产物核验状态)、项目决定与同步回执、投递与恢复;模型页是项目默认、角色默认、选型模式与允许池。
- 项目生命周期:左栏分「进行中 / 已归档 / 回收站」;右上角 … 提供暂停/恢复、归档、移入回收站、清理预览与永久删除。暂停、归档、回收站都先阻断新执行再请求停止,并重新读取真实成员状态;未确认停止时显示“停止未确认”,可重试核对或取消请求。恢复只会回到暂停态。移入回收站默认提示保留 30 天(trashRetentionDays),到期不会自动清除。永久删除需输入完整项目名并勾选确认,逐项释放插件独占资源,全部成功后只清理插件私有数据;源代码、借用会话、worktree 与宿主日志默认保留,并留下最小审计墓碑与删除审计;部分释放失败会停在“清理受阻”并可重试。
- 深度研究:主代理或用户可提出一次带范围、成员与预算的研究提议;群时间线上出现需要真实用户点击的审批卡。批准只覆盖当前 proposalRevision + scopeDigest,不会自动开始;可以拒绝、取消或调整范围/预算(调整会生成新版本并让旧批准失效),批准过期后不能启动。点击“开始研究”后经 ResearchGate 再核对项目版本、批准与预算,批准后为参与成员建立专用研究 Session(带 agent/pre-step 门禁、每研究运行锁、普通群工具禁用、写入路径真实解析门禁和 session 级用量归属;受监督原型暂不允许研究 Session 执行 shell,实验仍在受监督模式下由成员执行)。运行中可暂停/停止;归档/回收站会停止研究、撤销批准并释放专用会话,恢复后不能复用旧批准。重启后运行中的研究进入 PAUSED_RECONCILE,必须由人核对后才能恢复;多人类项目因无法验证具体审批人而 fail-closed。研究工具为 room_research_propose / get / start / hypothesis / experiment / finding / report / flowback,没有代理可调用的批准或删除入口。
- 投递状态是诚实的:已送达,尚未确认取用 与 对方本轮已取用 是两个不同状态,后者只在宿主真实报告取用后才出现。无法确认时显示 无法确认是否送达,正在核对,并停止自动重发。
- 技术细节不塞进群聊:工具执行与自然发言分开呈现,群消息只显示有意义的信息。

成员的正常回答会自动回到群里(每个群驱动轮次的最终回答),因此不会出现「代理明明回答了,群里却看不到」。工作中需要提前说话时用 room_send。

6. 权限与边界

- 作者身份由服务端根据真实调用者绑定;正文里写「我是老板」不会获得任何权限。
- 群成员只能读写自己加入的群;工具不接受可伪造的 senderId。
- 独立根会话显式应用项目的工作区与工具配置;设计/文档这类只做细节的成员会被真正移除写文件与 shell 工具(不是靠提示词请求它别改)。
- 宿主原生权限提示仍归宿主管理;群里的聊天不会被当成原生批准。
- 借用的用户会话:插件不会销毁它,也不会把它与项目无关的轮次发到群里。
- 生命周期操作只接受真实人类成员:代理不能调用暂停、归档、回收站或永久删除,也不能用聊天内容伪造确认;永久删除还需要完整项目名与明确勾选。
- 写入工作:git 仓库里每个写入尝试使用独立 worktree;非 git 或 worktree 创建失败时明确降级为串行写入并说明原因,不会声称已隔离。成员退出或失败后保留未合并变更,不自动删除工作目录。

7. 暂停、恢复、重启

| 操作 | 行为 |
| 暂停成员 | 停止该成员新的自动执行;消息与任务保留,新 @ 显示为待处理 |
| 恢复成员 | 先同步版本与未处理消息,再继续适用的任务 |
| 停止当前工作 | 请求取消当前轮次,保留待处理队列(不承诺已执行的动作被回滚) |
| 成员退出本群 | 终止新分配,保留历史作者身份;旧别名变 tombstone 不再误投新人;未完成任务转为待交接 |
| 暂停项目 | 先阻断新任务准入与成员唤醒,再请求停止运行中的成员;只有重新读取到成员已停止才进入“已暂停”,否则停在“停止未确认”,可重试核对或取消请求 |
| 恢复项目 | 只把已暂停项目恢复为 active,并重新校验/创建成员会话;失败会逐人报告 |
| 归档项目 | 先阻断执行并请求停止;确认停止后归档,保留消息、任务、决定、成果与模型绑定历史;恢复后回到“已暂停”,不会自动启动 |
| 移入回收站 | 立即进入停止阻断态并请求停止;确认停止后才写入可恢复快照并进入回收站;未确认时不会宣称“已删除”;源代码、借用会话、worktree 默认不删;默认提示保留 30 天 |
| 从回收站恢复 | 先校验移入时记录的结构快照与资源摘要,再恢复为“已暂停”;不重放旧副作用、不恢复旧审批 |
| 停止核对 / 取消请求 | 停止结果未知时项目显示“停止未确认”,可重试核对真实成员状态;尚未造成不可逆删除的请求可以取消并回到原状态 |
| 永久删除 | 只允许在回收站中执行;要求完整项目名与明确勾选,拒绝仍有成员运行的项目;逐项释放插件独占资源,全部成功后删除插件私有数据并保留最小审计墓碑;部分释放失败会停在“清理受阻”,保留数据并可重试 |
| 关闭群界面 | 只关闭视图,已启动任务继续 |
| 重启 Harness | 按群数据库恢复:群、成员、消息、任务、决定与投递账本;只恢复 active 项目的 owned 成员会话(暂停/归档/回收站的不恢复),不确定的投递在核对后才重试,并给出简短恢复报告 |

数据库使用 schemaVersion 与迁移前备份;单写者锁保证不会有第二个进程同时改同一个项目——第二个实例会被明确拒绝,而不是并发破坏数据。

8. 已知限制

这里只列最需要先知道的几条:

- 成员会话的文件与命令工具来自 memberAgentPreset:不配置时成员只有群协作类工具。预设是两段契约—— meta.agentPreset 只写会话头,真正的工具树由 agentPresets.mount() 挂到成员上下文上;插件两件都做(create 与 resume 都挂),两条路径都已在真实宿主验证:成员真跑 node --version、真写文件并通过验收。
- 生命周期操作不会假装成员已停止:归档/回收站会先阻断新执行,再请求停止,并重新读取真实 agent 状态;只有确认停止才进入目标状态,否则停在“停止未确认”(BLOCKED)。真实桌面端已实测:停止请求已发出时 confirmed=false,随后核对成功才归档。
- 项目生命周期是软删除闭环,不是“删库”:移入回收站只改变项目状态并保留全部插件数据;永久删除只清理该项目的插件私有记录、资源归属账本与插件拥有的会话,绝不默认删除源代码、用户工作区、借用会话、worktree 或宿主日志。插件无法证明清理的外部副本会如实保留并报告。回收站到期只做日期提示,不会自动清除。部分资源释放失败会进入“清理受阻”(PURGE_BLOCKED),保留数据并允许幂等重试。
- 可选源码 / 临时文件 / worktree 清理未实现:规范里的高级清理需要独立危险操作、逐路径授权、归属核验和宿主删除回执;本版不提供,清理预览会明确列出被保留的源码、worktree 与宿主日志。任何“清理源码”的操作都不应被当作已支持。
- 删除与研究审批都要求可验证的人类身份:项目里有多个活跃人类成员时,生命周期操作与研究审批会 fail-closed,而不是猜一个审批人。
- 深度研究是受监督原型,不是完整自主研究:已实现审批卡、scopeDigest/revision、取消/过期、预算预留、专用研究 Session(agent/pre-step 门禁、运行锁、按 researchId 精确归属用量、写入路径真实解析与 shell 禁用)、暂停/停止、归档/回收站撤销授权,以及可自动化的权限与恢复测试。尚未实现:共享成员会话的调用前拦截、自动研究编排/阶段循环、经验提示的产品层治理,以及完整真实研究演示。
- 插件必须被选为 bundle 才会生效。installed: true + enabled: false 时,插件的 cordis.patch.yml 整个不生效、loader 树里没有它的行,而且没有任何报错。必须把包名加进 profile package.json 的 dsh.profile.bundles。判定看三处:list_bundles.enabled、loader 条目、 boot-trace.jsonl 里是否有本进程的 activation.ready。
- 跨提供方验收需要宿主真实接入第二个提供方;只有一条路由时,跨提供方兼容性标为未实测(不用 Mock 替代)。
- 价格与费用只记真实用量,不显示金额:当前环境没有可靠价目来源,插件按"可靠价格缺失时显示未知"处理,所以留空而不编造。
- steer(运行中于步骤边界插入)与 queue(排到下一轮)的实际差异需要一次长工具调用来观察;界面会显示这一次实际用的是哪种。
- 群里的「活人感」是行为目标,不是提示词存在即成立:验收看的是真实依据、后续行动与产物,不按消息条数或情绪词评分。
- 非 git 项目没有文件系统级隔离,串行写入只是协作机制,不能阻止所有 shell 写入。
- 多窗口/多进程同时管理同一项目:单写者锁会拒绝第二个写入者。
- 源码热重载需要配置监听目录:插件若通过 junction 链接到 profile 之外,HMR 默认看不到 src/;把仓库目录加入 profile 的 hmr.root 即可就地重载,否则改完 src/ 需要重载宿主。

9. 开发与验证

生成浏览器半边(从 shared/ 单一来源内联,禁止手改生成区)
node scripts/build-client.mjs

语法闸门(含「禁止 import @deepseek-ai 包」检查)+ 生成物是否最新
npm run check

单元 + 集成测试
npm run test

客户端半边必须声明 inject

浏览器半边的 exports.inject 不能为空。客户端加载器会给每个条目一个 Cordis fiber,而未声明的服务不是"取不到",是读取就抛错,fiber 直接进入 failed;宿主随后的启动审计只报一句没有原因的:

web boot: 1 entry did not activate
dsh-project-room: failed

这就是桌面端启动不起来的直接原因。当前声明为 exports.inject = ['slots'](apply 需要槽位注册表)。凡是 apply() 中通过 ctx.xxx 直接读取的服务,都必须写进这个数组。

验证方式:npm run harness 会在真实 Chromium 里用一个只提供已声明服务的代理去执行 apply,一旦读了未声明的服务立刻报错——这条规则正是为了让"只报 failed、不给原因"的情况不再发生。

两个测试文件专门锁死曾经真实发生过的加载失败:

- tests/unit/activation-contract.test.js —— inject 声明必须覆盖 apply() 读到的每个服务(否则 Cordis 直接抛错,插件永远不激活);浏览器半边不得引用任何 chunk。
- tests/unit/client-materialize.test.js —— 按真实加载器契约在 Node 里物化浏览器半边,断言它只注册 sidebar.panellist:project-room 与 main:project-room,且只依赖 react / react/jsx-runtime。

10. 技术文档

- 深度研究技术文档——状态机、审批与范围冻结、预算账本、专用研究会话、证据协议、数据模型、威胁模型、恢复与测试覆盖。
预览分享卡片长什么样 ↓duxingxiake3/dsh-project-room
分享 · DeepSeek Harness Hub
duxingxiake3/dsh-project-room

让多个代理在同一项目群里分工协作并真实执行任务

这是你的仓库?认领条目

回到顶部