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

@niumoteam/node-plugin

v0.2.6

Published

TaskSync node plugin for deepseek-harness: keeps this harness connected to the TaskSync cloud as a worker node and runs dispatched tasks in-process through the harness's own agent engine (no ACP subprocess)

Readme

@niumoteam/node-plugin

TaskSync 工作节点插件 —— 直接运行在 deepseek-harness 进程内,反向出站连接 云端 TaskSync 并注册为工作节点;收到派发后通过 harness 自身的 agent 引擎 (ctx.agents)进程内执行任务,实时回传事件流。

替代原先 scripts/sidecar.ts 的独立 sidecar 进程方案:

| | 旧 sidecar | 本插件 | |---|---|---| | 进程模型 | 独立进程 + spawn deepseek-harness ACP 子进程 | harness 进程内直接执行 | | 资源占用 | 双份 harness | 零额外进程 | | 实时事件 | WS → ACP → WS 转发 | 进程内事件直接映射 | | HARNESS_PATH 配置 | 必需 | 不再需要(插件即 harness 的一部分) |

目录结构

plugins/tasksync-node/
├── build.mjs            # esbuild 构建脚本(host 半身自包含 + client 半身 __ModuleLoader__ bundle)
├── cordis.patch.yml     # dsh bundle patch:把插件插入 profile 组合树
├── package.json         # 声明 dsh.bundle / dsh.client + 构建/类型检查脚本
├── tsconfig.json        # 类型检查(paths 指向 harness 本地 .d.ts)
└── src/
    ├── index.ts         # 插件入口:Config / apply / 事件监听注册 / settings 接线
    ├── settings.ts      # settings 命名空间 schema + 本地 installSettingsSection 等价实现
    ├── cloud.ts         # 云端 WS 客户端(注册、心跳、重连、complete 缓存)
    ├── runner.ts        # 进程内任务执行器(agents.create + followup/whenIdle)
    └── client/          # 客户端半身:设置导航里的独立分区(与"插件"并列)
        ├── index.ts                    # client 插件 apply:注册 settings.section 分区
        ├── tasksync-card-controller.ts # staged-edit 表单 + credentials 写入(token)
        ├── TasksyncSection.tsx         # 分区页面(完整配置表单)
        ├── locales.ts                  # zh/en 文案(含导航 label)
        └── card.css.ts                 # 分区样式(<style data-plugin> 注入)

前置条件

  • deepseek-harness 仓库 checkout,与 TaskSync 仓库同级(或通过 HARNESS_REPO 环境变量指向其它位置)
  • Node.js ≥ 22(使用全局 WebSocket)
  • pnpm(dsh plugin 依赖)

构建

cd plugins/tasksync-node
npm install            # 安装 esbuild / typescript / react 类型等 devDependencies
npm run build          # 产物:lib/index.js(host 半身,自包含)+ lib/client.js(浏览器半身)
npm run typecheck      # tsc --noEmit

host 产物(lib/index.js)把唯一的运行时第三方依赖(@deepseek-ai/schemastery) 打进 bundle,因此无论插件以 link:/file:/registry 哪种方式安装都能加载。 这与 harness 兼容:cordis 校验插件 Config 只走 Standard Schema 接口 (Config['~standard'].validate),不依赖 schemastery 实例身份。

客户端产物(lib/client.js)是 harness 的 client-bundle 格式 (window.__ModuleLoader__.load({id, factory})):react / @deepseek-ai/cordis / dsh-client-* 等平台模块保持 external,由浏览器端模块表在运行时提供, 其余代码全部内联,产物除平台表外自包含。包通过 package.json 的 dsh.client + exports["./client"] 声明被发现。

构建脚本默认从与 TaskSync 同级目录找 deepseek-harness checkout(取其 vendor/schemastery 源码打包);harness 在其它位置时设 HARNESS_REPO。

开发机注意:连接性测试要求插件与网关共享同一 @deepseek-ai/dsh-typert-protocol 实例(装饰器标记表是模块私有 WeakMap)。插件目录用 npm install 会装 registry 副本导致测试端点失效;请把该包 link 到 harness 工作区: ln -s <harness>/packages/typert/protocol node_modules/@deepseek-ai/dsh-typert-protocol (link 之后不要再跑 npm install,否则会被替换)。通过 pnpm 安装发布版时 会自动去重到 harness 工作区同版本,无此问题。

