@dsh-fly/dsh-plugin-fly-mode 0.0.0-stage → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +79 -2
- package/cordis.patch.yml +399 -0
- package/package.json +32 -4
- package/tools/dsh-plugin-fly-binary/index.js +520 -0
- package/tools/dsh-plugin-fly-binary/package.json +23 -0
- package/tools/dsh-plugin-fly-blackbox/assets/client-blackbox/SKILL.md +163 -0
- package/tools/dsh-plugin-fly-blackbox/assets/client-blackbox/code/mitm_addon_template.py +302 -0
- package/tools/dsh-plugin-fly-blackbox/assets/client-blackbox/code/rules.example.json +52 -0
- package/tools/dsh-plugin-fly-blackbox/assets/client-blackbox/reference/case-ttw.md +157 -0
- package/tools/dsh-plugin-fly-blackbox/assets/client-blackbox/reference/checklist.md +133 -0
- package/tools/dsh-plugin-fly-blackbox/assets/client-blackbox/reference/playbook.md +228 -0
- package/tools/dsh-plugin-fly-blackbox/assets/client-blackbox/reference/rules.schema.md +76 -0
- package/tools/dsh-plugin-fly-blackbox/index.js +1453 -0
- package/tools/dsh-plugin-fly-blackbox/package.json +31 -0
- package/tools/dsh-plugin-fly-diag/index.js +772 -0
- package/tools/dsh-plugin-fly-diag/package.json +24 -0
- package/tools/dsh-plugin-fly-diag/wifi.js +402 -0
- package/tools/dsh-plugin-fly-guard/index.js +101 -0
- package/tools/dsh-plugin-fly-guard/package.json +26 -0
- package/tools/dsh-plugin-fly-pwn/index.js +583 -0
- package/tools/dsh-plugin-fly-pwn/package.json +23 -0
- package/tools/dsh-plugin-fly-recon/index.js +184 -0
- package/tools/dsh-plugin-fly-recon/package.json +23 -0
- package/tools/dsh-plugin-fly-reverse/index.js +178 -0
- package/tools/dsh-plugin-fly-reverse/package.json +23 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DSH Fly contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,80 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @dsh-fly/dsh-plugin-fly-mode
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
把 **Fly 安全模式**(agent preset `fly`)作为一个**可安装的 bundle 层**发出去:任何 profile
|
|
4
|
+
装上它之后就能服务 `fly` preset,于是跨 profile 共用的会话库里那些带 `fly` 标签的会话不再是
|
|
5
|
+
"看得见、拿不到"(宿主会抛 `agent-preset/not-found: Unknown agent preset: fly`)。
|
|
6
|
+
|
|
7
|
+
## 它是什么 / 不是什么
|
|
8
|
+
|
|
9
|
+
- **是**:一条 `- insert:` 声明(`id: preset-fly`,行表来自 `presets/fly/agent.cordis.yml`)。其中
|
|
10
|
+
**7 个 Fly 工具**(binary / reverse / pwn / diag / recon / blackbox / guard)的源码**内联在包内
|
|
11
|
+
`tools/`**,行表用**本包子路径**引用它们 —— 装这个包**不会**在 npm 上再拉这 7 个包;
|
|
12
|
+
**`fly-smart` 单独一个 plugin**:它是本包 `dependencies` 里**唯一**一项,行表保持裸名,
|
|
13
|
+
由 npm 装进 profile 的 `node_modules`(它变化最快,且与工作台面板是一个整体,不适合内联)。
|
|
14
|
+
- **不是**:不带 `dsh.client`(模式是 agent 平面,没有浏览器半边);不带 Fly 工作台
|
|
15
|
+
(console / diagnostics / netops / plugins / smart-panel 是各自独立的包);**不带**
|
|
16
|
+
`dsh-plugin-fly-shell`(那会在别人的 UI 上再画一层 Fly 外壳)。
|
|
17
|
+
- **不写 registry 的 `default:`**:默认模式归上游 `standard`。装上它 ≠ 默认变 fly —— fly
|
|
18
|
+
只是「设置 → Agent 预设」里多出来的一个可选模式。
|
|
19
|
+
- **不含三模型路由**:`brainRoute` / `handRoute` / `reviewRoute` 是**用户机器**上的状态
|
|
20
|
+
(`~/.dsh-fly/smart-routes.json`,面板写),本机那份值还是内网 provider。未被配置时工具会
|
|
21
|
+
大声报错并指路(行配置 `<field>Route` 优先,其次才是工作台抽屉)。
|
|
22
|
+
|
|
23
|
+
## `cordis.patch.yml` 是生成的,别手改
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# 在 dsh-fly 仓库里:
|
|
27
|
+
node scripts/build-fly-mode-bundle.mjs --out ../dsh-plugins/dsh-plugin-fly-mode/cordis.patch.yml
|
|
28
|
+
node scripts/build-fly-mode-bundle.mjs --out ../dsh-plugins/dsh-plugin-fly-mode/cordis.patch.yml --check
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
同源:它跑的是 `dsh-fly` 仓库里 `scripts/lib/fly-profile.mjs` 的 `seedAgentPreset()` —— dev 装配
|
|
32
|
+
(`pnpm setup:profile`)写进 `~/.dsh/profiles/fly/cordis.patch.yml` 的是**同一个函数**的输出。
|
|
33
|
+
`--check` 用于门禁(漂移即红)。
|
|
34
|
+
|
|
35
|
+
## 发布(0.1.3 起走 tag → OIDC,自动带 provenance)
|
|
36
|
+
|
|
37
|
+
- **以后每次发版**:升 `version` → 提交 → 打**注释 tag** → 推 tag;`.github/workflows/release.yml`
|
|
38
|
+
会自动 `npm publish --access public --provenance` —— **不需要 token、不需要 2FA、不需要人工批准**。
|
|
39
|
+
前提是包的「Settings → Trusted Publisher」按下面配好(**一次即可**):
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
Publisher GitHub Actions
|
|
43
|
+
Organization or user ethanchen669
|
|
44
|
+
Repository dsh-plugin-fly-mode
|
|
45
|
+
Workflow filename release.yml ← 只写文件名,不是 workflow 里的 name:
|
|
46
|
+
Allowed actions ☑ Allow npm publish ← 不勾只会"暂存",npm publish 会"成功"但什么都不发
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
重推同一个 tag **不会**重跑 workflow ⇒ 要重跑就换一个新 tag。
|
|
50
|
+
- **首次发布(≤0.1.2)走的是另一条路**:包在 npm 上还不存在 ⇒ 没有 Trusted Publisher 页面可填,
|
|
51
|
+
只能 `npm stage publish --access public` 再在网页上批准(`stage` 不需要 2FA)。
|
|
52
|
+
0.1.0 / 0.1.1 已废弃,**0.1.2 是最后一个用 stage 发出去的版本**。
|
|
53
|
+
- **验收三件**(必须**换缓存键**再读:registry 的 packument 会被 CDN 缓存,反复查同一把钥匙只会读到第一次的结果):
|
|
54
|
+
① `dist-tags.latest == 新版本`;② **`dist.attestations` 存在**(= provenance 成了);
|
|
55
|
+
③ `readme` 是**发布那一刻**的快照(改了 README 要等下一次发版才上 npm 页面)。
|
|
56
|
+
- 发布前两条硬要求:`repository.url` 与跑 workflow 的仓库**逐字一致**(`--provenance` 会校验,写错**直接拒发**);
|
|
57
|
+
发布目标钉在 `publishConfig.registry = https://registry.npmjs.org/` —— 本机默认 registry 是**内网镜像**。
|
|
58
|
+
|
|
59
|
+
## 安装
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# CLI 路径(web 等 profile);cwd 必须是 DSH_HOME
|
|
63
|
+
cd ~/.dsh
|
|
64
|
+
dsh plugin --profile=web add @dsh-fly/dsh-plugin-fly-mode@0.1.3 --registry=https://registry.npmjs.org/
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- 装完**必须重启那个进程**:引擎把层与服务缓存在**进程内**,刷新页面不够。
|
|
68
|
+
- **官方桌面版**归 app 独占(`dsh plugin` 会拒:`profile "desktop" is managed exclusively by the
|
|
69
|
+
Electron application`)⇒ 在 `~/.dsh/profiles/desktop/` 里 `pnpm add …@0.1.3 --registry=…`,
|
|
70
|
+
并且要把包名加进 `package.json` 的 **`dsh.profile.bundles`** —— 那一条才让它成为一层
|
|
71
|
+
(只写 `dependencies` 是不会生效的)。
|
|
72
|
+
|
|
73
|
+
## 仓库状态(2026-10-11)
|
|
74
|
+
|
|
75
|
+
- 形状定稿:一条 `- insert:` 声明 + 包内 `tools/`(7 个工具内联,行表用本包子路径引用)+
|
|
76
|
+
`dsh-plugin-fly-smart` 作为**唯一** npm 依赖。声明由 `dsh-fly` 仓的
|
|
77
|
+
`scripts/build-fly-mode-bundle.mjs` 生成,门禁用 `--check` 断漂移(含多出来的文件)。
|
|
78
|
+
- `.github/workflows/{ci,release}.yml` **已适配本仓**(纯声明包:不装依赖、直接跑
|
|
79
|
+
`node scripts/verify.mjs`),CI 已在公开仓实测全绿,含 `fetch-depth: 0` 的**全历史署名硬门**。
|
|
80
|
+
- 身份已按规范设好(仓级 `user.email = ethanchen669@users.noreply.github.com`)。
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
# 由仓库脚本生成,别手改:node scripts/build-fly-mode-bundle.mjs --out <本文件>
|
|
2
|
+
# 同源:这段声明来自 scripts/lib/fly-profile.mjs 的 seedAgentPreset()(dev 装配写进 profile 的
|
|
3
|
+
# 是同一条);8 个工具的行名被改写成**本包的子路径**(tools/**,随包一起发布)。
|
|
4
|
+
# 门禁用 --check 断言本文件与 tools/** 都 == 生成器输出。
|
|
5
|
+
# 不含三模型路由(用户机器状态)、不写 registry default(默认归上游 standard)。
|
|
6
|
+
- insert:
|
|
7
|
+
- id: preset-fly
|
|
8
|
+
name: '@deepseek-ai/dsh-agent-preset'
|
|
9
|
+
config:
|
|
10
|
+
id: fly
|
|
11
|
+
name: "Fly 安全"
|
|
12
|
+
description: "功能完整的编码 Agent,附带 Fly 安全/CTF 工具链(binary / reverse / pwn / diag / recon)。"
|
|
13
|
+
order: 10
|
|
14
|
+
plugins:
|
|
15
|
+
# Fly 的 agent preset:完整编码 agent + Fly 安全工具链。每个进程挂载一次。
|
|
16
|
+
#
|
|
17
|
+
# **怎么被挂上去的**:0.1.7-rc.2 的 `dsh-agent-preset-registry` 只从
|
|
18
|
+
# `@deepseek-ai/dsh-agent-preset` **声明行**组合 preset;`$DSH_HOME/.agent-presets/`
|
|
19
|
+
# 已经没人读了。声明行由 `scripts/lib/fly-profile.mjs` 的 `seedAgentPreset()` 从本文件
|
|
20
|
+
# 生成到 profile 的 patch 层(`- insert:` 一条 `preset-fly`,外加只写一次的 registry
|
|
21
|
+
# `default: standard` —— **默认模式留给上游**,见那个块里的注释:官方 Web / 官方桌面版
|
|
22
|
+
# 各自从自己的 profile 读同一个字段,装皮肤的人不该替它们决定默认模式;Fly 模式在
|
|
23
|
+
# 「设置 → Agent 预设」里可选、可设为默认)。
|
|
24
|
+
# 改本文件后重跑 `pnpm setup:profile` 即生效。
|
|
25
|
+
#
|
|
26
|
+
# This file is an AGENT-PLANE composition. The roster mounts it ONCE under a
|
|
27
|
+
# standing scope; every session naming it joins by scope parentage, so the
|
|
28
|
+
# tools and prompt sections registered here cover each joined agent while a
|
|
29
|
+
# session's own state stays keyed per Session/Agent inside the plugins. The
|
|
30
|
+
# host composition (`base.cordis.yml` + `web.cordis.yml`) keeps everything a
|
|
31
|
+
# preset must not own: the registries themselves, the sandbox and approval
|
|
32
|
+
# stack, persistence, and the model route.
|
|
33
|
+
#
|
|
34
|
+
# A service row here MUST sit inside a group carrying an `isolate` realm.
|
|
35
|
+
# Without one it publishes into the root realm, where it is process-global —
|
|
36
|
+
# another preset publishing the same name collides, and a host reader would
|
|
37
|
+
# resolve one preset's instance for every session; `dsh-agent-presets` rejects
|
|
38
|
+
# that at mount. `true` means an entry-local realm: this standing mount's own
|
|
39
|
+
# private instance, apart from every other preset's. (A shared label does NOT
|
|
40
|
+
# pool instances — `provide()` throws on the second registration under the
|
|
41
|
+
# same realm symbol; labels join REALMS, and are not what this file needs.)
|
|
42
|
+
|
|
43
|
+
# ── identity ────────────────────────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
# The preset's own persona, shadowing the deployment default for this agent.
|
|
46
|
+
# `{{model}}` and `{{cwd}}` resolve from the agent's own route and workspace.
|
|
47
|
+
#
|
|
48
|
+
# `prefix`/`suffix` are the schema (`dsh-persona`: `prefix` required, `suffix`
|
|
49
|
+
# defaulted, `text` is a *boolean* interpolation switch). A `text: <string>` row
|
|
50
|
+
# used to sit here: it is not this plugin's config, so the row failed to activate
|
|
51
|
+
# and — because a preset mounts as one composition — the rejected row took the
|
|
52
|
+
# whole Fly preset down with it (symptom: sessions that never become composable).
|
|
53
|
+
- id: persona
|
|
54
|
+
name: '@deepseek-ai/dsh-persona'
|
|
55
|
+
config:
|
|
56
|
+
prefix: You are a coding agent powered by the {{model}} model.
|
|
57
|
+
suffix: Your working directory is {{cwd}}.
|
|
58
|
+
|
|
59
|
+
- id: agent-instructions
|
|
60
|
+
name: '@deepseek-ai/dsh-agent-instructions'
|
|
61
|
+
config:
|
|
62
|
+
maxBytes: 65536
|
|
63
|
+
|
|
64
|
+
# ── shell ───────────────────────────────────────────────────────────────────
|
|
65
|
+
|
|
66
|
+
# `shell-env` stays in the HOST composition: `apps/cli/src/web.ts` injects it to
|
|
67
|
+
# publish `DSH_WEB_URL`/`DSH_WEB_MODE`, and a host row that injects a service is
|
|
68
|
+
# the criterion for host-plane ownership — injection resolves before any session
|
|
69
|
+
# exists, so there is no agent to key by. Behind a preset realm those variables
|
|
70
|
+
# never reached the model's shell at all. Both shell tools consume the host
|
|
71
|
+
# registry from here; their executors (`bash-sandbox`/`pwsh-sandbox`) are
|
|
72
|
+
# host-plane too.
|
|
73
|
+
- id: tool-bash
|
|
74
|
+
name: '@deepseek-ai/dsh-tool-bash'
|
|
75
|
+
disabled: !!js process.platform === 'win32'
|
|
76
|
+
|
|
77
|
+
- id: tool-pwsh
|
|
78
|
+
name: '@deepseek-ai/dsh-tool-pwsh'
|
|
79
|
+
disabled: !!js process.platform !== 'win32'
|
|
80
|
+
|
|
81
|
+
# ── filesystem ──────────────────────────────────────────────────────────────
|
|
82
|
+
|
|
83
|
+
# Both register into the host `tools` registry and provide nothing, so
|
|
84
|
+
# they need no realm. The `fs` service and its policy stay in the host.
|
|
85
|
+
- id: tool-fs
|
|
86
|
+
name: '@deepseek-ai/dsh-tool-fs'
|
|
87
|
+
|
|
88
|
+
- id: tool-fs-search
|
|
89
|
+
name: '@deepseek-ai/dsh-tool-fs-search'
|
|
90
|
+
config:
|
|
91
|
+
sampleOverCapGlobResults: false
|
|
92
|
+
|
|
93
|
+
# ── background jobs ────────────────────────────────────────────────────────
|
|
94
|
+
|
|
95
|
+
# Only the model-facing controls. The task REGISTRY stays on the host plane:
|
|
96
|
+
# its producers sit outside any realm this file could put it in — `tool-bash`
|
|
97
|
+
# above resolves it with `ctx.get`, and an entry-local realm here is invisible
|
|
98
|
+
# to every sibling row, so `run_in_background` would answer "background jobs
|
|
99
|
+
# unavailable" while these controls sat in the catalog. The registry is keyed by
|
|
100
|
+
# owning agent anyway, so one host instance serves every session. What a preset
|
|
101
|
+
# chooses is whether its agent can collect and stop background work at all.
|
|
102
|
+
- id: tool-jobs
|
|
103
|
+
name: '@deepseek-ai/dsh-tool-jobs'
|
|
104
|
+
|
|
105
|
+
# ── skills ──────────────────────────────────────────────────────────────────
|
|
106
|
+
|
|
107
|
+
# The skill REGISTRY lives in the host composition and is layered per scope:
|
|
108
|
+
# these rows register into THIS preset's layer of it, so they need no realm.
|
|
109
|
+
# `skill-filesystem` contributes local-root discovery for agents on this preset, and
|
|
110
|
+
# `tool-skill` gives them the catalog and loader; the merged catalog also
|
|
111
|
+
# carries whatever the deployment registered globally (repository plugins).
|
|
112
|
+
#
|
|
113
|
+
# `customSkillDirs` 借的是官方**创造模式**自带的那四份 skill
|
|
114
|
+
# (`agent-experience` / `cordis-plugin-development` / `editing-cordis-compositions` /
|
|
115
|
+
# `cordis-composition-reference`):它们随 `@deepseek-ai/dsh-agent-preset` 出货,
|
|
116
|
+
# 创造模式用下面这条完全相同的表达式挂它们(见
|
|
117
|
+
# `@deepseek-ai/dsh-web-app/presets/cordis.patch.yml` 的 `skill-filesystem` 行)。
|
|
118
|
+
#
|
|
119
|
+
# 为什么 Fly 要借:Fly 的定位就是"用 DSH 扩展 DSH"——本仓库的装配(手写 `- insert:`
|
|
120
|
+
# 补丁 + `fly-bundle.mjs` 打包)与官方创造模式的运行时路径是**同一条**(preset registry
|
|
121
|
+
# 的 README:新建 preset 只能是 bundle 补丁 + 装上 profile)。这四份 skill 是上游对那条
|
|
122
|
+
# 路径的说明书,且随包更新;我们自己的 `docs/analysis/dsh-plugin-composition-rules.md`
|
|
123
|
+
# 是它的手工版本。**门禁**:`acceptance fly-shell` 在真会话的 `/` 菜单里按名过滤出它们
|
|
124
|
+
# (`/cordis` 与 `/agent-experience` 都要命中、乱敲一个名字必须 0 行)——只声明不生效会红。
|
|
125
|
+
#
|
|
126
|
+
# 表达式逐字照抄,别"简化":`baseUrl` 是 Loader 求值 `!!js` 时的配置基准(app-boot:
|
|
127
|
+
# `ctx.baseUrl = new URL('.', pathToFileURL(filename)).href`),`createRequire(baseUrl)` 从
|
|
128
|
+
# **profile 目录**向上找 `@deepseek-ai/dsh-agent-preset`(它在 `profiles/node_modules` 里,
|
|
129
|
+
# dev 与打包两条路都把引擎闭包铺在那儿),所以不需要新加依赖。
|
|
130
|
+
- id: skill-filesystem
|
|
131
|
+
name: '@deepseek-ai/dsh-skill-filesystem'
|
|
132
|
+
config:
|
|
133
|
+
customSkillDirs:
|
|
134
|
+
- !!js process.getBuiltinModule('node:path').join(process.getBuiltinModule('node:path').dirname(process.getBuiltinModule('node:module').createRequire(baseUrl).resolve('@deepseek-ai/dsh-agent-preset/package.json')), 'skills')
|
|
135
|
+
|
|
136
|
+
- id: tool-skill
|
|
137
|
+
name: '@deepseek-ai/dsh-tool-skill'
|
|
138
|
+
|
|
139
|
+
# ── goals ───────────────────────────────────────────────────────────────────
|
|
140
|
+
|
|
141
|
+
# The goal service and session driver stay on the host plane, where the Gateway
|
|
142
|
+
# can resolve them. The human command and model-facing tool register into this
|
|
143
|
+
# preset's scoped layers.
|
|
144
|
+
- id: command-goal
|
|
145
|
+
name: '@deepseek-ai/dsh-command-goal'
|
|
146
|
+
|
|
147
|
+
- id: tool-goal
|
|
148
|
+
name: '@deepseek-ai/dsh-tool-goal'
|
|
149
|
+
|
|
150
|
+
# ── plan mode ───────────────────────────────────────────────────────────────
|
|
151
|
+
|
|
152
|
+
# Plan state is per-agent by nature, so an entry-local realm is not a
|
|
153
|
+
# workaround here — it is the correct lifetime.
|
|
154
|
+
- id: planning
|
|
155
|
+
name: cordis:group
|
|
156
|
+
group: true
|
|
157
|
+
isolate:
|
|
158
|
+
planMode: true
|
|
159
|
+
config:
|
|
160
|
+
- id: plan-mode
|
|
161
|
+
name: '@deepseek-ai/dsh-plan-mode'
|
|
162
|
+
config:
|
|
163
|
+
section: |
|
|
164
|
+
You are in plan mode. Stay in plan mode until exit_plan_mode succeeds or the user switches the session mode. Imperative language to implement changes means plan the implementation, not execute it. A user's conversational agreement — including an answer confirming something you asked — approves nothing and does not end plan mode; fold the confirmed decision into the plan and submit it through exit_plan_mode.
|
|
165
|
+
|
|
166
|
+
Explore first. Use non-mutating reads, searches, static analysis, and checks to ground the plan in the actual repository. Do not edit or write files, change configuration, run formatters or code generation that rewrites tracked files, commit, or otherwise carry out the plan. Prefer existing functions and patterns over new machinery.
|
|
167
|
+
|
|
168
|
+
The tool catalog stays the same across modes for request-cache stability. These plan-mode rules override any later tool description or guidance that suggests using mutation tools; those tools remain listed to keep the tool catalog unchanged. Do not use todo_write to track this planning phase: it tracks implementation after an approved plan, while the plan itself belongs in exit_plan_mode.
|
|
169
|
+
|
|
170
|
+
Resolve discoverable facts by inspection. Use ask_user_question only for user-owned choices or material ambiguity that inspection cannot answer. Do not ask the user where code lives or how current behavior works when you can find out.
|
|
171
|
+
|
|
172
|
+
Make the plan decision-complete: state the goal and success criteria; group implementation changes by subsystem; identify public API, schema, and data-flow changes; cover edge cases, failure modes, tests, acceptance criteria, and explicit assumptions. Keep it concise enough to review but detailed enough that another engineer can implement it without making design decisions.
|
|
173
|
+
|
|
174
|
+
When ready, call exit_plan_mode with the complete plan markdown, starting with a # title. Make exit_plan_mode the only and final tool call in that assistant response: it presents the plan for approval, and implementation begins only in a later step after approval. Do not paste the final plan as a plain reply or ask "should I proceed?" through prose or ask_user_question. If review rejects it, incorporate the feedback and present again. If the review channel is unavailable or aborted, stay in plan mode and ask the user to switch modes manually; do not proceed with implementation.
|
|
175
|
+
|
|
176
|
+
# ── compaction ──────────────────────────────────────────────────────────────
|
|
177
|
+
|
|
178
|
+
# `compaction-basic` reads `toolResultPrune` through `ctx.get`, so the pruner must
|
|
179
|
+
# share this realm rather than sit outside it.
|
|
180
|
+
#
|
|
181
|
+
# `tokenMeter` is deliberately NOT in this realm: the meter stays on the HOST
|
|
182
|
+
# plane, and the rows here resolve that one instance. It takes no configuration,
|
|
183
|
+
# keys every fold by Session, and owns the context-meter projection units the
|
|
184
|
+
# browser reads for every session — behind a realm those units would come and go
|
|
185
|
+
# with whichever presets happen to be mounted. What a preset chooses is whether
|
|
186
|
+
# its agent compacts at all, which is `compaction-basic` below.
|
|
187
|
+
- id: compaction
|
|
188
|
+
name: cordis:group
|
|
189
|
+
group: true
|
|
190
|
+
isolate:
|
|
191
|
+
compaction: true
|
|
192
|
+
toolResultPruner: true
|
|
193
|
+
config:
|
|
194
|
+
- id: compaction-basic
|
|
195
|
+
name: '@deepseek-ai/dsh-compaction-basic'
|
|
196
|
+
|
|
197
|
+
- id: command-compact
|
|
198
|
+
name: '@deepseek-ai/dsh-command-compact'
|
|
199
|
+
|
|
200
|
+
- id: tool-result-pruner
|
|
201
|
+
name: '@deepseek-ai/dsh-compaction-tool-result-pruner'
|
|
202
|
+
config:
|
|
203
|
+
thresholdChars: 8192
|
|
204
|
+
headChars: 4096
|
|
205
|
+
tailChars: 1024
|
|
206
|
+
|
|
207
|
+
# ── delegation and workflows ────────────────────────────────────────────────
|
|
208
|
+
|
|
209
|
+
# The `subagents` registry and its spawn/fork backends live in the HOST
|
|
210
|
+
# composition: the registry is a process singleton whose cross-session queries
|
|
211
|
+
# the api-proxy serves to the browser, and a provider name may only be
|
|
212
|
+
# registered once. This preset contributes the delegation TOOLS, which resolve
|
|
213
|
+
# that host registry.
|
|
214
|
+
#
|
|
215
|
+
# `workflows` is different — nothing outside an agent reads it — so every row
|
|
216
|
+
# that reaches it shares one entry-local realm here, and a consumer left
|
|
217
|
+
# outside would resolve a host registry this preset does not populate.
|
|
218
|
+
- id: delegation
|
|
219
|
+
name: cordis:group
|
|
220
|
+
group: true
|
|
221
|
+
isolate:
|
|
222
|
+
workflowEngine: true
|
|
223
|
+
config:
|
|
224
|
+
- id: tool-subagent-control
|
|
225
|
+
name: '@deepseek-ai/dsh-tool-subagent-control'
|
|
226
|
+
|
|
227
|
+
- id: tool-subagent-list-agents
|
|
228
|
+
name: '@deepseek-ai/dsh-tool-subagent-control/list-agents'
|
|
229
|
+
|
|
230
|
+
- id: tool-subagent
|
|
231
|
+
name: '@deepseek-ai/dsh-tool-subagent'
|
|
232
|
+
config:
|
|
233
|
+
provider: spawn
|
|
234
|
+
toolName: subagent
|
|
235
|
+
modelSelectionSettings: true
|
|
236
|
+
backgroundMode: continuable
|
|
237
|
+
|
|
238
|
+
# Fork omits model selection so provider/model stay equal to the parent and
|
|
239
|
+
# the inherited history remains eligible for KV Cache reuse. This preset
|
|
240
|
+
# keeps fork continuable; parent and child inherit the same messaging tool,
|
|
241
|
+
# while the parent id and return guidance follow the inherited history.
|
|
242
|
+
- id: tool-subagent-fork
|
|
243
|
+
name: '@deepseek-ai/dsh-tool-subagent'
|
|
244
|
+
config:
|
|
245
|
+
provider: fork
|
|
246
|
+
toolName: subagent_fork
|
|
247
|
+
backgroundMode: continuable
|
|
248
|
+
|
|
249
|
+
# Production dsh does not install these optional providers. Install the
|
|
250
|
+
# matching Bundle in this Profile and restart the Host, then copy this
|
|
251
|
+
# preset and remove `disabled` from the matching tool row. Host availability
|
|
252
|
+
# alone grants no tool.
|
|
253
|
+
- id: tool-subagent-codex
|
|
254
|
+
name: '@deepseek-ai/dsh-tool-subagent'
|
|
255
|
+
disabled: true
|
|
256
|
+
config:
|
|
257
|
+
provider: codex
|
|
258
|
+
toolName: subagent_codex
|
|
259
|
+
backgroundMode: one-shot
|
|
260
|
+
maxDepth: provider-managed
|
|
261
|
+
|
|
262
|
+
- id: tool-subagent-claude-code
|
|
263
|
+
name: '@deepseek-ai/dsh-tool-subagent'
|
|
264
|
+
disabled: true
|
|
265
|
+
config:
|
|
266
|
+
provider: claude-code
|
|
267
|
+
toolName: subagent_claude_code
|
|
268
|
+
backgroundMode: one-shot
|
|
269
|
+
maxDepth: provider-managed
|
|
270
|
+
|
|
271
|
+
- id: workflow-ptc
|
|
272
|
+
name: '@deepseek-ai/dsh-workflow-ptc'
|
|
273
|
+
config:
|
|
274
|
+
provider: spawn
|
|
275
|
+
|
|
276
|
+
- id: tool-workflow
|
|
277
|
+
name: '@deepseek-ai/dsh-tool-workflow'
|
|
278
|
+
|
|
279
|
+
- id: tool-ralph
|
|
280
|
+
name: '@deepseek-ai/dsh-tool-ralph'
|
|
281
|
+
config:
|
|
282
|
+
subagentProvider: spawn
|
|
283
|
+
maxRounds: 64
|
|
284
|
+
|
|
285
|
+
# ── remaining model-facing rows ─────────────────────────────────────────────
|
|
286
|
+
|
|
287
|
+
- id: tool-ask-user
|
|
288
|
+
name: '@deepseek-ai/dsh-tool-ask-user'
|
|
289
|
+
|
|
290
|
+
- id: tool-todo
|
|
291
|
+
name: '@deepseek-ai/dsh-tool-todo'
|
|
292
|
+
config:
|
|
293
|
+
allowParallelInProgress: true
|
|
294
|
+
|
|
295
|
+
# The `web` service and its search provider stay in the host composition; only
|
|
296
|
+
# the model-facing tool is per-session.
|
|
297
|
+
- id: tool-web
|
|
298
|
+
name: '@deepseek-ai/dsh-tool-web'
|
|
299
|
+
config:
|
|
300
|
+
fetch: true
|
|
301
|
+
searchTimeoutMs: 60000
|
|
302
|
+
|
|
303
|
+
# ── fly security tooling ─────────────────────────────────────────────────────
|
|
304
|
+
|
|
305
|
+
# Out-of-tree DSH Fly tool plugins. Like `tool-bash`/`tool-fs` above, each row
|
|
306
|
+
# registers model-facing tools into the HOST `tools` registry and provides
|
|
307
|
+
# nothing, so it needs no realm; it CONSUMES the host `shell` seam for sandboxed
|
|
308
|
+
# command execution (never node:child_process). The packages are installed as
|
|
309
|
+
# plain profile dependencies (they declare no `dsh.bundle`), and this preset is
|
|
310
|
+
# what mounts them per session.
|
|
311
|
+
#
|
|
312
|
+
# fly-recon registers BOTH a `tools/pre-execute` guard (deny unless
|
|
313
|
+
# FLY_ALLOW_RECON=1) and its two tools from one apply(), so it is a single row.
|
|
314
|
+
- id: tool-fly-binary
|
|
315
|
+
name: '@dsh-fly/dsh-plugin-fly-mode/tools/dsh-plugin-fly-binary/index.js'
|
|
316
|
+
- id: tool-fly-reverse
|
|
317
|
+
name: '@dsh-fly/dsh-plugin-fly-mode/tools/dsh-plugin-fly-reverse/index.js'
|
|
318
|
+
- id: tool-fly-pwn
|
|
319
|
+
name: '@dsh-fly/dsh-plugin-fly-mode/tools/dsh-plugin-fly-pwn/index.js'
|
|
320
|
+
- id: tool-fly-diag
|
|
321
|
+
name: '@dsh-fly/dsh-plugin-fly-mode/tools/dsh-plugin-fly-diag/index.js'
|
|
322
|
+
- id: tool-fly-recon
|
|
323
|
+
name: '@dsh-fly/dsh-plugin-fly-mode/tools/dsh-plugin-fly-recon/index.js'
|
|
324
|
+
# 客户端黑盒排查链(微信小程序实战沉淀):`bx_proxy` / `bx_flows` / `bx_diff` /
|
|
325
|
+
# `bx_doctor` / `bx_ca` / `bx_sysproxy` 六个工具 + 包内 `client-blackbox` skill 资产。
|
|
326
|
+
# 行形状与上面几个 `tool-fly-*` 完全一致(`id` + `name`,**不**写 `inject`):
|
|
327
|
+
# 声明面由包自己的 `export const inject` 决定(本包是 `['tools','shell','skills']`)。
|
|
328
|
+
# 为什么要在注释里点明 `skills`:skill provider 是在 `apply(ctx)` 里用
|
|
329
|
+
# `ctx.skills.registerProvider()` 注册的 —— 包上漏写 `skills`,引擎就不会把
|
|
330
|
+
# `ctx.skills` 交给它,apply 里那一步直接抛 ⇒ **整棵 preset 挂载被拒**(不是少一个
|
|
331
|
+
# skill,是整个 Fly 会话起不来)。门禁 `verify blackbox` 第 7/19 条同时盯
|
|
332
|
+
# "inject 恰好是这三项"与"preset 里有这一行"。
|
|
333
|
+
# 起停代理 / 主动探测 / 改系统代理走 `FLY_ALLOW_INTERCEPT=1` 授权门;只读面永远可用。
|
|
334
|
+
- id: tool-fly-blackbox
|
|
335
|
+
name: '@dsh-fly/dsh-plugin-fly-mode/tools/dsh-plugin-fly-blackbox/index.js'
|
|
336
|
+
# ── fly smart mode ───────────────────────────────────────────────────────────
|
|
337
|
+
|
|
338
|
+
# Smart 模式(docs/smart-mode-design.md):先设计、后执行、再验收的双模型工作流。
|
|
339
|
+
# 它只注册工具、自己不提供服务,所以和上面几行一样是普通行、不需要 realm;每个会话
|
|
340
|
+
# 的当前任务以 agent.session 为键记在插件闭包里,会话之间不串。除了九个工具,这一行还挂
|
|
341
|
+
# 纪律 section(`fly-smart:policy`)与宿主平面的 `/smart` 命令(官方 `/goal` 同款:
|
|
342
|
+
# 宿主 `commands` 注册表 + 本行 ctx 的 scoped layer),因此声明面是
|
|
343
|
+
# `inject = ['tools', 'commands', 'systemPrompt']` —— 少一个都会在 apply 里抛,
|
|
344
|
+
# 而抛 = 整棵 preset 挂载被拒(S6 根因,§12.6)。两个模型路由
|
|
345
|
+
# (brainRoute/handRoute)留给设置行配置。
|
|
346
|
+
- id: tool-fly-smart
|
|
347
|
+
name: dsh-plugin-fly-smart
|
|
348
|
+
config:
|
|
349
|
+
enabled: true
|
|
350
|
+
# 返工额度是**每阶段**的:一个阶段反复迭代不该把后面阶段的预算吃掉。额度耗尽不是强制
|
|
351
|
+
# 收尾 —— 门会把它交回用户(选「退回重做」=同意再加一个预算),详见 docs/smart-mode-design.md。
|
|
352
|
+
maxRework: 5
|
|
353
|
+
requireConsult: true
|
|
354
|
+
|
|
355
|
+
# ── 改自己:官方创造模式的能力 + Fly 的门 ───────────────────────────────────
|
|
356
|
+
#
|
|
357
|
+
# `present`:把工作区里的文件声明成「交付物」(官方 `@deepseek-ai/dsh-tool-present`)。宿主平面的
|
|
358
|
+
# `FILE_REFERENCE_PROMPT` 明确要求用它、而不是在回复里贴长文件;官方那两个 preset 都带这一行
|
|
359
|
+
# (`presets/cordis.patch.yml` 与 `presets/standard.patch.yml` 各一份,逐字相同),而我们此前没有 ——
|
|
360
|
+
# 尺子(`scripts/tests/preset-relation.spec.mjs`)把它记成 `DECLARED_MISSING`,所以它是一条**可见**的
|
|
361
|
+
# 偏差,而不是悄悄少一行。现在补齐:Fly 相对 `standard` 不再缺任何一行。
|
|
362
|
+
# 判据两面都断(`acceptance fly-shell`):mounted preset 里真的有这一行;并且把上游那个包真
|
|
363
|
+
# `apply()` 一遍 —— 注册出名为 `present` 的工具、`inject` 三个服务、配置不合法必须抛。
|
|
364
|
+
# 只断"行在"会漏掉"包解析不到/挂不上"这一半(那正是 preset 行最常见的失败形状)。
|
|
365
|
+
- id: present
|
|
366
|
+
name: '@deepseek-ai/dsh-tool-present'
|
|
367
|
+
|
|
368
|
+
# 这一段是"Fly 安全 × 官方创造模式"的交点。两者是同一个 registry 里的**兄弟**(同样的
|
|
369
|
+
# `dsh-agent-preset` 声明行、同一棵 profile 树,`packages/dsh-plugin-fly-plugins` 的面板里
|
|
370
|
+
# 并排显示):官方创造模式(preset `cordis`)= 标准 preset **加上"能改自己"的那两样**,
|
|
371
|
+
# 也就是下面这一行 cordis 组合工具与一行 plugin_manager。
|
|
372
|
+
#
|
|
373
|
+
# 我们的差异只在**门**上。创造模式那一层的授权面就是会话的沙箱模式 + 逐次审批 ——
|
|
374
|
+
# 而本机实测这两项是 `danger-full-access` + 审批 `never`,等于**没有门**;`plugin_manager`
|
|
375
|
+
# 能把包写进 profile、能让**会在宿主进程里跑起来**的代码落地,且跨会话存活。
|
|
376
|
+
# 所以 Fly 补一道自己的门:`packages/dsh-plugin-fly-guard`(默认全拒写入,只读面照旧;
|
|
377
|
+
# 人要显式给宿主设 `FLY_ALLOW_PROFILE_WRITE=1` 才放行)。这就是"Fly 安全是创造能力的护栏"。
|
|
378
|
+
#
|
|
379
|
+
# `@deepseek-ai/dsh-tool-cordis/host` 已经在宿主平面上注册过一次(`dsh-web-app` 的 patch
|
|
380
|
+
# 层,上游注释点名了这条重复 id 的坑),所以这里**只**挂 agent 半边。
|
|
381
|
+
- id: tool-cordis
|
|
382
|
+
name: '@deepseek-ai/dsh-tool-cordis'
|
|
383
|
+
|
|
384
|
+
# `disabled:` 那一行逐字照抄官方创造模式的同名行。判据:`profileContext` 由宿主提供
|
|
385
|
+
# (`dsh/lib/profile-boot-*.js` 里 `hostCtx.provide('profileContext', …)`),而会话上下文
|
|
386
|
+
# **看得见**宿主服务(反向不通,见 AGENTS.md 平面隔离那条),所以在 profile 里它恒为"启用";
|
|
387
|
+
# 在没有任何 profile 的裸上下文里它会自动关掉 —— 那里没有 `pluginManager` 服务,
|
|
388
|
+
# 硬挂会让**整棵 preset 挂载被拒**(不是少一个工具,是整个 Fly 会话起不来)。
|
|
389
|
+
- id: tool-plugin-manager
|
|
390
|
+
name: '@deepseek-ai/dsh-plugin-manager/tools'
|
|
391
|
+
disabled: !!js "!ctx.get('profileContext')"
|
|
392
|
+
|
|
393
|
+
# 这道门自己。它不注册任何工具(只挂 `tools/pre-execute` 的 waterfall),但仍是一行 preset 行:
|
|
394
|
+
# 门必须与它管的东西在同一个 scope 里(`inject: ['tools']`)。行 id 用 `tool-` 前缀不是口味问题 ——
|
|
395
|
+
# `scripts/lib/fly-profile.mjs` 的 `toolPackages` 是装配的唯一实现,门禁(含
|
|
396
|
+
# `verify-fly-profile.mjs` 的"preset 挂上全部 N 行")**从它派生**行名,凭喜好起名会让那条断言看不见这一行。
|
|
397
|
+
- id: tool-fly-guard
|
|
398
|
+
name: '@dsh-fly/dsh-plugin-fly-mode/tools/dsh-plugin-fly-guard/index.js'
|
|
399
|
+
# <<< fly-agent-preset
|
package/package.json
CHANGED
|
@@ -1,6 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-fly/dsh-plugin-fly-mode",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "Fly 安全模式(agent preset `fly`)作为一个可安装的包:自带 7 个 Fly 工具(源码内联在包内 tools/,行表用本包子路径引用),并依赖单独发布的 dsh-plugin-fly-smart;装进任何 profile 后那里就能服务 fly preset。",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/ethanchen669/dsh-plugin-fly-mode.git"
|
|
10
|
+
},
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": ">=20"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"cordis.patch.yml",
|
|
16
|
+
"README.md",
|
|
17
|
+
"tools"
|
|
18
|
+
],
|
|
19
|
+
"dsh": {
|
|
20
|
+
"bundle": {
|
|
21
|
+
"patch": "./cordis.patch.yml"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"verify": "node scripts/verify.mjs"
|
|
26
|
+
},
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"registry": "https://registry.npmjs.org/",
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"dsh-plugin-fly-smart": "^0.1.0"
|
|
33
|
+
}
|
|
34
|
+
}
|