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

@falsenex/dsh-subprocess

v1.0.0

Published

Subprocess seam (ctx.subprocess) for the DeepSeek Harness — managed process groups, bounded spill-backed output, and escalated kills behind one abstract service

Readme


description: "面向组合作者与能力消费方的子进程服务(ctx.subprocess)说明:启动、观察并终止受管子进程与终端会话。" kind: "package-reference"

@falsenex/dsh-subprocess

English | 中文

概述

ctx.subprocess 可解析可执行文件、启动显式指定的子进程或真实终端会话、流式读取或有界收集输出,并终止完整的受管进程范围。每个组合配置一个 subprocess 实现,并根据命令运行位置选择本地或远程执行。每次请求都指定 argv、工作目录、stdio、环境覆盖、终止宽限期与取消信号,不会添加 shell 解释或隐藏的执行默认值。子进程环境会先移除环境中的凭据与 DSH_* 值,再应用显式覆盖;时限、拆卸策略与面向模型的渲染由调用方负责,收集的输出在进程退出后仍可读取。

目录


使用本包

在需要运行子进程的组合中挂载一个 subprocess 提供方,并从拥有该命令的能力调用 ctx.subprocess。常用路径是显式的:解析可执行文件、用完全明确的请求 spawn、读取你要的输出,并在工作完成时终止受管范围。

挂载服务

每个组合由唯一一个提供方注册 ctx.subprocess;把它与经由它 spawn 的消费方放在一起加载——bash 执行器、LSP 主机、PTY shell 后端或进程外 subagent 后端。加载第二个提供方会快速失败(每个上下文只有一个服务,这是 Cordis 的标准行为)。

- name: '@falsenex/dsh-subprocess-local'
- name: '@falsenex/dsh-bash-local'

启动受管进程

请求完全明确:程序与参数、工作目录、每条流一种 stdio 处置方式、终止宽限期、可选的中止信号与可选的环境覆盖。目标与受管范围标识保留在提供方内部。done 以直接命令的退出事实(exitCode 与 signal)resolve,并在 spawn 或提供方失败时 reject;收集输出在退出后仍可读取。

const executable = await ctx.subprocess.resolveExecutable('bash')
const handle = ctx.subprocess.spawn({
  argv: [executable, '-c', 'echo hello'],
  cwd: '/workspace',
  stdio: { stdin: 'ignore', stdout: { maxBytes: 64 * 1024 }, stderr: 'inherit' },
  graceMs: 5000,
})
const { exitCode, signal } = await handle.done
const output = handle.collected.stdout?.readFrom(0)

选择输出投递方式

  • 'pipe' 把原始流交给你做自己的协议分帧——LSP 主机用 JSON-RPC,ACP(Agent Client Protocol)后端用 ndjson。
  • 'inherit' 让子进程直接写父进程自己的流,用于直通诊断输出。
  • 收集对象(collect object)在内存中缓冲一段有界尾部;加上 spill 上限后,完整流还可以从 spill 文件中恢复。

读取基于偏移量且从不消费:后台读取与最终批量读取可以共享同一条流,而不会抢走彼此的字节。

使用控制管道

设置 stdio.control: 'pipe' 后,handle.control 会返回独立的原始 Duplex。Node 子进程通过 @falsenex/dsh-subprocess/control 的 openInheritedControlChannel() 打开 fd 7;该辅助函数会消费提供方拥有的 DSH_SUBPROCESS_CONTROL=pipe 标记。调用方不能通过 env 提供该标记。控制字节不会进入 stdout/stderr 收集器。消费方负责分帧、校验、背压和关闭自身端点;提供方销毁时会在进程拆卸后销毁仍存在的端点。省略请求则返回 control: undefined。该通道仅适用于普通进程,不授予绕过工具审批的权限。

管理进程生命周期

终止与等待使用同一个由提供方管理的范围。terminate() 会启动提供方记录的流程,具有幂等性,并在该范围为空后成为空操作;请求的中止信号会启动同一流程。waitForExit() 观察同一范围,只在提供方证明它完全停稳后 resolve,因此直接命令结束不会掩盖仍存活的后代。所选 owner 无法再证明完全停稳时,它会 reject。提供方记录其 native owner 与较弱 fallback;时限、拆卸阶梯与原因分类归调用方所有。

运行终端会话

对于交互式程序,spawnTerminal 分配真实 PTY:写入文本、读取 UTF-8 输出、检查当前前台进程组并向其发送信号,以及等待一次 terminate(),让提供方仍可观察到的每个会话成员完全停稳。就绪状态、scrollback 与提示符策略仍归 PTY 消费方所有。

终端请求可显式启用 shellActivity。inspectActivity() 结合支持的 shell 生命周期信号与自有任务观察,返回 idle、busy 或 unknown,以及句柄内的 revision。不支持或不完整的观察不能推出空闲;输入会使已有提示符证据失效。启用后,根 shell 退出时继续持有剩余工作,不把该退出视为终止后代进程的许可。保活和清理期限由消费者决定。

