@hwfee/dsh-git-bash 0.1.0 → 0.1.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 CHANGED
@@ -1,8 +1,10 @@
1
- # dsh-git-bash · Git Bash 默认 shell
1
+ # @hwfee/dsh-git-bash · Git Bash 默认 shell
2
2
 
3
- 在 Windows 上把 DeepSeek Harness 的命令解释器从 PowerShell 换成 **Git Bash**。
3
+ 在 Windows 上把 DeepSeek Harness 的 shell 命令交给 **Git Bash** 跑,并提供一个 `run_shell` 工具。
4
4
 
5
- 装好之后:模型跑的 `bash` 命令走 Git Bash,`grep`、`sed`、`find`、`&&`、`$VAR`、shebang 脚本都按 POSIX 语义工作,路径就是你项目所在的那个文件系统。
5
+ 装好之后:模型跑的 `run_shell` 走 Git Bash,`grep`、`sed`、`find`、`&&`、`$VAR`、shebang 脚本都按 POSIX 语义工作,路径就是你项目所在的那个文件系统。
6
+
7
+ **前提是会话允许(Windows)。** 在 Windows 上 Git Bash 进不了宿主沙箱,所以只在 `danger-full-access` 会话里执行;只读或 `workspace-write` 会话会被拒绝,并提示改用 Windows PowerShell。POSIX 上 bash 就是宿主自己的 shell,没有这个限制。见下文「设置」与「它会给你什么」。
6
8
 
7
9
  ## 安装
8
10
 
@@ -20,45 +22,84 @@ dsh plugin --profile desktop remove @hwfee/dsh-git-bash
20
22
 
21
23
  ## 它怎么找到 Git Bash
22
24
 
23
- 按顺序试四个来源,第一个成功的就算数:
25
+ 按顺序试三个来源,第一个成功的就算数:
24
26
 
25
27
  1. **`DSH_GIT_BASH` 环境变量** —— 指向 `bash.exe` 的完整路径。非标准安装位置用这个。
26
- 2. **`git --exec-path`** —— 得到 `…/Git/mingw64/libexec/git-core`,往上两级就是 Git 根目录,取它自带的 `bin/bash.exe`。
27
- 3. **常见安装位置** —— `C:\Program Files\Git\bin\bash.exe` 等。
28
- 4. POSIX 上直接用 PATH 里的 `bash`。
28
+ 2. **`git --exec-path`** —— 得到 `…/Git/mingw64/libexec/git-core`,往上三级就是 Git 根目录,取它自带的 `bin/bash.exe`。
29
+ 3. **常见安装位置** —— `C:/Program Files/Git/bin/bash.exe`、`C:/Program Files/Git/usr/bin/bash.exe`、`C:/Program Files (x86)/Git/bin/bash.exe`。
30
+
31
+ POSIX 上不找 Git for Windows,直接取 PATH 里的 `bash`。
29
32
 
30
- **为什么不用 `where bash`。** Windows 上 `bash` 常常解析到 `C:\Windows\System32\bash.exe` —— WSL 的替身。它确实是 bash,但它是**另一个文件系统**(`/mnt/c/...`)、另一个用户、而且没有 Windows 那份 `git`。选错它之后每条命令都以一种看起来像"插件坏了"的方式失败,所以这里宁可找不到也不误选。
33
+ **为什么不用 `where bash`。** Windows 上 `bash` 常常解析到 `C:\Windows\System32\bash.exe` —— WSL 的替身。它确实是 bash,但它是**另一个文件系统**(`/mnt/c/...`)、另一个用户、而且没有 Windows 那份 `git`。选错它之后每条命令都以一种看起来像「插件坏了」的方式失败,所以这里宁可找不到也不误选。
31
34
 
32
- 找不到时插件**不会消失**:设置里的那一行会显示「没找到 Git Bash」并告诉你怎么指定路径。
35
+ 找不到时插件**不会消失**:设置里那一行会说明是哪一项配置不对(例如「没找到 Git Bash。请安装 Git for Windows,或设置 DSH_GIT_BASH。」)。
33
36
 
34
37
  ## 设置
35
38
 
