npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dshworks/dsh-watch

v0.2.0

Published

Background stream listeners that wake the DeepSeek Harness agent — put a watch on a command or file and receive new lines as in-session notices. Ships a daemon host so a watcher can run unattended for weeks.

Readme

dsh-watch

English | 中文

给数据流挂一个监听。它说话,agent 就醒 —— 哪怕正在空闲,哪怕现场没有人。

自带的 jobs 子系统只告诉 agent 任务结束了。dsh-watch 告诉它有东西开口了: 给长跑命令或持续增长的文件挂一个监听器,新出现的行按 pattern 过滤、按 tick 合批、 按字节封顶,作为会话内通知送达。

然后把人撤掉。把监听写进 profile 配置、挂上 daemon 宿主,你就得到一个开机自启、 空闲时零成本静默、连续数周被数据流唤醒的 agent。

ci npm powered by dsh license: MIT

安装

dsh plugin --profile web add @dshworks/dsh-watch
dsh --profile web

dsh plugin 会转发给 pnpm,所以 PATH 里要有 pnpm。除此之外不需要配置 —— 下一个会话里 watch 工具就可用了。

工具本体

watch(source: "command", command: "npm run dev", pattern: "error|warn|Ready", label: "dev")
→ Watch armed (watch-1) on command: npm run dev.

# …agent 继续干自己的活。当 dev server 打出 "Ready in 130ms",
# 一条通知把它唤醒:
[watch dev · watch-1] 1 line:
Ready in 130ms

也可以盯文件:

watch(source: "file", path: "/var/log/app.log", pattern: "ERROR|FATAL")

每个监听都是一等公民后台任务(kind 为 watch),因此标准接口原样适用: job_list 列出已布防的监听,job_output 取出某个监听积压的行,job_kill 撤防, 归属按会话隔离,结束时走普通的完成通知。这个插件只增加"听"这件事 —— 没有第二套生命周期,也没有第二个注册表。

| 行为 | 细节 | |---|---| | 数据源 | command(经 shell 能力启动一次,继承会话的沙箱策略与环境变量)· file(从当前末尾开始跟踪;已有内容一律不投递;被截断则从头重来;文件还不存在也可以先等着) | | 合批 | 一个 tick 内听到的所有行共用一条通知 —— 爆发式输出只花一次唤醒,而不是每行一次 | | 过滤 | 可选的 JavaScript 正则,只投递命中的行。失败特征也要写进去 —— 没声音不等于没问题 | | 唤醒预算 | 每个 owner 一个令牌桶:先允许 maxConsecutiveWakes 次连发,之后每 wakeRefillMs 回一个额度。用户消息被领取时直接加满 | | 事件预算 | 每个监听在 max_events 条通知后自行撤防并以 completed 结束;填 0 表示一直听下去 | | 字节上限 | 每条完整通知按 UTF-8 安全截断(含包装文本);job_output 保留有上限的积压,丢行时带明确的裁剪标记 | | 截断诚实 | 上游输出丢失(lossy 读)会作为标记行暴露出来,绝不吞掉 | | 生命周期 | 进程退出时先冲刷尾部再结算:completed(退出码 0)、failed(非零 —— 监听死了是一个发现,不是一段沉默)、killed(信号或撤防)。插件卸载会拆掉所有监听 | | 上限 | 每个 owner 的布防数量上限,超了就让这次调用明确失败 |

无人值守运行

一个连续盯一个月生态的 agent,不是一场对话。有两件事必须改,而两件都已在包里。

它不能变聋。 唤醒预算的存在,是为了不让一个失控的数据源把空闲 agent 无限循环唤醒。 "数连续唤醒次数、等下一条人类消息回血"这条规则,对有人坐在旁边的会话是对的 —— 对没人的会话就是一扇单向门:额度用完之后,每条通知都被注入到一个再也不会被唤醒的 空闲 agent 里。所以预算改成了令牌桶:额度随时间回来(wakeRefillMs,默认 60 秒), 而在桶空时到达的通知,会在额度回来的那一刻拿到一次补课唤醒。想要严格的 dsh-tool-jobs 语义,把 wakeRefillMs 设为 0

