dsh-preset-minimal-fs
Verified@lynn123411/dsh-preset-minimal-fs · v0.1.2 · MIT
极简-文件:官方极简模式的身份+文件工具(read / write / edit),不含任何 shell。工具目录就是这三个:没有 bash / pwsh、没有检索 / read_image、没有 skills / 计划 / 目标 / 子代理,专门用来对照测试模型在近乎零工具、无命令执行下的能力。
Install
dsh plugin add @lynn123411/dsh-preset-minimal-fs Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Published to npm without a public repository. Inspect the package contents before installing.
Tags
Readme
minimal-fs — 极简文件测试模式
官方
minimal(极简模式)的身份,并入文件工具三件套(read/write/edit)——没有 shell。工具目录就是这三行:没有bash/pwsh、没有glob/grep、没有read_image、没有 skills / 计划 / 目标 / 子代理 / 网页。专门用来做模型能力对照测试——排除一切命令执行与工具编排的便利,只看模型靠「读文件 + 写文件」能走多远。
与官方极简模式的异同
官方 minimal(极简模式) |
本 preset(极简-文件) | |
|---|---|---|
| persona | prefix 即完整系统提示词(complete: true)、关闭运行时快照 |
逐字相同 |
| shell | 持久 shell(bash,Windows 下 pwsh) |
整组不含(PTY 服务、终端后端与工具行都没有) |
| 文件工具 | 无(宿主那条 tool-fs 行被 web 层禁用) |
read / write / edit(read_image 已移出模型可见目录) |
| 上下文压缩 | 无 | 无 |
指令文件(AGENTS.md) |
不加载 | 不加载 |
身份与官方极简模式逐字一致:固定提示词、无运行时快照、无工具指引段落。差别在于官方极简模式把文件访问完全交给 shell(cat / sed / heredoc),这里把 shell 整个拿掉,只留三个结构化文件工具——模型没有别的执行通道,读、写、改都只能走这三个工具。
组成
minimal-fs/
├── package.json # bundle 声明:exports["./tool-filter"] + dsh.bundle.patch
├── minimal-fs.patch.yml # preset 声明(@deepseek-ai/dsh-agent-preset 行)与其组合行
├── README.md
└── plugins/tool-filter/index.js # 目录过滤行(本包的 ./tool-filter 导出)
顶层三行:persona(身份)、tool-fs、tool-filter(文件工具与其目录过滤)。没有 agent 自有服务,所以也没有 isolate realm;sandbox、审批、fs 服务与观察策略(写前必须读)都留在宿主组合里。
声明形态
一个 preset 由**插件组合包(bundle)**声明:package.json 的 dsh.bundle.patch 指向本目录的 minimal-fs.patch.yml,该 patch 往 profile 树里插一条 @deepseek-ai/dsh-agent-preset 行;preset 的组合行整体进这一行的 config.plugins,显示名与描述是 config.name / config.description,preset id 是 config.id。
order: 5:官方四条 preset 占用 1–4(standard 1、ptc 2、minimal 3、cordis 4),本 preset 排在它们之后。
过滤行为什么写成包内子路径 @lynn123411/dsh-preset-minimal-fs/tool-filter:preset 行由声明它那棵树按该树的 baseUrl 导入。bundle patch 的行整体合入 profile 的根 include,所以这个 baseUrl 是 profile 目录,不是本 preset 目录——实测一条探针 preset 行看到的 baseUrl 是 file:///<DSH_HOME>/profiles/web/。因此 ./plugins/tool-filter/index.js 这种相对写法会落到 profile 下、永远够不到本目录;改用本包的 exports 子路径后,Node 从 profile 的 node_modules(即装进去的这份 bundle)解析到同一个文件。
为什么过滤点在 system-prompt/assemble
@deepseek-ai/dsh-tool-fs 一个包同时注册 read / write / edit / read_image,没有逐工具开关。下面几条路都试过、都不成立:
ctx.tools.restrict({ allow }):它筛的是本 scope 继承来的工具(全局层与祖先层),源码明确写了「never what its OWN layer registers」。preset 的模型可见行注册进的正是 preset 自己这一层,没有「继承来的工具」给它减 →read_image原样留下。- 兄弟行包
ctx.tools.register:loader 用Promise.allSettled(config.map(...))并发启动同一组合的所有行,所以「谁先 apply」是竞态;dsh-tool-fs的read/write/edit在它apply里同步注册,过滤器落地时它已经注册完了 → 仍然留下。 - 旧的相对路径行:preset 目录形态下成立(挂载把 baseUrl 改到组合目录),新形态下
baseUrl是 profile 目录,相对行必挂(见上节)。
可用的落点是 system-prompt/assemble 这个 waterfall:它的 assembly.tools 就是模型最终收到的工具 schema 数组(见 PromptAssembly 类型),返回的 assembly 是权威值。plugins/tool-filter/index.js 在那里按名单过滤——per-assembly、在本 preset 的 scope 内、不依赖行顺序、不碰上游包、不需要解析裸包名。这也正是官方自己隐藏 read_image 的机制(路由模型不支持图片输入时它就从该数组里被拿掉),属于设计内的缝。
过滤后 read_image 仍然注册在工具表里,只是不出现在模型目录中;直接点名调用它不会被过滤拦下,而这个 preset 的场景里没有别的调用方。
安装与启用
# 装进 profile(npm 包名)
dsh plugin --profile web add @lynn123411/dsh-preset-minimal-fs
# 本仓库开发副本:在仓库根执行,命令把目录 link 进 profile 并登记包名
dsh plugin --profile web add ./presets/minimal-fs
重启 DSH 后,在新建会话界面选择「极简-文件」即可。preset 的挂载在进程内只装载一次,改 minimal-fs.patch.yml 或 plugins/ 后要重启 DSH,不会热更已挂载的那一份。
验证
组合解析(必跑)——把本目录的 patch 叠到 web profile 上,看它能否进组合树:
node "<DSH 安装>/node_modules/@deepseek-ai/dsh/lib/bin.js" \
--profile web --patch presets/minimal-fs/minimal-fs.patch.yml --dump-config
# exit=0;输出里出现 preset-minimal-fs 行与其 config.plugins(persona / tool-fs / tool-filter)
--dump-config 只做组合、不装载,也不求值 !!js;它证明 patch 能解析,不证明工具目录。
工具目录(唯一可信的那条)——开一个本 preset 的真会话发一句话,然后读该会话日志里 request/header 记录的 data.header.tools(会话日志是 session.v4.jsonl.zstd):
D=~/.dsh/sessions/--Users-tny-Desktop-work-my-dsh--/session-<id>
zstd -dc "$D/session.v4.jsonl.zstd" | python3 -c "
import sys, json
for raw in sys.stdin:
raw = raw.strip()
if raw.startswith('{'):
try: obj = json.loads(raw)
except Exception: continue
if obj.get('type') == 'request/header':
print([t['name'] for t in obj['data']['header'].get('tools', [])])
"
期望输出 ['edit', 'read', 'write']——bash / pwsh 不出现,read_image 也不出现。UI 的「工具」面板只反映装配期的定义解析,不等于模型实际收到的目录——以会话日志为准。
适配实测记录(0.2.0-rc.2,2026-09-30)——隔离 DSH_HOME 建一个 web profile,用上面的 dsh plugin add 装本目录,再叠一条探针宿主行:等 preset 挂载后对它的 scope 调 systemPrompt.assemble({ scope }),打印行状态与模型可见目录。实测结果:
PROBE_ROWS ["persona=up","tool-fs=up","tool-filter=up"]
PROBE_TOOLS ["edit","read","write"]
PROBE_SECTIONS [{"name":"deployment:persona-prefix","text":"You are a helpful software engineer assistant."}]
PROBE_CONTEXTS []
反向对照(同组合、只去掉 tool-filter 行):模型可见目录变成 ["edit","read","read_image","write"]——read_image 确实是这一行移除的,不是它根本没注册。三条行全 up 说明过滤行是作为本包 ./tool-filter 导出被解析并激活的。
其它同样值得确认的点:系统提示词只有 You are a helpful software engineer assistant. 一句,AGENTS.md、技能目录、运行时快照都不出现(PROBE_CONTEXTS 为空)。