@xth26/dsh-plan-build-mode 0.2.3 → 0.3.1
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/README.md +139 -139
- package/README.zh.md +136 -136
- package/package.json +101 -100
package/README.md
CHANGED
|
@@ -1,139 +1,139 @@
|
|
|
1
|
-
# dsh-plan-build-mode
|
|
2
|
-
|
|
3
|
-
OpenCode-style Plan / Build hard permission model for DeepSeek Harness.
|
|
4
|
-
|
|
5
|
-
This plugin adds an independent Plan/Build mode switch to DSH:
|
|
6
|
-
|
|
7
|
-
- **Plan mode** enforces a `read-only` sandbox and blocks mutating tools (`write`, `edit`).
|
|
8
|
-
- **Build mode** restores `workspace-write` and allows edits.
|
|
9
|
-
- DSH's built-in `/plan` soft-guidance mode is left untouched.
|
|
10
|
-
|
|
11
|
-
The tool denial only takes effect when Plan mode is configured as `read-only`. When the session has not been switched, Build mode is active by default.
|
|
12
|
-
|
|
13
|
-
## Installation
|
|
14
|
-
|
|
15
|
-
DSH plugins are loaded through a DSH profile. Install the plugin into the profile(s) you use:
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
# For the web profile
|
|
19
|
-
dsh plugin --profile web add @xth26/dsh-plan-build-mode
|
|
20
|
-
|
|
21
|
-
# For the TUI profile
|
|
22
|
-
dsh plugin --profile dsh-tui add @xth26/dsh-plan-build-mode
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
The plugin ships with a `cordis.patch.yml` that auto-injects the required row
|
|
26
|
-
when the package is loaded by a DSH profile.
|
|
27
|
-
|
|
28
|
-
## Using the same Plan/Build mode in both web and TUI
|
|
29
|
-
|
|
30
|
-
Plan/Build mode state is stored in the session event log (`sandbox/mode` event). Both `dsh web` and `dsh --profile <name>` use the same session store when they share the same profile and session ID.
|
|
31
|
-
|
|
32
|
-
- **Same profile**: if you run `dsh web --profile web` and `dsh --profile web`, the mode is shared because the session events are shared.
|
|
33
|
-
- **Different profiles**: by default `web` and `dsh-tui` are separate profiles with separate session directories. Switching in one does **not** affect the other.
|
|
34
|
-
|
|
35
|
-
To make web and TUI share the same mode and session history, use the **same profile** for both:
|
|
36
|
-
|
|
37
|
-
```bash
|
|
38
|
-
# Use the web profile for both interfaces
|
|
39
|
-
dsh web --profile web
|
|
40
|
-
dsh --profile web
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
Or, if you prefer to keep separate profiles but want to share only the session store, override the session root in each profile's `cordis.patch.yml` to point to the same directory:
|
|
44
|
-
|
|
45
|
-
```yaml
|
|
46
|
-
- id: session-root
|
|
47
|
-
config:
|
|
48
|
-
root: /path/to/shared/sessions
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
Note: sharing session directories across profiles requires both profiles to mount compatible service bundles; otherwise event interpretation may differ.
|
|
52
|
-
|
|
53
|
-
## Local development / link
|
|
54
|
-
|
|
55
|
-
To try the plugin from a local checkout without publishing:
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
# From the plugin checkout
|
|
59
|
-
cd /path/to/dsh-plan-build-mode
|
|
60
|
-
pnpm link --global
|
|
61
|
-
|
|
62
|
-
# From your DSH profile directory
|
|
63
|
-
pnpm link --global @xth26/dsh-plan-build-mode
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
Then start DSH with that profile. The `dsh.bundle.patch` field in the plugin's
|
|
67
|
-
`package.json` makes the patch apply automatically.
|
|
68
|
-
|
|
69
|
-
## Updating
|
|
70
|
-
|
|
71
|
-
For `0.x` versions, the semver range `^0.1.0` only matches `0.1.x` and will **never** auto-update to `0.2.0`. Always bump the declaration explicitly and restart the DSH process:
|
|
72
|
-
|
|
73
|
-
```bash
|
|
74
|
-
# Bump the installed version in the target profile
|
|
75
|
-
# (run this outside a sandboxed agent session; the profile directory is not writable from DSH)
|
|
76
|
-
dsh plugin --profile dsh-tui add @xth26/dsh-plan-build-mode@0.
|
|
77
|
-
|
|
78
|
-
# Restart the DSH process that uses that profile
|
|
79
|
-
# (old Node process still holds the previous plugin code in memory)
|
|
80
|
-
Stop-Process -Name dsh -Force # PowerShell
|
|
81
|
-
# or: taskkill /IM dsh.exe /F # CMD
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
Then start `dsh web` or `dsh tui` again. To always pull the latest published version:
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
dsh plugin --profile dsh-tui add @xth26/dsh-plan-build-mode@latest
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
## Usage
|
|
91
|
-
|
|
92
|
-
| Command | Effect |
|
|
93
|
-
|---|---|
|
|
94
|
-
| `/plan-build` | Toggle between Plan and Build modes |
|
|
95
|
-
| `/plan-build status` | Show the current mode |
|
|
96
|
-
| `/plan-build switch plan` | Enter Plan mode (read-only) |
|
|
97
|
-
| `/plan-build switch build` | Enter Build mode (writable) |
|
|
98
|
-
| `/plan-build switch` | Same as `/plan-build`; toggles between modes |
|
|
99
|
-
|
|
100
|
-
## Configuration
|
|
101
|
-
|
|
102
|
-
```yaml
|
|
103
|
-
- id: plan-build-mode
|
|
104
|
-
name: '@xth26/dsh-plan-build-mode'
|
|
105
|
-
config:
|
|
106
|
-
planSandbox: read-only
|
|
107
|
-
buildSandbox: workspace-write
|
|
108
|
-
denyWriteTools: true
|
|
109
|
-
section: true
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
`planSandbox` and `buildSandbox` must differ.
|
|
113
|
-
|
|
114
|
-
## Plan mode: command-line Python for inspection
|
|
115
|
-
|
|
116
|
-
While Plan mode is read-only and blocks `write`/`edit` tools, it is **encouraged** to run short, read-only command-line Python snippets to inspect data and validate assumptions. For example:
|
|
117
|
-
|
|
118
|
-
```bash
|
|
119
|
-
python -B -c "import json, sys; data = json.load(open('data/sample.json')); print(len(data))"
|
|
120
|
-
python -B -c "import pandas as pd; print(pd.read_csv('data.csv').describe())"
|
|
121
|
-
pytest -p no:cacheprovider -q tests/test_sanity.py
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
Use `-B` (or set `PYTHONDONTWRITEBYTECODE=1`) and `pytest -p no:cacheprovider` to avoid writing `__pycache__` or `.pytest_cache`. The read-only sandbox is the final guardrail; any command that tries to write files will still be blocked at the sandbox layer.
|
|
125
|
-
|
|
126
|
-
## Local integration check
|
|
127
|
-
|
|
128
|
-
After installing/linking the plugin in a DSH profile:
|
|
129
|
-
|
|
130
|
-
1. Start DSH with that profile.
|
|
131
|
-
2. Run `/plan-build` to enter Plan mode (read-only). You should see a confirmation.
|
|
132
|
-
3. Ask the agent to call the `write` tool. It should be denied with a reason.
|
|
133
|
-
4. Run `/plan-build` again to enter Build mode (writable). You should see a confirmation.
|
|
134
|
-
5. Ask the agent to call `write` again. It should now be allowed.
|
|
135
|
-
6. Run `/plan-build status` to check the current mode without switching.
|
|
136
|
-
|
|
137
|
-
## License
|
|
138
|
-
|
|
139
|
-
MIT
|
|
1
|
+
# dsh-plan-build-mode
|
|
2
|
+
|
|
3
|
+
OpenCode-style Plan / Build hard permission model for DeepSeek Harness.
|
|
4
|
+
|
|
5
|
+
This plugin adds an independent Plan/Build mode switch to DSH:
|
|
6
|
+
|
|
7
|
+
- **Plan mode** enforces a `read-only` sandbox and blocks mutating tools (`write`, `edit`).
|
|
8
|
+
- **Build mode** restores `workspace-write` and allows edits.
|
|
9
|
+
- DSH's built-in `/plan` soft-guidance mode is left untouched.
|
|
10
|
+
|
|
11
|
+
The tool denial only takes effect when Plan mode is configured as `read-only`. When the session has not been switched, Build mode is active by default.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
DSH plugins are loaded through a DSH profile. Install the plugin into the profile(s) you use:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# For the web profile
|
|
19
|
+
dsh plugin --profile web add @xth26/dsh-plan-build-mode
|
|
20
|
+
|
|
21
|
+
# For the TUI profile
|
|
22
|
+
dsh plugin --profile dsh-tui add @xth26/dsh-plan-build-mode
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The plugin ships with a `cordis.patch.yml` that auto-injects the required row
|
|
26
|
+
when the package is loaded by a DSH profile.
|
|
27
|
+
|
|
28
|
+
## Using the same Plan/Build mode in both web and TUI
|
|
29
|
+
|
|
30
|
+
Plan/Build mode state is stored in the session event log (`sandbox/mode` event). Both `dsh web` and `dsh --profile <name>` use the same session store when they share the same profile and session ID.
|
|
31
|
+
|
|
32
|
+
- **Same profile**: if you run `dsh web --profile web` and `dsh --profile web`, the mode is shared because the session events are shared.
|
|
33
|
+
- **Different profiles**: by default `web` and `dsh-tui` are separate profiles with separate session directories. Switching in one does **not** affect the other.
|
|
34
|
+
|
|
35
|
+
To make web and TUI share the same mode and session history, use the **same profile** for both:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Use the web profile for both interfaces
|
|
39
|
+
dsh web --profile web
|
|
40
|
+
dsh --profile web
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Or, if you prefer to keep separate profiles but want to share only the session store, override the session root in each profile's `cordis.patch.yml` to point to the same directory:
|
|
44
|
+
|
|
45
|
+
```yaml
|
|
46
|
+
- id: session-root
|
|
47
|
+
config:
|
|
48
|
+
root: /path/to/shared/sessions
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Note: sharing session directories across profiles requires both profiles to mount compatible service bundles; otherwise event interpretation may differ.
|
|
52
|
+
|
|
53
|
+
## Local development / link
|
|
54
|
+
|
|
55
|
+
To try the plugin from a local checkout without publishing:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# From the plugin checkout
|
|
59
|
+
cd /path/to/dsh-plan-build-mode
|
|
60
|
+
pnpm link --global
|
|
61
|
+
|
|
62
|
+
# From your DSH profile directory
|
|
63
|
+
pnpm link --global @xth26/dsh-plan-build-mode
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Then start DSH with that profile. The `dsh.bundle.patch` field in the plugin's
|
|
67
|
+
`package.json` makes the patch apply automatically.
|
|
68
|
+
|
|
69
|
+
## Updating
|
|
70
|
+
|
|
71
|
+
For `0.x` versions, the semver range `^0.1.0` only matches `0.1.x` and will **never** auto-update to `0.2.0`. Always bump the declaration explicitly and restart the DSH process:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Bump the installed version in the target profile
|
|
75
|
+
# (run this outside a sandboxed agent session; the profile directory is not writable from DSH)
|
|
76
|
+
dsh plugin --profile dsh-tui add @xth26/dsh-plan-build-mode@0.3.1
|
|
77
|
+
|
|
78
|
+
# Restart the DSH process that uses that profile
|
|
79
|
+
# (old Node process still holds the previous plugin code in memory)
|
|
80
|
+
Stop-Process -Name dsh -Force # PowerShell
|
|
81
|
+
# or: taskkill /IM dsh.exe /F # CMD
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Then start `dsh web` or `dsh tui` again. To always pull the latest published version:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
dsh plugin --profile dsh-tui add @xth26/dsh-plan-build-mode@latest
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Usage
|
|
91
|
+
|
|
92
|
+
| Command | Effect |
|
|
93
|
+
|---|---|
|
|
94
|
+
| `/plan-build` | Toggle between Plan and Build modes |
|
|
95
|
+
| `/plan-build status` | Show the current mode |
|
|
96
|
+
| `/plan-build switch plan` | Enter Plan mode (read-only) |
|
|
97
|
+
| `/plan-build switch build` | Enter Build mode (writable) |
|
|
98
|
+
| `/plan-build switch` | Same as `/plan-build`; toggles between modes |
|
|
99
|
+
|
|
100
|
+
## Configuration
|
|
101
|
+
|
|
102
|
+
```yaml
|
|
103
|
+
- id: plan-build-mode
|
|
104
|
+
name: '@xth26/dsh-plan-build-mode'
|
|
105
|
+
config:
|
|
106
|
+
planSandbox: read-only
|
|
107
|
+
buildSandbox: workspace-write
|
|
108
|
+
denyWriteTools: true
|
|
109
|
+
section: true
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`planSandbox` and `buildSandbox` must differ.
|
|
113
|
+
|
|
114
|
+
## Plan mode: command-line Python for inspection
|
|
115
|
+
|
|
116
|
+
While Plan mode is read-only and blocks `write`/`edit` tools, it is **encouraged** to run short, read-only command-line Python snippets to inspect data and validate assumptions. For example:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
python -B -c "import json, sys; data = json.load(open('data/sample.json')); print(len(data))"
|
|
120
|
+
python -B -c "import pandas as pd; print(pd.read_csv('data.csv').describe())"
|
|
121
|
+
pytest -p no:cacheprovider -q tests/test_sanity.py
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Use `-B` (or set `PYTHONDONTWRITEBYTECODE=1`) and `pytest -p no:cacheprovider` to avoid writing `__pycache__` or `.pytest_cache`. The read-only sandbox is the final guardrail; any command that tries to write files will still be blocked at the sandbox layer.
|
|
125
|
+
|
|
126
|
+
## Local integration check
|
|
127
|
+
|
|
128
|
+
After installing/linking the plugin in a DSH profile:
|
|
129
|
+
|
|
130
|
+
1. Start DSH with that profile.
|
|
131
|
+
2. Run `/plan-build` to enter Plan mode (read-only). You should see a confirmation.
|
|
132
|
+
3. Ask the agent to call the `write` tool. It should be denied with a reason.
|
|
133
|
+
4. Run `/plan-build` again to enter Build mode (writable). You should see a confirmation.
|
|
134
|
+
5. Ask the agent to call `write` again. It should now be allowed.
|
|
135
|
+
6. Run `/plan-build status` to check the current mode without switching.
|
|
136
|
+
|
|
137
|
+
## License
|
|
138
|
+
|
|
139
|
+
MIT
|
package/README.zh.md
CHANGED
|
@@ -1,136 +1,136 @@
|
|
|
1
|
-
# dsh-plan-build-mode
|
|
2
|
-
|
|
3
|
-
OpenCode 风格的 Plan / Build 硬权限模型插件。
|
|
4
|
-
|
|
5
|
-
本插件为 DSH 增加一个独立的 Plan/Build 模式切换,不影响 DSH 原生的 `/plan` 软提示模式:
|
|
6
|
-
|
|
7
|
-
- **Plan 模式**:强制 `read-only` 沙箱,并拦截写工具(`write`、`edit`)。
|
|
8
|
-
- **Build 模式**:恢复 `workspace-write`,允许编辑。
|
|
9
|
-
|
|
10
|
-
写工具拦截仅在 Plan 模式配置为 `read-only` 时生效。首次使用或未切换时,默认处于 Build 模式。
|
|
11
|
-
|
|
12
|
-
## 安装
|
|
13
|
-
|
|
14
|
-
DSH 插件通过 DSH profile 加载。把它装到你实际使用的 profile 里:
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
# 装到 web profile
|
|
18
|
-
dsh plugin --profile web add @xth26/dsh-plan-build-mode
|
|
19
|
-
|
|
20
|
-
# 装到 TUI profile
|
|
21
|
-
dsh plugin --profile dsh-tui add @xth26/dsh-plan-build-mode
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
插件自带的 `cordis.patch.yml` 会在 DSH profile 加载时自动注入。
|
|
25
|
-
|
|
26
|
-
## 让 Web 和 TUI 共享同一个 Plan/Build 模式
|
|
27
|
-
|
|
28
|
-
Plan/Build 模式状态存在会话事件日志里(`sandbox/mode` 事件)。`dsh web` 和 `dsh --profile <名称>` 只有在共用同一个 profile、同一个 session ID 时,才会读写同一个会话事件流。
|
|
29
|
-
|
|
30
|
-
- **同一个 profile**:比如 `dsh web --profile web` 和 `dsh --profile web` 启动的两个入口,会共享 session 事件,因此模式切换会同步生效。
|
|
31
|
-
- **不同 profile**:默认 `web` 和 `dsh-tui` 是两个独立 profile,会话目录也分开。在一处切换不会影响另一处。
|
|
32
|
-
|
|
33
|
-
想让 web 和 TUI 共享模式状态,最简单的方法是**两个入口都使用同一个 profile**:
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
# 两个入口都用 web profile
|
|
37
|
-
dsh web --profile web
|
|
38
|
-
dsh --profile web
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
如果你确实想用不同 profile,但只想共享会话存储,可以在每个 profile 的 `cordis.patch.yml` 里把 session root 指向同一个目录:
|
|
42
|
-
|
|
43
|
-
```yaml
|
|
44
|
-
- id: session-root
|
|
45
|
-
config:
|
|
46
|
-
root: /path/to/shared/sessions
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
注意:跨 profile 共享会话目录要求两个 profile 挂载的服务组合兼容,否则事件解释可能出现差异。
|
|
50
|
-
|
|
51
|
-
## 本地开发 / link 试用
|
|
52
|
-
|
|
53
|
-
想在发布前从本地源码试用:
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
# 在插件目录
|
|
57
|
-
cd /path/to/dsh-plan-build-mode
|
|
58
|
-
pnpm link --global
|
|
59
|
-
|
|
60
|
-
# 在你的 DSH profile 目录
|
|
61
|
-
pnpm link --global @xth26/dsh-plan-build-mode
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
然后启动 DSH。插件 `package.json` 里的 `dsh.bundle.patch` 会自动生效。
|
|
65
|
-
|
|
66
|
-
## 更新
|
|
67
|
-
|
|
68
|
-
对于 `0.x` 版本,semver 范围 `^0.1.0` 只会匹配 `0.1.x`,**永远不会**自动更新到 `0.2.0`。升级时必须显式提升声明并重启 DSH 进程:
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
# 在目标 profile 中提升已安装版本
|
|
72
|
-
# (这条命令需要在非沙箱的终端里执行;DSH agent 无法写入 profile 目录)
|
|
73
|
-
dsh plugin --profile dsh-tui add @xth26/dsh-plan-build-mode@0.
|
|
74
|
-
|
|
75
|
-
# 重启使用该 profile 的 DSH 进程
|
|
76
|
-
# (旧的 Node 进程仍缓存着旧插件代码)
|
|
77
|
-
Stop-Process -Name dsh -Force # PowerShell
|
|
78
|
-
# 或: taskkill /IM dsh.exe /F # CMD
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
然后重新启动 `dsh web` 或 `dsh tui`。如果想始终安装最新发布版本:
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
dsh plugin --profile dsh-tui add @xth26/dsh-plan-build-mode@latest
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
## 使用
|
|
88
|
-
|
|
89
|
-
| 命令 | 效果 |
|
|
90
|
-
|---|---|
|
|
91
|
-
| `/plan-build` | 在 Plan 与 Build 模式之间切换 |
|
|
92
|
-
| `/plan-build status` | 显示当前模式 |
|
|
93
|
-
| `/plan-build switch plan` | 进入 Plan 模式(只读) |
|
|
94
|
-
| `/plan-build switch build` | 进入 Build 模式(可写) |
|
|
95
|
-
| `/plan-build switch` | 同 `/plan-build`,切换当前模式 |
|
|
96
|
-
|
|
97
|
-
## 配置
|
|
98
|
-
|
|
99
|
-
```yaml
|
|
100
|
-
- id: plan-build-mode
|
|
101
|
-
name: '@xth26/dsh-plan-build-mode'
|
|
102
|
-
config:
|
|
103
|
-
planSandbox: read-only
|
|
104
|
-
buildSandbox: workspace-write
|
|
105
|
-
denyWriteTools: true
|
|
106
|
-
section: true
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
`planSandbox` 和 `buildSandbox` 必须不同。
|
|
110
|
-
|
|
111
|
-
## Plan 模式:命令行 Python 做数据检查
|
|
112
|
-
|
|
113
|
-
Plan 模式只读并拦截 `write`/`edit` 工具,但**鼓励**在命令行里跑简短、只读的 Python 片段来读数据和验证假设。例如:
|
|
114
|
-
|
|
115
|
-
```bash
|
|
116
|
-
python -B -c "import json, sys; data = json.load(open('data/sample.json')); print(len(data))"
|
|
117
|
-
python -B -c "import pandas as pd; print(pd.read_csv('data.csv').describe())"
|
|
118
|
-
pytest -p no:cacheprovider -q tests/test_sanity.py
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
使用 `-B`(或设置 `PYTHONDONTWRITEBYTECODE=1`)以及 `pytest -p no:cacheprovider`,避免写入 `__pycache__` 或 `.pytest_cache`。read-only 沙箱仍是最终防线,任何试图写文件的命令仍会在沙箱层被拒绝。
|
|
122
|
-
|
|
123
|
-
## 本地集成验证
|
|
124
|
-
|
|
125
|
-
安装或 link 插件到 DSH profile 后:
|
|
126
|
-
|
|
127
|
-
1. 启动 DSH。
|
|
128
|
-
2. 输入 `/plan-build`,应提示进入 Plan 模式。
|
|
129
|
-
3. 让 agent 调用 `write` 工具,应被拒绝。
|
|
130
|
-
4. 再次输入 `/plan-build`,应提示进入 Build 模式。
|
|
131
|
-
5. 再次让 agent 调用 `write`,应允许执行。
|
|
132
|
-
6. 输入 `/plan-build status`,可只查看当前模式而不切换。
|
|
133
|
-
|
|
134
|
-
## 许可证
|
|
135
|
-
|
|
136
|
-
MIT
|
|
1
|
+
# dsh-plan-build-mode
|
|
2
|
+
|
|
3
|
+
OpenCode 风格的 Plan / Build 硬权限模型插件。
|
|
4
|
+
|
|
5
|
+
本插件为 DSH 增加一个独立的 Plan/Build 模式切换,不影响 DSH 原生的 `/plan` 软提示模式:
|
|
6
|
+
|
|
7
|
+
- **Plan 模式**:强制 `read-only` 沙箱,并拦截写工具(`write`、`edit`)。
|
|
8
|
+
- **Build 模式**:恢复 `workspace-write`,允许编辑。
|
|
9
|
+
|
|
10
|
+
写工具拦截仅在 Plan 模式配置为 `read-only` 时生效。首次使用或未切换时,默认处于 Build 模式。
|
|
11
|
+
|
|
12
|
+
## 安装
|
|
13
|
+
|
|
14
|
+
DSH 插件通过 DSH profile 加载。把它装到你实际使用的 profile 里:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# 装到 web profile
|
|
18
|
+
dsh plugin --profile web add @xth26/dsh-plan-build-mode
|
|
19
|
+
|
|
20
|
+
# 装到 TUI profile
|
|
21
|
+
dsh plugin --profile dsh-tui add @xth26/dsh-plan-build-mode
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
插件自带的 `cordis.patch.yml` 会在 DSH profile 加载时自动注入。
|
|
25
|
+
|
|
26
|
+
## 让 Web 和 TUI 共享同一个 Plan/Build 模式
|
|
27
|
+
|
|
28
|
+
Plan/Build 模式状态存在会话事件日志里(`sandbox/mode` 事件)。`dsh web` 和 `dsh --profile <名称>` 只有在共用同一个 profile、同一个 session ID 时,才会读写同一个会话事件流。
|
|
29
|
+
|
|
30
|
+
- **同一个 profile**:比如 `dsh web --profile web` 和 `dsh --profile web` 启动的两个入口,会共享 session 事件,因此模式切换会同步生效。
|
|
31
|
+
- **不同 profile**:默认 `web` 和 `dsh-tui` 是两个独立 profile,会话目录也分开。在一处切换不会影响另一处。
|
|
32
|
+
|
|
33
|
+
想让 web 和 TUI 共享模式状态,最简单的方法是**两个入口都使用同一个 profile**:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# 两个入口都用 web profile
|
|
37
|
+
dsh web --profile web
|
|
38
|
+
dsh --profile web
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
如果你确实想用不同 profile,但只想共享会话存储,可以在每个 profile 的 `cordis.patch.yml` 里把 session root 指向同一个目录:
|
|
42
|
+
|
|
43
|
+
```yaml
|
|
44
|
+
- id: session-root
|
|
45
|
+
config:
|
|
46
|
+
root: /path/to/shared/sessions
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
注意:跨 profile 共享会话目录要求两个 profile 挂载的服务组合兼容,否则事件解释可能出现差异。
|
|
50
|
+
|
|
51
|
+
## 本地开发 / link 试用
|
|
52
|
+
|
|
53
|
+
想在发布前从本地源码试用:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# 在插件目录
|
|
57
|
+
cd /path/to/dsh-plan-build-mode
|
|
58
|
+
pnpm link --global
|
|
59
|
+
|
|
60
|
+
# 在你的 DSH profile 目录
|
|
61
|
+
pnpm link --global @xth26/dsh-plan-build-mode
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
然后启动 DSH。插件 `package.json` 里的 `dsh.bundle.patch` 会自动生效。
|
|
65
|
+
|
|
66
|
+
## 更新
|
|
67
|
+
|
|
68
|
+
对于 `0.x` 版本,semver 范围 `^0.1.0` 只会匹配 `0.1.x`,**永远不会**自动更新到 `0.2.0`。升级时必须显式提升声明并重启 DSH 进程:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# 在目标 profile 中提升已安装版本
|
|
72
|
+
# (这条命令需要在非沙箱的终端里执行;DSH agent 无法写入 profile 目录)
|
|
73
|
+
dsh plugin --profile dsh-tui add @xth26/dsh-plan-build-mode@0.3.1
|
|
74
|
+
|
|
75
|
+
# 重启使用该 profile 的 DSH 进程
|
|
76
|
+
# (旧的 Node 进程仍缓存着旧插件代码)
|
|
77
|
+
Stop-Process -Name dsh -Force # PowerShell
|
|
78
|
+
# 或: taskkill /IM dsh.exe /F # CMD
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
然后重新启动 `dsh web` 或 `dsh tui`。如果想始终安装最新发布版本:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
dsh plugin --profile dsh-tui add @xth26/dsh-plan-build-mode@latest
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## 使用
|
|
88
|
+
|
|
89
|
+
| 命令 | 效果 |
|
|
90
|
+
|---|---|
|
|
91
|
+
| `/plan-build` | 在 Plan 与 Build 模式之间切换 |
|
|
92
|
+
| `/plan-build status` | 显示当前模式 |
|
|
93
|
+
| `/plan-build switch plan` | 进入 Plan 模式(只读) |
|
|
94
|
+
| `/plan-build switch build` | 进入 Build 模式(可写) |
|
|
95
|
+
| `/plan-build switch` | 同 `/plan-build`,切换当前模式 |
|
|
96
|
+
|
|
97
|
+
## 配置
|
|
98
|
+
|
|
99
|
+
```yaml
|
|
100
|
+
- id: plan-build-mode
|
|
101
|
+
name: '@xth26/dsh-plan-build-mode'
|
|
102
|
+
config:
|
|
103
|
+
planSandbox: read-only
|
|
104
|
+
buildSandbox: workspace-write
|
|
105
|
+
denyWriteTools: true
|
|
106
|
+
section: true
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`planSandbox` 和 `buildSandbox` 必须不同。
|
|
110
|
+
|
|
111
|
+
## Plan 模式:命令行 Python 做数据检查
|
|
112
|
+
|
|
113
|
+
Plan 模式只读并拦截 `write`/`edit` 工具,但**鼓励**在命令行里跑简短、只读的 Python 片段来读数据和验证假设。例如:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
python -B -c "import json, sys; data = json.load(open('data/sample.json')); print(len(data))"
|
|
117
|
+
python -B -c "import pandas as pd; print(pd.read_csv('data.csv').describe())"
|
|
118
|
+
pytest -p no:cacheprovider -q tests/test_sanity.py
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
使用 `-B`(或设置 `PYTHONDONTWRITEBYTECODE=1`)以及 `pytest -p no:cacheprovider`,避免写入 `__pycache__` 或 `.pytest_cache`。read-only 沙箱仍是最终防线,任何试图写文件的命令仍会在沙箱层被拒绝。
|
|
122
|
+
|
|
123
|
+
## 本地集成验证
|
|
124
|
+
|
|
125
|
+
安装或 link 插件到 DSH profile 后:
|
|
126
|
+
|
|
127
|
+
1. 启动 DSH。
|
|
128
|
+
2. 输入 `/plan-build`,应提示进入 Plan 模式。
|
|
129
|
+
3. 让 agent 调用 `write` 工具,应被拒绝。
|
|
130
|
+
4. 再次输入 `/plan-build`,应提示进入 Build 模式。
|
|
131
|
+
5. 再次让 agent 调用 `write`,应允许执行。
|
|
132
|
+
6. 输入 `/plan-build status`,可只查看当前模式而不切换。
|
|
133
|
+
|
|
134
|
+
## 许可证
|
|
135
|
+
|
|
136
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,100 +1,101 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@xth26/dsh-plan-build-mode",
|
|
3
|
-
"description": "OpenCode-style Plan / Build hard permission model for DSH",
|
|
4
|
-
"version": "0.
|
|
5
|
-
"publishConfig": {
|
|
6
|
-
"access": "public"
|
|
7
|
-
},
|
|
8
|
-
"type": "module",
|
|
9
|
-
"main": "lib/index.js",
|
|
10
|
-
"types": "lib/types/index.d.ts",
|
|
11
|
-
"exports": {
|
|
12
|
-
".": {
|
|
13
|
-
"types": "./lib/types/index.d.ts",
|
|
14
|
-
"default": "./lib/index.js"
|
|
15
|
-
},
|
|
16
|
-
"./invariant": {
|
|
17
|
-
"types": "./lib/types/invariant.d.ts",
|
|
18
|
-
"default": "./lib/invariant.js"
|
|
19
|
-
},
|
|
20
|
-
"./src/*": "./src/*",
|
|
21
|
-
"./package.json": "./package.json"
|
|
22
|
-
},
|
|
23
|
-
"files": [
|
|
24
|
-
"lib",
|
|
25
|
-
"cordis.patch.yml",
|
|
26
|
-
"README.md",
|
|
27
|
-
"README.zh.md",
|
|
28
|
-
"LICENSE"
|
|
29
|
-
],
|
|
30
|
-
"dsh": {
|
|
31
|
-
"bundle": {
|
|
32
|
-
"patch": "./cordis.patch.yml"
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"@deepseek-ai/
|
|
44
|
-
"@deepseek-ai/dsh-
|
|
45
|
-
"@deepseek-ai/dsh-
|
|
46
|
-
"@deepseek-ai/
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"@deepseek-ai/
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"@deepseek-ai/
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"@deepseek-ai/
|
|
56
|
-
"optional": true
|
|
57
|
-
},
|
|
58
|
-
"@deepseek-ai/dsh-
|
|
59
|
-
"optional": true
|
|
60
|
-
},
|
|
61
|
-
"@deepseek-ai/dsh-
|
|
62
|
-
"optional": true
|
|
63
|
-
},
|
|
64
|
-
"@deepseek-ai/dsh-
|
|
65
|
-
"optional": true
|
|
66
|
-
},
|
|
67
|
-
"@deepseek-ai/dsh-
|
|
68
|
-
"optional": true
|
|
69
|
-
},
|
|
70
|
-
"@deepseek-ai/dsh-
|
|
71
|
-
"optional": true
|
|
72
|
-
},
|
|
73
|
-
"@deepseek-ai/dsh-
|
|
74
|
-
"optional": true
|
|
75
|
-
},
|
|
76
|
-
"@deepseek-ai/
|
|
77
|
-
"optional": true
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
"@deepseek-ai/
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
"@deepseek-ai/
|
|
88
|
-
"@deepseek-ai/dsh-
|
|
89
|
-
"@deepseek-ai/dsh-
|
|
90
|
-
"@deepseek-ai/
|
|
91
|
-
"@
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
"
|
|
97
|
-
"
|
|
98
|
-
"
|
|
99
|
-
|
|
100
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@xth26/dsh-plan-build-mode",
|
|
3
|
+
"description": "OpenCode-style Plan / Build hard permission model for DSH",
|
|
4
|
+
"version": "0.3.1",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "lib/index.js",
|
|
10
|
+
"types": "lib/types/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./lib/types/index.d.ts",
|
|
14
|
+
"default": "./lib/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./invariant": {
|
|
17
|
+
"types": "./lib/types/invariant.d.ts",
|
|
18
|
+
"default": "./lib/invariant.js"
|
|
19
|
+
},
|
|
20
|
+
"./src/*": "./src/*",
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"lib",
|
|
25
|
+
"cordis.patch.yml",
|
|
26
|
+
"README.md",
|
|
27
|
+
"README.zh.md",
|
|
28
|
+
"LICENSE"
|
|
29
|
+
],
|
|
30
|
+
"dsh": {
|
|
31
|
+
"bundle": {
|
|
32
|
+
"patch": "./cordis.patch.yml"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsc -b tsconfig.json",
|
|
37
|
+
"prepublishOnly": "pnpm build",
|
|
38
|
+
"test": "vitest run",
|
|
39
|
+
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
40
|
+
},
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
44
|
+
"@deepseek-ai/dsh-agent": "^0.1.0-rc.8",
|
|
45
|
+
"@deepseek-ai/dsh-commands": "^0.1.0-rc.8",
|
|
46
|
+
"@deepseek-ai/dsh-invariants": "^0.1.0-rc.8",
|
|
47
|
+
"@deepseek-ai/dsh-sandbox": "^0.1.0-rc.8",
|
|
48
|
+
"@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.8",
|
|
49
|
+
"@deepseek-ai/dsh-session": "^0.1.0-rc.8",
|
|
50
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.8",
|
|
51
|
+
"@deepseek-ai/dsh-tools": "^0.1.0-rc.8",
|
|
52
|
+
"@deepseek-ai/schemastery": "^3.18.1"
|
|
53
|
+
},
|
|
54
|
+
"peerDependenciesMeta": {
|
|
55
|
+
"@deepseek-ai/cordis": {
|
|
56
|
+
"optional": true
|
|
57
|
+
},
|
|
58
|
+
"@deepseek-ai/dsh-agent": {
|
|
59
|
+
"optional": true
|
|
60
|
+
},
|
|
61
|
+
"@deepseek-ai/dsh-commands": {
|
|
62
|
+
"optional": true
|
|
63
|
+
},
|
|
64
|
+
"@deepseek-ai/dsh-invariants": {
|
|
65
|
+
"optional": true
|
|
66
|
+
},
|
|
67
|
+
"@deepseek-ai/dsh-sandbox": {
|
|
68
|
+
"optional": true
|
|
69
|
+
},
|
|
70
|
+
"@deepseek-ai/dsh-sandbox-policy": {
|
|
71
|
+
"optional": true
|
|
72
|
+
},
|
|
73
|
+
"@deepseek-ai/dsh-session": {
|
|
74
|
+
"optional": true
|
|
75
|
+
},
|
|
76
|
+
"@deepseek-ai/dsh-system-prompt": {
|
|
77
|
+
"optional": true
|
|
78
|
+
},
|
|
79
|
+
"@deepseek-ai/dsh-tools": {
|
|
80
|
+
"optional": true
|
|
81
|
+
},
|
|
82
|
+
"@deepseek-ai/schemastery": {
|
|
83
|
+
"optional": true
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"devDependencies": {
|
|
87
|
+
"@deepseek-ai/cordis": "link:../deepseek-harness/vendor/cordis",
|
|
88
|
+
"@deepseek-ai/dsh-agent": "link:../deepseek-harness/packages/core/agent",
|
|
89
|
+
"@deepseek-ai/dsh-commands": "link:../deepseek-harness/packages/interaction/commands",
|
|
90
|
+
"@deepseek-ai/dsh-invariants": "link:../deepseek-harness/packages/runtime-diagnostics/invariants",
|
|
91
|
+
"@deepseek-ai/dsh-sandbox": "link:../deepseek-harness/packages/sandbox/sandbox",
|
|
92
|
+
"@deepseek-ai/dsh-sandbox-policy": "link:../deepseek-harness/packages/sandbox/sandbox-policy",
|
|
93
|
+
"@deepseek-ai/dsh-session": "link:../deepseek-harness/packages/core/session",
|
|
94
|
+
"@deepseek-ai/dsh-system-prompt": "link:../deepseek-harness/packages/core/system-prompt",
|
|
95
|
+
"@deepseek-ai/dsh-tools": "link:../deepseek-harness/packages/core/tools",
|
|
96
|
+
"@deepseek-ai/schemastery": "link:../deepseek-harness/vendor/schemastery",
|
|
97
|
+
"@types/node": "^22.0.0",
|
|
98
|
+
"typescript": "^5.7.0",
|
|
99
|
+
"vitest": "^2.1.0"
|
|
100
|
+
}
|
|
101
|
+
}
|