dsh-bash-terminal-ts 0.2.5

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 MAXeaglet
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.en.md ADDED
@@ -0,0 +1,195 @@
1
+ # dsh-bash-terminal-ts
2
+
3
+ [![test](https://github.com/drscrewdriver/dsh-bash-terminal-ts/actions/workflows/test.yml/badge.svg)](https://github.com/drscrewdriver/dsh-bash-terminal-ts/actions/workflows/test.yml)
4
+
5
+ **English** | [日本語](README.ja.md) | [한국어](README.ko.md) | [中文](README.md)
6
+
7
+ A DSH (DeepSeek Harness) plugin: a single `shell` tool that runs **PowerShell / Git Bash / MSYS2 / WSL** commands through one unified entry point on Windows.
8
+
9
+ The terminal is **selected by you in the Web UI** — the model cannot change it. Pick one once, and every command from then on runs through it.
10
+
11
+ ## Why use it
12
+
13
+ | Selling point | In one line |
14
+ |------|--------|
15
+ | **MSYS2 genuinely works** | This isn't "a new dropdown option" — it gets three things right at once: `bash.exe` resolution, the login shell, and the `MSYSTEM` environment. Pick MSYS2 and `gcc` / `make` just work (see "MSYS2 support" below) |
16
+ | **TypeScript source** | `strict` + `noUncheckedIndexedAccess`; pure functions build argv/env and are unit-testable |
17
+ | **Targets DSH 0.1.2 as the primary version** | `engines.dsh: >=0.1.2-rc.1 <0.2.0-0`, built against the 0.1.2 `ctx.subprocess` / `ctx.sandbox` / PTY seams |
18
+ | **Four terminals, one tool** | A single `shell` tool covers PowerShell / Git Bash / MSYS2 / WSL, so the model never has to learn four parameter sets |
19
+ | **Sandbox aligned with the official mechanism** | Uses the official `ctx.sandboxPolicy` + `ctx.sandbox`, fail-closed, and surfaces the same-turn escalation hint when a call is denied |
20
+ | **Interactive terminal** | A separate real-PTY session tool: `open / send / read / signal / close`, with Ctrl+C support and state that survives across turns |
21
+
22
+ ## Supported backends
23
+
24
+ | Backend | What actually runs | Syntax / paths | Environment variables |
25
+ |------|----------|-------------|----------|
26
+ | `powershell` (default) | `pwsh -NoLogo -NoProfile -NonInteractive -Command <cmd>` | PowerShell; `C:\...` | `$env:NAME` |
27
+ | `gitbash` | Git for Windows `bash -lc <cmd>` | POSIX; `/d/WorkSpace`; PATH includes `/usr/bin`, `/mingw64/bin` | `$NAME` |
28
+ | `msys2` | `C:\msys64\usr\bin\bash.exe -lc <cmd>` (login shell; `MSYSTEM=MINGW64`) | POSIX; ships a full GCC / mingw64 toolchain | `$NAME` |
29
+ | `wsl` | `wsl [-d <distro>] -e bash -lc <cmd>` | Linux; `/mnt/d/...` | `$NAME` (via WSLENV) |
30
+
31
+ Every call spins up a fresh shell: **no state is preserved** (cwd / variables / aliases) — pass `workdir` instead of using `cd`. Use the interactive terminal tool when you need state to persist across turns.
32
+
33
+ ## MSYS2 support
34
+
35
+ MSYS2 looks like "just one more backend", but it actually hides three traps, and the plugin handles each one:
36
+
37
+ **1. You cannot launch `msys2.exe`.**
38
+ `C:\msys64\msys2.exe` is a Cygwin launcher that allocates a console window. This plugin spawns processes with piped stdio (the standard DSH approach), and under those conditions it **exits 0 while returning zero bytes of output** — the command fails silently, appearing to "succeed" while doing nothing at all. So the candidate order is `usr\bin\bash.exe` → `bin\bash.exe` → `msys2.exe` as a fallback, and **a usable `bash.exe` always wins**.
39
+
40
+ **2. `-lc` is not optional.**
41
+ Only a login shell reads `/etc/profile`, and only `/etc/profile` adds `/usr/bin` and `/mingw64/bin` to PATH. With a bare `-c`, `tr`, `sed`, and `gcc` all come back as `command not found`.
42
+
43
+ **3. `MSYSTEM=MINGW64` has to be injected.**
44
+ Otherwise `/etc/profile` initializes with the default MSYS environment and the gcc and make in `/mingw64/bin` are unavailable. The plugin injects it through `buildEnv` (**values you set explicitly take precedence**), and the `shell` tool and the interactive terminal share that same `buildEnv` — so you never hit a "works in the tool but not in the terminal" discrepancy.
45
+
46
+ Verified in practice (real PTY): the prompt changes from `MSYS` to `MINGW64`, and `command -v gcc` → `/mingw64/bin/gcc`.
47
+
48
+ All three are guarded by regression tests: `test/unit.ts` asserts that `bash.exe` is ordered before `msys2.exe`; `test/apply.ts` asserts that the PTY environment contains `MSYSTEM=MINGW64` and that it does not leak into gitbash.
49
+
50
+ ## Design notes
51
+
52
+ - **The terminal is the user's decision, and the AI cannot change it**: the Web UI settings page (Settings → General) shows a "Default terminal" dropdown (PowerShell / Git Bash / MSYS2 / WSL); the `shell` tool always uses that setting and never exposes a terminal parameter to the model. The setting persists through the DSH settings system (settings.yaml).
53
+ - **It does not take over the `ctx.shell` capability seam**: DSH's built-in sandboxed `pwsh` tool stays available as-is; this plugin's `shell` tool is an **additional** multi-terminal entry point.
54
+ - Processes are spawned through the shared `ctx.subprocess` seam: process-tree termination (Windows `taskkill /T`), SIGTERM → grace → SIGKILL, and output spill files, matching the behavior of the official `dsh-tool-bash` / `dsh-tool-pwsh`.
55
+ - Background tasks register with the generic `jobs` registry and support `run_in_background` / `job_output` / `job_kill`.
56
+ - The tool's `shell` parameter is an enum (the UI renders it as a dropdown), and the model chooses a terminal on each call.
57
+ - The `<option>` entries for the four backends in the frontend dropdown, along with the `shell.<id>` strings in both locale bundles, are covered by drift-guard tests — add a backend and forget the copy, and the tests fail immediately.
58
+
59
+ ## Installation
60
+
61
+ ### Standard install (npm)
62
+
63
+ ```powershell
64
+ # 1. Install the plugin package
65
+ npm install -g dsh-bash-terminal-ts
66
+ dsh plugin --profile web add dsh-bash-terminal-ts
67
+
68
+ # 2. Patch the DSH settings allowlist (a DSH limitation, see the note below; install.ps1 can run this step on its own)
69
+ powershell -ExecutionPolicy Bypass -File install.ps1 install
70
+
71
+ # 3. Restart dsh web
72
+ ```
73
+
74
+ ### Local development install (junction-linked, source edits take effect immediately)
75
+
76
+ ```powershell
77
+ # 1. Link the plugin package into the profile's node_modules (junction, so source edits take effect immediately)
78
+ $profile = "$env:USERPROFILE\.dsh\profiles\web"
79
+ New-Item -ItemType Junction -Path "$profile\node_modules\dsh-bash-terminal-ts" -Target "D:\WorkSpace\projects\dsh-bash-terminal-ts" | Out-Null
80
+
81
+ # 2. Let the plugin resolve its @deepseek-ai/* dependencies (junction into the profile's dependency tree)
82
+ New-Item -ItemType Junction -Path "D:\WorkSpace\projects\dsh-bash-terminal-ts\node_modules\@deepseek-ai" -Target "$profile\..\node_modules\@deepseek-ai" | Out-Null
83
+
84
+ # 3. Append the mount line to cordis.patch.yml (see the patch snippet below)
85
+ # 4. (Only after changing frontend source) rebuild the client bundle:
86
+ # cd D:\WorkSpace\projects\dsh-bash-terminal-ts && node scripts/build-client.mjs
87
+ # 5. Let the settings UI accept this plugin's settings writes (a DSH limitation, see the note below)
88
+ # 6. Restart dsh web
89
+ ```
90
+
91
+ > **DSH settings UI allowlist limitation**: DSH's api-gateway (dsh-host-apiproxy) enforces a
92
+ > **hardcoded allowlist** of the settings namespaces exposed to the Web settings client
93
+ > (third-party plugin settings are rejected with `settings-not-exposed` by default, so
94
+ > changes made in the UI silently do nothing).
95
+ > install.ps1 patches that allowlist automatically (adding `bash-terminal`, after backing up
96
+ > the original file). **You must re-run install.ps1 after upgrading DSH** to restore the
97
+ > patch. On uninstall, install.ps1 reverts it.
98
+
99
+ Add to `cordis.patch.yml`:
100
+
101
+ ```yaml
102
+ - insert:
103
+ - id: tool-bash-terminal
104
+ name: 'dsh-bash-terminal-ts'
105
+ ```
106
+
107
+ Verify the composition tree (no restart required):
108
+
109
+ ```powershell
110
+ node "$env:APPDATA\nvm\v24.16.0\node_modules\@deepseek-ai\dsh\lib\bin.js" --profile web --dump-config | Select-String dsh-bash-terminal-ts
111
+ ```
112
+
113
+ ## Usage
114
+
115
+ **The user sets the default terminal in the Web UI**: open Settings (gear icon) → General → the "Default terminal" dropdown, and choose one of PowerShell / Git Bash / MSYS2 / WSL. The change takes effect immediately and is persisted.
116
+
117
+ Once the model sees the `shell` tool, it automatically runs commands through the terminal you selected (the tool exposes no terminal parameter, so the model cannot override your choice):
118
+
119
+ - Default terminal = Git Bash: `shell(command: "git status")` runs through Git Bash
120
+ - Default terminal = MSYS2: `shell(command: "gcc --version")` runs through MSYS2 (login shell, PATH includes `/usr/bin` and `/mingw64/bin`, with a full GCC / mingw64 toolchain)
121
+ - Default terminal = WSL: `shell(command: "ls -la /mnt/d/WorkSpace")` runs through WSL; pass `distro: "Ubuntu"` to target a specific distribution
122
+ - Default terminal = PowerShell: `shell(command: "Get-Process node")` runs through PowerShell
123
+
124
+ ## Configuration
125
+
126
+ **Web UI settings** (recommended): Settings → General → "Default terminal".
127
+
128
+ The plugin row's `config` (overrides the defaults and forms the composition baseline for the setting):
129
+
130
+ | Key | Default | Description |
131
+ |----|------|------|
132
+ | `defaultShell` | `powershell` | The backend used when the setting does not override it |
133
+ | `timeoutMs` | 120000 | Default timeout |
134
+ | `maxTimeoutMs` | 600000 | Upper bound for a caller-supplied timeoutMs |
135
+ | `pwshPath` | auto-detected | Pin the pwsh.exe path |
136
+ | `gitBashPath` | auto-detected | Pin the git bash.exe path |
137
+ | `msys2Path` | auto-detected | Pin the MSYS2 entry path (must point at `bash.exe`, not `msys2.exe`; see "MSYS2 support") |
138
+ | `wslPath` | auto-detected | Pin the wsl.exe path |
139
+
140
+ ## Uninstall
141
+
142
+ ```powershell
143
+ Remove-Item "$env:USERPROFILE\.dsh\profiles\web\node_modules\dsh-bash-terminal-ts" -Force
144
+ # Then delete the insert block from cordis.patch.yml and restart dsh web
145
+ ```
146
+
147
+ ## Sandbox (official mechanism integration)
148
+
149
+ The `shell` tool goes through DSH's official sandbox seams (`ctx.sandboxPolicy` + `ctx.sandbox`):
150
+
151
+ - Every call resolves the current sandbox policy; `danger-full-access` sessions execute directly (unwrapped).
152
+ - The PowerShell / Git Bash / MSYS2 backends wrap argv through `ctx.sandbox.confine` — with the same **fail-closed** semantics as the official executor: requesting a confined mode with no backend available throws `SandboxUnavailableError` rather than falling back to an unconfined run.
153
+ - The WSL backend is not wrapped: a WSL instance is its own isolated Linux VM (results report `enforcement: wsl-isolation`).
154
+ - When a confined mode denies the call, the result carries the official marker `[sandbox: file access denied under <mode> mode]` along with the same-turn escalation hint; the model can request a single escalation using `sandbox_permissions` + `justification` (approved by the user through `ctx.approval`), exactly as with the official bash/pwsh tools.
155
+ - Note: DSH's Windows ACL sandbox launcher (`node-addon-landlock-run-win32-x64`) is not published to npm yet, so the native sandbox backend is currently unavailable; the architecture is ready and activates automatically once DSH ships it.
156
+
157
+ ## ⚠️ Security notes
158
+
159
+ Commands run by the `shell` tool **outside the DSH sandbox**, with the same privileges as the dsh process
160
+ (equivalent to full-access command execution), and they do not benefit from the `pwsh` tool's
161
+ ConstrainedLanguage restrictions. DSH's file operation tools (read/write/edit) remain bound by the file sandbox.
162
+ Use this only in sessions you trust; when you need sandbox-protected PowerShell, keep using the official `pwsh` tool.
163
+
164
+ ## Known limitations
165
+
166
+ - The plugin only registers its tool on the `win32` platform.
167
+ - A WSL background process may briefly linger inside the distribution after a timeout or interruption (the WSL instance shuts down automatically once its last process exits).
168
+ - Git Bash and MSYS2 are both msys2 environments, so their behavior differs from WSL's Linux behavior (path mapping, package availability).
169
+ - If `C:\msys64` is installed in a non-default location and is not on PATH, `msys2Path` must be configured explicitly.
170
+
171
+ ## Testing
172
+
173
+ ```powershell
174
+ git clone https://github.com/drscrewdriver/dsh-bash-terminal-ts.git
175
+ cd dsh-bash-terminal-ts
176
+ npm install # install dependencies (including typescript)
177
+ npm run build # tsc compiles src/*.ts → lib/*.js; client.tsx → dist/client.js; test/*.ts → test-dist/
178
+ npm test # node test-dist/unit.js → apply.js → client.js
179
+ ```
180
+
181
+ CI runs the same suite on `windows-latest` (`.github/workflows/test.yml`).
182
+
183
+ ## Technical implementation
184
+
185
+ The source is TypeScript (`strict` + `noUncheckedIndexedAccess`), and the compiled artifacts `lib/` and `dist/` are committed alongside the repository, so DSH loads `lib/index.js` directly and the plugin **works without a build step**.
186
+
187
+ All require-side dependencies (13 packages, `@deepseek-ai/*` and friends) are declared as `peerDependencies` + `peerDependenciesMeta.optional`, avoiding a duplicate install alongside the host's own copies.
188
+
189
+ ## Credits
190
+
191
+ This project evolves from [MAXeaglet/dsh-bash-terminal](https://github.com/MAXeaglet/dsh-bash-terminal) — the original `shell` tool, the three-backend PowerShell / Git Bash / WSL architecture, and the sandbox seam integration all come from the original author, MAXeaglet. This version builds on that work by adding the MSYS2 backend, a TypeScript rewrite, and DSH 0.1.2 support.
192
+
193
+ ## License
194
+
195
+ MIT
package/README.ja.md ADDED
@@ -0,0 +1,194 @@
1
+ # dsh-bash-terminal-ts
2
+
3
+ [![test](https://github.com/drscrewdriver/dsh-bash-terminal-ts/actions/workflows/test.yml/badge.svg)](https://github.com/drscrewdriver/dsh-bash-terminal-ts/actions/workflows/test.yml)
4
+
5
+ [English](README.en.md) | **日本語** | [한국어](README.ko.md) | [中文](README.md)
6
+
7
+ DSH(DeepSeek Harness)プラグイン:Windows 上で **PowerShell / Git Bash / MSYS2 / WSL** の 4 種類のターミナルコマンドを 1 つの `shell` ツールに統合して実行します。
8
+
9
+ ターミナルは**あなたが Web UI で選びます**。モデルは変更できません。一度選べば、以降のすべてのコマンドはそのターミナルで実行されます。
10
+
11
+ ## なぜ使うのか
12
+
13
+ | 売り | ひとことで |
14
+ |------|--------|
15
+ | **MSYS2 が本当に動く** | 「ドロップダウンの選択肢を 1 つ足した」だけではありません。`bash.exe` の解決、ログインシェル、`MSYSTEM` 環境という 3 点をすべて正しく処理しています —— MSYS2 を選べばそのまま `gcc` や `make` が使えます(後述の「MSYS2 サポート」参照) |
16
+ | **TypeScript ソース** | `strict` + `noUncheckedIndexedAccess`。argv / env の構築は純関数が担当するため単体テスト可能です |
17
+ | **DSH 0.1.2 を主対象** | `engines.dsh: >=0.1.2-rc.1 <0.2.0-0`。0.1.2 の `ctx.subprocess` / `ctx.sandbox` / PTY の接合部に合わせて構築しています |
18
+ | **4 種類のターミナルを 1 つのツールで** | 同じ `shell` ツールが PowerShell / Git Bash / MSYS2 / WSL をカバーするので、モデルは 4 通りもの引数を覚える必要がありません |
19
+ | **サンドボックスは公式準拠** | 公式の `ctx.sandboxPolicy` + `ctx.sandbox` を使用し、fail-closed。拒否時には同一ターン内での昇格案内を返します |
20
+ | **対話型ターミナル** | 本物の PTY セッションツールも用意しています:`open / send / read / signal / close`。Ctrl+C が使え、ターンをまたいで状態を保持します |
21
+
22
+ ## 対応バックエンド
23
+
24
+ | バックエンド | 実際の実行 | 構文 / パス | 環境変数 |
25
+ |------|----------|-------------|----------|
26
+ | `powershell`(デフォルト) | `pwsh -NoLogo -NoProfile -NonInteractive -Command <cmd>` | PowerShell;`C:\...` | `$env:NAME` |
27
+ | `gitbash` | Git for Windows `bash -lc <cmd>` | POSIX;`/d/WorkSpace`;PATH に `/usr/bin`、`/mingw64/bin` を含む | `$NAME` |
28
+ | `msys2` | `C:\msys64\usr\bin\bash.exe -lc <cmd>`(ログインシェル;`MSYSTEM=MINGW64`) | POSIX;完全な GCC / mingw64 ツールチェーンを同梱 | `$NAME` |
29
+ | `wsl` | `wsl [-d <distro>] -e bash -lc <cmd>` | Linux;`/mnt/d/...` | `$NAME`(WSLENV 経由) |
30
+
31
+ 呼び出しごとにまったく新しいシェルが起動します:**状態は保持されません**(cwd / 変数 / エイリアス)。`cd` ではなく `workdir` を渡してください。ターンをまたいで状態を保持したい場合は対話型ターミナルツールを使ってください。
32
+
33
+ ## MSYS2 サポート
34
+
35
+ MSYS2 は「バックエンドをもう 1 つ足すだけ」に見えますが、実際には 3 つの落とし穴があり、本プラグインはそれを 1 つずつ処理しています。
36
+
37
+ **1. `msys2.exe` は起動できません。**
38
+ `C:\msys64\msys2.exe` はコンソールウィンドウを割り当てる Cygwin ランチャーです。本プラグインはパイプ stdio で spawn しますが(これが DSH の標準方式です)、その場合これは **exit 0 でゼロバイトの出力を返します** —— コマンドは静かに失敗し、「成功」したように見えて実際には何も行われません。したがって候補の順序は `usr\bin\bash.exe` → `bin\bash.exe` → `msys2.exe` のフォールバックとなり、**利用可能な `bash.exe` が常に優先されます**。
39
+
40
+ **2. `-lc` は省略できません。**
41
+ `/etc/profile` を読むのはログインシェルだけで、`/usr/bin` と `/mingw64/bin` を PATH に追加するのも `/etc/profile` だけです。裸の `-c` を使うと `tr`、`sed`、`gcc` がすべて `command not found` になります。
42
+
43
+ **3. `MSYSTEM=MINGW64` を注入する必要があります。**
44
+ そうしないと `/etc/profile` がデフォルトの MSYS 環境として初期化され、`/mingw64/bin` にある gcc や make が使えません。本プラグインは `buildEnv` 経由で注入します(**あなたが明示的に設定した値が優先されます**)。また `shell` ツールと対話型ターミナルは同じ `buildEnv` を通るため、「ツールでは動くのにターミナルでは動かない」といったずれは発生しません。
45
+
46
+ 実測(本物の PTY):プロンプトが `MSYS` から `MINGW64` に変わり、`command -v gcc` → `/mingw64/bin/gcc` となります。
47
+
48
+ これら 3 点はすべて回帰テストで守られています。`test/unit.ts` は `bash.exe` が `msys2.exe` より前に並ぶことを断言し、`test/apply.ts` は PTY 環境に `MSYSTEM=MINGW64` が含まれ、かつ gitbash に漏れないことを断言します。
49
+
50
+ ## 設計上の要点
51
+
52
+ - **ターミナルはユーザーが決め、AI は変更できない**:Web UI の設定画面(設定 → 一般)に「デフォルトターミナル」ドロップダウン(PowerShell / Git Bash / MSYS2 / WSL)が表示されます。`shell` ツールは常にこの設定のみを使用し、モデルにターミナル引数を公開しません。設定は DSH settings システム(settings.yaml)で永続化されます。
53
+ - **`ctx.shell` 能力の接合部を占有しない**:DSH 標準のサンドボックス化された `pwsh` ツールはそのまま利用可能です。本プラグインの `shell` ツールは**追加の**マルチターミナル入口です。
54
+ - 共有された `ctx.subprocess` seam を通じてプロセスを派生させます:プロセスツリーの終了(Windows `taskkill /T`)、SIGTERM→grace→SIGKILL、出力の spill ファイル。公式の `dsh-tool-bash` / `dsh-tool-pwsh` と同じ挙動です。
55
+ - バックグラウンドタスクは共通の `jobs` registry に登録され、`run_in_background` / `job_output` / `job_kill` をサポートします。
56
+ - ツール引数 `shell` は列挙型です(UI ではドロップダウンとして自動レンダリングされます)。モデルは呼び出しごとにターミナルを自身で選択します。
57
+ - 4 つのバックエンドについて、フロントエンドのドロップダウン内の `<option>` と 2 つの言語パックの `shell.<id>` 文言には drift ガードテストがあります —— バックエンドを追加して文言の更新を忘れると、テストがそのまま失敗します。
58
+
59
+ ## インストール
60
+
61
+ ### 標準インストール(npm)
62
+
63
+ ```powershell
64
+ # 1. プラグインパッケージをインストール
65
+ npm install -g dsh-bash-terminal-ts
66
+ dsh plugin --profile web add dsh-bash-terminal-ts
67
+
68
+ # 2. DSH 設定のホワイトリストを patch(DSH 側の制限。下記の説明を参照。install.ps1 でこの手順だけを単独実行することもできます)
69
+ powershell -ExecutionPolicy Bypass -File install.ps1 install
70
+
71
+ # 3. dsh web を再起動
72
+ ```
73
+
74
+ ### ローカル開発インストール(junction 直結、ソース変更が即時反映)
75
+
76
+ ```powershell
77
+ # 1. プラグインパッケージを profile の node_modules にリンク(junction なのでソース変更が即時反映されます)
78
+ $profile = "$env:USERPROFILE\.dsh\profiles\web"
79
+ New-Item -ItemType Junction -Path "$profile\node_modules\dsh-bash-terminal-ts" -Target "D:\WorkSpace\projects\dsh-bash-terminal-ts" | Out-Null
80
+
81
+ # 2. プラグインが @deepseek-ai/* 依存を解決できるようにする(profile の依存ツリーへ junction)
82
+ New-Item -ItemType Junction -Path "D:\WorkSpace\projects\dsh-bash-terminal-ts\node_modules\@deepseek-ai" -Target "$profile\..\node_modules\@deepseek-ai" | Out-Null
83
+
84
+ # 3. cordis.patch.yml にマウント行を追記(下記の patch 断片を参照)
85
+ # 4. (フロントエンドのソースを変更した場合のみ)client bundle を再ビルド:
86
+ # cd D:\WorkSpace\projects\dsh-bash-terminal-ts && node scripts/build-client.mjs
87
+ # 5. 設定 UI が本プラグインの設定書き込みを受け付けるようにする(DSH 側の制限。下記の説明を参照)
88
+ # 6. dsh web を再起動
89
+ ```
90
+
91
+ > **DSH 設定 UI のホワイトリスト制限**:DSH の api-gateway(dsh-host-apiproxy)は、
92
+ > Web 設定クライアントに公開する settings namespace について**ハードコードされた
93
+ > ホワイトリスト**を持っています(サードパーティ製プラグインの設定はデフォルトで
94
+ > `settings-not-exposed` として拒否され、UI で変更しても反映されません)。
95
+ > install.ps1 はこのホワイトリストを自動で patch します(`bash-terminal` を追加し、
96
+ > 元のファイルは先にバックアップされます)。
97
+ > **DSH をアップグレードした後は install.ps1 を再実行して** patch を復元してください。アンインストール時には install.ps1 が元に戻します。
98
+
99
+ `cordis.patch.yml` への追記:
100
+
101
+ ```yaml
102
+ - insert:
103
+ - id: tool-bash-terminal
104
+ name: 'dsh-bash-terminal-ts'
105
+ ```
106
+
107
+ 組み立てツリーの検証(再起動不要):
108
+
109
+ ```powershell
110
+ node "$env:APPDATA\nvm\v24.16.0\node_modules\@deepseek-ai\dsh\lib\bin.js" --profile web --dump-config | Select-String dsh-bash-terminal-ts
111
+ ```
112
+
113
+ ## 使い方
114
+
115
+ **ユーザーは Web UI でデフォルトターミナルを設定します**:設定(歯車)→ 一般 →「デフォルトターミナル」ドロップダウンから、PowerShell / Git Bash / MSYS2 / WSL のいずれかを選びます。変更は即時反映され、永続化されます。
116
+
117
+ モデルは `shell` ツールを認識すると、コマンド実行時にあなたが選んだターミナルを自動的に使用します(ツールはターミナル引数を公開しないため、モデルはあなたの選択を変更できません)。
118
+
119
+ - デフォルトターミナル = Git Bash の場合:`shell(command: "git status")` は Git Bash を通ります
120
+ - デフォルトターミナル = MSYS2 の場合:`shell(command: "gcc --version")` は MSYS2 を通ります(ログインシェルで、PATH に `/usr/bin` と `/mingw64/bin` を含み、完全な GCC / mingw64 ツールチェーンを同梱)
121
+ - デフォルトターミナル = WSL の場合:`shell(command: "ls -la /mnt/d/WorkSpace")` は WSL を通ります。`distro: "Ubuntu"` を渡すとディストリビューションを指定できます
122
+ - デフォルトターミナル = PowerShell の場合:`shell(command: "Get-Process node")` は PowerShell を通ります
123
+
124
+ ## 設定
125
+
126
+ **Web UI 設定**(推奨):設定 → 一般 →「デフォルトターミナル」。
127
+
128
+ プラグイン row の `config`(デフォルトを上書きし、設定の composition の基準となります):
129
+
130
+ | キー | デフォルト | 説明 |
131
+ |----|------|------|
132
+ | `defaultShell` | `powershell` | 設定で上書きされていない場合のバックエンド |
133
+ | `timeoutMs` | 120000 | デフォルトのタイムアウト |
134
+ | `maxTimeoutMs` | 600000 | 呼び出し側 timeoutMs の上限 |
135
+ | `pwshPath` | 自動検出 | pwsh.exe のパスを固定 |
136
+ | `gitBashPath` | 自動検出 | git bash.exe のパスを固定 |
137
+ | `msys2Path` | 自動検出 | MSYS2 入口パスを固定(`bash.exe` を指す必要があり、`msys2.exe` を指してはいけません。「MSYS2 サポート」参照) |
138
+ | `wslPath` | 自動検出 | wsl.exe のパスを固定 |
139
+
140
+ ## アンインストール
141
+
142
+ ```powershell
143
+ Remove-Item "$env:USERPROFILE\.dsh\profiles\web\node_modules\dsh-bash-terminal-ts" -Force
144
+ # あわせて cordis.patch.yml から insert ブロックを削除し、dsh web を再起動します
145
+ ```
146
+
147
+ ## サンドボックス(公式機構との接続)
148
+
149
+ `shell` ツールは DSH 公式のサンドボックス接合部(`ctx.sandboxPolicy` + `ctx.sandbox`)を通ります:
150
+
151
+ - 呼び出しごとに現在のサンドボックス方針を解決します。`danger-full-access` のセッションではそのまま実行されます(ラップしません)。
152
+ - PowerShell / Git Bash / MSYS2 の各バックエンドは `ctx.sandbox.confine` を通じて argv をラップします —— 公式 executor と同じ **fail-closed** の意味論です:制限モードを要求したのに利用可能なバックエンドがない場合は `SandboxUnavailableError` を投げ、ラップなしの実行を拒否します。
153
+ - WSL バックエンドはラップしません:WSL の独立した Linux 仮想マシン自体が隔離であるためです(結果は `enforcement: wsl-isolation` を報告します)。
154
+ - 制限モードでサンドボックスに拒否された場合、結果には公式のマーカー `[sandbox: file access denied under <mode> mode]` と同一ターン内での昇格案内が付与されます。モデルは `sandbox_permissions` + `justification` によって 1 回の昇格を申請できます(`ctx.approval` を通じたユーザー承認を経由)。公式の bash/pwsh ツールと完全に同じです。
155
+ - 注意:DSH の Windows ACL サンドボックス launcher(`node-addon-landlock-run-win32-x64`)は現在まだ npm で公開されていないため、本機のサンドボックスバックエンドは当面利用できません。アーキテクチャはすでに整っており、DSH の公開後には自動的に有効になります。
156
+
157
+ ## ⚠️ セキュリティに関する注意
158
+
159
+ `shell` ツールのコマンドは**DSH サンドボックスの外側**で実行され、dsh プロセスと同じ権限を持ちます(完全アクセスのコマンド実行に相当します)。
160
+ `pwsh` ツールの ConstrainedLanguage 制限は適用されません。DSH のファイル操作ツール(read/write/edit)は引き続きファイルサンドボックスの制約を受けます。
161
+ 信頼できるセッションでのみ使用してください。サンドボックスで保護された PowerShell が必要な場合は、引き続き公式の `pwsh` ツールを使用してください。
162
+
163
+ ## 既知の制限
164
+
165
+ - 本プラグインは `win32` プラットフォームでのみツールを登録します。
166
+ - WSL のバックグラウンドプロセスは、タイムアウトや中断の後、ディストリビューション内に一時的に残ることがあります(WSL インスタンスは最後のプロセスが終了した時点で自動的に終了します)。
167
+ - Git Bash と MSYS2 はどちらも msys2 環境であり、WSL の Linux とは挙動に差があります(パスマッピング、パッケージの可用性)。
168
+ - `C:\msys64` がデフォルト以外の場所にインストールされていて PATH 上にない場合は、`msys2Path` を明示的に設定する必要があります。
169
+
170
+ ## テスト
171
+
172
+ ```powershell
173
+ git clone https://github.com/drscrewdriver/dsh-bash-terminal-ts.git
174
+ cd dsh-bash-terminal-ts
175
+ npm install # 依存をインストール(typescript を含む)
176
+ npm run build # tsc でコンパイル src/*.ts → lib/*.js;client.tsx → dist/client.js;test/*.ts → test-dist/
177
+ npm test # node test-dist/unit.js → apply.js → client.js
178
+ ```
179
+
180
+ CI は `windows-latest` 上で同じ一式を実行します(`.github/workflows/test.yml`)。
181
+
182
+ ## 技術実装
183
+
184
+ ソースは TypeScript(`strict` + `noUncheckedIndexedAccess`)で、コンパイル成果物 `lib/`、`dist/` はリポジトリにコミットされています。DSH は `lib/index.js` をそのまま読み込むため、**インストール不要で使用できます**。
185
+
186
+ require 側の依存(`@deepseek-ai/*` など 13 パッケージ)はすべて `peerDependencies` + `peerDependenciesMeta.optional` として宣言し、ホストが同梱するコピーとの重複インストールを避けています。
187
+
188
+ ## 謝辞
189
+
190
+ 本プロジェクトは [MAXeaglet/dsh-bash-terminal](https://github.com/MAXeaglet/dsh-bash-terminal) を基に発展させたものです —— オリジナルの `shell` ツール、PowerShell / Git Bash / WSL の 3 バックエンド構成、およびサンドボックス接合部との接続はいずれも原作者によるものです。本バージョンではこれに MSYS2 バックエンド、TypeScript への書き直し、DSH 0.1.2 への適合を加えています。
191
+
192
+ ## ライセンス
193
+
194
+ MIT
package/README.ko.md ADDED
@@ -0,0 +1,192 @@
1
+ # dsh-bash-terminal-ts
2
+
3
+ [![test](https://github.com/drscrewdriver/dsh-bash-terminal-ts/actions/workflows/test.yml/badge.svg)](https://github.com/drscrewdriver/dsh-bash-terminal-ts/actions/workflows/test.yml)
4
+
5
+ [English](README.en.md) | [日本語](README.ja.md) | **한국어** | [中文](README.md)
6
+
7
+ DSH(DeepSeek Harness) 플러그인: Windows에서 **PowerShell / Git Bash / MSYS2 / WSL** 네 가지 터미널 명령을 하나의 `shell` 도구로 통합 실행합니다.
8
+
9
+ 터미널은 **Web UI에서 직접 선택**하며, 모델은 바꿀 수 없습니다. 한 번 선택하면 이후 모든 명령이 선택한 터미널로 실행됩니다.
10
+
11
+ ## 왜 사용해야 할까요
12
+
13
+ | 장점 | 한 줄 요약 |
14
+ |------|--------|
15
+ | **MSYS2가 실제로 동작합니다** | 단순히 "드롭다운 항목을 하나 추가한" 것이 아니라 `bash.exe` 해석, 로그인 셸, `MSYSTEM` 환경이라는 세 가지를 모두 제대로 처리했습니다 —— MSYS2를 선택하면 `gcc`, `make`를 바로 쓸 수 있습니다(아래 "MSYS2 지원" 참고) |
16
+ | **TypeScript 소스** | `strict` + `noUncheckedIndexedAccess` 적용, argv/env 구성은 순수 함수가 담당하므로 단위 테스트가 가능합니다 |
17
+ | **DSH 0.1.2를 주 버전으로 지원** | `engines.dsh: >=0.1.2-rc.1 <0.2.0-0`이며, 0.1.2의 `ctx.subprocess` / `ctx.sandbox` / PTY 접점에 맞춰 구축했습니다 |
18
+ | **네 가지 터미널을 하나의 도구로** | 동일한 `shell` 도구가 PowerShell / Git Bash / MSYS2 / WSL을 모두 지원하므로 모델이 네 가지 파라미터 체계를 익힐 필요가 없습니다 |
19
+ | **공식 샌드박스와 정렬** | 공식 `ctx.sandboxPolicy` + `ctx.sandbox`를 사용하고 fail-closed로 동작하며, 거부 시 같은 턴에 승격 안내를 제공합니다 |
20
+ | **대화형 터미널** | 실제 PTY 세션 도구를 별도로 제공합니다: `open / send / read / signal / close`, Ctrl+C 사용 가능, 턴 간 상태 유지 |
21
+
22
+ ## 지원하는 백엔드
23
+
24
+ | 백엔드 | 실제 실행 | 문법 / 경로 | 환경 변수 |
25
+ |------|----------|-------------|----------|
26
+ | `powershell`(기본) | `pwsh -NoLogo -NoProfile -NonInteractive -Command <cmd>` | PowerShell; `C:\...` | `$env:NAME` |
27
+ | `gitbash` | Git for Windows `bash -lc <cmd>` | POSIX; `/d/WorkSpace`; PATH에 `/usr/bin`, `/mingw64/bin` 포함 | `$NAME` |
28
+ | `msys2` | `C:\msys64\usr\bin\bash.exe -lc <cmd>`(로그인 셸; `MSYSTEM=MINGW64`) | POSIX; 완전한 GCC / mingw64 툴체인 내장 | `$NAME` |
29
+ | `wsl` | `wsl [-d <distro>] -e bash -lc <cmd>` | Linux; `/mnt/d/...` | `$NAME`(WSLENV 경유) |
30
+
31
+ 호출할 때마다 완전히 새로운 셸을 시작하며 **상태를 유지하지 않습니다**(cwd / 변수 / 별칭) —— `cd` 대신 `workdir`를 전달하세요. 턴 간에 상태를 유지해야 한다면 대화형 터미널 도구를 사용하세요.
32
+
33
+ ## MSYS2 지원
34
+
35
+ MSYS2는 얼핏 "백엔드를 하나 더 추가하는 것"처럼 보이지만 실제로는 세 가지 함정이 있고, 플러그인이 이를 하나씩 처리했습니다.
36
+
37
+ **1. `msys2.exe`는 실행할 수 없습니다.**
38
+ `C:\msys64\msys2.exe`는 콘솔 창을 할당하는 Cygwin 런처입니다. 이 플러그인은 파이프 stdio로 spawn하는데(DSH의 표준 방식), 이때 이 런처는 **exit 0을 반환하면서 출력은 0바이트**입니다 —— 명령이 조용히 실패하므로 "성공"한 것처럼 보이지만 아무 일도 하지 않습니다. 그래서 후보 순서는 `usr\bin\bash.exe` → `bin\bash.exe` → `msys2.exe` 폴백이며, **사용 가능한 `bash.exe`가 항상 우선**입니다.
39
+
40
+ **2. `-lc`는 생략할 수 없습니다.**
41
+ 로그인 셸만 `/etc/profile`을 읽고, `/etc/profile`만 `/usr/bin`과 `/mingw64/bin`을 PATH에 추가합니다. 순수 `-c`를 쓰면 `tr`, `sed`, `gcc`가 전부 `command not found`가 됩니다.
42
+
43
+ **3. `MSYSTEM=MINGW64`를 주입해야 합니다.**
44
+ 그렇지 않으면 `/etc/profile`이 기본 MSYS 환경으로 초기화되어 `/mingw64/bin`의 gcc, make를 사용할 수 없습니다. 플러그인은 `buildEnv`를 통해 주입하며(**명시적으로 설정한 값이 우선**), `shell` 도구와 대화형 터미널이 동일한 `buildEnv`를 사용하므로 "도구는 되는데 터미널은 안 되는" 편차가 생기지 않습니다.
45
+
46
+ 실측(실제 PTY): 프롬프트가 `MSYS`에서 `MINGW64`로 바뀌고, `command -v gcc` → `/mingw64/bin/gcc`.
47
+
48
+ 이 세 가지는 모두 회귀 테스트가 지키고 있습니다: `test/unit.ts`는 `bash.exe`가 `msys2.exe`보다 앞에 오는지 검증하고, `test/apply.ts`는 PTY 환경에 `MSYSTEM=MINGW64`가 포함되고 이것이 gitbash로 누출되지 않는지 검증합니다.
49
+
50
+ ## 설계 포인트
51
+
52
+ - **터미널은 사용자가 정하고 AI는 바꿀 수 없습니다**: Web UI 설정 페이지(설정 → 일반)에 "기본 터미널" 드롭다운(PowerShell / Git Bash / MSYS2 / WSL)이 나타나며, `shell` 도구는 항상 이 설정만 사용하고 터미널 파라미터를 모델에 노출하지 않습니다. 설정은 DSH settings 시스템을 통해 영구 저장됩니다(settings.yaml).
53
+ - **`ctx.shell` 능력 접점을 점유하지 않습니다**: DSH에 내장된 샌드박스 `pwsh` 도구는 그대로 사용할 수 있으며, 이 플러그인의 `shell` 도구는 **추가적인** 멀티 터미널 진입점입니다.
54
+ - 공유 `ctx.subprocess` seam을 통해 프로세스를 생성합니다: 프로세스 트리 종료(Windows `taskkill /T`), SIGTERM→grace→SIGKILL, 출력 spill 파일 등이 공식 `dsh-tool-bash` / `dsh-tool-pwsh`와 동일하게 동작합니다.
55
+ - 백그라운드 작업은 공용 `jobs` registry에 등록되며 `run_in_background` / `job_output` / `job_kill`을 지원합니다.
56
+ - 도구 파라미터 `shell`은 열거형이고(UI가 자동으로 드롭다운으로 렌더링), 모델이 호출할 때마다 터미널을 직접 선택합니다.
57
+ - 네 가지 백엔드의 프런트엔드 드롭다운 `<option>`과 두 언어 팩의 `shell.<id>` 문구에는 drift 가드 테스트가 있어, 백엔드를 추가하고 문구를 고치지 않으면 테스트가 바로 실패합니다.
58
+
59
+ ## 설치
60
+
61
+ ### 표준 설치(npm)
62
+
63
+ ```powershell
64
+ # 1. 플러그인 패키지 설치
65
+ npm install -g dsh-bash-terminal-ts
66
+ dsh plugin --profile web add dsh-bash-terminal-ts
67
+
68
+ # 2. DSH 설정 화이트리스트 패치 (DSH 제약, 아래 설명 참조; install.ps1로 이 단계만 따로 실행 가능)
69
+ powershell -ExecutionPolicy Bypass -File install.ps1 install
70
+
71
+ # 3. dsh web 재시작
72
+ ```
73
+
74
+ ### 로컬 개발 설치(junction 직접 연결, 소스 수정 즉시 반영)
75
+
76
+ ```powershell
77
+ # 1. 플러그인 패키지를 profile의 node_modules에 연결 (junction, 소스 수정 즉시 반영)
78
+ $profile = "$env:USERPROFILE\.dsh\profiles\web"
79
+ New-Item -ItemType Junction -Path "$profile\node_modules\dsh-bash-terminal-ts" -Target "D:\WorkSpace\projects\dsh-bash-terminal-ts" | Out-Null
80
+
81
+ # 2. 플러그인이 @deepseek-ai/* 의존성을 해석하도록 연결 (profile 의존성 트리로 junction)
82
+ New-Item -ItemType Junction -Path "D:\WorkSpace\projects\dsh-bash-terminal-ts\node_modules\@deepseek-ai" -Target "$profile\..\node_modules\@deepseek-ai" | Out-Null
83
+
84
+ # 3. cordis.patch.yml에 마운트 행 추가 (아래 patch 조각 참조)
85
+ # 4. (프런트엔드 소스를 수정한 경우에만) client bundle 재빌드:
86
+ # cd D:\WorkSpace\projects\dsh-bash-terminal-ts && node scripts/build-client.mjs
87
+ # 5. 설정 UI가 이 플러그인의 설정 쓰기를 받아들이도록 처리 (DSH 제약, 아래 설명 참조)
88
+ # 6. dsh web 재시작
89
+ ```
90
+
91
+ > **DSH 설정 UI 화이트리스트 제한**: DSH의 api-gateway(dsh-host-apiproxy)는
92
+ > Web 설정 클라이언트에 노출하는 settings namespace에 **하드코딩된 화이트리스트**를
93
+ > 둡니다(서드파티 플러그인의 설정은 기본적으로 `settings-not-exposed`로 거부되어 UI에서 바꿔도 반영되지 않습니다).
94
+ > install.ps1이 이 화이트리스트를 자동으로 patch합니다(`bash-terminal` 추가, 원본 파일은 먼저 백업).
95
+ > **DSH를 업그레이드한 뒤에는 install.ps1을 다시 실행해 patch를 복원해야 합니다.** 제거 시 install.ps1이 원래대로 되돌립니다.
96
+
97
+ `cordis.patch.yml` 추가:
98
+
99
+ ```yaml
100
+ - insert:
101
+ - id: tool-bash-terminal
102
+ name: 'dsh-bash-terminal-ts'
103
+ ```
104
+
105
+ 조합 트리 검증(재시작 불필요):
106
+
107
+ ```powershell
108
+ node "$env:APPDATA\nvm\v24.16.0\node_modules\@deepseek-ai\dsh\lib\bin.js" --profile web --dump-config | Select-String dsh-bash-terminal-ts
109
+ ```
110
+
111
+ ## 사용
112
+
113
+ **사용자가 Web UI에서 기본 터미널을 설정합니다**: 설정(톱니바퀴) → 일반 → "기본 터미널" 드롭다운에서 PowerShell / Git Bash / MSYS2 / WSL 중 하나를 선택합니다. 변경 사항은 즉시 반영되고 영구 저장됩니다.
114
+
115
+ 모델은 `shell` 도구를 인식하면 명령을 실행할 때 자동으로 선택한 터미널을 사용합니다(도구가 터미널 파라미터를 노출하지 않으므로 모델이 선택을 바꿀 수 없습니다):
116
+
117
+ - 기본 터미널 = Git Bash일 때: `shell(command: "git status")`는 Git Bash로 실행
118
+ - 기본 터미널 = MSYS2일 때: `shell(command: "gcc --version")`은 MSYS2로 실행(로그인 셸, PATH에 `/usr/bin`과 `/mingw64/bin` 포함, 완전한 GCC / mingw64 툴체인 내장)
119
+ - 기본 터미널 = WSL일 때: `shell(command: "ls -la /mnt/d/WorkSpace")`는 WSL로 실행되며, `distro: "Ubuntu"`를 전달해 배포판을 지정할 수 있습니다
120
+ - 기본 터미널 = PowerShell일 때: `shell(command: "Get-Process node")`는 PowerShell로 실행
121
+
122
+ ## 설정
123
+
124
+ **Web UI 설정**(권장): 설정 → 일반 → "기본 터미널".
125
+
126
+ 플러그인 row의 `config`(기본값을 덮어쓰며, 설정의 composition 기준이 됩니다):
127
+
128
+ | 키 | 기본값 | 설명 |
129
+ |----|------|------|
130
+ | `defaultShell` | `powershell` | 설정이 덮어쓰지 않았을 때의 백엔드 |
131
+ | `timeoutMs` | 120000 | 기본 타임아웃 |
132
+ | `maxTimeoutMs` | 600000 | 호출자 timeoutMs 상한 |
133
+ | `pwshPath` | 자동 감지 | pwsh.exe 경로 고정 |
134
+ | `gitBashPath` | 자동 감지 | git bash.exe 경로 고정 |
135
+ | `msys2Path` | 자동 감지 | MSYS2 진입 경로 고정(`bash.exe`를 가리켜야 하며 `msys2.exe`를 가리키면 안 됩니다. "MSYS2 지원" 참고) |
136
+ | `wslPath` | 자동 감지 | wsl.exe 경로 고정 |
137
+
138
+ ## 제거
139
+
140
+ ```powershell
141
+ Remove-Item "$env:USERPROFILE\.dsh\profiles\web\node_modules\dsh-bash-terminal-ts" -Force
142
+ # 그리고 cordis.patch.yml에서 insert 블록을 삭제하고 dsh web 재시작
143
+ ```
144
+
145
+ ## 샌드박스(공식 메커니즘 연동)
146
+
147
+ `shell` 도구는 DSH 공식 샌드박스 접점(`ctx.sandboxPolicy` + `ctx.sandbox`)을 사용합니다:
148
+
149
+ - 호출할 때마다 현재 샌드박스 정책을 해석하며, `danger-full-access` 세션은 래핑 없이 직접 실행합니다.
150
+ - PowerShell / Git Bash / MSYS2 백엔드는 `ctx.sandbox.confine`으로 argv를 래핑합니다 —— 공식 executor와 동일한 **fail-closed** 의미론으로, 제한 모드를 요청했지만 사용할 수 있는 백엔드가 없으면 `SandboxUnavailableError`를 던지고 그대로 실행하는 것을 거부합니다.
151
+ - WSL 백엔드는 래핑하지 않습니다: WSL은 그 자체가 독립적인 Linux 가상 머신이므로 격리로 간주합니다(결과에 `enforcement: wsl-isolation`으로 보고).
152
+ - 제한 모드에서 샌드박스가 거부하면 결과에 공식 마커 `[sandbox: file access denied under <mode> mode]`와 같은 턴의 승격 안내가 함께 담깁니다. 모델은 `sandbox_permissions` + `justification`으로 한 번의 승격을 요청할 수 있으며(`ctx.approval` 사용자 승인 경유), 공식 bash/pwsh 도구와 완전히 동일합니다.
153
+ - 참고: DSH의 Windows ACL 샌드박스 launcher(`node-addon-landlock-run-win32-x64`)는 현재 npm에 아직 게시되지 않아 이 머신에서는 샌드박스 백엔드를 사용할 수 없습니다. 아키텍처는 이미 준비되어 있으므로 DSH가 게시되면 자동으로 적용됩니다.
154
+
155
+ ## ⚠️ 보안 안내
156
+
157
+ `shell` 도구의 명령은 **DSH 샌드박스 밖에서** 실행되며 dsh 프로세스와 동일한 권한을 가집니다(완전 접근 명령 실행과 동일).
158
+ `pwsh` 도구의 ConstrainedLanguage 제한을 받지 않습니다. DSH의 파일 작업 도구(read/write/edit)는 여전히 파일 샌드박스의 제약을 받습니다.
159
+ 신뢰할 수 있는 세션에서만 사용하세요. 샌드박스 보호가 필요한 PowerShell이 필요하다면 공식 `pwsh` 도구를 계속 사용하세요.
160
+
161
+ ## 알려진 제한 사항
162
+
163
+ - 이 플러그인은 `win32` 플랫폼에서만 도구를 등록합니다.
164
+ - WSL 백그라운드 프로세스는 타임아웃/중단 후 배포판 안에 잠시 남아 있을 수 있습니다(WSL 인스턴스는 마지막 프로세스가 종료되면 자동으로 닫힙니다).
165
+ - Git Bash와 MSYS2는 모두 msys2 환경이므로 WSL의 Linux 동작과 차이가 있습니다(경로 매핑, 패키지 가용성).
166
+ - `C:\msys64`가 기본 위치가 아닌 곳에 설치되어 있고 PATH에 없다면 `msys2Path`를 명시적으로 설정해야 합니다.
167
+
168
+ ## 테스트
169
+
170
+ ```powershell
171
+ git clone https://github.com/drscrewdriver/dsh-bash-terminal-ts.git
172
+ cd dsh-bash-terminal-ts
173
+ npm install # 의존성 설치 (typescript 포함)
174
+ npm run build # tsc 컴파일 src/*.ts → lib/*.js; client.tsx → dist/client.js; test/*.ts → test-dist/
175
+ npm test # node test-dist/unit.js → apply.js → client.js
176
+ ```
177
+
178
+ CI는 `windows-latest`에서 동일한 세트를 실행합니다(`.github/workflows/test.yml`).
179
+
180
+ ## 기술 구현
181
+
182
+ 소스는 TypeScript(`strict` + `noUncheckedIndexedAccess`)이며, 컴파일 산출물 `lib/`, `dist/`는 저장소에 함께 커밋되어 DSH가 `lib/index.js`로 바로 로드하므로 **설치 없이 사용할 수 있습니다**.
183
+
184
+ require 측 의존성(`@deepseek-ai/*` 등 13개 패키지)은 모두 `peerDependencies` + `peerDependenciesMeta.optional`로 선언하여 호스트에 내장된 사본과 중복 설치되는 것을 피했습니다.
185
+
186
+ ## 감사의 글
187
+
188
+ 이 프로젝트는 [MAXeaglet/dsh-bash-terminal](https://github.com/MAXeaglet/dsh-bash-terminal)을 기반으로 발전시킨 것입니다 —— 원래의 `shell` 도구와 PowerShell / Git Bash / WSL 3백엔드 아키텍처, 샌드박스 접점 연동은 모두 원작자 MAXeaglet의 것입니다. 이 버전은 그 위에 MSYS2 백엔드, TypeScript 재작성, DSH 0.1.2 대응을 추가했습니다.
189
+
190
+ ## 라이선스
191
+
192
+ MIT