每个子进程起步时的环境

子进程永远不会隐式继承 harness 的环境秘密:形似凭据的名称与环境中的 DSH_* 事实都会被清除,调用方显式的 env 在该清除之后合并。有意转发的凭据或当前的 DSH_* 部署事实仍会到达子进程;显式的 undefined 墓碑值则移除一个普通的环境项。

可能出错的地方

无法解析可执行文件时,服务会明确报出稳定的错误。从未启动成功的 spawn 会让 done reject;从未运行过的进程没有任何缓冲输出。提供方无法证明所选范围为空时,waitForExit() 也会 reject;提供方 fallback 可能无法拥有逃离其进程组或已观察会话的后代。当传输拥有自己的 spawn(SDK 客户端、MCP)时,请绕开本服务并直接导入 scrubbedParentEnv,让环境策略保持单一来源。


理解实现

本节解释 seam 背后的设计决策,并指出实现它们的代码位置;可观察行为已在使用本包中说明。

设计理念

本 seam 建立在一个分离之上:服务负责进程坐标与生命周期;消费方负责定义进程的含义,以及决定塑造该进程的每一项默认值。正因如此,spawn 请求完全明确——没有任何隐藏的子进程服务默认值——SubprocessOutcome 也只携带退出事实:时限、拆卸阶梯与原因分类归调用方所有。dsh-shell 的 request/spec 拆分是这条规则的所属模板。

源码地图

| 文件 | 职责 | |---|---| | src/index.ts | 插件入口:抽象 SubprocessRuntime、ctx.subprocess 注册、共享的 scrubbedParentEnv 清除 | | src/types.ts | 词汇:spawn spec、stdio 模式、句柄、读取器、结果、DSH_* 命名空间 |

数据模型与流程

spawn 会立即返回活动句柄,而不公开目标身份。done 独立报告直接命令的结果或失败,waitForExit() 则报告受管范围是否完全停稳。请求的中止信号驱动与 terminate() 相同的终止流程。收集模式的读取器无游标:偏移量是调用方拥有的全流字节坐标,因此独立读取器不会消费彼此的输出,偏移量滑出内存尾部的读取标记为 lossy,并在 spill 文件存在时指向它。spawnTerminal 是一项底层原语,因为普通管道无法分配控制终端或清理终端会话成员。

生命周期与不变式

每个上下文只注册一个实现;加载第二个会抛错(Cordis 标准行为)。服务自身的 dispose(资源释放)会终止所有仍在运行的受管进程并等待其退出,因此进程生命周期在消费方重载后依然延续。argv 绝不经过 shell 解释;需要 shell 的消费方自行传入 ['bash', '-c', command]。终端分配的取消(spec 信号)与已发布句柄的生命周期相互独立。


进一步探索

当包级约定不够用时阅读以下页面。它们从穷尽式类型参考逐步进入各提供方,以及 seam 背后的决策证据。


终端消费者通过 terminalEnvironment() 读取 provider 平台和首选 shell,通过 resolveExecutable() 验证候选。确定未找到可执行文件时抛出 SubprocessExecutableNotFoundError,传输故障仍单独报告。spawnTerminal 要求 terminalType 和初始尺寸,返回的 handle 通过 resize(cols, rows) 调整尺寸,不重新分配进程。

模型体验

通过消费方 seam(例如 bash 执行器家族)间接影响,它们负责进程输出与生命周期的全部面向模型渲染。

KV Cache 影响

不会直接导致 KV Cache 失效;请求前缀变更由上述消费方负责。

已知限制与延期工作

这些限制说明该 seam 何时不合适,或何时把工作留给消费方。它们是当前包约束,不是对比或任务积压。

  • 由 SDK 管理的 spawn 仍在服务之外——拥有内部 spawn 的传输(SDK 客户端、MCP)无法把该调用路由到本服务;它仍可导入 scrubbedParentEnv,使环境策略保持单一来源。
  • 拆卸阶梯归消费方所有——该 seam 只提供信号动词与受管范围等待,不提供现成的完全停稳序列;每个进程外消费方自行编码其子进程的配合方式(ACP 后端以 stdin EOF 打头的阶梯是仓库内模板)。
  • 可观察性取决于提供方——native 提供方可以通过 systemd scope 或 Windows Job 拥有逃逸后代,fallback 提供方则只暴露较弱的进程组、进程树或会话可见性。该 seam 不新增持续的进程表监视器。

开发备注

本开发备注是维护者的工作上下文:开放设计问题与尚未决定的探索方向。它明确不具权威性——已交付的行为、限制与既定理由以上文、包代码和相关 Agent Note 为准。

未来:非 shell 运行器。该 seam 拆分的目的就是让直接 argv 执行器或 worker supervisor 无需深入 bash 内部即可消费它;目前尚无任何实现交付,终端原语也把就绪策略留在其消费方。