得有人去布防,也得有人让进程活着。 dsh --profile headless 跑完一个任务到静默 就退出;dsh --profile web 常驻,但要等浏览器里的人。于是 autoArm 把监听声明进 profile 配置 —— 在 agent/session-start 时为根会话布防,并且走工具注册表, 因此它要过的守卫、审批策略、沙箱和 shell 环境,跟模型自己发起的调用完全一致 —— 而 @dshworks/dsh-watch/daemon 是一个约 90 行的宿主:创建一个 agent、注入一份常驻 简报、把进程撑住,并把每个活动区间的收尾文本按 ISO 时间戳写到 stdout 作为运维日志。

# ~/.dsh/profiles/watcher/cordis.patch.yml
- id: dsh-watch
  config:
    wakeRefillMs: 300000
    autoArm:
      - source: command
        command: node recipes/ecosystem-watcher/feed.mjs --topic dsh-plugin
        pattern: '"kind":"new-repo"'
        label: ecosystem
        max_events: 0          # 会自己撤防的监听,算不上监听

- insert:
    - id: dsh-watch-daemon
      name: '@dshworks/dsh-watch/daemon'
      config:
        brief: >-
          You are the ecosystem watcher. A standing watch named "ecosystem"
          is armed on a feed of newly published repositories. For each one,
          decide whether there is an idea worth keeping, and append it to
          data/ideas.ndjson.
dsh plugin --profile watcher add @dshworks/dsh-watch
dsh --profile watcher | tee -a watcher.log

recipes/ecosystem-watcher/ 里是完整的一套, 包含一个按创建时间轮询 GitHub topic、对每个没见过的仓库输出一行 NDJSON 的 feed。

实测

2026-08-15 的一次真实运行,DeepSeek-V4-Pro,会话里没有人。feed 找到 53 个新发布的 dsh 仓库;watcher 被唤醒、读完、留下 11 个,并说明了另外 42 个为什么被放掉:

2026-08-15T16:21:23Z up — session 36041f74
2026-08-15T16:25:11Z Batch of 53 repos processed. Appended 11 ideas to data/ideas.ndjson
{"repo":"liustack/modlens","why":"Pasting an image and receiving structured JSON evidence
 (OCR, layout, semantics) gives text-only DSH models vision without a vision model.",
 "for":"awesome-dsh-plugins"}

这次运行还顺带换来一个 bug 修复:注入给忙碌 owner 的通知会在它的下一步被领取, 所以把它们算作"欠一次补课唤醒",就会多出一次唤醒,而那次唤醒的全部内容是 "你有排队的通知" —— 说的却是已经回答过的通知。改成在 agent/inbox/claimed 时清零, 并补了一个回归测试守住。

配置

每一项边界都是经过校验的 Config 字段,不是写死的常量。

| 字段 | 默认值 | 含义 | |---|---|---| | pollIntervalMs | 300 | 轮询节奏,同时也是合批窗口 | | maxNoticeBytes | 4096 | 单条完整通知(含头部)的 UTF-8 字节上限 | | maxConsecutiveWakes | 3 | 每个 owner 的唤醒额度桶容量 | | wakeRefillMs | 60000 | 回一个额度所需的毫秒数;0 表示不按时间回血 | | defaultMaxEvents | 50 | 每个监听的通知预算;0 表示不限 | | maxListenersPerOwner | 8 | 每个 agent 的布防数量上限 | | backlogBytes | 65536 | 单个监听 job_output 积压的保留字节预算 | | autoArm | [] | 启动时为根会话布防的常驻监听 |