36
- 设置 → 通用设置,多出一行 **默认 shell**:
39
+ 设置 → 通用设置,多出一行 **默认 shell**,一个三值菜单:
40
+
41
+ | 模式 | 行为 |
42
+ |---|---|
43
+ | **自动**(默认) | 沿用原来的选 shell 规则:能解析到 Git Bash 就用它,否则用 PowerShell。每次解析结果都写明走的是哪条分支(`DSH_GIT_BASH` / `git --exec-path` / known path) |
44
+ | **Windows PowerShell** | 只用 pwsh,找不到也不回落 Git Bash |
45
+ | **Git Bash** | 只用 Git Bash,找不到也不回落 PowerShell |
46
+
47
+ **「选中了某个 shell」和「这次会话能不能跑它」是两件事。** 自动模式不会因为沙箱策略临时换解释器——那会让同一个设置在不同会话里跑出不同 shell,看起来像工具坏了。Windows 上的对应关系:
48
+
49
+ | 会话策略(Windows) | Git Bash | Windows PowerShell |
50
+ |---|---|---|
51
+ | `read-only` / `workspace-write` | **拒绝**,spawn 之前报错 | 正常执行:交给宿主执行器,在该模式下运行 |
52
+ | 判定不出策略(服务缺失、取不到会话、模式不认识) | **拒绝**(fail closed,不猜) | **同样拒绝**:连交给执行器时该带哪个模式都不知道,宁可不跑 |
53
+ | `danger-full-access` | 允许,直接运行(不经过沙箱) | 正常执行 |
37
54
 
38
- - 上面显示**实际找到的路径**,一眼能看出用的是哪个 bash
39
- - 下面一个开关 **保留系统 shell 工具**(默认开)—— 关掉后模型的工具列表里只剩 `run_shell`,不再有平台的 PowerShell 工具
55
+ 被拒绝时的提示不会建议放宽会话权限,它给出的出路是:**切到 Windows PowerShell 模式**跑(沙箱生效)、**改写成等价的 PowerShell 命令**,或者**把「这条命令需要 POSIX shell」告诉用户、由用户决定**。插件不会暗中替换解释器。
56
+
57
+ POSIX 上不存在这一列的差异:`bash` 就是宿主自己的 shell,命令交给 `ctx.shell` 执行,沙箱照常生效。
58
+
59
+ **这一行不显示可执行文件路径。** 路径属于「结果里说一次就够」的细节:`run_shell` 的每条返回都会带上它,而设置行只回答「用哪个 shell」。
40
60
 
41
61
  ## 它会给你什么
42
62
 
43
- **`run_shell` 工具。** 参数 `command`(必填)和 `workdir`(可选,绝对路径)。返回运行它的 shell 路径、退出码、stdout 和 stderr。
63
+ **`run_shell` 工具。** 参数 `command`(必填)和 `workdir`(可选,绝对路径)。返回退出码、stdout、stderr,以及这次命令**在哪跑的**。
64
+
65
+ **非零退出不是错误。** `grep` 没匹配到会退出 1,那是一个结果而不是故障,工具照常返回退出码和输出。只有「shell 根本起不来」才算错误。
66
+
67
+ **每条结果都标明路径:`· host` 还是 `· direct`,而且能不能走 `· direct` 由会话的沙箱策略决定。**
44
68
 