安装到 profile

方式一:从 registry(发布后)

cd deepseek-harness
pnpm dsh plugin --profile <name> add @niumoteam/node-plugin

方式二:本地路径开发

cd deepseek-harness
pnpm dsh plugin --profile <name> add /path/to/TaskSync/plugins/tasksync-node

dsh plugin add 会把插件写入 profile 的 package.json 依赖并加入 dsh.profile.bundles(reconcilePlugins 依据 dsh.bundle 声明自动完成), 插件随 profile 一起 boot。

打包与发布

完整发布流程 + 排障速查见 PUBLISH.md(含 2FA/token/免费组织 access 等踩坑记录)。

cd plugins/tasksync-node
npm pack            # 生成 tasksync-node-plugin-<version>.tgz(prepack 自动跑 typecheck + build)
npm publish         # 发布;默认 registry 若是镜像需显式指定官方源:
                    #   npm publish --registry https://registry.npmjs.org

发布到公共 npm 时 @niumoteam 组织必须授予你(niumo)发布权限;若发布到 其它组织/scope,改 package.json 的 name 并同步修改 cordis.patch.yml 中的 name 字段(loader 按包名 import)。

包内只含 lib/index.js(自包含,含 schemastery 副本)、lib/client.js、 cordis.patch.yml、README.md、package.json。唯一运行时外部依赖是 @deepseek-ai/dsh-typert-protocol(连接性测试端点的装饰器标记必须与网关 共享同一模块实例;经 pnpm 安装时会去重到 harness 工作区同版本包)。其它 @deepseek-ai/* 均为编译期 type-only import,产物不含其运行时引用。

配置

必需:nodeId + token。三种配置入口,优先级从高到低:

  1. 设置面板(GUI):harness 的 设置 → TaskSync 节点(与"插件"/"模型" 并列的独立分区),所有字段可编辑;token 走凭证库(credentials 域),不会 进入设置文档。保存后重启 harness 生效。
  2. profile 的 cordis.patch.yml(~/.dsh/profiles/<name>/cordis.patch.yml)
  3. 环境变量(推荐承载机密)

方式一:设置面板(GUI)

设置导航里的 TaskSync 节点独立分区(不是插件页里的卡片):

| 字段 | 说明 | |---|---| | 节点 ID | 云端生成的节点 ID(TASKSYNC_NODE_ID) | | Token | 注册 token,写入凭证库(默认引用 TASKSYNC_NODE_TOKEN) | | Token 凭证引用 | 凭证引用名,默认 TASKSYNC_NODE_TOKEN | | 云端地址 | 默认 wss://niumo.leonsoft.cn | | 工作区白名单 | 每行一个 projectId=绝对路径 | | 模型名 | 注册时广告的模型名(不影响实际执行模型) | | 权限模式 | workspace-write / danger-full-access | | 派发超时(毫秒) | 默认 1800000 | | 调试帧输出 | 打印云端下发的每一帧 |

方式二:profile 的 cordis.patch.yml

- id: tasksync-node
  config:
    nodeId: '<云端节点 ID>'
    token: '<云端注册 token>'

方式三:环境变量

| 变量 | 说明 | 默认 | |---|---|---| | TASKSYNC_NODE_ID | 节点 ID(必需) | — | | TASKSYNC_NODE_TOKEN | 注册 token(必需) | — | | TASKSYNC_CLOUD_URL | 云端根地址 | wss://niumo.leonsoft.cn | | WORKSPACES | 工作区白名单:projectId=绝对路径,逗号分隔 | 空(可空,注册后自动同步云端 dev_path 兜底) | | MODEL | 注册时 capabilities.models 广告的模型名(不影响 agent 实际模型,agent 沿用 harness 自身默认模型) | 空 | | PERMISSION_MODE | workspace-write(越界权限请求一律拒绝)/ danger-full-access | workspace-write | | TIMEOUT_MS | 单轮派发超时(毫秒) | 1800000 | | SIDECAR_DEBUG_FRAMES | 1 时打印云端下发的每一帧 | 关闭 |

注意:GUI 可写优先级最高。patch 配置作为 settings 的 composition base 层, 一旦在 GUI 里保存过某字段,它以 user 层覆盖 patch/env,需在 GUI 卡片里 点"重置"才能回到 patch/env 值。

连接性测试

设置 → TaskSync 节点 分区底部的"测试连接"按钮:

  • 非破坏性探测:host 侧建一条临时 WebSocket 连云端 /ws/agent,发一帧 {"type":"ping"} 并等待服务端应答(云端对未知帧回 error 帧,任何应答即证明 握手与帧往返正常),随后关闭。不注册节点、不触碰正在运行的主连接 (云端对同一 nodeId 重复 register 是会话替换,因此测试绝不发 register)。
  • 展示:成功/失败徽标、往返耗时(毫秒)、服务端应答内容、主连接在线状态。
  • 端点:网关路由 tasksync-node/testConnection(TypertRemoteService 的 SRC 反射发现),浏览器经 /api RPC 调用。
  • 超时 8 秒;云端地址不可达、被拒、无应答均报失败。

设置面板的 harness 前提

2026-08-12 之后的 harness 无需任何改动:上游已改为 "registering is exposing" —— 插件注册 settings 命名空间即自动对浏览器暴露(api-proxy 不再持有任何白名单, WEB_SETTINGS_NAMESPACES 与 settings-not-exposed 错误码均已删除)。

旧版 harness(2026-08-12 之前) 才需要在 packages/host/apiproxy/src/api-proxy.ts 的 WEB_SETTINGS_NAMESPACES 数组里加 'tasksync-node' 并重新构建该包 —— 否则设置页该分区报 settings-not-exposed。

运行

cd deepseek-harness
pnpm dsh --profile <name>

启动后插件注册节点并保持连接:周期心跳(30s)、断线指数退避重连、断线期间完成的 任务 complete 帧缓存待重连补发。收到 dispatch 帧后校验目标路径在 workspaces 白名单内(云端 dev_path 兜底的工作区同样生效),随后在进程内 创建 agent 会话执行,assistant/message、tool/call 实时映射为云端 sessionUpdate 帧回传,整轮结束上报 complete。

安装排坑实录(务必先读)

以下问题均在真机安装中踩过,按出现频率排列。症状 → 原因 → 处理:

| 症状 | 原因 | 处理 | |---|---|---| | 启动即抛 tasksync-node 缺少 nodeId/token | nodeId/token 三种入口都没配到 | 按上文「配置」任一方式配好;profile 的 cordis.patch.yml 用 - id: tasksync-node 覆写 | | harness 起不来,报 Cannot find package 'node-pty'/'open' 等 | 仓库依赖没装全或构建产物缺失 | 仓库根目录 pnpm install && pnpm run build 后再启动 | | harness 起不来,报 EPERM ... ~/.dsh/... | 安装/启动命令跑在了 IDE agent 沙箱里,~/.dsh 写入被拦 | 在宿主终端执行 pnpm install 与启动命令 | | 设置面板能打开、其它 RPC 正常,唯独「测试连接」404 | 源码启动下的 src/lib 双模块分裂(见下节) | 按下节装 src 垫片 | | built bin 启动后行为和源码不一致,或报 client bundles not found | lib/、web 前端 dist/ 产物过期/缺失 —— built bin 不经 tsx,源码改动完全无效 | 仓库根目录 pnpm run build 后重启 | | 旧版插件(0.2.4 及更早)只设了 TASKSYNC_NODE_ID/TOKEN,节点连不上云端 | 该版本 env 兜底的 cloudUrl 默认是 ws://,云端强制 TLS 时握手失败 | 显式设 TASKSYNC_CLOUD_URL=wss://niumo.leonsoft.cn 或升级到 0.2.5+(默认已改 wss://) | | 挪动/删除 harness 仓库后,profile 里插件解析报模块找不到 | $DSH_HOME/profiles/node_modules 的 heal 符号链接锚定启动时的 checkout 位置,悬空后对解析不可见 | 从新 checkout 位置启动一次 harness(heal 幂等重指) |

大坑:源码启动(开发机)下 testConnection 404

机理:开发机上从源码跑 harness(npm run dsh,即 node --import tsx/esm)时, tsx 让仓库内 TS 代码经 tsconfig.base.json 的 paths 解析到工作区包的 src/;而 profile 里安装的本插件是纯 JS,经包 exports 解析到同一包的 lib/。于是同一进程加载了两份 @deepseek-ai/dsh-typert-protocol, @Remote 装饰器的标记表是模块私有 WeakMap —— 插件写进 lib 那份, Typert 网关(collectSrcClaims → remoteMethods)读 src 那份,永远读不到 → tasksync-node/testConnection 无人认领 → /api 落到固定路由表 → 404。

诊断(一条命令对比两侧解析结果,src vs lib 即中招):

cd deepseek-harness
echo "console.log(import.meta.resolve('@deepseek-ai/dsh-typert-protocol'))" \
  > packages/api/gateway/src/__probe.ts
node --import tsx/esm packages/api/gateway/src/__probe.ts        # → .../src/index.ts
node --import tsx/esm ~/.dsh/profiles/<name>/node_modules/@niumoteam/node-plugin/__probe.mjs \
  # 同目录放一个内容相同的 __probe.mjs             # → .../lib/index.js
rm packages/api/gateway/src/__probe.ts

Workaround(src 垫片):把插件嵌套目录里该包换成指向源码的垫片:

SHIM=~/.dsh/profiles/<name>/node_modules/@niumoteam/node-plugin/node_modules/@deepseek-ai/dsh-typert-protocol
rm -rf "$SHIM" && mkdir -p "$SHIM"
cat > "$SHIM/package.json" <<'EOF'
{ "name": "@deepseek-ai/dsh-typert-protocol", "version": "0.0.0-src-shim",
  "private": true, "type": "module", "main": "index.mjs", "exports": { ".": "./index.mjs" } }
EOF
cat > "$SHIM/index.mjs" <<'EOF'
export * from '/绝对路径/deepseek-harness/packages/typert/protocol/src/index.ts'
EOF

重启 harness 后 testConnection 应返回 200(可用 curl -X POST http://127.0.0.1:3080/api/tasksync-node/testConnection -H 'content-type: application/json' \ -d '{"type":"client-request","rpcId":"v","method":"tasksync-node/testConnection","payload":{"args":{}}}' 验证)。

注意:

  • profile 里执行 pnpm install 会清掉这个手工垫片,需重做;
  • 用发布产物/构建产物启动 harness(artifact 平面统一走 lib)则天然无此问题;
  • 根治要靠 harness 侧(如 @Remote 标记改用全局符号注册表而非模块私有 WeakMap), 已建议上游。

非源码启动(built bin / 安装版):分裂消失,剩这些坑

用构建产物启动(node apps/cli/lib/bin.js web,或未来 npm 安装版 dsh)时, 整进程统一走 lib/ 平面,上面的 src/lib 分裂与垫片都不需要。仍需注意:

  1. 产物新鲜度:built bin 不经 tsx 转译,源码改动完全无效;lib/ 或 web 前端 dist/ 缺失/过期会启动失败。拉新代码后先 pnpm run build。
  2. profile 升级切换:从旧版(0.2.4 + 手工垫片)切换过来时,重装即达干净状态 —— 0.2.5 依赖已 peer 化,pnpm 不会再把 @deepseek-ai/* 副本装进 profile。
  3. peer 版本范围:插件 peer 声明 ^0.1.0-rc.5,不含 harness 未来的 0.2.x 正式版;harness 大版本升级时要同步改插件 peer 范围并重新发布。
  4. cloudUrl 历史差异:0.2.4 env 兜底默认 ws://,0.2.5+ 默认 wss://; 只靠 env 回退的旧版部署建议显式设置 TASKSYNC_CLOUD_URL=wss://...。

给维护者:依赖声明铁律

@deepseek-ai/dsh-* 只能出现在 peerDependencies(+ 本地 typecheck 走 tsconfig.json 的 paths 指向 harness 仓库的 .d.ts),绝不能放进 dependencies。否则 pnpm 会把 npm 上的副本装进 profile 的 node_modules, 遮蔽 harness 的安装回退符号链接,同样造成进程内双模块(v0.2.4 → v0.2.5 已修复)。

卸载

cd deepseek-harness
pnpm dsh plugin --profile <name> remove @niumoteam/node-plugin