# dsh-plugins

> 为 DeepSeek Harness 增加会话级循环闹钟：按设定间隔自动给 agent 发送提醒消息，适合轮询检查、周期复盘等需要 agent 主动回头看的长时间任务。

## Metadata

- Author: [@Ephemeral-AI-Lab](https://github.com/Ephemeral-AI-Lab)
- Repo: <https://github.com/Ephemeral-AI-Lab/dsh-plugins.git>
- GitHub: [Ephemeral-AI-Lab/dsh-plugins](https://github.com/Ephemeral-AI-Lab/dsh-plugins)
- Stars: 44
- Language: Python
- License: [MIT](https://spdx.org/licenses/MIT.html)
- Topics: `dsh-plugin`, `dsh-plugin-market`, `dsh-plugins`
- Forks: 4
- Open Issues: 1
- Last push: 2026-08-20T20:04:56.000Z
- Added: 2026-08-20T00:00:00.000Z

## Install

```bash
dsh plugin --profile web add github:Ephemeral-AI-Lab/dsh-plugins/loop
```

## Wiki

> 落地页对应的仓库子路径是 `loop`，仓库中的承载目录也叫 `loop`，npm 包名 `dsh-loop`（`package.json:3`），是 `Ephemeral-AI-Lab/dsh-plugins` monorepo 下的子包之一。本百科聚焦 `loop` 路径对应的能力。

## 一句话定位
为 DeepSeek Harness 增加"会话级循环闹钟"：让当前会话里的 agent 按你设定的秒级间隔自动收到一条用户消息，从而周期性地回头做一件事——比如定时检查构建、轮询日志、阶段性复盘。

## 核心能力
- 用自然语言或工具创建循环闹钟：告诉 agent"每 30 秒提醒我看一下任务进度"，agent 会自动调用 `loop_create(prompt, time_in_seconds)` 落库。
- 三个 agent 工具一套共用：`loop_create` 新建、`loop_list` 列出当前会话活跃循环、`loop_delete(id)` 删除一个（`src/tools.ts:33-90`）。
- 用 `/loop` 命令操作同一个后端：`/loop <秒数> <提示>` 新建、`/loop list` 列出、`/loop delete <id>` 删除（`src/commands.ts:13-45`）。
- 到点自动投递给 agent：把提示打包成 `<heartbeat>` 用户消息送到 session inbox 并带 `wakeup:true`，空闲 agent 通过 next-turn 接收、运行中的 agent 通过 next-step 接收，不打断当前操作（`README.md:96-107`）。
- 状态持久化在会话事件日志里：循环定义和每次触发都写成 `loop/change` session 事件，定时器是进程局部的、会话恢复时按事件日志重建（`SPEC.md:115-121`）。
- Web 端有一个紧凑的 Loop dock：显示活跃数量、每条间隔、下次倒计时、完整 prompt，并带一键删除按钮（`src/ui/LoopsView.tsx:83-118`）。

## 技术实现
- **语言**: TypeScript（`tsc` 编译到 `lib/`，`package.json:11` 声明 `"type": "module"`）
- **关键依赖**:
  - `@deepseek-ai/cordis`（>=4.0.0）：宿主插件框架，`apply(ctx)` 走标准 Cordis effect
  - `@deepseek-ai/dsh-tools` / `@deepseek-ai/dsh-commands`：用 `defineTool` 注册三个工具、用 `ctx.commands.register` 注册 `/loop` 命令
  - `@deepseek-ai/dsh-session` + `@deepseek-ai/dsh-session-persistence`：把循环状态写进会话事件日志并 flush
  - `@deepseek-ai/dsh-client-ui-slots` + `@deepseek-ai/dsh-client-ui-conversation`：Web 端把 Loop dock 注入到 `conversation.input.dock` 槽位
- **架构模式**: Cordis 插件 + `cordis.patch.yml` 给宿主注入一行 `loop`。`apply(ctx)` 里监听 `agent/created` 事件，每个根 agent 绑一个 `LoopRuntime`，runtime 用 `setTimeout` 排下一次触发，到点调 `agent.send(..., 'next-turn'|'next-step', true)` 并回写 `loop/change` 事件；状态经一个 `loop` projection（`stateVersion: 1`）暴露给前端，事件类型 `loop/change` 通过运行时的 `dsh-session` 模块动态注册。
- **入口文件**: `loop/src/index.ts`（`export name = 'loop'`、`inject = ['tools','commands','agents','sessions','sessionPersistence','sessionProjections']`，`src/index.ts:13-14`）

## 适用场景
当一个 DSH 会话需要 agent 主动周期性回头看一眼——比如让 agent 每 20 秒自查最新错误并给修复建议、每 60 秒给草稿挑三个最弱的地方、每 10 秒检查构建是否还健康——都可以用这个插件：创建一条循环后，agent 不用你催就会按节奏自我触发，适合长时间运行、需要持续观察状态的场景。

## 前置依赖与兼容性
| 依赖 | 最低版本 | 说明 |
|---|---|---|
| `@deepseek-ai/dsh-tools` | `>=0.1.0-rc.5` | peerDependencies，`loop_create/list/delete` 三个工具的注册依赖 |
| `@deepseek-ai/dsh-commands` | `>=0.1.0-rc.5` | peerDependencies，`/loop` 命令注册依赖 |
| `@deepseek-ai/dsh-session` | `>=0.1.0-rc.5` | peerDependencies，写 `loop/change` 事件依赖 |
| `@deepseek-ai/dsh-session-persistence` | `>=0.1.0-rc.5` | peerDependencies，runtime 的 flush 依赖 |
| `@deepseek-ai/dsh-session-projection` | `>=0.1.0-rc.5` | peerDependencies，`loop` projection 注册依赖 |
| `@deepseek-ai/dsh-agent` | `>=0.1.0-rc.5` | peerDependencies，runtime 直接持有 `Agent` 实例 |
| `@deepseek-ai/dsh-llm` | `>=0.1.0-rc.5` | peerDependencies，`createUserMessage` 来源 |
| `@deepseek-ai/dsh-api-remotes` + `@deepseek-ai/dsh-client-runtime` + `@deepseek-ai/dsh-client-ui-conversation` + `@deepseek-ai/dsh-client-ui-slots` | 各 `>=0.1.0-rc.5` | peerDependencies，Web 端 Loop dock 注入必需；`package.json:18-25` 把前三个列在 `dsh.client.inject`，缺一加载不到 Web UI |
| `@deepseek-ai/cordis` | `>=4.0.0` | peerDependencies，宿主插件框架 |
| `react` | `>=18.2.0` | peerDependencies，Loop dock 是 React 组件 |
| `zod` | `^4.4.3` | dependencies，projection 的 schema 校验 |
| 平台 | DSH Web | `package.json:24` 显式声明 `dsh.client.platform: "web"`，命令行/桌面端未声明 |
| Node.js | 未声明 | package.json 没有 `engines` 字段；只有 devDependencies 里有 `@types/node ^22.20.0` |
| 原生模块 | 无 | 仅依赖上述纯 JS 包，无 node-gyp 构建项 |

## 安装方式
```bash
dsh plugin --profile web add github:Ephemeral-AI-Lab/dsh-plugins/loop
```

## 配置项
本插件无需额外配置。安装后重启 DSH 并新建会话即可使用，循环的间隔、提示词、ID 全部在运行时通过工具调用确定，不读取任何插件级配置文件或环境变量。

唯一会被校验的字段是 `time_in_seconds`（必须是正整数秒）、`prompt`（非空字符串）、`id`（非空且无首尾空白），这些是工具入参的硬约束，不算可配置项。

## 常见问题
**Q: 装完之后怎么用？**

A: 重启 DSH 并新建会话即可。在输入框打 `/loop 10 看一下构建状态` 就能立即创建第一条；agent 在会话里也能用自然语言要求"每 20 秒提醒我检查错误"自动调用 `loop_create`。无需新建 preset 或开关任何宿主配置。

**Q: 想改一个循环的间隔或提示词怎么办？**

A: v1 没有提供 `loop_update`/编辑/暂停/恢复/立即触发这一类操作（`SPEC.md:38-44` 明确列为非目标）。实际做法是先 `loop_delete` 再 `loop_create` 一次。

**Q: DSH 进程关掉之后循环还在跑吗？**

A: 不在。定时器是进程局部的，`README.md:119-121` 明确说"a stopped or cold process cannot run timers or wake itself"；会话恢复时 runtime 会按 `loop/change` 事件日志重建下一触发时间，所以休眠期间错过的提醒不会补送。

**Q: 不同会话之间能不能共享同一个循环？**

A: 不能。`SPEC.md:49-58` 规定每个循环归属于创建它的那个 session，其它会话既看不到也删不掉它；要做"全局循环"是 v2 的设计目标（见 `SPEC_V2.md`），v1 不实现。

**Q: 收到提醒时 agent 正在跑别的任务，会不会被打断？**

A: 不会。提醒是带 `wakeup:true` 的用户消息，runtime 根据 agent 当前状态投递：`'running'` 走 `next-step`，其它走 `next-turn`（`src/loop.ts:229`），即在下一个安全步骤边界处理，不抢断当前操作。

**Q: Web 端有可视化吗？**

A: 有。DSH Web 的对话输入框上方会显示一个紧凑的 Loop dock，展示活跃循环数量、每条的 `every Xs/m/h` 间隔、`next in …` 倒计时、完整 prompt 和一个一键删除按钮；循环达到 3 条以上会自动折叠成"X active loops · next in …"摘要（`src/ui/LoopsView.tsx:79-100`）。

**Q: 间隔能填小数或分钟/小时单位吗？**

A: 时间单位只能是秒。`time_in_seconds` 是正整数（`src/tools.ts:45`、`src/loop.ts:369-370`），需要分钟/小时就直接换算成秒再传。

**Q: 怎么卸载？**

A: 用对应的 dsh 卸载命令移除安装源即可；卸载后当前会话里还在跑的循环停止（runtime 随宿主 dispose），新会话也不再注册 `loop_create / loop_list / loop_delete` 三个工具和 `/loop` 命令。

## 上手难度
**入门** — 装好就能用，没有配置文件、没有原生模块、没有特殊 preset 要建；最快 30 秒就能发出第一条 `/loop 10 看一下构建状态`。

## 已知问题与限制
- v1 没有循环修改/暂停/恢复/立即触发 API（`SPEC.md:38-44`），改间隔或提示词必须先删再新建。
- 运行时是会话局部、进程局部的：DSH 进程停掉或系统睡眠期间定时器不触发，也不会补送错过的提醒（`SPEC.md:42-44`、`README.md:119-121`）。
- 循环归属于创建它的会话，跨会话共享、跨会话可视化是 v2 设计目标（`SPEC_V2.md`），v1 不支持。
- 单次 `setTimeout` 最大延迟 2,147,483,647 ms（约 24.8 天），由 `MAX_TIMER_DELAY_MS` 强制钳制（`src/loop.ts:17,255-257`），超过此上限的间隔会被切分到多个定时器重排。
- 只声明了 `dsh.client.platform: "web"`（`package.json:24`），命令行/桌面端是否可用源码中未明确。
- Web 端 Loop dock 只在至少有 1 条活跃循环时渲染（`src/ui/LoopsView.tsx:77`），没有循环时输入框上方不会出现该区域。
- 包内不修改 DeepSeek Harness 宿主代码，全部走 Cordis effect 和 DSH 公共 API（`SPEC.md:8-10`），但这也意味着宿主一旦更换 `dsh-session` 公开事件类型，插件对 `loop/change` 的注册会同步失效（`src/index.ts:18-25`）。

---

This document is auto-generated by [deepseek-plugin.org](https://deepseek-plugin.org). HTML page: [dsh-plugins](https://deepseek-plugin.org/plugins/Ephemeral-AI-Lab/dsh-plugins/loop)
Wiki generated by AI (model: `MiniMax-M3`)