45
- **非零退出不是错误。** `grep` 没匹配到会退出 1,那是一个结果而不是故障,工具照常返回退出码和输出。只有"shell 根本起不来"才算错误。
69
+ - `· host`:命令交给了宿主的 `ctx.shell`(Windows 上是 `pwsh-sandbox`),沙箱、取消、工作目录、进程生命周期都归宿主。会话的沙箱模式会随请求一起交给执行器,不会被丢掉。
70
+ - `· direct`:插件自己 spawn。**Git Bash 在 Windows 上只能走这条**——沙箱里的 pwsh 无法创建 MSYS 进程(`NtCreateDirectoryObject 0xC0000022`,已实测)。而它是**没有沙箱**的,所以只在会话明确是 `danger-full-access` 时才允许。
71
+
72
+ **受限会话里 Git Bash 会被拒绝,这是刻意的(fail closed)。** 只读、`workspace-write`、以及任何无法判定模式的会话,`run_shell` 会在**启动任何进程之前**报错并说明原因,什么也不执行。提示给出的是「改用 Windows PowerShell」——它能在沙箱内跑;插件不会替你换解释器,也不会劝你提权。
73
+
74
+ > 这条以前是 fail-open:旧版本会在未沙箱的情况下直接 spawn,只在结果里事后声明一句。事后的声明不是控制手段——一个只读会话仍然能写盘。现在的判据在 `lib/index.js` 的 `resolveSandboxDecision()`:策略服务缺失、取不到会话、模式不认识,一律拒绝;只有明确的 `danger-full-access` 才放行 direct 路径。
75
+
76
+ **取消会被传播。** 工具调用被取消时,中止信号会交给实际执行命令的那条路径(宿主执行器或插件的直接 spawn),已经取消的调用不会再启动进程。取消之后子进程树是否随之全部结束,取决于该平台的执行器实现,本文不把它写成跨平台保证。
77
+
78
+ **命令卡片。** `run_shell`、宿主的 `pwsh` 与 `bash` 三种命令行都渲染成同一张卡(`tool.call.toolview`,按 wire 名注册;宿主原有的 `bash` 视图用 `priority` 让位):
79
+
80
+ ```
81
+ Ran a command ← 描述(模型没写时用「已运行命令」)
82
+ ┌──────────────────────────────┐
83
+ │ $ grep -rn "box-shadow" src │ ← 带 $ 前缀的命令,命令/参数/字符串分色
84
+ └──────────────────────────────┘
85
+ 输出的前几行直接流淌在卡片里…… ← 无标签、无第二个框
86
+ ```
87
+
88
+ 罐头输出(`[gitbash · …] exit 0 · direct` 那几行)保持原样,它是结果的一部分。卡片默认自动换行,长输出在 280px 后内部滚动,不会把对话撑高。
46
89
 
47
90
  ## 与宿主 shell 的关系
48
91
 
49
92
  宿主的 shell 是 `ctx.shell` 能力接缝,**每个上下文只能有一个实现**。Windows 上基础 bundle 组装的是 `pwsh-sandbox`(PowerShell),POSIX 上是 `bash-sandbox`。
50
93
 
51
- **`run_shell` 尽量走宿主的执行器,并在结果里说明走没走。** 选中的解释器作为命令交给 `ctx.shell`:PowerShell 模式下是 `& '<pwsh.exe>' -NoProfile -NonInteractive -Command '<command>'`,结果显示 `· host`,沙箱、取消、工作目录和进程生命周期都归宿主。**Git Bash 在 Windows 上是个例外**:沙箱里的 pwsh 无法创建 MSYS 进程(`NtCreateDirectoryObject 0xC0000022`,已实测),所以这一模式仍由插件直接启动,结果显示 `· direct` 并附一句「未经过沙箱」。这不是静默降级——每一条结果都会写清楚。代价是本工具**不能**替用户发起沙箱升级审批(那是原生 `pwsh` 工具的职责),被拒绝时会如实报错。
94
+ 所以「让 Git Bash 成为默认」是 **profile 层**的决定,不是运行时劫持:本包的 `cordis.patch.yml` 只插入自己的行。真正的接管路径是在 profile 的 `cordis.patch.yml` 里用 `disabled:` 关掉平台默认那一行——代价是**宿主的 PowerShell 执行器不再可用**。不想付这个代价,就保留开关,让 `run_shell` 与原生 `pwsh` 并存。
52
95
 
53
96
  **模式的切换会真的到宿主。** 设置行在浏览器进程里,`run_shell` 在宿主进程里;两者之间有一条带同源头围栏的 `POST /dsh-git-bash/mode`(`GET` 可读回当前值)。只发 Cordis 事件是不够的——那个事件跨不过进程边界,宿主会永远停在 `auto`。
54
97
 
55
- 因此"让 Git Bash 成为默认"是 **profile 层**的决定,不是运行时劫持:本包的 `cordis.patch.yml` 只插入自己的行;要让 Git Bash 接管,需要在 profile 的 `cordis.patch.yml` 里用 `disabled:` 关掉平台默认的那一行。这样做的后果是**宿主的 PowerShell 执行器不再可用**——如果你需要它,别关那一行,改用 `run_shell` 与 `pwsh` 并存(即保留开关,让两个工具都在)。
56
-
57
98
  ## 开发者
58
99
 
59
100
  ```bash
60
101
  cd plugins/git-bash
61
- npm test # 新鲜度 + 清单契约 + 解析 + 工具 + 状态,31 项
102
+ npm test # 新鲜度 + 清单契约 + 解析 + 工具 + 状态 + 命令卡片(数字以输出为准)
62
103
  npm run build # 重新生成 client/client.js(产物提交进 git)
63
104
  ```
64
105