@harusame64/desktop-touch-mcp 1.10.4 → 1.12.0
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.ja.md +41 -11
- package/README.md +31 -12
- package/bin/launcher.js +3 -3
- package/package.json +10 -9
package/README.ja.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
npx -y @harusame64/desktop-touch-mcp
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
32 ツール、Rust ネイティブエンジン (UIA 2ms)、PowerShell 透過フォールバック、日本語/CJK 完全対応、MIT。上記 1 行を Claude / Cursor / VS Code Copilot の MCP 設定に追加するだけで、Notepad、Excel、Chrome、Windows Terminal、その他あらゆるアプリを Claude が操作できるようになります。
|
|
14
14
|
|
|
15
15
|
> *v0.15: Rust ネイティブエンジンにより**平均 82 倍高速化** — UIA フォーカス取得 2ms、SSE2 SIMD 画像差分 13〜15 倍速。設定不要:エンジンは自動ロード、不在時は PowerShell に透過フォールバック。*
|
|
16
16
|
> *v0.15.5: **固定リリース検証** — npm ランチャーは対応する GitHub Release tag だけを取得し、Windows runtime zip を検証してから展開します。*
|
|
@@ -47,6 +47,8 @@ npx -y @harusame64/desktop-touch-mcp
|
|
|
47
47
|
> **注意:** nut-js のネイティブバインディングは Visual C++ 再頒布可能パッケージを必要とします。
|
|
48
48
|
> インストール済みでない場合は [Microsoft公式](https://learn.microsoft.com/ja-jp/cpp/windows/latest-supported-vc-redist) からダウンロードしてください。
|
|
49
49
|
|
|
50
|
+
> **注意 (Key Locker):** Key Locker が使う認証情報ヘルパーは未署名の実行ファイルのため、環境によっては初回起動時に Windows SmartScreen やアンチウイルスが「発行元不明」の警告を表示することがあります。これは想定内で、ヘルパーは desktop-touch-mcp に同梱され、お使いのマシン上でローカルに動作します。許可して続行して問題ありません。(コード署名は今後のリリースで対応予定です。)
|
|
51
|
+
|
|
50
52
|
---
|
|
51
53
|
|
|
52
54
|
## インストール
|
|
@@ -137,19 +139,25 @@ npm run build
|
|
|
137
139
|
|
|
138
140
|
---
|
|
139
141
|
|
|
140
|
-
## ツール一覧 (
|
|
142
|
+
## ツール一覧 (32 ツール — 30 stub catalog + 2 dynamic v2)
|
|
141
143
|
|
|
142
144
|
> 📖 **詳細リファレンス**: [`docs/system-overview.md`](docs/system-overview.md) — 各ツールのパラメータ・応答形式・座標計算・レイヤーバッファ・技術ノートを網羅(英語)。
|
|
143
145
|
|
|
144
146
|
### スクリーンショット系 (5)
|
|
145
147
|
| ツール | 概要 |
|
|
146
148
|
|---|---|
|
|
147
|
-
| `screenshot` | メインキャプチャ。`detail` / `dotByDot` / `dotByDotMaxDimension` / `grayscale` / `region` / `diffMode`
|
|
149
|
+
| `screenshot` | メインキャプチャ。`detail` / `dotByDot` / `dotByDotMaxDimension` / `grayscale` / `region` / `diffMode` 対応。画像はインライン展開せず、ディスク保存した画像への安価なリンク `screenshot://by-ref/{id}` を返す |
|
|
148
150
|
| `screenshot_background` | 背面・最小化ウィンドウをキャプチャ (PrintWindow API) |
|
|
149
151
|
| `screenshot_ocr` | Windows OCR で文字と `clickAt` 座標を取得 |
|
|
150
152
|
| `get_screen_info` | モニター解像度・DPI・カーソル位置 |
|
|
151
153
|
| `scroll(action='capture')` | ページ全体をスクロールしながらスティッチ |
|
|
152
154
|
|
|
155
|
+
### スクリーンショットキャッシュ (2)
|
|
156
|
+
| ツール | 概要 |
|
|
157
|
+
|---|---|
|
|
158
|
+
| `screenshot_query` | by-ref リンクの裏にあるディスクキャッシュの一覧を、ピクセルを再読込せずに取得(captureId・by-ref uri・サイズ・寸法・時刻・tag、キャッシュ全体の合計)。パスは一切返さない |
|
|
159
|
+
| `screenshot_gc` | 保持ポリシー(最新 N 件 / バイト上限 / 経過時間)でキャッシュを掃除。既定は dry-run(削除対象の一覧のみ)。実削除は `dryRun:false` かつ `confirm:true` の両方が必要 |
|
|
160
|
+
|
|
153
161
|
### ウィンドウ管理 (4)
|
|
154
162
|
| ツール | 概要 |
|
|
155
163
|
|---|---|
|
|
@@ -235,6 +243,16 @@ DOM を触る `browser_*` ツールは `includeContext:false` で末尾の `acti
|
|
|
235
243
|
| `scroll(action='to_element')` | 要素名またはCSS selectorで対象をviewportへスクロール |
|
|
236
244
|
| `scroll(action='smart')` | CDP → UIA → 画像binary-searchの統合スクロール。ネスト・仮想リスト・sticky header対応 |
|
|
237
245
|
|
|
246
|
+
### Office (Excel) (1)
|
|
247
|
+
| ツール | 概要 |
|
|
248
|
+
|---|---|
|
|
249
|
+
| `excel` | Excel VBA マクロを COM 経由で記述・実行。`action='run_vba'` はマクロを管理下の Trusted Location に書き込んで実行、`action='check_access_vbom'` は読み取り専用の事前チェック。数式だけでは届かない処理を VBA で実行。初回のみ `node scripts/enable-access-vbom.mjs` |
|
|
250
|
+
|
|
251
|
+
### Key Locker (1)
|
|
252
|
+
| ツール | 概要 |
|
|
253
|
+
|---|---|
|
|
254
|
+
| `key_locker` | ターミナルが自動入力する認証情報(SSH 鍵のパスフレーズ、sudo / ログインパスワード)を管理。秘密情報はロッカー自身のセキュアダイアログに一度だけ入力し、この PC 上で暗号化保存(Windows DPAPI, current user)— アシスタントには一切見えない。`action='launch_console'` で自動入力対応コンソールを起動(返る `paneId` を `terminal` に渡して `ssh`/`sudo` を流す)/ `save`(登録)/ `list` / `forget` / `set_policy` / `status`。自動入力は `launch_console` で開いたコンソールでのみ発火。`DESKTOP_TOUCH_DISABLE_KEY_LOCKER=1` で無効化 |
|
|
255
|
+
|
|
238
256
|
---
|
|
239
257
|
|
|
240
258
|
## 推奨ワークフロー (v1.0.0)
|
|
@@ -537,15 +555,27 @@ V1 ツールはすべてそのまま動作します。再インストール不
|
|
|
537
555
|
|
|
538
556
|
フラグのセマンティクス(完全一致: 文字列 `"1"` のみ有効):
|
|
539
557
|
|
|
540
|
-
| `DISABLE_FUKUWARAI_V2` |
|
|
558
|
+
| `DISABLE_FUKUWARAI_V2` | V2 状態 |
|
|
559
|
+
|---|---|
|
|
560
|
+
| 未設定 / `"1"` 以外 | **ON**(デフォルト) |
|
|
561
|
+
| `"1"` | **OFF**(kill switch) |
|
|
562
|
+
|
|
563
|
+
### スクリーンショットキャッシュ (by-ref ストレージ)
|
|
564
|
+
|
|
565
|
+
`screenshot` などの画像系応答は、ピクセルを毎回インライン展開する代わりに、ディスク保存した画像への安価なリンク `screenshot://by-ref/{id}` を返します(look→act→confirm の反復が大幅に低トークン化)。キャッシュは自動で上限管理され、`screenshot_query` / `screenshot_gc` で確認・掃除できます。
|
|
566
|
+
|
|
567
|
+
| 環境変数 | デフォルト | 効果 |
|
|
541
568
|
|---|---|---|
|
|
542
|
-
|
|
|
543
|
-
|
|
|
544
|
-
| `
|
|
569
|
+
| `DESKTOP_TOUCH_SCREENSHOTS_DIR` | *(ユーザー別キャッシュ)* | キャッシュ保存先を固定。既定フォルダが作成・書き込み不可(ロックダウン PC など)の場合、この値 → runtime dir → OS の一時フォルダの順に書き込み可否を自動判定し、最初に書ける場所を使う(キャッシュを諦めない)。 |
|
|
570
|
+
| `DESKTOP_TOUCH_SCREENSHOT_MAX_COUNT` | `200` | 保持する最大キャプチャ数。 |
|
|
571
|
+
| `DESKTOP_TOUCH_SCREENSHOT_MAX_BYTES` | `256 MiB` | ディスク上のキャッシュ総量の上限。 |
|
|
572
|
+
| `DESKTOP_TOUCH_SCREENSHOT_MAX_AGE_MS` | *(無効)* | この経過時間(ms)より古いキャプチャを削除(opt-in)。 |
|
|
573
|
+
| `DESKTOP_TOUCH_SCREENSHOT_AUTOPRUNE` | `on` | 新規保存のたびに自動で間引く。`0` で無効化。 |
|
|
574
|
+
| `DESKTOP_TOUCH_SCREENSHOT_MIN_EVICT_AGE_MS` | `60000` | この時間(ms)より新しいキャプチャは自動退避しない。同一 PC 上で別の AI/プロセスが大量キャプチャしていても、渡したばかりの by-ref リンクが開けるよう保護。`0` で無効化。 |
|
|
545
575
|
|
|
546
|
-
###
|
|
576
|
+
### 削除済み: `DESKTOP_TOUCH_ENABLE_FUKUWARAI_V2`
|
|
547
577
|
|
|
548
|
-
v0.16.x での opt-in フラグです。v0.17
|
|
578
|
+
v0.16.x での opt-in フラグです。v0.17 以降は V2 がデフォルト ON のため、このフラグは効果を持たず、設定から削除して問題ありません。V2 を無効化するには `DESKTOP_TOUCH_DISABLE_FUKUWARAI_V2=1` を設定してください。
|
|
549
579
|
|
|
550
580
|
### V2 が失敗した場合のリカバリ
|
|
551
581
|
|
|
@@ -669,9 +699,9 @@ keyboard(action='type')(use_clipboard=true) を使うこと(IME バイパス
|
|
|
669
699
|
|
|
670
700
|
---
|
|
671
701
|
|
|
672
|
-
## 🚀
|
|
702
|
+
## 🚀 3,000+ Downloads!
|
|
673
703
|
|
|
674
|
-
おかげさまで
|
|
704
|
+
おかげさまで3,000ダウンロードを突破しました!この実験的なツールを試し、
|
|
675
705
|
Issue や PR、バグ報告で貢献してくれたすべての方に感謝します。皆さんの声が
|
|
676
706
|
次のリリースをより良くしてくれました。一緒に育ててくれてありがとう!
|
|
677
707
|
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
npx -y @harusame64/desktop-touch-mcp
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
32 tools, native Rust engine (UIA in 2 ms), zero-config PowerShell fallback, full CJK support, MIT licensed. Add the snippet above to your Claude / Cursor / VS Code Copilot config and Claude can drive Notepad, Excel, Chrome, Windows Terminal, and any other app on your machine.
|
|
14
14
|
|
|
15
15
|
> **Why this over pixel-clicking?** Two ideas run through every tool: **discover-then-act** — `desktop_discover` returns interactive entities with short-lived leases instead of raw coordinates, so `desktop_act` operates on *what* you mean, not *where* it was — and **per-action perception guards** that verify the target window's identity and bounds before input lands, catching wrong-window typing and stale-coordinate clicks before they happen.
|
|
16
16
|
>
|
|
@@ -48,6 +48,11 @@ npx -y @harusame64/desktop-touch-mcp
|
|
|
48
48
|
> **Note:** nut-js native bindings require the Visual C++ Redistributable.
|
|
49
49
|
> Download from [Microsoft](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist) if not already installed.
|
|
50
50
|
|
|
51
|
+
> **Note (Key Locker):** The credential helper Key Locker uses is an unsigned executable, so on
|
|
52
|
+
> some machines Windows SmartScreen or antivirus may show an "unknown publisher" warning the
|
|
53
|
+
> first time it runs. This is expected — the helper ships with desktop-touch-mcp and runs locally
|
|
54
|
+
> on your machine; you can allow it to proceed. Code signing is planned for a future release.
|
|
55
|
+
|
|
51
56
|
---
|
|
52
57
|
|
|
53
58
|
## Installation
|
|
@@ -141,7 +146,7 @@ For a local checkout, register the built server directly:
|
|
|
141
146
|
|
|
142
147
|
---
|
|
143
148
|
|
|
144
|
-
## Tools (
|
|
149
|
+
## Tools (32 Optimized Tools)
|
|
145
150
|
|
|
146
151
|
> 📖 **Full Reference**: [`docs/system-overview.md`](docs/system-overview.md) — Exhaustive guide on parameters, return schemas, and coordinate math.
|
|
147
152
|
|
|
@@ -155,7 +160,8 @@ For a local checkout, register the built server directly:
|
|
|
155
160
|
| Tool | Description |
|
|
156
161
|
|---|---|
|
|
157
162
|
| `desktop_state` | Lightweight check of focus, active window, cursor, and Auto-Perception attention signal. |
|
|
158
|
-
| `screenshot` | Multi-mode capture: `detail='text'` (UIA/OCR), `diffMode` (P-frame), `dotByDot` (1:1), and `background`. |
|
|
163
|
+
| `screenshot` | Multi-mode capture: `detail='text'` (UIA/OCR), `diffMode` (P-frame), `dotByDot` (1:1), and `background`. Returns a cheap `screenshot://by-ref/{id}` link to the saved image instead of inlining pixels every time. |
|
|
164
|
+
| `screenshot_query` / `screenshot_gc` | Inspect and prune the on-disk screenshot cache behind the by-ref links: `screenshot_query` lists saved captures without re-reading pixels; `screenshot_gc` reclaims space by retention policy (dry-run by default). |
|
|
159
165
|
| `workspace_snapshot` | Instant session orientation: all window thumbnails + UI summaries in one call. |
|
|
160
166
|
| `server_status` | Diagnostic check for native engine health and feature activation. |
|
|
161
167
|
|
|
@@ -184,6 +190,7 @@ For a local checkout, register the built server directly:
|
|
|
184
190
|
| `workspace_launch` | Launch apps and auto-detect new HWNDs (supports localized titles). |
|
|
185
191
|
| `run_macro` | Batch up to 50 operations into a single round-trip for maximum efficiency. |
|
|
186
192
|
| `clipboard` / `notification_show` | System-level text exchange and user alerts. |
|
|
193
|
+
| `key_locker` | Manage credentials the terminal autofills for you (SSH key passphrases, sudo / login passwords). Secrets are entered once into the locker's own secure dialog and stored encrypted on this machine (Windows DPAPI); they are never shown to the assistant. `action='launch_console'` opens an autofill-capable console (returns a `paneId` to drive `ssh`/`sudo` into via `terminal`); `save` / `list` / `forget` / `set_policy` / `status` manage bindings. Autofill only fires in a console opened by `launch_console`. Disable with `DESKTOP_TOUCH_DISABLE_KEY_LOCKER=1`. |
|
|
187
194
|
|
|
188
195
|
### 📊 Office (Excel)
|
|
189
196
|
| Tool | Description |
|
|
@@ -357,6 +364,19 @@ Keep Claude CLI visible while operating other apps full-screen. Set env vars in
|
|
|
357
364
|
|
|
358
365
|
> **Input routing gotcha:** when a pinned window is active (e.g. Claude CLI), `keyboard(action='type')` / `keyboard(action='press')` send keys to it, **not** the app you wanted to type into. Always call `focus_window(title=...)` before keyboard operations, then verify `isActive=true` via `screenshot(detail='meta')`.
|
|
359
366
|
|
|
367
|
+
### Screenshot cache (by-ref storage)
|
|
368
|
+
|
|
369
|
+
`screenshot` and the other visual results return a cheap `screenshot://by-ref/{id}` link to an image saved on disk instead of inlining the pixels every time, so routine look-act-confirm loops cost far fewer tokens. The cache bounds itself automatically and `screenshot_query` / `screenshot_gc` let you inspect and prune it. Tune the storage with:
|
|
370
|
+
|
|
371
|
+
| Env var | Default | Notes |
|
|
372
|
+
|---|---|---|
|
|
373
|
+
| `DESKTOP_TOUCH_SCREENSHOTS_DIR` | *(per-user cache dir)* | Pin the cache to a specific folder. If the default folder can't be created or written (e.g. corporate policy blocking new folders under your profile), the server auto-probes this → the runtime dir → an OS temp folder and uses the first writable one instead of giving up on the cache. |
|
|
374
|
+
| `DESKTOP_TOUCH_SCREENSHOT_MAX_COUNT` | `200` | Keep at most this many captures in the cache. |
|
|
375
|
+
| `DESKTOP_TOUCH_SCREENSHOT_MAX_BYTES` | `256 MiB` | Cap the total cache size on disk. |
|
|
376
|
+
| `DESKTOP_TOUCH_SCREENSHOT_MAX_AGE_MS` | *(off)* | Drop captures older than this many milliseconds (opt-in). |
|
|
377
|
+
| `DESKTOP_TOUCH_SCREENSHOT_AUTOPRUNE` | `on` | Auto-trim the cache as new captures are saved. Set `0` to disable. |
|
|
378
|
+
| `DESKTOP_TOUCH_SCREENSHOT_MIN_EVICT_AGE_MS` | `60000` | Never auto-evict a capture younger than this (ms), so a by-ref link you were just handed survives long enough to open even when another AI/process on the same PC is also capturing. `0` disables. |
|
|
379
|
+
|
|
360
380
|
### Auto Perception (always-on)
|
|
361
381
|
|
|
362
382
|
Phase 4 privatizes the explicit `perception_*` tool family — the v0.12 Auto
|
|
@@ -739,15 +759,14 @@ All V1 tools continue to work without interruption — no reinstall required. Re
|
|
|
739
759
|
|
|
740
760
|
Flag semantics (exact-match: only the literal string `"1"` counts):
|
|
741
761
|
|
|
742
|
-
| `DISABLE_FUKUWARAI_V2` |
|
|
743
|
-
|
|
744
|
-
| unset / not `"1"` |
|
|
745
|
-
|
|
|
746
|
-
| `"1"` | any | **OFF** — DISABLE wins |
|
|
762
|
+
| `DISABLE_FUKUWARAI_V2` | V2 state |
|
|
763
|
+
|---|---|
|
|
764
|
+
| unset / not `"1"` | **ON** (default) |
|
|
765
|
+
| `"1"` | **OFF** (kill switch) |
|
|
747
766
|
|
|
748
|
-
###
|
|
767
|
+
### Removed: `DESKTOP_TOUCH_ENABLE_FUKUWARAI_V2`
|
|
749
768
|
|
|
750
|
-
This was the opt-in switch in v0.16.x.
|
|
769
|
+
This was the opt-in switch in v0.16.x. V2 is on by default since v0.17, so the flag no longer has any effect and is safe to delete from your config. To turn V2 off, set `DESKTOP_TOUCH_DISABLE_FUKUWARAI_V2=1`.
|
|
751
770
|
|
|
752
771
|
### Recovery when V2 fails
|
|
753
772
|
|
|
@@ -790,9 +809,9 @@ For `desktop_discover` warnings (`visual_provider_unavailable`, `visual_provider
|
|
|
790
809
|
|
|
791
810
|
---
|
|
792
811
|
|
|
793
|
-
## 🚀
|
|
812
|
+
## 🚀 3,000+ Downloads!
|
|
794
813
|
|
|
795
|
-
This project just passed **
|
|
814
|
+
This project just passed **3,000+ downloads**. Huge thanks to everyone who
|
|
796
815
|
tried an experimental desktop-automation MCP server, filed issues, opened PRs,
|
|
797
816
|
and shared what broke. Every bug report made the next release better.
|
|
798
817
|
Thank you for building with me!
|
package/bin/launcher.js
CHANGED
|
@@ -18,15 +18,15 @@ import path from "node:path";
|
|
|
18
18
|
import { Readable } from "node:stream";
|
|
19
19
|
import { pipeline } from "node:stream/promises";
|
|
20
20
|
|
|
21
|
-
const PACKAGE_VERSION = "1.
|
|
21
|
+
const PACKAGE_VERSION = "1.12.0";
|
|
22
22
|
const RELEASE_TAG = `v${PACKAGE_VERSION}`;
|
|
23
23
|
const REPO_API_URL = `https://api.github.com/repos/Harusame64/desktop-touch-mcp/releases/tags/${RELEASE_TAG}`;
|
|
24
24
|
const ASSET_NAME = "desktop-touch-mcp-windows.zip";
|
|
25
25
|
const RELEASE_METADATA_FILE = ".desktop-touch-release.json";
|
|
26
26
|
const RELEASE_MANIFEST = {
|
|
27
|
-
tagName: "v1.
|
|
27
|
+
tagName: "v1.12.0",
|
|
28
28
|
assetName: ASSET_NAME,
|
|
29
|
-
sha256: "
|
|
29
|
+
sha256: "41751d3686d567f7e29638ccc1eca0af6ad744b2327c7d557f41f5e21da4abfc",
|
|
30
30
|
};
|
|
31
31
|
const CACHE_ROOT = process.env.DESKTOP_TOUCH_MCP_HOME
|
|
32
32
|
? path.resolve(process.env.DESKTOP_TOUCH_MCP_HOME)
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@harusame64/desktop-touch-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.0",
|
|
4
4
|
"mcpName": "io.github.Harusame64/desktop-touch-mcp",
|
|
5
|
-
"description": "Let Claude, Cursor, or any MCP client see and operate your Windows 10/11 desktop.
|
|
5
|
+
"description": "Let Claude, Cursor, or any MCP client see and operate your Windows 10/11 desktop. 31 tools for screenshots, UI Automation, Chrome CDP, keyboard/mouse, terminal, with semantic discover-then-act targeting and per-action perception guards that avoid wrong-window typing and stale-coordinate clicks.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mcp",
|
|
8
8
|
"mcp-server",
|
|
@@ -100,22 +100,23 @@
|
|
|
100
100
|
"build:rs": "node scripts/build-rs.mjs --release",
|
|
101
101
|
"build:rs:debug": "node scripts/build-rs.mjs --debug",
|
|
102
102
|
"artifacts:rs": "napi artifacts",
|
|
103
|
-
"bench:envelope-size": "node benches/l4_envelope_size.mjs"
|
|
103
|
+
"bench:envelope-size": "node benches/l4_envelope_size.mjs",
|
|
104
|
+
"bench:wgc-latency": "node benches/wgc_latency.mjs"
|
|
104
105
|
},
|
|
105
106
|
"devDependencies": {
|
|
106
107
|
"@eslint/js": "^10.0.1",
|
|
107
108
|
"@modelcontextprotocol/sdk": "^1.10.0",
|
|
108
109
|
"@napi-rs/cli": "^3.7.2",
|
|
109
110
|
"@nut-tree-fork/nut-js": "^4.2.6",
|
|
110
|
-
"@types/node": "^
|
|
111
|
+
"@types/node": "^26.1.0",
|
|
111
112
|
"@types/ws": "^8.18.1",
|
|
112
|
-
"eslint": "^10.
|
|
113
|
+
"eslint": "^10.6.0",
|
|
113
114
|
"fast-check": "^4.8.0",
|
|
114
|
-
"globals": "^17.
|
|
115
|
-
"sharp": "^0.35.
|
|
115
|
+
"globals": "^17.7.0",
|
|
116
|
+
"sharp": "^0.35.3",
|
|
116
117
|
"typescript": "^6.0.2",
|
|
117
|
-
"typescript-eslint": "^8.
|
|
118
|
-
"vitest": "^4.1.
|
|
118
|
+
"typescript-eslint": "^8.62.1",
|
|
119
|
+
"vitest": "^4.1.10",
|
|
119
120
|
"ws": "^8.21.0",
|
|
120
121
|
"zod": "^4.3.6"
|
|
121
122
|
}
|