daemon 自己的配置是 brief(必填)、flushIntervalMs300000)和 journaltrue)。

Model Experience

系统提示词

一段(order 107,排在后台任务指引之后):

You can arm a watch on a stream with the watch tool: it listens in the background and wakes you when new matching lines arrive, so never busy-poll a source you already listen to. Listeners are background jobs — job_list shows them, job_output reads a listener's heard-line backlog, job_kill disarms one.

配置了 autoArm 时,会追加第二段(order 108)列出常驻监听的名字, 免得模型把已经有的东西再布防一遍。

工具

只有一个工具 watch(source、command/path、workdir、pattern、max_events、label)。 撤防、列表、读取都复用自带的 job_kill / job_list / job_output

Token 影响

安静的数据源不花 token —— 轮询发生在宿主侧。每条通知是一条有字节上限的消息 (≤ maxNoticeBytes);空闲唤醒还要额外付它开启的那次模型请求, 这正是唤醒需要预算的原因。

依赖要求

  • jobs 子系统:@deepseek-ai/dsh-jobsdsh-jobs-localdsh-tool-jobs —— 都在 dsh-base 里,因此 web 与 headless 标准 profile 都自带。 没有挂上 job 控制器时,布防会明确失败
  • source: command 还需要 shell 能力(@deepseek-ai/dsh-shell 加一个 provider)。 文件源不需要。
  • daemon 另外需要 agentssessionsagentDefaultModel —— 同样在 dsh-base

开发

pnpm install && pnpm test    # 83 个测试

lib/ 里是纯 ESM JavaScript —— 安装时不构建任何东西,所以用 git 装不会碰到 allowBuilds。(开发安装会:vitest 会拉 esbuild,在 pnpm-workspace.yaml 里放行 —— pnpm ≥ 11 从那里读构建设置,package.json 里的 pnpm 字段会被静默忽略。)

除了测试套件,完整生命周期都在 0.1.0-rc.6 + DeepSeek-V4-Pro 的真实会话里验证过: 布防 → 不匹配的行保持沉默 → 空闲时命中即唤醒 → 用自带 job_kill 撤防 → 撤防后彻底安静(2026-08-14);以及启动 → 常驻简报 → 空闲 → 被无人值守的 feed 唤醒两次,从写入到回复约 1.6 秒(2026-08-15)。

与邻居的关系

  • 自带的 dsh-tool-jobs 在任务完成时通知;dsh-watch 在运行期间有输出时通知。 同一套唤醒机制,互补的两个时刻。
  • yoke233/dsh-tool-monitor 通过分流输出来订阅已经在跑的 bash/pwsh 任务。想盯一个你已经启动的任务用它; 想布一个带合批和预算的专门监听(或盯文件)用 dsh-watch。
  • AbnerAI/dsh-monitor 反复重跑一个命令、或轮询 NDJSON 收件箱,逐行唤醒 agent。dsh-watch 的不同在于: 命令只启动一次并按流处理、按 tick 合批、给唤醒和事件都上预算、每条通知都有字节上限、 活在 jobs 子系统内部,以及自带一个无人值守宿主。

已知限制与未做的事

  • 是轮询,不是 inotify/kqueue:低于 pollIntervalMs 的延迟不在范围内, tick 本身就是设计中的合批窗口。
  • 每个监听只有一个正则;多种特征用或来覆盖(error|Traceback|FAILED)。
  • 命令源的 stderr 混在 shell provider 的标记段落里,不是一条单独可过滤的通道。
  • 重启后不会自动恢复:监听与它的会话同生共死。重启后的 daemon 会开一个新会话并按 autoArm 重新布防,而不是接着上一个会话。
  • 补课扫描挂在监听的 tick 上,所以一个 owner 如果所有监听都被撤防了, 排队的通知会一直留到有别的东西唤醒它为止。

许可

MIT。与 DeepSeek 无隶属关系。已登记在 awesome-dsh-plugins